def test_EndTOEnd_group_write_binary_on(self):
        """Test parsing and streaming CEMIFrame KNX/IP packet, switch on light in my kitchen."""
        # Switch on Kitchen-L1
        raw = bytes.fromhex("0610053000112900BCD0FFF90149010081")
        xknx = XKNX()
        knxipframe = KNXIPFrame(xknx)
        knxipframe.from_knx(raw)
        telegram = knxipframe.body.cemi.telegram
        self.assertEqual(
            telegram,
            Telegram(
                destination_address=GroupAddress("329"),
                payload=GroupValueWrite(DPTBinary(1)),
                source_address=IndividualAddress("15.15.249"),
            ),
        )

        cemi = CEMIFrame(xknx, src_addr=IndividualAddress("15.15.249"))
        cemi.telegram = telegram
        cemi.set_hops(5)
        routing_indication = RoutingIndication(xknx, cemi=cemi)
        knxipframe2 = KNXIPFrame.init_from_body(routing_indication)

        self.assertEqual(knxipframe2.header.to_knx(), list(raw[0:6]))
        self.assertEqual(knxipframe2.body.to_knx(), list(raw[6:]))
        self.assertEqual(knxipframe2.to_knx(), list(raw))
    def test_EndTOEnd_group_write_2bytes(self):
        """Test parsing and streaming CEMIFrame KNX/IP packet, setting value of thermostat."""
        # Incoming Temperature from thermostat
        raw = bytes.fromhex("0610053000132900BCD01402080103008007C1")
        xknx = XKNX()
        knxipframe = KNXIPFrame(xknx)
        knxipframe.from_knx(raw)
        telegram = knxipframe.body.cemi.telegram
        self.assertEqual(
            telegram,
            Telegram(
                destination_address=GroupAddress("2049"),
                payload=GroupValueWrite(
                    DPTArray(DPTTemperature().to_knx(19.85))),
                source_address=IndividualAddress("1.4.2"),
            ),
        )

        cemi = CEMIFrame(xknx, src_addr=IndividualAddress("1.4.2"))
        cemi.telegram = telegram
        cemi.set_hops(5)
        routing_indication = RoutingIndication(xknx, cemi=cemi)
        knxipframe2 = KNXIPFrame.init_from_body(routing_indication)

        self.assertEqual(knxipframe2.header.to_knx(), list(raw[0:6]))
        self.assertEqual(knxipframe2.body.to_knx(), list(raw[6:]))
        self.assertEqual(knxipframe2.to_knx(), list(raw))
    def test_EndTOEnd_group_response(self):
        """Test parsing and streaming CEMIFrame KNX/IP packet, group response."""
        # Incoming state
        raw = bytes.fromhex("0610053000112900BCD013010188010041")
        xknx = XKNX()
        knxipframe = KNXIPFrame(xknx)
        knxipframe.from_knx(raw)
        telegram = knxipframe.body.cemi.telegram
        self.assertEqual(
            telegram,
            Telegram(
                destination_address=GroupAddress("392"),
                payload=GroupValueResponse(DPTBinary(1)),
                source_address=IndividualAddress("1.3.1"),
            ),
        )

        cemi = CEMIFrame(xknx, src_addr=IndividualAddress("1.3.1"))
        cemi.telegram = telegram
        cemi.set_hops(5)
        routing_indication = RoutingIndication(xknx, cemi=cemi)
        knxipframe2 = KNXIPFrame.init_from_body(routing_indication)

        self.assertEqual(knxipframe2.header.to_knx(), list(raw[0:6]))
        self.assertEqual(knxipframe2.body.to_knx(), list(raw[6:]))
        self.assertEqual(knxipframe2.to_knx(), list(raw))
