DemoWindow.xaml.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. /*
  2. This software is subject to the license described in the License.txt file
  3. included with this software distribution. You may not use this file except
  4. in compliance with this license.
  5. Copyright (c) Dynastream Innovations Inc. 2016
  6. All rights reserved.
  7. */
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Linq;
  11. using System.Text;
  12. using System.Windows;
  13. using System.Windows.Controls;
  14. using System.Windows.Data;
  15. using System.Windows.Documents;
  16. using System.Windows.Input;
  17. using System.Windows.Media;
  18. using System.Windows.Media.Imaging;
  19. using System.Windows.Navigation;
  20. using System.Windows.Shapes;
  21. using ANT_Managed_Library; //Reference the ANT_Managed_Library namespace to make the code easier and more readable
  22. /*
  23. * Setup instructions for creating .NET application using the managed library:
  24. * To use the library you must first import ANT_NET.dll as a reference.
  25. * Then, three additional libraries must also be present in the directory:
  26. * DSI_CP210xManufacturing_3_1.dll, DSI_SiUSBXp_3_1.dll, and the ANT_WrappedLib.dll
  27. *
  28. * That's it! Now start coding. Below is a sample application using the
  29. * managed library. The comments explain the library's features and some of the
  30. * basic functions and their usage.
  31. *
  32. */
  33. namespace ANT_NetDll_Demo
  34. {
  35. public partial class DemoWindow : Window
  36. {
  37. //This delegate is for using the dispatcher to avoid conflicts of the feedback thread referencing the UI elements
  38. delegate void dAppendText(String toAppend);
  39. /*
  40. * The ANT_Managed_Library has been designed so that if you have a valid reference
  41. * to an ANTDevice object it is a valid reference to a physical ANT device connected
  42. * to your computer. This can be broken by uncontrollable events such as physically
  43. * unplugging the device, but otherwise each ANTDevice object will always represent a
  44. * physical ANT device connected to your computer.
  45. *
  46. * The default behaviour is the device is reset when an instance is created so every time
  47. * you create a device you will have a fresh instance, unless you disable the automatic
  48. * reset in the static ANT_Common class.
  49. *
  50. * The ANT_Common class also contains the controls for managing debug logs, which are
  51. * pretty self-explanatory.
  52. *
  53. */
  54. ANT_Device device0;
  55. ANT_Device device1;
  56. public DemoWindow()
  57. {
  58. InitializeComponent();
  59. }
  60. //Calls the startup or shutdown function, and changes the UI accordingly
  61. private void button_Start_Click(object sender, RoutedEventArgs e)
  62. {
  63. if (button_Start.Content.Equals("Start Demo"))
  64. {
  65. if (startUp())
  66. {
  67. comboBox_demoMode.IsEnabled = false;
  68. border_DemoControls.IsEnabled = true;
  69. button_DoAction.IsEnabled = true;
  70. button_Start.Background = System.Windows.Media.Brushes.Salmon;
  71. button_Start.Content = "Stop Demo";
  72. return;
  73. }
  74. }
  75. //If we get here it means we failed startup or are stopping the demo
  76. shutdown();
  77. comboBox_demoMode.IsEnabled = true;
  78. button_DoAction.IsEnabled = false;
  79. button_Start.Background = System.Windows.Media.Brushes.LightGreen;
  80. button_Start.Content = "Start Demo";
  81. }
  82. //Creates the ANTDevice instances and calls the setupAndOpen routine according to the selected demo mode
  83. private bool startUp()
  84. {
  85. //The managed library will throw ANTExceptions on errors
  86. //We run this in a try catch because we want to print any errors instead of crash
  87. try
  88. {
  89. //Regardless of selection we need to connect to the first device
  90. //The library has an automatic constructor to automatically connect to the first available device
  91. //You can still manually choose which device to connect to by using the parameter constructor,
  92. // ie: ANTDeviceInstance = new ANTDevice(0, 57600)
  93. device0 = new ANT_Device();
  94. //First we want to setup the response functions so we can see the feedback as we setup
  95. //To do this, the device and each channel have response events which are fired when feedback
  96. //is received from the device, including command acknowledgements and transmission events.
  97. device0.deviceResponse += new ANT_Device.dDeviceResponseHandler(device0_deviceResponse);
  98. device0.getChannel(0).channelResponse += new dChannelResponseHandler(d0channel0_channelResponse);
  99. textBox_device0.Text = "Device 0 Connected" + Environment.NewLine;
  100. //Now handle the rest of the setup based on what mode we are in
  101. switch (comboBox_demoMode.SelectedIndex)
  102. {
  103. case 0: //Dev 0 - Master, Dev1 - Slave
  104. textBox_Display.Text = "Starting Mode: d0-Master, d1-Slave" + Environment.NewLine;
  105. //In this library we can connect to multiple devices by creating a new instance of an ANTDevice
  106. //So, in this mode we need a second device
  107. try
  108. {
  109. device1 = new ANT_Device();
  110. }
  111. catch (Exception ex) //Forward the exception with some more info
  112. {
  113. throw new Exception("Can not connect to second device, " + ex.Message);
  114. }
  115. textBox_device1.Text = "Device 1 Connected" + Environment.NewLine;
  116. textBox_device1.IsEnabled = true;
  117. //We need to assign the device1 response function now too
  118. device1.deviceResponse += new ANT_Device.dDeviceResponseHandler(device1_deviceResponse);
  119. device1.getChannel(0).channelResponse += new dChannelResponseHandler(d1channel0_channelResponse);
  120. //To be a little clearer we handle the setup in a common method which takes the device instance
  121. //and the channel type enum
  122. setupAndOpen(device0, ANT_ReferenceLibrary.ChannelType.BASE_Master_Transmit_0x10);
  123. setupAndOpen(device1, ANT_ReferenceLibrary.ChannelType.BASE_Slave_Receive_0x00);
  124. break;
  125. case 1: //Dev 0 Only - Master
  126. textBox_Display.Text = "Starting Mode: d0 only - Master" + Environment.NewLine;
  127. textBox_device1.Text = "Device 1 Not Used" + Environment.NewLine;
  128. textBox_device1.IsEnabled = false;
  129. setupAndOpen(device0, ANT_ReferenceLibrary.ChannelType.BASE_Master_Transmit_0x10);
  130. break;
  131. case 2: //Dev 0 Only - Slave
  132. textBox_Display.Text = "Starting Mode: d0 only - Slave" + Environment.NewLine;
  133. textBox_device1.Text = "Device 1 Not Used" + Environment.NewLine;
  134. textBox_device1.IsEnabled = false;
  135. setupAndOpen(device0, ANT_ReferenceLibrary.ChannelType.BASE_Slave_Receive_0x00);
  136. break;
  137. }
  138. }
  139. catch (Exception ex)
  140. {
  141. textBox_Display.AppendText("Error: " + ex.Message + Environment.NewLine);
  142. if (device0 == null) //We print another message if we didn't connect to any device to be a little more helpful
  143. textBox_Display.AppendText("Could not connect to any devices, ensure an ANT device is connected to your system and try again." + Environment.NewLine);
  144. textBox_Display.AppendText(Environment.NewLine);
  145. return false;
  146. }
  147. return true;
  148. }
  149. private void setupAndOpen(ANT_Device deviceToSetup, ANT_ReferenceLibrary.ChannelType channelType)
  150. {
  151. //We try-catch and forward exceptions to the calling function to handle and pass the errors to the user
  152. try
  153. {
  154. //To access an ANTChannel on a paticular device we need to get the channel from the device
  155. //Once again, this ensures you have a valid object associated with a real-world ANTChannel
  156. //ie: You can only get channels that actually exist
  157. ANT_Channel channel0 = deviceToSetup.getChannel(0);
  158. //Almost all functions in the library have two overloads, one with a response wait time and one without
  159. //If you give a wait time, you can check the return value for success or failure of the command, however
  160. //the wait time version is blocking. 500ms is usually a safe value to ensure you wait long enough for any response.
  161. //But with no wait time, the command is simply sent and you have to monitor the device response for success or failure.
  162. //To setup channels for communication there are three mandatory operations assign, setID, and Open
  163. //Various other settings such as message period and network key affect communication
  164. //between two channels as well, see the documentation for further details on these functions.
  165. //So, first we assign the channel, we have already been passed the channelType which is an enum that has various flags
  166. //If we were doing something more advanced we could use a bitwise or ie:base|adv1|adv2 here too
  167. //We also use net 0 which has the public network key by default
  168. if (channel0.assignChannel(channelType, 0, 500))
  169. threadSafePrintLine("Ch assigned to " + channelType + " on net 0.", textBox_Display);
  170. else
  171. throw new Exception("Channel assignment operation failed.");
  172. //Next we have to set the channel id. Slaves will only communicate with a master device that
  173. //has the same id unless one or more of the id parameters are set to a wild card 0. If wild cards are included
  174. //the slave will search until it finds a broadcast that matches all the non-wild card parameters in the id.
  175. //For now we pick an arbitrary id so that we can ensure we match between the two devices.
  176. //The pairing bit ensures on a search that you only pair with devices that also are requesting
  177. //pairing, but we don't need it here so we set it to false
  178. if(channel0.setChannelID(12345, false, 67, 89, 500))
  179. threadSafePrintLine("Set channel ID to 12345, 67, 89", textBox_Display);
  180. else
  181. throw new Exception("Set Channel ID operation failed.");
  182. //Setting the channel period isn't mandatory, but we set it slower than the default period so messages aren't coming so fast
  183. //The period parameter is divided by 32768 to set the period of a message in seconds. So here, 16384/32768 = 1/2 sec/msg = 2Hz
  184. if(channel0.setChannelPeriod(16384, 500))
  185. threadSafePrintLine("Message Period set to 16384/32768 seconds per message", textBox_Display);
  186. //Now we open the channel
  187. if(channel0.openChannel(500))
  188. threadSafePrintLine("Opened Channel" + Environment.NewLine, textBox_Display);
  189. else
  190. throw new Exception("Channel Open operation failed.");
  191. }
  192. catch (Exception ex)
  193. {
  194. throw new Exception("Setup and Open Failed. " + ex.Message + Environment.NewLine);
  195. }
  196. }
  197. //Print the device response to the textbox
  198. void device0_deviceResponse(ANT_Response response)
  199. {
  200. threadSafePrintLine(decodeDeviceFeedback(response), textBox_device0);
  201. }
  202. //Print the channel response to the textbox
  203. void d0channel0_channelResponse(ANT_Response response)
  204. {
  205. threadSafePrintLine(decodeChannelFeedback(response), textBox_device0);
  206. }
  207. //Print the device response to the textbox
  208. void device1_deviceResponse(ANT_Response response)
  209. {
  210. threadSafePrintLine(decodeDeviceFeedback(response), textBox_device1);
  211. }
  212. //Print the channel response to the textbox
  213. void d1channel0_channelResponse(ANT_Response response)
  214. {
  215. threadSafePrintLine(decodeChannelFeedback(response), textBox_device1);
  216. }
  217. //This function decodes the message code into human readable form, shows the error value on failures, and also shows the raw message contents
  218. String decodeDeviceFeedback(ANT_Response response)
  219. {
  220. string toDisplay = "Device: ";
  221. //The ANTReferenceLibrary contains all the message and event codes in user-friendly enums
  222. //This allows for more readable code and easy conversion to human readable strings for displays
  223. // So, for the device response we first check if it is an event, then we check if it failed,
  224. // and display the failure if that is the case. "Events" use message code 0x40.
  225. if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40)
  226. {
  227. //We cast the byte to its messageID string and add the channel number byte associated with the message
  228. toDisplay += (ANT_ReferenceLibrary.ANTMessageID)response.messageContents[1] + ", Ch:" + response.messageContents[0];
  229. //Check if the eventID shows an error, if it does, show the error message
  230. if ((ANT_ReferenceLibrary.ANTEventID)response.messageContents[2] != ANT_ReferenceLibrary.ANTEventID.RESPONSE_NO_ERROR_0x00)
  231. toDisplay += Environment.NewLine + ((ANT_ReferenceLibrary.ANTEventID)response.messageContents[2]).ToString();
  232. }
  233. else //If the message is not an event, we just show the messageID
  234. toDisplay += ((ANT_ReferenceLibrary.ANTMessageID)response.responseID).ToString();
  235. //Finally we display the raw byte contents of the response, converting it to hex
  236. toDisplay += Environment.NewLine + "::" + Convert.ToString(response.responseID, 16) + ", " + BitConverter.ToString(response.messageContents) + Environment.NewLine;
  237. return toDisplay;
  238. }
  239. String decodeChannelFeedback(ANT_Response response)
  240. {
  241. //Decoding channel events is an important consideration when building applications.
  242. //The channel events will be where broadcast, ack and burst messages are received, you
  243. //are also notified of messages sent and, for acknowledged and burst messages, their success or failure.
  244. //In a burst transfer, or if the device is operating at a small message period, then it is important that
  245. //decoding the messages is done quickly and efficiently.
  246. //The way the response retrieval works, messages should never be lost. If you decode messages too slow, they are simply queued.
  247. //However, you will be retrieving messages at a longer and longer delay from when they were actually received by the device.
  248. //One further consideration when handling channel events is to remember that the feedback functions will be triggered on a different thread
  249. //which is operating within the managed library to retrieve the feedback from the device. So, if you need to interact with your UI objects
  250. //you will need to use a Dispatcher invoke with a prority that will not make the UI unresponsive (see the threadSafePrint function used here).
  251. StringBuilder stringToPrint; //We use a stringbuilder for speed and better memory usage, but, it doesn't really matter for the demo.
  252. stringToPrint = new StringBuilder("Channel: ", 100); //Begin the string and allocate some more space
  253. //In the channel feedback we will get either RESPONSE_EVENTs or receive events,
  254. //If it is a response event we display what the event was and the error code if it failed.
  255. //Mostly, these response_events will all be broadcast events from a Master channel.
  256. if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40)
  257. stringToPrint.AppendLine(((ANT_ReferenceLibrary.ANTEventID)response.messageContents[2]).ToString());
  258. else //This is a receive event, so display the ID
  259. stringToPrint.AppendLine("Received " + ((ANT_ReferenceLibrary.ANTMessageID)response.responseID).ToString());
  260. //Always print the raw contents in hex, with leading '::' for easy visibility/parsing
  261. //If this is a receive event it will contain the payload of the message
  262. stringToPrint.Append(" :: ");
  263. stringToPrint.Append(Convert.ToString(response.responseID, 16));
  264. stringToPrint.Append(", ");
  265. stringToPrint.Append(BitConverter.ToString(response.messageContents) + Environment.NewLine);
  266. return stringToPrint.ToString();
  267. }
  268. void threadSafePrintLine(String stringToPrint, TextBox boxToPrintTo)
  269. {
  270. //We need to put this on the dispatcher because sometimes it is called by the feedback thread
  271. //If you set the priority to 'background' then it never interferes with the UI interaction if you have a high message rate (we don't have to worry about it in the demo)
  272. boxToPrintTo.Dispatcher.BeginInvoke(new dAppendText(boxToPrintTo.AppendText), System.Windows.Threading.DispatcherPriority.Background, stringToPrint + Environment.NewLine);
  273. }
  274. private void shutdown()
  275. {
  276. //If you need to manually disconnect from a ANTDevice call the shutdownDeviceInstance method,
  277. //It releases all the resources, the device, and nullifies the object reference
  278. ANT_Device.shutdownDeviceInstance(ref device0);
  279. ANT_Device.shutdownDeviceInstance(ref device1);
  280. }
  281. //This function just automatically scrolls to the bottom of the textbox
  282. private void textBox_autoScroll(object sender, TextChangedEventArgs e)
  283. {
  284. ((TextBox)sender).ScrollToEnd();
  285. }
  286. private void button_DoAction_Click(object sender, RoutedEventArgs e)
  287. {
  288. switch ((String)((ComboBoxItem)comboBox_actionList.SelectedItem).Content)
  289. {
  290. case "Send Acknowledged Message (d0)":
  291. action_SendAcknowledged();
  292. break;
  293. case "Send Burst Message (d0)":
  294. action_SendBurst();
  295. break;
  296. case "Set Broadcast to random value (d0)":
  297. action_SetRandomBroadcast();
  298. break;
  299. case "Request Capabilities":
  300. action_ReqCapabilities();
  301. break;
  302. case "Request Version":
  303. action_ReqVersion();
  304. break;
  305. case "Request Channel ID":
  306. action_ReqChannelID();
  307. break;
  308. case "Request Status":
  309. action_ReqStatus();
  310. break;
  311. default:
  312. break;
  313. }
  314. threadSafePrintLine("", textBox_Display);
  315. }
  316. private void action_SendAcknowledged()
  317. {
  318. //Acknowledged messages send an 8 byte payload and listen for an acknowledgement from a receiving device
  319. //They return a MessagingReturnCode indicating the result of the process.
  320. //The byte array sent in the transmission functions can be any length and will be automatically padded with zeros
  321. threadSafePrintLine("Sending Acknowledged Message from device 0", textBox_Display);
  322. if (device0.getChannel(0).sendAcknowledgedData(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }, 500) != ANT_ReferenceLibrary.MessagingReturnCode.Pass)
  323. threadSafePrintLine("Acknowledged Message Failed", textBox_Display);
  324. else
  325. threadSafePrintLine("Acknowledged Message Succeeded", textBox_Display);
  326. }
  327. private void action_SendBurst()
  328. {
  329. //Burst transfers will send the contents of the given byte array in 8 byte packets, ensuring each packet is
  330. //acknowledged by a receiving device. Packets will be resent up to five times on failures, if the packet fails again
  331. //the device will stop the burst and return a failure message.
  332. //In the managaed library all that is required is packaging the data in a byte array and the rest of the details are handled automatically
  333. byte[] byteArray = new byte[256];
  334. for (int i = 0; i < 256; ++i)
  335. byteArray[i] = (byte)i;
  336. threadSafePrintLine("Sending Burst Message from device 0", textBox_Display);
  337. if(device0.getChannel(0).sendBurstTransfer(byteArray, 3000) != ANT_ReferenceLibrary.MessagingReturnCode.Pass)
  338. threadSafePrintLine("Burst Message Failed", textBox_Display);
  339. else
  340. threadSafePrintLine("Burst Message Succeeded", textBox_Display);
  341. }
  342. private void action_SetRandomBroadcast()
  343. {
  344. //At the given frequency specified by the set message period, a master channel will broadcast the contents of its buffer.
  345. //This buffer contains whatever was last sent by the device, so it is important to manage it if the master broadcast
  346. //contains information being used elsewhere. It is recommended to set the broadcast message to what it should be every time
  347. //you receive an EVENT_TX message
  348. //The sendBroadcast function sets the buffer. On a slave device, a single broadcast
  349. //message will be sent.
  350. threadSafePrintLine("Setting Device 0 Broadcast Buffer to Random Value", textBox_Display);
  351. byte[] randArray = new byte[8];
  352. Random generator = new Random();
  353. generator.NextBytes(randArray);
  354. if(!device0.getChannel(0).sendBroadcastData(randArray))
  355. threadSafePrintLine("Broadcast Message Failed", textBox_Display);
  356. else
  357. threadSafePrintLine("Broadcast Message Succeeded", textBox_Display);
  358. }
  359. private void action_ReqCapabilities()
  360. {
  361. //The managed library provides this function which automatically requests and decodes device capabilities.
  362. //Requesting Capabilities returns a DeviceCapabilities object containing all the parameters decoded.
  363. //These capabilities are cached, so the message is not requested with the physical device unless the
  364. //optional forceNewCopy parameter is set to true.
  365. //Here, we force a new copy show it shows in the device feedback. The function will throw an exception
  366. //if the operation times out so we watch for that.
  367. threadSafePrintLine("Requesting Device 0's Capabilities", textBox_Display);
  368. try
  369. {
  370. ANT_DeviceCapabilities currentCaps = device0.getDeviceCapabilities(true, 500);
  371. //The capabilities object convieniently converts to a formatted string
  372. threadSafePrintLine("Retrieved Device 0's Capabilites:", textBox_Display);
  373. threadSafePrintLine(currentCaps.ToString(), textBox_Display);
  374. }
  375. catch (Exception)
  376. {
  377. threadSafePrintLine("Requesting Capabilities of Device 0 Timed Out", textBox_Display);
  378. }
  379. //If device 1 is open, request its capabilities too
  380. if (device1 != null)
  381. {
  382. threadSafePrintLine("Requesting Device 1's Capabilities", textBox_Display);
  383. try
  384. {
  385. ANT_DeviceCapabilities currentCaps = device1.getDeviceCapabilities(true, 500);
  386. threadSafePrintLine("Retrieved Device 1's Capabilites:", textBox_Display);
  387. threadSafePrintLine(currentCaps.ToString(), textBox_Display);
  388. }
  389. catch (Exception)
  390. {
  391. threadSafePrintLine("Requesting Capabilities of Device 1 Timed Out", textBox_Display);
  392. }
  393. }
  394. }
  395. private void action_ReqVersion()
  396. {
  397. //To request the version we use the requestMessageAndResponse function. To request messages you could
  398. //also use the requestMessage function, but then you need to monitor the device feedback for the response.
  399. //The version string is a null terminated ascii string, so we decode it and display it
  400. threadSafePrintLine("Requesting Device 0 Version", textBox_Display);
  401. //On failure an exception is thrown so we watch for it
  402. try
  403. {
  404. ANT_Response version = device0.requestMessageAndResponse(ANT_ReferenceLibrary.RequestMessageID.VERSION_0x3E, 500);
  405. threadSafePrintLine("Device 0 ANT Version: " + new ASCIIEncoding().GetString(version.messageContents, 0, version.messageContents.Length - 1), textBox_Display);
  406. }
  407. catch (Exception)
  408. {
  409. threadSafePrintLine("Requesting Device 0 Version Timed Out", textBox_Display);
  410. }
  411. //if device 1 is open, request its version too
  412. if (device1 != null)
  413. {
  414. threadSafePrintLine("Requesting Device 1 Version", textBox_Display);
  415. try
  416. {
  417. ANT_Response version = device1.requestMessageAndResponse(ANT_ReferenceLibrary.RequestMessageID.VERSION_0x3E, 500);
  418. threadSafePrintLine("Device 1 ANT Version: " + new ASCIIEncoding().GetString(version.messageContents, 0, version.messageContents.Length - 1), textBox_Display);
  419. }
  420. catch (Exception)
  421. {
  422. threadSafePrintLine("Requesting Device 1 Version Timed Out", textBox_Display);
  423. }
  424. }
  425. }
  426. private void action_ReqChannelID()
  427. {
  428. //To request the ID we also use the requestMessageAndResponse function
  429. threadSafePrintLine("Requesting Device 0 Channel ID", textBox_Display);
  430. //On failure an exception is thrown so we watch for it
  431. try
  432. {
  433. ANT_Response IDresp = device0.requestMessageAndResponse(ANT_ReferenceLibrary.RequestMessageID.CHANNEL_ID_0x51, 500);
  434. threadSafePrintLine("Device 0 Channel ID: " + "Dev#: " + ((IDresp.messageContents[2] << 8) + IDresp.messageContents[1]) + ", DevType: " + IDresp.messageContents[3] + ", TransType: " + IDresp.messageContents[4], textBox_Display);
  435. }
  436. catch (Exception)
  437. {
  438. threadSafePrintLine("Requesting Device 0 Channel ID Timed Out", textBox_Display);
  439. }
  440. //if device 1 is open, request its version too
  441. if (device1 != null)
  442. {
  443. threadSafePrintLine("Requesting Device 1 Channel ID", textBox_Display);
  444. try
  445. {
  446. ANT_Response IDresp = device1.requestMessageAndResponse(ANT_ReferenceLibrary.RequestMessageID.CHANNEL_ID_0x51, 500);
  447. threadSafePrintLine("Device 1 Channel ID: " + "Dev#: " + ((IDresp.messageContents[2] << 8) + IDresp.messageContents[1]) + ", DevType: " + IDresp.messageContents[3] + ", TransType: " + IDresp.messageContents[4], textBox_Display);
  448. }
  449. catch (Exception)
  450. {
  451. threadSafePrintLine("Requesting Device 1 Channel ID Timed Out", textBox_Display);
  452. }
  453. }
  454. }
  455. private void action_ReqStatus()
  456. {
  457. //The managed library has a function to request status that returns a ChannelStatus object
  458. threadSafePrintLine("Requesting Device 0 Status", textBox_Display);
  459. try
  460. {
  461. ANT_ChannelStatus chStatus = device0.getChannel(0).requestStatus(500);
  462. //Not all device types return a complete device status, so some of these fields may be inaccurate
  463. threadSafePrintLine("Device 0 Channel 0 Status: " + chStatus.BasicStatus + ", Network Number: " + chStatus.networkNumber + ", Type: " + chStatus.ChannelType, textBox_Display);
  464. }
  465. catch (Exception)
  466. {
  467. threadSafePrintLine("Requesting Device 0 Status Failed", textBox_Display);
  468. }
  469. //If present, request device 1 status too
  470. if (device1 != null)
  471. {
  472. threadSafePrintLine("Requesting Device 1 Status", textBox_Display);
  473. try
  474. {
  475. ANT_ChannelStatus chStatus = device1.getChannel(0).requestStatus(500);
  476. //Not all device types return a complete device status, so some of these fields may be inaccurate
  477. threadSafePrintLine("Device 1 Channel 0 Status: " + chStatus.BasicStatus + ", Network Number: " + chStatus.networkNumber + ", Type: " + chStatus.ChannelType, textBox_Display);
  478. }
  479. catch (Exception)
  480. {
  481. threadSafePrintLine("Requesting Device 1 Status Failed", textBox_Display);
  482. }
  483. }
  484. }
  485. }
  486. }