You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

865 lines
34 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;
/// <summary>
/// 每个设备的写入状态(支持多线并行)
/// </summary>
private class DeviceWriteState
{
public bool IsVerify;
public int WriteTime;
public string LastWrite = "";
public string Real_LastRFIDEPC = "";
public CancellationTokenSource? VerifyCts;
public CancellationTokenSource? WriteCts;
}
private Dictionary<string, DeviceWriteState> _deviceStates = new();
private DeviceWriteState GetDeviceState(string deviceId)
{
if (!_deviceStates.TryGetValue(deviceId, out var state))
{
state = new DeviceWriteState();
_deviceStates[deviceId] = state;
}
return state;
}
#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
{
var state = GetDeviceState(iCombineId);
state.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 (!state.IsVerify)
{
//写入前等待标签稳定
if (!state.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");
//拼接订单号写入标签OrderNo + 处理后的ProductOrder + 序号
string processedProductOrder = ProcessProductOrder(deviceInfo.ProductOrder);
string WriteData = deviceInfo.OrderNo + processedProductOrder + deviceInfo.SerialNo;
deviceInfo.CurrentState = "写入中";
//上次读的EPC
//LastRFIDEPC = tagInfos[0].EPCstring;
//保存最原始的EPC仅第一次读取时保存后续重试不覆盖
if (string.IsNullOrEmpty(state.Real_LastRFIDEPC))
{
state.Real_LastRFIDEPC = tagInfos[0].EPCstring;
}
//写入前暂停心跳和连续盘点
StopInventoryTimer(iCombineId);
await rfidInfo.Set_HeartBeat(0);
await Task.Delay(100);
//暂停订单自动刷新,防止写入过程中订单切换
WeakReferenceMessenger.Default.Send(string.Empty, "PauseOrderRefresh");
//处理写入字符串,并写入
//var originBytes = tagInfos[0].EPC.Where(b => b != 0x00).ToArray();
bool writeflag = await rfidInfo.Set_Write(tagInfos[0].EPC, WriteData);
state.WriteTime++;
if (writeflag) //写入成功
{
state.LastWrite = WriteData;
state.IsVerify = true;
state.WriteTime = 0;
//开始二次验证
await rfidInfo.Set_BeginIdentify();
// 启动验证超时检测
state.VerifyCts?.Cancel();
state.VerifyCts = new CancellationTokenSource();
var token = state.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($"第{state.WriteTime + 1}次写入失败,重试中...");
//重试前再读取一次标签
await rfidInfo.Set_BeginIdentify();
//设置下次读取超时
state.WriteCts?.Cancel();
state.WriteCts = new CancellationTokenSource();
var token = state.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);
state.WriteTime = 0;
}
catch (TaskCanceledException) { }
}, token);
StartInventoryTimer(iCombineId, deviceConfig.InventoryIntervalSeconds.Value);
await rfidInfo.Set_HeartBeat(5);
await Task.Delay(100);
}
return;
}
else
{
await Task.Run(async () =>
{
await Task.Delay(1000);
await rfidInfo!.Set_BeginIdentify();
deviceInfo.CurrentState = "盘点中";
});
}
}
else //二次验证流程
{
var judgeString = Encoding.ASCII.GetString(tagInfos[0].EPC);
judgeString = judgeString.Replace("\0", "");
//二次验证如果不通过 重新开始盘点
if (judgeString != state.LastWrite)
{
// 读到标签但数据不匹配,重置超时(标签仍在天线范围内)
state.VerifyCts?.Cancel();
state.VerifyCts = new CancellationTokenSource();
var token = state.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);
state.IsVerify = false;
//state.Real_LastRFIDEPC = LastRFIDEPC;
rfidInfo.Set_BeginIdentify().GetAwaiter().GetResult();
deviceInfo.CurrentState = "盘点中";
return;
}
else //二次验证通过
{
state.VerifyCts?.Cancel();
Log.Information($"验证成功");
//插入成功记录
await DataAdd(iCombineId, tagInfos, true);
return;
}
}
}
catch (Exception e)
{
Log.Error($"读结果准备写入时异常:{e.Message}");
var deviceInfo = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId);
if (deviceInfo != null)
deviceInfo.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 state = GetDeviceState(iCombineId);
var deviceConfig = appConfig.deviceInfoConfig.FirstOrDefault(x => x.Deviceid == iCombineId);
state.IsVerify = false;
deviceInfo.WriteTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
deviceInfo.WriteStatus = isSuccess ? "成功" : "失败";
deviceInfo.LastWriteState = isSuccess ? "成功" : "失败";
deviceInfo.RfidASCII = state.LastWrite;
deviceInfo.RfidEPC = state.Real_LastRFIDEPC;
deviceInfo.SerialNo = (Convert.ToInt32(deviceInfo.SerialNo) + 1).ToString("D2");
//更新下一个要写入的EPC预览
deviceInfo.NextWriteEPC = deviceInfo.OrderNo + ProcessProductOrder(deviceInfo.ProductOrder) + deviceInfo.SerialNo;
//保存写入记录
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,
productorder = ProcessProductOrder(deviceInfo.ProductOrder),
rfidepc = deviceInfo.RfidEPC,
rfidascii = state.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 = "";
state.Real_LastRFIDEPC = "";
state.LastWrite = "";
//写入完成,恢复订单自动刷新
WeakReferenceMessenger.Default.Send(string.Empty, "ResumeOrderRefresh");
await rfidInfo.Set_BeginIdentify();
await Task.Delay(100);
StartInventoryTimer(iCombineId, deviceConfig.InventoryIntervalSeconds.Value);
await rfidInfo.Set_HeartBeat(5);
deviceInfo.CurrentState = "盘点中";
return;
}
/// <summary>
/// 处理ProductOrder去掉前导字母和中间的"-"
/// 例:"GS426-0250" → "4260250""GSW426-0250" → "4260250"
/// </summary>
private static string ProcessProductOrder(string productOrder)
{
if (string.IsNullOrEmpty(productOrder))
return "";
return System.Text.RegularExpressions.Regex.Replace(productOrder, @"^[A-Za-z]+|-", "");
}
#endregion
#region 数据流相关
/// <summary>
/// 开始订单初次流程
/// </summary>
/// <param name="recipient"></param>
/// <param name="real_Data"></param>
private void RefreshOrderNo(object recipient, Real_DataInfo real_Data)
{
var deviceInfo = Deviceinfo.FirstOrDefault(x => x.Deviceid == real_Data.Deviceid);
var deviceConfig = appConfig.deviceInfoConfig.FirstOrDefault(x => x.Deviceid == real_Data.Deviceid);
//检测OrderNo或ProductOrder是否发生变化变化则重置计数器
bool orderChanged = deviceInfo.OrderNo != real_Data.OrderNo
|| deviceInfo.ProductOrder != real_Data.ProductOrder;
if (orderChanged)
{
//查询当前订单+产品订单下的最大序列号
string processedPo = ProcessProductOrder(real_Data.ProductOrder);
List<real_readdata> real_Readdatas = databaseService._helper.Query(x =>
x.orderno == real_Data.OrderNo && x.productorder == processedPo);
string SNo = "";
if (real_Readdatas.Count > 0)
{
SNo = real_Readdatas.Max(x => x.serialno);
SNo = (Convert.ToInt32(SNo) + 1).ToString("D2");
}
else
{
SNo = "01";
}
deviceInfo.SerialNo = SNo;
}
deviceInfo.OrderNo = real_Data.OrderNo;
deviceInfo.ProductType = real_Data.ProductType;
deviceInfo.LineNo = real_Data.LineNo;
deviceInfo.RfidCount = real_Data.RfidCount;
deviceInfo.NextProductNo = real_Data.NextProductNo;
deviceInfo.ProductOrder = real_Data.ProductOrder;
//更新下一个要写入的EPC预览
deviceInfo.NextWriteEPC = deviceInfo.OrderNo + ProcessProductOrder(deviceInfo.ProductOrder) + deviceInfo.SerialNo;
rfidList.FirstOrDefault(x => x.deviceid == real_Data.Deviceid).Set_BeginIdentify().GetAwaiter().GetResult();
var state = GetDeviceState(real_Data.Deviceid);
state.IsVerify = false;
state.Real_LastRFIDEPC = "";
deviceInfo.CurrentState = "盘点中";
// 启动定时盘点
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);
}
var deviceInfo = Deviceinfo.FirstOrDefault(x => x.Deviceid == e);
if (deviceInfo != null)
deviceInfo.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(() =>
{
var deviceInfo = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId);
if (deviceInfo == null) return;
RFIDHistoryRecords.Insert(0, new RFIDRecord
{
OrderNumber = deviceInfo.OrderNo,
LineNumber = deviceInfo.LineNo,
ProductType = deviceInfo.ProductType,
OriginalEPC = deviceInfo.RfidEPC,
RFIDCode = deviceInfo.RfidASCII,
ReadTime = deviceInfo.ReadTime,
WriteTime = deviceInfo.ReadTime,
WriteStatus = deviceInfo.WriteStatus,
DeviceId = iCombineId
});
//更新过滤后的历史记录
RefreshFilteredRecords();
});
});
}
/// <summary>
/// 当前选中的设备IDTab切换时更新
/// </summary>
private string? _selectedDeviceId;
public string? SelectedDeviceId
{
get => _selectedDeviceId;
set
{
if (_selectedDeviceId != value)
{
_selectedDeviceId = value;
RaisePropertyChanged(() => SelectedDeviceId);
RefreshFilteredRecords();
}
}
}
private ObservableCollection<RFIDRecord> _filteredRFIDHistoryRecords = new();
/// <summary>
/// 按选中设备过滤后的RFID历史记录
/// </summary>
public ObservableCollection<RFIDRecord> FilteredRFIDHistoryRecords
{
get => _filteredRFIDHistoryRecords;
set
{
_filteredRFIDHistoryRecords = value;
RaisePropertyChanged(() => FilteredRFIDHistoryRecords);
}
}
private void RefreshFilteredRecords()
{
var filtered = string.IsNullOrEmpty(_selectedDeviceId)
? RFIDHistoryRecords.ToList()
: RFIDHistoryRecords.Where(x => x.DeviceId == _selectedDeviceId).ToList();
FilteredRFIDHistoryRecords.Clear();
foreach (var item in filtered)
{
FilteredRFIDHistoryRecords.Add(item);
}
}
#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);
await rfid.Set_BeginIdentify();
}
}
catch (Exception ex)
{
Log.Error($"设备 {deviceId} 定时盘点异常: {ex.Message}");
}
}
#endregion
}
}