TcpServerFrame.cs 79 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920
  1. using SWRIS.Enums;
  2. using SWRIS.Events;
  3. using SWRIS.Extensions;
  4. using SWRIS.Models;
  5. using SWRIS.Models.Data;
  6. using System;
  7. using System.Collections.Concurrent;
  8. using System.Collections.Generic;
  9. using System.IO;
  10. using System.Linq;
  11. using System.Net;
  12. using System.Net.Sockets;
  13. using System.Reflection;
  14. using System.Security.Cryptography;
  15. using System.Text;
  16. using System.Threading;
  17. using System.Threading.Tasks;
  18. namespace SWRIS.Core
  19. {
  20. public class TcpServerFrame : IDisposable
  21. {
  22. // 定义事件
  23. public event EventHandler<ClientConnectedEventArgs> ClientConnected;
  24. public event EventHandler<ClientDisconnectedEventArgs> ClientDisconnected;
  25. public event EventHandler<LiveStreamReceivedEventArgs> LiveStreamReceived;
  26. public event EventHandler<AlarmDataReceivedEventArgs> AlarmDataReceived;
  27. public event EventHandler<FaultDataReceivedEventArgs> FaultDataReceived;
  28. public event EventHandler<DetectionDataReceivedEventArgs> DetectionDataReceived;
  29. public event EventHandler<RealTimeDataReceivedEventArgs> RealTimeDataReceived;
  30. public event EventHandler<DetectionRawDataReceivedEventArgs> DetectionRawDataReceived;
  31. public event EventHandler<ResetSystemDataReceivedEventArgs> ResetSystemDataReceived;
  32. public event EventHandler<SetAbsolutePositionDataReceivedEventArgs> SetAbsolutePositionDataReceived;
  33. public event EventHandler<DetectionRawDataResultReceivedEventArgs> DetectionRawDataResultReceived;
  34. public event EventHandler<DetectionStatusResultReceivedEventArgs> DetectionStatusResultReceived;
  35. public event EventHandler<UpgradedResultReceivedEventArgs> UpgradedRequestResultReceived;
  36. public event EventHandler<ClockResultReceivedEventArgs> ClockResultReceived;
  37. public event EventHandler<EncoderDirectionResultReceivedEventArgs> EncoderDirectionResultReceived;
  38. public event EventHandler<HeartbeatReceviedEventArgs> HeartbeatReceived;
  39. /// <summary>
  40. /// 数据激活状态变化事件(数据在正常收发/数据静默切换时触发)
  41. /// </summary>
  42. public event EventHandler<DataActiveStateChangedEventArgs> DataActiveStateChanged;
  43. public event EventHandler<DebugMessageReceivedEventArgs> DebugMessageReceived;
  44. private Socket _listener;
  45. private bool _isRunning;
  46. private readonly string _ipAddress;
  47. private readonly int _port;
  48. private readonly ByteTransform _byteTransform;
  49. private const string PASSWORD = "WNDTM4";
  50. /// <summary>
  51. /// 心跳检测周期(秒)
  52. /// </summary>
  53. private const int HeartbeatCheckIntervalSeconds = 5;
  54. /// <summary>
  55. /// 心跳超时时间(秒):超过该时间未收到任何数据则判定连接失效
  56. /// </summary>
  57. private const int HeartbeatTimeoutSeconds = 15;
  58. /// <summary>
  59. /// 数据静默超时时间(秒):超过该时间未收到有效数据则数据激活状态置为失活
  60. /// </summary>
  61. private const int DataTimeoutSeconds = 15;
  62. private static ConcurrentDictionary<string, ClientState> _connectedClients;
  63. private CancellationTokenSource ctsToken = new CancellationTokenSource();
  64. public TcpServerFrame(string ipAddress, int port)
  65. {
  66. _ipAddress = ipAddress;
  67. _port = port;
  68. _byteTransform = new ByteTransform(DataFormat.DCBA);
  69. _connectedClients = new ConcurrentDictionary<string, ClientState>();
  70. }
  71. public void Start()
  72. {
  73. _isRunning = true;
  74. _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  75. try
  76. {
  77. // 使用指定的IP地址和端口
  78. IPAddress ipAddress = IPAddress.Parse(_ipAddress);
  79. _listener.Bind(new IPEndPoint(ipAddress, _port));
  80. _listener.Listen(10);
  81. // 启动心跳检测线程
  82. StartHeartbeatCheck();
  83. // 开始接受客户端连接(异步)
  84. _listener.BeginAccept(OnClientConnected, null);
  85. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"服务已在 {_ipAddress}:{_port} 上启动"));
  86. }
  87. catch (SocketException ex)
  88. {
  89. LogHelper.Error($"启动服务时发生错误: {ex.Message}");
  90. if (ex.SocketErrorCode == SocketError.AddressAlreadyInUse)
  91. {
  92. LogHelper.Error("端口已被占用,请更换端口或关闭占用该端口的程序", ex);
  93. }
  94. else if (ex.SocketErrorCode == SocketError.AddressNotAvailable)
  95. {
  96. LogHelper.Error($"IP地址 {_ipAddress} 不可用,请检查网络配置", ex);
  97. }
  98. }
  99. catch (Exception ex)
  100. {
  101. LogHelper.Error($"TCP服务启动时发生未知错误: {ex.Message}", ex);
  102. }
  103. }
  104. public void Stop()
  105. {
  106. _isRunning = false;
  107. // 取消心跳检测任务
  108. ctsToken?.Cancel();
  109. ctsToken?.Dispose();
  110. ctsToken = null;
  111. // 关闭所有客户端连接
  112. foreach (var client in _connectedClients.Values)
  113. {
  114. SafeCloseClient(client);
  115. }
  116. _connectedClients.Clear();
  117. // 关闭监听器
  118. if (_listener != null)
  119. {
  120. try
  121. {
  122. _listener.Close();
  123. }
  124. catch (SocketException) { }
  125. catch (ObjectDisposedException) { }
  126. _listener = null;
  127. }
  128. }
  129. private void OnClientConnected(IAsyncResult ar)
  130. {
  131. if (!_isRunning)
  132. return;
  133. try
  134. {
  135. Socket clientSocket = _listener.EndAccept(ar);
  136. string ipAddress = (clientSocket.RemoteEndPoint as IPEndPoint)?.Address?.ToString();
  137. var equipmentData = App.Config.Equipments.FirstOrDefault(c => c.IpAddress == ipAddress);
  138. if (equipmentData != null)
  139. {
  140. ClientState client = new ClientState(clientSocket, ipAddress, equipmentData.SerialNo);
  141. // 添加到连接列表
  142. _connectedClients.TryAdd(client.IpAddress, client);
  143. // 开始异步接收数据
  144. clientSocket.BeginReceive(client.Buffer, 0, client.Buffer.Length, SocketFlags.None, OnDataReceived, client);
  145. // 触发客户端连接事件
  146. ClientConnected?.Invoke(this, new ClientConnectedEventArgs(clientSocket, ipAddress));
  147. }
  148. // 继续接受新连接
  149. _listener.BeginAccept(OnClientConnected, null);
  150. }
  151. catch (Exception ex)
  152. {
  153. LogHelper.Error($"Error accepting client: {ex.Message}", ex);
  154. }
  155. }
  156. private void StartHeartbeatCheck()
  157. {
  158. ThreadPool.QueueUserWorkItem(async state =>
  159. {
  160. var token = (CancellationTokenSource)state;
  161. while (_isRunning && !token.IsCancellationRequested)
  162. {
  163. try
  164. {
  165. await Task.Delay(TimeSpan.FromSeconds(HeartbeatCheckIntervalSeconds), token.Token);
  166. var now = DateTime.UtcNow;
  167. foreach (var client in _connectedClients.ToArray())
  168. {
  169. var clientState = client.Value;
  170. // 数据在正常收发时,链路是活跃的:即使心跳包缺失也应保持连接
  171. // 避免设备持续上报实时数据却被判为离线
  172. if ((now - clientState.LastDataReceivedTime).TotalSeconds <= DataTimeoutSeconds)
  173. {
  174. // 数据激活即刷新连接活跃时间,心跳缺失不再触发误判
  175. clientState.LastActiveTime = now;
  176. SetDataActiveState(clientState, true);
  177. continue;
  178. }
  179. // 数据已静默,置为失活后再按心跳超时判定
  180. SetDataActiveState(clientState, false);
  181. if ((now - clientState.LastActiveTime).TotalSeconds > HeartbeatTimeoutSeconds)
  182. {
  183. SafeCloseClient(clientState);
  184. DebugMessageReceived?.Invoke(this,
  185. new DebugMessageReceivedEventArgs($"心跳超时,强制断开", ipAddress: clientState.IpAddress));
  186. }
  187. }
  188. }
  189. catch (TaskCanceledException)
  190. {
  191. // 正常取消,退出循环
  192. break;
  193. }
  194. catch (Exception ex)
  195. {
  196. LogHelper.Error($"心跳检测异常: {ex.Message}", ex);
  197. }
  198. }
  199. }, ctsToken);
  200. }
  201. [Obfuscation(Feature = "virtualization", Exclude = false)]
  202. private async void OnDataReceived(IAsyncResult ar)
  203. {
  204. var state = (ClientState)ar.AsyncState;
  205. if (state == null || state.ClientSocket == null || !state.ClientSocket.Connected)
  206. {
  207. return;
  208. }
  209. try
  210. {
  211. int bytesRead = state.ClientSocket.EndReceive(ar);
  212. if (bytesRead > 0)
  213. {
  214. // 将接收到的数据添加到缓冲区
  215. state.ReceiveBuffer.Write(state.Buffer, 0, bytesRead);
  216. // 处理缓冲区中的所有数据包
  217. while (state.ReceiveBuffer.Length > 0)
  218. {
  219. byte packetType = state.ReceiveBuffer.PeekByte();
  220. if (packetType == 0xC0) // 心跳包
  221. {
  222. ProcessHeartbeatPacket(state);
  223. }
  224. else if (packetType == 0x30) // 数据包
  225. {
  226. bool processed = await ProcessDataPacket(state);
  227. if (!processed) break; // 数据包不完整,等待更多数据
  228. }
  229. else
  230. {
  231. // 未知包类型,跳过1字节继续检查
  232. DebugMessageReceived?.Invoke(this,
  233. new DebugMessageReceivedEventArgs($"未知包类型: 0x{packetType:X2}", state.IpAddress));
  234. state.ReceiveBuffer.Remove(1);
  235. }
  236. }
  237. // 继续接收数据
  238. if (state.ClientSocket != null)
  239. {
  240. Array.Clear(state.Buffer, 0, state.Buffer.Length);
  241. state.ClientSocket.BeginReceive(state.Buffer, 0, state.Buffer.Length,
  242. SocketFlags.None, OnDataReceived, state);
  243. }
  244. }
  245. else
  246. {
  247. // 客户端断开连接
  248. DebugMessageReceived?.Invoke(this,
  249. new DebugMessageReceivedEventArgs((bytesRead == 0 ? "设备主动断开连接" : "连接异常或错误") + $"({bytesRead})", state.IpAddress));
  250. SafeCloseClient(state);
  251. }
  252. }
  253. catch (SocketException sex)
  254. {
  255. HandleSocketException(sex, state);
  256. }
  257. catch (Exception ex)
  258. {
  259. var message = $"接收数据时错误: {ex.Message}";
  260. LogHelper.Error(message, ex);
  261. SafeCloseClient(state);
  262. }
  263. }
  264. private void HandleSocketException(SocketException sex, ClientState client)
  265. {
  266. string message;
  267. switch (sex.SocketErrorCode)
  268. {
  269. case SocketError.ConnectionReset:
  270. message = "设备强制断开连接 (Connection Reset)";
  271. break;
  272. case SocketError.OperationAborted:
  273. message = "操作被中止";
  274. break;
  275. case SocketError.ConnectionAborted:
  276. message = "连接被中止";
  277. break;
  278. case SocketError.TimedOut:
  279. message = "连接超时";
  280. break;
  281. case SocketError.Shutdown:
  282. message = "连接已关闭";
  283. break;
  284. case SocketError.NetworkReset:
  285. message = "网络连接被重置";
  286. break;
  287. case SocketError.HostUnreachable:
  288. message = "主机不可达";
  289. break;
  290. default:
  291. message = $"Socket错误: {sex.SocketErrorCode} - {sex.Message}";
  292. break;
  293. }
  294. DebugMessageReceived?.Invoke(this,
  295. new DebugMessageReceivedEventArgs(message, client.IpAddress));
  296. LogHelper.Error(message, sex);
  297. SafeCloseClient(client);
  298. }
  299. private void ProcessHeartbeatPacket(ClientState client)
  300. {
  301. // 心跳包固定长度为2字节: 0xC0 + 0x00
  302. if (client.ReceiveBuffer.Length < 2)
  303. return; // 等待更多数据
  304. byte[] heartBeatData = new byte[2];
  305. client.ReceiveBuffer.Read(heartBeatData, 0, 2);
  306. // 心跳也是有效数据,统一走数据激活标记
  307. MarkDataActive(client);
  308. RespondHeartbeat(heartBeatData, client.IpAddress, client.ClientSocket);
  309. HeartbeatReceived?.Invoke(this, new HeartbeatReceviedEventArgs(client.IpAddress));
  310. }
  311. private async Task<bool> ProcessDataPacket(ClientState client)
  312. {
  313. // 检查是否有足够的数据读取长度信息
  314. if (client.ReceiveBuffer.Length < 5) // 至少需要包类型 + 最小长度信息
  315. return false;
  316. // 窥探前10个字节来解析长度
  317. byte[] peekData = new byte[Math.Min(client.ReceiveBuffer.Length, 10)];
  318. int peeked = client.ReceiveBuffer.Peek(peekData, 0, peekData.Length);
  319. // 解析剩余长度
  320. (int byteLength, int remainingLength) = GetRemainingLength(peekData);
  321. if (byteLength == 0 || remainingLength == 0)
  322. {
  323. // 长度解析失败,可能是数据损坏,跳过1字节
  324. client.ReceiveBuffer.Remove(1);
  325. return true;
  326. }
  327. // 计算完整包长度
  328. int totalPacketLength = 1 + byteLength + remainingLength;
  329. // 检查是否收到完整包
  330. if (client.ReceiveBuffer.Length < totalPacketLength)
  331. return false;
  332. // 读取完整数据包
  333. byte[] packetData = new byte[totalPacketLength];
  334. client.ReceiveBuffer.Read(packetData, 0, totalPacketLength);
  335. // 提取事件类型和有效载荷
  336. int payloadStart = 1 + byteLength;
  337. if (payloadStart >= packetData.Length)
  338. {
  339. DebugMessageReceived?.Invoke(this,
  340. new DebugMessageReceivedEventArgs($"数据异常", client.IpAddress));
  341. return true;
  342. }
  343. byte eventType = packetData[payloadStart];
  344. byte[] payload = new byte[remainingLength];
  345. Buffer.BlockCopy(packetData, payloadStart, payload, 0, remainingLength);
  346. // 收到完整有效的业务数据包即标记数据激活,
  347. // 使设备在持续上报实时数据时不会因心跳缺失被误判离线
  348. MarkDataActive(client);
  349. // 处理数据包
  350. await ProcessEventByType(eventType, payload, client);
  351. return true;
  352. }
  353. /// <summary>
  354. /// 根据事件类型处理数据
  355. /// </summary>
  356. /// <param name="eventType"></param>
  357. /// <param name="payload"></param>
  358. /// <param name="client"></param>
  359. /// <returns></returns>
  360. [Obfuscation(Feature = "virtualization", Exclude = false)]
  361. private async Task ProcessEventByType(byte eventType, byte[] payload, ClientState client)
  362. {
  363. switch (eventType)
  364. {
  365. case 0x01:
  366. await ProcessSyncParameters(payload, client);
  367. break;
  368. case 0x06:
  369. await ProcessDetectionStatus(payload, client);
  370. break;
  371. case 0x07:
  372. await ProcessFaultData(payload, client);
  373. break;
  374. case 0x08:
  375. await ProcessAlarmData(payload, client);
  376. break;
  377. case 0x09:
  378. await ProcessDetectionData(payload, client);
  379. break;
  380. case 0x10:
  381. await ProcessClockData(payload, client);
  382. break;
  383. case 0x11:
  384. await ProcessUpgradedData(payload, client);
  385. break;
  386. case 0x12:
  387. await ProcessEncoderDirectionData(payload, client);
  388. break;
  389. case 0x13:
  390. await ProcessTwistFactorData(payload, client);
  391. break;
  392. case 0x0A:
  393. await ProcessOpenOrClosedRealtimeData(payload, client);
  394. break;
  395. case 0x0B:
  396. await ProcessRealTimeData(payload, client);
  397. break;
  398. case 0x0D:
  399. await ProcessLiveStreamData(payload, client);
  400. break;
  401. case 0x0C:
  402. await ProcessTurnLiveStreamData(payload, client);
  403. break;
  404. case 0x0E:
  405. await ProcessDetectionRawResultData(payload, client);
  406. break;
  407. case 0x0F:
  408. await ProcessDetectionRawData(payload, client);
  409. break;
  410. case 0x14:
  411. await ProcessSystemResetData(payload, client);
  412. break;
  413. case 0x15:
  414. await ProcessSetAbsolutePositionData(payload, client);
  415. break;
  416. case 0x16:
  417. await ProcessSerialNoData(payload, client);
  418. break;
  419. }
  420. }
  421. /// <summary>
  422. /// 设置实时位置
  423. /// </summary>
  424. /// <param name="buffer"></param>
  425. /// <param name="client"></param>
  426. /// <returns></returns>
  427. private async Task ProcessSetAbsolutePositionData(byte[] buffer, ClientState client)
  428. {
  429. var resetSystemData = ReceiveSetAbsolutePositionData(buffer);
  430. if (resetSystemData != null)
  431. {
  432. // 设置当前实时位置应答
  433. SetAbsolutePositionDataReceived?.Invoke(this,
  434. new SetAbsolutePositionDataReceivedEventArgs(client.IpAddress, resetSystemData));
  435. }
  436. await Task.CompletedTask;
  437. }
  438. /// <summary>
  439. /// 主板复位
  440. /// </summary>
  441. /// <param name="buffer"></param>
  442. /// <param name="client"></param>
  443. /// <returns></returns>
  444. private async Task ProcessSystemResetData(byte[] buffer, ClientState client)
  445. {
  446. var resetSystemData = ReceiveResetSystemData(buffer);
  447. if (resetSystemData != null)
  448. {
  449. // 主板复位结果
  450. ResetSystemDataReceived?.Invoke(this,
  451. new ResetSystemDataReceivedEventArgs(client.IpAddress, resetSystemData));
  452. }
  453. await Task.CompletedTask;
  454. }
  455. private async Task ProcessDetectionRawData(byte[] buffer, ClientState client)
  456. {
  457. await Task.Run(() =>
  458. {
  459. var detectionRawData = ReceiveDetectionRawData(buffer);
  460. if (detectionRawData != null)
  461. {
  462. // 处理检测原始数据
  463. DetectionRawDataReceived?.Invoke(this,
  464. new DetectionRawDataReceivedEventArgs(client.IpAddress, detectionRawData));
  465. }
  466. });
  467. await Task.CompletedTask;
  468. }
  469. private async Task ProcessDetectionRawResultData(byte[] buffer, ClientState client)
  470. {
  471. await Task.Run(() =>
  472. {
  473. var detectionRawResultData = ReceiveDetectionRawResultData(buffer);
  474. if (detectionRawResultData != null)
  475. {
  476. DetectionRawDataResultReceived?.Invoke(this,
  477. new DetectionRawDataResultReceivedEventArgs(client.IpAddress, detectionRawResultData));
  478. }
  479. });
  480. await Task.CompletedTask;
  481. }
  482. private async Task ProcessTurnLiveStreamData(byte[] buffer, ClientState client)
  483. {
  484. var liveStreamStatus = ReceiveTurnLiveStreamData(buffer);
  485. if (liveStreamStatus > 0)
  486. {
  487. // 开启/关闭结果,0=成功,>0=失败-原因码
  488. LogHelper.Error($"开启/关闭实时流数据失败,原因码:{liveStreamStatus}");
  489. }
  490. await Task.CompletedTask;
  491. }
  492. private async Task ProcessLiveStreamData(byte[] buffer, ClientState client)
  493. {
  494. await Task.Run(() =>
  495. {
  496. var liveStreamData = ReceiveLiveStreamDataModel(buffer);
  497. if (liveStreamData != null && liveStreamData.Data.Any())
  498. {
  499. // 触发事件
  500. LiveStreamReceived?.Invoke(this,
  501. new LiveStreamReceivedEventArgs(client.IpAddress, liveStreamData));
  502. }
  503. });
  504. await Task.CompletedTask;
  505. }
  506. private async Task ProcessRealTimeData(byte[] buffer, ClientState client)
  507. {
  508. await Task.Run(() =>
  509. {
  510. var realTimeData = ReceiveRealTimeData(buffer);
  511. if (realTimeData != null)
  512. {
  513. // 触发实时数据接收事件
  514. RealTimeDataReceived?.Invoke(this,
  515. new RealTimeDataReceivedEventArgs(client.IpAddress, realTimeData));
  516. }
  517. });
  518. await Task.CompletedTask;
  519. }
  520. private async Task ProcessOpenOrClosedRealtimeData(byte[] buffer, ClientState client)
  521. {
  522. var openOrClosed = ReceiveOpenOrClosedRealtimeData(buffer);
  523. if (openOrClosed > 0)
  524. {
  525. LogHelper.Error("开启或关闭实时数据失败,原因码:" + openOrClosed);
  526. }
  527. await Task.CompletedTask;
  528. }
  529. private async Task ProcessTwistFactorData(byte[] buffer, ClientState client)
  530. {
  531. var twistFactorData = ReceiveTwistFactorData(buffer);
  532. if (twistFactorData != null)
  533. {
  534. var equipmentData = App.Config.Equipments.FirstOrDefault(c => c.IpAddress == client.IpAddress);
  535. if (equipmentData != null && equipmentData.Parameter != null)
  536. {
  537. // 处理判伤捻距系数数据
  538. equipmentData.Parameter.TwistFactor = twistFactorData.TwistFactor;
  539. }
  540. }
  541. await Task.CompletedTask;
  542. }
  543. private async Task ProcessEncoderDirectionData(byte[] buffer, ClientState client)
  544. {
  545. var encoderDirection = ReceiveEncoderDirectionData(buffer);
  546. if (encoderDirection != null)
  547. {
  548. var equipmentData = App.Config.Equipments.FirstOrDefault(c => c.IpAddress == client.IpAddress);
  549. if (equipmentData != null && equipmentData.Parameter != null)
  550. {
  551. // 处理编码器方向数据
  552. equipmentData.Parameter.EncoderDirection = encoderDirection.Direction;
  553. // 编码器方向结果返回事件
  554. EncoderDirectionResultReceived?.Invoke(this,
  555. new EncoderDirectionResultReceivedEventArgs(client.IpAddress, encoderDirection.Direction));
  556. }
  557. }
  558. await Task.CompletedTask;
  559. }
  560. private async Task ProcessClockData(byte[] buffer, ClientState client)
  561. {
  562. var clockData = ReceiveClockData(buffer);
  563. if (clockData != null)
  564. {
  565. ClockResultReceived?.Invoke(this,
  566. new ClockResultReceivedEventArgs(client.IpAddress, clockData.Time));
  567. }
  568. await Task.CompletedTask;
  569. }
  570. private async Task ProcessDetectionData(byte[] buffer, ClientState client)
  571. {
  572. var detectionData = ReceiveDetectionData(buffer);
  573. if (detectionData != null)
  574. {
  575. // 回复检测结果确认
  576. if (SendDetectionConfirm(detectionData.StartTime, detectionData.EndTime, client.SerialNo, client.ClientSocket))
  577. {
  578. if (detectionData.DamageCount <= 0)
  579. {
  580. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"检测结果未发现损伤,本次结果不记录",
  581. ipAddress: client.IpAddress,
  582. serialNo: client.SerialNo));
  583. }
  584. else
  585. {
  586. // 发送获取原始数据请求
  587. SendGetDetectionRawData(client.SerialNo, client.ClientSocket);
  588. // 处理检测数据
  589. DetectionDataReceived?.Invoke(this,
  590. new DetectionDataReceivedEventArgs(client.IpAddress, detectionData));
  591. }
  592. }
  593. }
  594. await Task.CompletedTask;
  595. }
  596. private async Task ProcessFaultData(byte[] buffer, ClientState client)
  597. {
  598. var faultData = ReceiveFaultData(buffer);
  599. if (faultData != null)
  600. {
  601. var equipmentData = App.DataCenter.Equipments.FirstOrDefault(c => c.IpAddress == client.IpAddress);
  602. if (equipmentData != null)
  603. {
  604. equipmentData.InUseSensor = faultData.WorkingSensors;
  605. }
  606. // 处理故障数据
  607. FaultDataReceived?.Invoke(this, new FaultDataReceivedEventArgs(client.IpAddress, faultData));
  608. }
  609. await Task.CompletedTask;
  610. }
  611. private async Task ProcessAlarmData(byte[] buffer, ClientState client)
  612. {
  613. var alarmData = ReceiveAlarmData(buffer);
  614. if (alarmData != null)
  615. {
  616. //处理报警数据
  617. AlarmDataReceived?.Invoke(this, new AlarmDataReceivedEventArgs(client.IpAddress, alarmData));
  618. }
  619. await Task.CompletedTask;
  620. }
  621. private async Task ProcessSyncParameters(byte[] data, ClientState client)
  622. {
  623. var (serialNo, parametersData) = ReceiveSyncParameters(data);
  624. if (parametersData != null)
  625. {
  626. var equipmentData = App.Config.Equipments.FirstOrDefault(c => c.IpAddress == client.IpAddress);
  627. if (equipmentData != null)
  628. {
  629. equipmentData.SerialNo = serialNo;
  630. equipmentData.Parameter = parametersData;
  631. await Task.Run(() =>
  632. {
  633. lock (App.Config.Equipments)
  634. {
  635. ConfigHelper.SetEquipment(equipmentData);
  636. }
  637. });
  638. }
  639. }
  640. }
  641. private async Task ProcessDetectionStatus(byte[] buffer, ClientState client)
  642. {
  643. byte code = ReceiveStartOrStopDetectionResultData(buffer);
  644. if (code == 0)
  645. {
  646. // 启动/停止检测结果,0=成功,>0=失败-原因码
  647. DetectionStatusResultReceived?.Invoke(this,
  648. new DetectionStatusResultReceivedEventArgs(client.IpAddress, code));
  649. }
  650. else
  651. {
  652. LogHelper.Error($"启动/停止检测结果失败,原因码:{code}");
  653. }
  654. await Task.CompletedTask;
  655. }
  656. public async Task ProcessUpgradedData(byte[] buffer, ClientState client)
  657. {
  658. byte code = ReceiveUpgradedResultData(buffer);
  659. // 程序更新请求,0=成功,>0=拒绝-原因码
  660. UpgradedRequestResultReceived?.Invoke(this,
  661. new UpgradedResultReceivedEventArgs(client.IpAddress, code));
  662. await Task.CompletedTask;
  663. }
  664. public byte ReceiveTurnLiveStreamData(byte[] buffer)
  665. {
  666. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  667. return bytes[0];
  668. }
  669. public byte ReceiveOpenOrClosedRealtimeData(byte[] buffer)
  670. {
  671. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  672. return bytes[0]; // 开启/关闭结果,0=成功,>0=失败-原因码
  673. }
  674. private DateTime? _lastLiveStreamReceiveTime = null;
  675. public LiveStreamDataModel ReceiveLiveStreamDataModel(byte[] buffer)
  676. {
  677. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  678. var liveStreamData = new LiveStreamDataModel()
  679. {
  680. SensorCount = bytes[0],
  681. SampleCount = _byteTransform.TransUInt16(bytes, 1)
  682. };
  683. var data = bytes.Skip(3).ToArray(); // 跳过前3个字节
  684. liveStreamData.Data = ParseSensorData(data, liveStreamData.SensorCount, liveStreamData.SampleCount);
  685. // 计算本次接收与上次接收的时间差(毫秒)
  686. var now = DateTime.Now;
  687. if (_lastLiveStreamReceiveTime.HasValue)
  688. {
  689. liveStreamData.SampleInterval = (int)(now - _lastLiveStreamReceiveTime.Value).TotalMilliseconds;
  690. }
  691. _lastLiveStreamReceiveTime = now;
  692. return liveStreamData;
  693. }
  694. public TwistFactorDataModel ReceiveTwistFactorData(byte[] buffer)
  695. {
  696. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  697. var twistFactorData = new TwistFactorDataModel
  698. {
  699. Type = bytes[0],
  700. TwistFactor = _byteTransform.TransSingle(bytes, 1) // 判伤捻距系数
  701. };
  702. return twistFactorData;
  703. }
  704. /// <summary>
  705. /// 发送获取编码器方向请求
  706. /// </summary>
  707. /// <param name="serialNo"></param>
  708. /// <param name="client"></param>
  709. /// <returns></returns>
  710. [Obfuscation(Feature = "virtualization", Exclude = false)]
  711. public bool SendGetEncoderDirectionData(string serialNo, Socket clientSocket)
  712. {
  713. try
  714. {
  715. if (clientSocket == null || !clientSocket.Connected)
  716. return false;
  717. // 获取不含端口的IP地址
  718. string ipAddress = ((IPEndPoint)clientSocket.RemoteEndPoint).Address.ToString();
  719. using (var ms = new MemoryStream())
  720. {
  721. ms.WriteByte(0x00); // 操作,0 = 获取编码器方向,1 = 设置编码器方向
  722. ms.WriteByte(0x01); // 编码器方向,1=正向,2=反向
  723. byte[] buffer = CreateData(0x12, ms.ToArray(), serialNo);
  724. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"获取设备编码器方向", ipAddress: ipAddress, serialNo: serialNo));
  725. clientSocket.Send(buffer);
  726. return true;
  727. }
  728. }
  729. catch (Exception ex)
  730. {
  731. LogHelper.Error("发送获取编码器方向数据命令时错误", ex);
  732. return false;
  733. }
  734. }
  735. /// <summary>
  736. /// 发送设置编码器方向数据命令
  737. /// </summary>
  738. /// <param name="direction"></param>
  739. /// <param name="serialNo"></param>
  740. /// <param name="stream"></param>
  741. /// <returns></returns>
  742. [Obfuscation(Feature = "virtualization", Exclude = false)]
  743. public bool SendSetEncoderDirectionData(EncoderDirection direction, string serialNo, Socket clientSocket)
  744. {
  745. try
  746. {
  747. if (clientSocket == null || !clientSocket.Connected)
  748. return false;
  749. // 获取不含端口的IP地址
  750. string ipAddress = ((IPEndPoint)clientSocket.RemoteEndPoint).Address.ToString();
  751. using (var ms = new MemoryStream())
  752. {
  753. ms.WriteByte(0x01); // 操作,0 = 获取编码器方向,1 = 设置编码器方向
  754. ms.WriteByte((byte)direction); // 编码器方向,1=正向,2=反向
  755. byte[] buffer = CreateData(0x12, ms.ToArray(), serialNo);
  756. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"设置设备编码器方向", ipAddress: ipAddress, serialNo: serialNo));
  757. clientSocket.Send(buffer);
  758. return true;
  759. }
  760. }
  761. catch (Exception ex)
  762. {
  763. LogHelper.Error("发送设置编码器方向数据命令时错误", ex);
  764. return false;
  765. }
  766. }
  767. /// <summary>
  768. /// 发送检测结果原始数据请求
  769. /// </summary>
  770. /// <param name="serialNo"></param>
  771. /// <param name="clientSocket"></param>
  772. /// <returns></returns>
  773. [Obfuscation(Feature = "virtualization", Exclude = false)]
  774. private bool SendGetDetectionRawData(string serialNo, Socket clientSocket)
  775. {
  776. try
  777. {
  778. if (clientSocket == null || !clientSocket.Connected)
  779. return false;
  780. // 获取不含端口的IP地址
  781. string ipAddress = ((IPEndPoint)clientSocket.RemoteEndPoint).Address.ToString();
  782. using (var ms = new MemoryStream())
  783. {
  784. ms.WriteByte(0); // 数据类型,0=正常,1=报警,2=故障
  785. WriteBytes(ms, (short)2048); // 单包数据大小,单位:Byte
  786. ms.WriteByte(0x00); // 传输速度控制,单位:KB/s(B/ms),为0则不控速
  787. byte[] buffer = CreateData(0x0E, ms.ToArray(), serialNo);
  788. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"获取检测结果原始数据",
  789. ipAddress: ipAddress,
  790. serialNo: serialNo));
  791. clientSocket.Send(buffer);
  792. return true;
  793. }
  794. }
  795. catch (Exception ex)
  796. {
  797. LogHelper.Error("发送获取编码器方向数据命令时错误", ex);
  798. return false;
  799. }
  800. }
  801. /// <summary>
  802. /// 接收获取原始数据结果
  803. /// </summary>
  804. /// <param name="buffer"></param>
  805. /// <returns></returns>
  806. [Obfuscation(Feature = "virtualization", Exclude = false)]
  807. public DetectionRawResultDataModel ReceiveDetectionRawResultData(byte[] buffer)
  808. {
  809. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  810. var detectionRawResultData = new DetectionRawResultDataModel
  811. {
  812. Code = bytes[0],
  813. Timestamp = _byteTransform.TransInt32(bytes, 1),
  814. SamplingStep = _byteTransform.TransSingle(bytes, 5),
  815. StartAbsolutePosition = _byteTransform.TransSingle(bytes, 9),
  816. EndAbsolutePosition = _byteTransform.TransSingle(bytes, 13),
  817. SensorCount = bytes[17]
  818. };
  819. return detectionRawResultData;
  820. }
  821. /// <summary>
  822. /// 获取原始数据包
  823. /// </summary>
  824. /// <param name="buffer"></param>
  825. /// <returns></returns>
  826. [Obfuscation(Feature = "virtualization", Exclude = false)]
  827. public DetectionRawDataModel ReceiveDetectionRawData(byte[] buffer)
  828. {
  829. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  830. var detectionRawData = new DetectionRawDataModel
  831. {
  832. PacketNumber = _byteTransform.TransUInt32(bytes, 0),
  833. TotalPackets = _byteTransform.TransUInt32(bytes, 4),
  834. DataLength = _byteTransform.TransUInt16(bytes, 8),
  835. Data = bytes.Skip(10).ToArray() // 跳过前10个字节
  836. };
  837. return detectionRawData;
  838. }
  839. /// <summary>
  840. /// 发送开启实时流数据命令
  841. /// </summary>
  842. /// <param name="isOpen">是否开启</param>
  843. /// <param name="serialNo">设备序列号</param>
  844. /// <param name="clientSocket"></param>
  845. /// <returns></returns>
  846. [Obfuscation(Feature = "virtualization", Exclude = false)]
  847. public bool SendTurnLiveStreamData(bool isOpen, string serialNo, Socket clientSocket)
  848. {
  849. try
  850. {
  851. if (clientSocket == null || !clientSocket.Connected)
  852. return false;
  853. // 获取不含端口的IP地址
  854. string ipAddress = ((IPEndPoint)clientSocket.RemoteEndPoint).Address.ToString();
  855. using (var ms = new MemoryStream())
  856. {
  857. ms.WriteByte((byte)(isOpen ? 1 : 0)); // 0=关闭,1=开启
  858. byte[] buffer = CreateData(0x0C, ms.ToArray(), serialNo);
  859. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"{(isOpen ? "开启" : "关闭")}设备实时流",
  860. ipAddress: ipAddress,
  861. serialNo: serialNo));
  862. clientSocket.Send(buffer);
  863. return true;
  864. }
  865. }
  866. catch (Exception ex)
  867. {
  868. LogHelper.Error("发送开启实时流数据命令时错误", ex);
  869. return false;
  870. }
  871. }
  872. /// <summary>
  873. /// 发送获取判伤捻距系数数据命令
  874. /// </summary>
  875. /// <param name="serialNo"></param>
  876. /// <param name="client"></param>
  877. /// <returns></returns>
  878. public bool SendGetTwistFactorData(string serialNo, Socket clientSocket)
  879. {
  880. try
  881. {
  882. if (clientSocket == null || !clientSocket.Connected)
  883. return false;
  884. // 获取不含端口的IP地址
  885. string ipAddress = ((IPEndPoint)clientSocket.RemoteEndPoint).Address.ToString();
  886. using (var ms = new MemoryStream())
  887. {
  888. ms.WriteByte(0x00); // 操作,0=获取判伤捻距系数,1=设置判伤捻距系数
  889. WriteBytes(ms, 0); // 判伤捻距系数
  890. byte[] buffer = CreateData(0x13, ms.ToArray(), serialNo);
  891. clientSocket.Send(buffer);
  892. return true;
  893. }
  894. }
  895. catch (Exception ex)
  896. {
  897. LogHelper.Error("发送获取判伤捻距系数数据命令时错误", ex);
  898. return false;
  899. }
  900. }
  901. /// <summary>
  902. /// 设置判伤捻距系数
  903. /// </summary>
  904. /// <param name="twistFactor"></param>
  905. /// <param name="serialNo"></param>
  906. /// <param name="clientSocket"></param>
  907. /// <returns></returns>
  908. public bool SendSetTwistFactorData(float twistFactor, string serialNo, Socket clientSocket)
  909. {
  910. try
  911. {
  912. if (clientSocket == null || !clientSocket.Connected)
  913. return false;
  914. using (var ms = new MemoryStream())
  915. {
  916. ms.WriteByte(0x01); // 操作,0=获取判伤捻距系数,1=设置判伤捻距系数
  917. WriteBytes(ms, twistFactor); // 判伤捻距系数
  918. byte[] buffer = CreateData(0x13, ms.ToArray(), serialNo);
  919. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"设置设备判伤捻距系数", serialNo: serialNo));
  920. clientSocket.Send(buffer);
  921. return true;
  922. }
  923. }
  924. catch (Exception ex)
  925. {
  926. LogHelper.Error("发送设置判伤捻距系数数据命令时错误", ex);
  927. return false;
  928. }
  929. }
  930. /// <summary>
  931. /// 返回编码器方向
  932. /// </summary>
  933. /// <param name="buffer"></param>
  934. /// <returns></returns>
  935. public EncoderDirectionDataModel ReceiveEncoderDirectionData(byte[] buffer)
  936. {
  937. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  938. var encoderDirection = new EncoderDirectionDataModel
  939. {
  940. Code = bytes[0],
  941. Type = bytes[1],
  942. Direction = (EncoderDirection)bytes[2] // 编码器方向,1=正向,2=反向
  943. };
  944. return encoderDirection;
  945. }
  946. /// <summary>
  947. /// 接收返回系统时钟数据
  948. /// </summary>
  949. /// <param name="buffer"></param>
  950. /// <returns></returns>
  951. public ClockDataModel ReceiveClockData(byte[] buffer)
  952. {
  953. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  954. ClockDataModel clockData = new ClockDataModel
  955. {
  956. Code = bytes[0],
  957. Type = bytes[1],
  958. Time = _byteTransform.TransInt32(bytes, 2)
  959. };
  960. return clockData;
  961. }
  962. /// <summary>
  963. /// 主板复位应答
  964. /// </summary>
  965. /// <param name="buffer"></param>
  966. /// <returns></returns>
  967. public ResetSystemDataModel ReceiveResetSystemData(byte[] buffer)
  968. {
  969. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  970. var resetSystemData = new ResetSystemDataModel
  971. {
  972. Code = bytes[0]
  973. };
  974. return resetSystemData;
  975. }
  976. /// <summary>
  977. /// 设置当前实时位置应答
  978. /// </summary>
  979. /// <param name="buffer"></param>
  980. /// <returns></returns>
  981. public SetAbsolutePositionDataModel ReceiveSetAbsolutePositionData(byte[] buffer)
  982. {
  983. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  984. var setAbsolutePositionData = new SetAbsolutePositionDataModel
  985. {
  986. Code = bytes[0]
  987. };
  988. return setAbsolutePositionData;
  989. }
  990. /// <summary>
  991. /// 发送获取时钟数据命令
  992. /// </summary>
  993. /// <param name="serialNo"></param>
  994. /// <param name="stream"></param>
  995. /// <returns></returns>
  996. public bool SendGetClockData(string serialNo, Socket clientSocket)
  997. {
  998. try
  999. {
  1000. if (clientSocket == null || !clientSocket.Connected)
  1001. return false;
  1002. // 获取不含端口的IP地址
  1003. string ipAddress = ((IPEndPoint)clientSocket.RemoteEndPoint).Address.ToString();
  1004. using (var ms = new MemoryStream())
  1005. {
  1006. ms.WriteByte(0x00); // 操作,0=获取时钟,1=设置时钟
  1007. WriteBytes(ms, 0);// 设置时间戳
  1008. byte[] buffer = CreateData(0x10, ms.ToArray(), serialNo);
  1009. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"获取设备时钟", ipAddress: ipAddress, serialNo: serialNo));
  1010. clientSocket.Send(buffer);
  1011. return true;
  1012. }
  1013. }
  1014. catch (Exception ex)
  1015. {
  1016. LogHelper.Error("发送获取时钟数据命令时错误", ex);
  1017. return false;
  1018. }
  1019. }
  1020. /// <summary>
  1021. /// 发送设置时钟数据命令
  1022. /// </summary>
  1023. /// <param name="timestamp">时间戳</param>
  1024. /// <param name="serialNo">序列号</param>
  1025. /// <param name="clientSocket">网络数据流</param>
  1026. /// <returns></returns>
  1027. public bool SendSetClockData(int timestamp, string serialNo, Socket clientSocket)
  1028. {
  1029. try
  1030. {
  1031. if (clientSocket == null || !clientSocket.Connected)
  1032. return false;
  1033. // 获取不含端口的IP地址
  1034. string ipAddress = ((IPEndPoint)clientSocket.RemoteEndPoint).Address.ToString();
  1035. using (var ms = new MemoryStream())
  1036. {
  1037. ms.WriteByte(0x01); // 操作,0=获取时钟,1=设置时钟
  1038. WriteBytes(ms, timestamp);// 设置时间戳
  1039. byte[] buffer = CreateData(0x10, ms.ToArray(), serialNo);
  1040. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"设置设备时钟",
  1041. ipAddress: ipAddress,
  1042. serialNo: serialNo));
  1043. clientSocket.Send(buffer);
  1044. return true;
  1045. }
  1046. }
  1047. catch (Exception ex)
  1048. {
  1049. LogHelper.Error("发送设置时钟数据命令时错误", ex);
  1050. return false;
  1051. }
  1052. }
  1053. /// <summary>
  1054. /// 接收实时数据
  1055. /// </summary>
  1056. /// <param name="buffer"></param>
  1057. /// <returns></returns>
  1058. public RealTimeDataModel ReceiveRealTimeData(byte[] buffer)
  1059. {
  1060. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  1061. RealTimeDataModel realTimeData = new RealTimeDataModel
  1062. {
  1063. Status = (RunningStatus)bytes[0],
  1064. Speed = _byteTransform.TransSingle(bytes, 1),
  1065. AbsolutePosition = _byteTransform.TransSingle(bytes, 5),
  1066. Position = _byteTransform.TransSingle(bytes, 9)
  1067. };
  1068. return realTimeData;
  1069. }
  1070. /// <summary>
  1071. /// 接收检测结果
  1072. /// </summary>
  1073. /// <param name="buffer"></param>
  1074. /// <returns></returns>
  1075. public DetectionDataModel ReceiveDetectionData(byte[] buffer)
  1076. {
  1077. var verifyData = GetVerifyDataAndCheckCaption(buffer);
  1078. if (!verifyData.IsValid)
  1079. {
  1080. LogHelper.Error("接收检测结果时验证码校验失败");
  1081. return null;
  1082. }
  1083. var data = verifyData.Data;
  1084. DetectionDataModel detectionData = new DetectionDataModel
  1085. {
  1086. StartTime = _byteTransform.TransInt32(data, 0),
  1087. EndTime = _byteTransform.TransInt32(data, 4),
  1088. StartPoint = _byteTransform.TransSingle(data, 8),
  1089. EndPoint = _byteTransform.TransSingle(data, 12),
  1090. DetectionLength = _byteTransform.TransSingle(data, 16),
  1091. DetectedSpeed = _byteTransform.TransSingle(data, 20),
  1092. DamageCount = _byteTransform.TransInt16(data, 24),
  1093. Damages = new List<DamageModel>()
  1094. };
  1095. for (int i = 0; i < detectionData.DamageCount; i++)
  1096. {
  1097. int offset = 26 + i * 10; // 每个损伤数据占8字节
  1098. if (offset + 10 > data.Length) break; // 防止越界
  1099. var damageData = new DamageModel
  1100. {
  1101. RopeNumber = data[offset],
  1102. DamagePoint = _byteTransform.TransSingle(data, offset + 1),
  1103. DamageValue = _byteTransform.TransSingle(data, offset + 5),
  1104. DamageLevel = (DamageLevel)data[offset + 9]
  1105. };
  1106. detectionData.Damages.Add(damageData);
  1107. }
  1108. return detectionData;
  1109. }
  1110. /// <summary>
  1111. /// 接收损伤信息
  1112. /// </summary>
  1113. /// <param name="buffer"></param>
  1114. /// <returns></returns>
  1115. public AlarmDataModel ReceiveAlarmData(byte[] buffer)
  1116. {
  1117. var verifyData = GetVerifyDataAndCheckCaption(buffer);
  1118. if (!verifyData.IsValid)
  1119. {
  1120. LogHelper.Error("接收同步参数时验证码校验失败");
  1121. return null;
  1122. }
  1123. var data = verifyData.Data;
  1124. AlarmDataModel alarmData = new AlarmDataModel
  1125. {
  1126. RopeNumber = data[1],
  1127. DamagePosition = _byteTransform.TransSingle(data, 2),
  1128. DamageValue = _byteTransform.TransSingle(data, 6),
  1129. DamageLevel = (DamageLevel)data[10]
  1130. };
  1131. return alarmData;
  1132. }
  1133. /// <summary>
  1134. /// 接收故障信息
  1135. /// </summary>
  1136. /// <param name="buffer"></param>
  1137. /// <returns></returns>
  1138. public FaultDataModel ReceiveFaultData(byte[] buffer)
  1139. {
  1140. var verifyData = GetVerifyDataAndCheckCaption(buffer);
  1141. if (!verifyData.IsValid)
  1142. {
  1143. LogHelper.Error("接收设备故障时验证码校验失败");
  1144. return null;
  1145. }
  1146. FaultDataModel faultData = new FaultDataModel();
  1147. var data = verifyData.Data;
  1148. faultData.FaultType = (FaultType)data[0];
  1149. faultData.FaultCode = _byteTransform.TransInt32(data, 1);
  1150. return faultData;
  1151. }
  1152. public byte ReceiveStartOrStopDetectionResultData(byte[] buffer)
  1153. {
  1154. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  1155. return bytes[0];
  1156. }
  1157. public byte ReceiveUpgradedResultData(byte[] buffer)
  1158. {
  1159. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  1160. return bytes[0];
  1161. }
  1162. public byte ReceiveChangeSerialNoResultData(byte[] buffer)
  1163. {
  1164. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  1165. return bytes[0];
  1166. }
  1167. /// <summary>
  1168. /// 回复心跳
  1169. /// </summary>
  1170. /// <returns></returns>
  1171. private void RespondHeartbeat(byte[] buffer, string ipAddress, Socket clientSocket)
  1172. {
  1173. try
  1174. {
  1175. if (buffer[1] == 0x00)
  1176. {
  1177. byte[] response = new byte[] { 0xD0, 0x00 };
  1178. clientSocket?.Send(response); // 直接使用Socket发送
  1179. }
  1180. }
  1181. // 设备刚断开时回复心跳会抛 SocketException(对端重置),
  1182. // 就地吞掉即可,后续接收回调会走正常断开流程
  1183. catch (SocketException) { }
  1184. catch (ObjectDisposedException) { }
  1185. }
  1186. private async Task ProcessSerialNoData(byte[] buffer, ClientState client)
  1187. {
  1188. byte code = ReceiveChangeSerialNoResultData(buffer);
  1189. if (code == 0)
  1190. {
  1191. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"修改设备序列号成功", serialNo: client.SerialNo));
  1192. }
  1193. else
  1194. {
  1195. LogHelper.Error($"修改设备序列号结果失败,原因码:{code}");
  1196. }
  1197. await Task.CompletedTask;
  1198. }
  1199. /// <summary>
  1200. /// 接收同步参数
  1201. /// </summary>
  1202. /// <param name="buffer"></param>
  1203. /// <returns></returns>
  1204. public (string SerialNo, ParameterModel Parameter) ReceiveSyncParameters(byte[] buffer)
  1205. {
  1206. ParameterModel parameterData = new ParameterModel();
  1207. var verifyData = GetVerifyDataAndCheckCaption(buffer);
  1208. if (!verifyData.IsValid)
  1209. {
  1210. LogHelper.Error("接收同步参数时验证码校验失败");
  1211. return (null, null);
  1212. }
  1213. byte[] data = verifyData.Data;
  1214. int index = 0;
  1215. #region 主板软件版本号
  1216. short versionLength = data[index]; index += 1;
  1217. if (data.Length - index < versionLength)
  1218. return (null, null);
  1219. parameterData.MainBoardSoftwareVersion = Encoding.ASCII.GetString(data.Skip(index).Take(versionLength).ToArray());
  1220. index += versionLength;
  1221. #endregion
  1222. #region 基础参数
  1223. parameterData.SensorCount = _byteTransform.TransInt16(data, index); index += 2;
  1224. parameterData.SamplingStep = _byteTransform.TransSingle(data, index); index += 4;
  1225. parameterData.FrequencyDivisionFactor = _byteTransform.TransInt16(data, index); index += 2;
  1226. parameterData.DamageInterval = _byteTransform.TransInt16(data, index); index += 2;
  1227. #endregion
  1228. #region 判伤参数
  1229. parameterData.DamageThreshold = _byteTransform.TransInt16(data, index); index += 2;
  1230. parameterData.ScrapUpperLimit = _byteTransform.TransInt16(data, index); index += 2;
  1231. parameterData.FrontMagnetLength = _byteTransform.TransInt16(data, index); index += 2;
  1232. parameterData.BackMagnetLength = _byteTransform.TransInt16(data, index); index += 2;
  1233. parameterData.ValueCoefficient = _byteTransform.TransSingle(data, index); index += 4;
  1234. #endregion
  1235. #region 零点位参数
  1236. parameterData.EffectiveStrokeLength = _byteTransform.TransSingle(data, index); index += 4;
  1237. parameterData.ZeroPositionCorrectionDuration = _byteTransform.TransInt16(data, index); index += 2;
  1238. parameterData.ZeroPositionCorrectionOffset = _byteTransform.TransInt16(data, index); index += 2;
  1239. #endregion
  1240. #region 报警参数
  1241. parameterData.WarningValue = _byteTransform.TransSingle(data, index); index += 4;
  1242. parameterData.AlarmValue = _byteTransform.TransSingle(data, index); index += 4;
  1243. parameterData.SoundLightAlarmAutoResetMode = _byteTransform.TransInt16(data, index); index += 2;
  1244. #endregion
  1245. #region 钢丝绳信息
  1246. parameterData.WireRopeType = _byteTransform.TransInt16(data, index); index += 2;
  1247. parameterData.WireRopeCount = _byteTransform.TransInt16(data, index); index += 2;
  1248. parameterData.WireRopeLength = _byteTransform.TransSingle(data, index); index += 4;
  1249. parameterData.WireRopeDiameter = _byteTransform.TransSingle(data, index); index += 4;
  1250. parameterData.WireRopeStrandCount = _byteTransform.TransInt16(data, index); index += 2;
  1251. parameterData.WireRopeStrandWireCount = _byteTransform.TransInt16(data, index); index += 2;
  1252. #endregion
  1253. #region 限位校准位置
  1254. parameterData.FirstCalibrationPositiont = _byteTransform.TransSingle(data, index); index += 4;
  1255. parameterData.SecondCalibrationPositiont = _byteTransform.TransSingle(data, index); index += 4;
  1256. #endregion
  1257. return (verifyData.SerialNo, parameterData);
  1258. }
  1259. /// <summary>
  1260. /// 发送同步参数
  1261. /// </summary>
  1262. /// <param name="parameterData"></param>
  1263. /// <returns></returns>
  1264. public bool SendSyncParameters(ParameterModel parameters, string serialNo, Socket clientSocket)
  1265. {
  1266. try
  1267. {
  1268. if (clientSocket == null || !clientSocket.Connected)
  1269. return false;
  1270. using (var ms = new MemoryStream())
  1271. {
  1272. // Basic parameters
  1273. WriteBytes(ms, parameters.SensorCount);
  1274. WriteBytes(ms, parameters.SamplingStep);
  1275. WriteBytes(ms, parameters.FrequencyDivisionFactor);
  1276. WriteBytes(ms, parameters.DamageInterval);
  1277. // Damage judgment parameters
  1278. WriteBytes(ms, parameters.DamageThreshold);
  1279. WriteBytes(ms, parameters.ScrapUpperLimit);
  1280. WriteBytes(ms, parameters.FrontMagnetLength);
  1281. WriteBytes(ms, parameters.BackMagnetLength);
  1282. WriteBytes(ms, parameters.ValueCoefficient);
  1283. // Zero position parameters
  1284. WriteBytes(ms, parameters.EffectiveStrokeLength);
  1285. WriteBytes(ms, parameters.ZeroPositionCorrectionDuration);
  1286. WriteBytes(ms, parameters.ZeroPositionCorrectionOffset);
  1287. // Alarm parameters
  1288. WriteBytes(ms, parameters.WarningValue);
  1289. WriteBytes(ms, parameters.AlarmValue);
  1290. WriteBytes(ms, (ushort)parameters.SoundLightAlarmAutoResetMode);
  1291. // Wire rope info
  1292. WriteBytes(ms, parameters.WireRopeType);
  1293. WriteBytes(ms, parameters.WireRopeCount);
  1294. WriteBytes(ms, parameters.WireRopeLength);
  1295. WriteBytes(ms, parameters.WireRopeDiameter);
  1296. WriteBytes(ms, parameters.WireRopeStrandCount);
  1297. WriteBytes(ms, parameters.WireRopeStrandWireCount);
  1298. // Calibration Info
  1299. WriteBytes(ms, parameters.FirstCalibrationPositiont);
  1300. WriteBytes(ms, parameters.SecondCalibrationPositiont);
  1301. var buffer = CreateData(0x02, ms.ToArray(), serialNo);
  1302. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"同步设备参数", serialNo: serialNo));
  1303. clientSocket.Send(buffer);
  1304. return true;
  1305. }
  1306. }
  1307. catch (Exception ex)
  1308. {
  1309. LogHelper.Error("发送同步参数时错误", ex);
  1310. return false;
  1311. }
  1312. }
  1313. /// <summary>
  1314. /// 发送开始或停止检测命令
  1315. /// </summary>
  1316. /// <param name="runningMode">检测模式 0=停止,1=启动空域检测,2=启动时域检测</param>
  1317. /// <param name="serialNo">设备序列号</param>
  1318. /// <param name="clientSocket">数据流</param>
  1319. public bool SendStartOrStopDetection(byte runningMode, string serialNo, Socket clientSocket)
  1320. {
  1321. try
  1322. {
  1323. if (clientSocket == null || !clientSocket.Connected)
  1324. return false;
  1325. using (var ms = new MemoryStream())
  1326. {
  1327. ms.WriteByte(runningMode);// 0 = 停止,1 = 启动空域检测,2 = 启动时域检测
  1328. byte[] buffer = CreateData(0x06, ms.ToArray(), serialNo);
  1329. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"{(runningMode == 0 ? "停止" : "开始")}设备检测",
  1330. serialNo: serialNo));
  1331. clientSocket.Send(buffer);
  1332. return true;
  1333. }
  1334. }
  1335. catch (Exception ex)
  1336. {
  1337. LogHelper.Error("发送开始或停止检测命令时错误", ex);
  1338. return false;
  1339. }
  1340. }
  1341. /// <summary>
  1342. /// 发送修改设备序列号请求
  1343. /// </summary>
  1344. /// <param name="serialNo">设备序列号</param>
  1345. /// <param name="clientSocket">数据流</param>
  1346. /// <returns></returns>
  1347. public bool SendSerialNoRequest(string serialNo, Socket clientSocket)
  1348. {
  1349. try
  1350. {
  1351. if (clientSocket == null || !clientSocket.Connected || serialNo.IsNullOrEmpty())
  1352. return false;
  1353. using (var ms = new MemoryStream())
  1354. {
  1355. byte[] serialNoBytes = Encoding.UTF8.GetBytes(serialNo);
  1356. ms.WriteByte((byte)serialNoBytes.Length); // 序列号长度
  1357. ms.Write(serialNoBytes, 0, serialNoBytes.Length); // 序列号
  1358. byte[] buffer = CreateData(0x16, ms.ToArray(), serialNo);
  1359. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"请求修改设备序列号", serialNo: null));
  1360. clientSocket.Send(buffer);
  1361. return true;
  1362. }
  1363. }
  1364. catch (Exception ex)
  1365. {
  1366. LogHelper.Error("发送设备序列号请求命令时错误", ex);
  1367. return false;
  1368. }
  1369. }
  1370. /// <summary>
  1371. /// 发送程序更新请求
  1372. /// </summary>
  1373. /// <param name="serialNo">设备序列号</param>
  1374. /// <param name="clientSocket">数据流</param>
  1375. /// <returns></returns>
  1376. public bool SendUpgradeRequest(string serialNo, Socket clientSocket)
  1377. {
  1378. try
  1379. {
  1380. if (clientSocket == null || !clientSocket.Connected)
  1381. return false;
  1382. using (var ms = new MemoryStream())
  1383. {
  1384. ms.WriteByte(1);
  1385. byte[] buffer = CreateData(0x11, ms.ToArray(), serialNo);
  1386. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"发起程序更新请求", serialNo: serialNo));
  1387. clientSocket.Send(buffer);
  1388. return true;
  1389. }
  1390. }
  1391. catch (Exception ex)
  1392. {
  1393. LogHelper.Error("发送程序更新请求命令时错误", ex);
  1394. return false;
  1395. }
  1396. }
  1397. /// <summary>
  1398. /// 发送开始或停止实时数据
  1399. /// </summary>
  1400. /// <param name="isOpen">是否开启</param>
  1401. /// <param name="serialNo">序列号</param>
  1402. /// <param name="clientSocket"></param>
  1403. public void SendOpenOrClosedRealtimeData(bool isOpen, string serialNo, Socket clientSocket)
  1404. {
  1405. try
  1406. {
  1407. if (clientSocket == null || !clientSocket.Connected)
  1408. return;
  1409. string ipAddress = ((IPEndPoint)clientSocket.RemoteEndPoint).Address.ToString();
  1410. using (var ms = new MemoryStream())
  1411. {
  1412. ms.WriteByte((byte)(isOpen ? 1 : 0)); // 0=关闭,1=开启
  1413. byte[] buffer = CreateData(0x06, ms.ToArray(), serialNo);
  1414. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"{(isOpen ? "开启" : "停止")}设备实时数据",
  1415. ipAddress: ipAddress,
  1416. serialNo: serialNo));
  1417. clientSocket.Send(buffer);
  1418. }
  1419. }
  1420. catch (Exception ex)
  1421. {
  1422. LogHelper.Error("发送开始或停止实时数据命令时错误", ex);
  1423. }
  1424. }
  1425. /// <summary>
  1426. /// 标记客户端数据激活:收到任意有效数据(心跳包或业务数据包)时调用。
  1427. /// 数据在正常收发时保持连接活跃,避免心跳包缺失导致误判离线。
  1428. /// </summary>
  1429. private void MarkDataActive(ClientState client)
  1430. {
  1431. if (client == null)
  1432. return;
  1433. client.LastDataReceivedTime = DateTime.UtcNow;
  1434. client.LastActiveTime = DateTime.UtcNow;
  1435. SetDataActiveState(client, true);
  1436. }
  1437. /// <summary>
  1438. /// 设置数据激活状态,仅在状态发生变化时对外触发事件
  1439. /// </summary>
  1440. private void SetDataActiveState(ClientState client, bool isDataActive)
  1441. {
  1442. if (client == null || client.IsDataActive == isDataActive)
  1443. return;
  1444. client.IsDataActive = isDataActive;
  1445. DataActiveStateChanged?.Invoke(this,
  1446. new DataActiveStateChangedEventArgs(client.IpAddress, isDataActive, client.LastDataReceivedTime));
  1447. }
  1448. /// <summary>
  1449. /// 获取指定设备的数据激活状态(数据超时窗口内收到过有效数据)
  1450. /// </summary>
  1451. public bool IsDataActive(string ipAddress)
  1452. {
  1453. if (string.IsNullOrEmpty(ipAddress))
  1454. return false;
  1455. return _connectedClients.TryGetValue(ipAddress, out var client) && client.IsDataActive;
  1456. }
  1457. private void SafeCloseClient(ClientState client)
  1458. {
  1459. // 已关闭则直接返回,避免心跳线程与接收回调重复触发断开事件
  1460. if (client == null || client.IsClosed)
  1461. return;
  1462. client.IsClosed = true;
  1463. try
  1464. {
  1465. ClientDisconnected?.Invoke(this, new ClientDisconnectedEventArgs(client.ClientSocket, client.IpAddress));
  1466. _connectedClients.TryRemove(client.IpAddress, out _);
  1467. // 连接断开后数据激活状态置为失活
  1468. SetDataActiveState(client, false);
  1469. var socket = client.ClientSocket;
  1470. client.ClientSocket = null;
  1471. if (socket != null)
  1472. {
  1473. try
  1474. {
  1475. socket.Shutdown(SocketShutdown.Both);
  1476. }
  1477. catch (SocketException) { }
  1478. catch (ObjectDisposedException) { }
  1479. socket.Close();
  1480. socket.Dispose();
  1481. }
  1482. }
  1483. catch (Exception ex)
  1484. {
  1485. Console.WriteLine($"关闭Socket时错误: {ex.Message}");
  1486. }
  1487. }
  1488. private void WriteBytes(MemoryStream ms, dynamic value)
  1489. {
  1490. var bytes = _byteTransform.TransByte(value);
  1491. ms.Write(bytes, 0, bytes.Length);
  1492. }
  1493. /// <summary>
  1494. /// 发送检测结果确认
  1495. /// </summary>
  1496. /// <param name="parameterData"></param>
  1497. /// <returns></returns>
  1498. public bool SendDetectionConfirm(int startTime, int endTime, string serialNo, Socket clientSocket)
  1499. {
  1500. try
  1501. {
  1502. if (clientSocket == null || !clientSocket.Connected)
  1503. return false;
  1504. string ipAddress = ((IPEndPoint)clientSocket.RemoteEndPoint).Address.ToString();
  1505. using (var ms = new MemoryStream())
  1506. {
  1507. WriteBytes(ms, startTime);
  1508. WriteBytes(ms, endTime);
  1509. byte[] buffer = CreateData(0x09, ms.ToArray(), serialNo);
  1510. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"确认设备检测结果", ipAddress: ipAddress, serialNo: serialNo));
  1511. clientSocket.Send(buffer);
  1512. return true;
  1513. }
  1514. }
  1515. catch (Exception ex)
  1516. {
  1517. LogHelper.Error("发送检测结果确认时错误", ex);
  1518. return false;
  1519. }
  1520. }
  1521. /// <summary>
  1522. /// 发送主板复位请求
  1523. /// </summary>
  1524. /// <param name="serialNo"></param>
  1525. /// <param name="clientSocket"></param>
  1526. /// <returns></returns>
  1527. public bool SendResetSystemData(string serialNo, Socket clientSocket)
  1528. {
  1529. try
  1530. {
  1531. if (clientSocket == null || !clientSocket.Connected)
  1532. return false;
  1533. using (var ms = new MemoryStream())
  1534. {
  1535. byte[] buffer = CreateData(0x14, ms.ToArray(), serialNo);
  1536. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"发送主板复位请求", serialNo: serialNo));
  1537. clientSocket.Send(buffer);
  1538. return true;
  1539. }
  1540. }
  1541. catch (Exception ex)
  1542. {
  1543. LogHelper.Error("发送主板复位请求时错误", ex);
  1544. return false;
  1545. }
  1546. }
  1547. /// <summary>
  1548. /// 发送设置当前实时位置
  1549. /// </summary>
  1550. /// <returns></returns>
  1551. public bool SendRealTimeAbsolutePositionData(int switchIndex, float absolutePosition, string serialNo, Socket clientSocket)
  1552. {
  1553. try
  1554. {
  1555. if (clientSocket == null || !clientSocket.Connected)
  1556. return false;
  1557. using (var ms = new MemoryStream())
  1558. {
  1559. ms.WriteByte((byte)switchIndex);// 0无关联开关 1 关联开关1 2关联开关2
  1560. WriteBytes(ms, absolutePosition);
  1561. byte[] buffer = CreateData(0x15, ms.ToArray(), serialNo);
  1562. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"发送设置当前实时位置请求", serialNo: serialNo));
  1563. clientSocket.Send(buffer);
  1564. return true;
  1565. }
  1566. }
  1567. catch (Exception ex)
  1568. {
  1569. LogHelper.Error("发送设置当前实时位置请求时错误", ex);
  1570. return false;
  1571. }
  1572. }
  1573. /// <summary>
  1574. /// 获取数据并验证验证码
  1575. /// </summary>
  1576. /// <param name="buffer">数据</param>
  1577. /// <returns></returns>
  1578. [Obfuscation(Feature = "virtualization", Exclude = false)]
  1579. private VerifyDataModel GetVerifyDataAndCheckCaption(byte[] buffer)
  1580. {
  1581. VerifyDataModel verifyData = new VerifyDataModel() { Password = PASSWORD };
  1582. // 使用Span直接操作内存
  1583. Span<byte> span = buffer.AsSpan();
  1584. // 移除事件类型
  1585. span = span.Slice(1);
  1586. // 读取序列号长度
  1587. if (span.IsEmpty) return verifyData;
  1588. int serialNoLength = span[0];
  1589. // 读取序列号
  1590. if (span.Length - 1 < serialNoLength) return verifyData;
  1591. verifyData.SerialNo = SoftBasic.GetAsciiStringRender(span.Slice(1, serialNoLength).ToArray());
  1592. span = span.Slice(1 + serialNoLength);
  1593. // 读取随机码
  1594. if (span.Length < 4) return verifyData;
  1595. verifyData.RandomCode = _byteTransform.TransUInt32(span.ToArray(), 0);
  1596. span = span.Slice(4);
  1597. // 读取验证码长度
  1598. if (span.IsEmpty) return verifyData;
  1599. int captchaLength = span[0];
  1600. // 验证验证码
  1601. if (span.Length - 1 < captchaLength) return verifyData;
  1602. verifyData.Captcha = SoftBasic.AsciiBytesToBytes(span.Slice(1, captchaLength).ToArray());
  1603. // 截取剩余数据
  1604. verifyData.Data = span.Slice(captchaLength + 1).ToArray();
  1605. // 校验验证码
  1606. verifyData.IsValid = VerifyCaptcha(verifyData);
  1607. return verifyData;
  1608. }
  1609. /// <summary>
  1610. /// 验证码校验
  1611. /// </summary>
  1612. /// <returns></returns>
  1613. [Obfuscation(Feature = "virtualization", Exclude = false)]
  1614. private static bool VerifyCaptcha(VerifyDataModel verifyData)
  1615. {
  1616. if (verifyData == null)
  1617. throw new ArgumentNullException(nameof(verifyData));
  1618. if (verifyData.Captcha == null || verifyData.Captcha.Length < 16)
  1619. return false;
  1620. byte[] computedHash;
  1621. using (var md5 = MD5.Create())
  1622. {
  1623. computedHash = md5.ComputeHash(
  1624. Encoding.UTF8.GetBytes(
  1625. verifyData.SerialNo + verifyData.Password + verifyData.RandomCode));
  1626. }
  1627. // 常量时间比较(手动实现)
  1628. return FixedTimeEquals(verifyData.Captcha, computedHash, 16);
  1629. }
  1630. /// <summary>
  1631. /// 常量时间比较两个字节数组,防止时序攻击
  1632. /// </summary>
  1633. private static bool FixedTimeEquals(byte[] a, byte[] b, int length)
  1634. {
  1635. if (a.Length < length || b.Length < length)
  1636. return false;
  1637. int result = 0;
  1638. for (int i = 0; i < length; i++)
  1639. {
  1640. result |= a[i] ^ b[i]; // XOR 操作,相同为0,不同为非0
  1641. }
  1642. return result == 0;
  1643. }
  1644. ///<summary>
  1645. ///创建数据验证码
  1646. ///</summary>
  1647. /// <returns></returns>
  1648. [Obfuscation(Feature = "virtualization", Exclude = false)]
  1649. protected byte[] CreateData(byte eventType, byte[] data, string serialNo)
  1650. {
  1651. using (var md5 = MD5.Create())
  1652. {
  1653. using (var ms = new MemoryStream())
  1654. {
  1655. // 1. 预先计算所有字段的长度
  1656. uint randomCode = (uint)DateTimeOffset.UtcNow.ToUnixTimeSeconds();
  1657. byte[] randomCodeBytes = _byteTransform.TransByte(randomCode);
  1658. byte[] hash = md5.ComputeHash(Encoding.ASCII.GetBytes(serialNo + PASSWORD + randomCode));
  1659. byte[] captcha = SoftBasic.BytesToAsciiBytes(hash);
  1660. // 2. 正确计算剩余长度(关键修正点)
  1661. // 剩余长度 = 事件类型(1) + 序列号长度(1) + 序列号数据 + 随机码 + 验证码长度(1) + 验证码 + 用户数据
  1662. short remainingLength = (short)(
  1663. 1 + // eventType
  1664. randomCodeBytes.Length + // 随机码(固定4字节)
  1665. 1 + captcha.Length + // 验证码(长度字节 + 数据)
  1666. data.Length // 用户数据
  1667. );
  1668. // 3. 写入头部(0x30 + 剩余长度)
  1669. ms.WriteByte(0x30);
  1670. if (remainingLength <= 127)
  1671. {
  1672. ms.WriteByte((byte)remainingLength); // 单字节表示
  1673. }
  1674. else
  1675. {
  1676. // 假设byteTransform.TransByte将short转为2字节大端序
  1677. byte[] remainingLengthBytes = _byteTransform.TransByte(remainingLength);
  1678. ms.Write(remainingLengthBytes, 0, remainingLengthBytes.Length);
  1679. }
  1680. // 4. 写入各字段(保持原逻辑)
  1681. ms.WriteByte(eventType);
  1682. ms.Write(randomCodeBytes, 0, randomCodeBytes.Length);
  1683. ms.WriteByte((byte)captcha.Length);
  1684. ms.Write(captcha, 0, captcha.Length);
  1685. ms.Write(data, 0, data.Length);
  1686. return ms.ToArray();
  1687. }
  1688. }
  1689. }
  1690. [Obfuscation(Feature = "virtualization", Exclude = false)]
  1691. public ushort[][] ParseSensorData(byte[] data, int sensorCount, int sampleCount)
  1692. {
  1693. // 检查数据长度是否匹配
  1694. int expectedLength = sensorCount * sampleCount;
  1695. if (data.Length != expectedLength)
  1696. {
  1697. LogHelper.Error($"数据长度不匹配。预期 {expectedLength} 字节,实际 {data.Length} 字节。");
  1698. return null;
  1699. }
  1700. // 初始化结果列表,每个传感器的数据存储在一个单独的 ushort[]
  1701. ushort[][] sensorDataList = new ushort[sampleCount][];
  1702. for (int i = 0; i < sampleCount; i++)
  1703. {
  1704. sensorDataList[i] = new ushort[sensorCount];
  1705. }
  1706. // 解析数据
  1707. for (int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++)
  1708. {
  1709. for (int sensorIndex = 0; sensorIndex < sensorCount; sensorIndex++)
  1710. {
  1711. // 计算数据在字节数组中的位置
  1712. int dataIndex = (sampleIndex * sensorCount) + sensorIndex;
  1713. // 将 byte 转换为 ushort(直接赋值,因为 byte 可以隐式转换为 ushort)
  1714. sensorDataList[sampleIndex][sensorIndex] = data[dataIndex];
  1715. }
  1716. }
  1717. return sensorDataList;
  1718. }
  1719. /// <summary>
  1720. /// 获取剩余长度
  1721. /// </summary>
  1722. /// <param name="bytes"></param>
  1723. /// <param name="startIndex"></param>
  1724. /// <returns></returns>
  1725. [Obfuscation(Feature = "virtualization", Exclude = false)]
  1726. public static (int BytesConsumed, int Length) GetRemainingLength(byte[] bytes)
  1727. {
  1728. if (bytes == null || bytes.Length < 2) return (0, 0);
  1729. int index = 1; // 跳过包类型字节
  1730. int multiplier = 1;
  1731. int value = 0;
  1732. byte encodedByte;
  1733. int bytesConsumed = 0;
  1734. do
  1735. {
  1736. if (index >= bytes.Length) return (0, 0);
  1737. encodedByte = bytes[index];
  1738. value += (encodedByte & 0x7F) * multiplier;
  1739. multiplier *= 128;
  1740. index++;
  1741. bytesConsumed++;
  1742. if (multiplier > 128 * 128 * 128) // 防止溢出
  1743. return (0, 0);
  1744. } while ((encodedByte & 0x80) != 0 && bytesConsumed < 4); // 最多4字节长度
  1745. return (bytesConsumed, value);
  1746. }
  1747. [Obfuscation(Feature = "virtualization", Exclude = false)]
  1748. private static (string SerialNo, byte[] Bytes) GetSerialNoAndData(byte[] buffer)
  1749. {
  1750. // 使用Span直接操作内存
  1751. Span<byte> span = buffer.AsSpan();
  1752. // 移除事件类型
  1753. span = span.Slice(1);
  1754. // 读取序列号长度
  1755. if (span.IsEmpty) return (null, null);
  1756. int serialNoLength = span[0];
  1757. // 读取序列号
  1758. if (span.Length - 1 < serialNoLength) return (null, null);
  1759. var serialNo = SoftBasic.GetAsciiStringRender(span.Slice(1, serialNoLength).ToArray());
  1760. buffer = span.Slice(1 + serialNoLength).ToArray();
  1761. return (serialNo, buffer);
  1762. }
  1763. public void Dispose()
  1764. {
  1765. try
  1766. {
  1767. _isRunning = false;
  1768. Thread.Sleep(100);
  1769. if (_listener != null)
  1770. {
  1771. if (_listener.Connected)
  1772. {
  1773. _listener.Shutdown(SocketShutdown.Both);
  1774. }
  1775. _listener.Close();
  1776. _listener.Dispose();
  1777. }
  1778. }
  1779. catch (SocketException ex) when (ex.SocketErrorCode == SocketError.NotConnected)
  1780. {
  1781. _listener?.Dispose();
  1782. }
  1783. catch (Exception ex)
  1784. {
  1785. LogHelper.Error($"停止服务时发生异常: {ex.Message}", ex);
  1786. }
  1787. finally
  1788. {
  1789. _listener = null;
  1790. }
  1791. }
  1792. }
  1793. }