Skip to content

Commit

Permalink
Fix Issue #26 Type Req / Hardware Join 1 & Range Test / Hardware Join 2
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesleesaunders committed Apr 18, 2017
1 parent 373e651 commit 7a2fe44
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 114 deletions.
18 changes: 1 addition & 17 deletions pyalertme/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,14 +218,6 @@ def pretty_mac(address_long):
'profile': ZDP_PROFILE_ID,
'data': '\xff\x00'
},
'hardware_join_1': {
'description': 'Hardware Join Message 1', # Device (also note similarity to Version req)
'src_endpoint': b'\x02',
'dest_endpoint': b'\x02',
'cluster': b'\x00\xf6',
'profile': ALERTME_PROFILE_ID,
'data': b'\x11\x01\xfc'
},
'active_endpoint_request': {
'description': 'Active Endpoint Request', # Device
'src_endpoint': b'\x00',
Expand All @@ -248,7 +240,7 @@ def pretty_mac(address_long):
'dest_endpoint': b'\x02',
'cluster': b'\x00\xf6',
'profile': ALERTME_PROFILE_ID,
'data': b'\x11\x00\xfc\x00\x01'
'data': b'\x11\x00\xfc'
},
'plug_off': {
'description': 'Switch Plug Off', # SmartPlug
Expand All @@ -274,14 +266,6 @@ def pretty_mac(address_long):
'profile': ALERTME_PROFILE_ID,
'data': b'\x11\x00\x01\x01'
},
'hardware_join_2': {
'description': 'Hardware Join Message 2', # Device (also note similarity to Normal Mode)
'src_endpoint': b'\x00',
'dest_endpoint': b'\x02',
'cluster': b'\x00\xf0',
'profile': ALERTME_PROFILE_ID,
'data': b'\x19\x01\xfa\x00\x01'
},
'normal_mode': {
'description': 'Normal Mode', # SmartPlug
'src_endpoint': b'\x00',
Expand Down
53 changes: 36 additions & 17 deletions pyalertme/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def __init__(self, callback=None):
self.hub_addr_short = None

self.rssi = 197
self.mode = 'NORMAL'

def process_message(self, message):
"""
Expand All @@ -50,7 +51,7 @@ def process_message(self, message):
if profile_id == self.ZDP_PROFILE_ID:
# Zigbee Device Profile ID
if cluster_id == b'\x00\x32':
self._logger.debug('Received Broacast Discover TBC')
self._logger.debug('Received Management Routing Table Request')

elif cluster_id == b'\x00\x05':
self._logger.debug('Received Active Endpoint Request')
Expand All @@ -72,23 +73,41 @@ def process_message(self, message):
self._logger.debug('Received Version Request')
self.send_message(self.generate_type_update(), self.hub_addr_long, self.hub_addr_short)

# elif cluster_id == b'\x00\xf6':
# b'\x11\x01\xfc'
# Almost the same as type above? Not sure on link yet?
# self._logger.debug('Received Hardware Join Message 1')

elif cluster_id == b'\x00\xf0':
self._logger.debug('Received Hardware Join Message 2')
# Take note of hub address
self.hub_addr_long = message['source_addr_long']
self.hub_addr_short = message['source_addr']
# We are now fully associated
self.associated = True

elif cluster_id == b'\x00\xee':
if cluster_cmd == b'\xfa':
self._logger.debug('Received Range Test Request')
self.send_message(self.generate_range_update(), self.hub_addr_long, self.hub_addr_short)
self._logger.debug('Received Mode Change Request')
# Take note of hub address
self.hub_addr_long = source_addr_long
self.hub_addr_short = source_addr_short
# We are now fully associated
self.associated = True

modeCmd = message['rf_data'][3] + message['rf_data'][4]
if modeCmd == b'\x00\x01':
# Normal
# b'\x11\x00\xfa\x00\x01'
self._logger.debug('Normal Mode')
self.mode = 'NORMAL'

elif modeCmd == b'\x01\x01':
# Range Test
# b'\x11\x00\xfa\x01\x01'
self._logger.debug('Range Test Mode')
self.mode = 'RANGE'
# TODO Setup thread loop to send regular range RSSI updates - for now just send one...
self.send_message(self.generate_range_update(), self.hub_addr_long, self.hub_addr_short)

elif modeCmd == b'\x02\x01':
# Locked
# b'\x11\x00\xfa\x02\x01'
self._logger.debug('Locked Mode')
self.mode = 'LOCKED'

elif modeCmd == b'\x03\x01':
# Silent
# b'\x11\x00\xfa\x03\x01'
self._logger.debug('Silent Mode')
self.mode = 'SILENT'

else:
self._logger.error('Unrecognised Profile ID: %r', profile_id)
Expand Down Expand Up @@ -126,7 +145,7 @@ def generate_range_update(self):
"""
checksum = b'\t+'
cluster_cmd = b'\xfd'
payload = struct.pack('B', self.rssi)
payload = struct.pack('H', self.rssi)
data = checksum + cluster_cmd + payload

message = {
Expand Down
40 changes: 6 additions & 34 deletions pyalertme/hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,9 @@ def process_message(self, message):
node_id = self.addr_long_to_node_id(source_addr_long)

if node_id:
self.save_node_properties(node_id, {'AddressLong': source_addr_long, 'AddressShort': source_addr_short})
self.nodes[node_id]['AddressLong'] = source_addr_long
self.nodes[node_id]['AddressShort'] = source_addr_short

profile_id = message['profile']
cluster_id = message['cluster']

Expand Down Expand Up @@ -226,9 +228,9 @@ def process_message(self, message):
# The next message is directed at the hardware code (rather than the network code).
time.sleep(2)
# The device has to receive this message to stay joined.
reply = self.generate_hardware_join_1()
reply = self.generate_type_request()
self.send_message(reply, source_addr_long, source_addr_short)
reply = self.generate_hardware_join_2()
reply = self.generate_mode_change_request('NORMAL')
self.send_message(reply, source_addr_long, source_addr_short)

# We are fully associated!
Expand Down Expand Up @@ -516,37 +518,7 @@ def generate_type_request(self):
'cluster': b'\x00\xf6',
'src_endpoint': b'\x00',
'dest_endpoint': b'\x02',
'data': b'\x11\x00\xfc\x00\x01'
}
return message

def generate_hardware_join_1(self):
"""
Generate Hardware Join 1
"""
message = {
'description': 'Hardware Join Messages 1',
'profile': self.ALERTME_PROFILE_ID,
'cluster': b'\x00\xf6',
'src_endpoint': b'\x02',
'dest_endpoint': b'\x02',
'data': b'\x11\x01\xfc'
}
return message

def generate_hardware_join_2(self):
"""
Generate Hardware Join 2
"""
message = {
'description': 'Hardware Join Messages 2',
'profile': self.ALERTME_PROFILE_ID,
'cluster': b'\x00\xf0',
'src_endpoint': b'\x00',
'dest_endpoint': b'\x02',
'data': b'\x19\x01\xfa\x00\x01'
'data': b'\x11\x00\xfc'
}
return message

Expand Down
17 changes: 0 additions & 17 deletions pyalertme/smartplug.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,23 +78,6 @@ def process_message(self, message):
self.send_message(self.generate_switch_state_update(), source_addr_long, source_addr_short)
self._callback('Attribute', self.get_node_id(), 'State', 'ON')

elif cluster_cmd == b'\xfa':
# Set Mode
if message['rf_data'][4] == b'\x00\x01':
# Normal
# b'\x11\x00\xfa\x00\x01'
self._logger.debug('Normal Mode')

elif message['rf_data'][4] == b'\x00\x01':
# Locked
# b'\x11\x00\xfa\x02\x01'
self._logger.debug('Locked Mode')

elif message['rf_data'][4] == b'\x03\x01':
# Silent
# b'\x11\x00\xfa\x03\x01'
self._logger.debug('Silent Mode')

else:
self._logger.error('Unrecognised Cluster Command: %r', cluster_cmd)

Expand Down
4 changes: 2 additions & 2 deletions pyalertme/tests/test_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def test_generate_range_update(self):
result = self.device_obj.generate_range_update()
expected = {
'cluster': b'\x00\xf6',
'data': b'\t+\xfd\x00',
'data': b'\t+\xfd\x00\x00',
'description': 'Range Info',
'dest_endpoint': b'\x02',
'profile': b'\xc2\x16',
Expand All @@ -32,7 +32,7 @@ def test_generate_range_update(self):
result = self.device_obj.generate_range_update()
expected = {
'cluster': b'\x00\xf6',
'data': b'\t+\xfd\xc5',
'data': b'\t+\xfd\xc5\x00',
'description': 'Range Info',
'dest_endpoint': b'\x02',
'profile': b'\xc2\x16',
Expand Down
28 changes: 2 additions & 26 deletions pyalertme/tests/test_hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def test_endpoint_request(self):
}
self.hub_obj.receive_message(message)
result = self.ser.get_data_written()
expected = b'~\x00\x19}1\x00\x00\ro\x00\x03\xbb\xb9\xf8\x88\x9f\x00\x02\x00\xf0\xc2\x16\x00\x00\x19\x01\xfa\x00\x01\xfd'
expected = b'~\x00\x19}1\x00\x00\ro\x00\x03\xbb\xb9\xf8\x88\x9f\x00\x02\x00\xf0\xc2\x16\x00\x00}1\x00\xfa\x00\x01\x06'
self.assertEqual(result, expected)

def test_parse_tamper_state(self):
Expand Down Expand Up @@ -277,7 +277,7 @@ def test_generate_type_request(self):
'cluster': b'\x00\xf6',
'src_endpoint': b'\x00',
'dest_endpoint': b'\x02',
'data': b'\x11\x00\xfc\x00\x01'
'data': b'\x11\x00\xfc'
}
self.assertEqual(result, expected)

Expand Down Expand Up @@ -307,30 +307,6 @@ def test_generate_match_descriptor_response(self):
}
self.assertEqual(result, expected)

def test_generate_hardware_join_1(self):
result = self.hub_obj.generate_hardware_join_1()
expected = {
'description': 'Hardware Join Messages 1',
'profile': b'\xc2\x16',
'cluster': b'\x00\xf6',
'src_endpoint': b'\x02',
'dest_endpoint': b'\x02',
'data': b'\x11\x01\xfc'
}
self.assertEqual(result, expected)

def test_generate_hardware_join_2(self):
result = self.hub_obj.generate_hardware_join_2()
expected = {
'description': 'Hardware Join Messages 2',
'profile': b'\xc2\x16',
'cluster': b'\x00\xf0',
'src_endpoint': b'\x00',
'dest_endpoint': b'\x02',
'data': b'\x19\x01\xfa\x00\x01'
}
self.assertEqual(result, expected)

def test_generate_security_init(self):
result = self.hub_obj.generate_security_init()
expected = {
Expand Down
2 changes: 1 addition & 1 deletion scripts/hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

# Create console handler and set level to info
sh = logging.StreamHandler()
sh.setLevel(logging.DEBUG)
sh.setLevel(logging.ERROR)
sh.setFormatter(formatter)
logger.addHandler(sh)

Expand Down

0 comments on commit 7a2fe44

Please sign in to comment.