private void ReceiverBody()
        {
            try
            {
                try
                {
                    DateTime baseTime = DateTime.Now.ToUniversalTime();
                string[] rows;

                    // Check on each iteration if event was raised (signaled)
                    // that implicitly means if user requested to 'Stopreading'
                    while (false == _stopRequested.WaitOne(0, false))
                {
                    rows = ReceiveBatch(_maxCursorTimeout);
                    notifyBatchListeners(rows, baseTime);
                }
                SendQuery("SET AUTO=OFF", 0);
                int offTimeout;
                int zeroCount;
                int safetyCount;

                // 1 zeroCount response is for the AUTO=OFF response.
                // 1 zeroCount response is for the final tag bundle.
                    //   Sometimes there is no second response.  In this case, we should swallow
                    //   up the timeout exception to prevent it from causing trouble elsewhere.
                zeroCount = 2;
                offTimeout = _maxCursorTimeout;

                /* safetyCount keeps us from spinning indefinitely,but we don't want it to interfere with
                 normal termination, so put it safely out of the way */
                safetyCount = 10;
                while ((0 < zeroCount) && (0 < safetyCount))
                {
                    try
                    {
                        rows = ReceiveBatch(offTimeout, false);
                        notifyBatchListeners(rows, baseTime);

                        if (0 == rows.Length)
                        {
                            --zeroCount;
                        }
                        }
                        catch (ReaderCommException)
                        {
                            /* Assume timeout -- we don't have a good way
                             * to distinguish other comm exceptions */
                            // Clear socket timeout flag
                            _socket.Blocking = true;
                            // Treat as if it were the second empty response
                            --zeroCount;
                        }

                        --safetyCount;
                        offTimeout = 0;
                    }
                }
                finally
                    {
                    ResetRql();
                }
            }
            catch (ReaderException re)
                        {
                if ((re is ReaderCommException) &&
                    (-1 != re.Message.IndexOf("did not properly respond after a period of time")))
                {
                            // Timeout: RQL didn't send as many responses as we expected

                            // Clear socket timeout error condition (as suggested in
                            // http://www.codeguru.com/forum/showthread.php?threadid=469679)
                            // Otherwise, subsequent receives all fail with the same error
                            _socket.Blocking = true;
                }

                ReadExceptionPublisher expub = new ReadExceptionPublisher(this, re);
                Thread trd = new Thread(expub.OnReadException);
                trd.Start();
            }
            }
 private  void OnTimedEvent(object source, ElapsedEventArgs e)
 {            
     TimeSpan diff = (DateTime.Now - keepAliveTime); // time difference in seconds
     if (diff.TotalMilliseconds > (keepAliveTrigger * 4))  // 4 keep alives lost
     {
         //Release the TagQueueEmptyEvent when connection lost
         TagQueueEmptyEvent.Set();
         ReadExceptionPublisher expub = new ReadExceptionPublisher(this, new ReaderException("Connection Lost"));
         Thread trd = new Thread(expub.OnReadException);
         trd.Name = "OnReadException";
         trd.Start();
     }
 }
        private void ParseNotifyTag(MSG_RO_ACCESS_REPORT msg)
        {
            if (null == tagReads)
            {
                tagReads = new List<TagReadData>();
            }
            TagReadData tag = null;
            if (null != msg)
            {
                for (int i = 0; i < msg.TagReportData.Length; i++)
                {
                    try
                    {
                        tag = new TagReadData();
                        if (msg.TagReportData[i].EPCParameter.Count > 0)
                        {
                            string epc;
                            // reports come in two flavors.  Get the right flavor
                            if (msg.TagReportData[i].EPCParameter[0].GetType() == typeof(PARAM_EPC_96))
                            {
                                epc = ((PARAM_EPC_96)(msg.TagReportData[i].EPCParameter[0])).EPC.ToHexString();
                            }
                            else
                            {
                                epc = ((PARAM_EPCData)(msg.TagReportData[i].EPCParameter[0])).EPC.ToHexString();
                            }
                            TagData td = new TagData(ByteFormat.FromHex(epc));
                            TagProtocol tagProtocol = 0;
                            //Match the recieved rospec id with the rospec id stored in the hashtable at the time of setting readplan
                            if (roSpecProtcolTable.ContainsKey(msg.TagReportData[i].ROSpecID.ROSpecID))
                            {
                                tagProtocol = (TagProtocol)roSpecProtcolTable[msg.TagReportData[i].ROSpecID.ROSpecID];
                            }
                            if (TagProtocol.GEN2.Equals(tagProtocol))
                            {
                                //Get crc and pc bits
                                UNION_AirProtocolTagData tagdata = msg.TagReportData[i].AirProtocolTagData;
                                td = new Gen2.TagData(ByteFormat.FromHex(epc), ByteConv.EncodeU16(((PARAM_C1G2_CRC)tagdata[1]).CRC), ByteConv.EncodeU16(((PARAM_C1G2_PC)tagdata[0]).PC_Bits));
                            }
                            else if (TagProtocol.ISO180006B.Equals(tagProtocol))
                            {
                                td = new Iso180006b.TagData(ByteFormat.FromHex(epc));
                            }
                            else
                            {
                                td = new TagData(ByteFormat.FromHex(epc));
                            }
                            tag.Reader = this;
                            tag._tagData = td;
                            tag._antenna = (int)msg.TagReportData[i].AntennaID.AntennaID;
                            UInt64 usSinceEpoch = msg.TagReportData[i].LastSeenTimestampUTC.Microseconds;
                            tag._baseTime = epochTime.AddMilliseconds(usSinceEpoch / 1000);
                            tag._readOffset = 0;
                            // Since Spruce release firmware doesn't support phase, there won't be PARAM_ThingMagicTagReportContentSelector 
                            // custom paramter in ROReportSpec
                            string[] ver = softwareVersion.Split('.');
                            if (((Convert.ToInt32(ver[0]) == 4) && (Convert.ToInt32(ver[1]) >= 17)) ||
                                (Convert.ToInt32(ver[0]) > 4))
                            {
                                tag._phase = Convert.ToInt32(((PARAM_ThingMagicRFPhase)msg.TagReportData[i].Custom[0]).Phase);
                            }
                            tag.Rssi = Convert.ToInt32(msg.TagReportData[i].PeakRSSI.PeakRSSI.ToString());
                            tag.ReadCount = msg.TagReportData[i].TagSeenCount.TagCount;

                            int chIndex = Convert.ToInt32(msg.TagReportData[i].ChannelIndex.ChannelIndex);
                            List<uint> freq = frequencyHopTable[0].Frequency.data;
                            tag._frequency = Convert.ToInt32(freq[chIndex - 1]);
                            UNION_AccessCommandOpSpecResult opSpecResult = msg.TagReportData[i].AccessCommandOpSpecResult;

                            tag._data = EMPTY_DATA;
                            // Use try-finally to to keep failed tagops from preventing report of TagReadData
                            try
                            {
                                if (null != opSpecResult)
                                {
                                    if (opSpecResult.Count > 0)
                                    {
                                        ParseTagOpSpecResultType(opSpecResult, ref tag);
                                    }
                                }
                            }
                            finally
                            {
                                if (continuousReading)
                                {
                                    OnTagRead(tag);
                                }
                                else
                                {
                                    tagReads.Add(tag);
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        ReaderException rx;
                        if (ex is ReaderException)
                        {
                            rx = (ReaderException)ex;
                        }
                        else
                        {
                            rx = new ReaderException(ex.ToString());
                        }
                        //Release the TagQueueEmptyEvent when parsing exception raised
                        TagQueueEmptyEvent.Set();
                        ReadExceptionPublisher expub = new ReadExceptionPublisher(this, rx);

                        Thread trd = new Thread(expub.OnReadException);
                        trd.Name = "OnReadException";
                        trd.Start();
                    }
                    finally
                    {
                        tag = null;
                    }
                }
                TagQueueEmptyEvent.Set();
            }
        }
        private LTKD.Message SendLlrpMessage(LTKD.Message message)
        {
            LTKD.Message response = null;
            PARAM_LLRPStatus llrpStatus = null;
            object msgType = Enum.Parse(typeof(ENUM_LLRP_MSG_TYPE), message.MSG_TYPE.ToString(), true);
            int timeout = (int)ParamGet("/reader/commandTimeout") + (int)ParamGet("/reader/transportTimeout");

            BuildTransport(true, message);
            try
            {
                switch ((ENUM_LLRP_MSG_TYPE)msgType)
                {
                    case ENUM_LLRP_MSG_TYPE.DELETE_ROSPEC:
                        timeout += STOP_TIMEOUT;
                        response = (MSG_DELETE_ROSPEC_RESPONSE)llrp.DELETE_ROSPEC((MSG_DELETE_ROSPEC)message, out errorMessage, timeout);
                        llrpStatus = ((MSG_DELETE_ROSPEC_RESPONSE)response).LLRPStatus;
                        break;
                    case ENUM_LLRP_MSG_TYPE.ADD_ROSPEC:
                        response = (MSG_ADD_ROSPEC_RESPONSE)llrp.ADD_ROSPEC((MSG_ADD_ROSPEC)message, out errorMessage, timeout);
                        llrpStatus = ((MSG_ADD_ROSPEC_RESPONSE)response).LLRPStatus;
                        break;
                    case ENUM_LLRP_MSG_TYPE.ENABLE_ROSPEC:
                        response = (MSG_ENABLE_ROSPEC_RESPONSE)llrp.ENABLE_ROSPEC((MSG_ENABLE_ROSPEC)message, out errorMessage, timeout);
                        llrpStatus = ((MSG_ENABLE_ROSPEC_RESPONSE)response).LLRPStatus;
                        break;
                    case ENUM_LLRP_MSG_TYPE.START_ROSPEC:
                        response = (MSG_START_ROSPEC_RESPONSE)llrp.START_ROSPEC((MSG_START_ROSPEC)message, out errorMessage, timeout);
                        llrpStatus = ((MSG_START_ROSPEC_RESPONSE)response).LLRPStatus;
                        break;
                    case ENUM_LLRP_MSG_TYPE.STOP_ROSPEC:
                        timeout += STOP_TIMEOUT;
                        response = (MSG_STOP_ROSPEC_RESPONSE)llrp.STOP_ROSPEC((MSG_STOP_ROSPEC)message, out errorMessage, timeout);
                        llrpStatus = ((MSG_STOP_ROSPEC_RESPONSE)response).LLRPStatus;
                        break;
                    case ENUM_LLRP_MSG_TYPE.DISABLE_ROSPEC:
                        timeout += STOP_TIMEOUT;
                        response = (MSG_DISABLE_ROSPEC_RESPONSE)llrp.DISABLE_ROSPEC((MSG_DISABLE_ROSPEC)message, out errorMessage, timeout);
                        llrpStatus = ((MSG_DISABLE_ROSPEC_RESPONSE)response).LLRPStatus;
                        break;
                    case ENUM_LLRP_MSG_TYPE.SET_READER_CONFIG:
                        response = (MSG_SET_READER_CONFIG_RESPONSE)llrp.SET_READER_CONFIG((MSG_SET_READER_CONFIG)message, out errorMessage, timeout);
                        llrpStatus = ((MSG_SET_READER_CONFIG_RESPONSE)response).LLRPStatus;
                        break;
                    case ENUM_LLRP_MSG_TYPE.GET_READER_CONFIG:
                        response = (MSG_GET_READER_CONFIG_RESPONSE)llrp.GET_READER_CONFIG((MSG_GET_READER_CONFIG)message, out errorMessage, timeout);
                        llrpStatus = ((MSG_GET_READER_CONFIG_RESPONSE)response).LLRPStatus;
                        break;
                    case ENUM_LLRP_MSG_TYPE.GET_READER_CAPABILITIES:
                        response = (MSG_GET_READER_CAPABILITIES_RESPONSE)llrp.GET_READER_CAPABILITIES((MSG_GET_READER_CAPABILITIES)message, out errorMessage, timeout);
                        llrpStatus = ((MSG_GET_READER_CAPABILITIES_RESPONSE)response).LLRPStatus;
                        break;
                    case ENUM_LLRP_MSG_TYPE.GET_ACCESSSPECS:
                        response = (MSG_GET_ACCESSSPECS_RESPONSE)llrp.GET_ACCESSSPECS((MSG_GET_ACCESSSPECS)message, out errorMessage, timeout);
                        llrpStatus = ((MSG_GET_ACCESSSPECS_RESPONSE)response).LLRPStatus;
                        break;
                    case ENUM_LLRP_MSG_TYPE.GET_ROSPECS:
                        response = (MSG_GET_ROSPECS_RESPONSE)llrp.GET_ROSPECS((MSG_GET_ROSPECS)message, out errorMessage, timeout);
                        llrpStatus = ((MSG_GET_ROSPECS_RESPONSE)response).LLRPStatus;
                        break;
                    case ENUM_LLRP_MSG_TYPE.KEEPALIVE_ACK:
                        llrp.KEEPALIVE_ACK((MSG_KEEPALIVE_ACK)message, out errorMessage, timeout);
                        break;
                    case ENUM_LLRP_MSG_TYPE.ADD_ACCESSSPEC:
                        response = (MSG_ADD_ACCESSSPEC_RESPONSE)llrp.ADD_ACCESSSPEC((MSG_ADD_ACCESSSPEC)message, out errorMessage, timeout);
                        llrpStatus = ((MSG_ADD_ACCESSSPEC_RESPONSE)response).LLRPStatus;
                        break;
                    case ENUM_LLRP_MSG_TYPE.ENABLE_ACCESSSPEC:
                        response = (MSG_ENABLE_ACCESSSPEC_RESPONSE)llrp.ENABLE_ACCESSSPEC((MSG_ENABLE_ACCESSSPEC)message, out errorMessage, timeout);
                        llrpStatus = ((MSG_ENABLE_ACCESSSPEC_RESPONSE)response).LLRPStatus;
                        break;
                    case ENUM_LLRP_MSG_TYPE.DELETE_ACCESSSPEC:
                        response = (MSG_DELETE_ACCESSSPEC_RESPONSE)llrp.DELETE_ACCESSSPEC((MSG_DELETE_ACCESSSPEC)message, out errorMessage, timeout);
                        llrpStatus = ((MSG_DELETE_ACCESSSPEC_RESPONSE)response).LLRPStatus;
                        break;
                    case ENUM_LLRP_MSG_TYPE.ENABLE_EVENTS_AND_REPORTS:
                        llrp.ENABLE_EVENTS_AND_REPORTS((MSG_ENABLE_EVENTS_AND_REPORTS)message, out errorMessage, timeout);
                        break;
                    case ENUM_LLRP_MSG_TYPE.GET_REPORT:
                        llrp.GET_REPORT((MSG_GET_REPORT)message, out errorMessage, timeout);
                        break;
                    case ENUM_LLRP_MSG_TYPE.CUSTOM_MESSAGE:
                        response = (MSG_THINGMAGIC_CONTROL_RESPONSE_POWER_CYCLE_READER)llrp.CUSTOM_MESSAGE((MSG_CUSTOM_MESSAGE)message, out errorMessage, timeout);
                        break; 
                    default: throw new ReaderException("Not a valid llrp message");
                }
            }
            catch (Exception ex)
            {
                if(ErrCodeNullObjectReference == (uint)System.Runtime.InteropServices.Marshal.GetHRForException(ex))
                {
                    if (continuousReading)
                    {
                        ReadExceptionPublisher expub = new ReadExceptionPublisher(this, new ReaderException((((ENUM_LLRP_MSG_TYPE)msgType).ToString() + " failed. Request timed out")));
                        Thread trd = new Thread(expub.OnReadException);
                        trd.Name = "OnReadException";
                        trd.Start();
                    }
                    else
                    {
                        throw new ReaderException(((ENUM_LLRP_MSG_TYPE)msgType).ToString() + " failed. Request timed out");
                    }
                }
                else
                {
                    throw new Exception(ex.Message);
                }
            }
            BuildTransport(false, response);
            if (llrpStatus != null)
            {
                if (llrpStatus.StatusCode != ENUM_StatusCode.M_Success)
                {
                    throw new Exception(llrpStatus.ErrorDescription == "" ? (llrpStatus.StatusCode.ToString()) : llrpStatus.ErrorDescription);
                }
            }
            return response;
        }