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 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);
|
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)
|
{
|
//12.4出库改成调用WMS完成任务接口;WMS操控PDA托盘下架后,WCS任务状态才完成(避免小车继续跑)
|
if (modFinshTask.TaskType == TaskTypeEnum.In)
|
{
|
modFinshTask.Status = TaskStatusEnum.Complete;
|
modFinshTask.FinishDate = DateTime.Now;
|
_db.Updateable(modFinshTask).ExecuteCommand();
|
var taskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = modFinshTask.TaskNo,
|
PlcName = modDevice.Text,
|
InteractiveMsg = $"穿梭车反馈任务完成"
|
};
|
_db.Insertable(taskMonitor).ExecuteCommand();
|
//下发任务日志
|
HubUtil.PublicTask(modFinshTask.Adapt<WcsTaskOutput>());
|
HubUtil.PublicTaskMonitor(taskMonitor.Adapt<WcsTaskMonitorOutput>());
|
}
|
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();
|
|
if (dicTaskNo.ContainsKey(modDevice.Id.ToString()))
|
dicTaskNo.Remove(modDevice.Id.ToString());
|
dicTaskNo.Add(modDevice.Id.ToString(), valueTaskStr);
|
}
|
}
|
}
|
|
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 stationStart = ((int)valuex).ToString().PadLeft(2, '0');
|
var stationEnd = ((int)valuez).ToString().PadLeft(2, '0') + "01";
|
var listTask = _db.Queryable<WcsTask>().OrderBy(m => m.Levels, OrderByType.Asc).OrderBy(m => m.CreateTime)
|
.Where(s => s.Status <= TaskStatusEnum.Doing && s.Type == PLCTypeEnum.ShuttleCar
|
&& s.StartLocate.StartsWith(stationStart) && s.StartLocate.EndsWith(stationEnd)).ToList();
|
var modTask = listTask.FirstOrDefault();
|
//return;
|
if (modTask == null)
|
return;
|
if (modTask.StartLocate == modTask.EndLocate)
|
{
|
modTask.Status = TaskStatusEnum.Doing;
|
_db.Updateable(modTask).ExecuteCommand();
|
HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
|
return;
|
}
|
if (modTask.Status == TaskStatusEnum.Doing)
|
{
|
Thread.Sleep(3000);
|
return;
|
}
|
//先复位
|
var modRest = modDevice.listStation.FirstOrDefault(s => s.Text == "复位");
|
plcConn.SetDBValue(modRest.PosType, modRest.PlcPos, "1");
|
|
List<Result> listResult = new List<Result>();
|
//写入任务号Id的末4位,2个小车一起跑有极低概率重复
|
var modWriteTask = modDevice.listStation.FirstOrDefault(s => s.Text == "写入任务号");
|
listResult.Add(plcConn.SetDBValue(modWriteTask.PosType, modWriteTask.PlcPos, modTask.Id.ToString().Substring(modTask.Id.ToString().Length - 4)));
|
|
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"));
|
}
|
//写入起始位置取货
|
listResult.Add(plcConn.SetDBValue(modNodeX.PosType, posX++.ToString(), modTask.StartLocate.Substring(0, 2)));
|
listResult.Add(plcConn.SetDBValue(modNodeY.PosType, posY++.ToString(), modTask.StartLocate.Substring(2, 2)));
|
listResult.Add(plcConn.SetDBValue(modNodeZ.PosType, posZ++.ToString(), modTask.StartLocate.Substring(4, 2)));
|
listResult.Add(plcConn.SetDBValue(modNodeStatus.PosType, posStatus++.ToString(), "2"));
|
//写入目标位置放货
|
listResult.Add(plcConn.SetDBValue(modNodeX.PosType, posX++.ToString(), modTask.EndLocate.Substring(0, 2)));
|
listResult.Add(plcConn.SetDBValue(modNodeY.PosType, posY++.ToString(), modTask.EndLocate.Substring(2, 2)));
|
listResult.Add(plcConn.SetDBValue(modNodeZ.PosType, posZ++.ToString(), modTask.EndLocate.Substring(4, 2)));
|
listResult.Add(plcConn.SetDBValue(modNodeStatus.PosType, posStatus++.ToString(), "3"));
|
string endPos = "";
|
if (modTask.StartLocate.Substring(0, 2).ToInt() >= 14)
|
endPos = "01";
|
else
|
endPos = "21";
|
if (listTask.Count == 1 && modTask.EndLocate.Substring(2, 2) != endPos)
|
{
|
//如果后续没有任务,就让小车回到原位
|
listResult.Add(plcConn.SetDBValue(modNodeX.PosType, posX++.ToString(), modTask.EndLocate.Substring(0, 2)));
|
listResult.Add(plcConn.SetDBValue(modNodeY.PosType, posY++.ToString(), endPos));//todo:这里位置待定
|
listResult.Add(plcConn.SetDBValue(modNodeZ.PosType, posZ++.ToString(), modTask.EndLocate.Substring(4, 2)));
|
listResult.Add(plcConn.SetDBValue(modNodeStatus.PosType, posStatus++.ToString(), "3"));
|
}
|
//这里是把后面的坐标全写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)
|
{
|
modTask.Status = TaskStatusEnum.Doing;
|
_db.Updateable(modTask).ExecuteCommand();
|
var taskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
PlcName = modDevice.Text,
|
InteractiveMsg = $"向穿梭车下发任务{modTask.TaskNo}"
|
};
|
_db.Insertable(taskMonitor).ExecuteCommand();
|
//下发任务日志
|
HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
|
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.A2.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.A2.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)
|
{
|
if (AGVStatus)
|
{
|
return;
|
}
|
//这里找出来AGV待执行和正在执行的任务,如果有正在执行的任务就跳出,没有的话就按照优先级下发一个任务给AGV
|
var listTask = _db.Queryable<WcsTask>()
|
.Where(s => (s.Status == TaskStatusEnum.Doing || s.Status == TaskStatusEnum.Wait) && s.Type == PLCTypeEnum.AGV)
|
.OrderBy(s => s.Levels).ToList();
|
if (listTask.Count == 0)
|
return;
|
if (listTask.Any(s => s.Status == TaskStatusEnum.Doing))
|
{
|
//有任务执行中 暂不下发任务
|
return;
|
}
|
//WcsTask modTask = listTask.FirstOrDefault();
|
foreach (var modTask in listTask)
|
{
|
//入缓存区时,检验一下缓存区位置
|
if (modTask.EndLocate.Substring(0, 1) == "Z")
|
{
|
if (modTask.EndLocate.Substring(1, 1) == "5")
|
{
|
string end = AGVStorageUtil.GetPalletInStorage(modTask.TaskNo);
|
if (end.IsNullOrEmpty())
|
continue;
|
if (modTask.EndLocate != end)
|
{
|
modTask.EndLocate = end;
|
}
|
}
|
else
|
{
|
string end = AGVStorageUtil.GetProductInStorage(modTask.TaskNo);
|
if (end.IsNullOrEmpty())
|
continue;
|
if (modTask.EndLocate != end)
|
{
|
modTask.EndLocate = end;
|
}
|
}
|
}
|
//出缓存区时,检验一下缓存区位置
|
if (modTask.StartLocate.Substring(0, 1) == "Z")
|
{
|
if (modTask.StartLocate.Substring(1, 1) == "5")
|
{
|
string start = AGVStorageUtil.GetPalletOutStorage();
|
if (start.IsNullOrEmpty())
|
continue;
|
if (modTask.StartLocate != start)
|
{
|
modTask.StartLocate = start;
|
}
|
}
|
else
|
{
|
string start = AGVStorageUtil.GetProductOutStorage();
|
if (start.IsNullOrEmpty())
|
continue;
|
if (modTask.StartLocate != start)
|
{
|
modTask.StartLocate = start;
|
}
|
}
|
}
|
//把托盘拉到缓存位 先判断这里有没有
|
if (modTask.EndLocate.Substring(0, 1) == "C")
|
{
|
var bo = _sysConfigService.GetConfigValue<bool>("cache_" + modTask.EndLocate).Result;
|
if (bo)
|
continue;
|
}
|
//如果拉托盘去成品工位,先检查有没有缺托
|
if (modTask.StartLocate.Substring(0, 1) == "D" && modTask.EndLocate.Substring(0, 1) == "B")
|
{
|
if (listTask.Any(s => s.EndLocate.Substring(0, 1) == "D"))
|
continue;
|
}
|
if (modTask.EndLocate == AGVStaionEnum.F1.ToString())
|
{
|
if (_sysConfigService.GetConfigValue<bool>("cache_Materal").Result)
|
continue;
|
}
|
//if (modTask.StartLocate == AGVStaionEnum.F1.ToString())
|
//{
|
// if (!_sysConfigService.GetConfigValue<bool>("cache_Materal").Result)
|
// continue;
|
//}
|
if (modTask.StartLocate == AGVStaionEnum.D1.ToString())
|
{
|
var modPlc = PLCTaskAction.plcs.FirstOrDefault(s => s.Type == PLCTypeEnum.PalletMachine);
|
var modDevice2 = PLCTaskAction.plcDevices.FirstOrDefault(s => s.PlcId == modPlc.Id && s.Text == "拆托机");
|
var modConn = new PLCUtil(modPlc);
|
//是否缺托信号
|
var modPos = PLCTaskAction.plcPositions.FirstOrDefault(s => s.DeviceId == modDevice2.Id && s.Text == "允许取托");
|
var (result, value) = modConn.GetPlcDBValue(modPos.PosType, modDevice2.DbNumber, modPos.PlcPos);
|
if (result.IsSucceed)
|
{
|
if (value)
|
{
|
//如果未完成就判断下取托信号有没有写,完成就叫小车取托盘
|
modPos = PLCTaskAction.plcPositions.FirstOrDefault(s => s.DeviceId == modDevice2.Id && s.Text == "取托信号");
|
(result, value) = modConn.GetPlcDBValue(modPos.PosType, modDevice2.DbNumber, modPos.PlcPos);
|
//如果没写入取托信号,就写入
|
if (result.IsSucceed && !value)
|
{
|
result = modConn.SetPlcDBValue(modPos.PosType, modDevice2.DbNumber, modPos.PlcPos, "1");
|
WcsTaskMonitor modTaskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
PlcId = modDevice2.PlcId,
|
PlcName = modPos.PlcPos,
|
Status = TaskStatusEnum.Doing,
|
InteractiveMsg = $"向{modDevice2.Text}写入取托信号1,结果{result.IsSucceed}",
|
};
|
_db.Insertable(modTaskMonitor).ExecuteCommand();
|
HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>());
|
Thread.Sleep(5000);
|
}
|
break;
|
|
}
|
else
|
{
|
modPos = PLCTaskAction.plcPositions.FirstOrDefault(s => s.DeviceId == modDevice2.Id && s.Text == "准备完成");
|
(result, value) = modConn.GetPlcDBValue(modPos.PosType, modDevice2.DbNumber, modPos.PlcPos);
|
if (!value)
|
{
|
continue;
|
}
|
}
|
}
|
else
|
{
|
Console.WriteLine("连接拆托机信号失败");
|
continue;
|
}
|
}
|
if (modTask.EndLocate == AGVStaionEnum.A1.ToString())
|
{
|
if (_db.Queryable<WcsTask>().Where(s => s.Type == PLCTypeEnum.ConveyorLine && s.Status == TaskStatusEnum.Doing).Any())
|
continue;
|
}
|
|
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)
|
//{
|
|
//}
|
}
|
|
|
|
}
|