using Admin.NET.Core.Service; using Furion.DatabaseAccessor; using Furion.Logging; using WCS.Application.Entity; using WCS.Application.Util; using static SKIT.FlurlHttpClient.Wechat.Api.Models.ComponentTCBBatchCreateContainerServiceVersionRequest.Types; namespace WCS.Application; /// /// 示例开放接口 /// [ApiDescriptionSettings("开放接口", Name = "OpenApi", Order = 100)] //[Authorize(AuthenticationSchemes = SignatureAuthenticationDefaults.AuthenticationScheme)] [AllowAnonymous] public class OpenApi : IDynamicApiController { private static readonly ISqlSugarClient _db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId); private readonly UserManager _userManager; private readonly SysCacheService _sysCacheService; private readonly SysConfigService _sysConfigService; private readonly WcsTaskService _taskService; public OpenApi(UserManager userManager, SysCacheService sysCacheService, SysConfigService sysConfigService, WcsTaskService taskService) { _userManager = userManager; _sysCacheService = sysCacheService; _sysConfigService = sysConfigService; _taskService = taskService; } /// /// 测试分配任务路径 /// /// 任务信息 /// 反馈信息 [AllowAnonymous] public async Task AddAssignTasks(AgvTaskSend models) { var response = await new HttpService().GenAgvSendTask(models); //var response2 = await new HttpService().GenAgvContinueTask("Tk20250503000001"); //var response3 = await new HttpService().GenAgvUnbind("models", "B010101"); return response; // 验证任务是否已存在 //var taskInfo = await _db.Queryable().FirstAsync(w => w.TaskNo == models.TaskNo); //if (taskInfo == null) //{ // throw Oops.Bah("任务:" + models.TaskNo + ";不存在!"); //} //var data1 = FourWayCarUtil.GetCarPath("091501", "091601","0"); //if (data1 == null) //|| data1.Count == 0 //{ // throw Oops.Bah("分配路径不存在!"); //} //// 根据任务状态 补充起始结束节点状态 //var data2 = FourWayCarUtil.GetCarPathUp(data1, 0); //var path = ""; //var executionPath1 = ""; //foreach (var item in data1) //{ // //路径节点 // var pathXYZ = item.X.ToString().PadLeft(2, '0') + item.Y.ToString().PadLeft(2, '0') + item.Z.ToString().PadLeft(2, '0') + item.NodeCom.ToString(); // path += pathXYZ + ";"; // if (item.IsSendPlc) // { // executionPath1 += pathXYZ + ";"; // } //} //// 插入四向车任务表 //var carTask1 = new WcsCarTasks() //{ // TaskNo = taskInfo.TaskNo, // PreId = "", // ExecutionPath = executionPath1, // Path = path, // CarNo = "", // Status = TaskStatusEnum.Wait //}; //var i = _db.Insertable(carTask1).ExecuteCommand(); //Console.WriteLine(""+i); } /// WCS接受WMS下发的任务(多 /// 条任务) /// 任务信息 /// 反馈信息 /// [AllowAnonymous] [UnitOfWork] public async Task AddWcsTasks(List modelList) { var listTaskNo = modelList.Select(s => s.TaskNo).ToList(); // 验证任务是否已存在 var taskInfo = await _db.Queryable().CountAsync(w => listTaskNo.Contains(w.TaskNo)); if (taskInfo > 0) { throw Oops.Bah("任务已存在!"); } var listTask = new List(); var list = modelList.OrderBy(m => m.Order).ThenBy(m => m.TaskNo).ToList(); foreach (var models in list) { if (models.TaskType == "0") { models.Order = 1; } else { models.Order = 2; } //新增任务 var taskAdd = new WcsTask() { TaskNo = models.TaskNo, TaskType = (TaskTypeEnum)Convert.ToInt32(models.TaskType), Type = models.Type, Status = TaskStatusEnum.Wait, Levels = 999, Origin = "WMS", SkuNo = models.SkuNo, SkuName=models.SkuName, LotNo=models.LotNo, StartRoadway = models.StartRoadway, StartLocate = models.StartLocate, EndLocate = models.EndLocate, EndRoadway = models.EndRoadway, PalletNo = models.PalletNo, CreateTime = DateTime.Now }; // 若非AGV任务增加任务ID if (models.Type != PLCTypeEnum.AGV) { taskAdd.TaskId = FourWayCarUtil.GetTaskId(); } await _db.Insertable(taskAdd).ExecuteCommandAsync(); } } /// /// WCS接受WMS下发的任务(单条任务) /// /// 任务信息 /// 反馈信息 [AllowAnonymous] public async Task AddWcsTask(ResponseTasksModel models) { // 验证任务是否已存在 var taskInfo = await _db.Queryable().FirstAsync(w => w.TaskNo == models.TaskNo); if (taskInfo != null) { throw Oops.Bah("任务:" + models.TaskNo + ";已存在!"); } if (models.TaskType == "0") { models.Order = 1; } else { models.Order = 2; } //新增任务 var taskAdd = new WcsTask() { TaskNo = models.TaskNo, TaskType = (TaskTypeEnum?)int.Parse(models.TaskType), Status = TaskStatusEnum.Wait, Type = models.Type, Levels = 999, Origin = "WMS", SkuNo = models.SkuNo, SkuName = models.SkuName, LotNo = models.LotNo, StartRoadway = models.StartRoadway, StartLocate = models.StartLocate, EndLocate = models.EndLocate, EndRoadway = models.EndRoadway, PalletNo = models.PalletNo, }; // 若非AGV任务增加任务ID if (models.Type != PLCTypeEnum.AGV) { taskAdd.TaskId = FourWayCarUtil.GetTaskId(); } await _db.Insertable(taskAdd).ExecuteCommandAsync(); } /// /// WCS接收WMS下发的入库单任务 /// /// /// [HttpPost] [AllowAnonymous] public async Task AddOrderTask(List models) { foreach (var item in models) { // 验证任务是否已存在 //var taskInfo = _db.Queryable().First(w => w.OrderNo == item.OrderNo && w.SkuNo == item.SkuNo && w.LotNo == item.LotNo); //if (taskInfo == null) //{ var orderAdd = new WcsOderTask() { OrderNo = item.OrderNo, TaskNo = "", LotNo = item.LotNo, SkuNo = item.SkuNo, SkuName = item.SkuName, BoxType = item.BoxType, Qty = item.Qty, TaskType = (TaskTypeEnum)item.TaskType, }; await _db.Insertable(orderAdd).ExecuteCommandAsync(); //} } } /// /// WCS接收赋码系统推送的箱码信息 /// /// 箱码信息 /// 反馈信息 [HttpPost] [AllowAnonymous] public async Task AddBoxInfo(FumaBoxInfoInput models) { if (models.Origin != "赋码") { throw Oops.Bah("来源未识别"); } var num = await _db.Queryable().Where(m => m.BoxNo == models.BoxNo).ToListAsync(); var type = "add"; if (num.Count > 0) { //WCS存在箱码信息,更新箱码信息(需判断箱码是否已组盘入库) var num2 = num.Count(m => m.Status != "0" || !string.IsNullOrWhiteSpace(m.PalletNo)); if (num2 > 0) { throw Oops.Bah("该箱已入盘入库,不可更新信息"); } type = "edit"; } if (models.DelistList.Count == 0) { throw Oops.Bah("盒码集合不能为空"); } var listBox = new List(); foreach (var item in models.DelistList) { var level = "3"; if (string.IsNullOrWhiteSpace(item.BoxNo2)) { level = "2"; } if (item.DelistList2.Count == 0) { throw Oops.Bah("值码集合不能为空"); } //二级码 foreach (var item2 in item.DelistList2) { if (string.IsNullOrWhiteSpace(models.ProductionTime) || string.IsNullOrWhiteSpace(models.ExpirationTime)) { throw Oops.Bah("生产日期或失效日期不能为空"); } DateTime proTime; DateTime expTime; var isValid = DateTime.TryParse(models.ProductionTime, out proTime); var isValid2 = DateTime.TryParse(models.ExpirationTime, out expTime); if (!isValid || !isValid2) { throw Oops.Bah("生产日期或失效日期格式错误"); }; var boxAdd = new WcsBoxInfo() { BoxNo = models.BoxNo, //OrderNo = models.OrderNo, SkuNo = models.SkuNo, SkuName = models.SkuName, Standard = models.Standard, LotNo = models.LotNo, Qty = item2.Qty, FullQty = models.FullQty, //SupplierLot = models.SupplierLot, InsPectMark = models.InsPectMark, BitBoxMark = models.BitBoxMark, //InspectStatus = models.InspectStatus, ProductionTime = proTime, ExpirationTime = expTime, StoreTime = DateTime.Parse(models.StoreTime), EndLotFlag = string.IsNullOrWhiteSpace(models.EndBatchMark) ? "0" : models.EndBatchMark, BoxNo2 = item.BoxNo2, BoxNo3 = item2.BoxNo3, QtyCount = item2.QtyCount, QtyOrd = item2.QtyOrd, Status = "0", Level = level, }; listBox.Add(boxAdd); } } await _db.Insertable(listBox).ExecuteCommandAsync(); if (type == "edit") { await _db.Deleteable(num).ExecuteCommandAsync(); } } /// /// AGV小车申请开门 /// /// /// [HttpPost] [NonUnify] public async Task AgvApplyLock(AGVApplyLockInput input) { AGVCallBackResponse result = new AGVCallBackResponse() { //ReqCode = input.ReqCode, Message = "成功", Code = "0" }; var modPlc = PLCTaskAction.plcs.FirstOrDefault(s => s.Type == PLCTypeEnum.ConveyorLine); if (modPlc == null) { result.Code = "1"; result.Message = "找不到PLC信息"; } else { var modUtil = new PLCUtil(modPlc); string text = ""; if (input.DeviceIndex == "111") { text = "3号卷帘门"; } else if (input.DeviceIndex == "222") { text = "2号卷帘门"; } else { result.Code = "1"; result.Message = "卷帘门编号错误"; return result; } var modDevice = await _db.Queryable().FirstAsync(s => s.Text == text); if (modDevice == null) { result.Code = "1"; result.Message = "找不到卷帘门设备信息"; } else { if (input.ActionTask == "applyLock") { var (plcResult, value) = modUtil.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.PlcPos); if (plcResult.IsSucceed) { //写入10申请开门,等待写入20返回结果让小车通过 plcResult = modUtil.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "10"); if (!plcResult.IsSucceed) { result.Code = "1"; result.Message = "打开卷帘门写入值失败"; } else { _sysCacheService.Set("OpenDoor" + input.DeviceIndex, input); } } else { result.Code = "1"; result.Message = "获取卷帘门状态失败"; } } else { var (plcResult, value) = modUtil.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.PlcPos); if (plcResult.IsSucceed && value != 0) { plcResult = modUtil.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "30"); if (!plcResult.IsSucceed) { result.Code = "1"; result.Message = "关闭卷帘门写入值失败"; } } else { result.Code = "1"; result.Message = "获取卷帘门状态失败"; } } } } return result; } /// /// AGV小车回调 /// /// /// [HttpPost] [NonUnify] [UnitOfWork] public async Task agvCallback(AGVCallBackInput input) { Log.Information("AGV反馈任务" + input.ToJson()); AGVCallBackResponse result = new AGVCallBackResponse() { ReqCode = input.ReqCode, Message = "成功", Code = "0" }; if (input.robotTaskCode.Substring(0, 3) != "WCS" && input.robotTaskCode.Substring(0, 2) != "TK") { result.Message = "反馈的任务不是WCS的任务"; result.Code = "1"; return result; } PLCUtil modUtil = null; try { var modTask = await _db.Queryable().FirstAsync(s => s.TaskNo == input.robotTaskCode); if (modTask != null) { switch (input.Extra.Values.Method) { case "end"://任务完成 { modTask.Status = TaskStatusEnum.Complete; modTask.FinishDate = DateTime.Now; await _db.Updateable(modTask).ExecuteCommandAsync(); WcsTaskMonitor modTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, //PlcId = modDevice.PlcId, PlcName = "AGV", StartLocat = modTask.StartLocate, EndLocat = modTask.EndLocate, Status = TaskStatusEnum.Complete, InteractiveMsg = $"AGV小车反馈任务完成", }; await _db.Insertable(modTaskMonitor).ExecuteCommandAsync(); HubUtil.PublicTask(modTask.Adapt()); HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt()); //反馈WMS任务完成 if (modTask.Origin == "WMS") { HttpService httpService = new HttpService(); var inputs = new TaskRequestWMS(); inputs.TaskNo = modTask.TaskNo; inputs.PalletNo = modTask.PalletNo; inputs.TaskType = ((int)modTask.TaskType).ToString(); inputs.TaskStatus = "2"; var modResponseTask = httpService.RequestTask(inputs).Result; } } break; case "outbin"://走出储位 { WcsTaskMonitor modTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, //PlcId = modDevice.PlcId, PlcName = "AGV", StartLocat = modTask.StartLocate, EndLocat = modTask.EndLocate, Status = TaskStatusEnum.Complete, InteractiveMsg = $"AGV小车反馈任务取货完成,走出储位", }; await _db.Insertable(modTaskMonitor).ExecuteCommandAsync(); //反馈WMS任务取货完成、WMS判断是平库储位就更新储位状态 if (modTask.Origin == "WMS") { HttpService httpService = new HttpService(); var inputs = new TaskRequestWMS(); inputs.TaskNo = modTask.TaskNo; inputs.PalletNo = modTask.PalletNo; inputs.TaskType = ((int)modTask.TaskType).ToString(); inputs.TaskStatus = "2"; var modResponseTask = httpService.RequestTaskQh(inputs).Result; } } break; case "release"://放货申请 { if (modTask.EndLocate != "B040101")//9号工位地址 { result.Code = "1"; result.Message = "找不到该任务"; return result; } //modTask.Status = TaskStatusEnum.Complete; modTask.IsComple = "1"; await _db.Updateable(modTask).ExecuteCommandAsync(); WcsTaskMonitor modTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, //PlcId = modDevice.PlcId, PlcName = "AGV", StartLocat = modTask.StartLocate, EndLocat = modTask.EndLocate, Status = TaskStatusEnum.Complete, InteractiveMsg = $"AGV小车反馈任务到达9工位", }; await _db.Insertable(modTaskMonitor).ExecuteCommandAsync(); HubUtil.PublicTask(modTask.Adapt()); HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt()); if (modTask.Origin == "WMS") { HttpService httpService = new HttpService(); var inputs = new TaskRequestWMS(); inputs.TaskNo = modTask.TaskNo; inputs.PalletNo = modTask.PalletNo; inputs.TaskType = ((int)modTask.TaskType).ToString(); inputs.TaskStatus = "2"; var modResponseTask = httpService.RequestTaskQh(inputs).Result; } } break; case "notifyFullSite": { var palletNo = input.Extra.Values.carrierCode; var count = input.Extra.Values.pileCount; if (string.IsNullOrWhiteSpace(palletNo) || count <= 0) { throw new Exception("参数:托盘号/数量验证失败"); } //向WMS申请空托入库 HttpService httpService = new HttpService(); var inputs = new NullPallInRequest(); inputs.PalletNo = modTask.PalletNo; inputs.PallNum = count; inputs.Locate = "B100101";//叠托盘机位置 inputs.HouseNo = "W02"; var modResponseTask = httpService.RequestLiKuPallet(inputs); } break; case "cancel"://任务取消 { PLCService.AGVStatus = false; modTask.IsSuccess = TaskSuccessEnum.Fail; modTask.CancelDate = DateTime.Now; modTask.Status = TaskStatusEnum.Cancell; modTask.Levels = 999; await _db.Updateable(modTask).UpdateColumns(s => new { s.Status, s.IsSuccess, s.FinishDate, s.CancelDate, s.UpdateTime, s.UpdateUserId, s.UpdateUserName }).ExecuteCommandAsync(); //写入任务明细表 WcsTaskMonitor modTaskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, PlcId = 0, PlcName = "", Status = TaskStatusEnum.Complete, StartLocat = modTask.StartLocate, EndLocat = modTask.EndLocate, InteractiveMsg = "小车通知任务取消", PalletNo = modTask.PalletNo }; await _db.Insertable(modTaskMonitor).ExecuteCommandAsync(); HubUtil.PublicTask(modTask.Adapt()); HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt()); } break; default: break; } } else { result.Code = "1"; result.Message = "找不到该任务"; } } catch (Exception ex) { result.Code = "1"; result.Message = ex.Message; } finally { modUtil?.Close(); } Log.Information("AGV反馈任务返回" + result.ToJson()); return result; } /// /// 获取原材料仓状态 /// /// [HttpPost] public async Task HuoQuMateralStatus() { var data = await _sysConfigService.GetConfigValue("cache_Materal"); return data; } /// /// 修改原材料仓状态 /// /// [HttpPost] public async Task UpdateMateralStatus() { await _sysConfigService.UpdateConfigValue("cache_Materal", false); } /// /// 获取车间动向 /// /// [HttpPost] public async Task Workshop() { var result = Enum.TryParse(await _sysConfigService.GetConfigValue("workshop_Trend"), out WorkshopEnum workshop); return workshop; } /// /// 修改车间动向 /// /// [HttpPost] public async Task ChangeWorkshop(RequestTrends input) { await _sysConfigService.UpdateConfigValue("workshop_Trend", input.Type.ToString()); } /// /// 手动入托盘 /// /// //[HttpPost] //public async Task InPallet(RequestStorage input) //{ // var intPallet = _sysConfigService.GetConfigValue("cache_Pallet").Result; // if (intPallet + input.Qty > 3) // throw Oops.Bah($"输入数量大于可放置数"); // await _sysConfigService.UpdateConfigValue("cache_Pallet", (intPallet + input.Qty).ToString()); //} /// /// 成品缓存区入库 /// /// /// //[HttpPost] //[UnitOfWork] //public async Task ProductStorage(RequestStorage input) //{ // var intProduct = AGVStorageUtil.ProductCount(); // var intTask = await _db.Queryable().Where(s => s.TaskType == TaskTypeEnum.Move // && s.Type == PLCTypeEnum.AGV && s.Status <= TaskStatusEnum.Doing // && s.StartLocate.StartsWith("Z") && s.EndLocate == AGVStaionEnum.A1.ToString()).CountAsync(); // if (input.Qty > intProduct) // throw Oops.Bah($"输入数量大于可出数量{intProduct}"); // var listTask = new List(); // var TaskNo = GetTaskCode("WCS"); // for (int i = 0; i < input.Qty; i++) // { // listTask.Add(new WcsTask() // { // TaskNo = "WCS" + DateTime.Now.ToString("yyyyMMdd") + (TaskNo++).ToString().PadLeft(4, '0'), // TaskType = TaskTypeEnum.Move, // Type = PLCTypeEnum.AGV, // StartLocate = AGVStaionEnum.Z11.ToString(), // EndLocate = AGVStaionEnum.A1.ToString(), // PalletNo = "", // Status = TaskStatusEnum.Wait, // Levels = 10, // Origin = "PDA" // }); // } // await _db.Insertable(listTask).ExecuteCommandAsync(); //} /// /// 自动生成任务号 /// /// /// [NonAction] public static int GetTaskCode(string codeFlag = "WCS") { var list = _db.Queryable().Where(m => m.TaskNo.StartsWith("WCS")).ToList(); string maxNo = list.Max(m => m.TaskNo); if (!string.IsNullOrEmpty(maxNo)) { maxNo = maxNo.Substring(codeFlag.Length); } //获取数据库时间八位 string date = DateTime.Now.ToString("yyyyMMdd").Trim(); int no = 0; if (string.IsNullOrEmpty(maxNo)) { no = 1; } else { if (maxNo.Length == 12 && maxNo.Substring(0, 8) == date) { int lastNo = Convert.ToInt32(maxNo.Substring(8, 4)) + 1; no = lastNo; } else { no = 1; } } return no; } /// /// 完成任务 /// /// /// [HttpPost] public async Task FinishTask(WcsTask input) { if (input.TaskNo.IsNullOrEmpty()) throw Oops.Bah("任务号不能为空"); var modTask = await _db.Queryable().FirstAsync(s => s.TaskNo == input.TaskNo); if (modTask == null) throw Oops.Bah("找不到任务"); if (modTask.Status > TaskStatusEnum.Doing) throw Oops.Bah("任务状态不对"); modTask.FinishDate = DateTime.Now; modTask.Status = TaskStatusEnum.Complete; await _db.Updateable(modTask).ExecuteCommandAsync(); var taskMonitor = new WcsTaskMonitor() { TaskNo = modTask.TaskNo, InteractiveMsg = $"WMS调用完成任务" }; _db.Insertable(taskMonitor).ExecuteCommand(); //下发任务日志 HubUtil.PublicTask(modTask.Adapt()); HubUtil.PublicTaskMonitor(taskMonitor.Adapt()); } /// /// 查询缓存位状态 /// /// [HttpPost] public async Task> QueryCacheStorage() { string[] listPallet = new[] { "cache_Z11","cache_Z12","cache_Z13", "cache_Z21","cache_Z22","cache_Z23", "cache_Z31","cache_Z32","cache_Z33", "cache_Z41","cache_Z42","cache_Z43", "cache_Z51","cache_Z52","cache_Z53", }; Dictionary dic = new Dictionary(); foreach (var mod in listPallet) { dic.Add(mod.Split('_')[1], await _sysConfigService.GetConfigValue(mod)); } return dic; } /// /// 修改缓存位状态 /// /// [HttpPost] public async Task ChangeCacheStatus(StorageCacheStatus input) { Type type = input.GetType(); foreach (var item in type.GetProperties()) { string value = ""; var result = item.GetValue(input); if (!result.IsNullOrEmpty()) { if ((bool)item.GetValue(input)) value = "True"; else value = "False"; await _sysConfigService.UpdateConfigValue("cache_" + item.Name, value); } } } /// /// 查询小车正在执行的任务 /// /// [HttpPost] public async Task AGVTask() { return await _db.Queryable().Where(s => s.Type == PLCTypeEnum.AGV && s.Status == TaskStatusEnum.Doing).FirstAsync(); } /// /// 取消小车正在执行的任务 /// /// [HttpPost] public async Task CancelTask(WcsTask input) { await App.GetService().Finsh(new UpdateWcsTaskInput() { Id = input.Id, Status = TaskStatusEnum.Cancell }); } }