UdpListenerService.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. using AntDesign;
  2. using EasyTemplate.Tool;
  3. using EasyTemplate.Tool.Entity;
  4. using Masuit.Tools;
  5. using Microsoft.AspNetCore.Components;
  6. using Microsoft.Extensions.Hosting;
  7. using Microsoft.Extensions.Logging;
  8. using OneOf.Types;
  9. using SqlSugar;
  10. using System.Globalization;
  11. using System.Net.Sockets;
  12. using System.Reflection.Emit;
  13. using System.Runtime.InteropServices;
  14. using System.Security.Cryptography;
  15. using System.Text;
  16. using System.Xml.Linq;
  17. using static System.Runtime.InteropServices.JavaScript.JSType;
  18. namespace EasyTemplate.Service
  19. {
  20. public class UdpListenerService : IHostedService
  21. {
  22. private readonly ILogger<UdpListenerService> _logger;
  23. private UdpClient? _udpClient;
  24. public static List<string> ReceivedMessages { get; } = new();
  25. public Dictionary<int, NozzleState> g_mNozzleState = new Dictionary<int, NozzleState>();
  26. /// <summary>
  27. /// 注入实例
  28. /// </summary>
  29. [Inject] private SqlSugarRepository<TRecord> _RepoRecord { get; set; }
  30. [Inject] private SqlSugarRepository<TProduct> _Repository { get; set; }
  31. public UdpListenerService(ILogger<UdpListenerService> logger)
  32. {
  33. _logger = logger;
  34. }
  35. public string GetUdpData()
  36. {
  37. return "";
  38. }
  39. public Dictionary<int, NozzleState> GetNozzleState()
  40. {
  41. return g_mNozzleState;
  42. }
  43. public int getbufferdata(byte[] Buffer, ref int startIndex, int length)
  44. {
  45. if (startIndex + length > Buffer.Length)
  46. {
  47. return 0;
  48. }
  49. byte[] segment = new byte[length];
  50. Array.Copy(Buffer, startIndex, segment, 0, length);
  51. startIndex += length;
  52. int val = Tool.BytesToInt(segment);
  53. return val;
  54. }
  55. public Task StartAsync(CancellationToken cancellationToken)
  56. {
  57. _udpClient = new UdpClient(8080); // 监听8080端口
  58. _logger.LogInformation("开始监听UDP端口 8080");
  59. for (int i = 0; i < 40; i++)
  60. {
  61. NozzleState ns = new NozzleState();
  62. ns.noz = i + 1;
  63. ns.warnstate = i % 3;
  64. ns.oil = i % 2 == 0 ? "92#" : "95#";
  65. g_mNozzleState.Add(ns.noz, ns);
  66. }
  67. Task.Run(async () =>
  68. {
  69. while (!cancellationToken.IsCancellationRequested)
  70. {
  71. try
  72. {
  73. var result = await _udpClient.ReceiveAsync(cancellationToken);
  74. var message = Encoding.UTF8.GetString(result.Buffer);
  75. //dest-2;source-2;frame-1;length-2;cmd-1
  76. int datalength = result.Buffer[5] * 256 + result.Buffer[6];
  77. if (datalength + 9 == result.Buffer.Length)
  78. {
  79. // 计算crc
  80. int packlen = result.Buffer.Length;
  81. byte[] tmpbuf = result.Buffer;
  82. ushort nSum = Tool.chkcrc(tmpbuf, (ushort)(packlen - 2), 0xA001);
  83. ushort newSum = nSum;
  84. newSum = (ushort)(newSum / 256 + newSum % 256 * 256);
  85. ushort oldSum = BitConverter.ToUInt16(tmpbuf, packlen - 2);
  86. if (oldSum == newSum)
  87. {
  88. Console.WriteLine("CRC校验成功");
  89. }
  90. else
  91. {
  92. Console.WriteLine("crc校验失败");
  93. continue;
  94. }
  95. }
  96. else if (datalength + 9 == result.Buffer.Length + 2)
  97. {
  98. //旧协议无crc
  99. }
  100. else
  101. {
  102. continue;
  103. }
  104. int cmdtype = result.Buffer[7];
  105. int startindex = 8;
  106. switch (cmdtype)
  107. {
  108. case 1:
  109. filling_nozzleup up = extractFillingNozzleUP(result.Buffer, startindex);
  110. g_mNozzleState[up.noz].nozzlestate = Tool.NozzleState_Filling;
  111. break;
  112. case 2:
  113. filling_process process = extractFillingProcess(result.Buffer, startindex);
  114. g_mNozzleState[process.noz].nozzlestate = Tool.NozzleState_Filling;
  115. g_mNozzleState[process.noz].VLR = ((double)process.VLR / 1000).ToString("F2");
  116. break;
  117. case 3:
  118. filling_nozzledown down = extractFillingNozzleDown(result.Buffer, startindex);
  119. g_mNozzleState[down.noz].nozzlestate = Tool.NozzleState_Idle;
  120. break;
  121. case 4:
  122. TRecord record = extractFillingRecord(result.Buffer, startindex);
  123. g_mNozzleState[record.noz].nozzlestate = Tool.NozzleState_Idle;
  124. g_mNozzleState[record.noz].VLR = ((double)record.vlr / 1000).ToString("F2");
  125. var con = Sql.Connect();
  126. var res = con.Insertable<TRecord>(record).ExecuteCommand();
  127. // RefAsync<int> total = 0;
  128. //var s = _Repository.AsQueryable().Where(x => x.Id == record.fip).FirstAsync();
  129. // var res = await _RepoRecord.InsertAsync(record);
  130. break;
  131. default:
  132. continue;
  133. }
  134. string result1 = string.Join(", ", result.Buffer);
  135. lock (ReceivedMessages)
  136. {
  137. ReceivedMessages.Add($"{DateTime.Now:HH:mm:ss} - {message}");
  138. if (ReceivedMessages.Count > 100) ReceivedMessages.RemoveAt(0);
  139. }
  140. _logger.LogInformation($"接收到消息: {message}");
  141. // Echo back
  142. byte[] responseData = Encoding.UTF8.GetBytes("Echo: " + message);
  143. await _udpClient.SendAsync(responseData, responseData.Length, result.RemoteEndPoint);
  144. }
  145. catch (ObjectDisposedException) when (cancellationToken.IsCancellationRequested)
  146. {
  147. break;
  148. }
  149. catch (Exception ex)
  150. {
  151. _logger.LogError(ex, "接收UDP数据出错");
  152. }
  153. }
  154. }, cancellationToken);
  155. return Task.CompletedTask;
  156. }
  157. public Task StopAsync(CancellationToken cancellationToken)
  158. {
  159. _udpClient?.Close();
  160. _logger.LogInformation("停止监听UDP端口");
  161. return Task.CompletedTask;
  162. }
  163. public filling_nozzleup extractFillingNozzleUP(byte[] Buffer, int startIndex)
  164. {
  165. filling_nozzleup data = new filling_nozzleup();
  166. BufferHandler handler = new BufferHandler(Buffer, startIndex);
  167. data.board = handler.getData(1);
  168. data.noz = handler.getData(1);
  169. data.fip = data.board;
  170. data.time = handler.getDataString_BCD(7);
  171. return data;
  172. }
  173. public filling_nozzledown extractFillingNozzleDown(byte[] Buffer, int startIndex)
  174. {
  175. filling_nozzledown data = new filling_nozzledown();
  176. BufferHandler handler = new BufferHandler(Buffer, startIndex);
  177. data.board = handler.getData(1);
  178. data.noz = handler.getData(1);
  179. data.fip = data.board;
  180. data.time = handler.getDataString_BCD(7);
  181. return data;
  182. }
  183. public filling_process extractFillingProcess(byte[] Buffer, int startIndex)
  184. {
  185. filling_process data = new filling_process();
  186. BufferHandler handler = new BufferHandler(Buffer, startIndex);
  187. data.board = handler.getData(1);
  188. data.noz = handler.getData(1);
  189. data.fip = data.board;
  190. data.liquidVL = handler.getData(3);
  191. data.vaporVL = handler.getData(3);
  192. data.vaporFR = handler.getData(2);
  193. data.VLR = handler.getData(2);
  194. data.vaporPA = handler.getData(2);
  195. data.errornum = handler.getData(2);
  196. data.liquidFR = handler.getData(2);
  197. data.pwm = handler.getData(2);
  198. data.current = handler.getData(2);
  199. return data;
  200. }
  201. public TRecord extractFillingRecord(byte[] Buffer, int startIndex)
  202. {
  203. int bufferlen = Buffer.Length;
  204. TRecord data = new TRecord();
  205. BufferHandler handler = new BufferHandler(Buffer, startIndex);
  206. data.board = handler.getData(1);
  207. data.noz = handler.getData(1);
  208. data.fip = data.board;
  209. if (bufferlen == 22)//兼容旧协议,解析顺序不同
  210. {
  211. data.tmEnd = DateTime.Now;
  212. }
  213. else
  214. {
  215. data.ttc = handler.getData(4);
  216. }
  217. data.liquidVl = handler.getData(3);
  218. data.liquidFr = handler.getData(2);
  219. data.vaporVl = handler.getData(3);
  220. data.vaporFr = handler.getData(2);
  221. data.vlr = handler.getData(2);
  222. string s1 = handler.getDataString_BCD(7);
  223. if (s1 != "")
  224. {
  225. data.tmBegin = DateTime.ParseExact(s1, "yyyyMMddHHmmss", CultureInfo.InvariantCulture);
  226. }
  227. string s2 = handler.getDataString_BCD(7);
  228. if (s2 != "")
  229. {
  230. data.tmEnd = DateTime.ParseExact(s2, "yyyyMMddHHmmss", CultureInfo.InvariantCulture);
  231. }
  232. data.errornum = handler.getData(2);
  233. data.vaporPa = handler.getData(2);
  234. data.pwm = handler.getData(2);
  235. data.vccerrorinfo = "";
  236. return data;
  237. }
  238. public class BufferHandler
  239. {
  240. public byte[] buffer = Array.Empty<byte>();
  241. public int startIndex = 0;
  242. public int length = 0;
  243. public BufferHandler(byte[] buf, int startindex = 0)
  244. {
  245. buffer = buf;
  246. startIndex = startindex;
  247. length = buf.Length;
  248. }
  249. public string getDataString_BCD(int len)
  250. {
  251. if (startIndex + len > length)
  252. {
  253. return "";
  254. }
  255. byte[] segment = new byte[len];
  256. Array.Copy(buffer, startIndex, segment, 0, len);
  257. string result = Tool.BytesToBcd(segment);
  258. startIndex += len;
  259. return result;
  260. }
  261. public int getData(int len)
  262. {
  263. if (startIndex + len > length)
  264. {
  265. return 0;
  266. }
  267. byte[] segment = new byte[len];
  268. Array.Copy(buffer, startIndex, segment, 0, len);
  269. int val = Tool.BytesToInt(segment);
  270. startIndex += len;
  271. return val;
  272. }
  273. }
  274. //public filling_process struct2filling(s_vr_status cmd)
  275. //{
  276. // filling_process data = new filling_process();
  277. // //data.liquidVL = (uint)(st.liqvol[0] << 16 | st.liqvol[1] << 8 | st.liqvol[2]);
  278. // data.fip = cmd.fip;
  279. // data.noz = cmd.noz;
  280. // data.liquidVL = Tool.BytesToInt(cmd.liqvol);
  281. // data.liquidFR = Tool.BytesToInt(cmd.liqflow);
  282. // data.vaporFR = Tool.BytesToInt(cmd.vapflow);
  283. // data.vaporVL = Tool.BytesToInt(cmd.vapvol);
  284. // data.VLR = Tool.BytesToInt(cmd.vlr);
  285. // data.vaporPA = Tool.BytesToInt(cmd.press);
  286. // data.pwm = Tool.BytesToInt(cmd.pwm);
  287. // data.current = Tool.BytesToInt(cmd.current);
  288. // return data;
  289. //}
  290. public class NozzleState
  291. {
  292. public int noz = 0;
  293. public string VLR = "0";
  294. public string oil = string.Empty;
  295. public int nozzlestate = Tool.NozzleState_Offline;
  296. public int warnstate = Tool.WarningState_Normal;
  297. }
  298. public struct filling_nozzleup
  299. {
  300. public int fip;
  301. public int board;
  302. public int noz;
  303. public string time;
  304. /* byte cmd;
  305. byte fip;
  306. byte noz;
  307. byte time[7];
  308. byte product[4];*/
  309. /* auto& cmd = src->data.CMD1;
  310. dst.target = cmd.noz;
  311. _ubcd_to_str (dst.time, sizeof dst.time, cmd.time, sizeof cmd.time);
  312. _ubcd_to_str (dst.product, sizeof dst.product, cmd.product, sizeof cmd.product);*/
  313. }
  314. public struct filling_nozzledown
  315. {
  316. public int fip;
  317. public int board;
  318. public int noz;
  319. public string time;
  320. }
  321. public struct filling_record
  322. {
  323. public int fip;
  324. public int board;
  325. public int noz;
  326. public int liquidVL;
  327. public int vaporVL;
  328. public int liquidFR;
  329. public int vaporFR;
  330. public int VLR;
  331. public int vaporPA;
  332. public int ttc;
  333. public int VLR_BEFORE;
  334. public int VLR_OFFSET;
  335. public int pwm;
  336. public string tmBegin;
  337. public string tmEnd;
  338. public int overproof;
  339. public int uploadflag;
  340. public int uploadflag2;
  341. public int uploadflag3;
  342. public int downloadflag1;
  343. public int yz;
  344. public int tankpressure;
  345. public int refuelingseconds;
  346. public int errorcontrolvalue;
  347. public int errornum;
  348. public int callbackflag;
  349. public string vccerrorinfo;
  350. }
  351. public struct filling_process
  352. {
  353. public int fip;
  354. public int board;
  355. public int noz;
  356. public int liquidVL;
  357. public int vaporVL;
  358. public int liquidFR;
  359. public int vaporFR;
  360. public int VLR;
  361. public int vaporPA;
  362. public int ttc;
  363. public int VLR_BEFORE;
  364. public int VLR_OFFSET;
  365. public int errornum;
  366. public int pwm;
  367. public int current;
  368. }
  369. //[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
  370. //public struct s_vr_status
  371. //{
  372. // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
  373. // public byte[] dest;
  374. // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
  375. // public byte[] source;
  376. // public byte frame;
  377. // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
  378. // public byte[] length;
  379. // public byte cmd;
  380. // public byte fip;
  381. // public byte noz;
  382. // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
  383. // public byte[] liqvol;
  384. // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
  385. // public byte[] vapvol;
  386. // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
  387. // public byte[] vapflow;
  388. // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
  389. // public byte[] vlr;
  390. // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
  391. // public byte[] press;
  392. // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
  393. // public byte[] errornum;
  394. // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
  395. // public byte[] liqflow;
  396. // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
  397. // public byte[] pwm;
  398. // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
  399. // public byte[] current;
  400. // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
  401. // public byte[] crc;
  402. //}
  403. }
  404. }