etheralm / libpurecool

Python library for dyson devices.
Other
67 stars 30 forks source link

Question about MDNS discovery #32

Open wez opened 3 years ago

wez commented 3 years ago

This isn't directly an issue with this library, hope that's ok!

I'm looking at coding a Rust client for my dyson devices and I don't see them responding to mDNS queries. The readme in this project says that it has a modified version of zeroconf because the dyson implementation isn't valid.

I've tried sticking this in the bottom of zeroconf.py here to see if I can get something enumerating:

if __name__ == '__main__':
    import time
    zeroconf = Zeroconf()
    class MyListener(object):
        def add_service(self, zeroconf, device_type, name):
            print("add_service", device_type, name)

    listener = MyListener()
    zeroconf.add_service_listener("_dyson_mqtt._tcp.local.", listener=listener)
    for i in range(20):
        print("a")
        time.sleep(2)

but I never see any responses come back. Is there some trick to getting this to work, or is the mDNS implementation in the dyson devices really badly borked? I can see a few issues over in https://github.com/CharlesBlonde/libpurecoollink/issues that relate to auto-connect not working.

wez commented 3 years ago

I tracked down the difference that the readme mentions; it's just to allow underscores in the name:

$ diff -u zc-upstream.py zeroconf.py
--- zc-upstream.py      2021-01-23 23:01:15.599935355 -0800
+++ zeroconf.py 2021-01-23 22:59:07.084524866 -0800
@@ -148,7 +148,7 @@
           _TYPE_ANY: "any"}

 _HAS_A_TO_Z = re.compile(r'[A-Za-z]')
-_HAS_ONLY_A_TO_Z_NUM_HYPHEN = re.compile(r'^[A-Za-z0-9\-]+$')
+_HAS_ONLY_A_TO_Z_NUM_HYPHEN = re.compile(r'^[A-Za-z0-9\-\_]+$')
 _HAS_ASCII_CONTROL_CHARS = re.compile(r'[\x00-\x1f\x7f]')
wez commented 3 years ago

FWIW, while querying for _dyson_mqtt._tcp.local never seems to get a response for any record type (I tried SRV, A, PTR, and others) here, I did find that performing an mDNS A lookup for <SERIAL>.local does get a response from the device, so in my Rust implementation I'm going to use that to determine the device addresses. That might be a viable fallback for the auto-connect feature in libpurecool?

wez commented 3 years ago

And closing the loop here: I happened to discover that the "Auto-Optimize Network" function on my UniFi network settings was enabled. One of the consequences of this is to block multicast traffic, and that explains why the normal discovery was not working. With it disabled, I can now see responses to the _dyson_mqtt._tcp.local. What I plan to do about this in my rust crate is to try _dyson_mqtt._tcp.local first, then fall back to to the A lookups I mentioned above.

Sharing this here for puzzled internet searchers of the future!