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 包装上料工位(数据处理) /// /// 包装箱上料工位 /// private async Task FeedingStation(JYResult 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 cartonTagInfos = new List(); 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 { 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) ); } } } } /// /// 保存包装箱进站数据 /// /// 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(entity); string logMsg = con_success ? $"包装箱[{containerCode}](栈板码码[{palletCode}])进站信息存储成功" : $"包装箱[{containerCode}](栈板码码[{palletCode}])进站信息存储失败"; CommonMethods.AddDataMonitorLog(0, logMsg); } var entityList = new List { entity }; // 线程安全调用委托 CommonMethods.ShowFeedingDelegate.Invoke(entityList); } catch (Exception ex) { LogHelper.Instance.WriteError(containerCode + $"包装箱进站信息保存处理异常:{ex}", "SysErrorLog"); } } #endregion #region 获取箱唛信息 private async Task> GetCartonTagInfosAsync(PlcGroup pf, string containerCode) { List cartonTagInfos = new List(); 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 保存箱唛信息数据 /// /// 保存箱唛信息数据 /// /// private async Task SaveCartonTagInfosAsync(string containerCode, List list) { if (list == null || list.Count == 0) return; // 明确指定为异步 lambda try { ContainerEntity containerEntity = new ContainerEntity { container_id = containerCode, create_time = DateTime.Now }; List 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); bool kv_success = await CommonMethods.db.AddReturnBoolAsync(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 palletTagInfos)> GetPalletTagInfosAsync(PlcGroup pf, string containerCode) { string palletCode = string.Empty; List palletTagInfos = new List(); 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 保存栈板信息数据 /// /// 保存栈板信息数据 /// /// private async Task SavePalletTagInfosAsync(string containerCode, string pallet_id, List 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 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); bool kv_success = await CommonMethods.db.AddReturnBoolAsync(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 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 cartonTagInfos = new List(); 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 { 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(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 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 cartonTagInfos = new List(); 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 { 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(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 箱唛打印 /// /// 箱唛打印 /// /// /// /// private async Task PrintContainerStation(JYResult 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 listRes = GetList(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 { 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 CartonFieldMappings = new Dictionary { { "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> PrintContainer(string containercode, List 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 container_kv_data = null; // 初始化目标字典 Dictionary vdaPrintValues = new Dictionary(); if (!CommonMethods.sysConfig.IsDebugMode) { container_kv_data = CommonMethods.db.QueryWhereList(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; } /// /// 将KV数据映射到打印字典(业务转换层) /// /// KV数据列表 /// 打印字典 private void MapCartonKvDataToPrintDict(List kvData, Dictionary 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; } } } /// /// 填充调试模式的测试数据(测试层) /// /// 打印字典 private void FillDebugPrintCartonData(Dictionary 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"] = "测试"; } /// /// 保存包装箱进站数据 /// /// 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(entity); string logMsg = con_success ? $"包装箱[{containerCode}]箱唛打印信息存储成功" : $"包装箱[{containerCode}]箱唛打印信息存储失败"; CommonMethods.AddDataMonitorLog(0, logMsg); } var entityList = new List { entity }; CommonMethods.ShowPrintContainergDelegate?.Invoke(entityList); } catch (Exception ex) { LogHelper.Instance.WriteError(containerCode + $"包装箱进站信息保存处理异常:{ex}", "SysErrorLog"); } } #endregion #region 栈板打印 /// /// 栈板打印 /// /// /// /// private async Task PrintPalletStation(JYResult 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 listRes = GetList(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 listRes = GetList(1, 2); string palletcode = "222222"; listRes = await PrintPallet(palletcode, listRes); } } } private static readonly Dictionary PalletFieldMappings = new Dictionary { { "customer", "customer" }, // 客户编码 { "groupNumber", "groupNumber" }, // 组号 { "orderNumber", "orderNumber" }, // 订单号 { "packageQty", "packageQty" }, // 包装数量 { "productCode", "productCode" }, // 产品编码 { "palletQty", "palletQty" }, // 托盘数量 { "palletNo", "palletNo" }, // 托盘编号 { "remark", "remark" } // 备注 }; private async Task> PrintPallet(string palletcode, List 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 pallet_kv_data = null; // 初始化目标字典 Dictionary vdaPrintValues = new Dictionary(); if (!CommonMethods.sysConfig.IsDebugMode) { pallet_kv_data = CommonMethods.db.QueryWhereList(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; } /// /// 将KV数据映射到打印字典(业务转换层) /// /// KV数据列表 /// 打印字典 private void MapPalletKvDataToPrintDict(List kvData, Dictionary 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; } } } /// /// 填充调试模式的测试数据(测试层) /// /// 打印字典 private void FillDebugPrintPalletData(Dictionary 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"] = "测试"; } /// /// 保存栈板标签数据 /// /// 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(entity); string logMsg = con_success ? $"栈板[{palletCode}]标签信息存储成功" : $"栈板[{palletCode}]标签信息存储失败"; CommonMethods.AddDataMonitorLog(0, logMsg); var entityList = new List { entity }; CommonMethods.ShowPrintPalletDelegate?.Invoke(entityList); } catch (Exception ex) { LogHelper.Instance.WriteError(palletCode + $"栈板标签信息保存处理异常:{ex}", "SysErrorLog"); } } #endregion //#region 3S 打印 ///// ///// 3S打印 ///// ///// ///// ///// //private async Task Print3SStation(JYResult 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 listRes = GetList(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> Print3SLabel(string palletcode, List listRes) //{ // //try // //{ // // List pallet_kv_data = null; // // pallet_kv_data = CommonMethods.db.QueryWhereList(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 // // { // // //{ "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 vdaPrintValues = new Dictionary(); // // //循环处理每组数据 // // 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; //} ///// ///// 保存3S标签数据 ///// ///// //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(entity); // string logMsg = con_success // ? $"3S[{palletCode}]标签信息存储成功" // : $"3S[{palletCode}]标签信息存储失败"; // CommonMethods.AddDataMonitorLog(0, logMsg); // var entityList = new List { entity }; // CommonMethods.ShowPrintPalletDelegate?.Invoke(entityList); // } // catch (Exception ex) // { // LogHelper.Instance.WriteError(palletCode + $"3S标签信息保存处理异常:{ex}", "SysErrorLog"); // } //} //#endregion //#region 6J 打印 ///// ///// 6J打印 ///// ///// ///// ///// //private async Task Print6JStation(JYResult 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 listRes = GetList(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> Print6JLabel(string palletcode, List listRes) //{ // //try // //{ // // List pallet_kv_data = null; // // pallet_kv_data = CommonMethods.db.QueryWhereList(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 // // { // // //{ "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 vdaPrintValues = new Dictionary(); // // //循环处理每组数据 // // 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; //} ///// ///// 保存6J标签数据 ///// ///// //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(entity); // string logMsg = con_success // ? $"3S[{palletCode}]标签信息存储成功" // : $"3S[{palletCode}]标签信息存储失败"; // CommonMethods.AddDataMonitorLog(0, logMsg); // var entityList = new List { entity }; // CommonMethods.ShowPrintPalletDelegate?.Invoke(entityList); // } // catch (Exception ex) // { // LogHelper.Instance.WriteError(palletCode + $"3S标签信息保存处理异常:{ex}", "SysErrorLog"); // } //} //#endregion ///// ///// 绑定客户标签 ///// ///// ///// ///// //private async Task BindingLabelStation(JYResult 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 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 custcarton = new List(); // List custpallet = new List(); // ////有料标志 // #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 custcarton, List 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 保存箱唛信息数据 /// /// 保存绑定信息数据 /// /// private async Task SaveBindingDataAsync(string containerCode, List list) { if (list == null || list.Count == 0) return; // 明确指定为异步 lambda await Task.Run(async () => { try { // 数据库操作 bool success = await CommonMethods.db.AddReturnBoolAsync(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 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 { 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 cartonInfo, List 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 printData = new Dictionary(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 { "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}"); } } /// /// 保存包装线出站数据 /// /// 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 containerEntity = CommonMethods.db.QueryWhereList(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(entity); string logMsg = con_success ? $"包装箱[{cartonCode}]出站信息存储成功": $"包装箱[{cartonCode}]出站信息存储失败"; CommonMethods.AddDataMonitorLog(0, logMsg); var entityList = new List { entity }; CommonMethods.ShowBlankingDelegate?.Invoke(entityList); } catch (Exception ex) { LogHelper.Instance.WriteError(cartonCode + $"包装箱出站信息保存处理异常:{ex}", "SysErrorLog"); } } #endregion #region 中转数据给博杰 private async Task TransferStation(JYResult 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("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("DB44.6", PLC.DataType.Short); //short[] value2 = plc.ReadValue("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 GetList(int num, T data) { List list = new List(); for (int i = 0; i < num; i++) { list.Add(data); } return list; } public List GetMesType(int Num) { List mesResTypes = new List(); for (int i = 0; i < Num; i++) { mesResTypes.Add(MesResType.UnKnow); } return mesResTypes; } /// /// PLC内批量写\0 /// /// /// 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 辅助方法 /// /// 检测数据是否只包含字母加数字 /// /// /// public bool IsAlphaNumeric(string input) { // 使用正则表达式检查是否只包含字母和数字 return Regex.IsMatch(input, "^[a-zA-Z0-9]+$"); } ///// ///// 解析条码(通用方法,减少冗余) ///// //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(); //} /// /// 写入PLC结果(封装重复逻辑) /// 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) ); } ///// ///// 电池结果辅助方法 ///// ///// //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 } }