Beispiel #1
0
    async def test_callback_group_addresses(self):
        """Test telegram_received_callback after state of switch was changed."""
        xknx = XKNX()
        async_telegram_received_cb_one = AsyncMock()
        async_telegram_received_cb_two = AsyncMock()

        callback_one = xknx.telegram_queue.register_telegram_received_cb(
            async_telegram_received_cb_one,
            address_filters=[],
            group_addresses=[GroupAddress("1/2/3")],
        )
        callback_two = xknx.telegram_queue.register_telegram_received_cb(
            async_telegram_received_cb_two,
            address_filters=[],
            group_addresses=[])

        telegram = Telegram(
            destination_address=GroupAddress("1/2/3"),
            direction=TelegramDirection.INCOMING,
            payload=GroupValueWrite(DPTBinary(1)),
        )
        await xknx.telegram_queue.process_telegram_incoming(telegram)
        async_telegram_received_cb_one.assert_called_once_with(telegram)
        async_telegram_received_cb_two.assert_not_called()

        async_telegram_received_cb_one.reset_mock()
        # modify the filters - add/remove a GroupAddress
        callback_one.group_addresses.remove(GroupAddress("1/2/3"))
        callback_two.group_addresses.append(GroupAddress("1/2/3"))
        await xknx.telegram_queue.process_telegram_incoming(telegram)
        async_telegram_received_cb_one.assert_not_called()
        async_telegram_received_cb_two.assert_called_once_with(telegram)
    async def test_array_sensor_loop(self, value_type, test_payload, test_value):
        """Test sensor and expose_sensor with different values."""
        xknx = XKNX()
        xknx.knxip_interface = AsyncMock()
        xknx.rate_limit = False
        await xknx.telegram_queue.start()

        expose = ExposeSensor(
            xknx,
            "TestExpose",
            group_address="1/1/1",
            value_type=value_type,
        )
        assert expose.resolve_state() is None
        # set a value from expose - HA sends strings for new values
        stringified_value = str(test_value)
        await expose.set(stringified_value)

        outgoing_telegram = Telegram(
            destination_address=GroupAddress("1/1/1"),
            direction=TelegramDirection.OUTGOING,
            payload=GroupValueWrite(test_payload),
        )
        await xknx.telegrams.join()
        xknx.knxip_interface.send_telegram.assert_called_with(outgoing_telegram)
        assert expose.resolve_state() == test_value

        # init sensor after expose is set - with same group address
        sensor = Sensor(
            xknx,
            "TestSensor",
            group_address_state="1/1/1",
            value_type=value_type,
        )
        assert sensor.resolve_state() is None

        # read sensor state (from expose as it has the same GA)
        # wait_for_result so we don't have to await self.xknx.telegrams.join()
        await sensor.sync(wait_for_result=True)
        read_telegram = Telegram(
            destination_address=GroupAddress("1/1/1"),
            direction=TelegramDirection.OUTGOING,
            payload=GroupValueRead(),
        )
        response_telegram = Telegram(
            destination_address=GroupAddress("1/1/1"),
            direction=TelegramDirection.OUTGOING,
            payload=GroupValueResponse(test_payload),
        )
        xknx.knxip_interface.send_telegram.assert_has_calls(
            [
                call(read_telegram),
                call(response_telegram),
            ]
        )
        # test if Sensor has successfully read from ExposeSensor
        assert sensor.resolve_state() == test_value
        assert expose.resolve_state() == sensor.resolve_state()
        await xknx.telegram_queue.stop()
Beispiel #3
0
 def test_representation(self):
     """Test string representation of address."""
     assert repr(GroupAddress("0",
                              GroupAddressType.FREE)) == 'GroupAddress("0")'
     assert repr(GroupAddress(
         "0", GroupAddressType.SHORT)) == 'GroupAddress("0/0")'
     assert repr(GroupAddress(
         "0", GroupAddressType.LONG)) == 'GroupAddress("0/0/0")'
Beispiel #4
0
 def test_equal(self):
     """Test if the equal operator works in all cases."""
     assert IndividualAddress("1.0.0") == IndividualAddress(4096)
     assert IndividualAddress("1.0.0") != IndividualAddress("1.1.1")
     assert IndividualAddress("1.0.0") is not None
     assert IndividualAddress("1.0.0") != "example"
     assert IndividualAddress("1.1.1") != GroupAddress("1/1/1")
     assert IndividualAddress(250) != GroupAddress(250)
     assert IndividualAddress(250) != 250
