-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsecurity.py
172 lines (127 loc) · 5.1 KB
/
security.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# security.py>
from common import *
# Message Types
RFXCOM_SECURITY_MSG_UNKNOWN = 0
RFXCOM_SECURITY_MSG_POWERCODE = 1
RFXCOM_SECURITY_MSG_CODESECURE = 2
RFXCOM_SECURITY_MSG_X10SEC = 3
RFXCOM_SECURITY_JAMMING_DETECT = 4
RFXCOM_SECURITY_JAMMING_END = 5
# Message code format:
# Bit 7 6 5 4 3 2 1 0
# | | | | | | | |______ 0: Battery OK 1: Battery low
# | | | | | | |________ 0: Sensor 1: Keyfob
# | | | | | |__________ 0: No Visonic 1: Visonic
# | | | | |____________ 0: Door/Window 1: Motion
# | | | |______________ 0: 1:
# | | |________________ 0: 1:
# | |__________________ 0: Tamper close 1: Tamper open
# |____________________ 0: Alert 1: Normal
def even_parity(byte_to_check):
sum_of_bits = (byte_to_check & 0x80) >> 7
sum_of_bits += (byte_to_check & 0x40) >> 6
sum_of_bits += (byte_to_check & 0x20) >> 5
sum_of_bits += (byte_to_check & 0x10) >> 4
sum_of_bits += (byte_to_check & 0x08) >> 3
sum_of_bits += (byte_to_check & 0x04) >> 2
sum_of_bits += (byte_to_check & 0x02) >> 1
sum_of_bits += (byte_to_check & 0x01)
return (sum_of_bits & 0x01)
def secIsJammingDetect(msg):
if ((msg[3] == 0xE0) and ((msg[1] == 0xFF) or (msg[1] == 0x00))):
return True
return False
def secIsJammingEnd(msg):
if ((msg[3] == 0xF8) and ((msg[1] == 0xFF) or (msg[1] == 0x00))):
return True
return False
def isSecurity(msg):
msgtype = RFXCOM_SECURITY_MSG_UNKNOWN
# Check 41 bit message length for a Visonic PowerCode message
if ((msg[0] & 0x7F) == 0x29) and (len(msg) >= 7):
# Check bytes
if (msg[3] + msg[4] == 0xFF) and (even_parity(msg[5]) == ((msg[6] & 0x80) >> 7)):
# Check for jamming
if secIsJammingDetect(msg):
msgtype = RFXCOM_SECURITY_JAMMING_DETECT
elif secIsJammingEnd(msg):
msgtype = RFXCOM_SECURITY_JAMMING_END
else:
msgtype = RFXCOM_SECURITY_MSG_POWERCODE
# Check XX bit message length for a Visonic CodeSecure message
#else if ((msg[0] & 0x7F) == 0x??) {
# *msgtype = RFXCOM_SECURITY_MSG_CODESECURE;
#}
# Check if is a X10Security message
elif (len(msg) >= 5):
if (msg[1] == ((msg[2] & 0xF0) + (0xF - (msg[2] & 0xF)))) and ((msg[3] ^ msg[4]) == 0xFF):
# Check for jamming
if secIsJammingDetect(msg):
msgtype = RFXCOM_SECURITY_JAMMING_DETECT
elif secIsJammingEnd(msg):
msgtype = RFXCOM_SECURITY_JAMMING_END
else:
msgtype = RFXCOM_SECURITY_MSG_X10SEC
return msgtype
def getSecurityMsgLength(msg):
return (msg[0] & 0x7F) // 8 + 1 if (msg[0] & 0x7F) % 8 == 0 else (msg[0] & 0x7F) // 8 + 2
def decode_powercode(msg):
# Extract Address
addr0 = ((msg[1] & 0xF0) >> 4) + 48 if ((msg[1] & 0xF0) >> 4) < 10 else ((msg[1] & 0xF0) >> 4) + 55
addr1 = (msg[1] & 0x0F) + 48 if (msg[1] & 0x0F) < 10 else (msg[1] & 0x0F) + 55
addr2 = ((msg[2] & 0xF0) >> 4) + 48 if ((msg[2] & 0xF0) >> 4) < 10 else ((msg[2] & 0xF0) >> 4) + 55
addr3 = (msg[2] & 0x0F) + 48 if (msg[2] & 0x0F) < 10 else (msg[2] & 0x0F) + 55
addr4 = ((msg[5] & 0xF0) >> 4) + 48 if ((msg[5] & 0xF0) >> 4) < 10 else ((msg[5] & 0xF0) >> 4) + 55
addr5 = (msg[5] & 0x0F) + 48 if (msg[5] & 0x0F) < 10 else (msg[5] & 0x0F) + 55
addr = str(chr(addr0)) + str(chr(addr1)) + str(chr(addr2)) + str(chr(addr3)) + str(chr(addr4)) + str(chr(addr5))
# Extract msgcode
msgcode = msg[3]
return addr, msgcode
def decode_X10Sec(msg):
return decode_powercode(msg)
def motionSensorType(msgcode):
if msgcode & 0x08:
return True
return False
def batteryStatusAvailable(msgcode):
if ((msgcode & 0x02) == 0x0):
return True
return False
def batteryLow(msgcode):
if ((msgcode & 0x03) == 0x01):
return True
return False
def sensorAlerted(msgcode):
if ((msgcode & 0x82) == 0x00) or (msgcode == 0x20):
return True
return False
def tamperOpened(msgcode):
if (msgcode & 0x42) == 0x40:
return True
return False
def processSecurityMsg(msg, msgType):
# Initialize vars
securitySensorData = list()
securitySensorData.append(RFXCOM_SENSOR_SECURITY)
addr = []
if (msgType == RFXCOM_SECURITY_MSG_POWERCODE) or (msgType == RFXCOM_SECURITY_MSG_X10SEC):
if msgType == RFXCOM_SECURITY_MSG_POWERCODE: # Decode the PowerCode message
addr, msgcode = decode_powercode(msg)
elif msgType == RFXCOM_SECURITY_MSG_X10SEC: # Decode the X10 Security message
addr, msgcode = decode_X10Sec(msg)
securitySensorData.append(addr)
if batteryStatusAvailable(msgcode):
securitySensorData.append(4)
securitySensorData.append(("BatteryLow", str(1 if batteryLow(msgcode) else 0), ""))
else:
securitySensorData.append(3)
securitySensorData.append(("SensorType", "Motion" if motionSensorType(msgcode) else "Door/Window", ""))
securitySensorData.append(("State", str(1 if sensorAlerted(msgcode) else 0), ""))
securitySensorData.append(("Tampered", str(1 if tamperOpened(msgcode) else 0), ""))
#elif msgType == RFXCOM_SECURITY_MSG_CODESECURE:
#elif msgType == RFXCOM_SECURITY_JAMMING_DETECT:
#elif msgType == RFXCOM_SECURITY_JAMMING_END:
else:
securitySensorData.append(addr)
securitySensorData.append(0)
return securitySensorData