Merge branch '煤科院货架液晶显示屏' of https://gitee.com/cquni-wcs/wcs into 煤科院货架液晶显示屏

This commit is contained in:
hehaibing-1996
2024-12-07 17:53:05 +08:00
4 changed files with 290 additions and 160 deletions

View File

@ -90,13 +90,18 @@ namespace WCS.DAL.DbModels
[SugarColumn(ColumnName = "group_name", Length = 50, IsNullable = false, ColumnDescription = "货架的组别、区域(区分单个软件管哪些货架的,前端的配置文件配置一个组别,查询时只显示当前组别的货架)")] [SugarColumn(ColumnName = "group_name", Length = 50, IsNullable = false, ColumnDescription = "货架的组别、区域(区分单个软件管哪些货架的,前端的配置文件配置一个组别,查询时只显示当前组别的货架)")]
public string GroupName { get; set; } public string GroupName { get; set; }
/// <summary> /// <summary>
/// 是否串联绑定 /// 模块是不
/// </summary> /// </summary>
[SugarColumn(ColumnName = "is_bind", IsNullable = false, ColumnDescription = "是否串联绑定")] [SugarColumn(ColumnName = "is_bind", IsNullable = false, ColumnDescription = "是否串联绑定")]
public bool IsBind { get; set; } public bool IsBind { get; set; }
/// <summary>
/// 货架的模块是不是服务端
/// </summary>
[SugarColumn(ColumnName = "is_service", IsNullable = true, ColumnDescription = "货架的模块是不是服务端")]
public bool IsService { get; set; } = false;
/// <summary> /// <summary>
/// 串联绑定后的大货架编码 /// 串联绑定后的大货架编码
/// </summary> /// </summary>

View File

@ -78,6 +78,8 @@ namespace WCS.BLL.Manager
, typeof(AppVersion) , typeof(AppVersion)
); );
//DbHelp.db.CodeFirst.InitTables(typeof(ShelfInfo));
Logs.Write("【初始化数据库】db业务数据库建表", LogsType.StartBoot); Logs.Write("【初始化数据库】db业务数据库建表", LogsType.StartBoot);
DbHelp.dbLog.CodeFirst.InitTables(typeof(SystemApiLogRecord)); DbHelp.dbLog.CodeFirst.InitTables(typeof(SystemApiLogRecord));
Logs.Write("【初始化数据库】dblog日志数据库建表", LogsType.StartBoot); Logs.Write("【初始化数据库】dblog日志数据库建表", LogsType.StartBoot);

View File

