Admin.NET/WCS.Application/Entity/WcsCheckTask.cs
@@ -15,11 +15,23 @@ public class WcsCheckTask : EntityBaseData { /// <summary> /// 任务号 /// </summary> [SugarColumn(ColumnName = "TaskNo", ColumnDescription = "任务号", Length = 20)] public string? TaskNo { get; set; } /// <summary> /// WMS下发单号 /// </summary> [SugarColumn(ColumnName = "OrderNo", ColumnDescription = "WMS下发单号", Length = 20)] public string? OrderNo { get; set; } /// <summary> /// 机器人类型 /// </summary> [SugarColumn(ColumnName = "RoboatType", ColumnDescription = "机器人类型", Length = 5)] public string? RoboatType { get; set; } /// <summary> /// 机器人编号 /// </summary> @@ -29,8 +41,8 @@ /// <summary> /// 分拣线编号 /// </summary> [SugarColumn(ColumnName = "LineNO", ColumnDescription = "分拣线编号", Length = 5)] public string? LineNO { get; set; } [SugarColumn(ColumnName = "LineNo", ColumnDescription = "分拣线编号", Length = 5)] public string? LineNo { get; set; } /// <summary> /// 码盘工位号 Admin.NET/WCS.Application/Entity/WcsTask.cs
@@ -113,7 +113,7 @@ /// 拣货方式 /// </summary> [SugarColumn(ColumnName = "UnstackingMode", ColumnDescription = "拣货方式", Length = 10)] public string? UnstackingMode { get; set; } public UnstackingModeEnum? UnstackingMode { get; set; } /// <summary> /// 取消时间 Admin.NET/WCS.Application/Enum/TaskEnum.cs
@@ -85,4 +85,22 @@ /// </summary> [Description("回传失败")] Fail = 1 } /// <summary> /// 拣货方式 /// </summary> [Description("拣货方式")] public enum UnstackingModeEnum { /// <summary> /// 机器拆托出 /// </summary> [Description("机器拆托出")] Machine = 0, /// <summary> /// 人工拣货出 /// </summary> [Description("人工拣货出")] Artificial = 1, } Admin.NET/WCS.Application/Model/TaskRequest.cs
@@ -4,7 +4,7 @@ { public string TaskNo { get; set; } // 任务号 public string PalletNo { get; set; } // 托盘号 public string TaskType { get; set; } // 任务类型 public TaskTypeEnum TaskType { get; set; } // 任务类型 public TaskStatusEnum TaskStatus { get; set; } // 任务状态 0 等待执行 1 正在执行 2 执行完成 3 异常结束 4 任务取消 } public class ResponseTasks Admin.NET/WCS.Application/PLC/PLCCommon.cs
@@ -1,4 +1,5 @@ using Microsoft.AspNetCore.SignalR; using Elastic.Clients.Elasticsearch.Tasks; using Microsoft.AspNetCore.SignalR; using RazorEngine.Compilation.ImpromptuInterface.Dynamic; using System; using System.Collections.Generic; @@ -215,33 +216,32 @@ /// </summary> /// <param name="startStation"></param> /// <returns></returns> public static PlcTaskInfo GetPlcIp(string startStation) public static PLCUtil GetPlcIp(string startStation) { PlcTaskInfo taskInfo = new PlcTaskInfo(); string strIp = ""; var conveyList1 = new List<string>() { "147", "145", "139", "137", "129", "127", "121", "119", "111", "109", "103", "101", "093", "091", "085", "083", "075", "073", "067", "065" }; var conveyList2 = new List<string>() { "252", "254", "260", "262", "272", "272", "278", "280", "288", "290", "294", "301", "307", "309", "315", "317", "325", "327", "331", "337" }; var conveyList3 = new List<string>() { "401", "402", "405", "406", "409", "410", "413", "414", "417", "418", "421", "422", "425", "426", "429", "430", "433", "434", "437", "438" }; if (conveyList1.Contains(startStation)) { taskInfo.Ip = "10.18.51.110"; strIp = "10.18.51.110"; } else if (conveyList2.Contains(startStation)) { taskInfo.Ip = "10.18.51.120"; strIp = "10.18.51.120"; } else if (conveyList3.Contains(startStation)) { taskInfo.Ip = "10.18.51.130"; strIp = "10.18.51.130"; } else { throw new Exception("工位未查询到"); throw Oops.Bah("工位未查询到"); } return taskInfo; var plcConveyorConn = PLCTaskAction.listPlcConn.First(m => m.PlcIP == strIp); return plcConveyorConn; } /// <summary> Admin.NET/WCS.Application/PLC/PLCService.cs
@@ -4,10 +4,12 @@ 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 @@ -53,7 +55,7 @@ /// 跺机业务处理 /// </summary> /// <param name="modDevice"></param> private static async void StackingMachine(WcsDeviceDto modDevice) private static void StackingMachine(WcsDeviceDto modDevice) { var plcConn = modDevice.PLCUtil; switch (modDevice.Value.ToString()) @@ -62,8 +64,8 @@ // 跺机空闲,获取出库任务、移库任务 { // 获取任务信息 var modTask = _db.Queryable<WcsTask>().OrderBy(m=>m.CreateTime).OrderBy(m=>m.Levels,OrderByType.Desc) .First(s => s.Status == TaskStatusEnum.Wait && (s.TaskType == TaskTypeEnum.Out || s.TaskType == TaskTypeEnum.Move) var modTask = _db.Queryable<WcsTask>().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) { @@ -71,11 +73,11 @@ } // 根据目标地址和巷道获取放货工位对应的排列层 PlcTaskInfo taskInfo = PLCCommon.GetCTaskInfo(modTask.EndLocate, modTask.TaskType.ToString(), PlcTaskInfo taskInfo = PLCCommon.GetCTaskInfo(modTask.EndLocate, modTask.TaskType.ToString(), modTask.StartRoadway, modTask.EndRoadway); // 目标工位不为null,需先判断放货工位是否空闲 if (!string.IsNullOrEmpty(taskInfo.EndStation)) if (!string.IsNullOrEmpty(taskInfo.EndStation)) { // 打开对应的输送线连接 var plcConveyorConn = PLCTaskAction.listPlcConn.First(m => m.PlcIP == taskInfo.Ip); @@ -94,12 +96,12 @@ break; } } else else { break; } } else else { break; } @@ -143,7 +145,7 @@ .SetColumns(s => s.Status == TaskStatusEnum.Doing) .Where(s => s.Id == modTask.Id) .ExecuteCommand(); _taskLogHubContext.Clients.All.PublicTask(modTask.Adapt<WcsTaskOutput>()); WcsTaskMonitor modInsertTaskMonitor; if (string.IsNullOrEmpty(taskInfo.EndStation)) { @@ -160,7 +162,7 @@ EndLocat = modTask.EndLocate, }; } else else { // 出库任务 跨巷道移库 modInsertTaskMonitor = new WcsTaskMonitor() @@ -185,7 +187,7 @@ } } break; case "840": case "840": // 取货完成 { // 获取跺机点位配置 @@ -194,11 +196,11 @@ var modPosEndStation = modDevice.listStation.FirstOrDefault(m => m.Text == "目的工位"); var (endStationRes, endStation) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosTask.PlcPos); if (res.IsSucceed) if (res.IsSucceed) { // 获取任务信息 string tasknoVal = val.ToString(); var modTask = _db.Queryable<WcsTask>().First(m => m.Status == TaskStatusEnum.Doing && m.TaskNo == tasknoVal && m.IsDelete == true); var modTask = _db.Queryable<WcsTask>().First(m => m.Status == TaskStatusEnum.Doing && m.TaskNo == tasknoVal && m.IsDelete == true); if (modTask == null) { Log.Error(string.Format("PLC控制字840:未找到对应的任务。")); @@ -209,7 +211,7 @@ { TaskNo = modTask.TaskNo, PlcId = modDevice.Id, PlcName = modDevice.Text, PlcName = modDevice.Text, PalletNo = modTask.PalletNo, Status = TaskStatusEnum.Complete, StartLocat = modTask.StartLocate, @@ -220,12 +222,11 @@ // 获取跺机起始工位点位配置,读取起始工位 var modPosStartStation = modDevice.listStation.FirstOrDefault(m => m.Text == "起始工位"); var (startStationRes, startStationVal) = plcConn.GetPlcDBValue(PLCDataTypeEnum.String, modDevice.DbNumber, modPosStartStation.PlcPos); if (startStationRes.IsSucceed) if (startStationRes.IsSucceed) { // 根据工位号获取对应的输送线IP PlcTaskInfo taskInfo = PLCCommon.GetPlcIp(startStationVal); var plcConveyorConn = PLCTaskAction.listPlcConn.First(m => m.PlcIP == taskInfo.Ip); if (plcConveyorConn.Connected) var plcConveyorConn = PLCCommon.GetPlcIp(startStationVal); if (plcConveyorConn.Connected) { // 向取货工位写入流程字640 取货已完成 var ConveyorMod = PLCTaskAction.plcDevices.First(m => m.StationNum == startStationVal @@ -241,7 +242,7 @@ StartLocat = startStationVal, EndLocat = modTask.EndLocate // 目标储位地址 }; if (!retc.IsSucceed) if (!retc.IsSucceed) { modcTaskMonitor.InteractiveMsg = string.Format("输送线取货工位:{0},写入取货完成640失败等待在次写入", startStationVal); // 插入交互日志 @@ -267,7 +268,7 @@ modInsertTaskMonitor.InteractiveMsg = string.Format("输送线取货工位:{0}跺机取货完成850成功", startStationVal); modInsertTaskMonitor.EndLocat = modTask.EndLocate; // 目标储位地址 // 插入交互日志 // 插入交互日志 _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); //下发任务日志 _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>()); @@ -286,7 +287,7 @@ modInsertTaskMonitor.InteractiveMsg = string.Format("储位地址:{0}取货完成", modTask.StartLocate); modInsertTaskMonitor.EndLocat = endStation; // 放货工位 } else else { // 写入流程控制字 var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "850"); @@ -329,7 +330,7 @@ case TaskTypeEnum.In: { var res870 = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "870"); if (!res870.IsSucceed) if (!res870.IsSucceed) { Log.Error(string.Format("跺机控制字860写入870失败!")); break; @@ -337,34 +338,172 @@ // 改变任务状态 modTask.Status = TaskStatusEnum.Complete; modTask.FinishDate = DateTime.Now; modTask.FinishDate = DateTime.Now; _db.Updateable(modTask).ExecuteCommand(); if (modTask.Origin == "WMS") _taskLogHubContext.Clients.All.PublicTask(modTask.Adapt<WcsTaskOutput>()); 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 = "1", TaskType = TaskTypeEnum.In, TaskStatus = TaskStatusEnum.Complete }; // 此处添加调用WMS接口 liudl 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<WcsTaskMonitorOutput>()); // 此处添加不空跑业务 } 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<Result>(); //任务号 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<WcsTaskMonitorOutput>()); 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<WcsTaskOutput>()); 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<WcsTaskMonitorOutput>()); // 此处添加不空跑业务 } break; default: break; @@ -379,12 +518,128 @@ 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<WcsTask>().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<WcsTaskOutput>()); Log.Information($"【堆垛机】wcs任务变更空取异常,任务号:{modTask.TaskNo}"); var modTaskRequest = modTask.Adapt<TaskRequest>(); 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<WcsTaskOutput>()); } 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<WcsTaskOutput>()); } } 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<WcsTask>().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<WcsTaskOutput>()); Log.Information($"【堆垛机】wcs任务变更满取异常,任务号:{modTask.TaskNo}"); var modTaskRequest = modTask.Adapt<TaskRequest>(); 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<Result>(); // 任务号托盘号 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<WcsTaskMonitorOutput>()); } } //else //{ // //请求失败 // modTask.IsSuccess = TaskSuccessEnum.Fail; // modTask.Information = modResponseTask.Message; // _db.Updateable(modTask).UpdateColumns(s => new { s.IsSuccess, s.Information }).ExecuteCommand(); //} } break; default: @@ -900,5 +1155,5 @@ } } Admin.NET/WCS.Application/PLC/PLCTaskAction.cs
@@ -25,7 +25,7 @@ private static List<WcsPlc> listPlc = new List<WcsPlc>(); private static List<WcsDevice> listPlcDevice = new List<WcsDevice>(); private static List<WcsPosition> listPlcStation = new List<WcsPosition>(); private static List<WcsPosition> listPlcPosition = new List<WcsPosition>(); private static List<WcsAlarmInfo> listAlarmInfo = new List<WcsAlarmInfo>(); private static List<PLCUtil> listPlcUtil = new List<PLCUtil>(); @@ -36,16 +36,14 @@ get { return listPlcUtil; } } // 交互点集合 public static List<WcsDevice> plcDevices public static List<WcsDevice> plcDevices { get { return listPlcDevice; } } // 交互点集合 public static List<WcsPosition> plcStation public static List<WcsPosition> plcPositions { get { return listPlcStation; } get { return listPlcPosition; } } public static event EventHandler DeviceValueChangeEvent; static PLCTaskAction() { @@ -64,7 +62,7 @@ cts.Cancel(); listPlc = _db.Queryable<WcsPlc>().Where(s => s.Type == PLCTypeEnum.StackingMachine || s.Type == PLCTypeEnum.ConveyorLine || s.Type == PLCTypeEnum.BoxConveyorLine).ToList(); listPlcDevice = _db.Queryable<WcsDevice>().ToList(); listPlcStation = _db.Queryable<WcsPosition>().ToList(); listPlcPosition = _db.Queryable<WcsPosition>().ToList(); listAlarmInfo = _db.Queryable<WcsAlarmInfo>().ToList(); //等待几秒钟,把已有线程取消掉再连接 //Thread.Sleep(5000); @@ -156,7 +154,7 @@ dto.Value = value; dto.Type = _modplc.Type; dto.PLCUtil = modPlcUtil; dto.listStation = listPlcStation.Where(s => s.DeviceId == modDevice.Id).ToList(); dto.listStation = listPlcPosition.Where(s => s.DeviceId == modDevice.Id).ToList(); dto.listDevice = listDevice.Where(s => s.StationNum == modDevice.StationNum && s.Level == DeviceLevelEnum.Station).ToList(); //这里触发值变更事件 DeviceValueChangeEvent?.Invoke(dto, EventArgs.Empty); Admin.NET/WCS.Application/Service/WcsCheckTask/Dto/WcsCheckTaskInput.cs
@@ -169,7 +169,7 @@ /// <summary> /// 分拣线编号 /// </summary> public string? LineNO { get; set; } public string? LineNo { get; set; } /// <summary> /// 码盘工位号 Admin.NET/WCS.Application/Service/WcsCheckTask/WcsCheckTaskService.cs
@@ -45,7 +45,7 @@ .WhereIF(!string.IsNullOrEmpty(input.SearchKey), u => u.OrderNo.Contains(input.SearchKey) || u.RoboatNo.Contains(input.SearchKey) || u.LineNO.Contains(input.SearchKey) || u.LineNo.Contains(input.SearchKey) || u.Port.Contains(input.SearchKey) || u.LotNo.Contains(input.SearchKey) || u.SkuNo.Contains(input.SearchKey) @@ -57,7 +57,7 @@ ) .WhereIF(!string.IsNullOrWhiteSpace(input.OrderNo), u => u.OrderNo.Contains(input.OrderNo.Trim())) .WhereIF(!string.IsNullOrWhiteSpace(input.RoboatNo), u => u.RoboatNo.Contains(input.RoboatNo.Trim())) .WhereIF(!string.IsNullOrWhiteSpace(input.LineNO), u => u.LineNO.Contains(input.LineNO.Trim())) .WhereIF(!string.IsNullOrWhiteSpace(input.LineNo), u => u.LineNo.Contains(input.LineNo.Trim())) .WhereIF(!string.IsNullOrWhiteSpace(input.Port), u => u.Port.Contains(input.Port.Trim())) .WhereIF(!string.IsNullOrWhiteSpace(input.LotNo), u => u.LotNo.Contains(input.LotNo.Trim())) .WhereIF(!string.IsNullOrWhiteSpace(input.SkuNo), u => u.SkuNo.Contains(input.SkuNo.Trim())) @@ -196,6 +196,10 @@ checkTaskInfo.PZNo = skuInfo.PZNo; //更新分拣任务 await _wcsCheckTaskRep.AsUpdateable(checkTaskInfo).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync(); #region#给PLC写数据 #endregion } [HttpPost] @@ -203,18 +207,21 @@ [DisplayName("任务结批")] public async Task CloseTaskForPLC(BindTaskPLCInput input) { #region 请求PLC接口 #region 请求PLC接口(这个方法实际是预结批,给PLC发送预结批信息,然后PLC再给WCS发送结批信号再将分拣信息清空) #endregion //分拣任务信息 var checkTaskList = _wcsCheckTaskRep.Context.Queryable<WcsCheckTask>().Where(w => w.LotNo == input.lotNo && w.Status == "1").ToList(); foreach (var item in checkTaskList) { item.OrderNo = ""; item.TaskNo = ""; item.LotNo = ""; item.SkuNo = ""; item.SkuName = ""; item.BoxType = ""; item.Qty = 0; item.PZNo = ""; item.Status = "0";//未绑定 } //更新分拣任务 Admin.NET/WCS.Application/Service/WcsDevice/Dto/WcsDeviceTaskOrderDto.cs
@@ -9,6 +9,7 @@ { public long Id { get; set; } public string Text { get; set; } public string? TaskNo { get; set; } public string? OrderNo { get; set; } public string? LotNo { get; set; } public string? SkuNo { get; set; } @@ -18,6 +19,6 @@ /// 总箱数/计划箱数/预估箱数 /// </summary> public int? Qty { get; set; } public string? LineNO { get; set; } public string? LineNo { get; set; } public string? PZNo { get; set; } } Admin.NET/WCS.Application/Service/WcsDevice/WcsDeviceService.cs
@@ -405,11 +405,12 @@ { Id=device.Id, Text=device.Text, TaskNo=task.TaskNo, OrderNo=task.OrderNo, LotNo=task.LotNo, SkuNo=task.SkuNo, SkuName=task.SkuName, LineNO=task.LineNO, LineNo=task.LineNo, Status =task.Status, PZNo=task.PZNo, Qty=task.Qty Admin.NET/WCS.Application/Service/WcsPosition/WcsPositionService.cs
@@ -8,9 +8,11 @@ public class WcsPositionService : IDynamicApiController, ITransient { private readonly SqlSugarRepository<WcsPosition> _WcsPositionRep; public WcsPositionService(SqlSugarRepository<WcsPosition> WcsPositionRep) private readonly SqlSugarRepository<WcsPlc> _wcsPlcRep; public WcsPositionService(SqlSugarRepository<WcsPosition> WcsPositionRep, SqlSugarRepository<WcsPlc> wcsPlcRep) { _WcsPositionRep = WcsPositionRep; _wcsPlcRep = wcsPlcRep; } /// <summary> @@ -145,7 +147,22 @@ ).ToListAsync(); } /// <summary> /// 获取设备ID列表 /// </summary> /// <returns></returns> [ApiDescriptionSettings(Name = "WcsPlcIdDropdown"), HttpGet] [DisplayName("获取设备ID列表")] public async Task<dynamic> WcsPlcIdDropdown() { return await _wcsPlcRep.Context.Queryable<WcsPlc>() .Select(u => new { Label = u.Text, Value = u.Id } ).ToListAsync(); } } Admin.NET/WCS.Application/Service/WcsTask/Dto/WcsTaskInput.cs
@@ -102,7 +102,7 @@ /// <summary> /// 拣货方式 /// </summary> public virtual string? UnstackingMode { get; set; } public virtual UnstackingModeEnum? UnstackingMode { get; set; } /// <summary> /// 取消时间 Admin.NET/WCS.Application/Service/WcsTask/WcsTaskService.cs
@@ -1,7 +1,9 @@ using AngleSharp.Dom; using Elastic.Clients.Elasticsearch.Tasks; using Furion.DatabaseAccessor; using Microsoft.AspNetCore.SignalR; using WCS.Application.Entity; namespace WCS.Application; @@ -13,11 +15,15 @@ { private readonly SqlSugarRepository<WcsTask> _wcsTaskRep; private readonly IHubContext<TaskLogHub, ITaskLogHub> _taskLogHubContext; private readonly SqlSugarRepository<WcsCheckTask> _wcsCheckTaskRep; private readonly SqlSugarRepository<WcsMateialPzInfo> _wcsMateialPzInfoRep; public WcsTaskService(SqlSugarRepository<WcsTask> wcsTaskRep, IHubContext<TaskLogHub, ITaskLogHub> taskLogHubContext) public WcsTaskService(SqlSugarRepository<WcsTask> wcsTaskRep, IHubContext<TaskLogHub, ITaskLogHub> taskLogHubContext, SqlSugarRepository<WcsCheckTask> wcsCheckTaskRep, SqlSugarRepository<WcsMateialPzInfo> wcsMateialPzInfoRep) { _wcsTaskRep = wcsTaskRep; _taskLogHubContext = taskLogHubContext; _wcsCheckTaskRep = wcsCheckTaskRep; _wcsMateialPzInfoRep = wcsMateialPzInfoRep; } /// <summary> @@ -56,9 +62,48 @@ { throw Oops.Bah("任务号重复"); } if (input.UnstackingMode == UnstackingModeEnum.Machine) { if (string.IsNullOrEmpty(input.SkuNo) || string.IsNullOrEmpty(input.SkuName)) { throw Oops.Bah("机器人拣货,物料和批次信息不能为空"); } } var entity = input.Adapt<WcsTask>(); entity.Origin = "WCS"; await _wcsTaskRep.InsertAsync(entity); #region 绑定垛机 //物料品种信息 var skuInfo = await _wcsMateialPzInfoRep.Context.Queryable<WcsMateialPzInfo>().Where(w => w.SkuNo == input.SkuNo).FirstAsync(); if (skuInfo == null) { throw Oops.Oh("物料品种信息不存在"); } //分拣任务信息 var checkTaskInfo = await _wcsCheckTaskRep.Context.Queryable<WcsCheckTask>().Where(w => w.Status == "0" && w.RoboatType == "0").OrderBy(o => o.LineNo).FirstAsync(); if (checkTaskInfo == null) { throw Oops.Oh("分拣任务信息不存在"); } if (checkTaskInfo.Status != "0") { throw Oops.Oh("该工位已绑定任务,请勿再次绑定"); } checkTaskInfo.OrderNo = ""; checkTaskInfo.TaskNo = entity.TaskNo; checkTaskInfo.LotNo = entity.LotNo; checkTaskInfo.SkuNo = entity.SkuNo; checkTaskInfo.SkuName = entity.SkuName; checkTaskInfo.BoxType = ""; checkTaskInfo.Qty = entity.Qty; checkTaskInfo.Status = "1";//已绑定 checkTaskInfo.PZNo = skuInfo.PZNo; //更新分拣任务 await _wcsCheckTaskRep.AsUpdateable(checkTaskInfo).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync(); #endregion return entity.Id; } @@ -155,6 +200,25 @@ await _wcsTaskRep.Context.Insertable(modTaskMonitor).ExecuteCommandAsync(); //await _taskLogHubContext.Clients.All.PublicTask(modTask.Adapt<WcsTaskOutput>()); //await _taskLogHubContext.Clients.All.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>()); #region //分拣任务信息 var checkTaskList = _wcsCheckTaskRep.Context.Queryable<WcsCheckTask>().Where(w => w.TaskNo == modTask.TaskNo && w.Status == "1").ToList(); foreach (var item in checkTaskList) { item.OrderNo = ""; item.TaskNo = ""; item.LotNo = ""; item.SkuNo = ""; item.SkuName = ""; item.BoxType = ""; item.Qty = 0; item.PZNo = ""; item.Status = "0";//未绑定 } //更新分拣任务 await _wcsCheckTaskRep.AsUpdateable(checkTaskList).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync(); #endregion } else { Web/src/api/wcs/wcsPosition.ts
@@ -1,11 +1,12 @@ import request from '/@/utils/request'; enum Api { AddWcsPosition = '/api/wcsPosition/add', DeleteWcsPosition = '/api/wcsPosition/delete', UpdateWcsPosition = '/api/wcsPosition/update', PageWcsPosition = '/api/wcsPosition/page', DetailWcsPosition = '/api/wcsPosition/detail', GetWcsDeviceDeviceIdDropdown = '/api/wcsPosition/WcsDeviceDeviceIdDropdown', AddWcsPosition = '/api/wcsPosition/add', DeleteWcsPosition = '/api/wcsPosition/delete', UpdateWcsPosition = '/api/wcsPosition/update', PageWcsPosition = '/api/wcsPosition/page', DetailWcsPosition = '/api/wcsPosition/detail', GetWcsDeviceDeviceIdDropdown = '/api/wcsPosition/WcsDeviceDeviceIdDropdown', GetWcsPlcIdDropdown = '/api/wcsPosition/WcsPlcIdDropdown', } // 增加设备工位 @@ -17,40 +18,45 @@ }); // 删除设备工位 export const deleteWcsPosition = (params?: any) => export const deleteWcsPosition = (params?: any) => request({ url: Api.DeleteWcsPosition, method: 'post', data: params, }); url: Api.DeleteWcsPosition, method: 'post', data: params, }); // 编辑设备工位 export const updateWcsPosition = (params?: any) => export const updateWcsPosition = (params?: any) => request({ url: Api.UpdateWcsPosition, method: 'post', data: params, }); url: Api.UpdateWcsPosition, method: 'post', data: params, }); // 分页查询设备工位 export const pageWcsPosition = (params?: any) => export const pageWcsPosition = (params?: any) => request({ url: Api.PageWcsPosition, method: 'post', data: params, }); url: Api.PageWcsPosition, method: 'post', data: params, }); // 详情设备工位 export const detailWcsPosition = (id: any) => export const detailWcsPosition = (id: any) => request({ url: Api.DetailWcsPosition, method: 'get', data: { id }, }); url: Api.DetailWcsPosition, method: 'get', data: { id }, }); export const getWcsDeviceDeviceIdDropdown = () => request({ request({ url: Api.GetWcsDeviceDeviceIdDropdown, method: 'get' }); }); export const GetWcsPlcIdDropdown = () => request({ url: Api.GetWcsPlcIdDropdown, method: 'get' }); Web/src/views/device/sortPallet/index.vue
@@ -27,9 +27,9 @@ <el-form-item label="WMS明细单号"> <el-input v-model="deviceInfo.orderNo" readonly></el-input> </el-form-item> <!-- <el-form-item label="任务号"> <el-input v-model=""></el-input> </el-form-item> --> <el-form-item label="任务号"> <el-input v-model="deviceInfo.taskNo"></el-input> </el-form-item> <el-form-item label="批次号"> <el-input v-model="deviceInfo.lotNo" readonly></el-input> </el-form-item> @@ -40,7 +40,7 @@ <el-input v-model="deviceInfo.skuName" readonly></el-input> </el-form-item> <el-form-item label="分拣线编号"> <el-input v-model="deviceInfo.lineNO" readonly></el-input> <el-input v-model="deviceInfo.lineNo" readonly></el-input> </el-form-item> <el-form-item label="绑定状态"> <el-input :value="deviceInfo.status === '0' ? '未绑定' : '已绑定'" readonly></el-input> Web/src/views/device/wcsOderTask/component/editDialog.vue
@@ -115,7 +115,7 @@ </template> </el-dialog> <!-- 绑定任务弹框 --> <!-- 选择物料弹框 --> <el-dialog v-model="bindDialogVisible" title="选择数据"> <el-table :data="bindBoxData" Web/src/views/wcs/wcsPosition/index.vue
@@ -9,9 +9,20 @@ </el-form-item> </el-col> <!-- <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="showAdvanceQueryUI"> <el-form-item label="PLC"> <el-select clearable="" filterable="" v-model="queryParams.plcId" placeholder="请选择PLC"> <el-option v-for="(item, index) in wcsPLCList" :key="index" :value="item.value" :label="item.label" /> </el-select> </el-form-item> </el-col> --> <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10" v-if="showAdvanceQueryUI"> <el-form-item label="设备ID"> <el-select clearable="" filterable="" v-model="queryParams.deviceId" placeholder="请选择设备ID"> <el-form-item label="设备"> <el-select clearable="" filterable="" v-model="queryParams.deviceId" placeholder="请选择设备"> <el-option v-for="(item, index) in wcsDeviceDeviceIdDropdownList" :key="index" :value="item.value" :label="item.label" /> @@ -104,7 +115,7 @@ import ModifyRecord from '/@/components/table/modifyRecord.vue'; import printDialog from '/@/views/system/print/component/hiprint/preview.vue' import editDialog from '/@/views/wcs/wcsPosition/component/editDialog.vue' import { pageWcsPosition, deleteWcsPosition } from '/@/api/wcs/wcsPosition'; import { pageWcsPosition, deleteWcsPosition,GetWcsPlcIdDropdown } from '/@/api/wcs/wcsPosition'; import { getWcsDeviceDeviceIdDropdown } from '/@/api/wcs/wcsPosition'; const showAdvanceQueryUI = ref(false); @@ -194,6 +205,13 @@ }; getWcsDeviceDeviceIdDropdownList(); const wcsPLCList = ref<any>([]); const getwcsPLCList = async () => { let list = await GetWcsPlcIdDropdown(); wcsPLCList.value = list.data.result ?? []; }; getwcsPLCList(); handleQuery(); </script> <style scoped> Web/src/views/wcs/wcsTask/component/editDialog.vue
@@ -64,6 +64,37 @@ </el-form-item> </el-col> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-form-item label="拣货方式" prop="unstackingMode"> <el-select clearable v-model="ruleForm.unstackingMode" placeholder="请选择拣货方式"> <el-option v-for="(item,index) in dl('UnstackingModeEnum')" :key="index" :value="Number(item.value)" :label="`${item.name} (${item.code}) [${item.value}]`"></el-option> </el-select> </el-form-item> </el-col> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-form-item label="物料编码" prop="skuNo"> <el-input v-model="ruleForm.skuNo" placeholder="请输入物料编码" maxlength="20" show-word-limit clearable /> </el-form-item> </el-col> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-form-item label="物料名称" prop="skuName"> <el-input v-model="ruleForm.skuName" placeholder="请输入物料名称" maxlength="50" show-word-limit clearable/> </el-form-item> </el-col> <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20"> <el-form-item label="批次号" prop="lotNo"> <el-input v-model="ruleForm.lotNo" placeholder="请输入批次号" maxlength="50" show-word-limit clearable /> </el-form-item> </el-col> </el-row> </el-form> <template #footer>