添加上升降机边调度逻辑

This commit is contained in:
2024-04-29 15:57:28 +08:00
parent 1e699fb7db
commit 18ff3b29ed
10 changed files with 695 additions and 69 deletions

View File

@@ -1,22 +1,30 @@
using System;
using System.Data;
using System.DirectoryServices.ActiveDirectory;
using System.Dynamic;
using System.Security.Policy;
using System.Text;
using Aop.Api.Domain;
using JNPF;
using JNPF.Common.Cache;
using JNPF.Common.Core.Manager;
using JNPF.Common.Dtos.VisualDev;
using JNPF.Common.Extension;
using JNPF.FriendlyException;
using JNPF.Systems.Interfaces.System;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NetTaste;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NPOI.OpenXmlFormats;
using NPOI.SS.Formula.Eval;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.X509.Qualified;
using Qiniu.Util;
using SqlSugar;
using Tnb.BasicData.Entities;
using Tnb.Common.Extension;
using Tnb.Common.Redis;
using Tnb.Common.Utils;
@@ -44,18 +52,29 @@ namespace Tnb.ProductionMgr
private Timer? Floor2UpMachinecodetimer;
// 二楼下升降机
private Timer? Floor2DownMachinecodetimer;
// 二楼料架配送
private Timer? Floor2RackDeliverytimer;
public static SemaphoreSlim s_taskExecuteRackDelivery = new(1);
private readonly RedisData _redisData;
private readonly IPrdInstockService _prdInstockService;
private readonly ISqlSugarRepository<RedisReadConfig> _repository;
private readonly IWmsPDAScanInStockService _wmsPDAScanInStock;
private readonly IUserManager _userManager;
private readonly IBillRullService _billRullService;
private readonly IWareHouseService _wareHouseService;
private readonly ElevatorControlConfiguration _eleCtlCfg = App.Configuration.Build<ElevatorControlConfiguration>();
public RedisBackGround(RedisData redisData, IPrdInstockService prdInstockService, ISqlSugarRepository<RedisReadConfig> repository, IWmsPDAScanInStockService wmsPDAScanInStock)
public RedisBackGround(RedisData redisData, IPrdInstockService prdInstockService, ISqlSugarRepository<RedisReadConfig> repository, IWmsPDAScanInStockService wmsPDAScanInStock
, IUserManager userManager, IBillRullService billRullService, IWareHouseService wareHouseService)
{
_redisData = redisData;
_prdInstockService = prdInstockService;
_repository = repository;
_wmsPDAScanInStock = wmsPDAScanInStock;
_userManager = userManager;
_billRullService = billRullService;
_wareHouseService = wareHouseService;
}
//获取redis数据
private void GetRedisData(object state)
@@ -318,7 +337,7 @@ where carry_code = '{coderesult}' and status = '{WmsWareHouseConst.TASK_BILL_STA
// 二楼料架补充
protected ILogger LoggerFloor2RackSupplement => LoggerFactory.Create(builder => builder.AddFile($"{AppContext.BaseDirectory}/logs/customFloor2RackSupplement{DateTime.Now:yyyyMMdd}.log", cfgOpts =>
protected ILogger LoggerFloor2RackDelivery => LoggerFactory.Create(builder => builder.AddFile($"{AppContext.BaseDirectory}/logs/customFloor2RackDelivery{DateTime.Now:yyyyMMdd}.log", cfgOpts =>
{
//cfgOpts.DateFormat = "yyyy-MM-dd HH:mm:ss.fff";
cfgOpts.MessageFormat = (logMsg) =>
@@ -448,6 +467,8 @@ where carry_code = '{coderesult}' and status = '{WmsWareHouseConst.TASK_BILL_STA
var DistaskH = _repository.AsSugarClient().Queryable<WmsDistaskH>().Where(p => p.carry_code == result && p.status != WmsWareHouseConst.TASK_BILL_STATUS_COMPLE_ID).OrderByDescending(p => p.create_time).First();
if (DistaskH != null)
{
Logger.LogInformation($"【定时任务SSXcode】DistaskH != null putdic.Keys.Contains(DistaskH.startlocation_code):{putdic.Keys.Contains(DistaskH.startlocation_code)}");
Dictionary<string, string> dicCommand2 = new(StringComparer.OrdinalIgnoreCase)
{
["DevName"] = key,
@@ -467,6 +488,7 @@ where carry_code = '{coderesult}' and status = '{WmsWareHouseConst.TASK_BILL_STA
}
else
{
Logger.LogInformation($"【定时任务SSXcode】DistaskH == null {_repository.AsSugarClient().Queryable<WmsDistaskH>().Where(p => p.carry_code == result && p.status != WmsWareHouseConst.TASK_BILL_STATUS_COMPLE_ID).OrderByDescending(p => p.create_time).ToSqlString()}");
Dictionary<string, string> dicCommand2 = new(StringComparer.OrdinalIgnoreCase)
{
["DevName"] = key,
@@ -500,24 +522,147 @@ where carry_code = '{coderesult}' and status = '{WmsWareHouseConst.TASK_BILL_STA
CheckGettimer?.Dispose();
Scantimer?.Dispose();
SSXcodetimer?.Dispose();
Floor2UpMachinecodetimer?.Dispose();
Floor2DownMachinecodetimer?.Dispose();
Floor2RackDeliverytimer.Dispose();
}
#region
#region
// 上升降机
private void Floor2UpMachinecode(object args)
private async void Floor2UpMachinecode(object args)
{
// 补充料架
//var DistaskH = _repository.AsSugarClient().Queryable<WmsMechanicalArmD>().Where(p => p.carry_code == && p.status != WmsWareHouseConst.TASK_BILL_STATUS_COMPLE_ID).OrderByDescending(p => p.create_time).First();
using (var db = _repository.AsSugarClient().CopyNew())
{
string barcode = Floor2UpDownMachinecode_GetTag<string>(MechanicalArmConsts.).ToString();
if (string.IsNullOrEmpty(barcode))
{
LoggerFloor2UpDownMachine.LogError($@"【上升降机】未取到条码数据");
return;
}
// 读取上升降机的左右料架区配置
string[] configs = new string[2] { "二楼上升降机机械臂左", "二楼上升降机机械臂右" };
// 左右料架区配置
List<WmsMechanicalArmH> WmsMechanicalArmHs = db.Queryable<WmsMechanicalArmH>()
.Where(r => configs.Contains(r.name) && r.mechanicalconfirm == 1).ToList();
// 是否可以放货
if (WmsMechanicalArmHs.Count == 0)
{
LoggerFloor2UpDownMachine.LogWarning($@"【上升降机】目前没有可以放货的料架区");
return;
}
// 如果条码已被绑定
if (WmsMechanicalArmHs.Where(r => !string.IsNullOrEmpty(r.barcodes) && r.barcodes.Contains(barcode)).Count() > 0)
{
LoggerFloor2UpDownMachine.LogWarning($@"【上升降机】条码{barcode}已被绑定");
return;
}
LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】扫描到有效条码 {barcode}");
// 获取下到输送线9和10的未完成的出库单
List<WmsEmptyOutstockH> WmsEmptyOutstockHs = db.Queryable<WmsEmptyOutstockH>()
.InnerJoin<WmsEmptyOutstockD>((a, b) => a.id == b.bill_id)
.Where((a, b) => (a.location_id == "32609238573589" || a.location_id == "32609229889045") && a.bindrackcomplete != WmsWareHouseConst.BILLSTATUS_COMPLETE_ID
&& b.carry_code == barcode).ToList();
if (WmsEmptyOutstockHs.Count() == 0)
{
LoggerFloor2UpDownMachine.LogWarning($@"【上升降机】未找到条码{barcode}的输送线为9、10的出库单");
return;
}
// 出库单
WmsEmptyOutstockH WmsEmptyOutstockH = WmsEmptyOutstockHs.OrderByDescending(r => r.create_time).First();
// 找到条码在的出库单
string ckdCode = WmsEmptyOutstockH.bill_code;
int ckdRemainBindRackNum = (int)(WmsEmptyOutstockH.remainbindracknum != null ? WmsEmptyOutstockH.remainbindracknum : 0);
//扫描到的料箱 a.对应出库单的b.码垛计数未达到满托数量的料架区
IEnumerable<WmsMechanicalArmH> targetConfigs = WmsMechanicalArmHs.Where(r => r.outbill == ckdCode && r.stackingcount < r.maxnum);
WmsMechanicalArmH target;
await db.Ado.BeginTranAsync();
try
{
// 找不到对应的料架
if (targetConfigs.Count() == 0)
{
// 有空闲料架区且绑定了料架时
targetConfigs = WmsMechanicalArmHs.Where(r => string.IsNullOrEmpty(r.outbill)).OrderBy(r => r.id);
if (targetConfigs.Count() > 0)
{
target = targetConfigs.First();
// 计算当前料架区的满托数量
int? maxnum = ckdRemainBindRackNum > target.maxracknum ? ckdRemainBindRackNum % target.maxracknum : ckdRemainBindRackNum;
// 更新 出库单、满托数量
LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】为条码 {barcode} 所在的出库单 {ckdCode} 占用了一个空闲料架");
await db.Updateable<WmsMechanicalArmH>().SetColumns(r => new WmsMechanicalArmH
{
outbill = ckdCode,
maxnum = maxnum
}).Where(r => r.id == target.id).ExecuteCommandAsync();
bool result = await Floor2UpDownMachinecode_SetTag($"上升降机满托{target.stackingposition}数量", maxnum.ToString());
LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】设定升降机满托{target.stackingposition}满托数量为 {maxnum} 结果为 {result}");
}
else
{
LoggerFloor2UpDownMachine.LogError($@"【上升降机】条码{barcode}找不到绑定出库单{ckdCode}的料架区,且没有空闲的料架区可以用于绑定此出库单!");
await db.Ado.RollbackTranAsync();
return;
}
}
//如有多个料架绑定同个出库单则取第一个未满托的料架
target = targetConfigs.First();
LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】当前条码目标料架区为 {JsonConvert.SerializeObject(target)}");
// 判断《上升降机空托1/2送到》是否为true
string tag_上升降机空托送到 = $@"上升降机空托{target.stackingposition}送到";
bool = (bool)Floor2UpDownMachinecode_GetTag<bool>(tag_上升降机空托送到);
LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】取值 {tag_上升降机空托送到} 结果为 {上升降机空托送到}");
if ()
{
// 开始码垛
bool result = await Floor2UpDownMachinecode_SetTag(MechanicalArmConsts., target.stackingposition.ToString());
LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】码垛结果 {result}");
// 回写料箱条码、码垛计数
await db.Updateable<WmsMechanicalArmH>().SetColumns(r => new WmsMechanicalArmH
{
barcodes = $"{target.barcodes},{barcode}".Trim(','),
stackingcount = r.stackingcount + 1
}).Where(r => r.id == target.id).ExecuteCommandAsync();
LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】回写料箱条码、码垛计数");
// 回写出库单的剩余可绑定料架数量
await db.Updateable<WmsEmptyOutstockH>().SetColumns(r => new WmsEmptyOutstockH
{
remainbindracknum = r.remainbindracknum - 1
}).Where(r => r.id == WmsEmptyOutstockH.id).ExecuteCommandAsync();
LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】回写出库单的剩余可绑定料架数量");
}
else
{
LoggerFloor2UpDownMachine.LogError($@"【上升降机】料架未送到 料架区{target.stackingposition}");
}
await db.Ado.CommitTranAsync();
// MechanicalArmConsts.上升降机满托2数量
// 扫码分配码垛位
}
catch (Exception ex)
{
LoggerFloor2UpDownMachine.LogError(ex.ToString());
LoggerFloor2UpDownMachine.LogError(ex.StackTrace);
await db.Ado.RollbackTranAsync();
}
}
}
// 下升降机
@@ -525,33 +670,365 @@ where carry_code = '{coderesult}' and status = '{WmsWareHouseConst.TASK_BILL_STA
{
// 补充料架
// 扫码分配拆垛位
}
/// <summary>
/// 检查机械臂料架区信号(上升降机空托1送到)
/// </summary>
/// <returns></returns>
public async Task<bool> _上升降机空托1送到()
{
using (var db = _repository.AsSugarClient().CopyNew())
{
string[] configs_upMachine = new string[2] { "二楼上升降机机械臂左", "二楼上升降机机械臂右" };
// 找到AGV已到货没有机械臂确认的数据
ISugarQueryable<WmsMechanicalArmH> WmsMechanicalArmHsuagar = db.Queryable<WmsMechanicalArmH>()
.Where(r => r.agvconfirm == 1 && r.mechanicalconfirm == 0 && configs_upMachine.Contains(r.name));
foreach (WmsMechanicalArmH wmsMechanicalArmH in WmsMechanicalArmHsuagar.ToList())
{
bool = (bool)Floor2UpDownMachinecode_GetTag<bool>($"上升降机请求送空托{wmsMechanicalArmH.stackingposition}");
string data = _redisData.GetHash("东面提升机输送线", $"上升降机空托{wmsMechanicalArmH.stackingposition}送到").Result;
JObject? res = JsonConvert.DeserializeObject<JObject>(data);
bool result = res != null && res["Value"] != null ? res.Value<bool>("Value") : false;
LoggerFloor2RackDelivery.LogInformation($"【送空托到上升降区】 上升降机空托{wmsMechanicalArmH.stackingposition}送到 结果为{result}");
if (result)
{
// 绑定料架
await db.Updateable<WmsMechanicalArmH>().SetColumns(r => new WmsMechanicalArmH
{
mechanicalconfirm = 1
}).Where(r => r.id == wmsMechanicalArmH.id).ExecuteCommandAsync();
}
}
return true;
}
}
/// <summary>
/// 送空托到上升降区
/// </summary>
/// <returns></returns>
public async Task<bool> ()
{
using (var db = _repository.AsSugarClient().CopyNew())
{
string[] configs_upMachine = new string[2] { "二楼上升降机机械臂左", "二楼上升降机机械臂右" };
// 找到没有绑定料架的且点位未锁定的料架区
ISugarQueryable<WmsMechanicalArmH> WmsMechanicalArmHsuagar = _repository.AsSugarClient().Queryable<WmsMechanicalArmH>().
InnerJoin<WmsPointH>((a, b) => a.point_id == b.id)
.Where((a, b) => string.IsNullOrEmpty(a.rackcode) && b.is_lock == 0 && configs_upMachine.Contains(a.name));
List<WmsMechanicalArmH> WmsMechanicalArmHs = WmsMechanicalArmHsuagar.ToList();
if (WmsMechanicalArmHs.Count() == 0)
{
LoggerFloor2RackDelivery.LogWarning($"【送空托到上升降区】 无需补充料架区 {WmsMechanicalArmHsuagar.ToSqlString()}");
return false;
}
// 料架区
WmsMechanicalArmH wmsMechanicalArmH = WmsMechanicalArmHs[0];
bool = (bool)Floor2UpDownMachinecode_GetTag<bool>($"上升降机请求送空托{wmsMechanicalArmH.stackingposition}");
if (!)
{
LoggerFloor2RackDelivery.LogWarning($"【送空托到上升降区】 料架区 {wmsMechanicalArmH.name}{wmsMechanicalArmH.stackingposition} 上升降机请求送空托{wmsMechanicalArmH.stackingposition}信号不为true");
return false;
}
LoggerFloor2RackDelivery.LogInformation($"【送空托到上升降区】 即将补充料架区{wmsMechanicalArmH.name}");
// 找到占用且未锁定的库位上的空料架
ISugarQueryable<BasLocation> rackStartLocations =
_repository.AsSugarClient().Queryable<BasLocation>()
.InnerJoin<WmsCarryH>((a, b) => a.id == b.location_id)
.LeftJoin<WmsCarrybindCode>((a, b, c) => b.id == c.carrybind_id)
.Where((a, b, c) => a.wh_id == "33780009364245" && a.is_use == "1" && a.is_lock == 0 && string.IsNullOrEmpty(c.id)
&& b.carrystd_id == WmsWareHouseConst.CARRY_LJSTD_ID).OrderBy(a => a.id).Take(1);
if (rackStartLocations.Count() == 0)
{
LoggerFloor2RackDelivery.LogWarning($"【送空托到上升降区】 暂存仓中没有可用的空料架 {rackStartLocations.ToSqlString()}");
return false;
}
BasLocation startLocation = rackStartLocations.First();
List<WmsPointH> startPoints = _repository.AsSugarClient().Queryable<WmsPointH>().Where(r => r.location_id == startLocation.id).ToList();
if (startPoints.Count == 0)
{
LoggerFloor2RackDelivery.LogError($"【送空托到上升降区】 起始库位{startLocation.location_code}未在点位表维护对应的点位");
return false;
}
List<WmsPointH> endPoints = _repository.AsSugarClient().Queryable<WmsPointH>().Where(r => r.id == wmsMechanicalArmH.point_id).ToList();
if (endPoints.Count == 0)
{
LoggerFloor2RackDelivery.LogError($"【送空托到上升降区】 终点{wmsMechanicalArmH.point_id} {wmsMechanicalArmH.point_code}未在点位表维护对应的点位");
return false;
}
List<WmsCarryH> wmsCarryHs = _repository.AsSugarClient().Queryable<WmsCarryH>().Where(r => r.location_id == startLocation.id).ToList();
if (wmsCarryHs.Count == 0)
{
LoggerFloor2RackDelivery.LogError($"【送空托到上升降区】 起点{startLocation.id} {startLocation.location_code}上找不到料架");
return false;
}
if (wmsCarryHs.Count > 1)
{
LoggerFloor2RackDelivery.LogError($"【送空托到上升降区】 起点{startLocation.id} {startLocation.location_code}上存在多个料架");
return false;
}
// 空料架
WmsCarryH targetCarry = wmsCarryHs[0];
WmsPointH startPoint = startPoints.First();
WmsPointH endPoint = endPoints.First();
await _repository.AsSugarClient().Updateable<BasLocation>().SetColumns(r => new BasLocation
{
is_lock = 1
}).Where(r => r.id == startLocation.id).ExecuteCommandAsync();
await _repository.AsSugarClient().Updateable<WmsPointH>().SetColumns(r => new WmsPointH
{
is_lock = 1
}).Where(r => r.id == endPoint.id).ExecuteCommandAsync();
LoggerFloor2RackDelivery.LogInformation($"【送空托到上升降区】 开始生成预任务 起点{startPoint.point_code} 终点{endPoint.point_code} 料架 {targetCarry.carry_code}");
List<WmsPointH> points = new List<WmsPointH>();
points.Add(startPoint);
points.Add(endPoint);
bool isOk = await Floor2UpDownMachinecode_createPretask(points, targetCarry.id, targetCarry.carry_code);
if (!isOk)
{
throw new Exception("【送空托到上升降区】 未成功生成预任务");
}
return true;
}
}
/// <summary>
/// 移走上升降区未生成预任务且满托的料架
/// </summary>
/// <returns></returns>
public async Task<bool> ()
{
using (var db = _repository.AsSugarClient().CopyNew())
{
string[] configs_upMachine = new string[2] { "二楼上升降机机械臂左", "二楼上升降机机械臂右" };
// 读取上升降机的左右料架区配置
List<WmsMechanicalArmH> WmsMechanicalArmHs = _repository.AsSugarClient().Queryable<WmsMechanicalArmH>().Where(r => r.stackingcount == r.maxnum && r.maxnum != 0 && !string.IsNullOrEmpty(r.rackcode) && r.iscreatepretask == 0 && configs_upMachine.Contains(r.name)).ToList();
foreach (WmsMechanicalArmH wmsMechanicalArmH in WmsMechanicalArmHs)
{
try
{
// 判断是否 上升降机请求取满托
bool = (bool)Floor2UpDownMachinecode_GetTag<bool>($"上升降机请求取满托{wmsMechanicalArmH.stackingposition}");
if (!)
{
LoggerFloor2RackDelivery.LogError($"【移走上升降区满托的料架】上升降机请求取满托{wmsMechanicalArmH.stackingposition}");
return false;
}
await _repository.AsSugarClient().Updateable<WmsMechanicalArmH>().SetColumns(r => new WmsMechanicalArmH
{
iscreatepretask = 1
}).Where(r => r.id == wmsMechanicalArmH.id).ExecuteCommandAsync();
List<WmsPointH> points = new List<WmsPointH>();
List<WmsPointH> startPoints = _repository.AsSugarClient().Queryable<WmsPointH>().Where(r => r.id == wmsMechanicalArmH.point_id).ToList();
if (startPoints.Count == 0)
{
LoggerFloor2RackDelivery.LogError($"【移走上升降区满托的料架】 起点{wmsMechanicalArmH.point_id} {wmsMechanicalArmH.point_code}未在点位表维护对应的点位");
return false;
}
WmsPointH startPoint = startPoints.First();
points.Add(startPoint);
// 找到未占用且未锁定的库位
ISugarQueryable<BasLocation> rackEndLocations =
_repository.AsSugarClient().Queryable<BasLocation>()
.Where(r => r.wh_id == "33780009364245" && r.is_use == "0" && r.is_lock == 0).OrderBy(a => a.id).Take(1);
if (rackEndLocations.Count() == 0)
{
LoggerFloor2RackDelivery.LogWarning($"【移走上升降区满托的料架】 暂存仓中没有可用的空库位 {rackEndLocations.ToSqlString()}");
return false;
}
BasLocation endLocation = rackEndLocations.First();
List<WmsPointH> endPoints = _repository.AsSugarClient().Queryable<WmsPointH>().Where(r => r.location_id == endLocation.id).ToList();
if (endPoints.Count == 0)
{
LoggerFloor2RackDelivery.LogError($"【移走上升降区满托的料架】 终点库位{endLocation.location_code}未在点位表维护对应的点位");
return false;
}
WmsPointH endPoint = endPoints.First();
points.Add(endPoint);
LoggerFloor2RackDelivery.LogInformation($"开始执行预任务生成: 料架区为{wmsMechanicalArmH.name}{wmsMechanicalArmH.stackingposition} 料架为{wmsMechanicalArmH.rackcode}");
bool isOk = await Floor2UpDownMachinecode_createPretask(points, wmsMechanicalArmH.rackid, wmsMechanicalArmH.rackcode);
if (!isOk)
{
throw new Exception("未成功生成预任务");
}
}
catch (Exception ex)
{
LoggerFloor2RackDelivery.LogError(ex.ToString());
LoggerFloor2RackDelivery.LogError(ex.StackTrace);
}
}
return true;
}
}
// 料架配送
private async void Floor2RackDelivery(object args)
{
var db = _repository.AsSugarClient().CopyNew();
await s_taskExecuteRackDelivery.WaitAsync();
try
{
// 检查机械臂料架区信号(上升降机空托1送到)
await _上升降机空托1送到();
// 送空托到上升降区
await ();
// 移走上升降区未生成预任务且满托的料架
await ();
_ = _wareHouseService.GenTaskExecute();
}
catch (Exception ex)
{
LoggerFloor2RackDelivery.LogError(ex.ToString());
LoggerFloor2RackDelivery.LogError(ex.StackTrace);
}
s_taskExecuteRackDelivery.Release();
}
// 上下升降机生成预任务(补充料架、上升降机取货到料架、上升降机满托运走,下升降机拿货到输送线、下升降机空托运走)
private void Floor2UpDownMachinecode_createPretask()
private async Task<bool> Floor2UpDownMachinecode_createPretask(List<WmsPointH> points, string carry_id, string carry_code)
{
//根据获取的路径点生成预任务,生成顺序必须预路径算法返回的起终点的顺序一致(预任务顺序)
List<WmsPretaskH> preTasks = points.Where(it => !it.location_id.IsNullOrEmpty()).GroupBy(g => g.area_code).Select(it =>
{
WmsPointH? sPoint = it.FirstOrDefault();
WmsPointH? ePoint = it.LastOrDefault();
WmsPretaskH preTask = new()
{
org_id = "",
startlocation_id = sPoint?.location_id!,
startlocation_code = sPoint?.location_code!,
endlocation_id = ePoint?.location_id!,
endlocation_code = ePoint?.location_code!,
start_floor = sPoint?.floor.ToString(),
end_floor = ePoint?.floor.ToString(),
startpoint_id = sPoint?.id!,
startpoint_code = sPoint?.point_code!,
endpoint_id = ePoint?.id!,
endpoint_code = ePoint?.point_code!,
bill_code = _billRullService.GetBillNumber(WmsWareHouseConst.WMS_PRETASK_H_ENCODE).GetAwaiter().GetResult(),
status = WmsWareHouseConst.PRETASK_BILL_STATUS_DXF_ID,
biz_type = "",
task_type = "",
carry_id = carry_id,
carry_code = carry_code,
area_id = sPoint?.area_id!,
area_code = it.Key,
require_id = "",
require_code = "",
create_id = "",
create_time = DateTime.Now
};
return preTask;
}).ToList();
//更新页面
//赋值签收状态
bool result = await _wareHouseService.GenPreTask(preTasks, null!);
if (result)
{
LoggerFloor2RackDelivery.LogInformation($"成功生成预任务:{preTasks.First().bill_code}");
return true;
}
return false;
}
// 上下升降机生成任务执行
private void Floor2UpDownMachinecode_createDistask()
private object Floor2UpDownMachinecode_GetTag<T>(string tag)
{
string key = "东面提升机输送线";
string data = _redisData.GetHash(key, tag.ToString()).Result;
if (data == null)
{
LoggerFloor2UpDownMachine.LogError($@"{key} {tag} 未取到数值!");
return "";
}
JObject? res = JsonConvert.DeserializeObject<JObject>(data);
switch (typeof(T).ToString())
{
case "System.Boolean":
{
bool result = res != null && res["Value"] != null ? res.Value<bool>("Value") : false;
return result;
}
case "System.String":
{
string? result = res != null && res["Value"] != null ? res.Value<string>("Value") : "";
return result;
}
}
return "wrong type";
}
private Tuple<bool, T> Floor2UpDownMachinecode_GetTag<T>(MechanicalArmConsts tag)
private async Task<bool> Floor2UpDownMachinecode_SetTag(string tag, string value)
{
//string key = "东面提升机输送线";
//string data = _redisData.GetHash(key, tag.ToString()).Result;
//JObject? res = JsonConvert.DeserializeObject<JObject>(data);
//T result = res != null && res["Value"] != null ? res.Value<T>("Value") : false;
//return new Tuple<bool, T>(result, res.Value<T>("Value"));
return new Tuple<bool, T>(false, default(T));
string DevName = "东面提升机输送线";
Dictionary<string, string> dicCommand = new(StringComparer.OrdinalIgnoreCase)
{
["DevName"] = DevName,
["token"] = _eleCtlCfg.token,
["TagName"] = tag,
["Value"] = value,
};
string result = await HttpClientHelper.GetRequestAsync(_eleCtlCfg.WriteTagUrl, dicCommand);
// TODO 测试
//string result = "Ok";
return result.Contains("Ok");
}
/// <summary>
@@ -604,12 +1081,6 @@ where carry_code = '{coderesult}' and status = '{WmsWareHouseConst.TASK_BILL_STA
}
}
private void Floor2UpDownMachinecode_SetTag()
{
string key = "东面提升机输送线";
}
#endregion
@@ -618,12 +1089,14 @@ where carry_code = '{coderesult}' and status = '{WmsWareHouseConst.TASK_BILL_STA
Readtimer = new Timer(GetRedisData, null, TimeSpan.Zero, TimeSpan.FromSeconds(300));
CheckGettimer = new Timer(CheckGet, null, TimeSpan.Zero, TimeSpan.FromSeconds(10));
Scantimer = new Timer(ScanInStock, null, TimeSpan.Zero, TimeSpan.FromSeconds(60));
SSXcodetimer= new Timer(SSXcode, null, TimeSpan.Zero, TimeSpan.FromSeconds(10));
SSXcodetimer = new Timer(SSXcode, null, TimeSpan.Zero, TimeSpan.FromSeconds(10));
// 二楼上升降机
Floor2UpMachinecodetimer = new Timer(Floor2UpMachinecode, null, TimeSpan.Zero, TimeSpan.FromSeconds(10));
Floor2UpMachinecodetimer = new Timer(Floor2UpMachinecode, null, TimeSpan.Zero, TimeSpan.FromSeconds(20));
// 二楼下升降机
Floor2DownMachinecodetimer = new Timer(Floor2DownMachinecode, null, TimeSpan.Zero, TimeSpan.FromSeconds(10));
//Floor2DownMachinecodetimer = new Timer(Floor2DownMachinecode, null, TimeSpan.Zero, TimeSpan.FromSeconds(10));
// 二楼料架配送
Floor2RackDeliverytimer = new Timer(Floor2RackDelivery, null, TimeSpan.Zero, TimeSpan.FromSeconds(60));
return Task.CompletedTask;
}

View File

@@ -68,6 +68,11 @@ namespace Tnb.WarehouseMgr.Entities.Consts
/// </summary>
public const string = "下升降机当前码垛位";
/// <summary>
///
/// </summary>
public const string = "上升降机条码";
}
}

View File

@@ -84,4 +84,15 @@ public partial class WmsEmptyOutstockH : BaseEntity<string>
/// </summary>
public DateTime? timestamp { get; set; }
/// <summary>
/// 二楼机械臂剩余绑定料架数量
/// </summary>
public int? remainbindracknum { get; set; }
/// <summary>
/// 二楼机械臂料箱绑定完成
/// </summary>
public string? bindrackcomplete { get; set; }
}

View File

@@ -1,19 +0,0 @@
using JNPF.Common.Contracts;
using JNPF.Common.Security;
using SqlSugar;
namespace Tnb.WarehouseMgr.Entities;
/// <summary>
/// 机械臂主表
/// </summary>
[SugarTable("wms_mechanicalArm_d")]
public partial class WmsMechanicalArmD : BaseEntity<string>
{
public WmsMechanicalArmD()
{
id = SnowflakeIdHelper.NextId();
}
}

View File

@@ -7,11 +7,81 @@ namespace Tnb.WarehouseMgr.Entities;
/// <summary>
/// 机械臂主表
/// </summary>
[SugarTable("wms_mechanicalArm_h")]
[SugarTable("wms_mechanicalarm_h")]
public partial class WmsMechanicalArmH : BaseEntity<string>
{
public WmsMechanicalArmH()
{
id = SnowflakeIdHelper.NextId();
}
/// <summary>
/// 说明
/// </summary>
public string? name { get; set; }
/// <summary>
/// 码垛位
/// </summary>
public int? stackingposition { get; set; }
/// <summary>
/// 码垛计数
/// </summary>
public int? stackingcount { get; set; }
/// <summary>
/// 料架上的条码
/// </summary>
public string? barcodes { get; set; }
/// <summary>
/// 料架最大盛放数量
/// </summary>
public int? maxracknum { get; set; }
/// <summary>
/// 出库单
/// </summary>
public string? outbill { get; set; }
/// <summary>
/// 满托数量
/// </summary>
public int? maxnum { get; set; }
/// <summary>
/// 是否生成预任务
/// </summary>
public int? iscreatepretask { get; set; }
/// <summary>
/// 料架id
/// </summary>
public string? rackid { get; set; }
/// <summary>
/// 料架编号
/// </summary>
public string? rackcode { get; set; }
/// <summary>
/// 点位id
/// </summary>
public string? point_id { get; set; }
/// <summary>
/// 点位编号
/// </summary>
public string? point_code { get; set; }
/// <summary>
/// 取放货确认
/// </summary>
public int? agvconfirm { get; set; }
/// <summary>
/// 取放货确认
/// </summary>
public int? mechanicalconfirm { get; set; }
}

View File

@@ -77,5 +77,10 @@ namespace Tnb.WarehouseMgr.Interfaces
Task SsxControl(WmsDistaskH disTask, string action);
Func<string, int, Task> AddUnExecuteTask { get; set; }
Task<bool> Check(string code, string action);
/// <summary>
/// // 二楼机械臂
/// </summary>
/// <returns></returns>
Task<bool> Floor2MechanicalComplete(WmsDistaskH disTask, string action);
}
}

