|
|
using CommunityToolkit.Mvvm.Input;
|
|
|
using CommunityToolkit.Mvvm.Messaging;
|
|
|
using GalaSoft.MvvmLight;
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
using NVelocity.Runtime.Directive;
|
|
|
using Serilog;
|
|
|
using SlnMesnac.Common;
|
|
|
using SlnMesnac.Config;
|
|
|
using SlnMesnac.Model.domain;
|
|
|
using SlnMesnac.Model.dto;
|
|
|
using SlnMesnac.Model.Enum;
|
|
|
using SlnMesnac.Repository;
|
|
|
using SlnMesnac.Repository.service;
|
|
|
using SlnMesnac.Repository.service.Impl;
|
|
|
using SlnMesnac.Rfid;
|
|
|
using SlnMesnac.Rfid.Enum;
|
|
|
using SlnMesnac.Serilog;
|
|
|
using SlnMesnac.TouchSocket;
|
|
|
using SlnMesnac.WPF.Attribute;
|
|
|
using SlnMesnac.WPF.Model;
|
|
|
using SqlSugar;
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Collections.ObjectModel;
|
|
|
using System.Data;
|
|
|
using System.Drawing;
|
|
|
using System.Linq;
|
|
|
using System.Text;
|
|
|
using System.Text.Json.Serialization;
|
|
|
using System.Threading;
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
using System.Windows.Forms;
|
|
|
using System.Windows.Markup;
|
|
|
using System.Windows.Threading;
|
|
|
using System.Xml.Serialization;
|
|
|
using TouchSocket.Core;
|
|
|
using static Microsoft.WindowsAPICodePack.Shell.PropertySystem.SystemProperties.System;
|
|
|
using Task = System.Threading.Tasks.Task;
|
|
|
|
|
|
|
|
|
namespace SlnMesnac.WPF.ViewModel.IndexPage
|
|
|
{
|
|
|
[RegisterAsSingletonAttribute]
|
|
|
public class ProductionLineViewModel : ViewModelBase
|
|
|
{
|
|
|
#region 参数定义
|
|
|
|
|
|
private static StringChange _StringChange;
|
|
|
private String SerialNo = "";
|
|
|
private SerilogHelper _logger;
|
|
|
//private ISqlSugarClient? sqlSugarClient;
|
|
|
//容器里面的读写器集合
|
|
|
public List<RfidAbsractFactory> rfidList;
|
|
|
private AppConfig appConfig;
|
|
|
private MeshttpClient meshttpClient;
|
|
|
public TcpServer _TcpServer;
|
|
|
private DispatcherTimer _timer;
|
|
|
private Dictionary<string, DispatcherTimer> _inventoryTimers = new Dictionary<string, DispatcherTimer>();
|
|
|
private ObservableCollection<RFIDRecord> _rfidHistoryRecords = new ObservableCollection<RFIDRecord>();
|
|
|
private RealReadDataImpl databaseService = RealReadDataImpl.Instance;
|
|
|
private System.Threading.Timer ReReadTimer;
|
|
|
private bool IsVerify = false;
|
|
|
private int WriteTime = 0;
|
|
|
private string LastWrite;
|
|
|
private string LastRFIDEPC;
|
|
|
private CancellationTokenSource? _verifyCts;
|
|
|
private CancellationTokenSource? _writeCts;
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region 关联属性
|
|
|
|
|
|
public ObservableCollection<RFIDRecord> RFIDHistoryRecords
|
|
|
{
|
|
|
get { return _rfidHistoryRecords; }
|
|
|
set
|
|
|
{
|
|
|
_rfidHistoryRecords = value;
|
|
|
RaisePropertyChanged(() => RFIDHistoryRecords);
|
|
|
}
|
|
|
}
|
|
|
ChangeTypeViewModel ChangeTypeView;
|
|
|
|
|
|
|
|
|
|
|
|
private ObservableCollection<Real_DataInfo> _Deviceinfo = new ObservableCollection<Real_DataInfo>();
|
|
|
public ObservableCollection<Real_DataInfo> Deviceinfo
|
|
|
{
|
|
|
get { return _Deviceinfo; }
|
|
|
set
|
|
|
{
|
|
|
_Deviceinfo = value;
|
|
|
RaisePropertyChanged(() => Deviceinfo);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 日期时间
|
|
|
/// </summary>
|
|
|
private DateTime _currentDateTime;
|
|
|
public DateTime CurrentDateTime
|
|
|
{
|
|
|
get => _currentDateTime;
|
|
|
set
|
|
|
{
|
|
|
if (_currentDateTime != value)
|
|
|
{
|
|
|
_currentDateTime = value;
|
|
|
RaisePropertyChanged(() => CurrentDateTime);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 上一次写入状态
|
|
|
/// </summary>
|
|
|
private string _lastWriteState;
|
|
|
public string LastWriteState
|
|
|
{
|
|
|
get => _lastWriteState;
|
|
|
set
|
|
|
{
|
|
|
if (_lastWriteState != value)
|
|
|
{
|
|
|
_lastWriteState = value;
|
|
|
RaisePropertyChanged(() => LastWriteState);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 当前状态 空闲 盘点中 写入中
|
|
|
/// </summary>
|
|
|
private string _CurrentState = "空闲";
|
|
|
public string CurrentState
|
|
|
{
|
|
|
get => _CurrentState;
|
|
|
set
|
|
|
{
|
|
|
if (_CurrentState != value)
|
|
|
{
|
|
|
_CurrentState = value;
|
|
|
RaisePropertyChanged(() => CurrentState);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region 构造函数
|
|
|
|
|
|
public ProductionLineViewModel()
|
|
|
{
|
|
|
ChangeTypeView = App.ServiceProvider.GetService<ChangeTypeViewModel>();
|
|
|
// 构造函数里注册
|
|
|
WeakReferenceMessenger.Default.Register<Real_DataInfo>(this, RefreshOrderNo);
|
|
|
WeakReferenceMessenger.Default.Register<string, string>(this, "Cancel", StopMessage);
|
|
|
_StringChange = App.ServiceProvider.GetService<StringChange>();
|
|
|
_logger = App.ServiceProvider.GetService<SerilogHelper>();
|
|
|
appConfig = App.ServiceProvider.GetService<AppConfig>();
|
|
|
//sqlSugarClient = App.ServiceProvider.GetService<ISqlSugarClient>();
|
|
|
_TcpServer = App.ServiceProvider.GetRequiredService<TcpServer>();
|
|
|
rfidList = App.ServiceProvider.GetRequiredService<List<RfidAbsractFactory>>();
|
|
|
|
|
|
rfidList.ForEach(rfid =>
|
|
|
{
|
|
|
rfid._Action += RecvIdentifyData_Instance;
|
|
|
//rfid._RefreshLogMessageAction += RefreshLogMessage;
|
|
|
});
|
|
|
LoadDeviceInfo();
|
|
|
StartCheckStatus();
|
|
|
//GetRFIDHistoryRecords();
|
|
|
_currentDateTime = DateTime.Now;
|
|
|
_timer = new DispatcherTimer
|
|
|
{
|
|
|
Interval = TimeSpan.FromSeconds(1) // 每秒更新一次
|
|
|
};
|
|
|
_timer.Tick += (s, e) =>
|
|
|
{
|
|
|
CurrentDateTime = DateTime.Now;
|
|
|
};
|
|
|
_timer.Start();
|
|
|
|
|
|
Log.Information("RFID输送带系统启动");
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region 核心写入算法
|
|
|
|
|
|
/// <summary>
|
|
|
/// 接收到连续盘点标签返回
|
|
|
/// </summary>
|
|
|
/// <param name="iCombineId"></param>
|
|
|
/// <param name="tagInfos"></param>
|
|
|
private async void RecvIdentifyData_Instance(string iCombineId, List<TagInfo> tagInfos)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
_writeCts?.Cancel();
|
|
|
var rfidInfo = rfidList.FirstOrDefault(x => x.deviceid == iCombineId);
|
|
|
var deviceInfo = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId);
|
|
|
var deviceConfig = appConfig.deviceInfoConfig.FirstOrDefault(x => x.Deviceid == iCombineId);
|
|
|
//初次写入
|
|
|
if (!IsVerify)
|
|
|
{
|
|
|
//写入前等待标签稳定
|
|
|
if (!IsVerify)
|
|
|
{
|
|
|
await Task.Delay(deviceInfo.WriteDelaySet ?? 2000);
|
|
|
}
|
|
|
|
|
|
//验证是否已获取订单信息
|
|
|
if (string.IsNullOrEmpty(deviceInfo.OrderNo))
|
|
|
{
|
|
|
MessageBox.Show("请先获取MES订单号!", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
//查询数据库是否已存在记录
|
|
|
string epcascii = Encoding.ASCII.GetString(tagInfos[0].EPC);
|
|
|
epcascii = epcascii.Replace("\0", "");
|
|
|
List<real_readdata> real_Readdatas = databaseService._helper.Query(x => x.rfidascii == epcascii);
|
|
|
|
|
|
//如果不存在则写入
|
|
|
if (real_Readdatas.Count <= 0)
|
|
|
//if (true)
|
|
|
{
|
|
|
//验证是否已获取序列号
|
|
|
if (string.IsNullOrEmpty(deviceInfo.SerialNo))
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
deviceInfo.ReadTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
|
//拼接订单号写入标签
|
|
|
string WriteData = deviceInfo.OrderNo
|
|
|
+ deviceInfo.LineNo
|
|
|
+ DateTime.Now.ToString("yy")
|
|
|
+ deviceInfo.NextProductNo
|
|
|
+ deviceInfo.SerialNo;
|
|
|
CurrentState = "写入中";
|
|
|
LastRFIDEPC = tagInfos[0].EPCstring;
|
|
|
|
|
|
//写入前暂停心跳和连续盘点
|
|
|
StopInventoryTimer(iCombineId);
|
|
|
await rfidInfo.Set_HeartBeat(0);
|
|
|
Task.Delay(100).Wait();
|
|
|
|
|
|
//处理写入字符串,并写入
|
|
|
//var originBytes = tagInfos[0].EPC.Where(b => b != 0x00).ToArray();
|
|
|
bool writeflag = rfidInfo.Set_Write(tagInfos[0].EPC, WriteData).GetAwaiter().GetResult();
|
|
|
WriteTime++;
|
|
|
|
|
|
if (writeflag) //写入成功
|
|
|
{
|
|
|
LastWrite = WriteData;
|
|
|
IsVerify = true;
|
|
|
WriteTime = 0;
|
|
|
|
|
|
//开始二次验证
|
|
|
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
|
|
|
{
|
|
|
await Task.Delay(timeoutMs, token);
|
|
|
Log.Error($"二次验证超时未读到标签,标签已离开,记为写入失败");
|
|
|
await DataAdd(iCombineId, capturedTagInfos, false);
|
|
|
}
|
|
|
catch (TaskCanceledException) { }
|
|
|
}, token);
|
|
|
|
|
|
//开启定时盘点和心跳
|
|
|
StartInventoryTimer(iCombineId, deviceConfig.InventoryIntervalSeconds.Value);
|
|
|
await rfidInfo.Set_HeartBeat(5);
|
|
|
return;
|
|
|
}
|
|
|
else //写入失败
|
|
|
{
|
|
|
Log.Error($"第{WriteTime + 1}次写入失败,重试中...");
|
|
|
//重试前再读取一次标签
|
|
|
rfidInfo.Set_BeginIdentify().GetAwaiter().GetResult();
|
|
|
|
|
|
//设置下次读取超时
|
|
|
_writeCts?.Cancel();
|
|
|
_writeCts = new CancellationTokenSource();
|
|
|
var token = _writeCts.Token;
|
|
|
var capturedTagInfos = tagInfos;
|
|
|
var timeoutMs = deviceConfig.WriteTimeoutMilliseconds ?? 10000;
|
|
|
_ = Task.Run(async () =>
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
await Task.Delay(timeoutMs, token);
|
|
|
Log.Error($"写入前读取超时,[{tagInfos[0].EPCstring}] 记为写入失败");
|
|
|
await DataAdd(iCombineId, capturedTagInfos, false);
|
|
|
WriteTime = 0;
|
|
|
}
|
|
|
catch (TaskCanceledException) { }
|
|
|
}, token);
|
|
|
|
|
|
StartInventoryTimer(iCombineId, deviceConfig.InventoryIntervalSeconds.Value);
|
|
|
await rfidInfo.Set_HeartBeat(5);
|
|
|
Task.Delay(100).Wait();
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
await Task.Run(async () =>
|
|
|
{
|
|
|
await Task.Delay(1000);
|
|
|
await rfidInfo!.Set_BeginIdentify();
|
|
|
CurrentState = "盘点中";
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
else //二次验证流程
|
|
|
{
|
|
|
var judgeString = Encoding.ASCII.GetString(tagInfos[0].EPC);
|
|
|
judgeString = judgeString.Replace("\0", "");
|
|
|
//二次验证如果不通过 重新开始盘点
|
|
|
if (judgeString != LastWrite)
|
|
|
{
|
|
|
// 读到标签但数据不匹配,重置超时(标签仍在天线范围内)
|
|
|
_verifyCts?.Cancel();
|
|
|
_verifyCts = new CancellationTokenSource();
|
|
|
var token = _verifyCts.Token;
|
|
|
var capturedTagInfos = tagInfos;
|
|
|
var timeoutMs = deviceConfig?.VerifyTimeoutMilliseconds ?? 20000;
|
|
|
_ = Task.Run(async () =>
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
await Task.Delay(timeoutMs, token);
|
|
|
Log.Error($"二次验证超时写入标签超时,标签已离开,记为写入失败");
|
|
|
await DataAdd(iCombineId, capturedTagInfos, false);
|
|
|
}
|
|
|
catch (TaskCanceledException) { }
|
|
|
}, token);
|
|
|
|
|
|
IsVerify = false;
|
|
|
var tempEPC = LastRFIDEPC;
|
|
|
rfidInfo.Set_BeginIdentify().GetAwaiter().GetResult();
|
|
|
LastRFIDEPC = tempEPC;
|
|
|
CurrentState = "盘点中";
|
|
|
return;
|
|
|
}
|
|
|
else //二次验证通过
|
|
|
{
|
|
|
_verifyCts?.Cancel();
|
|
|
Log.Information($"验证成功");
|
|
|
//插入成功记录
|
|
|
await DataAdd(iCombineId, tagInfos, true);
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
catch (Exception e)
|
|
|
{
|
|
|
Log.Error($"读结果准备写入时异常:{e.Message}");
|
|
|
CurrentState = "空闲";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 插入记录
|
|
|
/// </summary>
|
|
|
/// <param name="iCombineId"></param>
|
|
|
/// <param name="tagInfos"></param>
|
|
|
/// <param name="isSuccess"></param>
|
|
|
private async Task 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.WriteTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
|
|
deviceInfo.WriteStatus = isSuccess ? "成功" : "失败";
|
|
|
LastWriteState = isSuccess ? "成功" : "失败";
|
|
|
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.SerialNo) - 1).ToString("D2"),
|
|
|
orderno = deviceInfo.OrderNo,
|
|
|
lineno = deviceInfo.LineNo,
|
|
|
producttype = deviceInfo.ProductType,
|
|
|
rfidepc = deviceInfo.RfidEPC,
|
|
|
rfidascii = LastWrite,
|
|
|
readtime = Convert.ToDateTime(deviceInfo.ReadTime),
|
|
|
writetime = Convert.ToDateTime(deviceInfo.WriteTime),
|
|
|
writestatus = deviceInfo.WriteStatus
|
|
|
};
|
|
|
|
|
|
//插入到数据库历史记录中
|
|
|
var a = databaseService._helper.Insert(real_Readdata);
|
|
|
|
|
|
//插入记录到首页临时数据显示
|
|
|
AddRFIDData(iCombineId, tagInfos);
|
|
|
|
|
|
LastRFIDEPC = "";
|
|
|
LastWrite = "";
|
|
|
|
|
|
await rfidInfo.Set_BeginIdentify();
|
|
|
await Task.Delay(100);
|
|
|
StartInventoryTimer(iCombineId, deviceConfig.InventoryIntervalSeconds.Value);
|
|
|
await rfidInfo.Set_HeartBeat(5);
|
|
|
CurrentState = "盘点中";
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region 数据流相关
|
|
|
|
|
|
/// <summary>
|
|
|
/// 开始订单初次流程
|
|
|
/// </summary>
|
|
|
/// <param name="recipient"></param>
|
|
|
/// <param name="real_Data"></param>
|
|
|
private void RefreshOrderNo(object recipient, Real_DataInfo real_Data)
|
|
|
{
|
|
|
//查询当前订单产线最大序列号
|
|
|
List<real_readdata> real_Readdatas = databaseService._helper.Query(x => x.orderno == real_Data.OrderNo && x.lineno == real_Data.LineNo);
|
|
|
string SNo = "";
|
|
|
if (real_Readdatas.Count > 0)
|
|
|
{
|
|
|
SNo = real_Readdatas.Max(x => x.serialno);
|
|
|
SNo = (Convert.ToInt32(SNo) + 1).ToString("D2");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
SNo = "1";
|
|
|
}
|
|
|
Deviceinfo.FirstOrDefault(x => x.Deviceid == real_Data.Deviceid).SerialNo = Convert.ToInt32(SNo).ToString("D2");
|
|
|
Deviceinfo.FirstOrDefault(x => x.Deviceid == real_Data.Deviceid).OrderNo = real_Data.OrderNo;
|
|
|
Deviceinfo.FirstOrDefault(x => x.Deviceid == real_Data.Deviceid).ProductType = real_Data.ProductType;
|
|
|
Deviceinfo.FirstOrDefault(x => x.Deviceid == real_Data.Deviceid).LineNo = real_Data.LineNo;
|
|
|
Deviceinfo.FirstOrDefault(x => x.Deviceid == real_Data.Deviceid).RfidCount = real_Data.RfidCount;
|
|
|
Deviceinfo.FirstOrDefault(x => x.Deviceid == real_Data.Deviceid).NextProductNo = real_Data.NextProductNo;
|
|
|
|
|
|
rfidList.FirstOrDefault(x => x.deviceid == real_Data.Deviceid).Set_BeginIdentify().GetAwaiter().GetResult();
|
|
|
IsVerify = false;
|
|
|
CurrentState = "盘点中";
|
|
|
|
|
|
// 启动定时盘点
|
|
|
var deviceConfig = appConfig.deviceInfoConfig.FirstOrDefault(x => x.Deviceid == real_Data.Deviceid);
|
|
|
if (deviceConfig?.InventoryIntervalSeconds > 0)
|
|
|
{
|
|
|
StartInventoryTimer(real_Data.Deviceid, deviceConfig.InventoryIntervalSeconds.Value);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 停止盘点消息
|
|
|
/// </summary>
|
|
|
private void StopMessage(object o, string e)
|
|
|
{
|
|
|
var rfid = rfidList.FirstOrDefault(x => x.deviceid == e);
|
|
|
StopInventoryTimer(e);
|
|
|
|
|
|
var res = rfid.Set_StopIdentify().GetAwaiter().GetResult();
|
|
|
if (res)
|
|
|
{
|
|
|
MessageBox.Show("停止盘点成功!", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
MessageBox.Show("停止盘点失败!", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
|
}
|
|
|
CurrentState = "空闲";
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 初次加载设备信息
|
|
|
/// </summary>
|
|
|
private void LoadDeviceInfo()
|
|
|
{
|
|
|
List<DeviceInfoConfig> DeviceInfos = appConfig.deviceInfoConfig.Where(x => x.Collectid == appConfig.StationCode && x.Deleteflag == 0).ToList();
|
|
|
List<Real_DataInfo> real_DataInfos = new List<Real_DataInfo>();
|
|
|
|
|
|
foreach (var item in DeviceInfos)
|
|
|
{
|
|
|
Real_DataInfo real_DataInfo = new Real_DataInfo()
|
|
|
{
|
|
|
Name = item.Name,
|
|
|
Deviceid = item.Deviceid,
|
|
|
Connectstr = item.Connectstr,
|
|
|
LineName = item.Name,
|
|
|
LineNo = item.Addr,
|
|
|
OrderNo = "",
|
|
|
ProductType = "",
|
|
|
WriteCount = "",
|
|
|
RfidCount = "",
|
|
|
IsOnline = "未连接",
|
|
|
RfidASCII = "",
|
|
|
RfidEPC = "",
|
|
|
ReadTime = "",
|
|
|
WriteTime = "",
|
|
|
ProductStatus = "",
|
|
|
WriteStatus = "",
|
|
|
WriteDelaySet = item.WriteDelaySet
|
|
|
};
|
|
|
real_DataInfos.Add(real_DataInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
App.Current.Dispatcher.Invoke(() =>
|
|
|
{
|
|
|
Deviceinfo.Clear();
|
|
|
|
|
|
foreach (var item in real_DataInfos)
|
|
|
{
|
|
|
Real_DataInfo real_DataInfo = new Real_DataInfo()
|
|
|
{
|
|
|
Name = item.Name,
|
|
|
Deviceid = item.Deviceid,
|
|
|
Connectstr = item.Connectstr,
|
|
|
LineName = item.Name,
|
|
|
LineNo = item.LineNo,
|
|
|
OrderNo = item.OrderNo,
|
|
|
ProductType = item.ProductType,
|
|
|
WriteCount = item.WriteCount,
|
|
|
RfidCount = item.RfidCount,
|
|
|
IsOnline = item.IsOnline,
|
|
|
RfidASCII = item.RfidASCII,
|
|
|
ReadTime = item.ReadTime,
|
|
|
WriteTime = item.WriteTime,
|
|
|
ProductStatus = item.ProductStatus,
|
|
|
WriteStatus = item.WriteStatus,
|
|
|
RfidEPC = item.RfidEPC,
|
|
|
WriteDelaySet = item.WriteDelaySet
|
|
|
};
|
|
|
Deviceinfo.Add(real_DataInfo);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 添加数据的方法
|
|
|
/// </summary>
|
|
|
/// <param name="iCombineId"></param>
|
|
|
/// <param name="tagInfos"></param>
|
|
|
public void AddRFIDData(string iCombineId, List<TagInfo> tagInfos)
|
|
|
{
|
|
|
Task.Run(() =>
|
|
|
{
|
|
|
App.Current.Dispatcher.Invoke(() =>
|
|
|
{
|
|
|
RFIDHistoryRecords.Insert(0, new RFIDRecord
|
|
|
{
|
|
|
OrderNumber = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).OrderNo,
|
|
|
LineNumber = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).LineNo,
|
|
|
ProductType = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).ProductType,
|
|
|
OriginalEPC = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).RfidEPC,
|
|
|
RFIDCode = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).RfidASCII,
|
|
|
ReadTime = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).ReadTime,
|
|
|
WriteTime = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).ReadTime,
|
|
|
WriteStatus = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).WriteStatus // 模拟1条失败数据
|
|
|
});
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region 设备状态检测
|
|
|
|
|
|
private void StartCheckStatus()
|
|
|
{
|
|
|
Task.Run(async () =>
|
|
|
{
|
|
|
while (true)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
#region RFID状态
|
|
|
//RefreshLogMessage("检测设备状态");
|
|
|
var batches = SplitListIntoBatches(rfidList, 10);
|
|
|
for (int i = 0; i < batches.Count; i++)
|
|
|
{
|
|
|
var currentBatch = batches[i];
|
|
|
// 显示当前批次信息(UI线程)
|
|
|
Console.WriteLine($"{DateTime.Now}开始检测第{i + 1}批(共{currentBatch.Count}个设备)\r\n");
|
|
|
|
|
|
// 异步检测当前批次的设备状态(不阻塞UI)
|
|
|
await DetectDeviceBatchAsync(currentBatch);
|
|
|
|
|
|
// 批次之间的间隔(最后一批无需等待)
|
|
|
if (i < batches.Count - 1)
|
|
|
{
|
|
|
Console.WriteLine($"{DateTime.Now}第{i + 1}批检测完成,共{batches.Count}批,等待{1000 / 1000}秒后检测下一批\r\n");
|
|
|
await Task.Delay(10);
|
|
|
}
|
|
|
}
|
|
|
#endregion RFID状态
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Log.Information($"监听设备状态异常:{ex.Message}");
|
|
|
}
|
|
|
await Task.Delay(1000 * 20);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
private List<List<RfidAbsractFactory>> SplitListIntoBatches(List<RfidAbsractFactory> sourceList, int batchSize)
|
|
|
{
|
|
|
var batches = new List<List<RfidAbsractFactory>>();
|
|
|
for (int i = 0; i < sourceList.Count; i += batchSize)
|
|
|
{
|
|
|
// 截取每批的设备(最后一批可能不足10个)
|
|
|
var batch = sourceList.Skip(i).Take(batchSize).ToList();
|
|
|
batches.Add(batch);
|
|
|
}
|
|
|
return batches;
|
|
|
}
|
|
|
|
|
|
private async Task DetectDeviceBatchAsync(List<RfidAbsractFactory> batch)
|
|
|
{
|
|
|
// 并行检测当前批次的设备(可选,根据接口性能调整)
|
|
|
var detectionTasks = batch.Select(device => DetectSingleDeviceAsync(device));
|
|
|
// 等待当前批次所有设备检测完成
|
|
|
await Task.WhenAll(detectionTasks);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 重连核心算法
|
|
|
/// </summary>
|
|
|
/// <param name="device"></param>
|
|
|
/// <returns></returns>
|
|
|
private async Task DetectSingleDeviceAsync(RfidAbsractFactory device)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
//基于心跳检测的断线重连机制
|
|
|
if (GloalVar.HeartBeatRecoard.TryGetValue(device.deviceid, out var value))
|
|
|
{
|
|
|
if (value.AddSeconds(15) < DateTime.Now)
|
|
|
{
|
|
|
await Reconnect(device);
|
|
|
Deviceinfo.FirstOrDefault(x => x.Deviceid == device.deviceid).IsOnline = "已连接";
|
|
|
}
|
|
|
}
|
|
|
else //第一次的逻辑
|
|
|
{
|
|
|
await Reconnect(device);
|
|
|
Deviceinfo.FirstOrDefault(x => x.Deviceid == device.deviceid).IsOnline = "已连接";
|
|
|
var res = false;
|
|
|
//无限获取心跳返回报文
|
|
|
Log.Information($"准备第一次获取心跳");
|
|
|
res = await device.Set_HeartBeat(5);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Log.Information($"更新RFID状态异常:{ex.Message}", ex);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 无限重连
|
|
|
/// </summary>
|
|
|
/// <param name="device"></param>
|
|
|
/// <returns></returns>
|
|
|
private async Task Reconnect(RfidAbsractFactory device)
|
|
|
{
|
|
|
var res = false;
|
|
|
do
|
|
|
{
|
|
|
await Task.Delay(1000);
|
|
|
Deviceinfo.FirstOrDefault(x => x.Deviceid == device.deviceid).IsOnline = "未连接";
|
|
|
Log.Information($"[{device.deviceid}]:[{device.ip}:{device.port}]连接中...");
|
|
|
res = await device.ConnectAsync(device.ip, device.port, device.deviceid);
|
|
|
}
|
|
|
while (!res);
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region 定时盘点
|
|
|
|
|
|
/// <summary>
|
|
|
/// 启动定时盘点
|
|
|
/// </summary>
|
|
|
private void StartInventoryTimer(string deviceId, int intervalSeconds)
|
|
|
{
|
|
|
StopInventoryTimer(deviceId);
|
|
|
var timer = new DispatcherTimer
|
|
|
{
|
|
|
Interval = TimeSpan.FromMilliseconds(intervalSeconds)
|
|
|
};
|
|
|
timer.Tick += (s, e) => OnInventoryTimerTick(deviceId);
|
|
|
timer.Start();
|
|
|
//OnInventoryTimerTick(deviceId);
|
|
|
_inventoryTimers[deviceId] = timer;
|
|
|
Log.Information($"设备 {deviceId} 启动定时盘点,间隔 {intervalSeconds} ms");
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 停止定时盘点
|
|
|
/// </summary>
|
|
|
private void StopInventoryTimer(string deviceId)
|
|
|
{
|
|
|
if (_inventoryTimers.TryGetValue(deviceId, out var timer))
|
|
|
{
|
|
|
timer.Stop();
|
|
|
_inventoryTimers.Remove(deviceId);
|
|
|
Log.Information($"设备 {deviceId} 停止定时盘点");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 定时盘点回调
|
|
|
/// </summary>
|
|
|
private async void OnInventoryTimerTick(string deviceId)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
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();
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
Log.Error($"设备 {deviceId} 定时盘点异常: {ex.Message}");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
}
|
|
|
}
|