车辆协议开发

master
smartwyy 6 months ago
parent 2fef57535e
commit 00536ce172

@ -8,6 +8,7 @@
".NETCoreApp,Version=v6.0": {
"HybirdFrameworkCore/1.0.0": {
"dependencies": {
"AutoMapper": "12.0.1",
"Autofac": "7.0.1",
"Microsoft.Extensions.Configuration.Abstractions": "7.0.0",
"Microsoft.Extensions.Configuration.Json": "7.0.0",
@ -30,6 +31,17 @@
}
}
},
"AutoMapper/12.0.1": {
"dependencies": {
"Microsoft.CSharp": "4.7.0"
},
"runtime": {
"lib/netstandard2.1/AutoMapper.dll": {
"assemblyVersion": "12.0.0.0",
"fileVersion": "12.0.1.0"
}
}
},
"log4net/2.0.15": {
"dependencies": {
"System.Configuration.ConfigurationManager": "4.5.0"
@ -41,6 +53,7 @@
}
}
},
"Microsoft.CSharp/4.7.0": {},
"Microsoft.Extensions.Configuration/7.0.0": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "7.0.0",
@ -283,6 +296,13 @@
"path": "autofac/7.0.1",
"hashPath": "autofac.7.0.1.nupkg.sha512"
},
"AutoMapper/12.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-hvV62vl6Hp/WfQ24yzo3Co9+OPl8wH8hApwVtgWpiAynVJkUcs7xvehnSftawL8Pe8FrPffBRM3hwzLQqWDNjA==",
"path": "automapper/12.0.1",
"hashPath": "automapper.12.0.1.nupkg.sha512"
},
"log4net/2.0.15": {
"type": "package",
"serviceable": true,
@ -290,6 +310,13 @@
"path": "log4net/2.0.15",
"hashPath": "log4net.2.0.15.nupkg.sha512"
},
"Microsoft.CSharp/4.7.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==",
"path": "microsoft.csharp/4.7.0",
"hashPath": "microsoft.csharp.4.7.0.nupkg.sha512"
},
"Microsoft.Extensions.Configuration/7.0.0": {
"type": "package",
"serviceable": true,

@ -1,5 +1,4 @@
using System.Collections.Concurrent;
using DotNetty.Buffers;
using DotNetty.Transport.Channels;
using log4net;
@ -25,7 +24,7 @@ public class IoSession
public ConcurrentDictionary<string, object> BusinessMap { get; } = new();
public void Send(IByteBuffer buffer)
public void Send(Object buffer)
{
Channel.WriteAndFlushAsync(buffer);
}

@ -1,5 +1,4 @@
using System.Collections.Concurrent;
using DotNetty.Buffers;
using DotNetty.Transport.Channels;
using log4net;
@ -83,9 +82,9 @@ public class SessionMgr
}
public static void Broadcast(IByteBuffer buffer, ConcurrentDictionary<string, IoSession> dictionary)
public static void Broadcast(Object buffer)
{
foreach (var session in dictionary.Values) session.Send(buffer);
foreach (var session in Dictionary.Values) session.Send(buffer);
}
public static object GetAttr(IoSession session, string key)

