diff --git a/src/JiShe.CollectBus.Application.Contracts/EnergySystem/Dto/AutoReportCollectionItemsSetInput.cs b/src/JiShe.CollectBus.Application.Contracts/EnergySystem/Dto/AutoReportCollectionItemsSetInput.cs
index d0a5651..111b806 100644
--- a/src/JiShe.CollectBus.Application.Contracts/EnergySystem/Dto/AutoReportCollectionItemsSetInput.cs
+++ b/src/JiShe.CollectBus.Application.Contracts/EnergySystem/Dto/AutoReportCollectionItemsSetInput.cs
@@ -17,7 +17,7 @@ namespace JiShe.CollectBus.EnergySystem.Dto
public string GatherCode { get; set; }
- public AutoReportCollectionItemsSetDetailsInput Details { get; set; }
+ public AutoReportCollectionItemsSetDetailsInput Detail { get; set; }
}
public class AutoReportCollectionItemsSetCodeInput
diff --git a/src/JiShe.CollectBus.Application.Contracts/EnergySystem/Dto/AutoReportSetInput.cs b/src/JiShe.CollectBus.Application.Contracts/EnergySystem/Dto/AutoReportSetInput.cs
index d76e6e9..f2543c2 100644
--- a/src/JiShe.CollectBus.Application.Contracts/EnergySystem/Dto/AutoReportSetInput.cs
+++ b/src/JiShe.CollectBus.Application.Contracts/EnergySystem/Dto/AutoReportSetInput.cs
@@ -17,7 +17,7 @@ namespace JiShe.CollectBus.EnergySystem.Dto
public string GatherCode { get; set; }
- public AutoReportSetDetailsInput Details { get; set; }
+ public AutoReportSetDetailsInput Detail { get; set; }
}
public class AutoReportSetCodeInput
diff --git a/src/JiShe.CollectBus.Application.Contracts/EnergySystem/IEnergySystemAppService.cs b/src/JiShe.CollectBus.Application.Contracts/EnergySystem/IEnergySystemAppService.cs
index 4c56fb9..8ac2cba 100644
--- a/src/JiShe.CollectBus.Application.Contracts/EnergySystem/IEnergySystemAppService.cs
+++ b/src/JiShe.CollectBus.Application.Contracts/EnergySystem/IEnergySystemAppService.cs
@@ -1,4 +1,5 @@
-using System.Threading.Tasks;
+using System.Collections.Generic;
+using System.Threading.Tasks;
using JiShe.CollectBus.EnergySystem.Dto;
using Volo.Abp.Application.Services;
@@ -130,19 +131,19 @@ public interface IEnergySystemAppService : IApplicationService
///
///
///
- Task AddConrOnlineRecord(AddConrOnlineRecordInput input);
+ Task AddConrOnlineRecord(List input);
///
/// 记录信号强度
///
///
///
- Task AddSignalStrength(AddSignalStrengthInput input);
+ Task AddSignalStrength(List input);
///
/// 集中器上下线、心跳记录
///
///
///
- Task AddFocusLog(AddFocusLogInput input);
+ Task AddFocusLog(List input);
}
\ No newline at end of file
diff --git a/src/JiShe.CollectBus.Application/EnergySystem/EnergySystemAppService.cs b/src/JiShe.CollectBus.Application/EnergySystem/EnergySystemAppService.cs
index df2c6e1..509f113 100644
--- a/src/JiShe.CollectBus.Application/EnergySystem/EnergySystemAppService.cs
+++ b/src/JiShe.CollectBus.Application/EnergySystem/EnergySystemAppService.cs
@@ -5,6 +5,7 @@ using System.Net;
using System.Text;
using System.Threading.Tasks;
using DotNetCore.CAP;
+using JiShe.CollectBus.Common.BuildSendDatas;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Models;
@@ -55,9 +56,9 @@ namespace JiShe.CollectBus.EnergySystem
if (ammeter == null) return result;
var dataUnit =
- HexStringExtensions.BuildAmmeterValveControlSendDataUnit(ammeter.Address, "", ammeter.Password,
+ Build645SendData.BuildAmmeterValveControlSendDataUnit(ammeter.Address, "", ammeter.Password,
state);
- bytes = HexStringExtensions.BuildTransparentForwardingSendCmd(address, ammeter.PortNumber ?? 2, ammeter.BaudRate, dataUnit);
+ bytes = Build3761SendData.BuildTransparentForwardingSendCmd(address, ammeter.PortNumber ?? 2, ammeter.BaudRate, dataUnit);
}
else if(input.MeterType == 2)
{
@@ -100,7 +101,7 @@ namespace JiShe.CollectBus.EnergySystem
if (ammeter == null) return result;
var address = $"{input.AreaCode}{input.Address}";
- var bytesList = HexStringExtensions.BuildReadMeterTimeSetSendCmd(address, ammeter.Code, ammeter.Address, ammeter.Password,
+ var bytesList = Build3761SendData.BuildReadMeterTimeSetSendCmd(address, ammeter.Code, ammeter.Address, ammeter.Password,
ammeter.PortNumber ?? 2, ammeter.BaudRate);
foreach (var bytes in bytesList)
@@ -132,9 +133,9 @@ namespace JiShe.CollectBus.EnergySystem
{
SerialNumber = it.SerialNumber,
Pn = it.Pn,
- BaudRate = HexStringExtensions.GetBaudreate(it.Rate.ToString()),
+ BaudRate = Build3761SendData.GetBaudreate(it.Rate.ToString()),
Port = it.Port,
- ProtocolType = HexStringExtensions.GetProtocolType(it.AgreementType),
+ ProtocolType = Build3761SendData.GetProtocolType(it.AgreementType),
Address = it.Addrress,
Password = it.Password.ToString(),
RateNumber = it.RatesCount,
@@ -145,7 +146,7 @@ namespace JiShe.CollectBus.EnergySystem
//UserSubclassNumber = it.UserSmallNumber
}).ToList();
- var bytes = HexStringExtensions.BuildAmmeterParameterSetSendCmd(address, meterParameters);
+ var bytes = Build3761SendData.BuildAmmeterParameterSetSendCmd(address, meterParameters);
await _capBus.PublishAsync(ProtocolConst.SubscriberIssuedEventName, new IssuedEventMessage
{
//ClientId = messageReceived.ClientId,
@@ -167,9 +168,27 @@ namespace JiShe.CollectBus.EnergySystem
///
///
[Route("Handmould/ReadMeterAddress_10_105")]
- public Task AmmeterArchivesMatch(AmmeterArchivesMatchInput input)
+ public async Task AmmeterArchivesMatch(AmmeterArchivesMatchInput input)
{
- throw new NotImplementedException();
+ var result = new BaseResultDto();
+ var address = $"{input.AreaCode}{input.Address}";
+ foreach (var detail in input.Details.Data)
+ {
+ var dataUnit = Build645SendData.BuildReadMeterAddressSendDataUnit(detail.MeterAddress);
+ var bytes =Build3761SendData.BuildTransparentForwardingSendCmd(address, detail.Port, detail.BaudRate.ToString(), dataUnit, StopBit.Stop1, Parity.None);
+ await _capBus.PublishAsync(ProtocolConst.SubscriberIssuedEventName, new IssuedEventMessage
+ {
+ //ClientId = messageReceived.ClientId,
+ DeviceNo = address,
+ Message = bytes,
+ Type = IssuedEventType.Data,
+ MessageId = NewId.NextGuid().ToString()
+ });
+ }
+
+ result.Status = true;
+ result.Msg = "操作成功";
+ return result;
}
///
@@ -202,7 +221,7 @@ namespace JiShe.CollectBus.EnergySystem
return result;
}
- var bytes = HexStringExtensions.BuildCommunicationParametersSetSendCmd(address, masterIP, materPort,
+ var bytes = Build3761SendData.BuildCommunicationParametersSetSendCmd(address, masterIP, materPort,
backupIP, backupPort, input.Data.APN);
await _capBus.PublishAsync(ProtocolConst.SubscriberIssuedEventName, new IssuedEventMessage
{
@@ -230,7 +249,7 @@ namespace JiShe.CollectBus.EnergySystem
var result = new BaseResultDto();
var address = $"{input.AreaCode}{input.Address}";
- var bytes = HexStringExtensions.BuildTerminalCalendarClockSendCmd(address);
+ var bytes = Build3761SendData.BuildTerminalCalendarClockSendCmd(address);
await _capBus.PublishAsync(ProtocolConst.SubscriberIssuedEventName, new IssuedEventMessage
{
//ClientId = messageReceived.ClientId,
@@ -257,7 +276,7 @@ namespace JiShe.CollectBus.EnergySystem
var result = new BaseResultDto();
var address = $"{input.AreaCode}{input.Address}";
- var bytes = HexStringExtensions.BuildConrCheckTimeSendCmd(address,DateTime.Now);
+ var bytes = Build3761SendData.BuildConrCheckTimeSendCmd(address,DateTime.Now);
await _capBus.PublishAsync(ProtocolConst.SubscriberIssuedEventName, new IssuedEventMessage
{
//ClientId = messageReceived.ClientId,
@@ -284,7 +303,7 @@ namespace JiShe.CollectBus.EnergySystem
var result = new BaseResultDto();
var address = $"{input.AreaCode}{input.Address}";
- var bytes = HexStringExtensions.BuildConrRebootSendCmd(address);
+ var bytes = Build3761SendData.BuildConrRebootSendCmd(address);
await _capBus.PublishAsync(ProtocolConst.SubscriberIssuedEventName, new IssuedEventMessage
{
//ClientId = messageReceived.ClientId,
@@ -312,7 +331,7 @@ namespace JiShe.CollectBus.EnergySystem
var address = $"{input.AreaCode}{input.Address}";
var pnList = input.Data.Split(',').Select(it => int.Parse(it)).ToList();
- var bytes = HexStringExtensions.BuildAmmeterParameterReadingSendCmd(address, pnList);
+ var bytes = Build3761SendData.BuildAmmeterParameterReadingSendCmd(address, pnList);
await _capBus.PublishAsync(ProtocolConst.SubscriberIssuedEventName, new IssuedEventMessage
{
//ClientId = messageReceived.ClientId,
@@ -349,13 +368,13 @@ namespace JiShe.CollectBus.EnergySystem
var fn = int.Parse(itemCodeArr[1]);
if (aFN == AFN.请求实时数据)
{
- var bytes = HexStringExtensions.BuildAmmeterReadRealTimeDataSendCmd(address, ammeter.MeterCode.Value, (ATypeOfDataItems)fn);
+ var bytes = Build3761SendData.BuildAmmeterReadRealTimeDataSendCmd(address, ammeter.MeterCode.Value, (ATypeOfDataItems)fn);
bytesList.Add(bytes);
}
else if (aFN == AFN.请求历史数据)
{
var density = (FreezeDensity)input.Density;
- var bytes = HexStringExtensions.BuildAmmeterReadingIIdataTypeItemsSendCmd(address, ammeter.MeterCode.Value, (IIdataTypeItems)fn, density,0);
+ var bytes = Build3761SendData.BuildAmmeterReadingIIdataTypeItemsSendCmd(address, ammeter.MeterCode.Value, (IIdataTypeItems)fn, density,0);
bytesList.Add(bytes);
}
}
@@ -391,6 +410,27 @@ namespace JiShe.CollectBus.EnergySystem
var ammeter = await SqlProvider.Instance.Change(DbEnum.EnergyDB).Select().Where(d => d.ID == input.MeterID).FirstAsync();
if (ammeter == null) return result;
+ //if (string.IsNullOrEmpty(ammeter.BrandType))
+ //{
+ // resultMsg.Status = false;
+ // resultMsg.Msg = "电表型号为空";
+ // return resultMsg;
+ //}
+ //var listData = ProgramModelConfig.ProgramModels;
+ //var pm = listData.FirstOrDefault(n => n.Model == ammeter.BrandType);
+ //if (pm == null)
+ //{
+ // resultMsg.Status = false;
+ // resultMsg.Msg = $"电表{ammeter.AmmerterAddress}型号{ammeter.BrandType}暂不支持时段设置";
+ // return resultMsg;
+ //}
+
+ //resultMsg.Status = true;
+ //if (pm.IsEnter)
+ //{
+ // resultMsg.Data = pm.cmdData;
+ //}
+
var address = input.FocusCode;
var timeDataList = input.Data.Select(it => new TimeSetDetail()
{
@@ -405,7 +445,7 @@ namespace JiShe.CollectBus.EnergySystem
}).ToList()
}).ToList()
}).ToList();
- var bytesList = HexStringExtensions.BuildAmmeterSetTimeSetSendCmd(address, ammeter.Code, ammeter.Address,
+ var bytesList = Build3761SendData.BuildAmmeterSetTimeSetSendCmd(address, ammeter.Code, ammeter.Address,
ammeter.PortNumber ?? 2, ammeter.BaudRate, timeDataList);
foreach (var bytes in bytesList)
@@ -431,9 +471,26 @@ namespace JiShe.CollectBus.EnergySystem
///
///
[Route("Handmould/SetAutoItemCode")]
- public Task AutoReportCollectionItemsSet(AutoReportCollectionItemsSetInput input)
+ public async Task AutoReportCollectionItemsSet(AutoReportCollectionItemsSetInput input)
{
- throw new NotImplementedException();
+ var result = new BaseResultDto();
+ foreach (var code in input.Codes)
+ {
+ var address = $"{code.AreaCode}{code.Address}";
+ var bytes = Build3761SendData.BuildAmmeterReportCollectionItemsSetSendCmd(address,input.Detail.Pn, input.Detail.Unit,input.Detail.Cycle,input.Detail.BaseTime,
+ input.Detail.CurveRatio,input.Detail.Details.Select(it => new PnFn(it.Pn,it.Fn)).ToList());
+ await _capBus.PublishAsync(ProtocolConst.SubscriberIssuedEventName, new IssuedEventMessage
+ {
+ //ClientId = messageReceived.ClientId,
+ DeviceNo = address,
+ Message = bytes,
+ Type = IssuedEventType.Data,
+ MessageId = NewId.NextGuid().ToString()
+ });
+ }
+ result.Status = true;
+ result.Msg = "操作成功";
+ return result;
}
///
@@ -443,21 +500,50 @@ namespace JiShe.CollectBus.EnergySystem
///
///
[Route("Handmould/SetAutoUpSwitch")]
- public Task AutoReportSet(AutoReportSetInput input)
+ public async Task AutoReportSet(AutoReportSetInput input)
{
- throw new NotImplementedException();
+ var result = new BaseResultDto();
+ foreach (var code in input.Codes)
+ {
+ var address = $"{code.AreaCode}{code.Address}";
+ var bytes = Build3761SendData.BuildAmmeterAutoUpSwitchSetSendCmd(address, input.Detail.Pn,input.Detail.IsOpen);
+ await _capBus.PublishAsync(ProtocolConst.SubscriberIssuedEventName, new IssuedEventMessage
+ {
+ //ClientId = messageReceived.ClientId,
+ DeviceNo = address,
+ Message = bytes,
+ Type = IssuedEventType.Data,
+ MessageId = NewId.NextGuid().ToString()
+ });
+ }
+ result.Status = true;
+ result.Msg = "操作成功";
+ return result;
}
///
- /// 查询自动上报开启状态 数据库操作
+ /// 查询自动上报开启状态
///
///
///
///
[Route("Handmould/QueryAutoUpSwitch")]
- public Task QueryAutoReportOpenStatus(QueryAutoReportOpenStatusInput input)
+ public async Task QueryAutoReportOpenStatus(QueryAutoReportOpenStatusInput input)
{
- throw new NotImplementedException();
+ var result = new BaseResultDto();
+ var address = $"{input.AreaCode}{input.Address}";
+ var bytes = Build3761SendData.BuildAmmeterReadAutoUpSwitchSendCmd(address, input.Detail.Pn);
+ await _capBus.PublishAsync(ProtocolConst.SubscriberIssuedEventName, new IssuedEventMessage
+ {
+ //ClientId = messageReceived.ClientId,
+ DeviceNo = address,
+ Message = bytes,
+ Type = IssuedEventType.Data,
+ MessageId = NewId.NextGuid().ToString()
+ });
+ result.Status = true;
+ result.Msg = "操作成功";
+ return result;
}
///
@@ -473,7 +559,7 @@ namespace JiShe.CollectBus.EnergySystem
foreach (var data in input.Data)
{
var address = $"{data.AreaCode}{data.Address}";
- var bytes = HexStringExtensions.BuildTerminalVersionInfoReadingSendCmd(address);
+ var bytes = Build3761SendData.BuildTerminalVersionInfoReadingSendCmd(address);
await _capBus.PublishAsync(ProtocolConst.SubscriberIssuedEventName, new IssuedEventMessage
{
//ClientId = messageReceived.ClientId,
@@ -510,13 +596,22 @@ namespace JiShe.CollectBus.EnergySystem
public async Task AdjustMeterTiming(AdjustMeterTimingInput input)
{
var result = new BaseResultDto();
-
- var ammeter = await SqlProvider.Instance.Change(DbEnum.EnergyDB).Select().Where(d => d.Address == input.MeterAddress).FirstAsync();
- if (ammeter == null) return result;
-
var address = $"{input.AreaCode}{input.Address}";
- var bytesList = HexStringExtensions.BuildAmmeterCorrectionTimeSendCmd(address, ammeter.Code, ammeter.Address, ammeter.Password,
- ammeter.PortNumber ?? 2, ammeter.BaudRate);
+
+ var bytesList = new List();
+ var dateDataUnit =
+ Build645SendData.BuildAmmeterCorrectionTimeSendDataUnit(input.MeterAddress, input.Password,
+ "04 00 01 01", 0);
+ var dateBytes = Build3761SendData.BuildTransparentForwardingSendCmd(address, input.Port, input.BaudRate.ToString(),
+ dateDataUnit);
+ bytesList.Add(dateBytes);
+
+ var timeDataUnit =
+ Build645SendData.BuildAmmeterCorrectionTimeSendDataUnit(input.MeterAddress, input.Password,
+ "04 00 01 02", 0);
+ var timeBytes = Build3761SendData.BuildTransparentForwardingSendCmd(address, input.Port, input.BaudRate.ToString(),
+ timeDataUnit);
+ bytesList.Add(timeBytes);
foreach (var bytes in bytesList)
{
@@ -542,10 +637,10 @@ namespace JiShe.CollectBus.EnergySystem
///
///
[Route("AfterSaleApi/AddConrOnlineRecord")]
- public async Task AddConrOnlineRecord(AddConrOnlineRecordInput input)
+ public async Task AddConrOnlineRecord(List input)
{
- var conrOnlineRecord = new ConrOnlineRecord(input.AreaCode,input.Address,input.State,input.LastTime);
- await _conrOnlineRecordRepository.InsertAsync(conrOnlineRecord);
+ var conrOnlineRecords = input.Select(it => new ConrOnlineRecord(it.AreaCode, it.Address, it.State, it.LastTime)).ToList();
+ await _conrOnlineRecordRepository.InsertManyAsync(conrOnlineRecords);
return new BaseResultDto()
{
Status = true
@@ -559,10 +654,11 @@ namespace JiShe.CollectBus.EnergySystem
///
///
[Route("AfterSaleApi/RssiToWebApi")]
- public async Task AddSignalStrength(AddSignalStrengthInput input)
+ public async Task AddSignalStrength(List input)
{
- var csqRecord = new CsqRecord(input.Address, input.AreaCode,input.DeviceType,input.Csq);
- await _csqRecordRepository.InsertAsync(csqRecord);
+ var csqRecords = input.Select(it =>
+ new CsqRecord(it.Address, it.AreaCode, it.DeviceType, it.Csq)).ToList();
+ await _csqRecordRepository.InsertManyAsync(csqRecords);
return new BaseResultDto()
{
@@ -577,11 +673,13 @@ namespace JiShe.CollectBus.EnergySystem
///
///
[Route("AfterSaleApi/AddFocusLog")]
- public async Task AddFocusLog(AddFocusLogInput input)
+ public async Task AddFocusLog(List input)
{
- var focusLog = new FocusRecord(input.Address, input.GatherServerId, int.Parse(input.IntervalTime), input.LogTime,
- input.LogType, input.Remark);
- await _focusRecordRepository.InsertAsync(focusLog);
+ var focusLogs = input.Select(it =>
+ new FocusRecord(it.Address, it.GatherServerId, int.Parse(it.IntervalTime), it.LogTime,
+ it.LogType, it.Remark)).ToList();
+
+ await _focusRecordRepository.InsertManyAsync(focusLogs);
return new BaseResultDto()
{
diff --git a/src/JiShe.CollectBus.Common/BuildSendDatas/Build188SendData.cs b/src/JiShe.CollectBus.Common/BuildSendDatas/Build188SendData.cs
new file mode 100644
index 0000000..5fb9e3b
--- /dev/null
+++ b/src/JiShe.CollectBus.Common/BuildSendDatas/Build188SendData.cs
@@ -0,0 +1,213 @@
+using JiShe.CollectBus.Common.Enums;
+using JiShe.CollectBus.Common.Extensions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace JiShe.CollectBus.Common.BuildSendDatas
+{
+ public static class Build188SendData
+ {
+ //起始字符
+ private const string startStr = "68";
+
+ //结束字符
+ private const string endStr = "16";
+
+ #region 188 下行命令
+
+ ///
+ /// 标准 188协议阀控
+ ///
+ ///
+ /// 表计类型
+ ///
+ public static List BuildConfirm188WaterValve(string waterMeterAddress, bool state, string mtype = "10")
+ {
+ if (string.IsNullOrWhiteSpace(waterMeterAddress)) return null;
+
+ var dataUnit = new List() { "A0", "17", "00", state ? "55" : "99" };
+
+ var dataList = Build188SendCommand(waterMeterAddress, "04", dataUnit);
+
+ return dataList;
+ }
+
+ ///
+ /// 构建188水表抄读下发数据单元
+ ///
+ ///
+ ///
+ public static List Build188WaterMeterReadingSendDataUnit(string waterMeterAddress)
+ {
+
+ var dataUnit = new List() { "1F", "90", "00" };
+ var dataList = Build188SendCommand(waterMeterAddress, "01", dataUnit);
+
+ return dataList;
+ }
+
+ ///
+ /// 构建188协议下发命令
+ ///
+ /// 水表地址
+ /// 控制码
+ /// 数据域
+ /// 表类型
+ ///
+ public static List Build188SendCommand(string waterMeterAddress, string controlCode, List? dataUnit = null, string meterType = "10")
+ {
+ //address.Substring(address.Length - 12, 12)
+ var cmdStrList = new List();
+ cmdStrList.Add(startStr);
+ cmdStrList.Add(meterType);
+
+ waterMeterAddress = waterMeterAddress.PadLeft(14, '0');
+ var addressList = waterMeterAddress.StringToPairs();
+ addressList.Reverse();
+ cmdStrList.AddRange(addressList);
+
+ //控制码
+ cmdStrList.Add(controlCode);
+
+ var len = dataUnit != null ? dataUnit.Count.DecToHex().PadLeft(2, '0') : "00";
+ cmdStrList.Add(len);
+ if (dataUnit != null)
+ {
+ cmdStrList.AddRange(dataUnit);
+ }
+
+ var strSum = cmdStrList.Select(i => Convert.ToInt32(i, 16)).Sum().ToString("X");
+ strSum = strSum.Substring(strSum.Length - 2);
+ cmdStrList.Add(strSum);
+ cmdStrList.Add(endStr);
+
+ return cmdStrList;
+ }
+
+ ///
+ /// 组装水表阀控
+ ///
+ /// 水表地址
+ /// The password.
+ /// The poprotocol.
+ /// if set to true [isopenvalve].
+ ///
+ public static List? WaterMeterValveControl(string waterMeterAddress, string password, int protocol, bool state)
+ {
+ List? turnData = null;
+ if (protocol == 1)
+ turnData = GetControlCode97(waterMeterAddress.Substring(waterMeterAddress.Length - 12, 12), password, state ? "3355" : "9966");//开阀/关阀
+ else if (protocol == 30)
+ turnData = GetControlCode07(waterMeterAddress.Substring(waterMeterAddress.Length - 12, 12), password, state ? "3355" : "9966");//开阀/关阀
+ return turnData;
+ }
+
+ private static List GetControlCode97(string waterMeterAddress, string password, string valueCode)
+ {
+ var dataList = new List();
+ var passwordList = password.StringToPairs();
+ passwordList.Reverse();
+
+ var valueCodeList = valueCode.StringToPairs();
+ valueCodeList.Reverse();
+
+ dataList.AddRange(valueCodeList);
+ dataList.AddRange(passwordList);
+ dataList.AddRange(valueCodeList);
+
+ return GetCode(waterMeterAddress, "04", dataList);
+ }
+
+ private static List GetControlCode07(string waterMeterAddress, string password, string valueCode)
+ {
+ var dataList = new List();
+ dataList.Add("02");
+
+ var passwordList = password.StringToPairs();
+ passwordList.Reverse();
+ dataList.AddRange(passwordList);
+ dataList.AddRange("01000000".StringToPairs());
+
+ dataList.AddRange(valueCode.StringToPairs());
+
+ dataList.Add("00");
+
+ var time = DateTime.Now.AddDays(1).ToString("yyMMddHHmmss");
+ var timeList = time.StringToPairs();
+ timeList.Reverse();
+ dataList.AddRange(timeList);
+
+ return GetCode(waterMeterAddress, "1C", dataList);
+ }
+
+ public static List GetCode(string waterMeterAddress, string controlCode, List childDataList)
+ {
+ var dataList = new List { startStr };
+
+ waterMeterAddress = waterMeterAddress.PadLeft(12, '0');
+ var addressList = waterMeterAddress.StringToPairs();
+ addressList.Reverse();
+ dataList.AddRange(addressList);
+
+ dataList.Add(startStr);
+ dataList.Add(controlCode);
+
+ var num = childDataList.Count;
+ dataList.Add(num.ToString("X2"));
+
+ dataList.AddRange(childDataList.AddHex33());
+
+ var cs = dataList.Select(it => Convert.ToInt32(it, 16)).Sum().ToString("X2");
+ cs = cs.Substring(cs.Length - 2, 2);
+ dataList.Add(cs);
+
+ dataList.Add(endStr);
+
+ return dataList;
+ }
+
+
+ public static object GetAnalyzeValue(this List hexStringList, CommandChunkEnum188 chunk)
+ {
+ if (hexStringList.Count < 11)
+ {
+ return null;
+ }
+
+ switch (chunk)
+ {
+ case CommandChunkEnum188.A:
+ var aHexList = hexStringList[(int)CommandChunkEnum188.A].Take(7).ToList();
+ aHexList.Reverse();
+ return string.Join("", aHexList.Skip(1).Take(6).ToList());
+ case CommandChunkEnum188.C:
+ var cHex = hexStringList[(int)CommandChunkEnum188.C];
+ return cHex;
+ case CommandChunkEnum188.Data:
+ var lenIndex = (int)CommandChunkEnum188.L;
+ var len = hexStringList[lenIndex].HexToDec();
+
+ //验证长度 2=(帧校验和+结束字符)
+ if (hexStringList.Count - 2 != 11 + len)
+ return null;
+
+ var dataHexList = hexStringList.Skip(11).Take(len).ToList();
+ return dataHexList;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(chunk), chunk, null);
+ }
+ }
+
+ //public double AnalyzeCurrentTotalRate(List hexList)
+ //{
+ // var str = string.Join("", hexList);
+ // var number = Convert.ToInt32(str) * 0.01;
+ // return number;
+ //}
+
+ #endregion
+ }
+}
diff --git a/src/JiShe.CollectBus.Common/BuildSendDatas/Build3761SendData.cs b/src/JiShe.CollectBus.Common/BuildSendDatas/Build3761SendData.cs
new file mode 100644
index 0000000..224c242
--- /dev/null
+++ b/src/JiShe.CollectBus.Common/BuildSendDatas/Build3761SendData.cs
@@ -0,0 +1,1650 @@
+using JiShe.CollectBus.Common.Enums;
+using JiShe.CollectBus.Common.Extensions;
+using JiShe.CollectBus.Common.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Volo.Abp.Domain.Entities;
+
+namespace JiShe.CollectBus.Common.BuildSendDatas
+{
+ public static class Build3761SendData
+ {
+ //起始字符
+ private const string startStr = "68";
+ //结束字符
+ private const string endStr = "16";
+ //头部字节长度
+ private const int hearderLen = 6;
+ //消息认证码字段长度
+ private const int pWLen = 16;
+
+ private const int FixedLength = 18;
+
+ static object locker = new object();
+ static List MSA = new List();
+ static Dictionary> usingMSA = new Dictionary>();
+
+ static Build3761SendData()
+ {
+ for (int i = 1; i <= 127; i++)
+ {
+ MSA.Add(i);
+ }
+ }
+ ///
+ /// Gets the msa.
+ ///
+ /// 集中器地址
+ ///
+ public static int GetMSA(string mark)
+ {
+ lock (locker)
+ {
+ if (!usingMSA.Keys.Contains(mark))
+ usingMSA.Add(mark, new List());
+
+ int msa = MSA.Except(usingMSA[mark]).FirstOrDefault();
+ //if (msa == 1) msa = 2;//msa=1为自定义指令保留
+ usingMSA[mark].Add(msa);
+
+ if (msa == 127)
+ usingMSA[mark].RemoveAll(m => true);
+
+ return msa;
+ }
+ }
+
+
+ #region 376.1下行命令
+
+ ///
+ /// 构建电表修正时间下发命令
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static List BuildAmmeterCorrectionTimeSendCmd(string address, string modelCode, string ammeterAddress, string password, int port, string baudRate)
+ {
+ var bytesList = new List();
+ if (modelCode == "PMAC9523")
+ {
+ var dataUnit = Build645SendData.BuildPMAC9523AmmeterCorrectionTimeSendDataUnit(ammeterAddress);
+ var bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, dataUnit, StopBit.Stop1, Parity.None);
+ bytesList.Add(bytes);
+ }
+ else if (modelCode == "DTSU193")
+ {
+ var dataUnit = Build645SendData.BuildDTSU193AmmeterCorrectionTimeSendDataUnit(ammeterAddress);
+ var bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, dataUnit);
+ bytesList.Add(bytes);
+ }
+ else
+ {
+ var dataUnitList = Build645SendData.BuildAmmeterCorrectionTimeSendDataUnit(ammeterAddress,password);
+ foreach (var dataUnit in dataUnitList)
+ {
+ var bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, dataUnit);
+ bytesList.Add(bytes);
+ }
+ }
+ return bytesList;
+ }
+
+
+ ///
+ /// 构建电表读取时段设置下发命令
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static List BuildReadMeterTimeSetSendCmd(string address, string modelCode, string ammeterAddress, string password, int port, string baudRate)
+ {
+ if (modelCode == "DTSU193")
+ {
+ return null;
+ }
+
+ if (modelCode == "PMAC9523")
+ {
+ var dataUnit = Build645SendData.BuildPMAC9523ReadMeterTimeSetSendDataUnit(ammeterAddress);
+ var bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, dataUnit, StopBit.Stop1, Parity.None);
+ return new List() { bytes };
+ }
+
+ var bytes1 = BuildTransparentForwardingSendCmd(address, port, baudRate,
+ Build645SendData.BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04010001"));
+
+ var bytes2 = BuildTransparentForwardingSendCmd(address, port, baudRate,
+ Build645SendData.BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04010002"));
+
+ var bytes3 = BuildTransparentForwardingSendCmd(address, port, baudRate,
+ Build645SendData.BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04010003"));
+
+ var bytes4 = BuildTransparentForwardingSendCmd(address, port, baudRate,
+ Build645SendData.BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04010004"));
+
+ var bytes9 = BuildTransparentForwardingSendCmd(address, port, baudRate,
+ Build645SendData.BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04010005"));
+
+ var bytes5 = BuildTransparentForwardingSendCmd(address, port, baudRate,
+ Build645SendData.BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04020001"));
+
+ var bytes6 = BuildTransparentForwardingSendCmd(address, port, baudRate,
+ Build645SendData.BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04020002"));
+
+ var bytes7 = BuildTransparentForwardingSendCmd(address, port, baudRate,
+ Build645SendData.BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04020003"));
+
+ var bytes8 = BuildTransparentForwardingSendCmd(address, port, baudRate,
+ Build645SendData.BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04020004"));
+
+ var bytes10 = BuildTransparentForwardingSendCmd(address, port, baudRate,
+ Build645SendData.BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04020005"));
+
+
+ return new List { bytes1, bytes2, bytes3, bytes4, bytes5, bytes6, bytes7, bytes8, bytes9, bytes10 };
+ }
+
+
+ ///
+ /// 构建设置时段下发命令
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static List BuildAmmeterSetTimeSetSendCmd(string address, string ammeterAddress, string modelCode, int port, string baudRate, List data)
+ {
+ List bytesList = new List();
+ if (modelCode == "DTSU193")
+ {
+ return null;
+ }
+ else if (modelCode == "PMAC9523")
+ {
+ var dataUnitList = Build645SendData.BuildPMAC9523AmmeterSetTimeSetSendDataUnit(ammeterAddress, data);
+ foreach (var dataUnit in dataUnitList)
+ {
+ var bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, dataUnit, StopBit.Stop1, Parity.None);
+ bytesList.Add(bytes);
+ }
+ }
+ else
+ {
+ #region 采用TimeSet方法设置 弃用
+ //List fm = null;
+ //SendInfo sendInfo = null;
+ //List tempSi = new List();
+ ////判断是否需要进入编程模式,获取编程模式指令
+ //var pm = ProgramModelConfig.ProgramModels.FirstOrDefault(n => n.BrandName == meterInfo.brand_name
+ //&& n.Model == meterInfo.model_name);
+ //if (pm != null)
+ //{
+ // if (pm.IsEnter)
+ // {
+ // //编程指令
+ // var bccmd= pm.cmdData;
+ // //替换表地址
+ // var addressList= Protocol.QGDW3761.DataTypeConvert.CutStr(meterInfo.meter_address, 2, true);
+ // var addressstr = string.Join(" ",addressList);
+ // bccmd = bccmd.Replace("AA AA AA AA AA AA", addressstr);
+ // fm = bccmd.Split(' ').ToList();
+
+ // //生成CRC
+ // var CRC = Protocol.QGDW3761.DataTypeConvert.GetCRC(fm);
+ // fm.Add(CRC);
+ // fm.Add("16");
+
+ // confirmResult = GatherCmdHelper.ConrTurnData(meterInfo, fm, true);
+ // sendInfo = new SendInfo
+ // (
+ // confirmResult.msa,
+ // confirmResult.cmd16,
+ // MeterType.Ammeter,
+ // CmdType.ProgramModel,
+ // null,
+ // sDto
+ // );
+ // si.Add(sendInfo);
+ // }
+ // //年时区数
+ // int yearTimeZoneCount = 0;
+ // //日时段数
+ // int dayTimeZoneCount = 0;
+ // //费率
+ // int rate = 0;
+ // //发送两套时区
+ // for (int j = 1; j <= 2; j++)
+ // {
+ // //发送时区表数据
+ // var timeZoneData = GenerateTimeZone(sDto);
+ // yearTimeZoneCount = timeZoneData.Count / 3;
+ // fm = GenerateCTCommand($"040{j}0000", string.Join("", timeZoneData));
+ // confirmResult = GatherCmdHelper.ConrTurnData(meterInfo, fm, true);
+ // sendInfo = new SendInfo
+ // (
+ // confirmResult.msa,
+ // confirmResult.cmd16,
+ // MeterType.Ammeter,
+ // CmdType.SetTimeSet,
+ // null,
+ // sDto
+ // );
+ // tempSi.Add(sendInfo);
+ // //发送日时段数据
+ // for (int i = 1; i <= sDto.data.Count; i++)
+ // {
+ // var dayTimeZone = GenerateDayTimeZone(sDto.data[i - 1].data);
+
+ // fm = GenerateCTCommand($"040{j}000{i}", string.Join("", dayTimeZone));
+ // confirmResult = GatherCmdHelper.ConrTurnData(meterInfo, fm, true);
+ // sendInfo = new SendInfo
+ // (
+ // confirmResult.msa,
+ // confirmResult.cmd16,
+ // MeterType.Ammeter,
+ // CmdType.SetTimeSet,
+ // null,
+ // sDto
+ // );
+ // tempSi.Add(sendInfo);
+
+ // //计算日时段数
+ // var dz = dayTimeZone.Count / 3;
+ // if (dz > dayTimeZoneCount) dayTimeZoneCount = dz;
+ // //计算费率
+
+ // foreach(var detail in sDto.data[i - 1].data)
+ // {
+ // int rt = Convert.ToInt32(detail.rate);
+ // if (rt > rate) rate = rt;
+ // }
+
+
+ // }
+ // }
+
+ // #region 年时区数(NN)
+ // fm = GenerateCTCommand($"04000201", yearTimeZoneCount.ToString().PadLeft(2, '0'));
+ // confirmResult = GatherCmdHelper.ConrTurnData(meterInfo, fm, true);
+ // sendInfo = new SendInfo
+ // (
+ // confirmResult.msa,
+ // confirmResult.cmd16,
+ // MeterType.Ammeter,
+ // CmdType.SetTimeSet,
+ // null,
+ // sDto
+ // );
+ // si.Add(sendInfo);
+ // #endregion
+ // #region 日时段数据(NN)
+ // fm = GenerateCTCommand($"04000202", sDto.data.Count.ToString().PadLeft(2, '0'));
+ // confirmResult = GatherCmdHelper.ConrTurnData(meterInfo, fm, true);
+ // sendInfo = new SendInfo
+ // (
+ // confirmResult.msa,
+ // confirmResult.cmd16,
+ // MeterType.Ammeter,
+ // CmdType.SetTimeSet,
+ // null,
+ // sDto
+ // );
+ // si.Add(sendInfo);
+ // #endregion
+ // #region 日时段数(每日切换数)(NN)
+ // fm = GenerateCTCommand($"04000203", dayTimeZoneCount.ToString().PadLeft(2, '0'));
+ // confirmResult = GatherCmdHelper.ConrTurnData(meterInfo, fm, true);
+ // sendInfo = new SendInfo
+ // (
+ // confirmResult.msa,
+ // confirmResult.cmd16,
+ // MeterType.Ammeter,
+ // CmdType.SetTimeSet,
+ // null,
+ // sDto
+ // );
+ // si.Add(sendInfo);
+ // #endregion
+ // #region 费率数(NN)
+ // fm = GenerateCTCommand($"04000204", rate.ToString().PadLeft(2, '0'));
+ // confirmResult = GatherCmdHelper.ConrTurnData(meterInfo, fm, true);
+ // sendInfo = new SendInfo
+ // (
+ // confirmResult.msa,
+ // confirmResult.cmd16,
+ // MeterType.Ammeter,
+ // CmdType.SetTimeSet,
+ // null,
+ // sDto
+ // );
+ // si.Add(sendInfo);
+ // #endregion
+ // si.AddRange(tempSi);
+
+ // tempSi.Clear();
+ // // si[si.Count - 1].cmdType = CmdType.SetTimeSet;//取最后一条指令的结果返回
+ //}
+
+ #endregion
+ }
+ return bytesList;
+ }
+
+
+ ///
+ /// 构建电表参数设置-下发命令
+ ///
+ /// 集中器地址
+ ///
+ ///
+ public static byte[] BuildAmmeterParameterSetSendCmd(string address, List meterParameters)
+ {
+ var dataUnit = BuildAmmeterParameterSendDataUnit(meterParameters);
+ var reqParameter = new ReqParameter2()
+ {
+ AFN = AFN.设置参数,
+ FunCode = (int)CMasterStationFunCode.请求1级数据,
+ A = address,
+ Seq = new Seq()
+ {
+ TpV = TpV.附加信息域中无时间标签,
+ FIRFIN = FIRFIN.单帧,
+ CON = CON.需要对该帧进行确认,
+ PRSEQ = 10,
+ },
+ MSA = GetMSA(address),
+ Pn = 0,
+ Fn = 10
+ };
+ var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
+ return bytes;
+ }
+
+ ///
+ /// 构建电表参数读取-下发命令
+ ///
+ /// 集中器地址
+ /// 对象序号
+ public static byte[] BuildAmmeterParameterReadingSendCmd(string address, List meterNumberList)
+ {
+ var dataUnit = new List();
+ var countHex = meterNumberList.Count().DecToHex().PadLeft(4, '0');
+ var countHexPairs = countHex.StringToPairs();
+ countHexPairs.Reverse();
+ dataUnit.AddRange(countHexPairs);
+
+ foreach (var number in meterNumberList)
+ {
+ var numberHex = number.DecToHex().PadLeft(4, '0');
+ var numberHexPairs = numberHex.StringToPairs();
+ numberHexPairs.Reverse();
+ dataUnit.AddRange(numberHexPairs);
+ }
+
+ var reqParameter = new ReqParameter2()
+ {
+ AFN = AFN.查询参数,
+ FunCode = (int)CMasterStationFunCode.请求2级数据,
+ A = address,
+ Seq = new Seq()
+ {
+ TpV = TpV.附加信息域中无时间标签,
+ FIRFIN = FIRFIN.单帧,
+ CON = CON.不需要对该帧进行确认,
+ PRSEQ = 0,
+ },
+ MSA = GetMSA(address),
+ Pn = 0,
+ Fn = 10
+ };
+ var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
+ return bytes;
+ }
+
+ ///
+ /// 构建电表抄读一类数据-下发命令
+ ///
+ ///
+ ///
+ /// 一类数据项
+ public static byte[] BuildAmmeterReadRealTimeDataSendCmd(string address, int pn, ATypeOfDataItems aTypeOfDataItems)
+ {
+ var reqParameter = new ReqParameter2()
+ {
+ AFN = AFN.请求实时数据,
+ FunCode = (int)CMasterStationFunCode.请求2级数据,
+ A = address,
+ Seq = new Seq()
+ {
+ TpV = TpV.附加信息域中无时间标签,
+ FIRFIN = FIRFIN.单帧,
+ CON = CON.不需要对该帧进行确认,
+ PRSEQ = 2,
+ },
+ MSA = GetMSA(address),
+ Pn = pn,
+ Fn = (int)aTypeOfDataItems
+ };
+ var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter);
+ return bytes;
+ }
+
+ ///
+ /// 构建电表抄读日冻结正向有功电能示值-下发命令
+ ///
+ ///
+ ///
+ ///
+ public static void BuildAmmeterReadDailyFreezingDataSendCmd(string address, int pn, DateTime time)
+ {
+ var dataUnit = time.ToString("yy-MM-dd").Split('-').ToList();
+ dataUnit.Reverse();
+ var reqParameter = new ReqParameter2()
+ {
+ AFN = AFN.请求历史数据,
+ FunCode = (int)CMasterStationFunCode.请求2级数据,
+ A = address,
+ Seq = new Seq()
+ {
+ TpV = TpV.附加信息域中无时间标签,
+ FIRFIN = FIRFIN.单帧,
+ CON = CON.不需要对该帧进行确认,
+ PRSEQ = 2,
+ },
+ MSA = GetMSA(address),
+ Pn = pn,
+ Fn = 161
+ };
+ var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
+ }
+
+ ///
+ /// 构建电表抄读实时电流-下发命令
+ ///
+ ///
+ ///
+ public static void BuildAmmeterRealTimeCurrentDataSendCmd(string address, int pn)
+ {
+ var reqParameter = new ReqParameter2()
+ {
+ AFN = AFN.请求实时数据,
+ FunCode = (int)CMasterStationFunCode.请求2级数据,
+ A = address,
+ Seq = new Seq()
+ {
+ TpV = TpV.附加信息域中无时间标签,
+ FIRFIN = FIRFIN.单帧,
+ CON = CON.不需要对该帧进行确认,
+ PRSEQ = 2,
+ },
+ MSA = GetMSA(address),
+ Pn = pn,
+ Fn = 25
+ };
+ var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter);
+ }
+
+ ///
+ /// 构建自动上报开启状态读取-下发命令
+ ///
+ /// 集中器地址
+ ///
+ ///
+ public static byte[] BuildAmmeterReadAutoUpSwitchSendCmd(string address, int pn)
+ {
+ var reqParameter = new ReqParameter2()
+ {
+ AFN = AFN.查询参数,
+ FunCode = (int)CMasterStationFunCode.请求2级数据,
+ A = address,
+ Seq = new Seq()
+ {
+ TpV = TpV.附加信息域中无时间标签,
+ FIRFIN = FIRFIN.单帧,
+ CON = CON.不需要对该帧进行确认,
+ PRSEQ = 2,
+ },
+ MSA = GetMSA(address),
+ Pn = pn,
+ Fn = 68
+ };
+ var bytes = BuildSendCommandBytes(reqParameter);
+ return bytes;
+ }
+
+ ///
+ /// 构建自动上报开启状态设置-下发命令
+ ///
+ /// 集中器地址
+ ///
+ ///
+ ///
+ public static byte[] BuildAmmeterAutoUpSwitchSetSendCmd(string address, int pn,bool isOpen)
+ {
+ var dataUnit = new List(){ isOpen ? "55" : "AA" };//自动上报任务命令字节
+ dataUnit.AddRange(GetPW());
+ var reqParameter = new ReqParameter2()
+ {
+ AFN = AFN.设置参数,
+ FunCode = (int)CMasterStationFunCode.请求1级数据,
+ A = address,
+ Seq = new Seq()
+ {
+ TpV = TpV.附加信息域中无时间标签,
+ FIRFIN = FIRFIN.单帧,
+ CON = CON.需要对该帧进行确认,
+ PRSEQ = 10,
+ },
+ MSA = GetMSA(address),
+ Pn = pn,
+ Fn = 68
+ };
+ var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
+ return bytes;
+ }
+
+
+ ///
+ /// 构建自动上报采集项设置-下发命令
+ ///
+ /// 集中器地址
+ /// 计量点
+ /// 定时发送周期(单位)
+ /// 定时发送周期 1:用 D6~D7 编码表示,取值 0~3 依次表示分、时、日、月 2:用 D0~D5 表示,为定时上报数据的时间周期
+ /// 发送基准时间
+ /// 曲线数据提取倍率
+ ///
+ ///
+ public static byte[] BuildAmmeterReportCollectionItemsSetSendCmd(string address, int pn,int unit,int cycle,DateTime baseTime,int curveRatio,List pnFns)
+ {
+ List dataUnit = new List();
+
+ var cycleSb = $"{unit.DecToBin()}{cycle.DecToBin()}";
+ dataUnit.Add(cycleSb.BinToHex().PadLeft(2, '0'));
+ dataUnit.AddRange(baseTime.ToString("ssmmHHddMMyy").StringToPairs());//发送基准时间
+ dataUnit.Add(curveRatio.DecToHex().PadLeft(2, '0'));//曲线数据提取倍率
+ dataUnit.Add(pnFns.Count.DecToHex().PadLeft(2, '0'));//数据单元标识个数 n
+
+ foreach (var item in pnFns)
+ {
+ dataUnit.AddRange(BuildDA(item.Pn));//单元数据标记、单元数据
+ dataUnit.AddRange(BuildDT(item.Fn));//单元数据标记、单元数据
+ }
+
+ dataUnit.AddRange(GetPW());
+ var reqParameter = new ReqParameter2()
+ {
+ AFN = AFN.设置参数,
+ FunCode = (int)CMasterStationFunCode.请求1级数据,
+ A = address,
+ Seq = new Seq()
+ {
+ TpV = TpV.附加信息域中无时间标签,
+ FIRFIN = FIRFIN.单帧,
+ CON = CON.需要对该帧进行确认,
+ PRSEQ = 10,
+ },
+ MSA = GetMSA(address),
+ Pn = pn,
+ Fn = 66
+ };
+ var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
+ return bytes;
+ }
+
+ ///
+ /// 构建电表读取二类数据-下发命令
+ ///
+ ///
+ ///
+ /// fn
+ /// 冻结密度
+ /// 冻结点数
+ /// 起始时间
+ public static byte[] BuildAmmeterReadingIIdataTypeItemsSendCmd(string address, int pn, IIdataTypeItems iIDataTypeItems, FreezeDensity density, int points, DateTime? beginTime = null)
+ {
+ var queryDate = beginTime ?? DateTime.Today.AddDays(-1);
+ var dataUnit = queryDate.ToString("yyMMddHHmm").StringToPairs();
+ dataUnit.Reverse();
+
+ //冻结密度
+ dataUnit.Add(((int)density).DecToHex());
+
+ dataUnit.Add(points.DecToHex());
+
+ var reqParameter = new ReqParameter2()
+ {
+ AFN = AFN.请求历史数据,
+ FunCode = (int)CMasterStationFunCode.请求2级数据,
+ A = address,
+ Seq = new Seq()
+ {
+ TpV = TpV.附加信息域中无时间标签,
+ FIRFIN = FIRFIN.单帧,
+ CON = CON.不需要对该帧进行确认,
+ PRSEQ = 2,
+ },
+ MSA = GetMSA(address),
+ Pn = pn,
+ Fn = (int)iIDataTypeItems
+ };
+ var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
+ return bytes;
+ }
+
+ ///
+ /// 构建电表读取二类数据-下发命令
+ ///
+ ///
+ ///
+ /// fn
+ /// 数据时标
+ /// 起始时间
+ public static void BuildAmmeterReadingBaseDataSendCmd(string address, int pn, IIdataTypeItems iIDataTypeItems, TdType tdType, DateTime? beginTime = null)
+ {
+ var queryDate = beginTime ?? DateTime.Today.AddDays(-1);
+ List? dataUnit = null;
+ switch (tdType)
+ {
+ case TdType.Td_d:
+ dataUnit = queryDate.ToString("yyMMdd").StringToPairs();
+ break;
+ case TdType.Td_m:
+ dataUnit = queryDate.ToString("yyMM").StringToPairs();
+ break;
+ }
+
+ if (dataUnit == null) return;
+
+ dataUnit.Reverse();
+ var reqParameter = new ReqParameter2()
+ {
+ AFN = AFN.请求历史数据,
+ FunCode = (int)CMasterStationFunCode.请求2级数据,
+ A = address,
+ Seq = new Seq()
+ {
+ TpV = TpV.附加信息域中无时间标签,
+ FIRFIN = FIRFIN.单帧,
+ CON = CON.不需要对该帧进行确认,
+ PRSEQ = 2,
+ },
+ MSA = GetMSA(address),
+ Pn = pn,
+ Fn = (int)iIDataTypeItems
+ };
+ var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
+ }
+
+
+ ///
+ /// 组装有/无功电量
+ ///
+ ///
+ ///
+ ///
+ public static void BuildAmmeterReadingElectricityDataSendCmd(string address, int pn, int cmdType)
+ {
+ var reqParameter = new ReqParameter2()
+ {
+ AFN = AFN.请求实时数据,
+ FunCode = (int)CMasterStationFunCode.请求2级数据,
+ A = address,
+ Seq = new Seq()
+ {
+ TpV = TpV.附加信息域中无时间标签,
+ FIRFIN = FIRFIN.单帧,
+ CON = CON.不需要对该帧进行确认,
+ PRSEQ = 2,
+ },
+ MSA = GetMSA(address),
+ Pn = pn,
+ Fn = cmdType
+ };
+ var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter);
+ }
+
+ ///
+ /// 构建超功率设置-下发命令
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void BuildAmmeterSuperpowerSettingSendCmd(string address, string password, string modelCode, int port, string baudRate, decimal power)
+ {
+ if (power > 0)
+ {
+
+ WsOnSupperPower(address, password, modelCode, true, port, baudRate);
+
+ //TODO:连续发几条嘛?
+ string dataMark;
+ //如果是多回路电表,地址只取前面部分 例如:564880000001_01 取564880000001
+ if (address.IndexOf('_') > 0)
+ {
+ var addressSplit = address.Split('_');
+ address = addressSplit[0];
+ var loop = Convert.ToInt32(addressSplit[1]);
+ if (loop == 1) { dataMark = "0E300101"; }
+ else if (loop == 2) { dataMark = "0E300201"; }
+ else
+ return;
+ }
+ else
+ {
+ dataMark = "0E300101";
+ }
+
+ var turnData = Build645SendData.AssembleWsSupperPower(address, password, dataMark, power);
+ if (turnData != null)
+ {
+ var bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, turnData);
+ }
+ }
+ else
+ {
+ WsOnSupperPower(address, password, modelCode, false, port, baudRate);
+ }
+
+ }
+
+ ///
+ /// 构建恶性负载绝对功率设置-下发命令
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void BuildAmmeterAbsolutePowerSettingSendCmd(string address, string password, int port, string baudRate, decimal power)
+ {
+ if (power <= 0)
+ {
+ power = 99;//等于小0 代表关闭
+ }
+
+ string dataMark;
+ //如果是多回路电表,地址只取前面部分 例如:564880000001_01 取564880000001
+ if (address.IndexOf('_') > 0)
+ {
+ var addressSplit = address.Split('_');
+ address = addressSplit[0];
+
+ var loop = Convert.ToInt32(addressSplit[1]);
+ if (loop == 1) { dataMark = "0E300103"; }
+ else if (loop == 2) { dataMark = "0E300203"; }
+ else
+ return;
+ }
+ else
+ {
+ dataMark = "0E300103";
+ }
+
+ var turnData = Build645SendData.AssembleWsAbsolutePowerSetting(address, password, dataMark, power);
+ if (turnData != null)
+ {
+ var bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, turnData);
+ }
+ }
+
+ ///
+ /// 构建恶性负载功率因数设置-下发命令
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void BuildAmmeterPowerFactorSettingSendCmd(string address, string password, int port, string baudRate, decimal power)
+ {
+ string dataMark;
+ //如果是多回路电表,地址只取前面部分 例如:564880000001_01 取564880000001
+ if (address.IndexOf('_') > 0)
+ {
+ var addressSplit = address.Split('_');
+ address = addressSplit[0];
+
+ var loop = Convert.ToInt32(addressSplit[1]);
+ if (loop == 1) { dataMark = "0E300104"; }
+ else if (loop == 2) { dataMark = "0E300204"; }
+ else
+ return;
+ }
+ else
+ {
+ dataMark = "0E300104";
+ }
+
+ var turnData = Build645SendData.AssembleWsPowerFactor(address, password, dataMark, power);
+ if (turnData != null)
+ {
+ var bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, turnData);
+ }
+ }
+
+ ///
+ /// 超功率开关
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void WsOnSupperPower(string address, string password, string modelCode, bool isOn, int port, string baudRate)
+ {
+
+ List modelCodes = new List() { "DDS3102-S2", "DDS71", "DDZY71", "DTZY71", "DSZY71" };
+ //这些型号需进入软编程
+ if (modelCodes.Contains(modelCode))
+ {
+ var dataUnit1 = Build645SendData.SoftProgram(address, modelCode, password);
+ BuildTransparentForwardingSendCmd(address, port, baudRate, dataUnit1);
+ }
+
+ var dataUnit2 = Build645SendData.AssembleWsOnSupperPower(address, password, isOn);
+ BuildTransparentForwardingSendCmd(address, port, baudRate, dataUnit2);
+ }
+
+ ///
+ /// 构建水表参数设置-下发命令
+ ///
+ /// 集中器地址
+ ///
+ ///
+ public static byte[] BuildWaterMeterParameterSetSendCmd(string address, List meterParameters)
+ {
+ var dataUnit = BuildWaterMeterParameterSendDataUnit(meterParameters);
+ var reqParameter = new ReqParameter2()
+ {
+ AFN = AFN.设置参数,
+ FunCode = (int)CMasterStationFunCode.请求1级数据,
+ A = address,
+ Seq = new Seq()
+ {
+ TpV = TpV.附加信息域中无时间标签,
+ FIRFIN = FIRFIN.单帧,
+ CON = CON.需要对该帧进行确认,
+ PRSEQ = 10,
+ },
+ MSA = GetMSA(address),
+ Pn = 0,
+ Fn = 10
+ };
+ var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
+ return bytes;
+ }
+
+ ///
+ /// 构建通讯参数设置-下发命令
+ ///
+ /// 集中器地址
+ /// 主站ip
+ /// 主站端口
+ /// 备用ip和端口
+ /// 备用ip和端口
+ /// APN:CMNET 63 6D 6E 65 74
+ ///
+ public static byte[] BuildCommunicationParametersSetSendCmd(string address, string masterIP, string masterPort,
+ string backupIP, string backupPort, string aPN)
+ {
+ var dataUnit = new List();
+ var masterIPList = masterIP.Split('.').Select(it => int.Parse(it).DecToHex().PadLeft(2, '0')).ToList();
+ dataUnit.AddRange(masterIPList);
+
+ var masterPortList = int.Parse(masterPort).DecToHex().PadLeft(4, '0').StringToPairs();
+ masterPortList.Reverse();
+ dataUnit.AddRange(masterPortList);
+
+ var backupIPList = backupIP.Split('.').Select(it => int.Parse(it).DecToHex().PadLeft(2, '0')).ToList();
+ dataUnit.AddRange(backupIPList);
+
+ var backupPortList = int.Parse(backupPort).DecToHex().PadLeft(4, '0').StringToPairs();
+ backupPortList.Reverse();
+ dataUnit.AddRange(backupPortList);
+
+ var aPNList = aPN.ToCharArray().Select(it => Convert.ToInt32(it).DecToHex().PadLeft(2, '0')).ToList();
+ aPNList.AddRange(Enumerable.Repeat("00", 16 - aPNList.Count));
+ dataUnit.AddRange(aPNList);
+
+ var reqParameter = new ReqParameter2()
+ {
+ AFN = AFN.设置参数,
+ FunCode = (int)CMasterStationFunCode.请求1级数据,
+ A = address,
+ Seq = new Seq()
+ {
+ TpV = TpV.附加信息域中无时间标签,
+ FIRFIN = FIRFIN.单帧,
+ CON = CON.需要对该帧进行确认,
+ PRSEQ = 10,
+ },
+ MSA = GetMSA(address),
+ Pn = 0,
+ Fn = 3
+ };
+ var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
+ return bytes;
+ }
+
+ ///
+ /// 构建抄读终端日历时钟-下发命令
+ ///
+ ///
+ public static byte[] BuildTerminalCalendarClockSendCmd(string address)
+ {
+ var reqParameter = new ReqParameter2()
+ {
+ AFN = AFN.请求实时数据,
+ FunCode = (int)CMasterStationFunCode.请求2级数据,
+ A = address,
+ Seq = new Seq()
+ {
+ TpV = TpV.附加信息域中无时间标签,
+ FIRFIN = FIRFIN.单帧,
+ CON = CON.不需要对该帧进行确认,
+ PRSEQ = 2,
+ },
+ MSA = GetMSA(address),
+ Pn = 0,
+ Fn = 2
+ };
+ var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter);
+ return bytes;
+ }
+
+ ///
+ /// 构建终端版本信息读取-下发命令
+ ///
+ ///
+ public static byte[] BuildTerminalVersionInfoReadingSendCmd(string address)
+ {
+ var reqParameter = new ReqParameter2()
+ {
+ AFN = AFN.请求终端配置,
+ FunCode = (int)CMasterStationFunCode.请求2级数据,
+ A = address,
+ Seq = new Seq()
+ {
+ TpV = TpV.附加信息域中无时间标签,
+ FIRFIN = FIRFIN.单帧,
+ CON = CON.不需要对该帧进行确认,
+ PRSEQ = 2,
+ },
+ MSA = GetMSA(address),
+ Pn = 0,
+ Fn = 1
+ };
+ var bytes = BuildSendCommandBytes(reqParameter);
+ return bytes;
+ }
+
+ ///
+ /// 集中器校时 秒、分、时、日、星期-月(3-1+4)、年
+ ///
+ ///
+ ///
+ ///
+ public static byte[] BuildConrCheckTimeSendCmd(string address, DateTime time)
+ {
+ var week = ((int)time.DayOfWeek).DecToBin().PadLeft(3, '0');
+ var monthTemp = time.Month.ToString().PadLeft(2, '0');
+ var m1 = int.Parse(monthTemp[0].ToString()).DecToBin();//十位
+ var m2 = int.Parse(monthTemp[1].ToString()).DecToBin().PadLeft(4, '0');//个位
+ var weekAndMonthHex = (week + m1 + m2).BinToHex().ToUpper();
+
+ var strTimeFm = time.ToString("ss mm HH dd $$ yy").Replace("$$", weekAndMonthHex);
+ var dataUnit = strTimeFm.Replace(" ", "").StringToPairs();
+ dataUnit.AddRange(GetPW());
+ var reqParameter = new ReqParameter2()
+ {
+ AFN = AFN.控制命令,
+ FunCode = (int)CMasterStationFunCode.请求1级数据,
+ A = address,
+ Seq = new Seq()
+ {
+ TpV = TpV.附加信息域中无时间标签,
+ FIRFIN = FIRFIN.单帧,
+ CON = CON.需要对该帧进行确认,
+ PRSEQ = 10,
+ },
+ MSA = GetMSA(address),
+ Pn = 0,
+ Fn = 31
+ };
+ var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
+ return bytes;
+ }
+
+ ///
+ /// 硬件初始化
+ ///
+ ///
+ ///
+ public static byte[] BuildConrRebootSendCmd(string address)
+ {
+ var dataUnit = GetPW();
+ var reqParameter = new ReqParameter2()
+ {
+ AFN = AFN.复位,
+ FunCode = (int)CMasterStationFunCode.复位命令,
+ A = address,
+ Seq = new Seq()
+ {
+ TpV = TpV.附加信息域中无时间标签,
+ FIRFIN = FIRFIN.单帧,
+ CON = CON.需要对该帧进行确认,
+ PRSEQ = 10,
+ },
+ MSA = GetMSA(address),
+ Pn = 0,
+ Fn = 1
+ };
+ var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
+ return bytes;
+ }
+
+ ///
+ /// 构建透明转发-下发命令
+ ///
+ /// 集中器地址
+ /// 终端通信端口 1~31
+ /// 300,600,1200,2400,4800,7200,9600,19200对应 0~7
+ /// 转发内容
+ /// 停止位
+ /// 校验方式
+ /// 数据位
+ /// 等待报文超时时间/s
+ /// 等待字节超时时间/ms
+ public static byte[] BuildTransparentForwardingSendCmd(string address, int port, string baudRate, List datas, StopBit stopBit = StopBit.Stop1, Parity parity = Parity.Even, DataBit dataBit = DataBit.D8,
+ int waitContentTimeout = 100, int waitByteTimeout = 100)
+ {
+ var baudRateValue = GetBaudreate(baudRate);
+
+ var dataUnit = BuildTransparentForwardingSendDataUnit(port, baudRateValue, datas, stopBit, parity, dataBit, waitContentTimeout, waitByteTimeout);
+ dataUnit.AddRange(GetPW());
+ var reqParameter = new ReqParameter2()
+ {
+ AFN = AFN.数据转发,
+ FunCode = (int)CMasterStationFunCode.请求2级数据,
+ A = address,
+ Seq = new Seq()
+ {
+ TpV = TpV.附加信息域中无时间标签,
+ FIRFIN = FIRFIN.单帧,
+ CON = CON.不需要对该帧进行确认,
+ PRSEQ = 0
+ },
+ MSA = GetMSA(address),
+ Pn = 0,
+ Fn = 1
+ };
+ var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
+ return bytes;
+ }
+
+ ///
+ /// 根据波特率获取值
+ ///
+ ///
+ ///
+ public static int GetBaudreate(string val)
+ {
+ var type = 0;
+ switch (val)
+ {
+ case "300": type = 0; break;
+ case "600": type = 1; break;
+ case "1200": type = 2; break;
+ case "2400": type = 3; break;
+ case "4800": type = 4; break;
+ case "7200": type = 5; break;
+ case "9600": type = 6; break;
+ case "19200": type = 7; break;
+ }
+ return type;
+ }
+
+ ///
+ /// 根据波特率获取值
+ ///
+ ///
+ ///
+ public static int GetProtocolType(string val)
+ {
+ var type = 0;
+ switch (val)
+ {
+ case "DL/T 645—2007": type = 30; break;
+ case "DL/T 645—1997": type = 1; break;
+ case "交流采样装置": type = 2; break;
+ case "串行接口连接窄带低压载波通讯": type = 31; break;
+ }
+ return type;
+ }
+
+ [Obsolete]
+ public static List AmmeterValveControl(string address, string specialnocode, string password, bool state, string modelCode = "")
+ {
+ address = address.Trim().TrimStart('0');
+ if (address.Length < 12) address = address.PadLeft(12, '0');
+ string Code = string.Empty;
+
+ if (state)
+ {
+ if (string.IsNullOrEmpty(specialnocode))
+ Code = "1B";
+ else
+ Code = specialnocode == "1B" || specialnocode == "1C" ? specialnocode : "1C";
+ }
+ else
+ Code = "1A";//跳闸
+
+ if (specialnocode == "1W")
+ {
+ if (state)
+ Code = "1A";
+ else
+ Code = "1C";
+ }
+
+ var pwdLevel = "02";
+ if (modelCode == "HL_DTSU2625" || modelCode == "DDZY9866")
+ pwdLevel = "04";
+ else if (modelCode == "DDS2705")
+ pwdLevel = "03";
+
+ if (!string.IsNullOrWhiteSpace(password) && password.Contains("|"))
+ {
+ var sp = password.Split('|');
+ pwdLevel = sp[1];
+ password = sp[0];
+ }
+
+ string strDate = DateTime.Now.AddYears(3).ToString("000012ddMMyy").StrAddSpan();
+ if (specialnocode == "1D" || modelCode == "SZBD_DDZY1225")
+ strDate = "FF FF FF FF FF FF";
+ string strP = password.StrAddSpan().StrReverseOrder();
+ string strSJY = " " + pwdLevel + " " + strP + " 01 00 00 00 " + Code + " 00 " + strDate;
+ string strLen = (strSJY.Replace(" ", "").Length / 2).ToString("X2");
+ string strReturn = "68 " + address.StrAddSpan().StrReverseOrder() + " 68 1C " + strLen + " " + strSJY.StrAddHex33() + " ";
+ string strSum = strReturn.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries).Select(i => Convert.ToInt32(i, 16)).Sum().ToString("X");
+ strReturn += strSum.Substring(strSum.Length - 2) + " 16";
+
+ return strReturn.Split(' ').ToList();
+ }
+
+
+ ///
+ /// 构建透明转发-下发数据单元
+ ///
+ /// 终端通信端口 1~31
+ /// 0~7 对应300,600,1200,2400,4800,7200,9600,19200
+ /// 转发内容
+ /// 停止位
+ /// 校验方式
+ /// 数据位
+ /// 等待报文超时时间/s
+ /// 等待字节超时时间/ms
+ ///
+ private static List BuildTransparentForwardingSendDataUnit(int port, int baudRate, List datas, StopBit stopBit = StopBit.Stop1, Parity parity = Parity.Even, DataBit dataBit = DataBit.D8,
+ int waitContentTimeout = 100, int waitByteTimeout = 100)
+ {
+ var dataUnit = new List();
+
+ var portHex = port.DecToHex().PadLeft(2, '0');
+ dataUnit.Add(portHex);
+
+ var baudRateBin = baudRate.DecToBin().PadLeft(3, '0');
+ var stopBitBin = ((int)stopBit).DecToBin();
+ var parityBin = parity != Parity.None ? $"1{((int)parity).DecToBin()}" : "00";
+ var dataBitBin = ((int)dataBit).DecToBin().PadLeft(2, '0');
+ var controlHex = $"{baudRateBin}{stopBitBin}{parityBin}{dataBitBin}".BinToHex().PadLeft(2, '0'); ;
+ dataUnit.Add(controlHex);
+
+ var waitContentTimeoutBin = $"1{waitContentTimeout.DecToBin().PadLeft(7, '0')}";
+ var waitContentTimeoutHex = waitContentTimeoutBin.BinToHex().PadLeft(2, '0');
+ var waitByteTimeoutHex = waitByteTimeout.DecToHex().PadLeft(2, '0');
+
+ dataUnit.Add(waitContentTimeoutHex);
+ dataUnit.Add(waitByteTimeoutHex);
+
+ var countHex = datas.Count.DecToHex().PadLeft(4, '0');
+ var countHexPairs = countHex.StringToPairs();
+ countHexPairs.Reverse();
+ dataUnit.AddRange(countHexPairs);
+
+ dataUnit.AddRange(datas);
+
+ return dataUnit;
+ }
+
+ ///
+ /// 构建下发命令
+ ///
+ ///
+ ///
+ ///
+ public static byte[] BuildSendCommandBytes(ReqParameter reqParameter, List? dataUnit = null)
+ {
+ var cmdStrList = new List();
+ var userDatas = BuildUserData(reqParameter, dataUnit);
+ var hearders = BuildHeaders(userDatas.Count);
+ var cs = GetCS(userDatas);
+ cmdStrList.AddRange(hearders);
+ cmdStrList.AddRange(userDatas);
+ cmdStrList.Add(cs);
+ cmdStrList.Add(endStr);
+ Console.WriteLine(string.Join(" ", cmdStrList));
+ var bytes = cmdStrList.Select(x => Convert.ToByte(x, 16)).ToArray();
+ return bytes;
+ }
+
+ ///
+ /// 构建电表参数设置-下发数据单元
+ ///
+ ///
+ ///
+ private static List BuildAmmeterParameterSendDataUnit(List meterParameters)
+ {
+ var hexDatas = new List();
+
+ var countHex = meterParameters.Count().DecToHex().PadLeft(4, '0');
+ hexDatas.Add(countHex);
+
+ for (int i = 0; i <= meterParameters.Count - 1; i++)
+ {
+ var meter = meterParameters[i];
+
+ //var indexHex = (i + 1).DecToHex().PadLeft(4, '0');
+ var indexHex = meter.SerialNumber.DecToHex().PadLeft(4, '0');
+ hexDatas.Add(indexHex);
+
+ var pnHex = meter.Pn.DecToHex().PadLeft(4, '0');
+ hexDatas.Add(pnHex);
+
+ var baudRateBin = meter.BaudRate.DecToBin().PadLeft(3, '0');
+ var portBin = meter.Port.DecToBin().PadLeft(5, '0');
+ var baudRateAndPortHex = $"{baudRateBin}{portBin}".BinToHex().PadLeft(2, '0');
+ hexDatas.Add(baudRateAndPortHex);
+
+ var protocolTypeHex = ((int)meter.ProtocolType).DecToHex().PadLeft(2, '0');
+ hexDatas.Add(protocolTypeHex);
+
+ hexDatas.Add(meter.Address);
+
+ hexDatas.Add(meter.Password.PadLeft(12, '0'));
+
+ var rateNumberBin = $"0000{meter.RateNumber.DecToBin().PadLeft(4, '0')}";
+ var rateNumberHex = rateNumberBin.BinToHex().PadLeft(2, '0');
+ hexDatas.Add(rateNumberHex);
+
+ var intBitNumberBin = (meter.IntegerBitNumber - 4).DecToBin().PadLeft(2, '0');
+ var decBitNumberBin = (meter.DecimalBitNumber - 1).DecToBin().PadLeft(2, '0');
+ var intAndDecBitNumberBin = $"0000{intBitNumberBin}{decBitNumberBin}";
+ var intAndDecBitNumberHex = intAndDecBitNumberBin.BinToHex().PadLeft(2, '0');
+ hexDatas.Add(intAndDecBitNumberHex);
+
+ hexDatas.Add(meter.CollectorAddress.PadLeft(12, '0'));
+
+ var userCategoryNumber = 0;//meter.UserCategoryNumber
+ var userSubclassNumber = 0;//meter.UserSubclassNumber
+ if (meter.ProtocolType == 32) userCategoryNumber = 1;
+ else if (meter.ProtocolType == 45) { userCategoryNumber = 1; userSubclassNumber = 9; }
+
+ var userCategoryNumberBin = userCategoryNumber.DecToBin().PadLeft(4, '0');
+ var userSubclassNumberBin = userSubclassNumber.DecToBin().PadLeft(4, '0');
+ var userNumberHex = $"{userCategoryNumberBin}{userSubclassNumberBin}".BinToHex().PadLeft(2, '0');
+ hexDatas.Add(userNumberHex);
+ }
+
+ //高位在前,低位在后
+ var datas = new List();
+ foreach (var hexData in hexDatas)
+ {
+ if (hexData.Length == 2)
+ datas.Add(hexData);
+ else
+ {
+ var lst = hexData.StringToPairs();
+ lst.Reverse();
+ datas.AddRange(lst);
+ }
+ }
+ datas.AddRange(GetPW());
+ return datas;
+ }
+
+ ///
+ /// 构建水表参数设置-下发数据单元
+ ///
+ ///
+ ///
+ private static List BuildWaterMeterParameterSendDataUnit(List meterParameters)
+ {
+ var hexDatas = new List();
+
+ var countHex = meterParameters.Count().DecToHex().PadLeft(4, '0');
+ hexDatas.Add(countHex);
+
+ for (int i = 0; i <= meterParameters.Count - 1; i++)
+ {
+
+ var meter = meterParameters[i];
+ var protocolType = (int)meter.ProtocolType;
+
+ var currentProtocolType = protocolType;
+ if (protocolType == 43)
+ currentProtocolType = 1;
+ else if (protocolType > 32) currentProtocolType = 32;
+
+ //TODO:无线水表 小数位
+ if (currentProtocolType == 32 && meter.Address.Substring(0, 2) != "00")
+ {
+ var ejz = meter.Address.Substring(0, 2).HexToBin().PadLeft(8, '0');
+ var xs = ejz.Substring(6, 2).BinToDec();
+ var zs = ejz.Substring(0, 6).BinToDec();
+ //userData.Add(new QGDW3671UserData() { Name = "整数位无线水表", Value = zs });
+ //userData.Add(new QGDW3671UserData() { Name = "小数位无线水表", Value = xs });
+ }
+
+ var userCategoryNumber = meter.UserCategoryNumber;
+ var userSubclassNumber = meter.UserSubclassNumber;
+
+ if (protocolType == 32)
+ userCategoryNumber = 1;
+ else if (protocolType == 45)
+ {
+ userCategoryNumber = 1;
+ userSubclassNumber = 9;
+ }
+ else if (protocolType == 1)
+ userSubclassNumber = 1;
+
+ var indexHex = (i + 1).DecToHex().PadLeft(4, '0');
+ hexDatas.Add(indexHex);
+
+ var pnHex = meter.Pn.DecToHex().PadLeft(4, '0');
+ hexDatas.Add(pnHex);
+
+ var baudRateBin = meter.BaudRate.DecToBin().PadLeft(3, '0');
+ var portBin = meter.Port.DecToBin().PadLeft(5, '0');
+ var baudRateAndPortHex = $"{baudRateBin}{portBin}".BinToHex().PadLeft(2, '0');
+ hexDatas.Add(baudRateAndPortHex);
+
+ var protocolTypeHex = currentProtocolType.DecToHex().PadLeft(2, '0');
+ hexDatas.Add(protocolTypeHex);
+
+ hexDatas.Add(meter.Address);
+
+ hexDatas.Add(meter.Password.PadLeft(12, '0'));
+
+ var rateNumberBin = $"0000{meter.RateNumber.DecToBin().PadLeft(4, '0')}";
+ var rateNumberHex = rateNumberBin.BinToHex().PadLeft(2, '0');
+ hexDatas.Add(rateNumberHex);
+
+ var intBitNumberBin = meter.IntegerBitNumber.DecToBin().PadLeft(2, '0');
+ var decBitNumberBin = meter.DecimalBitNumber.DecToBin().PadLeft(2, '0');
+ var intAndDecBitNumberBin = $"0000{intBitNumberBin}{decBitNumberBin}";
+ var intAndDecBitNumberHex = intAndDecBitNumberBin.BinToHex().PadLeft(2, '0');
+ hexDatas.Add(intAndDecBitNumberHex);
+
+ hexDatas.Add(meter.CollectorAddress.PadLeft(12, '0'));
+
+ var userCategoryNumberBin = userCategoryNumber.DecToBin().PadLeft(4, '0');
+ var userSubclassNumberBin = userSubclassNumber.DecToBin().PadLeft(4, '0');
+ var userNumberHex = $"{userCategoryNumberBin}{userSubclassNumberBin}".BinToHex().PadLeft(2, '0');
+ hexDatas.Add(userNumberHex);
+ }
+
+ //高位在前,低位在后
+ var datas = new List();
+ foreach (var hexData in hexDatas)
+ {
+ if (hexData.Length == 2)
+ datas.Add(hexData);
+ else
+ {
+ var lst = hexData.StringToPairs();
+ lst.Reverse();
+ datas.AddRange(lst);
+ }
+ }
+ datas.AddRange(GetPW());
+ return datas;
+ }
+
+
+ //AUX=消息认证码字段(PW,16个字节)
+ private static List GetPW()
+ {
+ var str = "00";
+ var pWList = Enumerable.Repeat(str, pWLen).ToList();
+ return pWList;
+ }
+
+
+ ///
+ /// 帧校验和
+ ///
+ /// 用户数据区
+ ///
+ private static string GetCS(List userData)
+ {
+ byte sum = 0;
+ foreach (var d in userData)
+ {
+ var b = Convert.ToByte(d, 16);
+ sum += b;
+ }
+ return sum.ToString("X2");
+ }
+
+ ///
+ /// 用户数据区
+ ///
+ ///
+ ///
+ private static List BuildUserData(ReqParameter reqParameter, List? dataUnit)
+ {
+ var c = BuildC(reqParameter.FunCode, reqParameter.PRM);
+ var a = BuildAList(reqParameter.A, reqParameter.MSA);
+
+ var linkUserData = BuildLinkUserData(reqParameter.AFN, reqParameter.Seq,
+ ((ReqParameter2)reqParameter).Pn, ((ReqParameter2)reqParameter).Fn, dataUnit);
+
+ var list = new List() { c };
+ list.AddRange(a);
+ list.AddRange(linkUserData);
+ return list;
+ }
+
+ ///
+ /// 固定长度的报文头 起始字符+长度+长度+起始字符
+ ///
+ ///
+ ///
+ private static List BuildHeaders(int length)
+ {
+ var headers = new List();
+ headers.Add(startStr);
+ var l = BuildLength(length);
+ headers.AddRange(l);
+ headers.AddRange(l);
+ headers.Add(startStr);
+ return headers;
+ }
+
+ ///
+ /// 长度 2字节 [用户数据区长度]
+ ///
+ ///
+ private static List BuildLength(int length1)
+ {
+ var binaryLen = length1.DecToBin();
+ var protocolIdentification = Enum.Format(typeof(ProtocolIdentification),
+ ProtocolIdentification.本规约使用, "d").PadLeft(2, '0');
+ var lenStr = $"{binaryLen}{protocolIdentification}";
+ var hexLen = lenStr.BinToHex();
+ hexLen = hexLen.PadLeft(4, '0');
+ var list = hexLen.StringToPairs();
+ list.Reverse();
+ return list;
+ }
+
+ ///
+ /// 控制域
+ ///
+ /// 功能码
+ ///
+ ///
+ ///
+ private static string BuildC(int funCode, PRM pRM, int fcb = 0, FCV fcv = FCV.FCB位无效)
+ {
+ var cMasterStationFunCodeHex = funCode.DecToBin();
+ cMasterStationFunCodeHex = cMasterStationFunCodeHex.ToString().PadLeft(4, '0');
+ var strC = $"{(int)DIR.主站下行报文}{(int)pRM}{fcb}{(int)fcv}{cMasterStationFunCodeHex}";
+ var hexC = strC.BinToHex().PadLeft(2, '0');
+ return hexC;
+ }
+
+
+ ///
+ /// 地址域 3220 09872
+ ///
+ /// 行政区划码 BCD码 3220=2032
+ /// 逻辑地址 BIN 09872=2690=>9026
+ /// 主站地址 BIN 0~127
+ ///
+ private static List BuildAList(string a, int mSA)
+ {
+ var list = new List();
+
+ var a1 = a.Substring(0, 4);
+ var a1Pairs = a1.StringToPairs();
+ a1Pairs.Reverse();
+ list.AddRange(a1Pairs);
+
+ var a2 = Convert.ToInt32(a.Substring(4));
+ var decA2 = a2.DecToHex();
+ var a2Pairs = decA2.PadLeft(4, '0').StringToPairs();
+ a2Pairs.Reverse();
+ list.AddRange(a2Pairs);
+
+ //TODO:主站地址和组地址标志
+ var a3Bin = $"{mSA.DecToBin().PadLeft(7, '0')}0";
+ list.Add(a3Bin.BinToHex().PadLeft(2, '0'));
+
+ return list;
+ }
+
+ private static List BuildLinkUserData(AFN aFN, Seq seq, int pn, int fn, List? dataUnit)
+ {
+ var aFNValue = ((int)aFN).DecToHex().PadLeft(2, '0');
+ var sEQ = BuildSEQ(seq.TpV, seq.FIRFIN, seq.CON, seq.PRSEQ);
+ var dA = BuildDA(pn);
+ var dT = BuildDT(fn);
+ var list = new List() { aFNValue, sEQ };
+ list.AddRange(dA);
+ list.AddRange(dT);
+
+ if (dataUnit != null)
+ {
+ list.AddRange(dataUnit);
+ }
+ //list.AddRange(GetDataUnit(aFN,seq));
+
+ if (seq.TpV == TpV.附加信息域中带时间标签)
+ list.AddRange(BuildTp("00"));
+
+ return list;
+ }
+
+ ///
+ /// 帧序列域
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static string BuildSEQ(TpV tpV, FIRFIN fIRFIN, CON cON, int pRSEQ)
+ {
+ var tpVValue = Enum.Format(typeof(TpV),
+ tpV, "d");
+ var fIRFINValue = Enum.Format(typeof(FIRFIN),
+ fIRFIN, "d");
+ var cONValue = (int)cON;
+ var sEQBin = $"{tpVValue}{fIRFINValue}{cONValue}{pRSEQ.DecToBin().PadLeft(4, '0')}";
+ var hexSEQ = sEQBin.BinToHex().PadLeft(2, '0');
+ return hexSEQ;
+ }
+
+ ///
+ /// 信息点标识
+ ///
+ /// 计量点
+ ///
+ private static List BuildDA(int pn)
+ {
+ if (pn == 0)
+ return new List() { "00", "00" };
+ var dA2 = (pn - 1) / 8 + 1;//信息点组从1开始 第几组
+ var dA1 = pn - (dA2 - 1) * 8;//pn % 8
+ var dA1Hex = "1".PadRight(dA1, '0').BinToHex();//对位信息 第几位 二进制有效位
+ var dA2Hex = dA2.DecToHex();
+ return new List() { dA1Hex.PadLeft(2, '0'), dA2Hex.PadLeft(2, '0') };
+
+ }
+
+ ///
+ /// 数据单元标识
+ ///
+ ///
+ ///
+ private static List BuildDT(int fn)
+ {
+ var dT2 = (fn - 1) / 8;//从零开始 第几组
+ var dT1 = fn - dT2 * 8;
+ var dT1Hex = "1".PadRight(dT1, '0').BinToHex();//对位信息 第几位 二进制有效位
+ var dT2Hex = dT2.DecToHex();
+ return new List() { dT1Hex.PadLeft(2, '0'), dT2Hex.PadLeft(2, '0') };
+ }
+
+ ///
+ /// 时间标签
+ ///
+ /// 启动帧帧序号计数器PFC 1字节
+ /// 允许发送传输延时时间 min 1字节
+ ///
+ private static List BuildTp(string pFC = "00", int delayTime = 0)
+ {
+ var now = DateTime.Now; // 获取当前时间
+ var seconds = now.Second.ToString().PadLeft(2, '0'); // 获取当前秒数
+ var minutes = now.Minute.ToString().PadLeft(2, '0'); // 获取当前分钟数
+ var hours = now.Hour.ToString().PadLeft(2, '0'); // 获取当前小时数
+ var day = now.Day.ToString().PadLeft(2, '0'); // 获取当前日期的日数
+ return new List() { pFC, seconds, minutes, hours, day, delayTime.ToString().PadLeft(2, '0') };
+ }
+
+ #endregion
+
+ }
+}
diff --git a/src/JiShe.CollectBus.Common/BuildSendDatas/Build645SendData.cs b/src/JiShe.CollectBus.Common/BuildSendDatas/Build645SendData.cs
new file mode 100644
index 0000000..d3df6cb
--- /dev/null
+++ b/src/JiShe.CollectBus.Common/BuildSendDatas/Build645SendData.cs
@@ -0,0 +1,755 @@
+using JiShe.CollectBus.Common.Enums;
+using JiShe.CollectBus.Common.Extensions;
+using JiShe.CollectBus.Common.Models;
+using System;
+using System.Collections.Generic;
+using static System.Runtime.InteropServices.JavaScript.JSType;
+
+namespace JiShe.CollectBus.Common.BuildSendDatas
+{
+ public static class Build645SendData
+ {
+ //起始字符
+ private const string startStr = "68";
+ //结束字符
+ private const string endStr = "16";
+
+ #region 645下行命令
+
+
+ ///
+ /// 构建电表阀控下发数据单元
+ ///
+ /// 电表地址
+ /// 特殊控制码
+ /// 密码
+ /// 是否为开阀
+ /// 型号码
+ ///
+ public static List BuildAmmeterValveControlSendDataUnit(string ammeterAddress, string specialControlCode, string password, bool state, string modelCode = "")
+ {
+ var code = string.Empty;
+
+ if (state)
+ {
+ if (string.IsNullOrEmpty(specialControlCode))
+ code = "1B";
+ else
+ code = specialControlCode == "1B" || specialControlCode == "1C" ? specialControlCode : "1C";
+ }
+ else
+ code = "1A";//跳闸
+
+ if (specialControlCode == "1W")
+ {
+ if (state)
+ code = "1A";
+ else
+ code = "1C";
+ }
+
+ var pwdLevel = "02";
+ if (modelCode == "HL_DTSU2625" || modelCode == "DDZY9866")
+ pwdLevel = "04";
+ else if (modelCode == "DDS2705")
+ pwdLevel = "03"; //不带安全认证密级
+
+ if (!string.IsNullOrWhiteSpace(password) && password.Contains("|"))
+ {
+ var sp = password.Split('|');
+ pwdLevel = sp[1];
+ password = sp[0];
+ }
+
+ var strDate = DateTime.Now.AddYears(3).ToString("000012ddMMyy").StrAddSpan();//命令有效截止时间
+ if (specialControlCode == "1D" || modelCode == "SZBD_DDZY1225")
+ strDate = "FF FF FF FF FF FF";
+ var strP = password.StrAddSpan().StrReverseOrder();
+ var strSJY = " " + pwdLevel + " " + strP + " 01 00 00 00 " + code + " 00 " + strDate;
+ var dataUnit = strSJY.Replace(" ", "").StringToPairs();
+ var dataList = Build645SendCommand(ammeterAddress, "1C", dataUnit);
+ return dataList;
+
+ //string strLen = (strSJY.Replace(" ", "").Length / 2).ToString("X2");
+ //string strReturn = "68 " + address.StrAddSpan().StrReverseOrder() + " 68 1C " + strLen + " " + strSJY.StrAddHex33() + " ";
+ //string strSum = strReturn.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries).Select(i => Convert.ToInt32(i, 16)).Sum().ToString("X");
+ //strReturn += strSum.Substring(strSum.Length - 2) + " 16";
+ //return strReturn.Split(' ').ToList();
+ }
+
+ ///
+ /// 构建电表保电下发数据单元
+ ///
+ /// 电表地址
+ ///
+ /// true 保电 false 保电解除
+ /// 型号码
+ ///
+ public static List BuildAmmeterLockSendDataUnit(string ammeterAddress, string password, bool state, string modelCode = "")
+ {
+ var code = state ? "3A" : "3B";
+
+ var strDate = (code + DateTime.Now.AddDays(1).ToString("00000012ddMMyy")).StrAddSpan();
+
+ if (modelCode == "SZBD_DDZY1225")
+ strDate = $"{code} 00 FF FF FF FF FF FF";
+
+ var strP = password.StrAddSpan().StrReverseOrder();
+ var strSJY = " 02 " + strP + " 01 00 00 00 " + strDate;
+
+ var dataUnit = strSJY.Replace(" ", "").StringToPairs();
+ var dataList = Build645SendCommand(ammeterAddress, "1C", dataUnit);
+ return dataList;
+ }
+
+ ///
+ /// 构建电表认证下发数据单元
+ ///
+ /// 电表地址
+ ///
+ ///
+ ///
+ public static List BuildAmmeterIdentitySendDataUnit(string ammeterAddress, string ramDon, string maco)
+ {
+ var codeList = "070004FF".StringToPairs();
+ codeList.Reverse();
+
+ var ramDonList = ramDon.StringToPairs();
+ ramDonList.Reverse();
+
+ var macoList = maco.StringToPairs();
+ macoList.Reverse();
+
+ var dataUnit = new List();
+ dataUnit.AddRange(codeList);
+ dataUnit.AddRange(ramDonList);
+ dataUnit.AddRange(macoList);
+ var dataList = Build645SendCommand(ammeterAddress, "03", dataUnit);
+ return dataList;
+ }
+
+ ///
+ /// 构建电表清零下发数据单元
+ ///
+ /// 电表地址
+ ///
+ ///
+ public static List BuildAmmeterClearSendDataUnit(string ammeterAddress, string password)
+ {
+ var strP = password.StrAddSpan().StrReverseOrder();
+ var strSJY = " 02 " + strP + " 01 00 00 00 ";
+ var dataUnit = strSJY.Replace(" ", "").StringToPairs();
+ var dataList = Build645SendCommand(ammeterAddress, "1A", dataUnit);
+ return dataList;
+ }
+
+ ///
+ /// 透明转发 表计校时/广播校时 F10-104
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 类型 0:日期部分指令,1,时间部分指令
+ ///
+ ///
+ ///
+ public static List BuildAmmeterCorrectionTimeSendDataUnit(string ammeterAddress,string password, string dataMark, int cmdType, string s_operator = "00000001")
+ {
+ List dataUnit = new List();
+
+ if (string.IsNullOrWhiteSpace(password))
+ password = "000000";
+ if (password?.Length != 6)
+ password = password.PadLeft(6, '0');
+ if (string.IsNullOrWhiteSpace(s_operator) || s_operator?.Length != 8)
+ throw new ArgumentNullException("电表操作人员格式不能为空或长度不等6位");
+
+ //数据标识 DIODI1DI2DI3+PAP0P1P2+C0C1C2C3+DATA
+ var dataMarks = dataMark.Split(' ').ToList();
+ dataMarks.Reverse();
+ dataUnit.AddRange(dataMarks);//数据标识
+
+ //密码权限 02明文 PAP0P1P2
+ var passsList = password.StringToPairs(true);
+ dataUnit.Add("02");//--密码权限 02明文
+ foreach (var item in passsList)
+ {
+ dataUnit.Add(item);
+ }
+ //操作人员 C0C1C2C3
+ var opers = s_operator.StringToPairs(true);
+ foreach (var item in opers)
+ {
+ dataUnit.Add(item);
+ }
+ //数据体 DATA
+ List datas = null;
+ switch (cmdType)
+ {
+ case 0:
+ datas = Date_MeterTiming();
+ break;
+ case 1:
+ datas = Time_MeterTiming();
+ break;
+ }
+ if (datas == null)
+ throw new Exception($"透明转发 表计校时/广播校时生成的数据内容为空");
+ datas.Reverse();
+ dataUnit.AddRange(datas);
+
+ var dataList = Build645SendCommand(ammeterAddress, "14", dataUnit);
+ return dataList;
+ }
+
+ ///
+ /// 设置尖峰平谷时段 F10-103
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static List BuildAmmeterTimeSetSendDataUnit(string ammeterAddress,string password, string dataMark,string data, string s_operator= "00000001")
+ {
+ List dataUnit = BuildAmmeterTimeSetDataUnit(password, dataMark, data);
+
+ var dataList = Build645SendCommand(ammeterAddress, "14", dataUnit);
+ return dataList;
+ }
+ //工具生成指令 F10 103
+ //internal override List GenerateContent(SetJFPGToolCmdIssueEntity transpond)
+ //{
+ // //TODO:替换表计地址
+ // var meterAddress = string.Join("", transpond.MeterAddress.Split(2, true)).PadRight(12, '0').Split(2, false);
+ // var cmdArr = transpond.Cmd.Replace(" ", "").Split(2, false);
+ // cmdArr.RemoveRange(1, 6);
+ // cmdArr.InsertRange(1, meterAddress);
+ // //TODO:替换校验码
+ // var csSum = GetCheckSumsHexString(string.Join("", cmdArr.Take(cmdArr.Count - 2)).StringToHexByte());
+ // cmdArr.RemoveRange(cmdArr.Count - 2, 2);
+ // cmdArr.Add(csSum);
+
+ // cmdArr.Add("16");
+
+ // return cmdArr;
+ //}
+
+ public static List BuildAmmeterGenerateBCCommand()
+ {
+ return null;
+ }
+
+
+ ///
+ /// 构建电表读取下发数据单元
+ ///
+ /// 电表地址
+ /// 功率读取 余额读取
+ /// 数据标识
+ ///
+ public static List BuildAmmeterReadDataUnit(string ammeterAddress, CmdType cmdType, string dataId = "")
+ {
+ var dn = "";
+ if (string.IsNullOrWhiteSpace(dataId))
+ {
+ if (cmdType == CmdType.PowerRead) dn = "04090B01";
+ else if (cmdType == CmdType.BalanceRead) dn = "00900200";
+ else if (cmdType == CmdType.CurrentRead) dn = "04090801";
+ else if (cmdType == CmdType.WsPowerDown) dn = "0E300103";
+ else if (cmdType == CmdType.ReadMeterStatus) dn = "04000503";
+ else if (cmdType == CmdType.TimeSet) dn = "04010001";//主用第一套时段数据
+ else if (cmdType == CmdType.ReadTimeSetMonth) dn = "04010000";//主用时区数据
+ else if (cmdType == CmdType.ReadTimeSetNum) dn = "04000202";//日时段数
+ }
+ else
+ dn = dataId;
+
+ var dataUnit = dn.StringToPairs(true);
+
+ var dataList = Build645SendCommand(ammeterAddress, "11", dataUnit);
+ return dataList;
+ }
+
+ ///
+ /// 构建电表修正时间下发命令-PMAC9523
+ ///
+ ///
+ ///
+ public static List BuildPMAC9523AmmeterCorrectionTimeSendDataUnit(string ammeterAddress)
+ {
+ var now = DateTime.Now;
+ var year = (now.Year - 2000).ToString("X2").PadLeft(4, '0');
+ var month = now.Month.ToString("X2").PadLeft(4, '0');
+ var day = now.Day.ToString("X2").PadLeft(4, '0');
+ var hour = now.Hour.ToString("X2").PadLeft(4, '0');
+ var minute = now.Minute.ToString("X2").PadLeft(4, '0');
+ var second = now.Second.ToString("X2").PadLeft(4, '0');
+ var adress = int.Parse(ammeterAddress.Substring(ammeterAddress.Length - 3)).DecToHex().PadLeft(2, '0');
+ var fm = new List() { adress, "10", "23", "35", "00", "06", "0C" };
+ fm.AddRange($"{second}{minute}{hour}{day}{month}{year}".StringToPairs());
+
+ var bts = fm.Select(s => s.HexToDec()).Select(s => byte.Parse(s.ToString())).ToArray();
+ var getCrc = HexStringExtensions.GetCRC16(bts, true).Select(s => int.Parse(s.ToString()).DecToHex().PadLeft(2, '0'));//long.Parse ?
+ fm.AddRange(getCrc);
+
+ return fm;
+ }
+
+ ///
+ /// 构建电表修正时间下发命令-DTSU193
+ ///
+ ///
+ ///
+ public static List BuildDTSU193AmmeterCorrectionTimeSendDataUnit(string ammeterAddress)
+ {
+ var now = DateTime.Now;
+ var year = now.Year.ToString().Substring(2);
+ var month = now.Month.ToString().PadLeft(2, '0');
+ var day = now.Day.ToString().PadLeft(2, '0');
+ var week = ((int)now.DayOfWeek).ToString().PadLeft(2, '0');
+ var hour = now.Hour.ToString().PadLeft(2, '0');
+ var minute = now.Minute.ToString().PadLeft(2, '0');
+ var second = now.Second.ToString().PadLeft(2, '0');
+ var fm = GenerateCTCommand(ammeterAddress, $"{year}{month}{day}{week}{hour}{minute}{second}");
+ return fm;
+ }
+
+ ///
+ /// 构建电表修正时间下发命令
+ ///
+ ///
+ ///
+ ///
+ public static List> BuildAmmeterCorrectionTimeSendDataUnit(string ammeterAddress,string password)
+ {
+ var listDataUnit = new List>();
+
+ var now = DateTime.Now;
+ var year = now.Year.ToString().PadLeft(4, '0');
+ var month = now.Month.ToString().PadLeft(2, '0');
+ var day = now.Day.ToString().PadLeft(2, '0');
+ var week = ((int)now.DayOfWeek).ToString().PadLeft(2, '0');
+ var hour = now.Hour.ToString().PadLeft(2, '0');
+ var minute = now.Minute.ToString().PadLeft(2, '0');
+ var second = now.Second.ToString().PadLeft(2, '0');
+
+ //组装数据域
+ List dataList = new List();
+ var dataMarkList = "04000101".StringToPairs(true);
+ dataList.AddRange(dataMarkList);
+ dataList.Add("02");
+ if (string.IsNullOrEmpty(password))
+ password = "000000";
+ var passwordList = password.StringToPairs(true);
+ dataList.AddRange(passwordList);
+ dataList.AddRange("00000000".StringToPairs(true));
+ dataList.AddRange($"{year}{month}{day}{week}".StringToPairs(true));
+
+ var fm = Build645SendCommand(ammeterAddress, "14", dataList);
+ listDataUnit.Add(fm);
+
+ dataList = new List();
+ dataMarkList = "04000102".StringToPairs(true);
+ dataList.AddRange(dataMarkList);
+ dataList.Add("02");
+ dataList.AddRange(passwordList);
+ dataList.AddRange("00000000".StringToPairs(true));
+ dataList.AddRange($"{hour}{minute}{second}".StringToPairs(true));
+ var fm2 = Build645SendCommand(ammeterAddress, "14", dataList);
+ listDataUnit.Add(fm2);
+
+ return listDataUnit;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static List BuildPMAC9523ReadMeterTimeSetSendDataUnit(string ammeterAddress)
+ {
+ //LogHelper.LogStr("ReadMeterTimeSet", $"表编号[{meterInfo.meter_address}]进入PMAC9523时段设置");
+ var adress = int.Parse(ammeterAddress.Substring(ammeterAddress.Length - 3)).DecToHex().PadLeft(2, '0');
+ var fm = new List() { adress, "03", "55", "F9", "00", "28" };
+ var bts = fm.Select(s => s.HexToDec()).Select(s => byte.Parse(s.ToString())).ToArray();
+ var getCrc = HexStringExtensions.GetCRC16(bts, true)
+ .Select(s => int.Parse(s.ToString()).DecToHex().PadLeft(2, '0'));
+ fm.AddRange(getCrc);
+ return fm;
+
+ }
+
+ ///
+ /// 构建电表表号读取下发命令
+ ///
+ /// 电表地址
+ ///
+ public static List BuildAmmeterReadNumSendCmd(string ammeterAddress)
+ {
+ var dataUnit = "04000402".StringToPairs(true);
+ return Build645SendCommand(ammeterAddress, "11", dataUnit);
+ }
+
+ public static List> BuildPMAC9523AmmeterSetTimeSetSendDataUnit(string ammeterAddress, List data)
+ {
+ List> dataUnitList = new List>();
+ var adress = int.Parse(ammeterAddress.Substring(ammeterAddress.Length - 3)).DecToHex().PadLeft(2, '0');
+ //第一步启用复费率编程:寄存器64503,写数据01启动编程
+ var fm = new List() { adress, "10", "FB", "F6", "00", "01", "02", "00", "01" };
+ var bts = fm.Select(s => s.HexToDec()).Select(s => byte.Parse(s.ToString())).ToArray();
+ var getCrc = HexStringExtensions.GetCRC16(bts, true).Select(s => int.Parse(s.ToString()).DecToHex().PadLeft(2, '0'));
+ fm.AddRange(getCrc);
+ dataUnitList.Add(fm);
+
+ //第二步写复费率模式:寄存器22002,写数据01固定一套费率
+ var fm2 = new List() { adress, "10", "55", "F1", "00", "01", "02", "00", "01" };
+ var bts2 = fm2.Select(s => s.HexToDec()).Select(s => byte.Parse(s.ToString())).ToArray();
+ var getCrc2 = HexStringExtensions.GetCRC16(bts2, true).Select(s => int.Parse(s.ToString()).DecToHex().PadLeft(2, '0'));
+ fm2.AddRange(getCrc2);
+ dataUnitList.Add(fm2);
+
+ //第三步写时段参数:寄存器22010开始,后续多少个寄存器根据时段内容来。
+ var timeSetDetailList = data.FirstOrDefault().Data;
+ var fm3 = new List() { adress, "10", "55", "F9", "00" };
+ //寄存器个数
+ var timeNum = timeSetDetailList.Sum(o => o.Times.Count);
+ fm3.Add($"{timeNum * 2 + 1:X2}");
+ //数据长度
+ fm3.Add($"{(timeNum * 2 + 1) * 2:X2}");
+
+ //时段个数
+ fm3.Add("00");
+ fm3.Add($"{timeNum:X2}");
+ Dictionary setDic = new Dictionary();
+ int rate = 0;
+ foreach (var item in timeSetDetailList)
+ {
+ int.TryParse(item.Rate, out rate);
+ foreach (var itemItem in item.Times)
+ {
+ fm3.Add("00");
+ fm3.Add($"{rate - 1:X2}");
+ fm3.Add("00");
+ fm3.Add($"{itemItem.StartTime.TakeTimeToInt():X2}");
+ }
+ }
+ var bts3 = fm3.Select(s => s.HexToDec()).Select(s => byte.Parse(s.ToString())).ToArray();
+ var getCrc3 = HexStringExtensions.GetCRC16(bts3, true).Select(s => int.Parse(s.ToString()).DecToHex().PadLeft(2, '0'));
+ fm3.AddRange(getCrc3);
+ dataUnitList.Add(fm3);
+
+ return dataUnitList;
+ }
+
+ ///
+ /// F1:透明转发 读取通信地址 04 00 04 01 NNNNNNNNNNNN 6 通信地址
+ ///
+ ///
+ ///
+ public static List BuildReadMeterAddressSendDataUnit(string ammeterAddress)
+ {
+ var dataMark = new List { "04", "00", "04", "01" };
+ //content.AddRange(string.Join("", transpond.MeterAddress.Split(2, true)).PadRight(12, '0').Split(2, false));
+ dataMark.Reverse();
+ return Build645SendCommand(ammeterAddress, "11", dataMark);
+ }
+
+ ///
+ /// 构建645协议下发命令
+ ///
+ /// 电表地址
+ /// 控制码
+ /// 数据域 发送方按字节进行加33处理,接收方按字节减33
+ ///
+ public static List Build645SendCommand(string ammeterAddress, string controlCode, List? dataUnit)
+ {
+ var cmdStrList = new List();
+ cmdStrList.Add(startStr);
+
+ ammeterAddress = ammeterAddress.PadLeft(12, '0');
+ var addressList = ammeterAddress.StringToPairs();
+ addressList.Reverse();
+ cmdStrList.AddRange(addressList);
+
+ cmdStrList.Add(startStr);
+
+ cmdStrList.Add(controlCode);
+
+ var len = dataUnit != null ? dataUnit.Count.DecToHex().PadLeft(2, '0') : "00";
+ cmdStrList.Add(len);
+
+ if (dataUnit != null)
+ {
+ cmdStrList.AddRange(dataUnit.AddHex33());
+ }
+
+ var strSum = cmdStrList.Select(i => Convert.ToInt32(i, 16)).Sum().ToString("X");
+ strSum = strSum.Substring(strSum.Length - 2);
+ cmdStrList.Add(strSum);
+ cmdStrList.Add(endStr);
+
+ return cmdStrList;
+ }
+
+ ///
+ /// 威胜表的超功率(第一路恶性负载超功率判断阀值)
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static List? AssembleWsSupperPower(string ammeterAddress, string password, string dataMark, decimal power)
+ {
+ power = Math.Round(power, 4);
+ if (power > (decimal)99.9999) return null;
+ var strPower = power < 10 ? $"0{power}" : power.ToString();
+ var pStr = strPower.Replace(".", "").PadRight(6, '0');
+ var data = new string[] { pStr[4] + "" + pStr[5], pStr[2] + "" + pStr[3], pStr[0] + "" + pStr[1] };
+ return AssembleWrite(ammeterAddress, password, dataMark, data);
+ }
+ ///
+ /// 威胜表的超功率(超功率开关)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static List AssembleWsOnSupperPower(string ammeterAddress, string password, bool isOn = true)
+ {
+ var data = new string[] { (isOn ? "01" : "00") };
+ return AssembleWrite(ammeterAddress, password, "0E400001", data);
+ }
+ ///
+ /// 威胜表的超功率(第一路恶性负载绝对功率判断阈值)
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static List? AssembleWsAbsolutePowerSetting(string ammeterAddress, string password, string dataMark, decimal power)
+ {
+ power = Math.Round(power, 4);
+ if (power > (decimal)99.9999) return null;
+ var strPower = power < 10 ? $"0{power}" : power.ToString();
+ var pStr = strPower.Replace(".", "").PadRight(6, '0');
+ var data = new string[] { pStr[4] + "" + pStr[5], pStr[2] + "" + pStr[3], pStr[0] + "" + pStr[1] };
+ return AssembleWrite(ammeterAddress, password, dataMark, data);
+ }
+ ///
+ /// 威胜表的超功率(第一路恶性负载功率因数判断阀值)
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static List? AssembleWsPowerFactor(string ammeterAddress, string password, string dataMark, decimal factor)
+ {
+ factor = Math.Round(factor, 3);
+ if (factor >= (decimal)1.0 || factor <= 0) return null;
+ var strFactor = factor.ToString();
+ var pStr = strFactor.Replace(".", "").PadRight(4, '0');
+ var data = new string[] { pStr[2] + "" + pStr[3], pStr[0] + "" + pStr[1] };
+ return AssembleWrite(ammeterAddress, password, dataMark, data);
+ }
+
+ ///
+ /// 构建写数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static List AssembleWrite(string ammeterAddress, string password, string di0_3, string[] data)
+ {
+ var returnList = new List();
+ returnList.Add(startStr);
+
+ var addressList = ammeterAddress.StringToPairs();
+ addressList.Reverse();
+ returnList.AddRange(addressList);
+
+ returnList.Add(startStr);
+ returnList.Add("14");
+
+ var len = (12 + data.Length).ToString("X2");
+ returnList.Add(len);
+
+
+ var di03List = di0_3.StringToPairs();
+ di03List.Reverse();
+ di03List.Add("02");
+
+ var pwdList = password.StringToPairs();
+ pwdList.Reverse();
+ di03List.AddRange(pwdList);
+
+ var mList = new List() { "00", "11", "22", "33" };
+ di03List.AddRange(mList);
+ di03List.AddRange(data);
+ var listAdd33 = di03List.AddHex33();
+
+ returnList.AddRange(listAdd33);
+
+ var strSum = returnList.Select(i => Convert.ToInt32(i, 16)).Sum().ToString("X");
+ var cs = strSum.Substring(strSum.Length - 2);
+ returnList.Add(cs);
+ returnList.Add(endStr);
+
+ return returnList;
+ }
+
+ ///
+ /// 生成软编程指令
+ /// 型号编码
+ ///
+ ///
+ public static List SoftProgram(string ammeterAddress, string modelCode, string password)
+ {
+ string bccmd = string.Empty;
+ if (modelCode == "DDS71")
+ {
+
+ bccmd = "68 AA AA AA AA AA AA 68 04 07 4E F4 35 BB BB BB 32";
+ }
+ else
+ {
+ bccmd = "68 AA AA AA AA AA AA 68 14 10 41 35 33 41 37 33 33 33 34 33 33 33 77 66 55 44";
+ }
+
+ //替换密码
+ var passwordList = password.StringToPairs();
+ passwordList.Reverse();
+ passwordList = passwordList.AddHex33();
+ var passwordStr = string.Join(" ", passwordList);
+ bccmd = bccmd.Replace("BB BB BB", passwordStr);
+ //替换表地址
+ var addressList = ammeterAddress.StringToPairs();
+ addressList.Reverse();
+ var addressStr = string.Join(" ", addressList);
+ bccmd = bccmd.Replace("AA AA AA AA AA AA", addressStr);
+ var fm = bccmd.Split(' ').ToList();
+ //生成CRC
+ var cRC = HexStringExtensions.GetCRC(fm);
+ fm.Add(cRC);
+ fm.Add("16");
+
+ return fm;
+ }
+
+
+ private static List GenerateCTCommand(string ammeterAddress, string data)
+ {
+ List fm = new List();
+ fm.Add(startStr);
+ List addressList = ammeterAddress.StringToPairs();
+ addressList.Reverse();
+ fm.AddRange(addressList);
+ fm.Add(startStr);
+ fm.Add("14");
+ fm.Add("13");
+ fm.Add("3F");
+ fm.Add("34");
+ fm.Add("33");
+ fm.Add("37");
+ fm.Add("35");
+ fm.Add("33");
+ fm.Add("33");
+ fm.Add("33");
+ fm.Add("44");
+ fm.Add("44");
+ fm.Add("44");
+ fm.Add("44");
+ //组装数据域
+ var dataList = data.StringToPairs();
+ dataList.Reverse();
+
+ fm.AddRange(dataList.AddHex33());
+
+ var cRC = HexStringExtensions.GetCRC(fm);
+ fm.Add(cRC);
+ fm.Add(endStr);
+ return fm;
+ }
+
+ private static List Time_MeterTiming()
+ {
+ return new List
+ {
+ DateTime.Now.Hour.ToString().PadLeft(2, '0'),
+ DateTime.Now.Minute.ToString().PadLeft(2, '0'),
+ (DateTime.Now.Second + 2).ToString().PadLeft(2, '0')
+ };
+ }
+
+ private static List Date_MeterTiming()
+ {
+ var week = (int)DateTime.Now.DayOfWeek;
+ var year = DateTime.Now.Year;
+ var month = DateTime.Now.Month;
+ var day = DateTime.Now.Day;
+
+ return new List
+ {
+ year.ToString().Substring(2,2).PadLeft(2,'0'),
+ month.ToString().PadLeft(2,'0'),
+ day.ToString().PadLeft(2,'0'),
+ week.ToString().PadLeft(2,'0'),
+ };
+ }
+
+ ///
+ /// 构建电表时段设置数据单元
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static List BuildAmmeterTimeSetDataUnit(string password, string dataMark, string data, string s_operator = "00000001")
+ {
+ List dataUnit = new List();
+ if (string.IsNullOrWhiteSpace(password))
+ password = "000000";
+ if (password?.Length != 6)
+ password = password.PadLeft(6, '0');
+ if (string.IsNullOrWhiteSpace(s_operator) || s_operator?.Length != 8)
+ throw new ArgumentNullException("电表操作人员格式不能为空或长度不等6位");
+
+ //数据标识 DIODI1DI2DI3+PAP0P1P2+C0C1C2C3+DATA
+ var dataMarks = dataMark.Split(' ').ToList();
+ dataMarks.Reverse();
+ dataUnit.AddRange(dataMarks);//数据标识
+
+ //密码权限 02明文 PAP0P1P2
+ var passs = password.StringToPairs(true);
+ dataUnit.Add("02");//--密码权限 02明文
+ foreach (var item in passs)
+ {
+ dataUnit.Add(item);
+ }
+ //操作人员 C0C1C2C3
+ var opers = s_operator.StringToPairs(true);
+ foreach (var item in opers)
+ {
+ dataUnit.Add(item);
+ }
+ //TODO:数据体 DATA
+ var datas = data.Split(' ').ToList();
+ datas.Reverse();
+ dataUnit.AddRange(datas);
+ return dataUnit;
+ }
+
+ #endregion
+ }
+}
diff --git a/src/JiShe.CollectBus.Common/Extensions/HexStringExtensions.cs b/src/JiShe.CollectBus.Common/Extensions/HexStringExtensions.cs
index 8d034fa..20ee829 100644
--- a/src/JiShe.CollectBus.Common/Extensions/HexStringExtensions.cs
+++ b/src/JiShe.CollectBus.Common/Extensions/HexStringExtensions.cs
@@ -1,11 +1,6 @@
using System.ComponentModel.DataAnnotations;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Models;
-using System.Reflection;
-using System.Net;
-using System.Collections.Generic;
-using System.Globalization;
-using static System.Runtime.InteropServices.JavaScript.JSType;
namespace JiShe.CollectBus.Common.Extensions
{
@@ -20,44 +15,9 @@ namespace JiShe.CollectBus.Common.Extensions
//消息认证码字段长度
private const int pWLen = 16;
- private const int tPLen = 6;
-
private const int FixedLength = 18;
- static object locker = new object();
- static List MSA = new List();
- static Dictionary> usingMSA = new Dictionary>();
-
- static HexStringExtensions()
- {
- for (int i = 1; i <= 127; i++)
- {
- MSA.Add(i);
- }
- }
- ///
- /// Gets the msa.
- ///
- /// 集中器地址
- ///
- public static int GetMSA(string mark)
- {
- lock (locker)
- {
- if (!usingMSA.Keys.Contains(mark))
- usingMSA.Add(mark, new List());
-
- int msa = MSA.Except(usingMSA[mark]).FirstOrDefault();
- //if (msa == 1) msa = 2;//msa=1为自定义指令保留
- usingMSA[mark].Add(msa);
-
- if (msa == 127)
- usingMSA[mark].RemoveAll(m => true);
-
- return msa;
- }
- }
-
+
public static object GetAnalyzeValue(this List hexStringList, CommandChunkEnum chunk)
{
if (hexStringList.Count < hearderLen || hexStringList[0] != startStr || hexStringList[5] != startStr || hexStringList.Count < FixedLength)
@@ -140,2132 +100,15 @@ namespace JiShe.CollectBus.Common.Extensions
return hexStringList;
}
- #region 376.1下行命令
-
- ///
- /// 构建电表参数设置-下发命令
- ///
- /// 集中器地址
- ///
- ///
- public static byte[] BuildAmmeterParameterSetSendCmd(string address, List meterParameters)
+ public static List ReduceHex33(this List hexStringList)
{
- var dataUnit = BuildAmmeterParameterSendDataUnit(meterParameters);
- var reqParameter = new ReqParameter2()
+ for (int i = 0; i < hexStringList.Count; i++)
{
- AFN = AFN.设置参数,
- FunCode = (int)CMasterStationFunCode.请求1级数据,
- A = address,
- Seq = new Seq()
- {
- TpV = TpV.附加信息域中无时间标签,
- FIRFIN = FIRFIN.单帧,
- CON = CON.需要对该帧进行确认,
- PRSEQ = 10,
- },
- MSA = GetMSA(address),
- Pn = 0,
- Fn = 10
- };
- var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
- return bytes;
- }
-
- ///
- /// 构建电表参数读取-下发命令
- ///
- /// 集中器地址
- /// 对象序号
- public static byte[] BuildAmmeterParameterReadingSendCmd(string address, List meterNumberList)
- {
- var dataUnit = new List();
- var countHex = meterNumberList.Count().DecToHex().PadLeft(4, '0');
- var countHexPairs = countHex.StringToPairs();
- countHexPairs.Reverse();
- dataUnit.AddRange(countHexPairs);
-
- foreach (var number in meterNumberList)
- {
- var numberHex = number.DecToHex().PadLeft(4, '0');
- var numberHexPairs = numberHex.StringToPairs();
- numberHexPairs.Reverse();
- dataUnit.AddRange(numberHexPairs);
+ var value = Convert.ToInt32(hexStringList[i], 16) - Convert.ToInt32("33", 16);
+ hexStringList[i] = value.DecToHex().PadLeft(2, '0');
}
- var reqParameter = new ReqParameter2()
- {
- AFN = AFN.查询参数,
- FunCode = (int)CMasterStationFunCode.请求2级数据,
- A = address,
- Seq = new Seq()
- {
- TpV = TpV.附加信息域中无时间标签,
- FIRFIN = FIRFIN.单帧,
- CON = CON.不需要对该帧进行确认,
- PRSEQ = 0,
- },
- MSA = GetMSA(address),
- Pn = 0,
- Fn = 10
- };
- var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
- return bytes;
- }
-
- ///
- /// 构建电表抄读一类数据-下发命令
- ///
- ///
- ///
- /// 一类数据项
- public static byte[] BuildAmmeterReadRealTimeDataSendCmd(string address, int pn, ATypeOfDataItems aTypeOfDataItems)
- {
- var reqParameter = new ReqParameter2()
- {
- AFN = AFN.请求实时数据,
- FunCode = (int)CMasterStationFunCode.请求2级数据,
- A = address,
- Seq = new Seq()
- {
- TpV = TpV.附加信息域中无时间标签,
- FIRFIN = FIRFIN.单帧,
- CON = CON.不需要对该帧进行确认,
- PRSEQ = 2,
- },
- MSA = GetMSA(address),
- Pn = pn,
- Fn = (int)aTypeOfDataItems
- };
- var bytes = HexStringExtensions.BuildSendCommandBytes(reqParameter);
- return bytes;
- }
-
- ///
- /// 构建电表抄读日冻结正向有功电能示值-下发命令
- ///
- ///
- ///
- ///
- public static void BuildAmmeterReadDailyFreezingDataSendCmd(string address, int pn, DateTime time)
- {
- var dataUnit = time.ToString("yy-MM-dd").Split('-').ToList();
- dataUnit.Reverse();
- var reqParameter = new ReqParameter2()
- {
- AFN = AFN.请求历史数据,
- FunCode = (int)CMasterStationFunCode.请求2级数据,
- A = address,
- Seq = new Seq()
- {
- TpV = TpV.附加信息域中无时间标签,
- FIRFIN = FIRFIN.单帧,
- CON = CON.不需要对该帧进行确认,
- PRSEQ = 2,
- },
- MSA = GetMSA(address),
- Pn = pn,
- Fn = 161
- };
- var bytes = HexStringExtensions.BuildSendCommandBytes(reqParameter, dataUnit);
- }
-
- ///
- /// 构建电表抄读实时电流-下发命令
- ///
- ///
- ///
- public static void BuildAmmeterRealTimeCurrentDataSendCmd(string address, int pn)
- {
- var reqParameter = new ReqParameter2()
- {
- AFN = AFN.请求实时数据,
- FunCode = (int)CMasterStationFunCode.请求2级数据,
- A = address,
- Seq = new Seq()
- {
- TpV = TpV.附加信息域中无时间标签,
- FIRFIN = FIRFIN.单帧,
- CON = CON.不需要对该帧进行确认,
- PRSEQ = 2,
- },
- MSA = GetMSA(address),
- Pn = pn,
- Fn = 25
- };
- var bytes = HexStringExtensions.BuildSendCommandBytes(reqParameter);
- }
-
-
- ///
- /// 构建电表读取二类数据-下发命令
- ///
- ///
- ///
- /// fn
- /// 冻结密度
- /// 冻结点数
- /// 起始时间
- public static byte[] BuildAmmeterReadingIIdataTypeItemsSendCmd(string address, int pn, IIdataTypeItems iIDataTypeItems, FreezeDensity density,int points,DateTime? beginTime = null)
- {
- var queryDate = beginTime ?? DateTime.Today.AddDays(-1);
- var dataUnit = queryDate.ToString("yyMMddHHmm").StringToPairs();
- dataUnit.Reverse();
-
- //冻结密度
- dataUnit.Add(((int)density).DecToHex());
-
- dataUnit.Add(points.DecToHex());
-
- var reqParameter = new ReqParameter2()
- {
- AFN = AFN.请求历史数据,
- FunCode = (int)CMasterStationFunCode.请求2级数据,
- A = address,
- Seq = new Seq()
- {
- TpV = TpV.附加信息域中无时间标签,
- FIRFIN = FIRFIN.单帧,
- CON = CON.不需要对该帧进行确认,
- PRSEQ = 2,
- },
- MSA = GetMSA(address),
- Pn = pn,
- Fn = (int)iIDataTypeItems
- };
- var bytes = HexStringExtensions.BuildSendCommandBytes(reqParameter, dataUnit);
- return bytes;
- }
-
- ///
- /// 构建电表读取二类数据-下发命令
- ///
- ///
- ///
- /// fn
- /// 数据时标
- /// 起始时间
- public static void BuildAmmeterReadingBaseDataSendCmd(string address, int pn, IIdataTypeItems iIDataTypeItems,TdType tdType, DateTime? beginTime = null)
- {
- var queryDate = beginTime ?? DateTime.Today.AddDays(-1);
- List? dataUnit = null;
- switch (tdType)
- {
- case TdType.Td_d:
- dataUnit = queryDate.ToString("yyMMdd").StringToPairs();
- break;
- case TdType.Td_m:
- dataUnit = queryDate.ToString("yyMM").StringToPairs();
- break;
- }
-
- if(dataUnit == null) return;
-
- dataUnit.Reverse();
- var reqParameter = new ReqParameter2()
- {
- AFN = AFN.请求历史数据,
- FunCode = (int)CMasterStationFunCode.请求2级数据,
- A = address,
- Seq = new Seq()
- {
- TpV = TpV.附加信息域中无时间标签,
- FIRFIN = FIRFIN.单帧,
- CON = CON.不需要对该帧进行确认,
- PRSEQ = 2,
- },
- MSA = GetMSA(address),
- Pn = pn,
- Fn = (int)iIDataTypeItems
- };
- var bytes = HexStringExtensions.BuildSendCommandBytes(reqParameter, dataUnit);
- }
-
-
- ///
- /// 组装有/无功电量
- ///
- ///
- ///
- ///
- public static void BuildAmmeterReadingElectricityDataSendCmd(string address, int pn,int cmdType)
- {
- var reqParameter = new ReqParameter2()
- {
- AFN = AFN.请求实时数据,
- FunCode = (int)CMasterStationFunCode.请求2级数据,
- A = address,
- Seq = new Seq()
- {
- TpV = TpV.附加信息域中无时间标签,
- FIRFIN = FIRFIN.单帧,
- CON = CON.不需要对该帧进行确认,
- PRSEQ = 2,
- },
- MSA = GetMSA(address),
- Pn = pn,
- Fn = cmdType
- };
- var bytes = HexStringExtensions.BuildSendCommandBytes(reqParameter);
- }
-
- ///
- /// 构建超功率设置-下发命令
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static void BuildAmmeterSuperpowerSettingSendCmd(string address, string password,string modelCode, int port, string baudRate, decimal power)
- {
- if (power > 0)
- {
-
- WsOnSupperPower(address, password, modelCode, true, port, baudRate);
-
- //TODO:连续发几条嘛?
- string dataMark;
- //如果是多回路电表,地址只取前面部分 例如:564880000001_01 取564880000001
- if (address.IndexOf('_') > 0)
- {
- var addressSplit = address.Split('_');
- address = addressSplit[0];
- var loop = Convert.ToInt32(addressSplit[1]);
- if (loop == 1) { dataMark = "0E300101"; }
- else if (loop == 2) { dataMark = "0E300201"; }
- else
- return;
- }
- else
- {
- dataMark = "0E300101";
- }
-
- var turnData = AssembleWsSupperPower(address, password, dataMark, power);
- if (turnData != null)
- {
- var bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, turnData);
- }
- }
- else
- {
- WsOnSupperPower(address, password, modelCode, false, port, baudRate);
- }
-
- }
-
- ///
- /// 构建恶性负载绝对功率设置-下发命令
- ///
- ///
- ///
- ///
- ///
- ///
- public static void BuildAmmeterAbsolutePowerSettingSendCmd(string address, string password, int port, string baudRate, decimal power)
- {
- if (power <= 0)
- {
- power = 99;//等于小0 代表关闭
- }
-
- string dataMark;
- //如果是多回路电表,地址只取前面部分 例如:564880000001_01 取564880000001
- if (address.IndexOf('_') > 0)
- {
- var addressSplit = address.Split('_');
- address = addressSplit[0];
-
- var loop = Convert.ToInt32(addressSplit[1]);
- if (loop == 1) { dataMark = "0E300103"; }
- else if (loop == 2) { dataMark = "0E300203"; }
- else
- return;
- }
- else
- {
- dataMark = "0E300103";
- }
-
- var turnData = AssembleWsAbsolutePowerSetting(address, password, dataMark, power);
- if (turnData != null)
- {
- var bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, turnData);
- }
- }
-
- ///
- /// 构建恶性负载功率因数设置-下发命令
- ///
- ///
- ///
- ///
- ///
- ///
- public static void BuildAmmeterPowerFactorSettingSendCmd(string address, string password, int port, string baudRate, decimal power)
- {
- string dataMark;
- //如果是多回路电表,地址只取前面部分 例如:564880000001_01 取564880000001
- if (address.IndexOf('_') > 0)
- {
- var addressSplit = address.Split('_');
- address = addressSplit[0];
-
- var loop = Convert.ToInt32(addressSplit[1]);
- if (loop == 1) { dataMark = "0E300104"; }
- else if (loop == 2) { dataMark = "0E300204"; }
- else
- return;
- }
- else
- {
- dataMark = "0E300104";
- }
-
- var turnData = AssembleWsPowerFactor(address, password, dataMark, power);
- if (turnData != null)
- {
- var bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, turnData);
- }
- }
-
- ///
- /// 超功率开关
- ///
- ///
- ///
- ///
- ///
- ///
- public static void WsOnSupperPower(string address,string password,string modelCode,bool isOn,int port,string baudRate)
- {
-
- List modelCodes = new List() { "DDS3102-S2", "DDS71", "DDZY71", "DTZY71", "DSZY71" };
- //这些型号需进入软编程
- if (modelCodes.Contains(modelCode))
- {
- var dataUnit1 = SoftProgram(address, modelCode, password);
- BuildTransparentForwardingSendCmd(address, port, baudRate, dataUnit1);
- }
-
- var dataUnit2 = AssembleWsOnSupperPower(address, password, isOn);
- BuildTransparentForwardingSendCmd(address, port, baudRate, dataUnit2);
- }
-
-
- ///
- /// 构建水表参数设置-下发命令
- ///
- /// 集中器地址
- ///
- ///
- public static byte[] BuildWaterMeterParameterSetSendCmd(string address, List meterParameters)
- {
- var dataUnit = BuildWaterMeterParameterSendDataUnit(meterParameters);
- var reqParameter = new ReqParameter2()
- {
- AFN = AFN.设置参数,
- FunCode = (int)CMasterStationFunCode.请求1级数据,
- A = address,
- Seq = new Seq()
- {
- TpV = TpV.附加信息域中无时间标签,
- FIRFIN = FIRFIN.单帧,
- CON = CON.需要对该帧进行确认,
- PRSEQ = 10,
- },
- MSA = GetMSA(address),
- Pn = 0,
- Fn = 10
- };
- var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
- return bytes;
- }
-
-
- ///
- /// 构建通讯参数设置-下发命令
- ///
- /// 集中器地址
- /// 主站ip
- /// 主站端口
- /// 备用ip和端口
- /// 备用ip和端口
- /// APN:CMNET 63 6D 6E 65 74
- ///
- public static byte[] BuildCommunicationParametersSetSendCmd(string address,string masterIP,string masterPort,
- string backupIP,string backupPort, string aPN)
- {
- var dataUnit = new List();
- var masterIPList = masterIP.Split('.').Select(it => int.Parse(it).DecToHex().PadLeft(2,'0')).ToList();
- dataUnit.AddRange(masterIPList);
-
- var masterPortList = int.Parse(masterPort).DecToHex().PadLeft(4, '0').StringToPairs();
- masterPortList.Reverse();
- dataUnit.AddRange(masterPortList);
-
- var backupIPList = backupIP.Split('.').Select(it => int.Parse(it).DecToHex().PadLeft(2, '0')).ToList();
- dataUnit.AddRange(backupIPList);
-
- var backupPortList = int.Parse(backupPort).DecToHex().PadLeft(4, '0').StringToPairs();
- backupPortList.Reverse();
- dataUnit.AddRange(backupPortList);
-
- var aPNList = aPN.ToCharArray().Select(it => Convert.ToInt32(it).DecToHex().PadLeft(2, '0')).ToList();
- aPNList.AddRange(Enumerable.Repeat("00",16 - aPNList.Count));
- dataUnit.AddRange(aPNList);
-
- var reqParameter = new ReqParameter2()
- {
- AFN = AFN.设置参数,
- FunCode = (int)CMasterStationFunCode.请求1级数据,
- A = address,
- Seq = new Seq()
- {
- TpV = TpV.附加信息域中无时间标签,
- FIRFIN = FIRFIN.单帧,
- CON = CON.需要对该帧进行确认,
- PRSEQ = 10,
- },
- MSA = GetMSA(address),
- Pn = 0,
- Fn = 3
- };
- var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
- return bytes;
- }
-
- ///
- /// 构建抄读终端日历时钟-下发命令
- ///
- ///
- public static byte[] BuildTerminalCalendarClockSendCmd(string address)
- {
- var reqParameter = new ReqParameter2()
- {
- AFN = AFN.请求实时数据,
- FunCode = (int)CMasterStationFunCode.请求2级数据,
- A = address,
- Seq = new Seq()
- {
- TpV = TpV.附加信息域中无时间标签,
- FIRFIN = FIRFIN.单帧,
- CON = CON.不需要对该帧进行确认,
- PRSEQ = 2,
- },
- MSA = GetMSA(address),
- Pn = 0,
- Fn = 2
- };
- var bytes = HexStringExtensions.BuildSendCommandBytes(reqParameter);
- return bytes;
- }
-
- ///
- /// 构建终端版本信息读取-下发命令
- ///
- ///
- public static byte[] BuildTerminalVersionInfoReadingSendCmd(string address)
- {
- var reqParameter = new ReqParameter2()
- {
- AFN = AFN.请求终端配置,
- FunCode = (int)CMasterStationFunCode.请求2级数据,
- A = address,
- Seq = new Seq()
- {
- TpV = TpV.附加信息域中无时间标签,
- FIRFIN = FIRFIN.单帧,
- CON = CON.不需要对该帧进行确认,
- PRSEQ = 2,
- },
- MSA = GetMSA(address),
- Pn = 0,
- Fn = 1
- };
- var bytes = HexStringExtensions.BuildSendCommandBytes(reqParameter);
- return bytes;
- }
-
- ///
- /// 集中器校时 秒、分、时、日、星期-月(3-1+4)、年
- ///
- ///
- ///
- ///
- public static byte[] BuildConrCheckTimeSendCmd(string address, DateTime time)
- {
- var week = ((int)time.DayOfWeek).DecToBin().PadLeft(3, '0');
- var monthTemp = time.Month.ToString().PadLeft(2, '0');
- var m1 = int.Parse(monthTemp[0].ToString()).DecToBin();//十位
- var m2 = int.Parse(monthTemp[1].ToString()).DecToBin().PadLeft(4, '0');//个位
- var weekAndMonthHex = (week + m1 + m2).BinToHex().ToUpper();
-
- var strTimeFm = time.ToString("ss mm HH dd $$ yy").Replace("$$", weekAndMonthHex);
- var dataUnit = strTimeFm.Replace(" ", "").StringToPairs();
- dataUnit.AddRange(GetPW());
- var reqParameter = new ReqParameter2()
- {
- AFN = AFN.控制命令,
- FunCode = (int)CMasterStationFunCode.请求1级数据,
- A = address,
- Seq = new Seq()
- {
- TpV = TpV.附加信息域中无时间标签,
- FIRFIN = FIRFIN.单帧,
- CON = CON.需要对该帧进行确认,
- PRSEQ = 10,
- },
- MSA = GetMSA(address),
- Pn = 0,
- Fn = 31
- };
- var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
- return bytes;
- }
-
- ///
- /// 硬件初始化
- ///
- ///
- ///
- public static byte[] BuildConrRebootSendCmd(string address)
- {
- var dataUnit = GetPW();
- var reqParameter = new ReqParameter2()
- {
- AFN = AFN.复位,
- FunCode = (int)CMasterStationFunCode.复位命令,
- A = address,
- Seq = new Seq()
- {
- TpV = TpV.附加信息域中无时间标签,
- FIRFIN = FIRFIN.单帧,
- CON = CON.需要对该帧进行确认,
- PRSEQ = 10,
- },
- MSA = GetMSA(address),
- Pn = 0,
- Fn = 1
- };
- var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
- return bytes;
- }
-
- ///
- /// 构建透明转发-下发命令
- ///
- /// 集中器地址
- /// 终端通信端口 1~31
- /// 300,600,1200,2400,4800,7200,9600,19200对应 0~7
- /// 转发内容
- /// 停止位
- /// 校验方式
- /// 数据位
- /// 等待报文超时时间/s
- /// 等待字节超时时间/ms
- public static byte[] BuildTransparentForwardingSendCmd(string address, int port, string baudRate, List datas, StopBit stopBit = StopBit.Stop1, Parity parity = Parity.Even, DataBit dataBit = DataBit.D8,
- int waitContentTimeout = 100, int waitByteTimeout = 100)
- {
- var baudRateValue = GetBaudreate(baudRate);
-
- var dataUnit = BuildTransparentForwardingSendDataUnit(port, baudRateValue, datas, stopBit, parity, dataBit, waitContentTimeout, waitByteTimeout);
- dataUnit.AddRange(GetPW());
- var reqParameter = new ReqParameter2()
- {
- AFN = AFN.数据转发,
- FunCode = (int)CMasterStationFunCode.请求2级数据,
- A = address,
- Seq = new Seq()
- {
- TpV = TpV.附加信息域中无时间标签,
- FIRFIN = FIRFIN.单帧,
- CON = CON.不需要对该帧进行确认,
- PRSEQ = 0
- },
- MSA = GetMSA(address),
- Pn = 0,
- Fn = 1
- };
- var bytes = BuildSendCommandBytes(reqParameter, dataUnit);
- return bytes;
- }
-
- ///
- /// 根据波特率获取值
- ///
- ///
- ///
- public static int GetBaudreate(string val)
- {
- var type = 0;
- switch (val)
- {
- case "300": type = 0; break;
- case "600": type = 1; break;
- case "1200": type = 2; break;
- case "2400": type = 3; break;
- case "4800": type = 4; break;
- case "7200": type = 5; break;
- case "9600": type = 6; break;
- case "19200": type = 7; break;
- }
- return type;
- }
-
- ///
- /// 根据波特率获取值
- ///
- ///
- ///
- public static int GetProtocolType(string val)
- {
- var type = 0;
- switch (val)
- {
- case "DL/T 645—2007": type = 30; break;
- case "DL/T 645—1997": type = 1; break;
- case "交流采样装置": type = 2; break;
- case "串行接口连接窄带低压载波通讯": type = 31; break;
- }
- return type;
- }
-
- [Obsolete]
- public static List AmmeterValveControl(string address, string specialnocode, string password, bool state, string modelCode = "")
- {
- address = address.Trim().TrimStart('0');
- if (address.Length < 12) address = address.PadLeft(12, '0');
- string Code = string.Empty;
-
- if (state)
- {
- if (string.IsNullOrEmpty(specialnocode))
- Code = "1B";
- else
- Code = specialnocode == "1B" || specialnocode == "1C" ? specialnocode : "1C";
- }
- else
- Code = "1A";//跳闸
-
- if (specialnocode == "1W")
- {
- if (state)
- Code = "1A";
- else
- Code = "1C";
- }
-
- var pwdLevel = "02";
- if (modelCode == "HL_DTSU2625" || modelCode == "DDZY9866")
- pwdLevel = "04";
- else if (modelCode == "DDS2705")
- pwdLevel = "03";
-
- if (!string.IsNullOrWhiteSpace(password) && password.Contains("|"))
- {
- var sp = password.Split('|');
- pwdLevel = sp[1];
- password = sp[0];
- }
-
- string strDate = DateTime.Now.AddYears(3).ToString("000012ddMMyy").StrAddSpan();
- if (specialnocode == "1D" || modelCode == "SZBD_DDZY1225")
- strDate = "FF FF FF FF FF FF";
- string strP = password.StrAddSpan().StrReverseOrder();
- string strSJY = " " + pwdLevel + " " + strP + " 01 00 00 00 " + Code + " 00 " + strDate;
- string strLen = (strSJY.Replace(" ", "").Length / 2).ToString("X2");
- string strReturn = "68 " + address.StrAddSpan().StrReverseOrder() + " 68 1C " + strLen + " " + strSJY.StrAddHex33() + " ";
- string strSum = strReturn.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries).Select(i => Convert.ToInt32(i, 16)).Sum().ToString("X");
- strReturn += strSum.Substring(strSum.Length - 2) + " 16";
-
- return strReturn.Split(' ').ToList();
- }
-
-
- ///
- /// 构建透明转发-下发数据单元
- ///
- /// 终端通信端口 1~31
- /// 0~7 对应300,600,1200,2400,4800,7200,9600,19200
- /// 转发内容
- /// 停止位
- /// 校验方式
- /// 数据位
- /// 等待报文超时时间/s
- /// 等待字节超时时间/ms
- ///
- private static List BuildTransparentForwardingSendDataUnit(int port, int baudRate, List datas, StopBit stopBit = StopBit.Stop1, Parity parity = Parity.Even, DataBit dataBit = DataBit.D8,
- int waitContentTimeout = 100, int waitByteTimeout = 100)
- {
- var dataUnit = new List();
-
- var portHex = port.DecToHex().PadLeft(2, '0');
- dataUnit.Add(portHex);
-
- var baudRateBin = baudRate.DecToBin().PadLeft(3, '0');
- var stopBitBin = ((int)stopBit).DecToBin();
- var parityBin = parity != Parity.None ? $"1{((int)parity).DecToBin()}" : "00";
- var dataBitBin = ((int)dataBit).DecToBin().PadLeft(2, '0');
- var controlHex = $"{baudRateBin}{stopBitBin}{parityBin}{dataBitBin}".BinToHex().PadLeft(2, '0'); ;
- dataUnit.Add(controlHex);
-
- var waitContentTimeoutBin = $"1{waitContentTimeout.DecToBin().PadLeft(7, '0')}";
- var waitContentTimeoutHex = waitContentTimeoutBin.BinToHex().PadLeft(2, '0');
- var waitByteTimeoutHex = waitByteTimeout.DecToHex().PadLeft(2, '0');
-
- dataUnit.Add(waitContentTimeoutHex);
- dataUnit.Add(waitByteTimeoutHex);
-
- var countHex = datas.Count.DecToHex().PadLeft(4, '0');
- var countHexPairs = countHex.StringToPairs();
- countHexPairs.Reverse();
- dataUnit.AddRange(countHexPairs);
-
- dataUnit.AddRange(datas);
-
- return dataUnit;
- }
-
- ///
- /// 构建下发命令
- ///
- ///
- ///
- ///
- public static byte[] BuildSendCommandBytes(ReqParameter reqParameter, List? dataUnit = null)
- {
- var cmdStrList = new List();
- var userDatas = BuildUserData(reqParameter, dataUnit);
- var hearders = BuildHeaders(userDatas.Count);
- var cs = GetCS(userDatas);
- cmdStrList.AddRange(hearders);
- cmdStrList.AddRange(userDatas);
- cmdStrList.Add(cs);
- cmdStrList.Add(endStr);
- Console.WriteLine(string.Join(" ", cmdStrList));
- var bytes = cmdStrList.Select(x => Convert.ToByte(x, 16)).ToArray();
- return bytes;
- }
-
- ///
- /// 构建电表参数设置-下发数据单元
- ///
- ///
- ///
- private static List BuildAmmeterParameterSendDataUnit(List meterParameters)
- {
- var hexDatas = new List();
-
- var countHex = meterParameters.Count().DecToHex().PadLeft(4, '0');
- hexDatas.Add(countHex);
-
- for (int i = 0; i <= meterParameters.Count - 1; i++)
- {
- var meter = meterParameters[i];
-
- //var indexHex = (i + 1).DecToHex().PadLeft(4, '0');
- var indexHex = meter.SerialNumber.DecToHex().PadLeft(4, '0');
- hexDatas.Add(indexHex);
-
- var pnHex = meter.Pn.DecToHex().PadLeft(4, '0');
- hexDatas.Add(pnHex);
-
- var baudRateBin = meter.BaudRate.DecToBin().PadLeft(3, '0');
- var portBin = meter.Port.DecToBin().PadLeft(5, '0');
- var baudRateAndPortHex = $"{baudRateBin}{portBin}".BinToHex().PadLeft(2, '0');
- hexDatas.Add(baudRateAndPortHex);
-
- var protocolTypeHex = ((int)meter.ProtocolType).DecToHex().PadLeft(2, '0');
- hexDatas.Add(protocolTypeHex);
-
- hexDatas.Add(meter.Address);
-
- hexDatas.Add(meter.Password.PadLeft(12, '0'));
-
- var rateNumberBin = $"0000{meter.RateNumber.DecToBin().PadLeft(4, '0')}";
- var rateNumberHex = rateNumberBin.BinToHex().PadLeft(2, '0');
- hexDatas.Add(rateNumberHex);
-
- var intBitNumberBin = (meter.IntegerBitNumber - 4).DecToBin().PadLeft(2, '0');
- var decBitNumberBin = (meter.DecimalBitNumber - 1).DecToBin().PadLeft(2, '0');
- var intAndDecBitNumberBin = $"0000{intBitNumberBin}{decBitNumberBin}";
- var intAndDecBitNumberHex = intAndDecBitNumberBin.BinToHex().PadLeft(2, '0');
- hexDatas.Add(intAndDecBitNumberHex);
-
- hexDatas.Add(meter.CollectorAddress.PadLeft(12, '0'));
-
- var userCategoryNumber = 0;//meter.UserCategoryNumber
- var userSubclassNumber = 0;//meter.UserSubclassNumber
- if (meter.ProtocolType == 32) userCategoryNumber = 1;
- else if (meter.ProtocolType == 45) { userCategoryNumber = 1; userSubclassNumber = 9; }
-
- var userCategoryNumberBin = userCategoryNumber.DecToBin().PadLeft(4, '0');
- var userSubclassNumberBin = userSubclassNumber.DecToBin().PadLeft(4, '0');
- var userNumberHex = $"{userCategoryNumberBin}{userSubclassNumberBin}".BinToHex().PadLeft(2, '0');
- hexDatas.Add(userNumberHex);
- }
-
- //高位在前,低位在后
- var datas = new List();
- foreach (var hexData in hexDatas)
- {
- if (hexData.Length == 2)
- datas.Add(hexData);
- else
- {
- var lst = hexData.StringToPairs();
- lst.Reverse();
- datas.AddRange(lst);
- }
- }
- datas.AddRange(GetPW());
- return datas;
- }
-
- ///
- /// 构建水表参数设置-下发数据单元
- ///
- ///
- ///
- private static List BuildWaterMeterParameterSendDataUnit(List meterParameters)
- {
- var hexDatas = new List();
-
- var countHex = meterParameters.Count().DecToHex().PadLeft(4, '0');
- hexDatas.Add(countHex);
-
- for (int i = 0; i <= meterParameters.Count - 1; i++)
- {
-
- var meter = meterParameters[i];
- var protocolType = (int)meter.ProtocolType;
-
- var currentProtocolType = protocolType;
- if (protocolType == 43)
- currentProtocolType = 1;
- else if (protocolType > 32) currentProtocolType = 32;
-
- //TODO:无线水表 小数位
- if (currentProtocolType == 32 && meter.Address.Substring(0, 2) != "00")
- {
- var ejz = meter.Address.Substring(0, 2).HexToBin().PadLeft(8, '0');
- var xs = ejz.Substring(6, 2).BinToDec();
- var zs = ejz.Substring(0, 6).BinToDec();
- //userData.Add(new QGDW3671UserData() { Name = "整数位无线水表", Value = zs });
- //userData.Add(new QGDW3671UserData() { Name = "小数位无线水表", Value = xs });
- }
-
- var userCategoryNumber = meter.UserCategoryNumber;
- var userSubclassNumber = meter.UserSubclassNumber;
-
- if (protocolType == 32)
- userCategoryNumber = 1;
- else if (protocolType == 45)
- {
- userCategoryNumber = 1;
- userSubclassNumber = 9;
- }
- else if (protocolType == 1)
- userSubclassNumber = 1;
-
- var indexHex = (i + 1).DecToHex().PadLeft(4, '0');
- hexDatas.Add(indexHex);
-
- var pnHex = meter.Pn.DecToHex().PadLeft(4, '0');
- hexDatas.Add(pnHex);
-
- var baudRateBin = meter.BaudRate.DecToBin().PadLeft(3, '0');
- var portBin = meter.Port.DecToBin().PadLeft(5, '0');
- var baudRateAndPortHex = $"{baudRateBin}{portBin}".BinToHex().PadLeft(2, '0');
- hexDatas.Add(baudRateAndPortHex);
-
- var protocolTypeHex = currentProtocolType.DecToHex().PadLeft(2, '0');
- hexDatas.Add(protocolTypeHex);
-
- hexDatas.Add(meter.Address);
-
- hexDatas.Add(meter.Password.PadLeft(12, '0'));
-
- var rateNumberBin = $"0000{meter.RateNumber.DecToBin().PadLeft(4, '0')}";
- var rateNumberHex = rateNumberBin.BinToHex().PadLeft(2, '0');
- hexDatas.Add(rateNumberHex);
-
- var intBitNumberBin = meter.IntegerBitNumber.DecToBin().PadLeft(2, '0');
- var decBitNumberBin = meter.DecimalBitNumber.DecToBin().PadLeft(2, '0');
- var intAndDecBitNumberBin = $"0000{intBitNumberBin}{decBitNumberBin}";
- var intAndDecBitNumberHex = intAndDecBitNumberBin.BinToHex().PadLeft(2, '0');
- hexDatas.Add(intAndDecBitNumberHex);
-
- hexDatas.Add(meter.CollectorAddress.PadLeft(12, '0'));
-
- var userCategoryNumberBin = userCategoryNumber.DecToBin().PadLeft(4, '0');
- var userSubclassNumberBin = userSubclassNumber.DecToBin().PadLeft(4, '0');
- var userNumberHex = $"{userCategoryNumberBin}{userSubclassNumberBin}".BinToHex().PadLeft(2, '0');
- hexDatas.Add(userNumberHex);
- }
-
- //高位在前,低位在后
- var datas = new List();
- foreach (var hexData in hexDatas)
- {
- if (hexData.Length == 2)
- datas.Add(hexData);
- else
- {
- var lst = hexData.StringToPairs();
- lst.Reverse();
- datas.AddRange(lst);
- }
- }
- datas.AddRange(GetPW());
- return datas;
- }
-
-
- //AUX=消息认证码字段(PW,16个字节)
- private static List GetPW()
- {
- var str = "00";
- var pWList = Enumerable.Repeat(str, pWLen).ToList();
- return pWList;
- }
-
-
- ///
- /// 帧校验和
- ///
- /// 用户数据区
- ///
- private static string GetCS(List userData)
- {
- byte sum = 0;
- foreach (var d in userData)
- {
- var b = Convert.ToByte(d, 16);
- sum += b;
- }
- return sum.ToString("X2");
- }
-
- ///
- /// 用户数据区
- ///
- ///
- ///
- private static List BuildUserData(ReqParameter reqParameter, List? dataUnit)
- {
- var c = BuildC(reqParameter.FunCode, reqParameter.PRM);
- var a = BuildAList(reqParameter.A, reqParameter.MSA);
-
- var linkUserData = BuildLinkUserData(reqParameter.AFN, reqParameter.Seq,
- ((ReqParameter2)reqParameter).Pn, ((ReqParameter2)reqParameter).Fn, dataUnit);
-
- var list = new List() { c };
- list.AddRange(a);
- list.AddRange(linkUserData);
- return list;
- }
-
- ///
- /// 固定长度的报文头 起始字符+长度+长度+起始字符
- ///
- ///
- ///
- private static List BuildHeaders(int length)
- {
- var headers = new List();
- headers.Add(startStr);
- var l = BuildLength(length);
- headers.AddRange(l);
- headers.AddRange(l);
- headers.Add(startStr);
- return headers;
- }
-
- ///
- /// 长度 2字节 [用户数据区长度]
- ///
- ///
- private static List BuildLength(int length1)
- {
- var binaryLen = length1.DecToBin();
- var protocolIdentification = Enum.Format(typeof(ProtocolIdentification),
- ProtocolIdentification.本规约使用, "d").PadLeft(2, '0');
- var lenStr = $"{binaryLen}{protocolIdentification}";
- var hexLen = lenStr.BinToHex();
- hexLen = hexLen.PadLeft(4, '0');
- var list = hexLen.StringToPairs();
- list.Reverse();
- return list;
- }
-
- ///
- /// 控制域
- ///
- /// 功能码
- ///
- ///
- ///
- private static string BuildC(int funCode, PRM pRM, int fcb = 0, FCV fcv = FCV.FCB位无效)
- {
- var cMasterStationFunCodeHex = funCode.DecToBin();
- cMasterStationFunCodeHex = cMasterStationFunCodeHex.ToString().PadLeft(4, '0');
- var strC = $"{(int)DIR.主站下行报文}{(int)pRM}{fcb}{(int)fcv}{cMasterStationFunCodeHex}";
- var hexC = strC.BinToHex().PadLeft(2, '0');
- return hexC;
- }
-
-
- ///
- /// 地址域 3220 09872
- ///
- /// 行政区划码 BCD码 3220=2032
- /// 逻辑地址 BIN 09872=2690=>9026
- /// 主站地址 BIN 0~127
- ///
- private static List BuildAList(string a, int mSA)
- {
- var list = new List();
-
- var a1 = a.Substring(0, 4);
- var a1Pairs = a1.StringToPairs();
- a1Pairs.Reverse();
- list.AddRange(a1Pairs);
-
- var a2 = Convert.ToInt32(a.Substring(4));
- var decA2 = a2.DecToHex();
- var a2Pairs = decA2.PadLeft(4, '0').StringToPairs();
- a2Pairs.Reverse();
- list.AddRange(a2Pairs);
-
- //TODO:主站地址和组地址标志
- var a3Bin = $"{mSA.DecToBin().PadLeft(7, '0')}0";
- list.Add(a3Bin.BinToHex().PadLeft(2, '0'));
-
- return list;
- }
-
- private static List BuildLinkUserData(AFN aFN, Seq seq, int pn, int fn, List? dataUnit)
- {
- var aFNValue = ((int)aFN).DecToHex().PadLeft(2, '0');
- var sEQ = BuildSEQ(seq.TpV, seq.FIRFIN, seq.CON, seq.PRSEQ);
- var dA = BuildDA(pn);
- var dT = BuildDT(fn);
- var list = new List() { aFNValue, sEQ };
- list.AddRange(dA);
- list.AddRange(dT);
-
- if (dataUnit != null)
- {
- list.AddRange(dataUnit);
- }
- //list.AddRange(GetDataUnit(aFN,seq));
-
- if (seq.TpV == TpV.附加信息域中带时间标签)
- list.AddRange(BuildTp("00"));
-
- return list;
- }
-
- ///
- /// 帧序列域
- ///
- ///
- ///
- ///
- ///
- private static string BuildSEQ(TpV tpV, FIRFIN fIRFIN, CON cON, int pRSEQ)
- {
- var tpVValue = Enum.Format(typeof(TpV),
- tpV, "d");
- var fIRFINValue = Enum.Format(typeof(FIRFIN),
- fIRFIN, "d");
- var cONValue = (int)cON;
- var sEQBin = $"{tpVValue}{fIRFINValue}{cONValue}{pRSEQ.DecToBin().PadLeft(4, '0')}";
- var hexSEQ = sEQBin.BinToHex().PadLeft(2, '0');
- return hexSEQ;
- }
-
- ///
- /// 信息点标识
- ///
- /// 计量点
- ///
- private static List BuildDA(int pn)
- {
- if (pn == 0)
- return new List() { "00", "00" };
- var dA2 = (pn - 1) / 8 + 1;//信息点组从1开始 第几组
- var dA1 = pn - (dA2 - 1) * 8;//pn % 8
- var dA1Hex = "1".PadRight(dA1, '0').BinToHex();//对位信息 第几位 二进制有效位
- var dA2Hex = dA2.DecToHex();
- return new List() { dA1Hex.PadLeft(2, '0'), dA2Hex.PadLeft(2, '0') };
-
- }
-
- ///
- /// 数据单元标识
- ///
- ///
- ///
- private static List BuildDT(int fn)
- {
- var dT2 = (fn - 1) / 8;//从零开始 第几组
- var dT1 = fn - dT2 * 8;
- var dT1Hex = "1".PadRight(dT1, '0').BinToHex();//对位信息 第几位 二进制有效位
- var dT2Hex = dT2.DecToHex();
- return new List() { dT1Hex.PadLeft(2, '0'), dT2Hex.PadLeft(2, '0') };
- }
-
- ///
- /// 时间标签
- ///
- /// 启动帧帧序号计数器PFC 1字节
- /// 允许发送传输延时时间 min 1字节
- ///
- private static List BuildTp(string pFC = "00", int delayTime = 0)
- {
- var now = DateTime.Now; // 获取当前时间
- var seconds = now.Second.ToString().PadLeft(2, '0'); // 获取当前秒数
- var minutes = now.Minute.ToString().PadLeft(2, '0'); // 获取当前分钟数
- var hours = now.Hour.ToString().PadLeft(2, '0'); // 获取当前小时数
- var day = now.Day.ToString().PadLeft(2, '0'); // 获取当前日期的日数
- return new List() { pFC, seconds, minutes, hours, day, delayTime.ToString().PadLeft(2, '0') };
- }
-
- #endregion
-
- #region 645下行命令
-
-
- ///
- /// 构建电表阀控下发数据单元
- ///
- /// 电表地址
- /// 特殊控制码
- /// 密码
- /// 是否为开阀
- /// 型号码
- ///
- public static List BuildAmmeterValveControlSendDataUnit(string ammeterAddress, string specialControlCode, string password, bool state, string modelCode = "")
- {
- var code = string.Empty;
-
- if (state)
- {
- if (string.IsNullOrEmpty(specialControlCode))
- code = "1B";
- else
- code = specialControlCode == "1B" || specialControlCode == "1C" ? specialControlCode : "1C";
- }
- else
- code = "1A";//跳闸
-
- if (specialControlCode == "1W")
- {
- if (state)
- code = "1A";
- else
- code = "1C";
- }
-
- var pwdLevel = "02";
- if (modelCode == "HL_DTSU2625" || modelCode == "DDZY9866")
- pwdLevel = "04";
- else if (modelCode == "DDS2705")
- pwdLevel = "03"; //不带安全认证密级
-
- if (!string.IsNullOrWhiteSpace(password) && password.Contains("|"))
- {
- var sp = password.Split('|');
- pwdLevel = sp[1];
- password = sp[0];
- }
-
- var strDate = DateTime.Now.AddYears(3).ToString("000012ddMMyy").StrAddSpan();//命令有效截止时间
- if (specialControlCode == "1D" || modelCode == "SZBD_DDZY1225")
- strDate = "FF FF FF FF FF FF";
- var strP = password.StrAddSpan().StrReverseOrder();
- var strSJY = " " + pwdLevel + " " + strP + " 01 00 00 00 " + code + " 00 " + strDate;
- var dataUnit = strSJY.Replace(" ", "").StringToPairs();
- var dataList = Build645SendCommand(ammeterAddress, "1C", dataUnit);
- return dataList;
-
- //string strLen = (strSJY.Replace(" ", "").Length / 2).ToString("X2");
- //string strReturn = "68 " + address.StrAddSpan().StrReverseOrder() + " 68 1C " + strLen + " " + strSJY.StrAddHex33() + " ";
- //string strSum = strReturn.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries).Select(i => Convert.ToInt32(i, 16)).Sum().ToString("X");
- //strReturn += strSum.Substring(strSum.Length - 2) + " 16";
- //return strReturn.Split(' ').ToList();
- }
-
- ///
- /// 构建电表保电下发数据单元
- ///
- /// 电表地址
- ///
- /// true 保电 false 保电解除
- /// 型号码
- ///
- public static List BuildAmmeterLockSendDataUnit(string ammeterAddress, string password, bool state, string modelCode = "")
- {
- var code = state ? "3A" : "3B";
-
- var strDate = (code + DateTime.Now.AddDays(1).ToString("00000012ddMMyy")).StrAddSpan();
-
- if (modelCode == "SZBD_DDZY1225")
- strDate = $"{code} 00 FF FF FF FF FF FF";
-
- var strP = password.StrAddSpan().StrReverseOrder();
- var strSJY = " 02 " + strP + " 01 00 00 00 " + strDate;
-
- var dataUnit = strSJY.Replace(" ", "").StringToPairs();
- var dataList = Build645SendCommand(ammeterAddress, "1C", dataUnit);
- return dataList;
- }
-
- ///
- /// 构建电表认证下发数据单元
- ///
- /// 电表地址
- ///
- ///
- ///
- public static List BuildAmmeterIdentitySendDataUnit(string ammeterAddress, string ramDon, string maco)
- {
- var codeList = "070004FF".StringToPairs();
- codeList.Reverse();
-
- var ramDonList = ramDon.StringToPairs();
- ramDonList.Reverse();
-
- var macoList = maco.StringToPairs();
- macoList.Reverse();
-
- var dataUnit = new List();
- dataUnit.AddRange(codeList);
- dataUnit.AddRange(ramDonList);
- dataUnit.AddRange(macoList);
- var dataList = Build645SendCommand(ammeterAddress, "03", dataUnit);
- return dataList;
- }
-
- ///
- /// 构建电表清零下发数据单元
- ///
- /// 电表地址
- ///
- ///
- public static List BuildAmmeterClearSendDataUnit(string ammeterAddress, string password)
- {
- var strP = password.StrAddSpan().StrReverseOrder();
- var strSJY = " 02 " + strP + " 01 00 00 00 ";
- var dataUnit = strSJY.Replace(" ", "").StringToPairs();
- var dataList = Build645SendCommand(ammeterAddress, "1A", dataUnit);
- return dataList;
- }
-
-
- ///
- /// 构建电表读取下发数据单元
- ///
- /// 电表地址
- /// 功率读取 余额读取
- /// 数据标识
- ///
- public static List BuildAmmeterReadDataUnit(string ammeterAddress, CmdType cmdType, string dataId = "")
- {
- var dn = "";
- if (string.IsNullOrWhiteSpace(dataId))
- {
- if (cmdType == CmdType.PowerRead) dn = "04090B01";
- else if (cmdType == CmdType.BalanceRead) dn = "00900200";
- else if (cmdType == CmdType.CurrentRead) dn = "04090801";
- else if (cmdType == CmdType.WsPowerDown) dn = "0E300103";
- else if (cmdType == CmdType.ReadMeterStatus) dn = "04000503";
- else if (cmdType == CmdType.TimeSet) dn = "04010001";//主用第一套时段数据
- else if (cmdType == CmdType.ReadTimeSetMonth) dn = "04010000";//主用时区数据
- else if (cmdType == CmdType.ReadTimeSetNum) dn = "04000202";//日时段数
- }
- else
- dn = dataId;
-
- var dataUnit = dn.StringToPairs(true);
-
- var dataList = Build645SendCommand(ammeterAddress, "11", dataUnit);
- return dataList;
- }
-
- ///
- /// 构建电表修正时间下发命令
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static List BuildAmmeterCorrectionTimeSendCmd(string address,string modelCode,string ammeterAddress,string password,int port,string baudRate)
- {
- var bytesList = new List();
- if (modelCode == "PMAC9523")
- {
- var now = DateTime.Now;
- var year = (now.Year - 2000).ToString("X2").PadLeft(4, '0');
- var month = now.Month.ToString("X2").PadLeft(4, '0');
- var day = now.Day.ToString("X2").PadLeft(4, '0');
- var hour = now.Hour.ToString("X2").PadLeft(4, '0');
- var minute = now.Minute.ToString("X2").PadLeft(4, '0');
- var second = now.Second.ToString("X2").PadLeft(4, '0');
- var adress = int.Parse(ammeterAddress.Substring(ammeterAddress.Length - 3)).DecToHex().PadLeft(2,'0');
- var fm = new List() { adress, "10", "23", "35", "00", "06", "0C" };
- fm.AddRange($"{second}{minute}{hour}{day}{month}{year}".StringToPairs());
-
- var bts = fm.Select(s => s.HexToDec()).Select(s => byte.Parse(s.ToString())).ToArray();
- var getCrc = GetCRC16(bts, true).Select(s => int.Parse(s.ToString()).DecToHex().PadLeft(2,'0'));//long.Parse ?
- fm.AddRange(getCrc);
-
- var bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, fm, StopBit.Stop1, Parity.None);
- bytesList.Add(bytes);
- }
- else if (modelCode == "DTSU193")
- {
- var now = DateTime.Now;
- var year = now.Year.ToString().Substring(2);
- var month = now.Month.ToString().PadLeft(2, '0');
- var day = now.Day.ToString().PadLeft(2, '0');
- var week = ((int)now.DayOfWeek).ToString().PadLeft(2, '0');
- var hour = now.Hour.ToString().PadLeft(2, '0');
- var minute = now.Minute.ToString().PadLeft(2, '0');
- var second = now.Second.ToString().PadLeft(2, '0');
- var fm = GenerateCTCommand(ammeterAddress,$"{year}{month}{day}{week}{hour}{minute}{second}");
- var bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, fm);
- bytesList.Add(bytes);
- }
- else
- {
- var now = DateTime.Now;
- var year = now.Year.ToString().PadLeft(4, '0');
- var month = now.Month.ToString().PadLeft(2, '0');
- var day = now.Day.ToString().PadLeft(2, '0');
- var week = ((int)now.DayOfWeek).ToString().PadLeft(2, '0');
- var hour = now.Hour.ToString().PadLeft(2, '0');
- var minute = now.Minute.ToString().PadLeft(2, '0');
- var second = now.Second.ToString().PadLeft(2, '0');
-
- //组装数据域
- List dataList = new List();
- var dataMarkList = "04000101".StringToPairs(true);
- dataList.AddRange(dataMarkList);
- dataList.Add("02");
- if (string.IsNullOrEmpty(password))
- password = "000000";
- var passwordList = password.StringToPairs(true);
- dataList.AddRange(passwordList);
- dataList.AddRange("00000000".StringToPairs(true));
- dataList.AddRange($"{year}{month}{day}{week}".StringToPairs(true));
-
- var fm = Build645SendCommand(ammeterAddress, "14", dataList);
- var bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, fm);
- bytesList.Add(bytes);
-
- dataList = new List();
- dataMarkList = "04000102".StringToPairs(true);
- dataList.AddRange(dataMarkList);
- dataList.Add("02");
- dataList.AddRange(passwordList);
- dataList.AddRange("00000000".StringToPairs(true));
- dataList.AddRange($"{hour}{minute}{second}".StringToPairs(true));
- fm = Build645SendCommand(ammeterAddress, "14", dataList);
- bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, fm);
- bytesList.Add(bytes);
-
- }
- return bytesList;
- }
-
- ///
- /// 构建电表读取时段设置下发命令
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static List BuildReadMeterTimeSetSendCmd(string address, string modelCode, string ammeterAddress, string password, int port, string baudRate)
- {
- if (modelCode == "DTSU193")
- {
- return null;
- }
-
- if (modelCode == "PMAC9523")
- {
- //LogHelper.LogStr("ReadMeterTimeSet", $"表编号[{meterInfo.meter_address}]进入PMAC9523时段设置");
- var adress = int.Parse(ammeterAddress.Substring(ammeterAddress.Length - 3)).DecToHex().PadLeft(2, '0');
- var fm = new List() { adress, "03", "55", "F9", "00", "28" };
- var bts = fm.Select(s => s.HexToDec()).Select(s => byte.Parse(s.ToString())).ToArray();
- var getCrc = GetCRC16(bts, true).Select(s => int.Parse(s.ToString()).DecToHex().PadLeft(2,'0'));
- fm.AddRange(getCrc);
-
- var bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, fm, StopBit.Stop1, Parity.None);
- return new List(){ bytes };
- }
-
- var bytes1 = BuildTransparentForwardingSendCmd(address, port, baudRate,
- BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04010001"));
-
- var bytes2 = BuildTransparentForwardingSendCmd(address, port, baudRate,
- BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04010002"));
-
- var bytes3 = BuildTransparentForwardingSendCmd(address, port, baudRate,
- BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04010003"));
-
- var bytes4 = BuildTransparentForwardingSendCmd(address, port, baudRate,
- BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04010004"));
-
- var bytes9 = BuildTransparentForwardingSendCmd(address, port, baudRate,
- BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04010005"));
-
- var bytes5 = BuildTransparentForwardingSendCmd(address, port, baudRate,
- BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04020001"));
-
- var bytes6 = BuildTransparentForwardingSendCmd(address, port, baudRate,
- BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04020002"));
-
- var bytes7 = BuildTransparentForwardingSendCmd(address, port, baudRate,
- BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04020003"));
-
- var bytes8 = BuildTransparentForwardingSendCmd(address, port, baudRate,
- BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04020004"));
-
- var bytes10 = BuildTransparentForwardingSendCmd(address, port, baudRate,
- BuildAmmeterReadDataUnit(ammeterAddress, CmdType.ReadTimeSet, "04020005"));
-
-
- return new List{ bytes1, bytes2, bytes3, bytes4, bytes5, bytes6, bytes7, bytes8, bytes9, bytes10 };
- }
-
- ///
- /// 构建电表表号读取下发命令
- ///
- /// 电表地址
- ///
- ///
- public static List BuildAmmeterReadNumSendCmd(string ammeterAddress)
- {
- var dataUnit = "04000402".StringToPairs(true);
- return Build645SendCommand(ammeterAddress, "11", dataUnit);
- }
-
- ///
- /// 构建设置时段下发命令
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static List BuildAmmeterSetTimeSetSendCmd(string address,string ammeterAddress,string modelCode,int port,string baudRate, List data)
- {
- List bytesList = new List();
- if (modelCode == "DTSU193")
- {
- return null;
- }
- else if (modelCode == "PMAC9523")
- {
- var adress = int.Parse(ammeterAddress.Substring(ammeterAddress.Length - 3)).DecToHex().PadLeft(2,'0');
- //第一步启用复费率编程:寄存器64503,写数据01启动编程
- var fm = new List() { adress, "10", "FB", "F6", "00", "01", "02", "00", "01" };
- var bts = fm.Select(s => s.HexToDec()).Select(s => byte.Parse(s.ToString())).ToArray();
- var getCrc = GetCRC16(bts, true).Select(s => int.Parse(s.ToString()).DecToHex().PadLeft(2,'0'));
- fm.AddRange(getCrc);
-
- var bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, fm, StopBit.Stop1, Parity.None);
- bytesList.Add(bytes);
-
- //第二步写复费率模式:寄存器22002,写数据01固定一套费率
- fm = new List() { adress, "10", "55", "F1", "00", "01", "02", "00", "01" };
- bts = fm.Select(s => s.HexToDec()).Select(s => byte.Parse(s.ToString())).ToArray();
- getCrc = GetCRC16(bts, true).Select(s => int.Parse(s.ToString()).DecToHex().PadLeft(2,'0'));
- fm.AddRange(getCrc);
- bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, fm, StopBit.Stop1, Parity.None);
- bytesList.Add(bytes);
-
- //第三步写时段参数:寄存器22010开始,后续多少个寄存器根据时段内容来。
- var timeSetDetailList = data.FirstOrDefault().Data;
- fm = new List() { adress, "10", "55", "F9", "00" };
- //寄存器个数
- var timeNum = timeSetDetailList.Sum(o => o.Times.Count);
- fm.Add($"{timeNum * 2 + 1:X2}");
- //数据长度
- fm.Add($"{(timeNum * 2 + 1) * 2:X2}");
-
- //时段个数
- fm.Add("00");
- fm.Add($"{timeNum:X2}");
- Dictionary setDic = new Dictionary();
- int rate = 0;
- foreach (var item in timeSetDetailList)
- {
- int.TryParse(item.Rate, out rate);
- foreach (var itemItem in item.Times)
- {
- fm.Add("00");
- fm.Add($"{rate - 1:X2}");
- fm.Add("00");
- fm.Add($"{itemItem.StartTime.TakeTimeToInt():X2}");
- }
- }
- bts = fm.Select(s => s.HexToDec()).Select(s => byte.Parse(s.ToString())).ToArray();
- getCrc = GetCRC16(bts, true).Select(s => int.Parse(s.ToString()).DecToHex().PadLeft(2,'0'));
- fm.AddRange(getCrc);
- bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, fm, StopBit.Stop1, Parity.None);
- bytesList.Add(bytes);
- }
- else
- {
- #region 采用TimeSet方法设置 弃用
- //List fm = null;
- //SendInfo sendInfo = null;
- //List tempSi = new List();
- ////判断是否需要进入编程模式,获取编程模式指令
- //var pm = ProgramModelConfig.ProgramModels.FirstOrDefault(n => n.BrandName == meterInfo.brand_name
- //&& n.Model == meterInfo.model_name);
- //if (pm != null)
- //{
- // if (pm.IsEnter)
- // {
- // //编程指令
- // var bccmd= pm.cmdData;
- // //替换表地址
- // var addressList= Protocol.QGDW3761.DataTypeConvert.CutStr(meterInfo.meter_address, 2, true);
- // var addressstr = string.Join(" ",addressList);
- // bccmd = bccmd.Replace("AA AA AA AA AA AA", addressstr);
- // fm = bccmd.Split(' ').ToList();
-
- // //生成CRC
- // var CRC = Protocol.QGDW3761.DataTypeConvert.GetCRC(fm);
- // fm.Add(CRC);
- // fm.Add("16");
-
- // confirmResult = GatherCmdHelper.ConrTurnData(meterInfo, fm, true);
- // sendInfo = new SendInfo
- // (
- // confirmResult.msa,
- // confirmResult.cmd16,
- // MeterType.Ammeter,
- // CmdType.ProgramModel,
- // null,
- // sDto
- // );
- // si.Add(sendInfo);
- // }
- // //年时区数
- // int yearTimeZoneCount = 0;
- // //日时段数
- // int dayTimeZoneCount = 0;
- // //费率
- // int rate = 0;
- // //发送两套时区
- // for (int j = 1; j <= 2; j++)
- // {
- // //发送时区表数据
- // var timeZoneData = GenerateTimeZone(sDto);
- // yearTimeZoneCount = timeZoneData.Count / 3;
- // fm = GenerateCTCommand($"040{j}0000", string.Join("", timeZoneData));
- // confirmResult = GatherCmdHelper.ConrTurnData(meterInfo, fm, true);
- // sendInfo = new SendInfo
- // (
- // confirmResult.msa,
- // confirmResult.cmd16,
- // MeterType.Ammeter,
- // CmdType.SetTimeSet,
- // null,
- // sDto
- // );
- // tempSi.Add(sendInfo);
- // //发送日时段数据
- // for (int i = 1; i <= sDto.data.Count; i++)
- // {
- // var dayTimeZone = GenerateDayTimeZone(sDto.data[i - 1].data);
-
- // fm = GenerateCTCommand($"040{j}000{i}", string.Join("", dayTimeZone));
- // confirmResult = GatherCmdHelper.ConrTurnData(meterInfo, fm, true);
- // sendInfo = new SendInfo
- // (
- // confirmResult.msa,
- // confirmResult.cmd16,
- // MeterType.Ammeter,
- // CmdType.SetTimeSet,
- // null,
- // sDto
- // );
- // tempSi.Add(sendInfo);
-
- // //计算日时段数
- // var dz = dayTimeZone.Count / 3;
- // if (dz > dayTimeZoneCount) dayTimeZoneCount = dz;
- // //计算费率
-
- // foreach(var detail in sDto.data[i - 1].data)
- // {
- // int rt = Convert.ToInt32(detail.rate);
- // if (rt > rate) rate = rt;
- // }
-
-
- // }
- // }
-
- // #region 年时区数(NN)
- // fm = GenerateCTCommand($"04000201", yearTimeZoneCount.ToString().PadLeft(2, '0'));
- // confirmResult = GatherCmdHelper.ConrTurnData(meterInfo, fm, true);
- // sendInfo = new SendInfo
- // (
- // confirmResult.msa,
- // confirmResult.cmd16,
- // MeterType.Ammeter,
- // CmdType.SetTimeSet,
- // null,
- // sDto
- // );
- // si.Add(sendInfo);
- // #endregion
- // #region 日时段数据(NN)
- // fm = GenerateCTCommand($"04000202", sDto.data.Count.ToString().PadLeft(2, '0'));
- // confirmResult = GatherCmdHelper.ConrTurnData(meterInfo, fm, true);
- // sendInfo = new SendInfo
- // (
- // confirmResult.msa,
- // confirmResult.cmd16,
- // MeterType.Ammeter,
- // CmdType.SetTimeSet,
- // null,
- // sDto
- // );
- // si.Add(sendInfo);
- // #endregion
- // #region 日时段数(每日切换数)(NN)
- // fm = GenerateCTCommand($"04000203", dayTimeZoneCount.ToString().PadLeft(2, '0'));
- // confirmResult = GatherCmdHelper.ConrTurnData(meterInfo, fm, true);
- // sendInfo = new SendInfo
- // (
- // confirmResult.msa,
- // confirmResult.cmd16,
- // MeterType.Ammeter,
- // CmdType.SetTimeSet,
- // null,
- // sDto
- // );
- // si.Add(sendInfo);
- // #endregion
- // #region 费率数(NN)
- // fm = GenerateCTCommand($"04000204", rate.ToString().PadLeft(2, '0'));
- // confirmResult = GatherCmdHelper.ConrTurnData(meterInfo, fm, true);
- // sendInfo = new SendInfo
- // (
- // confirmResult.msa,
- // confirmResult.cmd16,
- // MeterType.Ammeter,
- // CmdType.SetTimeSet,
- // null,
- // sDto
- // );
- // si.Add(sendInfo);
- // #endregion
- // si.AddRange(tempSi);
-
- // tempSi.Clear();
- // // si[si.Count - 1].cmdType = CmdType.SetTimeSet;//取最后一条指令的结果返回
- //}
-
- #endregion
- }
- return bytesList;
- }
-
- ///
- /// 构建645协议下发命令
- ///
- /// 电表地址
- /// 控制码
- /// 数据域 发送方按字节进行加33处理,接收方按字节减33
- ///
- public static List Build645SendCommand(string ammeterAddress, string controlCode, List