BluetoothDeviceScript.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class BluetoothDeviceScript : MonoBehaviour
  5. {
  6. public List<string> DiscoveredDeviceList;
  7. public Action InitializedAction;
  8. public Action DeinitializedAction;
  9. public Action<string> ErrorAction;
  10. public Action<string> ServiceAddedAction;
  11. public Action StartedAdvertisingAction;
  12. public Action StoppedAdvertisingAction;
  13. public Action<string, string> DiscoveredPeripheralAction;
  14. public Action<string, string, int, byte[]> DiscoveredPeripheralWithAdvertisingInfoAction;
  15. public Action<BluetoothLEHardwareInterface.iBeaconData> DiscoveredBeaconAction;
  16. public Action<string, string> RetrievedConnectedPeripheralAction;
  17. public Action<string, byte[]> PeripheralReceivedWriteDataAction;
  18. public Action<string> ConnectedPeripheralAction;
  19. public Action<string> ConnectedDisconnectPeripheralAction;
  20. public Action<string> DisconnectedPeripheralAction;
  21. public Action<string, string> DiscoveredServiceAction;
  22. public Action<string, string, string> DiscoveredCharacteristicAction;
  23. public Action<string> DidWriteCharacteristicAction;
  24. public Dictionary<string, Dictionary<string, Action<string>>> DidUpdateNotificationStateForCharacteristicAction;
  25. public Dictionary<string, Dictionary<string, Action<string, string>>> DidUpdateNotificationStateForCharacteristicWithDeviceAddressAction;
  26. public Dictionary<string, Dictionary<string, Action<string, byte[]>>> DidUpdateCharacteristicValueAction;
  27. public Dictionary<string, Dictionary<string, Action<string, string, byte[]>>> DidUpdateCharacteristicValueWithDeviceAddressAction;
  28. // Use this for initialization
  29. void Start ()
  30. {
  31. DiscoveredDeviceList = new List<string> ();
  32. DidUpdateNotificationStateForCharacteristicAction = new Dictionary<string, Dictionary<string, Action<string>>> ();
  33. DidUpdateNotificationStateForCharacteristicWithDeviceAddressAction = new Dictionary<string, Dictionary<string, Action<string, string>>> ();
  34. DidUpdateCharacteristicValueAction = new Dictionary<string, Dictionary<string, Action<string, byte[]>>> ();
  35. DidUpdateCharacteristicValueWithDeviceAddressAction = new Dictionary<string, Dictionary<string, Action<string, string, byte[]>>> ();
  36. }
  37. // Update is called once per frame
  38. void Update ()
  39. {
  40. }
  41. const string deviceInitializedString = "Initialized";
  42. const string deviceDeInitializedString = "DeInitialized";
  43. const string deviceErrorString = "Error";
  44. const string deviceServiceAdded = "ServiceAdded";
  45. const string deviceStartedAdvertising = "StartedAdvertising";
  46. const string deviceStoppedAdvertising = "StoppedAdvertising";
  47. const string deviceDiscoveredPeripheral = "DiscoveredPeripheral";
  48. const string deviceDiscoveredBeacon = "DiscoveredBeacon";
  49. const string deviceRetrievedConnectedPeripheral = "RetrievedConnectedPeripheral";
  50. const string devicePeripheralReceivedWriteData = "PeripheralReceivedWriteData";
  51. const string deviceConnectedPeripheral = "ConnectedPeripheral";
  52. const string deviceDisconnectedPeripheral = "DisconnectedPeripheral";
  53. const string deviceDiscoveredService = "DiscoveredService";
  54. const string deviceDiscoveredCharacteristic = "DiscoveredCharacteristic";
  55. const string deviceDidWriteCharacteristic = "DidWriteCharacteristic";
  56. const string deviceDidUpdateNotificationStateForCharacteristic = "DidUpdateNotificationStateForCharacteristic";
  57. const string deviceDidUpdateValueForCharacteristic = "DidUpdateValueForCharacteristic";
  58. const string deviceLog = "Log";
  59. public void OnBluetoothMessage (string message)
  60. {
  61. if (message != null)
  62. {
  63. char[] delim = new char[] { '~' };
  64. string[] parts = message.Split (delim);
  65. for (int i = 0; i < parts.Length; ++i)
  66. BluetoothLEHardwareInterface.Log (string.Format ("Part: {0} - {1}", i, parts[i]));
  67. if (message.Length >= deviceInitializedString.Length && message.Substring (0, deviceInitializedString.Length) == deviceInitializedString)
  68. {
  69. if (InitializedAction != null)
  70. InitializedAction ();
  71. }
  72. else if (message.Length >= deviceLog.Length && message.Substring (0, deviceLog.Length) == deviceLog)
  73. {
  74. Debug.Log (parts[1]);
  75. }
  76. else if (message.Length >= deviceDeInitializedString.Length && message.Substring (0, deviceDeInitializedString.Length) == deviceDeInitializedString)
  77. {
  78. BluetoothLEHardwareInterface.FinishDeInitialize ();
  79. if (DeinitializedAction != null)
  80. DeinitializedAction ();
  81. }
  82. else if (message.Length >= deviceErrorString.Length && message.Substring (0, deviceErrorString.Length) == deviceErrorString)
  83. {
  84. string error = "";
  85. if (parts.Length >= 2)
  86. error = parts[1];
  87. if (ErrorAction != null)
  88. ErrorAction (error);
  89. }
  90. else if (message.Length >= deviceServiceAdded.Length && message.Substring (0, deviceServiceAdded.Length) == deviceServiceAdded)
  91. {
  92. if (parts.Length >= 2)
  93. {
  94. if (ServiceAddedAction != null)
  95. ServiceAddedAction (parts[1]);
  96. }
  97. }
  98. else if (message.Length >= deviceStartedAdvertising.Length && message.Substring (0, deviceStartedAdvertising.Length) == deviceStartedAdvertising)
  99. {
  100. BluetoothLEHardwareInterface.Log ("Started Advertising");
  101. if (StartedAdvertisingAction != null)
  102. StartedAdvertisingAction ();
  103. }
  104. else if (message.Length >= deviceStoppedAdvertising.Length && message.Substring (0, deviceStoppedAdvertising.Length) == deviceStoppedAdvertising)
  105. {
  106. BluetoothLEHardwareInterface.Log ("Stopped Advertising");
  107. if (StoppedAdvertisingAction != null)
  108. StoppedAdvertisingAction ();
  109. }
  110. else if (message.Length >= deviceDiscoveredPeripheral.Length && message.Substring (0, deviceDiscoveredPeripheral.Length) == deviceDiscoveredPeripheral)
  111. {
  112. if (parts.Length >= 3)
  113. {
  114. // the first callback will only get called the first time this device is seen
  115. // this is because it gets added to the a list in the DiscoveredDeviceList
  116. // after that only the second callback will get called and only if there is
  117. // advertising data available
  118. if (!DiscoveredDeviceList.Contains (parts[1]))
  119. {
  120. DiscoveredDeviceList.Add (parts[1]);
  121. if (DiscoveredPeripheralAction != null)
  122. DiscoveredPeripheralAction (parts[1], parts[2]);
  123. }
  124. if (parts.Length >= 5 && DiscoveredPeripheralWithAdvertisingInfoAction != null)
  125. {
  126. // get the rssi from the 4th value
  127. int rssi = 0;
  128. if (!int.TryParse (parts[3], out rssi))
  129. rssi = 0;
  130. // parse the base 64 encoded data that is the 5th value
  131. byte[] bytes = System.Convert.FromBase64String (parts[4]);
  132. DiscoveredPeripheralWithAdvertisingInfoAction (parts[1], parts[2], rssi, bytes);
  133. }
  134. }
  135. }
  136. else if (message.Length >= deviceDiscoveredBeacon.Length && message.Substring (0, deviceDiscoveredBeacon.Length) == deviceDiscoveredBeacon)
  137. {
  138. if (parts.Length >= 7)
  139. {
  140. var iBeaconData = new BluetoothLEHardwareInterface.iBeaconData ();
  141. iBeaconData.UUID = parts[1];
  142. if (!int.TryParse (parts[2], out iBeaconData.Major))
  143. iBeaconData.Major = 0;
  144. if (!int.TryParse (parts[3], out iBeaconData.Minor))
  145. iBeaconData.Minor = 0;
  146. if (!int.TryParse (parts[4], out iBeaconData.RSSI))
  147. iBeaconData.RSSI = 0;
  148. if (!int.TryParse (parts[5], out iBeaconData.AndroidSignalPower))
  149. iBeaconData.AndroidSignalPower = 0;
  150. int iOSProximity = 0;
  151. if (!int.TryParse (parts[6], out iOSProximity))
  152. iOSProximity = 0;
  153. iBeaconData.iOSProximity = (BluetoothLEHardwareInterface.iOSProximity)iOSProximity;
  154. if (DiscoveredBeaconAction != null)
  155. DiscoveredBeaconAction (iBeaconData);
  156. }
  157. }
  158. else if (message.Length >= deviceRetrievedConnectedPeripheral.Length && message.Substring (0, deviceRetrievedConnectedPeripheral.Length) == deviceRetrievedConnectedPeripheral)
  159. {
  160. if (parts.Length >= 3)
  161. {
  162. DiscoveredDeviceList.Add (parts[1]);
  163. if (RetrievedConnectedPeripheralAction != null)
  164. RetrievedConnectedPeripheralAction (parts[1], parts[2]);
  165. }
  166. }
  167. else if (message.Length >= devicePeripheralReceivedWriteData.Length && message.Substring (0, devicePeripheralReceivedWriteData.Length) == devicePeripheralReceivedWriteData)
  168. {
  169. if (parts.Length >= 3)
  170. OnPeripheralData (parts[1], parts[2]);
  171. }
  172. else if (message.Length >= deviceConnectedPeripheral.Length && message.Substring (0, deviceConnectedPeripheral.Length) == deviceConnectedPeripheral)
  173. {
  174. if (parts.Length >= 2 && ConnectedPeripheralAction != null)
  175. ConnectedPeripheralAction (parts[1]);
  176. }
  177. else if (message.Length >= deviceDisconnectedPeripheral.Length && message.Substring (0, deviceDisconnectedPeripheral.Length) == deviceDisconnectedPeripheral)
  178. {
  179. if (parts.Length >= 2)
  180. {
  181. if (ConnectedDisconnectPeripheralAction != null)
  182. ConnectedDisconnectPeripheralAction (parts[1]);
  183. if (DisconnectedPeripheralAction != null)
  184. DisconnectedPeripheralAction (parts[1]);
  185. }
  186. }
  187. else if (message.Length >= deviceDiscoveredService.Length && message.Substring (0, deviceDiscoveredService.Length) == deviceDiscoveredService)
  188. {
  189. if (parts.Length >= 3 && DiscoveredServiceAction != null)
  190. DiscoveredServiceAction (parts[1], parts[2]);
  191. }
  192. else if (message.Length >= deviceDiscoveredCharacteristic.Length && message.Substring (0, deviceDiscoveredCharacteristic.Length) == deviceDiscoveredCharacteristic)
  193. {
  194. if (parts.Length >= 4 && DiscoveredCharacteristicAction != null)
  195. DiscoveredCharacteristicAction (parts[1], parts[2], parts[3]);
  196. }
  197. else if (message.Length >= deviceDidWriteCharacteristic.Length && message.Substring (0, deviceDidWriteCharacteristic.Length) == deviceDidWriteCharacteristic)
  198. {
  199. if (parts.Length >= 2 && DidWriteCharacteristicAction != null)
  200. DidWriteCharacteristicAction (parts[1]);
  201. }
  202. else if (message.Length >= deviceDidUpdateNotificationStateForCharacteristic.Length && message.Substring (0, deviceDidUpdateNotificationStateForCharacteristic.Length) == deviceDidUpdateNotificationStateForCharacteristic)
  203. {
  204. if (parts.Length >= 3)
  205. {
  206. if (DidUpdateNotificationStateForCharacteristicAction != null && DidUpdateNotificationStateForCharacteristicAction.ContainsKey (parts[1]))
  207. {
  208. var characteristicAction = DidUpdateNotificationStateForCharacteristicAction[parts[1]];
  209. if (characteristicAction != null && characteristicAction.ContainsKey (parts[2]))
  210. {
  211. var action = characteristicAction[parts[2]];
  212. if (action != null)
  213. action (parts[2]);
  214. }
  215. }
  216. if (DidUpdateNotificationStateForCharacteristicWithDeviceAddressAction != null && DidUpdateNotificationStateForCharacteristicWithDeviceAddressAction.ContainsKey (parts[1]))
  217. {
  218. var characteristicAction = DidUpdateNotificationStateForCharacteristicWithDeviceAddressAction[parts[1]];
  219. if (characteristicAction != null && characteristicAction.ContainsKey (parts[2]))
  220. {
  221. var action = characteristicAction[parts[2]];
  222. if (action != null)
  223. action (parts[1], parts[2]);
  224. }
  225. }
  226. }
  227. }
  228. else if (message.Length >= deviceDidUpdateValueForCharacteristic.Length && message.Substring (0, deviceDidUpdateValueForCharacteristic.Length) == deviceDidUpdateValueForCharacteristic)
  229. {
  230. if (parts.Length >= 4)
  231. OnBluetoothData (parts[1], parts[2], parts[3]);
  232. }
  233. }
  234. }
  235. public void OnBluetoothData (string base64Data)
  236. {
  237. OnBluetoothData ("", "", base64Data);
  238. }
  239. public void OnBluetoothData (string deviceAddress, string characteristic, string base64Data)
  240. {
  241. if (base64Data != null)
  242. {
  243. byte[] bytes = System.Convert.FromBase64String (base64Data);
  244. if (bytes.Length > 0)
  245. {
  246. deviceAddress = deviceAddress.ToUpper ();
  247. characteristic = characteristic.ToUpper ();
  248. BluetoothLEHardwareInterface.Log ("Device: " + deviceAddress + " Characteristic Received: " + characteristic);
  249. string byteString = "";
  250. foreach (byte b in bytes)
  251. byteString += string.Format ("{0:X2}", b);
  252. BluetoothLEHardwareInterface.Log (byteString);
  253. if (DidUpdateCharacteristicValueAction != null && DidUpdateCharacteristicValueAction.ContainsKey (deviceAddress))
  254. {
  255. var characteristicAction = DidUpdateCharacteristicValueAction[deviceAddress];
  256. #if UNITY_ANDROID
  257. characteristic = characteristic.ToLower ();
  258. #endif
  259. if (characteristicAction != null && characteristicAction.ContainsKey (characteristic))
  260. {
  261. var action = characteristicAction[characteristic];
  262. if (action != null)
  263. action (characteristic, bytes);
  264. }
  265. }
  266. if (DidUpdateCharacteristicValueWithDeviceAddressAction != null && DidUpdateCharacteristicValueWithDeviceAddressAction.ContainsKey (deviceAddress))
  267. {
  268. var characteristicAction = DidUpdateCharacteristicValueWithDeviceAddressAction[deviceAddress];
  269. #if UNITY_ANDROID
  270. characteristic = characteristic.ToLower ();
  271. #endif
  272. if (characteristicAction != null && characteristicAction.ContainsKey (characteristic))
  273. {
  274. var action = characteristicAction[characteristic];
  275. if (action != null)
  276. action (deviceAddress, characteristic, bytes);
  277. }
  278. }
  279. }
  280. }
  281. }
  282. public void OnPeripheralData (string characteristic, string base64Data)
  283. {
  284. if (base64Data != null)
  285. {
  286. byte[] bytes = System.Convert.FromBase64String (base64Data);
  287. if (bytes.Length > 0)
  288. {
  289. BluetoothLEHardwareInterface.Log ("Peripheral Received: " + characteristic);
  290. string byteString = "";
  291. foreach (byte b in bytes)
  292. byteString += string.Format ("{0:X2}", b);
  293. BluetoothLEHardwareInterface.Log (byteString);
  294. if (PeripheralReceivedWriteDataAction != null)
  295. PeripheralReceivedWriteDataAction (characteristic, bytes);
  296. }
  297. }
  298. }
  299. #if UNITY_IOS
  300. private void IncludeCoreLocationFramework()
  301. {
  302. // this method is here because Unity now only includes CoreLocation
  303. // if there are methods in the .cs code that access it
  304. Input.location.Stop ();
  305. }
  306. #endif
  307. }