Files
Web_CRICS_Server_VS2010_Prod/Common/ProtocalData.cs
2025-12-11 09:17:16 +08:00

312 lines
16 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 System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
namespace Common
{
public static class ProtocalData
{
/// <summary>
/// 获取子群数据
/// </summary>
/// <param name="subGroupNode"></param>
/// <returns></returns>
public static List<List<byte>> GetSubgroupSendData(XmlNode subGroupNode)
{
List<List<byte>> sendDatas = new List<List<byte>>();
int totalFrame = subGroupNode.ChildNodes.Count + 3;//补上配置xml文件版本号、配置数据版本号和全局属性数据
List<object> textData;
//=============1、新增配置xml文件版本号=======================
sendDatas.Add(GetSendData(GetVersionSendData(subGroupNode.Attributes["SettingVersion"].Value), 0xA9, totalFrame, 1));
//=============2、配置数据版本号===========================
sendDatas.Add(GetSendData(GetVersionSendData(subGroupNode.Attributes["Version"].Value), 0xA5, totalFrame, 2));
//=============3、全局属性数据=================================
sendDatas.Add(GetSendData(GetGlobalSendData(subGroupNode), 0xA3, totalFrame, 3));
//=============4、设备和动作数据=============================
for (int i = 0; i < subGroupNode.ChildNodes.Count; i++)
{
XmlNode detailNode = subGroupNode.ChildNodes[i];
textData = new List<object>();
textData.Add(detailNode.Attributes["Type"].Value);//类型
int paramCount = Convert.ToInt16(detailNode.Attributes["ParamCount"].Value);
switch (Convert.ToInt16(detailNode.Attributes["Type"].Value))
{
case 0://设备
textData.Add(detailNode.Attributes["DeviceAddress"].Value.Split('.')[0]);//设备地址第一位
textData.Add(detailNode.Attributes["DeviceAddress"].Value.Split('.')[1]);//设备地址第二位
textData.Add(detailNode.Attributes["DeviceAddress"].Value.Split('.')[2]);//设备地址第三位
for (int j = 1; j <= paramCount; j++)
{
//设备类型、输入回路数,输出回路数为两位字节
switch (j)
{
case 7:
case 8:
textData.Add("DeviceAddr");//标记一下,为了转为两位字节
textData.Add(detailNode.Attributes["Param" + j.ToString()].Value);
break;
default:
textData.Add(detailNode.Attributes["Param" + j.ToString()].Value);
break;
}
}
break;
case 1://动作
textData.Add(detailNode.Attributes["DeviceAddress"].Value.Split('.')[0]);//设备地址第一位
textData.Add(detailNode.Attributes["DeviceAddress"].Value.Split('.')[1]);//设备地址第二位
textData.Add(detailNode.Attributes["DeviceAddress"].Value.Split('.')[2]);//设备地址第三位
for (int j = 1; j <= paramCount; j++)
{
//设备类型、输入地址为两位字节
switch (j)
{
case 4:
textData.Add("DeviceAddr");//标记一下,为了转为两位字节
textData.Add(detailNode.Attributes["Param" + j.ToString()].Value);
break;
default:
textData.Add(detailNode.Attributes["Param" + j.ToString()].Value);
break;
}
}
//扩展属性
foreach (XmlNode expandNode in detailNode.ChildNodes)
{
paramCount = Convert.ToInt16(expandNode.Attributes["ParamCount"].Value);
for (int j = 1; j <= paramCount; j++)
{
switch (j)
{
case 1:
case 2:
case 4://延时执行内容
case 5://延时执行单位
textData.Add(expandNode.Attributes["Param" + j.ToString()].Value);
break;
default:
//扩展属性都为两位字节
textData.Add("DeviceAddr");//标记一下,为了转为两位字节
textData.Add(expandNode.Attributes["Param" + j.ToString()].Value);
break;
}
}
//扩展属性的输出类型
int outTypeParamCount = Convert.ToInt16(expandNode.Attributes["OutTypeParamCount"].Value);
switch (outTypeParamCount)
{
case 1:
textData.Add("DeviceAddr");//标记一下,为了转为两位字节
textData.Add(expandNode.Attributes["Param" + (paramCount + 1).ToString()].Value);
break;
case 2:
textData.Add(expandNode.Attributes["Param" + (paramCount + 1).ToString()].Value);
textData.Add(expandNode.Attributes["Param" + (paramCount + 2).ToString()].Value);
break;
case 3://背景音乐
textData.Add("DeviceAddr");//标记一下,为了转为两位字节
textData.Add((Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 1).ToString()].Value) << 0) +
(Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 2).ToString()].Value) << 12) +
(Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 3).ToString()].Value) << 8));
break;
case 4://地暖
textData.Add("DeviceAddr");//标记一下,为了转为两位字节
textData.Add((Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 1).ToString()].Value) << 12) +
(Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 2).ToString()].Value) << 8) +
(Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 3).ToString()].Value) << 6) +
Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 4).ToString()].Value));
break;
case 5://空调
textData.Add("DeviceAddr");//标记一下,为了转为两位字节
textData.Add((Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 1).ToString()].Value) << 14) +
(Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 2).ToString()].Value) << 12) +
(Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 3).ToString()].Value) << 10) +
(Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 4).ToString()].Value) << 8) +
Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 5).ToString()].Value));
break;
}
}
break;
case 2://MQTT映射去掉组地址、设备地址增加别名长度20
string deviceType2 = detailNode.Attributes["DeviceType"].Value;
textData.Add(deviceType2);
textData.Add(detailNode.Attributes["Param1"].Value);
if ("0" == deviceType2)
{
textData.Add(0x00);
textData.Add(detailNode.Attributes["Param2"].Value);
}
else
{
textData.Add("DeviceAddr");//标记一下,为了转为两位字节
textData.Add(detailNode.Attributes["Param2"].Value);
}
//paramCount = Convert.ToInt16(detailNode.Attributes["ParamCount"].Value);
//for (int j = 1; j <= paramCount; j++)
//{
// textData.Add(detailNode.Attributes["Param" + j.ToString()].Value);
//}
byte[] nameBGK = Encoding.GetEncoding("GBK").GetBytes(detailNode.Attributes["Name"].Value);
foreach (byte b in nameBGK)
{
textData.Add(b);
}
for (int j = nameBGK.Length; j < 20; j++)//不足20位补0
{
textData.Add(0x00);
}
break;
case 3://BLW映射
textData.Add(detailNode.Attributes["GroupAddress"].Value);
textData.Add(detailNode.Attributes["DeviceAddress"].Value);
string deviceType3 = detailNode.Attributes["DeviceType"].Value;
textData.Add(deviceType3);
textData.Add(detailNode.Attributes["Param1"].Value);
if ("0" == deviceType3)
{
textData.Add(0x00);
textData.Add(detailNode.Attributes["Param2"].Value);
}
else
{
textData.Add("DeviceAddr");//标记一下,为了转为两位字节
textData.Add(detailNode.Attributes["Param2"].Value);
}
//textData.Add(detailNode.Attributes["DeviceType"].Value);
//paramCount = Convert.ToInt16(detailNode.Attributes["ParamCount"].Value);
//for (int j = 1; j <= paramCount; j++)
//{
// textData.Add(detailNode.Attributes["Param" + j.ToString()].Value);
//}
break;
}
//每一组设备地址发送数据加入集合
sendDatas.Add(GetSendData(textData, 0xA2, totalFrame, (i + 4)));//组地址等属性
}
return sendDatas;
}
/// <summary>
/// 按所定义的格式获取与RCU主机通讯的数据
/// </summary>
/// <param name="textData">数据内容</param>
/// <param name="mode">模式:时间同步A0组地址调试A1子群发布A2全局属性A3V80复位开关A4配置数据版本号A5485调光A6网络设置A7</param>
/// <param name="totalFrame">数据总帧数</param>
/// <param name="currentFrame">当前帧数</param>
/// <returns></returns>
private static List<byte> GetSendData(List<object> textData, byte mode, Int32 totalFrame, Int32 currentFrame)
{
//发送数据
//byte[] demoData = new byte[] {
// 0xF0, 0x0F, //数据头
// 0xA1, //调试模式
// 0x00, 0x2C, //数据总长度
// 0x00, 0x01, //数据总帧数
// 0x00, 0x01, //当前帧数
// 0x54, 0x33, 0x53, 0x41, //识别码T3SA
// 0x01, 0x01, 0x02, //组地址属性
// 0x01, 0x00, 0x23, 0x01, 0x00, 0x00, 0x00, 0x02, //弱电输入
// 0x01, 0x01, 0x09, 0x01, 0xFF, 0x03, 0x00, 0x00, 0xFF, //弱电输出
// 0x01, 0x02, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, //强电输出
// 0x57, 0xDA //CRC16校验
//};
List<byte> sendData = new List<byte>();
sendData.Add(0xF0);//数据头
sendData.Add(0x0F);//数据头
sendData.Add(mode);//调试模式
//数据总长度除了前面2位数据头其他都算
byte[] dataLen = Tools.Int32ToByte(textData.Count + 13);
foreach (byte b in dataLen)
{
sendData.Add(b);
}
//数据总帧数
dataLen = Tools.Int32ToByte(totalFrame);
foreach (byte b in dataLen)
{
sendData.Add(b);
}
//当前帧数
dataLen = Tools.Int32ToByte(currentFrame);
foreach (byte b in dataLen)
{
sendData.Add(b);
}
sendData.Add(0x54);//识别码T3SA
sendData.Add(0x33);//识别码T3SA
sendData.Add(0x53);//识别码T3SA
sendData.Add(0x41);//识别码T3SA
bool isToByte = false;
foreach (object obj in textData)
{
//遇到“DeviceAddr”标记则改成2个byte
if (Convert.ToString(obj) == "DeviceAddr")
{
isToByte = true;
}
else
{
if (isToByte)
{
dataLen = Tools.Int32ToByte2(Convert.ToInt32(obj));//小端
foreach (byte b in dataLen)
{
sendData.Add(b);
}
isToByte = false;
}
else
{
sendData.Add(byte.Parse(obj.ToString()));
}
}
}
ushort crc = Tools.CRC16(sendData.ToArray(), sendData.Count);
sendData.Add(Convert.ToByte(crc & 0xFF));//CRC16校验
sendData.Add(Convert.ToByte((crc >> 8) & 0xFF));//CRC16校验
return sendData;
}
/// <summary>
/// 获取配置数据版本号发送数据version为空时提供默认值FF,FF,FF
/// </summary>
/// <param name="version"></param>
/// <returns></returns>
private static List<object> GetVersionSendData(string version)
{
List<object> textData = new List<object>();
if (string.IsNullOrEmpty(version))
{
textData.Add(0xFF);
textData.Add(0xFF);
textData.Add(0xFF);
}
else
{
textData.Add(version.Split('.')[0]);
textData.Add(version.Split('.')[1]);
textData.Add(version.Split('.')[2]);
}
return textData;
}
/// <summary>
/// 获取子群全局属性发送数据
/// </summary>
/// <param name="projectGroupAddrID">子群ID</param>
/// <param name="projectID">项目ID</param>
/// <returns></returns>
private static List<object> GetGlobalSendData(XmlNode subGroupNode)
{
List<object> textData = new List<object>();
int paramCount = Convert.ToInt16(subGroupNode.Attributes["ParamCount"].Value);
for (int j = 1; j <= paramCount; j++)
{
textData.Add(subGroupNode.Attributes["Param" + j.ToString()].Value);
}
return textData;
}
}
}