Beispiel #4
0
async def test_nm_individual_address_check_refused(_if_mock):
    """Test nm_individual_address_check."""
    xknx = XKNX()
    individual_address = IndividualAddress("4.0.10")

    connect = Telegram(destination_address=individual_address,
                       tpci=tpci.TConnect())
    device_desc_read = Telegram(
        destination_address=individual_address,
        tpci=tpci.TDataConnected(0),
        payload=apci.DeviceDescriptorRead(descriptor=0),
    )
    ack = Telegram(
        source_address=individual_address,
        destination_address=IndividualAddress(0),
        direction=TelegramDirection.INCOMING,
        tpci=tpci.TAck(0),
    )
    disconnect = Telegram(
        source_address=individual_address,
        destination_address=IndividualAddress(0),
        direction=TelegramDirection.INCOMING,
        tpci=tpci.TDisconnect(),
    )
    task = asyncio.create_task(
        procedures.nm_individual_address_check(xknx, individual_address))
    await asyncio.sleep(0)
    assert xknx.knxip_interface.send_telegram.call_args_list == [
        call(connect),
        call(device_desc_read),
    ]
    xknx.management.process(disconnect)
    xknx.management.process(ack)
    assert await task
Beispiel #5
0
    def from_knx_data_link_layer(self, cemi: bytes) -> int:
        """Parse L_DATA_IND, CEMIMessageCode.L_DATA_REQ, CEMIMessageCode.L_DATA_CON."""
        if len(cemi) < 10:
            raise UnsupportedCEMIMessage(
                f"CEMI too small. Length: {len(cemi)}; CEMI: {cemi.hex()}")

        # AddIL (Additional Info Length), as specified within
        # KNX Chapter 3.6.3/4.1.4.3 "Additional information."
        # Additional information is not yet parsed.
        addil = cemi[1]
        # Control field 1 and Control field 2 - first 2 octets after Additional information
        self.flags = cemi[2 + addil] * 256 + cemi[3 + addil]

        self.src_addr = IndividualAddress((cemi[4 + addil], cemi[5 + addil]))

        dst_is_group_address = bool(self.flags
                                    & CEMIFlags.DESTINATION_GROUP_ADDRESS)
        dst_raw_address = (cemi[6 + addil], cemi[7 + addil])
        self.dst_addr = (GroupAddress(dst_raw_address) if dst_is_group_address
                         else IndividualAddress(dst_raw_address))

        npdu_len = cemi[8 + addil]

        apdu = cemi[9 + addil:]
        if len(apdu) != (npdu_len +
                         1):  # TCPI octet not included in NPDU length
            raise CouldNotParseKNXIP(
                f"APDU LEN should be {npdu_len} but is {len(apdu) - 1} in CEMI: {cemi.hex()}"
            )

        # TPCI (transport layer control information)
        # - with control bit set -> 8 bit; no APDU
        # - no control bit set (data) -> First 6 bit
        # APCI (application layer control information) -> Last  10 bit of TPCI/APCI
        try:
            self.tpci = TPCI.resolve(raw_tpci=cemi[9 + addil],
                                     dst_is_group_address=dst_is_group_address)
        except ConversionError as err:
            raise UnsupportedCEMIMessage(
                f"TPCI not supported: {cemi[9 + addil]:#10b}") from err

        if self.tpci.control:
            if npdu_len:
                raise UnsupportedCEMIMessage(
                    f"Invalid length for control TPDU {self.tpci}: {npdu_len}")
            return 10 + addil

        _apci = apdu[0] * 256 + apdu[1]
        try:
            self.payload = APCI.resolve_apci(_apci)
        except ConversionError as err:
            raise UnsupportedCEMIMessage(
                f"APCI not supported: {_apci:#012b}") from err

        self.payload.from_knx(apdu)

        return 10 + addil + npdu_len
Beispiel #6
0
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.flags == 0
    assert frame.mpdu_len == 1
    assert frame.payload == GroupValueRead()
    assert frame.src_addr == IndividualAddress(0)
    assert frame.dst_addr == IndividualAddress(0)
    assert packet_len == 11
Beispiel #7
0
Datei: xknx.py Projekt: XKNX/xknx
    def __init__(
            self,
            own_address: str | IndividualAddress = DEFAULT_ADDRESS,
            address_format: GroupAddressType = GroupAddressType.LONG,
            telegram_received_cb: Callable[[Telegram], Awaitable[None]]
        | None = None,
            device_updated_cb: Callable[[Device], Awaitable[None]]
        | None = None,
            connection_state_changed_cb: Callable[[XknxConnectionState],
                                                  Awaitable[None]]
        | None = None,
            rate_limit: int = DEFAULT_RATE_LIMIT,
            multicast_group: str = DEFAULT_MCAST_GRP,
            multicast_port: int = DEFAULT_MCAST_PORT,
            log_directory: str | None = None,
            state_updater: TrackerOptionType = False,
            daemon_mode: bool = False,
            connection_config: ConnectionConfig = ConnectionConfig(),
    ) -> None:
        """Initialize XKNX class."""
        self.connection_manager = ConnectionManager()
        self.devices = Devices()
        self.knxip_interface = knx_interface_factory(
            self, connection_config=connection_config)
        self.management = Management(self)
        self.telegrams: asyncio.Queue[Telegram | None] = asyncio.Queue()
        self.telegram_queue = TelegramQueue(self)
        self.state_updater = StateUpdater(self,
                                          default_tracker_option=state_updater)
        self.task_registry = TaskRegistry(self)

        self.current_address = IndividualAddress(0)
        self.daemon_mode = daemon_mode
        self.multicast_group = multicast_group
        self.multicast_port = multicast_port
        self.own_address = IndividualAddress(own_address)
        self.rate_limit = rate_limit
        self.sigint_received = asyncio.Event()
        self.started = asyncio.Event()
        self.version = VERSION

        GroupAddress.address_format = address_format  # for global string representation
        if log_directory is not None:
            self.setup_logging(log_directory)

        if telegram_received_cb is not None:
            self.telegram_queue.register_telegram_received_cb(
                telegram_received_cb)

        if device_updated_cb is not None:
            self.devices.register_device_updated_cb(device_updated_cb)

        if connection_state_changed_cb is not None:
            self.connection_manager.register_connection_state_changed_cb(
                connection_state_changed_cb)
Beispiel #8
0
def test_invalid_payload():
    """Test for having wrong payload set."""
    frame = CEMIFrame()
    frame.code = CEMIMessageCode.L_DATA_IND
    frame.flags = 0
    frame.payload = None
    frame.src_addr = IndividualAddress(0)
    frame.dst_addr = IndividualAddress(0)

    with pytest.raises(TypeError):
        frame.calculated_length()

    with pytest.raises(ConversionError):
        frame.to_knx()
Beispiel #9
0
def test_valid_tpci_control():
    """Test for valid tpci control."""
    raw = bytes((0x29, 0, 0, 0, 0, 0, 0, 0, 0, 0x80))
    frame = CEMIFrame()
    packet_len = frame.from_knx(raw)
    assert frame.code == CEMIMessageCode.L_DATA_IND
    assert frame.flags == 0
    assert frame.payload is None
    assert frame.src_addr == IndividualAddress(0)
    assert frame.dst_addr == IndividualAddress(0)
    assert frame.tpci == TConnect()
    assert packet_len == 10
    assert frame.calculated_length() == 10
    assert frame.to_knx() == raw
Beispiel #10
0
def test_invalid_payload(frame):
    """Test for having wrong payload set"""
    frame.code = CEMIMessageCode.L_DATA_IND
    frame.flags = 0
    frame.mpdu_len = 1
    frame.payload = DPTBinary(1)
    frame.src_addr = IndividualAddress(0)
    frame.dst_addr = IndividualAddress(0)

    with raises(TypeError):
        frame.calculated_length()

    with raises(TypeError):
        frame.to_knx()
Beispiel #11
0
    def from_knx_data_link_layer(self, cemi: bytes) -> int:
        """Parse L_DATA_IND, CEMIMessageCode.L_DATA_REQ, CEMIMessageCode.L_DATA_CON."""
        if len(cemi) < 11:
            # eg. ETS Line-Scan issues L_DATA_IND with length 10
            raise UnsupportedCEMIMessage(
                "CEMI too small. Length: {}; CEMI: {}".format(len(cemi), cemi.hex())
            )

        # AddIL (Additional Info Length), as specified within
        # KNX Chapter 3.6.3/4.1.4.3 "Additional information."
        # Additional information is not yet parsed.
        addil = cemi[1]
        # Control field 1 and Control field 2 - first 2 octets after Additional information
        self.flags = cemi[2 + addil] * 256 + cemi[3 + addil]

        self.src_addr = IndividualAddress((cemi[4 + addil], cemi[5 + addil]))

        if self.flags & CEMIFlags.DESTINATION_GROUP_ADDRESS:
            self.dst_addr = GroupAddress(
                (cemi[6 + addil], cemi[7 + addil]), levels=self.xknx.address_format
            )
        else:
            self.dst_addr = IndividualAddress((cemi[6 + addil], cemi[7 + addil]))

        self.mpdu_len = cemi[8 + addil]

        # TPCI (transport layer control information)   -> First 14 bit
        # APCI (application layer control information) -> Last  10 bit

        apdu = cemi[9 + addil :]
        if len(apdu) != (self.mpdu_len + 1):
            raise CouldNotParseKNXIP(
                "APDU LEN should be {} but is {} in CEMI: {}".format(
                    self.mpdu_len, len(apdu), cemi.hex()
                )
            )

        tpci_apci = (apdu[0] << 8) + apdu[1]

        try:
            self.payload = APCI.resolve_apci(tpci_apci & 0x03FF)
        except ConversionError:
            raise UnsupportedCEMIMessage(
                "APCI not supported: {:#012b}".format(tpci_apci & 0x03FF)
            )

        self.payload.from_knx(apdu)

        return 10 + addil + self.mpdu_len
Beispiel #12
0
def fake_router_search_response(xknx: XKNX) -> KNXIPFrame:
    """Return the KNXIPFrame of a KNX/IP Router with a SearchResponse body."""
    frame_body = SearchResponse(xknx)
    frame_body.control_endpoint = HPAI(ip_addr="192.168.42.10", port=3671)

    device_information = DIBDeviceInformation()
    device_information.name = "Gira KNX/IP-Router"
    device_information.serial_number = "11:22:33:44:55:66"
    device_information.individual_address = IndividualAddress("1.1.0")
    device_information.mac_address = "01:02:03:04:05:06"

    svc_families = DIBSuppSVCFamilies()
    svc_families.families.append(
        DIBSuppSVCFamilies.Family(name=DIBServiceFamily.CORE, version=1))
    svc_families.families.append(
        DIBSuppSVCFamilies.Family(name=DIBServiceFamily.DEVICE_MANAGEMENT,
                                  version=2))
    svc_families.families.append(
        DIBSuppSVCFamilies.Family(name=DIBServiceFamily.TUNNELING, version=1))
    svc_families.families.append(
        DIBSuppSVCFamilies.Family(name=DIBServiceFamily.ROUTING, version=1))
    svc_families.families.append(
        DIBSuppSVCFamilies.Family(
            name=DIBServiceFamily.REMOTE_CONFIGURATION_DIAGNOSIS, version=1))

    frame_body.dibs.append(device_information)
    frame_body.dibs.append(svc_families)

    return KNXIPFrame.init_from_body(frame_body)
Beispiel #13
0
 def test_config_general(self):
     """Test reading general section from config file."""
     self.assertEqual(TestConfig.xknx.own_address,
                      IndividualAddress("15.15.249"))
     self.assertEqual(TestConfig.xknx.rate_limit, 18)
     self.assertEqual(TestConfig.xknx.multicast_group, "224.1.2.3")
     self.assertEqual(TestConfig.xknx.multicast_port, 1337)
Beispiel #14
0
 def test_dib_device_informatio(self):
     """Test string representation of DIBDeviceInformation."""
     dib = DIBDeviceInformation()
     dib.knx_medium = KNXMedium.TP1
     dib.programming_mode = False
     dib.individual_address = IndividualAddress("1.1.0")
     dib.name = "Gira KNX/IP-Router"
     dib.mac_address = "00:01:02:03:04:05"
     dib.multicast_address = "224.0.23.12"
     dib.serial_number = "13:37:13:37:13:37"
     dib.project_number = 564
     dib.installation_number = 2
     self.assertEqual(
         str(dib),
         "<DIBDeviceInformation \n"
         '\tknx_medium="KNXMedium.TP1" \n'
         '\tprogramming_mode="False" \n'
         '\tindividual_address="1.1.0" \n'
         '\tinstallation_number="2" \n'
         '\tproject_number="564" \n'
         '\tserial_number="13:37:13:37:13:37" \n'
         '\tmulticast_address="224.0.23.12" \n'
         '\tmac_address="00:01:02:03:04:05" \n'
         '\tname="Gira KNX/IP-Router" />',
     )
