| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714 |
- 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="isStart">是否开始</param>
- /// <param name="serialNo">设备序列号</param>
- /// <param name="clientSocket">数据流</param>
- public bool SendStartOrStopDetection(bool isStart, string serialNo, Socket clientSocket)
- {
- try
- {
- if (clientSocket == null || !clientSocket.Connected)
- return false;
- using (var ms = new MemoryStream())
- {
- ms.WriteByte((byte)(isStart ? 1 : 0)); // 0=停止检测,1=开始检测
- byte[] buffer = CreateData(0x06, ms.ToArray(), serialNo);
- DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"{(isStart ? "开始" : "停止")}设备检测", 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;
- }
- }
- }
- }
|