using HH.WCS.JunzhouNongfu.device; using HH.WCS.Mobox3.HD.api; using HH.WCS.Mobox3.HD.device; using HH.WCS.Mobox3.HD.dispatch; using HH.WCS.Mobox3.HD.models; using HH.WCS.Mobox3.HD.util; using HH.WCS.Mobox3.HD.wms; using Newtonsoft.Json; using NLog; using S7.Net; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using static HH.WCS.Mobox3.HD.api.DigitHelper; using static HH.WCS.Mobox3.HD.core.Monitor; using static HH.WCS.Mobox3.HD.dispatch.ShopFloorControl; using static HH.WCS.Mobox3.HD.process.TaskProcess; using static HH.WCS.Mobox3.HD.util.Settings; using static HH.WCS.Mobox3.HD.wms.WCSHelper; using static System.Runtime.CompilerServices.RuntimeHelpers; namespace HH.WCS.Mobox3.HD.core { /// /// 定时轮询任务 /// internal class Monitor { // 每十分钟对未连接的pic,尝试进行重新连接 public static void PlcAgainLink() { foreach (var item in S7Helper.plcDic) { S7Helper.Link(item.Value); } } /// /// 监听分拣区设备和货位,自动发布空盘垛出库任务 /// public static void MonitorSortArea() { List linePlcInfos = WCSHelper.GetLinePlcInfoList(2); foreach (var line in linePlcInfos) { var wmsTask = WMSHelper.GetWmsTaskByEnd(line.localtion); if (wmsTask == null) { // 线体货位 Location location = LocationHelper.GetLoc(line.localtion); // 线体信号 PipelineSignalInfo lineSignalInfo = WCSHelper.readPipelineInfo(line); LogHelper.Info("分拣区设备编号:"+ line.deviceNo +"线体编号:" + line.code+",设备信号:" + JsonConvert.SerializeObject(lineSignalInfo), "分拣区"); try { if (lineSignalInfo != null) { if (lineSignalInfo.agvTaskFeedback == 1 || lineSignalInfo.agvTaskFeedback == 2) { // 清除AGV任务反馈 S7Helper.WriteInt(line.deviceNo, 101, line.writeAddr + 14, 0); LogHelper.Info("清除AGV任务反馈", "分拣区"); } if (line.actType.Equals("入库")) { if (lineSignalInfo.lineState == 0 && lineSignalInfo.linePhotoelectric == 0 && lineSignalInfo.agvInfo == 1) { Location endLoc = location; if (endLoc != null && endLoc.N_LOCK_STATE == 0) { Location startLoc = WMSHelper.GetEmptyTrayStartLocation(endLoc.S_CODE); if (startLoc != null) { var locCntrRels = LocationHelper.GetLocCntr(startLoc.S_CODE); if (locCntrRels.Count == 1) { var cntrItemRels = ContainerHelper.GetCntrItemRel(locCntrRels[0].S_CNTR_CODE); if (cntrItemRels == null || cntrItemRels.Count == 0) { // 外侧接驳位 LogHelper.Info($"分拣区设备编号:{line.deviceNo} ,线体编号:{line.code}", "Mobox"); var connectLocCode = LocationHelper.GetConnectLocation(startLoc.S_AREA_CODE, 2, startLoc.N_ROADWAY, 1).FirstOrDefault(); // 查询接驳位 var connectLoc = LocationHelper.GetLoc(connectLocCode); if (connectLoc != null) { // 内测接驳位 /* string conLocCode = WCSHelper.GetLinePlcInfoByDesc(connectLoc.S_CODE).localtion; connectLoc = LocationHelper.GetLoc(conLocCode);*/ wmsTask = new WMSTask() { S_CNTR_CODE = locCntrRels[0].S_CNTR_CODE, S_CODE = WMSHelper.GenerateTaskNo(), S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_TYPE = "空盘垛出库", S_OP_DEF_NAME = "空盘垛出库", T_START_TIME = DateTime.Now, N_PRIORITY = 8, }; if (WMSHelper.CreateWmsTask(wmsTask)) { string eqNo = ApiHelper.getEqNo(startLoc.S_AREA_CODE, startLoc.N_ROADWAY); WCSTask wcsTask = new WCSTask { S_OP_NAME = wmsTask.S_OP_DEF_NAME, S_CODE = WCSHelper.GenerateTaskNo(), S_TYPE = wmsTask.S_TYPE + "-1", S_START_LOC = wmsTask.S_START_LOC, S_START_AREA = wmsTask.S_START_AREA, S_END_LOC = connectLoc.S_CODE, S_END_AREA = connectLoc.S_AREA_CODE, S_CNTR_CODE = wmsTask.S_CNTR_CODE, S_SCHEDULE_TYPE = "RB", S_OP_CODE = wmsTask.S_CODE, S_EQ_NO = eqNo, N_PRIORITY = wmsTask.N_PRIORITY, }; if (WCSHelper.CreateTask(wcsTask)) { // 对开始货位、接驳货位、终点货位进行加锁 LocationHelper.LockLoc(startLoc.S_CODE, 2); LocationHelper.LockLoc(connectLoc.S_CODE, 1); // 更新作业任务状态 wmsTask.N_B_STATE = 1; WMSHelper.UpdateTaskState(wmsTask); } } } else { LogHelper.Info("没有可出库的接驳位", "分拣区"); } } } } else { LogHelper.Info("没有可出库的空盘垛", "分拣区"); } } } } } } catch (Exception ex) { LogHelper.Info("监听分拣区错误,错误原因:" + ex.Message, "分拣区"); } } } } public static Dictionary logisticsTaskIdDict= new Dictionary(); public class NotificationInfo { public string logisticsTaskId { get; set; } public string locCode { get; set; } } /// /// 定时通知车间下发灵动任务(之前通知失败的任务) /// 每10秒通知一次,如5分钟内没有通知成功,则不再通知 /// public static void TimerNotification() { foreach (var item in logisticsTaskIdDict) { var notificationResult = ShopFloorControl.notificationCreateTransportOrder(new TransferTiledData() { logisticsTaskId = item.Key.logisticsTaskId }); if (notificationResult) { logisticsTaskIdDict.Remove(item.Key); LogHelper.Info("灵动AGV出库任务已下发,并通知车间下发灵动AGV任务,物流ID:" + item.Key.logisticsTaskId, "输送线"); } else { LogHelper.Info("通知车间下发灵动AGV任务失败,已重置发送次数:"+ item.Value / 10000 +",物流ID:" + item.Key.logisticsTaskId, "输送线"); if (item.Value == 300000) { logisticsTaskIdDict.Remove(item.Key); LogHelper.Info("向输送线发送报警信号" + item.Key, "输送线"); LinePlcInfo line = WCSHelper.GetLinePlcInfoByLoc(item.Key.locCode); S7Helper.WriteInt(line.deviceNo, 101, line.writeAddr + 18, 1); } else { logisticsTaskIdDict[item.Key] = item.Value + 10000; } } } } /// /// 监测输送线 /// public static void MonitorPipeline() { List linePlcInfos = WCSHelper.GetLinePlcInfoList(1); LogHelper.Info("-------------------------------------------------------------------------------------", "输送线"); foreach (var line in linePlcInfos) { // 线体货位 Location originLocation = LocationHelper.GetLoc(line.localtion); Location descLocation = LocationHelper.GetLoc(line.descLocation); LocCntrRel locCntrRel = ContainerHelper.getLocCntrByLoc(originLocation.S_CODE); // 线体信号 LogHelper.Info("输送线,线体:"+line.code, "输送线"); PipelineSignalInfo lineSignalInfo = WCSHelper.readPipelineInfo(line); try { if (lineSignalInfo != null) { LogHelper.Info("000000", "输送线"); if (lineSignalInfo.agvTaskFeedback == 1 || lineSignalInfo.agvTaskFeedback == 2) { // 清除AGV任务反馈 S7Helper.WriteInt(line.deviceNo, 101, line.writeAddr + 14, 0); LogHelper.Info("清除输送线【"+ line.deviceNo + "】的AGV任务反馈", "输送线"); } if (locCntrRel != null) { LogHelper.Info("1111111", "输送线"); if (lineSignalInfo.faultMessage == 1) { // 回报车间控制器 LogHelper.Info("输送线,线体【" + line.code + "】调整为手动状态", "输送线"); continue; } WMSTask wmsTask = WMSHelper.GetWmsTaskByCntr(locCntrRel.S_CNTR_CODE); if (wmsTask == null) { LogHelper.Info("没有正在执行的任务,货位:" + locCntrRel.S_LOC_CODE + " 容器:" + locCntrRel.S_CNTR_CODE, "输送线"); continue; } var date = DateTime.Now.ToString("yyMMdd"); string opTaskId = lineSignalInfo.taskId.ToString().PadLeft(4, '0'); LogHelper.Info("任务号:" + opTaskId, "输送线"); if (line.actType.Equals("入库") && line.sort == 1) { // 判断 请求去向 = 1 、线体光电 = 1 if (lineSignalInfo.requestReadCode == 1 && lineSignalInfo.linePhotoelectric == 1) { // 向该线体发送指令,任务号,目标地址 var descLinePlcInfo = WCSHelper.GetLinePlcInfo(line.descLocation); if (locCntrRel.S_CNTR_CODE.Equals(lineSignalInfo.trayCode)) { issueCommand(line, int.Parse(wmsTask.S_CODE.Substring(8)), (short)descLinePlcInfo.code, 2); LogHelper.Info("向线体发送入库指令 ,任务号:" + int.Parse(wmsTask.S_CODE.Substring(4)) + ", 目标地址:" + (short)descLinePlcInfo.code, "输送线"); } else if(lineSignalInfo.receiveInstruction != 3) { issueCommand(line, int.Parse(wmsTask.S_CODE.Substring(8)), (short)descLinePlcInfo.code, 3); LogHelper.Info("托盘码不一致,向线体发送退回指令 ,输送线托盘码:" + lineSignalInfo.trayCode + "任务托盘码:" + locCntrRel.S_CNTR_CODE, "输送线"); TrayErrorFeedbackInfo info = new TrayErrorFeedbackInfo() { wmsId = wmsTask.S_CODE, errMsg = "托盘码错误" }; ShopFloorControl.trayErrorFeedback(info); } } // 指令已读,清除指令 if (lineSignalInfo.receiveInstruction == 2) { issueCommand(line, 0, 0, 0); LocationHelper.UnBindingLoc(originLocation.S_CODE, new List() { locCntrRel.S_CNTR_CODE }); LocationHelper.BindingLoc(descLocation.S_CODE, new List() { locCntrRel.S_CNTR_CODE }); LogHelper.Info("入库指令已读,清除入库指令", "输送线"); } else if (lineSignalInfo.receiveInstruction == 3) { issueCommand(line, 0, 0, 0); LogHelper.Info("退回指令已读,清除退回指令", "输送线"); } try { // 更新物料重量数据 LogHelper.Info("更新物料重量数据 ,重量:" + lineSignalInfo.weight, "输送线"); var cntrItemRels = ItemHelper.GetCntrItemByCntrCode(wmsTask.S_CNTR_CODE); if (cntrItemRels != null && cntrItemRels.Count > 0) { foreach (var cntrItemRel in cntrItemRels) { cntrItemRel.F_WEIGHT = lineSignalInfo.weight; if (cntrItemRel.F_INIT_WEIGHT == 0) { cntrItemRel.F_INIT_WEIGHT = lineSignalInfo.weight; } ItemHelper.updateCntrItem(cntrItemRel); } } // 输送线称重回报车间控制器 LogHelper.Info("输送线称重回报车间控制器", "输送线"); ProductWeightInfo productWeightInfo = new ProductWeightInfo() { wmsId = wmsTask.S_CODE, trayCode = lineSignalInfo.trayCode, weight = lineSignalInfo.weight.ToString(), weightTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), }; ShopFloorControl.reportSemilFinishedProductWeight(productWeightInfo); } catch (Exception ex) { LogHelper.Info("输送线称重回报车间控制器错误 ,错误原因:" + ex.Message, "输送线"); } } if (line.actType.Equals("入库") && line.sort == 2) { // 判断 任务号、目标地址、是否允许堆垛机取货 LogHelper.Info("输送线里侧货位入库" , "输送线"); if (opTaskId == wmsTask.S_CODE.Substring(8) && lineSignalInfo.linePhotoelectric == 1 && lineSignalInfo.ddjInfo == 2) { LogHelper.Info("输送线条件满足", "输送线"); WCSTask wcsTask = WCSHelper.GetTaskByStart(originLocation.S_CODE, wmsTask.S_CODE); if (wcsTask == null) { LogHelper.Info("开始下发堆垛机入库任务", "输送线"); string itemCode = null; var cntrItems = ContainerHelper.GetCntrItemRel(wmsTask.S_CNTR_CODE); if (cntrItems != null && cntrItems.Count > 0) { itemCode = cntrItems[0].S_ITEM_CODE; } LogHelper.Info("堆垛机入库任务终点", "输送线"); Location endLoc = WMSHelper.GetEndLocation(wmsTask.S_END_AREA, itemCode, originLocation.N_ROADWAY, originLocation.N_ROW); LogHelper.Info($"堆垛机入库任务终点:{endLoc.S_CODE}", "输送线"); wmsTask.S_END_LOC = endLoc.S_CODE; WMSHelper.UpdateTask(wmsTask); string eqNo = ApiHelper.getEqNo(endLoc.S_AREA_CODE, endLoc.N_ROADWAY); List areaCdoes = Settings.getStoreAreaCodes(2, 1); WCSTask twoWcsTask = new WCSTask { S_OP_NAME = wmsTask.S_OP_DEF_NAME, S_OP_CODE = wmsTask.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = wmsTask.S_CNTR_CODE, S_TYPE = wmsTask.S_TYPE + "-2", S_START_LOC = originLocation.S_CODE, S_START_AREA = originLocation.S_AREA_CODE, S_END_LOC = wmsTask.S_END_LOC, S_END_AREA = wmsTask.S_END_AREA, S_EQ_NO = eqNo, S_SCHEDULE_TYPE = "RB", T_START_TIME = DateTime.Now, }; if (WCSHelper.CreateTask(twoWcsTask)) { // 接驳位加出库锁,终点货位加入库锁 LocationHelper.LockLoc(twoWcsTask.S_START_LOC, 2); LocationHelper.LockLoc(twoWcsTask.S_END_LOC, 1); LogHelper.Info("堆垛机入库任务已下发,任务信息:" + JsonConvert.SerializeObject(twoWcsTask), "输送线"); } } else { LogHelper.Info("任务已下发", "输送线"); } } } if (line.actType.Equals("出库") && line.sort == 1) { if (lineSignalInfo.linePhotoelectric == 1) { // 向该线体发送入库指令,任务号,目标地址 var descLinePlcInfo = WCSHelper.GetLinePlcInfo(line.descLocation); issueCommand(line, int.Parse(wmsTask.S_CODE.Substring(8)), (short)descLinePlcInfo.code, 1); LogHelper.Info("向线体发送出库指令 ,任务号:" + int.Parse(wmsTask.S_CODE.Substring(8)) + ", 目标地址:" + (short)descLinePlcInfo.code, "输送线"); } if (lineSignalInfo.receiveInstruction == 1) { issueCommand(line, 0, 0, 0); LocationHelper.UnBindingLoc(originLocation.S_CODE, new List() { locCntrRel.S_CNTR_CODE }); LocationHelper.BindingLoc(descLocation.S_CODE, new List() { locCntrRel.S_CNTR_CODE }); LogHelper.Info("出库指令已读,清除出库指令", "输送线"); } } if (line.actType.Equals("出库") && line.sort == 2) { // 判断 任务号、目标地址、托盘码、是否允许堆垛机取货 if (opTaskId == wmsTask.S_CODE.Substring(8) && lineSignalInfo.linePhotoelectric == 1 ) { if (locCntrRel.S_CNTR_CODE.Equals(lineSignalInfo.trayCode)) { WCSTask wcsTask = WCSHelper.GetTaskByStart(originLocation.S_CODE, wmsTask.S_CODE); if (wcsTask == null) { LogHelper.Info("开始下发灵动AGV出库任务", "输送线"); var twoWcsTask = new WCSTask { S_OP_NAME = wmsTask.S_OP_DEF_NAME, S_CODE = WCSHelper.GenerateTaskNo(), S_TYPE = wmsTask.S_TYPE + "-2", S_START_LOC = originLocation.S_CODE, S_START_AREA = originLocation.S_AREA_CODE, S_END_LOC = wmsTask.S_END_LOC, S_END_AREA = wmsTask.S_END_AREA, S_SCHEDULE_TYPE = "LD", S_CNTR_CODE = wmsTask.S_CNTR_CODE, N_CNTR_COUNT = 1, S_OP_CODE = wmsTask.S_CODE, N_PRIORITY = wmsTask.N_PRIORITY, T_START_TIME = DateTime.Now, }; if (wmsTask.S_TYPE.Equals("半成品/成品出库") || wmsTask.S_TYPE.Equals("叫托盘出库")) { twoWcsTask.S_SCHEDULE_TYPE = "LD-AUTO"; } if (WCSHelper.CreateTask(twoWcsTask)) { LocationHelper.LockLoc(twoWcsTask.S_START_LOC, 2); LocationHelper.LockLoc(twoWcsTask.S_END_LOC, 1); var notificationResult = ShopFloorControl.notificationCreateTransportOrder(new TransferTiledData() { logisticsTaskId = wmsTask.S_OP_DEF_CODE }); if (notificationResult) { WCSHelper.UpdateStatus(twoWcsTask,"已推送"); LogHelper.Info("灵动AGV出库任务已下发,并通知车间下发灵动AGV任务,任务信息:" + JsonConvert.SerializeObject(twoWcsTask), "输送线"); } else { NotificationInfo notificationInfo = new NotificationInfo() { logisticsTaskId = wmsTask.S_OP_DEF_CODE, locCode = originLocation.S_CODE }; LogHelper.Info("物流任务信息:" + JsonConvert.SerializeObject(notificationInfo), "输送线"); if (notificationInfo.logisticsTaskId != null && notificationInfo.locCode != null) { logisticsTaskIdDict.Add(notificationInfo, 0); } LogHelper.Info("通知车间下发灵动AGV任务失败,任务信息:" + JsonConvert.SerializeObject(twoWcsTask), "输送线"); } } } } else { LogHelper.Info("托盘码不一致,请进行人工干预 ,输送线托盘码:" + lineSignalInfo.trayCode + "任务托盘码:" + locCntrRel.S_CNTR_CODE, "输送线"); } } } } // 向数字孪生推送输送线状态信息 MQTTCore.MqttClientService mqttClientService = null; try { SSXStatusInfo info = new SSXStatusInfo() { deviceNo = line.code.ToString(), status = lineSignalInfo.lineState.ToString(), existCargo = lineSignalInfo.linePhotoelectric.ToString(), alertorInfo = lineSignalInfo.faultMessage.ToString(), dataDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), }; MQTTCore.mqqtClients.TryGetValue("数字孪生", out mqttClientService); mqttClientService.Publish("pipelineStatus", JsonConvert.SerializeObject(info)); } catch (Exception ex) { LogHelper.Error("推送输送线状态信息错误", ex, "数字孪生"); } } } catch (Exception ex) { Console.WriteLine(ex.ToString()); LogHelper.Info("输送线错误,错误信息:" + ex.Message, "哈电"); } } } /// /// 清除输送线命令 /// /// /// /// /// public static void issueCommand(LinePlcInfo line,int taskId ,short descLine, short command) { S7Helper.WriteDint(line.deviceNo, 101, line.writeAddr + 2, taskId); // 任务号 S7Helper.WriteInt(line.deviceNo, 101, line.writeAddr + 6, descLine); // 目标线体 S7Helper.WriteInt(line.deviceNo, 101, line.writeAddr + 8, command); // 下发指令(默认=0 入库=2 出库=1 不合格退回=3) } public class SSXStatusInfo { public string deviceNo { get; set; } public string status { get; set; } public string existCargo { get; set; } public string alertorInfo { get; set; } public string dataDate { get; set; } } /// /// 检测堆垛机信号 /// internal static void MonitorDDJSignal() { var ddjPlcInfos = Settings.devicePlcInfos.Where(a => a.deviceType == 1).ToList(); foreach (var item in ddjPlcInfos) { //1.检测堆垛机信号 LogHelper.Info("读取堆垛机 " + item.deviceNo, "堆垛机"); short[] resSignal1 = S7Helper.ReadInt(item.deviceNo, 551, 0, 8); int resSignal2 = S7Helper.ReadDint(item.deviceNo, 551, 16); short[] resSignal3 = S7Helper.ReadInt(item.deviceNo, 551, 20, 3); LogHelper.Info("读取堆垛机 "+item.deviceNo + " 信号: resSignal1:" + JsonConvert.SerializeObject(resSignal1)+ " resSignal2(任务号):" + JsonConvert.SerializeObject(resSignal2) + " resSignal3:" + JsonConvert.SerializeObject(resSignal3), "堆垛机"); if (resSignal1 != null && resSignal2 != 0 && resSignal3 != null) { ResSignalInfo resSignalInfo = new ResSignalInfo() { HandShake = resSignal1[0], SRM_Num = resSignal1[1], Auto = resSignal1[2], Alarm_Code = resSignal1[3], State = resSignal1[4], TaskStatus1 = resSignal1[5], Loaded1 = resSignal1[6], Busines1 = resSignal1[7], TaskId1 = resSignal2, Row = resSignal3[0], Layer = resSignal3[1], b_Fork1Pos = resSignal3[2], }; LogHelper.Info("检测堆垛机信号:" + JsonConvert.SerializeObject(resSignalInfo), "堆垛机"); // 3.堆垛机任务处理 taskProcessing(item.deviceNo, resSignalInfo); } } } /// /// 堆垛机任务处理 /// internal static void taskProcessing(string deviceNo, ResSignalInfo resSignalInfo) { // 堆垛机当前模式为联机自动 且 报警代码为1正常 if (resSignalInfo.Auto == 1) { // 查询任务 /*var wcsTask = WCSHelper.GetTask("TN25" + resSignalInfo.TaskId1.ToString().PadLeft(9, '0'));*/ LogHelper.Info("任务号:" + resSignalInfo.TaskId1, "堆垛机"); var wcsTask = WCSHelper.GetWcsTask(resSignalInfo.TaskId1.ToString()); if (wcsTask != null) { WMSTask wmsTask = WMSHelper.GetWmsTask(wcsTask.S_OP_CODE); if (resSignalInfo.Alarm_Code == 1) { if (wcsTask.N_B_STATE < 3 && wcsTask.S_SCHEDULE_TYPE.Equals("RB")) { // 任务状态 switch (resSignalInfo.TaskStatus1) { case 1:// 确认接收任务 WCSHelper.Begin(wcsTask); break; case 3: // 完成 case 5: // 强制完成 // 1.开始货位解绑、终点货位绑定 LocationHelper.UnBindingLoc(wcsTask.S_START_LOC, new List { wcsTask.S_CNTR_CODE }); LocationHelper.UnLockLoc(wcsTask.S_START_LOC); LocationHelper.BindingLoc(wcsTask.S_END_LOC, new List { wcsTask.S_CNTR_CODE }); LocationHelper.UnLockLoc(wcsTask.S_END_LOC); WCSHelper.End(wcsTask); LogHelper.Info("检测堆垛机任务完成,任务:" + JsonConvert.SerializeObject(wcsTask), "堆垛机"); // 2.判断是一段任务,还是二段任务 if (wmsTask != null && wmsTask.S_END_LOC.Equals(wcsTask.S_END_LOC)) { wmsTask.N_B_STATE = 2; wmsTask.T_END_TIME = DateTime.Now; WMSHelper.UpdateTaskState(wmsTask); // 2.1更新出入库记录 var cntrItemRels = ItemHelper.GetCntrItemByCntrCode(wcsTask.S_CNTR_CODE); if (cntrItemRels != null && cntrItemRels.Count > 0) { foreach (var cntrItemRel in cntrItemRels) { WMSHelper.AddStockRecord(wmsTask, cntrItemRel); } } else { WMSHelper.AddStockRecord(wmsTask, null); } } // 3.当收到PLC的完成时(TaskStatus1=3)上位写3确认,PLC收到确认,清除任务状态 S7Helper.WriteInt(deviceNo, 550, 28, 3); // 4.任务完成,清除堆垛机数据 clearingDDJData(deviceNo); break; case 6: // 取消任务 WCSHelper.Fail(wcsTask); LocationHelper.UnLockLoc(wcsTask.S_START_LOC); LocationHelper.UnLockLoc(wcsTask.S_END_LOC); /* clearingDDJData(deviceNo);*/ // 取消作业 wmsTask.N_B_STATE = 3; wmsTask.T_END_TIME = DateTime.Now; WMSHelper.UpdateTaskState(wmsTask); LocationHelper.UnLockLoc(wmsTask.S_END_LOC); LogHelper.Info("任务取消,任务号:" + wcsTask.S_CODE, "堆垛机"); break; } WCSHelper.AddActionRecord(wcsTask.S_CODE, resSignalInfo.TaskStatus1, wcsTask.S_EQ_NO, null); } } else { if (resSignalInfo.Busines1 == 1 || resSignalInfo.Busines1 == 3) { // 再清除wcs写入通道内任务数据,同时为该任务计算一个新的放货终点。 var cntrItemRels = ItemHelper.GetCntrItemByCntrCode(wcsTask.S_CNTR_CODE); Location formerEndLoc = LocationHelper.GetLoc(wcsTask.S_END_LOC); Location endLoc = WMSHelper.GetEndLocation(formerEndLoc.S_AREA_CODE, cntrItemRels[0].S_ITEM_CODE, formerEndLoc.N_ROADWAY, 1); wcsTask.S_END_LOC = endLoc.S_CODE; wcsTask.N_B_STATE = 0; wcsTask.S_B_STATE = "等待"; wcsTask.N_PRIORITY = 10; wcsTask.S_ERR = resSignalInfo.Busines1.ToString() + ":满入和放货阻塞报警;阻塞货位:" + formerEndLoc.S_CODE; WCSHelper.UpdateWcsTask(wcsTask); LocationHelper.UnLockLoc(formerEndLoc.S_CODE); LocationHelper.LockLoc(formerEndLoc.S_CODE, 3); LocationHelper.LockLoc(endLoc.S_CODE, 1); if (formerEndLoc.S_CODE == wmsTask.S_END_LOC) { wmsTask.S_END_LOC = endLoc.S_CODE; WMSHelper.UpdateTask(wmsTask); } // wcs在任务推送后需追加循环读取该地址信号。若为1. 需先写入地址4为12通知堆垛机清除其对应通道任务数据。 S7Helper.WriteInt(deviceNo, 550, 4, 12); LogHelper.Info("满入和放货阻塞报警", "堆垛机"); } if (resSignalInfo.Busines1 == 2 || resSignalInfo.Busines1 == 4) { /* S7Helper.WriteInt(deviceNo, 550, 4, 12); var cntrItemRels = ItemHelper.GetCntrItemByCntrCode(wcsTask.S_CNTR_CODE); LocationHelper.UnLockLoc(formerStartLoc.S_CODE); LocationHelper.LockLoc(formerStartLoc.S_CODE, 3);*/ Location formerStartLoc = LocationHelper.GetLoc(wcsTask.S_START_LOC); wcsTask.N_B_STATE = 4; wcsTask.S_B_STATE = "错误"; wcsTask.S_ERR = resSignalInfo.Busines1.ToString() + ":空取和取货阻塞报警; 取货货位:" + formerStartLoc.S_CODE; LogHelper.Info("空取和取货阻塞报警", "堆垛机"); } } } else { LogHelper.Info($"任务号:{resSignalInfo.TaskId1},未查询到堆垛机任务", "堆垛机"); } } // 堆垛机任务状态推送 try { // FromWcs(DB550)下发任务数据 short[] resSignal = S7Helper.ReadInt(deviceNo, 550, 8, 8); // 1.堆垛机状态推送数字孪生 MQTTCore.MqttClientService mqttClientService = null; DDJStatusInfo info = new DDJStatusInfo() { deviceNo = resSignalInfo.SRM_Num.ToString(), auto = resSignalInfo.Auto.ToString(), status = resSignalInfo.State.ToString(), alertorInfo = resSignalInfo.Alarm_Code.ToString(), Loaded1 = resSignalInfo.Loaded1.ToString(), Busines1 = resSignalInfo.Busines1.ToString(), Row = resSignalInfo.Row.ToString(), Layer = resSignalInfo.Layer.ToString(), b_Fork1Pos = resSignalInfo.b_Fork1Pos.ToString(), TaskId1 = resSignalInfo.TaskId1.ToString(), dataDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), }; if (resSignal != null) { info.Source_Z_S1 = resSignal[0].ToString(); info.Source_X_S1 = resSignal[1].ToString(); info.Source_Y_S1 = resSignal[2].ToString(); info.Dest_Z_S1 = resSignal[4].ToString(); info.Dest_X_S1 = resSignal[5].ToString(); info.Dest_Y_S1 = resSignal[6].ToString(); } MQTTCore.mqqtClients.TryGetValue("数字孪生", out mqttClientService); mqttClientService.Publish("stackerStatus", JsonConvert.SerializeObject(info)); // 2.向数字孪生推送堆垛机任务数据 MQTTCore.mqqtClients.TryGetValue("数字孪生", out mqttClientService); mqttClientService.Publish("unfinishedTask", JsonConvert.SerializeObject(WCSHelper.getDDJProceedTaskData())); } catch (Exception ex) { LogHelper.Error("推送堆垛机任务数据错误", ex, "数字孪生"); } } public static void clearingDDJData(string plc) { short HandShake = 0; short[] handShakeValues = S7Helper.ReadInt(plc, 551, 0, 1); if (handShakeValues != null) { if (handShakeValues[0] == 0) { HandShake = 1; } else if (handShakeValues[0] == 1) { HandShake = 0; } } // TODO s7 wcs -> plc 写入任务 RBWriteTaskInfo rBWriteTaskInfo = new RBWriteTaskInfo() { HandShake = HandShake, SRM_Num = 0, CommandType = 0, Source_Z_S1 = 0, Source_X_S1 = 0, Source_Y_S1 = 0, Source_L_S1 = 0, Dest_Z_S1 = 0, Dest_X_S1 = 0, Dest_Y_S1 = 0, Dest_L_S1 = 0, Task_S1 = 0, // TODO 任务号待确定 ConfirmSignal1 = 0, }; RBWriteTask(plc, rBWriteTaskInfo); LogHelper.Info("堆垛机任务取消或完成,清除数据:" + JsonConvert.SerializeObject(rBWriteTaskInfo), "堆垛机"); } [SugarTable("TN_Test_StackerCrane")] public class ResSignalInfo : BaseModel { public short HandShake { get; set; } // 心跳 public short SRM_Num { get; set; } // 堆垛机号 public short Auto { get; set; } // 堆垛机当前模式指示 1 联机自动;2手动;3半自动;4维修; public short Alarm_Code { get; set; } // 堆垛机报警代码 0:默认;1:正常 ;其他数字故障信息 public short State { get; set; } // 1:状态正常,允许任务下发(联机自动模式,不报警,叉在中位,无上条任务残留数据时才为1)其他:异常状态 public short TaskStatus1 { get; set; } // 0:默认; 1:确认接收任务; 3:工位1正常任务完成; 5.工位1强制完成 ; 6.取消任务 public short Loaded1 { get; set; } // 工位1载货台有无货 1:有货;0:无货 public short Busines1 { get; set; } // 工位1特殊业务状态反馈 [1:满入,2.空取,3:放货阻塞,4:取货阻塞] public int TaskId1 { get; set; } // 工位1任务号 public short Row { get; set; } // 堆垛机当前列(行走方向) public short Layer { get; set; } // 堆垛机当前层(升降方向) public short b_Fork1Pos { get; set; } // 堆垛机货叉1位置 [1:左远,2.左近,3:居中,4:右近,5:右远] } } }