using ArduinoBluetoothAPI; using System; using UnityEngine; using System.Collections.Generic; using UnityEngine.UI; using DG.Tweening; using UnityEngine.SceneManagement; /* 蓝牙瞄准模块 */ public class BluetoothAim : MonoBehaviour { BluetoothHelper bluetoothHelper; BluetoothHelperCharacteristic characteristicWrite; BluetoothHelperService bluetoothService; string targetDeviceName = "Bbow_20210501"; string deviceName = ""; bool canConnect = true; [SerializeField] Text textUI; public BluetoothStatusEnum status = BluetoothStatusEnum.Connect; public bool hasData = false; public long hasDataTime; public static bool scanLock = false; //防止同时扫描冲突 public static BluetoothAim ins; void Start() { ins = this; InitAutoDormancy(); } 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; SetStatus(BluetoothStatusEnum.ConnectFail); BowCamera.isTouchMode = true; DestroyWhenDisconenct(); } void Update() { if (userDoConnect && status == BluetoothStatusEnum.Connect) { DoConnect(); } if (doConnect) Connect(); } void SetStatus(BluetoothStatusEnum statusValue) { status = statusValue; if (status == BluetoothStatusEnum.ConnectFail) { Sequence sequence = DOTween.Sequence(); sequence.AppendInterval(2f); sequence.AppendCallback(delegate() { if (status == BluetoothStatusEnum.ConnectFail) { status = BluetoothStatusEnum.Connect; } }); sequence.SetUpdate(true); DeviceReconnectView.Show(); } } void Connect() { if (BluetoothShoot.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); BowCamera.isTouchMode = false; 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, OpenInfrared); // CallDelay(2, OpenReceiveData); // CallDelay(3, RequestBattery); CallDelay(2, () => { if (status != BluetoothStatusEnum.ConnectSuccess) return; InitWhenConenct(); }); }; bluetoothHelper.OnConnectionFailed += (BluetoothHelper helper) => { Log("连接失败\n" + helper.getDeviceName()); OnDisconnect(); }; bluetoothHelper.OnCharacteristicChanged += (helper, value, characteristic) => { if (!hasData) hasDataTime = JC.CS.Utility.GetTimestamp(); hasData = true; byte[] bytes = value; // Log(String.Join(",", bytes)); BluetoothClient.UploadData(0, bytes); if (AimHandler.ins) { AimHandler.ins.OnDataReceived(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("请打开蓝牙"); } } #region 自动进入/退出休眠状态, 这里做程指令发送队列,为了控制连续发送指令的间隔,避免硬件收不到或处理不过来 class CmdToSend { public string[] cmds; public Action onComplete; public Func canDo; public CmdToSend(string[] cmds, Action onComplete, Func canDo) { this.cmds = cmds; this.onComplete = onComplete; this.canDo = canDo; } } Queue cmdWaitingList = new Queue(); bool isSendCmdLocked = false; bool canAutoDormancy = false; bool isStartUp = false; JC.CS.CountLocker needModularAwake = new JC.CS.CountLocker(); void CheckAndStartUp() { if (needModularAwake.IsLocked()) { StartUp(); } else { Dormancy(); } } void InitAutoDormancy() { // GlobalEventCenter.ins.onGameSceneLoad += () => { // needModularAwake.Lock(); // CheckAndStartUp(); // }; // GlobalEventCenter.ins.onGameSceneDestroy += () => { // needModularAwake.Unlock(); // CheckAndStartUp(); // }; // GlobalEventCenter.ins.onSimulateMouseAwakeChanged += (waked) => { // if (waked) needModularAwake.Lock(); // else needModularAwake.Unlock();; // CheckAndStartUp(); // }; // GlobalEventCenter.ins.onDeviceCalibrateViewAwakeChanged += (waked) => { // if (waked) needModularAwake.Lock(); // else needModularAwake.Unlock();; // CheckAndStartUp(); // }; //暂时关闭自动休眠,默认是需要模块保持激活 needModularAwake.Lock(); } void InitWhenConenct() { canAutoDormancy = true; List cmds = new List(); cmds.Add("b"); //确保开启stm32 cmds.Add("b"); //获取初始电量 cmds.Add("1"); //开启发送逻辑 Action onComplete = null; if (needModularAwake.IsLocked()) { cmds.Add("w"); //红外灯开启 cmds.Add("3"); //九轴开启 onComplete = () => { isStartUp = true; }; } else { cmds.Add("s"); //红外灯关闭 cmds.Add("S"); //Stm32关闭 cmds.Add("4"); //九轴关闭 onComplete = () => { isStartUp = false; }; } SendCDM(null, onComplete, cmds.ToArray()); } void DestroyWhenDisconenct() { canAutoDormancy = false; sendCMD_CheckAndDoStop(null); } //启动 void StartUp() { SendCDM(() => { return !isStartUp; }, () => { isStartUp = true; }, "b", "w", "3"); } //休眠 void Dormancy() { SendCDM(() => { return isStartUp; }, () => { isStartUp = false; }, "4", "s", "S"); } void SendCDM(Func canDo, Action onComplete, params string[] cmds) { CmdToSend cmdToSend = new CmdToSend(cmds, onComplete, canDo); if (isSendCmdLocked) { cmdWaitingList.Enqueue(cmdToSend); return; } sendCMD_NotCheck(cmdToSend); } void sendCMD_NotCheck(CmdToSend cmdToSend) { if (cmdToSend.canDo != null && !cmdToSend.canDo.Invoke()) { sendCMD_CheckNext(); return; } isSendCmdLocked = true; Sequence sequence = DOTween.Sequence(); sequence.PrependInterval(0.3f); foreach (var cmd in cmdToSend.cmds) { sequence.AppendCallback(() => { bool stopped = sendCMD_CheckAndDoStop(sequence); if (!stopped) WriteData(cmd); }); sequence.AppendInterval(0.5f); } sequence.AppendCallback(() => { bool stopped = sendCMD_CheckAndDoStop(sequence); if (!stopped) { isSendCmdLocked = false; cmdToSend.onComplete?.Invoke(); sendCMD_CheckNext(); } }); sequence.SetUpdate(true); } void sendCMD_CheckNext() { if (cmdWaitingList.Count <= 0) return; CmdToSend cmdToSend = cmdWaitingList.Dequeue(); sendCMD_NotCheck(cmdToSend); } bool sendCMD_CheckAndDoStop(Sequence sequence) { if (canAutoDormancy) return false; isStartUp = false; isSendCmdLocked = false; cmdWaitingList.Clear(); if (sequence != null) sequence.Kill(); return true; } #endregion void OpenInfrared() { WriteData("1"); Log("红外线准备完成\n" + deviceName); } void OpenReceiveData() { WriteData("3"); Log("瞄准模块准备完成\n" + deviceName); } public void RequestBattery() { if (!isStartUp) return; if (isSendCmdLocked) return; WriteData("b"); } public void ReplyInfraredShoot() { if (isSendCmdLocked) return; WriteData("I"); } void CallDelay(float delayTime, TweenCallback callback) { Sequence sequence = DOTween.Sequence(); sequence.PrependInterval(delayTime).AppendCallback(callback); sequence.SetUpdate(true); } public void WriteData(string data) { if (DebugDeviceCMD.ins) DebugDeviceCMD.ins.ShowCMD(data); BluetoothHelperCharacteristic ch = new BluetoothHelperCharacteristic(characteristicWrite.getName()); ch.setService(bluetoothService.getName()); bluetoothHelper.WriteCharacteristic(ch, data); } void Log(string text) { if (textUI) { textUI.text = text; } } } // public class BluetoothAim : MonoBehaviour // { // BluetoothHelper bluetoothHelper; // BluetoothHelperCharacteristic characteristicWrite; // BluetoothHelperService bluetoothService; // string targetDeviceName = "Bbow_20210501"; // string deviceName = ""; // bool canConnect = true; // [SerializeField] Text textUI; // public BluetoothStatusEnum status = BluetoothStatusEnum.Connect; // public bool hasData = false; // public long hasDataTime; // public static bool scanLock = false; //防止同时扫描冲突 // public static BluetoothAim ins; // void Start() { // ins = this; // } // 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; // SetStatus(BluetoothStatusEnum.ConnectFail); // BowCamera.isTouchMode = true; // } // void Update() // { // if (userDoConnect && status == BluetoothStatusEnum.Connect) { // DoConnect(); // } // if (doConnect) Connect(); // } // void SetStatus(BluetoothStatusEnum statusValue) // { // status = statusValue; // if (status == BluetoothStatusEnum.ConnectFail) { // Sequence sequence = DOTween.Sequence(); // sequence.AppendInterval(2f); // sequence.AppendCallback(delegate() { // if (status == BluetoothStatusEnum.ConnectFail) { // status = BluetoothStatusEnum.Connect; // } // }); // sequence.SetUpdate(true); // DeviceReconnectView.Show(); // } // } // void Connect() // { // if (BluetoothShoot.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); // BowCamera.isTouchMode = false; // 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, OpenInfrared); // CallDelay(2, OpenReceiveData); // CallDelay(3, RequestBattery); // }; // bluetoothHelper.OnConnectionFailed += (BluetoothHelper helper) => // { // Log("连接失败\n" + helper.getDeviceName()); // OnDisconnect(); // }; // bluetoothHelper.OnCharacteristicChanged += (helper, value, characteristic) => // { // if (!hasData) hasDataTime = JC.CS.Utility.GetTimestamp(); // hasData = true; // byte[] bytes = value; // // Log(String.Join(",", bytes)); // BluetoothClient.UploadData(0, bytes); // if (AimHandler.ins) // { // AimHandler.ins.OnDataReceived(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 OpenInfrared() // { // WriteData("1"); // Log("红外线准备完成\n" + deviceName); // } // void OpenReceiveData() // { // WriteData("3"); // Log("瞄准模块准备完成\n" + deviceName); // } // public void RequestBattery() { // WriteData("b"); // } // public void ReplyInfraredShoot() { // WriteData("I"); // } // 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; // } // } // }