Skip to content

Allow external radio types - #461

Open
puddly wants to merge 12 commits into
zigpy:devfrom
puddly:puddly/external-radio-type
Open

puddly wants to merge 12 commits into
zigpy:devfrom
puddly:puddly/external-radio-type

Conversation

@puddly

@puddly puddly commented Jun 10, 2025 •

Copy link
Copy Markdown
Member

This will need a corresponding PR to Core (https://github.com/puddly/core/tree/puddly/zha-external-radio-libs) but will allow for pre-alpha radio libraries (Ziggurat, ZBOSS, BLZ, and ESPZB) to be used in Home Assistant.

You first need to modify your radio library's pyproject.toml file to register it with zigpy:

[project.entry-points."zigpy.radio"]
your_radio_type = "your_radio_module.zigbee.application:ControllerApplication"

And then just add a description to the ControllerApplication subclass:

class ControllerApplication(zigpy.application.ControllerApplication):
    DISPLAY_NAME = "Friendly Name"
    DESCRIPTION = "Very short description string"

     def __init__(self, ...

Unfortunately, HA Core provides no simple way to install custom dependencies other than a custom component. I'll make a custom component later (if one doesn't already exist) so you can add something like this to configuration.yaml:

# A custom component, unfortunately, to install dependencies
zha_custom_radio_libraries:
  - "git+https://github.com/zigpy/zigpy-ziggurat"

That's it. The Python module will self-register and show up in ZHA config flows, etc.


This is fundamentally a development tool so expect breakage if you rely on it 😄.

@puddly
puddly marked this pull request as draft June 10, 2025 15:32
@codecov

codecov Bot commented Jun 11, 2025 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.42%. Comparing base (a2ddc14) to head (1852b3f).
⚠️ Report is 52 commits behind head on dev.

Additional details and impacted files
@@           Coverage Diff           @@
##              dev     #461   +/-   ##
=======================================
  Coverage   97.41%   97.42%           
=======================================
  Files          50       50           
  Lines       10419    10433   +14     
=======================================
+ Hits        10150    10164   +14     
  Misses        269      269           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@puddly

puddly commented Jun 11, 2025

Copy link
Copy Markdown
Member Author

I've slightly expanded the scope of this PR to clean up and entirely remove the RadioType enum. Instead, we can have structured information within the Gateway object accessible via an API call.

@fangzheli

Copy link
Copy Markdown

Thanks @puddly for working on this — external radio type support would be a big deal for zigpy-blz.

We currently maintain a custom ZHA component to patch BLZ radio support into ZHA, which requires tracking every HA Core release. This PR would let us drop that entirely and ship as a standalone zigpy-blz package (now on PyPI).

We tested this PR locally with a Third Reality BL702 dongle — the Gateway successfully resolves and connects to zigpy-blz through external_radio_libraries. Happy to help with further testing as this moves forward.

@puddly
puddly force-pushed the puddly/external-radio-type branch from a286998 to 56ea7d5 Compare June 11, 2026 16:12
@puddly
puddly marked this pull request as ready for review June 12, 2026 17:22
Copilot AI review requested due to automatic review settings June 12, 2026 17:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors ZHA’s radio selection to support externally provided zigpy radio libraries (discovered via Python entry points), enabling experimentation with pre-alpha radio backends without hard-coding them into ZHA.

Changes:

  • Introduces a RadioLibrary registry with entry-point discovery (zigpy.radio) alongside built-in radios.
  • Updates Gateway initialization to resolve/import the selected radio controller dynamically (off the event loop).
  • Removes the hard-coded RadioType enum and updates tests/fixtures accordingly.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
zha/zigbee/device.py Uses the selected radio library’s display name when coordinator model is unknown.
zha/application/helpers.py Adds RadioLibrary + external radio discovery via entry points.
zha/application/gateway.py Switches radio selection from enum to dynamic registry and imports controller in executor.
zha/application/const.py Removes the hard-coded RadioType enum and related imports.
tests/test_gateway.py Updates gateway tests and adds coverage for external radio discovery/behavior.
tests/conftest.py Adjusts gateway test harness mocking to align with dynamic controller resolution.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +89 to +92

# The actual controller class will be imported dynamically
controller: type[ControllerApplication] = None # type: ignore[assignment]

Comment on lines +135 to +139
def get_radio_libraries() -> dict[str, RadioLibrary]:
"""Return built-in and discovered external radio libraries, keyed by radio type."""

radio_libraries: dict[str, RadioLibrary] = dict(RADIO_LIBRARIES)

Comment on lines +227 to 229
def get_application_controller_config(self) -> dict:
"""Get an uninitialized instance of a zigpy `ControllerApplication`."""
app_config = self.config.zigpy_config
@Hedda

Hedda commented Jun 16, 2026

Copy link
Copy Markdown

Any status updates on this support to allow external radios?

For reference also see this related PR for zigpy -> zigpy/zigpy#1836

@puddly

puddly commented Jun 16, 2026

Copy link
Copy Markdown
Member Author

@Hedda I appreciate your enthusiasm but as you can see, this PR was updated just a few days ago. If there's any update, it will be here.

@GeneralZero

Copy link
Copy Markdown

I've been running a a patched version of zigpy-zboss so I can get my nRF52840 Dongle working. Currently I have a hot patch that patches zha.application.const.RadioType with aenum.extend_enum at every HA startup.

This PR should help me finally remove that hot patch.

Happy to test this branch against my actual hardware and report back.

@puddly

puddly commented Nov 2, 2026 •

Copy link
Copy Markdown
Member Author

@GeneralZero External radio library support was something we were working on to help accelerate the development and testing of radio libraries for chips with less-supported Zigbee stacks, like those from Nordic, Bouffalo Lab, and Espressif. Things have evolved quite a bit since then. I don't think this is a direction we'll be pursuing.

Check out https://github.com/zigpy/ziggurat/, our fully open source, universal Zigbee stack. It runs either on your HA OS host or straight on any larger microcontroller. It's supported by ZHA today, is feature complete, and has excellent performance. The Ziggurat addon supports your nRF52840 dongle out of the box as long as you flash it with a recent build of OpenThread RCP.

You can also try out a very fresh embedded build that runs straight on the nRF52840 dongle. ZHA setup for embedded Ziggurat works best on HA Core dev/the upcoming 2026.11.0b3, likely releasing tomorrow.

@GeneralZero

Copy link
Copy Markdown

Sounds good Ill have a look at it tomorrow when the Home assistant releases.

@jackson-57

Copy link
Copy Markdown

Where does this leave zigpy-blz and similar? I'm running a Third Reality Zigbee dongle and I'd love to get off the hacky ZiGate protocol-based firmware. Is the idea that Ziggurat replaces the firmware on my existing dongle?

@puddly

puddly commented Nov 2, 2026

Copy link
Copy Markdown
Member Author

Is the idea that Ziggurat replaces the firmware on my existing dongle?

The project docs explain the architecture a bit more. In short: kind of! The simplest and most performant way to run Ziggurat is by installing OpenThread RCP firmware onto your adapter. It transforms it into a simple packet sender. The Ziggurat addon then controls the radio directly and you're good to go.

Where does this leave zigpy-blz and similar?

You can still run them as long as the radio libraries stay compatible with zigpy and ZHA. In the long term, they won't be required: the Ziggurat serial protocol is universal and doesn't depend on what the radio chip is. The SiLabs MG24, the nRF52840, the ESP32-C6, etc. all work exactly the same.


I looked around and unfortunately wasn't able to find any OpenThread RCP build for the ThirdReality dongle. If ThirdReality publishes one or I manage to make one (I have this adapter to test with), I'll ping you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking change Breaking change (mainly for PRs) new feature Adds new feature

Projects

Status: Next

Development

Successfully merging this pull request may close these issues.

7 participants