@ -13,6 +13,8 @@ public class ServerListenerHandler<TH, TD, TE> : ChannelHandlerAdapter where TH
{
private static readonly ILog Log = LogManager.GetLogger(typeof(ServerListenerHandler<TH, TD, TE>));
public Action? ChannelInActiveAction { get; set; }
public override void ChannelRegistered(IChannelHandlerContext context)
{
base.ChannelRegistered(context);
@ -35,6 +37,11 @@ public class ServerListenerHandler<TH, TD, TE> : ChannelHandlerAdapter where TH
public override void ChannelInactive(IChannelHandlerContext context)
{
base.ChannelInactive(context);
if (ChannelInActiveAction != null)
{
ChannelInActiveAction();
}
SessionMgr.UnregisterSession(context.Channel);
Log.Info("inactive " + context.Channel);
}

@ -2,6 +2,7 @@
using Autofac;
using Autofac.Core;
using DotNetty.Codecs;
using DotNetty.Common.Internal.Logging;
using DotNetty.Handlers.Logging;
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Bootstrapping;
@ -10,6 +11,8 @@ using DotNetty.Transport.Channels.Sockets;
using HybirdFrameworkCore.Autofac;
using HybirdFrameworkCore.Autofac.Attribute;
using log4net;
using Microsoft.Extensions.Logging;
using LogLevel = DotNetty.Handlers.Logging.LogLevel;
namespace HybirdFrameworkDriver.TcpServer;
@ -27,9 +30,18 @@ public class TcpServer<TH, TD, TE> : IDisposable where TH : IChannelHandler
private static ServerBootstrap? bootstrap;
private int _port = 9000;
public LogLevel? LogLevel { get; set; }
public Action? ChannelInActiveAction { get; set; }
public TcpServer()
{
if (LogLevel != null)
{
InternalLoggerFactory.DefaultFactory.AddProvider(new Log4NetProvider());
}
bossGroup = new MultithreadEventLoopGroup();
workerGroup = new MultithreadEventLoopGroup();
bootstrap = new ServerBootstrap();
@ -40,9 +52,12 @@ public class TcpServer<TH, TD, TE> : IDisposable where TH : IChannelHandler
.Handler(new LoggingHandler())
.ChildHandler(new ActionChannelInitializer<ISocketChannel>(channel =>
{
var serverListenerHandler = new ServerListenerHandler<TH, TD, TE>();
var serverListenerHandler = new ServerListenerHandler<TH, TD, TE>
{
ChannelInActiveAction = ChannelInActiveAction
};
var pipeline = channel.Pipeline;
pipeline.AddLast(new LoggingHandler(""));
pipeline.AddLast(new LoggingHandler());
pipeline.AddLast(serverListenerHandler);
pipeline.AddLast(new IdleStateHandler(0, 0, 180)); //检测空闲连接
//业务handler 这里是实际处理业务的Handler

@ -0,0 +1,33 @@
using DotNetty.Transport.Channels;
using HybirdFrameworkCore.Autofac.Attribute;
using Service.Car.Msg.Car.Req;
using Service.Car.Msg.Host.Resp;
using Service.Car.Server;
namespace Service.Car.Handler;
/// <summary>
///
/// </summary>
[Order(8)]
[Scope("InstancePerDependency")]
public class ElecMsgHandler : SimpleChannelInboundHandler<ElecMsg>, IBaseHandler
{
/// <summary>
///
/// </summary>
/// <param name="ctx"></param>
/// <param name="msg"></param>
/// <exception cref="NotImplementedException"></exception>
protected override void ChannelRead0(IChannelHandlerContext ctx, ElecMsg msg)
{
CarServerMgr.CarServer.Connected = true;
CarServerMgr.CarServer.ElecMsg = msg;
ElecMsgResp resp = new ElecMsgResp( 0)
{
CarNo = msg.CarNo
};
resp.InitCurrentTime();
ctx.Channel.WriteAndFlushAsync(resp);
}
}

@ -0,0 +1,34 @@
using DotNetty.Transport.Channels;
using HybirdFrameworkCore.Autofac.Attribute;
using Service.Car.Msg.Car.Req;
using Service.Car.Msg.Host.Resp;
using Service.Car.Server;
namespace Service.Car.Handler;
/// <summary>
///
/// </summary>
[Order(8)]
[Scope("InstancePerDependency")]
public class HeartBeatMsgHandler : SimpleChannelInboundHandler<HeartBeatMsg>, IBaseHandler
{
/// <summary>
///
/// </summary>
/// <param name="ctx"></param>
/// <param name="msg"></param>
/// <exception cref="NotImplementedException"></exception>
protected override void ChannelRead0(IChannelHandlerContext ctx, HeartBeatMsg msg)
{
CarServerMgr.CarServer.Connected = true;
CarServerMgr.CarServer.CarNo = msg.CarNo;
CarServerMgr.CarServer.HeartBeatMsg = msg;
HeartBeatMsgResp resp = new HeartBeatMsgResp( CarServerMgr.CarServer.StationStatus)
{
CarNo = msg.CarNo
};
resp.InitCurrentTime();
ctx.Channel.WriteAndFlushAsync(resp);
}
}

@ -0,0 +1,26 @@
using DotNetty.Transport.Channels;
using HybirdFrameworkCore.Autofac.Attribute;
using Service.Car.Msg.Car.Resp;
using Service.Car.Server;
namespace Service.Car.Handler;
/// <summary>
///
/// </summary>
[Order(8)]
[Scope("InstancePerDependency")]
public class LockMsgRespHandler : SimpleChannelInboundHandler<LockMsgResp>, IBaseHandler
{
/// <summary>
///
/// </summary>
/// <param name="ctx"></param>
/// <param name="msg"></param>
/// <exception cref="NotImplementedException"></exception>
protected override void ChannelRead0(IChannelHandlerContext ctx, LockMsgResp msg)
{
CarServerMgr.CarServer.Connected = true;
CarServerMgr.CarServer.LockMsgResp = msg;
}
}

@ -0,0 +1,26 @@
using DotNetty.Transport.Channels;
using HybirdFrameworkCore.Autofac.Attribute;
using Service.Car.Msg.Car.Resp;
using Service.Car.Server;
namespace Service.Car.Handler;
/// <summary>
///
/// </summary>
[Order(8)]
[Scope("InstancePerDependency")]
public class SetParamMsgRespHandler : SimpleChannelInboundHandler<SetParamMsgResp>, IBaseHandler
{
/// <summary>
///
/// </summary>
/// <param name="ctx"></param>
/// <param name="msg"></param>
/// <exception cref="NotImplementedException"></exception>
protected override void ChannelRead0(IChannelHandlerContext ctx, SetParamMsgResp msg)
{
CarServerMgr.CarServer.Connected = true;
CarServerMgr.CarServer.SetParamMsgResp = msg;
}
}

@ -0,0 +1,26 @@
using DotNetty.Transport.Channels;
using HybirdFrameworkCore.Autofac.Attribute;
using Service.Car.Msg.Car.Resp;
using Service.Car.Server;
namespace Service.Car.Handler;
/// <summary>
///
/// </summary>
[Order(8)]
[Scope("InstancePerDependency")]
public class SettleConfirmMsgRespHandler : SimpleChannelInboundHandler<SettleConfirmMsgResp>, IBaseHandler
{
/// <summary>
///
/// </summary>
/// <param name="ctx"></param>
/// <param name="msg"></param>
/// <exception cref="NotImplementedException"></exception>
protected override void ChannelRead0(IChannelHandlerContext ctx, SettleConfirmMsgResp msg)
{
CarServerMgr.CarServer.Connected = true;
CarServerMgr.CarServer.SettleConfirmMsgResp = msg;
}
}

@ -0,0 +1,27 @@
using DotNetty.Transport.Channels;
using HybirdFrameworkCore.Autofac.Attribute;
using Service.Car.Msg.Car.Resp;
using Service.Car.Server;
namespace Service.Car.Handler;
/// <summary>
///
/// </summary>
[Order(8)]
[Scope("InstancePerDependency")]
public class UnLockMsgRespHandler : SimpleChannelInboundHandler<UnLockMsgResp>, IBaseHandler
{
/// <summary>
///
/// </summary>
/// <param name="ctx"></param>
/// <param name="msg"></param>
/// <exception cref="NotImplementedException"></exception>
protected override void ChannelRead0(IChannelHandlerContext ctx, UnLockMsgResp msg)
{
CarServerMgr.CarServer.Connected = true;
CarServerMgr.CarServer.UnLockMsgResp = msg;
}
}

@ -8,4 +8,10 @@ public class LockMsg : BaseMsg
/// </summary>
[Property(248, 8)]
public byte Command { get; set; } = 0x55;
public LockMsg()
{
Cmd = 0x05;
Length = 33;
}
}

@ -81,4 +81,10 @@ public class SetParamMsg: BaseMsg
/// </summary>
[Property(536, 24, scale: 0.01, round: 2)]
public double ElectricityToBeSettled { get; set; }
public SetParamMsg()
{
Cmd = 0x11;
Length = 70;
}
}

@ -8,4 +8,10 @@ public class SettleConfirmMsg : BaseMsg
/// </summary>
[Property(248, 8)]
public byte Command { get; set; } = 0x55;
public SettleConfirmMsg()
{
Cmd = 0x09;
Length = 33;
}
}

@ -2,10 +2,16 @@
namespace Service.Car.Msg.Host.Req;
public class UnLockMsg: BaseMsg
public class UnLockMsg : BaseMsg
{
/// <summary>
/// </summary>
[Property(248, 8)]
public byte Command { get; set; } = 0x55;
public UnLockMsg()
{
Cmd = 0x07;
Length = 33;
}
}

@ -15,6 +15,8 @@ public class ElecMsgResp : BaseMsg
/// <param name="result"></param>
public ElecMsgResp(byte result)
{
Cmd = 0x02;
Length = 33;
this.Result = result;
}
}

@ -9,4 +9,11 @@ public class HeartBeatMsgResp : BaseMsg
/// </summary>
[Property(248, 8)]
public byte HostStatus { get; set; }
public HeartBeatMsgResp(byte hostStatus)
{
Cmd = 0x04;
Length = 33;
HostStatus = hostStatus;
}
}

@ -1,10 +1,50 @@
using HybirdFrameworkDriver.TcpServer;
using HybirdFrameworkCore.Autofac.Attribute;
using HybirdFrameworkDriver.TcpServer;
using Service.Car.Codec;
using Service.Car.Handler;
using Service.Car.Msg.Car.Req;
using Service.Car.Msg.Car.Resp;
namespace Service.Car.Server;
[Scope("SingleInstance")]
public class CarServer : TcpServer<IBaseHandler, Decoder, Encoder>
{
/// <summary>
/// 客户端连接状态
/// </summary>
public bool Connected { get; set; }
public string? CarNo { get; set; }
public HeartBeatMsg? HeartBeatMsg { get; set; }
/// <summary>
/// 1 待机 2 换电
/// </summary>
public byte StationStatus { get; set; }
/// <summary>
/// 度电数据车载设备连接上换电站的 Wifi 网络时,主动上送度电数据报文(命令代码: 0x01发送周期 60s服务器回复相应的报文(命令代码0x02)
/// </summary>
public ElecMsg? ElecMsg { get; set; }
public LockMsgResp? LockMsgResp { get; set; }
public UnLockMsgResp? UnLockMsgResp { get; set; }
public SetParamMsgResp? SetParamMsgResp { get; set; }
public SettleConfirmMsgResp? SettleConfirmMsgResp { get; set; }
public CarServer() : base()
{
this.ChannelInActiveAction = () =>
{
Connected = false;
HeartBeatMsg = null;
ElecMsg = null;
LockMsgResp = null;
UnLockMsgResp = null;
SetParamMsgResp = null;
SettleConfirmMsgResp = null;
};
}
}

@ -0,0 +1,15 @@
using Autofac;
using HybirdFrameworkCore.Autofac;
namespace Service.Car.Server;
public class CarServerMgr
{
public static CarServer? CarServer { get; set; }
public static void InitServer()
{
CarServer = AppInfo.Container.Resolve<CarServer>();
CarServer.Start(5588);
}
}

@ -0,0 +1,128 @@
using HybirdFrameworkDriver.Session;
using log4net;
using Microsoft.AspNetCore.Mvc;
using Service.Car.Msg.Host.Req;
using Service.Car.Server;
using WebStarter.Dto.Req;
using WebStarter.Dto.Resp;
namespace WebStarter.Controllers;
/// <summary>
/// 车辆管理
/// </summary>
[ApiController]
[Route("[controller]")]
public class CarController : ControllerBase
{
private static readonly ILog Log = LogManager.GetLogger(typeof(CarController));
/// <summary>
/// 获取车辆数据
/// </summary>
/// <returns></returns>
[HttpGet("/getCarInfo")]
public CarInfoResp GetCarInfo()
{
CarInfoResp carInfoResp = new CarInfoResp()
{
Connected = CarServerMgr.CarServer?.Connected ?? false,
CarNo = CarServerMgr.CarServer?.HeartBeatMsg?.CarNo,
ElecMsg = CarServerMgr.CarServer?.ElecMsg,
HeartBeatMsg = CarServerMgr.CarServer?.HeartBeatMsg
};
return carInfoResp;
}
/// <summary>
/// 锁车
/// </summary>
/// <returns>发送结果</returns>
[HttpGet("/lock")]
public bool Lock()
{
Log.Info("Lock ");
if (CarServerMgr.CarServer == null || (CarServerMgr.CarServer?.Connected ?? false))
{
return false;
}
CarServerMgr.CarServer.LockMsgResp = null;
SessionMgr.Broadcast(new LockMsg());
return true;
}
/// <summary>
/// 解锁
/// </summary>
/// <returns>发送结果</returns>
[HttpGet("/unLock")]
public bool UnLock()
{
Log.Info("UnLock ");
if (CarServerMgr.CarServer == null || (CarServerMgr.CarServer?.Connected ?? false))
{
return false;
}
CarServerMgr.CarServer.UnLockMsgResp = null;
SessionMgr.Broadcast(new UnLockMsg());
return true;
}
/// <summary>
/// 结算
/// </summary>
/// <returns>发送结果</returns>
[HttpGet("/SettleConfirm")]
public bool SettleConfirm()
{
Log.Info("SettleConfirm ");
if (CarServerMgr.CarServer == null || (CarServerMgr.CarServer?.Connected ?? false))
{
return false;
}
CarServerMgr.CarServer.SettleConfirmMsgResp = null;
SessionMgr.Broadcast(new SettleConfirmMsg());
return true;
}
/// <summary>
/// 设置参数
/// </summary>
/// <returns></returns>
[HttpPost("/setParam")]
public bool SetParam(SetParam setParam)
{
Log.Info("SetParam");
if (CarServerMgr.CarServer == null || (CarServerMgr.CarServer?.Connected ?? false))
{
return false;
}
CarServerMgr.CarServer.SetParamMsgResp = null;
SetParamMsg setParamMsg = new SetParamMsg()
{
AccDischargeCount = setParam.AccDischargeCount,
AccFallbackCount = setParam.AccFallbackCount,
AccChargeCount = setParam.AccChargeCount,
AccKgce = setParam.AccKgce,
ThisTimeRealDischarge = setParam.ThisTimeRealDischarge,
LastTimeBalanceDischarge = setParam.LastTimeBalanceDischarge,
ThisTimeRealFeedbackPower = setParam.ThisTimeRealFeedbackPower,
LastTimeBalanceFeedbackPower = setParam.LastTimeBalanceFeedbackPower,
ThisTimeRealChargeCount = setParam.ThisTimeRealChargeCount,
LastTimeBalanceChargeCount = setParam.LastTimeBalanceChargeCount,
ThisTimeRealKgce = setParam.ThisTimeRealKgce,
LastTimeBalanceKgce = setParam.LastTimeBalanceKgce,
ElectricityToBeSettled = setParam.ElectricityToBeSettled,
};
SessionMgr.Broadcast(setParamMsg);
return true;
}
}

@ -0,0 +1,69 @@
namespace WebStarter.Dto.Req;
public class SetParam
{
/// <summary>
/// 车辆累计放电量
/// </summary>
public double AccDischargeCount { get; set; }
/// <summary>
/// 车辆累计回馈电量
/// </summary>
public double AccFallbackCount { get; set; }
/// <summary>
/// 车辆累计插枪充电量
/// </summary>
public double AccChargeCount { get; set; }
/// <summary>
/// 5 车辆累计综合能耗
/// </summary>
public double AccKgce { get; set; }
/// <summary>
/// 6 本次实时放电量
/// </summary>
public double ThisTimeRealDischarge { get; set; }
/// <summary>
/// 7 上一次结算放电量
/// </summary>
public double LastTimeBalanceDischarge { get; set; }
/// <summary>
/// 8 本次实时回馈电量
/// </summary>
public double ThisTimeRealFeedbackPower { get; set; }
/// <summary>
/// 9 上一次结算回馈电量
/// </summary>
public double LastTimeBalanceFeedbackPower { get; set; }
/// <summary>
/// 10 本次实时插枪充电量
/// </summary>
public double ThisTimeRealChargeCount { get; set; }
/// <summary>
/// 11 上一次结算插枪充电量
/// </summary>
public double LastTimeBalanceChargeCount { get; set; }
/// <summary>
/// 12 本次实时综合能耗
/// </summary>
public double ThisTimeRealKgce { get; set; }
/// <summary>
/// 13 上一次结算综合能耗
/// </summary>
public double LastTimeBalanceKgce { get; set; }
/// <summary>
/// 14 待结算电费电量
/// </summary>
public double ElectricityToBeSettled { get; set; }
}

@ -0,0 +1,29 @@
using Service.Car.Msg.Car.Req;
namespace WebStarter.Dto.Resp;
/// <summary>
/// 车辆数据
/// </summary>
public class CarInfoResp
{
/// <summary>
/// 连接状态
/// </summary>
public bool Connected { get; set; }
/// <summary>
/// 车牌号
/// </summary>
public string? CarNo { get; set; }
/// <summary>
/// 度电数据
/// </summary>
public ElecMsg? ElecMsg { get; set; }
/// <summary>
/// 状态数据
/// </summary>
public HeartBeatMsg? HeartBeatMsg { get; set; }
}

@ -4,6 +4,7 @@ using HybirdFrameworkCore.Autofac;
using HybirdFrameworkCore.Configuration;
using HybirdFrameworkCore.Entity;
using HybirdFrameworkCore.Redis;
using Service.Car.Server;
using SqlSugar;
using SqlSugar.IOC;
@ -92,4 +93,5 @@ app.MapControllers();
AppInfo.Container = app.Services.GetAutofacRoot();
CarServerMgr.InitServer();
app.Run();
Loading…
Cancel
Save