From ed01d92099c2b421421901be73f8ea767c5b3a2c Mon Sep 17 00:00:00 2001 From: Dai Mr <1822802785@qq.com> Date: Tue, 12 Nov 2024 15:43:41 +0800 Subject: [PATCH] =?UTF-8?q?645=E5=8D=8F=E8=AE=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- JiShe.CollectBus.Common/Enums/645Enums.cs | 16 ++ .../Extensions/HexStringExtensions.cs | 263 ++++++++++++++---- 2 files changed, 218 insertions(+), 61 deletions(-) create mode 100644 JiShe.CollectBus.Common/Enums/645Enums.cs diff --git a/JiShe.CollectBus.Common/Enums/645Enums.cs b/JiShe.CollectBus.Common/Enums/645Enums.cs new file mode 100644 index 0000000..bf18666 --- /dev/null +++ b/JiShe.CollectBus.Common/Enums/645Enums.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JiShe.CollectBus.Common.Enums +{ + /// + /// 控制码 + /// + public enum ControlCode + { + + } +} diff --git a/JiShe.CollectBus.Common/Extensions/HexStringExtensions.cs b/JiShe.CollectBus.Common/Extensions/HexStringExtensions.cs index 674359e..39696c0 100644 --- a/JiShe.CollectBus.Common/Extensions/HexStringExtensions.cs +++ b/JiShe.CollectBus.Common/Extensions/HexStringExtensions.cs @@ -81,7 +81,26 @@ namespace JiShe.CollectBus.Common.Extensions return str == startStr ? true : false; } - #region 下行命令 + /// + /// 字节加33 + /// + /// + /// + public static List AddHex33(this List hexStringList) + { + for (int i = 0; i < hexStringList.Count; i++) + { + hexStringList[i] = (Convert.ToInt32(hexStringList[i], 16) + Convert.ToInt32("33", 16)).ToString("X2"); + if (hexStringList[i].Length > 2) + { + hexStringList[i] = hexStringList[i].Substring(hexStringList[i].Length - 2); + } + } + + return hexStringList; + } + + #region 376.1下行命令 /// /// 构建电表参数设置-下发命令 @@ -181,65 +200,6 @@ namespace JiShe.CollectBus.Common.Extensions return bytes; } - /// - /// 组装电表阀控下发数据单元 - /// - /// 电表地址 - /// 特殊控制码 - /// 密码 - /// 是否为开阀 - /// - public static List BuildAmmeterValveControlSendDataUnit(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(); - } - - /// /// 构建电表参数设置-下发数据单元 /// @@ -319,7 +279,6 @@ namespace JiShe.CollectBus.Common.Extensions return pWList; } - /// /// 帧校验和 @@ -525,5 +484,187 @@ namespace JiShe.CollectBus.Common.Extensions #endregion + + #region 645下行命令 + + + /// + /// 构建电表阀控下发数据单元 + /// + /// 电表地址 + /// 特殊控制码 + /// 密码 + /// 是否为开阀 + /// + public static List BuildAmmeterValveControlSendDataUnit(string address, string specialnocode, string password, bool state, string modelCode = "") + { + var 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]; + } + + var strDate = DateTime.Now.AddYears(3).ToString("000012ddMMyy").StrAddSpan();//命令有效截止时间 + if (specialnocode == "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 = BuildSendCommand(address, "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(); + } + + /// + /// 构建电表保电下发数据单元 + /// + /// 电表地址 + /// + /// + /// + public static List BuildAmmeterLockSendDataUnit(string address, string password, bool state, string modelCode = "") + { + string code = string.Empty; + if (state) + code = "3A"; + else + code = "3B"; + string strDate = (code + DateTime.Now.AddDays(1).ToString("00000012ddMMyy")).StrAddSpan(); + + if (modelCode == "SZBD_DDZY1225") + strDate = $"{code} 00 FF FF FF FF FF FF"; + + string strP = password.StrAddSpan().StrReverseOrder(); + string strSJY = " 02 " + strP + " 01 00 00 00 " + strDate; + + var dataUnit = strSJY.Replace(" ", "").StringToPairs(); + var dataList = BuildSendCommand(address, "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[] { " " }, System.StringSplitOptions.RemoveEmptyEntries).Select(i => Convert.ToInt32(i, 16)).Sum().ToString("X"); + //strReturn += strSum.Substring(strSum.Length - 2) + " 16"; + //return strReturn.Split(' ').ToList(); + } + + /// + /// 构建645协议下发命令 + /// + /// 电表地址 + /// 控制码 + /// 数据域 发送方按字节进行加33处理,接收方按字节减33 + /// + public static List BuildSendCommand(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); + + 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; + } + + /// + /// 构建写数据 TODO:待优化 + /// + /// + public static List AssembleWrite(string address, string password, string Di0_3, string[] data) + { + var address_str = address.StrAddSpan().StrReverseOrder(); + var L = (12 + data.Length).ToString("X2"); + var m = "00 11 22 33"; + var Di0_3_str = Di0_3.StrAddSpan().StrReverseOrder(); + var pwd_str = password.StrAddSpan().StrReverseOrder(); + var data_str = string.Join(" ", data); + var data_add33 = (Di0_3_str + " 02 " + pwd_str + " " + m + " " + data_str).StrAddHex33(); + var frame = $"68 {address_str} 68 14 {L} {data_add33}"; + string strSum = frame.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries).Select(i => Convert.ToInt32(i, 16)).Sum().ToString("X"); + var cs = strSum.Substring(strSum.Length - 2); + return $"{frame} {cs} 16".Split(' ').ToList(); + } + + #endregion + + /// + /// 标准 188协议阀控 WaterMeterSend + /// + /// + /// + /// + public static List Confirm188WaterValve(string address, bool state, string mtype = "10") + { + if (string.IsNullOrWhiteSpace(address)) return null; + var frm = $"68 {mtype} [00 00 00 00 00 00 00] 04 04 A0 17 00 {(state ? "55" : "99")} 21 16".Split(' ').ToList(); + address = address.PadLeft(14, '0'); + int n = 0; + for (int i = 7; i > 0; i--) + { + frm[i + 1] = address.Substring(n, 2); + n += 2; + } + frm[frm.Count - 2] = GetCRC(frm.Take(frm.Count - 2).ToList()); + return frm; + } + + public static string GetCRC(List inputFrm, int startIndex = 0) + { + int sum = 0; + for (int i = startIndex; i < inputFrm.Count; i++) + { + sum += (Convert.ToInt32(inputFrm[i], 16)); + } + var sum16 = Convert.ToString(sum, 16); + return sum16.Substring(sum16.Length - 2, 2).ToUpper(); + } + } }