Browse Source

整理及添加809模块

tags/old
SmallChi 6 years ago
parent
commit
c6e47b545e
38 changed files with 1483 additions and 32 deletions
  1. +33
    -0
      src/JT809.DotNetty.Abstractions/Dtos/JT809SystemCollectInfoDto.cs
  2. +12
    -0
      src/JT809.DotNetty.Abstractions/IJT809SessionPublishing.cs
  3. +7
    -0
      src/JT809.DotNetty.Abstractions/JT809.DotNetty.Abstractions.csproj
  4. +25
    -0
      src/JT809.DotNetty.Abstractions/JT809Constants.cs
  5. +20
    -0
      src/JT809.DotNetty.Core/Codecs/JT809TcpDecoder.cs
  6. +31
    -0
      src/JT809.DotNetty.Core/Configurations/JT809ClientConfiguration.cs
  7. +29
    -0
      src/JT809.DotNetty.Core/Configurations/JT809Configuration.cs
  8. +26
    -0
      src/JT809.DotNetty.Core/Converters/JsonIPAddressConverter.cs
  9. +32
    -0
      src/JT809.DotNetty.Core/Converters/JsonIPEndPointConverter.cs
  10. +109
    -0
      src/JT809.DotNetty.Core/Handlers/JT809MsgIdTcpHandlerBase.cs
  11. +14
    -0
      src/JT809.DotNetty.Core/Interfaces/IVerifyCodeGenerator.cs
  12. +13
    -0
      src/JT809.DotNetty.Core/Internal/JT809SessionPublishingEmptyImpl.cs
  13. +15
    -0
      src/JT809.DotNetty.Core/Internal/VerifyCodeGeneratorDefaultImpl.cs
  14. +23
    -0
      src/JT809.DotNetty.Core/JT809.DotNetty.Core.csproj
  15. +59
    -0
      src/JT809.DotNetty.Core/JT809CoreDotnettyExtensions.cs
  16. +113
    -0
      src/JT809.DotNetty.Core/Links/SubordinateLinkClient.cs
  17. +49
    -0
      src/JT809.DotNetty.Core/Metadata/JT809AtomicCounter.cs
  18. +23
    -0
      src/JT809.DotNetty.Core/Metadata/JT809Request.cs
  19. +27
    -0
      src/JT809.DotNetty.Core/Metadata/JT809Response.cs
  20. +28
    -0
      src/JT809.DotNetty.Core/Metadata/JT809TcpSession.cs
  21. +30
    -0
      src/JT809.DotNetty.Core/Services/JT809SimpleSystemCollectService.cs
  22. +51
    -0
      src/JT809.DotNetty.Core/Services/JT809TcpAtomicCounterService.cs
  23. +108
    -0
      src/JT809.DotNetty.Core/Session/JT809TcpSessionManager.cs
  24. +18
    -0
      src/JT809.DotNetty.Tcp/Handlers/JT809MsgIdDefaultTcpHandler.cs
  25. +98
    -0
      src/JT809.DotNetty.Tcp/Handlers/JT809TcpConnectionHandler.cs
  26. +83
    -0
      src/JT809.DotNetty.Tcp/Handlers/JT809TcpServerHandler.cs
  27. +11
    -0
      src/JT809.DotNetty.Tcp/JT809.DotNetty.Tcp.csproj
  28. +32
    -0
      src/JT809.DotNetty.Tcp/JT809TcpDotnettyExtensions.cs
  29. +95
    -0
      src/JT809.DotNetty.Tcp/JT809TcpServerHost.cs
  30. +27
    -0
      src/JT809.DotNetty.Tests/JT809.DotNetty.Host.Test/JT809.DotNetty.Host.Test.csproj
  31. +54
    -0
      src/JT809.DotNetty.Tests/JT809.DotNetty.Host.Test/Program.cs
  32. +18
    -0
      src/JT809.DotNetty.Tests/JT809.DotNetty.Host.Test/appsettings.json
  33. +31
    -0
      src/JT809.DotNetty.Tests/JT809.DotNetty.Tcp.Test/JT809.DotNetty.Tcp.Test.csproj
  34. +37
    -0
      src/JT809.DotNetty.Tests/JT809.DotNetty.Tcp.Test/TestBase.cs
  35. +18
    -0
      src/JT809.DotNetty.Tests/JT809.DotNetty.Tcp.Test/appsettings.json
  36. +83
    -0
      src/JT809.DotNetty.sln
  37. +1
    -1
      src/JT809.Protocol
  38. +0
    -31
      src/JT809Netty.sln

+ 33
- 0
src/JT809.DotNetty.Abstractions/Dtos/JT809SystemCollectInfoDto.cs View File

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

namespace JT809.DotNetty.Abstractions.Dtos
{
public class JT809SystemCollectInfoDto
{
/// <summary>
/// 进程Id
/// </summary>
public int ProcessId { get; set; }
/// <summary>
/// 进程分配内存
/// 单位MB
/// </summary>
public double WorkingSet64 { get; set; }
/// <summary>
/// 进程分配内存峰值
/// 单位MB
/// </summary>
public double PeakWorkingSet64 { get; set; }
/// <summary>
/// 进程分配私有内存
/// 单位MB
/// </summary>
public double PrivateMemorySize64 { get; set; }
/// <summary>
/// 进程执行CPU总处理时间
/// </summary>
public TimeSpan CPUTotalProcessorTime { get; set; }
}
}

+ 12
- 0
src/JT809.DotNetty.Abstractions/IJT809SessionPublishing.cs View File

@@ -0,0 +1,12 @@
using System.Threading.Tasks;

namespace JT809.DotNetty.Abstractions
{
/// <summary>
/// 会话通知(在线/离线)
/// </summary>
public interface IJT809SessionPublishing
{
Task PublishAsync(string topicName, string value);
}
}

+ 7
- 0
src/JT809.DotNetty.Abstractions/JT809.DotNetty.Abstractions.csproj View File

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

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

</Project>

+ 25
- 0
src/JT809.DotNetty.Abstractions/JT809Constants.cs View File

