@@ -48,12 +48,12 @@ | |||
|服务名称|服务说明|使用场景| | |||
|:------:|:------|:------| | |||
|JT808.DotNetty.MsgIdHandler| 消息处理服务|从队列中消费设备上报数据,再结合自身的业务场景,将数据进行处理并入库 | | |||
|JT808.DotNetty.MsgLogging | 消息日志服务|从队列中消费设备上报和平台应答数据,再将数据存入influxdb等数据库中,便于技术和技术支持排查设备与平台交互的原始数据| | |||
|JT808.DotNetty.ReplyMessage| 消息响应服务| 用于响应设备上报消息,以及下发指令信息到设备| | |||
|JT808.DotNetty.SessionNotice| 会话管理服务| 通知设备上线下线,对于udp设备来说,可以在设备上线时,将指令跟随消息下发到设备| | |||
|JT808.DotNetty.Traffic|流量统计服务 |由于运营商sim卡查询流量滞后,通过流量统计服务可以实时准确的统计设备流量,可以最优配置设备的流量大小,以节省成本 | |||
|JT808.DotNetty.Transmit| 原包转发服务|该服务可以将设备上报原始数据转发到第三方,支持全部转发,指定终端号转发| | |||
|MsgIdHandler| 消息处理服务|从队列中消费设备上报数据,再结合自身的业务场景,将数据进行处理并入库 | | |||
|MsgLogging | 消息日志服务|从队列中消费设备上报和平台应答数据,再将数据存入influxdb等数据库中,便于技术和技术支持排查设备与平台交互的原始数据| | |||
|ReplyMessage| 消息响应服务| 用于响应设备上报消息,以及下发指令信息到设备| | |||
|SessionNotice| 会话管理服务| 通知设备上线下线,对于udp设备来说,可以在设备上线时,将指令跟随消息下发到设备| | |||
|Traffic|流量统计服务 |由于运营商sim卡查询流量滞后,通过流量统计服务可以实时准确的统计设备流量,可以最优配置设备的流量大小,以节省成本 | |||
|Transmit| 原包转发服务|该服务可以将设备上报原始数据转发到第三方,支持全部转发,指定终端号转发| | |||
## NuGet安装 | |||
@@ -0,0 +1,19 @@ | |||
using Microsoft.Extensions.Options; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.CleintBenchmark.Configs | |||
{ | |||
public class ClientBenchmarkOptions : IOptions<ClientBenchmarkOptions> | |||
{ | |||
public string IP { get; set; } | |||
public int Port { get; set; } | |||
public int DeviceCount { get; set; } = 10; | |||
/// <summary> | |||
/// 5000ms毫秒 | |||
/// </summary> | |||
public int Interval { get; set; } = 5000; | |||
public ClientBenchmarkOptions Value =>this; | |||
} | |||
} |
@@ -0,0 +1,36 @@ | |||
<?xml version="1.0" encoding="utf-8" ?> | |||
<!-- | |||
参考:http://www.cnblogs.com/fuchongjundream/p/3936431.html | |||
autoReload:自动再配置 | |||
internalLogFile:可以让NLog把内部的调试和异常信息都写入指定文件里程序没问题了,日志却出了问题。这个该怎么办,到底是哪里不正确了?假如日志本身除了bug该如何解决?这就需要日志排错。把日志的错误信息写入日志。 | |||
<nlog throwExceptions="true" /> | |||
<nlog internalLogFile="file.txt" />- 设置internalLogFile属性可以让NLog把内部的调试和异常信息都写入指定文件里。 | |||
<nlog internalLogLevel="Trace|Debug|Info|Warn|Error|Fatal" /> - 决定内部日志的级别,级别越高,输出的日志信息越简洁。 | |||
<nlog internalLogToConsole="false|true" /> - 是否把内部日志输出到标准控制台。 | |||
<nlog internalLogToConsoleError="false|true" /> - 是否把内部日志输出到标准错误控制台 (stderr)。 | |||
设置throwExceptions属性为“true”可以让NLog不再阻挡这类异常,而是把它们抛给调用者。在部署是这样做可以帮我们快速定位问题。一旦应用程序已经正确配置了,我们建议把throwExceptions的值设为“false”,这样由于日志引发的问题不至于导致应用程序的崩溃。 | |||
--> | |||
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd" | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
autoReload="true" | |||
internalLogFile="/data/logs/JT808.DotNetty.Hosting/internalLog.txt" | |||
internalLogLevel="Debug" > | |||
<variable name="Directory" value="/data/logs/JT808.DotNetty.Hosting"/> | |||
<targets> | |||
<target name="all" xsi:type="File" | |||
fileName="${Directory}/all/${shortdate}.log" | |||
layout="${date:format=yyyyMMddHHmmss} ${callsite} ${level}:${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}"/> | |||
<target name="console" xsi:type="ColoredConsole" | |||
useDefaultRowHighlightingRules="false" | |||
layout="${date:format=yyyyMMddHHmmss} ${callsite} ${level} ${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}"> | |||
<highlight-row condition="level == LogLevel.Debug" foregroundColor="DarkGray" /> | |||
<highlight-row condition="level == LogLevel.Info" foregroundColor="Gray" /> | |||
<highlight-row condition="level == LogLevel.Warn" foregroundColor="Yellow" /> | |||
<highlight-row condition="level == LogLevel.Error" foregroundColor="Red" /> | |||
<highlight-row condition="level == LogLevel.Fatal" foregroundColor="Red" backgroundColor="White" /> | |||
</target> | |||
</targets> | |||
<rules> | |||
<logger name="*" minlevel="Debug" maxlevel="Fatal" writeTo="all,console"/> | |||
</rules> | |||
</nlog> |
@@ -0,0 +1,35 @@ | |||
<?xml version="1.0" encoding="utf-8" ?> | |||
<!-- | |||
参考:http://www.cnblogs.com/fuchongjundream/p/3936431.html | |||
autoReload:自动再配置 | |||
internalLogFile:可以让NLog把内部的调试和异常信息都写入指定文件里程序没问题了,日志却出了问题。这个该怎么办,到底是哪里不正确了?假如日志本身除了bug该如何解决?这就需要日志排错。把日志的错误信息写入日志。 | |||
<nlog throwExceptions="true" /> | |||
<nlog internalLogFile="file.txt" />- 设置internalLogFile属性可以让NLog把内部的调试和异常信息都写入指定文件里。 | |||
<nlog internalLogLevel="Trace|Debug|Info|Warn|Error|Fatal" /> - 决定内部日志的级别,级别越高,输出的日志信息越简洁。 | |||
<nlog internalLogToConsole="false|true" /> - 是否把内部日志输出到标准控制台。 | |||
<nlog internalLogToConsoleError="false|true" /> - 是否把内部日志输出到标准错误控制台 (stderr)。 | |||
设置throwExceptions属性为“true”可以让NLog不再阻挡这类异常,而是把它们抛给调用者。在部署是这样做可以帮我们快速定位问题。一旦应用程序已经正确配置了,我们建议把throwExceptions的值设为“false”,这样由于日志引发的问题不至于导致应用程序的崩溃。 | |||
--> | |||
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd" | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
autoReload="true" | |||
internalLogFile="${basedir}/wwwroot/logs/internalLog.txt" | |||
internalLogLevel="Debug" > | |||
<targets> | |||
<target name="all" xsi:type="File" | |||
fileName="${basedir}/wwwroot/logs/all/${shortdate}.log" | |||
layout="${date:format=yyyyMMddHHmmss} ${callsite} ${level}:${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}"/> | |||
<target name="console" xsi:type="ColoredConsole" | |||
useDefaultRowHighlightingRules="false" | |||
layout="${date:format=yyyyMMddHHmmss} ${callsite} ${level} ${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}"> | |||
<highlight-row condition="level == LogLevel.Debug" foregroundColor="DarkGray" /> | |||
<highlight-row condition="level == LogLevel.Info" foregroundColor="Gray" /> | |||
<highlight-row condition="level == LogLevel.Warn" foregroundColor="Yellow" /> | |||
<highlight-row condition="level == LogLevel.Error" foregroundColor="Red" /> | |||
<highlight-row condition="level == LogLevel.Fatal" foregroundColor="Red" backgroundColor="White" /> | |||
</target> | |||
</targets> | |||
<rules> | |||
<logger name="*" minlevel="Debug" maxlevel="Fatal" writeTo="all,console"/> | |||
</rules> | |||
</nlog> |
@@ -0,0 +1,33 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<OutputType>Exe</OutputType> | |||
<TargetFramework>netcoreapp3.0</TargetFramework> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.0.0" /> | |||
<PackageReference Include="NLog.Extensions.Logging" Version="1.6.0" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\JT808.Gateway\JT808.Gateway.csproj" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Update="appsettings.json"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
<None Update="Configs\nlog.unix.config"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
<None Update="Configs\nlog.win.config"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
<None Update="Configs\NLog.xsd"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
</ItemGroup> | |||
</Project> |
@@ -0,0 +1,51 @@ | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.Hosting; | |||
using Microsoft.Extensions.Logging; | |||
using NLog.Extensions.Logging; | |||
using System; | |||
using System.Threading.Tasks; | |||
using JT808.Protocol; | |||
using Microsoft.Extensions.Configuration; | |||
using JT808.Gateway.CleintBenchmark.Configs; | |||
using JT808.Gateway.Client; | |||
using JT808.Gateway.CleintBenchmark.Services; | |||
namespace JT808.Gateway.CleintBenchmark | |||
{ | |||
class Program | |||
{ | |||
static async Task Main(string[] args) | |||
{ | |||
var serverHostBuilder = new HostBuilder() | |||
.ConfigureAppConfiguration((hostingContext, config) => | |||
{ | |||
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory); | |||
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); | |||
}) | |||
.ConfigureLogging((context, logging) => | |||
{ | |||
if (Environment.OSVersion.Platform == PlatformID.Unix) | |||
{ | |||
NLog.LogManager.LoadConfiguration("Configs/nlog.unix.config"); | |||
} | |||
else | |||
{ | |||
NLog.LogManager.LoadConfiguration("Configs/nlog.win.config"); | |||
} | |||
logging.AddNLog(); | |||
logging.SetMinimumLevel(LogLevel.Trace); | |||
}) | |||
.ConfigureServices((hostContext, services) => | |||
{ | |||
services.Configure<ClientBenchmarkOptions>(hostContext.Configuration.GetSection("ClientBenchmarkOptions")); | |||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||
services.AddJT808Configure() | |||
.AddJT808Client(); | |||
services.AddHostedService<CleintBenchmarkHostedService>(); | |||
services.AddHostedService<CleintBenchmarkReportHostedService>(); | |||
}); | |||
await serverHostBuilder.RunConsoleAsync(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,82 @@ | |||
using JT808.Gateway.CleintBenchmark.Configs; | |||
using JT808.Gateway.Client; | |||
using JT808.Protocol.MessageBody; | |||
using Microsoft.Extensions.Hosting; | |||
using Microsoft.Extensions.Logging; | |||
using Microsoft.Extensions.Options; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.CleintBenchmark.Services | |||
{ | |||
public class CleintBenchmarkHostedService : IHostedService | |||
{ | |||
private readonly ClientBenchmarkOptions clientBenchmarkOptions; | |||
private readonly ILogger logger; | |||
private readonly IJT808TcpClientFactory jT808TcpClientFactory; | |||
private CancellationTokenSource cts=new CancellationTokenSource(); | |||
private TaskFactory taskFactory; | |||
public CleintBenchmarkHostedService( | |||
ILoggerFactory loggerFactory, | |||
IJT808TcpClientFactory jT808TcpClientFactory, | |||
IOptions<ClientBenchmarkOptions> clientBenchmarkOptionsAccessor) | |||
{ | |||
this.jT808TcpClientFactory = jT808TcpClientFactory; | |||
clientBenchmarkOptions = clientBenchmarkOptionsAccessor.Value; | |||
logger = loggerFactory.CreateLogger("CleintBenchmarkHostedService"); | |||
taskFactory = new TaskFactory(); | |||
} | |||
public Task StartAsync(CancellationToken cancellationToken) | |||
{ | |||
logger.LogInformation("StartAsync..."); | |||
ThreadPool.GetMinThreads(out var minWorkerThreads, out var minCompletionPortThreads); | |||
ThreadPool.GetMaxThreads(out var maxWorkerThreads, out var maxCompletionPortThreads); | |||
logger.LogInformation($"GetMinThreads:{minWorkerThreads}-{minCompletionPortThreads}"); | |||
logger.LogInformation($"GetMaxThreads:{maxWorkerThreads}-{maxCompletionPortThreads}"); | |||
//ThreadPool.SetMaxThreads(20, 20); | |||
//ThreadPool.GetMaxThreads(out var setMaxWorkerThreads, out var setMaxCompletionPortThreads); | |||
//logger.LogInformation($"SetMaxThreads:{setMaxWorkerThreads}-{setMaxCompletionPortThreads}"); | |||
for (int i=0;i< clientBenchmarkOptions.DeviceCount; i++) | |||
{ | |||
taskFactory.StartNew((item) => | |||
{ | |||
var client = jT808TcpClientFactory.Create(new DeviceConfig(((int)item).ToString(), clientBenchmarkOptions.IP, clientBenchmarkOptions.Port)); | |||
int lat = new Random(1000).Next(100000, 180000); | |||
int Lng = new Random(1000).Next(100000, 180000); | |||
while (!cts.IsCancellationRequested) | |||
{ | |||
client.Send(new JT808_0x0200() | |||
{ | |||
Lat = lat, | |||
Lng = Lng, | |||
GPSTime = DateTime.Now, | |||
Speed = 50, | |||
Direction = 30, | |||
AlarmFlag = 5, | |||
Altitude = 50, | |||
StatusFlag = 10 | |||
}); | |||
Thread.Sleep(clientBenchmarkOptions.Interval); | |||
} | |||
}, i,cts.Token); | |||
} | |||
return Task.CompletedTask; | |||
} | |||
public Task StopAsync(CancellationToken cancellationToken) | |||
{ | |||
cts.Cancel(); | |||
logger.LogInformation("StopAsync..."); | |||
return Task.CompletedTask; | |||
} | |||
} | |||
} |
@@ -0,0 +1,53 @@ | |||
using JT808.Gateway.Services; | |||
using JT808.Protocol.MessageBody; | |||
using Microsoft.Extensions.Hosting; | |||
using Microsoft.Extensions.Logging; | |||
using Microsoft.Extensions.Options; | |||
using Newtonsoft.Json; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.CleintBenchmark.Services | |||
{ | |||
public class CleintBenchmarkReportHostedService : IHostedService | |||
{ | |||
private readonly JT808ClientReportService jT808ReportService; | |||
private CancellationTokenSource cts=new CancellationTokenSource(); | |||
private readonly ILogger logger; | |||
public CleintBenchmarkReportHostedService( | |||
ILoggerFactory loggerFactory, | |||
JT808ClientReportService jT808ReportService) | |||
{ | |||
this.jT808ReportService = jT808ReportService; | |||
logger = loggerFactory.CreateLogger("CleintBenchmarkReportHostedService"); | |||
} | |||
public Task StartAsync(CancellationToken cancellationToken) | |||
{ | |||
logger.LogInformation("StartAsync..."); | |||
Task.Run(() => { | |||
while (!cts.IsCancellationRequested) | |||
{ | |||
logger.LogInformation(JsonConvert.SerializeObject(jT808ReportService.JT808Reports.LastOrDefault())); | |||
Thread.Sleep(3000); | |||
} | |||
}, cts.Token); | |||
return Task.CompletedTask; | |||
} | |||
public Task StopAsync(CancellationToken cancellationToken) | |||
{ | |||
logger.LogInformation("StopAsync..."); | |||
cts.Cancel(); | |||
logger.LogInformation("正在生成报表..."); | |||
logger.LogInformation(JsonConvert.SerializeObject(jT808ReportService.JT808Reports,Formatting.Indented)); | |||
return Task.CompletedTask; | |||
} | |||
} | |||
} |
@@ -0,0 +1,15 @@ | |||
using Confluent.Kafka; | |||
using Microsoft.Extensions.Options; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.Configs.Kafka | |||
{ | |||
public class JT808ConsumerConfig: ConsumerConfig, IOptions<JT808ConsumerConfig> | |||
{ | |||
public string TopicName { get; set; } | |||
public JT808ConsumerConfig Value => this; | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
using Confluent.Kafka; | |||
using Microsoft.Extensions.Options; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.Configs.Kafka | |||
{ | |||
public class JT808MsgConsumerConfig : JT808ConsumerConfig, IOptions<JT808MsgConsumerConfig> | |||
{ | |||
JT808MsgConsumerConfig IOptions<JT808MsgConsumerConfig>.Value => this; | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
using Confluent.Kafka; | |||
using Microsoft.Extensions.Options; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.Configs.Kafka | |||
{ | |||
public class JT808MsgProducerConfig : JT808ProducerConfig, IOptions<JT808MsgProducerConfig> | |||
{ | |||
JT808MsgProducerConfig IOptions<JT808MsgProducerConfig>.Value => this; | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
using Confluent.Kafka; | |||
using Microsoft.Extensions.Options; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.Configs.Kafka | |||
{ | |||
public class JT808MsgReplyConsumerConfig : JT808ConsumerConfig, IOptions<JT808MsgReplyConsumerConfig> | |||
{ | |||
JT808MsgReplyConsumerConfig IOptions<JT808MsgReplyConsumerConfig>.Value => this; | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
using Confluent.Kafka; | |||
using Microsoft.Extensions.Options; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.Configs.Kafka | |||
{ | |||
public class JT808MsgReplyProducerConfig : JT808ProducerConfig, IOptions<JT808MsgReplyProducerConfig> | |||
{ | |||
JT808MsgReplyProducerConfig IOptions<JT808MsgReplyProducerConfig>.Value => this; | |||
} | |||
} |
@@ -0,0 +1,15 @@ | |||
using Confluent.Kafka; | |||
using Microsoft.Extensions.Options; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.Configs.Kafka | |||
{ | |||
public class JT808ProducerConfig : ProducerConfig,IOptions<JT808ProducerConfig> | |||
{ | |||
public string TopicName { get; set; } | |||
public JT808ProducerConfig Value => this; | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
using Confluent.Kafka; | |||
using Microsoft.Extensions.Options; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.Configs.Kafka | |||
{ | |||
public class JT808SessionConsumerConfig : JT808ConsumerConfig, IOptions<JT808SessionConsumerConfig> | |||
{ | |||
JT808SessionConsumerConfig IOptions<JT808SessionConsumerConfig>.Value => this; | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
using Confluent.Kafka; | |||
using Microsoft.Extensions.Options; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.Configs.Kafka | |||
{ | |||
public class JT808SessionProducerConfig : JT808ProducerConfig, IOptions<JT808SessionProducerConfig> | |||
{ | |||
JT808SessionProducerConfig IOptions<JT808SessionProducerConfig>.Value => this; | |||
} | |||
} |
@@ -0,0 +1,39 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<TargetFramework>netstandard2.0</TargetFramework> | |||
<LangVersion>8.0</LangVersion> | |||
<Copyright>Copyright 2018.</Copyright> | |||
<Authors>SmallChi(Koike)</Authors> | |||
<RepositoryUrl>https://github.com/SmallChi/JT808DotNetty</RepositoryUrl> | |||
<PackageProjectUrl>https://github.com/SmallChi/JT808DotNetty</PackageProjectUrl> | |||
<licenseUrl>https://github.com/SmallChi/JT808DotNetty/blob/master/LICENSE</licenseUrl> | |||
<license>https://github.com/SmallChi/JT808DotNetty/blob/master/LICENSE</license> | |||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> | |||
<Version>1.0.0-preview1</Version> | |||
<SignAssembly>false</SignAssembly> | |||
<PackageLicenseFile>LICENSE</PackageLicenseFile> | |||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | |||
<PackageId>JT808.Gateway.Kafka</PackageId> | |||
<Product>JT808.Gateway.Kafka</Product> | |||
<Description>基于Kafka的JT808消息发布与订阅</Description> | |||
<PackageReleaseNotes>基于Kafka的JT808消息发布与订阅</PackageReleaseNotes> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="Confluent.Kafka" Version="1.2.1" /> | |||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Options" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.0.0" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Include="..\..\LICENSE" Pack="true" PackagePath="" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\JT808.Gateway\JT808.Gateway.csproj" /> | |||
</ItemGroup> | |||
</Project> |
@@ -0,0 +1,24 @@ | |||
using JT808.Protocol; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.DependencyInjection.Extensions; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.Kafka | |||
{ | |||
internal class JT808ClientBuilderDefault : IJT808ClientBuilder | |||
{ | |||
public IJT808Builder JT808Builder { get; } | |||
public JT808ClientBuilderDefault(IJT808Builder builder) | |||
{ | |||
JT808Builder = builder; | |||
} | |||
public IJT808Builder Builder() | |||
{ | |||
return JT808Builder; | |||
} | |||
} | |||
} |
@@ -0,0 +1,66 @@ | |||
using JJT808.Gateway.Kafka; | |||
using JT808.Gateway.Configs.Kafka; | |||
using JT808.Gateway.PubSub; | |||
using JT808.Protocol; | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.DependencyInjection.Extensions; | |||
namespace JT808.Gateway.Kafka | |||
{ | |||
public static class JT808ClientKafkaExtensions | |||
{ | |||
public static IJT808ClientBuilder AddJT808ClientKafka(this IJT808Builder builder) | |||
{ | |||
return new JT808ClientBuilderDefault(builder); | |||
} | |||
/// <summary> | |||
/// | |||
/// </summary> | |||
/// <param name="serviceDescriptors"></param> | |||
/// <param name="configuration">GetSection("JT808MsgConsumerConfig")</param> | |||
/// <returns></returns> | |||
public static IJT808ClientBuilder AddMsgConsumer(this IJT808ClientBuilder jT808ClientBuilder, IConfiguration configuration) | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.Configure<JT808MsgConsumerConfig>(configuration.GetSection("JT808MsgConsumerConfig")); | |||
jT808ClientBuilder.JT808Builder.Services.TryAddSingleton<IJT808MsgConsumer, JT808MsgConsumer>(); | |||
return jT808ClientBuilder; | |||
} | |||
/// <summary> | |||
/// | |||
/// </summary> | |||
/// <param name="serviceDescriptors"></param> | |||
/// <param name="configuration">GetSection("JT808MsgReplyProducerConfig")</param> | |||
/// <returns></returns> | |||
public static IJT808ClientBuilder AddMsgReplyProducer(this IJT808ClientBuilder jT808ClientBuilder, IConfiguration configuration) | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.Configure<JT808MsgReplyProducerConfig>(configuration.GetSection("JT808MsgReplyProducerConfig")); | |||
jT808ClientBuilder.JT808Builder.Services.TryAddSingleton<IJT808MsgReplyProducer, JT808MsgReplyProducer>(); | |||
return jT808ClientBuilder; | |||
} | |||
/// <summary> | |||
/// | |||
/// </summary> | |||
/// <param name="jT808NettyBuilder"></param> | |||
/// <param name="configuration">GetSection("JT808MsgReplyConsumerConfig")</param> | |||
/// <returns></returns> | |||
public static IJT808ClientBuilder AddMsgReplyConsumer(this IJT808ClientBuilder jT808ClientBuilder, IConfiguration configuration) | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.Configure<JT808MsgReplyConsumerConfig>(configuration.GetSection("JT808MsgReplyConsumerConfig")); | |||
jT808ClientBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgReplyConsumer), typeof(JT808MsgReplyConsumer), ServiceLifetime.Singleton)); | |||
return jT808ClientBuilder; | |||
} | |||
/// <summary> | |||
/// | |||
/// </summary> | |||
/// <param name="serviceDescriptors"></param> | |||
/// <param name="configuration">GetSection("JT808SessionConsumerConfig")</param> | |||
/// <returns></returns> | |||
public static IJT808ClientBuilder AddSessionConsumer(this IJT808ClientBuilder jT808ClientBuilder, IConfiguration configuration) | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.Configure<JT808SessionConsumerConfig>(configuration.GetSection("JT808SessionConsumerConfig")); | |||
jT808ClientBuilder.JT808Builder.Services.TryAddSingleton<IJT808SessionConsumer, JT808SessionConsumer>(); | |||
return jT808ClientBuilder; | |||
} | |||
} | |||
} |
@@ -0,0 +1,82 @@ | |||
using Confluent.Kafka; | |||
using JT808.Gateway.Configs.Kafka; | |||
using JT808.Gateway.PubSub; | |||
using Microsoft.Extensions.Logging; | |||
using Microsoft.Extensions.Options; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.Kafka | |||
{ | |||
public class JT808MsgConsumer : IJT808MsgConsumer | |||
{ | |||
public CancellationTokenSource Cts => new CancellationTokenSource(); | |||
private readonly IConsumer<string, byte[]> consumer; | |||
private readonly ILogger logger; | |||
public string TopicName { get; } | |||
public JT808MsgConsumer( | |||
IOptions<JT808MsgConsumerConfig> consumerConfigAccessor, | |||
ILoggerFactory loggerFactory) | |||
{ | |||
consumer = new ConsumerBuilder<string, byte[]>(consumerConfigAccessor.Value).Build(); | |||
TopicName = consumerConfigAccessor.Value.TopicName; | |||
logger = loggerFactory.CreateLogger("JT808MsgConsumer"); | |||
} | |||
public void OnMessage(Action<(string TerminalNo, byte[] Data)> callback) | |||
{ | |||
Task.Run(() => | |||
{ | |||
while (!Cts.IsCancellationRequested) | |||
{ | |||
try | |||
{ | |||
//如果不指定分区,根据kafka的机制会从多个分区中拉取数据 | |||
//如果指定分区,根据kafka的机制会从相应的分区中拉取数据 | |||
var data = consumer.Consume(Cts.Token); | |||
if (logger.IsEnabled(LogLevel.Debug)) | |||
{ | |||
logger.LogDebug($"Topic: {data.Topic} Key: {data.Key} Partition: {data.Partition} Offset: {data.Offset} TopicPartitionOffset:{data.TopicPartitionOffset}"); | |||
} | |||
callback((data.Key, data.Value)); | |||
} | |||
catch (ConsumeException ex) | |||
{ | |||
logger.LogError(ex, TopicName); | |||
} | |||
catch (OperationCanceledException ex) | |||
{ | |||
logger.LogError(ex, TopicName); | |||
} | |||
catch (Exception ex) | |||
{ | |||
logger.LogError(ex, TopicName); | |||
} | |||
} | |||
}, Cts.Token); | |||
} | |||
public void Subscribe() | |||
{ | |||
consumer.Subscribe(TopicName); | |||
} | |||
public void Unsubscribe() | |||
{ | |||
consumer.Unsubscribe(); | |||
} | |||
public void Dispose() | |||
{ | |||
consumer.Close(); | |||
consumer.Dispose(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,38 @@ | |||
using Confluent.Kafka; | |||
using JT808.Gateway.Configs.Kafka; | |||
using JT808.Gateway.PubSub; | |||
using Microsoft.Extensions.Options; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.Kafka | |||
{ | |||
public class JT808MsgProducer : IJT808MsgProducer | |||
{ | |||
public string TopicName { get; } | |||
private readonly IProducer<string, byte[]> producer; | |||
public JT808MsgProducer( | |||
IOptions<JT808MsgProducerConfig> producerConfigAccessor) | |||
{ | |||
producer = new ProducerBuilder<string, byte[]>(producerConfigAccessor.Value).Build(); | |||
TopicName = producerConfigAccessor.Value.TopicName; | |||
} | |||
public void Dispose() | |||
{ | |||
producer.Dispose(); | |||
} | |||
public async Task ProduceAsync(string terminalNo, byte[] data) | |||
{ | |||
await producer.ProduceAsync(TopicName, new Message<string, byte[]> | |||
{ | |||
Key = terminalNo, | |||
Value = data | |||
}); | |||
} | |||
} | |||
} |
@@ -0,0 +1,82 @@ | |||
using Confluent.Kafka; | |||
using JT808.Gateway.Configs.Kafka; | |||
using JT808.Gateway.PubSub; | |||
using Microsoft.Extensions.Logging; | |||
using Microsoft.Extensions.Options; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.Kafka | |||
{ | |||
public class JT808MsgReplyConsumer : IJT808MsgReplyConsumer | |||
{ | |||
public CancellationTokenSource Cts => new CancellationTokenSource(); | |||
private readonly IConsumer<string, byte[]> consumer; | |||
private readonly ILogger logger; | |||
public string TopicName { get; } | |||
public JT808MsgReplyConsumer( | |||
IOptions<JT808MsgReplyConsumerConfig> consumerConfigAccessor, | |||
ILoggerFactory loggerFactory) | |||
{ | |||
consumer = new ConsumerBuilder<string, byte[]>(consumerConfigAccessor.Value).Build(); | |||
TopicName = consumerConfigAccessor.Value.TopicName; | |||
logger = loggerFactory.CreateLogger("JT808MsgReplyConsumer"); | |||
} | |||
public void OnMessage(Action<(string TerminalNo, byte[] Data)> callback) | |||
{ | |||
Task.Run(() => | |||
{ | |||
while (!Cts.IsCancellationRequested) | |||
{ | |||
try | |||
{ | |||
//如果不指定分区,根据kafka的机制会从多个分区中拉取数据 | |||
//如果指定分区,根据kafka的机制会从相应的分区中拉取数据 | |||
var data = consumer.Consume(Cts.Token); | |||
if (logger.IsEnabled(LogLevel.Debug)) | |||
{ | |||
logger.LogDebug($"Topic: {data.Topic} Key: {data.Key} Partition: {data.Partition} Offset: {data.Offset} TopicPartitionOffset:{data.TopicPartitionOffset}"); | |||
} | |||
callback((data.Key, data.Value)); | |||
} | |||
catch (ConsumeException ex) | |||
{ | |||
logger.LogError(ex, TopicName); | |||
} | |||
catch (OperationCanceledException ex) | |||
{ | |||
logger.LogError(ex, TopicName); | |||
} | |||
catch (Exception ex) | |||
{ | |||
logger.LogError(ex, TopicName); | |||
} | |||
} | |||
}, Cts.Token); | |||
} | |||
public void Subscribe() | |||
{ | |||
consumer.Subscribe(TopicName); | |||
} | |||
public void Unsubscribe() | |||
{ | |||
consumer.Unsubscribe(); | |||
} | |||
public void Dispose() | |||
{ | |||
consumer.Close(); | |||
consumer.Dispose(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,38 @@ | |||
using Confluent.Kafka; | |||
using JT808.Gateway.Configs.Kafka; | |||
using JT808.Gateway.PubSub; | |||
using Microsoft.Extensions.Options; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
namespace JJT808.Gateway.Kafka | |||
{ | |||
public class JT808MsgReplyProducer : IJT808MsgReplyProducer | |||
{ | |||
public string TopicName { get;} | |||
private IProducer<string, byte[]> producer; | |||
public JT808MsgReplyProducer( | |||
IOptions<JT808MsgReplyProducerConfig> producerConfigAccessor) | |||
{ | |||
producer = new ProducerBuilder<string, byte[]>(producerConfigAccessor.Value).Build(); | |||
TopicName = producerConfigAccessor.Value.TopicName; | |||
} | |||
public void Dispose() | |||
{ | |||
producer.Dispose(); | |||
} | |||
public async Task ProduceAsync(string terminalNo, byte[] data) | |||
{ | |||
await producer.ProduceAsync(TopicName, new Message<string, byte[]> | |||
{ | |||
Key = terminalNo, | |||
Value = data | |||
}); | |||
} | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
using JT808.Gateway.Configs.Kafka; | |||
using JT808.Gateway.PubSub; | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.DependencyInjection.Extensions; | |||
namespace JT808.Gateway.Kafka | |||
{ | |||
public static class JT808ServerKafkaExtensions | |||
{ | |||
/// <summary> | |||
/// | |||
/// </summary> | |||
/// <param name="jT808NettyBuilder"></param> | |||
/// <param name="configuration">GetSection("JT808MsgProducerConfig")</param> | |||
/// <returns></returns> | |||
public static IJT808GatewayBuilder AddJT808ServerKafkaMsgProducer(this IJT808GatewayBuilder jT808GatewayBuilder, IConfiguration configuration) | |||
{ | |||
jT808GatewayBuilder.JT808Builder.Services.Configure<JT808MsgProducerConfig>(configuration.GetSection("JT808MsgProducerConfig")); | |||
jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgProducer), typeof(JT808MsgProducer), ServiceLifetime.Singleton)); | |||
return jT808GatewayBuilder; | |||
} | |||
/// <summary> | |||
/// | |||
/// </summary> | |||
/// <param name="jT808NettyBuilder"></param> | |||
/// <param name="configuration">GetSection("JT808MsgReplyConsumerConfig")</param> | |||
/// <returns></returns> | |||
public static IJT808GatewayBuilder AddJT808ServerKafkaMsgReplyConsumer(this IJT808GatewayBuilder jT808GatewayBuilder, IConfiguration configuration) | |||
{ | |||
jT808GatewayBuilder.JT808Builder.Services.Configure<JT808MsgReplyConsumerConfig>(configuration.GetSection("JT808MsgReplyConsumerConfig")); | |||
jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgReplyConsumer), typeof(JT808MsgReplyConsumer), ServiceLifetime.Singleton)); | |||
return jT808GatewayBuilder; | |||
} | |||
/// <summary> | |||
/// | |||
/// </summary> | |||
/// <param name="jT808NettyBuilder"></param> | |||
/// <param name="configuration">GetSection("JT808SessionProducerConfig")</param> | |||
/// <returns></returns> | |||
public static IJT808GatewayBuilder AddJT808ServerKafkaSessionProducer(this IJT808GatewayBuilder jT808GatewayBuilder, IConfiguration configuration) | |||
{ | |||
jT808GatewayBuilder.JT808Builder.Services.Configure<JT808SessionProducerConfig>(configuration.GetSection("JT808SessionProducerConfig")); | |||
jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808SessionProducer), typeof(JT808SessionProducer), ServiceLifetime.Singleton)); | |||
return jT808GatewayBuilder; | |||
} | |||
} | |||
} |
@@ -0,0 +1,82 @@ | |||
using Confluent.Kafka; | |||
using JT808.Gateway.Configs.Kafka; | |||
using JT808.Gateway.PubSub; | |||
using Microsoft.Extensions.Logging; | |||
using Microsoft.Extensions.Options; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.Kafka | |||
{ | |||
public class JT808SessionConsumer : IJT808SessionConsumer | |||
{ | |||
public CancellationTokenSource Cts => new CancellationTokenSource(); | |||
private readonly IConsumer<string, string> consumer; | |||
private readonly ILogger logger; | |||
public string TopicName { get; } | |||
public JT808SessionConsumer( | |||
IOptions<JT808SessionConsumerConfig> consumerConfigAccessor, | |||
ILoggerFactory loggerFactory) | |||
{ | |||
consumer = new ConsumerBuilder<string, string>(consumerConfigAccessor.Value).Build(); | |||
TopicName = consumerConfigAccessor.Value.TopicName; | |||
logger = loggerFactory.CreateLogger("JT808SessionConsumer"); | |||
} | |||
public void OnMessage(Action<(string Notice, string TerminalNo)> callback) | |||
{ | |||
Task.Run(() => | |||
{ | |||
while (!Cts.IsCancellationRequested) | |||
{ | |||
try | |||
{ | |||
//如果不指定分区,根据kafka的机制会从多个分区中拉取数据 | |||
//如果指定分区,根据kafka的机制会从相应的分区中拉取数据 | |||
var data = consumer.Consume(Cts.Token); | |||
if (logger.IsEnabled(LogLevel.Debug)) | |||
{ | |||
logger.LogDebug($"Topic: {data.Topic} Key: {data.Key} Partition: {data.Partition} Offset: {data.Offset} TopicPartitionOffset:{data.TopicPartitionOffset}"); | |||
} | |||
callback((data.Key, data.Value)); | |||
} | |||
catch (ConsumeException ex) | |||
{ | |||
logger.LogError(ex, TopicName); | |||
} | |||
catch (OperationCanceledException ex) | |||
{ | |||
logger.LogError(ex, TopicName); | |||
} | |||
catch (Exception ex) | |||
{ | |||
logger.LogError(ex, TopicName); | |||
} | |||
} | |||
}, Cts.Token); | |||
} | |||
public void Subscribe() | |||
{ | |||
consumer.Subscribe(TopicName); | |||
} | |||
public void Unsubscribe() | |||
{ | |||
consumer.Unsubscribe(); | |||
} | |||
public void Dispose() | |||
{ | |||
consumer.Close(); | |||
consumer.Dispose(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,38 @@ | |||
using Confluent.Kafka; | |||
using JT808.Gateway.Configs.Kafka; | |||
using JT808.Gateway.PubSub; | |||
using Microsoft.Extensions.Options; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.Kafka | |||
{ | |||
public class JT808SessionProducer : IJT808SessionProducer | |||
{ | |||
public string TopicName { get; } | |||
private readonly IProducer<string, string> producer; | |||
public JT808SessionProducer( | |||
IOptions<JT808SessionProducerConfig> producerConfigAccessor) | |||
{ | |||
producer = new ProducerBuilder<string, string>(producerConfigAccessor.Value).Build(); | |||
TopicName = producerConfigAccessor.Value.TopicName; | |||
} | |||
public void Dispose() | |||
{ | |||
producer.Dispose(); | |||
} | |||
public async Task ProduceAsync(string notice,string terminalNo) | |||
{ | |||
await producer.ProduceAsync(TopicName, new Message<string, string> | |||
{ | |||
Key = notice, | |||
Value = terminalNo | |||
}); | |||
} | |||
} | |||
} |
@@ -8,6 +8,7 @@ using System; | |||
using System.Threading.Tasks; | |||
using Grpc.Net.Client; | |||
using JT808.Gateway.GrpcService; | |||
using System.Net; | |||
namespace JT808.Gateway.SimpleClient | |||
{ | |||
@@ -16,7 +17,12 @@ namespace JT808.Gateway.SimpleClient | |||
static async Task Main(string[] args) | |||
{ | |||
//ref https://docs.microsoft.com/zh-cn/aspnet/core/grpc/troubleshoot?view=aspnetcore-3.0#call-insecure-grpc-services-with-net-core-client | |||
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); | |||
//ref https://docs.microsoft.com/zh-cn/aspnet/core/grpc/troubleshoot?view=aspnetcore-3.0 | |||
//先执行 dotnet dev-certs https --trust 命令生成开发证书 | |||
//使用 certmgr.msc 导出证书在服务端配置对应证书文件 | |||
//Uri "https://localhost:5001" | |||
var serverHostBuilder = new HostBuilder() | |||
.ConfigureLogging((context, logging) => | |||
{ | |||
@@ -27,7 +33,7 @@ namespace JT808.Gateway.SimpleClient | |||
{ | |||
services.AddGrpcClient<JT808Gateway.JT808GatewayClient>(o => | |||
{ | |||
o.Address = new Uri("https://127.0.0.1:5001"); | |||
o.Address = new Uri("https://localhost:5001"); | |||
}); | |||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||
@@ -32,8 +32,8 @@ namespace JT808.Gateway.SimpleClient.Services | |||
public Task StartAsync(CancellationToken cancellationToken) | |||
{ | |||
Task.Run(() => { | |||
while (!cancellationToken.IsCancellationRequested) | |||
{ | |||
//while (!cancellationToken.IsCancellationRequested) | |||
//{ | |||
Thread.Sleep(1000 * 10); | |||
var result1 = client.GetTcpAtomicCounter(new Empty()); | |||
var result2 = client.GetUdpAtomicCounter(new Empty()); | |||
@@ -55,7 +55,7 @@ namespace JT808.Gateway.SimpleClient.Services | |||
logger.LogDebug(JsonSerializer.Serialize(result4)); | |||
logger.LogDebug(JsonSerializer.Serialize(result5)); | |||
logger.LogDebug(JsonSerializer.Serialize(result6)); | |||
} | |||
//} | |||
}, cancellationToken); | |||
return Task.CompletedTask; | |||
} | |||
@@ -30,6 +30,9 @@ | |||
<None Update="Configs\NLog.xsd"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
<None Update="Configs\test.cer"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
</ItemGroup> | |||
</Project> | |||
@@ -11,6 +11,7 @@ using Microsoft.Extensions.Hosting; | |||
using Microsoft.Extensions.Logging; | |||
using NLog.Extensions.Logging; | |||
using System; | |||
using System.IO; | |||
using System.Net; | |||
namespace JT808.Gateway.SimpleServer | |||
@@ -31,17 +32,17 @@ namespace JT808.Gateway.SimpleServer | |||
configLogging.AddNLog(new NLogProviderOptions { CaptureMessageTemplates = true, CaptureMessageProperties = true }); | |||
configLogging.SetMinimumLevel(LogLevel.Trace); | |||
}) | |||
.ConfigureWebHostDefaults(webBuilder => | |||
{ | |||
webBuilder | |||
//.ConfigureKestrel(options => | |||
//{ | |||
// options.Listen(IPAddress.Any, 5001, listenOptions => | |||
// { | |||
// listenOptions.Protocols = HttpProtocols.Http2; | |||
// }); | |||
//}) | |||
.ConfigureKestrel(options => | |||
{ | |||
options.Listen(IPAddress.Any, 5001, listenOptions => | |||
{ | |||
listenOptions.Protocols = HttpProtocols.Http2; | |||
listenOptions.UseHttps($"{Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Configs", "test.cer")}", ""); | |||
}); | |||
}) | |||
.Configure(app => | |||
{ | |||
app.UseRouting(); | |||
@@ -53,7 +54,7 @@ namespace JT808.Gateway.SimpleServer | |||
}) | |||
.ConfigureServices((hostContext,services) => | |||
{ | |||
services.Configure<KestrelServerOptions>(hostContext.Configuration.GetSection("Kestrel")); | |||
//services.Configure<KestrelServerOptions>(hostContext.Configuration.GetSection("Kestrel")); | |||
services.AddGrpc(); | |||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||
@@ -0,0 +1,24 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<OutputType>Exe</OutputType> | |||
<TargetFramework>netcoreapp3.0</TargetFramework> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.0.0" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\..\JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj" /> | |||
<ProjectReference Include="..\..\JT808.Gateway\JT808.Gateway.csproj" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Update="appsettings.json"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
</ItemGroup> | |||
</Project> |
@@ -0,0 +1,44 @@ | |||
using JT808.Gateway.BusinessServices.MsgIdHandler; | |||
using JT808.Gateway.Configs.Kafka; | |||
using JT808.Gateway.Kafka; | |||
using JT808.Gateway.PubSub; | |||
using JT808.Protocol; | |||
using JT808.Protocol.Extensions; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.Logging; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.MsgIdHandler.Test | |||
{ | |||
public class JT808DotNettyMsgIdHandlerDefaultImpl : IJT808MsgIdHandler | |||
{ | |||
public readonly ILogger<JT808DotNettyMsgIdHandlerDefaultImpl> logger; | |||
public JT808DotNettyMsgIdHandlerDefaultImpl(ILoggerFactory loggerFactory, | |||
IServiceProvider serviceProvider) { | |||
logger = loggerFactory.CreateLogger<JT808DotNettyMsgIdHandlerDefaultImpl>(); | |||
Task.Run(()=> { | |||
while (true) | |||
{ | |||
Thread.Sleep(5000); | |||
using (IJT808MsgProducer jT808MsgProducer = new JT808MsgProducer(new JT808MsgProducerConfig | |||
{ | |||
BootstrapServers = "127.0.0.1:9092", | |||
TopicName = "JT808Msg" | |||
})) | |||
{ | |||
jT808MsgProducer.ProduceAsync("123456", new byte[] { 0x7E, 0, 0x7E }).Wait(); | |||
} | |||
} | |||
}); | |||
} | |||
public void Processor((string TerminalNo, byte[] Data) parameter) | |||
{ | |||
logger.LogDebug($"{parameter.TerminalNo}:{parameter.Data.ToHexString()}"); | |||
} | |||
} | |||
} |
@@ -0,0 +1,39 @@ | |||
using JT808.Gateway.BusinessServices.MsgIdHandler; | |||
using JT808.Gateway.Kafka; | |||
using JT808.Protocol; | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.Hosting; | |||
using Microsoft.Extensions.Logging; | |||
using System; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.MsgIdHandler.Test | |||
{ | |||
class Program | |||
{ | |||
async static Task Main(string[] args) | |||
{ | |||
var serverHostBuilder = new HostBuilder() | |||
.UseEnvironment(args[0].Split('=')[1]) | |||
.ConfigureAppConfiguration((hostingContext,config) => { | |||
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory); | |||
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) | |||
.AddJsonFile($"appsettings.{ hostingContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true); | |||
}) | |||
.ConfigureLogging(configLogging => { | |||
configLogging.AddConsole(); | |||
configLogging.SetMinimumLevel(LogLevel.Trace); | |||
}) | |||
.ConfigureServices((hostContext, services) => { | |||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||
services.AddJT808Configure() | |||
.AddJT808ClientKafka() | |||
.AddMsgConsumer(hostContext.Configuration) | |||
.AddJT808MsgIdHandler<JT808DotNettyMsgIdHandlerDefaultImpl>(); | |||
}); | |||
await serverHostBuilder.RunConsoleAsync(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,25 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<OutputType>Exe</OutputType> | |||
<TargetFramework>netcoreapp3.0</TargetFramework> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.0.0" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\..\JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj" /> | |||
<ProjectReference Include="..\..\JT808.Gateway\JT808.Gateway.csproj" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Update="appsettings.json"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
</ItemGroup> | |||
</Project> |
@@ -0,0 +1,52 @@ | |||
using JJT808.Gateway.Kafka; | |||
using JT808.Gateway.BusinessServices.MsgLogging; | |||
using JT808.Gateway.Configs.Kafka; | |||
using JT808.Gateway.Kafka; | |||
using JT808.Gateway.PubSub; | |||
using JT808.Protocol.Extensions; | |||
using Microsoft.Extensions.Logging; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.MsgLogging.Test | |||
{ | |||
public class JT808MsgLoggingImpl : IJT808MsgLogging | |||
{ | |||
public readonly ILogger<JT808MsgLoggingImpl> logger; | |||
public JT808MsgLoggingImpl(ILoggerFactory loggerFactory) { | |||
logger = loggerFactory.CreateLogger<JT808MsgLoggingImpl>(); | |||
Task.Run(() => { | |||
while (true) | |||
{ | |||
Thread.Sleep(5000); | |||
using (IJT808MsgProducer jT808MsgProducer = new JT808MsgProducer(new JT808MsgProducerConfig | |||
{ | |||
BootstrapServers = "127.0.0.1:9092", | |||
TopicName = "JT808Msg" | |||
})) | |||
{ | |||
jT808MsgProducer.ProduceAsync("123456", new byte[] { 0x7E, 0,0,0,0, 0x7E }).Wait(); | |||
} | |||
JT808MsgReplyProducerConfig JT808MsgProducerConfig = new JT808MsgReplyProducerConfig | |||
{ | |||
TopicName = "JT808MsgReply", | |||
BootstrapServers = "127.0.0.1:9092", | |||
}; | |||
using (IJT808MsgReplyProducer jT808MsgProducer = new JT808MsgReplyProducer(JT808MsgProducerConfig)) | |||
{ | |||
jT808MsgProducer.ProduceAsync("123456", new byte[] { 0x7E,1,1,1,1, 0x7E }).Wait(); | |||
} | |||
} | |||
}); | |||
} | |||
public void Processor((string TerminalNo, byte[] Data) parameter, JT808MsgLoggingType jT808MsgLoggingType) | |||
{ | |||
logger.LogDebug($"{parameter.TerminalNo}:{parameter.Data.ToHexString()},方向:{jT808MsgLoggingType.ToString()}"); | |||
} | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
using JT808.Gateway.BusinessServices.MsgLogging; | |||
using JT808.Gateway.Kafka; | |||
using JT808.Protocol; | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.Hosting; | |||
using Microsoft.Extensions.Logging; | |||
using Microsoft.Extensions.Logging.Console; | |||
using System; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.MsgLogging.Test | |||
{ | |||
class Program | |||
{ | |||
async static Task Main(string[] args) | |||
{ | |||
var hostBuilder = new HostBuilder() | |||
.UseEnvironment(args[0].Split('=')[1]) | |||
.ConfigureAppConfiguration((hostContext,config)=> { | |||
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory); | |||
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) | |||
.AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true); | |||
}) | |||
.ConfigureLogging((hostContext, configLogging) => { | |||
configLogging.AddConsole(); | |||
configLogging.SetMinimumLevel(LogLevel.Trace); | |||
}) | |||
.ConfigureServices((hostContext, services) => { | |||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||
services.AddJT808Configure() | |||
.AddJT808ClientKafka() | |||
.AddMsgConsumer(hostContext.Configuration) | |||
.AddMsgReplyConsumer(hostContext.Configuration) | |||
.AddJT808MsgLogging<JT808MsgLoggingImpl>(); | |||
}) | |||
; | |||
await hostBuilder.RunConsoleAsync(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,25 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<OutputType>Exe</OutputType> | |||
<TargetFramework>netcoreapp3.0</TargetFramework> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.0.0" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\..\JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj" /> | |||
<ProjectReference Include="..\..\JT808.Gateway\JT808.Gateway.csproj" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Update="appsettings.json"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
</ItemGroup> | |||
</Project> |
@@ -0,0 +1,48 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
using JT808.Gateway.BusinessServices.ReplyMessage; | |||
using JT808.Gateway.Configs.Kafka; | |||
using JT808.Gateway.Kafka; | |||
using JT808.Gateway.PubSub; | |||
using JT808.Protocol; | |||
using JT808.Protocol.Extensions; | |||
using Microsoft.Extensions.Logging; | |||
namespace JT808.Gateway.ReplyMessage.Test | |||
{ | |||
public class JT808DotNettyReplyMessageServiceInherited : JT808ReplyMessageService | |||
{ | |||
public readonly ILogger<JT808DotNettyReplyMessageServiceInherited> logger; | |||
public JT808DotNettyReplyMessageServiceInherited(IJT808Config jT808Config, | |||
IJT808MsgReplyProducer jT808MsgReplyProducer, | |||
ILoggerFactory loggerFactory) | |||
: base(jT808Config, jT808MsgReplyProducer) | |||
{ | |||
logger = loggerFactory.CreateLogger<JT808DotNettyReplyMessageServiceInherited>(); | |||
Task.Run(() => { | |||
while (true) | |||
{ | |||
Thread.Sleep(5000); | |||
using (IJT808MsgProducer jT808MsgProducer = new JT808MsgProducer(new JT808MsgProducerConfig | |||
{ | |||
BootstrapServers = "127.0.0.1:9092", | |||
TopicName = "JT808Msg" | |||
})) | |||
{ | |||
jT808MsgProducer.ProduceAsync("011111111111", "7E02000032011111111111012E00000000000C00000160E42506C30C82002C00000000180914142057010400001DC003020000250400000000300115310100977E".ToHexBytes()).Wait(); | |||
} | |||
} | |||
}); | |||
} | |||
public override void Processor((string TerminalNo, byte[] Data) parameter) | |||
{ | |||
logger.LogDebug($"{parameter.TerminalNo}:{parameter.Data.ToHexString()}"); | |||
base.Processor(parameter); | |||
} | |||
} | |||
} |
@@ -0,0 +1,42 @@ | |||
using JT808.Gateway.BusinessServices.ReplyMessage; | |||
using JT808.Gateway.Kafka; | |||
using JT808.Protocol; | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.Hosting; | |||
using Microsoft.Extensions.Logging; | |||
using System; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.ReplyMessage.Test | |||
{ | |||
class Program | |||
{ | |||
async static Task Main(string[] args) | |||
{ | |||
var hostBuilder = new HostBuilder() | |||
.UseEnvironment(args[0].Split('=')[1]) | |||
.ConfigureAppConfiguration((hostContext, config) => { | |||
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory); | |||
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) | |||
.AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true); | |||
}) | |||
.ConfigureLogging((hostContext, configLogging) => { | |||
configLogging.AddConsole(); | |||
configLogging.SetMinimumLevel(LogLevel.Trace); | |||
}) | |||
.ConfigureServices((hostContext, services) => { | |||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||
services.AddJT808Configure() | |||
.AddJT808ClientKafka() | |||
.AddMsgConsumer(hostContext.Configuration) | |||
.AddMsgReplyProducer(hostContext.Configuration) | |||
.AddInprocJT808ReplyMessage<JT808DotNettyReplyMessageServiceInherited>(); | |||
}) | |||
; | |||
await hostBuilder.RunConsoleAsync(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<OutputType>Exe</OutputType> | |||
<TargetFramework>netcoreapp3.0</TargetFramework> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.0.0" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\..\JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Update="appsettings.json"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
</ItemGroup> | |||
</Project> |
@@ -0,0 +1,41 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
using JT808.Gateway.BusinessServices.SessionNotice; | |||
using JT808.Gateway.Configs.Kafka; | |||
using JT808.Gateway.Kafka; | |||
using JT808.Gateway.PubSub; | |||
using Microsoft.Extensions.Logging; | |||
namespace JT808.Gateway.SessionNotice.Test | |||
{ | |||
public class JT808DotNettySessionNoticeServiceInherited : JT808SessionNoticeService | |||
{ | |||
public JT808DotNettySessionNoticeServiceInherited(ILoggerFactory loggerFactory) : base(loggerFactory) | |||
{ | |||
Task.Run(()=> { | |||
while (true) | |||
{ | |||
Thread.Sleep(5000); | |||
JT808SessionProducerConfig JT808ProducerConfig = new JT808SessionProducerConfig | |||
{ | |||
TopicName = "JT808Session", | |||
BootstrapServers = "127.0.0.1:9092" | |||
}; | |||
using (IJT808SessionProducer jT808MsgProducer = new JT808SessionProducer(JT808ProducerConfig)) | |||
{ | |||
jT808MsgProducer.ProduceAsync("online", "123456").Wait(); | |||
jT808MsgProducer.ProduceAsync("offline", "123457").Wait(); | |||
} | |||
} | |||
}); | |||
} | |||
public override void Processor((string Notice, string TerminalNo) parameter) | |||
{ | |||
base.Processor(parameter); | |||
} | |||
} | |||
} |
@@ -0,0 +1,41 @@ | |||
using JT808.Gateway.BusinessServices.SessionNotice; | |||
using JT808.Gateway.Kafka; | |||
using JT808.Protocol; | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.Hosting; | |||
using Microsoft.Extensions.Logging; | |||
using System; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.SessionNotice.Test | |||
{ | |||
class Program | |||
{ | |||
async static Task Main(string[] args) | |||
{ | |||
var hostBuilder = new HostBuilder() | |||
.UseEnvironment(args[0].Split('=')[1]) | |||
.ConfigureAppConfiguration((hostContext, config) => { | |||
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory); | |||
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) | |||
.AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true); | |||
}) | |||
.ConfigureLogging((hostContext, configLogging) => { | |||
configLogging.AddConsole(); | |||
configLogging.SetMinimumLevel(LogLevel.Trace); | |||
}) | |||
.ConfigureServices((hostContext, services) => { | |||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||
services.AddJT808Configure() | |||
.AddJT808ClientKafka() | |||
.AddSessionConsumer(hostContext.Configuration) | |||
.AddInprocJT808SessionNotice<JT808DotNettySessionNoticeServiceInherited>(); | |||
}) | |||
; | |||
await hostBuilder.RunConsoleAsync(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<TargetFramework>netcoreapp3.0</TargetFramework> | |||
<IsPackable>false</IsPackable> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" /> | |||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="2.2.0" /> | |||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" /> | |||
<PackageReference Include="xunit" Version="2.4.0" /> | |||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" /> | |||
<PackageReference Include="coverlet.collector" Version="1.0.1" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\..\JT808.Gateway\JT808.Gateway.csproj" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Update="Tcp\appsettings.json"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
<None Update="Udp\appsettings.json"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
</ItemGroup> | |||
</Project> |
@@ -0,0 +1,94 @@ | |||
using JT808.Protocol; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Net; | |||
using System.Text; | |||
using System.Threading; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using JT808.Protocol.Extensions; | |||
using Xunit; | |||
using JT808.Gateway.Interfaces; | |||
using JT808.Gateway.Session; | |||
using JT808.Gateway.Simples; | |||
namespace JT808.Gateway.Test.Tcp | |||
{ | |||
public class JT808SessionServiceTest:TestBase,IDisposable | |||
{ | |||
static IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6565); | |||
JT808SimpleTcpClient SimpleTcpClient1; | |||
JT808SimpleTcpClient SimpleTcpClient2; | |||
JT808SimpleTcpClient SimpleTcpClient3; | |||
JT808SimpleTcpClient SimpleTcpClient4; | |||
JT808SimpleTcpClient SimpleTcpClient5; | |||
public JT808SessionServiceTest() | |||
{ | |||
SimpleTcpClient1 = new JT808SimpleTcpClient(endPoint); | |||
SimpleTcpClient2 = new JT808SimpleTcpClient(endPoint); | |||
SimpleTcpClient3 = new JT808SimpleTcpClient(endPoint); | |||
SimpleTcpClient4 = new JT808SimpleTcpClient(endPoint); | |||
SimpleTcpClient5 = new JT808SimpleTcpClient(endPoint); | |||
// 心跳会话包 | |||
JT808Package jT808Package1 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789001"); | |||
SimpleTcpClient1.WriteAsync(JT808Serializer.Serialize(jT808Package1)); | |||
// 心跳会话包 | |||
JT808Package jT808Package2 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789002"); | |||
SimpleTcpClient2.WriteAsync(JT808Serializer.Serialize(jT808Package2)); | |||
// 心跳会话包 | |||
JT808Package jT808Package3 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789003"); | |||
SimpleTcpClient3.WriteAsync(JT808Serializer.Serialize(jT808Package3)); | |||
// 心跳会话包 | |||
JT808Package jT808Package4 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789004"); | |||
SimpleTcpClient4.WriteAsync(JT808Serializer.Serialize(jT808Package4)); | |||
// 心跳会话包 | |||
JT808Package jT808Package5 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789005"); | |||
SimpleTcpClient5.WriteAsync(JT808Serializer.Serialize(jT808Package5)); | |||
Thread.Sleep(1000); | |||
} | |||
public void Dispose() | |||
{ | |||
SimpleTcpClient1.Down(); | |||
SimpleTcpClient2.Down(); | |||
SimpleTcpClient3.Down(); | |||
SimpleTcpClient4.Down(); | |||
SimpleTcpClient5.Down(); | |||
} | |||
[Fact] | |||
public void Test1() | |||
{ | |||
IJT808SessionService jT808SessionServiceDefaultImpl = ServiceProvider.GetService<IJT808SessionService>(); | |||
var result = jT808SessionServiceDefaultImpl.GetTcpAll(); | |||
Thread.Sleep(5000); | |||
} | |||
[Fact] | |||
public void Test2() | |||
{ | |||
IJT808SessionService jT808SessionServiceDefaultImpl = ServiceProvider.GetService<IJT808SessionService>(); | |||
var result1 = jT808SessionServiceDefaultImpl.GetTcpAll(); | |||
var result2 = jT808SessionServiceDefaultImpl.RemoveByTerminalPhoneNo("123456789001"); | |||
var result3 = jT808SessionServiceDefaultImpl.GetTcpAll(); | |||
} | |||
[Fact] | |||
public void Test3() | |||
{ | |||
// 判断通道是否关闭 | |||
IJT808SessionService jT808SessionServiceDefaultImpl = ServiceProvider.GetService<IJT808SessionService>(); | |||
JT808SessionManager jT808TcpSessionManager = ServiceProvider.GetService<JT808SessionManager>(); | |||
var result1 = jT808SessionServiceDefaultImpl.GetTcpAll(); | |||
SimpleTcpClient1.Down(); | |||
Thread.Sleep(5000); | |||
var session = jT808TcpSessionManager.GetSessionByTerminalPhoneNo("123456789001"); | |||
Thread.Sleep(100000); | |||
} | |||
} | |||
} |
@@ -0,0 +1,75 @@ | |||
using JT808.Protocol; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Net; | |||
using System.Text; | |||
using System.Threading; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using JT808.Protocol.Extensions; | |||
using JT808.Protocol.MessageBody; | |||
using JT808.Gateway.Interfaces; | |||
using JT808.Gateway.Simples; | |||
using Xunit; | |||
using JT808.Gateway.Dtos; | |||
namespace JT808.Gateway.Test.Tcp | |||
{ | |||
public class JT808UnificationTcpSendServiceTest: TestBase | |||
{ | |||
static IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6565); | |||
private IJT808UnificationSendService jT808UnificationSendService; | |||
private IJT808SessionService jT808SessionServiceDefaultImpl; | |||
public JT808UnificationTcpSendServiceTest() | |||
{ | |||
JT808SimpleTcpClient SimpleTcpClient1 = new JT808SimpleTcpClient(endPoint); | |||
JT808SimpleTcpClient SimpleTcpClient2 = new JT808SimpleTcpClient(endPoint); | |||
JT808SimpleTcpClient SimpleTcpClient3 = new JT808SimpleTcpClient(endPoint); | |||
JT808SimpleTcpClient SimpleTcpClient4 = new JT808SimpleTcpClient(endPoint); | |||
JT808SimpleTcpClient SimpleTcpClient5 = new JT808SimpleTcpClient(endPoint); | |||
// 心跳会话包 | |||
JT808Package jT808Package1 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789001"); | |||
SimpleTcpClient1.WriteAsync(JT808Serializer.Serialize(jT808Package1)); | |||
// 心跳会话包 | |||
JT808Package jT808Package2 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789002"); | |||
SimpleTcpClient2.WriteAsync(JT808Serializer.Serialize(jT808Package2)); | |||
// 心跳会话包 | |||
JT808Package jT808Package3 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789003"); | |||
SimpleTcpClient3.WriteAsync(JT808Serializer.Serialize(jT808Package3)); | |||
// 心跳会话包 | |||
JT808Package jT808Package4 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789004"); | |||
SimpleTcpClient4.WriteAsync(JT808Serializer.Serialize(jT808Package4)); | |||
// 心跳会话包 | |||
JT808Package jT808Package5 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789005"); | |||
SimpleTcpClient5.WriteAsync(JT808Serializer.Serialize(jT808Package5)); | |||
Thread.Sleep(300); | |||
} | |||
[Fact] | |||
public void Test1() | |||
{ | |||
jT808SessionServiceDefaultImpl = ServiceProvider.GetService<IJT808SessionService>(); | |||
jT808UnificationSendService = ServiceProvider.GetService<IJT808UnificationSendService>(); | |||
jT808SessionServiceDefaultImpl.GetTcpAll(); | |||
string no = "123456789001"; | |||
// 文本信息包 | |||
JT808Package jT808Package2 = JT808.Protocol.Enums.JT808MsgId.文本信息下发.Create(no, new JT808_0x8300 | |||
{ | |||
TextFlag = 5, | |||
TextInfo = "smallchi 518" | |||
}); | |||
var data = JT808Serializer.Serialize(jT808Package2); | |||
JT808ResultDto<bool> jt808Result = jT808UnificationSendService.Send(no, data); | |||
Thread.Sleep(1000); | |||
Assert.Equal(200, jt808Result.Code); | |||
Assert.True(jt808Result.Data); | |||
} | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
using JT808.Gateway.Tcp; | |||
using JT808.Protocol; | |||
using JT808.Protocol.Interfaces; | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.Hosting; | |||
using Microsoft.Extensions.Logging; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Text; | |||
namespace JT808.Gateway.Test.Tcp | |||
{ | |||
public class TestBase | |||
{ | |||
public static IServiceProvider ServiceProvider; | |||
public static JT808Serializer JT808Serializer; | |||
static TestBase() | |||
{ | |||
var serverHostBuilder = new HostBuilder() | |||
.ConfigureAppConfiguration((hostingContext, config) => | |||
{ | |||
config.SetBasePath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Tcp")); | |||
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); | |||
}) | |||
.ConfigureServices((hostContext, services) => | |||
{ | |||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||
services.AddJT808Configure() | |||
.AddJT808Gateway(hostContext.Configuration) | |||
.AddJT808GatewayTcpHost() | |||
.Builder(); | |||
//.Replace<>; | |||
}); | |||
var build = serverHostBuilder.Build(); | |||
build.Start(); | |||
ServiceProvider = build.Services; | |||
JT808Serializer = ServiceProvider.GetRequiredService<IJT808Config>().GetSerializer(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,92 @@ | |||
using JT808.Protocol; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Net; | |||
using System.Text; | |||
using System.Threading; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using JT808.Protocol.Extensions; | |||
using Xunit; | |||
using JT808.Gateway.Simples; | |||
using JT808.Gateway.Interfaces; | |||
using JT808.Gateway.Session; | |||
namespace JT808.Gateway.Test.Udp | |||
{ | |||
public class JT808SessionServiceTest:TestBase,IDisposable | |||
{ | |||
static IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 818); | |||
JT808SimpleUdpClient SimpleUdpClient1; | |||
JT808SimpleUdpClient SimpleUdpClient2; | |||
JT808SimpleUdpClient SimpleUdpClient3; | |||
JT808SimpleUdpClient SimpleUdpClient4; | |||
JT808SimpleUdpClient SimpleUdpClient5; | |||
public void Dispose() | |||
{ | |||
SimpleUdpClient1.Down(); | |||
SimpleUdpClient2.Down(); | |||
SimpleUdpClient3.Down(); | |||
SimpleUdpClient4.Down(); | |||
SimpleUdpClient5.Down(); | |||
} | |||
public JT808SessionServiceTest() | |||
{ | |||
SimpleUdpClient1 = new JT808SimpleUdpClient(endPoint); | |||
SimpleUdpClient2 = new JT808SimpleUdpClient(endPoint); | |||
SimpleUdpClient3 = new JT808SimpleUdpClient(endPoint); | |||
SimpleUdpClient4 = new JT808SimpleUdpClient(endPoint); | |||
SimpleUdpClient5 = new JT808SimpleUdpClient(endPoint); | |||
// 心跳会话包 | |||
JT808Package jT808Package1 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789001"); | |||
SimpleUdpClient1.WriteAsync(JT808Serializer.Serialize(jT808Package1)); | |||
// 心跳会话包 | |||
JT808Package jT808Package2 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789002"); | |||
SimpleUdpClient2.WriteAsync(JT808Serializer.Serialize(jT808Package2)); | |||
// 心跳会话包 | |||
JT808Package jT808Package3 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789003"); | |||
SimpleUdpClient3.WriteAsync(JT808Serializer.Serialize(jT808Package3)); | |||
// 心跳会话包 | |||
JT808Package jT808Package4 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789004"); | |||
SimpleUdpClient4.WriteAsync(JT808Serializer.Serialize(jT808Package4)); | |||
// 心跳会话包 | |||
JT808Package jT808Package5 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789005"); | |||
SimpleUdpClient5.WriteAsync(JT808Serializer.Serialize(jT808Package5)); | |||
Thread.Sleep(1000); | |||
} | |||
[Fact] | |||
public void Test1() | |||
{ | |||
IJT808SessionService jT808SessionServiceDefaultImpl = ServiceProvider.GetService<IJT808SessionService>(); | |||
var result = jT808SessionServiceDefaultImpl.GetUdpAll(); | |||
} | |||
[Fact] | |||
public void Test2() | |||
{ | |||
IJT808SessionService jT808SessionServiceDefaultImpl = ServiceProvider.GetService<IJT808SessionService>(); | |||
var result1 = jT808SessionServiceDefaultImpl.GetUdpAll(); | |||
var result2 = jT808SessionServiceDefaultImpl.RemoveByTerminalPhoneNo("123456789001"); | |||
var result3 = jT808SessionServiceDefaultImpl.GetUdpAll(); | |||
} | |||
[Fact] | |||
public void Test3() | |||
{ | |||
// 判断通道是否关闭 | |||
IJT808SessionService jT808SessionServiceDefaultImpl = ServiceProvider.GetService<IJT808SessionService>(); | |||
JT808SessionManager jT808UdpSessionManager = ServiceProvider.GetService<JT808SessionManager>(); | |||
var result1 = jT808SessionServiceDefaultImpl.GetUdpAll(); | |||
SimpleUdpClient1.Down(); | |||
var session = jT808UdpSessionManager.GetSessionByTerminalPhoneNo("123456789001"); | |||
var result3 = jT808UdpSessionManager.GetUdpAll(); | |||
Thread.Sleep(100000); | |||
} | |||
} | |||
} |
@@ -0,0 +1,76 @@ | |||
using JT808.Protocol; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Net; | |||
using System.Text; | |||
using System.Threading; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using JT808.Protocol.Extensions; | |||
using JT808.Protocol.MessageBody; | |||
using JT808.Gateway.Interfaces; | |||
using JT808.Gateway.Simples; | |||
using JT808.Gateway.Dtos; | |||
using Xunit; | |||
namespace JT808.Gateway.Test.Udp | |||
{ | |||
public class JT808UnificationUdpSendServiceTest : TestBase | |||
{ | |||
static IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 818); | |||
private IJT808UnificationSendService jT808UnificationSendService; | |||
private IJT808SessionService jT808SessionServiceDefaultImpl; | |||
public JT808UnificationUdpSendServiceTest() | |||
{ | |||
JT808SimpleUdpClient SimpleUdpClient1 = new JT808SimpleUdpClient(endPoint); | |||
JT808SimpleUdpClient SimpleUdpClient2 = new JT808SimpleUdpClient(endPoint); | |||
JT808SimpleUdpClient SimpleUdpClient3 = new JT808SimpleUdpClient(endPoint); | |||
JT808SimpleUdpClient SimpleUdpClient4 = new JT808SimpleUdpClient(endPoint); | |||
JT808SimpleUdpClient SimpleUdpClient5 = new JT808SimpleUdpClient(endPoint); | |||
// 心跳会话包 | |||
JT808Package jT808Package1 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789001"); | |||
SimpleUdpClient1.WriteAsync(JT808Serializer.Serialize(jT808Package1)); | |||
// 心跳会话包 | |||
JT808Package jT808Package2 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789002"); | |||
SimpleUdpClient2.WriteAsync(JT808Serializer.Serialize(jT808Package2)); | |||
// 心跳会话包 | |||
JT808Package jT808Package3 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789003"); | |||
SimpleUdpClient3.WriteAsync(JT808Serializer.Serialize(jT808Package3)); | |||
// 心跳会话包 | |||
JT808Package jT808Package4 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789004"); | |||
SimpleUdpClient4.WriteAsync(JT808Serializer.Serialize(jT808Package4)); | |||
// 心跳会话包 | |||
JT808Package jT808Package5 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("123456789005"); | |||
SimpleUdpClient5.WriteAsync(JT808Serializer.Serialize(jT808Package5)); | |||
Thread.Sleep(300); | |||
} | |||
[Fact] | |||
public void Test1() | |||
{ | |||
//"126 131 0 0 13 18 52 86 120 144 1 0 11 5 115 109 97 108 108 99 104 105 32 53 49 56 24 126" | |||
jT808SessionServiceDefaultImpl = ServiceProvider.GetService<IJT808SessionService>(); | |||
jT808UnificationSendService = ServiceProvider.GetService<IJT808UnificationSendService>(); | |||
jT808SessionServiceDefaultImpl.GetUdpAll(); | |||
string no = "123456789001"; | |||
// 文本信息包 | |||
JT808Package jT808Package2 = JT808.Protocol.Enums.JT808MsgId.文本信息下发.Create(no, new JT808_0x8300 | |||
{ | |||
TextFlag = 5, | |||
TextInfo = "smallchi 518" | |||
}); | |||
var data = JT808Serializer.Serialize(jT808Package2); | |||
JT808ResultDto<bool> jt808Result = jT808UnificationSendService.Send(no, data); | |||
Thread.Sleep(1000); | |||
Assert.Equal(200, jt808Result.Code); | |||
Assert.True(jt808Result.Data); | |||
} | |||
} | |||
} |
@@ -0,0 +1,41 @@ | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.Hosting; | |||
using Microsoft.Extensions.Logging; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using JT808.Protocol; | |||
using JT808.Protocol.Interfaces; | |||
using JT808.Gateway.Udp; | |||
using System.IO; | |||
namespace JT808.Gateway.Test.Udp | |||
{ | |||
public class TestBase | |||
{ | |||
public static IServiceProvider ServiceProvider; | |||
public static JT808Serializer JT808Serializer; | |||
static TestBase() | |||
{ | |||
var serverHostBuilder = new HostBuilder() | |||
.ConfigureAppConfiguration((hostingContext, config) => | |||
{ | |||
config.SetBasePath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"Udp")); | |||
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); | |||
}) | |||
.ConfigureServices((hostContext, services) => | |||
{ | |||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||
services.AddJT808Configure() | |||
.AddJT808Gateway(hostContext.Configuration) | |||
.AddJT808GatewayUdpHost(); | |||
}); | |||
var build = serverHostBuilder.Build(); | |||
build.Start(); | |||
ServiceProvider = build.Services; | |||
JT808Serializer = ServiceProvider.GetRequiredService<IJT808Config>().GetSerializer(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<OutputType>Exe</OutputType> | |||
<TargetFramework>netcoreapp3.0</TargetFramework> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.0.0" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\..\JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Update="appsettings.json"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
</ItemGroup> | |||
</Project> |
@@ -0,0 +1,40 @@ | |||
using JT808.Gateway.Configs.Kafka; | |||
using JT808.Gateway.Kafka; | |||
using JT808.Gateway.PubSub; | |||
using JT808.Protocol.Extensions; | |||
using Microsoft.Extensions.Logging; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.Traffic.Test | |||
{ | |||
public class JT808DotNettyTrafficServiceTest | |||
{ | |||
private readonly CSRedis.CSRedisClient redisClien; | |||
public readonly ILogger<JT808DotNettyTrafficServiceTest> logger; | |||
public JT808DotNettyTrafficServiceTest(ILoggerFactory loggerFactory) { | |||
redisClien = new CSRedis.CSRedisClient("127.0.0.1:6379,password=smallchi"); | |||
RedisHelper.Initialization(redisClien); | |||
logger = loggerFactory.CreateLogger<JT808DotNettyTrafficServiceTest>(); | |||
Task.Run(() => { | |||
while (true) | |||
{ | |||
Thread.Sleep(5000); | |||
using (IJT808MsgProducer jT808MsgProducer = new JT808MsgProducer(new JT808MsgProducerConfig | |||
{ | |||
BootstrapServers = "127.0.0.1:9092", | |||
TopicName = "JT808Msg" | |||
})) | |||
{ | |||
jT808MsgProducer.ProduceAsync("011111111111", "7E02000032011111111111012E00000000000C00000160E42506C30C82002C00000000180914142057010400001DC003020000250400000000300115310100977E".ToHexBytes()).Wait(); | |||
} | |||
var length= RedisHelper.HGet("011111111111", DateTime.Now.ToString("yyyyMMdd")); | |||
logger.LogDebug($"{011111111111}:{length}"); | |||
} | |||
}); | |||
} | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
using JT808.Gateway.BusinessServices.Traffic; | |||
using JT808.Gateway.Kafka; | |||
using JT808.Protocol; | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.Hosting; | |||
using Microsoft.Extensions.Logging; | |||
using System; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.Traffic.Test | |||
{ | |||
class Program | |||
{ | |||
async static Task Main(string[] args) | |||
{ | |||
var hostBuilder = new HostBuilder() | |||
.UseEnvironment(args[0].Split('=')[1]) | |||
.ConfigureAppConfiguration((hostContext, config) => { | |||
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory); | |||
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) | |||
.AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true); | |||
}) | |||
.ConfigureLogging((hostContext, configLogging) => { | |||
configLogging.AddConsole(); | |||
configLogging.SetMinimumLevel(LogLevel.Trace); | |||
}) | |||
.ConfigureServices((hostContext, services) => { | |||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||
services.AddSingleton<JT808DotNettyTrafficServiceTest>(); | |||
services.AddJT808Configure() | |||
.AddJT808ClientKafka() | |||
.AddMsgConsumer(hostContext.Configuration) | |||
.AddInprocJT808Traffic(); | |||
services.BuildServiceProvider().GetRequiredService<JT808DotNettyTrafficServiceTest>(); | |||
}) | |||
; | |||
await hostBuilder.RunConsoleAsync(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<OutputType>Exe</OutputType> | |||
<TargetFramework>netcoreapp3.0</TargetFramework> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="2.2.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.0.0" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\..\JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Update="appsettings.json"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
</ItemGroup> | |||
</Project> |
@@ -0,0 +1,35 @@ | |||
using JT808.Gateway.Configs.Kafka; | |||
using JT808.Gateway.Kafka; | |||
using JT808.Gateway.PubSub; | |||
using JT808.Protocol.Extensions; | |||
using Microsoft.Extensions.Logging; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.Transmit.Test | |||
{ | |||
public class JT808DotNettyTransmitServiceTest | |||
{ | |||
public readonly ILogger<JT808DotNettyTransmitServiceTest> logger; | |||
public JT808DotNettyTransmitServiceTest(ILoggerFactory loggerFactory) { | |||
logger = loggerFactory.CreateLogger<JT808DotNettyTransmitServiceTest>(); | |||
Task.Run(() => { | |||
while (true) | |||
{ | |||
Thread.Sleep(5000); | |||
using (IJT808MsgProducer jT808MsgProducer = new JT808MsgProducer(new JT808MsgProducerConfig | |||
{ | |||
BootstrapServers = "127.0.0.1:9092", | |||
TopicName = "JT808Msg" | |||
})) | |||
{ | |||
jT808MsgProducer.ProduceAsync("011111111111", "7E02000032011111111111012E00000000000C00000160E42506C30C82002C00000000180914142057010400001DC003020000250400000000300115310100977E".ToHexBytes()).Wait(); | |||
} | |||
} | |||
}); | |||
} | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
using JT808.Gateway.BusinessServices.Transmit; | |||
using JT808.Gateway.Kafka; | |||
using JT808.Protocol; | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.Hosting; | |||
using Microsoft.Extensions.Logging; | |||
using System; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.Transmit.Test | |||
{ | |||
class Program | |||
{ | |||
async static Task Main(string[] args) | |||
{ | |||
var hostBuilder = new HostBuilder() | |||
.UseEnvironment(args[0].Split('=')[1]) | |||
.ConfigureAppConfiguration((hostContext, config) => { | |||
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory); | |||
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) | |||
.AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true); | |||
}) | |||
.ConfigureLogging((hostContext, configLogging) => { | |||
configLogging.AddConsole(); | |||
configLogging.SetMinimumLevel(LogLevel.Trace); | |||
}) | |||
.ConfigureServices((hostContext, services) => { | |||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||
services.AddSingleton<JT808DotNettyTransmitServiceTest>(); | |||
services.AddJT808Configure() | |||
.AddJT808ClientKafka() | |||
.AddMsgConsumer(hostContext.Configuration) | |||
.AddInprocJT808Transmit(hostContext.Configuration); | |||
services.BuildServiceProvider().GetRequiredService<JT808DotNettyTransmitServiceTest>(); | |||
}) | |||
; | |||
await hostBuilder.RunConsoleAsync(); | |||
} | |||
} | |||
} |
@@ -9,6 +9,26 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808.Gateway.SimpleServer" | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808.Gateway.SimpleClient", "JT808.Gateway.SimpleClient\JT808.Gateway.SimpleClient.csproj", "{886D4937-7265-40DC-87CC-85CE35553214}" | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808.Gateway.Kafka", "JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj", "{790E132C-7D92-4A6A-8CF0-2C181331FB31}" | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808.Gateway.CleintBenchmark", "JT808.Gateway.CleintBenchmark\JT808.Gateway.CleintBenchmark.csproj", "{1A925C08-2590-4E55-84F2-96F01306D34D}" | |||
EndProject | |||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{DC0E0AC1-C4BD-4291-AD16-744080411C3D}" | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.Traffic.Test", "JT808.Gateway.Tests\JT808.Gateway.Traffic.Test\JT808.Gateway.Traffic.Test.csproj", "{D4DF5285-612A-417D-BDE4-690BDF0C07C6}" | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.Transmit.Test", "JT808.Gateway.Tests\JT808.Gateway.Transmit.Test\JT808.Gateway.Transmit.Test.csproj", "{5E2C290C-637B-4F8B-AE03-1A4B669F7FFB}" | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.SessionNotice.Test", "JT808.Gateway.Tests\JT808.Gateway.SessionNotice.Test\JT808.Gateway.SessionNotice.Test.csproj", "{562B16BD-1D4C-40FD-86CF-7845DBC9C1EE}" | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.ReplyMessage.Test", "JT808.Gateway.Tests\JT808.Gateway.ReplyMessage.Test\JT808.Gateway.ReplyMessage.Test.csproj", "{CDE064DE-0E8E-4165-8F6A-6C03A8783506}" | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.MsgLogging.Test", "JT808.Gateway.Tests\JT808.Gateway.MsgLogging.Test\JT808.Gateway.MsgLogging.Test.csproj", "{8BD638B1-1F16-4BA8-8506-1B83DA4A884E}" | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.MsgIdHandler.Test", "JT808.Gateway.Tests\JT808.Gateway.MsgIdHandler.Test\JT808.Gateway.MsgIdHandler.Test.csproj", "{CC2ABC8E-CC78-4B68-8670-90C2BCAB434E}" | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808.Gateway.Test", "JT808.Gateway.Tests\JT808.Gateway.Test\JT808.Gateway.Test.csproj", "{F1031636-69CF-4C44-AF0B-F8BE8DE03864}" | |||
EndProject | |||
Global | |||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
Debug|Any CPU = Debug|Any CPU | |||
@@ -27,10 +47,55 @@ Global | |||
{886D4937-7265-40DC-87CC-85CE35553214}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{886D4937-7265-40DC-87CC-85CE35553214}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{886D4937-7265-40DC-87CC-85CE35553214}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{790E132C-7D92-4A6A-8CF0-2C181331FB31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{790E132C-7D92-4A6A-8CF0-2C181331FB31}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{790E132C-7D92-4A6A-8CF0-2C181331FB31}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{790E132C-7D92-4A6A-8CF0-2C181331FB31}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{1A925C08-2590-4E55-84F2-96F01306D34D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{1A925C08-2590-4E55-84F2-96F01306D34D}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{1A925C08-2590-4E55-84F2-96F01306D34D}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{1A925C08-2590-4E55-84F2-96F01306D34D}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{D4DF5285-612A-417D-BDE4-690BDF0C07C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{D4DF5285-612A-417D-BDE4-690BDF0C07C6}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{D4DF5285-612A-417D-BDE4-690BDF0C07C6}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{D4DF5285-612A-417D-BDE4-690BDF0C07C6}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{5E2C290C-637B-4F8B-AE03-1A4B669F7FFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{5E2C290C-637B-4F8B-AE03-1A4B669F7FFB}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{5E2C290C-637B-4F8B-AE03-1A4B669F7FFB}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{5E2C290C-637B-4F8B-AE03-1A4B669F7FFB}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{562B16BD-1D4C-40FD-86CF-7845DBC9C1EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{562B16BD-1D4C-40FD-86CF-7845DBC9C1EE}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{562B16BD-1D4C-40FD-86CF-7845DBC9C1EE}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{562B16BD-1D4C-40FD-86CF-7845DBC9C1EE}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{CDE064DE-0E8E-4165-8F6A-6C03A8783506}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{CDE064DE-0E8E-4165-8F6A-6C03A8783506}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{CDE064DE-0E8E-4165-8F6A-6C03A8783506}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{CDE064DE-0E8E-4165-8F6A-6C03A8783506}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{8BD638B1-1F16-4BA8-8506-1B83DA4A884E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{8BD638B1-1F16-4BA8-8506-1B83DA4A884E}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{8BD638B1-1F16-4BA8-8506-1B83DA4A884E}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{8BD638B1-1F16-4BA8-8506-1B83DA4A884E}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{CC2ABC8E-CC78-4B68-8670-90C2BCAB434E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{CC2ABC8E-CC78-4B68-8670-90C2BCAB434E}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{CC2ABC8E-CC78-4B68-8670-90C2BCAB434E}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{CC2ABC8E-CC78-4B68-8670-90C2BCAB434E}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{F1031636-69CF-4C44-AF0B-F8BE8DE03864}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{F1031636-69CF-4C44-AF0B-F8BE8DE03864}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{F1031636-69CF-4C44-AF0B-F8BE8DE03864}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{F1031636-69CF-4C44-AF0B-F8BE8DE03864}.Release|Any CPU.Build.0 = Release|Any CPU | |||
EndGlobalSection | |||
GlobalSection(SolutionProperties) = preSolution | |||
HideSolutionNode = FALSE | |||
EndGlobalSection | |||
GlobalSection(NestedProjects) = preSolution | |||
{D4DF5285-612A-417D-BDE4-690BDF0C07C6} = {DC0E0AC1-C4BD-4291-AD16-744080411C3D} | |||
{5E2C290C-637B-4F8B-AE03-1A4B669F7FFB} = {DC0E0AC1-C4BD-4291-AD16-744080411C3D} | |||
{562B16BD-1D4C-40FD-86CF-7845DBC9C1EE} = {DC0E0AC1-C4BD-4291-AD16-744080411C3D} | |||
{CDE064DE-0E8E-4165-8F6A-6C03A8783506} = {DC0E0AC1-C4BD-4291-AD16-744080411C3D} | |||
{8BD638B1-1F16-4BA8-8506-1B83DA4A884E} = {DC0E0AC1-C4BD-4291-AD16-744080411C3D} | |||
{CC2ABC8E-CC78-4B68-8670-90C2BCAB434E} = {DC0E0AC1-C4BD-4291-AD16-744080411C3D} | |||
{F1031636-69CF-4C44-AF0B-F8BE8DE03864} = {DC0E0AC1-C4BD-4291-AD16-744080411C3D} | |||
EndGlobalSection | |||
GlobalSection(ExtensibilityGlobals) = postSolution | |||
SolutionGuid = {F5671BD2-B44A-4A7C-80EA-E060A512992D} | |||
EndGlobalSection | |||
@@ -0,0 +1,14 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.BusinessServices.MsgIdHandler | |||
{ | |||
/// <summary> | |||
/// JT808消息Id处理程序 | |||
/// </summary> | |||
public interface IJT808MsgIdHandler | |||
{ | |||
void Processor((string TerminalNo, byte[] Data) parameter); | |||
} | |||
} |
@@ -0,0 +1,18 @@ | |||
using Microsoft.Extensions.DependencyInjection; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.BusinessServices.MsgIdHandler | |||
{ | |||
public static class JT808MsgIdHandlerExtensions | |||
{ | |||
public static IJT808ClientBuilder AddJT808MsgIdHandler<TJT808MsgIdHandler>(this IJT808ClientBuilder jT808ClientBuilder) | |||
where TJT808MsgIdHandler: IJT808MsgIdHandler | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.AddSingleton(typeof(IJT808MsgIdHandler),typeof(TJT808MsgIdHandler)); | |||
jT808ClientBuilder.JT808Builder.Services.AddHostedService<JT808MsgIdHandlerHostedService>(); | |||
return jT808ClientBuilder; | |||
} | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
using System.Threading.Tasks; | |||
using Microsoft.Extensions.Hosting; | |||
using System.Threading; | |||
using JT808.Gateway.PubSub; | |||
namespace JT808.Gateway.BusinessServices.MsgIdHandler | |||
{ | |||
public class JT808MsgIdHandlerHostedService : IHostedService | |||
{ | |||
private readonly IJT808MsgConsumer jT808MsgConsumer; | |||
private readonly IJT808MsgIdHandler jT808MsgIdHandler; | |||
public JT808MsgIdHandlerHostedService( | |||
IJT808MsgIdHandler jT808DotNettyMsgIdHandler, | |||
IJT808MsgConsumer jT808MsgConsumer) | |||
{ | |||
this.jT808MsgIdHandler = jT808DotNettyMsgIdHandler; | |||
this.jT808MsgConsumer = jT808MsgConsumer; | |||
} | |||
public Task StartAsync(CancellationToken cancellationToken) | |||
{ | |||
jT808MsgConsumer.Subscribe(); | |||
jT808MsgConsumer.OnMessage(jT808MsgIdHandler.Processor); | |||
return Task.CompletedTask; | |||
} | |||
public Task StopAsync(CancellationToken cancellationToken) | |||
{ | |||
jT808MsgConsumer.Unsubscribe(); | |||
return Task.CompletedTask; | |||
} | |||
} | |||
} |
@@ -0,0 +1,15 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.BusinessServices.MsgLogging | |||
{ | |||
/// <summary> | |||
/// 808数据上下行日志接口 | |||
/// </summary> | |||
public interface IJT808MsgLogging | |||
{ | |||
void Processor((string TerminalNo, byte[] Data) parameter, JT808MsgLoggingType jT808MsgLoggingType); | |||
} | |||
} |
@@ -0,0 +1,36 @@ | |||
using System.Threading.Tasks; | |||
using Microsoft.Extensions.Hosting; | |||
using System.Threading; | |||
using JT808.Gateway.PubSub; | |||
namespace JT808.Gateway.BusinessServices.MsgLogging | |||
{ | |||
public class JT808MsgDownLoggingHostedService : IHostedService | |||
{ | |||
private readonly IJT808MsgReplyConsumer jT808MsgReplyConsumer; | |||
private readonly IJT808MsgLogging jT808MsgLogging; | |||
public JT808MsgDownLoggingHostedService( | |||
IJT808MsgLogging jT808MsgLogging, | |||
IJT808MsgReplyConsumer jT808MsgReplyConsumer) | |||
{ | |||
this.jT808MsgReplyConsumer = jT808MsgReplyConsumer; | |||
this.jT808MsgLogging = jT808MsgLogging; | |||
} | |||
public Task StartAsync(CancellationToken cancellationToken) | |||
{ | |||
jT808MsgReplyConsumer.Subscribe(); | |||
jT808MsgReplyConsumer.OnMessage(item=> | |||
{ | |||
jT808MsgLogging.Processor(item, JT808MsgLoggingType.down); | |||
}); | |||
return Task.CompletedTask; | |||
} | |||
public Task StopAsync(CancellationToken cancellationToken) | |||
{ | |||
jT808MsgReplyConsumer.Unsubscribe(); | |||
return Task.CompletedTask; | |||
} | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
using Microsoft.Extensions.DependencyInjection; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.BusinessServices.MsgLogging | |||
{ | |||
public static class JT808MsgLoggingExtensions | |||
{ | |||
public static IJT808ClientBuilder AddJT808MsgLogging<TJT808MsgLogging>(this IJT808ClientBuilder jT808ClientBuilder) | |||
where TJT808MsgLogging: IJT808MsgLogging | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.AddSingleton(typeof(IJT808MsgLogging),typeof(TJT808MsgLogging)); | |||
jT808ClientBuilder.JT808Builder.Services.AddHostedService<JT808MsgDownLoggingHostedService>(); | |||
jT808ClientBuilder.JT808Builder.Services.AddHostedService<JT808MsgUpLoggingHostedService>(); | |||
return jT808ClientBuilder; | |||
} | |||
} | |||
} |
@@ -0,0 +1,18 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.BusinessServices.MsgLogging | |||
{ | |||
public enum JT808MsgLoggingType | |||
{ | |||
/// <summary> | |||
/// 数据上行 | |||
/// </summary> | |||
up, | |||
/// <summary> | |||
/// 数据下行 | |||
/// </summary> | |||
down | |||
} | |||
} |
@@ -0,0 +1,36 @@ | |||
using System.Threading.Tasks; | |||
using Microsoft.Extensions.Hosting; | |||
using System.Threading; | |||
using JT808.Gateway.PubSub; | |||
namespace JT808.Gateway.BusinessServices.MsgLogging | |||
{ | |||
public class JT808MsgUpLoggingHostedService : IHostedService | |||
{ | |||
private readonly IJT808MsgConsumer jT808MsgConsumer; | |||
private readonly IJT808MsgLogging jT808MsgLogging; | |||
public JT808MsgUpLoggingHostedService( | |||
IJT808MsgLogging jT808MsgLogging, | |||
IJT808MsgConsumer jT808MsgConsumer) | |||
{ | |||
this.jT808MsgConsumer = jT808MsgConsumer; | |||
this.jT808MsgLogging = jT808MsgLogging; | |||
} | |||
public Task StartAsync(CancellationToken cancellationToken) | |||
{ | |||
jT808MsgConsumer.Subscribe(); | |||
jT808MsgConsumer.OnMessage(item=> | |||
{ | |||
jT808MsgLogging.Processor(item, JT808MsgLoggingType.up); | |||
}); | |||
return Task.CompletedTask; | |||
} | |||
public Task StopAsync(CancellationToken cancellationToken) | |||
{ | |||
jT808MsgConsumer.Unsubscribe(); | |||
return Task.CompletedTask; | |||
} | |||
} | |||
} |
@@ -0,0 +1,57 @@ | |||
using Microsoft.Extensions.DependencyInjection; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.BusinessServices.ReplyMessage | |||
{ | |||
public static class JT808ReplyMessageExtensions | |||
{ | |||
/// <summary> | |||
/// 独享消息应答服务(不同的消费者实例) | |||
/// </summary> | |||
/// <param name="jT808ClientBuilder"></param> | |||
/// <returns></returns> | |||
public static IJT808ClientBuilder AddInprocJT808ReplyMessage(this IJT808ClientBuilder jT808ClientBuilder) | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.AddSingleton<JT808ReplyMessageService>(); | |||
jT808ClientBuilder.JT808Builder.Services.AddHostedService<JT808ReplyMessageHostedService>(); | |||
return jT808ClientBuilder; | |||
} | |||
/// <summary> | |||
/// 独享消息应答服务(不同的消费者实例) | |||
/// </summary> | |||
/// <typeparam name="TReplyMessageService">自定义消息回复服务</typeparam> | |||
/// <param name="jT808ClientBuilder"></param> | |||
/// <returns></returns> | |||
public static IJT808ClientBuilder AddInprocJT808ReplyMessage<TReplyMessageService>(this IJT808ClientBuilder jT808ClientBuilder) | |||
where TReplyMessageService : JT808ReplyMessageService | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.AddSingleton<JT808ReplyMessageService,TReplyMessageService>(); | |||
jT808ClientBuilder.JT808Builder.Services.AddHostedService<JT808ReplyMessageHostedService>(); | |||
return jT808ClientBuilder; | |||
} | |||
/// <summary> | |||
/// 共享消息应答服务(消费者单实例) | |||
/// </summary> | |||
/// <typeparam name="TReplyMessageService">自定义消息回复服务</typeparam> | |||
/// <param name="jT808ClientBuilder"></param> | |||
/// <returns></returns> | |||
public static IJT808ClientBuilder AddShareJT808ReplyMessage<TReplyMessageService>(this IJT808ClientBuilder jT808ClientBuilder) | |||
where TReplyMessageService : JT808ReplyMessageService | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.AddSingleton<JT808ReplyMessageService, TReplyMessageService>(); | |||
return jT808ClientBuilder; | |||
} | |||
/// <summary> | |||
/// 共享消息应答服务(消费者单实例) | |||
/// </summary> | |||
/// <param name="jT808ClientBuilder"></param> | |||
/// <returns></returns> | |||
public static IJT808ClientBuilder AddShareJT808ReplyMessage(this IJT808ClientBuilder jT808ClientBuilder) | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.AddSingleton<JT808ReplyMessageService>(); | |||
return jT808ClientBuilder; | |||
} | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
using System.Threading.Tasks; | |||
using Microsoft.Extensions.Hosting; | |||
using System.Threading; | |||
using JT808.Gateway.PubSub; | |||
namespace JT808.Gateway.BusinessServices.ReplyMessage | |||
{ | |||
public class JT808ReplyMessageHostedService : IHostedService | |||
{ | |||
private readonly IJT808MsgConsumer jT808MsgConsumer; | |||
private readonly JT808ReplyMessageService jT808DotNettyReplyMessageService; | |||
public JT808ReplyMessageHostedService( | |||
JT808ReplyMessageService jT808DotNettyReplyMessageService, | |||
IJT808MsgConsumer jT808MsgConsumer) | |||
{ | |||
this.jT808MsgConsumer = jT808MsgConsumer; | |||
this.jT808DotNettyReplyMessageService = jT808DotNettyReplyMessageService; | |||
} | |||
public Task StartAsync(CancellationToken cancellationToken) | |||
{ | |||
jT808MsgConsumer.Subscribe(); | |||
jT808MsgConsumer.OnMessage(jT808DotNettyReplyMessageService.Processor); | |||
return Task.CompletedTask; | |||
} | |||
public Task StopAsync(CancellationToken cancellationToken) | |||
{ | |||
jT808MsgConsumer.Unsubscribe(); | |||
return Task.CompletedTask; | |||
} | |||
} | |||
} |
@@ -0,0 +1,165 @@ | |||
using JT808.Gateway.PubSub; | |||
using JT808.Protocol; | |||
using JT808.Protocol.Enums; | |||
using JT808.Protocol.Extensions; | |||
using JT808.Protocol.MessageBody; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.BusinessServices.ReplyMessage | |||
{ | |||
public class JT808ReplyMessageService | |||
{ | |||
protected Dictionary<ushort, Func<JT808HeaderPackage, byte[]>> HandlerDict { get; } | |||
protected JT808Serializer JT808Serializer { get; } | |||
protected IJT808MsgReplyProducer JT808MsgReplyProducer { get; } | |||
public JT808ReplyMessageService( | |||
IJT808Config jT808Config, | |||
IJT808MsgReplyProducer jT808MsgReplyProducer) | |||
{ | |||
this.JT808Serializer = jT808Config.GetSerializer(); | |||
this.JT808MsgReplyProducer = jT808MsgReplyProducer; | |||
HandlerDict = new Dictionary<ushort, Func<JT808HeaderPackage, byte[]>> { | |||
{JT808MsgId.终端通用应答.ToUInt16Value(), Msg0x0001}, | |||
{JT808MsgId.终端鉴权.ToUInt16Value(), Msg0x0102}, | |||
{JT808MsgId.终端心跳.ToUInt16Value(), Msg0x0002}, | |||
{JT808MsgId.终端注销.ToUInt16Value(), Msg0x0003}, | |||
{JT808MsgId.终端注册.ToUInt16Value(), Msg0x0100}, | |||
{JT808MsgId.位置信息汇报.ToUInt16Value(),Msg0x0200 }, | |||
{JT808MsgId.定位数据批量上传.ToUInt16Value(),Msg0x0704 }, | |||
{JT808MsgId.数据上行透传.ToUInt16Value(),Msg0x0900 } | |||
}; | |||
} | |||
public virtual void Processor((string TerminalNo, byte[] Data) parameter) | |||
{ | |||
try | |||
{ | |||
var request = JT808Serializer.HeaderDeserialize(parameter.Data); | |||
if (HandlerDict.TryGetValue(request.Header.MsgId, out var func)) | |||
{ | |||
var buffer = func(request); | |||
if (buffer != null) | |||
{ | |||
JT808MsgReplyProducer.ProduceAsync(parameter.TerminalNo, buffer); | |||
} | |||
} | |||
} | |||
catch | |||
{ | |||
} | |||
} | |||
/// <summary> | |||
/// 终端通用应答 | |||
/// 平台无需回复 | |||
/// 实现自己的业务 | |||
/// </summary> | |||
/// <param name="request"></param> | |||
/// <returns></returns> | |||
public virtual byte[] Msg0x0001(JT808HeaderPackage request) | |||
{ | |||
return null; | |||
} | |||
/// <summary> | |||
/// 终端心跳 | |||
/// </summary> | |||
/// <param name="request"></param> | |||
/// <returns></returns> | |||
public virtual byte[] Msg0x0002(JT808HeaderPackage request) | |||
{ | |||
return JT808Serializer.Serialize(JT808MsgId.平台通用应答.Create(request.Header.TerminalPhoneNo, new JT808_0x8001() | |||
{ | |||
MsgId = request.Header.MsgId, | |||
JT808PlatformResult = JT808PlatformResult.成功, | |||
MsgNum = request.Header.MsgNum | |||
})); | |||
} | |||
/// <summary> | |||
/// 终端注销 | |||
/// </summary> | |||
/// <param name="request"></param> | |||
/// <returns></returns> | |||
public virtual byte[] Msg0x0003(JT808HeaderPackage request) | |||
{ | |||
return JT808Serializer.Serialize(JT808MsgId.平台通用应答.Create(request.Header.TerminalPhoneNo, new JT808_0x8001() | |||
{ | |||
MsgId = request.Header.MsgId, | |||
JT808PlatformResult = JT808PlatformResult.成功, | |||
MsgNum = request.Header.MsgNum | |||
})); | |||
} | |||
/// <summary> | |||
/// 终端注册 | |||
/// </summary> | |||
/// <param name="request"></param> | |||
/// <returns></returns> | |||
public virtual byte[] Msg0x0100(JT808HeaderPackage request) | |||
{ | |||
return JT808Serializer.Serialize(JT808MsgId.终端注册应答.Create(request.Header.TerminalPhoneNo, new JT808_0x8100() | |||
{ | |||
Code = "J" + request.Header.TerminalPhoneNo, | |||
JT808TerminalRegisterResult = JT808TerminalRegisterResult.成功, | |||
MsgNum = request.Header.MsgNum | |||
})); | |||
} | |||
/// <summary> | |||
/// 终端鉴权 | |||
/// </summary> | |||
/// <param name="request"></param> | |||
/// <returns></returns> | |||
public virtual byte[] Msg0x0102(JT808HeaderPackage request) | |||
{ | |||
return JT808Serializer.Serialize(JT808MsgId.平台通用应答.Create(request.Header.TerminalPhoneNo, new JT808_0x8001() | |||
{ | |||
MsgId = request.Header.MsgId, | |||
JT808PlatformResult = JT808PlatformResult.成功, | |||
MsgNum = request.Header.MsgNum | |||
})); | |||
} | |||
/// <summary> | |||
/// 位置信息汇报 | |||
/// </summary> | |||
/// <param name="request"></param> | |||
/// <returns></returns> | |||
public virtual byte[] Msg0x0200(JT808HeaderPackage request) | |||
{ | |||
return JT808Serializer.Serialize(JT808MsgId.平台通用应答.Create(request.Header.TerminalPhoneNo, new JT808_0x8001() | |||
{ | |||
MsgId = request.Header.MsgId, | |||
JT808PlatformResult = JT808PlatformResult.成功, | |||
MsgNum = request.Header.MsgNum | |||
})); | |||
} | |||
/// <summary> | |||
/// 定位数据批量上传 | |||
/// </summary> | |||
/// <param name="request"></param> | |||
/// <returns></returns> | |||
public virtual byte[] Msg0x0704(JT808HeaderPackage request) | |||
{ | |||
return JT808Serializer.Serialize(JT808MsgId.平台通用应答.Create(request.Header.TerminalPhoneNo, new JT808_0x8001() | |||
{ | |||
MsgId = request.Header.MsgId, | |||
JT808PlatformResult = JT808PlatformResult.成功, | |||
MsgNum = request.Header.MsgNum | |||
})); | |||
} | |||
/// <summary> | |||
/// 数据上行透传 | |||
/// </summary> | |||
/// <param name="request"></param> | |||
/// <returns></returns> | |||
public virtual byte[] Msg0x0900(JT808HeaderPackage request) | |||
{ | |||
return JT808Serializer.Serialize(JT808MsgId.平台通用应答.Create(request.Header.TerminalPhoneNo, new JT808_0x8001() | |||
{ | |||
MsgId = request.Header.MsgId, | |||
JT808PlatformResult = JT808PlatformResult.成功, | |||
MsgNum = request.Header.MsgNum | |||
})); | |||
} | |||
} | |||
} |
@@ -0,0 +1,60 @@ | |||
using Microsoft.Extensions.DependencyInjection; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.BusinessServices.SessionNotice | |||
{ | |||
public static class JT808SessionNoticeExtensions | |||
{ | |||
/// <summary> | |||
/// 独享消息会话通知服务(不同的消费者实例) | |||
/// </summary> | |||
/// <param name="jT808ClientBuilder"></param> | |||
/// <returns></returns> | |||
public static IJT808ClientBuilder AddInprocJT808SessionNotice(this IJT808ClientBuilder jT808ClientBuilder) | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.AddSingleton<JT808SessionNoticeService>(); | |||
jT808ClientBuilder.JT808Builder.Services.AddHostedService<JT808SessionNoticeHostedService>(); | |||
return jT808ClientBuilder; | |||
} | |||
/// <summary> | |||
/// 独享消息会话通知服务(不同的消费者实例) | |||
/// </summary> | |||
/// <typeparam name="TSessionNoticeService">自定义会话通知服务</typeparam> | |||
/// <param name="jT808ClientBuilder"></param> | |||
/// <returns></returns> | |||
public static IJT808ClientBuilder AddInprocJT808SessionNotice<TSessionNoticeService>(this IJT808ClientBuilder jT808ClientBuilder) | |||
where TSessionNoticeService : JT808SessionNoticeService | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.AddSingleton<JT808SessionNoticeService,TSessionNoticeService>(); | |||
jT808ClientBuilder.JT808Builder.Services.AddHostedService<JT808SessionNoticeHostedService>(); | |||
return jT808ClientBuilder; | |||
} | |||
/// <summary> | |||
/// 共享消息会话通知服务(消费者单实例) | |||
/// </summary> | |||
/// <typeparam name="TSessionNoticeService">自定义会话通知服务</typeparam> | |||
/// <param name="jT808ClientBuilder"></param> | |||
/// <returns></returns> | |||
public static IJT808ClientBuilder AddShareJT808SessionNotice<TSessionNoticeService>(this IJT808ClientBuilder jT808ClientBuilder) | |||
where TSessionNoticeService : JT808SessionNoticeService | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.AddSingleton<JT808SessionNoticeService, TSessionNoticeService>(); | |||
return jT808ClientBuilder; | |||
} | |||
/// <summary> | |||
/// 共享消息会话通知服务(消费者单实例) | |||
/// </summary> | |||
/// <param name="jT808ClientBuilder"></param> | |||
/// <returns></returns> | |||
public static IJT808ClientBuilder AddShareJT808SessionNotice(this IJT808ClientBuilder jT808ClientBuilder) | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.AddSingleton<JT808SessionNoticeService>(); | |||
return jT808ClientBuilder; | |||
} | |||
} | |||
} |
@@ -0,0 +1,35 @@ | |||
using System.Threading.Tasks; | |||
using JT808.Protocol; | |||
using JT808.Protocol.Interfaces; | |||
using Microsoft.Extensions.Hosting; | |||
using System.Threading; | |||
using JT808.Gateway.PubSub; | |||
namespace JT808.Gateway.BusinessServices.SessionNotice | |||
{ | |||
public class JT808SessionNoticeHostedService : IHostedService | |||
{ | |||
private readonly JT808SessionNoticeService jT808DotNettySessionNoticeService; | |||
private readonly IJT808SessionConsumer jT808SessionConsumer; | |||
public JT808SessionNoticeHostedService( | |||
IJT808SessionConsumer jT808SessionConsumer, | |||
JT808SessionNoticeService jT808DotNettySessionNoticeService) | |||
{ | |||
this.jT808DotNettySessionNoticeService = jT808DotNettySessionNoticeService; | |||
this.jT808SessionConsumer = jT808SessionConsumer; | |||
} | |||
public Task StartAsync(CancellationToken cancellationToken) | |||
{ | |||
jT808SessionConsumer.Subscribe(); | |||
jT808SessionConsumer.OnMessage(jT808DotNettySessionNoticeService.Processor); | |||
return Task.CompletedTask; | |||
} | |||
public Task StopAsync(CancellationToken cancellationToken) | |||
{ | |||
jT808SessionConsumer.Unsubscribe(); | |||
return Task.CompletedTask; | |||
} | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.Logging; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.BusinessServices.SessionNotice | |||
{ | |||
public class JT808SessionNoticeService | |||
{ | |||
protected ILogger logger { get; } | |||
public JT808SessionNoticeService(ILoggerFactory loggerFactory) | |||
{ | |||
logger = loggerFactory.CreateLogger("JT808DotNettySessionNoticeService"); | |||
} | |||
public virtual void Processor((string Notice, string TerminalNo) parameter) | |||
{ | |||
if (logger.IsEnabled(LogLevel.Debug)) | |||
{ | |||
logger.LogDebug($"{parameter.Notice}-{parameter.TerminalNo}"); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
using Microsoft.Extensions.Configuration; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.BusinessServices.Traffic | |||
{ | |||
public class JT808TrafficService:IDisposable | |||
{ | |||
private readonly CSRedis.CSRedisClient redisClien; | |||
public JT808TrafficService(IConfiguration configuration) | |||
{ | |||
redisClien = new CSRedis.CSRedisClient(configuration.GetConnectionString("TrafficRedisHost")); | |||
TrafficRedisClient.Initialization(redisClien); | |||
} | |||
public void Dispose() | |||
{ | |||
redisClien.Dispose(); | |||
} | |||
/// <summary> | |||
/// 按设备每天统计sim卡流量 | |||
/// </summary> | |||
/// <param name="terminalNo"></param> | |||
/// <param name="len"></param> | |||
public void Processor(string terminalNo,int len) | |||
{ | |||
TrafficRedisClient.HIncrBy(terminalNo, DateTime.Now.ToString("yyyyMMdd"), len); | |||
} | |||
} | |||
} |
@@ -0,0 +1,33 @@ | |||
using Microsoft.Extensions.DependencyInjection; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.BusinessServices.Traffic | |||
{ | |||
public static class JT808TrafficServiceExtensions | |||
{ | |||
/// <summary> | |||
/// 独享消息流量统计服务(不同的消费者实例) | |||
/// </summary> | |||
/// <param name="jT808ClientBuilder"></param> | |||
/// <returns></returns> | |||
public static IJT808ClientBuilder AddInprocJT808Traffic(this IJT808ClientBuilder jT808ClientBuilder) | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.AddSingleton<JT808TrafficService>(); | |||
jT808ClientBuilder.JT808Builder.Services.AddHostedService<JT808TrafficServiceHostedService>(); | |||
return jT808ClientBuilder; | |||
} | |||
/// <summary> | |||
/// 共享消息流量统计服务(消费者单实例) | |||
/// </summary> | |||
/// <typeparam name="TReplyMessageService"></typeparam> | |||
/// <param name="jT808ClientBuilder"></param> | |||
/// <returns></returns> | |||
public static IJT808ClientBuilder AddShareJT808Traffic(this IJT808ClientBuilder jT808ClientBuilder) | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.AddSingleton<JT808TrafficService>(); | |||
return jT808ClientBuilder; | |||
} | |||
} | |||
} |
@@ -0,0 +1,38 @@ | |||
using System.Threading.Tasks; | |||
using Microsoft.Extensions.Hosting; | |||
using System.Threading; | |||
using JT808.Protocol.Extensions; | |||
using JT808.Gateway.PubSub; | |||
namespace JT808.Gateway.BusinessServices.Traffic | |||
{ | |||
public class JT808TrafficServiceHostedService : IHostedService | |||
{ | |||
private readonly IJT808MsgConsumer jT808MsgConsumer; | |||
private readonly JT808TrafficService jT808DotNettyTrafficService; | |||
public JT808TrafficServiceHostedService( | |||
JT808TrafficService jT808DotNettyTrafficService, | |||
IJT808MsgConsumer jT808MsgConsumer) | |||
{ | |||
this.jT808MsgConsumer = jT808MsgConsumer; | |||
this.jT808DotNettyTrafficService = jT808DotNettyTrafficService; | |||
} | |||
public Task StartAsync(CancellationToken cancellationToken) | |||
{ | |||
jT808MsgConsumer.Subscribe(); | |||
jT808MsgConsumer.OnMessage((item)=> { | |||
string str = item.Data.ToHexString(); | |||
jT808DotNettyTrafficService.Processor(item.TerminalNo, item.Data.Length); | |||
}); | |||
return Task.CompletedTask; | |||
} | |||
public Task StopAsync(CancellationToken cancellationToken) | |||
{ | |||
jT808MsgConsumer.Unsubscribe(); | |||
return Task.CompletedTask; | |||
} | |||
} | |||
} |
@@ -0,0 +1,9 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.BusinessServices.Traffic | |||
{ | |||
class TrafficRedisClient: RedisHelper<TrafficRedisClient> | |||
{ } | |||
} |
@@ -0,0 +1,13 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.BusinessServices.Transmit.Configs | |||
{ | |||
public class DataTransferOptions | |||
{ | |||
public string Host { get; set; } | |||
public List<string> TerminalNos { get; set; } | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.BusinessServices.Transmit.Configs | |||
{ | |||
public class RemoteServerOptions | |||
{ | |||
public List<DataTransferOptions> DataTransfer { get; set; } | |||
} | |||
} |
@@ -0,0 +1,76 @@ | |||
using DotNetty.Transport.Bootstrapping; | |||
using DotNetty.Transport.Channels; | |||
using DotNetty.Transport.Channels.Sockets; | |||
using Polly; | |||
using System; | |||
using System.Linq; | |||
using System.Collections.Generic; | |||
using System.Net; | |||
using System.Text; | |||
using Microsoft.Extensions.Logging; | |||
namespace JT808.Gateway.BusinessServices.Transmit.Handlers | |||
{ | |||
public class ClientConnectionHandler : ChannelHandlerAdapter | |||
{ | |||
private readonly Bootstrap bootstrap; | |||
public Dictionary<string, IChannel> channeldic; | |||
private readonly ILogger<ClientConnectionHandler> logger; | |||
public ClientConnectionHandler(Bootstrap bootstrap, | |||
Dictionary<string, IChannel> channeldic, | |||
ILoggerFactory loggerFactory) | |||
{ | |||
this.bootstrap = bootstrap; | |||
this.channeldic = channeldic; | |||
logger = loggerFactory.CreateLogger<ClientConnectionHandler>(); | |||
} | |||
public override void ChannelInactive(IChannelHandlerContext context) | |||
{ | |||
Policy.HandleResult<bool>(context.Channel.Open) | |||
.WaitAndRetryForeverAsync(retryAttempt => | |||
{ | |||
return retryAttempt > 20 ? TimeSpan.FromSeconds(Math.Pow(2, 50)) : TimeSpan.FromSeconds(Math.Pow(2, retryAttempt));//超过重试20次,之后重试都是接近12个小时重试一次 | |||
}, | |||
(exception, timespan, ctx) => | |||
{ | |||
logger.LogError($"服务端断开{context.Channel.RemoteAddress},重试结果{exception.Result},重试次数{timespan},下次重试间隔(s){ctx.TotalSeconds}"); | |||
}) | |||
.ExecuteAsync(async () => | |||
{ | |||
try | |||
{ | |||
var oldChannel = channeldic.FirstOrDefault(m => m.Value == context.Channel); | |||
if (default(KeyValuePair<string, IChannel>).Equals(oldChannel)) | |||
{ | |||
if(logger.IsEnabled( LogLevel.Debug)) | |||
logger.LogDebug($"服务器已经删除了{oldChannel.Key}远程服务器配置"); | |||
return true; | |||
} | |||
var channel = await bootstrap.ConnectAsync(context.Channel.RemoteAddress); | |||
channeldic.Remove(oldChannel.Key); | |||
channeldic.Add(oldChannel.Key, channel); | |||
return channel.Open; | |||
} | |||
catch (Exception ex) | |||
{ | |||
logger.LogError($"服务端断开后{context.Channel.RemoteAddress},重连异常:{ex}"); | |||
return false; | |||
} | |||
}); | |||
} | |||
public override void ChannelRead(IChannelHandlerContext context, object message) | |||
{ | |||
if (logger.IsEnabled(LogLevel.Debug)) | |||
{ | |||
logger.LogError($"服务端返回消息{message}"); | |||
} | |||
} | |||
public override void ExceptionCaught(IChannelHandlerContext context, Exception exception) | |||
{ | |||
logger.LogError($"服务端Exception: {exception}"); | |||
context.CloseAsync(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,39 @@ | |||
using Microsoft.Extensions.DependencyInjection; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using JT808.Protocol; | |||
using Microsoft.Extensions.Configuration; | |||
using JT808.Gateway.BusinessServices.Transmit.Configs; | |||
namespace JT808.Gateway.BusinessServices.Transmit | |||
{ | |||
public static class JT808DotNettyTransmitExtensions | |||
{ | |||
/// <summary> | |||
/// 独享转发服务(不同的消费者实例) | |||
/// </summary> | |||
/// <param name="jT808ClientBuilder"></param> | |||
/// <param name="configuration"></param> | |||
/// <returns></returns> | |||
public static IJT808ClientBuilder AddInprocJT808Transmit(this IJT808ClientBuilder jT808ClientBuilder,IConfiguration configuration) | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.Configure<RemoteServerOptions>(configuration.GetSection("RemoteServerOptions")); | |||
jT808ClientBuilder.JT808Builder.Services.AddSingleton<JT808DotNettyTransmitService>(); | |||
jT808ClientBuilder.JT808Builder.Services.AddHostedService<JT808DotNettyTransmitHostedService>(); | |||
return jT808ClientBuilder; | |||
} | |||
/// <summary> | |||
/// 共享转发服务(消费者单实例) | |||
/// </summary> | |||
/// <param name="jT808ClientBuilder"></param> | |||
/// <param name="configuration"></param> | |||
/// <returns></returns> | |||
public static IJT808ClientBuilder AddShareJT808Transmit(this IJT808ClientBuilder jT808ClientBuilder, IConfiguration configuration) | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.Configure<RemoteServerOptions>(configuration.GetSection("RemoteServerOptions")); | |||
jT808ClientBuilder.JT808Builder.Services.AddSingleton<JT808DotNettyTransmitService>(); | |||
return jT808ClientBuilder; | |||
} | |||
} | |||
} |
@@ -0,0 +1,33 @@ | |||
using System.Threading.Tasks; | |||
using Microsoft.Extensions.Hosting; | |||
using System.Threading; | |||
using JT808.Gateway.PubSub; | |||
namespace JT808.Gateway.BusinessServices.Transmit | |||
{ | |||
public class JT808DotNettyTransmitHostedService:IHostedService | |||
{ | |||
private readonly JT808DotNettyTransmitService jT808DotNettyTransmitService; | |||
private readonly IJT808MsgConsumer jT808MsgConsumer; | |||
public JT808DotNettyTransmitHostedService( | |||
IJT808MsgConsumer jT808MsgConsumer, | |||
JT808DotNettyTransmitService jT808DotNettyTransmitService) | |||
{ | |||
this.jT808DotNettyTransmitService = jT808DotNettyTransmitService; | |||
this.jT808MsgConsumer = jT808MsgConsumer; | |||
} | |||
public Task StartAsync(CancellationToken cancellationToken) | |||
{ | |||
jT808MsgConsumer.Subscribe(); | |||
jT808MsgConsumer.OnMessage(jT808DotNettyTransmitService.Send); | |||
return Task.CompletedTask; | |||
} | |||
public Task StopAsync(CancellationToken cancellationToken) | |||
{ | |||
jT808MsgConsumer.Unsubscribe(); | |||
return Task.CompletedTask; | |||
} | |||
} | |||
} |
@@ -0,0 +1,236 @@ | |||
using DotNetty.Buffers; | |||
using DotNetty.Transport.Bootstrapping; | |||
using DotNetty.Transport.Channels; | |||
using DotNetty.Transport.Channels.Sockets; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Net; | |||
using System.Threading.Tasks; | |||
using Microsoft.Extensions.Logging; | |||
using Microsoft.Extensions.Options; | |||
using System.Linq; | |||
using JT808.Gateway.BusinessServices.Transmit.Configs; | |||
using JT808.Gateway.BusinessServices.Transmit.Handlers; | |||
namespace JT808.Gateway.BusinessServices.Transmit | |||
{ | |||
public class JT808DotNettyTransmitService | |||
{ | |||
private readonly ILogger logger; | |||
private readonly ILoggerFactory loggerFactory; | |||
private IOptionsMonitor<RemoteServerOptions> optionsMonitor; | |||
public Dictionary<string, IChannel> channeldic = new Dictionary<string, IChannel>(); | |||
public JT808DotNettyTransmitService(ILoggerFactory loggerFactory, | |||
IOptionsMonitor<RemoteServerOptions> optionsMonitor) | |||
{ | |||
this.loggerFactory = loggerFactory; | |||
logger = loggerFactory.CreateLogger("JT808DotNettyTransmitService"); | |||
this.optionsMonitor = optionsMonitor; | |||
InitialDispatcherClient(); | |||
} | |||
public void Send((string TerminalNo, byte[] Data) parameter) | |||
{ | |||
if (optionsMonitor.CurrentValue.DataTransfer != null) | |||
{ | |||
foreach (var item in optionsMonitor.CurrentValue.DataTransfer) | |||
{ | |||
if (channeldic.TryGetValue($"all_{item.Host}", out var allClientChannel)) | |||
{ | |||
try | |||
{ | |||
if (allClientChannel.Open) | |||
{ | |||
if (logger.IsEnabled(LogLevel.Debug)) | |||
{ | |||
logger.LogDebug($"转发所有数据到该网关{item.Host}"); | |||
} | |||
allClientChannel.WriteAndFlushAsync(Unpooled.WrappedBuffer(parameter.Data)); | |||
} | |||
else | |||
{ | |||
logger.LogError($"{item.Host}链接已关闭"); | |||
} | |||
} | |||
catch (Exception ex) | |||
{ | |||
logger.LogError($"{item.Host}发送数据出现异常:{ex}"); | |||
} | |||
} | |||
else | |||
{ | |||
if (item.TerminalNos.Contains(parameter.TerminalNo) && channeldic.TryGetValue($"{parameter.TerminalNo}_{item.Host}", out var clientChannel)) | |||
{ | |||
try | |||
{ | |||
if (clientChannel.Open) | |||
{ | |||
if (logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug)) | |||
logger.LogDebug($"转发{parameter.TerminalNo}到该网关{item.Host}"); | |||
clientChannel.WriteAndFlushAsync(Unpooled.WrappedBuffer(parameter.Data)); | |||
} | |||
else | |||
{ | |||
logger.LogError($"{item.Host},{parameter.TerminalNo}链接已关闭"); | |||
} | |||
} | |||
catch (Exception ex) | |||
{ | |||
logger.LogError($"{item.Host},{parameter.TerminalNo}发送数据出现异常:{ex}"); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
public void InitialDispatcherClient() | |||
{ | |||
Task.Run(async () => | |||
{ | |||
var group = new MultithreadEventLoopGroup(); | |||
var bootstrap = new Bootstrap(); | |||
bootstrap.Group(group) | |||
.Channel<TcpSocketChannel>() | |||
.Option(ChannelOption.TcpNodelay, true) | |||
.Handler(new ActionChannelInitializer<ISocketChannel>(channel => | |||
{ | |||
IChannelPipeline pipeline = channel.Pipeline; | |||
pipeline.AddLast(new ClientConnectionHandler(bootstrap, channeldic, loggerFactory)); | |||
})); | |||
optionsMonitor.OnChange(options => | |||
{ | |||
List<string> lastRemoteServers = new List<string>(); | |||
if (options.DataTransfer != null) | |||
{ | |||
if (options.DataTransfer.Any()) | |||
{ | |||
foreach (var item in options.DataTransfer) | |||
{ | |||
if (item.TerminalNos != null) | |||
{ | |||
if (item.TerminalNos.Any()) | |||
{ | |||
foreach (var terminal in item.TerminalNos) | |||
{ | |||
lastRemoteServers.Add($"{terminal}_{item.Host}"); | |||
} | |||
} | |||
else | |||
{ | |||
lastRemoteServers.Add($"all_{item.Host}"); | |||
} | |||
} | |||
else | |||
{ | |||
lastRemoteServers.Add($"all_{item.Host}"); | |||
} | |||
} | |||
} | |||
} | |||
DelRemoteServsers(lastRemoteServers); | |||
AddRemoteServsers(bootstrap, lastRemoteServers); | |||
}); | |||
await InitRemoteServsers(bootstrap); | |||
}); | |||
} | |||
/// <summary> | |||
/// 初始化远程服务器 | |||
/// </summary> | |||
/// <param name="bootstrap"></param> | |||
/// <param name="remoteServers"></param> | |||
/// <returns></returns> | |||
private async Task InitRemoteServsers(Bootstrap bootstrap) | |||
{ | |||
List<string> remoteServers = new List<string>(); | |||
if (optionsMonitor.CurrentValue.DataTransfer != null) | |||
{ | |||
if (optionsMonitor.CurrentValue.DataTransfer.Any()) | |||
{ | |||
foreach (var item in optionsMonitor.CurrentValue.DataTransfer) | |||
{ | |||
if (item.TerminalNos != null) | |||
{ | |||
if (item.TerminalNos.Any()) | |||
{ | |||
foreach (var terminal in item.TerminalNos) | |||
{ | |||
remoteServers.Add($"{terminal}_{item.Host}"); | |||
} | |||
} | |||
else | |||
{ | |||
remoteServers.Add($"all_{item.Host}"); | |||
} | |||
} | |||
else | |||
{ | |||
remoteServers.Add($"all_{item.Host}"); | |||
} | |||
} | |||
} | |||
} | |||
foreach (var item in remoteServers) | |||
{ | |||
try | |||
{ | |||
string ip_port = item.Split('_')[1]; | |||
IChannel clientChannel = await bootstrap.ConnectAsync(new IPEndPoint(IPAddress.Parse(ip_port.Split(':')[0]), int.Parse(ip_port.Split(':')[1]))); | |||
channeldic.Add(item, clientChannel); | |||
if (clientChannel.Open) | |||
{ | |||
if (logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug)) | |||
{ | |||
logger.LogDebug($"该终端{item.Replace("_", "已连接上该服务器")}"); | |||
} | |||
} | |||
} | |||
catch (Exception ex) | |||
{ | |||
logger.LogError($"初始化配置链接远程服务端{item},链接异常:{ex}"); | |||
} | |||
} | |||
await Task.CompletedTask; | |||
} | |||
/// <summary> | |||
/// 动态删除远程服务器 | |||
/// </summary> | |||
/// <param name="lastRemoteServers"></param> | |||
private void DelRemoteServsers(List<string> lastRemoteServers) | |||
{ | |||
var delChannels = channeldic.Keys.Except(lastRemoteServers).ToList(); | |||
foreach (var item in delChannels) | |||
{ | |||
channeldic[item].CloseAsync(); | |||
channeldic.Remove(item); | |||
} | |||
} | |||
/// <summary> | |||
/// 动态添加远程服务器 | |||
/// </summary> | |||
/// <param name="bootstrap"></param> | |||
/// <param name="lastRemoteServers"></param> | |||
private void AddRemoteServsers(Bootstrap bootstrap, List<string> lastRemoteServers) | |||
{ | |||
var addChannels = lastRemoteServers.Except(channeldic.Keys).ToList(); | |||
foreach (var item in addChannels) | |||
{ | |||
try | |||
{ | |||
var ip_port = item.Split('_')[1]; | |||
IChannel clientChannel = bootstrap.ConnectAsync(new IPEndPoint(IPAddress.Parse(ip_port.Split(':')[0]), int.Parse(ip_port.Split(':')[1]))).Result; | |||
channeldic.Add(item, clientChannel); | |||
if (clientChannel.Open) { | |||
if (logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug)) | |||
{ | |||
logger.LogDebug($"该终端{item.Replace("_", "已连接上该服务器")}"); | |||
} | |||
} | |||
} | |||
catch (Exception ex) | |||
{ | |||
logger.LogError($"变更配置后链接远程服务端{item},重连异常:{ex}"); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -1,31 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Net; | |||
using System.Text; | |||
namespace JT808.Gateway.Configurations | |||
{ | |||
public class JT808ClientConfiguration | |||
{ | |||
public string Host { get; set; } | |||
public int Port { get; set; } | |||
private EndPoint endPoint; | |||
public EndPoint EndPoint | |||
{ | |||
get | |||
{ | |||
if (endPoint == null) | |||
{ | |||
if (IPAddress.TryParse(Host, out IPAddress ip)) | |||
{ | |||
endPoint = new IPEndPoint(ip, Port); | |||
} | |||
} | |||
return endPoint; | |||
} | |||
} | |||
} | |||
} |
@@ -1,29 +0,0 @@ | |||
using Newtonsoft.Json; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.Converters | |||
{ | |||
class ByteArrayHexConverter : JsonConverter | |||
{ | |||
public override bool CanConvert(Type objectType) => objectType == typeof(byte[]); | |||
public override bool CanRead => false; | |||
public override bool CanWrite => true; | |||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) => throw new NotImplementedException(); | |||
private readonly string _separator; | |||
public ByteArrayHexConverter(string separator = " ") => _separator = separator; | |||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | |||
{ | |||
var hexString = string.Join(_separator, ((byte[])value).Select(p => p.ToString("X2"))); | |||
writer.WriteValue(hexString); | |||
} | |||
} | |||
} |
@@ -1,26 +0,0 @@ | |||
using Newtonsoft.Json; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Net; | |||
using System.Text; | |||
namespace JT808.Gateway.Converters | |||
{ | |||
public class JsonIPAddressConverter : JsonConverter | |||
{ | |||
public override bool CanConvert(Type objectType) | |||
{ | |||
return (objectType == typeof(IPAddress)); | |||
} | |||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | |||
{ | |||
writer.WriteValue(value.ToString()); | |||
} | |||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | |||
{ | |||
return IPAddress.Parse((string)reader.Value); | |||
} | |||
} | |||
} |
@@ -1,32 +0,0 @@ | |||
using Newtonsoft.Json; | |||
using Newtonsoft.Json.Linq; | |||
using System; | |||
using System.Net; | |||
namespace JT808.Gateway.Converters | |||
{ | |||
public class JsonIPEndPointConverter: JsonConverter | |||
{ | |||
public override bool CanConvert(Type objectType) | |||
{ | |||
return (objectType == typeof(IPEndPoint)); | |||
} | |||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | |||
{ | |||
IPEndPoint ep = (IPEndPoint)value; | |||
JObject jo = new JObject(); | |||
jo.Add("Host", JToken.FromObject(ep.Address, serializer)); | |||
jo.Add("Port", ep.Port); | |||
jo.WriteTo(writer); | |||
} | |||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | |||
{ | |||
JObject jo = JObject.Load(reader); | |||
IPAddress address = jo["Host"].ToObject<IPAddress>(serializer); | |||
int port = (int)jo["Port"]; | |||
return new IPEndPoint(address, port); | |||
} | |||
} | |||
} |
@@ -1,12 +0,0 @@ | |||
namespace JT808.Gateway.Dtos | |||
{ | |||
/// <summary> | |||
/// 包计数器服务 | |||
/// </summary> | |||
public class JT808AtomicCounterDto | |||
{ | |||
public long MsgSuccessCount { get; set; } | |||
public long MsgFailCount { get; set; } | |||
} | |||
} |
@@ -1,15 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Gateway.Dtos | |||
{ | |||
public class JT808DefaultResultDto: JT808ResultDto<string> | |||
{ | |||
public JT808DefaultResultDto() | |||
{ | |||
Data = "Hello,JT808 WebAPI"; | |||
Code = JT808ResultCode.Ok; | |||
} | |||
} | |||
} |
@@ -1,37 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Net; | |||
using System.Runtime.Serialization; | |||
using System.Text; | |||
namespace JT808.Gateway.Dtos | |||
{ | |||
public class JT808IPAddressDto | |||
{ | |||
public string Host { get; set; } | |||
public int Port { get; set; } | |||
public EndPoint endPoint; | |||
public EndPoint EndPoint | |||
{ | |||
get | |||
{ | |||
if (endPoint == null) | |||
{ | |||
if (IPAddress.TryParse(Host, out IPAddress ip)) | |||
{ | |||
endPoint = new IPEndPoint(ip, Port); | |||
} | |||
else | |||
{ | |||
endPoint = new DnsEndPoint(Host, Port); | |||
} | |||
} | |||
return endPoint; | |||
} | |||
set { } | |||
} | |||
} | |||
} |
@@ -1,11 +0,0 @@ | |||
namespace JT808.Gateway.Dtos | |||
{ | |||
/// <summary> | |||
/// 统一下发请求参数 | |||
/// </summary> | |||
public class JT808UnificationSendRequestDto | |||
{ | |||
public string TerminalPhoneNo { get; set; } | |||
public byte[] Data { get; set; } | |||
} | |||
} |
@@ -1,91 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using JT808.Gateway.Dtos; | |||
using JT808.Gateway.Metadata; | |||
using Newtonsoft.Json; | |||
namespace JT808.Gateway.Handlers | |||
{ | |||
/// <summary> | |||
/// 基于webapi http模式抽象消息处理业务 | |||
/// 自定义消息处理业务 | |||
/// 注意: | |||
/// 1.ConfigureServices: | |||
/// services.Replace(new ServiceDescriptor(typeof(JT808MsgIdHttpHandlerBase),typeof(JT808MsgIdCustomHttpHandlerImpl),ServiceLifetime.Singleton)); | |||
/// 2.解析具体的消息体,具体消息调用具体的JT808Serializer.Deserialize<T> | |||
/// </summary> | |||
public abstract class JT808MsgIdHttpHandlerBase | |||
{ | |||
/// <summary> | |||
/// 初始化消息处理业务 | |||
/// </summary> | |||
protected JT808MsgIdHttpHandlerBase() | |||
{ | |||
HandlerDict = new Dictionary<string, Func<JT808HttpRequest, JT808HttpResponse>>(); | |||
} | |||
protected void CreateRoute(string url, Func<JT808HttpRequest, JT808HttpResponse> func) | |||
{ | |||
if (!HandlerDict.ContainsKey(url)) | |||
{ | |||
HandlerDict.Add(url, func); | |||
} | |||
else | |||
{ | |||
// 替换 | |||
HandlerDict[url] = func; | |||
} | |||
} | |||
public Dictionary<string, Func<JT808HttpRequest, JT808HttpResponse>> HandlerDict { get; } | |||
protected JT808HttpResponse CreateJT808HttpResponse(dynamic dynamicObject) | |||
{ | |||
byte[] data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(dynamicObject)); | |||
return new JT808HttpResponse() | |||
{ | |||
Data = data | |||
}; | |||
} | |||
public JT808HttpResponse DefaultHttpResponse() | |||
{ | |||
byte[] json = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new JT808DefaultResultDto())); | |||
return new JT808HttpResponse(json); | |||
} | |||
public JT808HttpResponse EmptyHttpResponse() | |||
{ | |||
byte[] json = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new JT808ResultDto<string>() | |||
{ | |||
Code = JT808ResultCode.Empty, | |||
Message = "内容为空", | |||
Data = "Content Empty" | |||
})); | |||
return new JT808HttpResponse(json); | |||
} | |||
public JT808HttpResponse NotFoundHttpResponse() | |||
{ | |||
byte[] json = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new JT808ResultDto<string>() | |||
{ | |||
Code = JT808ResultCode.NotFound, | |||
Message = "没有该服务", | |||
Data = "没有该服务" | |||
})); | |||
return new JT808HttpResponse(json); | |||
} | |||
public JT808HttpResponse ErrorHttpResponse(Exception ex) | |||
{ | |||
byte[] json = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new JT808ResultDto<string>() | |||
{ | |||
Code = JT808ResultCode.Error, | |||
Message = JsonConvert.SerializeObject(ex), | |||
Data = ex.Message | |||
})); | |||
return new JT808HttpResponse(json); | |||
} | |||
} | |||
} |
@@ -1,7 +1,7 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<TargetFramework>netcoreapp3.0</TargetFramework> | |||
<TargetFramework>netstandard2.0</TargetFramework> | |||
<LangVersion>8.0</LangVersion> | |||
<Copyright>Copyright 2018.</Copyright> | |||
<Authors>SmallChi(Koike)</Authors> | |||
@@ -14,12 +14,15 @@ | |||
<SignAssembly>false</SignAssembly> | |||
<PackageLicenseFile>LICENSE</PackageLicenseFile> | |||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | |||
<PackageId>JT808.Gateway</PackageId> | |||
<Product>JT808.Gateway</Product> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<Protobuf Include="Protos\JT808Gateway.proto"/> | |||
<Protobuf Include="Protos\JT808Gateway.proto" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<PackageReference Include="CSRedisCore" Version="3.1.10" /> | |||
<PackageReference Include="Google.Protobuf" Version="3.10.0" /> | |||
<PackageReference Include="Grpc.Core" Version="2.24.0" /> | |||
<PackageReference Include="Grpc.Tools" Version="2.24.0"> | |||
@@ -32,8 +35,8 @@ | |||
<PackageReference Include="DotNetty.Codecs" Version="0.6.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.0.0" /> | |||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.0.0" /> | |||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" /> | |||
<PackageReference Include="Microsoft.Extensions.Options" Version="3.0.0" /> | |||
<PackageReference Include="Polly" Version="7.1.1" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Include="..\..\LICENSE" Pack="true" PackagePath="" /> | |||
@@ -1,6 +1,5 @@ | |||
using JT808.Gateway; | |||
using JT808.Gateway.Configurations; | |||
using JT808.Gateway.Converters; | |||
using JT808.Gateway.Impls; | |||
using JT808.Gateway.Interfaces; | |||
using JT808.Gateway.PubSub; | |||
@@ -11,47 +10,17 @@ using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.DependencyInjection.Extensions; | |||
using Microsoft.Extensions.Options; | |||
using Newtonsoft.Json; | |||
using System; | |||
using System.Runtime.CompilerServices; | |||
//[assembly: InternalsVisibleTo("JT808.DotNetty.Core.Test")] | |||
[assembly: InternalsVisibleTo("JT808.Gateway.Test")] | |||
namespace JT808.Gateway | |||
{ | |||
public static class JT808GatewayExtensions | |||
{ | |||
static JT808GatewayExtensions() | |||
public static IJT808GatewayBuilder AddJT808Gateway(this IJT808Builder jt808Builder, IConfiguration configuration) | |||
{ | |||
JsonConvert.DefaultSettings = new Func<JsonSerializerSettings>(() => | |||
{ | |||
Newtonsoft.Json.JsonSerializerSettings settings = new Newtonsoft.Json.JsonSerializerSettings(); | |||
//日期类型默认格式化处理 | |||
settings.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat; | |||
settings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; | |||
//空值处理 | |||
settings.NullValueHandling = NullValueHandling.Ignore; | |||
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; | |||
settings.Converters.Add(new JsonIPAddressConverter()); | |||
settings.Converters.Add(new JsonIPEndPointConverter()); | |||
settings.Converters.Add(new ByteArrayHexConverter()); | |||
return settings; | |||
}); | |||
} | |||
public static IJT808GatewayBuilder AddJT808Gateway(this IJT808Builder jt808Builder, IConfiguration configuration, Newtonsoft.Json.JsonSerializerSettings settings=null) | |||
{ | |||
if (settings != null) | |||
{ | |||
JsonConvert.DefaultSettings = new Func<JsonSerializerSettings>(() => | |||
{ | |||
settings.Converters.Add(new JsonIPAddressConverter()); | |||
settings.Converters.Add(new JsonIPEndPointConverter()); | |||
settings.Converters.Add(new ByteArrayHexConverter()); | |||
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; | |||
return settings; | |||
}); | |||
} | |||
IJT808GatewayBuilder nettyBuilder = new JT808GatewayBuilderDefault(jt808Builder); | |||
nettyBuilder.JT808Builder.Services.Configure<JT808Configuration>(configuration.GetSection("JT808Configuration")); | |||
nettyBuilder.JT808Builder.Services.TryAddSingleton<JT808AtomicCounterServiceFactory>(); | |||
@@ -66,19 +35,8 @@ namespace JT808.Gateway | |||
return nettyBuilder; | |||
} | |||
public static IJT808GatewayBuilder AddJT808Gateway(this IJT808Builder jt808Builder, Action<JT808Configuration> jt808Options, Newtonsoft.Json.JsonSerializerSettings settings = null) | |||
public static IJT808GatewayBuilder AddJT808Gateway(this IJT808Builder jt808Builder, Action<JT808Configuration> jt808Options) | |||
{ | |||
if (settings != null) | |||
{ | |||
JsonConvert.DefaultSettings = new Func<JsonSerializerSettings>(() => | |||
{ | |||
settings.Converters.Add(new JsonIPAddressConverter()); | |||
settings.Converters.Add(new JsonIPEndPointConverter()); | |||
settings.Converters.Add(new ByteArrayHexConverter()); | |||
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; | |||
return settings; | |||
}); | |||
} | |||
IJT808GatewayBuilder nettyBuilder = new JT808GatewayBuilderDefault(jt808Builder); | |||
nettyBuilder.JT808Builder.Services.Configure(jt808Options); | |||
nettyBuilder.JT808Builder.Services.TryAddSingleton<JT808AtomicCounterServiceFactory>(); | |||
@@ -35,15 +35,18 @@ namespace JT808.Gateway.Services | |||
{ | |||
var result = jT808SessionService.GetTcpAll(); | |||
TcpSessionInfoReply reply = new TcpSessionInfoReply(); | |||
foreach(var item in result.Data) | |||
if (result.Data != null) | |||
{ | |||
reply.TcpSessions.Add(new SessionInfo | |||
foreach (var item in result.Data) | |||
{ | |||
LastActiveTime= item.LastActiveTime.ToString("yyyy-MM-dd HH:mm:ss"), | |||
StartTime= item.StartTime.ToString("yyyy-MM-dd HH:mm:ss"), | |||
RemoteAddressIP= item.RemoteAddressIP, | |||
TerminalPhoneNo=item.TerminalPhoneNo | |||
}); | |||
reply.TcpSessions.Add(new SessionInfo | |||
{ | |||
LastActiveTime = item.LastActiveTime.ToString("yyyy-MM-dd HH:mm:ss"), | |||
StartTime = item.StartTime.ToString("yyyy-MM-dd HH:mm:ss"), | |||
RemoteAddressIP = item.RemoteAddressIP, | |||
TerminalPhoneNo = item.TerminalPhoneNo | |||
}); | |||
} | |||
} | |||
return Task.FromResult(reply); | |||
} | |||
@@ -58,15 +61,18 @@ namespace JT808.Gateway.Services | |||
{ | |||
var result = jT808SessionService.GetUdpAll(); | |||
UdpSessionInfoReply reply = new UdpSessionInfoReply(); | |||
foreach (var item in result.Data) | |||
if (result.Data != null) | |||
{ | |||
reply.UdpSessions.Add(new SessionInfo | |||
foreach (var item in result.Data) | |||
{ | |||
LastActiveTime = item.LastActiveTime.ToString("yyyy-MM-dd HH:mm:ss"), | |||
StartTime = item.StartTime.ToString("yyyy-MM-dd HH:mm:ss"), | |||
RemoteAddressIP = item.RemoteAddressIP, | |||
TerminalPhoneNo = item.TerminalPhoneNo | |||
}); | |||
reply.UdpSessions.Add(new SessionInfo | |||
{ | |||
LastActiveTime = item.LastActiveTime.ToString("yyyy-MM-dd HH:mm:ss"), | |||
StartTime = item.StartTime.ToString("yyyy-MM-dd HH:mm:ss"), | |||
RemoteAddressIP = item.RemoteAddressIP, | |||
TerminalPhoneNo = item.TerminalPhoneNo | |||
}); | |||
} | |||
} | |||
return Task.FromResult(reply); | |||
} | |||
@@ -36,7 +36,7 @@ namespace JT808.Gateway.Services | |||
{ | |||
resultDto.Data = null; | |||
resultDto.Code = JT808ResultCode.Error; | |||
resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex); | |||
resultDto.Message =ex.Message; | |||
} | |||
return resultDto; | |||
} | |||
@@ -59,7 +59,7 @@ namespace JT808.Gateway.Services | |||
{ | |||
resultDto.Data = null; | |||
resultDto.Code = JT808ResultCode.Error; | |||
resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex); | |||
resultDto.Message = ex.Message; | |||
} | |||
return resultDto; | |||
} | |||
@@ -84,13 +84,13 @@ namespace JT808.Gateway.Services | |||
{ | |||
resultDto.Data = false; | |||
resultDto.Code = 500; | |||
resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex); | |||
resultDto.Message = ex.Message; | |||
} | |||
catch (Exception ex) | |||
{ | |||
resultDto.Data = false; | |||
resultDto.Code = JT808ResultCode.Error; | |||
resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex); | |||
resultDto.Message = ex.Message; | |||
} | |||
return resultDto; | |||
} | |||
@@ -37,7 +37,7 @@ namespace JT808.Gateway.Services | |||
{ | |||
resultDto.Data = false; | |||
resultDto.Code = JT808ResultCode.Error; | |||
resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex); | |||
resultDto.Message = ex.Message; | |||
} | |||
return resultDto; | |||
} | |||
@@ -5,7 +5,7 @@ using System.Net.Sockets; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
namespace JT808.DotNetty.Core | |||
namespace JT808.Gateway.Simples | |||
{ | |||
internal class JT808SimpleTcpClient | |||
{ | |||
@@ -5,7 +5,7 @@ using System.Net.Sockets; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
namespace JT808.DotNetty.Core | |||
namespace JT808.Gateway.Simples | |||
{ | |||
internal class JT808SimpleUdpClient | |||
{ | |||