Beispiel #15
0
async def test_ack_timeout(_if_mock, time_travel):
    """Test ACK timeout handling."""
    xknx = XKNX()
    _ia = IndividualAddress("4.0.1")

    conn = await xknx.management.connect(_ia)
    xknx.knxip_interface.send_telegram.reset_mock()

    device_desc_read = Telegram(
        destination_address=_ia,
        tpci=tpci.TDataConnected(0),
        payload=apci.DeviceDescriptorRead(descriptor=0),
    )
    task = asyncio.create_task(
        conn.request(
            payload=apci.DeviceDescriptorRead(descriptor=0),
            expected=apci.DeviceDescriptorResponse,
        ))
    await asyncio.sleep(0)
    assert xknx.knxip_interface.send_telegram.call_args_list == [
        call(device_desc_read),
    ]
    await time_travel(MANAGAMENT_ACK_TIMEOUT)
    # telegram repeated
    assert xknx.knxip_interface.send_telegram.call_args_list == [
        call(device_desc_read),
        call(device_desc_read),
    ]
    await time_travel(MANAGAMENT_ACK_TIMEOUT)
    with pytest.raises(ManagementConnectionTimeout):
        # still no ACK -> timeout
        await task

    await conn.disconnect()
Beispiel #16
0
 def test_telegram_not_equal(self):
     """Test not equals operator."""
     assert Telegram(GroupAddress("1/2/3"),
                     payload=GroupValueRead()) != Telegram(
                         GroupAddress("1/2/4"), payload=GroupValueRead())
     assert Telegram(
         GroupAddress("1/2/3"), payload=GroupValueRead()) != Telegram(
             GroupAddress("1/2/3"), payload=GroupValueWrite(DPTBinary(1)))
     assert Telegram(GroupAddress("1/2/3"),
                     payload=GroupValueRead()) != Telegram(
                         GroupAddress("1/2/3"),
                         TelegramDirection.INCOMING,
                         payload=GroupValueRead(),
                     )
     assert Telegram(IndividualAddress(1), tpci=TConnect()) != Telegram(
         IndividualAddress(1), tpci=TDisconnect())
Beispiel #17
0
def test_telegram_individual_address():
    """Test telegram conversion flags with a individual address."""
    frame = CEMIFrame()
    frame.telegram = Telegram(destination_address=IndividualAddress(0))

    assert (
        frame.flags & CEMIFlags.DESTINATION_INDIVIDUAL_ADDRESS
    ) == CEMIFlags.DESTINATION_INDIVIDUAL_ADDRESS
Beispiel #18
0
async def test_connect(_if_mock):
    """Test establishing connections."""
    xknx = XKNX()
    ia_1 = IndividualAddress("4.0.1")
    ia_2 = IndividualAddress("4.0.2")

    def tg_connect(ia):
        return Telegram(
            source_address=xknx.current_address,
            destination_address=ia,
            direction=TelegramDirection.OUTGOING,
            tpci=tpci.TConnect(),
        )

    def tg_disconnect(ia):
        return Telegram(
            source_address=xknx.current_address,
            destination_address=ia,
            direction=TelegramDirection.OUTGOING,
            tpci=tpci.TDisconnect(),
        )

    await xknx.management.connect(ia_1)
    conn_2 = await xknx.management.connect(ia_2)

    with pytest.raises(ManagementConnectionError):
        # no 2 connections to the same IA
        await xknx.management.connect(ia_1)

    assert xknx.knxip_interface.send_telegram.call_args_list == [
        call(tg_connect(ia_1)),
        call(tg_connect(ia_2)),
    ]
    xknx.knxip_interface.send_telegram.reset_mock()

    await xknx.management.disconnect(ia_1)
    await conn_2.disconnect()

    assert xknx.knxip_interface.send_telegram.call_args_list == [
        call(tg_disconnect(ia_1)),
        call(tg_disconnect(ia_2)),
    ]

    # connect again doesn't raise
    await xknx.management.connect(ia_1)
