瀏覽代碼

1.修改文档及协议

2.增加pipeline结果
3.移除gateway项目
tags/v2.3.1
SmallChi(Koike) 5 年之前
父節點
當前提交
1a7c6c8794
共有 100 個文件被更改,包括 36 次插入9995 次删除
  1. +1
    -1
      LICENSE
  2. +13
    -4
      README.md
  3. +0
    -120
      README_V1.0.0.md
  4. +22
    -5
      doc/README.md
  5. +0
    -0
      doc/dotnetty/demo1.png
  6. +0
    -0
      doc/dotnetty/demo2.png
  7. +0
    -0
      doc/dotnetty/design_model.png
  8. +0
    -0
      doc/dotnetty/performance_1000.png
  9. +0
    -0
      doc/dotnetty/performance_10000.png
  10. +0
    -0
      doc/dotnetty/performance_2000.png
  11. +0
    -0
      doc/dotnetty/performance_5000.png
  12. 二進制
      doc/pipeline/client_10k.png
  13. 二進制
      doc/pipeline/server_network_10k.png
  14. 二進制
      doc/pipeline/server_proccess_10k.png
  15. +0
    -19
      src/JT808.Gateway.CleintBenchmark/Configs/ClientBenchmarkOptions.cs
  16. +0
    -3106
      src/JT808.Gateway.CleintBenchmark/Configs/NLog.xsd
  17. +0
    -36
      src/JT808.Gateway.CleintBenchmark/Configs/nlog.unix.config
  18. +0
    -35
      src/JT808.Gateway.CleintBenchmark/Configs/nlog.win.config
  19. +0
    -33
      src/JT808.Gateway.CleintBenchmark/JT808.Gateway.CleintBenchmark.csproj
  20. +0
    -51
      src/JT808.Gateway.CleintBenchmark/Program.cs
  21. +0
    -82
      src/JT808.Gateway.CleintBenchmark/Services/CleintBenchmarkHostedService.cs
  22. +0
    -53
      src/JT808.Gateway.CleintBenchmark/Services/CleintBenchmarkReportHostedService.cs
  23. +0
    -15
      src/JT808.Gateway.Kafka/Configs/JT808ConsumerConfig.cs
  24. +0
    -13
      src/JT808.Gateway.Kafka/Configs/JT808MsgConsumerConfig.cs
  25. +0
    -13
      src/JT808.Gateway.Kafka/Configs/JT808MsgProducerConfig.cs
  26. +0
    -13
      src/JT808.Gateway.Kafka/Configs/JT808MsgReplyConsumerConfig.cs
  27. +0
    -13
      src/JT808.Gateway.Kafka/Configs/JT808MsgReplyProducerConfig.cs
  28. +0
    -15
      src/JT808.Gateway.Kafka/Configs/JT808ProducerConfig.cs
  29. +0
    -13
      src/JT808.Gateway.Kafka/Configs/JT808SessionConsumerConfig.cs
  30. +0
    -13
      src/JT808.Gateway.Kafka/Configs/JT808SessionProducerConfig.cs
  31. +0
    -39
      src/JT808.Gateway.Kafka/JT808.Gateway.Kafka.csproj
  32. +0
    -24
      src/JT808.Gateway.Kafka/JT808ClientBuilderDefault.cs
  33. +0
    -66
      src/JT808.Gateway.Kafka/JT808ClientKafkaExtensions.cs
  34. +0
    -82
      src/JT808.Gateway.Kafka/JT808MsgConsumer.cs
  35. +0
    -38
      src/JT808.Gateway.Kafka/JT808MsgProducer.cs
  36. +0
    -82
      src/JT808.Gateway.Kafka/JT808MsgReplyConsumer.cs
  37. +0
    -38
      src/JT808.Gateway.Kafka/JT808MsgReplyProducer.cs
  38. +0
    -48
      src/JT808.Gateway.Kafka/JT808ServerKafkaExtensions.cs
  39. +0
    -82
      src/JT808.Gateway.Kafka/JT808SessionConsumer.cs
  40. +0
    -38
      src/JT808.Gateway.Kafka/JT808SessionProducer.cs
  41. +0
    -18
      src/JT808.Gateway.SimpleClient/JT808.Gateway.SimpleClient.csproj
  42. +0
    -52
      src/JT808.Gateway.SimpleClient/Program.cs
  43. +0
    -68
      src/JT808.Gateway.SimpleClient/Services/GrpcClientService.cs
  44. +0
    -68
      src/JT808.Gateway.SimpleClient/Services/UpService.cs
  45. +0
    -3106
      src/JT808.Gateway.SimpleServer/Configs/NLog.xsd
  46. +0
    -36
      src/JT808.Gateway.SimpleServer/Configs/nlog.Unix.config
  47. +0
    -36
      src/JT808.Gateway.SimpleServer/Configs/nlog.Win32NT.config
  48. 二進制
      src/JT808.Gateway.SimpleServer/Configs/test.cer
  49. +0
    -39
      src/JT808.Gateway.SimpleServer/JT808.Gateway.SimpleServer.csproj
  50. +0
    -71
      src/JT808.Gateway.SimpleServer/Program.cs
  51. +0
    -102
      src/JT808.Gateway.sln
  52. +0
    -14
      src/JT808.Gateway/BusinessServices/MsgIdHandler/IJT808MsgIdHandler.cs
  53. +0
    -18
      src/JT808.Gateway/BusinessServices/MsgIdHandler/JT808MsgIdHandlerExtensions.cs
  54. +0
    -34
      src/JT808.Gateway/BusinessServices/MsgIdHandler/JT808MsgIdHandlerHostedService.cs
  55. +0
    -15
      src/JT808.Gateway/BusinessServices/MsgLogging/IJT808MsgLogging.cs
  56. +0
    -36
      src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgDownLoggingHostedService.cs
  57. +0
    -19
      src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgLoggingExtensions.cs
  58. +0
    -18
      src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgLoggingType.cs
  59. +0
    -36
      src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgUpLoggingHostedService.cs
  60. +0
    -57
      src/JT808.Gateway/BusinessServices/ReplyMessage/JT808ReplyMessageExtensions.cs
  61. +0
    -34
      src/JT808.Gateway/BusinessServices/ReplyMessage/JT808ReplyMessageHostedService.cs
  62. +0
    -165
      src/JT808.Gateway/BusinessServices/ReplyMessage/JT808ReplyMessageService.cs
  63. +0
    -60
      src/JT808.Gateway/BusinessServices/SessionNotice/JT808SessionNoticeExtensions.cs
  64. +0
    -35
      src/JT808.Gateway/BusinessServices/SessionNotice/JT808SessionNoticeHostedService.cs
  65. +0
    -24
      src/JT808.Gateway/BusinessServices/SessionNotice/JT808SessionNoticeService.cs
  66. +0
    -32
      src/JT808.Gateway/BusinessServices/Traffic/JT808TrafficService.cs
  67. +0
    -33
      src/JT808.Gateway/BusinessServices/Traffic/JT808TrafficServiceExtensions.cs
  68. +0
    -38
      src/JT808.Gateway/BusinessServices/Traffic/JT808TrafficServiceHostedService.cs
  69. +0
    -9
      src/JT808.Gateway/BusinessServices/Traffic/TrafficRedisClient.cs
  70. +0
    -13
      src/JT808.Gateway/BusinessServices/Transmit/Configs/DataTransferOptions.cs
  71. +0
    -11
      src/JT808.Gateway/BusinessServices/Transmit/Configs/RemoteServerOptions.cs
  72. +0
    -76
      src/JT808.Gateway/BusinessServices/Transmit/Handlers/ClientConnectionHandler.cs
  73. +0
    -39
      src/JT808.Gateway/BusinessServices/Transmit/JT808DotNettyTransmitExtensions.cs
  74. +0
    -33
      src/JT808.Gateway/BusinessServices/Transmit/JT808DotNettyTransmitHostedService.cs
  75. +0
    -236
      src/JT808.Gateway/BusinessServices/Transmit/JT808DotNettyTransmitService.cs
  76. +0
    -28
      src/JT808.Gateway/Client/DeviceConfig.cs
  77. +0
    -23
      src/JT808.Gateway/Client/JT808ClientDotnettyExtensions.cs
  78. +0
    -16
      src/JT808.Gateway/Client/JT808ClientMsgSNDistributedImpl.cs
  79. +0
    -112
      src/JT808.Gateway/Client/JT808TcpClient.cs
  80. +0
    -103
      src/JT808.Gateway/Client/JT808TcpClientExtensions.cs
  81. +0
    -62
      src/JT808.Gateway/Client/JT808TcpClientFactory.cs
  82. +0
    -20
      src/JT808.Gateway/Codecs/JT808ClientTcpDecoder.cs
  83. +0
    -52
      src/JT808.Gateway/Codecs/JT808ClientTcpEncoder.cs
  84. +0
    -32
      src/JT808.Gateway/Codecs/JT808TcpDecoder.cs
  85. +0
    -52
      src/JT808.Gateway/Codecs/JT808TcpEncoder.cs
  86. +0
    -33
      src/JT808.Gateway/Codecs/JT808UdpDecoder.cs
  87. +0
    -41
      src/JT808.Gateway/Configurations/JT808Configuration.cs
  88. +0
    -29
      src/JT808.Gateway/Dtos/JT808ResultDto.cs
  89. +0
    -24
      src/JT808.Gateway/Dtos/JT808TcpSessionInfoDto.cs
  90. +0
    -24
      src/JT808.Gateway/Dtos/JT808UdpSessionInfoDto.cs
  91. +0
    -15
      src/JT808.Gateway/Enums/JT808TransportProtocolType.cs
  92. +0
    -96
      src/JT808.Gateway/Handlers/JT808TcpClientConnectionHandler.cs
  93. +0
    -31
      src/JT808.Gateway/Handlers/JT808TcpClientHandler.cs
  94. +0
    -104
      src/JT808.Gateway/Handlers/JT808TcpConnectionHandler.cs
  95. +0
    -77
      src/JT808.Gateway/Handlers/JT808TcpServerHandler.cs
  96. +0
    -79
      src/JT808.Gateway/Handlers/JT808UdpServerHandler.cs
  97. +0
    -14
      src/JT808.Gateway/IJT808ClientBuilder.cs
  98. +0
    -14
      src/JT808.Gateway/IJT808GatewayBuilder.cs
  99. +0
    -18
      src/JT808.Gateway/Impls/JT808DatagramPacketImpl.cs
  100. +0
    -25
      src/JT808.Gateway/Impls/JT808GatewayBuilderDefault.cs

