DFS_Shuo_Chen 1 mēnesi atpakaļ
vecāks
revīzija
5397554b4c

+ 1 - 0
.gitignore

@@ -21,3 +21,4 @@ bin-release/
 EasyTemplate.Blazor.Web/publish/
 tmptest/.vs/
 文档/~$重构时间评估.xlsx
+tmptestproject/.vs/

+ 4 - 3
EasyTemplate.Blazor.Web/Common/TheRegister.cs

@@ -182,13 +182,14 @@ public static class TheRegister
         builder.Services.AddHostedService<UdpListenerService>();
 
         builder.Services.AddHostedService<SerialPortBackgroundService>();
+        
+        // 注册数据处理后台服务
+        builder.Services.AddHostedService<HandleDataService>();
 
-        builder.Services.AddSingleton<HandleData>();
-        builder.Services.BuildServiceProvider().GetService<HandleData>();
+        builder.Services.AddScoped<NozzleService>();
 
         // builder.Services.AddSingleton<DB>();
 
-        builder.Services.AddScoped<NozzleService>();
 
         builder.Services.AddScoped<Init>();
 

+ 211 - 130
EasyTemplate.Service/HandleData.cs

@@ -1,167 +1,248 @@
-using AntDesign;
-using Microsoft.AspNetCore.Components;
+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 HandleData
+    /// <summary>
+    /// 数据处理后台服务
+    /// </summary>
+    public class HandleDataService : BackgroundService
     {
-        private Thread _thread;
-       // [Inject] public UdpListenerService udpclient { get; set; }
-        //public UdpListenerService udpclient { get; set; } = default!;
-
-
-        //private readonly UdpListenerService _udpclient;
+        private readonly IServiceProvider _serviceProvider;
+        private readonly ILogger<HandleDataService> _logger;
 
-     
-
-        public HandleData()//UdpListenerService myService)
+        public HandleDataService(IServiceProvider serviceProvider, ILogger<HandleDataService> logger)
         {
-            //_udpclient = myService;
-            // 初始化线程,但不立即启动
-            _thread = new Thread(new ThreadStart(Loop));
-            _thread.IsBackground = true; // 设置线程为后台线程,程序结束时自动结束
-            _thread.Start(); // 启动线程
+            _serviceProvider = serviceProvider;
+            _logger = logger;
         }
 
-        private void Loop()
+        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
         {
-            while (true) // 无限循环
+            _logger.LogInformation("数据处理服务已启动");
+            
+            while (!stoppingToken.IsCancellationRequested)
             {
-                Console.WriteLine("Looping..."); // 执行一些任务
-
                 try
                 {
-                    BufferData bd = GlobalTool.g_dataQueue.TryDequeue(out BufferData result) ? result : null;
-                    if(bd==null)
-                    {
-                        continue;
-                    }
-
+                    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
+            //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)
+            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)
                     {
-                        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)
-                            {
-                                Console.WriteLine("CRC校验成功");
-                            }
-                            else
-                            {
-                                Console.WriteLine("crc校验失败");
-                                continue;
-                            }
-                        }
-                        else if (datalength + 9 == bd.buffer.Length + 2)
-                        {
-                            //旧协议无crc
-                        }
-                        else
-                        {
-                            Console.WriteLine("数据长度不对");
-                            continue;
-                        }
+                        _logger.LogDebug("CRC 校验成功");
                     }
                     else
                     {
-                        int datalength = GlobalTool.ConvertBCDToDecimalSingle(bd.buffer[6]) * 100 + GlobalTool.ConvertBCDToDecimalSingle(bd.buffer[7]);
-                        if (datalength + 10 == bd.buffer.Length)
-                        {
-
-                        }
-                        else
-                        {
-                            Console.WriteLine("数据长度不对");
-                            continue;
-                        }
+                        _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;
+            }
 
-
-                    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);
-                            GlobalTool.g_mNozzleState[up.noz].nozzlestate = GlobalTool.NozzleState_Filling;
-                            break;
-                        case 2:
-                            filling_process process = GlobalTool.extractFillingProcess(bd.buffer, startindex);
-                            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);
-                            GlobalTool.g_mNozzleState[down.noz].nozzlestate = GlobalTool.NozzleState_Idle;
-                            break;
-                        case 4:
-                            filling_record record = GlobalTool.extractFillingRecord(bd.buffer, startindex);
-                            GlobalTool.g_mNozzleState[record.noz].nozzlestate = GlobalTool.NozzleState_Idle;
-                            GlobalTool.g_mNozzleState[record.noz].VLR = ((double)record.VLR / 1000).ToString("F2");
-                            break;
-
-
-
-                        default:
-                            continue;
-                    }
-
-                    if(bd.type == 0)
+            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))
                     {
-                        var message = Encoding.UTF8.GetString(bd.buffer);
-                        //_logger.LogInformation($"接收到消息: {result.Buffer.ToString()}\r\n");
-
-                        byte[] responseData = Encoding.UTF8.GetBytes("Echo: " + message);
-                        bd.udpClient.SendAsync(responseData, responseData.Length, bd.endpoint);
+                        GlobalTool.g_mNozzleState[process.noz].nozzlestate = GlobalTool.NozzleState_Filling;
+                        GlobalTool.g_mNozzleState[process.noz].VLR = ((double)process.VLR / 1000).ToString("F2");
                     }