@@ -0,0 +1,25 @@
namespace JT809.DotNetty.Abstractions
{
public static class JT809Constants
{
public const string SessionOnline= "JT809SessionOnline";

public const string SessionOffline = "JT809SessionOffline";

public static class JT809WebApiRouteTable
{
public const string RouteTablePrefix = "/jt809api";

public const string SessionPrefix = "Session";

public const string SystemCollectPrefix = "SystemCollect";

public const string TcpPrefix = "Tcp";

/// <summary>
///获取当前系统进程使用率
/// </summary>
public static string SystemCollectGet = $"{RouteTablePrefix}/{SystemCollectPrefix}/Get";
}
}
}

+ 20
- 0
src/JT809.DotNetty.Core/Codecs/JT809TcpDecoder.cs View File

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

namespace JT809.DotNetty.Core.Codecs
{
public class JT809TcpDecoder : 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] = JT809Package.BEGINFLAG;
buffer[input.Capacity + 1] = JT809Package.ENDFLAG;
output.Add(buffer);
}
}
}

+ 31
- 0
src/JT809.DotNetty.Core/Configurations/JT809ClientConfiguration.cs View File

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

namespace JT809.DotNetty.Core.Configurations
{
public class JT809ClientConfiguration
{
public string Host { get; set; }

public int Port { get; set; }

private EndPoint endPoint;

public EndPoint EndPoint
{
get
{
if (endPoint == null)
{
if (IPAddress.TryParse(Host, out IPAddress ip))
{
endPoint = new IPEndPoint(ip, Port);
}
}
return endPoint;
}
}
}
}

+ 29
- 0
src/JT809.DotNetty.Core/Configurations/JT809Configuration.cs View File

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

namespace JT809.DotNetty.Core.Configurations
{
public class JT809Configuration
{
public int TcpPort { get; set; } = 809;

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; } = 180;

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

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

+ 26
- 0
src/JT809.DotNetty.Core/Converters/JsonIPAddressConverter.cs View File

@@ -0,0 +1,26 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;

namespace JT809.DotNetty.Core.Converters
{
public class JsonIPAddressConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(IPAddress));
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return IPAddress.Parse((string)reader.Value);
}
}
}

+ 32
- 0
src/JT809.DotNetty.Core/Converters/JsonIPEndPointConverter.cs View File

@@ -0,0 +1,32 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Net;

namespace JT809.DotNetty.Core.Converters
{
public class JsonIPEndPointConverter: JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(IPEndPoint));
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
IPEndPoint ep = (IPEndPoint)value;
JObject jo = new JObject();
jo.Add("Host", JToken.FromObject(ep.Address, serializer));
jo.Add("Port", ep.Port);
jo.WriteTo(writer);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
IPAddress address = jo["Host"].ToObject<IPAddress>(serializer);
int port = (int)jo["Port"];
return new IPEndPoint(address, port);
}
}
}

+ 109
- 0
src/JT809.DotNetty.Core/Handlers/JT809MsgIdTcpHandlerBase.cs View File

@@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using JT809.DotNetty.Core.Interfaces;
using JT809.DotNetty.Core.Metadata;
using JT809.Protocol.Enums;
using JT809.Protocol.Extensions;
using JT809.Protocol.MessageBody;

namespace JT809.DotNetty.Core.Handlers
{
/// <summary>
/// 基于Tcp模式抽象消息处理业务
/// 自定义消息处理业务
/// 注意:
/// 1.ConfigureServices:
/// services.Replace(new ServiceDescriptor(typeof(JT809MsgIdTcpHandlerBase),typeof(JT809MsgIdCustomTcpHandlerImpl),ServiceLifetime.Singleton));
/// 2.解析具体的消息体,具体消息调用具体的JT809Serializer.Deserialize<T>
/// </summary>
public abstract class JT809MsgIdTcpHandlerBase
{
protected JT809TcpSessionManager sessionManager { get; }
protected IVerifyCodeGenerator verifyCodeGenerator { get; }
/// <summary>
/// 初始化消息处理业务
/// </summary>
protected JT809MsgIdTcpHandlerBase(
IVerifyCodeGenerator verifyCodeGenerator,
JT809TcpSessionManager sessionManager)
{
this.sessionManager = sessionManager;
this.verifyCodeGenerator = verifyCodeGenerator;
HandlerDict = new Dictionary<JT809BusinessType, Func<JT809Request, JT809Response>>
{
{JT809BusinessType.主链路登录请求消息, Msg0x1001},
{JT809BusinessType.主链路注销请求消息, Msg0x1003},
{JT809BusinessType.主链路连接保持请求消息, Msg0x1005},
{JT809BusinessType.主链路动态信息交换消息, Msg0x1200}
};
//SubHandlerDict = new Dictionary<JT809SubBusinessType, Func<JT809Request, JT809Response>>
//{
// {JT809SubBusinessType.实时上传车辆定位信息, Msg0x1200_0x1202},
//};
}

public Dictionary<JT809BusinessType, Func<JT809Request, JT809Response>> HandlerDict { get; protected set; }

//public Dictionary<JT809SubBusinessType, Func<JT809Request, JT809Response>> SubHandlerDict { get; protected set; }

/// <summary>
/// 主链路登录应答消息
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public virtual JT809Response Msg0x1001(JT809Request request)
{
var package= JT809BusinessType.主链路登录应答消息.Create(new JT809_0x1002()
{
Result= JT809_0x1002_Result.成功,
VerifyCode= verifyCodeGenerator.Create()
});

return new JT809Response(package,100);
}

/// <summary>
/// 主链路注销应答消息
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public virtual JT809Response Msg0x1003(JT809Request request)
{
var package = JT809BusinessType.主链路注销应答消息.Create();
return new JT809Response(package, 100);
}

/// <summary>
/// 主链路连接保持应答消息
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public virtual JT809Response Msg0x1005(JT809Request request)
{
var package = JT809BusinessType.主链路连接保持应答消息.Create();
return new JT809Response(package, 100);
}

/// <summary>
/// 主链路动态信息交换消息
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public virtual JT809Response Msg0x1200(JT809Request request)
{
return null;
}

///// <summary>
///// 主链路动态信息交换消息
///// </summary>
///// <param name="request"></param>
///// <returns></returns>
//public virtual JT809Response Msg0x1200_0x1202(JT809Request request)
//{

// return null;
//}
}
}

