diff --git a/maxcube/connection.py b/maxcube/connection.py index 79c66c6..1883394 100644 --- a/maxcube/connection.py +++ b/maxcube/connection.py @@ -35,8 +35,11 @@ def read(self): break self.response = buffer.decode('utf-8') + def send(self, command): + self.socket.send(command.encode('utf-8')) + self.read() + def disconnect(self): if self.socket: - # self.send_message(QuitMessage())?? self.socket.close() self.socket = None diff --git a/maxcube/cube.py b/maxcube/cube.py index 7e8310b..a5fdd78 100644 --- a/maxcube/cube.py +++ b/maxcube/cube.py @@ -1,5 +1,6 @@ import base64 import struct + from maxcube.device import \ MaxDevice, \ MAX_CUBE, \ @@ -26,10 +27,7 @@ def __init__(self, connection): self.init() def init(self): - self.connection.connect() - response = self.connection.response - self.parse_response(response) - self.connection.disconnect() + self.update() logger.info('Cube (rf=%s, firmware=%s)' % (self.rf_address, self.firmware_version)) for device in self.devices: if self.is_thermostat(device): @@ -40,6 +38,12 @@ def init(self): else: logger.info('Device (rf=%s, name=%s' % (device.rf_address, device.name)) + def update(self): + self.connection.connect() + response = self.connection.response + self.parse_response(response) + self.connection.disconnect() + def device_by_rf(self, rf): for device in self.devices: if device.rf_address == rf: @@ -95,6 +99,7 @@ def parse_m_message(self, message): device_rf_address = ''.join("%X" % x for x in data[pos + 1: pos + 1 + 3]) device_name_length = data[pos + 14] device_name = data[pos + 15:pos + 15 + device_name_length].decode('utf-8') + room_id = data[pos + 15 + device_name_length] device = self.device_by_rf(device_rf_address) @@ -108,6 +113,7 @@ def parse_m_message(self, message): if device: device.type = device_type device.rf_address = device_rf_address + device.room_id = room_id device.name = device_name pos += 1 + 3 + 10 + device_name_length + 2 @@ -135,6 +141,26 @@ def parse_l_message(self, message): device.target_temperature = (data[pos + 7] & 0x7F) / 2 pos += length + def set_target_temperature(self, thermostat, temperature): + rf_address = thermostat.rf_address + if len(rf_address) < 6: + rf_address = '0' + rf_address + room = str(thermostat.room_id) + if thermostat.room_id < 10: + room = '0' + room + target_temperature = int(temperature * 2) + target_temperature |= (1 << 6) + target_temperature &= ~ (1 << 7) + + byte_cmd = '000440000000' + rf_address + room + hex(target_temperature)[2:] + command = 's:' + base64.b64encode(bytearray.fromhex(byte_cmd)).decode('utf-8') + '\r\n' + + self.connection.connect() + self.connection.send(command) + self.connection.disconnect() + thermostat.target_temperature = int(temperature * 2)/2 + + @classmethod def resolve_device_mode(cls, bits): if not bool(bits & 0x02) and not bool(bits & 0x01): diff --git a/maxcube/device.py b/maxcube/device.py index 6f4f3ef..e00c9de 100644 --- a/maxcube/device.py +++ b/maxcube/device.py @@ -15,4 +15,5 @@ class MaxDevice: def __init__(self): self.type = None self.rf_address = None + self.room_id = None self.name = None diff --git a/tests/test_cube.py b/tests/test_cube.py index 2e03482..0f5528b 100644 --- a/tests/test_cube.py +++ b/tests/test_cube.py @@ -8,6 +8,7 @@ MAX_THERMOSTAT_PLUS, \ MAX_DEVICE_MODE_AUTOMATIC, \ MAX_DEVICE_MODE_MANUAL +from maxcube.thermostat import MaxThermostat INIT_RESPONSE = \ 'H:KEQ0566338,0b6475,0113,00000000,74b7b6f7,00,32,0f0c19,1527,03,0000\n\r' \ @@ -34,11 +35,15 @@ class MaxCubeConnectionMock(MaxCubeConnection): def __init__(self): super().__init__(None, None) + self.command = None def connect(self): self.response = INIT_RESPONSE return + def send(self, command): + self.command = command + def disconnect(self): return @@ -115,6 +120,12 @@ def test_is_thermostat(self): device.type = MAX_THERMOSTAT_PLUS self.assertEqual(True, self.cube.is_thermostat(device)) + def test_set_target_temperature(self): + self.cube.set_target_temperature(self.cube.devices[0], 24.5) + self.assertEqual('s:AARAAAAABrxTAXE=\r\n', self.cube.connection.command) + self.assertEqual(24.5, self.cube.devices[0].target_temperature) + self.cube.set_target_temperature(self.cube.devices[0], 24.6) + self.assertEqual(24.5, self.cube.devices[0].target_temperature)