using System; using System.Data; using System.DirectoryServices.ActiveDirectory; using System.Dynamic; using System.Security.Policy; using System.Text; using Aop.Api.Domain; using Aspose.Cells.Charts; 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 NPOI.SS.Formula.Functions; 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; using Tnb.ProductionMgr.Entities; using Tnb.ProductionMgr.Entities.Dto; using Tnb.ProductionMgr.Entities.Enums; using Tnb.ProductionMgr.Interfaces; using Tnb.WarehouseMgr.Entities; using Tnb.WarehouseMgr.Entities.Configs; using Tnb.WarehouseMgr.Entities.Consts; using Tnb.WarehouseMgr.Entities.Dto; using Tnb.WarehouseMgr.Entities.Dto.Inputs; using Tnb.WarehouseMgr.Entities.Enums; using Tnb.WarehouseMgr.Interfaces; namespace Tnb.ProductionMgr { //redis定时获取数采数据 public class RedisBackGround : IHostedService, IDisposable { private Timer? Readtimer; private Timer? CheckGettimer; private Timer? Scantimer; private Timer? SSXcodetimer; // 二楼上升降机 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 _repository; private readonly IWmsPDAScanInStockService _wmsPDAScanInStock; private readonly IUserManager _userManager; private readonly IBillRullService _billRullService; private readonly IWareHouseService _wareHouseService; private readonly IWmsCarryBindService _wmsCarryBindService; private readonly ElevatorControlConfiguration _eleCtlCfg = App.Configuration.Build(); public RedisBackGround(RedisData redisData, IPrdInstockService prdInstockService, ISqlSugarRepository repository, IWmsPDAScanInStockService wmsPDAScanInStock , IUserManager userManager, IBillRullService billRullService, IWareHouseService wareHouseService, IWmsCarryBindService wmsCarryBindService) { _redisData = redisData; _prdInstockService = prdInstockService; _repository = repository; _wmsPDAScanInStock = wmsPDAScanInStock; _userManager = userManager; _billRullService = billRullService; _wareHouseService = wareHouseService; _wmsCarryBindService = wmsCarryBindService; } //获取redis数据 private void GetRedisData(object state) { var _redisReadConfigs = _repository.AsQueryable().Where(p => p.enabled == 1).ToList(); foreach (var config in _redisReadConfigs) { try { var json = _redisData.GetHash(config.dev_name!, config.tag_name!).Result; JObject? res = JsonConvert.DeserializeObject(json); if (config.data_type == (int)DataType.INT) { if (config.check_type == (int)CheckType.相等) { if (res.Value("Value") == int.Parse(config.data!)) { InstockInput instockInput = new() { equip_code = res["DevName"]!.ToString(), label_code = res["TagName"]!.ToString() }; TriggerEvent((EventType)config.event_type, instockInput); } } else if (config.check_type == (int)CheckType.包含) { int[] ints = Array.ConvertAll(config.data!.Replace("[", "").Replace("]", "").Split(",", StringSplitOptions.RemoveEmptyEntries), int.Parse); if (ints.Contains(res.Value("Value"))) { InstockInput instockInput = new() { equip_code = res["DevName"]!.ToString(), label_code = res["TagName"]!.ToString() }; TriggerEvent((EventType)config.event_type, instockInput); } } } else if (config.data_type == (int)DataType.BOOL) { if (config.check_type == (int)CheckType.相等) { if (res.Value("Value") == bool.Parse(config.data!)) { InstockInput instockInput = new() { equip_code = res["DevName"]!.ToString(), label_code = res["TagName"]!.ToString() }; TriggerEvent((EventType)config.event_type, instockInput); } } } } catch (Exception) { } } } private void TriggerEvent(EventType eventType, InstockInput instockInput) { switch (eventType) { case EventType.注塑空满箱请求: _prdInstockService.InstockTypeOne(instockInput); break; case EventType.挤出空满箱请求: _prdInstockService.InstockTubeOne(instockInput); break; case EventType.限位请求: _prdInstockService.InstockOutPack(instockInput); break; default: break; } } //ctu取货 private void CheckGet(object state) { Dictionary getdic = new Dictionary(); getdic.Add("SSX-021-005", new string[] { "YTCS", "AllowFullOut_CS05", "LiftCode" }); getdic.Add("SSX-011-002", new string[] { "YTCS", "AllowAgvFullIn_CS02", "Code_CS02" }); getdic.Add("SSX-011-004", new string[] { "YTCS", "AllowCtuFullOut_CS04", "Code_CS04" }); getdic.Add("SSX-011-008", new string[] { "东面提升机输送线", "入库输送线8允许出箱", "入库输送线7条码" }); getdic.Add("SSX-111-011", new string[] { "东面提升机输送线", "下升降机11允许出箱", "下升降机11条码" }); getdic.Add("SSX-111-012", new string[] { "东面提升机输送线", "下升降机12允许出箱", "下升降机12条码" }); getdic.Add("ZSSSXCTU02", new string[] { "YTCS", "AllowAgvEmptyOut_CS03", "" }); getdic.Add("ZSSSXCTU01", new string[] { "YTCS", "AllowAgvEmptyOut_CS01", "" }); foreach (var key in getdic.Keys) { try { var strs = getdic.Where(p => p.Key == key).First().Value; bool flag = _redisData.HashExist(strs[0], strs[1]).Result; string data = _redisData.GetHash(strs[0], strs[1]).Result; JObject? res = JsonConvert.DeserializeObject(data); bool result = res != null && res["Value"] != null ? res.Value("Value") : false; if (result) { if (!string.IsNullOrEmpty(strs[2])) { string codedata = _redisData.GetHash(strs[0], strs[2]).Result; JObject? coderes = JsonConvert.DeserializeObject(codedata); string coderesult = coderes != null && coderes["Value"] != null ? coderes.Value("Value")! : ""; coderesult = coderesult.Replace("\r", ""); var DistaskH = _repository.AsSugarClient().Queryable().Where(p => p.carry_code == coderesult && p.status == WmsWareHouseConst.TASK_BILL_STATUS_YXD_ID && string.IsNullOrEmpty(p.extras)).First(); if (DistaskH != null) { Logger.LogInformation($@"【定时任务CheckGet】 {JsonConvert.SerializeObject(DistaskH)}"); dynamic reqBody = new ExpandoObject(); reqBody.taskCode = DistaskH.bill_code; reqBody.slotCode = key; reqBody.containerCode = coderesult; CancellationTokenSource Ctu = new(); if (strs[0] == "东面提升机输送线") { Logger.LogInformation($"【定时任务CheckGet】 开始发送请求到 http://192.168.11.104:1880/wcs/notify/cargo "); } dynamic respBody = HttpClientHelper.PostStreamAsync("http://192.168.11.104:1880/wcs/notify/cargo", reqBody, Ctu.Token).Result; if (strs[0] == "东面提升机输送线") { Logger.LogInformation($"【定时任务CheckGet】 接收请求 http://192.168.11.104:1880/wcs/notify/cargo 结果 {respBody} "); } DistaskH.extras = respBody; _repository.AsSugarClient().Updateable(DistaskH).ExecuteCommand(); Ctu.Dispose(); } else { LoggerSSX.LogInformation($@"【定时任务CheckGet】 {key}->{strs[0]} {strs[2]} 采集结果:{ $@"任务执行(wms_distask_h)中找不到匹配的记录 任务执行需要存在载具编号(carry_code)为{coderesult} 且单据状态(status)为已下达(26126853976101) 且扩展字段(extras)为空的记录 select extras,* from wms_distask_h where carry_code = '{coderesult}' and status = '{WmsWareHouseConst.TASK_BILL_STATUS_YXD_ID}' " }"); } } else { var DistaskH = _repository.AsSugarClient().Queryable().Where(p => p.startlocation_code == key && p.status == WmsWareHouseConst.TASK_BILL_STATUS_YXD_ID && string.IsNullOrEmpty(p.extras)).First(); if (DistaskH != null) { dynamic reqBody = new ExpandoObject(); reqBody.taskCode = DistaskH.bill_code; reqBody.slotCode = key; reqBody.containerCode = DistaskH.carry_code; CancellationTokenSource Ctu = new(); dynamic respBody = HttpClientHelper.PostStreamAsync("http://192.168.11.104:1880/wcs/notify/cargo", reqBody, Ctu.Token).Result; DistaskH.extras = respBody; _repository.AsSugarClient().Updateable(DistaskH).ExecuteCommand(); Ctu.Dispose(); } } } } catch (Exception ex) { LoggerSSX.LogError(ex.ToString()); } } } private static readonly Dictionary s_logLevelMap = new() { [LogLevel.Debug] = "DBG", [LogLevel.Information] = "INF", [LogLevel.Warning] = "WRN", [LogLevel.Error] = "ERR", }; #region 日志 protected ILogger Logger => LoggerFactory.Create(builder => builder.AddFile($"{AppContext.BaseDirectory}/logs/custom{DateTime.Now:yyyyMMdd}.log", cfgOpts => { //cfgOpts.DateFormat = "yyyy-MM-dd HH:mm:ss.fff"; cfgOpts.MessageFormat = (logMsg) => { var logLevel = s_logLevelMap[logMsg.LogLevel]; var sb = new StringBuilder(); _ = sb.Append($"[{logLevel}] "); _ = sb.Append($"{logMsg.LogName} "); _ = sb.Append($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} "); _ = sb.Append($"#{logMsg.EventId.Id} "); _ = sb.Append(logMsg.Message + " "); _ = sb.Append(logMsg.Exception?.ToString()); return sb.ToString(); }; })).CreateLogger(this.GetType()); protected ILogger LoggerBGW => LoggerFactory.Create(builder => builder.AddFile($"{AppContext.BaseDirectory}/logs/customBGW{DateTime.Now:yyyyMMdd}.log", cfgOpts => { //cfgOpts.DateFormat = "yyyy-MM-dd HH:mm:ss.fff"; cfgOpts.MessageFormat = (logMsg) => { var logLevel = s_logLevelMap[logMsg.LogLevel]; var sb = new StringBuilder(); _ = sb.Append($"[{logLevel}] "); _ = sb.Append($"{logMsg.LogName} "); _ = sb.Append($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} "); _ = sb.Append($"#{logMsg.EventId.Id} "); _ = sb.Append(logMsg.Message + " "); _ = sb.Append(logMsg.Exception?.ToString()); return sb.ToString(); }; })).CreateLogger(this.GetType()); protected ILogger LoggerSSX => LoggerFactory.Create(builder => builder.AddFile($"{AppContext.BaseDirectory}/logs/customSSX{DateTime.Now:yyyyMMdd}.log", cfgOpts => { //cfgOpts.DateFormat = "yyyy-MM-dd HH:mm:ss.fff"; cfgOpts.MessageFormat = (logMsg) => { var logLevel = s_logLevelMap[logMsg.LogLevel]; var sb = new StringBuilder(); _ = sb.Append($"[{logLevel}] "); _ = sb.Append($"{logMsg.LogName} "); _ = sb.Append($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} "); _ = sb.Append($"#{logMsg.EventId.Id} "); _ = sb.Append(logMsg.Message + " "); _ = sb.Append(logMsg.Exception?.ToString()); return sb.ToString(); }; })).CreateLogger(this.GetType()); // 二楼上下升降机日志 protected ILogger LoggerFloor2UpDownMachine => LoggerFactory.Create(builder => builder.AddFile($"{AppContext.BaseDirectory}/logs/customFloor2UpDownMachine{DateTime.Now:yyyyMMdd}.log", cfgOpts => { //cfgOpts.DateFormat = "yyyy-MM-dd HH:mm:ss.fff"; cfgOpts.MessageFormat = (logMsg) => { var logLevel = s_logLevelMap[logMsg.LogLevel]; var sb = new StringBuilder(); _ = sb.Append($"[{logLevel}] "); _ = sb.Append($"{logMsg.LogName} "); _ = sb.Append($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} "); _ = sb.Append($"#{logMsg.EventId.Id} "); _ = sb.Append(logMsg.Message + " "); _ = sb.Append(logMsg.Exception?.ToString()); return sb.ToString(); }; })).CreateLogger(this.GetType()); // 二楼料架补充 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) => { var logLevel = s_logLevelMap[logMsg.LogLevel]; var sb = new StringBuilder(); _ = sb.Append($"[{logLevel}] "); _ = sb.Append($"{logMsg.LogName} "); _ = sb.Append($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} "); _ = sb.Append($"#{logMsg.EventId.Id} "); _ = sb.Append(logMsg.Message + " "); _ = sb.Append(logMsg.Exception?.ToString()); return sb.ToString(); }; })).CreateLogger(this.GetType()); #endregion //扫码入库 private void ScanInStock(object state) { Dictionary getdic = new Dictionary(); getdic.Add("BGWRKYCL02", new string[] { "CP8", "AllowGetFullBox1", "code1", "PutDoneEmptyBox", "false" }); getdic.Add("BGWRKYCL01", new string[] { "CP8", "AllowGetFullBox2", "code2", "PutDoneEmptyBox", "false" }); foreach (var key in getdic.Keys) { try { var strs = getdic.Where(p => p.Key == key).First().Value; bool flag = _redisData.HashExist(strs[0], strs[1]).Result; string data = _redisData.GetHash(strs[0], strs[1]).Result; JObject? res = JsonConvert.DeserializeObject(data); bool result = res != null && res["Value"] != null ? res.Value("Value") : false; if (result) { Logger.LogInformation($"【ScanInStock】 八工位 {key} AllowGetFullBox1采集到 {res["Value"]}"); Dictionary dicCommand = new(StringComparer.OrdinalIgnoreCase) { ["DevName"] = strs[0], ["token"] = _eleCtlCfg.token, ["TagName"] = strs[3], ["Value"] = strs[4], }; Logger.LogInformation($"【ScanInStock】 八工位 {key} 发送PutDoneEmptyBox指令 {_eleCtlCfg.WriteTagUrl} {JsonConvert.SerializeObject(dicCommand)}"); HttpClientHelper.GetRequestAsync(_eleCtlCfg.WriteTagUrl, dicCommand).Wait(); string codedata = _redisData.GetHash(strs[0], strs[2]).Result; Logger.LogInformation($"【ScanInStock】 八工位 {key} 获取到扫码信息: {codedata}"); JObject? coderes = JsonConvert.DeserializeObject(codedata); string coderesult = coderes != null && coderes["Value"] != null ? coderes.Value("Value")! : ""; WmsCarryH? carry = _repository.AsSugarClient().Queryable().Single(it => it.carry_code == coderesult); Logger.LogInformation($"【ScanInStock】 八工位 {key} 查找{coderesult}绑定的托盘: {JsonConvert.SerializeObject(carry)}"); if (carry != null) { if (_repository.AsSugarClient().Queryable().Where(p => p.carry_id == carry.id && p.status != WmsWareHouseConst.TASK_BILL_STATUS_COMPLE_ID ).Any()) { Logger.LogInformation($"【ScanInStock】 八工位 {key} 托盘 {carry.id} 对应的执行任务状态(status)不是26126860808229(已完成),此时不能执行入库"); continue; } var WmsCarryCode = _repository.AsSugarClient().Queryable().Where(it => it.carry_id == carry.id).OrderByDescending(it => it.id).First(); // 用适当的字段替换 YourTimestampField if (WmsCarryCode != null) { Logger.LogInformation($"【ScanInStock】 八工位 {key} 查找到托盘{carry.id}在WmsCarryCode中存在"); VisualDevModelDataCrInput input = new VisualDevModelDataCrInput(); input.data = new Dictionary(); input.data.Add("barcode", coderesult); input.data.Add("codeqty", WmsCarryCode.codeqty);//条码数量 input.data.Add("material_code", WmsCarryCode.material_code); input.data.Add("extras", key);//location_code input.data.Add("warehouse_id", "1");//TEST input.data.Add("bill_code", "");//采购收货单号 input.data.Add("code_batch", WmsCarryCode.code_batch!);//批次 input.data.Add("material_specification", WmsCarryCode.material_specification!);//规格型号 input.data.Add("container_no", WmsCarryCode.container_no!);//箱号 input.data.Add("material_id", WmsCarryCode.material_id); input.data.Add("id", null); _wmsPDAScanInStock.ScanInStockByRedis(input).Wait(); } } } } catch (Exception ex) { Logger.LogInformation($"【ScanInStock】 八工位扫到码发送入库请求发生异常:{ex}"); } } } private void SSXcode(object state) { Dictionary dic = new Dictionary(); dic.Add("东面提升机输送线", new string[] { "下升降机判断请求", "下升降机判断条码", "下升降机判断完毕", "下升降机判断结果" }); Dictionary putdic = new Dictionary(); putdic.Add("SSX-111-011", 11); putdic.Add("SSX-111-012", 12); foreach (var key in dic.Keys) { try { var strs = dic.Where(p => p.Key == key).First().Value; string dataflag = _redisData.GetHash(key, strs[0]).Result; JObject? resflag = JsonConvert.DeserializeObject(dataflag); //Logger.LogInformation($"【定时任务SSXcode】 {key}->{strs[0]} 采集结果:{resflag}"); bool re = resflag != null && resflag["Value"] != null ? resflag.Value("Value") : false; if (!re) continue; string data = _redisData.GetHash(key, strs[1]).Result; JObject? res = JsonConvert.DeserializeObject(data); //Logger.LogInformation($"【定时任务SSXcode】 {key}->{strs[1]} 采集结果:{res}"); string? result = res != null && res["Value"] != null ? res.Value("Value") : ""; if (!string.IsNullOrEmpty(result)) { if (result.Length < 5) { result = "LX" + result.Replace("\r", ""); } var DistaskH = _repository.AsSugarClient().Queryable().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 dicCommand2 = new(StringComparer.OrdinalIgnoreCase) { ["DevName"] = key, ["token"] = _eleCtlCfg.token, ["TagName"] = strs[3], ["Value"] = putdic.Keys.Contains(DistaskH.startlocation_code) ? putdic.Where(p => p.Key == DistaskH.startlocation_code).First().Value.ToString() : "13", }; HttpClientHelper.GetRequestAsync(_eleCtlCfg.WriteTagUrl, dicCommand2).Wait(); Dictionary dicCommand = new(StringComparer.OrdinalIgnoreCase) { ["DevName"] = key, ["token"] = _eleCtlCfg.token, ["TagName"] = strs[2], ["Value"] = "true", }; HttpClientHelper.GetRequestAsync(_eleCtlCfg.WriteTagUrl, dicCommand).Wait(); } else { Logger.LogInformation($"【定时任务SSXcode】DistaskH == null {_repository.AsSugarClient().Queryable().Where(p => p.carry_code == result && p.status != WmsWareHouseConst.TASK_BILL_STATUS_COMPLE_ID).OrderByDescending(p => p.create_time).ToSqlString()}"); Dictionary dicCommand2 = new(StringComparer.OrdinalIgnoreCase) { ["DevName"] = key, ["token"] = _eleCtlCfg.token, ["TagName"] = strs[3], ["Value"] = "13", }; HttpClientHelper.GetRequestAsync(_eleCtlCfg.WriteTagUrl, dicCommand2).Wait(); Dictionary dicCommand = new(StringComparer.OrdinalIgnoreCase) { ["DevName"] = key, ["token"] = _eleCtlCfg.token, ["TagName"] = strs[2], ["Value"] = "true", }; HttpClientHelper.GetRequestAsync(_eleCtlCfg.WriteTagUrl, dicCommand).Wait(); } } } catch (Exception ex) { Logger.LogInformation($"【定时任务SSXcode】发生异常 {ex}"); } } } public void Dispose() { Readtimer?.Dispose(); CheckGettimer?.Dispose(); Scantimer?.Dispose(); SSXcodetimer?.Dispose(); Floor2UpMachinecodetimer?.Dispose(); Floor2DownMachinecodetimer?.Dispose(); Floor2RackDeliverytimer.Dispose(); } #region 二楼上升降机机械臂 // 上升降机 private async void Floor2UpMachinecode(object args) { using (var db = _repository.AsSugarClient().CopyNew()) { string barcode = Floor2UpDownMachinecode_GetTag(MechanicalArmConsts.上升降机条码).ToString(); if (string.IsNullOrEmpty(barcode)) { LoggerFloor2UpDownMachine.LogError($@"【上升降机】未取到条码数据"); return; } // 读取上升降机的左右料架区配置 string[] configs = new string[2] { "二楼上升降机机械臂左", "二楼上升降机机械臂右" }; // 左右料架区配置 List WmsMechanicalArmHs = db.Queryable() .Where(r => configs.Contains(r.name) && r.agvconfirm == 1).ToList(); // 是否可以放货 if (WmsMechanicalArmHs.Count == 0) { LoggerFloor2UpDownMachine.LogWarning($@"【上升降机】目前没有可以放货的料架区(机械臂空托送到信号为false)"); 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 WmsEmptyOutstockHs = db.Queryable() .InnerJoin((a, b) => a.id == b.bill_id) .Where((a, b) => (a.location_id == "32609238573589" || a.location_id == "32609229889045") && (string.IsNullOrEmpty(a.bindrackcomplete) || 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 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().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}"); if (!result) { throw new Exception($@"【上升降机】设定升降机满托{target.stackingposition}满托数量为 {maxnum} 结果为 {result}"); } // 尝试写入空托送到信号 bool result上升降机空托送到 = await Floor2UpDownMachinecode_SetTag($"上升降机空托{target.stackingposition}送到", "true"); LoggerFloor2UpDownMachine.LogInformation($@"【送空托到上升降区】回写 上升降机空托{target.stackingposition}送到 结果为{result上升降机空托送到}"); if (!result上升降机空托送到) { return; } } else { LoggerFloor2UpDownMachine.LogError($@"【上升降机】条码{barcode}找不到绑定出库单{ckdCode}的料架区,且没有空闲的料架区可以用于绑定此出库单!"); await db.Ado.RollbackTranAsync(); return; } } //如有多个料架绑定同个出库单则取第一个未满托的料架 target = targetConfigs.First(); LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】当前条码目标料架区为 {JsonConvert.SerializeObject(target)}"); // 料架信息 WmsCarryH rack = db.Queryable().Where(r => r.id == target.rackid).ToList()[0]; // 料箱信息 WmsCarryH LX = db.Queryable().Where(r => r.carry_code == barcode).ToList()[0]; // 开始码垛 bool result_开始码垛 = await Floor2UpDownMachinecode_SetTag(MechanicalArmConsts.上升降机当前码垛位, target.stackingposition.ToString()); LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】码垛结果 {result_开始码垛}"); if (!result_开始码垛) { throw new Exception($@"【上升降机】码垛结果 {result_开始码垛}"); } // 回写料箱条码、码垛计数 await db.Updateable().SetColumns(r => new WmsMechanicalArmH { barcodes = $"{target.barcodes},{barcode}".Trim(','), stackingcount = r.stackingcount + 1, mechanicalconfirm = 1 }).Where(r => r.id == target.id).ExecuteCommandAsync(); LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】回写料箱条码、码垛计数"); // 回写出库单的剩余可绑定料架数量 await db.Updateable().SetColumns(r => new WmsEmptyOutstockH { remainbindracknum = r.remainbindracknum - 1 }).Where(r => r.id == WmsEmptyOutstockH.id).ExecuteCommandAsync(); LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】回写出库单的剩余可绑定料架数量"); // 绑定料箱到料架 CarryBindFloor2UpDownMachineInput carryBindFloor2UpDownMachineInput = new() { }; carryBindFloor2UpDownMachineInput.carry_id = target.rackid; carryBindFloor2UpDownMachineInput.carry_code= target.rackcode; carryBindFloor2UpDownMachineInput.membercarry_id = LX.id; carryBindFloor2UpDownMachineInput.membercarry_code = LX.carry_code; carryBindFloor2UpDownMachineInput.carrystd_id = rack.carrystd_id; await _wmsCarryBindService.CarryBindFloor2UpDownMachine(carryBindFloor2UpDownMachineInput); await db.Ado.CommitTranAsync(); } catch (Exception ex) { LoggerFloor2UpDownMachine.LogError(ex.ToString()); LoggerFloor2UpDownMachine.LogError(ex.StackTrace); await db.Ado.RollbackTranAsync(); } } } //private async void Floor2DownMachinecode(object args) //{ // using (var db = _repository.AsSugarClient().CopyNew()) // { // // 读取上升降机的左右料架区配置 // string[] configs = new string[2] { "二楼下升降机机械臂左", "二楼下升降机机械臂右" }; // // 左右料架区配置 // List WmsMechanicalArmHs = db.Queryable() // .Where(r => configs.Contains(r.name) && r.mechanicalconfirm == 1 && r.stackingcount < r.maxnum).ToList(); // // 是否可以放货 // if (WmsMechanicalArmHs.Count == 0) // { // //LoggerFloor2UpDownMachine.LogWarning($@"【下升降机】目前没有可以取货的料架区"); // return; // } // WmsMechanicalArmH target; // target = WmsMechanicalArmHs.First(); // // 待拆垛列表 // List WmsCarryCodes = db.Queryable() // .InnerJoin((a, b) => a.rackid == b.carry_id) // .Where(a => configs.Contains(a.name) && a.mechanicalconfirm == 1 && a.id == target.id).Select((a, b) => b).OrderBy(a => a.id).ToList(); // // 料架拆垛完成 // if (WmsCarryCodes.Count() == 0) // { // return; // } // string barcode = WmsCarryCodes[0].membercarry_code; // // 如果条码已被绑定 // if (WmsMechanicalArmHs.Where(r => !string.IsNullOrEmpty(r.barcodes) && r.barcodes.Contains(barcode)).Count() > 0) // { // LoggerFloor2UpDownMachine.LogWarning($@"【下升降机】条码{barcode}已被绑定"); // return; // } // LoggerFloor2UpDownMachine.LogInformation($@"【下升降机】扫描到有效条码 {barcode}"); // await db.Ado.BeginTranAsync(); // try // { // LoggerFloor2UpDownMachine.LogInformation($@"【下升降机】当前条码目标料架区为 {JsonConvert.SerializeObject(target)}"); // // 料架信息 // WmsCarryH rack = db.Queryable().Where(r => r.id == target.rackid).ToList()[0]; // // 料箱信息 // WmsCarryH LX = db.Queryable().Where(r => r.carry_code == barcode).ToList()[0]; // await db.Updateable().SetColumns(r => new WmsMechanicalArmH // { // barcodes = $"{target.barcodes},{barcode}".Trim(','), // stackingcount = r.stackingcount + 1 // }).Where(r => r.id == target.id).ExecuteCommandAsync(); // LoggerFloor2UpDownMachine.LogInformation($@"【下升降机】回写料箱条码、拆垛计数"); // // 解除绑定料箱到料架 // CarryBindFloor2UpDownMachineInput carryBindFloor2UpDownMachineInput = new() { }; // carryBindFloor2UpDownMachineInput.carry_id = target.rackid; // carryBindFloor2UpDownMachineInput.carry_code = target.rackcode; // carryBindFloor2UpDownMachineInput.membercarry_id = LX.id; // carryBindFloor2UpDownMachineInput.membercarry_code = LX.carry_code; // carryBindFloor2UpDownMachineInput.carrystd_id = rack.carrystd_id; // await _wmsCarryBindService.CarryUnbindFloor2UpDownMachine(carryBindFloor2UpDownMachineInput); // await db.Ado.CommitTranAsync(); // } // catch (Exception ex) // { // LoggerFloor2UpDownMachine.LogError(ex.ToString()); // LoggerFloor2UpDownMachine.LogError(ex.StackTrace); // await db.Ado.RollbackTranAsync(); // } // } //} /// /// 检查机械臂料架区信号(上升降机空托1送到) /// /// //public async Task 检查机械臂料架区信号_上升降机空托1送到() //{ // using (var db = _repository.AsSugarClient().CopyNew()) // { // string[] configs_upMachine = new string[2] { "二楼上升降机机械臂左", "二楼上升降机机械臂右" }; // // 找到AGV已到货的数据 发送机械臂送到指令 // ISugarQueryable WmsMechanicalArmHsuagar = db.Queryable() // .Where(r => r.agvconfirm == 1 && r.mechanicalconfirm == 0 && configs_upMachine.Contains(r.name)); // foreach (WmsMechanicalArmH wmsMechanicalArmH in WmsMechanicalArmHsuagar.ToList()) // { // // 尝试写入空托送到信号 // bool result上升降机空托送到 = await Floor2UpDownMachinecode_SetTag($"上升降机空托{wmsMechanicalArmH.stackingposition}送到", "true"); // LoggerFloor2UpDownMachine.LogInformation($@"【送空托到上升降区】回写 上升降机空托{wmsMechanicalArmH.stackingposition}送到 结果为{result上升降机空托送到}"); // if (!result上升降机空托送到) // { // return false; // } // // 绑定料架 // await db.Updateable().SetColumns(r => new WmsMechanicalArmH // { // mechanicalconfirm = 1 // }).Where(r => r.id == wmsMechanicalArmH.id).ExecuteCommandAsync(); // } // return true; // } //} /// /// 检查机械臂料架区信号(上升降机满托1送到) /// /// public async Task 检查机械臂料架区信号_下升降机满托1送到() { using (var db = _repository.AsSugarClient().CopyNew()) { string[] configs_upMachine = new string[2] { "二楼下升降机机械臂左", "二楼下升降机机械臂右" }; // 找到AGV已到货,没有机械臂确认的数据 ISugarQueryable WmsMechanicalArmHsuagar = db.Queryable() .Where(r => r.agvconfirm == 1 && r.mechanicalconfirm == 0 && configs_upMachine.Contains(r.name)); LoggerFloor2UpDownMachine.LogInformation($@"【检查机械臂料架区信号_下升降机满托1送到】 {WmsMechanicalArmHsuagar.Count()}"); foreach (WmsMechanicalArmH wmsMechanicalArmH in WmsMechanicalArmHsuagar.ToList()) { // 尝试写入满托送到信号 bool result上升降机空托送到 = await Floor2UpDownMachinecode_SetTag($"下升降机满托{wmsMechanicalArmH.stackingposition}送到", "true"); LoggerFloor2UpDownMachine.LogInformation($@"【送满托到下升降区】回写 下升降机满托{wmsMechanicalArmH.stackingposition}送到 结果为{result上升降机空托送到}"); if (!result上升降机空托送到) { return false; } int LXCount = db.Queryable() .Where(a => a.carry_id == wmsMechanicalArmH.rackid).Count(); bool result = await Floor2UpDownMachinecode_SetTag($"下升降机满托{wmsMechanicalArmH.stackingposition}数量", LXCount.ToString()); LoggerFloor2UpDownMachine.LogInformation($@"【送满托到下升降区】设定下升降机满托{wmsMechanicalArmH.stackingposition}满托数量为 {LXCount} 结果为 {result}"); if (!result) { throw new Exception($@"【送满托到下升降区】设定升降机满托{wmsMechanicalArmH.stackingposition}满托数量为 {LXCount} 结果为 {result}"); } // 绑定料架 await db.Updateable().SetColumns(r => new WmsMechanicalArmH { mechanicalconfirm = 1, maxnum = LXCount }).Where(r => r.id == wmsMechanicalArmH.id).ExecuteCommandAsync(); LoggerFloor2UpDownMachine.LogInformation($@"【送满托到下升降区】 料架{wmsMechanicalArmH.rackid}下的料箱开始生成预任务"); bool pretask_result = await _wareHouseService.Floor2EmptyCarryCreateZZCPretask(wmsMechanicalArmH.rackid); if (pretask_result) { LoggerFloor2UpDownMachine.LogInformation($@"【送满托到下升降区】 料架{wmsMechanicalArmH.rackid}下的料箱生成预任务完成"); } else { LoggerFloor2UpDownMachine.LogInformation($@"【送满托到下升降区】 料架{wmsMechanicalArmH.rackid}下的料箱生成预任务失败"); } } return true; } } /// /// 送空托到上升降区 /// /// public async Task 送空托到上升降区() { using (var db = _repository.AsSugarClient().CopyNew()) { string[] configs_upMachine = new string[2] { "二楼上升降机机械臂左", "二楼上升降机机械臂右" }; // 找到没有绑定料架的且库位未锁定的料架区 ISugarQueryable WmsMechanicalArmHsuagar = _repository.AsSugarClient().Queryable(). InnerJoin((a, b) => a.point_id == b.id) .InnerJoin((a, b, c) => b.location_id == c.id) .Where((a, b, c) => string.IsNullOrEmpty(a.rackcode) && c.is_lock == 0 && configs_upMachine.Contains(a.name)); List WmsMechanicalArmHs = WmsMechanicalArmHsuagar.ToList(); if (WmsMechanicalArmHs.Count() == 0) { LoggerFloor2RackDelivery.LogWarning($"【送空托到上升降区】 无需补充料架区 {WmsMechanicalArmHsuagar.ToSqlString()}"); return false; } // 料架区 foreach (WmsMechanicalArmH wmsMechanicalArmH in WmsMechanicalArmHs) { LoggerFloor2RackDelivery.LogInformation($"【送空托到上升降区】 即将补充料架区{wmsMechanicalArmH.name}"); // 找到占用且未锁定的库位上的空料架 ISugarQueryable rackStartLocations = _repository.AsSugarClient().Queryable() .InnerJoin((a, b) => a.id == b.location_id) .LeftJoin((a, b, c) => b.id == c.carry_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()}"); continue; } BasLocation startLocation = rackStartLocations.First(); List startPoints = _repository.AsSugarClient().Queryable().Where(r => r.location_id == startLocation.id).ToList(); if (startPoints.Count == 0) { LoggerFloor2RackDelivery.LogError($"【送空托到上升降区】 起始库位{startLocation.location_code}未在点位表维护对应的点位"); continue; } List endPoints = _repository.AsSugarClient().Queryable().Where(r => r.id == wmsMechanicalArmH.point_id).ToList(); if (endPoints.Count == 0) { LoggerFloor2RackDelivery.LogError($"【送空托到上升降区】 终点{wmsMechanicalArmH.point_id} {wmsMechanicalArmH.point_code}未在点位表维护对应的点位"); continue; } List wmsCarryHs = _repository.AsSugarClient().Queryable().Where(r => r.location_id == startLocation.id).ToList(); if (wmsCarryHs.Count == 0) { LoggerFloor2RackDelivery.LogError($"【送空托到上升降区】 起点{startLocation.id} {startLocation.location_code}上找不到料架"); continue; } if (wmsCarryHs.Count > 1) { LoggerFloor2RackDelivery.LogError($"【送空托到上升降区】 起点{startLocation.id} {startLocation.location_code}上存在多个料架"); continue; } // 空料架 WmsCarryH targetCarry = wmsCarryHs[0]; WmsPointH startPoint = startPoints.First(); WmsPointH endPoint = endPoints.First(); await _repository.AsSugarClient().Updateable().SetColumns(r => new BasLocation { is_lock = 1 }).Where(r => r.id == startLocation.id).ExecuteCommandAsync(); await _repository.AsSugarClient().Updateable().SetColumns(r => new BasLocation { is_lock = 1 }).Where(r => r.id == endPoint.location_id).ExecuteCommandAsync(); //await _repository.AsSugarClient().Updateable().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 points = new List(); points.Add(startPoint); points.Add(endPoint); Tuple result = await Floor2UpDownMachinecode_createPretask(points, targetCarry.id, targetCarry.carry_code); if (!result.Item1) { continue; //throw new Exception("【送空托到上升降区】 未成功生成预任务"); } } return true; } } /// /// 送满托到下升降区 /// /// public async Task 送满托到下升降区() { using (var db = _repository.AsSugarClient().CopyNew()) { string[] configs_upMachine = new string[2] { "二楼下升降机机械臂左", "二楼下升降机机械臂右" }; // 找到没有绑定料架的且点位未锁定的料架区 ISugarQueryable WmsMechanicalArmHsuagar = _repository.AsSugarClient().Queryable(). InnerJoin((a, b) => a.point_id == b.id) .InnerJoin((a, b, c) => b.location_id == c.id) .Where((a, b, c) => string.IsNullOrEmpty(a.rackcode) && c.is_lock == 0 && configs_upMachine.Contains(a.name)); List WmsMechanicalArmHs = WmsMechanicalArmHsuagar.ToList(); if (WmsMechanicalArmHs.Count() == 0) { LoggerFloor2RackDelivery.LogWarning($"【送满托到下升降区】 无需补充料架区 {WmsMechanicalArmHsuagar.ToSqlString()}"); return false; } // 料架区 foreach (WmsMechanicalArmH wmsMechanicalArmH in WmsMechanicalArmHs) { bool 下升降机请求送满托 = (bool)Floor2UpDownMachinecode_GetTag($"下升降机请求送满托{wmsMechanicalArmH.stackingposition}"); if (!下升降机请求送满托) { LoggerFloor2RackDelivery.LogWarning($"【送满托到下升降区】 料架区 {wmsMechanicalArmH.name}{wmsMechanicalArmH.stackingposition} 下升降机请求送满托{wmsMechanicalArmH.stackingposition}信号不为true"); return false; } // 找到占用且未锁定的库位上的满料架且料架中的料箱是空的 List rackStartLocations = _repository.AsSugarClient().Queryable() .InnerJoin((a, b) => a.id == b.location_id) .LeftJoin((a, b, c) => b.id == c.carry_id) // 有料箱 .LeftJoin((a, b, c, d) => c.membercarry_id == d.carry_id) .Where((a, b, c, d) => 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, b, c, d) => d.id).Select((a, b, c, d) => new // 关联载具物料明细表 { basLocation = a, WmsCarryCode_id = d.id }).ToList().GroupBy(r => r.basLocation.location_code).Select(r => { var item = r.FirstOrDefault(); // 前面通过OrderBy(d => d.id)对WmsCarryCode_id进行了排序 那么如果第一行有数据则说明存在非空料箱 if (!string.IsNullOrEmpty(item.WmsCarryCode_id)) { return new BasLocation(); } else { // 进这里说明库位下的料箱都为空 return item.basLocation; } }) // 筛选非空库位数据 .Where(r => !string.IsNullOrEmpty(r.location_code)).ToList(); if (rackStartLocations.Count() == 0) { //LoggerFloor2RackDelivery.LogWarning($"【送满托到下升降区】 暂存仓中没有可用的满料架 {rackStartLocations.ToSqlString()}"); return false; } LoggerFloor2RackDelivery.LogInformation($"【送满托到下升降区】 即将补充料架区{wmsMechanicalArmH.name}"); BasLocation startLocation = rackStartLocations.First(); List startPoints = _repository.AsSugarClient().Queryable().Where(r => r.location_id == startLocation.id).ToList(); if (startPoints.Count == 0) { LoggerFloor2RackDelivery.LogError($"【送满托到下升降区】 起始库位{startLocation.location_code}未在点位表维护对应的点位"); return false; } List endPoints = _repository.AsSugarClient().Queryable().Where(r => r.id == wmsMechanicalArmH.point_id).ToList(); if (endPoints.Count == 0) { LoggerFloor2RackDelivery.LogError($"【送满托到下升降区】 终点{wmsMechanicalArmH.point_id} {wmsMechanicalArmH.point_code}未在点位表维护对应的点位"); return false; } List wmsCarryHs = _repository.AsSugarClient().Queryable().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().SetColumns(r => new BasLocation { is_lock = 1 }).Where(r => r.id == startLocation.id).ExecuteCommandAsync(); await _repository.AsSugarClient().Updateable().SetColumns(r => new BasLocation { is_lock = 1 }).Where(r => r.id == endPoint.location_id).ExecuteCommandAsync(); //await _repository.AsSugarClient().Updateable().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 points = new List(); points.Add(startPoint); points.Add(endPoint); Tuple result = await Floor2UpDownMachinecode_createPretask(points, targetCarry.id, targetCarry.carry_code); if (!result.Item1) { throw new Exception("【送满托到下升降区】 未成功生成预任务"); } } return true; } } /// /// 移走上升降区未生成预任务且满托的料架 /// /// public async Task 移走上升降区未生成预任务且满托的料架() { using (var db = _repository.AsSugarClient().CopyNew()) { string[] configs_upMachine = new string[2] { "二楼上升降机机械臂左", "二楼上升降机机械臂右" }; // 读取上升降机的左右料架区配置 List WmsMechanicalArmHs = _repository.AsSugarClient().Queryable().Where(r => r.stackingcount == r.maxnum && r.maxnum != 0 && !string.IsNullOrEmpty(r.rackcode) && r.iscreatepretask == 0 && configs_upMachine.Contains(r.name) && r.mechanicalconfirm == 1).ToList(); foreach (WmsMechanicalArmH wmsMechanicalArmH in WmsMechanicalArmHs) { await s_taskExecuteRackDelivery.WaitAsync(); LoggerFloor2RackDelivery.LogInformation($"【移走上升降区满托的料架】 开始执行预任务生成 {wmsMechanicalArmH.point_code} {wmsMechanicalArmH.outbill} {wmsMechanicalArmH.barcodes}"); try { // 判断是否 上升降机请求取满托 bool 上升降机请求取满托 = (bool)Floor2UpDownMachinecode_GetTag($"上升降机请求取满托{wmsMechanicalArmH.stackingposition}"); LoggerFloor2RackDelivery.LogError($"【移走上升降区满托的料架】上升降机请求取满托{wmsMechanicalArmH.stackingposition} {上升降机请求取满托}"); if (!上升降机请求取满托) { return false; } await _repository.AsSugarClient().Updateable().SetColumns(r => new WmsMechanicalArmH { iscreatepretask = 1 }).Where(r => r.id == wmsMechanicalArmH.id).ExecuteCommandAsync(); List points = new List(); List startPoints = _repository.AsSugarClient().Queryable().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 rackEndLocations = _repository.AsSugarClient().Queryable() .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 endPoints = _repository.AsSugarClient().Queryable().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); // 锁住终点库位 await db.Updateable(r => new BasLocation { is_lock = 1 }).Where(r => r.id == endLocation.id).ExecuteCommandAsync(); //await db.Updateable(r => new WmsPointH //{ // is_lock = 1 //}).Where(r => r.id == endPoint.id).ExecuteCommandAsync(); LoggerFloor2RackDelivery.LogInformation($"【移走上升降区满托的料架】 开始执行预任务生成: 料架区为{wmsMechanicalArmH.name}{wmsMechanicalArmH.stackingposition} 料架为{wmsMechanicalArmH.rackcode}"); Tuple result = await Floor2UpDownMachinecode_createPretask(points, wmsMechanicalArmH.rackid, wmsMechanicalArmH.rackcode); if (!result.Item1) { throw new Exception("未成功生成预任务"); } LoggerFloor2RackDelivery.LogInformation($"【移走上升降区满托的料架】 成功生成预任务 {result.Item2}"); s_taskExecuteRackDelivery.Release(); } catch (Exception ex) { LoggerFloor2RackDelivery.LogError(ex.ToString()); LoggerFloor2RackDelivery.LogError(ex.StackTrace); } finally { s_taskExecuteRackDelivery.Release(); } } return true; } } /// /// 移走下升降区未生成预任务且空托的料架 /// /// public async Task 移走下升降区未生成预任务且空托的料架() { using (var db = _repository.AsSugarClient().CopyNew()) { string[] configs_upMachine = new string[2] { "二楼下升降机机械臂左", "二楼下升降机机械臂右" }; // 读取下升降机的左右料架区配置 List WmsMechanicalArmHs = _repository.AsSugarClient().Queryable().Where(r => !string.IsNullOrEmpty(r.rackcode) && r.iscreatepretask == 0 && configs_upMachine.Contains(r.name)).ToList(); foreach (WmsMechanicalArmH wmsMechanicalArmH in WmsMechanicalArmHs) { try { // 判断是否 上升降机请求取满托 bool 下升降机请求取空托 = (bool)Floor2UpDownMachinecode_GetTag($"下升降机请求取空托{wmsMechanicalArmH.stackingposition}"); LoggerFloor2RackDelivery.LogError($"【移走下升降区空托的料架】下升降机请求取空托{wmsMechanicalArmH.stackingposition} {下升降机请求取空托}" ); if (!下升降机请求取空托) { return false; } LoggerFloor2RackDelivery.LogInformation($"【移走下升降区空托的料架】 开始执行预任务生成 {wmsMechanicalArmH.point_code} {wmsMechanicalArmH.outbill} {wmsMechanicalArmH.barcodes}"); await _repository.AsSugarClient().Updateable().SetColumns(r => new WmsMechanicalArmH { iscreatepretask = 1 }).Where(r => r.id == wmsMechanicalArmH.id).ExecuteCommandAsync(); List points = new List(); List startPoints = _repository.AsSugarClient().Queryable().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 rackEndLocations = _repository.AsSugarClient().Queryable() .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 endPoints = _repository.AsSugarClient().Queryable().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); // 解除绑定料箱到料架 CarryBindFloor2UpDownMachineInput carryBindFloor2UpDownMachineInput = new() { }; carryBindFloor2UpDownMachineInput.carry_id = wmsMechanicalArmH.rackid; carryBindFloor2UpDownMachineInput.carry_code = wmsMechanicalArmH.rackcode; await _wmsCarryBindService.CarryUnbindFloor2UpDownMachine(carryBindFloor2UpDownMachineInput); // 锁住终点库位 await db.Updateable(r => new BasLocation { is_lock = 1 }).Where(r => r.id == endLocation.id).ExecuteCommandAsync(); //await db.Updateable(r => new WmsPointH //{ // is_lock = 1 //}).Where(r => r.id == endPoint.id).ExecuteCommandAsync(); LoggerFloor2RackDelivery.LogInformation($"【移走下升降区空托的料架】 开始执行预任务生成: 料架区为{wmsMechanicalArmH.name}{wmsMechanicalArmH.stackingposition} 料架为{wmsMechanicalArmH.rackcode}"); Tuple result = await Floor2UpDownMachinecode_createPretask(points, wmsMechanicalArmH.rackid, wmsMechanicalArmH.rackcode); if (!result.Item1) { 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(); try { // 检查机械臂料架区信号(上升降机空托1送到) //await 检查机械臂料架区信号_上升降机空托1送到(); // 检查机械臂料架区信号(下升降机满托1送到) await 检查机械臂料架区信号_下升降机满托1送到(); // 送空托到上升降区 await 送空托到上升降区(); // 送满托到下升降区 await 送满托到下升降区(); // 移走上升降区未生成预任务且满托的料架 await 移走上升降区未生成预任务且满托的料架(); // 移走下升降区未生成预任务且空托的料架 await 移走下升降区未生成预任务且空托的料架(); _ = _wareHouseService.GenTaskExecute(); } catch (Exception ex) { LoggerFloor2RackDelivery.LogError(ex.ToString()); LoggerFloor2RackDelivery.LogError(ex.StackTrace); } } // 上下升降机生成预任务(补充料架、上升降机取货到料架、上升降机满托运走,下升降机拿货到输送线、下升降机空托运走) private async Task> Floor2UpDownMachinecode_createPretask(List points, string carry_id, string carry_code) { //根据获取的路径点生成预任务,生成顺序必须预路径算法返回的起终点的顺序一致(预任务顺序) WmsPretaskH preTask = null; string bill_code = _billRullService.GetBillNumber(WmsWareHouseConst.WMS_PRETASK_H_ENCODE).GetAwaiter().GetResult(); List preTasks = points.Where(it => !it.location_id.IsNullOrEmpty()).GroupBy(g => g.area_code).Select(it => { WmsPointH? sPoint = it.FirstOrDefault(); WmsPointH? ePoint = it.LastOrDefault(); 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 = bill_code, 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(); //更新页面 //赋值签收状态 LoggerFloor2RackDelivery.LogInformation($"开始执行 GenPreTask {JsonConvert.SerializeObject(preTasks)}"); bool result = await _wareHouseService.GenPreTask(preTasks, null!); LoggerFloor2RackDelivery.LogInformation($"GenPreTask 结果 {result}"); if (result) { LoggerFloor2RackDelivery.LogInformation($"成功生成预任务:{preTasks.First().bill_code}"); return new Tuple(true, preTask); } return new Tuple(false, null); } private object Floor2UpDownMachinecode_GetTag(string tag) { string key = "东面提升机输送线"; string data = _redisData.GetHash(key, tag.ToString()).Result; if (data == null) { LoggerFloor2UpDownMachine.LogError($@"{key} {tag} 未取到数值!"); return ""; } JObject? res = JsonConvert.DeserializeObject(data); switch (typeof(T).ToString()) { case "System.Boolean": { bool result = res != null && res["Value"] != null ? res.Value("Value") : false; return result; } case "System.String": { string? result = res != null && res["Value"] != null ? res.Value("Value") : ""; return result; } } return "wrong type"; } private async Task Floor2UpDownMachinecode_SetTag(string tag, string value) { string DevName = "东面提升机输送线"; Dictionary dicCommand = new(StringComparer.OrdinalIgnoreCase) { ["DevName"] = DevName, ["token"] = _eleCtlCfg.token, ["TagName"] = tag, ["Value"] = value, }; string result = await HttpClientHelper.GetRequestAsync(_eleCtlCfg.WriteTagUrl, dicCommand); // 测试 //JObject valueJson = new JObject(); //valueJson["Value"] = value; //bool res = await _redisData.HSet(DevName, tag, valueJson.ToString()); //return true; return result.Contains("Ok"); } #endregion public Task StartAsync(CancellationToken cancellationToken) { 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)); // 二楼上升降机 Floor2UpMachinecodetimer = new Timer(Floor2UpMachinecode, 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(30)); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { return Task.CompletedTask; } } }