+ 1
- 1
LICENSE 查看文件

@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2018 SmallChi(Koike)
Copyright (c) 2019 SmallChi(Koike)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal


+ 13
- 4
README.md 查看文件

@@ -1,6 +1,8 @@
# JT808DotNetty
# JT808Gateway

基于DotNetty封装的JT808DotNetty支持TCP/UDP通用消息业务处理
基于DotNetty封装的JT808DotNetty支持TCP/UDP通用消息业务处理

基于Pipeline封装的JT808DotNetty支持TCP/UDP通用消息业务处理

[了解JT808协议进这边](https://github.com/SmallChi/JT808)

@@ -14,7 +16,7 @@

[![MIT Licence](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/SmallChi/JT808DotNetty/blob/master/LICENSE)[![Build Status](https://travis-ci.org/SmallChi/JT808DotNetty.svg?branch=master)](https://travis-ci.org/SmallChi/JT808DotNetty)

## 新网关的优势
## 新网关的优势

1. 跨平台
2. 借助 .NET Core模块化的思想
@@ -55,7 +57,7 @@
|Traffic|流量统计服务 |由于运营商sim卡查询流量滞后,通过流量统计服务可以实时准确的统计设备流量,可以最优配置设备的流量大小,以节省成本
|Transmit| 原包转发服务|该服务可以将设备上报原始数据转发到第三方,支持全部转发,指定终端号转发|

## NuGet安装
## 基于DotNetty的NuGet安装

| Package Name | Version | Downloads |
| --------------------- | -------------------------------------------------- | --------------------------------------------------- |
@@ -75,6 +77,13 @@
| Install-Package JT808.DotNetty.Kafka | ![JT808](https://img.shields.io/nuget/v/JT808.DotNetty.Kafka.svg) | ![JT808](https://img.shields.io/nuget/dt/JT808.DotNetty.Kafka.svg) |
| Install-Package JT808.DotNetty.RabbitMQ | ![JT808](https://img.shields.io/nuget/v/JT808.DotNetty.RabbitMQ.svg) | ![JT808](https://img.shields.io/nuget/dt/JT808.DotNetty.RabbitMQ.svg) |

## 基于Pipeline的NuGet安装

| Package Name | Version | Downloads |
| --------------------- | -------------------------------------------------- | --------------------------------------------------- |
| Install-Package JT808.Gateway | ![JT808.Gateway](https://img.shields.io/nuget/v/JT808.Gateway.svg) | ![JT808.Gateway](https://img.shields.io/nuget/dt/JT808.Gateway.svg) |
| Install-Package JT808.Gateway.Kafka| ![JT808.Gateway.Kafka](https://img.shields.io/nuget/v/JT808.Gateway.Kafka.svg) | ![JT808.Gateway.Kafka](https://img.shields.io/nuget/dt/JT808.Gateway.Kafka.svg) |

## 举个栗子1

``` demo1


+ 0
- 120
README_V1.0.0.md 查看文件

@@ -1,120 +0,0 @@
# JT808DotNetty

基于DotNetty封装的JT808DotNetty支持TCP/UDP通用消息业务处理

[了解JT808协议进这边](https://github.com/SmallChi/JT808)

[了解JT809协议进这边](https://github.com/SmallChi/JT809)

[了解JT1078协议进这边](https://github.com/SmallChi/JT1078)

[了解JTNE协议进这边](https://github.com/SmallChi/JTNewEnergy)

[玩一玩压力测试](https://github.com/SmallChi/JT808DotNetty/blob/master/doc/README.md)

[V2.2.1老版本](https://github.com/SmallChi/JT808DotNetty/blob/master/doc/README_V2.2.1.md)

[![MIT Licence](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/SmallChi/JT808DotNetty/blob/master/LICENSE)

## 新网关的优势

1. 跨平台
2. 借助 .NET Core模块化的思想
3. 单机同时一万辆车在线不是梦(真有一万辆车那都很吃香了<( ̄3 ̄)> <( ̄3 ̄)> <( ̄3 ̄)> )
4. 简单易上手

## 设计模型

![design_model](https://github.com/SmallChi/JT808DotNetty/blob/master/doc/img/design_model.png)

## 基于Grpc的消息业务处理程序(JT808.Gateway.GrpcService)

``` 1
services.AddGrpcClient<JT808Gateway.JT808GatewayClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
});
```

## 集成接口功能(JT808.Gateway.PubSub)

|接口名称|接口说明|使用场景|
|:------:|:------|:------|
| IJT808SessionProducer| 会话通知(在线/离线)数据生产接口| 有些超长待机的设备,不会实时保持连接,那么通过平台下发的命令是无法到达的,这时候就需要设备一上线,就即时通知服务去处理,然后在即时的下发消息到设备。|
| IJT808SessionConsumer| 会话通知(在线/离线)数据消费接口| -|
| IJT808MsgProducer| 数据生产接口| 网关将接收到的数据发送到队列|
| IJT808MsgConsumer| 数据消费接口| 将数据进行对应的消息业务处理(例:设备流量统计、第三方平台数据转发、消息日志等) |
| IJT808MsgReplyProducer| 应答数据生产接口|将生产的数据解析为对应的消息Id应答发送到队列 |
| IJT808MsgReplyConsumer| 应答数据消费接口| 将接收到的应答数据下发给设备|

> 使用物联网卡通过udp下发指令时,存储的那个socket地址端口,有效期非常短,不速度快点下发,那个socket地址端口就可能映射到别的对应卡去了,所以此处采用跟随设备消息下发指令。

## 基于网关的相关服务(JT808.Gateway.BusinessServices)

|服务名称|服务说明|使用场景|
|:------:|:------|:------|
|MsgIdHandler| 消息处理服务|从队列中消费设备上报数据,再结合自身的业务场景,将数据进行处理并入库 |
|MsgLogging | 消息日志服务|从队列中消费设备上报和平台应答数据,再将数据存入influxdb等数据库中,便于技术和技术支持排查设备与平台交互的原始数据|
|ReplyMessage| 消息响应服务| 用于响应设备上报消息,以及下发指令信息到设备|
|SessionNotice| 会话管理服务| 通知设备上线下线,对于udp设备来说,可以在设备上线时,将指令跟随消息下发到设备|
|Traffic|流量统计服务 |由于运营商sim卡查询流量滞后,通过流量统计服务可以实时准确的统计设备流量,可以最优配置设备的流量大小,以节省成本
|Transmit| 原包转发服务|该服务可以将设备上报原始数据转发到第三方,支持全部转发,指定终端号转发|

## NuGet安装

| Package Name | Version | Downloads |
| --------------------- | -------------------------------------------------- | --------------------------------------------------- |
| Install-Package JT808.Gateway | ![JT808.Gateway](https://img.shields.io/nuget/v/JT808.Gateway.svg) | ![JT808.Gateway](https://img.shields.io/nuget/dt/JT808.Gateway.svg) |
| Install-Package JT808.Gateway.Kafka| ![JT808.Gateway.Kafka](https://img.shields.io/nuget/v/JT808.Gateway.Kafka.svg) | ![JT808.Gateway.Kafka](https://img.shields.io/nuget/dt/JT808.Gateway.Kafka.svg) |

## 举个栗子1

1.进入JT808.Gateway.SimpleServer项目下的Debug目录运行服务端

2.进入JT808.Gateway.SimpleClient项目下的Debug目录运行客户端

``` 1
static void Main(string[] args)
{
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
//配置Grpc服务端
webBuilder
.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();
app.UseEndpoints(endpoints =>
{
//配置Grpc服务节点
endpoints.MapGrpcService<JT808GatewayService>();
});
});
})
.ConfigureServices((hostContext,services) =>
{
//services.Configure<KestrelServerOptions>(hostContext.Configuration.GetSection("Kestrel"));
//添加Grpc服务
services.AddGrpc();
//添加JT808协议
services.AddJT808Configure()
//添加JT808网关配置
.AddJT808Gateway(hostContext.Configuration)
//添加基于Tcp的808网关
.AddJT808GatewayTcpHost()
//添加基于Udp的808网关
.AddJT808GatewayUdpHost()
.Builder();
})
.Build()
.Run();
}
```

+ 22
- 5
doc/README.md 查看文件

@@ -1,4 +1,6 @@
## 压力测试
# 压力测试

## 基于DotNetty

[感谢泥水佬提供的压力测试工具](https://www.cnblogs.com/smark/p/4496660.html?utm_source=tuicool)

@@ -7,10 +9,25 @@
| win server 2016 | 4c8g | 压力测试客户端 |
| centos7 | 4c8g | JT808服务端 |

![performance_1000](https://github.com/SmallChi/JT808DotNetty/blob/master/doc/img/performance_1000.png)
![performance_1000](https://github.com/SmallChi/JT808DotNetty/blob/master/doc/dotnetty/performance_1000.png)

![performance_2000](https://github.com/SmallChi/JT808DotNetty/blob/master/doc/dotnetty/performance_2000.png)

![performance_5000](https://github.com/SmallChi/JT808DotNetty/blob/master/doc/dotnetty/performance_5000.png)

![performance_10000](https://github.com/SmallChi/JT808DotNetty/blob/master/doc/dotnetty/performance_10000.png)

## 基于pipeline

| 操作系统 | 配置 | 使用 |
|:-------:|:-------:|:-------:|
| centos7 | 4c8g | JT808服务端 |
| centos7 | 4c8g | JT808客户端 |

> 计算网络增强型 sn1ne ecs.sn1ne.xlarge 4 vCPU 8 GiB Intel Xeon E5-2682v4 / Intel Xeon(Skylake) Platinum 8163 2.5 GHz 1.5 Gbps 50 万 PPS

![performance_2000](https://github.com/SmallChi/JT808DotNetty/blob/master/doc/img/performance_2000.png)
![server_proccess_10k](https://github.com/SmallChi/JT808DotNetty/blob/master/doc/pipeline/server_proccess_10k.png)

![performance_5000](https://github.com/SmallChi/JT808DotNetty/blob/master/doc/img/performance_5000.png)
![server_network_10k](https://github.com/SmallChi/JT808DotNetty/blob/master/doc/pipeline/server_network_10k.png)

![performance_10000](https://github.com/SmallChi/JT808DotNetty/blob/master/doc/img/performance_10000.png)
![client_10k](https://github.com/SmallChi/JT808DotNetty/blob/master/doc/pipeline/client_10k.png)

doc/img/demo1.png → doc/dotnetty/demo1.png 查看文件


doc/img/demo2.png → doc/dotnetty/demo2.png 查看文件


doc/img/design_model.png → doc/dotnetty/design_model.png 查看文件


doc/img/performance_1000.png → doc/dotnetty/performance_1000.png 查看文件


doc/img/performance_10000.png → doc/dotnetty/performance_10000.png 查看文件


doc/img/performance_2000.png → doc/dotnetty/performance_2000.png 查看文件


doc/img/performance_5000.png → doc/dotnetty/performance_5000.png 查看文件


二進制
doc/pipeline/client_10k.png 查看文件

Before After
Width: 1035  |  Height: 612  |  Size: 22 KiB

二進制
doc/pipeline/server_network_10k.png 查看文件

Before After
Width: 1694  |  Height: 672  |  Size: 62 KiB

二進制
doc/pipeline/server_proccess_10k.png 查看文件

Before After
Width: 1708  |  Height: 629  |  Size: 59 KiB

+ 0
- 19
src/JT808.Gateway.CleintBenchmark/Configs/ClientBenchmarkOptions.cs 查看文件

@@ -1,19 +0,0 @@
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
- 3106
src/JT808.Gateway.CleintBenchmark/Configs/NLog.xsd
文件差異過大導致無法顯示
查看文件


+ 0
- 36
src/JT808.Gateway.CleintBenchmark/Configs/nlog.unix.config 查看文件

@@ -1,36 +0,0 @@
<?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
- 35
src/JT808.Gateway.CleintBenchmark/Configs/nlog.win.config 查看文件

@@ -1,35 +0,0 @@
<?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
- 33
src/JT808.Gateway.CleintBenchmark/JT808.Gateway.CleintBenchmark.csproj 查看文件

@@ -1,33 +0,0 @@
<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
- 51
src/JT808.Gateway.CleintBenchmark/Program.cs 查看文件

@@ -1,51 +0,0 @@
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
- 82
src/JT808.Gateway.CleintBenchmark/Services/CleintBenchmarkHostedService.cs 查看文件

@@ -1,82 +0,0 @@
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
- 53
src/JT808.Gateway.CleintBenchmark/Services/CleintBenchmarkReportHostedService.cs 查看文件

@@ -1,53 +0,0 @@
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
- 15
src/JT808.Gateway.Kafka/Configs/JT808ConsumerConfig.cs 查看文件

@@ -1,15 +0,0 @@
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
- 13
src/JT808.Gateway.Kafka/Configs/JT808MsgConsumerConfig.cs 查看文件

@@ -1,13 +0,0 @@
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
- 13
src/JT808.Gateway.Kafka/Configs/JT808MsgProducerConfig.cs 查看文件

@@ -1,13 +0,0 @@
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
- 13
src/JT808.Gateway.Kafka/Configs/JT808MsgReplyConsumerConfig.cs 查看文件

@@ -1,13 +0,0 @@
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
- 13
src/JT808.Gateway.Kafka/Configs/JT808MsgReplyProducerConfig.cs 查看文件

@@ -1,13 +0,0 @@
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
- 15
src/JT808.Gateway.Kafka/Configs/JT808ProducerConfig.cs 查看文件

@@ -1,15 +0,0 @@
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
- 13
src/JT808.Gateway.Kafka/Configs/JT808SessionConsumerConfig.cs 查看文件

@@ -1,13 +0,0 @@
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
- 13
src/JT808.Gateway.Kafka/Configs/JT808SessionProducerConfig.cs 查看文件

@@ -1,13 +0,0 @@
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
- 39
src/JT808.Gateway.Kafka/JT808.Gateway.Kafka.csproj 查看文件

@@ -1,39 +0,0 @@
<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
- 24
src/JT808.Gateway.Kafka/JT808ClientBuilderDefault.cs 查看文件

@@ -1,24 +0,0 @@
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
- 66
src/JT808.Gateway.Kafka/JT808ClientKafkaExtensions.cs 查看文件

@@ -1,66 +0,0 @@
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
- 82
src/JT808.Gateway.Kafka/JT808MsgConsumer.cs 查看文件

@@ -1,82 +0,0 @@
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
- 38
src/JT808.Gateway.Kafka/JT808MsgProducer.cs 查看文件

@@ -1,38 +0,0 @@
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
- 82
src/JT808.Gateway.Kafka/JT808MsgReplyConsumer.cs 查看文件

@@ -1,82 +0,0 @@
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
- 38
src/JT808.Gateway.Kafka/JT808MsgReplyProducer.cs 查看文件

@@ -1,38 +0,0 @@
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
- 48
src/JT808.Gateway.Kafka/JT808ServerKafkaExtensions.cs 查看文件

@@ -1,48 +0,0 @@
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
- 82
src/JT808.Gateway.Kafka/JT808SessionConsumer.cs 查看文件

@@ -1,82 +0,0 @@
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
- 38
src/JT808.Gateway.Kafka/JT808SessionProducer.cs 查看文件

@@ -1,38 +0,0 @@
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
});
}
}
}

+ 0
- 18
src/JT808.Gateway.SimpleClient/JT808.Gateway.SimpleClient.csproj 查看文件

@@ -1,18 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.24.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\JT808.Gateway\JT808.Gateway.csproj" />
</ItemGroup>

</Project>

+ 0
- 52
src/JT808.Gateway.SimpleClient/Program.cs 查看文件

@@ -1,52 +0,0 @@
using JT808.Gateway.Client;
using JT808.Gateway.SimpleClient.Services;
using JT808.Protocol;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;
using Grpc.Net.Client;
using JT808.Gateway.GrpcService;
using System.Net;

namespace JT808.Gateway.SimpleClient
{
class Program
{
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
//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) =>
{
logging.AddConsole();
logging.SetMinimumLevel(LogLevel.Trace);
})
.ConfigureServices((hostContext, services) =>
{
services.AddGrpcClient<JT808Gateway.JT808GatewayClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
});
services.AddSingleton<ILoggerFactory, LoggerFactory>();
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
services.AddLogging(options => {
options.AddConsole();
options.SetMinimumLevel(LogLevel.Trace);
});
services.AddJT808Configure()
.AddJT808Client();
services.AddHostedService<UpService>();
//services.AddHostedService<GrpcClientService>();
});
await serverHostBuilder.RunConsoleAsync();
}
}
}

+ 0
- 68
src/JT808.Gateway.SimpleClient/Services/GrpcClientService.cs 查看文件

@@ -1,68 +0,0 @@
using JT808.Gateway.Client;
using JT808.Protocol.MessageBody;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using JT808.Gateway.GrpcService;
using static JT808.Gateway.GrpcService.JT808Gateway;
using Google.Protobuf;
using System.Text.Json;
using JT808.Protocol.Extensions;

namespace JT808.Gateway.SimpleClient.Services
{
public class GrpcClientService : IHostedService
{
private readonly ILogger logger;
private readonly JT808GatewayClient client;

public GrpcClientService(
ILoggerFactory loggerFactory,
JT808GatewayClient jT808GatewayClient)
{
this.client = jT808GatewayClient;
logger = loggerFactory.CreateLogger("GrpcClientService");
}

public Task StartAsync(CancellationToken cancellationToken)
{
Task.Run(() => {
//while (!cancellationToken.IsCancellationRequested)
//{
Thread.Sleep(1000 * 10);
var result1 = client.GetTcpAtomicCounter(new Empty());
var result2 = client.GetUdpAtomicCounter(new Empty());
var result3 = client.GetTcpSessionAll(new Empty());
var result4 = client.GetUdpSessionAll(new Empty());
var result5 = client.UnificationSend(new UnificationSendRequest()
{
TerminalPhoneNo= "12345678910",
Data= ByteString.CopyFrom("7E 02 00 00 26 12 34 56 78 90 12 00 7D 02 00 00 00 01 00 00 00 02 00 BA 7F 0E 07 E4 F1 1C 00 28 00 3C 00 00 18 10 15 10 10 10 01 04 00 00 00 64 02 02 00 7D 01 13 7E".ToHexBytes())
});
var result6 = client.RemoveSessionByTerminalPhoneNo(new SessionRemoveRequest()
{
TerminalPhoneNo= "12345678910"
});

logger.LogDebug(JsonSerializer.Serialize(result1));
logger.LogDebug(JsonSerializer.Serialize(result2));
logger.LogDebug(JsonSerializer.Serialize(result3));
logger.LogDebug(JsonSerializer.Serialize(result4));
logger.LogDebug(JsonSerializer.Serialize(result5));
logger.LogDebug(JsonSerializer.Serialize(result6));
//}
}, cancellationToken);
return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
}

+ 0
- 68
src/JT808.Gateway.SimpleClient/Services/UpService.cs 查看文件

@@ -1,68 +0,0 @@
using JT808.Gateway.Client;
using JT808.Protocol.MessageBody;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace JT808.Gateway.SimpleClient.Services
{
public class UpService : IHostedService
{
private readonly IJT808TcpClientFactory jT808TcpClientFactory;

public UpService(IJT808TcpClientFactory jT808TcpClientFactory)
{
this.jT808TcpClientFactory = jT808TcpClientFactory;
}

public Task StartAsync(CancellationToken cancellationToken)
{
JT808TcpClient client1 = jT808TcpClientFactory.Create(new DeviceConfig("12345678910", "127.0.0.1", 808));
//1.终端注册
client1.Send(new JT808_0x0100()
{
PlateNo = "粤A12345",
PlateColor = 2,
AreaID = 0,
CityOrCountyId = 0,
MakerId = "Koike001",
TerminalId = "Koike001",
TerminalModel = "Koike001"
});
//2.终端鉴权
client1.Send(new JT808_0x0102()
{
Code = "1234"
});
Task.Run(() => {
while (true)
{
var i = 0;
//3.每5000秒发一次
client1.Send(new JT808_0x0200()
{
Lat = 110000 + i,
Lng = 100000 + i,
GPSTime = DateTime.Now,
Speed = 50,
Direction = 30,
AlarmFlag = 5,
Altitude = 50,
StatusFlag = 10
});
i++;
Thread.Sleep(5000);
}
});
return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
}

+ 0
- 3106
src/JT808.Gateway.SimpleServer/Configs/NLog.xsd
文件差異過大導致無法顯示
查看文件


+ 0
- 36
src/JT808.Gateway.SimpleServer/Configs/nlog.Unix.config 查看文件

@@ -1,36 +0,0 @@
<?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/gps_services/serviceslogs/JT808.Gateway.SimpleServer/internalLog.txt"
internalLogLevel="Debug" >
<variable name="Directory" value="/data/gps_services/serviceslogs/JT808.Gateway.SimpleServer"/>
<targets>
<target name="SimpleServer" xsi:type="File"
fileName="${Directory}/SimpleServer.${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="SimpleServer"/>
</rules>
</nlog>

+ 0
- 36
src/JT808.Gateway.SimpleServer/Configs/nlog.Win32NT.config 查看文件

@@ -1,36 +0,0 @@
<?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="wwwroot/logs/JT808.Gateway.SimpleServer/internalLog.txt"
internalLogLevel="Debug" >
<variable name="Directory" value="/wwwroot/logs/JT808.Gateway.SimpleServer"/>
<targets>
<target name="SimpleServer" xsi:type="File"
fileName="${Directory}/SimpleServer.${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="Trace" maxlevel="Fatal" writeTo="SimpleServer,console"/>
</rules>
</nlog>

二進制
src/JT808.Gateway.SimpleServer/Configs/test.cer 查看文件


+ 0
- 39
src/JT808.Gateway.SimpleServer/JT808.Gateway.SimpleServer.csproj 查看文件

@@ -1,39 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Grpc.AspNetCore" Version="2.24.0" />
<PackageReference Include="NLog.Extensions.Logging" Version="1.6.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\JT808.Gateway\JT808.Gateway.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="appsettings.Development.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Configs\nlog.Unix.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Configs\nlog.Win32NT.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Configs\NLog.xsd">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Configs\test.cer">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>


+ 0
- 71
src/JT808.Gateway.SimpleServer/Program.cs 查看文件

@@ -1,71 +0,0 @@
using JT808.Gateway.Services;
using JT808.Gateway.Tcp;
using JT808.Gateway.Udp;
using JT808.Protocol;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging;
using System;
using System.IO;
using System.Net;

namespace JT808.Gateway.SimpleServer
{
class Program
{
static void Main(string[] args)
{
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory);
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
})
.ConfigureLogging((hostContext, configLogging) => {
Console.WriteLine($"Environment.OSVersion.Platform:{Environment.OSVersion.Platform.ToString()}");
NLog.LogManager.LoadConfiguration($"Configs/nlog.{Environment.OSVersion.Platform.ToString()}.config");
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;
listenOptions.UseHttps($"{Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Configs", "test.cer")}", "");
});
})
.Configure(app =>
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<JT808GatewayService>();
});
});
})
.ConfigureServices((hostContext,services) =>
{
//services.Configure<KestrelServerOptions>(hostContext.Configuration.GetSection("Kestrel"));
services.AddGrpc();
services.AddSingleton<ILoggerFactory, LoggerFactory>();
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
services.AddJT808Configure()
.AddJT808Gateway(hostContext.Configuration)
.AddJT808GatewayTcpHost()
.AddJT808GatewayUdpHost()
.Builder();
})
.Build()
.Run();
}
}
}

+ 0
- 102
src/JT808.Gateway.sln 查看文件

@@ -1,102 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29411.108
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway", "JT808.Gateway\JT808.Gateway.csproj", "{A42A396F-D32B-4AC2-B554-735AA7E2DBA8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808.Gateway.SimpleServer", "JT808.Gateway.SimpleServer\JT808.Gateway.SimpleServer.csproj", "{F9ABFDDB-84A2-44C8-A162-A1FE4EA4D332}"
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
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A42A396F-D32B-4AC2-B554-735AA7E2DBA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A42A396F-D32B-4AC2-B554-735AA7E2DBA8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A42A396F-D32B-4AC2-B554-735AA7E2DBA8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A42A396F-D32B-4AC2-B554-735AA7E2DBA8}.Release|Any CPU.Build.0 = Release|Any CPU
{F9ABFDDB-84A2-44C8-A162-A1FE4EA4D332}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F9ABFDDB-84A2-44C8-A162-A1FE4EA4D332}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F9ABFDDB-84A2-44C8-A162-A1FE4EA4D332}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F9ABFDDB-84A2-44C8-A162-A1FE4EA4D332}.Release|Any CPU.Build.0 = Release|Any CPU
{886D4937-7265-40DC-87CC-85CE35553214}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{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
EndGlobal

+ 0
- 14
src/JT808.Gateway/BusinessServices/MsgIdHandler/IJT808MsgIdHandler.cs 查看文件

@@ -1,14 +0,0 @@
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
- 18
src/JT808.Gateway/BusinessServices/MsgIdHandler/JT808MsgIdHandlerExtensions.cs 查看文件

@@ -1,18 +0,0 @@
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
- 34
src/JT808.Gateway/BusinessServices/MsgIdHandler/JT808MsgIdHandlerHostedService.cs 查看文件

@@ -1,34 +0,0 @@
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
- 15
src/JT808.Gateway/BusinessServices/MsgLogging/IJT808MsgLogging.cs 查看文件

@@ -1,15 +0,0 @@
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
- 36
src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgDownLoggingHostedService.cs 查看文件

@@ -1,36 +0,0 @@
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
- 19
src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgLoggingExtensions.cs 查看文件

@@ -1,19 +0,0 @@
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
- 18
src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgLoggingType.cs 查看文件

@@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace JT808.Gateway.BusinessServices.MsgLogging
{
public enum JT808MsgLoggingType
{
/// <summary>
/// 数据上行
/// </summary>
up,
/// <summary>
/// 数据下行
/// </summary>
down
}
}

+ 0
- 36
src/JT808.Gateway/BusinessServices/MsgLogging/JT808MsgUpLoggingHostedService.cs 查看文件

@@ -1,36 +0,0 @@
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
- 57
src/JT808.Gateway/BusinessServices/ReplyMessage/JT808ReplyMessageExtensions.cs 查看文件

@@ -1,57 +0,0 @@
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
- 34
src/JT808.Gateway/BusinessServices/ReplyMessage/JT808ReplyMessageHostedService.cs 查看文件

@@ -1,34 +0,0 @@
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
- 165
src/JT808.Gateway/BusinessServices/ReplyMessage/JT808ReplyMessageService.cs 查看文件

@@ -1,165 +0,0 @@
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
- 60
src/JT808.Gateway/BusinessServices/SessionNotice/JT808SessionNoticeExtensions.cs 查看文件

@@ -1,60 +0,0 @@
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
- 35
src/JT808.Gateway/BusinessServices/SessionNotice/JT808SessionNoticeHostedService.cs 查看文件

@@ -1,35 +0,0 @@
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
- 24
src/JT808.Gateway/BusinessServices/SessionNotice/JT808SessionNoticeService.cs 查看文件

@@ -1,24 +0,0 @@
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
- 32
src/JT808.Gateway/BusinessServices/Traffic/JT808TrafficService.cs 查看文件

@@ -1,32 +0,0 @@
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
- 33
src/JT808.Gateway/BusinessServices/Traffic/JT808TrafficServiceExtensions.cs 查看文件

@@ -1,33 +0,0 @@
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
- 38
src/JT808.Gateway/BusinessServices/Traffic/JT808TrafficServiceHostedService.cs 查看文件

@@ -1,38 +0,0 @@
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
- 9
src/JT808.Gateway/BusinessServices/Traffic/TrafficRedisClient.cs 查看文件

@@ -1,9 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace JT808.Gateway.BusinessServices.Traffic
{
class TrafficRedisClient: RedisHelper<TrafficRedisClient>
{ }
}

+ 0
- 13
src/JT808.Gateway/BusinessServices/Transmit/Configs/DataTransferOptions.cs 查看文件

@@ -1,13 +0,0 @@
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
- 11
src/JT808.Gateway/BusinessServices/Transmit/Configs/RemoteServerOptions.cs 查看文件

@@ -1,11 +0,0 @@
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
- 76
src/JT808.Gateway/BusinessServices/Transmit/Handlers/ClientConnectionHandler.cs 查看文件

@@ -1,76 +0,0 @@
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
- 39
src/JT808.Gateway/BusinessServices/Transmit/JT808DotNettyTransmitExtensions.cs 查看文件

@@ -1,39 +0,0 @@
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
- 33
src/JT808.Gateway/BusinessServices/Transmit/JT808DotNettyTransmitHostedService.cs 查看文件

@@ -1,33 +0,0 @@
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
- 236
src/JT808.Gateway/BusinessServices/Transmit/JT808DotNettyTransmitService.cs 查看文件

@@ -1,236 +0,0 @@
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}");
}
}
}
}
}

+ 0
- 28
src/JT808.Gateway/Client/DeviceConfig.cs 查看文件

@@ -1,28 +0,0 @@
using JT808.Protocol;
using JT808.Protocol.Interfaces;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT808.Gateway.Client
{
public class DeviceConfig
{
public DeviceConfig(string terminalPhoneNo, string tcpHost,int tcpPort)
{
TerminalPhoneNo = terminalPhoneNo;
TcpHost = tcpHost;
TcpPort = tcpPort;
MsgSNDistributed = new JT808ClientMsgSNDistributedImpl();
}
public string TerminalPhoneNo { get; private set; }
public string TcpHost { get; private set; }
public int TcpPort { get; private set; }
/// <summary>
/// 心跳时间(秒)
/// </summary>
public int Heartbeat { get; set; } = 30;

public IJT808MsgSNDistributed MsgSNDistributed { get; }
}
}

+ 0
- 23
src/JT808.Gateway/Client/JT808ClientDotnettyExtensions.cs 查看文件

@@ -1,23 +0,0 @@

using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Text;
using JT808.Protocol;
using JT808.Gateway.Services;

namespace JT808.Gateway.Client
{
public static class JT808ClientDotnettyExtensions
{
public static IJT808Builder AddJT808Client(this IJT808Builder jT808Builder)
{
jT808Builder.Services.AddSingleton<JT808ClientSendAtomicCounterService>();
jT808Builder.Services.AddSingleton<JT808ClientReceiveAtomicCounterService>();
jT808Builder.Services.AddSingleton<IJT808TcpClientFactory, JT808TcpClientFactory>();
jT808Builder.Services.AddSingleton<JT808ClientReportService>();
jT808Builder.Services.AddHostedService<JT808ClientReportHostedService>();
return jT808Builder;
}
}
}

+ 0
- 16
src/JT808.Gateway/Client/JT808ClientMsgSNDistributedImpl.cs 查看文件

@@ -1,16 +0,0 @@
using JT808.Protocol;
using JT808.Protocol.Interfaces;
using System.Threading;

namespace JT808.Gateway.Client
{
internal class JT808ClientMsgSNDistributedImpl : IJT808MsgSNDistributed
{
int _counter = 0;

public ushort Increment()
{
return (ushort)Interlocked.Increment(ref _counter);
}
}
}

+ 0
- 112
src/JT808.Gateway/Client/JT808TcpClient.cs 查看文件

@@ -1,112 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using Microsoft.Extensions.Logging;
using System;
using System.Runtime.InteropServices;
using Microsoft.Extensions.DependencyInjection;
using System.Net;
using JT808.Protocol;
using JT808.Gateway.Services;
using JT808.Gateway.Codecs;
using JT808.Gateway.Handlers;
using JT808.Gateway.Metadata;

namespace JT808.Gateway.Client
{
public sealed class JT808TcpClient : IDisposable
{
private MultithreadEventLoopGroup group;

private IChannel clientChannel;

private bool disposed = false;

public DeviceConfig DeviceConfig { get; private set; }

public ILoggerFactory LoggerFactory { get; private set; }

public JT808TcpClient(DeviceConfig deviceConfig, IServiceProvider serviceProvider)
{
DeviceConfig = deviceConfig;
LoggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
JT808ClientSendAtomicCounterService jT808SendAtomicCounterService = serviceProvider.GetRequiredService<JT808ClientSendAtomicCounterService>();
JT808ClientReceiveAtomicCounterService jT808ReceiveAtomicCounterService = serviceProvider.GetRequiredService<JT808ClientReceiveAtomicCounterService>();
IJT808Config jT808Config = serviceProvider.GetRequiredService<IJT808Config>();
group = new MultithreadEventLoopGroup(1);
Bootstrap bootstrap = new Bootstrap();
bootstrap.Group(group);
bootstrap.Channel<TcpSocketChannel>();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
bootstrap.Option(ChannelOption.SoReuseport, true);
}
bootstrap
.Option(ChannelOption.SoBacklog, 8192)
.Handler(new ActionChannelInitializer<IChannel>(channel =>
{
channel.Pipeline.AddLast("jt808TcpBuffer", new DelimiterBasedFrameDecoder(int.MaxValue,
Unpooled.CopiedBuffer(new byte[] { JT808.Protocol.JT808Package.BeginFlag }),
Unpooled.CopiedBuffer(new byte[] { JT808.Protocol.JT808Package.EndFlag })));
channel.Pipeline.AddLast("systemIdleState", new IdleStateHandler(60, deviceConfig.Heartbeat, 3600));
channel.Pipeline.AddLast("jt808TcpDecode", new JT808ClientTcpDecoder());
channel.Pipeline.AddLast("jt808TcpEncode", new JT808ClientTcpEncoder(jT808Config,jT808SendAtomicCounterService, LoggerFactory));
channel.Pipeline.AddLast("jt808TcpClientConnection", new JT808TcpClientConnectionHandler(this));
channel.Pipeline.AddLast("jt808TcpService", new JT808TcpClientHandler(jT808ReceiveAtomicCounterService,this));
}));
clientChannel = bootstrap.ConnectAsync(IPAddress.Parse(DeviceConfig.TcpHost), DeviceConfig.TcpPort).Result;
}

public async void Send(JT808ClientRequest request)
{
if (disposed) return;
if (clientChannel == null) throw new NullReferenceException("Channel is empty.");
if (request == null) throw new ArgumentNullException("JT808ClientRequest Parameter is empty.");
if (clientChannel.Active && clientChannel.Open)
{
await clientChannel.WriteAndFlushAsync(request);
}
}

public bool IsOpen
{
get
{
if (clientChannel == null) return false;
return clientChannel.Active && clientChannel.Open;
}
}

private void Dispose(bool disposing)
{
if (disposed)
{
return;
}
if (disposing)
{
// 清理托管资源
group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1));
}
disposed = true;
}

~JT808TcpClient()
{
//必须为false
//这表明,隐式清理时,只要处理非托管资源就可以了。
Dispose(false);
}

public void Dispose()
{
//必须为true
Dispose(true);
//通知垃圾回收机制不再调用终结器(析构器)
GC.SuppressFinalize(this);
}
}
}

+ 0
- 103
src/JT808.Gateway/Client/JT808TcpClientExtensions.cs 查看文件

@@ -1,103 +0,0 @@
using JT808.Protocol;
using JT808.Protocol.MessageBody;
using System;
using System.Collections.Generic;
using System.Text;
using JT808.Protocol.Enums;
using JT808.Protocol.Extensions;
using JT808.Gateway.Metadata;

namespace JT808.Gateway.Client
{
public static class JT808TcpClientExtensions
{
public static void Send(this JT808TcpClient client, JT808Header header, JT808Bodies bodies, int minBufferSize = 1024)
{
JT808Package package = new JT808Package();
package.Header = header;
package.Bodies = bodies;
package.Header.TerminalPhoneNo = client.DeviceConfig.TerminalPhoneNo;
package.Header.MsgNum = client.DeviceConfig.MsgSNDistributed.Increment();
JT808ClientRequest request = new JT808ClientRequest(package, minBufferSize);
client.Send(request);
}

/// <summary>
/// 终端通用应答
/// </summary>
/// <param name="client"></param>
/// <param name="bodies"></param>
/// <param name="minBufferSize"></param>
public static void Send(this JT808TcpClient client, JT808_0x0001 bodies, int minBufferSize = 100)
{
JT808Header header = new JT808Header();
header.MsgId = JT808MsgId.终端通用应答.ToUInt16Value();
client.Send(header, bodies, minBufferSize);
}

/// <summary>
/// 终端心跳
/// </summary>
/// <param name="client"></param>
/// <param name="bodies"></param>
/// <param name="minBufferSize"></param>
public static void Send(this JT808TcpClient client, JT808_0x0002 bodies, int minBufferSize = 100)
{
JT808Header header = new JT808Header();
header.MsgId = JT808MsgId.终端心跳.ToUInt16Value();
client.Send(header, bodies, minBufferSize);
}

/// <summary>
/// 终端注销
/// </summary>
/// <param name="client"></param>
/// <param name="bodies"></param>
/// <param name="minBufferSize"></param>
public static void Send(this JT808TcpClient client, JT808_0x0003 bodies, int minBufferSize = 100)
{
JT808Header header = new JT808Header();
header.MsgId = JT808MsgId.终端注销.ToUInt16Value();
client.Send(header, bodies, minBufferSize);
}

/// <summary>
/// 终端鉴权
/// </summary>
/// <param name="client"></param>
/// <param name="bodies"></param>
/// <param name="minBufferSize"></param>
public static void Send(this JT808TcpClient client, JT808_0x0102 bodies, int minBufferSize = 100)
{
JT808Header header = new JT808Header();
header.MsgId = JT808MsgId.终端鉴权.ToUInt16Value();
client.Send(header, bodies, minBufferSize);
}

/// <summary>
/// 终端注册
/// </summary>
/// <param name="client"></param>
/// <param name="bodies"></param>
/// <param name="minBufferSize"></param>
public static void Send(this JT808TcpClient client, JT808_0x0100 bodies, int minBufferSize = 100)
{
JT808Header header = new JT808Header();
header.MsgId = JT808MsgId.终端注册.ToUInt16Value();
client.Send(header, bodies, minBufferSize);
}

/// <summary>
/// 位置信息汇报
/// </summary>
/// <param name="client"></param>
/// <param name="bodies"></param>
/// <param name="minBufferSize"></param>
public static void Send(this JT808TcpClient client, JT808_0x0200 bodies, int minBufferSize = 200)
{
JT808Header header = new JT808Header();
header.MsgId = JT808MsgId.位置信息汇报.ToUInt16Value();
client.Send(header, bodies, minBufferSize);
}
}
}

+ 0
- 62
src/JT808.Gateway/Client/JT808TcpClientFactory.cs 查看文件

@@ -1,62 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace JT808.Gateway.Client
{
public interface IJT808TcpClientFactory : IDisposable
{
JT808TcpClient Create(DeviceConfig deviceConfig);

List<JT808TcpClient> GetAll();
}

public class JT808TcpClientFactory: IJT808TcpClientFactory
{
private readonly ConcurrentDictionary<string, JT808TcpClient> dict;

private readonly IServiceProvider serviceProvider;

public JT808TcpClientFactory(IServiceProvider serviceProvider)
{
dict = new ConcurrentDictionary<string, JT808TcpClient>(StringComparer.OrdinalIgnoreCase);
this.serviceProvider = serviceProvider;
}

public JT808TcpClient Create(DeviceConfig deviceConfig)
{
if(dict.TryGetValue(deviceConfig.TerminalPhoneNo,out var client))
{
return client;
}
else
{
JT808TcpClient jT808TcpClient = new JT808TcpClient(deviceConfig, serviceProvider);
dict.TryAdd(deviceConfig.TerminalPhoneNo, jT808TcpClient);
return jT808TcpClient;
}
}

public void Dispose()
{
foreach(var client in dict)
{
try
{
client.Value.Dispose();
}
catch
{
}
}
}

public List<JT808TcpClient> GetAll()
{
return dict.Values.ToList();
}
}
}

+ 0
- 20
src/JT808.Gateway/Codecs/JT808ClientTcpDecoder.cs 查看文件

@@ -1,20 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using System.Collections.Generic;
using JT808.Protocol;
using DotNetty.Transport.Channels;

namespace JT808.Gateway.Codecs
{
public class JT808ClientTcpDecoder : ByteToMessageDecoder
{
protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List<object> output)
{
byte[] buffer = new byte[input.Capacity + 2];
input.ReadBytes(buffer, 1, input.Capacity);
buffer[0] = JT808Package.BeginFlag;
buffer[input.Capacity + 1] = JT808Package.EndFlag;
output.Add(buffer);
}
}
}

+ 0
- 52
src/JT808.Gateway/Codecs/JT808ClientTcpEncoder.cs 查看文件

@@ -1,52 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using JT808.Protocol;
using DotNetty.Transport.Channels;
using Microsoft.Extensions.Logging;
using JT808.Gateway.Metadata;
using JT808.Gateway.Services;

namespace JT808.Gateway.Codecs
{
public class JT808ClientTcpEncoder : MessageToByteEncoder<JT808ClientRequest>
{
private readonly ILogger<JT808ClientTcpEncoder> logger;
private readonly JT808ClientSendAtomicCounterService jT808SendAtomicCounterService;
private readonly JT808Serializer JT808Serializer;

public JT808ClientTcpEncoder(
IJT808Config jT808Config,
JT808ClientSendAtomicCounterService jT808SendAtomicCounterService,ILoggerFactory loggerFactory)
{
logger=loggerFactory.CreateLogger<JT808ClientTcpEncoder>();
this.jT808SendAtomicCounterService = jT808SendAtomicCounterService;
JT808Serializer = jT808Config.GetSerializer();
}

protected override void Encode(IChannelHandlerContext context, JT808ClientRequest message, IByteBuffer output)
{
if (message.Package != null)
{
try
{
var sendData = JT808Serializer.Serialize(message.Package, message.MinBufferSize);
output.WriteBytes(sendData);
jT808SendAtomicCounterService.MsgSuccessIncrement();
}
catch (JT808.Protocol.Exceptions.JT808Exception ex)
{
logger.LogError(ex, context.Channel.Id.AsShortText());
}
catch (System.Exception ex)
{
logger.LogError(ex, context.Channel.Id.AsShortText());
}
}
else if (message.HexData != null)
{
output.WriteBytes(message.HexData);
jT808SendAtomicCounterService.MsgSuccessIncrement();
}
}
}
}

+ 0
- 32
src/JT808.Gateway/Codecs/JT808TcpDecoder.cs 查看文件

@@ -1,32 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using System.Collections.Generic;
using JT808.Protocol;
using DotNetty.Transport.Channels;

namespace JT808.Gateway.Codecs
{
public class JT808TcpDecoder : ByteToMessageDecoder
{
protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List<object> output)
{
//过滤掉不是808标准包
//不包括头尾标识
//(消息 ID )2+(消息体属性)2+(终端手机号)6+(消息流水号)2+(检验码 )1
if (input.Capacity < 12)
{
byte[] buffer = new byte[input.Capacity];
input.ReadBytes(buffer, 0, input.Capacity);
return;
}
else
{
byte[] buffer = new byte[input.Capacity + 2];
input.ReadBytes(buffer, 1, input.Capacity);
buffer[0] = JT808Package.BeginFlag;
buffer[input.Capacity + 1] = JT808Package.EndFlag;
output.Add(buffer);
}
}
}
}

+ 0
- 52
src/JT808.Gateway/Codecs/JT808TcpEncoder.cs 查看文件

@@ -1,52 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using JT808.Protocol;
using DotNetty.Transport.Channels;
using Microsoft.Extensions.Logging;
using JT808.Protocol.Interfaces;
using JT808.Gateway.Interfaces;

namespace JT808.Gateway.Codecs
{
/// <summary>
/// tcp统一下发出口
/// </summary>
public class JT808TcpEncoder : MessageToByteEncoder<IJT808Reply>
{
private readonly ILogger<JT808TcpEncoder> logger;

private readonly JT808Serializer JT808Serializer;

public JT808TcpEncoder(
IJT808Config jT808Config,
ILoggerFactory loggerFactory)
{
logger = loggerFactory.CreateLogger<JT808TcpEncoder>();
this.JT808Serializer = jT808Config.GetSerializer();
}

protected override void Encode(IChannelHandlerContext context, IJT808Reply message, IByteBuffer output)
{
if (message.Package != null)
{
try
{
var sendData = JT808Serializer.Serialize(message.Package, message.MinBufferSize);
output.WriteBytes(Unpooled.WrappedBuffer(sendData));
}
catch (JT808.Protocol.Exceptions.JT808Exception ex)
{
logger.LogError(ex, context.Channel.Id.AsShortText());
}
catch (System.Exception ex)
{
logger.LogError(ex, context.Channel.Id.AsShortText());
}
}
else if (message.HexData != null)
{
output.WriteBytes(Unpooled.WrappedBuffer(message.HexData));
}
}
}
}

+ 0
- 33
src/JT808.Gateway/Codecs/JT808UdpDecoder.cs 查看文件

@@ -1,33 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Transport.Channels;
using System.Collections.Generic;
using DotNetty.Transport.Channels.Sockets;
using JT808.Gateway.Metadata;

namespace JT808.Gateway.Codecs
{
public class JT808UdpDecoder : MessageToMessageDecoder<DatagramPacket>
{
protected override void Decode(IChannelHandlerContext context, DatagramPacket message, List<object> output)
{
if (!message.Content.IsReadable()) return;
IByteBuffer byteBuffer = message.Content;
//过滤掉非808标准包
//不包括头尾标识
//(消息 ID )2+(消息体属性)2+(终端手机号)6+(消息流水号)2+(检验码 )1
if (byteBuffer.ReadableBytes < 12)
{
byte[] buffer = new byte[byteBuffer.ReadableBytes];
byteBuffer.ReadBytes(buffer, 0, byteBuffer.ReadableBytes);
return;
}
else
{
byte[] buffer = new byte[byteBuffer.ReadableBytes];
byteBuffer.ReadBytes(buffer);
output.Add(new JT808UdpPackage(buffer, message.Sender));
}
}
}
}

+ 0
- 41
src/JT808.Gateway/Configurations/JT808Configuration.cs 查看文件

@@ -1,41 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace JT808.Gateway.Configurations
{
public class JT808Configuration
{
public int TcpPort { get; set; } = 808;

public int UdpPort { get; set; } = 808;

public int QuietPeriodSeconds { get; set; } = 1;

public TimeSpan QuietPeriodTimeSpan => TimeSpan.FromSeconds(QuietPeriodSeconds);

public int ShutdownTimeoutSeconds { get; set; } = 3;

public TimeSpan ShutdownTimeoutTimeSpan => TimeSpan.FromSeconds(ShutdownTimeoutSeconds);

public int SoBacklog { get; set; } = 8192;

public int EventLoopCount { get; set; } = Environment.ProcessorCount;

public int ReaderIdleTimeSeconds { get; set; } = 3600;

public int WriterIdleTimeSeconds { get; set; } = 3600;

public int AllIdleTimeSeconds { get; set; } = 3600;

/// <summary>
/// 转发远程地址 (可选项)知道转发的地址有利于提升性能
/// 按照808的消息,有些请求必须要应答,但是转发可以不需要有应答可以节省部分资源包括:
// 1.消息的序列化
// 2.消息的下发
// 都有一定的性能损耗,那么不需要判断写超时 IdleState.WriterIdle
// 就跟神兽貔貅一样。。。
/// </summary>
public List<string> ForwardingRemoteIPAddress { get; set; }
}
}

+ 0
- 29
src/JT808.Gateway/Dtos/JT808ResultDto.cs 查看文件

@@ -1,29 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace JT808.Gateway.Dtos
{
public class JT808ResultDto<T>
{
public JT808ResultDto()
{
Code = JT808ResultCode.Ok;
}

public string Message { get; set; }

public int Code { get; set; }

public T Data { get; set; }
}

public class JT808ResultCode
{
public const int Ok = 200;
public const int Empty = 201;
public const int NotFound = 404;
public const int Fail = 400;
public const int Error = 500;
}
}

+ 0
- 24
src/JT808.Gateway/Dtos/JT808TcpSessionInfoDto.cs 查看文件

@@ -1,24 +0,0 @@
using System;

namespace JT808.Gateway.Dtos
{
public class JT808TcpSessionInfoDto
{
/// <summary>
/// 最后上线时间
/// </summary>
public DateTime LastActiveTime { get; set; }
/// <summary>
/// 上线时间
/// </summary>
public DateTime StartTime { get; set; }
/// <summary>
/// 终端手机号
/// </summary>
public string TerminalPhoneNo { get; set; }
/// <summary>
/// 远程ip地址
/// </summary>
public string RemoteAddressIP { get; set; }
}
}

+ 0
- 24
src/JT808.Gateway/Dtos/JT808UdpSessionInfoDto.cs 查看文件

@@ -1,24 +0,0 @@
using System;

namespace JT808.Gateway.Dtos
{
public class JT808UdpSessionInfoDto
{
/// <summary>
/// 最后上线时间
/// </summary>
public DateTime LastActiveTime { get; set; }
/// <summary>
/// 上线时间
/// </summary>
public DateTime StartTime { get; set; }
/// <summary>
/// 终端手机号
/// </summary>
public string TerminalPhoneNo { get; set; }
/// <summary>
/// 远程ip地址
/// </summary>
public string RemoteAddressIP { get; set; }
}
}

+ 0
- 15
src/JT808.Gateway/Enums/JT808TransportProtocolType.cs 查看文件

@@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace JT808.Gateway.Enums
{
/// <summary>
/// 传输协议类型
/// </summary>
public enum JT808TransportProtocolType
{
tcp=1,
udp = 2
}
}

+ 0
- 96
src/JT808.Gateway/Handlers/JT808TcpClientConnectionHandler.cs 查看文件

@@ -1,96 +0,0 @@
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Channels;
using JT808.Gateway.Client;
using JT808.Protocol.MessageBody;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;

namespace JT808.Gateway.Handlers
{
/// <summary>
/// JT808客户端连接通道处理程序
/// </summary>
public class JT808TcpClientConnectionHandler : ChannelHandlerAdapter
{
private readonly ILogger<JT808TcpClientConnectionHandler> logger;
private readonly JT808TcpClient jT808TcpClient;

public JT808TcpClientConnectionHandler(
JT808TcpClient jT808TcpClient)
{
logger = jT808TcpClient.LoggerFactory.CreateLogger<JT808TcpClientConnectionHandler>();
this.jT808TcpClient = jT808TcpClient;
}

/// <summary>
/// 通道激活
/// </summary>
/// <param name="context"></param>
public override void ChannelActive(IChannelHandlerContext context)
{
string channelId = context.Channel.Id.AsShortText();
if (logger.IsEnabled(LogLevel.Debug))
logger.LogDebug($"<<<{ channelId } Successful client connection to server.");
base.ChannelActive(context);
}

/// <summary>
/// 设备主动断开
/// </summary>
/// <param name="context"></param>
public override void ChannelInactive(IChannelHandlerContext context)
{
string channelId = context.Channel.Id.AsShortText();
if (logger.IsEnabled(LogLevel.Debug))
logger.LogDebug($">>>{ channelId } The client disconnects from the server.");
base.ChannelInactive(context);
}

/// <summary>
/// 服务器主动断开
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override Task CloseAsync(IChannelHandlerContext context)
{
string channelId = context.Channel.Id.AsShortText();
if (logger.IsEnabled(LogLevel.Debug))
logger.LogDebug($"<<<{ channelId } The server disconnects from the client.");

return base.CloseAsync(context);
}

public override void ChannelReadComplete(IChannelHandlerContext context)=> context.Flush();

/// <summary>
/// 超时策略
/// </summary>
/// <param name="context"></param>
/// <param name="evt"></param>
public override void UserEventTriggered(IChannelHandlerContext context, object evt)
{
IdleStateEvent idleStateEvent = evt as IdleStateEvent;
if (idleStateEvent != null)
{
if(idleStateEvent.State== IdleState.WriterIdle)
{
string channelId = context.Channel.Id.AsShortText();
logger.LogInformation($"{idleStateEvent.State.ToString()}>>>{channelId}");
jT808TcpClient.Send(new JT808_0x0002());
}
}
base.UserEventTriggered(context, evt);
}

public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
{
string channelId = context.Channel.Id.AsShortText();
logger.LogError(exception,$"{channelId} {exception.Message}" );

context.CloseAsync();
}
}
}


+ 0
- 31
src/JT808.Gateway/Handlers/JT808TcpClientHandler.cs 查看文件

@@ -1,31 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Transport.Channels;
using System;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using JT808.Gateway.Services;
using JT808.Gateway.Client;

namespace JT808.Gateway.Handlers
{
/// <summary>
/// JT808客户端处理程序
/// </summary>
internal class JT808TcpClientHandler : SimpleChannelInboundHandler<byte[]>
{
private readonly ILogger<JT808TcpClientHandler> logger;
private readonly JT808ClientReceiveAtomicCounterService jT808ReceiveAtomicCounterService;
public JT808TcpClientHandler(JT808ClientReceiveAtomicCounterService jT808ReceiveAtomicCounterService,JT808TcpClient jT808TcpClient)
{
logger = jT808TcpClient.LoggerFactory.CreateLogger<JT808TcpClientHandler>();
this.jT808ReceiveAtomicCounterService= jT808ReceiveAtomicCounterService;
}

protected override void ChannelRead0(IChannelHandlerContext ctx, byte[] msg)
{
if(logger.IsEnabled(LogLevel.Trace))
logger.LogTrace("accept msg<<<" + ByteBufferUtil.HexDump(msg));
jT808ReceiveAtomicCounterService.MsgSuccessIncrement();
}
}
}

+ 0
- 104
src/JT808.Gateway/Handlers/JT808TcpConnectionHandler.cs 查看文件

@@ -1,104 +0,0 @@
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Channels;
using JT808.Gateway.Session;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;

namespace JT808.Gateway.Handlers
{
/// <summary>
/// JT808服务通道处理程序
/// </summary>
internal class JT808TcpConnectionHandler : ChannelHandlerAdapter
{
private readonly ILogger<JT808TcpConnectionHandler> logger;

private readonly JT808SessionManager jT808SessionManager;

public JT808TcpConnectionHandler(
JT808SessionManager jT808SessionManager,
ILoggerFactory loggerFactory)
{
this.jT808SessionManager = jT808SessionManager;
logger = loggerFactory.CreateLogger<JT808TcpConnectionHandler>();
}

/// <summary>
/// 通道激活
/// </summary>
/// <param name="context"></param>
public override void ChannelActive(IChannelHandlerContext context)
{
string channelId = context.Channel.Id.AsShortText();
if (logger.IsEnabled(LogLevel.Debug))
logger.LogDebug($"<<<{ channelId } Successful client connection to server.");
base.ChannelActive(context);
}

/// <summary>
/// 设备主动断开
/// </summary>
/// <param name="context"></param>
public override void ChannelInactive(IChannelHandlerContext context)
{
string channelId = context.Channel.Id.AsShortText();
if (logger.IsEnabled(LogLevel.Debug))
logger.LogDebug($">>>{ channelId } The client disconnects from the server.");
jT808SessionManager.RemoveSessionByChannel(context.Channel);
base.ChannelInactive(context);
}

/// <summary>
/// 服务器主动断开
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override Task CloseAsync(IChannelHandlerContext context)
{
string channelId = context.Channel.Id.AsShortText();
if (logger.IsEnabled(LogLevel.Debug))
logger.LogDebug($"<<<{ channelId } The server disconnects from the client.");
jT808SessionManager.RemoveSessionByChannel(context.Channel);
return base.CloseAsync(context);
}

public override void ChannelReadComplete(IChannelHandlerContext context)=> context.Flush();

/// <summary>
/// 超时策略
/// </summary>
/// <param name="context"></param>
/// <param name="evt"></param>
public override void UserEventTriggered(IChannelHandlerContext context, object evt)
{
IdleStateEvent idleStateEvent = evt as IdleStateEvent;
if (idleStateEvent != null)
{
if(idleStateEvent.State== IdleState.ReaderIdle)
{
string channelId = context.Channel.Id.AsShortText();
logger.LogInformation($"{idleStateEvent.State.ToString()}>>>{channelId}");
// 由于808是设备发心跳,如果很久没有上报数据,那么就由服务器主动关闭连接。
jT808SessionManager.RemoveSessionByChannel(context.Channel);
context.CloseAsync();
}
// 按照808的消息,有些请求必须要应答,但是转发可以不需要有应答可以节省部分资源包括:
// 1.消息的序列化
// 2.消息的下发
// 都有一定的性能损耗,那么不需要判断写超时 IdleState.WriterIdle
// 就跟神兽貔貅一样。。。
}
base.UserEventTriggered(context, evt);
}

public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
{
string channelId = context.Channel.Id.AsShortText();
logger.LogError(exception,$"{channelId} {exception.Message}" );
jT808SessionManager.RemoveSessionByChannel(context.Channel);
context.CloseAsync();
}
}
}


+ 0
- 77
src/JT808.Gateway/Handlers/JT808TcpServerHandler.cs 查看文件

@@ -1,77 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Transport.Channels;
using JT808.Protocol;
using System;
using Microsoft.Extensions.Logging;
using JT808.Protocol.Exceptions;
using JT808.Gateway.Session;
using JT808.Gateway.Services;
using JT808.Gateway.PubSub;
using JT808.Gateway.Enums;

namespace JT808.Gateway.Handlers
{
/// <summary>
/// JT808服务端处理程序
/// </summary>
internal class JT808TcpServerHandler : SimpleChannelInboundHandler<byte[]>
{
private readonly JT808SessionManager jT808SessionManager;

private readonly JT808AtomicCounterService jT808AtomicCounterService;

private readonly ILogger<JT808TcpServerHandler> logger;

private readonly JT808Serializer JT808Serializer;

private readonly IJT808MsgProducer JT808MsgProducer;

public JT808TcpServerHandler(
IJT808MsgProducer jT808MsgProducer,
IJT808Config jT808Config,
ILoggerFactory loggerFactory,
JT808AtomicCounterServiceFactory jT808AtomicCounterServiceFactory,
JT808SessionManager jT808SessionManager)
{
this.jT808SessionManager = jT808SessionManager;
this.JT808MsgProducer = jT808MsgProducer;
this.jT808AtomicCounterService = jT808AtomicCounterServiceFactory.Create(JT808TransportProtocolType.tcp);
this.JT808Serializer = jT808Config.GetSerializer();
logger = loggerFactory.CreateLogger<JT808TcpServerHandler>();
}

protected override void ChannelRead0(IChannelHandlerContext ctx, byte[] msg)
{
try
{
//解析到头部,然后根据具体的消息Id通过队列去进行消费
//要是一定要解析到数据体可以在JT808MsgIdHandlerBase类中根据具体的消息,
//解析具体的消息体,具体调用JT808Serializer.Deserialize<T>
JT808HeaderPackage jT808HeaderPackage = JT808Serializer.Deserialize<JT808HeaderPackage>(msg);
if (logger.IsEnabled(LogLevel.Trace))
{
logger.LogTrace($"accept package success count=>{jT808AtomicCounterService.MsgSuccessCount.ToString()},accept msg=>{ByteBufferUtil.HexDump(msg)}");
}
jT808AtomicCounterService.MsgSuccessIncrement();
jT808SessionManager.TryAdd(jT808HeaderPackage.Header.TerminalPhoneNo,ctx.Channel);
JT808MsgProducer.ProduceAsync(jT808HeaderPackage.Header.TerminalPhoneNo, msg);
}
catch (JT808Exception ex)
{
jT808AtomicCounterService.MsgFailIncrement();
if (logger.IsEnabled(LogLevel.Error))
{
logger.LogError(ex,$"accept package fail count=>{jT808AtomicCounterService.MsgFailCount.ToString()},accept msg=>{ByteBufferUtil.HexDump(msg)}");
}
}
catch (Exception ex)
{
jT808AtomicCounterService.MsgFailIncrement();
if (logger.IsEnabled(LogLevel.Error))
{
logger.LogError(ex, $"accept package fail count=>{jT808AtomicCounterService.MsgFailCount.ToString()},accept msg=>{ByteBufferUtil.HexDump(msg)}");
}
}
}
}
}

+ 0
- 79
src/JT808.Gateway/Handlers/JT808UdpServerHandler.cs 查看文件

@@ -1,79 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Transport.Channels;
using JT808.Protocol;
using System;
using Microsoft.Extensions.Logging;
using JT808.Gateway.Services;
using JT808.Gateway.Session;
using JT808.Gateway.PubSub;
using JT808.Gateway.Metadata;
using JT808.Gateway.Enums;

namespace JT808.Gateway.Handlers
{
/// <summary>
/// JT808 Udp服务端处理程序
/// </summary>
internal class JT808UdpServerHandler : SimpleChannelInboundHandler<JT808UdpPackage>
{
private readonly JT808AtomicCounterService jT808AtomicCounterService;

private readonly ILogger<JT808UdpServerHandler> logger;

private readonly JT808SessionManager jT808UdpSessionManager;

private readonly JT808Serializer JT808Serializer;

private readonly IJT808MsgProducer JT808MsgProducer;

public JT808UdpServerHandler(
IJT808MsgProducer jT808MsgProducer,
IJT808Config jT808Config,
ILoggerFactory loggerFactory,
JT808AtomicCounterServiceFactory jT808AtomicCounterServiceFactory,
JT808SessionManager jT808UdpSessionManager)
{
this.JT808MsgProducer = jT808MsgProducer;
this.jT808AtomicCounterService = jT808AtomicCounterServiceFactory.Create(JT808TransportProtocolType.udp);
this.jT808UdpSessionManager = jT808UdpSessionManager;
logger = loggerFactory.CreateLogger<JT808UdpServerHandler>();
JT808Serializer = jT808Config.GetSerializer();
}

protected override void ChannelRead0(IChannelHandlerContext ctx, JT808UdpPackage msg)
{
try
{
//解析到头部,然后根据具体的消息Id通过队列去进行消费
//要是一定要解析到数据体可以在JT808MsgIdHandlerBase类中根据具体的消息,
//解析具体的消息体,具体调用JT808Serializer.Deserialize<T>
JT808HeaderPackage jT808HeaderPackage = JT808Serializer.Deserialize<JT808HeaderPackage>(msg.Buffer);
if (logger.IsEnabled(LogLevel.Trace))
{
logger.LogTrace($"accept package success count=>{jT808AtomicCounterService.MsgFailCount.ToString()},accept msg=>{ByteBufferUtil.HexDump(msg.Buffer)}");
}
jT808AtomicCounterService.MsgSuccessIncrement();
jT808UdpSessionManager.TryAdd(ctx.Channel, msg.Sender, jT808HeaderPackage.Header.TerminalPhoneNo);
JT808MsgProducer.ProduceAsync(jT808HeaderPackage.Header.TerminalPhoneNo, msg.Buffer);
}
catch (JT808.Protocol.Exceptions.JT808Exception ex)
{
jT808AtomicCounterService.MsgFailIncrement();
if (logger.IsEnabled(LogLevel.Error))
{
logger.LogError(ex, $"accept package fail count=>{jT808AtomicCounterService.MsgFailCount.ToString()},accept msg=>{ByteBufferUtil.HexDump(msg.Buffer)}");
}
}
catch (Exception ex)
{
jT808AtomicCounterService.MsgFailIncrement();
if (logger.IsEnabled(LogLevel.Error))
{
logger.LogError(ex, $"accept package fail count=>{jT808AtomicCounterService.MsgFailCount.ToString()},accept msg=>{ByteBufferUtil.HexDump(msg.Buffer)}");
}
}
}

public override void ChannelReadComplete(IChannelHandlerContext context) => context.Flush();
}
}

+ 0
- 14
src/JT808.Gateway/IJT808ClientBuilder.cs 查看文件

@@ -1,14 +0,0 @@
using JT808.Protocol;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT808.Gateway
{
public interface IJT808ClientBuilder
{
IJT808Builder JT808Builder { get; }
IJT808Builder Builder();
}
}

+ 0
- 14
src/JT808.Gateway/IJT808GatewayBuilder.cs 查看文件

@@ -1,14 +0,0 @@
using JT808.Protocol;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT808.Gateway
{
public interface IJT808GatewayBuilder
{
IJT808Builder JT808Builder { get; }
IJT808Builder Builder();
}
}

+ 0
- 18
src/JT808.Gateway/Impls/JT808DatagramPacketImpl.cs 查看文件

@@ -1,18 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Transport.Channels.Sockets;
using JT808.Gateway.Interfaces;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;

namespace JT808.Gateway.Impls
{
class JT808DatagramPacketImpl : IJT808DatagramPacket
{
public DatagramPacket Create(byte[] message, EndPoint recipient)
{
return new DatagramPacket(Unpooled.WrappedBuffer(message), recipient);
}
}
}

+ 0
- 25
src/JT808.Gateway/Impls/JT808GatewayBuilderDefault.cs 查看文件

@@ -1,25 +0,0 @@
using JT808.Gateway;
using JT808.Protocol;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT808.Gateway.Impls
{
internal class JT808GatewayBuilderDefault : IJT808GatewayBuilder
{
public IJT808Builder JT808Builder { get; }

public JT808GatewayBuilderDefault(IJT808Builder builder)
{
JT808Builder = builder;
}

public IJT808Builder Builder()
{
return JT808Builder;
}
}
}

部分文件因文件數量過多而無法顯示

Loading…
取消
儲存