using DocumentFormat.OpenXml.Presentation;
|
using Elastic.Clients.Elasticsearch;
|
using Furion.DatabaseAccessor;
|
using Furion.Logging;
|
using NewLife.Serialization;
|
using Newtonsoft.Json;
|
using System;
|
using System.Diagnostics.CodeAnalysis;
|
using System.Linq;
|
using System.Text;
|
using WCS.Application.Entity;
|
using Microsoft.AspNetCore.Mvc;
|
using Admin.NET.Core.Service;
|
using DocumentFormat.OpenXml.Bibliography;
|
using AngleSharp.Common;
|
using AngleSharp.Text;
|
using Newtonsoft.Json.Linq;
|
using SqlSugar;
|
using NewLife.Reflection;
|
|
namespace WCS.Application;
|
|
/// <summary>
|
/// 示例开放接口
|
/// </summary>
|
[ApiDescriptionSettings("开放接口", Name = "OpenApi", Order = 100)]
|
//[Authorize(AuthenticationSchemes = SignatureAuthenticationDefaults.AuthenticationScheme)]
|
[AllowAnonymous]
|
public class OpenApi : IDynamicApiController
|
{
|
private static readonly ISqlSugarClient _db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId);
|
|
private readonly UserManager _userManager;
|
private readonly SysCacheService _sysCacheService;
|
private readonly SysConfigService _sysConfigService;
|
private readonly WcsTaskService _taskService;
|
public OpenApi(UserManager userManager, SysCacheService sysCacheService, SysConfigService sysConfigService, WcsTaskService taskService)
|
{
|
_userManager = userManager;
|
_sysCacheService = sysCacheService;
|
_sysConfigService = sysConfigService;
|
_taskService = taskService;
|
}
|
|
// <summary>
|
/// WCS接受WMS下发的任务(多
|
/// 条任务)
|
/// <param name="models">任务信息</param>
|
/// <returns>反馈信息</returns>
|
/// </summary>
|
[AllowAnonymous]
|
[UnitOfWork]
|
public async Task AddWcsTasks(List<ResponseTasksModel> modelList)
|
{
|
var listTaskNo = modelList.Select(s => s.TaskNo).ToList();
|
// 验证任务是否已存在
|
var taskInfo = await _db.Queryable<WcsTask>().CountAsync(w => listTaskNo.Contains(w.TaskNo));
|
if (taskInfo > 0)
|
{
|
throw Oops.Bah("任务已存在!");
|
}
|
var listTask = new List<WcsTask>();
|
foreach (var models in modelList)
|
{
|
if (models.TaskType == "0")
|
{
|
models.Order = 1;
|
}
|
else
|
{
|
models.Order = 2;
|
}
|
//新增任务
|
var taskAdd = new WcsTask()
|
{
|
TaskNo = models.TaskNo,
|
TaskType = (TaskTypeEnum)Convert.ToInt32(models.TaskType),
|
Type = models.Type,
|
Status = TaskStatusEnum.Wait,
|
Levels = 999,
|
Origin = "WMS",
|
StartRoadway = models.StartRoadway,
|
StartLocate = models.StartLocate,
|
EndLocate = models.EndLocate,
|
EndRoadway = models.EndRoadway,
|
PalletNo = models.PalletNo,
|
};
|
listTask.Add(taskAdd);
|
}
|
await _db.Insertable(listTask).ExecuteCommandAsync();
|
}
|
/// <summary>
|
/// WCS接受WMS下发的任务(单条任务)
|
/// </summary>
|
/// <param name="models">任务信息</param>
|
/// <returns>反馈信息</returns>
|
[AllowAnonymous]
|
public async Task AddWcsTask(ResponseTasksModel models)
|
{
|
// 验证任务是否已存在
|
var taskInfo = await _db.Queryable<WcsTask>().FirstAsync(w => w.TaskNo == models.TaskNo);
|
if (taskInfo != null)
|
{
|
throw Oops.Bah("任务:" + models.TaskNo + ";已存在!");
|
}
|
if (models.TaskType == "0")
|
{
|
models.Order = 1;
|
}
|
else
|
{
|
models.Order = 2;
|
}
|
//新增任务
|
var taskAdd = new WcsTask()
|
{
|
TaskNo = models.TaskNo,
|
TaskType = TaskTypeEnum.Out,
|
Status = TaskStatusEnum.Wait,
|
Levels = 999,
|
Origin = "WMS",
|
StartRoadway = models.StartRoadway,
|
StartLocate = models.StartLocate,
|
EndLocate = models.EndLocate,
|
EndRoadway = models.EndRoadway,
|
PalletNo = models.PalletNo,
|
};
|
await _db.Insertable(taskAdd).ExecuteCommandAsync();
|
}
|
|
/// <summary>
|
/// WCS接收WMS下发的入库单任务
|
/// </summary>
|
/// <param name="models"></param>
|
/// <returns></returns>
|
[HttpPost]
|
[AllowAnonymous]
|
public async Task AddOrderTask(List<ResponseOrderTaskModel> models)
|
{
|
foreach (var item in models)
|
{
|
// 验证任务是否已存在
|
//var taskInfo = _db.Queryable<WcsOderTask>().First(w => w.OrderNo == item.OrderNo && w.SkuNo == item.SkuNo && w.LotNo == item.LotNo);
|
//if (taskInfo == null)
|
//{
|
var orderAdd = new WcsOderTask()
|
{
|
OrderNo = item.OrderNo,
|
TaskNo = "",
|
LotNo = item.LotNo,
|
SkuNo = item.SkuNo,
|
SkuName = item.SkuName,
|
BoxType = item.BoxType,
|
Qty = item.Qty,
|
TaskType = (TaskTypeEnum)item.TaskType,
|
};
|
await _db.Insertable(orderAdd).ExecuteCommandAsync();
|
//}
|
}
|
}
|
|
|
/// <summary>
|
/// WCS接收赋码系统推送的箱码信息
|
/// </summary>
|
/// <param name="models">箱码信息</param>
|
/// <returns>反馈信息</returns>
|
[HttpPost]
|
[AllowAnonymous]
|
public async Task AddBoxInfo(FumaBoxInfoInput models)
|
{
|
if (models.Origin != "赋码")
|
{
|
throw Oops.Bah("来源未识别");
|
}
|
var num = await _db.Queryable<WcsBoxInfo>().Where(m => m.BoxNo == models.BoxNo).ToListAsync();
|
var type = "add";
|
if (num.Count > 0)
|
{
|
//WCS存在箱码信息,更新箱码信息(需判断箱码是否已组盘入库)
|
var num2 = num.Count(m => m.Status != "0" || !string.IsNullOrWhiteSpace(m.PalletNo));
|
if (num2 > 0)
|
{
|
throw Oops.Bah("该箱已入盘入库,不可更新信息");
|
}
|
type = "edit";
|
}
|
|
if (models.DelistList.Count == 0)
|
{
|
throw Oops.Bah("盒码集合不能为空");
|
}
|
|
var listBox = new List<WcsBoxInfo>();
|
foreach (var item in models.DelistList)
|
{
|
var level = "3";
|
if (string.IsNullOrWhiteSpace(item.BoxNo2))
|
{
|
level = "2";
|
}
|
if (item.DelistList2.Count == 0)
|
{
|
throw Oops.Bah("值码集合不能为空");
|
}
|
//二级码
|
foreach (var item2 in item.DelistList2)
|
{
|
if (string.IsNullOrWhiteSpace(models.ProductionTime) || string.IsNullOrWhiteSpace(models.ExpirationTime))
|
{
|
throw Oops.Bah("生产日期或失效日期不能为空");
|
}
|
DateTime proTime;
|
DateTime expTime;
|
var isValid = DateTime.TryParse(models.ProductionTime, out proTime);
|
var isValid2 = DateTime.TryParse(models.ExpirationTime, out expTime);
|
if (!isValid || !isValid2)
|
{
|
throw Oops.Bah("生产日期或失效日期格式错误");
|
};
|
|
var boxAdd = new WcsBoxInfo()
|
{
|
BoxNo = models.BoxNo,
|
//OrderNo = models.OrderNo,
|
SkuNo = models.SkuNo,
|
SkuName = models.SkuName,
|
Standard = models.Standard,
|
LotNo = models.LotNo,
|
Qty = item2.Qty,
|
FullQty = models.FullQty,
|
//SupplierLot = models.SupplierLot,
|
InsPectMark = models.InsPectMark,
|
BitBoxMark = models.BitBoxMark,
|
//InspectStatus = models.InspectStatus,
|
ProductionTime = proTime,
|
ExpirationTime = expTime,
|
StoreTime = DateTime.Parse(models.StoreTime),
|
EndLotFlag = string.IsNullOrWhiteSpace(models.EndBatchMark) ? "0" : models.EndBatchMark,
|
|
BoxNo2 = item.BoxNo2,
|
BoxNo3 = item2.BoxNo3,
|
QtyCount = item2.QtyCount,
|
QtyOrd = item2.QtyOrd,
|
|
Status = "0",
|
Level = level,
|
};
|
listBox.Add(boxAdd);
|
}
|
|
}
|
await _db.Insertable(listBox).ExecuteCommandAsync();
|
if (type == "edit")
|
{
|
await _db.Deleteable(num).ExecuteCommandAsync();
|
}
|
}
|
/// <summary>
|
/// AGV小车申请开门
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
[HttpPost]
|
[NonUnify]
|
public async Task<dynamic> AgvApplyLock(AGVApplyLockInput input)
|
{
|
AGVCallBackResponse result = new AGVCallBackResponse()
|
{
|
//ReqCode = input.ReqCode,
|
Message = "成功",
|
Code = "0"
|
};
|
var modPlc = PLCTaskAction.plcs.FirstOrDefault(s => s.Type == PLCTypeEnum.ConveyorLine);
|
if (modPlc == null)
|
{
|
result.Code = "1";
|
result.Message = "找不到PLC信息";
|
}
|
else
|
{
|
var modUtil = new PLCUtil(modPlc);
|
string text = "";
|
if (input.DeviceIndex == "111")
|
{
|
text = "3号卷帘门";
|
}
|
else if (input.DeviceIndex == "222")
|
{
|
text = "2号卷帘门";
|
}
|
else
|
{
|
result.Code = "1";
|
result.Message = "卷帘门编号错误";
|
return result;
|
}
|
var modDevice = await _db.Queryable<WcsDevice>().FirstAsync(s => s.Text == text);
|
if (modDevice == null)
|
{
|
result.Code = "1";
|
result.Message = "找不到卷帘门设备信息";
|
}
|
else
|
{
|
if (input.ActionTask == "applyLock")
|
{
|
var (plcResult, value) = modUtil.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.PlcPos);
|
if (plcResult.IsSucceed)
|
{
|
//写入10申请开门,等待写入20返回结果让小车通过
|
plcResult = modUtil.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "10");
|
if (!plcResult.IsSucceed)
|
{
|
result.Code = "1";
|
result.Message = "打开卷帘门写入值失败";
|
}
|
else
|
{
|
_sysCacheService.Set("OpenDoor" + input.DeviceIndex, input);
|
}
|
}
|
else
|
{
|
result.Code = "1";
|
result.Message = "获取卷帘门状态失败";
|
}
|
}
|
else
|
{
|
var (plcResult, value) = modUtil.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.PlcPos);
|
if (plcResult.IsSucceed && value != 0)
|
{
|
plcResult = modUtil.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "30");
|
if (!plcResult.IsSucceed)
|
{
|
result.Code = "1";
|
result.Message = "关闭卷帘门写入值失败";
|
}
|
}
|
else
|
{
|
result.Code = "1";
|
result.Message = "获取卷帘门状态失败";
|
}
|
|
}
|
}
|
}
|
return result;
|
}
|
/// <summary>
|
/// AGV小车回调
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
[HttpPost]
|
[NonUnify]
|
[UnitOfWork]
|
public async Task<dynamic> agvCallback(AGVCallBackInput input)
|
{
|
AGVCallBackResponse result = new AGVCallBackResponse()
|
{
|
ReqCode = input.ReqCode,
|
Message = "成功",
|
Code = "0"
|
};
|
if (input.TaskCode.Substring(0, 3) != "WCS" && input.TaskCode.Substring(0, 2) != "TK")
|
return result;
|
PLCUtil modUtil = null;
|
try
|
{
|
var modTask = await _db.Queryable<WcsTask>().FirstAsync(s => s.TaskNo == input.TaskCode);
|
if (modTask != null)
|
{
|
switch (input.Method)
|
{
|
case "end"://任务完成
|
{
|
PLCService.AGVStatus = false;
|
//把成品货物拉到缓存工位后,下一个任务把托盘拉去提升机或者缓存区(优先级低一点)
|
if (modTask.EndLocate == AGVStaionEnum.C1.ToString() || modTask.EndLocate == AGVStaionEnum.C2.ToString())
|
{
|
var strEndLocate = "";
|
Enum.TryParse(await _sysConfigService.GetConfigValue<string>("workshop_Trend"), out WorkshopEnum workshop);
|
if (workshop == WorkshopEnum.Storage)
|
strEndLocate = AGVStaionEnum.A1.ToString();
|
else
|
strEndLocate = AGVStorageUtil.GetProductInStorage();
|
WcsTask modInsertTask = new WcsTask()
|
{
|
TaskNo = _taskService.GetTaskCode(),
|
TaskType = TaskTypeEnum.Move,
|
Type = PLCTypeEnum.AGV,
|
StartLocate = modTask.EndLocate,//缓存区
|
EndLocate = strEndLocate,
|
PalletNo = modTask.PalletNo,
|
Status = TaskStatusEnum.Wait,
|
Levels = 6,
|
Origin = "WCS"
|
};
|
await _db.Insertable(modInsertTask).ExecuteCommandAsync();
|
HubUtil.PublicTask(modInsertTask.Adapt<WcsTaskOutput>());
|
}
|
|
//货品拉到电梯口需要向输送线写入100
|
if (modTask.EndLocate == AGVStaionEnum.A1.ToString())
|
{
|
var modPlc = PLCTaskAction.plcs.FirstOrDefault(s => s.Text == "输送线");
|
var modConn = new PLCUtil(modPlc);
|
var modDevice = PLCTaskAction.plcDevices.First(s => s.Text == "C口");
|
var modStation = PLCTaskAction.plcPositions.First(s => s.Text == "C口申请入库");
|
var plcResult = modConn.SetPlcDBValue(modStation.PosType, modDevice.DbNumber, modStation.PlcPos, "100");
|
if (plcResult.IsSucceed)
|
{
|
WcsTaskMonitor modTaskMonitorPLC = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
PlcId = modDevice.PlcId,
|
PlcName = modStation.PlcPos,
|
StartLocat = modTask.StartLocate,
|
EndLocat = modTask.EndLocate,
|
Status = TaskStatusEnum.Doing,
|
InteractiveMsg = $"向{modStation.Text}写入指令100,结果{plcResult.IsSucceed}",
|
};
|
_db.Insertable(modTaskMonitorPLC).ExecuteCommand();
|
HubUtil.PublicTaskMonitor(modTaskMonitorPLC.Adapt<WcsTaskMonitorOutput>());
|
}
|
else
|
{
|
Log.Error("C口申请入库写入值100失败");
|
}
|
}
|
//放入拆托机后,向拆托机写入完成信号
|
if (modTask.EndLocate == AGVStaionEnum.D1.ToString())
|
{
|
var modPlc = PLCTaskAction.plcs.FirstOrDefault(s => s.Type == PLCTypeEnum.PalletMachine);
|
var modConn = new PLCUtil(modPlc);
|
var modDevice = PLCTaskAction.plcDevices.FirstOrDefault(s => s.Text == "拆托机");
|
var res = modConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "0");
|
var modTaskMonitorPLC = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
PlcId = modDevice.PlcId,
|
PlcName = modDevice.WcsPos,
|
Status = TaskStatusEnum.Doing,
|
InteractiveMsg = $"向{modDevice.Text}写入完成信号0,结果{res.IsSucceed}",
|
};
|
_db.Insertable(modTaskMonitorPLC).ExecuteCommand();
|
HubUtil.PublicTaskMonitor(modTaskMonitorPLC.Adapt<WcsTaskMonitorOutput>());
|
modConn.Close();
|
}
|
//if (modTask.EndLocate == AGVStaionEnum.B1.ToString() || modTask.EndLocate == AGVStaionEnum.B2.ToString())
|
//{
|
// var num = modTask.EndLocate.Substring(1, 1);
|
// var modPlc = PLCTaskAction.plcs.FirstOrDefault(s => s.Type == PLCTypeEnum.RobotPalletizer && s.WareHouseNo == num);
|
// var modConn = new PLCUtil(modPlc);
|
// var modDevice = PLCTaskAction.plcDevices.FirstOrDefault(s => s.PlcId == modPlc.Id && s.Level == DeviceLevelEnum.DB);
|
// var res = modConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.PlcPos, "0");
|
// var modTaskMonitorPLC = new WcsTaskMonitor()
|
// {
|
// TaskNo = modTask.TaskNo,
|
// PlcId = modDevice.PlcId,
|
// PlcName = modDevice.PlcPos,
|
// Status = TaskStatusEnum.Doing,
|
// InteractiveMsg = $"向{modDevice.Text}写入放托完成信号,结果{res.IsSucceed}",
|
// };
|
// _db.Insertable(modTaskMonitorPLC).ExecuteCommand();
|
// HubUtil.PublicTaskMonitor(modTaskMonitorPLC.Adapt<WcsTaskMonitorOutput>());
|
// modConn.Close();
|
//}
|
if (modTask.EndLocate == AGVStaionEnum.F1.ToString())
|
{
|
await _sysConfigService.UpdateConfigValue("cache_Materal", true);
|
}
|
if (modTask.StartLocate == AGVStaionEnum.F1.ToString())
|
{
|
await _sysConfigService.UpdateConfigValue("cache_Materal", false);
|
}
|
modTask.Status = TaskStatusEnum.Complete;
|
modTask.FinishDate = DateTime.Now;
|
await _db.Updateable(modTask).ExecuteCommandAsync();
|
WcsTaskMonitor modTaskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
//PlcId = modDevice.PlcId,
|
PlcName = "AGV",
|
StartLocat = modTask.StartLocate,
|
EndLocat = modTask.EndLocate,
|
Status = TaskStatusEnum.Complete,
|
InteractiveMsg = $"AGV小车反馈任务完成",
|
};
|
await _db.Insertable(modTaskMonitor).ExecuteCommandAsync();
|
HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
|
HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>());
|
if (modTask.Origin == "WMS")
|
{
|
HttpService httpService = new HttpService();
|
var inputs = new TaskRequestWMS();
|
inputs.TaskNo = modTask.TaskNo;
|
inputs.PalletNo = modTask.PalletNo;
|
inputs.TaskType = "2";
|
inputs.TaskStatus = "2";
|
var modResponseTask = httpService.RequestTask(inputs).Result;
|
}
|
//托盘进出缓存区 需要记录
|
if (new[] { "Z", "C" }.Contains(modTask.EndLocate.Substring(0, 1)))
|
{
|
await _sysConfigService.UpdateConfigValue($"cache_{modTask.EndLocate}", true);
|
}
|
if (new[] { "Z", "C" }.Contains(modTask.StartLocate.Substring(0, 1)))
|
{
|
await _sysConfigService.UpdateConfigValue($"cache_{modTask.StartLocate}", false);
|
}
|
}
|
break;
|
case "outbin"://走出储位
|
{
|
//取空托完成后,向拆托机写入完成信号
|
if (modTask.StartLocate == AGVStaionEnum.D1.ToString() && (modTask.EndLocate == AGVStaionEnum.B1.ToString() || modTask.EndLocate == AGVStaionEnum.B2.ToString()))
|
{
|
var modPlc = PLCTaskAction.plcs.FirstOrDefault(s => s.Type == PLCTypeEnum.PalletMachine);
|
var modConn = new PLCUtil(modPlc);
|
var modDevice = PLCTaskAction.plcDevices.FirstOrDefault(s => s.Text == "拆托机");
|
var modPos = PLCTaskAction.plcPositions.FirstOrDefault(s => s.DeviceId == modDevice.Id && s.Text == "取托信号");
|
var res = modConn.SetPlcDBValue(modPos.PosType, modDevice.DbNumber, modPos.PlcPos, "0");
|
WcsTaskMonitor modTaskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
PlcId = modDevice.PlcId,
|
PlcName = modPos.PlcPos,
|
Status = TaskStatusEnum.Doing,
|
InteractiveMsg = $"向{modDevice.Text}写入取托信号0,结果{res.IsSucceed}",
|
};
|
_db.Insertable(modTaskMonitor).ExecuteCommand();
|
HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>());
|
modPos = PLCTaskAction.plcPositions.FirstOrDefault(s => s.DeviceId == modDevice.Id && s.Text == "取托完成");
|
res = modConn.SetPlcDBValue(modPos.PosType, modDevice.DbNumber, modPos.PlcPos, "1");
|
modTaskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
PlcId = modDevice.PlcId,
|
PlcName = modPos.PlcPos,
|
Status = TaskStatusEnum.Doing,
|
InteractiveMsg = $"向{modDevice.Text}写入取托完成1,结果{res.IsSucceed}",
|
};
|
_db.Insertable(modTaskMonitor).ExecuteCommand();
|
HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>());
|
modConn.Close();
|
}
|
//todo:去码垛工位取货完成后,需要写PLC信号开启光幕
|
if ((modTask.StartLocate == AGVStaionEnum.B1.ToString() || modTask.StartLocate == AGVStaionEnum.B2.ToString())
|
&& (modTask.EndLocate == AGVStaionEnum.C1.ToString() || modTask.EndLocate == AGVStaionEnum.C2.ToString()))
|
{
|
var num = modTask.StartLocate.Substring(1, 1);
|
var modPlc = PLCTaskAction.plcs.FirstOrDefault(s => s.Type == PLCTypeEnum.RobotPalletizer && s.WareHouseNo == num);
|
var modConn = new PLCUtil(modPlc);
|
var modDevice = PLCTaskAction.plcDevices.FirstOrDefault(s => s.PlcId == modPlc.Id && s.Level == DeviceLevelEnum.DB);
|
var modPos = PLCTaskAction.plcPositions.FirstOrDefault(s => s.DeviceId == modDevice.Id && s.Text == "开启光幕");
|
var res = modConn.SetPlcDBValue(modPos.PosType, modDevice.DbNumber, modPos.PlcPos, "1");
|
var modTaskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
PlcId = modDevice.PlcId,
|
PlcName = modPos.PlcPos,
|
Status = TaskStatusEnum.Doing,
|
InteractiveMsg = $"向{modDevice.Text}写入开启光幕1,结果{res.IsSucceed}",
|
};
|
_db.Insertable(modTaskMonitor).ExecuteCommand();
|
HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>());
|
//写入光幕0
|
Task.Run(() =>
|
{
|
var modDevice = PLCTaskAction.plcDevices.FirstOrDefault(s => s.PlcId == modPlc.Id && s.Level == DeviceLevelEnum.DB);
|
var modPos = PLCTaskAction.plcPositions.FirstOrDefault(s => s.DeviceId == modDevice.Id && s.Text == "开启光幕");
|
Thread.Sleep(1000);
|
var res = modConn.SetPlcDBValue(modPos.PosType, modDevice.DbNumber, modPos.PlcPos, "0");
|
var modTaskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
PlcId = modDevice.PlcId,
|
PlcName = modPos.PlcPos,
|
Status = TaskStatusEnum.Doing,
|
InteractiveMsg = $"向{modDevice.Text}写入开启光幕0,结果{res.IsSucceed}",
|
};
|
_db.Insertable(modTaskMonitor).ExecuteCommand();
|
HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>());
|
});
|
|
//向码垛机器人写取托完成信号
|
modDevice = PLCTaskAction.plcDevices.FirstOrDefault(s => s.PlcId == modPlc.Id && s.Level == DeviceLevelEnum.Station);
|
res = modConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.PlcPos, "0");
|
modTaskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
PlcId = modDevice.PlcId,
|
PlcName = modPos.PlcPos,
|
Status = TaskStatusEnum.Doing,
|
InteractiveMsg = $"向{modDevice.Text}写入取托完成信号,结果{res.IsSucceed}",
|
};
|
_db.Insertable(modTaskMonitor).ExecuteCommand();
|
HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>());
|
modConn.Close();
|
}
|
//起始工位是提升机取货工位
|
if (modTask.StartLocate == AGVStaionEnum.A2.ToString())
|
{
|
var modPlc = PLCTaskAction.plcs.FirstOrDefault(s => s.Type == PLCTypeEnum.ConveyorLine);
|
var modConn = new PLCUtil(modPlc);
|
var modDevice = PLCTaskAction.plcDevices.FirstOrDefault(s => s.PlcId == modPlc.Id && s.Text == "C口");
|
var modPos = PLCTaskAction.plcPositions.FirstOrDefault(s => s.DeviceId == modDevice.Id && s.Text == "取走确认");
|
var res = modConn.SetPlcDBValue(modPos.PosType, modDevice.DbNumber, modPos.PlcPos, "1");
|
var modTaskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
PlcId = modDevice.PlcId,
|
PlcName = modPos.PlcPos,
|
Status = TaskStatusEnum.Doing,
|
InteractiveMsg = $"向{modDevice.Text}写入取走确认,结果{res.IsSucceed}",
|
};
|
_db.Insertable(modTaskMonitor).ExecuteCommand();
|
HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>());
|
}
|
}
|
break;
|
case "apply"://放货申请
|
{
|
//todo:去码垛工位取货,需要写PLC信号关闭光幕
|
if ((modTask.StartLocate == AGVStaionEnum.B1.ToString() || modTask.StartLocate == AGVStaionEnum.B2.ToString())
|
&& (modTask.EndLocate == AGVStaionEnum.C1.ToString() || modTask.EndLocate == AGVStaionEnum.C2.ToString()))
|
{
|
var no = modTask.StartLocate.Substring(1, 1);
|
var modPlc = PLCTaskAction.plcs.FirstOrDefault(s => s.Type == PLCTypeEnum.RobotPalletizer && s.WareHouseNo == no);
|
var modConn = new PLCUtil(modPlc);
|
var modDevice = PLCTaskAction.plcDevices.FirstOrDefault(s => s.PlcId == modPlc.Id && s.Level == DeviceLevelEnum.DB);
|
var modPos = PLCTaskAction.plcPositions.FirstOrDefault(s => s.DeviceId == modDevice.Id && s.Text == "关闭光幕");
|
var res = modConn.SetPlcDBValue(modPos.PosType, modDevice.DbNumber, modPos.PlcPos, "1");
|
var modTaskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
PlcId = modDevice.PlcId,
|
PlcName = modPos.PlcPos,
|
Status = TaskStatusEnum.Doing,
|
InteractiveMsg = $"向{modDevice.Text}写入关闭光幕1,结果{res.IsSucceed}",
|
};
|
_db.Insertable(modTaskMonitor).ExecuteCommand();
|
HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>());
|
Task.Run(() =>
|
{
|
Thread.Sleep(1000);
|
modConn.SetPlcDBValue(modPos.PosType, modDevice.DbNumber, modPos.PlcPos, "0");
|
var modTaskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
PlcId = modDevice.PlcId,
|
PlcName = modPos.PlcPos,
|
Status = TaskStatusEnum.Doing,
|
InteractiveMsg = $"向{modDevice.Text}写入开启光幕0,结果{res.IsSucceed}",
|
};
|
_db.Insertable(modTaskMonitor).ExecuteCommand();
|
HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>());
|
});
|
modConn.Close();
|
}
|
}
|
break;
|
case "start"://任务开始
|
{
|
//开始向拆托机放入托盘任务
|
if (modTask.EndLocate == AGVStaionEnum.D1.ToString())
|
{
|
var modPlc = PLCTaskAction.plcs.FirstOrDefault(s => s.Type == PLCTypeEnum.PalletMachine);
|
var modConn = new PLCUtil(modPlc);
|
var modDevice = PLCTaskAction.plcDevices.FirstOrDefault(s => s.Text == "拆托机");
|
var res = modConn.SetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos, "1");
|
modConn.Close();
|
}
|
|
var taskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
PlcName = input.Method,
|
InteractiveMsg = $"AGV小车反馈任务开始"
|
};
|
await _db.Insertable(taskMonitor).ExecuteCommandAsync();
|
HubUtil.PublicTaskMonitor(taskMonitor.Adapt<WcsTaskMonitorOutput>());
|
}
|
break;
|
case "cancel"://任务结束
|
{
|
PLCService.AGVStatus = false;
|
modTask.IsSuccess = TaskSuccessEnum.Fail;
|
modTask.CancelDate = DateTime.Now;
|
modTask.Status = TaskStatusEnum.Cancell;
|
modTask.Levels = 999;
|
await _db.Updateable(modTask).UpdateColumns(s => new { s.Status, s.IsSuccess, s.FinishDate, s.CancelDate, s.UpdateTime, s.UpdateUserId, s.UpdateUserName }).ExecuteCommandAsync();
|
//写入任务明细表
|
WcsTaskMonitor modTaskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
PlcId = 0,
|
PlcName = "",
|
Status = TaskStatusEnum.Complete,
|
StartLocat = modTask.StartLocate,
|
EndLocat = modTask.EndLocate,
|
InteractiveMsg = "小车通知任务取消",
|
PalletNo = modTask.PalletNo
|
};
|
await _db.Insertable(modTaskMonitor).ExecuteCommandAsync();
|
|
HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
|
HubUtil.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>());
|
}
|
break;
|
default:
|
break;
|
}
|
}
|
else
|
{
|
result.Code = "1";
|
result.Message = "找不到该任务";
|
}
|
}
|
catch (Exception ex)
|
{
|
result.Code = "1";
|
result.Message = ex.Message;
|
}
|
finally
|
{
|
modUtil?.Close();
|
}
|
|
|
return result;
|
}
|
|
|
|
/// <summary>
|
/// 修改原材料仓状态
|
/// </summary>
|
/// <returns></returns>
|
[HttpPost]
|
public async Task UpdateMateralStatus()
|
{
|
await _sysConfigService.UpdateConfigValue("cache_Materal", false);
|
}
|
|
/// <summary>
|
/// 获取车间动向
|
/// </summary>
|
/// <returns></returns>
|
[HttpPost]
|
public async Task<WorkshopEnum> Workshop()
|
{
|
var result = Enum.TryParse(await _sysConfigService.GetConfigValue<string>("workshop_Trend"), out WorkshopEnum workshop);
|
return workshop;
|
}
|
|
/// <summary>
|
/// 修改车间动向
|
/// </summary>
|
/// <returns></returns>
|
[HttpPost]
|
public async Task ChangeWorkshop(RequestTrends input)
|
{
|
await _sysConfigService.UpdateConfigValue("workshop_Trend", input.Type.ToString());
|
}
|
|
/// <summary>
|
/// 手动入托盘
|
/// </summary>
|
/// <returns></returns>
|
//[HttpPost]
|
//public async Task InPallet(RequestStorage input)
|
//{
|
// var intPallet = _sysConfigService.GetConfigValue<int>("cache_Pallet").Result;
|
// if (intPallet + input.Qty > 3)
|
// throw Oops.Bah($"输入数量大于可放置数");
|
// await _sysConfigService.UpdateConfigValue("cache_Pallet", (intPallet + input.Qty).ToString());
|
//}
|
|
/// <summary>
|
/// 成品缓存区入库
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
[HttpPost]
|
[UnitOfWork]
|
public async Task ProductStorage(RequestStorage input)
|
{
|
var intProduct = AGVStorageUtil.ProductCount();
|
var intTask = await _db.Queryable<WcsTask>().Where(s => s.TaskType == TaskTypeEnum.Move
|
&& s.Type == PLCTypeEnum.AGV && s.Status <= TaskStatusEnum.Doing
|
&& s.StartLocate.StartsWith("Z") && s.EndLocate == AGVStaionEnum.A1.ToString()).CountAsync();
|
if (input.Qty > intProduct)
|
throw Oops.Bah($"输入数量大于可出数量{intProduct}");
|
var listTask = new List<WcsTask>();
|
var TaskNo = GetTaskCode("WCS");
|
for (int i = 0; i < input.Qty; i++)
|
{
|
listTask.Add(new WcsTask()
|
{
|
TaskNo = "WCS" + DateTime.Now.ToString("yyyyMMdd") + (TaskNo++).ToString().PadLeft(4, '0'),
|
TaskType = TaskTypeEnum.Move,
|
Type = PLCTypeEnum.AGV,
|
StartLocate = AGVStaionEnum.Z11.ToString(),
|
EndLocate = AGVStaionEnum.A1.ToString(),
|
PalletNo = "",
|
Status = TaskStatusEnum.Wait,
|
Levels = 10,
|
Origin = "PDA"
|
});
|
}
|
await _db.Insertable(listTask).ExecuteCommandAsync();
|
}
|
/// <summary>
|
/// 自动生成任务号
|
/// </summary>
|
/// <param name="codeFlag"></param>
|
/// <returns></returns>
|
[NonAction]
|
public static int GetTaskCode(string codeFlag = "WCS")
|
{
|
var list = _db.Queryable<WcsTask>().Where(m => m.TaskNo.StartsWith("WCS")).ToList();
|
string maxNo = list.Max(m => m.TaskNo);
|
if (!string.IsNullOrEmpty(maxNo))
|
{
|
maxNo = maxNo.Substring(codeFlag.Length);
|
}
|
//获取数据库时间八位
|
string date = DateTime.Now.ToString("yyyyMMdd").Trim();
|
int no = 0;
|
if (string.IsNullOrEmpty(maxNo))
|
{
|
no = 1;
|
}
|
else
|
{
|
if (maxNo.Length == 12 && maxNo.Substring(0, 8) == date)
|
{
|
int lastNo = Convert.ToInt32(maxNo.Substring(8, 4)) + 1;
|
no = lastNo;
|
}
|
else
|
{
|
no = 1;
|
}
|
}
|
return no;
|
}
|
/// <summary>
|
/// 完成任务
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
[HttpPost]
|
public async Task FinishTask(WcsTask input)
|
{
|
if (input.TaskNo.IsNullOrEmpty())
|
throw Oops.Bah("任务号不能为空");
|
var modTask = await _db.Queryable<WcsTask>().FirstAsync(s => s.TaskNo == input.TaskNo);
|
if (modTask == null)
|
throw Oops.Bah("找不到任务");
|
if (modTask.Status > TaskStatusEnum.Doing)
|
throw Oops.Bah("任务状态不对");
|
modTask.FinishDate = DateTime.Now;
|
modTask.Status = TaskStatusEnum.Complete;
|
await _db.Updateable(modTask).ExecuteCommandAsync();
|
var taskMonitor = new WcsTaskMonitor()
|
{
|
TaskNo = modTask.TaskNo,
|
InteractiveMsg = $"WMS调用完成任务"
|
};
|
_db.Insertable(taskMonitor).ExecuteCommand();
|
//下发任务日志
|
HubUtil.PublicTask(modTask.Adapt<WcsTaskOutput>());
|
HubUtil.PublicTaskMonitor(taskMonitor.Adapt<WcsTaskMonitorOutput>());
|
}
|
|
/// <summary>
|
/// 查询缓存位状态
|
/// </summary>
|
/// <returns></returns>
|
[HttpPost]
|
public async Task<Dictionary<string, bool>> QueryCacheStorage()
|
{
|
string[] listPallet = new[] {
|
"cache_Z11","cache_Z12","cache_Z13",
|
"cache_Z21","cache_Z22","cache_Z23",
|
"cache_Z31","cache_Z32","cache_Z33",
|
"cache_Z41","cache_Z42","cache_Z43",
|
"cache_Z51","cache_Z52","cache_Z53",
|
};
|
Dictionary<string, bool> dic = new Dictionary<string, bool>();
|
foreach (var mod in listPallet)
|
{
|
dic.Add(mod.Split('_')[1], await _sysConfigService.GetConfigValue<bool>(mod));
|
}
|
return dic;
|
}
|
/// <summary>
|
/// 修改缓存位状态
|
/// </summary>
|
/// <returns></returns>
|
[HttpPost]
|
public async Task ChangeCacheStatus(StorageCacheStatus input)
|
{
|
Type type = input.GetType();
|
foreach (var item in type.GetProperties())
|
{
|
string value = "";
|
var result = item.GetValue(input);
|
if (!result.IsNullOrEmpty())
|
{
|
if ((bool)item.GetValue(input))
|
value = "True";
|
else
|
value = "False";
|
await _sysConfigService.UpdateConfigValue("cache_" + item.Name, value);
|
}
|
}
|
}
|
|
/// <summary>
|
/// 查询小车正在执行的任务
|
/// </summary>
|
/// <returns></returns>
|
[HttpPost]
|
public async Task<WcsTask> AGVTask()
|
{
|
return await _db.Queryable<WcsTask>().Where(s => s.Type == PLCTypeEnum.AGV && s.Status == TaskStatusEnum.Doing).FirstAsync();
|
}
|
/// <summary>
|
/// 取消小车正在执行的任务
|
/// </summary>
|
/// <returns></returns>
|
[HttpPost]
|
public async Task CancelTask(WcsTask input)
|
{
|
await App.GetService<WcsTaskService>().Finsh(new UpdateWcsTaskInput() { Id = input.Id, Status = TaskStatusEnum.Cancell });
|
}
|
}
|