-                    else
+                    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))
                     {
-                        var message = Encoding.UTF8.GetString(bd.buffer);
-                        //_logger.LogInformation($"接收到消息: {result.Buffer.ToString()}\r\n");
-
-                        byte[] responseData = Encoding.UTF8.GetBytes("Echo: " + message);
-                        bd.serialPort.Write(responseData, 0, responseData.Length);
-
+                        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);
+            }
+        }
+        
+        /// <summary>
+        /// 异步插入交易记录到数据库
+        /// </summary>
+        private async Task InsertRecordToDatabaseAsync(filling_record record)
+        {
+            try
+            {
+                // 创建作用域以获取 Scoped 服务
+                using var scope = _serviceProvider.CreateScope();
+                var nozzleService = scope.ServiceProvider.GetRequiredService<NozzleService>();
+                
+                // 将 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
+                };
+                
+                // 调用 NozzleService 的插入方法
+                var result = await nozzleService.CreateRecordAsync(tRecord);
+                
+                if (result)
+                {
+                    _logger.LogInformation($"成功插入交易记录:油枪{record.noz}, 时间={record.tmEnd}");
                 }
-                catch(Exception e)
+                else
                 {
-
+                    _logger.LogWarning($"插入交易记录失败:油枪{record.noz}");
                 }
-
-
-
-                Thread.Sleep(50); 
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError(ex, $"插入交易记录异常:油枪{record.noz}");
             }
         }
+        
+        /// <summary>
+        /// 解析字符串时间为 DateTime
+        /// </summary>
+        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;
+        }
     }
 }
-

+ 154 - 1
EasyTemplate.Service/NozzleService.cs

@@ -17,13 +17,18 @@ namespace EasyTemplate.Service
         private readonly SqlSugarRepository<TEngine> _engine;
         private readonly SqlSugarRepository<TBoard> _board;
         private readonly SqlSugarRepository<TNozzle> _nozzle;
+        private readonly SqlSugarRepository<TRecord> _record;
+        private readonly SqlSugarRepository<TPrewarning> _prewarning;
 
 
-        public NozzleService(SqlSugarRepository<TEngine> engine, SqlSugarRepository<TBoard> board, SqlSugarRepository<TNozzle> nozzle)
+        public NozzleService(SqlSugarRepository<TEngine> engine, SqlSugarRepository<TBoard> board, SqlSugarRepository<TNozzle> nozzle, 
+            SqlSugarRepository<TRecord> record, SqlSugarRepository<TPrewarning> prewarning)
         {
             _engine = engine;
             _board = board;
             _nozzle = nozzle;
+            _record = record;
+            _prewarning = prewarning;
         }
 
         // Engine操作
@@ -148,5 +153,153 @@ namespace EasyTemplate.Service
 
             return engines;
         }
