demo_client.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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.ANTFS;
  26. using ANT_Managed_Library;
  27. namespace ANTFS_Demo
  28. {
  29. /// <summary>
  30. /// This demo shows how to configure a basic ANT-FS client
  31. /// For a more featured demo, please refer to the source code of the ANT-FS PC tools
  32. /// </summary>
  33. class ClientDemo
  34. {
  35. // ANT-FS Client Configuration Parameters
  36. readonly AuthenticationType ClientAuthenticationType = AuthenticationType.None; // Allow pairing, passkey and passthru
  37. readonly byte BeaconTimeout = 60; // The client will drop back to link state if no messages from the host are received within this timeout
  38. readonly byte PairingTimeout = 5; // Time to wait for the user to provide a response to a pairing request. Use a short value here since demo accepts pairing automatically
  39. readonly bool DataAvailable = true; // Indicate in beacon there is data available for download
  40. readonly bool PairingEnabled = true; // Indicate in beacon that pairing is enabled
  41. readonly bool UploadEnabled = false; // Indicate in beacon that pairing is not supported
  42. readonly byte[] PassKey = { 1, 2, 3, 1, 2, 3, 1, 2 }; // Authentication passkey
  43. readonly string ClientFriendlyName = "ConsoleClient"; // ANT-FS Client friendly name
  44. readonly uint TestFileSize = 512; // Size of file listed in the directory. This demo does not
  45. // access the file system; it just creates a file of the configured size
  46. ANT_Channel channel0; // ANT channel to use
  47. ANTFS_ClientChannel antfsClient; // ANT-FS client
  48. ANTFS_Directory dirFS; // ANT-FS directory
  49. bool demoDone = false; // Flag to allow demo to exit
  50. byte[] txBuffer = {0,0,0,0,0,0,0,0}; // Tx buffer to use while in broadcast mode
  51. int cursorIndex = 0; // index to handle cursor display while transmitting in broadcast mode
  52. /// <summary>
  53. /// Setup ANT-FS client to process messages from connected device
  54. /// </summary>
  55. public void Start(ANT_Device antDevice)
  56. {
  57. PrintMenu();
  58. try
  59. {
  60. // Create the ANT-FS client and attach it to a channel (in this case, 0)
  61. channel0 = antDevice.getChannel(0);
  62. antfsClient = new ANTFS_ClientChannel(channel0);
  63. // Setup callback to handle ANT-FS response events
  64. antfsClient.OnResponse += new Action<ANTFS_ClientChannel.Response>(HandleClientResponses);
  65. // Configure the client, and begin beaconing
  66. ConfigureClient(antDevice);
  67. while (!demoDone)
  68. {
  69. string command = Console.ReadLine();
  70. HandleUserInput(command);
  71. Thread.Sleep(0);
  72. }
  73. }
  74. catch(ANTFS_Exception antEx) // Handle exceptions thrown by ANT Managed library
  75. {
  76. Console.WriteLine("ANT-FS Exception: " + antEx.Message);
  77. }
  78. catch (Exception ex) // Handle other exceptions
  79. {
  80. Console.WriteLine("Demo failed: " + ex.Message);
  81. Console.ReadLine();
  82. }
  83. finally
  84. {
  85. Console.WriteLine("Disconnecting module...");
  86. antDevice.Dispose(); // Close down the device completely and completely shut down all communication
  87. antfsClient.Dispose(); // Release all native resources used by the client
  88. Console.WriteLine("Demo has completed successfully!");
  89. }
  90. }
  91. /// <summary>
  92. /// Configure the client beacon parameters, and start transmitting/beaconing
  93. /// </summary>
  94. /// <param name="antDevice">ANT USB device</param>
  95. public void ConfigureClient(ANT_Device antDevice)
  96. {
  97. // Configure ANT Channel parameters
  98. antfsClient.SetClientNetworkKey(0, Demo.NetworkKey);
  99. antfsClient.SetChannelID(Demo.DeviceType, Demo.TransmissionType);
  100. antfsClient.SetChannelPeriod(Demo.ChannelPeriod);
  101. // Setup client configuration parameters.
  102. // ANTFS_ClientParameters is a struct, so make sure to initialize ALL parameters
  103. ANTFS_ClientParameters clientConfig = new ANTFS_ClientParameters();
  104. clientConfig.BeaconDeviceType = Demo.ClientDeviceType;
  105. clientConfig.BeaconManufacturerID = Demo.ClientManufacturerID;
  106. clientConfig.BeaconRadioFrequency = Demo.SearchRF;
  107. clientConfig.LinkPeriod = Demo.LinkPeriod;
  108. clientConfig.AuthenticationType = ClientAuthenticationType;
  109. clientConfig.IsDataAvailable = DataAvailable;
  110. clientConfig.IsPairingEnabled = PairingEnabled;
  111. clientConfig.IsUploadEnabled = UploadEnabled;
  112. clientConfig.BeaconTimeout = BeaconTimeout;
  113. clientConfig.PairingTimeout = PairingTimeout;
  114. clientConfig.SerialNumber = antDevice.getSerialNumber(); // Use the serial number of the USB stick to identify the client
  115. // Apply configuration
  116. antfsClient.Configure(clientConfig);
  117. // Configure friendly name and passkey (optional)
  118. antfsClient.SetFriendlyName(ClientFriendlyName);
  119. antfsClient.SetPassKey(PassKey);
  120. // Create directory, an add a single entry, of the configured size
  121. dirFS = new ANTFS_Directory();
  122. ANTFS_Directory.Entry fileEntry;
  123. fileEntry.FileIndex = 1;
  124. fileEntry.FileSize = TestFileSize;
  125. fileEntry.FileDataType = 1;
  126. fileEntry.FileNumber = 1;
  127. fileEntry.FileSubType = 0;
  128. fileEntry.GeneralFlags = (byte) (ANTFS_Directory.GeneralFlags.Read | ANTFS_Directory.GeneralFlags.Write | ANTFS_Directory.GeneralFlags.Erase);
  129. fileEntry.SpecificFlags = 0;
  130. fileEntry.TimeStamp = 0; // TODO: Encode the timestamp properly
  131. dirFS.AddEntry(fileEntry);
  132. if (Demo.AntfsBroadcast)
  133. {
  134. // If we want to use ANT-FS broadcast mode, and start the channel in broadcast mode,
  135. // setup callback to handle responses for channel 0 while in broadcast mode
  136. channel0.channelResponse += new dChannelResponseHandler(HandleChannelResponses);
  137. // Configure the channel as a master, and look for the request message in the channel callback
  138. // to switch to ANT-FS mode
  139. if (!antDevice.setNetworkKey(Demo.NetworkNumber, Demo.NetworkKey, 500))
  140. throw new Exception("Error configuring network key");
  141. if (!channel0.assignChannel(ANT_ReferenceLibrary.ChannelType.BASE_Master_Transmit_0x10, Demo.NetworkNumber, 500))
  142. throw new Exception("Error assigning channel");
  143. if (!channel0.setChannelID((ushort)clientConfig.SerialNumber, false, Demo.DeviceType, Demo.TransmissionType, 500))
  144. throw new Exception("Error configuring Channel ID");
  145. if (!channel0.setChannelFreq(Demo.SearchRF, 500))
  146. throw new Exception("Error configuring radio frequency");
  147. if (!channel0.setChannelPeriod(Demo.ChannelPeriod, 500))
  148. throw new Exception("Error configuring channel period");
  149. if (!channel0.openChannel(500))
  150. throw new Exception("Error opening channel");
  151. }
  152. else
  153. {
  154. // If we want to start in ANT-FS mode, just open the beacon
  155. antfsClient.OpenBeacon();
  156. }
  157. }
  158. /// <summary>
  159. /// Create a test file, of the specified size
  160. /// </summary>
  161. /// <param name="fileSize">File size, in bytes</param>
  162. /// <returns></returns>
  163. public byte[] ReadFile(uint fileSize)
  164. {
  165. byte[] testFile = new byte[fileSize];
  166. for (uint i = 0; i < fileSize; i++)
  167. testFile[i] = (byte)i;
  168. return testFile;
  169. }
  170. /// <summary>
  171. /// Handle ANT-FS response events
  172. /// </summary>
  173. public void HandleClientResponses(ANTFS_ClientChannel.Response response)
  174. {
  175. Console.WriteLine(Print.AsString(response)); // Display response
  176. switch (response)
  177. {
  178. case ANTFS_ClientChannel.Response.ConnectionLost:
  179. case ANTFS_ClientChannel.Response.DisconnectPass:
  180. // Close the channel
  181. if (antfsClient.GetDisconnectParameters().CommandType == (byte)DisconnectType.Broadcast)
  182. {
  183. channel0.closeChannel();
  184. }
  185. else
  186. {
  187. antfsClient.CloseBeacon();
  188. }
  189. break;
  190. case ANTFS_ClientChannel.Response.BeaconClosed:
  191. demoDone = true;
  192. Console.WriteLine("Press enter to exit");
  193. break;
  194. case ANTFS_ClientChannel.Response.PairingRequest:
  195. Console.WriteLine("Pairing request from " + antfsClient.GetHostName());
  196. antfsClient.SendPairingResponse(true);
  197. break;
  198. case ANTFS_ClientChannel.Response.DownloadRequest:
  199. try
  200. {
  201. ushort index = antfsClient.GetRequestedFileIndex();
  202. if(index == 0)
  203. antfsClient.SendDownloadResponse(DownloadResponse.Ok, index, dirFS.ToByteArray());
  204. else
  205. antfsClient.SendDownloadResponse(DownloadResponse.Ok, index, ReadFile(dirFS.GetFileSize(index)));
  206. }
  207. catch(ANTFS_Exception)
  208. {
  209. antfsClient.SendDownloadResponse(DownloadResponse.InvalidIndex, 0, null);
  210. }
  211. break;
  212. default:
  213. break;
  214. }
  215. }
  216. /// <summary>
  217. /// Handle channel responses, while in broadcast mode
  218. /// </summary>
  219. /// <param name="response">ANT channel events</param>
  220. public void HandleChannelResponses(ANT_Response response)
  221. {
  222. // Make sure we are not processing responses if ANT-FS is active
  223. if(antfsClient.GetStatus() != ANTFS_ClientChannel.State.Idle)
  224. return;
  225. if ((response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40))
  226. {
  227. if(response.getChannelEventCode() == ANT_ReferenceLibrary.ANTEventID.EVENT_TX_0x03)
  228. {
  229. channel0.sendBroadcastData(txBuffer);
  230. txBuffer[7]++;
  231. Console.Write("Tx: " + Demo.CursorStrings[cursorIndex++] + "\r");
  232. cursorIndex &= 3;
  233. }
  234. else if(response.getChannelEventCode() == ANT_ReferenceLibrary.ANTEventID.EVENT_CHANNEL_CLOSED_0x07)
  235. {
  236. Console.WriteLine("Channel Closed");
  237. Console.WriteLine("Unassigning Channel...");
  238. if (channel0.unassignChannel(500))
  239. {
  240. Console.WriteLine("Unassigned Channel");
  241. Console.WriteLine("Press enter to exit");
  242. demoDone = true;
  243. }
  244. }
  245. }
  246. else if (response.responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.ACKNOWLEDGED_DATA_0x4F)
  247. {
  248. // Look for request page
  249. if (response.messageContents[1] == 0x46)
  250. {
  251. if (response.messageContents[6] == 0 &&
  252. response.messageContents[7] == 0x43 &&
  253. response.messageContents[8] == 0x02)
  254. Console.WriteLine("Remote device requesting ANT-FS session");
  255. antfsClient.OpenBeacon();
  256. }
  257. }
  258. }
  259. /// <summary>
  260. /// Display user menu
  261. /// </summary>
  262. public void PrintMenu()
  263. {
  264. Console.WriteLine(Environment.NewLine);
  265. Console.WriteLine("M - Print this menu");
  266. Console.WriteLine("V - Request version");
  267. Console.WriteLine("S - Request status");
  268. Console.WriteLine("Q - Quit");
  269. Console.WriteLine(Environment.NewLine);
  270. }
  271. /// <summary>
  272. /// Process user input and execute requested commands
  273. /// </summary>
  274. /// <param name="command">User command</param>
  275. public void HandleUserInput(string command)
  276. {
  277. try
  278. {
  279. switch (command)
  280. {
  281. case "M":
  282. case "m":
  283. PrintMenu();
  284. break;
  285. case "V":
  286. case "v":
  287. Console.WriteLine("ANT-FS Library Version " + ANTFS_ClientChannel.GetLibraryVersion());
  288. break;
  289. case "S":
  290. case "s":
  291. Console.WriteLine("Status: " + Print.AsString(antfsClient.GetStatus()));
  292. break;
  293. case "Q":
  294. case "q":
  295. demoDone = true;
  296. break;
  297. default:
  298. break;
  299. }
  300. }
  301. catch (ANTFS_RequestFailed_Exception antEx)
  302. {
  303. // Inform the user that the operation requested failed, and resume operation
  304. Console.WriteLine(antEx.Message);
  305. }
  306. }
  307. }
  308. }