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

Comments

Projects
None yet
4 participants
@postlund
Owner

postlund commented Feb 19, 2017

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

This comment has been minimized.

Show comment
Hide comment
@dale3h

dale3h 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 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

This comment has been minimized.

Show comment
Hide comment
@dale3h

dale3h 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)

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

This comment has been minimized.

Show comment
Hide comment
@gjames2467

gjames2467 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())

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

This comment has been minimized.

Show comment
Hide comment
@robbiet480

robbiet480 Feb 20, 2017

Contributor

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

Contributor

robbiet480 commented Feb 20, 2017

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

@gjames2467

This comment has been minimized.

Show comment
Hide comment
@gjames2467

gjames2467 Feb 20, 2017

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

gjames2467 commented Feb 20, 2017

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

@gjames2467

This comment has been minimized.

Show comment
Hide comment
@gjames2467

gjames2467 Feb 20, 2017

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.

gjames2467 commented Feb 20, 2017

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

This comment has been minimized.

Show comment
Hide comment
@robbiet480

robbiet480 Feb 20, 2017

Contributor

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

Contributor

robbiet480 commented Feb 20, 2017

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

@postlund

This comment has been minimized.

Show comment
Hide comment
@postlund

postlund Feb 21, 2017

Owner

@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.

Owner

postlund commented Feb 21, 2017

@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

This comment has been minimized.

Show comment
Hide comment
@gjames2467

gjames2467 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).

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

This comment has been minimized.

Show comment
Hide comment
@postlund

postlund Jun 19, 2017

Owner

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

Owner

postlund commented Jun 19, 2017

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

@postlund postlund closed this Jun 19, 2017

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