@ -23,12 +23,15 @@ namespace WCS.BLL.Manager
/// </summary> /// </summary>
public static List<TCPClient> TCPClients = new List<TCPClient>(); public static List<TCPClient> TCPClients = new List<TCPClient>();
public static TcpService Service { get; set; }
public static void InitTcpClient() public static void InitTcpClient()
{ {
#region Service的逻辑
Logs.Write("【InitTcpClient】开始", LogsType.StartBoot); Logs.Write("【InitTcpClient】开始", LogsType.StartBoot);
var moduleServices = DbHelp.db.Queryable<ShelfInfo>()
var clientsInDB = DbHelp.db.Queryable<ShelfInfo>()
.WhereIF(!string.IsNullOrEmpty(LocalFile.Config.GroupName), t => t.GroupName == LocalFile.Config.GroupName) .WhereIF(!string.IsNullOrEmpty(LocalFile.Config.GroupName), t => t.GroupName == LocalFile.Config.GroupName)
.Where(t => t.IsService)
.Select(t => new .Select(t => new
{ {
IP = t.ClientIp, IP = t.ClientIp,
@ -37,154 +40,208 @@ namespace WCS.BLL.Manager
}) })
.Distinct() .Distinct()
.ToList(); .ToList();
Logs.Write($"【InitTcpClient】需要连接的服务端地址如下\r\n{string.Join(";", clientsInDB)}", LogsType.StartBoot); if (moduleServices != null && moduleServices.Count > 0)
foreach (var cleientInDB in clientsInDB)
{ {
Logs.Write($"【InitTcpClient】需要连接的服务端地址如下\r\n{string.Join(";", moduleServices)}", LogsType.StartBoot);
foreach (var cleientInDB in moduleServices)
{
Task.Run(() =>
{
var tcpCleint = new TCPClient(cleientInDB.IP, cleientInDB.Port, cleientInDB.ShelfTypeName);
tcpCleint.tcpClient.Received += (client, e) =>
{
var clientIpHost = client.IP + ":" + client.Port;
var TcpCleint = TCPClientManager.GetTCPClientByIPHost(clientIpHost);
if (TcpCleint == null)
{
return EasyTask.CompletedTask;
}
var data = e.ByteBlock.Buffer.Take((int)e.ByteBlock.Length).ToArray();
Logs.Write($"【接收{clientIpHost}】{BitConverter.ToString(data)}", LogsType.Instructions);
e.ByteBlock.Clear();
var len = data.Length;
if (tcpCleint.ShelfTypeName == "信息化货架")
{
Logs.Write($"【信息化货架开始处理接收数据】{BitConverter.ToString(data)}", LogsType.InstructionsProcess);
Helper.ReturnDataProcess(TcpCleint, data);
Logs.Write($"【信息化货架完成处理接收数据】{BitConverter.ToString(data)}", LogsType.InstructionsProcess);
return EasyTask.CompletedTask;
}
if (tcpCleint.ShelfTypeName == "液晶货架")
{
Logs.Write($"【液晶货架开始处理接收数据】{BitConverter.ToString(data)}", LogsType.InstructionsProcess);
//Helper.ReturnDataProcess(TcpCleint, data);
Logs.Write($"【液晶货架完成处理接收数据】{BitConverter.ToString(data)}", LogsType.InstructionsProcess);
return EasyTask.CompletedTask;
}
for (int index = 0; index < data.Length - TcpCleint.PreFixLength; index++)
{
//协议拆包 通过前缀校验是否为完整数据包
var prefixInData = data.Skip(index).Take(TcpCleint.PreFixLength);
var isEqual = prefixInData.SequenceEqual(TcpCleint.Prefix);
if (isEqual)
{
var dataTemp = data.Skip(index).Take(TcpCleint.PreFixLength + TcpCleint.DataLength).ToArray();
if (dataTemp.Length < TcpCleint.PreFixLength + TcpCleint.DataLength)//拆包后不满足一条指令的长度
{
continue;
}
Logs.Write($"【处理单条指令 开始】{BitConverter.ToString(dataTemp)}", LogsType.InstructionsProcess);
index += (TcpCleint.PreFixLength + TcpCleint.DataLength - 1);//每次循环index会+1 所以这里-1
//获取板子ID
var boardId = (dataTemp[TcpCleint.PreFixLength + 0] << 8) + dataTemp[TcpCleint.PreFixLength + 1];
var lightNumber = Convert.ToInt32(dataTemp[TcpCleint.PreFixLength + 3]);
//报警灯 返回来就修改对应的灯的颜色
if (dataTemp[TcpCleint.PreFixLength + 2] == 0x20)
{
var shelf = ShelfManager.Shelves.Where(t => t.ClientIp == clientIpHost)
.Where(t => t.LightId == boardId)
.FirstOrDefault();
var smartShelf = shelf as SmartShelf;
smartShelf?.WarningLightProcess(dataTemp, boardId, lightNumber);
}
//!= 0x20 货架类型协议返回
else
{
var shelf = ShelfManager.Shelves
.Where(t => t.ClientIp == clientIpHost)
.Where(t => t.ModuleIds != null && t.ModuleIds.Contains(boardId))
.FirstOrDefault();
var smartShelf = shelf as SmartShelf;
smartShelf?.ProtocolProcess(dataTemp, boardId, lightNumber);
}
Logs.Write($"【处理单条指令 结束】{BitConverter.ToString(dataTemp)}", LogsType.InstructionsProcess);
}
}
return EasyTask.CompletedTask;
};
//配置首次连接后复位操作
tcpCleint.tcpClient.Connected += (client, e) =>
{
Logs.Write($"【TcpClient】{client.IP}完成连接,端口号{client.Port}", LogsType.StartBoot);
var clientIpHost = client.IP + ":" + client.Port;
var TcpCleint = TCPClientManager.GetTCPClientByIPHost(clientIpHost);
if (TcpCleint == null)
{
return EasyTask.CompletedTask;
}
//首次连接
if (TcpCleint.IsFirstConnected == false)
{
Logs.Write($"【InitTcpClient】{clientIpHost}完成首次连接", LogsType.StartBoot);
Console.WriteLine($"【InitTcpClient】{clientIpHost}完成首次连接");
InitStatus(TcpCleint);
TcpCleint.IsFirstConnected = true;
//获取剩余未完成连接的tcp
var noFirstConnectedTcps = TCPClientManager.TCPClients.Where(t => t.IsFirstConnected == false)
.Select(t => t.RemoteIPHost)
.ToList();
Logs.Write($"【InitTcpClient】剩余未完成连接的TCP为{string.Join(";", noFirstConnectedTcps)}", LogsType.StartBoot);
}
return EasyTask.CompletedTask;
};
lock (TCPClients)//避免添加失败的情况
{
TCPClients.Add(tcpCleint);
}
tcpCleint.Connect();
});
}
//启动线程监听所有TCP是否已经完成首次连接
Task.Run(() => Task.Run(() =>
{ {
var tcpCleint = new TCPClient(cleientInDB.IP, cleientInDB.Port, cleientInDB.ShelfTypeName); while (true)
tcpCleint.tcpClient.Received += (client, e) =>
{ {
var clientIpHost = client.IP + ":" + client.Port; try
var TcpCleint = TCPClientManager.GetTCPClientByIPHost(clientIpHost);
if (TcpCleint == null)
{ {
return EasyTask.CompletedTask; Thread.Sleep(1000);
} var noFirstConnectedClients = TCPClientManager.TCPClients.Where(t => t.IsFirstConnected == false)
.ToList();
var data = e.ByteBlock.Buffer.Take((int)e.ByteBlock.Length).ToArray(); if (noFirstConnectedClients.Count == 0)
Logs.Write($"【接收{clientIpHost}】{BitConverter.ToString(data)}", LogsType.Instructions);
e.ByteBlock.Clear();
var len = data.Length;
if (tcpCleint.ShelfTypeName == "信息化货架")
{
Logs.Write($"【信息化货架开始处理接收数据】{BitConverter.ToString(data)}", LogsType.InstructionsProcess);
Helper.ReturnDataProcess(TcpCleint, data);
Logs.Write($"【信息化货架完成处理接收数据】{BitConverter.ToString(data)}", LogsType.InstructionsProcess);
return EasyTask.CompletedTask;
}
if (tcpCleint.ShelfTypeName == "液晶货架")
{
Logs.Write($"【液晶货架开始处理接收数据】{BitConverter.ToString(data)}", LogsType.InstructionsProcess);
//Helper.ReturnDataProcess(TcpCleint, data);
Logs.Write($"【液晶货架完成处理接收数据】{BitConverter.ToString(data)}", LogsType.InstructionsProcess);
return EasyTask.CompletedTask;
}
for (int index = 0; index < data.Length - TcpCleint.PreFixLength; index++)
{
//协议拆包 通过前缀校验是否为完整数据包
var prefixInData = data.Skip(index).Take(TcpCleint.PreFixLength);
var isEqual = prefixInData.SequenceEqual(TcpCleint.Prefix);
if (isEqual)
{ {
var dataTemp = data.Skip(index).Take(TcpCleint.PreFixLength + TcpCleint.DataLength).ToArray(); break;
if (dataTemp.Length < TcpCleint.PreFixLength + TcpCleint.DataLength)//拆包后不满足一条指令的长度 }
else
{
Console.WriteLine($"存在tcp未完成首次连接继续重连");
noFirstConnectedClients.ForEach(t =>
{ {
continue; t.ReConnectAsync();
} });
Logs.Write($"【处理单条指令 开始】{BitConverter.ToString(dataTemp)}", LogsType.InstructionsProcess);
index += (TcpCleint.PreFixLength + TcpCleint.DataLength - 1);//每次循环index会+1 所以这里-1
//获取板子ID
var boardId = (dataTemp[TcpCleint.PreFixLength + 0] << 8) + dataTemp[TcpCleint.PreFixLength + 1];
var lightNumber = Convert.ToInt32(dataTemp[TcpCleint.PreFixLength + 3]);
//报警灯 返回来就修改对应的灯的颜色
if (dataTemp[TcpCleint.PreFixLength + 2] == 0x20)
{
var shelf = ShelfManager.Shelves.Where(t => t.ClientIp == clientIpHost)
.Where(t => t.LightId == boardId)
.FirstOrDefault();
var smartShelf = shelf as SmartShelf;
smartShelf?.WarningLightProcess(dataTemp, boardId, lightNumber);
}
//!= 0x20 货架类型协议返回
else
{
var shelf = ShelfManager.Shelves
.Where(t => t.ClientIp == clientIpHost)
.Where(t => t.ModuleIds != null && t.ModuleIds.Contains(boardId))
.FirstOrDefault();
var smartShelf = shelf as SmartShelf;
smartShelf?.ProtocolProcess(dataTemp, boardId, lightNumber);
}
Logs.Write($"【处理单条指令 结束】{BitConverter.ToString(dataTemp)}", LogsType.InstructionsProcess);
} }
} }
return EasyTask.CompletedTask; catch (Exception ex)
};
//配置首次连接后复位操作
tcpCleint.tcpClient.Connected += (client, e) =>
{
Logs.Write($"【TcpClient】{client.IP}完成连接,端口号{client.Port}", LogsType.StartBoot);
var clientIpHost = client.IP + ":" + client.Port;
var TcpCleint = TCPClientManager.GetTCPClientByIPHost(clientIpHost);
if (TcpCleint == null)
{ {
return EasyTask.CompletedTask;
} }
//首次连接
if (TcpCleint.IsFirstConnected == false)
{
Logs.Write($"【InitTcpClient】{clientIpHost}完成首次连接", LogsType.StartBoot);
Console.WriteLine($"【InitTcpClient】{clientIpHost}完成首次连接");
InitStatus(TcpCleint);
TcpCleint.IsFirstConnected = true;
//获取剩余未完成连接的tcp
var noFirstConnectedTcps = TCPClientManager.TCPClients.Where(t => t.IsFirstConnected == false)
.Select(t => t.RemoteIPHost)
.ToList();
Logs.Write($"【InitTcpClient】剩余未完成连接的TCP为{string.Join(";", noFirstConnectedTcps)}", LogsType.StartBoot);
}
return EasyTask.CompletedTask;
};
lock (TCPClients)//避免添加失败的情况
{
TCPClients.Add(tcpCleint);
} }
tcpCleint.Connect();
}); });
Logs.Write("【InitTcpClient】完成 后台继续连接", LogsType.StartBoot);
} }
#endregion
//启动线程监听所有TCP是否已经完成首次连接 #region Client的逻辑
Task.Run(() => var moduleClients = DbHelp.db.Queryable<ShelfInfo>()
.WhereIF(!string.IsNullOrEmpty(LocalFile.Config.GroupName), t => t.GroupName == LocalFile.Config.GroupName)
.Where(t => t.IsService == false)
.Select(t => new
{
IP = t.ClientIp,
ShelfTypeName = t.ShelfTypeName,
Port = t.Port,
})
.Distinct()
.ToList();
//有客户端作客户端时才需要初始化一个服务端
if (moduleClients != null && moduleClients.Count > 0)
{ {
while (true) Service = new TcpService();
Service.Connecting = (client, e) =>
{ {
try return EasyTask.CompletedTask;
{ };//有客户端正在连接
Thread.Sleep(1000); Service.Connected = (client, e) => { return EasyTask.CompletedTask; };//有客户端成功连接
var noFirstConnectedClients = TCPClientManager.TCPClients.Where(t => t.IsFirstConnected == false) Service.Disconnecting = (client, e) => { return EasyTask.CompletedTask; };//有客户端正在断开连接,只有当主动断开时才有效。
.ToList(); Service.Disconnected = (client, e) => { return EasyTask.CompletedTask; };//有客户端断开连接
if (noFirstConnectedClients.Count == 0) Service.Received = (client, e) =>
{ {
break; //从客户端收到信息
} var mes = Encoding.UTF8.GetString(e.ByteBlock.Buffer, 0, e.ByteBlock.Len);//注意数据长度是byteBlock.Len
else client.Logger.Info($"已从{client.Id}接收到信息:{mes}");
{
Console.WriteLine($"存在tcp未完成首次连接继续重连");
noFirstConnectedClients.ForEach(t =>
{
t.ReConnectAsync();
});
}
}
catch (Exception ex)
{
} //client.Send(mes);//将收到的信息直接返回给发送方
}
});
Logs.Write("【InitTcpClient】完成 后台继续连接", LogsType.StartBoot); return EasyTask.CompletedTask;
};
Service.Setup(new TouchSocketConfig()//载入配置
.SetListenIPHosts("tcp://0.0.0.0:9999", 7790)//同时监听两个地址
.ConfigureContainer(a =>//容器的配置顺序应该在最前面
{
a.AddConsoleLogger();//添加一个控制台日志注入注意在maui中控制台日志不可用
})
.ConfigurePlugins(a =>
{
//a.Add();//此处可以添加插件
}));
Service.Start();
}
#endregion
} }
//后台启动时给所有板子、警示灯发送复位操作 保持状态一致 //后台启动时给所有板子、警示灯发送复位操作 保持状态一致

View File

@ -75,7 +75,7 @@ namespace WCS.BLL.Services.Service
{ {
var shelfModel = new SingleLightShelfModel(); var shelfModel = new SingleLightShelfModel();
//报警灯 //报警灯
if(shelf.LightId > 0) if (shelf.LightId > 0)
{ {
shelfModel.WarningLightMode = request.LightMode; shelfModel.WarningLightMode = request.LightMode;
} }
@ -96,29 +96,62 @@ namespace WCS.BLL.Services.Service
} }
//合并同一个TCP的货架合并 报警灯和库位灯统一只发送一条指令 //合并同一个TCP的货架合并 报警灯和库位灯统一只发送一条指令
var clientIpList = shelfs.Select(t => t.ClientIp) var clients = shelfs.Select(t => new
.Distinct()
.ToList();
foreach (var clientIp in clientIpList)
{ {
var shelfModelsInOneIp = shelfModels.Where(t => t.ClientIp == clientIp).ToList(); ClientIp = t.ClientIp,
IsService = t.IsService,
})
.Distinct()
.ToList();
foreach (var client in clients)
{
var shelfModelsInOneIp = shelfModels.Where(t => t.ClientIp == client.ClientIp).ToList();
var sendData = Helper.SingleLightControl(shelfModelsInOneIp); var sendData = Helper.SingleLightControl(shelfModelsInOneIp);
TCPClient tcpClient = TCPClientManager.GetTCPClientByIPHost(clientIp); if (client.IsService)
if (tcpClient != null)
{ {
try TCPClient tcpClient = TCPClientManager.GetTCPClientByIPHost(client.ClientIp);
if (tcpClient != null)
{ {
tcpClient.Send(sendData); try
Logs.Write("【单灯单独控制】发送指令" + BitConverter.ToString(sendData)); {
tcpClient.Send(sendData);
Logs.Write("【单灯单独控制】发送指令" + BitConverter.ToString(sendData));
}
catch (Exception ex)
{
Logs.Write($"【单灯单独控制】{client}以下指令发送中遇到异常{ex.Message}" + BitConverter.ToString(sendData));
}
} }
catch (Exception ex) else
{ {
Logs.Write($"【单灯单独控制】{clientIp}以下指令发送中遇到异常{ex.Message}" + BitConverter.ToString(sendData)); Logs.Write($"【单灯单独控制】{client}未连接,以下指令未能成功发送" + BitConverter.ToString(sendData));
} }
} }
else else
{ {
Logs.Write($"【单灯单独控制】{clientIp}未连接,以下指令未能成功发送" + BitConverter.ToString(sendData)); var tcpClient = TCPClientManager.Service.GetClients().Where(t => t.IP + ":" + t.Port.ToString() == client.ClientIp).FirstOrDefault();
if (tcpClient != null)
{
try
{
tcpClient.Send(sendData,0,sendData.Length);
Logs.Write("【单灯单独控制】发送指令" + BitConverter.ToString(sendData));
}
catch (Exception ex)
{
Logs.Write($"【单灯单独控制】{client}以下指令发送中遇到异常{ex.Message}" + BitConverter.ToString(sendData));
}
}
else
{
Logs.Write($"【单灯单独控制】{client}未连接,以下指令未能成功发送" + BitConverter.ToString(sendData));
return new ResponseCommon<object>()
{
Code = 201,
Message = $"【单灯单独控制】{client}未连接,以下指令未能成功发送",
};
}
} }
} }
@ -172,31 +205,64 @@ namespace WCS.BLL.Services.Service
var shelfs = DbHelp.db.Queryable<ShelfInfo>().Where(t => shelfIds.Contains(t.Id)) var shelfs = DbHelp.db.Queryable<ShelfInfo>().Where(t => shelfIds.Contains(t.Id))
.ToList(); .ToList();
//获取对应货架所有IP //获取对应货架所有IP
var clientIPs = shelfs.Select(t => t.ClientIp) var clients = shelfs.Select(t => new
.Distinct() {
.ToList(); ClientIp = t.ClientIp,
IsService = t.IsService,
})
.Distinct()
.ToList();
//挨个发关灯指令 //挨个发关灯指令
foreach (var clientIP in clientIPs) foreach (var client in clients)
{ {
//生成关灯指令 //生成关灯指令
var sendData = Helper.SingleLightTrunOffAllLight(); var sendData = Helper.SingleLightTrunOffAllLight();
TCPClient tcpClient = TCPClientManager.GetTCPClientByIPHost(clientIP);
if (tcpClient != null) if (client.IsService)
{ {
try TCPClient tcpClient = TCPClientManager.GetTCPClientByIPHost(client.ClientIp);
if (tcpClient != null)
{ {
tcpClient.Send(sendData); try
Logs.Write("【单灯单独控制】发送指令" + BitConverter.ToString(sendData)); {
tcpClient.Send(sendData);
Logs.Write("【熄灯】发送指令" + BitConverter.ToString(sendData));
}
catch (Exception ex)
{
Logs.Write($"【熄灯】{client}以下指令发送中遇到异常{ex.Message}" + BitConverter.ToString(sendData));
}
} }
catch (Exception ex) else
{ {
Logs.Write($"【单灯单独控制】{clientIP}以下指令发送中遇到异常{ex.Message}" + BitConverter.ToString(sendData)); Logs.Write($"【熄灯】{client}未连接,以下指令未能成功发送" + BitConverter.ToString(sendData));
} }
} }
else else
{ {
Logs.Write($"【单灯单独控制】{clientIP}未连接,以下指令未能成功发送" + BitConverter.ToString(sendData)); var tcpClient = TCPClientManager.Service.GetClients().Where(t => t.IP + ":" + t.Port.ToString() == client.ClientIp).FirstOrDefault();
if (tcpClient != null)
{
try
{
tcpClient.Send(sendData, 0, sendData.Length);
Logs.Write("【熄灯】发送指令" + BitConverter.ToString(sendData));
}
catch (Exception ex)
{
Logs.Write($"【熄灯】{client}以下指令发送中遇到异常{ex.Message}" + BitConverter.ToString(sendData));
}
}
else
{
Logs.Write($"【熄灯】{client}未连接,以下指令未能成功发送" + BitConverter.ToString(sendData));
return new ResponseCommon<object>()
{
Code = 201,
Message = $"【熄灯】{client}未连接,以下指令未能成功发送",
};
}
} }
} }