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

Discovery doesn't work in an async context #711

Open
Untit1ed opened this issue Mar 21, 2023 · 5 comments
Open

Discovery doesn't work in an async context #711

Untit1ed opened this issue Mar 21, 2023 · 5 comments

Comments

@Untit1ed
Copy link

Untit1ed commented Mar 21, 2023

i'm trying to call my existing code in an async method, but the following code returns 0 devices:

async def main():
       chromecasts, browser = pychromecast.get_listed_chromecasts(
            friendly_names=["MyChromecastName"])

       if not chromecasts:
            raise RuntimeError('No Chromecast devices on the network')

asyncio.run(main())

I see the same issues with pychromecast.discover_chromecasts. Is there a workaround I could use?

PyChromecast 13.0.5

@mikewebkist
Copy link

mikewebkist commented May 2, 2023

Another demonstration of the problem:

import asyncio
import pychromecast

def find_chromecasts():
    chromecasts, browser = pychromecast.get_chromecasts()
    print(chromecasts)

async def async_find_chromecasts():
        find_chromecasts()

asyncio.run(async_find_chromecasts())
find_chromecasts()

Calling the find_chromecasts function in the async loop returns an empty list of devices, while the same function outside of the async loop returns whatever's on your network.

@negmos
Copy link

negmos commented Aug 4, 2023

I have the same issue.. have you managed to find a workaround?

I'm using FastAPI with a web page to trigger discovery.. it has exactly the same issue

@take-kun
Copy link

take-kun commented Oct 25, 2023

I could not find a workaround. This seems to be related to the fact that pychromecast is using synchronous implementation of Zeroconf discovery service. This warning is emitted:

zeroconf: unregister_all_services skipped as it does blocking i/o; use AsyncZeroconf with asyncio

@Lamarqe
Copy link

Lamarqe commented Aug 5, 2024

I found a solution to the problem.

There is a magic in zeroconf which automatically discovers if its created in an async loop or in a threaded environment.
When you create the zeroconf instance outside of async and hand it over to pychromecast, the example above succeeds:

zconf = zeroconf.Zeroconf()

async def main():
       chromecasts, browser = pychromecast.get_listed_chromecasts(
            friendly_names=["MyChromecastName"], zeroconf_instance=zconf)

       if not chromecasts:
            raise RuntimeError('No Chromecast devices on the network')

asyncio.run(main())

@Lamarqe
Copy link

Lamarqe commented Aug 5, 2024

For the example of @mikewebkist regarding get_chromecasts(), you should useblocking=False:

import asyncio
import pychromecast

async def find_chromecasts():
    done = asyncio.Event()
    loop = asyncio.get_running_loop()
    def callback(chromecast):
        loop.call_soon_threadsafe(done.set)
        loop.call_soon_threadsafe(done.clear)
    browser = pychromecast.get_chromecasts(blocking=False, callback=callback)
    expected_devices = 1
    for _ in range(expected_devices):
        await done.wait()
    print(browser.devices)

asyncio.run(find_chromecasts())

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

No branches or pull requests

5 participants