From de1654327fb1c1a62406f5350a8237eef8015aa5 Mon Sep 17 00:00:00 2001 From: Dai Mr <1822802785@qq.com> Date: Thu, 27 Feb 2025 17:02:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8D=8F=E8=AE=AE=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EnergySystem/Dto/EquitDubgInput.cs | 24 + .../EnergySystem/EnergySystemAppService.cs | 102 +++- .../BuildSendDatas/Build3761SendData.cs | 576 ++++++++++++------ .../BuildSendDatas/Build645SendData.cs | 107 +++- .../Enums/ComandCodeEnum.cs | 21 + .../Models/SetAmmeterJFPGEntity.cs | 26 + .../Abstracts/BaseProtocolPlugin.cs | 37 +- .../StandardProtocolPlugin.cs | 21 + 8 files changed, 691 insertions(+), 223 deletions(-) create mode 100644 src/JiShe.CollectBus.Application.Contracts/EnergySystem/Dto/EquitDubgInput.cs create mode 100644 src/JiShe.CollectBus.Common/Enums/ComandCodeEnum.cs create mode 100644 src/JiShe.CollectBus.Common/Models/SetAmmeterJFPGEntity.cs diff --git a/src/JiShe.CollectBus.Application.Contracts/EnergySystem/Dto/EquitDubgInput.cs b/src/JiShe.CollectBus.Application.Contracts/EnergySystem/Dto/EquitDubgInput.cs new file mode 100644 index 0000000..9342c42 --- /dev/null +++ b/src/JiShe.CollectBus.Application.Contracts/EnergySystem/Dto/EquitDubgInput.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.EnergySystem.Dto +{ + public class EquitDubgInput: BaseInput + { + public string ItemCode { get; set; } + public int FocusID { get; set; } + public string Data { get; set; } + /// + /// 表计类型 + /// 电表= 1,水表= 2,燃气表= 3,热能表= 4, + /// + public int MeterType { get; set; } + + public bool IsManual { get; set; } = true; + + public string TaskId { get; set; } + } +} diff --git a/src/JiShe.CollectBus.Application/EnergySystem/EnergySystemAppService.cs b/src/JiShe.CollectBus.Application/EnergySystem/EnergySystemAppService.cs index 5465ab3..9c4b653 100644 --- a/src/JiShe.CollectBus.Application/EnergySystem/EnergySystemAppService.cs +++ b/src/JiShe.CollectBus.Application/EnergySystem/EnergySystemAppService.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Net; using System.Text; using System.Threading.Tasks; +using DeviceDetectorNET.Class.Device; using DotNetCore.CAP; using JiShe.CollectBus.Common.BuildSendDatas; using JiShe.CollectBus.Common.Enums; @@ -18,6 +19,7 @@ using MassTransit; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Volo.Abp.Domain.Repositories; +using YamlDotNet.Core; namespace JiShe.CollectBus.EnergySystem { @@ -191,6 +193,101 @@ namespace JiShe.CollectBus.EnergySystem return result; } + [HttpPost("Handmould/EquitDubg")] + public async Task EquitDubg(EquitDubgInput input) + { + var result = new BaseResultDto(); + + try + { + byte[] bytes = null; + var address = $"{input.AreaCode}{input.Address}"; + bool isManual = !input.AreaCode.Equals("5110");//低功耗集中器不是长连接,在连接的那一刻再发送 + + switch (input.ItemCode) + { + case "01_1": + bytes = Build3761SendData.BuildConrRebootSendCmd(address); + break; + case "0C_2": + bytes = Build3761SendData.BuildTerminalCalendarClockSendCmd(address); + break; + case "04_3": + if (string.IsNullOrWhiteSpace(input.Data)) + { + result.Status = false; + result.Msg = "传入参数错误"; + return result; + } + var communicationParametersSetData = JsonConvert.DeserializeObject(input.Data); + var masterIPAndPortArr = communicationParametersSetData.MasterIPandPort.Split(':'); + var masterIP = masterIPAndPortArr[0]; + var materPort = masterIPAndPortArr[1]; + if (!masterIP.IsValidIPv4() || !materPort.IsValidPort()) + { + result.Status = false; + result.Msg = "主站IP和端口格式错误"; + return result; + } + var backupIPAndPortArr = communicationParametersSetData.BackupIPandPort.Split(':'); + var backupIP = backupIPAndPortArr[0]; + var backupPort = backupIPAndPortArr[1]; + if (!backupIP.IsValidIPv4() || !backupPort.IsValidPort()) + { + result.Status = false; + result.Msg = "主站IP和端口格式错误"; + return result; + } + + bytes = Build3761SendData.BuildCommunicationParametersSetSendCmd(address, masterIP, materPort, + backupIP, backupPort, communicationParametersSetData.APN); + break; + case "05_31": + bytes = Build3761SendData.BuildConrCheckTimeSendCmd(address, DateTime.Now, isManual); + break; + case "0A_10": + if (string.IsNullOrWhiteSpace(input.Data)) + { + result.Status = false; + result.Msg = "传入参数错误"; + return result; + } + var pnList = input.Data.Split(',').Select(int.Parse).ToList(); + bytes = Build3761SendData.BuildAmmeterParameterReadingSendCmd(address, pnList); + break; + default: + break; + } + + if (bytes != null) + { + await _capBus.PublishAsync(ProtocolConst.SubscriberIssuedEventName, new IssuedEventMessage + { + //ClientId = messageReceived.ClientId, + DeviceNo = address, + Message = bytes, + Type = IssuedEventType.Data, + MessageId = NewId.NextGuid().ToString() + }); + + if (isManual) + { + //等待设备返回结果 + } + } + } + catch (Exception ex) + { + result.Status = false; + result.Msg = ex.Message; + } + + result.Status = true; + result.Msg = "操作成功"; + return result; + } + + /// /// 通讯参数设置 AFN:04 FN:3 /// @@ -275,8 +372,9 @@ namespace JiShe.CollectBus.EnergySystem { var result = new BaseResultDto(); var address = $"{input.AreaCode}{input.Address}"; + bool isManual = !input.AreaCode.Equals("5110");//低功耗集中器不是长连接,在连接的那一刻再发送 - var bytes = Build3761SendData.BuildConrCheckTimeSendCmd(address,DateTime.Now); + var bytes = Build3761SendData.BuildConrCheckTimeSendCmd(address,DateTime.Now, isManual); await _capBus.PublishAsync(ProtocolConst.SubscriberIssuedEventName, new IssuedEventMessage { //ClientId = messageReceived.ClientId, @@ -445,7 +543,7 @@ namespace JiShe.CollectBus.EnergySystem }).ToList() }).ToList() }).ToList(); - var bytesList = Build3761SendData.BuildAmmeterSetTimeSetSendCmd(address, ammeter.Code, ammeter.Address, + var bytesList = Build3761SendData.BuildAmmeterSetTimeSetSendCmd(address,ammeter.Address,ammeter.Password, ammeter.PortNumber ?? 2, ammeter.BaudRate, timeDataList); foreach (var bytes in bytesList) diff --git a/src/JiShe.CollectBus.Common/BuildSendDatas/Build3761SendData.cs b/src/JiShe.CollectBus.Common/BuildSendDatas/Build3761SendData.cs index 224c242..9bed5b8 100644 --- a/src/JiShe.CollectBus.Common/BuildSendDatas/Build3761SendData.cs +++ b/src/JiShe.CollectBus.Common/BuildSendDatas/Build3761SendData.cs @@ -1,12 +1,14 @@ using JiShe.CollectBus.Common.Enums; using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.Common.Models; +using Nito.AsyncEx; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Volo.Abp.Domain.Entities; +using static System.Runtime.InteropServices.JavaScript.JSType; namespace JiShe.CollectBus.Common.BuildSendDatas { @@ -156,7 +158,7 @@ namespace JiShe.CollectBus.Common.BuildSendDatas return new List { bytes1, bytes2, bytes3, bytes4, bytes5, bytes6, bytes7, bytes8, bytes9, bytes10 }; } - + #region 旧版 /// /// 构建设置时段下发命令 /// @@ -167,185 +169,320 @@ namespace JiShe.CollectBus.Common.BuildSendDatas /// /// /// - public static List BuildAmmeterSetTimeSetSendCmd(string address, string ammeterAddress, string modelCode, int port, string baudRate, List data) + //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; + //} + #endregion + + /// + /// 构建时段设置下发命令 + /// + /// + /// + /// + /// + /// + /// + /// + public static List BuildAmmeterSetTimeSetSendCmd(string address, string ammeterAddress,string password,int port, string baudRate, List timeSetDetails) { List bytesList = new List(); - if (modelCode == "DTSU193") + //Cmd写死 programmodel.json + string cmd = ""; + var generateBCDataUnit = Build645SendData.BuildAmmeterGenerateBCCommand(ComandCodeEnum.SpecialMeter_A, ammeterAddress, cmd, password, + "", ""); + var bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, generateBCDataUnit, StopBit.Stop1, Parity.None); + bytesList.Add(bytes); + + + List listdata = new List(); + List templistdata = new List(); + + #region 排序 + var timeSets = timeSetDetails; + Dictionary dicTsDetails = new Dictionary(); + foreach (var timeSet in timeSets) { - return null; + int firstMonty = timeSet.Months[0]; + if (!dicTsDetails.Keys.Contains(firstMonty)) + dicTsDetails.Add(firstMonty, timeSet); } - else if (modelCode == "PMAC9523") + + var sortKeys = dicTsDetails.Keys.OrderBy(n => n).ToList(); + List orderTsDetails = new List(); + foreach (var key in sortKeys) { - var dataUnitList = Build645SendData.BuildPMAC9523AmmeterSetTimeSetSendDataUnit(ammeterAddress, data); - foreach (var dataUnit in dataUnitList) + orderTsDetails.Add(dicTsDetails[key]); + } + + timeSetDetails = orderTsDetails; + + #endregion + + //年时区数 + int yearTimeZoneCount = 0; + //日时段数/日切换数 + int dayTimeZoneCount = 0; + //费率 + int rate = 0; + for (int j = 1; j <= 2; j++) + { + + SetAmmeterJFPGEntity setJFPGTool = new SetAmmeterJFPGEntity(); + setJFPGTool.ComandCode = ComandCodeEnum.SpecialMeter_B; + //发送时区表数据 + var timeZoneData = GenerateTimeZone(timeSetDetails); + setJFPGTool.DataMark = $"040{j}0000"; + setJFPGTool.Data = timeZoneData; + templistdata.Add(setJFPGTool); + + yearTimeZoneCount = timeZoneData.Length / 6; + + //发送日时段数据 + for (int i = 1; i <= timeSets.Count; i++) { - var bytes = BuildTransparentForwardingSendCmd(address, port, baudRate, dataUnit, StopBit.Stop1, Parity.None); - bytesList.Add(bytes); + setJFPGTool = new SetAmmeterJFPGEntity(); + + setJFPGTool.ComandCode = ComandCodeEnum.SpecialMeter_B; + var dayTimeZone = GenerateDayTimeZone(timeSets[i - 1].Data); + var dataMark = $"040{j}000{i}"; + setJFPGTool.DataMark = dataMark; + setJFPGTool.Data = dayTimeZone; + templistdata.Add(setJFPGTool); + + //计算日时段数 + var dz = dayTimeZone.Length / 6; + if (dz > dayTimeZoneCount) dayTimeZoneCount = dz; + //计算费率 + foreach (var detail in timeSets[i - 1].Data) + { + var rt = Convert.ToInt32(detail.Rate); + if (rt > rate) rate = rt; + } } } - else + #region 年时区数(NN) + listdata.Add(new SetAmmeterJFPGEntity() { - #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(); + Data = yearTimeZoneCount.ToString().PadLeft(2, '0'), + DataMark = "04000201", + ComandCode = ComandCodeEnum.SpecialMeter_B + }); + #endregion + #region 日时段数(NN) + listdata.Add(new SetAmmeterJFPGEntity() + { + Data = timeSets.Count.ToString().PadLeft(2, '0'), + DataMark = "04000202", + ComandCode = ComandCodeEnum.SpecialMeter_B + }); + #endregion + #region 日切换数(NN) + listdata.Add(new SetAmmeterJFPGEntity() + { + Data = dayTimeZoneCount.ToString().PadLeft(2, '0'), + DataMark = "04000203", + ComandCode = ComandCodeEnum.SpecialMeter_B + }); + #endregion + #region 费率数(NN) + listdata.Add(new SetAmmeterJFPGEntity() + { + Data = rate.ToString().PadLeft(2, '0'), + DataMark = "04000204", + ComandCode = ComandCodeEnum.SpecialMeter_B + }); + #endregion - // //生成CRC - // var CRC = Protocol.QGDW3761.DataTypeConvert.GetCRC(fm); - // fm.Add(CRC); - // fm.Add("16"); + listdata.AddRange(templistdata); + templistdata.Clear(); - // 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 + foreach (var item in listdata) + { + var timeSetDataUnit = + Build645SendData.BuildAmmeterTimeSetSendDataUnit(ammeterAddress, password, item.DataMark, + item.Data); + var timeSetBytes = BuildTransparentForwardingSendCmd(address, port, baudRate, timeSetDataUnit, StopBit.Stop1, Parity.None); + bytesList.Add(timeSetBytes); } + return bytesList; } - /// /// 构建电表参数设置-下发命令 /// @@ -1002,18 +1139,29 @@ namespace JiShe.CollectBus.Common.BuildSendDatas /// /// /// + /// /// - public static byte[] BuildConrCheckTimeSendCmd(string address, DateTime time) + public static byte[] BuildConrCheckTimeSendCmd(string address, DateTime time,bool isManual) { - 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(); + List dataUnit; + if (isManual) + { + 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); + dataUnit = strTimeFm.Replace(" ", "").StringToPairs(); + } + else + { + dataUnit = new List(){"EE","EE","EE","EE"}; + } - 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.控制命令, @@ -1644,6 +1792,88 @@ namespace JiShe.CollectBus.Common.BuildSendDatas return new List() { pFC, seconds, minutes, hours, day, delayTime.ToString().PadLeft(2, '0') }; } + /// + /// 生成时区表数据 + /// + /// + /// + private static string GenerateTimeZone(List datas) + { + var fm = new List(); + var timeSets = datas; + for (int i = 1; i <= timeSets.Count; i++) + { + var item = timeSets[i - 1]; + var months = item.Months.ToList().OrderBy(n => n).ToArray(); + for (int j = 0; j < months.Length; j++) + { + + if (j == 0) + { + fm.Add($"{months[j].ToString().PadLeft(2, '0')}01{i.ToString().PadLeft(2, '0')}"); + } + else + { + if (months[j] - months[j - 1] > 1) + { + fm.Add($"{months[j].ToString().PadLeft(2, '0')}01{i.ToString().PadLeft(2, '0')}"); + } + } + } + } + fm = fm.OrderByDescending(n => Convert.ToInt32(n)).ToList(); + + + return string.Join("", fm.ToArray()); + } + + /// + /// 生成日时段数据 + /// + /// + /// + private static string GenerateDayTimeZone(List sDto) + { + var fm = new List(); + foreach (var item in sDto) + { + var sts = item.Times.Select(n => n.StartTime).OrderBy(n => n).ToList(); + for (int j = 0; j < sts.Count; j++) + { + + fm.Add($"{sts[j].Replace(":", "")}{item.Rate.PadLeft(2, '0')}"); + + } + } + + fm = fm.OrderByDescending(n => Convert.ToInt32(n)).ToList(); + //处理跨天的情况 23:00-7:00 这种需要拆分为2条 需要添加一条00:00 记录 23:00 00:00 + List stTimes = new List(); + // List etTimes = new List(); + foreach (var item in sDto) + { + stTimes.AddRange(item.Times.Select(n => n.StartTime).OrderBy(n => n).ToList()); + // etTimes.AddRange(item.times.Select(n => n.endTime).OrderByDescending(n => n).ToList()); + + } + stTimes = stTimes.OrderBy(n => n).ToList(); + if (!stTimes[0].Equals("00:00")) + { + //查出最大时间的费率 + var rate = "0"; + foreach (var item in sDto) + { + if (item.Times.Select(n => n.StartTime).Contains(stTimes[stTimes.Count - 1])) + { + rate = item.Rate; + break; + } + } + fm.Add($"{"00:00".Replace(":", "")}{rate.PadLeft(2, '0')}"); + } + return string.Join("", fm.ToArray()); + } + #endregion } diff --git a/src/JiShe.CollectBus.Common/BuildSendDatas/Build645SendData.cs b/src/JiShe.CollectBus.Common/BuildSendDatas/Build645SendData.cs index d3df6cb..d51810c 100644 --- a/src/JiShe.CollectBus.Common/BuildSendDatas/Build645SendData.cs +++ b/src/JiShe.CollectBus.Common/BuildSendDatas/Build645SendData.cs @@ -3,6 +3,8 @@ using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.Common.Models; using System; using System.Collections.Generic; +using System.Data; +using System.Reflection.Metadata; using static System.Runtime.InteropServices.JavaScript.JSType; namespace JiShe.CollectBus.Common.BuildSendDatas @@ -215,32 +217,90 @@ namespace JiShe.CollectBus.Common.BuildSendDatas /// public static List BuildAmmeterTimeSetSendDataUnit(string ammeterAddress,string password, string dataMark,string data, string s_operator= "00000001") { - List dataUnit = BuildAmmeterTimeSetDataUnit(password, dataMark, data); + var datas = data.Split(' ').ToList(); + datas.Reverse(); + List dataUnit = BuildAmmeterTimeSetDataUnit(password, dataMark, datas); - var dataList = Build645SendCommand(ammeterAddress, "14", dataUnit); + List dataList = new List(); + dataList.Add("68"); + dataList.AddRange(ammeterAddress.PadLeft(12, '0').StringToPairs(true)); + dataList.Add("68"); + dataList.Add("14");//控制码 + //transpond.Operator = "01000000"; + dataList.Add(dataUnit.Count.DecToHex().PadLeft(2, '0'));//数据域长度 + dataList.AddRange(dataUnit); + var csSum = HexStringExtensions.GetCRC(dataList);// GetCheckSumsHexString(string.Join("", content).StringToHexByte()); + dataList.Add(csSum); + dataList.Add("16"); 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() + /// + /// 工具生成指令 F10 103 + /// + /// + /// + /// + public static List GenerateContent(string ammeterAddress, string cmd) { - return null; + //替换表计地址 + var meterAddress = ammeterAddress.PadLeft(12, '0').StringToPairs(true); + var cmdArr = cmd.Replace(" ", "").StringToPairs(true); + cmdArr.RemoveRange(1, 6); + cmdArr.InsertRange(1, meterAddress); + //替换校验码 + var csSum = HexStringExtensions.GetCRC(cmdArr); //GetCheckSumsHexString(string.Join("", cmdArr.Take(cmdArr.Count - 2)).StringToHexByte()); + cmdArr.RemoveRange(cmdArr.Count - 2, 2); + cmdArr.Add(csSum); + + cmdArr.Add("16"); + + return cmdArr; + } + + /// + /// AFN16_F106 + /// + /// + /// + /// + /// + /// + /// + /// + public static List BuildAmmeterGenerateBCCommand(ComandCodeEnum comandCodeEnum,string ammeterAddress,string cmd, string password, string dataMark, string data) + { + List content = new List(); + var meterAddress = ammeterAddress.PadLeft(12, '0').StringToPairs(true); + if (comandCodeEnum == ComandCodeEnum.SpecialMeter_A) + { + //编程指令 + //TODO:替换表计地址 + var cmdArr = cmd.Replace(" ", "").StringToPairs(); + cmdArr.RemoveRange(1, 6); + cmdArr.InsertRange(1, meterAddress); + //TODO:替换校验码 + var csSum = HexStringExtensions.GetCRC(cmdArr); //GetCheckSumsHexString(string.Join("", cmdArr).StringToHexByte()); + cmdArr.Add(csSum); + cmdArr.Add("16"); + return cmdArr; + } + else if(comandCodeEnum == ComandCodeEnum.SpecialMeter_B) + { + content.Add("68"); + content.AddRange(meterAddress); + content.Add("68"); + content.Add("14");//控制码 + //transpond.Operator = "01000000"; + var datas = data.StringToPairs(true); + var dataUnit = BuildAmmeterTimeSetDataUnit(password, dataMark, datas); + content.Add(dataUnit.Count.DecToHex().PadLeft(2, '0'));//数据域长度 + content.AddRange(dataUnit); + var csSum = HexStringExtensions.GetCRC(content); //GetCheckSumsHexString(string.Join("", content).StringToHexByte()); + content.Add(csSum); + content.Add("16"); + } + return content; } @@ -644,7 +704,6 @@ namespace JiShe.CollectBus.Common.BuildSendDatas return fm; } - private static List GenerateCTCommand(string ammeterAddress, string data) { List fm = new List(); @@ -715,7 +774,7 @@ namespace JiShe.CollectBus.Common.BuildSendDatas /// /// /// - private static List BuildAmmeterTimeSetDataUnit(string password, string dataMark, string data, string s_operator = "00000001") + private static List BuildAmmeterTimeSetDataUnit(string password, string dataMark, List datas, string s_operator = "00000001") { List dataUnit = new List(); if (string.IsNullOrWhiteSpace(password)) @@ -744,8 +803,6 @@ namespace JiShe.CollectBus.Common.BuildSendDatas dataUnit.Add(item); } //TODO:数据体 DATA - var datas = data.Split(' ').ToList(); - datas.Reverse(); dataUnit.AddRange(datas); return dataUnit; } diff --git a/src/JiShe.CollectBus.Common/Enums/ComandCodeEnum.cs b/src/JiShe.CollectBus.Common/Enums/ComandCodeEnum.cs new file mode 100644 index 0000000..7ed210a --- /dev/null +++ b/src/JiShe.CollectBus.Common/Enums/ComandCodeEnum.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Common.Enums +{ + public enum ComandCodeEnum + { + /// + /// 特殊表第一个指令 + /// + SpecialMeter_A, + /// + /// 特殊表第二个指令 + /// + SpecialMeter_B + + } +} diff --git a/src/JiShe.CollectBus.Common/Models/SetAmmeterJFPGEntity.cs b/src/JiShe.CollectBus.Common/Models/SetAmmeterJFPGEntity.cs new file mode 100644 index 0000000..12f5dfb --- /dev/null +++ b/src/JiShe.CollectBus.Common/Models/SetAmmeterJFPGEntity.cs @@ -0,0 +1,26 @@ +using JiShe.CollectBus.Common.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Common.Models +{ + public class SetAmmeterJFPGEntity + { + public ComandCodeEnum ComandCode { get; set; } + /// + /// 数据标识 + /// + public string DataMark { get; set; } + /// + /// 数据 + /// + public string Data { get; set; } + /// + /// 自定义指令 + /// + public string Cmd { get; set; } + } +} diff --git a/src/JiShe.CollectBus.Protocol.Contracts/Abstracts/BaseProtocolPlugin.cs b/src/JiShe.CollectBus.Protocol.Contracts/Abstracts/BaseProtocolPlugin.cs index 67c9da4..6f504f5 100644 --- a/src/JiShe.CollectBus.Protocol.Contracts/Abstracts/BaseProtocolPlugin.cs +++ b/src/JiShe.CollectBus.Protocol.Contracts/Abstracts/BaseProtocolPlugin.cs @@ -7,20 +7,10 @@ using JiShe.CollectBus.MessageReceiveds; using JiShe.CollectBus.Protocol.Contracts.Interfaces; using JiShe.CollectBus.Protocols; using Microsoft.Extensions.Logging; -using System.Linq; using JiShe.CollectBus.Protocol.Contracts.Models; using Volo.Abp.Domain.Repositories; -using System; -using System.Runtime.CompilerServices; -using MassTransit.Internals.GraphValidation; -using JiShe.CollectBus.Devices; using JiShe.CollectBus.Common.BuildSendDatas; using JiShe.CollectBus.Protocol.Contracts.AnalysisData; -using Newtonsoft.Json.Linq; -using System.Diagnostics.Metrics; -using Newtonsoft.Json; -using TouchSocket.Core; -using Volo.Abp.Caching; using Microsoft.Extensions.DependencyInjection; namespace JiShe.CollectBus.Protocol.Contracts.Abstracts @@ -142,9 +132,10 @@ namespace JiShe.CollectBus.Protocol.Contracts.Abstracts /// /// 解析确认或否认数据 /// - /// + /// + /// /// - public virtual async Task AnalyzeAnswerDataAsync(MessageReceivedHeartbeat messageReceived, Action? sendAction = null) + public virtual async Task AnalyzeAnswerDataAsync(MessageReceived messageReceived, Action? sendAction = null) { var hexStringList = messageReceived.MessageHexString.StringToPairs(); var fn = hexStringList.GetAnalyzeValue(CommandChunkEnum.FN); @@ -160,7 +151,7 @@ namespace JiShe.CollectBus.Protocol.Contracts.Abstracts /// /// /// - public virtual List AnalyzeAmmeterParameterReadingDataAsync(MessageReceivedHeartbeat messageReceived, Action? sendAction = null) + public virtual List AnalyzeAmmeterParameterReadingDataAsync(MessageReceived messageReceived, Action? sendAction = null) { var hexDatas = GetHexDatas(messageReceived.MessageHexString); @@ -241,7 +232,7 @@ namespace JiShe.CollectBus.Protocol.Contracts.Abstracts /// 报文 /// 发送委托 /// - public virtual CurrentPositiveActiveEnergyAnalyze AnalyzeActivePowerIndicationReadingDataAsync(MessageReceivedHeartbeat messageReceived, Action? sendAction = null) + public virtual CurrentPositiveActiveEnergyAnalyze AnalyzeActivePowerIndicationReadingDataAsync(MessageReceived messageReceived, Action? sendAction = null) { var hexDatas = GetHexDatas(messageReceived.MessageHexString); @@ -287,7 +278,7 @@ namespace JiShe.CollectBus.Protocol.Contracts.Abstracts /// /// /// - public virtual void AnalyzeDailyFrozenReadingDataAsync(MessageReceivedHeartbeat messageReceived, Action? sendAction = null) + public virtual void AnalyzeDailyFrozenReadingDataAsync(MessageReceived messageReceived, Action? sendAction = null) { var hexDatas = GetHexDatas(messageReceived.MessageHexString); //附录A.20 日月年 @@ -351,7 +342,7 @@ namespace JiShe.CollectBus.Protocol.Contracts.Abstracts /// /// /// //F25ReadingAnalyze - public virtual Analyze3761Data AnalyzeF25ReadingDataAsync(MessageReceivedHeartbeat messageReceived, Action? sendAction = null) + public virtual Analyze3761Data AnalyzeF25ReadingDataAsync(MessageReceived messageReceived, Action? sendAction = null) { var hexDatas = GetHexDatas(messageReceived.MessageHexString); //A.15 分时日月年 @@ -504,7 +495,7 @@ namespace JiShe.CollectBus.Protocol.Contracts.Abstracts /// /// /// //TerminalVersionInfoAnalyze - public virtual Analyze3761Data AnalyzeTerminalVersionInfoReadingDataAsync(MessageReceivedHeartbeat messageReceived, Action? sendAction = null) + public virtual Analyze3761Data AnalyzeTerminalVersionInfoReadingDataAsync(MessageReceived messageReceived, Action? sendAction = null) { var hexDatas = GetHexDatas(messageReceived.MessageHexString); @@ -555,7 +546,7 @@ namespace JiShe.CollectBus.Protocol.Contracts.Abstracts /// /// /// - public virtual Analyze3761Data AnalyzeATypeOfDataItems49ReadingDataAsync(MessageReceivedHeartbeat messageReceived, Action? sendAction = null) + public virtual Analyze3761Data AnalyzeATypeOfDataItems49ReadingDataAsync(MessageReceived messageReceived, Action? sendAction = null) { var hexDatas = GetHexDatas(messageReceived.MessageHexString); @@ -600,7 +591,7 @@ namespace JiShe.CollectBus.Protocol.Contracts.Abstracts /// /// - public virtual void AnalyzeTerminalTimeReadingDataAsync(MessageReceivedHeartbeat messageReceived, Action? sendAction = null) + public virtual void AnalyzeTerminalTimeReadingDataAsync(MessageReceived messageReceived, Action? sendAction = null) { var hexDatas = GetHexDatas(messageReceived.MessageHexString); var time = Appendix.Appendix_A1(hexDatas.Take(6).ToList()); @@ -612,7 +603,7 @@ namespace JiShe.CollectBus.Protocol.Contracts.Abstracts /// /// /// - public virtual TB3761FN AnalyzeReadingDataAsync(MessageReceivedHeartbeat messageReceived, + public virtual TB3761FN AnalyzeReadingDataAsync(MessageReceived messageReceived, Action? sendAction = null) { var hexStringList = messageReceived.MessageHexString.StringToPairs(); @@ -683,7 +674,7 @@ namespace JiShe.CollectBus.Protocol.Contracts.Abstracts /// /// /// - public virtual TB3761FN AnalyzeReadingTdcDataAsync(MessageReceivedHeartbeat messageReceived, + public virtual TB3761FN AnalyzeReadingTdcDataAsync(MessageReceived messageReceived, Action? sendAction = null) { @@ -808,7 +799,7 @@ namespace JiShe.CollectBus.Protocol.Contracts.Abstracts /// /// /// - public virtual async Task AnalyzeTransparentForwardingAnswerAsync(MessageReceivedHeartbeat messageReceivedEvent, Action? sendAction = null) + public virtual async Task AnalyzeTransparentForwardingAnswerAsync(MessageReceived messageReceivedEvent, Action? sendAction = null) { var hexDatas = GetHexDatas(messageReceivedEvent.MessageHexString); @@ -835,7 +826,7 @@ namespace JiShe.CollectBus.Protocol.Contracts.Abstracts /// /// /// - public virtual async Task AnalyzeTransparentForwardingAnswerResultAsync(MessageReceivedHeartbeat messageReceived, Action? sendAction = null) + public virtual async Task AnalyzeTransparentForwardingAnswerResultAsync(MessageReceived messageReceived, Action? sendAction = null) { var hexDatas = GetHexDatas(messageReceived.MessageHexString); diff --git a/src/JiShe.CollectBus.Protocol/StandardProtocolPlugin.cs b/src/JiShe.CollectBus.Protocol/StandardProtocolPlugin.cs index 8be2845..8233b99 100644 --- a/src/JiShe.CollectBus.Protocol/StandardProtocolPlugin.cs +++ b/src/JiShe.CollectBus.Protocol/StandardProtocolPlugin.cs @@ -3,7 +3,9 @@ using JiShe.CollectBus.Common.Extensions; using JiShe.CollectBus.Common.Models; using JiShe.CollectBus.MessageReceiveds; using JiShe.CollectBus.Protocol.Contracts.Abstracts; +using JiShe.CollectBus.Protocol.Contracts.Models; using JiShe.CollectBus.Protocols; +using Newtonsoft.Json.Linq; namespace JiShe.CollectBus.Protocol { @@ -21,6 +23,25 @@ namespace JiShe.CollectBus.Protocol public override Task AnalyzeAsync(MessageReceived messageReceived, Action? sendAction = null) { + var hexStringList = messageReceived.MessageHexString.StringToPairs(); + var aTuple = (Tuple)hexStringList.GetAnalyzeValue(CommandChunkEnum.A); + var afn = (int)hexStringList.GetAnalyzeValue(CommandChunkEnum.AFN); + var fn = (int)hexStringList.GetAnalyzeValue(CommandChunkEnum.FN); + if (afn == (int)AFN.请求实时数据) + { + if (Enum.IsDefined(typeof(ATypeOfDataItems), fn)) //Enum.TryParse(afn.ToString(), out ATypeOfDataItems parseResult) + { + AnalyzeReadingDataAsync(messageReceived, sendAction); + } + } + else if(afn == (int)AFN.请求历史数据) + { + if (Enum.IsDefined(typeof(IIdataTypeItems), fn)) + { + AnalyzeReadingTdcDataAsync(messageReceived, sendAction); + } + } + throw new NotImplementedException(); }