BluetoothAim_SDK.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using ArduinoBluetoothAPI;
  6. namespace SmartBowSDK
  7. {
  8. public class BluetoothAim_SDK : MonoBehaviour
  9. {
  10. public SmartBowHelper smartBowHelper;
  11. public BluetoothDeviceConfig deviceConfig;
  12. private BluetoothHelper _bluetoothHelper;
  13. private BluetoothHelperService _bluetoothService;
  14. private BluetoothHelperCharacteristic _characteristicWrite;
  15. private static HashSet<object> _ScanLocker = new HashSet<object>();
  16. private int _receivedDataCount = 0;
  17. public string macAddress = null;
  18. public BluetoothStatusEnum bluetoothStatus;
  19. private BluetoothWindows _bluetoothWindows;
  20. /// <summary>
  21. /// 6轴
  22. /// </summary>
  23. private o06DOF.SixAxisFusion sixAxisFusion;
  24. /// <summary>
  25. /// 过滤名称
  26. /// </summary>
  27. public string filters { get; set; } = "";
  28. /// <summary>
  29. /// 是否使用mac过滤
  30. /// </summary>
  31. public bool isConnectName { get; set; } = true;//默认用名字连接
  32. /// <summary>
  33. /// 传入的mac
  34. /// </summary>
  35. public string connectMacStr { get; set; } = "";
  36. /// <summary>
  37. /// 当前的传感器类型
  38. /// </summary>
  39. public SensorAxisType sensorAxisType { get; set; } = SensorAxisType.NineAxisSensor;
  40. private void SetStatus(BluetoothStatusEnum newStatus)
  41. {
  42. BluetoothStatusEnum oldStatus = bluetoothStatus;
  43. if (oldStatus == newStatus) return;
  44. bluetoothStatus = newStatus;
  45. SmartBowLogger.Log(this, $"oldStatus[{oldStatus}]=>newStatus[{newStatus}]");
  46. if (newStatus == BluetoothStatusEnum.None)
  47. {
  48. _bluetoothHelper = null;
  49. _bluetoothService = null;
  50. _characteristicWrite = null;
  51. _receivedDataCount = 0;
  52. macAddress = null;
  53. _battery = 0;
  54. moduleInited = false;
  55. }
  56. smartBowHelper.InvokeOnBluetoothStatusChanged(oldStatus, newStatus);
  57. }
  58. void Awake()
  59. {
  60. DontDestroyOnLoad(gameObject);
  61. deviceConfig = BluetoothDeviceConfig.GetDefault();
  62. }
  63. void Update()
  64. {
  65. LoopHandleCommands();
  66. }
  67. private static int _NoneToConnectingStep = 0;
  68. public BluetoothWindows CreateWindowBLE() {
  69. //如果是window环境,直接实例化一个BluetoothWindows
  70. if (BluetoothWindows.IsWindows())
  71. {
  72. _bluetoothWindows = new BluetoothWindows();
  73. _bluetoothWindows.OnConnected = OnConnected_windows;
  74. _bluetoothWindows.OnConnectionFailed = OnConnectionFailed_windows;
  75. _bluetoothWindows.OnCharacteristicChanged = OnCharacteristicChanged_windows;
  76. return _bluetoothWindows;
  77. }
  78. return null;
  79. }
  80. public void Connect()
  81. {
  82. if (BluetoothWindows.IsWindows())
  83. {
  84. if (bluetoothStatus == BluetoothStatusEnum.None)
  85. {
  86. _bluetoothWindows.Connect();
  87. SetStatus(BluetoothStatusEnum.Connecting);
  88. //初始化一次六轴解析
  89. if (sixAxisFusion == null)
  90. {
  91. Vector3 accelOffset = Vector3.zero;
  92. Vector3 gyroOffset = Vector3.zero;
  93. float gForce = 1.0f;
  94. float gyroToDegree = 1.0f;
  95. sixAxisFusion = new o06DOF.SixAxisFusion(accelOffset, gyroOffset, gForce, gyroToDegree);
  96. }
  97. }
  98. return;
  99. }
  100. if (_ScanLocker.Count > 0) return;
  101. if (bluetoothStatus != BluetoothStatusEnum.None) return;
  102. if (_NoneToConnectingStep > 0) return;
  103. _NoneToConnectingStep = 1;
  104. if (Application.platform == RuntimePlatform.Android)
  105. {
  106. if (!BluetoothHelperAndroid_SDK.IsBluetoothEnabled())
  107. {
  108. HandleConnectError(BluetoothError.BluetoothNotEnabled, "蓝牙开关未打开");
  109. return;
  110. }
  111. if (BluetoothHelperAndroid_SDK.RequestBluetoothPermissions(() =>
  112. {
  113. _NoneToConnectingStep = 0;
  114. Connect();
  115. }, (permission) =>
  116. {
  117. if (permission.Contains("LOCATION"))
  118. {
  119. HandleConnectError(BluetoothError.LocationPermissionNotGranted, "尚未授予定位权限");
  120. }
  121. else if (permission.Contains("BLUETOOTH"))
  122. {
  123. HandleConnectError(BluetoothError.ScanPermissionNotGranted, "尚未授予扫描附近设备权限");
  124. }
  125. })) return;
  126. }
  127. try
  128. {
  129. BluetoothHelper.BLE = true;
  130. _bluetoothHelper = BluetoothHelper.GetNewInstance();
  131. _bluetoothHelper.OnConnected += OnConnected;
  132. _bluetoothHelper.OnConnectionFailed += OnConnectionFailed;
  133. SmartBowLogger.Log(this,"创建蓝牙的SensorAxisType类型:"+ sensorAxisType);
  134. if (sensorAxisType == SensorAxisType.SixAxisSensor)
  135. {
  136. //6轴时候,另外的解析操作
  137. _bluetoothHelper.OnCharacteristicChanged += OnCharacteristicChanged6Axis;
  138. //初始化一次六轴解析
  139. if (sixAxisFusion == null) {
  140. Vector3 accelOffset = Vector3.zero;
  141. Vector3 gyroOffset = Vector3.zero;
  142. float gForce = 1.0f;
  143. float gyroToDegree = 1.0f;
  144. sixAxisFusion = new o06DOF.SixAxisFusion(accelOffset, gyroOffset, gForce, gyroToDegree);
  145. }
  146. }
  147. else {
  148. //九轴的解析
  149. _bluetoothHelper.OnCharacteristicChanged += OnCharacteristicChanged;
  150. }
  151. _bluetoothHelper.OnScanEnded += OnScanEnded;
  152. _bluetoothHelper.ScanNearbyDevices();
  153. _NoneToConnectingStep = 2;
  154. }
  155. catch (Exception e)
  156. {
  157. HandleConnectError(BluetoothError.Unknown, e.ToString());
  158. }
  159. if (_NoneToConnectingStep == 2)
  160. {
  161. _NoneToConnectingStep = 0;
  162. _ScanLocker.Add(_bluetoothHelper);
  163. SetStatus(BluetoothStatusEnum.Connecting);
  164. }
  165. }
  166. private void HandleConnectError(BluetoothError error, string message)
  167. {
  168. _NoneToConnectingStep = 0;
  169. smartBowHelper.InvokeOnBluetoothError(error, message);
  170. }
  171. public void Disconnect()
  172. {
  173. //断开连接时候清除AimDeviceInfo
  174. ResetAimDeviceInfoToNull();
  175. if (BluetoothWindows.IsWindows())
  176. {
  177. if (_bluetoothWindows.Disconnect())
  178. SetStatus(BluetoothStatusEnum.None);
  179. return;
  180. }
  181. if (_bluetoothHelper != null)
  182. _bluetoothHelper.Disconnect();
  183. SetStatus(BluetoothStatusEnum.None);
  184. }
  185. void OnConnected(BluetoothHelper helper)
  186. {
  187. if (helper != _bluetoothHelper) return;
  188. SetStatus(BluetoothStatusEnum.Connected);
  189. foreach (BluetoothHelperService service in helper.getGattServices())
  190. {
  191. if (service.getName().ToLower().StartsWith(deviceConfig.service))
  192. {
  193. _bluetoothService = service;
  194. foreach (BluetoothHelperCharacteristic characteristic in service.getCharacteristics())
  195. {
  196. if (characteristic.getName().ToLower().StartsWith(deviceConfig.characteristicWrite))
  197. {
  198. _characteristicWrite = characteristic;
  199. }
  200. else if (characteristic.getName().ToLower().StartsWith(deviceConfig.characteristicNotify))
  201. {
  202. BluetoothHelperCharacteristic c = new BluetoothHelperCharacteristic(characteristic.getName());
  203. c.setService(_bluetoothService.getName());
  204. _bluetoothHelper.Subscribe(c);
  205. }
  206. }
  207. }
  208. }
  209. //指令区分
  210. if (sensorAxisType == SensorAxisType.SixAxisSensor)
  211. {
  212. //6轴指令
  213. StartCoroutine(InitWhenConnected6Axis());
  214. }
  215. else
  216. {
  217. //九轴
  218. StartCoroutine(InitWhenConnected());
  219. }
  220. }
  221. void OnConnected_windows()
  222. {
  223. SetStatus(BluetoothStatusEnum.Connected);
  224. if (sensorAxisType == SensorAxisType.SixAxisSensor)
  225. {
  226. //6轴指令
  227. StartCoroutine(InitWhenConnected6Axis());
  228. }
  229. else
  230. {
  231. //九轴
  232. StartCoroutine(InitWhenConnected());
  233. }
  234. }
  235. void OnConnectionFailed(BluetoothHelper helper)
  236. {
  237. if (helper != _bluetoothHelper) return;
  238. SetStatus(BluetoothStatusEnum.None);
  239. }
  240. void OnConnectionFailed_windows()
  241. {
  242. SetStatus(BluetoothStatusEnum.None);
  243. }
  244. /// <summary>
  245. /// 原九轴的传感器解析
  246. /// </summary>
  247. /// <param name="helper"></param>
  248. /// <param name="value"></param>
  249. /// <param name="characteristic"></param>
  250. void OnCharacteristicChanged(BluetoothHelper helper, byte[] value, BluetoothHelperCharacteristic characteristic)
  251. {
  252. if (helper != _bluetoothHelper) return;
  253. if (bluetoothStatus != BluetoothStatusEnum.Connected) return;
  254. byte[] bytes = value;
  255. if (macAddress == null && _receivedDataCount++ < 500) ParseMacAddress(value);
  256. smartBowHelper.aimHandler.OnDataReceived(bytes);
  257. }
  258. /// <summary>
  259. /// 六轴传感器时候使用的解析
  260. /// </summary>
  261. /// <param name="helper"></param>
  262. /// <param name="value"></param>
  263. /// <param name="characteristic"></param>
  264. void OnCharacteristicChanged6Axis(BluetoothHelper helper, byte[] value, BluetoothHelperCharacteristic characteristic)
  265. {
  266. if (helper != _bluetoothHelper) return;
  267. if (bluetoothStatus != BluetoothStatusEnum.Connected) return;
  268. byte[] bytes = value;
  269. if (macAddress == null && _receivedDataCount++ < 500) ParseMacAddress(value);
  270. //smartBowHelper.aimHandler.OnDataReceived(bytes);
  271. //转字符串后就是 Bat
  272. if (bytes.Length == 20 && bytes[19] == 0x0a
  273. //Bat
  274. && bytes[2] == 0x42 && bytes[3] == 0x61 && bytes[4] == 0x74) {
  275. //第一步 解析电量?
  276. string betty = System.Text.Encoding.ASCII.GetString(bytes);
  277. // SmartBowLogger.Log(this, BitConverter.ToString(bytes).Replace("-", ""));
  278. //SmartBowLogger.Log(this, "betty:" + betty);
  279. // 第二步:解析JSON字符串
  280. Newtonsoft.Json.Linq.JObject json = Newtonsoft.Json.Linq.JObject.Parse(betty);
  281. // 第三步:提取"Bat"的值
  282. int batValue = (int)json["Bat"];
  283. SmartBowLogger.Log(this, "Bat Value: " + batValue); // 输出: 100
  284. battery = batValue;
  285. }
  286. //传感器数据
  287. if (bytes.Length == 20 && bytes[0] == 0x7b && bytes[19] == 0x7d)
  288. {
  289. o06DOF.SixData sixData = sixAxisFusion.getSixAxisByBytes(bytes);
  290. Quaternion quaternion = sixAxisFusion.tranUpdateData(sixData);
  291. //输出欧拉角 pitch yaw roll
  292. smartBowHelper.InvokeOnSixAxisRotationUpdate(quaternion.eulerAngles);
  293. //smartBowHelper.InvokeOnAxisDataUpdateEvent(bytes);
  294. }
  295. }
  296. /// <summary>
  297. /// 重置6轴identify
  298. /// </summary>
  299. public void ResetSixAxisFusion() {
  300. if (sixAxisFusion != null) {
  301. sixAxisFusion.ResetToInitialRotation();
  302. }
  303. }
  304. /// <summary>
  305. /// pc调用
  306. /// </summary>
  307. /// <param name="deviceId"></param>
  308. /// <param name="value"></param>
  309. void OnCharacteristicChanged_windows(string deviceId, byte[] value)
  310. {
  311. if (sensorAxisType == SensorAxisType.SixAxisSensor)
  312. {
  313. //6轴指令
  314. OnCharacteristicChanged6Axis(null, value, null);
  315. }
  316. else
  317. {
  318. //九轴
  319. OnCharacteristicChanged(null, value, null);
  320. }
  321. }
  322. void OnScanEnded(BluetoothHelper helper, LinkedList<BluetoothDevice> nearbyDevices)
  323. {
  324. _ScanLocker.Remove(helper);
  325. if (helper != _bluetoothHelper) return;
  326. foreach (BluetoothDevice device in nearbyDevices)
  327. {
  328. if (isConnectName)
  329. {
  330. SmartBowLogger.Log(this, $"发现设备{device.DeviceName},is fileters empty:{ string.IsNullOrEmpty(filters)},name:{filters}");
  331. //if (device.DeviceName == deviceConfig.deviceName)
  332. //后续匹配名字 可以是多个设备
  333. string _filters = string.IsNullOrEmpty(filters) ? deviceConfig.deviceName : filters;
  334. if (_filters.Contains(device.DeviceName))
  335. {
  336. _bluetoothHelper.setDeviceName(device.DeviceName);
  337. _bluetoothHelper.Connect();
  338. SmartBowLogger.Log(this, $"Name匹配设备{device.DeviceName}");
  339. return;
  340. }
  341. }
  342. else
  343. {
  344. SmartBowLogger.Log(this, $"发现设备 {device.DeviceAddress},is connectMacStr:{ connectMacStr },DeviceAddress:{device.DeviceAddress}");
  345. //按mac地址匹配
  346. if (connectMacStr.Contains(device.DeviceAddress))
  347. {
  348. _bluetoothHelper.setDeviceName(device.DeviceName);
  349. _bluetoothHelper.setDeviceAddress(device.DeviceAddress);
  350. _bluetoothHelper.Connect();
  351. SmartBowLogger.Log(this, $"Mac匹配设备{device.DeviceAddress}");
  352. return;
  353. }
  354. }
  355. }
  356. SetStatus(BluetoothStatusEnum.None);
  357. smartBowHelper.InvokeOnBluetoothError(BluetoothError.ScanNotFoundTargetDevice, "扫描结束后未发现目标设备");
  358. }
  359. private float _lastWriteDataTime;
  360. bool WriteData(string data)
  361. {
  362. try
  363. {
  364. if (BluetoothWindows.IsWindows())
  365. {
  366. return _bluetoothWindows.Write(data);
  367. }
  368. BluetoothHelperCharacteristic c = new BluetoothHelperCharacteristic(_characteristicWrite.getName());
  369. c.setService(_bluetoothService.getName());
  370. _bluetoothHelper.WriteCharacteristic(c, data);
  371. _lastWriteDataTime = Time.realtimeSinceStartup;
  372. return true;
  373. }
  374. catch (Exception e)
  375. {
  376. Debug.LogError(e);
  377. return false;
  378. }
  379. }
  380. bool WriteByteData(byte[] data)
  381. {
  382. try
  383. {
  384. if (BluetoothWindows.IsWindows())
  385. {
  386. return _bluetoothWindows.WriteByte(data);
  387. }
  388. BluetoothHelperCharacteristic c = new BluetoothHelperCharacteristic(_characteristicWrite.getName());
  389. c.setService(_bluetoothService.getName());
  390. _bluetoothHelper.WriteCharacteristic(c, data);
  391. _lastWriteDataTime = Time.realtimeSinceStartup;
  392. return true;
  393. }
  394. catch (Exception e)
  395. {
  396. Debug.LogError(e);
  397. return false;
  398. }
  399. }
  400. public bool moduleInited;
  401. private string _connectedHandlerID = "";
  402. IEnumerator InitWhenConnected()
  403. {
  404. string myConnectedHandlerID = Guid.NewGuid().ToString();
  405. _connectedHandlerID = myConnectedHandlerID;
  406. yield return new WaitForSecondsRealtime(BluetoothWindows.IsWindows() ? 0.3f : 2.2f);
  407. Queue<string> cmds = new Queue<string>(new string[] { "M", "b", "b", "1" });
  408. while (cmds.Count > 0)
  409. {
  410. if (bluetoothStatus != BluetoothStatusEnum.Connected || myConnectedHandlerID != _connectedHandlerID) yield break;
  411. string cmd = cmds.Dequeue();
  412. WriteData(cmd);
  413. yield return new WaitForSecondsRealtime(0.3f);
  414. }
  415. if (bluetoothStatus != BluetoothStatusEnum.Connected || myConnectedHandlerID != _connectedHandlerID) yield break;
  416. StartCoroutine(LoopRequestBattery(myConnectedHandlerID));
  417. moduleInited = true;
  418. smartBowHelper.InvokeOnBluetoothModuleInited();
  419. }
  420. /// <summary>
  421. /// 初始化6轴指令
  422. /// </summary>
  423. /// <returns></returns>
  424. IEnumerator InitWhenConnected6Axis()
  425. {
  426. string myConnectedHandlerID = Guid.NewGuid().ToString();
  427. _connectedHandlerID = myConnectedHandlerID;
  428. yield return new WaitForSecondsRealtime(BluetoothWindows.IsWindows() ? 0.3f : 2.2f);
  429. Queue<string> cmds = new Queue<string>(new string[] { "M", "B", "B" });
  430. while (cmds.Count > 0)
  431. {
  432. if (bluetoothStatus != BluetoothStatusEnum.Connected || myConnectedHandlerID != _connectedHandlerID) yield break;
  433. string cmd = cmds.Dequeue();
  434. WriteData(cmd);
  435. yield return new WaitForSecondsRealtime(0.3f);
  436. }
  437. if (bluetoothStatus != BluetoothStatusEnum.Connected || myConnectedHandlerID != _connectedHandlerID) yield break;
  438. StartCoroutine(LoopRequestBattery6Axis(myConnectedHandlerID));
  439. moduleInited = true;
  440. smartBowHelper.InvokeOnBluetoothModuleInited();
  441. }
  442. private int _battery = 0;
  443. public int battery
  444. {
  445. get => _battery;
  446. set
  447. {
  448. _battery = value;
  449. //SmartBowLogger.Log(this, "Battery缓存成功");
  450. }
  451. }
  452. /// <summary>
  453. /// 九轴原本的连接电池指令
  454. /// </summary>
  455. /// <param name="myConnectedHandlerID"></param>
  456. /// <returns></returns>
  457. IEnumerator LoopRequestBattery(string myConnectedHandlerID)
  458. {
  459. while (bluetoothStatus == BluetoothStatusEnum.Connected && myConnectedHandlerID == _connectedHandlerID)
  460. {
  461. yield return new WaitForSecondsRealtime(10);
  462. AddCommandToQueue("b");
  463. }
  464. }
  465. /// <summary>
  466. /// 6轴的连接电池指令
  467. /// </summary>
  468. /// <param name="myConnectedHandlerID"></param>
  469. /// <returns></returns>
  470. IEnumerator LoopRequestBattery6Axis(string myConnectedHandlerID)
  471. {
  472. while (bluetoothStatus == BluetoothStatusEnum.Connected && myConnectedHandlerID == _connectedHandlerID)
  473. {
  474. yield return new WaitForSecondsRealtime(10);
  475. AddCommandToQueue("B");
  476. }
  477. }
  478. private List<string> _commands = new List<string>();
  479. void LoopHandleCommands()
  480. {
  481. if (bluetoothStatus != BluetoothStatusEnum.Connected || !moduleInited)
  482. {
  483. if (_commands.Count > 0) _commands.Clear();
  484. return;
  485. }
  486. if (Time.realtimeSinceStartup - _lastWriteDataTime < 0.2f) return;
  487. if (_commands.Count == 0) return;
  488. string cmd = _commands[0];
  489. _commands.RemoveAt(0);
  490. WriteData(cmd);
  491. }
  492. bool AddCommandToQueue(string cmd)
  493. {
  494. if (bluetoothStatus != BluetoothStatusEnum.Connected || !moduleInited) return false;
  495. //如果待插入的指令跟队尾的指令一样,就不要插入了,因为冗余的指令无意义
  496. if (_commands.Count > 0 && _commands[_commands.Count - 1].Equals(cmd)) return true;
  497. _commands.Add(cmd);
  498. return true;
  499. }
  500. public void ReplyInfraredShoot()
  501. {
  502. if (bluetoothStatus != BluetoothStatusEnum.Connected || !moduleInited) return;
  503. WriteData("I");
  504. }
  505. public void ReplyByte(byte[] value)
  506. {
  507. if (bluetoothStatus != BluetoothStatusEnum.Connected || !moduleInited) return;
  508. WriteByteData(value);
  509. }
  510. public bool RequestOpen9Axis()
  511. {
  512. return AddCommandToQueue("3");
  513. }
  514. public bool RequestClose9Axis()
  515. {
  516. return AddCommandToQueue("4");
  517. }
  518. public bool RequestOpenInfrared()
  519. {
  520. return AddCommandToQueue("w");
  521. }
  522. public bool RequestCloseInfrared()
  523. {
  524. return AddCommandToQueue("s");
  525. }
  526. void ParseMacAddress(byte[] bytes)
  527. {
  528. string mac = System.Text.Encoding.ASCII.GetString(bytes);
  529. if (mac != null) mac = mac.Trim();
  530. if (CheckIsMacValid(mac))
  531. {
  532. #region 根据aimDeviceInfo存在添加一个判断
  533. if (aimDeviceInfo != null) {
  534. //需要增加一个判断,判断是否对应的mac设备。不是需要进行重新连接
  535. if (!aimDeviceInfo.bInitMac)
  536. {
  537. SmartBowLogger.Log(this, "设置设备mac:" + mac);
  538. SetAimDeviceMac(mac);
  539. }
  540. else if (aimDeviceInfo.mac != mac)
  541. {
  542. SmartBowLogger.LogError(this, "设备不一样,断开连接");
  543. Disconnect();
  544. //抛出一个错误,给用户处理其他业务流程
  545. smartBowHelper.InvokeOnBluetoothError(BluetoothError.MacAddressAndDeviceMismatch, "验证设备MAC和记录的MAC不匹配!");
  546. return;
  547. }
  548. }
  549. #endregion
  550. macAddress = mac;
  551. SmartBowLogger.Log(this, "MacAddress解析成功");
  552. //获取MacAddress对应的校准记录
  553. string macXXX = macAddress;
  554. smartBowHelper.smartBowNetwork.GetCalibrateRecord(macXXX, (record) =>
  555. {
  556. if (macAddress != macXXX) return;
  557. smartBowHelper.aimHandler.ResumeCalibrateRecord(record);
  558. });
  559. }
  560. else SmartBowLogger.LogWarning(this, "MacAddress解析失败");
  561. }
  562. bool CheckIsMacValid(string mac)
  563. {
  564. if (mac == null) return false;
  565. if (!mac.StartsWith("{")) return false;
  566. if (!mac.EndsWith("}")) return false;
  567. if (!mac.Contains(":")) return false;
  568. char[] validChars = { '{', '}', ':', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
  569. foreach (var c in mac.ToCharArray())
  570. {
  571. if (Array.IndexOf(validChars, c) == -1) return false;
  572. }
  573. if (mac.Length != 19) return false;
  574. string macNoneFrame = mac.Substring(1, mac.Length - 2);
  575. string[] macNoneFrameSplits = macNoneFrame.Split(':');
  576. if (macNoneFrameSplits.Length != 6) return false;
  577. foreach (var item in macNoneFrameSplits)
  578. {
  579. if (item.Length != 2) return false;
  580. foreach (var c in item.ToCharArray())
  581. if (Array.IndexOf(validChars, c) < 3) return false;
  582. }
  583. return true;
  584. }
  585. #region 记录的设备处理部分
  586. //连接时候判断信息。存在对象则连接需要判断MAC
  587. //记录一个设备
  588. AimDeviceInfo aimDeviceInfo = null;
  589. //用户初始化一个保存数据的操作的id。
  590. //不设置情况下不给进行相关操作
  591. string keyPrefix = "aim-device-info-";
  592. string userTags = "";
  593. int deviceId = -1;
  594. //清空对应id的数据
  595. public void onClearAimDeviceInfoByDeviceId(string _userTags, int _deviceId)
  596. {
  597. string deviceInfo = PlayerPrefs.GetString(keyPrefix + _userTags + _deviceId, "");
  598. if (deviceInfo != "") {
  599. PlayerPrefs.DeleteKey(keyPrefix + _userTags + _deviceId);
  600. ResetAimDeviceInfoToNull();
  601. }
  602. }
  603. public AimDeviceInfo onGetAimDeviceInfos(string _userTags, int _deviceId)
  604. {
  605. OnGetAimDeviceInfo(_userTags, _deviceId);
  606. //SmartBowLogger.Log(this, $"onGetAimDeviceInfos[{JsonUtility.ToJson(aimDeviceInfo)}]");
  607. return aimDeviceInfo;
  608. }
  609. //根据设置的
  610. void OnGetAimDeviceInfo(string _userTags, int _deviceId)
  611. {
  612. string deviceInfo = PlayerPrefs.GetString(keyPrefix + _userTags + _deviceId, "");
  613. if (deviceInfo != "")
  614. {
  615. aimDeviceInfo = JsonUtility.FromJson<AimDeviceInfo>(deviceInfo);//这里的类是依据最外层{}决定的
  616. }
  617. }
  618. void OnSaveAimDeviceInfo(string _userTags, int _deviceId)
  619. {
  620. if (_userTags.Length == 0)
  621. {
  622. SmartBowLogger.LogError(this, $"存储标识不存在!");
  623. return;
  624. }
  625. SmartBowLogger.Log(this, $"OnSaveAimDeviceInfo [{JsonUtility.ToJson(aimDeviceInfo)}]");
  626. PlayerPrefs.SetString(keyPrefix + _userTags + _deviceId, JsonUtility.ToJson(aimDeviceInfo));
  627. }
  628. //连接蓝牙调用。连接时候创建一个连接信息,用于记录mac 是否要验证
  629. //传入一个id用于区分是哪个设备
  630. //bRecreateDeviceInfo 是否重新创建
  631. public void initAimDeviceInfo(string _userTags, int _deviceId, bool bRecreateDeviceInfo)
  632. {
  633. userTags = _userTags;
  634. deviceId = _deviceId;
  635. if (bRecreateDeviceInfo)
  636. {
  637. //直接覆盖设备信息
  638. onRecreateAimDeviceInfoById();
  639. }
  640. else
  641. {
  642. //获取设备信息。没有创建
  643. onCreateAimDeviceInfoById();
  644. }
  645. }
  646. //是否存在AimDeviceInfo,存在获取,不存在创建;
  647. void onCreateAimDeviceInfoById()
  648. {
  649. ResetAimDeviceInfoToNull();
  650. OnGetAimDeviceInfo(userTags, deviceId);
  651. if (aimDeviceInfo == null)
  652. {
  653. aimDeviceInfo = new AimDeviceInfo(deviceId);
  654. OnSaveAimDeviceInfo(userTags, deviceId);
  655. }
  656. }
  657. //直接覆盖新元素
  658. void onRecreateAimDeviceInfoById()
  659. {
  660. // 使用Lambda表达式删除特定条件的元素
  661. ResetAimDeviceInfoToNull();
  662. //添加一个新元素
  663. aimDeviceInfo = new AimDeviceInfo(deviceId);
  664. //更新信息
  665. OnSaveAimDeviceInfo(userTags, deviceId);
  666. }
  667. //APP连接需进行MAC地址的比对。
  668. void SetAimDeviceMac(string _mac)
  669. {
  670. aimDeviceInfo.setInitMac(_mac);
  671. OnSaveAimDeviceInfo(userTags, deviceId);
  672. }
  673. public void ResetAimDeviceInfoToNull()
  674. {
  675. aimDeviceInfo = null;
  676. }
  677. #endregion
  678. }
  679. #region 添加一个记录设备连接的信息,主要用于判断mac地址是否连接操作
  680. [Serializable]//需要在转换为json格式的类的上方添加序列化
  681. public class AimDeviceInfo
  682. {
  683. public int id; //区分用户设备对应的id
  684. public bool bInitMac = false; //是否初始化Mac
  685. public string mac; //记录当前
  686. public AimDeviceInfo(int _id)
  687. {
  688. this.id = _id;
  689. }
  690. public void setInitMac(string macTemp)
  691. {
  692. bInitMac = true;
  693. mac = macTemp;
  694. }
  695. public void resetInitMac()
  696. {
  697. bInitMac = false;
  698. mac = "";
  699. }
  700. }
  701. #endregion
  702. }