TcpServerFrame.cs 69 KB

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