Example #1
0
        String decodeChannelFeedback(ANT_Response response)
        {
            StringBuilder stringToPrint;                         //We use a stringbuilder for speed and better memory usage, but, it doesn't really matter for the demo.

            stringToPrint = new StringBuilder("Channel: ", 100); //Begin the string and allocate some more space

            //In the channel feedback we will get either RESPONSE_EVENTs or receive events,
            //If it is a response event we display what the event was and the error code if it failed.
            //Mostly, these response_events will all be broadcast events from a Master channel.
            if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40)
            {
                stringToPrint.AppendLine(((ANT_ReferenceLibrary.ANTEventID)response.messageContents[2]).ToString());
            }
            else   //This is a receive event, so display the ID
            {
                stringToPrint.AppendLine("Received " + ((ANT_ReferenceLibrary.ANTMessageID)response.responseID).ToString());
            }

            //Always print the raw contents in hex, with leading '::' for easy visibility/parsing
            //If this is a receive event it will contain the payload of the message
            stringToPrint.Append("  :: ");
            stringToPrint.Append(Convert.ToString(response.responseID, 16));
            stringToPrint.Append(", ");
            stringToPrint.Append(BitConverter.ToString(response.messageContents) + Environment.NewLine);

            if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E)
            {
//                if (log != null)
//                    log.WriteLine(BitConverter.ToString(response.messageContents));
            }

/*
 */
            return(stringToPrint.ToString());
        }
Example #2
0
            public void antChannel_channelResponse_DataFetch(ANT_Response response)
            {
                if (curStatus == ConnState.Connected)
                {
                    //If the channel closes we need to know
                    if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40 &&
                        response.messageContents[1] == (byte)ANT_ReferenceLibrary.ANTMessageID.EVENT_0x01)
                    {
                        if (response.messageContents[2] == (byte)ANT_ReferenceLibrary.ANTEventID.EVENT_RX_FAIL_GO_TO_SEARCH_0x08)
                        {
                            dataSource.isInitialized = false;
                            curStatus = ConnState.DrpdToSrch;
                        }
                        else if (response.messageContents[2] == (byte)ANT_ReferenceLibrary.ANTEventID.EVENT_CHANNEL_CLOSED_0x07)
                        {
                            curStatus = ConnState.Closed;   //TODO: qc Ensure search channel is cycling, or we will never get this back
                        }
                    }
                }
                else if (curStatus == ConnState.DrpdToSrch)  //If we are in search and see a new broadcast
                {
                    if (response.responseID == (byte)ANT_Managed_Library.ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E)
                    {
                        curStatus = ConnState.Connected;
                    }
                }

                dataSource.handleChannelResponse(response);
            }
Example #3
0
        void ChannelResponse(ANT_Response response)
        {
            try
            {
                switch ((ANTMessageID)response.responseID)
                {
                case ANTMessageID.RESPONSE_EVENT_0x40:
                    ChannelEventResponse(response);
                    break;

                case ANTMessageID.BROADCAST_DATA_0x4E:
                case ANTMessageID.ACKNOWLEDGED_DATA_0x4F:
                case ANTMessageID.BURST_DATA_0x50:
                case ANTMessageID.EXT_BROADCAST_DATA_0x5D:
                case ANTMessageID.EXT_ACKNOWLEDGED_DATA_0x5E:
                case ANTMessageID.EXT_BURST_DATA_0x5F:
                    ChannelDataResponse(response);
                    break;

                default:
                    Debug.WriteLine("Unknown Message " + response.responseID);
                    break;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Channel response processing failed with exception: " + ex.Message);
            }
        }
        private void action_ReqVersion()
        {
            //To request the version we use the requestMessageAndResponse function. To request messages you could
            //also use the requestMessage function, but then you need to monitor the device feedback for the response.
            //The version string is a null terminated ascii string, so we decode it and display it
            threadSafePrintLine("Requesting Device 0 Version", textBox_Display);
            //On failure an exception is thrown so we watch for it
            try
            {
                ANT_Response version = device0.requestMessageAndResponse(ANT_ReferenceLibrary.RequestMessageID.VERSION_0x3E, 500);
                threadSafePrintLine("Device 0 ANT Version: " + new ASCIIEncoding().GetString(version.messageContents, 0, version.messageContents.Length - 1), textBox_Display);
            }
            catch (Exception)
            {
                threadSafePrintLine("Requesting Device 0 Version Timed Out", textBox_Display);
            }

            //if device 1 is open, request its version too
            if (device1 != null)
            {
                threadSafePrintLine("Requesting Device 1 Version", textBox_Display);
                try
                {
                    ANT_Response version = device1.requestMessageAndResponse(ANT_ReferenceLibrary.RequestMessageID.VERSION_0x3E, 500);
                    threadSafePrintLine("Device 1 ANT Version: " + new ASCIIEncoding().GetString(version.messageContents, 0, version.messageContents.Length - 1), textBox_Display);
                }
                catch (Exception)
                {
                    threadSafePrintLine("Requesting Device 1 Version Timed Out", textBox_Display);
                }
            }
        }
Example #5
0
    /*
     * DeviceResponse
     * Called whenever a message is received from ANT unless that message is a
     * channel event message.
     * response: ANT message
     */

    void DeviceResponse(ANT_Response response)
    {
        if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40)
        {
            messageQueue.Enqueue(response);
        }
    }
