|
|
@@ -0,0 +1,744 @@
|
|
|
+using System;
|
|
|
+using System.Collections;
|
|
|
+using System.Collections.Generic;
|
|
|
+using UnityEngine;
|
|
|
+using ArduinoBluetoothAPI;
|
|
|
+
|
|
|
+namespace SmartBowSDK
|
|
|
+{
|
|
|
+ public class BluetoothAim_SDK : MonoBehaviour
|
|
|
+ {
|
|
|
+ public SmartBowHelper smartBowHelper;
|
|
|
+
|
|
|
+ public BluetoothDeviceConfig deviceConfig;
|
|
|
+ private BluetoothHelper _bluetoothHelper;
|
|
|
+ private BluetoothHelperService _bluetoothService;
|
|
|
+ private BluetoothHelperCharacteristic _characteristicWrite;
|
|
|
+ private static HashSet<object> _ScanLocker = new HashSet<object>();
|
|
|
+
|
|
|
+ private int _receivedDataCount = 0;
|
|
|
+ public string macAddress = null;
|
|
|
+
|
|
|
+ public BluetoothStatusEnum bluetoothStatus;
|
|
|
+
|
|
|
+ private BluetoothWindows _bluetoothWindows;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 6轴
|
|
|
+ /// </summary>
|
|
|
+ private o06DOF.SixAxisFusion sixAxisFusion;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 过滤名称
|
|
|
+ /// </summary>
|
|
|
+ public string filters { get; set; } = "";
|
|
|
+
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 当前的传感器类型
|
|
|
+ /// </summary>
|
|
|
+ public SensorAxisType sensorAxisType { get; set; } = SensorAxisType.NineAxisSensor;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ private void SetStatus(BluetoothStatusEnum newStatus)
|
|
|
+ {
|
|
|
+ BluetoothStatusEnum oldStatus = bluetoothStatus;
|
|
|
+ if (oldStatus == newStatus) return;
|
|
|
+ bluetoothStatus = newStatus;
|
|
|
+ SmartBowLogger.Log(this, $"oldStatus[{oldStatus}]=>newStatus[{newStatus}]");
|
|
|
+ if (newStatus == BluetoothStatusEnum.None)
|
|
|
+ {
|
|
|
+ _bluetoothHelper = null;
|
|
|
+ _bluetoothService = null;
|
|
|
+ _characteristicWrite = null;
|
|
|
+ _receivedDataCount = 0;
|
|
|
+ macAddress = null;
|
|
|
+ _battery = 0;
|
|
|
+ moduleInited = false;
|
|
|
+ }
|
|
|
+ smartBowHelper.InvokeOnBluetoothStatusChanged(oldStatus, newStatus);
|
|
|
+ }
|
|
|
+
|
|
|
+ void Awake()
|
|
|
+ {
|
|
|
+ DontDestroyOnLoad(gameObject);
|
|
|
+ deviceConfig = BluetoothDeviceConfig.GetDefault();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ void Update()
|
|
|
+ {
|
|
|
+ LoopHandleCommands();
|
|
|
+ }
|
|
|
+
|
|
|
+ private static int _NoneToConnectingStep = 0;
|
|
|
+
|
|
|
+ public BluetoothWindows CreateWindowBLE() {
|
|
|
+
|
|
|
+ //如果是window环境,直接实例化一个BluetoothWindows
|
|
|
+ if (BluetoothWindows.IsWindows())
|
|
|
+ {
|
|
|
+ _bluetoothWindows = new BluetoothWindows();
|
|
|
+ _bluetoothWindows.OnConnected = OnConnected_windows;
|
|
|
+ _bluetoothWindows.OnConnectionFailed = OnConnectionFailed_windows;
|
|
|
+ _bluetoothWindows.OnCharacteristicChanged = OnCharacteristicChanged_windows;
|
|
|
+
|
|
|
+ return _bluetoothWindows;
|
|
|
+ }
|
|
|
+
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ public void Connect()
|
|
|
+ {
|
|
|
+ if (BluetoothWindows.IsWindows())
|
|
|
+ {
|
|
|
+ if (bluetoothStatus == BluetoothStatusEnum.None)
|
|
|
+ {
|
|
|
+ _bluetoothWindows.Connect();
|
|
|
+ SetStatus(BluetoothStatusEnum.Connecting);
|
|
|
+
|
|
|
+ //初始化一次六轴解析
|
|
|
+ if (sixAxisFusion == null)
|
|
|
+ {
|
|
|
+ Vector3 accelOffset = Vector3.zero;
|
|
|
+ Vector3 gyroOffset = Vector3.zero;
|
|
|
+ float gForce = 1.0f;
|
|
|
+ float gyroToDegree = 1.0f;
|
|
|
+ sixAxisFusion = new o06DOF.SixAxisFusion(accelOffset, gyroOffset, gForce, gyroToDegree);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (_ScanLocker.Count > 0) return;
|
|
|
+ if (bluetoothStatus != BluetoothStatusEnum.None) return;
|
|
|
+ if (_NoneToConnectingStep > 0) return;
|
|
|
+ _NoneToConnectingStep = 1;
|
|
|
+ if (Application.platform == RuntimePlatform.Android)
|
|
|
+ {
|
|
|
+ if (!BluetoothHelperAndroid_SDK.IsBluetoothEnabled())
|
|
|
+ {
|
|
|
+ HandleConnectError(BluetoothError.BluetoothNotEnabled, "蓝牙开关未打开");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (BluetoothHelperAndroid_SDK.RequestBluetoothPermissions(() =>
|
|
|
+ {
|
|
|
+ _NoneToConnectingStep = 0;
|
|
|
+ Connect();
|
|
|
+ }, (permission) =>
|
|
|
+ {
|
|
|
+ if (permission.Contains("LOCATION"))
|
|
|
+ {
|
|
|
+ HandleConnectError(BluetoothError.LocationPermissionNotGranted, "尚未授予定位权限");
|
|
|
+ }
|
|
|
+ else if (permission.Contains("BLUETOOTH"))
|
|
|
+ {
|
|
|
+ HandleConnectError(BluetoothError.ScanPermissionNotGranted, "尚未授予扫描附近设备权限");
|
|
|
+ }
|
|
|
+ })) return;
|
|
|
+ }
|
|
|
+ try
|
|
|
+ {
|
|
|
+ BluetoothHelper.BLE = true;
|
|
|
+ _bluetoothHelper = BluetoothHelper.GetNewInstance();
|
|
|
+ _bluetoothHelper.OnConnected += OnConnected;
|
|
|
+ _bluetoothHelper.OnConnectionFailed += OnConnectionFailed;
|
|
|
+
|
|
|
+ SmartBowLogger.Log(this,"创建蓝牙的SensorAxisType类型:"+ sensorAxisType);
|
|
|
+ if (sensorAxisType == SensorAxisType.SixAxisSensor)
|
|
|
+ {
|
|
|
+ //6轴时候,另外的解析操作
|
|
|
+ _bluetoothHelper.OnCharacteristicChanged += OnCharacteristicChanged6Axis;
|
|
|
+ //初始化一次六轴解析
|
|
|
+ if (sixAxisFusion == null) {
|
|
|
+ Vector3 accelOffset = Vector3.zero;
|
|
|
+ Vector3 gyroOffset = Vector3.zero;
|
|
|
+ float gForce = 1.0f;
|
|
|
+ float gyroToDegree = 1.0f;
|
|
|
+ sixAxisFusion = new o06DOF.SixAxisFusion(accelOffset, gyroOffset, gForce, gyroToDegree);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ //九轴的解析
|
|
|
+ _bluetoothHelper.OnCharacteristicChanged += OnCharacteristicChanged;
|
|
|
+ }
|
|
|
+
|
|
|
+ _bluetoothHelper.OnScanEnded += OnScanEnded;
|
|
|
+ _bluetoothHelper.ScanNearbyDevices();
|
|
|
+ _NoneToConnectingStep = 2;
|
|
|
+ }
|
|
|
+ catch (Exception e)
|
|
|
+ {
|
|
|
+ HandleConnectError(BluetoothError.Unknown, e.ToString());
|
|
|
+ }
|
|
|
+ if (_NoneToConnectingStep == 2)
|
|
|
+ {
|
|
|
+ _NoneToConnectingStep = 0;
|
|
|
+ _ScanLocker.Add(_bluetoothHelper);
|
|
|
+ SetStatus(BluetoothStatusEnum.Connecting);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void HandleConnectError(BluetoothError error, string message)
|
|
|
+ {
|
|
|
+ _NoneToConnectingStep = 0;
|
|
|
+ smartBowHelper.InvokeOnBluetoothError(error, message);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Disconnect()
|
|
|
+ {
|
|
|
+ //断开连接时候清除AimDeviceInfo
|
|
|
+ ResetAimDeviceInfoToNull();
|
|
|
+
|
|
|
+ if (BluetoothWindows.IsWindows())
|
|
|
+ {
|
|
|
+ if (_bluetoothWindows.Disconnect())
|
|
|
+ SetStatus(BluetoothStatusEnum.None);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (_bluetoothHelper != null)
|
|
|
+ _bluetoothHelper.Disconnect();
|
|
|
+ SetStatus(BluetoothStatusEnum.None);
|
|
|
+ }
|
|
|
+
|
|
|
+ void OnConnected(BluetoothHelper helper)
|
|
|
+ {
|
|
|
+ if (helper != _bluetoothHelper) return;
|
|
|
+ SetStatus(BluetoothStatusEnum.Connected);
|
|
|
+ foreach (BluetoothHelperService service in helper.getGattServices())
|
|
|
+ {
|
|
|
+ if (service.getName().ToLower().StartsWith(deviceConfig.service))
|
|
|
+ {
|
|
|
+ _bluetoothService = service;
|
|
|
+ foreach (BluetoothHelperCharacteristic characteristic in service.getCharacteristics())
|
|
|
+ {
|
|
|
+ if (characteristic.getName().ToLower().StartsWith(deviceConfig.characteristicWrite))
|
|
|
+ {
|
|
|
+ _characteristicWrite = characteristic;
|
|
|
+ }
|
|
|
+ else if (characteristic.getName().ToLower().StartsWith(deviceConfig.characteristicNotify))
|
|
|
+ {
|
|
|
+ BluetoothHelperCharacteristic c = new BluetoothHelperCharacteristic(characteristic.getName());
|
|
|
+ c.setService(_bluetoothService.getName());
|
|
|
+ _bluetoothHelper.Subscribe(c);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //指令区分
|
|
|
+ if (sensorAxisType == SensorAxisType.SixAxisSensor)
|
|
|
+ {
|
|
|
+ //6轴指令
|
|
|
+ StartCoroutine(InitWhenConnected6Axis());
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //九轴
|
|
|
+ StartCoroutine(InitWhenConnected());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ void OnConnected_windows()
|
|
|
+ {
|
|
|
+ SetStatus(BluetoothStatusEnum.Connected);
|
|
|
+
|
|
|
+ if (sensorAxisType == SensorAxisType.SixAxisSensor)
|
|
|
+ {
|
|
|
+ //6轴指令
|
|
|
+ StartCoroutine(InitWhenConnected6Axis());
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //九轴
|
|
|
+ StartCoroutine(InitWhenConnected());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void OnConnectionFailed(BluetoothHelper helper)
|
|
|
+ {
|
|
|
+ if (helper != _bluetoothHelper) return;
|
|
|
+ SetStatus(BluetoothStatusEnum.None);
|
|
|
+ }
|
|
|
+ void OnConnectionFailed_windows()
|
|
|
+ {
|
|
|
+ SetStatus(BluetoothStatusEnum.None);
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 原九轴的传感器解析
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="helper"></param>
|
|
|
+ /// <param name="value"></param>
|
|
|
+ /// <param name="characteristic"></param>
|
|
|
+ void OnCharacteristicChanged(BluetoothHelper helper, byte[] value, BluetoothHelperCharacteristic characteristic)
|
|
|
+ {
|
|
|
+ if (helper != _bluetoothHelper) return;
|
|
|
+ if (bluetoothStatus != BluetoothStatusEnum.Connected) return;
|
|
|
+ byte[] bytes = value;
|
|
|
+ if (macAddress == null && _receivedDataCount++ < 500) ParseMacAddress(value);
|
|
|
+ smartBowHelper.aimHandler.OnDataReceived(bytes);
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 六轴传感器时候使用的解析
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="helper"></param>
|
|
|
+ /// <param name="value"></param>
|
|
|
+ /// <param name="characteristic"></param>
|
|
|
+ void OnCharacteristicChanged6Axis(BluetoothHelper helper, byte[] value, BluetoothHelperCharacteristic characteristic)
|
|
|
+ {
|
|
|
+ if (helper != _bluetoothHelper) return;
|
|
|
+ if (bluetoothStatus != BluetoothStatusEnum.Connected) return;
|
|
|
+ byte[] bytes = value;
|
|
|
+ if (macAddress == null && _receivedDataCount++ < 500) ParseMacAddress(value);
|
|
|
+ //smartBowHelper.aimHandler.OnDataReceived(bytes);
|
|
|
+ //转字符串后就是 Bat
|
|
|
+ if (bytes.Length == 20 && bytes[19] == 0x0a
|
|
|
+ //Bat
|
|
|
+ && bytes[2] == 0x42 && bytes[3] == 0x61 && bytes[4] == 0x74) {
|
|
|
+ //第一步 解析电量?
|
|
|
+ string betty = System.Text.Encoding.ASCII.GetString(bytes);
|
|
|
+ // SmartBowLogger.Log(this, BitConverter.ToString(bytes).Replace("-", ""));
|
|
|
+ //SmartBowLogger.Log(this, "betty:" + betty);
|
|
|
+ // 第二步:解析JSON字符串
|
|
|
+ Newtonsoft.Json.Linq.JObject json = Newtonsoft.Json.Linq.JObject.Parse(betty);
|
|
|
+ // 第三步:提取"Bat"的值
|
|
|
+ int batValue = (int)json["Bat"];
|
|
|
+ SmartBowLogger.Log(this, "Bat Value: " + batValue); // 输出: 100
|
|
|
+ battery = batValue;
|
|
|
+ }
|
|
|
+ //传感器数据
|
|
|
+ if (bytes.Length == 20 && bytes[0] == 0x7b && bytes[19] == 0x7d)
|
|
|
+ {
|
|
|
+ o06DOF.SixData sixData = sixAxisFusion.getSixAxisByBytes(bytes);
|
|
|
+ Quaternion quaternion = sixAxisFusion.tranUpdateData(sixData);
|
|
|
+ //输出欧拉角 pitch yaw roll
|
|
|
+ smartBowHelper.InvokeOnSixAxisRotationUpdate(quaternion.eulerAngles);
|
|
|
+ //smartBowHelper.InvokeOnAxisDataUpdateEvent(bytes);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 重置6轴identify
|
|
|
+ /// </summary>
|
|
|
+ public void ResetSixAxisFusion() {
|
|
|
+ if (sixAxisFusion != null) {
|
|
|
+ sixAxisFusion.ResetToInitialRotation();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// pc调用
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="deviceId"></param>
|
|
|
+ /// <param name="value"></param>
|
|
|
+ void OnCharacteristicChanged_windows(string deviceId, byte[] value)
|
|
|
+ {
|
|
|
+ if (sensorAxisType == SensorAxisType.SixAxisSensor)
|
|
|
+ {
|
|
|
+ //6轴指令
|
|
|
+ OnCharacteristicChanged6Axis(null, value, null);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //九轴
|
|
|
+ OnCharacteristicChanged(null, value, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ void OnScanEnded(BluetoothHelper helper, LinkedList<BluetoothDevice> nearbyDevices)
|
|
|
+ {
|
|
|
+ _ScanLocker.Remove(helper);
|
|
|
+ if (helper != _bluetoothHelper) return;
|
|
|
+ foreach (BluetoothDevice device in nearbyDevices)
|
|
|
+ {
|
|
|
+ SmartBowLogger.Log(this, $"发现设备{device.DeviceName},is fileters empty:{ string.IsNullOrEmpty(filters)},name:{filters}");
|
|
|
+ //if (device.DeviceName == deviceConfig.deviceName)
|
|
|
+ //后续匹配名字 可以是多个设备
|
|
|
+ string _filters = string.IsNullOrEmpty(filters) ? deviceConfig.deviceName : filters;
|
|
|
+ if (_filters.Contains(device.DeviceName))
|
|
|
+ {
|
|
|
+ _bluetoothHelper.setDeviceName(device.DeviceName);
|
|
|
+ _bluetoothHelper.Connect();
|
|
|
+ SmartBowLogger.Log(this, $"匹配设备{device.DeviceName}");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ SetStatus(BluetoothStatusEnum.None);
|
|
|
+ smartBowHelper.InvokeOnBluetoothError(BluetoothError.ScanNotFoundTargetDevice, "扫描结束后未发现目标设备");
|
|
|
+ }
|
|
|
+
|
|
|
+ private float _lastWriteDataTime;
|
|
|
+ bool WriteData(string data)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (BluetoothWindows.IsWindows())
|
|
|
+ {
|
|
|
+ return _bluetoothWindows.Write(data);
|
|
|
+ }
|
|
|
+ BluetoothHelperCharacteristic c = new BluetoothHelperCharacteristic(_characteristicWrite.getName());
|
|
|
+ c.setService(_bluetoothService.getName());
|
|
|
+ _bluetoothHelper.WriteCharacteristic(c, data);
|
|
|
+ _lastWriteDataTime = Time.realtimeSinceStartup;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ catch (Exception e)
|
|
|
+ {
|
|
|
+ Debug.LogError(e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ bool WriteByteData(byte[] data)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (BluetoothWindows.IsWindows())
|
|
|
+ {
|
|
|
+ return _bluetoothWindows.WriteByte(data);
|
|
|
+ }
|
|
|
+ BluetoothHelperCharacteristic c = new BluetoothHelperCharacteristic(_characteristicWrite.getName());
|
|
|
+ c.setService(_bluetoothService.getName());
|
|
|
+ _bluetoothHelper.WriteCharacteristic(c, data);
|
|
|
+ _lastWriteDataTime = Time.realtimeSinceStartup;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ catch (Exception e)
|
|
|
+ {
|
|
|
+ Debug.LogError(e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public bool moduleInited;
|
|
|
+ private string _connectedHandlerID = "";
|
|
|
+ IEnumerator InitWhenConnected()
|
|
|
+ {
|
|
|
+ string myConnectedHandlerID = Guid.NewGuid().ToString();
|
|
|
+ _connectedHandlerID = myConnectedHandlerID;
|
|
|
+ yield return new WaitForSecondsRealtime(BluetoothWindows.IsWindows() ? 0.3f : 2.2f);
|
|
|
+ Queue<string> cmds = new Queue<string>(new string[] { "M", "b", "b", "1" });
|
|
|
+ while (cmds.Count > 0)
|
|
|
+ {
|
|
|
+ if (bluetoothStatus != BluetoothStatusEnum.Connected || myConnectedHandlerID != _connectedHandlerID) yield break;
|
|
|
+ string cmd = cmds.Dequeue();
|
|
|
+ WriteData(cmd);
|
|
|
+ yield return new WaitForSecondsRealtime(0.3f);
|
|
|
+ }
|
|
|
+ if (bluetoothStatus != BluetoothStatusEnum.Connected || myConnectedHandlerID != _connectedHandlerID) yield break;
|
|
|
+ StartCoroutine(LoopRequestBattery(myConnectedHandlerID));
|
|
|
+ moduleInited = true;
|
|
|
+ smartBowHelper.InvokeOnBluetoothModuleInited();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 初始化6轴指令
|
|
|
+ /// </summary>
|
|
|
+ /// <returns></returns>
|
|
|
+ IEnumerator InitWhenConnected6Axis()
|
|
|
+ {
|
|
|
+ string myConnectedHandlerID = Guid.NewGuid().ToString();
|
|
|
+ _connectedHandlerID = myConnectedHandlerID;
|
|
|
+ yield return new WaitForSecondsRealtime(BluetoothWindows.IsWindows() ? 0.3f : 2.2f);
|
|
|
+ Queue<string> cmds = new Queue<string>(new string[] { "M", "B", "B" });
|
|
|
+ while (cmds.Count > 0)
|
|
|
+ {
|
|
|
+ if (bluetoothStatus != BluetoothStatusEnum.Connected || myConnectedHandlerID != _connectedHandlerID) yield break;
|
|
|
+ string cmd = cmds.Dequeue();
|
|
|
+ WriteData(cmd);
|
|
|
+ yield return new WaitForSecondsRealtime(0.3f);
|
|
|
+ }
|
|
|
+ if (bluetoothStatus != BluetoothStatusEnum.Connected || myConnectedHandlerID != _connectedHandlerID) yield break;
|
|
|
+ StartCoroutine(LoopRequestBattery6Axis(myConnectedHandlerID));
|
|
|
+ moduleInited = true;
|
|
|
+ smartBowHelper.InvokeOnBluetoothModuleInited();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private int _battery = 0;
|
|
|
+ public int battery
|
|
|
+ {
|
|
|
+ get => _battery;
|
|
|
+ set
|
|
|
+ {
|
|
|
+ _battery = value;
|
|
|
+ //SmartBowLogger.Log(this, "Battery缓存成功");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 九轴原本的连接电池指令
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="myConnectedHandlerID"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ IEnumerator LoopRequestBattery(string myConnectedHandlerID)
|
|
|
+ {
|
|
|
+ while (bluetoothStatus == BluetoothStatusEnum.Connected && myConnectedHandlerID == _connectedHandlerID)
|
|
|
+ {
|
|
|
+ yield return new WaitForSecondsRealtime(10);
|
|
|
+ AddCommandToQueue("b");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 6轴的连接电池指令
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="myConnectedHandlerID"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ IEnumerator LoopRequestBattery6Axis(string myConnectedHandlerID)
|
|
|
+ {
|
|
|
+ while (bluetoothStatus == BluetoothStatusEnum.Connected && myConnectedHandlerID == _connectedHandlerID)
|
|
|
+ {
|
|
|
+ yield return new WaitForSecondsRealtime(10);
|
|
|
+ AddCommandToQueue("B");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<string> _commands = new List<string>();
|
|
|
+ void LoopHandleCommands()
|
|
|
+ {
|
|
|
+ if (bluetoothStatus != BluetoothStatusEnum.Connected || !moduleInited)
|
|
|
+ {
|
|
|
+ if (_commands.Count > 0) _commands.Clear();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (Time.realtimeSinceStartup - _lastWriteDataTime < 0.2f) return;
|
|
|
+ if (_commands.Count == 0) return;
|
|
|
+ string cmd = _commands[0];
|
|
|
+ _commands.RemoveAt(0);
|
|
|
+ WriteData(cmd);
|
|
|
+ }
|
|
|
+ bool AddCommandToQueue(string cmd)
|
|
|
+ {
|
|
|
+ if (bluetoothStatus != BluetoothStatusEnum.Connected || !moduleInited) return false;
|
|
|
+ //如果待插入的指令跟队尾的指令一样,就不要插入了,因为冗余的指令无意义
|
|
|
+ if (_commands.Count > 0 && _commands[_commands.Count - 1].Equals(cmd)) return true;
|
|
|
+ _commands.Add(cmd);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void ReplyInfraredShoot()
|
|
|
+ {
|
|
|
+
|
|
|
+ if (bluetoothStatus != BluetoothStatusEnum.Connected || !moduleInited) return;
|
|
|
+ WriteData("I");
|
|
|
+ }
|
|
|
+
|
|
|
+ public void ReplyByte(byte[] value)
|
|
|
+ {
|
|
|
+
|
|
|
+ if (bluetoothStatus != BluetoothStatusEnum.Connected || !moduleInited) return;
|
|
|
+ WriteByteData(value);
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool RequestOpen9Axis()
|
|
|
+ {
|
|
|
+ return AddCommandToQueue("3");
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool RequestClose9Axis()
|
|
|
+ {
|
|
|
+ return AddCommandToQueue("4");
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool RequestOpenInfrared()
|
|
|
+ {
|
|
|
+ return AddCommandToQueue("w");
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool RequestCloseInfrared()
|
|
|
+ {
|
|
|
+ return AddCommandToQueue("s");
|
|
|
+ }
|
|
|
+
|
|
|
+ void ParseMacAddress(byte[] bytes)
|
|
|
+ {
|
|
|
+ string mac = System.Text.Encoding.ASCII.GetString(bytes);
|
|
|
+ if (mac != null) mac = mac.Trim();
|
|
|
+ if (CheckIsMacValid(mac))
|
|
|
+ {
|
|
|
+ #region 根据aimDeviceInfo存在添加一个判断
|
|
|
+ if (aimDeviceInfo != null) {
|
|
|
+ //需要增加一个判断,判断是否对应的mac设备。不是需要进行重新连接
|
|
|
+ if (!aimDeviceInfo.bInitMac)
|
|
|
+ {
|
|
|
+ SmartBowLogger.Log(this, "设置设备mac:" + mac);
|
|
|
+ SetAimDeviceMac(mac);
|
|
|
+ }
|
|
|
+ else if (aimDeviceInfo.mac != mac)
|
|
|
+ {
|
|
|
+ SmartBowLogger.LogError(this, "设备不一样,断开连接");
|
|
|
+ Disconnect();
|
|
|
+ //抛出一个错误,给用户处理其他业务流程
|
|
|
+ smartBowHelper.InvokeOnBluetoothError(BluetoothError.MacAddressAndDeviceMismatch, "验证设备MAC和记录的MAC不匹配!");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ macAddress = mac;
|
|
|
+ SmartBowLogger.Log(this, "MacAddress解析成功");
|
|
|
+ //获取MacAddress对应的校准记录
|
|
|
+ string macXXX = macAddress;
|
|
|
+ smartBowHelper.smartBowNetwork.GetCalibrateRecord(macXXX, (record) =>
|
|
|
+ {
|
|
|
+ if (macAddress != macXXX) return;
|
|
|
+ smartBowHelper.aimHandler.ResumeCalibrateRecord(record);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ else SmartBowLogger.LogWarning(this, "MacAddress解析失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ bool CheckIsMacValid(string mac)
|
|
|
+ {
|
|
|
+ if (mac == null) return false;
|
|
|
+ if (!mac.StartsWith("{")) return false;
|
|
|
+ if (!mac.EndsWith("}")) return false;
|
|
|
+ if (!mac.Contains(":")) return false;
|
|
|
+ char[] validChars = { '{', '}', ':', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
|
|
+ foreach (var c in mac.ToCharArray())
|
|
|
+ {
|
|
|
+ if (Array.IndexOf(validChars, c) == -1) return false;
|
|
|
+ }
|
|
|
+ if (mac.Length != 19) return false;
|
|
|
+ string macNoneFrame = mac.Substring(1, mac.Length - 2);
|
|
|
+ string[] macNoneFrameSplits = macNoneFrame.Split(':');
|
|
|
+ if (macNoneFrameSplits.Length != 6) return false;
|
|
|
+ foreach (var item in macNoneFrameSplits)
|
|
|
+ {
|
|
|
+ if (item.Length != 2) return false;
|
|
|
+ foreach (var c in item.ToCharArray())
|
|
|
+ if (Array.IndexOf(validChars, c) < 3) return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ #region 记录的设备处理部分
|
|
|
+ //连接时候判断信息。存在对象则连接需要判断MAC
|
|
|
+ //记录一个设备
|
|
|
+ AimDeviceInfo aimDeviceInfo = null;
|
|
|
+ //用户初始化一个保存数据的操作的id。
|
|
|
+ //不设置情况下不给进行相关操作
|
|
|
+ string keyPrefix = "aim-device-info-";
|
|
|
+ string userTags = "";
|
|
|
+ int deviceId = -1;
|
|
|
+
|
|
|
+ //清空对应id的数据
|
|
|
+ public void onClearAimDeviceInfoByDeviceId(string _userTags, int _deviceId)
|
|
|
+ {
|
|
|
+ string deviceInfo = PlayerPrefs.GetString(keyPrefix + _userTags + _deviceId, "");
|
|
|
+ if (deviceInfo != "") {
|
|
|
+ PlayerPrefs.DeleteKey(keyPrefix + _userTags + _deviceId);
|
|
|
+ ResetAimDeviceInfoToNull();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public AimDeviceInfo onGetAimDeviceInfos(string _userTags, int _deviceId)
|
|
|
+ {
|
|
|
+ OnGetAimDeviceInfo(_userTags, _deviceId);
|
|
|
+ //SmartBowLogger.Log(this, $"onGetAimDeviceInfos[{JsonUtility.ToJson(aimDeviceInfo)}]");
|
|
|
+ return aimDeviceInfo;
|
|
|
+ }
|
|
|
+ //根据设置的
|
|
|
+ void OnGetAimDeviceInfo(string _userTags, int _deviceId)
|
|
|
+ {
|
|
|
+ string deviceInfo = PlayerPrefs.GetString(keyPrefix + _userTags + _deviceId, "");
|
|
|
+ if (deviceInfo != "")
|
|
|
+ {
|
|
|
+ aimDeviceInfo = JsonUtility.FromJson<AimDeviceInfo>(deviceInfo);//这里的类是依据最外层{}决定的
|
|
|
+ }
|
|
|
+ }
|
|
|
+ void OnSaveAimDeviceInfo(string _userTags, int _deviceId)
|
|
|
+ {
|
|
|
+ if (_userTags.Length == 0)
|
|
|
+ {
|
|
|
+ SmartBowLogger.LogError(this, $"存储标识不存在!");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ SmartBowLogger.Log(this, $"OnSaveAimDeviceInfo [{JsonUtility.ToJson(aimDeviceInfo)}]");
|
|
|
+ PlayerPrefs.SetString(keyPrefix + _userTags + _deviceId, JsonUtility.ToJson(aimDeviceInfo));
|
|
|
+ }
|
|
|
+
|
|
|
+ //连接蓝牙调用。连接时候创建一个连接信息,用于记录mac 是否要验证
|
|
|
+ //传入一个id用于区分是哪个设备
|
|
|
+ //bRecreateDeviceInfo 是否重新创建
|
|
|
+ public void initAimDeviceInfo(string _userTags, int _deviceId, bool bRecreateDeviceInfo)
|
|
|
+ {
|
|
|
+ userTags = _userTags;
|
|
|
+ deviceId = _deviceId;
|
|
|
+
|
|
|
+ if (bRecreateDeviceInfo)
|
|
|
+ {
|
|
|
+ //直接覆盖设备信息
|
|
|
+ onRecreateAimDeviceInfoById();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //获取设备信息。没有创建
|
|
|
+ onCreateAimDeviceInfoById();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //是否存在AimDeviceInfo,存在获取,不存在创建;
|
|
|
+ void onCreateAimDeviceInfoById()
|
|
|
+ {
|
|
|
+ ResetAimDeviceInfoToNull();
|
|
|
+ OnGetAimDeviceInfo(userTags, deviceId);
|
|
|
+ if (aimDeviceInfo == null)
|
|
|
+ {
|
|
|
+ aimDeviceInfo = new AimDeviceInfo(deviceId);
|
|
|
+ OnSaveAimDeviceInfo(userTags, deviceId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //直接覆盖新元素
|
|
|
+ void onRecreateAimDeviceInfoById()
|
|
|
+ {
|
|
|
+ // 使用Lambda表达式删除特定条件的元素
|
|
|
+ ResetAimDeviceInfoToNull();
|
|
|
+ //添加一个新元素
|
|
|
+ aimDeviceInfo = new AimDeviceInfo(deviceId);
|
|
|
+ //更新信息
|
|
|
+ OnSaveAimDeviceInfo(userTags, deviceId);
|
|
|
+ }
|
|
|
+
|
|
|
+ //APP连接需进行MAC地址的比对。
|
|
|
+ void SetAimDeviceMac(string _mac)
|
|
|
+ {
|
|
|
+ aimDeviceInfo.setInitMac(_mac);
|
|
|
+ OnSaveAimDeviceInfo(userTags, deviceId);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void ResetAimDeviceInfoToNull()
|
|
|
+ {
|
|
|
+ aimDeviceInfo = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+ }
|
|
|
+
|
|
|
+ #region 添加一个记录设备连接的信息,主要用于判断mac地址是否连接操作
|
|
|
+
|
|
|
+ [Serializable]//需要在转换为json格式的类的上方添加序列化
|
|
|
+ public class AimDeviceInfo
|
|
|
+ {
|
|
|
+ public int id; //区分用户设备对应的id
|
|
|
+ public bool bInitMac = false; //是否初始化Mac
|
|
|
+ public string mac; //记录当前
|
|
|
+
|
|
|
+ public AimDeviceInfo(int _id)
|
|
|
+ {
|
|
|
+ this.id = _id;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setInitMac(string macTemp)
|
|
|
+ {
|
|
|
+ bInitMac = true;
|
|
|
+ mac = macTemp;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void resetInitMac()
|
|
|
+ {
|
|
|
+ bInitMac = false;
|
|
|
+ mac = "";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+}
|