Commit f5cb7bcf authored by captainwong's avatar captainwong

兼容WiFi主机的MAC地址账号

parent 06734ec6
...@@ -20,6 +20,27 @@ ...@@ -20,6 +20,27 @@
#define dline dprintf("%s %d\n", __FILE__, __LINE__); #define dline dprintf("%s %d\n", __FILE__, __LINE__);
#define dmsg dline; dprintf #define dmsg dline; dprintf
static uint8_t hex2char(uint8_t h) {
h &= 0x0F;
if (h > 9)
return 'A' + h - 10;
else
return '0' + h;
}
static uint8_t char2hex(uint8_t c) {
if ('0' <= c && c <= '9')
return c - '0';
else if ('A' <= c && c <= 'F')
return c - 'A' + 10;
else if ('a' <= c && c <= 'f')
return c - 'a' + 10;
else
return 0xFF;
}
void ademcoPrint(const ademco_char_t* p, size_t len) { void ademcoPrint(const ademco_char_t* p, size_t len) {
while (len--) { while (len--) {
if (isprint(*(const uint8_t*)p)) if (isprint(*(const uint8_t*)p))
...@@ -336,7 +357,7 @@ uint16_t ademcoCRC16(const ademco_char_t* buff, size_t len) { ...@@ -336,7 +357,7 @@ uint16_t ademcoCRC16(const ademco_char_t* buff, size_t len) {
return crc; return crc;
} }
size_t ademcoAppendDataSegment(ademco_char_t* buff, AdemcoId ademcoId, AdemcoEvent ademcoEvent, AdemcoGG gg, AdemcoZone zone) { size_t ademcoAppendDataSegment(ademco_char_t* buff, const char* acct, AdemcoId ademcoId, AdemcoEvent ademcoEvent, AdemcoGG gg, AdemcoZone zone) {
char* p = (char*)buff; char* p = (char*)buff;
if (ademcoEvent == EVENT_INVALID_EVENT) { if (ademcoEvent == EVENT_INVALID_EVENT) {
*p++ = '['; *p++ = '[';
...@@ -346,8 +367,12 @@ size_t ademcoAppendDataSegment(ademco_char_t* buff, AdemcoId ademcoId, AdemcoEve ...@@ -346,8 +367,12 @@ size_t ademcoAppendDataSegment(ademco_char_t* buff, AdemcoId ademcoId, AdemcoEve
*p++ = '['; *p++ = '[';
*p++ = '#'; *p++ = '#';
snprintf(p, 6 + 1, "%06X", ademcoId % ADEMCO_ID_SENTINEL); if (acct && ademcoId == 0) {
p += 6; p += snprintf(p, 20, "%s", acct);
} else {
snprintf(p, 6 + 1, "%06X", ademcoId % ADEMCO_ID_SENTINEL);
p += 6;
}
*p++ = '|'; *p++ = '|';
...@@ -374,20 +399,20 @@ size_t ademcoAppendDataSegment(ademco_char_t* buff, AdemcoId ademcoId, AdemcoEve ...@@ -374,20 +399,20 @@ size_t ademcoAppendDataSegment(ademco_char_t* buff, AdemcoId ademcoId, AdemcoEve
*p++ = ']'; *p++ = ']';
assert(p - (char*)buff == ADEMCO_PACKET_DATA_SEGMENT_FULL_LEN); //assert(p - (char*)buff == ADEMCO_PACKET_DATA_SEGMENT_FULL_LEN);
*p++ = '\0'; // for debug convenience *p = '\0'; // for debug convenience
return ADEMCO_PACKET_DATA_SEGMENT_FULL_LEN; return p - (char*)buff;
} }
} }
size_t ademcoAppendDataSegment2(AdemcoDataSegment* dataSegment, AdemcoId ademcoId, AdemcoEvent ademcoEvent, AdemcoGG gg, AdemcoZone zone) { size_t ademcoAppendDataSegment2(AdemcoDataSegment* dataSegment, const char* acct, AdemcoId ademcoId, AdemcoEvent ademcoEvent, AdemcoGG gg, AdemcoZone zone) {
dataSegment->ademcoId = ademcoId; dataSegment->ademcoId = ademcoId;
dataSegment->ademcoEvent = ademcoEvent; dataSegment->ademcoEvent = ademcoEvent;
dataSegment->gg = gg; dataSegment->gg = gg;
dataSegment->zone = zone; dataSegment->zone = zone;
return dataSegment->raw_len = ademcoAppendDataSegment(dataSegment->raw, ademcoId, ademcoEvent, gg, zone); return dataSegment->raw_len = ademcoAppendDataSegment(dataSegment->raw, acct, ademcoId, ademcoEvent, gg, zone);
} }
AdemcoParseResult ademcoParseDataSegment(const ademco_char_t* packet, size_t packet_len, AdemcoDataSegment* dataSegment) { AdemcoParseResult ademcoParseDataSegment(const ademco_char_t* packet, size_t packet_len, AdemcoDataSegment* dataSegment) {
...@@ -725,7 +750,7 @@ size_t ademcoMakeHbPacket(ademco_char_t* dst_buff, size_t len, uint16_t seq, con ...@@ -725,7 +750,7 @@ size_t ademcoMakeHbPacket(ademco_char_t* dst_buff, size_t len, uint16_t seq, con
snprintf(p, 7, "%06X", ademcoId); snprintf(p, 7, "%06X", ademcoId);
p += 6; p += 6;
} }
p += ademcoAppendDataSegment(p, ademcoId, ademcoEvent, gg, zone); p += ademcoAppendDataSegment(p, acct, ademcoId, ademcoEvent, gg, zone);
if (xdata && xdata->raw_len > 0) { if (xdata && xdata->raw_len > 0) {
memcpy(p, xdata->raw, xdata->raw_len); memcpy(p, xdata->raw, xdata->raw_len);
p += xdata->raw_len; p += xdata->raw_len;
...@@ -788,7 +813,7 @@ size_t ademcoMakeHbPacket2(AdemcoPacket* pkt, uint16_t seq, const char* acct, Ad ...@@ -788,7 +813,7 @@ size_t ademcoMakeHbPacket2(AdemcoPacket* pkt, uint16_t seq, const char* acct, Ad
AdemcoEvent ademcoEvent, AdemcoGG gg, AdemcoZone zone, const AdemcoXDataSegment* xdata) { AdemcoEvent ademcoEvent, AdemcoGG gg, AdemcoZone zone, const AdemcoXDataSegment* xdata) {
pkt->seq = seq; pkt->seq = seq;
copyAcct2AdemcoPacket(pkt, acct); copyAcct2AdemcoPacket(pkt, acct);
ademcoAppendDataSegment2(&pkt->data, ademcoId, ademcoEvent, gg, zone); ademcoAppendDataSegment2(&pkt->data, acct, ademcoId, ademcoEvent, gg, zone);
if (xdata && xdata->raw_len > 0) { if (xdata && xdata->raw_len > 0) {
pkt->xdata.lenghFormat = xdata->lenghFormat; pkt->xdata.lenghFormat = xdata->lenghFormat;
memcpy(pkt->xdata.raw, xdata->raw, xdata->raw_len); memcpy(pkt->xdata.raw, xdata->raw, xdata->raw_len);
...@@ -882,7 +907,7 @@ AdemcoParseResult ademcoPacketParse(const ademco_char_t* buff, size_t len, Ademc ...@@ -882,7 +907,7 @@ AdemcoParseResult ademcoPacketParse(const ademco_char_t* buff, size_t len, Ademc
// #acct // #acct
const char* pacct = ++p; const char* pacct = ++p;
while (p < pcr && *p != '[') { while (p < pcr && *p != '[') {
if (!isalnum(*p)) { p = NULL; dline; break; } if (!isxdigit(*p)) { p = NULL; dline; break; }
p++; p++;
} }
if (p == NULL || p >= pcr || *p != '[' || p - pacct >= ADEMCO_PACKET_ACCT_MAX_LEN) { dline; break; } if (p == NULL || p >= pcr || *p != '[' || p - pacct >= ADEMCO_PACKET_ACCT_MAX_LEN) { dline; break; }
...@@ -965,6 +990,34 @@ size_t ademcoHiLoArrayToDecStr(ademco_char_t* str, const uint8_t* arr, size_t le ...@@ -965,6 +990,34 @@ size_t ademcoHiLoArrayToDecStr(ademco_char_t* str, const uint8_t* arr, size_t le
return p - str; return p - str;
} }
size_t ademcoHiLoArrayToDecStr2(ademco_char_t* str, const uint8_t* arr, size_t len) {
char* p = str;
for (size_t i = 0; i < len; i++) {
char c = (arr[i] >> 4) & 0x0F;
if (c > 9) {
if (i < 6) {
*p++ = c - 10 + 'A';
} else {
return p - str;
}
} else {
*p++ = c + '0';
}
c = (arr[i] & 0x0F);
if (c > 9) {
if (i < 6) {
*p++ = c - 10 + 'A';
} else {
return p - str;
}
} else {
*p++ = c + '0';
}
}
return p - str;
}
size_t ademcoDecStrToHiLoArray(uint8_t* arr, size_t len, const char* str) { size_t ademcoDecStrToHiLoArray(uint8_t* arr, size_t len, const char* str) {
char* p = (char*)arr; char* p = (char*)arr;
size_t slen = str ? strlen(str) : 0; size_t slen = str ? strlen(str) : 0;
...@@ -993,14 +1046,36 @@ size_t ademcoDecStrToHiLoArray(uint8_t* arr, size_t len, const char* str) { ...@@ -993,14 +1046,36 @@ size_t ademcoDecStrToHiLoArray(uint8_t* arr, size_t len, const char* str) {
return len; return len;
} }
static uint8_t hex2char(uint8_t h) { size_t ademcoDecStrToHiLoArray2(uint8_t* arr, size_t len, const char* str) {
h &= 0x0F; char* p = (char*)arr;
if (h > 9) size_t slen = str ? strlen(str) : 0;
return 'A' + h - 10; if (slen > len * 2)
else slen = len * 2;
return '0' + h; for (size_t i = 0; i < slen; i += 2) {
char hi = str[i];
if (isxdigit(hi)) {
if (i + 1 < slen) {
char lo = str[i + 1];
if (isxdigit(lo))
*p++ = (char2hex(hi) << 4) | (char2hex(lo) & 0x0F);
else {
*p++ = (char2hex(hi) << 4) | 0x0F;
break;
}
} else {
*p++ = (char2hex(hi) << 4) | 0x0F;
break;
}
} else {
break;
}
}
while ((char*)arr + len > p)
*p++ = 0xFF;
return len;
} }
size_t ademcoHexArrayToStr(char* str, const uint8_t* arr, size_t len) { size_t ademcoHexArrayToStr(char* str, const uint8_t* arr, size_t len) {
char* p = str; char* p = str;
for (size_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
...@@ -1010,17 +1085,6 @@ size_t ademcoHexArrayToStr(char* str, const uint8_t* arr, size_t len) { ...@@ -1010,17 +1085,6 @@ size_t ademcoHexArrayToStr(char* str, const uint8_t* arr, size_t len) {
return p - str; return p - str;
} }
static uint8_t char2hex(uint8_t c) {
if ('0' <= c && c <= '9')
return c - '0';
else if ('A' <= c && c <= 'F')
return c - 'A' + 10;
else if ('a' <= c && c <= 'f')
return c - 'a' + 10;
else
return 0xFF;
}
size_t ademcoHexStrToArray(uint8_t* arr, const char* str, uint8_t padding) { size_t ademcoHexStrToArray(uint8_t* arr, const char* str, uint8_t padding) {
uint8_t* p = arr; uint8_t* p = arr;
uint8_t hi = 0, lo = 0; uint8_t hi = 0, lo = 0;
......
...@@ -380,9 +380,9 @@ ADEMCO_EXPORT_SYMBOL const char* ademcoEventToStringChinese(AdemcoEvent ademcoEv ...@@ -380,9 +380,9 @@ ADEMCO_EXPORT_SYMBOL const char* ademcoEventToStringChinese(AdemcoEvent ademcoEv
//////////////////////// AdemcoDataSegment functions //////////////////////// //////////////////////// AdemcoDataSegment functions ////////////////////////
//! make a `DATA` packet and store to `packet`, return length //! make a `DATA` packet and store to `packet`, return length
ADEMCO_EXPORT_SYMBOL size_t ademcoAppendDataSegment(ademco_char_t* packet, AdemcoId ademcoId, AdemcoEvent ademcoEvent, AdemcoGG gg, AdemcoZone zone); ADEMCO_EXPORT_SYMBOL size_t ademcoAppendDataSegment(ademco_char_t* packet, const char* acct, AdemcoId ademcoId, AdemcoEvent ademcoEvent, AdemcoGG gg, AdemcoZone zone);
//! make a `DATA` packet and store to `dataSegment`, return length //! make a `DATA` packet and store to `dataSegment`, return length
ADEMCO_EXPORT_SYMBOL size_t ademcoAppendDataSegment2(AdemcoDataSegment* dataSegment, AdemcoId ademcoId, AdemcoEvent ademcoEvent, AdemcoGG gg, AdemcoZone zone); ADEMCO_EXPORT_SYMBOL size_t ademcoAppendDataSegment2(AdemcoDataSegment* dataSegment, const char* acct, AdemcoId ademcoId, AdemcoEvent ademcoEvent, AdemcoGG gg, AdemcoZone zone);
//! parse `DATA` packet, if ok, `dataSegment`'s members will be useful //! parse `DATA` packet, if ok, `dataSegment`'s members will be useful
ADEMCO_EXPORT_SYMBOL AdemcoParseResult ademcoParseDataSegment(const ademco_char_t* packet, size_t packet_len, AdemcoDataSegment* dataSegment); ADEMCO_EXPORT_SYMBOL AdemcoParseResult ademcoParseDataSegment(const ademco_char_t* packet, size_t packet_len, AdemcoDataSegment* dataSegment);
// return 0 for empty packet, CONGWIN_FE100_PACKET_LEN for success // return 0 for empty packet, CONGWIN_FE100_PACKET_LEN for success
...@@ -459,6 +459,16 @@ ADEMCO_EXPORT_SYMBOL uint16_t ademcoCRC16(const ademco_char_t* buff, size_t len) ...@@ -459,6 +459,16 @@ ADEMCO_EXPORT_SYMBOL uint16_t ademcoCRC16(const ademco_char_t* buff, size_t len)
// 示例:输入数组:0x18 0x24 0x08 0x88 0x10 0x1f 0xff,输出字符串"18240888101" // 示例:输入数组:0x18 0x24 0x08 0x88 0x10 0x1f 0xff,输出字符串"18240888101"
ADEMCO_EXPORT_SYMBOL size_t ademcoHiLoArrayToDecStr(ademco_char_t* str, const uint8_t* arr, size_t len); ADEMCO_EXPORT_SYMBOL size_t ademcoHiLoArrayToDecStr(ademco_char_t* str, const uint8_t* arr, size_t len);
// 将一串以高低字节表示的十六进制数组转换为字符串
// 每个字节的高四位和低四位若不大于9,将该四位表示的数字以10进制ascii码填入str,否则:
// 若定长6字节包含a~f,说明是WiFi主机
// 返回字符串长度
// 注意:函数不会在str末尾补 null terminator
// 调用者应确保str有足够空间,至少len的2倍,否则会崩溃
// 示例:输入数组:0x18 0x24 0x08 0x88 0x10 0x1f 0xff,输出字符串"18240888101"
// 示例:输入数组:0x24 0x94 0x94 0x4c 0x48 0x15 0xff,输出字符串"2494944C4815"
ADEMCO_EXPORT_SYMBOL size_t ademcoHiLoArrayToDecStr2(ademco_char_t* str, const uint8_t* arr, size_t len);
// 将一个10进制数字符串转为高低字节表示的数组,节省空间 // 将一个10进制数字符串转为高低字节表示的数组,节省空间
// str应只包含'0'~'9',否则失败返回0 // str应只包含'0'~'9',否则失败返回0
// str长度若大于len * 2,str[len]及之后的内容将被舍弃以避免溢出 // str长度若大于len * 2,str[len]及之后的内容将被舍弃以避免溢出
...@@ -469,6 +479,16 @@ ADEMCO_EXPORT_SYMBOL size_t ademcoHiLoArrayToDecStr(ademco_char_t* str, const ui ...@@ -469,6 +479,16 @@ ADEMCO_EXPORT_SYMBOL size_t ademcoHiLoArrayToDecStr(ademco_char_t* str, const ui
// 示例:输入NULL,返回 9个 0xFF // 示例:输入NULL,返回 9个 0xFF
ADEMCO_EXPORT_SYMBOL size_t ademcoDecStrToHiLoArray(uint8_t* arr, size_t len, const char* str); ADEMCO_EXPORT_SYMBOL size_t ademcoDecStrToHiLoArray(uint8_t* arr, size_t len, const char* str);
// 将一个16进制数字符串转为高低字节表示的数组,节省空间
// str应只包含'0'~'9', 'A'~'F', 'a'~'f',否则失败返回0
// str长度若大于len * 2,str[len]及之后的内容将被舍弃以避免溢出
// 转换后的长度若不满len,则以0xF补满。
// 示例:输入字符串"123ABC",len=6, 则 arr 内容为 0x12 0x3a 0xbc 0xff 0xff 0xff
// 示例:输入字符串 "18240888101", len=9, 则arr内容为 0x18 0x24 0x08 0x88 0x10 0x1f 0xff 0xff 0xff, return 9
// 示例:输入字符串 "12345678901234567890", len=9, 则arr内容为 0x12 0x34 0x56 0x78 0x90 0x12 0x34 0x56 0x78, return 9
// 示例:输入NULL,返回 9个 0xFF
ADEMCO_EXPORT_SYMBOL size_t ademcoDecStrToHiLoArray2(uint8_t* arr, size_t len, const char* str);
// 将一串字节流转换为可打印形式 // 将一串字节流转换为可打印形式
// 返回str长度(len * 2) // 返回str长度(len * 2)
// 调用者应确保str有足够的容量,至少len*2 // 调用者应确保str有足够的容量,至少len*2
......
...@@ -37,23 +37,23 @@ ...@@ -37,23 +37,23 @@
### **各字段说明:** ### **各字段说明:**
* `LF` 固定起始符 0x0A * `LF` 固定起始符 `0x0A`
* `crc16` 固定长度4Bytes, 表示从 `id` 的左引号开始,至 `timestamp` 的最后一个字节结束(长度为 `length` )计算出的 `crc16` 值,以16进制数字的ASCII码表示 * `crc16` 固定长度 `4 Bytes`, 表示从 `id` 的左引号开始,至 `timestamp` 的最后一个字节结束(长度为 `length` )计算出的 `crc16` 值,以16进制数字的ASCII码表示
* `length``id` 的左引号开始,至 `timestamp` 的最后一个字节结束的字符串长度,以16进制数字的ASCII码表示,定长4Bytes * `length``id` 的左引号开始,至 `timestamp` 的最后一个字节结束的字符串长度,以16进制数字的ASCII码表示,定长 `4 Bytes`
* `"id"` 事件类型,分为 `NULL, ACK, DUH, ADM-CID, HENG-BO` 等,分别为心跳、回应、错误、主机事件、恒博事件。除事件 `ADM-CID/HENG-BO` 外,其他三种类型的 `data` 段都为空值 `[]` * `"id"` 事件类型,分为 `NULL, ACK, DUH, ADM-CID, HENG-BO` 等,分别为心跳、回应、错误、主机事件、恒博事件。除事件 `ADM-CID/HENG-BO` 外,其他三种类型的 `data` 段都为空值 `[]`
* `seq` 序号,定长4 Bytes,代表的十进制数字为主机发送命令字的序号,范围 `0001~9999`,超过 `9999` 则从1开始再次循环。`seq` 被用来判断主机发出的 `ADM-CID/HENG-BO` 类型命令字是否得到接警平台的正确处理。例:平台要对主机发出的 `NULL/ADM-CID/HENG-BO` 类型事件进行回应,回应的 `seq` 以接收到的 `seq` 为准。主机收到回应后会判断 `seq` 与之前发送的 `seq` 是否相同:相同则说明该事件已得到处理,否则会进行重发。 * `seq` 序号,定长 `4 Bytes`,代表的十进制数字为主机发送命令字的序号,范围 `0001~9999`,超过 `9999` 则从1开始再次循环。`seq` 被用来判断主机发出的 `ADM-CID/HENG-BO` 类型命令字是否得到接警平台的正确处理。例:平台要对主机发出的 `NULL/ADM-CID/HENG-BO` 类型事件进行回应,回应的 `seq` 以接收到的 `seq` 为准。主机收到回应后会判断 `seq` 与之前发送的 `seq` 是否相同:相同则说明该事件已得到处理,否则会进行重发。
* `Rrcvr` 以R开头的一段十六进制数字字符串,数字长度范围`1~6`,暂时仅占位,无意义。字段总长度`2~7` Bytes。 * `Rrcvr` 以R开头的一段十六进制数字字符串,数字长度范围`1~6`,暂时仅占位,无意义。字段总长度`2~7` Bytes。
* `Lpref` 以L开头的一段十六进制数字字符串,数字长度范围`1~6`,暂时仅占位,无意义。字段总长度`2~7` Bytes。 * `Lpref` 以L开头的一段十六进制数字字符串,数字长度范围`1~6`,暂时仅占位,无意义。字段总长度`2~7` Bytes。
* `#acct``#`开头,后跟有限位十进制数字(SIM卡号或出厂编号)或安定宝ID,表示主机的账号(有SIM卡的主机为手机号,无SIM卡的是出厂编号,有些主机直连时使用了安定宝ID为账号) * `#acct``#`开头,后跟有限位十六进制数字(`SIM`卡号或出厂编号或`MAC`地址或安定宝ID),表示主机的账号(有SIM卡的主机为手机号,无`SIM`卡的是出厂编号,有些主机直连时使用了安定宝ID为账号,`WiFi`主机使用 `MAC` 地址作为主机账号)
* `data` 格式为 `[]`(左右中括号,无空格,定长2Byte)或 `[#ademco_id|event gg zone]`(有空格)。当事件类型为 `NULL/ACK/DUH``data` 段为`[]`;当事件类型为 `ADM-CID/HENG-BO``data` 段格式为 `[#acct|event gg zone]` * `data` 格式为 `[]`(左右中括号,无空格,定长2Byte)或 `[#ademco_id|event gg zone]`(有空格)。当事件类型为 `NULL/ACK/DUH``data` 段为`[]`;当事件类型为 `ADM-CID/HENG-BO``data` 段格式为 `[#ademco_id|event gg zone]`
* `#ademco_id` 主机的安定宝ID,以 `#` 开头的4位或6位或8位十六进制数字,我司使用固定6位,如安定宝ID `16` 编码为6位是 `000010`,传输为 `#000010` * `#ademco_id` 主机的安定宝ID,以 `#` 开头的4位或6位或8位十六进制数字,我司使用固定6位,如安定宝ID `16` 编码为6位是 `000010`,传输为 `#000010`
* `event` 定长4Bytes,事件代码,具体含义见后文。 * `event` 定长4Bytes,事件代码,具体含义见后文。
* `gg` 定长2 Bytes, 一般为00,当非00时有特殊含义,参考下方 *4.1 事件报告与远程控制* * `gg` 定长2 Bytes, 一般为00,当非00时有特殊含义,参考下方 *4.1 事件报告与远程控制*
* `zone` 防区号,范围 `0~999``zone``0` 表示主机自身事件,如布防、撤防、防拆等。`1~999` 则为防区号,表示防区事件。定长3 Bytes。 * `zone` 防区号,范围 `0~999``zone``0` 表示主机自身事件,如布防、撤防、防拆等。`1~999` 则为防区号,表示防区事件。定长3 Bytes。
* `*xdata` 可选的字段,一般情况下留空,仅有限几种情况需要带 `xdata`:撤防时使用 `xdata` 传输密码、索要防区信息时使用 `xdata` 做串口命令透传。具体格式参考下方 *4.2 xdata 段格式* * `*xdata` 可选的字段,一般情况下留空,仅有限几种情况需要带 `xdata`:撤防时使用 `xdata` 传输密码、索要防区信息时使用 `xdata` 做串口命令透传。具体格式参考下方 *4.2 xdata 段格式*
* `timestamp` 时间戳字段,格式为 `_HH:MM:SS,mm-DD-YYYY`,定长20Bytes * `timestamp` 时间戳字段,格式为 `_HH:MM:SS,mm-DD-YYYY`,定长 `20Bytes`
* `CR` 固定结束符,0x0D * `CR` 固定结束符,`0x0D`
## 三、事件码 ## 三、事件码
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment