using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using ArduinoBluetoothAPI; using DG.Tweening; /* 蓝牙射击模块 */ public class BluetoothShoot : MonoBehaviour { BluetoothHelper bluetoothHelper; BluetoothHelperCharacteristic characteristicWrite; BluetoothHelperService bluetoothService; string targetDeviceName = "BArrow_202105"; string deviceName = ""; bool canConnect = true; [SerializeField] Text textUI; public BluetoothStatusEnum status = BluetoothStatusEnum.Connect; public bool hasData = false; public static bool scanLock = false; //防止同时扫描冲突 public static BluetoothShoot ins; void Start() { ins = this; BluetoothDispatcher.shoot = handleDataBytes; } void OnDestroy() { if (bluetoothHelper != null) { bluetoothHelper.Disconnect(); } } private bool userDoConnect = false; private bool doConnect = false; public void DoConnect() { if (status == BluetoothStatusEnum.Connect) { userDoConnect = true; doConnect = true; SetStatus(BluetoothStatusEnum.Connecting); } else if (status == BluetoothStatusEnum.ConnectSuccess) { userDoConnect = false; doConnect = false; OnDisconnect(); bluetoothHelper.Disconnect(); } } void OnDisconnect() { hasData = false; canConnect = true; if (ShootCheck.ins) ShootCheck.ins.canAdjustNormalOrHightMode = false; SetStatus(BluetoothStatusEnum.ConnectFail); //清除射箭收集的数据 dataGetting = false; dataBytes.Clear(); } void Update() { if (userDoConnect && status == BluetoothStatusEnum.Connect) { DoConnect(); } if (doConnect) Connect(); } void SetStatus(BluetoothStatusEnum statusValue) { status = statusValue; if (status == BluetoothStatusEnum.ConnectFail) { status = BluetoothStatusEnum.ConnectFail; Sequence sequence = DOTween.Sequence(); sequence.AppendInterval(2f); sequence.AppendCallback(delegate() { if (status == BluetoothStatusEnum.ConnectFail) { status = BluetoothStatusEnum.Connect; } }); sequence.SetUpdate(true); } } void Connect() { if (BluetoothAim.scanLock) { return; } if (!canConnect) { return; } doConnect = false; scanLock = true; canConnect = false; SetStatus(BluetoothStatusEnum.Connecting); try { BluetoothHelper.BLE = true; bluetoothHelper = BluetoothHelper.GetNewInstance(); bluetoothHelper.OnConnected += (BluetoothHelper helper) => { Log("连接成功\n" + helper.getDeviceName()); SetStatus(BluetoothStatusEnum.ConnectSuccess); foreach (BluetoothHelperService service in helper.getGattServices()) { if (service.getName().ToLower().StartsWith("0000fff0")) { bluetoothService = service; foreach (BluetoothHelperCharacteristic characteristic in service.getCharacteristics()) { if (characteristic.getName().ToLower().StartsWith("0000fff2")) { characteristicWrite = characteristic; } else if (characteristic.getName().ToLower().StartsWith("0000fff1")) { BluetoothHelperCharacteristic ch = new BluetoothHelperCharacteristic(characteristic.getName()); ch.setService(bluetoothService.getName()); bluetoothHelper.Subscribe(ch); } } } } CallDelay(1, OpenReceiveData); }; bluetoothHelper.OnConnectionFailed += (BluetoothHelper helper) => { Log("连接失败\n" + helper.getDeviceName()); OnDisconnect(); }; bluetoothHelper.OnCharacteristicChanged += (helper, value, characteristic) => { hasData = true; byte[] bytes = value; // Log(String.Join(",", bytes)); BluetoothClient.UploadData(1, bytes); handleDataBytes(bytes); }; bluetoothHelper.OnScanEnded += (BluetoothHelper helper, LinkedList nearbyDevices) => { scanLock = false; foreach (BluetoothDevice device in nearbyDevices) { if (device.DeviceName == targetDeviceName) { deviceName = device.DeviceName; bluetoothHelper.setDeviceName(deviceName); bluetoothHelper.Connect(); Log("发现设备\n" + device.DeviceName); return; } } canConnect = true; Log("没有发现设备"); SetStatus(BluetoothStatusEnum.ConnectFail); }; bluetoothHelper.ScanNearbyDevices(); Log("正在扫描设备"); } catch (Exception e) { Debug.Log(e.Message); canConnect = true; Log("请打开蓝牙"); } } void OpenReceiveData() { WriteData("5"); CallDelay(1, delegate() { if (ShootCheck.ins) { ShootCheck.ins.OnBluetoothReady(this); Log("射击模块准备完成\n" + deviceName); } }); CallDelay(2.5f, delegate() { WriteData("B"); }); } void CallDelay(float delayTime, TweenCallback callback) { Sequence sequence = DOTween.Sequence(); sequence.PrependInterval(delayTime).AppendCallback(callback); sequence.SetUpdate(true); } public void WriteData(string data) { BluetoothHelperCharacteristic ch = new BluetoothHelperCharacteristic(characteristicWrite.getName()); ch.setService(bluetoothService.getName()); bluetoothHelper.WriteCharacteristic(ch, data); } void Log(string text) { if (textUI) { textUI.text = text; } } //---收集射箭轴加速度--- bool dataGetting = false; int dataGetLen = 0; List dataBytes = new List(); int TwoByteToInt(byte b1, byte b2) { ushort twoByte = (ushort) (b1 * 256 + b2); short shortNum = (short) twoByte; return (int) shortNum; } void cacheDataBytes(byte[] bytes, int startIndex) { for (int i = startIndex; i < bytes.Length; i++) { byte b = bytes[i]; if (dataBytes.Count < dataGetLen) { dataBytes.Add(b); } else { if (ShootCheck.ins) ShootCheck.ins.OnDataReceived(dataBytes.ToArray()); dataGetting = false; dataBytes.Clear(); break; } } } public void handleDataBytes(byte[] bytes) { if (dataGetting) { cacheDataBytes(bytes, 0); } else { if (bytes.Length >= 5) { int byte3Value = 0; //轴数据识别,1:x轴,2:y轴,3:z轴 if (ShootCheck.ins) { CMD cmd = ShootCheck.ins.cmd; if (cmd.a == "x") byte3Value = 1; if (cmd.a == "y") byte3Value = 2; if (cmd.a == "z") byte3Value = 3; } if (bytes[0] == 255 || bytes[1] == 255 && bytes[2] == byte3Value) { dataGetting = true; dataGetLen = TwoByteToInt(bytes[3], bytes[4]); cacheDataBytes(bytes, 5); } } else if (bytes.Length == 2) { DeviceBatteryView.ins.RenderBattery(2, bytes[0]); } } } }