Example #6
0
    private void PublishReading(ANT_Response response)
    {
        Debug.Log("Publishing BROADCAST_DATA_0x4E !!!");
        byte[] payload = response.getDataPayload();

        // What the heck is going on here?!
        ushort[] dataArray1 = new ushort[4]
        {
            (ushort)(((int)payload [3] & (int)byte.MaxValue) << 2 | (int)payload [4] >> 6),
            (ushort)(((int)payload [4] & 63) << 4 | (int)payload [5] >> 4),
            (ushort)(((int)payload [5] & 15) << 6 | (int)payload [6] >> 2),
            (ushort)((uint)(((int)payload [6] & 3) << 8) | (uint)payload [7])
        };

        // Why are there 4 readings per sample?
        for (int index = 0; index < 4; index++)
        {
            /* logic to hanle sample history
             * this._gSampleHistorySum -= (uint)this._gSampleHistory [this._gBufferIndex];
             * this._gSampleHistory [this._gBufferIndex] = dataArray1 [index];
             * this._gSampleHistorySum += (uint)this._gSampleHistory [this._gBufferIndex];
             * this._gSampleAverageHistory [this._gBufferIndex] = (ushort)(this._gSampleHistorySum / this._gNumTaps);
             * this._gSampleAverageDifferenceSquaredHistory [this._gBufferIndex] =
             *      (uint)Math.Pow ((double)((int)this._gSampleHistory [this._gBufferIndex]
             *              - (int)this._gSampleAverageHistory [this._gBufferIndex]), 2.0);
             * uint num1 = 0U;
             * foreach (uint num2 in this._gSampleAverageDifferenceSquaredHistory)
             *      num1 += num2;
             * this._gPseudoStandardDeviationHistory [index] = (ushort)Math.Sqrt ((double)num1 / (double)(this._gNumTaps - 1U));
             * this._gBufferIndex = ++this._gBufferIndex % this._gNumTaps;
             */
            SomaxisReading reading = new SomaxisReading(payload [0], dataArray1 [index]);
            owner.PublishReading(reading, this);
        }
    }
Example #7
0
 void ChannelResponse(ANT_Response response)
 {
     if (response.getChannelEventCode() == ANT_ReferenceLibrary.ANTEventID.EVENT_TRANSFER_TX_FAILED_0x06)
     {
         deviceChannel.sendAcknowledgedData(pageToSend); //send the page again if the transfer failed
     }
 }
Example #8
0
    void ChannelResponse(ANT_Response response)
    {
        switch ((ANT_ReferenceLibrary.ANTMessageID)response.responseID)
        {
        case ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40:
        {
            //TODO: Handle many EVENT_RX_FAIL (close channel, throw exception?)
//                Debug.Log(response.getChannelEventCode());
            break;
        }

        case ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E:
        case ANT_ReferenceLibrary.ANTMessageID.ACKNOWLEDGED_DATA_0x4F:
        case ANT_ReferenceLibrary.ANTMessageID.BURST_DATA_0x50:
        case ANT_ReferenceLibrary.ANTMessageID.EXT_BROADCAST_DATA_0x5D:
        case ANT_ReferenceLibrary.ANTMessageID.EXT_ACKNOWLEDGED_DATA_0x5E:
        case ANT_ReferenceLibrary.ANTMessageID.EXT_BURST_DATA_0x5F:
        {
            var dataPayload = response.getDataPayload();
            ExtractHeartRateInfo(dataPayload);
            break;
        }

        default:
        {
            Debug.Log("Unknown Message " + response.responseID);
            break;
        }
        }
    }
        //This function decodes the message code into human readable form, shows the error value on failures, and also shows the raw message contents
        String decodeDeviceFeedback(ANT_Response response)
        {
            string toDisplay = "Device: ";

            //The ANTReferenceLibrary contains all the message and event codes in user-friendly enums
            //This allows for more readable code and easy conversion to human readable strings for displays

            // So, for the device response we first check if it is an event, then we check if it failed,
            // and display the failure if that is the case. "Events" use message code 0x40.
            if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40)
            {
                //We cast the byte to its messageID string and add the channel number byte associated with the message
                toDisplay += (ANT_ReferenceLibrary.ANTMessageID)response.messageContents[1] + ", Ch:" + response.messageContents[0];
                //Check if the eventID shows an error, if it does, show the error message
                if ((ANT_ReferenceLibrary.ANTEventID)response.messageContents[2] != ANT_ReferenceLibrary.ANTEventID.RESPONSE_NO_ERROR_0x00)
                {
                    toDisplay += Environment.NewLine + ((ANT_ReferenceLibrary.ANTEventID)response.messageContents[2]).ToString();
                }
            }
            else   //If the message is not an event, we just show the messageID
            {
                toDisplay += ((ANT_ReferenceLibrary.ANTMessageID)response.responseID).ToString();
            }

            //Finally we display the raw byte contents of the response, converting it to hex
            toDisplay += Environment.NewLine + "::" + Convert.ToString(response.responseID, 16) + ", " + BitConverter.ToString(response.messageContents) + Environment.NewLine;
            return(toDisplay);
        }
Example #10
0
    void cadenceSensorResponse(ANT_Response response)
    {
        if (response.responseID == 0x4E && response.messageContents[1] == 0x00)
        {
            ushort bs = BitConverter.ToUInt16(new byte[2] {
                response.messageContents[5], response.messageContents[6]
            }, 0);
            ushort crc = BitConverter.ToUInt16(new byte[2] {
                response.messageContents[7], response.messageContents[8]
            }, 0);

            rpmData[0].eventTime = (ushort)(bs);
            rpmData[0].revCount  = crc;

            rpmData[0] = rpmData[1];

            rpmData[1].eventTime = (ushort)(bs);
            rpmData[1].revCount  = crc;

            if (rpmData[0].Equals(rpmData[1]) == false)
            {
                current_rpm = (60 * ((rpmData[1].revCount - rpmData[0].revCount)) * 1024) / (rpmData[1].eventTime - rpmData[0].eventTime);

                Debug.Log("RPM : " + current_rpm.ToString() + " rpm");
            }
        }
    }
