using Admin.NET.Core.Service;
|
using COSXML.Network;
|
using DocumentFormat.OpenXml.Bibliography;
|
using DocumentFormat.OpenXml.Drawing;
|
using DocumentFormat.OpenXml.Spreadsheet;
|
using Furion.Logging;
|
using IoTClient;
|
using NewLife.Reflection;
|
using WCS.Application.Entity;
|
using WCS.Application.Util;
|
|
namespace WCS.Application;
|
public static class PLCService
|
{
|
private static readonly object OLock = new object();
|
public static bool AGVStatus = false;
|
private static readonly ISqlSugarClient _db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId);
|
private static readonly WcsTaskService _taskService = App.GetService<WcsTaskService>();
|
private static readonly SysCacheService sysCacheService = App.GetRequiredService<SysCacheService>();
|
private static readonly SysConfigService _sysConfigService = App.GetRequiredService<SysConfigService>();
|
private static Dictionary<string, string> dicTaskNo = new Dictionary<string, string>();
|
public static void OnChangeEvent(object sender, EventArgs e)
|
{
|
try
|
{
|
var mod = sender as WcsDeviceDto;
|
//Console.WriteLine($"{mod.Text}值为" + mod.Value);
|
switch (mod.Type)
|
{
|
case PLCTypeEnum.ConveyorLine:
|
ConveyorLine(mod); // 托盘输送线
|
break;
|
case PLCTypeEnum.AGV:
|
AGV(mod); // AGV调度
|
break;
|
case PLCTypeEnum.ShuttleCar: //穿梭车
|
ShuttleCar(mod);
|
break;
|
case PLCTypeEnum.RobotPalletizer:
|
RobotPalletizer(mod);//码垛机器人
|
break;
|
case PLCTypeEnum.PalletMachine:
|
PalletMachine(mod);
|
break;
|
default:
|
break;
|
}
|
}
|
catch (Exception ex)
|
{
|
Log.Error(ex.Message, ex);
|
}
|
}
|
/// <summary>
|
/// 拆托机
|
/// </summary>
|
/// <param name="modDevice"></param>
|
private static void PalletMachine(WcsDeviceDto modDevice)
|
{
|
if (modDevice.Value)
|
{
|
//检测到缺托信号执行这里,如果没有取托任务的话就添加一个(储位-拆托机)
|
if (!_db.Queryable<WcsTask>()
|
.Where(s => s.Type == PLCTypeEnum.AGV && s.Status <= TaskStatusEnum.Doing &&
|
s.EndLocate == AGVStaionEnum.D1.ToString()).Any())
|
{
|
WcsTask modTask = new WcsTask()
|
{
|
TaskNo = _taskService.GetTaskCode(),
|
TaskType = TaskTypeEnum.Move,
|
Type = PLCTypeEnum.AGV,
|
StartLocate = AGVStorageUtil.GetPalletOutStorage(),
|
EndLocate = AGVStaionEnum.D1.ToString(),
|
PalletNo = "",
|
Status = TaskStatusEnum.Wait,
|
Levels = 3,
|
Origin = "WCS"
|
};
|
if (modTask.StartLocate.IsNullOrEmpty())
|
return;
|
_db.Insertable(modTask).ExecuteCommand();
|
HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
|
}
|
}
|
}
|
/// <summary>
|
/// 码垛机器人业务处理
|
/// </summary>
|
private static void RobotPalletizer(WcsDeviceDto modDevice)
|
{
|
var plcConn = modDevice.modbusUtil;
|
string station = "B" + modDevice.StationNum;
|
string value = Convert.ToString(modDevice.Value);
|
if (value == "1")
|
{
|
if (modDevice.Level == DeviceLevelEnum.DB)
|
{
|
//生产工位缺托盘信号,生成任务叫小车去拉空托盘
|
if (!_db.Queryable<WcsTask>().Where(s => s.Type == PLCTypeEnum.AGV && s.Status <= TaskStatusEnum.Doing
|
&& s.StartLocate == AGVStaionEnum.D1.ToString() && s.EndLocate == station.ToString()).Any())
|
{
|
WcsTask modTask = new WcsTask()
|
{
|
TaskNo = _taskService.GetTaskCode(),
|
TaskType = TaskTypeEnum.Move,
|
Type = PLCTypeEnum.AGV,
|
StartLocate = AGVStaionEnum.D1.ToString(),
|
EndLocate = station,
|
PalletNo = "",
|
Status = TaskStatusEnum.Wait,
|
Levels = 4,
|
Origin = "WCS"
|
};
|
_db.Insertable(modTask).ExecuteCommand();
|
HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
|
}
|
}
|
else if (modDevice.Level == DeviceLevelEnum.Station)
|
{
|
//如果读到信号通知AGV小车拉货(满跺)
|
var endLocate = "C" + modDevice.StationNum;
|
if (!_db.Queryable<WcsTask>().Where(s => s.Type == PLCTypeEnum.AGV && s.Status <= TaskStatusEnum.Doing && s.StartLocate == station.ToString()).Any())
|
{
|
WcsTask modTask = new WcsTask()
|
{
|
TaskNo = _taskService.GetTaskCode(),
|
TaskType = TaskTypeEnum.Move,
|
Type = PLCTypeEnum.AGV,
|
StartLocate = station.ToString(),
|
EndLocate = endLocate,
|
PalletNo = "",
|
Status = TaskStatusEnum.Wait,
|
Levels = 2,
|
Origin = "WCS"
|
};
|
_db.Insertable(modTask).ExecuteCommand();
|
HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
|
}
|
}
|
}
|
}
|
/// <summary>
|
/// 穿梭车业务处理
|
/// </summary>
|
/// <param name="modDevice"></param>
|
private static void ShuttleCar(WcsDeviceDto modDevice)
|
{
|
var plcConn = modDevice.modbusUtil;
|
switch (modDevice.Value.ToString())
|
{
|
case "0":
|
sysCacheService.HashAddOrUpdate("AlarmInfo_Car", plcConn.PlcIP, -1);
|
break;
|
case "1":
|
{
|
sysCacheService.HashAddOrUpdate("AlarmInfo_Car", plcConn.PlcIP, -1);
|
var modPosTaskStatus = modDevice.listStation.FirstOrDefault(s => s.Text == "任务状态");
|
var (resultTaskStatus, valueTaskStatus) = plcConn.GetDBValue(modPosTaskStatus.PosType, modPosTaskStatus.PlcPos);
|
//判断读取任务状态是否成功 并且任务状态是1 0:未空闲,1:空闲,2:异常 3:充电中
|
|
WcsCarTasks carTask2 = null;//null 新任务 not null 路径2任务
|
if (resultTaskStatus.IsSucceed && valueTaskStatus == 1)
|
{
|
var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "任务号");
|
var (resultTask, valueTask) = plcConn.GetDBValue(modPosTask.PosType, modPosTask.PlcPos);
|
//读取任务号
|
int valueTaskStr = Convert.ToInt32(valueTask);
|
//获取任务信息 根据 任务号、小车编号
|
var carTask = _db.Queryable<WcsCarTasks>().First(m=>m.IsDelete == false && m.Status == TaskStatusEnum.Doing && m.CarTaskNo == valueTaskStr && m.CarNo == modDevice.PlcIdIP);
|
if (carTask == null)
|
{
|
return;//没有找到任务
|
}
|
|
var modFinshTask = _db.Queryable<WcsTask>().First(s => s.Status == TaskStatusEnum.Doing && s.Type == PLCTypeEnum.ShuttleCar && s.TaskNo == carTask.TaskNo);
|
if (modFinshTask == null)
|
{
|
return;//没有查询到总任务
|
}
|
//获取路径2的任务 下发
|
carTask2 = _db.Queryable<WcsCarTasks>().Where(m => m.IsDelete == false && m.TaskNo == carTask.TaskNo && m.CarNo == modDevice.PlcIdIP && m.PreId.Contains(carTask.Id.ToString())).OrderBy(m=>m.CreateTime).First();
|
|
if (carTask != null && carTask.Status != TaskStatusEnum.Complete)
|
{
|
carTask.Status = TaskStatusEnum.Complete;
|
carTask.UpdateTime = DateTime.Now;
|
_db.Updateable(carTask).ExecuteCommand();
|
//添加任务明细
|
var taskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = carTask.TaskNo,
|
PlcName = modDevice.Text,
|
InteractiveMsg = $"穿梭车反馈任务完成"
|
};
|
_db.Insertable(taskMonitor).ExecuteCommand();
|
//下发任务日志
|
|
HubUtil.PublicTaskMonitor(taskMonitor.Adapt<WcsTaskMonitorOutput>());
|
}
|
//没有路径2的任务 变更总任务信息
|
if (carTask2 == null && modFinshTask != null && modFinshTask.Status != TaskStatusEnum.Complete)
|
{
|
modFinshTask.Status = TaskStatusEnum.Complete;
|
modFinshTask.FinishDate = DateTime.Now;
|
_db.Updateable(modFinshTask).ExecuteCommand();
|
|
//反馈WMS系统 任务完成
|
//HttpService httpService = new HttpService();
|
//var requestMode = new TaskRequestWMS()
|
//{
|
// TaskNo = modFinshTask.TaskNo,
|
// PalletNo = modFinshTask.PalletNo,
|
// TaskType = ((int)modFinshTask.TaskType).ToString(),
|
// TaskStatus = ((int)TaskStatusEnum.Complete).ToString()
|
//};
|
//var modResponseTask = httpService.RequestTask(requestMode).Result;
|
//modFinshTask.IsSuccess = TaskSuccessEnum.Success;
|
//_db.Updateable(modFinshTask).ExecuteCommand();
|
HubUtil.PublicTask(modFinshTask.Adapt<WcsTaskOutput>());
|
|
}
|
|
}
|
|
var modStationX = modDevice.listStation.FirstOrDefault(s => s.Text == "四向车位置(X)");
|
var (resultx, valuex) = plcConn.GetDBValue(modStationX.PosType, modStationX.PlcPos);
|
var modStationY = modDevice.listStation.FirstOrDefault(s => s.Text == "四向车位置(Y)");
|
var (resulty, valuey) = plcConn.GetDBValue(modStationY.PosType, modStationY.PlcPos);
|
var modStationZ = modDevice.listStation.FirstOrDefault(s => s.Text == "四向车位置(Z)");
|
var (resultz, valuez) = plcConn.GetDBValue(modStationZ.PosType, modStationZ.PlcPos);
|
|
// 获取任务信息
|
var modTask = _db.Queryable<WcsTask>().Where(s => s.Status <= TaskStatusEnum.Doing && s.Type == PLCTypeEnum.ShuttleCar).OrderBy(m => m.Levels, OrderByType.Asc).OrderBy(m => m.CreateTime).First();
|
|
//要下发路径2任务
|
if (carTask2 == null)
|
{
|
modTask = _db.Queryable<WcsTask>().First(s => s.IsDelete == false && s.TaskNo == carTask2.TaskNo && s.Status <= TaskStatusEnum.Doing && s.Type == PLCTypeEnum.ShuttleCar);
|
|
carTask2= _db.Queryable<WcsCarTasks>().Where(m => m.IsDelete == false && m.TaskNo == modTask.TaskNo && m.CarNo == modDevice.PlcIdIP).OrderBy(m => m.CreateTime).First();
|
}
|
|
//return;
|
if (modTask == null || carTask2 == null)
|
{
|
return;
|
}
|
|
if (carTask2.Status == TaskStatusEnum.Doing)
|
{
|
Thread.Sleep(3000);
|
return;
|
}
|
//判断当前任务是否还有前置任务未完成
|
var preStrs = carTask2.PreId.Split(';');
|
foreach (var preStr in preStrs)
|
{
|
if (string.IsNullOrWhiteSpace(preStr))
|
{
|
continue;
|
}
|
var preId = long.Parse(preStr);
|
var CarTaskPre = _db.Queryable<WcsCarTasks>().First(m => m.Id == preId);
|
if (CarTaskPre.Status <= TaskStatusEnum.Doing)
|
{
|
return;//前置任务未完成
|
}
|
}
|
//先复位
|
var modRest = modDevice.listStation.FirstOrDefault(s => s.Text == "复位");
|
plcConn.SetDBValue(modRest.PosType, modRest.PlcPos, "1");
|
|
List<Result> listResult = new List<Result>();
|
//获取小车任务号
|
var carTaskNo = FourWayCarUtil.GetTaskNo();
|
|
var modWriteTask = modDevice.listStation.FirstOrDefault(s => s.Text == "写入任务号");
|
listResult.Add(plcConn.SetDBValue(modWriteTask.PosType, modWriteTask.PlcPos, carTaskNo.ToString()));
|
|
var modNodeX = modDevice.listStation.FirstOrDefault(s => s.Text == "节点坐标X");
|
var modNodeY = modDevice.listStation.FirstOrDefault(s => s.Text == "节点坐标Y");
|
var modNodeZ = modDevice.listStation.FirstOrDefault(s => s.Text == "节点坐标Z");
|
var modNodeStatus = modDevice.listStation.FirstOrDefault(s => s.Text == "节点举升状态");
|
int posX = Convert.ToInt32(modNodeX.PlcPos);
|
int posY = Convert.ToInt32(modNodeY.PlcPos);
|
int posZ = Convert.ToInt32(modNodeZ.PlcPos);
|
int posStatus = Convert.ToInt32(modNodeStatus.PlcPos);
|
if (Convert.ToInt32(valuey) != Convert.ToInt32(modTask.StartLocate.Substring(2, 2)))
|
{
|
//写入小车当前位置
|
listResult.Add(plcConn.SetDBValue(modNodeX.PosType, posX++.ToString(), Convert.ToString(valuex)));
|
listResult.Add(plcConn.SetDBValue(modNodeY.PosType, posY++.ToString(), Convert.ToString(valuey)));
|
listResult.Add(plcConn.SetDBValue(modNodeZ.PosType, posZ++.ToString(), Convert.ToString(valuez)));
|
listResult.Add(plcConn.SetDBValue(modNodeStatus.PosType, posStatus++.ToString(), "3"));
|
}
|
//交互路径
|
var execuPath = carTask2.ExecutionPath.Split(';');
|
foreach (var ePath in execuPath)
|
{
|
if (string.IsNullOrWhiteSpace(ePath))
|
{
|
continue;
|
}
|
//写入交互位置
|
listResult.Add(plcConn.SetDBValue(modNodeX.PosType, posX++.ToString(), ePath.Substring(0, 2)));
|
listResult.Add(plcConn.SetDBValue(modNodeY.PosType, posY++.ToString(), ePath.Substring(2, 2)));
|
listResult.Add(plcConn.SetDBValue(modNodeZ.PosType, posZ++.ToString(), ePath.Substring(4, 2)));
|
listResult.Add(plcConn.SetDBValue(modNodeStatus.PosType, posStatus++.ToString(), ePath.Substring(5, 1)));
|
}
|
|
//这里是把后面的坐标全写0(为了防止上次任务坐标没被覆盖)
|
while (posX <= 43097)
|
{
|
listResult.Add(plcConn.SetDBValue(modNodeX.PosType, posX++.ToString(), "0"));
|
listResult.Add(plcConn.SetDBValue(modNodeY.PosType, posY++.ToString(), "0"));
|
listResult.Add(plcConn.SetDBValue(modNodeZ.PosType, posZ++.ToString(), "0"));
|
listResult.Add(plcConn.SetDBValue(modNodeStatus.PosType, posStatus++.ToString(), "0"));
|
}
|
if (listResult.All(s => s.IsSucceed))
|
{
|
var modStart = modDevice.listStation.FirstOrDefault(s => s.Text == "启动命令");
|
var result = plcConn.SetDBValue(modStart.PosType, modStart.PlcPos, "1");
|
if (result.IsSucceed)
|
{
|
carTask2.Status = TaskStatusEnum.Doing;
|
carTask2.CarTaskNo = carTaskNo;
|
_db.Updateable(carTask2).ExecuteCommand();
|
var taskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = carTask2.TaskNo,
|
PlcName = modDevice.Text,
|
InteractiveMsg = $"向穿梭车下发任务{carTask2.TaskNo}"
|
};
|
_db.Insertable(taskMonitor).ExecuteCommand();
|
//下发任务日志
|
HubUtil.PublicTaskMonitor(taskMonitor.Adapt<WcsTaskMonitorOutput>());
|
}
|
}
|
}
|
break;
|
case "2":
|
{
|
//小车状态异常
|
var modPosTaskStatus = modDevice.listStation.FirstOrDefault(s => s.Text == "任务状态");
|
var (resultTaskStatus, valueTaskStatus) = plcConn.GetDBValue(modPosTaskStatus.PosType, modPosTaskStatus.PlcPos);
|
|
if (resultTaskStatus.IsSucceed && valueTaskStatus == 1)
|
{
|
var modPosTask = modDevice.listStation.FirstOrDefault(s => s.Text == "任务号");
|
var (resultTask, valueTask) = plcConn.GetDBValue(modPosTask.PosType, modPosTask.PlcPos);
|
string valueTaskStr = Convert.ToString(valueTask);
|
string strNo = "";
|
var boNo = dicTaskNo.TryGetValue(modDevice.Id.ToString(), out strNo);
|
if (valueTaskStr != "0" && strNo != valueTaskStr)
|
{
|
var modFinshTask = _db.Queryable<WcsTask>().First(s => s.Status == TaskStatusEnum.Doing && s.Type == PLCTypeEnum.ShuttleCar && s.Id.ToString().EndsWith(valueTaskStr));
|
if (modFinshTask != null && modFinshTask.Status != TaskStatusEnum.Complete)
|
{
|
HttpService httpService = new HttpService();
|
var requestMode = new TaskRequestWMS()
|
{
|
TaskNo = modFinshTask.TaskNo,
|
PalletNo = modFinshTask.PalletNo,
|
TaskType = ((int)modFinshTask.TaskType).ToString(),
|
TaskStatus = ((int)TaskStatusEnum.Complete).ToString()
|
};
|
var modResponseTask = httpService.RequestTask(requestMode).Result;
|
modFinshTask.IsSuccess = TaskSuccessEnum.Success;
|
_db.Updateable(modFinshTask).ExecuteCommand();
|
//下发任务日志
|
//HubUtil.PublicTask(modFinshTask.Adapt<WcsTaskOutput>());
|
//HubUtil.PublicTaskMonitor(taskMonitor.Adapt<WcsTaskMonitorOutput>());
|
|
if (dicTaskNo.ContainsKey(modDevice.Id.ToString()))
|
dicTaskNo.Remove(modDevice.Id.ToString());
|
dicTaskNo.Add(modDevice.Id.ToString(), valueTaskStr);
|
}
|
}
|
|
}
|
|
Console.WriteLine($"穿梭车{modDevice.PlcIdIP}异常");
|
var modPosError = modDevice.listStation.FirstOrDefault(s => s.Text == "错误码");
|
var (result, valueError) = plcConn.GetDBValue(modPosError.PosType, modPosError.PlcPos);
|
if (result.IsSucceed)
|
{
|
sysCacheService.HashAddOrUpdate("AlarmInfo_Car", plcConn.PlcIP, Convert.ToInt32(valueError));
|
}
|
}
|
break;
|
default:
|
break;
|
}
|
}
|
/// <summary>
|
/// 输送线业务处理
|
/// </summary>
|
/// <param name="modDevice"></param>
|
private static void ConveyorLine(WcsDeviceDto modDevice)
|
{
|
var plcConn = modDevice.PLCUtil;
|
|
switch (modDevice.Value.ToString())
|
{
|
case "20":
|
{
|
//小车请求开卷帘门 这里改成海康直接调用模块 这里不需要了
|
string Devicelndex = "";
|
if (modDevice.Text == "2号卷帘门")
|
Devicelndex = "222";
|
else if (modDevice.Text == "3号卷帘门")
|
Devicelndex = "111";
|
var modCallBack = sysCacheService.Get<AGVApplyLockInput>("OpenDoor" + Devicelndex);
|
if (modCallBack != null)
|
{
|
var modAgvDevice = PLCTaskAction.plcs.FirstOrDefault(s => s.Text == "AGV");
|
AgvNotifyInput input = new AgvNotifyInput()
|
{
|
ActionStatus = "1",
|
DeviceIndex = Devicelndex,
|
UUID = modCallBack.UUID,
|
};
|
var response = new HttpService().NotifyExcuteResultInfo(input).Result;
|
if (response.code == 0)
|
{
|
sysCacheService.Remove("OpenDoor" + Devicelndex);
|
}
|
}
|
}
|
break;
|
case "100":
|
{
|
//工位对应 1=A 4=B 10=C
|
string stationNum = "";
|
if (modDevice.StationNum == "1" || modDevice.StationNum == "4")
|
{
|
stationNum = "10";
|
//判断有没有小车到C口的任务,如果有就写120
|
var countTask = _db.Queryable<WcsTask>().Where(s => s.Status == TaskStatusEnum.Doing && s.Type == PLCTypeEnum.AGV && s.EndLocate == "A1").Count();
|
if (countTask != 0)
|
{
|
var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "120");
|
Log.Information($"向plc{modDevice.PlcIdIP}写入120,结果:{ret.ToJson()}");
|
return;
|
}
|
}
|
string strPalletNo = "";
|
if (modDevice.StationNum == "10" || modDevice.StationNum == "4")
|
{
|
var modPosPallet = modDevice.listStation.First(s => s.Text == "托盘条码");
|
//todo:这里读码器老读不到条码信息 先写死 读码器问题解决了可以注释掉
|
//plcConn.SetPlcDBValue(modPosPallet.PosType, modDevice.DbNumber, modPosPallet.PlcPos, "T2400001");
|
var (res, palletNo) = plcConn.GetPlcDBValue(modPosPallet.PosType, modDevice.DbNumber, modPosPallet.PlcPos, modPosPallet.StringLength);
|
if (!res.IsSucceed || palletNo == "")
|
{
|
var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "120");
|
Log.Information($"向plc{modDevice.PlcIdIP}写入120,结果:{ret.ToJson()}");
|
return;
|
}
|
strPalletNo = Convert.ToString(palletNo);
|
}
|
if (modDevice.StationNum == "10")
|
{
|
if (strPalletNo.Substring(0, 1) == "T")
|
stationNum = "4";
|
else
|
stationNum = "1";
|
}
|
|
// 写入托盘输送线码垛工位
|
var listResult = new List<Result>();
|
// 写入托盘输送线码垛工位 目的工位、任务号,写入交互流程组托成功
|
var posModel = modDevice.listStation.First(m => m.Text == "起始工位");
|
listResult.Add(plcConn.SetPlcDBValue(posModel.PosType, modDevice.DbNumber, posModel.PlcPos, modDevice.StationNum));
|
var posModel2 = modDevice.listStation.First(m => m.Text == "目标工位");
|
listResult.Add(plcConn.SetPlcDBValue(posModel2.PosType, modDevice.DbNumber, posModel2.PlcPos, stationNum));
|
string taskNo = _taskService.GetTaskCode("WCS");
|
var modPosTask = modDevice.listStation.First(s => s.Text == "任务号");
|
listResult.Add(plcConn.SetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, taskNo));
|
|
if (listResult.All(s => s.IsSucceed))
|
{
|
var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "130");
|
Log.Information($"向plc{modDevice.PlcIdIP}写入130,结果:{ret.ToJson()}");
|
if (ret.IsSucceed)
|
{
|
AddWcsTaskInput modTask = new AddWcsTaskInput()
|
{
|
TaskNo = taskNo,
|
TaskType = TaskTypeEnum.In,
|
PalletNo = strPalletNo,
|
Status = TaskStatusEnum.Doing,
|
IsSuccess = TaskSuccessEnum.Fail,
|
StartLocate = modDevice.StationNum,
|
EndLocate = stationNum,
|
Type = PLCTypeEnum.ConveyorLine,
|
};
|
_taskService.Add(modTask);
|
WcsTaskMonitor modTaskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
PlcId = modDevice.PlcId,
|
PlcName = modDevice.Text,
|
StartLocat = modDevice.StationNum,
|
EndLocat = stationNum,
|
Status = TaskStatusEnum.Doing,
|
InteractiveMsg = $"向{modDevice.Text}写入指令130,结果{ret.IsSucceed}",
|
};
|
_db.Insertable(modTaskMonitor).ExecuteCommand();
|
|
//下发任务日志
|
HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
|
HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>());
|
}
|
}
|
}
|
break;
|
case "140":
|
{
|
var modPosTask = modDevice.listStation.First(m => m.Text == "任务号");
|
var (result, taskNo) = plcConn.GetPlcDBValue(modPosTask.PosType, modDevice.DbNumber, modPosTask.PlcPos, modPosTask.StringLength);
|
var modPosPallet = modDevice.listStation.First(m => m.Text == "托盘条码");
|
var (res, palletNo) = plcConn.GetPlcDBValue(modPosPallet.PosType, modDevice.DbNumber, modPosPallet.PlcPos, modPosPallet.StringLength);
|
WcsTaskMonitor modTaskMonitor = new WcsTaskMonitor();
|
WcsTask modTask = new WcsTask();
|
if (!result.IsSucceed)
|
{
|
Log.Error($"{plcConn.PlcIP}读取任务号失败");
|
return;
|
}
|
if (modDevice.StationNum == "10")
|
{
|
var posModel = modDevice.listStation.First(m => m.Text == "起始工位");
|
var (resultS, station) = plcConn.GetPlcDBValue(posModel.PosType, modDevice.DbNumber, posModel.PlcPos);
|
if (resultS.IsSucceed)
|
{
|
if (station == 1)
|
{
|
WcsTask modInsertTask = new WcsTask()
|
{
|
TaskNo = _taskService.GetTaskCode(),
|
TaskType = TaskTypeEnum.Move,
|
Type = PLCTypeEnum.AGV,
|
StartLocate = AGVStaionEnum.A1.ToString(),
|
EndLocate = AGVStaionEnum.F1.ToString(),
|
PalletNo = modTask.PalletNo,
|
Status = TaskStatusEnum.Wait,
|
Levels = 5,
|
Origin = "WCS"
|
};
|
_db.Insertable(modInsertTask).ExecuteCommand();
|
HubUtil.PublicTask(modInsertTask.Adapt<WcsTaskOutput>());
|
}
|
else if (station == 4)
|
{
|
WcsTask modInsertTask = new WcsTask()
|
{
|
TaskNo = _taskService.GetTaskCode(),
|
TaskType = TaskTypeEnum.Move,
|
Type = PLCTypeEnum.AGV,
|
StartLocate = AGVStaionEnum.A1.ToString(),
|
EndLocate = AGVStorageUtil.GetPalletInStorage(),
|
PalletNo = modTask.PalletNo,
|
Status = TaskStatusEnum.Wait,
|
Levels = 5,
|
Origin = "WCS"
|
};
|
_db.Insertable(modInsertTask).ExecuteCommand();
|
HubUtil.PublicTask(modInsertTask.Adapt<WcsTaskOutput>());
|
}
|
}
|
else
|
{
|
Log.Error("获取起始工位失败,失败原因" + resultS.Err);
|
return;
|
}
|
}
|
var ledText = "";
|
if (modDevice.StationNum == "4")
|
{
|
//todo:led
|
ledText += "任务类型:入库\n\n";
|
ledText += $"任务号:{taskNo}\n";
|
ledText += $"托盘号:{palletNo}\n\n";
|
//ledText += $"起始位:10\n";
|
//ledText += $"目标位:4";
|
LedDisplay(modDevice.LedIP, ledText);
|
}
|
var ret = plcConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "150");
|
Log.Information($"向plc{modDevice.PlcIdIP}写入150,结果:{ret.ToJson()}");
|
if (ret.IsSucceed)
|
{
|
string strTaskNo = taskNo;
|
modTask = _db.Queryable<WcsTask>().First(s => s.TaskNo == strTaskNo);
|
if (modTask != null)
|
{
|
modTaskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
PlcId = modDevice.PlcId,
|
PlcName = modDevice.Text,
|
StartLocat = modTask.StationNum,
|
EndLocat = modTask.EndLocate,
|
InteractiveMsg = $"向{modDevice.Text}写入指令150,结果{ret.IsSucceed}",
|
};
|
modTaskMonitor.Status = TaskStatusEnum.Complete;
|
_db.Insertable(modTaskMonitor).ExecuteCommand();
|
modTask.FinishDate = DateTime.Now;
|
modTask.Status = TaskStatusEnum.Complete;
|
_db.Updateable(modTask).ExecuteCommand();
|
|
//下发任务日志
|
HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
|
HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>());
|
}
|
}
|
}
|
break;
|
|
default: break;
|
}
|
|
}
|
|
/// <summary>
|
/// AGV业务处理
|
/// </summary>
|
/// <param name="modDevice"></param>
|
private static void AGV(WcsDeviceDto modDevice)
|
{
|
|
//这里找出来AGV待执行的任务、按照优先级下发一个任务给AGV
|
var listTask = _db.Queryable<WcsTask>().Where(s => (s.Status == TaskStatusEnum.Wait || s.Status == TaskStatusEnum.Doing) && s.Type == PLCTypeEnum.AGV).OrderBy(s => s.Levels).ToList();
|
if (listTask.Count == 0)
|
{
|
return;
|
}
|
|
foreach (var modTask in listTask)
|
{
|
if (_db.Queryable<WcsTask>().Any(s => s.EndLocate == modTask.EndLocate && s.IsDelete == false && s.Status == TaskStatusEnum.Doing && s.Type == PLCTypeEnum.AGV ))
|
{
|
continue; // 有目的位置一致且正在执行的任务
|
}
|
|
//下发AGV任务
|
AgvTaskInput input = new AgvTaskInput()
|
{
|
ReqCode = modTask.Id.ToString(),
|
TaskCode = modTask.TaskNo,
|
CtnrCode = modTask.PalletNo,
|
PositionCodePath = new List<PositionCodePathItem>()
|
{
|
new PositionCodePathItem(){ PositionCode = modTask.StartLocate },
|
new PositionCodePathItem(){ PositionCode = modTask.EndLocate }
|
}
|
};
|
input.TaskTyp = "1" + modTask.StartLocate.Substring(0, 1) + modTask.EndLocate.Substring(0, 1);
|
var response = new HttpService().GenAgvSchedulingTask(input).Result;
|
if (response.code == "0")
|
{
|
AGVStatus = true;
|
modTask.Status = TaskStatusEnum.Doing;
|
_db.Updateable(modTask).ExecuteCommand();
|
var modTaskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
PlcId = modDevice.modPlc.Id,
|
PlcName = modDevice.modPlc.IP,
|
InteractiveMsg = "向AGV小车下发任务"
|
};
|
_db.Insertable(modTaskMonitor).ExecuteCommand();
|
|
//下发任务日志
|
HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
|
HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>());
|
}
|
Console.WriteLine(response.ToJson());
|
return;
|
}
|
Thread.Sleep(3000);
|
}
|
|
/// <summary>
|
/// Led屏展示信息
|
/// </summary>
|
/// <param name="ip">地址</param>
|
/// <param name="top">上方区域</param>
|
/// <param name="content">中间区域</param>
|
/// <param name="foot">底部区域</param>
|
private static void LedDisplay(string ip, string top, string content, string foot)
|
{
|
try
|
{
|
LedDll Led = new LedDll();
|
Led.LEDstr(ip, top, content, foot);
|
}
|
catch (Exception ex)
|
{
|
Log.Error(ex.Message);
|
}
|
}
|
/// <summary>
|
/// LED信息展示
|
/// </summary>
|
/// <param name="ip"></param>
|
/// <param name="text"></param>
|
private static void LedDisplay(string ip, string text)
|
{
|
try
|
{
|
LedDll Led = new LedDll();
|
Led.ConsoleLeds(ip, text);
|
// 设置实例
|
//Led.ConsoleLeds("10.18.51.238", $"任务类型:{TaskTypeEnum.Move.GetDescription()}\n\n任务号:TK2024102100001\n托盘号:LN000145\n\n起始位:033\n目标位:R01-02010102");
|
}
|
catch (Exception ex)
|
{
|
Log.Error(ex.Message);
|
}
|
}
|
|
|
private static void Test(WcsDeviceDto modDevice)
|
{
|
//卷帘门2申请打开
|
//var result = modDevice.PLCUtil.SetPlcDBValue(PLCDataTypeEnum.Short, "DB1000", "1152", "10");
|
//卷帘门2申请关闭
|
//var result = modDevice.PLCUtil.SetPlcDBValue(PLCDataTypeEnum.Short, "DB1000", "1152", "30");
|
|
//卷帘门3申请打开
|
//var result = modDevice.PLCUtil.SetPlcDBValue(PLCDataTypeEnum.Short, "DB1000", "1154", "10");
|
//卷帘门3申请关闭
|
//var result = modDevice.PLCUtil.SetPlcDBValue(PLCDataTypeEnum.Short, "DB1000", "1154", "30");
|
|
//C口AGV放托盘完成申请入库
|
var result = modDevice.PLCUtil.SetPlcDBValue(PLCDataTypeEnum.Short, "DB1000", "1156", "100");
|
|
////写死测试读string
|
//var (res, val) = modDevice.PLCUtil.GetPlcDBValue(PLCDataTypeEnum.String, "DB100", "64");
|
//Console.WriteLine("DB100.64----" + val);
|
////测试批量读取
|
//Dictionary<string, PLCDataTypeEnum> listaddress = new Dictionary<string, PLCDataTypeEnum>();
|
//foreach (var modStation in modDevice.listStation)
|
//{
|
// listaddress.Add(modStation.PlcPos, modStation.PosType);
|
//}
|
//var result = modDevice.PLCUtil.GetPlcBatchDBValue(listaddress);
|
//if (result.Value.Count > 0)
|
//{
|
// foreach (var value in result.Value)
|
// {
|
// Console.WriteLine("地址" + value.Key + "----值" + value, value);
|
// }
|
//}
|
//if (!result.IsSucceed)
|
//{
|
// foreach (var err in result.ErrList)
|
// {
|
// Console.WriteLine(err);
|
// }
|
// if (result.Value.Count > 0)//有错误的也有成功的
|
// {
|
|
// }
|
//}
|
//if (modDevice.Value == 820)
|
//{
|
// //测试写入830
|
// //var result = mod.PLCUtil.SetPlcDBValue(mod.PosType.Value, mod.DbNumber, mod.PlcPos, "830");
|
// ////写入是否成功
|
// //if (result.IsSucceed)
|
// //{
|
|
// //}
|
//}
|
//else if (modDevice.Value == 840)
|
//{
|
|
//}
|
//else if (modDevice.Value == 860)
|
//{
|
|
//}
|
}
|
|
|
|
}
|