Commit 158dd30f authored by captainwong's avatar captainwong

fix

parent b1dfcec1
......@@ -17,9 +17,6 @@ constexpr int TIMES = 100000;
char data[TIMES * 256];
static constexpr size_t MaxAdemcoId = 999999;
static constexpr size_t AdemcoIdSentinel = MaxAdemcoId + 1;
void ademcoPacketBench()
{
printf("\nademcoPacketBench...\n");
......
......@@ -66,7 +66,7 @@ struct Session {
event* timer = nullptr;
int id = 0;
std::string acct = {};
size_t ademco_id = 0;
AdemcoId ademco_id = 0;
uint16_t seq = 0;
AdemcoPacket packet = {};
......@@ -97,7 +97,7 @@ void handle_ademco_msg(Session* session, bufferevent* bev)
{
auto output = bufferevent_get_output(bev);
switch (session->packet.id_.eid_) {
case AdemcoId::id_ack:
case AdemcoMsgId::id_ack:
if (session->packet.seq_.value_ == session->seq) {
if (++session->seq == 10000) {
session->seq = 1;
......
......@@ -32,7 +32,7 @@ void test()
EXPECT_EQ(cb_commited, strlen(raw));
EXPECT_EQ(ap.crc_.value_, 0xC5C3);
EXPECT_EQ(ap.len_.value_, 0x0053);
EXPECT_EQ(ap.id_.eid_, AdemcoId::Enum::id_hb);
EXPECT_EQ(ap.id_.eid_, AdemcoMsgId::Enum::id_hb);
EXPECT_EQ(ap.seq_.value_, 0); // 0 is not a valid seq, but...
EXPECT_TRUE(strncmp("R000000", ap.rrcvr_.data_.data(), 7) == 0);
EXPECT_TRUE(strncmp("L000000", ap.lpref_.data_.data(), 7) == 0);
......@@ -64,11 +64,11 @@ void handle_network_data(const char* data_from_network)
{
printf("parse ok:\n%s\n", ap.toString().data());
switch (ap.id_.eid_) {
case AdemcoId::id_ack:
case AdemcoMsgId::id_ack:
// success
break;
case AdemcoId::id_hb: // event report
case AdemcoMsgId::id_hb: // event report
// reply ack
{
char ack[1024];
......@@ -107,8 +107,6 @@ int main()
handle_network_data(data_from_network);
handle_network_data("\n593F0034\"ACK\"0209R123ABCL456DEF#000001[]_09:00:00,04-18-2020\r");
char buff[1024];
AdemcoPacket ap;
......@@ -118,8 +116,8 @@ int main()
ap.make_ack(buff, sizeof(buff), 1, "861234567890", 123321);
handle_network_data(buff);
size_t ademco_id = 123456; // 主机标识
size_t zone = 123; // 防区标识
AdemcoId ademco_id = 123456; // 主机标识
AdemcoZone zone = 123; // 防区标识
auto evnt = EVENT_FIRE; // 事件码
ap.make_hb(buff, sizeof(buff), 1, nullptr, ademco_id, 0, evnt, zone);
handle_network_data(buff);
......
......@@ -54,7 +54,7 @@ struct Buffer
SOCKET clientSock = INVALID_SOCKET;
Buffer clientBuffer = {};
std::string clientAcct = {};
size_t clientAdemcoId = 0;
AdemcoId clientAdemcoId = 0;
std::mutex mutex = {};
std::vector<ADEMCO_EVENT> evntsWaiting4Send = {};
......@@ -151,11 +151,11 @@ int main(int argc, char** argv)
//printf("id=%s\n", ap.id_.data());
printf("C:%s\n", ap.toString().data());
switch (ap.id_.eid_) {
case AdemcoId::id_ack:
case AdemcoMsgId::id_ack:
// success
break;
case AdemcoId::id_null: // reply ack
case AdemcoMsgId::id_null: // reply ack
{
char ack[1024];
auto len = ap.make_ack(ack, sizeof(ack), ap.seq_.value_, ap.acct_.acct(), ap.ademcoData_.ademco_id_);
......@@ -164,8 +164,8 @@ int main(int argc, char** argv)
break;
}
case AdemcoId::id_hb: // event report
case AdemcoId::id_admcid:
case AdemcoMsgId::id_hb: // event report
case AdemcoMsgId::id_admcid:
{
clientAcct = ap.acct_.acct();
clientAdemcoId = ap.ademcoData_.ademco_id_;
......
......@@ -91,7 +91,7 @@ struct Client {
int fd = 0;
evbuffer* output = nullptr;
std::string acct = {};
size_t ademco_id = 0;
AdemcoId ademco_id = 0;
uint16_t seq = 0;
int type = -1;
MachineStatus status = MachineStatus::Arm;
......@@ -141,10 +141,10 @@ int threads_to_handled_event = 0;
std::mutex mutex = {};
struct UserInput {
char pwd[1024] = { 0 };
int ademco_id = 0;
AdemcoId ademco_id = 0;
int ev = 0;
int gg = 0;
int zone = 0;
AdemcoGG gg = 0;
AdemcoZone zone = 0;
char xdata[1024] = { 0 };
}userInput = {};
......@@ -222,7 +222,7 @@ void handle_com_passthrough(ThreadContext* context, Client& client, evbuffer* ou
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",
printf("T#%d S#%d acct=%s ademco_id=%06X :%s\n",
context->worker_id, client.fd, client.acct.data(), client.ademco_id,
context->packet.toString(detail::ToStringOption::ALL_CHAR_AS_HEX).data());
}
......@@ -231,7 +231,7 @@ void handle_com_passthrough(ThreadContext* context, Client& client, evbuffer* ou
EVENT_EXIT_SET_MODE, 0);
evbuffer_add(output, buf, n);
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=%06X :%s\n",
context->worker_id, client.fd, client.acct.data(), client.ademco_id,
context->packet.toString(detail::ToStringOption::ALL_CHAR_AS_HEX).data());
}
......@@ -262,7 +262,7 @@ void handle_com_passthrough(ThreadContext* context, Client& client, evbuffer* ou
EVENT_EXIT_SET_MODE, 0);
evbuffer_add(output, buf, n);
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=%06X :%s\n",
context->worker_id, client.fd, client.acct.data(), client.ademco_id,
context->packet.toString(detail::ToStringOption::ALL_CHAR_AS_HEX).data());
}
......@@ -297,7 +297,7 @@ void handle_com_passthrough(ThreadContext* context, Client& client, evbuffer* ou
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",
printf("T#%d S#%d acct=%s ademco_id=%06X :%s\n",
context->worker_id, client.fd, client.acct.data(), client.ademco_id,
context->packet.toString(detail::ToStringOption::ALL_CHAR_AS_HEX).data());
}
......@@ -308,7 +308,7 @@ void handle_com_passthrough(ThreadContext* context, Client& client, evbuffer* ou
EVENT_EXIT_SET_MODE, 0);
evbuffer_add(output, buf, n);
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=%06X :%s\n",
context->worker_id, client.fd, client.acct.data(), client.ademco_id,
context->packet.toString(detail::ToStringOption::ALL_CHAR_AS_HEX).data());
}
......@@ -342,17 +342,17 @@ void handle_ademco_msg(ThreadContext* context, bufferevent* bev)
int fd = (int)bufferevent_getfd(bev);
auto& client = context->clients[fd];
if (!disable_data_print) {
printf("T#%d C#%d acct=%s ademco_id=%06zX :%s\n",
printf("T#%d C#%d acct=%s ademco_id=%06X :%s\n",
context->worker_id, fd, client.acct.data(), client.ademco_id, context->packet.toString().data());
}
auto output = bufferevent_get_output(bev);
switch (context->packet.id_.eid_) {
case AdemcoId::id_null:
case AdemcoId::id_hb:
case AdemcoId::id_admcid:
case AdemcoMsgId::id_null:
case AdemcoMsgId::id_hb:
case AdemcoMsgId::id_admcid:
{
char buf[1024];
if (context->packet.id_.eid_ != AdemcoId::id_null) {
if (context->packet.id_.eid_ != AdemcoMsgId::id_null) {
client.acct = context->packet.acct_.acct();
client.ademco_id = context->packet.ademcoData_.ademco_id_;
if (ademco::isMachineTypeEvent(context->packet.ademcoData_.ademco_event_)) {
......@@ -364,7 +364,7 @@ void handle_ademco_msg(ThreadContext* context, bufferevent* bev)
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",
printf("T#%d S#%d acct=%s ademco_id=%06X :%s\n",
context->worker_id, fd, client.acct.data(), client.ademco_id,
context->packet.toString(detail::ToStringOption::ALL_CHAR_AS_HEX).data());
}
......@@ -389,7 +389,7 @@ void handle_ademco_msg(ThreadContext* context, bufferevent* bev)
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",
printf("T#%d S#%d acct=%s ademco_id=%06X :%s\n",
context->worker_id, fd, client.acct.data(), client.ademco_id,
context->packet.toString(detail::ToStringOption::ALL_CHAR_AS_HEX).data());
}
......@@ -401,7 +401,7 @@ void handle_ademco_msg(ThreadContext* context, bufferevent* bev)
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",
printf("T#%d S#%d acct=%s ademco_id=%06X :%s\n",
context->worker_id, fd, client.acct.data(), client.ademco_id,
context->packet.toString(detail::ToStringOption::ALL_CHAR_AS_HEX).data());
}
......@@ -416,7 +416,7 @@ void handle_ademco_msg(ThreadContext* context, bufferevent* bev)
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",
printf("T#%d S#%d acct=%s ademco_id=%06X :%s\n",
context->worker_id, fd, client.acct.data(), client.ademco_id, context->packet.toString().data());
}
}
......@@ -453,7 +453,7 @@ void commandcb(evutil_socket_t, short, void* user_data)
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",
printf("T#%d S#%d acct=%s ademco_id=%06X :%s\n",
context->worker_id, client.second.fd, client.second.acct.data(), client.second.ademco_id,
context->packet.toString().data());
}
......@@ -465,7 +465,7 @@ void commandcb(evutil_socket_t, short, void* user_data)
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",
printf("T#%d S#%d acct=%s ademco_id=%06X :%s\n",
context->worker_id, client.second.fd, client.second.acct.data(), client.second.ademco_id,
context->packet.toString().data());
}
......@@ -478,7 +478,7 @@ void commandcb(evutil_socket_t, short, void* user_data)
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",
printf("T#%d S#%d acct=%s ademco_id=%06X :%s\n",
context->worker_id, client.second.fd, client.second.acct.data(), client.second.ademco_id,
context->packet.toString().data());
}
......@@ -493,7 +493,7 @@ void commandcb(evutil_socket_t, short, void* user_data)
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",
printf("T#%d S#%d acct=%s ademco_id=%06X :%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());
}
......@@ -507,7 +507,7 @@ void commandcb(evutil_socket_t, short, void* user_data)
client.second.zones.clear();
client.second.queryStage = QueryStage::WaitingSettingsMode;
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=%06X :%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());
}
......@@ -522,12 +522,12 @@ void commandcb(evutil_socket_t, short, void* user_data)
client.second.zones.clear();
client.second.queryStage = QueryStage::WaitingSettingsMode2;
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=%06X :%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++) {
for (AdemcoGG gg = 1; gg <= 3; gg++) {
if (e == EVENT_DISARM) {
auto xdata = makeXData(userInput.pwd, 6);
n = context->packet.make_hb(buf, sizeof(buf), client.second.nextSeq(), client.second.acct, client.second.ademco_id, gg, e, 0, xdata);
......@@ -536,7 +536,7 @@ void commandcb(evutil_socket_t, short, void* user_data)
}
evbuffer_add(client.second.output, buf, n);
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=%06X :%s\n",
context->worker_id, client.second.fd, client.second.acct.data(), client.second.ademco_id,
context->packet.toString().data());
}
......@@ -550,7 +550,7 @@ void commandcb(evutil_socket_t, short, void* user_data)
}
evbuffer_add(client.second.output, buf, n);
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=%06X :%s\n",
context->worker_id, client.second.fd, client.second.acct.data(), client.second.ademco_id,
context->packet.toString().data());
}
......@@ -620,7 +620,7 @@ void accept_cb(evconnlistener* listener, evutil_socket_t fd, sockaddr* addr, int
printf("accpet TCP connection #%d from: %s:%d\n", (int)fd, str, sin->sin_port);
//evutil_make_socket_nonblocking(fd);
static int worker_id = 0;
static uint32_t worker_id = 0;
auto context = worker_thread_contexts[worker_id];
std::lock_guard<std::mutex> lg(context->mutex);
auto bev = bufferevent_socket_new(context->base, fd, BEV_OPT_CLOSE_ON_FREE);
......@@ -637,7 +637,7 @@ void accept_cb(evconnlistener* listener, evutil_socket_t fd, sockaddr* addr, int
bufferevent_setcb(bev, readcb, nullptr, eventcb, context);
bufferevent_enable(bev, EV_WRITE | EV_READ);
worker_id = (++worker_id) % thread_count;
worker_id = (worker_id + 1) % thread_count;
}
void accpet_error_cb(evconnlistener* listener, void* context)
......@@ -748,7 +748,7 @@ int main(int argc, char** argv)
sockaddr_in sin = { 0 };
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(port);
sin.sin_port = htons((uint16_t)(port & 0xFFFF));
printf("using libevent %s\n", event_get_version());
printf("%s is listening on port %d using %d threads, disable_data_print=%d\n",
......@@ -834,7 +834,7 @@ int main(int argc, char** argv)
int ret = 0;
do {
printf("Input [event gg zone]:");
ret = scanf("%d %d %d", &userInput.ev, &userInput.gg, &userInput.zone);
ret = scanf("%d %hhd %d", &userInput.ev, &userInput.gg, &userInput.zone);
clear_stdin();
} while (ret != 3);
{
......@@ -851,7 +851,7 @@ int main(int argc, char** argv)
int ret = 0;
do {
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 %hhd %d", &userInput.ademco_id, &userInput.ev, &userInput.gg, &userInput.zone);
clear_stdin();
} while (ret != 4);
{
......@@ -869,7 +869,7 @@ int main(int argc, char** argv)
int ret = 0;
do {
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 %hhd %d %s", &userInput.ademco_id, &userInput.ev, &userInput.gg, &userInput.zone, userInput.xdata);
clear_stdin();
} while (ret != 5);
{
......@@ -973,7 +973,7 @@ int main(int argc, char** argv)
void Client::printInfo() const
{
if (type == EVENT_I_AM_3_SECTION_MACHINE) {
printf(" fd=#%d acct=%s ademco_id=%zd type=%s\n",
printf(" fd=#%d acct=%s ademco_id=%d type=%s\n",
fd, acct.data(), ademco_id,
machineTypeToString(machineTypeFromAdemcoEvent((ADEMCO_EVENT)type)));
printf(" status1: %d %s status2: %d %s status3: %d %s\n",
......@@ -981,7 +981,7 @@ void Client::printInfo() const
(int)status2, machineStatusToString(status2),
(int)status3, machineStatusToString(status3));
} else {
printf(" fd=#%d acct=%s ademco_id=%zd type=%s status=%d %s\n",
printf(" fd=#%d acct=%s ademco_id=%d type=%s status=%d %s\n",
fd, acct.data(), ademco_id,
machineTypeToString(machineTypeFromAdemcoEvent((ADEMCO_EVENT)type)),
(int)status, machineStatusToString(status));
......
......@@ -104,6 +104,8 @@ enum ADEMCO_EVENT : uint32_t {
EVENT_WHAT_IS_YOUR_TYPE = 1798, // 索要主机类型
EVENT_SIGNAL_STRENGTH_CHANGED = 1799, // 主机信号强度变化
AdemcoEventSentinel = 10000,
// -------------------接警中心内部使用事件------------------------------
EVENT_PRIVATE_EVENT_BASE = 0x00010000,
EVENT_CLEARMSG, // 清除报警信息
......
......@@ -21,19 +21,48 @@ enum class ParseResult
RESULT_DATA_ERROR,
};
typedef uint32_t AdemcoId;
typedef uint8_t AdemcoGG;
typedef uint32_t AdemcoZone;
//! 安定宝ID范围
constexpr AdemcoId AdemcoIdMin = 1;
constexpr AdemcoId AdemcoIdMax = 999999; // 兼容性考虑,最大安定宝 ID 为 0x0F423F
constexpr AdemcoId AdemcoIdSentinel = AdemcoIdMax + 1;
inline bool isValidAdemcoId(AdemcoId ademcoId) { return AdemcoIdMin <= ademcoId && ademcoId <= AdemcoIdMax; }
//! 防区号为0时表示主机自身
constexpr AdemcoZone Zone4MachineSelf = 0;
//! 主机防区号范围
constexpr AdemcoZone ZoneMin = 1;
//! 对任何主机类型,最大的防区号
constexpr AdemcoZone ZoneMax = 999;
constexpr AdemcoZone ZoneSentinel = ZoneMax + 1;
//! 对任何主机类型,防区号是否合法(可以包含0防区)
inline bool isValidZone(AdemcoZone zone) {
return Zone4MachineSelf <= zone && zone < ZoneSentinel;
}
//! 对任何主机类型,防区号是否合法(不可以包含0防区)
inline bool isValidZoneStrict(AdemcoZone zone) {
return ZoneMin <= zone && zone < ZoneSentinel;
}
//! 安定宝数据包 data 段
struct AdemcoData
{
//! 数据
std::vector<char> data_ = {};
//! 安定宝ID
size_t ademco_id_ = 0;
AdemcoId ademco_id_ = 0;
//! 安定宝事件码
ADEMCO_EVENT ademco_event_ = ADEMCO_EVENT::EVENT_INVALID_EVENT;
//! gg
unsigned char gg_ = 0;
AdemcoGG gg_ = 0;
//! zone
size_t zone_ = 0;
AdemcoZone zone_ = 0;
AdemcoData() { make(); }
......@@ -54,21 +83,21 @@ struct AdemcoData
return str;
}
void assignAdemcoId(size_t ademco_id) {
void assignAdemcoId(AdemcoId ademco_id) {
char aid[7] = { 0 };
snprintf(aid, sizeof(aid), "%06X", static_cast<int>(ademco_id % 1000000));
snprintf(aid, sizeof(aid), "%06X", static_cast<int>(ademco_id % AdemcoIdSentinel));
std::copy(aid, aid + 6, std::back_inserter(data_));
ademco_id_ = ademco_id;
}
void assignAdemcoEvent(ADEMCO_EVENT ademco_event) {
char aev[5] = { 0 };
snprintf(aev, sizeof(aev), "%04d", static_cast<int>(ademco_event % 10000));
snprintf(aev, sizeof(aev), "%04d", static_cast<int>(ademco_event % AdemcoEventSentinel));
std::copy(aev, aev + 4, std::back_inserter(data_));
ademco_event_ = ademco_event;
}
void assignGG(size_t gg) {
void assignGG(AdemcoGG gg) {
if (gg == 0xEE) {
data_.push_back('E');
data_.push_back('E');
......@@ -83,15 +112,15 @@ struct AdemcoData
gg_ = static_cast<unsigned char>(gg);
}
void assignZone(size_t zone) {
void assignZone(AdemcoZone zone) {
char z[4] = { 0 };
snprintf(z, sizeof(z), "%03d", static_cast<int>(zone % 1000));
snprintf(z, sizeof(z), "%03d", static_cast<int>(zone % ZoneSentinel));
std::copy(z, z + 3, std::back_inserter(data_));
zone_ = zone;
}
//! 生成可用于网络传输的数据
void make(size_t ademco_id, size_t gg, ADEMCO_EVENT ademco_event, size_t zone) {
void make(AdemcoId ademco_id, AdemcoGG gg, ADEMCO_EVENT ademco_event, AdemcoZone zone) {
if (EVENT_INVALID_EVENT == ademco_event) { make(); return; }
clear();
......@@ -111,7 +140,7 @@ struct AdemcoData
}
//! 生成可用于网络传输的数据
void make(const char* acct, size_t gg, ADEMCO_EVENT ademco_event, size_t zone) {
void make(const char* acct, AdemcoGG gg, ADEMCO_EVENT ademco_event, AdemcoZone zone) {
clear();
data_.clear();
......@@ -165,12 +194,12 @@ struct AdemcoData
if (acct_len == 4) {
if (*(p + 4) != '|')
break;
ademco_id_ = detail::HexCharArrayToDec(p, 4);
ademco_id_ = static_cast<AdemcoId>(detail::HexCharArrayToDec(p, 4) % AdemcoIdSentinel);
p += 5;
} else if (acct_len == 6) {
if (*(p + 6) != '|')
break;
ademco_id_ = detail::HexCharArrayToDec(p, 6);
ademco_id_ = static_cast<AdemcoId>(detail::HexCharArrayToDec(p, 6) % AdemcoIdSentinel);
p += 7;
} else if (acct_len == 14) { // just ignore it
if (*(p + 14) != '|')
......@@ -182,7 +211,7 @@ struct AdemcoData
p += acct_len + 1;
}
ademco_event_ = static_cast<ADEMCO_EVENT>(detail::NumCharArray2Dec(p, 4));
ademco_event_ = static_cast<ADEMCO_EVENT>(detail::NumCharArray2Dec(p, 4) % AdemcoEventSentinel);
p += 4;
if (*p++ != ' ')
break;
......@@ -192,14 +221,14 @@ struct AdemcoData
} else if (*p == 'C' && *(p + 1) == 'C') {
gg_ = 0xCC;
} else {
gg_ = static_cast<unsigned char>((*p - '0') * 10 + (*(p + 1) - '0'));
gg_ = static_cast<AdemcoGG>((*p - '0') * 10 + (*(p + 1) - '0'));
}
p += 2;
if (*p++ != ' ')
break;
zone_ = detail::NumCharArray2Dec(p, 3);
zone_ = static_cast<AdemcoZone>(detail::NumCharArray2Dec(p, 3) % ZoneSentinel);
std::copy(pack, pack + pack_len, std::back_inserter(data_));
return true;
} while (0);
......@@ -219,8 +248,8 @@ struct AdemcoData
// 2016-11-4 16:47:51 for compatibility of congwin fe100 protocal
struct CongwinFe100Packet
{
char data_[32] = { 0 };
const int len_ = 31;
static constexpr size_t length = 31;
char data_[length + 1] = { 0 };
bool fromAdemcoData(const AdemcoData* data) {
assert(data && data->valid());
......@@ -228,10 +257,9 @@ struct CongwinFe100Packet
return false;
}
size_t acct = data->ademco_id_;
auto acct = data->ademco_id_;
auto evnt = data->ademco_event_;
//int gg = data->_gg;
size_t zone = data->zone_;
auto zone = data->zone_;
int ndx = 0;
data_[ndx++] = '\n'; // LF
......@@ -281,7 +309,7 @@ struct CongwinFe100Packet
data_[ndx++] = 'C'; // C
}
ndx += sprintf(data_ + ndx, "%03d", static_cast<int>(zone % 10000));
ndx += sprintf(data_ + ndx, "%03d", static_cast<int>(zone % ZoneSentinel));
data_[ndx++] = ' ';
data_[ndx++] = '\r';
......@@ -350,8 +378,8 @@ struct XData
data_ = tmp;
rawData_.resize(data_.size() + 4);
rawData_[0] = '[';
rawData_[1] = (data_.size() >> 8) & 0xFF;
rawData_[2] = data_.size() & 0xFF;
rawData_[1] = (char)((data_.size() >> 8) & 0xFF);
rawData_[2] = (char)(data_.size() & 0xFF);
memcpy(&rawData_[3], data_.data(), data_.size());
rawData_.back() = ']';
} else {
......@@ -688,7 +716,7 @@ static constexpr const char* AdemcoIds[ID_COUNT] = {
ID_REG_RSP,
};
struct AdemcoId
struct AdemcoMsgId
{
enum Enum {
id_null,
......@@ -794,7 +822,7 @@ struct AdemcoPacket
static constexpr char LF = 0x0A;
Crc16 crc_ = {};
Length16 len_ = {};
AdemcoId id_ = {};
AdemcoMsgId id_ = {};
AdemcoSeq seq_ = {};
Rrcvr rrcvr_ = {};
Lpref lpref_ = {};
......@@ -920,13 +948,13 @@ struct AdemcoPacket
// set acct to nullptr if you want to use ademco_id as acct
size_t make(char* pack, size_t pack_len,
AdemcoId::Enum id,
AdemcoMsgId::Enum id,
uint16_t seq,
const char* acct,
size_t ademco_id,
unsigned char gg,
AdemcoId ademco_id,
AdemcoGG gg,
ADEMCO_EVENT aevnt,
size_t zone,
AdemcoZone zone,
XDataPtr xdata = {})
{
assert(pack);
......@@ -946,9 +974,9 @@ struct AdemcoPacket
}
// set acct to nullptr if you want to use ademco_id as acct
size_t make_null(char* pack, size_t pack_len, uint16_t seq, const char* acct, size_t ademco_id)
size_t make_null(char* pack, size_t pack_len, uint16_t seq, const char* acct, AdemcoId ademco_id)
{
id_.eid_ = AdemcoId::Enum::id_null;
id_.eid_ = AdemcoMsgId::Enum::id_null;
seq_ = seq;
rrcvr_.setDefault(); lpref_.setDefault();
acct ? acct_.setAcct(acct) : acct_.setAcct(ademco_id);
......@@ -964,14 +992,14 @@ struct AdemcoPacket
}
// set acct to empty if you want to use ademco_id as acct
size_t make_null(char* pack, size_t pack_len, uint16_t seq, const std::string& acct, size_t ademco_id) {
size_t make_null(char* pack, size_t pack_len, uint16_t seq, const std::string& acct, AdemcoId ademco_id) {
return make_null(pack, pack_len, seq, acct.empty() ? nullptr : acct.data(), ademco_id);
}
// set acct to nullptr if you want to use ademco_id as acct
size_t make_ack(char* pack, size_t pack_len, uint16_t seq, const char* acct, size_t ademco_id)
size_t make_ack(char* pack, size_t pack_len, uint16_t seq, const char* acct, AdemcoId ademco_id)
{
id_.eid_ = AdemcoId::Enum::id_ack;
id_.eid_ = AdemcoMsgId::Enum::id_ack;
seq_ = seq;
rrcvr_.setDefault(); lpref_.setDefault();
acct ? acct_.setAcct(acct) : acct_.setAcct(ademco_id);
......@@ -987,12 +1015,12 @@ struct AdemcoPacket
}
// set acct to nullptr if you want to use ademco_id as acct
size_t make_ack(char* pack, size_t pack_len, uint16_t seq, const std::string& acct, size_t ademco_id) {
size_t make_ack(char* pack, size_t pack_len, uint16_t seq, const std::string& acct, AdemcoId ademco_id) {
return make_ack(pack, pack_len, seq, acct.empty() ? nullptr : acct.data(), ademco_id);
}
size_t make_nak(char* pack, size_t pack_len, uint16_t seq, const std::string& acct, size_t ademco_id) {
id_.eid_ = AdemcoId::Enum::id_nak;
size_t make_nak(char* pack, size_t pack_len, uint16_t seq, const std::string& acct, AdemcoId ademco_id) {
id_.eid_ = AdemcoMsgId::Enum::id_nak;
seq_ = seq;
rrcvr_.setDefault(); lpref_.setDefault();
!acct.empty() ? acct_.setAcct(acct) : acct_.setAcct(ademco_id);
......@@ -1011,13 +1039,13 @@ struct AdemcoPacket
size_t make_hb(char* pack, size_t pack_len,
uint16_t seq,
const char* acct,
size_t ademco_id,
unsigned char gg,
AdemcoId ademco_id,
AdemcoGG gg,
ADEMCO_EVENT evnt,
size_t zone,
AdemcoZone zone,
XDataPtr xdata = {})
{
id_.eid_ = AdemcoId::Enum::id_hb;
id_.eid_ = AdemcoMsgId::Enum::id_hb;
seq_ = seq;
rrcvr_.setDefault(); lpref_.setDefault();
acct ? acct_.setAcct(acct) : acct_.setAcct(ademco_id);
......@@ -1037,10 +1065,10 @@ struct AdemcoPacket
size_t make_hb(char* pack, size_t pack_len,
uint16_t seq,
const std::string& acct,
size_t ademco_id,
unsigned char gg,
AdemcoId ademco_id,
AdemcoGG gg,
ADEMCO_EVENT evnt,
size_t zone,
AdemcoZone zone,
XDataPtr xdata = {})
{
return make_hb(pack, pack_len, seq, acct.empty() ? nullptr : acct.data(), ademco_id, gg, evnt, zone, xdata);
......@@ -1049,156 +1077,161 @@ struct AdemcoPacket
// parser
ParseResult parse(const char* pack, size_t pack_len, size_t& cb_commited) {
//AUTO_LOG_FUNCTION;
do {
if (pack_len < 9) {
JLOG_INFO("AdemcoPacket::Parse pack_len {} < 9", pack_len); JLOG_HEX(pack, pack_len);
return ParseResult::RESULT_NOT_ENOUGH;
}
try {
do {
if (pack_len < 9) {
JLOG_INFO("AdemcoPacket::Parse pack_len {} < 9", pack_len); JLOG_HEX(pack, pack_len);
return ParseResult::RESULT_NOT_ENOUGH;
}
// check LF
if (pack[0] != LF) {
JLOG_ERRO("AdemcoPacket::Parse pack[0] {:d} 0x{:02X} is not _LF", pack[0], pack[0]);
// check LF
if (pack[0] != LF) {
JLOG_ERRO("AdemcoPacket::Parse pack[0] {:d} 0x{:02X} is not _LF", pack[0], pack[0]);
#ifdef _WIN32
return ParseResult::RESULT_DATA_ERROR;
return ParseResult::RESULT_DATA_ERROR;
#else
break;
break;
#endif
}
}
clear();
clear();
// read crc & len
crc_.fromCharArray(pack + 1);
len_.fromCharArray(pack + 5);
// read crc & len
crc_.fromCharArray(pack + 1);
len_.fromCharArray(pack + 5);
// read till CR
size_t len_to_parse = 9 + len_.value_ + 1; // 1 for CR
// read till CR
size_t len_to_parse = 9u + len_.value_ + 1; // 1 for CR
// check if packet is enough to parse
if (pack_len < len_to_parse) {
JLOG_ERRO("AdemcoPacket::Parse pack_len {} < len_to_parse {}", pack_len, len_to_parse);
return ParseResult::RESULT_NOT_ENOUGH;
}
// check if packet is enough to parse
if (pack_len < len_to_parse) {
JLOG_ERRO("AdemcoPacket::Parse pack_len {} < len_to_parse {}", pack_len, len_to_parse);
return ParseResult::RESULT_NOT_ENOUGH;
}
// check CR
const char* id_pos = pack + 9;
const char* CR_pos = id_pos + len_.value_;
if (*CR_pos != CR) {
JLOG_ERRO("AdemcoPacket::Parse ademco_len err!");
break;
}
// check CR
const char* id_pos = pack + 9;
const char* CR_pos = id_pos + len_.value_;
if (*CR_pos != CR) {
JLOG_ERRO("AdemcoPacket::Parse ademco_len err!");
break;
}
// check ademco CRC
unsigned short crc_calc = detail::CalculateCRC(id_pos, len_.value_);
if (crc_.value_ != crc_calc) {
JLOG_ERRO("AdemcoPacket::Parse crc failed!");
break;
}
// check ademco CRC
unsigned short crc_calc = detail::CalculateCRC(id_pos, len_.value_);
if (crc_.value_ != crc_calc) {
JLOG_ERRO("AdemcoPacket::Parse crc failed!");
break;
}
// id
if (*id_pos != '\"') { // find first " of "id".
JLOG_ERRO("AdemcoPacket::Parse find left \" of \"id\" faild!");
break;
}
const char* p = id_pos + 1; // find last " of "id".
while (p < CR_pos && *p != '\"') { p++; } if (p >= CR_pos) { break; }
if (*p++ != '\"') { // " not found.
JLOG_ERRO("AdemcoPacket::Parse find right \" of \"id\" faild!");
break;
}
if (!id_.checkAndSet(id_pos, p - id_pos)) {
JLOG_ERRO("AdemcoPacket::Parse check id faild!");
break;
}
// id
if (*id_pos != '\"') { // find first " of "id".
JLOG_ERRO("AdemcoPacket::Parse find left \" of \"id\" faild!");
break;
}
const char* p = id_pos + 1; // find last " of "id".
while (p < CR_pos && *p != '\"') { p++; } if (p >= CR_pos) { break; }
if (*p++ != '\"') { // " not found.
JLOG_ERRO("AdemcoPacket::Parse find right \" of \"id\" faild!");
break;
}
if (!id_.checkAndSet(id_pos, p - id_pos)) {
JLOG_ERRO("AdemcoPacket::Parse check id faild!");
break;
}
// seq (and Rrcvr, it may not exists)
const char* seq_pos = p;
while (p < CR_pos && *p != 'R' && *p != 'L') { p++; } if (p >= CR_pos) { break; }
if (p - seq_pos != 4) {
JLOG_ERRO("AdemcoPacket::Parse seq len != 4");
break;
}
seq_.fromCharArray(seq_pos);
if (*p == 'R') { // Rrcvr exists
const char* rrcvr_pos = p;
while (p < CR_pos && *p != 'L' && *p != '#') { p++; } if (p >= CR_pos) { break; }
//ASSIGH_SEG_DATA(rrcvr);
rrcvr_.fromCharArray(rrcvr_pos, p - rrcvr_pos);
} else if (*p == 'L') { // Rrcvr not exists, pass
// pass
} else {
JLOG_ERRO("AdemcoPacket::Parse Lpref and Rrcvr not found!");
break;
}
// seq (and Rrcvr, it may not exists)
const char* seq_pos = p;
while (p < CR_pos && *p != 'R' && *p != 'L') { p++; } if (p >= CR_pos) { break; }
if (p - seq_pos != 4) {
JLOG_ERRO("AdemcoPacket::Parse seq len != 4");
break;
}
seq_.fromCharArray(seq_pos);
if (*p == 'R') { // Rrcvr exists
const char* rrcvr_pos = p;
while (p < CR_pos && *p != 'L' && *p != '#') { p++; } if (p >= CR_pos) { break; }
//ASSIGH_SEG_DATA(rrcvr);
rrcvr_.fromCharArray(rrcvr_pos, p - rrcvr_pos);
} else if (*p == 'L') { // Rrcvr not exists, pass
// pass
} else {
JLOG_ERRO("AdemcoPacket::Parse Lpref and Rrcvr not found!");
break;
}
// Lpref
if (*p != 'L') { // L of Lpref not found.
JLOG_ERRO("AdemcoPacket::Parse Lpref not found!");
break;
}
const char* lpref_pos = p;
while (p < CR_pos && *p != '#') { p++; } if (p >= CR_pos) { break; }
lpref_.fromCharArray(lpref_pos, p - lpref_pos);
// Lpref
if (*p != 'L') { // L of Lpref not found.
JLOG_ERRO("AdemcoPacket::Parse Lpref not found!");
break;
}
const char* lpref_pos = p;
while (p < CR_pos && *p != '#') { p++; } if (p >= CR_pos) { break; }
lpref_.fromCharArray(lpref_pos, p - lpref_pos);
// acct
if (*p++ != '#') { // # of #acct not found
JLOG_ERRO("AdemcoPacket::Parse # of #acct not found!");
break;
}
const char* acct_pos = p;
while (p < CR_pos && *p != '[') {
if (!isalnum(*p)) { // acct must be alphanumeric
JLOG_ERRO("AdemcoPacket::Parse acct check isalnum failed!");
p = nullptr;
// acct
if (*p++ != '#') { // # of #acct not found
JLOG_ERRO("AdemcoPacket::Parse # of #acct not found!");
break;
}
p++;
}
if (p == nullptr) { break; }
if (p >= CR_pos) { break; }
acct_.setAcct(acct_pos, p - acct_pos);
const char* acct_pos = p;
while (p < CR_pos && *p != '[') {
if (!isalnum(*p)) { // acct must be alphanumeric
JLOG_ERRO("AdemcoPacket::Parse acct check isalnum failed!");
p = nullptr;
break;
}
p++;
}
if (p == nullptr) { break; }
if (p >= CR_pos) { break; }
acct_.setAcct(acct_pos, p - acct_pos);
// data
if (*p != '[') { // [ of [data] not found.
JLOG_ERRO("AdemcoPacket::Parse [ of [data] not found!");
break;
}
const char* data_pos = p;
while (p < CR_pos && *p != ']') { p++; } if (p >= CR_pos) { break; }
if (*p != ']') { // ] of [data] not found.
JLOG_ERRO("AdemcoPacket::Parse ] of [data] not found!");
break;
}
size_t ademco_data_len = ++p - data_pos;
if (!ademcoData_.parse(data_pos, ademco_data_len)) {
JLOG_ERRO("AdemcoPacket::Parse parse data failed!");
break;
}
// data
if (*p != '[') { // [ of [data] not found.
JLOG_ERRO("AdemcoPacket::Parse [ of [data] not found!");
break;
}
const char* data_pos = p;
while (p < CR_pos && *p != ']') { p++; } if (p >= CR_pos) { break; }
if (*p != ']') { // ] of [data] not found.
JLOG_ERRO("AdemcoPacket::Parse ] of [data] not found!");
break;
}
size_t ademco_data_len = ++p - data_pos;
if (!ademcoData_.parse(data_pos, ademco_data_len)) {
JLOG_ERRO("AdemcoPacket::Parse parse data failed!");
break;
}
// [x...data...]
if (*p == '[') { // xdata exists
xdata_ = parseXData(p, CR_pos);
if (!xdata_) { break; }
p += xdata_->rawSize();
}
// [x...data...]
if (*p == '[') { // xdata exists
xdata_ = parseXData(p, CR_pos);
if (!xdata_) { break; }
p += xdata_->rawSize();
}
if (*p != '_') { // _ of _timestamp not found.
JLOG_ERRO("AdemcoPacket::Parse _ of _timestamp not found!");
break;
}
if (!timestamp_.parse(p, CR_pos - p)) {
JLOG_ERRO("AdemcoPacket::Parse parse timestamp failed!");
break;
}
p += timestamp_.length;
if (*p != '_') { // _ of _timestamp not found.
JLOG_ERRO("AdemcoPacket::Parse _ of _timestamp not found!");
break;
}
if (!timestamp_.parse(p, CR_pos - p)) {
JLOG_ERRO("AdemcoPacket::Parse parse timestamp failed!");
break;
}
p += timestamp_.length;
// check CR
if (p++ != CR_pos) { assert(0); break; }
// check CR
if (p++ != CR_pos) { assert(0); break; }
cb_commited = p - pack;
return ParseResult::RESULT_OK;
} while (0);
cb_commited = p - pack;
return ParseResult::RESULT_OK;
} while (0);
} catch (std::exception& e) {
printf("AdemcoPacket::parse EXCEPTION: %s\n", e.what());
abort();
}
// dump data
JLOG_HEX(pack, pack_len);
......
......@@ -7,7 +7,7 @@
#include <string>
#include <type_traits>
#include <iterator>
#include "ademco_detail.h"
#include "ademco_packet.h"
namespace hb
{
......@@ -145,10 +145,6 @@ static constexpr MachineType AllMachineTypes[MachineTypeCount] = {
IoT,
};
//! 防区号为0时表示主机自身
static constexpr uint16_t Zone4MachineSelf = 0;
//! 主机防区号范围
static constexpr uint16_t ZoneMin = 1;
//! 最大防区号根据型号不同而不同
static uint16_t zoneMax(MachineType type) {
switch (type) {
......@@ -177,27 +173,15 @@ static uint16_t zoneMax(MachineType type) {
break;
}
}
//! 对任何主机类型,最大的防区数量
static constexpr uint16_t MaxZoneCount = 1000;
//! 对任何主机类型,防区号是否合法(可以包含0防区)
static bool isValidZone(uint16_t zone) {
return Zone4MachineSelf <= zone && zone < MaxZoneCount;
}
//! 对任何主机类型,防区号是否合法(不可以包含0防区)
static bool isValidZoneStrict(uint16_t zone) {
return ZoneMin <= zone && zone < MaxZoneCount;
}
//! 防区号是否合法(可以包含0防区)
static bool isValidZone(MachineType type, uint16_t zone) {
return Zone4MachineSelf <= zone && zone <= zoneMax(type);
return ademco::Zone4MachineSelf <= zone && zone <= zoneMax(type);
}
//! 防区号是否合法(不可以可以包含0防区)
static bool isValidZoneStrict(MachineType type, uint16_t zone) {
return ZoneMin <= zone && zone <= zoneMax(type);
return ademco::ZoneMin <= zone && zone <= zoneMax(type);
}
//! 主机是否具有半布防功能
......@@ -1776,20 +1760,15 @@ struct WirelessAddress {
};
//! 防区号为0时表示主机(或分主机)自身
static constexpr uint16_t Zone4MachineSelf = 0;
//! 主机防区号范围1~999
static constexpr uint16_t ZoneMin = 1;
static constexpr uint16_t ZoneMax = 999;
//! 主机有线防区范围1~7
static constexpr uint16_t ZoneMinWired = ZoneMin;
static constexpr uint16_t ZoneMaxWired = 8;
constexpr ademco::AdemcoZone ZoneMinWired = 1;
constexpr ademco::AdemcoZone ZoneMaxWired = 8;
//! 主机无线防区最小值
static constexpr uint16_t ZoneMinWireless = ZoneMaxWired + 1;
static constexpr uint16_t ZoneMaxWireless = ZoneMax;
constexpr ademco::AdemcoZone ZoneMinWireless = 9;
constexpr ademco::AdemcoZone ZoneMaxWireless = 999;
//! 分主机防区号范围1~99
static constexpr uint16_t ZoneMinSubMachine = 1;
static constexpr uint16_t ZoneMaxSubMachine = 99;
constexpr ademco::AdemcoZone ZoneMinSubMachine = 1;
constexpr ademco::AdemcoZone ZoneMaxSubMachine = 99;
//! 以2个字节表示的防区号
......@@ -1841,9 +1820,9 @@ struct ZoneInfo {
//! 所有防区信息
struct AllZoneInfo {
//! use extra 1 space, for convenience to use zone as index
ZoneInfo zones[ZoneMax + 1] = {};
ZoneInfo zones[ademco::ZoneSentinel] = {};
AllZoneInfo() { for (uint16_t i = 0; i <= ZoneMax; i++) { zones[i].zone = i; } }
AllZoneInfo() { for (uint16_t i = 0; i < ademco::ZoneSentinel; i++) { zones[i].zone = i; } }
bool isUniqueAddr(WirelessAddress addr) const {
for (const auto& z : zones) { if (z.addr == addr)return false; }
......@@ -1906,7 +1885,7 @@ struct Query {
void setZone(ZoneAsTwoChar zone) { data[3] = zone.hi; data[4] = zone.lo; }
static Query queryMachineStatus() {
return queryZoneStatus(Zone4MachineSelf);
return queryZoneStatus(ademco::Zone4MachineSelf);
}
static Query queryZoneStatus(uint16_t zone) {
......@@ -1918,7 +1897,7 @@ struct Query {
}
static Query querySubMachineStatus() {
return queryZoneStatusOfSubMachine(Zone4MachineSelf);
return queryZoneStatusOfSubMachine(ademco::Zone4MachineSelf);
}
static Query queryZoneStatusOfSubMachine(Char zone) {
......
......@@ -5,13 +5,6 @@
namespace hb
{
//! 安定宝ID范围
static constexpr size_t MinAdemcoId = 1;
static constexpr size_t MaxAdemcoId = 999999; // 兼容性考虑,最大安定宝 ID 为 0x0F423F
static constexpr size_t AdemcoIdSentinel = MaxAdemcoId + 1;
static constexpr bool isValidAdemcoId(size_t ademcoId) { return MinAdemcoId <= ademcoId && ademcoId <= MaxAdemcoId; }
/******** 结合 hb 与 ademco ******/
//! 从事件码推出主机类型
......@@ -23,6 +16,7 @@ static common::MachineType machineTypeFromAdemcoEvent(ademco::ADEMCO_EVENT e) {
case ademco::EVENT_I_AM_WIRE_MACHINE: return common::MachineType::Wired;
case ademco::EVENT_I_AM_WIFI_MACHINE: return common::MachineType::WiFi;
case ademco::EVENT_I_AM_3_SECTION_MACHINE: return common::MachineType::ThreeSection;
case ademco::EVENT_I_AM_IOT_MACHINE: return common::MachineType::IoT;
default: return common::MachineType::InvalidMachineType;
}
}
......
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