Skip to content

Commit

Permalink
com
Browse files Browse the repository at this point in the history
  • Loading branch information
captainwong committed Aug 19, 2020
1 parent 4be5489 commit 45b3a25
Show file tree
Hide file tree
Showing 10 changed files with 2,262 additions and 164 deletions.
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
|1737|我是网线主机|I_AM_WIRE_MACHINE|
|1747|我是WiFi主机|I_AM_WIFI_MACHINE|
|1757|我是三区段主机|I_AM_3_SECTION_MACHINE|
|1767|我是物联卡主机|I_AM_IOT_MACHINE|
|1709|手机用户SOS|SOS|
|1711|手机用户消警|PHONE_USER_CANCLE_ALARM|
|1712|主机进入设置状态|ENTER_SETTING_MODE|
Expand Down
36 changes: 36 additions & 0 deletions docs/串口透传协议.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# 串口透传协议

## 发给主机

|数据|长度|含义|说明|
|---|----|----|----|
|EB AB 3F **A0** 75|5|索要主机状态|
|EB AB 3F **A1** 76|5|索要防区|第一次索要时发送|
|EB AB 3F **A2** 77|5|索要防区|在主机回应“还有更多防区”时发送此命令继续索要|
|EB CB 3F 09 **A3** *P1* *P2* *P3* SUM|9|修改防区|*P1*:防区号,*P2*:防区属性,*P3*:操作码:0删除,1学码,2结束学码,3修改属性|
|EB AB 3F **A5** 7A|5|索要定时器|
|EB CB 3F 0E **A7** *H1 M1 H2 M2 H3 M3 H4 M4* SUM|13|设置定时器|第一组定时布防:*H1:M1*, 定时撤防:*H2:M2*;<br/> 第二组定时布防:*H3:M3*,定时撤防:*H4:M4*|
|EB CB 3F 08 **A9** *DH DL* SUM|8|测试地址|*DH*:测试地址高位,*DL*:测试地址低位|
|EB CB 3F 08 **AA** *P1 P2* SUM|8|修改防区探头遗失/失联|*P1*:防区号;*P2*: 0失联关,1失联开|
|EB AB 3F **AC** 81|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 06 **B0** AB|5|索要三区段主机状态||

## 主机回应

|数据|长度|含义|说明|
|---|----|----|----|
|EB BA 3F 07 *P0* **A0** *P1 P2 P3* SUM|10|主机状态回应|*P0*:语音;*P1*:0布防,1半布防,2撤防,3设置;*P2:主机类型|
|EB BA 3F *PN* *P0* **A2** *[Z, P]xN P1* SUM|变长|主机防区数据回应|*PN*:N表示本条数据内包含多少防区,最大20;<br/> *P0*:语音;Z:防区号;P:防区属性;*P1*:FF表示没有更多数据了,其他表示还有更多数据|
|EB BA 3F 07 *P0* **A3** SUM|7|学码开始回应|*P0*:语音。因为学码时主机要等待外部无线信号(用户触发探测器),<br/> 因此先回应A3表示已经开始学码,学码成功时再回 A4|
|EB BA 3F 0A *P0* **A4** *P1 P2 P3* SUM|10|修改防区回应|*P0*:语音;*P1*:防区号;*P2*:防区属性;*P3*:0失败,1成功,2失败-重码,3失败-空防区|
|EB BA 3F 0F *P0* **A6** *H1 M1 H2 M2 H3 M3 H4 M4* SUM|14|定时器回应|*P0*:语音;第一组定时布防:*H1:M1*, 定时撤防:*H2:M2*;<br/> 第二组定时布防:*H3:M3*,定时撤防:*H4:M4*|
|EB BA 3F 07 *P0* **A7** SUM|7|修改定时器回应|*P0*:语音|
|EB BA 3F 07 *P0* **A9** SUM|7|测试地址回应、激活|*P0*:语音|
|EB BA 3F 09 *P0* **AB** *P1 P2* SUM|9|修改防区探头遗失/失联回应|*P0*:语音;*P1*:防区号;*P2*:0失联关,1失联开,2拒绝设置|
|EB BA 3F *PN* *P0* **AD** *P1 DATA P2* SUM|变长|索要防区探头遗失/失联回应|回应所有失联开的防区。<br/> *PN*:失联开防区数量;*P0*:语音;<br/> *P1*:F0指示DATA以1个字节表示防区号,F1表示DATA以2个字节表示防区号;<br/> *DATA*:所有失联开的防区;<br/> *P2*:FF表示传输结束,其他表示还有更多数据|
|EB BA 3F 08 *P0* **AF** *P1 P2* SUM|9|三区段主机布撤防回应|*P0*:语音;*P1*:0主机,1区段1,2区段2,3区段3;*P2*:0布防成功,1撤防成功|
|EB BA 3F 08 *P0* **B1** *P1* SUM|8|三区段主机索要状态回应|*P0*:语音;<br/> *P1*:8位,7/6位主机状态,5/4位区段1状态,3/2位区段2状态,1/0位区段3状态<br/> 值为0布防,1撤防|
|EB BA 3F 07 P0 A8 SUM|7|拒绝设置|主机如果认为对方的命令非法,都可以回复此条命令|

