Zigbee-Routing: Ein oft übersehener Performance-Faktor?

Moin zusammen,

ich habe ja an der einen oder anderen Stelle schon über Source Routing und dessen Vorteile gesprochen. Da ich das Ganze aber mal genauer quantifizieren wollte, habe ich einige Tests durchgeführt – und ehrlich gesagt, hätte ich mit diesen Zahlen nicht gerechnet. Auch wenn der Unterschied spürbar ist, zeigen die Messungen noch viel deutlicher, wie viel effizienter Source Routing gegenüber Table Routing arbeitet.

Du hast keine Ahnung, wovon ich rede? Source? Table? Was? Kein Problem! Der folgende Beitrag holt dich mit ein paar technischen Details ab. Falls dich die Hintergründe und detaillierten Zeitmessungen nicht interessieren, kannst du diesen auch gerne überspringen und unten weiterlesen.

Im Wesentlichen gibt es im Zigbee-Standard zwei verschiedene Methoden, um Nachrichten innerhalb des Netzwerks zu vermitteln:

  • Table Routing setzt auf eine verteilte Logik, bei der jeder Router eigenständig entscheidet, wie Nachrichten weitergeleitet werden.
  • Source Routing verfolgt einen zentralisierten Ansatz, bei dem der Koordinator die Route vorgibt, wodurch weniger Netzwerkverkehr entsteht.

ZHA nutzt standardmäßig Table Routing. Das lässt sich aber über die configuration.yaml ändern. Zigbee2MQTT hingegen aktiviert Source Routing – je nach Koordinator – bereits von Haus aus. Beide Methoden haben ihre Vor- und Nachteile.

Der direkte Vergleich zeigt jedoch, dass Source Routing deutlich effizienter arbeitet. Und ja, wir sprechen hier über Zahlen, die auf den ersten Blick nicht dramatisch klingen.

Table Routing: 383 ms vs. Source Routing: 59 ms für dieselbe Aktion

Mag nicht nach viel klingen, oder? Schließlich sind beide Werte unter einer Sekunde. Aber jetzt stell dir vor, du hast eine Automation, die mehrere Geräte gleichzeitig ansteuert – zum Beispiel Bewegungsmelder → Licht → mehrere andere Geräte. Jede dieser Verzögerungen summiert sich, wodurch sich dein gesamtes Smart Home träger anfühlt.

Das größere Problem ist aber nicht nur die Verzögerung, sondern was im Hintergrund passiert. Beim Table Routing werden ständig neue Routen gesucht, wenn ein Gerät keine aktuelle Route hat. Dabei wird das Zigbee-Netz mit Broadcasts überflutet, und während dieser Zeit können andere Geräte nicht kommunizieren. Das führt dazu, dass

  • Automationen verzögert oder nicht ausgeführt werden
  • Pakete verloren gehen
  • Das Netzwerk insgesamt instabiler wirkt

Das passiert natürlich nicht immer, aber besonders in größeren Netzwerken mit vielen Routern kann es zu echten Problemen führen.

Falls du Source Routing ausprobieren möchtest, ist die Aktivierung denkbar einfach:

  1. Öffne die Datei configuration.yaml

  2. Füge den folgenden Eintrag hinzu (oder passe ihn an, falls bereits vorhanden):

    zha:
      zigpy_config:
        source_routing: true
    
  3. Speichere die Änderungen

  4. Starte Home Assistant neu, damit die Konfiguration übernommen wird

Sobald Home Assistant wieder läuft, nutzt ZHA Source Routing anstelle von Table Routing. Damit die Routen optimal gesetzt werden, sollte dem Koordinator etwas Zeit gegeben werden – nach etwa zehn Minuten sollten bereits spürbare Verbesserungen in der Stabilität und Reaktionsgeschwindigkeit auftreten.