Beispiel #5
0
    def test_middle(self):
        """
        Test if `GroupAddress.middle` works.

        Checks:
        * Middle group part of a strings returns the right value
        * Return `None` if not `GroupAddressType.LONG`
        """
        assert GroupAddress("1/0/1", GroupAddressType.LONG).middle == 0
        assert GroupAddress("1/7/1", GroupAddressType.LONG).middle == 7
        assert GroupAddress("1/0", GroupAddressType.SHORT).middle is None
        assert GroupAddress("1/0", GroupAddressType.FREE).middle is None
Beispiel #6
0
    def test_main(self):
        """
        Test if `GroupAddress.main` works.

        Checks:
        * Main group part of a strings returns the right value
        * Return `None` on `GroupAddressType.FREE`
        """
        assert GroupAddress("1/0").main == 1
        assert GroupAddress("15/0").main == 15
        assert GroupAddress("31/0/0").main == 31
        assert GroupAddress("1/0", GroupAddressType.FREE).main is None
Beispiel #7
0
    def test_internal_address_filter_wildcard(self):
        """Test AddressFilter with wildcards for InternalGroupAddress."""
        af1 = AddressFilter("i-?")
        assert af1.match("i1")
        assert af1.match("i 2")
        assert af1.match("i-3")
        assert af1.match(InternalGroupAddress("i-4"))
        assert not af1.match("1")
        assert not af1.match(GroupAddress(1))
        assert not af1.match("i11")
        assert not af1.match("i 11")
        assert not af1.match("i-11")
        assert not af1.match(InternalGroupAddress("i-11"))

        af2 = AddressFilter("i-t?st")
        assert af2.match("it1st")
        assert af2.match("i t2st")
        assert af2.match("i-test")
        assert af2.match(InternalGroupAddress("i-test"))
        assert not af2.match("1")
        assert not af2.match(GroupAddress(1))
        assert not af2.match("i11")
        assert not af2.match("i tst")
        assert not af2.match("i-teest")
        assert not af2.match(InternalGroupAddress("i-tst"))

        af3 = AddressFilter("i-*")
        assert af3.match("i1")
        assert af3.match("i asdf")
        assert af3.match("i-3sdf")
        assert af3.match(InternalGroupAddress("i-4"))
        assert not af3.match("1")
        assert not af3.match(GroupAddress(1))
        assert af3.match("i11")
        assert af3.match("i 11??")
        assert af3.match("i-11*")
        assert af3.match(InternalGroupAddress("i-11"))

        af4 = AddressFilter("i-t*t")
        assert af4.match("it1t")
        assert af4.match("i t22t")
        assert af4.match("i-testt")
        assert af4.match("i-tt")
        assert af4.match(InternalGroupAddress("i-t333t"))
        assert not af4.match("1")
        assert not af4.match(GroupAddress(1))
        assert not af4.match("i testx")
        assert not af4.match("i-11test")
        assert not af4.match(InternalGroupAddress("i-11"))
Beispiel #8
0
    def test_middle(self):
        """
        Test if `GroupAddress.middle` works.

        Checks:
        * Middle group part of a strings returns the right value
        * Return `None` if not `GroupAddressType.LONG`
        """
        GroupAddress.address_format = GroupAddressType.LONG
        assert GroupAddress("1/0/1").middle == 0
        assert GroupAddress("1/7/1").middle == 7
        GroupAddress.address_format = GroupAddressType.SHORT
        assert GroupAddress("1/0").middle is None
        GroupAddress.address_format = GroupAddressType.FREE
        assert GroupAddress("1/0").middle is None
Beispiel #9
0
 def test_equal(self):
     """Test if the equal operator works in all cases."""
     assert GroupAddress("1/0") == GroupAddress(2048)
     assert GroupAddress("1/1") != GroupAddress("1/1/0")
     assert GroupAddress("1/0") is not None
     assert GroupAddress("1/0") != "example"
     assert GroupAddress(1) != IndividualAddress(1)
     assert GroupAddress(1) != 1
Beispiel #10
0
    async def test_process_to_device(self, devices_by_ga_mock):
        """Test process_telegram_incoming for forwarding telegram to a device."""

        xknx = XKNX()
        test_device = AsyncMock()
        devices_by_ga_mock.return_value = [test_device]

        telegram = Telegram(
            destination_address=GroupAddress("1/2/3"),
            direction=TelegramDirection.INCOMING,
            payload=GroupValueWrite(DPTBinary(1)),
        )
        await xknx.telegram_queue.process_telegram_incoming(telegram)
        devices_by_ga_mock.assert_called_once_with(GroupAddress("1/2/3"))
        test_device.process.assert_called_once_with(telegram)
