using iWareCommon;
|
using iWareCommon.Utils;
|
using iWareSql;
|
using System;
|
using System.Collections.Generic;
|
using System.Threading;
|
|
using iWareCC.SrmService;
|
using System.Linq;
|
using iWareSql.Orm;
|
using System.Threading.Tasks;
|
using iWareSql.Entity.ParamModel;
|
using Newtonsoft.Json;
|
using iWareCC.BLL;
|
using iWareCC.Common;
|
|
using iWareModel;
|
using iWareCommon.Common.Globle;
|
using XiGang.Core.Model;
|
using iWareCC.Common.Helper;
|
using iWareModel.EnumType.AoSinPublicCommon;
|
using Admin.NET.Core.TaskModule.Enum;
|
using iWareSql.DbOrm;
|
using iWareSql.DataAccess;
|
using static WZ.Useful.Commons.DGVPrinter;
|
using System.Runtime.Remoting.Contexts;
|
|
namespace iWareCC
|
{
|
/// <summary>
|
/// 堆垛机任务服务线程类
|
/// </summary>
|
public class SrmTaskThreadService : DeviceThreadServiceHandle
|
{
|
private static string _namespace = "iWareCC.SrmTaskThreadService";
|
|
private SrmTaskThreadService() { }
|
public SrmTaskThreadService(iWareCommon.Utils.LogType logType)
|
{
|
base.currentLogType = logType;
|
}
|
public override void StartService()
|
{
|
Task.Run(() =>
|
{
|
try
|
{
|
//自动执行堆垛机任务线程
|
Log4NetHelper.WriteInfoLog(base.currentLogType, "自动执行堆垛机任务线程启动了");
|
//var srmList = new SrmService.SrmServiceClient().GetSrm_CacheEntity();
|
var srmList = FormCC.SrmDeviceList;
|
foreach (var x in srmList)
|
{
|
IssueTaskThread(x);
|
ConfirmFinishTaskThread(x);
|
}
|
}
|
catch (Exception ex)
|
{
|
Log4NetHelper.WriteErrorLog(base.currentLogType, "SrmTaskThreadService线程启动出现异常", ex);
|
}
|
});
|
}
|
|
|
#region 线程处理
|
|
#region 自动执行堆垛机任务线程
|
|
/// <summary>
|
/// 自动执行堆垛机任务
|
/// </summary>
|
/// <param name="srmName"></param>
|
public override void IssueTask(object deviceId)
|
{
|
string errMsg1 = "", errMsg2 = "", errMsg3 = "", errMsg4 = "";
|
int i_deviceId = (int)deviceId;
|
while (true)
|
{
|
if ((int)deviceId == (int)EDevice.堆垛机 && SystemValue.isStartedModel)
|
{
|
IssueTaskHandle(i_deviceId, out errMsg1);
|
}
|
//else if ((int)deviceId == (int)EDevice.二号堆垛机 && SystemValue.isAllowRuning_SrmTaskThreadService_2 && SystemValue.isStartedModel)
|
//{
|
// IssueTaskHandle(i_deviceId, out errMsg2);
|
//}
|
|
SystemWarningMsg._lbl_Alert_Srm1Release = errMsg1;
|
SystemWarningMsg._lbl_Alert_Srm2Release = errMsg2;
|
|
Thread.Sleep(500);//2秒一次
|
}
|
}
|
|
/// <summary>
|
/// 自动执行堆垛机任务(线程)
|
/// </summary>
|
/// <param name="srmName"></param>
|
public override void IssueTaskHandle(int deviceId, out string errMsg)
|
{
|
errMsg = "";
|
try
|
{
|
int int_deviceId = (int)deviceId;
|
var vs = new SrmServiceClient();
|
//2、判断堆垛机是否可以下发新任务
|
SdaResEntity sdaResult = vs.IsAllowSendTask(int_deviceId, out errMsg);
|
if (sdaResult.result == false)
|
{
|
errMsg = $"非自动、有任务未确认或有报警,{errMsg}";
|
return;
|
}
|
//bool isOk = ValidateDeviceIsAllowSendTask(int_deviceId, out errMsg);
|
//if (!isOk)
|
//{
|
// errMsg = "不允许下发新任务," + errMsg;
|
// return;
|
//}
|
|
using (DbOrm dbOrm = new DbOrm())
|
{
|
var srmTaskList = ValidateIsExistTaskToDisposeForIssued(dbOrm, int_deviceId, out errMsg);
|
if (srmTaskList == null || srmTaskList.Count == 0)
|
{
|
//表示DB中没有任务要发送给堆垛机
|
errMsg = $"没有要执行的堆垛机任务";
|
return;
|
}
|
foreach (var item in srmTaskList)
|
{
|
SingleIssueTaskHandle(item, dbOrm, int_deviceId, vs, out errMsg);
|
if (!string.IsNullOrEmpty(errMsg))
|
{//说明报错了,继续走下一个循环
|
continue;
|
}
|
else
|
{//说明执行成功了,跳出循环
|
//修改下发的堆垛机任务状态,0->1
|
item.TaskState = (int)SubTaskStateEnum.已下发;
|
dbOrm.SaveChanges();
|
break;
|
}
|
}
|
}
|
vs.Close();
|
}
|
catch (Exception ex)
|
{
|
errMsg = "异常,请联系管理员:" + ex.Message;
|
//SysExceptionInfoHandler.GetExceptionInfoForError("自动执行堆垛机任务(线程)出现异常,deviceId:" + deviceId + ",异常:" + ex.Message, ex, ref exception);
|
//SysExceptionInfoHandler.InsertExceptionInfo(exception, true);
|
}
|
}
|
|
private string GetRealLocatiomCodeOut(string sourcePlace)
|
{
|
switch (sourcePlace)
|
{
|
case "102":
|
return "1-00-901-00";
|
//case "202":
|
// return "1-00-902-00";
|
//case "203":
|
// return "2-00-901-00";
|
//case "204":
|
// return "2-00-902-00";
|
default:
|
return "ERROR";
|
}
|
}
|
|
private string GetRealLocatiomCodeIn(string sourcePlace)
|
{
|
switch (sourcePlace)
|
{
|
case "102":
|
return "1-00-801-00";
|
//case "202":
|
// return "1-00-802-00";
|
//case "203":
|
// return "2-00-801-00";
|
//case "204":
|
// return "2-00-802-00";
|
default:
|
return "ERROR";
|
}
|
}
|
|
/// <summary>
|
/// 单个堆垛机任务下发处理
|
/// </summary>
|
/// <param name="srmTask"></param>
|
/// <param name="exception"></param>
|
/// <param name="dbOrm"></param>
|
/// <param name="int_deviceId"></param>
|
/// <param name="errMsg"></param>
|
private void SingleIssueTaskHandle(ware_task_sub srmTask, DbOrm dbOrm, int int_deviceId, SrmServiceClient vs, out string errMsg)
|
{
|
#region //3、判断数据库中是否有可要下发的任务,如果有就下发
|
|
DeviceTaskTypeEnum _DeviceTaskTypeEnum = (DeviceTaskTypeEnum)Enum.Parse(typeof(DeviceTaskTypeEnum), srmTask.TaskType.ToString());
|
EDevice device = (EDevice)Enum.Parse(typeof(EDevice), int_deviceId.ToString());
|
string realSourcePlace = "";
|
string realToPlace = "";
|
bool isOk;
|
if (srmTask.TaskType == (int)TaskCategoryEnum.InStock)
|
{
|
realSourcePlace = GetRealLocatiomCodeIn(srmTask.SourcePlace);
|
realToPlace = srmTask.ToPlace;
|
|
if (realToPlace.Substring(2).StartsWith("02"))
|
{
|
//查看该1排是否有货
|
var arr = realToPlace.Split('-');
|
string newstr = arr[0] + "-" + "01" + "-" + arr[2] + "-" + arr[3];
|
//看1排是否有货,无货放1排
|
var lvc = dbOrm.ware_location_vs_container.AsNoTracking().Any(u => u.WareLocationCode == newstr);
|
if (!lvc)
|
{
|
var container1 = dbOrm.wms_container.Where(u => u.RealLocationCode == newstr).FirstOrDefault();
|
if (container1 != null)
|
{
|
container1.RealLocationCode = realToPlace;
|
}
|
//查看是否有指向1排原绑定库位的任务
|
var newtask = dbOrm.ware_task.Where(u => u.ToLocationCode == newstr).FirstOrDefault();
|
if (newtask != null)
|
{
|
newtask.ToLocationCode = realToPlace;
|
var newtasksub = dbOrm.ware_task_sub.Where(u => u.TaskId == newtask.Id && u.DeviceId == int_deviceId && u.ToPlace == newstr).FirstOrDefault();
|
if (newtasksub != null)
|
{
|
newtasksub.ToPlace = realToPlace;
|
}
|
}
|
|
//目标库位修改为1排
|
realToPlace = newstr;
|
|
var container = dbOrm.wms_container.Where(u => u.ContainerCode == srmTask.ContainerCode).FirstOrDefault();
|
container.RealLocationCode = newstr;
|
|
srmTask.ToPlace = realToPlace;
|
|
//主任务也修改
|
var maintask = dbOrm.ware_task.Where(u => u.Id == srmTask.TaskId).FirstOrDefault();
|
maintask.ToLocationCode = realToPlace;
|
}
|
}
|
//else if (realToPlace.Substring(2).StartsWith("01"))
|
//{
|
// //查看该1排是否有货
|
// var arr = realToPlace.Split('-');
|
// string newstr = arr[0] + "-" + "02" + "-" + arr[2] + "-" + arr[3];
|
// var lvc = dbOrm.ware_location_vs_container.AsNoTracking().Any(u => u.WareLocationCode == realToPlace);
|
// if (lvc)//有货就换到2排
|
// {
|
// //目标库位修改为1排
|
// realToPlace = newstr;
|
|
// var container = dbOrm.wms_container.Where(u => u.ContainerCode == srmTask.ContainerCode).FirstOrDefault();
|
// container.RealLocationCode = realToPlace;
|
|
// srmTask.ToPlace = realToPlace;
|
|
// //主任务也修改
|
// var maintask = dbOrm.ware_task.Where(u => u.Id == srmTask.TaskId).FirstOrDefault();
|
// maintask.ToLocationCode = realToPlace;
|
// }
|
//}
|
isOk = dbOrm.ware_location_vs_container.Any(x => x.WareLocationCode == realToPlace && x.WareContainerCode != srmTask.ContainerCode && x.IsDeleted == false);
|
if (isOk)
|
{
|
errMsg = device.ToString() + "不允许下发新任务,目标库位" + realToPlace + "系统显示有库存";
|
return;
|
}
|
}
|
else if (srmTask.TaskType == (int)TaskCategoryEnum.OutStock)
|
{
|
realSourcePlace = srmTask.SourcePlace;
|
realToPlace = GetRealLocatiomCodeOut(srmTask.ToPlace);
|
|
//判断是否存在指向放货站台的执行中的任务
|
isOk = dbOrm.ware_task_sub.Any(x => x.ToPlace == srmTask.ToPlace && x.TaskState == (int)SubTaskStateEnum.已下发);
|
if (isOk)
|
{
|
errMsg = "存在指向目标点" + srmTask.ToPlace + "的任务,不能下发同一目标点的任务";
|
return;
|
}
|
}
|
else
|
{
|
realSourcePlace = srmTask.SourcePlace;
|
realToPlace = srmTask.ToPlace;
|
|
if (realToPlace.Substring(2).StartsWith("02") && realToPlace != "1-02-06-04")
|
{
|
//查看该1排是否有货
|
var arr = realToPlace.Split('-');
|
string newstr = arr[0] + "-" + "01" + "-" + arr[2] + "-" + arr[3];
|
//看1排是否有货,无货放1排
|
var lvc = dbOrm.ware_location_vs_container.AsNoTracking().Any(u => u.WareLocationCode == newstr);
|
if (!lvc)
|
{
|
var container1 = dbOrm.wms_container.Where(u => u.RealLocationCode == newstr).FirstOrDefault();
|
if (container1 != null)
|
{
|
container1.RealLocationCode = realToPlace;
|
}
|
//查看是否有指向1排原绑定库位的任务
|
var newtask = dbOrm.ware_task.Where(u => u.ToLocationCode == newstr).FirstOrDefault();
|
if (newtask != null)
|
{
|
newtask.ToLocationCode = realToPlace;
|
var newtasksub = dbOrm.ware_task_sub.Where(u => u.TaskId == newtask.Id && u.DeviceId == int_deviceId && u.ToPlace == newstr).FirstOrDefault();
|
if (newtasksub != null)
|
{
|
newtasksub.ToPlace = realToPlace;
|
}
|
}
|
|
//目标库位修改为1排
|
realToPlace = newstr;
|
|
var container = dbOrm.wms_container.Where(u => u.ContainerCode == srmTask.ContainerCode).FirstOrDefault();
|
container.RealLocationCode = newstr;
|
|
srmTask.ToPlace = realToPlace;
|
|
//主任务也修改
|
var maintask = dbOrm.ware_task.Where(u => u.Id == srmTask.TaskId).FirstOrDefault();
|
maintask.ToLocationCode = realToPlace;
|
}
|
}
|
|
//判断是否存在指向放货站台的执行中的任务
|
isOk = dbOrm.ware_task_sub.Any(x => x.ToPlace == srmTask.ToPlace && x.TaskState == (int)SubTaskStateEnum.已下发);
|
if (isOk)
|
{
|
errMsg = "存在指向目标点" + srmTask.SourcePlace + "的任务,不能下发同一目标点的任务";
|
return;
|
}
|
}
|
|
//判断堆垛机是否有执行中的任务任务 【EditBy kejj,2022-09-22】
|
isOk = dbOrm.ware_task_sub.Any(u => u.DeviceId == int_deviceId && u.TaskState == (int)SubTaskStateEnum.执行中);
|
if (isOk)
|
{
|
errMsg = "不允许下发新任务,当前堆垛机存在执行中的任务";
|
return;
|
}
|
|
//同一个关联任务的其他设备任务
|
var relevanceTask = dbOrm.ware_task_sub.Where(x => x.TaskId == srmTask.TaskId && x.TaskSequence < srmTask.TaskSequence && x.TaskState == (int)SubTaskStateEnum.未开始).FirstOrDefault();
|
if (relevanceTask != null)
|
{
|
errMsg = string.Format("关联{0}任务未开始,所以堆垛机任务不允许下发!关联任务号:{1}", Enum.Parse(typeof(EDevice), relevanceTask.DeviceId.ToString()).ToString(), relevanceTask.TaskNo);
|
return;
|
}
|
|
ESrmCmd eSrmCmd;
|
if (srmTask.TaskType == (int)TaskCategoryEnum.InStock)
|
{
|
eSrmCmd = ESrmCmd.入库;
|
}
|
else if (srmTask.TaskType == (int)TaskCategoryEnum.OutStock)
|
{
|
eSrmCmd = ESrmCmd.出库;
|
}
|
else
|
{
|
eSrmCmd = ESrmCmd.库内搬运;
|
}
|
SdaResEntity sdaResult = new SdaResEntity();
|
try
|
{
|
if (WCSConfigHelper.GetConfig_IsSimulationPLC())
|
{
|
sdaResult.result = true;
|
}
|
else
|
{
|
if (Convert.ToInt32(srmTask.TaskNo) <= 0)
|
{
|
throw new Exception("任务号不能小于等于0,PlcTaskId:" + srmTask.TaskNo);
|
}
|
//short pallettype = GetSrmContainerType(srmTask.ContainerType);
|
short pallettype = Convert.ToInt16(srmTask.ContainerType);
|
if (pallettype == 0)
|
{
|
throw new Exception("托盘类型不能等于0,PlcTaskId:" + srmTask.TaskNo);
|
}
|
|
sdaResult = vs.SendSrmTask(int_deviceId, Convert.ToInt32(srmTask.TaskNo), realSourcePlace, realToPlace, (short)eSrmCmd, /*GetSrmContainerType(*/Convert.ToInt16(srmTask.ContainerType)/*)*/);
|
}
|
if (sdaResult.result == false)
|
{//给堆垛机下发指令失败
|
//exception.exceptionMsg = string.Format("发送指令给堆垛机失败,设备号{0},任务ID{1},起始位{2},目标位{3},ContainerId{4}", int_deviceId,
|
// Convert.ToInt32(srmTask.TaskNo), realSourcePlace, realToPlace, srmTask.ContainerCode);
|
//SysExceptionInfoHandler.InsertExceptionInfo(exception, true);
|
errMsg = string.Format("发送指令给堆垛机失败,设备号{0},任务ID{1},起始位{2},目标位{3},ContainerId{4}", int_deviceId,
|
Convert.ToInt32(srmTask.TaskNo), realSourcePlace, realToPlace, srmTask.ContainerCode);
|
return;
|
}
|
else
|
{
|
//SystemValueUtil.DelayExcuteForSrmTaskThreadService(int_deviceId, ThreadDirectionEnum.任务开始下发线程);
|
errMsg = "";
|
}
|
}
|
catch (Exception ex)
|
{
|
throw ex;
|
}
|
#endregion
|
}
|
|
public short GetSrmContainerType(int? conveyorContainerType)
|
{
|
if (conveyorContainerType == 1)
|
{
|
return 2;
|
}
|
else if (conveyorContainerType == 3)
|
{
|
return 1;
|
}
|
else
|
{
|
return 0;
|
}
|
}
|
#endregion
|
|
#region 自动结束堆垛机任务线程
|
|
/// <summary>
|
/// 自动结束堆垛机任务线程
|
/// </summary>
|
/// <param name="srmName"></param>
|
public override void ConfirmFinishTask(object deviceId)
|
{
|
string errMsg1 = "", errMsg2 = "", errMsg3 = "", errMsg4 = "";
|
int i_deviceId = (int)deviceId;
|
while (true)
|
{
|
if ((int)deviceId == (int)EDevice.堆垛机 && SystemValue.isStartedModel)
|
{
|
ConfirmFinishTaskHandle(i_deviceId, out errMsg1);
|
}
|
//else if ((int)deviceId == (int)EDevice.二号堆垛机 && SystemValue.isAllowRuning_SrmTaskThreadService_2_Finish && SystemValue.isStartedModel)
|
//{
|
// ConfirmFinishTaskHandle(i_deviceId, out errMsg2);
|
//}
|
|
SystemWarningMsg._lbl_Alert_Srm1ReleaseFinish = errMsg1;
|
SystemWarningMsg._lbl_Alert_Srm2ReleaseFinish = errMsg2;
|
|
Thread.Sleep(500);//设置2秒一次
|
}
|
}
|
|
/// <summary>
|
/// 自动结束堆垛机任务线程(线程)
|
/// </summary>
|
/// <param name="srmName"></param>
|
public override void ConfirmFinishTaskHandle(int deviceId, out string errMsg)
|
{
|
errMsg = "";
|
try
|
{
|
/*
|
* 执行发送给堆垛机的指令任务
|
* 1、验证根据设备号是否找到堆垛机
|
* 2、判断设备是否属于任务完成,如果属于任务完成,就继续走3
|
* 3、判断数据库中是否有可要完成的任务,如果有判断是否跟堆垛机中的完成任务相符,如果相符就处理
|
* 4、更新任务状态
|
*/
|
int int_deviceId = (int)deviceId;
|
var vs = new SrmService.SrmServiceClient();
|
using (DbOrm dbOrm = new DbOrm())
|
{
|
#region //3、判断数据库中是否有可要完成的任务,如果有判断是否跟堆垛机中的完成任务相符,如果相符就处理
|
var currentTask = ValidateIsExistTaskToDispose(dbOrm, int_deviceId, out errMsg, SubTaskStateEnum.已完成);
|
if (currentTask == null)
|
{//表示DB中没有任务要发送给堆垛机
|
errMsg = "没有堆垛机任务数据要处理";
|
return;
|
}
|
|
#endregion
|
|
//2、判断设备是否任务完成
|
//var isFinished = ValidateDeviceTaskIsFinsished(int_deviceId, currentTask, Convert.ToInt32(currentTask.TaskNo), (DeviceTaskTypeEnum)Enum.Parse(typeof(DeviceTaskTypeEnum), currentTask.TaskType.ToString()), true, out errMsg);
|
//if (!isFinished) return;
|
|
SdaResEntity sdaResult = vs.IsTaskFinish(int_deviceId, Convert.ToInt32(currentTask.TaskNo));
|
if (sdaResult.result != true)
|
{
|
errMsg = $"验证堆垛机是否任务完成 失败:{sdaResult.resMsg}";
|
return;
|
}
|
|
//同一个关联任务的其他设备任务
|
var relevanceTask = dbOrm.ware_task_sub.Where(x => x.TaskId == currentTask.TaskId && x.TaskSequence < currentTask.TaskSequence
|
&& (x.TaskState != (int)SubTaskStateEnum.已完成)).FirstOrDefault();
|
if (relevanceTask != null)
|
{
|
errMsg = string.Format("关联{0}任务未完成,所以堆垛机任务不允许完成!关联任务号:{1}", Enum.Parse(typeof(EDevice), relevanceTask.DeviceId.ToString()).ToString(), relevanceTask.TaskNo);
|
return;
|
}
|
|
//4、处理任务完成状态
|
//var isOk = ConfirmTaskFinishToSrm(currentTask, "堆垛机任务完成");
|
|
sdaResult = vs.ConfirmTaskFinish((int)currentTask.DeviceId, Convert.ToInt32(currentTask.TaskNo));
|
if (sdaResult.result)
|
{
|
//using (var tran = dbOrm.Database.BeginTransaction())
|
//{
|
//try
|
//{
|
//堆垛机完成了当前任务后进行任务状态的修改
|
//ChangeTaskStateWhenTaskFinish(currentTask);
|
currentTask.FinishedTime = DateTime.Now;//完成时间
|
currentTask.TaskState = (int)SubTaskStateEnum.已完成;
|
var isExist = dbOrm.ware_task_sub.Any(u => u.TaskId == currentTask.TaskId && u.TaskState != (int)SubTaskStateEnum.已完成 && u.Id != currentTask.Id);
|
if (!isExist)
|
{
|
var maintask = dbOrm.ware_task.Where(u => u.Id == currentTask.TaskId).FirstOrDefault();
|
if (maintask != null)
|
{
|
maintask.TaskState = (int)TaskStateEnum.已完成;
|
}
|
}
|
dbOrm.SaveChanges();
|
|
//tran.Commit();
|
//}
|
//catch (Exception)
|
//{
|
//tran.Rollback();
|
// throw;
|
//}
|
//}
|
}
|
|
}
|
vs.Close();
|
}
|
catch (Exception ex)
|
{
|
errMsg = $"堆垛机任务完成异常:{ex.Message}";
|
//SysExceptionInfoHandler.GetExceptionInfoForError("自动结束堆垛机任务线程(线程)出现异常,deviceId:" + deviceId + ",异常:" + ex.Message, ex, ref exception);
|
//SysExceptionInfoHandler.InsertExceptionInfo(exception, true);
|
}
|
}
|
|
|
|
/// <summary>
|
/// 判断是人工发送给任务,单独给堆垛机发送任务完成信号
|
/// </summary>
|
/// <param name="deviceId"></param>
|
/// <param name="taskId"></param>
|
/// <returns></returns>
|
private bool ConfirmTaskFinishToSda(int deviceId, int taskId)
|
{
|
//任务完成处理成功,需要再给堆垛机发送任务完成确认信号
|
SdaResEntity sdaResult = new SdaResEntity();
|
try
|
{
|
sdaResult = new SrmService.SrmServiceClient().ConfirmTaskFinish(deviceId, taskId);
|
|
if (!sdaResult.result)
|
{
|
Log4NetHelper.WriteInfoLog(iWareCommon.Utils.LogType.SrmTheadService, "判断是人工发送的任务,单独给堆垛机发送任务完成信号,【失败】,设备号:" + deviceId + ",任务号:" + taskId);
|
return false;
|
}
|
else
|
{
|
Log4NetHelper.WriteInfoLog(iWareCommon.Utils.LogType.SrmTheadService, "判断是人工发送的任务,单独给堆垛机发送任务完成信号,【成功】,设备号:" + deviceId + ",任务号:" + taskId);
|
return true;
|
}
|
}
|
catch (Exception ex)
|
{
|
Log4NetHelper.WriteErrorLog(iWareCommon.Utils.LogType.SrmTheadService, "判断是人工发送的任务,单独给堆垛机发送任务完成信号,【异常】,设备号:" + deviceId + ",任务号:" + taskId + ",ex:" + ex.Message, ex);
|
throw ex;
|
}
|
}
|
|
#region 向堆垛机发送任务完成确认信号
|
|
|
/// <summary>
|
/// 向堆垛机发送任务完成确认信号
|
/// </summary>
|
/// <param name="currentTask"></param>
|
/// <param name="business"></param>
|
/// <param name="exception"></param>
|
/// <returns></returns>
|
private bool ConfirmTaskFinishToSrm(ware_task_sub currentTask, string business)
|
{
|
//任务完成处理成功,需要再给堆垛机发送任务完成确认信号
|
SdaResEntity sdaResult = new SdaResEntity();
|
string realSourcePlace = "";
|
string realToPlace = "";
|
if (currentTask.TaskType == (int)TaskCategoryEnum.InStock)
|
{
|
realSourcePlace = GetRealLocatiomCodeIn(currentTask.SourcePlace);
|
realToPlace = currentTask.ToPlace;
|
}
|
else if (currentTask.TaskType == (int)TaskCategoryEnum.OutStock)
|
{
|
realSourcePlace = currentTask.SourcePlace;
|
realToPlace = GetRealLocatiomCodeOut(currentTask.ToPlace);
|
}
|
try
|
{
|
if (WCSConfigHelper.GetConfig_IsSimulationPLC())
|
{
|
sdaResult.result = true;
|
}
|
else
|
{
|
sdaResult = new SrmService.SrmServiceClient().ConfirmTaskFinish((int)currentTask.DeviceId, Convert.ToInt32(currentTask.TaskNo));
|
}
|
if (!sdaResult.result)
|
{
|
//exception.exceptionMsg = string.Format(business + ",需要再给堆垛机发送任务完成确认信号失败,设备号{0} 任务号{1}", (int)currentTask.DeviceId, currentTask.TaskNo);
|
//SysExceptionInfoHandler.InsertExceptionInfo(exception, true);
|
return false;
|
}
|
else
|
{
|
Log4NetHelper.WriteInfoLog(base.currentLogType, string.Format(business + ",再给堆垛机发送任务完成确认信号成功,设备号{0} 任务号{1}", (int)currentTask.DeviceId, currentTask.TaskNo));
|
return true;
|
}
|
}
|
catch (Exception ex)
|
{
|
throw ex;
|
}
|
}
|
|
#endregion
|
|
#endregion
|
|
#endregion
|
|
#region 公共处理
|
|
|
///// <summary>
|
///// 验证RGV站点上是否允许下发堆垛机新任务
|
///// </summary>
|
///// <param name="model"></param>
|
///// <param name="_DeviceTaskTypeEnum"></param>
|
///// <param name="realToPlace"></param>
|
///// <param name="errMsg"></param>
|
///// <returns>true:允许,false:不允许</returns>
|
//private bool ValidateIsAllowNewTaskForRgvStattion(DbModel model, DeviceTaskTypeEnum _DeviceTaskTypeEnum, string realToPlace, ref string errMsg)
|
//{
|
// MainInOutFlagEnum _MainInOutFlagEnum = GetMainInOutFlagForSrm(_DeviceTaskTypeEnum);
|
// if (_MainInOutFlagEnum == MainInOutFlagEnum.出库)
|
// {
|
// //判断目标点是否有光电占用
|
// var rgv_stationCode = model.Base_Station.Where(x => x.SrmStationCode == realToPlace).First();
|
// var isGD_HasCatogryForRgvStattion = MyExtendHelper.IsGD_HasCatogryForRgvStattion(rgv_stationCode.RgvStationCode);
|
// if (isGD_HasCatogryForRgvStattion)
|
// {
|
// errMsg = "RGV出库口站点" + rgv_stationCode.RgvStationCode + "上面光电显示有货,不允许下发堆垛机的出库任务";
|
// return false;
|
// }
|
// }
|
// return true;
|
//}
|
|
/// <summary>
|
/// 根据堆垛机任务类型判断出是出库还是入库
|
/// </summary>
|
/// <param name="_DeviceTaskTypeEnum"></param>
|
/// <returns></returns>
|
private MainInOutFlagEnum GetMainInOutFlagForSrm(DeviceTaskTypeEnum _DeviceTaskTypeEnum)
|
{
|
switch (_DeviceTaskTypeEnum)
|
{
|
case DeviceTaskTypeEnum.组盘入库:
|
case DeviceTaskTypeEnum.空托转运到立体库:
|
return MainInOutFlagEnum.入库;
|
case DeviceTaskTypeEnum.立库空托到拆盘机入口:
|
case DeviceTaskTypeEnum.出库:
|
return MainInOutFlagEnum.出库;
|
}
|
throw new Exception("堆垛机不支持的任务类型" + _DeviceTaskTypeEnum.ToString());
|
}
|
|
/// <summary>
|
/// 堆垛机任务完成后修改任务状态
|
/// </summary>
|
/// <param name="currentTask"></param>
|
private void ChangeTaskStateWhenTaskFinish(ware_task_sub currentTask)
|
{
|
//堆垛机完成了当前任务后进行任务状态的修改
|
currentTask.FinishedTime = DateTime.Now;//完成时间
|
//currentTask.IsFinished = true;
|
currentTask.TaskState = (int)SubTaskStateEnum.已完成;
|
//currentTask.TaskStateName = DeviceTaskStatusEnum.已完成.ToString();
|
//currentTask.OperationRemark = "已完成";
|
//currentTask.ModifyTime = DateTime.Now;
|
//currentTask.ModifyBy = SysGloble.WCSSystem;
|
//currentTask.IsLastTask = (int)EYesOrNo.否;//设置不是最新的任务
|
}
|
|
/// <summary>
|
/// 堆垛机任务完成后,根据堆垛机的任务类型去判断Base_Salver_V_Station 的State
|
/// </summary>
|
/// <param name="_DeviceTaskTypeEnum">堆垛机任务类型</param>
|
/// <param name="old_int_C_V_P_StateEnum">原先的Base_Salver_V_Station 的State</param>
|
/// <returns></returns>
|
private Salver_V_Station_StateEnum DeviceTaskTypeEnumToC_V_P_StateEnumWhenTaskFinish(DeviceTaskTypeEnum _DeviceTaskTypeEnum, int old_int_C_V_P_StateEnum)
|
{
|
Salver_V_Station_StateEnum old_C_V_P_StateEnum = (Salver_V_Station_StateEnum)Enum.Parse(typeof(Salver_V_Station_StateEnum), old_int_C_V_P_StateEnum.ToString());
|
Salver_V_Station_StateEnum _C_V_P_StateEnum = old_C_V_P_StateEnum;
|
switch (_DeviceTaskTypeEnum)
|
{
|
case DeviceTaskTypeEnum.组盘入库:
|
_C_V_P_StateEnum = Salver_V_Station_StateEnum.在库物料;
|
break;
|
//case DeviceTaskTypeEnum22.线下其他垛入库:
|
// _C_V_P_StateEnum = C_V_P_StateEnum.在库其他料;
|
// break;
|
//case DeviceTaskTypeEnum22.线下垫板垛入库:
|
// _C_V_P_StateEnum = C_V_P_StateEnum.在库垫板;
|
// break;
|
//case DeviceTaskTypeEnum22.成品料配板完成回库:
|
// _C_V_P_StateEnum = C_V_P_StateEnum.在库成品料;
|
// break;
|
//case DeviceTaskTypeEnum22.待拆垛回库:
|
// _C_V_P_StateEnum = C_V_P_StateEnum.在库待拆垛;
|
// break;
|
//case DeviceTaskTypeEnum22.桁架垫板垛入立库垫板库位:
|
//case DeviceTaskTypeEnum22.锯切垫板垛入立体库:
|
// _C_V_P_StateEnum = C_V_P_StateEnum.在库垫板;
|
// break;
|
//case DeviceTaskTypeEnum22.移库://移库,状态不变
|
//case DeviceTaskTypeEnum22.成品料上锯切线出库://成品料出库,状态不变
|
//case DeviceTaskTypeEnum22.垫板上料出库://垫板出库,状态不变
|
// _C_V_P_StateEnum = old_C_V_P_StateEnum;
|
// break;
|
//case DeviceTaskTypeEnum22.配板原料出库:
|
// _C_V_P_StateEnum = C_V_P_StateEnum.原料配板中;
|
// break;
|
//case DeviceTaskTypeEnum22.人工出库://出库后会将表Base_Salver_V_Station 清掉
|
// break;
|
}
|
return _C_V_P_StateEnum;
|
}
|
|
public override bool ValidateDeviceIsAllowSendTask(int int_deviceId, out string errMsg)
|
{
|
if (FormCC.IsSimulationPLC)
|
{
|
errMsg = "模拟PLC";
|
return true;
|
}
|
//errMsg = "";
|
if (!base.ValidateDeviceIsAllowSendTask(int_deviceId, out errMsg))
|
{
|
return false;
|
}
|
using (var srmService = new SrmService.SrmServiceClient())
|
{
|
SdaResEntity sdaResult = srmService.IsAllowSendTask(int_deviceId, out errMsg);
|
if (sdaResult.result == false)
|
{
|
errMsg = "非自动、有任务未确认或有报警," + sdaResult.resMsg;
|
Log4NetHelper.WriteErrorLog(currentLogType, "验证堆垛机不可以下发新任务,int_deviceId:" + int_deviceId + ",sdaResultStr:" + JsonConvert.SerializeObject(sdaResult));
|
}
|
return sdaResult.result;
|
}
|
}
|
|
/// <summary>
|
/// 验证堆垛机是否任务完成
|
/// </summary>
|
/// <param name="int_deviceId"></param>
|
/// <returns></returns>
|
private bool ValidateDeviceTaskIsFinsished(int int_deviceId, ware_task_sub _task, int taskId, DeviceTaskTypeEnum _DeviceTaskTypeEnum, bool? isAllowSimulateExecute, out string errMsg)
|
{
|
errMsg = "";
|
if (WCSConfigHelper.GetConfig_IsSimulationPLC())
|
{
|
errMsg = "模拟PLC完成或任务要求强制模拟完成";
|
return true;
|
}
|
|
SdaResEntity sdaResult = new SrmService.SrmServiceClient().IsTaskFinish(int_deviceId, taskId);
|
if (sdaResult.result == false)
|
{
|
errMsg = "验证堆垛机是否任务完成 失败:" + JsonConvert.SerializeObject(sdaResult);
|
//Log4NetHelper.WriteErrorLog(currentLogType, "验证堆垛机是否任务完成 失败:" + JsonConvert.SerializeObject(sdaResult));
|
}
|
//switch (_DeviceTaskTypeEnum)
|
//{
|
// //涉及到最后到输送线的任务,都要再加上输送线的任务是否完成
|
// case DeviceTaskTypeEnum.组盘入库:
|
// //using (var srmConveyorService = new SrmConveyorService.SrmConveyorServiceClient())
|
// //{
|
// // sdaResultStr = srmConveyorService.IsTaskFinish(taskId);
|
// // sdaResult = JsonConvert.DeserializeObject<SdaResEntity>(sdaResultStr);
|
// // if (sdaResult.result == false)
|
// // {
|
// // errMsg = "验证输送线是否任务完成 失败:" + sdaResultStr;
|
// // Log4NetHelper.WriteErrorLog(currentLogType, "验证输送线是否任务完成 失败:" + sdaResultStr);
|
// // }
|
// //}
|
// break;
|
//}
|
|
return sdaResult.result;
|
}
|
|
#endregion
|
|
#region 私有方法
|
|
/// <summary>
|
/// 验证数据库中是否有任务要处理
|
/// </summary>
|
/// <typeparam name="Task_Part"></typeparam>
|
/// <param name="dbModel"></param>
|
/// <param name="int_deviceId">Rgv设备号</param>
|
/// <param name="errMsg"></param>
|
/// <param name="_TaskExcuteTypeEnum"></param>
|
/// <returns></returns>
|
private List<ware_task_sub> ValidateIsExistTaskToDisposeForIssued(DbOrm dbOrm, int int_deviceId, out string errMsg)
|
{
|
errMsg = "";
|
List<ware_task_sub> partList = new List<ware_task_sub>();
|
//看同一个设备,是否还有其他正在执行的任务
|
var partTask = dbOrm.ware_task_sub.Where(x => x.DeviceId == int_deviceId && x.TaskState == (int)SubTaskStateEnum.已下发).
|
OrderBy(x => x.CreatedTime).FirstOrDefault();//按照主任务的顺序升序
|
if (partTask != null)
|
{
|
errMsg = string.Format("deviceId={0}的正在执行任务,任务ID:" + partTask.Id + ",主任务:" + partTask.TaskId + ",PLC任务号:" + partTask.TaskNo, int_deviceId);
|
return null;
|
}
|
|
//1、查询
|
var currTaskList = dbOrm.ware_task_sub.Where(x => x.DeviceId == int_deviceId && (x.TaskState == (int)SubTaskStateEnum.未开始 || x.TaskState == (int)SubTaskStateEnum.等待下发)).ToList().OrderBy(x => x.CreatedTime).ToList();//按照主任务优先级的升序排序
|
if (currTaskList == null || currTaskList.Count == 0)
|
{
|
errMsg = "没有需要处理的任务";
|
return null;
|
}
|
|
//查找所有AGV任务
|
var agvTaskList = dbOrm.ware_task_sub.AsNoTracking().Where(u => u.DeviceId == 1099).ToList();
|
var currentAgvTask = agvTaskList.Find(u => u.TaskState == (int)SubTaskStateEnum.已完成);
|
if (currentAgvTask == null)
|
{
|
//查找AGV执行步骤最高的
|
currentAgvTask = agvTaskList.OrderByDescending(u => u.TaskState).FirstOrDefault();
|
}
|
|
if (currentAgvTask != null)
|
{
|
//currentAgvTask是执行步骤最高的agv,优先下这个的关联任务
|
var vs = currTaskList.FindAll(u => u.TaskId == currentAgvTask.TaskId).OrderBy(u => u.TaskSequence).FirstOrDefault();
|
if (vs != null)
|
{
|
if (vs.TaskState == (int)SubTaskStateEnum.等待下发)
|
{
|
errMsg = $"目标点{vs.ToPlace}的堆垛机任务等待下发";
|
return null;
|
}
|
else
|
{
|
partList.Add(vs);
|
return partList;
|
}
|
}
|
else
|
{
|
//执行步骤最高的agv没有待处理的堆垛机任务
|
//查找另一个agv任务
|
var anotherAgvTask = agvTaskList.Find(u => u.TaskId != currentAgvTask.TaskId);
|
if (anotherAgvTask == null)
|
{
|
var temp = currTaskList.Find(u => u.TaskType == (int)TaskCategoryEnum.MoveStock && u.TaskSequence == 1);
|
if (temp != null)
|
{
|
partList.Add(temp);
|
return partList;
|
}
|
errMsg = "没有任务要执行";
|
return null;
|
}
|
else
|
{
|
var anthorSrmTask = currTaskList.FindAll(u => u.TaskId == anotherAgvTask.TaskId).OrderBy(u => u.TaskSequence).FirstOrDefault(); ;
|
if (anthorSrmTask != null)
|
{
|
if (anthorSrmTask.TaskState == (int)SubTaskStateEnum.等待下发)
|
{
|
errMsg = $"目标点{anthorSrmTask.ToPlace}的堆垛机任务等待下发";
|
return null;
|
}
|
else
|
{
|
partList.Add(vs);
|
return partList;
|
}
|
}
|
else
|
{
|
errMsg = "没有任务要执行";
|
return null;
|
}
|
}
|
}
|
}
|
else
|
{
|
var temp = currTaskList.Find(u => u.TaskType == (int)TaskCategoryEnum.MoveStock && u.TaskSequence == 1);
|
if (temp != null)
|
{
|
partList.Add(temp);
|
return partList;
|
}
|
else
|
{
|
return null;
|
}
|
}
|
|
|
|
//查找AGV执行步骤最高的
|
//var agvTask = dbOrm.ware_task_sub.AsNoTracking().Where(u => u.TaskState > 0 && u.DeviceId == 1099).OrderByDescending(u => u.TaskState).FirstOrDefault();
|
//ware_task_sub temp = null;
|
//if (agvTask == null)
|
//{
|
// temp = currTaskList.Find(u => u.TaskType == (int)TaskCategoryEnum.MoveStock);
|
// if (temp == null)
|
// {
|
// errMsg = "agv没有到达,等待下发";
|
// return null;
|
// }
|
// else
|
// {
|
// partList.Add(temp);
|
// return partList;
|
// }
|
//}
|
|
|
//var firstTask = currTaskList.First();//第一个待执行的任务
|
//var firstTask = currTaskList.Find(u => u.TaskId == agvTask.TaskId);
|
//partList.Add(firstTask);
|
/*
|
//判断如果这个任务是出库任务的话,就再查询第一个待执行的入库任务
|
DeviceTaskTypeEnum _DeviceTaskTypeEnum = (DeviceTaskTypeEnum)Enum.Parse(typeof(DeviceTaskTypeEnum), firstTask.TaskType.ToString());
|
//查询 出库和入库的两个任务,优先执行出库任务 【EditBy shaocx,2022-05-09】
|
MainInOutFlagEnum _MainInOutFlagEnum = GetMainInOutFlagForSrm(_DeviceTaskTypeEnum);
|
if (_MainInOutFlagEnum == MainInOutFlagEnum.出库)
|
{
|
//查询第一个待执行的入库任务
|
var queryInOutFlag = (int)MainInOutFlagEnum.入库;
|
var fisrtTaskForIn = currTaskList.Where(x => x.InOutFlag == queryInOutFlag).ToList().OrderBy(x => x.CreateTime).FirstOrDefault();
|
if (fisrtTaskForIn != null)
|
{
|
partList.Add(fisrtTaskForIn);
|
}
|
}
|
*/
|
//return partList;
|
}
|
|
#endregion
|
}
|
}
|