using SerialPortUtility; using System; using System.Collections.Generic; using UnityEngine; public class ArrowSerialPort : MonoBehaviour { private SerialPortUtilityPro serialPortUtility; private SerialPortUtilityPro.OpenSystem openMode = SerialPortUtilityPro.OpenSystem.PCI; private int baudrate = 115200; private string PortName = "/dev/ttyS1"; private static Dictionary _isInit = new(); public bool testMode = false; private void Awake() { if (!_isInit.TryGetValue(gameObject.name, out int instanceID) && instanceID == 0) { DontDestroyOnLoad(gameObject); Init(); } } private void LOG(string msg, bool warning = false) { if (!warning) Debug.Log($"{msg}"); else Debug.LogWarning($"{msg}"); } private void Init() { _isInit[gameObject.name] = GetInstanceID(); #if UNITY_ANDROID && !UNITY_EDITOR serialPortUtility = gameObject.GetComponent(); serialPortUtility.OpenMethod = openMode; serialPortUtility.DeviceName = PortName; serialPortUtility.BaudRate = baudrate; serialPortUtility.StopBit = SerialPortUtilityPro.StopBitEnum.OneBit; serialPortUtility.DataBit = SerialPortUtilityPro.DataBitEnum.EightBit; serialPortUtility.SystemEventObject.AddListener(SystemEventObject); TrySerialOpenPort(); #endif #if UNITY_EDITOR if (testMode) { var testBoard = Resources.Load("SerialPortTest"); GameObject.Instantiate(testBoard); } #endif } private void TrySerialOpenPort() { serialPortUtility?.Open(); } private void SystemEventObject(SerialPortUtilityPro arg0, string msg) { if (msg.Equals("OPEN_ERROR") || msg.Equals("PERMISSION_ERROR"))//串口开启失败 定时重试 { #if UNITY_ANDROID && !UNITY_EDITOR Invoke("TrySerialOpenPort", 1f); #endif LOG($"{PortName} 串口打开失败 重试中", true); } else if (msg.Equals("OPENED")) { SerialPortHelper.ins.OnConnect(arg0.DeviceName); RequestDeviceIno();//应用启动 请求一次设备信息 LOG($"{PortName} 串口打开成功!"); } else if (msg.Equals("CLOSED"))//串口断开 { SerialPortHelper.ins.OnDisConnect(arg0.DeviceName); LOG($"{PortName} 串口关闭!"); } } private void OnDestroy() { if (_isInit.TryGetValue(gameObject.name, out var instanceID) && instanceID == GetInstanceID()) { LOG($"{PortName} 串口关闭"); SerialPortHelper.ins.OnDisConnect(serialPortUtility?.DeviceName); serialPortUtility?.Close(); _isInit.Remove(gameObject.name); } } /// /// 串口读取二进制流数据(界面挂载调用) /// /// public void ReadStreamingBinary(object data) { PhraseData(data as byte[]); } public void TestRead(byte[] bytes) { PhraseData(bytes); } /// /// 解析串口数据 /// /// private void PhraseData(byte[] bytes) { LOG($"{PortName} 收到串口信息!"); if (bytes[0] == 0xAA) { var cmdID = bytes[1]; switch (cmdID) { case 0x80://设备信息响应 OnDeviceInfoBack(bytes); break; case 0x81://射击消息 OnDeviceShoot(bytes); break; case 0x82://按键消息 OnDeviceButton(bytes); break; } } } #region APP请求 // 异或校验内容:命令+长度+数据内容 /// /// app请求设备信息 /// public void RequestDeviceIno() { List data = new List(); data[0] = 0xAA;//起始码 data[1] = 0x80;//命令号 data[2] = 0x05;//长度 data[3] = 0x85;//异或校验 data[4] = 0x55;//结束码 serialPortUtility?.Write(data.ToArray()); } #endregion #region 返回消息处理 /// /// 设备信息响应 /// private void OnDeviceInfoBack(byte[] bytes)// 0xAA 0x80 0x07 0x01 0x01 0x89 0x5D { Debug.Log($"{PortName} 收到设备信息响应!"); var check = bytes[1] + bytes[2] + bytes[3] + bytes[4];//校验:命令+长度+数据内容 if (check != bytes[5]) LOG("OnDeviceInfoBack 数据校验错误!"); else { //0x01 HOUYI Pro //0x02 ARTEMIS Pro //0x03 Pistol 1 var deviceType = bytes[3];//设备类型 switch (deviceType) { case 0x01: UserSettings.ins.selectDevicesName = "HOUYI Pro"; DevicesHolder.ins.SwitchDeviceByType(AimDeviceType.HOUYIPRO); break; case 0x02: UserSettings.ins.selectDevicesName = "ARTEMIS Pro"; DevicesHolder.ins.SwitchDeviceByType(AimDeviceType.ARTEMISPRO); break; case 0x03: UserSettings.ins.selectDevicesName = "Pistol M9"; DevicesHolder.ins.SwitchDeviceByType(AimDeviceType.Gun); break; } //刷新界面 var setting = FindAnyObjectByType(); setting?.FlushDeviceSelect(); } } /// /// 射击消息 /// private void OnDeviceShoot(byte[] bytes) { LOG($"{PortName} 收到设备射击消息!"); var check = bytes[1] + bytes[2] + bytes[3] + bytes[4];//校验:命令+长度+数据内容 if (check != bytes[5]) { LOG("OnDeviceShoot 数据校验错误!"); }else SerialPortHelper.shoot?.Invoke(bytes); } /// /// 按键消息 /// /// private void OnDeviceButton(byte[] bytes) { Debug.Log($"{PortName} 收到设备按键消息!"); var check = bytes[1] + bytes[2] + bytes[3];//校验:命令+长度+数据内容 if (check != bytes[4]) { LOG("OnDeviceButton 数据校验错误!"); } else SerialPortHelper.aim?.Invoke(bytes); } #endregion }