BluetoothAim_SDK.cs 30 KB

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