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.

550 lines
24 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 HslCommunication.Enthernet;
using Microsoft.Extensions.DependencyInjection;
using Models;
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.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.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Threading;
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
{
private static StringChange _StringChange;
private String SerialNo = "";
private SerilogHelper _logger;
private ISqlSugarClient? sqlSugarClient;
//容器里面的读写器集合
public List<RfidAbsractFactory> rfidList;
private AppConfig appConfig;
public TcpServer _TcpServer;
private DispatcherTimer _timer;
private ObservableCollection<RFIDRecord> _rfidHistoryRecords = new ObservableCollection<RFIDRecord>();
public ObservableCollection<RFIDRecord> RFIDHistoryRecords
{
get { return _rfidHistoryRecords; }
set
{
_rfidHistoryRecords = value;
RaisePropertyChanged(() => RFIDHistoryRecords);
}
}
ChangeTypeViewModel ChangeTypeView;
/// <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>
/// RFID连接状态
/// </summary>
private string _rfidConnectState;
public string RFIDConnectState
{
get => _rfidConnectState;
set
{
if (_rfidConnectState != value)
{
_rfidConnectState = value;
RaisePropertyChanged(() => RFIDConnectState);
}
}
}
public ProductionLineViewModel()
{
GetOrderInfoCommand = new RelayCommand<object>(t => RefreshData(t));
ChangeTypeView = App.ServiceProvider.GetService<ChangeTypeViewModel>();
// 构造函数里注册
WeakReferenceMessenger.Default.Register<Real_DataInfo>(this, RefreshOrderNo);
_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输送带系统启动");
}
private void RefreshData(object? t)
{
Random random = new Random();
string ss = random.Next(10, 99).ToString();
string EPCstring = "JSSD" + ss;
List<TagInfo> tagInfos = new List<TagInfo>();
TagInfo tagInfo = new TagInfo()
{
EPCstring = "JSSD" + ss,
EPC = Encoding.ASCII.GetBytes(EPCstring),
};
tagInfos.Add(tagInfo);
Deviceinfo.FirstOrDefault(x => x.Deviceid == "10001").RfidEPC = _StringChange.bytesToHexStr(tagInfos[0].EPC, tagInfos[0].EPC.Length);
Deviceinfo.FirstOrDefault(x => x.Deviceid == "10001").RfidASCII = EPCstring;
Deviceinfo.FirstOrDefault(x => x.Deviceid == "10001").WriteStatus = "成功";
Deviceinfo.FirstOrDefault(x => x.Deviceid == "10001").ReadTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
Deviceinfo.FirstOrDefault(x => x.Deviceid == "10001").WriteTime = DateTime.Now.AddMinutes(1).ToString("yyyy-MM-dd HH:mm:ss");
RecvIdentifyData_Instance("10001", tagInfos);
}
public RelayCommand<object> GetOrderInfoCommand { get; set; }
private void RefreshOrderNo(object recipient, Real_DataInfo real_Data)
{
//查询当前订单产线最大序列号
List<real_readdata> real_Readdatas = sqlSugarClient.Queryable<real_readdata>().Where(expression: x => x.orderno == real_Data.OrderNo && x.lineno == real_Data.LineNo).ToList();
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();
}
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);
}
//Real_DataInfo real_DataInfo = new Real_DataInfo()
//{
// Name = "1",
// Deviceid = "10001",
// Connectstr = "192.168.0.1:20108",
// LineNo = "6#",
// OrderNo = "123456",
// ProductType = "整芯带",
// WriteCount = "0",
// RfidCount = "20",
// IsOnline = "未连接",
// RfidASCII = "0",
// RfidEPC = "0",
// ReadTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
// WriteTime = DateTime.Now.AddSeconds(10).ToString("yyyy-MM-dd HH:mm:ss"),
// ProductStatus = "生产中",
// WriteStatus = "写入成功",
//};
//Real_DataInfo real_DataInfo2 = new Real_DataInfo()
//{
// Name = "2",
// Deviceid = "10002",
// Connectstr = "127.0.0.1:20108",
// LineNo = "7#",
// OrderNo = "123456",
// ProductType = "整芯带",
// WriteCount = "0",
// RfidCount = "20",
// IsOnline = "未连接",
// RfidASCII = "0",
// RfidEPC = "0",
// ReadTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
// WriteTime = DateTime.Now.AddSeconds(10).ToString("yyyy-MM-dd HH:mm:ss"),
// ProductStatus = "生产中",
// WriteStatus = "写入成功",
//};
//real_DataInfos.Add(real_DataInfo);
//real_DataInfos.Add(real_DataInfo2);
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,
};
Deviceinfo.Add(real_DataInfo);
}
});
}
/// <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 = sqlSugarClient.Queryable<real_readdata>().Where(expression: x => x.rfidascii == epcascii).ToList();
//如果不存在则写入
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 = sqlSugarClient.Ado.Context.CopyNew().Insertable<real_readdata>(real_Readdata).ExecuteCommand();
//刷新界面
//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
{
}
}
public void RefreshEventArgs(string iCombineId, List<TagInfo> tagInfos)
{
try
{
App.Current.Dispatcher.BeginInvoke((Action)(() =>
{
Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId).RfidEPC = tagInfos[0].EPCstring;
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");
}));
}
catch (Exception ex)
{
Log.Information($"异常:{ex.Message}");
}
}
// 添加数据的方法(核心:添加前/后判断行数)
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();
});
}
private ObservableCollection<Real_DataInfo> _Deviceinfo = new ObservableCollection<Real_DataInfo>();
public ObservableCollection<Real_DataInfo> Deviceinfo
{
get { return _Deviceinfo; }
set
{
_Deviceinfo = value;
RaisePropertyChanged(() => Deviceinfo);
}
}
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
{
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);
}
}
}