Example #11
0
    //Print the channel response to the textbox
    void speedSensorResponse(ANT_Response response)
    {
        //if (response.responseID == 0x4E && response.messageContents[1] == 0x05)
        if (response.responseID == 0x4E)
        {
            stop = false;

            ushort bs = BitConverter.ToUInt16(new byte[2] {
                response.messageContents[5], response.messageContents[6]
            }, 0);
            ushort crc = BitConverter.ToUInt16(new byte[2] {
                response.messageContents[7], response.messageContents[8]
            }, 0);

            speedData[0].eventTime = (ushort)(bs);
            speedData[0].revCount  = crc;

            speedData[0] = speedData[1];

            speedData[1].eventTime = (ushort)(bs);
            speedData[1].revCount  = crc;

            if (speedData[0].Equals(speedData[1]) == false)
            {
                current_speed = (1.8 * ((speedData[1].revCount - speedData[0].revCount))) / (speedData[1].eventTime - speedData[0].eventTime) * 3600;

                if (current_speed > 100.0 || current_speed < 0)
                {
                    current_speed = 0;
                }

                Debug.Log("Speed : " + current_speed.ToString() + " km/h");
            }
        }
    }
        private void action_ReqChannelID()
        {
            //To request the ID we also use the requestMessageAndResponse function
            threadSafePrintLine("Requesting Device 0 Channel ID", textBox_Display);

            //On failure an exception is thrown so we watch for it
            try
            {
                ANT_Response IDresp = device0.requestMessageAndResponse(ANT_ReferenceLibrary.RequestMessageID.CHANNEL_ID_0x51, 500);
                threadSafePrintLine("Device 0 Channel ID: " + "Dev#: " + ((IDresp.messageContents[2] << 8) + IDresp.messageContents[1]) + ", DevType: " + IDresp.messageContents[3] + ", TransType: " + IDresp.messageContents[4], textBox_Display);
            }
            catch (Exception)
            {
                threadSafePrintLine("Requesting Device 0 Channel ID Timed Out", textBox_Display);
            }

            //if device 1 is open, request its version too
            if (device1 != null)
            {
                threadSafePrintLine("Requesting Device 1 Channel ID", textBox_Display);
                try
                {
                    ANT_Response IDresp = device1.requestMessageAndResponse(ANT_ReferenceLibrary.RequestMessageID.CHANNEL_ID_0x51, 500);
                    threadSafePrintLine("Device 1 Channel ID: " + "Dev#: " + ((IDresp.messageContents[2] << 8) + IDresp.messageContents[1]) + ", DevType: " + IDresp.messageContents[3] + ", TransType: " + IDresp.messageContents[4], textBox_Display);
                }
                catch (Exception)
                {
                    threadSafePrintLine("Requesting Device 1 Channel ID Timed Out", textBox_Display);
                }
            }
        }
Example #13
0
        void DeviceEventResponse(ANT_Response response)
        {
            var ec = response.getChannelEventCode();

            switch (response.getMessageID())
            {
            case ANTMessageID.CHANNEL_SEARCH_TIMEOUT_0x44:
                Debug.WriteLine("DeviceEventResponse CHANNEL_SEARCH_TIMEOUT_0x44");
                break;

            case ANTMessageID.CLOSE_CHANNEL_0x4C:
                if (ec == ANTEventID.CHANNEL_IN_WRONG_STATE_0x15)
                {
                    Debug.WriteLine("CHANNEL_IN_WRONG_STATE_0x15: Channel is already closed");
                }
                break;

            case ANTMessageID.NETWORK_KEY_0x46:
            case ANTMessageID.ASSIGN_CHANNEL_0x42:
            case ANTMessageID.CHANNEL_ID_0x51:
            case ANTMessageID.CHANNEL_RADIO_FREQ_0x45:
            case ANTMessageID.CHANNEL_MESG_PERIOD_0x43:
            case ANTMessageID.OPEN_CHANNEL_0x4B:
            case ANTMessageID.UNASSIGN_CHANNEL_0x41:
                if (ec != ANTEventID.RESPONSE_NO_ERROR_0x00)
                {
                    PrintErrorMessage(response, "UNASSIGN_CHANNEL_0x41 RESPONSE_NO_ERROR_0x00");
                }
                break;

            case ANTMessageID.RX_EXT_MESGS_ENABLE_0x66:
                if (ec == ANTEventID.INVALID_MESSAGE_0x28)
                {
                    Debug.WriteLine("Extended messages not supported in this ANT product");
                    break;
                }
                else if (ec != ANTEventID.RESPONSE_NO_ERROR_0x00)
                {
                    PrintErrorMessage(response, "RX_EXT_MESGS_ENABLE_0x66 RESPONSE_NO_ERROR_0x00");
                    break;
                }
                // Extended messages enabled
                break;

            case ANTMessageID.REQUEST_0x4D:
                if (ec == ANTEventID.INVALID_MESSAGE_0x28)
                {
                    Debug.WriteLine("Requested message not supported in this ANT product");
                    break;
                }
                break;

            default:
                PrintErrorMessage(response, "Unhandled response");
                break;
            }
        }
Example #14
0
        //Print the channel response to the textbox
        void d0channel0_channelResponse(ANT_Response response)
        {
            //threadSafePrintLine(decodeChannelFeedback(response), textBox_device0);
            antEventArgs aEA = new antEventArgs();

            aEA.data = response.messageContents;

            if (null != channelMessageHandler)
            {
                channelMessageHandler(this, aEA);
            }
        }
