using AntDesign; using EasyTemplate.Tool; using EasyTemplate.Tool.Entity; using Masuit.Tools; using Microsoft.AspNetCore.Components; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using OneOf.Types; using SqlSugar; using System.Globalization; using System.Net.Sockets; using System.Reflection.Emit; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; using System.Xml.Linq; using static System.Runtime.InteropServices.JavaScript.JSType; namespace EasyTemplate.Service { public class UdpListenerService : IHostedService { private readonly ILogger _logger; private UdpClient? _udpClient; public static List ReceivedMessages { get; } = new(); public Dictionary g_mNozzleState = new Dictionary(); /// /// 注入实例 /// [Inject] private SqlSugarRepository _RepoRecord { get; set; } [Inject] private SqlSugarRepository _Repository { get; set; } public UdpListenerService(ILogger logger) { _logger = logger; } public string GetUdpData() { return ""; } public Dictionary GetNozzleState() { return g_mNozzleState; } public int getbufferdata(byte[] Buffer, ref int startIndex, int length) { if (startIndex + length > Buffer.Length) { return 0; } byte[] segment = new byte[length]; Array.Copy(Buffer, startIndex, segment, 0, length); startIndex += length; int val = Tool.BytesToInt(segment); return val; } public Task StartAsync(CancellationToken cancellationToken) { _udpClient = new UdpClient(8080); // 监听8080端口 _logger.LogInformation("开始监听UDP端口 8080"); for (int i = 0; i < 40; i++) { NozzleState ns = new NozzleState(); ns.noz = i + 1; ns.warnstate = i % 3; ns.oil = i % 2 == 0 ? "92#" : "95#"; g_mNozzleState.Add(ns.noz, ns); } Task.Run(async () => { while (!cancellationToken.IsCancellationRequested) { try { var result = await _udpClient.ReceiveAsync(cancellationToken); var message = Encoding.UTF8.GetString(result.Buffer); //dest-2;source-2;frame-1;length-2;cmd-1 int datalength = result.Buffer[5] * 256 + result.Buffer[6]; if (datalength + 9 == result.Buffer.Length) { // 计算crc int packlen = result.Buffer.Length; byte[] tmpbuf = result.Buffer; ushort nSum = Tool.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 == result.Buffer.Length + 2) { //旧协议无crc } else { continue; } int cmdtype = result.Buffer[7]; int startindex = 8; switch (cmdtype) { case 1: filling_nozzleup up = extractFillingNozzleUP(result.Buffer, startindex); g_mNozzleState[up.noz].nozzlestate = Tool.NozzleState_Filling; break; case 2: filling_process process = extractFillingProcess(result.Buffer, startindex); g_mNozzleState[process.noz].nozzlestate = Tool.NozzleState_Filling; g_mNozzleState[process.noz].VLR = ((double)process.VLR / 1000).ToString("F2"); break; case 3: filling_nozzledown down = extractFillingNozzleDown(result.Buffer, startindex); g_mNozzleState[down.noz].nozzlestate = Tool.NozzleState_Idle; break; case 4: TRecord record = extractFillingRecord(result.Buffer, startindex); g_mNozzleState[record.noz].nozzlestate = Tool.NozzleState_Idle; g_mNozzleState[record.noz].VLR = ((double)record.vlr / 1000).ToString("F2"); var con = Sql.Connect(); var res = con.Insertable(record).ExecuteCommand(); // RefAsync total = 0; //var s = _Repository.AsQueryable().Where(x => x.Id == record.fip).FirstAsync(); // var res = await _RepoRecord.InsertAsync(record); break; default: continue; } string result1 = string.Join(", ", result.Buffer); lock (ReceivedMessages) { ReceivedMessages.Add($"{DateTime.Now:HH:mm:ss} - {message}"); if (ReceivedMessages.Count > 100) ReceivedMessages.RemoveAt(0); } _logger.LogInformation($"接收到消息: {message}"); // Echo back byte[] responseData = Encoding.UTF8.GetBytes("Echo: " + message); await _udpClient.SendAsync(responseData, responseData.Length, result.RemoteEndPoint); } catch (ObjectDisposedException) when (cancellationToken.IsCancellationRequested) { break; } catch (Exception ex) { _logger.LogError(ex, "接收UDP数据出错"); } } }, cancellationToken); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { _udpClient?.Close(); _logger.LogInformation("停止监听UDP端口"); return Task.CompletedTask; } public filling_nozzleup extractFillingNozzleUP(byte[] Buffer, int startIndex) { filling_nozzleup data = new filling_nozzleup(); BufferHandler handler = new BufferHandler(Buffer, startIndex); data.board = handler.getData(1); data.noz = handler.getData(1); data.fip = data.board; data.time = handler.getDataString_BCD(7); return data; } public filling_nozzledown extractFillingNozzleDown(byte[] Buffer, int startIndex) { filling_nozzledown data = new filling_nozzledown(); BufferHandler handler = new BufferHandler(Buffer, startIndex); data.board = handler.getData(1); data.noz = handler.getData(1); data.fip = data.board; data.time = handler.getDataString_BCD(7); return data; } public filling_process extractFillingProcess(byte[] Buffer, int startIndex) { filling_process data = new filling_process(); BufferHandler handler = new BufferHandler(Buffer, startIndex); data.board = handler.getData(1); data.noz = handler.getData(1); data.fip = data.board; data.liquidVL = handler.getData(3); data.vaporVL = handler.getData(3); data.vaporFR = handler.getData(2); data.VLR = handler.getData(2); data.vaporPA = handler.getData(2); data.errornum = handler.getData(2); data.liquidFR = handler.getData(2); data.pwm = handler.getData(2); data.current = handler.getData(2); return data; } public TRecord extractFillingRecord(byte[] Buffer, int startIndex) { int bufferlen = Buffer.Length; TRecord data = new TRecord(); BufferHandler handler = new BufferHandler(Buffer, startIndex); data.board = handler.getData(1); data.noz = handler.getData(1); data.fip = data.board; if (bufferlen == 22)//兼容旧协议,解析顺序不同 { data.tmEnd = DateTime.Now; } else { data.ttc = handler.getData(4); } data.liquidVl = handler.getData(3); data.liquidFr = handler.getData(2); data.vaporVl = handler.getData(3); data.vaporFr = handler.getData(2); data.vlr = handler.getData(2); string s1 = handler.getDataString_BCD(7); if (s1 != "") { data.tmBegin = DateTime.ParseExact(s1, "yyyyMMddHHmmss", CultureInfo.InvariantCulture); } string s2 = handler.getDataString_BCD(7); if (s2 != "") { data.tmEnd = DateTime.ParseExact(s2, "yyyyMMddHHmmss", CultureInfo.InvariantCulture); } data.errornum = handler.getData(2); data.vaporPa = handler.getData(2); data.pwm = handler.getData(2); data.vccerrorinfo = ""; return data; } public class BufferHandler { public byte[] buffer = Array.Empty(); public int startIndex = 0; public int length = 0; public BufferHandler(byte[] buf, int startindex = 0) { buffer = buf; startIndex = startindex; length = buf.Length; } public string getDataString_BCD(int len) { if (startIndex + len > length) { return ""; } byte[] segment = new byte[len]; Array.Copy(buffer, startIndex, segment, 0, len); string result = Tool.BytesToBcd(segment); startIndex += len; return result; } public int getData(int len) { if (startIndex + len > length) { return 0; } byte[] segment = new byte[len]; Array.Copy(buffer, startIndex, segment, 0, len); int val = Tool.BytesToInt(segment); startIndex += len; return val; } } //public filling_process struct2filling(s_vr_status cmd) //{ // filling_process data = new filling_process(); // //data.liquidVL = (uint)(st.liqvol[0] << 16 | st.liqvol[1] << 8 | st.liqvol[2]); // data.fip = cmd.fip; // data.noz = cmd.noz; // data.liquidVL = Tool.BytesToInt(cmd.liqvol); // data.liquidFR = Tool.BytesToInt(cmd.liqflow); // data.vaporFR = Tool.BytesToInt(cmd.vapflow); // data.vaporVL = Tool.BytesToInt(cmd.vapvol); // data.VLR = Tool.BytesToInt(cmd.vlr); // data.vaporPA = Tool.BytesToInt(cmd.press); // data.pwm = Tool.BytesToInt(cmd.pwm); // data.current = Tool.BytesToInt(cmd.current); // return data; //} public class NozzleState { public int noz = 0; public string VLR = "0"; public string oil = string.Empty; public int nozzlestate = Tool.NozzleState_Offline; public int warnstate = Tool.WarningState_Normal; } public struct filling_nozzleup { public int fip; public int board; public int noz; public string time; /* byte cmd; byte fip; byte noz; byte time[7]; byte product[4];*/ /* auto& cmd = src->data.CMD1; dst.target = cmd.noz; _ubcd_to_str (dst.time, sizeof dst.time, cmd.time, sizeof cmd.time); _ubcd_to_str (dst.product, sizeof dst.product, cmd.product, sizeof cmd.product);*/ } public struct filling_nozzledown { public int fip; public int board; public int noz; public string time; } public struct filling_record { public int fip; public int board; public int noz; public int liquidVL; public int vaporVL; public int liquidFR; public int vaporFR; public int VLR; public int vaporPA; public int ttc; public int VLR_BEFORE; public int VLR_OFFSET; public int pwm; public string tmBegin; public string tmEnd; public int overproof; public int uploadflag; public int uploadflag2; public int uploadflag3; public int downloadflag1; public int yz; public int tankpressure; public int refuelingseconds; public int errorcontrolvalue; public int errornum; public int callbackflag; public string vccerrorinfo; } public struct filling_process { public int fip; public int board; public int noz; public int liquidVL; public int vaporVL; public int liquidFR; public int vaporFR; public int VLR; public int vaporPA; public int ttc; public int VLR_BEFORE; public int VLR_OFFSET; public int errornum; public int pwm; public int current; } //[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)] //public struct s_vr_status //{ // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] // public byte[] dest; // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] // public byte[] source; // public byte frame; // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] // public byte[] length; // public byte cmd; // public byte fip; // public byte noz; // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] // public byte[] liqvol; // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] // public byte[] vapvol; // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] // public byte[] vapflow; // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] // public byte[] vlr; // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] // public byte[] press; // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] // public byte[] errornum; // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] // public byte[] liqflow; // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] // public byte[] pwm; // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] // public byte[] current; // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] // public byte[] crc; //} } }