diff --git a/pychromecast/dial.py b/pychromecast/dial.py index f508fc82c..d73864db1 100644 --- a/pychromecast/dial.py +++ b/pychromecast/dial.py @@ -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 @@ -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 @@ -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 @@ -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") @@ -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 @@ -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 @@ -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 = [] @@ -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 diff --git a/pychromecast/discovery.py b/pychromecast/discovery.py index 13e40e5f0..80a03e526 100644 --- a/pychromecast/discovery.py +++ b/pychromecast/discovery.py @@ -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 @@ -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() @@ -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): @@ -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: @@ -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