Example #15
0
        void antChannel_channelResponse_FeSearch(ANT_Response response)
        {
            switch ((ANT_ReferenceLibrary.ANTMessageID)response.responseID)
            {
            case ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E:
                AntPlus_Connection newConn = deviceList[searchingDeviceIndex];
                ANT_Response       idResp  = null;
                try
                {
                    idResp = antStick.requestMessageAndResponse(searchChannel.getChannelNum(), ANT_ReferenceLibrary.RequestMessageID.CHANNEL_ID_0x51, 1000);
                }
                catch (Exception)
                {
                    //Don't know what to do if we can't get id...could retry somewhere...
                    break;
                }


                lock (newConn)
                {
                    searchChannel.channelResponse -= antChannel_channelResponse_FeSearch;
                    newConn.dataSource.searchProfile.deviceNumber = (ushort)(idResp.messageContents[1] + ((ushort)idResp.messageContents[2] << 8));     //Save to the search profile so we keep this id after dropouts
                    newConn.connectedChannel = searchChannel;
                    //Note: the low pri search happens before the high pri, so this isn't even doing anything.
                    //newConn.connectedChannel.setChannelSearchTimeout(2, 500); //If we drop, we really want it back soon because it may be in use in a race, but we can't afford to ruin other channels staying in high priority. With the default search waveform, 5s is supposed to give us a really good rate of acquisition
                    newConn.connectedChannel.setLowPrioritySearchTimeout(255, 500);     //Search indefinitely
                    newConn.antChannel_channelResponse_DataFetch(response);
                    newConn.connectedChannel.channelResponse += newConn.antChannel_channelResponse_DataFetch;
                    newConn.setConnStatus(AntPlus_Connection.ConnState.Connected);
                }

                searchChannel = null;       //invalidate this channel as a search channel
                startNextSearch();
                break;

            case ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40:
                if (response.messageContents[1] == (byte)ANT_ReferenceLibrary.ANTMessageID.EVENT_0x01)
                {
                    //if(response.messageContents[2] == 0x01)  //Search timeout causes close channel, so wait for that
                    if (response.messageContents[2] == (byte)ANT_ReferenceLibrary.ANTEventID.EVENT_CHANNEL_CLOSED_0x07)     //Closed channel
                    {
                        startNextSearch();
                    }
                }
                break;
            }
        }
        private byte[] waitForMsg(byte[] leadingBytes, int wait_ms)
        {
            Queue <ANT_Response> msgSave = new Queue <ANT_Response>();
            int          i = 0;
            ANT_Response curResponse;

            System.Diagnostics.Stopwatch waitTimer = new System.Diagnostics.Stopwatch();
            waitTimer.Start();
            do
            {
                while (responseBuf.Count > 0)
                {
                    curResponse = responseBuf.Dequeue();
                    msgSave.Enqueue(curResponse);
                    //If the leading bytes match our expected response
                    if (curResponse.responseID.Equals(leadingBytes[0]))
                    {
                        //Check message id matches
                        for (i = 1; i < leadingBytes.Length; ++i)
                        {
                            //Check remaining bytes to check
                            if (!curResponse.messageContents[i - 1].Equals(leadingBytes[i]))
                            {
                                break;
                            }
                        }
                        //If all bytes matched return the remaining bytes of the message
                        if (i == leadingBytes.Length)
                        {
                            //Save the seen messages back to the response buffer
                            responseBuf = new Queue <ANT_Response>(msgSave.Concat(responseBuf));

                            //Send out the information
                            lastAcceptedResponse = curResponse;
                            i -= 1; //Start at the byte we were at
                            return(curResponse.messageContents.Skip(i).ToArray());
                        }
                    }
                }
            } while (waitTimer.ElapsedMilliseconds < wait_ms);

            //If we didn't find a matching response
            responseBuf          = new Queue <ANT_Response>(msgSave.Concat(responseBuf));
            lastAcceptedResponse = null;
            throw new Exception("Expected Message Timeout");
        }
Example #17
0
        void DeviceResponse(ANT_Response response)
        {
            switch ((ANTMessageID)response.responseID)
            {
            case ANTMessageID.STARTUP_MESG_0x6F:
                // RESET Complete
                break;

            case ANTMessageID.VERSION_0x3E:
                Debug.WriteLine("VERSION: " + new ASCIIEncoding().GetString(response.messageContents));
                break;

            case ANTMessageID.RESPONSE_EVENT_0x40:
                DeviceEventResponse(response);
                break;
            }
        }
        /// <summary>
        /// Wait for a message matching the desired pattern
        /// </summary>
        /// <param name="matchPattern">Pattern to match</param>
        /// <param name="wait_ms">time to wait, in ms</param>
        /// <returns>True if the matching message is seen in the configured timeout</returns>
        public bool WaitForNextMatchMsg(int[] matchPattern, int wait_ms)
        {
            Queue <ANT_Response> msgSave = new Queue <ANT_Response>();
            ANT_Response         curResponse;
            int i;

            responseBuf.Clear();
            System.Diagnostics.Stopwatch waitTimer = new System.Diagnostics.Stopwatch();
            waitTimer.Start();
            do
            {
                while (responseBuf.Count > 0)
                {
                    System.Threading.Thread.Sleep(10); //Allow time for a new message to arrive
                    curResponse = responseBuf.Dequeue();
                    msgSave.Enqueue(curResponse);
                    //Check each byte with the conditional match function against the given conditional byte match array
                    if (compareConditionalByte(curResponse.responseID, matchPattern[0]) && curResponse.messageContents.Length == (matchPattern.Length - 1))
                    {
                        //Check message id matches
                        for (i = 1; i < matchPattern.Length; ++i)
                        {
                            //Check remaining bytes to check
                            if (!compareConditionalByte(curResponse.messageContents[i - 1], matchPattern[i]))
                            {
                                break;
                            }
                        }
                        //If all bytes matched then we succeeded
                        if (i == matchPattern.Length)
                        {
                            //Save all the seen messages back to the buffer
                            responseBuf          = new Queue <ANT_Response>(msgSave.Concat(responseBuf));
                            lastAcceptedResponse = curResponse;
                            return(true);
                        }
                    }
                }
            } while (waitTimer.ElapsedMilliseconds < wait_ms);

            //If we didn't find a match
            responseBuf          = new Queue <ANT_Response>(msgSave.Concat(responseBuf));
            lastAcceptedResponse = null;
            return(false);
        }
        /// <summary>
        /// Handle ANT channel responses, while in broadcast mode
        /// </summary>
        /// <param name="response">ANT channel event</param>
        public void HandleChannelResponses(ANT_Response response)
        {
            // Make sure we are not processing responses if ANT-FS is active
            if (antfsHost.GetStatus() != ANTFS_HostChannel.State.Idle)
            {
                return;
            }

            if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E)
            {
                Console.Write("Rx: " + Demo.CursorStrings[cursorIndex++] + "\r");
                cursorIndex &= 3;
                if (response.getDataPayload()[7] >= 40)                 // Receive data for about 10 seconds
                {
                    antfsHost.RequestSession(Demo.SearchRF, ConnectRF); // Request ANT-FS session
                }
            }
        }
        /// <summary>
        /// Handle channel responses, while in broadcast mode
        /// </summary>
        /// <param name="response">ANT channel events</param>
        public void HandleChannelResponses(ANT_Response response)
        {
            // Make sure we are not processing responses if ANT-FS is active
            if (antfsClient.GetStatus() != ANTFS_ClientChannel.State.Idle)
            {
                return;
            }

            if ((response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40))
            {
                if (response.getChannelEventCode() == ANT_ReferenceLibrary.ANTEventID.EVENT_TX_0x03)
                {
                    channel0.sendBroadcastData(txBuffer);
                    txBuffer[7]++;
                    Console.Write("Tx: " + Demo.CursorStrings[cursorIndex++] + "\r");
                    cursorIndex &= 3;
                }
                else if (response.getChannelEventCode() == ANT_ReferenceLibrary.ANTEventID.EVENT_CHANNEL_CLOSED_0x07)
                {
                    Console.WriteLine("Channel Closed");
                    Console.WriteLine("Unassigning Channel...");
                    if (channel0.unassignChannel(500))
                    {
                        Console.WriteLine("Unassigned Channel");
                        Console.WriteLine("Press enter to exit");
                        demoDone = true;
                    }
                }
            }
            else if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.ACKNOWLEDGED_DATA_0x4F)
            {
                // Look for request page
                if (response.messageContents[1] == 0x46)
                {
                    if (response.messageContents[6] == 0 &&
                        response.messageContents[7] == 0x43 &&
                        response.messageContents[8] == 0x02)
                    {
                        Console.WriteLine("Remote device requesting ANT-FS session");
                    }
                    antfsClient.OpenBeacon();
                }
            }
        }
