feat: resolve chromecast discovery conflict and add CI/CD workflow
Build and Push Docker Image / build-and-push (push) Failing after 10m6s
Build and Push Docker Image / build-and-push (push) Failing after 10m6s
- Update Zeroconf to unicast mode to resolve port 5353 conflict with avahi-daemon - Make API and Streamlit ports configurable via environment variables (defaults: 8055, 8505) - Add Gitea Actions workflow for automated Docker builds and registry pushes - Refactor Chromecast discovery to use modern CastBrowser API
This commit is contained in:
+40
-8
@@ -17,16 +17,48 @@ class CastManager:
|
||||
self._lock = threading.Lock()
|
||||
self._discover_thread = None
|
||||
self.browser = None
|
||||
self.zconf = None
|
||||
self.found_devices = {}
|
||||
|
||||
def discover(self, timeout=5):
|
||||
logger.info("Discovering Chromecasts...")
|
||||
chromecasts, browser = pychromecast.get_chromecasts(timeout=timeout)
|
||||
self.browser = browser
|
||||
if chromecasts:
|
||||
# For simplicity, pick the first one found or allow selection later
|
||||
# In a real scenario, we might want to target a specific name
|
||||
self.chromecast = chromecasts[0]
|
||||
logger.info(f"Found Chromecast: {self.chromecast.name}")
|
||||
logger.info("Starting Chromecast discovery...")
|
||||
import zeroconf
|
||||
from pychromecast.discovery import CastBrowser, SimpleCastListener
|
||||
from .utils import get_host_ip
|
||||
|
||||
if not self.browser:
|
||||
try:
|
||||
ip = get_host_ip()
|
||||
logger.info(f"Binding zeroconf to IP: {ip} (unicast mode)")
|
||||
# unicast=True prevents binding to port 5353, avoiding conflict with Avahi
|
||||
self.zconf = zeroconf.Zeroconf(interfaces=[ip], unicast=True)
|
||||
except Exception as e:
|
||||
logger.error(f"Zeroconf init failed: {e}")
|
||||
self.zconf = zeroconf.Zeroconf(unicast=True)
|
||||
|
||||
self.found_devices = {}
|
||||
|
||||
def add_callback(uuid, service):
|
||||
cast_info = self.browser.devices[uuid]
|
||||
cast = pychromecast.get_chromecast_from_cast_info(cast_info, self.zconf)
|
||||
self.found_devices[cast.name] = cast
|
||||
logger.info(f"Discovered Chromecast: {cast.name}")
|
||||
|
||||
listener = SimpleCastListener(add_callback=add_callback)
|
||||
self.browser = CastBrowser(listener, zeroconf_instance=self.zconf)
|
||||
self.browser.start_discovery()
|
||||
|
||||
# Wait up to timeout seconds to find at least one
|
||||
start_time = time.time()
|
||||
while time.time() - start_time < timeout:
|
||||
if self.found_devices:
|
||||
break
|
||||
time.sleep(0.1)
|
||||
|
||||
if self.found_devices:
|
||||
# Pick the first one
|
||||
self.chromecast = list(self.found_devices.values())[0]
|
||||
logger.info(f"Selected Chromecast: {self.chromecast.name}")
|
||||
self.chromecast.wait()
|
||||
self.mc = self.chromecast.media_controller
|
||||
self.mc.register_status_listener(self)
|
||||
|
||||
Reference in New Issue
Block a user