using DocumentFormat.OpenXml.Bibliography; using Elastic.Clients.Elasticsearch.Tasks; using Furion.Logging; using IoTClient; using Microsoft.AspNetCore.SignalR; 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; namespace WCS.Application; public static class PLCService { private static readonly ISqlSugarClient _db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId); private static readonly IHubContext _taskLogHubContext; static PLCService() { _taskLogHubContext = App.GetService>(); } 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); break; case PLCTypeEnum.PalletMachine: PalletMachine(mod); break; case PLCTypeEnum.StackingRobot: PalletMachine(mod); break; default: break; } } catch (Exception ex) { Log.Error(ex.Message, ex); } } /// /// 跺机业务处理 /// /// private static void StackingMachine(WcsDeviceDto modDevice) { var plcConn = modDevice.PLCUtil; switch (modDevice.Value.ToString()) { case "820": // 跺机空闲,获取出库任务、移库任务 { // 获取任务信息 var modTask = _db.Queryable().OrderBy(m => m.CreateTime).OrderBy(m => m.Levels, OrderByType.Desc) .First(s => s.Status == TaskStatusEnum.Wait && (s.TaskType == TaskTypeEnum.Out || s.TaskType == TaskTypeEnum.Move) && s.StartRoadway == modDevice.StationNum); if (modTask == null) { break; } // 根据目标地址和巷道获取放货工位对应的排列层 PlcTaskInfo taskInfo = PLCCommon.GetCTaskInfo(modTask.EndLocate, 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 { break; } } else { break; } } // 获取转换后的起始排列层 PlcTaskInfo startTaskInfo = PLCCommon.GetEndPai(modTask.StartLocate.Substring(1, 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)) { // 写入跺机任务下发完成 plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "830"); // 将移库任务待执行改为正在执行 _db.Updateable() .SetColumns(s => s.Status == TaskStatusEnum.Doing) .Where(s => s.Id == modTask.Id) .ExecuteCommand(); _taskLogHubContext.Clients.All.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(); //下发任务日志 _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); //修改led屏信息 //LedDisplay(modDevice.LedIP, "工位:" + modTask.EndLocate, "出库中 " + $"储位地址:{modTask.StartLocate}", "托盘号:" + modTask.PalletNo); } } 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, modPosTask.PlcPos); if (res.IsSucceed) { // 获取任务信息 string tasknoVal = val.ToString(); var modTask = _db.Queryable().First(m => m.Status == TaskStatusEnum.Doing && m.TaskNo == tasknoVal && m.IsDelete == true); 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.String, modDevice.DbNumber, modPosStartStation.PlcPos); if (startStationRes.IsSucceed) { // 根据工位号获取对应的输送线IP var plcConveyorConn = PLCCommon.GetPlcIp(startStationVal); if (plcConveyorConn.Connected) { // 向取货工位写入流程字640 取货已完成 var ConveyorMod = PLCTaskAction.plcDevices.First(m => m.StationNum == startStationVal && m.DeviceType == DeviceTypeEnum.Business && m.IsDelete == true); var retc = plcConveyorConn.SetPlcDBValue(ConveyorMod.PosType, ConveyorMod.DbNumber, ConveyorMod.WcsPos, "640"); var modcTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = ConveyorMod.Id, PlcName = ConveyorMod.Text, PalletNo = modTask.PalletNo, Status = TaskStatusEnum.Complete, StartLocat = startStationVal, EndLocat = modTask.EndLocate // 目标储位地址 }; if (!retc.IsSucceed) { modcTaskMonitor.InteractiveMsg = string.Format("输送线取货工位:{0},写入取货完成640失败等待在次写入", startStationVal); // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); //下发任务日志 _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); break; } modcTaskMonitor.InteractiveMsg = string.Format("输送线取货工位:{0},写入取货完成640成功", startStationVal); // 插入交互日志 _db.Insertable(modcTaskMonitor).ExecuteCommand(); //下发任务日志 _taskLogHubContext.Clients.All.PublicTaskMonitor(modcTaskMonitor.Adapt()); } // 写入流程控制字 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "850"); if (!ret.IsSucceed) { break; // 写入失败跳出等待再次写入 } modInsertTaskMonitor.InteractiveMsg = string.Format("输送线取货工位:{0}跺机取货完成850成功", startStationVal); modInsertTaskMonitor.EndLocat = modTask.EndLocate; // 目标储位地址 // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); //下发任务日志 _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); } } else if (modTask.TaskType == TaskTypeEnum.Out) { // 写入流程控制字 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; // 放货工位 } 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(); //下发任务日志 _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); //修改led屏信息 //LedDisplay(modDevice.LedIP, "工位:" + modTask.EndLocate, "出库中 " + $"储位地址:{modTask.StartLocate}", "托盘号:" + modTask.PalletNo); } } 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 == true); 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(); _taskLogHubContext.Clients.All.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 TaskRequest() { TaskNo = modTask.TaskNo, PalletNo = modTask.PalletNo, TaskType = TaskTypeEnum.In, TaskStatus = TaskStatusEnum.Complete }; HttpService httpService = new HttpService(); var modResponseTask = httpService.RequestTask(requestMode).Result; if (modResponseTask.StatusCode == "0") { modcTaskMonitor.InteractiveMsg = "任务完成,返回给WMS任务完成"; } } // 插入交互日志 _db.Insertable(modcTaskMonitor).ExecuteCommand(); //下发任务日志 _taskLogHubContext.Clients.All.PublicTaskMonitor(modcTaskMonitor.Adapt()); // 此处添加不空跑业务 } 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, 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(plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo)); //任务类型 var modPosTaskType = listPos.FirstOrDefault(s => s.Text == "任务类型"); listResult.Add(plcConn.SetPlcDBValue(modPosTaskType.PosType, modDevice.DbNumber, modPosTaskType.PlcPos, ((int)modTask.TaskType).ToString())); //托盘号 var modPosPalletNo = listPos.FirstOrDefault(s => s.Text == "托盘码"); listResult.Add(plcConn.SetPlcDBValue(modPosPalletNo.PosType, modDevice.DbNumber, modPosPalletNo.PlcPos, modTask.PalletNo)); //起始工位 var modPosLocatNo = listPos.FirstOrDefault(s => s.Text == "起始工位"); listResult.Add(plcConn.SetPlcDBValue(modPosLocatNo.PosType, modDevice.DbNumber, modPosLocatNo.PlcPos, taskInfo.EndStation)); // 目标工位 var modPosEndLocatNo = listPos.FirstOrDefault(s => s.Text == "目的工位"); listResult.Add(plcConn.SetPlcDBValue(modPosEndLocatNo.PosType, modDevice.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(); //下发任务日志 _taskLogHubContext.Clients.All.PublicTaskMonitor(modcTaskMonitor.Adapt()); break; } } } //此处添加不空跑业务 } } break; case TaskTypeEnum.Move: // 移库任务 { var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "任务号"); var result = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modPosTask.PlcPos, modTask.TaskNo); if (!result.IsSucceed) { Log.Error($"{modDevice.Text}写入任务号失败"); break; } result = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "30"); if (!result.IsSucceed) { Log.Error($"{modDevice.Text}控制字写入30失败"); break; } // 改变任务状态 modTask.Status = TaskStatusEnum.Complete; modTask.FinishDate = DateTime.Now; _db.Updateable(modTask).ExecuteCommand(); //下发任务日志 _taskLogHubContext.Clients.All.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 TaskRequest() { TaskNo = modTask.TaskNo, PalletNo = modTask.PalletNo, TaskType = TaskTypeEnum.Move, TaskStatus = TaskStatusEnum.Complete }; HttpService httpService = new HttpService(); var modResponseTask = httpService.RequestTask(requestMode).Result; if (modResponseTask.StatusCode == "0") { modcTaskMonitor.InteractiveMsg = "任务完成,返回给WMS任务完成"; //修改储位信息 任务类型 执行状态 起始位置 目标位置 } } // 插入交互日志 _db.Insertable(modcTaskMonitor).ExecuteCommand(); //下发任务日志 _taskLogHubContext.Clients.All.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($"【堆垛机】当前任务号不存在对应的任务,任务号:{modTask.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(); _taskLogHubContext.Clients.All.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(); //下发任务日志 _taskLogHubContext.Clients.All.PublicTask(modTask.Adapt()); } else { //请求失败 modTask.IsSuccess = TaskSuccessEnum.Fail; modTask.Information = modResponseTask.Message; _db.Updateable(modTask).UpdateColumns(s => new { s.IsSuccess, s.Information }).ExecuteCommand(); _taskLogHubContext.Clients.All.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($"【堆垛机】当前任务号不存在对应的任务,任务号:{modTask.TaskNo}"); break; } modTask.Status = TaskStatusEnum.Exception; _db.Updateable(modTask).UpdateColumns(s => s.Status).ExecuteCommand(); _taskLogHubContext.Clients.All.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)); // 是否写入成功 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(); //下发任务日志 _taskLogHubContext.Clients.All.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; } } /// /// 输送线业务处理 /// /// private static void ConveyorLine(WcsDeviceDto modDevice) { var plcConn = modDevice.PLCUtil; // 获取楼层数 var louCeng = PLCCommon.GetRoadwayByStationNew(modDevice.StationNum); switch (modDevice.Value.ToString()) { case "320": { // 申请巷道 string strMsg = ""; string taskModel = ""; // 判断是否演示模式 if (PLCTaskAction.boDemo) { taskModel = "1";// 演示模式 } // 获取工位托盘码信息 var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码"); var (res, palletVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos); var http = new HttpService(); string TaskNo = "", EndLocate = ""; strMsg = http.RequestRoadWay(palletVal, modDevice.StationNum, taskModel, louCeng, ref EndLocate, ref TaskNo); if (!strMsg.Contains("-1")) { // 写入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(); // 通知任务界面任务已存在更新 请更新界面 if (PLCTaskAction.boRefresh) { _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); } // led更新内容 //DataRow ConveyorsRow10 = PlcInfoDt.Select($"Level = '2' and StationNum = '{EndLocat}'")[0]; //LedDisplay(ConveyorsRow10["LedIP"].ToString(), "工位:" + EndLocat, "出库中 " + $"储位地址:{StartLocat}", "托盘号:" + PalletNo); } } else { // 申请巷道失败!LED显示 Log.Error(string.Format($"申请巷道失败:{ strMsg },读写plc错误")); } } break; case "330": { // 写入任务 托盘移动 340 // 获取工位托盘码信息 var modPosPallet = modDevice.listStation.FirstOrDefault(m => m.Text == "托盘码"); var (res, palletVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosPallet.PlcPos); 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 && s.StartRoadway == modDevice.StationNum); if (modTask == null) { // 此托盘没有对应的转移任务 led显示 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 == "任务号"); listResult.Add(plcConn.SetPlcDBValue(modPosTaskType.PosType, modDevice.DbNumber, modPosTaskType.PlcPos, modTask.TaskType.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"); 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(); // 通知任务界面任务已存在更新 请更新界面 if (PLCTaskAction.boRefresh) { _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); } // led更新内容 //LedDisplay(modDevice.LedIP, "工位:" + modTask.EndLocate, "出库中 " + $"储位地址:{modTask.StartLocate}", "托盘号:" + modTask.PalletNo); } } } 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); var http = new HttpService(); string TaskNo = ""; // 向WMS申请储位信息 strMsg = http.RequestLocate(palletVal, modDevice.StationNum, taskModel, roadway, ref TaskNo); if (!strMsg.Contains("-1")) { // 写入流程字 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(); // 通知任务界面任务已存在更新 请更新界面 if (PLCTaskAction.boRefresh) { _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); } // led更新内容 //DataRow ConveyorsRow10 = PlcInfoDt.Select($"Level = '2' and StationNum = '{EndLocat}'")[0]; //LedDisplay(ConveyorsRow10["LedIP"].ToString(), "工位:" + EndLocat, "出库中 " + $"储位地址:{StartLocat}", "托盘号:" + PalletNo); } } else { // 申请储位失败!LED显示 Log.Error(string.Format($"申请储位失败:{strMsg},读写plc错误")); } } 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); 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)) { throw new Exception("根据巷道获取跺机IP失败,请联系管理员"); } // 跺机连接 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; } 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 djMod = PLCTaskAction.plcDevices.First(m => m.StationNum == modTask.EndRoadway && 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 (djVal != "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 == "任务类型"); listResult.Add(plcStackeConn.SetPlcDBValue(modPosTaskType.PosType, djMod.DbNumber, modPosTaskType.PlcPos, modTask.TaskType.ToString())); var modPosPalletNo = djInfos.FirstOrDefault(s => s.Text == "托盘号"); listResult.Add(plcStackeConn.SetPlcDBValue(modPosPallet.PosType, djMod.DbNumber, modPosPallet.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(); //下发任务日志 _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); break; } modInsertTaskMonitor.InteractiveMsg = $"跺机写入指令830:{modDevice.StationNum}工位====》" + modTask.EndLocate + "储位地址!"; // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); if (PLCTaskAction.boRefresh) { //下发任务日志 _taskLogHubContext.Clients.All.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); // 插入任务明细 var modInsertTaskMonitor = new WcsTaskMonitor() { TaskNo = taskVal, PlcId = modDevice.Id, PlcName = modDevice.Text, InteractiveMsg = $"写入指令430:托盘到达{modDevice.StationNum}工位", PalletNo = palletVal, Status = TaskStatusEnum.Complete, StartLocat = starVal, EndLocat = modDevice.StationNum, }; // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); // 通知任务界面任务已存在更新 请更新界面 if (PLCTaskAction.boRefresh) { _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); } // led更新内容 //DataRow ConveyorsRow10 = PlcInfoDt.Select($"Level = '2' and StationNum = '{EndLocat}'")[0]; //LedDisplay(ConveyorsRow10["LedIP"].ToString(), "工位:" + EndLocat, "出库中 " + $"储位地址:{StartLocat}", "托盘号:" + PalletNo); } // 反馈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); // 插入任务明细 var modInsertTaskMonitor = new WcsTaskMonitor() { TaskNo = taskVal, PlcId = modDevice.Id, PlcName = modDevice.Text, InteractiveMsg = $"写入指令450:{modDevice.StationNum}拣选完成,托盘离开工位", PalletNo = palletVal, Status = TaskStatusEnum.Complete, StartLocat = starVal, EndLocat = modDevice.StationNum, }; // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); // 通知任务界面任务已存在更新 请更新界面 if (PLCTaskAction.boRefresh) { _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt()); } // led更新内容 //DataRow ConveyorsRow10 = PlcInfoDt.Select($"Level = '2' and StationNum = '{EndLocat}'")[0]; //LedDisplay(ConveyorsRow10["LedIP"].ToString(), "工位:" + EndLocat, "出库中 " + $"储位地址:{StartLocat}", "托盘号:" + PalletNo); } #endregion } break; #endregion default: break; } } /// /// AGV业务处理 /// /// private static void AGV(WcsDeviceDto modDevice) { } /// /// 叠托机业务处理 /// /// private static void PalletMachine(WcsDeviceDto modDevice) { } /// /// 拆垛机器人业务处理 /// /// private static void StackingRobot(WcsDeviceDto modDevice) { var plcConn = modDevice.PLCUtil; switch (modDevice.Value.ToString()) { case "0": { // 若拆垛工位为空闲,查询任务表是否有未绑定的出库任务,做绑定操作 } break; default: break; } } private static void Test(WcsDeviceDto modDevice) { //写死测试读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) { } } }