1.前后端增加复位功能

2.tcpclient心跳设置
3.优化后端启动速度
4.增加后端出库日志
This commit is contained in:
hehaibing-1996
2024-05-28 17:48:48 +08:00
parent d53532c22e
commit ac14b22507
24 changed files with 2403 additions and 1140 deletions

View File

@ -38,6 +38,7 @@ namespace WCS.BLL.Config
/// </summary>
public string? WMSUrl { get; set; }
public bool IsResetDBOrTable { get; set; }
#region
public bool IsMx { get; set; }
/// <summary>

View File

@ -72,7 +72,7 @@ namespace WCS.BLL.HardWare
public void Reset()
{
throw new NotImplementedException();
return;
}
public void SetCurrentMode()

View File

@ -302,6 +302,7 @@ namespace WCS.BLL.HardWare
CurrentOutStoreMatSNs.Clear();
////添加属于当前货架的物料
CurrentOutStoreMatSNs.AddRange(MatDetails.Select(t => t.MatSN).ToList());
Logs.Write($"货架【{ShelfCode}】本次发料物料为{string.Join(",", CurrentOutStoreMatSNs)}", LogsType.Outstore);
////记录当前出库的发料单
CurrentOutOrder = outOrder;
@ -365,63 +366,71 @@ namespace WCS.BLL.HardWare
}
catch (Exception e)
{
Logs.Write($"货架【{ShelfCode}】进入出库模式发生异常!", LogsType.Outstore);
GoOutOutstore();
throw e;
}
}
public void GoOutOutstore()
{
//找到在出库中的模组
var outingModules = Modules.Where(t => t.CurrentMode == Mode.)
.ToList();
foreach (var module in outingModules)
try
{
module.GoOutOutStoreMode(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 isExistsOutstore = outingModules.Where(t => t.CurrentMode == Mode.)
.Where(t => t.IsEnable)
.Any();
if (!isExistsOutstore)
Logs.Write($"货架【{ShelfCode}】,开始退出出库", LogsType.Outstore);
//找到在出库中的模组
var outingModules = Modules.Where(t => t.CurrentMode == Mode.)
.ToList();
foreach (var module in outingModules)
{
break;
module.GoOutOutStoreMode(TcpCleint);
}
//循环延时处理
Thread.Sleep(50);
}
var list = outingModules.Where(t => t.IsEnable && t.CurrentMode == Mode.).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()
//通信校验
var timeOut = 3000;
var timeSpan = TimeSpan.FromMilliseconds(0);
var beginTime = DateTime.Now;
while (timeSpan <= TimeSpan.FromMilliseconds(timeOut))
{
IsWarning = true,
WarningType = WarningTypeEnum.退,
StoreId = 0,
StoreCode = "",
ShelfCode = ShelfCode,
ShelfId = ShelfId,
WarningMessage = exceptionMessage,
ClientIp = WebSocketIpAddress,
};
WarningManager.SendWarning(warningModel);
timeSpan = DateTime.Now - beginTime;
//所有板子成功退出出库模式 表示退出出库模式成功,跳出循环
var isExistsOutstore = outingModules.Where(t => t.CurrentMode == Mode.)
.Where(t => t.IsEnable)
.Any();
if (!isExistsOutstore)
{
break;
}
//循环延时处理
Thread.Sleep(50);
}
var list = outingModules.Where(t => t.IsEnable && t.CurrentMode == Mode.).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 = Mode.;
Logs.Write($"货架【{ShelfCode}】,结束退出出库", LogsType.Outstore);
}
catch (Exception ex)
{
Logs.Write($"货架【{ShelfCode}】,退出出库时发生异常{ex.Message}", LogsType.Outstore);
}
//});
CurrentOutStoreMatSNs.Clear();
WarningLight.CloseLight(TcpCleint);
this.CurrentMode = Mode.;
}
public void GoInStocktaking(List<StockTakingOrderMatDetail> MatDetails, StockTakingOrder stockTakingOrder)
@ -603,9 +612,18 @@ namespace WCS.BLL.HardWare
this.CurrentMode = Mode.;
}
void IShelfBase.Reset()
public void Reset()
{
throw new NotImplementedException();
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 = Mode.;
}
void IShelfBase.SetCurrentMode()
@ -630,7 +648,6 @@ namespace WCS.BLL.HardWare
#region
public void ProtocolProcess(byte[] data, int boardId, int lightNumber)
{
Logs.Write("协议处理4");
//协议处理 判断功能位
switch (data[TcpCleint.PreFixLength + 2])
{
@ -672,7 +689,6 @@ namespace WCS.BLL.HardWare
break;
}
Logs.Write("协议处理5");
}
/// <summary>
/// 进入入库模式返回信号处理
@ -1034,19 +1050,16 @@ namespace WCS.BLL.HardWare
/// <param name="lightNumber"></param>
public void InStoreExceptionReturnProcess(byte[] data, int boardId, int lightNumber)
{
Logs.Write("协议处理5.1");
lightNumber = (int)data[TcpCleint.PreFixLength + 4];
var storeInfo = DbHelp.db.Queryable<StoreInfo>()
.Where(t => t.ShelfId == ShelfId)
.Where(t => t.BoardId == boardId && t.LightNumber == lightNumber)
.First();
Logs.Write("协议处理5.2");
if (storeInfo == null)
{
//TO DO 库位未找到
return;
}
Logs.Write("协议处理5.3");
//已放物料丢失了 物料多放了 储位恢复正常
switch (data[TcpCleint.PreFixLength + 3])
{
@ -1077,12 +1090,10 @@ namespace WCS.BLL.HardWare
});
ProcessingExceptions.RemoveAll(t => t.BoardId == boardId);
Logs.Write("协议处理5.5");
}
break;
case 0x01:
{
Logs.Write("协议处理5.4");
var exceptionMessage = storeInfo.StoreCode + "入库过程中存在物料未扫描上架!";
var warningModel = new WebSocketMessageModel()
{
@ -1104,12 +1115,10 @@ namespace WCS.BLL.HardWare
LightNumber = lightNumber,
ExceptionMessage = storeInfo.StoreCode + "入库过程中存在物料未扫描上架!"
});
Logs.Write("协议处理5.5");
}
break;
case 0x02:
{
Logs.Write("协议处理5.4");
var exceptionMessage = storeInfo.StoreCode + "物料被取出!";
var warningModel = new WebSocketMessageModel()
{
@ -1131,7 +1140,6 @@ namespace WCS.BLL.HardWare
LightNumber = lightNumber,
ExceptionMessage = storeInfo.StoreCode + "入库过程中物料丢失!"
});
Logs.Write("协议处理5.5");
}
break;
default:
@ -1281,7 +1289,7 @@ namespace WCS.BLL.HardWare
{
if (CurrentMode != Mode.)
{
Logs.Write($"出库错误:{ShelfCode}该货架模式不是出库模式或盘点模式!");
Logs.Write($"出库错误:{ShelfCode}该货架模式不是出库模式或盘点模式!", LogsType.Outstore);
return;
}
lightNumber = Convert.ToInt32(data[TcpCleint.PreFixLength + 3]);
@ -1303,7 +1311,7 @@ namespace WCS.BLL.HardWare
if (string.IsNullOrEmpty(storeInfo.CurrentMatSn))
{
//该库位是需要出库的库位物料被多次取出or给了多个正常出库信号
Logs.Write($"该库位是需要出库的库位物料被反复取出or给了多个正常出库信号,库位{storeInfo.StoreCode}");
Logs.Write($"该库位是需要出库的库位物料被反复取出or给了多个正常出库信号,库位{storeInfo.StoreCode}", LogsType.Outstore);
//暂不进行处理
return;
}
@ -1311,7 +1319,7 @@ namespace WCS.BLL.HardWare
//不是本次出库需要出的物料
if (!CurrentOutStoreMatSNs.Contains(storeInfo.CurrentMatSn))
{
Logs.Write($"{storeInfo.CurrentMatSn}不是本次需要出库的物料");
Logs.Write($"{storeInfo.CurrentMatSn}不是本次需要出库的物料", LogsType.Outstore);
//报警灯报警
WarningLight.WaringLightAlwaysRed(TcpCleint);
return;
@ -1321,7 +1329,7 @@ namespace WCS.BLL.HardWare
var inventoryDetail = DbHelp.db.Queryable<InventoryDetail>().Where(t => t.MatSN == storeInfo.CurrentMatSn).First();
if (inventoryDetail == null)
{
Logs.Write($"{storeInfo.CurrentMatSn}库存信息不存在");
Logs.Write($"{storeInfo.CurrentMatSn}库存信息不存在", LogsType.Outstore);
//报警灯报警
WarningLight.WaringLightAlwaysRed(TcpCleint);
return;
@ -1335,7 +1343,7 @@ namespace WCS.BLL.HardWare
if (orderMatDetails == null)
{
Logs.Write($"{storeInfo.CurrentMatSn},OrderDetail出库明细信息不存在");
Logs.Write($"{storeInfo.CurrentMatSn},OrderDetail出库明细信息不存在", LogsType.Outstore);
//报警灯报警
WarningLight.WaringLightAlwaysRed(TcpCleint);
return;
@ -1408,9 +1416,11 @@ namespace WCS.BLL.HardWare
module.ComfirmOutstore(TcpCleint, data[TcpCleint.PreFixLength + 3]);
//当前柜子是否还存在未出库的
Logs.Write($"货架【{ShelfCode}】,用户取出物料{matSN}", LogsType.Outstore);
CurrentOutStoreMatSNs.RemoveAll(t => t == matSN);//删除本次已出的物料SN
Logs.Write($"货架【{ShelfCode}】,当前货架剩余物料{string.Join(",", CurrentOutStoreMatSNs)}", LogsType.Outstore);
var isExsistOut = CurrentOutStoreMatSNs.Any();
var tempOrder = CurrentOutOrder;
@ -1432,6 +1442,7 @@ namespace WCS.BLL.HardWare
//本次亮灯的物料已全部取出
if (!isExsistOut)
{
Logs.Write($"货架【{ShelfCode}】,本次亮灯的物料已全部取出", LogsType.Outstore);
CurrentOutOrder = null;
//退出出库模式
@ -1453,7 +1464,7 @@ namespace WCS.BLL.HardWare
.Any();
if (!isLastShelf)
{
Logs.Write($"发料单{OrderNumber},最后一个出库货架,触发精准发料机制!查询是否还存在待出库物料");
Logs.Write($"发料单{OrderNumber},最后一个出库货架,触发精准发料机制!查询是否还存在待出库物料", LogsType.Outstore);
var outOrder = DbHelp.db.Queryable<OutOrder>()
.Where(t => t.OrderNumber == OrderNumber)
.First();
@ -1468,7 +1479,7 @@ namespace WCS.BLL.HardWare
if (outOrderMatDetails != null && outOrderMatDetails.Count > 0)
{
//存在待出库 然后之前又没亮灯的情况 => 继续分批次亮灯
Logs.Write($"发料单{OrderNumber},还有物料未出!");
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)
@ -1480,13 +1491,13 @@ namespace WCS.BLL.HardWare
var matCode = outOrderDetailCount.First().bb.Key;
outOrderMatDetails = outOrderMatDetails.Where(t => t.MatCode == matCode)
.ToList();
Logs.Write($"发料单{OrderNumber},本次亮灯物料{matCode}");
Logs.Write($"发料单{OrderNumber},本次亮灯物料{matCode}", LogsType.Outstore);
}
//相同物料不存在盘数超过n的情况剩余物料全部亮灯
else
{
//剩余物料全出
Logs.Write($"发料单{OrderNumber},剩余物料灯全亮!");
Logs.Write($"发料单{OrderNumber},剩余物料灯全亮!", LogsType.Outstore);
}
var shelfIds = outOrderMatDetails.Select(t => t.StoreInfo.ShelfId)
@ -1517,14 +1528,35 @@ namespace WCS.BLL.HardWare
}
else
{
Logs.Write($"发料单{OrderNumber},当前物料已发完!");
Logs.Write($"发料单{OrderNumber},当前物料已发完!", LogsType.Outstore);
}
}
else
{
Logs.Write($"发料单{OrderNumber}OutOrder为null肯定是有问题");
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 == Mode.)
.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
}

View File

@ -21,7 +21,7 @@ namespace WCS.BLL.Manager
Logs.Write("【初始化数据库】开始", LogsType.StartBoot);
//初始化数据库对象
if (LocalFile.Config.IsMx)
{
{
DbHelp.db = new SqlSugarScope(new ConnectionConfig()
{
ConnectionString = LocalFile.Config.DataDbPath,
@ -57,60 +57,73 @@ namespace WCS.BLL.Manager
{
};
});
Logs.Write("【初始化数据库】MX", LogsType.StartBoot);
}
DbHelp.db.DbMaintenance.CreateDatabase();
DbHelp.dbLog.DbMaintenance.CreateDatabase();
DbHelp.db.CodeFirst.InitTables(typeof(ModuleInfo), typeof(ShelfInfo), typeof(StoreInfo)
, typeof(InventoryDetail), typeof(OutOrder), typeof(OutOrderDetail), typeof(OutOrderMatDetail)
, typeof(ShelfTypeInfo), typeof(MatBaseInfo), typeof(MatInfo)
, typeof(StockTakingOrder), typeof(StockTakingOrderMatDetail), typeof(InOutRecord)
, typeof(DocumentSerialNumber)
);
DbHelp.dbLog.CodeFirst.InitTables(typeof(SystemApiLogRecord));
//初始化单据序列号数据
if (!DbHelp.db.Queryable<DocumentSerialNumber>().Any())
//手动修改后台配置后再进行CodeFirst 数据库的生成、表的生成
if (LocalFile.Config.IsResetDBOrTable)
{
var outDocumentSerialNumber = new DocumentSerialNumber()
{
DocumentType = DocumentTypeEnum.,
UpdateDate = DateTime.Now,
CurrentSerialNumber = 0
};
#region
DbHelp.db.DbMaintenance.CreateDatabase();
DbHelp.dbLog.DbMaintenance.CreateDatabase();
Logs.Write("【初始化数据库】创建数据库", LogsType.StartBoot);
var stockTakingDocumentSerialNumber = new DocumentSerialNumber()
{
DocumentType = DocumentTypeEnum.,
UpdateDate = DateTime.Now,
CurrentSerialNumber = 0
};
DbHelp.db.CodeFirst.InitTables(typeof(ModuleInfo), typeof(ShelfInfo), typeof(StoreInfo)
, typeof(InventoryDetail), typeof(OutOrder), typeof(OutOrderDetail), typeof(OutOrderMatDetail)
, typeof(ShelfTypeInfo), typeof(MatBaseInfo), typeof(MatInfo)
, typeof(StockTakingOrder), typeof(StockTakingOrderMatDetail), typeof(InOutRecord)
, typeof(DocumentSerialNumber)
);
Logs.Write("【初始化数据库】db建表", LogsType.StartBoot);
DbHelp.db.Insertable(outDocumentSerialNumber).ExecuteCommand();
DbHelp.db.Insertable(stockTakingDocumentSerialNumber).ExecuteCommand();
DbHelp.dbLog.CodeFirst.InitTables(typeof(SystemApiLogRecord));
Logs.Write("【初始化数据库】logdb建表", LogsType.StartBoot);
//初始化单据序列号数据
if (!DbHelp.db.Queryable<DocumentSerialNumber>().Any())
{
var outDocumentSerialNumber = new DocumentSerialNumber()
{
DocumentType = DocumentTypeEnum.,
UpdateDate = DateTime.Now,
CurrentSerialNumber = 0
};
var stockTakingDocumentSerialNumber = new DocumentSerialNumber()
{
DocumentType = DocumentTypeEnum.,
UpdateDate = DateTime.Now,
CurrentSerialNumber = 0
};
DbHelp.db.Insertable(outDocumentSerialNumber).ExecuteCommand();
DbHelp.db.Insertable(stockTakingDocumentSerialNumber).ExecuteCommand();
}
Logs.Write("【初始化数据库】DocumentSerialNumber", LogsType.StartBoot);
//初始化货架类型
if (!DbHelp.db.Queryable<ShelfTypeInfo>().Any())
{
var smartShelf = new ShelfTypeInfo()
{
ShelfTypeName = "智能货架"
};
var singleLight = new ShelfTypeInfo()
{
ShelfTypeName = "信息化货架"
};
DbHelp.db.Insertable(smartShelf).ExecuteCommand();
DbHelp.db.Insertable(singleLight).ExecuteCommand();
}
Logs.Write("【初始化数据库】初始化货架类型", LogsType.StartBoot);
//初始化权限数据库
AuthDbHelp.InitDb();
#endregion
LocalFile.Config.IsResetDBOrTable = false;
LocalFile.SaveConfig();
}
//初始化货架类型
if (!DbHelp.db.Queryable<ShelfTypeInfo>().Any())
{
var smartShelf = new ShelfTypeInfo()
{
ShelfTypeName = "智能货架"
};
var singleLight = new ShelfTypeInfo()
{
ShelfTypeName = "信息化货架"
};
DbHelp.db.Insertable(smartShelf).ExecuteCommand();
DbHelp.db.Insertable(singleLight).ExecuteCommand();
}
Logs.Write("【初始化数据库】结束", LogsType.StartBoot);
//初始化权限数据库
AuthDbHelp.InitDb();
}
}
}

