-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathkwikset_protocol.py
More file actions
99 lines (82 loc) · 2.69 KB
/
Copy pathkwikset_protocol.py
File metadata and controls
99 lines (82 loc) · 2.69 KB
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
#!/usr/bin/python
# This is a library for providing access to Kwikset Smartcode Locks via UART
# The h/w interface is 3.3V 9600 baud 8N1 standard UART
# This is more of a protocol encoder/decoder though
from binascii import hexlify,unhexlify
pkt_count = 0
NO_DATA = ''
LOCK_CMD = 'e703'
UNLOCK_CMD = 'e705'
INIT_CMDS = ('e707','e74d','e702','e70a','e718','e709','e742','e70f')
INIT_DATAS = ('','','','','','','01010101','15031301471205')
PARSE_LOOKUP = {'e709':"parse_initack",'e727':"parse_lockstatus",'e729':"parse_newlockcode",'e742':"parse_error"}
def generate_packet(cmd,data):
global pkt_count
pkt_count += 1
length = (len(cmd+data)/2)+2
base_pkt = "%0.2x%0.2x" % (length,pkt_count)+cmd+data
pkt = "bd"+base_pkt+calculate_crc(base_pkt)
return pkt
def calculate_crc(pkt):
crc = int("ff",16)
#print "Starting crc = %0.2x"%crc
while len(pkt)>1:
crc ^= int(pkt[0:2],16)
#print "After byte 0x%s, CRC = %0.2x, Len=%d"%(pkt[0:2],crc,len(pkt))
pkt = pkt[2:]
return "%0.2x"%crc
def validate_crc(pkt):
if calculate_crc(pkt) == '00':
return True
else:
return False
def parse_packet(pkt):
if pkt[0:2] != 'bd':
print "Bad packet header"
return False
if not validate_crc(pkt[2:]):
print "Bad packet CRC"
return False
if ((len(pkt)/2)-2) != int(pkt[2:4],16):
print "Bad packet length"
return False
cmd = pkt[6:10]
data = pkt[10:-2]
print "Found cmd=%s & data=%s"%(cmd,data)
if cmd in PARSE_LOOKUP:
parse = globals()[PARSE_LOOKUP[cmd]]
return parse(data)
return True
def parse_initack(data):
if data == '64':
return True
else:
return False
def parse_lockstatus(data):
code_used = int(data[2:4],16)
status_bits = int(data[4:6],16)
if status_bits & 0x80:
cause = "Remote Control"
elif status_bits & 0x40:
cause = "Code %d Entered"%(code_used)
elif status_bits & 0x20:
cause = "Automatic Lock"
else:
cause = "Manual/Key"
if status_bits & 0x02:
lock_state = "Unlocked"
elif status_bits & 0x01:
lock_state = "Locked"
else:
lock_state = "Unknown"
return (lock_state,cause)
def parse_newlockcode(data):
return data
def parse_error(data):
return data
def generate_init_packet(num):
return unhexlify(generate_packet(INIT_CMDS[num],INIT_DATAS[num]))
def generate_lock_packet():
return unhexlify(generate_packet(LOCK_CMD,''))
def generate_unlock_packet():
return unhexlify(generate_packet(UNLOCK_CMD,''))