BluetoothAim_SDK.cs 28 KB

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