Просмотр исходного кода

1.修改原包分发器消息提示

2.增加项目文档描述
tags/v1.0.0
SmallChi 6 лет назад
Родитель
Сommit
e3c8f887e2
13 измененных файлов: 364 добавлений и 23 удалений
  1. +328
    -6
      README.md
  2. +1
    -6
      src/JT808.DotNetty.Hosting/JT808MsgIdCustomHandler.cs
  3. +0
    -2
      src/JT808.DotNetty.Hosting/Program.cs
  4. +1
    -1
      src/JT808.DotNetty/Interfaces/IJT808SessionService.cs
  5. +8
    -7
      src/JT808.DotNetty/Internal/JT808SourcePackageDispatcherDefaultImpl.cs
  6. +8
    -0
      src/JT808.DotNetty/JT808.DotNetty.csproj
  7. +2
    -1
      src/JT808.DotNetty/JT808WebAPIService.cs
  8. +16
    -0
      src/doc/README.md
  9. Двоичные данные
      src/doc/img/design_model.png
  10. Двоичные данные
      src/doc/img/performance_1000.png
  11. Двоичные данные
      src/doc/img/performance_10000.png
  12. Двоичные данные
      src/doc/img/performance_2000.png
  13. Двоичные данные
      src/doc/img/performance_5000.png

+ 328
- 6
README.md Просмотреть файл

@@ -2,24 +2,346 @@

基于DotNetty封装的JT808DotNetty专注消息业务处理

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

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

