wms电梯设定,新增开关电梯控制接口

This commit is contained in:
yang.lee
2023-11-30 15:25:44 +08:00
parent 0fbc485cc3
commit 08888ac4c2
11 changed files with 150 additions and 66 deletions

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Tnb.WarehouseMgr.Entities.Dto.Inputs
{
public class CloseElevatorInput
{
public IEnumerable<string> devNames { get; set; }
public int value { get; set; }
public string flag{ get; set; }
}
}

View File

@@ -32,7 +32,7 @@ public partial class WmsDistaskH : BaseEntity<string>
/// <summary>
/// 起始楼层
/// </summary>
public string? start_floor { get; set; }
public int start_floor { get; set; }
/// <summary>
/// 目标库位ID
@@ -42,7 +42,7 @@ public partial class WmsDistaskH : BaseEntity<string>
/// <summary>
/// 目标楼层
/// </summary>
public string? end_floor { get; set; }
public int end_floor { get; set; }
/// <summary>
/// 起始点位ID

View File

@@ -1,4 +1,6 @@
namespace Tnb.WarehouseMgr.Interfaces
using Tnb.WarehouseMgr.Entities.Dto.Inputs;
namespace Tnb.WarehouseMgr.Interfaces
{
/// <summary>
/// 电梯控制服务接口
@@ -31,10 +33,10 @@
/// <param name="tags">标签集合</param>
/// <param name="token">取消标志</param>
/// <returns>获取到的状态值</returns>
Task<(int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus)> GetElevatorStatus(string devName,IEnumerable<string> tags, CancellationToken token);
Task<(int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus)> GetElevatorStatus(string devName, IEnumerable<string> tags, CancellationToken token);
Task<Dictionary<string,int>> GetELevatorStatusMap(string devName,IEnumerable<string> tags, CancellationToken token);
Task<Dictionary<string, int>> GetELevatorStatusMap(string devName, IEnumerable<string> tags, CancellationToken token);
/// <summary>
/// 检查Agv状态
/// </summary>
@@ -61,5 +63,7 @@
/// <returns></returns>
Task<bool> CallLift(string devName, int floor, CancellationToken cancellationToken);
Task CloseElevatorControl(CloseElevatorInput input);
}
}

View File

@@ -182,6 +182,10 @@ namespace Tnb.WarehouseMgr
{
realFloor = 3;
}
else if(floor == 1)
{
realFloor = 1;
}
return Task.FromResult(realFloor);
}

View File

@@ -200,10 +200,8 @@ namespace Tnb.WarehouseMgr
}
}
return await ToApiResult(HttpStatusCode.InternalServerError, "电梯还未开门,请重试!");
}
catch (Exception ex)
{
@@ -223,53 +221,40 @@ namespace Tnb.WarehouseMgr
try
{
Logger.Information($"任务链上报->任务链编号:{input.taskChainCode},状态:{input.status},设备ID{input.deviceID}");
/*switch (input.status)
switch (input.status)
{
case "CREATED": break;
case "ALLOCATED": break;
case "PROCESSING":
//if (await _cacheManager.GetAsync($"{input.taskChainCode}") == "任务链状态上报,上报状态PROCESSING") break;
if (input.taskChainCode.Trim().IsNullOrEmpty())
{
break;
return await ToApiResult(HttpStatusCode.InternalServerError, "请重试!");
}
List<WmsDistaskH> disTasks = await _db.Queryable<WmsDistaskH>().Where(it => it.bill_code.Contains(input.taskChainCode)).ToListAsync();
List<EqpEquipment> eps = await _db.Queryable<EqpEquipment>().Where(it => it.code.Contains(input.deviceID)).ToListAsync();
TaskExecuteUpInput taskExecuteUpInput = new()
if (disTasks == null || disTasks.Count < 1)
{
disTaskIds = disTasks.Select(x => x.id).ToList(),
EqpIds = eps.Select(x => x.id).ToList(),
};
await _wareHouseService.TaskExecute(taskExecuteUpInput); break;
Logger.Error($"根据任务链编号:{input.taskChainCode} ,未获取到任何任务");
}
if (disTasks?.Count > 0)
{
TaskExecuteUpInput taskExecuteUpInput = new()
{
disTaskIds = disTasks?.Select(x => x.id).ToList() ?? Enumerable.Empty<string>().ToList(),
EqpIds = eps?.Select(x => x.id).ToList() ?? Enumerable.Empty<string>().ToList(),
};
await _wareHouseService.TaskExecute(taskExecuteUpInput);
}
break;
case "CANCELLED": break;
case "SUCCEED": break;
case "FAILURE": break;
case "FINISHED": break;
default: break;
}*/
if (input.taskChainCode.Trim().IsNullOrEmpty())
{
return await ToApiResult(HttpStatusCode.InternalServerError, "请重试!");
}
List<WmsDistaskH> disTasks = await _db.Queryable<WmsDistaskH>().Where(it => it.bill_code.Contains(input.taskChainCode)).ToListAsync();
List<EqpEquipment> eps = await _db.Queryable<EqpEquipment>().Where(it => it.code.Contains(input.deviceID)).ToListAsync();
if (disTasks == null || disTasks.Count < 1)
{
Logger.Error($"根据任务链编号:{input.taskChainCode} ,未获取到任何任务");
}
if (disTasks?.Count > 0)
{
TaskExecuteUpInput taskExecuteUpInput = new()
{
disTaskIds = disTasks?.Select(x => x.id).ToList() ?? Enumerable.Empty<string>().ToList(),
EqpIds = eps?.Select(x => x.id).ToList() ?? Enumerable.Empty<string>().ToList(),
};
await _wareHouseService.TaskExecute(taskExecuteUpInput);
}
/*ConnectionConfigOptions opts = App.GetOptions<ConnectionConfigOptions>();

View File

@@ -4,12 +4,14 @@ using DingTalk.Api.Request;
using JNPF;
using JNPF.Common.Extension;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json.Linq;
using Tnb.Common.Extension;
using Tnb.Common.Utils;
using Tnb.WarehouseMgr.Entities.Configs;
using Tnb.WarehouseMgr.Entities.Consts;
using Tnb.WarehouseMgr.Entities.Dto.Inputs;
using Tnb.WarehouseMgr.Entities.Enums;
using Tnb.WarehouseMgr.Interfaces;
@@ -24,11 +26,14 @@ namespace Tnb.WarehouseMgr
private readonly BackgroundService _agvHeartbeatMonitor;
private static readonly Dictionary<string, Func<BackgroundService, bool>> _fetchStartedStausValue = new();
private readonly bool isFrontDoorBit = false; //是否到前门位
private readonly IServiceProvider _sp;
private readonly BackgroundService _backgudSvc;
public ElevatorControlService()
public ElevatorControlService(IServiceProvider sp, BackgroundService bgSvc)
{
_elevatorCtlCfg = App.Configuration.Build<ElevatorControlConfiguration>();
//_agvHeartbeatMonitor = agvHeartbeatMonitorService;
_sp = sp;
_backgudSvc = bgSvc;
}
/// <summary>
@@ -402,5 +407,39 @@ namespace Tnb.WarehouseMgr
}
return isSuccefuly;
}
private List<Task<dynamic>> ParallelWriteTagAsync(CloseElevatorInput input)
{
var tasks = new List<Task<dynamic>>(input.devNames.Count());
foreach (var devName in input.devNames)
{
tasks.Add(WriteTagAsync(devName, ElevatorConsts.AGVControl, input.value));
}
return tasks;
}
public async Task CloseElevatorControl(CloseElevatorInput input)
{
if (input.devNames == null || !input.devNames.Any())
{
throw new ArgumentNullException(nameof(input.devNames));
}
var tasks = ParallelWriteTagAsync(input);
await Task.WhenAll(tasks);
var timedTaskSvc = _backgudSvc as TimedTaskBackgroundService;
if (timedTaskSvc != null)
{
if (input.flag.Equals("close", StringComparison.OrdinalIgnoreCase))
{
_ = timedTaskSvc.CloseAgvHeartbeat(input.devNames);
}
else
{
_ = timedTaskSvc.OpenAgvHeartbeat(input.devNames);
}
}
}
}
}

View File

@@ -6,7 +6,8 @@ namespace Tnb.WarehouseMgr.Print
{
private const uint IMAGE_BITMAP = 0;
private const uint LR_LOADFROMFILE = 16;
private static readonly string dllPath = Path.Combine(AppContext.BaseDirectory, @"Library\x64", "Library\\x64\\Winpplb.dll");
private static readonly string winPPLBDllPath = Path.Combine(AppContext.BaseDirectory, @"Library\x64", "Library\\x64\\Winpplb.dll");
private static readonly string winPortDllPath = Path.Combine(AppContext.BaseDirectory, @"Library\x64", "Library\\x64\\WinPort.dll");
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr LoadImage(IntPtr hinst, string lpszName, uint uType,
@@ -490,7 +491,7 @@ namespace Tnb.WarehouseMgr.Print
/// 注经测试type=1E 手机不能识别type=1 手机可识别;
/// 这个 B_Prn_Barcode 函数可以列印出一个指定类型的条码 功能。
/// </remarks>
[DllImport("Library\\x64\\Winpplb.dll")]
[DllImport($"Library\\x64\\Winpplb.dll")]
public static extern int B_Prn_Barcode(int x, int y, int ori, string type, int narrow,
int width, int height, char human, string data);

View File

@@ -1,4 +1,5 @@
using System.Collections.Concurrent;
using Aop.Api.Domain;
using JNPF;
using JNPF.Common.Extension;
using JNPF.Common.Security;
@@ -26,24 +27,24 @@ namespace Tnb.WarehouseMgr
private IEventPublisher _eventPublisher = default!;
private readonly ElevatorControlConfiguration _elevatorControlConfiguration = App.Configuration.Build<ElevatorControlConfiguration>();
private readonly IServiceProvider _serviceProvider;
private readonly IHostApplicationLifetime _lifeTime;
private static List<string> s_heartbeatDevNames = new();
//private static Dictionary<string, Func<CancellationToken?, Task>> _timedFuncMap = new(StringComparer.OrdinalIgnoreCase);
public TimedTaskBackgroundService(IServiceProvider serviceProvider)
public TimedTaskBackgroundService()
{
_serviceProvider = serviceProvider;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
IsStarted = true;
s_heartbeatDevNames = _elevatorControlConfiguration.HeartbeatDevNames;
Task timedTask = Task.Run(() =>
{
_eventPublisher = App.GetRequiredService<IEventPublisher>();
//电梯Agv心跳检测
_ = TimedTask(async token =>
{
foreach (var devName in _elevatorControlConfiguration.HeartbeatDevNames)
foreach (var devName in s_heartbeatDevNames)
{
Dictionary<string, string> parameter = new()
{
@@ -56,7 +57,7 @@ namespace Tnb.WarehouseMgr
await Console.Out.WriteLineAsync($"{devName.Match(@"\d+")}#梯, 心跳检测结果:{result}");
}
}, stoppingToken, 30);
});
return timedTask;
}
@@ -144,6 +145,18 @@ namespace Tnb.WarehouseMgr
return delayTask;
}
public Task CloseAgvHeartbeat(IEnumerable<string> devNames)
{
s_heartbeatDevNames.RemoveAll(x => devNames.Contains(x));
return Task.CompletedTask;
}
public Task OpenAgvHeartbeat(IEnumerable<string> devNames)
{
s_heartbeatDevNames.AddRange(devNames);
return Task.CompletedTask;
}
}
/// <summary>
/// 自定义任务调度器,保证长任务在单独的线程中运行

View File

@@ -161,7 +161,7 @@ namespace Tnb.WarehouseMgr
List<BasLocation> items = new();
try
{
WmsInstockPolicies policy = await _db.Queryable<WmsInstockPolicies>().Where(it => it.status == 1).FirstAsync();
WmsInstockPolicies policy = await _db.CopyNew().Queryable<WmsInstockPolicies>().Where(it => it.status == 1).FirstAsync();
if (policy == null)
{
throw new AppFriendlyException("没有可用的策略", 500);
@@ -173,7 +173,7 @@ namespace Tnb.WarehouseMgr
.And(it => it.is_type == ((int)EnumLocationType.).ToString())
.And(it => it.is_use == ((int)EnumCarryStatus.).ToString())
.ToExpression();
items = await _db.Queryable<BasLocation>().Where(whereExp).OrderBy(policy.policy).ToListAsync();
items = await _db.CopyNew().Queryable<BasLocation>().Where(whereExp).OrderBy(policy.policy).ToListAsync();
}
catch (Exception)
{
@@ -238,6 +238,7 @@ namespace Tnb.WarehouseMgr
{
//获取电梯数据
List<WmsElevatorH> elevatorList = await db.Queryable<WmsElevatorH>().InnerJoin<WmsElevatorD>((a, b) => a.id == b.bill_id)
.Where((a, b) => a.enabled == 1)
.Select((a, b) => new WmsElevatorH
{
@@ -249,6 +250,7 @@ namespace Tnb.WarehouseMgr
floor = b.floor
}, true).ToListAsync();
Logger.Information($"可用电梯信息:{elevatorList.Select(e => e.elevator_code)}");
//获取所有未下发的预任务申请
@@ -416,14 +418,14 @@ namespace Tnb.WarehouseMgr
foreach (var at in agvDTTasks)
{
var ele = elevatorList.Find(x => x.location_code == at.endlocation_code);
Logger.Information($"ele.elevator_id={ele?.elevator_id}");
Logger.Information($"ele.elevator_id:{ele?.elevator_id},elevator_code:{ele.elevator_code}");
if (ele != null)
{
at.device_id = ele.elevator_id;
}
}
List<(string endlocation_code, string device_id, string id, string? start_floor)> endLocCodes = agvDTTasks
List<(string endlocation_code, string device_id, string id, int start_floor)> endLocCodes = agvDTTasks
.Select(it => (it.endlocation_code, it.device_id, it.id, it.start_floor)).ToList();
if (endLocCodes?.Count > 0)
{
@@ -475,13 +477,13 @@ namespace Tnb.WarehouseMgr
/// </summary>
/// <param name="endLocCodes"></param>
/// <returns></returns>
private async Task CallingLanding(List<(string endlocation_code, string device_id, string id, string floorNO)> endLocCodes)
private async Task CallingLanding(List<(string endlocation_code, string device_id, string id, int floorNO)> endLocCodes)
{
Logger.Information($" 开始呼梯操作.............");
Logger.Information($"电梯信息:{JsonConvert.SerializeObject(s_elevatorMap)}");
try
{
foreach ((_, string devId, string disTaskId, string floorNO) in endLocCodes)
foreach ((_, string devId, string disTaskId, int floorNO) in endLocCodes)
{
Logger.Information($"devId:{devId}");
if (!s_elevatorMap.TryGetValue(devId, out object? elevatorCode))
@@ -597,7 +599,7 @@ namespace Tnb.WarehouseMgr
} while (doorStatus != 4);
Logger.Information($"当前门状态:{doorStatus}");
int floor = await GetRealFloor(disTask.end_floor.ParseToInt());
int floor = await GetRealFloor(disTask.end_floor);
Logger.Information($"目标楼层:{floor}");
@@ -608,7 +610,7 @@ namespace Tnb.WarehouseMgr
do
{
tuple = await _elevatorControlService.GetElevatorStatus(devName,tags, CancellationToken.None);
tuple = await _elevatorControlService.GetElevatorStatus(devName, tags, CancellationToken.None);
await Task.Delay(1000);
} while (tuple.sysStatus != 3 && tuple.runStatus != 0);
@@ -986,27 +988,38 @@ namespace Tnb.WarehouseMgr
{
List<WmsRoad> roads = await _db.Queryable<WmsRoad>().Where(it => it.status == 1).ToListAsync();
List<WmsPointH> points = await LocPathCalcAlgorithms(pStartId, pEndId, roads);
Logger.Information($"points:{string.Join(",", points.Select(p => p.point_code))}");
try
{
if (points.FindAll(x => x.location_code != null && x.location_code.Contains("dt", StringComparison.OrdinalIgnoreCase))?.Count > 0)
if (points?.FindAll(x => x.location_code != null && x.location_code.Contains("dt", StringComparison.OrdinalIgnoreCase))?.Count > 0)
{
Logger.Information("包含电梯Agv任务");
//查询当前电梯点
List<WmsElevatorD> curEleDs = await _db.Queryable<WmsElevatorD>().Where(it => points.Select(x => x.id).Contains(it.point_id)).ToListAsync();
List<WmsElevatorD> curEleDs = await _db.Queryable<WmsElevatorD>().InnerJoin<WmsElevatorH>((a, b) => a.bill_id == b.id).Where((a, b) => points.Select(x => x.id).Contains(a.point_id)).ToListAsync();
Logger.Information($"curEleDs==null :{curEleDs == null},curEleDs:{string.Join(",", curEleDs.Select(x => x.bill_id))}");
//如果有电梯点,则会进行电梯的均匀分配
if (curEleDs?.Count > 0)
{
//当前电梯
WmsElevatorH curEle = await _db.Queryable<WmsElevatorH>().SingleAsync(it => it.id == curEleDs.First().bill_id && it.enabled == 1);
WmsElevatorH curEle = await _db.Queryable<WmsElevatorH>().SingleAsync(it => it.id == curEleDs.First().bill_id);
Logger.Information($"curEle==null :{curEle == null}");
//同电梯组电梯
List<WmsElevatorH> sGpEle = await _db.Queryable<WmsElevatorH>().Where(it => it.elevator_group == curEle.elevator_group && it.id != curEle.id && it.enabled == 1).ToListAsync();
if (curEle == null && sGpEle?.Count > 0)
if (curEle.enabled == 0 && (sGpEle == null || sGpEle.Count < 1))
{
throw new AppFriendlyException("电梯被禁用或未配置", 500);
}
if ((sGpEle == null || sGpEle.Count < 1) && curEle.enabled == 1)
{
return points;
}
if (sGpEle?.Count > 0 && curEle.enabled == 0)
{
return points;
}
//判断电梯组中各电梯任务数
if (curEle == null || sGpEle.FindAll(x => Math.Abs(x.task_nums - curEle.task_nums) % 2 == 1)?.Count > 0)
if (sGpEle.FindAll(x => Math.Abs(x.task_nums - curEle.task_nums) % 2 == 1)?.Count > 0)
{
List<WmsElevatorD> sGpDs = await _db.Queryable<WmsElevatorD>().Where(it => it.bill_id == sGpEle.First().id).ToListAsync();
if (sGpDs?.Count > 0)

View File

@@ -31,6 +31,7 @@ namespace Tnb.WarehouseMgr
preTask.status = WmsWareHouseConst.PRETASK_BILL_STATUS_DXF_ID;
_ = await _db.Updateable(preTask).UpdateColumns(it => it.status).ExecuteCommandAsync();
}
_ = await _db.Deleteable<WmsElevatorUnexecute>().Where(it => it.distask_id == id).ExecuteCommandAsync();
_ = await _db.Deleteable(disTask).ExecuteCommandAsync();
}

View File

@@ -20,6 +20,7 @@ namespace JNPF.API.Entry;
public class Startup : AppStartup
{
//private TimedTaskBackgroundService timedTaskSvc = new();
public void ConfigureServices(IServiceCollection services)
{
// 注册和配置Mvc和api服务
@@ -48,7 +49,7 @@ public class Startup : AppStartup
services.AddMemoryCache(); // 使用本地缓存必须添加
services.AddConfigurableOptions<CacheOptions>();
services.AddSingleton( typeof(ISingleton), typeof(RedisData));
services.AddSingleton(typeof(ISingleton), typeof(RedisData));
// 微信
services.AddSenparcGlobalServices(App.Configuration) // Senparc.CO2NET 全局注册
.AddSenparcWeixinServices(App.Configuration); // Senparc.Weixin 注册如果使用Senparc.Weixin SDK则添加
@@ -56,15 +57,18 @@ public class Startup : AppStartup
services.AddOverideVisualDev();
//定时任务
services.AddHostedService<TimedTaskBackgroundService>();
//services.AddHostedService<RedisBackGround>();
services.AddHostedService<TimedTaskBackgroundService>();
services.AddSingleton<BackgroundService, TimedTaskBackgroundService>(sp => new TimedTaskBackgroundService());
//var bgSvc = App.GetRequiredService<BackgroundService>();
//bgSvc.StartAsync(CancellationToken.None);
//services.AddHostedService<RedisBackGround>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider, IOptions<SenparcSetting> senparcSetting, IOptions<SenparcWeixinSetting> senparcWeixinSetting)
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider, IOptions<SenparcSetting> senparcSetting, IOptions<SenparcWeixinSetting> senparcWeixinSetting, IHostApplicationLifetime lifeTime)
{
// 添加状态码拦截中间件
app.UseUnifyResultStatusCodes();
@@ -113,5 +117,10 @@ public class Startup : AppStartup
bool isStartTimeJob = App.GetConfig<bool>("IsStartTimeJob");
if (isStartTimeJob)
serviceProvider.GetRequiredService<ITimeTaskService>().StartTimerJob();
}
}