View File

@@ -486,7 +486,7 @@ namespace Tnb.WarehouseMgr
}
else
{
Logger.Information($"【TaskCallback】sourceName不符合条件 {input.sourceName}");
//Logger.Information($"【TaskCallback】电梯sourceName不符合条件 {input.sourceName}");
}
@@ -505,6 +505,8 @@ namespace Tnb.WarehouseMgr
else
{
await _wareHouseService.SsxControl(disTask, "LOAD");
// 二楼机械臂
await _wareHouseService.Floor2MechanicalComplete(disTask, "LOAD");
}
}
else if (input.action == "UNLOAD")
@@ -517,6 +519,8 @@ namespace Tnb.WarehouseMgr
Logger.Information($"taskCompleUpInput json parameter:{JsonConvert.SerializeObject(taskCompleUpInput)}");
await _wareHouseService.TaskComplate(taskCompleUpInput);
await _wareHouseService.SsxControl(disTask, "UNLOAD");
// 二楼机械臂
await _wareHouseService.Floor2MechanicalComplete(disTask, "UNLOAD");
}
}
catch (Exception ex)

View File

@@ -201,6 +201,12 @@ namespace Tnb.WarehouseMgr
var eleStatusMap = await RedisHelper.HGetAllAsync(devName);
try
{
(int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus) = await GetElevatorStatus(devName, CancellationToken.None);//elevator.elevator_code
Logger.Information($"【UnloadConfirm】 电梯当前状态->系统状态:{sysStatus.ToEnum<EnumSysStatus>()},运行状态:{runStatus},门状态:{doorStatus},Agv状态:{agvStatus},当前楼层:{floorNo}");
//判断Agv电梯是否进入状态
if (agvStatus != (int)EnumAgvStatus.AGV运行状态)
_ = await WriteTagAsync(devName, ElevatorConsts.AGVControl, 1);
Logger.Information($"【SendOpenCloseCmd】 向系统发送开关门指令 {_elevatorCtlCfg.WriteTagUrl} {JsonConvert.SerializeObject(dicCommand)}");
var res = await HttpClientHelper.GetAsync(_elevatorCtlCfg.WriteTagUrl, pars: dicCommand);
Logger.Information($"【SendOpenCloseCmd】 向系统发送开关门指令 结果:{res}");

View File

@@ -434,6 +434,70 @@ namespace Tnb.WarehouseMgr
}
/// <summary>
/// // 二楼机械臂
/// </summary>
/// <returns></returns>
public async Task<bool> Floor2MechanicalComplete(WmsDistaskH disTask, string action)
{
if (disTask.area_code == "E")
{
Logger.Information($"【二楼机械臂Floor2MechanicalComplete】收到到货完成信号 传入参数: {disTask.bill_code} {action}");
SqlSugarClient db = _db.CopyNew();
if (action == "UNLOAD")
{
ISugarQueryable<WmsMechanicalArmH> WmsMechanicalArmHs = db.Queryable<WmsMechanicalArmH>().Where(r => r.point_code == disTask.endpoint_code);
if (WmsMechanicalArmHs.Count() == 0)
{
Logger.Information($"【二楼机械臂Floor2MechanicalComplete】 任务执行终点{disTask.endpoint_code} 与料架区的点位不匹配");
return false;
}
WmsMechanicalArmH target = WmsMechanicalArmHs.First();
// 回写料架和AGV确认
await db.Updateable<WmsMechanicalArmH>().SetColumns(r => new WmsMechanicalArmH
{
agvconfirm = 1,
rackid = disTask.carry_id,
rackcode = disTask.carry_code
}).Where(r => r.id == target.id).ExecuteCommandAsync();
Logger.Information($"【二楼机械臂Floor2MechanicalComplete】{disTask.bill_code} AGV已到货");
}
else
{
ISugarQueryable<WmsMechanicalArmH> WmsMechanicalArmHs = db.Queryable<WmsMechanicalArmH>().Where(r => r.point_code == disTask.startpoint_code);
if (WmsMechanicalArmHs.Count() == 0)
{
Logger.Information($"【二楼机械臂Floor2MechanicalComplete】 任务执行起点{disTask.endpoint_code} 与料架区的点位不匹配");
return false;
}
WmsMechanicalArmH target = WmsMechanicalArmHs.First();
//回写出库单状态
await db.Updateable<WmsEmptyOutstockH>().SetColumns(r=>new WmsEmptyOutstockH
{
bindrackcomplete = WmsWareHouseConst.BILLSTATUS_COMPLETE_ID
}).Where(r => r.bill_code == target.outbill).ExecuteCommandAsync();
// 重置料架区
await db.Updateable<WmsMechanicalArmH>().SetColumns(r => new WmsMechanicalArmH
{
stackingcount = 0,
barcodes = "",
outbill = "",
maxnum = 0,
iscreatepretask = 0,
rackcode = "",
rackid = "",
agvconfirm = 0,
mechanicalconfirm = 0
}).Where(r => r.id == target.id).ExecuteCommandAsync();
Logger.Information($"【二楼机械臂Floor2MechanicalComplete】{disTask.bill_code} AGV已到货");
}
}
return true;
}
/// <summary>
/// 生成任务执行
@@ -1223,7 +1287,7 @@ namespace Tnb.WarehouseMgr
{
tuple = await _elevatorControlService.GetElevatorStatus(devName, tags, CancellationToken.None);
await Task.Delay(1000);
} while (tuple.sysStatus != 3 && tuple.runStatus != 0);
} while (tuple.sysStatus != 3 || tuple.runStatus != 0);
Logger.Information($"sysStatus:{tuple.sysStatus},runStatus:{tuple.runStatus},floorNo:{tuple.floorNo},disTask.end_floor={disTask.end_floor}");
@@ -1448,6 +1512,9 @@ namespace Tnb.WarehouseMgr
locIts.Add(loc);
}
Logger.Information($@"TaskComplate 更新carryIts: {JsonConvert.SerializeObject(carryIts)}");
Logger.Information($@"TaskComplate 更新carryCodeIts: {JsonConvert.SerializeObject(carryCodeIts)}");
_ = await _db.Updateable(carryIts).UpdateColumns(it => new { it.is_lock, it.location_id, it.location_code }).ExecuteCommandAsync();
//更新条码的库位和仓库信息
_ = await _db.Updateable(carryCodeIts).UpdateColumns(it => new { it.warehouse_id, it.location_id, it.location_code }).Where(it => multiList.Select(x => x.carry_id).Contains(it.carry_id)).ExecuteCommandAsync();