Beispiel #11
0
    async def test_process_exception(self, process_tg_in_mock,
                                     logging_error_mock):
        """Test process_telegram exception handling."""

        xknx = XKNX()

        async def process_exception():
            raise CouldNotParseTelegram(
                "Something went wrong when receiving the telegram.")

        process_tg_in_mock.return_value = asyncio.ensure_future(
            process_exception())

        telegram = Telegram(
            destination_address=GroupAddress("1/2/3"),
            direction=TelegramDirection.INCOMING,
            payload=GroupValueWrite(DPTBinary(1)),
        )

        xknx.telegrams.put_nowait(telegram)
        await xknx.telegram_queue._process_all_telegrams()

        logging_error_mock.assert_called_once_with(
            "Error while processing telegram %s",
            CouldNotParseTelegram(
                "Something went wrong when receiving the telegram."),
        )
Beispiel #12
0
    async def test_process_raising(self, process_mock, logging_exception_mock):
        """Test unexpected exception handling in telegram queues."""
        xknx = XKNX()
        telegram_in = Telegram(
            destination_address=GroupAddress("1/2/3"),
            direction=TelegramDirection.INCOMING,
            payload=GroupValueWrite(DPTBinary(1)),
        )
        # InternalGroupAddress to avoid CommunicationError for missing knxip_interface
        telegram_out = Telegram(
            destination_address=InternalGroupAddress("i-outgoing"),
            direction=TelegramDirection.OUTGOING,
            payload=GroupValueWrite(DPTBinary(0)),
        )
        xknx.telegrams.put_nowait(telegram_in)
        xknx.telegrams.put_nowait(telegram_out)

        await xknx.telegram_queue.start()
        await xknx.telegram_queue.stop()

        log_calls = [
            call(
                "Unexpected error while processing incoming telegram %s",
                telegram_in,
            ),
            call(
                "Unexpected error while processing outgoing telegram %s",
                telegram_out,
            ),
        ]
        logging_exception_mock.assert_has_calls(log_calls)
Beispiel #13
0
    async def test_callback_raising(self, logging_exception_mock):
        """Test telegram_received_callback raising an exception."""
        xknx = XKNX()
        good_callback_1 = AsyncMock()
        bad_callback = AsyncMock(side_effect=Exception("Boom"))
        good_callback_2 = AsyncMock()

        xknx.telegram_queue.register_telegram_received_cb(good_callback_1)
        xknx.telegram_queue.register_telegram_received_cb(bad_callback)
        xknx.telegram_queue.register_telegram_received_cb(good_callback_2)

        telegram = Telegram(
            destination_address=GroupAddress("1/2/3"),
            direction=TelegramDirection.INCOMING,
            payload=GroupValueWrite(DPTBinary(1)),
        )
        await xknx.telegram_queue.process_telegram_incoming(telegram)

        good_callback_1.assert_called_once_with(telegram)
        bad_callback.assert_called_once_with(telegram)
        good_callback_2.assert_called_once_with(telegram)

        logging_exception_mock.assert_called_once_with(
            "Unexpected error while processing telegram_received_cb for %s",
            telegram,
        )
Beispiel #14
0
    async def test_start(self):
        """Test start, run and stop."""

        xknx = XKNX()

        telegram_in = Telegram(
            destination_address=GroupAddress("1/2/3"),
            direction=TelegramDirection.INCOMING,
            payload=GroupValueWrite(DPTBinary(1)),
        )

        await xknx.telegram_queue.start()

        assert not xknx.telegram_queue._consumer_task.done()
        # queue shall now consume telegrams from xknx.telegrams
        assert xknx.telegrams.qsize() == 0
        xknx.telegrams.put_nowait(telegram_in)
        xknx.telegrams.put_nowait(telegram_in)
        assert xknx.telegrams.qsize() == 2
        # wait until telegrams are consumed
        await xknx.telegrams.join()
        assert xknx.telegrams.qsize() == 0
        await xknx.telegrams.join()
        assert xknx.telegrams.qsize() == 0
        # stop run() task with stop()
        await xknx.telegram_queue.stop()
        assert xknx.telegram_queue._consumer_task.done()
Beispiel #15
0
 def test_internal_address_filter_exact(self):
     """Test AddressFilter for InternalGroupAddress."""
     af1 = AddressFilter("i-1")
     assert af1.match("i1")
     assert af1.match("i 1")
     assert af1.match("i-1")
     assert af1.match(InternalGroupAddress("i-1"))
     assert not af1.match("1")
     assert not af1.match(GroupAddress(1))