View File

@ -8,6 +8,7 @@ using System.Text;
using System.Threading.Tasks;
using TouchSocket.Core;
using TouchSocket.Sockets;
using WCS.BLL.Config;
using WCS.BLL.HardWare;
using WCS.DAL.Db;
using WCS.DAL.DbModels;
@ -25,6 +26,7 @@ namespace WCS.BLL.Manager
Logs.Write("【InitTcpClient】开始", LogsType.StartBoot);
var ips = DbHelp.db.Queryable<ShelfInfo>()
.WhereIF(!string.IsNullOrEmpty(LocalFile.Config.GroupName),t => t.GroupName == LocalFile.Config.GroupName)
.Select(t => t.ClientIp)
.Distinct()
.ToList();
@ -33,7 +35,6 @@ namespace WCS.BLL.Manager
Task.Run(() =>
{
var tcpCleint = new TCPClient(ip, "");
//配置断线重连
tcpCleint.tcpClient.Received += (client, e) =>
{
var clientIpHost = client.IP + ":" + client.Port;
@ -44,7 +45,7 @@ namespace WCS.BLL.Manager
}
var data = e.ByteBlock.Buffer.Take((int)e.ByteBlock.Length).ToArray();
Logs.Write($"【接收】{BitConverter.ToString(data)}",LogsType.Instructions);
Logs.Write($"【接收】{BitConverter.ToString(data)}", LogsType.Instructions);
e.ByteBlock.Clear();
var len = data.Length;
for (int index = 0; index < data.Length - TcpCleint.PreFixLength; index++)
@ -78,7 +79,7 @@ namespace WCS.BLL.Manager
{
var shelf = ShelfManager.Shelves
.Where(t => t.ClientIp == clientIpHost)
.Where(t => t.ModuleIds.Contains(boardId))
.Where(t => t.ModuleIds != null && t.ModuleIds.Contains(boardId))
.FirstOrDefault();
var smartShelf = shelf as SmartShelf;
smartShelf?.ProtocolProcess(dataTemp, boardId, lightNumber);
@ -101,6 +102,7 @@ namespace WCS.BLL.Manager
if (TcpCleint.IsFirstConnected == false)
{
Logs.Write($"【InitTcpClient】{clientIpHost}完成首次连接", LogsType.StartBoot);
Console.WriteLine($"【InitTcpClient】{clientIpHost}完成首次连接");
InitStatus(TcpCleint);
TcpCleint.IsFirstConnected = true;
}
@ -117,23 +119,31 @@ namespace WCS.BLL.Manager
{
while (true)
{
Thread.Sleep(1000);
var noFirstConnectedClients = TCPClientManager.TCPClients.Where(t => t.IsFirstConnected == false)
.ToList();
if (noFirstConnectedClients.Count == 0)
try
{
break;
}
else
{
noFirstConnectedClients.ForEach(t =>
Thread.Sleep(1000);
var noFirstConnectedClients = TCPClientManager.TCPClients.Where(t => t.IsFirstConnected == false)
.ToList();
if (noFirstConnectedClients.Count == 0)
{
t.ReConnectAsync();
});
break;
}
else
{
Console.WriteLine($"存在tcp未完成首次连接继续重连");
noFirstConnectedClients.ForEach(t =>
{
t.ReConnectAsync();
});
}
}
catch (Exception ex)
{
}
}
});
Logs.Write("【InitTcpClient】完成后台继续连接", LogsType.StartBoot);
Logs.Write("【InitTcpClient】完成 后台继续连接", LogsType.StartBoot);
}
//后台启动时给所有板子、警示灯发送复位操作 保持状态一致

