using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using System.Net.Sockets; using System.Text; using EasyTemplate.Tool.Entity; using EasyTemplate.Tool.Entity.App; namespace EasyTemplate.Service { /// /// 数据处理后台服务 /// public class HandleDataService : BackgroundService { private readonly IServiceProvider _serviceProvider; private readonly ILogger _logger; public HandleDataService(IServiceProvider serviceProvider, ILogger logger) { _serviceProvider = serviceProvider; _logger = logger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { _logger.LogInformation("数据处理服务已启动"); while (!stoppingToken.IsCancellationRequested) { try { await ProcessDataAsync(); } catch (Exception ex) { _logger.LogError(ex, "数据处理发生错误"); } await Task.Delay(50, stoppingToken); } _logger.LogInformation("数据处理服务已停止"); } private async Task ProcessDataAsync() { BufferData bd = GlobalTool.g_dataQueue.TryDequeue(out BufferData result) ? result : null; if(bd==null) { return; } //TQC dest-2;source-2;frame-1;length-2(HEX);cmd-1 //VRC 包头(0xfa)+ 目标地址 2+ 源地址 2+ 控制/帧号 1+ 数据长度 2(BCD)+ 命令字 1+ 数据 + CRC 校验 2 if(bd.type == 0) { int datalength = bd.buffer[5] * 256 + bd.buffer[6]; if (datalength + 9 == bd.buffer.Length) { // 计算 crc int packlen = bd.buffer.Length; byte[] tmpbuf = bd.buffer; ushort nSum = GlobalTool.chkcrc(tmpbuf, (ushort)(packlen - 2), 0xA001); ushort newSum = nSum; newSum = (ushort)(newSum / 256 + newSum % 256 * 256); ushort oldSum = BitConverter.ToUInt16(tmpbuf, packlen - 2); if (oldSum == newSum) { _logger.LogDebug("CRC 校验成功"); } else { _logger.LogWarning("crc 校验失败"); return; } } else if (datalength + 9 == bd.buffer.Length + 2) { //旧协议无 crc } else { _logger.LogWarning("数据长度不对"); return; } } else { int datalength = GlobalTool.ConvertBCDToDecimalSingle(bd.buffer[6]) * 100 + GlobalTool.ConvertBCDToDecimalSingle(bd.buffer[7]); if (datalength + 10 == bd.buffer.Length) { } else { _logger.LogWarning("数据长度不对"); return; } } int cmdtype = bd.buffer[7]; int startindex = 8; if (bd.type == 1) { cmdtype = bd.buffer[8]; startindex = 9; } switch (cmdtype) { case 1: filling_nozzleup up = GlobalTool.extractFillingNozzleUP(bd.buffer, startindex); if(GlobalTool.g_mNozzleState.ContainsKey(up.noz)) GlobalTool.g_mNozzleState[up.noz].nozzlestate = GlobalTool.NozzleState_Filling; break; case 2: filling_process process = GlobalTool.extractFillingProcess(bd.buffer, startindex); if(GlobalTool.g_mNozzleState.ContainsKey(process.noz)) { GlobalTool.g_mNozzleState[process.noz].nozzlestate = GlobalTool.NozzleState_Filling; GlobalTool.g_mNozzleState[process.noz].VLR = ((double)process.VLR / 1000).ToString("F2"); } break; case 3: filling_nozzledown down = GlobalTool.extractFillingNozzleDown(bd.buffer, startindex); if(GlobalTool.g_mNozzleState.ContainsKey(down.noz)) GlobalTool.g_mNozzleState[down.noz].nozzlestate = GlobalTool.NozzleState_Idle; break; case 4: filling_record record = GlobalTool.extractFillingRecord(bd.buffer, startindex); if(GlobalTool.g_mNozzleState.ContainsKey(record.noz)) { GlobalTool.g_mNozzleState[record.noz].nozzlestate = GlobalTool.NozzleState_Idle; GlobalTool.g_mNozzleState[record.noz].VLR = ((double)record.VLR / 1000).ToString("F2"); } // 将记录插入到数据库 await InsertRecordToDatabaseAsync(record); break; default: return; } if(bd.type == 0) { var message = Encoding.UTF8.GetString(bd.buffer); byte[] responseData = Encoding.UTF8.GetBytes("Echo: " + message); await bd.udpClient.SendAsync(responseData, responseData.Length, bd.endpoint); } else { var message = Encoding.UTF8.GetString(bd.buffer); byte[] responseData = Encoding.UTF8.GetBytes("Echo: " + message); bd.serialPort.Write(responseData, 0, responseData.Length); } } /// /// 异步插入交易记录到数据库 /// private async Task InsertRecordToDatabaseAsync(filling_record record) { try { // 创建作用域以获取 Scoped 服务 using var scope = _serviceProvider.CreateScope(); var nozzleService = scope.ServiceProvider.GetRequiredService(); // 将 filling_record 转换为 TRecord var tRecord = new TRecord { fip = record.fip, board = record.board, noz = record.noz, liquidVl = record.liquidVL, vaporVl = record.vaporVL, liquidFr = record.liquidFR, vaporFr = record.vaporFR, vlr = record.VLR, vaporPa = record.vaporPA, ttc = record.ttc, vlrBefore = record.VLR_BEFORE, vlrOffset = record.VLR_OFFSET, pwm = record.pwm, tmBegin = ParseDateTime(record.tmBegin), tmEnd = ParseDateTime(record.tmEnd), overproof = record.overproof, uploadflag = record.uploadflag, uploadflag2 = record.uploadflag2, uploadflag3 = record.uploadflag3, downloadflag1 = record.downloadflag1, yz = record.yz, tankpressure = record.tankpressure, refuelingseconds = record.refuelingseconds, errorcontrolvalue = record.errorcontrolvalue, errornum = record.errornum, callbackflag = record.callbackflag, vccerrorinfo = record.vccerrorinfo ?? string.Empty }; if(tRecord.vlr > GlobalTool.vlr_sys_max || tRecord.vlr < GlobalTool.vlr_sys_min) { tRecord.overproof = 1; } if (tRecord.vlr > GlobalTool.vlr_sys_max_alert || tRecord.vlr < GlobalTool.vlr_sys_min_alert) { tRecord.overproof_alert = 1; } if (tRecord.vlr > GlobalTool.vlr_sys_max_gd_zsh || tRecord.vlr < GlobalTool.vlr_sys_min_gd_zsh) { tRecord.overproof_2 = 1; } // 调用 NozzleService 的插入方法 var result = await nozzleService.CreateRecordAsync(tRecord); if (result) { _logger.LogInformation($"成功插入交易记录:油枪{record.noz}, 时间={record.tmEnd}"); } else { _logger.LogWarning($"插入交易记录失败:油枪{record.noz}"); } } catch (Exception ex) { _logger.LogError(ex, $"插入交易记录异常:油枪{record.noz}"); } } /// /// 解析字符串时间为 DateTime /// private DateTime ParseDateTime(string timeStr) { if (string.IsNullOrEmpty(timeStr)) { return DateTime.Now; } // 假设时间格式为 yyyyMMddHHmmss 或类似格式 // 根据实际协议格式调整解析逻辑 if (timeStr.Length >= 14) { if (DateTime.TryParseExact(timeStr, "yyyyMMddHHmmss", null, System.Globalization.DateTimeStyles.None, out var result)) { return result; } } // 如果解析失败,返回当前时间 return DateTime.Now; } } }