[玩一玩压力测试](https://github.com/SmallChi/JT808DotNetty/blob/master/doc/README.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)

## NuGet安装

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

## 集成功能实现

### 1.集成原包分发器

| 功能 | 说明 | 使用场景 |
|:-------:|:-------:|:-------:|
| ISourcePackageDispatcher | 原包分发器(支持热更新) | 需要将源数据转给其他平台 |
| ISourcePackageDispatcher | 原包分发器(支持热更新、断线重连) | 需要将原数据转给其他平台 |

### 2.集成WebApi服务器(默认端口828)
### 2.集成WebApi服务器

#### 2.1.统一下发设备消息服务 IJT808UnificationSendService
#### [2.1.统一下发设备消息服务 IJT808UnificationSendService](#send)

#### 2.2.管理会话服务 IJT808SessionService
#### [2.2.管理会话服务 IJT808SessionService](#session)

#### 2.3.消息包计数服务 JT808AtomicCounterService
#### [2.3.消息包计数服务 JT808AtomicCounterService 接口尚未实现](#counter)

### 3.集成业务消息处理程序

| 功能 | 说明 | 使用场景 |
|:-------:|:-------:|:-------:|
| JT808MsgIdHandlerBase | 业务消息处理程序 | 需要自定义实现业务消息处理程序 |
| JT808MsgIdHandlerBase | 业务消息处理程序 | 需要自定义实现业务消息处理程序 |

### 举个栗子1

#### 1.实现业务消息处理程序JT808MsgIdHandlerBase

```business Impl
using JT808.DotNetty;
public class JT808MsgIdCustomHandler : JT808MsgIdHandlerBase
{
private readonly ILogger<JT808MsgIdCustomHandler> logger;

public JT808MsgIdCustomHandler(ILoggerFactory loggerFactory,
JT808SessionManager sessionManager) : base(sessionManager)
{
logger = loggerFactory.CreateLogger<JT808MsgIdCustomHandler>();
}

public override JT808Response Msg0x0102(JT808Request request)
{
logger.LogDebug("Msg0x0102");
return base.Msg0x0102(request);
}
}

```
#### 2.自定义业务消息处理程序替换默认实现

```
services.Replace(new ServiceDescriptor(typeof(JT808MsgIdHandlerBase), typeof(JT808MsgIdCustomHandler), ServiceLifetime.Singleton));
```
#### 3.使用JT808 Host

``` host
UseJT808Host()
```

#### 4.完整示例
``` demo
// 默认网关端口:808
// 默认webapi端口:828
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) =>
{
logging.AddConsole();
logging.SetMinimumLevel(LogLevel.Error);
})
.ConfigureServices((hostContext, services) =>
{
services.AddSingleton<ILoggerFactory, LoggerFactory>();
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
services.Replace(new ServiceDescriptor(typeof(JT808MsgIdHandlerBase), typeof(JT808MsgIdCustomHandler), ServiceLifetime.Singleton));
})
.UseJT808Host();
await serverHostBuilder.RunConsoleAsync();
}
```

## 提供WebApi接口服务(默认端口828)

基地址:<a href="#">http://localhost:828/jt808api/</a>
数据格式:只支持Json格式

#### 统一对象返回 JT808ResultDto\<T>

|属性|数据类型|参数说明|
|:------:|:------:|:------|
| Message| string| 消息描述|
| Code| int| 状态码|
| Data| T(泛型)| 数据|

返回Code[状态码]说明:
|状态码|说明|
|:------:|:------:|
| 200 | 返回成功 |
| 201 | 内容为空 |
| 404 | 没有该服务 |
| 500 | 服务内部错误 |

#### <span id="send">统一下发设备消息接口</span>

请求地址:UnificationSend
请求方式:POST
请求参数:
|属性|数据类型|参数说明|
|:------:|:------:|:------|
| TerminalPhoneNo| string| 设备终端号|
| Data| byte[]| JT808 byte[]数组|
返回数据:
|属性|数据类型|参数说明|
|:------:|:------:|:------|
| Data| bool| 是否成功|
返回结果:
``` result1
{
"Message":"",
"Code":200,
"Data":true
}
```
#### <span id="session">会话服务接口</span>

##### 统一会话信息对象返回 JT808SessionInfoDto

|属性|数据类型|参数说明|
|:------:|:------:|:------|
| ChannelId| string| 通道Id|
| LastActiveTime| DateTime| 最后上线时间|
| StartTime| DateTime| 上线时间|
| TerminalPhoneNo|string| 终端手机号|

##### 1.获取实际连接数(存在其他平台转发过来的数据,这时候通道Id和设备属于一对多的关系)

请求地址:Session/GetRealLinkCount
请求方式:GET
返回数据:
|属性|数据类型|参数说明|
|:------:|:------:|:------|
| Data| int| 实际连接数|
返回结果:
``` result1
{
"Message":"",
"Code":200,
"Data":10
}
```
##### 2.获取设备相关连的连接数

请求地址:Session/GetRelevanceLinkCount
请求方式:GET
返回数据:
|属性|数据类型|参数说明|
|:------:|:------:|:------|
| Data| int | 设备相关连的连接数 |
返回结果:
``` result2
{
"Message":"",
"Code":200,
"Data":10
}
```
##### 3.获取实际会话集合

请求地址:Session/GetRealAll
请求方式:GET
返回数据:
|属性|数据类型|参数说明|
|:------:|:------:|:------|
| Data| List\<JT808SessionInfoDto> | 实际会话信息集合 |
返回结果:
``` result3
{
"Message":"",
"Code":200,
"Data":[
{
"ChannelId":"eadad23",
"LastActiveTime":"2018-11-27 20:00:00",
"StartTime":"2018-11-25 20:00:00",
"TerminalPhoneNo":"123456789012"
},{
"ChannelId":"eadad23",
"LastActiveTime":"2018-11-27 20:00:00",
"StartTime":"2018-11-25 20:00:00",
"TerminalPhoneNo":"123456789013"
}
]
}
```
##### 4.获取设备相关联会话集合

请求地址:Session/GetRelevanceAll
请求方式:GET
返回数据:
|属性|数据类型|参数说明|
|:------:|:------:|:------|
| Data| List\<JT808SessionInfoDto> | 设备相关联会话信息集合 |
返回结果:
``` result4
{
"Message":"",
"Code":200,
"Data":[
{
"ChannelId":"eadad23",
"LastActiveTime":"2018-11-27 20:00:00",
"StartTime":"2018-11-25 20:00:00",
"TerminalPhoneNo":"123456789012"
}, {
"ChannelId":"eadad24",
"LastActiveTime":"2018-11-26 20:00:00",
"StartTime":"2018-11-22 20:00:00",
"TerminalPhoneNo":"123456789013"
}
]
}
```

##### 5.通过通道Id移除对应会话

请求地址:Session/RemoveByChannelId
请求方式:POST
请求参数:
|属性|数据类型|参数说明|
|:------:|:------:|:------|
| channelId| string| 通道Id|
返回数据:
|属性|数据类型|参数说明|
|:------:|:------:|:------|
| Data| bool | 是否成功 |
返回结果:
``` result5
{
"Message":"",
"Code":200,
"Data":true
}
```
##### 6.通过设备终端号移除对应会话

请求地址:Session/RemoveByTerminalPhoneNo
请求方式:POST
请求参数:
|属性|数据类型|参数说明|
|:------:|:------:|:------|
| terminalPhoneNo| string| 设备终端号|
返回数据:
|属性|数据类型|参数说明|
|:------:|:------:|:------|
| Data| bool | 是否成功 |
返回结果:
``` result6
{
"Message":"",
"Code":200,
"Data":true
}
```
##### 7.通过通道Id获取会话信息

请求地址:Session/GetByChannelId
请求方式:POST
请求参数:
|属性|数据类型|参数说明|
|:------:|:------:|:------|
| channelId| string| 通道Id|
返回数据:
|属性|数据类型|参数说明|
|:------:|:------:|:------|
| Data| JT808SessionInfoDto | 会话信息对象 |
返回结果:
``` result7
{
"Message":"",
"Code":200,
"Data":{
"ChannelId":"eadad24",
"LastActiveTime":"2018-11-26 20:00:00",
"StartTime":"2018-11-22 20:00:00",
"TerminalPhoneNo":"123456789013"
}
}
```

##### 8.通过设备终端号获取会话信息

请求地址:Session/GetByTerminalPhoneNo
请求方式:POST
请求参数:
|属性|数据类型|参数说明|
|:------:|:------:|:------|
| terminalPhoneNo| string| 设备终端号|
返回数据:
|属性|数据类型|参数说明|
|:------:|:------:|:------|
| Data| JT808SessionInfoDto | 会话信息对象 |
返回结果:
``` result8
{
"Message":"",
"Code":200,
"Data":{
"ChannelId":"eadad24",
"LastActiveTime":"2018-11-26 20:00:00",
"StartTime":"2018-11-22 20:00:00",
"TerminalPhoneNo":"123456789013"
}
}
```

+ 1
- 6
src/JT808.DotNetty.Hosting/JT808MsgIdCustomHandler.cs Просмотреть файл

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using DotNetty.Transport.Channels;
using JT808.DotNetty.Metadata;
using JT808.Protocol;
using JT808.DotNetty.Metadata;
using Microsoft.Extensions.Logging;

namespace JT808.DotNetty.Hosting


+ 0
- 2
src/JT808.DotNetty.Hosting/Program.cs Просмотреть файл

@@ -15,8 +15,6 @@ namespace JT808.DotNetty.Hosting
{
static async Task Main(string[] args)
{
//7E 01 02 00 06 01 38 12 34 56 78 00 85 32 31 31 33 31 33 B2 7E

var serverHostBuilder = new HostBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{


+ 1
- 1
src/JT808.DotNetty/Interfaces/IJT808SessionService.cs Просмотреть файл

@@ -26,7 +26,7 @@ namespace JT808.DotNetty.Interfaces
/// <returns></returns>
JT808ResultDto<List<JT808SessionInfoDto>> GetRealAll();
/// <summary>
/// 获取设备相关会话集合
/// 获取设备相关会话集合
/// </summary>
/// <returns></returns>
JT808ResultDto<List<JT808SessionInfoDto>> GetRelevanceAll();


+ 8
- 7
src/JT808.DotNetty/Internal/JT808SourcePackageDispatcherDefaultImpl.cs Просмотреть файл

@@ -52,12 +52,12 @@ namespace JT808.DotNetty.Internal
}
else
{
logger.LogError($"{item}链接已关闭");
logger.LogInformation($"{item} link closed.");
}
}
catch (Exception ex)
{
logger.LogError($"{item}发送数据出现异常:{ex}");
logger.LogError(ex,$"{item} Send Data Error.");
}
}
await Task.CompletedTask;
@@ -83,7 +83,8 @@ namespace JT808.DotNetty.Internal
DelRemoteServsers(chgRemoteServers);
AddRemoteServsers(chgRemoteServers);
});
if (jT808ConfigurationOptionsMonitor.CurrentValue.SourcePackageDispatcherClientConfigurations != null && jT808ConfigurationOptionsMonitor.CurrentValue.SourcePackageDispatcherClientConfigurations.Count > 0)
if (jT808ConfigurationOptionsMonitor.CurrentValue.SourcePackageDispatcherClientConfigurations != null &&
jT808ConfigurationOptionsMonitor.CurrentValue.SourcePackageDispatcherClientConfigurations.Count > 0)
{
foreach (var item in jT808ConfigurationOptionsMonitor.CurrentValue.SourcePackageDispatcherClientConfigurations)
{
@@ -93,12 +94,12 @@ namespace JT808.DotNetty.Internal
{
IChannel clientChannel = await bootstrap.ConnectAsync(item.EndPoint);
channels.TryAdd(item.EndPoint, clientChannel);
logger.LogInformation($"初始化链接远程服务端{item.EndPoint.ToString()}");
logger.LogInformation($"init remote link {item.EndPoint.ToString()}.");
});
}
catch (Exception ex)
{
logger.LogError($"初始化链接远程服务端{item},链接异常:{ex}");
logger.LogError(ex,$"there is an exception in sending data {item}.");
}
}
}
@@ -156,11 +157,11 @@ namespace JT808.DotNetty.Internal
{
IChannel clientChannel =await bootstrap.ConnectAsync(item);
channels.TryAdd(item, clientChannel);
logger.LogInformation($"变更后链接远程服务端{item}");
logger.LogInformation($"link to the remote server after the change {item}.");
}
catch (Exception ex)
{
logger.LogError(ex,$"重连异常变更后链接远程服务端{item}");
logger.LogError(ex,$"reconnect the remote server after the exception changes {item}.");
}
}
}


