pyatv: Failed to find device with identifier

Describe the bug After initially setting up the AppleTV in HomeAssistant 0.102.2 in Hass.io, you restart HomeAssistant, and the AppleTV no longer works. 2019-11-27 22:57:08 ERROR (MainThread) [custom_components.apple_tv] Failed to find device with identifier xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx The only way to make it work again is to remove the AppleTv and re-add it again.

To Reproduce

  • Configure the AppleTv integration
  • Restart HomeAssistant

Expected behavior

System Setup (please complete the following information):

  • Os: Hass.io
  • Python: 3.7
  • pyatv: 5d20516

Additional context

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 65 (31 by maintainers)

Most upvoted comments

My AppleTV seems to have resurrected itself after installing 2f16e2f (missing after reboot initially, installed the update, rebooted, AppleTV was picked up again during the startup). Still need to check if it survives additional reboots though…

Thank you!

I have managed to complete #343 and integrate it with the component, but I need to do some clean up and additional testing of it. To summarize how it works:

  • Unicast scanning (as implemented in #343) will be used when entering an IP-address in the add-dialog in Integrations. This means that if you enter an IP-address when adding a new device, pyatv will scan for that device only by sending a request directly to the device. This should work even when normal scans doesn’t work. Entering an identifier or name will trigger a scan just like before in order to find the device.
  • IP-address of the device will be saved in the config entry. So the configuration in .storage/core.config_entries will contain the last known-to-be-working IP-address.
  • When starting Home Assistant, a unicast scan will be performed on the saved address. This will greatly speed up initial connection, assuming the device has not changed IP-address.
  • If the device has changed IP-address (compared to what is stored in the config entry), a scan will be performed. If the scan finds the device, a connection will be established and IP-address updated in the config entry, so it is up-to-date when connecting the next time.
  • If scan fails, unicast scan + regular scan will be retried again after a while.
  • The error message in the title of this issue has been removed. You will have to look at the device state/title to see what is happening (or enable debug logs). The reason for this is to not spam the log with retry-attempts in case the device isn’t found (e.g. because of issues or it being turned off). My intention is for this integration to reach Plantinum level on the quality scale in due time, so this is necessary.

This should work good for all users. My assumption is that scanning works sometimes, even for users that have problems. This approach hopefully makes the connection recover at some point in time. If it doesn’t, then the integration must be removed and added again for now. I will have to look at an approach to edit IP-address manually in the future.

My intention is to release an update to the component today/tonight. I would be extremely happy to get some testers on this, especially if you have said problems.

This will be a breaking change: you must remove and re-add your integration when updating!

@postlund I’ve been looking through HASS code to check how other components use zeroconf and stumbled upon the Chromecast component. It seems like its backend library, pychromecast, is using another zeroconf implementation, not the one pyatv is using. As far as I can see that library doesn’t support asyncio though. Could the library be the culprit?

Home Assistant uses python-zeroconf internally for zeroconf (the one mentioned in pychromecast). I used that library as well until I couple of weeks ago, where I concluded that aiozeroconf worked a lot better for the users involved in the investigation. See issue for #214 for details. I know that there were discussion of switching to aiozeroconf in home assistant as well (since it’s natively asyncio), but there were some issue left. Looking at the issues in the projects GitHub page will reveal some interesting read. Also, all zeroconf implementations in python are forks of the same project. So at their cores, they are more or less the same thing.

Nevertheless, I do believe we will continue see problems like these going forward. It is not the correct way to use zeroconf like this. It is much better to have a daemon (like Anahi) that is always running, maintaining a cache of all discovered services. Applications can then just ask that daemon and get a service list. If a service is not available at one time, it will probably be later. I see missing and delayed discoveries of services all the time when using AirPlay (in iOS). It usually takes some time until devices appear, so not even the “golden standard” of implementations is foolproof. The important part is to have mitigations. The re-connect support should improve the situation, but I hope #293 will make it even better.

@postlund yes, that’s what I did. That bothers me as well. I have two uneducated guesses:

* these five second delay gives something inside HASS finish initalizing

* these five second just let us skip the most CPU-intense part of HASS launch, making the subsequent scan faster.

I mean, writing this:

atvs = await scan(loop, timeout=5)

or

atvs = await scan(loop)

Should result in the exact same thing as default value for timeout is 5. This is mainly what I’m asking if you did and it worked?

Adding a delay before is of course another matter, as that changes timing a bit. In theory it could mean that mDNS responses from Home Assistants zeroconf implementation are picked up (since it’s multicast traffic). But I still don’t understand why that would matter. I want to know the root cause, just adding s sleep for some random time is not something I’m gonna do as it’s very fragile. Maybe it works now for some people, but the problem likely still exists and will haunt other users.

I assume that it recovers with my latest update to the component?

I wonder if it has something to do with timing, what if the initial scan happens too early in specific circumstances? Although as you mention trying to add a bogus device on Integrations page should’ve helped in this case.

@Veldkornet what do you think about sharing some details about our setups in order to find what’s common? I’ll start:

  • HASS runs in Docker on Raspberry Pi 3, homeassistant/raspberrypi3-homeassistant:0.102.1
  • Both Pi and Apple TV 4K are wired to a Ubiquiti EdgeRouter X router

As long as Home Assistant has network access, it should work. It must have otherwise none of the other integrations would work. You both seem to be running in docker (via hass.io or just plain docker). I haven’t tested it in docker myself yet, just run in plain. So I can try that tomorrow or so and see if I can reproduce. It would be a lot easier to troubleshoot if I can reproduce it myself.

Another data point: my local dev HASS installation running on Mac via venv is not affected by this issue.

@Veldkornet I also added info about VLAN

I have Hass.io running on a RaspberryPi 4 with HA version 0.102.2. RaspberryPi is connected via WiFi Apple TV is connected via cable. Both devices are on the same VLAN. Network is Ubiquiti UniFi.

With Hass.io though, if I’m not mistaken, the device itself stays connected to the network during a HomeAssistant restart. So the Docker container should have network access right from the start.