TcpServerFrame.cs 69 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720
  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. var equipmentData = App.Config.Equipments.FirstOrDefault(c => c.IpAddress == client.IpAddress);
  534. if (equipmentData != null)
  535. {
  536. equipmentData.InUseSensor = faultData.WorkingSensors;
  537. }
  538. // 处理故障数据
  539. FaultDataReceived?.Invoke(this, new FaultDataReceivedEventArgs(client.IpAddress, faultData));
  540. }
  541. await Task.CompletedTask;
  542. }
  543. private async Task ProcessAlarmData(byte[] buffer, ClientState client)
  544. {
  545. var alarmData = ReceiveAlarmData(buffer);
  546. if (alarmData != null)
  547. {
  548. //处理报警数据
  549. AlarmDataReceived?.Invoke(this, new AlarmDataReceivedEventArgs(client.IpAddress, alarmData));
  550. }
  551. await Task.CompletedTask;
  552. }
  553. private async Task ProcessSyncParameters(byte[] data, ClientState client)
  554. {
  555. var (serialNo, parametersData) = ReceiveSyncParameters(data);
  556. if (parametersData != null)
  557. {
  558. var equipmentData = App.Config.Equipments.FirstOrDefault(c => c.IpAddress == client.IpAddress);
  559. if (equipmentData != null)
  560. {
  561. equipmentData.SerialNo = serialNo;
  562. equipmentData.Parameter = parametersData;
  563. await Task.Run(() =>
  564. {
  565. lock (App.Config.Equipments)
  566. {
  567. ConfigHelper.SetEquipment(equipmentData);
  568. }
  569. });
  570. }
  571. }
  572. }
  573. private async Task ProcessDetectionStatus(byte[] buffer, ClientState client)
  574. {
  575. byte code = ReceiveStartOrStopDetectionResultData(buffer);
  576. if (code == 0)
  577. {
  578. // 启动/停止检测结果,0=成功,>0=失败-原因码
  579. DetectionStatusResultReceived?.Invoke(this,
  580. new DetectionStatusResultReceivedEventArgs(client.IpAddress, code));
  581. }
  582. else
  583. {
  584. LogHelper.Error($"启动/停止检测结果失败,原因码:{code}");
  585. }
  586. await Task.CompletedTask;
  587. }
  588. public async Task ProcessUpgradedData(byte[] buffer, ClientState client)
  589. {
  590. byte code = ReceiveUpgradedResultData(buffer);
  591. // 程序更新请求,0=成功,>0=拒绝-原因码
  592. UpgradedRequestResultReceived?.Invoke(this,
  593. new UpgradedResultReceivedEventArgs(client.IpAddress, code));
  594. await Task.CompletedTask;
  595. }
  596. public byte ReceiveTurnLiveStreamData(byte[] buffer)
  597. {
  598. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  599. return bytes[0];
  600. }
  601. public byte ReceiveOpenOrClosedRealtimeData(byte[] buffer)
  602. {
  603. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  604. return bytes[0]; // 开启/关闭结果,0=成功,>0=失败-原因码
  605. }
  606. public LiveStreamDataModel ReceiveLiveStreamDataModel(byte[] buffer)
  607. {
  608. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  609. var liveStreamData = new LiveStreamDataModel()
  610. {
  611. SensorCount = bytes[0],
  612. SampleCount = byteTransform.TransUInt16(bytes, 1)
  613. };
  614. var data = bytes.Skip(3).ToArray(); // 跳过前3个字节
  615. liveStreamData.Data = ParseSensorData(data, liveStreamData.SensorCount, liveStreamData.SampleCount);
  616. return liveStreamData;
  617. }
  618. public TwistFactorDataModel ReceiveTwistFactorData(byte[] buffer)
  619. {
  620. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  621. var twistFactorData = new TwistFactorDataModel
  622. {
  623. Type = bytes[0],
  624. TwistFactor = byteTransform.TransSingle(bytes, 1) // 判伤捻距系数
  625. };
  626. return twistFactorData;
  627. }
  628. /// <summary>
  629. /// 发送获取编码器方向请求
  630. /// </summary>
  631. /// <param name="serialNo"></param>
  632. /// <param name="client"></param>
  633. /// <returns></returns>
  634. public bool SendGetEncoderDirectionData(string serialNo, Socket clientSocket)
  635. {
  636. try
  637. {
  638. if (clientSocket == null || !clientSocket.Connected)
  639. return false;
  640. using (var ms = new MemoryStream())
  641. {
  642. ms.WriteByte(0x00); // 操作,0 = 获取编码器方向,1 = 设置编码器方向
  643. ms.WriteByte(0x01); // 编码器方向,1=正向,2=反向
  644. byte[] buffer = CreateData(0x12, ms.ToArray(), serialNo);
  645. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"获取设备编码器方向", serialNo: serialNo));
  646. clientSocket.Send(buffer);
  647. return true;
  648. }
  649. }
  650. catch (Exception ex)
  651. {
  652. LogHelper.Error("发送获取编码器方向数据命令时错误", ex);
  653. return false;
  654. }
  655. }
  656. /// <summary>
  657. /// 发送设置编码器方向数据命令
  658. /// </summary>
  659. /// <param name="direction"></param>
  660. /// <param name="serialNo"></param>
  661. /// <param name="stream"></param>
  662. /// <returns></returns>
  663. public bool SendSetEncoderDirectionData(EncoderDirection direction, string serialNo, Socket clientSocket)
  664. {
  665. try
  666. {
  667. if (clientSocket == null || !clientSocket.Connected)
  668. return false;
  669. using (var ms = new MemoryStream())
  670. {
  671. ms.WriteByte(0x01); // 操作,0 = 获取编码器方向,1 = 设置编码器方向
  672. ms.WriteByte((byte)direction); // 编码器方向,1=正向,2=反向
  673. byte[] buffer = CreateData(0x12, ms.ToArray(), serialNo);
  674. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"设置设备编码器方向", serialNo: serialNo));
  675. clientSocket.Send(buffer);
  676. return true;
  677. }
  678. }
  679. catch (Exception ex)
  680. {
  681. LogHelper.Error("发送设置编码器方向数据命令时错误", ex);
  682. return false;
  683. }
  684. }
  685. /// <summary>
  686. /// 发送检测结果原始数据请求
  687. /// </summary>
  688. /// <param name="serialNo"></param>
  689. /// <param name="clientSocket"></param>
  690. /// <returns></returns>
  691. private bool SendGetDetectionRawData(string serialNo, Socket clientSocket)
  692. {
  693. try
  694. {
  695. if (clientSocket == null || !clientSocket.Connected)
  696. return false;
  697. using (var ms = new MemoryStream())
  698. {
  699. ms.WriteByte(0); // 数据类型,0=正常,1=报警,2=故障
  700. WriteBytes(ms, (short)2048); // 单包数据大小,单位:Byte
  701. ms.WriteByte(0x00); // 传输速度控制,单位:KB/s(B/ms),为0则不控速
  702. byte[] buffer = CreateData(0x0E, ms.ToArray(), serialNo);
  703. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"获取检测结果原始数据", serialNo: serialNo));
  704. clientSocket.Send(buffer);
  705. return true;
  706. }
  707. }
  708. catch (Exception ex)
  709. {
  710. LogHelper.Error("发送获取编码器方向数据命令时错误", ex);
  711. return false;
  712. }
  713. }
  714. /// <summary>
  715. /// 接收获取原始数据结果
  716. /// </summary>
  717. /// <param name="buffer"></param>
  718. /// <returns></returns>
  719. public DetectionRawResultDataModel ReceiveDetectionRawResultData(byte[] buffer)
  720. {
  721. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  722. var detectionRawResultData = new DetectionRawResultDataModel
  723. {
  724. Code = bytes[0],
  725. Timestamp = byteTransform.TransInt32(bytes, 1),
  726. SamplingStep = byteTransform.TransSingle(bytes, 5),
  727. StartAbsolutePosition = byteTransform.TransSingle(bytes, 9),
  728. EndAbsolutePosition = byteTransform.TransSingle(bytes, 13),
  729. SensorCount = bytes[17]
  730. };
  731. return detectionRawResultData;
  732. }
  733. /// <summary>
  734. /// 获取原始数据包
  735. /// </summary>
  736. /// <param name="buffer"></param>
  737. /// <returns></returns>
  738. public DetectionRawDataModel ReceiveDetectionRawData(byte[] buffer)
  739. {
  740. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  741. var detectionRawData = new DetectionRawDataModel
  742. {
  743. PacketNumber = byteTransform.TransUInt32(bytes, 0),
  744. TotalPackets = byteTransform.TransUInt32(bytes, 4),
  745. DataLength = byteTransform.TransUInt16(bytes, 8),
  746. Data = bytes.Skip(10).ToArray() // 跳过前10个字节
  747. };
  748. return detectionRawData;
  749. }
  750. /// <summary>
  751. /// 发送开启实时流数据命令
  752. /// </summary>
  753. /// <param name="isOpen">是否开启</param>
  754. /// <param name="serialNo">设备序列号</param>
  755. /// <param name="client"></param>
  756. /// <returns></returns>
  757. public bool SendTurnLiveStreamData(bool isOpen, string serialNo, Socket clientSocket)
  758. {
  759. try
  760. {
  761. if (clientSocket == null || !clientSocket.Connected)
  762. return false;
  763. using (var ms = new MemoryStream())
  764. {
  765. ms.WriteByte((byte)(isOpen ? 1 : 0)); // 0=关闭,1=开启
  766. byte[] buffer = CreateData(0x0C, ms.ToArray(), serialNo);
  767. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"{(isOpen ? "开启" : "关闭")}设备实时流", serialNo: serialNo));
  768. clientSocket.Send(buffer);
  769. return true;
  770. }
  771. }
  772. catch (Exception ex)
  773. {
  774. LogHelper.Error("发送开启实时流数据命令时错误", ex);
  775. return false;
  776. }
  777. }
  778. /// <summary>
  779. /// 发送获取判伤捻距系数数据命令
  780. /// </summary>
  781. /// <param name="serialNo"></param>
  782. /// <param name="client"></param>
  783. /// <returns></returns>
  784. public bool SendGetTwistFactorData(string serialNo, Socket clientSocket)
  785. {
  786. try
  787. {
  788. if (clientSocket == null || !clientSocket.Connected)
  789. return false;
  790. using (var ms = new MemoryStream())
  791. {
  792. ms.WriteByte(0x00); // 操作,0=获取判伤捻距系数,1=设置判伤捻距系数
  793. WriteBytes(ms, 0); // 判伤捻距系数
  794. byte[] buffer = CreateData(0x13, ms.ToArray(), serialNo);
  795. DebugMessageReceived?.Invoke(this,
  796. new DebugMessageReceivedEventArgs($"获取设备判伤捻距系数", serialNo: serialNo));
  797. clientSocket.Send(buffer);
  798. return true;
  799. }
  800. }
  801. catch (Exception ex)
  802. {
  803. LogHelper.Error("发送获取判伤捻距系数数据命令时错误", ex);
  804. return false;
  805. }
  806. }
  807. /// <summary>
  808. /// 设置判伤捻距系数
  809. /// </summary>
  810. /// <param name="twistFactor"></param>
  811. /// <param name="serialNo"></param>
  812. /// <param name="stream"></param>
  813. /// <returns></returns>
  814. public bool SendSetTwistFactorData(float twistFactor, string serialNo, Socket clientSocket)
  815. {
  816. try
  817. {
  818. if (clientSocket == null || !clientSocket.Connected)
  819. return false;
  820. using (var ms = new MemoryStream())
  821. {
  822. ms.WriteByte(0x01); // 操作,0=获取判伤捻距系数,1=设置判伤捻距系数
  823. WriteBytes(ms, twistFactor); // 判伤捻距系数
  824. byte[] buffer = CreateData(0x13, ms.ToArray(), serialNo);
  825. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"设置设备判伤捻距系数", serialNo: serialNo));
  826. clientSocket.Send(buffer);
  827. return true;
  828. }
  829. }
  830. catch (Exception ex)
  831. {
  832. LogHelper.Error("发送设置判伤捻距系数数据命令时错误", ex);
  833. return false;
  834. }
  835. }
  836. /// <summary>
  837. /// 返回编码器方向
  838. /// </summary>
  839. /// <param name="buffer"></param>
  840. /// <returns></returns>
  841. public EncoderDirectionDataModel ReceiveEncoderDirectionData(byte[] buffer)
  842. {
  843. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  844. var encoderDirection = new EncoderDirectionDataModel
  845. {
  846. Code = bytes[0],
  847. Type = bytes[1],
  848. Direction = (EncoderDirection)bytes[2] // 编码器方向,1=正向,2=反向
  849. };
  850. return encoderDirection;
  851. }
  852. /// <summary>
  853. /// 接收返回系统时钟数据
  854. /// </summary>
  855. /// <param name="buffer"></param>
  856. /// <returns></returns>
  857. public ClockDataModel ReceiveClockData(byte[] buffer)
  858. {
  859. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  860. ClockDataModel clockData = new ClockDataModel
  861. {
  862. Code = bytes[0],
  863. Type = bytes[1],
  864. Time = byteTransform.TransInt32(bytes, 2)
  865. };
  866. return clockData;
  867. }
  868. /// <summary>
  869. /// 主板复位应答
  870. /// </summary>
  871. /// <param name="buffer"></param>
  872. /// <returns></returns>
  873. public ResetSystemDataModel ReceiveResetSystemData(byte[] buffer)
  874. {
  875. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  876. var resetSystemData = new ResetSystemDataModel
  877. {
  878. Code = bytes[0]
  879. };
  880. return resetSystemData;
  881. }
  882. /// <summary>
  883. /// 设置当前实时位置应答
  884. /// </summary>
  885. /// <param name="buffer"></param>
  886. /// <returns></returns>
  887. public SetAbsolutePositionDataModel ReceiveSetAbsolutePositionData(byte[] buffer)
  888. {
  889. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  890. var setAbsolutePositionData = new SetAbsolutePositionDataModel
  891. {
  892. Code = bytes[0]
  893. };
  894. return setAbsolutePositionData;
  895. }
  896. /// <summary>
  897. /// 发送获取时钟数据命令
  898. /// </summary>
  899. /// <param name="serialNo"></param>
  900. /// <param name="stream"></param>
  901. /// <returns></returns>
  902. public bool SendGetClockData(string serialNo, Socket clientSocket)
  903. {
  904. try
  905. {
  906. if (clientSocket == null || !clientSocket.Connected)
  907. return false;
  908. using (var ms = new MemoryStream())
  909. {
  910. ms.WriteByte(0x00); // 操作,0=获取时钟,1=设置时钟
  911. WriteBytes(ms, 0);// 设置时间戳
  912. byte[] buffer = CreateData(0x10, ms.ToArray(), serialNo);
  913. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"获取设备时钟", serialNo: serialNo));
  914. clientSocket.Send(buffer);
  915. return true;
  916. }
  917. }
  918. catch (Exception ex)
  919. {
  920. LogHelper.Error("发送获取时钟数据命令时错误", ex);
  921. return false;
  922. }
  923. }
  924. /// <summary>
  925. /// 发送设置时钟数据命令
  926. /// </summary>
  927. /// <param name="timestamp">时间戳</param>
  928. /// <param name="serialNo">序列号</param>
  929. /// <param name="stream">网络数据流</param>
  930. /// <returns></returns>
  931. public bool SendSetClockData(int timestamp, string serialNo, Socket clientSocket)
  932. {
  933. try
  934. {
  935. if (clientSocket == null || !clientSocket.Connected)
  936. return false;
  937. using (var ms = new MemoryStream())
  938. {
  939. ms.WriteByte(0x01); // 操作,0=获取时钟,1=设置时钟
  940. WriteBytes(ms, timestamp);// 设置时间戳
  941. byte[] buffer = CreateData(0x10, ms.ToArray(), serialNo);
  942. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"设置设备时钟", serialNo: serialNo));
  943. clientSocket.Send(buffer);
  944. return true;
  945. }
  946. }
  947. catch (Exception ex)
  948. {
  949. LogHelper.Error("发送设置时钟数据命令时错误", ex);
  950. return false;
  951. }
  952. }
  953. /// <summary>
  954. /// 接收实时数据
  955. /// </summary>
  956. /// <param name="buffer"></param>
  957. /// <returns></returns>
  958. public RealTimeDataModel ReceiveRealTimeData(byte[] buffer)
  959. {
  960. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  961. RealTimeDataModel realTimeData = new RealTimeDataModel
  962. {
  963. Status = (RunningStatus)bytes[0],
  964. Speed = byteTransform.TransSingle(bytes, 1),
  965. AbsolutePosition = byteTransform.TransSingle(bytes, 5),
  966. Position = byteTransform.TransSingle(bytes, 9)
  967. };
  968. return realTimeData;
  969. }
  970. /// <summary>
  971. /// 接收检测结果
  972. /// </summary>
  973. /// <param name="buffer"></param>
  974. /// <returns></returns>
  975. public DetectionDataModel ReceiveDetectionData(byte[] buffer)
  976. {
  977. var verifyData = GetVerifyDataAndCheckCaption(buffer);
  978. if (!verifyData.IsValid)
  979. {
  980. LogHelper.Error("接收检测结果时验证码校验失败");
  981. return null;
  982. }
  983. var data = verifyData.Data;
  984. DetectionDataModel detectionData = new DetectionDataModel
  985. {
  986. StartTime = byteTransform.TransInt32(data, 0),
  987. EndTime = byteTransform.TransInt32(data, 4),
  988. StartPoint = byteTransform.TransSingle(data, 8),
  989. EndPoint = byteTransform.TransSingle(data, 12),
  990. DetectionLength = byteTransform.TransSingle(data, 16),
  991. DetectedSpeed = byteTransform.TransSingle(data, 20),
  992. DamageCount = byteTransform.TransInt16(data, 24),
  993. Damages = new List<DamageModel>()
  994. };
  995. for (int i = 0; i < detectionData.DamageCount; i++)
  996. {
  997. int offset = 26 + i * 10; // 每个损伤数据占8字节
  998. if (offset + 10 > data.Length) break; // 防止越界
  999. var damageData = new DamageModel
  1000. {
  1001. RopeNumber = data[offset],
  1002. DamagePoint = byteTransform.TransSingle(data, offset + 1),
  1003. DamageValue = byteTransform.TransSingle(data, offset + 5),
  1004. DamageLevel = (DamageLevel)data[offset + 9]
  1005. };
  1006. detectionData.Damages.Add(damageData);
  1007. }
  1008. return detectionData;
  1009. }
  1010. /// <summary>
  1011. /// 接收损伤信息
  1012. /// </summary>
  1013. /// <param name="buffer"></param>
  1014. /// <returns></returns>
  1015. public AlarmDataModel ReceiveAlarmData(byte[] buffer)
  1016. {
  1017. var verifyData = GetVerifyDataAndCheckCaption(buffer);
  1018. if (!verifyData.IsValid)
  1019. {
  1020. LogHelper.Error("接收同步参数时验证码校验失败");
  1021. return null;
  1022. }
  1023. var data = verifyData.Data;
  1024. AlarmDataModel alarmData = new AlarmDataModel
  1025. {
  1026. RopeNumber = data[1],
  1027. DamagePosition = byteTransform.TransSingle(data, 2),
  1028. DamageValue = byteTransform.TransSingle(data, 6),
  1029. DamageLevel = (DamageLevel)data[10]
  1030. };
  1031. return alarmData;
  1032. }
  1033. /// <summary>
  1034. /// 接收故障信息
  1035. /// </summary>
  1036. /// <param name="buffer"></param>
  1037. /// <returns></returns>
  1038. public FaultDataModel ReceiveFaultData(byte[] buffer)
  1039. {
  1040. var verifyData = GetVerifyDataAndCheckCaption(buffer);
  1041. if (!verifyData.IsValid)
  1042. {
  1043. LogHelper.Error("接收设备故障时验证码校验失败");
  1044. return null;
  1045. }
  1046. FaultDataModel faultData = new FaultDataModel();
  1047. var data = verifyData.Data;
  1048. faultData.FaultType = (FaultType)data[0];
  1049. faultData.FaultCode = byteTransform.TransInt32(data, 1);
  1050. return faultData;
  1051. }
  1052. public byte ReceiveStartOrStopDetectionResultData(byte[] buffer)
  1053. {
  1054. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  1055. return bytes[0];
  1056. }
  1057. public byte ReceiveUpgradedResultData(byte[] buffer)
  1058. {
  1059. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  1060. return bytes[0];
  1061. }
  1062. public byte ReceiveChangeSerialNoResultData(byte[] buffer)
  1063. {
  1064. (string serialNo, byte[] bytes) = GetSerialNoAndData(buffer);
  1065. return bytes[0];
  1066. }
  1067. /// <summary>
  1068. /// 回复心跳
  1069. /// </summary>
  1070. /// <returns></returns>
  1071. private void RespondHeartbeat(byte[] buffer, string ipAddress, Socket clientSocket)
  1072. {
  1073. if (buffer[1] == 0x00)
  1074. {
  1075. byte[] response = new byte[] { 0xD0, 0x00 };
  1076. clientSocket.Send(response); // 直接使用Socket发送
  1077. }
  1078. }
  1079. private async Task ProcessSerialNoData(byte[] buffer, ClientState client)
  1080. {
  1081. byte code = ReceiveChangeSerialNoResultData(buffer);
  1082. if (code == 0)
  1083. {
  1084. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"修改设备序列号成功", serialNo: client.SerialNo));
  1085. }
  1086. else
  1087. {
  1088. LogHelper.Error($"修改设备序列号结果失败,原因码:{code}");
  1089. }
  1090. await Task.CompletedTask;
  1091. }
  1092. /// <summary>
  1093. /// 接收同步参数
  1094. /// </summary>
  1095. /// <param name="buffer"></param>
  1096. /// <returns></returns>
  1097. public (string SerialNo, ParameterModel Parameter) ReceiveSyncParameters(byte[] buffer)
  1098. {
  1099. ParameterModel parameterData = new ParameterModel();
  1100. var verifyData = GetVerifyDataAndCheckCaption(buffer);
  1101. if (!verifyData.IsValid)
  1102. {
  1103. LogHelper.Error("接收同步参数时验证码校验失败");
  1104. return (null, null);
  1105. }
  1106. byte[] data = verifyData.Data;
  1107. int index = 0;
  1108. #region 主板软件版本号
  1109. short versionLength = data[index]; index += 1;
  1110. if (data.Length - index < versionLength)
  1111. return (null, null);
  1112. parameterData.MainBoardSoftwareVersion = Encoding.ASCII.GetString(data.Skip(index).Take(versionLength).ToArray());
  1113. index += versionLength;
  1114. #endregion
  1115. #region 基础参数
  1116. parameterData.SensorCount = byteTransform.TransInt16(data, index); index += 2;
  1117. parameterData.SamplingStep = byteTransform.TransSingle(data, index); index += 4;
  1118. parameterData.FrequencyDivisionFactor = byteTransform.TransInt16(data, index); index += 2;
  1119. parameterData.TimeDomainFrequency = byteTransform.TransInt16(data, index); index += 2;
  1120. #endregion
  1121. #region 判伤参数
  1122. parameterData.DamageThreshold = byteTransform.TransInt16(data, index); index += 2;
  1123. parameterData.ScrapUpperLimit = byteTransform.TransInt16(data, index); index += 2;
  1124. parameterData.FrontMagnetLength = byteTransform.TransInt16(data, index); index += 2;
  1125. parameterData.BackMagnetLength = byteTransform.TransInt16(data, index); index += 2;
  1126. parameterData.ValueCoefficient = byteTransform.TransSingle(data, index); index += 4;
  1127. #endregion
  1128. #region 零点位参数
  1129. parameterData.EffectiveStrokeLength = byteTransform.TransSingle(data, index); index += 4;
  1130. parameterData.ZeroPositionCorrectionDuration = byteTransform.TransInt16(data, index); index += 2;
  1131. parameterData.ZeroPositionCorrectionOffset = byteTransform.TransInt16(data, index); index += 2;
  1132. #endregion
  1133. #region 报警参数
  1134. parameterData.WarningValue = byteTransform.TransSingle(data, index); index += 4;
  1135. parameterData.AlarmValue = byteTransform.TransSingle(data, index); index += 4;
  1136. parameterData.SoundLightAlarmAutoResetMode = byteTransform.TransInt16(data, index); index += 2;
  1137. #endregion
  1138. #region 钢丝绳信息
  1139. parameterData.WireRopeType = byteTransform.TransInt16(data, index); index += 2;
  1140. parameterData.WireRopeCount = byteTransform.TransInt16(data, index); index += 2;
  1141. parameterData.WireRopeLength = byteTransform.TransSingle(data, index); index += 4;
  1142. parameterData.WireRopeDiameter = byteTransform.TransSingle(data, index); index += 4;
  1143. parameterData.WireRopeStrandCount = byteTransform.TransInt16(data, index); index += 2;
  1144. parameterData.WireRopeStrandWireCount = byteTransform.TransInt16(data, index); index += 2;
  1145. #endregion
  1146. return (verifyData.SerialNo, parameterData);
  1147. }
  1148. /// <summary>
  1149. /// 发送同步参数
  1150. /// </summary>
  1151. /// <param name="parameterData"></param>
  1152. /// <returns></returns>
  1153. public bool SendSyncParameters(ParameterModel parameters, string serialNo, Socket clientSocket)
  1154. {
  1155. try
  1156. {
  1157. if (clientSocket == null || !clientSocket.Connected)
  1158. return false;
  1159. using (var ms = new MemoryStream())
  1160. {
  1161. // Basic parameters
  1162. WriteBytes(ms, parameters.SensorCount);
  1163. WriteBytes(ms, parameters.SamplingStep);
  1164. WriteBytes(ms, parameters.FrequencyDivisionFactor);
  1165. WriteBytes(ms, parameters.TimeDomainFrequency);
  1166. // Damage judgment parameters
  1167. WriteBytes(ms, parameters.DamageThreshold);
  1168. WriteBytes(ms, parameters.ScrapUpperLimit);
  1169. WriteBytes(ms, parameters.FrontMagnetLength);
  1170. WriteBytes(ms, parameters.BackMagnetLength);
  1171. WriteBytes(ms, parameters.ValueCoefficient);
  1172. // Zero position parameters
  1173. WriteBytes(ms, parameters.EffectiveStrokeLength);
  1174. WriteBytes(ms, parameters.ZeroPositionCorrectionDuration);
  1175. WriteBytes(ms, parameters.ZeroPositionCorrectionOffset);
  1176. // Alarm parameters
  1177. WriteBytes(ms, parameters.WarningValue);
  1178. WriteBytes(ms, parameters.AlarmValue);
  1179. WriteBytes(ms, (ushort)parameters.SoundLightAlarmAutoResetMode);
  1180. // Wire rope info
  1181. WriteBytes(ms, parameters.WireRopeType);
  1182. WriteBytes(ms, parameters.WireRopeCount);
  1183. WriteBytes(ms, parameters.WireRopeLength);
  1184. WriteBytes(ms, parameters.WireRopeDiameter);
  1185. WriteBytes(ms, parameters.WireRopeStrandCount);
  1186. WriteBytes(ms, parameters.WireRopeStrandWireCount);
  1187. var buffer = CreateData(0x02, ms.ToArray(), serialNo);
  1188. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"同步设备参数", serialNo: serialNo));
  1189. clientSocket.Send(buffer);
  1190. return true;
  1191. }
  1192. }
  1193. catch (Exception ex)
  1194. {
  1195. LogHelper.Error("发送同步参数时错误", ex);
  1196. return false;
  1197. }
  1198. }
  1199. /// <summary>
  1200. /// 发送开始或停止检测命令
  1201. /// </summary>
  1202. /// <param name="mode">检测模式 0=停止,1=启动空域检测,2=启动时域检测</param>
  1203. /// <param name="serialNo">设备序列号</param>
  1204. /// <param name="clientSocket">数据流</param>
  1205. public bool SendStartOrStopDetection(byte runningMode, string serialNo, Socket clientSocket)
  1206. {
  1207. try
  1208. {
  1209. if (clientSocket == null || !clientSocket.Connected)
  1210. return false;
  1211. using (var ms = new MemoryStream())
  1212. {
  1213. ms.WriteByte(runningMode);// 0 = 停止,1 = 启动空域检测,2 = 启动时域检测
  1214. byte[] buffer = CreateData(0x06, ms.ToArray(), serialNo);
  1215. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"{(runningMode == 0 ? "停止" : "开始")}设备检测",
  1216. serialNo: serialNo));
  1217. clientSocket.Send(buffer);
  1218. return true;
  1219. }
  1220. }
  1221. catch (Exception ex)
  1222. {
  1223. LogHelper.Error("发送开始或停止检测命令时错误", ex);
  1224. return false;
  1225. }
  1226. }
  1227. /// <summary>
  1228. /// 发送修改设备序列号请求
  1229. /// </summary>
  1230. /// <param name="serialNo">设备序列号</param>
  1231. /// <param name="clientSocket">数据流</param>
  1232. /// <returns></returns>
  1233. public bool SendSerialNoRequest(string serialNo, Socket clientSocket)
  1234. {
  1235. try
  1236. {
  1237. if (clientSocket == null || !clientSocket.Connected || serialNo.IsNullOrEmpty())
  1238. return false;
  1239. using (var ms = new MemoryStream())
  1240. {
  1241. byte[] serialNoBytes = Encoding.UTF8.GetBytes(serialNo);
  1242. ms.WriteByte((byte)serialNoBytes.Length); // 序列号长度
  1243. ms.Write(serialNoBytes, 0, serialNoBytes.Length); // 序列号
  1244. byte[] buffer = CreateData(0x16, ms.ToArray(), serialNo);
  1245. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"请求修改设备序列号", serialNo: null));
  1246. clientSocket.Send(buffer);
  1247. return true;
  1248. }
  1249. }
  1250. catch (Exception ex)
  1251. {
  1252. LogHelper.Error("发送设备序列号请求命令时错误", ex);
  1253. return false;
  1254. }
  1255. }
  1256. /// <summary>
  1257. /// 发送程序更新请求
  1258. /// </summary>
  1259. /// <param name="serialNo">设备序列号</param>
  1260. /// <param name="clientSocket">数据流</param>
  1261. /// <returns></returns>
  1262. public bool SendUpgradeRequest(string serialNo, Socket clientSocket)
  1263. {
  1264. try
  1265. {
  1266. if (clientSocket == null || !clientSocket.Connected)
  1267. return false;
  1268. using (var ms = new MemoryStream())
  1269. {
  1270. ms.WriteByte(1);
  1271. byte[] buffer = CreateData(0x11, ms.ToArray(), serialNo);
  1272. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"发起程序更新请求", serialNo: serialNo));
  1273. clientSocket.Send(buffer);
  1274. return true;
  1275. }
  1276. }
  1277. catch (Exception ex)
  1278. {
  1279. LogHelper.Error("发送程序更新请求命令时错误", ex);
  1280. return false;
  1281. }
  1282. }
  1283. /// <summary>
  1284. /// 发送开始或停止实时数据
  1285. /// </summary>
  1286. /// <param name="isOpen">是否开启</param>
  1287. /// <param name="serialNo">序列号</param>
  1288. /// <param name="clientSocket"></param>
  1289. public void SendOpenOrClosedRealtimeData(bool isOpen, string serialNo, Socket clientSocket)
  1290. {
  1291. try
  1292. {
  1293. if (clientSocket == null || !clientSocket.Connected)
  1294. return;
  1295. using (var ms = new MemoryStream())
  1296. {
  1297. ms.WriteByte((byte)(isOpen ? 1 : 0)); // 0=关闭,1=开启
  1298. byte[] buffer = CreateData(0x06, ms.ToArray(), serialNo);
  1299. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"{(isOpen ? "开启" : "停止")}设备实时数据", serialNo: serialNo));
  1300. clientSocket.Send(buffer);
  1301. }
  1302. }
  1303. catch (Exception ex)
  1304. {
  1305. LogHelper.Error("发送开始或停止实时数据命令时错误", ex);
  1306. }
  1307. }
  1308. private void SafeCloseClient(ClientState client)
  1309. {
  1310. try
  1311. {
  1312. ClientDisconnected?.Invoke(this, new ClientDisconnectedEventArgs(client.ClientSocket, client.IpAddress));
  1313. _connectedClients.TryRemove(client.IpAddress, out _);
  1314. if (client.ClientSocket?.Connected == true)
  1315. {
  1316. client.ClientSocket?.Shutdown(SocketShutdown.Both);
  1317. client.ClientSocket?.Close();
  1318. client.ClientSocket?.Dispose();
  1319. client.ClientSocket = null;
  1320. }
  1321. }
  1322. catch (Exception ex)
  1323. {
  1324. Console.WriteLine($"关闭Socket时错误: {ex.Message}");
  1325. }
  1326. }
  1327. private void WriteBytes(MemoryStream ms, dynamic value)
  1328. {
  1329. var bytes = byteTransform.TransByte(value);
  1330. ms.Write(bytes, 0, bytes.Length);
  1331. }
  1332. /// <summary>
  1333. /// 发送检测结果确认
  1334. /// </summary>
  1335. /// <param name="parameterData"></param>
  1336. /// <returns></returns>
  1337. public bool SendDetectionConfirm(int startTime, int endTime, string serialNo, Socket clientSocket)
  1338. {
  1339. try
  1340. {
  1341. if (clientSocket == null || !clientSocket.Connected)
  1342. return false;
  1343. using (var ms = new MemoryStream())
  1344. {
  1345. WriteBytes(ms, startTime);
  1346. WriteBytes(ms, endTime);
  1347. byte[] buffer = CreateData(0x09, ms.ToArray(), serialNo);
  1348. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"确认设备检测结果", serialNo: serialNo));
  1349. clientSocket.Send(buffer);
  1350. return true;
  1351. }
  1352. }
  1353. catch (Exception ex)
  1354. {
  1355. LogHelper.Error("发送检测结果确认时错误", ex);
  1356. return false;
  1357. }
  1358. }
  1359. /// <summary>
  1360. /// 发送主板复位请求
  1361. /// </summary>
  1362. /// <param name="serialNo"></param>
  1363. /// <param name="clientSocket"></param>
  1364. /// <returns></returns>
  1365. public bool SendResetSystemData(string serialNo, Socket clientSocket)
  1366. {
  1367. try
  1368. {
  1369. if (clientSocket == null || !clientSocket.Connected)
  1370. return false;
  1371. using (var ms = new MemoryStream())
  1372. {
  1373. byte[] buffer = CreateData(0x14, ms.ToArray(), serialNo);
  1374. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"发送主板复位请求", serialNo: serialNo));
  1375. clientSocket.Send(buffer);
  1376. return true;
  1377. }
  1378. }
  1379. catch (Exception ex)
  1380. {
  1381. LogHelper.Error("发送主板复位请求时错误", ex);
  1382. return false;
  1383. }
  1384. }
  1385. /// <summary>
  1386. /// 发送设置当前实时位置
  1387. /// </summary>
  1388. /// <returns></returns>
  1389. public bool SendRealTimeAbsolutePositionData(float absolutePosition, string serialNo, Socket clientSocket)
  1390. {
  1391. try
  1392. {
  1393. if (clientSocket == null || !clientSocket.Connected)
  1394. return false;
  1395. using (var ms = new MemoryStream())
  1396. {
  1397. ms.WriteByte(1);// 1=设置当前实时位置
  1398. WriteBytes(ms, absolutePosition);
  1399. byte[] buffer = CreateData(0x15, ms.ToArray(), serialNo);
  1400. DebugMessageReceived?.Invoke(this, new DebugMessageReceivedEventArgs($"发送设置当前实时位置请求", serialNo: serialNo));
  1401. clientSocket.Send(buffer);
  1402. return true;
  1403. }
  1404. }
  1405. catch (Exception ex)
  1406. {
  1407. LogHelper.Error("发送设置当前实时位置请求时错误", ex);
  1408. return false;
  1409. }
  1410. }
  1411. /// <summary>
  1412. /// 获取数据并验证验证码
  1413. /// </summary>
  1414. /// <param name="buffer">数据</param>
  1415. /// <returns></returns>
  1416. private VerifyDataModel GetVerifyDataAndCheckCaption(byte[] buffer)
  1417. {
  1418. VerifyDataModel verifyData = new VerifyDataModel() { Password = PASSWORD };
  1419. // 使用Span直接操作内存
  1420. Span<byte> span = buffer.AsSpan();
  1421. // 移除事件类型
  1422. span = span.Slice(1);
  1423. // 读取序列号长度
  1424. if (span.IsEmpty) return verifyData;
  1425. int serialNoLength = span[0];
  1426. // 读取序列号
  1427. if (span.Length - 1 < serialNoLength) return verifyData;
  1428. verifyData.SerialNo = SoftBasic.GetAsciiStringRender(span.Slice(1, serialNoLength).ToArray());
  1429. span = span.Slice(1 + serialNoLength);
  1430. // 读取随机码
  1431. if (span.Length < 4) return verifyData;
  1432. verifyData.RandomCode = byteTransform.TransUInt32(span.ToArray(), 0);
  1433. span = span.Slice(4);
  1434. // 读取验证码长度
  1435. if (span.IsEmpty) return verifyData;
  1436. int captchaLength = span[0];
  1437. // 验证验证码
  1438. if (span.Length - 1 < captchaLength) return verifyData;
  1439. verifyData.Captcha = SoftBasic.AsciiBytesToBytes(span.Slice(1, captchaLength).ToArray());
  1440. // 截取剩余数据
  1441. verifyData.Data = span.Slice(captchaLength + 1).ToArray();
  1442. // 校验验证码
  1443. verifyData.IsValid = VerifyCaptcha(verifyData);
  1444. return verifyData;
  1445. }
  1446. /// <summary>
  1447. /// 验证码校验
  1448. /// </summary>
  1449. /// <returns></returns>
  1450. private static bool VerifyCaptcha(VerifyDataModel verifyData)
  1451. {
  1452. byte[] computedHash;
  1453. using (var md5 = MD5.Create())
  1454. {
  1455. computedHash = md5.ComputeHash(Encoding.UTF8.GetBytes(verifyData.SerialNo + verifyData.Password + verifyData.RandomCode));
  1456. }
  1457. var buffer = verifyData.Captcha;
  1458. for (int i = 0; i < 16; i++)
  1459. {
  1460. if (buffer[i] != computedHash[i])
  1461. return false;
  1462. }
  1463. return true;
  1464. }
  1465. ///<summary>
  1466. ///创建数据验证码
  1467. ///</summary>
  1468. /// <returns></returns>
  1469. protected byte[] CreateData(byte eventType, byte[] data, string serialNo)
  1470. {
  1471. using (var md5 = MD5.Create())
  1472. {
  1473. using (var ms = new MemoryStream())
  1474. {
  1475. // 1. 预先计算所有字段的长度
  1476. uint randomCode = (uint)DateTimeOffset.UtcNow.ToUnixTimeSeconds();
  1477. byte[] randomCodeBytes = byteTransform.TransByte(randomCode);
  1478. byte[] hash = md5.ComputeHash(Encoding.ASCII.GetBytes(serialNo + PASSWORD + randomCode));
  1479. byte[] captcha = SoftBasic.BytesToAsciiBytes(hash);
  1480. // 2. 正确计算剩余长度(关键修正点)
  1481. // 剩余长度 = 事件类型(1) + 序列号长度(1) + 序列号数据 + 随机码 + 验证码长度(1) + 验证码 + 用户数据
  1482. short remainingLength = (short)(
  1483. 1 + // eventType
  1484. randomCodeBytes.Length + // 随机码(固定4字节)
  1485. 1 + captcha.Length + // 验证码(长度字节 + 数据)
  1486. data.Length // 用户数据
  1487. );
  1488. // 3. 写入头部(0x30 + 剩余长度)
  1489. ms.WriteByte(0x30);
  1490. if (remainingLength <= 127)
  1491. {
  1492. ms.WriteByte((byte)remainingLength); // 单字节表示
  1493. }
  1494. else
  1495. {
  1496. // 假设byteTransform.TransByte将short转为2字节大端序
  1497. byte[] remainingLengthBytes = byteTransform.TransByte(remainingLength);
  1498. ms.Write(remainingLengthBytes, 0, remainingLengthBytes.Length);
  1499. }
  1500. // 4. 写入各字段(保持原逻辑)
  1501. ms.WriteByte(eventType);
  1502. ms.Write(randomCodeBytes, 0, randomCodeBytes.Length);
  1503. ms.WriteByte((byte)captcha.Length);
  1504. ms.Write(captcha, 0, captcha.Length);
  1505. ms.Write(data, 0, data.Length);
  1506. return ms.ToArray();
  1507. }
  1508. }
  1509. }
  1510. public ushort[][] ParseSensorData(byte[] data, int sensorCount, int sampleCount)
  1511. {
  1512. // 检查数据长度是否匹配
  1513. int expectedLength = sensorCount * sampleCount;
  1514. if (data.Length != expectedLength)
  1515. {
  1516. LogHelper.Error($"数据长度不匹配。预期 {expectedLength} 字节,实际 {data.Length} 字节。");
  1517. return null;
  1518. }
  1519. // 初始化结果列表,每个传感器的数据存储在一个单独的 ushort[]
  1520. ushort[][] sensorDataList = new ushort[sampleCount][];
  1521. for (int i = 0; i < sampleCount; i++)
  1522. {
  1523. sensorDataList[i] = new ushort[sensorCount];
  1524. }
  1525. // 解析数据
  1526. for (int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++)
  1527. {
  1528. for (int sensorIndex = 0; sensorIndex < sensorCount; sensorIndex++)
  1529. {
  1530. // 计算数据在字节数组中的位置
  1531. int dataIndex = (sampleIndex * sensorCount) + sensorIndex;
  1532. // 将 byte 转换为 ushort(直接赋值,因为 byte 可以隐式转换为 ushort)
  1533. sensorDataList[sampleIndex][sensorIndex] = data[dataIndex];
  1534. }
  1535. }
  1536. return sensorDataList;
  1537. }
  1538. /// <summary>
  1539. /// 获取剩余长度
  1540. /// </summary>
  1541. /// <param name="bytes"></param>
  1542. /// <param name="startIndex"></param>
  1543. /// <returns></returns>
  1544. public static (int BytesConsumed, int Length) GetRemainingLength(byte[] bytes)
  1545. {
  1546. if (bytes == null || bytes.Length < 2) return (0, 0);
  1547. int index = 1; // 跳过包类型字节
  1548. int multiplier = 1;
  1549. int value = 0;
  1550. byte encodedByte;
  1551. int bytesConsumed = 0;
  1552. do
  1553. {
  1554. if (index >= bytes.Length) return (0, 0);
  1555. encodedByte = bytes[index];
  1556. value += (encodedByte & 0x7F) * multiplier;
  1557. multiplier *= 128;
  1558. index++;
  1559. bytesConsumed++;
  1560. if (multiplier > 128 * 128 * 128) // 防止溢出
  1561. return (0, 0);
  1562. } while ((encodedByte & 0x80) != 0 && bytesConsumed < 4); // 最多4字节长度
  1563. return (bytesConsumed, value);
  1564. }
  1565. private static (string SerialNo, byte[] Bytes) GetSerialNoAndData(byte[] buffer)
  1566. {
  1567. // 使用Span直接操作内存
  1568. Span<byte> span = buffer.AsSpan();
  1569. // 移除事件类型
  1570. span = span.Slice(1);
  1571. // 读取序列号长度
  1572. if (span.IsEmpty) return (null, null);
  1573. int serialNoLength = span[0];
  1574. // 读取序列号
  1575. if (span.Length - 1 < serialNoLength) return (null, null);
  1576. var serialNo = SoftBasic.GetAsciiStringRender(span.Slice(1, serialNoLength).ToArray());
  1577. buffer = span.Slice(1 + serialNoLength).ToArray();
  1578. return (serialNo, buffer);
  1579. }
  1580. public void Dispose()
  1581. {
  1582. try
  1583. {
  1584. _isRunning = false;
  1585. Thread.Sleep(100);
  1586. if (_listener != null)
  1587. {
  1588. if (_listener.Connected)
  1589. {
  1590. _listener.Shutdown(SocketShutdown.Both);
  1591. }
  1592. _listener.Close();
  1593. _listener.Dispose();
  1594. }
  1595. }
  1596. catch (SocketException ex) when (ex.SocketErrorCode == SocketError.NotConnected)
  1597. {
  1598. _listener?.Dispose();
  1599. }
  1600. catch (Exception ex)
  1601. {
  1602. LogHelper.Error($"停止服务时发生异常: {ex.Message}", ex);
  1603. }
  1604. finally
  1605. {
  1606. _listener = null;
  1607. }
  1608. }
  1609. }
  1610. }