diff --git a/JiShe.CollectBus.Core/Plugins/TcpServiceReceivedPlugin.cs b/JiShe.CollectBus.Core/Plugins/TcpServiceReceivedPlugin.cs index 374ca04..2907e27 100644 --- a/JiShe.CollectBus.Core/Plugins/TcpServiceReceivedPlugin.cs +++ b/JiShe.CollectBus.Core/Plugins/TcpServiceReceivedPlugin.cs @@ -30,7 +30,7 @@ namespace JiShe.CollectBus.Core.Plugins var messageHexString = Convert.ToHexString(e.ByteBlock.Span); client.Logger.Info($"[TCP] 已从{client.GetIPPort()}接收到信息:{messageHexString}"); - + protocolPlugin?.Received(e); await e.InvokeNext(); } diff --git a/JiShe.CollectBus.Protocol.Contracts/Models/Enums.cs b/JiShe.CollectBus.Protocol.Contracts/Models/Enums.cs index 0b4a5a6..878d45c 100644 --- a/JiShe.CollectBus.Protocol.Contracts/Models/Enums.cs +++ b/JiShe.CollectBus.Protocol.Contracts/Models/Enums.cs @@ -121,7 +121,7 @@ namespace JiShe.CollectBus.Protocol.Contracts.Models /// /// 通信协议类型 数值0-255 /// - public enum ProtocolType + public enum CommunicationProtocolType { DLT6451997 = 1, 交流采样装置 = 2, diff --git a/JiShe.CollectBus.Protocol.Contracts/Models/ReqParameter.cs b/JiShe.CollectBus.Protocol.Contracts/Models/ReqParameter.cs index 1d6761d..55756cd 100644 --- a/JiShe.CollectBus.Protocol.Contracts/Models/ReqParameter.cs +++ b/JiShe.CollectBus.Protocol.Contracts/Models/ReqParameter.cs @@ -46,7 +46,7 @@ namespace JiShe.CollectBus.Protocol.Contracts.Models /// public int Port { get; set; } - public ProtocolType ProtocolType { get; set; } + public CommunicationProtocolType ProtocolType { get; set; } /// /// 通信地址 0~999999999999 /// diff --git a/JiShe.CollectBus.Protocol/StandardProtocolPlugin.cs b/JiShe.CollectBus.Protocol/StandardProtocolPlugin.cs index ccdafce..1f7a7a1 100644 --- a/JiShe.CollectBus.Protocol/StandardProtocolPlugin.cs +++ b/JiShe.CollectBus.Protocol/StandardProtocolPlugin.cs @@ -5,6 +5,7 @@ using JiShe.CollectBus.Protocol.Contracts.DependencyInjection; using JiShe.CollectBus.Protocol.Contracts.Models; using Microsoft.Extensions.Caching.Distributed; using System.Data; +using System.Net.Sockets; using TouchSocket.Sockets; namespace JiShe.CollectBus.Protocol @@ -23,6 +24,18 @@ namespace JiShe.CollectBus.Protocol private const int tPLen = 6; + static object locker = new object(); + static List MSA = new List(); + static Dictionary> usingMSA = new Dictionary>(); + + static StandardProtocolPlugin() + { + for (int i = 1; i <= 127; i++) + { + MSA.Add(i); + } + } + public override ProtocolInfo Get() { @@ -50,25 +63,431 @@ namespace JiShe.CollectBus.Protocol throw new NotImplementedException(); } + /// + /// Gets the msa. + /// + /// The mark. + /// + 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 上行命令 + + //68 + //32 00 + //32 00 + //68 + //C9 1100'1001. 控制域C。 + // D7=1, (终端发送)上行方向。 + // D6=1, 此帧来自启动站。 + // D5=0, (上行方向)要求访问位。表示终端无事件数据等待访问。 + // D4=0, 保留 + // D3~D0=9, 功能码。链路测试 + + //20 32 行政区划码 + //90 26 终端地址 + //00 主站地址和组地址标志。终端为单地址。 //3220 09 87 2 + // 终端启动的发送帧的 MSA 应为 0, 其主站响应帧的 MSA 也应为 0. + //02 应用层功能码。AFN=2, 链路接口检测 + //70 0111'0000. 帧序列域。无时间标签、单帧、需要确认。 + //00 00 信息点。DA1和DA2全为“0”时,表示终端信息点。 + //01 00 信息类。F1, 登录。 + //44 帧尾,包含用户区数据校验和 + //16 帧结束标志 + + /// + /// 解析上行命令 + /// + /// + /// + public CommandReulst? AnalysisCmd(string cmd) + { + CommandReulst? commandReulst = null; + var hexStringList = DataConvert.StringToPairs(cmd); + + if (hexStringList.Count < hearderLen) + { + return commandReulst; + } + //验证起始字符 + if (hexStringList[0] != stx || hexStringList[5] != stx) + { + return commandReulst; + } + + var lenHexStr = $"{hexStringList[2]}{hexStringList[1]}"; + var lenBin = DataConvert.HexToBin(lenHexStr); + var len = DataConvert.BinToDec(lenBin.Remove(lenBin.Length - 2)); + //验证长度 + if (hexStringList.Count - 2 != hearderLen + len) + return commandReulst; + + var userDataIndex = hearderLen; + var c = hexStringList[userDataIndex];//控制域 1字节 + userDataIndex += 1; + + var aHexList = hexStringList.Skip(userDataIndex).Take(5).ToList();//地址域 5字节 + var a = AnalysisA(aHexList); + var a3Bin = DataConvert.HexToBin(aHexList[4]).PadLeft(8, '0'); + var mSA = DataConvert.BinToDec(a3Bin.Substring(0, 7)); + userDataIndex += 5; + + var aFN = (AFN)DataConvert.HexToDec(hexStringList[userDataIndex]);//1字节 + userDataIndex += 1; + + var seq = DataConvert.HexToBin(hexStringList[userDataIndex]).PadLeft(8, '0'); + var tpV = (TpV)Convert.ToInt32(seq.Substring(0, 1)); + var fIRFIN = (FIRFIN)Convert.ToInt32(seq.Substring(1, 2)); + var cON = (CON)Convert.ToInt32(seq.Substring(3, 1)); + var prseqBin = seq.Substring(4, 4); + userDataIndex += 1; + + // (DA2 - 1) * 8 + DA1 = pn + var da1Bin = DataConvert.HexToBin(hexStringList[userDataIndex]); + var da1 = da1Bin == "0" ? 0 : da1Bin.Length; + userDataIndex += 1; + var da2 = DataConvert.HexToDec(hexStringList[userDataIndex]); + userDataIndex += 1; + var pn = da2 == 0 ? 0 : (da2 - 1) * 8 + da1; + + //(DT2*8)+DT1=fn + var dt1Bin = DataConvert.HexToBin(hexStringList[userDataIndex]); + var dt1 = dt1Bin != "0" ? dt1Bin.Length : 0; + userDataIndex += 1; + var dt2 = DataConvert.HexToDec(hexStringList[userDataIndex]); + userDataIndex += 1; + var fn = dt2 * 8 + dt1; + + //数据单元 + var datas = hexStringList.Skip(userDataIndex).Take(len + hearderLen - userDataIndex).ToList(); + + //EC + //Tp + commandReulst = new CommandReulst() + { + A = a, + MSA = mSA, + AFN = aFN, + Seq = new Seq() + { + TpV = tpV, + FIRFIN = fIRFIN, + CON = cON, + PRSEQ = DataConvert.BinToDec(prseqBin), + }, + CmdLength = len, + Pn = pn, + Fn = fn, + HexDatas = datas + }; + + return commandReulst; + } + + /// + /// 解析地址 + /// + /// + /// + private string AnalysisA(List aHexList) + { + var a1 = aHexList[1] + aHexList[0]; + var a2 = aHexList[3] + aHexList[2]; + var a2Dec = DataConvert.HexToDec(a2); + var a3 = aHexList[4]; + var a = $"{a1}{a2Dec.ToString().PadLeft(5, '0')}"; + return a; + } + + /// + /// 解析上行命令数据包 + /// + /// + public void AnalysisData(CommandReulst commandReulst) + { + switch (commandReulst.AFN) + { + case AFN.确认或否认: + //commandReulst.fn + //1:全部确认 + //2:全部否认 + //3:按数据单元表示确认和否认 + //4 硬件安全认证错误应答 + break; + case AFN.复位: + break; + case AFN.链路接口检测: + AnalysisAFN02(commandReulst); + break; + case AFN.中继站命令: + break; + case AFN.设置参数: + break; + case AFN.控制命令: + break; + case AFN.身份认证及密钥协商: + break; + case AFN.备用: + break; + case AFN.请求被级联终端主动上报: + break; + case AFN.请求终端配置: + break; + case AFN.查询参数: + break; + case AFN.请求任务数据: + break; + case AFN.请求实时数据: + break; + case AFN.请求历史数据: + break; + case AFN.请求事件数据: + break; + case AFN.文件传输: + break; + case AFN.数据转发: + break; + default: + break; + } + } + + //终端启动发送帧的MSA应为零,其主站响应帧的MSA也应为零 + public void AnalysisAFN02(CommandReulst commandReulst) + { + if (commandReulst.Fn == 1) //登录 + { + Console.WriteLine($"{commandReulst.A},登录:{DateTime.Now}"); + var reqParam = new ReqParameter2() + { + AFN = AFN.确认或否认, + CMasterStationFunCode = CMasterStationFunCode.链路测试, + PRM = PRM.从动站报文, + A = commandReulst.A, + Seq = new Seq() + { + TpV = TpV.附加信息域中无时间标签, + FIRFIN = FIRFIN.单帧, + CON = CON.不需要对该帧进行确认, + PRSEQ = commandReulst.Seq.PRSEQ, + }, + MSA = commandReulst.MSA, + Pn = 0, + Fn = 1 + }; + commandReulst.ReplyBytes = GetCommandBytes(reqParam); + } + else if (commandReulst.Fn == 2)//退出登录 + { + Console.WriteLine($"{commandReulst.A},退出登录:{DateTime.Now}"); + } + else if (commandReulst.Fn == 3)//心跳 + { + Console.WriteLine($"{commandReulst.A},心跳:{DateTime.Now}"); + AnalysisHeartbeat(commandReulst); + } + } + + public void AnalysisHeartbeat(CommandReulst commandReulst) + { + if (commandReulst.Seq.TpV == TpV.附加信息域中带时间标签) + { + //解析 + + } + if (commandReulst.Seq.CON == CON.需要对该帧进行确认) + { + var reqParam = new ReqParameter2() + { + AFN = AFN.确认或否认, + CMasterStationFunCode = CMasterStationFunCode.链路测试, + PRM = PRM.从动站报文, + A = commandReulst.A, + Seq = new Seq() + { + TpV = TpV.附加信息域中无时间标签, + FIRFIN = FIRFIN.单帧, + CON = CON.不需要对该帧进行确认, + PRSEQ = commandReulst.Seq.PRSEQ, + }, + MSA = commandReulst.MSA, + Pn = 0, + Fn = 1 + }; + commandReulst.ReplyBytes = GetCommandBytes(reqParam); + } + } + + /// + /// 解析时间标签 + /// + /// + private void AnalysisTp(List hexDatas) + { + var pFC = DataConvert.HexToDec(hexDatas[0]);//启动帧帧序号计数器 + var seconds = Convert.ToInt32(hexDatas[1]); // 获取当前秒数 + var minutes = Convert.ToInt32(hexDatas[2]); // 获取当前分钟数 + var hours = Convert.ToInt32(hexDatas[3]); // 获取当前小时数 + var day = Convert.ToInt32(hexDatas[4]); // 获取当前日期的日数 + var delayTime = DataConvert.HexToDec(hexDatas[5]);//延迟时间 min + } + + /// + /// 解析电表档案 + /// + /// + /// + public List AnalysisAFN04F10DataUnit(List hexDatas) + { + var meterList = new List(); + var count = DataConvert.HexToDec($"{hexDatas[1]}{hexDatas[0]}"); + //if (2 + count * 27 != hexDatas.Count - pWLen - tPLen - 2) + // return; + var index = 2;//数量 + for (int i = 1; i <= count; i++) + { + var meterNumber = DataConvert.HexToDec($"{hexDatas[index + 1]}{hexDatas[index]}"); + index += 2; + + var pn = DataConvert.HexToDec($"{hexDatas[index + 1]}{hexDatas[index]}"); + index += 2; + + var baudRateAndPortBin = DataConvert.HexToBin(hexDatas[index]).PadLeft(8, '0'); + var baudRate = DataConvert.BinToDec(baudRateAndPortBin.Substring(0, 3)); + var port = DataConvert.BinToDec(baudRateAndPortBin.Substring(3, 5)); + index += 1; + + var protocolType = (CommunicationProtocolType)DataConvert.HexToDec(hexDatas[index]); + index += 1; + + var addressHexList = hexDatas.Skip(index).Take(6).ToList(); + addressHexList.Reverse(); + var address = string.Join("", addressHexList); + index += 6; + + var pwdHexList = hexDatas.Skip(index).Take(6).ToList(); + pwdHexList.Reverse(); + var password = string.Join("", pwdHexList.Take(3).ToList()); + index += 6; + + var rateNumberBin = DataConvert.HexToBin(hexDatas[index]).PadLeft(8, '0'); + var rateNumber = DataConvert.BinToDec(rateNumberBin.Substring(4)); + index += 1; + + var intBitAndDecBitNumberBin = DataConvert.HexToBin(hexDatas[index]).PadLeft(8, '0'); + var intBitNumber = DataConvert.BinToDec(intBitAndDecBitNumberBin.Substring(4, 2)) + 4; + var decBitNumber = DataConvert.BinToDec(intBitAndDecBitNumberBin.Substring(6, 2)) + 1; + index += 1; + + // hexDatas.GetRange() + var collectorAddressHexList = hexDatas.Skip(index).Take(6).ToList(); + collectorAddressHexList.Reverse(); + var collectorAddress = string.Join("", collectorAddressHexList); + index += 6; + + var userClassNumberBin = DataConvert.HexToBin(hexDatas[index]).PadLeft(8, '0'); + var userClass = DataConvert.BinToDec(userClassNumberBin.Substring(0, 4)); + var userSubClass = DataConvert.BinToDec(userClassNumberBin.Substring(4, 4)); + index += 1; + + meterList.Add(new MeterParameter() + { + Pn = pn, + BaudRate = baudRate, + Port = port, + ProtocolType = protocolType, + Address = address, + Password = password, + RateNumber = rateNumber, + IntegerBitNumber = intBitNumber, + DecimalBitNumber = decBitNumber, + CollectorAddress = collectorAddress, + UserCategoryNumber = userClass, + UserSubclassNumber = userSubClass, + }); + } + return meterList; + } + + /// + /// 解析实时数据F129 + /// + /// + private void AnalysisAFN0CF129DataUnit(List hexDatas) + { + var minutes = Convert.ToInt32(hexDatas[0]); // 获取当前分钟数 + var hours = Convert.ToInt32(hexDatas[1]); // 获取当前小时数 + var day = Convert.ToInt32(hexDatas[2]); // 获取当前日期的日数 + var month = Convert.ToInt32(hexDatas[3]); // 获取当前月份 + var year = Convert.ToInt32(hexDatas[4]); // 获取当前日期的年份 + + var rateNumber = Convert.ToInt32(hexDatas[5]); + var kwhTotal = hexDatas.Skip(5).Take(5).ToList(); + var kwhList = new List(); + var index = 11; + for (int i = 0; i < rateNumber; i++) + { + var kwhHexList = hexDatas.Skip(11).Take(5).ToList(); + kwhHexList.Reverse(); + var integerStr = $"{kwhHexList.Take(0)}{kwhHexList.Take(1)}{kwhHexList.Take(2)}"; + var decimalValStr = $"{kwhHexList[3]}{kwhHexList[4]}"; + var val = decimal.Parse($"{integerStr}{decimalValStr}"); + kwhList.Add(val); + index += 5; + } + } + + #endregion + #region 下行命令 /// /// 设置电表档案 /// - /// + /// 集中器地址 /// - public void GetAFN04F10DataUnit(ReqParameter reqParameter, List meterParameters) + public void GetSetAmmeterParameter(string a, List meterParameters) { var dataUnit = GetAFN04F10DataUnit(meterParameters); - var bytes = GetCommandBytes(reqParameter, dataUnit); + var bytes = GetCommandBytes(new ReqParameter2() + { + AFN = AFN.设置参数, + CMasterStationFunCode = CMasterStationFunCode.请求1级数据, + A = a, + Seq = new Seq() + { + TpV = TpV.附加信息域中无时间标签, + FIRFIN = FIRFIN.单帧, + CON = CON.需要对该帧进行确认, + PRSEQ = 10, + }, + MSA = GetMSA(a), + Pn = 0, + Fn = 10 + }, dataUnit); } /// /// 查询电表档案 /// - /// + /// /// 对象序号 - public void GetAFN10F10DataUnit(ReqParameter reqParameter, List meterNumberList) + public void GetAmmeterParameter(string a, List meterNumberList) { var dataUnit = new List(); var countHex = DataConvert.DecToHex(meterNumberList.Count()).PadLeft(4, '0'); @@ -83,10 +502,46 @@ namespace JiShe.CollectBus.Protocol numberHexPairs.Reverse(); dataUnit.AddRange(numberHexPairs); } - var bytes = GetCommandBytes(reqParameter, dataUnit); + var bytes = GetCommandBytes(new ReqParameter2() + { + AFN = AFN.查询参数, + CMasterStationFunCode = CMasterStationFunCode.请求2级数据, + A = a, + Seq = new Seq() + { + TpV = TpV.附加信息域中无时间标签, + FIRFIN = FIRFIN.单帧, + CON = CON.不需要对该帧进行确认, + PRSEQ = 0, + }, + MSA = GetMSA(a), + Pn = 0, + Fn = 10 + }, dataUnit); } - + + public void GetAmmterReading(string a,int pn) + { + var bytes = GetCommandBytes(new ReqParameter2() + { + AFN = AFN.请求实时数据, + CMasterStationFunCode = CMasterStationFunCode.请求2级数据, + A = a, + Seq = new Seq() + { + TpV = TpV.附加信息域中无时间标签, + FIRFIN = FIRFIN.单帧, + CON = CON.不需要对该帧进行确认, + PRSEQ = 2, + }, + MSA = GetMSA(a), + Pn = pn, + Fn = 129 + }); + } + + /// /// 组装电表阀控 /// @@ -549,368 +1004,6 @@ namespace JiShe.CollectBus.Protocol #endregion - #region 上行命令 - - //68 - //32 00 - //32 00 - //68 - //C9 1100'1001. 控制域C。 - // D7=1, (终端发送)上行方向。 - // D6=1, 此帧来自启动站。 - // D5=0, (上行方向)要求访问位。表示终端无事件数据等待访问。 - // D4=0, 保留 - // D3~D0=9, 功能码。链路测试 - - //20 32 行政区划码 - //90 26 终端地址 - //00 主站地址和组地址标志。终端为单地址。 //3220 09 87 2 - // 终端启动的发送帧的 MSA 应为 0, 其主站响应帧的 MSA 也应为 0. - //02 应用层功能码。AFN=2, 链路接口检测 - //70 0111'0000. 帧序列域。无时间标签、单帧、需要确认。 - //00 00 信息点。DA1和DA2全为“0”时,表示终端信息点。 - //01 00 信息类。F1, 登录。 - //44 帧尾,包含用户区数据校验和 - //16 帧结束标志 - - /// - /// 解析上行命令 - /// - /// - /// - public CommandReulst? AnalysisCmd(string cmd) - { - CommandReulst? commandReulst = null; - var hexStringList = DataConvert.StringToPairs(cmd); - if (hexStringList.Count < hearderLen) - { - return commandReulst; - } - if (hexStringList[0] != stx || hexStringList[5] != stx) - { - return commandReulst; - } - - var lenHexStr = $"{hexStringList[2]}{hexStringList[1]}"; - var lenBin = DataConvert.HexToBin(lenHexStr); - var len = DataConvert.BinToDec(lenBin.Remove(lenBin.Length - 2)); - if (hexStringList.Count - 2 != hearderLen + len) - return commandReulst; - - var userDataIndex = hearderLen; - var c = hexStringList[userDataIndex];//控制域 1字节 - userDataIndex += 1; - - var aHexList = hexStringList.Skip(userDataIndex).Take(5).ToList();//地址域 5字节 - var a = AnalysisA(aHexList); - var a3Bin = DataConvert.HexToBin(aHexList[4]).PadLeft(8, '0'); - var mSA = DataConvert.BinToDec(a3Bin.Substring(0, 7)); - userDataIndex += 5; - - var aFN = (AFN)DataConvert.HexToDec(hexStringList[userDataIndex]);//1字节 - userDataIndex += 1; - - var seq = DataConvert.HexToBin(hexStringList[userDataIndex]).PadLeft(8, '0'); - var tpV = (TpV)Convert.ToInt32(seq.Substring(0, 1)); - var fIRFIN = (FIRFIN)Convert.ToInt32(seq.Substring(1, 2)); - var cON = (CON)Convert.ToInt32(seq.Substring(3, 1)); - var prseqBin = seq.Substring(4, 4); - userDataIndex += 1; - - // (DA2 - 1) * 8 + DA1 = pn - var da1Bin = DataConvert.HexToBin(hexStringList[userDataIndex]); - var da1 = da1Bin == "0" ? 0 : da1Bin.Length; - userDataIndex += 1; - var da2 = DataConvert.HexToDec(hexStringList[userDataIndex]); - userDataIndex += 1; - var pn = da2 == 0 ? 0 : (da2 - 1) * 8 + da1; - - //(DT2*8)+DT1=fn - var dt1Bin = DataConvert.HexToBin(hexStringList[userDataIndex]); - var dt1 = dt1Bin != "0" ? dt1Bin.Length : 0; - userDataIndex += 1; - var dt2 = DataConvert.HexToDec(hexStringList[userDataIndex]); - userDataIndex += 1; - var fn = dt2 > 0 ? dt2 * 8 + dt1 : 0; - - //数据单元 - var datas = hexStringList.Skip(userDataIndex).Take(len + hearderLen - userDataIndex).ToList(); - - //EC - //Tp - commandReulst = new CommandReulst() - { - A = a, - MSA = mSA, - AFN = aFN, - Seq = new Seq() - { - TpV = tpV, - FIRFIN = fIRFIN, - CON = cON, - PRSEQ = DataConvert.BinToDec(prseqBin), - }, - CmdLength = len, - Pn = pn, - Fn = fn, - HexDatas = datas - }; - - return commandReulst; - } - - /// - /// 解析地址 - /// - /// - /// - private string AnalysisA(List aHexList) - { - var a1 = aHexList[1] + aHexList[0]; - var a2 = aHexList[3] + aHexList[2]; - var a2Dec = DataConvert.HexToDec(a2); - var a3 = aHexList[4]; - var a = $"{a1}{a2Dec.ToString().PadLeft(5, '0')}"; - return a; - } - - /// - /// 解析上行命令数据包 - /// - /// - public void AnalysisData(CommandReulst commandReulst) - { - switch (commandReulst.AFN) - { - case AFN.确认或否认: - //commandReulst.fn - //1:全部确认 - //2:全部否认 - //3:按数据单元表示确认和否认 - //4 硬件安全认证错误应答 - break; - case AFN.复位: - break; - case AFN.链路接口检测: - AnalysisAFN02(commandReulst); - break; - case AFN.中继站命令: - break; - case AFN.设置参数: - break; - case AFN.控制命令: - break; - case AFN.身份认证及密钥协商: - break; - case AFN.备用: - break; - case AFN.请求被级联终端主动上报: - break; - case AFN.请求终端配置: - break; - case AFN.查询参数: - break; - case AFN.请求任务数据: - break; - case AFN.请求实时数据: - break; - case AFN.请求历史数据: - break; - case AFN.请求事件数据: - break; - case AFN.文件传输: - break; - case AFN.数据转发: - break; - default: - break; - } - } - - public void AnalysisAFN02(CommandReulst commandReulst) - { - if (commandReulst.Fn == 1) //登录 - { - Console.WriteLine($"{commandReulst.A},登录:{DateTime.Now}"); - var reqParam = new ReqParameter2() - { - AFN = AFN.确认或否认, - CMasterStationFunCode = CMasterStationFunCode.链路测试, - PRM = PRM.从动站报文, - A = commandReulst.A, - Seq = new Seq() - { - TpV = TpV.附加信息域中无时间标签, - FIRFIN = FIRFIN.单帧, - CON = CON.不需要对该帧进行确认, - PRSEQ = commandReulst.Seq.PRSEQ, - }, - MSA = commandReulst.MSA, - Pn = 0, - Fn = 1 - }; - commandReulst.ReplyBytes = GetCommandBytes(reqParam); - } - else if (commandReulst.Fn == 2)//退出登录 - { - Console.WriteLine($"{commandReulst.A},退出登录:{DateTime.Now}"); - } - else if (commandReulst.Fn == 3)//心跳 - { - Console.WriteLine($"{commandReulst.A},心跳:{DateTime.Now}"); - AnalysisHeartbeat(commandReulst); - } - } - - public void AnalysisHeartbeat(CommandReulst commandReulst) - { - if (commandReulst.Seq.TpV == TpV.附加信息域中带时间标签) - { - //解析 - - } - if (commandReulst.Seq.CON == CON.需要对该帧进行确认) - { - var reqParam = new ReqParameter2() - { - AFN = AFN.确认或否认, - CMasterStationFunCode = CMasterStationFunCode.链路测试, - PRM = PRM.从动站报文, - A = commandReulst.A, - Seq = new Seq() - { - TpV = TpV.附加信息域中无时间标签, - FIRFIN = FIRFIN.单帧, - CON = CON.不需要对该帧进行确认, - PRSEQ = commandReulst.Seq.PRSEQ, - }, - MSA = commandReulst.MSA, - Pn = 0, - Fn = 1 - }; - //commandReulst.ReplyBytes = GetCommandBytes(reqParam); - } - } - - /// - /// 解析时间标签 - /// - /// - private void AnalysisTp(List hexDatas) - { - var pFC = DataConvert.HexToDec(hexDatas[0]);//启动帧帧序号计数器 - var seconds = Convert.ToInt32(hexDatas[1]); // 获取当前秒数 - var minutes = Convert.ToInt32(hexDatas[2]); // 获取当前分钟数 - var hours = Convert.ToInt32(hexDatas[3]); // 获取当前小时数 - var day = Convert.ToInt32(hexDatas[4]); // 获取当前日期的日数 - var delayTime = DataConvert.HexToDec(hexDatas[5]);//延迟时间 min - } - - /// - /// 解析电表档案 - /// - /// - /// - public List AnalysisAFN04F10DataUnit(List hexDatas) - { - var meterList = new List(); - var count = DataConvert.HexToDec($"{hexDatas[1]}{hexDatas[0]}"); - //if (2 + count * 27 != hexDatas.Count - pWLen - tPLen - 2) - // return; - var index = 2;//数量 - for (int i = 1; i <= count; i++) - { - var meterNumber = DataConvert.HexToDec($"{hexDatas[index + 1]}{hexDatas[index]}"); - index += 2; - - var pn = DataConvert.HexToDec($"{hexDatas[index + 1]}{hexDatas[index]}"); - index += 2; - - var baudRateAndPortBin = DataConvert.HexToBin(hexDatas[index]).PadLeft(8, '0'); - var baudRate = DataConvert.BinToDec(baudRateAndPortBin.Substring(0, 3)); - var port = DataConvert.BinToDec(baudRateAndPortBin.Substring(3, 5)); - index += 1; - - var protocolType = (ProtocolType)DataConvert.HexToDec(hexDatas[index]); - index += 1; - - var addressHexList = hexDatas.Skip(index).Take(6).ToList(); - addressHexList.Reverse(); - var address = string.Join("", addressHexList); - index += 6; - - var pwdHexList = hexDatas.Skip(index).Take(6).ToList(); - pwdHexList.Reverse(); - var password = string.Join("", pwdHexList.Take(3).ToList()); - index += 6; - - var rateNumberBin = DataConvert.HexToBin(hexDatas[index]).PadLeft(8, '0'); - var rateNumber = DataConvert.BinToDec(rateNumberBin.Substring(4)); - index += 1; - - var intBitAndDecBitNumberBin = DataConvert.HexToBin(hexDatas[index]).PadLeft(8, '0'); - var intBitNumber = DataConvert.BinToDec(intBitAndDecBitNumberBin.Substring(4, 2)) + 4; - var decBitNumber = DataConvert.BinToDec(intBitAndDecBitNumberBin.Substring(6, 2)) + 1; - index += 1; - - // hexDatas.GetRange() - var collectorAddressHexList = hexDatas.Skip(index).Take(6).ToList(); - collectorAddressHexList.Reverse(); - var collectorAddress = string.Join("", collectorAddressHexList); - index += 6; - - var userClassNumberBin = DataConvert.HexToBin(hexDatas[index]).PadLeft(8, '0'); - var userClass = DataConvert.BinToDec(userClassNumberBin.Substring(0, 4)); - var userSubClass = DataConvert.BinToDec(userClassNumberBin.Substring(4, 4)); - index += 1; - - meterList.Add(new MeterParameter() - { - Pn = pn, - BaudRate = baudRate, - Port = port, - ProtocolType = protocolType, - Address = address, - Password = password, - RateNumber = rateNumber, - IntegerBitNumber = intBitNumber, - DecimalBitNumber = decBitNumber, - CollectorAddress = collectorAddress, - UserCategoryNumber = userClass, - UserSubclassNumber = userSubClass, - }); - } - return meterList; - } - - /// - /// 解析实时数据F129 - /// - /// - private void AnalysisAFN0CF129DataUnit(List hexDatas) - { - var minutes = Convert.ToInt32(hexDatas[0]); // 获取当前分钟数 - var hours = Convert.ToInt32(hexDatas[1]); // 获取当前小时数 - var day = Convert.ToInt32(hexDatas[2]); // 获取当前日期的日数 - var month = Convert.ToInt32(hexDatas[3]); // 获取当前月份 - var year = Convert.ToInt32(hexDatas[4]); // 获取当前日期的年份 - - var rateNumber = Convert.ToInt32(hexDatas[5]); - var kwhTotal = hexDatas.Skip(5).Take(5).ToList(); - var kwhList = new List(); - var index = 11; - for (int i = 0; i < rateNumber; i++) - { - var kwhHexList = hexDatas.Skip(11).Take(5).ToList(); - kwhHexList.Reverse(); - var integerStr = $"{kwhHexList.Take(0)}{kwhHexList.Take(1)}{kwhHexList.Take(2)}"; - var decimalValStr = $"{kwhHexList[3]}{kwhHexList[4]}"; - var val = decimal.Parse($"{integerStr}{decimalValStr}"); - kwhList.Add(val); - index += 5; - } - } - - #endregion + } }