Skip to content

Commit

Permalink
Decrease discovery overhead
Browse files Browse the repository at this point in the history
  • Loading branch information
bdraco committed Apr 3, 2021
1 parent d160ad1 commit 7921ba7
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 20 deletions.
41 changes: 24 additions & 17 deletions pychromecast/dial.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@
Implements the DIAL-protocol to communicate with the Chromecast
"""
from collections import namedtuple
import json
import logging
import socket
import ssl
import urllib.request
import requests
from uuid import UUID

import zeroconf
Expand Down Expand Up @@ -58,7 +56,7 @@ def _get_host_from_zc_service_info(service_info: zeroconf.ServiceInfo):
return (host, port)


def _get_status(host, services, zconf, path, secure, timeout):
def _get_status(host, services, zconf, path, secure, timeout, session=None):
"""
:param host: Hostname or ip to fetch status from
:type host: str
Expand All @@ -75,21 +73,30 @@ def _get_status(host, services, zconf, path, secure, timeout):

headers = {"content-type": "application/json"}

context = None
if secure:
url = FORMAT_BASE_URL_HTTPS.format(host) + path
context = ssl.SSLContext()
context.verify_mode = ssl.CERT_NONE
else:
url = FORMAT_BASE_URL_HTTP.format(host) + path

req = urllib.request.Request(url, headers=headers)
with urllib.request.urlopen(req, timeout=timeout, context=context) as response:
data = response.read()
return json.loads(data.decode("utf-8"))
has_session = bool(session)
if not has_session:
session = get_requests_session()

try:
return session.get(url, headers=headers, timeout=timeout).json()
finally:
if not has_session:
session.close()


def get_requests_session():
"""Create a requests session."""
session = requests.Session()
session.verify = False
return session


def get_device_status(host, services=None, zconf=None, timeout=10):
def get_device_status(host, services=None, zconf=None, timeout=10, session=None):
"""
:param host: Hostname or ip to fetch status from
:type host: str
Expand All @@ -99,7 +106,7 @@ def get_device_status(host, services=None, zconf=None, timeout=10):

try:
status = _get_status(
host, services, zconf, "/setup/eureka_info?options=detail", True, timeout
host, services, zconf, "/setup/eureka_info?options=detail", True, timeout, session
)

friendly_name = status.get("name", "Unknown Chromecast")
Expand All @@ -119,7 +126,7 @@ def get_device_status(host, services=None, zconf=None, timeout=10):

return DeviceStatus(friendly_name, model_name, manufacturer, uuid, cast_type)

except (urllib.error.HTTPError, urllib.error.URLError, OSError, ValueError):
except (requests.exceptions.Timeout, requests.exceptions.RequestException, OSError, ValueError):
return None


Expand All @@ -144,7 +151,7 @@ def _get_group_info(host, group):
return MultizoneInfo(name, uuid, leader_host, leader_port)


def get_multizone_status(host, services=None, zconf=None, timeout=10):
def get_multizone_status(host, services=None, zconf=None, timeout=10, session=None):
"""
:param host: Hostname or ip to fetch status from
:type host: str
Expand All @@ -154,7 +161,7 @@ def get_multizone_status(host, services=None, zconf=None, timeout=10):

try:
status = _get_status(
host, services, zconf, "/setup/eureka_info?params=multizone", True, timeout
host, services, zconf, "/setup/eureka_info?params=multizone", True, timeout, session
)

dynamic_groups = []
Expand All @@ -169,7 +176,7 @@ def get_multizone_status(host, services=None, zconf=None, timeout=10):

return MultizoneStatus(dynamic_groups, groups)

except (urllib.error.HTTPError, urllib.error.URLError, OSError, ValueError):
except (requests.exceptions.Timeout, requests.exceptions.RequestException, OSError, ValueError):
return None


Expand Down
8 changes: 5 additions & 3 deletions pychromecast/discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import zeroconf

from .const import SERVICE_TYPE_HOST, SERVICE_TYPE_MDNS
from .dial import get_device_status, get_multizone_status
from .dial import get_device_status, get_multizone_status, get_requests_session

DISCOVER_TIMEOUT = 5

Expand Down Expand Up @@ -234,6 +234,7 @@ def update_hosts(self, known_hosts):
def run(self):
"""Start worker thread."""
_LOGGER.debug("HostBrowser thread started")
self.session = get_requests_session()
try:
while not self.stop.is_set():
self._poll_hosts()
Expand All @@ -242,6 +243,7 @@ def run(self):
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unhandled exception in worker thread")
raise
self.session.close()
_LOGGER.debug("HostBrowser thread done")

def _poll_hosts(self):
Expand All @@ -252,7 +254,7 @@ def _poll_hosts(self):
uuids = []
if self.stop.is_set():
break
device_status = get_device_status(host, timeout=4)
device_status = get_device_status(host, timeout=4, session=self.session)
try:
hoststatus = self._known_hosts[host]
except KeyError:
Expand Down Expand Up @@ -280,7 +282,7 @@ def _poll_hosts(self):
)
uuids.append(device_status.uuid)

multizone_status = get_multizone_status(host)
multizone_status = get_multizone_status(host, session=self.session)
if not multizone_status:
return

Expand Down

0 comments on commit 7921ba7

Please sign in to comment.