+ 14
- 0
src/JT809.DotNetty.Core/Interfaces/IVerifyCodeGenerator.cs View File

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

namespace JT809.DotNetty.Core.Interfaces
{
/// <summary>
/// 校验码生成器
/// </summary>
public interface IVerifyCodeGenerator
{
uint Create();
}
}

+ 13
- 0
src/JT809.DotNetty.Core/Internal/JT809SessionPublishingEmptyImpl.cs View File

@@ -0,0 +1,13 @@
using JT809.DotNetty.Abstractions;
using System.Threading.Tasks;

namespace JT809.DotNetty.Core
{
internal class JT809SessionPublishingEmptyImpl : IJT809SessionPublishing
{
public Task PublishAsync(string topicName, string value)
{
return Task.CompletedTask;
}
}
}

+ 15
- 0
src/JT809.DotNetty.Core/Internal/VerifyCodeGeneratorDefaultImpl.cs View File

@@ -0,0 +1,15 @@
using JT809.DotNetty.Core.Interfaces;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT809.DotNetty.Core.Internal
{
internal class VerifyCodeGeneratorDefaultImpl : IVerifyCodeGenerator
{
public uint Create()
{
return (uint)Guid.NewGuid().GetHashCode();
}
}
}

+ 23
- 0
src/JT809.DotNetty.Core/JT809.DotNetty.Core.csproj View File

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

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DotNetty.Handlers" Version="0.6.0" />
<PackageReference Include="DotNetty.Transport.Libuv" Version="0.6.0" />
<PackageReference Include="DotNetty.Codecs" Version="0.6.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="Microsoft.Extensions.Options" Version="2.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\JT809.DotNetty.Abstractions\JT809.DotNetty.Abstractions.csproj" />
<ProjectReference Include="..\JT809.Protocol\src\JT809.Protocol\JT809.Protocol.csproj" />
</ItemGroup>

</Project>

+ 59
- 0
src/JT809.DotNetty.Core/JT809CoreDotnettyExtensions.cs View File

@@ -0,0 +1,59 @@
using JT809.DotNetty.Abstractions;
using JT809.DotNetty.Core.Configurations;
using JT809.DotNetty.Core.Converters;
using JT809.DotNetty.Core.Interfaces;
using JT809.DotNetty.Core.Internal;
using JT809.DotNetty.Core.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Newtonsoft.Json;
using System;
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("JT809.DotNetty.Core.Test")]
[assembly: InternalsVisibleTo("JT809.DotNetty.Tcp.Test")]
[assembly: InternalsVisibleTo("JT809.DotNetty.Udp.Test")]
[assembly: InternalsVisibleTo("JT809.DotNetty.WebApi.Test")]

namespace JT809.DotNetty.Core
{
public static class JT809CoreDotnettyExtensions
{
static JT809CoreDotnettyExtensions()
{
JsonConvert.DefaultSettings = new Func<JsonSerializerSettings>(() =>
{
Newtonsoft.Json.JsonSerializerSettings settings = new Newtonsoft.Json.JsonSerializerSettings();
//日期类型默认格式化处理
settings.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;
settings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
//空值处理
settings.NullValueHandling = NullValueHandling.Ignore;
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
settings.Converters.Add(new JsonIPAddressConverter());
settings.Converters.Add(new JsonIPEndPointConverter());
return settings;
});
}

public static IServiceCollection AddJT809Core(this IServiceCollection serviceDescriptors, IConfiguration configuration, Newtonsoft.Json.JsonSerializerSettings settings=null)
{
if (settings != null)
{
JsonConvert.DefaultSettings = new Func<JsonSerializerSettings>(() =>
{
settings.Converters.Add(new JsonIPAddressConverter());
settings.Converters.Add(new JsonIPEndPointConverter());
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
return settings;
});
}
serviceDescriptors.Configure<JT809Configuration>(configuration.GetSection("JT809Configuration"));
serviceDescriptors.TryAddSingleton<IVerifyCodeGenerator, VerifyCodeGeneratorDefaultImpl>();
serviceDescriptors.TryAddSingleton<IJT809SessionPublishing, JT809SessionPublishingEmptyImpl>();
serviceDescriptors.TryAddSingleton<JT809SimpleSystemCollectService>();
return serviceDescriptors;
}
}
}

+ 113
- 0
src/JT809.DotNetty.Core/Links/SubordinateLinkClient.cs View File

@@ -0,0 +1,113 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using JT809.DotNetty.Core.Codecs;
using JT809.Protocol;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;

