using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WCS.Data;
using WCS.Data.Models;
namespace WCS.PLC
{
public class Srm
{
#region 属性
///
/// 堆垛机名称
///
internal string SrmNo { get; set; }
///
/// plc信息
///
protected WCS_PLC WCS_PLCItem
{
get
{
return Current.PlcSet.FirstOrDefault(v => v.PLC_NAME == SrmNo);
}
}
///
/// 堆垛机信号
///
protected SrmSignal EquSignal
{
get
{
return WCS_PLCItem.WCS_StackerDataSet[0].StackerData;
}
}
///
/// 写入DB名称
///
protected int WriteDbName
{
get
{
return WCS_PLCItem.WCS_DBSet[0].DB_NAME;
}
}
///
/// 堆垛机出入库口设置列表
///
protected List SrmOutInInfoSet = new List();
#endregion;
#region 构造函数
public Srm(string srmno)
{
SrmNo = srmno;
}
#endregion;
#region 方法
private int _locExecute = 0;
internal void ExecuteSrm()
{
if (Interlocked.Exchange(ref _locExecute, 1) == 0)
{
try
{
if (WCS_PLCItem.IsConnSuccess == false) return;
//写入心跳
//WriteHandShake();
//完成任务
SRMCompleteTask();
//执行任务
SRMStartExecuteTask();
//入库分配货位
ThreadHelper.TaskThread(InTaskAssignWareCell);
}
catch (Exception ex)
{
string errormsg = string.Format("堆垛机[{0}]执行异常,消息:{1}", SrmNo, ex.ToString());
Log4netHelper.Logger_Error.ErrorFormat(errormsg);
}
finally
{
Interlocked.Exchange(ref _locExecute, 0);
}
}
}
///
/// 堆垛机任务完成
///
protected virtual void SRMCompleteTask()
{
try
{
//当前任务完成
if (EquSignal.DB521_Task_Finishi == false) return;
//查询任务
var task = SugarBase.DB.Queryable().First(v => v.TASK_NO == EquSignal.DB521_Taskfinishi_ID);
if (task == null) return;
if (task.TASK_WKSTATUS >= 99) return;
if (task.TASK_COMTYPE == (int)ComTypeEnum.入库 || task.TASK_COMTYPE == (int)ComTypeEnum.移库)
{
//完成任务
string result = TryCachHelper.TryTranExecute((db) =>
{
//修改任务的状态
db.Updateable(it => new WCS_TASK() { TASK_WKSTATUS = 99, TASK_EDITUSERNO = "WCS", TASK_EDITDATETIME = DateTime.Now })
.Where(it => it.TASK_NO == task.TASK_NO)
.ExecuteCommand();
//添加修改明细
string msg = string.Format("任务[{0}]完成", task.TASK_NO);
CommonData.AddWCS_TASK_DTL(db, task.TASK_NO, task.TASK_NO, task.TASK_POSIDCUR, task.TASK_POSIDTO, msg);
});
if (string.IsNullOrWhiteSpace(result))
{
if (task.TASK_COMTYPE == (int)ComTypeEnum.入库)
{
SrmConvNoMoveToLast(task.TASK_POSIDCUR);
}
}
}
else if (task.TASK_COMTYPE == (int)ComTypeEnum.出库)
{
if (task.TASK_WKSTATUS == (int)WkStatus.堆垛机执行)
{
var routeSet = EquRouteHelper.QueryRoute(task.TASK_SRMNO, task.TASK_POSIDTO);
var route = routeSet.FirstOrDefault(v => v.ROUTE_STARTPOS == task.TASK_SRMNO);
string result = TryCachHelper.TryTranExecute((db) =>
{
//修改任务的状态
db.Updateable(it => new WCS_TASK() { TASK_WKSTATUS = 6, TASK_POSIDCUR = route.ROUTE_NEXTPOS, TASK_POSIDNEXT = route.ROUTE_NEXTPOS, TASK_EDITUSERNO = "WCS", TASK_EDITDATETIME = DateTime.Now })
.Where(it => it.TASK_NO == task.TASK_NO)
.ExecuteCommand();
//添加修改明细
string msg = string.Format("任务[{0}]堆垛机完成,修改当前地址为[{1}]", task.TASK_NO, route.ROUTE_NEXTPOS);
CommonData.AddWCS_TASK_DTL(db, task.TASK_NO, task.TASK_NO, route.ROUTE_NEXTPOS, route.ROUTE_NEXTPOS, msg);
});
if (string.IsNullOrWhiteSpace(result))
{
SrmConvNoMoveToLast(task.TASK_POSIDNEXT);
}
}
}
//TaskComplete(task.TASK_SRMNO, task.TASK_ID, task.TASK_COMTYPE);
}
catch (Exception ex)
{
Log4netHelper.Logger_Error.ErrorFormat(ex.ToString());
}
}
///
/// 调整堆垛机出入口顺序
///
///
private void SrmConvNoMoveToLast(string convNo)
{
//检测是否是最后一项
if (SrmOutInInfoSet[SrmOutInInfoSet.Count() - 1].SRMOUTIN_CONVNO == convNo) return;
//查询要调整执行顺序的输送线
var outininfo = SrmOutInInfoSet.FirstOrDefault(v => v.SRMOUTIN_CONVNO == convNo);
//删除当前
SrmOutInInfoSet.Remove(outininfo);
//添加到最后
SrmOutInInfoSet.Add(outininfo);
}
///
/// 堆垛机执行任务
///
private void SRMStartExecuteTask()
{
//检测堆垛机模式
if (EquSignal.DB521_Auto_status != (int)SrmModeEnum.远程) return;
//检测堆垛机报警
if (EquSignal.SrmDB541_Alarm) return;
//检测堆垛机状态
if (EquSignal.DB521_Srm_Status != (int)SrmStateFork1Enum.空闲) return;
TryCachHelper.TryExecute((db) =>
{
var taskSet = db.Queryable().Where(v => v.TASK_SRMNO == SrmNo).ToList();
var task = taskSet.FirstOrDefault(v => (v.TASK_WKSTATUS == (int)WkStatus.堆垛机执行));
if (task == null)
{
//查询移库任务
var moveTask = taskSet.FirstOrDefault(v => v.TASK_COMTYPE == 3 && v.TASK_WKSTATUS <= 1);
if (moveTask != null)
{
WriteTaskInfoToSrm(task);
}
else
{
//查询出库任务
var tasks = taskSet.Where(v => v.TASK_COMTYPE == 2 && v.TASK_WKSTATUS <= 1).ToList();
//查询入库任务(已分配货位的任务)
var inTasks = taskSet.Where(v => v.TASK_COMTYPE == 1 && v.TASK_WKSTATUS == 11).ToList();
tasks.AddRange(inTasks);
OutInStockByPriority(db, tasks);
}
}
else
{
Log4netHelper.Logger_Error.ErrorFormat(string.Format("堆垛机[{0}]状态正常,但是存在执行中的任务[{1}]", SrmNo, task.TASK_NO));
}
});
}
private void SrmOutIn(WCSWriteToSrmSignal srmSignal, string posIdnext)
{
if (EquSignal.DB520_Start_number == srmSignal.Start_number &&
EquSignal.DB520_End_number == srmSignal.End_number &&
EquSignal.DB520_Goodtype == srmSignal.Goodtype &&
EquSignal.DB520_Runmode == srmSignal.Runmode &&
EquSignal.DB520_FromRowPos == srmSignal.RowPos1 &&
EquSignal.DB520_FromColumnPos == srmSignal.Travelpos1 &&
EquSignal.DB520_FromLayerPos == srmSignal.Liftpos1 &&
EquSignal.DB520_Fork_start_pos1 == srmSignal.Fork_start_pos1 &&
EquSignal.DB520_ToRowPos == srmSignal.RowPos2 &&
EquSignal.DB520_ToColumnPos == srmSignal.Travelpos2 &&
EquSignal.DB520_ToLayerPos == srmSignal.Liftpos2 &&
EquSignal.DB520_Fork_dest_pos2 == srmSignal.Fork_dest_pos2 &&
EquSignal.DB520_TaskID == srmSignal.TaskID)
{
string result = TryCachHelper.TryTranExecute((db) =>
{
var task = db.Queryable().First(t => t.TASK_NO == srmSignal.TaskID);
db.Updateable(it => new WCS_TASK() { TASK_WKSTATUS = (int)WkStatus.堆垛机执行, TASK_POSIDNEXT = posIdnext, TASK_EDITUSERNO = "WCS", TASK_EDITDATETIME = DateTime.Now })
.Where(it => it.TASK_NO == srmSignal.TaskID).ExecuteCommand();
string msg = string.Format("任务[{0}]已下发给堆垛机执行。", task.TASK_NO);
CommonData.AddWCS_TASK_DTL(db, task.TASK_NO, task.TASK_NO, task.TASK_POSIDCUR, posIdnext, msg);
if (EquSignal.DB520_Task_trigger != 1)
{
if (!WCS_PLCItem.Plc.WriteSignal((ushort)WriteDbName, 28, 2, 1))
{
throw new Exception(string.Format("任务[{0}]写入触发信号失败!", task.TASK_NO));
}
}
});
if (!string.IsNullOrWhiteSpace(result))
throw new Exception(string.Format("任务[{0}]堆垛机执行失败,原因:[{1}]", srmSignal.TaskID, result));
}
else
{
WriteTaskToSrm(srmSignal);
}
}
///
/// 写入任务信息到堆垛机
///
///
private void WriteTaskInfoToSrm(WCS_TASK task)
{
var writeSignal = new WCSWriteToSrmSignal();
writeSignal.Start_number = 0;
writeSignal.End_number = 0;
writeSignal.Goodtype = 0;
if (task.TASK_COMTYPE == 1)
{
//入库
var route = Current.EquRouteSet.FirstOrDefault(v => v.ROUTE_STARTPOS == task.TASK_POSIDCUR);
writeSignal.RowPos1 = (int)route.SRMROW;
writeSignal.Travelpos1 = (int)route.SRMCOLUMN;
writeSignal.Liftpos1 = (int)route.SRMLAYER;
writeSignal.RowPos2 = task.ToRow;
writeSignal.Travelpos2 = task.ToCol;
writeSignal.Liftpos2 = task.ToLayer;
}
else if (task.TASK_COMTYPE == 2)
{
//出库
writeSignal.RowPos1 = task.FromRow;
writeSignal.Travelpos1 = task.FromCol;
writeSignal.Liftpos1 = task.FromLayer;
var routeSet = EquRouteHelper.QueryRoute(task.TASK_SRMNO, task.TASK_POSIDTO);
var route = routeSet.FirstOrDefault(v => v.ROUTE_STARTPOS == task.TASK_SRMNO);
writeSignal.RowPos2 = (int)route.SRMROW;
writeSignal.Travelpos2 = (int)route.SRMCOLUMN;
writeSignal.Liftpos2 = (int)route.SRMLAYER;
}
else if (task.TASK_COMTYPE == 3)
{
//移库
writeSignal.RowPos1 = task.FromRow;
writeSignal.Travelpos1 = task.FromCol;
writeSignal.Liftpos1 = task.FromLayer;
writeSignal.RowPos2 = task.ToRow;
writeSignal.Travelpos2 = task.ToCol;
writeSignal.Liftpos2 = task.ToLayer;
}
writeSignal.TaskID = task.TASK_NO;
//执行任务
SrmOutIn(writeSignal, task.TASK_POSIDTO);
}
private void WriteTaskToSrm(WCSWriteToSrmSignal srmSignal)
{
List list = new List();
list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.Start_number).ToList());
list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.End_number).ToList());
list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.Goodtype).ToList());
list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.Runmode).ToList());
list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.RowPos1).ToList());
list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.Travelpos1).ToList());
list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.Liftpos1).ToList());
list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.Fork_start_pos1).ToList());
list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.RowPos2).ToList());
list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.Travelpos2).ToList());
list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.Liftpos2).ToList());
list.AddRange(ExtendsUtil.UshortToByte((ushort)srmSignal.Fork_dest_pos2).ToList());
list.AddRange(ExtendsUtil.UintToByte((uint)srmSignal.TaskID).ToList());
Log4netHelper.Logger_Info.InfoFormat(string.Format("写入任务[{0}]信息", srmSignal.TaskID));
bool result = WCS_PLCItem.Plc.Write((ushort)WriteDbName, 2, list.ToArray());
}
private void OutInStockByPriority(SqlSugarClient db, List tasks)
{
int taskMaxPriority = tasks.Max(v => v.TASK_PRIORITY);
for (int index = 0; index < taskMaxPriority; index++)
{
var tasks_Temp = tasks.Where(v => v.TASK_PRIORITY == index).ToList();
if (InOutStock(db, tasks_Temp)) break;
}
}
private bool InOutStock(SqlSugarClient db, List tasks)
{
bool result = false;
if (tasks.Count == 0) return result;
//克隆集合
List outininfoSet = SrmOutInInfoSet.GetRange(0, SrmOutInInfoSet.Count);
foreach (var outininfo in outininfoSet)
{
if (outininfo.SRMOUTIN_OUTINTYPE == "in")
{
//检测入库口状态
var convSignal = ConveyorHelper.GetConveyorSignal(outininfo.SRMOUTIN_CONVPLCNAME, outininfo.SRMOUTIN_CONVNO);
if (convSignal.DB521_Tasknum > 0 &&
convSignal.DB521_Goodsend.ToString() == outininfo.SRMOUTIN_CONVNO)
{
var curtask = tasks.FirstOrDefault(v => v.TASK_NO == convSignal.DB521_Tasknum);
if (curtask != null)
{
WriteTaskInfoToSrm(curtask);
result = true;
break;
}
}
}
else if (outininfo.SRMOUTIN_OUTINTYPE == "out")
{
//检测出口状态
var convSignal = ConveyorHelper.GetConveyorSignal(outininfo.SRMOUTIN_CONVPLCNAME, outininfo.SRMOUTIN_CONVNO);
if (convSignal.DB521_Request == false && convSignal.DB521_Tasknum <= 0)
{
var curOutTask = db.Queryable().First(v => v.TASK_POSIDCUR == outininfo.SRMOUTIN_CONVNO);
if (curOutTask == null ||
((curOutTask.TASK_WKSTATUS != (int)WkStatus.输送机执行) && (curOutTask.TASK_WKSTATUS != (int)WkStatus.堆垛机完成)))
{
var outtaskSet = new List();
//检测是否存在该出口的任务
foreach (var task in tasks)
{
var route = EquRouteHelper.QueryRoute(task.TASK_SRMNO, task.TASK_POSIDTO).FirstOrDefault(v => v.ROUTE_STARTPOS == SrmNo);
if (route == null)
{
Log4netHelper.Logger_Error.ErrorFormat(string.Format("任务[{0}]目标地址[{1}]堆垛机[{2}]", task.TASK_NO, task.TASK_POSIDTO, SrmNo));
}
if (outininfo.SRMOUTIN_CONVNO == route.ROUTE_NEXTPOS)
{
//outtask = task;
outtaskSet.Add(task);
break;
}
}
var temptask = QueryOutTask(db, outtaskSet);
if (temptask != null)
{
WriteTaskInfoToSrm(temptask);
result = true;
break;
}
}
}
}
//无任务则移动到最后
SrmConvNoMoveToLast(outininfo.SRMOUTIN_CONVNO);
}
return result;
}
private WCS_TASK QueryOutTask(SqlSugarClient db, List outtaskSet)
{
WCS_TASK temptask = null;
var outtasks = QueryOutTask(outtaskSet);
foreach (var outtask in outtasks)
{
if (outtask.FromDepth == 2)
{
var oneDepthTask = Current.TaskSet.First(v => v.FromRow == outtask.FromSingleDepthRow &&
v.FromLayer == outtask.FromLayer &&
v.FromCol == outtask.FromCol &&
(v.TASK_WKSTATUS <= 1));
if (oneDepthTask == null)
{
//调用WMS接口申请移库
var moveTaskresult = Current.WmsInterface.I_WCS_GetMoveTask(new GetMoveTaskParam() { WMSTaskNum = outtask.TASK_WMSNO });
if (moveTaskresult.ResType == 0)
{
Log4netHelper.Logger_Error.ErrorFormat(moveTaskresult.ResMessage);
}
else if (moveTaskresult.ResType == 2)
{
//创建移库任务并执行
var moveTask = new WCS_TASK();
db.Insertable(moveTask).ExecuteCommand();
temptask = db.Queryable().First(v => v.TASK_WMSNO == moveTask.TASK_WMSNO);
break;
}
else if (moveTaskresult.ResType == 1)
{
temptask = outtask;
break;
}
}
else
{
if (oneDepthTask.TASK_COMTYPE == 2)
{
//判断是否是相同出口的任务
if (outtasks.Any(v => v.TASK_NO == oneDepthTask.TASK_NO))
{
temptask = oneDepthTask;
}
else
{
var routeSet = EquRouteHelper.QueryRoute(oneDepthTask.TASK_SRMNO, oneDepthTask.TASK_POSIDTO);
var route = routeSet.FirstOrDefault(v => v.ROUTE_STARTPOS == outtask.TASK_SRMNO);
var outinitem = SrmOutInInfoSet.FirstOrDefault(v => v.SRMOUTIN_CONVNO == route.ROUTE_NEXTPOS);
var convs = ConveyorHelper.GetConveyorSignal(outinitem.SRMOUTIN_CONVPLCNAME, outinitem.SRMOUTIN_CONVNO);
if (convs.DB521_Tasknum > 0)
{
var ttask = Current.TaskSet.FirstOrDefault(v => v.TASK_NO == convs.DB521_Tasknum && v.TASK_WKSTATUS == 2);
if (ttask != null && ttask.TASK_EDITDATETIME.AddMinutes(3) < db.GetDate())
{
//堆垛机出口输送线任务3分钟未执行,//调用WMS接口申请移库任务,同时建议WMS将出库任务修改为移库任务。
//调用WMS接口申请移库
var moveTaskresult = Current.WmsInterface.I_WCS_GetMoveTask(new GetMoveTaskParam() { WMSTaskNum = outtask.TASK_WMSNO });
if (moveTaskresult.ResType == 0)
{
Log4netHelper.Logger_Error.ErrorFormat(moveTaskresult.ResMessage);
}
else if (moveTaskresult.ResType == 2)
{
//创建移库任务并执行
var moveTask = new WCS_TASK();
db.Insertable(moveTask).ExecuteCommand();
temptask = db.Queryable().First(v => v.TASK_WMSNO == moveTask.TASK_WMSNO);
break;
}
else if (moveTaskresult.ResType == 1)
{
temptask = outtask;
break;
}
}
}
}
}
}
}
}
return temptask;
}
internal virtual List QueryOutTask(List taskSet)
{
return taskSet.OrderByDescending(v => v.TASK_PRIORITY).OrderBy(v => v.TASK_EDITDATETIME).ToList();
}
private int _locInTaskAssignWareCell = 0;
///
/// 分配入库货位
///
internal void InTaskAssignWareCell()
{
if (Interlocked.Exchange(ref _locInTaskAssignWareCell, 1) == 0)
{
try
{
var taskSet = Current.TaskSet.Where(v => v.TASK_COMTYPE == 1 &&
v.TASK_SRMNO == SrmNo &&
v.TASK_WKSTATUS != 11 &&
SrmOutInInfoSet.Any(t => t.SRMOUTIN_CONVNO == v.TASK_POSIDCUR && t.SRMOUTIN_OUTINTYPE == "in"))
.OrderByDescending(v => v.TASK_PRIORITY).ToList();
foreach (var task in taskSet)
{
if (string.IsNullOrWhiteSpace(task.TASK_POSIDTO) || task.TASK_POSIDTO == SrmNo)
{
//入库任务分配货位
GetWareCell(task);
}
}
}
catch (Exception ex)
{
Log4netHelper.Logger_Error.ErrorFormat(ex.ToString());
}
finally
{
Interlocked.Exchange(ref _locInTaskAssignWareCell, 0);
}
}
}
public bool GetWareCell(WCS_TASK task)
{
string resultMsg = string.Empty;
//调度接口获取货位
var getWareCell = Current.WmsInterface.I_WCS_GetWareCell(new GetWareCellParam() { WMSTaskNum = task.TASK_WMSNO.ToString(), TunnelNum = task.TASK_SRMNO, PickUpEquipmentNo = task.TASK_POSIDNEXT });
if (getWareCell.ResType)
{
resultMsg = TryCachHelper.TryTranExecute((db) =>
{
//修改任务分配货位
db.Updateable(it => new WCS_TASK() { TASK_POSIDNEXT = getWareCell.CellNo, TASK_POSIDTO = getWareCell.CellNo, TASK_EDITUSERNO = "WCS", TASK_EDITDATETIME = DateTime.Now })
.Where(it => it.TASK_NO == task.TASK_NO)
.ExecuteCommand();
//添加修改明细
string msg = string.Format("任务[{0}]分配货位[{1}]成功。", task.TASK_NO, getWareCell.CellNo);
CommonData.AddWCS_TASK_DTL(db, task.TASK_NO, task.TASK_NO, task.TASK_POSIDCUR, task.TASK_POSIDNEXT, msg);
});
}
else
{
resultMsg = string.Format("任务[{0}]调用接口分配货位[{1}]失败,原因:{2}", task.TASK_NO, getWareCell.CellNo, getWareCell.ResMessage);
Log4netHelper.Logger_Error.ErrorFormat(resultMsg);
}
if (string.IsNullOrWhiteSpace(resultMsg))
{
task.TASK_POSIDNEXT = getWareCell.CellNo;
task.TASK_POSIDTO = getWareCell.CellNo;
return true;
}
else
{
return false;
}
}
#endregion;
}
}