View File

@ -0,0 +1,552 @@
using OracleInternal.SqlAndPlsqlParser.LocalParsing;
using System.ComponentModel.DataAnnotations.Schema;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using WCS.BLL.Config;
using WCS.BLL.DbModels;
using WCS.BLL.HardWare;
using WCS.BLL.Manager;
using WCS.BLL.Services.IService;
using WCS.BLL.Tool;
using WCS.BLL.Tool.Api.ApiModel;
using WCS.DAL.Db;
using WCS.DAL.DbModels;
using WCS.Model;
using WCS.Model.ApiModel.InOutRecord;
using WCS.Model.ApiModel.MXBackgroundThread;
namespace WCS.BLL.Services.Service
{
public class InstoreService : IInstoreService
{
public InstoreService() { }
public ResponseBase shelfGoInInStore(ShelfGoInInstoreRequest request)
{
//校验货架编码规则
//取配置文件中得货架编码规则
bool isValid = false;
var patterns = LocalFile.Config.ModuleCodePatterns;
if (patterns != null && patterns.Count > 0)
{
foreach (var pattern in patterns)
{
isValid = Regex.IsMatch(request.ModuleCode, pattern);
//匹配到第一个符合条件的货架码 就直接退出循环 认为匹配成功
if (isValid)
break;
}
}
//如果配置文件缺失 使用默认正则进行匹配
else
{
isValid = Regex.IsMatch(request.ModuleCode, LocalFile.DefaultModuleCodePattern);
}
if (!isValid)
{
return new ResponseBase()
{
Code = 202,
Message = $"模组编码{request.ModuleCode}不满足模组编码规则!",
};
}
//找到模组对应的货架
var shelf = ShelfManager.Shelves.Where(t => t.ModulesStr.Contains(request.ModuleCode)).FirstOrDefault();
if (shelf == null)//未找到
{
return new ResponseBase()
{
Code = 201,
Message = "未找到模组对应的货架",
};
}
//已找到模组对应货架
shelf.GoInInstore(request.IpAdress);
if (shelf.CurrentMode == Mode.)
//成功进入入库模式
return new ShelfGoInInstoreResponse()
{
Code = 200,
Message = $"货架进入入库模式成功!{string.Join(",", shelf.ExceptionMessages)}",
Data = new ShelfGoInInstoreDto()
{
ShelfCode = shelf.ShelfCode,
ModulesStr = shelf.ModulesStr,
}
};
else
return new ShelfGoInInstoreResponse()
{
Code = 201,
Message = $"货架进入入库模式失败:{string.Join(",", shelf.ExceptionMessages)}",
Data = null
};
}
public ResponseBase shelfGoOutInStore(ShelfGoOutInStoreRequest request)
{
//获取货架
var shelf = ShelfManager.Shelves.Where(t => t.ShelfCode == request.ShelfCode).FirstOrDefault();
if (shelf == null)//货架不存在
{
return new ResponseCommon()
{
Code = 201,
Message = $"退出入库模式失败:货架[{request.ShelfCode}]不存在!",
};
}
//判断扫码枪 是否被其他扫码枪所占用 如果占用 直接退出入库模式 不发指令
shelf.GoOutInstore();
if (shelf.ExceptionMessages == null || shelf.ExceptionMessages.Count == 0)
//已退出
return new ResponseCommon()
{
Code = 200,
Message = $"货架[{request.ShelfCode}]已退出入库模式!",
};
else
return new ResponseCommon()
{
Code = 200,
Message = $"货架[{request.ShelfCode}]已退出入库模式!{string.Join(",", shelf.ExceptionMessages)}",
};
}
public async Task<ResponseBase> queryByMatSn(QueryByMatSnRequest request)
{
//判断物料是否已入库
var inventory = await DbHelp.db.Queryable<InventoryDetail>().Where(t => t.MatSN == request.MatSn).FirstAsync();
if (inventory != null)
{
return new ResponseCommon<MatInfo>()
{
Code = 201,
Message = $"操作失败:物料{inventory.MatSN}已入库!库位为{inventory.StoreCode}",
};
}
IShelfBase shelf = null;
if (!request.SingleLightIn)
{
//获取货架
shelf = ShelfManager.Shelves.Where(t => t.ShelfCode == request.ShelfCode).FirstOrDefault();
if (shelf == null)//货架不存在
{
return new ResponseCommon<MatInfo>()
{
Code = 201,
Message = $"操作失败:货架[{request.ShelfCode}]不存在!",
};
}
//判断当前是否是入库模式
if (shelf.CurrentMode != Mode.)
{
return new ResponseCommon<MatInfo>()
{
Code = 201,
Message = $"操作失败:货架[{request.ShelfCode}]不在入库模式!\r\n当前为{shelf.CurrentMode}",
};
}
}
#region //调用接口或者直接查询数据库
// 调用接口
if (LocalFile.Config.IsAccessWMS)
{
#region WMS接口获取物料信息
try
{
var body = new
{
materialBar = request.MatSn
};
var Result = ApiHelp.GetDataFromHttp<ResponseCommon<List<queryByBarResponse>>>("http://192.168.2.23:9213/integrate/instock/queryBybar", body, "POST", true);
//查询到物料信息
if (Result != null && Result.Code == 200 && Result.Data != null && Result.Data.Count > 0)
{
var data = Result.Data.First();
if (!request.SingleLightIn && shelf != null)
shelf.InStoreData = new MatInfoResponse()
{
materialBar = data.materialBar,
materialCode = data.materialCode,
materialName = data.materialName,
materialQty = data.materialQty,
materialSpec = data.materialSpec,
batchNo = data.batchNo,
supplier = "",
customer = "",
InstoreUser = request.UserName
};
var matInfo = new MatInfo()
{
MatSn = data.materialBar,
MatCode = data.materialCode,
MatName = data.materialName,
MatBatch = data.batchNo,
MatQty = (int)data.materialQty,
MatSpec = data.materialSpec,
MatSupplier = "",
MatCustomer = "",
};
return new ResponseCommon<MatInfo>()
{
Code = 200,
Data = matInfo,
Message = "success"
};
}
else if (Result != null && Result.Code == 200 && Result.Data == null)
{
//Mes系统中未获取到物料信息
//简单校验看是否满足海康物料
//海康物料 只扫了外箱码 未扫条码
if ((request.MatSn.Length == 54 || request.MatSn.Length == 56) && !request.MatSn.Contains("\\") && !request.MatSn.Contains("/"))
{
if (!request.SingleLightIn && shelf != null)
shelf.InStoreData = new MatInfoResponse()
{
materialBar = request.MatSn,
materialCode = "暂时未知",
materialName = "暂时未知",
materialQty = 0,
materialSpec = "暂时未知",
batchNo = "暂时未知",
supplier = "",
customer = "",
InstoreUser = request.UserName
};
var matInfo = new MatInfo()
{
MatSn = request.MatSn,
MatCode = "暂时未知",
MatName = "暂时未知",
MatBatch = "暂时未知",
MatQty = 0,
MatSpec = "暂时未知",
MatSupplier = "",
MatCustomer = "",
};
return new ResponseCommon<MatInfo>()
{
Code = 200,
Data = matInfo,
Message = "success"
};
}
return new ResponseCommon<MatInfo>()
{
Code = 201,
Message = $"操作失败调用Mes接口未获取到物料信息",
};
}
else
{
return new ResponseCommon<MatInfo>()
{
Code = 201,
Message = $"操作失败调用Mes接口失败",
};
}
}
catch (Exception e)
{
return new ResponseCommon<MatInfo>()
{
Code = 300,
Message = $"操作失败调用Mes接口发生异常{e.Message}",
};
}
#endregion
}
//查询数据库是否存在这个物料
else
{
var matInfo = await DbHelp.db.Queryable<MatInfo>().Where(t => t.MatSn == request.MatSn).FirstAsync();
if (matInfo != null)
{
//TODO 改成wcs的实体
if (!request.SingleLightIn && shelf != null)
shelf.InStoreData = new MatInfoResponse()
{
materialBar = matInfo.MatSn,
materialCode = matInfo.MatCode,
materialName = matInfo.MatName,
materialQty = matInfo.MatQty,
materialSpec = matInfo.MatSpec,
batchNo = matInfo.MatBatch,
supplier = matInfo.MatSupplier,
customer = matInfo.MatCustomer,
InstoreUser = request.UserName
};
return new ResponseCommon<MatInfo>()
{
Code = 200,
Data = matInfo,
Message = "success"
};
}
else
return new ResponseCommon<MatInfo>()
{
Code = 201,
Data = null,
Message = $"不存在物料{request.MatSn}"
};
}
#endregion
}
/// <summary>
/// 单灯出库时查询物料信息 这里返回库存的数据
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task<ResponseBase> queryByMatSnOut(QueryByMatSnRequest request)
{
//判断物料是否已入库
var inventory = await DbHelp.db.Queryable<InventoryDetail>().Where(t => t.MatSN == request.MatSn).FirstAsync();
if (inventory == null)
{
return new ResponseCommon<MatInfo>()
{
Code = 201,
Message = $"操作失败:物料不在库存内,无法进行出库!",
};
}
else
{
return new ResponseCommon<MatInfo>()
{
Code = 200,
Message = $"Success",
Data = new MatInfo()
{
MatSn = inventory.MatSN,
MatCode = inventory.MatCode,
MatName = inventory.MatName,
MatBatch = inventory.MatBatch,
MatQty = inventory.MatQty,
MatSpec = inventory.MatSpec,
MatSupplier = inventory.MatSupplier,
MatCustomer = inventory.MatCustomer,
}
};
}
}
public async Task<ResponseBase> queryInstoreStatus(QueryByMatSnRequest request)
{
//获取货架
var shelf = ShelfManager.Shelves.Where(t => t.ShelfCode == request.ShelfCode).FirstOrDefault();
if (shelf == null)//货架不存在
{
return new ResponseCommon()
{
Code = 201,
Message = $"货架[{request.ShelfCode}]不存在!",
};
}
//判断当前是否是入库模式
if (shelf.CurrentMode != Mode.)
{
return new ResponseCommon()
{
Code = 201,
Message = $"货架[{request.ShelfCode}]已退出入库模式!\r\n当前为{shelf.CurrentMode}",
};
}
//TODO 配置这个时间相当于需要入库扫码后需要等待的时间
var timeOut = 5000;
var timeSpan = TimeSpan.FromMilliseconds(0);
var beginTime = DateTime.Now;
while (timeSpan <= TimeSpan.FromMilliseconds(timeOut))
{
timeSpan = DateTime.Now - beginTime;
//已入库当前扫码的物料时 查询数据库
if (shelf.InStoreData == null || (shelf.InStoreData as object) == null)
{
await Task.Delay(50);
var inventoryDetail = DbHelp.db.Queryable<InventoryDetail>()
.Where(t => t.MatSN == request.MatSn)
.First();
if (inventoryDetail != null)
{
return new ResponseCommon()
{
Code = 200,
Message = $"入库成功!物料已放入库位{inventoryDetail.StoreCode}",
Data = new
{
StoreCode = inventoryDetail.StoreCode,
}
};
}
else
break;
}
//延时处理
Thread.Sleep(50);
}
//超时未成功入库
shelf.InStoreData = null;
return new ResponseCommon()
{
Code = 201,
Message = $"超时未入库!请重新扫码后入库!",
Data = new
{
StoreCode = string.Empty,
}
};
}
public async Task<ResponseBase> queryInstoreStatusSingle(QueryByMatSnRequestSingle request)
{
//获取货架
//var shelf = ShelfManager.Shelves.Where(t => t.ShelfCode == request.ShelfCode).FirstOrDefault();
//if (shelf == null)//货架不存在
//{
// return new ResponseCommon()
// {
// Code = 201,
// Message = $"货架[{request.ShelfCode}]不存在!",
// };
//}
List<ModuleInfo> MI = DbHelp.db.Queryable<ModuleInfo>().Where(it => it.ModuleCode == request.ShelfCode).ToList();
if (MI.Count == 0)
{
return new ResponseCommonSingle()
{
Code = 201,
Message = $"货架[{request.ShelfCode}]不存在!",
};
}
ResponseCommonSingle rcs = new ResponseCommonSingle();
rcs.Data = new List<Detail>();
string sendIP = MI[0].CleintIp; //单灯IP
int PCBId = MI[0].BoardId; //单灯PCB板ID
List<StoreInfo> SI = DbHelp.db.Queryable<StoreInfo>().Where(it => it.ModuleCode == request.ShelfCode).ToList();
List<ShelfInfo> si = DbHelp.db.Queryable<ShelfInfo>().Where(it => it.ShelfCode == MI[0].ShelfCode).ToList();
int warnLightID = si[0].LightId;
foreach (QueryByMatSnRequestSingle.MatSnListDetail matSnListDetail in request.MatSnList)
{
Detail detail = new Detail();
try
{
InventoryDetail inventoryDetail = new InventoryDetail();
inventoryDetail.MatSN = matSnListDetail.MatSn;
inventoryDetail.MatCode = matSnListDetail.MatCode;
inventoryDetail.MatName = matSnListDetail.MatName;
inventoryDetail.MatSpec = matSnListDetail.MatSpec;
inventoryDetail.MatBatch = matSnListDetail.MatBatch;
inventoryDetail.MatQty = matSnListDetail.MatQty;
inventoryDetail.MatCustomer = matSnListDetail.MatCustomer;
inventoryDetail.MatSupplier = matSnListDetail.MatSupplier;
inventoryDetail.StoreCode = request.ShelfCode;
inventoryDetail.StoreId = SI[0].Id;
int count = DbHelp.db.Insertable(inventoryDetail).ExecuteCommand();
InOutRecord ior = new InOutRecord();
ior.MatSN = matSnListDetail.MatSn;
ior.MatCode = matSnListDetail.MatCode;
ior.MatName = matSnListDetail.MatName;
ior.MatSpec = matSnListDetail.MatSpec;
ior.MatBatch = matSnListDetail.MatBatch;
ior.MatQty = matSnListDetail.MatQty;
ior.MatCustomer = matSnListDetail.MatCustomer;
ior.MatSupplier = matSnListDetail.MatSupplier;
ior.StoreCode = request.ShelfCode;
ior.StoreId = SI[0].Id;
ior.Direction = DirectionEnum.;
ior.OperateTime = DateTime.Now;
ior.OperateUser = request.UserName;
int count1 = DbHelp.db.Insertable(ior).ExecuteCommand();
detail.matsn = matSnListDetail.MatSn;
detail.result = "入库成功";
rcs.Data.Add(detail);
}
catch (Exception ee)
{
detail.matsn = matSnListDetail.MatSn;
detail.result = "入库失败";
detail.reason = ee.Message;
rcs.Data.Add(detail);
}
}
//亮灯
TCPClient tCPClient = TCPClientManager.GetTCPClientByIPHost(sendIP);
<<<<<<< HEAD
//byte[] data1 = new byte[8];
//data1[0] = 0xff;
//data1[1] = 0x02;
//data1[2] = 0x00;
//data1[3] = 0x0a;
//data1[4] = (byte)warnLightID;
//data1[5] = 0x03;
//data1[6] = 0x02;
//data1[7] = 0x02;
//byte[] senddata1 = Tool.Helper.Crc16(data1, data1.Length, true);
byte[] senddata1 = Tool.Helper.InstoreWarnLight(warnLightID);
=======
byte[] data1 = new byte[8];
data1[0] = 0xff;
data1[1] = 0x02;
data1[2] = 0x00;
data1[3] = 0x0a;
data1[4] = (byte)warnLightID;
data1[5] = 0x03;
data1[6] = 0x02;
data1[7] = 0x02;
byte[] senddata1 = Tool.Helper.Crc16(data1, data1.Length, false);
>>>>>>> 11
tCPClient.Send(senddata1); //报警灯短亮一次
//byte[] data2 = new byte[8];
//data2[0] = 0xff;
//data2[1] = 0x01;
//data2[2] = 0x00;
//data2[3] = 0x0a;
//data2[4] = 0x01;
//data2[5] = (byte)PCBId;
//data2[6] = 0x03;
//data2[7] = 0x02;
//byte[] senddata2 = Tool.Helper.Crc16(data2, data2.Length, true);
byte[] senddata2 = Tool.Helper.InstoreLight(PCBId);
tCPClient.Send(senddata2); //库位灯短亮一次
return new ResponseCommonSingle()
{
Code = 200,
Message = $"入库成功!",
Data = rcs.Data,
};
}
}
}

