using Hanhe.iWCS.Business; using Hanhe.iWCS.Common; using Hanhe.iWCS.Interface; using Hanhe.iWCS.Model; using System; using System.Collections.Generic; using System.Text; using System.Linq; using MongoDB.Bson; using Hanhe.iWCS.MData; using Newtonsoft.Json; using MongoDB.Driver.Builders; using static Hanhe.iWCS.IndonesiaGLMProtocol.MESHelper; using MongoDB.Driver; using static Hanhe.iWCS.IndonesiaGLMProtocol.ProcessHelper; using static Hanhe.iWCS.IndonesiaGLMProtocol.ApiHelper; using System.Threading; using Hanhe.iWCS.Model.AMS; using Hanhe.iWCS.IndonesiaGLMTCP; using static Hanhe.iWCS.IndonesiaGLMProtocol.ProtocolAnalysis; using System.Threading.Tasks; using static System.Runtime.CompilerServices.RuntimeHelpers; using static Hanhe.iWCS.IndonesiaGLMProtocol.AMSHelper; using System.Collections; using log4net.Config; using System.Text.RegularExpressions; using static Hanhe.iWCS.IndonesiaGLMProtocol.ERPService; using System.Globalization; using System.Security.Cryptography; namespace Hanhe.iWCS.IndonesiaGLMProtocol { public class PLCControl : IPLCControl { private EquipmentCommandEQBLL commandBLL = new EquipmentCommandEQBLL(); /// /// PLC 数据发送 /// /// /// public void SendMessage(EquipmentCommandEQ command) { bool sended = SessionInstance.Instance.PLCSend(command.EquipmentIP, int.Parse(command.EquipmentPort), command.CommandText); if (sended) { //CMMLog.Info("设备指令发送成功;EquipmentCode=" + command.EquipmentCode + "-指令=" + command.CommandText); commandBLL.UpdateCommandEQStatus(command._id, Constants.COMMANDEQ_STATUS_SENDED, command.SendCount); } else { //CMMLog.Info("设备指令发送失败;EquipmentCode=" + command.EquipmentCode + "-指令=" + command.CommandText); commandBLL.UpdateCommandEQStatus(command._id, Constants.COMMANDEQ_STATUS_SEND_ERRORS, command.SendCount); } } /// /// 处理光电信息 /// /// public static void Analysis(string data) { //3f 00 01 00 00 00 24 24 } #region 纯3楼设备任务 #region 3楼包装机取料至复称平台流程——无需回报WMS任务状态——3楼包装取料——已完成(待测试,时间戳处理) #region 收到包装机下料信号1,开始判断复称平台是否满足条件,选择性下发任务 /// /// 3楼包装机取料至复称平台流程——任务开始前,判断包装机有没有下线信号,并判断当前复称平台是否NG以及有没有任务在进行中 /// /// internal static void CheckPackingMachine(Settings.PlcInfo pmInfo) { //var count = MongoDBSingleton.Instance.FindOne<>//occupy var count = MongoDBSingleton.Instance.FindOne(Query.And(Query.EQ("occupy", "1"),Query.EQ("machineNo", pmInfo.location)), "MachineInfo"); //检查包装机通道0是否有下料信号,如果有生成下料任务。线程循环读取,无需设置循环。——通道0参数为1 if (count == null) { if (PickUpStartFree(pmInfo.location) && PickUpEndFree(pmInfo.location)) { try { var result = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, addr = pmInfo.readAddr, host = pmInfo.ip, port = pmInfo.port }); if (result != null && result.errCode == 0) { CMMLog.Debug($"包装下线流程-{pmInfo.location}:读取包装机{pmInfo.device}通道号为:{pmInfo.readAddr}的值为:{result.result[0]}"); if (result != null && result.errCode == 0 && result.result.Count() > 0) { //1:取料 if (result.result[0] == 1 || result.result[0] == 5) { var FCBit = Settings.GetPlcInfo().Where(a => a.deviceType == "2" && a.enable == 1).ToList(); if(FCBit.Count > 0) { foreach(var a in FCBit) { string PlcBit02 = a.location; CMMLog.Debug($"复称点位:{PlcBit02}"); //包装下线任务,终点为复称位置(这里判断包装机起点,复称起点终点均无任务,则推送任务) if (ProcessHelper.PickUpStartFree(pmInfo.location) && ProcessHelper.CheckEndFree(PlcBit02) && ProcessHelper.PickUpStartFree(PlcBit02)) { //判断复称位置,没有货并且不为NG(ng参数0,1,2——0,不确定(包装机刚开始工作时)1,ok 2,ng) var state = GetSecondWeighState(pmInfo.location, PlcBit02); CMMLog.Debug($"包装下线流程:判断复称位置空满状态为:{state.full},ng状态为:{state.ng}"); if (state.full == 0) { if (Settings.mesOpen == "0") { //可以生成任务,调mes接口获取生产信息 2022.7.28 变更 MES可能需要1~2年才能上线,先把MES功能注销 var info = MESHelper.GetPackingMachineInfo(pmInfo.location); if (info != null) { CMMLog.Debug($"包装下线流程:获取MES之后进入info判断!"); //Console.WriteLine($"包装下线流程:获取MES之后进入info判断!"); var trayCode = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { addr = pmInfo.readAddr + 10, dataNum = 80,//数据个数要增加 addr以及dataNum的具体数据为16个 现80个参数 host = pmInfo.ip, port = pmInfo.port }); if (trayCode.errCode == 0 && trayCode.result.Length == 80) { //获取托盘码等信息 读取通道 10、11、12的数据作为托盘码 读取其它通道 重量 叠包等信息 所有数据存入MachineInfo表 GetMachineData(trayCode.result); var tray = MongoDBSingleton.Instance.FindOne(Query.EQ("machineNo", pmInfo.location), "MachineInfo"); if (tray != null && tray.addState == 0) { MongoDBSingleton.Instance.Remove(Query.EQ("machineNo", tray.machineNo), RemoveFlags.Single); CMMLog.Debug("包装下线任务,叠托层数为0,不生成任务"); } else if (tray != null) { if (tray.trayCode != "0" && tray.trayCode != "" && tray.trayCode != null) { //AMSHelper.CreateTask(DateTime.Now.Ticks.ToString(), pmInfo.location, GetSecondWeighBit(), "3楼包装取料", 1, JsonConvert.SerializeObject(info)); int i = 1; while (i == 1) { var amsResult = AMSHelper.CreateTask(DateTime.Now.Ticks.ToString(), pmInfo.location, PlcBit02, "3楼包装取料", 0, tray.trayCode); if (amsResult.success) { i = 2; CMMLog.Debug($"包装下线流程:AMS调用API成功!"); //记录包装间下料信息 MongoDBSingleton.Instance.Insert(new packageInfoModel { machineNo = tray.machineNo, trayCode = tray.trayCode, time = DateTime.Now.ToString("yyyy-MM-dd"), weight = tray.oneTrayWeight }); break; } else CMMLog.Debug($"包装下线流程:AMS调用API失败,开始重新调用!"); } CMMLog.Debug($"包装下线流程:接受并读取包装机通道里面的物料信息,并将其写入MachineInfo中间表中!接收到的信息:{JsonConvert.SerializeObject(trayCode.result)}"); } } else { CMMLog.Debug($"包装下线流程:tray==null!"); //Console.WriteLine($"包装下线流程:tray==null!"); } } else { CMMLog.Debug($"包装下线流程:3楼包装至复称获取MODBUS值错误!trayCode.errCode:{trayCode.errCode},trayCode.result.Length:{trayCode.result.Length}"); //Console.WriteLine($"包装下线流程:3楼包装至复称获取MODBUS值错误!trayCode.errCode:{trayCode.errCode},trayCode.result.Length:{trayCode.result.Length}"); } } else CMMLog.Debug($"包装下线流程:MES接口数据返回空值!MES接口数据:{info}"); } else if (Settings.mesOpen == "1") { //可以生成任务,调mes接口获取生产信息 2022.7.28 变更 MES可能需要1~2年才能上线,先把MES功能注销 CMMLog.Debug($"包装下线流程-{pmInfo.location}:获取MES之后进入info判断!"); var trayCode = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { addr = pmInfo.readAddr + 10, dataNum = 91,////ERP变更:90 原先:80 host = pmInfo.ip, port = pmInfo.port }); if (trayCode.errCode == 0 && trayCode.result.Length == 91) { //获取托盘码等信息 读取通道 11、12、13的数据作为托盘码 读取其它通道 重量 叠包等信息 所有数据存入MachineInfo表 GetMachineData(trayCode.result, false); var tray = MongoDBSingleton.Instance.FindOne(Query.EQ("machineNo", pmInfo.location), "MachineInfo"); if (tray != null) { if (tray.addState == 0) { MongoDBSingleton.Instance.Remove(Query.EQ("machineNo", pmInfo.location), "MachineInfo", RemoveFlags.None); //if (ERPService.ERPSwitch01 == "0") MongoDBSingleton.Instance.Remove(Query.EQ("machineNo", pmInfo.location), "MachineInfoTwo", RemoveFlags.None); CMMLog.Debug($"包装下线流程-{pmInfo.location}:叠托层数为0,不允许生成任务"); } else if (tray.trayCode != "0" && !string.IsNullOrEmpty(tray.trayCode)) { CMMLog.Info($"物料编码:{tray.materialCode},批次号:{tray.lotNo}"); if(result.result[0] == 1) { string timeStamp = ProcessHelper.GetTimeStamp(31, 1, 1); HHAmsExecuteResult req = AMSHelper.CreateTask(DateTime.Now.Ticks.ToString(), pmInfo.location, PlcBit02, "PackagingMachineMaterialHandling", 0, tray.trayCode, timeStamp); //记录包装间下料信息 if (req.success) { string Weight = (decimal.Parse(tray.oneTrayWeight) / 100).ToString("F2"); MongoDBSingleton.Instance.Insert(new packageInfoModel { machineNo = tray.machineNo, trayCode = tray.trayCode, batchNo = tray.lotNo, time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), weight = Weight }); } break; } else { var writeRes0 = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = pmInfo.ip, addr = pmInfo.writeAddr, data = 5,//原先是1,单个写入 port = pmInfo.port }); //人工模式,无需生成任务 //删除machineInfo表中的数据 MongoDBSingleton.Instance.Remove(Query.And(Query.EQ("machineNo", pmInfo.location),Query.EQ("trayCode", tray.trayCode)), "MachineInfo", RemoveFlags.None); //记录包装间下料信息 string Weight = (decimal.Parse(tray.oneTrayWeight) / 100).ToString("F2"); MongoDBSingleton.Instance.Insert(new packageInfoModel { machineNo = tray.machineNo, trayCode = tray.trayCode, batchNo = tray.lotNo, time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), weight = Weight }); break; } //包装取料卸货完成,设备生产数量加一 //判断是否有当天的数据,如果没有,则生成数据 #region var proInfo = MongoDBSingleton.Instance.FindOne(Query.And(Query.EQ("Date", DateTime.Now.ToString("yyyy-MM-dd")), Query.EQ("machine", tray.machineNo)), "ProductList"); if (proInfo != null) { proInfo.total = proInfo.total + 1; proInfo.percentOfPass = Math.Round(((proInfo.qualifiedQuantity / proInfo.total) * 100), 2); MongoDBSingleton.Instance.Update(Query.And(Query.EQ("Date", DateTime.Now.ToString("yyyy-MM-dd")), Query.EQ("machine", tray.machineNo)), Update.Set("total", proInfo.total).Set("percentOfPass", proInfo.percentOfPass), UpdateFlags.None); } else { ProductList machine = new ProductList { Date = DateTime.Now.ToString("yyyy-MM-dd"), machine = tray.machineNo, total = 1, qualifiedQuantity = 0, percentOfPass = 0, overallPassRate = 0 }; MongoDBSingleton.Instance.Insert(machine); } #endregion } } else CMMLog.Debug($"包装下线流程-{pmInfo.location}:tray==null!"); } else CMMLog.Debug($"包装下线流程-{pmInfo.location}:3楼包装至复称获取MODBUS值错误!trayCode.errCode:{trayCode.errCode},trayCode.result.Length:{trayCode.result.Length}"); } } else { var task = MongoDBSingleton.Instance.FindOne(Query.Or(Query.EQ("CN_S_START_BIT", PlcBit02), Query.EQ("CN_S_END_BIT", PlcBit02)), "TN_I_TASK_MST"); if (task != null) CMMLog.Debug($"包装下线流程-{pmInfo.location}:检查复称中间表是否为空,不为空则检查其数据full以及ng是否为0和1!任务号为:{task.CN_S_TASK_NO}"); else CMMLog.Debug($"包装下线流程-{pmInfo.location}:检查复称中间表是否为空,不为空则检查其数据full以及ng是否为0和1!"); } } else { var taskNo = MongoDBSingleton.Instance.FindOne(Query.EQ("CN_S_START_BIT", pmInfo.location), "TN_I_TASK_MST"); var taskNo1 = MongoDBSingleton.Instance.FindOne(Query.Or(Query.EQ("CN_S_START_BIT", PlcBit02), Query.EQ("CN_S_END_BIT", PlcBit02)), "TN_I_TASK_MST"); string task = "", startbit = "", endbit = ""; if (taskNo != null) { task = taskNo.CN_S_TASK_NO; startbit = taskNo.CN_S_START_BIT; endbit = taskNo.CN_S_END_BIT; } else if (taskNo1 != null) { task = taskNo1.CN_S_TASK_NO; startbit = taskNo1.CN_S_START_BIT; endbit = taskNo1.CN_S_END_BIT; } CMMLog.Debug($"包装机起点或者复称起点终点有任务在执行中!任务号:{task},起点:{startbit},终点:{endbit}"); } } } } else CMMLog.Debug($"包装下线流程-{pmInfo.location}:包装机通道0里面的数据不为1!result为:{JsonConvert.SerializeObject(result)}"); } else CMMLog.Debug($"包装下线流程-{pmInfo.location}:未读取到包装机通道0里面的数据!!!result:{JsonConvert.SerializeObject(result)}"); } else CMMLog.Debug($"包装下线流程-{pmInfo.location}:未读取到包装机通道0里面的数据!!!result:{JsonConvert.SerializeObject(result)}"); } catch (Exception ex) { CMMLog.Debug($"包装下线流程-{pmInfo.location}:" + ex.Message); } } else CMMLog.Debug($"当前包装机起点终点有任务正在执行,请确认当前包装机的任务是否取货卸货完成!包装机货位编码:{pmInfo.location}"); } else CMMLog.Debug($"当前machineInfo中间表已存在数据:{JsonConvert.SerializeObject(count)}"); } #endregion #region 包装机MODBUS交互(开始取料,取料完成) /// 小车请求进料 1 AMS写,PLC读 1-请求进入;2-到位后,请求接驳滚动;3-取货完成;4-离开安全门外,清零通道 /// 设备允许出料 1 PLC写,AMS读 1-XXXXXXXX;2-允许进入;3-接驳滚动,送出物料 ;4-结束;5-安全门关闭 /// /// 小车到达包装机安全门口请求进入 /// 判断是否是改道后 复秤入缓存架任务 /// /// internal static void PickUpFullDoorUnload(string ip, string taskNo, string deviceType) { if(deviceType != "2") { var plc = Settings.GetPlcInfo().Where(a => a.ip == ip).FirstOrDefault(); //ASM写入通道0小车动作,1-取料 int[] num = new int[2] { 1, 1 }; var writeRes0 = OITcpHelper.RegisterWriteOutPutMulti(new OITcpHelper.RegisterWriteOutPutModelMulti { host = ip, addr = plc.writeAddr, data = num,//原先是1,单个写入 port = plc.port }); if (writeRes0.errCode == 0) { //小车请求进入安全门交互 //小车请求进料,并且查询设备是否允许AGV进入 //读地址1设备是否 2-可以进入 var readRes = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, host = ip, addr = plc.readAddr + 1, port = plc.port }); CMMLog.Debug($"读取设备{plc.location}通道{plc.readAddr + 1}里面数据为{readRes.result[0]}."); //Console.WriteLine($"读取设备{plc.location}通道{plc.readAddr + 1}里面数据为{readRes.result[0]}."); if (readRes != null && readRes.errCode == 0) { if (readRes.result[0] == 2) { //设备允许进入,改参数通知AGV WorkFlowAction.TrackLog(taskNo, 10, 1012, "success"); TSHelper.GoToAGV(taskNo, 10, 1); } } else CMMLog.Debug($"包装下线:1012,readRes:{readRes},readRes.errCode:{readRes.errCode}"); } } else { PLCControl.SecondWeightInCache1012(ip, taskNo);//二期:直接改参数 } } /// /// 小车请求取货 /// /// /// internal static void PickUpFullUnload(string ip , string taskNo, int port) { var plc = Settings.GetPlcInfo().Where(a => a.ip == ip && a.port == port).FirstOrDefault(); if (ip != "") { //小车请求出料,并且查询设备是否允许AGV进入 //读地址2设备是否 2-允许进料 保险起见,可以不读 var readRes = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, host = ip, addr = plc.readAddr + 1, port = plc.port }); CMMLog.Debug($"读取设备{plc.location}通道{plc.readAddr + 1}里面数据为{readRes.result[0]}."); //Console.WriteLine($"读取设备{plc.location}通道{plc.readAddr + 1}里面数据为{readRes.result[0]}."); if (readRes != null && readRes.errCode == 0) { if (readRes.result[0] == 2) { //TSHelper.GoToAGV(taskNo, 10, 2);//原先先改AGV参数 var writeRes1 = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = ip, addr = plc.writeAddr + 1, data = 2, port = plc.port }); if(writeRes1.errCode == 0) TSHelper.GoToAGV(taskNo, 10, 2); CMMLog.Debug($"写入设备{plc.location}通道{plc.writeAddr + 1}里面数据为2."); //Console.WriteLine($"写入设备{plc.location}通道{plc.writeAddr + 1}里面数据为2."); } } else CMMLog.Debug($"包装下线,1112,readRes={readRes}"); } else CMMLog.Debug($"包装下线,1112,ip=null!"); } /// /// 小车取货完成--二期协议无此指令动作 /// /// /// internal static void PickUpFullComplete(string ip, string taskNo) { var plc = Settings.GetPlcInfo().Where(a => a.ip == ip).FirstOrDefault(); if (ip != "") { //小车请求出料,并且查询设备是否允许AGV进入 //读地址2设备是否 2-允许进料 var readRes = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, host = ip, addr = plc.readAddr+1, port = plc.port }); CMMLog.Debug($"读取设备{plc.location}通道{plc.readAddr + 1}里面数据为{readRes.result[0]}."); //Console.WriteLine($"读取设备{plc.location}通道{plc.readAddr + 1}里面数据为{readRes.result[0]}."); DateTime dateTime = DateTime.Now; if (readRes != null && readRes.errCode == 0) { if (readRes.result[0] == 3) { var writeRes1 = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = ip, addr = plc.writeAddr+1, data = 3, port = plc.port }); CMMLog.Debug($"写入设备{plc.location}通道{plc.writeAddr + 1}里面数据为3."); //Console.WriteLine($"写入设备{plc.location}通道{plc.writeAddr + 1}里面数据为3."); } else if(readRes.result[0] == 4) { WorkFlowAction.TrackLog(taskNo, 10, 1212, "success"); TSHelper.GoToAGV(taskNo, 10, 5); } } else CMMLog.Debug($"包装下线,1212,readRes={readRes}!"); } else CMMLog.Debug($"包装下线,1212,ip=null!"); } /// /// 小车卸货完成离开安全门后通知包装机 /// /// /// internal static void PickUpFullDoorComplete(string ip, string taskNo, string deviceType) { if(deviceType == "1") { var plc = Settings.GetPlcInfo().Where(a => a.ip == ip).FirstOrDefault(); if (plc != null) { //写入包装机--安全门关门指令 var writeRes = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = ip, addr = plc.writeAddr + 1, data = 3, port = plc.port }); CMMLog.Debug($"写入设备{plc.location}通道{plc.writeAddr + 1}里面数据为3."); //Console.WriteLine($"写入设备{plc.location}通道{plc.writeAddr + 1}里面数据为4."); } else CMMLog.Debug($"包装下线,3,ip=null!"); } else { PLCControl.SecondWeightInCache4(deviceType,taskNo); } } #endregion #region 复称平台交互 ///小车请求进料 1 AMS写,PLC读 1-请求进入;2-小车进料,输送托盘;3-XXXXXXX ///设备允许出料 1 PLC写,AMS读 1-XXXXXXXX;2-允许进料,开始滚动;3-上料完成 ///复称平台小车动作: 1:上料复称;2:上砝码教称;3:取复称NG托盘,4:取砝码到包装机 /// ///复称平台安全请求进入——因为现场需求,所以额外增加一个类似安全门的交互,直接改参数就行 /// internal static void SecondWeightSafe(string ip,string taskNo, int port) { var plc = Settings.GetPlcInfo().Where(a => a.ip == ip && a.port == port).FirstOrDefault(); //ASM写入小车动作,1:上料复称;2:上砝码教称;3:取复称NG托盘,4:取砝码到包装机 int[] num = new int[2] { 1, 1 }; var writeRes0 = OITcpHelper.RegisterWriteOutPutMulti(new OITcpHelper.RegisterWriteOutPutModelMulti { host = ip, addr = plc.writeAddr, data = num,//原先是1,单个写入 port = plc.port }); CMMLog.Debug($"写入设备{plc.location}通道{plc.writeAddr}里面数据为1."); //Console.WriteLine($"写入设备{plc.location}通道{plc.writeAddr}里面数据为1."); ///小车和复称位对接 //小车请求进料,并且查询设备是否允许AGV进入 var readRes = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, host = plc.ip, addr = plc.readAddr + 1, port = plc.port }); CMMLog.Debug($"读取设备{plc.location}通道{plc.readAddr + 1}里面数据为{readRes.result[0]}."); //Console.WriteLine($"读取设备{plc.location}通道{plc.readAddr + 1}里面数据为{readRes.result[0]}."); if (readRes != null && readRes.errCode == 0) { if(readRes.result[0] == 2) { WorkFlowAction.TrackLog(taskNo, 10, 1013, "success"); TSHelper.GoToAGV(taskNo, 10, 3); } } //将数据写入通道 } public static int SecondRelax = 0; /// /// 请求进入复称取货 /// /// /// internal static void SecondWeightInCache1012(string ip, string taskNo) { var plc = Settings.GetPlcInfo().Where(a => a.ip == ip).FirstOrDefault(); if (ip != null) { CMMLog.Info($"ip:{ip}"); ///小车和复称位对接 if (ip != "") { //小车请求进料,并且查询设备是否允许AGV进入 WorkFlowAction.TrackLog(taskNo, 10, 1012, "success"); TSHelper.GoToAGV(taskNo, 10, 1); SecondRelax = 0; } else CMMLog.Info($"复称入缓存架,1012,ip=null!"); } else CMMLog.Info($"地址{ip}的设备未配置"); } /// /// 复称卸货 /// /// /// internal static void CheckUpReqUnload(Settings.PlcInfo plc, string taskNo) { ///小车和复称位对接 if (plc != null) { //设备允许进入,改参数通知AGV //WorkFlowAction.TrackLog(taskNo, 10, 1113, "success"); //TSHelper.GoToAGV(taskNo, 10, 4); //CMMLog.Debug($"改AGV参数:10,4"); //判断任务起点,找到起点包装机设备号,在中间表MachineInfo中查找上一台设备(包装机)的数据,通过modbus通道传入(数据需要转换,ASCII转16short,可能还需要数据拆分) var taskInfo = MongoDBSingleton.Instance.FindOne(Query.EQ("CN_S_TASK_NO",taskNo), "TN_I_TASK_MST"); var machine = MongoDBSingleton.Instance.FindOne(Query.EQ("trayCode", taskInfo.CN_S_BATCH_NO), "MachineInfo"); if (machine != null) { CMMLog.Debug("进入machine判断"); //向复称卸货复称,并将从包装机获取到的数据写入通道中 #region 多个数据写入MODBUS var arr = JsonConvert.DeserializeObject>(machine.jsonData); int[] num = new int[91]; for(int i = 0; i <= 90; i++) num[i] = arr[i]; CMMLog.Debug($"num:{JsonConvert.SerializeObject(num)}"); //Console.WriteLine(num); var wirteall = OITcpHelper.RegisterWriteOutPutMulti(new OITcpHelper.RegisterWriteOutPutModelMulti { addr = plc.writeAddr + 10, host = plc.ip, data = num, port = plc.port }); //var writeRes1 = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel //{ // host = plc.ip, // addr = plc.writeAddr + 1, // data = 2, // port = plc.port //}); //CMMLog.Debug($"写入设备{plc.location}通道{plc.writeAddr + 1}里面数据为2."); //Console.WriteLine($"写入设备{plc.location}通道{plc.writeAddr + 1}里面数据为2."); #endregion } else CMMLog.Debug($"machine判断错误,为null!"); } else CMMLog.Debug($"包装下线,1113,ip=null!"); } /// /// 复称卸货完成 /// /// /// /// internal static void CheckUpUnloadComplete(string ip, string cN_S_TASK_NO,string machineNo, int port) { var plc = Settings.GetPlcInfo().Where(a => a.ip == ip && a.port == port).FirstOrDefault(); int[] num = new int[1] { 2 }; var writeRes0 = OITcpHelper.RegisterWriteOutPutMulti(new OITcpHelper.RegisterWriteOutPutModelMulti { host = ip, addr = plc.writeAddr + 1, data = num,//原先是1,单个写入 port = plc.port }); var tray = MongoDBSingleton.Instance.FindOne(Query.EQ("CN_S_TASK_NO", cN_S_TASK_NO), "TN_I_TASK_MST"); var query = Query.And(Query.EQ("actionNo", "1"), Query.EQ("ext1", ip), Query.EQ("ext2", tray.CN_S_BATCH_NO)); var ActionControlInfo = MongoDBSingleton.Instance.FindOne(query, "ActionControlModel"); if (ActionControlInfo == null) { MongoDBSingleton.Instance.Insert(new ActionControlModel { actionNo = "1", ext1 = ip, ext2 = tray.CN_S_BATCH_NO, ext3 = plc.port, machince = machineNo }, "ActionControlModel"); } } /// /// 取货完成,离开复称,复位通道,并读取设备通道数据 /// /// /// internal static void SecondWeightInCache4(string ip, string taskNo) { CMMLog.Info("离开复称平台,任务处理开始"); var plc = Settings.GetPlcInfo().Where(a => a.deviceType == ip).FirstOrDefault(); var trayCodeTask = MongoDBSingleton.Instance.FindOne(Query.EQ("CN_S_TASK_NO", taskNo), "TN_I_TASK_MST"); if (trayCodeTask != null) { string trayCodeNo = trayCodeTask.CN_S_BATCH_NO; if (trayCodeNo != "") { //var status = MongoDBSingleton.Instance.FindOne(Query.EQ("location", GetSecondWeighBit()), "SecondWeighState"); //UpdateBuilder update = Update.Set("full", 0); //if (status.ng != 2) //{ // update = Update.Set("ng", 0).Set("full", 0); //} UpdateBuilder update = Update.Set("full", 0).Set("ng", 0); CMMLog.Info($"开始更改复称状态中间表状态:full:0"); CMMLog.Info($"三楼双层缓存架卸货交互:trayCode:{trayCodeTask.CN_S_BATCH_NO}"); if (MongoDBSingleton.Instance.Remove(Query.EQ("trayCode", trayCodeTask.CN_S_BATCH_NO), "MachineInfo", RemoveFlags.Single)) { CMMLog.Info($"删除中间表MachineInfo的数据成功,tray:{trayCodeTask.CN_S_BATCH_NO}"); } else { CMMLog.Info($"删除中间表MachineInfo的数据失败,tray:{trayCodeTask.CN_S_BATCH_NO}"); } if (ERPService.ERPSwitch01 == "0") MongoDBSingleton.Instance.Remove(Query.EQ("trayCode", trayCodeTask.CN_S_BATCH_NO), "MachineInfoTwo", RemoveFlags.Single); //MongoDBSingleton.Instance.Update(Query.EQ("CN_S_TASK_NO", taskNo), Update.Set("CN_S_BATCH_NO", trayCodeNo), UpdateFlags.None); MongoDBSingleton.Instance.Update(Query.EQ("location", plc.location), update, "SecondWeighState", UpdateFlags.None); } } if (plc != null) { var writeRes1 = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = plc.ip, addr = plc.writeAddr + 3, data = 1, port = plc.port }); CMMLog.Info($"【缓存架入复称】写入通道{plc.writeAddr + 3}的信号为[1]"); } } /// /// 复称平台安全退出(已退出)--二期无需执行此指令动作 /// /// /// /// internal static bool SecondWeightSafeComplete(string ip, string cN_S_TASK_NO) { var plc = Settings.GetPlcInfo().Where(a => a.ip == ip).FirstOrDefault(); bool result = true; if(ip != "") { //var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel //{ // addr = plc.writeAddr, // data = 0, // host = ip, // port = plc.port //}); //CMMLog.Debug($"写入设备{plc.location}通道{plc.writeAddr}里面数据为0."); ////Console.WriteLine($"写入设备{plc.location}通道{plc.writeAddr}里面数据为0."); //var wirte1 = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel //{ // addr = plc.writeAddr + 1, // data = 0, // host = ip, // port = plc.port //}); //CMMLog.Debug($"写入设备{plc.location}通道{plc.writeAddr + 1}里面数据为0."); ////Console.WriteLine($"写入设备{plc.location}通道{plc.writeAddr + 1}里面数据为0."); result = true; } else { CMMLog.Debug($"包装下线,4,ip=null!"); } return result; } internal static void SecondWeightActionOne(ActionControlModel model) { var plc = Settings.GetPlcInfo().Where(a => a.ip == model.ext1 && a.port == model.ext3).FirstOrDefault(); if (plc != null) { bool req = false; var result = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 28, addr = plc.readAddr + 1, host = plc.ip, port = plc.port }); CMMLog.Info("SecondWeightActionOne----" + JsonConvert.SerializeObject(result) + $"{result.result.Length}"); if(result.result.Length > 0) { CMMLog.Debug($"读取设备{plc.location},ip:{plc.ip}通道{plc.readAddr + 1}里面数据为{result.result[2]}."); MongoDBSingleton.Instance.Update(Query.EQ("trayCode", model.ext2), Update.Set("secondNg", result.result[2]), UpdateFlags.None); //获取从复称平台读出的 时间戳,并转换处理为 string 字符串 string timeStamp = Convert.ToInt32(Completion(result.result[25]) + Completion(result.result[26]), 2).ToString(); string wmstaskno = ""; string traycode = ""; CMMLog.Info($"SecondWeightActionOne:readData:{JsonConvert.SerializeObject(result.result)},timeStamp:{timeStamp}"); if (result.result[0] == 3) { int[] num = new int[1] { 0 }; var writeRes0 = OITcpHelper.RegisterWriteOutPutMulti(new OITcpHelper.RegisterWriteOutPutModelMulti { host = plc.ip, addr = plc.writeAddr + 1, data = num,//原先是1,单个写入 port = plc.port }); } if (result.result[0] == 3 && result.result[2] == 1) { CMMLog.Debug($"准备生成复称入缓存架任务,开始确定托盘号:{model.ext2}"); //更新复称平台的数据到中间表 var trayCode = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { addr = plc.readAddr + 8, dataNum = 12,//数据个数要增加 host = plc.ip, port = plc.port }); if (trayCode.errCode == 0 && trayCode.result.Length == 12) { //获取复称OK数据存入MachineInfo表 GetOKWeight(trayCode.result, model.ext2); } else { CMMLog.Debug($"复称OK流程:读取复称平台重量错误!trayCode.errCode:{trayCode.errCode},trayCode.result.Length:{trayCode.result.Length}"); //Console.WriteLine($"复称OK流程:读取复称平台重量错误!trayCode.errCode:{trayCode.errCode},trayCode.result.Length:{trayCode.result.Length}"); } //req = WMSHelper.WMSIn(plc.location, model.ext2, ref wmstaskno, ref traycode, timeStamp); req = WMSHelper.WMSIn(plc.location, model.ext2, ref wmstaskno, ref traycode); //ERPService.updatePackageInfo(model.machince, model.ext2, result.result); if (req) { var queryList = MongoDBSingleton.Instance.Find(Query.And(Query.EQ("machineNo", model.machince), Query.EQ("trayCode", model.ext2), Query.EQ("weight2", "")), "packageInfoModel"); if (queryList.Count > 0) { packageInfoModel query = queryList.OrderByDescending(a => a.time).First(); if (query != null) { CMMLog.Debug($"machine:{query.machineNo},trayCode:{query.trayCode},weight:{query.weight}"); //读取复称平台的重量 double x = (double)Convert.ToInt32(Completion(result.result[0]) + Completion(result.result[1]), 2) / 100; //double x = (double)Convert.ToInt32(Completion(result[8]) + Completion(result[9]), 2) / 100; string weight = x.ToString(); CMMLog.Debug($"读取设备{plc.location},ip:{plc.ip}通道{plc.readAddr + 8}里面数据为{result.result[0]}."); CMMLog.Debug($"读取设备{plc.location},ip:{plc.ip}通道{plc.readAddr + 9}里面数据为{result.result[1]}."); CMMLog.Debug($"weight:{weight}"); //重量差值 string weightDifference = Math.Round((double.Parse(query.weight) - x), 2).ToString(); //将复称平台重量写入中间表 MongoDBSingleton.Instance.Update(Query.And(Query.EQ("machineNo", model.machince), Query.EQ("time", query.time), Query.EQ("trayCode", query.trayCode), Query.EQ("weight2", "")), Update.Set("weight2", weight).Set("weightDifference", weightDifference), UpdateFlags.None); } else CMMLog.Debug($"数据查询失败"); } else CMMLog.Debug($"packageInfoModel未找到数据,machineNo:{model.machince},trayCode:{model.ext2}"); var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + 3, host = plc.ip, port = plc.port, data = 1 }); CMMLog.Debug($"复称任务任务生成完成,ip:{plc.ip},端口:{plc.port},写入通道{plc.writeAddr + 3} 的值为1"); //复称合格,更新表数据 var proInfo = MongoDBSingleton.Instance.FindOne(Query.And(Query.EQ("Date", DateTime.Now.ToString("yyyy-MM-dd")), Query.EQ("machine", model.machince)), "ProductList"); if (proInfo != null) { proInfo.qualifiedQuantity = proInfo.qualifiedQuantity + 1; proInfo.percentOfPass = Math.Round(((proInfo.qualifiedQuantity / proInfo.total) * 100), 2); MongoDBSingleton.Instance.Update(Query.And(Query.EQ("Date", DateTime.Now.ToString("yyyy-MM-dd")), Query.EQ("machine", model.machince)), Update.Set("percentOfPass", proInfo.percentOfPass).Set("qualifiedQuantity", proInfo.qualifiedQuantity), UpdateFlags.None); } } } if (result.result[2] == 2) { CMMLog.Debug($"准备生成复称入缓存架NG任务,开始确定托盘号:{model.ext2}"); //复称平台复称货物NG——进入NG复称流程 调用WMS接口分配货架库位 //TSHelper.GoToAGV(cN_S_TASK_NO, 10, 6); req = WMSHelper.WMSIn(plc.location, model.ext2, ref wmstaskno, ref traycode, timeStamp); //req = WMSHelper.WMSIn(plc.location, model.ext2, ref wmstaskno, ref traycode); if (req) { var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + 3, host = plc.ip, port = plc.port, data = 1 }); CMMLog.Debug($"复称入缓存架NG流程:WMS生成任务成功!"); //更新复称平台的数据到中间表 var trayCode = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { addr = plc.readAddr + 8, dataNum = 2,//数据个数要增加 host = plc.ip, port = plc.port }); if (trayCode.errCode == 0 && trayCode.result.Length == 2) { var queryList = MongoDBSingleton.Instance.Find(Query.And(Query.EQ("machineNo", model.machince), Query.EQ("trayCode", model.ext2), Query.EQ("weight2", "")), "packageInfoModel"); if (queryList.Count > 0) { packageInfoModel query = queryList.OrderByDescending(a => a.time).First(); if (query != null) { CMMLog.Debug($"machine:{query.machineNo},trayCode:{query.trayCode},weight:{query.weight}"); //读取复称平台的重量 double x = (double)Convert.ToInt32(Completion(trayCode.result[0]) + Completion(trayCode.result[1]), 2) / 100; //double x = (double)Convert.ToInt32(Completion(result[8]) + Completion(result[9]), 2) / 100; string weight = x.ToString(); CMMLog.Debug($"读取设备{plc.location},ip:{plc.ip}通道{plc.readAddr + 8}里面数据为{trayCode.result[0]}."); CMMLog.Debug($"读取设备{plc.location},ip:{plc.ip}通道{plc.readAddr + 9}里面数据为{trayCode.result[1]}."); CMMLog.Debug($"weight:{weight}"); //重量差值 string weightDifference = Math.Round((double.Parse(query.weight) - x), 2).ToString(); //将复称平台重量写入中间表 MongoDBSingleton.Instance.Update(Query.And(Query.EQ("machineNo", model.machince), Query.EQ("time", query.time), Query.EQ("trayCode", query.trayCode), Query.EQ("weight2", "")), Update.Set("weight2", weight).Set("weightDifference", weightDifference), UpdateFlags.None); } else CMMLog.Debug($"数据查询失败"); } else CMMLog.Debug($"packageInfoModel未找到数据,machineNo:{model.machince},trayCode:{model.ext2}"); } } else CMMLog.Debug($"复称入缓存架NG流程:WMS生成任务失败!"); } string PlcBit02 = Settings.GetPlcInfo().Where(a => a.deviceType == "2").FirstOrDefault().location; UpdateBuilder update = Update.Set("ng", result.result[2]); if (MongoDBSingleton.Instance.Update(Query.EQ("location", PlcBit02), update, "SecondWeighState", UpdateFlags.None)) { CMMLog.Debug($"中间表SecondWeighState数据插入成功,location:{PlcBit02}"); } if (req) { if (MongoDBSingleton.Instance.Remove(Query.EQ("_id", model._id), "ActionControlModel", RemoveFlags.Single)) { CMMLog.Debug($"中间表ActionControlModel数据删除成功,id:{model._id}"); } } } } else CMMLog.Debug($"复称平台未配置,ip:{model.ext1},端口:{model.ext3}"); } private static void GetOKWeight(int[] result, string ItemCode) { var info = MongoDBSingleton.Instance.FindOne(Query.EQ("trayCode", ItemCode), "MachineInfo"); if (info != null) { CMMLog.Info($"从包装机获取的物料重量:{info.oneTrayWeight}"); var newWeight = Convert.ToInt32(Completion(result[10]) + Completion(result[11]), 2).ToString(); //更新数据 CMMLog.Info($"从复称平台获取的物料重量:{newWeight}"); UpdateBuilder update = Update.Set("oneTrayWeight", newWeight); MongoDBSingleton.Instance.Update(Query.EQ("trayCode", ItemCode), update, "MachineInfo", UpdateFlags.None); //MongoDBSingleton.Instance.Update(Query.EQ("trayCode", ItemCode), Update.Set("oneTrayWeight", info.oneTrayWeight), "MachineInfo", UpdateFlags.None); CMMLog.Info("复称OK的重量更新到中间表MachineInfo"); } var infoTwo = MongoDBSingleton.Instance.FindOne(Query.EQ("trayCode", ItemCode), "MachineInfo"); if (infoTwo != null) { //var newWeight = (Convert.ToInt32(Completion(result[0]) + Completion(result[1]), 2) / 100).ToString(); var newWeight = result[0] + "," + result[1]; //更新数据 CMMLog.Info($"从复称平台获取的物料重量:{newWeight}"); UpdateBuilder update = Update.Set("oneTrayWeightFC", newWeight); MongoDBSingleton.Instance.Update(Query.EQ("trayCode", ItemCode), update, "MachineInfoTwo", UpdateFlags.None); CMMLog.Info("复称毛重更新到中间表MachineInfoTwo"); } } #endregion #endregion #region 3楼双层缓存货架到三楼叠托口——需回报WMS任务状态——3楼缓存架入叠托——半完成(待测试) /// /// 判断三楼叠托口是否有允许上料请求(通道1参数1),有就调WMS生成缓存架到叠托口任务 /// /// internal static void CacheStackingMouth(Settings.PlcInfo pmInfo) { //需要设置时间延迟 try { //读取通道1里面参数是否为1,判断叠盘机是否需要上料 var result = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, addr = pmInfo.readAddr + 1, host = pmInfo.ip, port = pmInfo.port }); if (result != null && result.errCode == 0) { //参数1表示叠托点申请入料 if (result.result[0] == 1) { //var tasks = MongoDBSingleton.Instance.Find(Query.EQ("CN_S_END_BIT", pmInfo.location), "TN_I_TASK_MST"); var tasks = MongoDBSingleton.Instance.Find(Query.EQ("S_END_LOC", pmInfo.location), "elevatorTask"); //判断一下当前叠托点是否有任务占用 if (ProcessHelper.CheckEndFree(pmInfo.location) && tasks.Count == 0) { //可以生成任务,调WMS接口获取任务信息 bool req = WMSHelper.WMSOut(pmInfo.location, ""); if (req) CMMLog.Debug($"调用WMS获取碟盘出库生成任务成功!");//现在任务由WMS自己下发,AMS做拦截处理(查询ext1里面对应的任务类型,并更改任务类型) else CMMLog.Debug($"调用WMS获取碟盘出库生成任务失败!"); } else CMMLog.Debug($"检查当前叠托点是否有任务占用,或者elevatorTask表中有缓存架入叠盘机的任务!"); } } else CMMLog.Debug($"缓存入叠盘机,创建任务,result={result.errMsg}"); } catch (Exception ex) { CMMLog.Error(ex.Message, ex); } } #region 三楼叠托机交互 /// /// 请求进入三楼叠托机 /// /// /// internal static void CacheStackingMouth1013(string ip,string taskNo, string CN_S_END_BIT) { CMMLog.Info("【电梯开门】叠盘机任务请求进入电梯,信号1013"); var plc = Settings.GetPlcInfo().Where(a => a.deviceType == ip).FirstOrDefault(); if(plc != null) { var readres = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, addr = plc.readAddr + 1, host = plc.ip, port = plc.port }); CMMLog.Info($"【电梯开门】读取通道{plc.readAddr + 1}的信号为[{JsonConvert.SerializeObject(readres)}]"); if (readres.result[0] != 2) { var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + 1, host = plc.ip, port = plc.port, data = 1 }); CMMLog.Info($"【电梯开门】写入通道{plc.writeAddr + 1}的信号为[1]"); } else { TSHelper.GoToAGV(taskNo, 10, 3); var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + 1, host = plc.ip, port = plc.port, data = 2 }); CMMLog.Info($"【电梯开门】写入通道{plc.writeAddr + 1}的信号为[2]"); } } else CMMLog.Debug($"缓存入叠盘机,1013,plc=null!"); } /// /// 三楼叠托机扫码 /// /// /// internal static void CacheStackingMouth1313(string dev, TN_I_TASK_MST mst) { CMMLog.Info($"【叠包入口】任务流程处理开始------------"); var plc = Settings.GetPlcInfo().Where(a => a.deviceType == dev).FirstOrDefault(); if(plc != null) { var readres = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 2, addr = plc.readAddr + 1, host = plc.ip, port = plc.port }); if(readres != null) { var eleInfo = MongoDBSingleton.Instance.FindOne(Query.And(Query.EQ("S_DT_LOC", mst.CN_S_START_BIT),Query.EQ("S_USE", "1")), "elevatorTask"); if(eleInfo != null) { var taskInfo = eleInfo.task_mst; CMMLog.Info($"【叠包入口】读取通道{plc.readAddr + 1}的信号为[{readres.result[0]}],收到通道{plc.readAddr + 2}的信号为[{readres.result[1]}]"); if (readres.result[0] == 3) { if (readres.result[1] == 1) { CMMLog.Info($"读码信息比对结果:条码与传送的数据一致"); //读码信息比对结果:OK 读到通道2参数为1时,小车将托盘放置在叠盘机上(改参数10为7) var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + 1, host = plc.ip, data = 3,//4 port = plc.port }); CMMLog.Info($"【叠包入口】写入通道{plc.writeAddr + 1}的信号为{3},返回值:{wirte.errCode}"); if (wirte.errCode == 0) { //并删除WMSInfo中间表中对应托盘号的数据(也可在小车离开叠盘机之后删除,暂定通道2参数1) CMMLog.Info($"读码信息比对结果:OK ,并删除WMSInfo中间表中对应托盘号的数据"); MongoDBSingleton.Instance.Remove(Query.EQ("trayCode", taskInfo.CN_S_BATCH_NO), RemoveFlags.Single); TSHelper.GoToAGV(mst.CN_S_TASK_NO, 10, 7); } //通道写入4,ok流程可以直接写,ng流程需要等到小车取货完之后写入(注:该流程测试通过,暂时可以不改,现场出现问题在更改) PLCControl.CacheStackingMouth6(plc); } else if (readres.result[1] == 2) { CMMLog.Info($"读码信息比对结果:条码与传送的数据不一致"); //二期--调用 WMS 改道接口 获取 目标点位,并 更改 AGV 站点 string ChangeBit = WMSHelper.WmsUpdateWay(taskInfo.CN_S_SOURCE_NO, plc.Extend); if (!string.IsNullOrEmpty(ChangeBit)) { CMMLog.Info($"起点:{taskInfo.CN_S_END_BIT}"); CMMLog.Info($"终点:{ChangeBit}"); int[] parms = { StockInstance.Instance.GetAGVCodeForBitCode(taskInfo.CN_S_END_BIT), StockInstance.Instance.GetAGVCodeForBitCode(ChangeBit) }; //TSHelper.ChangeParam(taskNo, 1, StockInstance.Instance.GetAGVCodeForBitCode(taskInfo.CN_S_END_BIT)); //TSHelper.ChangeParam(taskNo, 2, StockInstance.Instance.GetAGVCodeForBitCode(ChangeBit)); TSHelper.ChangeParam(mst.CN_S_TASK_NO, 1, parms); TSHelper.GoToAGV(mst.CN_S_TASK_NO, 3, 1); TSHelper.GoToAGV(mst.CN_S_TASK_NO, 10, 8); MongoDBSingleton.Instance.Update(Query.EQ("CN_S_TASK_NO", mst.CN_S_TASK_NO), Update.Set("CN_S_END_BIT", ChangeBit).Set("CN_S_START_BIT", taskInfo.CN_S_END_BIT), "TN_I_TASK_MST", UpdateFlags.None); MongoDBSingleton.Instance.Remove(Query.EQ("trayCode", taskInfo.CN_S_BATCH_NO), RemoveFlags.Single); } else CMMLog.Debug($"调用WMS改道接口,未获取到可用点位。"); //Console.WriteLine($"读码信息比对结果:条码与传送的数据不一致"); } } } } } CMMLog.Info($"【叠包入口】任务流程处理结束------------"); } /// /// 卸货离开三楼叠托机--二期:需要和TS对接,让小车 卸货完成等到 小车离开之后再发送 /// /// internal static bool CacheStackingMouth6(Settings.PlcInfo plc) { bool result = false; var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + 1, data = 4, host = plc.ip, port = plc.port }); if (wirte.errCode == 0) result = true; return result; } #endregion #endregion #region 3楼包装机空托补给3楼包装机流程——无需回报WMS任务状态——3楼包装补空——已完成(待测试) /// /// 3楼包装机补空托流程——任务开始前,判断包装机有没有下线信号,并判断当前包装机对应的地堆位是否有任务占用 /// /// internal static void PickUpBlank(Settings.PlcInfo pmInfo) { /* 包装补空流程: * 先判断包装机是否有任务占用,若无任务占用则判断是否需要补空托 * 判断起点是否有任务占用 * **/ //包装补空缺陷,同时会有两个空托点补一个包装机 try { if (ProcessHelper.PickUpEndFree(pmInfo.location)) { //读取输入寄存器还是输出寄存器待定,读取通道0的数据 var result = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, addr = pmInfo.readAddr, host = pmInfo.ip, port = pmInfo.port }); CMMLog.Info($"包装机补空托流程:包装机号:{pmInfo.location},判断包装机通道{pmInfo.readAddr}值为{JsonConvert.SerializeObject(result)},ip:{pmInfo.ip}"); if (result.result.Count() > 0) { if (result != null && result.errCode == 0) { //1:取料;3:人工叫空托盘 if (result.result[0] == 3) { //包装线补空流程 //判断空托缓存点(5 对 2)是否有空托,有空托判断是否有任务,有任务则判断另一个点位 var locInfo = Settings.GetAGVLocationList().Where(b => b.machineLoc.Contains(pmInfo.location) && b.Enabel == 1).First(); if (locInfo != null) { CMMLog.Info($"包装机点位:{pmInfo.location}"); foreach (var a in locInfo.ddLoc) { if (ProcessHelper.PickUpEndFree(pmInfo.location) && ProcessHelper.PickUpStartFree(a)) { var empInfo = MongoDBSingleton.Instance.FindOne(Query.EQ("Bit", a), "BZEmptyPoint"); if (empInfo != null && empInfo.Quantity > 0) { CMMLog.Info($"包装线补空任务,包装机点位:{pmInfo.location},周转托盘位:{a},周转托盘位数量:{empInfo.Quantity}"); HHAmsExecuteResult amsResult = AMSHelper.CreateTask(DateTime.Now.Ticks.ToString(), a, pmInfo.location, "PackagingMachineFillsEmptyPallet", 0, ""); if (amsResult.success) { CMMLog.Info($"包装线补空任务生成成功"); break; } } } } } else { CMMLog.Info("配置文件未配置包装机空托缓存点"); } } } else { CMMLog.Info($"err 包装机通道{pmInfo.readAddr} ip:{pmInfo.ip}"); } } } } catch (Exception ex) { CMMLog.Error(ex.Message, ex); } } static object PickUpBlankCompleteLock = new object(); /// /// 包装补空任务完成--复位 收到上空信号 为 0 /// /// internal static void PickUpBlankComplete(string PlcBitCache01,string Extend = "") { lock (PickUpBlankCompleteLock) { CMMLog.Info("包装线补空流程任务处理"); try { if (Extend != "") { CMMLog.Info($"当前周转托盘位:{Extend}"); int addr = 0; int qun = 0; //修改中间表的值,若中间表的数量为0,则调用解绑方法 var bzEmp = MongoDBSingleton.Instance.FindOne(Query.EQ("Bit", Extend), "BZEmptyPoint"); if (bzEmp != null) { CMMLog.Info($"当前货位的数量:{bzEmp.Quantity}"); if (bzEmp.Quantity == 1) { CMMLog.Info($"调用解绑接口"); //解绑 if (WMSHelper.WMSEmptyUnbind(Extend)) { //删除中间表数据 MongoDBSingleton.Instance.Remove(Query.EQ("Bit", Extend), RemoveFlags.Single); } } else { var quantity = bzEmp.Quantity - 1; var updateBuider = Update.Set("Quantity", quantity); MongoDBSingleton.Instance.Update(Query.EQ("Bit", Extend), updateBuider, UpdateFlags.None); CMMLog.Info($"减去当前周转托盘位数量之后,数量为:{quantity}"); qun = quantity; } } } } catch (Exception ex) { CMMLog.Error($"PickUpBlankComplete Error:" + ex.Message); } } } #endregion #region 3楼补给成品空托区到3楼拆盘机流程——需回报WMS任务状态——3楼拆盘补空——已完成(待测试) /// /// 线程循环查询拆盘机是否需要补空托 /// /// internal static void CheckPackingLineEmpty(Settings.PlcInfo plc) { //读plc信号,看有没有叫料请求,判断是否已经有任务 //没有任务,调WMS生成空托补充任务 try { //RegisterReadInPut 读取输入寄存器还是输出寄存器待定,读取通道1的数据 var result = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, addr = plc.readAddr+1, host = plc.ip, port = plc.port }); if (result != null && result.errCode == 0) { //1.补空托盘 if (result.result[0] == 1) { //判断3楼拆盘机(补空托盘点位)终点是否有任务占用,没有则生成任务 if (ProcessHelper.CheckEndFree(plc.location)) { string wmstaskno = ""; string traycode = ""; bool req = WMSHelper.WMSEmptyOut(plc.location, "", ref wmstaskno, ref traycode); if (req) CMMLog.Debug($"调用WMS获取三楼拆盘机生成任务成功!"); else CMMLog.Debug($"调用WMS获取三楼拆盘机生成任务失败!"); } } } } catch (Exception ex) { CMMLog.Error(ex.Message, ex); } } #region 拆盘机交互 /// 小车请求出料 1 AMS写,PLC读 1-请求出料;2-出料进行中;3-动作完成 /// 设备允许进料 1 PLC写,AMS读 1-允许进料;2-进料进行中;3-动作完成 /// /// 向拆盘机请求卸货 /// /// internal static void DiscRemoverReqUnload(string ip, string taskNo) { var plc = Settings.GetPlcInfo().Where(a => a.deviceType == ip).FirstOrDefault(); if (plc != null) { var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + 1, host = plc.ip, port = plc.port, data = 1 }); CMMLog.Info($"写{plc.ip}取通道{plc.writeAddr + 1}的数据为1"); var readRes = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, host = plc.ip, port = plc.port, addr = plc.readAddr + 1 }); CMMLog.Info($"读{plc.ip}取通道{plc.readAddr + 1}的数据为{JsonConvert.SerializeObject(readRes)}"); if (readRes != null && readRes.errCode == 0) { if (readRes.result[0] == 0 || readRes.result[0] == 1) { //不允许进料,ams写入请求出料 var writeRes = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = plc.ip, port = plc.port, addr = plc.writeAddr + 1, data = 1 }); } else if (readRes.result[0] == 2) { //设备允许进料 //改参数通知agv if (TSHelper.GoToAGV(taskNo, 10, 3)) { WorkFlowAction.TrackLog(taskNo, 10, 1013, "success"); //改成出料进行中 CMMLog.Debug("三楼拆盘机:小车正在卸空盘中!"); var writeRes = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = plc.ip, port = plc.port, addr = plc.writeAddr + 1, data = 2 }); } else CMMLog.Debug($"三楼拆盘补空,1013,TS,10,3,false!"); } } } } /// /// 小车卸货完成离开通知拆盘机 /// /// /// internal static bool DiscRemoverUnloadComplete(string ip, string taskNo) { var result = false; var plc = Settings.GetPlcInfo().Where(a => a.deviceType == ip).FirstOrDefault(); if (plc != null) { //1.0 读地址1设备是否动作完成 //var readRes = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel //{ // dataNum = 1, // host = plc.ip, // port = plc.port, // addr = plc.readAddr + 1 //}); //CMMLog.Info($"读{plc.ip}取通道{plc.readAddr + 1}的数据为{readRes.result[0]}"); //if (readRes != null && readRes.errCode == 0) //{ //if (readRes.result[0] == 2) //{ var writeRes = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = plc.ip, port = plc.port, addr = plc.writeAddr + 1, data = 3 }); CMMLog.Info($"写入{plc.ip}通道{plc.writeAddr + 1}的数据为{3}"); result = true; CMMLog.Debug("读取设备【参数不为0】,AMS设置小车【动作完成】,等待设备【参数为0】时再改参数通知agv"); //} //} } else CMMLog.Info($"deviceType:{ip},未找到"); return result; } #endregion #endregion #region 3楼叠盘机满托下线入库流程——需回报WMS任务状态——3楼叠盘下线--已完成(待测试) /// /// 线程循环查询叠盘机是否需要下满托 /// /// internal static void StackingLineEmpty(Settings.PlcInfo plc) { //读plc信号,看有没有叫料请求,判断是否已经有任务 //没有任务,调WMS生成空托补充任务 try { //RegisterReadInPut 读取输入寄存器还是输出寄存器待定,读取通道1的数据 var result = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, addr = plc.readAddr + 1, host = plc.ip, port = plc.port }); if (result != null && result.errCode == 0) { //1.满托下线 if (result.result[0] == 1) { //判断3楼叠盘起点是否有任务占用,没有则生成任务 if (ProcessHelper.CheckStartFree(plc.location)) { string wmstaskno = ""; string traycode = ""; bool req = WMSHelper.WMSIn(plc.location, "", ref wmstaskno, ref traycode); if (req) CMMLog.Debug($"调用WMS获取三楼叠盘机生成任务成功!"); else CMMLog.Debug($"调用WMS获取三楼叠盘机生成任务失败!"); } } } } catch (Exception ex) { CMMLog.Error(ex.Message, ex); } } #region 叠盘机交互 /// 小车请求出料 1 AMS写,PLC读 1-请求出料;2-出料进行中;3-动作完成 /// 设备允许进料 1 PLC写,AMS读 1-允许进料;2-进料进行中;3-动作完成 /// /// 向叠盘机请求取货 /// /// internal static void StackingReqUnload(string ip, string taskNo) { var plc = Settings.GetPlcInfo().Where(a => a.deviceType == ip).FirstOrDefault(); if (plc != null) { var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + 1, host = plc.ip, port = plc.port, data = 1 }); CMMLog.Debug($"写入通道号为:{plc.writeAddr + 1},的数据为:1"); var readRes = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, host = plc.ip, port = plc.port, addr = plc.readAddr + 1 }); CMMLog.Debug($"读取通道号为:{plc.readAddr + 1},的数据为:{JsonConvert.SerializeObject(readRes)}"); if (readRes != null && readRes.errCode == 0) { if (readRes.result[0] == 0 || readRes.result[0] == 1) { //不允许进料,ams写入请求出料 var writeRes = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = plc.ip, port = plc.port, addr = plc.writeAddr + 1, data = 1 }); } else if (readRes.result[0] == 2) { //设备允许进料 //改参数通知agv if (TSHelper.GoToAGV(taskNo, 10, 1)) { WorkFlowAction.TrackLog(taskNo, 10, 1013, "success"); //改成出料进行中 CMMLog.Debug("三楼叠盘机:小车正在取托盘中!"); var writeRes = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = plc.ip, port = plc.port, addr = plc.writeAddr + 1, data = 2 }); CMMLog.Debug($"写入通道号为:{plc.writeAddr + 1},的数据为:2"); } else CMMLog.Debug($"三楼叠盘机,1013,TS,10,3,false!"); } } } } /// /// 小车取货完成离开通知叠盘机 /// /// /// internal static bool StackingComplete(string ip, string taskNo) { var result = false; var plc = Settings.GetPlcInfo().Where(a => a.deviceType == ip).FirstOrDefault(); if (plc != null) { //1.0 读地址1设备是否动作完成 var writeRes = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = plc.ip, port = plc.port, addr = plc.writeAddr + 1, data = 3 }); result = true; CMMLog.Debug("读取设备【参数不为0】,AMS设置小车【动作完成】,等待设备【参数为0】时再改参数通知agv"); } return result; } #endregion #endregion #region 包装线补空任务 internal static void PackingLine(string ip, string taskNo) { var plc = Settings.GetPlcInfo().Where(a => a.ip == ip).FirstOrDefault(); //ASM写入小车动作,1:上料复称;2:上砝码教称;3:取复称NG托盘,4:取砝码到包装机 int[] num = new int[1] { 1 }; var writeRes0 = OITcpHelper.RegisterWriteOutPutMulti(new OITcpHelper.RegisterWriteOutPutModelMulti { host = ip, addr = plc.writeAddr + 2, data = num,//原先是1,单个写入 port = plc.port }); CMMLog.Debug($"写入设备{plc.location}通道{plc.writeAddr + 2}里面数据为1."); writeRes0 = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = ip, addr = plc.writeAddr, data = 3,//原先是1,单个写入 port = plc.port }); CMMLog.Debug($"写入设备{plc.location}通道{plc.writeAddr + 2}里面数据为1."); //Console.WriteLine($"写入设备{plc.location}通道{plc.writeAddr + 2}里面数据为1."); ///小车和复称位对接 //小车请求进料,并且查询设备是否允许AGV进入 var readRes = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, host = plc.ip, addr = plc.readAddr + 2, port = plc.port }); CMMLog.Debug($"读取设备{plc.location}通道{plc.readAddr + 2}里面数据为{readRes.result[0]}."); //Console.WriteLine($"读取设备{plc.location}通道{plc.readAddr + 2}里面数据为{readRes.result[0]}."); if (readRes != null && readRes.errCode == 0) { if (readRes.result[0] == 2) { var writeRes = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = ip, addr = plc.writeAddr + 2, data = 2, port = plc.port }); CMMLog.Debug($"写入设备{plc.location}通道{plc.writeAddr + 2}里面数据为2."); //Console.WriteLine($"写入设备{plc.location}通道{plc.writeAddr + 2}里面数据为2."); WorkFlowAction.TrackLog(taskNo, 10, 1013, "success"); TSHelper.GoToAGV(taskNo, 10, 3); } } } #endregion #endregion #region 跨楼层任务 #region 货物入库流程——满托入库 #region 收到打包机下线信号,判断条件是否允许,选择性下发任务 internal static void CheckPackingLineFull1(Settings.PlcInfo plc) { //读plc信号,看有没有下线请求,判断是否已经有任务 //没有任务,继续plc,包装下线的物料信号 //检查打包机通道1是否有出料任务信号,如果有生成取料任务。 if (CheckStartFree(plc.location)) { try { var result = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, addr = plc.readAddr + 1, host = plc.ip, port = plc.port }); CMMLog.Debug($"打包下线流程:读取通道号为:{plc.readAddr + 1},ip:{plc.ip},端口:{plc.port}"); CMMLog.Debug($"值为:{result.result[0]}"); if (result != null && result.errCode == 0) { if (result.result[0] == 1) { //获取MODBUS通道里面存放的时间戳 var resultTime = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { addr = plc.readAddr + 10, host = plc.ip, port = plc.port, dataNum = 2 }); if (resultTime.errCode == 0) { string wmstaskno = ""; string timeCuoData = (resultTime.result[0] * 65536 + resultTime.result[1]).ToString(); //CMMLog.Info($"获取到的MODBUS时间戳:{timeCuoData},地址:{plc.ip},端口:{plc.port},通道:{plc.readAddr + 10}、{plc.readAddr + 11}"); //Console.WriteLine($"获取到的MODBUS时间戳:{timeCuoData}"); //这里需要调用照相机接口,获取数据存入中间表,等到入库流程完成,将数据传送给WMS CMMLog.Info($"获取到的MODBUS时间戳:{timeCuoData}"); //Console.WriteLine($"获取到的MODBUS时间戳:{timeCuoData}"); //这里需要调用照相机接口,获取数据存入中间表,等到入库流程完成,将数据传送给WMS string deviceNo = ""; var timecuo = TimeCuo(timeCuoData, ref deviceNo); if (timecuo != null) { string timeStamp = timecuo.data.First().timeStamp.ToString(); string employeeId = timecuo.data.First().employeeID1.ToString(); WMSHelper.WMSIn(plc.location, "打包下线", ref wmstaskno, ref timeStamp, timeStamp, "CPHJ"); } else CMMLog.Info($"时间戳接口返回值为空!"); } } } } catch (Exception ex) { CMMLog.Debug(ex.Message+ "CheckPackingLineFull1"); } } } public class MATERIALSync { public ObjectId _id { get; set; } /// /// 名称 /// public string FName { get; set; } /// /// 流水号 /// public string FNumber { get; set; } public string FExpUnit { get; set; } public string FStoreUnit { get; set; } /// /// 员工编号 /// public string EMP_FNumber { get; set; } /// /// 员工名称 /// public string EMP_FName { get; set; } public DateTime time { get; set; } } #endregion #region 打包机出口MODBUS交互(开始取料,取料完成) /// 小车请求进料 1 AMS写,PLC读 1-AGV到位信号;2-到位后,请求接驳滚动;3-取货完成; /// 设备允许出料 1 PLC写,AMS读 1-设备请求出料;2-允许进入;3-确认货物取走,送出物料; ///打包线下线——小车开始取货 internal static void PackingLineUnload1012(string ip, string taskNo) { CMMLog.Info($"【打包下线】起点安全请求进入流程处理开始--------"); var plc = Settings.GetPlcInfo().Where(a => a.deviceType == "4").FirstOrDefault(); if (plc != null) { try { var readRes = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, addr = plc.readAddr + 1, host = plc.ip, port = plc.port }); if (readRes != null && readRes.errCode == 0) { CMMLog.Info($"【打包下线】读取通道{plc.readAddr + 1}的数据为:{readRes.result[0]}"); if (readRes.result[0] == 1) { var write = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + 1, data = 1, host = plc.ip, port = plc.port }); CMMLog.Info($"【打包下线】写入通道{plc.writeAddr + 1}的数据为:{1}"); } else if (readRes.result[0] == 2) { TSHelper.GoToAGV(taskNo, 10, 1); var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + 1, data = 2, host = plc.ip, port = plc.port }); CMMLog.Info($"【打包下线】写入通道{plc.writeAddr + 1}的数据为:{2}"); } } else CMMLog.Info($"【打包下线】读取通道{plc.readAddr + 1}的数据失败"); } catch (Exception ex) { CMMLog.Info(ex.Message); } } else CMMLog.Info($"ip为:{ip}的设备未配置"); CMMLog.Info($"【打包下线】起点安全请求进入流程处理结束--------"); } /// /// 打包线下线——小车取货完成 /// /// /// internal static void PackingLineComplete4(string ip, string taskNo) { CMMLog.Info($"【打包下线】起点安全请求退出流程处理开始-------------"); //取货完成后需要读取设备时间戳里面的数据,并将其暂存至中间表等到入库任务完成传输给WMS var plc = Settings.GetPlcInfo().Where(a => a.deviceType == "4").FirstOrDefault(); if (plc != null) { try { //var readRes = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel //{ // dataNum = 1, // addr = plc.readAddr + 1, // host = plc.ip, // port = plc.port //}); //if (readRes != null && readRes.errCode == 0) //{ // CMMLog.Info($"【打包下线】读取通道{plc.readAddr + 1}的值为{readRes.result[0]}"); // if (readRes.result[0] == 3) // { var write = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + 1, data = 3, host = plc.ip, port = plc.port }); CMMLog.Info($"【打包下线】写入通道{plc.writeAddr + 1}的值为{3}"); // } //} //else CMMLog.Info($"【打包下线】读取通道{plc.readAddr + 1}的值失败"); } catch (Exception ex) { CMMLog.Info(ex.Message); } } else CMMLog.Info($"ip为{ip}的设备未配置"); CMMLog.Info($"【打包下线】起点安全请求退出流程处理结束-------------"); } #endregion #endregion #endregion public static DateTime TenMin = DateTime.MinValue; /// /// 每隔十分钟往所有开启的打包下线口MODBUS通道里面写小车电量 /// 其实地址26,连续往里面写入四个值 /// internal static void WriteBattery() { CMMLog.Info("写入小车电量:进入写入电量信息流程!"); ////Console.WriteLine("写入小车电量:进入写入电量信息流程!"); if(TenMin == DateTime.MinValue) TenMin = DateTime.Now; else if (DateTime.Now.Subtract(TenMin).TotalMinutes >= 10) { //Console.WriteLine("写入小车电量:写入所有开启的打包下线口MODBUS通道电量值,并重置时间为当前时间"); CMMLog.Info("写入小车电量:写入所有开启的打包下线口MODBUS通道电量值,并重置时间为当前时间"); //写入所有开启的打包下线口MODBUS通道电量值,并重置时间为当前时间 //获取所有电量值 int[] num = ProcessHelper.GetBatteryHang(); CMMLog.Info($"写入小车电量:写入数据:{JsonConvert.SerializeObject(num)}"); //Console.WriteLine($"写入小车电量:写入数据:{JsonConvert.SerializeObject(num)}"); var PlcInfo04 = Settings.GetPlcInfo().Where(a => a.enable == 1 && a.deviceType == "4").FirstOrDefault();//plcInfo if (PlcInfo04 != null) { var wirteall = OITcpHelper.RegisterWriteOutPutMulti(new OITcpHelper.RegisterWriteOutPutModelMulti { addr = PlcInfo04.writeAddr + 5, host = PlcInfo04.ip, data = num, port = PlcInfo04.port }); } TenMin = DateTime.Now; } } #region 数据处理业务 /// /// 获取设备的包装物料信息(并写入中间表) /// /// /// /// true : MES交互方式 false : 无MES交互方式 private static void GetMachineData(int[] result ,bool noPack = true) { //Console.WriteLine($"进入数据处理流程!"); CMMLog.Info($"进入数据处理流程!"); string trayCode = GetTrayCode(result.Take(3).ToArray());//托盘码 //string location = RemoveNull(GetTrayCode(result.Skip(3).Take(1).ToArray()));//设备货位编码 string location = Convert.ToInt32(Completion(result[3]), 2).ToString(); if (trayCode != null && location != null) { CMMLog.Info($"trayCode:{trayCode},location:{location}"); var json = ""; if (!noPack) { CMMLog.Info($"数据处理流程:包装机无MES情况下,自动生成以当前包装机号{location}为首的数据"); var task = MongoDBSingleton.Instance.FindOne(Query.EQ("machineNo", location), "MachineInfo"); if (task == null) { if (MongoDBSingleton.Instance.Insert(new MachineInfo { machineNo = location, })) CMMLog.Info($"MachineInfo中插入数据,包装机号:{location}"); } else CMMLog.Info($"数据处理流程:包装机无MES情况下,模拟MES数据,中间表中已有当前包装机号{location}为首的数据"); var taskTwo = MongoDBSingleton.Instance.FindOne(Query.EQ("trayCode", trayCode), "MachineInfoTwo"); if (taskTwo != null) { MongoDBSingleton.Instance.Update(Query.EQ("trayCode", trayCode), Update.Set("machineNo", location), UpdateFlags.None); CMMLog.Info($"MachineInfoTwo中更新入数据,托盘号:{trayCode}"); } else { if (MongoDBSingleton.Instance.Insert(new MachineInfoTwo { machineNo = location, trayCode = trayCode, })) CMMLog.Info($"MachineInfoTwo中插入数据,包装机号:{location}"); } } var info = MongoDBSingleton.Instance.FindOne(Query.EQ("machineNo", location), "MachineInfo"); if (info != null) { CMMLog.Info($"info:{info}"); #region 获取设备通道信息 #region 转换后 info.location = location; info.trayCode = trayCode; //获取重量 叠包等其它信息 info.productWeight = Convert.ToInt32(Completion(result[4]) + Completion(result[5]), 2).ToString(); CMMLog.Info($"获取数据 productWeight:{info.productWeight}"); info.trayCodeWeight = Convert.ToInt32(Completion(result[6]) + Completion(result[7]), 2).ToString(); CMMLog.Info($"获取数据 trayCodeWeight:{info.trayCodeWeight}"); double x = (double)Convert.ToInt32(Completion(result[8]) + Completion(result[9]), 2) / 100; info.oneTrayWeight = x.ToString(); CMMLog.Info($"获取数据 oneTrayWeight:{info.oneTrayWeight}"); //预留托盘类型 10通道 info.addState = Convert.ToInt32(Completion(result[11]), 2); CMMLog.Info($"获取数据 addState:{info.addState}"); if (info.addState == 0) CMMLog.Error($"获取MODBUS信息异常:是否叠包值为0."); info.packageCode = Convert.ToInt32(Completion(result[12]), 2).ToString(); CMMLog.Info($"获取数据 packageCode:{info.packageCode}"); //info.empNum = Convert.ToInt32(Completion(result[13]) + Completion(result[14])+ Completion(result[15]) + Completion(result[16]) + Completion(result[17]), 2).ToString(); info.empNum = RemoveNull(GetTrayCode(result.Skip(13).Take(5).ToArray()));//员工编号 CMMLog.Info($"获取数据 empNum:{info.empNum}"); info.productTime = Convert.ToInt32(Completion(result[18]) + Completion(result[19]), 2).ToString(); CMMLog.Info($"获取数据 productTime:{info.productTime}"); CMMLog.Debug($"获取MODBUS转换后的数据信息:location:{info.location},trayCode:{info.trayCode},productWeight:{info.productWeight}" + $",trayCodeWeight:{info.trayCodeWeight},oneTrayWeight:{info.oneTrayWeight}" + $",addState:{info.addState},packageCode:{info.packageCode},empNum:{info.empNum},productTime:{info.productTime}"); #endregion #region 转换前 for (int i = 0; i <= 90; i++) { info.machinedown[i] = result[i]; } //将数组数据接受转换为JSON数据并在后续方法判断中存入中间表 json = JsonConvert.SerializeObject(info.machinedown); CMMLog.Debug($"获取MODBUS转换前的数据信息:{json}"); //Console.WriteLine($"获取MODBUS转换前的数据信息:{json}"); #endregion #endregion } else CMMLog.Info($"请查询表中machineNo字段是否为当前包装机号,并且trayCode是否为0"); var infoPack = MongoDBSingleton.Instance.FindOne(Query.And(Query.EQ("machineNo", location), Query.EQ("trayCode", "0")), "MachineInfo"); if (infoPack != null) { //包装机下线至复称,读取包装机平台数据 CMMLog.Info("进入info判断01"); //AMS包装机下线首先调用MES,之后获取新的设备数据存入中间表 //根据托盘号获取指定的通道的JSON数据,将其转换为数组类型——写入通道数据时会使用 //var arr = JsonConvert.DeserializeObject>(json); if(!noPack) { CMMLog.Info($"数据处理流程:包装机无MES情况下,获取以往MES传输的数据,并原样写入原先MES字段中。"); info.lotNo = RemoveNull(GetTrayCode(result.Skip(20).Take(20).ToArray()).Trim().ToString()); info.productType = RemoveNull(GetTrayCode(result.Skip(40).Take(10).ToArray()).Trim().ToString()); info.materialCode = RemoveNull(GetTrayCode(result.Skip(50).Take(15).ToArray()).Trim().ToString()); info.materialName = RemoveNull(GetTrayCode(result.Skip(65).Take(20).ToArray()).Trim().ToString()); info.measurementUnit = RemoveNull(GetTrayCode(result.Skip(85).Take(5).ToArray()).Trim().ToString()); //info.organizeCode = RemoveNull(GetTrayCode(result.Skip(90).Take(1).ToArray()).Trim().ToString()); info.organizeCode = result[90].ToString(); CMMLog.Info($"获取包装机的物料编码:{RemoveNull(GetTrayCode(result.Skip(50).Take(20).ToArray()).Trim().ToString())}"); CMMLog.Info($"数据处理流程:包装机无MES情况下,获取以往MES传输的数据,新获得数据,lotNo:{info.lotNo},productType:{info.productType},materialCode:{info.materialCode},materialName:{info.materialName},measurementUnit:{info.measurementUnit},organizeCode:{info.organizeCode}"); //注意:这里赋值中间表参数请对照信息交互表具体通道值对应 UpdateBuilder update = Update.Set("palletLayers", info.secondNg.ToString()).Set("overlappingLayers", info.addState.ToString()).Set("bagNo", info.packageCode). Set("lotNo", info.lotNo).Set("productType", info.productType).Set("materialCode", info.materialCode).Set("materialName",info.materialName). Set("measurementUnit", info.measurementUnit).Set("organizeCode", info.organizeCode); MongoDBSingleton.Instance.Update(Query.EQ("machineNo", location), update, UpdateFlags.None); MongoDBSingleton.Instance.Update(Query.EQ("trayCode", trayCode), update, UpdateFlags.None); } //在中间表中找到刚刚插入的MES数据(目前还没有读取并写入设备数据) var query1 = Query.And(Query.EQ("machineNo", location), Query.EQ("trayCode", "0")); UpdateBuilder updateBuider = Update.Set("location", info.location). Set("trayCode", info.trayCode).Set("productWeight", info.productWeight). Set("trayCodeWeight", info.trayCodeWeight).Set("oneTrayWeight", info.oneTrayWeight). Set("addState", info.addState).Set("packageCode", info.packageCode).Set("empNum", info.empNum).Set("productTime", info.productTime). Set("jsonData", json).Set("modify", DateTime.Now); MongoDBSingleton.Instance.Update(query1, updateBuider, UpdateFlags.None); MongoDBSingleton.Instance.Update(Query.EQ("trayCode", trayCode), updateBuider, UpdateFlags.None); CMMLog.Info($"MachineInfo:更新MachineInfo中间表刚刚插入的MES数据!设备号为:{location},托盘号为:{trayCode}"); CMMLog.Info($"MachineInfo:更新MachineInfoTwo中间表刚刚插入的MES数据!设备号为:{location},托盘号为:{trayCode}"); } else { //复称入缓存架,读取复称平台数据 CMMLog.Info("进入info判断02"); //读取除包装机外其他设备的信息,更新包装机下线时的数据 var query2 = Query.And(Query.EQ("machineNo", location), Query.EQ("trayCode", trayCode)); var info2 = MongoDBSingleton.Instance.FindOne(query2, "MachineInfo"); if (info2 != null) { UpdateBuilder updateBuider = Update.Set("location", info.location). Set("trayCode", info.trayCode).Set("productWeight", info.productWeight). Set("trayCodeWeight", info.trayCodeWeight).Set("oneTrayWeight", info.oneTrayWeight). Set("addState", info.addState).Set("packageCode", info.packageCode).Set("empNum", info.empNum).Set("productTime", info.productTime). Set("jsonData", json).Set("modify", DateTime.Now); MongoDBSingleton.Instance.Update(query2, updateBuider, UpdateFlags.None); MongoDBSingleton.Instance.Update(query2, updateBuider, UpdateFlags.None); CMMLog.Info($"MachineInfo:更新MachineInfo中间表其他设备的数据!设备号为:{location},托盘号为:{trayCode}"); } else CMMLog.Info($"MachineInfo:无法在MachineInfo中间表中找到当前设备编号的数据!当前设备编号为:{location},托盘码为:{trayCode}"); } } else { //Console.WriteLine("数据流程处理托盘号或包装机号为空值!"); CMMLog.Info("数据流程处理托盘号或包装机号为空值!"); } //Console.WriteLine($"数据处理流程结束!"); CMMLog.Info($"数据处理流程结束!"); } /// /// 获取复称点状态信息 /// /// public static SecondWeighState GetSecondWeighState(string location,string devicetype) { CMMLog.Debug($"查询点位:{devicetype}"); //传入当前设备编号,并将传入的设备编号放入复称中间表的来源变量中 string PlcBit02 = Settings.GetPlcInfo().Where(a => a.location == devicetype && a.enable == 1).FirstOrDefault().location; var query = Query.EQ("location", PlcBit02); var model = MongoDBSingleton.Instance.FindOne(query, "SecondWeighState"); if (model == null) { MongoDBSingleton.Instance.Insert(new SecondWeighState { location = PlcBit02, from = location,full = 0,ng = 1 }); CMMLog.Debug($"判断复称状态信息服务,复称中间表数据为空,开始插入默认值!"); } else MongoDBSingleton.Instance.Update(query, Update.Set("from", location), "SecondWeighState", UpdateFlags.None); return model; } /// /// 复称平台数据 /// public class SecondWeighState { public ObjectId _id { get; set; } public string location { get; set; } /// /// 0未知 1合格 2不合格 /// public int ng { get; set; } /// /// 复称平台货从哪里来的 /// public string from { get; set; } /// /// 批次号 /// public string batchNo { get; set; } /// /// 包装机下线重量 /// public int weight { get; set; } /// /// 1 满 0 空 /// public int full { get; set; } public string mesInfo { get; set; } } /// /// 获取复称点位位置 /// /// /// public static string GetSecondWeighBit() { //改成读settings var plc = Settings.GetPlcInfo().Where(a => a.deviceType == "2").FirstOrDefault(); return plc.location; } /// /// 将设备通道里面读取的16位short转成ascii字符串 /// /// /// private static string GetTrayCode(int[] data) { StringBuilder sb = new StringBuilder(); data.ToList().ForEach(a => { var bytes = BitConverter.GetBytes((short)a).Reverse().ToArray(); sb.Append(Encoding.ASCII.GetString(bytes)); }); return sb.ToString(); } /// /// 十进制转换为2进制(自动补全16位) /// /// /// public static string Completion(int data) { var result = Convert.ToString(data, 2).PadLeft(16, '0'); return result; } /// /// ascii转10进制(通过16进制中转) /// /// /// public static string AsciiToTen(string data) { byte[] oneSixbad = System.Text.ASCIIEncoding.Default.GetBytes(data); StringBuilder oneSixsb = new StringBuilder(); foreach (byte b in oneSixbad) { oneSixsb.Append(b.ToString("x")); } int oneSixA2 = Convert.ToInt32(oneSixsb.ToString(), 16); return oneSixA2.ToString(); } #region 叠盘机批量写入数据 #region 产品型号分离处理方法 //public static int[] DiePan(WMSInfo machine) //{ // //偏移量 +11 通道范围: 40311 ~ 40370 // CMMLog.Info($"进入DiePan数据处理方法"); // //10~19通道 // int[] num = new int[60]; // int[] num3 = new int[40]; // int a = 0;//托盘码处理 // for (int b = 0; b <= 2; b++) // { // num[b] = int.Parse(AsciiToTen(machine.trayCode.Substring(a, 2))); // a = a + 2; // } // num[3] = int.Parse(AsciiToTen(machine.location));//包装机号 // for (int b = 4; b <= 5; b++) // { // int k = b % 2 == 0 ? 0 : 16; // num[b] = Convert.ToInt32(Convert.ToString(int.Parse(machine.productWeight), 2).PadLeft(32, '0').ToString().Substring(k, 16), 2); // } // for (int b = 6; b <= 7; b++) // { // int k = b % 2 == 0 ? 0 : 16; // num[b] = Convert.ToInt32(Convert.ToString(int.Parse(machine.trayCodeWeight), 2).PadLeft(32, '0').ToString().Substring(k, 16), 2); // } // for (int b = 8; b <= 9; b++) // { // int k = b % 2 == 0 ? 0 : 16; // num[b] = Convert.ToInt32(Convert.ToString(int.Parse(machine.oneTrayWeight), 2).PadLeft(32, '0').ToString().Substring(k, 16), 2); // } // for (int b = 10; b <= 12; b++) num[b] = 0;// 叠包后实际重量 && 复称结果 默认:0 // num[13] = string.IsNullOrEmpty(machine.palletLayers) ? 0 : int.Parse(machine.palletLayers);//是否需要叠托盘 // num[14] = machine.addState;//是否需要叠包 // num[15] = int.Parse(machine.packageCode);//袋号 // //时间戳处理 // string timeStamp = ProcessHelper.GetTimeStamp(32, 1, 1); // for (int b = 16; b <= 17; b++) // { // int k = b % 2 == 0 ? 0 : 16; // num[b] = Convert.ToInt32(Convert.ToString(int.Parse(timeStamp), 2).PadLeft(32, '0').ToString().Substring(k, 16), 2); // } // for (int b = 18; b <= 19; b++) num[b] = 0;//预留的两个通道 默认:0 // //19 = 30 31 ~ 60 // //30~59通道 60~70通道 // string pcHead = ""; // string cpHead = ""; // #region 31~60 // string data = machine.itemPCode; // CMMLog.Info($"31~60data1_1:{data}"); // if (data.Length % 2 != 0) // { // data = "0" + machine.itemPCode; // pcHead = "" + machine.itemPCode.Substring(0, 1); // } // CMMLog.Info($"31~60data1_2:{data}"); // int x = data.Length / 2; // int aa = 0; // for (int i = 0; i <= x - 1; i++) // { // num3[i] = int.Parse(AsciiToTen(data.Substring(aa, 2))); // aa = aa + 2; // } // for (int m = x; m <= 29; m++) num3[m] = 0;//将产品批次号无数据的通道全部置为 0 // CMMLog.Info($"itemPCode:" + JsonConvert.SerializeObject(num3)); // #endregion // #region 61~70 // string data2 = machine.itemCode; // CMMLog.Info($"61~70data2_1:{data2}"); // if (data2.Length % 2 != 0) // { // data2 = "0" + machine.itemCode; // cpHead = "" + machine.itemCode.Substring(0, 1); // } // CMMLog.Info($"61~70data2_2:{data2}"); // int y = data2.Length / 2; // CMMLog.Info($"{y}"); // int aaa = 0; // //4 2 32 9 41 // for (int i = 30; i <= y + 29; i++) // { // num3[i] = int.Parse(AsciiToTen(data2.Substring(aaa, 2))); // CMMLog.Info(JsonConvert.SerializeObject(num3[i])); // aaa = aaa + 2; // } // int mm = y + 30; // CMMLog.Info($"mm:{mm}"); // for (int mmm = mm; mmm <= 39; mmm++) // { // num3[mmm] = 0; // CMMLog.Info(JsonConvert.SerializeObject(num3[mmm])); // } // CMMLog.Info($"itemPCode+itemCode:{JsonConvert.SerializeObject(num3)}"); // #endregion // for (int i = 20; i <= 60; i++) num[i] = num3[i - 20]; // // 如果 产品批次号 或者 产品型号 位数 为 奇数,则将提前取出的 首字符 重新转码 写入 其所对应通道区域的 首通道 // if (pcHead != "" || cpHead != "") // { // if (pcHead != "") num[20] = int.Parse(AsciiToTen(pcHead)); // if (cpHead != "") num[50] = int.Parse(AsciiToTen(cpHead)); // CMMLog.Info($"产品型号或批次号数量为奇数,特将首位取出单独处理,以下为批次号和产品型号的十进制数值{num[20]},{num[50]}"); // } // CMMLog.Info($"DiePan数据处理方法完毕"); // return num; //} #endregion public static int[] DiePan(WMSInfo machine) { //偏移量 +11 通道范围: 40311 ~ 40370 CMMLog.Info($"叠盘机数据处理."); //10~19通道 int[] num = new int[60];//总长度:60 #region 0~19 => 11~30 int a = 0;//托盘码处理 for (int b = 0; b <= 2; b++) { num[b] = int.Parse(AsciiToTen(machine.trayCode.Substring(a, 2))); a = a + 2; } num[3] = int.Parse(AsciiToTen(machine.location));//包装机号 for (int b = 4; b <= 5; b++) { int k = b % 2 == 0 ? 0 : 16; num[b] = Convert.ToInt32(Convert.ToString(int.Parse(machine.productWeight), 2).PadLeft(32, '0').ToString().Substring(k, 16), 2); } for (int b = 6; b <= 7; b++) { int k = b % 2 == 0 ? 0 : 16; num[b] = Convert.ToInt32(Convert.ToString(int.Parse(machine.trayCodeWeight), 2).PadLeft(32, '0').ToString().Substring(k, 16), 2); } for (int b = 8; b <= 9; b++) { int k = b % 2 == 0 ? 0 : 16; num[b] = Convert.ToInt32(Convert.ToString(int.Parse(machine.oneTrayWeight), 2).PadLeft(32, '0').ToString().Substring(k, 16), 2); } for (int b = 10; b <= 12; b++) num[b] = 0;// 叠包后实际重量 && 复称结果 默认:0 num[13] = string.IsNullOrEmpty(machine.palletLayers) ? 0 : int.Parse(machine.palletLayers);//是否需要叠托盘 num[14] = machine.addState;//是否需要叠包 num[15] = int.Parse(machine.packageCode);//袋号 //时间戳处理 string timeStamp = ProcessHelper.GetTimeStamp(32, 1, 1); for (int b = 16; b <= 17; b++) { int k = b % 2 == 0 ? 0 : 16; num[b] = Convert.ToInt32(Convert.ToString(int.Parse(timeStamp), 2).PadLeft(32, '0').ToString().Substring(k, 16), 2); } for (int b = 18; b <= 19; b++) num[b] = 0;//预留的两个通道 默认:0 #endregion string pcHead = ""; string cpHead = ""; #region 20~49 => 31~60 产品批次号 string data = machine.itemPCode; CMMLog.Info($"31~60data1_1:{data}"); if (data.Length % 2 != 0) { data = "0" + machine.itemPCode; pcHead = "" + machine.itemPCode.Substring(0, 1); } CMMLog.Info($"31~60data1_2:{data}"); //字符串长度 / 2 = 写入通道数量(两位一转) 列: 3L0050 写入三个通道 int maxLength = 19 + (data.Length / 2);// data.Length / 2 至少为 1 int aa = 0; for (int i = 20; i <= maxLength; i++) { num[i] = int.Parse(AsciiToTen(data.Substring(aa, 2))); aa = aa + 2; } for (int x = maxLength + 1; x <= 49; x++) num[x] = 0;//将产品批次号无数据的通道全部置为 0 #endregion #region 50~59 => 61~70 产品型号 string data2 = machine.itemCode; CMMLog.Info($"61~70data2_1:{data2}"); if (data2.Length % 2 != 0) { data2 = "0" + machine.itemCode; cpHead = "" + machine.itemCode.Substring(0, 1); } CMMLog.Info($"61~70data2_2:{data2}"); maxLength = 49 + (data2.Length / 2); int aaa = 0; for (int i = 50; i <= maxLength; i++) { num[i] = int.Parse(AsciiToTen(data2.Substring(aaa, 2))); aaa = aaa + 2; } for (int x = maxLength + 1; x <= 59; x++) num[x] = 0;//将产品型号无数据的通道全部置为0 #endregion // 如果 产品批次号 或者 产品型号 位数 为 奇数,则将提前取出的 首字符 重新转码 写入 其所对应通道区域的 首通道 if (pcHead != "") num[20] = int.Parse(AsciiToTen(pcHead)); if (cpHead != "") num[50] = int.Parse(AsciiToTen(cpHead)); if (pcHead != "" || cpHead != "") CMMLog.Info($"产品型号或批次号数量为奇数,特将首位取出单独处理,以下为批次号和产品型号的十进制数值{num[20]},{num[50]}"); CMMLog.Info($"叠盘机数据处理完毕:{JsonConvert.SerializeObject(num)}"); return num; } public static int[] DiePanTwo(MachineInfoTwo machine) { //偏移量 +11 通道范围: 40311 ~ 40370 CMMLog.Info($"叠盘机数据处理."); //10~19通道 int[] num = new int[60];//总长度:60 #region 0~19 => 11~30 // int a = 0;//托盘码处理 // for (int b = 0; b <= 2; b++) // { // num[b] = int.Parse(AsciiToTen(machine.trayCode.Substring(a, 2))); // a = a + 2; // } // num[3] = int.Parse(AsciiToTen(machine.location));//包装机号 // for (int b = 4; b <= 5; b++) // { // int k = b % 2 == 0 ? 0 : 16; // num[b] = Convert.ToInt32(Convert.ToString(int.Parse(machine.productWeight), 2).PadLeft(32, '0').ToString().Substring(k, 16), 2); // } // for (int b = 6; b <= 7; b++) // { // int k = b % 2 == 0 ? 0 : 16; // num[b] = Convert.ToInt32(Convert.ToString(int.Parse(machine.trayCodeWeight), 2).PadLeft(32, '0').ToString().Substring(k, 16), 2); // } // for (int b = 8; b <= 9; b++) // { // int k = b % 2 == 0 ? 0 : 16; // num[b] = Convert.ToInt32(Convert.ToString(int.Parse(machine.oneTrayWeight), 2).PadLeft(32, '0').ToString().Substring(k, 16), 2); // } // num[10] = 0; //托盘类型 预留 // num[11] = machine.addState;//是否需要叠包 // num[12] = int.Parse(machine.packageCode);//袋号 // //时间戳处理 // string timeStamp = ProcessHelper.GetTimeStamp(32, 1, 1); // for (int b = 16; b <= 17; b++) // { // int k = b % 2 == 0 ? 0 : 16; // num[b] = Convert.ToInt32(Convert.ToString(int.Parse(timeStamp), 2).PadLeft(32, '0').ToString().Substring(k, 16), 2); // } // for (int b = 18; b <= 19; b++) num[b] = 0;//预留的两个通道 默认:0 // // #endregion // // string pcHead = ""; // string cpHead = ""; // // #region 20~49 => 31~60 产品批次号 // // string data = machine.itemPCode; // CMMLog.Info($"31~60data1_1:{data}"); // if (data.Length % 2 != 0) // { // data = "0" + machine.itemPCode; // pcHead = "" + machine.itemPCode.Substring(0, 1); // } // CMMLog.Info($"31~60data1_2:{data}"); // //字符串长度 / 2 = 写入通道数量(两位一转) 列: 3L0050 写入三个通道 // int maxLength = 19 + (data.Length / 2);// data.Length / 2 至少为 1 // int aa = 0; // for (int i = 20; i <= maxLength; i++) // { // num[i] = int.Parse(AsciiToTen(data.Substring(aa, 2))); // aa = aa + 2; // } // for (int x = maxLength + 1; x <= 49; x++) num[x] = 0;//将产品批次号无数据的通道全部置为 0 // #endregion // // #region 50~59 => 61~70 产品型号 // // string data2 = machine.itemCode; // CMMLog.Info($"61~70data2_1:{data2}"); // if (data2.Length % 2 != 0) // { // data2 = "0" + machine.itemCode; // cpHead = "" + machine.itemCode.Substring(0, 1); // } // CMMLog.Info($"61~70data2_2:{data2}"); // maxLength = 49 + (data2.Length / 2); // int aaa = 0; // for (int i = 50; i <= maxLength; i++) // { // num[i] = int.Parse(AsciiToTen(data2.Substring(aaa, 2))); // aaa = aaa + 2; // } // for (int x = maxLength + 1; x <= 59; x++) num[x] = 0;//将产品型号无数据的通道全部置为0 #endregion // // // 如果 产品批次号 或者 产品型号 位数 为 奇数,则将提前取出的 首字符 重新转码 写入 其所对应通道区域的 首通道 // if (pcHead != "") num[20] = int.Parse(AsciiToTen(pcHead)); // if (cpHead != "") num[50] = int.Parse(AsciiToTen(cpHead)); // if (pcHead != "" || cpHead != "") CMMLog.Info($"产品型号或批次号数量为奇数,特将首位取出单独处理,以下为批次号和产品型号的十进制数值{num[20]},{num[50]}"); // // CMMLog.Info($"叠盘机数据处理完毕:{JsonConvert.SerializeObject(num)}"); return num; } internal static void PackingLineComplete(string ip) { var plc = Settings.GetPlcInfo().Where(a => a.ip == ip).FirstOrDefault(); if (plc != null) { //写入包装机--安全门关门指令 var writeRes = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = ip, addr = plc.writeAddr + 2, data = 3, port = plc.port }); CMMLog.Debug($"写入设备{plc.location}通道{plc.writeAddr + 2}里面数据为3."); } else CMMLog.Debug($"包装线空托上线,3,ip=null!"); } internal static void BZBKComplete(string PlcBitCache01, string Extend = "") { var plcInfo = Settings.GetPlcInfo().Where(a => a.location == PlcBitCache01).FirstOrDefault(); var writeRes = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = plcInfo.ip, addr = plcInfo.writeAddr + 2, data = 3, port = plcInfo.port }); CMMLog.Debug($"写入设备{plcInfo.location}通道{plcInfo.writeAddr + 2}里面数据3"); var result = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, addr = plcInfo.readAddr + 2, host = plcInfo.ip, port = plcInfo.port }); if (result != null && result.errCode == 0) { //3:安全门关闭,等待关闭到位后,清零本通道 if (result.result[0] == 3) { CMMLog.Debug($"读取设备{plcInfo.location}通道{plcInfo.readAddr + 2}里面数据3"); writeRes = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = plcInfo.ip, addr = plcInfo.writeAddr + 2, data = 0, port = plcInfo.port }); } } } internal static void writeStackingMouth6(string loca, string taskNo) { var plc = Settings.GetPlcInfo().Where(a => a.location == loca && a.enable == 1).FirstOrDefault(); CMMLog.Info($"3楼缓存架入叠托:收到信号6,查询设备信息:{JsonConvert.SerializeObject(plc)}。"); if (plc != null) { var eleInfo = MongoDBSingleton.Instance.FindOne("elevatorTask"); if(eleInfo != null) { var task = eleInfo.task_mst; CMMLog.Info($"3楼缓存架入叠托:收到信号6,查询任务信息:{JsonConvert.SerializeObject(task)}。"); var machine = eleInfo.wmsInfo; CMMLog.Info($"3楼缓存架入叠托:收到信号6,查询WMSInfo表信息:{JsonConvert.SerializeObject(machine)}。"); if (machine != null) { int[] num = DiePan(machine); CMMLog.Info($"send num:{JsonConvert.SerializeObject(num)}"); var wirteall01 = OITcpHelper.RegisterWriteOutPutMulti(new OITcpHelper.RegisterWriteOutPutModelMulti { addr = plc.writeAddr + 10, host = plc.ip, port = plc.port, data = num }); //WriteCacheStackingData(plc, task, machine); var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + 1, host = plc.ip, port = plc.port, data = 2 }); } } else { CMMLog.Info($"3楼缓存架入叠托:电梯中间表异常"); } } } private static void WriteCacheStackingData(Settings.PlcInfo plc, TN_I_TASK_MST task, WMSInfo machine) { var machineTwo = MongoDBSingleton.Instance.FindOne(Query.EQ("trayCode", task.CN_S_BATCH_NO), "MachineInfoTwo"); CMMLog.Info($"3楼缓存架入叠托:收到信号6,查询MachineInfoTwo表信息:{JsonConvert.SerializeObject(machineTwo)}。"); if (machineTwo != null) { int[] num = DiePanTwo(machine, machineTwo); CMMLog.Info($"3楼缓存架入叠托:写入数据:{JsonConvert.SerializeObject(num)},IPort:{plc.ip},{plc.port}"); var wirteall01 = OITcpHelper.RegisterWriteOutPutMulti(new OITcpHelper.RegisterWriteOutPutModelMulti { addr = plc.writeAddr + 7, host = plc.ip, port = plc.port, data = num }); CMMLog.Info($"3楼缓存架入叠托:返回数据:{JsonConvert.SerializeObject(wirteall01)},IPort:{plc.ip},{plc.port}"); if (wirteall01.errCode == 0) { MongoDBSingleton.Instance.Remove(Query.EQ("trayCode", task.CN_S_BATCH_NO), "MachineInfoTwo", RemoveFlags.Single); } } } private static int[] DiePanTwo(WMSInfo machine, MachineInfoTwo machineInfoTwo) { var ErpItemInfo = new SqlHelper().GetInstance(false).Queryable().Where(x => x.FNumber == machineInfoTwo.materialCode).First(); CMMLog.Info($"3楼缓存架入叠托:收到信号6,查询T_JY_MATERIALSync表信息:{JsonConvert.SerializeObject(ErpItemInfo)}。"); CMMLog.Info($"叠盘机数据处理。"); //偏移量 +11 通道范围: 40311 ~ 40390 //10~19通道 int[] num = new int[94];//总长度:94 var arr = JsonConvert.DeserializeObject>(machineInfoTwo.jsonData); #region 0~21 => 9~30 num[0] = 1; CMMLog.Info($"1111111111。"); for (int b = 1; b <= 2; b++) { var arrTwo = machineInfoTwo.oneTrayWeightFC.Split(',').ToList(); num[b] = int.Parse(arrTwo[b - 1]);//复称重量 //int k = b % 2 == 0 ? 0 : 16; //num[b] = Convert.ToInt32(Convert.ToString(int.Parse(machineInfoTwo.oneTrayWeightFC), 2).PadLeft(32, '0').ToString().Substring(k, 16), 2); } CMMLog.Info($"2222222。"); int a = 0;//托盘码处理 for (int b = 3; b <= 5; b++) { num[b] = int.Parse(AsciiToTen(machine.trayCode.Substring(a, 2))); a = a + 2; } CMMLog.Info($"3333333333333。"); num[6] = int.Parse(machine.location);//包装机号 CMMLog.Info($"4444444444444。"); for (int b = 7; b <= 8; b++) { num[b] = arr[b - 3];//产品需求重量 //int k = b % 2 == 0 ? 0 : 16; //num[b] = Convert.ToInt32(Convert.ToString(int.Parse(machine.productWeight), 2).PadLeft(32, '0').ToString().Substring(k, 16), 2); } CMMLog.Info($"5555555555555。"); for (int b = 9; b <= 10; b++) { num[b] = arr[b - 3];//单托毛重 //int k = b % 2 == 0 ? 0 : 16; //num[b] = Convert.ToInt32(Convert.ToString(int.Parse(machineInfoTwo.trayCodeWeight), 2).PadLeft(32, '0').ToString().Substring(k, 16), 2); } CMMLog.Info($"66666666。"); for (int b = 11; b <= 12; b++) { num[b] = arr[b - 3];//单托净重 //int k = b % 2 == 0 ? 0 : 16; //num[b] = Convert.ToInt32(Convert.ToString(int.Parse(machineInfoTwo.oneTrayWeight), 2).PadLeft(32, '0').ToString().Substring(k, 16), 2); } CMMLog.Info($"77777777。"); num[13] = 0; //物料打包类型 CMMLog.Info($"88888888。"); num[14] = machine.addState; //是否需要叠包 CMMLog.Info($"9999999999999。"); num[15] = int.Parse(machine.packageCode);//袋号 for (int b = 16; b <= 20; b++) { num[b] = arr[b - 3];//员工编号 } for (int b = 21; b <= 22; b++) { num[b] = arr[b - 3];//生产日期 } #endregion string pcHead = ""; string pcTail = ""; string cpHead = ""; string mtHead = "";// 设备的真实物料编码 #region 23~42 => 31~50 产品批次号 string data = machineInfoTwo.lotNo; CMMLog.Info($"31~50data1_1:{data}"); if (data.Length % 2 != 0) { //data = "0" + machineInfoTwo.lotNo; //pcHead = "" + machineInfoTwo.lotNo.Substring(0, 1); pcTail = machineInfoTwo.lotNo.Substring(data.Length - 1, 1) + ""; CMMLog.Info($"pcTail:{pcTail}"); data = machineInfoTwo.lotNo + " "; } CMMLog.Info($"31~50data1_2:{data}"); //字符串长度 / 2 = 写入通道数量(两位一转) 列: 3L0050 写入三个通道 int maxLength = 22 + (data.Length / 2);// data.Length / 2 至少为 1 int maxLength2 = maxLength; int aa = 0; for (int i = 23; i <= maxLength; i++) { num[i] = int.Parse(AsciiToTen(data.Substring(aa, 2))); aa = aa + 2; } for (int x = maxLength + 1; x <= 42; x++) num[x] = 0;//将产品批次号无数据的通道全部置为 0 #endregion #region 43~52 => 51~60 产品型号 ERPService.HandleItemInfoChina(ErpItemInfo.FSpecification, 43, 52, num);// 中文处理 43~52 51~60 //string data2 = machine.itemCode; //CMMLog.Info($"51~50data2_1:{data2}"); //if (data2.Length % 2 != 0) //{ // data2 = "0" + machine.itemCode; // cpHead = "" + machine.itemCode.Substring(0, 1); //} //CMMLog.Info($"51~60data2_2:{data2}"); //maxLength = 39 + (data2.Length / 2); //int aaa = 0; //for (int i = 40; i <= maxLength; i++) //{ // num[i] = int.Parse(AsciiToTen(data2.Substring(aaa, 2))); // aaa = aaa + 2; //} //for (int x = maxLength + 1; x <= 49; x++) num[x] = 0;//将产品型号无数据的通道全部置为0 #endregion #region 53~67 => 61~75 物料编码 string data3 = machineInfoTwo.materialCode; CMMLog.Info($"61~75data3_1:{data3}"); if (data3.Length % 2 != 0) { data3 = "0" + machineInfoTwo.materialCode; mtHead = "" + machineInfoTwo.materialCode.Substring(0, 1); } CMMLog.Info($"61~75data3_2:{data3}"); maxLength = 52 + (data3.Length / 2); int aaaa = 0; for (int i = 53; i <= maxLength; i++) { num[i] = int.Parse(AsciiToTen(data3.Substring(aaaa, 2))); aaaa = aaaa + 2; } for (int x = maxLength + 1; x <= 67; x++) num[x] = 0;//将产品型号无数据的通道全部置为0 #endregion ERPService.HandleItemInfoChina(ErpItemInfo.FName, 68, 87, num);// 中文处理 68~87 76~95 ERPService.HandleItemInfo(ErpItemInfo.FStoreUnit, 88, 92, num);// 88~92 96~100 CMMLog.Info($"{num.Length}"); num[93] = int.Parse(machineInfoTwo.organizeCode); //组织编码 // 如果 产品批次号 或者 产品型号 位数 为 奇数,则将提前取出的 首字符 重新转码 写入 其所对应通道区域的 首通道 //if (pcHead != "") num[23] = int.Parse(AsciiToTen(pcHead)); if (pcTail != "") num[maxLength2] = tailToTen(pcTail); if (cpHead != "") num[43] = int.Parse(AsciiToTen(cpHead)); if (mtHead != "") num[53] = int.Parse(AsciiToTen(mtHead)); if (pcHead != "" || cpHead != "") CMMLog.Info($"产品型号或批次号数量为奇数,特将首位取出单独处理,以下为批次号和产品型号的十进制数值{num[23]},{num[53]}"); CMMLog.Info($"叠盘机数据处理完毕:{JsonConvert.SerializeObject(num)}"); return num; } private static int tailToTen(string Tail) { char inputChar = Tail[0]; // 获取字符串的第一个字符 int asciiValue = (int)inputChar; // 转换为ASCII码 string hexValue = asciiValue.ToString("X2"); // 转换为16进制 string binaryValue = Convert.ToString(asciiValue, 2).PadLeft(8, '0'); // 转换为8位二进制 string finalBinaryValue = binaryValue + "00000000"; // 补8个二进制0 int finalDecimalValue = Convert.ToInt32(finalBinaryValue, 2); // 转换为10进制 return finalDecimalValue; } internal static bool writeStackingMouth5(string loc) { bool result = false; var plc = Settings.GetPlcInfo().Where(a => a.location == loc).FirstOrDefault(); if (plc != null) { var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + 2, data = 1, host = plc.ip, port = plc.port }); if (wirte.errCode == 0) result = true; } else CMMLog.Debug($"缓存入叠盘机,5,plc=null!"); return result; } internal static void changeSignal() { CMMLog.Info("荆门变更任务处理"); #region 计算设备合格率 //ip地址:10.50.65.30 端口:502 //查询中间表ProductList 字段overallPassRate往通道40073写入复称平台合格率 通过machine查询每个设备的合格率写入40074 - 字段 try { //CMMLog.Info("计算设备合格率处理开始"); //var proInfo = MongoDBSingleton.Instance.Find(Query.EQ("Date", DateTime.Now.ToString("yyyy-MM-dd")), "ProductList"); //if (proInfo.Count > 0) //{ // CMMLog.Info($"{proInfo.Count}"); // var sum = proInfo.Count; // int[] num = new int[15]; // proInfo.ForEach(a => // { // CMMLog.Info("11111111111111111"); // CMMLog.Info(JsonConvert.SerializeObject(a)); // if (string.IsNullOrEmpty(a.machine)) // { // num[0] = (int)a.overallPassRate; // } // else // { // CMMLog.Info("----------------------"); // string devInfo = Settings.GetPlcInfo().Where(it => it.location == a.machine).FirstOrDefault().device; // if (devInfo != null) // { // int m = int.Parse(devInfo); // CMMLog.Info($"{m}"); // num[m] = (int)a.percentOfPass; // } // CMMLog.Info("222222222222222222"); // } // }); // // CMMLog.Info($"bgip:{Settings.BGip}"); // var writeRes0 = OITcpHelper.RegisterWriteOutPutMulti(new OITcpHelper.RegisterWriteOutPutModelMulti // { // host = Settings.BGip, // addr = 72, // data = num,//原先是1,单个写入 // port = int.Parse(Settings.BGPort) // }); //} } catch(Exception ex) { CMMLog.Info($"计算合格率处理-异常:{ex.Message}!"); } #endregion #region 写入流转空托数量 //var emptyInfo = MongoDBSingleton.Instance.FindAll(); //if(emptyInfo.Count > 0) //{ // // int x = 0; // foreach(var a in emptyInfo) // { // var address = x == 0 ? 70 : 71; // var write = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel // { // host = Settings.BGip, // addr = address, // dataNum = a.Quantity, // port = int.Parse(Settings.BGPort) // }); // if (write.errCode == 0) x = x + 1; // } //} #endregion #region 写入小车状态 CMMLog.Info("车辆状态处理:执行开始!"); try { //查询小车状态表,写入小车坐标和方向 并写入中间表 var agvState = MongoDBSingleton.Instance.FindAll(); if (agvState.Count > 0) { CMMLog.Info($"{agvState.Count}"); agvState.ForEach(a => { var stateInfo = Settings.GetAGVStateList().Where(it => it.AgvNo == a.forkliftNo).FirstOrDefault(); if (stateInfo != null) { CMMLog.Info(JsonConvert.SerializeObject(stateInfo)); int[] num = new int[6];//总长度:6 int divisor = 65536; // 除数 int xPos = int.Parse(a.xPos); int yPos = int.Parse(a.yPos); int xquotient = xPos / divisor; // 计算商数 int xremainder = xPos % divisor; // 计算余数 num[0] = xquotient; num[1] = xremainder; int yquotient = yPos / divisor; // 计算商数 int yremainder = yPos % divisor; // 计算余数 num[2] = yquotient; num[3] = yremainder; num[4] = string.IsNullOrEmpty(a.Degree) ? 0 : int.Parse(a.Degree); //num[4] = int.Parse(a.Degree); num[5] = a.errCode != "0" || a.errCode2 != "0" || a.faildCode != "0" ? 2 : 0; //if (a.errCode != "0" || a.errCode2 != "0" || a.faildCode != "0") num[5] = 2; CMMLog.Info($"车辆状态处理:写入车辆数据:车号:{a.forkliftNo},ip:{stateInfo.ip},port:{stateInfo.port},data:{JsonConvert.SerializeObject(num)}"); var wirteal = OITcpHelper.RegisterWriteOutPutMulti(new OITcpHelper.RegisterWriteOutPutModelMulti { addr = stateInfo.writeAddr, host = stateInfo.ip, port = stateInfo.port, data = num }); } else CMMLog.Info($"车辆状态处理:小车{a.forkliftNo}未配置"); }); } else CMMLog.Info("车辆状态处理:AGV_STATE 车辆状态表未获取到车辆状态数据!"); } catch (Exception ex) { CMMLog.Info($"车辆状态处理-异常:{ex.Message}!"); } #endregion Thread.Sleep(1000); } internal static void outWare(string taskNo,bool flage) { var plc = Settings.GetPlcInfo().Where(a => a.Extend == "2" && a.enable == 1).FirstOrDefault(); if(plc != null) { if (flage) { //电动门开门步骤: //1、在通道【40101】中写入1,发送开门信号 //2、读取通道【40001】中的值,如果为2,表示开门到位,通知小车进去 var writeRes = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = plc.ip, port = plc.port, addr = plc.writeAddr, data = 1 }); CMMLog.Info($"发送开门信号,在通道{plc.writeAddr}中写入1,ip:{plc.ip},端口:{plc.port}"); var result = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 2, addr = plc.readAddr, host = plc.ip, port = plc.port }); if (result != null && result.errCode == 0) { CMMLog.Info($"电动门开门流程:读取电动门通道号为:{plc.readAddr}里面的值为{result.result[0]},{plc.readAddr + 1}里面的值为{result.result[1]}"); //Console.WriteLine($"电动门开门流程:读取电动门通道号为:{plc.readAddr}里面的值为{result.result[0]},{plc.readAddr + 1}里面的值为{result.result[1]}"); if (result.result[0] == 1 && result.result[1] == 1) { //推送小车进去 CMMLog.Info($"电动门已经打开,门号:2"); TSHelper.GoToAGV(taskNo, 10, 3); } } else CMMLog.Info($"电动门开门流程:未读取到包装机通道{plc.readAddr}里面的数据!!!result:{JsonConvert.SerializeObject(result)}"); } else { //电动门关门步骤 //1、小车通过电动门后,在通道【40101】中写入2 var writeRes = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = plc.ip, port = plc.port, addr = plc.writeAddr, data = 2 }); CMMLog.Info($"电动门关门流程,在通道{plc.writeAddr}中写入2,ip:{plc.ip},端口:{plc.port}"); } } else CMMLog.Info($"门号为【2】的门未在配置文件配置或者未启用"); } /// /// 缓存架入入料口 /// /// /// internal static void InInlet(Settings.PlcInfo plc) { var locInfo = MongoDBSingleton.Instance.FindOne(Query.And(Query.EQ("S_LOC_STATE", "无"), Query.EQ("N_CURRENT_NUM", 0)), "location"); if(locInfo != null) { //判断上料是否有任务 if (CheckEndFree(plc.location)) { var num = plc.device == "26" ? 1 : 2; var result1 = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, addr = plc.readAddr + 1, host = plc.ip, port = plc.port }); if (result1 != null && result1.errCode == 0) { if (result1.result[0] == num) { //上料平台为空,可生成任务 var amsResult = AMSHelper.CreateTask(DateTime.Now.Ticks.ToString(), locInfo.S_LOC_CODE, plc.location, "3楼成品出库", 0, locInfo.S_TRAY_CODE); if (amsResult.success) { CMMLog.Debug($"缓存架出库流程:AMS调用API成功!"); } else CMMLog.Debug($"缓存架出库流程:AMS调用API失败,开始重新调用!"); } } } } } internal static void machine() { //MongoDBSingleton.Instance.Remove(Query.EQ("weight2", ""), RemoveFlags.Single); //获取当天的所有合格率 var proInfoList = MongoDBSingleton.Instance.Find(Query.EQ("Date", DateTime.Now.ToString("yyyy-MM-dd")), "ProductList").ToList(); if (proInfoList.Count > 0) { double sum = 0; int flage = 0; proInfoList.ForEach(a => { if (!string.IsNullOrEmpty(a.machine)) { sum = sum + a.percentOfPass; } else flage = 1; }); sum = flage == 0 ? Math.Round((sum / proInfoList.Count), 2) : Math.Round((sum / (proInfoList.Count - 1)), 2); //计算当天的总合格率 var HGL = MongoDBSingleton.Instance.FindOne(Query.And(Query.EQ("Date", DateTime.Now.ToString("yyyy-MM-dd")), Query.EQ("machine", "")), "ProductList"); if (HGL != null) { HGL.overallPassRate = sum; MongoDBSingleton.Instance.Update(Query.And(Query.EQ("Date", DateTime.Now.ToString("yyyy-MM-dd")), Query.EQ("machine", "")), Update.Set("overallPassRate", HGL.overallPassRate), UpdateFlags.None); } else { ProductList machine = new ProductList { Date = DateTime.Now.ToString("yyyy-MM-dd"), machine = "", total = 0, qualifiedQuantity = 0, percentOfPass = 0, overallPassRate = sum }; MongoDBSingleton.Instance.Insert(machine); } } } internal static void deleteTableTask() { var request = MongoDBSingleton.Instance.FindAll(); if (request.Count > 0) { request.ForEach(a => { DateTime CreateTime = Convert.ToDateTime(a.time); CMMLog.Info($"deleteTableTask CreateTime:{CreateTime}"); //if (DateTime.Now.Subtract(CreateTime).TotalHours > 48) if (DateTime.Now.Subtract(CreateTime).TotalDays > 7) { MongoDBSingleton.Instance.Remove(Query.EQ("_id", a._id), "packageInfoModel", RemoveFlags.None); } }); } var requestTwo = MongoDBSingleton.Instance.FindAll(); if (requestTwo.Count > 0) { requestTwo.ForEach(a => { DateTime CreateTime = Convert.ToDateTime(a.Date + " 00:00:00"); CMMLog.Info($"deleteTableTask CreateTime:{CreateTime}"); if (DateTime.Now.Subtract(CreateTime).TotalDays > 7) { MongoDBSingleton.Instance.Remove(Query.EQ("_id", a._id), "ProductList", RemoveFlags.None); } }); } } internal static void productOutWare(string endBit, string taskNo, bool action) { var plc = Settings.GetPlcInfo().Where(a => a.location == endBit).FirstOrDefault(); if (plc != null) { if (action) { var writeRes = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = plc.ip, addr = plc.writeAddr, data = 1, port = plc.port }); CMMLog.Debug($"写入设备{plc.location}通道{plc.writeAddr}里面数据为1."); var result = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 2, addr = plc.readAddr, host = plc.ip, port = plc.port }); CMMLog.Debug($"查询设备{plc.location}通道{plc.readAddr}里面数据为{result.result[0]}、{result.result[1]}."); if (result != null && result.errCode == 0) { if (result.result[0] == 1 && result.result[1] == 1) { //推送小车进入 TSHelper.GoToAGV(taskNo, 10, 3); } } } else { var writeRes = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { host = plc.ip, addr = plc.writeAddr, data = 2, port = plc.port }); CMMLog.Debug($"写入设备{plc.location}通道{plc.writeAddr}里面数据为2."); } } } /// /// 将中间表 InAndOutQuantity 的值写入通道 /// /// internal static void writeQtt() { //40075 148 UDint 出库数量(总) 出库总数量(按年计算) //40077 152 UDint 入库数量(总) 入库总数量(按年计算) //40081 160 Uint 本月出库数量总计 //40082 162 Uint 本月入库数量总计 //40083 164 Uint 本周出库数量总计 //40084 166 Uint 本周入库数量总计 int outTotal = 0; //出库数量总和 int inTotal = 0; //入库数量总和 int outMonthTotal = 0; //本月出库数量总和 int intMonthTotal = 0; //本月入库数量总和 int outWeekTotal = 0; //本周出库数量总和 int inWeekTotal = 0; //本周入库数量总和 string week = GetWeekOfMonth(DateTime.Now).ToString(); //当前为本月的第几周 //出库总数 var outList = MongoDBSingleton.Instance.Find(Query.And(Query.EQ("Type", "出库"), Query.EQ("Year", DateTime.Now.ToString("yyyy"))), "InAndOutQuantity"); if(outList.Count > 0) { foreach(var a in outList) { outTotal = outTotal + a.Quntity; } } //入库总数 var inList = MongoDBSingleton.Instance.Find(Query.And(Query.EQ("Type", "入库"), Query.EQ("Year", DateTime.Now.ToString("yyyy"))), "InAndOutQuantity"); if (inList.Count > 0) { foreach (var a in inList) { inTotal = inTotal + a.Quntity; } } //月出库总数 var outMonthList = MongoDBSingleton.Instance.Find(Query.And(Query.EQ("Type", "出库"), Query.EQ("Year", DateTime.Now.ToString("yyyy")),Query.EQ("Month",DateTime.Now.ToString("MM"))), "InAndOutQuantity"); if (outMonthList.Count > 0) { foreach (var a in outMonthList) { outMonthTotal = outMonthTotal + a.Quntity; } } //月入库总数 var inMonthList = MongoDBSingleton.Instance.Find(Query.And(Query.EQ("Type", "入库"), Query.EQ("Year", DateTime.Now.ToString("yyyy")), Query.EQ("Month", DateTime.Now.ToString("MM"))), "InAndOutQuantity"); if (inMonthList.Count > 0) { foreach (var a in inMonthList) { intMonthTotal = intMonthTotal + a.Quntity; } } //周总数算法 获取当前是星期几 然后当天的日期减去星期数加一 获取本周一的日期 然后计算本周一到今天的数量 int xq = (int)DateTime.Now.DayOfWeek; int startDay = int.Parse(DateTime.Now.ToString("dd")) - xq + 1; //周出库总数 var outWeekList = MongoDBSingleton.Instance.Find(Query.And(Query.EQ("Type", "出库"),Query.GTE("Day", startDay), Query.LTE("Day", DateTime.Now.ToString("dd"))), "InAndOutQuantity"); //var outWeekList = MongoDBSingleton.Instance.Find(Query.And(Query.EQ("Type", "入库"), Query.EQ("Year", DateTime.Now.ToString("yyyy")), Query.EQ("Month", DateTime.Now.ToString("MM"))), "InAndOutQuantity"); if (outWeekList.Count > 0) { foreach (var a in outWeekList) { outWeekTotal = outWeekTotal + a.Quntity; } } //周入库总数 var inWeekList = MongoDBSingleton.Instance.Find(Query.And(Query.EQ("Type", "入库"), Query.GTE("Day", startDay), Query.LTE("Day", DateTime.Now.ToString("dd"))), "InAndOutQuantity"); if (inWeekList.Count > 0) { foreach (var a in inWeekList) { inWeekTotal = inWeekTotal + a.Quntity; } } int[] num = new int[4]; num[0] = outMonthTotal; num[1] = intMonthTotal; num[2] = outWeekTotal; num[3] = inWeekTotal; var wirte = OITcpHelper.RegisterWriteOutPutMulti(new OITcpHelper.RegisterWriteOutPutModelMulti { addr = 80, host = "10.15.73.26", port = 5006, data = num }); int[] num1 = new int[4]; int hightOutTotal = outTotal / 65536; // 计算商数 int lowOutTotal = outTotal % 65536; // 计算余数 int hightInTotal = inTotal / 65536; // 计算商数 int lowInTotal = inTotal % 65536; // 计算余数 num1[0] = hightOutTotal; num1[1] = lowOutTotal; num1[2] = hightInTotal; num1[3] = lowInTotal; var wirte1 = OITcpHelper.RegisterWriteOutPutMulti(new OITcpHelper.RegisterWriteOutPutModelMulti { addr = 74, host = "10.15.73.26", port = 5006, data = num1 }); } /// /// 提升机起点安全交互 /// /// /// /// internal static void ElevatorStart(string ip, string taskNo, string taskType,int port) { var plc = Settings.GetPlcInfo().Where(a => a.ip == ip && a.port == port).FirstOrDefault(); if (plc != null) { if (plc.deviceType == "3") { //起点是叠盘机就是ng任务 TSHelper.GoToAGV(taskNo, 10, 1); } else { //判断当前任务的起点是在几楼 var eleInfo = MongoDBSingleton.Instance.FindOne("elevatorTask"); if (eleInfo != null) { int num = eleInfo.S_END_FLOOR == 1 ? 0 : 1; var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + num, host = plc.ip, port = plc.port, data = 1 }); CMMLog.Info($"【电梯开门】写入通道{plc.writeAddr + num}的信号为[1]"); var readRes = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, host = plc.ip, port = plc.port, addr = plc.readAddr + num }); CMMLog.Info($"【电梯开门】读取通道{plc.readAddr + num}的信号为[{JsonConvert.SerializeObject(readRes)}]"); if (readRes != null && readRes.errCode == 0) { if (readRes.result[0] == 2) { TSHelper.GoToAGV(taskNo, 10, 1); var wirte1 = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + num, host = plc.ip, port = plc.port, data = 2 }); CMMLog.Info($"【电梯开门】写入通道{plc.readAddr + num}的信号为[2]"); } } } } } } internal static void EcheckWeighingPlatform1313(string deviceType, TN_I_TASK_MST mst) { CMMLog.Info($"【复秤改道】任务流程处理开始------------"); string taskName = mst.CN_S_BUSS_TYPE = getTaskType("3楼复称入缓存架", true); string taskNameNG = mst.CN_S_BUSS_TYPE = getTaskType("3楼复称入缓存架NG", true); var taskInfo = MongoDBSingleton.Instance.FindOne(Query.And(Query.EQ("CN_S_START_BIT", mst.CN_S_END_BIT), Query.Or(Query.EQ("CN_S_BUSS_TYPE", taskName), Query.EQ("CN_S_BUSS_TYPE", taskNameNG))) , "TN_I_TASK_MST"); if(taskInfo != null) { CMMLog.Info($"起点:{mst.CN_S_END_BIT}"); CMMLog.Info($"终点:{taskInfo.CN_S_END_BIT}"); int[] parms = { StockInstance.Instance.GetAGVCodeForBitCode(mst.CN_S_END_BIT), StockInstance.Instance.GetAGVCodeForBitCode(taskInfo.CN_S_END_BIT) }; //TSHelper.ChangeParam(taskNo, 1, StockInstance.Instance.GetAGVCodeForBitCode(taskInfo.CN_S_END_BIT)); //TSHelper.ChangeParam(taskNo, 2, StockInstance.Instance.GetAGVCodeForBitCode(ChangeBit)); TSHelper.ChangeParam(mst.CN_S_TASK_NO, 1, parms); //TSHelper.GoToAGV(mst.CN_S_TASK_NO, 3, 1); TSHelper.GoToAGV(mst.CN_S_TASK_NO, 10, 8); MongoDBSingleton.Instance.Update(Query.EQ("CN_S_TASK_NO", mst.CN_S_TASK_NO), Update.Set("CN_S_END_BIT", taskInfo.CN_S_END_BIT).Set("CN_S_START_BIT", mst.CN_S_END_BIT), "TN_I_TASK_MST", UpdateFlags.None); } else { CMMLog.Info($"【复秤改道】未查询到复秤入缓存架任务"); } CMMLog.Info($"【复秤改道】任务流程处理结束------------"); } internal static void SecondWeightInCache6(string ip, string cN_S_TASK_NO) { var plc = Settings.GetPlcInfo().Where(a => a.deviceType == ip).FirstOrDefault(); if (plc != null) { //判断当前任务的起点是在几楼 var eleInfo = MongoDBSingleton.Instance.FindOne(Query.EQ("S_USE", "0"),"elevatorTask"); if (eleInfo != null) { int num = eleInfo.S_END_FLOOR == 1 ? 1 : 0; var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + num, host = plc.ip, port = plc.port, data = 3 }); CMMLog.Info($"【电梯开门】写入通道{plc.writeAddr + 1}的信号为[3]"); } } else CMMLog.Debug($"缓存入叠盘机,6,plc=null!"); //var plc = Settings.GetPlcInfo().Where(a => a.deviceType == ip).FirstOrDefault(); //if (plc != null) //{ // var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel // { // addr = plc.writeAddr + 1, // host = plc.ip, // port = plc.port, // data = 3 // }); // CMMLog.Info($"【电梯开门】写入通道{plc.writeAddr + 1}的信号为[3]"); //} //else CMMLog.Debug($"缓存入叠盘机,6,plc=null!"); } internal static void ElevatorEnd(string ip, string cN_S_TASK_NO, string cN_S_BUSS_TYPE) { CMMLog.Info("ElevatorEnd 111111111"); var plc = Settings.GetPlcInfo().Where(a => a.ip == ip).FirstOrDefault(); if (plc != null) { CMMLog.Info("ElevatorEnd 2222222"); //判断当前任务的起点是在几楼 var eleInfo = MongoDBSingleton.Instance.FindOne(Query.EQ("S_USE", "1"),"elevatorTask"); if (eleInfo != null) { CMMLog.Info("ElevatorEnd 3333333"); int num = eleInfo.S_END_FLOOR == 1 ? 0 : 1; CMMLog.Info($"ElevatorEnd 44444444:{num}"); var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + num, host = plc.ip, port = plc.port, data = 3 }); CMMLog.Info($"【电梯开门】写入通道{plc.writeAddr + num}的信号为[3]"); } } } internal static void CacheStackingMouth1013Two(string ip, string taskNo) { var plc = Settings.GetPlcInfo().Where(a => a.deviceType == ip).FirstOrDefault(); if (plc != null) { var readres = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, addr = plc.readAddr + 1, host = plc.ip, port = plc.port }); if (readres.result[0] == 0 || readres.result[0] == 1) { var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + 1, host = plc.ip, port = plc.port, data = 1 }); } else if (readres.result[0] == 2) { TSHelper.GoToAGV(taskNo, 10, 3); } } else CMMLog.Debug($"缓存入叠盘机,1013,plc=null!"); } internal static void CacheStackingMouth6Two(string loca) { var plc = Settings.GetPlcInfo().Where(a => a.location == loca && a.enable == 1).FirstOrDefault(); CMMLog.Info($"3楼缓存架入叠托:收到信号6,查询设备信息:{JsonConvert.SerializeObject(plc)}。"); if (plc != null) { var eleInfo = MongoDBSingleton.Instance.FindOne("elevatorTask"); if (eleInfo != null) { var task = eleInfo.task_mst; CMMLog.Info($"3楼缓存架入叠托:收到信号6,查询任务信息:{JsonConvert.SerializeObject(task)}。"); var machine = eleInfo.wmsInfo; CMMLog.Info($"3楼缓存架入叠托:收到信号6,查询WMSInfo表信息:{JsonConvert.SerializeObject(machine)}。"); if (machine != null) { WriteCacheStackingData(plc, task, machine); var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + 1, host = plc.ip, port = plc.port, data = 2 }); } } else { CMMLog.Info($"3楼缓存架入叠托:电梯中间表异常"); } } } internal static void machineEmpty1013(string deviceType, string taskNo,bool action) { var plc = Settings.GetPlcInfo().Where(a => a.deviceType == deviceType && a.enable == 1).First(); if(plc != null) { //判断当前任务的起点是在几楼 var eleInfo = MongoDBSingleton.Instance.FindOne("elevatorTask"); if (eleInfo != null) { int num = eleInfo.S_END_FLOOR == 2 ? 0 : 1; if (action) { var wirte = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + num, host = plc.ip, port = plc.port, data = 1 }); CMMLog.Info($"【电梯开门】写入通道{plc.writeAddr + num}的信号为[1]"); var readRes = OITcpHelper.RegisterReadOutPut(new OITcpHelper.RegisterReadOutPutModel { dataNum = 1, host = plc.ip, port = plc.port, addr = plc.readAddr + num }); CMMLog.Info($"【电梯开门】读取通道{plc.readAddr + num}的信号为[{JsonConvert.SerializeObject(readRes)}]"); if (readRes != null && readRes.errCode == 0) { if (readRes.result[0] == 2) { TSHelper.GoToAGV(taskNo, 10, 3); var wirte1 = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + num, host = plc.ip, port = plc.port, data = 2 }); CMMLog.Info($"【电梯开门】写入通道{plc.readAddr + num}的信号为[2]"); } } } else { var wirte1 = OITcpHelper.RegisterWriteOutPut(new OITcpHelper.RegisterWriteOutPutModel { addr = plc.writeAddr + num, host = plc.ip, port = plc.port, data = 3 }); CMMLog.Info($"【电梯开门】写入通道{plc.readAddr + num}的信号为[3]"); } } } } #endregion #endregion public class Z_ChaiPanEmptyOrFull { public ObjectId _id { get; set; } /// /// 拆盘点位 /// public string ChaiPanBit { get; set; } /// /// 拆盘点位空满状态--空|满 /// public string ChaiPanState { get; set; } } public class ActionControlModel { public ObjectId _id { get; set; } /// /// 功能码-- 1-生成复称平台入缓存架任务 /// public string actionNo { get; set; } = "0"; /// /// 1-ip /// public string ext1 { get; set; } = ""; /// /// 1-CN_S_BATCH_NO /// public string ext2 { get; set; } = ""; public int ext3 { get; set; } = 0; public string machince { get; set; } = ""; } public class packageInfoModel { public ObjectId _id { get; set; } /// /// 包装机号 /// public string machineNo { get; set; } = ""; /// /// 托盘号 /// public string trayCode { get; set; } = ""; /// /// 批次号 /// public string batchNo { get; set; } = ""; /// /// 下料时间 /// public string time { get; set; } = ""; /// /// 重量 /// public string weight { get; set; } = ""; /// /// 复称重量 /// public string weight2 { get; set; } = ""; /// /// 重量差值 /// public string weightDifference { get; set; } = ""; } } }