| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715 |
- 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<ClientConnectedEventArgs> ClientConnected;
- public event EventHandler<ClientDisconnectedEventArgs> ClientDisconnected;
- public event EventHandler<LiveStreamReceivedEventArgs> LiveStreamReceived;
- public event EventHandler<AlarmDataReceivedEventArgs> AlarmDataReceived;
- public event EventHandler<FaultDataReceivedEventArgs> FaultDataReceived;
- public event EventHandler<DetectionDataReceivedEventArgs> DetectionDataReceived;
- public event EventHandler<RealTimeDataReceivedEventArgs> RealTimeDataReceived;
- public event EventHandler<DetectionRawDataReceivedEventArgs> DetectionRawDataReceived;
- public event EventHandler<ResetSystemDataReceivedEventArgs> ResetSystemDataReceived;
- public event EventHandler<SetAbsolutePositionDataReceivedEventArgs> SetAbsolutePositionDataReceived;
- public event EventHandler<DetectionRawDataResultReceivedEventArgs> DetectionRawDataResultReceived;
- public event EventHandler<DetectionStatusResultReceivedEventArgs> DetectionStatusResultReceived;
- public event EventHandler<UpgradedResultReceivedEventArgs> UpgradedRequestResultReceived;
- public event EventHandler<ClockResultReceivedEventArgs> ClockResultReceived;
- public event EventHandler<EncoderDirectionResultReceivedEventArgs> EncoderDirectionResultReceived;
- public event EventHandler<HeartbeatReceviedEventArgs> HeartbeatReceived;
- public event EventHandler<DebugMessageReceivedEventArgs> 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<string, ClientState> _connectedClients;
- public TcpServerFrame(string ipAddress, int port)
- {
- _ipAddress = ipAddress;
- _port = port;
- byteTransform = new ByteTransform(DataFormat.DCBA);
- _connectedClients = new ConcurrentDictionary<string, ClientState>();
- }
- 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<bool> 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;
- }
- /// <summary>
- /// 根据事件类型处理数据
- /// </summary>
- /// <param name="eventType"></param>
- /// <param name="payload"></param>
- /// <param name="client"></param>
- /// <returns></returns>
- 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;
- }
- }
- /// <summary>
- /// 设置实时位置
- /// </summary>
- /// <param name="buffer"></param>
- /// <param name="client"></param>
- /// <returns></returns>
- 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;
- }
- /// <summary>
- /// 主板复位
- /// </summary>
- /// <param name="buffer"></param>
- /// <param name="client"></param>
- /// <returns></returns>
- 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;
- }
- /// <summary>
- /// 发送获取编码器方向请求
- /// </summary>
- /// <param name="serialNo"></param>
- /// <param name="client"></param>
- /// <returns></returns>
- 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;
- }
- }
- /// <summary>
- /// 发送设置编码器方向数据命令
- /// </summary>
- /// <param name="direction"></param>
- /// <param name="serialNo"></param>
- /// <param name="stream"></param>
- /// <returns></returns>
- 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;
- }
- }
- /// <summary>
- /// 发送检测结果原始数据请求
- /// </summary>
- /// <param name="serialNo"></param>
- /// <param name="clientSocket"></param>
- /// <returns></returns>
- 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;
- }
- }
- /// <summary>
- /// 接收获取原始数据结果
- /// </summary>
- /// <param name="buffer"></param>
- /// <returns></returns>
- 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;
- }
- /// <summary>
- /// 获取原始数据包
- /// </summary>
- /// <param name="buffer"></param>
- /// <returns></returns>
- 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;
- }
- /// <summary>
- /// 发送开启实时流数据命令
- /// </summary>
- /// <param name="isOpen">是否开启</param>
- /// <param name="serialNo">设备序列号</param>
- /// <param name="client"></param>
- /// <returns></returns>
- 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;
- }
- }
- /// <summary>
- /// 发送获取判伤捻距系数数据命令
- /// </summary>
- /// <param name="serialNo"></param>
- /// <param name="client"></param>
- /// <returns></returns>
- 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;
- }
- }
- /// <summary>
- /// 设置判伤捻距系数
- /// </summary>
- /// <param name="twistFactor"></param>
- /// <param name="serialNo"></param>
- /// <param name="stream"></param>
- /// <returns></returns>
- 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;
- }
- }
- /// <summary>
- /// 返回编码器方向
- /// </summary>
- /// <param name="buffer"></param>
- /// <returns></returns>
- 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;
- }
- /// <summary>
- /// 接收返回系统时钟数据
- /// </summary>
- /// <param name="buffer"></param>
- /// <returns></returns>
- 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;
- }
- /// <summary>
- /// 主板复位应答
- /// </summary>
- /// <param name="buffer"></param>
- /// <returns></returns>
- public ResetSystemDataModel ReceiveResetSystemData(byte[] buffer)
- {
- (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
- var resetSystemData = new ResetSystemDataModel
- {
- Code = bytes[0]
- };
- return resetSystemData;
- }
- /// <summary>
- /// 设置当前实时位置应答
- /// </summary>
- /// <param name="buffer"></param>
- /// <returns></returns>
- public SetAbsolutePositionDataModel ReceiveSetAbsolutePositionData(byte[] buffer)
- {
- (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
- var setAbsolutePositionData = new SetAbsolutePositionDataModel
- {
- Code = bytes[0]
- };
- return setAbsolutePositionData;
- }
- /// <summary>
- /// 发送获取时钟数据命令
- /// </summary>
- /// <param name="serialNo"></param>
- /// <param name="stream"></param>
- /// <returns></returns>
- 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;
- }
- }
- /// <summary>
- /// 发送设置时钟数据命令
- /// </summary>
- /// <param name="timestamp">时间戳</param>
- /// <param name="serialNo">序列号</param>
- /// <param name="stream">网络数据流</param>
- /// <returns></returns>
- 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;
- }
- }
- /// <summary>
- /// 接收实时数据
- /// </summary>
- /// <param name="buffer"></param>
- /// <returns></returns>
- 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;
- }
- /// <summary>
- /// 接收检测结果
- /// </summary>
- /// <param name="buffer"></param>
- /// <returns></returns>
- 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<DamageModel>()
- };
- 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;
- }
- /// <summary>
- /// 接收损伤信息
- /// </summary>
- /// <param name="buffer"></param>
- /// <returns></returns>
- 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;
- }
- /// <summary>
- /// 接收故障信息
- /// </summary>
- /// <param name="buffer"></param>
- /// <returns></returns>
- 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];
- }
- /// <summary>
- /// 回复心跳
- /// </summary>
- /// <returns></returns>
- 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;
- }
- /// <summary>
- /// 接收同步参数
- /// </summary>
- /// <param name="buffer"></param>
- /// <returns></returns>
- 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);
- }
- /// <summary>
- /// 发送同步参数
- /// </summary>
- /// <param name="parameterData"></param>
- /// <returns></returns>
- 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;
- }
- }
- /// <summary>
- /// 发送开始或停止检测命令
- /// </summary>
- /// <param name="mode">检测模式 0=停止,1=启动空域检测,2=启动时域检测</param>
- /// <param name="serialNo">设备序列号</param>
- /// <param name="clientSocket">数据流</param>
- 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;
- }
- }
- /// <summary>
- /// 发送修改设备序列号请求
- /// </summary>
- /// <param name="serialNo">设备序列号</param>
- /// <param name="clientSocket">数据流</param>
- /// <returns></returns>
- 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;
- }
- }
- /// <summary>
- /// 发送程序更新请求
- /// </summary>
- /// <param name="serialNo">设备序列号</param>
- /// <param name="clientSocket">数据流</param>
- /// <returns></returns>
- 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;
- }
- }
- /// <summary>
- /// 发送开始或停止实时数据
- /// </summary>
- /// <param name="isOpen">是否开启</param>
- /// <param name="serialNo">序列号</param>
- /// <param name="clientSocket"></param>
- 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);
- }
- /// <summary>
- /// 发送检测结果确认
- /// </summary>
- /// <param name="parameterData"></param>
- /// <returns></returns>
- 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;
- }
- }
- /// <summary>
- /// 发送主板复位请求
- /// </summary>
- /// <param name="serialNo"></param>
- /// <param name="clientSocket"></param>
- /// <returns></returns>
- 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;
- }
- }
- /// <summary>
- /// 发送设置当前实时位置
- /// </summary>
- /// <returns></returns>
- 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;
- }
- }
- /// <summary>
- /// 获取数据并验证验证码
- /// </summary>
- /// <param name="buffer">数据</param>
- /// <returns></returns>
- private VerifyDataModel GetVerifyDataAndCheckCaption(byte[] buffer)
- {
- VerifyDataModel verifyData = new VerifyDataModel() { Password = PASSWORD };
- // 使用Span直接操作内存
- Span<byte> 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;
- }
- /// <summary>
- /// 验证码校验
- /// </summary>
- /// <returns></returns>
- 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;
- }
- ///<summary>
- ///创建数据验证码
- ///</summary>
- /// <returns></returns>
- 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;
- }
- /// <summary>
- /// 获取剩余长度
- /// </summary>
- /// <param name="bytes"></param>
- /// <param name="startIndex"></param>
- /// <returns></returns>
- 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<byte> 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;
- }
- }
- }
- }
|