BluetoothShoot.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. using ArduinoBluetoothAPI;
  6. using DG.Tweening;
  7. /* 蓝牙射击模块 */
  8. public class BluetoothShoot : MonoBehaviour
  9. {
  10. BluetoothHelper bluetoothHelper;
  11. BluetoothHelperCharacteristic characteristicWrite;
  12. BluetoothHelperService bluetoothService;
  13. string targetDeviceName = "BArrow_202105";
  14. string deviceName = "";
  15. bool canConnect = true;
  16. [SerializeField] Text textUI;
  17. public BluetoothStatusEnum status = BluetoothStatusEnum.Connect;
  18. public bool hasData = false;
  19. public static bool scanLock = false; //防止同时扫描冲突
  20. public static BluetoothShoot ins;
  21. void Start() {
  22. ins = this;
  23. BluetoothDispatcher.shoot = handleDataBytes;
  24. }
  25. void OnDestroy()
  26. {
  27. if (bluetoothHelper != null)
  28. {
  29. bluetoothHelper.Disconnect();
  30. }
  31. }
  32. private bool userDoConnect = false;
  33. private bool doConnect = false;
  34. public void DoConnect() {
  35. if (status == BluetoothStatusEnum.Connect) {
  36. userDoConnect = true;
  37. doConnect = true;
  38. SetStatus(BluetoothStatusEnum.Connecting);
  39. } else if (status == BluetoothStatusEnum.ConnectSuccess) {
  40. userDoConnect = false;
  41. doConnect = false;
  42. OnDisconnect();
  43. bluetoothHelper.Disconnect();
  44. }
  45. }
  46. void OnDisconnect() {
  47. hasData = false;
  48. canConnect = true;
  49. if (ShootCheck.ins) ShootCheck.ins.canAdjustNormalOrHightMode = false;
  50. SetStatus(BluetoothStatusEnum.ConnectFail);
  51. //清除射箭收集的数据
  52. dataGetting = false;
  53. dataBytes.Clear();
  54. }
  55. void Update()
  56. {
  57. if (userDoConnect && status == BluetoothStatusEnum.Connect) {
  58. DoConnect();
  59. }
  60. if (doConnect) Connect();
  61. }
  62. void SetStatus(BluetoothStatusEnum statusValue)
  63. {
  64. status = statusValue;
  65. if (status == BluetoothStatusEnum.ConnectFail) {
  66. status = BluetoothStatusEnum.ConnectFail;
  67. Sequence sequence = DOTween.Sequence();
  68. sequence.AppendInterval(2f);
  69. sequence.AppendCallback(delegate() {
  70. if (status == BluetoothStatusEnum.ConnectFail) {
  71. status = BluetoothStatusEnum.Connect;
  72. }
  73. });
  74. sequence.SetUpdate(true);
  75. DeviceReconnectView.Show();
  76. }
  77. }
  78. void Connect()
  79. {
  80. if (BluetoothAim.scanLock)
  81. {
  82. return;
  83. }
  84. if (!canConnect)
  85. {
  86. return;
  87. }
  88. doConnect = false;
  89. scanLock = true;
  90. canConnect = false;
  91. SetStatus(BluetoothStatusEnum.Connecting);
  92. try
  93. {
  94. BluetoothHelper.BLE = true;
  95. bluetoothHelper = BluetoothHelper.GetNewInstance();
  96. bluetoothHelper.OnConnected += (BluetoothHelper helper) =>
  97. {
  98. Log("连接成功\n" + helper.getDeviceName());
  99. SetStatus(BluetoothStatusEnum.ConnectSuccess);
  100. foreach (BluetoothHelperService service in helper.getGattServices())
  101. {
  102. if (service.getName().ToLower().StartsWith("0000fff0"))
  103. {
  104. bluetoothService = service;
  105. foreach (BluetoothHelperCharacteristic characteristic in service.getCharacteristics())
  106. {
  107. if (characteristic.getName().ToLower().StartsWith("0000fff2"))
  108. {
  109. characteristicWrite = characteristic;
  110. }
  111. else if (characteristic.getName().ToLower().StartsWith("0000fff1"))
  112. {
  113. BluetoothHelperCharacteristic ch = new BluetoothHelperCharacteristic(characteristic.getName());
  114. ch.setService(bluetoothService.getName());
  115. bluetoothHelper.Subscribe(ch);
  116. }
  117. }
  118. }
  119. }
  120. CallDelay(1, OpenReceiveData);
  121. };
  122. bluetoothHelper.OnConnectionFailed += (BluetoothHelper helper) =>
  123. {
  124. Log("连接失败\n" + helper.getDeviceName());
  125. OnDisconnect();
  126. };
  127. bluetoothHelper.OnCharacteristicChanged += (helper, value, characteristic) =>
  128. {
  129. hasData = true;
  130. byte[] bytes = value;
  131. // Log(String.Join(",", bytes));
  132. BluetoothClient.UploadData(1, bytes);
  133. handleDataBytes(bytes);
  134. };
  135. bluetoothHelper.OnScanEnded += (BluetoothHelper helper, LinkedList<BluetoothDevice> nearbyDevices) =>
  136. {
  137. scanLock = false;
  138. foreach (BluetoothDevice device in nearbyDevices)
  139. {
  140. if (device.DeviceName == targetDeviceName)
  141. {
  142. deviceName = device.DeviceName;
  143. bluetoothHelper.setDeviceName(deviceName);
  144. bluetoothHelper.Connect();
  145. Log("发现设备\n" + device.DeviceName);
  146. return;
  147. }
  148. }
  149. canConnect = true;
  150. Log("没有发现设备");
  151. SetStatus(BluetoothStatusEnum.ConnectFail);
  152. };
  153. bluetoothHelper.ScanNearbyDevices();
  154. Log("正在扫描设备");
  155. }
  156. catch (Exception e)
  157. {
  158. Debug.Log(e.Message);
  159. canConnect = true;
  160. Log("请打开蓝牙");
  161. }
  162. }
  163. void OpenReceiveData()
  164. {
  165. WriteData("5");
  166. CallDelay(1, delegate() {
  167. if (ShootCheck.ins)
  168. {
  169. ShootCheck.ins.OnBluetoothReady(this);
  170. Log("射击模块准备完成\n" + deviceName);
  171. }
  172. });
  173. CallDelay(2.5f, delegate() {
  174. WriteData("B");
  175. });
  176. }
  177. void CallDelay(float delayTime, TweenCallback callback)
  178. {
  179. Sequence sequence = DOTween.Sequence();
  180. sequence.PrependInterval(delayTime).AppendCallback(callback);
  181. sequence.SetUpdate(true);
  182. }
  183. public void WriteData(string data)
  184. {
  185. BluetoothHelperCharacteristic ch = new BluetoothHelperCharacteristic(characteristicWrite.getName());
  186. ch.setService(bluetoothService.getName());
  187. bluetoothHelper.WriteCharacteristic(ch, data);
  188. }
  189. void Log(string text)
  190. {
  191. if (textUI)
  192. {
  193. textUI.text = text;
  194. }
  195. }
  196. //---收集射箭轴加速度---
  197. bool dataGetting = false;
  198. int dataGetLen = 0;
  199. List<byte> dataBytes = new List<byte>();
  200. int TwoByteToInt(byte b1, byte b2)
  201. {
  202. ushort twoByte = (ushort) (b1 * 256 + b2);
  203. short shortNum = (short) twoByte;
  204. return (int) shortNum;
  205. }
  206. void cacheDataBytes(byte[] bytes, int startIndex) {
  207. for (int i = startIndex; i < bytes.Length; i++) {
  208. byte b = bytes[i];
  209. if (dataBytes.Count < dataGetLen) {
  210. dataBytes.Add(b);
  211. } else {
  212. if (ShootCheck.ins) ShootCheck.ins.OnDataReceived(dataBytes.ToArray());
  213. dataGetting = false;
  214. dataBytes.Clear();
  215. break;
  216. }
  217. }
  218. }
  219. public void handleDataBytes(byte[] bytes) {
  220. if (dataGetting) {
  221. cacheDataBytes(bytes, 0);
  222. } else {
  223. if (bytes.Length >= 5) {
  224. int byte3Value = 0; //轴数据识别,1:x轴,2:y轴,3:z轴
  225. if (ShootCheck.ins) {
  226. CMD cmd = ShootCheck.ins.cmd;
  227. if (cmd.a == "x") byte3Value = 1;
  228. if (cmd.a == "y") byte3Value = 2;
  229. if (cmd.a == "z") byte3Value = 3;
  230. }
  231. if (bytes[0] == 255 || bytes[1] == 255 && bytes[2] == byte3Value) {
  232. dataGetting = true;
  233. dataGetLen = TwoByteToInt(bytes[3], bytes[4]);
  234. cacheDataBytes(bytes, 5);
  235. }
  236. } else if (bytes.Length == 2) {
  237. DeviceBatteryView.ins.RenderBattery(2, bytes[0]);
  238. }
  239. }
  240. }
  241. }