def test_sync_operation_mode_state(self): """Test sync function / sending group reads to KNX bus for multiple mode addresses.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode( xknx, 'TestClimate', group_address_operation_mode='1/2/3', group_address_operation_mode_state='1/2/5', group_address_controller_status='1/2/4', group_address_controller_status_state='1/2/6', group_address_controller_mode='1/2/13', group_address_controller_mode_state='1/2/14') self.loop.run_until_complete(asyncio.Task(climate_mode.sync(False))) self.assertEqual(xknx.telegrams.qsize(), 3) telegram1 = xknx.telegrams.get_nowait() self.assertEqual( telegram1, Telegram(GroupAddress('1/2/5'), TelegramType.GROUP_READ)) telegram2 = xknx.telegrams.get_nowait() self.assertEqual( telegram2, Telegram(GroupAddress('1/2/6'), TelegramType.GROUP_READ)) telegram3 = xknx.telegrams.get_nowait() self.assertEqual( telegram3, Telegram(GroupAddress('1/2/14'), TelegramType.GROUP_READ))
def test_set_operation_mode_with_separate_addresses(self): """Test set_operation_mode with combined and separated group adddresses defined.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode( xknx, 'TestClimate', group_address_operation_mode='1/2/4', group_address_operation_mode_protection='1/2/5', group_address_operation_mode_night='1/2/6', group_address_operation_mode_comfort='1/2/7') self.loop.run_until_complete( asyncio.Task( climate_mode.set_operation_mode(HVACOperationMode.COMFORT))) self.assertEqual(xknx.telegrams.qsize(), 4) telegram = xknx.telegrams.get_nowait() self.assertEqual(telegram, Telegram(GroupAddress('1/2/4'), payload=DPTArray(1))) telegram = xknx.telegrams.get_nowait() self.assertEqual(telegram, Telegram(GroupAddress('1/2/5'), payload=DPTBinary(0))) telegram = xknx.telegrams.get_nowait() self.assertEqual(telegram, Telegram(GroupAddress('1/2/6'), payload=DPTBinary(0))) telegram = xknx.telegrams.get_nowait() self.assertEqual(telegram, Telegram(GroupAddress('1/2/7'), payload=DPTBinary(1)))
def test_set_operation_mode_not_supported(self): """Test set_operation_mode but not supported.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode( xknx, 'TestClimate') with self.assertRaises(DeviceIllegalValue): self.loop.run_until_complete(asyncio.Task(climate_mode.set_operation_mode(HVACOperationMode.AUTO)))
def test_set_operation_mode_not_supported(self): """Test set_operation_mode but not supported.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode(xknx, 'TestClimate') with self.assertRaises(DeviceIllegalValue): self.loop.run_until_complete( asyncio.Task( climate_mode.set_operation_mode(HVACOperationMode.AUTO)))
def test_process_controller_status_wrong_payload(self): """Test process wrong telegram for controller status (wrong payload type).""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode(xknx, 'TestClimate', group_address_operation_mode='1/2/5', group_address_controller_status='1/2/3') telegram = Telegram(GroupAddress('1/2/3'), payload=DPTBinary(1)) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete( asyncio.Task(climate_mode.process(telegram)))
def test_process_controller_status_wrong_payload(self): """Test process wrong telegram for controller status (wrong payload type).""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode( xknx, 'TestClimate', group_address_operation_mode='1/2/5', group_address_controller_status='1/2/3') telegram = Telegram(GroupAddress('1/2/3'), payload=DPTBinary(1)) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(asyncio.Task(climate_mode.process(telegram)))
def test_process_operation_mode_payload_invalid_length(self): """Test process wrong telegram for operation mode (wrong payload length).""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode( xknx, 'TestClimate', group_address_operation_mode='1/2/5', group_address_controller_status='1/2/3') telegram = Telegram(GroupAddress('1/2/5'), payload=DPTArray((23, 24))) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(asyncio.Task(climate_mode.process(telegram)))
def test_process_operation_mode_payload_invalid_length(self): """Test process wrong telegram for operation mode (wrong payload length).""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode(xknx, 'TestClimate', group_address_operation_mode='1/2/5', group_address_controller_status='1/2/3') telegram = Telegram(GroupAddress('1/2/5'), payload=DPTArray((23, 24))) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete( asyncio.Task(climate_mode.process(telegram)))
def test_process_controller_mode(self): """Test process / reading telegrams from telegram queue. Test if DPT20.105 controller mode is set correctly.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode( xknx, 'TestClimate', group_address_controller_mode='1/2/5') for _, operation_mode in DPTHVACContrMode.SUPPORTED_MODES.items(): telegram = Telegram(GroupAddress('1/2/5')) telegram.payload = DPTArray(DPTHVACContrMode.to_knx(operation_mode)) self.loop.run_until_complete(asyncio.Task(climate_mode.process(telegram))) self.assertEqual(climate_mode.operation_mode, operation_mode)
def test_process_controller_mode(self): """Test process / reading telegrams from telegram queue. Test if DPT20.105 controller mode is set correctly.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode(xknx, 'TestClimate', group_address_controller_mode='1/2/5') for _, operation_mode in DPTHVACContrMode.SUPPORTED_MODES.items(): telegram = Telegram(GroupAddress('1/2/5')) telegram.payload = DPTArray( DPTHVACContrMode.to_knx(operation_mode)) self.loop.run_until_complete( asyncio.Task(climate_mode.process(telegram))) self.assertEqual(climate_mode.operation_mode, operation_mode)
def test_state_addresses(self): """Test state_addresses of Climate and ClimateMode.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode( xknx, name=None, group_address_operation_mode='1/2/5', group_address_operation_mode_state='1/2/13', group_address_operation_mode_protection='1/2/6', group_address_operation_mode_night='1/2/7', group_address_operation_mode_comfort='1/2/8', group_address_controller_mode='1/2/9', group_address_controller_mode_state='1/2/10') climate = Climate(xknx, 'TestClimate', group_address_temperature='1/2/1', group_address_target_temperature='1/2/2', group_address_setpoint_shift='1/2/3', group_address_setpoint_shift_state='1/2/4', group_address_on_off='1/2/11', group_address_on_off_state='1/2/12', mode=climate_mode) self.assertEqual(climate.state_addresses(), [ GroupAddress("1/2/1"), GroupAddress("1/2/4"), GroupAddress("1/2/12"), GroupAddress("1/2/13"), GroupAddress("1/2/10") ])
def test_set_operation_mode(self): """Test set_operation_mode.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode(xknx, 'TestClimate', group_address_operation_mode='1/2/4') for operation_mode in DPT_20102_MODES: self.loop.run_until_complete( asyncio.Task(climate_mode.set_operation_mode(operation_mode))) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, Telegram(GroupAddress('1/2/4'), payload=DPTArray(DPTHVACMode.to_knx(operation_mode))))
def test_support_operation_mode(self): """Test supports_supports_operation_mode flag. One group address for all modes.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode(xknx, 'TestClimate', group_address_operation_mode='1/2/4') self.assertTrue(climate_mode.supports_operation_mode)
def test_config_climate_operation_mode(self): """Test reading Climate object with operation mode in one group address from config file.""" self.assertEqual( TestConfig.xknx.devices["Office.Climate"].mode, ClimateMode(TestConfig.xknx, name=None, group_address_operation_mode="1/7/6"), )
def test_supported_operation_modes_only_night(self): """Test get_supported_operation_modes with only night mode supported.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode(xknx, 'TestClimate', group_address_operation_mode_night='1/2/7') self.assertEqual(climate_mode.operation_modes, [HVACOperationMode.STANDBY, HVACOperationMode.NIGHT])
def test_set_operation_mode(self): """Test set_operation_mode.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode( xknx, 'TestClimate', group_address_operation_mode='1/2/4') for operation_mode in DPT_20102_MODES: self.loop.run_until_complete(asyncio.Task(climate_mode.set_operation_mode(operation_mode))) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, Telegram( GroupAddress('1/2/4'), payload=DPTArray(DPTHVACMode.to_knx(operation_mode))))
def test_support_operation_mode2(self): """Test supports_supports_operation_mode flag. Splitted group addresses for each mode.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode( xknx, 'TestClimate', group_address_operation_mode_protection='1/2/4') self.assertTrue(climate_mode.supports_operation_mode)
def test_set_controller_operation_mode(self): """Test set_operation_mode with DPT20.105 controller.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode( xknx, 'TestClimate', group_address_controller_mode='1/2/4') for _, operation_mode in DPTHVACContrMode.SUPPORTED_MODES.items(): self.loop.run_until_complete(asyncio.Task(climate_mode.set_operation_mode(operation_mode))) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, Telegram( GroupAddress('1/2/4'), payload=DPTArray(DPTHVACContrMode.to_knx(operation_mode))))
def test_set_controller_operation_mode(self): """Test set_operation_mode with DPT20.105 controller.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode(xknx, 'TestClimate', group_address_controller_mode='1/2/4') for _, operation_mode in DPTHVACContrMode.SUPPORTED_MODES.items(): self.loop.run_until_complete( asyncio.Task(climate_mode.set_operation_mode(operation_mode))) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, Telegram(GroupAddress('1/2/4'), payload=DPTArray( DPTHVACContrMode.to_knx(operation_mode))))
def test_process_callback_mode(self): """Test if after_update_callback is called after update of Climate object was changed.""" # pylint: disable=no-self-use xknx = XKNX(loop=self.loop) climate_mode = ClimateMode(xknx, 'TestClimate', group_address_operation_mode='1/2/5') after_update_callback = Mock() async def async_after_update_callback(device): """Async callback.""" after_update_callback(device) climate_mode.register_device_updated_cb(async_after_update_callback) self.loop.run_until_complete( asyncio.Task( climate_mode.set_operation_mode(HVACOperationMode.COMFORT))) after_update_callback.assert_called_with(climate_mode) after_update_callback.reset_mock() self.loop.run_until_complete( asyncio.Task( climate_mode.set_operation_mode(HVACOperationMode.COMFORT))) after_update_callback.assert_not_called() after_update_callback.reset_mock() self.loop.run_until_complete( asyncio.Task( climate_mode.set_operation_mode( HVACOperationMode.FROST_PROTECTION))) after_update_callback.assert_called_with(climate_mode) after_update_callback.reset_mock()
def test_custom_supported_operation_modes(self): """Test get_supported_operation_modes with custom mode.""" modes = [HVACOperationMode.STANDBY, HVACOperationMode.NIGHT] xknx = XKNX(loop=self.loop) climate_mode = ClimateMode(xknx, 'TestClimate', group_address_operation_mode='1/2/7', operation_modes=modes) self.assertEqual(climate_mode.operation_modes, modes)
def test_config_climate_controller_status_state(self): """Test reading Climate object with addresses for controller status.""" self.assertEqual( TestConfig.xknx.devices['Cellar.Climate'].mode, ClimateMode(TestConfig.xknx, name=None, group_address_controller_status='1/7/12', group_address_controller_status_state='1/7/13', device_updated_cb=TestConfig.xknx.devices.device_updated))
def test_config_climate_operation_mode_state(self): """Test reading Climate object with status address for operation mode.""" self.assertEqual( TestConfig.xknx.devices['Bath.Climate'].mode, ClimateMode(TestConfig.xknx, name=None, group_address_operation_mode='1/7/6', group_address_operation_mode_state='1/7/7', device_updated_cb=TestConfig.xknx.devices.device_updated))
def test_sync_operation_mode(self): """Test sync function / sending group reads to KNX bus for operation mode.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode( xknx, 'TestClimate', group_address_operation_mode='1/2/3', group_address_controller_status='1/2/4') self.loop.run_until_complete(asyncio.Task(climate_mode.sync(False))) self.assertEqual(xknx.telegrams.qsize(), 2) telegram1 = xknx.telegrams.get_nowait() self.assertEqual( telegram1, Telegram(GroupAddress('1/2/3'), TelegramType.GROUP_READ)) telegram2 = xknx.telegrams.get_nowait() self.assertEqual( telegram2, Telegram(GroupAddress('1/2/4'), TelegramType.GROUP_READ))
def test_config_climate_operation_mode(self): """Test reading Climate object with operation mode in one group address from config file.""" xknx = XKNX(config='xknx.yaml', loop=self.loop) self.assertEqual( xknx.devices['Office.Climate'].mode, ClimateMode(xknx, name=None, group_address_operation_mode='1/7/6', device_updated_cb=xknx.devices.device_updated))
def test_config_climate_operation_mode2(self): """Test reading Climate object with operation mode in different group addresses from config file.""" self.assertEqual( TestConfig.xknx.devices['Attic.Climate'].mode, ClimateMode(TestConfig.xknx, name=None, group_address_operation_mode_protection='1/7/8', group_address_operation_mode_night='1/7/9', group_address_operation_mode_comfort='1/7/10', device_updated_cb=TestConfig.xknx.devices.device_updated))
def test_set_operation_mode_with_controller_status(self): """Test set_operation_mode with controller status adddressedefined.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode(xknx, 'TestClimate', group_address_controller_status='1/2/4') for operation_mode in DPT_20102_MODES: if operation_mode == HVACOperationMode.AUTO: continue self.loop.run_until_complete( asyncio.Task(climate_mode.set_operation_mode(operation_mode))) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, Telegram(GroupAddress('1/2/4'), payload=DPTArray( DPTControllerStatus.to_knx(operation_mode))))
def test_set_operation_mode_with_controller_status(self): """Test set_operation_mode with controller status adddressedefined.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode( xknx, 'TestClimate', group_address_controller_status='1/2/4') for operation_mode in DPT_20102_MODES: if operation_mode == HVACOperationMode.AUTO: continue self.loop.run_until_complete(asyncio.Task(climate_mode.set_operation_mode(operation_mode))) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, Telegram( GroupAddress('1/2/4'), payload=DPTArray(DPTControllerStatus.to_knx(operation_mode))))
def test_config_climate_controller_status_state(self): """Test reading Climate object with addresses for controller status.""" xknx = XKNX(config='xknx.yaml', loop=self.loop) self.assertEqual( xknx.devices['Cellar.Climate'].mode, ClimateMode(xknx, name=None, group_address_controller_status='1/7/12', group_address_controller_status_state='1/7/13', device_updated_cb=xknx.devices.device_updated))
def test_config_climate_operation_mode_state(self): """Test reading Climate object with status address for operation mode.""" xknx = XKNX(config='xknx.yaml', loop=self.loop) self.assertEqual( xknx.devices['Bath.Climate'].mode, ClimateMode(xknx, name=None, group_address_operation_mode='1/7/6', group_address_operation_mode_state='1/7/7', device_updated_cb=xknx.devices.device_updated))
def test_custom_supported_operation_modes_as_str(self): """Test get_supported_operation_modes with custom mode as str list.""" str_modes = ['STANDBY', 'FROST_PROTECTION'] modes = [HVACOperationMode.STANDBY, HVACOperationMode.FROST_PROTECTION] xknx = XKNX(loop=self.loop) climate_mode = ClimateMode(xknx, 'TestClimate', group_address_operation_mode='1/2/7', operation_modes=str_modes) self.assertEqual(climate_mode.operation_modes, modes)
def test_supported_operation_modes_controller_status(self): """Test get_supported_operation_modes with combined group address.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode(xknx, 'TestClimate', group_address_controller_status='1/2/5') self.assertEqual(climate_mode.operation_modes, [ HVACOperationMode.COMFORT, HVACOperationMode.STANDBY, HVACOperationMode.NIGHT, HVACOperationMode.FROST_PROTECTION ])
def test_config_climate_controller_status_state(self): """Test reading Climate object with addresses for controller status.""" self.assertEqual( TestConfig.xknx.devices["Cellar.Climate"].mode, ClimateMode( TestConfig.xknx, name="Cellar.Climate_mode", group_address_controller_status="1/7/12", group_address_controller_status_state="1/7/13", ), )
def test_process_operation_mode(self): """Test process / reading telegrams from telegram queue. Test if setpoint is processed correctly.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode( xknx, 'TestClimate', group_address_operation_mode='1/2/5', group_address_controller_status='1/2/3') for operation_mode in DPT_20102_MODES: telegram = Telegram(GroupAddress('1/2/5')) telegram.payload = DPTArray(DPTHVACMode.to_knx(operation_mode)) self.loop.run_until_complete(asyncio.Task(climate_mode.process(telegram))) self.assertEqual(climate_mode.operation_mode, operation_mode) for operation_mode in DPT_20102_MODES: if operation_mode == HVACOperationMode.AUTO: continue telegram = Telegram(GroupAddress('1/2/3')) telegram.payload = DPTArray(DPTControllerStatus.to_knx(operation_mode)) self.loop.run_until_complete(asyncio.Task(climate_mode.process(telegram))) self.assertEqual(climate_mode.operation_mode, operation_mode)
def test_config_climate_operation_mode_state(self): """Test reading Climate object with status address for operation mode.""" self.assertEqual( TestConfig.xknx.devices["Bath.Climate"].mode, ClimateMode( TestConfig.xknx, name="Bath.Climate_mode", group_address_operation_mode="1/7/6", group_address_operation_mode_state="1/7/7", ), )
def test_config_climate_operation_mode2(self): """Test reading Climate object with operation mode in different group addresses from config file.""" self.assertEqual( TestConfig.xknx.devices["Attic.Climate"].mode, ClimateMode( TestConfig.xknx, name="Attic.Climate_mode", group_address_operation_mode_protection="1/7/8", group_address_operation_mode_night="1/7/9", group_address_operation_mode_comfort="1/7/10", ), )
def test_process_callback_mode(self): """Test if after_update_callback is called after update of Climate object was changed.""" # pylint: disable=no-self-use xknx = XKNX(loop=self.loop) climate_mode = ClimateMode( xknx, 'TestClimate', group_address_operation_mode='1/2/5') after_update_callback = Mock() async def async_after_update_callback(device): """Async callback.""" after_update_callback(device) climate_mode.register_device_updated_cb(async_after_update_callback) self.loop.run_until_complete(asyncio.Task( climate_mode.set_operation_mode(HVACOperationMode.COMFORT))) after_update_callback.assert_called_with(climate_mode) after_update_callback.reset_mock() self.loop.run_until_complete(asyncio.Task( climate_mode.set_operation_mode(HVACOperationMode.COMFORT))) after_update_callback.assert_not_called() after_update_callback.reset_mock() self.loop.run_until_complete(asyncio.Task( climate_mode.set_operation_mode(HVACOperationMode.FROST_PROTECTION))) after_update_callback.assert_called_with(climate_mode) after_update_callback.reset_mock()
def test_supported_operation_modes_with_separate_addresses(self): """Test get_supported_operation_modes with separated group addresses.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode( xknx, 'TestClimate', group_address_operation_mode_protection='1/2/5', group_address_operation_mode_night='1/2/6', group_address_operation_mode_comfort='1/2/7') self.assertEqual(climate_mode.operation_modes, [ HVACOperationMode.COMFORT, HVACOperationMode.STANDBY, HVACOperationMode.NIGHT, HVACOperationMode.FROST_PROTECTION ])
def test_process_operation_mode(self): """Test process / reading telegrams from telegram queue. Test if setpoint is processed correctly.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode(xknx, 'TestClimate', group_address_operation_mode='1/2/5', group_address_controller_status='1/2/3') for operation_mode in DPT_20102_MODES: telegram = Telegram(GroupAddress('1/2/5')) telegram.payload = DPTArray(DPTHVACMode.to_knx(operation_mode)) self.loop.run_until_complete( asyncio.Task(climate_mode.process(telegram))) self.assertEqual(climate_mode.operation_mode, operation_mode) for operation_mode in DPT_20102_MODES: if operation_mode == HVACOperationMode.AUTO: continue telegram = Telegram(GroupAddress('1/2/3')) telegram.payload = DPTArray( DPTControllerStatus.to_knx(operation_mode)) self.loop.run_until_complete( asyncio.Task(climate_mode.process(telegram))) self.assertEqual(climate_mode.operation_mode, operation_mode)
def test_set_operation_mode_with_separate_addresses(self): """Test set_operation_mode with combined and separated group adddresses defined.""" xknx = XKNX(loop=self.loop) climate_mode = ClimateMode( xknx, 'TestClimate', group_address_operation_mode='1/2/4', group_address_operation_mode_protection='1/2/5', group_address_operation_mode_night='1/2/6', group_address_operation_mode_comfort='1/2/7') self.loop.run_until_complete(asyncio.Task(climate_mode.set_operation_mode(HVACOperationMode.COMFORT))) self.assertEqual(xknx.telegrams.qsize(), 4) telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, Telegram( GroupAddress('1/2/4'), payload=DPTArray(1))) telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, Telegram( GroupAddress('1/2/5'), payload=DPTBinary(0))) telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, Telegram( GroupAddress('1/2/6'), payload=DPTBinary(0))) telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, Telegram( GroupAddress('1/2/7'), payload=DPTBinary(1)))
def test_climate_mode_process_callback_updated_via_telegram(self): """Test if after_update_callback is called after update of ClimateMode object.""" # pylint: disable=no-self-use xknx = XKNX(loop=self.loop) climate_mode = ClimateMode( xknx, 'TestClimateMode', group_address_operation_mode='1/2/4') after_update_callback = Mock() climate = Climate(xknx, 'TestClimate', mode=climate_mode) async def async_after_update_callback(device): """Async callback.""" after_update_callback(device) climate_mode.register_device_updated_cb(async_after_update_callback) # Note: the climate object processes the telegram, but the cb # is called with the climate_mode object. telegram = Telegram(GroupAddress('1/2/4'), payload=DPTArray(1)) self.loop.run_until_complete(asyncio.Task(climate.process(telegram))) after_update_callback.assert_called_with(climate_mode) after_update_callback.reset_mock()
def test_climate_mode_process_callback_updated_via_telegram(self): """Test if after_update_callback is called after update of ClimateMode object.""" # pylint: disable=no-self-use xknx = XKNX(loop=self.loop) climate_mode = ClimateMode(xknx, 'TestClimateMode', group_address_operation_mode='1/2/4') after_update_callback = Mock() climate = Climate(xknx, 'TestClimate', mode=climate_mode) async def async_after_update_callback(device): """Async callback.""" after_update_callback(device) climate_mode.register_device_updated_cb(async_after_update_callback) # Note: the climate object processes the telegram, but the cb # is called with the climate_mode object. telegram = Telegram(GroupAddress('1/2/4'), payload=DPTArray(1)) self.loop.run_until_complete(asyncio.Task(climate.process(telegram))) after_update_callback.assert_called_with(climate_mode) after_update_callback.reset_mock()