BluetoothAim.cs 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685
  1. using ArduinoBluetoothAPI;
  2. using System;
  3. using UnityEngine;
  4. using System.Collections.Generic;
  5. using UnityEngine.UI;
  6. using DG.Tweening;
  7. using SmartBowSDK;
  8. using System.Collections;
  9. using UnityEngine.SceneManagement;
  10. using BleWinHelper = SmartBowSDK_BleWinHelper.BleWinHelper;
  11. /* 蓝牙瞄准模块 */
  12. /* 管理1p和2p蓝牙连接,脚本外调用逻辑如果同时连接1p和2p设备,以前的逻辑还是以1p为主,如果只连2p,则使用2p数据*/
  13. public class BluetoothAim : MonoBehaviour
  14. {
  15. #region 2p蓝牙使用的是sdk,所以需要另外定义
  16. //2p时候过滤的名字
  17. readonly string targetDeviceName2P = "Bbow_20210501 | HOUYI Pro | Pistol | Pistol M9 | ARTEMIS Pro | Pistol M17 | Rifle M416";
  18. #endregion
  19. #region 弓箭蓝牙模块基本信息
  20. readonly string targetDeviceNameAxis = "Bbow_20210501 | ARTEMIS | HOUYI | HOUYI Pro | ARTEMIS Pro";
  21. readonly string targetDeviceName = "Bbow_20210501 | ARTEMIS Pro";//HOUYI Pro
  22. readonly string targetDeviceNameHOUYIPro = "HOUYI Pro";
  23. readonly string targetDeviceNameGun = "Pistol | Pistol M9 | Bbow_20210501";
  24. readonly string targetDeviceNameGun_M17 = "Pistol M17";
  25. readonly string targetDeviceNameGun_M416 = "Rifle M416";
  26. string targetDeviceService
  27. {
  28. get
  29. {
  30. if (CommonConfig.devicePlan == 0 || CommonConfig.devicePlan == 3)
  31. {
  32. #if UNITY_ANDROID
  33. return "0000fff0";
  34. #else
  35. return "fff0";
  36. #endif
  37. }
  38. return "6e400001";
  39. }
  40. }
  41. string targetDeviceCharacteristicWrite
  42. {
  43. get
  44. {
  45. if (CommonConfig.devicePlan == 0 || CommonConfig.devicePlan == 3)
  46. {
  47. #if UNITY_ANDROID
  48. return "0000fff2";
  49. #else
  50. return "fff2";
  51. #endif
  52. }
  53. return "6e400002";
  54. }
  55. }
  56. string targetDeviceCharacteristicNotify
  57. {
  58. get
  59. {
  60. if (CommonConfig.devicePlan == 0 || CommonConfig.devicePlan == 3)
  61. {
  62. #if UNITY_ANDROID
  63. return "0000fff1";
  64. #else
  65. return "fff1";
  66. #endif
  67. }
  68. return "6e400003";
  69. }
  70. }
  71. #endregion
  72. //当前选择的设备
  73. BluetoothPlayer currentBLEPlayer = BluetoothPlayer.FIRST_PLAYER;
  74. //1p蓝牙连接
  75. BluetoothHelper bluetoothHelper;
  76. BluetoothHelperCharacteristic characteristicWrite;
  77. BluetoothHelperService bluetoothService;
  78. string deviceName = "";
  79. bool canConnect = true;
  80. [SerializeField] Text textUI;
  81. public BluetoothStatusEnum status = BluetoothStatusEnum.Connect;
  82. int dataCount = 0;
  83. public bool hasData = false;
  84. public long hasDataTime;
  85. public static bool scanLock = false; //防止同时扫描冲突
  86. public static BluetoothAim ins;
  87. //根据设备情况来看是否需要解密,目前就是枪需要进行解密操作
  88. public bool NeedDecryption = false;
  89. public BluetoothWindows firstBluetoothWindows { get; set; }
  90. //首页初始化时候调用一次连接
  91. public bool bStartConnect = false;
  92. void Start()
  93. {
  94. ins = this;
  95. InitAutoDormancy();
  96. #if UNITY_STANDALONE_WIN || UNITY_EDITOR
  97. // new GameObject("BleUDP").AddComponent<BleUDP>();
  98. firstBluetoothWindows = new BluetoothWindows();
  99. firstBluetoothWindows.OnConnected = OnConnected_windows1;
  100. firstBluetoothWindows.OnConnectionFailed = OnConnectionFailed_windows1;
  101. firstBluetoothWindows.OnCharacteristicChanged = OnCharacteristicChanged_windows1;
  102. //window蓝牙连接
  103. if (currentBLEPlayer == BluetoothPlayer.FIRST_PLAYER)
  104. {
  105. Debug.Log("FIRST_PLAYER BleWinHelper.RegisterTo");
  106. BleWinHelper.RegisterTo(gameObject, firstBluetoothWindows, "1P");
  107. }
  108. #endif
  109. }
  110. void OnDestroy()
  111. {
  112. //删除ble。1p,2p 都删除
  113. DisconnectBleHelper();
  114. DisconnectSmartBowHelper2P();
  115. }
  116. /// <summary>
  117. /// 首页初始化的时候,如果是第一次。尝试连接蓝牙。只进行一次
  118. /// </summary>
  119. public void HomeViewConnectBLE()
  120. {
  121. if (bStartConnect) return;
  122. bStartConnect = true;
  123. //当已经连接过一把弓(1P)时,下一次打开 APP,1P 就自动处于连接的状态;用户只要打1.开 APP 和打开模块就可以自动连接,减少连接设备的操作。
  124. Debug.Log("[初始化自动连接蓝牙] 自动开始连接上一次连接的设备 1P?");
  125. AimHandler.ins.OnGetAimDeviceInfos();
  126. if (AimHandler.ins.aimDeviceInfos.arry.Count != 0)
  127. {
  128. //如果需要连接
  129. if (status != BluetoothStatusEnum.ConnectSuccess)
  130. {
  131. //setBLEPlayer(BluetoothPlayer.FIRST_PLAYER);
  132. Debug.Log("[初始化自动连接蓝牙] 当前选择的操作用户:" + getBLEPlayer());
  133. //AimHandler.ins.SetAimDeviceSelectIndex(0);
  134. //第一次进入从存储的资料获取 aimDeviceInfo
  135. AimHandler.ins.onCreateAimDeviceInfoById();
  136. DoConnect();
  137. }
  138. }
  139. }
  140. private bool userDoConnect = false;
  141. private bool doConnect = false;
  142. public Func<bool> action_DoConnectInterceptor;
  143. public void DoConnect()
  144. {
  145. if (action_DoConnectInterceptor != null)
  146. {
  147. if (action_DoConnectInterceptor.Invoke()) return;
  148. }
  149. if (status == BluetoothStatusEnum.Connect)
  150. {
  151. connectCanceled = false;
  152. userDoConnect = true;
  153. doConnect = true;
  154. SetStatus(BluetoothStatusEnum.Connecting);
  155. }
  156. else if (status == BluetoothStatusEnum.ConnectSuccess)
  157. {
  158. userDoConnect = false;
  159. doConnect = false;
  160. OnDisconnect();
  161. DisconnectBleHelper();
  162. //#if UNITY_STANDALONE_WIN || UNITY_EDITOR
  163. // //BleUDP.ins.Disconnect();
  164. // if (firstBluetoothWindows.Disconnect()) SetStatus(BluetoothStatusEnum.Connect);
  165. //#else
  166. // DisconnectBleHelper();
  167. //#endif
  168. }
  169. }
  170. //连接取消,退回登录时需要取消连接(扫描)
  171. [NonSerialized] public bool connectCanceled = false;
  172. void OnDisconnect()
  173. {
  174. curMac = null;
  175. dataCount = 0;
  176. hasData = false;
  177. canConnect = true;
  178. SetStatus(BluetoothStatusEnum.ConnectFail);
  179. BowCamera.isTouchMode = true;
  180. DestroyWhenDisconenct();
  181. if (AimHandler.ins) AimHandler.ins.SetMsOldDefault();
  182. }
  183. float notUserDoConnectTime = 0;
  184. void Update()
  185. {
  186. updateSmartBowHelper2P();
  187. if (userDoConnect && status == BluetoothStatusEnum.Connect)
  188. {
  189. DoConnect();
  190. }
  191. if (doConnect) Connect();
  192. //if (CommonConfig.StandaloneMode)
  193. //{
  194. // if (!userDoConnect && status == BluetoothStatusEnum.Connect)
  195. // {
  196. // if (notUserDoConnectTime == 0)
  197. // {
  198. // DoConnect();
  199. // notUserDoConnectTime = 0.1f;
  200. // }
  201. // else
  202. // {
  203. // notUserDoConnectTime += Time.deltaTime;
  204. // if (notUserDoConnectTime > 2.5f)
  205. // {
  206. // DoConnect();
  207. // notUserDoConnectTime = 0.1f;
  208. // }
  209. // }
  210. // }
  211. //}
  212. }
  213. void SetStatus(BluetoothStatusEnum statusValue)
  214. {
  215. status = statusValue;
  216. if (status == BluetoothStatusEnum.ConnectFail)
  217. {
  218. Sequence sequence = DOTween.Sequence();
  219. sequence.AppendInterval(2f);
  220. sequence.AppendCallback(delegate ()
  221. {
  222. if (status == BluetoothStatusEnum.ConnectFail)
  223. {
  224. status = BluetoothStatusEnum.Connect;
  225. }
  226. });
  227. sequence.SetUpdate(true);
  228. SimulateMouseController.ins?.SetBleConnected(false);
  229. }
  230. else if (status == BluetoothStatusEnum.ConnectSuccess)
  231. {
  232. SimulateMouseController.ins?.SetBleConnected(true);
  233. }
  234. }
  235. void DisconnectBleHelper()
  236. {
  237. if (BluetoothWindows.IsWindows())
  238. {
  239. if (firstBluetoothWindows.Disconnect())
  240. SetStatus(BluetoothStatusEnum.Connect);
  241. return;
  242. }
  243. if (bluetoothHelper != null) bluetoothHelper.Disconnect();
  244. }
  245. void DisconnectSmartBowHelper2P()
  246. {
  247. //2p
  248. if (smartBowHelper2P != null) smartBowHelper2P.Disconnect();
  249. }
  250. void Connect()
  251. {
  252. //if (BluetoothShoot.scanLock)
  253. //{
  254. // return;
  255. //}
  256. if (!canConnect)
  257. {
  258. return;
  259. }
  260. doConnect = false;
  261. doConnect2P = false;
  262. scanLock = true;
  263. canConnect = false;
  264. _scanCanRetryCount = 4;
  265. SetStatus(BluetoothStatusEnum.Connecting);
  266. #if UNITY_STANDALONE_WIN || UNITY_EDITOR
  267. //ConnectBleByUDP();
  268. firstBluetoothWindows.Connect();
  269. #else
  270. ConnectBleHelper();
  271. #endif
  272. }
  273. int _scanCanRetryCount = 4;
  274. void ConnectBleHelper()
  275. {
  276. #if UNITY_ANDROID
  277. PopupMgr.ins.ClearAllTip();
  278. if (BluetoothHelperAndroid.IsBluetoothEnabled() == false)
  279. {
  280. Debug.Log("BluetoothHelperAndroid.IsBluetoothEnabled():" + BluetoothHelperAndroid.IsBluetoothEnabled());
  281. HandleConnectException(TextAutoLanguage2.GetTextByKey("ble-exception1"));
  282. return;
  283. }
  284. if (BluetoothHelperAndroid.RequestBluetoothPermissions(ConnectBleHelper, (permission) =>
  285. {
  286. Debug.Log("permission ==== :" + permission);
  287. if (permission.Contains("LOCATION"))
  288. {
  289. HandleConnectException(TextAutoLanguage2.GetTextByKey("ble-exception2"));
  290. }
  291. else if (permission.Contains("BLUETOOTH"))
  292. {
  293. HandleConnectException(TextAutoLanguage2.GetTextByKey("ble-exception3"));
  294. }
  295. })) return;
  296. #endif
  297. try
  298. {
  299. BluetoothHelper.BLE = true;
  300. bluetoothHelper = BluetoothHelper.GetNewInstance();
  301. bluetoothHelper.OnConnected += (BluetoothHelper helper) =>
  302. {
  303. Log("连接成功\n" + helper.getDeviceName());
  304. SetStatus(BluetoothStatusEnum.ConnectSuccess);
  305. SetMainConnectDeviceType();
  306. if (connectCanceled)
  307. {
  308. Debug.Log("ble connectCanceled");
  309. DoConnect();
  310. return;
  311. }
  312. BowCamera.isTouchMode = false;
  313. foreach (BluetoothHelperService service in helper.getGattServices())
  314. {
  315. if (service.getName().ToLower().StartsWith(targetDeviceService))
  316. {
  317. bluetoothService = service;
  318. foreach (BluetoothHelperCharacteristic characteristic in service.getCharacteristics())
  319. {
  320. if (characteristic.getName().ToLower().StartsWith(targetDeviceCharacteristicWrite))
  321. {
  322. characteristicWrite = characteristic;
  323. }
  324. else if (characteristic.getName().ToLower().StartsWith(targetDeviceCharacteristicNotify))
  325. {
  326. BluetoothHelperCharacteristic ch = new BluetoothHelperCharacteristic(characteristic.getName());
  327. ch.setService(bluetoothService.getName());
  328. bluetoothHelper.Subscribe(ch);
  329. }
  330. }
  331. }
  332. }
  333. // CallDelay(1, OpenInfrared);
  334. // CallDelay(2, OpenReceiveData);
  335. // CallDelay(3, RequestBattery);
  336. if (CommonConfig.EnableDecryption && NeedDecryption)
  337. {
  338. // 这里验证指令,开始请求授权
  339. // 启动轮询协程
  340. StartCoroutine(PollingCoroutine());
  341. }
  342. else
  343. {
  344. //除了pc,Android 直接连接
  345. CallDelay(2, () =>
  346. {
  347. if (status != BluetoothStatusEnum.ConnectSuccess) return;
  348. InitWhenConenct();
  349. //if (CommonConfig.StandaloneMode)
  350. //{
  351. // if (UnityEngine.SceneManagement.SceneManager.GetActiveScene().name == "Home"
  352. // && PersistenHandler.ins.menuBackCtr.views.Count == 0
  353. // && !FindObjectOfType<NewUserGuider>())
  354. // {
  355. // ViewMgr.Instance.ShowView<GameStartView>();
  356. // }
  357. //}
  358. });
  359. }
  360. };
  361. bluetoothHelper.OnConnectionFailed += (BluetoothHelper helper) =>
  362. {
  363. Log("连接失败\n" + helper.getDeviceName());
  364. OnDisconnect();
  365. };
  366. bluetoothHelper.OnCharacteristicChanged += (helper, value, characteristic) =>
  367. {
  368. OnCharacteristicChanged(helper, value, characteristic);
  369. };
  370. bluetoothHelper.OnScanEnded += (BluetoothHelper helper, LinkedList<BluetoothDevice> nearbyDevices) =>
  371. {
  372. scanLock = false;
  373. if (connectCanceled)
  374. {
  375. userDoConnect = false;
  376. canConnect = true;
  377. status = BluetoothStatusEnum.Connect;
  378. Debug.Log("ble connectCanceled");
  379. return;
  380. }
  381. foreach (BluetoothDevice device in nearbyDevices)
  382. {
  383. Log("发现设备 " + device.DeviceName);
  384. if (AimHandler.ins.aimDeviceInfo.type == (int)AimDeviceType.HOUYIPRO)
  385. { //需要判断是否是红外弓箭
  386. if (TryConnectDevice(targetDeviceNameHOUYIPro, device.DeviceName, "HOUYIPRO")) return;
  387. }
  388. else if (AimHandler.ins.aimDeviceInfo.type == (int)AimDeviceType.ARTEMISPRO)
  389. { //需要判断是否是ARTEMISPro弓箭
  390. if (TryConnectDevice(targetDeviceName, device.DeviceName, "ARTEMISPRO")) return;
  391. }
  392. else if (AimHandler.ins.aimDeviceInfo.type == (int)AimDeviceType.Gun)
  393. {
  394. if (TryConnectDevice(targetDeviceNameGun, device.DeviceName, "Pistol")) return;
  395. }
  396. else if (AimHandler.ins.aimDeviceInfo.type == (int)AimDeviceType.PistolM17)
  397. {
  398. if (TryConnectDevice(targetDeviceNameGun_M17, device.DeviceName, "PistolM17")) return;
  399. }
  400. else if (AimHandler.ins.aimDeviceInfo.type == (int)AimDeviceType.RifleM416)
  401. {
  402. if (TryConnectDevice(targetDeviceNameGun_M416, device.DeviceName, "RifleM416")) return;
  403. }
  404. else
  405. { //其余的九轴连接
  406. //不允许匹配HOUYIPRO,因为这个没有九轴 targetDeviceName { Bbow_20210501 }
  407. //if (targetDeviceName.Contains(device.DeviceName))
  408. //{
  409. // BLEConnectByName(device.DeviceName);
  410. // Log("匹配普通设备设备 " + device.DeviceName);
  411. // return;
  412. //}
  413. if (TryConnectDevice(targetDeviceNameAxis, device.DeviceName, device.DeviceName)) return;
  414. }
  415. }
  416. if (_scanCanRetryCount > 0)
  417. {
  418. _scanCanRetryCount--;
  419. scanLock = true;
  420. ConnectBleHelper();
  421. }
  422. else
  423. {
  424. userDoConnect = false;
  425. canConnect = true;
  426. Log("没有发现设备");
  427. TextAutoLanguage2.GetTextByKey("ble-dev-notfound");
  428. SetStatus(BluetoothStatusEnum.ConnectFail);
  429. }
  430. };
  431. bluetoothHelper.ScanNearbyDevices();
  432. Log("正在扫描设备");
  433. }
  434. catch (Exception e)
  435. {
  436. Debug.LogError(e);
  437. HandleConnectException(TextAutoLanguage2.GetTextByKey("ble-please-open-ble"));
  438. }
  439. }
  440. /// <summary>
  441. /// 精确匹配,大小写敏感,多设备名字用 " | " 分隔
  442. /// </summary>
  443. /// <param name="filterNames">过滤字符串</param>
  444. /// <param name="deviceName">真实连接名字</param>
  445. /// <param name="deviceTypeName">日志名字</param>
  446. /// <returns></returns>
  447. private bool TryConnectDevice(string filterNames, string deviceName, string deviceTypeName)
  448. {
  449. if (string.IsNullOrWhiteSpace(filterNames)) return false;
  450. string[] filterArray = filterNames.Split('|'); // 支持多个名字
  451. foreach (var f in filterArray)
  452. {
  453. if (string.Equals(f.Trim(), deviceName.Trim(), StringComparison.OrdinalIgnoreCase))
  454. {
  455. BLEConnectByName(deviceName);
  456. Log($"匹配设备 {deviceTypeName}: {deviceName}");
  457. return true;
  458. }
  459. }
  460. return false;
  461. }
  462. void BLEConnectByName(string name)
  463. {
  464. deviceName = name;
  465. bluetoothHelper.setDeviceName(deviceName);
  466. bluetoothHelper.Connect();
  467. }
  468. void HandleConnectException(string errorText)
  469. {
  470. scanLock = false;
  471. canConnect = true;
  472. // SetStatus(BluetoothStatusEnum.ConnectFail);
  473. status = BluetoothStatusEnum.Connect;
  474. userDoConnect = false;
  475. PopupMgr.ins.ShowTip(errorText);
  476. }
  477. // 协程来处理轮询
  478. // 目前仅手枪支持该指令。
  479. // 调用 AUTHOR_SendReq 方法,传递系统Tick值(在这里用一个示例值)
  480. private bool isPolling = false;
  481. private int PollingCoroutineCount = 4;
  482. private IEnumerator PollingCoroutine()
  483. {
  484. // 发送请求
  485. // SendEncrypt();
  486. // 设置轮询标志
  487. isPolling = true;
  488. PollingCoroutineCount = 4;
  489. uint systemTick = (uint)DateTime.Now.Ticks;
  490. while (isPolling)
  491. {
  492. // 等待一秒
  493. yield return new WaitForSeconds(1f);
  494. SendEncrypt(systemTick);
  495. PollingCoroutineCount--;
  496. }
  497. }
  498. /// <summary>
  499. /// 1、加密字节由系统生成的随机码加密而成;
  500. /// 2、蓝牙每次断开并重新连接后,会重新生成随机加密值;
  501. /// 3、当设备未发送正确的解密信息时,APP会每秒发送1次请求,直到解密成功。
  502. /// </summary>
  503. /// <param name="systemTick"></param>
  504. private void SendEncrypt(uint systemTick)
  505. {
  506. byte[] sendByte = BluetoothDecryptor.AUTHOR_SendReq(systemTick);
  507. Debug.Log("请求sendByte:" + BitConverter.ToString(sendByte));
  508. WriteByteData(sendByte);
  509. }
  510. // 模拟从硬件读取数据
  511. public void StopEncrypt()
  512. {
  513. isPolling = false;
  514. }
  515. void ConnectBleByUDP()
  516. {
  517. try
  518. {
  519. BleUDP.ins.OnConnected = () =>
  520. {
  521. Log("连接成功\n" + deviceName);
  522. SetStatus(BluetoothStatusEnum.ConnectSuccess);
  523. BowCamera.isTouchMode = false;
  524. InitWhenConenct();
  525. };
  526. BleUDP.ins.OnConnectionFailed = () =>
  527. {
  528. Log("连接失败\n" + deviceName);
  529. OnDisconnect();
  530. };
  531. BleUDP.ins.OnCharacteristicChanged = (byte[] value) =>
  532. {
  533. //if (!hasData) {
  534. // hasDataTime = JCUnityLib.TimeUtils.GetTimestamp();
  535. // UploadMacAddress(value);
  536. //}
  537. //hasData = true;
  538. if (status != BluetoothStatusEnum.ConnectSuccess) return;
  539. if (!hasData)
  540. {
  541. hasData = true;
  542. hasDataTime = JCUnityLib.TimeUtils.GetTimestamp();
  543. }
  544. dataCount++;
  545. if (curMac == null && dataCount < 500)
  546. {
  547. UploadMacAddress(value);
  548. }
  549. byte[] bytes = value;
  550. // Log(String.Join(",", bytes));
  551. BluetoothClient.UploadData(0, bytes);
  552. if (AimHandler.ins)
  553. {
  554. AimHandler.ins.OnDataReceived(bytes);
  555. }
  556. };
  557. BleUDP.ins.OnScanEnded = () =>
  558. {
  559. scanLock = false;
  560. deviceName = targetDeviceName;
  561. BleUDP.ins.Connect();
  562. Log("发现设备\n" + deviceName);
  563. };
  564. BleUDP.ins.ScanNearbyDevices();
  565. }
  566. catch (Exception e)
  567. {
  568. Debug.LogError(e.Message);
  569. Debug.LogError(e.StackTrace);
  570. scanLock = false;
  571. canConnect = true;
  572. SetStatus(BluetoothStatusEnum.ConnectFail);
  573. }
  574. }
  575. #region 自动进入/退出休眠状态, 这里做程指令发送队列,为了控制连续发送指令的间隔,避免硬件收不到或处理不过来
  576. class CmdToSend
  577. {
  578. public string[] cmds;
  579. public Action onComplete;
  580. public Func<bool> canDo;
  581. public CmdToSend(string[] cmds, Action onComplete, Func<bool> canDo)
  582. {
  583. this.cmds = cmds;
  584. this.onComplete = onComplete;
  585. this.canDo = canDo;
  586. }
  587. }
  588. Queue<CmdToSend> cmdWaitingList = new Queue<CmdToSend>();
  589. bool isSendCmdLocked = false;
  590. bool canAutoDormancy = false;
  591. bool isStartUp = false;
  592. JCUnityLib.CountLock needModularAwake = new JCUnityLib.CountLock();
  593. void CheckAndStartUp()
  594. {
  595. if (needModularAwake.IsLocked())
  596. {
  597. StartUp();
  598. }
  599. else
  600. {
  601. Dormancy();
  602. }
  603. }
  604. void InitAutoDormancy()
  605. {
  606. // GlobalEventCenter.ins.onGameSceneLoad += () => {
  607. // needModularAwake.Lock();
  608. // CheckAndStartUp();
  609. // };
  610. // GlobalEventCenter.ins.onGameSceneDestroy += () => {
  611. // needModularAwake.Unlock();
  612. // CheckAndStartUp();
  613. // };
  614. // GlobalEventCenter.ins.onSimulateMouseAwakeChanged += (waked) => {
  615. // if (waked) needModularAwake.Lock();
  616. // else needModularAwake.Unlock();;
  617. // CheckAndStartUp();
  618. // };
  619. // GlobalEventCenter.ins.onDeviceCalibrateViewAwakeChanged += (waked) => {
  620. // if (waked) needModularAwake.Lock();
  621. // else needModularAwake.Unlock();;
  622. // CheckAndStartUp();
  623. // };
  624. //暂时关闭自动休眠,默认是需要模块保持激活
  625. needModularAwake.Lock();
  626. }
  627. void InitWhenConenct()
  628. {
  629. canAutoDormancy = true;
  630. List<string> cmds = new List<string>();
  631. cmds.Add("M"); //获取Mac地址
  632. cmds.Add("I"); //获取设备信息
  633. cmds.Add("b"); //确保开启stm32
  634. cmds.Add("b"); //获取初始电量
  635. cmds.Add("1"); //开启发送逻辑
  636. Action onComplete = null;
  637. if (needModularAwake.IsLocked())
  638. {
  639. cmds.Add("w"); //红外灯开启
  640. cmds.Add("3"); //九轴开启
  641. onComplete = () =>
  642. {
  643. isStartUp = true;
  644. };
  645. }
  646. else
  647. {
  648. cmds.Add("s"); //红外灯关闭
  649. cmds.Add("S"); //Stm32关闭
  650. cmds.Add("4"); //九轴关闭
  651. onComplete = () =>
  652. {
  653. isStartUp = false;
  654. };
  655. }
  656. SendCDM(null, onComplete, cmds.ToArray());
  657. }
  658. void DestroyWhenDisconenct()
  659. {
  660. canAutoDormancy = false;
  661. sendCMD_CheckAndDoStop(null);
  662. }
  663. //启动
  664. void StartUp()
  665. {
  666. SendCDM(() =>
  667. {
  668. return !isStartUp;
  669. }, () =>
  670. {
  671. isStartUp = true;
  672. }, "b", "w", "3");
  673. }
  674. //休眠
  675. void Dormancy()
  676. {
  677. SendCDM(() =>
  678. {
  679. return isStartUp;
  680. }, () =>
  681. {
  682. isStartUp = false;
  683. }, "4", "s", "S");
  684. }
  685. void SendCDM(Func<bool> canDo, Action onComplete, params string[] cmds)
  686. {
  687. CmdToSend cmdToSend = new CmdToSend(cmds, onComplete, canDo);
  688. if (isSendCmdLocked)
  689. {
  690. cmdWaitingList.Enqueue(cmdToSend);
  691. return;
  692. }
  693. sendCMD_NotCheck(cmdToSend);
  694. }
  695. void sendCMD_NotCheck(CmdToSend cmdToSend)
  696. {
  697. if (cmdToSend.canDo != null && !cmdToSend.canDo.Invoke())
  698. {
  699. sendCMD_CheckNext();
  700. return;
  701. }
  702. isSendCmdLocked = true;
  703. Sequence sequence = DOTween.Sequence();
  704. sequence.PrependInterval(0.3f);
  705. foreach (var cmd in cmdToSend.cmds)
  706. {
  707. sequence.AppendCallback(() =>
  708. {
  709. bool stopped = sendCMD_CheckAndDoStop(sequence);
  710. if (!stopped) WriteData(cmd);
  711. });
  712. sequence.AppendInterval(0.5f);
  713. }
  714. sequence.AppendCallback(() =>
  715. {
  716. bool stopped = sendCMD_CheckAndDoStop(sequence);
  717. if (!stopped)
  718. {
  719. isSendCmdLocked = false;
  720. cmdToSend.onComplete?.Invoke();
  721. sendCMD_CheckNext();
  722. }
  723. });
  724. sequence.SetUpdate(true);
  725. }
  726. void sendCMD_CheckNext()
  727. {
  728. if (cmdWaitingList.Count <= 0) return;
  729. CmdToSend cmdToSend = cmdWaitingList.Dequeue();
  730. sendCMD_NotCheck(cmdToSend);
  731. }
  732. bool sendCMD_CheckAndDoStop(Sequence sequence)
  733. {
  734. if (canAutoDormancy) return false;
  735. isStartUp = false;
  736. isSendCmdLocked = false;
  737. cmdWaitingList.Clear();
  738. if (sequence != null) sequence.Kill();
  739. return true;
  740. }
  741. #endregion
  742. public void RequestBattery()
  743. {
  744. if (!isStartUp) return;
  745. if (isSendCmdLocked) return;
  746. WriteData("b");
  747. }
  748. /// <summary>
  749. /// 获取设备信息 手枪、HOUYI Pro 和 ARTEMIS Pro
  750. /// </summary>
  751. public void RequestDeviceInfo()
  752. {
  753. if (isSendCmdLocked) return;
  754. WriteData("I");
  755. }
  756. /// <summary>
  757. /// 旧的红外射箭指令
  758. /// </summary>
  759. public void ReplyInfraredShoot()
  760. {
  761. if (isSendCmdLocked) return;
  762. WriteData("I");
  763. }
  764. void CallDelay(float delayTime, TweenCallback callback)
  765. {
  766. Sequence sequence = DOTween.Sequence();
  767. sequence.PrependInterval(delayTime).AppendCallback(callback);
  768. sequence.SetUpdate(true);
  769. }
  770. public void WriteData(string data)
  771. {
  772. //Debug.Log("WriteData:" + data);
  773. #if UNITY_STANDALONE_WIN || UNITY_EDITOR
  774. //BleUDP.ins.SendMsg(data);
  775. firstBluetoothWindows.Write(data);
  776. #else
  777. if (DebugDeviceCMD.ins) DebugDeviceCMD.ins.ShowCMD(data);
  778. BluetoothHelperCharacteristic ch = new BluetoothHelperCharacteristic(characteristicWrite.getName());
  779. ch.setService(bluetoothService.getName());
  780. bluetoothHelper.WriteCharacteristic(ch, data);
  781. #endif
  782. }
  783. public void WriteByteData(byte[] data)
  784. {
  785. #if UNITY_STANDALONE_WIN || UNITY_EDITOR
  786. firstBluetoothWindows.WriteByte(data);
  787. #else
  788. BluetoothHelperCharacteristic ch = new BluetoothHelperCharacteristic(characteristicWrite.getName());
  789. ch.setService(bluetoothService.getName());
  790. bluetoothHelper.WriteCharacteristic(ch, data);
  791. #endif
  792. }
  793. void Log(string text)
  794. {
  795. if (textUI)
  796. {
  797. textUI.text = text;
  798. }
  799. Debug.Log(string.Format("[{0}]{1}", typeof(BluetoothAim).Name, text));
  800. }
  801. [NonSerialized] public string curMac;
  802. void UploadMacAddress(byte[] bytes)
  803. {
  804. string mac = System.Text.Encoding.ASCII.GetString(bytes);
  805. if (mac != null) mac = mac.Trim();
  806. if (CheckIsMacValid(mac))
  807. {
  808. SideTipView.ShowTip("Mac获取成功:" + mac, Color.white);
  809. //需要增加一个判断,判断是否对应的mac设备。不是需要进行重新连接
  810. if (!AimHandler.ins.aimDeviceInfo.bInitMac)
  811. {
  812. Debug.Log("设置设备mac:" + mac);
  813. AimHandler.ins.SetAimDeviceMac(mac);
  814. }
  815. else if (AimHandler.ins.aimDeviceInfo.mac != mac)
  816. {
  817. Debug.Log("设备不一样,断开连接");
  818. DoConnect();
  819. //延迟一点时间后重新触发扫描
  820. CallDelay(4, () =>
  821. {
  822. Debug.Log("CallDelay 重新连接");
  823. DoConnect();
  824. });
  825. return;
  826. }
  827. curMac = mac;
  828. LoginMgr.myUserInfo.mac = mac;
  829. UserComp.Instance.saveMac();
  830. }
  831. //else {
  832. // SideTipView.ShowTip("Mac获取失败", Color.yellow);
  833. //}
  834. }
  835. bool CheckIsMacValid(string mac)
  836. {
  837. if (mac == null) return false;
  838. if (!mac.StartsWith("{")) return false;
  839. if (!mac.EndsWith("}")) return false;
  840. if (!mac.Contains(":")) return false;
  841. char[] validChars = { '{', '}', ':', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
  842. foreach (var c in mac.ToCharArray())
  843. {
  844. if (Array.IndexOf(validChars, c) == -1) return false;
  845. }
  846. if (mac.Length != 19) return false;
  847. string macNoneFrame = mac.Substring(1, mac.Length - 2);
  848. string[] macNoneFrameSplits = macNoneFrame.Split(':');
  849. if (macNoneFrameSplits.Length != 6) return false;
  850. foreach (var item in macNoneFrameSplits)
  851. {
  852. if (item.Length != 2) return false;
  853. foreach (var c in item.ToCharArray())
  854. if (Array.IndexOf(validChars, c) < 3) return false;
  855. }
  856. return true;
  857. }
  858. #region 2p蓝牙部分,使用了SmartBowSDK
  859. //2p蓝牙连接 使用 SmartBowSDK
  860. SmartBowHelper smartBowHelper2P;
  861. //陀螺仪校准进度
  862. public int smartBowHelper2_Progress { get => (int)(smartBowHelper2P.GetGyrProgress() * 100); }
  863. bool doConnect2P = false;
  864. bool userDoConnect2P = false;
  865. int _scanCanRetryCount2P = 4;
  866. bool canConnect2P = true;
  867. public bool bNoNeedToReconnect { get; set; } = true;//是否需要重连
  868. bool lerpForRotation2P = true;
  869. float lerpTimeRate2P = 7;
  870. private Quaternion newRotation2P = Quaternion.identity;
  871. //数据存储标识
  872. string userTags = "smartbow";
  873. int deviceId2 = 2;
  874. public void onCreateSmartBowHelper2P()
  875. {
  876. smartBowHelper2P = SmartBowHelper.NewInstance();
  877. smartBowHelper2P.SetFilters(targetDeviceName2P);
  878. smartBowHelper2P.OnBluetoothModuleInited += () =>
  879. {
  880. Debug.Log("OnBluetoothModuleInited");
  881. //判断是否是同一个mac
  882. //需要增加一个判断,判断是否对应的mac设备。不是需要进行重新连接
  883. string mac = smartBowHelper2P.GetMacAddress();
  884. if (!AimHandler.ins.aimDeviceInfo.bInitMac)
  885. {
  886. Debug.Log("smartBowHelper2P 设置设备mac:" + mac);
  887. AimHandler.ins.SetAimDeviceMac(mac);
  888. }
  889. else if (AimHandler.ins.aimDeviceInfo.mac != mac)
  890. {
  891. Debug.Log("设备不一样,断开连接");
  892. DoConnect2P();
  893. //延迟一点时间后重新触发扫描
  894. CallDelay(4, () =>
  895. {
  896. Debug.Log("CallDelay 重新连接");
  897. DoConnect2P();
  898. });
  899. return;
  900. }
  901. UpdateConnectText();
  902. smartBowHelper2P.StartRotationSensor();
  903. smartBowHelper2P.StartShootingSensor();
  904. //if (SB_EventSystem.ins)
  905. //{
  906. // //唤起/隐藏虚拟鼠标
  907. // SB_EventSystem.ins.AwakenSimulateMouse();
  908. //}
  909. };
  910. smartBowHelper2P.OnBluetoothError += (error, message) =>
  911. {
  912. Debug.Log("smartBowHelper2P error:" + error);
  913. if (error == BluetoothError.ScanNotFoundTargetDevice)
  914. {
  915. scanLock = false;
  916. PopupMgr.ins.ShowTip("连接失败,未发现目标设备!");
  917. if (_scanCanRetryCount2P > 0)
  918. {
  919. _scanCanRetryCount2P--;
  920. scanLock = true;
  921. ConnectSmartBowHelper2P();
  922. }
  923. else
  924. {
  925. userDoConnect2P = false;
  926. canConnect2P = true;
  927. Log("没有发现设备");
  928. TextAutoLanguage2.GetTextByKey("ble-dev-notfound");
  929. }
  930. return;
  931. }
  932. PopupMgr.ins.ShowTip(message);
  933. };
  934. smartBowHelper2P.OnBluetoothStatusChanged += (oldStatus, newStatus) =>
  935. {
  936. UpdateConnectText();
  937. };
  938. smartBowHelper2P.OnRotationUpdate += (r) =>
  939. {
  940. newRotation2P = r;
  941. //GameController.ins.aimCrossHairs[playerIndex].UpdatePositionByModuleRotation(r);
  942. //if (SB_EventSystem.ins && SB_EventSystem.ins.simulateMouseIsAwaked) SB_EventSystem.ins.MoveSimulateMouse(r);
  943. };
  944. smartBowHelper2P.OnShooting += OnShot2P;
  945. smartBowHelper2P.OnFunctionKeyPress += () =>
  946. {
  947. //如果是双人场景,触发提示
  948. if (SceneManager.GetActiveScene().name == "GameDouble")
  949. {
  950. if (GameObject.Find("AutoResetViewNewRight")) return;
  951. GameObject resetView = Instantiate(Resources.Load<GameObject>("AutoResetViewNew"));
  952. resetView.name = "AutoResetViewNewRight";
  953. AutoResetViewNew autoResetViewNewScript = resetView.GetComponent<AutoResetViewNew>();
  954. autoResetViewNewScript.setTextKey("new-user-guider_tip_视角归位-瞄准-infraredD");
  955. autoResetViewNewScript.setPosRight();
  956. autoResetViewNewScript.action_OnDestroy += () =>
  957. {
  958. smartBowHelper2P.ResetAim();
  959. };
  960. }
  961. else if (SceneManager.GetActiveScene().name == "InfraredGameDouble" || SceneManager.GetActiveScene().name == "WildAttackDouble")
  962. {
  963. if (GameObject.Find("AutoResetViewNewRight")) return;
  964. GameObject resetView = Instantiate(Resources.Load<GameObject>("AutoResetViewNew"));
  965. resetView.name = "AutoResetViewNewRight";
  966. AutoResetViewNew autoResetViewNewScript = resetView.GetComponent<AutoResetViewNew>();
  967. autoResetViewNewScript.setTextKey("new-user-guider_tip_视角归位-瞄准-infraredD");
  968. autoResetViewNewScript.setPosRight();
  969. autoResetViewNewScript.action_OnDestroy += () =>
  970. {
  971. if (SceneManager.GetActiveScene().name == "InfraredGameDouble")
  972. {
  973. InfraredDemo._ins?.SetAdjustPointsOffset(PlayerType.SecondPlayer);
  974. }
  975. else if (SceneManager.GetActiveScene().name == "WildAttackDouble")
  976. {
  977. WildAttack.GameMananger.GetInstance().ResetAim(WildAttack.PlayerTypeEnum.Second);
  978. }
  979. };
  980. }
  981. //else if (SceneManager.GetActiveScene().name.Equals("WildAttackDouble"))
  982. //{
  983. // //双人场景直接校准2P
  984. // WildAttack.GameMananger.GetInstance().ResetAim(WildAttack.PlayerTypeEnum.Second);
  985. //}
  986. else
  987. {
  988. smartBowHelper2P.ResetAim();
  989. }
  990. };
  991. //#if UNITY_STANDALONE_WIN || UNITY_EDITOR
  992. // //用户2window连接 BluetoothWindows.IsWindows() &&
  993. // if (currentBLEPlayer == BluetoothPlayer.SECONDE_PLAYER)
  994. // {
  995. // Debug.Log("SECONDE_PLAYER BleWinHelper.RegisterTo");
  996. // BleWinHelper com = BleWinHelper.RegisterTo(smartBowHelper2P.gameObject, smartBowHelper2P.CreateBluetoothWindows(), "2P");
  997. // }
  998. //#endif
  999. }
  1000. void OnShot2P(float speed)
  1001. {
  1002. if (SceneManager.GetActiveScene().name.Equals("WildAttackDouble"))
  1003. {
  1004. WildAttack.SmartBowController.Instance.OnShooting2P(speed);
  1005. }
  1006. else
  1007. {
  1008. if (GameController.ins.GetArmBowDoublePlayer(PlayerType.SecondPlayer) != null)
  1009. {
  1010. //本地双人模式下处理2P ,1P在 ShootCheck 类处理
  1011. GameController.ins.GetArmBowDoublePlayer(PlayerType.SecondPlayer).ADS_fire(true, speed);
  1012. }
  1013. }
  1014. }
  1015. void UpdateConnectText()
  1016. {
  1017. var newStatus = smartBowHelper2P.GetBluetoothStatus();
  1018. if (newStatus == SmartBowSDK.BluetoothStatusEnum.None)
  1019. {
  1020. if (GameController.ins)
  1021. {
  1022. GameController.ins.GetBowCameraDoublePlayer(PlayerType.SecondPlayer).isTouchMode = true;
  1023. }
  1024. Debug.Log("<color=blue>未连接</color>(点击连接)");
  1025. if (!bNoNeedToReconnect) return;
  1026. scanLock = false;
  1027. if (_scanCanRetryCount2P > 0)
  1028. {
  1029. _scanCanRetryCount2P--;
  1030. scanLock = true;
  1031. ConnectSmartBowHelper2P();
  1032. }
  1033. else
  1034. {
  1035. userDoConnect2P = false;
  1036. canConnect2P = true;
  1037. Log("没有发现设备");
  1038. PopupMgr.ins.ShowTip("连接失败,未发现目标设备!");
  1039. TextAutoLanguage2.GetTextByKey("ble-dev-notfound");
  1040. }
  1041. }
  1042. else if (newStatus == SmartBowSDK.BluetoothStatusEnum.Connecting)
  1043. {
  1044. Debug.Log("<color=#FF670D>连接中</color>");
  1045. if (GameController.ins)
  1046. {
  1047. GameController.ins.GetBowCameraDoublePlayer(PlayerType.SecondPlayer).isTouchMode = false;
  1048. }
  1049. }
  1050. else if (newStatus == SmartBowSDK.BluetoothStatusEnum.Connected)
  1051. {
  1052. if (GameController.ins)
  1053. {
  1054. GameController.ins.GetBowCameraDoublePlayer(PlayerType.SecondPlayer).isTouchMode = false;
  1055. }
  1056. if (smartBowHelper2P.IsBluetoothModuleInited()) Debug.Log("<color=green>已连接</color>(点击断开)");
  1057. else Debug.Log("<color=green>已连接</color><color=blue>(正在初始化)</color>");
  1058. }
  1059. }
  1060. public void ConnectSmartBowHelper2P()
  1061. {
  1062. //#if UNITY_ANDROID
  1063. // PopupMgr.ins.ClearAllTip();
  1064. // if (BluetoothHelperAndroid.IsBluetoothEnabled() == false)
  1065. // {
  1066. // HandleConnectException(TextAutoLanguage2.GetTextByKey("ble-exception1"));
  1067. // return;
  1068. // }
  1069. // if (BluetoothHelperAndroid.RequestBluetoothPermissions(ConnectSmartBowHelper2P, (permission) => {
  1070. // if (permission.Contains("LOCATION"))
  1071. // {
  1072. // HandleConnectException(TextAutoLanguage2.GetTextByKey("ble-exception2"));
  1073. // }
  1074. // else if (permission.Contains("BLUETOOTH"))
  1075. // {
  1076. // HandleConnectException(TextAutoLanguage2.GetTextByKey("ble-exception3"));
  1077. // }
  1078. // })) return;
  1079. //#endif
  1080. if (smartBowHelper2P == null)
  1081. {
  1082. onCreateSmartBowHelper2P();
  1083. CallDelay(1, () =>
  1084. {
  1085. smartBowHelper2P.Connect(userTags, deviceId2, true);//不在sdk 判断mac
  1086. });
  1087. }
  1088. else
  1089. {
  1090. smartBowHelper2P.Connect(userTags, deviceId2, true);
  1091. }
  1092. }
  1093. public void DoConnect2P()
  1094. {
  1095. Debug.Log("DoConnect2P");
  1096. if (smartBowHelper2P == null || smartBowHelper2P.GetBluetoothStatus() == SmartBowSDK.BluetoothStatusEnum.None)
  1097. {
  1098. //connectCanceled = false;
  1099. userDoConnect2P = true;
  1100. doConnect2P = true;
  1101. bNoNeedToReconnect = true;
  1102. Connect2P();
  1103. }
  1104. else if (smartBowHelper2P.GetBluetoothStatus() == SmartBowSDK.BluetoothStatusEnum.Connected)
  1105. {
  1106. userDoConnect2P = false;
  1107. doConnect2P = false;
  1108. canConnect2P = true;
  1109. DisconnectSmartBowHelper2P();
  1110. }
  1111. }
  1112. void Connect2P()
  1113. {
  1114. //if (BluetoothShoot.scanLock)
  1115. //{
  1116. // return;
  1117. //}
  1118. if (!canConnect2P)
  1119. {
  1120. return;
  1121. }
  1122. doConnect = false;
  1123. doConnect2P = false;
  1124. scanLock = true;
  1125. canConnect2P = false;
  1126. _scanCanRetryCount2P = 4;
  1127. //SetStatus2P(BluetoothStatusEnum.Connecting);
  1128. ConnectSmartBowHelper2P();
  1129. }
  1130. //初始化陀螺仪
  1131. public void OnCalibrateGyr2P()
  1132. {
  1133. if (smartBowHelper2P.IsGyrCalibrating()) smartBowHelper2P.StopGyrCalibration();
  1134. else smartBowHelper2P.StartGyrCalibration();
  1135. }
  1136. //初始化地磁计
  1137. public void OnCalibrateMag2P()
  1138. {
  1139. smartBowHelper2P.StartMagCalibration();
  1140. }
  1141. #endregion
  1142. #region 当前选择操作的设备 如1p或者2p
  1143. public SmartBowHelper getSmartBowHelper2P()
  1144. {
  1145. return smartBowHelper2P;
  1146. }
  1147. public void setBLEPlayer(BluetoothPlayer blePlayer)
  1148. {
  1149. //切换蓝牙用户时候,判断是否正在连接,如果正在匹配连接的话,取消连接状态
  1150. if (blePlayer != currentBLEPlayer)
  1151. {
  1152. Debug.Log("Set BluetoothPlayer status:" + status);
  1153. onCancelAllConnecting();
  1154. }
  1155. currentBLEPlayer = blePlayer;
  1156. Debug.Log("Set BluetoothPlayer:" + currentBLEPlayer);
  1157. }
  1158. public BluetoothPlayer getBLEPlayer()
  1159. {
  1160. //Debug.Log("Get BluetoothPlayer:" + currentBLEPlayer);
  1161. return currentBLEPlayer;
  1162. }
  1163. //更新跟随点位置
  1164. public void UpdateCameraToLookNewPoint2P()
  1165. {
  1166. if (SceneManager.GetActiveScene().name != "InfraredGameDouble")
  1167. {
  1168. if (CameraToLookNew.ins != null)
  1169. {
  1170. Transform m_controlObj = CameraToLookNew.ins.transform;
  1171. if (lerpForRotation2P)
  1172. m_controlObj.localRotation = Quaternion.Lerp(m_controlObj.localRotation, newRotation2P, Time.deltaTime * lerpTimeRate2P);
  1173. else
  1174. m_controlObj.localRotation = newRotation2P;
  1175. }
  1176. }
  1177. }
  1178. public int get2PBattery()
  1179. {
  1180. return smartBowHelper2P == null ? 0 : smartBowHelper2P.GetBattery();
  1181. }
  1182. //主更新调用
  1183. void updateSmartBowHelper2P()
  1184. {
  1185. UpdateCameraToLookNewPoint2P();
  1186. }
  1187. #endregion
  1188. //取消正在连接的连接
  1189. public void onCancelAllConnecting(BluetoothStatusEnum _bluetoothStatus = BluetoothStatusEnum.ConnectFail)
  1190. {
  1191. // status != BluetoothStatusEnum.ConnectSuccess
  1192. Debug.LogWarning("onCancelAllConnecting 1:" + status);
  1193. #if UNITY_STANDALONE_WIN || UNITY_EDITOR
  1194. //BleUDP.ins != null
  1195. //BluetoothWindows.IsWindows() &&
  1196. if (status == BluetoothStatusEnum.Connecting)
  1197. {
  1198. //Debug.LogWarning("onCancelAllConnecting 2:" + status);
  1199. userDoConnect = false;
  1200. doConnect = false;
  1201. OnDisconnect();
  1202. // BleUDP.ins.Disconnect();
  1203. firstBluetoothWindows.Disconnect();
  1204. SetStatus(_bluetoothStatus);
  1205. Debug.LogWarning("onCancelAllConnecting 3:" + status);
  1206. }
  1207. #else
  1208. if (bluetoothHelper != null && status == BluetoothStatusEnum.Connecting)
  1209. {
  1210. Debug.LogWarning("onCancelAllConnecting 2:" + status);
  1211. userDoConnect = false;
  1212. doConnect = false;
  1213. OnDisconnect();
  1214. DisconnectBleHelper();
  1215. SetStatus(_bluetoothStatus);
  1216. }
  1217. #endif
  1218. //smartBowHelper2P.GetBluetoothStatus() != SmartBowSDK.BluetoothStatusEnum.Connected
  1219. if (smartBowHelper2P != null && smartBowHelper2P.GetBluetoothStatus() == SmartBowSDK.BluetoothStatusEnum.Connecting)
  1220. {
  1221. userDoConnect2P = false;
  1222. doConnect2P = false;
  1223. canConnect2P = true;
  1224. DisconnectSmartBowHelper2P();
  1225. //smartBowHelper2P.Disconnect();
  1226. Debug.Log("onCancelAllConnecting smartBowHelper2P 2:" + smartBowHelper2P.GetBluetoothStatus());
  1227. }
  1228. }
  1229. #region 判断是否是1p设备连接的是HOUYIPRO信息
  1230. public bool isMainConnectToHOUYIPRO()
  1231. {
  1232. bool _isHOUYIPRO = false;
  1233. foreach (AimDeviceInfo p in AimHandler.ins.aimDeviceInfos.arry)
  1234. {
  1235. if ((int)BluetoothPlayer.FIRST_PLAYER == p.id && p.type == (int)AimDeviceType.HOUYIPRO)
  1236. {
  1237. _isHOUYIPRO = true;
  1238. }
  1239. }
  1240. if (_isHOUYIPRO)
  1241. {
  1242. if (CommonConfig.bDisableBluetooth)
  1243. {
  1244. return true;
  1245. }
  1246. else
  1247. {
  1248. //如果是。判断是否连接
  1249. return status == BluetoothStatusEnum.ConnectSuccess;
  1250. }
  1251. }
  1252. else
  1253. {
  1254. return false;
  1255. }
  1256. }
  1257. #endregion
  1258. #region 判断是否是1p设备连接的是ARTEMISPRO信息
  1259. public bool isMainConnectToARTEMISPRO()
  1260. {
  1261. bool _isARTEMISPRO = false;
  1262. foreach (AimDeviceInfo p in AimHandler.ins.aimDeviceInfos.arry)
  1263. {
  1264. if ((int)BluetoothPlayer.FIRST_PLAYER == p.id && p.type == (int)AimDeviceType.ARTEMISPRO)
  1265. {
  1266. _isARTEMISPRO = true;
  1267. }
  1268. }
  1269. if (_isARTEMISPRO)
  1270. {
  1271. if (CommonConfig.bDisableBluetooth)
  1272. {
  1273. return true;
  1274. }
  1275. else
  1276. {
  1277. //如果是。判断是否连接
  1278. return status == BluetoothStatusEnum.ConnectSuccess;
  1279. }
  1280. }
  1281. else
  1282. {
  1283. return false;
  1284. }
  1285. }
  1286. #endregion
  1287. #region 判断是否是1p设备连接的是红外信息,有多种红外设备
  1288. public bool isMainConnectToInfraredDevice()
  1289. {
  1290. bool _isInfraredDevice = false;
  1291. foreach (AimDeviceInfo p in AimHandler.ins.aimDeviceInfos.arry)
  1292. {
  1293. if ((int)BluetoothPlayer.FIRST_PLAYER == p.id && (p.type == (int)AimDeviceType.ARTEMISPRO || p.type == (int)AimDeviceType.HOUYIPRO))
  1294. {
  1295. _isInfraredDevice = true;
  1296. }
  1297. }
  1298. if (_isInfraredDevice)
  1299. {
  1300. if (CommonConfig.bDisableBluetooth)
  1301. {
  1302. return true;
  1303. }
  1304. else
  1305. {
  1306. //如果是。判断是否连接
  1307. return status == BluetoothStatusEnum.ConnectSuccess;
  1308. }
  1309. }
  1310. else
  1311. {
  1312. return false;
  1313. }
  1314. }
  1315. #endregion
  1316. #region 判断是否是1p设备连接的是Gun信息
  1317. public bool isMainConnectToGun()
  1318. {
  1319. bool _isGun = false;
  1320. foreach (AimDeviceInfo p in AimHandler.ins.aimDeviceInfos.arry)
  1321. {
  1322. if ((int)BluetoothPlayer.FIRST_PLAYER == p.id && (p.type == (int)AimDeviceType.Gun || p.type == (int)AimDeviceType.PistolM17 || p.type == (int)AimDeviceType.RifleM416))
  1323. {
  1324. _isGun = true;
  1325. }
  1326. }
  1327. if (_isGun)
  1328. {
  1329. if (CommonConfig.bDisableBluetooth)
  1330. {
  1331. return true;
  1332. }
  1333. else
  1334. {
  1335. //如果是。判断是否连接
  1336. return status == BluetoothStatusEnum.ConnectSuccess;
  1337. }
  1338. }
  1339. else
  1340. {
  1341. return false;
  1342. }
  1343. }
  1344. /// <summary>
  1345. /// 获取连接枪的类型
  1346. /// </summary>
  1347. /// <returns></returns>
  1348. public (bool isGun, AimDeviceType gunType) isMainConnectToGunType()
  1349. {
  1350. bool _isGun = false;
  1351. AimDeviceType aimDeviceType = AimDeviceType.NONE;
  1352. foreach (AimDeviceInfo p in AimHandler.ins.aimDeviceInfos.arry)
  1353. {
  1354. if ((int)BluetoothPlayer.FIRST_PLAYER == p.id && (p.type == (int)AimDeviceType.Gun || p.type == (int)AimDeviceType.PistolM17 || p.type == (int)AimDeviceType.RifleM416))
  1355. {
  1356. _isGun = true;
  1357. aimDeviceType = (AimDeviceType)p.type;
  1358. }
  1359. }
  1360. if (_isGun)
  1361. {
  1362. if (CommonConfig.bDisableBluetooth)
  1363. {
  1364. return (true, aimDeviceType);
  1365. }
  1366. else
  1367. {
  1368. //如果是。判断是否连接
  1369. return (status == BluetoothStatusEnum.ConnectSuccess, aimDeviceType);
  1370. }
  1371. }
  1372. else
  1373. {
  1374. return (false, aimDeviceType);
  1375. }
  1376. }
  1377. #endregion
  1378. /// <summary>
  1379. /// 设置设备类型
  1380. /// </summary>
  1381. public void SetMainConnectDeviceType()
  1382. {
  1383. //1号玩家连接蓝牙成功时候,设置一次 GlobalData.MyDeviceMode
  1384. foreach (AimDeviceInfo p in AimHandler.ins.aimDeviceInfos.arry)
  1385. {
  1386. if ((int)BluetoothPlayer.FIRST_PLAYER == p.id)
  1387. {
  1388. if (p.type == (int)AimDeviceType.Gun || p.type == (int)AimDeviceType.PistolM17 || p.type == (int)AimDeviceType.RifleM416)
  1389. {
  1390. //设置枪
  1391. HomeView.ins.MyTopBarView.onChangeType(1);
  1392. }
  1393. else
  1394. {
  1395. //其余默认是弓箭
  1396. HomeView.ins.MyTopBarView.onChangeType(0);
  1397. }
  1398. }
  1399. }
  1400. }
  1401. #region 用户1 window ble 连接和部分共用代码
  1402. void OnConnected_windows1()
  1403. {
  1404. Log("[WinBle_1P]连接成功\n" + deviceName);
  1405. SetStatus(BluetoothStatusEnum.ConnectSuccess);
  1406. BowCamera.isTouchMode = false;
  1407. if (CommonConfig.EnableDecryption && NeedDecryption)
  1408. {
  1409. // 这里验证指令,开始请求授权
  1410. // 启动轮询协程
  1411. StartCoroutine(PollingCoroutine());
  1412. }
  1413. else
  1414. {
  1415. //除了pc,Android 直接连接
  1416. InitWhenConenct();
  1417. }
  1418. }
  1419. void OnConnectionFailed_windows1()
  1420. {
  1421. Log("连接失败\n" + deviceName);
  1422. OnDisconnect();
  1423. }
  1424. void OnCharacteristicChanged_windows1(string deviceId, byte[] value)
  1425. {
  1426. OnCharacteristicChanged(null, value, null);
  1427. }
  1428. void OnCharacteristicChanged(BluetoothHelper helper, byte[] value, BluetoothHelperCharacteristic characteristic)
  1429. {
  1430. if (status != BluetoothStatusEnum.ConnectSuccess) return;
  1431. if (!hasData)
  1432. {
  1433. hasData = true;
  1434. hasDataTime = JCUnityLib.TimeUtils.GetTimestamp();
  1435. }
  1436. if (CommonConfig.EnableDecryption && NeedDecryption)
  1437. {
  1438. //Pc 版本先走校验流程
  1439. if (!BluetoothDecryptor.AUTHOR_IsDecrypt())
  1440. {
  1441. if (value[0] == 0x5a)
  1442. {
  1443. // 从硬件读取数据
  1444. if (value != null && value.Length > 0)
  1445. {
  1446. Debug.Log("接收到数据:" + BitConverter.ToString(value));
  1447. BluetoothDecryptor.AUTHOR_Decrypt(value);
  1448. if (BluetoothDecryptor.AUTHOR_IsDecrypt())
  1449. {
  1450. Debug.Log("解密成功!");
  1451. //解密成功后
  1452. StopEncrypt();
  1453. //开始连接其他信息
  1454. InitWhenConenct();
  1455. }
  1456. else
  1457. {
  1458. Debug.Log("解密失败!");
  1459. //SideTipView.ShowTip("设备通信失败,断开连接", Color.yellow);
  1460. //断开连接等操作
  1461. if (PollingCoroutineCount <= 0)
  1462. {
  1463. StopEncrypt();
  1464. DoConnect();
  1465. }
  1466. }
  1467. }
  1468. }
  1469. return;
  1470. }
  1471. }
  1472. dataCount++;
  1473. if (curMac == null && dataCount < 500)
  1474. {
  1475. UploadMacAddress(value);
  1476. }
  1477. byte[] bytes = value;
  1478. // Log(String.Join(",", bytes));
  1479. BluetoothClient.UploadData(0, bytes);
  1480. if (AimHandler.ins)
  1481. {
  1482. AimHandler.ins.OnDataReceived(bytes);
  1483. }
  1484. }
  1485. #endregion
  1486. #region 管理部分监听通信
  1487. /// <summary>
  1488. /// 监听枪状态
  1489. /// </summary>
  1490. public BleDeviceEvent OnBleDeviceState;
  1491. /// <summary>
  1492. /// 硬件对应的事件
  1493. /// </summary>
  1494. public delegate void BleDeviceEvent(BluetoothDeviceType bleDeviceType, BluetoothDeviceStatus gunStatusEnum);
  1495. internal void InvokeOnBleDevice(BluetoothDeviceType bleDeviceType, BluetoothDeviceStatus gunStatusEnum)
  1496. {
  1497. try
  1498. {
  1499. OnBleDeviceState?.Invoke(bleDeviceType, gunStatusEnum);
  1500. }
  1501. catch (Exception e)
  1502. {
  1503. Debug.LogError(e);
  1504. }
  1505. }
  1506. /// <summary>
  1507. /// 记录硬件反馈的设备状态和连接的设备平台信息
  1508. /// </summary>
  1509. public BluetoothDeviceType myBluetoothDeviceType = BluetoothDeviceType.NONE;
  1510. public ConnectPlatform myConnectPlatform = ConnectPlatform.NONE;
  1511. /// <summary>
  1512. /// 监听设备状态和连接的设备平台信息
  1513. /// </summary>
  1514. public DeviceAndSystemInfoEvent OnDeviceAndSystemInfoEvent;
  1515. /// <summary>
  1516. /// 硬件对应的事件初始化回调
  1517. /// </summary>
  1518. public delegate void DeviceAndSystemInfoEvent(ConnectPlatform connectPlatform, BluetoothDeviceType bleDeviceType);
  1519. internal void InvokeOnDeviceAndSystemInfoEvent(ConnectPlatform connectPlatform, BluetoothDeviceType bleDeviceType)
  1520. {
  1521. try
  1522. {
  1523. myConnectPlatform = connectPlatform;
  1524. myBluetoothDeviceType = bleDeviceType;
  1525. OnDeviceAndSystemInfoEvent?.Invoke(connectPlatform, bleDeviceType);
  1526. }
  1527. catch (Exception e)
  1528. {
  1529. Debug.LogError(e);
  1530. }
  1531. }
  1532. /// <summary>
  1533. /// 获取一次当前记录的信息
  1534. /// </summary>
  1535. public void GetDeviceAndSystemInfoEvent() {
  1536. OnDeviceAndSystemInfoEvent?.Invoke(myConnectPlatform, myBluetoothDeviceType);
  1537. }
  1538. /// <summary>
  1539. /// 返回一个存储用户的新手教程字符串
  1540. /// </summary>
  1541. /// <returns></returns>
  1542. public string GetInfraredGuiderKey() {
  1543. return $"hideInfraredGuider-{LoginMgr.myUserInfo.id}-{myBluetoothDeviceType}";
  1544. }
  1545. /// <summary>
  1546. /// 清除当前红外记录的存储的所有key内容
  1547. /// </summary>
  1548. public void ClearAllInfraredGuider() {
  1549. int userId = LoginMgr.myUserInfo.id;
  1550. foreach (BluetoothDeviceType type in Enum.GetValues(typeof(BluetoothDeviceType)))
  1551. {
  1552. string key = $"hideInfraredGuider-{userId}-{type}";
  1553. PlayerPrefs.DeleteKey(key);
  1554. }
  1555. PlayerPrefs.Save();
  1556. }
  1557. #endregion
  1558. }