2025-04-23 16:17:29 +08:00

813 lines
34 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using JiShe.CollectBus.Common.Enums;
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
{
public static class Build645SendData
{
//起始字符
private const string startStr = "68";
//结束字符
private const string endStr = "16";
#region 645
/// <summary>
/// 构建电表阀控下发数据单元
/// </summary>
/// <param name="ammeterAddress">电表地址</param>
/// <param name="specialControlCode">特殊控制码</param>
/// <param name="password">密码</param>
/// <param name="state">是否为开阀,true合闸false关闸</param>
/// <param name="modelCode">型号码</param>
/// <returns></returns>
public static List<string> 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();
}
/// <summary>
/// 构建电表保电下发数据单元
/// </summary>
/// <param name="ammeterAddress">电表地址</param>
/// <param name="password"></param>
/// <param name="state">true 保电 false 保电解除</param>
/// <param name="modelCode">型号码</param>
/// <returns></returns>
public static List<string> 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;
}
/// <summary>
/// 构建电表认证下发数据单元
/// </summary>
/// <param name="ammeterAddress">电表地址</param>
/// <param name="ramDon"></param>
/// <param name="maco"></param>
/// <returns></returns>
public static List<string> 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<string>();
dataUnit.AddRange(codeList);
dataUnit.AddRange(ramDonList);
dataUnit.AddRange(macoList);
var dataList = Build645SendCommand(ammeterAddress, "03", dataUnit);
return dataList;
}
/// <summary>
/// 构建电表清零下发数据单元
/// </summary>
/// <param name="ammeterAddress">电表地址</param>
/// <param name="password"></param>
/// <returns></returns>
public static List<string> 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;
}
/// <summary>
/// 透明转发 表计校时/广播校时 F10-104
/// </summary>
/// <param name="ammeterAddress"></param>
/// <param name="password"></param>
/// <param name="s_operator"></param>
/// <param name="dataMark"></param>
/// <param name="cmdType">类型 0日期部分指令1时间部分指令</param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="Exception"></exception>
public static List<string> BuildAmmeterCorrectionTimeSendDataUnit(string ammeterAddress,string password, string dataMark, int cmdType, string s_operator = "00000001")
{
List<string> dataUnit = new List<string>();
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<string> 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;
}
/// <summary>
/// 设置尖峰平谷时段 F10-103
/// </summary>
/// <param name="ammeterAddress"></param>
/// <param name="password"></param>
/// <param name="dataMark"></param>
/// <param name="data"></param>
/// <param name="s_operator"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static List<string> BuildAmmeterTimeSetSendDataUnit(string ammeterAddress,string password, string dataMark,string data, string s_operator= "00000001")
{
var datas = data.Split(' ').ToList();
datas.Reverse();
List<string> dataUnit = BuildAmmeterTimeSetDataUnit(password, dataMark, datas);
List<string> dataList = new List<string>();
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;
}
/// <summary>
/// 工具生成指令 F10 103
/// </summary>
/// <param name="ammeterAddress"></param>
/// <param name="cmd"></param>
/// <returns></returns>
public static List<string> GenerateContent(string ammeterAddress, string cmd)
{
//替换表计地址
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;
}
/// <summary>
/// AFN16_F106
/// </summary>
/// <param name="comandCodeEnum"></param>
/// <param name="ammeterAddress"></param>
/// <param name="cmd"></param>
/// <param name="password"></param>
/// <param name="dataMark"></param>
/// <param name="data"></param>
/// <returns></returns>
public static List<string> BuildAmmeterGenerateBCCommand(ComandCodeEnum comandCodeEnum,string ammeterAddress,string cmd, string password, string dataMark, string data)
{
List<string> content = new List<string>();
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;
}
/// <summary>
/// 构建电表读取下发数据单元
/// </summary>
/// <param name="ammeterAddress">电表地址</param>
/// <param name="cmdType">功率读取 余额读取</param>
/// <param name="dataId">数据标识</param>
/// <returns></returns>
public static List<string> 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;
}
/// <summary>
/// 构建电表修正时间下发命令-PMAC9523
/// </summary>
/// <param name="ammeterAddress"></param>
/// <returns></returns>
public static List<string> 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<string>() { 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;
}
/// <summary>
/// 构建电表修正时间下发命令-DTSU193
/// </summary>
/// <param name="ammeterAddress"></param>
/// <returns></returns>
public static List<string> 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;
}
/// <summary>
/// 构建电表修正时间下发命令
/// </summary>
/// <param name="ammeterAddress"></param>
/// <param name="password"></param>
/// <returns></returns>
public static List<List<string>> BuildAmmeterCorrectionTimeSendDataUnit(string ammeterAddress,string password)
{
var listDataUnit = new List<List<string>>();
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<string> dataList = new List<string>();
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<string>();
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;
}
/// <summary>
///
/// </summary>
/// <param name="ammeterAddress"></param>
/// <returns></returns>
public static List<string> 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<string>() { 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;
}
/// <summary>
/// 构建电表表号读取下发命令
/// </summary>
/// <param name="ammeterAddress">电表地址</param>
/// <returns></returns>
public static List<string> BuildAmmeterReadNumSendCmd(string ammeterAddress)
{
var dataUnit = "04000402".StringToPairs(true);
return Build645SendCommand(ammeterAddress, "11", dataUnit);
}
public static List<List<string>> BuildPMAC9523AmmeterSetTimeSetSendDataUnit(string ammeterAddress, List<TimeSetDetail> data)
{
List<List<string>> dataUnitList = new List<List<string>>();
var adress = int.Parse(ammeterAddress.Substring(ammeterAddress.Length - 3)).DecToHex().PadLeft(2, '0');
//第一步启用复费率编程寄存器64503写数据01启动编程
var fm = new List<string>() { 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<string>() { 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<string>() { 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<string, string> setDic = new Dictionary<string, string>();
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;
}
/// <summary>
/// F1透明转发 读取通信地址 04 00 04 01 NNNNNNNNNNNN 6 通信地址
/// </summary>
/// <param name="ammeterAddress"></param>
/// <returns></returns>
public static List<string> BuildReadMeterAddressSendDataUnit(string ammeterAddress)
{
var dataMark = new List<string> { "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);
}
/// <summary>
/// 构建645协议下发命令
/// </summary>
/// <param name="ammeterAddress">电表地址</param>
/// <param name="controlCode">控制码</param>
/// <param name="dataUnit">数据域 发送方按字节进行加33处理接收方按字节减33</param>
/// <returns></returns>
public static List<string> Build645SendCommand(string ammeterAddress, string controlCode, List<string>? dataUnit)
{
var cmdStrList = new List<string>();
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;
}
/// <summary>
/// 威胜表的超功率(第一路恶性负载超功率判断阀值)
/// </summary>
/// <param name="ammeterAddress"></param>
/// <param name="password"></param>
/// <param name="dataMark"></param>
/// <param name="power"></param>
/// <returns></returns>
public static List<string>? 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);
}
/// <summary>
/// 威胜表的超功率(超功率开关)
/// </summary>
/// <param name="ammeterAddress"></param>
/// <param name="password"></param>
/// <param name="isOn"></param>
/// <returns></returns>
public static List<string> AssembleWsOnSupperPower(string ammeterAddress, string password, bool isOn = true)
{
var data = new string[] { (isOn ? "01" : "00") };
return AssembleWrite(ammeterAddress, password, "0E400001", data);
}
/// <summary>
/// 威胜表的超功率(第一路恶性负载绝对功率判断阈值)
/// </summary>
/// <param name="ammeterAddress"></param>
/// <param name="password"></param>
/// <param name="dataMark"></param>
/// <param name="power"></param>
/// <returns></returns>
public static List<string>? 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);
}
/// <summary>
/// 威胜表的超功率(第一路恶性负载功率因数判断阀值)
/// </summary>
/// <param name="ammeterAddress"></param>
/// <param name="password"></param>
/// <param name="dataMark"></param>
/// <param name="factor"></param>
/// <returns></returns>
public static List<string>? 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);
}
/// <summary>
/// 构建写数据
/// </summary>
/// <param name="ammeterAddress"></param>
/// <param name="password"></param>
/// <param name="di0_3"></param>
/// <param name="data"></param>
/// <returns></returns>
public static List<string> AssembleWrite(string ammeterAddress, string password, string di0_3, string[] data)
{
var returnList = new List<string>();
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<string>() { "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;
}
/// <summary>
/// 生成软编程指令
/// <param name="modelCode">型号编码</param>
/// </summary>
/// <returns></returns>
public static List<string> 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<string> GenerateCTCommand(string ammeterAddress, string data)
{
List<string> fm = new List<string>();
fm.Add(startStr);
List<string> 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<string> Time_MeterTiming()
{
return new List<string>
{
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<string> 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<string>
{
year.ToString().Substring(2,2).PadLeft(2,'0'),
month.ToString().PadLeft(2,'0'),
day.ToString().PadLeft(2,'0'),
week.ToString().PadLeft(2,'0'),
};
}
/// <summary>
/// 构建电表时段设置数据单元
/// </summary>
/// <param name="ammeterAddress"></param>
/// <param name="password"></param>
/// <param name="dataMark"></param>
/// <param name="data"></param>
/// <param name="s_operator"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
private static List<string> BuildAmmeterTimeSetDataUnit(string password, string dataMark, List<string> datas, string s_operator = "00000001")
{
List<string> dataUnit = new List<string>();
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
dataUnit.AddRange(datas);
return dataUnit;
}
#endregion
}
}