diff --git a/README.md b/README.md index 63746da..a499e1d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# JT808DotNetty +# JT808DotNetty 基于DotNetty封装的JT808DotNetty专注消息业务处理 @@ -21,12 +21,6 @@ ![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.集成原包分发器 @@ -53,8 +47,7 @@ #### 1.实现业务消息处理程序JT808MsgIdHandlerBase -```business Impl -using JT808.DotNetty; +```business Imp public class JT808MsgIdCustomHandler : JT808MsgIdHandlerBase { private readonly ILogger logger; @@ -172,50 +165,13 @@ static async Task Main(string[] args) | LastActiveTime| DateTime| 最后上线时间| | StartTime| DateTime| 上线时间| | TerminalPhoneNo|string| 终端手机号| +| LoaclAddressIP| string| 本地ip地址| +| WebApiPort| string| WebApi端口号| +| RemoteAddressIP| string| 远程ip地址| -##### 1.获取实际连接数(存在其他平台转发过来的数据,这时候通道Id和设备属于一对多的关系) - -请求地址:Session/GetRealLinkCount - -请求方式:GET - -返回数据: - -|属性|数据类型|参数说明| -|:------:|:------:|:------| -| Data| int| 实际连接数| - -返回结果: -``` result1 -{ - "Message":"", - "Code":200, - "Data":10 -} -``` -##### 2.获取设备相关连的连接数 +##### 1.获取会话集合 -请求地址:Session/GetRelevanceLinkCount - -请求方式:GET - -返回数据: - -|属性|数据类型|参数说明| -|:------:|:------:|:------| -| Data| int | 设备相关连的连接数 | - -返回结果: -``` result2 -{ - "Message":"", - "Code":200, - "Data":10 -} -``` -##### 3.获取实际会话集合 - -请求地址:Session/GetRealAll +请求地址:Session/GetAll 请求方式:GET @@ -226,7 +182,7 @@ static async Task Main(string[] args) | Data| List\ | 实际会话信息集合 | 返回结果: -``` result3 +``` session1 { "Message":"", "Code":200, @@ -235,50 +191,23 @@ static async Task Main(string[] args) "ChannelId":"eadad23", "LastActiveTime":"2018-11-27 20:00:00", "StartTime":"2018-11-25 20:00:00", - "TerminalPhoneNo":"123456789012" + "TerminalPhoneNo":"123456789012", + "LoaclAddressIP":"127.0.0.1:808", + "WebApiPort":828, + "RemoteAddressIP":"127.0.0.1:11808" },{ "ChannelId":"eadad23", "LastActiveTime":"2018-11-27 20:00:00", "StartTime":"2018-11-25 20:00:00", - "TerminalPhoneNo":"123456789013" + "TerminalPhoneNo":"123456789013", + "LoaclAddressIP":"127.0.0.1:808", + "WebApiPort":828, + "RemoteAddressIP":"127.0.0.1:11808" } ] } ``` -##### 4.获取设备相关联会话集合 - -请求地址:Session/GetRelevanceAll - -请求方式:GET - -返回数据: - -|属性|数据类型|参数说明| -|:------:|:------:|:------| -| Data| List\ | 设备相关联会话信息集合 | - -返回结果: -``` 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移除对应会话 +##### 2.通过通道Id移除对应会话 请求地址:Session/RemoveByChannelId @@ -297,14 +226,14 @@ static async Task Main(string[] args) | Data| bool | 是否成功 | 返回结果: -``` result5 +``` session2 { "Message":"", "Code":200, "Data":true } ``` -##### 6.通过设备终端号移除对应会话 +##### 3.通过设备终端号移除对应会话 请求地址:Session/RemoveByTerminalPhoneNo @@ -323,73 +252,10 @@ static async Task Main(string[] args) | Data| bool | 是否成功 返回结果: -``` result6 +``` session3 { "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" - } -} -``` diff --git a/src/JT808.DotNetty.Dashbord.sln b/src/JT808.DotNetty.Dashbord.sln new file mode 100644 index 0000000..be58372 --- /dev/null +++ b/src/JT808.DotNetty.Dashbord.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28010.2050 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.DotNetty.Dashbord", "JT808.DotNetty.Dashbord\JT808.DotNetty.Dashbord.csproj", "{3A9698C3-CEBB-4C93-A40C-3F7FE650217C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3A9698C3-CEBB-4C93-A40C-3F7FE650217C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3A9698C3-CEBB-4C93-A40C-3F7FE650217C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3A9698C3-CEBB-4C93-A40C-3F7FE650217C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3A9698C3-CEBB-4C93-A40C-3F7FE650217C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0DDBE27F-708F-46DC-837F-BEF34A50A0B1} + EndGlobalSection +EndGlobal diff --git a/src/JT808.DotNetty.Dashbord/Configurations/JT808Options.cs b/src/JT808.DotNetty.Dashbord/Configurations/JT808Options.cs new file mode 100644 index 0000000..0a67c19 --- /dev/null +++ b/src/JT808.DotNetty.Dashbord/Configurations/JT808Options.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace JT808.DotNetty.Dashbord.Configurations +{ + public class JT808Options + { + /// + /// 接口服务地址 + /// + public List WebApiHosts { get; set; } + } +} diff --git a/src/JT808.DotNetty.Dashbord/Controllers/JT808UnificationSendController.cs b/src/JT808.DotNetty.Dashbord/Controllers/JT808UnificationSendController.cs new file mode 100644 index 0000000..b8a2904 --- /dev/null +++ b/src/JT808.DotNetty.Dashbord/Controllers/JT808UnificationSendController.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; + +namespace JT808.DotNetty.Dashbord.Controllers +{ + /// + /// 统一信息下发 + /// + [Route("jt808webapi/UnificationSend")] + [ApiController] + public class JT808UnificationSendController : ControllerBase + { + // GET api/values + [HttpGet] + public ActionResult> Get() + { + return new string[] { "value1", "value2" }; + } + + // GET api/values/5 + [HttpGet("{id}")] + public ActionResult Get(int id) + { + return "value"; + } + + // POST api/values + [HttpPost] + public void Post([FromBody] string value) + { + } + + // PUT api/values/5 + [HttpPut("{id}")] + public void Put(int id, [FromBody] string value) + { + } + + // DELETE api/values/5 + [HttpDelete("{id}")] + public void Delete(int id) + { + } + } +} diff --git a/src/JT808.DotNetty.Dashbord/Dtos/JT808ResultDto.cs b/src/JT808.DotNetty.Dashbord/Dtos/JT808ResultDto.cs new file mode 100644 index 0000000..cd3bdd7 --- /dev/null +++ b/src/JT808.DotNetty.Dashbord/Dtos/JT808ResultDto.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.DotNetty.Dashbord.Dtos +{ + public class JT808ResultDto + { + public string Message { get; set; } + + public int Code { get; set; } + + public T Data { get; set; } + } +} diff --git a/src/JT808.DotNetty.Dashbord/Dtos/JT808SessionInfoDto.cs b/src/JT808.DotNetty.Dashbord/Dtos/JT808SessionInfoDto.cs new file mode 100644 index 0000000..4759581 --- /dev/null +++ b/src/JT808.DotNetty.Dashbord/Dtos/JT808SessionInfoDto.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.DotNetty.Dashbord.Dtos +{ + public class JT808SessionInfoDto + { + /// + /// 通道Id + /// + public string ChannelId { get; set; } + /// + /// 最后上线时间 + /// + public DateTime LastActiveTime { get; set; } + /// + /// 上线时间 + /// + public DateTime StartTime { get; set; } + /// + /// 终端手机号 + /// + public string TerminalPhoneNo { get; set; } + /// + /// 本地ip地址 + /// + public string LoaclAddressIP { get; set; } + /// + /// WebApi端口号 + /// + public int WebApiPort { get; set; } + /// + /// 远程ip地址 + /// + public string RemoteAddressIP { get; set; } + } +} diff --git a/src/JT808.DotNetty.Dashbord/Dtos/JT808UnificationSendRequestDto.cs b/src/JT808.DotNetty.Dashbord/Dtos/JT808UnificationSendRequestDto.cs new file mode 100644 index 0000000..5987dfa --- /dev/null +++ b/src/JT808.DotNetty.Dashbord/Dtos/JT808UnificationSendRequestDto.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT808.DotNetty.Dashbord.Dtos +{ + /// + /// 统一下发请求参数 + /// + public class JT808UnificationSendRequestDto + { + public string TerminalPhoneNo { get; set; } + public byte[] Data { get; set; } + } +} diff --git a/src/JT808.DotNetty.Dashbord/JT808.DotNetty.Dashbord.csproj b/src/JT808.DotNetty.Dashbord/JT808.DotNetty.Dashbord.csproj new file mode 100644 index 0000000..ffe2b91 --- /dev/null +++ b/src/JT808.DotNetty.Dashbord/JT808.DotNetty.Dashbord.csproj @@ -0,0 +1,16 @@ + + + + netcoreapp2.1 + + + + + + + + + + + + diff --git a/src/JT808.DotNetty.Dashbord/Program.cs b/src/JT808.DotNetty.Dashbord/Program.cs new file mode 100644 index 0000000..181342b --- /dev/null +++ b/src/JT808.DotNetty.Dashbord/Program.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; + +namespace JT808.DotNetty.Dashbord +{ + public class Program + { + public static void Main(string[] args) + { + CreateWebHostBuilder(args).Build().Run(); + } + + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseStartup(); + } +} diff --git a/src/JT808.DotNetty.Dashbord/Startup.cs b/src/JT808.DotNetty.Dashbord/Startup.cs new file mode 100644 index 0000000..bd3750f --- /dev/null +++ b/src/JT808.DotNetty.Dashbord/Startup.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace JT808.DotNetty.Dashbord +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseMvc(); + } + } +} diff --git a/src/JT808.DotNetty.Dashbord/appsettings.Development.json b/src/JT808.DotNetty.Dashbord/appsettings.Development.json new file mode 100644 index 0000000..e203e94 --- /dev/null +++ b/src/JT808.DotNetty.Dashbord/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/src/JT808.DotNetty.Dashbord/appsettings.json b/src/JT808.DotNetty.Dashbord/appsettings.json new file mode 100644 index 0000000..def9159 --- /dev/null +++ b/src/JT808.DotNetty.Dashbord/appsettings.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/src/JT808.DotNetty.Test/JT808SessionManagerTest.cs b/src/JT808.DotNetty.Test/JT808SessionManagerTest.cs index d722d52..95c7c2b 100644 --- a/src/JT808.DotNetty.Test/JT808SessionManagerTest.cs +++ b/src/JT808.DotNetty.Test/JT808SessionManagerTest.cs @@ -63,8 +63,7 @@ namespace JT808.DotNetty.Test [Fact] public void Test8() { - var realSessionInfos = jT808SessionManager.GetRealAll(); - var relevanceSessionInfos = jT808SessionManager.GetRelevanceAll(); + var realSessionInfos = jT808SessionManager.GetAll(); } [Fact] diff --git a/src/JT808.DotNetty.Test/JT808WebAPIServiceTest.cs b/src/JT808.DotNetty.Test/JT808WebAPIServiceTest.cs index 4544f7c..f8fd2fa 100644 --- a/src/JT808.DotNetty.Test/JT808WebAPIServiceTest.cs +++ b/src/JT808.DotNetty.Test/JT808WebAPIServiceTest.cs @@ -41,155 +41,45 @@ namespace JT808.DotNetty.Test } [Fact] - public void GetRealLinkCountTest() + public void GetAllTest() { - var result = httpClient.GetAsync($"{Url}/{sessionRoutePrefix}/GetRealLinkCount").Result; - string content = result.Content.ReadAsStringAsync().Result; - JT808ResultDto jt808Result = JsonConvert.DeserializeObject>(content); - Assert.Equal(200, jt808Result.Code); - Assert.Equal(1,jt808Result.Data); - } - - [Fact] - public void GetRelevanceLinkCountTest() - { - var result = httpClient.GetAsync($"{Url}/{sessionRoutePrefix}/GetRelevanceLinkCount").Result; - string content = result.Content.ReadAsStringAsync().Result; - JT808ResultDto jt808Result = JsonConvert.DeserializeObject>(content); - Assert.Equal(200, jt808Result.Code); - Assert.Equal(length, jt808Result.Data); - } - - [Fact] - public void GetRealAllTest() - { - var result = httpClient.GetAsync($"{Url}/{sessionRoutePrefix}/GetRealAll").Result; + var result = httpClient.GetAsync($"{Url}/{sessionRoutePrefix}/GetAll").Result; string content = result.Content.ReadAsStringAsync().Result; JT808ResultDto> jt808Result = JsonConvert.DeserializeObject>>(content); Assert.Equal(200, jt808Result.Code); Assert.Single(jt808Result.Data); } - [Fact] - public void GetRelevanceAllTest() - { - var result = httpClient.GetAsync($"{Url}/{sessionRoutePrefix}/GetRelevanceAll").Result; - string content = result.Content.ReadAsStringAsync().Result; - JT808ResultDto> jt808Result = JsonConvert.DeserializeObject>>(content); - Assert.Equal(200, jt808Result.Code); - Assert.Equal(length,jt808Result.Data.Count()); - } - [Fact] public void RemoveByChannelIdTest() { - var result1 = httpClient.GetAsync($"{Url}/{sessionRoutePrefix}/GetRelevanceLinkCount").Result; - string content1 = result1.Content.ReadAsStringAsync().Result; - JT808ResultDto jt808Result1 = JsonConvert.DeserializeObject>(content1); - Assert.Equal(200, jt808Result1.Code); - Assert.Equal(length, jt808Result1.Data); - // 心跳会话包 JT808Package jT808Package1 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("99"); SimpleTcpClient.WriteAsync(JT808Serializer.Serialize(jT808Package1)); - var result2 = httpClient.GetAsync($"{Url}/{sessionRoutePrefix}/GetRelevanceLinkCount").Result; - string content2 = result2.Content.ReadAsStringAsync().Result; - JT808ResultDto jt808Result2 = JsonConvert.DeserializeObject>(content2); - Assert.Equal(200, jt808Result2.Code); - Assert.Equal(length + 1, jt808Result2.Data); - - var result3 = httpClient.PostAsync($"{Url}/{sessionRoutePrefix}/GetByTerminalPhoneNo", new StringContent("99")).Result; - string content3 = result3.Content.ReadAsStringAsync().Result; - - JT808ResultDto jt808Result3 = JsonConvert.DeserializeObject>(content3); - Assert.Equal(200, jt808Result3.Code); - Assert.Equal("99", jt808Result3.Data.TerminalPhoneNo); - - var result4 = httpClient.PostAsync($"{Url}/{sessionRoutePrefix}/RemoveByChannelId", new StringContent(jt808Result3.Data.ChannelId)).Result; + var result4 = httpClient.PostAsync($"{Url}/{sessionRoutePrefix}/RemoveByChannelId", new StringContent("")).Result; string content4 = result4.Content.ReadAsStringAsync().Result; JT808ResultDto jt808Result4= JsonConvert.DeserializeObject>(content4); Assert.Equal(200, jt808Result4.Code); Assert.True(jt808Result4.Data); - - var result5 = httpClient.GetAsync($"{Url}/{sessionRoutePrefix}/GetRelevanceLinkCount").Result; - string content5 = result5.Content.ReadAsStringAsync().Result; - JT808ResultDto jt808Result5 = JsonConvert.DeserializeObject>(content5); - Assert.Equal(200, jt808Result5.Code); - Assert.Equal(length, jt808Result5.Data); } [Fact] public void RemoveByTerminalPhoneNoTest() { - var result1 = httpClient.GetAsync($"{Url}/{sessionRoutePrefix}/GetRelevanceLinkCount").Result; - string content1 = result1.Content.ReadAsStringAsync().Result; - JT808ResultDto jt808Result1 = JsonConvert.DeserializeObject>(content1); - Assert.Equal(200, jt808Result1.Code); - Assert.Equal(length, jt808Result1.Data); - // 心跳会话包 JT808Package jT808Package1 = JT808.Protocol.Enums.JT808MsgId.终端心跳.Create("999"); SimpleTcpClient.WriteAsync(JT808Serializer.Serialize(jT808Package1)); - var result2 = httpClient.GetAsync($"{Url}/{sessionRoutePrefix}/GetRelevanceLinkCount").Result; - string content2 = result2.Content.ReadAsStringAsync().Result; - JT808ResultDto jt808Result2 = JsonConvert.DeserializeObject>(content2); - Assert.Equal(200, jt808Result2.Code); - Assert.Equal(length + 1, jt808Result2.Data); - - var result3 = httpClient.PostAsync($"{Url}/{sessionRoutePrefix}/GetByTerminalPhoneNo", new StringContent("999")).Result; - string content3 = result3.Content.ReadAsStringAsync().Result; - - JT808ResultDto jt808Result3 = JsonConvert.DeserializeObject>(content3); - Assert.Equal(200, jt808Result3.Code); - Assert.Equal("999", jt808Result3.Data.TerminalPhoneNo); var result4 = httpClient.PostAsync($"{Url}/{sessionRoutePrefix}/RemoveByTerminalPhoneNo", new StringContent("999")).Result; string content4 = result4.Content.ReadAsStringAsync().Result; JT808ResultDto jt808Result4 = JsonConvert.DeserializeObject>(content4); Assert.Equal(200, jt808Result4.Code); Assert.True(jt808Result4.Data); - - var result5 = httpClient.GetAsync($"{Url}/{sessionRoutePrefix}/GetRelevanceLinkCount").Result; - string content5 = result5.Content.ReadAsStringAsync().Result; - JT808ResultDto jt808Result5 = JsonConvert.DeserializeObject>(content5); - Assert.Equal(200, jt808Result5.Code); - Assert.Equal(length, jt808Result5.Data); - } - - [Fact] - public void GetByChannelIdTest() - { - var result = httpClient.GetAsync($"{Url}/{sessionRoutePrefix}/GetRealAll").Result; - string content = result.Content.ReadAsStringAsync().Result; - JT808ResultDto> jt808Result1 = JsonConvert.DeserializeObject>>(content); - var sessionInfo1 = jt808Result1.Data.FirstOrDefault(); - - var result2 = httpClient.PostAsync($"{Url}/{sessionRoutePrefix}/GetByChannelId",new StringContent(sessionInfo1.ChannelId)).Result; - string content2 = result2.Content.ReadAsStringAsync().Result; - - JT808ResultDto jt808Result2 = JsonConvert.DeserializeObject>(content2); - Assert.Equal(200, jt808Result2.Code); - Assert.Equal(sessionInfo1.ChannelId, jt808Result2.Data.ChannelId); } - [Fact] - public void GetByTerminalPhoneNoTest() - { - var result = httpClient.GetAsync($"{Url}/{sessionRoutePrefix}/GetRelevanceAll").Result; - string content = result.Content.ReadAsStringAsync().Result; - JT808ResultDto> jt808Result1 = JsonConvert.DeserializeObject>>(content); - var sessionInfo1 = jt808Result1.Data.FirstOrDefault(); - - var result2 = httpClient.PostAsync($"{Url}/{sessionRoutePrefix}/GetByTerminalPhoneNo", new StringContent(sessionInfo1.TerminalPhoneNo)).Result; - string content2 = result2.Content.ReadAsStringAsync().Result; - - JT808ResultDto jt808Result2 = JsonConvert.DeserializeObject>(content2); - Assert.Equal(200, jt808Result2.Code); - Assert.Equal(sessionInfo1.TerminalPhoneNo, jt808Result2.Data.TerminalPhoneNo); - } public override void Dispose() { diff --git a/src/JT808.DotNetty/Dtos/JT808SessionInfoDto.cs b/src/JT808.DotNetty/Dtos/JT808SessionInfoDto.cs index e50a69a..c57be31 100644 --- a/src/JT808.DotNetty/Dtos/JT808SessionInfoDto.cs +++ b/src/JT808.DotNetty/Dtos/JT808SessionInfoDto.cs @@ -22,5 +22,17 @@ namespace JT808.DotNetty.Dtos /// 终端手机号 /// public string TerminalPhoneNo { get; set; } + /// + /// 本地ip地址 + /// + public string LoaclAddressIP { get; set; } + /// + /// WebApi端口号 + /// + public int WebApiPort { get; set; } + /// + /// 远程ip地址 + /// + public string RemoteAddressIP { get; set; } } } diff --git a/src/JT808.DotNetty/Interfaces/IJT808SessionService.cs b/src/JT808.DotNetty/Interfaces/IJT808SessionService.cs index e08083c..5edd314 100644 --- a/src/JT808.DotNetty/Interfaces/IJT808SessionService.cs +++ b/src/JT808.DotNetty/Interfaces/IJT808SessionService.cs @@ -11,25 +11,10 @@ namespace JT808.DotNetty.Interfaces internal interface IJT808SessionService { /// - /// 获取真实连接数 + /// 获取会话集合 /// /// - JT808ResultDto GetRealLinkCount(); - /// - /// 获取设备相关连的连接数 - /// - /// - JT808ResultDto GetRelevanceLinkCount(); - /// - /// 获取实际会话集合 - /// - /// - JT808ResultDto> GetRealAll(); - /// - /// 获取设备相关联会话集合 - /// - /// - JT808ResultDto> GetRelevanceAll(); + JT808ResultDto> GetAll(); /// /// 通过通道Id移除对应会话 /// @@ -42,17 +27,5 @@ namespace JT808.DotNetty.Interfaces /// /// JT808ResultDto RemoveByTerminalPhoneNo(string terminalPhoneNo); - /// - /// 通过通道Id获取会话信息 - /// - /// - /// - JT808ResultDto GetByChannelId(string channelId); - /// - /// 通过设备终端号获取会话信息 - /// - /// - /// - JT808ResultDto GetByTerminalPhoneNo(string terminalPhoneNo); } } diff --git a/src/JT808.DotNetty/Internal/JT808SessionServiceDefaultImpl.cs b/src/JT808.DotNetty/Internal/JT808SessionServiceDefaultImpl.cs index 95365bb..a4b558c 100644 --- a/src/JT808.DotNetty/Internal/JT808SessionServiceDefaultImpl.cs +++ b/src/JT808.DotNetty/Internal/JT808SessionServiceDefaultImpl.cs @@ -5,6 +5,8 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.CompilerServices; +using Microsoft.Extensions.Options; +using JT808.DotNetty.Configurations; namespace JT808.DotNetty.Internal { @@ -12,104 +14,30 @@ namespace JT808.DotNetty.Internal { private readonly JT808SessionManager jT808SessionManager; - public JT808SessionServiceDefaultImpl(JT808SessionManager jT808SessionManager) - { - this.jT808SessionManager = jT808SessionManager; - } - - public JT808ResultDto GetByChannelId(string channelId) - { - JT808ResultDto resultDto = new JT808ResultDto(); - try - { - var result = jT808SessionManager.GetSessionByID(channelId); - JT808SessionInfoDto jT808SessionInfoDto = new JT808SessionInfoDto - { - TerminalPhoneNo = result.TerminalPhoneNo, - ChannelId=result.SessionID, - LastActiveTime=result.LastActiveTime, - StartTime=result.StartTime - }; - resultDto.Code = 200; - resultDto.Data = jT808SessionInfoDto; - } - catch (Exception ex) - { - resultDto.Data = null; - resultDto.Code = 500; - resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex); - } - return resultDto; - } + private readonly JT808Configuration jT808Configuration; - public JT808ResultDto GetRelevanceLinkCount() + public JT808SessionServiceDefaultImpl( + IOptions jT808ConfigurationAccssor, + JT808SessionManager jT808SessionManager) { - JT808ResultDto resultDto = new JT808ResultDto(); - try - { - resultDto.Data = jT808SessionManager.RelevanceSessionCount; - resultDto.Code = 200; - } - catch (Exception ex) - { - resultDto.Data = 0; - resultDto.Code = 500; - resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex); - } - return resultDto; - } - - public JT808ResultDto GetRealLinkCount() - { - JT808ResultDto resultDto = new JT808ResultDto(); - try - { - resultDto.Data = jT808SessionManager.RealSessionCount; - resultDto.Code = 200; - } - catch (Exception ex) - { - resultDto.Data = 0; - resultDto.Code = 500; - resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex); - } - return resultDto; - } - - public JT808ResultDto> GetRealAll() - { - JT808ResultDto> resultDto = new JT808ResultDto>(); - try - { - resultDto.Data = jT808SessionManager.GetRealAll().Select(s => new JT808SessionInfoDto - { - ChannelId = s.SessionID, - LastActiveTime = s.LastActiveTime, - StartTime = s.StartTime, - TerminalPhoneNo = s.TerminalPhoneNo - }).ToList(); - resultDto.Code = 200; - } - catch (Exception ex) - { - resultDto.Data = null; - resultDto.Code = 500; - resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex); - } - return resultDto; + this.jT808SessionManager = jT808SessionManager; + this.jT808Configuration = jT808ConfigurationAccssor.Value; } - public JT808ResultDto> GetRelevanceAll() + public JT808ResultDto> GetAll() { JT808ResultDto> resultDto = new JT808ResultDto>(); try { - resultDto.Data = jT808SessionManager.GetRelevanceAll().Select(s => new JT808SessionInfoDto + resultDto.Data = jT808SessionManager.GetAll().Select(s => new JT808SessionInfoDto { ChannelId = s.SessionID, LastActiveTime = s.LastActiveTime, StartTime = s.StartTime, - TerminalPhoneNo = s.TerminalPhoneNo + TerminalPhoneNo = s.TerminalPhoneNo, + WebApiPort = jT808Configuration.WebAPIPort, + LoaclAddressIP = s.Channel.LocalAddress.ToString(), + RemoteAddressIP = s.Channel.RemoteAddress.ToString(), }).ToList(); resultDto.Code = 200; } @@ -177,30 +105,5 @@ namespace JT808.DotNetty.Internal } return resultDto; } - - public JT808ResultDto GetByTerminalPhoneNo(string terminalPhoneNo) - { - JT808ResultDto resultDto = new JT808ResultDto(); - try - { - var result = jT808SessionManager.GetSessionByTerminalPhoneNo(terminalPhoneNo); - JT808SessionInfoDto jT808SessionInfoDto = new JT808SessionInfoDto - { - TerminalPhoneNo = result.TerminalPhoneNo, - ChannelId = result.SessionID, - LastActiveTime = result.LastActiveTime, - StartTime = result.StartTime - }; - resultDto.Code = 200; - resultDto.Data = jT808SessionInfoDto; - } - catch (Exception ex) - { - resultDto.Data = null; - resultDto.Code = 500; - resultDto.Message = Newtonsoft.Json.JsonConvert.SerializeObject(ex); - } - return resultDto; - } } } diff --git a/src/JT808.DotNetty/JT808.DotNetty.xml b/src/JT808.DotNetty/JT808.DotNetty.xml new file mode 100644 index 0000000..f19c8ef --- /dev/null +++ b/src/JT808.DotNetty/JT808.DotNetty.xml @@ -0,0 +1,323 @@ + + + + JT808.DotNetty + + + + + JT808客户端解码(测试客户端) + + + + + JT808解码 + + + + + WebAPI服务 + 默认828端口 + + + + + 源包分发器配置 + + + + + 通道Id + + + + + 最后上线时间 + + + + + 上线时间 + + + + + 终端手机号 + + + + + 本地ip地址 + + + + + WebApi端口号 + + + + + 远程ip地址 + + + + + 统一下发请求参数 + + + + + 通道激活 + + + + + + 设备主动断开 + + + + + + 服务器主动断开 + + + + + + + 超时策略 + + + + + + + jt808 webapi服务 + 请求量不大,只支持JSON格式并且只支持post发数据 + ref: dotnetty HttpServer + + + + + JT808会话服务 + + + + + 获取会话集合 + + + + + + 通过通道Id移除对应会话 + + + + + + + 通过设备终端号移除对应会话 + + + + + + + 源包分发器 + 自定义源包分发器业务 + ConfigureServices: + services.Replace(new ServiceDescriptor(typeof(IJT808SourcePackageDispatcher),typeof(JT808SourcePackageDispatcherDefaultImpl),ServiceLifetime.Singleton)); + + + + + JT808统一下发命令 + + + + + 计数包服务 + + + + + 默认消息处理业务实现 + + + + + 源包分发器默认实现 + + + + + 动态删除远程服务器 + + + + + + 动态添加远程服务器 + + + + + + + 抽象消息处理业务 + 自定义消息处理业务 + ConfigureServices: + services.Replace(new ServiceDescriptor(typeof(JT808MsgIdHandlerBase),typeof(JT808MsgIdCustomHandlerImpl),ServiceLifetime.Singleton)); + + + + + 初始化消息处理业务 + + + + + 终端通用应答 + + + + + + + + 终端心跳 + + + + + + + + 终端注销 + + + + + + + + 终端注册 + + + + + + + + 终端鉴权 + + + + + + + + 位置信息汇报 + + + + + + + + 定位数据批量上传 + + + + + + + + 数据上行透传 + + + + + + + + Netty生成的sessionID和Session的对应关系 + key = seession id + value = Session + + + + + 终端手机号和netty生成的sessionID的对应关系 + key = 终端手机号 + value = seession id + + + + + 获取实际连接数 + + + + + 获取设备相关连的连接数 + + + + + 集成一个webapi服务 + + + + + 初始化消息处理业务 + + + + + 统一下发信息 + + + + + + + 会话服务集合 + + + + + + + 会话服务-通过通道Id移除对应会话 + + + + + + + 会话服务-通过设备终端号移除对应会话 + + + + + + + + + + + + + 根据实际情况适当调整包的大小 + + + + + 终端手机号 + + + + diff --git a/src/JT808.DotNetty/JT808DotnettyExtensions.cs b/src/JT808.DotNetty/JT808DotnettyExtensions.cs index b89a9d9..ee833dc 100644 --- a/src/JT808.DotNetty/JT808DotnettyExtensions.cs +++ b/src/JT808.DotNetty/JT808DotnettyExtensions.cs @@ -6,6 +6,7 @@ using JT808.DotNetty.Internal; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; +using Newtonsoft.Json; using System; using System.Reflection; using System.Runtime.CompilerServices; @@ -15,6 +16,20 @@ namespace JT808.DotNetty { public static class JT808DotnettyExtensions { + static JT808DotnettyExtensions() + { + JsonSerializerSettings setting = new JsonSerializerSettings(); + JsonConvert.DefaultSettings = new Func(() => + { + //日期类型默认格式化处理 + setting.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; + setting.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat; + setting.DateFormatString = "yyyy-MM-dd HH:mm:ss"; + setting.NullValueHandling = NullValueHandling.Include; + return setting; + }); + } + public static IHostBuilder UseJT808Host(this IHostBuilder builder) { return builder.ConfigureServices((hostContext, services) => diff --git a/src/JT808.DotNetty/JT808SessionManager.cs b/src/JT808.DotNetty/JT808SessionManager.cs index d58df46..9748b16 100644 --- a/src/JT808.DotNetty/JT808SessionManager.cs +++ b/src/JT808.DotNetty/JT808SessionManager.cs @@ -1,12 +1,8 @@ using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; using JT808.DotNetty.Metadata; namespace JT808.DotNetty @@ -35,7 +31,7 @@ namespace JT808.DotNetty private ConcurrentDictionary TerminalPhoneNo_SessionId_Dict = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); /// - /// 实际连接数 + /// 获取实际连接数 /// public int RealSessionCount { @@ -121,8 +117,8 @@ namespace JT808.DotNetty public void TryAddOrUpdateSession(JT808Session appSession) { - SessionIdDict.AddOrUpdate(appSession.SessionID, appSession, (x, y) => appSession); - TerminalPhoneNo_SessionId_Dict.AddOrUpdate(appSession.TerminalPhoneNo, appSession.SessionID, (x, y) => appSession.SessionID); + SessionIdDict.TryAdd(appSession.SessionID, appSession); + TerminalPhoneNo_SessionId_Dict.TryAdd(appSession.TerminalPhoneNo, appSession.SessionID); } public JT808Session RemoveSessionByID(string sessionID) @@ -132,17 +128,13 @@ namespace JT808.DotNetty { if (SessionIdDict.TryRemove(sessionID, out JT808Session session)) { - if (session.TerminalPhoneNo != null) + // 处理转发过来的是数据 这时候通道对设备是1对多关系 + var removeKeys = TerminalPhoneNo_SessionId_Dict.Where(s => s.Value == sessionID).Select(s => s.Key).ToList(); + foreach(var key in removeKeys) { - if (TerminalPhoneNo_SessionId_Dict.TryRemove(session.TerminalPhoneNo, out string sessionid)) - { - logger.LogInformation($">>>{sessionID}-{session.TerminalPhoneNo} Session Remove."); - } - } - else - { - logger.LogInformation($">>>{sessionID} Session Remove."); + TerminalPhoneNo_SessionId_Dict.TryRemove(key, out string sessionid); } + logger.LogInformation($">>>{sessionID}-{string.Join(",",removeKeys)} Session Remove."); return session; } return null; @@ -161,9 +153,19 @@ namespace JT808.DotNetty { if (TerminalPhoneNo_SessionId_Dict.TryRemove(terminalPhoneNo, out string sessionid)) { + // 处理转发过来的是数据 这时候通道对设备是1对多关系 + var removeKeys = TerminalPhoneNo_SessionId_Dict.Where(w => w.Value == sessionid).Select(s=>s.Key).ToList(); + if (removeKeys.Count > 0) + { + foreach (var key in removeKeys) + { + TerminalPhoneNo_SessionId_Dict.TryRemove(key, out string sessionid1); + } + logger.LogInformation($">>>{sessionid}-{string.Join(",", removeKeys)} 1-n Session Remove."); + } if (SessionIdDict.TryRemove(sessionid, out JT808Session session)) { - logger.LogInformation($">>>{sessionid}-{session.TerminalPhoneNo} Session Remove."); + logger.LogInformation($">>>{sessionid}-{session.TerminalPhoneNo} 1-1 Session Remove."); return session; } else @@ -179,16 +181,17 @@ namespace JT808.DotNetty return null; } - public IEnumerable GetRealAll() - { - return SessionIdDict.Select(s=>s.Value); - } - - public IEnumerable GetRelevanceAll() + public IEnumerable GetAll() { - return SessionIdDict.Join(TerminalPhoneNo_SessionId_Dict, m => m.Key, s => s.Value, (m, s) => m.Value); + return TerminalPhoneNo_SessionId_Dict.Join(SessionIdDict, m => m.Value, s => s.Key, (m, s) => new JT808Session + { + Channel= s.Value.Channel, + LastActiveTime= s.Value.LastActiveTime, + SessionID= s.Value.SessionID, + StartTime= s.Value.StartTime, + TerminalPhoneNo= m.Key + }).ToList(); } - } } diff --git a/src/JT808.DotNetty/JT808WebAPIService.cs b/src/JT808.DotNetty/JT808WebAPIService.cs index 876cb6f..05e0ce8 100644 --- a/src/JT808.DotNetty/JT808WebAPIService.cs +++ b/src/JT808.DotNetty/JT808WebAPIService.cs @@ -32,14 +32,9 @@ namespace JT808.DotNetty HandlerDict = new Dictionary> { {$"{RouteTablePrefix}/UnificationSend", UnificationSend}, - {$"{RouteTablePrefix}/{sessionRoutePrefix}/GetRealLinkCount", GetRealLinkCount}, - {$"{RouteTablePrefix}/{sessionRoutePrefix}/GetRelevanceLinkCount", GetRelevanceLinkCount}, - {$"{RouteTablePrefix}/{sessionRoutePrefix}/GetRealAll", GetRealAll}, - {$"{RouteTablePrefix}/{sessionRoutePrefix}/GetRelevanceAll", GetRelevanceAll}, + {$"{RouteTablePrefix}/{sessionRoutePrefix}/GetAll", GetAll}, {$"{RouteTablePrefix}/{sessionRoutePrefix}/RemoveByChannelId", RemoveByChannelId}, {$"{RouteTablePrefix}/{sessionRoutePrefix}/RemoveByTerminalPhoneNo", RemoveByTerminalPhoneNo}, - {$"{RouteTablePrefix}/{sessionRoutePrefix}/GetByChannelId", GetByChannelId}, - {$"{RouteTablePrefix}/{sessionRoutePrefix}/GetByTerminalPhoneNo", GetByTerminalPhoneNo}, }; } @@ -60,47 +55,13 @@ namespace JT808.DotNetty } /// - /// 会话服务-获取实际连接数 - /// 存在其他平台转发过来的数据,这时候通道Id和设备属于一对多的关系 + /// 会话服务集合 /// /// /// - public JT808HttpResponse GetRealLinkCount(JT808HttpRequest request) + public JT808HttpResponse GetAll(JT808HttpRequest request) { - var result = jT808SessionService.GetRealLinkCount(); - return CreateJT808HttpResponse(result); - } - - /// - /// 会话服务-获取设备相关连的连接数 - /// - /// - /// - public JT808HttpResponse GetRelevanceLinkCount(JT808HttpRequest request) - { - var result = jT808SessionService.GetRelevanceLinkCount(); - return CreateJT808HttpResponse(result); - } - - /// - /// 会话服务-获取实际会话集合 - /// - /// - /// - public JT808HttpResponse GetRealAll(JT808HttpRequest request) - { - var result = jT808SessionService.GetRealAll(); - return CreateJT808HttpResponse(result); - } - - /// - /// 会话服务-获取设备相关连会话集合 - /// - /// - /// - public JT808HttpResponse GetRelevanceAll(JT808HttpRequest request) - { - var result = jT808SessionService.GetRelevanceAll(); + var result = jT808SessionService.GetAll(); return CreateJT808HttpResponse(result); } @@ -134,36 +95,6 @@ namespace JT808.DotNetty return CreateJT808HttpResponse(result); } - /// - /// 会话服务-通过通道Id获取会话信息 - /// - /// - /// - public JT808HttpResponse GetByChannelId(JT808HttpRequest request) - { - if (string.IsNullOrEmpty(request.Json)) - { - return EmptyHttpResponse(); - } - var result = jT808SessionService.GetByChannelId(request.Json); - return CreateJT808HttpResponse(result); - } - - /// - /// 会话服务-通过设备终端号获取会话信息 - /// - /// - /// - public JT808HttpResponse GetByTerminalPhoneNo(JT808HttpRequest request) - { - if (string.IsNullOrEmpty(request.Json)) - { - return EmptyHttpResponse(); - } - var result = jT808SessionService.GetByTerminalPhoneNo(request.Json); - return CreateJT808HttpResponse(result); - } - private JT808HttpResponse CreateJT808HttpResponse(dynamic dynamicObject) { byte[] data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(dynamicObject)); diff --git a/src/JT808.DotNetty/Metadata/JT808Session.cs b/src/JT808.DotNetty/Metadata/JT808Session.cs index 0c3af26..9d5e5a2 100644 --- a/src/JT808.DotNetty/Metadata/JT808Session.cs +++ b/src/JT808.DotNetty/Metadata/JT808Session.cs @@ -24,17 +24,19 @@ namespace JT808.DotNetty.Metadata SessionID = Channel.Id.AsShortText(); } + public JT808Session() { } + /// /// 终端手机号 /// public string TerminalPhoneNo { get; set; } - public string SessionID { get; } + public string SessionID { get; set; } - public IChannel Channel { get; } + public IChannel Channel { get; set; } public DateTime LastActiveTime { get; set; } - public DateTime StartTime { get; } + public DateTime StartTime { get; set; } } }