Mich würde wirklich interessieren, ob andere die gleichen Unterschiede bemerken wie ich. Falls du ZHA nutzt, probiere Source Routing doch einfach mal aus. Läuft dein Netzwerk danach stabiler? Reagieren deine Automationen schneller? Oder hast du vielleicht unerwartete Nebenwirkungen festgestellt?

Teile deine Erfahrungen – vielleicht hilft das ja auch dabei, Source Routing in ZHA langfristig als Standard zu etablieren.

VG, Cem

11 „Gefällt mir“

Herzlichen Dank für den Beitrag. Gleich aktiviert und schon einen Fehler im Log weniger wo gemeldet wurde, dass die Laufzeit eines Gerätes zu lange auf sich warten lässt :+1: hat sich also schon gelohnt :smiling_face: danke!

Edit: zu früh gefreut, der Traceback Error taucht auch hier immer wieder auf…

1 „Gefällt mir“

Moin,

schade, das wäre doch ein perfektes Beispiel gewesen! :smiley: Hast du einen Traceback oder kannst du genauer beschreiben, welche Aktion den Fehler auslöst? Würde mich interessieren, ob sich daraus noch was ableiten lässt.

Ich habe gestern in der Home Assistant Reddit-Community mal nachgefragt und schon einiges an Feedback bekommen - unter anderem auch von einigen ZHA-Maintainern. Bisher scheint das Aktivieren von Source Routing bei den meisten eher positiv auszuwirken, was ziemlich spannend ist.

Konntest du denn insgesamt einen Unterschied feststellen, oder läuft bei dir alles wie vorher?

Viele Grüße,
Cem

Du versuchst hier ziemlich durchschaubar, Deinen Blog zu promoten und Traffic abzugreifen. Dazu machst Du neue Themen auf und formulierst diese als Streitthemen in Form offener Fragen, was möglichst viele triggern soll
Zigbee2MQTT vs. ZHA – Ist Z2M wirklich noch die bessere Wahl?
Zigbee-Routing: Ein oft übersehener Performance-Faktor?
Usw.

Aber es ist nicht an mir, das zu entscheiden. Das müssen die Mods tun.

2 „Gefällt mir“

Gefühlt würde ich tatsächlich sagen, dass es minimal schneller geworden ist :+1:

Fehler ist bei mir folgender

Logger: zigpy.zcl
Quelle: runner.py:154
Erstmals aufgetreten: 15. Februar 2025 um 21:06:32 (76 Vorkommnisse)
Zuletzt protokolliert: 08:58:47

