}         // Run()

        #endregion

        #region SendWeatherPacket()
        public void SendWeatherPacket()
        {
            if (mOutQueue == null)
            {
                return;
            } // if mOutQueue == null
            WeatherPacket curRecord = (WeatherPacket)mRecords.Dequeue();

            mLog.Print(2, curRecord.mSerialString);
            IntPtr outData = Marshal.AllocHGlobal(
                Marshal.SizeOf(curRecord));

            Marshal.StructureToPtr(curRecord, outData, true);
            Marshal.Copy(outData, mQueueBuf, 0,
                         Marshal.SizeOf(curRecord));
            if (mOutQueue.WriteBuffer(mQueueBuf) == false)
            {
                throw new Exception("Could not write to the output " +
                                    "queue.");
            } // if WriteQueue() == false
        }     // SendWeatherPacket()
        }     // OldWeatherDeviceParser()

        #endregion

        #region WeatherReportLoggerParser()
        private void WeatherReportLoggerParser(WeatherPacket newRecord,
                                               string inputString)
        {
            string info = string.Empty;

            try {
                string[] recordParts =
                    inputString.Trim(" \n\r\t".ToCharArray()).Split(
                        " \n\r\t/:".ToCharArray(),
                        StringSplitOptions.RemoveEmptyEntries);
                info += "Parts: " + recordParts.Length;
                DateTime curTime = new DateTime(
                    Convert.ToUInt16(recordParts[0]) + 2000,
                    Convert.ToUInt16(recordParts[1]),
                    Convert.ToUInt16(recordParts[2]),
                    Convert.ToUInt16(recordParts[3]),
                    Convert.ToUInt16(recordParts[4]),
                    Convert.ToUInt16(recordParts[5]),
                    0);
                curTime = curTime.AddHours(mConfig.mWlConfig.TimeOffset);
                info   += ", Time: " + curTime.ToString();
                DateTime sysTime = DateTime.UtcNow;
                newRecord.mLocalHeader.mRecordTime.mYear =
                    (ushort)curTime.Year;
                newRecord.mGlobalHeader.mStartTime.mYear    =
                    newRecord.mGlobalHeader.mStopTime.mYear =
                        (ushort)sysTime.Year;
                newRecord.mLocalHeader.mRecordTime.mMonth =
                    (ushort)curTime.Month;
                newRecord.mGlobalHeader.mStartTime.mMonth    =
                    newRecord.mGlobalHeader.mStopTime.mMonth =
                        (ushort)sysTime.Month;
                newRecord.mLocalHeader.mRecordTime.mDayOfWeek =
                    (ushort)curTime.DayOfWeek;
                newRecord.mGlobalHeader.mStartTime.mDayOfWeek    =
                    newRecord.mGlobalHeader.mStopTime.mDayOfWeek =
                        (ushort)sysTime.DayOfWeek;
                newRecord.mLocalHeader.mRecordTime.mDay =
                    (ushort)curTime.Day;
                newRecord.mGlobalHeader.mStartTime.mDay    =
                    newRecord.mGlobalHeader.mStopTime.mDay =
                        (ushort)sysTime.Day;
                newRecord.mLocalHeader.mRecordTime.mHour =
                    (ushort)curTime.Hour;
                newRecord.mGlobalHeader.mStartTime.mHour    =
                    newRecord.mGlobalHeader.mStopTime.mHour =
                        (ushort)sysTime.Hour;
                newRecord.mLocalHeader.mRecordTime.mMinute =
                    (ushort)curTime.Minute;
                newRecord.mGlobalHeader.mStartTime.mMinute    =
                    newRecord.mGlobalHeader.mStopTime.mMinute =
                        (ushort)sysTime.Minute;
                newRecord.mLocalHeader.mRecordTime.mSecond =
                    (ushort)curTime.Second;
                newRecord.mGlobalHeader.mStartTime.mSecond    =
                    newRecord.mGlobalHeader.mStopTime.mSecond =
                        (ushort)sysTime.Second;
                newRecord.mLocalHeader.mRecordTime.mMilliseconds =
                    (ushort)curTime.Millisecond;
                newRecord.mGlobalHeader.mStartTime.mMilliseconds    =
                    newRecord.mGlobalHeader.mStopTime.mMilliseconds =
                        (ushort)sysTime.Millisecond;
                info += ", Wind Dir: " + recordParts[6];
                newRecord.mLocalHeader.mWindDirection =
                    (ushort)((ConvertCompassToDegrees)Enum.Parse(
                                 typeof(ConvertCompassToDegrees), recordParts[6], true));
                info += ", Wind Speed: " + recordParts[7];
                if (recordParts[6].Contains("MPH"))
                {
                    newRecord.mLocalHeader.mWindSpeed =
                        Convert.ToSingle(recordParts[7].Trim(
                                             "MPH".ToCharArray())) / 1.15F;
                } // if MPH
                else if (recordParts[7].Contains("KTS"))
                {
                    newRecord.mLocalHeader.mWindSpeed =
                        Convert.ToSingle(recordParts[7].Trim(
                                             "KTS".ToCharArray()));
                } // else if KTS
                newRecord.mLocalHeader.mSolar = 0;
                info += ", Inside Temp: " + recordParts[9];
                newRecord.mLocalHeader.mInsideTemp =
                    Convert.ToSingle(recordParts[9].Trim(
                                         "F".ToCharArray()));
                info += ", Outside Temp: " + recordParts[10];
                newRecord.mLocalHeader.mOutsideTemp =
                    Convert.ToSingle(recordParts[10].Trim(
                                         "F".ToCharArray()));
                info += ", Humidity: " + recordParts[11];
                newRecord.mLocalHeader.mHumidity =
                    Convert.ToUInt16(recordParts[11].Trim(
                                         "%".ToCharArray()));
                info += ", Pressure: " + recordParts[12];
                newRecord.mLocalHeader.mPressure =
                    Convert.ToSingle(recordParts[12].Remove(
                                         recordParts[11].Length - 1));
                info += ", Rain Fall: " + recordParts[13];
                newRecord.mLocalHeader.mRainFall =
                    Convert.ToSingle(recordParts[13].Trim(
                                         "\"DMT".ToCharArray()));
                info += ", Success";
            } // try
            catch (Exception exp) {
                info += exp.Message;
                throw new Exception(info);
            } // catch exp
            mLog.Print(2, info);
        }     // WeatherReportLoggerParser()
        }         // ReadThread()

        #endregion

        #region OldWeatherDeviceParser()
        private void OldWeatherDeviceParser(WeatherPacket newRecord,
                                            string inputString)
        {
            string info = string.Empty;

            try {
                string[] recordParts =
                    inputString.Trim(" \n\r\t".ToCharArray()).Split(
                        " \n\r\t/:".ToCharArray());
                info += "Parts: " + recordParts.Length;
                DateTime curTime = new DateTime(
                    Convert.ToUInt16(recordParts[0]) + 2000,
                    Convert.ToUInt16(recordParts[1]),
                    Convert.ToUInt16(recordParts[2]),
                    Convert.ToUInt16(recordParts[3]),
                    Convert.ToUInt16(recordParts[4]),
                    Convert.ToUInt16(recordParts[5]), 0);
                curTime = curTime.AddHours(mConfig.mWlConfig.TimeOffset);
                info   += ", Time: " + curTime.ToString();
                DateTime sysTime = DateTime.UtcNow;
                newRecord.mLocalHeader.mRecordTime.mYear =
                    (ushort)curTime.Year;
                newRecord.mGlobalHeader.mStartTime.mYear    =
                    newRecord.mGlobalHeader.mStopTime.mYear =
                        (ushort)sysTime.Year;
                newRecord.mLocalHeader.mRecordTime.mMonth =
                    (ushort)curTime.Month;
                newRecord.mGlobalHeader.mStartTime.mMonth    =
                    newRecord.mGlobalHeader.mStopTime.mMonth =
                        (ushort)sysTime.Month;
                newRecord.mLocalHeader.mRecordTime.mDayOfWeek =
                    (ushort)curTime.DayOfWeek;
                newRecord.mGlobalHeader.mStartTime.mDayOfWeek    =
                    newRecord.mGlobalHeader.mStopTime.mDayOfWeek =
                        (ushort)sysTime.DayOfWeek;
                newRecord.mLocalHeader.mRecordTime.mDay =
                    (ushort)curTime.Day;
                newRecord.mGlobalHeader.mStartTime.mDay    =
                    newRecord.mGlobalHeader.mStopTime.mDay =
                        (ushort)sysTime.Day;
                newRecord.mLocalHeader.mRecordTime.mHour =
                    (ushort)curTime.Hour;
                newRecord.mGlobalHeader.mStartTime.mHour    =
                    newRecord.mGlobalHeader.mStopTime.mHour =
                        (ushort)sysTime.Hour;
                newRecord.mLocalHeader.mRecordTime.mMinute =
                    (ushort)curTime.Minute;
                newRecord.mGlobalHeader.mStartTime.mMinute    =
                    newRecord.mGlobalHeader.mStopTime.mMinute =
                        (ushort)sysTime.Minute;
                newRecord.mLocalHeader.mRecordTime.mSecond =
                    (ushort)curTime.Second;
                newRecord.mGlobalHeader.mStartTime.mSecond    =
                    newRecord.mGlobalHeader.mStopTime.mSecond =
                        (ushort)sysTime.Second;
                newRecord.mLocalHeader.mRecordTime.mMilliseconds =
                    (ushort)curTime.Millisecond;
                newRecord.mGlobalHeader.mStartTime.mMilliseconds    =
                    newRecord.mGlobalHeader.mStopTime.mMilliseconds =
                        (ushort)sysTime.Millisecond;
                info += ", Wind Dir: " + recordParts[6];
                newRecord.mLocalHeader.mWindDirection =
                    Convert.ToUInt16(recordParts[6]);
                info += ", Wind Speed: " + recordParts[7];
                newRecord.mLocalHeader.mWindSpeed =
                    Convert.ToSingle(recordParts[7].Trim(
                                         "KTS".ToCharArray()));
                newRecord.mLocalHeader.mSolar =
                    Convert.ToUInt16(recordParts[9].Trim(
                                         "K".ToCharArray()));
                info += ", Inside Temp: " + recordParts[10];
                newRecord.mLocalHeader.mInsideTemp =
                    Convert.ToSingle(recordParts[10].Trim(
                                         "F".ToCharArray()));
                info += ", Outside Temp: " + recordParts[11];
                newRecord.mLocalHeader.mOutsideTemp =
                    Convert.ToSingle(recordParts[11].Trim(
                                         "F".ToCharArray()));
                info += ", Humidity: " + recordParts[12];
                newRecord.mLocalHeader.mHumidity =
                    Convert.ToUInt16(recordParts[12].Trim(
                                         "%".ToCharArray()));
                info += ", Pressure: " + recordParts[13];
                newRecord.mLocalHeader.mPressure =
                    Convert.ToSingle(recordParts[13].Trim(
                                         "\"".ToCharArray()));
                info += ", Rain Fall: " + recordParts[15];
                newRecord.mLocalHeader.mRainFall =
                    Convert.ToSingle(recordParts[15].Trim(
                                         "\"".ToCharArray()));
                info += ", Success";
            } // try
            catch (Exception exp) {
                info += exp.Message;
                throw new Exception(info);
            } // catch exp
            mLog.Print(2, info);
        }     // OldWeatherDeviceParser()
        }     // SendWeatherPacket()

        #endregion

        #region ReadThread()
        public void ReadThread()
        {
            bool startReading = false;

            while (startReading == false)
            {
                if (mReadEvent.WaitOne(1000, true) == true)
                {
                    startReading = true;
                } // if WaitOne() == true
                if (mReadTerminate.WaitOne(10, true) == true)
                {
                    return;
                } // if WaitOne() == true
            }     // while startReading == false
            mReadMutex.WaitOne();
            bool endReading = false;

            while (endReading == false)
            {
#if !DEBUG
                if (mSerialPort.IsOpen == false)
                {
                    endReading = true;
                    mLog.Print(0, "Serial Port is not open.");
                    continue;
                } // if IsOpen == false
#endif
                if (mReadTerminate.WaitOne(10, true) == true)
                {
                    endReading = true;
                    continue;
                } // if WaitOne() == true
#if DEBUG
                string inputStr = "15/04/23 18:48:51 162 001.9MPH 458.9F 063.8F 047.0F 096% 31.264\"  000.00\"";
                Thread.Sleep(1000);
#else
                string inputStr = mSerialPort.ReadLine();
#endif
                WeatherPacket newRecord = new WeatherPacket();
                newRecord.mGlobalHeader.mDataType  = "WEATHER";
                newRecord.mGlobalHeader.mChannelId =
                    mConfig.mWlConfig.OutputChannelId;
                mCurSeqNum++;
                newRecord.mGlobalHeader.mSequenceNumber  = mCurSeqNum;
                newRecord.mGlobalHeader.mTotalHeaderSize = 126;
                newRecord.mGlobalHeader.mDataSize        = 256;
                newRecord.mGlobalHeader.mFirstFlag       = (mCurSeqNum == 1);
                newRecord.mGlobalHeader.mLastFlag        = endReading;
                newRecord.mGlobalHeader.mAbortFlag       = false;
                newRecord.mGlobalHeader.mValidFlag       = true;
                try {
                    switch (mConfig.mWlConfig.DeviceStreamFormat)
                    {
                    case WeatherLoggerConfiguration.StreamFormat.OldWeatherDevice: {
                        OldWeatherDeviceParser(newRecord, inputStr);
                        break;
                    }         // case OldWeatherDevice

                    case WeatherLoggerConfiguration.StreamFormat.WeatherReportLogger: {
                        WeatherReportLoggerParser(newRecord, inputStr);
                        break;
                    }         // case WeatherReportLogger

                    case WeatherLoggerConfiguration.StreamFormat.UnknownDevice:
                    default: {
                        newRecord.mGlobalHeader.mValidFlag = false;
                        break;
                    }         // default
                    } // switch DeviceStreamFormat
                } // try
                catch (Exception exp) {
                    newRecord.mGlobalHeader.mValidFlag = false;
                    mLog.Print(2, exp.Message);
                } // catch
                if (inputStr.Length > 256)
                {
                    newRecord.mSerialString = inputStr.Substring(0, 256);
                } // if Length > 256
                else
                {
                    newRecord.mSerialString = inputStr;
                } // else
                mRecords.Enqueue(newRecord);
            }     // while endReading == false
            mReadMutex.ReleaseMutex();
        }         // ReadThread()