HandleData.cs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. using Microsoft.Extensions.DependencyInjection;
  2. using Microsoft.Extensions.Hosting;
  3. using Microsoft.Extensions.Logging;
  4. using System.Net.Sockets;
  5. using System.Text;
  6. using EasyTemplate.Tool.Entity;
  7. using EasyTemplate.Tool.Entity.App;
  8. namespace EasyTemplate.Service
  9. {
  10. /// <summary>
  11. /// 数据处理后台服务
  12. /// </summary>
  13. public class HandleDataService : BackgroundService
  14. {
  15. private readonly IServiceProvider _serviceProvider;
  16. private readonly ILogger<HandleDataService> _logger;
  17. public HandleDataService(IServiceProvider serviceProvider, ILogger<HandleDataService> logger)
  18. {
  19. _serviceProvider = serviceProvider;
  20. _logger = logger;
  21. }
  22. protected override async Task ExecuteAsync(CancellationToken stoppingToken)
  23. {
  24. _logger.LogInformation("数据处理服务已启动");
  25. while (!stoppingToken.IsCancellationRequested)
  26. {
  27. try
  28. {
  29. await ProcessDataAsync();
  30. }
  31. catch (Exception ex)
  32. {
  33. _logger.LogError(ex, "数据处理发生错误");
  34. }
  35. await Task.Delay(50, stoppingToken);
  36. }
  37. _logger.LogInformation("数据处理服务已停止");
  38. }
  39. private async Task ProcessDataAsync()
  40. {
  41. BufferData bd = GlobalTool.g_dataQueue.TryDequeue(out BufferData result) ? result : null;
  42. if(bd==null)
  43. {
  44. return;
  45. }
  46. //TQC dest-2;source-2;frame-1;length-2(HEX);cmd-1
  47. //VRC 包头(0xfa)+ 目标地址 2+ 源地址 2+ 控制/帧号 1+ 数据长度 2(BCD)+ 命令字 1+ 数据 + CRC 校验 2
  48. if(bd.type == 0)
  49. {
  50. int datalength = bd.buffer[5] * 256 + bd.buffer[6];
  51. if (datalength + 9 == bd.buffer.Length)
  52. {
  53. // 计算 crc
  54. int packlen = bd.buffer.Length;
  55. byte[] tmpbuf = bd.buffer;
  56. ushort nSum = GlobalTool.chkcrc(tmpbuf, (ushort)(packlen - 2), 0xA001);
  57. ushort newSum = nSum;
  58. newSum = (ushort)(newSum / 256 + newSum % 256 * 256);
  59. ushort oldSum = BitConverter.ToUInt16(tmpbuf, packlen - 2);
  60. if (oldSum == newSum)
  61. {
  62. _logger.LogDebug("CRC 校验成功");
  63. }
  64. else
  65. {
  66. _logger.LogWarning("crc 校验失败");
  67. return;
  68. }
  69. }
  70. else if (datalength + 9 == bd.buffer.Length + 2)
  71. {
  72. //旧协议无 crc
  73. }
  74. else
  75. {
  76. _logger.LogWarning("数据长度不对");
  77. return;
  78. }
  79. }
  80. else
  81. {
  82. int datalength = GlobalTool.ConvertBCDToDecimalSingle(bd.buffer[6]) * 100 + GlobalTool.ConvertBCDToDecimalSingle(bd.buffer[7]);
  83. if (datalength + 10 == bd.buffer.Length)
  84. {
  85. }
  86. else
  87. {
  88. _logger.LogWarning("数据长度不对");
  89. return;
  90. }
  91. }
  92. int cmdtype = bd.buffer[7];
  93. int startindex = 8;
  94. if (bd.type == 1)
  95. {
  96. cmdtype = bd.buffer[8];
  97. startindex = 9;
  98. }
  99. switch (cmdtype)
  100. {
  101. case 1:
  102. filling_nozzleup up = GlobalTool.extractFillingNozzleUP(bd.buffer, startindex);
  103. if(GlobalTool.g_mNozzleState.ContainsKey(up.noz))
  104. GlobalTool.g_mNozzleState[up.noz].nozzlestate = GlobalTool.NozzleState_Filling;
  105. break;
  106. case 2:
  107. filling_process process = GlobalTool.extractFillingProcess(bd.buffer, startindex);
  108. if(GlobalTool.g_mNozzleState.ContainsKey(process.noz))
  109. {
  110. GlobalTool.g_mNozzleState[process.noz].nozzlestate = GlobalTool.NozzleState_Filling;
  111. GlobalTool.g_mNozzleState[process.noz].VLR = ((double)process.VLR / 1000).ToString("F2");
  112. }
  113. break;
  114. case 3:
  115. filling_nozzledown down = GlobalTool.extractFillingNozzleDown(bd.buffer, startindex);
  116. if(GlobalTool.g_mNozzleState.ContainsKey(down.noz))
  117. GlobalTool.g_mNozzleState[down.noz].nozzlestate = GlobalTool.NozzleState_Idle;
  118. break;
  119. case 4:
  120. filling_record record = GlobalTool.extractFillingRecord(bd.buffer, startindex);
  121. if(GlobalTool.g_mNozzleState.ContainsKey(record.noz))
  122. {
  123. GlobalTool.g_mNozzleState[record.noz].nozzlestate = GlobalTool.NozzleState_Idle;
  124. GlobalTool.g_mNozzleState[record.noz].VLR = ((double)record.VLR / 1000).ToString("F2");
  125. }
  126. // 将记录插入到数据库
  127. await InsertRecordToDatabaseAsync(record);
  128. break;
  129. default:
  130. return;
  131. }
  132. if(bd.type == 0)
  133. {
  134. var message = Encoding.UTF8.GetString(bd.buffer);
  135. byte[] responseData = Encoding.UTF8.GetBytes("Echo: " + message);
  136. await bd.udpClient.SendAsync(responseData, responseData.Length, bd.endpoint);
  137. }
  138. else
  139. {
  140. var message = Encoding.UTF8.GetString(bd.buffer);
  141. byte[] responseData = Encoding.UTF8.GetBytes("Echo: " + message);
  142. bd.serialPort.Write(responseData, 0, responseData.Length);
  143. }
  144. }
  145. /// <summary>
  146. /// 异步插入交易记录到数据库
  147. /// </summary>
  148. private async Task InsertRecordToDatabaseAsync(filling_record record)
  149. {
  150. try
  151. {
  152. // 创建作用域以获取 Scoped 服务
  153. using var scope = _serviceProvider.CreateScope();
  154. var nozzleService = scope.ServiceProvider.GetRequiredService<NozzleService>();
  155. // 将 filling_record 转换为 TRecord
  156. var tRecord = new TRecord
  157. {
  158. fip = record.fip,
  159. board = record.board,
  160. noz = record.noz,
  161. liquidVl = record.liquidVL,
  162. vaporVl = record.vaporVL,
  163. liquidFr = record.liquidFR,
  164. vaporFr = record.vaporFR,
  165. vlr = record.VLR,
  166. vaporPa = record.vaporPA,
  167. ttc = record.ttc,
  168. vlrBefore = record.VLR_BEFORE,
  169. vlrOffset = record.VLR_OFFSET,
  170. pwm = record.pwm,
  171. tmBegin = ParseDateTime(record.tmBegin),
  172. tmEnd = ParseDateTime(record.tmEnd),
  173. overproof = record.overproof,
  174. uploadflag = record.uploadflag,
  175. uploadflag2 = record.uploadflag2,
  176. uploadflag3 = record.uploadflag3,
  177. downloadflag1 = record.downloadflag1,
  178. yz = record.yz,
  179. tankpressure = record.tankpressure,
  180. refuelingseconds = record.refuelingseconds,
  181. errorcontrolvalue = record.errorcontrolvalue,
  182. errornum = record.errornum,
  183. callbackflag = record.callbackflag,
  184. vccerrorinfo = record.vccerrorinfo ?? string.Empty
  185. };
  186. // 调用 NozzleService 的插入方法
  187. var result = await nozzleService.CreateRecordAsync(tRecord);
  188. if (result)
  189. {
  190. _logger.LogInformation($"成功插入交易记录:油枪{record.noz}, 时间={record.tmEnd}");
  191. }
  192. else
  193. {
  194. _logger.LogWarning($"插入交易记录失败:油枪{record.noz}");
  195. }
  196. }
  197. catch (Exception ex)
  198. {
  199. _logger.LogError(ex, $"插入交易记录异常:油枪{record.noz}");
  200. }
  201. }
  202. /// <summary>
  203. /// 解析字符串时间为 DateTime
  204. /// </summary>
  205. private DateTime ParseDateTime(string timeStr)
  206. {
  207. if (string.IsNullOrEmpty(timeStr))
  208. {
  209. return DateTime.Now;
  210. }
  211. // 假设时间格式为 yyyyMMddHHmmss 或类似格式
  212. // 根据实际协议格式调整解析逻辑
  213. if (timeStr.Length >= 14)
  214. {
  215. if (DateTime.TryParseExact(timeStr, "yyyyMMddHHmmss", null, System.Globalization.DateTimeStyles.None, out var result))
  216. {
  217. return result;
  218. }
  219. }
  220. // 如果解析失败,返回当前时间
  221. return DateTime.Now;
  222. }
  223. }
  224. }