diff --git a/src/JT809Netty.Core/Handlers/JT809DecodeHandler.cs b/src/JT809Netty.Core/Handlers/JT809DecodeHandler.cs index 9a55292..735d97d 100644 --- a/src/JT809Netty.Core/Handlers/JT809DecodeHandler.cs +++ b/src/JT809Netty.Core/Handlers/JT809DecodeHandler.cs @@ -42,6 +42,7 @@ namespace JT809Netty.Core.Handlers if (logger.IsEnabled(LogLevel.Debug)) { msg = ByteBufferUtil.HexDump(buffer); + logger.LogDebug("accept package <<<" + msg); logger.LogDebug("accept package success count<<<" + MsgSuccessCounter.Count.ToString()); } } diff --git a/src/JT809Netty.Core/Handlers/JT809DownMasterLinkConnectionHandler.cs b/src/JT809Netty.Core/Handlers/JT809DownMasterLinkConnectionHandler.cs index fd3cceb..1486b6c 100644 --- a/src/JT809Netty.Core/Handlers/JT809DownMasterLinkConnectionHandler.cs +++ b/src/JT809Netty.Core/Handlers/JT809DownMasterLinkConnectionHandler.cs @@ -10,6 +10,8 @@ using System.Threading.Tasks; using JT809.Protocol; using DotNetty.Buffers; using JT809Netty.Core.ServiceHandlers; +using System.Threading; +using System; namespace JT809Netty.Core.Handlers { @@ -22,20 +24,22 @@ namespace JT809Netty.Core.Handlers private readonly IOptionsMonitor optionsMonitor; - private readonly JT809BusinessTypeHandler jT809BusinessTypeHandler; + private readonly JT809DownMasterLinkBusinessTypeHandler jT809DownMasterLinkBusinessTypeHandler; public JT809DownMasterLinkConnectionHandler( - JT809BusinessTypeHandler jT809BusinessTypeHandler, + JT809DownMasterLinkBusinessTypeHandler jT809DownMasterLinkBusinessTypeHandler, IOptionsMonitor optionsMonitor, ILoggerFactory loggerFactory) { - this.jT809BusinessTypeHandler = jT809BusinessTypeHandler; + this.jT809DownMasterLinkBusinessTypeHandler = jT809DownMasterLinkBusinessTypeHandler; this.optionsMonitor = optionsMonitor; logger = loggerFactory.CreateLogger(); } public override void ChannelActive(IChannelHandlerContext context) { + if (logger.IsEnabled(LogLevel.Debug)) + logger.LogDebug(">>>Activate the channel."); base.ChannelActive(context); } @@ -75,12 +79,12 @@ namespace JT809Netty.Core.Handlers if (idleStateEvent != null) { string channelId = context.Channel.Id.AsShortText(); - logger.LogInformation($"{idleStateEvent.State.ToString()}>>>{channelId}"); switch (idleStateEvent.State) { case IdleState.WriterIdle: //发送心跳保持 - jT809BusinessTypeHandler.Msg0x1005(context); + logger.LogInformation($"{idleStateEvent.State.ToString()} heartbeat>>>{channelId}"); + jT809DownMasterLinkBusinessTypeHandler.Msg0x1005(context); break; } } diff --git a/src/JT809Netty.Core/Handlers/JT809DownMasterLinkServiceHandler.cs b/src/JT809Netty.Core/Handlers/JT809DownMasterLinkServiceHandler.cs index 688850d..88713c9 100644 --- a/src/JT809Netty.Core/Handlers/JT809DownMasterLinkServiceHandler.cs +++ b/src/JT809Netty.Core/Handlers/JT809DownMasterLinkServiceHandler.cs @@ -14,17 +14,20 @@ using JT809.Protocol.JT809Exceptions; namespace JT809Netty.Core.Handlers { + /// + /// 下级平台主链路 + /// public class JT809DownMasterLinkServiceHandler : ChannelHandlerAdapter { private readonly ILogger logger; - private readonly JT809BusinessTypeHandler jT809BusinessTypeHandler; + private readonly JT809DownMasterLinkBusinessTypeHandler jT809DownMasterLinkBusinessTypeHandler; public JT809DownMasterLinkServiceHandler( - JT809BusinessTypeHandler jT809BusinessTypeHandler, + JT809DownMasterLinkBusinessTypeHandler jT809DownMasterLinkBusinessTypeHandler, ILoggerFactory loggerFactory) { - this.jT809BusinessTypeHandler = jT809BusinessTypeHandler; + this.jT809DownMasterLinkBusinessTypeHandler = jT809DownMasterLinkBusinessTypeHandler; logger = loggerFactory.CreateLogger(); } @@ -34,7 +37,12 @@ namespace JT809Netty.Core.Handlers string receive = string.Empty; try { - + if (logger.IsEnabled(LogLevel.Debug)) + logger.LogDebug(JsonConvert.SerializeObject(jT809Package)); + if (jT809DownMasterLinkBusinessTypeHandler.ResponseHandlerDict.TryGetValue(jT809Package.Header.BusinessType,out var action)) + { + action(jT809Package, context); + } } catch (JT809Exception ex) { diff --git a/src/JT809Netty.Core/Handlers/JT809DownSlaveLinkConnectionHandler.cs b/src/JT809Netty.Core/Handlers/JT809DownSlaveLinkConnectionHandler.cs index 97f521b..3a73ba1 100644 --- a/src/JT809Netty.Core/Handlers/JT809DownSlaveLinkConnectionHandler.cs +++ b/src/JT809Netty.Core/Handlers/JT809DownSlaveLinkConnectionHandler.cs @@ -73,15 +73,6 @@ namespace JT809Netty.Core.Handlers case IdleState.ReaderIdle: //下级平台连续 3min 未收到上级平台发送的从链路保持应答数据包,则认为上级平台的连接中断,将主动断开数据传输从链路。 context.CloseAsync(); - break; - //case IdleState.WriterIdle: - - // break; - //case IdleState.AllIdle: - - // break; - default: - break; } } diff --git a/src/JT809Netty.Core/JT809DownMasterLinkNettyService.cs b/src/JT809Netty.Core/JT809DownMasterLinkNettyService.cs index 6659232..baca8d7 100644 --- a/src/JT809Netty.Core/JT809DownMasterLinkNettyService.cs +++ b/src/JT809Netty.Core/JT809DownMasterLinkNettyService.cs @@ -7,8 +7,10 @@ using DotNetty.Transport.Channels.Sockets; using DotNetty.Transport.Libuv; using JT809Netty.Core.Configs; using JT809Netty.Core.Handlers; +using JT809Netty.Core.ServiceHandlers; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; @@ -32,10 +34,20 @@ namespace JT809Netty.Core readonly IOptionsMonitor nettyOptions; + IChannel ClientChannel; + + private readonly JT809DownMasterLinkBusinessTypeHandler jT809DownMasterLinkBusinessTypeHandler; + + private readonly ILogger logger; + public JT809DownMasterLinkNettyService( + ILoggerFactory loggerFactory, + JT809DownMasterLinkBusinessTypeHandler jT809DownMasterLinkBusinessTypeHandler, IOptionsMonitor nettyOptionsAccessor, IServiceProvider serviceProvider) { + logger = loggerFactory.CreateLogger(); + this.jT809DownMasterLinkBusinessTypeHandler = jT809DownMasterLinkBusinessTypeHandler; nettyOptions = nettyOptionsAccessor; this.serviceProvider = serviceProvider; } @@ -54,8 +66,10 @@ namespace JT809Netty.Core { InitChannel(channel); })) - .Option(ChannelOption.SoBacklog, 1048576); - IChannel clientChannel = await bootstrap.ConnectAsync(new IPEndPoint(IPAddress.Parse(nettyOptions.CurrentValue.Host), nettyOptions.CurrentValue.Port)); + .Option(ChannelOption.SoBacklog, 1048576); + ClientChannel = await bootstrap.ConnectAsync(new IPEndPoint(IPAddress.Parse(nettyOptions.CurrentValue.Host), nettyOptions.CurrentValue.Port)); + + jT809DownMasterLinkBusinessTypeHandler.Msg0x1001(ClientChannel); } catch (Exception ex) { @@ -69,11 +83,19 @@ namespace JT809Netty.Core { try { - Task.WhenAll(workerGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1))); + jT809DownMasterLinkBusinessTypeHandler.Msg0x1003(ClientChannel); + // 已发送注销请求,等待30s,待服务器响应 + int sleepTime = 50000; + logger.LogInformation($">>>The logout request has been sent, waiting for {sleepTime/1000}s for the server to respond..."); + Thread.Sleep(sleepTime); + logger.LogInformation($"Check Status:<<<{jT809DownMasterLinkBusinessTypeHandler.Status.ToString()}"); + ClientChannel.CloseAsync().ContinueWith((state) => { + Task.WhenAll(workerGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1))); + }); } catch (Exception ex) { - + logger.LogError(ex,""); } return Task.CompletedTask; } @@ -84,7 +106,7 @@ namespace JT809Netty.Core try { //下级平台应每 1min 发送一个主链路保持清求数据包到上级平台以保持链路连接 - channel.Pipeline.AddLast("systemIdleState", new WriteTimeoutHandler(60)); + channel.Pipeline.AddLast("systemIdleState", new IdleStateHandler(0, 60, 0)); channel.Pipeline.AddLast("jt809DownMasterLinkConnection", scope.ServiceProvider.GetRequiredService()); channel.Pipeline.AddLast("jt809Buffer", new DelimiterBasedFrameDecoder(int.MaxValue, Unpooled.CopiedBuffer(new byte[] { JT809.Protocol.JT809Package.BEGINFLAG }), Unpooled.CopiedBuffer(new byte[] { JT809.Protocol.JT809Package.ENDFLAG }))); channel.Pipeline.AddLast("jt809Decode", scope.ServiceProvider.GetRequiredService()); diff --git a/src/JT809Netty.Core/JT809DownSlaveLinkNettyService.cs b/src/JT809Netty.Core/JT809DownSlaveLinkNettyService.cs index 416c563..6afc032 100644 --- a/src/JT809Netty.Core/JT809DownSlaveLinkNettyService.cs +++ b/src/JT809Netty.Core/JT809DownSlaveLinkNettyService.cs @@ -93,7 +93,7 @@ namespace JT809Netty.Core { var scope = serviceProvider.CreateScope(); //下级平台连续 3min 未收到上级平台发送的从链路保持应答数据包,则认为上级平台的连接中断,将主动断开数据传输从链路。 - channel.Pipeline.AddLast("systemIdleState", new ReadTimeoutHandler(180)); + channel.Pipeline.AddLast("systemIdleState", new IdleStateHandler(180, 0, 0)); channel.Pipeline.AddLast("jt809DownSlaveLinkConnection", scope.ServiceProvider.GetRequiredService()); channel.Pipeline.AddLast("jt809Buffer", new DelimiterBasedFrameDecoder(int.MaxValue, Unpooled.CopiedBuffer(new byte[] { JT809.Protocol.JT809Package.BEGINFLAG }), Unpooled.CopiedBuffer(new byte[] { JT809.Protocol.JT809Package.ENDFLAG }))); channel.Pipeline.AddLast("jt809Decode", scope.ServiceProvider.GetRequiredService()); diff --git a/src/JT809Netty.Core/JT809Netty.Core.csproj b/src/JT809Netty.Core/JT809Netty.Core.csproj index d824e7a..948c147 100644 --- a/src/JT809Netty.Core/JT809Netty.Core.csproj +++ b/src/JT809Netty.Core/JT809Netty.Core.csproj @@ -10,9 +10,9 @@ - - - + + + diff --git a/src/JT809Netty.Core/ServiceHandlers/JT809BusinessTypeHandler.cs b/src/JT809Netty.Core/ServiceHandlers/JT809BusinessTypeHandler.cs deleted file mode 100644 index c39bd7a..0000000 --- a/src/JT809Netty.Core/ServiceHandlers/JT809BusinessTypeHandler.cs +++ /dev/null @@ -1,108 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using DotNetty.Transport.Channels; -using JT809.Protocol; -using JT809.Protocol.JT809Enums; -using JT809.Protocol.JT809MessageBody; -using JT809.Protocol.JT809Extensions; -using DotNetty.Buffers; -using Microsoft.Extensions.Logging; -using Newtonsoft.Json; - -namespace JT809Netty.Core.ServiceHandlers -{ - public class JT809BusinessTypeHandler - { - public Dictionary> RequestHandlerDict { get; } - - public Dictionary> ResponseHandlerDict { get; } - - private readonly ILogger logger; - - /// - /// 初始化业务处理 - /// - public JT809BusinessTypeHandler( - ILoggerFactory loggerFactory - ) - { - logger = loggerFactory.CreateLogger(); - //RequestHandlerDict = new Dictionary> - //{ - // {JT809.Protocol.JT809Enums.JT809BusinessType.UP_CONNECT_REQ, Msg0x1001}, - // {JT809.Protocol.JT809Enums.JT809BusinessType.UP_DISCONNECT_REQ, Msg0x1003}, - // {JT809.Protocol.JT809Enums.JT809BusinessType.UP_LINKTEST_REQ, Msg0x1005}, - // //{JT809.Protocol.JT809Enums.JT809BusinessType.UP_DISCONNECT_INFORM, Msg0x1007}, - // //{JT809.Protocol.JT809Enums.JT809BusinessType.UP_CLOSELINK_INFORM, Msg0x1008}, - //}; - ResponseHandlerDict = new Dictionary> - { - {JT809.Protocol.JT809Enums.JT809BusinessType.UP_CONNECT_RSP, Msg0x1002}, - {JT809.Protocol.JT809Enums.JT809BusinessType.UP_DISCONNECT_RSP, Msg0x1004}, - {JT809.Protocol.JT809Enums.JT809BusinessType.UP_LINKTEST_RSP, Msg0x1006}, - }; - } - - public JT809Package Msg0x1001(IChannelHandlerContext channelHandlerContext) - { - JT809Package loginPackage = JT809BusinessType.UP_CONNECT_REQ.Create(new JT809_0x1001 - { - UserId=1234, - DownLinkIP="127.0.0.1", - DownLinkPort=8091, - Password="20181009" - }); - try - { - byte[] sendLoginData = JT809Serializer.Serialize(loginPackage, 1000); - channelHandlerContext.WriteAndFlushAsync(Unpooled.WrappedBuffer(sendLoginData)); - return loginPackage; - } - catch (Exception) - { - - throw; - } - - } - - public void Msg0x1002(JT809Package jT809Package, IChannelHandlerContext channelHandlerContext) - { - logger.LogDebug(JsonConvert.SerializeObject(jT809Package)); - } - - public JT809Package Msg0x1003(IChannelHandlerContext channelHandlerContext) - { - return null; - } - - public void Msg0x1004(JT809Package jT809Package, IChannelHandlerContext channelHandlerContext) - { - - } - - public JT809Package Msg0x1005(IChannelHandlerContext channelHandlerContext) - { - JT809Package heartbeatPackage = JT809BusinessType.UP_LINKTEST_REQ.Create(new JT809_0x1005()); - byte[] sendHeartbeatData = JT809Serializer.Serialize(heartbeatPackage, 100); - channelHandlerContext.WriteAndFlushAsync(Unpooled.WrappedBuffer(sendHeartbeatData)); - return heartbeatPackage; - } - - public void Msg0x1006(JT809Package jT809Package, IChannelHandlerContext channelHandlerContext) - { - - } - - public JT809Package Msg0x1007(IChannelHandlerContext channelHandlerContext) - { - return null; - } - - public void Msg0x1008(JT809Package jT809Package, IChannelHandlerContext channelHandlerContext) - { - - } - } -} diff --git a/src/JT809Netty.Core/ServiceHandlers/JT809DownMasterLinkBusinessTypeHandler.cs b/src/JT809Netty.Core/ServiceHandlers/JT809DownMasterLinkBusinessTypeHandler.cs new file mode 100644 index 0000000..ec45b62 --- /dev/null +++ b/src/JT809Netty.Core/ServiceHandlers/JT809DownMasterLinkBusinessTypeHandler.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.Text; +using DotNetty.Transport.Channels; +using JT809.Protocol; +using JT809.Protocol.JT809Enums; +using JT809.Protocol.JT809MessageBody; +using JT809.Protocol.JT809Extensions; +using DotNetty.Buffers; +using Microsoft.Extensions.Logging; + +namespace JT809Netty.Core.ServiceHandlers +{ + public class JT809DownMasterLinkBusinessTypeHandler + { + public ConnectionStatus Status { get; private set; } = ConnectionStatus.蓄势待发; + + public Dictionary> RequestHandlerDict { get; } + + public Dictionary> ResponseHandlerDict { get; } + + private readonly ILogger logger; + + public JT809DownMasterLinkBusinessTypeHandler( + ILoggerFactory loggerFactory) + { + logger = loggerFactory.CreateLogger(); + RequestHandlerDict = new Dictionary> + { + {JT809.Protocol.JT809Enums.JT809BusinessType.主链路登录请求消息, Msg0x1001}, + {JT809.Protocol.JT809Enums.JT809BusinessType.主链路注销请求消息, Msg0x1003}, + {JT809.Protocol.JT809Enums.JT809BusinessType.主链路连接保持请求消息, Msg0x1005}, + //{JT809.Protocol.JT809Enums.JT809BusinessType.UP_DISCONNECT_INFORM, Msg0x1007}, + //{JT809.Protocol.JT809Enums.JT809BusinessType.UP_CLOSELINK_INFORM, Msg0x1008}, + }; + ResponseHandlerDict = new Dictionary> + { + {JT809.Protocol.JT809Enums.JT809BusinessType.主链路登录应答消息, Msg0x1002}, + {JT809.Protocol.JT809Enums.JT809BusinessType.主链路注销应答消息, Msg0x1004}, + {JT809.Protocol.JT809Enums.JT809BusinessType.主链路连接保持应答消息, Msg0x1006}, + }; + } + + public enum ConnectionStatus + { + 蓄势待发=0, + 下级平台主链路已发送注销请求=1, + 上级级平台主链路已发送注销应答 = 2, + } + + public JT809Package Msg0x1001(IChannelHandlerContext channelHandlerContext) + { + JT809Package loginPackage = JT809BusinessType.主链路登录请求消息.Create(new JT809_0x1001 + { + UserId = 1234, + Password = "20181009", + DownLinkIP = "127.0.0.1", + DownLinkPort = 8091 + }); + byte[] sendLoginData = JT809Serializer.Serialize(loginPackage, 256); + channelHandlerContext.WriteAndFlushAsync(Unpooled.WrappedBuffer(sendLoginData)); + return loginPackage; + } + + public JT809Package Msg0x1001(IChannel channel) + { + JT809Package loginPackage = JT809BusinessType.主链路登录请求消息.Create(new JT809_0x1001 + { + UserId = 1234, + Password = "20181009", + DownLinkIP = "127.0.0.1", + DownLinkPort = 8091 + }); + byte[] sendLoginData = JT809Serializer.Serialize(loginPackage, 256); + channel.WriteAndFlushAsync(Unpooled.WrappedBuffer(sendLoginData)); + return loginPackage; + } + + public JT809Package Msg0x1003(IChannelHandlerContext channelHandlerContext) + { + JT809Package loginPackage = JT809BusinessType.主链路登录请求消息.Create(new JT809_0x1001 + { + UserId = 1234, + Password = "20181009", + DownLinkIP = "127.0.0.1", + DownLinkPort = 8091 + }); + byte[] sendLoginData = JT809Serializer.Serialize(loginPackage, 256); + channelHandlerContext.WriteAndFlushAsync(Unpooled.WrappedBuffer(sendLoginData)); + return loginPackage; + } + + public JT809Package Msg0x1003(IChannel channel) + { + JT809Package logoutPackage = JT809BusinessType.主链路注销请求消息.Create(new JT809_0x1003 + { + UserId = 1234, + Password = "20181009", + }); + byte[] sendLoginData = JT809Serializer.Serialize(logoutPackage, 128); + channel.WriteAndFlushAsync(Unpooled.WrappedBuffer(sendLoginData)); + Status = ConnectionStatus.下级平台主链路已发送注销请求; + return logoutPackage; + } + + public JT809Package Msg0x1005(IChannelHandlerContext channelHandlerContext) + { + JT809Package heartbeatPackage = JT809BusinessType.主链路连接保持请求消息.Create(); + byte[] sendHeartbeatData = JT809Serializer.Serialize(heartbeatPackage, 100); + channelHandlerContext.WriteAndFlushAsync(Unpooled.WrappedBuffer(sendHeartbeatData)); + return heartbeatPackage; + } + + public JT809Package Msg0x1007(IChannelHandlerContext channelHandlerContext) + { + return null; + } + + public void Msg0x1002(JT809Package jT809Package, IChannelHandlerContext channelHandlerContext) + { + + } + + public void Msg0x1004(JT809Package jT809Package, IChannelHandlerContext channelHandlerContext) + { + Status = ConnectionStatus.上级级平台主链路已发送注销应答; + } + + public void Msg0x1006(JT809Package jT809Package, IChannelHandlerContext channelHandlerContext) + { + + } + + public void Msg0x1008(JT809Package jT809Package, IChannelHandlerContext channelHandlerContext) + { + + } + } +} diff --git a/src/JT809Netty.DownMasterLink/Program.cs b/src/JT809Netty.DownMasterLink/Program.cs index eaeaee9..0b44e86 100644 --- a/src/JT809Netty.DownMasterLink/Program.cs +++ b/src/JT809Netty.DownMasterLink/Program.cs @@ -16,6 +16,14 @@ namespace JT809Netty.DownMasterLink { static async Task Main(string[] args) { + JT809.Protocol.JT809GlobalConfig.Instance + .SetHeaderOptions(new JT809.Protocol.JT809Configs.JT809HeaderOptions + { + MsgGNSSCENTERID= 20141013, + Version=new JT809.Protocol.JT809Header_Version (2,0,0), + EncryptKey=9595 + }); + var serverHostBuilder = new HostBuilder() .UseEnvironment(args[0].Split('=')[1]) .ConfigureAppConfiguration((hostingContext, config) => @@ -36,7 +44,7 @@ namespace JT809Netty.DownMasterLink services.AddSingleton(); services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); services.Configure(hostContext.Configuration.GetSection("JT809NettyOptions")); - services.AddSingleton(); + services.AddSingleton(); services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/src/JT809Netty.sln b/src/JT809Netty.sln index b5c0b22..42fdaa3 100644 --- a/src/JT809Netty.sln +++ b/src/JT809Netty.sln @@ -5,7 +5,7 @@ VisualStudioVersion = 15.0.28010.2016 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT809Netty.Core", "JT809Netty.Core\JT809Netty.Core.csproj", "{2054D7E6-53B6-412F-BE9D-C6DABD80A111}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT809Netty.DownMasterLink", "JT809Netty.DownMasterLink\JT809Netty.DownMasterLink.csproj", "{3BF1D40D-A17D-4FBC-B3FF-B6DF8B3F13ED}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT809Netty.DownMasterLink", "JT809Netty.DownMasterLink\JT809Netty.DownMasterLink.csproj", "{3BF1D40D-A17D-4FBC-B3FF-B6DF8B3F13ED}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution