async def test_process_position(self): """Test process / reading telegrams from telegram queue. Test if position is processed correctly.""" xknx = XKNX() cover = Cover( xknx, "TestCover", group_address_long="1/2/1", group_address_short="1/2/2", group_address_position="1/2/3", group_address_position_state="1/2/4", ) # initial position process - position is unknown so this is the new state - not moving telegram = Telegram(GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray(213))) await cover.process(telegram) assert cover.current_position() == 84 assert not cover.is_traveling() # state telegram updates current position - we are not moving so this is new state - not moving telegram = Telegram(GroupAddress("1/2/4"), payload=GroupValueWrite(DPTArray(42))) await cover.process(telegram) assert cover.current_position() == 16 assert not cover.is_traveling() assert cover.travelcalculator.travel_to_position == 16 # new position - movement starts telegram = Telegram(GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray(255))) await cover.process(telegram) assert cover.current_position() == 16 assert cover.is_closing() assert cover.travelcalculator.travel_to_position == 100 # new state while moving - movement goes on; travelcalculator updated telegram = Telegram(GroupAddress("1/2/4"), payload=GroupValueWrite(DPTArray(213))) await cover.process(telegram) assert cover.current_position() == 84 assert cover.is_closing() assert cover.travelcalculator.travel_to_position == 100
def test_payload_valid_preassigned_mode(self): """Test if setpoint_shift_mode is assigned properly by payload length.""" xknx = XKNX() remote_value_6 = RemoteValueSetpointShift( xknx=xknx, setpoint_shift_mode=SetpointShiftMode.DPT6010) remote_value_9 = RemoteValueSetpointShift( xknx=xknx, setpoint_shift_mode=SetpointShiftMode.DPT9002) dpt_6_payload = DPTArray(DPTValue1Count.to_knx(1)) dpt_9_payload = DPTArray(DPTTemperature.to_knx(1)) assert remote_value_6.dpt_class == DPTValue1Count assert remote_value_6.payload_valid(None) is None assert remote_value_6.payload_valid(dpt_9_payload) is None assert remote_value_6.payload_valid(DPTArray((1, 2, 3, 4))) is None assert remote_value_6.payload_valid(DPTBinary(1)) is None assert remote_value_6.payload_valid(dpt_6_payload) == dpt_6_payload assert remote_value_9.dpt_class == DPTTemperature assert remote_value_9.payload_valid(None) is None assert remote_value_9.payload_valid(dpt_6_payload) is None assert remote_value_9.payload_valid(DPTArray((1, 2, 3))) is None assert remote_value_9.payload_valid(DPTBinary(1)) is None assert remote_value_9.payload_valid(dpt_9_payload) == dpt_9_payload
async def test_set_percent(self): """Test set with percent numeric value.""" xknx = XKNX() num_value = NumericValue( xknx, "TestSensor", group_address="1/2/3", value_type="percent" ) await num_value.set(75) assert xknx.telegrams.qsize() == 1 telegram = xknx.telegrams.get_nowait() assert telegram == Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray((0xBF,))), )
async def test_process_wrong_payload(self): """Test process wrong telegram (wrong payload type).""" xknx = XKNX() binary_sensor = BinarySensor(xknx, "Warning", group_address_state="1/2/3") telegram = Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray((0x1, 0x2, 0x3))), ) with patch("logging.Logger.warning") as log_mock: await binary_sensor.process(telegram) log_mock.assert_called_once() assert binary_sensor.state is None
def test_process_invalid_payload(self): """Test if exception is raised when processing telegram with invalid payload.""" xknx = XKNX(loop=self.loop) remote_value = RemoteValue(xknx) with patch('xknx.remote_value.RemoteValue.payload_valid') as patch_valid, \ patch('xknx.remote_value.RemoteValue.has_group_address') as patch_has_group_address: patch_valid.return_value = False patch_has_group_address.return_value = True telegram = Telegram(GroupAddress('1/2/1'), payload=DPTArray((0x01, 0x02))) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete( asyncio.Task(remote_value.process(telegram)))
def test_payload_valid_mode_assignment(self): """Test if setpoint_shift_mode is assigned properly by payload length.""" xknx = XKNX() remote_value = RemoteValueSetpointShift(xknx=xknx) dpt_6_payload = DPTArray(DPTValue1Count.to_knx(1)) dpt_9_payload = DPTArray(DPTTemperature.to_knx(1)) assert remote_value.payload_valid(DPTBinary(0)) is None assert remote_value.payload_valid(DPTArray((0, 1, 2))) is None # DPT 6 - payload_length 1 assert remote_value.dpt_class is None assert remote_value.payload_valid(dpt_6_payload) == dpt_6_payload assert remote_value.dpt_class == SetpointShiftMode.DPT6010.value # DPT 9 is invalid now assert remote_value.payload_valid(dpt_9_payload) is None remote_value.dpt_class = None # DPT 9 - payload_length 2 assert remote_value.payload_valid(dpt_9_payload) == dpt_9_payload assert remote_value.dpt_class == SetpointShiftMode.DPT9002.value # DPT 6 is invalid now assert remote_value.payload_valid(dpt_6_payload) is None
async def test_to_process_error(self): """Test process errornous telegram.""" xknx = XKNX() remote_value = RemoteValueDpt2ByteUnsigned( xknx, group_address=GroupAddress("1/2/3")) with pytest.raises(CouldNotParseTelegram): telegram = Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTBinary(1)), ) await remote_value.process(telegram) with pytest.raises(CouldNotParseTelegram): telegram = Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray((0x64, ))), ) await remote_value.process(telegram) with pytest.raises(CouldNotParseTelegram): telegram = Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray((0x64, 0x53, 0x42))), ) await remote_value.process(telegram)
async def test_run(self): """Test running scene.""" xknx = XKNX() scene = Scene(xknx, "TestScene", group_address="1/2/1", scene_number=23) await scene.run() assert xknx.telegrams.qsize() == 1 telegram = xknx.telegrams.get_nowait() assert telegram == Telegram( destination_address=GroupAddress("1/2/1"), payload=GroupValueWrite(DPTArray(0x16)), )
def test_process_operation_mode(self): """Test process telegram.""" xknx = XKNX() remote_value = RemoteValueClimateMode( xknx, group_address=GroupAddress("1/2/3"), climate_mode_type=RemoteValueClimateMode.ClimateModeType.HVAC_MODE, ) telegram = Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray((0x00,))), ) self.loop.run_until_complete(remote_value.process(telegram)) self.assertEqual(remote_value.value, HVACOperationMode.AUTO)
def test_from_knx(self): """Test from_knx function with normal operation.""" xknx = XKNX(loop=self.loop) remote_value = RemoteValueColorRGBW(xknx) self.assertEqual( remote_value.from_knx( DPTArray((0x64, 0x65, 0x66, 0x7f, 0x00, 0x00))), [0, 0, 0, 0]) self.assertEqual( remote_value.from_knx( DPTArray((0x64, 0x65, 0x66, 0x7f, 0x00, 0x0f))), [100, 101, 102, 127]) self.assertEqual( remote_value.from_knx( DPTArray((0x64, 0x65, 0x66, 0x7f, 0x00, 0x00))), [100, 101, 102, 127]) self.assertEqual( remote_value.from_knx( DPTArray((0xff, 0x65, 0x66, 0xff, 0x00, 0x09))), [255, 101, 102, 255]) self.assertEqual( remote_value.from_knx( DPTArray((0x64, 0x65, 0x66, 0x7f, 0x00, 0x01))), [255, 101, 102, 127])
async def test_set_operation_mode(self): """Test setting value.""" xknx = XKNX() remote_value = RemoteValueOperationMode( xknx, group_address=GroupAddress("1/2/3"), climate_mode_type=RemoteValueOperationMode.ClimateModeType. HVAC_MODE, ) await remote_value.set(HVACOperationMode.NIGHT) assert xknx.telegrams.qsize() == 1 telegram = xknx.telegrams.get_nowait() assert telegram == Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray((0x03, ))), ) await remote_value.set(HVACOperationMode.FROST_PROTECTION) assert xknx.telegrams.qsize() == 1 telegram = xknx.telegrams.get_nowait() assert telegram == Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray((0x04, ))), )
async def test_set_temperature(self): """Test set with temperature sensor.""" xknx = XKNX() expose_sensor = ExposeSensor(xknx, "TestSensor", group_address="1/2/3", value_type="temperature") await expose_sensor.set(21.0) assert xknx.telegrams.qsize() == 1 telegram = xknx.telegrams.get_nowait() assert telegram == Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray((0x0C, 0x1A))), )
def test_process_angle(self): """Test process / reading telegrams from telegram queue. Test if position is processed correctly.""" xknx = XKNX() cover = Cover( xknx, "TestCover", group_address_long="1/2/1", group_address_short="1/2/2", group_address_angle="1/2/3", group_address_angle_state="1/2/4", ) telegram = Telegram(GroupAddress("1/2/4"), payload=DPTArray(42)) self.loop.run_until_complete(cover.process(telegram)) self.assertEqual(cover.current_angle(), 16)
async def service_send_to_knx_bus(self, call: ServiceCall) -> None: """Service for sending an arbitrary KNX message to the KNX bus.""" attr_address = call.data[KNX_ADDRESS] attr_payload = call.data[SERVICE_KNX_ATTR_PAYLOAD] attr_type = call.data.get(SERVICE_KNX_ATTR_TYPE) payload: DPTBinary | DPTArray if attr_type is not None: transcoder = DPTBase.parse_transcoder(attr_type) if transcoder is None: raise ValueError(f"Invalid type for knx.send service: {attr_type}") payload = DPTArray(transcoder.to_knx(attr_payload)) elif isinstance(attr_payload, int): payload = DPTBinary(attr_payload) else: payload = DPTArray(attr_payload) for address in attr_address: telegram = Telegram( destination_address=parse_device_group_address(address), payload=GroupValueWrite(payload), ) await self.xknx.telegrams.put(telegram)
def test_process_tunable_white(self): """Test process / reading telegrams from telegram queue. Test if tunable white is processed.""" xknx = XKNX() light = Light( xknx, name="TestLight", group_address_switch="1/2/3", group_address_tunable_white="1/2/5", ) self.assertEqual(light.current_tunable_white, None) telegram = Telegram(GroupAddress("1/2/5"), payload=DPTArray(23)) self.loop.run_until_complete(light.process(telegram)) self.assertEqual(light.current_tunable_white, 23)
def test_humidity(self): """Test humidity.""" xknx = XKNX(loop=self.loop) weather = Weather(name="weather", xknx=xknx, group_address_humidity="1/2/4") weather._humidity.payload = DPTArray(( 0x7E, 0xE1, )) self.assertEqual(weather.humidity, 577044.48) self.assertEqual(weather._humidity.unit_of_measurement, "%") self.assertEqual(weather._humidity.ha_device_class, "humidity")
def test_set_tw(self): """Test setting the tunable white value of a Light.""" xknx = XKNX() light = Light( xknx, name="TestLight", group_address_switch="1/2/3", group_address_tunable_white="1/2/5", ) self.loop.run_until_complete(light.set_tunable_white(23)) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() self.assertEqual(telegram, Telegram(GroupAddress("1/2/5"), payload=DPTArray(23)))
def test_process_color(self): """Test process / reading telegrams from telegram queue. Test if color is processed.""" xknx = XKNX() light = Light( xknx, name="TestLight", group_address_switch="1/2/3", group_address_color="1/2/5", ) self.assertEqual(light.current_color, (None, None)) telegram = Telegram(GroupAddress("1/2/5"), payload=DPTArray((23, 24, 25))) self.loop.run_until_complete(light.process(telegram)) self.assertEqual(light.current_color, ((23, 24, 25), None))
def test_position(self): """Test moving cover to absolute position.""" xknx = XKNX(loop=self.loop) cover = Cover(xknx, 'TestCover', group_address_long='1/2/1', group_address_short='1/2/2', group_address_position='1/2/3', group_address_position_state='1/2/4') self.loop.run_until_complete(asyncio.Task(cover.set_position(50))) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, Telegram(GroupAddress('1/2/3'), payload=DPTArray(0x80)))
def test_to_process_error_heat_cool(self): """Test process errornous telegram.""" xknx = XKNX() remote_value = RemoteValueBinaryHeatCool( xknx, group_address=GroupAddress("1/2/3"), controller_mode=HVACControllerMode.COOL, ) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray((0x01, ))), ) self.loop.run_until_complete(remote_value.process(telegram)) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray(( 0x64, 0x65, ))), ) self.loop.run_until_complete(remote_value.process(telegram))
def test_to_process_error(self): """Test process errornous telegram.""" xknx = XKNX(loop=self.loop) remote_value = RemoteValueDpt2ByteUnsigned( xknx, group_address=GroupAddress("1/2/3")) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram(group_address=GroupAddress("1/2/3"), payload=DPTBinary(1)) self.loop.run_until_complete(remote_value.process(telegram)) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram(group_address=GroupAddress("1/2/3"), payload=DPTArray((0x64, ))) self.loop.run_until_complete(remote_value.process(telegram)) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( group_address=GroupAddress("1/2/3"), payload=DPTArray(( 0x64, 0x53, 0x42, )), ) self.loop.run_until_complete(remote_value.process(telegram))
def test_process(self): """Test if telegram is handled by the correct process_* method.""" xknx = XKNX(loop=self.loop) device = Device(xknx, 'TestDevice') with patch('xknx.devices.Device.process_group_read') as mock_group_read: fut = asyncio.Future() fut.set_result(None) mock_group_read.return_value = fut telegram = Telegram( GroupAddress('1/2/1'), payload=DPTArray((0x01, 0x02)), telegramtype=TelegramType.GROUP_READ) self.loop.run_until_complete(asyncio.Task(device.process(telegram))) mock_group_read.assert_called_with(telegram) with patch('xknx.devices.Device.process_group_write') as mock_group_write: fut = asyncio.Future() fut.set_result(None) mock_group_write.return_value = fut telegram = Telegram( GroupAddress('1/2/1'), payload=DPTArray((0x01, 0x02)), telegramtype=TelegramType.GROUP_WRITE) self.loop.run_until_complete(asyncio.Task(device.process(telegram))) mock_group_write.assert_called_with(telegram) with patch('xknx.devices.Device.process_group_response') as mock_group_response: fut = asyncio.Future() fut.set_result(None) mock_group_response.return_value = fut telegram = Telegram( GroupAddress('1/2/1'), payload=DPTArray((0x01, 0x02)), telegramtype=TelegramType.GROUP_RESPONSE) self.loop.run_until_complete(asyncio.Task(device.process(telegram))) mock_group_response.assert_called_with(telegram)
def test_wind_speed(self): """Test wind speed received.""" xknx = XKNX(loop=self.loop) weather: Weather = Weather(name="weather", xknx=xknx, group_address_brightness_east="1/3/8") weather._wind_speed.payload = DPTArray(( 0x7D, 0x98, )) self.assertEqual(weather.wind_speed, 469237.76) self.assertEqual(weather._wind_speed.unit_of_measurement, "m/s") self.assertEqual(weather._wind_speed.ha_device_class, None)
def test_set_temperature(self): """Test set with temperature sensor.""" xknx = XKNX(loop=self.loop) expose_sensor = ExposeSensor(xknx, 'TestSensor', group_address='1/2/3', value_type="temperature") self.loop.run_until_complete(asyncio.Task(expose_sensor.set(21.0))) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, Telegram(GroupAddress('1/2/3'), TelegramType.GROUP_WRITE, payload=DPTArray((0x0c, 0x1a))))
async def test_process_angle(self): """Test process / reading telegrams from telegram queue. Test if position is processed correctly.""" xknx = XKNX() cover = Cover( xknx, "TestCover", group_address_long="1/2/1", group_address_short="1/2/2", group_address_angle="1/2/3", group_address_angle_state="1/2/4", ) telegram = Telegram(GroupAddress("1/2/4"), payload=GroupValueWrite(DPTArray(42))) await cover.process(telegram) assert cover.current_angle() == 16
def test_to_process_error(self): """Test process errornous telegram.""" xknx = XKNX() remote_value = RemoteValueStep(xknx, group_address=GroupAddress("1/2/3")) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram(group_address=GroupAddress("1/2/3"), payload=DPTArray(0x01)) self.loop.run_until_complete(remote_value.process(telegram)) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram(group_address=GroupAddress("1/2/3"), payload=DPTBinary(3)) self.loop.run_until_complete(remote_value.process(telegram)) # pylint: disable=pointless-statement remote_value.value
async def test_process_callback(self): """Test process / reading telegrams from telegram queue. Test if callback was called.""" xknx = XKNX() notification = Notification(xknx, "Warning", group_address="1/2/3") after_update_callback = AsyncMock() notification.register_device_updated_cb(after_update_callback) telegram_set = Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray( DPTString().to_knx("Ein Prosit!"))), ) await notification.process(telegram_set) after_update_callback.assert_called_with(notification)
def test_set_speed(self): """Test setting the speed of a Fan.""" xknx = XKNX() fan = Fan(xknx, name="TestFan", group_address_speed="1/2/3") self.loop.run_until_complete(fan.set_speed(55)) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() # 140 is 55% as byte (0...255) self.assertEqual( telegram, Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray(140)), ), )
def test_to_process_error(self): """Test process errornous telegram.""" xknx = XKNX() remote_value = RemoteValueColorRGBW( xknx, group_address=GroupAddress("1/2/3")) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete(remote_value.process(telegram)) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray((0x64, 0x65, 0x66))), ) self.loop.run_until_complete(remote_value.process(telegram)) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite( DPTArray((0x00, 0x00, 0x0F, 0x64, 0x65, 0x66, 0x67))), ) self.loop.run_until_complete(remote_value.process(telegram))
def test_process(self): """Test if telegram is handled by the correct process_* method.""" xknx = XKNX() device = Device(xknx, "TestDevice") with patch("xknx.devices.Device.process_group_read") as mock_group_read: fut = asyncio.Future() fut.set_result(None) mock_group_read.return_value = fut telegram = Telegram( destination_address=GroupAddress("1/2/1"), payload=GroupValueRead() ) self.loop.run_until_complete(device.process(telegram)) mock_group_read.assert_called_with(telegram) with patch("xknx.devices.Device.process_group_write") as mock_group_write: fut = asyncio.Future() fut.set_result(None) mock_group_write.return_value = fut telegram = Telegram( destination_address=GroupAddress("1/2/1"), payload=GroupValueWrite(DPTArray((0x01, 0x02))), ) self.loop.run_until_complete(device.process(telegram)) mock_group_write.assert_called_with(telegram) with patch("xknx.devices.Device.process_group_response") as mock_group_response: fut = asyncio.Future() fut.set_result(None) mock_group_response.return_value = fut telegram = Telegram( destination_address=GroupAddress("1/2/1"), payload=GroupValueResponse(DPTArray((0x01, 0x02))), ) self.loop.run_until_complete(device.process(telegram)) mock_group_response.assert_called_with(telegram)