@@ -23,15 +23,21 @@ namespace JT808.Gateway.Abstractions | |||||
protected IJT808MsgProducer MsgProducer; | protected IJT808MsgProducer MsgProducer; | ||||
protected IJT808MsgReplyLoggingProducer MsgReplyLoggingProducer; | |||||
protected IOptionsMonitor<JT808Configuration> JT808ConfigurationOptionsMonitor; | protected IOptionsMonitor<JT808Configuration> JT808ConfigurationOptionsMonitor; | ||||
protected IJT808Config JT808Config; | |||||
public JT808MessageHandler( | public JT808MessageHandler( | ||||
IOptionsMonitor<JT808Configuration> jT808ConfigurationOptionsMonitor, | IOptionsMonitor<JT808Configuration> jT808ConfigurationOptionsMonitor, | ||||
IJT808MsgProducer msgProducer, | IJT808MsgProducer msgProducer, | ||||
IJT808MsgReplyLoggingProducer msgReplyLoggingProducer, | |||||
IJT808Config jT808Config) | IJT808Config jT808Config) | ||||
{ | { | ||||
this.JT808Serializer = jT808Config.GetSerializer(); | this.JT808Serializer = jT808Config.GetSerializer(); | ||||
this.MsgProducer = msgProducer; | this.MsgProducer = msgProducer; | ||||
this.MsgReplyLoggingProducer = msgReplyLoggingProducer; | |||||
this.JT808ConfigurationOptionsMonitor = jT808ConfigurationOptionsMonitor; | this.JT808ConfigurationOptionsMonitor = jT808ConfigurationOptionsMonitor; | ||||
HandlerDict = new Dictionary<ushort, MsgIdMethodDelegate> { | HandlerDict = new Dictionary<ushort, MsgIdMethodDelegate> { | ||||
{JT808MsgId.终端通用应答.ToUInt16Value(), Msg0x0001}, | {JT808MsgId.终端通用应答.ToUInt16Value(), Msg0x0001}, | ||||
@@ -56,12 +62,6 @@ namespace JT808.Gateway.Abstractions | |||||
}; | }; | ||||
} | } | ||||
public JT808MessageHandler(IOptionsMonitor<JT808Configuration> jT808ConfigurationOptionsMonitor | |||||
, IJT808Config jT808Config) : this(jT808ConfigurationOptionsMonitor, null, jT808Config) | |||||
{ | |||||
} | |||||
/// <summary> | /// <summary> | ||||
/// 消息处理 | /// 消息处理 | ||||
/// </summary> | /// </summary> | ||||
@@ -85,12 +85,16 @@ namespace JT808.Gateway.Abstractions | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
return func(request, session); | |||||
var data=func(request, session); | |||||
MsgReplyLoggingProducer.ProduceAsync(request.Header.TerminalPhoneNo, data); | |||||
return data; | |||||
} | } | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
return func(request, session); | |||||
var data = func(request, session); | |||||
MsgReplyLoggingProducer.ProduceAsync(request.Header.TerminalPhoneNo, data); | |||||
return data; | |||||
} | } | ||||
} | } | ||||
else | else | ||||
@@ -28,7 +28,7 @@ namespace JT808.Gateway.Kafka | |||||
{ | { | ||||
consumer = new ConsumerBuilder<string, byte[]>(consumerConfigAccessor.Value).Build(); | consumer = new ConsumerBuilder<string, byte[]>(consumerConfigAccessor.Value).Build(); | ||||
TopicName = consumerConfigAccessor.Value.TopicName; | TopicName = consumerConfigAccessor.Value.TopicName; | ||||
logger = loggerFactory.CreateLogger("JT808MsgReplyConsumer"); | |||||
logger = loggerFactory.CreateLogger<JT808MsgReplyConsumer>(); | |||||
} | } | ||||
public void OnMessage(Action<(string TerminalNo, byte[] Data)> callback) | public void OnMessage(Action<(string TerminalNo, byte[] Data)> callback) | ||||
@@ -16,24 +16,33 @@ namespace JT808.Gateway.NormalHosting.Impl | |||||
{ | { | ||||
private readonly ILogger logger; | private readonly ILogger logger; | ||||
//private readonly IJT808Traffic jT808Traffic; | //private readonly IJT808Traffic jT808Traffic; | ||||
private readonly IJT808MsgLogging jT808MsgLogging; | |||||
//private readonly JT808TransmitService jT808TransmitService; | //private readonly JT808TransmitService jT808TransmitService; | ||||
private readonly IJT808MsgLogging jT808MsgLogging; | |||||
private readonly IJT808MsgReplyProducer MsgReplyProducer; | |||||
public JT808CustomMessageHandlerImpl( | public JT808CustomMessageHandlerImpl( | ||||
IOptionsMonitor<JT808Configuration> jT808ConfigurationOptionsMonitor, | |||||
//JT808TransmitService jT808TransmitService, | |||||
ILoggerFactory loggerFactory, | |||||
IJT808MsgReplyProducer msgReplyProducer, | |||||
IJT808MsgLogging jT808MsgLogging, | IJT808MsgLogging jT808MsgLogging, | ||||
//IJT808Traffic jT808Traffic, | |||||
ILoggerFactory loggerFactory, | |||||
IJT808Config jT808Config) : base(jT808ConfigurationOptionsMonitor, jT808Config) | |||||
IOptionsMonitor<JT808Configuration> jT808ConfigurationOptionsMonitor, | |||||
IJT808MsgProducer msgProducer, | |||||
IJT808MsgReplyLoggingProducer msgReplyLoggingProducer, | |||||
IJT808Config jT808Config) : base(jT808ConfigurationOptionsMonitor, | |||||
msgProducer, | |||||
msgReplyLoggingProducer, | |||||
jT808Config) | |||||
{ | { | ||||
MsgReplyProducer = msgReplyProducer; | |||||
//this.jT808TransmitService = jT808TransmitService; | //this.jT808TransmitService = jT808TransmitService; | ||||
//this.jT808Traffic = jT808Traffic; | //this.jT808Traffic = jT808Traffic; | ||||
this.jT808MsgLogging = jT808MsgLogging; | this.jT808MsgLogging = jT808MsgLogging; | ||||
logger =loggerFactory.CreateLogger<JT808CustomMessageHandlerImpl>(); | |||||
logger = loggerFactory.CreateLogger<JT808CustomMessageHandlerImpl>(); | |||||
//添加自定义消息 | //添加自定义消息 | ||||
HandlerDict.Add(0x9999, Msg0x9999); | HandlerDict.Add(0x9999, Msg0x9999); | ||||
} | } | ||||
/// <summary> | /// <summary> | ||||
/// 重写消息处理器 | /// 重写消息处理器 | ||||
/// </summary> | /// </summary> | ||||
@@ -72,7 +81,10 @@ namespace JT808.Gateway.NormalHosting.Impl | |||||
public override byte[] Msg0x0200(JT808HeaderPackage request, IJT808Session session) | public override byte[] Msg0x0200(JT808HeaderPackage request, IJT808Session session) | ||||
{ | { | ||||
logger.LogDebug("重写自带Msg0x0200的消息"); | logger.LogDebug("重写自带Msg0x0200的消息"); | ||||
return base.Msg0x0200(request, session); | |||||
var data = base.Msg0x0200(request, session); | |||||
logger.LogDebug("往应答服务发送相同数据进行测试"); | |||||
MsgReplyProducer.ProduceAsync(request.Header.TerminalPhoneNo, data).ConfigureAwait(false); | |||||
return data; | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||
@@ -0,0 +1,64 @@ | |||||
using JT808.Gateway.Abstractions; | |||||
using JT808.Gateway.NormalHosting.Services; | |||||
using Microsoft.Extensions.Logging; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
using System.Threading; | |||||
using System.Threading.Tasks; | |||||
namespace JT808.Gateway.NormalHosting.Impl | |||||
{ | |||||
public class JT808MsgReplyConsumer : IJT808MsgReplyConsumer | |||||
{ | |||||
public CancellationTokenSource Cts { get; } = new CancellationTokenSource(); | |||||
public string TopicName { get; } = JT808GatewayConstants.MsgReplyTopic; | |||||
private readonly JT808MsgReplyDataService MsgReplyDataService; | |||||
private ILogger logger; | |||||
public JT808MsgReplyConsumer( | |||||
ILoggerFactory loggerFactory, | |||||
JT808MsgReplyDataService msgReplyDataService) | |||||
{ | |||||
MsgReplyDataService = msgReplyDataService; | |||||
logger = loggerFactory.CreateLogger<JT808MsgReplyConsumer>(); | |||||
} | |||||
public void Dispose() | |||||
{ | |||||
} | |||||
public void OnMessage(Action<(string TerminalNo, byte[] Data)> callback) | |||||
{ | |||||
Task.Run(async () => | |||||
{ | |||||
while (!Cts.IsCancellationRequested) | |||||
{ | |||||
try | |||||
{ | |||||
var item = await MsgReplyDataService.ReadAsync(Cts.Token); | |||||
callback(item); | |||||
} | |||||
catch (Exception ex) | |||||
{ | |||||
logger.LogError(ex, ""); | |||||
} | |||||
} | |||||
}, Cts.Token); | |||||
} | |||||
public void Subscribe() | |||||
{ | |||||
} | |||||
public void Unsubscribe() | |||||
{ | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,30 @@ | |||||
using JT808.Gateway.Abstractions; | |||||
using JT808.Gateway.NormalHosting.Services; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace JT808.Gateway.NormalHosting.Impl | |||||
{ | |||||
public class JT808MsgReplyProducer : IJT808MsgReplyProducer | |||||
{ | |||||
public string TopicName { get; } = JT808GatewayConstants.MsgReplyTopic; | |||||
private readonly JT808MsgReplyDataService MsgReplyDataService; | |||||
public JT808MsgReplyProducer(JT808MsgReplyDataService msgReplyDataService) | |||||
{ | |||||
MsgReplyDataService = msgReplyDataService; | |||||
} | |||||
public async ValueTask ProduceAsync(string terminalNo, byte[] data) | |||||
{ | |||||
await MsgReplyDataService.WriteAsync(terminalNo, data); | |||||
} | |||||
public void Dispose() | |||||
{ | |||||
} | |||||
} | |||||
} |
@@ -22,7 +22,7 @@ namespace JT808.Gateway.NormalHosting.Impl | |||||
JT808SessionService jT808SessionService, | JT808SessionService jT808SessionService, | ||||
ILoggerFactory loggerFactory) | ILoggerFactory loggerFactory) | ||||
{ | { | ||||
logger = loggerFactory.CreateLogger("JT808SessionConsumer"); | |||||
logger = loggerFactory.CreateLogger<JT808SessionConsumer>(); | |||||
JT808SessionService = jT808SessionService; | JT808SessionService = jT808SessionService; | ||||
} | } | ||||
@@ -44,11 +44,15 @@ namespace JT808.Gateway.NormalHosting | |||||
services.AddSingleton<JT808SessionService>(); | services.AddSingleton<JT808SessionService>(); | ||||
services.AddSingleton<IJT808SessionProducer, JT808SessionProducer>(); | services.AddSingleton<IJT808SessionProducer, JT808SessionProducer>(); | ||||
services.AddSingleton<IJT808SessionConsumer, JT808SessionConsumer>(); | services.AddSingleton<IJT808SessionConsumer, JT808SessionConsumer>(); | ||||
//使用内存队列实现应答生产消费 | |||||
services.AddSingleton<JT808MsgReplyDataService>(); | |||||
services.AddSingleton<IJT808MsgReplyProducer, JT808MsgReplyProducer>(); | |||||
services.AddJT808Configure() | services.AddJT808Configure() | ||||
//添加客户端工具 | //添加客户端工具 | ||||
//.AddClient() | //.AddClient() | ||||
.AddGateway(hostContext.Configuration) | .AddGateway(hostContext.Configuration) | ||||
.ReplaceMessageHandler<JT808CustomMessageHandlerImpl>() | |||||
.AddMessageHandler<JT808CustomMessageHandlerImpl>() | |||||
.AddMsgReplyConsumer<JT808MsgReplyConsumer>() | |||||
.AddMsgLogging<JT808MsgLogging>() | .AddMsgLogging<JT808MsgLogging>() | ||||
//.AddTraffic() | //.AddTraffic() | ||||
//.AddSessionNotice() | //.AddSessionNotice() | ||||
@@ -56,7 +60,7 @@ namespace JT808.Gateway.NormalHosting | |||||
.AddTcp() | .AddTcp() | ||||
//.AddUdp() | //.AddUdp() | ||||
.AddHttp() | .AddHttp() | ||||
; | |||||
.Register();//必须注册的 | |||||
//流量统计 | //流量统计 | ||||
//services.AddHostedService<TrafficJob>(); | //services.AddHostedService<TrafficJob>(); | ||||
//grpc客户端调用 | //grpc客户端调用 | ||||
@@ -0,0 +1,28 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
using System.Threading; | |||||
using System.Threading.Channels; | |||||
using System.Threading.Tasks; | |||||
namespace JT808.Gateway.NormalHosting.Services | |||||
{ | |||||
public class JT808MsgReplyDataService | |||||
{ | |||||
private readonly Channel<(string TerminalNo, byte[] Data)> _channel; | |||||
public JT808MsgReplyDataService() | |||||
{ | |||||
_channel = Channel.CreateUnbounded<(string TerminalNo, byte[] Data)>(); | |||||
} | |||||
public async ValueTask WriteAsync(string terminalNo, byte[] Data) | |||||
{ | |||||
await _channel.Writer.WriteAsync((terminalNo, Data)); | |||||
} | |||||
public async ValueTask<(string TerminalNo, byte[] Data)> ReadAsync(CancellationToken cancellationToken) | |||||
{ | |||||
return await _channel.Reader.ReadAsync(cancellationToken); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,23 @@ | |||||
using JT808.Gateway.Abstractions; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace JT808.Gateway.Internal | |||||
{ | |||||
class JT808MsgProducer_Empty : IJT808MsgProducer | |||||
{ | |||||
public string TopicName { get; } | |||||
public void Dispose() | |||||
{ | |||||
} | |||||
public ValueTask ProduceAsync(string terminalNo, byte[] data) | |||||
{ | |||||
return default; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,23 @@ | |||||
using JT808.Gateway.Abstractions; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace JT808.Gateway.Internal | |||||
{ | |||||
class JT808MsgReplyLoggingProducer_Empty : IJT808MsgReplyLoggingProducer | |||||
{ | |||||
public string TopicName { get; } | |||||
public void Dispose() | |||||
{ | |||||
} | |||||
public ValueTask ProduceAsync(string terminalNo, byte[] data) | |||||
{ | |||||
return default; | |||||
} | |||||
} | |||||
} |
@@ -1,20 +0,0 @@ | |||||
using JT808.Gateway.Abstractions; | |||||
using JT808.Protocol; | |||||
namespace JT808.Gateway.Internal | |||||
{ | |||||
public class JT808NormalGatewayBuilderDefault : IJT808NormalGatewayBuilder | |||||
{ | |||||
public IJT808Builder JT808Builder { get; } | |||||
public JT808NormalGatewayBuilderDefault(IJT808Builder builder) | |||||
{ | |||||
JT808Builder = builder; | |||||
} | |||||
public IJT808Builder Builder() | |||||
{ | |||||
return JT808Builder; | |||||
} | |||||
} | |||||
} |
@@ -1,20 +0,0 @@ | |||||
using JT808.Gateway.Abstractions; | |||||
using JT808.Protocol; | |||||
namespace JT808.Gateway.Internal | |||||
{ | |||||
public class JT808QueueGatewayBuilderDefault : IJT808QueueGatewayBuilder | |||||
{ | |||||
public IJT808Builder JT808Builder { get; } | |||||
public JT808QueueGatewayBuilderDefault(IJT808Builder builder) | |||||
{ | |||||
JT808Builder = builder; | |||||
} | |||||
public IJT808Builder Builder() | |||||
{ | |||||
return JT808Builder; | |||||
} | |||||
} | |||||
} |
@@ -19,6 +19,12 @@ | |||||
<Product>JT808.Gateway</Product> | <Product>JT808.Gateway</Product> | ||||
<Version>$(JT808GatewayPackageVersion)</Version> | <Version>$(JT808GatewayPackageVersion)</Version> | ||||
</PropertyGroup> | </PropertyGroup> | ||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | |||||
<DocumentationFile>JT808.Gateway.xml</DocumentationFile> | |||||
</PropertyGroup> | |||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | |||||
<DocumentationFile>JT808.Gateway.xml</DocumentationFile> | |||||
</PropertyGroup> | |||||
<ItemGroup> | <ItemGroup> | ||||
<Compile Remove="Internal\JT808NormalGatewayBuilderDefault.cs" /> | <Compile Remove="Internal\JT808NormalGatewayBuilderDefault.cs" /> | ||||
<Compile Remove="Internal\JT808QueueGatewayBuilderDefault.cs" /> | <Compile Remove="Internal\JT808QueueGatewayBuilderDefault.cs" /> | ||||
@@ -0,0 +1,186 @@ | |||||
<?xml version="1.0"?> | |||||
<doc> | |||||
<assembly> | |||||
<name>JT808.Gateway</name> | |||||
</assembly> | |||||
<members> | |||||
<member name="T:JT808.Gateway.Handlers.JT808MsgIdDefaultWebApiHandler"> | |||||
<summary> | |||||
默认消息处理业务实现 | |||||
</summary> | |||||
</member> | |||||
<member name="M:JT808.Gateway.Handlers.JT808MsgIdDefaultWebApiHandler.GetTcpSessionAll(System.String)"> | |||||
<summary> | |||||
会话服务集合 | |||||
</summary> | |||||
<param name="json"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.Handlers.JT808MsgIdDefaultWebApiHandler.QueryTcpSessionByTerminalPhoneNo(System.String)"> | |||||
<summary> | |||||
通过终端手机号查询对应会话 | |||||
</summary> | |||||
<param name="json"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.Handlers.JT808MsgIdDefaultWebApiHandler.RemoveSessionByTerminalPhoneNo(System.String)"> | |||||
<summary> | |||||
会话服务-通过设备终端号移除对应会话 | |||||
</summary> | |||||
<param name="json"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.Handlers.JT808MsgIdDefaultWebApiHandler.GetUdpSessionAll(System.String)"> | |||||
<summary> | |||||
会话服务集合 | |||||
</summary> | |||||
<param name="json"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.Handlers.JT808MsgIdDefaultWebApiHandler.QueryUdpSessionByTerminalPhoneNo(System.String)"> | |||||
<summary> | |||||
通过终端手机号查询对应会话 | |||||
</summary> | |||||
<param name="json"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.Handlers.JT808MsgIdDefaultWebApiHandler.RemoveUdpByTerminalPhoneNo(System.String)"> | |||||
<summary> | |||||
会话服务-通过设备终端号移除对应会话 | |||||
</summary> | |||||
<param name="json"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.Handlers.JT808MsgIdDefaultWebApiHandler.UnificationSend(System.String)"> | |||||
<summary> | |||||
统一下发信息 | |||||
</summary> | |||||
<param name="json"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.JT808GatewayExtensions.AddGateway(JT808.Protocol.IJT808Builder,System.Action{JT808.Gateway.Abstractions.Configurations.JT808Configuration})"> | |||||
<summary> | |||||
添加808网关 | |||||
</summary> | |||||
<param name="jT808Builder"></param> | |||||
<param name="config"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.JT808GatewayExtensions.AddGateway(JT808.Protocol.IJT808Builder,Microsoft.Extensions.Configuration.IConfiguration)"> | |||||
<summary> | |||||
添加808网关 | |||||
</summary> | |||||
<param name="jT808Builder"></param> | |||||
<param name="configuration"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.JT808GatewayExtensions.AddTcp(JT808.Gateway.Abstractions.IJT808GatewayBuilder)"> | |||||
<summary> | |||||
添加tcp服务器 | |||||
</summary> | |||||
<param name="config"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.JT808GatewayExtensions.AddUdp(JT808.Gateway.Abstractions.IJT808GatewayBuilder)"> | |||||
<summary> | |||||
添加udp服务器 | |||||
</summary> | |||||
<param name="config"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.JT808GatewayExtensions.AddHttp(JT808.Gateway.Abstractions.IJT808GatewayBuilder)"> | |||||
<summary> | |||||
添加http服务器 | |||||
</summary> | |||||
<param name="config"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.JT808GatewayExtensions.AddHttp``1(JT808.Gateway.Abstractions.IJT808GatewayBuilder)"> | |||||
<summary> | |||||
添加http服务器 | |||||
</summary> | |||||
<typeparam name="TJT808MsgIdDefaultWebApiHandler"></typeparam> | |||||
<param name="config"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.JT808GatewayExtensions.AddMessageHandler``1(JT808.Gateway.Abstractions.IJT808GatewayBuilder)"> | |||||
<summary> | |||||
添加消息业务处理程序 | |||||
</summary> | |||||
<typeparam name="TJT808MessageHandler"></typeparam> | |||||
<param name="config"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.JT808GatewayExtensions.AddHttpAuthorization``1(JT808.Gateway.Abstractions.IJT808GatewayBuilder)"> | |||||
<summary> | |||||
添加Http服务认证机制 | |||||
</summary> | |||||
<typeparam name="TJT808Authorization"></typeparam> | |||||
<param name="config"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.JT808GatewayExtensions.AddMsgProducer``1(JT808.Gateway.Abstractions.IJT808GatewayBuilder)"> | |||||
<summary> | |||||
添加消息生产者 | |||||
</summary> | |||||
<typeparam name="TJT808MsgProducer"></typeparam> | |||||
<param name="config"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.JT808GatewayExtensions.AddMsgReplyLoggingProducer``1(JT808.Gateway.Abstractions.IJT808GatewayBuilder)"> | |||||
<summary> | |||||
添加消息应答后的应答生产者 | |||||
</summary> | |||||
<typeparam name="TJT808MsgReplyLoggingProducer"></typeparam> | |||||
<param name="config"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.JT808GatewayExtensions.AddMsgReplyConsumer``1(JT808.Gateway.Abstractions.IJT808GatewayBuilder)"> | |||||
<summary> | |||||
添加消息应答消费者 | |||||
</summary> | |||||
<typeparam name="TJT808MsgReplyConsumer"></typeparam> | |||||
<param name="config"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.JT808GatewayExtensions.Register(JT808.Gateway.Abstractions.IJT808GatewayBuilder)"> | |||||
<summary> | |||||
必须注册的 | |||||
</summary> | |||||
<param name="config"></param> | |||||
</member> | |||||
<member name="M:JT808.Gateway.JT808GatewayExtensions.AddJT808Core(JT808.Gateway.Abstractions.IJT808GatewayBuilder)"> | |||||
<summary> | |||||
添加公共模块 | |||||
</summary> | |||||
<param name="config"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Gateway.JT808TcpServer.#ctor(JT808.Gateway.Abstractions.JT808MessageHandler,Microsoft.Extensions.Options.IOptions{JT808.Gateway.Abstractions.Configurations.JT808Configuration},JT808.Protocol.IJT808Config,Microsoft.Extensions.Logging.ILoggerFactory,JT808.Gateway.Session.JT808SessionManager)"> | |||||
<summary> | |||||
使用队列方式 | |||||
</summary> | |||||
<param name="messageHandler"></param> | |||||
<param name="jT808ConfigurationAccessor"></param> | |||||
<param name="jT808Config"></param> | |||||
<param name="loggerFactory"></param> | |||||
<param name="jT808SessionManager"></param> | |||||
</member> | |||||
<member name="T:JT808.Gateway.Session.JT808SessionManager"> | |||||
<summary> | |||||
<remark>不支持变态类型:既发TCP和UDP</remark> | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Gateway.Session.JT808TcpSession.TerminalPhoneNo"> | |||||
<summary> | |||||
终端手机号 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Gateway.Session.JT808UdpSession.TerminalPhoneNo"> | |||||
<summary> | |||||
终端手机号 | |||||
</summary> | |||||
</member> | |||||
</members> | |||||
</doc> |
@@ -11,6 +11,7 @@ using Microsoft.Extensions.DependencyInjection; | |||||
using Microsoft.Extensions.DependencyInjection.Extensions; | using Microsoft.Extensions.DependencyInjection.Extensions; | ||||
using System; | using System; | ||||
using System.Runtime.CompilerServices; | using System.Runtime.CompilerServices; | ||||
using System.Linq; | |||||
[assembly: InternalsVisibleTo("JT808.Gateway.TestHosting")] | [assembly: InternalsVisibleTo("JT808.Gateway.TestHosting")] | ||||
[assembly: InternalsVisibleTo("JT808.Gateway.Test")] | [assembly: InternalsVisibleTo("JT808.Gateway.Test")] | ||||
@@ -18,44 +19,12 @@ namespace JT808.Gateway | |||||
{ | { | ||||
public static partial class JT808GatewayExtensions | public static partial class JT808GatewayExtensions | ||||
{ | { | ||||
//public static IJT808QueueGatewayBuilder AddQueueGateway(this IJT808Builder jT808Builder, Action<JT808Configuration> config) | |||||
//{ | |||||
// IJT808QueueGatewayBuilder server = new JT808QueueGatewayBuilderDefault(jT808Builder); | |||||
// server.JT808Builder.Services.Configure(config); | |||||
// server.AddJT808Core(); | |||||
// server.JT808Builder.Services.AddHostedService<JT808MsgReplyHostedService>(); | |||||
// return server; | |||||
//} | |||||
//public static IJT808NormalGatewayBuilder AddNormalGateway(this IJT808Builder jT808Builder, Action<JT808Configuration> config) | |||||
//{ | |||||
// IJT808NormalGatewayBuilder server = new JT808NormalGatewayBuilderDefault(jT808Builder); | |||||
// server.JT808Builder.Services.AddSingleton<JT808NormalReplyMessageHandler>(); | |||||
// server.JT808Builder.Services.Configure(config); | |||||
// server.AddJT808Core(); | |||||
// return server; | |||||
//} | |||||
//public static IJT808QueueGatewayBuilder AddQueueGateway(this IJT808Builder jT808Builder, IConfiguration configuration) | |||||
//{ | |||||
// IJT808QueueGatewayBuilder server = new JT808QueueGatewayBuilderDefault(jT808Builder); | |||||
// server.JT808Builder.Services.Configure<JT808Configuration>(configuration.GetSection("JT808Configuration")); | |||||
// server.AddJT808Core(); | |||||
// server.JT808Builder.Services.AddHostedService<JT808MsgReplyHostedService>(); | |||||
// return server; | |||||
//} | |||||
//public static IJT808NormalGatewayBuilder AddNormalGateway(this IJT808Builder jT808Builder, IConfiguration configuration) | |||||
//{ | |||||
// IJT808NormalGatewayBuilder server = new JT808NormalGatewayBuilderDefault(jT808Builder); | |||||
// server.JT808Builder.Services.AddSingleton<JT808NormalReplyMessageHandler>(); | |||||
// server.JT808Builder.Services.Configure<JT808Configuration>(configuration.GetSection("JT808Configuration")); | |||||
// server.AddJT808Core(); | |||||
// return server; | |||||
//} | |||||
/// <summary> | |||||
/// 添加808网关 | |||||
/// </summary> | |||||
/// <param name="jT808Builder"></param> | |||||
/// <param name="config"></param> | |||||
/// <returns></returns> | |||||
public static IJT808GatewayBuilder AddGateway(this IJT808Builder jT808Builder, Action<JT808Configuration> config) | public static IJT808GatewayBuilder AddGateway(this IJT808Builder jT808Builder, Action<JT808Configuration> config) | ||||
{ | { | ||||
JT808GatewayBuilderDefault jT808GatewayBuilderDefault = new JT808GatewayBuilderDefault(jT808Builder); | JT808GatewayBuilderDefault jT808GatewayBuilderDefault = new JT808GatewayBuilderDefault(jT808Builder); | ||||
@@ -63,7 +32,12 @@ namespace JT808.Gateway | |||||
jT808GatewayBuilderDefault.AddJT808Core(); | jT808GatewayBuilderDefault.AddJT808Core(); | ||||
return jT808GatewayBuilderDefault; | return jT808GatewayBuilderDefault; | ||||
} | } | ||||
/// <summary> | |||||
/// 添加808网关 | |||||
/// </summary> | |||||
/// <param name="jT808Builder"></param> | |||||
/// <param name="configuration"></param> | |||||
/// <returns></returns> | |||||
public static IJT808GatewayBuilder AddGateway(this IJT808Builder jT808Builder, IConfiguration configuration) | public static IJT808GatewayBuilder AddGateway(this IJT808Builder jT808Builder, IConfiguration configuration) | ||||
{ | { | ||||
JT808GatewayBuilderDefault jT808GatewayBuilderDefault = new JT808GatewayBuilderDefault(jT808Builder); | JT808GatewayBuilderDefault jT808GatewayBuilderDefault = new JT808GatewayBuilderDefault(jT808Builder); | ||||
@@ -71,28 +45,33 @@ namespace JT808.Gateway | |||||
jT808GatewayBuilderDefault.AddJT808Core(); | jT808GatewayBuilderDefault.AddJT808Core(); | ||||
return jT808GatewayBuilderDefault; | return jT808GatewayBuilderDefault; | ||||
} | } | ||||
public static IJT808GatewayBuilder ReplaceMessageHandler<TJT808MessageHandler>(this IJT808GatewayBuilder config) | |||||
where TJT808MessageHandler : JT808MessageHandler | |||||
{ | |||||
config.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(JT808MessageHandler), typeof(TJT808MessageHandler), ServiceLifetime.Singleton)); | |||||
return config; | |||||
} | |||||
/// <summary> | |||||
/// 添加tcp服务器 | |||||
/// </summary> | |||||
/// <param name="config"></param> | |||||
/// <returns></returns> | |||||
public static IJT808GatewayBuilder AddTcp(this IJT808GatewayBuilder config) | public static IJT808GatewayBuilder AddTcp(this IJT808GatewayBuilder config) | ||||
{ | { | ||||
config.JT808Builder.Services.AddHostedService<JT808TcpServer>(); | config.JT808Builder.Services.AddHostedService<JT808TcpServer>(); | ||||
config.JT808Builder.Services.AddHostedService<JT808TcpReceiveTimeoutHostedService>(); | config.JT808Builder.Services.AddHostedService<JT808TcpReceiveTimeoutHostedService>(); | ||||
return config; | return config; | ||||
} | } | ||||
/// <summary> | |||||
/// 添加udp服务器 | |||||
/// </summary> | |||||
/// <param name="config"></param> | |||||
/// <returns></returns> | |||||
public static IJT808GatewayBuilder AddUdp(this IJT808GatewayBuilder config) | public static IJT808GatewayBuilder AddUdp(this IJT808GatewayBuilder config) | ||||
{ | { | ||||
config.JT808Builder.Services.AddHostedService<JT808UdpServer>(); | config.JT808Builder.Services.AddHostedService<JT808UdpServer>(); | ||||
config.JT808Builder.Services.AddHostedService<JT808UdpReceiveTimeoutHostedService>(); | config.JT808Builder.Services.AddHostedService<JT808UdpReceiveTimeoutHostedService>(); | ||||
return config; | return config; | ||||
} | } | ||||
/// <summary> | |||||
/// 添加http服务器 | |||||
/// </summary> | |||||
/// <param name="config"></param> | |||||
/// <returns></returns> | |||||
public static IJT808GatewayBuilder AddHttp(this IJT808GatewayBuilder config) | public static IJT808GatewayBuilder AddHttp(this IJT808GatewayBuilder config) | ||||
{ | { | ||||
config.JT808Builder.Services.AddSingleton<IJT808Authorization, JT808AuthorizationDefault>(); | config.JT808Builder.Services.AddSingleton<IJT808Authorization, JT808AuthorizationDefault>(); | ||||
@@ -100,7 +79,12 @@ namespace JT808.Gateway | |||||
config.JT808Builder.Services.AddHostedService<JT808HttpServer>(); | config.JT808Builder.Services.AddHostedService<JT808HttpServer>(); | ||||
return config; | return config; | ||||
} | } | ||||
/// <summary> | |||||
/// 添加http服务器 | |||||
/// </summary> | |||||
/// <typeparam name="TJT808MsgIdDefaultWebApiHandler"></typeparam> | |||||
/// <param name="config"></param> | |||||
/// <returns></returns> | |||||
public static IJT808GatewayBuilder AddHttp<TJT808MsgIdDefaultWebApiHandler>(this IJT808GatewayBuilder config) | public static IJT808GatewayBuilder AddHttp<TJT808MsgIdDefaultWebApiHandler>(this IJT808GatewayBuilder config) | ||||
where TJT808MsgIdDefaultWebApiHandler: JT808MsgIdDefaultWebApiHandler | where TJT808MsgIdDefaultWebApiHandler: JT808MsgIdDefaultWebApiHandler | ||||
{ | { | ||||
@@ -109,11 +93,88 @@ namespace JT808.Gateway | |||||
config.JT808Builder.Services.AddHostedService<JT808HttpServer>(); | config.JT808Builder.Services.AddHostedService<JT808HttpServer>(); | ||||
return config; | return config; | ||||
} | } | ||||
/// <summary> | |||||
/// 添加消息业务处理程序 | |||||
/// </summary> | |||||
/// <typeparam name="TJT808MessageHandler"></typeparam> | |||||
/// <param name="config"></param> | |||||
/// <returns></returns> | |||||
public static IJT808GatewayBuilder AddMessageHandler<TJT808MessageHandler>(this IJT808GatewayBuilder config) | |||||
where TJT808MessageHandler : JT808MessageHandler | |||||
{ | |||||
config.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(JT808MessageHandler), typeof(TJT808MessageHandler), ServiceLifetime.Singleton)); | |||||
return config; | |||||
} | |||||
/// <summary> | |||||
/// 添加Http服务认证机制 | |||||
/// </summary> | |||||
/// <typeparam name="TJT808Authorization"></typeparam> | |||||
/// <param name="config"></param> | |||||
/// <returns></returns> | |||||
public static IJT808GatewayBuilder AddHttpAuthorization<TJT808Authorization>(this IJT808GatewayBuilder config) | |||||
where TJT808Authorization : IJT808Authorization | |||||
{ | |||||
config.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808Authorization), typeof(TJT808Authorization), ServiceLifetime.Singleton)); | |||||
return config; | |||||
} | |||||
/// <summary> | |||||
/// 添加消息生产者 | |||||
/// </summary> | |||||
/// <typeparam name="TJT808MsgProducer"></typeparam> | |||||
/// <param name="config"></param> | |||||
/// <returns></returns> | |||||
public static IJT808GatewayBuilder AddMsgProducer<TJT808MsgProducer>(this IJT808GatewayBuilder config) | |||||
where TJT808MsgProducer : IJT808MsgProducer | |||||
{ | |||||
config.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgProducer), typeof(TJT808MsgProducer), ServiceLifetime.Singleton)); | |||||
return config; | |||||
} | |||||
/// <summary> | |||||
/// 添加消息应答后的应答生产者 | |||||
/// </summary> | |||||
/// <typeparam name="TJT808MsgReplyLoggingProducer"></typeparam> | |||||
/// <param name="config"></param> | |||||
/// <returns></returns> | |||||
public static IJT808GatewayBuilder AddMsgReplyLoggingProducer<TJT808MsgReplyLoggingProducer>(this IJT808GatewayBuilder config) | |||||
where TJT808MsgReplyLoggingProducer : IJT808MsgReplyLoggingProducer | |||||
{ | |||||
config.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgReplyLoggingProducer), typeof(TJT808MsgReplyLoggingProducer), ServiceLifetime.Singleton)); | |||||
return config; | |||||
} | |||||
/// <summary> | |||||
/// 添加消息应答消费者 | |||||
/// </summary> | |||||
/// <typeparam name="TJT808MsgReplyConsumer"></typeparam> | |||||
/// <param name="config"></param> | |||||
/// <returns></returns> | |||||
public static IJT808GatewayBuilder AddMsgReplyConsumer<TJT808MsgReplyConsumer>(this IJT808GatewayBuilder config) | |||||
where TJT808MsgReplyConsumer : IJT808MsgReplyConsumer | |||||
{ | |||||
config.JT808Builder.Services.Add(new ServiceDescriptor(typeof(IJT808MsgReplyConsumer), typeof(TJT808MsgReplyConsumer), ServiceLifetime.Singleton)); | |||||
return config; | |||||
} | |||||
/// <summary> | |||||
/// 必须注册的 | |||||
/// </summary> | |||||
/// <param name="config"></param> | |||||
public static void Register(this IJT808GatewayBuilder config) | |||||
{ | |||||
if(config.JT808Builder.Services.Where(s => s.ServiceType == typeof(IJT808MsgReplyConsumer)).Count() > 0) | |||||
{ | |||||
config.JT808Builder.Services.AddHostedService<JT808MsgReplyHostedService>(); | |||||
} | |||||
} | |||||
/// <summary> | |||||
/// 添加公共模块 | |||||
/// </summary> | |||||
/// <param name="config"></param> | |||||
/// <returns></returns> | |||||
private static IJT808GatewayBuilder AddJT808Core(this IJT808GatewayBuilder config) | private static IJT808GatewayBuilder AddJT808Core(this IJT808GatewayBuilder config) | ||||
{ | { | ||||
config.JT808Builder.Services.AddSingleton<JT808MessageHandler>(); | config.JT808Builder.Services.AddSingleton<JT808MessageHandler>(); | ||||
config.JT808Builder.Services.AddSingleton<JT808SessionManager>(); | config.JT808Builder.Services.AddSingleton<JT808SessionManager>(); | ||||
config.JT808Builder.Services.AddSingleton<IJT808MsgProducer, JT808MsgProducer_Empty>(); | |||||
config.JT808Builder.Services.AddSingleton<IJT808MsgReplyLoggingProducer, JT808MsgReplyLoggingProducer_Empty>(); | |||||
return config; | return config; | ||||
} | } | ||||
} | } |
@@ -230,7 +230,7 @@ namespace JT808.Gateway | |||||
} | } | ||||
public Task StopAsync(CancellationToken cancellationToken) | public Task StopAsync(CancellationToken cancellationToken) | ||||
{ | { | ||||
Logger.LogInformation("808 Tcp Server Stop"); | |||||
Logger.LogInformation("JT808 Tcp Server Stop"); | |||||
if (server?.Connected ?? false) | if (server?.Connected ?? false) | ||||
server.Shutdown(SocketShutdown.Both); | server.Shutdown(SocketShutdown.Both); | ||||
server?.Close(); | server?.Close(); | ||||
@@ -43,7 +43,7 @@ namespace JT808.Gateway | |||||
JT808MessageHandler messageHandler) | JT808MessageHandler messageHandler) | ||||
{ | { | ||||
SessionManager = jT808SessionManager; | SessionManager = jT808SessionManager; | ||||
Logger = loggerFactory.CreateLogger("JT808UdpServer"); | |||||
Logger = loggerFactory.CreateLogger<JT808UdpServer>(); | |||||
Serializer = jT808Config.GetSerializer(); | Serializer = jT808Config.GetSerializer(); | ||||
Configuration = jT808ConfigurationAccessor.Value; | Configuration = jT808ConfigurationAccessor.Value; | ||||
MessageHandler = messageHandler; | MessageHandler = messageHandler; | ||||
@@ -113,7 +113,7 @@ namespace JT808.Gateway | |||||
} | } | ||||
public Task StopAsync(CancellationToken cancellationToken) | public Task StopAsync(CancellationToken cancellationToken) | ||||
{ | { | ||||
Logger.LogInformation("808 Udp Server Stop"); | |||||
Logger.LogInformation("JT808 Udp Server Stop"); | |||||
if (server?.Connected ?? false) | if (server?.Connected ?? false) | ||||
server.Shutdown(SocketShutdown.Both); | server.Shutdown(SocketShutdown.Both); | ||||
server?.Close(); | server?.Close(); | ||||
@@ -1,49 +0,0 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
using System.Threading; | |||||
namespace JT808.Gateway.Metadata | |||||
{ | |||||
/// <summary> | |||||
/// | |||||
/// <see cref="Grpc.Core.Internal"/> | |||||
/// </summary> | |||||
internal class JT808AtomicCounter | |||||
{ | |||||
long counter = 0; | |||||
public JT808AtomicCounter(long initialCount = 0) | |||||
{ | |||||
this.counter = initialCount; | |||||
} | |||||
public void Reset() | |||||
{ | |||||
Interlocked.Exchange(ref counter, 0); | |||||
} | |||||
public long Increment() | |||||
{ | |||||
return Interlocked.Increment(ref counter); | |||||
} | |||||
public long Add(long len) | |||||
{ | |||||
return Interlocked.Add(ref counter,len); | |||||
} | |||||
public long Decrement() | |||||
{ | |||||
return Interlocked.Decrement(ref counter); | |||||
} | |||||
public long Count | |||||
{ | |||||
get | |||||
{ | |||||
return Interlocked.Read(ref counter); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,6 +1,7 @@ | |||||
using JT808.Gateway.Abstractions; | using JT808.Gateway.Abstractions; | ||||
using JT808.Gateway.Abstractions.Configurations; | using JT808.Gateway.Abstractions.Configurations; | ||||
using JT808.Gateway.Session; | using JT808.Gateway.Session; | ||||
using JT808.Protocol.Extensions; | |||||
using Microsoft.Extensions.Hosting; | using Microsoft.Extensions.Hosting; | ||||
using Microsoft.Extensions.Logging; | using Microsoft.Extensions.Logging; | ||||
using System; | using System; | ||||
@@ -16,19 +17,30 @@ namespace JT808.Gateway.Services | |||||
private readonly IJT808MsgReplyConsumer JT808MsgReplyConsumer; | private readonly IJT808MsgReplyConsumer JT808MsgReplyConsumer; | ||||
private ILogger logger; | |||||
public JT808MsgReplyHostedService( | public JT808MsgReplyHostedService( | ||||
ILoggerFactory loggerFactory, | |||||
IJT808MsgReplyConsumer jT808MsgReplyConsumer, | IJT808MsgReplyConsumer jT808MsgReplyConsumer, | ||||
JT808SessionManager jT808SessionManager) | JT808SessionManager jT808SessionManager) | ||||
{ | { | ||||
JT808MsgReplyConsumer = jT808MsgReplyConsumer; | JT808MsgReplyConsumer = jT808MsgReplyConsumer; | ||||
JT808SessionManager = jT808SessionManager; | JT808SessionManager = jT808SessionManager; | ||||
logger = loggerFactory.CreateLogger<JT808MsgReplyHostedService>(); | |||||
} | } | ||||
public Task StartAsync(CancellationToken cancellationToken) | public Task StartAsync(CancellationToken cancellationToken) | ||||
{ | { | ||||
JT808MsgReplyConsumer.OnMessage(async(item) => | JT808MsgReplyConsumer.OnMessage(async(item) => | ||||
{ | { | ||||
await JT808SessionManager.TrySendByTerminalPhoneNoAsync(item.TerminalNo, item.Data); | |||||
try | |||||
{ | |||||
await JT808SessionManager.TrySendByTerminalPhoneNoAsync(item.TerminalNo, item.Data); | |||||
} | |||||
catch (Exception ex) | |||||
{ | |||||
logger.LogError(ex, $"{item.TerminalNo}-{item.Data.ToHexString()}"); | |||||
} | |||||
}); | }); | ||||
JT808MsgReplyConsumer.Subscribe(); | JT808MsgReplyConsumer.Subscribe(); | ||||
return Task.CompletedTask; | return Task.CompletedTask; | ||||
@@ -29,14 +29,14 @@ namespace JT808.Gateway.Session | |||||
JT808SessionProducer = jT808SessionProducer; | JT808SessionProducer = jT808SessionProducer; | ||||
Sessions = new ConcurrentDictionary<string, IJT808Session>(StringComparer.OrdinalIgnoreCase); | Sessions = new ConcurrentDictionary<string, IJT808Session>(StringComparer.OrdinalIgnoreCase); | ||||
TerminalPhoneNoSessions = new ConcurrentDictionary<string, IJT808Session>(StringComparer.OrdinalIgnoreCase); | TerminalPhoneNoSessions = new ConcurrentDictionary<string, IJT808Session>(StringComparer.OrdinalIgnoreCase); | ||||
logger = loggerFactory.CreateLogger("JT808SessionManager"); | |||||
logger = loggerFactory.CreateLogger<JT808SessionManager>(); | |||||
} | } | ||||
public JT808SessionManager(ILoggerFactory loggerFactory) | public JT808SessionManager(ILoggerFactory loggerFactory) | ||||
{ | { | ||||
Sessions = new ConcurrentDictionary<string, IJT808Session>(StringComparer.OrdinalIgnoreCase); | Sessions = new ConcurrentDictionary<string, IJT808Session>(StringComparer.OrdinalIgnoreCase); | ||||
TerminalPhoneNoSessions = new ConcurrentDictionary<string, IJT808Session>(StringComparer.OrdinalIgnoreCase); | TerminalPhoneNoSessions = new ConcurrentDictionary<string, IJT808Session>(StringComparer.OrdinalIgnoreCase); | ||||
logger = loggerFactory.CreateLogger("JT808SessionManager"); | |||||
logger = loggerFactory.CreateLogger<JT808SessionManager>(); | |||||
} | } | ||||
public int TotalSessionCount | public int TotalSessionCount | ||||
@@ -126,7 +126,7 @@ namespace JT808.Gateway.Session | |||||
public async ValueTask<bool> TrySendByTerminalPhoneNoAsync(string terminalPhoneNo, byte[] data) | public async ValueTask<bool> TrySendByTerminalPhoneNoAsync(string terminalPhoneNo, byte[] data) | ||||
{ | { | ||||
if(TerminalPhoneNoSessions.TryGetValue(terminalPhoneNo,out var session)) | |||||
if (TerminalPhoneNoSessions.TryGetValue(terminalPhoneNo, out var session)) | |||||
{ | { | ||||
if (session.TransportProtocolType == JT808TransportProtocolType.tcp) | if (session.TransportProtocolType == JT808TransportProtocolType.tcp) | ||||
{ | { | ||||