| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- 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 int baudrate = 921600;
- private string PortName = "/dev/ttyS0";
- private static Dictionary<string, int> _isInit = new();
- public bool testMode = true;
- 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($"<color=#00FF00>{msg}</color>");
- else
- Debug.LogWarning($"<color=#00FF00>{msg}</color>");
- }
- private void Init()
- {
- _isInit[gameObject.name] = GetInstanceID();
- #if UNITY_ANDROID && !UNITY_EDITOR
- serialPortUtility = gameObject.GetComponent<SerialPortUtilityPro>();
- 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<GameObject>("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);
- //应用启动 间隔十秒请求一次设备信息
- CancelInvoke("RequestDeviceIno");
- InvokeRepeating("RequestDeviceIno", 0f, 10f);
- //LOG($"{PortName} 串口打开成功!");
- ////激光默认打开
- //RequestLightState(true);
- }
- 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);
- }
- }
- /// <summary>
- /// 串口读取二进制流数据(界面挂载调用)
- /// </summary>
- /// <param name="data"></param>
- public void ReadStreamingBinary(object data)
- {
- var realData = new List<byte>();
- var tempData = data as byte[];
- for (int i = 0; i < tempData.Length; i++)
- {
- realData.Add(tempData[i]);
- if (tempData.Length > i + 1)
- {
- if (tempData[i + 1] == 0XAA) //多条消息 粘包位置
- {
- //把上一条发送
- PhraseData(realData.ToArray());
- realData.Clear();
- }
- }
- else
- PhraseData(realData.ToArray());
- }
- }
- public void TestRead(byte[] bytes)
- {
- ReadStreamingBinary(bytes);
- }
- /// <summary>
- /// 解析串口数据
- /// </summary>
- /// <param name="bytes"></param>
- private void PhraseData(byte[] bytes)
- {
- string msg = string.Empty;
- for (int i = 0; i < bytes.Length; i++)
- {
- msg += bytes[i].ToString("x2") + " ";
- }
- LOG($"{PortName} 收到串口信息 msg={msg}!");
- 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;
- case 0x83://激光控制
- OnLightChange(bytes);
- break;
- case 0x84://弹夹消息(仅手枪)
- OnMagazinesInfo(bytes);
- break;
- }
- }
- }
- bool lightWaitClose = false;
- public void DelayCloseLight()
- {
- if (!lightWaitClose && hasOnceInceCoin)
- {
- LOG("游戏时间结束 延迟关闭激光");
- Invoke("DoDelayCloseLight", 60f);
- lightWaitClose = true;
- }
- }
- public void CancelDelayCloseLight()
- {
- LOG("关闭延迟关闭激光");
- lightWaitClose = false;
- CancelInvoke("DoDelayCloseLight");
- }
- private void DoDelayCloseLight()
- {
- RequestLightState(false);
- }
- //是否有过首次投币 没投币过 不关闭摄像头
- bool hasOnceInceCoin = false;
- #region APP请求
- // 异或校验内容:命令+长度+数据内容
- /// <summary>
- /// 设置激光状态
- /// </summary>
- public void RequestLightState(bool on, bool insertCoin = false)
- {
- if (insertCoin)
- hasOnceInceCoin = true;
- List<byte> data = new List<byte>();
- data.Add(0xAA);//起始码
- data.Add(0x83);//命令号
- data.Add(0x06);//长度
- data.Add((byte)(on ? 0x01 : 0x00));//长度
- byte temp = 0;
- for (int i = 1; i < data.Count; i++)
- {
- temp ^= data[i];
- }
- data.Add(temp);//异或校验
- data.Add(0x55);//结束码
- serialPortUtility?.Write(data.ToArray());
- LOG($"设置激光状态:{on}!");
- OnLightChange(data.ToArray());
- }
- /// <summary>
- /// app请求设备信息
- /// </summary>
- public void RequestDeviceIno()
- {
- List<byte> data = new List<byte>();
- data.Add(0xAA);//起始码
- data.Add(0x80);//命令号
- data.Add(0x05);//长度
- data.Add(0x85);//异或校验
- data.Add(0x55);//结束码
- serialPortUtility?.Write(data.ToArray());
- Debug.Log("发送心跳包");
- DevicesHolder.ins?.ShowConnectTip();
- }
- #endregion
- #region 返回消息处理
- /// <summary>
- /// 弹夹消息
- /// </summary>
- /// <param name="bytes"></param>
- private void OnMagazinesInfo(byte[] bytes)
- {
- Debug.Log($"{PortName} 收到弹夹消息!");
- SerialPortHelper.ins.OnMagazineChange(bytes);
- }
- private void OnLightChange(byte[] bytes)// 0xAA 0x83 0x06 0x01 0x84 0x55
- {
- lightWaitClose = false;
- Debug.Log($"{PortName} 激光状态变更回包!");
- var isOn = bytes[3] == 0x01;
- UserSettings.ins.lightState = isOn;
- }
- /// <summary>
- /// 设备信息响应
- /// </summary>
- 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 (HomeView.ins == null) {
- return;
- }
- //0x01 HOUYI Pro
- //0x02 ARTEMIS Pro
- //0x03 Pistol 1
- var deviceType = bytes[3];//设备类型
- Debug.Log("设备类型 Device Type: " + deviceType);
- 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;
- }
- UserSettings.ins.Save();
- //刷新界面
- var setting = FindAnyObjectByType<CustomUIView.BoxUserSettings>();
- setting?.FlushDeviceSelect();
- }
- /// <summary>
- /// 射击消息
- /// </summary>
- 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);
- }
- /// <summary>
- /// 按键消息
- /// </summary>
- /// <param name="bytes"></param>
- private void OnDeviceButton(byte[] bytes)
- {
- Debug.Log($"{PortName} 收到设备按键消息!");
- var check = bytes[1] + bytes[2] + bytes[3];
- //校验:命令+长度+数据内容
- //if (check != bytes[4])
- //{
- // LOG("OnDeviceButton 数据校验错误!");
- //}
- //else
- if (string.IsNullOrEmpty(UserSettings.ins.selectDevicesName))
- //开机
- RequestDeviceIno();
- SerialPortHelper.aim?.Invoke(bytes);
- }
- #endregion
- }
|