Commit eb88a9fd authored by captainwong's avatar captainwong

source

parent b047506b
# Ademco Change Log
## 1.5.0
- `HbComResp_A2_Iter.com` changed to pointer
- update parser for `timestamp`
- add `AdemcoControlSource` defs
## 1.4.0
- `hb_com reqeust, response` update
## 1.3.1
- compile with warning level 4
- change `static inline` function to micro
## 1.3.0
- add `file` for parse error
- fix `struct tm not initilized` on parse
- fix parsing pointer on parse timestamp failed
## 1.2.0
- add config
- add `offset` for parse error
- refactor parser
## 1.1.0
- ADEMCO_PACKET_ACCT_MAX_LEN changed from 64 to 18
- add ADEMCO_PACKET_ACCT_MAX_LEN
- hb_com 读写主机账号命令
## 1.0.0
initial version
- initial version
......@@ -36,7 +36,7 @@
# define ADEMCO_VERSION_STRING ADEMCO_VERSION_STRING_BASE "-" ADEMCO_VERSION_SUFFIX
#endif
unsigned int ademcoVersion(void) {
uint32_t ademcoVersion(void) {
return ADEMCO_VERSION_HEX;
}
......@@ -991,7 +991,6 @@ AdemcoParseResult ademcoPacketParse(const ademco_char_t* buff, size_t len,
uint16_t crc;
size_t len_needed;
if (len < 9) {
ADEMCO_FILL_PARSE_ERROR(err, 0, "RESULT_NOT_ENOUGH");
return RESULT_NOT_ENOUGH;
......@@ -1084,7 +1083,6 @@ AdemcoParseResult ademcoPacketParse(const ademco_char_t* buff, size_t len,
if ('0' <= *p && *p <= '9') {
pkt->seq = (pkt->seq * 10) + (*p - '0');
} else {
dline;
ADEMCO_FILL_PARSE_ERROR(err, p - buff, "seq contains non-digit characters");
// some apps use FFFF, wtf
// return RESULT_ERROR;
......@@ -1243,12 +1241,13 @@ AdemcoParseResult ademcoPacketParse(const ademco_char_t* buff, size_t len,
tm.tm_year = tm.tm_year * 10 + char2hex(*p++);
tm.tm_year = tm.tm_year * 10 + char2hex(*p++);
tm.tm_year = tm.tm_year * 10 + char2hex(*p++);
tm.tm_year -= 1900;
tm.tm_mon--;
tm.tm_isdst = -1;
pkt->timestamp = mktime(&tm);
} while (0);
tm.tm_year -= 1900;
tm.tm_mon--;
tm.tm_isdst = -1;
pkt->timestamp = mktime(&tm);
if (pkt->timestamp <= 0) { // use local time instead
pkt->timestamp = time(NULL);
p = pend;
......
......@@ -21,10 +21,10 @@ extern "C" {
#define ADEMCO_PACKET_DATA_SEGMENT_EMPTY_LEN 2 // 空data段[]长度
#define ADEMCO_PACKET_DATA_SEGMENT_FULL_LEN 21 // 非空data段长度,acct长度6
#define ADEMCO_PACKET_DATA_SEGMENT_FULL_LEN_MAX 64 // 非空data段长度,acct长度未知
#define ADEMCO_PACKET_MAX_LEN 512
#define CONGWIN_FE100_PACKET_LEN 31 // 丛文FE100协议长度
#define ADEMCO_PACKET_TIMESTAMP_LEN 20
#define ADEMCO_PACKET_XDATA_MAX_LEN 128
#define ADEMCO_PACKET_MAX_LEN 512 // 安定宝协议最大长度,包括前缀、后缀、data段、xdata段
#define CONGWIN_FE100_PACKET_LEN 31 // 丛文FE100协议长度
#define ADEMCO_PACKET_TIMESTAMP_LEN 20 // 时间戳长度
#define ADEMCO_PACKET_XDATA_MAX_LEN 128 // xdata段最大长度
// Prototypes
typedef uint32_t AdemcoId;
......@@ -191,10 +191,10 @@ typedef enum AdemcoParseResult {
// 安定宝协议解析错误信息
typedef struct AdemcoParseError {
const char* file; // user do not free
int line; // line number in ademco.c
size_t offset; // error offset
const char* msg; // user do not free
const char* file; // user do not free
int line; // line number in ademco.c
size_t offset; // error offset
const char* msg; // user do not free
} AdemcoParseError;
// 安定宝协议data段
......@@ -266,10 +266,48 @@ typedef struct AdemcoPacket {
size_t raw_len;
} AdemcoPacket;
/* control source defs
* 范围 0~255
* 0: 主机
* 1~50: 遥控器
* 51~97: 智能家居
* 98: 中转接警中心
* 99: 直连接警中心
* 100~199: 手机APP,末二位为手机尾号
* 200: web用户,web端包括 网页,H5, 公众号,小程序等
* 201~255: web分享用户
* 特别注意:三区段主机,0 代表主机,1~255 都是遥控器
*/
#define ADEMCO_CONTROL_SOURCES_MAP(XX) \
XX(MACHINE, 0, "主机") \
XX(REMOTE, 1, "遥控器") \
XX(REMOTE_MAX, 50, "遥控器MAX") \
XX(SMART_HOME_ALEXA, 51, "Amazon Alexa") \
XX(SMART_HOME_GOOGLE, 52, "Google Home") \
XX(SMART_HOME_APPLE, 54, "Apple Homekit") \
XX(SMART_HOME_SAMSUNG, 55, "Samsung Smartthings") \
XX(SMART_HOME_ALI_GENIE, 56, "阿里天猫精灵") \
XX(SMART_HOME_MI_AI, 57, "小米小爱同学") \
XX(SMART_HOME_BAIDU, 58, "百度小度") \
XX(SMART_HOME_MAX, 97, "智能家居MAX") \
XX(CENTER_TRANSMIT, 98, "中转接警中心") \
XX(CENTER_DIRECT, 99, "直连接警中心") \
XX(PHONE_APP, 100, "手机APP") \
XX(PHONE_APP_MAX, 199, "手机APP_MAX") \
XX(OWNER, 200, "web用户") \
XX(SHAREE, 201, "web分享用户") \
XX(SHAREE_MAX, 255, "web分享用户MAX")
typedef enum AdemcoControlSource {
#define XX(name, code, zh) ADEMCO_CONTROL_SOURCE_##name = code,
ADEMCO_CONTROL_SOURCES_MAP(XX)
#undef XX
} AdemcoControlSource;
//////////////////////// Functions ////////////////////////
ADEMCO_EXPORT_SYMBOL
unsigned int ademcoVersion(void);
uint32_t ademcoVersion(void);
ADEMCO_EXPORT_SYMBOL
const char* ademcoVersionString(void);
......
......@@ -7,8 +7,8 @@
*/
#define ADEMCO_VERSION_MAJOR 1
#define ADEMCO_VERSION_MINOR 3
#define ADEMCO_VERSION_PATCH 1
#define ADEMCO_VERSION_MINOR 5
#define ADEMCO_VERSION_PATCH 0
#define ADEMCO_VERSION_IS_RELEASE 1
#define ADEMCO_VERSION_SUFFIX ""
......
......@@ -301,88 +301,42 @@
防区号与操作源对照表:
|zone| 操作源| 数量| 备注|
|----|--------|----|-------|
|000 | 主机 | 1 |
|001-097| 遥控器| 97 |
|098| 中转接警中心| 1 |
|099| 直连接警中心| 1 |
|100-199| APP| 100| 1开头,后2位数字使用手机号码的2位尾号|
|200-255| 微信公众号用户| 56 |
## 附录
### crc16算法
```cpp
/**
* @brief 计算一个字节(char)的crc16值
* @param c 要计算crc16的字节
* @param crc 初始crc值
* @return crc16
*/
static unsigned short CalculateCRC_char(char c, unsigned short crc)
{
static unsigned short crcTable[] = {
/* DEFINE THE FIRST ORDER POLYINOMIAL TABLE */
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,
};
unsigned short CRC = crc;
auto tmp = static_cast<unsigned short>(CRC >> 8) ^ (crcTable[static_cast<unsigned char>(c) ^ static_cast<unsigned char>(CRC & 0xFF)]);
CRC = static_cast<unsigned short>(tmp);
return CRC;
}
/**
* @brief 计算一段数据包的crc16值
* @param buff 要计算crc16的数据包指针
* @param len 要计算crc16的数据包长度
* @param crc 初始crc值
* @return crc16
*/
static unsigned short CalculateCRC(const char* buff, size_t len, unsigned short crc = 0)
{
unsigned short CRC = crc;
for (size_t i = 0; i < len; ++i) {
CRC = CalculateCRC_char(buff[i], CRC);
}
return CRC;
}
```c
/* control source defs
* 范围 0~255
* 0: 主机
* 1~50: 遥控器
* 51~97: 智能家居
* 98: 中转接警中心
* 99: 直连接警中心
* 100~199: 手机APP,末二位为手机尾号
* 200: web用户,web端包括 网页,H5, 公众号,小程序等
* 201~255: web分享用户
* 特别注意:三区段主机,0 代表主机,1~255 都是遥控器
*/
```
|zone|name|source|
|----|----|------|
|0|MACHINE|主机|
|1|REMOTE|遥控器|
|50|REMOTE_MAX|遥控器MAX|
|51|SMART_HOME_ALEXA|Amazon Alexa|
|52|SMART_HOME_GOOGLE|Google Home|
|54|SMART_HOME_APPLE|Apple Homekit|
|55|SMART_HOME_SAMSUNG|Samsung Smartthings|
|56|SMART_HOME_ALI_GENIE|阿里天猫精灵|
|57|SMART_HOME_MI_AI|小米小爱同学|
|58|SMART_HOME_BAIDU|百度小度|
|97|SMART_HOME_MAX|智能家居MAX|
|98|CENTER_TRANSMIT|中转接警中心|
|99|CENTER_DIRECT|直连接警中心|
|100|PHONE_APP|手机APP|
|199|PHONE_APP_MAX|手机APP_MAX|
|200|OWNER|web用户|
|201|SHAREE|web分享用户|
|255|SHAREE_MAX|web分享用户MAX|
### 示例
* 主机000000布防
......
......@@ -372,9 +372,42 @@ void print_g250_alarm_codes()
}
void gen_sources() {
const char* comment = R"(
```c
/* control source defs
* 范围 0~255
* 0: 主机
* 1~50: 遥控器
* 51~97: 智能家居
* 98: 中转接警中心
* 99: 直连接警中心
* 100~199: 手机APP,末二位为手机尾号
* 200: web用户,web端包括 网页,H5, 公众号,小程序等
* 201~255: web分享用户
* 特别注意:三区段主机,0 代表主机,1~255 都是遥控器
*/
```
)";
printf("%s\n", comment);
printf("|zone|name|source|\n");
printf("|----|----|------|\n");
#define XX(name, code, zh) \
printf("|%d|%s|%s|\n", code, #name, zh);
ADEMCO_CONTROL_SOURCES_MAP(XX)
#undef XX
}
int main()
{
if (1) {
#define GEN_EVENTS 1
#define GEN_G250_CODES 2
#define GEN_CONTROL_SOURCES 3
const int what = GEN_CONTROL_SOURCES;
if (what == GEN_EVENTS) {
printf("### 主机状态\n\n");
printEvents(statusEvents, _countof(statusEvents));
......@@ -393,9 +426,11 @@ int main()
print_available_zone_props();
} else {
} else if (what == GEN_G250_CODES) {
print_g250_alarm_codes();
} else if (what == GEN_CONTROL_SOURCES) {
gen_sources();
}
......
......@@ -58,6 +58,52 @@ void mybuf_append(mybuf_t* buf, const char* data, size_t len) {
}
}
void mybuf_append_hexdump(mybuf_t* buf, const char* data, size_t len,
int show_header, int show_address, int show_ascii, char def_ascii) {
size_t addr = 0;
if (show_header) {
if (show_address)
mybuf_cat_printf(buf, "addr ");
mybuf_cat_printf(buf, "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E OF");
if (show_ascii) {
mybuf_cat_printf(buf, " 0123456789ABCDEF");
}
mybuf_cat_printf(buf, "\n");
}
if (def_ascii < 32 || def_ascii > 126) {
def_ascii = '.'; // default ascii
}
for (size_t i = 0; i < len; i++) {
if (show_address) {
if (i % 16 == 0) {
mybuf_cat_printf(buf, "%04zX ", addr);
addr += 16;
}
}
mybuf_cat_printf(buf, "%02X ", (unsigned char)data[i]);
if (i % 16 == 15 || i == len - 1) {
if (show_ascii) {
if (i % 16 != 15) {
for (size_t j = 0; j < 16 - (i % 16) - 1; j++) {
mybuf_cat_printf(buf, " ");
}
}
mybuf_cat_printf(buf, "| ");
for (size_t j = i - (i % 16); j <= i; j++) {
if (data[j] >= 32 && data[j] <= 126) {
mybuf_cat_printf(buf, "%c", data[j]);
} else {
mybuf_cat_printf(buf, "%c", def_ascii);
}
}
mybuf_cat_printf(buf, "\n");
} else {
mybuf_cat_printf(buf, "\n");
}
}
}
}
static void mybuf_cat_vprintf(mybuf_t* buf, const char* fmt, va_list ap) {
va_list cpy;
int l;
......
......@@ -13,6 +13,10 @@ extern "C" {
#define MYBUF_DEFAULT_SIZE 4096
#endif
#if MYBUF_DEFAULT_SIZE < 8
#error "MYBUF_DEFAULT_SIZE must >= 8"
#endif
typedef struct {
char* buf;
char mybuf[MYBUF_DEFAULT_SIZE];
......@@ -24,6 +28,16 @@ size_t mybuf_space(mybuf_t* buf);
void mybuf_reserve(mybuf_t* buf, size_t size);
void mybuf_append(mybuf_t* buf, const char* data, size_t len);
/*
* append hex dump to mybuf
* show_header: show 00~0F address header, default is 0
* show_address: show 0000~FFFF address on left
* show_ascii: show ascii on right if can print, default is 0
* def_ascii: when show_ascii but can't print, show def_ascii instead, default is '?'
*/
void mybuf_append_hexdump(mybuf_t* buf, const char* data, size_t len,
int show_header, int show_address, int show_ascii, char def_ascii);
#ifdef __GNUC__
void mybuf_cat_printf(mybuf_t* buf, const char* fmt, ...)
__attribute__((format(printf, 2, 3)));
......
......@@ -6,9 +6,36 @@
#include <time.h>
#include <uv.h>
#include "mybuf.h"
static uv_log_level_t g_level = uv_log_level_info;
static char g_logfile[1024] = {0};
uv_log_level_t uv_log_level_from_string(const char* str) {
#define XX(name, value) \
if (strcmp(str, #name) == 0) { \
return value; \
}
UV_LOG_LEVELS_MAP(XX)
#undef XX
return uv_log_level_invalid;
}
const char* uv_log_level_to_string(uv_log_level_t level) {
switch (level) {
#define XX(name, value) \
case value: { \
return #name; \
}
UV_LOG_LEVELS_MAP(XX)
#undef XX
default:
return "invalid level";
break;
}
}
void uv_log_set_level(uv_log_level_t level) {
g_level = level;
}
......@@ -29,7 +56,7 @@ void uv_log_raw(uv_log_level_t level, const char* msg) {
size_t off;
uv_timeval64_t now;
char buf[64];
const char* c = "ADIWEF";
const char* c = "AVDIWEF";
int log_to_stdout = g_logfile[0] == '\0';
FILE* fp = NULL;
......@@ -45,6 +72,17 @@ void uv_log_raw(uv_log_level_t level, const char* msg) {
if (!log_to_stdout) fclose(fp);
}
void uv_log_hexdump(uv_log_level_t level, const char* buf, size_t len,
int show_header, int show_address, int show_ascii, char def_ascii) {
mybuf_t mybuf;
if (level < g_level || level > uv_log_level_fatal) return;
mybuf_init(&mybuf);
mybuf_cat_printf(&mybuf, "hex dump of %p, len=%zu\n", buf, len);
mybuf_append_hexdump(&mybuf, buf, len, show_header, show_address, show_ascii, def_ascii);
uv_log_raw(level, mybuf.buf);
mybuf_clear(&mybuf);
}
static void uv_log_vprintf(uv_log_level_t level, const char* fmt, va_list ap) {
va_list cpy;
char msg[1024], *p = msg;
......
......@@ -9,23 +9,45 @@
extern "C" {
#endif
#define UV_LOG_LEVELS_MAP(XX) \
XX(all, 0) \
XX(verbose, 1) \
XX(debug, 2) \
XX(info, 3) \
XX(warn, 4) \
XX(error, 5) \
XX(fatal, 6)
typedef enum {
uv_log_level_all,
uv_log_level_debug,
uv_log_level_info,
uv_log_level_warn,
uv_log_level_error,
uv_log_level_fatal,
uv_log_level_raw = 1 << 10, // modifier to log without timestamp
#define XX(name, value) uv_log_level_##name = value,
UV_LOG_LEVELS_MAP(XX)
#undef XX
// modifier to log without timestamp
uv_log_level_raw = 1 << 10,
// invalid
uv_log_level_invalid = 1 << 11,
} uv_log_level_t;
uv_log_level_t uv_log_level_from_string(const char* str);
const char* uv_log_level_to_string(uv_log_level_t level);
void uv_log_set_level(uv_log_level_t level);
void uv_log_set_log_file(const char* file);
uv_log_level_t uv_log_get_level();
void uv_log(uv_log_level_t level, const char* fmt, ...);
void uv_log_raw(uv_log_level_t level, const char* msg);
/**
* log hex dump
* show_header: show 00~0F address header, default is 0
* show_address: show 0000~FFFF address on left
* show_ascii: show ascii on right if can print, default is 0
* def_ascii: when show_ascii but can't print, show def_ascii instead, default is '?'
*/
void uv_log_hexdump(uv_log_level_t level, const char* buf, size_t len,
int show_header, int show_address, int show_ascii, char def_ascii);
#define uvlog_all(...) uv_log(uv_log_level_all, __VA_ARGS__)
#define uvlog_verbose(...) uv_log(uv_log_level_verbose, __VA_ARGS__)
#define uvlog_debug(...) uv_log(uv_log_level_debug, __VA_ARGS__)
#define uvlog_dline uvlog_debug("%s:%d", __FILE__, __LINE__)
#define uvlog_info(...) uv_log(uv_log_level_info, __VA_ARGS__)
......
......@@ -10,6 +10,7 @@
#include "uv_log.h"
#include "uv_tcpclient.h"
#include "uv_tcpserver.h"
#include "uvlib_version.h"
#ifdef _WIN32
......
#include "uvlib_version.h"
#define UVLIB_STRINGIFY(v) UVLIB_STRINGIFY_HELPER(v)
#define UVLIB_STRINGIFY_HELPER(v) #v
#define UVLIB_VERSION_STRING_BASE UVLIB_STRINGIFY(UVLIB_VERSION_MAJOR) "." \
UVLIB_STRINGIFY(UVLIB_VERSION_MINOR) "." \
UVLIB_STRINGIFY(UVLIB_VERSION_PATCH)
#if UVLIB_VERSION_IS_RELEASE
# define UVLIB_VERSION_STRING UVLIB_VERSION_STRING_BASE
#else
# define UVLIB_VERSION_STRING UVLIB_VERSION_STRING_BASE "-" UVLIB_VERSION_SUFFIX
#endif
unsigned int uvlib_version(void) {
return UVLIB_VERSION_HEX;
}
const char* uvlib_version_string(void) {
return UVLIB_VERSION_STRING;
}
#ifndef __UVLIB_VERSION_H__
#define __UVLIB_VERSION_H__
#ifdef __cplusplus
extern "C" {
#endif
/*
* Versions with the same major number are ABI stable. API is allowed to
* evolve between minor releases, but only in a backwards compatible way.
*/
#define UVLIB_VERSION_MAJOR 1
#define UVLIB_VERSION_MINOR 0
#define UVLIB_VERSION_PATCH 0
#define UVLIB_VERSION_IS_RELEASE 1
#define UVLIB_VERSION_SUFFIX ""
#define UVLIB_VERSION_HEX ((UVLIB_VERSION_MAJOR << 16) | \
(UVLIB_VERSION_MINOR << 8) | \
(UVLIB_VERSION_PATCH))
unsigned int uvlib_version(void);
const char* uvlib_version_string(void);
#ifdef __cplusplus
}
#endif
#endif /* __UVLIB_VERSION_H__ */
......@@ -422,6 +422,32 @@ const char* hbZonePropertyToString(HbZoneProperty zp) {
}
}
const char* hbComReqTypeToString(HbComRequestType type) {
switch (type) {
#define XX(name, str) \
case HbComReq_##name: \
return #name;
HB_COM_REQUESTS_MAP(XX)
#undef XX
default:
return "InvalidRequestType";
}
}
const char* hbComRespTypeToString(HbComResponseType type) {
switch (type) {
#define XX(name, str) \
case HbComResp_##name: \
return #name;
HB_COM_RESPONSES_MAP(XX)
#undef XX
default:
return "InvalidResponseType";
}
}
#if ADEMCO_ENABLE_CHINESE
const char* hbMachineStatusToStringChinese(HbMachineStatus status) {
switch (status) {
......@@ -461,7 +487,34 @@ const char* hbZonePropertyToStringChinese(HbZoneProperty zp) {
return "无效属性";
}
}
#endif
const char* hbComReqTypeToStringChinese(HbComRequestType type) {
switch (type) {
#define XX(name, str) \
case HbComReq_##name: \
return str;
HB_COM_REQUESTS_MAP(XX)
#undef XX
default:
return "无效请求";
}
}
const char* hbComRespTypeToStringChinese(HbComResponseType type) {
switch (type) {
#define XX(name, str) \
case HbComResp_##name: \
return str;
HB_COM_RESPONSES_MAP(XX)
#undef XX
default:
return "无效回应";
}
}
#endif // ADEMCO_ENABLE_CHINESE
const char* hbGetZoneFormatString(HbMachineType type) {
uint16_t zone = hbZoneMax(type);
......@@ -586,10 +639,10 @@ HbComRequestType hbComParseRequest(const uint8_t* data,
if (data[2] != 0x3F) {
break;
}
if (len == HbComReq_READ_acct_len &&
memcmp(data, HbComReq_READ_acct_data, len) == 0) {
if (len == HbComReq_RA_len &&
memcmp(data, HbComReq_RA_data, len) == 0) {
copy_data_to_com;
return HbComReq_RD_acct;
return HbComReq_RA;
}
break;
}
......@@ -608,10 +661,10 @@ HbComRequestType hbComParseRequest(const uint8_t* data,
}
} else if (data[3] == 0x0F &&
data[4] == 0x4D &&
len == HbComReq_WRITE_acct_len) {
len == HbComReq_WA_len) {
if (hbCheckSum(data, len)) {
copy_data_to_com;
return HbComReq_WR_acct;
return HbComReq_WA;
}
} else if (data[3] == 0x0E &&
data[4] == 0xA7 &&
......@@ -806,13 +859,13 @@ HbComResponseType hbComParseResponse(const uint8_t* data,
// 处理读写主机账号回应
do {
if (len >= HbComResp_WRITE_acct_len &&
memcmp(HbComResp_WRITE_acct_data, data, HbComResp_WRITE_acct_len) == 0) {
if (len >= HbComResp_WA_len &&
memcmp(HbComResp_WA_data, data, HbComResp_WA_len) == 0) {
return HbComResp_WA;
}
if (len >= HbComResp_READ_acct_len &&
memcmp(HbComResp_READ_acct_head, data, sizeof(HbComResp_READ_acct_head) - 1) == 0 &&
if (len >= HbComResp_RA_len &&
memcmp(HbComResp_RA_head, data, sizeof(HbComResp_RA_head) - 1) == 0 &&
hbCheckSum(data, len)) {
copy_data_to_com;
return HbComResp_RA;
......@@ -907,22 +960,24 @@ void hbComMakeReqB0_get3SectionMachineStatus(HbComData* data) {
data->len = HbComReq_B0_len;
}
void hbComMakeReqRead_acct(HbComData* data) {
memcpy(data->data, HbComReq_READ_acct_data, HbComReq_READ_acct_len);
data->len = HbComReq_READ_acct_len;
void hbComMakeReqRA_readAcct(HbComData* data) {
memcpy(data->data, HbComReq_RA_data, HbComReq_RA_len);
data->len = HbComReq_RA_len;
}
void hbComMakeReqWrite_acct(HbComData* data, const char* acct) {
memcpy(data->data, HbComReq_WRITE_acct_head, 5);
ademcoDecStrToHiLoArray2(data->data + 5, ADEMCO_PACKET_ACCT_MAX_LEN / 2, acct);
data->len = HbComReq_WRITE_acct_len;
void hbComMakeReqWA_writeAcct(HbComData* data, const char* acct) {
memcpy(data->data, HbComReq_WA_head, 5);
ademcoDecStrToHiLoArray2(data->data + 5,
ADEMCO_PACKET_ACCT_MAX_LEN / 2,
acct);
data->len = HbComReq_WA_len;
hbSum(data->data, data->len);
}
void hbComResp_A2_Iter_init(HbComResp_A2_Iter* iter,
const HbComData* com) {
void hbComRespA2_IterInit(HbComResp_A2_Iter* iter,
const HbComData* com) {
if (!iter || !com) return;
memcpy(&iter->com, com, sizeof(HbComData));
iter->com = com;
iter->i = 0;
if (com->len > HbComResp_A2_len_min) {
iter->total = (com->len - HbComResp_A2_len_min) / 2;
......@@ -935,12 +990,12 @@ void hbComResp_A2_Iter_init(HbComResp_A2_Iter* iter,
}
}
HbComResp_A2_p1 hbComResp_A2_Iter_next(HbComResp_A2_Iter* iter,
HbZoneAndProperty* zp) {
HbComResp_A2_p1 hbComRespA2_IterNext(HbComResp_A2_Iter* iter,
HbZoneAndProperty* zp) {
if (iter->i == iter->total)
return HbComResp_A2_p1_nomore;
zp->zone = iter->com.data[6 + iter->i * 2];
zp->prop = (HbZoneProperty)iter->com.data[7 + iter->i * 2];
zp->zone = iter->com->data[6 + iter->i * 2];
zp->prop = (HbZoneProperty)iter->com->data[7 + iter->i * 2];
iter->i++;
return HbComResp_A2_p1_more;
}
......
......@@ -153,41 +153,57 @@ typedef struct HbComData {
uint8_t len;
} HbComData;
// COM request table
#define HB_COM_REQUESTS_MAP(XX) \
XX(A0, "索要主机状态") \
XX(A1, "索要防区") \
XX(A2, "索要更多防区") \
XX(A3, "修改防区") \
XX(A5, "获取定时器") \
XX(A7, "设置定时器") \
XX(A9, "TODO") \
XX(AA, "修改防区探头遗失/失联") \
XX(AC, "索要防区探头遗失/失联--第一次索要") \
XX(AD, "索要防区探头遗失/失联--继续索要") \
XX(AE, "三区段主机布撤防命令") \
XX(B0, "索要三区段主机状态") \
XX(RA, "读取主机账号") \
XX(WA, "写入主机账号")
// 发给主机
typedef enum HbComRequestType {
HbComReq_A0, // 索要主机状态
HbComReq_A1, // 索要防区
HbComReq_A2, // 索要更多防区
HbComReq_A3, // 修改防区
HbComReq_A5, // 获取定时器
HbComReq_A7, // 设置定时器
HbComReq_A9, // TODO
HbComReq_AA, // 修改防区探头遗失/失联
HbComReq_AC, // 索要防区探头遗失/失联--第一次索要
HbComReq_AD, // 索要防区探头遗失/失联--继续索要
HbComReq_AE, // 三区段主机布撤防命令
HbComReq_B0, // 索要三区段主机状态
HbComReq_RD_acct, // 读取主机账号
HbComReq_WR_acct, // 写入主机账号
#define XX(name, str) HbComReq_##name,
HB_COM_REQUESTS_MAP(XX)
#undef XX
// invalid
HbComReq_Invalid = -1,
} HbComRequestType;
// COM response table
#define HB_COM_RESPONSES_MAP(XX) \
XX(A0, "索要主机状态回应") \
XX(A2, "索要防区回应") \
XX(A3, "学码开始回应") \
XX(A4, "修改防区回应") \
XX(A6, "获取定时器回应") \
XX(A7, "设置定时器回应") \
XX(A8, "拒绝设置或设置失败回应") \
XX(A9, "TODO") \
XX(AB, "修改防区探头遗失/失联回应") \
XX(AD, "索要防区探头遗失/失联回应") \
XX(AF, "三区段主机布撤防命令回应") \
XX(B1, "三区段主机状态回应") \
XX(RA, "读取主机账号回应") \
XX(WA, "写入主机账号回应")
// 主机回应
typedef enum HbComResponseType {
HbComResp_A0, // 索要主机状态回应
HbComResp_A2, // 索要防区回应
HbComResp_A3, // 学码开始回应
HbComResp_A4, // 修改防区回应
HbComResp_A6, // 获取主机定时器回应
HbComResp_A7, // 设置主机定时器回应
HbComResp_A8, // 拒绝设置或设置失败回应
HbComResp_A9, // TODO
HbComResp_AB, // 修改防区探头遗失/失联回应
HbComResp_AD, // 索要防区探头遗失/失联回应
HbComResp_AF, // 三区段主机布撤防命令回应
HbComResp_B1, // 三区段主机状态回应
HbComResp_RA, // 读取主机账号回应
HbComResp_WA, // 写入主机账号回应
#define XX(name, str) HbComResp_##name,
HB_COM_RESPONSES_MAP(XX)
#undef XX
// invalid
HbComResp_Invalid = -1,
} HbComResponseType;
......@@ -216,7 +232,7 @@ typedef enum HbComResp_A2_p1 {
} HbComResp_A2_p1;
#define HbComResp_A2_head "\xEB\xBA\x3F\x08\xCC\xA2"
typedef struct HbComResp_A2_Iter {
HbComData com;
const HbComData* com;
uint8_t i, total;
HbComResp_A2_p1 p1;
} HbComResp_A2_Iter;
......@@ -366,21 +382,22 @@ typedef enum HbCom_3sec_which {
((((d)[6]) & 0x03) == HbCom_3sec_arm ? HMS_ARM : HMS_DISARM)
// 读取主机账号
#define HbComReq_READ_acct_len 7
#define HbComReq_READ_acct_data "\xEB\xBA\x3F\x07\x00\x4C\x37"
#define HbComReq_RA_len 7
#define HbComReq_RA_data "\xEB\xBA\x3F\x07\x00\x4C\x37"
// 读取主机账号回应
#define HbComResp_READ_acct_len 15
#define HbComResp_READ_acct_head "\xEB\xCB\x3F\x0F\x4C"
#define HbComResp_RA_len 15
#define HbComResp_RA_head "\xEB\xCB\x3F\x0F\x4C"
// 写入主机账号
#define HbComReq_WRITE_acct_len 15
#define HbComReq_WRITE_acct_head "\xEB\xCB\x3F\x0F\x4D"
#define HbComReq_WA_len 15
#define HbComReq_WA_head "\xEB\xCB\x3F\x0F\x4D"
// 写入主机账号回应(与读取命令相同)
#define HbComResp_WRITE_acct_len HbComReq_READ_acct_len
#define HbComResp_WRITE_acct_data HbComReq_READ_acct_data
#define HbComResp_WA_len HbComReq_RA_len
#define HbComResp_WA_data HbComReq_RA_data
///////////////////////////// property functions //////////////////////////////
// return available count
ADEMCO_EXPORT_SYMBOL
int hbGetAvailableZoneProperties(HbMachineType type, HbZoneProperty props[HZP_COUNT]);
......@@ -449,6 +466,9 @@ int hbMachineCanLinkSubMachine(HbMachineType type);
ADEMCO_EXPORT_SYMBOL
int hbZonePropCanReportLost(HbZoneProperty zp);
///////////////////////////// timer functions /////////////////////////////////
ADEMCO_EXPORT_SYMBOL
void hbInitMachineTimer(HbMachineTimer* timer);
......@@ -474,6 +494,9 @@ void hbMachineTimerToGreenwich(HbMachineTimer* timer);
ADEMCO_EXPORT_SYMBOL
void hbMachineTimerFromGreenwich(HbMachineTimer* timer);
///////////////////////////// helper functions ////////////////////////////////
ADEMCO_EXPORT_SYMBOL
AdemcoEvent hbMachineStatusToAdemcoEvent(HbMachineStatus status);
......@@ -498,18 +521,35 @@ const char* hbMachineTypeToString(HbMachineType type);
ADEMCO_EXPORT_SYMBOL
const char* hbZonePropertyToString(HbZoneProperty zp);
ADEMCO_EXPORT_SYMBOL
const char* hbComReqTypeToString(HbComRequestType type);
ADEMCO_EXPORT_SYMBOL
const char* hbComRespTypeToString(HbComResponseType type);
#if ADEMCO_ENABLE_CHINESE
ADEMCO_EXPORT_SYMBOL
const char* hbMachineStatusToStringChinese(HbMachineStatus status);
ADEMCO_EXPORT_SYMBOL
const char* hbMachineTypeToStringChinese(HbMachineType type);
ADEMCO_EXPORT_SYMBOL
const char* hbZonePropertyToStringChinese(HbZoneProperty zp);
ADEMCO_EXPORT_SYMBOL
const char* hbComReqTypeToStringChinese(HbComRequestType type);
ADEMCO_EXPORT_SYMBOL
const char* hbComRespTypeToStringChinese(HbComResponseType type);
#endif // ADEMCO_ENABLE_CHINESE
ADEMCO_EXPORT_SYMBOL
const char* hbGetZoneFormatString(HbMachineType type);
///////////////////////////// COM functions ///////////////////////////////////
// 累加校验,计算data[0] ~ data[len-2],校验和放在data[len-1]
ADEMCO_EXPORT_SYMBOL
void hbSum(uint8_t* data, size_t len);
......@@ -578,17 +618,17 @@ ADEMCO_EXPORT_SYMBOL
void hbComMakeReqB0_get3SectionMachineStatus(HbComData* data);
ADEMCO_EXPORT_SYMBOL
void hbComMakeReqRead_acct(HbComData* data);
void hbComMakeReqRA_readAcct(HbComData* data);
ADEMCO_EXPORT_SYMBOL
void hbComMakeReqWrite_acct(HbComData* data, const char* acct);
void hbComMakeReqWA_writeAcct(HbComData* data, const char* acct);
ADEMCO_EXPORT_SYMBOL
void hbComResp_A2_Iter_init(HbComResp_A2_Iter* iter, const HbComData* com);
void hbComRespA2_IterInit(HbComResp_A2_Iter* iter, const HbComData* com);
ADEMCO_EXPORT_SYMBOL
HbComResp_A2_p1 hbComResp_A2_Iter_next(HbComResp_A2_Iter* iter,
HbZoneAndProperty* zp);
HbComResp_A2_p1 hbComRespA2_IterNext(HbComResp_A2_Iter* iter,
HbZoneAndProperty* zp);
ADEMCO_EXPORT_SYMBOL
void hbComMakeRespA0_getMachineStatus(HbComData* data,
......
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