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.

609 lines
20 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 CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.DependencyInjection;
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.Rfid;
using SlnMesnac.Rfid.Enum;
using SlnMesnac.Serilog;
using SlnMesnac.WPF.Attribute;
using SlnMesnac.WPF.Model;
using SlnMesnac.WPF.Page.IndexPage;
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.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Threading;
using TouchSocket.Core;
using TouchSocket.Sockets;
using static Microsoft.WindowsAPICodePack.Shell.PropertySystem.SystemProperties.System;
using Task = System.Threading.Tasks.Task;
namespace SlnMesnac.WPF.ViewModel.IndexPage
{
[RegisterAsSingletonAttribute]
public class ProductionLineViewModel : ObservableObject
{
private static StringChange _StringChange;
private String SerialNo = "";
private SerilogHelper _logger;
//容器里面的读写器集合
public List<RfidAbsractFactory> rfidList;
private AppConfig appConfig;
private DispatcherTimer _timer;
private RealReadDataService dataService = RealReadDataService.Instance;
private real_readdata NowReadData;
#region 关联属性
public ObservableCollection<string> Items { get; set; }
private string _QueryIsCheck = "";
public string QueryIsCheck
{
get { return _QueryIsCheck; }
set
{
_QueryIsCheck = value;
if (_QueryIsCheck != value)
{
SetProperty(ref _QueryIsCheck, value);
}
}
}
/// <summary>
/// 准备写入的列表
/// </summary>
private ObservableCollection<real_readdata> _preparedWriteList = new ObservableCollection<real_readdata>();
public ObservableCollection<real_readdata> PreparedWriteList
{
get { return _preparedWriteList; }
set
{
if (_preparedWriteList != value)
{
SetProperty(ref _preparedWriteList, value);
}
}
}
/// <summary>
/// 写入记录
/// </summary>
private ObservableCollection<real_readdata> _tempRecordList = new ObservableCollection<real_readdata>();
public ObservableCollection<real_readdata> TempRecordList
{
get { return _tempRecordList; }
set
{
if (_tempRecordList != value)
{
SetProperty(ref _tempRecordList, value);
}
}
}
/// <summary>
/// 日期时间
/// </summary>
private DateTime _currentDateTime;
public DateTime CurrentDateTime
{
get => _currentDateTime;
set
{
if (_currentDateTime != value)
{
SetProperty(ref _currentDateTime, value);
}
}
}
/// <summary>
/// 上一次写入状态
/// </summary>
private string _lastWriteState;
public string LastWriteState
{
get => _lastWriteState;
set
{
if (_lastWriteState != value)
{
SetProperty(ref _lastWriteState, value);
}
}
}
/// <summary>
/// 工作状态
/// </summary>
private string _workState;
public string WorkState
{
get => _workState;
set
{
if (_workState != value)
{
SetProperty(ref _workState, value);
}
}
}
/// <summary>
/// RFID连接状态
/// </summary>
private string _rfidConnectState;
public string RFIDConnectState
{
get => _rfidConnectState;
set
{
if (_rfidConnectState != value)
{
SetProperty(ref _rfidConnectState, value);
}
}
}
/// <summary>
/// 订单号
/// </summary>
private string _orderNo;
public string OrderNo
{
get => _orderNo;
set
{
if (_orderNo != value)
{
SetProperty(ref _orderNo, value);
}
}
}
/// <summary>
/// 产线号
/// </summary>
private string _lineNo;
public string LineNo
{
get => _lineNo;
set
{
if (_lineNo != value)
{
SetProperty(ref _lineNo, value);
}
}
}
/// <summary>
/// 带号
/// </summary>
private string _bindNo;
public string BindNo
{
get => _bindNo;
set
{
if (_bindNo != value)
{
SetProperty(ref _bindNo, value);
}
}
}
/// <summary>
/// 写入数量
/// </summary>
private string _writeCount;
public string WriteCount
{
get => _writeCount;
set
{
if (_writeCount != value)
{
SetProperty(ref _writeCount, value);
}
}
}
public RelayCommand<object> GenerateCodeCommand { get; set; }
public RelayCommand<object> ListClearCommand { get; set; }
public RelayCommand<object> HistoryClearCommand { get; set; }
public RelayCommand<object> HistoryPageCommand { get; set; }
public RelayCommand<object> AutoWriteCommand { get; set; }
public RelayCommand<object> RFIDWriteCommand { get; set; }
#endregion
public ProductionLineViewModel()
{
GenerateCodeCommand = new RelayCommand<object>(t => GenerateCode(t));
ListClearCommand = new RelayCommand<object>(t => ListClear(t));
HistoryClearCommand = new RelayCommand<object>(t => HistoryClear(t));
HistoryPageCommand = new RelayCommand<object>(t => HistoryPage(t));
AutoWriteCommand = new RelayCommand<object>(t => AutoWrite(t));
RFIDWriteCommand = new RelayCommand<object>(t => RFIDWrite(t));
// 构造函数里注册
_StringChange = App.ServiceProvider.GetService<StringChange>();
_logger = App.ServiceProvider.GetService<SerilogHelper>();
appConfig = App.ServiceProvider.GetService<AppConfig>();
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();
Items = new ObservableCollection<string>();
foreach (var rfid in rfidList)
{
Items.Add(rfid.FilterData);
}
WorkState = "空闲";
Log.Information("RFID输送带系统启动");
}
/// <summary>
/// 编码生成
/// </summary>
/// <param name="obj"></param>
private void GenerateCode(object obj)
{
PreparedWriteList.Clear();
if (!int.TryParse(WriteCount, out int count))
{
MessageBox.Show("请输入有效的写入数量!", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
for (int i = 1; i <= count; i++)
{
string writeString = OrderNo + LineNo + DateTime.Now.ToString("yy") + BindNo + i.ToString("D2");
PreparedWriteList.Add(new real_readdata()
{
//objid = Guid.NewGuid().ToString(),
orderno = OrderNo,
lineno = LineNo,
bindno = BindNo,
serialno = i.ToString("D2"),
rfidascii = writeString,
writestatus = "等待"
});
}
}
/// <summary>
/// 清除生成编码数据
/// </summary>
/// <param name="obj"></param>
private void ListClear(object obj)
{
if (MessageBox.Show("确认", "确定要清除已生成的数据吗?(该操作不可还原)", MessageBoxButtons.OKCancel) == DialogResult.OK)
{
PreparedWriteList.Clear();
}
}
/// <summary>
/// 清除历史数据
/// </summary>
/// <param name="obj"></param>
private void HistoryClear(object obj)
{
if (MessageBox.Show("确认", "确定要清除本次写入的数据吗?(可在查看历史中查询以往写入的标签)", MessageBoxButtons.OKCancel) == DialogResult.OK)
{
TempRecordList.Clear();
}
}
/// <summary>
/// 历史记录页面
/// </summary>
/// <param name="obj"></param>
private void HistoryPage(object obj)
{
HistorySearch window = new HistorySearch();
window.Show();
}
/// <summary>
/// 自动写入
/// </summary>
/// <param name="obj"></param>
private void AutoWrite(object obj)
{
//获取设备编号
if (string.IsNullOrEmpty(QueryIsCheck.ToString().Trim()))
{
MessageBox.Show("请选择产线!", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
}
/// <summary>
/// 手动写入
/// </summary>
/// <param name="obj"></param>
private void RFIDWrite(object obj)
{
try
{
//获取设备编号
if (string.IsNullOrEmpty(QueryIsCheck.ToString().Trim()))
{
MessageBox.Show("请选择产线!", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
real_readdata? data;
if (obj is real_readdata)
{
data = obj as real_readdata;
NowReadData = data;
}
else
{
return;
}
List<DeviceInfoConfig> DeviceInfos = appConfig.deviceInfoConfig.Where(x => x.Collectid == appConfig.StationCode && x.Name == QueryIsCheck.ToString().Trim() && x.Deleteflag == 0).ToList();
rfidList.FirstOrDefault(x => x.deviceid == DeviceInfos[0].Deviceid).Set_BeginIdentify().GetAwaiter().GetResult();
WorkState = "盘点中";
}
catch (Exception ex)
{
Log.Error($"手动写入异常:{ex.Message}");
}
}
/// <summary>
/// 接收到连续盘点标签返回
/// </summary>3
/// <param name="iCombineId"></param>
/// <param name="tagInfos"></param>
private async void RecvIdentifyData_Instance(string iCombineId, List<TagInfo> tagInfos)
{
try
{
//读到停止连续盘点
bool stopflag = await rfidList.FirstOrDefault(x => x.deviceid == iCombineId).Set_StopIdentify();
if (string.IsNullOrEmpty(NowReadData.serialno))
{
MessageBox.Show("错误,无序列号");
return;
}
WorkState = "写入中";
//写入 三次重写
bool writeflag = await rfidList.FirstOrDefault(x => x.deviceid == iCombineId).Set_Write(tagInfos[0].EPC, NowReadData.rfidascii);
if (!writeflag)
{
Log.Error($"第一次写入失败,重试中...");
writeflag = await rfidList.FirstOrDefault(x => x.deviceid == iCombineId).Set_Write(tagInfos[0].EPC, NowReadData.rfidascii);
if (!writeflag)
{
Log.Error($"第二次写入失败,重试中...");
writeflag = await rfidList.FirstOrDefault(x => x.deviceid == iCombineId).Set_Write(tagInfos[0].EPC, NowReadData.rfidascii);
if (!writeflag)
{
Log.Error($"第三次写入失败");
MessageBox.Show("三次写入失败,请重新开始盘点");
LastWriteState = "失败";
WorkState = "空闲";
return;
}
}
}
WorkState = "空闲";
NowReadData.rfidepc = tagInfos[0].EPCstring;
NowReadData.writetime = DateTime.Now;
NowReadData.writestatus = "已写入";
NowReadData.objid = Guid.NewGuid().ToString();
dataService.Helper.Insert(NowReadData);
int.TryParse(NowReadData.serialno, out int no);
App.Current.Dispatcher.Invoke(() =>
{
TempRecordList.Add(NowReadData);
PreparedWriteList[no - 1].writestatus = "已写入";
});
NowReadData = null!;
LastWriteState = "成功";
}
catch (Exception e)
{
Log.Error($"读结果准备写入时异常:{e.Message}");
}
}
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 = "",
};
real_DataInfos.Add(real_DataInfo);
}
}
#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);
}
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);
RFIDConnectState = "已连接";
}
else
{
RFIDConnectState = "已连接";
}
}
else
{
await Reconnect(device);
RFIDConnectState = "已连接";
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
{
RFIDConnectState = "未连接";
Log.Information($"[{device.deviceid}]:[{device.ip}:{device.port}]连接中...");
res = await device.ConnectAsync(device.ip, device.port, device.deviceid);
}
while (!res);
}
#endregion
}
}