[0x2DC8:1:0x0020] Traceback (most recent call last): File "/usr/local/lib/python3.13/site-packages/zigpy/endpoint.py", line 270, in request return await self.device.request( ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...<11 lines>... ) ^ File "/usr/local/lib/python3.13/site-packages/zigpy/device.py", line 378, in request await send_request() File "/usr/local/lib/python3.13/site-packages/zigpy/application.py", line 835, in request await self.send_packet( ...<14 lines>... ) File "/usr/local/lib/python3.13/site-packages/bellows/zigbee/application.py", line 937, in send_packet raise zigpy.exceptions.DeliveryError( f"Failed to deliver message: {send_status!r}", send_status ) zigpy.exceptions.DeliveryError: Failed to deliver message: <sl_Status.ZIGBEE_DELIVERY_FAILED: 3074> The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/local/lib/python3.13/site-packages/zha/zigbee/cluster_handlers/general.py", line 630, in check_in_response await self.checkin_response(True, self.CHECKIN_FAST_POLL_TIMEOUT, tsn=tsn) File "/usr/local/lib/python3.13/site-packages/zha/zigbee/cluster_handlers/__init__.py", line 85, in wrapper with wrap_zigpy_exceptions(): ~~~~~~~~~~~~~~~~~~~~~^^ File "/usr/local/lib/python3.13/contextlib.py", line 162, in __exit__ self.gen.throw(value) ~~~~~~~~~~~~~~^^^^^^^ File "/usr/local/lib/python3.13/site-packages/zha/zigbee/cluster_handlers/__init__.py", line 77, in wrap_zigpy_exceptions raise ZHAException(message) from exc zha.exceptions.ZHAException: Failed to send request: Failed to deliver message: <sl_Status.ZIGBEE_DELIVERY_FAILED: 3074>
[0x53EA:1:0x0020] Traceback (most recent call last): File "/usr/local/lib/python3.13/site-packages/zigpy/endpoint.py", line 270, in request return await self.device.request( ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...<11 lines>... ) ^ File "/usr/local/lib/python3.13/site-packages/zigpy/device.py", line 378, in request await send_request() File "/usr/local/lib/python3.13/site-packages/zigpy/application.py", line 835, in request await self.send_packet( ...<14 lines>... ) File "/usr/local/lib/python3.13/site-packages/bellows/zigbee/application.py", line 937, in send_packet raise zigpy.exceptions.DeliveryError( f"Failed to deliver message: {send_status!r}", send_status ) zigpy.exceptions.DeliveryError: Failed to deliver message: <sl_Status.ZIGBEE_DELIVERY_FAILED: 3074> The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/local/lib/python3.13/site-packages/zha/zigbee/cluster_handlers/general.py", line 630, in check_in_response await self.checkin_response(True, self.CHECKIN_FAST_POLL_TIMEOUT, tsn=tsn) File "/usr/local/lib/python3.13/site-packages/zha/zigbee/cluster_handlers/__init__.py", line 85, in wrapper with wrap_zigpy_exceptions(): ~~~~~~~~~~~~~~~~~~~~~^^ File "/usr/local/lib/python3.13/contextlib.py", line 162, in __exit__ self.gen.throw(value) ~~~~~~~~~~~~~~^^^^^^^ File "/usr/local/lib/python3.13/site-packages/zha/zigbee/cluster_handlers/__init__.py", line 77, in wrap_zigpy_exceptions raise ZHAException(message) from exc zha.exceptions.ZHAException: Failed to send request: Failed to deliver message: <sl_Status.ZIGBEE_DELIVERY_FAILED: 3074>
[0xD16B:1:0x0020] Traceback (most recent call last): File "/usr/local/lib/python3.13/site-packages/zigpy/endpoint.py", line 270, in request return await self.device.request( ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...<11 lines>... ) ^ File "/usr/local/lib/python3.13/site-packages/zigpy/device.py", line 378, in request await send_request() File "/usr/local/lib/python3.13/site-packages/zigpy/application.py", line 835, in request await self.send_packet( ...<14 lines>... ) File "/usr/local/lib/python3.13/site-packages/bellows/zigbee/application.py", line 937, in send_packet raise zigpy.exceptions.DeliveryError( f"Failed to deliver message: {send_status!r}", send_status ) zigpy.exceptions.DeliveryError: Failed to deliver message: <sl_Status.ZIGBEE_DELIVERY_FAILED: 3074> The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/local/lib/python3.13/site-packages/zha/zigbee/cluster_handlers/general.py", line 630, in check_in_response await self.checkin_response(True, self.CHECKIN_FAST_POLL_TIMEOUT, tsn=tsn) File "/usr/local/lib/python3.13/site-packages/zha/zigbee/cluster_handlers/__init__.py", line 85, in wrapper with wrap_zigpy_exceptions(): ~~~~~~~~~~~~~~~~~~~~~^^ File "/usr/local/lib/python3.13/contextlib.py", line 162, in __exit__ self.gen.throw(value) ~~~~~~~~~~~~~~^^^^^^^ File "/usr/local/lib/python3.13/site-packages/zha/zigbee/cluster_handlers/__init__.py", line 77, in wrap_zigpy_exceptions raise ZHAException(message) from exc zha.exceptions.ZHAException: Failed to send request: Failed to deliver message: <sl_Status.ZIGBEE_DELIVERY_FAILED: 3074>
[0xDD1D:1:0x0020] Traceback (most recent call last): File "/usr/local/lib/python3.13/site-packages/zigpy/endpoint.py", line 270, in request return await self.device.request( ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...<11 lines>... ) ^ File "/usr/local/lib/python3.13/site-packages/zigpy/device.py", line 378, in request await send_request() File "/usr/local/lib/python3.13/site-packages/zigpy/application.py", line 835, in request await self.send_packet( ...<14 lines>... ) File "/usr/local/lib/python3.13/site-packages/bellows/zigbee/application.py", line 937, in send_packet raise zigpy.exceptions.DeliveryError( f"Failed to deliver message: {send_status!r}", send_status ) zigpy.exceptions.DeliveryError: Failed to deliver message: <sl_Status.ZIGBEE_DELIVERY_FAILED: 3074> The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/local/lib/python3.13/site-packages/zha/zigbee/cluster_handlers/general.py", line 632, in check_in_response await self.set_long_poll_interval(self.LONG_POLL) File "/usr/local/lib/python3.13/site-packages/zha/zigbee/cluster_handlers/__init__.py", line 85, in wrapper with wrap_zigpy_exceptions(): ~~~~~~~~~~~~~~~~~~~~~^^ File "/usr/local/lib/python3.13/contextlib.py", line 162, in __exit__ self.gen.throw(value) ~~~~~~~~~~~~~~^^^^^^^ File "/usr/local/lib/python3.13/site-packages/zha/zigbee/cluster_handlers/__init__.py", line 77, in wrap_zigpy_exceptions raise ZHAException(message) from exc zha.exceptions.ZHAException: Failed to send request: Failed to deliver message: <sl_Status.ZIGBEE_DELIVERY_FAILED: 3074>
[0x54B5:1:0x0020] Traceback (most recent call last): File "/usr/local/lib/python3.13/site-packages/zigpy/endpoint.py", line 270, in request return await self.device.request( ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...<11 lines>... ) ^ File "/usr/local/lib/python3.13/site-packages/zigpy/device.py", line 378, in request await send_request() File "/usr/local/lib/python3.13/site-packages/zigpy/application.py", line 835, in request await self.send_packet( ...<14 lines>... ) File "/usr/local/lib/python3.13/site-packages/bellows/zigbee/application.py", line 937, in send_packet raise zigpy.exceptions.DeliveryError( f"Failed to deliver message: {send_status!r}", send_status ) zigpy.exceptions.DeliveryError: Failed to deliver message: <sl_Status.ZIGBEE_DELIVERY_FAILED: 3074> The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/local/lib/python3.13/site-packages/zha/zigbee/cluster_handlers/general.py", line 630, in check_in_response await self.checkin_response(True, self.CHECKIN_FAST_POLL_TIMEOUT, tsn=tsn) File "/usr/local/lib/python3.13/site-packages/zha/zigbee/cluster_handlers/__init__.py", line 85, in wrapper with wrap_zigpy_exceptions(): ~~~~~~~~~~~~~~~~~~~~~^^ File "/usr/local/lib/python3.13/contextlib.py", line 162, in __exit__ self.gen.throw(value) ~~~~~~~~~~~~~~^^^^^^^ File "/usr/local/lib/python3.13/site-packages/zha/zigbee/cluster_handlers/__init__.py", line 77, in wrap_zigpy_exceptions raise ZHAException(message) from exc zha.exceptions.ZHAException: Failed to send request: Failed to deliver message: <sl_Status.ZIGBEE_DELIVERY_FAILED: 3074>

