Commit cedb229f authored by captainwong's avatar captainwong

update

parent f9a6118f
......@@ -22,14 +22,14 @@
|数据|长度|含义|说明|
|---|----|----|----|
|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 *PN* *P0* **A2** *[Z, P]x(N-8)/2 P1* SUM|变长|主机防区数据回应|*PN*:表示本条数据内包含多少个字节,最大20,防区/属性字节对的数量为 (N-8)/2<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 *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|拒绝设置|主机如果认为对方的命令非法,都可以回复此条命令|
......
......@@ -64,6 +64,18 @@ using namespace ademco;
using namespace hb;
using namespace hb::common;
enum class QueryZoneStage {
None,
WaitingSettingsMode,
QueryingZones,
QueryingLostConfig,
};
struct ZonePropertyAndLostConfig {
ZoneProperty prop = ZoneProperty::InvalidZoneProperty;
bool enableLostReport = false; // 失联开关
};
struct Client {
int fd = 0;
evbuffer* output = nullptr;
......@@ -71,6 +83,8 @@ struct Client {
size_t ademco_id = 0;
uint16_t seq = 0;
int type = -1;
std::unordered_map<size_t, ZonePropertyAndLostConfig> zones = {};
QueryZoneStage queryZoneStage = QueryZoneStage::None;
uint16_t nextSeq() { if (++seq == 10000) { seq = 1; } return seq; }
};
......@@ -96,6 +110,8 @@ std::vector<ThreadContext*> worker_thread_contexts = {};
#define COMMAND_X_AEGZX ((ADEMCO_EVENT)(EVENT_INVALID_EVENT + 2))
// Y
#define COMMAND_Y_AEGZX ((ADEMCO_EVENT)(EVENT_INVALID_EVENT + 3))
// Z
#define COMMAND_Z_QUERY_ZONE ((ADEMCO_EVENT)(EVENT_INVALID_EVENT + 4))
// events will be sent to all clients
......@@ -125,6 +141,7 @@ void op_usage()
"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"
"Z: Query Zone info: [ademco_id]\n"
"\n"
"I: Print clients info\n"
"P: Toggle enable/disable data print\n"
......@@ -137,60 +154,85 @@ 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;
}
void handle_com_passthrough(ThreadContext* context, Client& client, evbuffer* output)
{
if (!context->packet.xdata_) {
printf("WARNING! 1704 NO XDATA!\n");
return;
}
// 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());
// 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");
auto resp_type = com::ResponseParser::parse((const Char*)xdata.data(), xdata.size() & 0xFF);
switch (resp_type) {
case com::ResponseParser::ResponseType::A0_response:
break;
case com::ResponseParser::ResponseType::A2_response:
{
com::A2R resp; memcpy(resp.data, xdata.data(), xdata.size()); resp.len = xdata.size() & 0xFF;
com::A2R::ZoneAndProperties zps; bool hasMore = false;
if (client.queryZoneStage == QueryZoneStage::QueryingZones && resp.parse(zps, hasMore)) {
for (const auto& zp : zps) {
client.zones[zp.zone] = ZonePropertyAndLostConfig{ zp.prop, false };
}
char buf[1024];
XDataPtr xdata;
if (hasMore) { // 继续索要剩余防区
com::A2 req;
xdata = makeXData((const char*)req.data, req.len);
} else { // 开始索要防区失联设置
com::AC req;
xdata = makeXData((const char*)req.data, req.len);
client.queryZoneStage = QueryZoneStage::QueryingLostConfig;
}
break;
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());
}
}
case hb::common::com::ResponseParser::ResponseType::Invalid_response:
break;
default:
}
case com::ResponseParser::ResponseType::A3_response:
break;
case com::ResponseParser::ResponseType::A4_response:
break;
case com::ResponseParser::ResponseType::A6_response:
break;
case com::ResponseParser::ResponseType::A7_response:
break;
case com::ResponseParser::ResponseType::A8_response:
break;
case com::ResponseParser::ResponseType::A9_response:
break;
case com::ResponseParser::ResponseType::AB_response:
break;
case com::ResponseParser::ResponseType::AD_response:
break;
case com::ResponseParser::ResponseType::AE_response:
break;
case com::ResponseParser::ResponseType::B1_response:
{
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 com::ResponseParser::ResponseType::Invalid_response:
break;
default:
break;
}
} while (0);
}
void handle_ademco_msg(ThreadContext* context, bufferevent* bev)
......@@ -214,19 +256,32 @@ void handle_ademco_msg(ThreadContext* context, bufferevent* bev)
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;
com::B0 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);
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());
context->worker_id, fd, client.acct.data(), client.ademco_id,
context->packet.toString(detail::ToStringOption::ALL_CHAR_AS_HEX).data());
}
break;
}
} else if (context->packet.ademcoData_.ademco_event_ == EVENT_COM_PASSTHROUGH) {
handle_com_passthrough(context, bev);
handle_com_passthrough(context, client, output);
break;
} else if (context->packet.ademcoData_.ademco_event_ == EVENT_ENTER_SET_MODE && client.queryZoneStage == QueryZoneStage::WaitingSettingsMode) {
client.queryZoneStage = QueryZoneStage::QueryingZones;
com::A1 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(detail::ToStringOption::ALL_CHAR_AS_HEX).data());
}
}
}
......@@ -268,7 +323,7 @@ void commandcb(evutil_socket_t, short, void* user_data)
for (auto e : evs) {
size_t n = 0;
if (e == COMMAND_M_EGZ) { // M
n = context->packet.make_hb(buf, sizeof(buf), client.second.seq, client.second.acct, client.second.ademco_id,
n = context->packet.make_hb(buf, sizeof(buf), client.second.nextSeq(), 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) {
......@@ -279,7 +334,7 @@ void commandcb(evutil_socket_t, short, void* user_data)
if (client.second.ademco_id != userInput.ademco_id) {
continue;
}
n = context->packet.make_hb(buf, sizeof(buf), client.second.seq, client.second.acct, client.second.ademco_id,
n = context->packet.make_hb(buf, sizeof(buf), client.second.nextSeq(), 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) {
......@@ -291,7 +346,7 @@ void commandcb(evutil_socket_t, short, void* user_data)
continue;
}
auto xdata = makeXData(userInput.xdata, strlen(userInput.xdata));
n = context->packet.make_hb(buf, sizeof(buf), client.second.seq, client.second.acct, client.second.ademco_id,
n = context->packet.make_hb(buf, sizeof(buf), client.second.nextSeq(), 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) {
......@@ -305,7 +360,7 @@ void commandcb(evutil_socket_t, short, void* user_data)
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,
n = context->packet.make_hb(buf, sizeof(buf), client.second.nextSeq(), 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) {
......@@ -313,16 +368,27 @@ void commandcb(evutil_socket_t, short, void* user_data)
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 (e == COMMAND_Z_QUERY_ZONE) {
if (client.second.ademco_id != userInput.ademco_id) {
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);
evbuffer_add(client.second.output, buf, n);
client.second.zones.clear();
client.second.queryZoneStage = QueryZoneStage::WaitingSettingsMode;
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) {
client.second.seq = 1;
}
if (e == EVENT_DISARM) {
auto xdata = makeXData(userInput.pwd, 6);
n = context->packet.make_hb(buf, sizeof(buf), client.second.seq, client.second.acct, client.second.ademco_id, gg, e, 0, xdata);
n = context->packet.make_hb(buf, sizeof(buf), client.second.nextSeq(), client.second.acct, client.second.ademco_id, gg, e, 0, xdata);
} else {
n = context->packet.make_hb(buf, sizeof(buf), client.second.seq, client.second.acct, client.second.ademco_id, gg, e, 0);
n = context->packet.make_hb(buf, sizeof(buf), client.second.nextSeq(), client.second.acct, client.second.ademco_id, gg, e, 0);
}
evbuffer_add(client.second.output, buf, n);
if (!disable_data_print) {
......@@ -331,14 +397,11 @@ void commandcb(evutil_socket_t, short, void* user_data)
}
}
} else {
if (++client.second.seq == 10000) {
client.second.seq = 1;
}
if (e == EVENT_DISARM) {
auto xdata = makeXData(userInput.pwd, 6);
n = context->packet.make_hb(buf, sizeof(buf), client.second.seq, client.second.acct, client.second.ademco_id, 0, e, 0, xdata);
n = context->packet.make_hb(buf, sizeof(buf), client.second.nextSeq(), client.second.acct, client.second.ademco_id, 0, e, 0, xdata);
} else {
n = context->packet.make_hb(buf, sizeof(buf), client.second.seq, client.second.acct, client.second.ademco_id, 0, e, 0);
n = context->packet.make_hb(buf, sizeof(buf), client.second.nextSeq(), client.second.acct, client.second.ademco_id, 0, e, 0);
}
evbuffer_add(client.second.output, buf, n);
if (!disable_data_print) {
......@@ -662,6 +725,23 @@ int main(int argc, char** argv)
break;
}
case 'Z':
{
int ret = 0;
do {
printf("Input [ademco_id]:");
ret = scanf("%d", &userInput.ademco_id);
} while (ret != 1);
{
std::lock_guard<std::mutex> lg(mutex);
commands.push_back(COMMAND_Z_QUERY_ZONE);
threads_to_handled_event = thread_count;
}
fire_command();
break;
}
case 'I':
{
......
......@@ -125,6 +125,7 @@
<PreprocessorDefinitions>_DEBUG;_CONSOLE;ENABLE_BREAKPAD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)..\include;$(DEVLIBS)\libevent-2.1.12-stable-install-x64\include;$(DEVLIBS)\google\breakpad\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
......
......@@ -427,10 +427,10 @@ struct MachineStatusResponse3Section {
struct Cmd {
Char head[6];
// 0 撤防,1 布防
Char status : 2;
Char status1 : 2;
Char status3 : 2;
Char status2 : 2;
Char status3 : 2;
Char status1 : 2;
Char status : 2;
Char sum;
};
......@@ -497,7 +497,7 @@ struct ZoneResponse {
}
/*
* @brief add zone to data and (if this packet isOver) calc sum
* @brief maker, add zone to data and (if this packet isOver) calc sum
* @note first time zone&prop will be placed in 6&7, then second zone&prop will be in 8&9, and so on
* @note but the max number of zone&prop you can add is 20
* @note len is automatically added (with 2) everytime except for first time
......@@ -512,6 +512,27 @@ struct ZoneResponse {
if (isOver) { sum(this); }
return *this;
}
struct ZoneAndProperty {
Char zone = 0;
ZoneProperty prop = ZoneProperty::InvalidZoneProperty;
};
typedef std::vector<ZoneAndProperty> ZoneAndProperties;
//! parser, make sure to call ResponseParser::parse first and return is A2_response to check data valid, then copy data/len to member.
bool parse(ZoneAndProperties& zps, bool& hasMore) {
if (len < 8 || data[3] != len) { return false; } // check valid again
Char sum_ = data[len - 1]; sum(data, len); if (sum_ != data[len - 1]) { return false; } // check sum again
Char count = len - 8 / 2; // zone/prop pairs
if (count == 0) { zps.clear(); hasMore = false; return true; }
for (Char i = 0; i < count; i++) {
Char zone = data[5 + i * 2];
ZoneProperty prop = zonePropertyFromChar(data[6 + i * 2]);
if (prop != ZoneProperty::InvalidZoneProperty) { zps.emplace_back(ZoneAndProperty{ zone, prop }); }
}
hasMore = data[len - 2] == 0xFF;
return true;
}
};
typedef ZoneResponse A2R;
......@@ -716,7 +737,7 @@ struct RequestParser {
Invalid_request = -1,
};
static RequestType parse(const Char* data, size_t len) {
static RequestType parse(const Char* data, Char len) {
do {
if (len < 5) { break; }
if (data[0] != 0xEB) { break; }
......@@ -813,47 +834,80 @@ struct ResponseParser {
Invalid_response = -1,
};
static ResponseType parse(const char* data, size_t len) {
static ResponseType parse(const Char* data, Char len) {
do {
if (len < 7) { break; } // 所有的 response ,长度最小为 7
if (data[0] != 0xEB || data[1] != 0xBA || data[2] != 0x3F) { break; }
switch (data[4]) {
#define define_ResponseType_case(t) \
case 0x ## t: \
{ \
if (len != t ## R::len) { break; } \
t##R resp; memcpy(resp.data, data, len); sum(resp); \
if (resp.data[len - 1] != data[len - 1]) { break; } \
return ResponseType:: ## t ## _response; \
}
switch (data[5]) {
case 0xA0: // EB BA 3F 07 P0 A0 P1 P2 P3 SUM
{
if (len != A0R::len) { break; }
A0R resp; memcpy(resp.data, data, len); sum(resp);
if (resp.data[len - 1] != data[len - 1]) { break; }
return ResponseType::A0_response;
}
case 0xA2: // EB BA 3F PN P0 A2 [Z, P]xN P1 SUM
{
if (len != 8 + data[3] * 2) { break; }
A2R resp; memcpy(resp.data, data, len); sum(resp);
if (resp.data[len - 1] != data[len - 1]) { break; }
return ResponseType::A2_response;
}
case 0xA3:
{
if (len != A3R::len) { break; }
A3R resp; memcpy(resp.data, data, len); sum(resp);
if (resp.data[len - 1] != data[len - 1]) { break; }
return ResponseType::A3_response;
}
case 0xA4:
{
if (len != A4R::len) { break; }
A4R resp; memcpy(resp.data, data, len); sum(resp);
if (resp.data[len - 1] != data[len - 1]) { break; }
return ResponseType::A4_response;
}
case 0xA6:
{
if (len != A6R::len) { break; }
A6R resp; memcpy(resp.data, data, len); sum(resp);
if (resp.data[len - 1] != data[len - 1]) { break; }
return ResponseType::A6_response;
}
//case 0xA0: // EB BA 3F 07 P0 A0 P1 P2 P3 SUM
// {
// if (len != A0R::len) { break; }
// A0R resp; memcpy(resp.data, data, len); sum(resp);
// if (resp.data[len - 1] != data[len - 1]) { break; }
// return ResponseType::A0_response;
// }
case 0xA7:
{
if (len != A7R::len) { break; }
A7R resp; memcpy(resp.data, data, len); sum(resp);
if (resp.data[len - 1] != data[len - 1]) { break; }
return ResponseType::A7_response;
}
case 0xA8:
{
if (len != A8R::len) { break; }
A8R resp; memcpy(resp.data, data, len); sum(resp);
if (resp.data[len - 1] != data[len - 1]) { break; }
return ResponseType::A8_response;
}
define_ResponseType_case(A0)
define_ResponseType_case(A3)
define_ResponseType_case(A4)
define_ResponseType_case(A6)
define_ResponseType_case(A7)
define_ResponseType_case(A8)
//define_case(A9) TODO
define_ResponseType_case(AB)
case 0xA9:
{
// TODO
}
case 0xAB:
{
if (len != ABR::len) { break; }
ABR resp; memcpy(resp.data, data, len); sum(resp);
if (resp.data[len - 1] != data[len - 1]) { break; }
return ResponseType::AB_response;
}
case 0xA2: // EB BA 3F PN P0 A2 [Z, P]xN P1 SUM
{
if (len != 8 + data[3] * 2) { break; }
A2R resp; memcpy(resp.data, data, len); sum(resp);
if (resp.data[len - 1] != data[len - 1]) { break; }
return ResponseType::A2_response;
}
case 0xAD: // EB BA 3F PN P0 AD P1 DATA P2 SUM
{
Char lenExpected = 0;
......@@ -876,7 +930,7 @@ case 0x ## t: \
case 0xB1: // EB BA 3F 08 P0 B1 P1 SUM
{
if (len != A0R::len) { break; }
if (len != B1R::len) { break; }
B1R resp; memcpy(resp.data.data, data, len); sum(resp.data.data, resp.len);
if (resp.data.data[len - 1] != data[len - 1]) { break; }
return ResponseType::B1_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