diff --git a/ConsoleStarter/Program.cs b/ConsoleStarter/Program.cs
index 19fc46a..e6508fb 100644
--- a/ConsoleStarter/Program.cs
+++ b/ConsoleStarter/Program.cs
@@ -1,14 +1,19 @@
// See https://aka.ms/new-console-template for more information
using ConsoleStarter;
+using log4net;
using log4net.Config;
+using Newtonsoft.Json;
internal class Program
{
+
+ private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
public static void Main(string[] args)
{
XmlConfigurator.ConfigureAndWatch(new FileInfo(AppDomain.CurrentDomain.BaseDirectory + @"\log4net.xml"));
- var exportDb = new ExportDb();
- exportDb.Export();
+
+ string str = "{\n\"header\":{\n\"cmd\":\"amtBat\",\n\"id\":1,\n\"sid\":\"xxxx\"\n},\n\"body\":{\n\"sn\": \"xxxx\",\n\"cn\": \"xxxx\",\n\"bn\": \"xxxx\",\n\"bm\": \"xxxx\",\n\"at\": \"2020-11-20 18:23:06\",\n\"am\": 30\n}\n}";
+ Log.Info(str);
}
}
\ No newline at end of file
diff --git a/HybirdFrameworkDriver/HybirdFrameworkDriver.csproj b/HybirdFrameworkDriver/HybirdFrameworkDriver.csproj
index 02708b7..bfcb4b0 100644
--- a/HybirdFrameworkDriver/HybirdFrameworkDriver.csproj
+++ b/HybirdFrameworkDriver/HybirdFrameworkDriver.csproj
@@ -17,6 +17,7 @@
+
diff --git a/HybirdFrameworkDriver/TcpClient/TcpClient.cs b/HybirdFrameworkDriver/TcpClient/TcpClient.cs
index 32dca10..0a0df9e 100644
--- a/HybirdFrameworkDriver/TcpClient/TcpClient.cs
+++ b/HybirdFrameworkDriver/TcpClient/TcpClient.cs
@@ -3,6 +3,8 @@ using System.Reflection;
using Autofac;
using Autofac.Core;
using DotNetty.Codecs;
+using DotNetty.Common.Internal.Logging;
+using DotNetty.Handlers.Logging;
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
@@ -10,6 +12,8 @@ using DotNetty.Transport.Channels.Sockets;
using HybirdFrameworkCore.Autofac;
using HybirdFrameworkCore.Autofac.Attribute;
using log4net;
+using Microsoft.Extensions.Logging;
+using LogLevel = DotNetty.Handlers.Logging.LogLevel;
namespace HybirdFrameworkDriver.TcpClient;
@@ -26,21 +30,37 @@ public class TcpClient where TH : IChannelHandler
public string Host { get; set; }
public int Port { get; set; }
+
+ public LogLevel? LogLevel { get; set; }
public void InitBootstrap(string host, int port, Action? channelInactiveHandler = null)
{
Host = host;
Port = port;
+
+ if (LogLevel != null)
+ {
+ InternalLoggerFactory.DefaultFactory.AddProvider(new Log4NetProvider());
+ }
+
_bootstrap = new Bootstrap();
_bootstrap
.Group(new MultithreadEventLoopGroup())
.Channel()
.Option(ChannelOption.TcpNodelay, true)
+ .Handler(new LoggingHandler())
.Handler(new ActionChannelInitializer(channel =>
{
var clientListenerHandler = new ClientListenerHandler(this);
+
var pipeline = channel.Pipeline;
+
+ if (LogLevel != null)
+ {
+ pipeline.AddLast(new LoggingHandler(LogLevel.Value));
+ }
+
// 监听器
pipeline.AddLast(clientListenerHandler);
pipeline.AddLast("idleStateHandler", new IdleStateHandler(30, 0, 0)); // 触发读取超时
diff --git a/HybirdFrameworkDriver/TcpServer/TcpServer.cs b/HybirdFrameworkDriver/TcpServer/TcpServer.cs
index 5afc53b..0faa7a8 100644
--- a/HybirdFrameworkDriver/TcpServer/TcpServer.cs
+++ b/HybirdFrameworkDriver/TcpServer/TcpServer.cs
@@ -2,6 +2,7 @@
using Autofac;
using Autofac.Core;
using DotNetty.Codecs;
+using DotNetty.Common.Internal.Logging;
using DotNetty.Handlers.Logging;
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Bootstrapping;
@@ -10,6 +11,8 @@ using DotNetty.Transport.Channels.Sockets;
using HybirdFrameworkCore.Autofac;
using HybirdFrameworkCore.Autofac.Attribute;
using log4net;
+using Microsoft.Extensions.Logging;
+using LogLevel = DotNetty.Handlers.Logging.LogLevel;
namespace HybirdFrameworkDriver.TcpServer;
@@ -27,9 +30,15 @@ public class TcpServer | : IDisposable where TH : IChannelHandler
private static ServerBootstrap? bootstrap;
private int _port = 9000;
+
+ public LogLevel? LogLevel { get; set; }
public TcpServer()
{
+ if (LogLevel != null)
+ {
+ InternalLoggerFactory.DefaultFactory.AddProvider(new Log4NetProvider());
+ }
bossGroup = new MultithreadEventLoopGroup();
workerGroup = new MultithreadEventLoopGroup();
bootstrap = new ServerBootstrap();
@@ -42,7 +51,10 @@ public class TcpServer | : IDisposable where TH : IChannelHandler
{
var serverListenerHandler = new ServerListenerHandler | ();
var pipeline = channel.Pipeline;
- pipeline.AddLast(new LoggingHandler(""));
+ if (LogLevel != null)
+ {
+ pipeline.AddLast(new LoggingHandler(LogLevel.Value));
+ }
pipeline.AddLast(serverListenerHandler);
pipeline.AddLast(new IdleStateHandler(0, 0, 180)); //检测空闲连接
//业务handler ,这里是实际处理业务的Handler
diff --git a/Service/Cloud/Client/CloudClient.cs b/Service/Cloud/Client/CloudClient.cs
index 04776d0..5892147 100644
--- a/Service/Cloud/Client/CloudClient.cs
+++ b/Service/Cloud/Client/CloudClient.cs
@@ -1,12 +1,34 @@
using System.Text;
+using Autofac;
+using Autofac.Core;
+using HybirdFrameworkCore.Autofac;
+using HybirdFrameworkCore.Autofac.Attribute;
+using log4net;
+using MQTTnet;
using MQTTnet.Client;
+using MQTTnet.Client.Connecting;
+using MQTTnet.Client.Disconnecting;
+using MQTTnet.Client.Options;
+using MQTTnet.Client.Publishing;
+using MQTTnet.Client.Receiving;
using MQTTnet.Formatter;
+using MQTTnet.Protocol;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Linq;
+using Service.Cloud.Handler;
+using Service.Cloud.Msg;
+using Service.Cloud.Msg.Host.Req;
namespace Service.Cloud.Client;
-public class CloudClient
+[Scope("SingleInstance")]
+public class CloudClient : IMqttClientConnectedHandler, IMqttApplicationMessageReceivedHandler,
+ IMqttClientDisconnectedHandler
{
- #region client param
+ private static readonly ILog Log = LogManager.GetLogger(typeof(CloudClient));
+
+ #region tcp param
public string ServerIp { get; set; }
public int ServerPort { get; set; }
@@ -20,8 +42,251 @@ public class CloudClient
#endregion
+ #region property
+
+ public bool Connected { get; set; }
+ public bool AutoReConnect { get; set; }
+
+ public string StationNo { get; set; }
+ public string SubTopic { get; set; }
+
+ public string PubTopic { get; set; }
+
+ public int Encrypt { get; set; }
+
+ public string? AesKey { get; set; }
+
+ #endregion
+
+
+ private IMqttClient? MqttClient;
+
+ private List handlers = new List();
+
+ private static ushort _incrementId;
+
+ private static ushort GetIncrementId()
+ {
+ if (_incrementId < 65535)
+ {
+ _incrementId += 1;
+ }
+ else
+ {
+ _incrementId = 1;
+ }
+
+ return _incrementId;
+ }
+
+ public void InitHandler()
+ {
+ var list = new List();
+
+ foreach (var reg in AppInfo.Container.ComponentRegistry.Registrations)
+ foreach (var service in reg.Services)
+ if (service is TypedService ts)
+ if (MatchHandlers(ts))
+ list.Add(ts.ServiceType);
+
+
+ foreach (var type in list)
+ {
+ var resolve = AppInfo.Container.Resolve(type);
+ handlers.Add((IBaseHandler)resolve);
+ }
+ }
+
+ private bool MatchHandlers(TypedService ts)
+ {
+ var interfaces = ts.ServiceType.GetInterfaces();
+ if (interfaces.Length > 0)
+ foreach (var type in interfaces)
+ {
+ if (type.ToString().Contains("Service.Cloud.Handler"))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ public void Connect()
+ {
+ Log.Info($"begin connect cloud {ServerIp}:{ServerPort} with client={ClientId}");
+ if (MqttClient == null)
+ {
+ MqttClient = new MqttFactory().CreateMqttClient();
+ MqttClient.ConnectedHandler = this;
+ MqttClient.ApplicationMessageReceivedHandler = this;
+ MqttClient.DisconnectedHandler = this;
+ }
+
+ try
+ {
+ var task = MqttClient.ConnectAsync(BuildOptions());
+ MqttClientConnectResult result = task.Result;
+ Log.Info($"connect cloud {result.ResultCode}");
+ if (result.ResultCode == MqttClientConnectResultCode.Success)
+ {
+ Connected = true;
+ }
+ else
+ {
+ Connected = false;
+ if (AutoReConnect)
+ {
+ Connect();
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Log.Error("connect cloud error", e);
+ if (AutoReConnect)
+ {
+ Connect();
+ }
+ }
+ }
+
+ ///
+ /// 连接成功回调
+ ///
+ ///
+ ///
+ public async Task HandleConnectedAsync(MqttClientConnectedEventArgs eventArgs)
+ {
+ await DoSubTopic(SubTopic);
+ Publish(new SignIn());
+ }
+
+ private async Task DoSubTopic(string topic)
+ {
+ List list = new List();
+ string[] topics = topic.Split(new char[] { ',' });
+ foreach (string str in topics)
+ {
+ MqttTopicFilter topicFilter = new MqttTopicFilter
+ {
+ Topic = str,
+ QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce
+ };
+ list.Add(topicFilter);
+ }
+
+ await MqttClient.SubscribeAsync(list.ToArray());
+
+ Log.Info($"subscribe {topic} success ");
+ }
+
+ public void Publish(T data) where T : ICmd
+ {
+ Model model = new Model
+ {
+ Header = new Header()
+ {
+ cmd = data.GetCmd(),
+ chipherFlag = Encrypt,
+ id = GetIncrementId(),
+ sid = StationNo,
+ timeStamp = DateTime.Now.Millisecond
+ },
+ body = data
+ };
+
+ model.dataSign = SignData(model);
+
+ var appMsg = new MqttApplicationMessage
+ {
+ Topic = PubTopic,
+ Payload = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(model)),
+ QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce,
+ Retain = false
+ };
+
+ Task task = MqttClient.PublishAsync(appMsg);
+ var result = task.Result;
+ if (result.ReasonCode == MqttClientPublishReasonCode.Success)
+ {
+ Log.Info($"send {JsonConvert.SerializeObject(model)} success");
+ }
+ }
+
+ private string SignData(Model model) where T : ICmd
+ {
+ IsoDateTimeConverter timeConverter = new IsoDateTimeConverter();
+ timeConverter.DateTimeFormat = "yyyy-MM-dd HH:mm:ss";
+ string body = JsonConvert.SerializeObject(model.body, timeConverter);
+ return body + ":" + model.Header.timeStamp + ":" + model.Header.id;
+ }
+
+ ///
+ /// 消息接收回调
+ ///
+ ///
+ ///
+ public Task HandleApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs eventArgs)
+ {
+ var message = eventArgs.ApplicationMessage;
+ if (message.Topic != SubTopic)
+ {
+ return Task.CompletedTask;
+ }
+
+ if (message.Payload == null)
+ {
+ return Task.CompletedTask;
+ }
+
+ string s = Encoding.UTF8.GetString(message.Payload);
+ if (string.IsNullOrWhiteSpace(s))
+ {
+ return Task.CompletedTask;
+ }
+
+ Log.Info($"from cloud receive {s} ");
+ JObject objResult = JObject.Parse(s);
+ string headerStr = objResult["header"].ToString();
+ Header? header = JsonConvert.DeserializeObject(headerStr);
+ if (header == null)
+ {
+ return Task.CompletedTask;
+ }
+
+ foreach (IBaseHandler handler in handlers)
+ {
+ if (handler.CanHandle(header.cmd))
+ {
+ string bodyStr = objResult["body"].ToString();
+ handler.Handle(bodyStr);
+ break;
+ }
+ }
+ return Task.CompletedTask;
+ }
+
+
+ ///
+ /// 断开回调
+ ///
+ ///
+ ///
+ public Task HandleDisconnectedAsync(MqttClientDisconnectedEventArgs eventArgs)
+ {
+ Log.Info("cloud disconnect");
+ Connected = false;
+ if (AutoReConnect)
+ {
+ return Task.Run(Connect);
+ }
+
+ return Task.CompletedTask;
+ }
- private MqttClientOptions BuildOptions()
+ private IMqttClientOptions BuildOptions()
{
MqttClientOptionsBuilder builder =
new MqttClientOptionsBuilder().WithTcpServer(ServerIp, ServerPort).WithClientId(ClientId);
@@ -35,7 +300,8 @@ public class CloudClient
builder.WithCleanSession();
}
- builder.WithKeepAlivePeriod(TimeSpan.FromSeconds(KeepalivePeriod)).WithTimeout(TimeSpan.FromSeconds(Timeout));
+ builder.WithKeepAlivePeriod(TimeSpan.FromSeconds(KeepalivePeriod))
+ .WithCommunicationTimeout(TimeSpan.FromSeconds(Timeout));
switch (Version)
{
case "3.1.0":
diff --git a/Service/Cloud/Client/CloudClientMgr.cs b/Service/Cloud/Client/CloudClientMgr.cs
new file mode 100644
index 0000000..14fd7d9
--- /dev/null
+++ b/Service/Cloud/Client/CloudClientMgr.cs
@@ -0,0 +1,17 @@
+using Autofac;
+using HybirdFrameworkCore.Autofac;
+using HybirdFrameworkCore.Autofac.Attribute;
+
+namespace Service.Cloud.Client;
+
+[Scope("SingleInstance")]
+public class CloudClientMgr
+{
+ public static CloudClient? CloudClient { get; set; }
+
+ public static void Init()
+ {
+ CloudClient = AppInfo.Container.Resolve();
+ CloudClient.InitHandler();
+ }
+}
\ No newline at end of file
diff --git a/Service/Cloud/Common/CloudConst.cs b/Service/Cloud/Common/CloudConst.cs
index 1a6bc8b..b5be3ac 100644
--- a/Service/Cloud/Common/CloudConst.cs
+++ b/Service/Cloud/Common/CloudConst.cs
@@ -6,6 +6,8 @@ public class CloudConst
public static readonly string signIn = "signIn";
public static readonly string signInRes = "signInRes";
+ public static readonly string amtBat = "amtBat";
+ public static readonly string amtBatRes = "amtBatRes";
#endregion
}
\ No newline at end of file
diff --git a/Service/Cloud/Handler/AmtBatHandler.cs b/Service/Cloud/Handler/AmtBatHandler.cs
new file mode 100644
index 0000000..64cd936
--- /dev/null
+++ b/Service/Cloud/Handler/AmtBatHandler.cs
@@ -0,0 +1,20 @@
+using HybirdFrameworkCore.Autofac.Attribute;
+using Newtonsoft.Json;
+using Service.Cloud.Common;
+using Service.Cloud.Msg.Cloud.Req;
+
+namespace Service.Cloud.Handler;
+
+[Scope("InstancePerDependency")]
+public class AmtBatHandler : IBaseHandler
+{
+ public void Handle(string t)
+ {
+ AmtBat? amtBat = JsonConvert.DeserializeObject(t);
+ }
+
+ public bool CanHandle(string cmd)
+ {
+ return CloudConst.amtBat == cmd;
+ }
+}
\ No newline at end of file
diff --git a/Service/Cloud/Handler/IBaseHandler.cs b/Service/Cloud/Handler/IBaseHandler.cs
index fcbb96d..89c8f3c 100644
--- a/Service/Cloud/Handler/IBaseHandler.cs
+++ b/Service/Cloud/Handler/IBaseHandler.cs
@@ -1,11 +1,8 @@
namespace Service.Cloud.Handler;
-public interface IBaseHandler
+public interface IBaseHandler
{
- public void Handler(T t);
+ public bool CanHandle(string cmd);
- public bool CanHandle(object obj)
- {
- return obj.GetType() == typeof(T);
- }
+ public void Handle(string t);
}
\ No newline at end of file
diff --git a/Service/Cloud/Handler/SignInRespHandler.cs b/Service/Cloud/Handler/SignInRespHandler.cs
index fc3ade3..2b4569a 100644
--- a/Service/Cloud/Handler/SignInRespHandler.cs
+++ b/Service/Cloud/Handler/SignInRespHandler.cs
@@ -1,13 +1,23 @@
using HybirdFrameworkCore.Autofac.Attribute;
+using Newtonsoft.Json;
+using Service.Cloud.Common;
using Service.Cloud.Msg;
using Service.Cloud.Msg.Cloud.Resp;
namespace Service.Cloud.Handler;
[Scope("InstancePerDependency")]
-public class SignInRespHandler : IBaseHandler>
+public class SignInRespHandler : IBaseHandler
{
- public void Handler(Model t)
+
+ public void Handle(string t)
{
+ SignInResp? signInResp = JsonConvert.DeserializeObject(t);
}
+
+ public bool CanHandle(string cmd)
+ {
+ return CloudConst.signInRes == cmd;
+ }
+
}
\ No newline at end of file
diff --git a/Service/Cloud/Msg/Cloud/Req/AmtBat.cs b/Service/Cloud/Msg/Cloud/Req/AmtBat.cs
new file mode 100644
index 0000000..c2ecf59
--- /dev/null
+++ b/Service/Cloud/Msg/Cloud/Req/AmtBat.cs
@@ -0,0 +1,17 @@
+using Service.Cloud.Common;
+
+namespace Service.Cloud.Msg.Cloud.Req;
+
+public class AmtBat : ICmd
+{
+ public string sn { get; set; }
+ public string cn { get; set; }
+ public string bn { get; set; }
+ public int bm { get; set; }
+ public DateTime at { get; set; }
+ public int am { get; set; }
+ public string GetCmd()
+ {
+ return CloudConst.amtBat;
+ }
+}
\ No newline at end of file
diff --git a/Service/Cloud/Msg/Host/Req/SignIn.cs b/Service/Cloud/Msg/Host/Req/SignIn.cs
index a53f263..f5d2a4a 100644
--- a/Service/Cloud/Msg/Host/Req/SignIn.cs
+++ b/Service/Cloud/Msg/Host/Req/SignIn.cs
@@ -1,6 +1,6 @@
using Service.Cloud.Common;
-namespace Service.Cloud.Msg;
+namespace Service.Cloud.Msg.Host.Req;
public class SignIn : ICmd
{
diff --git a/Service/Cloud/Msg/Host/Resp/AmtBatRes.cs b/Service/Cloud/Msg/Host/Resp/AmtBatRes.cs
new file mode 100644
index 0000000..19ed67a
--- /dev/null
+++ b/Service/Cloud/Msg/Host/Resp/AmtBatRes.cs
@@ -0,0 +1,13 @@
+using Service.Cloud.Common;
+
+namespace Service.Cloud.Msg.Host.Resp;
+
+public class AmtBatRes : ICmd
+{
+ public int rs { get; set; }
+
+ public string GetCmd()
+ {
+ return CloudConst.amtBatRes;
+ }
+}
\ No newline at end of file
diff --git a/Service/Service.csproj b/Service/Service.csproj
index 18ef796..b3a7682 100644
--- a/Service/Service.csproj
+++ b/Service/Service.csproj
@@ -14,7 +14,8 @@
-
+
+
@@ -29,9 +30,4 @@
-
-
-
-
-
diff --git a/Service/Station/StationParamConst.cs b/Service/Station/StationParamConst.cs
new file mode 100644
index 0000000..d99cfe0
--- /dev/null
+++ b/Service/Station/StationParamConst.cs
@@ -0,0 +1,7 @@
+namespace Service.Station;
+
+public class StationParamConst
+{
+ public static readonly string StationNo = "Station.StationNo";
+ public static readonly string StationName = "Station.StationName";
+}
\ No newline at end of file
diff --git a/Service/System/SysConfigService.cs b/Service/System/SysConfigService.cs
index 0128e45..e4e0b87 100644
--- a/Service/System/SysConfigService.cs
+++ b/Service/System/SysConfigService.cs
@@ -158,11 +158,11 @@ namespace Service.System
///
///
///
- /// GroupCode#code
+ /// GroupCode.code
///
public string? Get(string key)
{
- string[] keys = key.Split("#");
+ string[] keys = key.Split('.');
if (keys.Length !=2)
{
throw new InvalidParameterException("配置数据key格式错误");
@@ -180,11 +180,11 @@ namespace Service.System
///
///
///
- /// GroupCode#code
+ /// GroupCode.code
///
public void Set(string key, string value)
{
- string[] keys = key.Split("#");
+ string[] keys = key.Split('.');
if (keys.Length !=2)
{
throw new InvalidParameterException("配置数据key格式错误");
diff --git a/WebStarter/Program.cs b/WebStarter/Program.cs
index 598454c..b480f9f 100644
--- a/WebStarter/Program.cs
+++ b/WebStarter/Program.cs
@@ -1,3 +1,4 @@
+using System.Text;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Entity.Dto.Resp;
@@ -8,10 +9,9 @@ using HybirdFrameworkCore.Redis;
using Mapster;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
-using Microsoft.OpenApi.Models;
+using Service.Cloud.Client;
using SqlSugar;
using SqlSugar.IOC;
-using System.Text;
var builder = WebApplication.CreateBuilder(args);
@@ -142,4 +142,6 @@ app.MapControllers();
AppInfo.Container = app.Services.GetAutofacRoot();
+CloudClientMgr.Init();
+
app.Run();
\ No newline at end of file
| |