namespace JT809.DotNetty.Core.Links
{
/// <summary>
/// 从链路客户端
/// </summary>
public sealed class SubordinateLinkClient:IDisposable
{
private Bootstrap bootstrap;

private MultithreadEventLoopGroup group;

private IChannel channel;

private readonly ILogger<SubordinateLinkClient> logger;

private readonly ILoggerFactory loggerFactory;

private readonly IServiceProvider serviceProvider;

private bool disposed = false;

public SubordinateLinkClient(
IServiceProvider provider,
ILoggerFactory loggerFactory)
{
this.serviceProvider = provider;
this.loggerFactory = loggerFactory;
this.logger = loggerFactory.CreateLogger<SubordinateLinkClient>();
}

public async void ConnectAsync(string ip,int port,uint verifyCode)
{
group = new MultithreadEventLoopGroup();
bootstrap = new Bootstrap();
bootstrap.Group(group)
.Channel<TcpSocketChannel>()
.Option(ChannelOption.TcpNodelay, true)
.Handler(new ActionChannelInitializer<ISocketChannel>(channel =>
{
IChannelPipeline pipeline = channel.Pipeline;
//下级平台1分钟发送心跳
//上级平台是3分钟没有发送就断开连接
channel.Pipeline.AddLast("jt809SystemIdleState", new IdleStateHandler(60,180,200));
//pipeline.AddLast(new ClientConnectionHandler(bootstrap, channeldic, loggerFactory));
channel.Pipeline.AddLast("jt809TcpBuffer", new DelimiterBasedFrameDecoder(int.MaxValue,
Unpooled.CopiedBuffer(new byte[] { JT809Package.BEGINFLAG }),
Unpooled.CopiedBuffer(new byte[] { JT809Package.ENDFLAG })));
using (var scope = serviceProvider.CreateScope())
{
channel.Pipeline.AddLast("jt809TcpDecode", scope.ServiceProvider.GetRequiredService<JT809TcpDecoder>());

}
}));
channel = await bootstrap.ConnectAsync(new IPEndPoint(IPAddress.Parse(ip), port));
}

public async void SendAsync(byte[] data)
{
if (channel == null) throw new NullReferenceException("Channel Not Open");
if (data == null) throw new ArgumentNullException("data is null");
if (channel.Open && channel.Active)
{
await channel.WriteAndFlushAsync(Unpooled.WrappedBuffer(data));
}
}

private void Dispose(bool disposing)
{
if (disposed)
{
return;
}
if (disposing)
{
//清理托管资源
channel.CloseAsync();
group.ShutdownGracefullyAsync(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(3));
}
//让类型知道自己已经被释放
disposed = true;
}

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

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

+ 49
- 0
src/JT809.DotNetty.Core/Metadata/JT809AtomicCounter.cs View File

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

namespace JT809.DotNetty.Core.Metadata
{
/// <summary>
///
/// <see cref="Grpc.Core.Internal"/>
/// </summary>
public class JT809AtomicCounter
{
long counter = 0;

public JT809AtomicCounter(long initialCount = 0)
{
this.counter = initialCount;
}

public void Reset()
{
Interlocked.Exchange(ref counter, 0);
}

public long Increment()
{
return Interlocked.Increment(ref counter);
}

public long Add(long len)
{
return Interlocked.Add(ref counter,len);
}

public long Decrement()
{
return Interlocked.Decrement(ref counter);
}

public long Count
{
get
{
return Interlocked.Read(ref counter);
}
}
}
}

+ 23
- 0
src/JT809.DotNetty.Core/Metadata/JT809Request.cs View File

@@ -0,0 +1,23 @@
using JT809.Protocol;
using System;
using System.Collections.Generic;
using System.Reflection;

namespace JT809.DotNetty.Core.Metadata
{
public class JT809Request
{
public JT809Package Package { get; }

/// <summary>
/// 用于消息发送
/// </summary>
public byte[] OriginalPackage { get;}

public JT809Request(JT809Package package, byte[] originalPackage)
{
Package = package;
OriginalPackage = originalPackage;
}
}
}

+ 27
- 0
src/JT809.DotNetty.Core/Metadata/JT809Response.cs View File

@@ -0,0 +1,27 @@
using JT809.Protocol;
using System;
using System.Collections.Generic;
using System.Reflection;

namespace JT809.DotNetty.Core.Metadata
{
public class JT809Response
{
public JT809Package Package { get; set; }
/// <summary>
/// 根据实际情况适当调整包的大小
/// </summary>
public int MinBufferSize { get; set; }

public JT809Response()
{

}

public JT809Response(JT809Package package, int minBufferSize = 1024)
{
Package = package;
MinBufferSize = minBufferSize;
}
}
}

+ 28
- 0
src/JT809.DotNetty.Core/Metadata/JT809TcpSession.cs View File

@@ -0,0 +1,28 @@
using DotNetty.Transport.Channels;
using System;
using JT809.Protocol.Enums;

namespace JT809.DotNetty.Core.Metadata
{
public class JT809TcpSession
{
public JT809TcpSession(IChannel channel, uint msgGNSSCENTERID)
{
MsgGNSSCENTERID = msgGNSSCENTERID;
Channel = channel;
StartTime = DateTime.Now;
LastActiveTime = DateTime.Now;
}

/// <summary>
/// 下级平台接入码,上级平台给下级平台分配唯一标识码。
/// </summary>
public uint MsgGNSSCENTERID { get; set; }

public IChannel Channel { get;}

public DateTime LastActiveTime { get; set; }

public DateTime StartTime { get; }
}
}

+ 30
- 0
src/JT809.DotNetty.Core/Services/JT809SimpleSystemCollectService.cs View File

@@ -0,0 +1,30 @@
using JT809.DotNetty.Abstractions.Dtos;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;

namespace JT809.DotNetty.Core.Services
{
/// <summary>
/// 简单系统收集服务
/// </summary>
public class JT809SimpleSystemCollectService
{
/// <summary>
/// 获取系统当前进程使用情况
/// </summary>
/// <returns></returns>
public JT809SystemCollectInfoDto Get()
{
JT809SystemCollectInfoDto jT808SystemCollectInfoDto = new JT809SystemCollectInfoDto();
var proc = Process.GetCurrentProcess();
jT808SystemCollectInfoDto.ProcessId = proc.Id;
jT808SystemCollectInfoDto.WorkingSet64 = proc.WorkingSet64 / 1024.0 / 1024.0;
jT808SystemCollectInfoDto.PeakWorkingSet64 = proc.PeakWorkingSet64 / 1024.0 / 1024.0;
jT808SystemCollectInfoDto.PrivateMemorySize64 = proc.PrivateMemorySize64 / 1024.0 / 1024.0;
jT808SystemCollectInfoDto.CPUTotalProcessorTime = proc.TotalProcessorTime;
return jT808SystemCollectInfoDto;
}
}
}

+ 51
- 0
src/JT809.DotNetty.Core/Services/JT809TcpAtomicCounterService.cs View File

@@ -0,0 +1,51 @@
using JT809.DotNetty.Core.Metadata;

namespace JT809.DotNetty.Core.Services
{
/// <summary>
/// Tcp计数包服务
/// </summary>
public class JT809TcpAtomicCounterService
{
private readonly JT809AtomicCounter MsgSuccessCounter = new JT809AtomicCounter();

private readonly JT809AtomicCounter MsgFailCounter = new JT809AtomicCounter();

public JT809TcpAtomicCounterService()
{

}

public void Reset()
{
MsgSuccessCounter.Reset();
MsgFailCounter.Reset();
}

public long MsgSuccessIncrement()
{
return MsgSuccessCounter.Increment();
}

public long MsgSuccessCount
{
get
{
return MsgSuccessCounter.Count;
}
}

public long MsgFailIncrement()
{
return MsgFailCounter.Increment();
}

public long MsgFailCount
{
get
{
return MsgFailCounter.Count;
}
}
}
}

+ 108
- 0
src/JT809.DotNetty.Core/Session/JT809TcpSessionManager.cs View File

@@ -0,0 +1,108 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using DotNetty.Transport.Channels;
using JT809.DotNetty.Abstractions;
using JT809.DotNetty.Core.Metadata;

namespace JT809.DotNetty.Core
{
/// <summary>
/// JT809 Tcp会话管理
/// </summary>
public class JT809TcpSessionManager
{
private readonly ILogger<JT809TcpSessionManager> logger;

private readonly IJT809SessionPublishing jT809SessionPublishing;

public JT809TcpSessionManager(
IJT809SessionPublishing jT809SessionPublishing,
ILoggerFactory loggerFactory)
{
this.jT809SessionPublishing = jT809SessionPublishing;
logger = loggerFactory.CreateLogger<JT809TcpSessionManager>();
}

private ConcurrentDictionary<uint, JT809TcpSession> SessionIdDict = new ConcurrentDictionary<uint, JT809TcpSession>();

public int SessionCount
{
get
{
return SessionIdDict.Count;
}
}

public JT809TcpSession GetSession(uint msgGNSSCENTERID)
{
if (SessionIdDict.TryGetValue(msgGNSSCENTERID, out JT809TcpSession targetSession))
{
return targetSession;
}
else
{
return default;
}
}

public void Heartbeat(uint msgGNSSCENTERID)
{
if (SessionIdDict.TryGetValue(msgGNSSCENTERID, out JT809TcpSession oldjT808Session))
{
oldjT808Session.LastActiveTime = DateTime.Now;
SessionIdDict.TryUpdate(msgGNSSCENTERID, oldjT808Session, oldjT808Session);
}
}

public void TryAdd(JT809TcpSession appSession)
{
if (SessionIdDict.TryAdd(appSession.MsgGNSSCENTERID, appSession))
{
jT809SessionPublishing.PublishAsync(JT809Constants.SessionOnline, appSession.MsgGNSSCENTERID.ToString());
}
}

public JT809TcpSession RemoveSession(uint msgGNSSCENTERID)
{
//可以使用任意mq的发布订阅
if (!SessionIdDict.TryGetValue(msgGNSSCENTERID, out JT809TcpSession jT808Session))
{
return default;
}
if (SessionIdDict.TryRemove(msgGNSSCENTERID, out JT809TcpSession jT808SessionRemove))
{
logger.LogInformation($">>>{msgGNSSCENTERID} Session Remove.");
jT809SessionPublishing.PublishAsync(JT809Constants.SessionOffline, msgGNSSCENTERID.ToString());
return jT808SessionRemove;
}
else
{
return default;
}
}

public void RemoveSessionByChannel(IChannel channel)
{
var keys = SessionIdDict.Where(w => w.Value.Channel.Id == channel.Id).Select(s => s.Key).ToList();
if (keys.Count > 0)
{
foreach (var key in keys)
{
SessionIdDict.TryRemove(key, out JT809TcpSession jT808SessionRemove);
}
string nos = string.Join(",", keys);
logger.LogInformation($">>>{nos} Channel Remove.");
jT809SessionPublishing.PublishAsync(JT809Constants.SessionOffline, nos);
}
}

public IEnumerable<JT809TcpSession> GetAll()
{
return SessionIdDict.Select(s => s.Value).ToList();
}
}
}


+ 18
- 0
src/JT809.DotNetty.Tcp/Handlers/JT809MsgIdDefaultTcpHandler.cs View File

@@ -0,0 +1,18 @@
using JT809.DotNetty.Core;
using JT809.DotNetty.Core.Handlers;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT809.DotNetty.Tcp.Handlers
{
/// <summary>
/// 默认消息处理业务实现
/// </summary>
internal class JT809MsgIdDefaultTcpHandler : JT809MsgIdTcpHandlerBase
{
public JT809MsgIdDefaultTcpHandler(JT809TcpSessionManager sessionManager) : base(sessionManager)
{
}
}
}

+ 98
- 0
src/JT809.DotNetty.Tcp/Handlers/JT809TcpConnectionHandler.cs View File

@@ -0,0 +1,98 @@
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Channels;
using JT809.DotNetty.Core;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;

namespace JT809.DotNetty.Tcp.Handlers
{
/// <summary>
/// JT809服务通道处理程序
/// </summary>
internal class JT809TcpConnectionHandler : ChannelHandlerAdapter
{
private readonly ILogger<JT809TcpConnectionHandler> logger;

private readonly JT809TcpSessionManager jT809SessionManager;

public JT809TcpConnectionHandler(
JT809TcpSessionManager jT809SessionManager,
ILoggerFactory loggerFactory)
{
this.jT809SessionManager = jT809SessionManager;
logger = loggerFactory.CreateLogger<JT809TcpConnectionHandler>();
}

/// <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.");
jT809SessionManager.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.");
jT809SessionManager.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}");
jT809SessionManager.RemoveSessionByChannel(context.Channel);
context.CloseAsync();
}
}
base.UserEventTriggered(context, evt);
}

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


