BluetoothHardwareInterface.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969
  1. #define EXPERIMENTAL_MACOS_EDITOR
  2. /*
  3. This build includes an experimental implementation for the macOS editor of Unity
  4. It is experiemental because of the way that the Unity editor hangs on to plugin
  5. instances after leaving play mode. This causes this plugin to not free up its
  6. resources and therefore can cause crashes in the Unity editor on macOS.
  7. Since Unity does not give plugins or apps a chance to do anything when the user
  8. hits the play / stop button in the Editor there isn't a chance for the app to
  9. deinitialize this plugin.
  10. What I have found in my own use of this is that if you put a button on your app
  11. somewhere that you can press before hitting the stop button in the editor and
  12. then in that button handler call this plugin's Deinitialize method it seems to
  13. minimize how often the editor crashes.
  14. WARNING: using the macOS editor can cause the editor to crash an loose your work
  15. and settings. Save often. You have been warned, so please don't contact me if
  16. you have lost work becausee of this problem. This is experimental only. Use at
  17. your own risk.
  18. */
  19. using UnityEngine;
  20. using System;
  21. using System.Runtime.InteropServices;
  22. using System.Collections.Generic;
  23. #if UNITY_2018_3_OR_NEWER
  24. #if UNITY_ANDROID
  25. using UnityEngine.Android;
  26. #endif
  27. #endif
  28. public class BluetoothLEHardwareInterface
  29. {
  30. public enum CBCharacteristicProperties
  31. {
  32. CBCharacteristicPropertyBroadcast = 0x01,
  33. CBCharacteristicPropertyRead = 0x02,
  34. CBCharacteristicPropertyWriteWithoutResponse = 0x04,
  35. CBCharacteristicPropertyWrite = 0x08,
  36. CBCharacteristicPropertyNotify = 0x10,
  37. CBCharacteristicPropertyIndicate = 0x20,
  38. CBCharacteristicPropertyAuthenticatedSignedWrites = 0x40,
  39. CBCharacteristicPropertyExtendedProperties = 0x80,
  40. CBCharacteristicPropertyNotifyEncryptionRequired = 0x100,
  41. CBCharacteristicPropertyIndicateEncryptionRequired = 0x200,
  42. };
  43. public enum ScanMode
  44. {
  45. LowPower = 0,
  46. Balanced = 1,
  47. LowLatency = 2
  48. }
  49. public enum ConnectionPriority
  50. {
  51. LowPower = 0,
  52. Balanced = 1,
  53. High = 2,
  54. }
  55. public enum iOSProximity
  56. {
  57. Unknown = 0,
  58. Immediate = 1,
  59. Near = 2,
  60. Far = 3,
  61. }
  62. public struct iBeaconData
  63. {
  64. public string UUID;
  65. public int Major;
  66. public int Minor;
  67. public int RSSI;
  68. public int AndroidSignalPower;
  69. public iOSProximity iOSProximity;
  70. }
  71. #if UNITY_ANDROID
  72. public enum CBAttributePermissions
  73. {
  74. CBAttributePermissionsReadable = 0x01,
  75. CBAttributePermissionsWriteable = 0x10,
  76. CBAttributePermissionsReadEncryptionRequired = 0x02,
  77. CBAttributePermissionsWriteEncryptionRequired = 0x20,
  78. };
  79. #else
  80. public enum CBAttributePermissions
  81. {
  82. CBAttributePermissionsReadable = 0x01,
  83. CBAttributePermissionsWriteable = 0x02,
  84. CBAttributePermissionsReadEncryptionRequired = 0x04,
  85. CBAttributePermissionsWriteEncryptionRequired = 0x08,
  86. };
  87. #endif
  88. #if EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
  89. public delegate void UnitySendMessageCallbackDelegate (IntPtr objectName, IntPtr commandName, IntPtr commandData);
  90. [DllImport ("BluetoothLEOSX")]
  91. private static extern void ConnectUnitySendMessageCallback ([MarshalAs (UnmanagedType.FunctionPtr)]UnitySendMessageCallbackDelegate callbackMethod);
  92. [DllImport ("BluetoothLEOSX")]
  93. private static extern void OSXBluetoothLELog (string message);
  94. [DllImport ("BluetoothLEOSX")]
  95. private static extern void OSXBluetoothLEInitialize ([MarshalAs (UnmanagedType.Bool)]bool asCentral, [MarshalAs (UnmanagedType.Bool)]bool asPeripheral);
  96. [DllImport ("BluetoothLEOSX")]
  97. private static extern void OSXBluetoothLEDeInitialize ();
  98. [DllImport ("BluetoothLEOSX")]
  99. private static extern void OSXBluetoothLEPauseMessages (bool isPaused);
  100. [DllImport ("BluetoothLEOSX")]
  101. private static extern void OSXBluetoothLEScanForPeripheralsWithServices (string serviceUUIDsString, bool allowDuplicates, bool rssiOnly, bool clearPeripheralList);
  102. [DllImport ("BluetoothLEOSX")]
  103. private static extern void OSXBluetoothLERetrieveListOfPeripheralsWithServices (string serviceUUIDsString);
  104. [DllImport ("BluetoothLEOSX")]
  105. private static extern void OSXBluetoothLEStopScan ();
  106. [DllImport ("BluetoothLEOSX")]
  107. private static extern void OSXBluetoothLEConnectToPeripheral (string name);
  108. [DllImport ("BluetoothLEOSX")]
  109. private static extern void OSXBluetoothLEDisconnectAll ();
  110. [DllImport ("BluetoothLEOSX")]
  111. private static extern void OSXBluetoothLEDisconnectPeripheral (string name);
  112. [DllImport ("BluetoothLEOSX")]
  113. private static extern void OSXBluetoothLEReadCharacteristic (string name, string service, string characteristic);
  114. [DllImport ("BluetoothLEOSX")]
  115. private static extern void OSXBluetoothLEWriteCharacteristic (string name, string service, string characteristic, byte[] data, int length, bool withResponse);
  116. [DllImport ("BluetoothLEOSX")]
  117. private static extern void OSXBluetoothLESubscribeCharacteristic (string name, string service, string characteristic);
  118. [DllImport ("BluetoothLEOSX")]
  119. private static extern void OSXBluetoothLEUnSubscribeCharacteristic (string name, string service, string characteristic);
  120. #endif
  121. #if UNITY_IOS || UNITY_TVOS
  122. [DllImport ("__Internal")]
  123. private static extern void _iOSBluetoothLELog (string message);
  124. [DllImport ("__Internal")]
  125. private static extern void _iOSBluetoothLEInitialize (bool asCentral, bool asPeripheral);
  126. [DllImport ("__Internal")]
  127. private static extern void _iOSBluetoothLEDeInitialize ();
  128. [DllImport ("__Internal")]
  129. private static extern void _iOSBluetoothLEPauseMessages (bool isPaused);
  130. [DllImport ("__Internal")]
  131. private static extern void _iOSBluetoothLEScanForPeripheralsWithServices (string serviceUUIDsString, bool allowDuplicates, bool rssiOnly, bool clearPeripheralList);
  132. [DllImport ("__Internal")]
  133. private static extern void _iOSBluetoothLERetrieveListOfPeripheralsWithServices (string serviceUUIDsString);
  134. [DllImport ("__Internal")]
  135. private static extern void _iOSBluetoothLEStopScan ();
  136. [DllImport ("__Internal")]
  137. private static extern void _iOSBluetoothLEConnectToPeripheral (string name);
  138. [DllImport ("__Internal")]
  139. private static extern void _iOSBluetoothLEDisconnectPeripheral (string name);
  140. [DllImport ("__Internal")]
  141. private static extern void _iOSBluetoothLEReadCharacteristic (string name, string service, string characteristic);
  142. [DllImport ("__Internal")]
  143. private static extern void _iOSBluetoothLEWriteCharacteristic (string name, string service, string characteristic, byte[] data, int length, bool withResponse);
  144. [DllImport ("__Internal")]
  145. private static extern void _iOSBluetoothLESubscribeCharacteristic (string name, string service, string characteristic);
  146. [DllImport ("__Internal")]
  147. private static extern void _iOSBluetoothLEUnSubscribeCharacteristic (string name, string service, string characteristic);
  148. [DllImport ("__Internal")]
  149. private static extern void _iOSBluetoothLEDisconnectAll ();
  150. #if !UNITY_TVOS
  151. [DllImport ("__Internal")]
  152. private static extern void _iOSBluetoothLEScanForBeacons (string proximityUUIDsString);
  153. [DllImport ("__Internal")]
  154. private static extern void _iOSBluetoothLEStopBeaconScan ();
  155. [DllImport ("__Internal")]
  156. private static extern void _iOSBluetoothLEPeripheralName (string newName);
  157. [DllImport ("__Internal")]
  158. private static extern void _iOSBluetoothLECreateService (string uuid, bool primary);
  159. [DllImport ("__Internal")]
  160. private static extern void _iOSBluetoothLERemoveService (string uuid);
  161. [DllImport ("__Internal")]
  162. private static extern void _iOSBluetoothLERemoveServices ();
  163. [DllImport ("__Internal")]
  164. private static extern void _iOSBluetoothLECreateCharacteristic (string uuid, int properties, int permissions, byte[] data, int length);
  165. [DllImport ("__Internal")]
  166. private static extern void _iOSBluetoothLERemoveCharacteristic (string uuid);
  167. [DllImport ("__Internal")]
  168. private static extern void _iOSBluetoothLERemoveCharacteristics ();
  169. [DllImport ("__Internal")]
  170. private static extern void _iOSBluetoothLEStartAdvertising ();
  171. [DllImport ("__Internal")]
  172. private static extern void _iOSBluetoothLEStopAdvertising ();
  173. [DllImport ("__Internal")]
  174. private static extern void _iOSBluetoothLEUpdateCharacteristicValue (string uuid, byte[] data, int length);
  175. #endif
  176. #elif UNITY_ANDROID
  177. static AndroidJavaObject _android = null;
  178. #endif
  179. private static BluetoothDeviceScript bluetoothDeviceScript;
  180. public static void Log (string message)
  181. {
  182. #if EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
  183. Debug.Log(message);
  184. #else
  185. if (!Application.isEditor)
  186. {
  187. #if UNITY_IOS || UNITY_TVOS
  188. _iOSBluetoothLELog (message);
  189. #elif UNITY_ANDROID
  190. if (_android == null)
  191. {
  192. AndroidJavaClass javaClass = new AndroidJavaClass ("com.shatalmic.unityandroidbluetoothlelib.UnityBluetoothLE");
  193. _android = javaClass.CallStatic<AndroidJavaObject> ("getInstance");
  194. }
  195. if (_android != null)
  196. _android.Call ("androidBluetoothLog", message);
  197. #endif
  198. }
  199. #endif
  200. }
  201. public static BluetoothDeviceScript Initialize (bool asCentral, bool asPeripheral, Action action, Action<string> errorAction)
  202. {
  203. bluetoothDeviceScript = null;
  204. #if UNITY_2018_3_OR_NEWER
  205. #if UNITY_ANDROID
  206. if (!Permission.HasUserAuthorizedPermission (Permission.FineLocation))
  207. Permission.RequestUserPermission (Permission.FineLocation);
  208. #endif
  209. #endif
  210. GameObject bluetoothLEReceiver = GameObject.Find("BluetoothLEReceiver");
  211. if (bluetoothLEReceiver == null)
  212. bluetoothLEReceiver = new GameObject ("BluetoothLEReceiver");
  213. if (bluetoothLEReceiver != null)
  214. {
  215. bluetoothDeviceScript = bluetoothLEReceiver.GetComponent<BluetoothDeviceScript> ();
  216. if (bluetoothDeviceScript == null)
  217. bluetoothDeviceScript = bluetoothLEReceiver.AddComponent<BluetoothDeviceScript> ();
  218. if (bluetoothDeviceScript != null)
  219. {
  220. bluetoothDeviceScript.InitializedAction = action;
  221. bluetoothDeviceScript.ErrorAction = errorAction;
  222. }
  223. }
  224. GameObject.DontDestroyOnLoad (bluetoothLEReceiver);
  225. #if EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
  226. ConnectUnitySendMessageCallback ((objectName, commandName, commandData) => {
  227. string name = Marshal.PtrToStringAuto (objectName);
  228. string command = Marshal.PtrToStringAuto (commandName);
  229. string data = Marshal.PtrToStringAuto (commandData);
  230. GameObject foundObject = GameObject.Find (name);
  231. if (foundObject != null)
  232. foundObject.SendMessage (command, data);
  233. });
  234. BluetoothLEHardwareInterface.OSXBluetoothLEInitialize (asCentral, asPeripheral);
  235. #else
  236. if (Application.isEditor)
  237. {
  238. if (bluetoothDeviceScript != null)
  239. bluetoothDeviceScript.SendMessage ("OnBluetoothMessage", "Initialized");
  240. }
  241. else
  242. {
  243. #if UNITY_IOS || UNITY_TVOS
  244. _iOSBluetoothLEInitialize (asCentral, asPeripheral);
  245. #elif UNITY_ANDROID
  246. if (_android == null)
  247. {
  248. AndroidJavaClass javaClass = new AndroidJavaClass ("com.shatalmic.unityandroidbluetoothlelib.UnityBluetoothLE");
  249. _android = javaClass.CallStatic<AndroidJavaObject> ("getInstance");
  250. }
  251. if (_android != null)
  252. _android.Call ("androidBluetoothInitialize", asCentral, asPeripheral);
  253. #endif
  254. }
  255. #endif
  256. return bluetoothDeviceScript;
  257. }
  258. public static void DeInitialize (Action action)
  259. {
  260. if (bluetoothDeviceScript != null)
  261. bluetoothDeviceScript.DeinitializedAction = action;
  262. #if EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
  263. BluetoothLEHardwareInterface.OSXBluetoothLEDeInitialize ();
  264. #else
  265. if (Application.isEditor)
  266. {
  267. if (bluetoothDeviceScript != null)
  268. bluetoothDeviceScript.SendMessage ("OnBluetoothMessage", "DeInitialized");
  269. }
  270. else
  271. {
  272. #if UNITY_IOS || UNITY_TVOS
  273. _iOSBluetoothLEDeInitialize ();
  274. #elif UNITY_ANDROID
  275. if (_android != null)
  276. _android.Call ("androidBluetoothDeInitialize");
  277. #endif
  278. }
  279. #endif
  280. }
  281. public static void FinishDeInitialize ()
  282. {
  283. GameObject bluetoothLEReceiver = GameObject.Find("BluetoothLEReceiver");
  284. if (bluetoothLEReceiver != null)
  285. GameObject.Destroy(bluetoothLEReceiver);
  286. }
  287. public static void BluetoothEnable (bool enable)
  288. {
  289. if (!Application.isEditor)
  290. {
  291. #if UNITY_IOS || UNITY_TVOS
  292. //_iOSBluetoothLELog (message);
  293. #elif UNITY_ANDROID
  294. if (_android != null)
  295. _android.Call ("androidBluetoothEnable", enable);
  296. #endif
  297. }
  298. }
  299. public static void BluetoothScanMode (ScanMode scanMode)
  300. {
  301. if (!Application.isEditor)
  302. {
  303. #if UNITY_IOS || UNITY_TVOS
  304. #elif UNITY_ANDROID
  305. if (_android != null)
  306. _android.Call ("androidBluetoothScanMode", (int)scanMode);
  307. #endif
  308. }
  309. }
  310. public static void BluetoothConnectionPriority (ConnectionPriority connectionPriority)
  311. {
  312. if (!Application.isEditor)
  313. {
  314. #if UNITY_IOS || UNITY_TVOS
  315. #elif UNITY_ANDROID
  316. if (_android != null)
  317. _android.Call ("androidBluetoothConnectionPriority", (int)connectionPriority);
  318. #endif
  319. }
  320. }
  321. public static void PauseMessages (bool isPaused)
  322. {
  323. #if EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
  324. OSXBluetoothLEPauseMessages (isPaused);
  325. #else
  326. if (!Application.isEditor)
  327. {
  328. #if UNITY_IOS || UNITY_TVOS
  329. _iOSBluetoothLEPauseMessages (isPaused);
  330. #elif UNITY_ANDROID
  331. if (_android != null)
  332. _android.Call ("androidBluetoothPause", isPaused);
  333. #endif
  334. }
  335. #endif
  336. }
  337. // scanning for beacons requires that you know the Proximity UUID
  338. public static void ScanForBeacons (string[] proximityUUIDs, Action<iBeaconData> actionBeaconResponse)
  339. {
  340. if (proximityUUIDs != null && proximityUUIDs.Length >= 0)
  341. {
  342. if (!Application.isEditor)
  343. {
  344. if (bluetoothDeviceScript != null)
  345. bluetoothDeviceScript.DiscoveredBeaconAction = actionBeaconResponse;
  346. string proximityUUIDsString = null;
  347. if (proximityUUIDs != null && proximityUUIDs.Length > 0)
  348. {
  349. proximityUUIDsString = "";
  350. foreach (string proximityUUID in proximityUUIDs)
  351. proximityUUIDsString += proximityUUID + "|";
  352. proximityUUIDsString = proximityUUIDsString.Substring (0, proximityUUIDsString.Length - 1);
  353. }
  354. #if UNITY_IOS
  355. _iOSBluetoothLEScanForBeacons (proximityUUIDsString);
  356. #elif UNITY_ANDROID
  357. if (_android != null)
  358. _android.Call ("androidBluetoothScanForBeacons", proximityUUIDsString);
  359. #endif
  360. }
  361. }
  362. }
  363. public static void ScanForPeripheralsWithServices (string[] serviceUUIDs, Action<string, string> action, Action<string, string, int, byte[]> actionAdvertisingInfo = null, bool rssiOnly = false, bool clearPeripheralList = true, int recordType = 0xFF)
  364. {
  365. #if !UNITY_EDITOR_OSX || !EXPERIMENTAL_MACOS_EDITOR
  366. if (!Application.isEditor)
  367. {
  368. #endif
  369. if (bluetoothDeviceScript != null)
  370. {
  371. bluetoothDeviceScript.DiscoveredPeripheralAction = action;
  372. bluetoothDeviceScript.DiscoveredPeripheralWithAdvertisingInfoAction = actionAdvertisingInfo;
  373. if (bluetoothDeviceScript.DiscoveredDeviceList != null)
  374. bluetoothDeviceScript.DiscoveredDeviceList.Clear ();
  375. }
  376. string serviceUUIDsString = null;
  377. if (serviceUUIDs != null && serviceUUIDs.Length > 0)
  378. {
  379. serviceUUIDsString = "";
  380. foreach (string serviceUUID in serviceUUIDs)
  381. serviceUUIDsString += serviceUUID + "|";
  382. serviceUUIDsString = serviceUUIDsString.Substring (0, serviceUUIDsString.Length - 1);
  383. }
  384. #if EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
  385. OSXBluetoothLEScanForPeripheralsWithServices (serviceUUIDsString, (actionAdvertisingInfo != null), rssiOnly, clearPeripheralList);
  386. #elif UNITY_IOS || UNITY_TVOS
  387. _iOSBluetoothLEScanForPeripheralsWithServices (serviceUUIDsString, (actionAdvertisingInfo != null), rssiOnly, clearPeripheralList);
  388. #elif UNITY_ANDROID
  389. if (_android != null)
  390. {
  391. if (serviceUUIDsString == null)
  392. serviceUUIDsString = "";
  393. _android.Call ("androidBluetoothScanForPeripheralsWithServices", serviceUUIDsString, rssiOnly, recordType);
  394. }
  395. #endif
  396. #if !UNITY_EDITOR_OSX || !EXPERIMENTAL_MACOS_EDITOR
  397. }
  398. #endif
  399. }
  400. public static void RetrieveListOfPeripheralsWithServices (string[] serviceUUIDs, Action<string, string> action)
  401. {
  402. #if !UNITY_EDITOR_OSX || !EXPERIMENTAL_MACOS_EDITOR
  403. if (!Application.isEditor)
  404. {
  405. #endif
  406. if (bluetoothDeviceScript != null)
  407. {
  408. bluetoothDeviceScript.RetrievedConnectedPeripheralAction = action;
  409. if (bluetoothDeviceScript.DiscoveredDeviceList != null)
  410. bluetoothDeviceScript.DiscoveredDeviceList.Clear ();
  411. }
  412. string serviceUUIDsString = serviceUUIDs.Length > 0 ? "" : null;
  413. foreach (string serviceUUID in serviceUUIDs)
  414. serviceUUIDsString += serviceUUID + "|";
  415. // strip the last delimeter
  416. serviceUUIDsString = serviceUUIDsString.Substring (0, serviceUUIDsString.Length - 1);
  417. #if EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
  418. OSXBluetoothLERetrieveListOfPeripheralsWithServices (serviceUUIDsString);
  419. #elif UNITY_IOS || UNITY_TVOS
  420. _iOSBluetoothLERetrieveListOfPeripheralsWithServices (serviceUUIDsString);
  421. #elif UNITY_ANDROID
  422. if (_android != null)
  423. _android.Call ("androidBluetoothRetrieveListOfPeripheralsWithServices", serviceUUIDsString);
  424. #endif
  425. #if !UNITY_EDITOR_OSX || !EXPERIMENTAL_MACOS_EDITOR
  426. }
  427. #endif
  428. }
  429. public static void StopScan ()
  430. {
  431. #if EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
  432. OSXBluetoothLEStopScan ();
  433. #else
  434. if (!Application.isEditor)
  435. {
  436. #if UNITY_IOS || UNITY_TVOS
  437. _iOSBluetoothLEStopScan ();
  438. #elif UNITY_ANDROID
  439. if (_android != null)
  440. _android.Call ("androidBluetoothStopScan");
  441. #endif
  442. }
  443. #endif
  444. }
  445. public static void StopBeaconScan ()
  446. {
  447. if (!Application.isEditor)
  448. {
  449. #if UNITY_IOS
  450. _iOSBluetoothLEStopBeaconScan ();
  451. #elif UNITY_ANDROID
  452. if (_android != null)
  453. _android.Call ("androidBluetoothStopBeaconScan");
  454. #endif
  455. }
  456. }
  457. public static void DisconnectAll ()
  458. {
  459. #if EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
  460. OSXBluetoothLEDisconnectAll ();
  461. #else
  462. if (!Application.isEditor)
  463. {
  464. #if UNITY_IOS || UNITY_TVOS
  465. _iOSBluetoothLEDisconnectAll ();
  466. #elif UNITY_ANDROID
  467. if (_android != null)
  468. _android.Call ("androidBluetoothDisconnectAll");
  469. #endif
  470. }
  471. #endif
  472. }
  473. public static void ConnectToPeripheral (string name, Action<string> connectAction, Action<string, string> serviceAction, Action<string, string, string> characteristicAction, Action<string> disconnectAction = null)
  474. {
  475. #if !UNITY_EDITOR_OSX || !EXPERIMENTAL_MACOS_EDITOR
  476. if (!Application.isEditor)
  477. {
  478. #endif
  479. if (bluetoothDeviceScript != null)
  480. {
  481. bluetoothDeviceScript.ConnectedPeripheralAction = connectAction;
  482. bluetoothDeviceScript.DiscoveredServiceAction = serviceAction;
  483. bluetoothDeviceScript.DiscoveredCharacteristicAction = characteristicAction;
  484. bluetoothDeviceScript.ConnectedDisconnectPeripheralAction = disconnectAction;
  485. }
  486. #if EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
  487. OSXBluetoothLEConnectToPeripheral (name);
  488. #elif UNITY_IOS || UNITY_TVOS
  489. _iOSBluetoothLEConnectToPeripheral (name);
  490. #elif UNITY_ANDROID
  491. if (_android != null)
  492. _android.Call ("androidBluetoothConnectToPeripheral", name);
  493. #endif
  494. #if !UNITY_EDITOR_OSX || !EXPERIMENTAL_MACOS_EDITOR
  495. }
  496. #endif
  497. }
  498. public static void DisconnectPeripheral (string name, Action<string> action)
  499. {
  500. #if !UNITY_EDITOR_OSX || !EXPERIMENTAL_MACOS_EDITOR
  501. if (!Application.isEditor)
  502. {
  503. #endif
  504. if (bluetoothDeviceScript != null)
  505. bluetoothDeviceScript.DisconnectedPeripheralAction = action;
  506. #if EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
  507. OSXBluetoothLEDisconnectPeripheral (name);
  508. #elif UNITY_IOS || UNITY_TVOS
  509. _iOSBluetoothLEDisconnectPeripheral (name);
  510. #elif UNITY_ANDROID
  511. if (_android != null)
  512. _android.Call ("androidBluetoothDisconnectPeripheral", name);
  513. #endif
  514. #if !UNITY_EDITOR_OSX || !EXPERIMENTAL_MACOS_EDITOR
  515. }
  516. #endif
  517. }
  518. public static void ReadCharacteristic (string name, string service, string characteristic, Action<string, byte[]> action)
  519. {
  520. #if !UNITY_EDITOR_OSX || !EXPERIMENTAL_MACOS_EDITOR
  521. if (!Application.isEditor)
  522. {
  523. #endif
  524. if (bluetoothDeviceScript != null)
  525. {
  526. if (!bluetoothDeviceScript.DidUpdateCharacteristicValueAction.ContainsKey (name))
  527. bluetoothDeviceScript.DidUpdateCharacteristicValueAction[name] = new Dictionary<string, Action<string, byte[]>>();
  528. #if UNITY_IOS || UNITY_TVOS || (EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX))
  529. bluetoothDeviceScript.DidUpdateCharacteristicValueAction [name] [characteristic] = action;
  530. #elif UNITY_ANDROID
  531. bluetoothDeviceScript.DidUpdateCharacteristicValueAction [name] [FullUUID (characteristic).ToLower ()] = action;
  532. #endif
  533. }
  534. #if EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
  535. OSXBluetoothLEReadCharacteristic (name, service, characteristic);
  536. #elif UNITY_IOS || UNITY_TVOS
  537. _iOSBluetoothLEReadCharacteristic (name, service, characteristic);
  538. #elif UNITY_ANDROID
  539. if (_android != null)
  540. _android.Call ("androidReadCharacteristic", name, service, characteristic);
  541. #endif
  542. #if !UNITY_EDITOR_OSX || !EXPERIMENTAL_MACOS_EDITOR
  543. }
  544. #endif
  545. }
  546. public static void WriteCharacteristic (string name, string service, string characteristic, byte[] data, int length, bool withResponse, Action<string> action)
  547. {
  548. #if !UNITY_EDITOR_OSX || !EXPERIMENTAL_MACOS_EDITOR
  549. if (!Application.isEditor)
  550. {
  551. #endif
  552. if (bluetoothDeviceScript != null)
  553. bluetoothDeviceScript.DidWriteCharacteristicAction = action;
  554. #if EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
  555. OSXBluetoothLEWriteCharacteristic (name, service, characteristic, data, length, withResponse);
  556. #elif UNITY_IOS || UNITY_TVOS
  557. _iOSBluetoothLEWriteCharacteristic (name, service, characteristic, data, length, withResponse);
  558. #elif UNITY_ANDROID
  559. if (_android != null)
  560. _android.Call ("androidWriteCharacteristic", name, service, characteristic, data, length, withResponse);
  561. #endif
  562. #if !UNITY_EDITOR_OSX || !EXPERIMENTAL_MACOS_EDITOR
  563. }
  564. #endif
  565. }
  566. public static void SubscribeCharacteristic (string name, string service, string characteristic, Action<string> notificationAction, Action<string, byte[]> action)
  567. {
  568. #if !UNITY_EDITOR_OSX || !EXPERIMENTAL_MACOS_EDITOR
  569. if (!Application.isEditor)
  570. {
  571. #endif
  572. if (bluetoothDeviceScript != null)
  573. {
  574. name = name.ToUpper ();
  575. service = service.ToUpper ();
  576. characteristic = characteristic.ToUpper ();
  577. #if UNITY_IOS || UNITY_TVOS || (EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX))
  578. if (!bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicAction.ContainsKey (name))
  579. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicAction [name] = new Dictionary<string, Action<string>> ();
  580. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicAction [name] [characteristic] = notificationAction;
  581. if (!bluetoothDeviceScript.DidUpdateCharacteristicValueAction.ContainsKey (name))
  582. bluetoothDeviceScript.DidUpdateCharacteristicValueAction [name] = new Dictionary<string, Action<string, byte[]>> ();
  583. bluetoothDeviceScript.DidUpdateCharacteristicValueAction [name] [characteristic] = action;
  584. #elif UNITY_ANDROID
  585. if (!bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicAction.ContainsKey (name))
  586. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicAction [name] = new Dictionary<string, Action<string>> ();
  587. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicAction [name] [FullUUID (characteristic).ToLower ()] = notificationAction;
  588. if (!bluetoothDeviceScript.DidUpdateCharacteristicValueAction.ContainsKey (name))
  589. bluetoothDeviceScript.DidUpdateCharacteristicValueAction [name] = new Dictionary<string, Action<string, byte[]>> ();
  590. bluetoothDeviceScript.DidUpdateCharacteristicValueAction [name] [FullUUID (characteristic).ToLower ()] = action;
  591. #endif
  592. }
  593. #if EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
  594. OSXBluetoothLESubscribeCharacteristic (name, service, characteristic);
  595. #elif UNITY_IOS || UNITY_TVOS
  596. _iOSBluetoothLESubscribeCharacteristic (name, service, characteristic);
  597. #elif UNITY_ANDROID
  598. if (_android != null)
  599. _android.Call ("androidSubscribeCharacteristic", name, service, characteristic);
  600. #endif
  601. #if !UNITY_EDITOR_OSX || !EXPERIMENTAL_MACOS_EDITOR
  602. }
  603. #endif
  604. }
  605. public static void SubscribeCharacteristicWithDeviceAddress (string name, string service, string characteristic, Action<string, string> notificationAction, Action<string, string, byte[]> action)
  606. {
  607. #if !UNITY_EDITOR_OSX || !EXPERIMENTAL_MACOS_EDITOR
  608. if (!Application.isEditor)
  609. {
  610. #endif
  611. if (bluetoothDeviceScript != null)
  612. {
  613. name = name.ToUpper ();
  614. service = service.ToUpper ();
  615. characteristic = characteristic.ToUpper ();
  616. #if UNITY_IOS || UNITY_TVOS || (EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX))
  617. if (!bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicWithDeviceAddressAction.ContainsKey (name))
  618. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicWithDeviceAddressAction[name] = new Dictionary<string, Action<string, string>>();
  619. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicWithDeviceAddressAction[name][characteristic] = notificationAction;
  620. if (!bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicAction.ContainsKey (name))
  621. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicAction[name] = new Dictionary<string, Action<string>>();
  622. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicAction[name][characteristic] = null;
  623. if (!bluetoothDeviceScript.DidUpdateCharacteristicValueWithDeviceAddressAction.ContainsKey (name))
  624. bluetoothDeviceScript.DidUpdateCharacteristicValueWithDeviceAddressAction[name] = new Dictionary<string, Action<string, string, byte[]>>();
  625. bluetoothDeviceScript.DidUpdateCharacteristicValueWithDeviceAddressAction[name][characteristic] = action;
  626. #elif UNITY_ANDROID
  627. if (!bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicWithDeviceAddressAction.ContainsKey (name))
  628. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicWithDeviceAddressAction[name] = new Dictionary<string, Action<string, string>>();
  629. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicWithDeviceAddressAction[name][FullUUID (characteristic).ToLower ()] = notificationAction;
  630. if (!bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicAction.ContainsKey(name))
  631. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicAction[name] = new Dictionary<string, Action<string>>();
  632. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicAction[name][FullUUID (characteristic).ToLower ()] = null;
  633. if (!bluetoothDeviceScript.DidUpdateCharacteristicValueWithDeviceAddressAction.ContainsKey (name))
  634. bluetoothDeviceScript.DidUpdateCharacteristicValueWithDeviceAddressAction[name] = new Dictionary<string, Action<string, string, byte[]>>();
  635. bluetoothDeviceScript.DidUpdateCharacteristicValueWithDeviceAddressAction[name][FullUUID (characteristic).ToLower ()] = action;
  636. #endif
  637. }
  638. #if EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
  639. OSXBluetoothLESubscribeCharacteristic (name, service, characteristic);
  640. #elif UNITY_IOS || UNITY_TVOS
  641. _iOSBluetoothLESubscribeCharacteristic (name, service, characteristic);
  642. #elif UNITY_ANDROID
  643. if (_android != null)
  644. _android.Call ("androidSubscribeCharacteristic", name, service, characteristic);
  645. #endif
  646. #if !UNITY_EDITOR_OSX || !EXPERIMENTAL_MACOS_EDITOR
  647. }
  648. #endif
  649. }
  650. public static void UnSubscribeCharacteristic (string name, string service, string characteristic, Action<string> action)
  651. {
  652. #if !UNITY_EDITOR_OSX || !EXPERIMENTAL_MACOS_EDITOR
  653. if (!Application.isEditor)
  654. {
  655. #endif
  656. if (bluetoothDeviceScript != null)
  657. {
  658. name = name.ToUpper ();
  659. service = service.ToUpper ();
  660. characteristic = characteristic.ToUpper ();
  661. #if UNITY_IOS || UNITY_TVOS || (EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX))
  662. if (!bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicWithDeviceAddressAction.ContainsKey (name))
  663. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicWithDeviceAddressAction[name] = new Dictionary<string, Action<string, string>>();
  664. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicWithDeviceAddressAction[name][characteristic] = null;
  665. if (!bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicAction.ContainsKey (name))
  666. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicAction[name] = new Dictionary<string, Action<string>> ();
  667. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicAction[name][characteristic] = action;
  668. #elif UNITY_ANDROID
  669. if (!bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicWithDeviceAddressAction.ContainsKey (name))
  670. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicWithDeviceAddressAction[name] = new Dictionary<string, Action<string, string>>();
  671. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicWithDeviceAddressAction[name][FullUUID (characteristic).ToLower ()] = null;
  672. if (!bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicAction.ContainsKey (name))
  673. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicAction[name] = new Dictionary<string, Action<string>> ();
  674. bluetoothDeviceScript.DidUpdateNotificationStateForCharacteristicAction[name][FullUUID (characteristic).ToLower ()] = action;
  675. #endif
  676. }
  677. #if EXPERIMENTAL_MACOS_EDITOR && (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
  678. OSXBluetoothLEUnSubscribeCharacteristic (name, service, characteristic);
  679. #elif UNITY_IOS || UNITY_TVOS
  680. _iOSBluetoothLEUnSubscribeCharacteristic (name, service, characteristic);
  681. #elif UNITY_ANDROID
  682. if (_android != null)
  683. _android.Call ("androidUnsubscribeCharacteristic", name, service, characteristic);
  684. #endif
  685. #if !UNITY_EDITOR_OSX || !EXPERIMENTAL_MACOS_EDITOR
  686. }
  687. #endif
  688. }
  689. public static void PeripheralName (string newName)
  690. {
  691. if (!Application.isEditor)
  692. {
  693. #if UNITY_IOS
  694. _iOSBluetoothLEPeripheralName (newName);
  695. #elif UNITY_ANDROID
  696. if (_android != null)
  697. _android.Call ("androidPeripheralName", newName);
  698. #endif
  699. }
  700. }
  701. public static void CreateService (string uuid, bool primary, Action<string> action)
  702. {
  703. if (!Application.isEditor)
  704. {
  705. if (bluetoothDeviceScript != null)
  706. bluetoothDeviceScript.ServiceAddedAction = action;
  707. #if UNITY_IOS
  708. _iOSBluetoothLECreateService (uuid, primary);
  709. #elif UNITY_ANDROID
  710. if (_android != null)
  711. _android.Call ("androidCreateService", uuid, primary);
  712. #endif
  713. }
  714. }
  715. public static void RemoveService (string uuid)
  716. {
  717. if (!Application.isEditor)
  718. {
  719. #if UNITY_IOS
  720. _iOSBluetoothLERemoveService (uuid);
  721. #elif UNITY_ANDROID
  722. if (_android != null)
  723. _android.Call ("androidRemoveService", uuid);
  724. #endif
  725. }
  726. }
  727. public static void RemoveServices ()
  728. {
  729. if (!Application.isEditor)
  730. {
  731. #if UNITY_IOS
  732. _iOSBluetoothLERemoveServices ();
  733. #elif UNITY_ANDROID
  734. if (_android != null)
  735. _android.Call ("androidRemoveServices");
  736. #endif
  737. }
  738. }
  739. public static void CreateCharacteristic (string uuid, CBCharacteristicProperties properties, CBAttributePermissions permissions, byte[] data, int length, Action<string, byte[]> action)
  740. {
  741. if (!Application.isEditor)
  742. {
  743. if (bluetoothDeviceScript != null)
  744. bluetoothDeviceScript.PeripheralReceivedWriteDataAction = action;
  745. #if UNITY_IOS
  746. _iOSBluetoothLECreateCharacteristic (uuid, (int)properties, (int)permissions, data, length);
  747. #elif UNITY_ANDROID
  748. if (_android != null)
  749. _android.Call ("androidCreateCharacteristic", uuid, (int)properties, (int)permissions, data, length);
  750. #endif
  751. }
  752. }
  753. public static void RemoveCharacteristic (string uuid)
  754. {
  755. if (!Application.isEditor)
  756. {
  757. if (bluetoothDeviceScript != null)
  758. bluetoothDeviceScript.PeripheralReceivedWriteDataAction = null;
  759. #if UNITY_IOS
  760. _iOSBluetoothLERemoveCharacteristic (uuid);
  761. #elif UNITY_ANDROID
  762. if (_android != null)
  763. _android.Call ("androidRemoveCharacteristic", uuid);
  764. #endif
  765. }
  766. }
  767. public static void RemoveCharacteristics ()
  768. {
  769. if (!Application.isEditor)
  770. {
  771. #if UNITY_IOS
  772. _iOSBluetoothLERemoveCharacteristics ();
  773. #elif UNITY_ANDROID
  774. if (_android != null)
  775. _android.Call ("androidRemoveCharacteristics");
  776. #endif
  777. }
  778. }
  779. public static void StartAdvertising (Action action)
  780. {
  781. if (!Application.isEditor)
  782. {
  783. if (bluetoothDeviceScript != null)
  784. bluetoothDeviceScript.StartedAdvertisingAction = action;
  785. #if UNITY_IOS
  786. _iOSBluetoothLEStartAdvertising ();
  787. #elif UNITY_ANDROID
  788. if (_android != null)
  789. _android.Call ("androidStartAdvertising");
  790. #endif
  791. }
  792. }
  793. public static void StopAdvertising (Action action)
  794. {
  795. if (!Application.isEditor)
  796. {
  797. if (bluetoothDeviceScript != null)
  798. bluetoothDeviceScript.StoppedAdvertisingAction = action;
  799. #if UNITY_IOS
  800. _iOSBluetoothLEStopAdvertising ();
  801. #elif UNITY_ANDROID
  802. if (_android != null)
  803. _android.Call ("androidStopAdvertising");
  804. #endif
  805. }
  806. }
  807. public static void UpdateCharacteristicValue (string uuid, byte[] data, int length)
  808. {
  809. if (!Application.isEditor)
  810. {
  811. #if UNITY_IOS
  812. _iOSBluetoothLEUpdateCharacteristicValue (uuid, data, length);
  813. #elif UNITY_ANDROID
  814. if (_android != null)
  815. _android.Call ("androidUpdateCharacteristicValue", uuid, data, length);
  816. #endif
  817. }
  818. }
  819. public static string FullUUID (string uuid)
  820. {
  821. if (uuid.Length == 4)
  822. return "0000" + uuid + "-0000-1000-8000-00805f9b34fb";
  823. return uuid;
  824. }
  825. }