banksy-git / lidl-gateway-freedom

Freeing the Silvercrest (Lidl/Tuya) Smart Home Gateway from the cloud.
https://paulbanks.org/projects/lidl-zigbee/
GNU General Public License v3.0
211 stars 66 forks source link

[REQUEST] Zeroconf or SSDP automatic network discovery compatibility with Home Assistant ZHA integration #9

Open Hedda opened 3 years ago

Hedda commented 3 years ago

Please consider adding automatic network discovery of this so can be discovered by Home Assistant’s ZHA (Zigbee) integration:

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

Support for Zeroconf network discovery of Tube's ESPHome based Zigbee Gateways was recently added to the ZHA integration:

https://github.com/home-assistant/core/pull/48420

Note that Home Assistant already have integration support to add Zeroconf and/or SSDP automatic network discovery methods.

banksy-git commented 3 years ago

Should be doable... if you point me at a spec for the mDNS records. ;-)

Hedda commented 3 years ago

Standard Zeroconf TCP broadcast with mDNS name should be supported as I understand, but then need to explicitly add it to ZHA:

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

"mDNS uses packets similar to unicast DNS to resolve hostnames except they are sent over a multicast link. Each host listens on the mDNS port, 5353, transmitted to a well-known multicast address and resolves requests for the DNS record of its .local hostname (e.g. the A, AAAA, CNAME) to its IP address. When an mDNS client needs to resolve a local hostname to an IP address, it sends a DNS request for that name to the well-known multicast address; the computer with the corresponding A/AAAA record replies with its IP address. The mDNS multicast address is 224.0.0.251 for IPv4 and ff02::fb for IPv6 link-local addressing. DNS Service Discovery (DNS-SD) requests can also be sent using mDNS to yield zero-configuration DNS-SD. This uses DNS PTR, SRV, TXT records to advertise instances of service types, domain names for those instances, and optional configuration parameters for connecting to those instances. But SRV records can now resolve to .local domain names, which mDNS can resolve to local IP addresses."

Home Assistant documentation has this information on Zeroconf in HA:

https://www.home-assistant.io/integrations/zeroconf/

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

So far ZHA developers only explicitly added Zeroconf discovery of Tube's ESPHome based gateways -> https://github.com/home-assistant/core/pull/48420

@banksy-git If you could hack/script in Zeroconf broadcast to Tuya/Lidl/Silvercrest gateways as the first step then in a second step could explicitly add your chosen local record name to Home Assistant and set "zha" as the domain for HA to make ZHA discover ít:

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

Believe Zeroconf for ZHA needs to include hostname, port, baud rate, and local name which ZHA can translate into the radio type.

https://github.com/home-assistant/core/pull/48420/commits/6ba0629fcb68d12a34cd242f8ee70c5e9d89634c

PS: Automatic discovery via Zeroconf or SSDP should further simply hacking and adding Tuya/Lidl/Silvercrest gateway to ZHA:

https://paulbanks.org/projects/lidl-zigbee/ha.html

Hedda commented 3 years ago

Do you know if Zeroconf in Home Assistant support DNS-SD (Rendezvous) "TXT record" to pass config parameters to integrations?

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

If so, you think that Zeroconf DNS-SD (DNS Service Discovery) could pass "TXT records" data on to the ZHA integration config flow?

Example of config parameters that Zeroconf could be passed along to ZHA integration via TXT records:

I understand initial PR https://github.com/home-assistant/core/pull/48420 for ZHA rely on explicit host name for discovery but maybe TXT record is better?

TXT records should be supported by mDNS and Zeroconf standards if I read all this correctly:

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

"Each service instance is described using a DNS SRV and DNS TXT record. A client discovers the list of available instances for a given service type by querying the DNS PTR record of that service type's name; the server returns zero or more names of the form ., each corresponding to a SRV/TXT record pair. The SRV record resolves to the domain name providing the instance, while the TXT can contain service-specific configuration parameters."

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

"DNS Service Discovery (DNS-SD) requests can also be sent using mDNS to yield zero-configuration DNS-SD. This uses DNS PTR, SRV, TXT records to advertise instances of service types, domain names for those instances, and optional configuration parameters for connecting to those instances. But SRV records can now resolve to .local domain names, which mDNS can resolve to local IP addresses."

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

"TXT record (short for text record) is a type of resource record in the Domain name system (DNS) used to provide the ability to associate arbitrary text with a host or other name, such as human readable information about a server, network, data center, or other accounting information. It is also often used in a more structured fashion to record small amounts of machine-readable data into the DNS."

Hedda commented 3 years ago

@banksy-git FYI, while about a other device you also want to follow the related discussion here -> https://github.com/thegroove/esphome-zbbridge/issues/1

Hedda commented 3 years ago

FYI, Home Assistant's zeroconf maintainer/dev @bdraco referred to this example for using TXT record to pass values to integrations:

https://github.com/home-assistant/core/blob/d4ed65e0f53fcab991b13061b1101470f24287a6/homeassistant/components/homekit_controller/config_flow.py#L199

banksy-git commented 3 years ago

I need to find a bit of time to sit down and play with that. Broadcasting a couple of mDNS records looks like the easy bit! :)

Hedda commented 3 years ago

By the way, check out related Zeroconf in thegroove fork of ESPHome firmware for Sonoff ZBBridge

https://github.com/thegroove/esphome-zeroconf

https://github.com/thegroove/esphome-zha-ezsp-zeroconf

https://github.com/thegroove/esphome-zbbridge/issues/1

Hedda commented 3 years ago

FYI, there is now a working proof-of-concept how 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

So today 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
        )

Then DNS TXT records should be used to pass along recommended settings parameters config flow to the ZHA domian in Home Assistant:

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

I believe that is advertised for Zeroconf config in this format or similar:

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.

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