diff --git a/Common/Util/HttpUtil.cs b/Common/Util/HttpUtil.cs
index 0d9e8a6..db474ba 100644
--- a/Common/Util/HttpUtil.cs
+++ b/Common/Util/HttpUtil.cs
@@ -3,6 +3,9 @@ using Newtonsoft.Json;
namespace Common.Util;
+///
+/// http工具类
+///
public static class HttpUtil
{
private static readonly HttpClient httpClient = new HttpClient();
diff --git a/Service/Charger/Client/ChargerClient.cs b/Service/Charger/Client/ChargerClient.cs
index 4b0d09c..e8c9f43 100644
--- a/Service/Charger/Client/ChargerClient.cs
+++ b/Service/Charger/Client/ChargerClient.cs
@@ -18,9 +18,9 @@ using Service.Charger.Msg;
using Service.Charger.Msg.Charger.OutCharger.Req;
using Service.Charger.Msg.Charger.Req;
using Service.Charger.Msg.Charger.Resp;
-using Service.Charger.Msg.Host.OutCharger.Req;
using Service.Charger.Msg.Host.Req;
using Service.Charger.Msg.Host.Req.Bms;
+using Service.Charger.Msg.Host.Req.OutCharger.Req;
namespace Service.Charger.Client;
@@ -545,6 +545,24 @@ public class ChargerClient : TcpClient
return Result.Success();
}
+
+ ///
+ /// 3.7.9 监控平台发送充电桩功率调节指令
+ ///
+ ///
+ ///
+ ///
+ public Result SendPileAdjustPower(byte pn,float expectedOperatingPower)
+ {
+ if (!Connected)
+ {
+ return Result.Fail($"charger-{BinNo} disconnect");
+ }
+
+ PileAdjustPower powerRegulation = new PileAdjustPower(pn,expectedOperatingPower);
+ this.Channel.WriteAndFlushAsync(powerRegulation);
+ return Result.Success();
+ }
///
///
///
diff --git a/Service/Charger/Client/ChargerPile.cs b/Service/Charger/Client/ChargerPile.cs
index 240b1a6..a5f3f07 100644
--- a/Service/Charger/Client/ChargerPile.cs
+++ b/Service/Charger/Client/ChargerPile.cs
@@ -46,5 +46,10 @@ public class ChargerPile
/// 充电枪的唯一标识码
///
public string? pn { get; set; }
+
+ ///
+ /// 工作状态
+ ///
+ public byte WorkStatus { get; set; }
}
\ No newline at end of file
diff --git a/Service/Charger/Codec/Decoder.cs b/Service/Charger/Codec/Decoder.cs
index 869098d..6826491 100644
--- a/Service/Charger/Codec/Decoder.cs
+++ b/Service/Charger/Codec/Decoder.cs
@@ -250,6 +250,7 @@ public class Decoder : ByteToMessageDecoder
12 => ModelConvert.Decode(bytes),
11 => ModelConvert.Decode(bytes),
14 => ModelConvert.Decode(bytes),
+ 10 => ModelConvert.Decode(bytes),
_ => throw new InvalidOperationException("This should never be reached"),
},
#endregion
diff --git a/Service/Charger/Handler/OutCharger/PileAdjustPowerHandler.cs b/Service/Charger/Handler/OutCharger/PileAdjustPowerHandler.cs
new file mode 100644
index 0000000..ca2a1c7
--- /dev/null
+++ b/Service/Charger/Handler/OutCharger/PileAdjustPowerHandler.cs
@@ -0,0 +1,22 @@
+using DotNetty.Transport.Channels;
+using log4net;
+using Service.Charger.Client;
+using Service.Charger.Msg.Charger.OutCharger.Resp;
+
+namespace Service.Charger.Handler.OutCharger;
+///
+/// 3.7.10 充电桩应答功率调节指令
+///
+public class PileAdjustPowerHandler : SimpleChannelInboundHandler, IBaseHandler
+{
+ private static readonly ILog Log = LogManager.GetLogger(typeof(PileAdjustPowerHandler));
+
+
+ protected override void ChannelRead0(IChannelHandlerContext ctx, PileAdjustPowerRes msg)
+ {
+ if (ClientMgr.TryGetClient(ctx.Channel, out var sn, out var client))
+ {
+ Log.Info($"receive {msg} from {sn}");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Service/Charger/Handler/OutCharger/PileStartChargeResHandler.cs b/Service/Charger/Handler/OutCharger/PileStartChargeResHandler.cs
index b2913bd..33c92d2 100644
--- a/Service/Charger/Handler/OutCharger/PileStartChargeResHandler.cs
+++ b/Service/Charger/Handler/OutCharger/PileStartChargeResHandler.cs
@@ -11,6 +11,7 @@ using Service.Charger.Msg.Charger.OutCharger.Resp;
using Service.Charger.Msg.Http.Resp;
namespace Service.Charger.Handler.OutCharger;
+
///
/// 3.7.2 充电桩响应远程启动充电
///
@@ -20,7 +21,7 @@ public class PileStartChargeResHandler : SimpleChannelInboundHandler
+/// 3.7.10 充电桩应答功率调节指令
+///
+public class PileAdjustPowerRes: ASDU
+{
+ ///
+ /// 记录类型
+ ///
+ [Property(0, 8)]
+ public byte RecordType { get; set; }
+
+ ///
+ /// 充电枪ID
+ /// 0x01:充电枪1;0x02:充电枪2;0x03:双枪充电;(0x00&0xFF无效)
+ ///
+ [Property(8, 8)]
+ public byte Pn { get; set; }
+
+ ///
+ /// 启动结果
+ /// 0 成功 1 失败
+ ///
+ [Property(16, 8)]
+ public byte Result { get; set; }
+
+ ///
+ /// 失败原因
+ /// 默认 0
+ ///
+ [Property(24, 8)]
+ public byte FailReason { get; set; }
+}
\ No newline at end of file
diff --git a/Service/Charger/Msg/Host/Req/OutCharger/Req/PileAdjustPower.cs b/Service/Charger/Msg/Host/Req/OutCharger/Req/PileAdjustPower.cs
new file mode 100644
index 0000000..eb31fc0
--- /dev/null
+++ b/Service/Charger/Msg/Host/Req/OutCharger/Req/PileAdjustPower.cs
@@ -0,0 +1,42 @@
+using HybirdFrameworkCore.Autofac.Attribute;
+
+namespace Service.Charger.Msg.Host.Req.OutCharger.Req;
+///
+/// 3.7.9 监控平台发送充电桩功率调节指令
+///
+public class PileAdjustPower: ASDU
+{
+
+ ///
+ /// 记录类型
+ ///
+ [Property(0, 8)]
+ public byte RecordType { get; set; }
+
+ ///
+ /// 充电枪ID号
+ /// 0x01:充电枪1;0x02:充电枪2;0x03:双枪充电;(0x00&0xFF无效)
+ ///
+ [Property(8, 8)]
+ public byte Pn { get; set; }
+
+ ///
+ ///期望运行 功率
+ ///
+ [Property(8, 16, PropertyReadConstant.Bit, 0.1, 1)]
+ public float ExpectPower { get; set; }
+
+
+ public PileAdjustPower(byte pn,float expectPower)
+ {
+ RecordType = 9;
+ FrameTypeNo = 51;
+ MsgBodyCount = 1;
+ TransReason = 3;
+ PublicAddr = 0;
+ MsgBodyAddr = new byte[] { 0, 0, 0 };
+
+ Pn = pn;
+ ExpectPower = expectPower;
+ }
+}
\ No newline at end of file
diff --git a/Service/Charger/Msg/Host/Req/OutCharger/Req/PileStartCharge.cs b/Service/Charger/Msg/Host/Req/OutCharger/Req/PileStartCharge.cs
index 4bd0419..a0c74a4 100644
--- a/Service/Charger/Msg/Host/Req/OutCharger/Req/PileStartCharge.cs
+++ b/Service/Charger/Msg/Host/Req/OutCharger/Req/PileStartCharge.cs
@@ -1,6 +1,6 @@
using HybirdFrameworkCore.Autofac.Attribute;
-namespace Service.Charger.Msg.Host.OutCharger.Req;
+namespace Service.Charger.Msg.Host.Req.OutCharger.Req;
///
/// 3.7.1 监控平台远程启动充电桩充电
diff --git a/Service/Charger/Msg/Host/Req/OutCharger/Req/PileStopCharge.cs b/Service/Charger/Msg/Host/Req/OutCharger/Req/PileStopCharge.cs
index ee47f01..e011708 100644
--- a/Service/Charger/Msg/Host/Req/OutCharger/Req/PileStopCharge.cs
+++ b/Service/Charger/Msg/Host/Req/OutCharger/Req/PileStopCharge.cs
@@ -1,6 +1,6 @@
using HybirdFrameworkCore.Autofac.Attribute;
-namespace Service.Charger.Msg.Host.OutCharger.Req;
+namespace Service.Charger.Msg.Host.Req.OutCharger.Req;
///
/// 3.7.3 监控平台远程停止充电桩充电
diff --git a/Service/Charger/Msg/Http/Req/PileRealtimeReq.cs b/Service/Charger/Msg/Http/Req/PileRealtimeReq.cs
new file mode 100644
index 0000000..1128c8e
--- /dev/null
+++ b/Service/Charger/Msg/Http/Req/PileRealtimeReq.cs
@@ -0,0 +1,45 @@
+namespace Service.Charger.Msg.Http.Req;
+///
+/// 9.2.1.5 站控上报充电枪实时数据上报
+///
+public class PileRealtimeReq
+{
+ ///
+ /// 换电站编码
+ ///
+ public string sn { get; set; }
+
+
+ ///
+ /// Desc:充电枪编号
+ /// Default:
+ /// Nullable:True
+ ///
+ public string? pn { get; set; }
+
+ ///
+ /// 充电枪状态
+ ///
+ public int ps { get; set; }
+
+ ///
+ /// 插枪状态
+ ///
+ public int con { get; set; }
+
+
+ ///
+ /// 单枪输出电压
+ ///
+ public float pov { get; set; }
+
+ ///
+ /// 单枪输出电流
+ ///
+ public float poe { get; set; }
+
+ ///
+ /// 单枪故障代码
+ ///
+ public int ec { get; set; }
+}
\ No newline at end of file
diff --git a/Service/Charger/MyTask/PileChargeRealtimeTask.cs b/Service/Charger/MyTask/PileChargeRealtimeTask.cs
new file mode 100644
index 0000000..d2cb561
--- /dev/null
+++ b/Service/Charger/MyTask/PileChargeRealtimeTask.cs
@@ -0,0 +1,103 @@
+using System.Collections.Concurrent;
+using Common.Util;
+using HybirdFrameworkCore.Autofac.Attribute;
+using HybirdFrameworkCore.AutoTask;
+using log4net;
+using Service.Charger.Client;
+using Service.Charger.Msg.Charger.OutCharger.Req;
+using Service.Charger.Msg.Charger.Req;
+using Service.Charger.Msg.Http.Req;
+using Service.Init;
+
+namespace Service.Charger.MyTask;
+///
+/// 9.2.1.7 站控上报充电枪充电遥测数据
+///
+[Scope]
+public class PileChargeRealtimeTask : ITask
+{
+ private static readonly ILog Log = LogManager.GetLogger(typeof(PileChargeRealtimeTask));
+ private volatile bool _stop;
+
+
+ public string Name()
+ {
+ return "PileChargeRealtimeTask";
+ }
+
+ public int Interval()
+ {
+ return 1000 * 30;
+ }
+
+ public void Handle()
+ {
+
+ ConcurrentDictionary chargerClients = ClientMgr.Dictionary;
+
+ if (chargerClients.Values.Count <= 0)
+ {
+ return;
+ }
+
+ foreach (var clientPair in chargerClients)
+ {
+ ChargerClient client = clientPair.Value;
+
+ ProcessClient(client, 1);
+ ProcessClient(client, 2);
+ }
+ }
+
+ private void ProcessClient(ChargerClient client, byte gunNumber)
+ {
+ if (client.GunCharged[gunNumber])
+ {
+ ChargerPile chargerPile = client.ChargerPile[gunNumber];
+ PileUploadTelemetry telemetry = client.PileUploadTelemetry[gunNumber];
+ PileUploadRemoteSignal pileUploadRemoteSignal = client.PileUploadRemoteSignal[gunNumber];
+
+ PileChargeRealtimeReq req = new PileChargeRealtimeReq
+ {
+ sn = StaticStationInfo.StationNo,
+ con = chargerPile.con,
+ cosn = chargerPile.cosn,
+ pn = chargerPile.pn,
+ rv = telemetry.BmsNeedVoltage,
+ re = telemetry.BmsNeedCurrent,
+ cm = telemetry.ChargeMode,
+ cdv = telemetry.BmsChargingVoltage,
+ cde = telemetry.BmsChargingCurrent,
+ soc = telemetry.CurrentSoc,
+ tr = telemetry.EstimatedRemainingTime,
+ pov = telemetry.DcMeterVoltage,
+ poe = telemetry.DcMeterCurrent,
+ tct = telemetry.ChargingTime,
+ lbtn = telemetry.MinTempDetectionPointNo,
+ lbt = telemetry.MinBatteryTemp,
+ hbtn = telemetry.MaxTempDetectionPointNo,
+ hbt = telemetry.MaxBatteryTemp,
+ hlbva = pileUploadRemoteSignal.ChargerInputOverVoltageError ? 1 :
+ pileUploadRemoteSignal.ChargerInputUnderVoltageError ? 2 : 0,
+ bia = pileUploadRemoteSignal.InsulationDetectionAlarm ? 1 : 0
+ };
+
+ HttpUtil.SendPostRequest(req, "http://127.0.0.1:5034/api/OutCharger/SendPileChargeRealtime");
+ }
+ }
+
+ public bool Stoped()
+ {
+ return _stop;
+ }
+
+ public void Stop()
+ {
+ _stop = true;
+ }
+
+ public void ResetStop()
+ {
+ _stop = false;
+ }
+}
\ No newline at end of file
diff --git a/Service/Charger/MyTask/PileRealtimeTask.cs b/Service/Charger/MyTask/PileRealtimeTask.cs
new file mode 100644
index 0000000..3b6bf4c
--- /dev/null
+++ b/Service/Charger/MyTask/PileRealtimeTask.cs
@@ -0,0 +1,100 @@
+using System.Collections.Concurrent;
+using Common.Util;
+using HybirdFrameworkCore.Autofac.Attribute;
+using HybirdFrameworkCore.AutoTask;
+using log4net;
+using Service.Charger.Client;
+using Service.Charger.Msg.Charger.OutCharger.Req;
+using Service.Charger.Msg.Http.Req;
+using Service.Init;
+
+namespace Service.Charger.MyTask;
+///
+/// 9.2.1.5 站控上报充电枪实时数据上报
+///
+[Scope]
+public class PileRealtimeTask : ITask
+{
+ private static readonly ILog Log = LogManager.GetLogger(typeof(PileRealtimeTask));
+ private volatile bool _stop;
+
+ public string Name()
+ {
+ return "PileRealtimeTask";
+ }
+
+ public int Interval()
+ {
+ return 1000 * 5;
+ }
+
+ public void Handle()
+ {
+ ConcurrentDictionary chargerClients = ClientMgr.Dictionary;
+
+ if (chargerClients.Values.Count <= 0)
+ {
+ return;
+ }
+
+ foreach (var kvp in chargerClients)
+ {
+ ChargerClient client = kvp.Value;
+
+ HandleChargerPile(client, 1);
+ HandleChargerPile(client, 2);
+ }
+ }
+
+
+
+ public bool Stoped()
+ {
+ return _stop;
+ }
+
+ public void Stop()
+ {
+ _stop = true;
+ }
+
+ public void ResetStop()
+ {
+ _stop = false;
+ }
+
+ private void HandleChargerPile(ChargerClient client, byte pileIndex)
+ {
+ if (client.ChargedPile[pileIndex])
+ {
+ ChargerPile chargerPile = client.ChargerPile[pileIndex];
+ PileUploadTelemetry pileUploadTelemetry = client.PileUploadTelemetry[pileIndex];
+
+ PileRealtimeReq req = new PileRealtimeReq
+ {
+ sn = StaticStationInfo.StationNo,
+ pn = chargerPile.pn,
+ ps = GetPileStatus(chargerPile.WorkStatus),
+ pov = pileUploadTelemetry.BmsChargingVoltage,
+ poe = pileUploadTelemetry.BmsChargingCurrent,
+ ec = 0
+ };
+
+ HttpUtil.SendPostRequest(req, "http://127.0.0.1:5034/api/OutCharger/SendPileRealtime");
+ }
+ }
+
+ private int GetPileStatus(int workStatus)
+ {
+ return workStatus switch
+ {
+ 0 => 1,
+ 1 => 3,
+ 2 => 4,
+ 3 => 5,
+ _ => 1
+ };
+ }
+
+
+}
\ No newline at end of file
diff --git a/WebStarter/Controllers/OutChargerController.cs b/WebStarter/Controllers/OutChargerController.cs
index 0cca89a..05eab35 100644
--- a/WebStarter/Controllers/OutChargerController.cs
+++ b/WebStarter/Controllers/OutChargerController.cs
@@ -32,6 +32,7 @@ public class OutChargerController
[Route("SendStartOutCharger")]
public Result SendStartOutCharger([FromBody] PileStartChargeHttpReq httpReq)
{
+
string chargerCode = ChargerUtils.GetOutChargerCode(httpReq.pn);
byte chargerGunCode = ChargerUtils.GetTheGun(httpReq.pn);
@@ -92,4 +93,36 @@ public class OutChargerController
return Result.Success(true);
}
+
+ ///
+ /// 给充电枪发送功率调节指令
+ ///
+ /// 充电机code
+ /// 1枪 or 2枪
+ /// 功率
+ ///
+ [HttpGet]
+ [Route("SendPowerRegulation/{code}/{pn}/{power}")]
+ public Result SendPowerRegulation(string code,byte pn, float power)
+ {
+ if (power <=0 || power > 280)
+ {
+ return Result.Fail("功率值范围1到360");
+ }
+
+ if (pn != 1 && pn != 2)
+ {
+ return Result.Fail("请选择1枪或者2枪");
+ }
+
+ ChargerClient? chargerClient = ClientMgr.GetBySn(code);
+
+ if (chargerClient != null)
+ {
+ chargerClient.SendPileAdjustPower(pn,power);
+ return Result.Success(true);
+ }
+
+ return Result.Fail("充电机未连接");
+ }
}
\ No newline at end of file