feat - 读取时停止盘点,心跳取所有信号,去除锁,添加控制台显示配置

master
SoulStar 1 month ago
parent 7324a8ca41
commit d264182fb0

@ -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
/// <returns></returns>
public override async Task<bool> 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;
}
}
}
//}
}
/// <summary>
@ -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)

@ -9,8 +9,11 @@ namespace SlnMesnac.Rfid
/// </summary>
public class GloalVar
{
/// <summary>
/// deviceid,心跳时间
/// </summary>
public static Dictionary<string, DateTime> HeartBeatRecoard { get; set; } = new Dictionary<string, DateTime>();
public static readonly object TCPLocker = new object();
//public static readonly object TCPLocker = new object();
}
}

@ -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
/// </summary>
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<bool?>();
var consoleWindow = GetConsoleWindow();
if (consoleWindow != IntPtr.Zero)
{
if (showConsole == true)
{
ShowWindow(consoleWindow, SW_SHOW);
}
else if (showConsole == false)
{
ShowWindow(consoleWindow, SW_HIDE);
}
}
}
catch
{
}
}
/// <summary>
/// 从命令行参数获取实例ID

@ -58,7 +58,6 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
private Dictionary<string, DispatcherTimer> _inventoryTimers = new Dictionary<string, DispatcherTimer>();
private ObservableCollection<RFIDRecord> _rfidHistoryRecords = new ObservableCollection<RFIDRecord>();
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
/// <param name="isSuccess"></param>
private void DataAdd(string iCombineId, List<TagInfo> 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)

@ -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,
//

Loading…
Cancel
Save