@@ -26,4 +26,20 @@ | |||
> 前提条件:需要安装kafka以及zookeeper | |||
 | |||
 | |||
## 作为下级平台(企业对企业) | |||
### 作为客户端主链路 | |||
主链路登录请求消息=>主链路登录应答消息=》成功=》主链路车辆动态信息交换_实时上传车辆定位信息消息 | |||
当没有发送定位数据时,需要发送主链路连接保持请求消息(心跳)=>主链路连接保持应答消息 | |||
### 作为服务端从链路 | |||
从链路连接请求消息=>从链路连接应答消息 | |||
从链路连接保持请求消息=>从链路连接保持应答消息 | |||
> 注意:作为下级平台发送数据时,有些企业需要双链路,有些企业只需要主链路发送数据,不管从链路,这时候就需要一个简单的从链路网关只负责简单的保持链路畅通。 |
@@ -6,14 +6,19 @@ using DotNetty.Transport.Channels; | |||
using DotNetty.Transport.Channels.Sockets; | |||
using JT809.DotNetty.Core.Codecs; | |||
using JT809.DotNetty.Core.Handlers; | |||
using JT809.DotNetty.Core.Interfaces; | |||
using JT809.DotNetty.Core.Metadata; | |||
using JT809.Protocol; | |||
using JT809.Protocol.Extensions; | |||
using JT809.Protocol.MessageBody; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.Logging; | |||
using Polly; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Net; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
namespace JT809.DotNetty.Core.Clients | |||
{ | |||
@@ -31,19 +36,20 @@ namespace JT809.DotNetty.Core.Clients | |||
private readonly ILogger<JT809MainClient> logger; | |||
private readonly ILoggerFactory loggerFactory; | |||
private readonly IServiceProvider serviceProvider; | |||
private bool disposed = false; | |||
private readonly IJT809ManualResetEvent manualResetEvent; | |||
public JT809MainClient( | |||
IJT809ManualResetEvent jT809ManualResetEvent, | |||
IServiceProvider provider, | |||
ILoggerFactory loggerFactory) | |||
{ | |||
this.serviceProvider = provider; | |||
this.loggerFactory = loggerFactory; | |||
this.logger = loggerFactory.CreateLogger<JT809MainClient>(); | |||
this.manualResetEvent = jT809ManualResetEvent; | |||
group = new MultithreadEventLoopGroup(); | |||
bootstrap = new Bootstrap(); | |||
bootstrap.Group(group) | |||
@@ -63,24 +69,43 @@ namespace JT809.DotNetty.Core.Clients | |||
pipeline.AddLast("jt809MainClientEncode", scope.ServiceProvider.GetRequiredService<JT809Encoder>()); | |||
pipeline.AddLast("jt809MainClientDecode", scope.ServiceProvider.GetRequiredService<JT809Decoder>()); | |||
pipeline.AddLast("jt809MainClientConnection", scope.ServiceProvider.GetRequiredService<JT809MainClientConnectionHandler>()); | |||
pipeline.AddLast("jt809MainClientServer", scope.ServiceProvider.GetRequiredService<JT809MainServerHandler>()); | |||
pipeline.AddLast("jt809MainClientServer", scope.ServiceProvider.GetRequiredService<JT809MainClientHandler>()); | |||
} | |||
})); | |||
} | |||
public async void ConnectAsync(string ip,int port) | |||
private JT809_0x1001 _jT809_0x1001; | |||
private IPEndPoint iPEndPoint; | |||
public async Task<bool> Login( | |||
string ip, | |||
int port, | |||
JT809_0x1001 jT809_0x1001) | |||
{ | |||
if (disposed) return await Task.FromResult(false); | |||
logger.LogInformation($"ip:{ip},port:{port}"); | |||
this._jT809_0x1001 = jT809_0x1001; | |||
this.iPEndPoint = new IPEndPoint(IPAddress.Parse(ip), port); | |||
bool successed = false; | |||
try | |||
{ | |||
//IPAddress[] hostinfo = Dns.GetHostAddresses(host); | |||
//IPAddress address = hostinfo[0]; | |||
if (channel == null) | |||
{ | |||
channel = await bootstrap.ConnectAsync(new IPEndPoint(IPAddress.Parse(ip), port)); | |||
} | |||
else | |||
{ | |||
await channel.CloseAsync(); | |||
channel = await bootstrap.ConnectAsync(new IPEndPoint(IPAddress.Parse(ip), port)); | |||
channel = await bootstrap.ConnectAsync(iPEndPoint); | |||
successed = channel.Open && channel.Active; | |||
if (channel.Open && channel.Active) | |||
{ | |||
//JT809.Protocol.MessageBody.JT809_0x1001 jT809_0X1001 = jT809_0X1001 new Protocol.MessageBody.JT809_0x1001(); | |||
//jT809_0X1001.DownLinkIP = downLinkIP; | |||
//jT809_0X1001.DownLinkPort = downLinkPort; | |||
//jT809_0X1001.UserId = userId; | |||
//jT809_0X1001.Password = password; | |||
var package = JT809.Protocol.Enums.JT809BusinessType.主链路登录请求消息.Create(_jT809_0x1001); | |||
await channel.WriteAndFlushAsync(new JT809Response(package, 100)); | |||
logger.LogInformation("等待登录应答结果..."); | |||
manualResetEvent.Pause(); | |||
} | |||
} | |||
} | |||
catch (AggregateException ex) | |||
@@ -91,16 +116,40 @@ namespace JT809.DotNetty.Core.Clients | |||
{ | |||
logger.LogError(ex, $"ip:{ip},port:{port}"); | |||
} | |||
return await Task.FromResult(successed); | |||
} | |||
public async void SendAsync(JT809Response jT809Response) | |||
{ | |||
if (disposed) return; | |||
if (channel == null) throw new NullReferenceException("Channel Not Open"); | |||
if (jT809Response == null) throw new ArgumentNullException("Data is null"); | |||
if (channel.Open && channel.Active) | |||
{ | |||
manualResetEvent.Pause(); | |||
await channel.WriteAndFlushAsync(jT809Response); | |||
} | |||
else | |||
{ | |||
manualResetEvent.Reset(); | |||
_ = Policy.HandleResult(channel.Open && channel.Active) | |||
.WaitAndRetryForeverAsync(retryAttempt => | |||
{ | |||
return TimeSpan.FromSeconds(10); | |||
}, (exception, timespan, ctx) => | |||
{ | |||
logger.LogError($"服务端断开{channel.RemoteAddress},重试结果{exception.Result},重试次数{timespan},下次重试间隔(s){ctx.TotalSeconds}"); | |||
}) | |||
.ExecuteAsync(async () => | |||
{ | |||
channel = await bootstrap.ConnectAsync(iPEndPoint); | |||
var package = JT809.Protocol.Enums.JT809BusinessType.主链路登录请求消息.Create(_jT809_0x1001); | |||
await channel.WriteAndFlushAsync(new JT809Response(package, 100)); | |||
logger.LogInformation("尝试重连,等待登录应答结果..."); | |||
manualResetEvent.Pause(); | |||
return await Task.FromResult(channel.Open && channel.Active); | |||
}); | |||
} | |||
} | |||
private void Dispose(bool disposing) | |||
@@ -0,0 +1,33 @@ | |||
using JT809.DotNetty.Core.Interfaces; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading; | |||
namespace JT809.DotNetty.Core.Events | |||
{ | |||
public class JT809InferoprManualResetEvent: IJT809ManualResetEvent | |||
{ | |||
private ManualResetEvent ManualResetEvent; | |||
public JT809InferoprManualResetEvent() | |||
{ | |||
ManualResetEvent = new ManualResetEvent(false); | |||
} | |||
public void Pause() | |||
{ | |||
ManualResetEvent.WaitOne(); | |||
} | |||
public bool Reset() | |||
{ | |||
return ManualResetEvent.Reset(); | |||
} | |||
public bool Resume() | |||
{ | |||
return ManualResetEvent.Set(); | |||
} | |||
} | |||
} |
@@ -9,6 +9,7 @@ using JT809.Protocol.Extensions; | |||
using JT809.Protocol.MessageBody; | |||
using Microsoft.Extensions.Logging; | |||
using Microsoft.Extensions.Options; | |||
using Newtonsoft.Json; | |||
namespace JT809.DotNetty.Core.Handlers | |||
{ | |||
@@ -20,26 +21,25 @@ namespace JT809.DotNetty.Core.Handlers | |||
{ | |||
protected JT809Configuration Configuration { get; } | |||
protected ILogger Logger { get; } | |||
protected IJT809ManualResetEvent ManualResetEvent { get; } | |||
/// <summary> | |||
/// 初始化消息处理业务 | |||
/// </summary> | |||
protected JT809InferiorMsgIdReceiveHandlerBase( | |||
ILoggerFactory loggerFactory, | |||
IOptions<JT809Configuration> jT809ConfigurationAccessor, | |||
IJT809VerifyCodeGenerator verifyCodeGenerator, | |||
JT809SubordinateClient subordinateLinkClient) | |||
IJT809ManualResetEvent jT809ManualResetEvent, | |||
ILoggerFactory loggerFactory) | |||
{ | |||
this.Logger = loggerFactory.CreateLogger<JT809SuperiorMsgIdReceiveHandlerBase>(); | |||
this.ManualResetEvent = jT809ManualResetEvent; | |||
HandlerDict = new Dictionary<JT809BusinessType, Func<JT809Request, JT809Response>> | |||
{ | |||
//{JT809BusinessType.主链路登录请求消息, Msg0x1001}, | |||
{JT809BusinessType.主链路注销请求消息, Msg0x1003}, | |||
{JT809BusinessType.主链路连接保持请求消息, Msg0x1005}, | |||
{JT809BusinessType.主链路动态信息交换消息, Msg0x1200}, | |||
{JT809BusinessType.从链路注销应答消息, Msg0x9004}, | |||
{JT809BusinessType.主链路登录应答消息,Msg0x1002}, | |||
{JT809BusinessType.主链路连接保持应答消息,Msg0x1006}, | |||
{JT809BusinessType.从链路连接请求消息,Msg0x9001}, | |||
{JT809BusinessType.从链路注销请求消息, Msg0x9003}, | |||
{JT809BusinessType.从链路连接保持请求消息,Msg0x9005 }, | |||
}; | |||
SubHandlerDict = new Dictionary<JT809SubBusinessType, Func<JT809Request, JT809Response>> | |||
{ | |||
//{JT809SubBusinessType.实时上传车辆定位信息, Msg0x1200_0x1202}, | |||
@@ -50,69 +50,83 @@ namespace JT809.DotNetty.Core.Handlers | |||
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 verifyCode = VerifyCodeGenerator.Create(); | |||
// Logger.LogInformation($"VerifyCode-{verifyCode}"); | |||
// var package = JT809BusinessType.主链路登录应答消息.Create(new JT809_0x1002() | |||
// { | |||
// Result = JT809_0x1002_Result.成功, | |||
// VerifyCode = verifyCode | |||
// }); | |||
// if (Configuration.SubordinateClientEnable) | |||
// { | |||
// var jT809_0x1001 = request.Package.Bodies as JT809_0x1001; | |||
// SubordinateLinkClient.ConnectAsync(jT809_0x1001.DownLinkIP, jT809_0x1001.DownLinkPort, verifyCode); | |||
// } | |||
// return new JT809Response(package, 100); | |||
//} | |||
/// <returns></returns> | |||
public virtual JT809Response Msg0x1002(JT809Request request) | |||
{ | |||
if (Logger.IsEnabled(LogLevel.Information)) | |||
{ | |||
Logger.LogInformation(JsonConvert.SerializeObject(request)); | |||
} | |||
var jT809_0x1002 = request.Package.Bodies as JT809_0x1002; | |||
if(jT809_0x1002.Result== JT809_0x1002_Result.成功) | |||
{ | |||
ManualResetEvent.Resume(); | |||
} | |||
return null; | |||
} | |||
/// <summary> | |||
/// 主链路注销请求消息 | |||
/// 主链路连接保持应答消息 | |||
/// </summary> | |||
/// <param name="request"></param> | |||
/// <returns>主链路注销应答消息</returns> | |||
public virtual JT809Response Msg0x1003(JT809Request request) | |||
/// <returns></returns> | |||
public virtual JT809Response Msg0x1006(JT809Request request) | |||
{ | |||
var package = JT809BusinessType.主链路注销应答消息.Create(); | |||
return new JT809Response(package, 100); | |||
if (Logger.IsEnabled(LogLevel.Information)) | |||
{ | |||
Logger.LogInformation(JsonConvert.SerializeObject(request)); | |||
} | |||
return null; | |||
} | |||
/// <summary> | |||
/// 主链路连接保持请求消息 | |||
/// 从链路连接请求消息 | |||
/// </summary> | |||
/// <param name="request"></param> | |||
/// <returns>主链路连接保持应答消息</returns> | |||
public virtual JT809Response Msg0x1005(JT809Request request) | |||
/// <returns>从链路连接应答消息</returns> | |||
public virtual JT809Response Msg0x9001(JT809Request request) | |||
{ | |||
var package = JT809BusinessType.主链路连接保持应答消息.Create(); | |||
var package = JT809BusinessType.从链路连接应答消息.Create(new JT809_0x9002 { | |||
Result = JT809_0x9002_Result.成功 | |||
}); | |||
if (Logger.IsEnabled(LogLevel.Information)) | |||
{ | |||
Logger.LogInformation(JsonConvert.SerializeObject(request)); | |||
} | |||
return new JT809Response(package, 100); | |||
} | |||
/// <summary> | |||
/// 主链路动态信息交换消息 | |||
/// 从链路注销请求消息 | |||
/// </summary> | |||
/// <param name="request"></param> | |||
/// <returns></returns> | |||
public virtual JT809Response Msg0x1200(JT809Request request) | |||
/// <returns>从链路注销应答消息</returns> | |||
public virtual JT809Response Msg0x9003(JT809Request request) | |||
{ | |||
return null; | |||
var package = JT809BusinessType.从链路注销应答消息.Create(); | |||
if (Logger.IsEnabled(LogLevel.Information)) | |||
{ | |||
Logger.LogInformation(JsonConvert.SerializeObject(request)); | |||
} | |||
return new JT809Response(package, 100); | |||
} | |||
/// <summary> | |||
/// | |||
/// 从链路连接保持请求消息 | |||
/// </summary> | |||
/// <param name="request"></param> | |||
/// <returns>从链路注销应答消息</returns> | |||
public virtual JT809Response Msg0x9004(JT809Request request) | |||
/// <returns>从链路连接保持应答消息</returns> | |||
public virtual JT809Response Msg0x9005(JT809Request request) | |||
{ | |||
return null; | |||
var package = JT809BusinessType.从链路连接保持应答消息.Create(); | |||
if (Logger.IsEnabled(LogLevel.Information)) | |||
{ | |||
Logger.LogInformation(JsonConvert.SerializeObject(request)); | |||
} | |||
return new JT809Response(package, 100); | |||
} | |||
} | |||
} |
@@ -16,7 +16,6 @@ namespace JT809.DotNetty.Core.Handlers | |||
private readonly ILogger<JT809SubordinateServerConnectionHandler> logger; | |||
public JT809SubordinateServerConnectionHandler( | |||
JT809SubordinateClient subordinateClient, | |||
ILoggerFactory loggerFactory) | |||
{ | |||
logger = loggerFactory.CreateLogger<JT809SubordinateServerConnectionHandler>(); | |||
@@ -73,10 +72,7 @@ namespace JT809.DotNetty.Core.Handlers | |||
{ | |||
if (idleStateEvent.State == IdleState.ReaderIdle) | |||
{ | |||
if (idleStateEvent.State == IdleState.ReaderIdle) | |||
{ | |||
context.CloseAsync(); | |||
} | |||
context.CloseAsync(); | |||
} | |||
} | |||
base.UserEventTriggered(context, evt); | |||
@@ -0,0 +1,13 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT809.DotNetty.Core.Interfaces | |||
{ | |||
public interface IJT809ManualResetEvent | |||
{ | |||
void Pause(); | |||
bool Resume(); | |||
bool Reset(); | |||
} | |||
} |
@@ -17,7 +17,7 @@ namespace JT809.DotNetty.Core.Internal | |||
/// </summary> | |||
internal class JT809InferiorMsgIdReceiveDefaultHandler : JT809InferiorMsgIdReceiveHandlerBase | |||
{ | |||
public JT809InferiorMsgIdReceiveDefaultHandler(ILoggerFactory loggerFactory, IOptions<JT809Configuration> jT809ConfigurationAccessor, IJT809VerifyCodeGenerator verifyCodeGenerator, JT809SubordinateClient subordinateLinkClient) : base(loggerFactory, jT809ConfigurationAccessor, verifyCodeGenerator, subordinateLinkClient) | |||
public JT809InferiorMsgIdReceiveDefaultHandler(IJT809ManualResetEvent jT809ManualResetEvent, ILoggerFactory loggerFactory) : base(jT809ManualResetEvent, loggerFactory) | |||
{ | |||
} | |||
} | |||
@@ -19,6 +19,7 @@ using System.Runtime.CompilerServices; | |||
using Microsoft.Extensions.Options; | |||
using JT808.DotNetty.WebApi; | |||
using JT809.DotNetty.Core.Session; | |||
using JT809.DotNetty.Core.Events; | |||
[assembly: InternalsVisibleTo("JT809.DotNetty.Core.Test")] | |||
@@ -83,15 +84,35 @@ namespace JT809.DotNetty.Core | |||
//主从链路接收消息默认业务处理器 | |||
serviceDescriptors.TryAddSingleton<JT809InferiorMsgIdReceiveHandlerBase, JT809InferiorMsgIdReceiveDefaultHandler>(); | |||
//主从链路消息接收处理器 | |||
serviceDescriptors.TryAddScoped<JT809MainServerHandler>(); | |||
serviceDescriptors.TryAddScoped<JT809SubordinateServerHandler>(); | |||
//主链路客户端 | |||
serviceDescriptors.TryAddSingleton<JT809MainClient>(); | |||
//serviceDescriptors.TryAddSingleton<JT809MainClient>(); | |||
//从链路服务端 | |||
serviceDescriptors.AddHostedService<JT809SubordinateServerHost>(); | |||
return serviceDescriptors; | |||
} | |||
/// <summary> | |||
/// 下级平台 | |||
/// 主链路为客户端 | |||
/// 从链路为服务端 | |||
/// </summary> | |||
/// <param name="serviceDescriptors"></param> | |||
/// <returns></returns> | |||
public static IServiceCollection AddJT809InferiorPlatformClient(this IServiceCollection serviceDescriptors) | |||
{ | |||
serviceDescriptors.TryAddSingleton<IJT809ManualResetEvent, JT809InferoprManualResetEvent>(); | |||
//主从链路客户端和服务端连接处理器 | |||
serviceDescriptors.TryAddScoped<JT809MainClientConnectionHandler>(); | |||
//主从链路接收消息默认业务处理器 | |||
serviceDescriptors.TryAddSingleton<JT809InferiorMsgIdReceiveHandlerBase, JT809InferiorMsgIdReceiveDefaultHandler>(); | |||
//主从链路消息接收处理器 | |||
serviceDescriptors.TryAddScoped<JT809MainClientHandler>(); | |||
//主链路客户端 | |||
serviceDescriptors.TryAddSingleton<JT809MainClient>(); | |||
return serviceDescriptors; | |||
} | |||
/// <summary> | |||
/// 上级平台 | |||
@@ -33,7 +33,6 @@ namespace JT809.DotNetty.Core.Servers | |||
private WorkerEventLoopGroup workerGroup; | |||
private IChannel bootstrapChannel; | |||
private IByteBufferAllocator serverBufferAllocator; | |||
private ILoggerFactory loggerFactory; | |||
public JT809SubordinateServerHost( | |||
IServiceProvider provider, | |||
@@ -43,7 +42,6 @@ namespace JT809.DotNetty.Core.Servers | |||
serviceProvider = provider; | |||
configuration = jT809ConfigurationAccessor.Value; | |||
logger = loggerFactory.CreateLogger<JT809SubordinateServerHost>(); | |||
this.loggerFactory = loggerFactory; | |||
} | |||
public Task StartAsync(CancellationToken cancellationToken) | |||
@@ -0,0 +1,24 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<OutputType>Exe</OutputType> | |||
<TargetFramework>netcoreapp2.2</TargetFramework> | |||
<LangVersion>7.3</LangVersion> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="JT809.Extensions.DependencyInjection" Version="1.2.1" /> | |||
<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.Core\JT809.DotNetty.Core.csproj" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Update="appsettings.json"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
</ItemGroup> | |||
</Project> |
@@ -0,0 +1,119 @@ | |||
using JT809.DotNetty.Core.Clients; | |||
using JT809.DotNetty.Core.Metadata; | |||
using JT809.Protocol.Extensions; | |||
using Microsoft.Extensions.Hosting; | |||
using Microsoft.Extensions.Logging; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
using JT809.Protocol.SubMessageBody; | |||
using JT809.Protocol.Metadata; | |||
using JT809.Protocol.MessageBody; | |||
namespace JT809.Inferior.Client | |||
{ | |||
public class JT809InferiorService : IHostedService | |||
{ | |||
private readonly JT809MainClient mainClient; | |||
private readonly ILogger<JT809InferiorService> logger; | |||
public JT809InferiorService( | |||
ILoggerFactory loggerFactory, | |||
JT809MainClient mainClient) | |||
{ | |||
this.mainClient = mainClient; | |||
logger = loggerFactory.CreateLogger<JT809InferiorService>(); | |||
} | |||
public Task StartAsync(CancellationToken cancellationToken) | |||
{ | |||
//5B0000001F0000053B100201341725010000000000270F00000004E8A6F25D | |||
var connect = mainClient.Login("127.0.0.1", 809, new JT809_0x1001 | |||
{ | |||
DownLinkIP = "127.0.0.1", | |||
DownLinkPort = 1809, | |||
UserId = 123456, | |||
Password = "12345678" | |||
}).Result; | |||
if (connect) | |||
{ | |||
Task.Run(() => | |||
{ | |||
while (true) | |||
{ | |||
JT809.Protocol.MessageBody.JT809_0x1200 jT809_0X1200 = new Protocol.MessageBody.JT809_0x1200(); | |||
jT809_0X1200.VehicleColor = Protocol.Enums.JT809VehicleColorType.黄色; | |||
jT809_0X1200.VehicleNo = "粤A12345"; | |||
jT809_0X1200.SubBusinessType = Protocol.Enums.JT809SubBusinessType.实时上传车辆定位信息; | |||
jT809_0X1200.SubBodies = new JT809_0x1200_0x1202() | |||
{ | |||
VehiclePosition = new JT809VehiclePositionProperties | |||
{ | |||
Day = (byte)(DateTime.Now.Day), | |||
Month = (byte)(DateTime.Now.Month), | |||
Year = (byte)(DateTime.Now.Year), | |||
Hour = (byte)(DateTime.Now.Hour), | |||
Minute = (byte)(DateTime.Now.Minute), | |||
Second = (byte)(DateTime.Now.Second), | |||
Alarm = 1, | |||
Direction = 2, | |||
State = 2, | |||
Altitude = 32, | |||
Lat = 122334565, | |||
Lon = 12354563, | |||
Vec1 = 112, | |||
Vec2 = 22, | |||
Vec3 = 12 | |||
} | |||
}; | |||
var package = JT809.Protocol.Enums.JT809BusinessType.主链路动态信息交换消息.Create(jT809_0X1200); | |||
mainClient.SendAsync(new JT809Response(package, 256)); | |||
logger.LogDebug($"Thread:{Thread.CurrentThread.ManagedThreadId}-2s"); | |||
Thread.Sleep(2000); | |||
} | |||
}); | |||
Task.Run(() => | |||
{ | |||
while (true) | |||
{ | |||
JT809.Protocol.MessageBody.JT809_0x1200 jT809_0X1200 = new Protocol.MessageBody.JT809_0x1200(); | |||
jT809_0X1200.VehicleColor = Protocol.Enums.JT809VehicleColorType.黄色; | |||
jT809_0X1200.VehicleNo = "粤A12346"; | |||
jT809_0X1200.SubBusinessType = Protocol.Enums.JT809SubBusinessType.实时上传车辆定位信息; | |||
jT809_0X1200.SubBodies = new JT809_0x1200_0x1202() | |||
{ | |||
VehiclePosition = new JT809VehiclePositionProperties | |||
{ | |||
Day = (byte)(DateTime.Now.Day), | |||
Month = (byte)(DateTime.Now.Month), | |||
Year = (byte)(DateTime.Now.Year), | |||
Hour = (byte)(DateTime.Now.Hour), | |||
Minute = (byte)(DateTime.Now.Minute), | |||
Second = (byte)(DateTime.Now.Second), | |||
Alarm = 1, | |||
Direction = 2, | |||
State = 2, | |||
Altitude = 32, | |||
Lat = 122334565, | |||
Lon = 12354563, | |||
Vec1 = 112, | |||
Vec2 = 22, | |||
Vec3 = 12 | |||
} | |||
}; | |||
var package = JT809.Protocol.Enums.JT809BusinessType.主链路动态信息交换消息.Create(jT809_0X1200); | |||
mainClient.SendAsync(new JT809Response(package, 256)); | |||
logger.LogDebug($"Thread:{Thread.CurrentThread.ManagedThreadId}-4s"); | |||
Thread.Sleep(4000); | |||
} | |||
}); | |||
} | |||
return Task.CompletedTask; | |||
} | |||
public Task StopAsync(CancellationToken cancellationToken) | |||
{ | |||
return Task.CompletedTask; | |||
} | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
using JT809.DotNetty.Core; | |||
using JT809.DotNetty.Core.Handlers; | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.DependencyInjection.Extensions; | |||
using Microsoft.Extensions.Hosting; | |||
using Microsoft.Extensions.Logging; | |||
using System; | |||
using System.Threading.Tasks; | |||
using JT809.Protocol.Extensions.DependencyInjection; | |||
using JT809.Protocol.Extensions.DependencyInjection.Options; | |||
namespace JT809.Inferior.Client | |||
{ | |||
class Program | |||
{ | |||
static async Task Main(string[] args) | |||
{ | |||
var serverHostBuilder = new HostBuilder() | |||
.ConfigureAppConfiguration((hostingContext, config) => | |||
{ | |||
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory); | |||
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); | |||
}) | |||
.ConfigureLogging((context, logging) => | |||
{ | |||
logging.AddConsole(); | |||
logging.SetMinimumLevel(LogLevel.Trace); | |||
}) | |||
.ConfigureServices((hostContext, services) => | |||
{ | |||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||
services.AddJT809Configure(new JT809Options | |||
{ | |||
HeaderOptions = new Protocol.Configs.JT809HeaderOptions | |||
{ | |||
MsgGNSSCENTERID = 100210, | |||
} | |||
}); | |||
services.AddJT809Core(hostContext.Configuration) | |||
.AddJT809InferiorPlatformClient(); | |||
services.AddHostedService<JT809InferiorService>(); | |||
}); | |||
await serverHostBuilder.RunConsoleAsync(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,15 @@ | |||
{ | |||
"Logging": { | |||
"IncludeScopes": false, | |||
"Debug": { | |||
"LogLevel": { | |||
"Default": "Trace" | |||
} | |||
}, | |||
"Console": { | |||
"LogLevel": { | |||
"Default": "Trace" | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<OutputType>Exe</OutputType> | |||
<TargetFramework>netcoreapp2.2</TargetFramework> | |||
<LangVersion>7.3</LangVersion> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="JT809.Extensions.DependencyInjection" Version="1.2.1" /> | |||
<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.Core\JT809.DotNetty.Core.csproj" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Update="appsettings.json"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
</ItemGroup> | |||
</Project> |
@@ -0,0 +1,55 @@ | |||
using JT809.DotNetty.Core; | |||
using JT809.DotNetty.Core.Handlers; | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.DependencyInjection.Extensions; | |||
using Microsoft.Extensions.Hosting; | |||
using Microsoft.Extensions.Logging; | |||
using System; | |||
using System.Threading.Tasks; | |||
using JT809.Protocol.Extensions.DependencyInjection; | |||
using JT809.Protocol.Extensions.DependencyInjection.Options; | |||
namespace JT809.Inferior.Server | |||
{ | |||
class Program | |||
{ | |||
static async Task Main(string[] args) | |||
{ | |||
//作为从链路服务器,接收上级平台连接请求包括 | |||
//1.从链路连接请求消息-从链路连接应答消息 | |||
//5B 00 00 00 1B 00 00 00 02 90 02 00 01 87 72 01 00 00 00 00 00 00 00 00 AB 10 5D | |||
//2.从链路连接保持请求消息-从链路连接保持应答消息 | |||
//5B 00 00 00 1A 00 00 00 03 90 06 00 01 87 72 01 00 00 00 00 00 00 00 64 E7 5D | |||
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.AddJT809Configure(new JT809Options | |||
{ | |||
HeaderOptions=new Protocol.Configs.JT809HeaderOptions | |||
{ | |||
MsgGNSSCENTERID=100210 | |||
} | |||
}); | |||
services.AddJT809Core(hostContext.Configuration) | |||
.AddJT809InferiorPlatform(options: options => { | |||
options.TcpPort = 809; | |||
}); | |||
}); | |||
await serverHostBuilder.RunConsoleAsync(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,15 @@ | |||
{ | |||
"Logging": { | |||
"IncludeScopes": false, | |||
"Debug": { | |||
"LogLevel": { | |||
"Default": "Trace" | |||
} | |||
}, | |||
"Console": { | |||
"LogLevel": { | |||
"Default": "Trace" | |||
} | |||
} | |||
} | |||
} |
@@ -27,9 +27,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT809.KafkaService", "JT809 | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT809.KafkaServiceTest", "JT809.DotNetty.Simples\Superior\JT809.KafkaServiceTest\JT809.KafkaServiceTest.csproj", "{22F008D5-61F8-4889-80DB-91B37591322F}" | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT809.Superior.Server", "JT809.DotNetty.Simples\Superior\JT809.Superior.Server\JT809.Superior.Server.csproj", "{8620735D-FBD5-4832-882F-A2F607DC6861}" | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT809.Superior.Server", "JT809.DotNetty.Simples\Superior\JT809.Superior.Server\JT809.Superior.Server.csproj", "{8620735D-FBD5-4832-882F-A2F607DC6861}" | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT809.GpsConsumer", "JT809.DotNetty.Simples\Superior\JT809.GpsConsumer\JT809.GpsConsumer.csproj", "{FBC06008-6F18-4CC3-B7C2-5B476317F92D}" | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT809.GpsConsumer", "JT809.DotNetty.Simples\Superior\JT809.GpsConsumer\JT809.GpsConsumer.csproj", "{FBC06008-6F18-4CC3-B7C2-5B476317F92D}" | |||
EndProject | |||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Inferior", "Inferior", "{139F3035-EAC2-42A8-9123-1F7E6B79AFEB}" | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT809.Inferior.Server", "JT809.DotNetty.Simples\Inferior\JT809.Inferior.Server\JT809.Inferior.Server.csproj", "{126FFC37-3ABF-4537-A0DD-3FC609F853EF}" | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT809.Inferior.Client", "JT809.DotNetty.Simples\Inferior\JT809.Inferior.Client\JT809.Inferior.Client.csproj", "{5990307A-4EE9-40B7-80E8-5AE2E7697287}" | |||
EndProject | |||
Global | |||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
@@ -77,6 +83,14 @@ Global | |||
{FBC06008-6F18-4CC3-B7C2-5B476317F92D}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{FBC06008-6F18-4CC3-B7C2-5B476317F92D}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{FBC06008-6F18-4CC3-B7C2-5B476317F92D}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{126FFC37-3ABF-4537-A0DD-3FC609F853EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{126FFC37-3ABF-4537-A0DD-3FC609F853EF}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{126FFC37-3ABF-4537-A0DD-3FC609F853EF}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{126FFC37-3ABF-4537-A0DD-3FC609F853EF}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{5990307A-4EE9-40B7-80E8-5AE2E7697287}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{5990307A-4EE9-40B7-80E8-5AE2E7697287}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{5990307A-4EE9-40B7-80E8-5AE2E7697287}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{5990307A-4EE9-40B7-80E8-5AE2E7697287}.Release|Any CPU.Build.0 = Release|Any CPU | |||
EndGlobalSection | |||
GlobalSection(SolutionProperties) = preSolution | |||
HideSolutionNode = FALSE | |||
@@ -91,6 +105,9 @@ Global | |||
{22F008D5-61F8-4889-80DB-91B37591322F} = {E9DC871D-EFCE-4D53-A5B5-8A88D2D52EA4} | |||
{8620735D-FBD5-4832-882F-A2F607DC6861} = {E9DC871D-EFCE-4D53-A5B5-8A88D2D52EA4} | |||
{FBC06008-6F18-4CC3-B7C2-5B476317F92D} = {E9DC871D-EFCE-4D53-A5B5-8A88D2D52EA4} | |||
{139F3035-EAC2-42A8-9123-1F7E6B79AFEB} = {3C761892-4ED8-42D2-96CF-F76041D17EC1} | |||
{126FFC37-3ABF-4537-A0DD-3FC609F853EF} = {139F3035-EAC2-42A8-9123-1F7E6B79AFEB} | |||
{5990307A-4EE9-40B7-80E8-5AE2E7697287} = {139F3035-EAC2-42A8-9123-1F7E6B79AFEB} | |||
EndGlobalSection | |||
GlobalSection(ExtensibilityGlobals) = postSolution | |||
SolutionGuid = {0FC2A52E-3B7A-4485-9C3B-9080C825419D} | |||