Beispiel #16
0
 async def _receive_telegram(self, group_address: str, payload: APCI) -> None:
     """Inject incoming KNX telegram."""
     self.xknx.telegrams.put_nowait(
         Telegram(
             destination_address=GroupAddress(group_address),
             direction=TelegramDirection.INCOMING,
             payload=payload,
             source_address=IndividualAddress(self.INDIVIDUAL_ADDRESS),
         )
     )
     await self.hass.async_block_till_done()
Beispiel #17
0
 def test_equal(self):
     """Test if the equal operator works in all cases."""
     assert InternalGroupAddress("i 123") == InternalGroupAddress("i 123")
     assert InternalGroupAddress("i-asdf") == InternalGroupAddress("i asdf")
     assert InternalGroupAddress("i-asdf") == InternalGroupAddress("Iasdf")
     assert InternalGroupAddress("i-1") != InternalGroupAddress("i-2")
     assert InternalGroupAddress("i-1") is not None
     assert InternalGroupAddress("i-example") != "example"
     assert InternalGroupAddress("i-0") != GroupAddress(0)
     assert InternalGroupAddress("i-1") != IndividualAddress(1)
     assert InternalGroupAddress("i-1") != 1
Beispiel #18
0
    def test_with_valid(self, address_test, address_raw):
        """
        Test if the class constructor generates valid raw values.

        This test checks:
        * all allowed input variants (strings, tuples, integers)
        * for conversation errors
        * for upper/lower limits still working, to avoid off-by-one errors
        """

        assert GroupAddress(address_test).raw == address_raw
Beispiel #19
0
    def test_sub(self):
        """
        Test if `GroupAddress.sub` works.

        Checks:
        * Sub group part of a strings returns the right value
        * Return never `None`
        """
        assert GroupAddress("1/0", GroupAddressType.SHORT).sub == 0
        assert GroupAddress("31/0", GroupAddressType.SHORT).sub == 0
        assert GroupAddress("1/2047", GroupAddressType.SHORT).sub == 2047
        assert GroupAddress("31/2047", GroupAddressType.SHORT).sub == 2047
        assert GroupAddress("1/0/0", GroupAddressType.LONG).sub == 0
        assert GroupAddress("1/0/255", GroupAddressType.LONG).sub == 255
        assert GroupAddress("0/0", GroupAddressType.FREE).sub == 0
        assert GroupAddress("1/0", GroupAddressType.FREE).sub == 2048
        assert GroupAddress("31/2047", GroupAddressType.FREE).sub == 65535
Beispiel #20
0
    def test_with_invalid(self, address_test):
        """
        Test if constructor raises an exception for all known invalid cases.

        Checks:
        * addresses or parts of it too high/low
        * invalid input variants (lists instead of tuples)
        * invalid strings
        """

        with pytest.raises(CouldNotParseAddress):
            GroupAddress(address_test)
Beispiel #21
0
 def test_representation(self, initializer, string_free, string_short,
                         string_long):
     """Test string representation of address."""
     group_address = GroupAddress(initializer)
     GroupAddress.address_format = GroupAddressType.FREE
     assert str(group_address) == string_free
     assert repr(group_address) == f'GroupAddress("{string_free}")'
     GroupAddress.address_format = GroupAddressType.SHORT
     assert str(group_address) == string_short
     assert repr(group_address) == f'GroupAddress("{string_short}")'
     GroupAddress.address_format = GroupAddressType.LONG
     assert str(group_address) == string_long
     assert repr(group_address) == f'GroupAddress("{string_long}")'
Beispiel #22
0
    async def test_register(self):
        """Test telegram_received_callback after state of switch was changed."""

        xknx = XKNX()
        async_telegram_received_cb = AsyncMock()
        xknx.telegram_queue.register_telegram_received_cb(async_telegram_received_cb)

        telegram = Telegram(
            destination_address=GroupAddress("1/2/3"),
            direction=TelegramDirection.INCOMING,
            payload=GroupValueWrite(DPTBinary(1)),
        )
        await xknx.telegram_queue.process_telegram_incoming(telegram)
        async_telegram_received_cb.assert_called_once_with(telegram)
