| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728 |
- 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)
- {
- LogHelper.Error($"Error accepting client: {ex.Message}", ex);
- }
- }
- 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)
- {
- var equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => c.IpAddress == client.IpAddress);
- if (equipmentData != null)
- {
- equipmentData.InUseSensor = faultData.WorkingSensors;
- }
- // 处理故障数据
- 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];
- faultData.FaultCode = byteTransform.TransInt32(data, 1);
- 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
- #region 限位校准位置
- parameterData.FirstCalibrationPositiont = byteTransform.TransSingle(data, index); index += 4;
- parameterData.SecondCalibrationPositiont = byteTransform.TransSingle(data, index); index += 4;
- #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);
- // Calibration Info
- WriteBytes(ms, parameters.FirstCalibrationPositiont);
- WriteBytes(ms, parameters.SecondCalibrationPositiont);
- 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(int switchIndex, float absolutePosition, string serialNo, Socket clientSocket)
- {
- try
- {
- if (clientSocket == null || !clientSocket.Connected)
- return false;
- using (var ms = new MemoryStream())
- {
- ms.WriteByte((byte)switchIndex);// 0无关联开关 1 关联开关1 2关联开关2
- 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;
- }
- }
- }
- }
|