PowerMeterDisplay.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using ANT_Managed_Library;
  5. using System;
  6. /*
  7. Frequencies such as 4.06 Hz (ANT+ Heart
  8. Rate) and 4.005 Hz (ANT+ Bike Power) will
  9. periodically “drift” into each other, or into
  10. other channel periods that may be present
  11. in the vicinity. During this overlap, channel
  12. collisions may occur as the radio can only
  13. service channel at a time.
  14. */
  15. public class PowerMeterDisplay : MonoBehaviour {
  16. public bool autoStartScan = true; //start scan on play
  17. public bool connected = false; //will be set to true once connected
  18. //windows and mac settings
  19. public bool autoConnectToFirstSensorFound = true; //for windows and mac, either connect to the first sensor found or let you pick a sensor manually in the scanResult list with your own UI and call ConnectToDevice(AntDevice device)
  20. public List<AntDevice> scanResult;
  21. //android settings
  22. public bool useAndroidUI = true; //will open the unified ant+ UI on the android app if set to true, otherwise will connect to the first found device
  23. public bool skipPreferredSearch = true; //- True = Don't automatically connect to user's preferred device, but always go to search for other devices.
  24. //the sensor values we receive fron the onReceiveData event
  25. public int instantaneousPower; // the instantaneous power in watt
  26. public int instantaneousCadence; // crank cadence in RPM if available ( 255 indicates invalid)
  27. private AntChannel backgroundScanChannel;
  28. private AntChannel deviceChannel;
  29. public int deviceID = 0; //set this to connect to a specific device ID
  30. private byte[] pageToSend;
  31. void Start() {
  32. if (autoStartScan)
  33. StartScan();
  34. }
  35. //Start a background Scan to find the device
  36. public void StartScan() {
  37. Debug.Log("Looking for ANT + power meter sensor");
  38. #if UNITY_ANDROID && !UNITY_EDITOR
  39. //java: connect_power(String gameobjectName, boolean useAndroidUI, boolean skipPreferredSearch, int deviceID)
  40. AndroidJNI.AttachCurrentThread();
  41. using (AndroidJavaClass javaClass = new AndroidJavaClass("com.ant.plugin.Ant_Connector")) {
  42. using (AndroidJavaObject activity = javaClass.GetStatic<AndroidJavaObject>("mContext")) {
  43. activity.Call("connect_power", this.gameObject.name, useAndroidUI,skipPreferredSearch,deviceID);
  44. }
  45. }
  46. #else
  47. AntManager.Instance.Init();
  48. scanResult = new List<AntDevice>();
  49. backgroundScanChannel = AntManager.Instance.OpenBackgroundScanChannel(0);
  50. backgroundScanChannel.onReceiveData += ReceivedBackgroundScanData;
  51. #endif
  52. }
  53. //Android function
  54. void ANTPLUG_ConnectEvent(string resultCode) {
  55. switch (resultCode) {
  56. case "SUCCESS":
  57. connected = true;
  58. break;
  59. case "CHANNEL_NOT_AVAILABLE":
  60. //Channel Not Available
  61. break;
  62. case "ADAPTER_NOT_DETECTED":
  63. //ANT Adapter Not Available. Built-in ANT hardware or external adapter required.
  64. Debug.Log("ANT Adapter Not Available. Built-in ANT hardware or external adapter required.");
  65. break;
  66. case "BAD_PARAMS":
  67. //Bad request parameters.
  68. break;
  69. case "OTHER_FAILUR":
  70. //RequestAccess failed. See logcat for details.
  71. break;
  72. case "DEPENDENCY_NOT_INSTALLED":
  73. //You need to install the ANT+ Plugins service or you may need to update your existing version if you already have it.
  74. case "USER_CANCELLED":
  75. //USER_CANCELLED
  76. break;
  77. case "UNRECOGNIZED":
  78. //UNRECOGNIZED. PluginLib Upgrade Required?",
  79. break;
  80. default:
  81. //UNRECOGNIZED
  82. break;
  83. }
  84. }
  85. void ANTPLUG_StateChange(string newDeviceState) {
  86. switch (newDeviceState) {
  87. case "DEAD":
  88. connected = false;
  89. break;
  90. case "CLOSED":
  91. break;
  92. case "SEARCHING":
  93. //searching
  94. break;
  95. case "TRACKING":
  96. //tracking
  97. break;
  98. case "PROCESSING_REQUEST":
  99. break;
  100. default:
  101. //UNRECOGNIZED
  102. break;
  103. }
  104. }
  105. void ANTPLUG_Receive_calculatedPower(string s) {
  106. instantaneousPower = (int)float.Parse(s);
  107. }
  108. void ANTPLUG_Receive_calculatedCadence(string s) {
  109. instantaneousCadence = (int)float.Parse(s);
  110. }
  111. //Windows and mac
  112. //If the device is found
  113. void ReceivedBackgroundScanData(Byte[] data) {
  114. byte deviceType = (data[12]); // extended info Device Type byte
  115. switch (deviceType) {
  116. case AntplusDeviceType.BikePower: {
  117. int deviceNumber = (data[10]) | data[11] << 8;
  118. byte transType = data[13];
  119. foreach (AntDevice d in scanResult) {
  120. if (d.deviceNumber == deviceNumber && d.transType == transType) //device already found
  121. return;
  122. }
  123. Debug.Log("Powermeter sensor found " + deviceNumber);
  124. AntDevice foundDevice = new AntDevice();
  125. foundDevice.deviceType = deviceType;
  126. foundDevice.deviceNumber = deviceNumber;
  127. foundDevice.transType = transType;
  128. foundDevice.period = 8182;
  129. foundDevice.radiofreq = 57;
  130. foundDevice.name = "Powermeter(" + foundDevice.deviceNumber + ")";
  131. scanResult.Add(foundDevice);
  132. if (autoConnectToFirstSensorFound) {
  133. ConnectToDevice(foundDevice);
  134. }
  135. break;
  136. }
  137. default: {
  138. break;
  139. }
  140. }
  141. }
  142. void ConnectToDevice(AntDevice device) {
  143. AntManager.Instance.CloseBackgroundScanChannel();
  144. byte channelID = AntManager.Instance.GetFreeChannelID();
  145. deviceChannel = AntManager.Instance.OpenChannel(ANT_ReferenceLibrary.ChannelType.BASE_Slave_Receive_0x00, channelID, (ushort)device.deviceNumber, device.deviceType, device.transType, (byte)device.radiofreq, (ushort)device.period, false);
  146. connected = true;
  147. deviceChannel.onReceiveData += Data;
  148. deviceChannel.onChannelResponse += ChannelResponse;
  149. deviceChannel.hideRXFAIL = true;
  150. }
  151. int update_event_count = 0;
  152. int sameEventCounter = 0;
  153. //Deal with the received Data
  154. public void Data(Byte[] data) {
  155. if (data[0] == 0x10) {
  156. if (data[1] == update_event_count)
  157. sameEventCounter++;
  158. else
  159. sameEventCounter = 0;
  160. update_event_count = data[1];
  161. if (sameEventCounter > 3) {
  162. instantaneousPower = 0;
  163. instantaneousCadence = 0;
  164. } else {
  165. instantaneousPower = (data[6]) | data[7] << 8;
  166. instantaneousCadence = data[3];
  167. }
  168. }
  169. }
  170. public void Calibrate() {
  171. Debug.Log("Sending : Manual Zero Calibration request");
  172. pageToSend = new byte[8] { 0x01, 0xAA, 0x0FF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
  173. deviceChannel.sendAcknowledgedData(pageToSend);
  174. }
  175. void ChannelResponse(ANT_Response response) {
  176. if (response.getChannelEventCode() == ANT_ReferenceLibrary.ANTEventID.EVENT_TRANSFER_TX_FAILED_0x06) {
  177. deviceChannel.sendAcknowledgedData(pageToSend); //send the page again if the transfer failed
  178. }
  179. }
  180. }