cyijun / OpenZ3Gateway

An open source Zstack3 gateway powered by ESP8266 and CC2652 modules
Apache License 2.0
39 stars 13 forks source link

[REQUEST] Zeroconf support to OpenZ3Gateway for Home Assistant ZHA network discovery #4

Closed Hedda closed 2 years ago

Hedda commented 2 years ago

Please consider adding Zeroconf DNS TXT Reconds parameters in firmware for automatic ZHA network discovery but only enable it when running in "Zigbee Home Automation Mode".

Home Assistant OS (formerly HASSIO) support automatic network scanning and “Service Discovery” via Zeroconf and when a whitelisted Zigbee serial gateway is discovered it can pass along that to a domain like the ZHA integration component in Home Assistant.

For more context about this Zigbee gateway “Service Discovery” via Zeroconf for the ZHA integration in Home Assistant, please see:

https://community.home-assistant.io/t/zha-automatic-discovery-of-zigbee-coordinator-bridges-gateways-ethernet-wifi-network-devices-that-support-zeroconf-or-ssdp/293300

and

https://developers.home-assistant.io/docs/creating_integration_manifest/#zeroconf

FYI, there is already a working proof-of-concept this is now supported by Tube's Zigbee gateways (based on ESPHome firmware):

https://www.home-assistant.io/integrations/zha#discovery-via-usb-or-zeroconf

https://github.com/tube0013/tube_gateways

Once support for Zeroconf has been added to the firmware you also need the firmware to provide DNS TXT records for passing along setting parameters to integration config flows.

You first need to add Zeroconf service and give it name and as well as adding information about protocol (tcp) and port (????), etc.

Then DNS TXT records is used to pass along recommended settings parameters config flow to Home Assistant's ZHA integration:

version=1.0
radio_type=znp
baud_rate=value
data_flow_control=software

I believe that is advertised for Zeroconf config in this format or similar (though is obviously for emberznet "ezsp" instead of zstack "znp"):

zha_ezsp_zeroconf  _ezsp._tcp  local
   hostname = [zha_ezsp_zeroconf.local]
   port = [8080]
   protocol = [tcp]
   service = tubes_zb_gw
   txt = ["version=1.0"]
   txt = ["radio_type=ezsp"]
   txt = ["baud_rate=value"]
   txt = ["data_flow_control=software"]

(use e.g. avahi-browse -r -a to see this)

As can see, you will need one DNS TXT Record for each attribute and value that is to be passed along to HA's ZHA integration.

Zeroconf DNS TXT records could also be used to pass along info about hostname, versions, location, MAC address, and more, etc..

http://www.zeroconf.org/Rendezvous/txtrecords.html

https://en.wikipedia.org/wiki/Zero-configuration_networking#DNS-based_service_discovery

https://en.wikipedia.org/wiki/TXT_record

More information about idea of using DNS TXT records for passing along setting parameters in https://github.com/thegroove/esphome-zbbridge#1 and https://github.com/thegroove/esphome-zha-ezsp-zeroconf

In the end it is probably best to see actual example config for ESPHome as in Tube's Zigbee Gateway as that is the reference:

https://github.com/tube0013/tube_gateways/blob/main/V2_tube_zb_gw_cc2752p2/ESPHome/tube_zb_gw_cc2652p2v2.yml

zeroconf:
  - service: tubes_zb_gw
    protocol: tcp
    port: 6638
    txt:
      version: 1.0
      radio_type: znp
      baud_rate: 115200
      data_flow_control: software

Again, support for Tube's Zigbee Gateway was initially added to Home Aassistant core for ZHA support in https://github.com/home-assistant/core/pull/48420

As I believe to then whitelist Zeroconf for more gateways and/or radio types in HA's zeroconf as well as for ZHA need to do PR for:

https://github.com/home-assistant/core/blob/dev/homeassistant/generated/zeroconf.py

 "_esphomelib._tcp.local.": [
        {
            "domain": "zha",
            "name": "tube*"
        }
    ],

and

https://github.com/home-assistant/core/blob/dev/homeassistant/components/zha/manifest.json

"zeroconf": [
    {
      "type": "_esphomelib._tcp.local.",
      "name": "tube*"
    }
  ],

and

https://github.com/home-assistant/core/blob/dev/homeassistant/components/zha/config_flow.py

async def async_step_zeroconf(self, discovery_info: DiscoveryInfoType):
        """Handle zeroconf discovery."""
        # Hostname is format: livingroom.local.
        local_name = discovery_info["hostname"][:-1]
        node_name = local_name[: -len(".local")]
        host = discovery_info[CONF_HOST]
        device_path = f"socket://{host}:6638"

        if current_entry := await self.async_set_unique_id(node_name):
            self._abort_if_unique_id_configured(
                updates={
                    CONF_DEVICE: {
                        **current_entry.data.get(CONF_DEVICE, {}),
                        CONF_DEVICE_PATH: device_path,
                    },
                }
            )

        # Check if already configured
        if self._async_current_entries():
            return self.async_abort(reason="single_instance_allowed")

        self.context["title_placeholders"] = {
            CONF_NAME: node_name,
        }

        self._device_path = device_path
        self._radio_type = (
            RadioType.ezsp.name if "efr32" in local_name else RadioType.znp.name
        )
Hedda commented 2 years ago

ops, duplicate