Example #21
0
 void OnChannelResponse(ANT_Response response)
 {
     if (response.getChannelEventCode() == ANT_ReferenceLibrary.ANTEventID.EVENT_RX_FAIL_0x02)
     {
         DisplayText("channel " + response.antChannel.ToString() + " " + "RX fail");
     }
     else if (response.getChannelEventCode() == ANT_ReferenceLibrary.ANTEventID.EVENT_RX_FAIL_GO_TO_SEARCH_0x08)
     {
         DisplayText("channel " + response.antChannel.ToString() + " " + "Go to search");
     }
     else if (response.getChannelEventCode() == ANT_ReferenceLibrary.ANTEventID.EVENT_TX_0x03)
     {
         DisplayText("channel " + response.antChannel.ToString() + " " + "Tx: (" + response.antChannel.ToString() + ")" + BitConverter.ToString(hrChannel.txBuffer));
     }
     else
     {
         DisplayText("channel " + response.antChannel.ToString() + " " + response.getChannelEventCode());
     }
 }
Example #22
0
 private void handleANTResponses(ANT_Response response)
 {
     if ((int)response.responseID == 64)
     {
         if (response.getChannelEventCode() == ANT_ReferenceLibrary.ANTEventID.RESPONSE_NO_ERROR_0x00)
         {
             Debug.LogError("SET " + ((object)response.getMessageID()).ToString() + "... OK");
         }
         else
         {
             Debug.LogError("Response: " + ((object)response.getChannelEventCode()).ToString()
                            + " to " + ((object)response.getMessageID()).ToString());
         }
     }
     else
     {
         Debug.LogError(((object)(ANT_ReferenceLibrary.ANTMessageID)response.responseID).ToString());
     }
 }
Example #23
0
    String decodeDeviceFeedback(ANT_Response response)
    {
        string toDisplay = "Device: ";

        if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40)
        {
            toDisplay += (ANT_ReferenceLibrary.ANTMessageID)response.messageContents[1] + ", Ch:" + response.messageContents[0];
            if ((ANT_ReferenceLibrary.ANTEventID)response.messageContents[2] != ANT_ReferenceLibrary.ANTEventID.RESPONSE_NO_ERROR_0x00)
            {
                toDisplay += Environment.NewLine + ((ANT_ReferenceLibrary.ANTEventID)response.messageContents[2]).ToString();
            }
        }
        else   //If the message is not an event, we just show the messageID
        {
            toDisplay += ((ANT_ReferenceLibrary.ANTMessageID)response.responseID).ToString();
        }

        toDisplay += Environment.NewLine + "::" + Convert.ToString(response.responseID, 16) + ", " + BitConverter.ToString(response.messageContents) + Environment.NewLine;
        return(toDisplay);
    }
Example #24
0
    String decodeChannelFeedback(ANT_Response response)
    {
        StringBuilder stringToPrint;                         //We use a stringbuilder for speed and better memory usage, but, it doesn't really matter for the demo.

        stringToPrint = new StringBuilder("Channel: ", 100); //Begin the string and allocate some more space

        if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40)
        {
            stringToPrint.AppendLine(((ANT_ReferenceLibrary.ANTEventID)response.messageContents[2]).ToString());
        }
        else   //This is a receive event, so display the ID
        {
            stringToPrint.AppendLine("Received " + ((ANT_ReferenceLibrary.ANTMessageID)response.responseID).ToString());
        }

        stringToPrint.Append("  :: ");
        stringToPrint.Append(Convert.ToString(response.responseID, 16));
        stringToPrint.Append(", ");
        stringToPrint.Append(BitConverter.ToString(response.messageContents) + Environment.NewLine);
        return(stringToPrint.ToString());
    }
