From dbf70deed4c72d84bfc915539f1d54aca955813d Mon Sep 17 00:00:00 2001 From: Bas Stottelaar Date: Tue, 3 Dec 2019 19:44:35 +0100 Subject: [PATCH 1/6] Remove `Telegram.telegramtype` This becomes unnecessary if the telegram type can be derrived from the payload. --- test/str_test.py | 4 ++-- xknx/telegram/__init__.py | 2 +- xknx/telegram/telegram.py | 16 ++-------------- 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/test/str_test.py b/test/str_test.py index 7972402fe..cad6df811 100644 --- a/test/str_test.py +++ b/test/str_test.py @@ -473,8 +473,8 @@ def test_telegram(self): ) self.assertEqual( str(telegram), - '" />', + '" />', ) def test_dib_generic(self): diff --git a/xknx/telegram/__init__.py b/xknx/telegram/__init__.py index b47b5fd09..1b222e1d5 100644 --- a/xknx/telegram/__init__.py +++ b/xknx/telegram/__init__.py @@ -8,4 +8,4 @@ # flake8: noqa from .address import GroupAddress, GroupAddressType, IndividualAddress from .address_filter import AddressFilter -from .telegram import Telegram, TelegramDirection, TelegramType +from .telegram import Telegram, TelegramDirection diff --git a/xknx/telegram/telegram.py b/xknx/telegram/telegram.py index 759bc6e0a..3b4280c29 100644 --- a/xknx/telegram/telegram.py +++ b/xknx/telegram/telegram.py @@ -8,10 +8,9 @@ It contains -* the telegram type (e.g. GROUP_WRITE) * the direction (incoming or outgoing) * the group address (e.g. 1/2/3) -* and the payload (e.g. "12%" or "23.23 C". +* and the payload (e.g. GroupValueWrite("12%")). """ from enum import Enum @@ -27,14 +26,6 @@ class TelegramDirection(Enum): OUTGOING = "Outgoing" -class TelegramType(Enum): - """Enum class for type of telegram.""" - - GROUP_READ = "GroupValueRead" - GROUP_WRITE = "GroupValueWrite" - GROUP_RESPONSE = "GroupValueResponse" - - class Telegram: """Class for KNX telegrams.""" @@ -45,14 +36,12 @@ def __init__( destination_address: Union[GroupAddress, IndividualAddress] = GroupAddress( None ), - telegramtype: TelegramType = TelegramType.GROUP_WRITE, direction: TelegramDirection = TelegramDirection.OUTGOING, payload: Any = None, source_address: IndividualAddress = IndividualAddress(None), ) -> None: """Initialize Telegram class.""" self.destination_address = destination_address - self.telegramtype = telegramtype self.direction = direction self.payload = payload self.source_address = source_address @@ -60,10 +49,9 @@ def __init__( def __str__(self) -> str: """Return object as readable string.""" return ( - ''.format( self.direction.value, - self.telegramtype.value, self.source_address, self.destination_address, self.payload, From 2eb10b6e11f04c4a166a6cd96a4b90507c69319a Mon Sep 17 00:00:00 2001 From: Bas Stottelaar Date: Tue, 3 Dec 2019 19:52:44 +0100 Subject: [PATCH 2/6] Add `xknx.telegram.apci` Thi adds payload classes that represent APCI messages, such as GroupValueRead/Write/Response. --- xknx/telegram/__init__.py | 1 + xknx/telegram/apci.py | 213 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 xknx/telegram/apci.py diff --git a/xknx/telegram/__init__.py b/xknx/telegram/__init__.py index 1b222e1d5..2c7187bad 100644 --- a/xknx/telegram/__init__.py +++ b/xknx/telegram/__init__.py @@ -8,4 +8,5 @@ # flake8: noqa from .address import GroupAddress, GroupAddressType, IndividualAddress from .address_filter import AddressFilter +from .apci import GroupValueRead, GroupValueResponse, GroupValueWrite from .telegram import Telegram, TelegramDirection diff --git a/xknx/telegram/apci.py b/xknx/telegram/apci.py new file mode 100644 index 000000000..52bb0aa82 --- /dev/null +++ b/xknx/telegram/apci.py @@ -0,0 +1,213 @@ +""" +Module for serialization and deserialization of APCI payloads. + +APCI stands for Application Layer Protocol Control Information. + +An APCI payload contains a service and payload. For example, a GroupValueWrite +is a service that takes a DPT as a value. +""" +from enum import Enum +import logging +from typing import Optional, Type, Union + +from xknx.dpt import DPTArray, DPTBinary +from xknx.exceptions import ConversionError + +logger = logging.getLogger("xknx.log") + + +def encode_cmd_and_payload( + cmd: "APCICommand", + encoded_payload: int = 0, + appended_payload: Optional[bytes] = None, +) -> bytes: + """Encode cmd and payload.""" + if appended_payload is None: + appended_payload = bytes() + + data = bytearray( + [ + 1 + len(appended_payload), + (cmd.value >> 8) & 0xFF, + (cmd.value & 0xFF) | (encoded_payload & DPTBinary.APCI_BITMASK), + ] + ) + data.extend(appended_payload) + return data + + +class APCICommand(Enum): + """Enum class for APCI services.""" + + GROUP_READ = 0x0000 + GROUP_RESPONSE = 0x0040 + GROUP_WRITE = 0x0080 + + ESCAPE = 0x03C0 + + +class APCIExtendedCommand(Enum): + """Enum class for extended APCI services.""" + + +class APCI: + """ + Base class for ACPI services. + + This base class is only the interface for the derived classes. + """ + + code: APCICommand = APCICommand.ESCAPE + + def __init__(self) -> None: + """Initialize APCI class.""" + + def calculated_length(self) -> int: + """Get length of APCI payload - to be implemented in derived class.""" + logger.warning( + "'calculated_length()' not implemented for %s", self.__class__.__name__ + ) + + return 0 + + def from_knx(self, raw: bytes) -> None: + """Parse/deserialize from KNX/IP raw data - to be implemented in derived class.""" + # pylint: disable=unused-argument + logger.warning("'from_knx()' not implemented for %s", self.__class__.__name__) + + def to_knx(self) -> bytes: + """Serialize to KNX/IP raw data - to be implemented in derived class.""" + # pylint: disable=unused-argument + logger.warning("'to_knx()' not implemented for %s", self.__class__.__name__) + + return bytes() + + def __eq__(self, other: object) -> bool: + """Equal operator.""" + return self.__dict__ == other.__dict__ + + @staticmethod + def resolve_class(apci: int) -> Type["APCI"]: + """Return telegram type from APCI Command.""" + extended = (apci & APCICommand.ESCAPE.value) == APCICommand.ESCAPE.value + + if extended: + raise ConversionError( + f"Telegram not implemented for extended APCI {apci:#012b}." + ) + + apci = apci & 0x03C0 + + if apci == APCICommand.GROUP_READ.value: + return GroupValueRead + if apci == APCICommand.GROUP_WRITE.value: + return GroupValueWrite + if apci == APCICommand.GROUP_RESPONSE.value: + return GroupValueResponse + raise ConversionError(f"Telegram not implemented for APCI {apci:#012b}.") + + +class GroupValueRead(APCI): + """ + GroupValueRead service. + + Does not have any payload. + """ + + code = APCICommand.GROUP_READ + + def calculated_length(self) -> int: + """Get length of APCI payload.""" + return 1 + + def to_knx(self) -> bytes: + """Serialize to KNX/IP raw data.""" + return encode_cmd_and_payload(self.code) + + def __str__(self) -> str: + """Return object as readable string.""" + return "" + + +class GroupValueWrite(APCI): + """ + GroupValueRead service. + + Takes a DPT as payload. + """ + + code = APCICommand.GROUP_WRITE + + def __init__(self, dpt: Optional[Union[DPTBinary, DPTArray]] = None) -> None: + """Initialize a new instance of GroupValueWrite.""" + super().__init__() + self.dpt = dpt + + def calculated_length(self) -> int: + """Get length of APCI payload.""" + if isinstance(self.dpt, DPTBinary): + return 1 + if isinstance(self.dpt, DPTArray): + return 1 + len(self.dpt.value) + raise TypeError() + + def from_knx(self, raw: bytes) -> None: + """Parse/deserialize from KNX/IP raw data.""" + if len(raw) == 1: + self.dpt = DPTBinary(raw[0] & DPTBinary.APCI_BITMASK) + else: + self.dpt = DPTArray(raw[1:]) + + def to_knx(self) -> bytes: + """Serialize to KNX/IP raw data.""" + if isinstance(self.dpt, DPTBinary): + return encode_cmd_and_payload(self.code, encoded_payload=self.dpt.value) + if isinstance(self.dpt, DPTArray): + return encode_cmd_and_payload(self.code, appended_payload=self.dpt.value) + raise TypeError() + + def __str__(self) -> str: + """Return object as readable string.""" + return f'' + + +class GroupValueResponse(APCI): + """ + GroupValueResponse service. + + Takes a DPT as payload. + """ + + code = APCICommand.GROUP_RESPONSE + + def __init__(self, dpt: Optional[Union[DPTBinary, DPTArray]] = None) -> None: + """Initialize a new instance of GroupValueResponse.""" + super().__init__() + self.dpt = dpt + + def calculated_length(self) -> int: + """Get length of APCI payload.""" + if isinstance(self.dpt, DPTBinary): + return 1 + if isinstance(self.dpt, DPTArray): + return 1 + len(self.dpt.value) + raise TypeError() + + def from_knx(self, raw: bytes) -> None: + """Parse/deserialize from KNX/IP raw data.""" + if len(raw) == 1: + self.dpt = DPTBinary(raw[0] & DPTBinary.APCI_BITMASK) + else: + self.dpt = DPTArray(raw[1:]) + + def to_knx(self) -> bytes: + """Serialize to KNX/IP raw data.""" + if isinstance(self.dpt, DPTBinary): + return encode_cmd_and_payload(self.code, encoded_payload=self.dpt.value) + if isinstance(self.dpt, DPTArray): + return encode_cmd_and_payload(self.code, appended_payload=self.dpt.value) + raise TypeError() + + def __str__(self) -> str: + """Return object as readable string.""" + return f'' From b350674aae321035a6115c01755ef71897981989 Mon Sep 17 00:00:00 2001 From: Bas Stottelaar Date: Tue, 3 Dec 2019 19:53:28 +0100 Subject: [PATCH 3/6] Refactor `Telegram.payload` This adapts all Telegram payload objects to the corresponding APCI payload objects. It removes the need for `Telegram.telegramtype`. --- examples/example_tunnel.py | 12 +- test/core_tests/telegram_queue_test.py | 38 +-- test/core_tests/value_reader_test.py | 27 +- test/devices_tests/binary_sensor_test.py | 49 ++-- test/devices_tests/climate_test.py | 256 +++++++++++------- test/devices_tests/cover_test.py | 108 +++++--- test/devices_tests/datetime_test.py | 29 +- test/devices_tests/device_test.py | 18 +- test/devices_tests/expose_sensor_test.py | 35 ++- test/devices_tests/fan_test.py | 22 +- test/devices_tests/light_test.py | 128 +++++---- test/devices_tests/notification_test.py | 21 +- test/devices_tests/scene_test.py | 12 +- test/devices_tests/sensor_expose_loop_test.py | 14 +- test/devices_tests/sensor_test.py | 30 +- test/devices_tests/switch_test.py | 61 +++-- test/io_tests/tunnelling_test.py | 5 +- test/knxip_tests/cemi_frame_test.py | 30 +- test/knxip_tests/routing_indication_test.py | 36 ++- test/knxip_tests/tunnelling_request_test.py | 10 +- .../remote_value_1count_test.py | 24 +- .../remote_value_climate_mode_test.py | 46 ++-- .../remote_value_color_rgb_test.py | 13 +- .../remote_value_color_rgbw_test.py | 17 +- .../remote_value_dpt_2_byte_unsigned_test.py | 35 ++- .../remote_value_dpt_value_1_ucount_test.py | 24 +- .../remote_value_scene_number_test.py | 24 +- .../remote_value_step_test.py | 21 +- .../remote_value_string_test.py | 57 ++-- .../remote_value_switch_test.py | 24 +- test/remote_value_tests/remote_value_test.py | 10 +- .../remote_value_updown_test.py | 21 +- test/str_test.py | 24 +- test/telegram_tests/telegram_test.py | 25 +- xknx/core/telegram_queue.py | 4 +- xknx/core/value_reader.py | 13 +- xknx/devices/device.py | 12 +- xknx/knxip/cemi_frame.py | 78 ++---- xknx/knxip/knxip_enum.py | 6 +- xknx/remote_value/remote_value.py | 31 ++- 40 files changed, 833 insertions(+), 617 deletions(-) diff --git a/examples/example_tunnel.py b/examples/example_tunnel.py index c54505685..9276c3921 100644 --- a/examples/example_tunnel.py +++ b/examples/example_tunnel.py @@ -4,7 +4,7 @@ from xknx import XKNX from xknx.dpt import DPTBinary from xknx.io import GatewayScanner, Tunnel -from xknx.telegram import GroupAddress, IndividualAddress, Telegram +from xknx.telegram import GroupAddress, GroupValueWrite, IndividualAddress, Telegram async def main(): @@ -38,11 +38,17 @@ async def main(): await tunnel.connect() await tunnel.send_telegram( - Telegram(destination_address=GroupAddress("1/0/15"), payload=DPTBinary(1)) + Telegram( + destination_address=GroupAddress("1/0/15"), + payload=GroupValueWrite(DPTBinary(1)), + ) ) await asyncio.sleep(2) await tunnel.send_telegram( - Telegram(destination_address=GroupAddress("1/0/15"), payload=DPTBinary(0)) + Telegram( + destination_address=GroupAddress("1/0/15"), + payload=GroupValueWrite(DPTBinary(0)), + ) ) await asyncio.sleep(2) diff --git a/test/core_tests/telegram_queue_test.py b/test/core_tests/telegram_queue_test.py index 4460ec296..74917c3e5 100644 --- a/test/core_tests/telegram_queue_test.py +++ b/test/core_tests/telegram_queue_test.py @@ -6,7 +6,13 @@ from xknx import XKNX from xknx.dpt import DPTBinary from xknx.exceptions import CouldNotParseTelegram -from xknx.telegram import AddressFilter, GroupAddress, Telegram, TelegramDirection +from xknx.telegram import ( + AddressFilter, + GroupAddress, + GroupValueWrite, + Telegram, + TelegramDirection, +) class AsyncMock(MagicMock): @@ -40,7 +46,7 @@ def test_start(self): telegram_in = Telegram( destination_address=GroupAddress("1/2/3"), direction=TelegramDirection.INCOMING, - payload=DPTBinary(1), + payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete(xknx.telegram_queue.start()) @@ -75,14 +81,12 @@ async def async_none(): telegram_in = Telegram( direction=TelegramDirection.INCOMING, - payload=DPTBinary(1), - destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) telegram_out = Telegram( direction=TelegramDirection.OUTGOING, - payload=DPTBinary(1), - destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete(xknx.telegram_queue.start()) @@ -120,7 +124,7 @@ async def async_telegram_received_cb(device): telegram = Telegram( destination_address=GroupAddress("1/2/3"), direction=TelegramDirection.INCOMING, - payload=DPTBinary(1), + payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete( xknx.telegram_queue.process_telegram_incoming(telegram) @@ -144,7 +148,7 @@ def test_unregister(self): telegram = Telegram( destination_address=GroupAddress("1/2/3"), direction=TelegramDirection.INCOMING, - payload=DPTBinary(1), + payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete( xknx.telegram_queue.process_telegram_incoming(telegram) @@ -170,7 +174,7 @@ def test_process_to_device(self, devices_by_ga_mock): telegram = Telegram( destination_address=GroupAddress("1/2/3"), direction=TelegramDirection.INCOMING, - payload=DPTBinary(1), + payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete( xknx.telegram_queue.process_telegram_incoming(telegram) @@ -193,7 +197,7 @@ def test_process_to_callback(self, devices_process): telegram = Telegram( destination_address=GroupAddress("1/2/3"), direction=TelegramDirection.INCOMING, - payload=DPTBinary(1), + payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete( xknx.telegram_queue.process_telegram_incoming(telegram) @@ -215,7 +219,7 @@ def test_outgoing(self, logger_warning_mock, if_mock): telegram = Telegram( destination_address=GroupAddress("1/2/3"), direction=TelegramDirection.OUTGOING, - payload=DPTBinary(1), + payload=GroupValueWrite(DPTBinary(1)), ) # log a warning if there is no KNXIP interface instanciated @@ -249,7 +253,7 @@ async def process_exception(): telegram = Telegram( destination_address=GroupAddress("1/2/3"), direction=TelegramDirection.INCOMING, - payload=DPTBinary(1), + payload=GroupValueWrite(DPTBinary(1)), ) xknx.telegrams.put_nowait(telegram) @@ -279,12 +283,12 @@ def test_process_all_telegrams( telegram_in = Telegram( destination_address=GroupAddress("1/2/3"), direction=TelegramDirection.INCOMING, - payload=DPTBinary(1), + payload=GroupValueWrite(DPTBinary(1)), ) telegram_out = Telegram( destination_address=GroupAddress("1/2/3"), direction=TelegramDirection.OUTGOING, - payload=DPTBinary(1), + payload=GroupValueWrite(DPTBinary(1)), ) xknx.telegrams.put_nowait(telegram_in) @@ -314,7 +318,7 @@ async def async_telegram_received_cb(device): telegram = Telegram( destination_address=GroupAddress("1/2/3"), direction=TelegramDirection.INCOMING, - payload=DPTBinary(1), + payload=GroupValueWrite(DPTBinary(1)), ) xknx.telegrams.put_nowait(telegram) self.loop.run_until_complete(xknx.telegram_queue._process_all_telegrams()) @@ -343,7 +347,7 @@ async def async_telegram_received_cb(device): telegram = Telegram( destination_address=GroupAddress("1/2/3"), direction=TelegramDirection.INCOMING, - payload=DPTBinary(1), + payload=GroupValueWrite(DPTBinary(1)), ) xknx.telegrams.put_nowait(telegram) self.loop.run_until_complete(xknx.telegram_queue._process_all_telegrams()) @@ -372,7 +376,7 @@ async def async_telegram_received_cb(device): telegram = Telegram( destination_address=GroupAddress("1/2/3"), direction=TelegramDirection.INCOMING, - payload=DPTBinary(1), + payload=GroupValueWrite(DPTBinary(1)), ) xknx.telegrams.put_nowait(telegram) self.loop.run_until_complete(xknx.telegram_queue._process_all_telegrams()) diff --git a/test/core_tests/value_reader_test.py b/test/core_tests/value_reader_test.py index 901739227..76edc8c05 100644 --- a/test/core_tests/value_reader_test.py +++ b/test/core_tests/value_reader_test.py @@ -6,7 +6,14 @@ from xknx import XKNX from xknx.core import ValueReader from xknx.dpt import DPTBinary -from xknx.telegram import GroupAddress, Telegram, TelegramDirection, TelegramType +from xknx.telegram import ( + GroupAddress, + GroupValueRead, + GroupValueResponse, + GroupValueWrite, + Telegram, + TelegramDirection, +) class TestValueReader(unittest.TestCase): @@ -28,9 +35,8 @@ def test_value_reader_read_success(self, timeout_mock): test_group_address = GroupAddress("0/0/0") response_telegram = Telegram( destination_address=test_group_address, - telegramtype=TelegramType.GROUP_RESPONSE, direction=TelegramDirection.INCOMING, - payload=DPTBinary(1), + payload=GroupValueResponse(DPTBinary(1)), ) value_reader = ValueReader(xknx, test_group_address) @@ -94,8 +100,7 @@ def test_value_reader_send_group_read(self): self.assertEqual( telegram, Telegram( - destination_address=GroupAddress("0/0/0"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("0/0/0"), payload=GroupValueRead() ), ) @@ -105,27 +110,23 @@ def test_value_reader_telegram_received(self): test_group_address = GroupAddress("0/0/0") expected_telegram_1 = Telegram( destination_address=test_group_address, - telegramtype=TelegramType.GROUP_RESPONSE, direction=TelegramDirection.INCOMING, - payload=DPTBinary(1), + payload=GroupValueResponse(DPTBinary(1)), ) expected_telegram_2 = Telegram( destination_address=test_group_address, - telegramtype=TelegramType.GROUP_WRITE, direction=TelegramDirection.INCOMING, - payload=DPTBinary(1), + payload=GroupValueWrite(DPTBinary(1)), ) telegram_wrong_address = Telegram( destination_address=GroupAddress("0/0/1"), - telegramtype=TelegramType.GROUP_RESPONSE, direction=TelegramDirection.INCOMING, - payload=DPTBinary(1), + payload=GroupValueResponse(DPTBinary(1)), ) telegram_wrong_type = Telegram( destination_address=test_group_address, - telegramtype=TelegramType.GROUP_READ, direction=TelegramDirection.INCOMING, - payload=DPTBinary(1), + payload=GroupValueRead(), ) value_reader = ValueReader(xknx, test_group_address) diff --git a/test/devices_tests/binary_sensor_test.py b/test/devices_tests/binary_sensor_test.py index 33649836f..65268fd7d 100644 --- a/test/devices_tests/binary_sensor_test.py +++ b/test/devices_tests/binary_sensor_test.py @@ -7,7 +7,7 @@ from xknx.devices import Action, BinarySensor, Switch from xknx.dpt import DPTArray, DPTBinary from xknx.exceptions import CouldNotParseTelegram -from xknx.telegram import GroupAddress, Telegram, TelegramType +from xknx.telegram import GroupAddress, GroupValueResponse, GroupValueWrite, Telegram class AsyncMock(MagicMock): @@ -38,14 +38,16 @@ def test_process(self): self.assertEqual(binaryinput.state, None) telegram_on = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete(binaryinput.process(telegram_on)) self.assertEqual(binaryinput.state, True) telegram_off = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(0) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(0)), ) self.loop.run_until_complete(binaryinput.process(telegram_off)) self.assertEqual(binaryinput.state, False) @@ -54,7 +56,8 @@ def test_process(self): self.assertEqual(binaryinput2.state, None) telegram_off2 = Telegram( - destination_address=GroupAddress("1/2/4"), payload=DPTBinary(0) + destination_address=GroupAddress("1/2/4"), + payload=GroupValueWrite(DPTBinary(0)), ) self.loop.run_until_complete(binaryinput2.process(telegram_off2)) self.assertEqual(binaryinput2.state, False) @@ -67,14 +70,16 @@ def test_process_invert(self): self.assertEqual(bs_invert.state, None) telegram_on = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(0) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(0)), ) self.loop.run_until_complete(bs_invert.process(telegram_on)) self.assertEqual(bs_invert.state, True) telegram_off = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete(bs_invert.process(telegram_off)) self.assertEqual(bs_invert.state, False) @@ -92,7 +97,8 @@ def test_process_reset_after(self): device_updated_cb=async_after_update_callback, ) telegram_on = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete(binaryinput.process(telegram_on)) @@ -131,7 +137,8 @@ def test_process_action(self): self.assertEqual(switch.state, None) telegram_on = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete(binary_sensor.process(telegram_on)) # process outgoing telegram from queue @@ -141,7 +148,8 @@ def test_process_action(self): self.assertEqual(switch.state, True) telegram_off = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(0) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(0)), ) self.loop.run_until_complete(binary_sensor.process(telegram_off)) self.loop.run_until_complete(switch.process(xknx.telegrams.get_nowait())) @@ -164,7 +172,8 @@ def test_process_action_ignore_internal_state(self): self.assertEqual(switch.state, None) telegram_on = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) with patch("time.time") as mock_time, patch( @@ -197,7 +206,8 @@ def test_process_wrong_payload(self): xknx = XKNX() binary_sensor = BinarySensor(xknx, "Warning", group_address_state="1/2/3") telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((0x1, 0x2, 0x3)) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((0x1, 0x2, 0x3))), ) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(binary_sensor.process(telegram)) @@ -245,7 +255,8 @@ def test_process_callback(self): switch.register_device_updated_cb(async_after_update_callback) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete(switch.process(telegram)) # no _context_task started because ignore_internal_state is False @@ -273,7 +284,8 @@ def test_process_callback_ignore_internal_state(self): switch.register_device_updated_cb(async_after_update_callback) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) self.assertEqual(switch.counter, 0) @@ -315,7 +327,8 @@ def test_process_callback_ignore_internal_state_no_counter(self): switch.register_device_updated_cb(async_after_update_callback) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete(switch.process(telegram)) # no _context_task started because context_timeout is False @@ -342,12 +355,14 @@ def test_process_group_value_response(self): switch.register_device_updated_cb(async_after_update_callback) write_telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) response_telegram = Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTBinary(1), - telegramtype=TelegramType.GROUP_RESPONSE, + payload=GroupValueResponse( + DPTBinary(1), + ), ) self.assertIsNone(switch.state) # initial GroupValueResponse changes state and runs callback diff --git a/test/devices_tests/climate_test.py b/test/devices_tests/climate_test.py index 7d9587b52..70c482de5 100644 --- a/test/devices_tests/climate_test.py +++ b/test/devices_tests/climate_test.py @@ -19,7 +19,7 @@ ) from xknx.dpt.dpt_hvac_mode import HVACControllerMode from xknx.exceptions import CouldNotParseTelegram, DeviceIllegalValue -from xknx.telegram import GroupAddress, Telegram, TelegramType +from xknx.telegram import GroupAddress, GroupValueRead, GroupValueWrite, Telegram DPT_20102_MODES = [ HVACOperationMode.AUTO, @@ -233,7 +233,7 @@ async def async_after_update_callback(device): telegram = Telegram( destination_address=GroupAddress("1/2/1"), - payload=DPTArray(DPTTemperature.to_knx(23)), + payload=GroupValueWrite(DPTArray(DPTTemperature.to_knx(23))), ) self.loop.run_until_complete(climate.process(telegram)) after_update_callback.assert_called_with(climate) @@ -241,7 +241,7 @@ async def async_after_update_callback(device): telegram = Telegram( destination_address=GroupAddress("1/2/2"), - payload=DPTArray(DPTTemperature.to_knx(23)), + payload=GroupValueWrite(DPTArray(DPTTemperature.to_knx(23))), ) self.loop.run_until_complete(climate.process(telegram)) after_update_callback.assert_called_with(climate) @@ -249,7 +249,7 @@ async def async_after_update_callback(device): telegram = Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray(DPTValue1Count.to_knx(-4)), + payload=GroupValueWrite(DPTArray(DPTValue1Count.to_knx(-4))), ) self.loop.run_until_complete(climate.process(telegram)) after_update_callback.assert_called_with(climate) @@ -276,7 +276,8 @@ async def async_after_update_callback(device): # Note: the climate object processes the telegram, but the cb # is called with the climate_mode object. telegram = Telegram( - destination_address=GroupAddress("1/2/4"), payload=DPTArray(1) + destination_address=GroupAddress("1/2/4"), + payload=GroupValueWrite(DPTArray(1)), ) self.loop.run_until_complete(climate.process(telegram)) after_update_callback.assert_called_with(climate_mode) @@ -303,7 +304,9 @@ def test_set_operation_mode(self): telegram, Telegram( destination_address=GroupAddress("1/2/4"), - payload=DPTArray(DPTHVACMode.to_knx(operation_mode)), + payload=GroupValueWrite( + DPTArray(DPTHVACMode.to_knx(operation_mode)) + ), ), ) @@ -325,7 +328,9 @@ def test_set_controller_operation_mode(self): telegram, Telegram( destination_address=GroupAddress("1/2/4"), - payload=DPTArray(DPTHVACContrMode.to_knx(controller_mode)), + payload=GroupValueWrite( + DPTArray(DPTHVACContrMode.to_knx(controller_mode)) + ), ), ) @@ -367,7 +372,9 @@ def test_set_operation_mode_with_controller_status(self): telegram, Telegram( destination_address=GroupAddress("1/2/4"), - payload=DPTArray(DPTControllerStatus.to_knx(operation_mode)), + payload=GroupValueWrite( + DPTArray(DPTControllerStatus.to_knx(operation_mode)) + ), ), ) @@ -393,15 +400,21 @@ def test_set_operation_mode_with_separate_addresses(self): telegrams.append(xknx.telegrams.get_nowait()) test_telegrams = [ - Telegram(destination_address=GroupAddress("1/2/4"), payload=DPTArray(1)), Telegram( - destination_address=GroupAddress("1/2/5"), payload=DPTBinary(False) + destination_address=GroupAddress("1/2/4"), + payload=GroupValueWrite(DPTArray(1)), + ), + Telegram( + destination_address=GroupAddress("1/2/5"), + payload=GroupValueWrite(DPTBinary(False)), ), Telegram( - destination_address=GroupAddress("1/2/6"), payload=DPTBinary(False) + destination_address=GroupAddress("1/2/6"), + payload=GroupValueWrite(DPTBinary(False)), ), Telegram( - destination_address=GroupAddress("1/2/7"), payload=DPTBinary(True) + destination_address=GroupAddress("1/2/7"), + payload=GroupValueWrite(DPTBinary(True)), ), ] @@ -425,7 +438,8 @@ def test_set_heat_cool_binary(self): self.assertEqual( telegram, Telegram( - destination_address=GroupAddress("1/2/14"), payload=DPTBinary(True) + destination_address=GroupAddress("1/2/14"), + payload=GroupValueWrite(DPTBinary(True)), ), ) self.loop.run_until_complete( @@ -436,7 +450,8 @@ def test_set_heat_cool_binary(self): self.assertEqual( telegram, Telegram( - destination_address=GroupAddress("1/2/14"), payload=DPTBinary(False) + destination_address=GroupAddress("1/2/14"), + payload=GroupValueWrite(DPTBinary(False)), ), ) @@ -533,7 +548,10 @@ def test_target_temperature_up(self): self.assertEqual( _telegram, # DEFAULT_TEMPERATURE_STEP is 0.1 -> payload = setpoint_shift * 10 - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTArray(30)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray(30)), + ), ) self.loop.run_until_complete(xknx.devices.process(_telegram)) @@ -544,7 +562,7 @@ def test_target_temperature_up(self): _telegram, Telegram( destination_address=GroupAddress("1/2/2"), - payload=DPTArray(DPT2ByteFloat().to_knx(23.00)), + payload=GroupValueWrite(DPTArray(DPT2ByteFloat().to_knx(23.00))), ), ) self.loop.run_until_complete(xknx.devices.process(_telegram)) @@ -556,7 +574,10 @@ def test_target_temperature_up(self): _telegram = xknx.telegrams.get_nowait() self.assertEqual( _telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTArray(40)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray(40)), + ), ) self.loop.run_until_complete(xknx.devices.process(_telegram)) _telegram = xknx.telegrams.get_nowait() @@ -564,7 +585,7 @@ def test_target_temperature_up(self): _telegram, Telegram( destination_address=GroupAddress("1/2/2"), - payload=DPTArray(DPT2ByteFloat().to_knx(24.00)), + payload=GroupValueWrite(DPTArray(DPT2ByteFloat().to_knx(24.00))), ), ) self.loop.run_until_complete(xknx.devices.process(_telegram)) @@ -576,7 +597,10 @@ def test_target_temperature_up(self): _telegram = xknx.telegrams.get_nowait() self.assertEqual( _telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTArray(35)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray(35)), + ), ) self.loop.run_until_complete(xknx.devices.process(_telegram)) _telegram = xknx.telegrams.get_nowait() @@ -584,7 +608,7 @@ def test_target_temperature_up(self): _telegram, Telegram( destination_address=GroupAddress("1/2/2"), - payload=DPTArray(DPT2ByteFloat().to_knx(23.50)), + payload=GroupValueWrite(DPTArray(DPT2ByteFloat().to_knx(23.50))), ), ) self.loop.run_until_complete(xknx.devices.process(_telegram)) @@ -619,7 +643,10 @@ def test_target_temperature_down(self): self.assertEqual( _telegram, # DEFAULT_TEMPERATURE_STEP is 0.1 -> payload = setpoint_shift * 10 - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTArray(10)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray(10)), + ), ) self.loop.run_until_complete(xknx.devices.process(_telegram)) @@ -630,7 +657,7 @@ def test_target_temperature_down(self): _telegram, Telegram( destination_address=GroupAddress("1/2/2"), - payload=DPTArray(DPT2ByteFloat().to_knx(23.00)), + payload=GroupValueWrite(DPTArray(DPT2ByteFloat().to_knx(23.00))), ), ) self.loop.run_until_complete(xknx.devices.process(_telegram)) @@ -642,7 +669,10 @@ def test_target_temperature_down(self): _telegram = xknx.telegrams.get_nowait() self.assertEqual( _telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTArray(0xF1)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray(0xF1)), + ), ) # -15 self.loop.run_until_complete(xknx.devices.process(_telegram)) _telegram = xknx.telegrams.get_nowait() @@ -650,7 +680,7 @@ def test_target_temperature_down(self): _telegram, Telegram( destination_address=GroupAddress("1/2/2"), - payload=DPTArray(DPT2ByteFloat().to_knx(20.50)), + payload=GroupValueWrite(DPTArray(DPT2ByteFloat().to_knx(20.50))), ), ) self.loop.run_until_complete(xknx.devices.process(_telegram)) @@ -662,7 +692,10 @@ def test_target_temperature_down(self): _telegram = xknx.telegrams.get_nowait() self.assertEqual( _telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTArray(0xE2)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray(0xE2)), + ), ) # -30 self.loop.run_until_complete(xknx.devices.process(_telegram)) _telegram = xknx.telegrams.get_nowait() @@ -670,7 +703,7 @@ def test_target_temperature_down(self): _telegram, Telegram( destination_address=GroupAddress("1/2/2"), - payload=DPTArray(DPT2ByteFloat().to_knx(19.00)), + payload=GroupValueWrite(DPTArray(DPT2ByteFloat().to_knx(19.00))), ), ) self.loop.run_until_complete(xknx.devices.process(_telegram)) @@ -709,7 +742,10 @@ def test_target_temperature_modified_step(self): self.assertEqual( _telegram, # temperature_step is 0.5 -> payload = setpoint_shift * 2 - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTArray(6)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray(6)), + ), ) self.loop.run_until_complete(climate.target_temperature.set(23.00)) @@ -720,7 +756,7 @@ def test_target_temperature_modified_step(self): _telegram, Telegram( destination_address=GroupAddress("1/2/2"), - payload=DPTArray(DPT2ByteFloat().to_knx(23.00)), + payload=GroupValueWrite(DPTArray(DPT2ByteFloat().to_knx(23.00))), ), ) self.assertEqual(climate.base_temperature, 20.00) @@ -730,7 +766,10 @@ def test_target_temperature_modified_step(self): self.loop.run_until_complete(xknx.devices.process(_telegram)) self.assertEqual( _telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTArray(8)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray(8)), + ), ) _telegram = xknx.telegrams.get_nowait() self.loop.run_until_complete(xknx.devices.process(_telegram)) @@ -738,7 +777,7 @@ def test_target_temperature_modified_step(self): _telegram, Telegram( destination_address=GroupAddress("1/2/2"), - payload=DPTArray(DPT2ByteFloat().to_knx(24.00)), + payload=GroupValueWrite(DPTArray(DPT2ByteFloat().to_knx(24.00))), ), ) self.assertEqual(climate.target_temperature.value, 24.00) @@ -771,7 +810,7 @@ def test_base_temperature(self): _telegram, Telegram( destination_address=GroupAddress("1/2/2"), - payload=DPTArray(DPT2ByteFloat().to_knx(21.00)), + payload=GroupValueWrite(DPTArray(DPT2ByteFloat().to_knx(21.00))), ), ) self.assertFalse(climate.initialized_for_setpoint_shift_calculations) @@ -785,7 +824,10 @@ def test_base_temperature(self): self.assertEqual( _telegram, # DEFAULT_TEMPERATURE_STEP is 0.1 -> payload = setpoint_shift * 10 - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTArray(10)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray(10)), + ), ) self.assertTrue(climate.initialized_for_setpoint_shift_calculations) self.assertEqual(climate.base_temperature, 20.00) @@ -799,7 +841,10 @@ def test_base_temperature(self): self.assertEqual( _telegram, # DEFAULT_TEMPERATURE_STEP is 0.1 -> payload = setpoint_shift * 10 - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTArray(20)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray(20)), + ), ) _telegram = xknx.telegrams.get_nowait() self.loop.run_until_complete(xknx.devices.process(_telegram)) @@ -826,7 +871,7 @@ def test_target_temperature_step_mode_9002(self): climate.target_temperature.process( Telegram( destination_address=GroupAddress("1/2/2"), - payload=DPTArray(DPT2ByteFloat().to_knx(20.00)), + payload=GroupValueWrite(DPTArray(DPT2ByteFloat().to_knx(20.00))), ) ) ) @@ -841,7 +886,7 @@ def test_target_temperature_step_mode_9002(self): _telegram, Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray((0x00, 0x00)), + payload=GroupValueWrite(DPTArray((0x00, 0x00))), ), ) # 0 # - 0.6 °C = 19.4 @@ -853,7 +898,7 @@ def test_target_temperature_step_mode_9002(self): _telegram, Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray((0x87, 0xC4)), + payload=GroupValueWrite(DPTArray((0x87, 0xC4))), ), ) # -0.6 # simulate incoming new target temperature for next calculation @@ -861,7 +906,7 @@ def test_target_temperature_step_mode_9002(self): climate.target_temperature.process( Telegram( destination_address=GroupAddress("1/2/2"), - payload=DPTArray(DPT2ByteFloat().to_knx(19.40)), + payload=GroupValueWrite(DPTArray(DPT2ByteFloat().to_knx(19.40))), ) ) ) @@ -874,7 +919,7 @@ def test_target_temperature_step_mode_9002(self): _telegram, Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray((0x01, 0x5E)), + payload=GroupValueWrite(DPTArray((0x01, 0x5E))), ), ) # +3.5 @@ -927,11 +972,7 @@ def test_sync(self): self.assertEqual(xknx.telegrams.qsize(), 1) telegram1 = xknx.telegrams.get_nowait() self.assertEqual( - telegram1, - Telegram( - destination_address=GroupAddress("1/2/3"), - telegramtype=TelegramType.GROUP_READ, - ), + telegram1, Telegram(GroupAddress("1/2/3"), payload=GroupValueRead()) ) def test_sync_operation_mode(self): @@ -947,11 +988,7 @@ def test_sync_operation_mode(self): self.assertEqual(xknx.telegrams.qsize(), 1) telegram1 = xknx.telegrams.get_nowait() self.assertEqual( - telegram1, - Telegram( - destination_address=GroupAddress("1/2/4"), - telegramtype=TelegramType.GROUP_READ, - ), + telegram1, Telegram(GroupAddress("1/2/4"), payload=GroupValueRead()) ) def test_sync_controller_status(self): @@ -967,11 +1004,7 @@ def test_sync_controller_status(self): self.assertEqual(xknx.telegrams.qsize(), 1) telegram1 = xknx.telegrams.get_nowait() self.assertEqual( - telegram1, - Telegram( - destination_address=GroupAddress("1/2/24"), - telegramtype=TelegramType.GROUP_READ, - ), + telegram1, Telegram(GroupAddress("1/2/24"), payload=GroupValueRead()) ) def test_sync_controller_mode(self): @@ -987,11 +1020,7 @@ def test_sync_controller_mode(self): self.assertEqual(xknx.telegrams.qsize(), 1) telegram1 = xknx.telegrams.get_nowait() self.assertEqual( - telegram1, - Telegram( - destination_address=GroupAddress("1/2/14"), - telegramtype=TelegramType.GROUP_READ, - ), + telegram1, Telegram(GroupAddress("1/2/14"), payload=GroupValueRead()) ) def test_sync_operation_mode_state(self): @@ -1013,22 +1042,13 @@ def test_sync_operation_mode_state(self): telegrams = [] for _ in range(3): telegrams.append(xknx.telegrams.get_nowait()) - self.assertSetEqual( - set(telegrams), - { - Telegram( - destination_address=GroupAddress("1/2/5"), - telegramtype=TelegramType.GROUP_READ, - ), - Telegram( - destination_address=GroupAddress("1/2/6"), - telegramtype=TelegramType.GROUP_READ, - ), - Telegram( - destination_address=GroupAddress("1/2/14"), - telegramtype=TelegramType.GROUP_READ, - ), - }, + self.assertListEqual( + telegrams, + [ + Telegram(GroupAddress("1/2/5"), payload=GroupValueRead()), + Telegram(GroupAddress("1/2/6"), payload=GroupValueRead()), + Telegram(GroupAddress("1/2/14"), payload=GroupValueRead()), + ], ) def test_sync_heat_cool(self): @@ -1044,11 +1064,7 @@ def test_sync_heat_cool(self): self.assertEqual(xknx.telegrams.qsize(), 1) telegram1 = xknx.telegrams.get_nowait() self.assertEqual( - telegram1, - Telegram( - destination_address=GroupAddress("1/2/15"), - telegramtype=TelegramType.GROUP_READ, - ), + telegram1, Telegram(GroupAddress("1/2/15"), payload=GroupValueRead()) ) # @@ -1059,8 +1075,10 @@ def test_process_temperature(self): xknx = XKNX() climate = Climate(xknx, "TestClimate", group_address_temperature="1/2/3") - telegram = Telegram(destination_address=GroupAddress("1/2/3")) - telegram.payload = DPTArray(DPTTemperature().to_knx(21.34)) + telegram = Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray(DPTTemperature().to_knx(21.34))), + ) self.loop.run_until_complete(climate.process(telegram)) self.assertEqual(climate.temperature.value, 21.34) @@ -1074,15 +1092,21 @@ def test_process_operation_mode(self): group_address_controller_status="1/2/3", ) for operation_mode in DPT_20102_MODES: - telegram = Telegram(destination_address=GroupAddress("1/2/5")) - telegram.payload = DPTArray(DPTHVACMode.to_knx(operation_mode)) + telegram = Telegram( + destination_address=GroupAddress("1/2/5"), + payload=GroupValueWrite(DPTArray(DPTHVACMode.to_knx(operation_mode))), + ) self.loop.run_until_complete(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(destination_address=GroupAddress("1/2/3")) - telegram.payload = DPTArray(DPTControllerStatus.to_knx(operation_mode)) + telegram = Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite( + DPTArray(DPTControllerStatus.to_knx(operation_mode)) + ), + ) self.loop.run_until_complete(climate_mode.process(telegram)) self.assertEqual(climate_mode.operation_mode, operation_mode) @@ -1093,8 +1117,12 @@ def test_process_controller_mode(self): xknx, "TestClimate", group_address_controller_mode="1/2/5" ) for _, controller_mode in DPTHVACContrMode.SUPPORTED_MODES.items(): - telegram = Telegram(destination_address=GroupAddress("1/2/5")) - telegram.payload = DPTArray(DPTHVACContrMode.to_knx(controller_mode)) + telegram = Telegram( + destination_address=GroupAddress("1/2/5"), + payload=GroupValueWrite( + DPTArray(DPTHVACContrMode.to_knx(controller_mode)) + ), + ) self.loop.run_until_complete(climate_mode.process(telegram)) self.assertEqual(climate_mode.controller_mode, controller_mode) @@ -1108,7 +1136,8 @@ def test_process_controller_status_wrong_payload(self): group_address_controller_status="1/2/3", ) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(climate_mode.process(telegram)) @@ -1123,7 +1152,8 @@ def test_process_controller_status_payload_invalid_length(self): group_address_controller_status="1/2/3", ) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((23, 24)) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((23, 24))), ) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(climate_mode.process(telegram)) @@ -1138,7 +1168,8 @@ def test_process_operation_mode_wrong_payload(self): group_address_controller_status="1/2/3", ) telegram = Telegram( - destination_address=GroupAddress("1/2/5"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/5"), + payload=GroupValueWrite(DPTBinary(1)), ) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(climate_mode.process(telegram)) @@ -1153,7 +1184,8 @@ def test_process_operation_mode_payload_invalid_length(self): group_address_controller_status="1/2/3", ) telegram = Telegram( - destination_address=GroupAddress("1/2/5"), payload=DPTArray((23, 24)) + destination_address=GroupAddress("1/2/5"), + payload=GroupValueWrite(DPTArray((23, 24))), ) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(climate_mode.process(telegram)) @@ -1172,8 +1204,10 @@ async def async_after_update_callback(device): climate.register_device_updated_cb(async_after_update_callback) - telegram = Telegram(destination_address=GroupAddress("1/2/3")) - telegram.payload = DPTArray(DPTTemperature().to_knx(21.34)) + telegram = Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray(DPTTemperature().to_knx(21.34))), + ) self.loop.run_until_complete(climate.process(telegram)) after_update_callback.assert_called_with(climate) @@ -1187,13 +1221,17 @@ def test_process_heat_cool(self): group_address_heat_cool_state="1/2/15", ) - telegram = Telegram(destination_address=GroupAddress("1/2/14")) - telegram.payload = DPTBinary(False) + telegram = Telegram( + destination_address=GroupAddress("1/2/14"), + payload=GroupValueWrite(DPTBinary(False)), + ) self.loop.run_until_complete(climate_mode.process(telegram)) self.assertEqual(climate_mode.controller_mode, HVACControllerMode.COOL) - telegram = Telegram(destination_address=GroupAddress("1/2/14")) - telegram.payload = DPTBinary(True) + telegram = Telegram( + destination_address=GroupAddress("1/2/14"), + payload=GroupValueWrite(DPTBinary(True)), + ) self.loop.run_until_complete(climate_mode.process(telegram)) self.assertEqual(climate_mode.controller_mode, HVACControllerMode.HEAT) @@ -1349,16 +1387,20 @@ def test_process_power_status(self): """Test process / reading telegrams from telegram queue. Test if DPT20.105 controller mode is set correctly.""" xknx = XKNX() climate = Climate(xknx, "TestClimate", group_address_on_off="1/2/2") - telegram = Telegram(destination_address=GroupAddress("1/2/2")) - telegram.payload = DPTBinary(1) + telegram = Telegram( + destination_address=GroupAddress("1/2/2"), + payload=GroupValueWrite(DPTBinary(1)), + ) self.loop.run_until_complete(climate.process(telegram)) self.assertEqual(climate.is_on, True) climate_inv = Climate( xknx, "TestClimate", group_address_on_off="1/2/2", on_off_invert=True ) - telegram = Telegram(destination_address=GroupAddress("1/2/2")) - telegram.payload = DPTBinary(1) + telegram = Telegram( + destination_address=GroupAddress("1/2/2"), + payload=GroupValueWrite(DPTBinary(1)), + ) self.loop.run_until_complete(climate_inv.process(telegram)) self.assertEqual(climate_inv.is_on, False) @@ -1373,7 +1415,8 @@ def test_power_on_off(self): self.assertEqual( _telegram, Telegram( - destination_address=GroupAddress("1/2/2"), payload=DPTBinary(True) + destination_address=GroupAddress("1/2/2"), + payload=GroupValueWrite(DPTBinary(True)), ), ) self.loop.run_until_complete(climate.turn_off()) @@ -1383,7 +1426,8 @@ def test_power_on_off(self): self.assertEqual( _telegram, Telegram( - destination_address=GroupAddress("1/2/2"), payload=DPTBinary(False) + destination_address=GroupAddress("1/2/2"), + payload=GroupValueWrite(DPTBinary(False)), ), ) @@ -1397,7 +1441,8 @@ def test_power_on_off(self): self.assertEqual( _telegram, Telegram( - destination_address=GroupAddress("1/2/2"), payload=DPTBinary(False) + destination_address=GroupAddress("1/2/2"), + payload=GroupValueWrite(DPTBinary(False)), ), ) self.loop.run_until_complete(climate_inv.turn_off()) @@ -1407,6 +1452,7 @@ def test_power_on_off(self): self.assertEqual( _telegram, Telegram( - destination_address=GroupAddress("1/2/2"), payload=DPTBinary(True) + destination_address=GroupAddress("1/2/2"), + payload=GroupValueWrite(DPTBinary(True)), ), ) diff --git a/test/devices_tests/cover_test.py b/test/devices_tests/cover_test.py index c70353379..22bcbd029 100644 --- a/test/devices_tests/cover_test.py +++ b/test/devices_tests/cover_test.py @@ -7,7 +7,7 @@ from xknx import XKNX from xknx.devices import Cover from xknx.dpt import DPTArray, DPTBinary -from xknx.telegram import GroupAddress, Telegram, TelegramType +from xknx.telegram import GroupAddress, GroupValueRead, GroupValueWrite, Telegram class TestCover(unittest.TestCase): @@ -129,8 +129,7 @@ def test_sync(self): self.assertEqual( telegram1, Telegram( - destination_address=GroupAddress("1/2/3"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/3"), payload=GroupValueRead() ), ) @@ -151,8 +150,7 @@ def test_sync_state(self): self.assertEqual( telegram1, Telegram( - destination_address=GroupAddress("1/2/4"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/4"), payload=GroupValueRead() ), ) @@ -173,16 +171,14 @@ def test_sync_angle(self): self.assertEqual( telegram1, Telegram( - destination_address=GroupAddress("1/2/3"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/3"), payload=GroupValueRead() ), ) telegram2 = xknx.telegrams.get_nowait() self.assertEqual( telegram2, Telegram( - destination_address=GroupAddress("1/2/4"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/4"), payload=GroupValueRead() ), ) @@ -203,8 +199,7 @@ def test_sync_angle_state(self): self.assertEqual( telegram1, Telegram( - destination_address=GroupAddress("1/2/4"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/4"), payload=GroupValueRead() ), ) @@ -228,7 +223,10 @@ def test_set_up(self): # DPT 1.008 - 0:up 1:down self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/1"), payload=DPTBinary(0)), + Telegram( + destination_address=GroupAddress("1/2/1"), + payload=GroupValueWrite(DPTBinary(0)), + ), ) # @@ -250,7 +248,10 @@ def test_set_short_down(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/1"), payload=DPTBinary(1)), + Telegram( + destination_address=GroupAddress("1/2/1"), + payload=GroupValueWrite(DPTBinary(1)), + ), ) # @@ -273,7 +274,10 @@ def test_set_down_inverted(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/1"), payload=DPTBinary(0)), + Telegram( + destination_address=GroupAddress("1/2/1"), + payload=GroupValueWrite(DPTBinary(0)), + ), ) # @@ -296,7 +300,10 @@ def test_set_short_up(self): # DPT 1.008 - 0:up 1:down self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/2"), payload=DPTBinary(0)), + Telegram( + destination_address=GroupAddress("1/2/2"), + payload=GroupValueWrite(DPTBinary(0)), + ), ) # @@ -320,7 +327,10 @@ def test_set_up_inverted(self): # DPT 1.008 - 0:up 1:down self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/2"), payload=DPTBinary(1)), + Telegram( + destination_address=GroupAddress("1/2/2"), + payload=GroupValueWrite(DPTBinary(1)), + ), ) # @@ -343,7 +353,10 @@ def test_set_down(self): # DPT 1.008 - 0:up 1:down self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/2"), payload=DPTBinary(1)), + Telegram( + destination_address=GroupAddress("1/2/2"), + payload=GroupValueWrite(DPTBinary(1)), + ), ) # @@ -365,7 +378,10 @@ def test_stop(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/2"), payload=DPTBinary(1)), + Telegram( + destination_address=GroupAddress("1/2/2"), + payload=GroupValueWrite(DPTBinary(1)), + ), ) cover_manual_stop = Cover( @@ -382,7 +398,10 @@ def test_stop(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/0"), payload=DPTBinary(1)), + Telegram( + destination_address=GroupAddress("1/2/0"), + payload=GroupValueWrite(DPTBinary(1)), + ), ) # @@ -404,7 +423,10 @@ def test_position(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTArray(0x80)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray(0x80)), + ), ) def test_position_without_position_address_up(self): @@ -424,7 +446,10 @@ def test_position_without_position_address_up(self): # DPT 1.008 - 0:up 1:down self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/1"), payload=DPTBinary(0)), + Telegram( + destination_address=GroupAddress("1/2/1"), + payload=GroupValueWrite(DPTBinary(0)), + ), ) self.assertEqual(cover.travelcalculator.travel_to_position, 50) self.assertTrue(cover.is_opening()) @@ -449,7 +474,10 @@ def test_position_without_position_address_down(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/1"), payload=DPTBinary(1)), + Telegram( + destination_address=GroupAddress("1/2/1"), + payload=GroupValueWrite(DPTBinary(1)), + ), ) self.assertEqual(cover.travelcalculator.travel_to_position, 80) self.assertTrue(cover.is_closing()) @@ -480,7 +508,10 @@ def test_position_without_position_address_uninitialized_up(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/1"), payload=DPTBinary(0)), + Telegram( + destination_address=GroupAddress("1/2/1"), + payload=GroupValueWrite(DPTBinary(0)), + ), ) def test_position_without_position_address_uninitialized_down(self): @@ -506,7 +537,10 @@ def test_position_without_position_address_uninitialized_down(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/1"), payload=DPTBinary(1)), + Telegram( + destination_address=GroupAddress("1/2/1"), + payload=GroupValueWrite(DPTBinary(1)), + ), ) def test_angle(self): @@ -528,7 +562,8 @@ def test_angle(self): self.assertEqual( telegram, Telegram( - destination_address=GroupAddress("1/4/18"), payload=DPTArray(0x80) + destination_address=GroupAddress("1/4/18"), + payload=GroupValueWrite(DPTArray(0x80)), ), ) @@ -564,14 +599,14 @@ def test_process_position(self): ) # initial position process - position is unknown so this is the new state - not moving telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray(213) + GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray(213)) ) self.loop.run_until_complete(cover.process(telegram)) self.assertEqual(cover.current_position(), 84) self.assertFalse(cover.is_traveling()) # state telegram updates current position - we are not moving so this is new state - not moving telegram = Telegram( - destination_address=GroupAddress("1/2/4"), payload=DPTArray(42) + GroupAddress("1/2/4"), payload=GroupValueWrite(DPTArray(42)) ) self.loop.run_until_complete(cover.process(telegram)) self.assertEqual(cover.current_position(), 16) @@ -579,7 +614,7 @@ def test_process_position(self): self.assertEqual(cover.travelcalculator.travel_to_position, 16) # new position - movement starts telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray(255) + GroupAddress("1/2/3"), payload=GroupValueWrite(DPTArray(255)) ) self.loop.run_until_complete(cover.process(telegram)) self.assertEqual(cover.current_position(), 16) @@ -587,7 +622,7 @@ def test_process_position(self): self.assertEqual(cover.travelcalculator.travel_to_position, 100) # new state while moving - movement goes on; travelcalculator updated telegram = Telegram( - destination_address=GroupAddress("1/2/4"), payload=DPTArray(213) + GroupAddress("1/2/4"), payload=GroupValueWrite(DPTArray(213)) ) self.loop.run_until_complete(cover.process(telegram)) self.assertEqual(cover.current_position(), 84) @@ -606,7 +641,7 @@ def test_process_angle(self): group_address_angle_state="1/2/4", ) telegram = Telegram( - destination_address=GroupAddress("1/2/4"), payload=DPTArray(42) + GroupAddress("1/2/4"), payload=GroupValueWrite(DPTArray(42)) ) self.loop.run_until_complete(cover.process(telegram)) self.assertEqual(cover.current_angle(), 16) @@ -620,7 +655,7 @@ def test_process_up(self): cover.travelcalculator.set_position(50) self.assertFalse(cover.is_traveling()) telegram = Telegram( - destination_address=GroupAddress("1/2/1"), payload=DPTBinary(0) + GroupAddress("1/2/1"), payload=GroupValueWrite(DPTBinary(0)) ) self.loop.run_until_complete(cover.process(telegram)) self.assertTrue(cover.is_opening()) @@ -634,7 +669,7 @@ def test_process_down(self): cover.travelcalculator.set_position(50) self.assertFalse(cover.is_traveling()) telegram = Telegram( - destination_address=GroupAddress("1/2/1"), payload=DPTBinary(1) + GroupAddress("1/2/1"), payload=GroupValueWrite(DPTBinary(1)) ) self.loop.run_until_complete(cover.process(telegram)) self.assertTrue(cover.is_closing()) @@ -652,7 +687,7 @@ def test_process_stop(self): self.loop.run_until_complete(cover.set_down()) self.assertTrue(cover.is_traveling()) telegram = Telegram( - destination_address=GroupAddress("1/2/2"), payload=DPTBinary(1) + GroupAddress("1/2/2"), payload=GroupValueWrite(DPTBinary(1)) ) self.loop.run_until_complete(cover.process(telegram)) self.assertFalse(cover.is_traveling()) @@ -670,7 +705,7 @@ def test_process_short_stop(self): self.loop.run_until_complete(cover.set_down()) self.assertTrue(cover.is_traveling()) telegram = Telegram( - destination_address=GroupAddress("1/2/2"), payload=DPTBinary(1) + GroupAddress("1/2/2"), payload=GroupValueWrite(DPTBinary(1)) ) self.loop.run_until_complete(cover.process(telegram)) self.assertFalse(cover.is_traveling()) @@ -708,14 +743,15 @@ async def async_after_update_callback(device): ]: with self.subTest(address=address, feature=feature): telegram = Telegram( - destination_address=GroupAddress(address), payload=payload + destination_address=GroupAddress(address), + payload=GroupValueWrite(payload), ) self.loop.run_until_complete(cover.process(telegram)) after_update_callback.assert_called_with(cover) after_update_callback.reset_mock() # Stop only when cover is travelling telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + GroupAddress("1/2/3"), payload=GroupValueWrite(DPTBinary(1)) ) self.loop.run_until_complete(cover.process(telegram)) after_update_callback.assert_not_called() diff --git a/test/devices_tests/datetime_test.py b/test/devices_tests/datetime_test.py index c47cbece6..81126a94e 100644 --- a/test/devices_tests/datetime_test.py +++ b/test/devices_tests/datetime_test.py @@ -7,7 +7,13 @@ from xknx import XKNX from xknx.devices import DateTime from xknx.dpt import DPTArray -from xknx.telegram import GroupAddress, Telegram, TelegramType +from xknx.telegram import ( + GroupAddress, + GroupValueRead, + GroupValueResponse, + GroupValueWrite, + Telegram, +) class TestDateTime(unittest.TestCase): @@ -43,10 +49,9 @@ def test_sync_datetime(self): self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() self.assertEqual(telegram.destination_address, GroupAddress("1/2/3")) - self.assertEqual(telegram.telegramtype, TelegramType.GROUP_WRITE) - self.assertEqual(len(telegram.payload.value), 8) + self.assertEqual(len(telegram.payload.dpt.value), 8) self.assertEqual( - telegram.payload.value, (0x75, 0x01, 0x07, 0xE9, 0x0D, 0x0E, 0x20, 0x80) + telegram.payload.dpt.value, (0x75, 0x01, 0x07, 0xE9, 0x0D, 0x0E, 0x20, 0x80) ) # @@ -69,9 +74,8 @@ def test_sync_date(self): telegram = xknx.telegrams.get_nowait() self.assertEqual(telegram.destination_address, GroupAddress("1/2/3")) - self.assertEqual(telegram.telegramtype, TelegramType.GROUP_WRITE) - self.assertEqual(len(telegram.payload.value), 3) - self.assertEqual(telegram.payload.value, (0x07, 0x01, 0x11)) + self.assertEqual(len(telegram.payload.dpt.value), 3) + self.assertEqual(telegram.payload.dpt.value, (0x07, 0x01, 0x11)) # # SYNC Time @@ -93,9 +97,8 @@ def test_sync_time(self): telegram = xknx.telegrams.get_nowait() self.assertEqual(telegram.destination_address, GroupAddress("1/2/3")) - self.assertEqual(telegram.telegramtype, TelegramType.GROUP_WRITE) - self.assertEqual(len(telegram.payload.value), 3) - self.assertEqual(telegram.payload.value, (0xE9, 0x0D, 0x0E)) + self.assertEqual(len(telegram.payload.dpt.value), 3) + self.assertEqual(telegram.payload.dpt.value, (0xE9, 0x0D, 0x0E)) # # PROCESS @@ -111,8 +114,7 @@ def test_process_read(self): ) telegram_read = Telegram( - destination_address=GroupAddress("1/2/3"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/3"), payload=GroupValueRead() ) with patch("time.localtime") as mock_time: mock_time.return_value = time.struct_time([2017, 1, 7, 9, 13, 14, 6, 0, 0]) @@ -127,8 +129,7 @@ def test_process_read(self): telegram, Telegram( destination_address=GroupAddress("1/2/3"), - telegramtype=TelegramType.GROUP_RESPONSE, - payload=DPTArray((0xE9, 0xD, 0xE)), + payload=GroupValueResponse(DPTArray((0xE9, 0xD, 0xE))), ), ) diff --git a/test/devices_tests/device_test.py b/test/devices_tests/device_test.py index c925e0b43..a4d292ff3 100644 --- a/test/devices_tests/device_test.py +++ b/test/devices_tests/device_test.py @@ -6,7 +6,13 @@ from xknx import XKNX from xknx.devices import Device, Sensor from xknx.dpt import DPTArray -from xknx.telegram import GroupAddress, Telegram, TelegramType +from xknx.telegram import ( + GroupAddress, + GroupValueRead, + GroupValueResponse, + GroupValueWrite, + Telegram, +) class TestDevice(unittest.TestCase): @@ -102,9 +108,7 @@ def test_process(self): fut.set_result(None) mock_group_read.return_value = fut telegram = Telegram( - destination_address=GroupAddress("1/2/1"), - payload=DPTArray((0x01, 0x02)), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/1"), payload=GroupValueRead() ) self.loop.run_until_complete(device.process(telegram)) mock_group_read.assert_called_with(telegram) @@ -115,8 +119,7 @@ def test_process(self): mock_group_write.return_value = fut telegram = Telegram( destination_address=GroupAddress("1/2/1"), - payload=DPTArray((0x01, 0x02)), - telegramtype=TelegramType.GROUP_WRITE, + payload=GroupValueWrite(DPTArray((0x01, 0x02))), ) self.loop.run_until_complete(device.process(telegram)) mock_group_write.assert_called_with(telegram) @@ -127,8 +130,7 @@ def test_process(self): mock_group_response.return_value = fut telegram = Telegram( destination_address=GroupAddress("1/2/1"), - payload=DPTArray((0x01, 0x02)), - telegramtype=TelegramType.GROUP_RESPONSE, + payload=GroupValueResponse(DPTArray((0x01, 0x02))), ) self.loop.run_until_complete(device.process(telegram)) mock_group_response.assert_called_with(telegram) diff --git a/test/devices_tests/expose_sensor_test.py b/test/devices_tests/expose_sensor_test.py index c7fbafe17..5d2fc6886 100644 --- a/test/devices_tests/expose_sensor_test.py +++ b/test/devices_tests/expose_sensor_test.py @@ -6,7 +6,13 @@ from xknx import XKNX from xknx.devices import ExposeSensor from xknx.dpt import DPTArray, DPTBinary -from xknx.telegram import GroupAddress, Telegram, TelegramType +from xknx.telegram import ( + GroupAddress, + GroupValueRead, + GroupValueResponse, + GroupValueWrite, + Telegram, +) class TestExposeSensor(unittest.TestCase): @@ -73,8 +79,7 @@ def test_set_binary(self): telegram, Telegram( destination_address=GroupAddress("1/2/3"), - telegramtype=TelegramType.GROUP_WRITE, - payload=DPTBinary(0), + payload=GroupValueWrite(DPTBinary(0)), ), ) @@ -92,8 +97,7 @@ def test_set_percent(self): telegram, Telegram( destination_address=GroupAddress("1/2/3"), - telegramtype=TelegramType.GROUP_WRITE, - payload=DPTArray((0xBF,)), + payload=GroupValueWrite(DPTArray((0xBF,))), ), ) @@ -110,8 +114,7 @@ def test_set_temperature(self): telegram, Telegram( destination_address=GroupAddress("1/2/3"), - telegramtype=TelegramType.GROUP_WRITE, - payload=DPTArray((0x0C, 0x1A)), + payload=GroupValueWrite(DPTArray((0x0C, 0x1A))), ), ) @@ -126,8 +129,7 @@ def test_process_binary(self): ) expose_sensor.sensor_value.payload = DPTBinary(1) - telegram = Telegram(destination_address=GroupAddress("1/2/3")) - telegram.telegramtype = TelegramType.GROUP_READ + telegram = Telegram(GroupAddress("1/2/3"), payload=GroupValueRead()) self.loop.run_until_complete(expose_sensor.process(telegram)) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() @@ -135,8 +137,7 @@ def test_process_binary(self): telegram, Telegram( destination_address=GroupAddress("1/2/3"), - telegramtype=TelegramType.GROUP_RESPONSE, - payload=DPTBinary(True), + payload=GroupValueResponse(DPTBinary(True)), ), ) @@ -148,8 +149,7 @@ def test_process_percent(self): ) expose_sensor.sensor_value.payload = DPTArray((0x40,)) - telegram = Telegram(destination_address=GroupAddress("1/2/3")) - telegram.telegramtype = TelegramType.GROUP_READ + telegram = Telegram(GroupAddress("1/2/3"), payload=GroupValueRead()) self.loop.run_until_complete(expose_sensor.process(telegram)) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() @@ -157,8 +157,7 @@ def test_process_percent(self): telegram, Telegram( destination_address=GroupAddress("1/2/3"), - telegramtype=TelegramType.GROUP_RESPONSE, - payload=DPTArray((0x40,)), + payload=GroupValueResponse(DPTArray((0x40,))), ), ) @@ -170,8 +169,7 @@ def test_process_temperature(self): ) expose_sensor.sensor_value.payload = DPTArray((0x0C, 0x1A)) - telegram = Telegram(destination_address=GroupAddress("1/2/3")) - telegram.telegramtype = TelegramType.GROUP_READ + telegram = Telegram(GroupAddress("1/2/3"), payload=GroupValueRead()) self.loop.run_until_complete(expose_sensor.process(telegram)) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() @@ -179,8 +177,7 @@ def test_process_temperature(self): telegram, Telegram( destination_address=GroupAddress("1/2/3"), - telegramtype=TelegramType.GROUP_RESPONSE, - payload=DPTArray((0x0C, 0x1A)), + payload=GroupValueResponse(DPTArray((0x0C, 0x1A))), ), ) diff --git a/test/devices_tests/fan_test.py b/test/devices_tests/fan_test.py index f9715e6ba..b120b96be 100644 --- a/test/devices_tests/fan_test.py +++ b/test/devices_tests/fan_test.py @@ -7,7 +7,7 @@ from xknx.devices import Fan from xknx.dpt import DPTArray, DPTBinary from xknx.exceptions import CouldNotParseTelegram -from xknx.telegram import GroupAddress, Telegram, TelegramType +from xknx.telegram import GroupAddress, GroupValueRead, GroupValueWrite, Telegram class TestFan(unittest.TestCase): @@ -39,8 +39,7 @@ def test_sync(self): self.assertEqual( telegram1, Telegram( - destination_address=GroupAddress("1/2/3"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/3"), payload=GroupValueRead() ), ) @@ -64,8 +63,7 @@ def test_sync_state_address(self): self.assertEqual( telegram1, Telegram( - destination_address=GroupAddress("1/2/4"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/4"), payload=GroupValueRead() ), ) @@ -83,7 +81,10 @@ def test_set_speed(self): # 140 is 55% as byte (0...255) self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTArray(140)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray(140)), + ), ) # @@ -97,7 +98,8 @@ def test_process_speed(self): # 140 is 55% as byte (0...255) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray(140) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray(140)), ) self.loop.run_until_complete(fan.process(telegram)) self.assertEqual(fan.current_speed, 55) @@ -107,7 +109,8 @@ def test_process_speed_wrong_payload(self): # pylint: disable=invalid-name xknx = XKNX() fan = Fan(xknx, name="TestFan", group_address_speed="1/2/3") telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(fan.process(telegram)) @@ -118,7 +121,8 @@ def test_process_fan_payload_invalid_length(self): xknx = XKNX() fan = Fan(xknx, name="TestFan", group_address_speed="1/2/3") telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((23, 24)) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((23, 24))), ) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(fan.process(telegram)) diff --git a/test/devices_tests/light_test.py b/test/devices_tests/light_test.py index 0d6e8b104..66def1f68 100644 --- a/test/devices_tests/light_test.py +++ b/test/devices_tests/light_test.py @@ -7,7 +7,7 @@ from xknx.devices import Light from xknx.dpt import DPTArray, DPTBinary from xknx.exceptions import CouldNotParseTelegram -from xknx.telegram import GroupAddress, Telegram, TelegramType +from xknx.telegram import GroupAddress, GroupValueRead, GroupValueWrite, Telegram class TestLight(unittest.TestCase): @@ -156,33 +156,27 @@ def test_sync(self): test_telegrams = [ Telegram( - destination_address=GroupAddress("1/2/3"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/3"), payload=GroupValueRead() ), Telegram( - destination_address=GroupAddress("1/2/5"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/5"), payload=GroupValueRead() ), Telegram( - destination_address=GroupAddress("1/2/6"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/6"), payload=GroupValueRead() ), Telegram( - destination_address=GroupAddress("1/2/7"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/9"), payload=GroupValueRead() ), Telegram( - destination_address=GroupAddress("1/2/8"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/7"), payload=GroupValueRead() ), Telegram( - destination_address=GroupAddress("1/2/9"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/8"), payload=GroupValueRead() ), ] - self.assertEqual(len(set(telegrams)), 6) - self.assertEqual(set(telegrams), set(test_telegrams)) + self.assertEqual(len(telegrams), 6) + self.assertListEqual(telegrams, test_telegrams) # # SYNC WITH STATE ADDRESS @@ -216,33 +210,27 @@ def test_sync_state_address(self): test_telegrams = [ Telegram( - destination_address=GroupAddress("1/2/4"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/4"), payload=GroupValueRead() ), Telegram( - destination_address=GroupAddress("1/2/6"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/6"), payload=GroupValueRead() ), Telegram( - destination_address=GroupAddress("1/2/8"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/8"), payload=GroupValueRead() ), Telegram( - destination_address=GroupAddress("1/2/10"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/14"), payload=GroupValueRead() ), Telegram( - destination_address=GroupAddress("1/2/12"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/10"), payload=GroupValueRead() ), Telegram( - destination_address=GroupAddress("1/2/14"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/12"), payload=GroupValueRead() ), ] - self.assertEqual(len(set(telegrams)), 6) - self.assertEqual(set(telegrams), set(test_telegrams)) + self.assertEqual(len(telegrams), 6) + self.assertListEqual(telegrams, test_telegrams) # # TEST SET ON @@ -261,7 +249,10 @@ def test_set_on(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), + ), ) # @@ -281,7 +272,10 @@ def test_set_off(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTBinary(0)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(0)), + ), ) # @@ -301,7 +295,10 @@ def test_set_brightness(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/5"), payload=DPTArray(23)), + Telegram( + destination_address=GroupAddress("1/2/5"), + payload=GroupValueWrite(DPTArray(23)), + ), ) def test_set_brightness_not_dimmable(self): @@ -335,7 +332,7 @@ def test_set_color(self): telegram, Telegram( destination_address=GroupAddress("1/2/5"), - payload=DPTArray((23, 24, 25)), + payload=GroupValueWrite(DPTArray((23, 24, 25))), ), ) self.loop.run_until_complete(xknx.devices.process(telegram)) @@ -373,7 +370,7 @@ def test_set_color_rgbw(self): telegram, Telegram( destination_address=GroupAddress("1/2/5"), - payload=DPTArray((23, 24, 25, 26, 0, 15)), + payload=GroupValueWrite(DPTArray((23, 24, 25, 26, 0, 15))), ), ) self.loop.run_until_complete(xknx.devices.process(telegram)) @@ -414,7 +411,10 @@ def test_set_tw(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/5"), payload=DPTArray(23)), + Telegram( + destination_address=GroupAddress("1/2/5"), + payload=GroupValueWrite(DPTArray(23)), + ), ) def test_set_tw_unsupported(self): @@ -448,10 +448,12 @@ def test_set_color_temp(self): telegram, Telegram( destination_address=GroupAddress("1/2/5"), - payload=DPTArray( - ( - 0x0F, - 0xA0, + payload=GroupValueWrite( + DPTArray( + ( + 0x0F, + 0xA0, + ) ) ), ), @@ -484,13 +486,15 @@ def test_process_switch(self): self.assertEqual(light.state, None) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete(light.process(telegram)) self.assertEqual(light.state, True) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(0) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(0)), ) self.loop.run_until_complete(light.process(telegram)) self.assertEqual(light.state, False) @@ -515,7 +519,8 @@ async def async_after_update_callback(device): light.register_device_updated_cb(async_after_update_callback) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete(light.process(telegram)) @@ -533,7 +538,8 @@ def test_process_dimm(self): self.assertEqual(light.current_brightness, None) telegram = Telegram( - destination_address=GroupAddress("1/2/5"), payload=DPTArray(23) + destination_address=GroupAddress("1/2/5"), + payload=GroupValueWrite(DPTArray(23)), ) self.loop.run_until_complete(light.process(telegram)) self.assertEqual(light.current_brightness, 23) @@ -548,7 +554,8 @@ def test_process_dimm_wrong_payload(self): group_address_brightness="1/2/5", ) telegram = Telegram( - destination_address=GroupAddress("1/2/5"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/5"), + payload=GroupValueWrite(DPTBinary(1)), ) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(light.process(telegram)) @@ -564,7 +571,8 @@ def test_process_dimm_payload_invalid_length(self): group_address_brightness="1/2/5", ) telegram = Telegram( - destination_address=GroupAddress("1/2/5"), payload=DPTArray((23, 24)) + destination_address=GroupAddress("1/2/5"), + payload=GroupValueWrite(DPTArray((23, 24))), ) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(light.process(telegram)) @@ -580,7 +588,8 @@ def test_process_color(self): ) self.assertEqual(light.current_color, (None, None)) telegram = Telegram( - destination_address=GroupAddress("1/2/5"), payload=DPTArray((23, 24, 25)) + destination_address=GroupAddress("1/2/5"), + payload=GroupValueWrite(DPTArray((23, 24, 25))), ) self.loop.run_until_complete(light.process(telegram)) self.assertEqual(light.current_color, ((23, 24, 25), None)) @@ -598,7 +607,7 @@ def test_process_color_rgbw(self): self.assertEqual(light.current_color, (None, None)) telegram = Telegram( destination_address=GroupAddress("1/2/5"), - payload=DPTArray((23, 24, 25, 26, 0, 15)), + payload=GroupValueWrite(DPTArray((23, 24, 25, 26, 0, 15))), ) self.loop.run_until_complete(light.process(telegram)) self.assertEqual(light.current_color, ([23, 24, 25], 26)) @@ -615,7 +624,8 @@ def test_process_tunable_white(self): self.assertEqual(light.current_tunable_white, None) telegram = Telegram( - destination_address=GroupAddress("1/2/5"), payload=DPTArray(23) + destination_address=GroupAddress("1/2/5"), + payload=GroupValueWrite(DPTArray(23)), ) self.loop.run_until_complete(light.process(telegram)) self.assertEqual(light.current_tunable_white, 23) @@ -630,7 +640,8 @@ def test_process_tunable_white_wrong_payload(self): group_address_tunable_white="1/2/5", ) telegram = Telegram( - destination_address=GroupAddress("1/2/5"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/5"), + payload=GroupValueWrite(DPTBinary(1)), ) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(light.process(telegram)) @@ -646,7 +657,8 @@ def test_process_tunable_white_payload_invalid_length(self): group_address_tunable_white="1/2/5", ) telegram = Telegram( - destination_address=GroupAddress("1/2/5"), payload=DPTArray((23, 24)) + destination_address=GroupAddress("1/2/5"), + payload=GroupValueWrite(DPTArray((23, 24))), ) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(light.process(telegram)) @@ -664,10 +676,12 @@ def test_process_color_temperature(self): telegram = Telegram( destination_address=GroupAddress("1/2/5"), - payload=DPTArray( - ( - 0x0F, - 0xA0, + payload=GroupValueWrite( + DPTArray( + ( + 0x0F, + 0xA0, + ) ) ), ) @@ -684,7 +698,8 @@ def test_process_color_temperature_wrong_payload(self): group_address_color_temperature="1/2/5", ) telegram = Telegram( - destination_address=GroupAddress("1/2/5"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/5"), + payload=GroupValueWrite(DPTBinary(1)), ) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(light.process(telegram)) @@ -700,7 +715,8 @@ def test_process_color_temperature_payload_invalid_length(self): group_address_color_temperature="1/2/5", ) telegram = Telegram( - destination_address=GroupAddress("1/2/5"), payload=DPTArray(23) + destination_address=GroupAddress("1/2/5"), + payload=GroupValueWrite(DPTArray(23)), ) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(light.process(telegram)) diff --git a/test/devices_tests/notification_test.py b/test/devices_tests/notification_test.py index 31e5a22c0..005b296bb 100644 --- a/test/devices_tests/notification_test.py +++ b/test/devices_tests/notification_test.py @@ -7,7 +7,7 @@ from xknx.devices import Notification from xknx.dpt import DPTArray, DPTBinary, DPTString from xknx.exceptions import CouldNotParseTelegram -from xknx.telegram import GroupAddress, Telegram, TelegramType +from xknx.telegram import GroupAddress, GroupValueRead, GroupValueWrite, Telegram class TestNotification(unittest.TestCase): @@ -37,8 +37,7 @@ def test_sync_state(self): self.assertEqual( telegram, Telegram( - destination_address=GroupAddress("1/2/4"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/4"), payload=GroupValueRead() ), ) @@ -51,14 +50,14 @@ def test_process(self): notification = Notification(xknx, "Warning", group_address="1/2/3") telegram_set = Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray(DPTString().to_knx("Ein Prosit!")), + payload=GroupValueWrite(DPTArray(DPTString().to_knx("Ein Prosit!"))), ) self.loop.run_until_complete(notification.process(telegram_set)) self.assertEqual(notification.message, "Ein Prosit!") telegram_unset = Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray(DPTString().to_knx("")), + payload=GroupValueWrite(DPTArray(DPTString().to_knx(""))), ) self.loop.run_until_complete(notification.process(telegram_unset)) self.assertEqual(notification.message, "") @@ -77,7 +76,7 @@ async def async_after_update_callback(device): notification.register_device_updated_cb(async_after_update_callback) telegram_set = Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray(DPTString().to_knx("Ein Prosit!")), + payload=GroupValueWrite(DPTArray(DPTString().to_knx("Ein Prosit!"))), ) self.loop.run_until_complete(notification.process(telegram_set)) after_update_callback.assert_called_with(notification) @@ -88,7 +87,8 @@ def test_process_payload_invalid_length(self): xknx = XKNX() notification = Notification(xknx, "Warning", group_address="1/2/3") telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((23, 24)) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((23, 24))), ) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(notification.process(telegram)) @@ -98,7 +98,8 @@ def test_process_wrong_payload(self): xknx = XKNX() notification = Notification(xknx, "Warning", group_address="1/2/3") telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(notification.process(telegram)) @@ -117,7 +118,7 @@ def test_set(self): telegram, Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray(DPTString().to_knx("Ein Prosit!")), + payload=GroupValueWrite(DPTArray(DPTString().to_knx("Ein Prosit!"))), ), ) # test if message longer than 14 chars gets cropped @@ -129,7 +130,7 @@ def test_set(self): telegram, Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray(DPTString().to_knx("This is too lo")), + payload=GroupValueWrite(DPTArray(DPTString().to_knx("This is too lo"))), ), ) diff --git a/test/devices_tests/scene_test.py b/test/devices_tests/scene_test.py index 671b94003..93644af65 100644 --- a/test/devices_tests/scene_test.py +++ b/test/devices_tests/scene_test.py @@ -7,7 +7,7 @@ from xknx import XKNX from xknx.devices import Scene from xknx.dpt import DPTArray -from xknx.telegram import GroupAddress, Telegram +from xknx.telegram import GroupAddress, GroupValueWrite, Telegram class TestScene(unittest.TestCase): @@ -46,7 +46,10 @@ def test_run(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/1"), payload=DPTArray(0x16)), + Telegram( + destination_address=GroupAddress("1/2/1"), + payload=GroupValueWrite(DPTArray(0x16)), + ), ) def test_do(self): @@ -58,7 +61,10 @@ def test_do(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/1"), payload=DPTArray(0x16)), + Telegram( + destination_address=GroupAddress("1/2/1"), + payload=GroupValueWrite(DPTArray(0x16)), + ), ) def test_wrong_do(self): diff --git a/test/devices_tests/sensor_expose_loop_test.py b/test/devices_tests/sensor_expose_loop_test.py index db73175b9..36f05a7f9 100644 --- a/test/devices_tests/sensor_expose_loop_test.py +++ b/test/devices_tests/sensor_expose_loop_test.py @@ -5,7 +5,7 @@ from xknx import XKNX from xknx.devices import BinarySensor, ExposeSensor, Sensor from xknx.dpt import DPTArray, DPTBinary -from xknx.telegram import GroupAddress, Telegram, TelegramDirection, TelegramType +from xknx.telegram import GroupAddress, GroupValueWrite, Telegram, TelegramDirection class SensorExposeLoopTest(unittest.TestCase): @@ -1460,9 +1460,8 @@ def test_array_sensor_loop(self): incoming_telegram = Telegram( destination_address=GroupAddress("1/1/1"), - telegramtype=TelegramType.GROUP_WRITE, direction=TelegramDirection.INCOMING, - payload=test_payload, + payload=GroupValueWrite(test_payload), ) self.loop.run_until_complete(sensor.process(incoming_telegram)) @@ -1482,9 +1481,8 @@ def test_array_sensor_loop(self): outgoing_telegram, Telegram( destination_address=GroupAddress("2/2/2"), - telegramtype=TelegramType.GROUP_WRITE, direction=TelegramDirection.OUTGOING, - payload=test_payload, + payload=GroupValueWrite(test_payload), ), ) @@ -1510,9 +1508,8 @@ def test_binary_sensor_loop(self): incoming_telegram = Telegram( destination_address=GroupAddress("1/1/1"), - telegramtype=TelegramType.GROUP_WRITE, direction=TelegramDirection.INCOMING, - payload=test_payload, + payload=GroupValueWrite(test_payload), ) self.loop.run_until_complete(sensor.process(incoming_telegram)) @@ -1526,8 +1523,7 @@ def test_binary_sensor_loop(self): outgoing_telegram, Telegram( destination_address=GroupAddress("2/2/2"), - telegramtype=TelegramType.GROUP_WRITE, direction=TelegramDirection.OUTGOING, - payload=test_payload, + payload=GroupValueWrite(test_payload), ), ) diff --git a/test/devices_tests/sensor_test.py b/test/devices_tests/sensor_test.py index 7157ce386..5ec5a783a 100644 --- a/test/devices_tests/sensor_test.py +++ b/test/devices_tests/sensor_test.py @@ -6,7 +6,13 @@ from xknx import XKNX from xknx.devices import Sensor from xknx.dpt import DPTArray -from xknx.telegram import GroupAddress, Telegram, TelegramType +from xknx.telegram import ( + GroupAddress, + GroupValueRead, + GroupValueResponse, + GroupValueWrite, + Telegram, +) class TestSensor(unittest.TestCase): @@ -78,11 +84,12 @@ async def async_after_update_callback(device): # set initial payload of sensor sensor.sensor_value.payload = payload - telegram = Telegram(destination_address=GroupAddress("1/2/3"), payload=payload) + telegram = Telegram( + destination_address=GroupAddress("1/2/3"), payload=GroupValueWrite(payload) + ) response_telegram = Telegram( destination_address=GroupAddress("1/2/3"), - payload=payload, - telegramtype=TelegramType.GROUP_RESPONSE, + payload=GroupValueResponse(payload), ) # verify not called when always_callback is False @@ -2642,8 +2649,7 @@ def test_sync(self): self.assertEqual( telegram, Telegram( - destination_address=GroupAddress("1/2/3"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/3"), payload=GroupValueRead() ), ) @@ -2669,8 +2675,10 @@ def test_process(self): xknx, "TestSensor", value_type="temperature", group_address_state="1/2/3" ) - telegram = Telegram(destination_address=GroupAddress("1/2/3")) - telegram.payload = DPTArray((0x06, 0xA0)) + telegram = Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((0x06, 0xA0))), + ) self.loop.run_until_complete(sensor.process(telegram)) self.assertEqual(sensor.sensor_value.payload, DPTArray((0x06, 0xA0))) self.assertEqual(sensor.resolve_state(), 16.96) @@ -2691,7 +2699,9 @@ async def async_after_update_callback(device): sensor.register_device_updated_cb(async_after_update_callback) - telegram = Telegram(destination_address=GroupAddress("1/2/3")) - telegram.payload = DPTArray((0x01, 0x02)) + telegram = Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((0x01, 0x02))), + ) self.loop.run_until_complete(sensor.process(telegram)) after_update_callback.assert_called_with(sensor) diff --git a/test/devices_tests/switch_test.py b/test/devices_tests/switch_test.py index 2ed54db4d..c2bc8ee9f 100644 --- a/test/devices_tests/switch_test.py +++ b/test/devices_tests/switch_test.py @@ -6,7 +6,13 @@ from xknx import XKNX from xknx.devices import Switch from xknx.dpt import DPTBinary -from xknx.telegram import GroupAddress, Telegram, TelegramType +from xknx.telegram import ( + GroupAddress, + GroupValueRead, + GroupValueResponse, + GroupValueWrite, + Telegram, +) class AsyncMock(MagicMock): @@ -44,8 +50,7 @@ def test_sync(self): self.assertEqual( telegram, Telegram( - destination_address=GroupAddress("1/2/3"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/3"), payload=GroupValueRead() ), ) @@ -63,8 +68,7 @@ def test_sync_state_address(self): self.assertEqual( telegram, Telegram( - destination_address=GroupAddress("1/2/4"), - telegramtype=TelegramType.GROUP_READ, + destination_address=GroupAddress("1/2/4"), payload=GroupValueRead() ), ) @@ -87,10 +91,12 @@ def test_process(self): callback_mock.assert_not_called() telegram_on = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) telegram_off = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(0) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(0)), ) self.loop.run_until_complete(switch1.process(telegram_on)) @@ -136,13 +142,11 @@ def test_process_state(self): telegram_on = Telegram( destination_address=GroupAddress("1/2/4"), - payload=DPTBinary(1), - telegramtype=TelegramType.GROUP_RESPONSE, + payload=GroupValueResponse(DPTBinary(1)), ) telegram_off = Telegram( destination_address=GroupAddress("1/2/4"), - payload=DPTBinary(0), - telegramtype=TelegramType.GROUP_RESPONSE, + payload=GroupValueResponse(DPTBinary(0)), ) self.loop.run_until_complete(switch1.process(telegram_on)) @@ -170,10 +174,12 @@ def test_process_invert(self): self.assertEqual(switch.state, None) telegram_inv_on = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(0) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(0)), ) telegram_inv_off = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete(switch.process(telegram_inv_on)) @@ -189,7 +195,8 @@ def test_process_reset_after(self): xknx, "TestInput", group_address="1/2/3", reset_after=reset_after_sec ) telegram_on = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete(switch.process(telegram_on)) @@ -208,7 +215,8 @@ def test_process_reset_after_cancel_existing(self): xknx, "TestInput", group_address="1/2/3", reset_after=reset_after_sec ) telegram_on = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueResponse(DPTBinary(1)), ) self.loop.run_until_complete(switch.process(telegram_on)) @@ -238,7 +246,8 @@ async def async_after_update_callback(device): switch.register_device_updated_cb(async_after_update_callback) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete(switch.process(telegram)) @@ -256,7 +265,10 @@ def test_set_on(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), + ), ) # @@ -271,7 +283,10 @@ def test_set_off(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTBinary(0)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(0)), + ), ) # @@ -287,7 +302,10 @@ def test_set_invert(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTBinary(0)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(0)), + ), ) self.loop.run_until_complete(switch.set_off()) @@ -295,7 +313,10 @@ def test_set_invert(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), + ), ) # diff --git a/test/io_tests/tunnelling_test.py b/test/io_tests/tunnelling_test.py index 198fe70e4..cb9f5851c 100644 --- a/test/io_tests/tunnelling_test.py +++ b/test/io_tests/tunnelling_test.py @@ -7,7 +7,7 @@ from xknx.dpt import DPTArray from xknx.io import Tunnelling, UDPClient from xknx.knxip import ErrorCode, KNXIPFrame, KNXIPServiceType, TunnellingAck -from xknx.telegram import GroupAddress, IndividualAddress, Telegram +from xknx.telegram import GroupAddress, GroupValueWrite, IndividualAddress, Telegram class TestTunnelling(unittest.TestCase): @@ -29,7 +29,8 @@ def test_tunnelling(self): communication_channel_id = 23 udp_client = UDPClient(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234)) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((0x1, 0x2, 0x3)) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((0x1, 0x2, 0x3))), ) sequence_counter = 42 src_address = IndividualAddress("2.2.2") diff --git a/test/knxip_tests/cemi_frame_test.py b/test/knxip_tests/cemi_frame_test.py index c3804a2ca..461889cd0 100644 --- a/test/knxip_tests/cemi_frame_test.py +++ b/test/knxip_tests/cemi_frame_test.py @@ -7,7 +7,7 @@ from xknx.exceptions import ConversionError, CouldNotParseKNXIP, UnsupportedCEMIMessage from xknx.knxip.cemi_frame import CEMIFrame from xknx.knxip.knxip_enum import APCICommand, CEMIFlags, CEMIMessageCode -from xknx.telegram import GroupAddress, IndividualAddress, Telegram +from xknx.telegram import GroupAddress, GroupValueRead, IndividualAddress, Telegram def get_data(code, adil, flags, src, dst, mpdu_len, tpci_apci, payload): @@ -40,10 +40,9 @@ def test_valid_command(frame): """Test for valid frame parsing""" packet_len = frame.from_knx(get_data(0x29, 0, 0, 0, 0, 1, 0, [])) assert frame.code == CEMIMessageCode.L_DATA_IND - assert frame.cmd == APCICommand.GROUP_READ assert frame.flags == 0 assert frame.mpdu_len == 1 - assert frame.payload == DPTBinary(0) + assert frame.payload == GroupValueRead() assert frame.src_addr == IndividualAddress(0) assert frame.dst_addr == IndividualAddress(0) assert packet_len == 11 @@ -67,7 +66,7 @@ def test_invalid_src_addr(frame): frame.cmd = APCICommand.GROUP_READ frame.flags = 0 frame.mpdu_len = 1 - frame.payload = DPTBinary(0) + frame.payload = GroupValueRead() frame.src_addr = None frame.dst_addr = IndividualAddress(0) @@ -81,7 +80,7 @@ def test_invalid_dst_addr(frame): frame.cmd = APCICommand.GROUP_READ frame.flags = 0 frame.mpdu_len = 1 - frame.payload = DPTBinary(0) + frame.payload = GroupValueRead() frame.src_addr = IndividualAddress(0) frame.dst_addr = None @@ -89,20 +88,6 @@ def test_invalid_dst_addr(frame): frame.to_knx() -def test_no_payload(frame): - """Test for having no payload set""" - frame.code = CEMIMessageCode.L_DATA_IND - frame.cmd = APCICommand.GROUP_READ - frame.flags = 0 - frame.mpdu_len = 1 - frame.payload = None - frame.src_addr = IndividualAddress(0) - frame.dst_addr = IndividualAddress(0) - - assert [41, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0] == frame.to_knx() - assert 11 == frame.calculated_length() - - def test_invalid_payload(frame): """Test for having wrong payload set""" frame.code = CEMIMessageCode.L_DATA_IND @@ -142,13 +127,6 @@ def test_invalid_telegram(frame): tg = frame.telegram -def test_set_invalid_telegram(frame): - """Test for setting invalid telegram type""" - tg = Telegram(telegramtype=None) - with raises(TypeError): - frame.telegram = tg - - def test_invalid_invalid_len(frame): """Test for invalid cemi len""" with raises(UnsupportedCEMIMessage, match=r".*CEMI too small.*"): diff --git a/test/knxip_tests/routing_indication_test.py b/test/knxip_tests/routing_indication_test.py index fed7dda78..e9492bcd3 100644 --- a/test/knxip_tests/routing_indication_test.py +++ b/test/knxip_tests/routing_indication_test.py @@ -6,7 +6,14 @@ from xknx import XKNX from xknx.dpt import DPTArray, DPTBinary, DPTTemperature, DPTTime from xknx.knxip import CEMIFrame, KNXIPFrame, KNXIPServiceType, RoutingIndication -from xknx.telegram import GroupAddress, IndividualAddress, Telegram, TelegramType +from xknx.telegram import ( + GroupAddress, + GroupValueRead, + GroupValueResponse, + GroupValueWrite, + IndividualAddress, + Telegram, +) class Test_KNXIP(unittest.TestCase): @@ -36,8 +43,8 @@ def test_from_knx(self): self.assertEqual(knxipframe.body.cemi.src_addr, IndividualAddress("1.2.2")) self.assertEqual(knxipframe.body.cemi.dst_addr, GroupAddress(337)) - self.assertEqual(len(knxipframe.body.cemi.payload.value), 1) - self.assertEqual(knxipframe.body.cemi.payload.value[0], 0xF0) + self.assertEqual(len(knxipframe.body.cemi.payload.dpt.value), 1) + self.assertEqual(knxipframe.body.cemi.payload.dpt.value[0], 0xF0) def test_from_knx_to_knx(self): """Test parsing and streaming CEMIFrame KNX/IP.""" @@ -61,7 +68,9 @@ def test_telegram_set(self): telegram = Telegram( destination_address=GroupAddress(337), - payload=DPTArray(DPTTime().to_knx(time.strptime("13:23:42", "%H:%M:%S"))), + payload=GroupValueWrite( + DPTArray(DPTTime().to_knx(time.strptime("13:23:42", "%H:%M:%S"))) + ), ) knxipframe.body.cemi.telegram = telegram @@ -86,8 +95,8 @@ def test_telegram_get(self): self.assertEqual(telegram.destination_address, GroupAddress(337)) - self.assertEqual(len(telegram.payload.value), 1) - self.assertEqual(telegram.payload.value[0], 0xF0) + self.assertEqual(len(telegram.payload.dpt.value), 1) + self.assertEqual(telegram.payload.dpt.value[0], 0xF0) # # End-tox-End tests: @@ -109,7 +118,7 @@ def test_EndTOEnd_group_write_binary_on(self): telegram, Telegram( destination_address=GroupAddress("329"), - payload=DPTBinary(1), + payload=GroupValueWrite(DPTBinary(1)), source_address=IndividualAddress("15.15.249"), ), ) @@ -137,7 +146,7 @@ def test_EndTOEnd_group_write_binary_off(self): telegram, Telegram( destination_address=GroupAddress("329"), - payload=DPTBinary(0), + payload=GroupValueWrite(DPTBinary(0)), source_address=IndividualAddress("15.15.249"), ), ) @@ -165,7 +174,7 @@ def test_EndTOEnd_group_write_1byte(self): telegram, Telegram( destination_address=GroupAddress("331"), - payload=DPTArray(0x65), + payload=GroupValueWrite(DPTArray(0x65)), source_address=IndividualAddress("15.15.249"), ), ) @@ -193,7 +202,7 @@ def test_EndTOEnd_group_write_2bytes(self): telegram, Telegram( destination_address=GroupAddress("2049"), - payload=DPTArray(DPTTemperature().to_knx(19.85)), + payload=GroupValueWrite(DPTArray(DPTTemperature().to_knx(19.85))), source_address=IndividualAddress("1.4.2"), ), ) @@ -221,7 +230,7 @@ def test_EndTOEnd_group_read(self): telegram, Telegram( destination_address=GroupAddress("440"), - telegramtype=TelegramType.GROUP_READ, + payload=GroupValueRead(), source_address=IndividualAddress("15.15.249"), ), ) @@ -249,8 +258,7 @@ def test_EndTOEnd_group_response(self): telegram, Telegram( destination_address=GroupAddress("392"), - telegramtype=TelegramType.GROUP_RESPONSE, - payload=DPTBinary(1), + payload=GroupValueResponse(DPTBinary(1)), source_address=IndividualAddress("1.3.1"), ), ) @@ -270,7 +278,7 @@ def test_maximum_apci(self): """Test parsing and streaming CEMIFrame KNX/IP packet, testing maximum APCI.""" telegram = Telegram( destination_address=GroupAddress(337), - payload=DPTBinary(DPTBinary.APCI_MAX_VALUE), + payload=GroupValueWrite(DPTBinary(DPTBinary.APCI_MAX_VALUE)), source_address=IndividualAddress("1.3.1"), ) xknx = XKNX() diff --git a/test/knxip_tests/tunnelling_request_test.py b/test/knxip_tests/tunnelling_request_test.py index d13eca7ad..77cc89eda 100644 --- a/test/knxip_tests/tunnelling_request_test.py +++ b/test/knxip_tests/tunnelling_request_test.py @@ -6,7 +6,7 @@ from xknx.dpt import DPTBinary from xknx.exceptions import CouldNotParseKNXIP from xknx.knxip import CEMIFrame, KNXIPFrame, KNXIPServiceType, TunnellingRequest -from xknx.telegram import GroupAddress, Telegram +from xknx.telegram import GroupAddress, GroupValueWrite, Telegram class Test_KNXIP_TunnelingReq(unittest.TestCase): @@ -59,13 +59,17 @@ def test_connect_request(self): self.assertEqual( knxipframe.body.cemi.telegram, - Telegram(destination_address=GroupAddress("9/0/8"), payload=DPTBinary(1)), + Telegram( + destination_address=GroupAddress("9/0/8"), + payload=GroupValueWrite(DPTBinary(1)), + ), ) knxipframe2 = KNXIPFrame(xknx) knxipframe2.init(KNXIPServiceType.TUNNELLING_REQUEST) knxipframe2.body.cemi.telegram = Telegram( - destination_address=GroupAddress("9/0/8"), payload=DPTBinary(1) + destination_address=GroupAddress("9/0/8"), + payload=GroupValueWrite(DPTBinary(1)), ) knxipframe2.body.sequence_counter = 23 knxipframe2.normalize() diff --git a/test/remote_value_tests/remote_value_1count_test.py b/test/remote_value_tests/remote_value_1count_test.py index bcf5b4112..7cd7f85b0 100644 --- a/test/remote_value_tests/remote_value_1count_test.py +++ b/test/remote_value_tests/remote_value_1count_test.py @@ -6,7 +6,7 @@ from xknx.dpt import DPTArray, DPTBinary from xknx.exceptions import CouldNotParseTelegram from xknx.remote_value import RemoteValue1Count -from xknx.telegram import GroupAddress, Telegram +from xknx.telegram import GroupAddress, GroupValueWrite, Telegram class TestRemoteValue1Count(unittest.TestCase): @@ -43,7 +43,8 @@ def test_set(self): self.assertEqual( telegram, Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((0x64,)) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((0x64,))), ), ) self.loop.run_until_complete( @@ -56,7 +57,8 @@ def test_set(self): self.assertEqual( telegram, Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((0x65,)) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((0x65,))), ), ) @@ -65,7 +67,8 @@ def test_process(self): xknx = XKNX() remote_value = RemoteValue1Count(xknx, group_address=GroupAddress("1/2/3")) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((0x64,)) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((0x64,))), ) self.loop.run_until_complete(remote_value.process(telegram)) self.assertEqual(remote_value.value, 100) @@ -76,16 +79,19 @@ def test_to_process_error(self): remote_value = RemoteValue1Count(xknx, group_address=GroupAddress("1/2/3")) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + 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=DPTArray( - ( - 0x64, - 0x65, + payload=GroupValueWrite( + DPTArray( + ( + 0x64, + 0x65, + ) ) ), ) diff --git a/test/remote_value_tests/remote_value_climate_mode_test.py b/test/remote_value_tests/remote_value_climate_mode_test.py index 2f745e363..b704785ec 100644 --- a/test/remote_value_tests/remote_value_climate_mode_test.py +++ b/test/remote_value_tests/remote_value_climate_mode_test.py @@ -12,7 +12,7 @@ RemoteValueClimateMode, ) from xknx.remote_value.remote_value_climate_mode import _RemoteValueBinaryClimateMode -from xknx.telegram import GroupAddress, Telegram +from xknx.telegram import GroupAddress, GroupValueWrite, Telegram class TestRemoteValueDptValue1Ucount(unittest.TestCase): @@ -178,7 +178,8 @@ def test_set_operation_mode(self): self.assertEqual( telegram, Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((0x03,)) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((0x03,))), ), ) self.loop.run_until_complete( @@ -189,7 +190,8 @@ def test_set_operation_mode(self): self.assertEqual( telegram, Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((0x04,)) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((0x04,))), ), ) @@ -207,7 +209,8 @@ def test_set_binary(self): self.assertEqual( telegram, Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(True) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(True)), ), ) self.loop.run_until_complete( @@ -218,7 +221,8 @@ def test_set_binary(self): self.assertEqual( telegram, Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(False) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(False)), ), ) @@ -231,7 +235,8 @@ def test_process_operation_mode(self): climate_mode_type=RemoteValueClimateMode.ClimateModeType.HVAC_MODE, ) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((0x00,)) + 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) @@ -245,7 +250,8 @@ def test_process_binary(self): operation_mode=HVACOperationMode.FROST_PROTECTION, ) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(True) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(True)), ) self.loop.run_until_complete(remote_value.process(telegram)) self.assertEqual(remote_value.value, HVACOperationMode.FROST_PROTECTION) @@ -260,16 +266,19 @@ def test_to_process_error_operation_mode(self): ) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + 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=DPTArray( - ( - 0x64, - 0x65, + payload=GroupValueWrite( + DPTArray( + ( + 0x64, + 0x65, + ) ) ), ) @@ -285,16 +294,19 @@ def test_to_process_error_heat_cool(self): ) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((0x01,)) + 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=DPTArray( - ( - 0x64, - 0x65, + payload=GroupValueWrite( + DPTArray( + ( + 0x64, + 0x65, + ) ) ), ) diff --git a/test/remote_value_tests/remote_value_color_rgb_test.py b/test/remote_value_tests/remote_value_color_rgb_test.py index e6c33dd02..466796b5e 100644 --- a/test/remote_value_tests/remote_value_color_rgb_test.py +++ b/test/remote_value_tests/remote_value_color_rgb_test.py @@ -6,7 +6,7 @@ from xknx.dpt import DPTArray, DPTBinary from xknx.exceptions import ConversionError, CouldNotParseTelegram from xknx.remote_value import RemoteValueColorRGB -from xknx.telegram import GroupAddress, Telegram +from xknx.telegram import GroupAddress, GroupValueWrite, Telegram class TestRemoteValueColorRGB(unittest.TestCase): @@ -66,7 +66,7 @@ def test_set(self): telegram, Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray((0x64, 0x65, 0x66)), + payload=GroupValueWrite(DPTArray((0x64, 0x65, 0x66))), ), ) self.loop.run_until_complete(remote_value.set((100, 101, 104))) @@ -76,7 +76,7 @@ def test_set(self): telegram, Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray((0x64, 0x65, 0x68)), + payload=GroupValueWrite(DPTArray((0x64, 0x65, 0x68))), ), ) @@ -86,7 +86,7 @@ def test_process(self): remote_value = RemoteValueColorRGB(xknx, group_address=GroupAddress("1/2/3")) telegram = Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray((0x64, 0x65, 0x66)), + payload=GroupValueWrite(DPTArray((0x64, 0x65, 0x66))), ) self.loop.run_until_complete(remote_value.process(telegram)) self.assertEqual(remote_value.value, (100, 101, 102)) @@ -97,12 +97,13 @@ def test_to_process_error(self): remote_value = RemoteValueColorRGB(xknx, group_address=GroupAddress("1/2/3")) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + 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=DPTArray((0x64, 0x65, 0x66, 0x67)), + payload=GroupValueWrite(DPTArray((0x64, 0x65, 0x66, 0x67))), ) self.loop.run_until_complete(remote_value.process(telegram)) diff --git a/test/remote_value_tests/remote_value_color_rgbw_test.py b/test/remote_value_tests/remote_value_color_rgbw_test.py index 5b929b23b..55c359f59 100644 --- a/test/remote_value_tests/remote_value_color_rgbw_test.py +++ b/test/remote_value_tests/remote_value_color_rgbw_test.py @@ -6,7 +6,7 @@ from xknx.dpt import DPTArray, DPTBinary from xknx.exceptions import ConversionError, CouldNotParseTelegram from xknx.remote_value import RemoteValueColorRGBW -from xknx.telegram import GroupAddress, Telegram +from xknx.telegram import GroupAddress, GroupValueWrite, Telegram class TestRemoteValueColorRGBW(unittest.TestCase): @@ -94,7 +94,7 @@ def test_set(self): telegram, Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray((0x64, 0x65, 0x66, 0x67, 0x00, 0x0F)), + payload=GroupValueWrite(DPTArray((0x64, 0x65, 0x66, 0x67, 0x00, 0x0F))), ), ) self.loop.run_until_complete(remote_value.set((100, 101, 104, 105))) @@ -104,7 +104,7 @@ def test_set(self): telegram, Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray((0x64, 0x65, 0x68, 0x69, 0x00, 0x0F)), + payload=GroupValueWrite(DPTArray((0x64, 0x65, 0x68, 0x69, 0x00, 0x0F))), ), ) @@ -114,7 +114,7 @@ def test_process(self): remote_value = RemoteValueColorRGBW(xknx, group_address=GroupAddress("1/2/3")) telegram = Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray((0x64, 0x65, 0x66, 0x67, 0x00, 0x0F)), + payload=GroupValueWrite(DPTArray((0x64, 0x65, 0x66, 0x67, 0x00, 0x0F))), ) self.loop.run_until_complete(remote_value.process(telegram)) self.assertEqual(remote_value.value, [100, 101, 102, 103]) @@ -125,18 +125,21 @@ def test_to_process_error(self): remote_value = RemoteValueColorRGBW(xknx, group_address=GroupAddress("1/2/3")) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + 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=DPTArray((0x64, 0x65, 0x66)), + 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=DPTArray((0x00, 0x00, 0x0F, 0x64, 0x65, 0x66, 0x67)), + payload=GroupValueWrite( + DPTArray((0x00, 0x00, 0x0F, 0x64, 0x65, 0x66, 0x67)) + ), ) self.loop.run_until_complete(remote_value.process(telegram)) diff --git a/test/remote_value_tests/remote_value_dpt_2_byte_unsigned_test.py b/test/remote_value_tests/remote_value_dpt_2_byte_unsigned_test.py index e34c8dcc0..70a5152e8 100644 --- a/test/remote_value_tests/remote_value_dpt_2_byte_unsigned_test.py +++ b/test/remote_value_tests/remote_value_dpt_2_byte_unsigned_test.py @@ -6,7 +6,7 @@ from xknx.dpt import DPTArray, DPTBinary from xknx.exceptions import ConversionError, CouldNotParseTelegram from xknx.remote_value import RemoteValueDpt2ByteUnsigned -from xknx.telegram import GroupAddress, Telegram +from xknx.telegram import GroupAddress, GroupValueWrite, Telegram class TestRemoteValueDptValue2Ucount(unittest.TestCase): @@ -55,7 +55,7 @@ def test_set(self): telegram, Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray((0x0A, 0x0B)), + payload=GroupValueWrite(DPTArray((0x0A, 0x0B))), ), ) self.loop.run_until_complete(remote_value.set(5500)) @@ -65,10 +65,12 @@ def test_set(self): telegram, Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray( - ( - 0x15, - 0x7C, + payload=GroupValueWrite( + DPTArray( + ( + 0x15, + 0x7C, + ) ) ), ), @@ -81,7 +83,8 @@ def test_process(self): xknx, group_address=GroupAddress("1/2/3") ) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((0x0A, 0x0B)) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((0x0A, 0x0B))), ) self.loop.run_until_complete(remote_value.process(telegram)) self.assertEqual(remote_value.value, 2571) @@ -94,22 +97,26 @@ def test_to_process_error(self): ) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + 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=DPTArray((0x64,)) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((0x64,))), ) self.loop.run_until_complete(remote_value.process(telegram)) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray( - ( - 0x64, - 0x53, - 0x42, + payload=GroupValueWrite( + DPTArray( + ( + 0x64, + 0x53, + 0x42, + ) ) ), ) diff --git a/test/remote_value_tests/remote_value_dpt_value_1_ucount_test.py b/test/remote_value_tests/remote_value_dpt_value_1_ucount_test.py index 5f3ae1eb0..2dbca8d58 100644 --- a/test/remote_value_tests/remote_value_dpt_value_1_ucount_test.py +++ b/test/remote_value_tests/remote_value_dpt_value_1_ucount_test.py @@ -6,7 +6,7 @@ from xknx.dpt import DPTArray, DPTBinary from xknx.exceptions import ConversionError, CouldNotParseTelegram from xknx.remote_value import RemoteValueDptValue1Ucount -from xknx.telegram import GroupAddress, Telegram +from xknx.telegram import GroupAddress, GroupValueWrite, Telegram class TestRemoteValueDptValue1Ucount(unittest.TestCase): @@ -54,7 +54,8 @@ def test_set(self): self.assertEqual( telegram, Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((0x0A,)) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((0x0A,))), ), ) self.loop.run_until_complete(remote_value.set(11)) @@ -63,7 +64,8 @@ def test_set(self): self.assertEqual( telegram, Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((0x0B,)) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((0x0B,))), ), ) @@ -74,7 +76,8 @@ def test_process(self): xknx, group_address=GroupAddress("1/2/3") ) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((0x0A,)) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((0x0A,))), ) self.loop.run_until_complete(remote_value.process(telegram)) self.assertEqual(remote_value.value, 10) @@ -87,16 +90,19 @@ def test_to_process_error(self): ) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + 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=DPTArray( - ( - 0x64, - 0x65, + payload=GroupValueWrite( + DPTArray( + ( + 0x64, + 0x65, + ) ) ), ) diff --git a/test/remote_value_tests/remote_value_scene_number_test.py b/test/remote_value_tests/remote_value_scene_number_test.py index a356bd7c0..6907d46a6 100644 --- a/test/remote_value_tests/remote_value_scene_number_test.py +++ b/test/remote_value_tests/remote_value_scene_number_test.py @@ -6,7 +6,7 @@ from xknx.dpt import DPTArray, DPTBinary from xknx.exceptions import ConversionError, CouldNotParseTelegram from xknx.remote_value import RemoteValueSceneNumber -from xknx.telegram import GroupAddress, Telegram +from xknx.telegram import GroupAddress, GroupValueWrite, Telegram class TestRemoteValueSceneNumber(unittest.TestCase): @@ -52,7 +52,8 @@ def test_set(self): self.assertEqual( telegram, Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((0x0A,)) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((0x0A,))), ), ) self.loop.run_until_complete(remote_value.set(12)) @@ -61,7 +62,8 @@ def test_set(self): self.assertEqual( telegram, Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((0x0B,)) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((0x0B,))), ), ) @@ -70,7 +72,8 @@ def test_process(self): xknx = XKNX() remote_value = RemoteValueSceneNumber(xknx, group_address=GroupAddress("1/2/3")) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray((0x0A,)) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTArray((0x0A,))), ) self.loop.run_until_complete(remote_value.process(telegram)) self.assertEqual(remote_value.value, 11) @@ -81,16 +84,19 @@ def test_to_process_error(self): remote_value = RemoteValueSceneNumber(xknx, group_address=GroupAddress("1/2/3")) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + 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=DPTArray( - ( - 0x64, - 0x65, + payload=GroupValueWrite( + DPTArray( + ( + 0x64, + 0x65, + ) ) ), ) diff --git a/test/remote_value_tests/remote_value_step_test.py b/test/remote_value_tests/remote_value_step_test.py index 5a326954e..d900bd19f 100644 --- a/test/remote_value_tests/remote_value_step_test.py +++ b/test/remote_value_tests/remote_value_step_test.py @@ -6,7 +6,7 @@ from xknx.dpt import DPTArray, DPTBinary from xknx.exceptions import ConversionError, CouldNotParseTelegram from xknx.remote_value import RemoteValueStep -from xknx.telegram import GroupAddress, Telegram +from xknx.telegram import GroupAddress, GroupValueWrite, Telegram class TestRemoteValueStep(unittest.TestCase): @@ -81,14 +81,20 @@ def test_set(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTBinary(0)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(0)), + ), ) self.loop.run_until_complete(remote_value.increase()) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), + ), ) def test_process(self): @@ -96,7 +102,8 @@ def test_process(self): xknx = XKNX() remote_value = RemoteValueStep(xknx, group_address=GroupAddress("1/2/3")) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(0) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(0)), ) self.assertEqual(remote_value.value, None) self.loop.run_until_complete(remote_value.process(telegram)) @@ -108,12 +115,14 @@ def test_to_process_error(self): remote_value = RemoteValueStep(xknx, group_address=GroupAddress("1/2/3")) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray(0x01) + 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=DPTBinary(3) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(3)), ) self.loop.run_until_complete(remote_value.process(telegram)) # pylint: disable=pointless-statement diff --git a/test/remote_value_tests/remote_value_string_test.py b/test/remote_value_tests/remote_value_string_test.py index 78ac49491..a739de4f1 100644 --- a/test/remote_value_tests/remote_value_string_test.py +++ b/test/remote_value_tests/remote_value_string_test.py @@ -6,7 +6,7 @@ from xknx.dpt import DPTArray, DPTBinary from xknx.exceptions import ConversionError, CouldNotParseTelegram from xknx.remote_value import RemoteValueString -from xknx.telegram import GroupAddress, Telegram +from xknx.telegram import GroupAddress, GroupValueWrite, Telegram class TestRemoteValueString(unittest.TestCase): @@ -93,7 +93,9 @@ def test_set(self): telegram, Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray((97, 115, 100, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), + payload=GroupValueWrite( + DPTArray((97, 115, 100, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + ), ), ) self.loop.run_until_complete(remote_value.set("ASDF")) @@ -103,7 +105,9 @@ def test_set(self): telegram, Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray((65, 83, 68, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), + payload=GroupValueWrite( + DPTArray((65, 83, 68, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + ), ), ) @@ -113,22 +117,24 @@ def test_process(self): remote_value = RemoteValueString(xknx, group_address=GroupAddress("1/2/3")) telegram = Telegram( destination_address=GroupAddress("1/2/3"), - payload=DPTArray( - ( - 0x41, - 0x41, - 0x41, - 0x41, - 0x41, - 0x42, - 0x42, - 0x42, - 0x42, - 0x42, - 0x43, - 0x43, - 0x43, - 0x43, + payload=GroupValueWrite( + DPTArray( + ( + 0x41, + 0x41, + 0x41, + 0x41, + 0x41, + 0x42, + 0x42, + 0x42, + 0x42, + 0x42, + 0x43, + 0x43, + 0x43, + 0x43, + ) ) ), ) @@ -141,16 +147,19 @@ def test_to_process_error(self): remote_value = RemoteValueString(xknx, group_address=GroupAddress("1/2/3")) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + 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=DPTArray( - ( - 0x64, - 0x65, + payload=GroupValueWrite( + DPTArray( + ( + 0x64, + 0x65, + ) ) ), ) diff --git a/test/remote_value_tests/remote_value_switch_test.py b/test/remote_value_tests/remote_value_switch_test.py index 325dc0426..b8c48638e 100644 --- a/test/remote_value_tests/remote_value_switch_test.py +++ b/test/remote_value_tests/remote_value_switch_test.py @@ -6,7 +6,7 @@ from xknx.dpt import DPTArray, DPTBinary from xknx.exceptions import ConversionError, CouldNotParseTelegram from xknx.remote_value import RemoteValueSwitch -from xknx.telegram import GroupAddress, Telegram +from xknx.telegram import GroupAddress, GroupValueWrite, Telegram class TestRemoteValueSwitch(unittest.TestCase): @@ -65,14 +65,20 @@ def test_set(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), + ), ) self.loop.run_until_complete(remote_value.off()) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTBinary(0)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(0)), + ), ) def test_process(self): @@ -80,7 +86,8 @@ def test_process(self): xknx = XKNX() remote_value = RemoteValueSwitch(xknx, group_address=GroupAddress("1/2/3")) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) self.assertEqual(remote_value.value, None) self.loop.run_until_complete(remote_value.process(telegram)) @@ -92,7 +99,8 @@ def test_process_off(self): xknx = XKNX() remote_value = RemoteValueSwitch(xknx, group_address=GroupAddress("1/2/3")) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(0) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(0)), ) self.assertEqual(remote_value.value, None) self.loop.run_until_complete(remote_value.process(telegram)) @@ -105,12 +113,14 @@ def test_to_process_error(self): remote_value = RemoteValueSwitch(xknx, group_address=GroupAddress("1/2/3")) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray(0x01) + 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=DPTBinary(3) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(3)), ) self.loop.run_until_complete(remote_value.process(telegram)) # pylint: disable=pointless-statement diff --git a/test/remote_value_tests/remote_value_test.py b/test/remote_value_tests/remote_value_test.py index 44c528a0c..844ed4348 100644 --- a/test/remote_value_tests/remote_value_test.py +++ b/test/remote_value_tests/remote_value_test.py @@ -7,7 +7,7 @@ from xknx.dpt import DPTArray, DPTBinary from xknx.exceptions import CouldNotParseTelegram from xknx.remote_value import RemoteValue, RemoteValueSwitch -from xknx.telegram import GroupAddress, Telegram +from xknx.telegram import GroupAddress, GroupValueWrite, Telegram class TestRemoteValue(unittest.TestCase): @@ -96,7 +96,7 @@ def test_process_invalid_payload(self): telegram = Telegram( destination_address=GroupAddress("1/2/1"), - payload=DPTArray((0x01, 0x02)), + payload=GroupValueWrite(DPTArray((0x01, 0x02))), ) with self.assertRaises(CouldNotParseTelegram): self.loop.run_until_complete(remote_value.process(telegram)) @@ -113,7 +113,8 @@ def test_read_state(self): fut = asyncio.Future() telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) fut.set_result(telegram) patch_read.return_value = fut @@ -158,7 +159,8 @@ def test_process_listening_address(self): patch_valid.return_value = True test_payload = DPTArray((0x01, 0x02)) telegram = Telegram( - destination_address=GroupAddress("1/1/1"), payload=test_payload + destination_address=GroupAddress("1/1/1"), + payload=GroupValueWrite(test_payload), ) self.assertTrue( self.loop.run_until_complete( diff --git a/test/remote_value_tests/remote_value_updown_test.py b/test/remote_value_tests/remote_value_updown_test.py index 303c9fb45..f4e165acd 100644 --- a/test/remote_value_tests/remote_value_updown_test.py +++ b/test/remote_value_tests/remote_value_updown_test.py @@ -6,7 +6,7 @@ from xknx.dpt import DPTArray, DPTBinary from xknx.exceptions import ConversionError, CouldNotParseTelegram from xknx.remote_value import RemoteValueUpDown -from xknx.telegram import GroupAddress, Telegram +from xknx.telegram import GroupAddress, GroupValueWrite, Telegram class TestRemoteValueUpDown(unittest.TestCase): @@ -81,14 +81,20 @@ def test_set(self): telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), + ), ) self.loop.run_until_complete(remote_value.up()) self.assertEqual(xknx.telegrams.qsize(), 1) telegram = xknx.telegrams.get_nowait() self.assertEqual( telegram, - Telegram(destination_address=GroupAddress("1/2/3"), payload=DPTBinary(0)), + Telegram( + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(0)), + ), ) def test_process(self): @@ -96,7 +102,8 @@ def test_process(self): xknx = XKNX() remote_value = RemoteValueUpDown(xknx, group_address=GroupAddress("1/2/3")) telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(1) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(1)), ) self.assertEqual(remote_value.value, None) self.loop.run_until_complete(remote_value.process(telegram)) @@ -108,12 +115,14 @@ def test_to_process_error(self): remote_value = RemoteValueUpDown(xknx, group_address=GroupAddress("1/2/3")) with self.assertRaises(CouldNotParseTelegram): telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTArray(0x01) + 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=DPTBinary(3) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(3)), ) self.loop.run_until_complete(remote_value.process(telegram)) # pylint: disable=pointless-statement diff --git a/test/str_test.py b/test/str_test.py index cad6df811..8441e649f 100644 --- a/test/str_test.py +++ b/test/str_test.py @@ -55,7 +55,13 @@ TunnellingRequest, ) from xknx.remote_value import RemoteValue -from xknx.telegram import GroupAddress, IndividualAddress, Telegram, TelegramDirection +from xknx.telegram import ( + GroupAddress, + GroupValueWrite, + IndividualAddress, + Telegram, + TelegramDirection, +) # pylint: disable=too-many-public-methods,invalid-name @@ -283,7 +289,7 @@ def test_sensor(self): telegram = Telegram( destination_address=GroupAddress("1/2/3"), direction=TelegramDirection.INCOMING, - payload=DPTArray(0x40), + payload=GroupValueWrite(DPTArray(0x40)), ) self.loop.run_until_complete(sensor.process_group_write(telegram)) self.assertEqual( @@ -352,7 +358,7 @@ def test_weather(self): telegram = Telegram( destination_address=GroupAddress("7/0/10"), direction=TelegramDirection.INCOMING, - payload=DPTBinary(1), + payload=GroupValueWrite(DPTBinary(1)), ) self.loop.run_until_complete(weather.process_group_write(telegram)) @@ -469,12 +475,13 @@ def test_dpt_binary(self): def test_telegram(self): """Test string representation of Telegram.""" telegram = Telegram( - destination_address=GroupAddress("1/2/3"), payload=DPTBinary(7) + destination_address=GroupAddress("1/2/3"), + payload=GroupValueWrite(DPTBinary(7)), ) self.assertEqual( str(telegram), '" />', + 'destination_address="GroupAddress("1/2/3")" payload="" />" />', ) def test_dib_generic(self): @@ -662,12 +669,13 @@ def test_cemi_frame(self): cemi_frame = CEMIFrame(xknx) cemi_frame.src_addr = GroupAddress("1/2/3") cemi_frame.telegram = Telegram( - destination_address=GroupAddress("1/2/5"), payload=DPTBinary(7) + destination_address=GroupAddress("1/2/5"), + payload=GroupValueWrite(DPTBinary(7)), ) self.assertEqual( str(cemi_frame), - '" />', + '" />" />', ) def test_knxip_frame(self): diff --git a/test/telegram_tests/telegram_test.py b/test/telegram_tests/telegram_test.py index 37e759935..3d35bdd5a 100644 --- a/test/telegram_tests/telegram_test.py +++ b/test/telegram_tests/telegram_test.py @@ -1,7 +1,14 @@ """Unit test for Telegram objects.""" import unittest -from xknx.telegram import GroupAddress, Telegram, TelegramDirection, TelegramType +from xknx.dpt import DPTBinary +from xknx.telegram import ( + GroupAddress, + GroupValueRead, + GroupValueWrite, + Telegram, + TelegramDirection, +) class TestTelegram(unittest.TestCase): @@ -13,25 +20,25 @@ class TestTelegram(unittest.TestCase): def test_telegram_equal(self): """Test equals operator.""" self.assertEqual( - Telegram(GroupAddress("1/2/3"), TelegramType.GROUP_READ), - Telegram(GroupAddress("1/2/3"), TelegramType.GROUP_READ), + Telegram(GroupAddress("1/2/3"), payload=GroupValueRead()), + Telegram(GroupAddress("1/2/3"), payload=GroupValueRead()), ) def test_telegram_not_equal(self): """Test not equals operator.""" self.assertNotEqual( - Telegram(GroupAddress("1/2/3"), TelegramType.GROUP_READ), - Telegram(GroupAddress("1/2/4"), TelegramType.GROUP_READ), + Telegram(GroupAddress("1/2/3"), payload=GroupValueRead()), + Telegram(GroupAddress("1/2/4"), payload=GroupValueRead()), ) self.assertNotEqual( - Telegram(GroupAddress("1/2/3"), TelegramType.GROUP_READ), - Telegram(GroupAddress("1/2/3"), TelegramType.GROUP_WRITE), + Telegram(GroupAddress("1/2/3"), payload=GroupValueRead()), + Telegram(GroupAddress("1/2/3"), payload=GroupValueWrite(DPTBinary(1))), ) self.assertNotEqual( - Telegram(GroupAddress("1/2/3"), TelegramType.GROUP_READ), + Telegram(GroupAddress("1/2/3"), payload=GroupValueRead()), Telegram( GroupAddress("1/2/3"), - TelegramType.GROUP_READ, TelegramDirection.INCOMING, + payload=GroupValueRead(), ), ) diff --git a/xknx/core/telegram_queue.py b/xknx/core/telegram_queue.py index 5d8eb94f7..0295427b7 100644 --- a/xknx/core/telegram_queue.py +++ b/xknx/core/telegram_queue.py @@ -11,7 +11,7 @@ import logging from xknx.exceptions import CommunicationError, XKNXException -from xknx.telegram import TelegramDirection, TelegramType +from xknx.telegram import GroupValueWrite, TelegramDirection logger = logging.getLogger("xknx.log") telegram_logger = logging.getLogger("xknx.telegram") @@ -133,7 +133,7 @@ async def process_telegram_outgoing(self, telegram): telegram_logger.debug(telegram) if self.xknx.knxip_interface is not None: await self.xknx.knxip_interface.send_telegram(telegram) - if telegram.telegramtype == TelegramType.GROUP_WRITE: + if isinstance(telegram.payload, GroupValueWrite): await self.xknx.devices.process(telegram) else: logger.warning("No KNXIP interface defined") diff --git a/xknx/core/value_reader.py b/xknx/core/value_reader.py index 6c3ea6f62..936ccc1ea 100644 --- a/xknx/core/value_reader.py +++ b/xknx/core/value_reader.py @@ -10,7 +10,7 @@ import asyncio import logging -from xknx.telegram import Telegram, TelegramType +from xknx.telegram import GroupValueRead, GroupValueResponse, GroupValueWrite, Telegram logger = logging.getLogger("xknx.log") @@ -49,19 +49,14 @@ async def read(self): async def send_group_read(self): """Send group read.""" telegram = Telegram( - destination_address=self.group_address, telegramtype=TelegramType.GROUP_READ + destination_address=self.group_address, payload=GroupValueRead() ) await self.xknx.telegrams.put(telegram) async def telegram_received(self, telegram): """Test if telegram has correct group address and trigger event.""" - if ( - telegram.destination_address == self.group_address - and telegram.telegramtype - in ( - TelegramType.GROUP_RESPONSE, - TelegramType.GROUP_WRITE, - ) + if telegram.destination_address == self.group_address and isinstance( + telegram.payload, (GroupValueResponse, GroupValueWrite) ): self.success = True self.received_telegram = telegram diff --git a/xknx/devices/device.py b/xknx/devices/device.py index 6d33b2e7e..3729828b6 100644 --- a/xknx/devices/device.py +++ b/xknx/devices/device.py @@ -5,7 +5,7 @@ """ import logging -from xknx.telegram import TelegramType +from xknx.telegram import GroupValueRead, GroupValueResponse, GroupValueWrite logger = logging.getLogger("xknx.log") @@ -51,12 +51,14 @@ async def sync(self, wait_for_result=False): async def process(self, telegram): """Process incoming telegram.""" - if telegram.telegramtype == TelegramType.GROUP_WRITE: + if isinstance(telegram.payload, GroupValueWrite): await self.process_group_write(telegram) - elif telegram.telegramtype == TelegramType.GROUP_RESPONSE: + elif isinstance(telegram.payload, GroupValueResponse): await self.process_group_response(telegram) - elif telegram.telegramtype == TelegramType.GROUP_READ: + elif isinstance(telegram.payload, GroupValueRead): await self.process_group_read(telegram) + else: + raise ValueError("Unsupported payload.") async def process_group_read(self, telegram): """Process incoming GroupValueRead telegrams.""" @@ -69,7 +71,7 @@ async def process_group_response(self, telegram): async def process_group_write(self, telegram): """Process incoming GroupValueWrite telegrams.""" - # The dafault is, that devices dont process group writes + # The default is, that devices dont process group writes def get_name(self): """Return name of device.""" diff --git a/xknx/knxip/cemi_frame.py b/xknx/knxip/cemi_frame.py index c26dd1e64..bf4352971 100644 --- a/xknx/knxip/cemi_frame.py +++ b/xknx/knxip/cemi_frame.py @@ -13,9 +13,9 @@ """ from typing import Union -from xknx.dpt import DPTArray, DPTBinary from xknx.exceptions import ConversionError, CouldNotParseKNXIP, UnsupportedCEMIMessage -from xknx.telegram import GroupAddress, IndividualAddress, Telegram, TelegramType +from xknx.telegram import GroupAddress, IndividualAddress, Telegram +from xknx.telegram.apci import APCI from .knxip_enum import APCICommand, CEMIFlags, CEMIMessageCode @@ -63,19 +63,8 @@ def init_from_telegram( def telegram(self) -> Telegram: """Return telegram.""" - def resolve_telegram_type(cmd): - """Return telegram type from APCI Command.""" - if cmd == APCICommand.GROUP_WRITE: - return TelegramType.GROUP_WRITE - if cmd == APCICommand.GROUP_READ: - return TelegramType.GROUP_READ - if cmd == APCICommand.GROUP_RESPONSE: - return TelegramType.GROUP_RESPONSE - raise ConversionError(f"Telegram not implemented for {self.cmd}") - return Telegram( destination_address=self.dst_addr, - telegramtype=resolve_telegram_type(self.cmd), payload=self.payload, source_address=self.src_addr, ) @@ -105,19 +94,6 @@ def telegram(self, telegram: Telegram): else: raise TypeError() - # TODO: use telegram.direction - def resolve_cmd(telegramtype: TelegramType) -> APCICommand: - """Resolve APCICommand from TelegramType.""" - if telegramtype == TelegramType.GROUP_READ: - return APCICommand.GROUP_READ - if telegramtype == TelegramType.GROUP_WRITE: - return APCICommand.GROUP_WRITE - if telegramtype == TelegramType.GROUP_RESPONSE: - return APCICommand.GROUP_RESPONSE - raise TypeError() - - self.cmd = resolve_cmd(telegram.telegramtype) - def set_hops(self, hops: int): """Set hops.""" # Resetting hops @@ -127,13 +103,9 @@ def set_hops(self, hops: int): def calculated_length(self) -> int: """Get length of KNX/IP body.""" - if self.payload is None: - return 11 - if isinstance(self.payload, DPTBinary): - return 11 - if isinstance(self.payload, DPTArray): - return 11 + len(self.payload.value) - raise TypeError() + if not isinstance(self.payload, APCI): + raise TypeError() + return 10 + self.payload.calculated_length() def from_knx(self, raw) -> int: """Parse/deserialize from KNX/IP raw data.""" @@ -207,16 +179,21 @@ def from_knx_data_link_layer(self, cemi) -> int: ) ) - if len(apdu) == 1: - apci = tpci_apci & DPTBinary.APCI_BITMASK - self.payload = DPTBinary(apci) - else: - self.payload = DPTArray(cemi[11 + addil :]) + try: + self.payload = APCI.resolve_class(tpci_apci & 0x03FF)() + except ConversionError: + raise UnsupportedCEMIMessage( + "APCI not supported: {:#012b}".format(tpci_apci & 0x03FF) + ) + + self.payload.from_knx(apdu) return 10 + addil + len(apdu) def to_knx(self): """Serialize to KNX/IP raw data.""" + if not isinstance(self.payload, APCI): + raise TypeError() if not isinstance(self.src_addr, (GroupAddress, IndividualAddress)): raise ConversionError("src_addr not set") if not isinstance(self.dst_addr, (GroupAddress, IndividualAddress)): @@ -230,31 +207,8 @@ def to_knx(self): data.append(self.flags & 255) data.extend(self.src_addr.to_knx()) data.extend(self.dst_addr.to_knx()) + data.extend(self.payload.to_knx()) - def encode_cmd_and_payload(cmd, encoded_payload=0, appended_payload=None): - """Encode cmd and payload.""" - if appended_payload is None: - appended_payload = [] - data = [ - 1 + len(appended_payload), - (cmd.value >> 8) & 0xFF, - (cmd.value & 0xFF) | (encoded_payload & DPTBinary.APCI_BITMASK), - ] - data.extend(appended_payload) - return data - - if self.payload is None: - data.extend(encode_cmd_and_payload(self.cmd)) - elif isinstance(self.payload, DPTBinary): - data.extend( - encode_cmd_and_payload(self.cmd, encoded_payload=self.payload.value) - ) - elif isinstance(self.payload, DPTArray): - data.extend( - encode_cmd_and_payload(self.cmd, appended_payload=self.payload.value) - ) - else: - raise TypeError() return data def __str__(self): diff --git a/xknx/knxip/knxip_enum.py b/xknx/knxip/knxip_enum.py index 127a76e9e..2199eb2bb 100644 --- a/xknx/knxip/knxip_enum.py +++ b/xknx/knxip/knxip_enum.py @@ -52,9 +52,9 @@ class CEMIMessageCode(Enum): class APCICommand(Enum): """Enum class for KNX/IP APCI Commands.""" - GROUP_READ = 0x00 - GROUP_WRITE = 0x80 - GROUP_RESPONSE = 0x40 + GROUP_READ = 0x0000 + GROUP_RESPONSE = 0x0040 + GROUP_WRITE = 0x0080 class CEMIFlags: diff --git a/xknx/remote_value/remote_value.py b/xknx/remote_value/remote_value.py index 88f86ee31..e5744924d 100644 --- a/xknx/remote_value/remote_value.py +++ b/xknx/remote_value/remote_value.py @@ -10,7 +10,7 @@ from typing import List from xknx.exceptions import CouldNotParseTelegram -from xknx.telegram import GroupAddress, Telegram, TelegramType +from xknx.telegram import GroupAddress, GroupValueResponse, GroupValueWrite, Telegram logger = logging.getLogger("xknx.log") @@ -112,7 +112,21 @@ async def process(self, telegram, always_callback=False): """Process incoming or outgoing telegram.""" if not self.has_group_address(telegram.destination_address): return False - if not self.payload_valid(telegram.payload): + if not isinstance( + telegram.payload, + ( + GroupValueWrite, + GroupValueResponse, + ), + ): + raise CouldNotParseTelegram( + "payload not a GroupValueWrite or GroupValueResponse", + payload=telegram.payload, + address=telegram.address, + device_name=self.device_name, + feature_name=self.feature_name, + ) + if not self.payload_valid(telegram.payload.dpt): raise CouldNotParseTelegram( "payload invalid", payload=telegram.payload, @@ -121,8 +135,12 @@ async def process(self, telegram, always_callback=False): feature_name=self.feature_name, ) self.xknx.state_updater.update_received(self) - if self.payload is None or always_callback or self.payload != telegram.payload: - self.payload = telegram.payload + if ( + self.payload is None + or always_callback + or self.payload != telegram.payload.dpt + ): + self.payload = telegram.payload.dpt if self.after_update_cb is not None: await self.after_update_cb() return True @@ -138,10 +156,9 @@ async def _send(self, payload, response=False): """Send payload as telegram to KNX bus.""" telegram = Telegram( destination_address=self.group_address, - telegramtype=( - TelegramType.GROUP_RESPONSE if response else TelegramType.GROUP_WRITE + payload=( + GroupValueResponse(payload) if response else GroupValueWrite(payload) ), - payload=payload, ) await self.xknx.telegrams.put(telegram) From 42f3393617422ff032891ac5fb618efecbf5b558 Mon Sep 17 00:00:00 2001 From: Bas Stottelaar Date: Tue, 1 Dec 2020 00:30:46 +0100 Subject: [PATCH 4/6] Remove `CEMIFrame.cmd` This can be derived from the payload of the telegram. --- test/knxip_tests/cemi_frame_test.py | 15 ++------------- test/str_test.py | 8 ++++---- xknx/io/routing.py | 7 ------- xknx/knxip/__init__.py | 1 - xknx/knxip/cemi_frame.py | 20 ++++---------------- xknx/knxip/knxip_enum.py | 8 -------- 6 files changed, 10 insertions(+), 49 deletions(-) diff --git a/test/knxip_tests/cemi_frame_test.py b/test/knxip_tests/cemi_frame_test.py index 461889cd0..81488890a 100644 --- a/test/knxip_tests/cemi_frame_test.py +++ b/test/knxip_tests/cemi_frame_test.py @@ -6,7 +6,7 @@ from xknx.dpt import DPTBinary, DPTComparator from xknx.exceptions import ConversionError, CouldNotParseKNXIP, UnsupportedCEMIMessage from xknx.knxip.cemi_frame import CEMIFrame -from xknx.knxip.knxip_enum import APCICommand, CEMIFlags, CEMIMessageCode +from xknx.knxip.knxip_enum import CEMIFlags, CEMIMessageCode from xknx.telegram import GroupAddress, GroupValueRead, IndividualAddress, Telegram @@ -50,7 +50,7 @@ def test_valid_command(frame): def test_invalid_tpci_apci(frame): """Test for invalid APCICommand""" - with raises(UnsupportedCEMIMessage, match=r".*APCI not supported: .*"): + with raises(CouldNotParseKNXIP, match=r".*APCI not supported: .*"): frame.from_knx_data_link_layer(get_data(0x29, 0, 0, 0, 0, 1, 0xFFC0, [])) @@ -63,7 +63,6 @@ def test_invalid_apdu_len(frame): def test_invalid_src_addr(frame): """Test for invalid src addr""" frame.code = CEMIMessageCode.L_DATA_IND - frame.cmd = APCICommand.GROUP_READ frame.flags = 0 frame.mpdu_len = 1 frame.payload = GroupValueRead() @@ -77,7 +76,6 @@ def test_invalid_src_addr(frame): def test_invalid_dst_addr(frame): """Test for invalid dst addr""" frame.code = CEMIMessageCode.L_DATA_IND - frame.cmd = APCICommand.GROUP_READ frame.flags = 0 frame.mpdu_len = 1 frame.payload = GroupValueRead() @@ -91,7 +89,6 @@ def test_invalid_dst_addr(frame): def test_invalid_payload(frame): """Test for having wrong payload set""" frame.code = CEMIMessageCode.L_DATA_IND - frame.cmd = APCICommand.GROUP_READ frame.flags = 0 frame.mpdu_len = 1 frame.payload = DPTComparator() @@ -119,14 +116,6 @@ def test_from_knx_with_not_implemented_cemi(frame): ) -def test_invalid_telegram(frame): - """Test for invalid telegram type""" - packet_len = frame.from_knx(get_data(0x29, 0, 0, 0, 0, 1, 0, [])) - frame.cmd = None - with raises(ConversionError, match=r".*Telegram not implemented for.*"): - tg = frame.telegram - - def test_invalid_invalid_len(frame): """Test for invalid cemi len""" with raises(UnsupportedCEMIMessage, match=r".*CEMI too small.*"): diff --git a/test/str_test.py b/test/str_test.py index 8441e649f..d19885f5a 100644 --- a/test/str_test.py +++ b/test/str_test.py @@ -481,7 +481,7 @@ def test_telegram(self): self.assertEqual( str(telegram), '" />" />', + 'destination_address="1/2/3" payload="" />" />', ) def test_dib_generic(self): @@ -649,7 +649,7 @@ def test_tunnelling_request(self): self.assertEqual( str(tunnelling_request), '" />', + ' DestinationAddress="GroupAddress("0/0/0")" Flags=" 0" payload="None" />" />', ) def test_tunnelling_ack(self): @@ -675,7 +675,7 @@ def test_cemi_frame(self): self.assertEqual( str(cemi_frame), '" />" />', + 'payload="" />" />', ) def test_knxip_frame(self): @@ -718,5 +718,5 @@ def test_routing_indication_str(self): ri = RoutingIndication(xknx) self.assertEqual( str(ri), - '" />', + '" />', ) diff --git a/xknx/io/routing.py b/xknx/io/routing.py index 57776ffb8..3fbd4aa0d 100644 --- a/xknx/io/routing.py +++ b/xknx/io/routing.py @@ -6,7 +6,6 @@ import logging from xknx.knxip import ( - APCICommand, CEMIFrame, CEMIMessageCode, KNXIPFrame, @@ -49,12 +48,6 @@ def response_rec_callback(self, knxipframe, _): return elif knxipframe.body.cemi.src_addr == self.xknx.own_address: logger.debug("Ignoring own packet") - elif knxipframe.body.cemi.cmd not in ( - APCICommand.GROUP_READ, - APCICommand.GROUP_WRITE, - APCICommand.GROUP_RESPONSE, - ): - logger.warning("APCI not implemented: %s", knxipframe) else: telegram = knxipframe.body.cemi.telegram telegram.direction = TelegramDirection.INCOMING diff --git a/xknx/knxip/__init__.py b/xknx/knxip/__init__.py index cb8edbaf5..0b1d000b9 100644 --- a/xknx/knxip/__init__.py +++ b/xknx/knxip/__init__.py @@ -14,7 +14,6 @@ from .hpai import HPAI from .knxip import KNXIPFrame from .knxip_enum import ( - APCICommand, CEMIFlags, CEMIMessageCode, ConnectRequestType, diff --git a/xknx/knxip/cemi_frame.py b/xknx/knxip/cemi_frame.py index bf4352971..21f9fb438 100644 --- a/xknx/knxip/cemi_frame.py +++ b/xknx/knxip/cemi_frame.py @@ -17,7 +17,7 @@ from xknx.telegram import GroupAddress, IndividualAddress, Telegram from xknx.telegram.apci import APCI -from .knxip_enum import APCICommand, CEMIFlags, CEMIMessageCode +from .knxip_enum import CEMIFlags, CEMIMessageCode class CEMIFrame: @@ -30,7 +30,6 @@ def __init__( xknx, code: CEMIMessageCode = CEMIMessageCode.L_DATA_IND, flags: int = 0, - cmd: APCICommand = APCICommand.GROUP_READ, src_addr: IndividualAddress = IndividualAddress(None), dst_addr: Union[GroupAddress, IndividualAddress] = GroupAddress(None), mpdu_len: int = 0, @@ -40,7 +39,6 @@ def __init__( self.xknx = xknx self.code = code self.flags = flags - self.cmd = cmd self.src_addr = src_addr self.dst_addr = dst_addr self.mpdu_len = mpdu_len @@ -160,17 +158,6 @@ def from_knx_data_link_layer(self, cemi) -> int: # TPCI (transport layer control information) -> First 14 bit # APCI (application layer control information) -> Last 10 bit - tpci_apci = cemi[9 + addil] * 256 + cemi[10 + addil] - - try: - self.cmd = APCICommand(tpci_apci & 0xFFC0) - except ValueError: - raise UnsupportedCEMIMessage( - "APCI not supported: {:#012b} in CEMI: {}".format( - tpci_apci & 0xFFC0, cemi.hex() - ) - ) - apdu = cemi[10 + addil :] if len(apdu) != self.mpdu_len: raise CouldNotParseKNXIP( @@ -179,6 +166,8 @@ def from_knx_data_link_layer(self, cemi) -> int: ) ) + tpci_apci = cemi[9 + addil] * 256 + cemi[10 + addil] + try: self.payload = APCI.resolve_class(tpci_apci & 0x03FF)() except ConversionError: @@ -215,11 +204,10 @@ def __str__(self): """Return object as readable string.""" return ( ''.format( + 'Flags="{:16b}" payload="{}" />'.format( self.src_addr.__repr__(), self.dst_addr.__repr__(), self.flags, - self.cmd, self.payload, ) ) diff --git a/xknx/knxip/knxip_enum.py b/xknx/knxip/knxip_enum.py index 2199eb2bb..f4d1e060c 100644 --- a/xknx/knxip/knxip_enum.py +++ b/xknx/knxip/knxip_enum.py @@ -49,14 +49,6 @@ class CEMIMessageCode(Enum): L_RAW_CON = 0x2F -class APCICommand(Enum): - """Enum class for KNX/IP APCI Commands.""" - - GROUP_READ = 0x0000 - GROUP_RESPONSE = 0x0040 - GROUP_WRITE = 0x0080 - - class CEMIFlags: """Enum class for KNX/IP CEMI Flags.""" From bdbb11388169bd7ae4c041a7e4511a404f70b9ac Mon Sep 17 00:00:00 2001 From: Bas Stottelaar Date: Tue, 1 Dec 2020 00:48:07 +0100 Subject: [PATCH 5/6] Adapt Home-Assistant plugin. --- home-assistant-plugin/custom_components/xknx/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/home-assistant-plugin/custom_components/xknx/__init__.py b/home-assistant-plugin/custom_components/xknx/__init__.py index 4b82e1d31..a2be6fa71 100644 --- a/home-assistant-plugin/custom_components/xknx/__init__.py +++ b/home-assistant-plugin/custom_components/xknx/__init__.py @@ -325,11 +325,11 @@ async def telegram_received_cb(self, telegram): self.hass.bus.async_fire( "knx_event", { - "data": telegram.payload.value, + "data": telegram.payload, "destination": str(telegram.destination_address), "direction": telegram.direction.value, "source": str(telegram.source_address), - "telegramtype": telegram.telegramtype.value, + "telegramtype": telegram.payload.__class__.__name__, }, ) From 7e047d6bd1ca3d090677048f05c495bd85f08340 Mon Sep 17 00:00:00 2001 From: Bas Stottelaar Date: Thu, 26 Nov 2020 22:42:47 +0100 Subject: [PATCH 6/6] Update changelog.md --- changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/changelog.md b/changelog.md index 43f43cedd..9474a6564 100644 --- a/changelog.md +++ b/changelog.md @@ -10,6 +10,8 @@ - renamed "PhysicalAddress" to "IndividualAddress" - Telegram: `group_address` renamed to `destination_address`, to prepare support for other APCI services and add `source_address` +- Telegram: remove `Telegram.telegramtype` and replace with payload object derived from `xknx.telegram.apci.APCI`. +- CEMIFrame: remove `CEMIFrame.cmd`, which can be derived from `CEMIFrame.payload`. - Farewell Travis CI; Welcome Github Actions! ## 0.15.6 Bugfix for StateUpater 2020-11-26