diff --git a/SlnMesnac.Rfid/Factory/RflyFactory.cs b/SlnMesnac.Rfid/Factory/RflyFactory.cs index 2058412..f58095d 100644 --- a/SlnMesnac.Rfid/Factory/RflyFactory.cs +++ b/SlnMesnac.Rfid/Factory/RflyFactory.cs @@ -96,33 +96,35 @@ namespace SlnMesnac.Rfid.Factory { try { - lock (GloalVar.TCPLocker) - { + //lock (GloalVar.TCPLocker) + //{ m_deviceID = deviceid; m_strIP = ip; _tcpClient.SetupAsync(new TouchSocketConfig().SetRemoteIPHost($"{ip}:{port}")); _tcpClient.ConnectAsync(1500).GetAwaiter().GetResult(); - } + //} _tcpClient.Received = (client, e) => { //从客户端收到信息 //var mes = Encoding.UTF8.GetString(e.Memory.Span.ToArray(), 0, e.Memory.Span.Length);//注意:数据长度是byteBlock.Len - + //只要收到消息,就算心跳 + if (GloalVar.HeartBeatRecoard.TryGetValue(deviceid, out var value)) + { + GloalVar.HeartBeatRecoard[deviceid] = DateTime.Now; + } + else + { + GloalVar.HeartBeatRecoard.Add(deviceid, DateTime.Now); + } byte[] receivedBuffer = new byte[e.Memory.Span.Length]; Array.Copy(e.Memory.Span.ToArray(), 0, receivedBuffer, 0, e.Memory.Span.Length); if (receivedBuffer.Length > 3) { + //心跳 if (e.Memory.Span.ToArray()[3] == 0xBF) { - if (GloalVar.HeartBeatRecoard.TryGetValue(deviceid, out var value)) - { - GloalVar.HeartBeatRecoard[deviceid] = DateTime.Now; - } - else - { - GloalVar.HeartBeatRecoard.Add(deviceid, DateTime.Now); - } + //Log.Information($"{m_deviceID},IP:{m_strIP}接收心跳{_stringChange.bytesToHexStr(receivedBuffer, receivedBuffer.Length)}"); } //连续盘点返回 if (e.Memory.Span.ToArray()[3] == 0x01) @@ -189,8 +191,9 @@ namespace SlnMesnac.Rfid.Factory /// public override async Task Set_HeartBeat(byte second) { - lock (GloalVar.TCPLocker) - { + //lock (GloalVar.TCPLocker) + //{ + Log.Information($"设置心跳:【{second}】秒"); byte[] data = new byte[3]; data[0] = 0x00; data[1] = second; @@ -234,7 +237,7 @@ namespace SlnMesnac.Rfid.Factory return false; } } - } + //} } /// @@ -551,8 +554,8 @@ namespace SlnMesnac.Rfid.Factory byte[] bCRC = new byte[4]; try { - lock (GloalVar.TCPLocker) - { + //lock (GloalVar.TCPLocker) + //{ #region 指令封装 MessagePack pMessagePack = new MessagePack(); pMessagePack.m_pData = new byte[8]; @@ -594,7 +597,7 @@ namespace SlnMesnac.Rfid.Factory //} //return false; return true; - } + //} } catch (Exception e) { @@ -613,8 +616,8 @@ namespace SlnMesnac.Rfid.Factory byte[] bCRC = new byte[4]; try { - lock (GloalVar.TCPLocker) - { + //lock (GloalVar.TCPLocker) + //{ #region 指令封装 MessagePack pMessagePack = new MessagePack(); @@ -656,7 +659,7 @@ namespace SlnMesnac.Rfid.Factory // } //} return true; - } + //} } catch (Exception e) { @@ -708,8 +711,8 @@ namespace SlnMesnac.Rfid.Factory try { - lock (GloalVar.TCPLocker) - { + //lock (GloalVar.TCPLocker) + //{ #region 指令封装 //自动根据写入数据封装 Base03HENtity rawData = new Base03HENtity() @@ -788,6 +791,15 @@ namespace SlnMesnac.Rfid.Factory { var reciveBuffer = responsedData.Memory.ToArray(); Log.Information($"{m_deviceID}接收写入指令{_stringChange.bytesToHexStr(reciveBuffer, reciveBuffer.Length)}"); + //只要收到消息,就算心跳 + if (GloalVar.HeartBeatRecoard.TryGetValue(deviceid, out var value)) + { + GloalVar.HeartBeatRecoard[deviceid] = DateTime.Now; + } + else + { + GloalVar.HeartBeatRecoard.Add(deviceid, DateTime.Now); + } if (reciveBuffer[3] == 0x03 && reciveBuffer[4] == 0x00) { Log.Information($"写入成功,写入数值{pWriteData}"); @@ -795,7 +807,7 @@ namespace SlnMesnac.Rfid.Factory } } return false; - } + //} } catch (Exception e) diff --git a/SlnMesnac.Rfid/GloalVar.cs b/SlnMesnac.Rfid/GloalVar.cs index 0532738..cfbebd8 100644 --- a/SlnMesnac.Rfid/GloalVar.cs +++ b/SlnMesnac.Rfid/GloalVar.cs @@ -9,8 +9,11 @@ namespace SlnMesnac.Rfid /// public class GloalVar { + /// + /// deviceid,心跳时间 + /// public static Dictionary HeartBeatRecoard { get; set; } = new Dictionary(); - public static readonly object TCPLocker = new object(); + //public static readonly object TCPLocker = new object(); } } diff --git a/SlnMesnac.WPF/App.xaml.cs b/SlnMesnac.WPF/App.xaml.cs index 447482d..0044757 100644 --- a/SlnMesnac.WPF/App.xaml.cs +++ b/SlnMesnac.WPF/App.xaml.cs @@ -15,6 +15,7 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; +using System.Runtime.InteropServices; using System.Threading; using System.Windows; using TouchSocket.Sockets; @@ -26,6 +27,18 @@ namespace SlnMesnac.WPF /// public partial class App : Application { + [DllImport("kernel32.dll")] + private static extern IntPtr GetConsoleWindow(); + + [DllImport("user32.dll")] + private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); + + [DllImport("kernel32.dll")] + private static extern bool AllocConsole(); + + private const int SW_HIDE = 0; + private const int SW_SHOW = 5; + private Mutex _instanceMutex = null; private LierdaCracker cracker = new LierdaCracker(); public static IServiceProvider ServiceProvider { get; private set; } @@ -50,6 +63,7 @@ namespace SlnMesnac.WPF { try { + HideConsoleIfConfigured(); this.DispatcherUnhandledException += App_DispatcherUnhandledException; //全局异常处理 #region 多实例初始化 // 从命令行参数获取实例ID(如果指定了) @@ -132,6 +146,34 @@ namespace SlnMesnac.WPF } } + private void HideConsoleIfConfigured() + { + try + { + var config = new ConfigurationBuilder() + .SetBasePath(AppDomain.CurrentDomain.BaseDirectory) + .AddJsonFile("appsettings.json", optional: true) + .Build(); + + var showConsole = config.GetSection("AppConfig:ShowConsole").Get(); + var consoleWindow = GetConsoleWindow(); + + if (consoleWindow != IntPtr.Zero) + { + if (showConsole == true) + { + ShowWindow(consoleWindow, SW_SHOW); + } + else if (showConsole == false) + { + ShowWindow(consoleWindow, SW_HIDE); + } + } + } + catch + { + } + } /// /// 从命令行参数获取实例ID diff --git a/SlnMesnac.WPF/ViewModel/IndexPage/ProductionLineViewModel.cs b/SlnMesnac.WPF/ViewModel/IndexPage/ProductionLineViewModel.cs index 8f77098..601003a 100644 --- a/SlnMesnac.WPF/ViewModel/IndexPage/ProductionLineViewModel.cs +++ b/SlnMesnac.WPF/ViewModel/IndexPage/ProductionLineViewModel.cs @@ -58,7 +58,6 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage private Dictionary _inventoryTimers = new Dictionary(); private ObservableCollection _rfidHistoryRecords = new ObservableCollection(); private RealReadDataImpl databaseService = RealReadDataImpl.Instance; - private static readonly object _lockObj = new object(); private System.Threading.Timer ReReadTimer; private bool IsVerify = false; private string LastWrite; @@ -197,17 +196,19 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage { try { + var rfidInfo = rfidList.FirstOrDefault(x => x.deviceid == iCombineId); + var deviceInfo = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId); //初次写入 if (!IsVerify) { //写入前等待标签稳定 if (!IsVerify) { - await Task.Delay(Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).WriteDelaySet ?? 2000); + await Task.Delay(deviceInfo.WriteDelaySet ?? 2000); } //验证是否已获取订单信息 - if (string.IsNullOrEmpty(Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).OrderNo)) + if (string.IsNullOrEmpty(deviceInfo.OrderNo)) { MessageBox.Show("请先获取MES订单号!", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; @@ -223,72 +224,79 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage //if (true) { //验证是否已获取序列号 - if (string.IsNullOrEmpty(Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).SerialNo)) + if (string.IsNullOrEmpty(deviceInfo.SerialNo)) { return; } - Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).ReadTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + deviceInfo.ReadTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); //拼接订单号写入标签 - string WriteData = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).OrderNo - + Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).LineNo + string WriteData = deviceInfo.OrderNo + + deviceInfo.LineNo + DateTime.Now.ToString("yy") - + Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).NextProductNo - + Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).SerialNo; + + deviceInfo.NextProductNo + + deviceInfo.SerialNo; CurrentState = "写入中"; LastRFIDEPC = tagInfos[0].EPCstring; - //写入 三次重写 - lock (_lockObj) //锁住写入过程,防止写入的时候开始定时盘点 + //写入 + StopInventoryTimer(iCombineId); + await rfidInfo.Set_HeartBeat(0); + Task.Delay(100).Wait(); + var deviceConfig = appConfig.deviceInfoConfig.FirstOrDefault(x => x.Deviceid == iCombineId); + for (int i = 0; i < deviceConfig.WriteCount; i++) { - var deviceConfig = appConfig.deviceInfoConfig.FirstOrDefault(x => x.Deviceid == iCombineId); - for (int i = 0; i < deviceConfig.WriteCount; i++) + bool writeflag = rfidInfo.Set_Write(tagInfos[0].EPC, WriteData).GetAwaiter().GetResult(); + if (writeflag) { - bool writeflag = rfidList.FirstOrDefault(x => x.deviceid == iCombineId).Set_Write(tagInfos[0].EPC, WriteData).GetAwaiter().GetResult(); - if (writeflag) - { - LastWrite = WriteData; - IsVerify = true; + LastWrite = WriteData; + IsVerify = true; - // 启动验证超时检测 - _verifyCts?.Cancel(); - _verifyCts = new CancellationTokenSource(); - var token = _verifyCts.Token; - var capturedTagInfos = tagInfos; - var timeoutMs = deviceConfig.VerifyTimeoutMilliseconds ?? 20000; - _ = Task.Run(async () => + rfidInfo.Set_BeginIdentify().GetAwaiter().GetResult(); + + // 启动验证超时检测 + _verifyCts?.Cancel(); + _verifyCts = new CancellationTokenSource(); + var token = _verifyCts.Token; + var capturedTagInfos = tagInfos; + var timeoutMs = deviceConfig.VerifyTimeoutMilliseconds ?? 20000; + _ = Task.Run(async () => + { + try { - try + await Task.Delay(timeoutMs, token); + if (IsVerify) { - await Task.Delay(timeoutMs, token); - if (IsVerify) - { - Log.Error($"二次验证超时未读到标签,标签已离开,记为写入失败"); - DataAdd(iCombineId, capturedTagInfos, false); - } + Log.Error($"二次验证超时未读到标签,标签已离开,记为写入失败"); + DataAdd(iCombineId, capturedTagInfos, false); } - catch (TaskCanceledException) { } - }, token); + } + catch (TaskCanceledException) { } + }, token); - rfidList.FirstOrDefault(x => x.deviceid == iCombineId).Set_BeginIdentify().GetAwaiter().GetResult(); - return; - } - else - { - Log.Error($"第{i + 1}次写入失败,重试中..."); - continue; - } + StartInventoryTimer(iCombineId, deviceConfig.InventoryIntervalSeconds.Value); + await rfidInfo.Set_HeartBeat(5); + return; + } + else + { + Log.Error($"第{i + 1}次写入失败,重试中..."); + Task.Delay(100).Wait(); + continue; } - Log.Error($"写入失败,[{tagInfos[0].EPCstring}] 记为失败写入"); - //插入失败记录 - DataAdd(iCombineId, tagInfos, false); - return; } + Log.Error($"写入失败,[{tagInfos[0].EPCstring}] 记为失败写入"); + //插入失败记录 + DataAdd(iCombineId, tagInfos, false); + StartInventoryTimer(iCombineId, deviceConfig.InventoryIntervalSeconds.Value); + await rfidInfo.Set_HeartBeat(5); + return; + } else { await Task.Run(async () => { await Task.Delay(1000); - await rfidList.FirstOrDefault(x => x.deviceid == iCombineId)!.Set_BeginIdentify(); + await rfidInfo!.Set_BeginIdentify(); CurrentState = "盘点中"; }); } @@ -312,17 +320,15 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage try { await Task.Delay(timeoutMs, token); - if (IsVerify) - { - Log.Error($"二次验证超时写入标签超时,标签已离开,记为写入失败"); - DataAdd(iCombineId, capturedTagInfos, false); - } + Log.Error($"二次验证超时写入标签超时,标签已离开,记为写入失败"); + DataAdd(iCombineId, capturedTagInfos, false); } catch (TaskCanceledException) { } }, token); + IsVerify = false; var tempEPC = LastRFIDEPC; - rfidList.FirstOrDefault(x => x.deviceid == iCombineId).Set_BeginIdentify().GetAwaiter().GetResult(); + rfidInfo.Set_BeginIdentify().GetAwaiter().GetResult(); LastRFIDEPC = tempEPC; CurrentState = "盘点中"; return; @@ -352,26 +358,30 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage /// private void DataAdd(string iCombineId, List tagInfos, bool isSuccess) { + var deviceInfo = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId); + var rfidInfo = rfidList.FirstOrDefault(x => x.deviceid == iCombineId); + + var deviceConfig = appConfig.deviceInfoConfig.FirstOrDefault(x => x.Deviceid == iCombineId); IsVerify = false; - Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).WriteTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); - Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).WriteStatus = isSuccess ? "成功" : "失败"; + deviceInfo.WriteTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + deviceInfo.WriteStatus = isSuccess ? "成功" : "失败"; LastWriteState = isSuccess ? "成功" : "失败"; - Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).RfidASCII = LastWrite; - Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).RfidEPC = LastRFIDEPC; - Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).SerialNo = (Convert.ToInt32(Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).SerialNo) + 1).ToString("D2"); + deviceInfo.RfidASCII = LastWrite; + deviceInfo.RfidEPC = LastRFIDEPC; + deviceInfo.SerialNo = (Convert.ToInt32(deviceInfo.SerialNo) + 1).ToString("D2"); //保存写入记录 real_readdata real_Readdata = new real_readdata() { objid = Guid.NewGuid().ToString(), - serialno = (Convert.ToInt32(Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).SerialNo) - 1).ToString("D2"), - orderno = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).OrderNo, - lineno = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).LineNo, - producttype = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).ProductType, - rfidepc = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).RfidEPC, + serialno = (Convert.ToInt32(deviceInfo.SerialNo) - 1).ToString("D2"), + orderno = deviceInfo.OrderNo, + lineno = deviceInfo.LineNo, + producttype = deviceInfo.ProductType, + rfidepc = deviceInfo.RfidEPC, rfidascii = LastWrite, - readtime = Convert.ToDateTime(Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).ReadTime), - writetime = Convert.ToDateTime(Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).WriteTime), - writestatus = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).WriteStatus + readtime = Convert.ToDateTime(deviceInfo.ReadTime), + writetime = Convert.ToDateTime(deviceInfo.WriteTime), + writestatus = deviceInfo.WriteStatus }; //插入到数据库历史记录中 @@ -383,7 +393,8 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage LastRFIDEPC = ""; LastWrite = ""; - rfidList.FirstOrDefault(x => x.deviceid == iCombineId).Set_BeginIdentify().GetAwaiter().GetResult(); + rfidInfo.Set_BeginIdentify().GetAwaiter().GetResult(); + StartInventoryTimer(iCombineId, deviceConfig.InventoryIntervalSeconds.Value); CurrentState = "盘点中"; return; } @@ -681,6 +692,7 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage }; timer.Tick += (s, e) => OnInventoryTimerTick(deviceId); timer.Start(); + //OnInventoryTimerTick(deviceId); _inventoryTimers[deviceId] = timer; Log.Information($"设备 {deviceId} 启动定时盘点,间隔 {intervalSeconds} ms"); } @@ -705,16 +717,13 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage { try { - lock (_lockObj) + var rfid = rfidList.FirstOrDefault(x => x.deviceid == deviceId); + if (rfid != null) { - var rfid = rfidList.FirstOrDefault(x => x.deviceid == deviceId); - if (rfid != null) - { - //Log.Information($"设备 {deviceId} 执行定时盘点"); - //await rfid.Set_StopIdentify(); - //await Task.Delay(100); - rfid.Set_BeginIdentify().GetAwaiter().GetResult(); - } + //Log.Information($"设备 {deviceId} 执行定时盘点"); + //await rfid.Set_StopIdentify(); + //await Task.Delay(100); + rfid.Set_BeginIdentify().GetAwaiter().GetResult(); } } catch (Exception ex) diff --git a/SlnMesnac.WPF/appsettings.json b/SlnMesnac.WPF/appsettings.json index 723f600..efd94f3 100644 --- a/SlnMesnac.WPF/appsettings.json +++ b/SlnMesnac.WPF/appsettings.json @@ -8,6 +8,8 @@ }, "AllowedHosts": "*", "AppConfig": { + //是否显示控制台 + "ShowConsole": false, "logPath": "D:\\net6.0-windows\\log", "InstanceDataPath": "D:\\net6.0-windows\\log", "SqlConfig": [ @@ -93,7 +95,7 @@ //初次读到数据后写入数据延迟设置,单位毫秒 "WriteDelaySet": 1000, //写入失败重试次数(每次写入设置为五秒超时时间) - "WriteCount": 3, + "WriteCount": 30, //定时重置盘点间隔时间,单位毫秒 "InventoryIntervalSeconds": 5000, //二次验证超时时间,单位毫秒