大家好,欢迎来到IT知识分享网。
环保 HJ212协议解析
HJ212协议简介
6.1.1通讯包结构组成
名称 | 类型 | 长度 | 描述 |
---|---|---|---|
包头 | 字符 | 2 | 固定为 |
数据段长度 | 十进制整数 | 4 | 数据段的ASCII字符数。例如数据段的字符数为128,则写为“0128” |
数据段 | 字符 | 0<=n<=9999 | 变长的数据 |
CRC校验 | 十六进制 | 4 | 数据段的校验结果,例如C901,如果CRC错,即执行超时 |
包尾 | 字符 | 2 | 回车换行(\r\n) |
基于C++的HJ212解析类
#pragma once #include <type.h> #include <func.h> // 国标 212 // 所有的通讯包都是由ASCII码 class GB212 {
public: typedef std::vector<GB212> GB212Array; typedef std::vector<StringMap> DataItemArray; // 切分数据 static void split_kv(DataItemArray& _return, const String& cp) {
auto arr1 = Math::Tools::split(cp, ";", true); for (auto& i : arr1) {
StringMap item; auto arr2 = Math::Tools::split(i, ",", true); for (auto& j : arr2) {
auto arrkv = Math::Tools::split(j, "=", false); if (arrkv.size() == 2) {
item.insert(std::make_pair(arrkv[0], arrkv[1])); } } _return.emplace_back(item); } } // 组合数据 static String join_kv(const DataItemArray& arr) {
StringArray item; for (auto& i : arr) {
StringArray arrkv; for (auto& j : i) {
arrkv.emplace_back(j.first + "=" + j.second); } item.emplace_back(Math::Tools::join(arrkv, ",")); } return Math::Tools::join(item, ";"); } // 数据区 struct DataCP {
DataCP() {
} DataCP(const String& s) {
DataItemArray arr; split_kv(arr, s); for (auto& i : arr) {
auto kvlen = i.size(); String key; for (auto& j : i) {
// 对指定监测因子的项,统一使用因子代表 if (j.first == "PolId") {
key = j.second; this->Value[key] = StringMap(); continue; } String name, field; // 查询是否包含标准协议中的设备状态 auto f1 = j.first.find("SB"); auto f2 = j.first.find("-"); if (f2 != String::npos && f1 != 0) {
// a20004-Rtd name-field name = j.first.substr(0, f2); field = j.first.substr(f2 + 1); // i11001-Info field if (field == "Info") {
field = name; } else {
key = name; } } else {
if (j.first == "DataTime") {
this->DataTime = j.second; } name = j.first; key = name; field = "value"; } this->Value[key].insert(std::make_pair(field, j.second)); } } // 如果不包含DataTime字段,则将当前时间作为数据时间 if (this->Value.find("DataTime") == this->Value.end()) {
this->DataTime = Math::Date::getnow("%04d%02d%02d%02d%02d%02d"); } } void clear() {
this->Value.clear(); } std::map<String, StringMap> Value; String DataTime; }; // 数据段 struct Data {
String QN; // 请求编码 20字符 QN=YYYYMMDDHHmmssZZZ String ST; // 系统编码 5字符 ST=21 String CN; // 命令编码 7字符 CN=2011 String PW; // 访问密码 9字符 PW= String MN; // 设备标识 27字符 MN=[0-9A-F] String Flag = "4"; // 标志位 8整数 Flag=7 bit:000001(协议版本)0(是否有包号)0(是否需应答) String PNUM; // 总包数 9字符 PNUM=0000 [不分包则没有本字段] String PNO; // 包号 8字符 PNO=0000 [不分包则没有本字段] String CP; // 指令参数 <=950字符 CP=&&数据区&& DataCP CPs; // 设置flag, bit从1开始 void set_flag(uint32 bit, bool enable) {
int32 flag = 4; Math::Tools::to_int(flag, Flag); enable ? SETBIT(flag, bit) : CLRBIT(flag, bit); this->Flag = std::to_string(flag); } // 获取flag, bit从1开始 bool get_flag(uint32 bit) const {
int32 flag = 4; Math::Tools::to_int(flag, Flag); return GETBIT(flag, bit); } // 有效性 bool valid() const {
return bvalid; } // 长度 size_t size() const {
#define ADDDataItem(name, subnum) result += name.size() + (name.empty() ? 0 : subnum); size_t result = 0; ADDDataItem(QN, 3); ADDDataItem(ST, 3); ADDDataItem(CN, 3); ADDDataItem(PW, 3); ADDDataItem(MN, 3); ADDDataItem(Flag, 5); ADDDataItem(PNUM, 5); ADDDataItem(PNO, 4); ADDDataItem(CP, 3); #undef ADDDataItem return QN.size() + ST.size() + CN.size() + PW.size() + MN.size() + Flag.size() + PNUM.size() + PNO.size() + CP.size(); } // 构造函数 Data() {
} Data(const String& s){
CopyStr(s); } // 赋值构造 Data& operator=(const String& str) {
CopyStr(str); return *this; } void CopyStr(const String& s) {
auto d1 = s.find("CP=&&"); auto d2 = s.find("&&", d1 + 5); String tmp; if (d1 != String::npos && d2 != String::npos) {
CP = s.substr(d1 + 5, d2 - d1 - 5); CPs = CP; tmp = s.substr(0, d1) + s.substr(d2 + 2); } else {
tmp = s; } StringMap it; auto arr1 = Math::Tools::split(tmp, ";", true); for (auto& i : arr1) {
auto arr2 = Math::Tools::split(i, "=", false); if (arr2.size() == 2) {
it.insert(std::make_pair(arr2[0], arr2[1])); } } #define SETDataItem(name) name = it[#name]; SETDataItem(QN); SETDataItem(ST); SETDataItem(CN); SETDataItem(PW); SETDataItem(MN); SETDataItem(Flag); SETDataItem(PNUM); SETDataItem(PNO)
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/139628.html