View File

@ -654,7 +654,7 @@ namespace WCS.BLL.Services.Service
};
}
if (request.IsStart)//&& order.OutOrderExeStatus != OutOrderExeStatus.发料完成
if (request.IsStart)
{
order.OutOrderExeStatus = OutOrderExeStatus.;
DbHelp.db.Updateable(order).ExecuteCommand();
@ -690,13 +690,13 @@ namespace WCS.BLL.Services.Service
var matCode = outOrderDetailCount.First().bb.Key;
outOrderMatDetails = outOrderMatDetails.Where(t => t.MatCode == matCode)
.ToList();
Logs.Write($"出库单{order.OrderNumber},本次亮灯物料{matCode}");
Logs.Write($"出库单{order.OrderNumber},本次亮灯物料{matCode}",LogsType.Outstore);
}
//相同物料不存在盘数超过n的情况剩余物料全部亮灯
else
{
//剩余物料全出
Logs.Write($"出库单{order.OrderNumber},剩余物料灯全亮!");
Logs.Write($"出库单{order.OrderNumber},剩余物料灯全亮!", LogsType.Outstore);
}
}
@ -708,6 +708,7 @@ namespace WCS.BLL.Services.Service
.ToList();
shelf.GoInOutstore(matDetails, order);
shelf.OrderNumber = order.OrderNumber;
Logs.Write($"出库单{order.OrderNumber},货架{shelf.ShelfCode}进入入库模式!", LogsType.Outstore);
});
//返回
@ -720,6 +721,7 @@ namespace WCS.BLL.Services.Service
}
catch (Exception ex)
{
Logs.Write($"本次发料发生异常!{ex.Message}", LogsType.Outstore);
await GoOutOutstore(request);
throw ex;
}
@ -1108,16 +1110,12 @@ namespace WCS.BLL.Services.Service
};
}
//退出出库模式
shelves.ForEach(t =>
{
t.GoOutOutstore();
});
return new ResponseCommon()
{
Code = 200,

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TouchSocket.Core;
using TouchSocket.Sockets;
namespace WCS.BLL.Tool
{
/// <summary>
/// 一个心跳计数器扩展。
/// </summary>
internal static class DependencyExtensions
{
public static readonly DependencyProperty<Timer> HeartbeatTimerProperty =
DependencyProperty<Timer>.Register("HeartbeatTimer", null);
public static bool Ping<TClient>(this TClient client) where TClient : ITcpClientBase
{
try
{
var data = new byte[] { 0x05, 0x00, 0x00, 0x06, 0x78, 0x12, 0x34, 0x56, 0x78, 0x00, 0x00, 0x00, 0x00 };
client.Send(data);
return true;
}
catch (Exception ex)
{
Logs.Write($"【{client.IP}:{client.Port}】发送心跳中发现异常:" + ex.Message, LogsType.Info);
if (ex is NotConnectedException)
{
}
}
return false;
}
public static bool Pong<TClient>(this TClient client) where TClient : ITcpClientBase
{
try
{
client.Send(new MyRequestInfo() { DataType = DataType.Pong }.PackageAsBytes());
return true;
}
catch (Exception ex)
{
client.Logger.Exception(ex);
}
return false;
}
}
}

View File

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TouchSocket.Core;
using TouchSocket.Sockets;
namespace WCS.BLL.Tool
{
internal class HeartbeatAndReceivePlugin : PluginBase, ITcpConnectedPlugin<ITcpClientBase>, ITcpDisconnectedPlugin<ITcpClientBase>, ITcpReceivedPlugin<ITcpClientBase>
{
private readonly int m_timeTick;
private readonly ILog logger;
[DependencyInject("20000")]
public HeartbeatAndReceivePlugin(int timeTick, ILog logger)
{
this.m_timeTick = 20000;
this.logger = logger;
}
public async Task OnTcpConnected(ITcpClientBase client, ConnectedEventArgs e)
{
if (client is ISocketClient)
{
return;//此处可判断,如果为服务器,则不用使用心跳。
}
if (client.GetValue(DependencyExtensions.HeartbeatTimerProperty) is Timer timer)
{
timer.Dispose();
}
client.SetValue(DependencyExtensions.HeartbeatTimerProperty, new Timer((o) =>
{
client.Ping();
}, null, 0, this.m_timeTick));
await e.InvokeNext();
}
public async Task OnTcpDisconnected(ITcpClientBase client, DisconnectEventArgs e)
{
if (client.GetValue(DependencyExtensions.HeartbeatTimerProperty) is Timer timer)
{
timer.Dispose();
client.SetValue(DependencyExtensions.HeartbeatTimerProperty, null);
}
await e.InvokeNext();
}
public async Task OnTcpReceived(ITcpClientBase client, ReceivedDataEventArgs e)
{
if (e.RequestInfo is MyRequestInfo myRequest)
{
this.logger.Info(myRequest.ToString());
if (myRequest.DataType == DataType.Ping)
{
client.Pong();
}
}
await e.InvokeNext();
}
}
}

View File

@ -36,7 +36,11 @@ namespace WCS.BLL
/// <summary>
/// 指令重发
/// </summary>
InstructionResend
InstructionResend,
/// <summary>
/// 出库流程日志
/// </summary>
Outstore,
}
/// <summary>