+ 83
- 0
src/JT809.DotNetty.Tcp/Handlers/JT809TcpServerHandler.cs View File

@@ -0,0 +1,83 @@
using DotNetty.Buffers;
using DotNetty.Transport.Channels;
using JT809.Protocol;
using System;
using Microsoft.Extensions.Logging;
using JT809.Protocol.Exceptions;
using JT809.DotNetty.Core.Services;
using JT809.DotNetty.Core;
using JT809.DotNetty.Core.Handlers;
using JT809.DotNetty.Core.Metadata;

namespace JT809.DotNetty.Tcp.Handlers
{
/// <summary>
/// JT809服务端处理程序
/// </summary>
internal class JT809TcpServerHandler : SimpleChannelInboundHandler<byte[]>
{
private readonly JT809MsgIdTcpHandlerBase handler;
private readonly JT809TcpSessionManager jT809SessionManager;

private readonly JT809TcpAtomicCounterService jT809AtomicCounterService;

private readonly ILogger<JT809TcpServerHandler> logger;

public JT809TcpServerHandler(
ILoggerFactory loggerFactory,
JT809MsgIdTcpHandlerBase handler,
JT809TcpAtomicCounterService jT809AtomicCounterService,
JT809TcpSessionManager jT809SessionManager
)
{
this.handler = handler;
this.jT809SessionManager = jT809SessionManager;
this.jT809AtomicCounterService = jT809AtomicCounterService;
logger = loggerFactory.CreateLogger<JT809TcpServerHandler>();
}


protected override void ChannelRead0(IChannelHandlerContext ctx, byte[] msg)
{
try
{
JT809Package jT809Package = JT809Serializer.Deserialize(msg);
jT809AtomicCounterService.MsgSuccessIncrement();
if (logger.IsEnabled(LogLevel.Debug))
{
logger.LogDebug("accept package success count<<<" + jT809AtomicCounterService.MsgSuccessCount.ToString());
}
jT809SessionManager.TryAdd(new JT809TcpSession(ctx.Channel, jT809Package.Header.MsgGNSSCENTERID));
Func<JT809Request, JT809Response> handlerFunc;
if (handler.HandlerDict.TryGetValue(jT809Package.Header.BusinessType, out handlerFunc))
{
JT809Response jT808Response = handlerFunc(new JT809Request(jT809Package, msg));
if (jT808Response != null)
{
var sendData = JT809Serializer.Serialize(jT808Response.Package, jT808Response.MinBufferSize);
ctx.WriteAndFlushAsync(Unpooled.WrappedBuffer(sendData));
}
}
}
catch (JT809Exception ex)
{
jT809AtomicCounterService.MsgFailIncrement();
if (logger.IsEnabled(LogLevel.Error))
{
logger.LogError("accept package fail count<<<" + jT809AtomicCounterService.MsgFailCount.ToString());
logger.LogError(ex, "accept msg<<<" + ByteBufferUtil.HexDump(msg));
}
}
catch (Exception ex)
{
jT809AtomicCounterService.MsgFailIncrement();
if (logger.IsEnabled(LogLevel.Error))
{
logger.LogError("accept package fail count<<<" + jT809AtomicCounterService.MsgFailCount.ToString());
logger.LogError(ex, "accept msg<<<" + ByteBufferUtil.HexDump(msg));
}
}
}
}
}