Ganz ehrlich: es gibt hier 1000 Z2M Threads und dich stören 2 Threads welche ZHA in den Vordergrund rücken? Da gibt es andere Themen, welche du getrost ignorieren darfst, wenn du sie nicht magst und offensichtlich auch kein ZHA Nutzer bist.
Mir bringt der Thread hier auf jeden Fall was und bin froh, dass ich hier jetzt auch noch ein paar andere ZHA Nutzer kennenlerne

3 „Gefällt mir“

Das ist eine Art die Dinge zu betrachten oder: Ich greife offene Fragestellungen auf und teile meine Erfahrungen dazu. Es ist offensichtlich, dass das für dich keinen Mehrwert bietet - was absolut in Ordnung ist. Ich schätze deine Offenheit in diesem Punkt. Mein Eingangspost enthält alle notwendigen Informationen, und es gibt hier einige Nutzer, die ZHA verwenden, aber möglicherweise noch nichts von Source Routing gehört haben oder nicht wissen, dass es überhaupt eine Option gibt.

Falls du offen für andere Perspektiven bist, könntest du dir diese Diskussion ansehen. Vielleicht liefert sie einen neuen Blickwinkel und regt dazu an, dein Feedback noch einmal zu überdenken.


Das klingt vielversprechend. Siehst du nur den Traceback, oder wird die damit verbundene Aktion ebenfalls nicht korrekt ausgeführt? Dieser Fehler wird auch protokolliert, wenn einer von mehreren Versuchen aufgrund eines Timeouts fehlschlägt. Zigbee bzw. Bellows ist in dieser Hinsicht sehr timing-kritisch - wenn innerhalb eines bestimmten Zeitraums kein Acknowledge empfangen wird, erscheint dieser Logeintrag.