View File

@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TouchSocket.Core;
namespace WCS.BLL.Tool
{
internal class MyFixedHeaderDataHandlingAdapter : CustomFixedHeaderDataHandlingAdapter<MyRequestInfo>
{
public override int HeaderLength => 3;
public override bool CanSendRequestInfo => false;
protected override MyRequestInfo GetInstance()
{
return new MyRequestInfo();
}
protected override void PreviewSend(IRequestInfo requestInfo)
{
throw new NotImplementedException();
}
}
internal class MyRequestInfo : IFixedHeaderRequestInfo
{
public DataType DataType { get; set; }
public byte[] Data { get; set; }
public int BodyLength { get; private set; }
public bool OnParsingBody(byte[] body)
{
if (body.Length == this.BodyLength)
{
this.Data = body;
return true;
}
return false;
}
public bool OnParsingHeader(byte[] header)
{
if (header.Length == 3)
{
this.BodyLength = TouchSocketBitConverter.Default.ToUInt16(header, 0) - 1;
this.DataType = (DataType)header[2];
return true;
}
return false;
}
public void Package(ByteBlock byteBlock)
{
byteBlock.Write((ushort)((this.Data == null ? 0 : this.Data.Length) + 1));
byteBlock.Write((byte)this.DataType);
if (this.Data != null)
{
byteBlock.Write(this.Data);
}
}
public byte[] PackageAsBytes()
{
using var byteBlock = new ByteBlock();
this.Package(byteBlock);
return byteBlock.ToArray();
}
public override string ToString()
{
return $"数据类型={this.DataType},数据={(this.Data == null ? "null" : Encoding.UTF8.GetString(this.Data))}";
}
}
internal enum DataType : byte
{
Ping,
Pong,
Data
}
}

View File

@ -2,6 +2,7 @@
using System.Text;
using TouchSocket.Core;
using TouchSocket.Sockets;
using WCS.BLL.Tool;
namespace WCS.BLL
@ -68,6 +69,7 @@ namespace WCS.BLL
{
//配置断线重连
a.UseReconnection(-1, true, 1000);
a.Add<HeartbeatAndReceivePlugin>();
})
.ConfigureContainer(a =>
{