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.

915 lines
32 KiB
C#

using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.ObjectModel;
using log4net;
using Aucma.Core.CodeBinding.Common;
using LiveCharts;
using Admin.Core.Model;
using Admin.Core.Service;
using LiveCharts.Wpf;
using Admin.Core.IService;
using Microsoft.Extensions.DependencyInjection;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Collections;
using Aucma.Core.CodeBinding.Models;
using System.Reflection.Emit;
using NPOI.SS.Formula.Functions;
using System.Threading;
using System.Windows.Threading;
using static Admin.Core.Service.CodeBindingRecordServices;
using System.Windows.Data;
using System.Windows;
using System.Linq;
using System.Collections.Generic;
using NPOI.HSSF.Record;
using SqlSugar;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Admin.Core.Model.ViewModels;
using System.Windows.Media;
using System.Drawing;
using Brushes = System.Windows.Media.Brushes;
using Admin.Core.Model.Model_New;
using Microsoft.IdentityModel.Logging;
using static Npgsql.Replication.PgOutput.Messages.RelationMessage;
using Aucma.Core.HwPLc;
using System.Windows.Documents;
using Admin.Core.Common;
using Aucma.Core.CodeBinding.Business;
using Aucma.Core.Scanner;
using LiveCharts.Defaults;
using Admin.Core.Socket;
using System.Runtime.ConstrainedExecution;
/*
*
*/
namespace Aucma.Core.CodeBinding.ViewModels
{
public partial class IndexPageViewModel : ObservableObject
{
private static readonly log4net.ILog log = LogManager.GetLogger(typeof(IndexPageViewModel));
private readonly ICodeBindingRecordServices? _codeBindingRecordServices;
private readonly IBaseMaterialInfoServices? _baseMaterialInfoServices;
private readonly IBaseBomInfoServices? _baseBomInfoServices;
private readonly IPrintBarCodeServices? _printBarCodeServices;
// 过点数据表物料完成记录MaterialCompletion
private readonly IMaterialCompletionServices? _iMaterialCompletionServices;
// 静态变量存code1,mes条码
private static string code1Str = string.Empty;
// 静态变量存code2,SN条码
private static string code2Str = string.Empty;
//配置文件扫码器列表
private static List<ScannerModel> allScanners = Appsettings.app<ScannerModel>("ScannerServer").ToList();
// mes扫码器ip
private static string MesScannerIp = allScanners.First(x => x.Name == "mes扫码器").Ip;
// sn扫码器ip
private static string SnScannerIp = allScanners.First(x => x.Name == "sn扫码器").Ip;
private SpeechStr speechStr = SpeechStr.Instance;
private string ProductLineCode = Appsettings.app("StationInfo", "ProductLineCode");
// 质检记录
private readonly IReportQualityInspectionServices? _reportQualityInspectionServices;
//异常记录,记录质检失败情况
private readonly IExceptionRecordServices? exceptionRecordServices;
public IndexPageViewModel()
{
1 year ago
try
{
_codeBindingRecordServices = App.ServiceProvider.GetService<ICodeBindingRecordServices>();
_baseBomInfoServices = App.ServiceProvider.GetService<IBaseBomInfoServices>();
_baseMaterialInfoServices = App.ServiceProvider.GetService<IBaseMaterialInfoServices>();
_reportQualityInspectionServices = App.ServiceProvider.GetService<IReportQualityInspectionServices>();
_printBarCodeServices = App.ServiceProvider.GetService<IPrintBarCodeServices>();
_iMaterialCompletionServices = App.ServiceProvider.GetService<IMaterialCompletionServices>();
exceptionRecordServices = App.ServiceProvider.GetService<IExceptionRecordServices>();
// Business.MvCodeHelper.ReceiveCodeEvent += ReceiveCode;
// Business.MvCodeHelper.BindingCodeEvent += BindingCode;
// Business.MvCodeHelper.NoReadEvent += ReceiveNoRead;
TouchSocketService.ReceiveCodeDelegateEvent += ReceiveCode;
TouchSocketService.NoReadReceiveEvent += ReceiveNoRead;
GunBusiness.BindingReceiveCodeEvent += BindingCode;
GunBusiness.RefreshMaterialCodeStrEvent += ReceiveCode;
MsgUIColor = "White";
1 year ago
LoadData();
//实时绑定条码和实时下发plc放行信号
realBindingAndSendPlc();
1 year ago
LoadCharts();
1 year ago
}
catch (Exception ex)
1 year ago
{
log.Error(ex);
1 year ago
}
1 year ago
}
/// <summary>
/// 实时绑定条码和实时下发plc放行信号
/// </summary>
public void realBindingAndSendPlc()
{
string tempCode1;
string tempCode2;
// 实时绑定条码
//Task.Run(() =>
//{
// while (true)
// {
// try
// {
// if (!string.IsNullOrEmpty(code1Str) && !string.IsNullOrEmpty(code2Str))
// {
// BindingCode(code1Str, code2Str);
// code1Str = string.Empty;
// code2Str = string.Empty;
// }
// }
// catch (Exception ex)
// {
// code1Str = string.Empty;
// code2Str = string.Empty;
// Console.WriteLine(ex.ToString());
// }
// Thread.Sleep(500);
// }
//});
// 心跳线程
Task.Run(() =>
1 year ago
{
try
1 year ago
{
Thread.Sleep(3000);
var obj = PlcHelper.melsecList.FirstOrDefault(d => d.EquipName.Equals("条码绑定Plc"));
if (obj != null)
{
while (true)
{
SendHeart(obj, "0");
Thread.Sleep(1000);
SendHeart(obj, "1");
Thread.Sleep(1000);
}
}
}
catch (Exception ex)
{
log.Error(ex.ToString());
1 year ago
}
});
#region 暂未启用
// 实时下发plc放行信号
//Task.Run(() =>
//{
// try
// {
// while (true)
// {
// Thread.Sleep(3000);
// var obj = PlcHelper.melsecList.FirstOrDefault(d => d.EquipName.Equals("条码绑定Plc"));
// if (obj != null && obj.plc.IsConnected)
// {
// CodeBindingRecord record = _codeBindingRecordServices.FirstAsync(x => x.isPlcPass == 1 && x.RecordTime2 >= System.DateTime.Now.AddDays(-1)).Result;
// if (record != null)
// {
// // 下发plc放行信号
// RefreshAndWriteLog($"条码[{record.BoxCode}]下发plc放行信号等待plc反馈...");
// if (SendPlcPass(obj))
// {
// RefreshAndWriteLog($"条码[{record.BoxCode}]放行成功");
// record.isPlcPass = 2;
// _ = _codeBindingRecordServices.UpdateAsync(record).Result;
// LoadData();
// }
// else
// {
// RefreshAndWriteLog("等待Plc反馈信号5秒超时!");
// }
// }
// }
// Thread.Sleep(1000);
// }
// }
// catch (Exception ex)
// {
// log.Error(ex.ToString());
// }
//});
#endregion
1 year ago
}
#region 加载DataGrid数据
private async void LoadData()
{
try
{
// LoadCharts();
1 year ago
List<CodeBindingRecord> records = null;
records = _codeBindingRecordServices.QueryAsync(x => x.BoxCode != null && x.RecordTime2 >= DateTime.Today && x.RecordTime2 < DateTime.Today.AddDays(1)).Result;
if (records != null && records.Count > 0)
{
records = records.OrderBy(x => x.RecordTime2).ToList();
Application.Current.Dispatcher.Invoke(() =>
{
ListItems.Clear();
foreach (CodeBindingRecord record in records)
{
ListItems.Insert(0, new ReaderInfo()
{
No = ListItems.Count + 1,
BoxCode = record.BoxCode,
ProductCode = record.ProductCode,
BoxName = record.BoxName,
BindingResult = record.BindingResult,
10 months ago
IsPass = record.IsPass==1?"自动":"手动",
RecordTime = record.RecordTime2.ToString()
});
}
});
}
}
catch (Exception)
{
}
}
// 修改为统计近一天白班或夜班
private async void LoadCharts()
{
try
{
List<CodeBindCharts> list = _codeBindingRecordServices.QueryCharts().Result;
if (list == null || list.Count == 0) return;
10 months ago
var result = from m in list
group m by GetSubstringBetweenCommas(m.BoxName) into g
select new CodeBindCharts()
{
BoxName = g.Key,
Amount = g.Sum(m => m.Amount)
};
10 months ago
App.Current.Dispatcher.Invoke(() =>
{
ProductionHourList.Clear();
ModelStatistics.Clear();
// 图表赋值
ChartValues<ObservablePoint> achievement = new ChartValues<ObservablePoint>();
int i = 0;
double total = 0;
10 months ago
foreach (var item in result)
{
10 months ago
ProductionHourList.Add(item.BoxName);
achievement.Add(new ObservablePoint(i, item.Amount));
total += item.Amount;
i++;
}
//加一个汇总柱状图
ProductionHourList.Add("合计");
achievement.Add(new ObservablePoint(i, total));
var column = new ColumnSeries();
column.DataLabels = true;
column.Title = "型号";
column.Values = achievement;
column.Foreground = Brushes.White;
ModelStatistics.Add(column);
});
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// 截取两个逗号之间的字符串
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
static string GetSubstringBetweenCommas(string input)
{
if (input == null) return null;
// 找到第一个逗号的位置
int firstCommaIndex = input.IndexOf(',');
if (firstCommaIndex != -1)
{
// 找到第二个逗号的位置
int secondCommaIndex = input.IndexOf(',', firstCommaIndex + 1);
if (secondCommaIndex != -1)
{
// 使用Substring截取第一个逗号和第二个逗号之间的字符
return input.Substring(firstCommaIndex + 1, secondCommaIndex - firstCommaIndex - 1);
}
else
{
return null;
}
}
else
{
return null;
}
}
#endregion
#region 参数定义
/// <summary>
/// 条码1
/// </summary>
private string code1 = string.Empty;
public string Code1
{
get { return code1; }
set
{
code1 = value;
OnPropertyChanged(nameof(Code1));
}
}
/// <summary>
/// 条码1扫描时间
/// </summary>
private string code1Time = string.Empty;
public string Code1Time
{
get { return code1Time; }
set
{
code1Time = value;
OnPropertyChanged(nameof(Code1Time));
}
}
/// <summary>
/// 条码2
/// </summary>
private string code2 = string.Empty;
public string Code2
{
get { return code2; }
set
{
code2 = value;
OnPropertyChanged(nameof(Code2));
}
}
///// <summary>
///// 条码2扫描时间
///// </summary>
private string code2Time = string.Empty;
public string Code2Time
{
get { return code2Time; }
set
{
code2Time = value;
OnPropertyChanged(nameof(Code2Time));
}
}
/// <summary>
/// 绑定提示信息
/// </summary>
private string bindingInfo = string.Empty;
public string BindingInfo
{
get { return bindingInfo; }
set
{
bindingInfo = value;
OnPropertyChanged(nameof(BindingInfo));
}
}
#region 日产量柱状图X轴日期
/// <summary>
/// 日产量柱状图X轴日期
/// </summary>
private List<string> productionHourList = new List<string>();
public List<string> ProductionHourList
{
get { return productionHourList; }
set { productionHourList = value; }
}
#endregion
#region 型号统计柱状图
/// <summary>
/// 型号统计柱状图
/// </summary>
private SeriesCollection modelStatistics = new SeriesCollection();
public SeriesCollection ModelStatistics
{
get { return modelStatistics; }
set { modelStatistics = value; }
}
#endregion
#endregion
#region 初始化datagrid
private ObservableCollection<ReaderInfo> listItems = new ObservableCollection<ReaderInfo>() { };
public ObservableCollection<ReaderInfo> ListItems
{
get { return listItems; }
set
{
listItems = value;
OnPropertyChanged();//属性通知
}
}
#endregion
/// <summary>
/// NoRead处理
/// </summary>
/// <param name="scannerIp"></param>
private async void ReceiveNoRead(string scannerIp)
{
// ScannerModel model = allScanners.FirstOrDefault(x => x.Ip == scannerIp);
if (scannerIp == MesScannerIp)
{
// log.Info("MES条码NoRead:");
SendPlcStop();
Clear();
RefreshAndWriteLog("MES条码未扫描到,NoRead报警,线体停止,请重新扫描!",true);
}
else if (SnScannerIp == scannerIp)
{
SendPlcStop();
Clear();
RefreshAndWriteLog("SN条码未扫描到,NoRead报警,线体停止,请重新扫描!", true);
}
speechStr.SpeakAsync("扫码失败,请补扫");
}
/// <summary>
/// 页面扫码信息清空
/// </summary>
public void Clear()
{
code1Str = string.Empty;
code2Str = string.Empty;
// 页面扫码信息清空
Code1 = string.Empty;
Code2 = string.Empty;
Code1Time = string.Empty;
Code2Time = string.Empty;
BindingInfo = string.Empty;
}
/// <summary>
/// 接收扫码器传输的条码扫码器ip
/// </summary>
/// <param name="code1"></param>
/// <param name="scannerIp"></param>
private void ReceiveCode(string scannerIp, string codeStr)
{
// ScannerModel model = allScanners.FirstOrDefault(x => x.Ip == scannerIp);
if (MesScannerIp == scannerIp)
{
log.Info("扫描到MES条码:" + codeStr);
// 全局变量赋值SN码扫描后使用
code1Str = codeStr;
RefreshCode1(codeStr);
if (!string.IsNullOrEmpty(code1Str) && !string.IsNullOrEmpty(code2Str))
{
BindingCode(code1Str, code2Str);
code1Str = string.Empty;
code2Str = string.Empty;
}
}
else if (SnScannerIp == scannerIp)
{
// Clear();
log.Info("扫描到成品条码:" + codeStr);
// 1.刷新界面条码信息
// 全局变量赋值,mes条码扫描后使用
code2Str = codeStr;
RefreshCode2(codeStr);
if (!string.IsNullOrEmpty(code1Str) && !string.IsNullOrEmpty(code2Str))
{
BindingCode(code1Str, code2Str);
code1Str = string.Empty;
code2Str = string.Empty;
}
}
#region
// 2.创建任务更新数据库条码1
// CodeBindingRecord codeRecord = new CodeBindingRecord();
// codeRecord.BoxCode = code1;
// codeRecord.BoxName = "去别的数据库查询";
//List<BaseBomInfo> bomInfo = await _baseBomInfoServices.QueryAsync(x => x.MaterialCode == code);
//string aa = bomInfo.FirstOrDefault().MaterialName;
// codeRecord.RecordTime1 = time;
// int a = await _codeBindingRecordServices.AddAsync(codeRecord);
1 year ago
// 页面刷新ListItems
//await Application.Current.Dispatcher.InvokeAsync(() =>
//{
// // 在 UI 线程上操作列表
// ListItems.Insert(0, new ReaderInfo() { No = codeRecord.ObjId, BoxCode = codeRecord.BoxCode, RecordTime = codeRecord.RecordTime1.ToString() });
//});
//log.Info("条码1记录更新");
#endregion
}
private void RefreshCode1(string code1)
{
DateTime time = System.DateTime.Now;
Code1 = code1;
Code1Time = time.ToString();
}
private void RefreshCode2(string code2)
{
DateTime time = System.DateTime.Now;
Code2 = code2;
Code2Time = time.ToString();
}
/// <summary>
/// 提示信息刷新并且存日志
/// </summary>
/// <param name="logStr"></param>
private void RefreshAndWriteLog(string logStr,bool warnflag=false)
{
TimeSpan currentTime = DateTime.Now.TimeOfDay;
// DateTime time = System.DateTime.Now;
string timeString = currentTime.ToString(@"hh\:mm\:ss");
BindingInfo = timeString + ":" + logStr;
if(warnflag)
{
MsgUIColor = "Red";
}
else
{
MsgUIColor = "White";
}
log.Info(BindingInfo);
}
/// <summary>
/// 提示信息-颜色
/// </summary>
public string msgUIColor;
public string MsgUIColor
{
get => msgUIColor;
set => SetProperty(ref msgUIColor, value);
}
/// <summary>
/// 条码绑定
/// </summary>
/// <param name="code1">MES码</param>
/// <param name="code2">SN码</param>
10 months ago
/// <param name="flag">1为自动扫描2为手动扫描</param>
public void BindingCode(string code1, string code2,int flag =1)
{
try
{
if (code1.Substring(0, 1) != "B")
{
speechStr.SpeakAsync("扫码失败,请补扫");
RefreshAndWriteLog("MES码:" + code1 + ",扫描错误,请重新扫描!");
SendPlcStop();
return;
}
if (code2.Length != 20)
{
speechStr.SpeakAsync("扫码失败,请补扫");
RefreshAndWriteLog("SN码:" + code2 + ",扫描错误,请重新扫描!");
SendPlcStop();
return;
}
#region 终检校验-未查到终检合格记录即为质检不合格
ReportQualityInsPection qualityList = _reportQualityInspectionServices.JudgeIsQualified(code1);
if (qualityList == null)
{
SendPlcStop();
RefreshAndWriteLog($"终检失败!! 箱体码{code1}未查询到终检合格记录,请重新终检!",true);
speechStr.SpeakAsync("终检失败,请终检");
AddExceptionRecord(code1, $"终检失败!! 箱体码{code1}未查询到终检合格记录,请重新终检!", 4);
return;
}
#endregion
RefreshAndWriteLog("开始绑定MES条码:" + code1 + " SN条码:" + code2);
// 1.数据库查询各个工序质检结果,不合格报警
//// 2.查询条码绑定记录表(内胆箱壳绑定处就应该插入记录)绑定SN码
int Repeatflag = 0;
CodeBindingRecord record = _codeBindingRecordServices.FirstAsync(x => x.BoxCode == code1).Result;
if (record == null)
{
RefreshAndWriteLog("未查询到MES条码记录,集存库未绑定箱壳内胆");
//return;
// 没有记录重新插入一条
record = new CodeBindingRecord();
}
else
{
Repeatflag = 1;
}
1 year ago
BaseMaterialInfo materialInfo = _baseMaterialInfoServices.FirstAsync(x => x.MaterialCode == code1.Substring(7, 10)).Result;
if (materialInfo == null)
{
record.BoxName = "";
}
else
{
record.BoxName = materialInfo.MaterialName;
}
record.BoxCode = code1;
record.ProductCode = code2;
//record.RecordTime1 = System.DateTime.Now;
record.RecordTime2 = System.DateTime.Now;
10 months ago
record.IsPass = flag;
record.BindingResult = "成功";
bool result = false;
if (Repeatflag == 0)
{ // 没有记录,新加
result = _codeBindingRecordServices.AddAsync(record).Result > 0 ? true : false;
}
else if (Repeatflag == 1)
{
result = _codeBindingRecordServices.UpdateAsync(record).Result;
}
if (result)
{
RefreshAndWriteLog("条码【" + record.BoxCode + "】与SN码【" + record.ProductCode + "】绑定成功");
#region 更新过点数据,插入记录到MATERIAL_COMPLETION表
10 months ago
PrintBarCode print = _printBarCodeServices.FirstAsync(x => x.MaterialBarcode == code1).Result;
if (print == null) return;
MaterialCompletion completion = new MaterialCompletion();
completion.OrderCode = print.OrderCode;
completion.MaterialBarcode = code1;
completion.MaterialCode = print.MaterialCode;
completion.MaterialName = print.MaterialName;
completion.StationName = "1008";
completion.CompleteDate = DateTime.Now;
completion.isDownLine = 0;
completion.ProductLineCode = "CX_02";
_ = _iMaterialCompletionServices.AddAsync(completion).Result;
#endregion
SendPlcPass();
//刷新页面
LoadData();
LoadCharts();
}
else
{
RefreshAndWriteLog("条码【" + record.BoxCode + "】与SN码【" + record.ProductCode + "】绑定失败", true);
if (SendPlcStop())
{
RefreshAndWriteLog("条码绑定失败,线体停止");
}
}
}
catch (Exception ex)
{
RefreshAndWriteLog(ex.Message.ToString());
SendPlcStop();
}
finally
{
// code1Str = string.Empty;
// code2Str = string.Empty;
}
}
/// <summary>
/// 往mes数据库添加异常记录
/// </summary>
/// <param name="SNCode"></param>
/// <param name="Msg"></param>
/// <param name="Type">1=69码校验;2=重复扫描;3=未绑条码;4=未终检</param>
public async void AddExceptionRecord(string BoxCode, string Msg, int Type)
{
try
{
ExceptionRecord record = new ExceptionRecord();
record.ProductSnCode = BoxCode;
record.ProductScanTime = DateTime.Now;
record.ProductLineCode = ProductLineCode;
record.ExceptionMsg = Msg;
record.ExceptionType = Type;
record.Position = "条码绑定";
await exceptionRecordServices.AddAsync(record);
}
catch (Exception ex)
{
log.Info("添加异常记录方法AddExceptionRecord异常:" + ex.Message.ToString());
}
}
#region plc交互
/// <summary>
/// 下发plc停止信号
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
private bool SendPlcStop()
{
bool result = false;
try
{
var obj = PlcHelper.melsecList.FirstOrDefault(d => d.EquipName.Equals("条码绑定Plc"));
if (obj != null)
{
log.Info($"NoRead信号,下发停止信号成功,当前箱体码{code1Str},当前成品码{code2Str}");
// 往plc写入停止信号
obj.plc.WriteInt16("D7102", "1");
// 报警信号
obj.plc.WriteInt16("D7101", "1");
result = true;
}
else
{
log.Info($"NoRead信号,下发停止信号失败plc未连接当前箱体码{code1Str},当前成品码{code2Str}");
}
}
catch (Exception ex)
{
log.Info($"NoRead信号,下发停止信号异常plc未连接当前箱体码{code1Str},当前成品码{code2Str}");
}
return result;
}
/// <summary>
/// 下发plc放行信号
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
private bool SendPlcPass()
{
bool result = false;
try
{
var obj = PlcHelper.melsecList.FirstOrDefault(d => d.EquipName.Equals("条码绑定Plc"));
if (obj != null)
{
log.Info("下发放行,停止信号D7102写0");
// 停止信号复位
obj.plc.WriteInt16("D7102", "0");
// 报警信号复位
obj.plc.WriteInt16("D7101", "0");
result = true;
}
}
catch (Exception ex)
{
log.Error("下发plc停止信号方法出现异常,ex:" + ex);
}
return result;
}
/// <summary>
/// 发送心跳
/// </summary>
/// <param name="obj"></param>
/// <param name="flag"></param>
private void SendHeart(PlcModel obj, string flag)
{
try
{
// log.Info("心跳D7100写:"+flag);
// 往plc写入停止信号
obj.plc.WriteInt16("D7100", flag);
// obj.plc.WriteInt32("D7102", 1);
}
catch (Exception ex)
{
log.Error("SendHeart异常,ex:" + ex);
}
}
///// <summary>
///// 下发plc放行信号
///// </summary>
///// <param name="materialType"></param>
//private bool SendPlcPass(PlcModel obj)
//{
// bool result = false;
// try
// {
// log.Info("D7100写1");
// // 往plc写入放行信号
// obj.plc.WriteInt16("D7100", "1");
// // 等待plc反馈信号
// result = waitPlcSignal(obj);
// }
// catch (Exception ex)
// {
// log.Error("下发plc放行信号方法SendPlcPass()出现异常,ex:" + ex);
// }
// return result;
//}
///// <summary>
///// 读取plc放行反馈
///// </summary>
///// <param name="materialType"></param>
//private bool waitPlcSignal(PlcModel obj)
//{
// bool result = false;
// try
// {
// DateTime startTime = DateTime.Now;
// bool isFlag = true;
// do
// {
// if (obj.plc.ReadInt16("D7200") == 2)
// {
// log.Info("D7100读2");
// isFlag = false;
// result = true;
// }
// TimeSpan elapsedTime = DateTime.Now - startTime;
// if (elapsedTime.TotalSeconds >= 5)
// {
// isFlag = false;
// }
// Thread.Sleep(500);
// } while (isFlag);
// }
// catch (Exception ex)
// {
// log.Error("读取plc放行反馈方法waitPlcSignal()出现异常,ex:" + ex);
// }
// return result;
//}
#endregion
}
}