+ 8
- 0
src/JT808.DotNetty/JT808.DotNetty.csproj Просмотреть файл

@@ -17,6 +17,14 @@
<Version>1.0.0</Version>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile></DocumentationFile>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DocumentationFile>E:\koike\My Project\JT808DotNetty\src\JT808.DotNetty\JT808.DotNetty.xml</DocumentationFile>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="DotNetty.Codecs" Version="0.6.0" />
<PackageReference Include="DotNetty.Codecs.Http" Version="0.6.0" />


+ 2
- 1
src/JT808.DotNetty/JT808WebAPIService.cs Просмотреть файл

@@ -60,7 +60,8 @@ namespace JT808.DotNetty
}

/// <summary>
/// 会话服务-获取真实连接数
/// 会话服务-获取实际连接数
/// 存在其他平台转发过来的数据,这时候通道Id和设备属于一对多的关系
/// </summary>
/// <param name="request"></param>
/// <returns></returns>


+ 16
- 0
src/doc/README.md Просмотреть файл

@@ -0,0 +1,16 @@
## 压力测试

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

| 操作系统 | 配置 | 使用 |
|:-------:|:-------:|:-------:|
| win server 2018 | 4c8g | 压力测试客户端 |
| centos7 | 4c8g | JT808服务端 |

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

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

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

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

Двоичные данные
src/doc/img/design_model.png Просмотреть файл

До После
Ширина: 674  |  Высота: 401  |  Размер: 38 KiB

Двоичные данные
src/doc/img/performance_1000.png Просмотреть файл

До После
Ширина: 957  |  Высота: 676  |  Размер: 130 KiB

Двоичные данные
src/doc/img/performance_10000.png Просмотреть файл

До После
Ширина: 962  |  Высота: 680  |  Размер: 156 KiB

Двоичные данные
src/doc/img/performance_2000.png Просмотреть файл

До После
Ширина: 964  |  Высота: 681  |  Размер: 136 KiB

Двоичные данные
src/doc/img/performance_5000.png Просмотреть файл

До После
Ширина: 958  |  Высота: 683  |  Размер: 153 KiB

Загрузка…
Отмена
Сохранить