Files

2078 lines
89 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.4", (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
}
}