+ 11
- 0
src/JT809.DotNetty.Tcp/JT809.DotNetty.Tcp.csproj View File

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

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\JT809.DotNetty.Core\JT809.DotNetty.Core.csproj" />
</ItemGroup>

</Project>

+ 32
- 0
src/JT809.DotNetty.Tcp/JT809TcpDotnettyExtensions.cs View File

@@ -0,0 +1,32 @@
using JT809.DotNetty.Core;
using JT809.DotNetty.Core.Codecs;
using JT809.DotNetty.Core.Handlers;
using JT809.DotNetty.Core.Services;
using JT809.DotNetty.Tcp.Handlers;
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;

[assembly: InternalsVisibleTo("JT809.DotNetty.Tcp.Test")]

namespace JT809.DotNetty.Tcp
{
public static class JT809TcpDotnettyExtensions
{
public static IServiceCollection AddJT809TcpHost(this IServiceCollection serviceDescriptors)
{
serviceDescriptors.TryAddSingleton<JT809TcpSessionManager>();
serviceDescriptors.TryAddSingleton<JT809TcpAtomicCounterService>();
serviceDescriptors.TryAddSingleton<JT809MsgIdTcpHandlerBase, JT809MsgIdDefaultTcpHandler>();
serviceDescriptors.TryAddScoped<JT809TcpConnectionHandler>();
serviceDescriptors.TryAddScoped<JT809TcpDecoder>();
serviceDescriptors.TryAddScoped<JT809TcpServerHandler>();
serviceDescriptors.AddHostedService<JT809TcpServerHost>();
return serviceDescriptors;
}
}
}

+ 95
- 0
src/JT809.DotNetty.Tcp/JT809TcpServerHost.cs View File

@@ -0,0 +1,95 @@
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Libuv;
using JT809.DotNetty.Core.Configurations;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Net;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using JT809.Protocol;
using JT809.DotNetty.Core.Codecs;
using JT809.DotNetty.Tcp.Handlers;

namespace JT809.DotNetty.Tcp
{
/// <summary>
/// JT809 Tcp网关服务
/// </summary>
internal class JT809TcpServerHost : IHostedService
{
private readonly IServiceProvider serviceProvider;
private readonly JT809Configuration configuration;
private readonly ILogger<JT809TcpServerHost> logger;
private DispatcherEventLoopGroup bossGroup;
private WorkerEventLoopGroup workerGroup;
private IChannel bootstrapChannel;
private IByteBufferAllocator serverBufferAllocator;

public JT809TcpServerHost(
IServiceProvider provider,
ILoggerFactory loggerFactory,
IOptions<JT809Configuration> jT809ConfigurationAccessor)
{
serviceProvider = provider;
configuration = jT809ConfigurationAccessor.Value;
logger=loggerFactory.CreateLogger<JT809TcpServerHost>();
}

public Task StartAsync(CancellationToken cancellationToken)
{
bossGroup = new DispatcherEventLoopGroup();
workerGroup = new WorkerEventLoopGroup(bossGroup, configuration.EventLoopCount);
serverBufferAllocator = new PooledByteBufferAllocator();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.Group(bossGroup, workerGroup);
bootstrap.Channel<TcpServerChannel>();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
|| RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
bootstrap
.Option(ChannelOption.SoReuseport, true)
.ChildOption(ChannelOption.SoReuseaddr, true);
}
bootstrap
.Option(ChannelOption.SoBacklog, configuration.SoBacklog)
.ChildOption(ChannelOption.Allocator, serverBufferAllocator)
.ChildHandler(new ActionChannelInitializer<IChannel>(channel =>
{
IChannelPipeline pipeline = channel.Pipeline;
using (var scope = serviceProvider.CreateScope())
{
channel.Pipeline.AddLast("jt809SystemIdleState", new IdleStateHandler(
configuration.ReaderIdleTimeSeconds,
configuration.WriterIdleTimeSeconds,
configuration.AllIdleTimeSeconds));
channel.Pipeline.AddLast("jt809TcpConnection", scope.ServiceProvider.GetRequiredService<JT809TcpConnectionHandler>());
channel.Pipeline.AddLast("jt809TcpBuffer", new DelimiterBasedFrameDecoder(int.MaxValue,
Unpooled.CopiedBuffer(new byte[] { JT809Package.BEGINFLAG }),
Unpooled.CopiedBuffer(new byte[] { JT809Package.ENDFLAG })));
channel.Pipeline.AddLast("jt809TcpDecode", scope.ServiceProvider.GetRequiredService<JT809TcpDecoder>());
channel.Pipeline.AddLast("jt809TcpService", scope.ServiceProvider.GetRequiredService<JT809TcpServerHandler>());
}
}));
logger.LogInformation($"JT809 TCP Server start at {IPAddress.Any}:{configuration.TcpPort}.");
return bootstrap.BindAsync(configuration.TcpPort)
.ContinueWith(i => bootstrapChannel = i.Result);
}

public async Task StopAsync(CancellationToken cancellationToken)
{
await bootstrapChannel.CloseAsync();
var quietPeriod = configuration.QuietPeriodTimeSpan;
var shutdownTimeout = configuration.ShutdownTimeoutTimeSpan;
await workerGroup.ShutdownGracefullyAsync(quietPeriod, shutdownTimeout);
await bossGroup.ShutdownGracefullyAsync(quietPeriod, shutdownTimeout);
}
}
}

