def test_constructor_valid_values(self): self.assertEqual( RFAddr('122b65')._bytes, bytearray([0x12, 0x2b, 0x65])) self.assertEqual( RFAddr(bytearray([0x12, 0x2b, 0x65]))._bytes, bytearray([0x12, 0x2b, 0x65])) self.assertEqual( RFAddr((0x12, 0x2b, 0x65))._bytes, bytearray([0x12, 0x2b, 0x65]))
def test_contains(self): dl = DeviceList() dl.append( Device(rf_address=RFAddr('122b65'), serial='123', name='foobar')) self.assertTrue('foobar' in dl) self.assertTrue(RFAddr('122b65') in dl) self.assertTrue(bytearray([0x12, 0x2b, 0x65]) in dl) self.assertFalse(True in dl) self.assertFalse(1 in dl)
def test_equals(self): # string: case insensitive self.assertEqual(RFAddr('122b65'), '122b65') self.assertEqual(RFAddr('122b65'), '122B65') # another rf addr instance self.assertEqual(RFAddr('122b65'), RFAddr('122b65')) # bytearray self.assertEqual(RFAddr('122b65'), bytearray([0x12, 0x2b, 0x65]))
def test_update_add(self): dl = DeviceList() dl.update(rf_address=RFAddr('122b65'), serial='123', name='foobar', battery_low=False) self.assertEqual(dl, [ Device(rf_address=RFAddr('122b65'), serial='123', name='foobar', battery_low=False) ])
def test_equals(self): dev1 = Device(foo='bar') dev2 = Device(foo='bar') self.assertEqual(dev1, dev2) self.assertEqual(dev1, {'foo': 'bar'}) self.assertEqual(Device(rf_address=RFAddr('122b65')), Device(rf_address='122b65')) self.assertEqual(Device(rf_address=RFAddr('122b65')), {'rf_address': '122b65'}) self.assertNotEqual(Device(foo='bar'), Device(baz='bat', blah='blubb')) self.assertNotEqual(Device(foo='bar', baz='bat'), Device(blah='blubb')) self.assertNotEqual(Device(foo='bar'), {'baz': 'bat', 'blah': 'blubb'}) self.assertNotEqual(Device(foo='bar'), 1)
def _parse(self): self.name = self.data[0:8].decode('utf-8') self.serial = self.data[8:18].decode('utf-8') self.request_id = chr(self.data[18]) self.request_type = chr(self.data[19]) self.rf_address = RFAddr(self.data[21:24]) self.fw_version = ''.join("%02x" % x for x in self.data[24:26])
def _parse(self): device = self.data[:6].decode('utf-8') b64 = self.data[7:] data = bytearray(base64.b64decode(b64)) #self.dump_bytes(data, "device config") data_length = data[0] logger.debug("Data length for device config: %s", data_length) self.device_addr = RFAddr(data[1:4]) self.device_type, self.room_id, self.firmware_version, self.test_result = struct.unpack( 'bbbb', data[4:8]) self.serial_number = data[8:17].decode('utf-8') logger.debug( "Device config for %s: type: %s, room: %s, firmware: %s, test: %s, serial number: %s", self.device_addr, self.device_type, self.room_id, self.firmware_version, self.test_result, self.serial_number) if self.device_type == DeviceCube: self._parse_cube_config(data[18:]) elif self.device_type == DeviceRadiatorThermostat or self.device_type == DeviceRadiatorThermostatPlus: self._parse_thermostat_config(data[18:]) elif self.device_type == DeviceWallThermostat: self._parse_wall_thermostat_config(data[18:]) else: logger.warning( "Cannot parse device configuration for type %s (%s)", self.device_type, device_type_name(self.device_type))
def _parse(self): base64_data = self.data.decode('utf-8') data = bytearray(base64.b64decode(base64_data)) self.dump_bytes(data, "MResponse") # first two bytes are currently unknown self.num_rooms = data[2] logger.debug("Number of rooms from MResponse: %s", self.num_rooms) self.rooms = [] pos = 3 for i in range(0, self.num_rooms): logger.debug("Parsing room %s of %s (from pos %s)", i + 1, self.num_rooms, pos) room_id, name_length = struct.unpack('bb', data[pos:pos + 2]) room_name = data[pos + 2:pos + 2 + name_length].decode('utf-8') group_rf_address = RFAddr(data[pos + name_length + 2:pos + name_length + 2 + 3]) logger.debug("Room ID: %s, Room Name: %s, Group RF address: %s", room_id, room_name, group_rf_address) self.rooms.append((room_id, room_name, group_rf_address)) # set pos to start of next section pos += 1 + 1 + name_length + 3 self.devices = [] self.num_devices = data[pos] pos += 1 for device_idx in range(0, self.num_devices): device_type = data[pos] device_rf_address = RFAddr(data[pos + 1:pos + 1 + 3]) device_serial = data[pos + 4:pos + 14].decode('utf-8') 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] logger.debug( "Device: %s, Device RF address: %s, Device serial: %s, Device: %s, Room: %s", device_idx, device_rf_address, device_serial, device_name, room_id) self.devices.append((device_idx, device_type, device_rf_address, device_serial, device_name, room_id)) pos += 1 + 3 + 10 + device_name_length + 2
def test_set_program_with_rfaddr(self): c = self._mocked_cube() rfaddr = RFAddr('122b56') response = c.set_program(1, rfaddr, 1, []) setmessage = SetProgramMessage(rfaddr, 1, 1, []) c.send_message.assert_called_with(setmessage) self.assertIsInstance(response, SetResponse)
def test_for_room(self): dl = DeviceList() self.assertEqual(list(dl.for_room(0)), []) dev = Device(rf_address=RFAddr('122b65'), serial='123', name='foobar', room_id=1) dl.append(dev) self.assertEqual(list(dl.for_room(0)), []) self.assertEqual(list(dl.for_room(1)), [dev])
def test_update(self): for k, v in ( ('rf_address', '122b65'), ('name', 'foobar'), ): dl = DeviceList([ Device(rf_address=RFAddr('122b65'), serial='123', name='foobar', room_id=0, battery_low=False) ]) dl.update(room_id=1, **{k: v}) self.assertEqual(dl, [ Device(rf_address=RFAddr('122b65'), serial='123', name='foobar', room_id=1, battery_low=False) ])
def test_get(self): dev = Device(rf_address=RFAddr('122b65'), serial='123', name='foobar') dl = DeviceList([dev]) self.assertIsNone(dl.get()) self.assertEqual(dl.get(rf_address='122b65'), dev) self.assertEqual(dl.get(rf_address='122b65', serial='123'), dev) self.assertEqual( dl.get(rf_address='122b65', serial='123', name='foobar'), dev) self.assertIsNone( dl.get(rf_address='122b65', serial='123', name='foobar', blah='blubb')) self.assertIsNone(dl.get(rf_address='foo'))
def _parse(self): submessage_len, rf1, rf2, rf3, unknown, flags1, flags2 = struct.unpack( 'B3BBBB', self.data[:7]) # for row_num in range(0, len(self.data), 10): # row_bytes = self.data[row_num:row_num+10] # print("%s %s" % (str(row_num).ljust(2), ' '.join(["%02x" % x for x in row_bytes]))) # print(" %s" % ' '.join([chr(x) if 32 < x < 128 else ' ' for x in row_bytes])) self.rf_addr = RFAddr((rf1, rf2, rf3)) self.weekly_program = not (flags2 & 0x01 or flags2 & 0x02) self.manual_program = bool(flags2 & 0x01 and not flags2 & 0x02) self.vacation_program = bool(flags2 & 0x02 and not flags2 & 0x01) self.boost_program = bool(flags2 & 0x01 and flags2 & 0x02) self.dst_active = flags2 & 0x08 self.gateway_known = bool(flags2 & 0x05) self.panel_locked = bool(flags2 & 0x06) self.link_ok = bool(flags2 & 0x07) self.battery_low = bool(not (flags2 & 0x08)) self.status_initialized = bool(flags1 & 0x02) self.is_answer = bool(not (flags1 & 0x03)) self.is_error = bool(flags1 & 0x04) self.is_valid = bool(flags1 & 0x05) self.description = "%s: RF addr: %s, program: (weekly: %s, manual: %s, vacation: %s, boost_program: %s)" % ( self.__class__.__name__, self.rf_addr, self.weekly_program, self.manual_program, self.vacation_program, self.boost_program) self.description += ", gateway_known: %s, panel_locked: %s, link_ok: %s, battery_low: %s " % ( self.gateway_known, self.panel_locked, self.link_ok, self.battery_low) self.description += ", status_initialized: %s, is_answer: %s, is_error: %s, is_valid: %s " % ( self.status_initialized, self.is_answer, self.is_error, self.is_valid) # differ the devices, windowshutter is special. # state is coded in mode field: # open = auto/weekly program (00) # closed = vacation (10) if submessage_len == 12: self._parse_wall_mounted_thermostat(self.data) elif submessage_len == 11: self._parse_heater_thermostat(self.data)
def test_set_program_same_payload(self): c = self._mocked_cube() rfaddr = RFAddr('122b56') response1 = c.set_program(1, rfaddr, 1, []) setmessage1 = SetProgramMessage(rfaddr, 1, 1, []) payload1 = setmessage1.get_payload() c.send_message.assert_called_with(setmessage1) self.assertIsInstance(response1, SetResponse) response2 = c.set_program(1, '122b56', 1, []) setmessage2 = SetProgramMessage('122b56', 1, 1, []) payload2 = setmessage1.get_payload() c.send_message.assert_called_with(setmessage2) self.assertIsInstance(response2, SetResponse) self.assertEqual(payload1, payload2)
def _parse(self): parts = tuple(self.data.split(b',')) self.serial = parts[0].decode('utf-8') self.rf_address = RFAddr(parts[1].decode('utf-8')) self.fw_version = parts[2].decode('utf-8') # unknown = parts[3] self.http_connection_id = parts[4] self.duty_cycle = parts[5] self.free_mem_slots = parts[6] date = parts[7] time = parts[8] self.state_cube_time = parts[9] self.ntp_counter = parts[10] # 0f0c0c -> 2015-12-12 self.datetime = datetime.datetime( int(date[0:2].decode('utf-8'), 16) + 2000, int(date[2:4].decode('utf-8'), 16), int(date[4:6].decode('utf-8'), 16), int(time[0:2].decode('utf-8'), 16), int(time[2:4].decode('utf-8'), 16))
def test_repr(self): addr = RFAddr('122b65') self.assertEqual(str(addr), repr(addr))