public BllResult CopyEquipment(EquipmentType equipmentType) { using (IDbConnection connection = AppSession.Dal.GetConnection()) { IDbTransaction transaction = null; try { connection.Open(); transaction = connection.BeginTransaction(); var temp = AppSession.Dal.GetCommonModelByCondition <EquipmentType>($"where id = {equipmentType.Id}", connection, transaction); if (temp.Success) { var e = temp.Data[0]; var temp2 = AppSession.Dal.GetCommonModelByCondition <EquipmentTypeTemplate>($"where equipmentTypeId = {e.Id}", connection, transaction); if (temp2.Success) { var props = temp2.Data; //e.Id = null; e.Code = e.Code + "2"; var temp3 = AppSession.Dal.InsertCommonModel <EquipmentType>(e, connection, transaction); if (temp3.Success) { props.ForEach(t => { t.EquipmentTypeId = temp3.Data.Value; }); foreach (var item in props) { var temp4 = AppSession.Dal.InsertCommonModel <EquipmentTypeTemplate>(item, connection, transaction); if (!temp4.Success) { transaction?.Rollback(); return(BllResultFactory.Error($"复制出错:{temp4.Msg}")); } } transaction.Commit(); return(BllResultFactory.Sucess()); } else { transaction?.Rollback(); return(BllResultFactory.Error($"复制出错:{temp3.Msg}")); } } else { transaction?.Rollback(); return(BllResultFactory.Error($"复制出错:{temp2.Msg}")); } } else { transaction?.Rollback(); return(BllResultFactory.Error($"复制出错:{temp.Msg}")); } } catch (Exception ex) { transaction?.Rollback(); return(BllResultFactory.Error($"复制出错:{ex.Message}")); } } }
public BllResult SyncEquipmentProp(int?id, string plcDb) { using (IDbConnection connection = AppSession.Dal.GetConnection()) { IDbTransaction tran = null; try { connection.Open(); tran = connection.BeginTransaction(); //现获取这个设备,防止同步删除 var a = AppSession.Dal.GetCommonModelByCondition <Equipment>($"where id = {id}"); if (!a.Success) { tran.Rollback(); return(BllResultFactory.Error("同步失败,设备已被同步删除")); } var equipment = a.Data[0]; //查询对应模板的属性 var b = AppSession.Dal.GetCommonModelByCondition <EquipmentTypeTemplate>($"where equipmentTypeId = {equipment.EquipmentTypeId}"); if (!b.Success) { tran.Rollback(); return(BllResultFactory.Error("同步失败,设备无模板属性")); } var templateProps = b.Data; var c = AppSession.Dal.GetCommonModelByCondition <EquipmentProp>($"where equipmentId = {equipment.Id}"); var props = new List <EquipmentProp>(); if (c.Success) { props = c.Data; } var idsFordelete = props.Where(t => !templateProps.Exists(i => i.Id == t.EquipmentTypeTemplateId)).Select(t => t.Id).ToList(); if (idsFordelete != null && idsFordelete.Count > 0) { connection.DeleteList <EquipmentProp>("where id in @ids", new { ids = idsFordelete }, tran); } var propForAdd = templateProps.Where(t => !props.Exists(i => i.EquipmentTypeTemplateId == t.Id)).ToList(); List <EquipmentProp> propListToAdd = new List <EquipmentProp>(); foreach (var item in propForAdd) { EquipmentProp equipmentProp = new EquipmentProp(); equipmentProp.EquipmentId = equipment.Id; equipmentProp.EquipmentTypeTemplateId = item.Id; equipmentProp.EquipmentTypeTemplateCode = item.Code; equipmentProp.ServerHandle = 0; if (string.IsNullOrWhiteSpace(plcDb) || !string.IsNullOrWhiteSpace(item.Address)) { equipmentProp.Address = item.Address; } else { switch (item.DataType) { case "BOOL": { equipmentProp.Address = plcDb + "X" + item.Offset; break; } case "BYTE": { equipmentProp.Address = plcDb + "B" + item.Offset; break; } case "INT": { equipmentProp.Address = plcDb + "W" + item.Offset; break; } case "DINT": { equipmentProp.Address = plcDb + "D" + item.Offset; break; } case "CHAR": { equipmentProp.Address = plcDb + "CHAR" + item.Offset + ",20"; break; } default: { equipmentProp.Address = item.Address; break; } } } equipmentProp.Value = ""; equipmentProp.Remark = item.Name; equipmentProp.CreateTime = DateTime.Now; equipmentProp.CreateBy = ""; propListToAdd.Add(equipmentProp); } propListToAdd.ForEach(t => connection.Insert <EquipmentProp>(t, tran)); tran.Commit(); return(BllResultFactory.Sucess("成功")); } catch (Exception ex) { tran?.Rollback(); AppSession.LogService.WriteDBExceptionLog(ex); return(BllResultFactory.Error($"删除失败:{ex.Message}")); } } }
/// <summary> /// 控制逻辑实现 /// </summary> /// <param name="srm"></param> /// <param name="plc"></param> /// <returns></returns> public BllResult ExcuteSingle(Equipment srm, List <Equipment> allEquipments, IPLC plc) { //联机、无故障 if (Validate(srm).Success) { #region 对于单叉堆垛机,判断这个货叉有误故障 if (srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.Fork1TotalError.ToString()).Value == "True") { //如果报有故障,则返回 return(BllResultFactory.Error("货叉1故障")); } #endregion #region 任务执行判断 if (srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.Fork1TaskExcuteStatus.ToString()).Value == SRMTaskExcuteStatus.任务执行中.GetIndexString()) { //任务执行中就return return(BllResultFactory.Sucess()); } if (srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.Fork1TaskExcuteStatus.ToString()).Value == SRMTaskExcuteStatus.任务中断_出错.GetIndexString()) { //由人工处理,一般为空出和重入 return(BllResultFactory.Sucess()); } if (srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.Fork1TaskExcuteStatus.ToString()).Value == SRMTaskExcuteStatus.发任务错误.GetIndexString()) { //由人工处理,需要重新下发任务 return(BllResultFactory.Sucess()); } #endregion #region 任务,货位和本巷道的其他设备 //找出所有未完成的任务 var tasksResult = AppSession.Dal.GetCommonModelByCondition <TaskEntity>($"where taskStatus < {TaskEntityStatus.任务完成.GetIndexInt()} " + $"and taskStatus>={TaskEntityStatus.下发任务.GetIndexInt()} and deleted = 0 and warehouseCode='{AppSession.WarehouseCode}'"); if (!tasksResult.Success) { //如果没有找到任务就直接返回 return(BllResultFactory.Error(tasksResult.Msg)); } //找出同巷道的库位,考虑到可能多个巷道移库,这里分别查询出所有库位和当前堆垛机所在巷道的库位 var locationsResult = AppSession.LocationService.GetAllLocations(null, null, null, null, null, null, null, srm.WarehouseCode); if (!locationsResult.Success) { return(BllResultFactory.Error(locationsResult.Msg)); } //所有库位 var allLocations = locationsResult.Data; //本巷道库位 var locationsRoadWay = allLocations.Where(t => t.RoadWay == srm.RoadWay).ToList(); //找出本巷道的所有设备 var equipmentsRoadWay = allEquipments.Where(t => t.RoadWay == srm.RoadWay && t.WarehouseCode == srm.WarehouseCode).ToList(); //可用的可出站台 //hack:注意,此处针对每个巷道均需要配置StationStatusMonitor!如果没有配置,则可出站台为空集合; var stationOutStatusMonitor = equipmentsRoadWay.Find(a => a.EquipmentType.Code == "StationStatusMonitor"); var availableOutStation = stationOutStatusMonitor == null ? new List <Equipment>() : equipmentsRoadWay.Where(t => t.EquipmentType.Code.Contains("Station") && stationOutStatusMonitor.EquipmentProps. Count(b => b.EquipmentTypeTemplateCode == t.StationIndex.ToString() && b.Value == StationTaskLimit.可出.GetIndexString()) > 0).ToList(); //hack:这里筛选本巷道或关联到本巷道的任务,规则为起始或目标库位,所以,当将来出现跨巷道移库时,需要特别处理跨巷道移库任务 var tasks = tasksResult.Data.Where(t => locationsRoadWay.Count(a => a.Code == t.FromLocationCode || a.Code == t.ToLocationCode) > 0).ToList(); //筛选任务,任务的前置任务如果存在,则其前置任务需要大于完成状态 tasks = tasks.Where(t => { if (t.PreTaskId != 0) { var tempResult = AppSession.Dal.GetCommonModelByCondition <TaskEntity>($"where id = {t.PreTaskId}"); if (tempResult.Success) { var innerTask = tempResult.Data[0]; if (innerTask.TaskStatus >= (int)TaskEntityStatus.任务完成) { return(true); } else { return(false); } } else { Logger.Log($"未找到任务{t.Id},远程任务号:{t.RemoteTaskNo}的前置远程任务:{t.PreRemoteTaskNo},前置内部任务号:{t.PreTaskId},该任务不允许执行。如果要执行,请取消其前置任务号", LogLevel.Warning); return(false); } } else { return(true); } }).ToList(); #endregion //堆垛机待机情况下 string Fork1TaskExecuteStatus = srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.Fork1TaskExcuteStatus.ToString()).Value; if (Fork1TaskExecuteStatus == SRMTaskExcuteStatus.待机.GetIndexString()) { //货叉任务待机时,可执行放和取任务,同时当执行完成时,交互后堆垛机会从任务完成更新为待机 //均判断put放货任务标志 //响应任务删除 string WcsFork1TaskFlag = srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.WCSPutFork1TaskFlag.ToString()).Value; if (WcsFork1TaskFlag == SRMForkTaskFlag.除任务.GetIndexString()) { return(ClearWCSDataS(srm, plc)); } //响应任务完成 string WcsTaskAccount = srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.WCSTaskCompleteFlag.ToString()).Value; if (WcsTaskAccount == SRMForkTaskFlag.任务完成.GetIndexString()) { return(ClearWCSDataS(srm, plc)); } //响应无任务且货叉在中心 else if (WcsFork1TaskFlag == SRMForkTaskFlag.无任务.GetIndexString() && srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.Fork1Center.ToString()).Value == "True") { //hack:单任务由人员手动处理,不重发 //获取需要下发给堆垛机的任务 if (srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.Fork1HasPallet.ToString()).Value == "True") { Logger.Log($"堆垛机{srm.Name}显示货叉上有货且无任务,状态错误", LogLevel.Error); return(BllResultFactory.Error()); } else { //判断任务限制情况 var tempTasks = tasks; //完全空闲的堆垛机实际只执行取货任务,则为库外取与库内取两种 //找出下发状态的待取的离堆垛机最近的任务,并且对应站台口需要可用 var task1s = tempTasks.Where(t => t.TaskStatus == TaskEntityStatus.发任务.GetIndexInt() && (t.TaskType == TaskType.出库查看.GetIndexInt() || t.TaskType == TaskType.分拣出库.GetIndexInt() || t.TaskType == TaskType.整盘出库.GetIndexInt() || t.TaskType == TaskType.盘点.GetIndexInt() || t.TaskType == TaskType.空容器出库.GetIndexInt() || t.TaskType == TaskType.补充入库.GetIndexInt() || t.TaskType == TaskType.移库.GetIndexInt()) && locationsRoadWay.Exists(a => a.Code == t.FromLocationCode)).ToList(); task1s.ForEach(t => { t.FromLocation = locationsRoadWay.Find(a => a.Code == t.FromLocationCode); t.ToLocation = allLocations.Find(a => a.Code == t.ToLocationCode); t.ToPortEquipment = equipmentsRoadWay.FirstOrDefault(a => a.Code == t.ToPort); }); //任务过滤条件,任务port对应的station要可用 task1s = task1s.Where(t => availableOutStation.Exists(a => AppSession.ExcuteService.GetOutStationByPort(srm.DestinationArea, t.ToPort, App.WarehouseCode).Data?.Exists(b => b.Code == a.Code) == true)).ToList(); //库内取货的任务 var task1 = task1s.OrderByDescending(t => t.Priority).ThenBy(t => Math.Abs((int)t.FromLocation.Line - CurrentColumn)).FirstOrDefault(); //本巷道接入口的任务 var task2s = tempTasks.Where(t => t.TaskStatus == TaskEntityStatus.响应接入站台到达.GetIndexInt() && equipmentsRoadWay.Exists(a => a.Code == t.Gateway)).ToList(); task2s.ForEach(t => { t.ArrivaEquipment = equipmentsRoadWay.Find(a => a.Code == t.Gateway); t.ToLocation = allLocations.Find(a => a.Code == t.ToLocationCode); }); //按优先级以及站台与现有堆垛机的距离优先做调度 var task2 = task2s.OrderByDescending(t => t.Priority).ThenBy(t => Math.Abs(t.ArrivaEquipment.ColumnIndex - CurrentColumn)).FirstOrDefault(); if (task1 == null && task2 == null) { //说明当前没有可以被执行的任务 return(BllResultFactory.Sucess()); } if (task2 != null) { //说明库外取货任务不为空,则下发接入任务 //库外取分为换站和其他,换站需要再放到库外,其他则放到库内 return(OutGet(srm, plc, availableOutStation, task2)); } if (task1 != null) { //说明库内取货任务不为空 //库内取分为两种,一种移到库外,一种重新到到库内另一个库位上 return(InGet(srm, plc, locationsRoadWay, availableOutStation, task1)); } //当两种任务均存在时,此处设置两种模式,出库优先与均衡模式(按堆垛机位置进行) var configResult = AppSession.BllService.GetAllConfig(); var config = configResult.Data?.FirstOrDefault(t => t.Code == ConfigStrings.OutFirst.ToString()); if (config == null || config.Value != "1") { //均衡模式 var dis1 = Math.Abs((int)task1.FromLocation.Line - CurrentColumn); var dis2 = Math.Abs(task2.ArrivaEquipment.RowIndex1 - CurrentColumn); if (dis1 <= dis2) { return(InGet(srm, plc, locationsRoadWay, availableOutStation, task1)); } else { return(OutGet(srm, plc, availableOutStation, task2)); } } else { //出库优先模式 return(OutGet(srm, plc, availableOutStation, task2)); } } } else { //hack:其他情况1-库内取货,2-库内放货,3-库外入库,4库外出库, 5重新分配入库地址,暂时不做处理,这里也应不需要处理这些情况 } } //当堆垛机有任务完成且wcs没有任务完成时,说明是堆垛机新发任务完成 else if (Fork1TaskExecuteStatus == SRMTaskExcuteStatus.任务完成.GetIndexString() && srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.WCSTaskCompleteFlag.ToString()).Value != SSRMTaskCompleteFlag.任务完成.GetIndexString()) { //todo:检查任务完成 //单叉单任务堆垛机只有2种情况会有完成信号 库外出库和库内放货 //根据任务号和货叉类型进行任务完成处理 int taskNo = int.Parse(srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.Fork1TaskNo.ToString()).Value); int forkType = int.Parse(srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.Fork1TaskType.ToString()).Value); //库内放货完成 if (forkType == SRMForkTaskFlag.库内放货.GetIndexInt()) { var task = tasks.FirstOrDefault(t => t.Id == taskNo); if (task != null) { if (!locationsRoadWay.Exists(a => a.Code == task.ToLocationCode)) { Logger.Log($"堆垛机{srm.Code},任务:{task.Id},去向库位:{task.ToLocationCode}不在本巷道中", LogLevel.Error); return(BllResultFactory.Error()); } var tempStatus = task.TaskStatus; task.TaskStatus = TaskEntityStatus.任务完成.GetIndexInt(); task.Updated = DateTime.Now; task.UpdatedBy = Accounts.WCS.ToString(); var tempResult = AppSession.Dal.UpdateCommonModel <TaskEntity>(task); if (tempResult.Success) { //标记交换区地址,任务完成10 var prop = srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.WCSTaskCompleteFlag.ToString()); prop.Value = SSRMTaskCompleteFlag.任务完成.GetIndexString(); var sendResult = plc.Write(prop); if (sendResult.Success) { Logger.Log($"堆垛机{srm.Name}完成库内放货成功,任务:{task.Id}", LogLevel.Success); return(BllResultFactory.Sucess()); } else { //回滚 task.TaskStatus = tempStatus; AppSession.Dal.UpdateCommonModel <TaskEntity>(task); Logger.Log($"堆垛机{srm.Name}完成库内放货失败,任务:{task.Id},原因:{sendResult.Msg}", LogLevel.Error); return(BllResultFactory.Error()); } } else { Logger.Log($"完成堆垛机{srm.Name}库内放货失败,任务{task.Id}请求WMS接口失败:{tempResult.Msg}", LogLevel.Error); return(BllResultFactory.Error($"完成堆垛机{srm.Name}库内放货失败,任务{task.Id}请求WMS接口失败:{tempResult.Msg}")); } } else { Logger.Log($"堆垛机{srm.Code}记录任务{task.Id}状态不对,请核查任务是否为本巷道任务,以及任务的状态{Enum.GetName(typeof(TaskEntityStatus), task.TaskStatus)}", LogLevel.Error); return(BllResultFactory.Error()); } } //库外放货完成时 else if (forkType == SRMForkTaskFlag.库外放货.GetIndexInt()) { var task = tasks.FirstOrDefault(t => t.Id == taskNo); if (task != null) { //更新任务状态 int preStatus = task.TaskStatus; task.TaskStatus = TaskEntityStatus.响应堆垛机库外放货完成.GetIndexInt(); task.Updated = DateTime.Now; task.UpdatedBy = Accounts.WCS.ToString(); var tempResult = AppSession.Dal.UpdateCommonModel <TaskEntity>(task); if (tempResult.Success) { //标记交换区地址,任务完成10 var prop = srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == SSRMProps.WCSTaskCompleteFlag.ToString()); prop.Value = SSRMTaskCompleteFlag.任务完成.GetIndexString(); var sendResult = plc.Write(prop); if (sendResult.Success) { Logger.Log($"堆垛机{srm.Name}完成库外放货成功,任务:{task.Id}", LogLevel.Success); return(BllResultFactory.Sucess()); } else { Logger.Log($"堆垛机{srm.Name}完成库外放货失败,任务:{task.Id},原因:{sendResult.Msg}", LogLevel.Error); task.TaskStatus = preStatus; AppSession.Dal.UpdateCommonModel <TaskEntity>(task); return(BllResultFactory.Error()); } } else { Logger.Log($"完成堆垛机{srm.Name}库外放货时,更新任务{task.Id}状态失败:{tempResult.Msg}", LogLevel.Error); return(BllResultFactory.Error($"完成堆垛机{srm.Name}库外放货时,更新任务{task.Id}状态失败:{tempResult.Msg}")); } } else { Logger.Log($"堆垛机{srm.Code}记录任务{task.Id}状态不对,请核查任务是否为本巷道任务,以及任务的状态{Enum.GetName(typeof(TaskEntityStatus), task.TaskStatus)}", LogLevel.Error); return(BllResultFactory.Error()); } } //未知情况 Logger.Log($"堆垛机{srm.Name}的任务完成时候和系统对应的任务出现了异常:PLC:{taskNo}或 货叉的任务类型:{forkType} ", LogLevel.Warning); return(BllResultFactory.Error($"堆垛机{srm.Name}的任务完成时候和系统对应的任务出现了异常:PLC:{taskNo}或 货叉的任务类型:{forkType} ")); } else { //Logger.Log($"堆垛机{stocker.Name}的任务完成时候和系统对应的任务出现了异常:PLC:{taskNo}或 货叉的任务类型:{forkType} ", LogLevel.Warning); //未知情况 Logger.Log($"堆垛机{srm.Name}处理中,执行状态为:{srm.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "Fork1TaskExcuteStatus").Value}", LogLevel.Warning); return(BllResultFactory.Sucess()); } } return(BllResultFactory.Sucess()); }
/// <summary> /// 处理接收到客户端的消息 /// HACK:目前只返回成功 /// </summary> /// <param name="RecsiveMsg">客户端消息</param> /// <returns></returns> public static BllResult HandClientRecsiveMsg(string clientRecsiveMsg) { return(BllResultFactory.Sucess()); }
/// <summary> /// 库外取 /// </summary> /// <param name="srm"></param> /// <param name="plc"></param> /// <param name="availableOutStation"></param> /// <param name="task"></param> /// <returns></returns> private BllResult OutGet(Equipment srm, IPLC plc, List <Equipment> availableOutStation, TaskEntity task) { if (task.TaskType == TaskType.换站.GetIndexInt()) { //获取目标站台 var stationsResult = AppSession.ExcuteService.GetOutStationByPort(srm.DestinationArea, task.ToPort, App.WarehouseCode); if (!stationsResult.Success) { Logger.Log($"堆垛机{srm.Code},任务:{task.Id},未找到可出站台:" + stationsResult.Msg, LogLevel.Error); return(BllResultFactory.Error(stationsResult.Msg)); } var station = stationsResult.Data.Where(t => availableOutStation.Exists(a => a.Code == t.Code)).OrderBy(t => CurrentColumn - t.ColumnIndex).FirstOrDefault(); if (station == null) { Logger.Log($"堆垛机{srm.Name}当前没有可用的站台可以放货,任务:{task.Id}", LogLevel.Warning); return(BllResultFactory.Error()); } else { var tempStatus = task.TaskStatus; task.TaskStatus = (int)TaskEntityStatus.发堆垛机换站任务; task.Updated = DateTime.Now; task.UpdatedBy = Accounts.WCS.ToString(); var result = AppSession.Dal.UpdateCommonModel <TaskEntity>(task); if (result.Success) { result = SendTaskToSRM(srm, plc, SSRMNewTaskFlag.新任务, SRMForkTaskFlag.库外取货, task.ArrivaEquipment.RowIndex1.ToString(), "0", "0", task.ArrivaEquipment.StationIndex.ToString(), SRMForkTaskFlag.库外放货, station.RowIndex1.ToString(), "0", "0", station.StationIndex.ToString(), task.Id.ToString(), SSRMTaskCompleteFlag.无完成);; if (result.Success) { Logger.Log($"下发堆垛机{srm.Code}换站任务:{task.Id}成功", LogLevel.Success); return(BllResultFactory.Sucess()); } else { //回滚 task.TaskStatus = tempStatus; AppSession.Dal.UpdateCommonModel <TaskEntity>(task); Logger.Log($"下发堆垛机{srm.Code}换站任务:{task.Id}失败,写入地址失败:{result.Msg}", LogLevel.Error); return(BllResultFactory.Error()); } } else { Logger.Log($"下发堆垛机{srm.Code}换站任务时,更新任务{task.Id}状态失败:{result.Msg}", LogLevel.Error); return(BllResultFactory.Error()); } } } else { var tempStatus = task.TaskStatus; task.TaskStatus = (int)TaskEntityStatus.发堆垛机入库任务; task.Updated = DateTime.Now; task.UpdatedBy = Accounts.WCS.ToString(); var result = AppSession.Dal.UpdateCommonModel <TaskEntity>(task); if (result.Success) { result = SendTaskToSRM(srm, plc, SSRMNewTaskFlag.新任务, SRMForkTaskFlag.库外取货, task.ArrivaEquipment.RowIndex1.ToString(), "0", "0", task.ArrivaEquipment.StationIndex.ToString(), SRMForkTaskFlag.库内放货, task.ToLocation.RowIndex1.ToString(), task.ToLocation.Line.ToString(), task.ToLocation.Layer.ToString(), "0", task.Id.ToString(), SSRMTaskCompleteFlag.无完成); if (result.Success) { Logger.Log($"下发堆垛机{srm.Code}入库任务:{task.Id}成功", LogLevel.Success); return(BllResultFactory.Sucess()); } else { //回滚 task.TaskStatus = tempStatus; AppSession.Dal.UpdateCommonModel <TaskEntity>(task); Logger.Log($"下发堆垛机{srm.Code}入库任务:{task.Id}失败,写入地址失败:{result.Msg}", LogLevel.Error); return(BllResultFactory.Error()); } } else { Logger.Log($"下发堆垛机{srm.Code}入库任务时,更新任务{task.Id}状态失败:{result.Msg}", LogLevel.Error); return(BllResultFactory.Error()); } } }
public override BllResult ExcuteRequest(Equipment station, List <Equipment> allEquipments, IPLC plc) { //获取任务 var taskResult = AppSession.Dal.GetCommonModelByCondition <TaskEntity>($"where taskStatus= {TaskEntityStatus.响应堆垛机库外放货完成.GetIndexInt()} " + $"and gateway = '{station.SelfAddress}' and warehouseCode = '{station.WarehouseCode}'"); if (taskResult.Success) { var tasks = taskResult.Data; if (tasks.Count == 0) { return(BllResultFactory.Error($"站台{station.Name}根据任务状态{TaskEntityStatus.响应堆垛机库外放货完成}没有找到任务数据,请检查数据")); } if (tasks.Count > 1) { return(BllResultFactory.Error($"站台{station.Name}根据任务状态{TaskEntityStatus.响应堆垛机库外放货完成}查找到了多条任务,请检查数据")); } else { var task = taskResult.Data[0]; //if (task.Type == TaskType.整盘入库.GetIndexInt() || task.Type == TaskType.空容器入库.GetIndexInt()) //{ // Logger.Log($"站台{station.Name}不接受整盘入库和空容器入库任务", LogLevel.Error); // return; //} if (station.GoAddress.ToString() == "") { return(BllResultFactory.Error($"站台{station.Name}没有设置去向地址")); } int tempStatus = task.TaskStatus; //记录原始状态以便回滚 string tempGateWay = task.Gateway; task.TaskStatus = TaskEntityStatus.响应接出口站台请求.GetIndexInt(); task.Gateway = station.Code; //task.Roadway = station.RoadWay; var temp = AppSession.Dal.UpdateCommonModel <TaskEntity>(task); if (temp.Success) { String number = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "RequestNumber").Value; String weight = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "RequestWeight").Value; String length = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "RequestLength").Value; String width = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "RequestWidth").Value; String height = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == "RequestHeight").Value; temp = SendAddressReplyToPlc(station, plc, StationMessageFlag.地址回复, StationLoadStatus.回复到达, number, task.ContainerCode, weight, length, width, height, station.GoAddress.ToString(), ""); if (temp.Success) { return(BllResultFactory.Sucess($"响应站台{station.Name}地址请求成功,条码{task.ContainerCode},任务{task.Id}")); } else { task.TaskStatus = tempStatus; task.Gateway = tempGateWay; AppSession.Dal.UpdateCommonModel <TaskEntity>(task); return(BllResultFactory.Error($"响应站台{station.Name}地址请求失败,条码{task.ContainerCode},任务{task.Id},回滚任务状态")); } } else { return(BllResultFactory.Error($"站台{station.Name},响应请求时更新任务{task.Id}状态失败。")); } } } else { return(BllResultFactory.Error($"站台{station.Name}未能获取到任务状态为'{TaskEntityStatus.响应堆垛机库外放货完成}'的任务,请检查数据。")); } }
public override BllResult ExcuteArrive(Equipment station, List <Equipment> allEquipments, IPLC plc) { var isSuccess = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.ArriveResult.ToString()).Value; if (isSuccess == StationArriveResult.成功.GetIndexString()) { //获取条码 var barcode = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.ArriveBarcode.ToString()).Value; if (string.IsNullOrWhiteSpace(barcode)) { return(BllResultFactory.Error($"站台{station.Name}有位置到达但是没有条码信息")); } else { var taskResult = AppSession.Dal.GetCommonModelByCondition <TaskEntity>($"where containerCode = '{barcode}' and taskStatus < {TaskEntityStatus.任务完成.GetIndexInt()} and deleted = 0"); if (taskResult.Success) { if (taskResult.Data.Count > 1) { return(BllResultFactory.Error($"站台{station.Name}根据条码{barcode}查找到了多条任务,请检查数据")); } else { var task = taskResult.Data[0]; if (task.TaskType == TaskType.空容器出库.GetIndexInt() || task.TaskType == TaskType.整盘出库.GetIndexInt() || task.TaskType == TaskType.换站.GetIndexInt()) { using (IDbConnection connection = AppSession.Dal.GetConnection()) { IDbTransaction transaction = null; try { connection.Open(); transaction = connection.BeginTransaction(); var result = AppSession.TaskService.CompleteTask(task.Id.Value, App.User.UserCode, connection, transaction); if (result.Success) { //回复位置到达 result = SendAckToPlc(station, plc, StationMessageFlag.WCSPLCACK, StationLoadStatus.回复到达, station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.ArriveRealAddress.ToString()).Value, "0"); if (result.Success) { transaction.Commit(); //发送LED AppSession.BllService.SendLED(station, task); return(BllResultFactory.Sucess($"响应站台{station.Name}位置到达成功,完成任务成功,条码{barcode},任务{task.Id}")); } else { transaction.Rollback(); return(BllResultFactory.Error($"响应站台{station.Name}位置到达失败,条码{barcode},任务{task.Id},详情:{result.Msg}")); } } else { transaction.Rollback(); return(BllResultFactory.Error($"响应站台{station.Name}位置到达请求失败,完成任务失败,条码{barcode},任务{task.Id},详情:{result.Msg}")); } } catch (Exception ex) { transaction?.Rollback(); return(BllResultFactory.Error($"响应站台{station.Name}位置到达请求失败,完成任务失败,条码{barcode},任务{task.Id},详情:{ex.Message}")); } } } else { return(BllResultFactory.Error($"响应站台{station.Name}位置到达请求失败,完成任务失败,条码{barcode},任务{task.Id},详情:只出站台对应的任务类型有问题")); } } } else { return(BllResultFactory.Error($"站台{station.Name}根据条码{barcode}没有查询到任务:{taskResult.Msg}")); } } } else { return(BllResultFactory.Error($"站台{station.Name}位置到达失败")); } }
/// <summary> /// 具体的站台实现逻辑 /// </summary> /// <param name="stations"></param> /// <param name="plcs"></param> /// <returns></returns> public override void Excute(List <Equipment> stations, List <Equipment> allEquipments, IPLC plc) { //每隔3秒处理一次到达和离开 if (DateTime.Now.Subtract(excuteDateTime).Seconds > 3) { excuteDateTime = DateTime.Now; } else { return; } var locations = AppSession.Dal.GetCommonModelByCondition <ProductFinishedStation>($"where 1=1"); if (locations.Success) { foreach (var station in stations) { BllResult result = null; try { var location = locations.Data.FirstOrDefault(t => t.Code == station.Code); if (station.EquipmentProps.FirstOrDefault(t => t.EquipmentTypeTemplateCode == StationProps.AGV_Arrive_WCS.ToString())?.Value == true.ToString()) { //如果AGV到达,并且库位是停用的,就改为可以用 if (location.IsStop == true) { location.IsStop = false; AppSession.Dal.UpdateCommonModel <ProductFinishedStation>(location); result = BllResultFactory.Sucess($"AGV站台[{station.Code}][{station.Name}]到达,对应的库位{location.Code}更改为可用"); } } if (station.EquipmentProps.FirstOrDefault(t => t.EquipmentTypeTemplateCode == StationProps.AGV_Leave_WCS.ToString())?.Value == true.ToString()) { //如果AGV不是到达,并且库位未锁定,就改为停用,恢复为1层1列 if (location.IsStop == false) { var stepTraceResult = AppSession.Dal.GetCommonModelByCondition <StepTrace>($"where status < {StepTraceStatus.下发放货任务.GetIndexInt()} and nextStationId = '{station.StationId}'"); if (stepTraceResult.Success) { foreach (var stepTrace in stepTraceResult.Data.Where(t => t.Status < StepTraceStatus.发取货任务.GetIndexInt())) { stepTrace.NextStationId = 0; stepTrace.WCSLayer = null; stepTrace.WCSLine = null; stepTrace.Status = StepTraceStatus.设备请求下料.GetIndexInt(); AppSession.Dal.UpdateCommonModel <StepTrace>(stepTrace); } foreach (var stepTrace in stepTraceResult.Data.Where(t => t.Status == StepTraceStatus.发取货任务.GetIndexInt())) { var stationCode = string.Empty; switch (station.Code) { case "StationForFinished1": stationCode = "StationForFinished2"; break; case "StationForFinished2": stationCode = "StationForFinished1"; break; case "StationForFinished3": stationCode = "StationForFinished4"; break; case "StationForFinished4": stationCode = "StationForFinished3"; break; } var otherStation = stations.Find(t => t.Code == stationCode); if (otherStation != null) { List <Station> stationList = station.StationList.Where(t => t.Id == otherStation.StationId).ToList(); TrussNormalExcute trussNormalExcutea = new TrussNormalExcute(); trussNormalExcutea.setStation(stationList, stepTrace, stepTrace.NextStepId.Value); } } } location.PutType = (int)PutTypeFlag.初始摆放类型值; location.Line = 1; location.Layer = 1; location.IsStop = true; AppSession.Dal.UpdateCommonModel <ProductFinishedStation>(location); result = BllResultFactory.Sucess($"AGV站台[{station.Code}][{station.Name}]离开,对应的库位{location.Code}更改为停用,并且恢复到1列1层"); } } } catch (Exception ex) { result = BllResultFactory.Error($"AGV站台[{station.Code}][{station.Name}]处理发生异常:{ex.Message}"); } LogResult(result); } } }
public override BllResult ExcuteRequest(Equipment station, List <Equipment> allEquipments, IPLC plc) { var barcode = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.RequestBarcode.ToString()).Value; var requestNumber = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.RequestNumber.ToString()).Value; var height = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.RequestHeight.ToString()).Value; var weight = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.RequestWeight.ToString()).Value; var length = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.RequestLength.ToString()).Value; var width = station.EquipmentProps.Find(t => t.EquipmentTypeTemplateCode == StationProps.RequestWidth.ToString()).Value; string goAddress = ""; string backAddress = ""; if (string.IsNullOrWhiteSpace(barcode)) { SendBack(station, plc, barcode); return(BllResultFactory.Error($"站台{station.Name}有地址请求但是没有条码信息")); } else { //获取任务 var taskResult = AppSession.Dal.GetCommonModelByConditionWithZero <TaskEntity>($"where containerCode = '{barcode}' and taskStatus < {TaskEntityStatus.任务完成.GetIndexInt()} and deleted = 0"); if (taskResult.Success) { if (taskResult.Data.Count > 1) { SendBack(station, plc, barcode); return(BllResultFactory.Error($"站台{station.Name}根据条码{barcode}查找到了多条任务,请检查数据")); } if (taskResult.Data.Count == 0) { return(BllResultFactory.Error($"站台{station.Name}根据条码{barcode}没有找到任务,请检查数据")); } else { var task = taskResult.Data[0]; if (task.TaskType == TaskType.整盘出库.GetIndexInt() || task.TaskType == TaskType.空容器出库.GetIndexInt()) { SendBack(station, plc, barcode); return(BllResultFactory.Error($"站台{station.Name}不接受整盘出库和空托盘出库任务")); } //检测是否有去向库位,没有则请求 if (task.TaskType == TaskType.换站.GetIndexInt()) { //如果是换站任务,则port不能为此站台,否则无意义 if (task.ToPort == station.Code) { SendBack(station, plc, barcode); return(BllResultFactory.Error($"托盘{task.ContainerCode}为换站任务,但是换站目的地与入口目的地相同")); } } goAddress = station.GoAddress; if (string.IsNullOrWhiteSpace(goAddress)) { // 检测是否有去向库位或去向站台 设计逻辑:优先考虑是否分配了目标区域,没有则判断是否分配了库位 if (string.IsNullOrWhiteSpace(task.DestinationArea)) { if (string.IsNullOrWhiteSpace(task.ToLocationCode)) { //没有分配目标区域,也没有分配库位的情况 这个时候需要请求上游系统分配目标区域或库位 //hack:这里默认进行去向库位获取,按需改成获取去向区域 LocationAssignReqModelInfo locationRequest = new LocationAssignReqModelInfo(); locationRequest.TaskNo = task.RemoteTaskNo.ToString(); locationRequest.Height = height; locationRequest.Weight = weight; locationRequest.Length = length; locationRequest.Width = width; var result = AppSession.TaskService.GetDestinationLocationFromWMS(locationRequest); if (!result.Success) { SendBack(station, plc, barcode); return(BllResultFactory.Error($"任务{task.Id}没有去向库位,并且请求上游系统库位失败:{result.Msg}")); } Logger.Log($"任务{task.Id}请求上位系统去向库位成功,获取库位为:{result.Data.Code}", LogLevel.Success); task.DestinationArea = result.Data.DestinationArea; task.ToLocationCode = result.Data.Code; } else { //没有分配目标区域,分配了库位的情况 // 根据库位 查找巷道 var temp2 = AppSession.LocationService.GetLocationByCode(task.ToLocationCode); if (!temp2.Success) { SendBack(station, plc, barcode); return(BllResultFactory.Error($"任务{task.Id}获取去向库位{task.ToLocationCode}出错:{temp2.Msg}")); } task.DestinationArea = temp2.Data.DestinationArea; } //将获取到的数据进行update AppSession.Dal.UpdateCommonModel <TaskEntity>(task); } //根据目标区域查找前进地址 var temp3 = AppSession.ExcuteService.GetGoAddressByDestinationArea(task.DestinationArea, station.Code, App.WarehouseCode); if (!temp3.Success) { SendBack(station, plc, barcode); return(BllResultFactory.Error($"托盘{task.ContainerCode}没有查找到对应请进地址,请核对信息是否录入维护错误")); } //hack:这里默认取第一个,如果有项目存在多个选择,请加逻辑进行判断 if (string.IsNullOrWhiteSpace(temp3.Data[0].SelfAddress)) { SendBack(station, plc, barcode); return(BllResultFactory.Error($"托盘{task.ContainerCode}查找设备{temp3.Data[0].Code}无目标地址,请核对设备信息是否配置正确")); } goAddress = temp3.Data[0].SelfAddress; } int tempStatus = task.TaskStatus; //记录原始状态以便回滚 string tempArrivaEquipmentCode = task.Gateway; task.TaskStatus = TaskEntityStatus.拣选台回库.GetIndexInt(); task.Gateway = station.Code; task.ReqHeight = height; task.ReqLength = length; task.ReqWeight = weight; task.ReqWidth = width; var temp = AppSession.Dal.UpdateCommonModel <TaskEntity>(task); if (temp.Success) { //回复地址请求 temp = SendAddressReplyToPlc(station, plc, StationMessageFlag.地址回复, StationLoadStatus.默认, requestNumber, barcode, weight, length, width, height, goAddress, backAddress); if (temp.Success) { //发送LED AppSession.BllService.SendLED(station, task); return(BllResultFactory.Sucess($"响应站台{station.Name}地址请求成功,条码{barcode},任务{task.Id}")); } else { task.TaskStatus = tempStatus; task.Gateway = tempArrivaEquipmentCode; AppSession.Dal.UpdateCommonModel <TaskEntity>(task); SendBack(station, plc, barcode); return(BllResultFactory.Error($"响应站台{station.Name}地址请求失败,条码{barcode},任务{task.Id},详情:{temp.Msg},回滚任务状态")); } } else { SendBack(station, plc, barcode); return(BllResultFactory.Error($"站台{station.Name},响应请求时更新任务{task.Id}状态失败。详情:{temp.Msg}")); } } } else { SendBack(station, plc, barcode); return(BllResultFactory.Error($"站台{station.Name}根据条码{barcode}没有查询到任务:{taskResult.Msg}")); } } }