Files
1257B_DB/JinYuan.ControlCenter/ControlCenter_Plc.cs
T

2078 lines
89 KiB
C#
Raw Normal View History

2026-08-06 09:23:30 +08:00
using JinYuan.Helper;
using JinYuan.MES.Enums;
using JinYuan.MES.Models;
using JinYuan.Models;
using JinYuan.VirtualDataLibrary;
using JinYuan.VirtualDataLibrary.Utlis;
using Language;
using Microsoft.SqlServer.Server;
using PLC;
using PLCCommunication;
using PLCCommunication.BasicFramework;
using PLCCommunication.Common;
using PLCCommunication.Common.DataConvert;
using SqlSugar;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Eventing.Reader;
using System.IO;
using System.Net;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
namespace JinYuan.ControlCenters
{
public partial class ControlCenter
{
public object FileLock = new object();//文件锁
#region 保留2位小数
private float SaveTwoNum(float TNum)
{
//1.2333 0.998
int value = (int)(TNum * 1000) % 10;
value = value > 4 ? 10 - value : -value;
TNum += ((float)value / 1000);
//保留3位小数
TNum = (float)(int)(TNum * 1000) / 1000;
return TNum;
}
#endregion
#region 包装上料工位(数据处理)
/// <summary>
/// 包装箱上料工位
/// </summary>
private async Task FeedingStation(JYResult<byte[]> bArrays, object plcModel)
{
PlcGroup pf = plcModel as PlcGroup;
if (pf == null)
{
LogHelper.Instance.WriteError("PLC模型转换失败", "SysErrorLog");
return;
}
using (var timer = new TimedOperation("包装箱进站", (elapsedMs, operationName) =>
{
CommonMethods.AddDataMonitorLog(0, $"包装箱进站共耗时:{operationName} 执行耗时:{elapsedMs}ms");
}))
{
if (bArrays.IsSuccess && bArrays.Content != null)
{
try
{
#region 数据初始化
//解析数据
List<TagInfo> cartonTagInfos = new List<TagInfo>();
const int CODE_SIZE = 40;
#endregion
#region 数据解析
byte[] bytes = bArrays.Content.ByteReverse();//高低位转换
string containerCode = StringLib.GetStringFromByteArrayByEncoding(bytes, 0, CODE_SIZE -1, System.Text.Encoding.ASCII).// 从D3100开始
Replace('\0', ' ').Replace('\r', ' ').Replace(" ", "").Trim();
#endregion
#region 获取箱唛信息MES
if (String.IsNullOrEmpty(containerCode) || containerCode.Trim() == "ERROR" || !IsAlphaNumeric(containerCode))
{
CommonMethods.AddDataMonitorLog(0, "PLC中读取箱唛码NG:" + containerCode);
var entity = new AGearEntity
{
ContainerCode = "NG",
PalletCode = "NG",
TestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
Remark = "包装箱进站",
Result = "NG"
};
var entityList = new List<AGearEntity> { entity };
// 线程安全调用委托
CommonMethods.ShowFeedingDelegate.Invoke(entityList);
await Task.Run(() => CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[1].VarAddress, 1));
return;
}
if (CommonMethods.sysConfig.MesModeSwitching)
{
try
{
await GetCartonTagInfosAsync(pf, containerCode);
}
catch (Exception ex)
{
CommonMethods.AddDataMonitorLog(0, "保存箱唛信息失败,箱唛码:" + containerCode + ",异常信息:" + ex.Message);
}
#region 箱唛数据反馈&保存
if (cartonTagInfos.Count > 0)
{
try
{
await SaveCartonTagInfosAsync(containerCode, cartonTagInfos);
}
catch (Exception ex)
{
CommonMethods.AddDataMonitorLog(0, "保存箱唛信息失败,箱唛码:" + containerCode + ",异常信息:" + ex.Message);
}
}
else
{
CommonMethods.AddDataMonitorLog(0, "未从mes中获取到箱唛信息,箱唛码:" + containerCode);
}
#endregion
#region 获取栈板信息
(var palletCode, var palletTagInfos) = await GetPalletTagInfosAsync(pf, containerCode);
#endregion
#region 栈板数据反馈&保存
if (palletTagInfos.Count > 0)
{
try
{
await SavePalletTagInfosAsync(containerCode, palletCode, palletTagInfos);
}
catch (Exception ex)
{
CommonMethods.AddDataMonitorLog(0, "保存栈板信息失败,栈板码:" + palletCode + ",异常信息:" + ex.Message);
}
}
else
{
CommonMethods.AddDataMonitorLog(0, "未从mes中获取到栈板信息,栈板码:" + palletCode);
}
await SaveFeedingStationAsync(containerCode, palletCode);
#endregion
//if (palletTagInfos.Count > 0 && cartonTagInfos.Count > 0)
// await Task.Run(() => CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[2].VarAddress, 1));
//else
// await Task.Run(() => CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[2].VarAddress, 2));
var taginfo = cartonTagInfos.FirstOrDefault(x => x.tagCode == "model");
int model = CommonMethods.mesConfig.GetModel(taginfo.tagValue);
await Task.Run(() => CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[3].VarAddress, (short)model));
}
else if (CommonMethods.sysConfig.IsDebugMode)
{
string batModel = CommonMethods.mesConfig.ModelName;
TagInfo kVDetail = new TagInfo()
{
tagCode="model",
tagValue = batModel
};
cartonTagInfos.Add(kVDetail);
await SaveCartonTagInfosAsync(containerCode, cartonTagInfos);
string palletCode = containerCode + "_01";
await SaveFeedingStationAsync(containerCode, palletCode);
int model = CommonMethods.mesConfig.GetModel(batModel);
await Task.Run(() => CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[3].VarAddress, (short)model));
}
else
{
CommonMethods.AddDataMonitorLog(0, "MES 功能未开启,无法获取箱唛和栈板信息");
//await Task.Run(() => CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[2].VarAddress, 2));
}
#endregion
////O2 客户还是普通客户
//short customertype = CommonMethods.mesConfig.customerType == "O2" ? (short)1 : (short)2;
//await Task.Run(() => CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[2].VarAddress, customertype));
}
catch (Exception ex)
{
LogHelper.Instance.WriteError($"获取箱唛和栈板信息线程处理异常:{ex}", "SysErrorLog");
// 异常时反馈PLC错误
await WritePlcResult(pf, "D80", 1, PLC.DataType.Short);
}
finally
{
// 重置PLC信号
await Task.Run(() =>
CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[1].VarAddress, 1)
);
}
}
}
}
/// <summary>
/// 保存包装箱进站数据
/// </summary>
/// <param name="list"></param>
private async Task SaveFeedingStationAsync(string containerCode, string palletCode)
{
var entity = new AGearEntity
{
ContainerCode = containerCode,
PalletCode = palletCode,
TestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
Remark = "包装箱进站",
Result = "成功"
};
if (string.IsNullOrWhiteSpace(containerCode))
{
LogHelper.Instance.WriteError("包装箱码为空,无法保存进站信息", "SysErrorLog");
entity.ContainerCode = "NG";
entity.Remark = "NG";
}
if (string.IsNullOrWhiteSpace(palletCode))
{
LogHelper.Instance.WriteLog($"包装箱[{containerCode}]对应的栈板码码为空");
entity.PalletCode = "NG";
entity.Remark = "NG";
}
try
{
if (entity.ContainerCode != "NG")
{
bool con_success = await CommonMethods.db.AddReturnBoolAsync<AGearEntity>(entity);
string logMsg = con_success
? $"包装箱[{containerCode}](栈板码码[{palletCode}])进站信息存储成功"
: $"包装箱[{containerCode}](栈板码码[{palletCode}])进站信息存储失败";
CommonMethods.AddDataMonitorLog(0, logMsg);
}
var entityList = new List<AGearEntity> { entity };
// 线程安全调用委托
CommonMethods.ShowFeedingDelegate.Invoke(entityList);
}
catch (Exception ex)
{
LogHelper.Instance.WriteError(containerCode + $"包装箱进站信息保存处理异常:{ex}", "SysErrorLog");
}
}
#endregion
#region 获取箱唛信息
private async Task<List<TagInfo>> GetCartonTagInfosAsync(PlcGroup pf, string containerCode)
{
List<TagInfo> cartonTagInfos = new List<TagInfo>();
const int maxRetry = 3; // 最大重试3次
const int retryIntervalMs = 1000; // 重试间隔1秒
int retryCount = 0;
//bool success = false;
while (retryCount < maxRetry)
{
if (!CommonMethods.mesConfig.isConnected)
{
CommonMethods.AddDataMonitorLog(1, "MES连接中断,停止上传"); // 1:错误级别
await WritePlcResult(pf, "D80", 1, PLC.DataType.Short); // 反馈错误
break;
}
var (success, mesMessage, mesResType, cartonTags) = await CommonMethods.hbgMes.QueryCartonAsync(
CommonMethods.mesConfig.queryCartonUrl,
CommonMethods.mesConfig.siteCode,
CommonMethods.mesConfig.lineCode,
CommonMethods.mesConfig.equipNum,
containerCode
);
if (success && cartonTags.Count > 0)
{
cartonTagInfos = cartonTags;
await WritePlcResult(pf, "D80", 0, PLC.DataType.Short); // 反馈成功
break;
}
// 失败处理
retryCount++;
CommonMethods.AddDataMonitorLog(1, $"MES请求失败({retryCount}/{maxRetry}):{mesMessage}");
if (retryCount >= maxRetry)
{
await WritePlcResult(pf, "D80", 1, PLC.DataType.Short); // 超过重试次数,反馈错误
break;
}
else
{
await Task.Delay(retryIntervalMs); // 等待重试
}
}
return cartonTagInfos;
}
#endregion
#region 保存箱唛信息数据
/// <summary>
/// 保存箱唛信息数据
/// </summary>
/// <param name="list"></param>
private async Task SaveCartonTagInfosAsync(string containerCode, List<TagInfo> list)
{
if (list == null || list.Count == 0)
return;
// 明确指定为异步 lambda
try
{
ContainerEntity containerEntity = new ContainerEntity
{
container_id = containerCode,
create_time = DateTime.Now
};
List<ContainerKVDetail> containerKVList = list
.Select(tag => new ContainerKVDetail
{
container_id = containerCode,
tag_code = tag.tagCode,
tag_value = tag.tagValue,
create_time = DateTime.Now
})
.ToList();
// 数据库操作
bool con_success = await CommonMethods.db.AddReturnBoolAsync<ContainerEntity>(containerEntity);
bool kv_success = await CommonMethods.db.AddReturnBoolAsync<ContainerKVDetail>(containerKVList);
if (kv_success)
{
CommonMethods.AddDataMonitorLog(0, containerCode + "箱唛信息存储成功");
}
else
{
CommonMethods.AddDataMonitorLog(0, containerCode + "箱唛信息存储失败");
}
}
catch (Exception ex)
{
LogHelper.Instance.WriteError(containerCode + $"箱唛信息保存处理异常:{ex}", "SysErrorLog");
}
}
#endregion
#region 获取栈板信息
private async Task<(string palletCode, List<TagInfo> palletTagInfos)> GetPalletTagInfosAsync(PlcGroup pf, string containerCode)
{
string palletCode = string.Empty;
List<TagInfo> palletTagInfos = new List<TagInfo>();
const int maxRetry = 3; // 最大重试3次
const int retryIntervalMs = 1000; // 重试间隔1秒
int retryCount = 0;
if (!CommonMethods.mesConfig.isConnected)
{
CommonMethods.AddDataMonitorLog(1, "MES连接中断");
await WritePlcResult(pf, "D80", 1, PLC.DataType.Short); // 反馈错误
return (palletCode, palletTagInfos);
}
// 调用MES接口
var (success, mesMessage, mesResType, retPalletCode, retPalletTags) = await CommonMethods.hbgMes.QueryPalletAsync(
CommonMethods.mesConfig.queryPalletUrl,
CommonMethods.mesConfig.siteCode,
CommonMethods.mesConfig.lineCode,
CommonMethods.mesConfig.equipNum,
containerCode
);
if (!success || retPalletTags == null || retPalletTags.Count == 0)
{
CommonMethods.AddDataMonitorLog(1, "MES获取栈板信息失败");
await WritePlcResult(pf, "D80", 1, PLC.DataType.Short); // 反馈错误
return (palletCode, palletTagInfos);
}
// 赋值有效数据
palletCode = retPalletCode;
palletTagInfos = retPalletTags;
return (palletCode, palletTagInfos);
}
#endregion
#region 保存栈板信息数据
/// <summary>
/// 保存栈板信息数据
/// </summary>
/// <param name="list"></param>
private async Task SavePalletTagInfosAsync(string containerCode, string pallet_id, List<TagInfo> list)
{
if (list == null || list.Count == 0)
return;
// 明确指定为异步 lambda
try
{
PalletEntity palletEntity = new PalletEntity
{
container_id = containerCode,
pallet_id = pallet_id,
create_time = DateTime.Now
};
List<PalletKVDetail> palletKVList = list
.Select(tag => new PalletKVDetail
{
pallet_id = pallet_id,
tag_code = tag.tagCode,
tag_value = tag.tagValue,
create_time = DateTime.Now
})
.ToList();
// 数据库操作
bool con_success = await CommonMethods.db.AddReturnBoolAsync<PalletEntity>(palletEntity);
bool kv_success = await CommonMethods.db.AddReturnBoolAsync<PalletKVDetail>(palletKVList);
if (con_success && kv_success)
{
CommonMethods.AddDataMonitorLog(0, containerCode + "栈板信息存储成功");
}
else
{
CommonMethods.AddDataMonitorLog(0, containerCode + "栈板信息存储失败");
}
}
catch (Exception ex)
{
LogHelper.Instance.WriteError(containerCode+ "_" + $"栈板信息保存处理异常:{ex}", "SysErrorLog");
}
}
#endregion
private async Task FeedingStationB(JYResult<byte[]> bArrays, object plcModel)
{
PlcGroup pf = plcModel as PlcGroup;
if (pf == null)
{
LogHelper.Instance.WriteError("PLC模型转换失败", "SysErrorLog");
return;
}
using (var timer = new TimedOperation("中部扫描", (elapsedMs, operationName) =>
{
CommonMethods.AddDataMonitorLog(0, $"中部扫描共耗时:{operationName} 执行耗时:{elapsedMs}ms");
}))
{
if (bArrays.IsSuccess && bArrays.Content != null)
{
try
{
#region 数据初始化
//解析数据
List<TagInfo> cartonTagInfos = new List<TagInfo>();
const int CODE_SIZE = 40;
#endregion
#region 数据解析
byte[] bytes = bArrays.Content.ByteReverse();//高低位转换
string containerCode = StringLib.GetStringFromByteArrayByEncoding(bytes, 0, CODE_SIZE - 1, System.Text.Encoding.ASCII).// 从D3100开始
Replace('\0', ' ').Replace('\r', ' ').Replace(" ", "").Trim();
#endregion
//#region 获取箱唛信息
if (String.IsNullOrEmpty(containerCode) || containerCode.Trim() == "ERROR" || IsAlphaNumeric(containerCode))
{
CommonMethods.AddDataMonitorLog(0, "PLC中读取箱唛码NG:" + containerCode);
var entity = new AGearEntity
{
ContainerCode = "NG",
PalletCode = "NG",
TestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
Remark = "中部扫描包装箱",
Result = "NG"
};
var entityList = new List<AGearEntity> { entity };
// 线程安全调用委托
//CommonMethods.ShowFeedingDelegate.Invoke(entityList);
await Task.Run(() => CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[1].VarAddress, 1));
return;
}
ContainerKVDetail modelDetail = CommonMethods.db.Query<ContainerKVDetail>(it => it.container_id == containerCode && it.tag_code == "model");
//string palletCode = cartonEntity.ContainerCode;
//if (cartonEntity == null || string.IsNullOrWhiteSpace(palletCode))
//{
// LogHelper.Instance.WriteLog($"包装箱[{containerCode}]对应的栈板码为空");
// await Task.Run(() => CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[4].VarAddress, 1));
// return;
//}
string batModel = modelDetail.tag_code;
int model = CommonMethods.mesConfig.GetModel(batModel);
await Task.Run(() => CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[3].VarAddress, (short)model));
}
catch (Exception ex)
{
LogHelper.Instance.WriteError($"中部扫描获取箱唛信息线程处理异常:{ex}", "SysErrorLog");
}
finally
{
await Task.Run(() => CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[1].VarAddress, 1));
}
}
}
}
private async Task FeedingStationC(JYResult<byte[]> bArrays, object plcModel)
{
PlcGroup pf = plcModel as PlcGroup;
if (pf == null)
{
LogHelper.Instance.WriteError("PLC模型转换失败", "SysErrorLog");
return;
}
using (var timer = new TimedOperation("尾部扫描", (elapsedMs, operationName) =>
{
CommonMethods.AddDataMonitorLog(0, $"尾部扫描共耗时:{operationName} 执行耗时:{elapsedMs}ms");
}))
{
if (bArrays.IsSuccess && bArrays.Content != null)
{
try
{
#region 数据初始化
//解析数据
List<TagInfo> cartonTagInfos = new List<TagInfo>();
const int CODE_SIZE = 40;
#endregion
#region 数据解析
byte[] bytes = bArrays.Content.ByteReverse();//高低位转换
string containerCode = StringLib.GetStringFromByteArrayByEncoding(bytes, 0, CODE_SIZE - 1, System.Text.Encoding.ASCII).// 从D3100开始
Replace('\0', ' ').Replace('\r', ' ').Replace(" ", "").Trim();
#endregion
//#region 获取箱唛信息
if (String.IsNullOrEmpty(containerCode) || containerCode.Trim() == "ERROR" || IsAlphaNumeric(containerCode))
{
CommonMethods.AddDataMonitorLog(0, "PLC中读取箱唛码NG:" + containerCode);
var entity = new AGearEntity
{
ContainerCode = "NG",
PalletCode = "NG",
TestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
Remark = "尾部扫描包装箱",
Result = "NG"
};
var entityList = new List<AGearEntity> { entity };
// 线程安全调用委托
//CommonMethods.ShowFeedingDelegate.Invoke(entityList);
await Task.Run(() => CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[1].VarAddress, 1));
return;
}
ContainerKVDetail modelDetail = CommonMethods.db.Query<ContainerKVDetail>(it => it.container_id == containerCode && it.tag_code == "model");
string batModel = modelDetail.tag_code;
int model = CommonMethods.mesConfig.GetModel(batModel);
await Task.Run(() => CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[3].VarAddress, (short)model));
}
catch (Exception ex)
{
LogHelper.Instance.WriteError($"尾部扫描获取箱唛信息线程处理异常:{ex}", "SysErrorLog");
}
finally
{
await Task.Run(() => CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[1].VarAddress, 1));
}
}
}
}
#region 箱唛打印
/// <summary>
/// 箱唛打印
/// </summary>
/// <param name="bArrays"></param>
/// <param name="plcModel"></param>
/// <returns></returns>
private async Task PrintContainerStation(JYResult<byte[]> bArrays, object plcModel)
{
PlcGroup pf = plcModel as PlcGroup;
if (pf == null)
{
LogHelper.Instance.WriteError("PLC模型转换失败", "SysErrorLog");
return;
}
if (CommonMethods.mesConfig.customerType == "O2")
{
// 重置PLC信号
await Task.Run(() =>
CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[0].VarAddress, 0)
);
CommonMethods.AddDataMonitorLog(0, "上位机不打印O2客户箱唛标签.");
return;
}
using (var timer = new TimedOperation("箱唛标签打印", (elapsedMs, operationName) =>
{
CommonMethods.AddDataMonitorLog(0, $"箱唛标签打印共耗时:{operationName} 执行耗时:{elapsedMs}ms");
}))
{
if (bArrays.IsSuccess && bArrays.Content != null)
{
List<short> listRes = GetList<short>(1, 2);//默认为2,判断箱唛码
byte[] bytes = bArrays.Content.ByteReverse();
string containercode = StringLib.GetStringFromByteArrayByEncoding(bytes, 0, 39, System.Text.Encoding.ASCII).// D4610~4629
Replace('\0', ' ').Replace('\r', ' ').Replace(" ", "").Trim();
if (String.IsNullOrEmpty(containercode) || containercode.Contains("ERROR") || containercode.Contains("NG"))
{
var entity = new DGearEntity
{
ContainerCode = "NG",
TestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
Remark = "箱唛标签打印",
Result = "NG"
};
var entityList = new List<DGearEntity> { entity };
CommonMethods.ShowPrintContainergDelegate?.Invoke(entityList);
//CommonMethods.plcDevices[pf.PlcNum - 1].WriteValue(pf.VarList[2].VarAddress, listRes.ToArray(), PLC.DataType.ArrShort);//判断结果写入PLC
CommonMethods.AddDataMonitorLog(0, "获取箱唛码为空,请检查".Translated());
CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[0].VarAddress, (short)0);//置位0
return;
}
else
{
listRes = await PrintContainer(containercode, listRes);
await SavePrintContainerAsync(containercode);
//CommonMethods.plcDevices[pf.PlcNum - 1].WriteValue(pf.VarList[2].VarAddress, listRes.ToArray(), PLC.DataType.ArrShort);//判断结果写入PLC
CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[0].VarAddress, (short)0);//复位
}
}
}
}
private static readonly Dictionary<string, string> CartonFieldMappings = new Dictionary<string, string>
{
{ "customer", "57" },
{ "supplier", "EVE" },
{ "orderNumber", "19999" },
{ "materialCode", "1" },
{ "productModel", "123" },
{ "productDate", "2026-01-15" },
{ "batchQuantity", "240 " },
{ "packingQuantity", "10 " },
{ "level", "A" },
{ "voltage", "100" },
{ "resistance", "1000" },
{ "capacity", "99" },
{ "boxNumber", "test111" },
{ "groupNumber", "88" },
{ "remark", "测试" }
};
private async Task<List<short>> PrintContainer(string containercode, List<short> listRes)
{
if (CommonMethods.containerPrint == null)
{
if (!string.IsNullOrEmpty(CommonMethods.btwConfig.printerName))
{
CommonMethods.containerPrint = new BartenderPrinter(CommonMethods.btwConfig.printerName);
}
else
{
listRes[0] = 3;
LogHelper.Instance.WriteLog($"打印机未设置和连接", "printLog");
return listRes;
}
}
try
{
List<ContainerKVDetail> container_kv_data = null;
// 初始化目标字典
Dictionary<string, string> vdaPrintValues = new Dictionary<string, string>();
if (!CommonMethods.sysConfig.IsDebugMode)
{
container_kv_data = CommonMethods.db.QueryWhereList<ContainerKVDetail>(it => it.container_id == containercode);
if (container_kv_data == null || !container_kv_data.Any())
{
listRes[0] = 3;
CommonMethods.AddDataMonitorLog(0, $"container:{containercode}获取参数失败".Translated());
LogHelper.Instance.WriteLog($"container:{containercode}获取参数失败", "printLog");
return listRes;
}
MapCartonKvDataToPrintDict(container_kv_data, vdaPrintValues);
}
else
{
FillDebugPrintCartonData(vdaPrintValues);
}
//使用zebra打印机
bool b = CommonMethods.containerPrint.write(CommonMethods.btwConfig.containerBTWPath, "carton label", vdaPrintValues);
if (b)
{
listRes[0] = 1;
CommonMethods.AddDataMonitorLog(0, $"箱唛码{containercode}:打印发送成功".Translated());
}
else
{
listRes[0] = 2;
CommonMethods.AddDataMonitorLog(0, $"箱唛码{containercode}:打印发送失败".Translated());
LogHelper.Instance.WriteLog($"{containercode}发送失败", "printLog");
}
}
catch (Exception ex)
{
LogHelper.Instance.WriteError($"箱唛打印线程异常:{ex}", "printLog");
}
return listRes;
}
/// <summary>
/// 将KV数据映射到打印字典(业务转换层)
/// </summary>
/// <param name="kvData">KV数据列表</param>
/// <param name="printDict">打印字典</param>
private void MapCartonKvDataToPrintDict(List<ContainerKVDetail> kvData, Dictionary<string, string> printDict)
{
var kvDict = kvData.ToDictionary(kv => kv.tag_code, kv => kv.tag_value, StringComparer.OrdinalIgnoreCase);
foreach (var mapping in CartonFieldMappings)
{
if (kvDict.TryGetValue(mapping.Value, out var value))
{
printDict[mapping.Key] = value ?? string.Empty; // 空值处理
}
else
{
LogHelper.Instance.WriteLog($"托盘数据缺失字段:{mapping.Key}(对应TagCode:{mapping.Value})", "printLog");
printDict[mapping.Key] = string.Empty;
}
}
}
/// <summary>
/// 填充调试模式的测试数据(测试层)
/// </summary>
/// <param name="printDict">打印字典</param>
private void FillDebugPrintCartonData(Dictionary<string, string> printDict)
{
printDict["customer"] = "57";
printDict["supplier"] = "EVE";
printDict["orderNumber"] = "19999";
printDict["materialCode"] = "1";
//printDict["产品描述"] = "方形铁锂";
printDict["productModel"] = "123";
printDict["productDate"] = "2026-01-15";
printDict["batchQuantity"] = "240 ";
printDict["packingQuantity"] = "10 ";
printDict["level"] = "A";
printDict["voltage"] = "100";
printDict["resistance"] = "1000";
printDict["capacity"] = "99";
printDict["boxNumber"] = "test111";
printDict["groupNumber"] = "88";
printDict["remark"] = "测试";
}
/// <summary>
/// 保存包装箱进站数据
/// </summary>
/// <param name="list"></param>
private async Task SavePrintContainerAsync(string containerCode)
{
var entity = new DGearEntity
{
ContainerCode = containerCode,
TestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
Remark = "箱唛标签打印",
Result = "成功"
};
// 入参校验(避免空值写入数据库)
if (string.IsNullOrWhiteSpace(containerCode))
{
LogHelper.Instance.WriteError("包装箱码为空,无法保存进站信息", "SysErrorLog");
entity.ContainerCode = "NG";
entity.Result = "NG";
}
// 明确指定为异步 lambda
try
{
if (entity.ContainerCode != "NG")
{
// 数据库操作
bool con_success = await CommonMethods.db.AddReturnBoolAsync<DGearEntity>(entity);
string logMsg = con_success
? $"包装箱[{containerCode}]箱唛打印信息存储成功"
: $"包装箱[{containerCode}]箱唛打印信息存储失败";
CommonMethods.AddDataMonitorLog(0, logMsg);
}
var entityList = new List<DGearEntity> { entity };
CommonMethods.ShowPrintContainergDelegate?.Invoke(entityList);
}
catch (Exception ex)
{
LogHelper.Instance.WriteError(containerCode + $"包装箱进站信息保存处理异常:{ex}", "SysErrorLog");
}
}
#endregion
#region 栈板打印
/// <summary>
/// 栈板打印
/// </summary>
/// <param name="bArrays"></param>
/// <param name="plcModel"></param>
/// <returns></returns>
private async Task PrintPalletStation(JYResult<byte[]> bArrays, object plcModel)
{
PlcGroup pf = plcModel as PlcGroup;
if (pf == null)
{
LogHelper.Instance.WriteError("PLC模型转换失败", "SysErrorLog");
return;
}
if (CommonMethods.mesConfig.customerType == "O2")
{
// 重置PLC信号
await Task.Run(() =>
CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[0].VarAddress, 0)
);
CommonMethods.AddDataMonitorLog(0, "上位机不打印O2客户栈板标签.");
return;
}
using (var timer = new TimedOperation("栈板打印", (elapsedMs, operationName) =>
{
CommonMethods.AddDataMonitorLog(0, $"栈板打印共耗时:{operationName} 执行耗时:{elapsedMs}ms");
}))
{
if (!CommonMethods.sysConfig.IsDebugMode)
{
if (bArrays.IsSuccess && bArrays.Content != null)
{
List<short> listRes = GetList<short>(1, 2);//默认为2,判断栈板码
byte[] bytes = bArrays.Content.ByteReverse();
string palletcode = StringLib.GetStringFromByteArrayByEncoding(bytes, 0, 39, System.Text.Encoding.ASCII).// D4610~4629
Replace('\0', ' ').Replace('\r', ' ').Replace(" ", "").Trim();
if (String.IsNullOrEmpty(palletcode) || palletcode.Contains("ERROR") || palletcode.Contains("NG"))
{
CommonMethods.plcDevices[pf.PlcNum - 1].WriteValue(pf.VarList[2].VarAddress, listRes.ToArray(), PLC.DataType.ArrShort);//判断结果写入PLC
CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[0].VarAddress, (short)0);//置位0
CommonMethods.AddDataMonitorLog(0, "获取栈板码为空,请检查".Translated());
return;
}
else
{
listRes = await PrintPallet(palletcode, listRes);
await SavePrintPalletAsync(palletcode);
CommonMethods.plcDevices[pf.PlcNum - 1].WriteValue(pf.VarList[2].VarAddress, listRes.ToArray(), PLC.DataType.ArrShort);//判断结果写入PLC
CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[0].VarAddress, (short)0);//复位
}
}
}
else
{
List<short> listRes = GetList<short>(1, 2);
string palletcode = "222222";
listRes = await PrintPallet(palletcode, listRes);
}
}
}
private static readonly Dictionary<string, string> PalletFieldMappings = new Dictionary<string, string>
{
{ "customer", "customer" }, // 客户编码
{ "groupNumber", "groupNumber" }, // 组号
{ "orderNumber", "orderNumber" }, // 订单号
{ "packageQty", "packageQty" }, // 包装数量
{ "productCode", "productCode" }, // 产品编码
{ "palletQty", "palletQty" }, // 托盘数量
{ "palletNo", "palletNo" }, // 托盘编号
{ "remark", "remark" } // 备注
};
private async Task<List<short>> PrintPallet(string palletcode, List<short> listRes)
{
if (CommonMethods.palletPrint == null)
{
if (!string.IsNullOrEmpty(CommonMethods.btwConfig.printerName))
{
CommonMethods.palletPrint = new BartenderPrinter(CommonMethods.btwConfig.printerName);
}
else
{
listRes[0] = 3;
LogHelper.Instance.WriteLog($"打印机未设置和连接", "printLog");
return listRes;
}
}
try
{
List<PalletKVDetail> pallet_kv_data = null;
// 初始化目标字典
Dictionary<string, string> vdaPrintValues = new Dictionary<string, string>();
if (!CommonMethods.sysConfig.IsDebugMode)
{
pallet_kv_data = CommonMethods.db.QueryWhereList<PalletKVDetail>(it => it.pallet_id == palletcode);
if (pallet_kv_data == null || !pallet_kv_data.Any())
{
listRes[0] = 3;
CommonMethods.AddDataMonitorLog(0, $"Pallet:{palletcode}获取参数失败".Translated());
LogHelper.Instance.WriteLog($"Pallet:{palletcode}获取参数失败", "printLog");
return listRes;
}
MapPalletKvDataToPrintDict(pallet_kv_data, vdaPrintValues);
}
else
{
FillDebugPrintPalletData(vdaPrintValues);
}
//使用zera打印机
bool b = CommonMethods.palletPrint.write(CommonMethods.btwConfig.palletBTWPath, "pallet label", vdaPrintValues);
if (b)
{
listRes[0] = 1;
CommonMethods.AddDataMonitorLog(0, $"栈板码{palletcode}:打印VDA发送成功".Translated());
}
else
{
listRes[0] = 2;
CommonMethods.AddDataMonitorLog(0, $"栈板码{palletcode}:打印VDA发送失败".Translated());
LogHelper.Instance.WriteLog($"{palletcode}发送VDA失败", "printLog");
}
}
catch (Exception ex)
{
LogHelper.Instance.WriteError($"栈板打印线程异常:{ex}", "printLog");
}
return listRes;
}
/// <summary>
/// 将KV数据映射到打印字典(业务转换层)
/// </summary>
/// <param name="kvData">KV数据列表</param>
/// <param name="printDict">打印字典</param>
private void MapPalletKvDataToPrintDict(List<PalletKVDetail> kvData, Dictionary<string, string> printDict)
{
var kvDict = kvData.ToDictionary(kv => kv.tag_code, kv => kv.tag_value, StringComparer.OrdinalIgnoreCase);
foreach (var mapping in PalletFieldMappings)
{
if (kvDict.TryGetValue(mapping.Value, out var value))
{
printDict[mapping.Key] = value ?? string.Empty; // 空值处理
}
else
{
LogHelper.Instance.WriteLog($"托盘数据缺失字段:{mapping.Key}(对应TagCode:{mapping.Value})", "printLog");
printDict[mapping.Key] = string.Empty;
}
}
}
/// <summary>
/// 填充调试模式的测试数据(测试层)
/// </summary>
/// <param name="printDict">打印字典</param>
private void FillDebugPrintPalletData(Dictionary<string, string> printDict)
{
printDict["customer"] = "57";
printDict["groupNumber"] = "88";
printDict["orderNumber"] = "19999";
printDict["packageQty"] = "10";
//printDict["产品描述"] = "方形铁锂";
printDict["productCode"] = "123";
printDict["palletQty"] = "2400";
printDict["palletNo"] = "1000";
printDict["remark"] = "测试";
}
/// <summary>
/// 保存栈板标签数据
/// </summary>
/// <param name="list"></param>
private async Task SavePrintPalletAsync(string palletCode)
{
// 入参校验(避免空值写入数据库)
if (string.IsNullOrWhiteSpace(palletCode))
{
LogHelper.Instance.WriteLog($"包装箱[{palletCode}]对应的栈板码码为空");
}
// 明确指定为异步 lambda
try
{
var entity = new EGearEntity
{
PalletCode = palletCode,
TestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
Remark = "栈板标签打印",
Result = "成功"
};
// 数据库操作
bool con_success = await CommonMethods.db.AddReturnBoolAsync<EGearEntity>(entity);
string logMsg = con_success
? $"栈板[{palletCode}]标签信息存储成功"
: $"栈板[{palletCode}]标签信息存储失败";
CommonMethods.AddDataMonitorLog(0, logMsg);
var entityList = new List<EGearEntity> { entity };
CommonMethods.ShowPrintPalletDelegate?.Invoke(entityList);
}
catch (Exception ex)
{
LogHelper.Instance.WriteError(palletCode + $"栈板标签信息保存处理异常:{ex}", "SysErrorLog");
}
}
#endregion
//#region 3S 打印
///// <summary>
///// 3S打印
///// </summary>
///// <param name="bArrays"></param>
///// <param name="plcModel"></param>
///// <returns></returns>
//private async Task Print3SStation(JYResult<byte[]> bArrays, object plcModel)
//{
// PlcGroup pf = plcModel as PlcGroup;
// if (pf == null)
// {
// LogHelper.Instance.WriteError("PLC模型转换失败", "SysErrorLog");
// return;
// }
// if (CommonMethods.mesConfig.customerType != "O2")
// {
// // 重置PLC信号
// await Task.Run(() =>
// CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[0].VarAddress, 0)
// );
// CommonMethods.AddDataMonitorLog(0, "上位机不打印普通客户的3S标签.");
// return;
// }
// using (var timer = new TimedOperation("3S标签打印", (elapsedMs, operationName) =>
// {
// CommonMethods.AddDataMonitorLog(0, $"3S标签打印共耗时:{operationName} 执行耗时:{elapsedMs}ms");
// }))
// {
// if (bArrays.IsSuccess && bArrays.Content != null)
// {
// List<short> listRes = GetList<short>(1, 2);//默认为2,判断栈板码
// byte[] bytes = bArrays.Content.ByteReverse();
// string palletcode = StringLib.GetStringFromByteArrayByEncoding(bytes, 0, 39, System.Text.Encoding.ASCII).// D4610~4629
// Replace('\0', ' ').Replace('\r', ' ').Replace(" ", "").Trim();
// if (String.IsNullOrEmpty(palletcode) || palletcode.Contains("ERROR") || palletcode.Contains("NG"))
// {
// CommonMethods.plcDevices[pf.PlcNum - 1].WriteValue(pf.VarList[2].VarAddress, listRes.ToArray(), PLC.DataType.ArrShort);//判断结果写入PLC
// CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[0].VarAddress, (short)0);//置位0
// CommonMethods.AddDataMonitorLog(0, "获取栈板码为空,请检查".Translated());
// return;
// }
// else
// {
// listRes = await Print3SLabel(palletcode, listRes);
// await SavePrint3SAsync(palletcode);
// CommonMethods.plcDevices[pf.PlcNum - 1].WriteValue(pf.VarList[2].VarAddress, listRes.ToArray(), PLC.DataType.ArrShort);//判断结果写入PLC
// CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[0].VarAddress, (short)0);//复位
// }
// }
// }
//}
//private async Task<List<short>> Print3SLabel(string palletcode, List<short> listRes)
//{
// //try
// //{
// // List<PalletKVDetail> pallet_kv_data = null;
// // pallet_kv_data = CommonMethods.db.QueryWhereList<PalletKVDetail>(it => it.pallet_id == palletcode);
// // if (pallet_kv_data == null || pallet_kv_data.Count == 0)
// // {
// // listRes[0] = 3;
// // CommonMethods.AddDataMonitorLog(0, $"Pallet:{palletcode}获取参数失败".Translated());
// // LogHelper.Instance.WriteLog($"Pallet:{palletcode}获取参数失败", "printLog");
// // return listRes;
// // }
// // // 定义需要写入的多组数据(变量名和值的键值对)
// // var palletLabelData = new Dictionary<string, string>
// // {
// // //{ "vda1", VDAdata.receiver },
// // //{ "vda2", VDAdata.unloading },
// // //{ "vda4", VDAdata.supplier },
// // //{ "vda5", VDAdata.netWeight },
// // //{ "vda6", VDAdata.groWeight },
// // //{ "vda7", VDAdata.noBoxes },
// // //{ "vda8", VDAdata.partNo },//8数字+条形码(格式为39码)
// // //{ "vda8-1", VDAdata.bmwDmcJYA },//8-1 二维码
// // //{ "vda9", VDAdata.quantity },//9数字+条形码(格式为39码)
// // //{ "vda10", VDAdata.skuDescr },
// // //{ "vda11.1", VDAdata.sku },
// // // 可继续添加更多数据...
// // };
// // 初始化目标字典
// Dictionary<string, string> vdaPrintValues = new Dictionary<string, string>();
// // //循环处理每组数据
// // foreach (var entry in palletLabelData)
// // {
// // // 获取PLC变量信息
// // var plcVariable = getPLCVariable(entry.Key);
// // // 将BTName与值存入字典
// // vdaPrintValues[plcVariable.BTName] = entry.Value; // 使用索引器避免重复键异常(会覆盖旧值)
// // // 或者用 Add 方法(如果确保键不重复):
// // // vdaPrintValues.Add(plcVariable.BTName, entry.Value);
// // }
// //使用VDA打印机
// bool b = CommonMethods._3SPrint.write(CommonMethods.btwConfig.palletBTWPath, vdaPrintValues);
// if (b)
// {
// listRes[0] = 1;
// CommonMethods.AddDataMonitorLog(0, $"栈板码{palletcode}:打印VDA发送成功".Translated());
// }
// else
// {
// listRes[0] = 2;
// CommonMethods.AddDataMonitorLog(0, $"栈板码{palletcode}:打印VDA发送失败".Translated());
// LogHelper.Instance.WriteLog($"{palletcode}发送VDA失败", "printLog");
// }
// //}
// //catch (Exception ex)
// //{
// // LogHelper.Instance.WriteError($"栈板打印线程异常:{ex}", "printLog");
// //}
// return listRes;
//}
///// <summary>
///// 保存3S标签数据
///// </summary>
///// <param name="list"></param>
//private async Task SavePrint3SAsync(string palletCode)
//{
// // 入参校验(避免空值写入数据库)
// if (string.IsNullOrWhiteSpace(palletCode))
// {
// LogHelper.Instance.WriteLog($"包装箱[{palletCode}]对应的栈板码码为空");
// }
// // 明确指定为异步 lambda
// try
// {
// var entity = new EGearEntity
// {
// PalletCode = palletCode,
// TestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
// Remark = "3S标签打印",
// Result = "成功"
// };
// // 数据库操作
// bool con_success = await CommonMethods.db.AddReturnBoolAsync<EGearEntity>(entity);
// string logMsg = con_success
// ? $"3S[{palletCode}]标签信息存储成功"
// : $"3S[{palletCode}]标签信息存储失败";
// CommonMethods.AddDataMonitorLog(0, logMsg);
// var entityList = new List<EGearEntity> { entity };
// CommonMethods.ShowPrintPalletDelegate?.Invoke(entityList);
// }
// catch (Exception ex)
// {
// LogHelper.Instance.WriteError(palletCode + $"3S标签信息保存处理异常:{ex}", "SysErrorLog");
// }
//}
//#endregion
//#region 6J 打印
///// <summary>
///// 6J打印
///// </summary>
///// <param name="bArrays"></param>
///// <param name="plcModel"></param>
///// <returns></returns>
//private async Task Print6JStation(JYResult<byte[]> bArrays, object plcModel)
//{
// PlcGroup pf = plcModel as PlcGroup;
// if (pf == null)
// {
// LogHelper.Instance.WriteError("PLC模型转换失败", "SysErrorLog");
// return;
// }
// if (CommonMethods.mesConfig.customerType != "O2")
// {
// // 重置PLC信号
// await Task.Run(() =>
// CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[0].VarAddress, 0)
// );
// CommonMethods.AddDataMonitorLog(0, "上位机不打印普通客户的6J标签.");
// return;
// }
// using (var timer = new TimedOperation("6J标签打印", (elapsedMs, operationName) =>
// {
// CommonMethods.AddDataMonitorLog(0, $"6J标签打印共耗时:{operationName} 执行耗时:{elapsedMs}ms");
// }))
// {
// if (bArrays.IsSuccess && bArrays.Content != null)
// {
// List<short> listRes = GetList<short>(1, 2);//默认为2,判断栈板码
// byte[] bytes = bArrays.Content.ByteReverse();
// string palletcode = StringLib.GetStringFromByteArrayByEncoding(bytes, 0, 39, System.Text.Encoding.ASCII).// D4610~4629
// Replace('\0', ' ').Replace('\r', ' ').Replace(" ", "").Trim();
// if (String.IsNullOrEmpty(palletcode) || palletcode.Contains("ERROR") || palletcode.Contains("NG"))
// {
// CommonMethods.plcDevices[pf.PlcNum - 1].WriteValue(pf.VarList[2].VarAddress, listRes.ToArray(), PLC.DataType.ArrShort);//判断结果写入PLC
// CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[0].VarAddress, (short)0);//置位0
// CommonMethods.AddDataMonitorLog(0, "获取栈板码为空,请检查".Translated());
// return;
// }
// else
// {
// listRes = await Print6JLabel(palletcode, listRes);
// await SavePrint6JAsync(palletcode);
// CommonMethods.plcDevices[pf.PlcNum - 1].WriteValue(pf.VarList[2].VarAddress, listRes.ToArray(), PLC.DataType.ArrShort);//判断结果写入PLC
// CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[0].VarAddress, (short)0);//复位
// }
// }
// }
//}
//private async Task<List<short>> Print6JLabel(string palletcode, List<short> listRes)
//{
// //try
// //{
// // List<PalletKVDetail> pallet_kv_data = null;
// // pallet_kv_data = CommonMethods.db.QueryWhereList<PalletKVDetail>(it => it.pallet_id == palletcode);
// // if (pallet_kv_data == null || pallet_kv_data.Count == 0)
// // {
// // listRes[0] = 3;
// // CommonMethods.AddDataMonitorLog(0, $"Pallet:{palletcode}获取参数失败".Translated());
// // LogHelper.Instance.WriteLog($"Pallet:{palletcode}获取参数失败", "printLog");
// // return listRes;
// // }
// // // 定义需要写入的多组数据(变量名和值的键值对)
// // var palletLabelData = new Dictionary<string, string>
// // {
// // //{ "vda1", VDAdata.receiver },
// // //{ "vda2", VDAdata.unloading },
// // //{ "vda4", VDAdata.supplier },
// // //{ "vda5", VDAdata.netWeight },
// // //{ "vda6", VDAdata.groWeight },
// // //{ "vda7", VDAdata.noBoxes },
// // //{ "vda8", VDAdata.partNo },//8数字+条形码(格式为39码)
// // //{ "vda8-1", VDAdata.bmwDmcJYA },//8-1 二维码
// // //{ "vda9", VDAdata.quantity },//9数字+条形码(格式为39码)
// // //{ "vda10", VDAdata.skuDescr },
// // //{ "vda11.1", VDAdata.sku },
// // // 可继续添加更多数据...
// // };
// // 初始化目标字典
// Dictionary<string, string> vdaPrintValues = new Dictionary<string, string>();
// // //循环处理每组数据
// // foreach (var entry in palletLabelData)
// // {
// // // 获取PLC变量信息
// // var plcVariable = getPLCVariable(entry.Key);
// // // 将BTName与值存入字典
// // vdaPrintValues[plcVariable.BTName] = entry.Value; // 使用索引器避免重复键异常(会覆盖旧值)
// // // 或者用 Add 方法(如果确保键不重复):
// // // vdaPrintValues.Add(plcVariable.BTName, entry.Value);
// // }
// //使用VDA打印机
// bool b = CommonMethods._6JPrint.write(CommonMethods.btwConfig.palletBTWPath, vdaPrintValues);
// if (b)
// {
// listRes[0] = 1;
// CommonMethods.AddDataMonitorLog(0, $"栈板码{palletcode}:打印VDA发送成功".Translated());
// }
// else
// {
// listRes[0] = 2;
// CommonMethods.AddDataMonitorLog(0, $"栈板码{palletcode}:打印VDA发送失败".Translated());
// LogHelper.Instance.WriteLog($"{palletcode}发送VDA失败", "printLog");
// }
// //}
// //catch (Exception ex)
// //{
// // LogHelper.Instance.WriteError($"栈板打印线程异常:{ex}", "printLog");
// //}
// return listRes;
//}
///// <summary>
///// 保存6J标签数据
///// </summary>
///// <param name="list"></param>
//private async Task SavePrint6JAsync(string palletCode)
//{
// // 入参校验(避免空值写入数据库)
// if (string.IsNullOrWhiteSpace(palletCode))
// {
// LogHelper.Instance.WriteLog($"包装箱[{palletCode}]对应的栈板码码为空");
// }
// // 明确指定为异步 lambda
// try
// {
// var entity = new EGearEntity
// {
// PalletCode = palletCode,
// TestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
// Remark = "3S标签打印",
// Result = "成功"
// };
// // 数据库操作
// bool con_success = await CommonMethods.db.AddReturnBoolAsync<EGearEntity>(entity);
// string logMsg = con_success
// ? $"3S[{palletCode}]标签信息存储成功"
// : $"3S[{palletCode}]标签信息存储失败";
// CommonMethods.AddDataMonitorLog(0, logMsg);
// var entityList = new List<EGearEntity> { entity };
// CommonMethods.ShowPrintPalletDelegate?.Invoke(entityList);
// }
// catch (Exception ex)
// {
// LogHelper.Instance.WriteError(palletCode + $"3S标签信息保存处理异常:{ex}", "SysErrorLog");
// }
//}
//#endregion
///// <summary>
///// 绑定客户标签
///// </summary>
///// <param name="bArrays"></param>
///// <param name="plcModel"></param>
///// <returns></returns>
//private async Task BindingLabelStation(JYResult<byte[]> bArrays, object plcModel)
//{
// PlcGroup pf = plcModel as PlcGroup;
// if (pf == null)
// {
// LogHelper.Instance.WriteError("PLC模型转换失败", "SysErrorLog");
// return;
// }
// if (CommonMethods.mesConfig.customerType != "O2")
// {
// // 重置PLC信号
// await Task.Run(() =>
// CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[0].VarAddress, 0)
// );
// CommonMethods.AddDataMonitorLog(0, "普通客户不用上传MES绑定标签");
// return;
// }
// using (var timer = new TimedOperation("标签绑定", (elapsedMs, operationName) =>
// {
// CommonMethods.AddDataMonitorLog(0, $"标签绑定共耗时:{operationName} 执行耗时:{elapsedMs}ms");
// }))
// {
// if (bArrays.IsSuccess && bArrays.Content != null)
// {
// await BindingLabelAsync(bArrays, plcModel);
// }
// // 重置PLC信号
// await Task.Run(() =>
// CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[0].VarAddress, 0)
// );
// }
//}
//private async Task BindingLabelAsync(JYResult<byte[]> bArrays, object plcModel)
//{
// PlcGroup pf = plcModel as PlcGroup;
// if (pf == null)
// {
// LogHelper.Instance.WriteError("PLC模型转换失败", "SysErrorLog");
// return;
// }
// using (var timer = new TimedOperation("标签绑定", (elapsedMs, operationName) =>
// {
// CommonMethods.AddDataMonitorLog(0, $"标签绑定共耗时:{operationName} 执行耗时:{elapsedMs}ms");
// }))
// {
// if (bArrays.IsSuccess && bArrays.Content != null)
// {
// try
// {
// #region 数据初始化
// //解析数据
// const int maxChannel = 8; // 固定8通道,改为常量便于维护
// var listMark = Enumerable.Repeat(false, maxChannel).ToList(); // 有料标志
// #endregion
// // 从D2021开始
// #region 数据解析
// byte[] bytes = bArrays.Content.ByteReverse();//高低位转换
// // TODO 从PLC读取出所有的电芯条码和条码位置!
// string containerCode = "";
// string palletCode = "";
// string custcartonCode = "";
// string custpalletCode = "";
// List<TagInfo> custcarton = new List<TagInfo>();
// List<TagInfo> custpallet = new List<TagInfo>();
// ////有料标志
// #endregion
// #region 上传MES
// //上传MES
// if (custcarton.Count > 0 && custpallet.Count > 0)
// {
// const int maxRetry = 3; // 最大重试3次
// const int retryIntervalMs = 1000; // 重试间隔1秒
// int retryCount = 0;
// //bool isSuccess = false;
// while (retryCount < maxRetry)
// {
// if (!CommonMethods.mesConfig.isConnected)
// {
// CommonMethods.AddDataMonitorLog(1, "MES连接中断,停止上传"); // 1:错误级别
// await WritePlcResult(pf, "D80", 1, PLC.DataType.Short); // 反馈错误
// break;
// }
// //Task<(bool success, string mesMessage, MesResType mesResType)>
// // BindingAsync( string containerCode, string palletCode, string custcartonCode, string custpalletCode, List<TagInfo> custcarton, List<TagInfo> custpallet)
// // 调用MES接口
// var (success, mesMessage, mesResType) = await CommonMethods.hbgMes.BindingAsync(
// CommonMethods.mesConfig.bindingUrl,
// CommonMethods.mesConfig.siteCode,
// CommonMethods.mesConfig.lineCode,
// CommonMethods.mesConfig.equipNum,
// containerCode, palletCode, custcartonCode, custpalletCode, custcarton, custpallet
// );
// if (success)
// {
// await WritePlcResult(pf, "D80", 0, PLC.DataType.Short); // 反馈成功
// break;
// }
// // 失败处理
// retryCount++;
// CommonMethods.AddDataMonitorLog(1, $"MES请求失败({retryCount}/{maxRetry}):{mesMessage}");
// if (retryCount >= maxRetry)
// {
// await WritePlcResult(pf, "D80", 1, PLC.DataType.Short); // 超过重试次数,反馈错误
// break;
// }
// await Task.Delay(retryIntervalMs); // 等待重试
// }
// }
// #endregion
// #region 数据反馈&保存
// // //读取结果显示
// // // TODO 界面上将本次mes获得档位的电芯码状态置为红色!存储各个档位的数据,监控每个档位的电芯是不是满了,满了就调用另一个上传mes接口处理,需要另外写一个监控线程来监控吗?
// try
// {
// //await SaveBindingDataAsync(custcarton); //是否需要存库?
// }
// catch (Exception ex)
// {
// //MessageBox.Show($"保存失败:{ex.Message}"); //TODO 是否需要弹窗提示?
// }
// // 重置PLC信号
// await Task.Run(() =>
// CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[0].VarAddress, 0)
// );
// #endregion
// }
// catch (Exception ex)
// {
// LogHelper.Instance.WriteError($"标签绑定线程处理异常:{ex}", "SysErrorLog");
// // 异常时反馈PLC错误
// await WritePlcResult(pf, "D80", 1, PLC.DataType.Short);
// }
// }
// }
//}
#region 保存箱唛信息数据
/// <summary>
/// 保存绑定信息数据
/// </summary>
/// <param name="list"></param>
private async Task SaveBindingDataAsync(string containerCode, List<TagInfo> list)
{
if (list == null || list.Count == 0)
return;
// 明确指定为异步 lambda
await Task.Run(async () =>
{
try
{
// 数据库操作
bool success = await CommonMethods.db.AddReturnBoolAsync<TagInfo>(list);
if (success)
{
//// TODO 界面需要展示吗?
//await SafeInvokeOnUIThread(() =>
//{
// CommonMethods.ShowBatteryNGRsnDelegate?.Invoke(list);
//});
}
}
catch (Exception ex)
{
LogHelper.Instance.WriteError($"箱唛信息保存处理异常:{ex}", "SysErrorLog");
}
});
}
#endregion
#region 包装出站
private async Task BlankingStation(JYResult<byte[]> bArrays, object plcModel)
{
PlcGroup pf = plcModel as PlcGroup;
if (pf == null)
{
LogHelper.Instance.WriteError("PLC模型转换失败", "SysErrorLog");
return;
}
using (var timer = new TimedOperation("包装箱出站", (elapsedMs, operationName) =>
{
CommonMethods.AddDataMonitorLog(0, $"包装箱出站共耗时:{operationName} 执行耗时:{elapsedMs}ms");
}))
{
if (bArrays.IsSuccess && bArrays.Content != null)
{
try
{
#region 数据解析
byte[] bytes = bArrays.Content.ByteReverse();//高低位转换
// 从PLC读取出卡板码
int containerLen = 40;
string containerCode = StringLib.GetStringFromByteArrayByEncoding(bytes, 0, containerLen, System.Text.Encoding.ASCII).// 从D3100开始
Replace('\0', ' ').Replace('\r', ' ').Replace(" ", "").Trim();
#endregion
if (!String.IsNullOrEmpty(containerCode)) //(String.IsNullOrEmpty(x) || x.Trim() == "ERROR" || !IsAlphaNumeric(x))
{
CommonMethods.AddDataMonitorLog(0, "包装箱出站,箱唛码:" + containerCode);
// 出站界面显示
await SaveBlankingAsync(containerCode);
}
else
{
var entity = new BGearEntity
{
ContainerCode = "NG",
PalletCode = "NG",
//Weight = weight.ToString(),
TestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
Remark = "包装箱出站",
Result = "NG"
};
var entityList = new List<BGearEntity> { entity };
CommonMethods.ShowBlankingDelegate?.Invoke(entityList);
CommonMethods.AddDataMonitorLog(0, "未从plc中获取到栈板码");
}
}
catch (Exception ex)
{
LogHelper.Instance.WriteError($"包装箱出站线程处理异常:{ex}", "SysErrorLog");
// 异常时反馈PLC错误
await WritePlcResult(pf, "D80", 1, PLC.DataType.Short);
}
finally
{
await Task.Run(() => CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[1].VarAddress, 1));
}
}
}
}
private async Task PreparePrintDataAsync(List<ContainerKVDetail> cartonInfo, List<PalletKVDetail> palletInfo, string weight)
{
try
{
if (CommonMethods.tcpClient == null)
{
CommonMethods.tcpClient = new PrintSocket.TCPClient();
}
if (!CommonMethods.tcpClient.IsConnected())
{
CommonMethods.tcpClient.InitClient("127.0.0.1", 8000);
}
Dictionary<string, string> printData = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
printData.Add("siteCode", CommonMethods.mesConfig.siteCode);
printData.Add("lineCode", CommonMethods.mesConfig.lineCode);
printData.Add("equipName", CommonMethods.mesConfig.equipNum);
if (cartonInfo != null && cartonInfo.Count > 0)
{
printData.Add("ContainerCode", cartonInfo[0].container_id);
foreach (var containerItem in cartonInfo)
{
// 过滤空Key/空Value,避免无效数据
if (string.IsNullOrWhiteSpace(containerItem.tag_code) || string.IsNullOrWhiteSpace(containerItem.tag_value))
{
LogHelper.Instance.WriteLog($"ContainerKVDetail无效数据:tag_code={containerItem.tag_code}, tag_value={containerItem.tag_value}");
continue;
}
// 重复Key则覆盖(后添加的覆盖先添加的)
if (printData.ContainsKey(containerItem.tag_code))
{
printData[containerItem.tag_code] = containerItem.tag_value;
}
else
{
printData.Add(containerItem.tag_code, containerItem.tag_value);
}
}
}
if (palletInfo != null && palletInfo.Count > 0)
{
foreach (var palletItem in palletInfo)
{
// 过滤空Key/空Value
if (string.IsNullOrWhiteSpace(palletItem.tag_code) || string.IsNullOrWhiteSpace(palletItem.tag_value))
{
LogHelper.Instance.WriteLog($"PalletKVDetail无效数据:tag_code={palletItem.tag_code}, tag_value={palletItem.tag_value}");
continue;
}
// 重复Key则覆盖(Pallet覆盖Container)
if (!printData.ContainsKey(palletItem.tag_code))
{
printData.Add(palletItem.tag_code, palletItem.tag_value);
}
}
}
if (!string.IsNullOrWhiteSpace(weight))
{
if (printData.ContainsKey("weight"))
{
printData["weight"] = weight;
}
else
{
printData.Add("weight", weight);
}
}
// 如果PrintData中的containerTypeCode未从KV中获取到,设置默认空值
var printDataFields = new List<string>
{
"ContainerCode", "containerTypeCode", "virtualContainerCode", "groupNum",
"supplierCode", "customerCode", "customerName", "packQty", "batchQty",
"soNum", "customerOrder", "soLineNum", "materialCode", "materialName",
"model", "grade", "voltage", "inresistance", "capacity", "productDate",
"rohs", "locatorCode", "locatorName", "enableFlag", "actualLoadQty",
"palletCode", "containerCode", "poNum", "autoFlag"
};
foreach (var field in printDataFields)
{
if (!printData.ContainsKey(field))
{
printData.Add(field, string.Empty); // 缺失字段赋值为空字符串
}
}
// 发送打印任务
CommonMethods.tcpClient.Send(printData);
}
catch (Exception ex)
{
LogHelper.Instance.WriteLog($"发送打印数据失败{ex.Message}");
}
}
/// <summary>
/// 保存包装线出站数据
/// </summary>
/// <param name="list"></param>
private async Task SaveBlankingAsync(string cartonCode)
{
var entity = new BGearEntity
{
ContainerCode = cartonCode,
TestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
Remark = "包装箱出站",
Weight = "",
};
try
{
List<AGearEntity> containerEntity = CommonMethods.db.QueryWhereList<AGearEntity>(it => it.ContainerCode == cartonCode);
if (containerEntity == null || !containerEntity.Any())
{
LogHelper.Instance.WriteLog($"数据库中无包装箱[{cartonCode}]进站信息");
entity.PalletCode = "NG";
entity.Result = "NG";
entity.Remark += ",对应的栈板码为空";
}
else
{
entity.PalletCode = containerEntity[0].PalletCode;
entity.Result = "OK";
}
// 数据库操作
bool con_success = await CommonMethods.db.AddReturnBoolAsync<BGearEntity>(entity);
string logMsg = con_success ? $"包装箱[{cartonCode}]出站信息存储成功": $"包装箱[{cartonCode}]出站信息存储失败";
CommonMethods.AddDataMonitorLog(0, logMsg);
var entityList = new List<BGearEntity> { entity };
CommonMethods.ShowBlankingDelegate?.Invoke(entityList);
}
catch (Exception ex)
{
LogHelper.Instance.WriteError(cartonCode + $"包装箱出站信息保存处理异常:{ex}", "SysErrorLog");
}
}
#endregion
#region 中转数据给博杰
private async Task TransferStation(JYResult<byte[]> bArrays, object plcModel)
{
PlcGroup pf = plcModel as PlcGroup;
if (pf == null)
{
LogHelper.Instance.WriteError("PLC模型转换失败", "SysErrorLog");
return;
}
using (var timer = new TimedOperation("中转数据", (elapsedMs, operationName) =>
{
CommonMethods.AddDataMonitorLog(0, $"【结束】中转数据共耗时:{operationName} 执行耗时:{elapsedMs}ms");
}))
{
if (bArrays.IsSuccess && bArrays.Content != null)
{
try
{
#region 数据解析
byte[] bytes = bArrays.Content.ByteReverse();//高低位转换
// 从PLC读取出卡板码
int containerLen = 40;
short model = CommonMethods.plcDevices[0].ReadInt16(pf.VarList[2].VarAddress); //ShortLib.GetShortFromByteArray(bArrays.Content, 0); // 产品型号
string containerCode = StringLib.GetStringFromByteArrayByEncoding(bytes, 6, containerLen, System.Text.Encoding.ASCII).// 从D3100开始
Replace('\r', ' ').Replace(" ", "").Trim();
#endregion
if (String.IsNullOrEmpty(containerCode) || String.IsNullOrEmpty(containerCode) || containerCode.ToUpper().Trim() == "ERROR" || containerCode.Length < 5)
{
CommonMethods.AddDataMonitorLog(0, "中转数据,箱唛码无效" + containerCode);
return;
}
CommonMethods.AddDataMonitorLog(0, $"【开始】中转数据,产品型号:{model}, 箱唛码:{containerCode}\n");
PlcReadWriteBase plc = PLCFactory.CreatePLC(PLCType.Siemens, 1, "S7_1200", new IPEndPoint(IPAddress.Parse("192.168.2.50"), 102));
string msg = "";
plc.Connect(ref msg);
if (plc.IsConnected)
{
plc.WriteValue("DB44.8", new short[(ushort)(containerLen + 2)], PLC.DataType.ArrShort);
//short[] value4 = plc.ReadValue<short[]>("DB44.8", PLC.DataType.ArrShort, (ushort)(containerLen + 2));
//string value5 = ShortArrayToString(value4);
//CommonMethods.AddDataMonitorLog(0, $"清空后再读取【DB44.8】:{value4}=>{value5}");
// 写入数据 偏移量产品类型地址是,DB44.6 条码地址是DB44.8
plc.WriteValue("DB44.6", (short)model, PLC.DataType.Short);
plc.WriteValue("DB44.8", containerCode, PLC.DataType.String);
CommonMethods.AddDataMonitorLog(0, $"【DB44.6】写入型号:{model},【DB44.8】写入箱唛码:{containerCode}\n");
//object value = plc.ReadValue<short>("DB44.6", PLC.DataType.Short);
//short[] value2 = plc.ReadValue<short[]>("DB44.8", PLC.DataType.ArrShort, (ushort)(containerLen+2));
//string value3 = ShortArrayToString(value2);
//CommonMethods.AddDataMonitorLog(0, $"读取【DB44.6】:{value}, 读取【DB44.8】:{value3}");
}
else
{
CommonMethods.AddDataMonitorLog(0, "连接失败,请检查网络和PLC设置。");
}
// 关闭连接
plc.Disconnect();
}
catch (Exception ex)
{
LogHelper.Instance.WriteError($"中转数据处理异常:{ex}", "SysErrorLog");
// 异常时反馈PLC错误
await WritePlcResult(pf, "D80", 1, PLC.DataType.Short);
}
finally
{
await Task.Run(() => CommonMethods.plcDevices[pf.PlcNum - 1].WriteInt16(pf.VarList[1].VarAddress, 1));
}
}
}
}
private string ShortArrayToString(short[] shortArray)
{
if (shortArray == null || shortArray.Length < 1)
return "";
// short[] 转 byte[]
byte[] byteArray = new byte[shortArray.Length * 2];
Buffer.BlockCopy(shortArray, 0, byteArray, 0, byteArray.Length);
// 长度
int currentLength = byteArray[0];
if (currentLength <= 0 || (2 + currentLength) > byteArray.Length)
return "";
// 从第2个字节开始,转字符串
string result = Encoding.ASCII.GetString(byteArray.ByteReverse(), 2, currentLength);
return result;
}
#endregion
#region 斑马/VDA打印机
public static void initPrint()
{
//安装驱动后初始化
//CommonMethods.containerPrint = new BartenderPrinter(CommonMethods.containerPrintName);
//CommonMethods.palletPrint = new BartenderPrinter(CommonMethods.palletPrintName);
}
#endregion
#region 创建空的数组List
public List<T> GetList<T>(int num, T data)
{
List<T> list = new List<T>();
for (int i = 0; i < num; i++)
{
list.Add(data);
}
return list;
}
public List<MesResType> GetMesType(int Num)
{
List<MesResType> mesResTypes = new List<MesResType>();
for (int i = 0; i < Num; i++)
{
mesResTypes.Add(MesResType.UnKnow);
}
return mesResTypes;
}
/// <summary>
/// PLC内批量写\0
/// </summary>
/// <param name="Num"></param>
/// <returns></returns>
public string GetString_0(int Num)
{
string ff = "";
for (int i = 0; i < Num; i++)
{
ff = ff.Insert(ff.Length, "\0");
}
return ff;
}
public string GetBarCodeNum(int Num)
{
string CodeNo = "";
int CodeLenth = Num.ToString().Length;
switch (CodeLenth)
{
case 1:
return CodeNo = $"00000{Num}";
case 2:
return CodeNo = $"0000{Num}";
case 3:
return CodeNo = $"000{Num}";
case 4:
return CodeNo = $"00{Num}";
case 5:
return CodeNo = $"0{Num}";
default:
return CodeNo = $"{Num}";
}
}
#endregion
#region 辅助方法
/// <summary>
/// 检测数据是否只包含字母加数字
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public bool IsAlphaNumeric(string input)
{
// 使用正则表达式检查是否只包含字母和数字
return Regex.IsMatch(input, "^[a-zA-Z0-9]+$");
}
///// <summary>
///// 解析条码(通用方法,减少冗余)
///// </summary>
//private string ParseBarcode(byte[] bytes, int offset, int length)
//{
// return StringLib.GetStringFromByteArrayByEncoding(bytes, offset, length * 2, System.Text.Encoding.ASCII)
// .Replace('\0', ' ')
// .Replace('\r', ' ')
// .Trim();
//}
/// <summary>
/// 写入PLC结果(封装重复逻辑)
/// </summary>
private async Task WritePlcResult(PlcGroup pf, string plcAddress, short result, PLC.DataType datatype)
{
await Task.Run(() =>
CommonMethods.plcDevices[pf.PlcNum - 1].WriteValue(plcAddress, result, datatype)
//CommonMethods.plcDevices[pf.PlcNum - 1].WriteValue("D80", result, PLC.DataType.Short)
);
}
///// <summary>
///// 电池结果辅助方法
///// </summary>
///// <returns></returns>
//private string GetNGReasons(int value, string reasonCode)
//{
// // 只有当值为2时才返回原因代码,否则返回空字符串
// return value == 2 ? reasonCode : string.Empty;
//}
//// 组合多个NG原因字段
//private string CombineNGReasons(params string[] reasons)
//{
// // 过滤空值并连接
// var validReasons = reasons
// .Where(r => !string.IsNullOrEmpty(r))
// .Distinct(); // 去重
// return string.Join(",", validReasons);
//}
#endregion
}
}