1 „Gefällt mir“

Von den Aktionen läuft bisher alles, da ist mir noch nichts aufgefallen, was nicht laufen würde. Ich tippe auf einen Aktor im Keller, der vom Empfang nicht so toll ist

Für mich ist es egal ob ein Anwender seine Lösungen auch woanders veröffentlicht. Was in meinen Augen zählt, jemand ist bereit, sein Wissen zu teilen. Im Ernstfall finde ich eine Hilfe lieber mehrfach als gar nicht.

10 „Gefällt mir“

Falls du noch einen EZSP-fähigen USB-Koordinator zur Hand hast, könnte ein Mitschnitt aufschlussreich sein. Alternativ kannst du die Debug-Protokollierung von ZHA aktivieren und den Fehler gezielt reproduzieren. So lässt sich möglicherweise der genaue Verursacher identifizieren – und vielleicht sogar die Ursache direkt erkennen.

Entweder habe ich mich schlecht ausgedrückt oder Du mich falsch verstanden. Mich stören Threads zu ZHA nicht im Geringsten. Threads, die mich nicht interessieren, muss ich ja nicht lesen. Welches Recht hätte ich, mich darüber aufzuregen, dass andere sich für andere Themen interessieren als ich?

Mich stört, wenn jemand ein Forum, eine Community missbraucht, um nur seine private Website zu promoten. Typischerweise mit dem Ziel, sie früher oder später zu monetarisieren. In anderen Foren wird so etwas meist unterbunden. Aber wie ich schon gesagt habe: Wenn das für die Mods hier OK ist, dann ist das eben so.

Das ist jetzt aber sehr viel Vorwurf mit einer Menge Meinung…

Vielleicht kann das in einem Blog einfach besser erklärt werden als in einem Forum? Ich finde den Artikel sehr spannend, auch wenn ich Z2M nutze - und auch den Blog an sich.

Leben und leben lassen :wink:

1 „Gefällt mir“

Das heißt, wenn die Verlinkung auf Deinen Blog entfernt wird, ist das für Dich kein Problem. Richtig?

1 „Gefällt mir“

Moment, ich muss mir den Link erst kopieren :smile:

2 „Gefällt mir“

Mir geht es in erster Linie darum, das Thema mit der Community zu teilen und zu diskutieren. Die Kerninhalte habe ich bereits direkt im Beitrag wiedergegeben, sodass alle relevanten Informationen auch ohne den Link verfügbar sind. Die Verlinkung dient lediglich als Referenz für weiterführende Details, falls jemand tiefer in das Thema einsteigen möchte. Falls das problematisch ist, steht es dir natürlich frei, den Link zu entfernen.

