THMessage.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace TestSeverDemo
{
public class THMessage
{
public string header = string.Empty;
public string ender = string.Empty;
public string sn = string.Empty;
public int funcode = -1;
public int datalen = -1;
//收到的数据用string表示
public string rawdata = string.Empty;
//收到的包里的crcm
public string crcm = string.Empty;
public MessageType msgType = MessageType.None;
public DeviceType deviceType = DeviceType.None;
public byte[] receivepayload;
//生成后的数据往仪表发送
public byte[] sendpayload;
public string hexStringPyaload = string.Empty;
public THMessage(byte[] p)
{
receivepayload = p;
hexStringPyaload = Helper.byteToHexStr(receivepayload);
Parse();
sendpayload = null;
}
private bool Parse()
{
if (hexStringPyaload.Length != 0)
{
int i = hexStringPyaload.Length;
//是正确的包头跟包尾
if (hexStringPyaload.Substring(0, 2) == "7E" && hexStringPyaload.Substring(i - 2, 2) == "0D")
{
header = "7E";
ender = "0D";
sn = hexStringPyaload.Substring(2, 12);
int.TryParse(hexStringPyaload.Substring(14, 2), System.Globalization.NumberStyles.AllowHexSpecifier, null, out funcode);
int.TryParse(hexStringPyaload.Substring(16, 4), System.Globalization.NumberStyles.AllowHexSpecifier, null, out datalen);
rawdata = hexStringPyaload.Substring(20, datalen * 2);
//need to add validate crcm before parse data
ParseData();
crcm = hexStringPyaload.Substring(i - 6, 4);
return true;
}
}
return false;
}
private void ParseData()
{
switch (funcode)
{
case 1:
case 11: msgType = MessageType.Realtime; break;
case 2:
case 12: msgType = MessageType.History; break;
case 3:
case 13: msgType = MessageType.Alarm; break;
case 7: msgType = MessageType.Register7;break;
default: msgType = MessageType.Unknown; break;
}
string tempD = sn.Substring(0, 2);
if (tempD == "C0") deviceType = DeviceType.TH;
else if (tempD == "80") deviceType = DeviceType.T;
else
{
deviceType = DeviceType.Unknown;
Console.WriteLine("收到非温湿度设备发来的数据");
}
}
public virtual byte[] GenerateMessage(THDeviceParams thdp)
{
//header+sn+function code + datalen in byte+state+operation
string s = header + sn + Helper.ConverIntToHexStr2(funcode) + "0001" + "00" + "0000";
//不包含包尾的0x0D;
string temp = s;
string crc = string.Empty;
int cc = 0;
int.TryParse(Helper.CRC16(temp).ToString(), out cc);
crc = Helper.ConverIntToHexStr4(cc);
s = s + crc + ender;
Console.WriteLine("发送数据:" + s);
sendpayload = Helper.StrToHexByte(s);
return sendpayload;
}
}
public class RealtimeTHMessage : THMessage
{
public double temp = -9999;
public double humidity = -9999;
public long battery;
public long alarmstate;
public long alarmtrigger;
public RealtimeTHMessage(byte[] p) : base(p)
{
msgType = MessageType.Realtime;
temp = Helper.ConvertHexToSInt(rawdata.Substring(0, 4)) / 10f;
humidity = Helper.ConvertHexToSInt(rawdata.Substring(4, 4)) / 10f;
battery = Helper.ConvertHexToSInt(rawdata.Substring(8, 2));
alarmstate = Helper.ConvertHexToSInt(rawdata.Substring(10, 8));
alarmtrigger = Helper.ConvertHexToSInt(rawdata.Substring(18, 8));
}
public override byte[] GenerateMessage(THDeviceParams thdp)
{
if(thdp==null)
{
thdp = new THDeviceParams();
}
//header+sn+function code + datalen in byte+state+datalen+operation
string s = header + sn + Helper.ConverIntToHexStr2(funcode)+ "0001" + "00" + "001B" + "0000";
DateTime current = DateTime.Now;
s = s +
Helper.ConverIntToHexStr2(current.Year - 2000) +
Helper.ConverIntToHexStr2(current.Month) +
Helper.ConverIntToHexStr2(current.Day) +
Helper.ConverIntToHexStr2(current.Hour) +
Helper.ConverIntToHexStr2(current.Minute) +
Helper.ConverIntToHexStr2(current.Second);
s = s + Helper.ConverIntToHexStr4(thdp.RTReportInterval);
s = s + Helper.ConverIntToHexStr4(thdp.RecordInterval);
s = s + Helper.ConverIntToHexStr2(thdp.dateTime.Hour) + Helper.ConverIntToHexStr2(thdp.dateTime.Minute);
s = s + Helper.ConverIntToHexStr2(thdp.HDReport);
s = s + Helper.ConverIntToHexStr4((int)(thdp.HTAlarm * 10)) +
Helper.ConverIntToHexStr4((int)(thdp.LTAlarm * 10)) +
Helper.ConverIntToHexStr4((int)(thdp.TBuffer * 10)) +
Helper.ConverIntToHexStr4((int)(thdp.HHAlarm * 10)) +
Helper.ConverIntToHexStr4((int)(thdp.LHAlarm * 10)) +
Helper.ConverIntToHexStr4((int)(thdp.HBuffer * 10));
//不包含包尾的0x0D;
string temp = s;
string crc = string.Empty;
int cc = 0;
int.TryParse(Helper.CRC16(temp).ToString(), out cc);
crc = Helper.ConverIntToHexStr4(cc);
s = s + crc + ender;
Console.WriteLine("发送数据:"+s);
sendpayload = Helper.StrToHexByte(s);
return sendpayload;
}
}
public class RealtimeTMessage : THMessage
{
public double temp = -9999;
public long battery;
public long alarmstate;
public long alarmtrigger;
public RealtimeTMessage(byte[] p) : base(p)
{
temp = Helper.ConvertHexToSInt(rawdata.Substring(0, 4)) / 10f;
battery = Helper.ConvertHexToSInt(rawdata.Substring(4, 2));
alarmstate = Helper.ConvertHexToSInt(rawdata.Substring(6, 8));
alarmtrigger = Helper.ConvertHexToSInt(rawdata.Substring(14, 8));
}
public override byte[] GenerateMessage(THDeviceParams thdp)
{
if (thdp == null)
{
thdp = new THDeviceParams();
}
//header+sn+function code + datalen in byte+state+datalen+operation(realtme data)
string s = header + sn + Helper.ConverIntToHexStr2(funcode) + "0001" + "00" + "001B" + "0000";
DateTime current = DateTime.Now;
s = s +
Helper.ConverIntToHexStr2(current.Year - 2000) +
Helper.ConverIntToHexStr2(current.Month) +
Helper.ConverIntToHexStr2(current.Day) +
Helper.ConverIntToHexStr2(current.Hour) +
Helper.ConverIntToHexStr2(current.Minute) +
Helper.ConverIntToHexStr2(current.Second);
s = s + Helper.ConverIntToHexStr4(thdp.RTReportInterval);
s = s + Helper.ConverIntToHexStr4(thdp.RecordInterval);
s = s + Helper.ConverIntToHexStr2(thdp.dateTime.Hour) + Helper.ConverIntToHexStr2(thdp.dateTime.Minute);
s = s + Helper.ConverIntToHexStr2(thdp.HDReport);
s = s + Helper.ConverIntToHexStr4((int)(thdp.HTAlarm * 10)) +
Helper.ConverIntToHexStr4((int)(thdp.LTAlarm * 10)) +
Helper.ConverIntToHexStr4((int)(thdp.TBuffer * 10));
//不包含包尾的0x0D;
string temp = s;
string crc = string.Empty;
int cc = 0;
int.TryParse(Helper.CRC16(temp).ToString(), out cc);
crc = Helper.ConverIntToHexStr4(cc);
s = s + crc + ender;
Console.WriteLine("发送数据:" + s);
sendpayload = Helper.StrToHexByte(s);
return sendpayload;
}
}
public class AlarmTHMessage:THMessage
{
public double alarmValue = -9999;
public double temp = -9999;
public double humidity = -9999;
public bool poweroff = true;
public bool lowBattery = false;
public bool isOffline = true;
public AlarmType alarmType = AlarmType.None;
public DateTime timeOccur = new DateTime(2000,1,1,0,0,0);
public AlarmTHMessage(byte[] p) : base(p)
{
msgType = MessageType.Alarm;
alarmValue= Helper.ConvertHexToSInt(rawdata.Substring(0, 8)) / 10f;
alarmType = (AlarmType)Helper.ConvertHexToSInt(rawdata.Substring(8, 2));
switch(alarmType)
{
case AlarmType.HH: humidity = alarmValue; break;
case AlarmType.RemoveHH: humidity = alarmValue; break;
case AlarmType.LH: humidity = alarmValue; break;
case AlarmType.RemoveLH: humidity = alarmValue; break;
case AlarmType.HT:temp = alarmValue; break;
case AlarmType.RemoveHT: temp = alarmValue; break;
case AlarmType.LT: temp = alarmValue; break;
case AlarmType.RemoveLT: temp = alarmValue; break;
case AlarmType.Power:poweroff = true; break;
case AlarmType.RemovePower: poweroff = false; break;
case AlarmType.LowElectric: lowBattery = false; break;
case AlarmType.RemoveLowElectric: lowBattery = true; break;
case AlarmType.Offline: isOffline = true; break;
case AlarmType.Online: isOffline = false; break;
default:
alarmType = AlarmType.Unkown;
break;
}
int year = 2000+(int)Helper.ConvertHexToSInt(rawdata.Substring(10, 2));
int month = (int)Helper.ConvertHexToSInt(rawdata.Substring(12, 2));
int day = (int)Helper.ConvertHexToSInt(rawdata.Substring(14, 2));
int hour = (int)Helper.ConvertHexToSInt(rawdata.Substring(16, 2));
int min= (int)Helper.ConvertHexToSInt(rawdata.Substring(18, 2));
int sec = (int)Helper.ConvertHexToSInt(rawdata.Substring(20, 2));
timeOccur = new DateTime(year, month, day, hour, min, sec);
Console.WriteLine(Enum.GetName(typeof(AlarmType), alarmType) + "告警发生在:" + timeOccur.ToString("F"));
}
}
public class HistoryTHMessage: THMessage
{
public List<THRecord> historyReocrds;
public HistoryTHMessage(byte[] p) : base(p)
{
msgType = MessageType.History;
historyReocrds = new List<THRecord>();
for(int i = 0; i< datalen/10; i++)
{
double t = Helper.ConvertHexToSInt(rawdata.Substring(i * 20, 4)) / 10f;
double h= Helper.ConvertHexToSInt(rawdata.Substring(i * 20+4, 4)) / 10f;
int year = 2000+ (int)Helper.ConvertHexToSInt(rawdata.Substring(i * 20 + 8, 2));
int month = (int)Helper.ConvertHexToSInt(rawdata.Substring(i * 20 + 10, 2));
int day = (int)Helper.ConvertHexToSInt(rawdata.Substring(i * 20 + 12, 2));
int hour = (int)Helper.ConvertHexToSInt(rawdata.Substring(i * 20 + 14, 2));
int min = (int)Helper.ConvertHexToSInt(rawdata.Substring(i * 20 + 16, 2));
int sec = (int)Helper.ConvertHexToSInt(rawdata.Substring(i * 20 + 18, 2));
DateTime timeOccur = new DateTime(year, month, day, hour, min, sec);
THRecord th = new THRecord();
th.temp = t;
th.humidity = h;
th.time = timeOccur;
historyReocrds.Add(th);
}
}
}
public class HistoryTMessage : THMessage
{
public List<TRecord> historyReocrds;
public HistoryTMessage(byte[] p) : base(p)
{
msgType = MessageType.History;
historyReocrds = new List<TRecord>();
for (int i = 0; i < datalen/8; i++)
{
double t = Helper.ConvertHexToSInt(rawdata.Substring(i * 16, 4)) / 10f;
int year = (int)Helper.ConvertHexToSInt(rawdata.Substring(i * 16 + 4, 2));
int month = (int)Helper.ConvertHexToSInt(rawdata.Substring(i * 16 + 6, 2));
int day = (int)Helper.ConvertHexToSInt(rawdata.Substring(i * 16 + 8, 2));
int hour = (int)Helper.ConvertHexToSInt(rawdata.Substring(i * 16 + 10, 2));
int min = (int)Helper.ConvertHexToSInt(rawdata.Substring(i * 16 + 12, 2));
int sec = (int)Helper.ConvertHexToSInt(rawdata.Substring(i * 16 + 14, 2));
DateTime timeOccur = new DateTime(year, month, day, hour, min, sec);
TRecord th = new TRecord();
th.temp = t;
th.time = timeOccur;
historyReocrds.Add(th);
}
}
}
public class RegisterTHMessage : THMessage
{
public RegisterTHMessage(byte[] p) : base(p)
{
msgType = MessageType.Register7;
}
}
public enum MessageType
{
Realtime,Alarm,History,Register7,None,Unknown
}
//T:温度, TH:温湿度 Unkown表示未知可以扩展 None为初始值
public enum DeviceType
{
T, TH,Unknown,None
}
public enum AlarmType
{
HT = 1,
LT = 2,
HH = 3,
LH = 4,
HPA = 5,
TVoc = 6,
PM25 = 7,
PM01 = 8,
PM10 = 9,
HC02 = 10,
LC02 = 11,
Power = 12,
Offline = 13,
LowElectric = 14,
HNH3=15,
Hlight=16,
Llight=17,
HPressuer=18,
LPressuer=19,
HPh=20,
LPh=21,
HDi1=22,
LDi1=23,
HDi2=24,
LDi2=25,
RemoveHT=101,
RemoveLT = 102,
RemoveHH = 103,
RemoveLH = 104,
RemoveHPA = 105,
RemoveTVoc = 106,
RemovePM25=107,
RemovePM01 = 108,
RemovePM10 = 109,
RemoveHC02=110,
RemoveLC02 = 111,
RemovePower=112,
Online=113,
RemoveLowElectric =114,
RemoveHNH3 = 115,
RemoveHlight = 116,
RemoveLlight = 117,
RemoveHPressuer = 118,
RemoveLPressuer = 119,
RemoveHPh = 120,
RemoveLPh = 121,
Unkown = 9999,
None = 0
}
public struct THRecord
{
public double temp;
public double humidity;
public DateTime time;
}
public struct TRecord
{
public double temp;
public DateTime time;
}
public class THDeviceParams
{
public int RTReportInterval;
public int RecordInterval;
public int HDReport;
public double HTAlarm;
public double LTAlarm;
public double TBuffer;
public double HHAlarm;
public double LHAlarm;
public double HBuffer;
public DateTime dateTime;
public THDeviceParams()
{
RTReportInterval = 1;
RecordInterval = 1;
HDReport = 0;
HTAlarm = 35.0;
LTAlarm = -10.0;
TBuffer = 0.1;
HHAlarm = 80.0;
LHAlarm = 40;
HBuffer = 0.1;
dateTime = new DateTime(2000, 1, 1, 0, 10, 0);
}
public THDeviceParams(int a, int b, int c, double d, double e, double f, double g, double h, double i,DateTime dt)
{
RTReportInterval = a;
RecordInterval = b;
HDReport = c;
HTAlarm = d;
LTAlarm = e;
TBuffer = f;
HHAlarm = g;
LHAlarm = h;
HBuffer = i;
dateTime = dt;
}
}
}