hj212协议如何和php通讯,HJ212数据传输标准报文解析
HJ212分為2005年(HJ/T212-2005)和2017年(HJ212-2017)的版本,略有不同。
網(wǎng)上沒找到非常官方的渠道下載,在這貼一份2017年版本的下載地址
TCP/IP通訊包組成
名稱
類型
長度
描述
包頭
字符
2
固定為##
數(shù)據(jù)段長度
十進(jìn)制整數(shù)
4
表示數(shù)據(jù)段長度,如長度336則為0336
數(shù)據(jù)段
字符
0-1024
變長的數(shù)據(jù),為包的傳輸內(nèi)容
CRC校驗
十六進(jìn)制整數(shù)
4
用于校驗數(shù)據(jù)包完整性的CRC校驗值,后續(xù)附上算法
包尾
字符
2
固定為(回車、換行)
通訊包數(shù)據(jù)段組成
HJ/T212-2005
名稱
類型
長度
描述
請求編碼QN
字符
20
精確到毫秒的時間戳:QN=YYYYMMDDhhmmsszzz,用來唯一標(biāo)識一次命令交互
系統(tǒng)編碼ST
字符
5
系統(tǒng)編號
命令編號CN
字符
7
命令編號
訪問密碼PW
字符
6
訪問密碼
設(shè)備唯一標(biāo)識MN
字符
14
監(jiān)測點編號
拆分包及應(yīng)答標(biāo)志Flag
字符
3
見文檔原文
總包號PNUM
字符
4
表示本次通訊總共包含的包數(shù)
包號PNO
字符
4
PNO指示當(dāng)前數(shù)據(jù)包的包號
指令參數(shù)CP
字符
0-960
CP=&&數(shù)據(jù)區(qū)&&
HJ212-2017
名稱
類型
長度
描述
請求編碼QN
字符
20
精確到毫秒的時間戳:QN=YYYYMMDDhhmmsszzz,用來唯一標(biāo)識一次命令交互
系統(tǒng)編碼ST
字符
5
系統(tǒng)編號
命令編號CN
字符
7
命令編號
訪問密碼PW
字符
9
訪問密碼
設(shè)備唯一標(biāo)識MN
字符
27
監(jiān)測點編號
拆分包及應(yīng)答標(biāo)志Flag
字符
8
見文檔原文
總包號PNUM
字符
9
表示本次通訊總共包含的包數(shù)
包號PNO
字符
8
PNO指示當(dāng)前數(shù)據(jù)包的包號
指令參數(shù)CP
字符
0-950
CP=&&數(shù)據(jù)區(qū)&&
報文解析
因2005、2017對原始報文的解析上沒有什么巨大分別,只是不同字段的長度在2017協(xié)議中有所擴(kuò)展。在此僅以一例2005年規(guī)范的報文作為樣例(因簡書格式問題,調(diào)試時請自行補(bǔ)全包尾換行符):
"##0336ST=31;CN=2011;PW=123456;MN=63010000020001;CP=&&DataTime=20200108143205;B02-Rtd=9.88,B02-Flag=N;01-Rtd=10.73,01-ZsRtd=12.38,01-Flag=N;02-Rtd=0.705,02-ZsRtd=0.814,02-Flag=N;03-Rtd=69.064,03-ZsRtd=79.684,03-Flag=N;S01-Rtd=5.8,S01-Flag=N;S02-Rtd=19.38,S02-Flag=N;S03-Rtd=99.04,S03-Flag=N;S08-Rtd=-46.12,S08-Flag=N;S05-Rtd=14.66,S05-Flag=N&&8EC1"
代碼解析
在這里不贅述如何通過TCP/IP協(xié)議獲得報文再轉(zhuǎn)成字符串的了,直接貼一些關(guān)鍵代碼(C#),直接看可能比看協(xié)議文檔要快一些。
本來是想封裝個類庫的…不過考慮我實際使用情況只有最簡單的接受解析數(shù)據(jù),沒調(diào)試過收發(fā)控制命令、數(shù)據(jù)分包。單純根據(jù)文檔封裝出來可能會有很大的局限性(其實是懶)。
因力求樣例代碼精簡,可能缺乏防錯及數(shù)據(jù)結(jié)構(gòu)展現(xiàn),大家可以針對自己實際業(yè)務(wù)需求做相應(yīng)完善。
//Msg 是解析TCP/IP報文后獲得的報文字符串
if (string.IsNullOrEmpty(Msg) || Msg.Length < 12 || !Msg.StartsWith("##") || !Msg.EndsWith("\r\n"))
{
Console.WriteLine("不是HJ212協(xié)議的報文!");
return false;
}
var msg_len_str = Msg.Substring(2, 4);
if (!int.TryParse(msg_len_str, out int msg_len))
{
Console.WriteLine("報文格式非法,報文長度無法解析!");
return false;
}
var content = Msg.Substring(6, msg_len);
var msg_crc = Msg.Substring(6 + msg_len, 4);
var calc_crc = CalcCRC(content);
if (calc_crc != msg_crc)
{
Console.WriteLine($"CRC校驗失敗! MsgCRC:{msg_crc} CalcCRC:{calc_crc}");
return false;
}
var cp = Regex.Match(content, @"CP=&&[\S]*&&");
var msg_head = string.Empty;
if (!cp.Success)
{
Console.WriteLine("未匹配到數(shù)據(jù)!");
msg_head = content;
}
msg_head = content.Substring(0, cp.Index);
var headers = msg_head.Split(';');
for (int i = 0; i < headers.Length - 1; i++)
{
var index = headers[i].IndexOf('=');
if (index == -1) continue;
Console.WriteLine($"Header key:{headers[i].Substring(0, index)} Header Value:{headers[i].Substring(index + 1, headers[i].Length - index - 1)}");
}
if (cp.Success)
{
var datadic = cp.Value.Substring(5, cp.Length - 7);
var dataarr = datadic.Split(';');
foreach (var rawdata in dataarr)
{
var items = rawdata.Split(',');
foreach (var rawitem in items)
{
var index = rawitem.IndexOf("=");
if (index == -1)
{
return false;
}
Console.WriteLine($"Data Name:{rawitem.Substring(0, index)} Data Value:{rawitem.Substring(index + 1, rawitem.Length - index - 1)}");
}
}
}
return true;
針對以上報文的解析如下:
對于Data Name的含義,參照協(xié)議文檔中的字段對照表即可
如B02-Rtd代表廢氣-實時采樣數(shù)據(jù),不一定完全照搬文檔,可與對接廠商根據(jù)現(xiàn)場情況擬定。
CRC算法
CRC算法如下(摘自HJ212-2017,2005版本沒有明確定義但實測是兼容的,語言是C):
一定要注意CRC是針對數(shù)據(jù)段進(jìn)行計算的,去頭(##、報文長度字符),去尾(CRC字符、包尾換行符)
unsigned int CRC16_Checkout(unsigned char *puchMsg, unsigned int usDataLen)
{
unsigned int i, j, crc_reg, check;
crc_reg = 0xFFFF;
for (i = 0; i < usDataLen; i++)
{
crc_reg = (crc_reg >> 8) ^ puchMsg[i];
for (j = 0; j < 8; j++)
{
check = crc_reg & 0x0001;
crc_reg >>= 1;
if (check == 0x0001)
{
crc_reg ^= 0xA001;
}
}
}
return crc_reg;
}
總結(jié)
以上是生活随笔為你收集整理的hj212协议如何和php通讯,HJ212数据传输标准报文解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 彩铃开发,motorola铃声
- 下一篇: PHP判断标量,php中is_scala