using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine; using static Pc2McuProto; public static class UDE_API { private const string package_name = "cn.wch.ch9140lib"; static AndroidJavaClass UnityPlayer; static AndroidJavaObject CurrentActivity; static AndroidJavaObject App; static AndroidJavaClass CH9140BluetoothManager; static AndroidJavaObject ManagerInstance; static ConcurrentDictionary DeviceMacDir; //线程保护的字典,key是蓝牙名,value是mac地址 static ConcurrentDictionary DeviceDir; private static bool isSearchVaild = true; //是否准许搜索设备 static ConcurrentDictionary DeviceConnectState; /// /// 初始化 /// public static void UDE_Init() { DeviceConnectState = new ConcurrentDictionary(); DeviceMacDir = new ConcurrentDictionary(); DeviceDir = new ConcurrentDictionary(); // UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); // CurrentActivity = UnityPlayer.GetStatic("currentActivity"); // App = CurrentActivity.Call("getApplication"); // // CH9140BluetoothManager = new AndroidJavaClass(package_name + ".CH9140BluetoothManager"); // ManagerInstance = CH9140BluetoothManager.CallStatic("getInstance"); // // ManagerInstance.Call("init", App); BluetoothLEHardwareInterface.Initialize(true, false, () => { }, (error) => { Debug.LogError($"UDE Init Faild ,{error}"); }); //registerSerialModemNotify(); Debug.Log("UDE:" + "Init Success!!"); } /// /// 启动搜索设备 /// public static void StartEnumDevices() { DeviceDir.Clear(); BluetoothLEHardwareInterface.ScanForPeripheralsWithServices(null, (address, name) => { if (name.Contains("UDST")) { Debug.Log("UDE:" + $"Enum Result {name}"); if (string.IsNullOrEmpty(address)) { Debug.Log("UDE:" + "Device is Invalid!!"); //LogUtil.d("该设备不是合法设备"); return; } RegisterDevice(name, address); } }, null); // EnumResult enumResult = new EnumResult();//创建一个回调对象 // Debug.Log("UDE:" + "Start Enum Devices!!"); // ManagerInstance.Call("startEnumDevices", enumResult); // Debug.Log("UDE:" + "Start Enum Devices Success!!"); } /// /// 停止搜索设备 /// public static void StopEnumDevices() { BluetoothLEHardwareInterface.StopScan(); Debug.Log("UDE:" + "Stop Enum Deivces!!"); } /// /// 注册设备 /// /// 设备名 /// 地址 private static void RegisterDevice(string name, string mac) { if (DeviceMacDir.ContainsKey(name)) { DeviceMacDir[name] = mac; return; } DeviceMacDir.TryAdd(name, mac); UDE_Device device = new UDE_Device(); DeviceDir.TryAdd(mac, device); } /// /// 取消注册设备 /// /// 需要取消的设备名 /// public static bool UnRegisterDevice(string name) { string mac = DeviceMacDir[name]; bool result = DeviceDir.TryRemove(mac, out UDE_Device _); result &= DeviceMacDir.TryRemove(name, out string _); return result; } /// /// 获取设备名的集合 /// /// public static List GetDeviceList() { return DeviceMacDir.Keys.ToList(); } /// /// 按照名字开启设备 /// /// public static bool OpenDeviceByName(string name, Action action = null) { if (!DeviceMacDir.ContainsKey(name)) { return false; } string mac = DeviceMacDir[name]; DeviceDir[mac].OpenDevice(mac, action); SetConnectByMac(mac, false); return true; } /// /// 按照名字关闭设备 /// /// public static bool CloseDeviceByName(string name) { if (!DeviceMacDir.ContainsKey(name)) { return false; } string mac = DeviceMacDir[name]; DeviceDir[mac].CloseDevice(mac, true); return true; } public static string GetDeviceDataByName(string name) { if (DeviceMacDir == null || !DeviceMacDir.ContainsKey(name)) { return null; } string mac = DeviceMacDir[name]; Debug.Log($"name :{name},mac:{mac}"); return DeviceDir[mac].GetDeviceData(); } public static int GetDeviceBatteryByName(string name) { if (DeviceMacDir == null || !DeviceMacDir.ContainsKey(name)) { return 0; } string mac = DeviceMacDir[name]; Debug.Log($"name :{name},mac:{mac}"); return DeviceDir[mac].GetBatteryType(); } /// /// 开启接收蓝牙数据 /// public static void Pc2Mcu_StartReceive(string name) { if (name == null) { return; } if (!DeviceMacDir.ContainsKey(name)) { return; } string mac = DeviceMacDir[name]; DeviceDir[mac].Pc2Mcu_StartReceive(mac); } /// /// 停止接收蓝牙数据 /// public static void Pc2Mcu_StopReceive(string name) { if (!DeviceMacDir.ContainsKey(name)) { return; } string mac = DeviceMacDir[name]; DeviceDir[mac].Pc2Mcu_StopReceive(mac); } /// /// /// public static void Pc2Mcu_StringData(string name) { if (!DeviceMacDir.ContainsKey(name)) { return; } string mac = DeviceMacDir[name]; DeviceDir[mac].Pc2Mcu_StringData(mac); } /// /// 发送振动反馈 /// public static void Pc2Mcu_SendVibration(string name, byte address, byte time, byte stren) { if (!DeviceMacDir.ContainsKey(name)) { return; } string mac = DeviceMacDir[name]; DeviceDir[mac].Pc2Mcu_SendVibration(mac, address, time, stren); } /// /// 启动心跳 /// public static void OnHeartBeat(string name) { if (name == null) { return; } if (!DeviceMacDir.ContainsKey(name)) { return; } string mac = DeviceMacDir[name]; DeviceDir[mac].OnHeartBeat(mac); Debug.Log($"[HeartBeat] in {DateTime.Now.ToString("G")}"); } /// /// 是否连接 /// /// public static bool IsCon() { bool result = false; foreach (var item in DeviceConnectState.Values) { //Debug.Log("---iscon---" + item.ToString() + "//" + item.Value.IsCon); result |= item; } return result; } public static void SetMTU(string name, int mtu) { if (!DeviceMacDir.ContainsKey(name)) { return; } string mac = DeviceMacDir[name]; DeviceDir[mac].SetMtu(mac, mtu); } public static void SetMTUByMac(string mac, int mtu) { if (!DeviceDir.ContainsKey(mac)) { return; } DeviceDir[mac].SetMtu(mac, mtu); } /// /// 获取最大传输单元 /// /// public static int GetMTUByMac(string mac) { if (!DeviceDir.ContainsKey(mac)) { return -1; } return DeviceDir[mac].GetMTU(mac); } public static bool SetSerialBaudByMac(string mac) { if (!DeviceMacDir.ContainsKey(mac)) { return false; } return DeviceDir[mac].SetSerialBaud(mac); } /// /// 设置串行调制解调器 /// /// public static bool SetSerialModemByMac(string mac) { if (!DeviceMacDir.ContainsKey(mac)) { return false; } return DeviceDir[mac].SetSerialModem(mac); } public static void SetSearchVaild(bool flag) { isSearchVaild = flag; } public static bool IsSupportedFirmware() { return ManagerInstance.Call("isSupportedFirmware"); } public static bool IsSearchVaild() { return isSearchVaild; } public static bool CheckConnectByName(string Device_name) { if (Device_name == string.Empty || !DeviceMacDir.ContainsKey(Device_name)) { return false; } string mac = DeviceMacDir[Device_name]; if (!DeviceDir.ContainsKey(mac)) { return false; } return DeviceDir[mac].IsConnect; } public static void SetConnectByMac(string mac, bool connect) { DeviceConnectState[mac] = connect; } public static int GetTransferFrequency(string name) { if (!DeviceMacDir.ContainsKey(name)) { return 0; } string mac = DeviceMacDir[name]; return DeviceDir[mac].Transfer_freq; } /// /// 开启搜索的回调 /// public class EnumResult : AndroidJavaProxy { public EnumResult() : base("cn.wch.ch9140lib.callback.EnumResult") { } public void onResult(AndroidJavaObject device, int var2, byte[] var3) { Debug.Log("UDE:" + $"onResult!!"); string name = device.Call("getName"); string mac = device.Call("getAddress"); Debug.Log("UDE:" + $"Enum Result {name}"); if (string.IsNullOrEmpty(mac)) { Debug.Log("UDE:" + "Device is Invalid!!"); //LogUtil.d("该设备不是合法设备"); return; } RegisterDevice(name, mac); //UDE_API.StopEnumDevices(); //UDE_API.OpenDevice(mac); } } } public class UDE_Device { ConcurrentDictionary DeviceDir; //线程保护的字典,key是蓝牙名,value是mac地址 private string data_s; private readonly string serivce_uuid = "8653000a-43e6-47b7-9cb0-5fc21d4ae340"; private readonly string write_character_uuid = "8653000c-43e6-47b7-9cb0-5fc21d4ae340"; private readonly string read_character_uuid = "8653000b-43e6-47b7-9cb0-5fc21d4ae340"; int index = 0; List one_buff = new List(); private int buff_len = int.MaxValue; private int count = 0; public int Transfer_freq; private DateTime last_time; public bool IsConnect = false; public Action ConnectListener; private int last_battery = 0; private int _batteryType = 0; public int BatteryType { get => _batteryType; set { _batteryType = value; } } /// /// 开启设备 /// /// 设备地址 public void OpenDevice(string mac, Action action = null) { ConnectListener = action; Debug.Log("UDE:" + $"Start Open Device {mac} !!"); BluetoothLEHardwareInterface.ConnectToPeripheral(mac, (address) => { }, null, (address, service, characteristic) => { Debug.Log("UDE:" + $"{address} Connect Success!!!"); IsConnect = true; Pc2Mcu_StartReceive(mac); ConnectListener?.Invoke(address, IsConnect); }); UDE_API.SetSearchVaild(false); } /// /// 蓝牙读取数据解析 /// /// 蓝牙数据链表 private void ReadBuffAnalysis(List read_buff_list) { byte[] read_buff = read_buff_list.ToArray(); StringBuilder msg = new StringBuilder(); Mcu2PcProto mcu2PcProto = new Mcu2PcProto(); mcu2PcProto.crc = read_buff[read_buff.Length - 1]; if (mcu2PcProto.crc != Pc2McuProto.check_num(read_buff, read_buff.Length)) { return; } if (read_buff[0] != 0xAA) { return; } if (read_buff[1] != 0x55) { return; } mcu2PcProto.Address = read_buff[2]; mcu2PcProto.CommandType = read_buff[3]; mcu2PcProto.DataType = read_buff[4]; mcu2PcProto.DataLength = read_buff[5]; byte[] decrypt_data = new byte[mcu2PcProto.DataLength]; Array.Copy(read_buff, 6, decrypt_data, 0, decrypt_data.Length); decrypt(decrypt_data, (short)decrypt_data.Length); if (mcu2PcProto.CommandType == CommandType.BATTERY_VOLTAGE_DATA) { short[] int16arry = new short[1]; ConvertByte2Int16Aarry(decrypt_data, 0, 1, out int16arry); short battery = int16arry[0]; int battery_type; if (battery <= 2180) { battery_type = 1; } else if (battery <= 2290) { battery_type = 2; } else if (battery <= 2350) { battery_type = 3; } else if (battery <= 2500) { battery_type = 4; } else { battery_type = 5; } if (battery_type > last_battery) { if (battery <= 2200) { battery_type = 1; } else if (battery <= 2310) { battery_type = 2; } else if (battery <= 2370) { battery_type = 3; } else if (battery <= 2520) { battery_type = 4; } else { battery_type = 5; } } last_battery = battery_type; _batteryType = battery_type; return; } if (mcu2PcProto.CommandType == CommandType.ADC_IMU_16) { ConvertByte2Int16Aarry(decrypt_data, 0, mcu2PcProto.DataLength / 2, out mcu2PcProto.AngleDatas); for (int i = 0; i < mcu2PcProto.AngleDatas.Length; i++) { msg.Append(mcu2PcProto.AngleDatas[i]); if (i != mcu2PcProto.AngleDatas.Length - 1) { msg.Append(","); } } if (last_time == null) { last_time = DateTime.Now; } data_s = msg.ToString(); count++; if (DateTime.Now - last_time > TimeSpan.FromSeconds(1)) { Transfer_freq = count; count = 0; last_time = DateTime.Now; } } } /// /// 解密算法 解密得原始数据 /// void decrypt(byte[] arr, short len) { for (int i = 0; i < len; i++) { arr[i] ^= 0x01; arr[i] ^= 0x80; } } /// /// 将Byte类型数据转换为Ini类型数据 /// public void ConvertByte2Int16Aarry(byte[] buff, int byte_index, int int_length, out short[] data) { data = new short[int_length]; for (int i = 0; i < int_length; i++) { Array.Reverse(buff, byte_index, 2); data[i] = BitConverter.ToInt16(buff, byte_index); byte_index += 2; } } /// /// 关闭设备 /// public void CloseDevice(string mac, bool force) { BluetoothLEHardwareInterface.DisconnectPeripheral(mac, (address) => { Debug.Log("UDE:" + $"Close Device {address}"); IsConnect = false; ConnectListener?.Invoke(address, IsConnect); }); } /// /// 设置传递数据的宽度 /// /// private void SetMTU(string mac, int mtu) { BluetoothLEHardwareInterface.RequestMtu(mac, mtu, (address, mtu1) => { Debug.Log("UDE:" + $"Set MTU Success {mtu1}!!"); }); // ManagerInstance.Call("setMTU", mac,mtu, mtu_callback); } public void SetMtu(string mac, int mtu) { SetMTU(mac, mtu); } /// /// 获取最大传输单元 /// /// public int GetMTU(string mac) { return 200; } /// /// 发送给下位机的实际方法 /// /// /// /// private int Write(string mac, byte[] data, int length) { int len = 0; BluetoothLEHardwareInterface.WriteCharacteristic(mac, serivce_uuid, write_character_uuid, data, length, true, (address) => { UDE_API.SetConnectByMac(address, true); UDE_API.SetSearchVaild(true); Debug.Log("开启了蓝牙:" + $"当前连接状态{true}"); SetMTU(address, 200); Debug.Log("UDE:" + $"Write Success {mac} {address}!!"); BluetoothLEHardwareInterface.SubscribeCharacteristic(mac, serivce_uuid, read_character_uuid, (characteristic) => { }, (characteristic, bytes) => { try { for (int i = 0; i < bytes.Length; i++) { if (index == 0) { if (bytes[i] != 0xAA) { continue; } } if (index == 1) { if (bytes[i] != 0x55) { one_buff.Clear(); index = 0; continue; } } one_buff.Add(bytes[i]); if (index == 5) { buff_len = bytes[i]; } if (index >= buff_len + 6 && buff_len != Int32.MaxValue) { ReadBuffAnalysis(one_buff); one_buff.Clear(); index = 0; buff_len = int.MaxValue; } else { index++; } } } catch (Exception) { throw; } }); //mac = address; }); //Debug.Log("UDE:" + $"Write Data Length {length}"); return len; } /// /// 设置串行波特率 /// /// public bool SetSerialBaud(string mac) { Debug.Log("UDE:" + " Set Serial Baud!!"); return false; } /// /// 设置串行调制解调器 /// /// public bool SetSerialModem(string mac) { Debug.Log("UDE:" + "Set Serial Modem!!"); return false; } private void registerSerialModemNotify() { //ModemStatus modemStatus = new ModemStatus(); //ManagerInstance.Call("registerSerialModemNotify", modemStatus); Debug.Log("UDE:" + "registerSerialModemNotify Success!!"); } /// /// 获取解析出的数据字符串 /// /// public string GetDeviceData() { return data_s; } /// /// 获取电量 /// /// public int GetBatteryType() { return BatteryType; } /// /// 开启接收蓝牙数据 /// public void Pc2Mcu_StartReceive(string mac) { SendMessage(mac, Pc2McuProto.HumanAddress.LeftPalm, Pc2McuProto.CommandType.ADC_IMU_16, new byte[] { 0x02, 0x43, 0x56 }); } /// /// 停止接收蓝牙数据 /// public void Pc2Mcu_StopReceive(string mac) { SendMessage(mac, Pc2McuProto.HumanAddress.LeftPalm, Pc2McuProto.CommandType.StopDataReceive, new byte[] { 0x01 }); } /// /// 接收字符串数据 /// public void Pc2Mcu_StringData(string mac) { SendMessage(mac, Pc2McuProto.HumanAddress.LeftPalm, 0xD0, new byte[] { 0x01 }); } /// /// 发送振动反馈 /// public void Pc2Mcu_SendVibration(string mac, byte address, byte time, byte stren) { SendMessage(mac, Pc2McuProto.HumanAddress.LeftPalm, Pc2McuProto.CommandType.SHAKE_CONTROLLER_COMMAND, new byte[] { address, 0x00,time, stren }); } /// /// 启动心跳 /// public void OnHeartBeat(string mac) { SendMessage(mac, Pc2McuProto.HumanAddress.LeftPalm, Pc2McuProto.CommandType.HeartBeat, new byte[] { 0x42 }); Debug.Log($"[HeartBeat] in {DateTime.Now.ToString("G")}"); } private void SendMessage(string mac, byte humanAddress, byte commandType, byte[] data) { byte[] message = new byte[6 + data.Length]; message[0] = 0x55; message[1] = 0xAA; message[2] = humanAddress; message[3] = commandType; message[4] = (byte)data.Length; for (int i = 0; i < data.Length; i++) { message[5 + i] = data[i]; } byte crc = Pc2McuProto.check_num(message, message.Length); int crc_index = message.Length - 1; message[crc_index] = crc; try { int result = Write(mac, message, message.Length); Debug.Log($"UDE: Write Result---{mac} {message.Length}"); } catch (Exception e) { Debug.LogError(e); } } }