demo_host.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  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. //////////////////////////////////////////////////////////////////////////
  9. // To use the ANT-FS functionality in the managed library, you must:
  10. // 1. Import ANT_NET.dll as a reference
  11. // 2. Reference the ANT_Managed_Library and ANT_Managed_Library.ANTFS namespaces
  12. // 3. Include the following files in the working directory of your application:
  13. // - DSI_CP310xManufacturing_3_1.dll
  14. // - DSI_SiUSBXp_3_1.dll
  15. // - ANT_WrappedLib.dll
  16. // - ANT_NET.dll
  17. // 4. You will also need to copy ANT_NET.xml into your project for
  18. // Intellisense to work properly
  19. //////////////////////////////////////////////////////////////////////////
  20. using System;
  21. using System.Text;
  22. using System.IO;
  23. using System.Collections.Generic;
  24. using System.Threading;
  25. using ANT_Managed_Library;
  26. using ANT_Managed_Library.ANTFS;
  27. namespace ANTFS_Demo
  28. {
  29. /// <summary>
  30. /// This demo shows how to configure a basic ANT-FS host
  31. /// For a more featured demo, please refer to the source code of the ANT-FS PC tools (however, the host source code is in C++)
  32. /// </summary>
  33. public class HostDemo
  34. {
  35. // ANT-FS Configuration Parameters
  36. readonly string HostFriendlyName = "ConsoleHost"; // ANT-FS Host Friendly Name
  37. readonly byte ConnectRF = (byte)ANT_Managed_Library.ANTFS.RadioFrequency.Auto; // Radio Frequency to use once a connection is established (set by host)
  38. readonly uint ClientDeviceID = 0; // ANT-FS Client Device ID (Serial Number): Wildcard to match any client ID
  39. readonly ushort DeviceNumber = 0; // Device Number (ANT Channel ID): Wildcard to match any client Device Number
  40. readonly byte SearchTimeout = 60; // How long to search for a client device, in seconds
  41. ANT_Channel channel0; // ANT channel to use
  42. ANTFS_HostChannel antfsHost; // ANT-FS host
  43. ANTFS_Directory dirFS; // ANT-FS directory
  44. byte[] clientPassKey; // Used to store pass key retrieved from the client during pairing
  45. bool demoDone = false; // Signal when the demo is done to exit
  46. int cursorIndex = 0; // Index to handle cursor display while transmitting in broadcast mode
  47. ushort currentDownloadIndex = 0; // Current index being downloaded. Start with directory (0)
  48. Timer searchTimer; // Timer to limit search time, in case there are no client devices around
  49. /// <summary>
  50. /// Setup ANT-FS host to process messages from connected USB device
  51. /// </summary>
  52. public void Start(ANT_Device antDevice)
  53. {
  54. PrintMenu();
  55. try
  56. {
  57. // Create the ANT-FS host and attach it to a channel (in this case, 0)
  58. channel0 = antDevice.getChannel(0);
  59. antfsHost = new ANTFS_HostChannel(channel0);
  60. // Setup callback to handle ANT-FS response events
  61. antfsHost.OnResponse += new Action<ANTFS_HostChannel.Response>(HandleHostResponses);
  62. // Configure the host, and begin searching
  63. ConfigureHost(antDevice);
  64. while (!demoDone)
  65. {
  66. string command = Console.ReadLine();
  67. HandleUserInput(command);
  68. Thread.Sleep(0);
  69. }
  70. }
  71. catch(ANTFS_Exception antEx) // Handle exceptions thrown by ANT Managed library
  72. {
  73. Console.WriteLine("ANT-FS Exception: " + antEx.Message);
  74. }
  75. catch (Exception ex) // Handle other exceptions
  76. {
  77. Console.WriteLine("Demo failed: " + ex.Message);
  78. }
  79. finally
  80. {
  81. Console.WriteLine("Disconnecting module...");
  82. antDevice.Dispose(); // Close down the device completely and completely shut down all communication
  83. antfsHost.Dispose(); // Release all native resources used by the host
  84. Console.WriteLine("Demo has completed successfully!");
  85. }
  86. }
  87. /// <summary>
  88. /// Configure the host search parameters, and begin the search
  89. /// </summary>
  90. /// <param name="antDevice">ANT USB device</param>
  91. public void ConfigureHost(ANT_Device antDevice)
  92. {
  93. // Configure ANT channel parameters
  94. antfsHost.SetNetworkKey(Demo.NetworkNumber, Demo.NetworkKey);
  95. antfsHost.SetChannelID(Demo.DeviceType, Demo.TransmissionType);
  96. antfsHost.SetChannelPeriod(Demo.ChannelPeriod);
  97. // Configure search parameters
  98. if (antfsHost.AddSearchDevice(ClientDeviceID, Demo.ClientManufacturerID, Demo.ClientDeviceType) == 0)
  99. throw new Exception("Error adding search device: ");
  100. if (Demo.AntfsBroadcast)
  101. {
  102. // If we want to use ANT-FS broadcast mode, and start the channel in broadcast mode,
  103. // setup callback to handle responses for channel 0 while in broadcast mode
  104. channel0.channelResponse += new dChannelResponseHandler(HandleChannelResponses);
  105. // Configure the channel as a slave, and look for messages from the master in the channel callback
  106. // This demo will automatically switch to ANT-FS mode after a few seconds
  107. if (!antDevice.setNetworkKey(Demo.NetworkNumber, Demo.NetworkKey, 500))
  108. throw new Exception("Error configuring network key");
  109. if (!channel0.assignChannel(ANT_ReferenceLibrary.ChannelType.BASE_Slave_Receive_0x00, Demo.NetworkNumber, 500))
  110. throw new Exception("Error assigning channel");
  111. if (!channel0.setChannelID(DeviceNumber, false, Demo.DeviceType, Demo.TransmissionType, 500))
  112. throw new Exception("Error configuring Channel ID");
  113. if (!channel0.setChannelFreq(Demo.SearchRF, 500))
  114. throw new Exception("Error configuring radio frequency");
  115. if (!channel0.setChannelPeriod(Demo.ChannelPeriod, 500))
  116. throw new Exception("Error configuring channel period");
  117. if (!channel0.openChannel(500))
  118. throw new Exception("Error opening channel");
  119. }
  120. else
  121. {
  122. // Start searching directly for an ANT-FS client matching the search criteria
  123. // NOTE: If not interested in the payload while in broadcast mode and intend to start a session right away,
  124. // you can specify useRequestPage = true to search for broadcast devices, and automatically request them
  125. // to switch to ANT-FS mode
  126. antfsHost.SearchForDevice(Demo.SearchRF, ConnectRF, DeviceNumber);
  127. }
  128. Console.WriteLine("Searching for devices...");
  129. // Setup a timer, so that we can cancel the search if no device is found
  130. searchTimer = new Timer(SearchExpired, null, SearchTimeout * 1000, Timeout.Infinite); // convert time to milliseconds
  131. }
  132. /// <summary>
  133. /// Handle ANT-FS response events
  134. /// </summary>
  135. public void HandleHostResponses(ANTFS_HostChannel.Response response)
  136. {
  137. Console.WriteLine(Print.AsString(response)); // Display response
  138. switch (response)
  139. {
  140. case ANTFS_HostChannel.Response.ConnectPass:
  141. // A device matching the search criteria was found
  142. // Disable the search timeout
  143. searchTimer.Change(Timeout.Infinite, Timeout.Infinite);
  144. // Obtain and display the device parameters
  145. ANTFS_SearchResults foundDevice = antfsHost.GetFoundDeviceParameters();
  146. if (foundDevice != null)
  147. Console.WriteLine(foundDevice.ToString());
  148. else
  149. Console.WriteLine("Error obtaining device parameters");
  150. break;
  151. case ANTFS_HostChannel.Response.AuthenticatePass:
  152. // The authentication request was accepted
  153. // If using Pairing authentication mode, the client will send a Passkey after accepting the request
  154. byte[] authString = antfsHost.GetAuthResponse();
  155. if (authString.Length > 0)
  156. {
  157. Console.WriteLine("Received Passkey: Stored for use in next session");
  158. clientPassKey = authString; // Store Passkey for future use
  159. }
  160. break;
  161. case ANTFS_HostChannel.Response.DownloadPass:
  162. // Download completed successfully
  163. // Retrieve downloaded data
  164. byte[] dlData = antfsHost.GetTransferData();
  165. if ((dlData.Length > 0))
  166. {
  167. if (currentDownloadIndex == 0) // Directory
  168. {
  169. // Parse downloaded directory
  170. Console.WriteLine("Received Directory");
  171. dirFS = new ANTFS_Directory(dlData);
  172. Console.WriteLine(dirFS.ToString());
  173. }
  174. else
  175. {
  176. // Store downloaded file
  177. Console.WriteLine("Downloaded file " + currentDownloadIndex + ", Download size: " + antfsHost.GetDownloadSize());
  178. if (dlData != null)
  179. {
  180. File.WriteAllBytes("rawdataout.txt", dlData);
  181. Console.WriteLine("Saved to: rawdataout.txt");
  182. }
  183. else
  184. {
  185. Console.WriteLine("No data available");
  186. }
  187. }
  188. }
  189. else
  190. {
  191. Console.WriteLine("No data available");
  192. }
  193. break;
  194. case ANTFS_HostChannel.Response.DisconnectPass:
  195. case ANTFS_HostChannel.Response.ConnectionLost:
  196. case ANTFS_HostChannel.Response.CancelDone:
  197. Console.WriteLine("Press any key to exit");
  198. demoDone = true;
  199. break;
  200. default:
  201. break;
  202. }
  203. }
  204. /// <summary>
  205. /// Handle ANT channel responses, while in broadcast mode
  206. /// </summary>
  207. /// <param name="response">ANT channel event</param>
  208. public void HandleChannelResponses(ANT_Response response)
  209. {
  210. // Make sure we are not processing responses if ANT-FS is active
  211. if (antfsHost.GetStatus() != ANTFS_HostChannel.State.Idle)
  212. return;
  213. if (response.responseID == (byte) ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E)
  214. {
  215. Console.Write("Rx: " + Demo.CursorStrings[cursorIndex++] + "\r");
  216. cursorIndex &= 3;
  217. if (response.getDataPayload()[7] >= 40) // Receive data for about 10 seconds
  218. {
  219. antfsHost.RequestSession(Demo.SearchRF, ConnectRF); // Request ANT-FS session
  220. }
  221. }
  222. }
  223. /// <summary>
  224. /// Cancel the search after the timeout has expired
  225. /// </summary>
  226. /// <param name="state">timer param</param>
  227. private void SearchExpired(Object state)
  228. {
  229. lock (this)
  230. {
  231. ANTFS_HostChannel.State currentState = antfsHost.GetStatus();
  232. if (currentState == ANTFS_HostChannel.State.Searching)
  233. {
  234. Console.WriteLine("No devices found...");
  235. antfsHost.Cancel();
  236. }
  237. }
  238. }
  239. /// <summary>
  240. /// Display user menu
  241. /// </summary>
  242. public void PrintMenu()
  243. {
  244. Console.WriteLine(Environment.NewLine);
  245. Console.WriteLine("M - Print this menu");
  246. Console.WriteLine("A - Authenticate");
  247. Console.WriteLine("D - Download");
  248. Console.WriteLine("U - Upload");
  249. Console.WriteLine("E - Erase");
  250. Console.WriteLine("X - Disconnect");
  251. Console.WriteLine("C - Cancel");
  252. Console.WriteLine("P - Print directory");
  253. Console.WriteLine("V - Request version");
  254. Console.WriteLine("S - Request status");
  255. Console.WriteLine("Q - Quit");
  256. Console.WriteLine(Environment.NewLine);
  257. }
  258. /// <summary>
  259. /// Process user input and execute requested commands
  260. /// </summary>
  261. /// <param name="command">User command</param>
  262. public void HandleUserInput(string command)
  263. {
  264. try
  265. {
  266. switch (command)
  267. {
  268. case "M":
  269. case "m":
  270. PrintMenu();
  271. break;
  272. case "A":
  273. case "a":
  274. // Send authentication request based on user selection
  275. // The library will wait for the configured timeout to receive a response to the request
  276. Console.WriteLine("Select authentication mode:");
  277. Console.WriteLine("1 - Skip authentication");
  278. Console.WriteLine("2 - Request pairing");
  279. Console.WriteLine("3 - Send passkey");
  280. string authChoice = Console.ReadLine();
  281. switch (authChoice)
  282. {
  283. case "1":
  284. antfsHost.Authenticate(AuthenticationType.None, 60000); // Passthru authentication. Timeout = 60 sec
  285. break;
  286. case "2":
  287. antfsHost.Authenticate(AuthenticationType.Pairing, HostFriendlyName, 60000); // Request pairing. Timeout = 60 sec
  288. break;
  289. case "3":
  290. if (clientPassKey != null)
  291. antfsHost.Authenticate(AuthenticationType.PassKey, clientPassKey, 60000); // Use passkey, if we have one. Timeout = 60 sec
  292. else
  293. Console.WriteLine("Try pairing first");
  294. break;
  295. default:
  296. Console.WriteLine("Invalid authentication type.");
  297. break;
  298. }
  299. break;
  300. case "D":
  301. case "d":
  302. // Send a download request based on user selection
  303. Console.WriteLine("Select the file index to download.");
  304. Console.WriteLine("Choose 0 for the directory");
  305. string downloadChoice = Console.ReadLine();
  306. currentDownloadIndex = Demo.ParseInput(downloadChoice);
  307. antfsHost.Download(currentDownloadIndex, 0, 0); // Start download from the beginning, and do not limit size
  308. break;
  309. case "U":
  310. case "u":
  311. // Send an upload request based on user selection
  312. Console.WriteLine("Select the file index to upload.");
  313. string uploadChoice = Console.ReadLine();
  314. byte[] ulData;
  315. if (File.Exists("rawdataout.txt"))
  316. ulData = File.ReadAllBytes("rawdataout.txt");
  317. else
  318. ulData = new byte[200];
  319. antfsHost.Upload(Demo.ParseInput(uploadChoice), ulData);
  320. Console.WriteLine("Uploading: {0} bytes", ulData.Length);
  321. break;
  322. case "E":
  323. case "e":
  324. // Send an erase request depending on user selection
  325. Console.WriteLine("Select the file index to erase");
  326. string eraseChoice = Console.ReadLine();
  327. antfsHost.EraseData(Demo.ParseInput(eraseChoice));
  328. break;
  329. case "X":
  330. case "x":
  331. // Disconnect from the remote device
  332. antfsHost.Disconnect();
  333. break;
  334. case "C":
  335. case "c":
  336. // Cancel pending operations
  337. antfsHost.Cancel();
  338. break;
  339. case "P":
  340. case "p":
  341. if (dirFS != null)
  342. Console.WriteLine(dirFS.ToString());
  343. else
  344. Console.WriteLine("Try requesting the directory first");
  345. break;
  346. case "V":
  347. case "v":
  348. Console.WriteLine("ANT-FS Library Version " + antfsHost.GetLibraryVersion());
  349. break;
  350. case "S":
  351. case "s":
  352. Console.WriteLine("Status: " + Print.AsString(antfsHost.GetStatus()));
  353. break;
  354. case "Q":
  355. case "q":
  356. demoDone = true;
  357. break;
  358. default:
  359. break;
  360. }
  361. }
  362. catch (ANTFS_RequestFailed_Exception antEx)
  363. {
  364. // Inform the user that the operation requested failed, and resume operation
  365. Console.WriteLine(antEx.Message);
  366. }
  367. catch (System.ArgumentException argEx)
  368. {
  369. // Inform the user about the invalid input, and resume operation
  370. Console.WriteLine(argEx.Message);
  371. }
  372. }
  373. }
  374. }