XKNX / xknx

XKNX - A KNX library written in Python

Home Page:http://xknx.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

System telegrams are not properly processed

knxjoerg opened this issue · comments

I am using xknx in Py3.10 on Win10 with a Weinzierl 731 KNX IP Interface.

Problem 1:
Using xknx as a simple bus-monitor system telegrams like T_Connect, T_Disconnect, DeviceDescriptor_Read, DeviceDescriptor_Response, PropertyValue_Read, PropertyValue_Response are not properly passed to the telegram_received_cb callback function.

Problem 2:
A T_Connect telegram never appears on the KNX bus. I get an "Unhandled management telegram" warning instead. I did not try any further system telegrams, because without connection, they dont make sense.

Example program:

import asyncio
from xknx import XKNX
from xknx.telegram import Telegram
from xknx.telegram.address import IndividualAddress
from xknx.telegram.tpci import TConnect

async def telegram_received_cb(telegram: Telegram):
    print("Telegram received: {0}".format(telegram))

async def main():
    xknx = XKNX(own_address="0.4.63", telegram_received_cb=telegram_received_cb) #, daemon_mode=True)
    await xknx.start()
    telegram = Telegram(source_address="0.4.63", destination_address=IndividualAddress("0.4.6"), tpci=TConnect())
    await xknx.telegrams.put(telegram)
    await asyncio.sleep(60)
    await xknx.stop()

asyncio.run(main())

Many thanks,
Joerg

Hi 👋!
Currently only incoming broadcast (group address) telegrams are put in the TelegramQueue.
For point to point telegrams we have a special package management where telegrams addressed to xknx' individual address are handled.

Have a look at
https://github.com/XKNX/xknx/blob/main/xknx/management/procedures.py

This module currently only handles outbound connections, but it should be possible to handle inbound as well.
We'd love PRs adding more procedures to that module 😉

See here for the incoming telegram filtering:

async def telegram_received(self, telegram: Telegram) -> list[Telegram] | None:

Maybe the best way to start is to describe what exactly you want to achieve.

Is there any way, to simply tell XNNX to trasmit binary telegrams bytes

not really. Everything is built on either the Telegram or the KNXIPFrame abstractions. Sure, you can hack your way around that by modifying eg. the Tunnel class, but I'd not recommend doing that.

like B0 11 FD 04 06 60 80

👀📎💬 looks like you want to do a T_Connect using an extended frame format.
Extended frame format is not explicitly supported by xknx - I have no idea if it would handle it silently or just raise some error.

pass any received KNX telegram binary to a callback function without further checks

again, no, there is no build-in callback supporting that directly. Any received data is immediately parsed to a KNXIPFrame before passing to any callback.


To do a outgoing peer to peer connection you can simply do

# create a transport layer connection context - it sends `T_Connect` on call and `T_Disconnect` when exiting
async with xknx.management.connection(address=IndividualAddress("1.2.3")) as connection:
    # the `request` method sends a request and returns the response
    response = await connection.request(
        # this is your request payload
        payload=apci.DeviceDescriptorRead(descriptor=0),
        # and this is the response you expect - if it times out or receives a different response it will raise an exception
        expected=apci.DeviceDescriptorResponse,
    )
    # do something with `response` or send additional requests...

For an example on how to handle exceptions for that, again have a look at the xknx.management.procedures module.

Incoming management connections are not supported right now. See

if isinstance(telegram.tpci, TConnect):
# refuse incoming connections
# TODO: handle incoming telegrams for connections not initiated by us, or connection-less
# TODO: maybe use outgoing telegram queue or new task to not stall the consumer task
disconnect = Telegram(
destination_address=telegram.source_address, tpci=TDisconnect()
)
response.append(disconnect)
return response

Not sure I can follow.

What do you need incoming management connections for in that case? Is xknx running on these controllers?

Incoming management telegrams that are responses to outgoing requests can be received just fine with the example above. I don't think a device should send p2p telegrams without a previous request, should it?

  • identify a device with programming button pressed or
  • wait for a programming button pressed on a device to be programmed

These two are just not implemented yet. 03_05_02 Management Procedures v01.09.02 AS.pdf describes the steps to be done.

  • make the connection to the specific device
  • close the connection

This is already covered by my second post here.

async with xknx.management.connection(address=IndividualAddress("1.2.3")) as connection:
  • send configuration data like e.g. write a new physical address or
  • write the group communication table

Again not implemented directly - as in, there is no function to pass a current and new IA and that's it. This would be an additional procedure function.
I guess it can be done manually by sending the right requests in the right order.

    response = await connection.request( ... )
  • restart the device

This is implemented as a procedure (DM_Restart):

async def dm_restart(xknx: XKNX, individual_address: IndividualAddressableType) -> None:

Here is an example on how to use it exactly:
https://github.com/XKNX/xknx/blob/main/examples/example_restart.py
As part of a bigger procedure it would have to be called manually in the existing connection context. See implementation on how to do that.

telegram = Telegram(source_address="0.4.17", destination_address="0/4/8",
telegramtype=TelegramType.GROUP_WRITE, payload=True)

Please just have a look at the signature of Telegram.__init__():
https://github.com/XKNX/xknx/blob/main/xknx/telegram/telegram.py#L33-L45
There is no telegramtype keyword argument and I don't know where you get TelegramType.GROUP_WRITE from.
Consider using a proper IDE with helpers like code completion etc. (eg. VSCode, PyCharm) this helps you find such errors easily.
Easiest way to send telegrams (high-level) is described here: https://github.com/XKNX/xknx/blob/main/examples/example_send_telegrams.py

Maybe an example in the documentation would be
helpful.

I fully agree that our documentation is not very extensive and could be much more.
The things you try to use are considered low-level - they are quite new (management) and may be subject of change in near future (not extensively tested). We try to write readable code, have good docstrings, extensive comments and type annotations to help new users understand how these low-level things work.
Some examples can be found in the examples directory.

Guess, we share a communication problem rather than a problem with the software itself. If you like, we can have a video discussion.

Feel free to join our Discord server (invite link can be found in the Readme) for a more direct conversation.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Please make sure to update to the latest version of xknx (or Home Assistant) and check if that solves the issue. Let us know if that works for you by adding a comment 👍 This issue has now been marked as stale and will be closed if no further activity occurs. Thank you for your contributions.