Beispiel #19
0
 def init_from_telegram(
         telegram: Telegram,
         code: CEMIMessageCode = CEMIMessageCode.L_DATA_IND,
         src_addr: IndividualAddress = IndividualAddress(None),
 ) -> CEMIFrame:
     """Return CEMIFrame from a Telegram."""
     cemi = CEMIFrame(code=code, src_addr=src_addr)
     # dst_addr, payload and cmd are set by telegram.setter - mpdu_len not needed for outgoing telegram
     cemi.telegram = telegram
     return cemi
Beispiel #20
0
    def parse_xml(self, node: Document) -> None:
        """Parse all needed attributes from the given node map."""
        attributes = node.attributes
        self.type = InterfaceType(
            self.get_attribute_value(attributes.get("Type")))
        self.host = IndividualAddress(
            self.get_attribute_value(attributes.get("Host")))
        self.user_id = int(
            self.get_attribute_value(attributes.get("UserID")) or 2)
        self.password = self.get_attribute_value(attributes.get("Password"))
        self.individual_address = IndividualAddress(
            self.get_attribute_value(attributes.get("IndividualAddress")))
        self.authentication = self.get_attribute_value(
            attributes.get("Authentication"))

        for assigned_ga in filter(lambda x: x.nodeType != 3, node.childNodes):
            group_address: XMLAssignedGroupAddress = XMLAssignedGroupAddress()
            group_address.parse_xml(assigned_ga)
            self.group_addresses.append(group_address)
Beispiel #21
0
Datei: dib.py Projekt: XKNX/xknx
 def __init__(self) -> None:
     """Initialize DIBDeviceInformation class."""
     self.knx_medium: KNXMedium = KNXMedium.TP1
     self.programming_mode: bool = False
     self.individual_address: IndividualAddress = IndividualAddress(None)
     self.installation_number: int = 0
     self.project_number: int = 0
     self.serial_number: str = ""
     self.multicast_address: str = "224.0.23.12"
     self.mac_address: str = ""
     self.name: str = ""
Beispiel #22
0
def test_invalid_dst_addr(frame):
    """Test for invalid dst addr"""
    frame.code = CEMIMessageCode.L_DATA_IND
    frame.flags = 0
    frame.mpdu_len = 1
    frame.payload = GroupValueRead()
    frame.src_addr = IndividualAddress(0)
    frame.dst_addr = None

    with raises(ConversionError, match=r"dst_addr not set"):
        frame.to_knx()
Beispiel #23
0
def test_invalid_src_addr():
    """Test for invalid src addr."""
    frame = CEMIFrame()
    frame.code = CEMIMessageCode.L_DATA_IND
    frame.flags = 0
    frame.payload = GroupValueRead()
    frame.src_addr = GroupAddress(0)
    frame.dst_addr = IndividualAddress(0)

    with pytest.raises(ConversionError, match=r"src_addr invalid"):
        frame.to_knx()
Beispiel #24
0
def test_telegram_individual_address():
    """Test telegram conversion flags with a individual address."""
    frame = CEMIFrame()
    _telegram = Telegram(destination_address=IndividualAddress(0), tpci=TConnect())
    # test CEMIFrame.telegram setter
    frame.telegram = _telegram
    assert frame.flags & 0x0080 == CEMIFlags.DESTINATION_INDIVIDUAL_ADDRESS
    assert frame.flags & 0x0C00 == CEMIFlags.PRIORITY_SYSTEM
    assert frame.flags & 0x0200 == CEMIFlags.NO_ACK_REQUESTED
    # test CEMIFrame.telegram property
    assert frame.telegram == _telegram
