Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
A
ademco_hb
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
captainwong
ademco_hb
Commits
b01215da
Commit
b01215da
authored
Aug 23, 2020
by
captainwong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
防拆索要
parent
85f9f57a
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
196 additions
and
60 deletions
+196
-60
server_demo_libevent.cpp
examples/server_demo_libevent/server_demo_libevent.cpp
+94
-12
ademco_event.h
include/ademco_event.h
+1
-1
ademco_packet.h
include/ademco_packet.h
+1
-1
hb_detail.h
include/hb_detail.h
+98
-44
hb_helper.h
include/hb_helper.h
+2
-2
No files found.
examples/server_demo_libevent/server_demo_libevent.cpp
View file @
b01215da
...
...
@@ -22,6 +22,7 @@
#include <algorithm>
#include <chrono>
#include <unordered_map>
#include <map>
#include <event2/listener.h>
#include <event2/buffer.h>
...
...
@@ -57,8 +58,11 @@ static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
#define DISABLE_JLIB_LOG2
#include <ademco_packet.h>
#define ENABLE_COMMON_MACHINE_STATUS_TO_STRING
#define ENABLE_COMMON_MACHINE_TYPE_TO_STRING
#define ENABLE_COMMON_ZONE_PROPERTY_TO_STRING
#include <hb_detail.h>
#include <hb_helper.h>
using
namespace
ademco
;
using
namespace
hb
;
...
...
@@ -83,7 +87,7 @@ enum class QueryZoneStage {
struct
ZonePropertyAndLostConfig
{
ZoneProperty
prop
=
ZoneProperty
::
InvalidZoneProperty
;
bool
enableLostReport
=
false
;
// 失联开关
bool
tamper_enabled
=
false
;
// 失联开关
};
struct
Client
{
...
...
@@ -93,7 +97,11 @@ struct Client {
size_t
ademco_id
=
0
;
uint16_t
seq
=
0
;
int
type
=
-
1
;
std
::
unordered_map
<
size_t
,
ZonePropertyAndLostConfig
>
zones
=
{};
MachineStatus
status
=
MachineStatus
::
Arm
;
MachineStatus
status1
=
MachineStatus
::
Arm
;
MachineStatus
status2
=
MachineStatus
::
Arm
;
MachineStatus
status3
=
MachineStatus
::
Arm
;
std
::
map
<
size_t
,
ZonePropertyAndLostConfig
>
zones
=
{};
QueryZoneStage
queryZoneStage
=
QueryZoneStage
::
None
;
uint16_t
nextSeq
()
{
if
(
++
seq
==
10000
)
{
seq
=
1
;
}
return
seq
;
}
...
...
@@ -167,30 +175,34 @@ void usage(const char* name)
void
handle_com_passthrough
(
ThreadContext
*
context
,
Client
&
client
,
evbuffer
*
output
)
{
if
(
!
context
->
packet
.
xdata_
)
{
printf
(
"WARNING! 1704 NO XDATA!
\n
"
);
printf
(
"
\t
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
());
printf
(
"
\t
%s
\n
"
,
detail
::
toString
(
xdata
,
detail
::
ToStringOption
::
ALL_CHAR_AS_HEX
,
false
,
false
).
data
());
char
buf
[
1024
];
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
:
{
char
buf
[
1024
];
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
)
{
ZonePropertyAndLostConfig
zplc
;
zplc
.
prop
=
zp
.
prop
;
zplc
.
enableLostReport
=
false
;
zplc
.
tamper_enabled
=
false
;
client
.
zones
[
zp
.
zone
]
=
zplc
;
snprintf
(
buf
,
sizeof
(
buf
),
getZoneFormatString
(
machineTypeFromAdemcoEvent
((
ADEMCO_EVENT
)
client
.
type
)),
zp
.
zone
);
printf
(
"
\t\t
Zone:"
);
printf
(
buf
);
printf
(
" Prop:0x%02X %s
\n
"
,
zp
.
prop
,
zonePropertyToStringEn
(
zp
.
prop
));
}
XDataPtr
xdata
;
if
(
hasMore
)
{
// 继续索要剩余防区
...
...
@@ -237,16 +249,56 @@ void handle_com_passthrough(ThreadContext* context, Client& client, evbuffer* ou
case
com
:
:
ResponseParser
::
ResponseType
::
AB_response
:
break
;
case
com
:
:
ResponseParser
::
ResponseType
::
AD_response
:
break
;
{
com
::
ADR
resp
;
memcpy
(
resp
.
data
,
xdata
.
data
(),
xdata
.
size
());
resp
.
len
=
xdata
.
size
()
&
0xFF
;
bool
hasMore
=
false
;
std
::
vector
<
size_t
>
zones
;
if
(
client
.
queryZoneStage
==
QueryZoneStage
::
QueryingLostConfig
&&
resp
.
parse
(
zones
,
hasMore
))
{
for
(
const
auto
&
zone
:
zones
)
{
auto
&
z
=
client
.
zones
[
zone
];
client
.
zones
[
zone
].
tamper_enabled
=
true
;
snprintf
(
buf
,
sizeof
(
buf
),
getZoneFormatString
(
machineTypeFromAdemcoEvent
((
ADEMCO_EVENT
)
client
.
type
)),
zone
);
printf
(
"
\t\t
Zone:"
);
printf
(
buf
);
printf
(
" Tamper Enabled: true
\n
"
);
}
XDataPtr
xdata
;
if
(
hasMore
)
{
// 继续索要剩余防区
com
::
A2
req
;
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
,
client
.
fd
,
client
.
acct
.
data
(),
client
.
ademco_id
,
context
->
packet
.
toString
(
detail
::
ToStringOption
::
ALL_CHAR_AS_HEX
).
data
());
}
break
;
}
}
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
);
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
());
}
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"
);
client
.
status1
=
b1
.
data
.
cmd
.
status1
==
0
?
MachineStatus
::
Arm
:
MachineStatus
::
Disarm
;
client
.
status2
=
b1
.
data
.
cmd
.
status2
==
0
?
MachineStatus
::
Arm
:
MachineStatus
::
Disarm
;
client
.
status3
=
b1
.
data
.
cmd
.
status3
==
0
?
MachineStatus
::
Arm
:
MachineStatus
::
Disarm
;
printf
(
"
\t\t
status1: %d %s
\n\t\t
status2: %d %s
\n\t\t
status3: %d %s
\n
"
,
client
.
status1
,
machineStatusToString
(
client
.
status1
),
client
.
status2
,
machineStatusToString
(
client
.
status2
),
client
.
status3
,
machineStatusToString
(
client
.
status3
));
break
;
}
case
com
:
:
ResponseParser
::
ResponseType
::
Invalid_response
:
...
...
@@ -290,6 +342,13 @@ void handle_ademco_msg(ThreadContext* context, bufferevent* bev)
}
break
;
}
}
else
if
(
ademco
::
isMachineStatusEvent
(
context
->
packet
.
ademcoData_
.
ademco_event_
))
{
auto
status
=
machienStatusFromAdemcoEvent
(
context
->
packet
.
ademcoData_
.
ademco_event_
);
if
(
context
->
packet
.
ademcoData_
.
gg_
==
0
)
{
client
.
status
=
status
;
}
else
if
(
context
->
packet
.
ademcoData_
.
gg_
==
1
)
{
client
.
status1
=
status
;
}
else
if
(
context
->
packet
.
ademcoData_
.
gg_
==
2
)
{
client
.
status2
=
status
;
}
else
if
(
context
->
packet
.
ademcoData_
.
gg_
==
3
)
{
client
.
status3
=
status
;
}
else
{
break
;
}
}
else
if
(
context
->
packet
.
ademcoData_
.
ademco_event_
==
EVENT_COM_PASSTHROUGH
)
{
handle_com_passthrough
(
context
,
client
,
output
);
break
;
...
...
@@ -795,8 +854,31 @@ int main(int argc, char** argv)
}
}
printf
(
"Total connnected %zd clients:
\n
"
,
copiedClients
.
size
());
for
(
const
auto
&
client
:
copiedClients
)
{
printf
(
" fd=#%d acct=%s ademco_id=%zd
\n
"
,
client
.
fd
,
client
.
acct
.
data
(),
client
.
ademco_id
);
if
(
client
.
type
==
EVENT_I_AM_3_SECTION_MACHINE
)
{
printf
(
" fd=#%d acct=%s ademco_id=%zd type=%s
\n
"
,
client
.
fd
,
client
.
acct
.
data
(),
client
.
ademco_id
,
machineTypeToString
(
machineTypeFromAdemcoEvent
((
ADEMCO_EVENT
)
client
.
type
)));
printf
(
" status1: %d %s status2: %d %s status3: %d %s
\n
"
,
client
.
status1
,
machineStatusToString
(
client
.
status1
),
client
.
status2
,
machineStatusToString
(
client
.
status2
),
client
.
status3
,
machineStatusToString
(
client
.
status3
));
}
else
{
printf
(
" fd=#%d acct=%s ademco_id=%zd type=%s status=%d %s
\n
"
,
client
.
fd
,
client
.
acct
.
data
(),
client
.
ademco_id
,
machineTypeToString
(
machineTypeFromAdemcoEvent
((
ADEMCO_EVENT
)
client
.
type
)),
client
.
status
,
machineStatusToString
(
client
.
status
));
}
for
(
const
auto
&
zp
:
client
.
zones
)
{
char
buf
[
512
];
snprintf
(
buf
,
sizeof
(
buf
),
getZoneFormatString
(
machineTypeFromAdemcoEvent
((
ADEMCO_EVENT
)
client
.
type
)),
zp
.
first
);
printf
(
" Zone:"
);
printf
(
buf
);
printf
(
" Prop:0x%02X %s
\t
Tamper Enabled:%s
\n
"
,
zp
.
second
.
prop
,
zonePropertyToStringEn
(
zp
.
second
.
prop
),
zp
.
second
.
tamper_enabled
?
"true"
:
"false"
);
}
}
}
break
;
...
...
include/ademco_event.h
View file @
b01215da
...
...
@@ -344,7 +344,7 @@ inline const std::wstring ademcoEventToStringChinese(ADEMCO_EVENT ademco_event,
#endif
//! 是否主机状态事件
static
inline
bool
isStatusEvent
(
ADEMCO_EVENT
ademco_event
)
static
inline
bool
is
Machine
StatusEvent
(
ADEMCO_EVENT
ademco_event
)
{
return
ademco_event
==
EVENT_ARM
||
ademco_event
==
EVENT_HALFARM
...
...
include/ademco_packet.h
View file @
b01215da
...
...
@@ -275,7 +275,7 @@ struct CongwinFe100Packet
data_
[
ndx
++
]
=
' '
;
// 'C' for zone, 'U' for user
if
(
isStatusEvent
(
evnt
))
{
if
(
is
Machine
StatusEvent
(
evnt
))
{
data_
[
ndx
++
]
=
'U'
;
// U
}
else
{
data_
[
ndx
++
]
=
'C'
;
// C
...
...
include/hb_detail.h
View file @
b01215da
...
...
@@ -286,7 +286,7 @@ static const wchar_t* machineTypeToWString(MachineType type) {
//! 防区属性
enum
ZoneProperty
:
Char
{
//! 匪警全局
Buglar
Global
=
0x00
,
Buglar
=
0x00
,
//! 匪警紧急
Emergency
=
0x01
,
//! 火警防区
...
...
@@ -325,27 +325,27 @@ enum ZoneProperty : Char {
};
static
ZoneProperty
zonePropertyFromChar
(
Char
zp
)
{
if
(
ZoneProperty
::
Buglar
Global
<=
zp
&&
zp
<
ZoneProperty
::
ZonePropertyCount
)
if
(
ZoneProperty
::
Buglar
<=
zp
&&
zp
<
ZoneProperty
::
ZonePropertyCount
)
{
return
static_cast
<
ZoneProperty
>
(
zp
);
}
return
ZoneProperty
::
InvalidZoneProperty
;
}
static
std
::
vector
<
ZoneProperty
>
getAvailableZoneProperties
(
MachineType
type
)
{
switch
(
type
)
{
case
NetMod
:
return
{
Buglar
Global
,
Emergency
,
Fire
,
Duress
,
Gas
,
Water
,
SubMachine
,
RemoteControl
,
BuglarHalf
,
Shield
,
DoorRing
};
case
Gprs
:
return
{
Buglar
Global
,
Emergency
,
Fire
,
Duress
,
Gas
,
Water
,
};
case
Lcd
:
return
{
Buglar
Global
,
Emergency
,
Fire
,
Duress
,
Gas
,
Water
,
SubMachine
,
RemoteControl
,
BuglarHalf
,
Shield
,
DoorRing
};
case
Wired
:
return
{
Buglar
Global
,
Emergency
,
Fire
,
Duress
,
Gas
,
Water
,
};
case
TrueColor
:
return
{
Buglar
Global
,
Emergency
,
Fire
,
Duress
,
Gas
,
Water
,
RemoteControl
,
Shield
,
DoorRing
,
Bypass
};
case
ThreeSection
:
return
{
Buglar
Global
,
Emergency
,
Fire
,
Duress
,
Gas
,
Water
,
RemoteControl
,
Shield
,
DoorRing
,
Bypass
};
case
NetMod
:
return
{
Buglar
,
Emergency
,
Fire
,
Duress
,
Gas
,
Water
,
SubMachine
,
RemoteControl
,
BuglarHalf
,
Shield
,
DoorRing
};
case
Gprs
:
return
{
Buglar
,
Emergency
,
Fire
,
Duress
,
Gas
,
Water
,
};
case
Lcd
:
return
{
Buglar
,
Emergency
,
Fire
,
Duress
,
Gas
,
Water
,
SubMachine
,
RemoteControl
,
BuglarHalf
,
Shield
,
DoorRing
};
case
Wired
:
return
{
Buglar
,
Emergency
,
Fire
,
Duress
,
Gas
,
Water
,
};
case
TrueColor
:
return
{
Buglar
,
Emergency
,
Fire
,
Duress
,
Gas
,
Water
,
RemoteControl
,
Shield
,
DoorRing
,
Bypass
};
case
ThreeSection
:
return
{
Buglar
,
Emergency
,
Fire
,
Duress
,
Gas
,
Water
,
RemoteControl
,
Shield
,
DoorRing
,
Bypass
};
default
:
return
{};
}
}
#ifdef ENABLE_COMMON_ZONE_PROPERTY_TO_STRING
static
const
wchar_t
*
zonePropertyToString
(
ZoneProperty
zp
)
{
static
const
wchar_t
*
zonePropertyToString
Chinese
(
ZoneProperty
zp
)
{
switch
(
zp
)
{
case
ZoneProperty
:
:
Buglar
Global
:
return
L"匪警全局"
;
case
ZoneProperty
:
:
Buglar
:
return
L"匪警全局"
;
case
ZoneProperty
:
:
Emergency
:
return
L"匪警紧急"
;
case
ZoneProperty
:
:
Fire
:
return
L"火警防区"
;
case
ZoneProperty
:
:
Duress
:
return
L"胁迫防区"
;
...
...
@@ -365,6 +365,28 @@ static const wchar_t* zonePropertyToString(ZoneProperty zp) {
default
:
return
L"无效属性"
;
}
}
static
const
char
*
zonePropertyToStringEn
(
ZoneProperty
zp
)
{
switch
(
zp
)
{
case
ZoneProperty
:
:
Buglar
:
return
"Buglar"
;
case
ZoneProperty
:
:
Emergency
:
return
"Emergency"
;
case
ZoneProperty
:
:
Fire
:
return
"Fire"
;
case
ZoneProperty
:
:
Duress
:
return
"Duress"
;
case
ZoneProperty
:
:
Gas
:
return
"Gas"
;
case
ZoneProperty
:
:
Water
:
return
"Water"
;
case
ZoneProperty
:
:
SubMachine
:
return
"SubMachine"
;
case
ZoneProperty
:
:
RemoteControl
:
return
"RemoteControl"
;
case
ZoneProperty
:
:
BuglarHalf
:
return
"BuglarHalf"
;
case
ZoneProperty
:
:
Shield
:
return
"Shield"
;
case
ZoneProperty
:
:
DoorRing
:
return
"DoorRing"
;
case
ZoneProperty
:
:
Reserved0B
:
return
"Reserved0B"
;
case
ZoneProperty
:
:
Reserved0C
:
return
"Reserved0C"
;
case
ZoneProperty
:
:
Reserved0D
:
return
"Reserved0D"
;
case
ZoneProperty
:
:
Reserved0E
:
return
"Reserved0E"
;
case
ZoneProperty
:
:
Bypass
:
return
"Bypass"
;
case
ZoneProperty
:
:
InvalidZoneProperty
:
default
:
return
"InvalidZoneProperty"
;
}
}
#endif // ENABLE_COMMON_ZONE_PROPERTY_TO_STRING
...
...
@@ -428,7 +450,7 @@ struct MachineStatusResponse3Section {
Char
head
[
6
];
// 0 撤防,1 布防
Char
status3
:
2
;
Char
status2
:
2
;
Char
status2
:
2
;
Char
status1
:
2
;
Char
status
:
2
;
Char
sum
;
...
...
@@ -445,6 +467,16 @@ struct MachineStatusResponse3Section {
&&
data
.
cmd
.
head
[
5
]
==
0xB1
&&
sum
(
data
.
data
,
len
)
==
s
;
}
void
make
(
MachineStatus
status1
,
MachineStatus
status2
,
MachineStatus
status3
,
MachineStatus
status
=
MachineStatus
::
Arm
)
{
Char
head
[
6
]
=
{
0xEB
,
0xBA
,
0x3F
,
0x08
,
0xCC
,
0xB1
};
memcpy
(
data
.
cmd
.
head
,
head
,
6
);
data
.
cmd
.
status
=
(
Char
)
status
&
0x3
;
data
.
cmd
.
status1
=
(
Char
)
status1
&
0x3
;
data
.
cmd
.
status2
=
(
Char
)
status2
&
0x3
;
data
.
cmd
.
status3
=
(
Char
)
status3
&
0x3
;
sum
(
data
.
data
,
len
);
}
};
static_assert
(
sizeof
(
MachineStatusResponse3Section
)
==
8
,
"sizeof(MachineStatusResponse3Section) must be 8"
);
typedef
MachineStatusResponse3Section
B1R
;
...
...
@@ -478,22 +510,20 @@ typedef ZoneRequest A1;
//! 回应主机防区 EB BA 3F PN P0 A2 [Z, P]xN P1 SUM
struct
ZoneResponse
{
//! 一包数据最多有20个字节,所以最多可以包含 (20 - 8) / 2 = 6 个防区
static
constexpr
Char
max_
zone
=
6
;
static
constexpr
Char
max_
len
=
8
+
2
*
max_zone
;
static
constexpr
Char
min_len
=
8
;
// 无防区防拆数据时长度最小为8
static
constexpr
Char
max_
len
=
20
;
// 一包数据最多有20个字节
static
constexpr
Char
max_
zone
=
(
max_len
-
min_len
)
/
2
;
// 最多可以包含 (20 - 8) / 2 = 6 个防区
/*
* when param is not 0xFF, means there's more zone coming; vice versa
* zone&prop can be placed as much as 20 times
* 0 1 2 3.len 4 5 6.zone 7.prop 8.param 9.sum
*/
Char
data
[
max_len
]
=
{
0xEB
,
0xBA
,
0x3F
,
0x0A
,
0xCC
,
0xA2
,
0x00
,
0x00
,
0xFF
,
0x00
};
Char
len
=
10
;
// init as minimum len
Char
data
[
max_len
]
=
{};
Char
len
=
min_len
;
// init as minimum len
// default ctor, no zone exists
ZoneResponse
()
{
len
=
8
;
Char
nodata
[
8
]
=
{
0xEB
,
0xBA
,
0x3F
,
0x08
,
0xCC
,
0xA2
,
0xFF
,
0x00
};
memcpy
(
data
,
nodata
,
8
);
Char
nodata
[
min_len
]
=
{
0xEB
,
0xBA
,
0x3F
,
0x08
,
0xCC
,
0xA2
,
0xFF
,
0x00
};
sum
(
nodata
,
min_len
);
memcpy
(
data
,
nodata
,
min_len
);
len
=
min_len
;
}
/*
...
...
@@ -521,9 +551,9 @@ struct ZoneResponse {
//! 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
if
(
len
<
min_len
||
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
Char
count
=
(
len
-
min_len
)
/
2
;
// zone/prop pairs
if
(
count
==
0
)
{
zps
.
clear
();
hasMore
=
false
;
return
true
;
}
for
(
Char
i
=
0
;
i
<
count
;
i
++
)
{
ZoneAndProperty
zp
;
...
...
@@ -675,25 +705,55 @@ typedef QueryMoreSensorLostSettingsRequest AD;
//! 索要防区探头遗失/失联回应 EB BA 3F PN P0 AD P1 DATA P2 SUM
struct
QuerySensorLostSettingsResponse
{
CharVector
data
{};
const
Char
p1
=
0xF0
;
// F0 防区号单字节表示,F1防区号双字节表示
static
constexpr
Char
P1FlagZoneAs1Char
=
0xF0
;
static
constexpr
Char
P1FlagZoneAs2Chars
=
0xF1
;
static
constexpr
Char
min_len
=
9
;
// 无防区防拆数据时长度最小为9
static
constexpr
Char
max_len
=
20
;
QuerySensorLostSettingsResponse
(
Char
p1
=
0xF0
)
:
p1
(
p1
)
{
data
=
{
0xEB
,
0xBA
,
0x3F
,
0
,
0xAD
,
p1
};
Char
data
[
max_len
]
=
{};
Char
len
=
9
;
// init as minimum len
const
Char
p1
=
P1FlagZoneAs1Char
;
// F0 防区号单字节表示,F1防区号双字节表示
// default ctor, no zone exists
QuerySensorLostSettingsResponse
(
Char
p1
=
P1FlagZoneAs1Char
)
:
p1
(
p1
)
{
Char
nodata
[
min_len
]
=
{
0xEB
,
0xBA
,
0x3F
,
0x09
,
0x00
,
0xAD
,
p1
,
0xFF
,
0x00
};
sum
(
nodata
,
min_len
);
memcpy
(
data
,
nodata
,
min_len
);
len
=
min_len
;
}
void
addZone
(
size_t
zone
,
bool
isOver
=
true
,
bool
hasMore
=
false
)
{
data
[
3
]
++
;
if
(
p1
==
0xF0
)
{
data
.
push_back
(
zone
&
0xFF
);
}
else
{
data
.
push_back
((
zone
>>
8
)
&
0xFF
);
data
.
push_back
(
zone
&
0xFF
);
Char
maxZone
()
const
{
Char
res
=
(
max_len
-
min_len
);
if
(
p1
==
P1FlagZoneAs2Chars
)
{
res
/=
2
;
}
return
res
;
}
QuerySensorLostSettingsResponse
&
addZone
(
size_t
zone
,
bool
isOver
=
true
,
bool
hasMore
=
false
)
{
if
(
len
==
max_len
)
{
return
*
this
;
}
Char
pos
=
static_cast
<
Char
>
(
len
-
2
);
if
(
p1
==
P1FlagZoneAs1Char
)
{
data
[
pos
]
=
zone
&
0xFF
;
len
=
static_cast
<
Char
>
(
len
+
1
);
data
[
3
]
=
len
;
}
else
{
data
[
pos
]
=
(
zone
>>
8
)
&
0xFF
;
data
[
pos
+
1
]
=
zone
&
0xFF
;
len
=
static_cast
<
Char
>
(
len
+
2
);
data
[
3
]
=
len
;
}
if
(
isOver
)
{
data
.
push_back
(
hasMore
?
0x00
:
0xFF
);
data
.
push_back
(
0
);
// sum
sum
(
data
);
data
[
len
-
2
]
=
hasMore
?
0x00
:
0xFF
;
if
(
isOver
)
{
sum
(
this
);
}
return
*
this
;
}
//! parser, make sure to call ResponseParser::parse first and return is ADR_response to check data valid, then copy data/len to member.
bool
parse
(
std
::
vector
<
size_t
>&
zones
,
bool
&
hasMore
)
{
if
(
len
<
min_len
||
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
flag
=
data
[
6
];
if
(
flag
!=
P1FlagZoneAs1Char
&&
flag
!=
P1FlagZoneAs2Chars
)
{
return
false
;
}
// check param
Char
count
=
(
len
-
min_len
);
if
(
flag
==
P1FlagZoneAs2Chars
)
{
count
/=
2
;
}
if
(
count
==
0
)
{
zones
.
clear
();
hasMore
=
false
;
return
true
;
}
for
(
Char
i
=
0
;
i
<
count
;
i
++
)
{
size_t
zone
=
data
[
7
+
i
];
if
(
p1
==
P1FlagZoneAs2Chars
)
{
zone
<<=
8
;
zone
|=
data
[
8
+
i
];
}
zones
.
push_back
(
zone
);
}
hasMore
=
data
[
len
-
2
]
!=
0xFF
;
return
true
;
}
};
typedef
QuerySensorLostSettingsResponse
ADR
;
...
...
@@ -839,7 +899,7 @@ struct RequestParser {
}*/
// EB CB 3F 06 B0 AB
if
(
data
[
3
]
==
0x0
8
&&
data
[
4
]
==
0xB0
&&
len
==
B0
::
len
&&
memcmp
(
B0
::
data
,
data
,
len
)
==
0
)
{
if
(
data
[
3
]
==
0x0
6
&&
data
[
4
]
==
0xB0
&&
len
==
B0
::
len
&&
memcmp
(
B0
::
data
,
data
,
len
)
==
0
)
{
return
RequestType
::
B0_request
;
}
}
...
...
@@ -944,14 +1004,8 @@ struct ResponseParser {
case
0xAD
:
// EB BA 3F PN P0 AD P1 DATA P2 SUM
{
//Char lenExpected = 0;
//if (data[6] == 0xF0) { // 防区号1个字节
// lenExpected = 6 + data[3] + 2;
//} else if (data[6] == 0xF1) { // 防区号2个字节
// lenExpected = 6 + data[3] * 2 + 2;
//} else { 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
;
memcpy
(
resp
.
data
,
data
,
len
);
sum
(
resp
);
sum
(
resp
);
if
(
resp
.
data
[
len
-
1
]
!=
data
[
len
-
1
])
{
break
;
}
return
ResponseType
::
AD_response
;
}
...
...
include/hb_helper.h
View file @
b01215da
...
...
@@ -76,7 +76,7 @@ static ademco::ADEMCO_EVENT ademcoEventFromMachineStatus(common::MachineStatus s
static
ademco
::
ADEMCO_EVENT
ademcoEventFromZoneProperty
(
common
::
ZoneProperty
zp
)
{
switch
(
zp
)
{
case
hb
:
:
common
::
Buglar
Global
:
return
ademco
::
EVENT_BURGLAR
;
case
hb
:
:
common
::
Buglar
:
return
ademco
::
EVENT_BURGLAR
;
case
hb
:
:
common
::
BuglarHalf
:
return
ademco
::
EVENT_BURGLAR
;
case
hb
:
:
common
::
Emergency
:
return
ademco
::
EVENT_EMERGENCY
;
case
hb
:
:
common
::
Fire
:
return
ademco
::
EVENT_FIRE
;
...
...
@@ -104,7 +104,7 @@ static ademco::ADEMCO_EVENT ademcoEventFromZonePropertyOld(old::ZoneProperty zp)
{
switch
(
zp
)
{
case
hb
:
:
old
::
ZP_GLOBAL
:
return
ademco
::
EVENT_BURGLAR
;
case
hb
:
:
old
::
ZP_HALF
:
return
ademco
::
EVENT_
HALFARM
;
case
hb
:
:
old
::
ZP_HALF
:
return
ademco
::
EVENT_
BURGLAR
;
case
hb
:
:
old
::
ZP_EMERGENCY
:
return
ademco
::
EVENT_EMERGENCY
;
case
hb
:
:
old
::
ZP_DOORRING
:
return
ademco
::
EVENT_DOORRINGING
;
case
hb
:
:
old
::
ZP_FIRE
:
return
ademco
::
EVENT_FIRE
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment