using Dm.filter; using DocumentFormat.OpenXml.Bibliography; using DocumentFormat.OpenXml.Drawing.Charts; using Elastic.Clients.Elasticsearch.Snapshot; using Elastic.Clients.Elasticsearch.Tasks; using Flurl.Util; using Furion.Logging; using IoTClient; using Microsoft.AspNetCore.SignalR; using NewLife.Reflection; using Qiniu.Storage; using RazorEngine.Compilation.ImpromptuInterface.Dynamic; using SKIT.FlurlHttpClient.Wechat.TenpayV3.ExtendedSDK.Global.Models; using System; using System.Data; using System.Reflection.Emit; using WCS.Application.Entity; using WCS.Application.Service.WcsDevice.Dto; using WCS.Application.Util; using static SKIT.FlurlHttpClient.Wechat.Api.Models.CgibinExpressIntracityUpdateStoreRequest.Types; using static SKIT.FlurlHttpClient.Wechat.Api.Models.NontaxInsertBillRequest.Types.CardExtra.Types.BillCard.Types; namespace WCS.Application; public static class PLCService { private static readonly object OLock = new object(); private static readonly ISqlSugarClient _db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId); private static int fendao = 1; public static void OnChangeEvent(object sender, EventArgs e) { try { var mod = sender as WcsDeviceDto; Console.WriteLine("PLC值为" + mod.Value); switch (mod.Type) { case PLCTypeEnum.StackingMachine: StackingMachine(mod); // 跺机 break; case PLCTypeEnum.ConveyorLine: ConveyorLine(mod); // 托盘输送线 break; case PLCTypeEnum.AGV: AGV(mod); // AGV调度 break; case PLCTypeEnum.BoxConveyorLine: BoxConveyorLine(mod); // 码垛机器人 break; case PLCTypeEnum.StackingRobot: StackingRobot(mod); //拆垛机器人 break; default: break; } } catch (Exception ex) { Log.Error(ex.Message, ex); } } /// /// 跺机业务处理 /// /// private static void StackingMachine(WcsDeviceDto modDevice) { var plcConn = modDevice.PLCUtil; string ledText = ""; switch (modDevice.Value.ToString()) { case "820": // 跺机空闲,获取出库任务、移库任务 { // 获取任务信息 var modTask = _db.Queryable().OrderBy(m => m.Levels, OrderByType.Asc).OrderBy(m => m.CreateTime) .First(s => s.Status == TaskStatusEnum.Wait && (s.TaskType == TaskTypeEnum.Out || s.TaskType == TaskTypeEnum.Move) && s.StartRoadway == modDevice.StationNum); if (modTask == null) { break; } //判断出库锁定是否打开 if (PLCTaskAction.boOutLock) { break;//出库锁定打开则不执行出库任务 } PlcTaskInfo taskInfo = new PlcTaskInfo(); if (modTask.TaskType == TaskTypeEnum.Move) { taskInfo = PLCCommon.GetEndPai(modTask.EndRoadway.Substring(1, 2), modTask.EndLocate.Substring(2, 2), modTask.EndLocate.Substring(0, 2), modTask.EndLocate.Substring(4, 2), modTask.EndLocate.Substring(6, 2)); } else { // 根据目标地址和巷道获取放货工位对应的排列层 taskInfo = PLCCommon.GetCTaskInfo(modTask.EndLocate, ((int)modTask.TaskType).ToString(), modTask.StartRoadway, modTask.EndRoadway); // 目标工位不为null,需先判断放货工位是否空闲 if (!string.IsNullOrEmpty(taskInfo.EndStation)) { // 打开对应的输送线连接 var plcConveyorConn = PLCTaskAction.listPlcConn.First(m => m.PlcIP == taskInfo.Ip); if (plcConveyorConn.Connected) { // 获取放货工位配置信息 var ConveyorMod = PLCTaskAction.plcDevices.First(m => m.StationNum == taskInfo.EndStation && m.DeviceType == DeviceTypeEnum.Business); var (result, value) = plcConveyorConn.GetPlcDBValue(ConveyorMod.PosType, ConveyorMod.DbNumber, ConveyorMod.PlcPos); if (result.IsSucceed) { if (value.ToString() != "720") // 720:放货空位空闲,可放货 { Log.Error(string.Format("任务号:{0}:放货工位占用,稍后执行。", modTask.TaskNo)); break; } else if (value.ToString() == "720") { // 若空闲提前占用此工位,同工位出入公用口 放开此程序 // var ret = plcConn.SetPlcDBValue(ConveyorMod.PosType, ConveyorMod.DbNumber, ConveyorMod.WcsPos, "730"); } } else { break; } } else { break; } } } // 获取转换后的起始排列层 06010101 PlcTaskInfo startTaskInfo = PLCCommon.GetEndPai(modTask.StartRoadway.Substring(1, 2), modTask.StartLocate.Substring(2, 2), modTask.StartLocate.Substring(0, 2), modTask.StartLocate.Substring(4, 2), modTask.StartLocate.Substring(6, 2)); // 给PLC写入任务数据 var listResult = new List(); // 任务号托盘号 var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "任务号"); listResult.Add(plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo)); var modPosPalletNo = modDevice.listStation.FirstOrDefault(s => s.Text == "托盘码"); listResult.Add(plcConn.SetPlcDBValue(modPosPalletNo.PosType, modDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo)); // 起始排列层 var modPosRow = modDevice.listStation.FirstOrDefault(s => s.Text == "取货排"); listResult.Add(plcConn.SetPlcDBValue(modPosRow.PosType, modDevice.DbNumber, modPosRow.PlcPos, startTaskInfo.EndPai)); var modPosColumn = modDevice.listStation.FirstOrDefault(s => s.Text == "取货列"); listResult.Add(plcConn.SetPlcDBValue(modPosColumn.PosType, modDevice.DbNumber, modPosColumn.PlcPos, startTaskInfo.EndLie)); var modPosStorey = modDevice.listStation.FirstOrDefault(s => s.Text == "取货层"); listResult.Add(plcConn.SetPlcDBValue(modPosStorey.PosType, modDevice.DbNumber, modPosStorey.PlcPos, startTaskInfo.EndCeng)); // 目标放货工位(固定排列层) var modPosEndRow = modDevice.listStation.FirstOrDefault(s => s.Text == "放货排"); listResult.Add(plcConn.SetPlcDBValue(modPosEndRow.PosType, modDevice.DbNumber, modPosEndRow.PlcPos, taskInfo.EndPai)); var modPosEndColumn = modDevice.listStation.FirstOrDefault(s => s.Text == "放货列"); listResult.Add(plcConn.SetPlcDBValue(modPosEndColumn.PosType, modDevice.DbNumber, modPosEndColumn.PlcPos, taskInfo.EndLie)); var modPosEndStorey = modDevice.listStation.FirstOrDefault(s => s.Text == "放货层"); listResult.Add(plcConn.SetPlcDBValue(modPosEndStorey.PosType, modDevice.DbNumber, modPosEndStorey.PlcPos, taskInfo.EndCeng)); // 是否写入成功 if (listResult.All(s => s.IsSucceed)) { // 写入跺机任务下发完成 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "830"); // 将移库任务待执行改为正在执行 _db.Updateable() .SetColumns(s => s.Status == TaskStatusEnum.Doing) .Where(s => s.Id == modTask.Id) .ExecuteCommand(); HubUtil.PublicTask(modTask.Adapt()); WcsTaskMonitor modInsertTaskMonitor; if (string.IsNullOrEmpty(taskInfo.EndStation)) { // 同巷道移库 modInsertTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = modDevice.Id, PlcName = modDevice.Text, InteractiveMsg = $"写入指令:{modTask.StartLocate}储位====》{modTask.EndLocate}储位。", PalletNo = modTask.PalletNo, Status = TaskStatusEnum.Complete, StartLocat = modTask.StartLocate, EndLocat = modTask.EndLocate, }; } else { // 出库任务 跨巷道移库 modInsertTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = modDevice.Id, PlcName = modDevice.Text, InteractiveMsg = $"写入指令:{modTask.StartLocate}储位====》{taskInfo.EndStation}工位。", PalletNo = modTask.PalletNo, Status = TaskStatusEnum.Complete, StartLocat = modTask.StartLocate, EndLocat = modTask.EndLocate, }; } // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); //下发任务日志 HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); //修改led屏信息 var ledDevice = PLCTaskAction.plcDevices.First(m => m.StationNum == taskInfo.EndStation && m.IsDelete == false && m.DeviceType == DeviceTypeEnum.Business); //ledText += $"任务类型:{modTask.TaskType.GetDescription()}\n\n"; //ledText += $"任务号:{modTask.TaskNo}\n"; //ledText += $"托盘号:{modTask.PalletNo}\n\n"; //ledText += $"起始位:{modTask.StartRoadway + " " + modTask.StartLocate}\n"; //ledText += $"目标位:{modTask.EndRoadway + " " + modTask.EndLocate}"; ledText += $"名称:{modTask.SkuName}\n"; ledText += $"批号:{modTask.LotNo}\n"; ledText += $"入库数量:{modTask.Qty}\n"; ledText += $"托盘号:{modTask.PalletNo}\n\n"; LedDisplay(ledDevice.LedIP, ledText); } } break; case "840": // 取货完成 { // 获取跺机点位配置 var modPosTask = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号"); var (res, val) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosTask.PlcPos); var modPosEndStation = modDevice.listStation.FirstOrDefault(m => m.Text == "目的工位"); var (endStationRes, endStation) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosEndStation.PlcPos); if (res.IsSucceed) { // 获取任务信息 string tasknoVal = val.ToString(); var modTask = _db.Queryable().First(m => m.Status == TaskStatusEnum.Doing && m.TaskNo == tasknoVal && m.IsDelete == false); if (modTask == null) { Log.Error(string.Format("PLC控制字840:未找到对应的任务。")); break; } // 记录任务明细 var modInsertTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = modDevice.Id, PlcName = modDevice.Text, PalletNo = modTask.PalletNo, Status = TaskStatusEnum.Complete, StartLocat = modTask.StartLocate, }; if (modTask.TaskType == TaskTypeEnum.In) { // 获取跺机起始工位点位配置,读取起始工位 var modPosStartStation = modDevice.listStation.FirstOrDefault(m => m.Text == "起始工位"); var (startStationRes, startStationVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.Short, modDevice.DbNumber, modPosStartStation.PlcPos); if (startStationRes.IsSucceed) { // 根据工位号获取对应的输送线IP PLCUtil plcConveyorConn = PLCCommon.GetPlcIp(startStationVal.ToString()); if (plcConveyorConn.Connected) { // 向取货工位写入流程字640 取货已完成 var ConveyorMod = PLCTaskAction.plcDevices.First(m => m.StationNum == startStationVal.ToString() && m.DeviceType == DeviceTypeEnum.Business && m.IsDelete == false); var modcTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = ConveyorMod.Id, PlcName = ConveyorMod.Text, PalletNo = modTask.PalletNo, Status = TaskStatusEnum.Complete, StartLocat = startStationVal.ToString(), EndLocat = modTask.EndLocate // 目标储位地址 }; // 读取wcs控制字 var (ress, va1s) = plcConveyorConn.GetPlcDBValue(ConveyorMod.PosType, ConveyorMod.DbNumber, ConveyorMod.WcsPos); if (va1s.ToString() == "630") { modcTaskMonitor.InteractiveMsg = string.Format("工位:{0},写入取货完成:640", startStationVal); // 插入交互日志 _db.Insertable(modcTaskMonitor).ExecuteCommand(); var retc = plcConveyorConn.SetPlcDBValue(ConveyorMod.PosType, ConveyorMod.DbNumber, ConveyorMod.WcsPos, "640"); if (!retc.IsSucceed) { modcTaskMonitor.InteractiveMsg = string.Format("工位:{0},写入取货完成640失败", startStationVal); // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); //下发任务日志 HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); break; } //下发任务日志 HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); } } // 读取wcs控制字 var (resss, va1ss) = plcConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos); if (va1ss.ToString() == "830") { modInsertTaskMonitor.InteractiveMsg = string.Format("工位:{0}跺机取货完成写入850", startStationVal); modInsertTaskMonitor.EndLocat = modTask.EndLocate; // 目标储位地址 // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); } // 写入流程控制字 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "850"); if (!ret.IsSucceed) { modInsertTaskMonitor.InteractiveMsg = string.Format("工位:{0}跺机取货完成写入850失败,等待再次写入。", startStationVal); modInsertTaskMonitor.EndLocat = modTask.EndLocate; // 目标储位地址 // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); break; // 写入失败跳出等待再次写入 } //下发任务日志 HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); } } else if (modTask.TaskType == TaskTypeEnum.Out) { // 读取wcs控制字 var (resss, va1ss) = plcConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos); if (va1ss.ToString() == "830") { // 记录任务明细 modInsertTaskMonitor.InteractiveMsg = string.Format("储位地址:{0}取货完成写入850", modTask.StartLocate); modInsertTaskMonitor.EndLocat = endStation; // 放货工位 } // 写入流程控制字 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "850"); if (!ret.IsSucceed) { modInsertTaskMonitor.InteractiveMsg = string.Format("储位地址:{0}取货完成写入850失败,等待再次写入。", modTask.StartLocate); modInsertTaskMonitor.EndLocat = modTask.EndLocate; // 目标储位地址 // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); break; // 写入失败跳出等待再次写入 } //下发任务日志 HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); } else { // 写入流程控制字 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "850"); if (!ret.IsSucceed) { break; // 写入失败跳出等待再次写入 } modInsertTaskMonitor.InteractiveMsg = string.Format("储位地址:{0}取货完成", modTask.StartLocate); modInsertTaskMonitor.EndLocat = endStation; // 目标储位 // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); //下发任务日志 HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); } } } break; case "860": { // 获取跺机点位配置 var modPos860Task = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号"); var (res, val) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPos860Task.PlcPos); // 根据任务号获取任务信息 if (res.IsSucceed) { string tasknoVal = val.ToString(); var modTask = _db.Queryable().First(m => m.Status == TaskStatusEnum.Doing && m.TaskNo == tasknoVal && m.IsDelete == false); if (modTask == null) { Log.Error(string.Format("跺机控制字860:未找到对应的任务。")); break; } switch (modTask.TaskType) { case TaskTypeEnum.In: { var res870 = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "870"); if (!res870.IsSucceed) { Log.Error(string.Format("跺机控制字860写入870失败!")); break; } // 改变任务状态 modTask.Status = TaskStatusEnum.Complete; modTask.FinishDate = DateTime.Now; _db.Updateable(modTask).ExecuteCommand(); HubUtil.PublicTask(modTask.Adapt()); var modTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = modDevice.Id, PlcName = modDevice.Text, PalletNo = modTask.PalletNo, Status = TaskStatusEnum.Complete, StartLocat = modTask.StartLocate, EndLocat = modTask.EndLocate, InteractiveMsg = $"任务完成" }; if (modTask.Origin == "WMS") { // 反馈WMS var requestMode = new TaskRequestWMS() { TaskNo = modTask.TaskNo, PalletNo = modTask.PalletNo, TaskType = ((int)TaskTypeEnum.In).ToString(), TaskStatus = ((int)TaskStatusEnum.Complete).ToString() }; HttpService httpService = new HttpService(); var modResponseTask = httpService.RequestTask(requestMode).Result; if (modResponseTask.StatusCode == 0) { modTaskMonitor.InteractiveMsg = "任务完成,返回给WMS任务完成"; } else { Log.Error(string.Format("c:StatusCode:{0};Msg:{1}", modResponseTask.StatusCode, modResponseTask.Msg)); } } // 根据任务号获取起始工位地址,根据起始工位地址获取LEDIP 推送到LED屏幕。 modDevice.LedIP = _db.Queryable().Where(w => w.StationNum == modTask.StartLocate).Select(s => s.LedIP).First(); // 插入交互日志 _db.Insertable(modTaskMonitor).ExecuteCommand(); //下发任务日志 HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt()); // led显示内容 var ledDevice = PLCTaskAction.plcDevices.First(m => m.StationNum == modTask.StartLocate && m.IsDelete == false && m.DeviceType == DeviceTypeEnum.Business); //ledText += $"入库完成\n\n"; //ledText += $"任务号:{modTask.TaskNo}\n"; //ledText += $"托盘号:{modTask.PalletNo}\n\n"; //ledText += $"起始位:{modTask.StartRoadway + " " + modTask.StartLocate}\n"; //ledText += $"目标位:{modTask.EndRoadway + " " + modTask.EndLocate}"; ledText += $"名称:{modTask.SkuName}\n"; ledText += $"批号:{modTask.LotNo}\n"; ledText += $"入库数量:{modTask.Qty}\n"; ledText += $"托盘号:{modTask.PalletNo}\n\n"; LedDisplay(ledDevice.LedIP, ledText); // 此处添加不空跑业务 } break; case TaskTypeEnum.Out: // 出库任务 { string roadway = modTask.StartRoadway; // 从出库任务获取放货工位 string outCode = modTask.EndLocate; // 根据工位号获取对应的输送线IP var plcConveyorConn = PLCCommon.GetPlcIp(outCode); if (plcConveyorConn.Connected) { // 根据目标地址和巷道获取放货工位对应的排列层 PlcTaskInfo taskInfo = PLCCommon.GetCTaskInfo(modTask.EndLocate, ((int)modTask.TaskType).ToString(), modTask.StartRoadway, modTask.EndRoadway); // 根据工位号获取工位信息 var wcsDevice = PLCTaskAction.plcDevices.First(s => s.PlcId == plcConveyorConn.PlcId && s.Level == DeviceLevelEnum.Station && s.StationNum == taskInfo.EndStation); // 读取当前工位各偏移量值 var listPos = PLCTaskAction.plcPositions.Where(s => s.DeviceId == wcsDevice.Id).ToList(); // 给PLC写入任务数据 var listResult = new List(); //任务号 var modPosTask = listPos.FirstOrDefault(s => s.Text == "任务号"); listResult.Add(plcConveyorConn.SetPlcDBValue(modPosTask.PosType, wcsDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo)); //任务类型 var modPosTaskType = listPos.FirstOrDefault(s => s.Text == "任务类型"); listResult.Add(plcConveyorConn.SetPlcDBValue(modPosTaskType.PosType, wcsDevice.DbNumber, modPosTaskType.PlcPos, ((int)modTask.TaskType).ToString())); //托盘号 var modPosPalletNo = listPos.FirstOrDefault(s => s.Text == "托盘码"); listResult.Add(plcConveyorConn.SetPlcDBValue(modPosPalletNo.PosType, wcsDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo)); //起始工位 var modPosLocatNo = listPos.FirstOrDefault(s => s.Text == "起始工位"); listResult.Add(plcConveyorConn.SetPlcDBValue(modPosLocatNo.PosType, wcsDevice.DbNumber, modPosLocatNo.PlcPos, taskInfo.EndStation)); // 目标工位 var modPosEndLocatNo = listPos.FirstOrDefault(s => s.Text == "目的工位"); listResult.Add(plcConveyorConn.SetPlcDBValue(modPosEndLocatNo.PosType, wcsDevice.DbNumber, modPosEndLocatNo.PlcPos, outCode)); // 是否写入成功 if (listResult.All(s => s.IsSucceed)) { var result = plcConveyorConn.SetPlcDBValue(wcsDevice.PosType, wcsDevice.DbNumber, wcsDevice.WcsPos, "740"); if (result.IsSucceed) { // 写入跺机wcs控制字 返回垛机执行完成 result = modDevice.PLCUtil.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "870"); if (result.IsSucceed) { var modcTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = wcsDevice.Id, PlcName = wcsDevice.Text, PalletNo = modTask.PalletNo, Status = TaskStatusEnum.Complete, StartLocat = taskInfo.EndStation, EndLocat = outCode, InteractiveMsg = $"写入指令:收到跺机放货完成;放货{taskInfo.EndStation}工位===》{outCode}出库口" }; // 插入交互日志 _db.Insertable(modcTaskMonitor).ExecuteCommand(); //下发任务日志 HubUtil.PublicTaskMonitor(modcTaskMonitor.Adapt()); break; } } } //此处添加不空跑业务 } } break; case TaskTypeEnum.Move: // 移库任务 { var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "任务号"); var result = plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo); if (!result.IsSucceed) { Log.Error($"{modDevice.Text}写入任务号失败"); break; } result = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "870"); if (!result.IsSucceed) { Log.Error($"{modDevice.Text}控制字写入870失败"); break; } // 改变任务状态 modTask.Status = TaskStatusEnum.Complete; modTask.FinishDate = DateTime.Now; modTask.Levels = 999; _db.Updateable(modTask).ExecuteCommand(); //下发任务日志 HubUtil.PublicTask(modTask.Adapt()); var modcTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = modDevice.Id, PlcName = modDevice.Text, PalletNo = modTask.PalletNo, Status = TaskStatusEnum.Complete, StartLocat = modTask.StartLocate, EndLocat = modTask.EndLocate, InteractiveMsg = $"任务完成" }; if (modTask.Origin == "WMS") { // 反馈WMS var requestMode = new TaskRequestWMS() { TaskNo = modTask.TaskNo, PalletNo = modTask.PalletNo, TaskType = ((int)TaskTypeEnum.Move).ToString(), TaskStatus = ((int)TaskStatusEnum.Complete).ToString() }; HttpService httpService = new HttpService(); var modResponseTask = httpService.RequestTask(requestMode).Result; if (modResponseTask.StatusCode == 0) { modcTaskMonitor.InteractiveMsg = "任务完成,返回给WMS任务完成"; //修改储位信息 任务类型 执行状态 起始位置 目标位置 } else { Log.Error(string.Format("任务反馈失败:StatusCode:{0};Msg:{1}", modResponseTask.StatusCode, modResponseTask.Msg)); } } // 插入交互日志 _db.Insertable(modcTaskMonitor).ExecuteCommand(); //下发任务日志 HubUtil.PublicTaskMonitor(modcTaskMonitor.Adapt()); // 此处添加不空跑业务 } break; default: break; } } } break; case "841": { } break; case "843": { //空取货异常 var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "任务号"); var (result, TaskNo) = plcConn.GetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos); if (!result.IsSucceed) break; string taskNo = Convert.ToString(TaskNo); var modTask = _db.Queryable().First(s => s.TaskNo == taskNo && s.Status == TaskStatusEnum.Doing); if (modTask == null) { Log.Error($"【堆垛机】当前任务号不存在对应的任务,任务号:{TaskNo}"); break; } var res = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "844"); if (!res.IsSucceed) break; modTask.Status = TaskStatusEnum.Exception; _db.Updateable(modTask).UpdateColumns(s => s.Status).ExecuteCommand(); HubUtil.PublicTask(modTask.Adapt()); Log.Information($"【堆垛机】wcs任务变更空取异常,任务号:{modTask.TaskNo}"); var modTaskRequest = modTask.Adapt(); HttpService httpService = new HttpService(); var modResponseTask = httpService.RequestEmptyException(modTaskRequest).Result; if (modResponseTask.StatusCode == "0") { //请求成功 modTask.IsSuccess = TaskSuccessEnum.Success; _db.Updateable(modTask).UpdateColumns(s => s.IsSuccess).ExecuteCommand(); //下发任务日志 HubUtil.PublicTask(modTask.Adapt()); } else { //请求失败 modTask.IsSuccess = TaskSuccessEnum.Fail; modTask.Information = modResponseTask.Message; _db.Updateable(modTask).UpdateColumns(s => new { s.IsSuccess, s.Information }).ExecuteCommand(); HubUtil.PublicTask(modTask.Adapt()); } } break; case "861": { //满放货异常 var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "任务号"); var modPosPalletNo = modDevice.listStation.FirstOrDefault(s => s.Text == "托盘码"); var (result, TaskNo) = plcConn.GetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos); if (!result.IsSucceed) break; string taskNo = Convert.ToString(TaskNo); var modTask = _db.Queryable().First(s => s.TaskNo == taskNo && s.Status == TaskStatusEnum.Doing); if (modTask == null) { Log.Error($"【堆垛机】当前任务号不存在对应的任务,任务号:{TaskNo}"); break; } modTask.Status = TaskStatusEnum.Exception; _db.Updateable(modTask).UpdateColumns(s => s.Status).ExecuteCommand(); HubUtil.PublicTask(modTask.Adapt()); Log.Information($"【堆垛机】wcs任务变更满取异常,任务号:{modTask.TaskNo}"); var modTaskRequest = modTask.Adapt(); HttpService httpService = new HttpService(); var modResponseTask = httpService.RequestFullException(modTaskRequest).Result; if (modResponseTask.StatusCode == "0") { //修改任务为正在执行 modTask.Status = TaskStatusEnum.Doing; _db.Updateable(modTask).UpdateColumns(s => s.Status).ExecuteCommand(); // 起始排列层 var modPosRow = modDevice.listStation.FirstOrDefault(s => s.Text == "取货排"); var modPosColumn = modDevice.listStation.FirstOrDefault(s => s.Text == "取货列"); var modPosStorey = modDevice.listStation.FirstOrDefault(s => s.Text == "取货层"); // 目标放货工位 var modPosEndRow = modDevice.listStation.FirstOrDefault(s => s.Text == "放货排"); var modPosEndColumn = modDevice.listStation.FirstOrDefault(s => s.Text == "放货列"); var modPosEndStorey = modDevice.listStation.FirstOrDefault(s => s.Text == "放货层"); string endLocat = modResponseTask.TaskList.EndLocate; string row = int.Parse(endLocat.Substring(0, 2)).ToString(); string column = int.Parse(endLocat.Substring(2, 2)).ToString(); string storey = int.Parse(endLocat.Substring(4, 2)).ToString(); // 给PLC写入任务数据 //var listResult = new List(); //// 任务号托盘号 //listResult.Add(plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo)); //listResult.Add(plcConn.SetPlcDBValue(modPosPalletNo.PosType, modDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo)); //// 起始排列层 //listResult.Add(plcConn.SetPlcDBValue(modPosRow.PosType, modDevice.DbNumber, modPosRow.PlcPos, "2")); //listResult.Add(plcConn.SetPlcDBValue(modPosColumn.PosType, modDevice.DbNumber, modPosColumn.PlcPos, "100")); //listResult.Add(plcConn.SetPlcDBValue(modPosStorey.PosType, modDevice.DbNumber, modPosStorey.PlcPos, "1")); //listResult.Add(plcConn.SetPlcDBValue(modPosEndRow.PosType, modDevice.DbNumber, modPosEndRow.PlcPos, row)); //listResult.Add(plcConn.SetPlcDBValue(modPosEndColumn.PosType, modDevice.DbNumber, modPosEndColumn.PlcPos, column)); //listResult.Add(plcConn.SetPlcDBValue(modPosEndStorey.PosType, modDevice.DbNumber, modPosEndStorey.PlcPos, storey)); PlcTaskInfo taskInfo = new PlcTaskInfo(); taskInfo = PLCCommon.GetEndPai(modTask.EndRoadway.Substring(1, 2), modTask.EndLocate.Substring(2, 2), modTask.EndLocate.Substring(0, 2), modTask.EndLocate.Substring(4, 2), modTask.EndLocate.Substring(6, 2)); // 给PLC写入任务数据 var listResult = new List(); // 任务号托盘号 modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "任务号"); listResult.Add(plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo)); modPosPalletNo = modDevice.listStation.FirstOrDefault(s => s.Text == "托盘码"); listResult.Add(plcConn.SetPlcDBValue(modPosPalletNo.PosType, modDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo)); // 目标放货工位(固定排列层) modPosEndRow = modDevice.listStation.FirstOrDefault(s => s.Text == "放货排"); listResult.Add(plcConn.SetPlcDBValue(modPosEndRow.PosType, modDevice.DbNumber, modPosEndRow.PlcPos, taskInfo.EndPai)); modPosEndColumn = modDevice.listStation.FirstOrDefault(s => s.Text == "放货列"); listResult.Add(plcConn.SetPlcDBValue(modPosEndColumn.PosType, modDevice.DbNumber, modPosEndColumn.PlcPos, taskInfo.EndLie)); modPosEndStorey = modDevice.listStation.FirstOrDefault(s => s.Text == "放货层"); listResult.Add(plcConn.SetPlcDBValue(modPosEndStorey.PosType, modDevice.DbNumber, modPosEndStorey.PlcPos, taskInfo.EndCeng)); // 是否写入成功 if (listResult.All(s => s.IsSucceed)) { // 向跺机写入控制流程字 var res = modDevice.PLCUtil.SetPlcDBValue(modDevice.PosType, modDevice.WcsPos, "862"); var modcTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = modDevice.Id, PlcName = modDevice.Text, PalletNo = modTask.PalletNo, Status = TaskStatusEnum.Complete, StartLocat = modDevice.StationNum, EndLocat = endLocat, InteractiveMsg = $"写入指令:{modDevice.StationNum}工位====》" + endLocat + "储位地址!" }; // 插入交互日志 _db.Insertable(modcTaskMonitor).ExecuteCommand(); //下发任务日志 HubUtil.PublicTaskMonitor(modcTaskMonitor.Adapt()); } } //else //{ // //请求失败 // modTask.IsSuccess = TaskSuccessEnum.Fail; // modTask.Information = modResponseTask.Message; // _db.Updateable(modTask).UpdateColumns(s => new { s.IsSuccess, s.Information }).ExecuteCommand(); //} } break; default: break; } } /// /// 不空跑 /// /// 操作完成的任务 /// plc连接 /// 设备信息 private static void ContinuousOperation(WcsTask modTask, PLCUtil plcConn, WcsDeviceDto modDevice) { // 查询所有待执行的任务 var listTask = _db.Queryable().Where(s => s.Status == TaskStatusEnum.Wait).ToList(); WcsTask modNextTask = null; switch (modTask.TaskType) { case TaskTypeEnum.In: { // 先找出对应排列层的入库任务 var listInTask = listTask.Where(s => s.TaskType == TaskTypeEnum.In) .Select(s => s.EndLocate.Substring(0, 6)) .ToHashSet(); // 找出库任务,对应巷道的任务 var listNextTask = listTask.Where(s => s.TaskType == TaskTypeEnum.Out && s.StartRoadway == modTask.EndRoadway).ToList(); foreach (var modNext in listNextTask) { // 如果有对应排列层的入库任务,那就不能优先执行 if (listInTask.Contains(modNext.EndLocate.Substring(0, 6))) { continue; } // todo: 写入modNext任务信息给plc Console.WriteLine($"入库任务{modTask.TaskNo}执行完成后,不空跑逻辑检测下一任务为{modNext.TaskNo}"); modNextTask = modNext; break; } } break; case TaskTypeEnum.Out: { // 先找出对应排列层的出库任务 var listInTask = listTask.Where(s => s.TaskType == TaskTypeEnum.Out) .Select(s => s.EndLocate.Substring(0, 6)) .ToHashSet(); // 找入库任务,对应巷道的任务 var listNextTask = listTask.Where(s => s.TaskType == TaskTypeEnum.In && s.StartRoadway == modTask.EndRoadway).ToList(); foreach (var modNext in listNextTask) { // 如果有对应排列层的出库任务,那就不能优先执行 if (listInTask.Contains(modNext.EndLocate.Substring(0, 6))) { continue; } // todo: 写入modNext任务信息给plc Console.WriteLine($"出库任务{modTask.TaskNo}执行完成后,不空跑逻辑检测下一任务为{modNext.TaskNo}"); modNextTask = modNext; break; } } break; case TaskTypeEnum.Move: { var modDevicePos = _db.Queryable().Where(s => s.PlcId == plcConn.PlcId && s.DeviceType == DeviceTypeEnum.Show).First(); var (result, value) = plcConn.GetPlcDBValue(modDevicePos.PosType, modDevicePos.DbNumber, modDevicePos.PlcPos); //当前堆垛机所在位置 var height = Math.Round(value / 790000d * 200).ToInt(); //todo:这里看能不能找到堆垛机所在位置在哪个排列层,优先寻找附近的任务? } break; } if (modNextTask != null) { // 获取转换后的起始排列层 06010101 PlcTaskInfo startTaskInfo = PLCCommon.GetEndPai(modTask.StartRoadway.Substring(1, 2), modTask.StartLocate.Substring(2, 2), modTask.StartLocate.Substring(0, 2), modTask.StartLocate.Substring(4, 2), modTask.StartLocate.Substring(6, 2)); // 给PLC写入任务数据 var listResult = new List(); // 任务号托盘号 var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "任务号"); listResult.Add(plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo)); var modPosPalletNo = modDevice.listStation.FirstOrDefault(s => s.Text == "托盘码"); listResult.Add(plcConn.SetPlcDBValue(modPosPalletNo.PosType, modDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo)); // 起始排列层 var modPosRow = modDevice.listStation.FirstOrDefault(s => s.Text == "取货排"); listResult.Add(plcConn.SetPlcDBValue(modPosRow.PosType, modDevice.DbNumber, modPosRow.PlcPos, startTaskInfo.EndPai)); var modPosColumn = modDevice.listStation.FirstOrDefault(s => s.Text == "取货列"); listResult.Add(plcConn.SetPlcDBValue(modPosColumn.PosType, modDevice.DbNumber, modPosColumn.PlcPos, startTaskInfo.EndLie)); var modPosStorey = modDevice.listStation.FirstOrDefault(s => s.Text == "取货层"); listResult.Add(plcConn.SetPlcDBValue(modPosStorey.PosType, modDevice.DbNumber, modPosStorey.PlcPos, startTaskInfo.EndCeng)); // 目标放货工位(固定排列层) PlcTaskInfo taskInfo = PLCCommon.GetCTaskInfo(modTask.EndLocate, ((int)modTask.TaskType).ToString(), modTask.StartRoadway, modTask.EndRoadway); var modPosEndRow = modDevice.listStation.FirstOrDefault(s => s.Text == "放货排"); listResult.Add(plcConn.SetPlcDBValue(modPosEndRow.PosType, modDevice.DbNumber, modPosEndRow.PlcPos, taskInfo.EndPai)); var modPosEndColumn = modDevice.listStation.FirstOrDefault(s => s.Text == "放货列"); listResult.Add(plcConn.SetPlcDBValue(modPosEndColumn.PosType, modDevice.DbNumber, modPosEndColumn.PlcPos, taskInfo.EndLie)); var modPosEndStorey = modDevice.listStation.FirstOrDefault(s => s.Text == "放货层"); listResult.Add(plcConn.SetPlcDBValue(modPosEndStorey.PosType, modDevice.DbNumber, modPosEndStorey.PlcPos, taskInfo.EndCeng)); // 是否写入成功 if (listResult.All(s => s.IsSucceed)) { // 写入跺机任务下发完成 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "830"); // 将移库任务待执行改为正在执行 _db.Updateable() .SetColumns(s => s.Status == TaskStatusEnum.Doing) .Where(s => s.Id == modTask.Id) .ExecuteCommand(); HubUtil.PublicTask(modTask.Adapt()); WcsTaskMonitor modInsertTaskMonitor; if (string.IsNullOrEmpty(taskInfo.EndStation)) { // 同巷道移库 modInsertTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = modDevice.Id, PlcName = modDevice.Text, InteractiveMsg = $"写入指令:{modTask.StartLocate}储位====》{modTask.EndLocate}储位。", PalletNo = modTask.PalletNo, Status = TaskStatusEnum.Complete, StartLocat = modTask.StartLocate, EndLocat = modTask.EndLocate, }; } else { // 出库任务 跨巷道移库 modInsertTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = modDevice.Id, PlcName = modDevice.Text, InteractiveMsg = $"写入指令:{modTask.StartLocate}储位====》{taskInfo.EndStation}工位。", PalletNo = modTask.PalletNo, Status = TaskStatusEnum.Complete, StartLocat = modTask.StartLocate, EndLocat = modTask.EndLocate, }; } // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); //下发任务日志 HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); //修改led屏信息 //LedDisplay(modDevice.LedIP, "工位:" + modTask.EndLocate, "出库中 " + $"储位地址:{modTask.StartLocate}", "托盘号:" + modTask.PalletNo); } } } /// /// 输送线业务处理 /// /// private static void ConveyorLine(WcsDeviceDto modDevice) { var plcConn = modDevice.PLCUtil; // 获取楼层数ceshi var louCeng = PLCCommon.GetRoadwayByStationNew(modDevice.StationNum); if (louCeng == "") { return; } var ledText = ""; switch (modDevice.Value.ToString()) { case "320": { // 申请巷道 string strMsg = ""; string taskModel = ""; // 获取工位托盘码信息 var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码"); var (res, palletVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos); if (!res.IsSucceed) { break; } var modPosEndLocat = modDevice.listStation.FirstOrDefault(s => s.Text == "目的工位"); //判断入库锁定是否打开 if (PLCTaskAction.boEnterLock) { var (res350, palletVal350) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos); if (res350.IsSucceed && palletVal350 != "350") { ledText += $"申请入库失败\n\n"; ledText += $"托盘号:{palletVal}\n"; ledText += $"入库任务已锁定,请解锁后重试!\n"; LedDisplay(modDevice.LedIP, ledText); } // 写入输送线退回指令 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modPosEndLocat.PlcPos, modDevice.StationNum); if (ret.IsSucceed) { plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "350"); } break; } if (palletVal == null) { var (res350, palletVal350) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos); if (res350.IsSucceed && palletVal350 != "350") { ledText += $"申请入库失败\n\n"; ledText += $"托盘号:{palletVal}\n"; ledText += $"扫描托盘号失败!\n"; LedDisplay(modDevice.LedIP, ledText); } // 写入输送线退回指令 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modPosEndLocat.PlcPos, modDevice.StationNum); if (ret.IsSucceed) { plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "350"); } break; } var http = new HttpService(); string TaskNo = "", EndLocate = ""; //根据工位判断是否为叠托机工位申请空托盘跺入库,是:向WMS申请空托盘跺组托 string groupMsg = ""; if (modDevice.StationNum == "27") { var (res2,Qty) = plcConn.GetPlcDBValue(PLCDataTypeEnum.Short,"DB135","0");//获取叠托机叠托数量 groupMsg = http.BindPlnInHouseWcs(Qty.ToString(), palletVal); if (groupMsg.Contains("-1")) { var (res350, palletVal350) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos); if (res350.IsSucceed && palletVal350 != "350") { ledText += $"申请入库失败\n\n"; ledText += $"托盘号:{palletVal}\n"; ledText += $"{strMsg}\n"; LedDisplay(modDevice.LedIP, ledText); } // 写入输送线退回指令 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modPosEndLocat.PlcPos, modDevice.StationNum); if (ret.IsSucceed) { plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "350"); } break; } } string IsBale = "0"; strMsg = http.RequestRoadWay(palletVal, modDevice.StationNum, taskModel, louCeng, ref EndLocate, ref TaskNo); if (!strMsg.Contains("-1")) { // 根据任务号获取起始工位地址,根据起始工位地址获取LEDIP 推送到LED屏幕。 var taskInfo = _db.Queryable().First(w => w.TaskNo == TaskNo); modDevice.LedIP = _db.Queryable().Where(w => w.StationNum == taskInfo.StartLocate).Select(s => s.LedIP).First(); // 写入330 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "330"); if (ret.IsSucceed) { // 插入任务明细 var modInsertTaskMonitor = new WcsTaskMonitor() { TaskNo = TaskNo, PlcId = modDevice.Id, PlcName = modDevice.Text, InteractiveMsg = $"写入指令330:{modDevice.StationNum}工位申请巷道", PalletNo = palletVal, Status = TaskStatusEnum.Complete, StartLocat = modDevice.StationNum, EndLocat = EndLocate, }; // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); //判断是否裹包 var gbPos = modDevice.listStation.FirstOrDefault(s => s.Text == "Element_1"); strMsg = new HttpService().RequestPackWcs(palletVal); if (strMsg == "1") { //写入裹包指令 ret = plcConn.SetPlcDBValue(gbPos.PosType, modDevice.DbNumber, gbPos.PlcPos, "2"); } else { ret = plcConn.SetPlcDBValue(gbPos.PosType, modDevice.DbNumber, gbPos.PlcPos, "1"); } // 通知任务界面任务已存在更新 请更新界面 HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); // led显示内容 try { //ledText += $"任务类型:{taskInfo.TaskType.GetDescription()}\n\n"; //ledText += $"任务号:{taskInfo.TaskNo}\n"; //ledText += $"托盘号:{taskInfo.PalletNo}\n\n"; //ledText += $"起始位:{taskInfo.StartRoadway + " " + taskInfo.StartLocate}\n"; //ledText += $"目标位:{taskInfo.EndRoadway + " " + taskInfo.EndLocate}"; ledText += $"名称:{taskInfo.SkuName}\n"; ledText += $"批号:{taskInfo.LotNo}\n"; ledText += $"入库数量:{taskInfo.Qty}\n"; ledText += $"托盘号:{taskInfo.PalletNo}\n\n"; LedDisplay(modDevice.LedIP, ledText); } catch (Exception ex) { Log.Error(ex.Message); } } } else { var (res350, palletVal350) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos); if (res350.IsSucceed && palletVal350 != "350") { ledText += $"申请入库失败\n\n"; ledText += $"托盘号:{palletVal}\n"; ledText += $"{strMsg}\n"; LedDisplay(modDevice.LedIP, ledText); } // 写入输送线退回指令 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modPosEndLocat.PlcPos, modDevice.StationNum); if (ret.IsSucceed) { plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "350"); } } } break; case "330": { // 写入任务 托盘移动 340 // 获取工位托盘码信息 var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码"); var (res, palletVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos); if (!res.IsSucceed) { break; } string pallet = palletVal.ToString(); // 获取任务信息 var modTask = _db.Queryable().First(s => s.IsDelete == false && s.PalletNo == pallet && (s.Status == TaskStatusEnum.Wait || s.Status == TaskStatusEnum.Doing) && s.TaskType == TaskTypeEnum.In); if (modTask == null) { // 此托盘没有对应的转移任务 led显示 break; } //判断入库锁定是否打开 if (PLCTaskAction.boEnterLock) { break;//入库锁定打开则不执行入库任务 } // 获取巷道口入库工位 string endLocatVlue = PLCCommon.RoadwayToStationNum(modTask.EndRoadway, louCeng); // 给PLC写入任务数据 var listResult = new List(); // 任务号、任务类型、托盘号 var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "任务号"); listResult.Add(plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo)); var modPosTaskType = modDevice.listStation.FirstOrDefault(s => s.Text == "任务类型"); var taskTypeStr = (int)modTask.TaskType; listResult.Add(plcConn.SetPlcDBValue(modPosTaskType.PosType, modDevice.DbNumber, modPosTaskType.PlcPos, taskTypeStr.ToString())); var modPosPalletNo = modDevice.listStation.FirstOrDefault(s => s.Text == "托盘码"); listResult.Add(plcConn.SetPlcDBValue(modPosPalletNo.PosType, modDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo)); // 起始工位、目的工位 var modPosStrLocat = modDevice.listStation.FirstOrDefault(s => s.Text == "起始工位"); listResult.Add(plcConn.SetPlcDBValue(modPosStrLocat.PosType, modDevice.DbNumber, modPosStrLocat.PlcPos, modDevice.StationNum)); var modPosEndLocat = modDevice.listStation.FirstOrDefault(s => s.Text == "目的工位"); listResult.Add(plcConn.SetPlcDBValue(modPosEndLocat.PosType, modDevice.DbNumber, modPosEndLocat.PlcPos, endLocatVlue)); if (listResult.All(s => s.IsSucceed)) { // 将任务状态变更为正在执行 _db.Updateable() .SetColumns(s => s.Status == TaskStatusEnum.Doing) .Where(s => s.Id == modTask.Id) .ExecuteCommand(); // 写入流程字 330 340 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "340"); // 根据任务号获取起始工位地址,根据起始工位地址获取LEDIP 推送到LED屏幕。 modDevice.LedIP = _db.Queryable().Where(w => w.StationNum == modTask.StartLocate).Select(s => s.LedIP).First(); if (ret.IsSucceed) { // 插入任务明细 var modInsertTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = modDevice.Id, PlcName = modDevice.Text, InteractiveMsg = $"写入指令340:{modDevice.StationNum}储位====》{endLocatVlue}工位", PalletNo = palletVal, Status = TaskStatusEnum.Complete, StartLocat = modDevice.StationNum, EndLocat = endLocatVlue, }; // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); // 通知任务界面任务已存在更新 请更新界面 HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); } } } break; case "620": { // 申请储位 更新入库任务(储位地址) 630 var strMsg = ""; var taskModel = ""; // 判断是否演示模式 if (PLCTaskAction.boDemo) { // 演示模式 taskModel = "1"; } // 根据工位号获取巷道号 var roadway = PLCCommon.GetRoadwayByStation(modDevice.StationNum); if (roadway == "") { break; } // 获取工位托盘码信息 var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码"); var (res, palletVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos); if (!res.IsSucceed) { break; } var http = new HttpService(); string TaskNo = ""; // 向WMS申请储位信息 strMsg = http.RequestLocate(palletVal, modDevice.StationNum, taskModel, roadway, ref TaskNo); if (!strMsg.Contains("-1")) { // 根据任务号获取起始工位地址,根据起始工位地址获取LEDIP 推送到LED屏幕。 var taskInfo = _db.Queryable().First(w => w.TaskNo == TaskNo); modDevice.LedIP = _db.Queryable().Where(w => w.StationNum == taskInfo.StartLocate).Select(s => s.LedIP).First(); // 写入流程字 630 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "630"); if (ret.IsSucceed) { // 插入任务明细 var modInsertTaskMonitor = new WcsTaskMonitor() { TaskNo = TaskNo, PlcId = modDevice.Id, PlcName = modDevice.Text, InteractiveMsg = $"写入指令340:{modDevice.StationNum}工位申请储位", PalletNo = palletVal, Status = TaskStatusEnum.Complete, StartLocat = modDevice.StationNum, EndLocat = strMsg, }; // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); // 通知任务界面任务已存在更新 请更新界面 HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); var ledDevice = PLCTaskAction.plcDevices.First(m => m.StationNum == modDevice.StationNum && m.IsDelete == false && m.DeviceType == DeviceTypeEnum.Business); //ledText += $"任务类型:{taskInfo.TaskType.GetDescription()}\n\n"; //ledText += $"任务号:{taskInfo.TaskNo}\n"; //ledText += $"托盘号:{taskInfo.PalletNo}\n\n"; //ledText += $"起始位:{taskInfo.StartRoadway + " " + taskInfo.StartLocate}\n"; //ledText += $"目标位:{taskInfo.EndRoadway + " " + taskInfo.EndLocate}"; ledText += $"名称:{taskInfo.SkuName}\n\n"; ledText += $"批号:{taskInfo.LotNo}\n"; ledText += $"入库数量:{taskInfo.Qty}\n"; ledText += $"托盘号:{taskInfo.PalletNo}\n\n"; LedDisplay(modDevice.LedIP, ledText); } } else { // 申请储位失败!LED显示 Log.Error(string.Format($"申请储位失败:{strMsg},读写plc错误")); // led显示内容 var ledDevice = PLCTaskAction.plcDevices.First(m => m.StationNum == modDevice.StationNum && m.IsDelete == false && m.DeviceType == DeviceTypeEnum.Business); ledText += $"申请入库失败\n\n"; ledText += $"{strMsg}\n"; LedDisplay(modDevice.LedIP, ledText); } } break; case "630": { #region 写入跺机取货任务 640 // 获取工位托盘码信息 var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码"); var (res, palletVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos); // 获取工位任务号信息 var modPosTaskNo = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号"); var (taskRes, taskNoVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosTaskNo.PlcPos); if (!res.IsSucceed || !taskRes.IsSucceed) { break; } string pallet = palletVal.ToString(); string taskNo = taskNoVal.ToString(); // 获取任务信息 var modTask = _db.Queryable().First(s => s.IsDelete == false && s.PalletNo == pallet && s.Status == TaskStatusEnum.Doing && s.TaskType == TaskTypeEnum.In && s.TaskNo == taskNo); if (modTask == null) { // 此托盘没有对应的转移任务 led显示 break; } var sInfo = PLCCommon.GetStokePlc(modTask.EndRoadway, louCeng); if (string.IsNullOrWhiteSpace(sInfo.Ip)) { //需加上LED显示 Log.Error(string.Format($"根据巷道获取跺机IP失败,请联系管理员")); break; } // 跺机连接 var plcStackeConn = PLCTaskAction.listPlcConn.First(m => m.PlcIP == sInfo.Ip); if (plcStackeConn.Connected) { // 目标排列层 var endLocate = modTask.EndLocate; if (string.IsNullOrWhiteSpace(modTask.EndLocate)) { Log.Error(string.Format($"目标位置为空,请人工处理,读写plc错误")); break; } // 转换目标工位排列层 03010301 var paiVal = PLCCommon.GetDjAdress(modTask.EndRoadway.Substring(1, 2), endLocate.Substring(0, 2), endLocate.Substring(6, 2)); string pai = paiVal.ToString(); string lie = int.Parse(endLocate.Substring(2, 2)).ToString(); string ceng = int.Parse(endLocate.Substring(4, 2)).ToString(); var djmodel = _db.Queryable().First(m => m.IP == sInfo.Ip); var djMod = PLCTaskAction.plcDevices.First(m => m.PlcId == djmodel.Id && m.DeviceType == DeviceTypeEnum.Business && m.IsDelete == false); var djInfos = PLCTaskAction.plcPositions.Where(m => m.IsDelete == false && m.DeviceId == djMod.Id).ToList(); var djInfo = djInfos.First(m => m.Text == "PLC流程字"); // 获取跺机当前状态 var (djRes, djVal) = plcStackeConn.GetPlcDBValue(djMod.PosType, djMod.DbNumber, djMod.PlcPos); if (!djRes.IsSucceed || djVal.ToString() != "820") { // 跺机非空闲等待 break; } // 给PLC写入任务数据 var listResult = new List(); // 任务号、任务类型、托盘号 var modPosTask = djInfos.FirstOrDefault(s => s.Text == "任务号"); listResult.Add(plcStackeConn.SetPlcDBValue(modPosTask.PosType, djMod.DbNumber, modPosTask.PlcPos, modTask.TaskNo)); var modPosTaskType = djInfos.FirstOrDefault(s => s.Text == "任务类型"); var taskTypeStr = (int)modTask.TaskType; listResult.Add(plcStackeConn.SetPlcDBValue(modPosTaskType.PosType, djMod.DbNumber, modPosTaskType.PlcPos, taskTypeStr.ToString())); var modPosPalletNo = djInfos.FirstOrDefault(s => s.Text == "托盘码"); listResult.Add(plcStackeConn.SetPlcDBValue(modPosPalletNo.PosType, djMod.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo)); //起始工位 var modPosStrStationNum = djInfos.FirstOrDefault(s => s.Text == "起始工位"); listResult.Add(plcStackeConn.SetPlcDBValue(modPosStrStationNum.PosType, djMod.DbNumber, modPosStrStationNum.PlcPos, modDevice.StationNum)); //取货排、列、层 var modPosStrPai = djInfos.FirstOrDefault(s => s.Text == "取货排"); listResult.Add(plcStackeConn.SetPlcDBValue(modPosStrPai.PosType, djMod.DbNumber, modPosStrPai.PlcPos, sInfo.Pai)); var modPosStrLie = djInfos.FirstOrDefault(s => s.Text == "取货列"); listResult.Add(plcStackeConn.SetPlcDBValue(modPosStrLie.PosType, djMod.DbNumber, modPosStrLie.PlcPos, sInfo.Lie)); var modPosStrCeng = djInfos.FirstOrDefault(s => s.Text == "取货层"); listResult.Add(plcStackeConn.SetPlcDBValue(modPosStrCeng.PosType, djMod.DbNumber, modPosStrCeng.PlcPos, sInfo.Ceng)); //放货排、列、层 var modPosEndPai = djInfos.FirstOrDefault(s => s.Text == "放货排"); listResult.Add(plcStackeConn.SetPlcDBValue(modPosEndPai.PosType, djMod.DbNumber, modPosEndPai.PlcPos, pai)); var modPosEndLie = djInfos.FirstOrDefault(s => s.Text == "放货列"); listResult.Add(plcStackeConn.SetPlcDBValue(modPosEndLie.PosType, djMod.DbNumber, modPosEndLie.PlcPos, lie)); var modPosEndCeng = djInfos.FirstOrDefault(s => s.Text == "放货层"); listResult.Add(plcStackeConn.SetPlcDBValue(modPosEndCeng.PosType, djMod.DbNumber, modPosEndCeng.PlcPos, ceng)); if (listResult.All(s => s.IsSucceed)) { // 写入跺机 830 var retc2 = plcStackeConn.SetPlcDBValue(djMod.PosType, djMod.DbNumber, djMod.WcsPos, "830"); // 插入任务明细 任务明细实体类 var modInsertTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = modDevice.Id, PlcName = modDevice.Text, PalletNo = modTask.PalletNo, Status = TaskStatusEnum.Complete, StartLocat = modDevice.StationNum, EndLocat = modTask.EndLocate // 目标储位地址 }; if (!retc2.IsSucceed) { modInsertTaskMonitor.InteractiveMsg = $"输送线取货工位:{modDevice.StationNum},写入垛机取货任务830失败等待再次写入"; // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); //下发任务日志 HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); break; } modInsertTaskMonitor.InteractiveMsg = $"跺机写入指令830:{modDevice.StationNum}工位====》" + modTask.EndLocate + "储位地址!"; // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); if (PLCTaskAction.boRefresh) { //下发任务日志 HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); } } } #endregion } break; #region 出库交互 case "420": { #region 托盘到达拣选工位/出库口 // 出库口 // led显示托盘信息 // 写入430 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "430"); if (ret.IsSucceed) { var modPosTask = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号"); var (res, taskVal) = plcConn.GetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos); var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码"); var (res2, palletVal) = plcConn.GetPlcDBValue(modPosPallet.PosType, modDevice.DbNumber, modPosPallet.PlcPos); var modPosStarStationNum = modDevice.listStation.FirstOrDefault(m => m.Text == "起始工位"); var (res3, starVal) = plcConn.GetPlcDBValue(modPosStarStationNum.PosType, modDevice.DbNumber, modPosStarStationNum.PlcPos); string tasknoVal = taskVal.ToString(); ////string b = taskVal.GetValue(); //string a = palletVal.ToString(); // 插入任务明细 var modInsertTaskMonitor = new WcsTaskMonitor() { TaskNo = taskVal, PlcId = modDevice.Id, PlcName = modDevice.Text, InteractiveMsg = $"写入指令430:托盘到达{modDevice.StationNum}工位", PalletNo = palletVal, Status = TaskStatusEnum.Complete, StartLocat = starVal.ToString(), EndLocat = modDevice.StationNum, }; // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); // 通知任务界面任务已存在更新 请更新界面 HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); // 根据任务号获取起始工位地址,根据起始工位地址获取LEDIP 推送到LED屏幕。 var taskInfo = _db.Queryable().First(w => w.TaskNo == modInsertTaskMonitor.TaskNo); modDevice.LedIP = _db.Queryable().Where(w => w.StationNum == taskInfo.EndLocate).Select(s => s.LedIP).First(); // led显示内容 // 根据目标工位号获取对应的LEDIP地址 var ledDevice = PLCTaskAction.plcDevices.First(m => m.StationNum == modDevice.StationNum && m.IsDelete == false && m.DeviceType == DeviceTypeEnum.Business && m.PlcId == modDevice.PlcId); ledText += $"出库完成\n\n"; //ledText += $"任务号:{taskInfo.TaskNo}\n"; //ledText += $"托盘号:{taskInfo.PalletNo}\n\n"; //ledText += $"起始位:{taskInfo.StartRoadway + " " + taskInfo.StartLocate}\n"; //ledText += $"目标位:{taskInfo.EndRoadway + " " + taskInfo.EndLocate}"; ledText += $"名称:{taskInfo.SkuName}\n"; ledText += $"批号:{taskInfo.LotNo}\n"; ledText += $"出库数量:{taskInfo.Qty}\n"; ledText += $"分配数量:{taskInfo.CompleteQty}\n"; ledText += $"托盘号:{taskInfo.PalletNo}\n\n"; LedDisplay(ledDevice.LedIP, ledText); } // 反馈WMS出库完成 //TaskReques taskReques = new TaskReques(); //taskReques.taskNo = TaskNo; //taskReques.TaskType = "1"; //taskReques.TaskStatus = "2"; //bool bl = wcsMySql.RequestTasks(taskReques); #endregion } break; case "440": { #region 拣选完成,托盘离开工位 // 写入450 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "450"); if (ret.IsSucceed) { var modPosTask = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号"); var (res, taskVal) = plcConn.GetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos); var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码"); var (res2, palletVal) = plcConn.GetPlcDBValue(modPosPallet.PosType, modDevice.DbNumber, modPosPallet.PlcPos); var modPosStarStationNum = modDevice.listStation.FirstOrDefault(m => m.Text == "起始工位"); var (res3, starVal) = plcConn.GetPlcDBValue(modPosStarStationNum.PosType, modDevice.DbNumber, modPosStarStationNum.PlcPos); string tasknoVal = taskVal.ToString(); var modTask = _db.Queryable().First(m => m.Status == TaskStatusEnum.Doing && m.TaskNo == tasknoVal && m.IsDelete == false); if (modTask == null) { Log.Error(string.Format("输送线440:未找到对应的任务。")); break; } // 改变任务状态 modTask.Status = TaskStatusEnum.Complete; modTask.FinishDate = DateTime.Now; modTask.Levels = 999; _db.Updateable(modTask).ExecuteCommand(); HubUtil.PublicTask(modTask.Adapt()); // 插入任务明细 var modInsertTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = modDevice.Id, PlcName = modDevice.Text, InteractiveMsg = $"写入指令450:{modDevice.StationNum}出库完成", PalletNo = palletVal, Status = TaskStatusEnum.Complete, StartLocat = starVal.ToString(), EndLocat = modDevice.StationNum, }; if (modTask.Origin == "WMS") { // 反馈WMS var requestMode = new TaskRequestWMS() { TaskNo = modTask.TaskNo + modTask.EndLocate , PalletNo = modTask.PalletNo, TaskType = ((int)TaskTypeEnum.Out).ToString(), TaskStatus = ((int)TaskStatusEnum.Complete).ToString() }; HttpService httpService = new HttpService(); var modResponseTask = httpService.RequestTask(requestMode).Result; if (modResponseTask.StatusCode == 0) { modInsertTaskMonitor.InteractiveMsg += ",返回给WMS任务完成"; } else { Log.Error(string.Format("任务反馈失败:StatusCode:{0};Msg:{1}", modResponseTask.StatusCode, modResponseTask.Msg)); } } // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); // 通知任务界面任务已存在更新 请更新界面 HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); // led显示内容 var ledDevice = PLCTaskAction.plcDevices.First(m => m.StationNum == modDevice.StationNum && m.IsDelete == false && m.DeviceType == DeviceTypeEnum.Business && m.PlcId == modDevice.PlcId); ledText += $"出库完成\n\n"; //ledText += $"任务号:{modTask.TaskNo}\n"; //ledText += $"托盘号:{modTask.PalletNo}\n\n"; //ledText += $"起始位:{modTask.StartRoadway + " " + modTask.StartLocate}\n"; //ledText += $"目标位:{modTask.EndRoadway + " " + modTask.EndLocate}"; ledText += $"名称:{modTask.SkuName}\n"; ledText += $"批号:{modTask.LotNo}\n"; ledText += $"出库数量:{modTask.Qty}\n"; ledText += $"分配数量:{modTask.CompleteQty}\n"; ledText += $"托盘号:{modTask.PalletNo}\n\n"; LedDisplay(ledDevice.LedIP, ledText); } #endregion } break; #endregion #region 叫空托盘跺 case "50": // plc申请空托 { // 防止重复叫空托跺 var (res, palletVal) = plcConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos); if (palletVal != 0) { break; } // 调用WMS空托出库接口,返回出库任务存入出库表 var strMsg = ""; var http = new HttpService(); strMsg = http.IssuePlnOutHouseWcs("1", "205"); if (!strMsg.Contains("-1")) { // 写入plc流程字60 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "60"); } else { // 申请巷道失败!LED显示 Log.Error(string.Format($"工位号:{modDevice.StationNum}申请空托跺失败:{strMsg};")); } } break; case "80": // 空托盘跺已到位 { // 调用wms任务出库任务完成 // 获取跺机点位配置 var modPosTask = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号"); var (res, val) = plcConn.GetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos); // 根据任务号获取任务信息 if (res.IsSucceed) { string tasknoVal = val.ToString(); var modTask = _db.Queryable().First(m => m.Status == TaskStatusEnum.Doing && m.TaskNo == tasknoVal && m.IsDelete == false); if (modTask == null) { //Log.Error(string.Format($"工位号:{modDevice.StationNum}空托盘到达,未找到对应的任务!任务号{tasknoVal};")); break; } // 写入plc流程字90 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "90"); if (ret.IsSucceed) { // 改变任务状态 modTask.Status = TaskStatusEnum.Complete; modTask.FinishDate = DateTime.Now; modTask.Levels = 999; _db.Updateable(modTask).ExecuteCommand(); HubUtil.PublicTask(modTask.Adapt()); var modTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = modDevice.Id, PlcName = modDevice.Text, PalletNo = modTask.PalletNo, Status = TaskStatusEnum.Complete, StartLocat = modTask.StartLocate, EndLocat = modTask.EndLocate, InteractiveMsg = $"任务完成" }; if (modTask.Origin == "WMS") { // 反馈WMS var requestMode = new TaskRequestWMS() { TaskNo = modTask.TaskNo + modTask.EndLocate , PalletNo = modTask.PalletNo, TaskType = ((int)TaskTypeEnum.Out).ToString(), TaskStatus = ((int)TaskStatusEnum.Complete).ToString() }; HttpService httpService = new HttpService(); var modResponseTask = httpService.RequestTask(requestMode).Result; if (modResponseTask.StatusCode == 0) { modTaskMonitor.InteractiveMsg = "任务完成,返回给WMS任务完成"; } else { Log.Error(string.Format("任务反馈失败:StatusCode:{0};Msg:{1}", modResponseTask.StatusCode, modResponseTask.Msg)); } } // 插入交互日志 _db.Insertable(modTaskMonitor).ExecuteCommand(); //下发任务日志 HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt()); } } } break; #endregion case "10": { #region 缠膜完成 // 获取工位托盘码信息 var strMsg = ""; var http = new HttpService(); var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码"); var (res, palletVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos); //向WMS反馈托盘缠膜完成 strMsg = http.RequestPackedWcs(palletVal); if (!strMsg.Contains("-1")) { var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "11");//收到缠膜完成11 if (ret.IsSucceed) { // 插入任务明细 var modInsertTaskMonitor = new WcsTaskMonitor() { PlcId = modDevice.Id, PlcName = modDevice.Text, InteractiveMsg = $"写入指令11:{modDevice.StationNum}工位缠膜完成", PalletNo = palletVal, Status = TaskStatusEnum.Complete, StartLocat = modDevice.StationNum }; // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); } } else { } #endregion } break; case "20": { #region 是否拆膜 21:否 22:是 // 获取工位托盘码信息 var strMsg = ""; var http = new HttpService(); var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码"); var (res, palletVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos); // 获取托盘任务号 var modPosTask = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号"); var (res1, val) = plcConn.GetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos); // 根据任务号获取任务信息,目的工位是009的再向WMS发出拆膜申请 if (res1.IsSucceed) { string tasknoVal = val.ToString(); var modTask = _db.Queryable().First(m => m.Status == TaskStatusEnum.Doing && m.TaskNo == tasknoVal && m.EndLocate == "009" && m.IsDelete == false); if (modTask == null) { break; } } strMsg = http.RequestUnPackWcs(palletVal); if (!strMsg.Contains("-1")) { var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "22"); if (ret.IsSucceed) { // 插入任务明细 var modInsertTaskMonitor = new WcsTaskMonitor() { PlcId = modDevice.Id, PlcName = modDevice.Text, InteractiveMsg = $"写入指令22:{modDevice.StationNum}工位需要拆膜", PalletNo = palletVal, Status = TaskStatusEnum.Complete, StartLocat = modDevice.StationNum }; // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); } } else { var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "21"); if (ret.IsSucceed) { // 插入任务明细 var modInsertTaskMonitor = new WcsTaskMonitor() { PlcId = modDevice.Id, PlcName = modDevice.Text, InteractiveMsg = $"写入指令21:{modDevice.StationNum}工位不需要拆膜", PalletNo = palletVal, Status = TaskStatusEnum.Complete, StartLocat = modDevice.StationNum }; // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); } } #endregion } break; #region 小车可放信号 case "150": { // 获取工位任务号信息 var strMsg = ""; var http = new HttpService(); // 获取托盘任务号 var modPosTask = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号"); var (res1, val) = plcConn.GetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos); if (res1.IsSucceed) { string tasknoVal = val.ToString(); var modTask = _db.Queryable().First(m => m.Status == TaskStatusEnum.Doing && m.TaskNo == tasknoVal && m.IsDelete == false); if (modTask == null) { //读取成功后写入151 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "151");//收到可放信号后写入151 if (ret.IsSucceed) { //回传WMS可放信号 strMsg = http.RequesContinueAgv(val.ToString(), modDevice.StationNum); if (!strMsg.Contains("-1")) { // 插入任务明细 var modInsertTaskMonitor = new WcsTaskMonitor() { TaskNo = tasknoVal, PlcId = modDevice.Id, PlcName = modDevice.Text, InteractiveMsg = $"写入指令151:{modDevice.StationNum}工位可接受AGV放货入库", Status = TaskStatusEnum.Complete, StartLocat = modDevice.StationNum }; // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); } } break; } } // } break; #endregion default: break; } } /// /// AGV业务处理 /// /// private static void AGV(WcsDeviceDto modDevice) { } /// /// 叠托机业务处理 /// /// private static void PalletMachine(WcsDeviceDto modDevice) { var plcConn = modDevice.PLCUtil; switch (modDevice.Value.ToString()) { case "220": // 注释1 { } break; case "230": // 注释2 { } break; case "240": { } break; default: break; } } /// /// 件箱输送和码垛机器人业务处理 配置的是件箱输送 /// /// private static async void BoxConveyorLine(WcsDeviceDto modDevice) { var plcConn = modDevice.PLCUtil; //二楼主扫分道 if (modDevice.DbNumber == "DB101")//&& modDevice.DbNumber == "DB102"&& (modDevice.DbNumber == "DB102"||modDevice.PlcIdIP == "10.18.51.110") { // 主扫交互流程 switch (modDevice.Value.ToString()) { case "1": // 主扫申请分道 wcs写入2 { // 判断是否演示模式 true:演示模式 false:生产模式 if (PLCTaskAction.boDemo) { // 通道号 var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "通道号"); // 演示模式直接写入分道号 //Random random = new Random(); //int ranNumber = random.Next(2) == 0 ? 1 : 5; if (fendao == 1) { fendao = 5; } else { fendao = 1; } var ret = plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, fendao.ToString()); // if (ret.IsSucceed) { Log.Information(string.Format("分道成功,道号是:" + fendao)); // 写入流程控制字 2 var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2"); if (!retVal.IsSucceed) { Log.Error("演示模式写入分道号失败!"); break; } } } else { // 通道号 var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "通道号"); // 读取plc箱码 var modBoxNo = modDevice.listStation.FirstOrDefault(m => m.Text == "箱码"); var (res, boxNo) = plcConn.GetPlcDBValue(modBoxNo.PosType, modDevice.DbNumber, modBoxNo.PlcPos); if (string.IsNullOrWhiteSpace(boxNo.ToString())) { // 箱码为null写入剔除通道号 var ret = plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, "0"); if (ret.IsSucceed) { // 写入流程控制字 2 var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2"); if (retVal.IsSucceed) { Log.Error("箱码为null进行剔除"); break; } } } else { // 根据箱码获取箱内信息 string boxNoVal = boxNo.ToString(); var boxInfo = _db.Queryable().First(w => w.IsDelete == false && w.BoxNo == boxNoVal && string.IsNullOrEmpty(w.PalletNo)); if (boxInfo == null) { // 箱信息为null写入剔除通道号 var ret = plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, "0"); if (ret.IsSucceed) { // 写入流程控制字 2 var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2"); if (retVal.IsSucceed) { Log.Error("箱码为null或已绑定托盘,进行剔除。"); break; } } } // 验证是否零箱 if (boxInfo.BitBoxMark == "1") { // 是零箱直接剔除,进行人工组托 var ret = plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, "0"); if (ret.IsSucceed) { // 写入流程控制字 2 var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2"); if (retVal.IsSucceed) { Log.Error("零箱,进行剔除。"); break; } } break; } // 根据箱内品种号获取码躲绑定工位及对应的分道号 var checkTaskInfo = _db.Queryable().First(w => w.SkuNo == boxInfo.SkuNo && w.SkuName == boxInfo.SkuName && w.LotNo == boxInfo.LotNo && w.Status == "1"); if (checkTaskInfo == null) { // 判断是否关联单据 wcsordertask var orderModel = _db.Queryable() .First(m => m.SkuNo == boxInfo.SkuNo && m.Status == TaskStatusEnum.Wait && m.LotNo == boxInfo.LotNo && m.IsDelete == false); if (orderModel != null) { // 根据boxinfo表产线字段自动绑定分道(1线产品只能绑定到8道) if (boxInfo.LineNo != "一线") {// 绑定到除8道外其他道 // 获取未绑定道 var lineNoModels = _db.Queryable() .Where(m => m.Status == "0" && m.LineNo != "8" && m.RoboatType == PLCTypeEnum.RobotPalletizer).ToList(); if (lineNoModels.Count > 0) { // 获取当前物料品种号 var skuInfo = await _db.Queryable().Where(w => w.SkuNo == boxInfo.SkuNo).FirstAsync(); if (skuInfo == null) { // 此产品若没设定品规,进行剔除处理。防止堵塞件箱线 var ret = plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, "0"); if (ret.IsSucceed) { // 写入流程控制字 2 var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2"); if (retVal.IsSucceed) { Log.Error("没有空闲分道,进行剔除。"); break; } } break; } foreach (var lineNoModel in lineNoModels) { // 读取设备验证是否绑定分道 var (respg, pzNo) = plcConn.GetPlcDBValue(lineNoModel.PosType, lineNoModel.DbNumber, lineNoModel.PlcPos); if (respg.IsSucceed) { if (pzNo != 0) { // plc此分道未解绑 break; } else { // 自动绑定分道 lineNoModel.OrderNo = orderModel.OrderNo; lineNoModel.LotNo = boxInfo.LotNo; lineNoModel.SkuNo = boxInfo.SkuNo; lineNoModel.SkuName = boxInfo.SkuName; lineNoModel.Qty = 0; lineNoModel.Status = "1";//已绑定 lineNoModel.PZNo = skuInfo.PZNo; lineNoModel.FinishQty = 0; // 给PLC写入品规 var ret = plcConn.SetPlcDBValue(lineNoModel.PosType, lineNoModel.DbNumber, lineNoModel.PlcPos, skuInfo.PZNo); if (ret.IsSucceed) { //写入流程字成功后更新分拣任务 _db.Updateable(lineNoModel).ExecuteCommand(); //更新WcsOderTask表 orderModel.Status = TaskStatusEnum.Doing; _db.Updateable(orderModel).ExecuteCommand(); // Liudl 通知前端更新分拣任务 //下发分拣任务 HubUtil.PublicCheckTask(lineNoModel.Adapt()); break; } else { throw Oops.Bah("与PCL交互失败,绑定失败!"); } } } else { // 读取plc失败 break; } } } else { // 若没有空闲道,进行剔除处理。防止堵塞件箱线 var ret = plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, "0"); if (ret.IsSucceed) { // 写入流程控制字 2 var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2"); if (retVal.IsSucceed) { Log.Error("没有空闲分道,进行剔除。"); break; } } break; } } else {// 绑定到8道 // 获取未绑定道 var lineNo8Model = _db.Queryable() .First(m => m.Status == "0" && m.LineNo == "8" && m.RoboatType == PLCTypeEnum.RobotPalletizer); if (lineNo8Model != null) { // 获取当前物料品种号 var skuInfo = await _db.Queryable().Where(w => w.SkuNo == boxInfo.SkuNo).FirstAsync(); if (skuInfo == null) { // 此产品若没设定品规,进行剔除处理。防止堵塞件箱线 var ret = plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, "0"); if (ret.IsSucceed) { // 写入流程控制字 2 var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2"); if (retVal.IsSucceed) { Log.Error("没有空闲分道,进行剔除。"); break; } } break; } // 读取设备验证是否绑定分道 var (respg, pzNo) = plcConn.GetPlcDBValue(lineNo8Model.PosType, lineNo8Model.DbNumber, lineNo8Model.PlcPos); if (respg.IsSucceed) { if (pzNo != 0) { // plc此分道未解绑 break; } else { // 自动绑定分道 lineNo8Model.OrderNo = orderModel.OrderNo; lineNo8Model.LotNo = boxInfo.LotNo; lineNo8Model.SkuNo = boxInfo.SkuNo; lineNo8Model.SkuName = boxInfo.SkuName; lineNo8Model.Qty = 0; lineNo8Model.Status = "1";//已绑定 lineNo8Model.PZNo = skuInfo.PZNo; lineNo8Model.FinishQty = 0; // 给PLC写入品规 var ret = plcConn.SetPlcDBValue(lineNo8Model.PosType, lineNo8Model.DbNumber, lineNo8Model.PlcPos, skuInfo.PZNo); if (ret.IsSucceed) { //写入流程字成功后更新分拣任务 _db.Updateable(lineNo8Model).ExecuteCommand(); //更新WcsOderTask表 orderModel.Status = TaskStatusEnum.Doing; _db.Updateable(orderModel).ExecuteCommand(); // Liudl 通知前端更新分拣任务 //下发分拣任务 HubUtil.PublicCheckTask(lineNo8Model.Adapt()); break; } else { throw Oops.Bah("与PCL交互失败,绑定失败!"); } } } else { // 读取plc失败 break; } } else { // 没有空闲道,进行剔除处理。防止堵塞件箱线 var ret = plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, "0"); if (ret.IsSucceed) { // 写入流程控制字 2 var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2"); if (retVal.IsSucceed) { Log.Error("没有空闲分道,进行剔除。"); break; } } break; } } } else { // 不关联单据直接进行剔除处理 var ret = plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, "0"); if (ret.IsSucceed) { // 写入流程控制字 2 var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2"); if (retVal.IsSucceed) { Log.Error("箱码未绑定分拣任务,进行剔除。"); break; } } } } else { // 与plc交互写入分道号和流程控制字 var ret = plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, checkTaskInfo.LineNo); if (ret.IsSucceed) { // 写入流程控制字 2 var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2"); if (retVal.IsSucceed) { { // liudl 此段程序不会执行 确认后直接删除 if (modDevice.DbNumber == "DB102")//1L拆跺分拣后需要回传箱码 { var http = new HttpService(); IsBaleModel2 ret1 = http.RequestBoxno(boxNoVal); if (ret1.Success == -1) { Log.Error("箱码分拣回传失败,需要手动拣货。失败箱码:" + boxNoVal); break; } } } break; } } } } } } break; default: break; } } //一楼主扫分道 else if (modDevice.DbNumber == "DB102") { switch (modDevice.Value.ToString()) { case "1": // 1楼件箱PLC请求WCS读码 { // 读取plc箱码 var modBoxNo = modDevice.listStation.FirstOrDefault(m => m.Text == "主扫条码"); var (res, boxNo) = plcConn.GetPlcDBValue(modBoxNo.PosType, modDevice.DbNumber, modBoxNo.PlcPos); if (string.IsNullOrWhiteSpace(boxNo.ToString())) { // 箱信息为null写入剔除通道号:0 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "0"); if (ret.IsSucceed) { // 写入流程控制字 2 var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2"); if (retVal.IsSucceed) { Log.Error("箱码为null或已绑定托盘,进行剔除。"); break; } } } else { // 箱码 string boxNoVal = boxNo.ToString(); // 通道号 var modLineNo = modDevice.listStation.FirstOrDefault(m => m.Text == "通道号"); // 调用wms接口验证箱码是否可拣货并返回装车口 var http = new HttpService(); RequestloadingAddre requesModel = http.ResultBoxInfoExportWcs(boxNoVal); if (requesModel.Success != "1") { // 箱信息为null写入剔除通道号:0 var ret = plcConn.SetPlcDBValue(modLineNo.PosType, modDevice.DbNumber, modLineNo.PlcPos, "0"); if (ret.IsSucceed) { // 写入流程控制字 2 var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2"); if (retVal.IsSucceed) { Log.Error("出库分拣根据箱码获取装车口失败,进行剔除。" + requesModel.Message); break; } } } else { // 写入出库分道号 // var ret = plcConn.SetPlcDBValue(modLineNo.PosType, modDevice.DbNumber, modLineNo.PlcPos, requesModel.loadingAddre); var ret = plcConn.SetPlcDBValue(modLineNo.PosType, modDevice.DbNumber, modLineNo.PlcPos, requesModel.loadingAddre); if (ret.IsSucceed) { // 写入流程控制字 2 var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2"); if (retVal.IsSucceed) { break; } } } } }; break; case "10": // 1楼件箱PLC读码失败,WCS不做处理直接剔除手持拣货。 { }; break; default: break; } } else { // 插码交互 switch (modDevice.Value.ToString()) { case "1": // 托盘条码可读 { // 获取托盘条码配置 var modPalletNo = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘条码"); // 读取PLC托盘条码号 var (res, palletVal) = plcConn.GetPlcDBValue(modPalletNo.PosType, modDevice.DbNumber, modPalletNo.PlcPos); string palletNo = palletVal.ToString(); if (string.IsNullOrEmpty(palletNo)) { Log.Error(string.Format("{0},读取的托盘号为null", modDevice.Text)); break; } // 根据工位号将托盘号保存在分道表 var checkTaskMedel = _db.Queryable().First(m => m.Port == modDevice.StationNum && m.IsDelete == false); if (checkTaskMedel == null) { Log.Error(string.Format("根据码垛工位{0},获取分道失败!", modDevice.StationNum)); break; } checkTaskMedel.PalletNo = palletNo; var rowCount = _db.Updateable(checkTaskMedel).ExecuteCommand(); if (rowCount > 0) { // plc写入读取成功表示 2 var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "2"); if (retVal.IsSucceed) { // liudl 此处需添加 // 通知分拣码垛页更新 } } } break; case "20": // 申请插码 { // 获取托盘条码配置 var modAddCode = modDevice.listStation.FirstOrDefault(m => m.Text == "插码结果"); // 判断是否演示模式 true:演示模式 false:生产模式 if (PLCTaskAction.boDemo) { // 演示模式直接写入插码结果 1:成功 var retVal = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "1"); break; } else { // 获取箱条码 // 获取箱条码配置 var modBoxNo = modDevice.listStation.FirstOrDefault(m => m.Text == "箱条码"); var (res, boxVal) = plcConn.GetPlcDBValue(modBoxNo.PosType, modDevice.DbNumber, modBoxNo.PlcPos); string boxNo = boxVal.ToString(); if (string.IsNullOrEmpty(boxNo)) { Log.Error($"码垛工位{modDevice.StationNum},箱码为null插码失败!请人工强制结批。"); // 写入插入结果 2:插码失败 var retVal = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "2"); break; } // 验证箱码表是否存在此箱码 var boxInfo = _db.Queryable().Where(w => w.IsDelete == false && w.BoxNo == boxNo).ToList(); if (boxInfo.Count == 0) { Log.Error($"码垛工位{modDevice.StationNum},箱码{boxNo}不存在!请人工强制结批。"); // 写入插入结果 2:插码失败 var retVal = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "2"); break; } // 获取当前分道托盘号 string port = modDevice.StationNum.ToString(); var checkTaskMedel = _db.Queryable().First(m => m.Port == port && m.Status == "1"); if (checkTaskMedel == null) { Log.Error(string.Format("根据码垛工位{0},获取分道失败!", modDevice.StationNum)); break; } string palletNo = checkTaskMedel.PalletNo; if (string.IsNullOrEmpty(palletNo)) { Log.Error(string.Format("获取码垛工位{0}上的托盘号失败!", modDevice.StationNum)); break; } // 修改插码表 foreach (WcsBoxInfo item in boxInfo) { item.PalletNo = palletNo; item.UpdateTime = DateTime.Now; item.OrderCode = checkTaskMedel.OrderNo; } checkTaskMedel.Qty += boxInfo.First().QtyCount;//记录当前托盘上物料数量 _db.Updateable(checkTaskMedel).ExecuteCommand(); var rowCount = _db.Updateable(boxInfo).ExecuteCommand(); Log.Information(string.Format("插码成功,箱码是:" + boxNo, modDevice.StationNum)); if (rowCount > 0) { // 插码成功 var retVal = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "1"); //是否结批箱 //if (boxInfo[0].EndLotFlag == "1" && retVal.IsSucceed) //{ // // 触发结批 分道变为结批中 // AutoEndLot(boxInfo[0].LotNo, plcConn, "2"); //} if (retVal.IsSucceed) { //判读是否接收完工数量 var models = _db.Queryable().First(w => w.SkuNo == boxInfo.First().SkuNo && w.LotNo == boxInfo.First().LotNo); if (models.FinishQty>0) { //检查已码垛箱数(不含零箱),码垛数量与完工数量相等后自动结批:写入PLC信号——结批中 int Fqty = (int)models.FinishQty;//完工数量 int Jpqty = 0;//已码垛数量 //获取已组盘数量 var checkNum = _db.Queryable().Where(m => m.SkuNo == models.SkuNo && m.LotNo == models.LotNo && m.OrderCode == checkTaskMedel.OrderNo).ToList();//组盘表箱码信息 if (checkNum.Count > 0) { if (!string.IsNullOrEmpty(checkNum.First().BoxNo2) || !string.IsNullOrEmpty(checkNum.First().BoxNo3))//有支码 { foreach (var item in checkNum) { Jpqty = (int)(Jpqty + item.Qty); } } else//无支码 { foreach (var item in checkNum) { Jpqty = (int)(Jpqty + item.QtyCount); } } } //获取已插码数量 var checkNum2 = _db.Queryable().Where(m => m.SkuNo == models.SkuNo && m.LotNo == models.LotNo &&(m.PalletNo != null || m.PalletNo != "") && m.OrderCode == checkTaskMedel.OrderNo).ToList();//箱码表已码垛箱码信息 if (checkNum2.Count > 0) { if (!string.IsNullOrEmpty(checkNum2.First().BoxNo2) || !string.IsNullOrEmpty(checkNum2.First().BoxNo3))//有支码 { foreach (var item2 in checkNum2) { Jpqty = (int)(Jpqty + item2.Qty); } } else//无支码 { foreach (var item2 in checkNum2) { Jpqty = (int)(Jpqty + item2.QtyCount); } } } //获取零箱数量 var checkNum3 = _db.Queryable().Where(m => m.BitBoxMark == "1" && m.SkuNo == models.SkuNo && m.LotNo == models.LotNo).ToList(); if (checkNum3.Count > 0) { if (!string.IsNullOrEmpty(checkNum3.First().BoxNo2) || !string.IsNullOrEmpty(checkNum3.First().BoxNo3))//有支码 { foreach (var item3 in checkNum3) { Jpqty = (int)(Jpqty + item3.Qty); } } else//无支码 { foreach (var item3 in checkNum3) { Jpqty = (int)(Jpqty + item3.QtyCount); } } } if (Jpqty == Fqty) { // 触发结批 分道变为结批中 AutoEndLot(boxInfo[0].LotNo, plcConn, "2"); } } } } else { // 插码失败 Log.Error($"箱码{boxNo};码垛工位{modDevice.StationNum},插码失败,请强制结批"); var retVal = plcConn.SetPlcDBValue(modAddCode.PosType, modDevice.DbNumber, modAddCode.PlcPos, "2"); if (retVal.IsSucceed) { // 触发结批 不解绑分道 AutoEndLot(boxInfo[0].LotNo, plcConn, "1"); } } } } break; case "40": // 请求组托,申请入库 { lock (OLock) { // 根据工位号,获取托盘号 var checkTaskMedel = _db.Queryable().First(m => m.Port == modDevice.StationNum && m.IsDelete == false); // 根据工位号获取 托盘线该工位号的配置信息 var numModel = PLCTaskAction.plcDevices.First(m => m.StationNum == modDevice.StationNum && m.IsDelete == false && m.DeviceType == DeviceTypeEnum.Business && m.PlcId != modDevice.PlcId); var posModel = PLCTaskAction.plcPositions.First(m => m.DeviceId == numModel.Id && m.Text == "目的工位" && m.IsDelete == false); if (checkTaskMedel == null) { Log.Error(string.Format("组托失败根据码垛工位{0},获取托盘号失败!", modDevice.StationNum)); // 写入交互工位目标地址 var retVal = plcConn.SetPlcDBValue(posModel.PosType, numModel.DbNumber, posModel.PlcPos, "234"); if (retVal.IsSucceed) { // 写入组托回复流程字 retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "50"); } break; } // 码垛工位托盘号 string palletNo = checkTaskMedel.PalletNo; // 是否演示模式 if (PLCTaskAction.boDemo) { // 直接箱wms申请巷道 var http = new HttpService(); string TaskNo = "", EndLocate = ""; string strMsg = http.RequestRoadWay(palletNo, modDevice.StationNum, "1", "2", ref EndLocate, ref TaskNo); if (strMsg.Contains("-1")) { Log.Error(string.Format("申请巷道失败,码垛工位{0};原因{1}", modDevice.StationNum, strMsg)); break; } else { // 获取入库任务信息 var taskModel = _db.Queryable().First(m => m.TaskNo == TaskNo && m.IsDelete == false && (m.Status == TaskStatusEnum.Wait || m.Status == TaskStatusEnum.Doing)); if (taskModel != null) { // 获取入库取货工位 string endLocatVlue = PLCCommon.RoadwayToStationNum(taskModel.EndRoadway, "2"); var listResult = new List(); // 写入托盘输送线码垛工位 目的工位、任务号,写入交互流程组托成功 执行入库{若需要可以写入任务号等等其他信息} listResult.Add(plcConn.SetPlcDBValue(posModel.PosType, numModel.DbNumber, posModel.PlcPos, endLocatVlue)); // 目标工位 var modPosTask = PLCTaskAction.plcPositions.First(s => s.DeviceId == numModel.Id && s.Text == "任务号" && s.IsDelete == false); listResult.Add(plcConn.SetPlcDBValue(modPosTask.PosType, numModel.DbNumber, modPosTask.PlcPos, TaskNo)); var modPosTaskType = PLCTaskAction.plcPositions.First(s => s.DeviceId == numModel.Id && s.Text == "任务类型" && s.IsDelete == false); var taskTypeStr = (int)taskModel.TaskType; listResult.Add(plcConn.SetPlcDBValue(modPosTaskType.PosType, numModel.DbNumber, modPosTaskType.PlcPos, taskTypeStr.ToString())); if (listResult.All(s => s.IsSucceed)) { // 写入组托回复流程字 var retVal1 = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "50"); if (retVal1.IsSucceed) { // 将入库任务由正在执行改为正在执行 taskModel.Status = TaskStatusEnum.Doing; _db.Updateable(taskModel).ExecuteCommand(); // 插入任务明细 var modInsertTaskMonitor = new WcsTaskMonitor() { TaskNo = TaskNo, PlcId = modDevice.Id, PlcName = modDevice.Text, InteractiveMsg = $"写入指令50:申请巷道成功", PalletNo = palletNo, Status = TaskStatusEnum.Complete, StartLocat = modDevice.StationNum, EndLocat = strMsg, }; // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); // 通知任务界面任务已存在更新 请更新界面 HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); } } //// 写入托盘输送线码垛工位 目的工位,写入交互流程组托成功 执行入库{若需要可以写入任务号等等其他信息} //var retVal = plcConn.SetPlcDBValue(posModel.PosType, numModel.DbNumber, posModel.PlcPos, endLocatVlue); //if (retVal.IsSucceed) //{ // // 写入码垛交互-组托回复流程字 // retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "50"); // // 将入库任务由正在执行改为正在执行 // taskModel.Status = TaskStatusEnum.Doing; // _db.Updateable(taskModel).ExecuteCommand(); //} } } } else { // 根据托盘号,将组托信息插入boxinfolog表 并删除boxinfo表数据 var boxInfoList = _db.Queryable().Where(w => w.IsDelete == false && w.PalletNo == palletNo).ToList(); if (boxInfoList.Count <= 0) { Log.Error(string.Format("申请巷道失败,码垛工位{0},箱码信息不存在", modDevice.StationNum)); // 写入交互工位目标地址 var retVal = plcConn.SetPlcDBValue(posModel.PosType, numModel.DbNumber, posModel.PlcPos, "234"); if (retVal.IsSucceed) { // 写入组托回复流程字 retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "50"); } break; } //判断托盘上的箱码是否已组盘 foreach (var item in boxInfoList) { var groupBoxno = _db.Queryable().Where(w => w.BoxNo == item.BoxNo).ToList(); if (groupBoxno.Count>0) { Log.Error(string.Format("申请巷道失败,码垛工位{0},箱码信息不存在", modDevice.StationNum)); // 写入交互工位目标地址 var retVal = plcConn.SetPlcDBValue(posModel.PosType, numModel.DbNumber, posModel.PlcPos, "234"); if (retVal.IsSucceed) { // 写入组托回复流程字 retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "50"); } break; } } // 组托成功后将信息存到log表 string sqlStr = $"insert into WCSBoxInfoLog select * from WCSBoxInfo where IsDelete=0 and PalletNo='{palletNo}'"; int insertCount = _db.Ado.ExecuteCommand(sqlStr); if (insertCount > 0) { string sqlStr2 = $"delete from WCSBoxInfo where IsDelete=0 and PalletNo='{palletNo}'"; _db.Ado.ExecuteCommand(sqlStr2); } //组盘成功后清空分拣表当前托盘上物料数量 checkTaskMedel.Qty = 0; _db.Updateable(checkTaskMedel).ExecuteCommand(); // 向WMS申请巷道 var http = new HttpService(); string TaskNo = "", EndLocate = ""; string strMsg = http.BindRequestRoadWay(checkTaskMedel.OrderNo, palletNo, checkTaskMedel.Qty.ToDecimal(), "0", checkTaskMedel.SkuNo, checkTaskMedel.LotNo, "", "", boxInfoList, modDevice.StationNum, "1", "2", ref EndLocate, ref TaskNo); if (strMsg.Contains("-1")) { Log.Error(string.Format("申请巷道失败,码垛工位{0};原因{1}", modDevice.StationNum, strMsg)); break; } else { //判断是否结批中 var (res, jiepi) = plcConn.GetPlcDBValue(checkTaskMedel.PosType, modDevice.DbNumber, checkTaskMedel.PosLot); if (jiepi == 2)//结批中 { // 分道解绑,抓箱品种写入0 var ret1 = plcConn.SetPlcDBValue(checkTaskMedel.PosTypeLot, modDevice.DbNumber, checkTaskMedel.PlcPos, "0"); if (ret1.IsSucceed) { //更新入库订单 var orderTask = _db.Queryable().Where(w => w.SkuNo == checkTaskMedel.SkuNo && w.LotNo == checkTaskMedel.LotNo && w.IsDelete == false).ToList(); if (orderTask.Count >0) { foreach (var item in orderTask) { item.Status = TaskStatusEnum.Complete; _db.Updateable(item).ExecuteCommand(); } } //写入流程字成功后更新分拣任务 liudl 最后一托盘申请完入库才可清空 checkTaskMedel.OrderNo = ""; checkTaskMedel.TaskNo = ""; checkTaskMedel.LotNo = ""; checkTaskMedel.SkuNo = ""; checkTaskMedel.SkuName = ""; checkTaskMedel.BoxType = ""; checkTaskMedel.Qty = 0; checkTaskMedel.PZNo = ""; checkTaskMedel.Status = "0"; // 绑定分道 0:解绑 1:绑定 checkTaskMedel.FinishQty = 0; //更新分拣任务 _db.Updateable(checkTaskMedel).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync(); } } // 获取入库任务信息 var taskModel = _db.Queryable().First(m => m.TaskNo == TaskNo && m.IsDelete == false && m.Status == TaskStatusEnum.Wait); if (taskModel != null) { // 获取入库取货工位 string endLocatVlue = PLCCommon.RoadwayToStationNum(taskModel.EndRoadway, "2"); var listResult = new List(); // 写入托盘输送线码垛工位 目的工位、任务号,写入交互流程组托成功 执行入库{若需要可以写入任务号等等其他信息} listResult.Add(plcConn.SetPlcDBValue(posModel.PosType, numModel.DbNumber, posModel.PlcPos, endLocatVlue)); // 目标工位 var modPosTask = PLCTaskAction.plcPositions.First(s => s.DeviceId == numModel.Id && s.Text == "任务号" && s.IsDelete == false); listResult.Add(plcConn.SetPlcDBValue(modPosTask.PosType, numModel.DbNumber, modPosTask.PlcPos, TaskNo)); var modPosTaskType = PLCTaskAction.plcPositions.First(s => s.DeviceId == numModel.Id && s.Text == "任务类型" && s.IsDelete == false); var taskTypeStr = (int)taskModel.TaskType; listResult.Add(plcConn.SetPlcDBValue(modPosTaskType.PosType, numModel.DbNumber, modPosTaskType.PlcPos, taskTypeStr.ToString())); if (listResult.All(s => s.IsSucceed)) { // 写入组托回复流程字 var retVal = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "50"); if (retVal.IsSucceed) { // 将入库任务由正在执行改为正在执行 taskModel.Status = TaskStatusEnum.Doing; _db.Updateable(taskModel).ExecuteCommand(); // 插入任务明细 var modInsertTaskMonitor = new WcsTaskMonitor() { TaskNo = TaskNo, PlcId = modDevice.Id, PlcName = modDevice.Text, InteractiveMsg = $"写入指令50:申请巷道成功", PalletNo = palletNo, Status = TaskStatusEnum.Complete, StartLocat = modDevice.StationNum, EndLocat = strMsg, }; // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); // 通知任务界面任务已存在更新 请更新界面 HubUtil.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); } } } } } } } break; default: break; } } } /// /// 出库件箱输送和拆垛机器人业务处理 /// /// private static void StackingRobot(WcsDeviceDto modDevice) { var plcConn = modDevice.PLCUtil; if (modDevice.DbNumber == "DB131" || modDevice.DbNumber == "DB132" || modDevice.DbNumber == "DB133" || modDevice.DbNumber == "DB134") { switch (modDevice.Value.ToString()) { case "10"://10 plc请求wcs读托盘码 20 wcs读取ok wcs 写入数量及规格 30 //wcs读取ok20 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "20"); if (ret.IsSucceed) { //获取托盘码 var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码"); var (res, palletVal) = plcConn.GetPlcDBValue(modPosPallet.PosType, modDevice.DbNumber, modPosPallet.PlcPos); // 获取托盘任务号 var modPosTask = modDevice.listStation.FirstOrDefault(m => m.Text == "任务号"); var (res1, val) = plcConn.GetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos); string tasknoVal = val.ToString(); // 根据任务号获取任务信息 if (res1.IsSucceed) { var modTask = _db.Queryable().First(m => m.TaskNo == tasknoVal && m.EndLocate == "009" && m.IsDelete == false); if (modTask == null) { Log.Error(string.Format($"出库任务未下发,请人工处理,无法拆垛!")); break; } //通过任务号和托盘号向WMS申请此托盘的拆垛信息 var http = new HttpService(); RequestBoxInfoCheckAll tasklist = http.RequestBoxCheckinfo(palletVal, tasknoVal); if (tasklist.Success != -1) { //获取拆垛物料品种(需要增加物料判断,同一个物料号可能会出现不同的码垛规则) var pz = _db.Queryable().First(m => m.SkuNo == tasklist.data.SkuNo); //下发拆托规格,拆箱数和托盘上总箱数(不绑定机器人,拆垛任务信息只下发一次) // 给PLC写入任务数据 var listResult = new List(); // 获取托盘规则 var Standard = modDevice.listStation.FirstOrDefault(m => m.Text == "规格"); listResult.Add(plcConn.SetPlcDBValue(Standard.PosType, modDevice.DbNumber, Standard.PlcPos, pz.PZNo)); //抓箱数 var qty = modDevice.listStation.FirstOrDefault(m => m.Text == "拆箱数量"); listResult.Add(plcConn.SetPlcDBValue(qty.PosType, modDevice.DbNumber, qty.PlcPos, tasklist.data.Qty.ToString())); //总箱数 var qtycount = modDevice.listStation.FirstOrDefault(m => m.Text == "总箱数"); listResult.Add(plcConn.SetPlcDBValue(qtycount.PosType, modDevice.DbNumber, qtycount.PlcPos, tasklist.data.QtyCount.ToString())); // 是否写入成功 if (listResult.All(s => s.IsSucceed)) { //wcs 写入数量及规格 30 var ret1 = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "30"); } else { Log.Error(string.Format($"码垛信息未写入!托盘号:" + palletVal + ",码垛位:" + modDevice.StationNum)); break; } } } } break; } } } /// /// Led屏展示信息 /// /// 地址 /// 上方区域 /// 中间区域 /// 底部区域 private static void LedDisplay(string ip, string top, string content, string foot) { try { LedDll Led = new LedDll(); Led.LEDstr(ip, top, content, foot); } catch (Exception ex) { Log.Error(ex.Message); } } /// /// LED信息展示 /// /// /// private static void LedDisplay(string ip,string text) { try { LedDll Led = new LedDll(); Led.ConsoleLeds(ip, text); // 设置实例 //Led.ConsoleLeds("10.18.51.238", $"任务类型:{TaskTypeEnum.Move.GetDescription()}\n\n任务号:TK2024102100001\n托盘号:LN000145\n\n起始位:033\n目标位:R01-02010102"); } catch (Exception ex) { Log.Error(ex.Message); } } /// /// 自动结批 并 解绑分道 /// /// 批次号 /// Plc连接 /// 是否解绑分道 0:解绑 1:绑定 private static void AutoEndLot(string lotNo,PLCUtil plcConn,string status) { try { if (string.IsNullOrWhiteSpace(lotNo)) { Console.WriteLine("批次号为nul"); } var checkTaskList = _db.Queryable().Where(w => w.LotNo == lotNo && w.Status == "1").ToList(); if (checkTaskList.Count <= 0) { Console.WriteLine("未找到分道绑定信息"); } foreach (var item in checkTaskList) { #region#给PLC写入结批批次号 // 写入结批信号 var ret = plcConn.SetPlcDBValue(item.PosTypeLot, item.DbNumber, item.PosLot, "1"); // 分道解绑,抓箱品种写入0 //var ret1 = plcConn.SetPlcDBValue(item.PosTypeLot, item.DbNumber, item.PlcPos, "0"); if (ret.IsSucceed) { //写入流程字成功后更新分拣任务 liudl 最后一托盘申请完入库才可清空 //item.OrderNo = ""; //item.TaskNo = ""; //item.LotNo = ""; //item.SkuNo = ""; //item.SkuName = ""; //item.BoxType = ""; //item.Qty = 0; item.PZNo = ""; item.Status = status; // 绑定分道 0:解绑 1:绑定 2:结批中 //更新分拣任务 _db.Updateable(item).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync(); } #endregion } } catch (Exception ex) { Log.Error(ex.Message); throw; } } private static void Test(WcsDeviceDto modDevice) { //var strMsg = new HttpService().RequestPackWcs("LN000001"); ////写死测试读string //var (res, val) = modDevice.PLCUtil.GetPlcDBValue(PLCDataTypeEnum.String, "DB100", "64"); //Console.WriteLine("DB100.64----" + val); ////测试批量读取 //Dictionary listaddress = new Dictionary(); //foreach (var modStation in modDevice.listStation) //{ // listaddress.Add(modStation.PlcPos, modStation.PosType); //} //var result = modDevice.PLCUtil.GetPlcBatchDBValue(listaddress); //if (result.Value.Count > 0) //{ // foreach (var value in result.Value) // { // Console.WriteLine("地址" + value.Key + "----值" + value, value); // } //} //if (!result.IsSucceed) //{ // foreach (var err in result.ErrList) // { // Console.WriteLine(err); // } // if (result.Value.Count > 0)//有错误的也有成功的 // { // } //} //if (modDevice.Value == 820) //{ // //测试写入830 // //var result = mod.PLCUtil.SetPlcDBValue(mod.PosType.Value, mod.DbNumber, mod.PlcPos, "830"); // ////写入是否成功 // //if (result.IsSucceed) // //{ // //} //} //else if (modDevice.Value == 840) //{ //} //else if (modDevice.Value == 860) //{ //} } }