Commit c8c70103 authored by captainwong's avatar captainwong

com passthrough

parent 83b6b3c8
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
|EB AB 3F **AC** 81|5|索要防区探头遗失/失联|第一次索要时发送| |EB AB 3F **AC** 81|5|索要防区探头遗失/失联|第一次索要时发送|
|EB AB 3F **AD** 82|5|索要防区探头遗失/失联|在主机回应“还有更多数据”时发送此命令继续索要| |EB AB 3F **AD** 82|5|索要防区探头遗失/失联|在主机回应“还有更多数据”时发送此命令继续索要|
|EB CB 3F 08 **AE** *P1 P2* SUM|8|三区段主机布撤防|*P1*:0主机,1区段1,2区段2,3区段3;*P2*:0布防,1撤防| |EB CB 3F 08 **AE** *P1 P2* SUM|8|三区段主机布撤防|*P1*:0主机,1区段1,2区段2,3区段3;*P2*:0布防,1撤防|
|EB CB 3F 06 **B0** AB|5|索要三区段主机状态|| |EB CB 3F 06 **B0** AB|6|索要三区段主机状态||
## 主机回应 ## 主机回应
......
...@@ -150,7 +150,7 @@ void op_usage() ...@@ -150,7 +150,7 @@ void op_usage()
"M: Mannualy input [event gg zone], Exampel Input: 'M' <enter> 3400 1 0 <enter>\n" "M: Mannualy input [event gg zone], Exampel Input: 'M' <enter> 3400 1 0 <enter>\n"
"C: Like M, not send to all clients, but send to specific client with ademco_id: [ademco_id event gg zone]\n" "C: Like M, not send to all clients, but send to specific client with ademco_id: [ademco_id event gg zone]\n"
"X: Like C, with xdata: [ademco_id event gg zone xdata]\n" "X: Like C, with xdata: [ademco_id event gg zone xdata]\n"
"Y: Like X, with xdata, but xdata is hex: [ademco_id event gg zone xdata], example: [1 1704 0 0 EB AB 3F A1 76]\n" "Y: Like X, with xdata, but xdata is hex: [ademco_id event gg zone xdata], example: [1 1704 0 0 EBAB3FA176]\n"
"Z: Query Zone info: [ademco_id]\n" "Z: Query Zone info: [ademco_id]\n"
"\n" "\n"
"I: Print clients info\n" "I: Print clients info\n"
...@@ -182,6 +182,7 @@ void handle_com_passthrough(ThreadContext* context, Client& client, evbuffer* ou ...@@ -182,6 +182,7 @@ void handle_com_passthrough(ThreadContext* context, Client& client, evbuffer* ou
break; break;
case com::ResponseParser::ResponseType::A2_response: case com::ResponseParser::ResponseType::A2_response:
{ {
char buf[1024];
com::A2R resp; memcpy(resp.data, xdata.data(), xdata.size()); resp.len = xdata.size() & 0xFF; com::A2R resp; memcpy(resp.data, xdata.data(), xdata.size()); resp.len = xdata.size() & 0xFF;
com::A2R::ZoneAndProperties zps; bool hasMore = false; com::A2R::ZoneAndProperties zps; bool hasMore = false;
if (client.queryZoneStage == QueryZoneStage::QueryingZones && resp.parse(zps, hasMore)) { if (client.queryZoneStage == QueryZoneStage::QueryingZones && resp.parse(zps, hasMore)) {
...@@ -191,8 +192,6 @@ void handle_com_passthrough(ThreadContext* context, Client& client, evbuffer* ou ...@@ -191,8 +192,6 @@ void handle_com_passthrough(ThreadContext* context, Client& client, evbuffer* ou
zplc.enableLostReport = false; zplc.enableLostReport = false;
client.zones[zp.zone] = zplc; client.zones[zp.zone] = zplc;
} }
char buf[1024];
XDataPtr xdata; XDataPtr xdata;
if (hasMore) { // 继续索要剩余防区 if (hasMore) { // 继续索要剩余防区
com::A2 req; com::A2 req;
...@@ -203,7 +202,17 @@ void handle_com_passthrough(ThreadContext* context, Client& client, evbuffer* ou ...@@ -203,7 +202,17 @@ void handle_com_passthrough(ThreadContext* context, Client& client, evbuffer* ou
client.queryZoneStage = QueryZoneStage::QueryingLostConfig; client.queryZoneStage = QueryZoneStage::QueryingLostConfig;
} }
auto n = context->packet.make_hb(buf, sizeof(buf), client.nextSeq(), client.acct, client.ademco_id, 0, EVENT_COM_PASSTHROUGH, 0, xdata); auto n = context->packet.make_hb(buf, sizeof(buf), client.nextSeq(), client.acct, client.ademco_id, 0,
EVENT_COM_PASSTHROUGH, 0, xdata);
evbuffer_add(output, buf, n);
if (!disable_data_print) {
printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n",
context->worker_id, client.fd, client.acct.data(), client.ademco_id,
context->packet.toString(detail::ToStringOption::ALL_CHAR_AS_HEX).data());
}
} else {
auto n = context->packet.make_hb(buf, sizeof(buf), client.nextSeq(), client.acct, client.ademco_id, 0,
EVENT_EXIT_SET_MODE, 0);
evbuffer_add(output, buf, n); evbuffer_add(output, buf, n);
if (!disable_data_print) { if (!disable_data_print) {
printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n", printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n",
...@@ -284,11 +293,13 @@ void handle_ademco_msg(ThreadContext* context, bufferevent* bev) ...@@ -284,11 +293,13 @@ void handle_ademco_msg(ThreadContext* context, bufferevent* bev)
} else if (context->packet.ademcoData_.ademco_event_ == EVENT_COM_PASSTHROUGH) { } else if (context->packet.ademcoData_.ademco_event_ == EVENT_COM_PASSTHROUGH) {
handle_com_passthrough(context, client, output); handle_com_passthrough(context, client, output);
break; break;
} else if (context->packet.ademcoData_.ademco_event_ == EVENT_ENTER_SET_MODE && client.queryZoneStage == QueryZoneStage::WaitingSettingsMode) { } else if (context->packet.ademcoData_.ademco_event_ == EVENT_ENTER_SET_MODE &&
client.queryZoneStage == QueryZoneStage::WaitingSettingsMode) {
client.queryZoneStage = QueryZoneStage::QueryingZones; client.queryZoneStage = QueryZoneStage::QueryingZones;
com::A1 req; com::A1 req;
auto xdata = makeXData((const char*)req.data, req.len); auto xdata = makeXData((const char*)req.data, req.len);
auto n = context->packet.make_hb(buf, sizeof(buf), client.nextSeq(), client.acct, client.ademco_id, 0, EVENT_COM_PASSTHROUGH, 0, xdata); auto n = context->packet.make_hb(buf, sizeof(buf), client.nextSeq(), client.acct, client.ademco_id, 0,
EVENT_COM_PASSTHROUGH, 0, xdata);
evbuffer_add(output, buf, n); evbuffer_add(output, buf, n);
if (!disable_data_print) { if (!disable_data_print) {
printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n", printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n",
...@@ -300,7 +311,8 @@ void handle_ademco_msg(ThreadContext* context, bufferevent* bev) ...@@ -300,7 +311,8 @@ void handle_ademco_msg(ThreadContext* context, bufferevent* bev)
// ACK // ACK
{ {
size_t n = context->packet.make_ack(buf, sizeof(buf), context->packet.seq_.value_, context->packet.acct_.acct(), context->packet.ademcoData_.ademco_id_); size_t n = context->packet.make_ack(buf, sizeof(buf), context->packet.seq_.value_,
context->packet.acct_.acct(), context->packet.ademcoData_.ademco_id_);
evbuffer_add(output, buf, n); evbuffer_add(output, buf, n);
if (!disable_data_print) { if (!disable_data_print) {
printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n", printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n",
...@@ -341,7 +353,8 @@ void commandcb(evutil_socket_t, short, void* user_data) ...@@ -341,7 +353,8 @@ void commandcb(evutil_socket_t, short, void* user_data)
evbuffer_add(client.second.output, buf, n); evbuffer_add(client.second.output, buf, n);
if (!disable_data_print) { if (!disable_data_print) {
printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n", printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n",
context->worker_id, client.second.fd, client.second.acct.data(), client.second.ademco_id, context->packet.toString().data()); context->worker_id, client.second.fd, client.second.acct.data(), client.second.ademco_id,
context->packet.toString().data());
} }
} else if (e == (COMMAND_C_AEGZ)) { // C } else if (e == (COMMAND_C_AEGZ)) { // C
if (client.second.ademco_id != userInput.ademco_id) { if (client.second.ademco_id != userInput.ademco_id) {
...@@ -352,7 +365,8 @@ void commandcb(evutil_socket_t, short, void* user_data) ...@@ -352,7 +365,8 @@ void commandcb(evutil_socket_t, short, void* user_data)
evbuffer_add(client.second.output, buf, n); evbuffer_add(client.second.output, buf, n);
if (!disable_data_print) { if (!disable_data_print) {
printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n", printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n",
context->worker_id, client.second.fd, client.second.acct.data(), client.second.ademco_id, context->packet.toString().data()); context->worker_id, client.second.fd, client.second.acct.data(), client.second.ademco_id,
context->packet.toString().data());
} }
} else if (e == (COMMAND_X_AEGZX)) { // X } else if (e == (COMMAND_X_AEGZX)) { // X
if (client.second.ademco_id != userInput.ademco_id) { if (client.second.ademco_id != userInput.ademco_id) {
...@@ -364,7 +378,8 @@ void commandcb(evutil_socket_t, short, void* user_data) ...@@ -364,7 +378,8 @@ void commandcb(evutil_socket_t, short, void* user_data)
evbuffer_add(client.second.output, buf, n); evbuffer_add(client.second.output, buf, n);
if (!disable_data_print) { if (!disable_data_print) {
printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n", printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n",
context->worker_id, client.second.fd, client.second.acct.data(), client.second.ademco_id, context->packet.toString().data()); context->worker_id, client.second.fd, client.second.acct.data(), client.second.ademco_id,
context->packet.toString().data());
} }
} else if (e == (COMMAND_Y_AEGZX)) { // Y } else if (e == (COMMAND_Y_AEGZX)) { // Y
if (client.second.ademco_id != userInput.ademco_id) { if (client.second.ademco_id != userInput.ademco_id) {
...@@ -385,7 +400,8 @@ void commandcb(evutil_socket_t, short, void* user_data) ...@@ -385,7 +400,8 @@ void commandcb(evutil_socket_t, short, void* user_data)
if (client.second.ademco_id != userInput.ademco_id) { if (client.second.ademco_id != userInput.ademco_id) {
continue; continue;
} }
n = context->packet.make_hb(buf, sizeof(buf), client.second.nextSeq(), client.second.acct, client.second.ademco_id, 0, EVENT_ENTER_SET_MODE, 0); n = context->packet.make_hb(buf, sizeof(buf), client.second.nextSeq(), client.second.acct, client.second.ademco_id, 0,
EVENT_ENTER_SET_MODE, 0);
evbuffer_add(client.second.output, buf, n); evbuffer_add(client.second.output, buf, n);
client.second.zones.clear(); client.second.zones.clear();
client.second.queryZoneStage = QueryZoneStage::WaitingSettingsMode; client.second.queryZoneStage = QueryZoneStage::WaitingSettingsMode;
...@@ -406,7 +422,8 @@ void commandcb(evutil_socket_t, short, void* user_data) ...@@ -406,7 +422,8 @@ void commandcb(evutil_socket_t, short, void* user_data)
evbuffer_add(client.second.output, buf, n); evbuffer_add(client.second.output, buf, n);
if (!disable_data_print) { if (!disable_data_print) {
printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n", printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n",
context->worker_id, client.second.fd, client.second.acct.data(), client.second.ademco_id, context->packet.toString().data()); context->worker_id, client.second.fd, client.second.acct.data(), client.second.ademco_id,
context->packet.toString().data());
} }
} }
} else { } else {
...@@ -419,7 +436,8 @@ void commandcb(evutil_socket_t, short, void* user_data) ...@@ -419,7 +436,8 @@ void commandcb(evutil_socket_t, short, void* user_data)
evbuffer_add(client.second.output, buf, n); evbuffer_add(client.second.output, buf, n);
if (!disable_data_print) { if (!disable_data_print) {
printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n", printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n",
context->worker_id, client.second.fd, client.second.acct.data(), client.second.ademco_id, context->packet.toString().data()); context->worker_id, client.second.fd, client.second.acct.data(), client.second.ademco_id,
context->packet.toString().data());
} }
} }
} }
...@@ -556,6 +574,12 @@ ThreadContext* init_worker_thread(int i) ...@@ -556,6 +574,12 @@ ThreadContext* init_worker_thread(int i)
return context; return context;
} }
void clear_stdin()
{
int ret = scanf("%*[^\n]%*c");
(void)ret;
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
usage(argv[0]); usage(argv[0]);
...@@ -661,6 +685,7 @@ int main(int argc, char** argv) ...@@ -661,6 +685,7 @@ int main(int argc, char** argv)
do { do {
printf("Input 6 digit password:"); printf("Input 6 digit password:");
ret = scanf("%s", userInput.pwd); ret = scanf("%s", userInput.pwd);
clear_stdin();
} while (ret != 1 || strlen(userInput.pwd) != 6); } while (ret != 1 || strlen(userInput.pwd) != 6);
{ {
std::lock_guard<std::mutex> lg(mutex); std::lock_guard<std::mutex> lg(mutex);
...@@ -695,6 +720,7 @@ int main(int argc, char** argv) ...@@ -695,6 +720,7 @@ int main(int argc, char** argv)
do { do {
printf("Input [event gg zone]:"); printf("Input [event gg zone]:");
ret = scanf("%d %d %d", &userInput.ev, &userInput.gg, &userInput.zone); ret = scanf("%d %d %d", &userInput.ev, &userInput.gg, &userInput.zone);
clear_stdin();
} while (ret != 3); } while (ret != 3);
{ {
std::lock_guard<std::mutex> lg(mutex); std::lock_guard<std::mutex> lg(mutex);
...@@ -711,6 +737,7 @@ int main(int argc, char** argv) ...@@ -711,6 +737,7 @@ int main(int argc, char** argv)
do { do {
printf("Input [ademco_id event gg zone]:"); printf("Input [ademco_id event gg zone]:");
ret = scanf("%d %d %d %d", &userInput.ademco_id, &userInput.ev, &userInput.gg, &userInput.zone); ret = scanf("%d %d %d %d", &userInput.ademco_id, &userInput.ev, &userInput.gg, &userInput.zone);
clear_stdin();
} while (ret != 4); } while (ret != 4);
{ {
std::lock_guard<std::mutex> lg(mutex); std::lock_guard<std::mutex> lg(mutex);
...@@ -728,6 +755,7 @@ int main(int argc, char** argv) ...@@ -728,6 +755,7 @@ int main(int argc, char** argv)
do { do {
printf("Input [ademco_id event gg zone xdata]:"); printf("Input [ademco_id event gg zone xdata]:");
ret = scanf("%d %d %d %d %s", &userInput.ademco_id, &userInput.ev, &userInput.gg, &userInput.zone, userInput.xdata); ret = scanf("%d %d %d %d %s", &userInput.ademco_id, &userInput.ev, &userInput.gg, &userInput.zone, userInput.xdata);
clear_stdin();
} while (ret != 5); } while (ret != 5);
{ {
std::lock_guard<std::mutex> lg(mutex); std::lock_guard<std::mutex> lg(mutex);
...@@ -744,6 +772,7 @@ int main(int argc, char** argv) ...@@ -744,6 +772,7 @@ int main(int argc, char** argv)
do { do {
printf("Input [ademco_id]:"); printf("Input [ademco_id]:");
ret = scanf("%d", &userInput.ademco_id); ret = scanf("%d", &userInput.ademco_id);
clear_stdin();
} while (ret != 1); } while (ret != 1);
{ {
std::lock_guard<std::mutex> lg(mutex); std::lock_guard<std::mutex> lg(mutex);
...@@ -797,6 +826,7 @@ int main(int argc, char** argv) ...@@ -797,6 +826,7 @@ int main(int argc, char** argv)
break; break;
default: default:
clear_stdin();
printf("Invalid command\n"); printf("Invalid command\n");
op_usage(); op_usage();
break; break;
......
...@@ -325,7 +325,7 @@ static void NumStr2HexCharArray_N(const char* str, char* hexarr, size_t max_hex_ ...@@ -325,7 +325,7 @@ static void NumStr2HexCharArray_N(const char* str, char* hexarr, size_t max_hex_
/** /**
* @brief 将字符串形式的高低字节转换为真正的高低字节数组 * @brief 将字符串形式的高低字节转换为真正的高低字节数组
* @param dst 结果地址 * @param dst 结果地址,调用方需确保 dst 可写长度至少为 len / 2
* @param src 字符串形式的高低字节, 如 "ffffabcd1234", 输出 0xff 0xff 0xab 0xcd 0x12 0x34 * @param src 字符串形式的高低字节, 如 "ffffabcd1234", 输出 0xff 0xff 0xab 0xcd 0x12 0x34
* @param len 字符串长度 * @param len 字符串长度
* @note 起因是钱工的GPRS模块无法传输hex,只能传输ascii字节 * @note 起因是钱工的GPRS模块无法传输hex,只能传输ascii字节
...@@ -333,8 +333,8 @@ static void NumStr2HexCharArray_N(const char* str, char* hexarr, size_t max_hex_ ...@@ -333,8 +333,8 @@ static void NumStr2HexCharArray_N(const char* str, char* hexarr, size_t max_hex_
static void ConvertHiLoAsciiToHexCharArray(char* dst, const char* src, size_t len) static void ConvertHiLoAsciiToHexCharArray(char* dst, const char* src, size_t len)
{ {
for (size_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
if (!isdigit(src[i]) && !isalpha(src[i])) { if (!isxdigit((int)(unsigned char)src[i])) {
JLOG_ERRO("NumStr2HexCharArray_N: not all character is digit or alpha."); JLOG_ERRO("NumStr2HexCharArray_N: not all character is xdigit.");
return; return;
} }
} }
......
...@@ -77,7 +77,7 @@ enum ADEMCO_EVENT : uint32_t { ...@@ -77,7 +77,7 @@ enum ADEMCO_EVENT : uint32_t {
EVENT_COM_PASSTHROUGH = 1704, // 串口透传 EVENT_COM_PASSTHROUGH = 1704, // 串口透传
EVENT_ENTER_SET_MODE = 2704, // 进入设置状态 EVENT_ENTER_SET_MODE = 2704, // 进入设置状态
EVENT_STOP_RETRIEVE = 3704, // 接警中心发送,为停止索要;报警主机发送,为拒绝索要 EVENT_EXIT_SET_MODE = 3704, // 接警中心发送,为停止索要;报警主机发送,为拒绝索要
EVENT_QUERY_SUB_MACHINE = 1705, // 查询分机信息 EVENT_QUERY_SUB_MACHINE = 1705, // 查询分机信息
EVENT_WRITE_TO_MACHINE = 1706, // 写入主机信息 EVENT_WRITE_TO_MACHINE = 1706, // 写入主机信息
...@@ -166,7 +166,7 @@ static constexpr ADEMCO_EVENT AdemcoEvents[] = { ...@@ -166,7 +166,7 @@ static constexpr ADEMCO_EVENT AdemcoEvents[] = {
EVENT_COM_PASSTHROUGH, EVENT_COM_PASSTHROUGH,
EVENT_ENTER_SET_MODE, EVENT_ENTER_SET_MODE,
EVENT_STOP_RETRIEVE, EVENT_EXIT_SET_MODE,
EVENT_QUERY_SUB_MACHINE, EVENT_QUERY_SUB_MACHINE,
EVENT_WRITE_TO_MACHINE, EVENT_WRITE_TO_MACHINE,
...@@ -240,7 +240,7 @@ inline std::string ademcoEventToStringEnglish(ADEMCO_EVENT ademco_event, bool wi ...@@ -240,7 +240,7 @@ inline std::string ademcoEventToStringEnglish(ADEMCO_EVENT ademco_event, bool wi
case EVENT_SUB_MACHINE_POWER_RESUME: return n_to_s(ademco_event) + "SUB_POWER_RESUME"; case EVENT_SUB_MACHINE_POWER_RESUME: return n_to_s(ademco_event) + "SUB_POWER_RESUME";
case EVENT_COM_PASSTHROUGH: return n_to_s(ademco_event) + "COM_PASSTHROUGH"; case EVENT_COM_PASSTHROUGH: return n_to_s(ademco_event) + "COM_PASSTHROUGH";
case EVENT_ENTER_SET_MODE: return n_to_s(ademco_event) + "ENTER_SET_MODE"; case EVENT_ENTER_SET_MODE: return n_to_s(ademco_event) + "ENTER_SET_MODE";
case EVENT_STOP_RETRIEVE: return n_to_s(ademco_event) + "STOP RETRIEVE"; case EVENT_EXIT_SET_MODE: return n_to_s(ademco_event) + "EXIT_SET_MODE";
case EVENT_QUERY_SUB_MACHINE: return n_to_s(ademco_event) + "QUERY"; case EVENT_QUERY_SUB_MACHINE: return n_to_s(ademco_event) + "QUERY";
case EVENT_WRITE_TO_MACHINE: return n_to_s(ademco_event) + "WRITE_TO_MACHINE"; case EVENT_WRITE_TO_MACHINE: return n_to_s(ademco_event) + "WRITE_TO_MACHINE";
case EVENT_I_AM_NET_MODULE: return n_to_s(ademco_event) + "I_AM_NET_MODULE"; case EVENT_I_AM_NET_MODULE: return n_to_s(ademco_event) + "I_AM_NET_MODULE";
...@@ -318,7 +318,7 @@ inline const std::wstring ademcoEventToStringChinese(ADEMCO_EVENT ademco_event, ...@@ -318,7 +318,7 @@ inline const std::wstring ademcoEventToStringChinese(ADEMCO_EVENT ademco_event,
case EVENT_SUB_MACHINE_POWER_RESUME: return n_to_s(ademco_event) + L"分防区电源恢复"; case EVENT_SUB_MACHINE_POWER_RESUME: return n_to_s(ademco_event) + L"分防区电源恢复";
case EVENT_COM_PASSTHROUGH: return n_to_s(ademco_event) + L"串口透传"; case EVENT_COM_PASSTHROUGH: return n_to_s(ademco_event) + L"串口透传";
case EVENT_ENTER_SET_MODE: return n_to_s(ademco_event) + L"进入设置状态"; case EVENT_ENTER_SET_MODE: return n_to_s(ademco_event) + L"进入设置状态";
case EVENT_STOP_RETRIEVE: return n_to_s(ademco_event) + L"拒绝/停止索要"; case EVENT_EXIT_SET_MODE: return n_to_s(ademco_event) + L"拒绝/停止设置";
case EVENT_QUERY_SUB_MACHINE: return n_to_s(ademco_event) + L"查询"; case EVENT_QUERY_SUB_MACHINE: return n_to_s(ademco_event) + L"查询";
case EVENT_WRITE_TO_MACHINE: return n_to_s(ademco_event) + L"写入主机信息"; case EVENT_WRITE_TO_MACHINE: return n_to_s(ademco_event) + L"写入主机信息";
case EVENT_I_AM_NET_MODULE: return n_to_s(ademco_event) + L"我是网络模块"; case EVENT_I_AM_NET_MODULE: return n_to_s(ademco_event) + L"我是网络模块";
......
...@@ -295,8 +295,13 @@ struct CongwinFe100Packet ...@@ -295,8 +295,13 @@ struct CongwinFe100Packet
struct XData struct XData
{ {
enum class LengthFormat { enum class LengthFormat {
TWO_HEX, TWO_HEX, // 以两个hex字节表示长度,如 \x00, \x06
FOUR_DECIMAL, FOUR_DECIMAL, // 以4个ASCII字符表示长度,如 "0008"
};
enum class DataFormat {
AS_IS, //! 原样打包
TO_ASCII, //! 一个字节的HEX值转换为两个ASCII字符,如 6 转为 00 06
}; };
LengthFormat lengthFormat_ = LengthFormat::TWO_HEX; LengthFormat lengthFormat_ = LengthFormat::TWO_HEX;
...@@ -336,37 +341,38 @@ inline bool operator==(const XDataPtr& lhs, const XDataPtr& rhs) ...@@ -336,37 +341,38 @@ inline bool operator==(const XDataPtr& lhs, const XDataPtr& rhs)
} }
//! 生成xdata //! 生成xdata
static XDataPtr makeXData(const std::vector<char>& payload, XData::LengthFormat lengthFormat = XData::LengthFormat::TWO_HEX) static XDataPtr makeXData(const std::vector<char>& payload,
XData::LengthFormat lengthFormat = XData::LengthFormat::TWO_HEX,
XData::DataFormat dataFormat = XData::DataFormat::AS_IS)
{ {
auto xdata = std::make_shared<XData>(); auto xdata = std::make_shared<XData>();
xdata->lengthFormat_ = lengthFormat; xdata->lengthFormat_ = lengthFormat;
if (dataFormat == XData::DataFormat::TO_ASCII) {
auto tmp = detail::toString(payload, detail::ToStringOption::ALL_CHAR_AS_HEX, false, false);
std::copy(tmp.begin(), tmp.end(), std::back_inserter(xdata->data_));
} else {
xdata->data_ = payload;
}
switch (lengthFormat) switch (lengthFormat)
{ {
case XData::LengthFormat::FOUR_DECIMAL: case XData::LengthFormat::FOUR_DECIMAL:
{ {
xdata->data_ = payload; xdata->rawData_.resize(1 + 4 + xdata->data_.size() + 1);
// [ len ]
xdata->rawData_.resize(1 + 4 + payload.size() + 1);
xdata->rawData_[0] = '['; xdata->rawData_[0] = '[';
/*Dec2HexCharArray_4(payload.size() * 2, &xdata->rawData_[1], false); detail::Dec2HexCharArray_4(xdata->data_.size(), &xdata->rawData_[1], false);
for (size_t i = 0; i < payload.size(); i++) { memcpy(&xdata->rawData_[5], xdata->data_.data(), xdata->data_.size());
xdata->rawData_[5 + i * 2] = detail::Dec2Hex((payload[i] >> 4) & 0x0F);
xdata->rawData_[5 + i * 2 + 1] = detail::Dec2Hex((payload[i] & 0x0F));
}*/
detail::Dec2HexCharArray_4(payload.size(), &xdata->rawData_[1], false);
memcpy(&xdata->rawData_[5], payload.data(), payload.size());
xdata->rawData_.back() = ']'; xdata->rawData_.back() = ']';
break; break;
} }
case XData::LengthFormat::TWO_HEX: case XData::LengthFormat::TWO_HEX:
default: default:
{ {
xdata->data_ = payload; xdata->rawData_.resize(1 + 2 + xdata->data_.size() + 1);
xdata->rawData_.resize(1 + 2 + payload.size() + 1);
xdata->rawData_[0] = '['; xdata->rawData_[0] = '[';
xdata->rawData_[1] = static_cast<char>((payload.size() << 8) & 0xFF); xdata->rawData_[1] = static_cast<char>((xdata->data_.size() << 8) & 0xFF);
xdata->rawData_[2] = static_cast<char>(payload.size() & 0xFF); xdata->rawData_[2] = static_cast<char>(xdata->data_.size() & 0xFF);
memcpy(&xdata->rawData_[3], payload.data(), payload.size()); memcpy(&xdata->rawData_[3], xdata->data_.data(), xdata->data_.size());
xdata->rawData_.back() = ']'; xdata->rawData_.back() = ']';
} }
break; break;
...@@ -375,9 +381,18 @@ static XDataPtr makeXData(const std::vector<char>& payload, XData::LengthFormat ...@@ -375,9 +381,18 @@ static XDataPtr makeXData(const std::vector<char>& payload, XData::LengthFormat
return xdata; return xdata;
} }
static XDataPtr makeXData(const char* pack, size_t len, XData::LengthFormat lengthFormat = XData::LengthFormat::TWO_HEX) { static XDataPtr makeXData(const char* pack, size_t len,
XData::LengthFormat lengthFormat = XData::LengthFormat::TWO_HEX,
XData::DataFormat dataFormat = XData::DataFormat::AS_IS) {
std::vector<char> data(pack, pack + len); std::vector<char> data(pack, pack + len);
return makeXData(data, lengthFormat); return makeXData(data, lengthFormat, dataFormat);
}
static XDataPtr makeXData(const unsigned char* pack, size_t len,
XData::LengthFormat lengthFormat = XData::LengthFormat::TWO_HEX,
XData::DataFormat dataFormat = XData::DataFormat::AS_IS) {
std::vector<char> data((const char*)pack, (const char*)pack + len);
return makeXData(data, lengthFormat, dataFormat);
} }
static XDataPtr parseXData(const char* pack, const char* pack_end) static XDataPtr parseXData(const char* pack, const char* pack_end)
......
...@@ -478,8 +478,8 @@ typedef ZoneRequest A1; ...@@ -478,8 +478,8 @@ typedef ZoneRequest A1;
//! 回应主机防区 EB BA 3F PN P0 A2 [Z, P]xN P1 SUM //! 回应主机防区 EB BA 3F PN P0 A2 [Z, P]xN P1 SUM
struct ZoneResponse { struct ZoneResponse {
//! 一包数据最多有20个防区 //! 一包数据最多有20个字节,所以最多可以包含 (20 - 8) / 2 = 6 个防区
static constexpr Char max_zone = 20; static constexpr Char max_zone = 6;
static constexpr Char max_len = 8 + 2 * max_zone; static constexpr Char max_len = 8 + 2 * max_zone;
/* /*
* when param is not 0xFF, means there's more zone coming; vice versa * when param is not 0xFF, means there's more zone coming; vice versa
...@@ -527,11 +527,11 @@ struct ZoneResponse { ...@@ -527,11 +527,11 @@ struct ZoneResponse {
if (count == 0) { zps.clear(); hasMore = false; return true; } if (count == 0) { zps.clear(); hasMore = false; return true; }
for (Char i = 0; i < count; i++) { for (Char i = 0; i < count; i++) {
ZoneAndProperty zp; ZoneAndProperty zp;
zp.zone = data[5 + i * 2]; zp.zone = data[6 + i * 2];
zp.prop = zonePropertyFromChar(data[6 + i * 2]); zp.prop = zonePropertyFromChar(data[7 + i * 2]);
if (zp.prop != ZoneProperty::InvalidZoneProperty) { zps.emplace_back(zp); } if (zp.prop != ZoneProperty::InvalidZoneProperty) { zps.emplace_back(zp); }
} }
hasMore = data[len - 2] == 0xFF; hasMore = data[len - 2] != 0xFF;
return true; return true;
} }
}; };
...@@ -733,6 +733,10 @@ struct RequestParser { ...@@ -733,6 +733,10 @@ struct RequestParser {
A3_request, // 修改防区 A3_request, // 修改防区
A5_request, // 获取定时器 A5_request, // 获取定时器
A7_request, // 设置定时器 A7_request, // 设置定时器
AA_request, // 修改防区探头遗失/失联
AC_request, // 索要防区探头遗失/失联--第一次索要
AD_request, // 索要防区探头遗失/失联--继续索要
B0_request, // 索要三区段主机状态
RD_acct_request, // 读取主机账号 RD_acct_request, // 读取主机账号
WR_acct_request, // 写入主机账号 WR_acct_request, // 写入主机账号
Invalid_request = -1, Invalid_request = -1,
...@@ -771,21 +775,29 @@ struct RequestParser { ...@@ -771,21 +775,29 @@ struct RequestParser {
if (memcmp(A5::data, data, len) != 0) { break; } if (memcmp(A5::data, data, len) != 0) { break; }
return RequestType::A5_request; return RequestType::A5_request;
} }
default: case 0xAC: // EB AB 3F AC 81
if (data[3] == 0x09 && data[4] == 0xA3 && len == A3::len) { {
A3 a3; memcpy(a3.data, data, len); sum(a3); if (len != AC::len) { break; }
if (a3.data[len - 1] != data[len - 1]) { break; } if (memcmp(AC::data, data, len) != 0) { break; }
return RequestType::A3_request; return RequestType::AC_request;
}
case 0xAD: // EB AB 3F AD 82
{
if (len != AD::len) { break; }
if (memcmp(AD::data, data, len) != 0) { break; }
return RequestType::AD_request;
} }
default:
break;
} }
break; break;
} }
case 0xBA: case 0xBA:
{ {
if (data[2] != 0x3F) { break; } if (data[2] != 0x3F) { break; }
if (len == ReadMachineAcctRequest::len) { if (len == ReadMachineAcctRequest::len && memcmp(data, ReadMachineAcctRequest::data, len) == 0) {
if (memcmp(data, ReadMachineAcctRequest::data, len) == 0) return RequestType::RD_acct_request;
{ return RequestType::RD_acct_request; }
} }
break; break;
} }
...@@ -809,6 +821,27 @@ struct RequestParser { ...@@ -809,6 +821,27 @@ struct RequestParser {
A7 req; memcpy(req.data, data, req.len); sum(req); A7 req; memcpy(req.data, data, req.len); sum(req);
if (data[len - 1] == req.data[len - 1]) { return RequestType::A7_request; } if (data[len - 1] == req.data[len - 1]) { return RequestType::A7_request; }
} }
/*if (data[3] == 0x08 && data[4] == 0xA9 && len == A9::len) {
A7 req; memcpy(req.data, data, req.len); sum(req);
if (data[len - 1] == req.data[len - 1]) { return RequestType::A7_request; }
}*/
// EB CB 3F 08 AA P1 P2 SUM
if (data[3] == 0x08 && data[4] == 0xAA && len == AA::len) {
AA req; memcpy(req.data, data, req.len); sum(req);
if (data[len - 1] == req.data[len - 1]) { return RequestType::AA_request; }
}
/*if (data[3] == 0x08 && data[4] == 0xAE && len == AE::len) {
AA req; memcpy(req.data, data, req.len); sum(req);
if (data[len - 1] == req.data[len - 1]) { return RequestType::AA_request; }
}*/
// EB CB 3F 06 B0 AB
if (data[3] == 0x08 && data[4] == 0xB0 && len == B0::len && memcmp(B0::data, data, len) == 0) {
return RequestType::B0_request;
}
} }
} }
} while (0); } while (0);
...@@ -850,7 +883,7 @@ struct ResponseParser { ...@@ -850,7 +883,7 @@ struct ResponseParser {
case 0xA2: // EB BA 3F PN P0 A2 [Z, P]xN P1 SUM case 0xA2: // EB BA 3F PN P0 A2 [Z, P]xN P1 SUM
{ {
if (len != 8 + data[3] * 2) { break; } if (len != data[3]) { break; }
A2R resp; memcpy(resp.data, data, len); sum(resp); A2R resp; memcpy(resp.data, data, len); sum(resp);
if (resp.data[len - 1] != data[len - 1]) { break; } if (resp.data[len - 1] != data[len - 1]) { break; }
return ResponseType::A2_response; return ResponseType::A2_response;
...@@ -911,13 +944,13 @@ struct ResponseParser { ...@@ -911,13 +944,13 @@ struct ResponseParser {
case 0xAD: // EB BA 3F PN P0 AD P1 DATA P2 SUM case 0xAD: // EB BA 3F PN P0 AD P1 DATA P2 SUM
{ {
Char lenExpected = 0; //Char lenExpected = 0;
if (data[6] == 0xF0) { // 防区号1个字节 //if (data[6] == 0xF0) { // 防区号1个字节
lenExpected = 6 + data[3] + 2; // lenExpected = 6 + data[3] + 2;
} else if (data[6] == 0xF1) { // 防区号2个字节 //} else if (data[6] == 0xF1) { // 防区号2个字节
lenExpected = 6 + data[3] * 2 + 2; // lenExpected = 6 + data[3] * 2 + 2;
} else { break; } //} else { break; }
if (len != lenExpected) { break; } if (len != data[3]) { break; }
ADR resp; std::copy(data, data + len, std::back_inserter(resp.data)); sum(resp.data.data(), (Char)resp.data.size()); ADR resp; std::copy(data, data + len, std::back_inserter(resp.data)); sum(resp.data.data(), (Char)resp.data.size());
if (resp.data[len - 1] != data[len - 1]) { break; } if (resp.data[len - 1] != data[len - 1]) { break; }
return ResponseType::AD_response; return ResponseType::AD_response;
......
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