+ 27
- 0
src/JT809.DotNetty.Tests/JT809.DotNetty.Host.Test/JT809.DotNetty.Host.Test.csproj View File

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

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\JT809.DotNetty.Tcp\JT809.DotNetty.Tcp.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

+ 54
- 0
src/JT809.DotNetty.Tests/JT809.DotNetty.Host.Test/Program.cs View File

@@ -0,0 +1,54 @@
using JT809.DotNetty.Core;
using JT809.DotNetty.Tcp;
using JT809.Protocol.Configs;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;

namespace JT809.DotNetty.Host.Test
{
class Program
{
static async Task Main(string[] args)
{
JT809.Protocol.JT809GlobalConfig.Instance
.SetHeaderOptions(new JT809HeaderOptions
{
MsgGNSSCENTERID = 20190222,
Version = new JT809.Protocol.JT809Header_Version(1, 0, 0),
EncryptKey = 9595
});

//主链路登录请求消息
//5B000000480000008510010134140E010000000000270F0134140E32303139303232323132372E302E302E31000000000000000000000000000000000000000000000003297B8D5D
//主链路注销请求消息
//5B000000260000008510030134140E010000000000270F0001E24031323334353600003FE15D
//主链路连接保持请求消息
//5B0000001A0000008510050134140E010000000000270FBA415D

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.Trace);
})
.ConfigureServices((hostContext, services) =>
{
services.AddSingleton<ILoggerFactory, LoggerFactory>();
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
services.AddJT809Core(hostContext.Configuration)
.AddJT809TcpHost();
});

await serverHostBuilder.RunConsoleAsync();
}
}
}

+ 18
- 0
src/JT809.DotNetty.Tests/JT809.DotNetty.Host.Test/appsettings.json View File

@@ -0,0 +1,18 @@
{
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Trace"
}
},
"Console": {
"LogLevel": {
"Default": "Trace"
}
}
},
"JT809Configuration": {

}
}

+ 31
- 0
src/JT809.DotNetty.Tests/JT809.DotNetty.Tcp.Test/JT809.DotNetty.Tcp.Test.csproj View File

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

<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="2.2.0" />
</ItemGroup>

<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\JT809.DotNetty.Tcp\JT809.DotNetty.Tcp.csproj" />
</ItemGroup>

</Project>

+ 37
- 0
src/JT809.DotNetty.Tests/JT809.DotNetty.Tcp.Test/TestBase.cs View File

@@ -0,0 +1,37 @@
using JT809.DotNetty.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT809.DotNetty.Tcp.Test
{
public class TestBase
{
public static IServiceProvider ServiceProvider;

static TestBase()
{
var serverHostBuilder = new HostBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory);
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
})
.ConfigureServices((hostContext, services) =>
{
services.AddSingleton<ILoggerFactory, LoggerFactory>();
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
services.AddJT809Core(hostContext.Configuration)
.AddJT809TcpHost();
});
var build = serverHostBuilder.Build();
build.Start();
ServiceProvider = build.Services;

}
}
}

+ 18
- 0
src/JT809.DotNetty.Tests/JT809.DotNetty.Tcp.Test/appsettings.json View File

@@ -0,0 +1,18 @@
{
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Trace"
}
},
"Console": {
"LogLevel": {
"Default": "Trace"
}
}
},
"JT809Configuration": {

}
}

+ 83
- 0
src/JT809.DotNetty.sln View File