Example #25
0
        public sealed override void handleChannelResponse(ANT_Response response)
        {
            //Watch for collisions or failures, if we miss a message, interpolate from the last known speed
            if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40 &&
                response.messageContents[1] == (byte)ANT_ReferenceLibrary.ANTMessageID.EVENT_0x01 &&
                (response.messageContents[2] == (byte)ANT_ReferenceLibrary.ANTEventID.EVENT_RX_FAIL_0x02 ||
                 response.messageContents[2] == (byte)ANT_ReferenceLibrary.ANTEventID.EVENT_CHANNEL_COLLISION_0x09))
            {
                DataSourcePacket lastData = getLastDataRcvd();
                if (lastData != null)
                {
                    DateTime curEventTime = DateTime.Now;
                    double   timeMissed_s = curEventTime.Subtract(lastEventTime).TotalSeconds;
                    double   distMissed_m = timeMissed_s * averageSpeed; //Use the recent average speed so we get a closer estimate
                    interpolatedDistanceDiff += distMissed_m;

                    lastEventTime = curEventTime;
                    base.incrementDistanceAndUpdate(distMissed_m, averageSpeed, lastData.cadence, lastData.heartRate, lastData.power);

                    ////DEBUG
                    //System.Console.Out.WriteLine((ANT_ReferenceLibrary.ANTEventID)response.messageContents[2] + " interpolated " + distMissed_m);
                }
            }
            if (response.messageContents[2] == (byte)ANT_ReferenceLibrary.ANTEventID.EVENT_RX_FAIL_GO_TO_SEARCH_0x08)
            {
                //Sorry, if we drop to search there is not much we can do to recover, let the race display know we are dead
                base.incrementDistanceAndUpdate(0, 0, 0, 0, 0);
            }
            else //If it is not an rx failure, let the derived class handle it
            {
                //Don't worry about isInitialized=false on rx_drop_to_search here, because we hope the broadcast
                //comes back soon enough for it to not matter, if we have to wait long enough for it to matter,
                //we have waited too long anyway

                ////DEBUG
                //if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40)
                //    System.Console.Out.WriteLine((ANT_ReferenceLibrary.ANTEventID)response.messageContents[2]);
                handleNonRxFailChannelResponse(response);
            }
        }
        void channel_channelResponse(ANT_Response response)
        {
            switch ((ANT_ReferenceLibrary.ANTMessageID)response.responseID)
            {
            case ANT_ReferenceLibrary.ANTMessageID.ACKNOWLEDGED_DATA_0x4F:
                statusReport = String.Format("Open - Last Activity = {0}:{1}", DateTime.Now.ToLongTimeString(), "Rcvd Ack");
                lastMsgBytes = response.messageContents.Skip(1).ToArray();
                decodeCmd(lastMsgBytes);
                break;

            case ANT_ReferenceLibrary.ANTMessageID.BURST_DATA_0x50:
                statusReport = String.Format("Open - Last Activity = {0}:{1}", DateTime.Now.ToLongTimeString(), "Rcvd Burst");
                if ((response.messageContents[0] & 0xE0) == 0)      //first packet
                {
                    lastMsgBytes = response.messageContents.Skip(1).ToArray();
                }
                else
                {
                    lastMsgBytes = lastMsgBytes.Concat(response.messageContents.Skip(1)).ToArray();
                    if ((response.messageContents[0] & 0x80) == 0x80)    //last packet
                    {
                        decodeCmd(lastMsgBytes);
                    }
                }
                break;

            case ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40:
                //Print all messages except EVENT_TX to status
                if ((ANT_ReferenceLibrary.ANTEventID)response.messageContents[2] != ANT_ReferenceLibrary.ANTEventID.EVENT_TX_0x03)
                {
                    statusReport = String.Format("Open - Last Activity = {0}:{1}", DateTime.Now.ToLongTimeString(), (ANT_ReferenceLibrary.ANTEventID)response.messageContents[2]);
                }
                break;

            default:
                statusReport = String.Format("Open - Last Activity = {0}:{1}", DateTime.Now.ToLongTimeString(), (ANT_ReferenceLibrary.ANTMessageID)response.responseID);
                break;
            }
        }
        String decodeChannelFeedback(ANT_Response response)
        {
            //Decoding channel events is an important consideration when building applications.
            //The channel events will be where broadcast, ack and burst messages are received, you
            //are also notified of messages sent and, for acknowledged and burst messages, their success or failure.
            //In a burst transfer, or if the device is operating at a small message period, then it is important that
            //decoding the messages is done quickly and efficiently.
            //The way the response retrieval works, messages should never be lost. If you decode messages too slow, they are simply queued.
            //However, you will be retrieving messages at a longer and longer delay from when they were actually received by the device.

            //One further consideration when handling channel events is to remember that the feedback functions will be triggered on a different thread
            //which is operating within the managed library to retrieve the feedback from the device. So, if you need to interact with your UI objects
            //you will need to use a Dispatcher invoke with a prority that will not make the UI unresponsive (see the threadSafePrint function used here).

            StringBuilder stringToPrint;                         //We use a stringbuilder for speed and better memory usage, but, it doesn't really matter for the demo.

            stringToPrint = new StringBuilder("Channel: ", 100); //Begin the string and allocate some more space

            //In the channel feedback we will get either RESPONSE_EVENTs or receive events,
            //If it is a response event we display what the event was and the error code if it failed.
            //Mostly, these response_events will all be broadcast events from a Master channel.
            if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40)
            {
                stringToPrint.AppendLine(((ANT_ReferenceLibrary.ANTEventID)response.messageContents[2]).ToString());
            }
            else   //This is a receive event, so display the ID
            {
                stringToPrint.AppendLine("Received " + ((ANT_ReferenceLibrary.ANTMessageID)response.responseID).ToString());
            }

            //Always print the raw contents in hex, with leading '::' for easy visibility/parsing
            //If this is a receive event it will contain the payload of the message
            stringToPrint.Append("  :: ");
            stringToPrint.Append(Convert.ToString(response.responseID, 16));
            stringToPrint.Append(", ");
            stringToPrint.Append(BitConverter.ToString(response.messageContents) + Environment.NewLine);
            return(stringToPrint.ToString());
        }
        private void ChannelResponse(ANT_Response response)
        {
            // Debug.Log("[AntStick] " + decodeChannelFeedback(response));

            if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40)
            {
                if (response.messageContents[2] == (byte)ANT_ReferenceLibrary.ANTEventID.EVENT_RX_SEARCH_TIMEOUT_0x01)
                {
                    Debug.LogWarning("[AntStick] Failed to connect to any device.");
                    Debug.LogWarning("[AntStick] <b>WARNING --- UNITY MAY CRASH!</b> Try lowering AntStick.CONNECT_TIMEOUT value.");
                    UpdateState(AntState.ConnectFail);
                    Stop();
                }

                if (response.messageContents[2] == (byte)ANT_ReferenceLibrary.ANTEventID.EVENT_RX_FAIL_0x02)
                {
                    Stats.IncrementRxFailCount();
                }

                if (response.messageContents[2] == (byte)ANT_ReferenceLibrary.ANTEventID.EVENT_RX_FAIL_GO_TO_SEARCH_0x08)
                {
                    UpdateState(AntState.ReConnecting);
                    StartConnectTimeout();
                }
            }
            else
            {
                if (state == AntState.Starting || state == AntState.ReConnecting)
                {
                    Debug.Log("[AntStick] Successfully began receiving data.");
                    UpdateState(AntState.Connected);
                }

                DataPage dataPage = DataPage.BuildDataPageFromReceivedData(response.messageContents);
                Stats.IncrementPageCount(dataPage.DataPageNumber);
                dataPage.FireReceived();
            }
        }
