Unity Udexreal开发插件包
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

862 lines
23 KiB

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<string, string> DeviceMacDir; //线程保护的字典,key是蓝牙名,value是mac地址
static ConcurrentDictionary<string, UDE_Device> DeviceDir;
private static bool isSearchVaild = true; //是否准许搜索设备
static ConcurrentDictionary<string, bool> DeviceConnectState;
/// <summary>
/// 初始化
/// </summary>
public static void UDE_Init()
{
DeviceConnectState = new ConcurrentDictionary<string, bool>();
DeviceMacDir = new ConcurrentDictionary<string, string>();
DeviceDir = new ConcurrentDictionary<string, UDE_Device>();
// UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
// CurrentActivity = UnityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
// App = CurrentActivity.Call<AndroidJavaObject>("getApplication");
//
// CH9140BluetoothManager = new AndroidJavaClass(package_name + ".CH9140BluetoothManager");
// ManagerInstance = CH9140BluetoothManager.CallStatic<AndroidJavaObject>("getInstance");
//
// ManagerInstance.Call("init", App);
BluetoothLEHardwareInterface.Initialize(true, false, () => { },
(error) => { Debug.LogError($"UDE Init Faild ,{error}"); });
//registerSerialModemNotify();
Debug.Log("UDE:" + "Init Success!!");
}
/// <summary>
/// 启动搜索设备
/// </summary>
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!!");
}
/// <summary>
/// 停止搜索设备
/// </summary>
public static void StopEnumDevices()
{
BluetoothLEHardwareInterface.StopScan();
Debug.Log("UDE:" + "Stop Enum Deivces!!");
}
/// <summary>
/// 注册设备
/// </summary>
/// <param name="name">设备名</param>
/// <param name="mac">地址</param>
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);
}
/// <summary>
/// 取消注册设备
/// </summary>
/// <param name="name">需要取消的设备名</param>
/// <returns></returns>
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;
}
/// <summary>
/// 获取设备名的集合
/// </summary>
/// <returns></returns>
public static List<string> GetDeviceList()
{
return DeviceMacDir.Keys.ToList();
}
/// <summary>
/// 按照名字开启设备
/// </summary>
/// <param name="name"></param>
public static bool OpenDeviceByName(string name, Action<string, bool> action = null)
{
if (!DeviceMacDir.ContainsKey(name))
{
return false;
}
string mac = DeviceMacDir[name];
DeviceDir[mac].OpenDevice(mac, action);
SetConnectByMac(mac, false);
return true;
}
/// <summary>
/// 按照名字关闭设备
/// </summary>
/// <param name="name"></param>
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();
}
/// <summary>
/// 开启接收蓝牙数据
/// </summary>
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);
}
/// <summary>
/// 停止接收蓝牙数据
/// </summary>
public static void Pc2Mcu_StopReceive(string name)
{
if (!DeviceMacDir.ContainsKey(name))
{
return;
}
string mac = DeviceMacDir[name];
DeviceDir[mac].Pc2Mcu_StopReceive(mac);
}
/// <summary>
///
/// </summary>
public static void Pc2Mcu_StringData(string name)
{
if (!DeviceMacDir.ContainsKey(name))
{
return;
}
string mac = DeviceMacDir[name];
DeviceDir[mac].Pc2Mcu_StringData(mac);
}
/// <summary>
/// 发送振动反馈
/// </summary>
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);
}
/// <summary>
/// 启动心跳
/// </summary>
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")}");
}
/// <summary>
/// 是否连接
/// </summary>
/// <returns></returns>
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);
}
/// <summary>
/// 获取最大传输单元
/// </summary>
/// <returns></returns>
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);
}
/// <summary>
/// 设置串行调制解调器
/// </summary>
/// <returns></returns>
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<bool>("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;
}
/// <summary>
/// 开启搜索的回调
/// </summary>
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<string>("getName");
string mac = device.Call<string>("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<string, string> 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<byte> one_buff = new List<byte>();
private int buff_len = int.MaxValue;
private int count = 0;
public int Transfer_freq;
private DateTime last_time;
public bool IsConnect = false;
public Action<string, bool> ConnectListener;
private int last_battery = 0;
private int _batteryType = 0;
public int BatteryType
{
get => _batteryType;
set
{
_batteryType = value;
}
}
/// <summary>
/// 开启设备
/// </summary>
/// <param name="mac">设备地址</param>
public void OpenDevice(string mac, Action<string, bool> 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);
}
/// <summary>
/// 蓝牙读取数据解析
/// </summary>
/// <param name="read_buff_list">蓝牙数据链表</param>
private void ReadBuffAnalysis(List<byte> 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;
}
}
}
/// <summary>
/// 解密算法 解密得原始数据
/// </summary>
void decrypt(byte[] arr, short len)
{
for (int i = 0; i < len; i++)
{
arr[i] ^= 0x01;
arr[i] ^= 0x80;
}
}
/// <summary>
/// 将Byte类型数据转换为Ini类型数据
/// </summary>
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;
}
}
/// <summary>
/// 关闭设备
/// </summary>
public void CloseDevice(string mac, bool force)
{
BluetoothLEHardwareInterface.DisconnectPeripheral(mac,
(address) => { Debug.Log("UDE:" + $"Close Device {address}");
IsConnect = false;
ConnectListener?.Invoke(address, IsConnect);
});
}
/// <summary>
/// 设置传递数据的宽度
/// </summary>
/// <param name="mtu"></param>
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);
}
/// <summary>
/// 获取最大传输单元
/// </summary>
/// <returns></returns>
public int GetMTU(string mac)
{
return 200;
}
/// <summary>
/// 发送给下位机的实际方法
/// </summary>
/// <param name="data"></param>
/// <param name="length"></param>
/// <returns></returns>
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("<color=red>开启了蓝牙</color>:" + $"当前连接状态{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;
}
/// <summary>
/// 设置串行波特率
/// </summary>
/// <returns></returns>
public bool SetSerialBaud(string mac)
{
Debug.Log("UDE:" + " Set Serial Baud!!");
return false;
}
/// <summary>
/// 设置串行调制解调器
/// </summary>
/// <returns></returns>
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!!");
}
/// <summary>
/// 获取解析出的数据字符串
/// </summary>
/// <returns></returns>
public string GetDeviceData()
{
return data_s;
}
/// <summary>
/// 获取电量
/// </summary>
/// <returns></returns>
public int GetBatteryType()
{
return BatteryType;
}
/// <summary>
/// 开启接收蓝牙数据
/// </summary>
public void Pc2Mcu_StartReceive(string mac)
{
SendMessage(mac, Pc2McuProto.HumanAddress.LeftPalm, Pc2McuProto.CommandType.ADC_IMU_16,
new byte[] { 0x02, 0x43, 0x56 });
}
/// <summary>
/// 停止接收蓝牙数据
/// </summary>
public void Pc2Mcu_StopReceive(string mac)
{
SendMessage(mac, Pc2McuProto.HumanAddress.LeftPalm, Pc2McuProto.CommandType.StopDataReceive,
new byte[] { 0x01 });
}
/// <summary>
/// 接收字符串数据
/// </summary>
public void Pc2Mcu_StringData(string mac)
{
SendMessage(mac, Pc2McuProto.HumanAddress.LeftPalm, 0xD0,
new byte[] { 0x01 });
}
/// <summary>
/// 发送振动反馈
/// </summary>
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 });
}
/// <summary>
/// 启动心跳
/// </summary>
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);
}
}
}