// using System;
// using System.Collections.Generic;
// using UnityEngine;
// using System.Threading;
// using GeneralTools;
// namespace DCX.Communication
// {
// ///
// /// DCS项目串口通信管理器
// /// 基于DCS项目串口通信协议说明书实现
// /// 支持安卓平台的串口通信
// ///
// public class DCSSerialManager : MonoBehaviour
// {
// #region 协议常量
// // 帧结构常量
// private const byte FRAME_HEADER_1 = 0xAA;
// private const byte FRAME_HEADER_2 = 0x55;
// private const byte FRAME_TAIL_1 = 0x0D;
// private const byte FRAME_TAIL_2 = 0x0A;
// // 命令字定义(基于协议文档)
// public enum CommandType : byte
// {
// HandshakeResponse = 0x01, // 握手应答 + 时间同步(下→上)
// HandshakeRequest = 0x02, // 握手请求(上→下)
// HeartbeatReport = 0x03, // 心跳上报(上→下)
// HeartbeatAck = 0x04, // 心跳应答(下→上)
// AlarmControl = 0x05, // 报警控制命令(下→上)
// DataReport = 0x06, // 数据上报(上→下)
// ParameterQuery = 0x07, // 参数查询或设置(下→上)
// AlarmFeedback = 0x08, // 告警状态反馈(上→下)
// TimeSync = 0x09 // 时间同步命令(下→上)
// }
// // 报警代码定义
// public enum AlarmCode : byte
// {
// BatteryLow40 = 0x11, // 电池电量低(<40%)
// LaserTempAbnormal = 0x22, // 激光器温度异常
// BatteryLow20 = 0x21, // 电池电量低(<20%)
// BatteryEmpty5 = 0x31, // 电池电量空(<5%)
// BFIAbnormal = 0x32, // BFI数值异常
// LaserWorkAbnormal = 0x33, // 激光器工作异常
// CommAbnormal = 0x34, // 通信异常
// BatteryFault = 0x35, // 电池故障
// ACNotConnected = 0x12 // 交流电未连接
// }
// #endregion
// #region 数据结构
// [Serializable]
// public struct HeartbeatData
// {
// public float bfiValue; // BFI血流值
// public byte batteryLevel; // 电池电量 0-100%
// public ushort batteryVoltage; // 电池电压 mV
// public ushort temperature; // 内部温度 0.1°C
// public byte laserStatus; // 激光器状态 0=异常,1=工作,2=停止
// public byte powerType; // 电源类型 0=AC,1=BAT
// public uint reserved; // 保留字段
// }
// [Serializable]
// public struct AlarmCommand
// {
// public AlarmCode alarmCode; // 报警代码
// public byte priority; // 报警级别 0=低,1=中,2=高
// public byte status; // 报警状态 0=清除,1=触发
// }
// #endregion
// #region 事件定义
// public event Action OnConnected;
// public event Action OnDisconnected;
// public event Action OnHeartbeatReceived;
// public event Action OnAlarmReceived;
// public event Action OnError;
// public event Action OnRawDataReceived;
// #endregion
// #region 私有字段
// private ISerialPortAdapter serialPort;
// private Thread readThread;
// private bool isRunning = false;
// private Queue sendQueue = new Queue();
// private object lockObject = new object();
// private float lastHeartbeatTime = 0f;
// private float lastDataReportTime = 0f;
// private bool isHandshakeCompleted = false;
// // 配置参数(从AndroidConfigHelper加载)
// private string portName;
// private int baudRate;
// private int heartbeatInterval;
// private int communicationTimeout;
// private bool autoReconnect;
// private int maxReconnectAttempts;
// #endregion
// #region Unity生命周期
// void Start()
// {
// LoadConfiguration();
// InitializeSerialPort();
// }
// void Update()
// {
// ProcessSendQueue();
// CheckHeartbeat();
// // CheckDataReport();
// }
// void OnDestroy()
// {
// Disconnect();
// }
// #endregion
// #region 配置加载
// private void LoadConfiguration()
// {
// // 根据平台设置默认串口名称
// string defaultPortName;
// #if UNITY_ANDROID && !UNITY_EDITOR
// defaultPortName = "/dev/ttyS4";
// #elif UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
// defaultPortName = "COM1";
// #elif UNITY_STANDALONE_LINUX || UNITY_EDITOR_LINUX
// defaultPortName = "/dev/ttyS4";
// #elif UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX
// defaultPortName = "/dev/cu.usbserial-1410";
// #else
// defaultPortName = "COM1";
// #endif
// portName = AndroidConfigHelper.GetConfig("serialPortName", "SerialPort", defaultPortName);
// baudRate = AndroidConfigHelper.GetConfig("serialBaudRate", "SerialPort", 115200);
// heartbeatInterval = AndroidConfigHelper.GetConfig("heartbeatInterval", "SerialPort", 1000);
// communicationTimeout = AndroidConfigHelper.GetConfig("communicationTimeout", "SerialPort", 5000);
// autoReconnect = AndroidConfigHelper.GetConfig("autoReconnect", "SerialPort", true);
// maxReconnectAttempts = AndroidConfigHelper.GetConfig("maxReconnectAttempts", "SerialPort", 5);
// Debug.Log($"DCS串口配置加载完成: {portName}, {baudRate}bps (平台: {Application.platform})");
// }
// #endregion
// #region 串口初始化和连接
// private void InitializeSerialPort()
// {
// try
// {
// #if UNITY_ANDROID && !UNITY_EDITOR
// // 安卓平台使用JNI调用原生串口
// serialPort = new AndroidSerialPortAdapter();
// #elif UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
// // Windows平台使用真实串口
// serialPort = new WindowsSerialPortAdapter();
// Debug.Log("DCS使用Windows真实串口");
// #elif UNITY_STANDALONE_LINUX || UNITY_EDITOR_LINUX
// // Linux平台使用真实串口
// serialPort = new WindowsSerialPortAdapter(); // 复用Windows适配器
// Debug.Log("DCS使用Linux真实串口");
// #else
// // 其他平台使用模拟器
// serialPort = new SimulatedSerialPortAdapter();
// Debug.LogWarning("DCS使用串口模拟器(未支持平台)");
// #endif
// Connect();
// }
// catch (Exception e)
// {
// Debug.LogError($"DCS串口初始化失败: {e.Message}");
// OnError?.Invoke($"串口初始化失败: {e.Message}");
// }
// }
// public void Connect()
// {
// try
// {
// if (serialPort != null && serialPort.Open(portName, baudRate))
// {
// isRunning = true;
// StartReadThread();
// SendHandshakeRequest();
// OnConnected?.Invoke();
// Debug.Log("串口连接成功");
// }
// else
// {
// OnError?.Invoke("串口连接失败");
// }
// }
// catch (Exception e)
// {
// OnError?.Invoke($"连接异常: {e.Message}");
// }
// }
// public void Disconnect()
// {
// isRunning = false;
// if (readThread != null && readThread.IsAlive)
// {
// readThread.Join(1000); // 等待读取线程结束
// }
// serialPort?.Close();
// OnDisconnected?.Invoke();
// Debug.Log("串口已断开");
// }
// #endregion
// #region 数据发送和接收
// private void StartReadThread()
// {
// readThread = new Thread(ReadDataThread)
// {
// IsBackground = true
// };
// readThread.Start();
// }
// private void ReadDataThread()
// {
// byte[] buffer = new byte[1024];
// while (isRunning)
// {
// try
// {
// if (serialPort != null && serialPort.IsOpen)
// {
// int bytesRead = serialPort.Read(buffer, 0, buffer.Length);
// if (bytesRead > 0)
// {
// byte[] data = new byte[bytesRead];
// Array.Copy(buffer, 0, data, 0, bytesRead);
// // 在主线程处理数据
// MainThreadDispatcher.Enqueue(() => ProcessReceivedData(data));
// }
// }
// }
// catch (Exception e)
// {
// MainThreadDispatcher.Enqueue(() => OnError?.Invoke($"读取数据异常: {e.Message}"));
// }
// Thread.Sleep(10); // 避免过度占用CPU
// }
// }
// private void ProcessReceivedData(byte[] data)
// {
// OnRawDataReceived?.Invoke(data);
// // 解析协议帧
// for (int i = 0; i < data.Length - 6; i++) // 最小帧长度检查
// {
// if (data[i] == FRAME_HEADER_1 && data[i + 1] == FRAME_HEADER_2)
// {
// if (TryParseFrame(data, i, out var frame))
// {
// ProcessFrame(frame);
// }
// }
// }
// }
// private bool TryParseFrame(byte[] data, int startIndex, out ProtocolFrame frame)
// {
// frame = new ProtocolFrame();
// try
// {
// if (startIndex + 6 >= data.Length) return false;
// frame.Command = (CommandType)data[startIndex + 2];
// frame.DataLength = data[startIndex + 3];
// int totalFrameLength = 4 + frame.DataLength + 3; // 帧头+命令+长度+数据+校验+帧尾
// if (startIndex + totalFrameLength > data.Length) return false;
// frame.Data = new byte[frame.DataLength];
// Array.Copy(data, startIndex + 4, frame.Data, 0, frame.DataLength);
// frame.Checksum = data[startIndex + 4 + frame.DataLength];
// // 验证校验和
// byte calculatedChecksum = CalculateChecksum(data, startIndex + 2, 2 + frame.DataLength);
// if (calculatedChecksum != frame.Checksum)
// {
// Debug.LogWarning("校验和不匹配");
// return false;
// }
// // 验证帧尾
// if (data[startIndex + 5 + frame.DataLength] != FRAME_TAIL_1 ||
// data[startIndex + 6 + frame.DataLength] != FRAME_TAIL_2)
// {
// Debug.LogWarning("帧尾不匹配");
// return false;
// }
// return true;
// }
// catch (Exception e)
// {
// Debug.LogError($"解析帧失败: {e.Message}");
// return false;
// }
// }
// private void ProcessFrame(ProtocolFrame frame)
// {
// switch (frame.Command)
// {
// case CommandType.HeartbeatReport:
// ProcessHeartbeatReport(frame.Data);
// SendHeartbeatAck();
// break;
// case CommandType.DataReport:
// ProcessDataReport(frame.Data);
// break;
// case CommandType.AlarmFeedback:
// ProcessAlarmFeedback(frame.Data);
// break;
// case CommandType.HandshakeRequest:
// ProcessHandshakeRequest(frame.Data);
// break;
// default:
// Debug.Log($"收到未处理的命令: {frame.Command}");
// break;
// }
// }
// private void ProcessHeartbeatReport(byte[] data)
// {
// if (data.Length >= 15) // HeartbeatData结构体大小
// {
// HeartbeatData heartbeat = new HeartbeatData
// {
// bfiValue = BitConverter.ToSingle(data, 0),
// batteryLevel = data[4],
// batteryVoltage = BitConverter.ToUInt16(data, 5),
// temperature = BitConverter.ToUInt16(data, 7),
// laserStatus = data[9],
// powerType = data[10],
// reserved = BitConverter.ToUInt32(data, 11)
// };
// OnHeartbeatReceived?.Invoke(heartbeat);
// lastHeartbeatTime = Time.time;
// }
// }
// private void ProcessDataReport(byte[] data)
// {
// // 处理数据上报,格式与心跳报告相同
// ProcessHeartbeatReport(data);
// lastDataReportTime = Time.time;
// }
// private void ProcessAlarmFeedback(byte[] data)
// {
// if (data.Length >= 3)
// {
// AlarmCommand alarm = new AlarmCommand
// {
// alarmCode = (AlarmCode)data[0],
// priority = data[1],
// status = data[2]
// };
// OnAlarmReceived?.Invoke(alarm);
// }
// }
// private void ProcessHandshakeRequest(byte[] data)
// {
// Debug.Log("收到握手请求,发送时间同步应答");
// SendHandshakeResponse();
// isHandshakeCompleted = true;
// }
// #endregion
// #region 协议命令发送
// public void SendHandshakeRequest()
// {
// byte[] data = { 0x01 }; // 固件版本
// SendFrame(CommandType.HandshakeRequest, data);
// }
// public void SendHandshakeResponse()
// {
// DateTime now = DateTime.Now;
// byte[] data = {
// (byte)(now.Year % 100),
// (byte)now.Month,
// (byte)now.Day,
// (byte)now.Hour,
// (byte)now.Minute,
// (byte)now.Second
// };
// SendFrame(CommandType.HandshakeResponse, data);
// }
// public void SendHeartbeatAck()
// {
// byte[] data = { 0x00 }; // 简单应答
// SendFrame(CommandType.HeartbeatAck, data);
// }
// public void SendAlarmControl(AlarmCode alarmCode, byte priority, byte status)
// {
// byte[] data = { (byte)alarmCode, priority, status };
// SendFrame(CommandType.AlarmControl, data);
// }
// private void SendFrame(CommandType command, byte[] data)
// {
// try
// {
// List frame = new List();
// // 帧头
// frame.Add(FRAME_HEADER_1);
// frame.Add(FRAME_HEADER_2);
// // 命令字
// frame.Add((byte)command);
// // 数据长度
// frame.Add((byte)data.Length);
// // 数据
// frame.AddRange(data);
// // 校验和
// byte checksum = CalculateChecksum(frame.ToArray(), 2, 2 + data.Length);
// frame.Add(checksum);
// // 帧尾
// frame.Add(FRAME_TAIL_1);
// frame.Add(FRAME_TAIL_2);
// var frameArray = frame.ToArray();
// var hexString = BitConverter.ToString(frameArray).Replace("-", " ");
// Debug.Log($"[DCS发送队列] {GetCommandName(command)}: {hexString}");
// lock (lockObject)
// {
// sendQueue.Enqueue(frameArray);
// }
// }
// catch (Exception e)
// {
// Debug.LogError($"DCS发送帧失败: {e.Message}");
// OnError?.Invoke($"发送帧失败: {e.Message}");
// }
// }
// private string GetCommandName(CommandType command)
// {
// return command switch
// {
// CommandType.HandshakeResponse => "握手应答",
// CommandType.HandshakeRequest => "握手请求",
// CommandType.HeartbeatReport => "心跳上报",
// CommandType.HeartbeatAck => "心跳应答",
// CommandType.AlarmControl => "报警控制",
// CommandType.DataReport => "数据上报",
// CommandType.ParameterQuery => "参数查询",
// CommandType.AlarmFeedback => "报警反馈",
// CommandType.TimeSync => "时间同步",
// _ => $"未知命令({(byte)command:X2})"
// };
// }
// private void ProcessSendQueue()
// {
// lock (lockObject)
// {
// while (sendQueue.Count > 0)
// {
// byte[] frame = sendQueue.Dequeue();
// try
// {
// if (serialPort != null && serialPort.IsOpen)
// {
// serialPort.Write(frame, 0, frame.Length);
// var hexString = BitConverter.ToString(frame).Replace("-", " ");
// Debug.Log($"[DCS串口发送] {hexString}");
// }
// else
// {
// Debug.LogError("DCS串口未打开,无法发送数据");
// }
// }
// catch (Exception e)
// {
// Debug.LogError($"DCS串口写入失败: {e.Message}");
// OnError?.Invoke($"串口写入失败: {e.Message}");
// }
// }
// }
// }
// #endregion
// #region 辅助方法
// private byte CalculateChecksum(byte[] data, int offset, int length)
// {
// byte checksum = 0;
// for (int i = offset; i < offset + length; i++)
// {
// checksum ^= data[i];
// }
// return checksum;
// }
// private void CheckHeartbeat()
// {
// if (isHandshakeCompleted && Time.time - lastHeartbeatTime > communicationTimeout / 1000f)
// {
// Debug.LogWarning("心跳超时");
// if (autoReconnect)
// {
// Reconnect();
// }
// }
// }
// private void CheckDataReport()
// {
// // 检查数据上报间隔
// float dataReportInterval = AndroidConfigHelper.GetConfig("dataReportInterval", "SerialPort", 1000) / 1000f;
// if (Time.time - lastDataReportTime > dataReportInterval * 2)
// {
// Debug.LogWarning("数据上报超时");
// }
// }
// private void Reconnect()
// {
// Debug.Log("尝试重连...");
// Disconnect();
// Invoke(nameof(Connect), 2f); // 2秒后重连
// }
// #endregion
// #region 内部数据结构
// private struct ProtocolFrame
// {
// public CommandType Command;
// public byte DataLength;
// public byte[] Data;
// public byte Checksum;
// }
// #endregion
// }
// #region 串口适配器接口
// public interface ISerialPortAdapter
// {
// bool Open(string portName, int baudRate);
// void Close();
// bool IsOpen { get; }
// int Read(byte[] buffer, int offset, int count);
// void Write(byte[] buffer, int offset, int count);
// }
// // Windows平台串口适配器(使用System.IO.Ports)
// public class WindowsSerialPortAdapter : ISerialPortAdapter
// {
// #if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN || UNITY_STANDALONE_LINUX || UNITY_EDITOR_LINUX
// private System.IO.Ports.SerialPort serialPort;
// public bool IsOpen => serialPort?.IsOpen ?? false;
// public bool Open(string portName, int baudRate)
// {
// try
// {
// serialPort = new System.IO.Ports.SerialPort(portName, baudRate, System.IO.Ports.Parity.None, 8, System.IO.Ports.StopBits.One)
// {
// ReadTimeout = 1000,
// WriteTimeout = 1000
// };
// serialPort.Open();
// Debug.Log($"Windows串口打开成功: {portName} @ {baudRate}");
// return true;
// }
// catch (Exception e)
// {
// Debug.LogError($"Windows串口打开失败: {e.Message}");
// return false;
// }
// }
// public void Close()
// {
// try
// {
// if (serialPort?.IsOpen == true)
// {
// serialPort.Close();
// serialPort.Dispose();
// serialPort = null;
// Debug.Log("Windows串口已关闭");
// }
// }
// catch (Exception e)
// {
// Debug.LogError($"Windows串口关闭失败: {e.Message}");
// }
// }
// public int Read(byte[] buffer, int offset, int count)
// {
// try
// {
// if (serialPort != null && serialPort.IsOpen && serialPort.BytesToRead > 0)
// {
// return serialPort.Read(buffer, offset, count);
// }
// return 0;
// }
// catch (Exception e)
// {
// Debug.LogError($"Windows串口读取失败: {e.Message}");
// return 0;
// }
// }
// public void Write(byte[] buffer, int offset, int count)
// {
// try
// {
// if (serialPort != null && serialPort.IsOpen)
// {
// serialPort.Write(buffer, offset, count);
// }
// }
// catch (Exception e)
// {
// Debug.LogError($"Windows串口写入失败: {e.Message}");
// }
// }
// #else
// public bool IsOpen => false;
// public bool Open(string portName, int baudRate) { Debug.LogWarning("WindowsSerialPortAdapter不支持此平台"); return false; }
// public void Close() { }
// public int Read(byte[] buffer, int offset, int count) { return 0; }
// public void Write(byte[] buffer, int offset, int count) { }
// #endif
// }
// // 安卓平台串口适配器(需要JNI实现)
// public class AndroidSerialPortAdapter : ISerialPortAdapter
// {
// private AndroidJavaObject serialPortJNI;
// public bool IsOpen { get; private set; }
// public bool Open(string portName, int baudRate)
// {
// try
// {
// #if UNITY_ANDROID && !UNITY_EDITOR
// serialPortJNI = new AndroidJavaObject("com.dcx.serialport.SerialPortHelper");
// bool result = serialPortJNI.Call("openSerialPort", portName, baudRate);
// IsOpen = result;
// return result;
// #else
// return false;
// #endif
// }
// catch (Exception e)
// {
// Debug.LogError($"Android串口打开失败: {e.Message}");
// return false;
// }
// }
// public void Close()
// {
// try
// {
// #if UNITY_ANDROID && !UNITY_EDITOR
// serialPortJNI?.Call("closeSerialPort");
// #endif
// IsOpen = false;
// }
// catch (Exception e)
// {
// Debug.LogError($"Android串口关闭失败: {e.Message}");
// }
// }
// public int Read(byte[] buffer, int offset, int count)
// {
// try
// {
// #if UNITY_ANDROID && !UNITY_EDITOR
// byte[] data = serialPortJNI.Call("readData", count);
// if (data != null && data.Length > 0)
// {
// Array.Copy(data, 0, buffer, offset, Math.Min(data.Length, count));
// return data.Length;
// }
// #endif
// return 0;
// }
// catch (Exception e)
// {
// Debug.LogError($"Android串口读取失败: {e.Message}");
// return 0;
// }
// }
// public void Write(byte[] buffer, int offset, int count)
// {
// try
// {
// #if UNITY_ANDROID && !UNITY_EDITOR
// byte[] data = new byte[count];
// Array.Copy(buffer, offset, data, 0, count);
// serialPortJNI.Call("writeData", data);
// #endif
// }
// catch (Exception e)
// {
// Debug.LogError($"Android串口写入失败: {e.Message}");
// }
// }
// }
// // 模拟串口适配器(用于测试)
// public class SimulatedSerialPortAdapter : ISerialPortAdapter
// {
// public bool IsOpen { get; private set; }
// private Queue simulatedData = new Queue();
// private System.Random random = new System.Random();
// public bool Open(string portName, int baudRate)
// {
// IsOpen = true;
// Debug.Log($"模拟串口已打开: {portName}@{baudRate}");
// return true;
// }
// public void Close()
// {
// IsOpen = false;
// Debug.Log("模拟串口已关闭");
// }
// public int Read(byte[] buffer, int offset, int count)
// {
// // 模拟接收心跳数据
// if (simulatedData.Count == 0 && random.NextDouble() < 0.1) // 10%概率生成数据
// {
// GenerateSimulatedHeartbeat();
// }
// int bytesRead = 0;
// while (simulatedData.Count > 0 && bytesRead < count)
// {
// buffer[offset + bytesRead] = simulatedData.Dequeue();
// bytesRead++;
// }
// return bytesRead;
// }
// public void Write(byte[] buffer, int offset, int count)
// {
// string hex = BitConverter.ToString(buffer, offset, count);
// Debug.Log($"模拟串口发送: {hex}");
// }
// private void GenerateSimulatedHeartbeat()
// {
// // 生成模拟心跳帧
// List frame = new List
// {
// 0xAA, 0x55, // 帧头
// 0x03, // 心跳报告命令
// 0x0F, // 数据长度15字节
// };
// // BFI值 (float)
// byte[] bfiBytes = BitConverter.GetBytes(50.0f + (float)(random.NextDouble() - 0.5) * 20);
// frame.AddRange(bfiBytes);
// // 电池电量
// frame.Add((byte)(80 + random.Next(0, 20)));
// // 电池电压 (mV)
// byte[] voltageBytes = BitConverter.GetBytes((ushort)(3700 + random.Next(0, 500)));
// frame.AddRange(voltageBytes);
// // 温度
// byte[] tempBytes = BitConverter.GetBytes((ushort)(250 + random.Next(0, 100))); // 25.0-35.0°C
// frame.AddRange(tempBytes);
// // 激光器状态
// frame.Add(0x01); // 工作中
// // 电源类型
// frame.Add(0x01); // 电池供电
// // 保留字段
// frame.AddRange(new byte[4]);
// // 校验和
// byte checksum = 0;
// for (int i = 2; i < frame.Count; i++)
// {
// checksum ^= frame[i];
// }
// frame.Add(checksum);
// // 帧尾
// frame.Add(0x0D);
// frame.Add(0x0A);
// foreach (byte b in frame)
// {
// simulatedData.Enqueue(b);
// }
// }
// }
// // 主线程调度器(用于在主线程处理串口数据)
// public class MainThreadDispatcher : MonoBehaviour
// {
// private static MainThreadDispatcher instance;
// private static Queue executionQueue = new Queue();
// public static void Enqueue(Action action)
// {
// lock (executionQueue)
// {
// executionQueue.Enqueue(action);
// }
// }
// void Awake()
// {
// if (instance == null)
// {
// instance = this;
// DontDestroyOnLoad(gameObject);
// }
// else
// {
// Destroy(gameObject);
// }
// }
// void Update()
// {
// lock (executionQueue)
// {
// while (executionQueue.Count > 0)
// {
// executionQueue.Dequeue().Invoke();
// }
// }
// }
// }
// #endregion
// }