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.

593 lines
22 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;
#region 关联属性
/// <summary>
/// 历史遗留的达芬
/// </summary>
private ObservableCollection<Real_DataInfo> _Deviceinfo = new ObservableCollection<Real_DataInfo>();
public ObservableCollection<Real_DataInfo> Deviceinfo
{
get { return _Deviceinfo; }
set
{
if (_Deviceinfo != value)
{
SetProperty(ref _Deviceinfo, 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>
/// 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;
});
StartCheckStatus();
//GetRFIDHistoryRecords();
_currentDateTime = DateTime.Now;
_timer = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(1) // 每秒更新一次
};
_timer.Tick += (s, e) =>
{
CurrentDateTime = DateTime.Now;
};
_timer.Start();
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)
{
}
/// <summary>
/// 手动写入
/// </summary>
/// <param name="obj"></param>
private void RFIDWrite(object obj)
{
real_readdata? data;
if (obj is real_readdata)
{
data = obj as real_readdata;
}
else
{
return;
}
//rfidList.FirstOrDefault(x => x.deviceid == iCombineId)
}
/// <summary>
/// 接收到连续盘点标签返回
/// </summary>
/// <param name="iCombineId"></param>
/// <param name="tagInfos"></param>
private async void RecvIdentifyData_Instance(string iCombineId, List<TagInfo> tagInfos)
{
string info = "";
try
{
if (string.IsNullOrEmpty(Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).OrderNo))
{
MessageBox.Show("请先获取MES订单号", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
//读到停止连续盘点
bool stopflag = await rfidList.FirstOrDefault(x => x.deviceid == iCombineId).Set_StopIdentify();
//查询数据库是否已存在记录
bool iflag = false;
string epcascii = Encoding.ASCII.GetString(tagInfos[0].EPC);
epcascii = epcascii.Replace("\0", "");
List<real_readdata> real_Readdatas = dataService.Helper.Query(x => x.rfidascii == epcascii);
//如果不存在则写入
if (real_Readdatas.Count <= 0)
//if (true)
{
if (string.IsNullOrEmpty(Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).SerialNo))
{
return;
}
Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).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
+ DateTime.Now.ToString("yy")
+ Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).NextProductNo
+ Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).SerialNo;
//写入 三次重写
bool writeflag = await rfidList.FirstOrDefault(x => x.deviceid == iCombineId).Set_Write(tagInfos[0].EPC, WriteData);
if (!writeflag)
{
Log.Error($"第一次写入失败,重试中...");
writeflag = await rfidList.FirstOrDefault(x => x.deviceid == iCombineId).Set_Write(tagInfos[0].EPC, WriteData);
if (!writeflag)
{
Log.Error($"第二次写入失败,重试中...");
writeflag = await rfidList.FirstOrDefault(x => x.deviceid == iCombineId).Set_Write(tagInfos[0].EPC, WriteData);
if (!writeflag)
{
Log.Error($"第三次写入失败,立即开始重新盘点");
LastWriteState = "失败";
rfidList.FirstOrDefault(x => x.deviceid == iCombineId).Set_BeginIdentify().GetAwaiter().GetResult();
return;
}
}
}
Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).WriteTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).WriteStatus = "成功";
LastWriteState = "成功";
Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).RfidASCII = WriteData;
Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).RfidEPC = tagInfos[0].EPCstring;
Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).SerialNo = (Convert.ToInt32(Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).SerialNo) + 1).ToString("D2");
//保存写入记录
real_readdata real_Readdata = new real_readdata()
{
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,
rfidascii = WriteData,
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
};
var a = dataService.Helper.Insert(real_Readdata);
//刷新界面
//Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).RfidASCII = Encoding.ASCII.GetString(tagInfos[0].EPC);
//Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).ReadTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
//RefreshEventArgs(iCombineId, tagInfos);
AddRFIDData(iCombineId, tagInfos);
}
await Task.Run(async () =>
{
await Task.Delay(1000);
await rfidList.FirstOrDefault(x => x.deviceid == iCombineId)!.Set_BeginIdentify();
});
}
catch (Exception e)
{
Log.Error($"读结果准备写入时异常:{e.Message}");
}
finally
{
}
}
/// <summary>
/// 添加数据的方法(核心:添加前/后判断行数)
/// </summary>
/// <param name="iCombineId"></param>
/// <param name="tagInfos"></param>
public void AddRFIDData(string iCombineId, List<TagInfo> tagInfos)
{
//// 1. 判断当前行数是否>10是则清空
//if (RFIDHistoryRecords.Count >= 10)
//{
// RFIDHistoryRecords.Clear();
//}
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条失败数据
//});
//RFIDHistoryRecords.OrderByDescending(x => x.ReadTime).ToList();
});
}
#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
}
}