using System; using WCS.BLL.Config; using WCS.BLL.DbModels; using WCS.BLL.DbModels.Task; using WCS.BLL.Manager; using WCS.DAL.Db; using WCS.DAL.DbModels; using WCS.Model; using WCS.Model.ApiModel.InOutRecord; using WCS.Model.ApiModel.OutStore; using WCS.Model.WebSocketModel; using static WCS.BLL.HardWare.WarningLight; namespace WCS.BLL.HardWare { /// /// 智能货架 /// public class SmartShelf : IShelfBase { public SmartShelf(ShelfInfo shelfInfo) { ShelfId = shelfInfo.Id; ShelfCode = shelfInfo.ShelfCode; RowCounts = shelfInfo.Rowcounts; ColumnCounts = shelfInfo.Columncounts; SetCurrentMode(TaskModeEnum.待机模式); ClientIp = shelfInfo.ClientIp; LightId = shelfInfo.LightId; WarningLight = new WarningLight() { LightId = shelfInfo.LightId }; ShelfTypeName = shelfInfo.ShelfTypeName; //初始化Module Task.Run(() => { var modules = DbHelp.db.Queryable().Where(t => t.ShelfId == ShelfId).ToList(); foreach (var module in modules) { Modules.Add(new SmartShelfModule() { ModuleId = module.Id, ModuleCode = module.ModuleCode, BoardId = module.BoardId, IsEnable = module.IsEnable, CurrentMode = module.CurrentMode }); } ModulesStr = string.Join(";", Modules.Select(t => t.ModuleCode)); ModuleIds = Modules.Select(t => t.BoardId).ToList(); }); } public int ShelfId { get; set; } public string ShelfCode { get; set; } public int RowCounts { get; set; } public int ColumnCounts { get; set; } public TaskModeEnum CurrentMode { get; set; } public DateTime SetCurrentModeTime { get; set; } public string ModulesStr { get; set; }//当前货架所有模组的Str public string GroupName { get; set; } public List Modules { get; set; } = new List(); public TCPClient TcpCleint { get { return TCPClientManager.GetTCPClientByIPHost(ClientIp); } } public int LightId { get; set; } public LightColorEnum LightColor { get; set; } public bool IsWarning { get; set; } = false; public WarningLight WarningLight { get; set; } public void ClearWarning() { if (this.CurrentMode == TaskModeEnum.入库模式) { WarningLight.BlueLight(TcpCleint); } else if (this.CurrentMode == TaskModeEnum.出库模式) { WarningLight.GreenLight(TcpCleint); } else if (this.CurrentMode == TaskModeEnum.盘点模式) { WarningLight.GreenLight(TcpCleint); } else { WarningLight.CloseLight(TcpCleint); } } /// /// 自检异常、未响应对应模式的异常 /// public List ExceptionMessages { get; set; } = new List(); /// /// 过程中异常 入库过程中异常/出库过程中异常 /// public List ProcessingExceptions { get; set; } = new List(); public string? CurrentCom { get; set; } = string.Empty; public MatInfoResponse InStoreData { get; set; } public List CurrentOutStoreMatSNs { get; set; } = new List(); public OutOrder CurrentOutOrder { get; set; } public string OrderNumber { get; set; } public StockTakingOrder CurrentStockTakingOrder { get; set; } public List ModuleIds { get; set; } public string ClientIp { get; set; } //websocket通知的前端的IP地址 public string WebSocketIpAddress { get; set; } = "127.0.0.2"; public string OutOperateUser { get; set; } = string.Empty; public List MXL4Modules { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public string ShelfTypeName { get; set; } #region 协议处理 public void GoInInstore(string? IPAddress) { try { Logs.Write($"[GoInInstore IPAddress]{IPAddress}", LogsType.Instore); if (this.CurrentMode == TaskModeEnum.入库模式) { CurrentCom = IPAddress; return; } //判断当前模式是否为待机模式 else if (this.CurrentMode != TaskModeEnum.待机模式) { return; } else { //this.CurrentMode = TaskModeEnum.入库模式; SetCurrentMode(TaskModeEnum.入库模式); } //清空错误 ExceptionMessages.Clear(); ProcessingExceptions.Clear(); this.IsWarning = false; //清空报警状态以免报警后 处理了异常后续无法亮灯 //货架所有模组发送指令进入入库模式 Logs.Write($"货架{ShelfCode}开始发送指令进入入库模式", LogsType.Instore); foreach (var module in Modules.Where(t => t.IsEnable).ToList()) { Logs.Write($"货架{ShelfCode}模组【{module.ModuleCode}】发送指令进入入库模式", LogsType.Instore); module.GoInInstoreMode(TcpCleint); } Logs.Write($"货架{ShelfCode}指令发送完毕", LogsType.Instore); //延时获取异常 var timeOut = 3000; var timeSpan = TimeSpan.FromMilliseconds(0); var beginTime = DateTime.Now; while (timeSpan <= TimeSpan.FromMilliseconds(timeOut)) { timeSpan = DateTime.Now - beginTime; //所有板子成功进入入库模式 表示进入入库模式成功,跳出循环 var isExistsNotInstore = Modules.Where(t => t.CurrentMode != TaskModeEnum.入库模式) .Where(t => t.IsEnable) .Any(); if (!isExistsNotInstore) { break; } //接收到第一个异常就不继续循环了 if (ExceptionMessages.Count() > 0) { var deficientTime = timeOut - (int)timeSpan.TotalMilliseconds; if (deficientTime > 0) Thread.Sleep(deficientTime); //出现异常的未进入入库模式,有红灯进行指引 break; } //循环延时处理 Thread.Sleep(50); } //循环结束后判断当前板子状态 var notInstoreList = Modules.Where(t => t.CurrentMode != TaskModeEnum.入库模式) .Where(t => t.IsEnable).ToList(); if (notInstoreList.Count > 0) { Logs.Write($"货架{ShelfCode}存在模组未进入入库模式", LogsType.Instore); foreach (var item in notInstoreList) { ExceptionMessages.Add($"模组{item.ModuleCode}未进入入库模式!"); } //通信校验 var messages = notInstoreList.Select(t => $"模组{t.ModuleCode}未进入入库模式!").ToList(); messages.Add("请及时联系技术人员处理!"); var exceptionMessage = string.Join("\r\n", messages); var warningModel = new WebSocketMessageModel() { IsWarning = true, WarningType = WarningTypeEnum.进入入库未响应, StoreId = 0, StoreCode = "", ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress, }; WarningManager.SendWarning(warningModel); IsWarning = true; WarningLight.WaringLightAlwaysRed(TcpCleint); } //没有报警才亮蓝灯 Logs.Write($"货架{ShelfCode},IsWarning现在为{IsWarning}", LogsType.Instore); if (!IsWarning) WarningLight.BlueLight(TcpCleint); //绑定当前进入入库PDA/WCS前端的IP CurrentCom = IPAddress; Logs.Write($"[GoInInstore CurrentCom]{CurrentCom}", LogsType.Instore); //返回成功 return; } catch (Exception ex) { GoOutInstore(); throw ex; } } public void GoOutInstore() { //当前货架是否为入库模式 if (CurrentMode != TaskModeEnum.入库模式) { return; } else { //this.CurrentMode = TaskModeEnum.待机模式; SetCurrentMode(TaskModeEnum.待机模式); } //清空错误 ExceptionMessages.Clear(); //货架所有模组发送指令退出入库模式 foreach (var module in Modules.Where(t => t.IsEnable) .ToList()) { if (module.CurrentMode == TaskModeEnum.入库模式) module.GoOutInstoreMode(TcpCleint); } var timeOut = 3000; var timeSpan = TimeSpan.FromMilliseconds(0); var beginTime = DateTime.Now; while (timeSpan <= TimeSpan.FromMilliseconds(timeOut)) { timeSpan = DateTime.Now - beginTime; //所有板子是否成功退出入库模式 var isExistsInstore = Modules.Where(t => t.CurrentMode != TaskModeEnum.待机模式) .Where(t => t.IsEnable) .Any(); if (!isExistsInstore) { break; } //循环延时处理 Thread.Sleep(50); } //循环结束后判断当前板子状态 var list = Modules.Where(t => t.CurrentMode != TaskModeEnum.待机模式) .Where(t => t.IsEnable) .ToList(); if (list.Count > 0) { //CurrentMode = TaskModeEnum.待机模式; SetCurrentMode(TaskModeEnum.待机模式); foreach (var item in list) { ExceptionMessages.Add($"模组{item.ModuleCode}未成功退出入库模式!"); } var messages = list.Select(t => $"模组{t.ModuleCode}未成功退出入库模式!").ToList(); messages.Add("请及时联系技术人员处理!"); var exceptionMessage = string.Join("\r\n", messages); var warningModel = new WebSocketMessageModel() { IsWarning = true, WarningType = WarningTypeEnum.退出入库未响应, StoreId = 0, StoreCode = "", ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress, }; WarningManager.SendWarning(warningModel); } //报警灯熄灭 WarningLight.CloseLight(TcpCleint); //通知前台货架已结束入库 Task.Run(() => { var warningModel = new WebSocketMessageModel() { IsWarning = false, WarningType = WarningTypeEnum.通知前台结束入库, StoreId = 0, StoreCode = "", ShelfCode = ShelfCode, ShelfId = ShelfId, ClientIp = WebSocketIpAddress, }; WarningManager.SendWarning(warningModel); }); } /// /// 由自检异常等错误导致的 手动操作处理后重新进入出库模式 /// /// public void GoInOutstoreByWebSocket(int moduleId) { try { Logs.Write("GoInOutstoreByWebSocket", LogsType.Outstore); //找到对应的模组 var module = Modules.Where(t => t.ModuleId == moduleId).First(); if (module == null) { Logs.Write($"GoInOutstoreByModule货架【{ShelfCode}】,未找到MouduleId为{moduleId}的模组", LogsType.Outstore); return; } //判断删除后是否还有继续需要亮灯的情况 if (module.CurrentOutSns == null || module.CurrentOutSns.Count == 0) { Logs.Write($"GoInOutstoreByModule货架【{ShelfCode}】,模组【{module.ModuleCode}】,不存在需要继续出的物料,给其复位。", LogsType.Outstore); //不需要这个模组继续亮灯了 module.GoOutOutStoreMode(TcpCleint); Thread.Sleep(400); //判断此货架是否还有出库模式的模块 #region 判断是否退出入库 是否亮下一次灯逻辑 var isExsistOut = CurrentOutStoreMatSNs.Any(); //本次亮灯的物料已全部取出 if (!isExsistOut) { Logs.Write($"货架【{ShelfCode}】,本次亮灯的物料已全部取出", LogsType.Outstore); CurrentOutOrder = null; //退出出库模式 var taskGoOut = Task.Run(() => { Thread.Sleep(10); GoOutOutstore(); }); //看是否是分批次出库的情况 分批次亮灯 Task.Run(async () => { await Task.WhenAll(taskGoOut); if (LocalFile.Config.IsSameMatCodeOut) { #region 触发下一批次的物料发料 //查一下是否是当前发料单最后一个货架(在出库模式 同一个发料单下) var isLastShelf = ShelfManager.Shelves .Where(t => t.OrderNumber == OrderNumber) .Where(t => t.CurrentMode == TaskModeEnum.出库模式) .Any(); if (!isLastShelf) { Logs.Write($"发料单{OrderNumber},最后一个出库货架,触发精准发料机制!查询是否还存在待出库物料", LogsType.Outstore); var outOrder = DbHelp.db.Queryable() .Where(t => t.OrderNumber == OrderNumber) .WhereIF(!string.IsNullOrEmpty(LocalFile.Config.GroupName), t => t.GroupName == LocalFile.Config.GroupName) .First(); if (outOrder != null) { var outOrderMatDetails = DbHelp.db.Queryable() .Where(t => t.OrderId == outOrder.Id) .Where(t => t.IsSended == false) .Includes(t => t.StoreInfo) .ToList(); if (outOrderMatDetails != null && outOrderMatDetails.Count > 0) { //相邻物料亮不同颜色 这里绿色和蓝色互相切换 LocalStatic.CurrentOutStoreColor = LocalStatic.CurrentOutStoreColor == (byte)0x02 ? (byte)0x04 : (byte)0x02; //存在待出库 然后之前又没亮灯的情况 => 继续分批次亮灯 Logs.Write($"发料单{OrderNumber},还有物料未出!", LogsType.Outstore); var outOrderDetailCount = outOrderMatDetails.GroupBy(t => t.MatCode) .Select(o => new { count = o.Count(), bb = o }) .Where(o => o.count >= 2) .OrderByDescending(o => o.count) .ToList(); //相同物料存在盘数超过2的情况,亮下一个盘数多的物料 if (outOrderDetailCount.Count > 0) { var matCode = outOrderDetailCount.First().bb.Key; outOrderMatDetails = outOrderMatDetails.Where(t => t.MatCode == matCode) .ToList(); Logs.Write($"发料单{OrderNumber},本次亮灯物料{matCode}!", LogsType.Outstore); } //相同物料不存在盘数超过n的情况,剩余物料全部亮灯 else { //剩余物料全出 Logs.Write($"发料单{OrderNumber},剩余所有物料灯全亮(发送命令)!", LogsType.Outstore); } var shelfIds = outOrderMatDetails.Select(t => t.StoreInfo.ShelfId) .Distinct() .ToList(); var shelfs = ShelfManager.Shelves.Where(t => shelfIds.Contains(t.ShelfId)).ToList(); var otherModeShelfs = shelfs.Where(t => t.CurrentMode != TaskModeEnum.待机模式).ToList(); if (otherModeShelfs != null && otherModeShelfs.Count > 0) { otherModeShelfs.ForEach(t => { t.Reset(); }); Thread.Sleep(1000); } //对应的货架对应位置 进入出库模式 亮灯 shelfs.ForEach(shelf => { var matDetails = outOrderMatDetails.Where(t => t.StoreInfo.ShelfCode == shelf.ShelfCode) .Distinct() .ToList(); shelf.GoInOutstore(matDetails, outOrder, OutOperateUser); shelf.OrderNumber = outOrder.OrderNumber; }); } else { #region 当前单据物料已发完 Logs.Write($"发料单{OrderNumber},当前物料已发完!", LogsType.Outstore); //清空发料单缓存 var outingShelfs = ShelfManager.Shelves.Where(t => t.OrderNumber == OrderNumber).ToList(); outingShelfs.ForEach(t => { t.OrderNumber = string.Empty; }); Task.Run(() => { //判断是否是当前订单最后一个出库货架 var isOuting = ShelfManager.Shelves.Where(t => t.CurrentMode == TaskModeEnum.出库模式 && t.OrderNumber == OrderNumber) .Any(); //WebSocket通知前台以更新左侧出库单列表的状态 if (!isOuting) { #region WebSocket var messageMode = new WebSocketMessageModel() { IsWarning = false, ClientIp = WebSocketIpAddress, WarningType = WarningTypeEnum.通知刷新出库单列表, }; WarningManager.SendWarning(messageMode); #endregion } }); #endregion } } else { Logs.Write($"发料单{OrderNumber},OutOrder为null,肯定是有问题", LogsType.Outstore); } } else { Logs.Write($"发料单{OrderNumber},非最后一个出库货架!", LogsType.Outstore); var otherShelfs = ShelfManager.Shelves .Where(t => t.OrderNumber == OrderNumber) .Where(t => t.CurrentMode == TaskModeEnum.出库模式) .ToList(); otherShelfs.ForEach(shelf => { try { if (shelf is SmartShelf) { var smartShelf = (SmartShelf)shelf; Logs.Write($"货架【{smartShelf.ShelfCode}】待取物料{string.Join(",", smartShelf.CurrentOutStoreMatSNs)}", LogsType.Outstore); } } catch { } }); } #endregion } else { #region 当前单据物料已发完 Logs.Write($"发料单{OrderNumber},当前物料已发完!", LogsType.Outstore); //清空发料单缓存 var outingShelfs = ShelfManager.Shelves.Where(t => t.OrderNumber == OrderNumber).ToList(); outingShelfs.ForEach(t => { t.OrderNumber = string.Empty; }); Task.Run(() => { //判断是否是当前订单最后一个出库货架 var isOuting = ShelfManager.Shelves.Where(t => t.CurrentMode == TaskModeEnum.出库模式 && t.OrderNumber == OrderNumber) .Any(); //WebSocket通知前台以更新左侧出库单列表的状态 if (!isOuting) { #region WebSocket var messageMode = new WebSocketMessageModel() { IsWarning = false, ClientIp = WebSocketIpAddress, WarningType = WarningTypeEnum.通知刷新出库单列表, }; WarningManager.SendWarning(messageMode); #endregion } }); #endregion } }); } #endregion } else { //继续亮灯 Logs.Write($"GoInOutstoreByModule货架【{ShelfCode}】,模组【{module.ModuleCode}】,存在需要继续出的物料,继续亮灯。", LogsType.Outstore); module.GoInOutStoreMode(TcpCleint, module.CurrentOutSns); Thread.Sleep(65); WarningLight.GreenLight(TcpCleint); Logs.Write("GoInOutstoreByWebSocket", LogsType.Outstore); } } catch (Exception e) { Logs.Write($"GoInOutstoreByModule货架【{ShelfCode}】进入出库模式发生异常!", LogsType.Outstore); GoOutOutstore(); throw e; } } public void GoInOutstore(List MatDetails, OutOrder outOrder, string OperateUser) { try { //第一步:设置货架当前模式 if (CurrentMode != TaskModeEnum.待机模式) { Modules.ForEach(t => { t.Reset(TcpCleint); }); //复位需要点时间间隔才能响应指令 Thread.Sleep(1500); } //CurrentMode = TaskModeEnum.出库模式; SetCurrentMode(TaskModeEnum.出库模式); //设置当前操作人 OutOperateUser = OperateUser; //第二步:货架添加需要出的SN 出库的领料单号 //移除货架所有现有待出库的MatSN CurrentOutStoreMatSNs.Clear(); ////添加属于当前货架的物料 CurrentOutStoreMatSNs.AddRange(MatDetails.Select(t => t.MatSN).ToList()); Logs.Write($"货架【{ShelfCode}】本次发料物料为{string.Join(",", CurrentOutStoreMatSNs)}!", LogsType.Outstore); ////记录当前出库的发料单 CurrentOutOrder = outOrder; ////第三步:对应的模组进入出库模式 var boardIds = MatDetails.Select(t => t.StoreInfo.BoardId) .Distinct() .OrderBy(t => t) .ToList(); var outModules = Modules.Where(t => boardIds.Contains(t.BoardId)).ToList(); outModules.ForEach(t => { var outMatSns = MatDetails.Where(mat => mat.StoreInfo.BoardId == t.BoardId) .Select(mat => mat.MatSN) .ToList(); t.GoInOutStoreMode(TcpCleint, outMatSns); Thread.Sleep(45);//出库每块板子之间增加15ms的间隔 }); Thread.Sleep(20);//报警灯在板子之后增加间隔 //所有板子亮灯后 亮警示灯 WarningLight.GreenLight(TcpCleint); Task.Run(() => { //通信校验 var timeOut = 3000; var timeSpan = TimeSpan.FromMilliseconds(0); var beginTime = DateTime.Now; while (timeSpan <= TimeSpan.FromMilliseconds(timeOut)) { timeSpan = DateTime.Now - beginTime; //所有板子成功进入出库模式 表示进入出库模式成功,跳出循环 var isExistsNotInstore = outModules.Where(t => t.CurrentMode != TaskModeEnum.出库模式) .Where(t => t.IsEnable) .Any(); if (!isExistsNotInstore) { break; } //循环延时处理 Thread.Sleep(50); } var list = outModules.Where(t => t.IsEnable && t.CurrentMode != TaskModeEnum.出库模式).ToList(); if (list != null && list.Count > 0) { var messages = list.Select(t => $"模组{t.ModuleCode}未进入出库模式!").ToList(); messages.Add("请及时联系技术人员处理!"); var exceptionMessage = string.Join("\r\n", messages); var warningModel = new WebSocketMessageModel() { IsWarning = true, WarningType = WarningTypeEnum.进入入库未响应, StoreId = 0, StoreCode = "", ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress, }; WarningManager.SendWarning(warningModel); } }); } catch (Exception e) { Logs.Write($"货架【{ShelfCode}】进入出库模式发生异常!", LogsType.Outstore); GoOutOutstore(); throw e; } } public void GoOutOutstore() { try { Logs.Write($"货架【{ShelfCode}】,开始退出出库", LogsType.Outstore); //找到在出库中的模组 var outingModules = Modules.Where(t => t.CurrentMode == TaskModeEnum.出库模式) .ToList(); foreach (var module in outingModules) { module.GoOutOutStoreMode(TcpCleint); } //通信校验 var timeOut = 3000; var timeSpan = TimeSpan.FromMilliseconds(0); var beginTime = DateTime.Now; while (timeSpan <= TimeSpan.FromMilliseconds(timeOut)) { timeSpan = DateTime.Now - beginTime; //所有板子成功退出出库模式 表示退出出库模式成功,跳出循环 var isExistsOutstore = outingModules.Where(t => t.CurrentMode == TaskModeEnum.出库模式) .Where(t => t.IsEnable) .Any(); if (!isExistsOutstore) { break; } //循环延时处理 Thread.Sleep(50); } var list = outingModules.Where(t => t.IsEnable && t.CurrentMode == TaskModeEnum.出库模式).ToList(); if (list != null && list.Count > 0) { var messages = list.Select(t => $"模组{t.ModuleCode}未退出出库模式!").ToList(); messages.Add("请及时联系技术人员处理!"); var exceptionMessage = string.Join("\r\n", messages); var warningModel = new WebSocketMessageModel() { IsWarning = true, WarningType = WarningTypeEnum.退出出库未响应, StoreId = 0, StoreCode = "", ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress, }; WarningManager.SendWarning(warningModel); } CurrentOutStoreMatSNs.Clear(); WarningLight.CloseLight(TcpCleint); SetCurrentMode(TaskModeEnum.待机模式); Logs.Write($"货架【{ShelfCode}】,结束退出出库", LogsType.Outstore); //Task.Run(() => //{ // //判断是否是当前订单最后一个出库货架 // var isOuting = ShelfManager.Shelves.Where(t => t.CurrentMode == TaskModeEnum.出库模式 && t.OrderNumber == OrderNumber) // .Any(); // //WebSocket通知前台以更新左侧出库单列表的状态 // if (!isOuting) // { // #region WebSocket // var messageMode = new WebSocketMessageModel() // { // IsWarning = false, // ClientIp = WebSocketIpAddress, // WarningType = WarningTypeEnum.通知刷新出库单列表, // }; // WarningManager.SendWarning(messageMode); // #endregion // } //}); } catch (Exception ex) { Logs.Write($"货架【{ShelfCode}】,退出出库时发生异常{ex.Message}", LogsType.Outstore); } } public void GoInStocktaking(List MatDetails, StockTakingOrder stockTakingOrder) { try { //第一步:设置货架当前模式 if (CurrentMode != TaskModeEnum.待机模式) { Modules.ForEach(t => { if (CurrentMode != TaskModeEnum.待机模式) t.Reset(TcpCleint); }); //复位需要点时间间隔才能响应指令 Thread.Sleep(1500); } //CurrentMode = TaskModeEnum.盘点模式; SetCurrentMode(TaskModeEnum.盘点模式); //第二步:货架添加 盘点单号 记录当前盘点的发料单 CurrentStockTakingOrder = stockTakingOrder; //第三步:对应的模组进入盘点模式 var boardIds = MatDetails.Select(t => t.StoreInfo.BoardId) .Distinct() .OrderBy(t => t) .ToList(); var outModules = Modules.Where(t => boardIds.Contains(t.BoardId)).ToList(); outModules.ForEach(t => { var noStockTakings = MatDetails.Where(mat => mat.StoreInfo.BoardId == t.BoardId) .Where(t => t.IsStocktaking == false) .Select(mat => mat.MatSN) .ToList(); t.GoInStockTakingMode(TcpCleint, noStockTakings); var stockTakings = MatDetails.Where(mat => mat.StoreInfo.BoardId == t.BoardId) .Where(t => t.IsStocktaking) .Select(mat => mat.MatSN) .ToList(); t.ConfirmStockTaking(TcpCleint, stockTakings); }); //所有板子亮灯后 亮警示灯 WarningLight.GreenLight(TcpCleint); Task.Run(() => { //通信校验 var timeOut = 3000; var timeSpan = TimeSpan.FromMilliseconds(0); var beginTime = DateTime.Now; while (timeSpan <= TimeSpan.FromMilliseconds(timeOut)) { timeSpan = DateTime.Now - beginTime; //所有板子成功进入盘点模式 表示进入盘点模式成功,跳出循环 var isExistsNotInstore = outModules.Where(t => t.CurrentMode != TaskModeEnum.盘点模式) .Where(t => t.IsEnable) .Any(); if (!isExistsNotInstore) { break; } //循环延时处理 Thread.Sleep(50); } var list = outModules.Where(t => t.IsEnable && t.CurrentMode != TaskModeEnum.盘点模式).ToList(); if (list != null && list.Count > 0) { var messages = list.Select(t => $"模组{t.ModuleCode}未进入盘点模式!").ToList(); messages.Add("请及时联系技术人员处理!"); var exceptionMessage = string.Join("\r\n", messages); var warningModel = new WebSocketMessageModel() { IsWarning = true, WarningType = WarningTypeEnum.进入盘点未响应, StoreId = 0, StoreCode = "", ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress, }; WarningManager.SendWarning(warningModel); } }); } catch (Exception e) { GoOutStocktaking(); throw e; } } /// /// 确认盘点 Pda进行触发 /// public bool ConfirmStocktakingSingle(int BoardId, int LightNumber) { //寻找对应模组 var module = Modules.Where(t => t.BoardId == BoardId).FirstOrDefault(); ; if (module == null) return false; else { module.ConfirmStockTakingSingle(TcpCleint, LightNumber); //报警灯闪一下 WarningLight.SuccessLightGreenEnd(TcpCleint); return true; } } public void GoOutStocktaking() { //找到在盘点中的模组 var stockTakingModules = Modules.Where(t => t.CurrentMode == TaskModeEnum.盘点模式) .ToList(); foreach (var module in stockTakingModules) { module.GoOutStockTakingMode(TcpCleint); } Task.Run(() => { //通信校验 var timeOut = 3000; var timeSpan = TimeSpan.FromMilliseconds(0); var beginTime = DateTime.Now; while (timeSpan <= TimeSpan.FromMilliseconds(timeOut)) { timeSpan = DateTime.Now - beginTime; //所有板子成功退出盘点模式 表示退出盘点模式成功,跳出循环 var isExistsNotInstore = stockTakingModules.Where(t => t.CurrentMode == TaskModeEnum.盘点模式) .Where(t => t.IsEnable) .Any(); if (!isExistsNotInstore) { break; } //循环延时处理 Thread.Sleep(50); } var list = stockTakingModules.Where(t => t.IsEnable && t.CurrentMode == TaskModeEnum.盘点模式).ToList(); if (list != null && list.Count > 0) { var messages = list.Select(t => $"模组{t.ModuleCode}未退出盘点模式!").ToList(); messages.Add("请及时联系技术人员处理!"); var exceptionMessage = string.Join("\r\n", messages); var warningModel = new WebSocketMessageModel() { IsWarning = true, WarningType = WarningTypeEnum.退出盘点未响应, StoreId = 0, StoreCode = "", ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress, }; WarningManager.SendWarning(warningModel); } }); CurrentOutStoreMatSNs.Clear(); WarningLight.CloseLight(TcpCleint); //this.CurrentMode = TaskModeEnum.待机模式; SetCurrentMode(TaskModeEnum.待机模式); } public void Reset() { var modules = Modules.Where(t => t.IsEnable).ToList(); if (modules != null && modules.Count > 0) { modules.ForEach(t => { t.Reset(TcpCleint); }); } WarningLight.CloseLight(TcpCleint); //this.CurrentMode = TaskModeEnum.待机模式; SetCurrentMode(TaskModeEnum.待机模式); } public void QueryVoltage(int moduleId) { var moudle = Modules.Where(t => t.ModuleId == moduleId).First(); if (moudle != null) { moudle.QueryVoltage(TcpCleint); } } public void CalibrationSetOffset(int moduleId, int offSet) { var moudle = Modules.Where(t => t.ModuleId == moduleId).First(); if (moudle != null) { moudle.CalibrationSetOffset(offSet, TcpCleint); } } public void SetCurrentMode(TaskModeEnum mode) { this.CurrentMode = mode; this.SetCurrentModeTime = DateTime.Now; Task.Run(() => { var shelf = DbHelp.db.Queryable().Where(t => t.Id == ShelfId).First(); if (shelf != null) { shelf.CurrentMode = mode; shelf.SetCurrentModeTime = SetCurrentModeTime; DbHelp.db.Updateable(shelf).ExecuteCommand(); } }); } void IShelfBase.Warning() { throw new NotImplementedException(); } public void ShelfCheck() { try { if (CurrentMode == TaskModeEnum.待机模式) OrderNumber = "自检中..."; foreach (var module in Modules.Where(t => t.IsEnable).ToList()) { module.IsSelfCheck = true; module.ShelfCheck(TcpCleint); } //状态校验 自检模式未响应 Task.Run(() => { var timeOut = 3000; var timeSpan = TimeSpan.FromMilliseconds(0); var beginTime = DateTime.Now; while (timeSpan <= TimeSpan.FromMilliseconds(timeOut)) { timeSpan = DateTime.Now - beginTime; //所有板子成功进入入库模式 表示进入入库模式成功,跳出循环 var isSelfChecking = Modules.Where(t => t.IsSelfCheck) .Where(t => t.IsEnable) .Any(); if (!isSelfChecking) { break; } //循环延时处理 Thread.Sleep(50); } var notReturnList = Modules.Where(t => t.IsSelfCheck) .Where(t => t.IsEnable).ToList(); if (notReturnList.Count > 0) { Logs.Write($"货架{ShelfCode}存在模组自检未响应:", LogsType.Instore); foreach (var item in notReturnList) { ExceptionMessages.Add($"模组{item.ModuleCode}未响应自检!"); } //通信校验 var messages = notReturnList.Select(t => $"模组{t.ModuleCode}({t.CurrentMode})未响应自检!").ToList(); var exceptionMessage = string.Join("\r\n", messages); var warningModel = new WebSocketMessageModel() { IsWarning = false, WarningType = WarningTypeEnum.自检未响应, StoreId = 0, StoreCode = "", ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress, }; WarningManager.SendWarning(warningModel); } }); } catch (Exception ex) { Logs.Write("自检发现异常:" + ex); } finally { if (CurrentMode == TaskModeEnum.待机模式) OrderNumber = string.Empty; } } #endregion #region 报警灯协议返回处理 public void WarningLightProcess(byte[] data, int boardId, int lightNumber) { if (data[TcpCleint.PreFixLength + 2] == 0x20 && data[TcpCleint.PreFixLength + 3] == 0x01) { //常亮或关闭 0x00常亮 0x01关闭 if (data[TcpCleint.PreFixLength + 5] == 0x00) { LightColor = LightColorEnum.关闭; Logs.Write($"货架[{ShelfCode}],灯状态更新为:{LightColor}"); } else if (data[TcpCleint.PreFixLength + 5] == 0x01) { switch (data[7]) { case 0x01: LightColor = LightColorEnum.红色; break; case 0x02: LightColor = LightColorEnum.绿色; break; case 0x03: LightColor = LightColorEnum.蓝色; break; default: break; } Logs.Write($"货架[{ShelfCode}],灯状态更新为:{LightColor}"); } } } #endregion #region 协议返回处理 public void ProtocolProcess(byte[] data, int boardId, int lightNumber) { //协议处理 判断功能位 switch (data[TcpCleint.PreFixLength + 2]) { case 0x01://进入入库模式返回信号 GoInInstoreProcess(data, boardId, lightNumber); break; case 0x02://退出入库模式返回信号 GoOutInstoreProcess(data, boardId, lightNumber); break; case 0x03://正常入库信号 InStoreReturnProcess(data); break; case 0x04://入库模式中异常信号 InStoreExceptionReturnProcess(data, boardId, lightNumber); break; case 0x05://进入出库模式返回信号 GoInOutstoreProcess(data, boardId, lightNumber); break; case 0x06://退出出库模式返回信号 GoOutOutstoreProcess(data, boardId, lightNumber); break; case 0x07://正常出库返回信号 OutstoreReturnProcess(data, boardId, lightNumber); break; case 0x08://出库模式中异常信号 OutstoreExceptionReturnProcess(data, boardId, lightNumber); break; case 0x09://进入盘点模式返回信号 GoInStockTakingReturnProcess(data, boardId, lightNumber); break; case 0x0A://退出盘点模式返回信号 GoOutStockTakingReturnProcess(data, boardId, lightNumber); break; case 0x13://复位的返回信号 ResetReturnProcess(data, boardId, lightNumber); break; case 0x17://电压值1 QueryVoltageProcess(data, boardId, lightNumber); break; case 0x18://电压值2 QueryVoltageProcess(data, boardId, lightNumber); break; case 0x19://电压值3 QueryVoltageProcess(data, boardId, lightNumber); break; case 0x0B://自检结果反馈 SelfCheckProcess(data, boardId, lightNumber); break; default: ; break; } } /// /// 进入入库模式返回信号处理 /// /// public void GoInInstoreProcess(byte[] data, int boardId, int lightNumber) { //库存物料与实际情况匹配 if (data[TcpCleint.PreFixLength + 3] == 0x01) { var module = this.Modules.Where(t => t.BoardId == boardId) .FirstOrDefault(); if (module == null) { return; } else { module.CurrentMode = TaskModeEnum.入库模式; } } //库存物料与实际情况不匹配 else if (data[TcpCleint.PreFixLength + 3] == 0x00) { var module = this.Modules.Where(t => t.BoardId == boardId).FirstOrDefault(); if (module == null) { return; } else { module.CurrentMode = TaskModeEnum.入库模式; } //获取当前板所有库位 var storeInfos = DbHelp.db.Queryable() .Where(t => t.ShelfId == ShelfId) .Where(t => t.BoardId == boardId) .ToList(); //当前板子的灯数量 var boardStoreNumber = storeInfos.Count(); List dataTemp = new List(); int index11 = 0; while (boardStoreNumber > 0) { if (boardStoreNumber >= 4) { dataTemp.AddRange(Convert.ToString(data[TcpCleint.PreFixLength + 4 + index11], 2).PadLeft(8, '0').Reverse().ToList()); boardStoreNumber = boardStoreNumber - 4; } else { dataTemp.AddRange(Convert.ToString(data[TcpCleint.PreFixLength + 4 + index11], 2).PadLeft(2 * boardStoreNumber, '0').Reverse().ToList()); boardStoreNumber = 0; } index11++; } //当前板子的灯数量 boardStoreNumber = storeInfos.Count(); for (int index = 0; index <= boardStoreNumber - 1; index++) { //当前库位异常 if (dataTemp[2 * index + 1] == '1') { if (dataTemp[2 * index] == '1') { var storeInfo = storeInfos.Where(t => t.LightNumber == index + 1).First(); if (storeInfo != null) { #region 缓存记录异常信息 ExceptionMessages.Add($"{storeInfo.StoreCode}物料{storeInfo.CurrentMatSn}丢失,库存数据已删除,请重新扫码后入库"); #endregion #region 不处理、WebSocket通知前台 var exceptionMessage = storeInfo.StoreCode + $"进入入库自检发现物料{storeInfo.CurrentMatSn}丢失,请确认是否删除?"; var warningModel = new WebSocketMessageModel() { WarningType = WarningTypeEnum.入库自检丢失, StoreId = storeInfo.Id, StoreCode = storeInfo.StoreCode, ModuleId = module.ModuleId, ModuleCode = module.ModuleCode, ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress }; WarningManager.SendWarning(warningModel); this.IsWarning = true; #endregion Logs.Write($"货架【{ShelfCode},模组{module}发现物料丢失,开始发送红灯】", LogsType.Instore); WarningLight.WaringLightAlwaysRed(TcpCleint); Logs.Write($"货架【{ShelfCode},模组{module}发现物料丢失,发送红灯完成】", LogsType.Instore); } //库位未配置、返回数据异常 else { Logs.Write($"[进入入库模式异常]板Id{boardId},库位号{index + 1}找不到对应库位!"); } } else if (dataTemp[2 * index] == '0') { var storeInfo = storeInfos.Where(t => t.LightNumber == index + 1).First(); if (storeInfo != null) { #region 缓存记录异常信息 ExceptionMessages.Add($"库位{storeInfo.StoreCode}:存在物料未扫描上架"); #endregion #region 不处理、WebSocket通知前台 var exceptionMessage = $"进入入库自检发现库位{storeInfo.StoreCode}存在物料未扫描上架,请拿下后点击【确认】消除报警"; var warningModel = new WebSocketMessageModel() { WarningType = WarningTypeEnum.入库自检未扫描上架, StoreId = storeInfo.Id, StoreCode = storeInfo.StoreCode, ModuleId = module.ModuleId, ModuleCode = module.ModuleCode, ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress }; WarningManager.SendWarning(warningModel); this.IsWarning = true; #endregion Logs.Write($"货架【{ShelfCode},模组{module}发现物料未扫描上架,开始发送红灯】", LogsType.Instore); WarningLight.WaringLightAlwaysRed(TcpCleint); Logs.Write($"货架【{ShelfCode},模组{module}发现物料未扫描上架,发送红灯完成】", LogsType.Instore); } else { Logs.Write($"[进入入库模式异常]板Id{boardId},库位号{index + 1}找不到对应库位!"); } } } } } } /// /// 退出入库模式返回信号处理 /// /// public void GoOutInstoreProcess(byte[] data, int boardId, int lightNumber) { var module = this.Modules.Where(t => t.BoardId == boardId && t.CurrentMode == TaskModeEnum.入库模式).FirstOrDefault(); if (module == null) { return; } else { module.CurrentMode = TaskModeEnum.待机模式; } } /// /// 正常入库信号 /// /// public void InStoreReturnProcess(byte[] data) { var boardId = (data[TcpCleint.PreFixLength + 0] << 8) + data[TcpCleint.PreFixLength + 1]; var number = Convert.ToInt32(data[TcpCleint.PreFixLength + 3]); var storeInfo = DbHelp.db.Queryable().Where(t => t.ShelfId == ShelfId && t.BoardId == boardId && t.LightNumber == number).First(); if (storeInfo == null) { return; } var module = this.Modules.Where(t => t.BoardId == boardId) .FirstOrDefault(); if (module == null) { return; } #region 判断是否扫码获取物料信息 //物料未扫码 if (this.InStoreData == null) { //重复给了多次信号 if (!string.IsNullOrEmpty(storeInfo.CurrentMatSn)) { module.ComfirmInstore(TcpCleint); Logs.Write($"CAN给了多次正常入库信号,防止硬件异常,返回了确认入库"); return; } else { var exceptionMessage = storeInfo.StoreCode + "入库过程中存在物料未扫描上架!"; var warningModel = new WebSocketMessageModel() { WarningType = WarningTypeEnum.入库中未扫描上架, StoreId = storeInfo.Id, StoreCode = storeInfo.StoreCode, ModuleId = module.ModuleId, ModuleCode = module.ModuleCode, ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = storeInfo.StoreCode + "入库过程中存在物料未扫描上架!", ClientIp = WebSocketIpAddress }; WarningManager.SendWarning(warningModel); module.ComfirmErrInstore(TcpCleint); WarningLight.WaringLightAlwaysRed(TcpCleint); return; } } //该位置已放置物料 else if (!string.IsNullOrEmpty(storeInfo.CurrentMatSn)) { module.ComfirmErrInstore(TcpCleint); WarningLight.WaringLightBlueEnd(TcpCleint); Logs.Write($"{storeInfo.StoreCode}该位置已放置物料!", LogsType.Instore); return; } #endregion #region 已扫码且库位未被占用 保存数据 { try { DbHelp.db.BeginTran(); //库存明细表 var inventoryDetail = new InventoryDetail { StoreCode = storeInfo.StoreCode, StoreId = storeInfo.Id, R = storeInfo.R, C = storeInfo.C, Wei = storeInfo.Wei, BigShelfCode = storeInfo.BigShelfCode, GroupName = storeInfo.GroupName, MatSN = this.InStoreData.materialBar, MatCode = this.InStoreData.materialCode, MatName = this.InStoreData.materialName, MatSpec = this.InStoreData.materialSpec, MatBatch = this.InStoreData.batchNo, MatQty = (int)this.InStoreData.materialQty, MatCustomer = this.InStoreData.customer, MatSupplier = this.InStoreData.supplier, InstoreTime = DateTime.Now, InstoreUser = this.InStoreData.InstoreUser, }; //出入库记录表 var inOutRecord = new InOutRecord() { StoreCode = storeInfo.StoreCode, StoreId = storeInfo.Id, StoreInfo = storeInfo, R = storeInfo.R, C = storeInfo.C, Wei = storeInfo.Wei, BigShelfCode = storeInfo.BigShelfCode, GroupName = storeInfo.GroupName, MatSN = this.InStoreData.materialBar, MatCode = this.InStoreData.materialCode, MatName = this.InStoreData.materialName, MatSpec = this.InStoreData.materialSpec, MatBatch = this.InStoreData.batchNo, MatQty = (int)this.InStoreData.materialQty, MatCustomer = this.InStoreData.customer, MatSupplier = this.InStoreData.supplier, OperateUser = this.InStoreData.InstoreUser, Direction = DirectionEnum.入库, }; //库位表 storeInfo.CurrentMatSn = this.InStoreData.materialBar; //保存and更新数据 DbHelp.db.Insertable(inventoryDetail).ExecuteCommand(); DbHelp.db.Insertable(inOutRecord).ExecuteCommand(); DbHelp.db.Updateable(storeInfo).ExecuteCommand(); DbHelp.db.CommitTran(); //清空扫码信息 this.InStoreData = null; //实际入库位置亮灯1S,报警灯同时进行亮绿灯并鸣叫一次提示。 Task.Run(() => { //确认入库(硬件入库位置亮灯1秒) module.ComfirmInstore(TcpCleint); //报警灯亮绿灯 鸣叫一次提示 WarningLight.SuccessLightBlueEnd(TcpCleint); }); } catch (Exception ex) { DbHelp.db.RollbackTran(); Logs.Write($"入库保存数据异常,异常信息为{ex.Message}"); //报警灯报警 WarningLight.WaringLightBlueEnd(TcpCleint); } } #endregion } /// /// 入库模式中异常处理 /// /// /// /// public void InStoreExceptionReturnProcess(byte[] data, int boardId, int lightNumber) { lightNumber = (int)data[TcpCleint.PreFixLength + 4]; var storeInfo = DbHelp.db.Queryable() .Where(t => t.ShelfId == ShelfId) .Where(t => t.BoardId == boardId && t.LightNumber == lightNumber) .First(); //库位未找到 if (storeInfo == null) { Logs.Write($"【InStoreExceptionReturnProcess】boardId:{boardId},lightNumber{lightNumber},库位未找到 ", LogsType.Instore); return; } //已放物料丢失了 物料多放了 储位恢复正常 switch (data[TcpCleint.PreFixLength + 3]) { case 0x00: { var warnings = WarningManager.Warnings.Where(t => t.IsWarning = true) .Where(t => t.ShelfId == ShelfId && t.StoreId == storeInfo.Id) .ToList(); var exceptionMessage = storeInfo.StoreCode + "恢复正常!"; var warningModel = new WebSocketMessageModel() { IsWarning = false, WarningType = WarningTypeEnum.恢复正常, StoreId = storeInfo.Id, StoreCode = storeInfo.StoreCode, ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress, SolvedGuids = warnings.Select(t => t.Guid).ToList(), }; WarningManager.SendWarning(warningModel); ProcessingExceptions.RemoveAll(t => t.BoardId == boardId); } break; case 0x01: { var exceptionMessage = storeInfo.StoreCode + "入库过程中存在物料未扫描上架!"; var warningModel = new WebSocketMessageModel() { WarningType = WarningTypeEnum.入库中未扫描上架, StoreId = storeInfo.Id, StoreCode = storeInfo.StoreCode, //ModuleId = module.ModuleId, //ModuleCode = module.ModuleCode, ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress }; WarningManager.SendWarning(warningModel); WarningLight.WaringLightAlwaysRed(TcpCleint); ProcessingExceptions.Add(new ProcessingExceptionType() { BoardId = boardId, LightNumber = lightNumber, ExceptionMessage = storeInfo.StoreCode + "入库过程中存在物料未扫描上架!" }); } break; case 0x02: { var exceptionMessage = storeInfo.StoreCode + "物料被取出!"; var warningModel = new WebSocketMessageModel() { WarningType = WarningTypeEnum.入库中异常取出, StoreId = storeInfo.Id, StoreCode = storeInfo.StoreCode, //ModuleId = module.ModuleId, //ModuleCode = module.ModuleCode, ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress }; WarningManager.SendWarning(warningModel); WarningLight.WaringLightAlwaysRed(TcpCleint); ProcessingExceptions.Add(new ProcessingExceptionType() { BoardId = boardId, LightNumber = lightNumber, ExceptionMessage = storeInfo.StoreCode + "入库过程中物料丢失!" }); } break; default: break; } } /// /// 进入出库模式协议返回 /// /// /// /// public void GoInOutstoreProcess(byte[] data, int boardId, int lightNumber) { //库存物料与实际情况匹配 if (data[TcpCleint.PreFixLength + 3] == 0x01) { var module = this.Modules.Where(t => t.BoardId == boardId) .FirstOrDefault(); if (module == null) { //TO DO 报错 return; } else { module.CurrentMode = TaskModeEnum.出库模式; } } //库存物料与实际情况不匹配 else if (data[TcpCleint.PreFixLength + 3] == 0x00) { var module = this.Modules.Where(t => t.BoardId == boardId).FirstOrDefault(); if (module == null) { //TO DO 报错 return; } else { module.CurrentMode = TaskModeEnum.出库模式; } //获取当前板所有库位 var storeInfos = DbHelp.db.Queryable() .Where(t => t.ShelfId == ShelfId) .Where(t => t.BoardId == boardId) .ToList(); //当前板子的灯数量 var boardStoreNumber = storeInfos.Count(); List dataTemp = new List(); int index11 = 0; while (boardStoreNumber > 0) { if (boardStoreNumber >= 4) { dataTemp.AddRange(Convert.ToString(data[TcpCleint.PreFixLength + 4 + index11], 2).PadLeft(8, '0').Reverse().ToList()); boardStoreNumber = boardStoreNumber - 4; } else { dataTemp.AddRange(Convert.ToString(data[TcpCleint.PreFixLength + 4 + index11], 2).PadLeft(2 * boardStoreNumber, '0').Reverse().ToList()); boardStoreNumber = 0; } index11++; } //当前板子的灯数量 boardStoreNumber = storeInfos.Count(); for (int index = 0; index <= boardStoreNumber - 1; index++) { //当前库位异常 if (dataTemp[2 * index + 1] == '1') { if (dataTemp[2 * index] == '1') { var storeInfo = storeInfos.Where(t => t.LightNumber == index + 1).First(); if (storeInfo != null) { #region 缓存记录异常信息 ExceptionMessages.Add($"{storeInfo.StoreCode}物料{storeInfo.CurrentMatSn}丢失,库存数据已删除,请重新扫码后入库"); #endregion #region 不处理、WebSocket通知前台 var exceptionMessage = storeInfo.StoreCode + $"进入出库自检发现物料{storeInfo.CurrentMatSn}丢失,请确认是否删除?"; var warningModel = new WebSocketMessageModel() { WarningType = WarningTypeEnum.出库自检丢失, StoreId = storeInfo.Id, StoreCode = storeInfo.StoreCode, ModuleId = module.ModuleId, ModuleCode = module.ModuleCode, ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress }; WarningManager.SendWarning(warningModel); #endregion WarningLight.WaringLightAlwaysRed(TcpCleint); } //库位未配置、返回数据异常 else { //Logs.Write($"[进入入库模式异常]板Id{boardIds},库位号{index + 1}找不到对应库位!"); } } else if (dataTemp[2 * index] == '0') { var storeInfo = storeInfos.Where(t => t.LightNumber == index + 1).First(); if (storeInfo != null) { #region 缓存记录异常信息 ExceptionMessages.Add($"库位{storeInfo.StoreCode}:存在物料未扫描上架"); #endregion #region 不处理、WebSocket通知前台 var exceptionMessage = $"进入出库自检发现库位{storeInfo.StoreCode}存在物料未扫描上架,请拿下后点击【确认】消除报警"; var warningModel = new WebSocketMessageModel() { WarningType = WarningTypeEnum.出库自检未扫描上架, StoreId = storeInfo.Id, StoreCode = storeInfo.StoreCode, ModuleId = module.ModuleId, ModuleCode = module.ModuleCode, ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress }; WarningManager.SendWarning(warningModel); #endregion WarningLight.WaringLightAlwaysRed(TcpCleint); } else { Logs.Write($"[进入入库模式异常]板Id{boardId},库位号{index + 1}找不到对应库位!"); } } } } } } public void OutstoreReturnProcess(byte[] data, int boardId, int lightNumber) { if (CurrentMode != TaskModeEnum.出库模式) { Logs.Write($"出库错误:{ShelfCode}该货架模式不是出库模式或盘点模式!", LogsType.Outstore); return; } lightNumber = Convert.ToInt32(data[TcpCleint.PreFixLength + 3]); var storeInfo = DbHelp.db.Queryable().Where(t => t.BoardId == boardId && t.ShelfId == ShelfId && t.LightNumber == lightNumber) .First(); if (storeInfo == null) { return; } var module = this.Modules.Where(t => t.BoardId == boardId) .FirstOrDefault(); if (module == null) { return; } //当前库位未记录MatSn if (string.IsNullOrEmpty(storeInfo.CurrentMatSn)) { //该库位是需要出库的库位,物料被多次取出or给了多个正常出库信号 Logs.Write($"该库位是需要出库的库位,物料被反复取出or给了多个正常出库信号,库位{storeInfo.StoreCode}", LogsType.Outstore); //暂不进行处理 return; } //不是本次出库需要出的物料 if (!CurrentOutStoreMatSNs.Contains(storeInfo.CurrentMatSn)) { Logs.Write($"{storeInfo.CurrentMatSn}不是本次需要出库的物料", LogsType.Outstore); //报警灯报警 WarningLight.WaringLightAlwaysRed(TcpCleint); return; } //获取当前的库存信息 var inventoryDetail = DbHelp.db.Queryable().Where(t => t.MatSN == storeInfo.CurrentMatSn).First(); if (inventoryDetail == null) { Logs.Write($"{storeInfo.CurrentMatSn}库存信息不存在", LogsType.Outstore); //报警灯报警 WarningLight.WaringLightAlwaysRed(TcpCleint); return; } //获取对应的出库单物料明细 var orderMatDetails = DbHelp.db.Queryable() .Where(t => t.OrderId == CurrentOutOrder.Id) .Where(t => t.MatSN == inventoryDetail.MatSN) .Where(t => t.IsSended == false) .First(); if (orderMatDetails == null) { Logs.Write($"{storeInfo.CurrentMatSn},OrderDetail出库明细信息不存在", LogsType.Outstore); //报警灯报警 WarningLight.WaringLightAlwaysRed(TcpCleint); return; } //当前库位的SN var matSN = storeInfo.CurrentMatSn; try { #region 校验项通过 处理出库逻辑 DbHelp.db.BeginTran(); //库存明细表 删除 ; //出入库记录表 新增 var inOutRecord = new InOutRecord() { StoreCode = storeInfo.StoreCode, StoreId = storeInfo.Id, StoreInfo = storeInfo, R = storeInfo.R, C = storeInfo.C, Wei = storeInfo.Wei, BigShelfCode = storeInfo.BigShelfCode, GroupName = storeInfo.GroupName, MatSN = inventoryDetail.MatSN, MatCode = inventoryDetail.MatCode, MatName = inventoryDetail.MatName, MatBatch = inventoryDetail.MatBatch, MatQty = inventoryDetail.MatQty, MatSpec = inventoryDetail.MatSpec, MatCustomer = inventoryDetail.MatCustomer, MatSupplier = inventoryDetail.MatSupplier, OrderNumber = orderMatDetails.OrderNumber, OperateUser = OutOperateUser, Direction = orderMatDetails.IsMXPD == false ? DirectionEnum.出库 : DirectionEnum.盘点下架, }; //库位表 修改 storeInfo.CurrentMatSn = string.Empty; //发料单物料明细表 更新为已出库 orderMatDetails.IsSended = true; //发料需求表增加数量 if (CurrentOutOrder.SyncType == SyncTypeEnum.ByMatCode) { //同步更新发料需求表已发数量 var outOrderDetail = DbHelp.db.Queryable() .Where(t => t.Id == orderMatDetails.OutOrderDetailId) .First(); if (outOrderDetail != null) { outOrderDetail.OutQty += orderMatDetails.MatQty; DbHelp.db.Updateable(outOrderDetail).ExecuteCommand(); } } //保存数据 DbHelp.db.Deleteable(inventoryDetail).ExecuteCommand(); DbHelp.db.Insertable(inOutRecord).ExecuteCommand(); DbHelp.db.Updateable(storeInfo).ExecuteCommand(); DbHelp.db.Updateable(orderMatDetails).ExecuteCommand(); DbHelp.db.CommitTran(); //报警灯同时亮绿灯并鸣叫一次提示。 WarningLight.SuccessLightGreenEnd(TcpCleint); //确认本次出库 module.ComfirmOutstore(TcpCleint, data[TcpCleint.PreFixLength + 3]); //更新时间 避免超时被自动退出 Task.Run(() => { var shelves = ShelfManager.Shelves.Where(t => t.CurrentMode == TaskModeEnum.出库模式 && t.OrderNumber == OrderNumber).ToList(); foreach (var shelf in shelves) { shelf.SetCurrentModeTime = DateTime.Now; } }); //当前柜子是否还存在未出库的 Logs.Write($"货架【{ShelfCode}】,用户取出物料{matSN}", LogsType.Outstore); CurrentOutStoreMatSNs.RemoveAll(t => t == matSN);//删除本次已出的物料SN Logs.Write($"货架【{ShelfCode}】,当前货架剩余物料{string.Join(",", CurrentOutStoreMatSNs)}", LogsType.Outstore); #endregion #region 刷新出库明细逻辑 var tempOrder = CurrentOutOrder; var isMXPD = orderMatDetails.IsMXPD == true; //通知前台刷新 Task.Run(() => { //更新订单状态 UpdateOutOrderStatus(tempOrder); var messageMode = new WebSocketMessageModel() { IsWarning = false, ClientIp = WebSocketIpAddress, WarningType = isMXPD ? WarningTypeEnum.通知刷新盟讯盘点 : WarningTypeEnum.通知刷新出库 }; WarningManager.SendWarning(messageMode); }); #endregion #region 判断是否退出入库 是否亮下一次灯逻辑 var isExsistOut = CurrentOutStoreMatSNs.Any(); //本次亮灯的物料已全部取出 if (!isExsistOut) { Logs.Write($"货架【{ShelfCode}】,本次亮灯的物料已全部取出", LogsType.Outstore); CurrentOutOrder = null; //退出出库模式 var taskGoOut = Task.Run(() => { GoOutOutstore(); }); //看是否是分批次出库的情况 分批次亮灯 Task.Run(async () => { await Task.WhenAll(taskGoOut); if (LocalFile.Config.IsSameMatCodeOut) { #region 触发下一批次的物料发料 //查一下是否是当前发料单最后一个货架(在出库模式 同一个发料单下) var isLastShelf = ShelfManager.Shelves .Where(t => t.OrderNumber == OrderNumber) .Where(t => t.CurrentMode == TaskModeEnum.出库模式) .Any(); if (!isLastShelf) { Logs.Write($"发料单{OrderNumber},最后一个出库货架,触发精准发料机制!查询是否还存在待出库物料", LogsType.Outstore); var outOrder = DbHelp.db.Queryable() .Where(t => t.OrderNumber == OrderNumber) .WhereIF(!string.IsNullOrEmpty(LocalFile.Config.GroupName), t => t.GroupName == LocalFile.Config.GroupName) .First(); if (outOrder != null) { var outOrderMatDetails = DbHelp.db.Queryable() .Where(t => t.OrderId == outOrder.Id) .Where(t => t.IsSended == false) .Includes(t => t.StoreInfo) .ToList(); if (outOrderMatDetails != null && outOrderMatDetails.Count > 0) { //相邻物料亮不同颜色 这里绿色和蓝色互相切换 LocalStatic.CurrentOutStoreColor = LocalStatic.CurrentOutStoreColor == (byte)0x02 ? (byte)0x04 : (byte)0x02; //存在待出库 然后之前又没亮灯的情况 => 继续分批次亮灯 Logs.Write($"发料单{OrderNumber},还有物料未出!", LogsType.Outstore); var outOrderDetailCount = outOrderMatDetails.GroupBy(t => t.MatCode) .Select(o => new { count = o.Count(), bb = o }) .Where(o => o.count >= 2) .OrderByDescending(o => o.count) .ToList(); //相同物料存在盘数超过2的情况,亮下一个盘数多的物料 if (outOrderDetailCount.Count > 0) { var matCode = outOrderDetailCount.First().bb.Key; outOrderMatDetails = outOrderMatDetails.Where(t => t.MatCode == matCode) .ToList(); Logs.Write($"发料单{OrderNumber},本次亮灯物料{matCode}!", LogsType.Outstore); } //相同物料不存在盘数超过n的情况,剩余物料全部亮灯 else { //剩余物料全出 Logs.Write($"发料单{OrderNumber},剩余所有物料灯全亮(发送命令)!", LogsType.Outstore); } var shelfIds = outOrderMatDetails.Select(t => t.StoreInfo.ShelfId) .Distinct() .ToList(); var shelfs = ShelfManager.Shelves.Where(t => shelfIds.Contains(t.ShelfId)).ToList(); var otherModeShelfs = shelfs.Where(t => t.CurrentMode != TaskModeEnum.待机模式).ToList(); if (otherModeShelfs != null && otherModeShelfs.Count > 0) { otherModeShelfs.ForEach(t => { t.Reset(); }); Thread.Sleep(1000); } //对应的货架对应位置 进入出库模式 亮灯 shelfs.ForEach(shelf => { var matDetails = outOrderMatDetails.Where(t => t.StoreInfo.ShelfCode == shelf.ShelfCode) .Distinct() .ToList(); shelf.GoInOutstore(matDetails, outOrder, OutOperateUser); shelf.OrderNumber = outOrder.OrderNumber; }); } else { Logs.Write($"发料单{OrderNumber},当前物料已发完!", LogsType.Outstore); //清空发料单缓存 var outingShelfs = ShelfManager.Shelves.Where(t => t.OrderNumber == OrderNumber).ToList(); outingShelfs.ForEach(t => { t.OrderNumber = string.Empty; }); Task.Run(() => { //判断是否是当前订单最后一个出库货架 var isOuting = ShelfManager.Shelves.Where(t => t.CurrentMode == TaskModeEnum.出库模式 && t.OrderNumber == OrderNumber) .Any(); //WebSocket通知前台以更新左侧出库单列表的状态 if (!isOuting) { #region WebSocket var messageMode = new WebSocketMessageModel() { IsWarning = false, ClientIp = WebSocketIpAddress, WarningType = WarningTypeEnum.通知刷新出库单列表, }; WarningManager.SendWarning(messageMode); #endregion } }); } } else { Logs.Write($"发料单{OrderNumber},OutOrder为null,肯定是有问题", LogsType.Outstore); } } else { Logs.Write($"发料单{OrderNumber},非最后一个出库货架!", LogsType.Outstore); var otherShelfs = ShelfManager.Shelves .Where(t => t.OrderNumber == OrderNumber) .Where(t => t.CurrentMode == TaskModeEnum.出库模式) .ToList(); otherShelfs.ForEach(shelf => { try { if (shelf is SmartShelf) { var smartShelf = (SmartShelf)shelf; Logs.Write($"货架【{smartShelf.ShelfCode}】待取物料{string.Join(",", smartShelf.CurrentOutStoreMatSNs)}", LogsType.Outstore); } } catch { } }); } #endregion } else { //清空发料单缓存 var outingShelfs = ShelfManager.Shelves.Where(t => t.OrderNumber == OrderNumber).ToList(); outingShelfs.ForEach(t => { t.OrderNumber = string.Empty; }); Task.Run(() => { //判断是否是当前订单最后一个出库货架 var isOuting = ShelfManager.Shelves.Where(t => t.CurrentMode == TaskModeEnum.出库模式 && t.OrderNumber == OrderNumber) .Any(); //WebSocket通知前台以更新左侧出库单列表的状态 if (!isOuting) { #region WebSocket var messageMode = new WebSocketMessageModel() { IsWarning = false, ClientIp = WebSocketIpAddress, WarningType = WarningTypeEnum.通知刷新出库单列表, }; WarningManager.SendWarning(messageMode); #endregion } }); } }); } #endregion } catch (Exception ex) { DbHelp.db.RollbackTran(); //报警灯报警 WarningLight.WaringLightAlwaysRed(TcpCleint); } } public void UpdateOutOrderStatus(OutOrder order) { //再去获取一遍Order order = DbHelp.db.Queryable() .Where(t => t.Id == order.Id) .First(); if (order != null) { #region 物料明细表是否已发完 var orderMatDetails = DbHelp.db.Queryable() .Where(t => t.OrderId == order.Id) .ToList(); var isExistNoSendMat = orderMatDetails.Where(t => t.IsSended == false) .Any(); if (isExistNoSendMat) { order.OrderStatus = OutOrderStatus.部分发料; } else { order.OrderStatus = OutOrderStatus.全部发料; order.OutOrderExeStatus = OutOrderExeStatus.发料完成; } #endregion #region 单据明细是否已满足发料需求 if (order.OrderStatus == OutOrderStatus.全部发料 && order.SyncType == SyncTypeEnum.ByMatCode) { var orderDetails = DbHelp.db.Queryable() .Where(t => t.OrderId == order.Id) .ToList(); var isExistNoSend = orderDetails.Where(t => t.ReqQty > t.OutQty).Any(); if (isExistNoSend) { order.OrderStatus = OutOrderStatus.部分发料; } else { order.OrderStatus = OutOrderStatus.全部发料; } } #endregion DbHelp.db.Updateable(order).ExecuteCommand(); } } /// /// 退出出库模式返回信号处理 /// /// public void GoOutOutstoreProcess(byte[] data, int boardId, int lightNumber) { var module = this.Modules.Where(t => t.BoardId == boardId && t.CurrentMode == TaskModeEnum.出库模式).FirstOrDefault(); if (module == null) { return; } else { module.CurrentMode = TaskModeEnum.待机模式; } } /// /// 出库模式中异常处理 /// /// /// /// public void OutstoreExceptionReturnProcess(byte[] data, int boardId, int lightNumber) { lightNumber = (int)data[TcpCleint.PreFixLength + 4]; var storeInfo = DbHelp.db.Queryable() .Where(t => t.ShelfId == ShelfId) .Where(t => t.BoardId == boardId && t.LightNumber == lightNumber) .First(); if (storeInfo == null) { Logs.Write($"[OutstoreExceptionReturnProcess]boardId{boardId};lightNumber{lightNumber}库位未找到!", LogsType.Outstore); return; } //已放物料丢失了 物料多放了 储位恢复正常 switch (data[TcpCleint.PreFixLength + 3]) { case 0x00: { //对应的异常 var warnings = WarningManager.Warnings.Where(t => t.IsWarning = true) .Where(t => t.ShelfId == ShelfId && t.StoreId == storeInfo.Id) .ToList(); var exceptionMessage = storeInfo.StoreCode + "恢复正常!"; var warningModel = new WebSocketMessageModel() { IsWarning = false, WarningType = WarningTypeEnum.恢复正常, StoreId = storeInfo.Id, StoreCode = storeInfo.StoreCode, ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress, SolvedGuids = warnings.Select(t => t.Guid).ToList(), }; WarningManager.SendWarning(warningModel); ProcessingExceptions.RemoveAll(t => t.BoardId == boardId); } break; case 0x01: { var exceptionMessage = storeInfo.StoreCode + "出库过程中存在物料上架!"; var warningModel = new WebSocketMessageModel() { WarningType = WarningTypeEnum.出库中未扫描上架, StoreId = storeInfo.Id, StoreCode = storeInfo.StoreCode, ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress, }; WarningManager.SendWarning(warningModel); WarningLight.WaringLightAlwaysRed(TcpCleint); ProcessingExceptions.Add(new ProcessingExceptionType() { BoardId = boardId, LightNumber = lightNumber, ExceptionMessage = storeInfo.StoreCode + "出库过程中存在物料上架!" }); } break; case 0x02: { var exceptionMessage = storeInfo.StoreCode + "物料被取出!"; var warningModel = new WebSocketMessageModel() { WarningType = WarningTypeEnum.出库中丢失, StoreId = storeInfo.Id, StoreCode = storeInfo.StoreCode, //ModuleId = module.ModuleId, //ModuleCode = module.ModuleCode, ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress }; WarningManager.SendWarning(warningModel); WarningLight.WaringLightAlwaysRed(TcpCleint); ProcessingExceptions.Add(new ProcessingExceptionType() { BoardId = boardId, LightNumber = lightNumber, ExceptionMessage = storeInfo.StoreCode + "出库过程中物料被异常取出!" }); } break; default: break; } } /// /// 进入盘点模式返回信号 /// /// /// /// public void GoInStockTakingReturnProcess(byte[] data, int boardId, int lightNumber) { var module = this.Modules.Where(t => t.BoardId == boardId).FirstOrDefault(); if (module == null) { return; } else { module.CurrentMode = TaskModeEnum.盘点模式; } } public void GoOutStockTakingReturnProcess(byte[] data, int boardId, int lightNumber) { var module = this.Modules.Where(t => t.BoardId == boardId && t.CurrentMode == TaskModeEnum.盘点模式).FirstOrDefault(); if (module == null) { return; } else { module.CurrentMode = TaskModeEnum.待机模式; } } public void ResetReturnProcess(byte[] data, int boardId, int lightNumber) { var module = this.Modules .Where(t => t.BoardId == boardId) .FirstOrDefault(); if (module == null) { return; } else { module.CurrentMode = TaskModeEnum.待机模式; } } public void QueryVoltageProcess(byte[] data, int boardId, int lightNumber) { //第n帧 var n = (int)data[TcpCleint.PreFixLength + 3]; var voltage1 = (data[TcpCleint.PreFixLength + 4] << 8) + data[TcpCleint.PreFixLength + 5]; var voltage2 = (data[TcpCleint.PreFixLength + 6] << 8) + data[TcpCleint.PreFixLength + 7]; var voltage3 = (data[TcpCleint.PreFixLength + 8] << 8) + data[TcpCleint.PreFixLength + 9]; var number1 = (n - 1) * 3 + 1; var number2 = (n - 1) * 3 + 2; var number3 = (n - 1) * 3 + 3; if (number1 <= 16) { var storeInfo1 = DbHelp.db.Queryable() .Where(t => t.BoardId == boardId && t.LightNumber == number1 && t.ShelfId == ShelfId) .First(); if (storeInfo1 != null) { if (data[TcpCleint.PreFixLength + 2] == 0x17) storeInfo1.CurrentVoltage = voltage1; else if (data[TcpCleint.PreFixLength + 2] == 0x18) storeInfo1.OffsetVoltage = voltage1; else storeInfo1.StandardVoltage = voltage1; DbHelp.db.Updateable(storeInfo1).ExecuteCommand(); } } if (number2 <= 16) { var storeInfo2 = DbHelp.db.Queryable() .Where(t => t.BoardId == boardId && t.LightNumber == number2 && t.ShelfId == ShelfId) .First(); if (storeInfo2 != null) { if (data[TcpCleint.PreFixLength + 2] == 0x17) storeInfo2.CurrentVoltage = voltage2; else if (data[TcpCleint.PreFixLength + 2] == 0x18) storeInfo2.OffsetVoltage = voltage2; else storeInfo2.StandardVoltage = voltage2; DbHelp.db.Updateable(storeInfo2).ExecuteCommand(); } } if (number1 <= 16) { var storeInfo3 = DbHelp.db.Queryable() .Where(t => t.BoardId == boardId && t.LightNumber == number3 && t.ShelfId == ShelfId) .First(); if (storeInfo3 != null) { if (data[TcpCleint.PreFixLength + 2] == 0x17) storeInfo3.CurrentVoltage = voltage3; else if (data[TcpCleint.PreFixLength + 2] == 0x18) storeInfo3.OffsetVoltage = voltage3; else storeInfo3.StandardVoltage = voltage3; DbHelp.db.Updateable(storeInfo3).ExecuteCommand(); } } } public void SelfCheckProcess(byte[] data, int boardId, int lightNumber) { var module = this.Modules.Where(t => t.BoardId == boardId).FirstOrDefault(); if (module == null) { return; } else { module.IsSelfCheck = false; } if (data[TcpCleint.PreFixLength + 3] == 0x01) { //比对结果相同 } //比对结果不同 else if (data[TcpCleint.PreFixLength + 3] == 0x00) { //获取当前板所有库位 var storeInfos = DbHelp.db.Queryable() .Where(t => t.BoardId == boardId && t.ShelfId == ShelfId) .ToList(); //当前设置的板库位数 var boardStoreNumber = storeInfos.Count(); List dataTemp = new List(); int index11 = 0; while (boardStoreNumber > 0) { if (boardStoreNumber >= 4) { dataTemp.AddRange(Convert.ToString(data[TcpCleint.PreFixLength + 4 + index11], 2).PadLeft(8, '0').Reverse().ToList()); boardStoreNumber = boardStoreNumber - 4; } else { dataTemp.AddRange(Convert.ToString(data[TcpCleint.PreFixLength + 4 + index11], 2).PadLeft(2 * boardStoreNumber, '0').Reverse().ToList()); boardStoreNumber = 0; } index11++; } boardStoreNumber = storeInfos.Count(); for (int index = 0; index <= boardStoreNumber - 1; index++) { //当前库位异常 if (dataTemp[2 * index + 1] == '1') { if (dataTemp[2 * index] == '1') { var storeInfo = storeInfos.Where(t => t.LightNumber == index + 1).First(); if (storeInfo != null) { #region 不处理、WebSocket通知前台 var exceptionMessage = storeInfo.StoreCode + $"自检发现物料{storeInfo.CurrentMatSn}丢失,请确认是否删除?"; var warningModel = new WebSocketMessageModel() { WarningType = WarningTypeEnum.自检丢失, StoreId = storeInfo.Id, StoreCode = storeInfo.StoreCode, ModuleId = storeInfo.ModuleId, ModuleCode = storeInfo.ModuleCode, ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress }; WarningManager.SendWarning(warningModel); #endregion IsWarning = true; Logs.Write($"货架自检【{ShelfCode},库位{storeInfo.StoreCode}发现物料丢失,开始发送红灯】", LogsType.Instore); WarningLight.WaringLightAlwaysRed(TcpCleint); Logs.Write($"货架自检【{ShelfCode},库位{storeInfo.StoreCode}发现物料丢失,发送红灯完成】", LogsType.Instore); } //库位未配置、返回数据异常 else { Logs.Write($"[进入入库模式异常]板Id{boardId},库位号{index + 1}找不到对应库位!"); } } else if (dataTemp[2 * index] == '0') { var storeInfo = storeInfos.Where(t => t.LightNumber == index + 1).First(); if (storeInfo != null) { #region 不处理、WebSocket通知前台 var exceptionMessage = $"自检发现库位{storeInfo.StoreCode}存在物料未扫描上架,请拿下后点击【确认】消除报警"; var warningModel = new WebSocketMessageModel() { WarningType = WarningTypeEnum.自检未扫描上架, StoreId = storeInfo.Id, StoreCode = storeInfo.StoreCode, ModuleId = storeInfo.ModuleId, ModuleCode = storeInfo.ModuleCode, ShelfCode = ShelfCode, ShelfId = ShelfId, WarningMessage = exceptionMessage, ClientIp = WebSocketIpAddress }; WarningManager.SendWarning(warningModel); #endregion IsWarning = true; Logs.Write($"货架自检【{ShelfCode},库位{storeInfo.StoreCode}存在物料未扫描上架,开始发送红灯】", LogsType.Instore); WarningLight.WaringLightAlwaysRed(TcpCleint); Logs.Write($"货架自检【{ShelfCode},库位{storeInfo.StoreCode}存在物料未扫描上架,发送红灯完成】", LogsType.Instore); } else { Logs.Write($"[进入入库模式异常]板Id{boardId},库位号{index + 1}找不到对应库位!"); } } } } } } #endregion } /// /// 过程中异常类型 /// public class ProcessingExceptionType { public int BoardId { get; set; } public int LightNumber { get; set; } public string ExceptionMessage { get; set; } } }