Example #29
0
    ////////////////////////////////////////////////////////////////////////////////
    // ChannelResponse
    //
    // Called whenever a channel event is recieved.
    //
    // response: ANT message
    ////////////////////////////////////////////////////////////////////////////////
    void ChannelResponse(ANT_Response response)
    {
        //With the messageQueue we can deal with ANT response in the Unity main thread
        if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40)
        {
            messageQueue.Enqueue(response);
        }

        try
        {
            switch ((ANT_ReferenceLibrary.ANTMessageID)response.responseID)
            {
            case ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40:
            {
                switch (response.getChannelEventCode())
                {
                // This event indicates that a message has just been
                // sent over the air. We take advantage of this event to set
                // up the data for the next message period.
                case ANT_ReferenceLibrary.ANTEventID.EVENT_TX_0x03:
                {
                    // Broadcast data will be sent over the air on
                    // the next message period
                    if (broadcasting)
                    {
                        channel.sendBroadcastData(txBuffer);
                    }
                    break;
                }

                case ANT_ReferenceLibrary.ANTEventID.EVENT_RX_SEARCH_TIMEOUT_0x01:
                {
                    Debug.Log("Search Timeout");
                    break;
                }

                case ANT_ReferenceLibrary.ANTEventID.EVENT_RX_FAIL_0x02:
                {
                    if (!hideRXFAIL)
                    {
                        Debug.Log("Rx Fail");
                    }
                    break;
                }

                case ANT_ReferenceLibrary.ANTEventID.EVENT_TRANSFER_RX_FAILED_0x04:
                {
                    Debug.Log("Burst receive has failed");
                    break;
                }

                case ANT_ReferenceLibrary.ANTEventID.EVENT_TRANSFER_TX_COMPLETED_0x05:
                {
                    Debug.Log("Transfer Completed");
                    break;
                }

                case ANT_ReferenceLibrary.ANTEventID.EVENT_TRANSFER_TX_FAILED_0x06:
                {
                    Debug.Log("Transfer Failed");
                    break;
                }

                case ANT_ReferenceLibrary.ANTEventID.EVENT_CHANNEL_CLOSED_0x07:
                {
                    channel.unassignChannel(500);
                    break;
                }

                case ANT_ReferenceLibrary.ANTEventID.EVENT_RX_FAIL_GO_TO_SEARCH_0x08:
                {
                    Debug.Log("Go to Search");
                    break;
                }

                case ANT_ReferenceLibrary.ANTEventID.EVENT_CHANNEL_COLLISION_0x09:
                {
                    Debug.Log("Channel Collision");
                    break;
                }

                case ANT_ReferenceLibrary.ANTEventID.EVENT_TRANSFER_TX_START_0x0A:
                {
                    Debug.Log("Burst Started");
                    break;
                }

                default:
                {
                    Debug.Log("Unhandled Channel Event " + response.getChannelEventCode());
                    break;
                }
                }
                break;
            }

            case ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E:
            case ANT_ReferenceLibrary.ANTMessageID.ACKNOWLEDGED_DATA_0x4F:
            case ANT_ReferenceLibrary.ANTMessageID.BURST_DATA_0x50:
            case ANT_ReferenceLibrary.ANTMessageID.EXT_BROADCAST_DATA_0x5D:
            case ANT_ReferenceLibrary.ANTMessageID.EXT_ACKNOWLEDGED_DATA_0x5E:
            case ANT_ReferenceLibrary.ANTMessageID.EXT_BURST_DATA_0x5F:
            {
                if (response.isExtended() && isBackgroundScan == true)
                {
                    RXQueue.Enqueue(response.messageContents);
                }
                else
                {
                    RXQueue.Enqueue(response.getDataPayload());
                }
                break;
            }

            default:
            {
                Debug.Log("Unknown Message " + response.responseID);
                break;
            }
            }
        }
        catch (Exception ex)
        {
            Debug.Log("Channel response processing failed with exception: " + ex.Message);
        }
    }
Example #30
0
        ////////////////////////////////////////////////////////////////////////////////
        // DeviceResponse
        //
        // Called whenever a message is received from ANT unless that message is a
        // channel event message.
        //
        // response: ANT message
        ////////////////////////////////////////////////////////////////////////////////
        static void DeviceResponse(ANT_Response response)
        {
            switch ((ANT_ReferenceLibrary.ANTMessageID)response.responseID)
            {
            case ANT_ReferenceLibrary.ANTMessageID.STARTUP_MESG_0x6F:
            {
                Console.Write("RESET Complete, reason: ");

                byte ucReason = response.messageContents[0];

                if (ucReason == (byte)ANT_ReferenceLibrary.StartupMessage.RESET_POR_0x00)
                {
                    Console.WriteLine("RESET_POR");
                }
                if (ucReason == (byte)ANT_ReferenceLibrary.StartupMessage.RESET_RST_0x01)
                {
                    Console.WriteLine("RESET_RST");
                }
                if (ucReason == (byte)ANT_ReferenceLibrary.StartupMessage.RESET_WDT_0x02)
                {
                    Console.WriteLine("RESET_WDT");
                }
                if (ucReason == (byte)ANT_ReferenceLibrary.StartupMessage.RESET_CMD_0x20)
                {
                    Console.WriteLine("RESET_CMD");
                }
                if (ucReason == (byte)ANT_ReferenceLibrary.StartupMessage.RESET_SYNC_0x40)
                {
                    Console.WriteLine("RESET_SYNC");
                }
                if (ucReason == (byte)ANT_ReferenceLibrary.StartupMessage.RESET_SUSPEND_0x80)
                {
                    Console.WriteLine("RESET_SUSPEND");
                }
                break;
            }

            case ANT_ReferenceLibrary.ANTMessageID.VERSION_0x3E:
            {
                Console.WriteLine("VERSION: " + new ASCIIEncoding().GetString(response.messageContents));
                break;
            }

            case ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40:
            {
                switch (response.getMessageID())
                {
                case ANT_ReferenceLibrary.ANTMessageID.CLOSE_CHANNEL_0x4C:
                {
                    if (response.getChannelEventCode() == ANT_ReferenceLibrary.ANTEventID.CHANNEL_IN_WRONG_STATE_0x15)
                    {
                        Console.WriteLine("Channel is already closed");
                        Console.WriteLine("Unassigning Channel...");
                        if (channel0.unassignChannel(500))
                        {
                            Console.WriteLine("Unassigned Channel");
                            Console.WriteLine("Press enter to exit");
                            bDone = true;
                        }
                    }
                    break;
                }

                case ANT_ReferenceLibrary.ANTMessageID.NETWORK_KEY_0x46:
                case ANT_ReferenceLibrary.ANTMessageID.ASSIGN_CHANNEL_0x42:
                case ANT_ReferenceLibrary.ANTMessageID.CHANNEL_ID_0x51:
                case ANT_ReferenceLibrary.ANTMessageID.CHANNEL_RADIO_FREQ_0x45:
                case ANT_ReferenceLibrary.ANTMessageID.CHANNEL_MESG_PERIOD_0x43:
                case ANT_ReferenceLibrary.ANTMessageID.OPEN_CHANNEL_0x4B:
                case ANT_ReferenceLibrary.ANTMessageID.UNASSIGN_CHANNEL_0x41:
                {
                    if (response.getChannelEventCode() != ANT_ReferenceLibrary.ANTEventID.RESPONSE_NO_ERROR_0x00)
                    {
                        Console.WriteLine(String.Format("Error {0} configuring {1}", response.getChannelEventCode(), response.getMessageID()));
                    }
                    break;
                }

                case ANT_ReferenceLibrary.ANTMessageID.RX_EXT_MESGS_ENABLE_0x66:
                {
                    if (response.getChannelEventCode() == ANT_ReferenceLibrary.ANTEventID.INVALID_MESSAGE_0x28)
                    {
                        Console.WriteLine("Extended messages not supported in this ANT product");
                        break;
                    }
                    else if (response.getChannelEventCode() != ANT_ReferenceLibrary.ANTEventID.RESPONSE_NO_ERROR_0x00)
                    {
                        Console.WriteLine(String.Format("Error {0} configuring {1}", response.getChannelEventCode(), response.getMessageID()));
                        break;
                    }
                    Console.WriteLine("Extended messages enabled");
                    break;
                }

                case ANT_ReferenceLibrary.ANTMessageID.REQUEST_0x4D:
                {
                    if (response.getChannelEventCode() == ANT_ReferenceLibrary.ANTEventID.INVALID_MESSAGE_0x28)
                    {
                        Console.WriteLine("Requested message not supported in this ANT product");
                        break;
                    }
                    break;
                }

                default:
                {
                    Console.WriteLine("Unhandled response " + response.getChannelEventCode() + " to message " + response.getMessageID());                            break;
                }
                }
                break;
            }
            }
        }
