//public void RequestDataPage(byte pageNumber) //{ // if (state != AntState.Connected) // return; // byte[] message = new byte[8]; // message[0] = 0x46; // Data Page Request // message[1] = 0xFF; // Reserved // message[2] = 0xFF; // Reserved // message[3] = 0xFF; // Descriptor Byte 1 (0xFF = None) // message[4] = 0xFF; // Descriptor Byte 2 (0xFF = None) // message[5] = 0x04; // Ask to transmit 4 times. // message[6] = pageNumber; // Requested Page Number // message[7] = 0x01; // 0x01 = Data Page, 0x02 = ANT-FS // // Debug.LogFormat("[AntStick] Sending Broadcast {0}", BitConverter.ToString(message)); // // if (channel != null) // channel.sendBroadcastData(message); //} public void SendResistance(float resistance) { if (state != AntState.Connected) { return; } // The control point parameter for resistance mode is a 14-bit value transmitted in a // 16-bit unsigned. This value is the PWM duty cycle, 0 is full off, and 0x3FFF is full // on. // Clamp the resistance between 0 and 1. if (resistance < 0f) { resistance = 0f; } if (resistance > 1f) { resistance = 1f; } // Invert the scale to account for active low. resistance = 1f - resistance; // Convert the scale to 14-bit integer. ushort resistance16bit = (ushort)(resistance * 0x3FFF); // Build the message. The Kickr doesn't actually seem to care if the device Id is set // correctly so don't even bother setting it. byte[] message = new byte[8]; message[0] = 0xF1; // Wahoo Kickr Command Page message[1] = 0x40; // Set Resistance Mode message[2] = 0xFF; // Device Id Low Byte message[3] = 0xFF; // Device Id High Byte message[4] = (byte)resistance16bit; // Resistance Low Byte message[5] = (byte)(resistance16bit >> 8); // Resistance High Byte message[6] = 0xFF; // Reserved message[7] = 0xFF; // Reserved // Debug.LogFormat("[AntStick] Sending Broadcast {0}", BitConverter.ToString(message)); if (channel != null) { channel.sendBroadcastData(message); } }
/// <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(); } } }
//////////////////////////////////////////////////////////////////////////////// // 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); } }
//////////////////////////////////////////////////////////////////////////////// // ChannelResponse // // Called whenever a channel event is recieved. // // response: ANT message //////////////////////////////////////////////////////////////////////////////// public void ChannelResponse(ANT_Response 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: { txBuffer[0]++; // Increment the first byte of the buffer // Broadcast data will be sent over the air on // the next message period if (bBroadcasting) { channel0.sendBroadcastData(txBuffer); if (bDisplay) { // Echo what the data will be over the air on the next message period Console.WriteLine("Tx: (" + response.antChannel.ToString() + ")" + BitConverter.ToString(txBuffer)); } } else { string[] ac = { "|", "/", "_", "\\" }; Console.Write("Tx: " + ac[iIndex++] + "\r"); iIndex &= 3; } break; } case ANT_ReferenceLibrary.ANTEventID.EVENT_RX_SEARCH_TIMEOUT_0x01: { Console.WriteLine("Search Timeout"); break; } case ANT_ReferenceLibrary.ANTEventID.EVENT_RX_FAIL_0x02: { Console.WriteLine("Rx Fail"); break; } case ANT_ReferenceLibrary.ANTEventID.EVENT_TRANSFER_RX_FAILED_0x04: { Console.WriteLine("Burst receive has failed"); break; } case ANT_ReferenceLibrary.ANTEventID.EVENT_TRANSFER_TX_COMPLETED_0x05: { Console.WriteLine("Transfer Completed"); break; } case ANT_ReferenceLibrary.ANTEventID.EVENT_TRANSFER_TX_FAILED_0x06: { Console.WriteLine("Transfer Failed"); break; } case ANT_ReferenceLibrary.ANTEventID.EVENT_CHANNEL_CLOSED_0x07: { // This event should be used to determine that the channel is closed. Console.WriteLine("Channel 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.ANTEventID.EVENT_RX_FAIL_GO_TO_SEARCH_0x08: { Console.WriteLine("Go to Search"); break; } case ANT_ReferenceLibrary.ANTEventID.EVENT_CHANNEL_COLLISION_0x09: { Console.WriteLine("Channel Collision"); break; } case ANT_ReferenceLibrary.ANTEventID.EVENT_TRANSFER_TX_START_0x0A: { Console.WriteLine("Burst Started"); break; } default: { Console.WriteLine("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 (bDisplay) { if (response.isExtended()) // Check if we are dealing with an extended message { ANT_ChannelID chID = response.getDeviceIDfromExt(); // Channel ID of the device we just received a message from if (chID.deviceTypeID == 120) { this.Heartrate = System.Convert.ToString(response.getDataPayload()[7]); // Device type for HR monitor is 120 } else if (chID.deviceTypeID == 11) { if (response.getDataPayload()[0] == 10) { this.pwr = response.getDataPayload()[7]; this.cadence = response.getDataPayload()[4]; } } if (chID.deviceTypeID == 120) { this.Heartrate = System.Convert.ToString(response.getDataPayload()[7]); } Console.Write("Chan ID(" + chID.deviceNumber.ToString() + "," + chID.deviceTypeID.ToString() + "," + chID.transmissionTypeID.ToString() + ") - "); } if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E || response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.EXT_BROADCAST_DATA_0x5D) { Console.Write("Rx:(" + response.antChannel.ToString() + "): "); } else if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.ACKNOWLEDGED_DATA_0x4F || response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.EXT_ACKNOWLEDGED_DATA_0x5E) { Console.Write("Acked Rx:(" + response.antChannel.ToString() + "): "); } else { Console.Write("Burst(" + response.getBurstSequenceNumber().ToString("X2") + ") Rx:(" + response.antChannel.ToString() + "): "); } //Console.Write(BitConverter.ToString(response.getDataPayload()) + Environment.NewLine); // Display data payload Console.Write(" Heart Rate is: " + this.Heartrate + Environment.NewLine); } else { string[] ac = { "|", "/", "_", "\\" }; Console.Write("Rx: " + ac[iIndex++] + "\r"); iIndex &= 3; } break; } default: { Console.WriteLine("Unknown Message " + response.responseID); break; } } } catch (Exception ex) { Console.WriteLine("Channel response processing failed with exception: " + ex.Message); } }
void ChannelEventResponse(ANT_Response response) { 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 ANTEventID.EVENT_TX_0x03: { txBuffer[0]++; // Increment the first byte of the buffer // Broadcast data will be sent over the air on // the next message period if (isBroadcasting) { channel.sendBroadcastData(txBuffer); } break; } case ANTEventID.EVENT_RX_SEARCH_TIMEOUT_0x01: { Debug.WriteLine("Search Timeout"); OnSearchEnded(this, false, 0); Closed(); break; } case ANTEventID.EVENT_RX_FAIL_0x02: { // Rx Fail break; } case ANTEventID.EVENT_TRANSFER_RX_FAILED_0x04: { // Burst receive has failed break; } case ANTEventID.EVENT_TRANSFER_TX_COMPLETED_0x05: { // Transfer Completed break; } case ANTEventID.EVENT_TRANSFER_TX_FAILED_0x06: { // Transfer Failed break; } case ANTEventID.EVENT_CHANNEL_CLOSED_0x07: { Debug.WriteLine("Channel closed"); // This event should be used to determine that the channel is closed. Closed(); break; } case ANTEventID.EVENT_RX_FAIL_GO_TO_SEARCH_0x08: { // Go to Search break; } case ANTEventID.EVENT_CHANNEL_COLLISION_0x09: { Debug.WriteLine("Channel Collision"); break; } case ANTEventID.EVENT_TRANSFER_TX_START_0x0A: { // Burst Started break; } default: { Debug.WriteLine("Unhandled Channel Event " + response.getChannelEventCode()); break; } } }
static void Start() { bDone = false; PrintMenu(); try { while (!bDone) { string command = Console.ReadLine(); switch (command) { case "M": case "m": { PrintMenu(); break; } case "U": case "u": { DisplayUSBConfiguration(); break; } case "Q": case "q": { // Quit Console.WriteLine(DateTime.Now + " - Closing Channel"); bDone = true; break; } case "A": case "a": { // Allocate USB Dongle AllocateUSBDongle(); break; } case "R": case "r": { // Release USB Dongle ReleaseUSBDongle(); break; } case "S": case "s": { // Re-Init USB Dongle Byte[] bytes = new byte[8]; channel0.sendBroadcastData(bytes); break; } default: { break; } } System.Threading.Thread.Sleep(0); } ReleaseUSBDongle(); // Clean up ANT //Console.WriteLine("Disconnecting ANT USB Dongle..."); //ANT_Device.shutdownDeviceInstance(ref device0); // Close down the device completely and completely shut down all communication WriteLog("Application has completed successfully!"); System.Threading.Thread.Sleep(1000); return; } catch (Exception ex) { throw new Exception("Error: " + ex.Message + Environment.NewLine); } }
static async void Init() { try { WriteLog("Connecting to ANT USB Dongle..."); //device0 = new ANT_Device(); // Create a device instance using the automatic constructor (automatic detection of USB device number and baud rate) device0.serialError += new ANT_Device.dSerialErrorHandler(SerialError); device0.deviceResponse += new ANT_Device.dDeviceResponseHandler(DeviceResponse); // Add device response function to receive protocol event messages channel0 = device0.getChannel(USER_ANT_CHANNEL); // Get channel from ANT device channel0.channelResponse += new dChannelResponseHandler(ChannelResponse); // Add channel response function to receive channel event messages WriteLog("ANT USB Dongle initialization successful"); WriteLog("ANT USB Dongle Device Number: " + device0.getOpenedUSBDeviceNum()); WriteLog("ANT USB Dongle Serial Number: " + device0.getSerialNumber()); USER_DEVICENUM = (ushort)device0.getOpenedUSBDeviceNum(); bReset = false; List <Task> tasks = new List <Task>(); tasks.Add(Task.Factory.StartNew(() => { while (!bReset) { WriteLog("Checking ANT USB Dongle..."); Byte[] bytes = new byte[8]; try { if (channel0.sendBroadcastData(bytes)) { WriteLog("ANT USB Dongle is operationnal"); } else { WriteLog("ANT USB Dongle is not operationnal"); } } catch (Exception ex) { WriteLog("Problem with ANT USB Dongle..."); } System.Threading.Thread.Sleep(5000); } })); await Task.WhenAll(tasks); } catch (Exception ex) { Console.WriteLine("Exception: " + ex); } /* * if (device0 == null) // Unable to connect to ANT * { * throw new Exception("Could not connect to any ANT device.\n" + * "Details: \n " + ex.Message); * } * else * { * throw new Exception("Error connecting to ANT device: " + ex.Message); * } * } */ }