TcpServerFrame.cs 70 KB

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