Example #31
0
        private byte[] waitForMsg(byte[] leadingBytes, int wait_ms)
        {
            Queue<ANT_Response> msgSave = new Queue<ANT_Response>();
            int i = 0;
            ANT_Response curResponse;

            System.Diagnostics.Stopwatch waitTimer = new System.Diagnostics.Stopwatch();
            waitTimer.Start();
            do
            {
                while (responseBuf.Count > 0)
                {
                    curResponse = responseBuf.Dequeue();
                    msgSave.Enqueue(curResponse);
                    //If the leading bytes match our expected response
                    if (curResponse.responseID.Equals(leadingBytes[0]))
                    {
                        //Check message id matches
                        for (i = 1; i < leadingBytes.Length; ++i)
                        {
                            //Check remaining bytes to check
                            if (!curResponse.messageContents[i - 1].Equals(leadingBytes[i]))
                                break;
                        }
                        //If all bytes matched return the remaining bytes of the message
                        if (i == leadingBytes.Length)
                        {
                            //Save the seen messages back to the response buffer
                            responseBuf = new Queue<ANT_Response>(msgSave.Concat(responseBuf));

                            //Send out the information
                            lastAcceptedResponse = curResponse;
                            i -= 1; //Start at the byte we were at
                            return curResponse.messageContents.Skip(i).ToArray();
                        }
                    }

                }
            } while (waitTimer.ElapsedMilliseconds < wait_ms);

            //If we didn't find a matching response
            responseBuf = new Queue<ANT_Response>(msgSave.Concat(responseBuf));
            lastAcceptedResponse = null;
            throw new Exception("Expected Message Timeout");
        }
Example #32
0
 void dev_hostdeviceEvents(ANT_Response response)
 {
     hostdeviceEvents = response.messageContents;
     flagHostDeviceEvents = true;
 }
Example #33
0
 //TODO: This buffer gets really big if we sit around for very long
 void dev_deviceResponse(ANT_Response response)
 {
     responseBuf.Enqueue(response);
 }
Example #34
0
        /// <summary>
        /// Wait for a message matching the desired pattern
        /// </summary>
        /// <param name="matchPattern">Pattern to match</param>
        /// <param name="wait_ms">time to wait, in ms</param>
        /// <returns>True if the matching message is seen in the configured timeout</returns>
        public bool WaitForNextMatchMsg(int[] matchPattern, int wait_ms)
        {
            Queue<ANT_Response> msgSave = new Queue<ANT_Response>();
            ANT_Response curResponse;
            int i;

            responseBuf.Clear();
            System.Diagnostics.Stopwatch waitTimer = new System.Diagnostics.Stopwatch();
            waitTimer.Start();
            do
            {
                while (responseBuf.Count > 0)
                {
                    System.Threading.Thread.Sleep(10); //Allow time for a new message to arrive
                    curResponse = responseBuf.Dequeue();
                    msgSave.Enqueue(curResponse);
                    //Check each byte with the conditional match function against the given conditional byte match array
                    if (compareConditionalByte(curResponse.responseID, matchPattern[0]) && curResponse.messageContents.Length == (matchPattern.Length - 1))
                    {
                        //Check message id matches
                        for (i = 1; i < matchPattern.Length; ++i)
                        {
                            //Check remaining bytes to check
                            if (!compareConditionalByte(curResponse.messageContents[i - 1], matchPattern[i]))
                                break;
                        }
                        //If all bytes matched then we succeeded
                        if (i == matchPattern.Length)
                        {
                            //Save all the seen messages back to the buffer
                            responseBuf = new Queue<ANT_Response>(msgSave.Concat(responseBuf));
                            lastAcceptedResponse = curResponse;
                            return true;
                        }
                    }
                }
            } while (waitTimer.ElapsedMilliseconds < wait_ms);

            //If we didn't find a match
            responseBuf = new Queue<ANT_Response>(msgSave.Concat(responseBuf));
            lastAcceptedResponse = null;
            return false;
        }