Beispiel #25
0
    def from_knx(self, raw: bytes) -> int:
        """Parse/deserialize from KNX/IP raw data."""
        if len(raw) < DIBDeviceInformation.LENGTH:
            raise CouldNotParseKNXIP("wrong connection header length")
        if raw[0] != DIBDeviceInformation.LENGTH:
            raise CouldNotParseKNXIP("wrong connection header length")
        if DIBTypeCode(raw[1]) != DIBTypeCode.DEVICE_INFO:
            raise CouldNotParseKNXIP("DIB is no device info")

        self.knx_medium = KNXMedium(raw[2])
        # last bit of device_status. All other bits are unused
        self.programming_mode = bool(raw[3])
        self.individual_address = IndividualAddress((raw[4], raw[5]))
        installation_project_identifier = raw[6] * 256 + raw[7]
        self.project_number = installation_project_identifier >> 4
        self.installation_number = installation_project_identifier & 15
        self.serial_number = ":".join("%02x" % i for i in raw[8:14])
        self.multicast_address = ".".join("%i" % i for i in raw[14:18])
        self.mac_address = ":".join("%02x" % i for i in raw[18:24])
        self.name = "".join(map(chr, raw[24:54])).rstrip("\0")
        return DIBDeviceInformation.LENGTH
Beispiel #26
0
 def parse_general(self, doc):
     """Parse the general section of xknx.yaml."""
     if "general" in doc:
         if "own_address" in doc["general"]:
             self.xknx.own_address = IndividualAddress(
                 doc["general"]["own_address"])
         if "rate_limit" in doc["general"]:
             self.xknx.rate_limit = doc["general"]["rate_limit"]
         if "multicast_group" in doc["general"]:
             self.xknx.multicast_group = doc["general"]["multicast_group"]
         if "multicast_port" in doc["general"]:
             self.xknx.multicast_port = doc["general"]["multicast_port"]
Beispiel #27
0
 def parse_xml(self, node: Document) -> None:
     """Parse all needed attributes from the given node map."""
     attributes = node.attributes
     self.individual_address = IndividualAddress(
         self.get_attribute_value(attributes.get("IndividualAddress")))
     self.tool_key = self.get_attribute_value(attributes.get("ToolKey"))
     self.management_password = self.get_attribute_value(
         attributes.get("ManagementPassword"))
     self.authentication = self.get_attribute_value(
         attributes.get("Authentication"))
     self.sequence_number = int(
         self.get_attribute_value(attributes.get("SequenceNumber", 0)))
Beispiel #28
0
 def test_with_valid(self):
     """Test with some valid addresses."""
     valid_addresses = (
         ("0.0.0", 0),
         ("123", 123),
         ("1.0.0", 4096),
         ("1.1.0", 4352),
         ("1.1.1", 4353),
         ("1.1.11", 4363),
         ("1.1.111", 4463),
         ("1.11.111", 7023),
         ("11.11.111", 47983),
         (IndividualAddress("11.11.111"), 47983),
         ("15.15.255", 65535),
         ((0xFF, 0xFF), 65535),
         (0, 0),
         (65535, 65535),
     )
     for address in valid_addresses:
         with self.subTest(address=address):
             self.assertEqual(IndividualAddress(address[0]).raw, address[1])
Beispiel #29
0
 def test_gateway_descriptor(self):
     """Test string representation of GatewayDescriptor."""
     gateway_descriptor = GatewayDescriptor(
         name="KNX-Interface",
         ip_addr="192.168.2.3",
         port=1234,
         local_interface="en1",
         local_ip="192.168.2.50",
         supports_tunnelling=True,
         supports_routing=False,
         individual_address=IndividualAddress("1.1.1"),
     )
     assert str(gateway_descriptor) == "1.1.1 - KNX-Interface @ 192.168.2.3:1234"
Beispiel #30
0
    async def test_payload_reader_send_timeout(self, logger_warning_mock):
        """Test payload reader: timeout while waiting for response."""
        xknx = XKNX()

        destination_address = IndividualAddress("1.2.3")
        request_payload = MemoryRead(0xAABB, 3)

        payload_reader = PayloadReader(xknx,
                                       destination_address,
                                       timeout_in_seconds=0)

        payload = await payload_reader.send(request_payload,
                                            response_class=MemoryResponse)

        # No response received.
        assert payload is None
        # Warning was logged.
        logger_warning_mock.assert_called_once_with(
            "Error: KNX bus did not respond in time (%s secs) to payload request for: %s",
            0.0,
            IndividualAddress("1.2.3"),
        )