using HH.WCS.Mobox3.FJJF.models; using HH.WCS.Mobox3.FJJT.device; using HH.WCS.Mobox3.FJJT.dispatch; using HH.WCS.Mobox3.FJJT.models; using HH.WCS.Mobox3.FJJT.process; using HH.WCS.Mobox3.FJJT.util; using HH.WCS.Mobox3.FJJT.wms; using Newtonsoft.Json; using NLog; using NLog.Fluent; using SqlSugar; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Threading; using static HH.WCS.Mobox3.FJJT.api.ApiModel; using static HH.WCS.Mobox3.FJJT.api.OtherModel; using static HH.WCS.Mobox3.FJJT.api.WmsController; using static HH.WCS.Mobox3.FJJT.util.ExcetionHelper; using static HH.WCS.Mobox3.FJJT.util.Settings; using static System.Net.Mime.MediaTypeNames; namespace HH.WCS.Mobox3.FJJT.api { /// /// api接口辅助类 /// public class ApiHelper { static ApiHelper() { } /// /// 空工装出库 /// /// /// public static ResponseResult emptyPalletOutStock(OutStockModel model) { ResponseResult result = new ResponseResult(); Location endLoc = LocationHelper.GetLoc(model.endLocCode); if (endLoc == null) { WMSHelper.addAlarmRecord("流程异常", "低", $"空工装出库,WMS系统未查询到终点货位:{model.endLocCode}"); throw new BusinessException($"空工装出库,WMS系统未查询到终点货位:{model.endLocCode},请检查终点货位编码是否正确"); } else if (endLoc.N_LOCK_STATE != 0) { WMSHelper.addAlarmRecord("流程异常", "低", $"空工装出库,终点货位:{model.endLocCode}处于锁定状态"); throw new BusinessException($"空工装出库,终点货位:{model.endLocCode}处于锁定状态"); } var areaCodes = Settings.getRelAreaCodes(endLoc.S_AREA_CODE); if (areaCodes.Count == 0) { WMSHelper.addAlarmRecord("流程异常", "低", $"空工装出库,未配置库区:{endLoc.S_AREA_CODE}的关联关系"); throw new BusinessException($"空工装出库,未配置库区:{endLoc.S_AREA_CODE}的关联关系"); } Location startLoc = WMSHelper.getOutStockStartLoc(areaCodes[0], null); if (startLoc == null) { WMSHelper.addAlarmRecord("流程异常", "低", $"空工装出库,库区:{areaCodes[0]}未查询到空工装"); throw new BusinessException($"空工装出库,未查询到空工装,立库可能缺少空工装"); } var locCntrRels = LocationHelper.GetLocCntr(startLoc.S_CODE); if (locCntrRels.Count > 0) { string cntrCode = locCntrRels[0].S_CNTR_CODE; var wmsTask = new WMSTask() { S_CNTR_CODE = cntrCode, S_CODE = WMSHelper.GenerateTaskNo(), S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_TYPE = "空工装出库任务", S_OP_DEF_NAME = "空工装出库", N_PRIORITY = 10, T_START_TIME = DateTime.Now, }; if (WMSHelper.CreateWmsTask(wmsTask)) { // 创建一段入库任务 WCSTask wcsTask = new WCSTask() { S_OP_NAME = wmsTask.S_OP_DEF_NAME, S_OP_CODE = wmsTask.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = wmsTask.S_CNTR_CODE, S_TYPE = wmsTask.S_TYPE, S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "WCS", N_PRIORITY = wmsTask.N_PRIORITY, T_START_TIME = DateTime.Now, }; if (WCSHelper.CreateTask(wcsTask)) { // 起点、终点加锁 LocationHelper.LockLoc(wcsTask.S_START_LOC, 2); LocationHelper.LockLoc(wcsTask.S_END_LOC, 1); // 更新作业任务状态 wmsTask.N_B_STATE = 1; WMSHelper.UpdateTaskState(wmsTask); } } } else { WMSHelper.addAlarmRecord("流程异常", "中", $"查询的空工装有误,错误原因:未查询到货位容器的绑定关系"); throw new BusinessException($"查询空工装错误,未查询到货位容器的绑定关系,请联系开发人员排查"); } return result; } /// /// WCS读码请求流程 /// 业务场景:读码入库、读码出库 /// 1.判断RFID是否存在WMS系统中,否,则默认为RFID无法识别 /// 2.判断RFID是否与任务RFID是否一致 /// 3.记录RFID异常信息 /// /// /// public static ResponseResult readCodeProcess(ReadCodeRequest request) { ResponseResult responseResult = new ResponseResult(); Location loc = LocationHelper.GetLoc(request.loc); if (loc != null) { var cst = WCSHelper.GetTask(request.taskNo); if (cst != null) { var container = ContainerHelper.GetCntr(request.cntrNo); if (container != null) { if (cst.S_CNTR_CODE != request.cntrNo) { ContainerHelper.UpdateCntrState(cst.S_CNTR_CODE, 1); WMSHelper.addRfidAnomalyRecord(cst.S_CNTR_CODE, 2, request.loc, cst.S_CODE); } } else { ContainerHelper.UpdateCntrState(cst.S_CNTR_CODE, 1); WMSHelper.addRfidAnomalyRecord(cst.S_CNTR_CODE, 1, request.loc, cst.S_CODE); } /*WCSHelper.ActivatePreCreateTask(cst.S_OP_CODE);*/ // 方案2 4.如果读取不成功,查看异常区是否有空货位 /* var agvEndLoc = WMSHelper.GetTransfeRelevanceLoc(loc.S_AREA_CODE, "4"); if (agvEndLoc != null) { // 4.1 有,则创建搬运异常区任务 WCSTask wcsTask = new WCSTask() { S_OP_NAME = cst.S_OP_NAME, S_OP_CODE = cst.S_OP_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = cst.S_CNTR_CODE, S_TYPE = "异常工装移库异常区", S_START_LOC = loc.S_CODE, S_START_AREA = loc.S_AREA_CODE, S_END_LOC = agvEndLoc.S_CODE, S_END_AREA = agvEndLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "AGV", N_PRIORITY = 99, T_START_TIME = DateTime.Now, }; if (WCSHelper.CreateTask(wcsTask)) { // 起点、接驳点、终点加锁 LocationHelper.LockLoc(wcsTask.S_START_LOC, 1); LocationHelper.LockLoc(wcsTask.S_END_LOC, 1); WCSHelper.CancelPreCreateTask(cst.S_OP_CODE); } } else { // 4.2 无,则记录异常激活预创建任务 WCSHelper.ActivatePreCreateTask(cst.S_OP_CODE); }*/ } else { WMSHelper.addAlarmRecord("流程异常", "低", $"没有查询到读码的任务,任务号:{request.taskNo}"); } } else { WMSHelper.addAlarmRecord("流程异常", "中", $"读码位:{request.loc},没有在WMS系统中录入"); throw new BusinessException($"读码位:{request.loc},没有在WMS系统中录入"); } return responseResult; } /// /// 满料下线流程 /// 1.判断RFID是否读取成功,读取不成功,记录异常(读取失败后,临时生成一个托盘码) /// 2.根据RFID查询中间表,不存在,记录异常 /// 3.判断满料接驳位对应的空工装缓存位状态(查询线体光电) /// /// 直连 /// 4.需要补,则生成空工装出库任务(胎面、胎侧直连提高优先级) /// 5.下发满料搬运任务(帘布直连提高优先级) /// /// 非直连 /// 4.需要补空工装,则空工装出库任务(完成后,生成满料搬运任务,并提高优先级99) /// 5.不需要补空工装,则生成满料搬运任务 /// /// 6.读任务中间表 /// /// /// public static ResponseResult offLineProcess(OffLineRequest model) { ResponseResult responseResult = new ResponseResult(); var areaCodes = Settings.areaPropertyList.Select(a => a.areaCode).ToList(); var isExistCntr = LocationHelper.checkAreaExistCntr(areaCodes,model.cntrNo); if (!isExistCntr) { // 查询起点货位是否存在已存在任务,防止任务重复发起 var existWmsTask = WMSHelper.GetWmsTaskByStart(model.loc); if (existWmsTask == null) { // 查询对应机台的物料下线配置信息 var logicConfig = WMSHelper.getLogicConfigByJtCode(model.jtNo); if (logicConfig != null) { Container container = ContainerHelper.GetCntr(model.cntrNo); if (container == null || !model.isNormal) { ContainerHelper.AddCntr(model.cntrNo); ContainerHelper.UpdateCntrState(model.cntrNo, 1); WMSHelper.addRfidAnomalyRecord(model.cntrNo, 1, model.loc, null); } // 根据物料下线配置信息,判断任务类型是直连下线还是非直连下线 if (logicConfig.S_TASK_TYPE == "1" || logicConfig.S_TASK_TYPE == "2") { triggerItemOffLineFlow(model.loc, model.cntrNo, logicConfig); } else { // 满料下线(非直连) triggerItemOffLineFlow4(model.loc, model.cntrNo, logicConfig); } } else { WMSHelper.addAlarmRecord("流程异常", "高", $"机台号{model.jtNo},没有可用的逻辑线路,请联系管理人员"); throw new BusinessException($"机台号{model.jtNo},没有可用的逻辑线路,请联系管理人员"); } } else { WMSHelper.addAlarmRecord("流程异常", "低", $"下线货位:{model.loc}已有任务,请勿重复下发任务"); throw new BusinessException($"下线货位:{model.loc}已有任务,请勿重复下发任务"); } } else { WMSHelper.addAlarmRecord("流程异常", "高", $"工装:{model.cntrNo}已入库,请勿重复入库"); throw new BusinessException($"工装:{model.cntrNo}已入库,请勿重复入库"); } return responseResult; } /// /// 满料下线(非直连) /// 1.创建满料下线作业 /// 2.判断是否需要补空工装,需要则创建空工装补缓存位任务 /// 3.判断容器是否是异常工装,是,如异常区有空货位则创建异常工装入线边异常区任务;否,则创建满料工装入库任务(如需要补空工装,则将任务状态改为预创建,等待补空工装任务完成后触发) /// 4.作业创建完成后,读取中间表,更新中间表状态 /// /// /// /// /// public static bool triggerItemOffLineFlow4(string offLineLoc,string cntrNo, LogicConfig logicConfig ,LjMesTask mesTask = null) { bool result = true; try { if (mesTask == null) { mesTask = WMSHelper.getLjMesTaskByCntr(cntrNo); } if (mesTask != null) { // 2.判断是否需要补空工装,需要,则创建空工装出库任务 bool photoStatus = false; var hcLoc = LocationHelper.GetLoc(logicConfig.S_LKBKHCLOC); if (hcLoc != null) { if (hcLoc.N_CURRENT_NUM != 0 && hcLoc.N_LOCK_STATE == 0) { hcLoc = LocationHelper.GetEmptyLoc(hcLoc.S_AREA_CODE); } if (hcLoc != null) { var bufferLocConfig = Settings.GetBufferLocConfig(hcLoc.S_CODE); // 缓存位关联属性 if (bufferLocConfig != null || hcLoc.N_CURRENT_NUM == 0) { photoStatus = true; // 方案1,如果非直连的缓存位有光电信号,则查询设备状态判断是否需要补空工装 /* var deviceStatusDatas = WCSDispatch.getDeviceStatus(new List() { bufferLocConfig.deviceNo }); if (deviceStatusDatas != null && deviceStatusDatas.Count > 0) { var deviceStatus = deviceStatusDatas[0]; if (deviceStatus.workStatus == 1 && deviceStatus.manualStatus == 0) { photoStatus = deviceStatus.photoStatus == 1; } else { WMSHelper.addAlarmRecord("流程异常", "高", $"设备号:{bufferLocConfig.deviceNo},设备当前处于不可用状态,请联系管理人员调整设备状态"); throw new BusinessException($"设备号:{bufferLocConfig.deviceNo},设备当前处于不可用状态,请联系管理人员调整设备状态"); } } else { WMSHelper.addAlarmRecord("流程异常", "高", $"设备号:{bufferLocConfig.deviceNo},查询设备状态失败,请联系工作人员查看设备是否正常"); throw new BusinessException($"设备号:{bufferLocConfig.deviceNo},查询设备状态失败,请联系工作人员查看设备是否正常"); }*/ } else { WMSHelper.addAlarmRecord("流程异常", "高", $"缓存位:{logicConfig.S_LKBKHCLOC},没有配置属性信息,请联系管理人员配置"); throw new BusinessException($"缓存位:{logicConfig.S_LKBKHCLOC},没有配置属性信息,请联系管理人员配置"); } } } else { WMSHelper.addAlarmRecord("流程异常", "高", $"缓存位:{logicConfig.S_LKBKHCLOC},没有WMS系统中录入"); throw new BusinessException($"缓存位:{logicConfig.S_LKBKHCLOC},没有WMS系统中录入"); } // 空工装出库判断条件 Location kgzStartLoc = null; Location kgzEndLoc = null; string kgzCntrCode = null; if (photoStatus) { kgzStartLoc = LocationHelper.GetLoc(logicConfig.S_LKKTJBLOC); kgzEndLoc = LocationHelper.GetLoc(logicConfig.S_LKBKHCLOC); if (kgzStartLoc == null) { WMSHelper.addAlarmRecord("流程异常", "高", $"空工装出库站台:{logicConfig.S_LKKTJBLOC},没有在WMS系统中录入"); photoStatus = false; } if (kgzEndLoc == null) { WMSHelper.addAlarmRecord("流程异常", "中", $"空工装缓存位:{logicConfig.S_LKBKHCLOC},没有在WMS系统中录入"); photoStatus = false; } var locCntrRels = LocationHelper.GetLocCntr(kgzStartLoc.S_CODE); if (locCntrRels.Count > 0) { kgzCntrCode = locCntrRels[0].S_CNTR_CODE; } else { kgzCntrCode = "虚拟容器"; WMSHelper.addAlarmRecord("流程异常", "低", $"空工装出库站台:{logicConfig.S_LKKTJBLOC},没有空工装"); } } string cntrCode = mesTask.PALLET_ID; Location startLoc = LocationHelper.GetLoc(offLineLoc); if (startLoc != null) { // 1.创建满料下线作业 var wmsTask = new WMSTask() { S_CNTR_CODE = cntrCode, S_CODE = WMSHelper.GenerateTaskNo(), S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = "虚拟货位", S_END_AREA = "虚拟库区", S_TYPE = "满料/异常工装入库任务(非直连)", S_OP_DEF_NAME = "满料/异常工装入库任务(非直连)", S_OP_DEF_CODE = mesTask.ID.ToString(), T_START_TIME = DateTime.Now, }; if (WMSHelper.CreateWmsTask(wmsTask)) { int priority = 10; // 2.判断是否需要补空工装,需要则创建空工装补缓存位任务 if (photoStatus) { WCSTask kgzWcsTask = new WCSTask() { S_OP_NAME = wmsTask.S_OP_DEF_NAME, S_OP_CODE = wmsTask.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = kgzCntrCode, S_TYPE = "空工装出库任务", S_START_LOC = kgzStartLoc.S_CODE, S_START_AREA = kgzStartLoc.S_AREA_CODE, S_END_LOC = kgzEndLoc.S_CODE, S_END_AREA = kgzEndLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "AGV", N_PRIORITY = priority, T_START_TIME = DateTime.Now, }; if (WCSHelper.CreateTask(kgzWcsTask)) { // 起点、终点加锁 LocationHelper.LockLoc(kgzWcsTask.S_START_LOC, 2); LocationHelper.LockLoc(kgzWcsTask.S_END_LOC, 1); } } // 3.创建满料工装入库任务(如需要补空工装,则将任务状态改为预创建,等待补空工装任务完成后触发) WCSTask wcsTask = new WCSTask() { S_OP_NAME = wmsTask.S_OP_DEF_NAME, S_OP_CODE = wmsTask.S_CODE, S_TYPE = "满料工装入库任务(非直连)", S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = wmsTask.S_CNTR_CODE, S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = wmsTask.S_END_LOC, S_END_AREA = wmsTask.S_END_AREA, S_SCHEDULE_TYPE = "AGV", N_PRIORITY = 99, T_START_TIME = DateTime.Now, }; if (photoStatus) { wcsTask.N_B_STATE = -1; wcsTask.S_B_STATE = "预创建"; } if (WCSHelper.CreateTask(wcsTask)) { // 起点、终点加锁 LocationHelper.LockLoc(wcsTask.S_START_LOC, 2); LocationHelper.LockLoc(wcsTask.S_END_LOC, 1); // 更新作业任务状态 wmsTask.N_B_STATE = 1; WMSHelper.UpdateTaskState(wmsTask); // 4.作业创建完成后,读取中间表,更新中间表状态 WMSHelper.readLjMesOffItemTask(wmsTask.S_CODE, mesTask.ID); } } } else { WMSHelper.addAlarmRecord("流程异常", "中", $"下线位:{offLineLoc},没有在WMS系统中录入"); throw new BusinessException($"下线位:{offLineLoc},没有在WMS系统中录入"); } } else { WMSHelper.addAlarmRecord("流程异常", "中", $"非直连下线货位:{offLineLoc}触发下线请求,未查询到MES任务"); throw new BusinessException($"非直连下线货位:{offLineLoc}触发下线请求,未查询到MES任务"); } } catch (BusinessException be) { throw be; } catch (Exception ex) { WMSHelper.addAlarmRecord("系统错误", "高", ex.Message); LogHelper.Error("WMS内部错误:触发满料下线(非直连)作业错误 ; ERROR_MGS:" + ex.Message, ex, "WMS"); result = false; } return result; } /// /// 满料下线(直连) /// 1.创建满料下线作业 /// 2.判断是否需要补空工装,需要,则创建空工装出库任务 /// 3.创建满料入库任务 /// 4.判断直连模式,如是胎侧直连模式,则提高空工装出库任务优先级;如是帘布直连模式则,提高满料入库优先级 /// 5.作业创建完成后,读取中间表,更新中间表状态 /// /// 下线货位 /// 下线容器编码 /// 逻辑配置 /// public static bool triggerItemOffLineFlow(string offLineLoc, string cntrNo, LogicConfig logicConfig ) { bool result = true; try { // 2.判断是否需要补空工装,需要,则创建空工装出库任务 bool photoStatus = false; var hcLoc = LocationHelper.GetLoc(logicConfig.S_LKBKHCLOC); if (hcLoc != null) { var bufferLocConfig = Settings.GetBufferLocConfig(hcLoc.S_CODE); if (bufferLocConfig != null) { // 测试代码 photoStatus = true; /* // 业务代码,勿删 var deviceStatusDatas = WCSDispatch.getDeviceStatus(new List() { bufferLocConfig.deviceNo }); if (deviceStatusDatas != null && deviceStatusDatas.Count > 0) { var deviceStatus = deviceStatusDatas[0]; if (deviceStatus.workStatus == 1 && deviceStatus.manualStatus == 0) { photoStatus = deviceStatus.photoStatus == 1; } else { WMSHelper.addAlarmRecord("流程异常", "高", $"设备号:{bufferLocConfig.deviceNo},设备当前处于不可用状态,请联系管理人员调整设备状态"); throw new BusinessException($"设备号:{bufferLocConfig.deviceNo},设备当前处于不可用状态,请联系管理人员调整设备状态"); } } else { WMSHelper.addAlarmRecord("流程异常", "高", $"设备号:{bufferLocConfig.deviceNo},查询设备状态失败,请联系工作人员查看设备是否正常"); throw new BusinessException($"设备号:{bufferLocConfig.deviceNo},查询设备状态失败,请联系工作人员查看设备是否正常"); }*/ } else { WMSHelper.addAlarmRecord("流程异常", "高", $"缓存位:{logicConfig.S_LKBKHCLOC},没有配置属性信息,请联系管理人员配置"); throw new BusinessException($"缓存位:{logicConfig.S_LKBKHCLOC},没有配置属性信息,请联系管理人员配置"); } } else { WMSHelper.addAlarmRecord("流程异常", "高", $"缓存位:{logicConfig.S_LKBKHCLOC},没有在WMS系统中录入"); throw new BusinessException($"缓存位:{logicConfig.S_LKBKHCLOC},没有在WMS系统中录入"); } Location startLoc = LocationHelper.GetLoc(offLineLoc); if (startLoc == null) { WMSHelper.addAlarmRecord("流程异常", "中", $"下线位:{offLineLoc},没有在WMS系统中录入"); throw new BusinessException($"下线位:{offLineLoc},没有在WMS系统中录入"); } Location endLoc = WMSHelper.getInStockEndLoc(logicConfig.S_AREA_CODE, 1); if (endLoc == null) { WMSHelper.addAlarmRecord("流程异常", "高", $"库内没有空余货位"); throw new BusinessException($"库内没有空余货位"); } LjMesTask mesTask = WMSHelper.getLjMesTaskByCntr(cntrNo); // 1.创建满料下线作业 var wmsTask = new WMSTask() { S_CNTR_CODE = cntrNo, S_CODE = WMSHelper.GenerateTaskNo(), S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_TYPE = "满料/异常工装入库任务(直连)", S_OP_DEF_NAME = "满料/异常工装入库任务(直连)", S_OP_DEF_CODE = mesTask != null ? mesTask.ID.ToString() : null, T_START_TIME = DateTime.Now, }; if (WMSHelper.CreateWmsTask(wmsTask)) { int priority = 10; Dictionary taskDic = new Dictionary(); // 是否创建空工装出口任务 if (photoStatus || true ) { Location kgzStartLoc = WMSHelper.getOutStockStartLoc(logicConfig.S_AREA_CODE, null); Location kgzEndLoc = LocationHelper.GetLoc(logicConfig.S_LKBKHCLOC); if (kgzStartLoc == null) { WMSHelper.DeleteWmsTask(wmsTask.S_CODE); WMSHelper.addAlarmRecord("流程异常", "高", $"库区:{logicConfig.S_AREA_CODE},没有可用的空工装"); throw new BusinessException($"库区:{logicConfig.S_AREA_CODE},没有可用的空工装"); } if (kgzEndLoc == null) { WMSHelper.DeleteWmsTask(wmsTask.S_CODE); WMSHelper.addAlarmRecord("流程异常", "中", $"空工装缓存位:{logicConfig.S_LKBKHCLOC},没有在WMS系统中录入"); throw new BusinessException($"空工装缓存位:{logicConfig.S_LKBKHCLOC},没有在WMS系统中录入"); } var locCntrRels = LocationHelper.GetLocCntr(kgzStartLoc.S_CODE); if (locCntrRels.Count > 0) { string kgzCntrCode = locCntrRels[0].S_CNTR_CODE; // 如是胎侧直连模式,则提高空工装出库任务优先级 if (logicConfig.S_TASK_TYPE == "1") { priority = 99; } WCSTask kgzWcsTask = new WCSTask() { S_OP_NAME = wmsTask.S_OP_DEF_NAME, S_OP_CODE = wmsTask.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = kgzCntrCode, S_TYPE = "空工装出库任务", S_START_LOC = kgzStartLoc.S_CODE, S_START_AREA = kgzStartLoc.S_AREA_CODE, S_END_LOC = kgzEndLoc.S_CODE, S_END_AREA = kgzEndLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "WCS", N_PRIORITY = priority, T_START_TIME = DateTime.Now, }; taskDic.Add(priority, kgzWcsTask); } else { WMSHelper.DeleteWmsTask(wmsTask.S_CODE); WMSHelper.addAlarmRecord("流程异常", "高", $"查询空工装货位错误,货位:{kgzStartLoc.S_CODE}没有空工装"); throw new BusinessException($"查询空工装货位错误,货位:{kgzStartLoc.S_CODE}没有空工装"); } } // 如是帘布直连模式则,提高满料入库优先级 if (logicConfig.S_TASK_TYPE == "2") { priority = 99; } else { priority = 10; } WCSTask wcsTask = new WCSTask() { S_OP_NAME = wmsTask.S_OP_DEF_NAME, S_OP_CODE = wmsTask.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = wmsTask.S_CNTR_CODE, S_TYPE = wmsTask.S_TYPE, S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "WCS", N_PRIORITY = priority, T_START_TIME = DateTime.Now, }; taskDic.Add(priority, wcsTask); var tasks = taskDic.OrderByDescending(a => a.Key).Select(a => a.Value).ToList(); foreach (var task in tasks) { if (WCSHelper.CreateTask(task)) { // 起点、终点加锁 LocationHelper.LockLoc(task.S_START_LOC, 2); LocationHelper.LockLoc(task.S_END_LOC, 1); } } // 更新作业任务状态 wmsTask.N_B_STATE = 1; WMSHelper.UpdateTaskState(wmsTask); // 5.作业创建完成后,读取中间表,更新中间表状态 if (mesTask != null) { WMSHelper.readLjMesOffItemTask(wmsTask.S_CODE, mesTask.ID); } else { ContainerHelper.UpdateCntrState(cntrNo, 1); WMSHelper.addRfidAnomalyRecord(cntrNo, 3, offLineLoc, null); } } } catch (BusinessException be) { throw be; } catch (Exception ex) { // 报警:WMS内部错误:触发满料工装下线作业错误 WMSHelper.addAlarmRecord("系统错误", "高", ex.Message); LogHelper.Info($"WMS内部错误:触发满料工装下线作业错误 ; 错误原因:{ex.Message}", "WMS"); result = false; } return result; } /// /// 叫料请求 /// 1.查询中间表,判断是否是环带物料 /// 2.查询库区物料信息,并过滤故障的堆垛机立库 /// 3.无库存写入中间表异常和异常原因 /// 4.计算出库货位,生成出库任务 /// /// /// public static ResponseResult callMaterialProcess(CallMaterialRequest model) { ResponseResult responseResult = new ResponseResult(); var mesTask = WMSHelper.getLjMesTaskByLoc(model.loc); if (mesTask != null) { Location endLoc = LocationHelper.GetLoc(model.loc); Location startLoc = null; Location middleLoc = null; string scheduleType = ""; if (mesTask.PALLET_TYPE == "环带") { scheduleType = "HDK"; // 查询环带库该物料库存情况,并比较与中转库的库存进行比较,先入先出 } else { scheduleType = "WCS"; // 查询库区物料信息,根据先入先出原则计算,物料起点 startLoc = WMSHelper.getOutStockStartLoc(null, mesTask.MATERIAL_CODE); } if (startLoc == null) { // 无库存写入中间表异常和异常原因 mesTask.RETURN_CODE = "6"; mesTask.RECEIVE_MSG = "没有库存或设备故障无法出库"; WMSHelper.updateLjMesTask(mesTask); WMSHelper.addAlarmRecord("流程异常", "低", $"MES叫料任务{mesTask.ID},没有库存或设备故障无法出库"); responseResult.code = 1; responseResult.msg = "没有库存或设备故障无法出库"; return responseResult; } middleLoc = WMSHelper.GetMinTaskTransfeLoc(startLoc.S_AREA_CODE, 2 , 2); if (middleLoc == null) { WMSHelper.addAlarmRecord("流程异常", "高", $"MES叫料任务{mesTask.ID},立库接驳位可能处于锁定或禁用状态,请查看"); responseResult.code = 1; responseResult.msg = "立库接驳位可能处于锁定或禁用状态"; return responseResult; } String cntrCode = ""; var locCntrs = LocationHelper.GetLocCntr(startLoc.S_CODE); if (locCntrs != null && locCntrs.Count > 0) { cntrCode = locCntrs[0].S_CNTR_CODE; } var wmsTask = new WMSTask() { S_CNTR_CODE = "", S_CODE = WMSHelper.GenerateTaskNo(), S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_TYPE = "满料出库任务", N_PRIORITY = 10, T_START_TIME = DateTime.Now, }; if (WMSHelper.CreateWmsTask(wmsTask)) { // 创建一段入库任务 WCSTask wcsTask = new WCSTask() { S_OP_NAME = wmsTask.S_OP_DEF_NAME, S_OP_CODE = wmsTask.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = wmsTask.S_CNTR_CODE, S_TYPE = wmsTask.S_TYPE, S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = middleLoc.S_CODE, S_END_AREA = middleLoc.S_AREA_CODE, S_SCHEDULE_TYPE = scheduleType, N_PRIORITY = wmsTask.N_PRIORITY, T_START_TIME = DateTime.Now, }; if (WCSHelper.CreateTask(wcsTask)) { // 起点、终点加锁 LocationHelper.LockLoc(wcsTask.S_START_LOC, 2); LocationHelper.LockLoc(wcsTask.S_END_LOC, 1); LocationHelper.LockLoc(wmsTask.S_END_LOC, 1); // 更新作业任务状态 wmsTask.N_B_STATE = 1; WMSHelper.UpdateTaskState(wmsTask); WMSHelper.updateMesTaskStatus("", "2"); // 任务创建成功读取MES任务 WMSHelper.readLjMesCallItemTask("", mesTask.ID); } } } else { WMSHelper.addAlarmRecord("流程异常", "高", $"MES叫料任务{mesTask.ID},MES中间表没有该线边货位的叫料任务,请查看"); responseResult.code = 1; responseResult.msg = "MES中间表没有该线边货位的叫料任务"; } return responseResult; } /// /// WCS任务状态回报 /// 任务状态 1:开始/执行中;完成;3:准备取货;4:取货完成;5:准备卸货;6:卸货完成;7:异常取消;8:强制完成 /// 1.根据任务状态回报更新货位状态、任务状态 /// 2.更新任务中间表状态 /// 4.更新出库任务中间表状态 /// /// /// public static ResponseResult taskStatusFeedback(TaskStatusFeedbackModel model) { ResponseResult responseResult = new ResponseResult(); WCSTask cst = WCSHelper.GetTask(model.taskNo); if (cst != null) { WMSTask mst = WMSHelper.GetWmsTask(cst.S_OP_CODE); if (mst != null) { switch (model.status) { case 1: WCSHelper.Begin(cst); WMSHelper.updateMesTaskStatus(mst.S_CODE, "2"); if (cst.S_TYPE.Contains("出库")) { WMSHelper.addLotOutTask(mst.S_START_LOC); } break; case 2: WCSHelper.End(cst); break; case 3: WCSHelper.UpdateStatus(cst, "准备取货"); break; case 4: WCSHelper.UpdateStatus(cst, "取货完成"); TaskProcess.OperateStatus(cst, 4); break; case 5: WCSHelper.UpdateStatus(cst, "准备卸货"); break; case 6: WCSHelper.UpdateStatus(cst, "卸货完成"); TaskProcess.OperateStatus(cst, 6); break; case 7: WCSHelper.UpdateStatus(cst, "异常取消"); TaskProcess.OperateStatus(cst, 7); mst.N_B_STATE = 3; WMSHelper.UpdateTaskState(mst); WMSHelper.updateMesTaskStatus(mst.S_CODE, "5", "WCS异常取消任务"); WMSHelper.addAlarmRecord("流程异常", "高", $"WCS异常取消任务,任务号:{cst.S_CODE}"); break; case 8: WCSHelper.UpdateStatus(cst, "强制完成"); break; } // 添加WCS动作记录 WCSHelper.AddActionRecord(model.taskNo, model.status, model.deviceNo, model.loc); if (model.status == 2 || model.status == 8) { if (cst.S_TYPE.Contains("入库")) { var cntrItemRels = ContainerHelper.GetCntrItemRel(cst.S_CNTR_CODE); if (cntrItemRels != null && cntrItemRels.Count > 0) { foreach (var cntrItem in cntrItemRels) { cntrItem.T_INBOUND_TIME = DateTime.Now; ContainerHelper.updateCntrItemRel(cntrItem); } } } if (cst.S_TYPE.Contains("【异常】")) { WCSHelper.ActivatePreCreateTask(mst.S_CODE, 1); } else { WCSHelper.ActivatePreCreateTask(mst.S_CODE); } if (WMSHelper.isFinishTask(mst.S_CODE)) { // 更新作业任务状态 mst.N_B_STATE = 2; mst.T_END_TIME = DateTime.Now; WMSHelper.UpdateTaskState(mst); // 更新任务中间表状态 WMSHelper.updateMesTaskStatus(mst.S_CODE, "3"); if (cst.S_TYPE.Contains("出库")) { // 更新出库任务中间表状态 WMSHelper.updateLotOutTask(cst.S_CNTR_CODE, "2"); } } } } } return responseResult; } /// /// WCS申请终点 /// /// /// public static ResponseResult applyDest(ApplyDestinationModel model) { ResponseResult result = new ResponseResult(); ApplyDest applyDest = new ApplyDest(); WCSTask cst = WCSHelper.GetTask(model.taskNo); if (cst != null && cst.N_B_STATE < 3) { WMSTask mst = WMSHelper.GetWmsTask(cst.S_OP_CODE); if (mst != null && mst.N_B_STATE < 2) { int emptyFlag = 0; // 容器空满标识 var cntrItemRels = ContainerHelper.GetCntrItemRel(cst.S_CNTR_CODE); if (cntrItemRels.Count > 0) { emptyFlag = 1; } // 1:堆垛机放货异常申请新终点 if (model.applyType == 1) { // 报警:流程异常 WMSHelper.addAlarmRecord("流程异常", "中", $"堆垛机放货异常,任务号:{cst.S_CODE},异常货位:{cst.S_END_LOC}"); // 1.将异常货位上锁,并报警 LocationHelper.LockLoc(cst.S_END_LOC, 3); // 2.查询新的入库终点 Location endLoc = WMSHelper.getInStockEndLoc(cst.S_END_AREA, emptyFlag ); cst.S_END_LOC = endLoc.S_CODE; WCSHelper.UpdateEndLoc(cst); LocationHelper.LockLoc(endLoc.S_CODE, 1); applyDest.destLoc = endLoc.S_CODE; } } } result.data = applyDest; return result; } /// /// AGV申请终点 /// 顺序 RFID验证 -> RFID与任务号验证 -> 物料合格状态验证 -> 虚拟终点 /// 申请类型: 1.正常 2.异常 /// 入库策略:先计算库区的容积率,再计算库区对应的入库站台的任务数,都取最小的 /// /// 1.确定任务是否在执行中 /// 2.判断申请类型 /// 1).虚拟终点,计算入库站台,同时预先生成入库站台-立库终点的搬运任务 /// 2).RFID验证失败,记录异常,并计算异常区的空货位 /// 3).RFID与任务不匹配,记录异常并报警,并计算异常区的空货位 /// 4).物料状态不合格,记录异常,计算入库站台,同时预先生成入库站台-立库终点的搬运任务 ;最后重新生成新的出库任务 /// /// 3. 2)\3) 异常区没有空货位,计算入库站台,同时预先生成入库站台-立库终点的搬运任务 /// /// 4.余料/空工装回库任务 /// 1).根据RFID查询中间表,判断物料类型,如为空工装,正常入库(计算入库站台,生成预创建搬运任务) /// 2).如是余料,查询是否有余料有关的叫料任务,且未执行,则取消叫料任务,修改终点为该叫料终点 /// 3).如没有相关叫料任务,则正常入库 /// /// 5.空工装出库和成型机叫料任务,当申请类型为2,3,4是,需要重新生成任务 /// /// /// /// /// 1.正常 2.异常 /// public static string AGVApplyDest(string taskNo ,string loc ,string trayCode,string applyType) { LogHelper.Info($"AGV申请终点,任务号:{taskNo},当前位置:{loc},申请类型:{applyType}", "HosttoagvTask"); string applyDest = null; try { WCSTask cst = WCSHelper.GetTask(taskNo); if (cst != null && cst.N_B_STATE < 3) { WMSTask mst = WMSHelper.GetWmsTask(cst.S_OP_CODE); if (mst != null && mst.N_B_STATE < 2) { // 防止重复申请 if ((applyType != "1" && !cst.S_TYPE.Contains("【异常】")) || (applyType == "1" && cst.S_END_LOC.Contains("虚拟货位"))) { // 斜裁立库 if (mst.S_OP_DEF_NAME.Contains("斜裁")) { applyDest = applyAgvDestXC(applyType, mst, cst); } else { applyDest = applyAgvDest(applyType, loc, mst, cst); } } } } } catch (Exception ex) { WMSHelper.addAlarmRecord("系统错误","高", $"AGV申请终点,WMS内部错误,错误原因:{ex.Message}", "AGV"); } LogHelper.Info($"变更AGV终点:{applyDest}", "AGV"); return applyDest; } /// /// 斜裁立库任务,AGV申请终点 /// 1).根据RFID查询中间表,判断物料类型,如为空工装,正常入库(计算入库站台,生成预创建搬运任务) /// 2).如是余料,查询是否有余料有关的叫料任务,且未执行,则取消叫料任务,修改终点为该叫料终点 /// /// /// /// /// public static string applyAgvDestXC(string applyType, WMSTask mst, WCSTask cst) { Location endLoc = null; if (applyType == "1") { if (mst.S_TYPE == "余料/空工装入库") { var bo = int.TryParse(mst.S_OP_DEF_CODE, out int mesId); if (bo) { var mesTask = WMSHelper.GetLjMesTaskById(mesId); if (mesTask.QTY != 0) { var awaitTask = WMSHelper.GetAwaitWmsTaskByMaterialCode(mesTask.MATERIAL_CODE); if (awaitTask != null) { // 取消任务 ApiHelper.cancelTask(awaitTask.S_CODE); // 修改终点 endLoc = LocationHelper.GetLoc(awaitTask.S_END_LOC); mst.S_TYPE = "叫料出库任务"; } } } } } if (endLoc == null) { string msg = ""; if (applyType == "2") { cst.S_TYPE = cst.S_TYPE + "【异常】"; msg = "工装异常"; } // TODO 反馈斜裁立库异常,请求斜裁入库终点 string locCode = "XCCRKZTKQ-1-1"; endLoc = LocationHelper.GetLoc(locCode); } if (endLoc != null) { cst.S_END_LOC = endLoc.S_CODE; cst.S_END_AREA = endLoc.S_AREA_CODE; WCSHelper.UpdateEndLoc(cst); mst.S_END_LOC = endLoc.S_CODE; mst.S_END_AREA = endLoc.S_AREA_CODE; WMSHelper.UpdateTaskEnd(mst); return endLoc.S_CODE; } return null; } /// /// AGV申请终点 /// 场景:1.余料/空工装入库任务(成型机) 2.满料/空工装入库(机台) 3.满料/空工装出库异常 4.满料/空工装入库异常 /// /// 1.正常 2.RFID与任务RFID不匹配 3.物料状态不合格 /// /// /// /// public static string applyAgvDest(string applyType,string loc, WMSTask mst, WCSTask cst) { LogHelper.Info($"开始申请AGV终点", "AGV"); string destLoc = null; Location agvEndLoc = null; Location wmsEndLoc = null; Location currentLoc = LocationHelper.GetLoc(loc); // RFID 检测正常 if (applyType == "1") { // 场景:1.余料/空工装入库任务 // 1).根据RFID查询中间表,判断物料类型,如为空工装,正常入库(计算入库站台,生成预创建搬运任务) // 2).如是余料,查询是否有余料有关的叫料任务,且未执行,则取消叫料任务,修改终点为该叫料终点 if (cst.S_TYPE.Contains("余料/空工装入库")) { LogHelper.Info($"余料/空工装入库任务,判断是否回库或发往叫料点", "AGV"); var mesTask = WMSHelper.GetLjMesTaskById(int.Parse(mst.S_OP_DEF_CODE)); if (mesTask.QTY != 0) { var awaitTask = WMSHelper.GetAwaitWmsTaskByMaterialCode(mesTask.MATERIAL_CODE); if (awaitTask != null) { LogHelper.Info($"余料/空工装入库任务,存在等待的叫料任务,发往叫料点", "AGV"); // 取消任务 ApiHelper.cancelTask(awaitTask.S_CODE); // 修改终点 agvEndLoc = LocationHelper.GetLoc(awaitTask.S_END_LOC); cst.S_TYPE = "叫料出库任务"; mst.S_TYPE = mst.S_TYPE + "【叫料】"; } } } // 场景:1.满料/空工装入库 2.余料/空工装入库 if (agvEndLoc == null && cst.S_TYPE.Contains("入库")) { LogHelper.Info($"如没有满足条件的agv终点货位,则发往立库", "AGV"); Container container = ContainerHelper.GetCntr(cst.S_CNTR_CODE); if (container != null) { wmsEndLoc = WMSHelper.getInStockEndLoc(null, container.N_DETAIL_COUNT == 0 ? 0 : 1, container.N_TYPE); if (wmsEndLoc != null) { agvEndLoc = WMSHelper.GetMinTaskTransfeLoc(wmsEndLoc.S_AREA_CODE, 1, 2); // 1.立库接驳位 1.入库 2.非直连 if (agvEndLoc != null) { LogHelper.Info($"创建立库站台到立库的预创建任务,agv终点货位:{agvEndLoc.S_CODE},立库终点货位:{wmsEndLoc.S_CODE}", "AGV"); // 预先生成入库站台-立库终点的搬运任务 WCSTask wcsTask = new WCSTask() { S_OP_NAME = mst.S_OP_DEF_NAME, S_OP_CODE = mst.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = cst.S_CNTR_CODE, S_TYPE = mst.S_TYPE, S_START_LOC = agvEndLoc.S_CODE, S_START_AREA = agvEndLoc.S_AREA_CODE, S_END_LOC = wmsEndLoc.S_CODE, S_END_AREA = wmsEndLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "WCS", N_PRIORITY = 10, N_B_STATE = -1, T_START_TIME = DateTime.Now, }; if (WCSHelper.CreateTask(wcsTask)) { // 起点、终点加锁 LocationHelper.LockLoc(wcsTask.S_START_LOC, 1); LocationHelper.LockLoc(wcsTask.S_END_LOC, 1); } } else { WMSHelper.addAlarmRecord("流程异常", "高", $"AGV申请终点失败,立库:{wmsEndLoc.S_AREA_CODE}未配置立库接驳位"); return null; } } else { WMSHelper.addAlarmRecord("流程异常", "高", $"AGV申请终点失败,未查询到空余立库货位"); return null; } } else { WMSHelper.addAlarmRecord("流程异常", "高", $"AGV申请终点失败,未查询到容器编码:{cst.S_CNTR_CODE}的容器"); return null; } } } // 场景:1.满料/空工装出库异常 2.满料/空工装入库异常(空工装出库异常 、满料入库异常) if (applyType == "2" ) { WCSHelper.CancelPreCreateTask(mst.S_CODE); mst.S_TYPE = mst.S_TYPE + "【异常】"; // 1.异常工装优先发往异常区 LogHelper.Info($"异常工装优先发往异常区", "AGV"); agvEndLoc = WMSHelper.getAbnormalAreaLoc(currentLoc.S_AREA_CODE); if (agvEndLoc != null) { wmsEndLoc = agvEndLoc; } else { LogHelper.Info($"异常区没有空货位,发往立库", "AGV"); } // 2.异常区没有空货位,则发往立库 if (agvEndLoc == null) { LogHelper.Info($"如没有满足条件的agv终点货位,则发往立库", "AGV"); Container container = ContainerHelper.GetCntr(cst.S_CNTR_CODE); if (container != null) { wmsEndLoc = WMSHelper.getInStockEndLoc(null, container.N_DETAIL_COUNT == 0 ? 0 : 1, container.N_TYPE); if (wmsEndLoc != null) { agvEndLoc = WMSHelper.GetMinTaskTransfeLoc(wmsEndLoc.S_AREA_CODE, 1, 2); // 1.立库接驳位 1.入库 2.非直连 if (agvEndLoc != null) { LogHelper.Info($"创建立库站台到立库的预创建任务,agv终点货位:{agvEndLoc.S_CODE},立库终点货位:{wmsEndLoc.S_CODE}", "AGV"); // 预先生成入库站台-立库终点的搬运任务 WCSTask wcsTask = new WCSTask() { S_OP_NAME = mst.S_OP_DEF_NAME, S_OP_CODE = mst.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = cst.S_CNTR_CODE, S_TYPE = cst.S_TYPE + "【异常】", S_START_LOC = agvEndLoc.S_CODE, S_START_AREA = agvEndLoc.S_AREA_CODE, S_END_LOC = wmsEndLoc.S_CODE, S_END_AREA = wmsEndLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "WCS", N_PRIORITY = 10, N_B_STATE = -1, S_B_STATE = "预创建", T_START_TIME = DateTime.Now, }; if (WCSHelper.CreateTask(wcsTask)) { // 起点、终点加锁 LocationHelper.LockLoc(wcsTask.S_START_LOC, 1); LocationHelper.LockLoc(wcsTask.S_END_LOC, 1); cst.S_TYPE = cst.S_TYPE + "【异常】"; } } else { WMSHelper.addAlarmRecord("流程异常", "高", $"AGV申请终点失败,未查询到立库接驳位"); return null; } } else { WMSHelper.addAlarmRecord("流程异常", "高", $"AGV申请终点失败,未查询到空余立库货位"); return null; } } else { WMSHelper.addAlarmRecord("流程异常", "高", $"AGV申请终点失败,未查询到容器编码:{cst.S_CNTR_CODE}的容器"); return null; } } var mesTask = WMSHelper.GetLjMesTaskByAgvorderId(mst.S_CODE); if (mesTask != null) { if (mst.S_TYPE.Contains("叫料出库任务")) { LogHelper.Info($"叫料出库任务异常,再次发起叫料出库任务", "AGV"); callMaterial(mesTask.MATERIAL_CODE, mesTask.POSITION_ID, mesTask.ID); } // 满料下线(非直连) if (mst.S_TYPE.Contains("满料/异常工装入库任务") && cst.S_TYPE.Contains("空工装出库任务")) { LogHelper.Info($"满料/异常工装入库任务异常,再次发起满料/异常工装入库任务", "AGV"); var logicConfig = WMSHelper.getLogicConfigByJtCode(mesTask.EQP); if (logicConfig != null) { triggerItemOffLineFlow4(mesTask.POSITION_ID, mst.S_CNTR_CODE, logicConfig, mesTask); } else { WMSHelper.addAlarmRecord("流程异常", "高", $"MES任务{mesTask.ID},机台号:{mesTask.EQP},未查询到逻辑线路", "AGV"); } } } } if (agvEndLoc != null && wmsEndLoc != null) { destLoc = agvEndLoc.S_CODE; cst.S_END_LOC = agvEndLoc.S_CODE; cst.S_END_AREA = agvEndLoc.S_AREA_CODE; WCSHelper.UpdateEndLoc(cst); mst.S_END_LOC = wmsEndLoc.S_CODE; mst.S_END_AREA = wmsEndLoc.S_AREA_CODE; WMSHelper.UpdateTaskEnd(mst); } return destLoc; } /// /// 成新机叫料 /// /// /// /// public static void callMaterial(string materialCode, string jtNo, int mesTaskId) { string cntrCode = ""; var mesTask = WMSHelper.GetLjMesTaskById(mesTaskId); if (mesTask != null) { Location endLoc = WMSHelper.getCallMaterialLocCode(jtNo); if (endLoc != null) { Location middleLoc = null; Location startLoc = WMSHelper.getOutStockStartLoc(null, materialCode); if (startLoc != null) { var locCntrRels = LocationHelper.GetLocCntr(startLoc.S_CODE); if (locCntrRels.Count > 0) { cntrCode = locCntrRels[0].S_CNTR_CODE; middleLoc = WMSHelper.GetTransfeRelevanceLoc(startLoc.S_AREA_CODE, 2, 2); if (middleLoc != null) { // 1.创建成新机叫料作业 var wmsTask = new WMSTask() { S_CNTR_CODE = cntrCode, S_CODE = WMSHelper.GenerateTaskNo(), S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_TYPE = "叫料出库任务", S_OP_DEF_CODE = mesTaskId.ToString(), S_OP_DEF_NAME = "成型机叫料出库任务", T_START_TIME = DateTime.Now, }; if (WMSHelper.CreateWmsTask(wmsTask)) { WCSTask wcsTask = new WCSTask() { S_OP_NAME = wmsTask.S_OP_DEF_NAME, S_OP_CODE = wmsTask.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = wmsTask.S_CNTR_CODE, S_TYPE = wmsTask.S_TYPE, S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = middleLoc.S_CODE, S_END_AREA = middleLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "WCS", N_PRIORITY = 10, T_START_TIME = DateTime.Now, }; if (WCSHelper.CreateTask(wcsTask)) { // 起点、终点加锁 LocationHelper.LockLoc(wcsTask.S_START_LOC, 2); LocationHelper.LockLoc(wcsTask.S_END_LOC, 1); // 更新作业任务状态 wmsTask.N_B_STATE = 1; WMSHelper.UpdateTaskState(wmsTask); } // 预创建二段任务 WCSTask twoWcsTask = new WCSTask() { S_OP_NAME = wmsTask.S_OP_DEF_NAME, S_OP_CODE = wmsTask.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = wmsTask.S_CNTR_CODE, S_TYPE = wmsTask.S_TYPE, S_START_LOC = middleLoc.S_CODE, S_START_AREA = middleLoc.S_AREA_CODE, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "AGV", N_PRIORITY = 10, T_START_TIME = DateTime.Now, N_B_STATE = -1 }; WCSHelper.CreateTask(twoWcsTask); WMSHelper.readLjMesCallItemTask(wmsTask.S_CODE, mesTaskId); } } else { WMSHelper.addAlarmRecord("流程异常", "高", $"成型机叫料失败,库区{startLoc.S_AREA_CODE}未查询到可用的接驳位"); } } else { WMSHelper.addAlarmRecord("流程异常", "高", $"成型机叫料失败,开始货位:{startLoc.S_CODE}异常,缺少容器信息"); } } else { mesTask.AWAIT_MSG = "库存不足"; WMSHelper.updateLjMesTask(mesTask); WMSHelper.addAlarmRecord("流程异常", "高", $"成型机叫料失败,物料:{materialCode}库存不足"); } } } } /// /// 成新机叫料(环带库) /// 1.查询环带库物料库存 /// 2.查询中转库库存,根据入库时间 进行先入先出 /// 3.如果为环带库物料,则将mes任务写入环带库任务中间表 /// /// /// /// public static void callMaterialXC(string materialCode, string endLocCode, int mesTaskId) { var mesTask = WMSHelper.GetLjMesTaskById(mesTaskId); if (mesTask != null) { // 1.查询环带库物料库存最早入库时间 DateTime inStockTimeXc = DateTime.MinValue; // 2.查询中转库库存 DateTime inStockTime = WMSHelper.getZZKInventoryInfo(materialCode); // 3.根据先进先出计算出库的物料是环带库 还是中转库 if (inStockTime >= inStockTimeXc) { Location endLoc = WMSHelper.getCallMaterialLocCode(mesTask.EQP); if (endLoc != null) { // 4.创建斜裁-成新机叫料作业 var wmsTask = new WMSTask() { S_CODE = WMSHelper.GenerateTaskNo(), S_CNTR_CODE = "", S_START_LOC = "虚拟起点", S_START_AREA = "虚拟库区", S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_TYPE = "叫料出库任务", S_OP_DEF_CODE = mesTask.ID.ToString(), S_OP_DEF_NAME = "成型机叫料出库任务(斜裁)", T_START_TIME = DateTime.Now, N_B_STATE = 0 }; if (WMSHelper.CreateWmsTask(wmsTask)) { WCSTask wcsTask = new WCSTask() { S_OP_NAME = wmsTask.S_OP_DEF_NAME, S_OP_CODE = wmsTask.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = wmsTask.S_CNTR_CODE, S_TYPE = wmsTask.S_TYPE, S_START_LOC = wmsTask.S_START_LOC, S_START_AREA = wmsTask.S_START_AREA, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "AGV", N_PRIORITY = 10, T_START_TIME = DateTime.Now, N_B_STATE = -1, S_B_STATE = "预创建", }; if (WCSHelper.CreateTask(wcsTask)) { // 起点、终点加锁 LocationHelper.LockLoc(wcsTask.S_START_LOC, 2); LocationHelper.LockLoc(wcsTask.S_END_LOC, 1); // 5.将MES任务写入斜裁任务中间表 mesTask.AGVORDER_ID = wcsTask.S_CODE; WMSHelper.addLjXcTask(mesTask); } } } } else { //中转库物料出库 Location startLoc = WMSHelper.getOutStockStartLoc(null, materialCode); if (startLoc != null) { var locCntrRels = LocationHelper.GetLocCntr(startLoc.S_CODE); if (locCntrRels != null && locCntrRels.Count > 0) { Location middleLoc = null; Location endLoc = WMSHelper.getCallMaterialLocCode(mesTask.EQP); if (endLoc != null) { middleLoc = WMSHelper.GetTransfeRelevanceLoc(startLoc.S_AREA_CODE, 2, 2); if (middleLoc != null) { // 1.创建成新机叫料作业 var wmsTask = new WMSTask() { S_CNTR_CODE = locCntrRels[0].S_CNTR_CODE, S_CODE = WMSHelper.GenerateTaskNo(), S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_TYPE = "叫料出库任务", S_OP_DEF_CODE = mesTaskId.ToString(), S_OP_DEF_NAME = "成型机叫料出库任务", T_START_TIME = DateTime.Now, }; if (WMSHelper.CreateWmsTask(wmsTask)) { WCSTask wcsTask = new WCSTask() { S_OP_NAME = wmsTask.S_OP_DEF_NAME, S_OP_CODE = wmsTask.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = wmsTask.S_CNTR_CODE, S_TYPE = wmsTask.S_TYPE, S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = middleLoc.S_CODE, S_END_AREA = middleLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "WCS", N_PRIORITY = 10, T_START_TIME = DateTime.Now, }; if (WCSHelper.CreateTask(wcsTask)) { // 起点、终点加锁 LocationHelper.LockLoc(wcsTask.S_START_LOC, 2); LocationHelper.LockLoc(wcsTask.S_END_LOC, 1); // 更新作业任务状态 wmsTask.N_B_STATE = 1; WMSHelper.UpdateTaskState(wmsTask); } // 预创建二段任务 WCSTask twoWcsTask = new WCSTask() { S_OP_NAME = wmsTask.S_OP_DEF_NAME, S_OP_CODE = wmsTask.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = wmsTask.S_CNTR_CODE, S_TYPE = wmsTask.S_TYPE, S_START_LOC = middleLoc.S_CODE, S_START_AREA = middleLoc.S_AREA_CODE, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "AGV", N_PRIORITY = 10, T_START_TIME = DateTime.Now, N_B_STATE = -1 }; WCSHelper.CreateTask(twoWcsTask); WMSHelper.readLjMesCallItemTask(wmsTask.S_CODE, mesTaskId); } } else { WMSHelper.addAlarmRecord("流程异常", "高", $"成型机叫料失败,库区{startLoc.S_AREA_CODE}未查询到可用的接驳位"); } } else { WMSHelper.addAlarmRecord("流程异常", "高", $"成型机叫料失败,开始货位:{startLoc.S_CODE}异常,缺少容器信息"); } } else { mesTask.AWAIT_MSG = "库存不足"; WMSHelper.updateLjMesTask(mesTask); WMSHelper.addAlarmRecord("流程异常", "高", $"成型机叫料失败,物料:{materialCode}库存不足"); } } } } } /// /// 余料/空托回库 /// /// 1.查询成型机叫料终点对应的 余料/空托返回位 /// 2.查询mes任务中间表是否存在返料任务 /// 3.创建余料回库作业,创建agv搬运任务,虚拟终点 /// /// 成型机叫料终点 /// 成型机叫料终点 public static void returnMaterialOrEmptyTray(string locCode ,string jtNo) { if (locCode != null) { var mesTask = WMSHelper.getLjMesTaskByJtNo(jtNo); if (mesTask != null) { createReturnTask(locCode, mesTask); } } } /// /// 创建余料/空工装返回任务 /// /// /// public static void createReturnTask(string locCode ,LjMesTask mesTask) { Location startLoc = LocationHelper.GetLoc(locCode); Location endLoc = new Location() { S_CODE = "虚拟货位", S_AREA_CODE = "虚拟库区" }; string suffix = ""; if (mesTask.PALLET_TYPE == "5" || mesTask.PALLET_TYPE == "6") { suffix = "(斜裁)"; } var wmsTask = new WMSTask() { S_CNTR_CODE = mesTask.PALLET_ID, S_CODE = WMSHelper.GenerateTaskNo(), S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_TYPE = "余料/空工装入库任务", S_OP_DEF_CODE = mesTask.ID.ToString(), S_OP_DEF_NAME = "余料/空工装入库" + suffix, T_START_TIME = DateTime.Now }; if (WMSHelper.CreateWmsTask(wmsTask)) { // 创建一段入库任务 WCSTask wcsTask = new WCSTask() { S_OP_NAME = wmsTask.S_OP_DEF_NAME, S_OP_CODE = wmsTask.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = wmsTask.S_CNTR_CODE, S_TYPE = wmsTask.S_TYPE, S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "AGV", N_PRIORITY = 99, T_START_TIME = DateTime.Now, }; if (WCSHelper.CreateTask(wcsTask)) { // 起点、接驳点、终点加锁 LocationHelper.LockLoc(wcsTask.S_START_LOC, 2); LocationHelper.LockLoc(wcsTask.S_END_LOC, 1); // 更新作业任务状态 wmsTask.N_B_STATE = 1; WMSHelper.UpdateTaskState(wmsTask); WMSHelper.readLjMesOffItemTask(wmsTask.S_CODE, mesTask.ID); } } } /// /// 不合格品回库 /// 1.创建回库任务 /// 2.重新发起新的叫料任务 /// /// /// /// public static bool rejectReturnStock(WMSTask mst, WCSTask cst) { bool result = true; Location startLoc = LocationHelper.GetLoc(cst.S_END_LOC); Location agvEndLoc = null; Location wmsEndLoc = null; // 斜裁立库 if (mst.S_OP_DEF_NAME.Contains("斜裁")) { // TODO 反馈斜裁立库异常,请求斜裁入库终点 agvEndLoc = null; wmsEndLoc = agvEndLoc; if (agvEndLoc != null) { // 预先生成入库站台-立库终点的搬运任务 WCSTask wcsTask = new WCSTask() { S_OP_NAME = mst.S_OP_DEF_NAME, S_OP_CODE = mst.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = cst.S_CNTR_CODE, S_TYPE = "不合格品入库任务", S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = agvEndLoc.S_CODE, S_END_AREA = agvEndLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "AGV", N_PRIORITY = 10, T_START_TIME = DateTime.Now, }; if (WCSHelper.CreateTask(wcsTask)) { // 起点、接驳点、终点加锁 LocationHelper.LockLoc(wcsTask.S_START_LOC, 1); LocationHelper.LockLoc(wcsTask.S_END_LOC, 1); } } } else { Container container = ContainerHelper.GetCntr(cst.S_CNTR_CODE); wmsEndLoc = WMSHelper.getInStockEndLoc(null, container.N_DETAIL_COUNT == 0 ? 0 : 1, container.N_TYPE); if (wmsEndLoc != null) { agvEndLoc = WMSHelper.GetMinTaskTransfeLoc(wmsEndLoc.S_AREA_CODE, 1, 2); // 1.立库接驳位 1.入库 2.非直连 if (agvEndLoc != null) { // 预先生成入库站台-立库终点的搬运任务 WCSTask oneWcsTask = new WCSTask() { S_OP_NAME = mst.S_OP_DEF_NAME, S_OP_CODE = mst.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = cst.S_CNTR_CODE, S_TYPE = "不合格品入库任务", S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = agvEndLoc.S_CODE, S_END_AREA = agvEndLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "AGV", N_PRIORITY = 10, T_START_TIME = DateTime.Now, }; if (WCSHelper.CreateTask(oneWcsTask)) { // 起点、接驳点、终点加锁 LocationHelper.LockLoc(oneWcsTask.S_START_LOC, 1); LocationHelper.LockLoc(oneWcsTask.S_END_LOC, 1); } // 预先生成入库站台-立库终点的搬运任务 WCSTask twoWcsTask = new WCSTask() { S_OP_NAME = mst.S_OP_DEF_NAME, S_OP_CODE = mst.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = cst.S_CNTR_CODE, S_TYPE = "不合格品入库任务", S_START_LOC = agvEndLoc.S_CODE, S_START_AREA = agvEndLoc.S_AREA_CODE, S_END_LOC = wmsEndLoc.S_CODE, S_END_AREA = wmsEndLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "WCS", N_PRIORITY = 10, N_B_STATE = -1, T_START_TIME = DateTime.Now, }; if (WCSHelper.CreateTask(twoWcsTask)) { // 起点、接驳点、终点加锁 LocationHelper.LockLoc(twoWcsTask.S_START_LOC, 1); LocationHelper.LockLoc(twoWcsTask.S_END_LOC, 1); } } } var bo = int.TryParse(mst.S_OP_DEF_CODE, out int mesId); if (bo) { var mesTask = WMSHelper.GetLjMesTaskById(mesId); callMaterial(mesTask.MATERIAL_CODE, mesTask.POSITION_ID, mesTask.ID); } } return result; } /// /// 查询容器物料信息(中间表) /// /// /// public static ResponseResult findTrayItemInfo(FindTrayItemInfoModel model) { ResponseResult responseResult = new ResponseResult(); var cntrItemRels = ContainerHelper.GetCntrItemRel(model.cntrNo); if (cntrItemRels != null && cntrItemRels.Count > 0) { TrayItemInfo trayItemInfo = new TrayItemInfo() { S_SERIAL_NO = cntrItemRels[0].S_SERIAL_NO, S_ITEM_CODE = cntrItemRels[0].S_ITEM_CODE, S_ITEM_NAME = cntrItemRels[0].S_ITEM_NAME, S_ITEM_SPEC = cntrItemRels[0].S_ITEM_SPEC, S_ITEM_STATE = cntrItemRels[0].S_ITEM_STATE, N_ITEM_STATE = cntrItemRels[0].N_ITEM_STATE, S_BATCH_NO = cntrItemRels[0].S_BATCH_NO, F_QTY = cntrItemRels[0].F_QTY, S_UOM = cntrItemRels[0].S_UOM, S_CNTR_CODE = cntrItemRels[0].S_CNTR_CODE, D_PRD_DATE = cntrItemRels[0].D_PRD_DATE, D_EXP_DATE = cntrItemRels[0].D_EXP_DATE, D_EXP_DATE1 = cntrItemRels[0].D_EXP_DATE1, }; responseResult.data = trayItemInfo; } return responseResult; } /// /// 设备报警反馈 /// /// /// public static ResponseResult notifyAlarm(DeviceAlertorFeedbackModel model) { ResponseResult responseResult = new ResponseResult(); WMSHelper.addAlarmRecord("设备故障", "高", $"设备号{model.deviceNo},错误信息:"+model.errMsg); return responseResult; } /// /// 人工手动入库 /// 2.根据容器号查询入库任务 /// 3.如果没有入库任务,记录异常 /// 4.进行入库 /// /// /// public static ResponseResult manualStorage(ManualStorageModel model) { ResponseResult responseResult = new ResponseResult(); // 查询中间表 var ljMesTask = WMSHelper.getLjMesTaskByCntr( model.cntrNo); if (ljMesTask == null) { responseResult.code = 1; responseResult.msg = "未查询到MES下发的入库任务"; return responseResult; } string taskType = ""; if (ljMesTask.QTY == 0) { taskType = "空工装人工入库"; } else { taskType = "满料工装人工入库"; } var startLoc = LocationHelper.GetLoc(model.from); var transfeRele = WMSHelper.GetTransfeRelevance(model.from); // 接驳位属性 if (transfeRele != null) { var endLoc = WMSHelper.getInStockEndLoc(transfeRele.S_RELE_AREA, ljMesTask.QTY); if (startLoc == null) { responseResult.code = 1; responseResult.msg = "接驳位不存在,请检查起点货位编码是否有误"; return responseResult; } if (endLoc == null) { responseResult.code = 1; responseResult.msg = "立库空余库位不足"; return responseResult; } var wmsTask = new WMSTask() { S_CNTR_CODE = model.cntrNo, S_CODE = WMSHelper.GenerateTaskNo(), S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_TYPE = taskType, S_OP_DEF_CODE = ljMesTask.ID.ToString(), S_OP_DEF_NAME = "人工入库任务", N_PRIORITY = 1, T_START_TIME = DateTime.Now }; if (WMSHelper.CreateWmsTask(wmsTask)) { // 创建一段入库任务 WCSTask wcsTask = new WCSTask() { S_OP_NAME = wmsTask.S_OP_DEF_NAME, S_OP_CODE = wmsTask.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = wmsTask.S_CNTR_CODE, S_TYPE = wmsTask.S_TYPE + "-WCS", S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "WCS", N_PRIORITY = wmsTask.N_PRIORITY, T_START_TIME = DateTime.Now, }; if (WCSHelper.CreateTask(wcsTask)) { // 起点、接驳点、终点加锁 LocationHelper.LockLoc(wcsTask.S_START_LOC, 2); LocationHelper.LockLoc(wcsTask.S_END_LOC, 1); // 更新作业任务状态 wmsTask.N_B_STATE = 1; WMSHelper.UpdateTaskState(wmsTask); WMSHelper.readLjMesOffItemTask(wmsTask.S_CODE ,ljMesTask.ID); } } } else { WMSHelper.addAlarmRecord("流程异常", "中", $"接驳位:{model.from},缺少属性配置项,请联系管理进行配置"); responseResult.code = 1; responseResult.msg = $"接驳位缺少属性配置项,请联系管理进行配置"; } return responseResult; } /// /// 人工出库 /// /// /// public static ResponseResult manualDelivery(ManualDeliveryModel model) { ResponseResult responseResult = new ResponseResult(); // 查询中间表 var ljMesTask = WMSHelper.getLjMesTaskByLoc(model.to); if (ljMesTask == null) { responseResult.code = 1; responseResult.msg = "未查询到MES任务表数据"; return responseResult; } string taskType = ""; if (ljMesTask.QTY == 0) { taskType = "空工装人工出库"; } else { taskType = "满料工装人工出库"; } var endLoc = LocationHelper.GetLoc(model.to); var transfeRele = WMSHelper.GetTransfeRelevance(model.to); // 接驳位属性 if (transfeRele != null) { var startLoc = WMSHelper.getOutStockStartLoc(transfeRele.S_RELE_AREA, model.materialCode,model.trayStatus, model.cntrNo); if (endLoc == null) { responseResult.code = 1; responseResult.msg = "接驳位不存在,请检查起点货位编码是否有误"; return responseResult; } if (startLoc == null) { responseResult.code = 1; responseResult.msg = "立库库存不足"; return responseResult; } var wmsTask = new WMSTask() { S_CNTR_CODE = model.cntrNo, S_CODE = WMSHelper.GenerateTaskNo(), S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_TYPE = taskType, S_OP_DEF_NAME = "人工出库任务", N_PRIORITY = 1, T_START_TIME = DateTime.Now }; if (WMSHelper.CreateWmsTask(wmsTask)) { // 创建一段入库任务 WCSTask wcsTask = new WCSTask() { S_OP_NAME = wmsTask.S_OP_DEF_NAME, S_OP_CODE = wmsTask.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = wmsTask.S_CNTR_CODE, S_TYPE = wmsTask.S_TYPE + "-WCS", S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "WCS", N_PRIORITY = wmsTask.N_PRIORITY, T_START_TIME = DateTime.Now, }; if (WCSHelper.CreateTask(wcsTask)) { // 起点、接驳点、终点加锁 LocationHelper.LockLoc(wcsTask.S_START_LOC, 2); LocationHelper.LockLoc(wcsTask.S_END_LOC, 1); // 更新作业任务状态 wmsTask.N_B_STATE = 1; WMSHelper.UpdateTaskState(wmsTask); WMSHelper.readLjMesOffItemTask(wmsTask.S_CODE, ljMesTask.ID); } } } else { WMSHelper.addAlarmRecord("流程异常", "中", $"接驳位:{model.to},缺少属性配置项,请联系管理进行配置"); responseResult.code = 1; responseResult.msg = $"接驳位缺少属性配置项,请联系管理进行配置"; } return responseResult; } /// /// 取消任务 /// /// public static ResponseResult cancelTask(string taskNo) { ResponseResult responseResult = new ResponseResult(); WMSTask wmsTask = WMSHelper.GetWmsTask(taskNo); if (wmsTask != null && wmsTask.N_B_STATE == 0) { var wcsTaskList = WCSHelper.GetTaskListBySrcNo(wmsTask.S_CODE); foreach (var wcsTask in wcsTaskList) { if (wcsTask != null && wcsTask.N_B_STATE < 3) { WCSHelper.Fail(wcsTask); LocationHelper.UnLockLoc(wcsTask.S_START_LOC); LocationHelper.UnLockLoc(wcsTask.S_END_LOC); } } wmsTask.N_B_STATE = 3; wmsTask.S_B_STATE = "取消"; wmsTask.T_END_TIME = DateTime.Now; WMSHelper.UpdateTaskState(wmsTask); } return responseResult; } /// /// 切换站台属性 /// /// /// public static ResponseResult switchStationAttribute(SwitchStationAttributeModel model) { ResponseResult responseResult = new ResponseResult(); var task = WCSHelper.GetTaskByStartOrEnd(model.locCode); if (task == null) { var transfeRelevance = WMSHelper.GetTransfeRelevance(model.locCode); // 接驳位属性 LogHelper.Info($"原站台属性:{JsonConvert.SerializeObject(transfeRelevance)}", "WMS"); if (transfeRelevance != null && transfeRelevance.N_PROPERTY == 2) { if (model.signalType == "1") { WMSHelper.updateTransfeLocProperty(model.locCode, 0); } if (model.signalType == "2") { WMSHelper.updateTransfeLocProperty(model.locCode, 1); } } } else { responseResult.code = 1; responseResult.msg = "接驳位存在未完成的任务,无法切换站台属性"; } return responseResult; } /// /// 货位状态反馈 /// /// /// public static bool locStateFeedBack(LocStateFeedBackModel model) { bool result = false; if (model.type == "1") { var task = WCSHelper.GetTask(model.req_no); if (task != null) { TaskAction taskAction = null; if (model.type == "1") { taskAction = WCSHelper.getActionRecord(task.S_CODE, 1101); } if (model.type == "2") { taskAction = WCSHelper.getActionRecord(task.S_CODE, 1102); } if (taskAction != null) { taskAction.N_S_STATUS = 1; result = WCSHelper.updateActionRecord(taskAction); } } } return result; } /// /// 斜裁物料出库任务 /// /// /// public static ResponseResult createXcItemOutStockTask(XcItemOutStockModel model) { ResponseResult responseResult = new ResponseResult(); Location startLoc = LocationHelper.GetLoc(model.startLoc); if (startLoc == null) { WMSHelper.addAlarmRecord("流程异常", "高", $"成型机叫料出库(斜裁),起点:{model.startLoc}在WMS系统中不存在"); responseResult.code = 201; responseResult.msg = $"起点:{model.startLoc}在WMS系统中不存在"; return responseResult; } Location endLoc = WMSHelper.getCallMaterialLocCode(model.eqNo); if (endLoc != null) { var wmsTask = WMSHelper.GetWmsTaskByCntr(model.palletId); if (wmsTask == null) { ContainerHelper.AddCntr(model.palletId); // 1.创建斜裁-成新机叫料作业 wmsTask = new WMSTask() { S_CNTR_CODE = model.palletId, S_CODE = WMSHelper.GenerateTaskNo(), S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_TYPE = "叫料出库任务", S_OP_DEF_CODE = model.reqId, S_OP_DEF_NAME = "成型机叫料出库任务(斜裁)", T_START_TIME = DateTime.Now, }; if (WMSHelper.CreateWmsTask(wmsTask)) { WCSTask wcsTask = new WCSTask() { S_OP_NAME = wmsTask.S_OP_DEF_NAME, S_OP_CODE = wmsTask.S_CODE, S_CODE = WCSHelper.GenerateTaskNo(), S_CNTR_CODE = wmsTask.S_CNTR_CODE, S_TYPE = wmsTask.S_TYPE, S_START_LOC = startLoc.S_CODE, S_START_AREA = startLoc.S_AREA_CODE, S_END_LOC = endLoc.S_CODE, S_END_AREA = endLoc.S_AREA_CODE, S_SCHEDULE_TYPE = "AGV", N_PRIORITY = 10, T_START_TIME = DateTime.Now, }; if (WCSHelper.CreateTask(wcsTask)) { // 起点、终点加锁 LocationHelper.LockLoc(wcsTask.S_START_LOC, 2); LocationHelper.LockLoc(wcsTask.S_END_LOC, 1); // 更新作业任务状态 wmsTask.N_B_STATE = 1; WMSHelper.UpdateTaskState(wmsTask); } } } } else { responseResult.code = 201; responseResult.msg = $"成型机机台:{model.eqNo}没有空余的叫料货位"; } return responseResult; } //---------------------------------------------------------------------------------------------------------------------------- public class LocModel { public string locCode { get; set; } // 返料货位编号 public string jtNo { get; set; } // 机台号 } public class ApplyDest { public string destLoc { get; set; } // 终点货位编码 } public class TrayItemInfo { public string S_SERIAL_NO { get; set; } // 原材料批次号 public string S_ITEM_CODE { get; set; } // 物料编码 public string S_ITEM_NAME { get; set; } // 物料编码 public string S_ITEM_SPEC { get; set; } // 规格 public string S_ITEM_STATE { get; set; } = "0"; // 检验状态 0:未检验 1:合格,2:不合格 /// /// 1:合格 2:不合格 /// public int N_ITEM_STATE { get; set; } // 物料状态 public string S_BATCH_NO { get; set; } // 批次条码 public float F_QTY { get; set; } // 数量 public string S_UOM { get; set; } = ""; // 单位 public string S_CNTR_CODE { get; set; } // 容器 public string D_PRD_DATE { get; set; } // 生产日期 public string D_EXP_DATE { get; set; } // 最小停放日期 public string D_EXP_DATE1 { get; set; } // 最大停放日期 } /// /// 人工出库模型 /// public class ManualDeliveryModel { public string to { get; set; } // 接驳货位编码 public string cntrNo { get; set; } // 容器号 public int trayStatus { get; set; } // 托盘状态 0.正常 1.异常 public string materialCode { get; set; } // 物料编号 物料编码为空,表示空工装 } /// /// 人工入库模型 /// public class ManualStorageModel { public string from { get; set; } // 起点 public string cntrNo { get; set; } // 容器号 } /// /// 设备报警反馈模型 /// public class DeviceAlertorFeedbackModel { public string reqId { get; set; } public string reqTime { get; set; } public string deviceNo { get; set; } // 设备号 public string errCode { get; set; } // 错误码 public string errMsg { get; set; } // 错误信息 } /// /// 获取托盘物料信息模型 /// public class FindTrayItemInfoModel { public string reqId { get; set; } public string reqTime { get; set; } public string cntrNo { get; set; } // 托盘号 } /// /// 申请终点模型 /// public class ApplyDestinationModel { public string reqId { get; set; } public string reqTime { get; set; } public string taskNo { get; set; } // 任务号 public string loc { get; set; } // 当前货位 public int applyType { get; set; } // 申请类型 1:堆垛机放货异常申请新终点;2:输送线到达接驳位申请终点;3: } public class AGVApplyDestModel{ public string taskNo { get; set; } // 任务号 public string loc { get; set; } // 当前货位 public string trayCode { get; set; } // 托盘码(RFID) public string applyType { get; set; } // 1.虚拟终点 2.RFID验证失败 3.RFID与任务不匹配 4.物料状态不合格 } /// /// 任务状态反馈模型 /// public class TaskStatusFeedbackModel { public string reqId { get; set; } public string reqTime { get; set; } public string taskNo { get; set; } // 任务号 public string subTaskNo { get; set; } // 子任务号 public int status { get; set; } // 任务状态 1:开始/执行中;2:完成;3:准备取货;4:取货完成;5:准备卸货;6:卸货完成;7:异常取消;8:强制完成 public string deviceNo { get; set; } // 设备号 public string errCode { get; set; } // 异常代码 0.无异常 1.设备故障码、2.rfid校验失败、3.取货无货、4.放货有货 public string loc { get; set; } // 当前货位 } /// /// 设备信号反馈模型 /// public class DeviceSignalFeedbackModel { public string reqId { get; set; } public string reqTime { get; set; } public string taskNo { get; set; } // 托盘号 public string loc { get; set; } // 货位 上料点、下料点、读码位、称重位(必填) public string cntrNo { get; set; } // 托盘号 public int signalType { get; set; } //请求类型 1:下线请求 2:叫料请求 3:读码请求(必填) public string deviceNo { get; set; } //设备号 public object extData { get; set; } } /// /// 叫料请求 /// public class CallMaterialRequest { public string loc { get; set; } // 货位 上料点、下料点、读码位、称重位(必填) } /// /// 下线请求 /// public class OffLineRequest { public string loc { get; set; } // 货位 上料点、下料点、读码位、称重位(必填) public string cntrNo { get; set; } // 托盘号 public string jtNo { get; set; } // 机台号 public bool isNormal { get; set; } //是否异常 } /// /// 读码请求 /// public class ReadCodeRequest { public string loc { get; set; } // 货位 上料点、下料点、读码位、称重位(必填) public string cntrNo { get; set; } // 托盘号 public string taskNo { get; set; } // 任务号 } public class AddTaskModel { public string From { get; set; } public string To { get; set; } public string No { get; set; } } public class TN_LocationModel { public string TN_Location { get; set; } } public class CodeInfo { /// /// 生产订单内码 /// public string FInterID { get; set; } /// /// 生产订单编号 /// public string FSourceNo { get; set; } /// /// 批号 /// public string FGMPBatchNo { get; set; } public string FState { get; set; } /// /// 物料编码(内码就是编码) /// public string Fitemid_XK { get; set; } /// /// 分录id /// public string Fentryid { get; set; } } public class NoteInfo : CodeInfo { public string WmsBillNo { get; set; } } } }