using ScottPlot.Colormaps; using SWRIS.Enums; using SWRIS.Events; using SWRIS.Extensions; using SWRIS.Models; using SWRIS.Models.Data; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; namespace SWRIS.Core { public class TcpServerFrame : IDisposable { // 定义事件 public event EventHandler ClientConnected; public event EventHandler ClientDisconnected; public event EventHandler LiveStreamReceived; public event EventHandler AlarmDataReceived; public event EventHandler FaultDataReceived; public event EventHandler DetectionDataReceived; public event EventHandler RealTimeDataReceived; public event EventHandler DetectionRawDataReceived; public event EventHandler ResetSystemDataReceived; public event EventHandler SetAbsolutePositionDataReceived; public event EventHandler DetectionRawDataResultReceived; public event EventHandler DetectionStatusResultReceived; public event EventHandler UpgradedRequestResultReceived; public event EventHandler ClockResultReceived; public event EventHandler EncoderDirectionResultReceived; public event EventHandler HeartbeatReceived; public event EventHandler DebugMessageReceived; private Socket _listener; private bool _isRunning; private readonly string _ipAddress; private readonly int _port; private readonly ByteTransform byteTransform; private const string PASSWORD = "WNDTM4"; private static ConcurrentDictionary _connectedClients; public TcpServerFrame(string ipAddress, int port) { _ipAddress = ipAddress; _port = port; byteTransform = new ByteTransform(DataFormat.DCBA); _connectedClients = new ConcurrentDictionary(); } public void Start() { _isRunning = true; _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { // 使用指定的IP地址和端口 IPAddress ipAddress = IPAddress.Parse(_ipAddress); _listener.Bind(new IPEndPoint(ipAddress, _port)); _listener.Listen(10); // 启动心跳检测线程 StartHeartbeatCheck(); // 开始接受客户端连接(异步) _listener.BeginAccept(OnClientConnected, null); DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"服务已在 {_ipAddress}:{_port} 上启动")); } catch (SocketException ex) { LogHelper.Error($"启动服务时发生错误: {ex.Message}"); if (ex.SocketErrorCode == SocketError.AddressAlreadyInUse) { LogHelper.Error("端口已被占用,请更换端口或关闭占用该端口的程序", ex); } else if (ex.SocketErrorCode == SocketError.AddressNotAvailable) { LogHelper.Error($"IP地址 {_ipAddress} 不可用,请检查网络配置", ex); } } catch (Exception ex) { LogHelper.Error($"TCP服务启动时发生未知错误: {ex.Message}", ex); } } public void Stop() { _isRunning = false; _listener.Shutdown(SocketShutdown.Both); _listener?.Close(); } private void OnClientConnected(IAsyncResult ar) { if (!_isRunning) return; try { Socket clientSocket = _listener.EndAccept(ar); string ipAddress = (clientSocket.RemoteEndPoint as IPEndPoint)?.Address?.ToString(); var equipmentData = App.Config.Equipments.FirstOrDefault(c => c.IpAddress == ipAddress); if (equipmentData != null) { ClientState client = new ClientState(clientSocket, ipAddress, equipmentData.SerialNo); // 添加到连接列表 _connectedClients.TryAdd(client.IpAddress, client); // 开始异步接收数据 clientSocket.BeginReceive(client.Buffer, 0, client.Buffer.Length, SocketFlags.None, OnDataReceived, client); // 触发客户端连接事件 ClientConnected?.Invoke(this, new ClientConnectedEventArgs(clientSocket, ipAddress)); } // 继续接受新连接 _listener.BeginAccept(OnClientConnected, null); } catch (Exception ex) { Console.WriteLine($"Error accepting client: {ex.Message}"); } } private void StartHeartbeatCheck() { ThreadPool.QueueUserWorkItem(act => { while (_isRunning) { Thread.Sleep(TimeSpan.FromSeconds(5)); // 每5秒检测一次 foreach (var client in _connectedClients.ToArray()) { if ((DateTime.UtcNow - client.Value.LastActiveTime).TotalSeconds > 15) { SafeCloseClient(client.Value); DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"心跳超时,强制断开", ipAddress: client.Value.IpAddress)); } } } }); } private async void OnDataReceived(IAsyncResult ar) { var state = (ClientState)ar.AsyncState; if (state == null || state.ClientSocket == null || !state.ClientSocket.Connected) { return; } try { int bytesRead = state.ClientSocket.EndReceive(ar); if (bytesRead > 0) { // 将接收到的数据添加到缓冲区 state.ReceiveBuffer.Write(state.Buffer, 0, bytesRead); // 处理缓冲区中的所有数据包 while (state.ReceiveBuffer.Length > 0) { byte packetType = state.ReceiveBuffer.PeekByte(); if (packetType == 0xC0) // 心跳包 { ProcessHeartbeatPacket(state); } else if (packetType == 0x30) // 数据包 { bool processed = await ProcessDataPacket(state); if (!processed) break; // 数据包不完整,等待更多数据 } else { // 未知包类型,跳过1字节继续检查 DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"未知包类型: 0x{packetType:X2}", state.IpAddress)); state.ReceiveBuffer.Remove(1); } } // 继续接收数据 if (state.ClientSocket?.Connected == true) { Array.Clear(state.Buffer, 0, state.Buffer.Length); state.ClientSocket.BeginReceive(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, OnDataReceived, state); } } else { // 客户端断开连接 DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs((bytesRead == 0 ? "设备主动断开连接" : "连接异常或错误") + $"({bytesRead})", state.IpAddress)); SafeCloseClient(state); } } catch (SocketException sex) { HandleSocketException(sex, state); } catch (Exception ex) { var message = $"接收数据时错误: {ex.Message}"; LogHelper.Error(message, ex); SafeCloseClient(state); } } private void HandleSocketException(SocketException sex, ClientState client) { string message; switch (sex.SocketErrorCode) { case SocketError.ConnectionReset: message = "设备强制断开连接 (Connection Reset)"; break; case SocketError.OperationAborted: message = "操作被中止"; break; case SocketError.ConnectionAborted: message = "连接被中止"; break; case SocketError.TimedOut: message = "连接超时"; break; case SocketError.Shutdown: message = "连接已关闭"; break; case SocketError.NetworkReset: message = "网络连接被重置"; break; case SocketError.HostUnreachable: message = "主机不可达"; break; default: message = $"Socket错误: {sex.SocketErrorCode} - {sex.Message}"; break; } DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs(message, client.IpAddress)); LogHelper.Error(message, sex); SafeCloseClient(client); } private void ProcessHeartbeatPacket(ClientState client) { // 心跳包固定长度为2字节: 0xC0 + 0x00 if (client.ReceiveBuffer.Length < 2) return; // 等待更多数据 byte[] heartBeatData = new byte[2]; client.ReceiveBuffer.Read(heartBeatData, 0, 2); client.LastActiveTime = DateTime.UtcNow; RespondHeartbeat(heartBeatData, client.IpAddress, client.ClientSocket); HeartbeatReceived?.Invoke(this, new HeartbeatReceviedEventArgs(client.IpAddress)); } private async Task ProcessDataPacket(ClientState client) { // 检查是否有足够的数据读取长度信息 if (client.ReceiveBuffer.Length < 5) // 至少需要包类型 + 最小长度信息 return false; // 窥探前10个字节来解析长度 byte[] peekData = new byte[Math.Min(client.ReceiveBuffer.Length, 10)]; int peeked = client.ReceiveBuffer.Peek(peekData, 0, peekData.Length); // 解析剩余长度 (int byteLength, int remainingLength) = GetRemainingLength(peekData); if (byteLength == 0 || remainingLength == 0) { // 长度解析失败,可能是数据损坏,跳过1字节 client.ReceiveBuffer.Remove(1); return true; } // 计算完整包长度 int totalPacketLength = 1 + byteLength + remainingLength; // 检查是否收到完整包 if (client.ReceiveBuffer.Length < totalPacketLength) return false; // 读取完整数据包 byte[] packetData = new byte[totalPacketLength]; client.ReceiveBuffer.Read(packetData, 0, totalPacketLength); // 提取事件类型和有效载荷 int payloadStart = 1 + byteLength; if (payloadStart >= packetData.Length) { DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"数据异常", client.IpAddress)); return true; } byte eventType = packetData[payloadStart]; byte[] payload = new byte[remainingLength]; Buffer.BlockCopy(packetData, payloadStart, payload, 0, remainingLength); // 处理数据包 await ProcessEventByType(eventType, payload, client); return true; } /// /// 根据事件类型处理数据 /// /// /// /// /// private async Task ProcessEventByType(byte eventType, byte[] payload, ClientState client) { switch (eventType) { case 0x01: await ProcessSyncParameters(payload, client); break; case 0x06: await ProcessDetectionStatus(payload, client); break; case 0x07: await ProcessFaultData(payload, client); break; case 0x08: await ProcessAlarmData(payload, client); break; case 0x09: await ProcessDetectionData(payload, client); break; case 0x10: await ProcessClockData(payload, client); break; case 0x11: await ProcessUpgradedData(payload, client); break; case 0x12: await ProcessEncoderDirectionData(payload, client); break; case 0x13: await ProcessTwistFactorData(payload, client); break; case 0x0A: await ProcessOpenOrClosedRealtimeData(payload, client); break; case 0x0B: await ProcessRealTimeData(payload, client); break; case 0x0D: await ProcessLiveStreamData(payload, client); break; case 0x0C: await ProcessTurnLiveStreamData(payload, client); break; case 0x0E: await ProcessDetectionRawResultData(payload, client); break; case 0x0F: await ProcessDetectionRawData(payload, client); break; case 0x14: await ProcessSystemResetData(payload, client); break; case 0x15: await ProcessSetAbsolutePositionData(payload, client); break; case 0x16: await ProcessSerialNoData(payload, client); break; } } /// /// 设置实时位置 /// /// /// /// private async Task ProcessSetAbsolutePositionData(byte[] buffer, ClientState client) { var resetSystemData = ReceiveSetAbsolutePositionData(buffer); if (resetSystemData != null) { // 设置当前实时位置应答 SetAbsolutePositionDataReceived?.Invoke(this, new SetAbsolutePositionDataReceivedEventArgs(client.IpAddress, resetSystemData)); } await Task.CompletedTask; } /// /// 主板复位 /// /// /// /// private async Task ProcessSystemResetData(byte[] buffer, ClientState client) { var resetSystemData = ReceiveResetSystemData(buffer); if (resetSystemData != null) { // 主板复位结果 ResetSystemDataReceived?.Invoke(this, new ResetSystemDataReceivedEventArgs(client.IpAddress, resetSystemData)); } await Task.CompletedTask; } private async Task ProcessDetectionRawData(byte[] buffer, ClientState client) { await Task.Run(() => { var detectionRawData = ReceiveDetectionRawData(buffer); if (detectionRawData != null) { // 处理检测原始数据 DetectionRawDataReceived?.Invoke(this, new DetectionRawDataReceivedEventArgs(client.IpAddress, detectionRawData)); } }); await Task.CompletedTask; } private async Task ProcessDetectionRawResultData(byte[] buffer, ClientState client) { await Task.Run(() => { var detectionRawResultData = ReceiveDetectionRawResultData(buffer); if (detectionRawResultData != null) { DetectionRawDataResultReceived?.Invoke(this, new DetectionRawDataResultReceivedEventArgs(client.IpAddress, detectionRawResultData)); } }); await Task.CompletedTask; } private async Task ProcessTurnLiveStreamData(byte[] buffer, ClientState client) { var liveStreamStatus = ReceiveTurnLiveStreamData(buffer); if (liveStreamStatus > 0) { // 开启/关闭结果,0=成功,>0=失败-原因码 LogHelper.Error($"开启/关闭实时流数据失败,原因码:{liveStreamStatus}"); } await Task.CompletedTask; } private async Task ProcessLiveStreamData(byte[] buffer, ClientState client) { await Task.Run(() => { var liveStreamData = ReceiveLiveStreamDataModel(buffer); if (liveStreamData != null && liveStreamData.Data.Any()) { Console.WriteLine($"接收实时流数据: {liveStreamData.ToString()}"); // 触发事件 LiveStreamReceived?.Invoke(this, new LiveStreamReceivedEventArgs(client.IpAddress, liveStreamData)); } }); await Task.CompletedTask; } private async Task ProcessRealTimeData(byte[] buffer, ClientState client) { await Task.Run(() => { var realTimeData = ReceiveRealTimeData(buffer); if (realTimeData != null) { // 触发实时数据接收事件 RealTimeDataReceived?.Invoke(this, new RealTimeDataReceivedEventArgs(client.IpAddress, realTimeData)); } }); await Task.CompletedTask; } private async Task ProcessOpenOrClosedRealtimeData(byte[] buffer, ClientState client) { var openOrClosed = ReceiveOpenOrClosedRealtimeData(buffer); if (openOrClosed > 0) { LogHelper.Error("开启或关闭实时数据失败,原因码:" + openOrClosed); } await Task.CompletedTask; } private async Task ProcessTwistFactorData(byte[] buffer, ClientState client) { var twistFactorData = ReceiveTwistFactorData(buffer); if (twistFactorData != null) { var equipmentData = App.Config.Equipments.FirstOrDefault(c => c.IpAddress == client.IpAddress); if (equipmentData != null && equipmentData.Parameter != null) { // 处理判伤捻距系数数据 equipmentData.Parameter.TwistFactor = twistFactorData.TwistFactor; } } await Task.CompletedTask; } private async Task ProcessEncoderDirectionData(byte[] buffer, ClientState client) { var encoderDirection = ReceiveEncoderDirectionData(buffer); if (encoderDirection != null) { var equipmentData = App.Config.Equipments.FirstOrDefault(c => c.IpAddress == client.IpAddress); if (equipmentData != null && equipmentData.Parameter != null) { // 处理编码器方向数据 equipmentData.Parameter.EncoderDirection = encoderDirection.Direction; // 编码器方向结果返回事件 EncoderDirectionResultReceived?.Invoke(this, new EncoderDirectionResultReceivedEventArgs(client.IpAddress, encoderDirection.Direction)); } } await Task.CompletedTask; } private async Task ProcessClockData(byte[] buffer, ClientState client) { var clockData = ReceiveClockData(buffer); if (clockData != null) { ClockResultReceived?.Invoke(this, new ClockResultReceivedEventArgs(client.IpAddress, clockData.Time)); } await Task.CompletedTask; } private async Task ProcessDetectionData(byte[] buffer, ClientState client) { var detectionData = ReceiveDetectionData(buffer); if (detectionData != null) { // 回复检测结果确认 if (SendDetectionConfirm(detectionData.StartTime, detectionData.EndTime, client.SerialNo, client.ClientSocket)) { if (detectionData.DamageCount <= 0) { DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"检测结果未发现损伤,本次结果不记录", serialNo: client.SerialNo)); } else { // 发送获取原始数据请求 SendGetDetectionRawData(client.SerialNo, client.ClientSocket); // 处理检测数据 DetectionDataReceived?.Invoke(this, new DetectionDataReceivedEventArgs(client.IpAddress, detectionData)); } } } await Task.CompletedTask; } private async Task ProcessFaultData(byte[] buffer, ClientState client) { var faultData = ReceiveFaultData(buffer); if (faultData != null) { // 处理故障数据 FaultDataReceived?.Invoke(this, new FaultDataReceivedEventArgs(client.IpAddress, faultData)); } await Task.CompletedTask; } private async Task ProcessAlarmData(byte[] buffer, ClientState client) { var alarmData = ReceiveAlarmData(buffer); if (alarmData != null) { //处理报警数据 AlarmDataReceived?.Invoke(this, new AlarmDataReceivedEventArgs(client.IpAddress, alarmData)); } await Task.CompletedTask; } private async Task ProcessSyncParameters(byte[] data, ClientState client) { var (serialNo, parametersData) = ReceiveSyncParameters(data); if (parametersData != null) { var equipmentData = App.Config.Equipments.FirstOrDefault(c => c.IpAddress == client.IpAddress); if (equipmentData != null) { equipmentData.SerialNo = serialNo; equipmentData.Parameter = parametersData; await Task.Run(() => { lock (App.Config.Equipments) { ConfigHelper.SetEquipment(equipmentData); } }); } } } private async Task ProcessDetectionStatus(byte[] buffer, ClientState client) { byte code = ReceiveStartOrStopDetectionResultData(buffer); if (code == 0) { // 启动/停止检测结果,0=成功,>0=失败-原因码 DetectionStatusResultReceived?.Invoke(this, new DetectionStatusResultReceivedEventArgs(client.IpAddress, code)); } else { LogHelper.Error($"启动/停止检测结果失败,原因码:{code}"); } await Task.CompletedTask; } public async Task ProcessUpgradedData(byte[] buffer, ClientState client) { byte code = ReceiveUpgradedResultData(buffer); // 程序更新请求,0=成功,>0=拒绝-原因码 UpgradedRequestResultReceived?.Invoke(this, new UpgradedResultReceivedEventArgs(client.IpAddress, code)); await Task.CompletedTask; } public byte ReceiveTurnLiveStreamData(byte[] buffer) { (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer); return bytes[0]; } public byte ReceiveOpenOrClosedRealtimeData(byte[] buffer) { (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer); return bytes[0]; // 开启/关闭结果,0=成功,>0=失败-原因码 } public LiveStreamDataModel ReceiveLiveStreamDataModel(byte[] buffer) { (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer); var liveStreamData = new LiveStreamDataModel() { SensorCount = bytes[0], SampleCount = byteTransform.TransUInt16(bytes, 1) }; var data = bytes.Skip(3).ToArray(); // 跳过前3个字节 liveStreamData.Data = ParseSensorData(data, liveStreamData.SensorCount, liveStreamData.SampleCount); return liveStreamData; } public TwistFactorDataModel ReceiveTwistFactorData(byte[] buffer) { (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer); var twistFactorData = new TwistFactorDataModel { Type = bytes[0], TwistFactor = byteTransform.TransSingle(bytes, 1) // 判伤捻距系数 }; return twistFactorData; } /// /// 发送获取编码器方向请求 /// /// /// /// public bool SendGetEncoderDirectionData(string serialNo, Socket clientSocket) { try { if (clientSocket == null || !clientSocket.Connected) return false; using (var ms = new MemoryStream()) { ms.WriteByte(0x00); // 操作,0 = 获取编码器方向,1 = 设置编码器方向 ms.WriteByte(0x01); // 编码器方向,1=正向,2=反向 byte[] buffer = CreateData(0x12, ms.ToArray(), serialNo); DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"获取设备编码器方向", serialNo: serialNo)); clientSocket.Send(buffer); return true; } } catch (Exception ex) { LogHelper.Error("发送获取编码器方向数据命令时错误", ex); return false; } } /// /// 发送设置编码器方向数据命令 /// /// /// /// /// public bool SendSetEncoderDirectionData(EncoderDirection direction, string serialNo, Socket clientSocket) { try { if (clientSocket == null || !clientSocket.Connected) return false; using (var ms = new MemoryStream()) { ms.WriteByte(0x01); // 操作,0 = 获取编码器方向,1 = 设置编码器方向 ms.WriteByte((byte)direction); // 编码器方向,1=正向,2=反向 byte[] buffer = CreateData(0x12, ms.ToArray(), serialNo); DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"设置设备编码器方向", serialNo: serialNo)); clientSocket.Send(buffer); return true; } } catch (Exception ex) { LogHelper.Error("发送设置编码器方向数据命令时错误", ex); return false; } } /// /// 发送检测结果原始数据请求 /// /// /// /// private bool SendGetDetectionRawData(string serialNo, Socket clientSocket) { try { if (clientSocket == null || !clientSocket.Connected) return false; using (var ms = new MemoryStream()) { ms.WriteByte(0); // 数据类型,0=正常,1=报警,2=故障 WriteBytes(ms, (short)2048); // 单包数据大小,单位:Byte ms.WriteByte(0x00); // 传输速度控制,单位:KB/s(B/ms),为0则不控速 byte[] buffer = CreateData(0x0E, ms.ToArray(), serialNo); DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"获取检测结果原始数据", serialNo: serialNo)); clientSocket.Send(buffer); return true; } } catch (Exception ex) { LogHelper.Error("发送获取编码器方向数据命令时错误", ex); return false; } } /// /// 接收获取原始数据结果 /// /// /// public DetectionRawResultDataModel ReceiveDetectionRawResultData(byte[] buffer) { (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer); var detectionRawResultData = new DetectionRawResultDataModel { Code = bytes[0], Timestamp = byteTransform.TransInt32(bytes, 1), SamplingStep = byteTransform.TransSingle(bytes, 5), StartAbsolutePosition = byteTransform.TransSingle(bytes, 9), EndAbsolutePosition = byteTransform.TransSingle(bytes, 13), SensorCount = bytes[17] }; return detectionRawResultData; } /// /// 获取原始数据包 /// /// /// public DetectionRawDataModel ReceiveDetectionRawData(byte[] buffer) { (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer); var detectionRawData = new DetectionRawDataModel { PacketNumber = byteTransform.TransUInt32(bytes, 0), TotalPackets = byteTransform.TransUInt32(bytes, 4), DataLength = byteTransform.TransUInt16(bytes, 8), Data = bytes.Skip(10).ToArray() // 跳过前10个字节 }; return detectionRawData; } /// /// 发送开启实时流数据命令 /// /// 是否开启 /// 设备序列号 /// /// public bool SendTurnLiveStreamData(bool isOpen, string serialNo, Socket clientSocket) { try { if (clientSocket == null || !clientSocket.Connected) return false; using (var ms = new MemoryStream()) { ms.WriteByte((byte)(isOpen ? 1 : 0)); // 0=关闭,1=开启 byte[] buffer = CreateData(0x0C, ms.ToArray(), serialNo); DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"{(isOpen ? "开启" : "关闭")}设备实时流", serialNo: serialNo)); clientSocket.Send(buffer); return true; } } catch (Exception ex) { LogHelper.Error("发送开启实时流数据命令时错误", ex); return false; } } /// /// 发送获取判伤捻距系数数据命令 /// /// /// /// public bool SendGetTwistFactorData(string serialNo, Socket clientSocket) { try { if (clientSocket == null || !clientSocket.Connected) return false; using (var ms = new MemoryStream()) { ms.WriteByte(0x00); // 操作,0=获取判伤捻距系数,1=设置判伤捻距系数 WriteBytes(ms, 0); // 判伤捻距系数 byte[] buffer = CreateData(0x13, ms.ToArray(), serialNo); DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"获取设备判伤捻距系数", serialNo: serialNo)); clientSocket.Send(buffer); return true; } } catch (Exception ex) { LogHelper.Error("发送获取判伤捻距系数数据命令时错误", ex); return false; } } /// /// 设置判伤捻距系数 /// /// /// /// /// public bool SendSetTwistFactorData(float twistFactor, string serialNo, Socket clientSocket) { try { if (clientSocket == null || !clientSocket.Connected) return false; using (var ms = new MemoryStream()) { ms.WriteByte(0x01); // 操作,0=获取判伤捻距系数,1=设置判伤捻距系数 WriteBytes(ms, twistFactor); // 判伤捻距系数 byte[] buffer = CreateData(0x13, ms.ToArray(), serialNo); DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"设置设备判伤捻距系数", serialNo: serialNo)); clientSocket.Send(buffer); return true; } } catch (Exception ex) { LogHelper.Error("发送设置判伤捻距系数数据命令时错误", ex); return false; } } /// /// 返回编码器方向 /// /// /// public EncoderDirectionDataModel ReceiveEncoderDirectionData(byte[] buffer) { (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer); var encoderDirection = new EncoderDirectionDataModel { Code = bytes[0], Type = bytes[1], Direction = (EncoderDirection)bytes[2] // 编码器方向,1=正向,2=反向 }; return encoderDirection; } /// /// 接收返回系统时钟数据 /// /// /// public ClockDataModel ReceiveClockData(byte[] buffer) { (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer); ClockDataModel clockData = new ClockDataModel { Code = bytes[0], Type = bytes[1], Time = byteTransform.TransInt32(bytes, 2) }; return clockData; } /// /// 主板复位应答 /// /// /// public ResetSystemDataModel ReceiveResetSystemData(byte[] buffer) { (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer); var resetSystemData = new ResetSystemDataModel { Code = bytes[0] }; return resetSystemData; } /// /// 设置当前实时位置应答 /// /// /// public SetAbsolutePositionDataModel ReceiveSetAbsolutePositionData(byte[] buffer) { (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer); var setAbsolutePositionData = new SetAbsolutePositionDataModel { Code = bytes[0] }; return setAbsolutePositionData; } /// /// 发送获取时钟数据命令 /// /// /// /// public bool SendGetClockData(string serialNo, Socket clientSocket) { try { if (clientSocket == null || !clientSocket.Connected) return false; using (var ms = new MemoryStream()) { ms.WriteByte(0x00); // 操作,0=获取时钟,1=设置时钟 WriteBytes(ms, 0);// 设置时间戳 byte[] buffer = CreateData(0x10, ms.ToArray(), serialNo); DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"获取设备时钟", serialNo: serialNo)); clientSocket.Send(buffer); return true; } } catch (Exception ex) { LogHelper.Error("发送获取时钟数据命令时错误", ex); return false; } } /// /// 发送设置时钟数据命令 /// /// 时间戳 /// 序列号 /// 网络数据流 /// public bool SendSetClockData(int timestamp, string serialNo, Socket clientSocket) { try { if (clientSocket == null || !clientSocket.Connected) return false; using (var ms = new MemoryStream()) { ms.WriteByte(0x01); // 操作,0=获取时钟,1=设置时钟 WriteBytes(ms, timestamp);// 设置时间戳 byte[] buffer = CreateData(0x10, ms.ToArray(), serialNo); DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"设置设备时钟", serialNo: serialNo)); clientSocket.Send(buffer); return true; } } catch (Exception ex) { LogHelper.Error("发送设置时钟数据命令时错误", ex); return false; } } /// /// 接收实时数据 /// /// /// public RealTimeDataModel ReceiveRealTimeData(byte[] buffer) { (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer); RealTimeDataModel realTimeData = new RealTimeDataModel { Status = (RunningStatus)bytes[0], Speed = byteTransform.TransSingle(bytes, 1), AbsolutePosition = byteTransform.TransSingle(bytes, 5), Position = byteTransform.TransSingle(bytes, 9) }; return realTimeData; } /// /// 接收检测结果 /// /// /// public DetectionDataModel ReceiveDetectionData(byte[] buffer) { var verifyData = GetVerifyDataAndCheckCaption(buffer); if (!verifyData.IsValid) { LogHelper.Error("接收检测结果时验证码校验失败"); return null; } var data = verifyData.Data; DetectionDataModel detectionData = new DetectionDataModel { StartTime = byteTransform.TransInt32(data, 0), EndTime = byteTransform.TransInt32(data, 4), StartPoint = byteTransform.TransSingle(data, 8), EndPoint = byteTransform.TransSingle(data, 12), DetectionLength = byteTransform.TransSingle(data, 16), DetectedSpeed = byteTransform.TransSingle(data, 20), DamageCount = byteTransform.TransInt16(data, 24), Damages = new List() }; for (int i = 0; i < detectionData.DamageCount; i++) { int offset = 26 + i * 10; // 每个损伤数据占8字节 if (offset + 10 > data.Length) break; // 防止越界 var damageData = new DamageModel { RopeNumber = data[offset], DamagePoint = byteTransform.TransSingle(data, offset + 1), DamageValue = byteTransform.TransSingle(data, offset + 5), DamageLevel = (DamageLevel)data[offset + 9] }; detectionData.Damages.Add(damageData); } return detectionData; } /// /// 接收损伤信息 /// /// /// public AlarmDataModel ReceiveAlarmData(byte[] buffer) { var verifyData = GetVerifyDataAndCheckCaption(buffer); if (!verifyData.IsValid) { LogHelper.Error("接收同步参数时验证码校验失败"); return null; } var data = verifyData.Data; AlarmDataModel alarmData = new AlarmDataModel { RopeNumber = data[1], DamagePosition = byteTransform.TransSingle(data, 2), DamageValue = byteTransform.TransSingle(data, 6), DamageLevel = (DamageLevel)data[10] }; return alarmData; } /// /// 接收故障信息 /// /// /// public FaultDataModel ReceiveFaultData(byte[] buffer) { var verifyData = GetVerifyDataAndCheckCaption(buffer); if (!verifyData.IsValid) { LogHelper.Error("接收设备故障时验证码校验失败"); return null; } FaultDataModel faultData = new FaultDataModel(); var data = verifyData.Data; faultData.FaultType = (FaultType)data[0]; return faultData; } public byte ReceiveStartOrStopDetectionResultData(byte[] buffer) { (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer); return bytes[0]; } public byte ReceiveUpgradedResultData(byte[] buffer) { (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer); return bytes[0]; } public byte ReceiveChangeSerialNoResultData(byte[] buffer) { (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer); return bytes[0]; } /// /// 回复心跳 /// /// private void RespondHeartbeat(byte[] buffer, string ipAddress, Socket clientSocket) { if (buffer[1] == 0x00) { byte[] response = new byte[] { 0xD0, 0x00 }; clientSocket.Send(response); // 直接使用Socket发送 } } private async Task ProcessSerialNoData(byte[] buffer, ClientState client) { byte code = ReceiveChangeSerialNoResultData(buffer); if (code == 0) { DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"修改设备序列号成功", serialNo: client.SerialNo)); } else { LogHelper.Error($"修改设备序列号结果失败,原因码:{code}"); } await Task.CompletedTask; } /// /// 接收同步参数 /// /// /// public (string SerialNo, ParameterModel Parameter) ReceiveSyncParameters(byte[] buffer) { ParameterModel parameterData = new ParameterModel(); var verifyData = GetVerifyDataAndCheckCaption(buffer); if (!verifyData.IsValid) { LogHelper.Error("接收同步参数时验证码校验失败"); return (null, null); } byte[] data = verifyData.Data; int index = 0; #region 主板软件版本号 short versionLength = data[index]; index += 1; if (data.Length - index < versionLength) return (null, null); parameterData.MainBoardSoftwareVersion = Encoding.ASCII.GetString(data.Skip(index).Take(versionLength).ToArray()); index += versionLength; #endregion #region 基础参数 parameterData.SensorCount = byteTransform.TransInt16(data, index); index += 2; parameterData.SamplingStep = byteTransform.TransSingle(data, index); index += 4; parameterData.FrequencyDivisionFactor = byteTransform.TransInt16(data, index); index += 2; parameterData.TimeDomainFrequency = byteTransform.TransInt16(data, index); index += 2; #endregion #region 判伤参数 parameterData.DamageThreshold = byteTransform.TransInt16(data, index); index += 2; parameterData.ScrapUpperLimit = byteTransform.TransInt16(data, index); index += 2; parameterData.FrontMagnetLength = byteTransform.TransInt16(data, index); index += 2; parameterData.BackMagnetLength = byteTransform.TransInt16(data, index); index += 2; parameterData.ValueCoefficient = byteTransform.TransSingle(data, index); index += 4; #endregion #region 零点位参数 parameterData.EffectiveStrokeLength = byteTransform.TransSingle(data, index); index += 4; parameterData.ZeroPositionCorrectionDuration = byteTransform.TransInt16(data, index); index += 2; parameterData.ZeroPositionCorrectionOffset = byteTransform.TransInt16(data, index); index += 2; #endregion #region 报警参数 parameterData.WarningValue = byteTransform.TransSingle(data, index); index += 4; parameterData.AlarmValue = byteTransform.TransSingle(data, index); index += 4; parameterData.SoundLightAlarmAutoResetMode = byteTransform.TransInt16(data, index); index += 2; #endregion #region 钢丝绳信息 parameterData.WireRopeType = byteTransform.TransInt16(data, index); index += 2; parameterData.WireRopeCount = byteTransform.TransInt16(data, index); index += 2; parameterData.WireRopeLength = byteTransform.TransSingle(data, index); index += 4; parameterData.WireRopeDiameter = byteTransform.TransSingle(data, index); index += 4; parameterData.WireRopeStrandCount = byteTransform.TransInt16(data, index); index += 2; parameterData.WireRopeStrandWireCount = byteTransform.TransInt16(data, index); index += 2; #endregion return (verifyData.SerialNo, parameterData); } /// /// 发送同步参数 /// /// /// public bool SendSyncParameters(ParameterModel parameters, string serialNo, Socket clientSocket) { try { if (clientSocket == null || !clientSocket.Connected) return false; using (var ms = new MemoryStream()) { // Basic parameters WriteBytes(ms, parameters.SensorCount); WriteBytes(ms, parameters.SamplingStep); WriteBytes(ms, parameters.FrequencyDivisionFactor); WriteBytes(ms, parameters.TimeDomainFrequency); // Damage judgment parameters WriteBytes(ms, parameters.DamageThreshold); WriteBytes(ms, parameters.ScrapUpperLimit); WriteBytes(ms, parameters.FrontMagnetLength); WriteBytes(ms, parameters.BackMagnetLength); WriteBytes(ms, parameters.ValueCoefficient); // Zero position parameters WriteBytes(ms, parameters.EffectiveStrokeLength); WriteBytes(ms, parameters.ZeroPositionCorrectionDuration); WriteBytes(ms, parameters.ZeroPositionCorrectionOffset); // Alarm parameters WriteBytes(ms, parameters.WarningValue); WriteBytes(ms, parameters.AlarmValue); WriteBytes(ms, (ushort)parameters.SoundLightAlarmAutoResetMode); // Wire rope info WriteBytes(ms, parameters.WireRopeType); WriteBytes(ms, parameters.WireRopeCount); WriteBytes(ms, parameters.WireRopeLength); WriteBytes(ms, parameters.WireRopeDiameter); WriteBytes(ms, parameters.WireRopeStrandCount); WriteBytes(ms, parameters.WireRopeStrandWireCount); var buffer = CreateData(0x02, ms.ToArray(), serialNo); DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"同步设备参数", serialNo: serialNo)); clientSocket.Send(buffer); return true; } } catch (Exception ex) { LogHelper.Error("发送同步参数时错误", ex); return false; } } /// /// 发送开始或停止检测命令 /// /// 检测模式 0=停止,1=启动空域检测,2=启动时域检测 /// 设备序列号 /// 数据流 public bool SendStartOrStopDetection(byte runningMode, string serialNo, Socket clientSocket) { try { if (clientSocket == null || !clientSocket.Connected) return false; using (var ms = new MemoryStream()) { ms.WriteByte(runningMode);// 0 = 停止,1 = 启动空域检测,2 = 启动时域检测 byte[] buffer = CreateData(0x06, ms.ToArray(), serialNo); DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"{(runningMode == 0 ? "停止" : "开始")}设备检测", serialNo: serialNo)); clientSocket.Send(buffer); return true; } } catch (Exception ex) { LogHelper.Error("发送开始或停止检测命令时错误", ex); return false; } } /// /// 发送修改设备序列号请求 /// /// 设备序列号 /// 数据流 /// public bool SendSerialNoRequest(string serialNo, Socket clientSocket) { try { if (clientSocket == null || !clientSocket.Connected || serialNo.IsNullOrEmpty()) return false; using (var ms = new MemoryStream()) { byte[] serialNoBytes = Encoding.UTF8.GetBytes(serialNo); ms.WriteByte((byte)serialNoBytes.Length); // 序列号长度 ms.Write(serialNoBytes, 0, serialNoBytes.Length); // 序列号 byte[] buffer = CreateData(0x16, ms.ToArray(), serialNo); DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"请求修改设备序列号", serialNo: null)); clientSocket.Send(buffer); return true; } } catch (Exception ex) { LogHelper.Error("发送设备序列号请求命令时错误", ex); return false; } } /// /// 发送程序更新请求 /// /// 设备序列号 /// 数据流 /// public bool SendUpgradeRequest(string serialNo, Socket clientSocket) { try { if (clientSocket == null || !clientSocket.Connected) return false; using (var ms = new MemoryStream()) { ms.WriteByte(1); byte[] buffer = CreateData(0x11, ms.ToArray(), serialNo); DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"发起程序更新请求", serialNo: serialNo)); clientSocket.Send(buffer); return true; } } catch (Exception ex) { LogHelper.Error("发送程序更新请求命令时错误", ex); return false; } } /// /// 发送开始或停止实时数据 /// /// 是否开启 /// 序列号 /// public void SendOpenOrClosedRealtimeData(bool isOpen, string serialNo, Socket clientSocket) { try { if (clientSocket == null || !clientSocket.Connected) return; using (var ms = new MemoryStream()) { ms.WriteByte((byte)(isOpen ? 1 : 0)); // 0=关闭,1=开启 byte[] buffer = CreateData(0x06, ms.ToArray(), serialNo); DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"{(isOpen ? "开启" : "停止")}设备实时数据", serialNo: serialNo)); clientSocket.Send(buffer); } } catch (Exception ex) { LogHelper.Error("发送开始或停止实时数据命令时错误", ex); } } private void SafeCloseClient(ClientState client) { try { ClientDisconnected?.Invoke(this, new ClientDisconnectedEventArgs(client.ClientSocket, client.IpAddress)); _connectedClients.TryRemove(client.IpAddress, out _); if (client.ClientSocket?.Connected == true) { client.ClientSocket?.Shutdown(SocketShutdown.Both); client.ClientSocket?.Close(); client.ClientSocket?.Dispose(); client.ClientSocket = null; } } catch (Exception ex) { Console.WriteLine($"关闭Socket时错误: {ex.Message}"); } } private void WriteBytes(MemoryStream ms, dynamic value) { var bytes = byteTransform.TransByte(value); ms.Write(bytes, 0, bytes.Length); } /// /// 发送检测结果确认 /// /// /// public bool SendDetectionConfirm(int startTime, int endTime, string serialNo, Socket clientSocket) { try { if (clientSocket == null || !clientSocket.Connected) return false; using (var ms = new MemoryStream()) { WriteBytes(ms, startTime); WriteBytes(ms, endTime); byte[] buffer = CreateData(0x09, ms.ToArray(), serialNo); DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"确认设备检测结果", serialNo: serialNo)); clientSocket.Send(buffer); return true; } } catch (Exception ex) { LogHelper.Error("发送检测结果确认时错误", ex); return false; } } /// /// 发送主板复位请求 /// /// /// /// public bool SendResetSystemData(string serialNo, Socket clientSocket) { try { if (clientSocket == null || !clientSocket.Connected) return false; using (var ms = new MemoryStream()) { byte[] buffer = CreateData(0x14, ms.ToArray(), serialNo); DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"发送主板复位请求", serialNo: serialNo)); clientSocket.Send(buffer); return true; } } catch (Exception ex) { LogHelper.Error("发送主板复位请求时错误", ex); return false; } } /// /// 发送设置当前实时位置 /// /// public bool SendRealTimeAbsolutePositionData(float absolutePosition, string serialNo, Socket clientSocket) { try { if (clientSocket == null || !clientSocket.Connected) return false; using (var ms = new MemoryStream()) { ms.WriteByte(1);// 1=设置当前实时位置 WriteBytes(ms, absolutePosition); byte[] buffer = CreateData(0x15, ms.ToArray(), serialNo); DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"发送设置当前实时位置请求", serialNo: serialNo)); clientSocket.Send(buffer); return true; } } catch (Exception ex) { LogHelper.Error("发送设置当前实时位置请求时错误", ex); return false; } } /// /// 获取数据并验证验证码 /// /// 数据 /// private VerifyDataModel GetVerifyDataAndCheckCaption(byte[] buffer) { VerifyDataModel verifyData = new VerifyDataModel() { Password = PASSWORD }; // 使用Span直接操作内存 Span span = buffer.AsSpan(); // 移除事件类型 span = span.Slice(1); // 读取序列号长度 if (span.IsEmpty) return verifyData; int serialNoLength = span[0]; // 读取序列号 if (span.Length - 1 < serialNoLength) return verifyData; verifyData.SerialNo = SoftBasic.GetAsciiStringRender(span.Slice(1, serialNoLength).ToArray()); span = span.Slice(1 + serialNoLength); // 读取随机码 if (span.Length < 4) return verifyData; verifyData.RandomCode = byteTransform.TransUInt32(span.ToArray(), 0); span = span.Slice(4); // 读取验证码长度 if (span.IsEmpty) return verifyData; int captchaLength = span[0]; // 验证验证码 if (span.Length - 1 < captchaLength) return verifyData; verifyData.Captcha = SoftBasic.AsciiBytesToBytes(span.Slice(1, captchaLength).ToArray()); // 截取剩余数据 verifyData.Data = span.Slice(captchaLength + 1).ToArray(); // 校验验证码 verifyData.IsValid = VerifyCaptcha(verifyData); return verifyData; } /// /// 验证码校验 /// /// private static bool VerifyCaptcha(VerifyDataModel verifyData) { byte[] computedHash; using (var md5 = MD5.Create()) { computedHash = md5.ComputeHash(Encoding.UTF8.GetBytes(verifyData.SerialNo + verifyData.Password + verifyData.RandomCode)); } var buffer = verifyData.Captcha; for (int i = 0; i < 16; i++) { if (buffer[i] != computedHash[i]) return false; } return true; } /// ///创建数据验证码 /// /// protected byte[] CreateData(byte eventType, byte[] data, string serialNo) { using (var md5 = MD5.Create()) { using (var ms = new MemoryStream()) { // 1. 预先计算所有字段的长度 uint randomCode = (uint)DateTimeOffset.UtcNow.ToUnixTimeSeconds(); byte[] randomCodeBytes = byteTransform.TransByte(randomCode); byte[] hash = md5.ComputeHash(Encoding.ASCII.GetBytes(serialNo + PASSWORD + randomCode)); byte[] captcha = SoftBasic.BytesToAsciiBytes(hash); // 2. 正确计算剩余长度(关键修正点) // 剩余长度 = 事件类型(1) + 序列号长度(1) + 序列号数据 + 随机码 + 验证码长度(1) + 验证码 + 用户数据 short remainingLength = (short)( 1 + // eventType randomCodeBytes.Length + // 随机码(固定4字节) 1 + captcha.Length + // 验证码(长度字节 + 数据) data.Length // 用户数据 ); // 3. 写入头部(0x30 + 剩余长度) ms.WriteByte(0x30); if (remainingLength <= 127) { ms.WriteByte((byte)remainingLength); // 单字节表示 } else { // 假设byteTransform.TransByte将short转为2字节大端序 byte[] remainingLengthBytes = byteTransform.TransByte(remainingLength); ms.Write(remainingLengthBytes, 0, remainingLengthBytes.Length); } // 4. 写入各字段(保持原逻辑) ms.WriteByte(eventType); ms.Write(randomCodeBytes, 0, randomCodeBytes.Length); ms.WriteByte((byte)captcha.Length); ms.Write(captcha, 0, captcha.Length); ms.Write(data, 0, data.Length); return ms.ToArray(); } } } public ushort[][] ParseSensorData(byte[] data, int sensorCount, int sampleCount) { // 检查数据长度是否匹配 int expectedLength = sensorCount * sampleCount; if (data.Length != expectedLength) { LogHelper.Error($"数据长度不匹配。预期 {expectedLength} 字节,实际 {data.Length} 字节。"); return null; } // 初始化结果列表,每个传感器的数据存储在一个单独的 ushort[] ushort[][] sensorDataList = new ushort[sampleCount][]; for (int i = 0; i < sampleCount; i++) { sensorDataList[i] = new ushort[sensorCount]; } // 解析数据 for (int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++) { for (int sensorIndex = 0; sensorIndex < sensorCount; sensorIndex++) { // 计算数据在字节数组中的位置 int dataIndex = (sampleIndex * sensorCount) + sensorIndex; // 将 byte 转换为 ushort(直接赋值,因为 byte 可以隐式转换为 ushort) sensorDataList[sampleIndex][sensorIndex] = data[dataIndex]; } } return sensorDataList; } /// /// 获取剩余长度 /// /// /// /// public static (int BytesConsumed, int Length) GetRemainingLength(byte[] bytes) { if (bytes == null || bytes.Length < 2) return (0, 0); int index = 1; // 跳过包类型字节 int multiplier = 1; int value = 0; byte encodedByte; int bytesConsumed = 0; do { if (index >= bytes.Length) return (0, 0); encodedByte = bytes[index]; value += (encodedByte & 0x7F) * multiplier; multiplier *= 128; index++; bytesConsumed++; if (multiplier > 128 * 128 * 128) // 防止溢出 return (0, 0); } while ((encodedByte & 0x80) != 0 && bytesConsumed < 4); // 最多4字节长度 return (bytesConsumed, value); } private static (string SerialNo, byte[] Bytes) GetSerialNoAndData(byte[] buffer) { // 使用Span直接操作内存 Span span = buffer.AsSpan(); // 移除事件类型 span = span.Slice(1); // 读取序列号长度 if (span.IsEmpty) return (null, null); int serialNoLength = span[0]; // 读取序列号 if (span.Length - 1 < serialNoLength) return (null, null); var serialNo = SoftBasic.GetAsciiStringRender(span.Slice(1, serialNoLength).ToArray()); buffer = span.Slice(1 + serialNoLength).ToArray(); return (serialNo, buffer); } public void Dispose() { try { _isRunning = false; Thread.Sleep(100); if (_listener != null) { if (_listener.Connected) { _listener.Shutdown(SocketShutdown.Both); } _listener.Close(); _listener.Dispose(); } } catch (SocketException ex) when (ex.SocketErrorCode == SocketError.NotConnected) { _listener?.Dispose(); } catch (Exception ex) { LogHelper.Error($"停止服务时发生异常: {ex.Message}", ex); } finally { _listener = null; } } } }