Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Devices not showing up during a scan #51

Closed
postlund opened this issue Feb 19, 2017 · 10 comments
Closed

Devices not showing up during a scan #51

postlund opened this issue Feb 19, 2017 · 10 comments

Comments

@postlund
Copy link
Owner

This library relies on Bonjour/zeroconf for service discovery. If that doesn't work, a scan will not show anything. From my past endeavours when troubleshooting this on Linux, I know that lots of things can go wrong and some users see this issue. So, we need to work systematically to figure out why it works for some and not for others.

An initial test is to just scan for all services and see if anything shows up. If it's empty, then something is really broken. A simple test is to install python-zeroconf in a venv and run this from a python interpreter (python3):

from zeroconf import ZeroconfServiceTypes
ZeroconfServiceTypes.find(timeout=10)

It will scan for ten seconds and show available services, like in my case:

('_acp-sync._tcp.local.', '_airplay._tcp.local.', '_airport._tcp.local.', '_apple-mobdev2._tcp.local.', '_appletv-v2._tcp.local.', '_canon-bjnp1._tcp.local.', '_hap._tcp.local.', '_home-assistant._tcp.local.', '_homekit._tcp.local.', '_http._tcp.local.', '_ipp._tcp.local.', '_ipps._tcp.local.', '_printer._tcp.local.', '_privet._tcp.local.', '_raop._tcp.local.', '_scanner._tcp.local.', '_sleep-proxy._udp.local.', '_smb._tcp.local.', '_sub._apple-mobdev2._tcp.local.', '_touch-able._tcp.local.', '_udisks-ssh._tcp.local.', '_uscan._tcp.local.', '_workstation._tcp.local.')

So if someone with scanning issues could try this, it would help a lot.

@dale3h
Copy link

dale3h commented Feb 19, 2017

Here is the results from my scan:

(homeassistant) homeassistant@ubuntu:~$ python3
Python 3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from zeroconf import ZeroconfServiceTypes
>>> ZeroconfServiceTypes.find(timeout=10)
('_CGI._tcp.local.', '_hap._tcp.local.', '_home-assistant._tcp.local.', '_http._tcp.local.', '_psia._tcp.local.', '_teamviewer._tcp.local.', '_workstation._tcp.local.')

@dale3h
Copy link

dale3h commented Feb 19, 2017

With the ATVs on WiFi, I was able to see them from my MacBookPro (which is also on wifi):

Dale@Dales-MacBook-Pro:~$ dns-sd -B _appletv-v2._tcp
Browsing for _appletv-v2._tcp
DATE: ---Sun 19 Feb 2017---
11:34:09.342  ...STARTING...
Timestamp     A/R    Flags  if Domain               Service Type         Instance Name
11:34:09.343  Add        2   4 local.               _appletv-v2._tcp.    CA1E52614B4ED06F9C009A2CF6BB6A5B4A12F4A1
11:34:09.530  Add        2   4 local.               _appletv-v2._tcp.    07D2977F5302F290DC744EA012B9AD0EE24D00E6

After switching one of my ATVs to ethernet, I am now able to see it in a zeroconf scan:

(homeassistant) homeassistant@ubuntu:~$ python3
Python 3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from zeroconf import ZeroconfServiceTypes
>>> ZeroconfServiceTypes.find(timeout=10)
('_CGI._tcp.local.', '_JB2XiOSApp._tcp.local.', '_airplay._tcp.local.', '_appletv-v2._tcp.local.', '_hap._tcp.local.', '_home-assistant._tcp.local.', '_homekit._tcp.local.', '_http._tcp.local.', '_mediaremotetv._tcp.local.', '_psia._tcp.local.', '_raop._tcp.local.', '_sleep-proxy._udp.local.', '_spotify-connect._tcp.local.', '_teamviewer._tcp.local.', '_touch-able._tcp.local.', '_workstation._tcp.local.')

It also now shows up in atvremote scan:

(homeassistant) homeassistant@ubuntu:~$ atvremote scan
Found Apple TVs:
 - Living Room at 192.168.1.37 (login id: 00000000-0b3f-db19-f900-05b643f64266)