Beispiel #23
0
    async def test_process_all_telegrams(self, process_telegram_incoming_mock,
                                         process_telegram_outgoing_mock):
        """Test _process_all_telegrams for clearing the queue."""
        xknx = XKNX()

        telegram_in = Telegram(
            destination_address=GroupAddress("1/2/3"),
            direction=TelegramDirection.INCOMING,
            payload=GroupValueWrite(DPTBinary(1)),
        )
        telegram_out = Telegram(
            destination_address=GroupAddress("1/2/3"),
            direction=TelegramDirection.OUTGOING,
            payload=GroupValueWrite(DPTBinary(1)),
        )

        xknx.telegrams.put_nowait(telegram_in)
        xknx.telegrams.put_nowait(telegram_out)
        res = await xknx.telegram_queue._process_all_telegrams()

        assert res is None
        process_telegram_incoming_mock.assert_called_once()
        process_telegram_outgoing_mock.assert_called_once()
Beispiel #24
0
    async def test_register_with_outgoing_telegrams_does_not_trigger(self):
        """Test telegram_received_callback with outgoing telegrams."""

        xknx = XKNX()
        xknx.knxip_interface = AsyncMock()
        async_telegram_received_cb = AsyncMock()
        xknx.telegram_queue.register_telegram_received_cb(async_telegram_received_cb)

        telegram = Telegram(
            destination_address=GroupAddress("1/2/3"),
            direction=TelegramDirection.OUTGOING,
            payload=GroupValueWrite(DPTBinary(1)),
        )

        await xknx.telegram_queue.process_telegram_outgoing(telegram)
        async_telegram_received_cb.assert_not_called()
Beispiel #25
0
    async def test_callback_no_filters(self):
        """Test telegram_received_callback after state of switch was changed."""
        xknx = XKNX()
        async_telegram_received_callback = AsyncMock()

        xknx.telegram_queue.register_telegram_received_cb(
            async_telegram_received_callback)

        telegram = Telegram(
            destination_address=GroupAddress("1/2/3"),
            direction=TelegramDirection.INCOMING,
            payload=GroupValueWrite(DPTBinary(1)),
        )
        xknx.telegrams.put_nowait(telegram)
        await xknx.telegram_queue._process_all_telegrams()

        async_telegram_received_callback.assert_called_with(telegram)
Beispiel #26
0
    async def test_process_to_callback(self, devices_process):
        """Test process_telegram_incoming with callback."""

        xknx = XKNX()
        async_telegram_received_callback = AsyncMock()

        xknx.telegram_queue.register_telegram_received_cb(
            async_telegram_received_callback)

        telegram = Telegram(
            destination_address=GroupAddress("1/2/3"),
            direction=TelegramDirection.INCOMING,
            payload=GroupValueWrite(DPTBinary(1)),
        )
        await xknx.telegram_queue.process_telegram_incoming(telegram)
        async_telegram_received_callback.assert_called_once_with(telegram)
        devices_process.assert_called_once_with(telegram)
Beispiel #27
0
    async def test_outgoing(self):
        """Test outgoing telegrams in telegram queue."""
        xknx = XKNX()

        telegram = Telegram(
            destination_address=GroupAddress("1/2/3"),
            direction=TelegramDirection.OUTGOING,
            payload=GroupValueWrite(DPTBinary(1)),
        )

        # log a warning if there is no KNXIP interface instanciated
        with pytest.raises(CommunicationError):
            await xknx.telegram_queue.process_telegram_outgoing(telegram)

        # if we have an interface send the telegram (doesn't raise)
        xknx.knxip_interface.send_telegram = AsyncMock()
        await xknx.telegram_queue.process_telegram_outgoing(telegram)
        xknx.knxip_interface.send_telegram.assert_called_once_with(telegram)
Beispiel #28
0
    "0/0/11": 11,
    "0/0/111": 111,
    "0/0/255": 255,
    "0/1/11": 267,
    "0/1/111": 367,
    "0/7/255": 2047,
    "1/0": 2048,
    "1/0/0": 2048,
    "1/1/111": 2415,
    "1/7/255": 4095,
    "31/7/255": 65535,
    "1": 1,
    0: 0,
    65535: 65535,
    (0xFF, 0xFF): 65535,
    GroupAddress("1/1/111"): 2415,
    None: 0,
}

group_addresses_invalid = [
    "0/2049",
    "0/8/0",
    "0/0/256",
    "32/0",
    "0/0a",
    "a0/0",
    "abc",
    "1.1.1",
    "0.0",
    IndividualAddress("11.11.111"),
    65536,
Beispiel #29
0
 def test_to_knx(self):
     """Test if `GroupAddress.to_knx()` generates valid byte tuples."""
     assert GroupAddress("0/0").to_knx() == (0x0, 0x0)
     assert GroupAddress("31/2047").to_knx() == (0xFF, 0xFF)