using System.Collections.Generic;
using UnityEngine;
using System.IO.Ports;
using System.Threading;
using System;
using System.Text;
using System.Xml;
namespace ZX_DEVICE
{
/// <summary>
/// 设备通信组件
/// </summary>
public class DeviceComponent : MonoBehaviour
{
/// <summary>
/// 设备通信组件对象
/// </summary>
public static DeviceComponent Instance;
SerialPort port;//串口实例
Thread recvThread;//接收数据线程
byte[] receiveBytes;//接收数据字节组
int SendTime, TimeOut = 500;//发送指令时的时间;任务超时的检测时间
List<TaskBase> MyTaskTable = new List<TaskBase>();
StringBuilder receiveStr = new StringBuilder();//接收消息的字符序列
bool IsTimer, ThreadRuning, Receiving;//是否开始计时;读取数据线程控制符;是否等待信号返回中,T为是
//--------------------------------------------------------------------------------
/// <summary>
/// 打开设备连接
/// </summary>
public bool OpenDeviceConnect(string comName) { return OpenSerialPort(comName); }
/// <summary>
/// 关闭设备连接(程序退出时会自动调用一次)
/// </summary>
public void CloseDeviceConnect()
{
if (recvThread != null && recvThread.IsAlive)
{
ThreadRuning = false;
Debug.Log("设备接收线程成功关闭");
}
else
Debug.Log("设备接收线程关闭失败");
if (port != null && port.IsOpen)
{
port.Close(); port = null;
Debug.Log("设备串口成功关闭");
}
else
Debug.Log("设备串口关闭失败");
}
/// <summary>
/// 获取应答结果
/// </summary>
/// <returns>第一个参数是命令的应答状态,第二个是应答返回结果</returns>
public (bool, string) GetReceiveMessage()
{
string tmp;
if (!string.IsNullOrEmpty(receiveStr.ToString()))
{
tmp = receiveStr.ToString();
receiveStr.Clear();
return (true, tmp);
}
else
return (false, null);
}
/// <summary>
/// 获取通信的连接状态
/// </summary>
/// <returns></returns>
public bool GetConnectState() { return ThreadRuning; }
/// <summary>
/// 设置命令超时的检测时间:发送一个命令后,在此时间内没有收到处理结果,则认为该命令处理失败。组件将移除该命令
/// (默认是500毫秒)
/// </summary>
/// <param name="timeOut">超时时间</param>
public void SetOrderTimeOut(int timeOut) { TimeOut = timeOut; }
#region 外部调用命令集
/// <summary>
/// 发送心跳命令
/// </summary>
public void SendHeartOrder(AddressCode receive, AddressCode send = AddressCode.Host) { AddTaskFunction(new TaskBase(CmdType.Heart, send, receive)); }
/// <summary>
/// 发送开始检测命令(预留接口,暂未使用)
/// </summary>
public void SendStartCheckOrder(AddressCode receive, AddressCode send = AddressCode.Host) { AddTaskFunction(new TaskBase(CmdType.StartCheck, send, receive)); }
/// <summary>
/// 发送结束检测命令(预留接口,暂未使用)
/// </summary>
public void SendOverCheckOrder(AddressCode receive, AddressCode send = AddressCode.Host) { AddTaskFunction(new TaskBase(CmdType.OverCheck, send, receive)); }
/// <summary>
/// 发送状态查询命令
/// </summary>
public void SendStateQueryOrder(AddressCode receive, AddressCode send = AddressCode.Host) { AddTaskFunction(new TaskBase(CmdType.StateQuery, send, receive)); }
/// <summary>
/// 发送编码器清零命令(预留接口,暂未使用)
/// </summary>
public void SendClearEncoderOrder(AddressCode receive, AddressCode send = AddressCode.Host) { AddTaskFunction(new TaskBase(CmdType.ClearEncoder, send, receive)); }
//-----------------------------------------------------------------------------------------------------------------------------------
/// <summary>
/// 发送控制AED按键灯命令(数字输出控制)
/// </summary>
public void SendAEDLightOrder(AEDLightType lightType, AddressCode send = AddressCode.Host)
{
switch (lightType)
{
case AEDLightType.AllOff:
AddTaskFunction(new TaskBase(CmdType.OutPutCtrl, send, AddressCode.AED, "0x1F"));
break;
case AEDLightType.AllOn:
AddTaskFunction(new TaskBase(CmdType.OutPutCtrl, send, AddressCode.AED, "0x12"));
break;
case AEDLightType.Prower:
AddTaskFunction(new TaskBase(CmdType.OutPutCtrl, send, AddressCode.AED, "0x08"));
break;
default:
Debug.LogError("未找到对应AED灯光类型");
break;
}
}
/// <summary>
/// 发送控制模型人脉搏命令(模拟输出控制)
/// </summary>
public void SendPulseCtrlOrder(bool IsJump, AddressCode send = AddressCode.Host)
{
if (IsJump)
AddTaskFunction(new TaskBase(CmdType.DragCtrl, send, AddressCode.Human, "0209C4"));
else
AddTaskFunction(new TaskBase(CmdType.DragCtrl, send, AddressCode.Human, "020000"));
}
/// <summary>
/// 发送AED音频控制命令
/// </summary>
public void SendAEDAudioOrder(AEDAudioType audioType, AddressCode send = AddressCode.Host)
{
switch (audioType)
{
case AEDAudioType.ReadyTip:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.AED, "0100"));
break;
case AEDAudioType.NotDefibrillate:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.AED, "0200"));
break;
case AEDAudioType.OverDefibrillate:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.AED, "0300"));
break;
case AEDAudioType.Charging:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.AED, "0400"));
break;
case AEDAudioType.DisCharging:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.AED, "0500"));
break;
case AEDAudioType.ReadyTipAgain:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.AED, "0600"));
break;
case AEDAudioType.DontTouch:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.AED, "0700"));
break;
case AEDAudioType.LowBattery:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.AED, "0800"));
break;
default:
Debug.LogError("AED音频类型不正确");
break;
}
}
/// <summary>
/// 发送除颤仪心率显示状态命令
/// </summary>
public void SendHeartRateStateOrder(int rate, AddressCode send = AddressCode.Host)
{
if (rate > 249) rate = 249;
if (rate < 0) rate = 0;
if (rate == 0)
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "010" + Convert.ToString(rate, 16)));
else
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "01" + Convert.ToString(rate, 16)));
}
/// <summary>
/// 发送电极连接显示状态命令(预留接口,暂未使用)
/// </summary>
public void SendElectrodesStateOrder(bool IsShow, AddressCode send = AddressCode.Host)
{
if (IsShow)
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0201"));
else
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0200"));
}
/// <summary>
/// 发送波形显示状态命令
/// </summary>
public void SendWaveformStateOrder(WaveformType waveform, AddressCode send = AddressCode.Host)
{
switch (waveform)
{
case WaveformType.None:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0300"));
break;
case WaveformType.Die:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0301"));
break;
case WaveformType.VF:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0302"));
break;
case WaveformType.Normal:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0303"));
break;
default:
Debug.LogError("波形类型错误");
break;
}
}
/// <summary>
/// 发送同步开关显示状态命令
/// </summary>
public void SendSyncStateOrder(SyncType syncType, AddressCode send = AddressCode.Host)
{
switch (syncType)
{
case SyncType.None:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0400"));
break;
case SyncType.OFF:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0401"));
break;
case SyncType.ON:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0402"));
break;
default:
Debug.LogError("同步开关类型错误");
break;
}
}
/// <summary>
/// 发送充电显示状态命令
/// </summary>
public void SendChargeStateOrder(ChargeType chargeType, AddressCode send = AddressCode.Host)
{
switch (chargeType)
{
case ChargeType.None:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0500"));
break;
case ChargeType.Charge:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0501"));
break;
case ChargeType.Disarm:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0502"));
break;
default:
Debug.LogError("充电类型错误");
break;
}
}
/// <summary>
/// 发送充电标识显示状态命令
/// </summary>
public void SendChargeSignStateOrder(bool IsShow, AddressCode send = AddressCode.Host)
{
if (IsShow)
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0601"));
else
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0600"));
}
/// <summary>
/// 发送放电显示状态命令
/// </summary>
public void SendShockStateOrder(bool IsShow, AddressCode send = AddressCode.Host)
{
if (IsShow)
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0701"));
else
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0700"));
}
/// <summary>
/// 发送放电标识显示状态命令
/// </summary>
public void SendShockSignStateOrder(bool IsShow, AddressCode send = AddressCode.Host)
{
if (IsShow)
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0801"));
else
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0800"));
}
/// <summary>
/// 发送能量显示状态命令
/// </summary>
public void SendEnergyStateOrder(EnergyType energyType, AddressCode send = AddressCode.Host)
{
switch (energyType)
{
case EnergyType.ON:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0900"));
break;
case EnergyType.Twenty:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0914"));
break;
case EnergyType.Forty:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0928"));
break;
case EnergyType.Eighty:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0950"));
break;
case EnergyType.OneHundredAndTwenty:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0978"));
break;
case EnergyType.OneHundredAndFifty:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0996"));
break;
case EnergyType.TwoHundred:
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "09C8"));
break;
default:
Debug.LogError("能量类型错误");
break;
}
}
/// <summary>
/// 发送背景显示状态命令
/// </summary>
public void SendBackGroundStateOrder(bool IsShow, AddressCode send = AddressCode.Host)
{
if (IsShow)
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0A01"));
else
AddTaskFunction(new TaskBase(CmdType.AedCtrl, send, AddressCode.Defibrillator, "0A00"));
}
#endregion
//public void SetReceivingState() { Receiving = false; }
//--------------------------------------------------------------------------------
private void Awake()
{
if (Instance != null)
{
Debug.LogError("设备串口组件已经存在,不要重复添加!");
DestroyImmediate(gameObject);
}
else
Instance = this;
}
private void Update()
{
return;
Debug.LogAssertion(GetConnectState());
if (Input.GetKeyDown(KeyCode.D))
OpenDeviceConnect("COM5");
if (Input.GetKeyDown(KeyCode.Keypad9))
CloseDeviceConnect();
//查询结果
if (Input.GetKeyDown(KeyCode.PageUp))
{
bool b; string str;
(b, str) = GetReceiveMessage();
Debug.LogError(b + ">>>>>>>" + str);
}
//心跳
if (Input.GetKeyDown(KeyCode.Q))
SendHeartOrder(AddressCode.Defibrillator);
if (Input.GetKeyDown(KeyCode.W))
SendHeartOrder(AddressCode.AED);
if (Input.GetKeyDown(KeyCode.E))
SendHeartOrder(AddressCode.Human);
//状态查询
if (Input.GetKeyDown(KeyCode.R))
SendStateQueryOrder(AddressCode.Defibrillator);
if (Input.GetKeyDown(KeyCode.T))
SendStateQueryOrder(AddressCode.AED);
if (Input.GetKeyDown(KeyCode.Y))
SendStateQueryOrder(AddressCode.Human);
//AED灯光
if (Input.GetKeyDown(KeyCode.U))
SendAEDLightOrder(AEDLightType.AllOff);
if (Input.GetKeyDown(KeyCode.I))
SendAEDLightOrder(AEDLightType.AllOn);
if (Input.GetKeyDown(KeyCode.O))
SendAEDLightOrder(AEDLightType.Prower);
//模型人脉搏
if (Input.GetKeyDown(KeyCode.P))
SendPulseCtrlOrder(true);
if (Input.GetKeyDown(KeyCode.A))
SendPulseCtrlOrder(false);
//AED语音
if (Input.GetKeyDown(KeyCode.S))
SendAEDAudioOrder(AEDAudioType.Charging);
if (Input.GetKeyDown(KeyCode.F))
SendAEDAudioOrder(AEDAudioType.DisCharging);
if (Input.GetKeyDown(KeyCode.G))
SendAEDAudioOrder(AEDAudioType.DontTouch);
if (Input.GetKeyDown(KeyCode.H))
SendAEDAudioOrder(AEDAudioType.LowBattery);
if (Input.GetKeyDown(KeyCode.J))
SendAEDAudioOrder(AEDAudioType.NotDefibrillate);
if (Input.GetKeyDown(KeyCode.K))
SendAEDAudioOrder(AEDAudioType.OverDefibrillate);
if (Input.GetKeyDown(KeyCode.L))
SendAEDAudioOrder(AEDAudioType.ReadyTip);
if (Input.GetKeyDown(KeyCode.Z))
SendAEDAudioOrder(AEDAudioType.ReadyTipAgain);
//除颤仪心率
if (Input.GetKeyDown(KeyCode.X))
SendHeartRateStateOrder(100);
if (Input.GetKeyDown(KeyCode.C))
SendHeartRateStateOrder(0);
//除颤仪波形
if (Input.GetKeyDown(KeyCode.V))
SendWaveformStateOrder(WaveformType.Die);
if (Input.GetKeyDown(KeyCode.B))
SendWaveformStateOrder(WaveformType.None);
if (Input.GetKeyDown(KeyCode.N))
SendWaveformStateOrder(WaveformType.Normal);
if (Input.GetKeyDown(KeyCode.M))
SendWaveformStateOrder(WaveformType.VF);
//同步开关
if (Input.GetKeyDown(KeyCode.Alpha1))
SendSyncStateOrder(SyncType.None);
if (Input.GetKeyDown(KeyCode.Alpha2))
SendSyncStateOrder(SyncType.OFF);
if (Input.GetKeyDown(KeyCode.Alpha3))
SendSyncStateOrder(SyncType.ON);
//充电显示
if (Input.GetKeyDown(KeyCode.Alpha4))
SendChargeStateOrder(ChargeType.Charge);
if (Input.GetKeyDown(KeyCode.Alpha5))
SendChargeStateOrder(ChargeType.Disarm);
if (Input.GetKeyDown(KeyCode.Alpha6))
SendChargeStateOrder(ChargeType.None);
//充电标识显示
if (Input.GetKeyDown(KeyCode.Alpha7))
SendChargeSignStateOrder(true);
if (Input.GetKeyDown(KeyCode.Alpha8))
SendChargeSignStateOrder(false);
//放电显示
if (Input.GetKeyDown(KeyCode.Alpha9))
SendShockStateOrder(true);
if (Input.GetKeyDown(KeyCode.Alpha0))
SendShockStateOrder(false);
//放电标识
if (Input.GetKeyDown(KeyCode.UpArrow))
SendShockSignStateOrder(true);
if (Input.GetKeyDown(KeyCode.DownArrow))
SendShockSignStateOrder(false);
//能量选择
if (Input.GetKeyDown(KeyCode.Keypad0))
SendEnergyStateOrder(EnergyType.ON);
if (Input.GetKeyDown(KeyCode.Keypad1))
SendEnergyStateOrder(EnergyType.Twenty);
if (Input.GetKeyDown(KeyCode.Keypad2))
SendEnergyStateOrder(EnergyType.Forty);
if (Input.GetKeyDown(KeyCode.Keypad3))
SendEnergyStateOrder(EnergyType.Eighty);
if (Input.GetKeyDown(KeyCode.Keypad4))
SendEnergyStateOrder(EnergyType.OneHundredAndTwenty);
if (Input.GetKeyDown(KeyCode.Keypad5))
SendEnergyStateOrder(EnergyType.OneHundredAndFifty);
if (Input.GetKeyDown(KeyCode.Keypad6))
SendEnergyStateOrder(EnergyType.TwoHundred);
//背景显示
if (Input.GetKeyDown(KeyCode.Keypad7))
SendBackGroundStateOrder(true);
if (Input.GetKeyDown(KeyCode.Keypad8))
SendBackGroundStateOrder(false);
}
private void FixedUpdate()
{
TaskTimeOutFun();
}
/// <summary>
/// 任务超时检测(500毫秒)
/// </summary>
private void TaskTimeOutFun()
{
if (IsTimer)
{
if (GetTime() - SendTime > TimeOut && MyTaskTable.Count > 0)//任务发送后500毫秒未收到响应,就移除当前任务
{
MyTaskTable.Remove(MyTaskTable[0]);
receiveStr.Clear();
Receiving = IsTimer = false;//进入非等待响应状态 并且 关闭定时
Debug.Log("当前任务超时,移除任务");
}
}
}
/// <summary>
/// 打开设备串口
/// </summary>
private bool OpenSerialPort(string comName)
{
try
{
if (port != null && port.IsOpen)
{
Debug.LogError("设备串口已开启,请勿重复启动"); return false;
}
port = new SerialPort(comName, 115200, Parity.None, 8, StopBits.One);
//串口初始化
if (!port.IsOpen)
port.Open();
recvThread = new Thread(ReceiveData); //该线程用于接收串口数据
ThreadRuning = true;
recvThread.Start();
return true;
}
catch (Exception ex)
{
Debug.LogError("设备串口打开错误:" + ex);
return false;
}
}
/// <summary>
/// 添加任务
/// </summary>
private void AddTaskFunction(TaskBase task)
{
//int cacheID = MyTaskTable.Count;//在这里设置ID
if (port != null && port.IsOpen)
{
MyTaskTable.Add(task);//Debug.LogError("添加任务");
}
else
Debug.LogError("主机串口未打开,请检查设备连接!");
}
/// <summary>
/// 发送数据
/// </summary>
private void SendData()
{
if (MyTaskTable.Count <= 0)
return;
TaskBase task = MyTaskTable[0];
#region 拼接命令
Byte[] bytes;
switch (task.cmdType)//根据命令的不同,决定数据长度与内容;
{
case CmdType.Heart://心跳
bytes = new Byte[9];
bytes[2] = 0x01;//命令
bytes[5] = 0x01;//长度
bytes[6] = (byte)Convert.ToInt32(task.data, 16);//数据
break;
case CmdType.StartCheck://开始检测
bytes = new Byte[9];
bytes[2] = 0x02;//命令
bytes[5] = 0x01;//长度
bytes[6] = (byte)Convert.ToInt32(task.data, 16);//数据
break;
case CmdType.OverCheck://结束检测
bytes = new Byte[9];
bytes[2] = 0x03;//命令
bytes[5] = 0x01;//长度
bytes[6] = (byte)Convert.ToInt32(task.data, 16);//数据
break;
case CmdType.StateQuery://状态查询
bytes = new Byte[9];
bytes[2] = 0x04;//命令
bytes[5] = 0x01;//长度
bytes[6] = (byte)Convert.ToInt32(task.data, 16);//数据
break;
case CmdType.OutPutCtrl://输出控制
bytes = new Byte[9];
bytes[2] = 0x05;//命令
bytes[5] = 0x01;//长度
bytes[6] = (byte)Convert.ToInt32(task.data, 16);//数据
break;
case CmdType.DragCtrl://阻力控制
bytes = new Byte[11];
bytes[2] = 0x06;//命令
bytes[5] = 0x03;//长度
bytes[6] = (byte)Convert.ToInt32("0x" + task.data.Substring(0, 2), 16);//数据
bytes[7] = (byte)Convert.ToInt32("0x" + task.data.Substring(2, 2), 16); //数据
bytes[8] = (byte)Convert.ToInt32("0x" + task.data.Substring(4, 2), 16);// 数据
break;
case CmdType.ClearEncoder://编码器清零
bytes = new Byte[9];
bytes[2] = 0x07;//命令
bytes[5] = 0x01;//长度
bytes[6] = (byte)Convert.ToInt32(task.data, 16);//数据
break;
case CmdType.AedCtrl://除颤仪/AED控制
bytes = new Byte[10];
bytes[2] = 0x08;//命令
bytes[5] = 0x02;//长度
bytes[6] = (byte)Convert.ToInt32("0x" + task.data.Substring(0, 2), 16);//数据
bytes[7] = (byte)Convert.ToInt32("0x" + task.data.Substring(2, 2), 16); //数据
break;
default:
Debug.LogError("命令类型不正确,请检查");
return;
}
switch (task.receiveAddress)//接收地址
{
case AddressCode.Host:
bytes[3] = 0x00;
break;
case AddressCode.Pad:
bytes[3] = 0x10;
break;
case AddressCode.AED:
bytes[3] = 0x20;
break;
case AddressCode.Defibrillator:
bytes[3] = 0x30;
break;
case AddressCode.Human:
bytes[3] = 0x40;
break;
default:
break;
}
switch (task.sendAddress)//发送地址
{
case AddressCode.Host:
bytes[4] = 0x00;
break;
case AddressCode.Pad:
bytes[4] = 0x10;
break;
case AddressCode.AED:
bytes[4] = 0x20;
break;
case AddressCode.Defibrillator:
bytes[4] = 0x30;
break;
case AddressCode.Human:
bytes[4] = 0x40;
break;
default:
break;
}
bytes[0] = 0x90;//固定起始帧头
bytes[1] = 0xEB;//固定起始帧头
#endregion
#region 计算数据的校验和
int SumInt = 0;
for (int i = 0; i < bytes.Length - 4; i++)
SumInt += Convert.ToInt32(bytes[i + 2]);
SumInt = 65535 - SumInt;
string SumStr = Convert.ToString(SumInt, 16);
bytes[bytes.Length - 2] = (byte)Convert.ToInt32("0x" + SumStr.Substring(2, 2), 16);
bytes[bytes.Length - 1] = (byte)Convert.ToInt32("0x" + SumStr.Substring(0, 2), 16);
#endregion
#region 打印预备发送的数据
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
sb.Append(Convert.ToString(bytes[i], 16));
if (i != bytes.Length - 1) sb.Append("-");
}
Debug.Log("发送的数据:" + sb.ToString() + " 数据长度为:" + bytes.Length);
#endregion
DataSend(bytes, bytes.Length);//发送数据
SendTime = GetTime();//获取发送数据的时间
IsTimer = true;
}
/// <summary>
/// 接收数据
/// </summary>
private void ReceiveData()
{
try
{
if (port.IsOpen)
Debug.Log("成功打开串口:" + port.PortName);
while (ThreadRuning)
{
Thread.Sleep(30);
if (!port.IsOpen)//串口没开-跳出线程
return;
// Debug.Log("接收线程运行中...");
int datalength = port.BytesToRead;
if (datalength == 0)//长度为0-无返回数据
{
//Debug.Log("无返回数据...当前任务数量:" + MyTaskTable.Count + Receiving);
if (MyTaskTable.Count > 0 && !Receiving)//判断是否有后续任务 并且 是否正在等待响应
{
Debug.Log("无返回数据...但有缓存任务");
SendData(); Receiving = true;//有任务未发送且不等待响应,则发送下一个任务,并且进入等待响应
}
}
else
{
receiveBytes = new byte[datalength];
port.Read(receiveBytes, 0, datalength);
if (datalength < 9) { Debug.LogError("接受的数据总长度低于最小数据长度,请校验"); continue; }//9是长度,因为最小data为1,算上其他固定数据。就是9;
if (int.Parse(Convert.ToString(receiveBytes[3], 10)) != 0) { Debug.LogAssertion("<接收到数据,但接收地址不是主机,过滤掉了>"); continue; }
bool result = CheckSumFun(receiveBytes);
if (result)
{
receiveStr.Clear();
for (int i = 0; i < datalength; i++)
{
receiveStr.Append(Convert.ToString(receiveBytes[i], 16));
if (i < datalength - 1)
receiveStr.Append("-");
}
// Debug.LogError("接收的数据:" + receiveStr.ToString() + "***数据总长度:" + datalength + "***有效数据长度:" + Convert.ToString(receiveBytes[5], 10) + "***本次处理时长:" + (GetTime() - SendTime) + "毫秒");
//接收过一次返回后,清空本次任务,并且进入非等待接收状态,关闭计时(要在单主机情况下进行
if (MyTaskTable.Count > 0)
MyTaskTable.Remove(MyTaskTable[0]);
IsTimer = false;
}
else
{
Debug.LogError("接收数据检验和结果不正确");
}
Receiving = false;//进入非等待响应状态
}
}
}
catch (Exception ex)
{
Debug.LogError("接收串口数据错误:" + ex);
port = null; ThreadRuning = false;
}
}
/// <summary>
/// 检查校验和 T:合法 F:非法
/// </summary>
private bool CheckSumFun(byte[] receiveBytes)
{
#region 检测命令是否正确
if (Convert.ToInt32(receiveBytes[2]) == 0)
{
Debug.LogError("返回数据指出上一次发送的命令是错误的!");
return false;
}
#endregion
#region 计算数据的校验和是否与返回数据的校验和一致
int SumInt = 0;
for (int i = 0; i < receiveBytes.Length - 4; i++)
SumInt += Convert.ToInt32(receiveBytes[i + 2]);
SumInt = 65535 - SumInt;
string SumStr = Convert.ToString(SumInt, 16);
if (SumStr.Substring(0, 2) == Convert.ToString(receiveBytes[receiveBytes.Length - 1], 16) &&
SumStr.Substring(2, 2) == Convert.ToString(receiveBytes[receiveBytes.Length - 2], 16))
{
return true;
}
else
{
return false;
}
#endregion
}
/// <summary>
/// 获取当前系统时间(毫秒
/// </summary>
/// <returns></returns>
private int GetTime()
{
string timeStr = DateTime.Now.ToString("ss:fff");
string[] strs = timeStr.Split(':');
int currentTime = int.Parse(strs[0]) * 1000;
return currentTime += int.Parse(strs[1]);
}
/// <summary>
/// 数据发送
/// </summary>
/// <param name="data"></param>
/// <param name="count"></param>
private void DataSend(Byte[] data, int count)
{
port.Write(data, 0, count);
}
private void OnApplicationQuit()
{
CloseDeviceConnect();
}
}
/// <summary>
/// 任务基类
/// </summary>
internal class TaskBase
{
//public int id;//任务唯一ID
public CmdType cmdType;//命令类型
public AddressCode sendAddress;//发送地址
public AddressCode receiveAddress;//接收地址
public string data;//数据
public TaskBase(CmdType cmdType, AddressCode sendAddress, AddressCode receiveAddress, string data = "0x00")
{
this.cmdType = cmdType;
this.sendAddress = sendAddress;
this.receiveAddress = receiveAddress;
this.data = data;
}
}
/// <summary>
/// 命令类型
/// </summary>
public enum CmdType
{
/// <summary>
/// 心跳0x01
/// </summary>
Heart,
/// <summary>
/// 开始检测0x02
/// </summary>
StartCheck,
/// <summary>
/// 结束检测0x03
/// </summary>
OverCheck,
/// <summary>
/// 状态查询0x04
/// </summary>
StateQuery,
/// <summary>
/// 数字输出控制0x05
/// </summary>
OutPutCtrl,
/// <summary>
/// 模拟输出控制0x06
/// </summary>
DragCtrl,
/// <summary>
/// 清除编码器0x07
/// </summary>
ClearEncoder,
/// <summary>
/// AED控制0x08
/// </summary>
AedCtrl
}
/// <summary>
/// 地址编码
/// </summary>
public enum AddressCode
{
/// <summary>
/// 主机0x00
/// </summary>
Host,
/// <summary>
/// 平板0x10
/// </summary>
Pad,
/// <summary>
/// AED 0x20
/// </summary>
AED,
/// <summary>
/// 除颤仪0x30
/// </summary>
Defibrillator,
/// <summary>
/// 模型人0x40
/// </summary>
Human
}
/// <summary>
/// 数据长度
/// </summary>
public enum DataLength
{
/// <summary>
/// 一个字节
/// </summary>
One,
/// <summary>
/// 两个字节
/// </summary>
Two
}
/// <summary>
/// AED灯光类型
/// </summary>
public enum AEDLightType
{
/// <summary>
/// 全关
/// </summary>
AllOff,
/// <summary>
/// 全开
/// </summary>
AllOn,
/// <summary>
/// 只开电源
/// </summary>
Prower
}
/// <summary>
/// AED音频类型
/// </summary>
public enum AEDAudioType
{
/// <summary>
/// 按照图示,将电极贴在病人胸部的皮肤上,将电极插头插入插座上
/// </summary>
ReadyTip,
/// <summary>
/// 不建议除颤
/// </summary>
NotDefibrillate,
/// <summary>
/// 除颤完成,开始心肺复苏
/// </summary>
OverDefibrillate,
/// <summary>
/// 建议除颤,正在充电,不要接触病人身体
/// </summary>
Charging,
/// <summary>
/// 立刻进行除颤,按橘黄色按钮
/// </summary>
DisCharging,
/// <summary>
/// 贴上电极,插入插头
/// </summary>
ReadyTipAgain,
/// <summary>
/// 正在分析病人,不要触碰病人
/// </summary>
DontTouch,
/// <summary>
/// 电量不足,请充电
/// </summary>
LowBattery,
}
/// <summary>
/// 除颤仪波形类型
/// </summary>
public enum WaveformType
{
/// <summary>
/// 不显示
/// </summary>
None,//
/// <summary>
/// 死亡
/// </summary>
Die,
/// <summary>
/// 室颤
/// </summary>
VF,
/// <summary>
/// 正常
/// </summary>
Normal
}
/// <summary>
/// 同步开关类型
/// </summary>
public enum SyncType
{
/// <summary>
/// 不显示
/// </summary>
None,
/// <summary>
/// 关
/// </summary>
OFF,
/// <summary>
/// 开
/// </summary>
ON,
}
/// <summary>
/// 充电类型
/// </summary>
public enum ChargeType
{
/// <summary>
/// 不显示
/// </summary>
None,
/// <summary>
/// 充电
/// </summary>
Charge,
/// <summary>
/// 释放
/// </summary>
Disarm,
}
/// <summary>
/// 除颤仪能量类型
/// </summary>
public enum EnergyType
{
/// <summary>
/// 不显示
/// </summary>
ON,
/// <summary>
/// 20
/// </summary>
Twenty,
/// <summary>
/// 40
/// </summary>
Forty,
/// <summary>
/// 80
/// </summary>
Eighty,
/// <summary>
/// 120
/// </summary>
OneHundredAndTwenty,
/// <summary>
/// 150
/// </summary>
OneHundredAndFifty,
/// <summary>
/// 200
/// </summary>
TwoHundred
}
}
2021-05-28
最新推荐文章于 2022-02-24 13:31:38 发布