123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- using Edge.Core.Parser;
- using Edge.Core.Processor;
- using Edge.Core.Processor.Communicator;
- using Edge.Core.Processor.Dispatcher.Attributes;
- using Edge.Core.UniversalApi;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Logging;
- using Microsoft.Extensions.Logging.Abstractions;
- using SuZhouSuAnXin_BatteryEMS.MessageEntity;
- using System;
- using System.Linq;
- using System.Threading.Tasks;
- namespace SuZhouSuAnXin_BatteryEMS
- {
- [MetaPartsRequired(typeof(HalfDuplexActivePollingDeviceProcessor<,>))]
- [MetaPartsRequired(typeof(TcpClientCommunicator<>))]
- [MetaPartsDescriptor(
- "速安行电池EMS",
- "用于驱动 苏州速安行新能源科技有限公司 电池EMS系统,EMS侧默认端口为502,日志名称:DynamicPrivate_SuZhouSuAnXin_BatteryEMS",
- new[] { "lang-zh-cn:电池储能lang-en-us:BatterySystem" })]
- public class DeviceHandler : TestableActivePollingDeviceHandler<byte[], MessageEntity.MessageBase>, IDisposable
- {
- private IContext<byte[], MessageEntity.MessageBase> context;
- private ILogger logger = NullLogger.Instance;
- private IServiceProvider services;
- private DeviceConfigV1 deviceConfig;
- public class DeviceConfigV1
- {
- public string DeviceName { get; set; }
- public byte SlaveAddress { get; set; }
- public string Description { get; set; }
- }
- [ParamsJsonSchemas("ctorParamsJsonSchema")]
- public DeviceHandler(DeviceConfigV1 deviceConfig, IServiceProvider services)
- {
- this.deviceConfig = deviceConfig;
- this.services = services;
- var loggerFactory = services.GetRequiredService<ILoggerFactory>();
- this.logger = loggerFactory.CreateLogger("DynamicPrivate_SuZhouSuAnXin_BatteryEMS");
- }
- public override void Init(IContext<byte[], MessageEntity.MessageBase> context)
- {
- base.Init(context);
- this.context = context;
- var timeWindowWithActivePollingOutgoing =
- this.context.Outgoing as TimeWindowWithActivePollingOutgoing<byte[], MessageEntity.MessageBase>;
- int previousPolledDeviceIndex = 0;
- timeWindowWithActivePollingOutgoing.PollingMsgProducer = () =>
- {
- try
- {
- if (DateTime.Now.Ticks % 2 == 0)
- {
- //0x0016 2 总电压 电池系统当前直流测电压(外侧电压)
- //0x0017 2 总电流 电池系统当前直流充放电电流
- //0x0018 2 SOC 电池系统当前 SOC 数据
- //0x0019 2 SOH 电池系统当前 SOH 数据
- //0x001A 2 DOD 放电深度
- return new OutgoingQueryMessage(0x16, 5);
- }
- else
- {
- //寄存器地址 字节数 含义 备注
- //0x0230 2 系统时钟:年 数据范围:2000 - 2099
- //0x0231 2 系统时钟:月 数据范围:1 - 12
- //0x0232 2 系统时钟:日 数据范围:1 - 31
- //0x0233 2 系统时钟:时 数据范围:0 - 23
- //0x0234 2 系统时钟:分 数据范围:0 - 59
- //0x0235 2 系统时钟:秒 数据范围:0 - 59
- return new OutgoingQueryMessage(0x0230, 5);
- }
- }
- catch (Exception exxx)
- {
- logger.LogError($"Exceptioned (previousPolledHandlerIndex: {previousPolledDeviceIndex}): {exxx}");
- return null;
- }
- };
- }
- public override async Task Process(IContext<byte[], MessageEntity.MessageBase> context)
- {
- await base.Process(context);
- return;
- }
- public void Dispose()
- {
- }
- [UniversalApi]
- public async Task<object> SendOutgoingQueryMessageAsync(int startingRegAddress, byte noOfRegAddress)
- {
- var response = await this.context.Outgoing.WriteAsync(new OutgoingQueryMessage(startingRegAddress, noOfRegAddress),
- (_, testResponse) => testResponse is IncomingMessage, 6000) as IncomingMessage;
- if (response == null)
- throw new TimeoutException("long time no see incoming response");
- return response.ToLogString();
- }
- [UniversalApi]
- public async Task<object> ReadGenericInfoAsync()
- {
- //数据类型 比例因子 范围 偏移量 实际量程 字节数 备注
- //总电压 0.1V 0 - 10000 0 0 - 1000V 2(UINT16)
- //总电流 0.1A 0 - 6000 - 3000 - 300 - 300A 2(INT16) 实际充电为负数,放电为正数
- //SOC 0.1 % 0 - 1000 0 0 - 100 % 2(UINT16)
- //SOH 0.1 % 0 - 1000 0 0 - 100 % 2(UINT16)
- //DOD 0.1 % 0 - 1000 0 0 - 100 % 2(UINT16) 最近一次放电深度
- //单体电压 0.001V 0 - 5000 0 0 - 5V 2(UINT16)
- //温度 1℃ 0 - 210 - 80 - 80 - 130℃ 1
- //湿度 1 % 0 - 100 0 0 - 100 % 1
- //总充电电量 1kWH 0 4(UINT32)
- //总放电电量 1kWH 0 4(UINT32)
- //寄存器地址 字节数 含义 备注
- //0x0016 2 总电压 电池系统当前直流测电压(外侧电压)
- //0x0017 2 总电流 电池系统当前直流充放电电流
- //0x0018 2 SOC 电池系统当前 SOC 数据
- //0x0019 2 SOH 电池系统当前 SOH 数据
- //0x001A 2 DOD 放电深度
- //0x001B 2 循环次数 电池系统累计循环次数
- //0x001C 2 总电压—内侧 电池系统当前直流累加电压数据
- //0x001D 2 单体最高电压值 电池系统当前单体最高电压
- //0x001E 2 单体最低电压值 电池系统当前单体最低电压
- //0x001F 2 单体平均电压 电池系统当前单体平均电压
- var response = await this.context.Outgoing.WriteAsync(new OutgoingQueryMessage(0x0016, 10),
- (_, testResponse) => testResponse is IncomingMessage, 6000) as IncomingMessage;
- if (response == null)
- throw new TimeoutException("long time no see incoming response for reg address starts from 0x0016 of 10 count");
- //0.1V
- var 总电压 = ((decimal)(BitConverter.ToUInt16(response.InnerRawData.Take(2).Reverse().ToArray()))) / 10;
- //0.1A
- var 总电流 = ((decimal)(BitConverter.ToInt16(response.InnerRawData.Skip(2).Take(2).Reverse().ToArray()))) / 10;
- //0.1%
- var SOC = ((decimal)(BitConverter.ToUInt16(response.InnerRawData.Skip(4).Take(2).Reverse().ToArray()))) / 10;
- //0.1%
- var SOH = ((decimal)(BitConverter.ToUInt16(response.InnerRawData.Skip(6).Take(2).Reverse().ToArray()))) / 10;
- //0.1%
- var DOD = ((decimal)(BitConverter.ToUInt16(response.InnerRawData.Skip(8).Take(2).Reverse().ToArray()))) / 10;
- var 电池系统累计循环次数 = BitConverter.ToUInt16(response.InnerRawData.Skip(10).Take(2).Reverse().ToArray());
- //0.1V
- var 电池系统当前直流累加电压数据 = ((decimal)(BitConverter.ToUInt16(response.InnerRawData.Skip(12).Take(2).Reverse().ToArray()))) / 10;
- //0.1V
- var 电池系统当前单体最高电压 = ((decimal)(BitConverter.ToUInt16(response.InnerRawData.Skip(14).Take(2).Reverse().ToArray()))) / 10;
- //0.1V
- var 电池系统当前单体最低电压 = ((decimal)(BitConverter.ToUInt16(response.InnerRawData.Skip(16).Take(2).Reverse().ToArray()))) / 10;
- //0.1V
- var 电池系统当前单体平均电压 = ((decimal)(BitConverter.ToUInt16(response.InnerRawData.Skip(18).Take(2).Reverse().ToArray()))) / 10;
- //寄存器地址 字节数 含义 备注
- //0x0200 2 系统充放电状态 0:正常 1:禁充 2:禁放 3:待机
- //0x0201 2 充放电计划1使能 0:禁用 1:使能
- //0x0202 2 充放电计划1模式 0:待机 1:充电 2:放电
- //0x0203 2 充放电计划1起始时间 高字节小时数 0 - 23 低字节分钟数 0 - 59
- //0x0204 2 充放电计划1终止时间 高字节小时数 0 - 23 低字节分钟数 0 - 59
- //0x0205 2 充放电计划1有功功率 Kw
- //0x0206 2 充放电计划2使能 0:禁用 1:使能
- //0x0207 2 充放电计划2模式 0:待机 1:充电 2:放电
- //0x0208 2 充放电计划2起始时间 高字节小时数 0 - 23 低字节分钟数 0 - 59
- //0x0209 2 充放电计划2终止时间 高字节小时数 0 - 23 低字节分钟数 0 - 59
- //0x020A 2 充放电计划2有功功率 Kw
- response = await this.context.Outgoing.WriteAsync(new OutgoingQueryMessage(0x0200, 11),
- (_, testResponse) => testResponse is IncomingMessage, 6000) as IncomingMessage;
- if (response == null)
- throw new TimeoutException("long time no see incoming response for reg address starts from 0x0200 of 11 count");
- var 系统充放电状态 = "???undefined???";
- var __系统充放电状态value = BitConverter.ToInt16(response.InnerRawData.Take(2).Reverse().ToArray());
- if (__系统充放电状态value == 0)
- 系统充放电状态 = "正常";
- else if (__系统充放电状态value == 1)
- 系统充放电状态 = "禁充";
- else if (__系统充放电状态value == 2)
- 系统充放电状态 = "禁放";
- else if (__系统充放电状态value == 3)
- 系统充放电状态 = "待机";
- var 充放电计划1使能 = BitConverter.ToInt16(response.InnerRawData.Skip(2).Take(2).Reverse().ToArray()) == 0 ? "禁用" : "使能";
- var __充放电计划1模式value = BitConverter.ToInt16(response.InnerRawData.Skip(4).Take(2).Reverse().ToArray());
- var 充放电计划1模式 = __充放电计划1模式value == 0 ? "待机" : (__充放电计划1模式value == 1 ? "充电" : "放电");
- var 充放电计划1起始时间_分钟数 = response.InnerRawData.Skip(6).First();
- var 充放电计划1起始时间_小时数 = response.InnerRawData.Skip(7).First();
- var 充放电计划1终止时间_分钟数 = response.InnerRawData.Skip(8).First();
- var 充放电计划1终止时间_小时数 = response.InnerRawData.Skip(9).First();
- var 充放电计划1有功功率 = ((decimal)(BitConverter.ToInt16(response.InnerRawData.Skip(10).Take(2).Reverse().ToArray()))) / 10;
- var 充放电计划2使能 = BitConverter.ToInt16(response.InnerRawData.Skip(12).Take(2).Reverse().ToArray()) == 0 ? "禁用" : "使能";
- var __充放电计划2模式value = BitConverter.ToInt16(response.InnerRawData.Skip(14).Take(2).Reverse().ToArray());
- var 充放电计划2模式 = __充放电计划1模式value == 0 ? "待机" : (__充放电计划1模式value == 1 ? "充电" : "放电");
- var 充放电计划2起始时间_分钟数 = response.InnerRawData.Skip(16).First();
- var 充放电计划2起始时间_小时数 = response.InnerRawData.Skip(17).First();
- var 充放电计划2终止时间_分钟数 = response.InnerRawData.Skip(18).First();
- var 充放电计划2终止时间_小时数 = response.InnerRawData.Skip(19).First();
- var 充放电计划2有功功率 = ((decimal)(BitConverter.ToInt16(response.InnerRawData.Skip(20).Take(2).Reverse().ToArray()))) / 10;
- //寄存器地址 字节数 含义 备注
- //0x0230 2 系统时钟:年 数据范围:2000 - 2099
- //0x0231 2 系统时钟:月 数据范围:1 - 12
- //0x0232 2 系统时钟:日 数据范围:1 - 31
- //0x0233 2 系统时钟:时 数据范围:0 - 23
- //0x0234 2 系统时钟:分 数据范围:0 - 59
- //0x0235 2 系统时钟:秒 数据范围:0 - 5
- response = await this.context.Outgoing.WriteAsync(new OutgoingQueryMessage(0x0230, 6),
- (_, testResponse) => testResponse is IncomingMessage, 6000) as IncomingMessage;
- if (response == null)
- throw new TimeoutException("long time no see incoming response for reg address starts from 0x0230 of 6 count");
- var 系统时钟_年 = BitConverter.ToUInt16(response.InnerRawData.Take(2).Reverse().ToArray());
- var 系统时钟_月 = BitConverter.ToUInt16(response.InnerRawData.Skip(2).Take(2).Reverse().ToArray());
- var 系统时钟_日 = BitConverter.ToUInt16(response.InnerRawData.Skip(4).Take(2).Reverse().ToArray());
- var 系统时钟_时 = BitConverter.ToUInt16(response.InnerRawData.Skip(6).Take(2).Reverse().ToArray());
- var 系统时钟_分 = BitConverter.ToUInt16(response.InnerRawData.Skip(8).Take(2).Reverse().ToArray());
- var 系统时钟_秒 = BitConverter.ToUInt16(response.InnerRawData.Skip(10).Take(2).Reverse().ToArray());
- return new
- {
- 总电压,
- 总电流,
- SOC,
- SOH,
- DOD,
- 电池系统累计循环次数,
- 电池系统当前直流累加电压数据,
- 电池系统当前单体最高电压,
- 电池系统当前单体最低电压,
- 电池系统当前单体平均电压,
- 系统充放电状态,
- 充放电计划1使能,
- 充放电计划1模式,
- 充放电计划1起始时间_分钟数,
- 充放电计划1起始时间_小时数,
- 充放电计划1终止时间_分钟数,
- 充放电计划1终止时间_小时数,
- 充放电计划1有功功率,
- 充放电计划2使能,
- 充放电计划2模式,
- 充放电计划2起始时间_分钟数,
- 充放电计划2起始时间_小时数,
- 充放电计划2终止时间_分钟数,
- 充放电计划2终止时间_小时数,
- 充放电计划2有功功率,
- 系统时钟_年,
- 系统时钟_月,
- 系统时钟_日,
- 系统时钟_时,
- 系统时钟_分,
- 系统时钟_秒
- };
- }
- }
- }
|