Darüber hinaus wäre es hilfreich, wenn diejenigen, die Source Routing in ZHA getestet haben, ihre Erfahrungen in der GitHub Discussion zur zigpy-Library (ZHA’s Schnittstelle zur Hardware) teilen könnten.

In Zigbee2MQTT ist Source Routing per default aktiviert, und mit genug Feedback könnte es auch in ZHA zur Standard-Einstellung werden - vorausgesetzt, es bewährt sich als stabiler und effizienter. Falls ihr es getestet habt, wäre es super, wenn ihr eure Erfahrungen an der GitHub Discussion teilt. Jede Rückmeldung - egal ob positiv oder negativ - hilft, das Ganze voranzubringen!

1 „Gefällt mir“

Danke, klingt sehr interessant und ich finde deinen Post hier auch vollständig genug ohne dein Blog zu lesen. Auch die Diskussion auf github ist spannend.

Mein Netzwerk ist klein mit wenigen Geräten. Echte Performance Unterschiede erwarte ich jetzt nicht. Ich habe einfach mal umgestellt und HA neu gestartet.

Wie kann ich denn feststellen, dass ich es richtig konfiguriert habe? Gibt es einen Log-Eintrag irgendwo?

Du kannst dir die Diagnose Daten der ZHA Integration ziehen und dir den Abschnitt zigpy_config anschauen:

Hier sollte dann bestätigt werden das source_routing aktiv ist.

VG, Cem

1 „Gefällt mir“

Ich steig hier nicht in die Diskussion ein, ob Z2M noch Sinn macht oder nicht:
ich habe Z2M und warum steht ganz unten.

Zum Post im eigentlichem: Die Performance der Routing-Unterschiede sind deutlich und Interessant für jeden Netzwerker. Danke für den Aufzeig, das war mir selbst auch nicht bewusst. Insofern gut, dass es in der Integration umstellbar ist.

Ach ja, warum Z2M. Eine Frage des Standortes.
Z2M läuft auf einem separatem Raspberry mit der Coordinator-Antenne ziemlich mittig im Haus. (2 extra Router im EG und Dach decken zusätzlich ab) und ist einfach besser erreichbar als der UnRaid, auf dem HA in VM läuft - der steht wie der Rest im Keller.

Hallo Cem,

Du hast ganz oben geschrieben:

Wie finde ich denn heraus ob ich einen passenden / geeigneten Koordinator habe, und ob Source Routing tatsächlich aktiv ist?

Gruß
Fabian

Moin Fabian,

gute Frage! Ich starte gleich die VM und schaue, ob das irgendwo in der UI oder den Logs ausgegeben wird. Aber falls du einen EmberZNet-fähigen Adapter nutzt, ist source routing auf jeden Fall aktiv.

Ein Maintainer der ZHA-Integration hat dazu folgenden Codeausschnitt gepostet, der das ebenfalls bestätigt:

Der Code bezieht sich zwar primär auf einen Workaround für den BUGZID 12261-Bug, den Z2M nutzt, aber er impliziert indirekt, dass source routing aktiv ist.

Vielleicht hat jemand mit tieferem Z2M-Wissen noch genauere Infos dazu.


Ich fand es auch spannend, dass sich der Unterschied überhaupt so eindeutig messen ließ und nicht einfach in einem indirekten “Verklemmen” innerhalb des Koordinators untergeht. Besonders interessant ist, dass noch so viele Broadcasts empfangen werden, selbst nachdem die Antwort bereits an den Koordinator zurückgeschickt wurde. Jeder Router propagiert die Nachricht weiter - selbst wenn das Zielgerät über diesen Router gar nicht erreichbar ist.

VG, Cem