+        
+        // ===== TRecord 操作 =====
+        
+        /// <summary>
+        /// 插入交易记录,并自动处理预警告数据
+        /// </summary>
+        public async Task<bool> CreateRecordAsync(TRecord record)
+        {
+            try
+            {
+                // 插入记录
+                var result = await _record.InsertAsync(record);
+                
+                if (result)
+                {
+                    // 自动处理预警告数据
+                    await ProcessPrewarningAsync(record);
+                }
+                
+                return result;
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"插入交易记录失败:{ex.Message}");
+                return false;
+            }
+        }
+        
+        /// <summary>
+        /// 根据条件查询交易记录
+        /// </summary>
+        public async Task<List<TRecord>> GetRecordsByDateAndNozzleAsync(DateTime beginDate, DateTime endDate, int nozzleId)
+        {
+            return await _record.AsQueryable()
+                .Where(r => r.tmBegin >= beginDate && r.tmEnd <= endDate && r.noz == nozzleId)
+                .ToListAsync();
+        }
+        
+        /// <summary>
+        /// 获取所有交易记录
+        /// </summary>
+        public async Task<List<TRecord>> GetAllRecordsAsync()
+        {
+            return await _record.AsQueryable().ToListAsync();
+        }
+        
+        // ===== TPrewarning 操作 =====
+        
+        /// <summary>
+        /// 插入预警告记录
+        /// </summary>
+        public async Task<bool> CreatePrewarningAsync(TPrewarning prewarning)
+        {
+            return await _prewarning.InsertAsync(prewarning);
+        }
+        
+        /// <summary>
+        /// 更新预警告记录
+        /// </summary>
+        public async Task<bool> UpdatePrewarningAsync(TPrewarning prewarning)
+        {
+            return await _prewarning.UpdateAsync(prewarning) == true;
+        }
+        
+        /// <summary>
+        /// 根据日期和油枪查询预警告记录
+        /// </summary>
+        public async Task<TPrewarning> GetPrewarningByDateAndNozzleAsync(DateOnly date, int nozzleId)
+        {
+            return await _prewarning.AsQueryable()
+                .Where(p => p.date == date && p.nozzle == nozzleId)
+                .FirstAsync();
+        }
+        
+        /// <summary>
+        /// 获取所有预警告记录
+        /// </summary>
+        public async Task<List<TPrewarning>> GetAllPrewarningsAsync()
+        {
+            return await _prewarning.AsQueryable().ToListAsync();
+        }
+        
+        // ===== 私有辅助方法 =====
+        
+        /// <summary>
+        /// 处理预警告数据的自动插入或更新逻辑
+        /// </summary>
+        private async Task ProcessPrewarningAsync(TRecord record)
+        {
+            try
+            {
+                // 从 tmEnd 提取日期
+                var date = DateOnly.FromDateTime(record.tmEnd);
+                var nozzleId = record.noz;
+                
+                // 查询是否已存在当天的记录
+                var existingPrewarning = await GetPrewarningByDateAndNozzleAsync(date, nozzleId);
+                
+                if (existingPrewarning == null)
+                {
+                    // 不存在则插入新记录
+                    var newPrewarning = new TPrewarning
+                    {
+                        date = date,
+                        nozzle = nozzleId,
+                        overproof = record.overproof > 0 ? 1 : 0, // 根据 overproof 设置
+                        total = 1, // 首次记录,总数为 1
+                        overproofrate = 0, // 初始超标率
+                        overproof_alert = 0,
+                        overproof_2 = 0,
+                        overproofrate_2 = 0,
+                        continueoverproof = record.overproof > 0 ? 1 : 0
+                    };
+                    
+                    await CreatePrewarningAsync(newPrewarning);
+                    Console.WriteLine($"已为新油枪 {nozzleId} 创建预警告记录,日期:{date}");
+                }
+                else
+                {
+                    // 存在则更新现有记录
+                    // 在这里进行自定义修改逻辑
+                    if (record.overproof > 0)
+                    {
+                        existingPrewarning.overproof++;
+                        existingPrewarning.continueoverproof++;
+                    }
+                    
+                    existingPrewarning.total++;
+                    
+                    // 计算超标率
+                    if (existingPrewarning.total > 0)
+                    {
+                        existingPrewarning.overproofrate = (existingPrewarning.overproof * 100) / existingPrewarning.total;
+                    }
+                    
+                    // 可以在这里添加更多的自定义修改逻辑
+                    // 例如:根据其他字段更新 overproof_2, overproofrate_2 等
+                    
+                    await UpdatePrewarningAsync(existingPrewarning);
+                    Console.WriteLine($"已更新油枪 {nozzleId} 的预警告记录,日期:{date}");
+                }
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"处理预警告数据失败:{ex.Message}");
+                // 不抛出异常,避免影响主流程
+            }
+        }
     }
 }

+ 28 - 0
EasyTemplate.Tool/Entity/App/TPrewarning.cs

@@ -0,0 +1,28 @@
+using Microsoft.EntityFrameworkCore.Metadata.Internal;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace EasyTemplate.Tool.Entity.App
+{
+    [SugarTable("t_prewarning")]
+    public class TPrewarning
+    {
+        [SugarColumn(IsPrimaryKey = true)]
+        public DateOnly date { get; set; }
+
+        [SugarColumn(IsPrimaryKey = true)]
+        public int nozzle { get; set; }
+        public int overproof { get; set; }
+        public int total { get; set; }
+        public int overproofrate { get; set; }
+        public int overproof_alert { get; set; }
+        public int overproof_2 { get; set; }
+        public int overproofrate_2 { get; set; }
+        public int continueoverproof { get; set; }
+
+    }
+}

BIN
tmptestproject/.vs/BlazorWeb1/v17/.suo