9 changes: 9 additions & 0 deletions examples/examples.sln
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bench_client", "bench_clien
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_event_md", "gen_event_md\gen_event_md.vcxproj", "{FED919A9-19E0-4D4A-972F-DDF537F5DEFE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "include", "include", "{332EE094-40C5-4E48-AD90-286EA3ACDD81}"
ProjectSection(SolutionItems) = preProject
..\include\ademco_detail.h = ..\include\ademco_detail.h
..\include\ademco_event.h = ..\include\ademco_event.h
..\include\ademco_packet.h = ..\include\ademco_packet.h
..\include\hb_detail.h = ..\include\hb_detail.h
..\include\hb_helper.h = ..\include\hb_helper.h
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down
3 changes: 2 additions & 1 deletion examples/gen_event_md/gen_event_md.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ ADEMCO_EVENT privateEvents[] = {
EVENT_SUB_MACHINE_POWER_EXCEPTION,
EVENT_SUB_MACHINE_POWER_RESUME,

EVENT_RETRIEVE_ZONE_OR_SUB_MACHINE,
EVENT_COM_PASSTHROUGH,
EVENT_ENTER_SET_MODE,
EVENT_STOP_RETRIEVE,

Expand All @@ -83,6 +83,7 @@ ADEMCO_EVENT privateEvents[] = {
EVENT_I_AM_WIRE_MACHINE,
EVENT_I_AM_WIFI_MACHINE,
EVENT_I_AM_3_SECTION_MACHINE,
EVENT_I_AM_IOT_MACHINE,

EVENT_PHONE_USER_SOS,
EVENT_PHONE_USER_CANCLE_ALARM,
Expand Down
162 changes: 136 additions & 26 deletions examples/server_demo_libevent/server_demo_libevent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,12 @@ static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
#define DISABLE_JLIB_LOG2
#include <ademco_packet.h>

#define ENABLE_COMMON_ZONE_PROPERTY_TO_STRING
#include <hb_detail.h>

using namespace ademco;
using namespace hb;
using namespace hb::common;

struct Client {
int fd = 0;
Expand All @@ -66,6 +71,8 @@ struct Client {
size_t ademco_id = 0;
uint16_t seq = 0;
int type = -1;

uint16_t nextSeq() { if (++seq == 10000) { seq = 1; } return seq; }
};

struct ThreadContext {
Expand All @@ -80,8 +87,19 @@ event_base* listen_thread_evbase = nullptr;
int thread_count = 4;
std::vector<ThreadContext*> worker_thread_contexts = {};

// Commands
// M
#define COMMAND_M_EGZ EVENT_INVALID_EVENT
// C
#define COMMAND_C_AEGZ ((ADEMCO_EVENT)(EVENT_INVALID_EVENT + 1))
// X
#define COMMAND_X_AEGZX ((ADEMCO_EVENT)(EVENT_INVALID_EVENT + 2))
// Y
#define COMMAND_Y_AEGZX ((ADEMCO_EVENT)(EVENT_INVALID_EVENT + 3))


// events will be sent to all clients
std::vector<ADEMCO_EVENT> events = {};
std::vector<ADEMCO_EVENT> commands = {};
int threads_to_handled_event = 0;
std::mutex mutex = {};
struct UserInput {
Expand All @@ -106,6 +124,7 @@ void op_usage()
"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"
"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"
"\n"
"I: Print clients info\n"
"P: Toggle enable/disable data print\n"
Expand All @@ -118,6 +137,62 @@ void usage(const char* name)
printf("Usage: %s [listening_port] [thread_count] [disable_data_print]\n", name);
}

void handle_com_passthrough(ThreadContext* context, bufferevent* bev)
{
do {
if (!context->packet.xdata_) {
printf("WARNING! 1704 NO XDATA!\n");
break;
}

// GRPS cannot send us hex data, we need to convert data like "1234ABCDEF" to hex 0x1234ABCDEF
std::vector<char> xdata(context->packet.xdata_->data_.size() / 2);
detail::ConvertHiLoAsciiToHexCharArray(&xdata[0], context->packet.xdata_->data_.data(), context->packet.xdata_->data_.size());
printf("1704 real xdata is %s\n", detail::toString(xdata, detail::ToStringOption::ALL_CHAR_AS_HEX, false, false).data());

auto resp_type = hb::common::com::ResponseParser::parse(xdata.data(), xdata.size());
switch (resp_type) {
case hb::common::com::ResponseParser::ResponseType::A0_response:
break;
case hb::common::com::ResponseParser::ResponseType::A2_response:
break;
case hb::common::com::ResponseParser::ResponseType::A3_response:
break;
case hb::common::com::ResponseParser::ResponseType::A4_response:
break;
case hb::common::com::ResponseParser::ResponseType::A6_response:
break;
case hb::common::com::ResponseParser::ResponseType::A7_response:
break;
case hb::common::com::ResponseParser::ResponseType::A8_response:
break;
case hb::common::com::ResponseParser::ResponseType::A9_response:
break;
case hb::common::com::ResponseParser::ResponseType::AB_response:
break;
case hb::common::com::ResponseParser::ResponseType::AD_response:
break;
case hb::common::com::ResponseParser::ResponseType::AE_response:
break;
case hb::common::com::ResponseParser::ResponseType::B1_response:
{
hb::common::com::B1R b1; memcpy(b1.data.data, xdata.data(), xdata.size());
printf("\t\t status1:%s status2:%s status3:%s\n",
b1.data.cmd.status1 == 0 ? "Arm" : "Disarm",
b1.data.cmd.status2 == 0 ? "Arm" : "Disarm",
b1.data.cmd.status3 == 0 ? "Arm" : "Disarm");

break;
}
case hb::common::com::ResponseParser::ResponseType::Invalid_response:
break;
default:
break;
}

} while (0);
}

void handle_ademco_msg(ThreadContext* context, bufferevent* bev)
{
int fd = (int)bufferevent_getfd(bev);
Expand All @@ -131,23 +206,41 @@ void handle_ademco_msg(ThreadContext* context, bufferevent* bev)
case AdemcoId::id_null:
case AdemcoId::id_hb:
case AdemcoId::id_admcid:
if (context->packet.id_.eid_ != AdemcoId::id_null) {
client.acct = context->packet.acct_.acct();
client.ademco_id = context->packet.ademcoData_.ademco_id_;
if (ademco::isMachineTypeEvent(context->packet.ademcoData_.ademco_event_)) {
client.type = context->packet.ademcoData_.ademco_event_;
}
}
{
char buf[1024];
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);
if (!disable_data_print) {
printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n",
context->worker_id, fd, client.acct.data(), client.ademco_id, context->packet.toString().data());
if (context->packet.id_.eid_ != AdemcoId::id_null) {
client.acct = context->packet.acct_.acct();
client.ademco_id = context->packet.ademcoData_.ademco_id_;
if (ademco::isMachineTypeEvent(context->packet.ademcoData_.ademco_event_)) {
client.type = context->packet.ademcoData_.ademco_event_;
if (client.type == EVENT_I_AM_3_SECTION_MACHINE) { // 三区段主机需要主动索要主机状态
hb::common::com::MachineStatusRequest3Section req;
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);
evbuffer_add(output, buf, n);
if (!disable_data_print) {
printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n",
context->worker_id, fd, client.acct.data(), client.ademco_id, context->packet.toString().data());
}
break;
}
} else if (context->packet.ademcoData_.ademco_event_ == EVENT_COM_PASSTHROUGH) {
handle_com_passthrough(context, bev);
break;
}
}

// ACK
{
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);
if (!disable_data_print) {
printf("T#%d S#%d acct=%s ademco_id=%06zX :%s\n",
context->worker_id, fd, client.acct.data(), client.ademco_id, context->packet.toString().data());
}
}
break;
}
break;
default:
break;
}
Expand All @@ -162,9 +255,9 @@ void commandcb(evutil_socket_t, short, void* user_data)
{
std::lock_guard<std::mutex> lg(mutex);
if (--threads_to_handled_event == 0) {
evs = std::move(events);
evs = std::move(commands);
} else {
evs = events;
evs = commands;
}
}

Expand All @@ -174,15 +267,15 @@ void commandcb(evutil_socket_t, short, void* user_data)
for (auto& client : context->clients) {
for (auto e : evs) {
size_t n = 0;
if (e == EVENT_INVALID_EVENT) { // M
if (e == COMMAND_M_EGZ) { // M
n = context->packet.make_hb(buf, sizeof(buf), client.second.seq, client.second.acct, client.second.ademco_id,
userInput.gg, (ADEMCO_EVENT)userInput.ev, userInput.zone);
evbuffer_add(client.second.output, buf, n);
if (!disable_data_print) {
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());
}
} else if (e == (EVENT_INVALID_EVENT + 1)) { // C
} else if (e == (COMMAND_C_AEGZ)) { // C
if (client.second.ademco_id != userInput.ademco_id) {
continue;
}
Expand All @@ -193,7 +286,7 @@ void commandcb(evutil_socket_t, short, void* user_data)
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());
}
} else if (e == (EVENT_INVALID_EVENT + 2)) { // X
} else if (e == (COMMAND_X_AEGZX)) { // X
if (client.second.ademco_id != userInput.ademco_id) {
continue;
}
Expand All @@ -205,6 +298,21 @@ void commandcb(evutil_socket_t, short, void* user_data)
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());
}
} else if (e == (COMMAND_Y_AEGZX)) { // Y
if (client.second.ademco_id != userInput.ademco_id) {
continue;
}
std::vector<char> data(strlen(userInput.xdata) / 2);
ademco::detail::ConvertHiLoAsciiToHexCharArray(&data[0], userInput.xdata, strlen(userInput.xdata));
auto xdata = makeXData(data);
n = context->packet.make_hb(buf, sizeof(buf), client.second.seq, client.second.acct, client.second.ademco_id,
userInput.gg, (ADEMCO_EVENT)userInput.ev, userInput.zone, xdata);
evbuffer_add(client.second.output, buf, n);
if (!disable_data_print) {
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(ademco::detail::ToStringOption::ALL_CHAR_AS_HEX).data());
}
} else if (client.second.type == EVENT_I_AM_3_SECTION_MACHINE && (e == EVENT_ARM || e == EVENT_DISARM)) {
for (int gg = 1; gg <= 3; gg++) {
if (++client.second.seq == 10000) {
Expand Down Expand Up @@ -465,7 +573,7 @@ int main(int argc, char** argv)
case 'A':
{
std::lock_guard<std::mutex> lg(mutex);
events.push_back(EVENT_ARM);
commands.push_back(EVENT_ARM);
threads_to_handled_event = thread_count;
}
fire_command();
Expand All @@ -480,7 +588,7 @@ int main(int argc, char** argv)
} while (ret != 1 || strlen(userInput.pwd) != 6);
{
std::lock_guard<std::mutex> lg(mutex);
events.push_back(EVENT_DISARM);
commands.push_back(EVENT_DISARM);
threads_to_handled_event = thread_count;
}
fire_command();
Expand All @@ -490,7 +598,7 @@ int main(int argc, char** argv)
case 'E':
{
std::lock_guard<std::mutex> lg(mutex);
events.push_back(EVENT_EMERGENCY);
commands.push_back(EVENT_EMERGENCY);
threads_to_handled_event = thread_count;
}
fire_command();
Expand All @@ -499,7 +607,7 @@ int main(int argc, char** argv)
case 'T':
{
std::lock_guard<std::mutex> lg(mutex);
events.push_back(EVENT_WHAT_IS_YOUR_TYPE);
commands.push_back(EVENT_WHAT_IS_YOUR_TYPE);
threads_to_handled_event = thread_count;
}
fire_command();
Expand All @@ -514,7 +622,7 @@ int main(int argc, char** argv)
} while (ret != 3);
{
std::lock_guard<std::mutex> lg(mutex);
events.push_back(EVENT_INVALID_EVENT);
commands.push_back(COMMAND_M_EGZ);
threads_to_handled_event = thread_count;
}
fire_command();
Expand All @@ -530,14 +638,15 @@ int main(int argc, char** argv)
} while (ret != 4);
{
std::lock_guard<std::mutex> lg(mutex);
events.push_back((ADEMCO_EVENT)(EVENT_INVALID_EVENT + 1));
commands.push_back(COMMAND_C_AEGZ);
threads_to_handled_event = thread_count;
}
fire_command();
break;
}

case 'X':
case 'Y':
{
int ret = 0;
do {
Expand All @@ -546,13 +655,14 @@ int main(int argc, char** argv)
} while (ret != 5);
{
std::lock_guard<std::mutex> lg(mutex);
events.push_back((ADEMCO_EVENT)(EVENT_INVALID_EVENT + 2));
commands.push_back(cmd == 'X' ? COMMAND_X_AEGZX : COMMAND_Y_AEGZX);
threads_to_handled_event = thread_count;
}
fire_command();
break;
}


case 'I':
{
std::vector<Client> copiedClients;
Expand Down
Loading

0 comments on commit 45b3a25

Please sign in to comment.