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;
}
}
}