@@ -0,0 +1,83 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2016
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT809Netty.Core", "JT809Netty.Core\JT809Netty.Core.csproj", "{2054D7E6-53B6-412F-BE9D-C6DABD80A111}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT809Netty.DownMasterLink", "JT809Netty.DownMasterLink\JT809Netty.DownMasterLink.csproj", "{3BF1D40D-A17D-4FBC-B3FF-B6DF8B3F13ED}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT809.DotNetty.Core", "JT809.DotNetty.Core\JT809.DotNetty.Core.csproj", "{0291C1D6-B4C6-4E7E-984B-0BAFB238727D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C712B2DE-34FE-4D9C-B574-A08B019246E4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT809.Protocol", "JT809.Protocol\src\JT809.Protocol\JT809.Protocol.csproj", "{321EE8EE-10D7-4233-8B8A-279BE68FB18A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT809.DotNetty.Tcp", "JT809.DotNetty.Tcp\JT809.DotNetty.Tcp.csproj", "{9BE94CDE-E813-403A-A68B-45C78BCAAF74}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT809.DotNetty.Abstractions", "JT809.DotNetty.Abstractions\JT809.DotNetty.Abstractions.csproj", "{EB8276CC-1848-4E7D-B77E-29B22AF767F0}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{DD4611CF-79A9-45C7-91EB-1E84D22B7D07}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT809.DotNetty.Tcp.Test", "JT809.DotNetty.Tests\JT809.DotNetty.Tcp.Test\JT809.DotNetty.Tcp.Test.csproj", "{560913C8-B618-46AD-B974-9D324F1ABBAC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT809.DotNetty.Host.Test", "JT809.DotNetty.Tests\JT809.DotNetty.Host.Test\JT809.DotNetty.Host.Test.csproj", "{D4E18559-C429-416F-9399-42C0E604D27B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT809.Protocol.Extensions.DependencyInjection", "JT809.Protocol\src\JT809.Protocol.Extensions.DependencyInjection\JT809.Protocol.Extensions.DependencyInjection.csproj", "{975D959C-7C0B-418E-838E-EB383E912F8C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2054D7E6-53B6-412F-BE9D-C6DABD80A111}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2054D7E6-53B6-412F-BE9D-C6DABD80A111}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2054D7E6-53B6-412F-BE9D-C6DABD80A111}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2054D7E6-53B6-412F-BE9D-C6DABD80A111}.Release|Any CPU.Build.0 = Release|Any CPU
{3BF1D40D-A17D-4FBC-B3FF-B6DF8B3F13ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3BF1D40D-A17D-4FBC-B3FF-B6DF8B3F13ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3BF1D40D-A17D-4FBC-B3FF-B6DF8B3F13ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3BF1D40D-A17D-4FBC-B3FF-B6DF8B3F13ED}.Release|Any CPU.Build.0 = Release|Any CPU
{0291C1D6-B4C6-4E7E-984B-0BAFB238727D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0291C1D6-B4C6-4E7E-984B-0BAFB238727D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0291C1D6-B4C6-4E7E-984B-0BAFB238727D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0291C1D6-B4C6-4E7E-984B-0BAFB238727D}.Release|Any CPU.Build.0 = Release|Any CPU
{321EE8EE-10D7-4233-8B8A-279BE68FB18A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{321EE8EE-10D7-4233-8B8A-279BE68FB18A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{321EE8EE-10D7-4233-8B8A-279BE68FB18A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{321EE8EE-10D7-4233-8B8A-279BE68FB18A}.Release|Any CPU.Build.0 = Release|Any CPU
{9BE94CDE-E813-403A-A68B-45C78BCAAF74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9BE94CDE-E813-403A-A68B-45C78BCAAF74}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9BE94CDE-E813-403A-A68B-45C78BCAAF74}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9BE94CDE-E813-403A-A68B-45C78BCAAF74}.Release|Any CPU.Build.0 = Release|Any CPU
{EB8276CC-1848-4E7D-B77E-29B22AF767F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EB8276CC-1848-4E7D-B77E-29B22AF767F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EB8276CC-1848-4E7D-B77E-29B22AF767F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EB8276CC-1848-4E7D-B77E-29B22AF767F0}.Release|Any CPU.Build.0 = Release|Any CPU
{560913C8-B618-46AD-B974-9D324F1ABBAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{560913C8-B618-46AD-B974-9D324F1ABBAC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{560913C8-B618-46AD-B974-9D324F1ABBAC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{560913C8-B618-46AD-B974-9D324F1ABBAC}.Release|Any CPU.Build.0 = Release|Any CPU
{D4E18559-C429-416F-9399-42C0E604D27B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D4E18559-C429-416F-9399-42C0E604D27B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D4E18559-C429-416F-9399-42C0E604D27B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D4E18559-C429-416F-9399-42C0E604D27B}.Release|Any CPU.Build.0 = Release|Any CPU
{975D959C-7C0B-418E-838E-EB383E912F8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{975D959C-7C0B-418E-838E-EB383E912F8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{975D959C-7C0B-418E-838E-EB383E912F8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{975D959C-7C0B-418E-838E-EB383E912F8C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{321EE8EE-10D7-4233-8B8A-279BE68FB18A} = {C712B2DE-34FE-4D9C-B574-A08B019246E4}
{560913C8-B618-46AD-B974-9D324F1ABBAC} = {DD4611CF-79A9-45C7-91EB-1E84D22B7D07}
{D4E18559-C429-416F-9399-42C0E604D27B} = {DD4611CF-79A9-45C7-91EB-1E84D22B7D07}
{975D959C-7C0B-418E-838E-EB383E912F8C} = {C712B2DE-34FE-4D9C-B574-A08B019246E4}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0FC2A52E-3B7A-4485-9C3B-9080C825419D}
EndGlobalSection
EndGlobal

+ 1
- 1
src/JT809.Protocol

@@ -1 +1 @@
Subproject commit b84dec6af9a812ea0ea02850987fd4455d1f20ee
Subproject commit 359a347cec6a1ee1ce3544d8ca399a94cadd9484

+ 0
- 31
src/JT809Netty.sln View File

@@ -1,31 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2016
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT809Netty.Core", "JT809Netty.Core\JT809Netty.Core.csproj", "{2054D7E6-53B6-412F-BE9D-C6DABD80A111}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT809Netty.DownMasterLink", "JT809Netty.DownMasterLink\JT809Netty.DownMasterLink.csproj", "{3BF1D40D-A17D-4FBC-B3FF-B6DF8B3F13ED}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2054D7E6-53B6-412F-BE9D-C6DABD80A111}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2054D7E6-53B6-412F-BE9D-C6DABD80A111}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2054D7E6-53B6-412F-BE9D-C6DABD80A111}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2054D7E6-53B6-412F-BE9D-C6DABD80A111}.Release|Any CPU.Build.0 = Release|Any CPU
{3BF1D40D-A17D-4FBC-B3FF-B6DF8B3F13ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3BF1D40D-A17D-4FBC-B3FF-B6DF8B3F13ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3BF1D40D-A17D-4FBC-B3FF-B6DF8B3F13ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3BF1D40D-A17D-4FBC-B3FF-B6DF8B3F13ED}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0FC2A52E-3B7A-4485-9C3B-9080C825419D}
EndGlobalSection
EndGlobal

Loading…
Cancel
Save