ANT_Response.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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. namespace ANT_Managed_Library
  13. {
  14. /// <summary>
  15. /// Container for all the information passed from an ANT device callback function
  16. /// </summary>
  17. public class ANT_Response
  18. {
  19. /// <summary>
  20. /// The object that created this response (ie: The corresponding ANTChannel or ANTDevice instance).
  21. /// </summary>
  22. public object sender;
  23. /// <summary>
  24. /// The channel parameter received in the message. Note: For some messages this is not applicable.
  25. /// </summary>
  26. public byte antChannel;
  27. /// <summary>
  28. /// The time the message was received.
  29. /// </summary>
  30. public DateTime timeReceived;
  31. /// <summary>
  32. /// The MessageID of the response
  33. /// </summary>
  34. public byte responseID;
  35. /// <summary>
  36. /// The raw contents of the response message
  37. /// </summary>
  38. public byte[] messageContents;
  39. internal ANT_Response(object sender, byte antChannel, DateTime timeReceived, byte IDcode, byte[] messageContents)
  40. {
  41. this.sender = sender;
  42. this.antChannel = antChannel;
  43. this.timeReceived = timeReceived;
  44. this.responseID = IDcode;
  45. this.messageContents = messageContents;
  46. }
  47. #region Accessors
  48. /// <summary>
  49. /// Returns messageContents[2] cast to an ANTEventID. Throws an exception if this is not a channel event.
  50. /// </summary>
  51. public ANT_ReferenceLibrary.ANTEventID getChannelEventCode()
  52. {
  53. if (responseID != (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40)
  54. throw new ANT_Exception("Response is not a channel event");
  55. return (ANT_ReferenceLibrary.ANTEventID)messageContents[2];
  56. }
  57. /// <summary>
  58. /// Returns messageContents[1] cast to an ANTMessageID. Throws an exception if this is not a response event.
  59. /// </summary>
  60. public ANT_ReferenceLibrary.ANTMessageID getMessageID()
  61. {
  62. if (responseID != (byte)ANT_ReferenceLibrary.ANTMessageID.RESPONSE_EVENT_0x40)
  63. throw new ANT_Exception("Response is not a response event");
  64. return (ANT_ReferenceLibrary.ANTMessageID)messageContents[1];
  65. }
  66. /// <summary>
  67. /// Returns the 8-byte data payload of an ANT message. Throws an exception if this is not a received message.
  68. /// </summary>
  69. /// <returns></returns>
  70. public byte[] getDataPayload()
  71. {
  72. if (messageContents.Length == 9
  73. && (responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E
  74. || responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.ACKNOWLEDGED_DATA_0x4F
  75. || responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.BURST_DATA_0x50
  76. ))
  77. return messageContents.Skip(1).ToArray(); //Just skip the channel byte and return the payload
  78. else
  79. return splitExtMessage(extMsgParts.DataPayload); // Extended message
  80. }
  81. /// <summary>
  82. /// Returns the burst sequence number (upper three bits of channel number). Throws exception if this is not a burst event.
  83. /// </summary>
  84. public byte getBurstSequenceNumber()
  85. {
  86. if (responseID != (byte)ANT_ReferenceLibrary.ANTMessageID.BURST_DATA_0x50
  87. && responseID != (byte)ANT_ReferenceLibrary.ANTMessageID.EXT_BURST_DATA_0x5F
  88. )
  89. throw new ANT_Exception("Response is not a burst event");
  90. else
  91. return (byte)((messageContents[0] & 0xE0) >> 5);
  92. }
  93. /// <summary>
  94. /// Returns the channel ID portion of an extended message. Throws an exception if this is not an extended message.
  95. /// </summary>
  96. public ANT_ChannelID getDeviceIDfromExt()
  97. {
  98. ANT_ChannelID extID = new ANT_ChannelID();
  99. byte[] rawID = splitExtMessage(extMsgParts.DeviceID);
  100. extID.deviceNumber = (UInt16)(rawID[0] + (rawID[1] << 8));
  101. extID.pairingBit = Convert.ToBoolean(rawID[2] & 0x80);
  102. extID.deviceTypeID = (byte)(rawID[2] & 0x7F);
  103. extID.transmissionTypeID = rawID[3];
  104. return extID;
  105. }
  106. /// <summary>
  107. /// Returns true if this is an extended message, false otherwise
  108. /// </summary>
  109. public bool isExtended()
  110. {
  111. if (messageContents.Length < 13
  112. )
  113. return false;
  114. else
  115. return true;
  116. }
  117. /// <summary>
  118. /// Splits and returns the requested part of an extended message. Throws an exception if this is not an extended message.
  119. /// </summary>
  120. /// <param name="whichPart">The desired part of the message</param>
  121. private byte[] splitExtMessage(extMsgParts whichPart)
  122. {
  123. if (!isExtended())
  124. throw new ANT_Exception("Response is not an extended message");
  125. byte[] dataPayload;
  126. byte[] deviceID;
  127. // Legacy extended message
  128. // The "extended" part of this message is the 4-byte channel ID of the device that we recieved this message from.
  129. // This event is only available on the AT3
  130. if (responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.EXT_BROADCAST_DATA_0x5D
  131. || responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.EXT_ACKNOWLEDGED_DATA_0x5E
  132. || responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.EXT_BURST_DATA_0x5F)
  133. {
  134. deviceID = messageContents.Skip(1).Take(4).ToArray(); //Skip channel byte
  135. dataPayload = messageContents.Skip(5).Take(8).ToArray(); //Skip channel byte and 4 bytes of id parameters
  136. }
  137. // "Flag" extended message. The 4-byte channel ID is included if the flag byte includes 0x80
  138. else if (responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E
  139. || responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.ACKNOWLEDGED_DATA_0x4F
  140. || responseID == (byte)ANT_ReferenceLibrary.ANTMessageID.BURST_DATA_0x50)
  141. {
  142. dataPayload = messageContents.Skip(1).Take(8).ToArray(); //Skip channel byte
  143. if ((messageContents[9] & 0x80) == 0) // Check flag byte
  144. throw new ANT_Exception("Response does not contain a channel ID");
  145. deviceID = messageContents.Skip(10).Take(4).ToArray(); //Skip channel byte, 8 bytes of data, and flag byte
  146. }
  147. else
  148. throw new ANT_Exception("Response is not an extended message");
  149. switch (whichPart)
  150. {
  151. case extMsgParts.DataPayload:
  152. return dataPayload;
  153. case extMsgParts.DeviceID:
  154. return deviceID;
  155. default:
  156. throw new ANT_Exception("Invalid extMsgPart");
  157. }
  158. }
  159. //This enum makes the code more readable when calling splitExtMessage()
  160. private enum extMsgParts
  161. {
  162. DataPayload,
  163. DeviceID
  164. }
  165. #endregion
  166. }
  167. }