View File

@@ -98,6 +98,7 @@ namespace Tnb.Common.Utils
}
return respJson;
}
public static async Task<string> GetRequestAsync(string url, Dictionary<string, string> pars = null)
{
Log.Information($"开始请求 {url} 请求参数: {JsonConvert.SerializeObject(pars)}");
@@ -116,23 +117,26 @@ namespace Tnb.Common.Utils
public static async Task<string> GetAsync(string url, Dictionary<string, string> headers = null, Dictionary<string, string> pars = null)
{
var reqUri = url;
if (pars?.Count > 0)
using (var client = new HttpClient())
{
reqUri = QueryHelpers.AddQueryString(url, pars);
//await Console.Out.WriteLineAsync(reqUri);
}
if (headers?.Count > 0)
{
foreach (var (k, v) in headers)
var reqUri = url;
if (pars?.Count > 0)
{
HttpClient.DefaultRequestHeaders.Add(k, v);
reqUri = QueryHelpers.AddQueryString(url, pars);
//await Console.Out.WriteLineAsync(reqUri);
}
if (headers?.Count > 0)
{
foreach (var (k, v) in headers)
{
client.DefaultRequestHeaders.Add(k, v);
}
}
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var respBody = await client.GetAsync(reqUri);
var result = await respBody.Content.ReadAsStringAsync();
return result;
}
HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var respBody = await HttpClient.GetAsync(reqUri);
var result = await respBody.Content.ReadAsStringAsync();
return result;
}