@gjames2467
Copy link

gjames2467 commented Feb 20, 2017

I dislike event loops--I have not finished rewriting the discovery sequence to be function driven, but i have written a version that returns the info you need to initiate a login (GUID/Login ID/Homehsare Key/ IP/ Port)--It is python 2.7 but should work on 3+. I also rewrote the whole library in a simpler non-event-loop based way, if someone is interested email me (george.james18@gmail.com) and i will post it.

from __future__ import absolute_import, division, print_function, unicode_literals

""" Example of browsing for a service (in this case, HTTP) """

import logging
import socket
import sys
from time import sleep

from zeroconf import ServiceBrowser, ServiceStateChange, Zeroconf

def find_service():
    global login_details
    global stuff
    stuff = True
    login_details = {}

    def on_service_state_change(zeroconf, service_type, name, state_change):
        if state_change is ServiceStateChange.Added:
            info = zeroconf.get_service_info(service_type, name)
            if info:

                login_details['address']=socket.inet_ntoa(info.address)
                login_details['port']=info.port
                global stuff
                if info.properties:
                    for key, value in info.properties.items():
                        stuff=False
                        login_details[key]=value

                    stuff=False
            else:
                pass
        logging.basicConfig(level=logging.DEBUG)




    if True:
        zeroconf = Zeroconf()
        browser = ServiceBrowser(zeroconf, "_appletv-v2._tcp.local.", handlers=[on_service_state_change])
        try:
            while stuff:
                sleep(0.1)

            return login_details

        except KeyboardInterrupt:
            pass
        finally:
            zeroconf.close()

print(find_service())

@robbiet480
Copy link
Contributor

@gjames2467 The reason that this library is async is because Home Assistant has fully moved to async for all new platforms.

@gjames2467
Copy link

O yea I forgot to say if you are having issues make sure you have OpenSSL installed (use pip/google specific command)

@gjames2467
Copy link

My code is not asynchronous and works fine, also jas left right up and down supported (not supported here). I have looked at the new protocol (remote app iOS 9+ ) and cannot reverse engineer it for now which as you say might require asynchronous but what is being used here does not require it and only makes for messy unreadable code.

@robbiet480
Copy link
Contributor

@gjames2467 It might work fine but Home Assistant won't accept new contributions that aren't async...

@postlund
Copy link
Owner Author

@gjames2467 Synchronous versions basically always work. They are easy to implement as you only have one control flow and easy to understand for the same reason. What they are not, however, are easy to integrate with other software as you force the library user into dealing with threads and locking in some way. If you are writing a single-flow command line client, that is fine. But if you were to integrate such a library into a GUI application for example, you will block the main thread and lock the UI when doing I/O tasks. To solve this, you must use threading or something similar (like a separate process). In python 3.4 and later, asyncio (cooperative multitasking) is available as a solution. So that is one reason why this library is async. That it is mainly written for Home Assistant (which enforces the requirement, like @robbiet480 mentioned) is another strong one.

But, we are getting from the point here. This issue was related to not finding devices during a scan. Since we are using the same library (python-zeroconf), we will have the same issue. From the conversations I've had with @dale3h on gittr, it seems like the mDNS traffic is not received at all.

@dale3h could you try sudo tcpdump "udp port 5353" and have a look at what is received? You can add -w too, if you want to save it to a PCAP-file and look at it with wireshark later.

@gjames2467
Copy link

gjames2467 commented Feb 21, 2017

@postlund now I understand why your using async for the code, a remote should always be running and just waiting for callbacks to actually do what it needs to do (e.g., this is applicable to all smart home stuff).

Back to the topic at hand though. I created a static mDNS discovery module for device discovery that does not use zeroconf , see the repo here.

I replicated pyatv and posted and autodiscovery example which falls back on the new mDNS discovery module if the zeroconf based module fails. The new module only requires one additional dependency, dnslib. I fixed the bug completely on my machine and tested in Linux / Windows (Ethernet and WiFi).

@postlund
Copy link
Owner Author

I will close this, #65 can be used for scan issues instead.

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

No branches or pull requests

4 participants