Hello community,
here is the log from the commit of package python-PyChromecast for openSUSE:Factory checked in at 2019-03-06 15:50:06
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-PyChromecast (Old)
and /work/SRC/openSUSE:Factory/.python-PyChromecast.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-PyChromecast"
Wed Mar 6 15:50:06 2019 rev:4 rq:681900 version:2.5.2
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-PyChromecast/python-PyChromecast.changes 2019-01-24 14:03:38.904035507 +0100
+++ /work/SRC/openSUSE:Factory/.python-PyChromecast.new.28833/python-PyChromecast.changes 2019-03-06 15:50:09.128433168 +0100
@@ -1,0 +2,9 @@
+Tue Mar 5 20:03:56 UTC 2019 - Tomáš Chvátal
+
+- Update to 2.5.2:
+ * YouTube controller version update (#258) @ur1katz
+ * Add support for connecting to named service (#267) @emontnemery
+ * Exponential backoff of mdns service resolution retries (#268) @emontnemery
+ * Improve exponential backoff of mdns service resolution retries (#269) @emontnemery
+
+-------------------------------------------------------------------
Old:
----
PyChromecast-2.3.0.tar.gz
New:
----
PyChromecast-2.5.2.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-PyChromecast.spec ++++++
--- /var/tmp/diff_new_pack.yAhYcP/_old 2019-03-06 15:50:10.384433340 +0100
+++ /var/tmp/diff_new_pack.yAhYcP/_new 2019-03-06 15:50:10.392433341 +0100
@@ -19,7 +19,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
%define skip_python2 1
Name: python-PyChromecast
-Version: 2.3.0
+Version: 2.5.2
Release: 0
Summary: Python module to talk to Google Chromecast
License: MIT
++++++ PyChromecast-2.3.0.tar.gz -> PyChromecast-2.5.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PyChromecast-2.3.0/PKG-INFO new/PyChromecast-2.5.2/PKG-INFO
--- old/PyChromecast-2.3.0/PKG-INFO 2018-09-05 15:02:22.000000000 +0200
+++ new/PyChromecast-2.5.2/PKG-INFO 2019-02-16 20:45:19.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: PyChromecast
-Version: 2.3.0
+Version: 2.5.2
Summary: Python module to talk to Google Chromecast.
Home-page: https://github.com/balloob/pychromecast
Author: Paulus Schoutsen
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PyChromecast-2.3.0/PyChromecast.egg-info/PKG-INFO new/PyChromecast-2.5.2/PyChromecast.egg-info/PKG-INFO
--- old/PyChromecast-2.3.0/PyChromecast.egg-info/PKG-INFO 2018-09-05 15:02:22.000000000 +0200
+++ new/PyChromecast-2.5.2/PyChromecast.egg-info/PKG-INFO 2019-02-16 20:45:19.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: PyChromecast
-Version: 2.3.0
+Version: 2.5.2
Summary: Python module to talk to Google Chromecast.
Home-page: https://github.com/balloob/pychromecast
Author: Paulus Schoutsen
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PyChromecast-2.3.0/PyChromecast.egg-info/requires.txt new/PyChromecast-2.5.2/PyChromecast.egg-info/requires.txt
--- old/PyChromecast-2.3.0/PyChromecast.egg-info/requires.txt 2018-09-05 15:02:22.000000000 +0200
+++ new/PyChromecast-2.5.2/PyChromecast.egg-info/requires.txt 2019-02-16 20:45:19.000000000 +0100
@@ -1,4 +1,4 @@
requests>=2.0
protobuf>=3.0.0
zeroconf>=0.17.7
-casttube>=0.1.0
+casttube>=0.2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PyChromecast-2.3.0/pychromecast/__init__.py new/PyChromecast-2.5.2/pychromecast/__init__.py
--- old/PyChromecast-2.3.0/pychromecast/__init__.py 2018-07-10 10:42:56.000000000 +0200
+++ new/PyChromecast-2.5.2/pychromecast/__init__.py 2019-02-12 20:29:47.000000000 +0100
@@ -23,6 +23,8 @@
IDLE_APP_ID = 'E8C28D3C'
IGNORE_CEC = []
+_LOGGER = logging.getLogger(__name__)
+
def _get_chromecast_from_host(host, tries=None, retry_wait=None, timeout=None,
blocking=True):
@@ -31,6 +33,7 @@
# the primary source and the remaining will be fetched
# later on.
ip_address, port, uuid, model_name, friendly_name = host
+ _LOGGER.debug("_get_chromecast_from_host %s", host)
cast_type = CAST_TYPES.get(model_name.lower(),
CAST_TYPE_CHROMECAST)
device = DeviceStatus(
@@ -42,6 +45,25 @@
blocking=blocking)
+def _get_chromecast_from_service(services, tries=None, retry_wait=None,
+ timeout=None, blocking=True):
+ """Creates a Chromecast object from a zeroconf service."""
+ # Build device status from the mDNS service name info, this
+ # information is the primary source and the remaining will be
+ # fetched later on.
+ services, zconf, uuid, model_name, friendly_name = services
+ _LOGGER.debug("_get_chromecast_from_service %s", services)
+ cast_type = CAST_TYPES.get(model_name.lower(),
+ CAST_TYPE_CHROMECAST)
+ device = DeviceStatus(
+ friendly_name=friendly_name, model_name=model_name,
+ manufacturer=None, uuid=uuid, cast_type=cast_type,
+ )
+ return Chromecast(host=None, device=device, tries=tries, timeout=timeout,
+ retry_wait=retry_wait, blocking=blocking,
+ services=services, zconf=zconf)
+
+
# pylint: disable=too-many-locals
def get_chromecasts(tries=None, retry_wait=None, timeout=None,
blocking=True, callback=None):
@@ -123,17 +145,20 @@
timeout = kwargs.pop('timeout', None)
retry_wait = kwargs.pop('retry_wait', None)
blocking = kwargs.pop('blocking', True)
+ services = kwargs.pop('services', None)
+ zconf = kwargs.pop('zconf', True)
self.logger = logging.getLogger(__name__)
# Resolve host to IP address
+ self._services = services
self.host = host
self.port = port or 8009
self.logger.info("Querying device status")
self.device = device
if device:
- dev_status = get_device_status(self.host)
+ dev_status = get_device_status(self.host, services, zconf)
if dev_status:
# Values from `device` have priority over `dev_status`
# as they come from the dial information.
@@ -154,7 +179,7 @@
else:
self.device = device
else:
- self.device = get_device_status(self.host)
+ self.device = get_device_status(self.host, services, zconf)
if not self.device:
raise ChromecastConnectionError( # noqa
@@ -166,7 +191,7 @@
self.socket_client = socket_client.SocketClient(
host, port=port, cast_type=self.device.cast_type,
tries=tries, timeout=timeout, retry_wait=retry_wait,
- blocking=blocking)
+ blocking=blocking, services=services, zconf=zconf)
receiver_controller = self.socket_client.receiver_controller
receiver_controller.register_status_listener(self)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PyChromecast-2.3.0/pychromecast/controllers/youtube.py new/PyChromecast-2.5.2/pychromecast/controllers/youtube.py
--- old/PyChromecast-2.3.0/pychromecast/controllers/youtube.py 2018-07-10 10:42:56.000000000 +0200
+++ new/PyChromecast-2.5.2/pychromecast/controllers/youtube.py 2019-01-17 19:45:56.000000000 +0100
@@ -34,13 +34,14 @@
self.update_screen_id()
self._session = YouTubeSession(screen_id=self._screen_id)
- def play_video(self, video_id):
+ def play_video(self, video_id, playlist_id=None):
"""
Play video(video_id) now. This ignores the current play queue order.
:param video_id: YouTube video id(http://youtube.com/watch?v=video_id)
+ :param playlist_id: youtube.com/watch?v=video_id&list=playlist_id
"""
self.start_session_if_none()
- self._session.play_video(video_id)
+ self._session.play_video(video_id, playlist_id)
def add_to_queue(self, video_id):
"""
@@ -66,6 +67,13 @@
self.start_session_if_none()
self._session.remove_video(video_id)
+ def clear_playlist(self):
+ """
+ Clear the entire video queue
+ """
+ self.start_session_if_none()
+ self._session.clear_playlist()
+
def update_screen_id(self):
"""
Sends a getMdxSessionStatus to get the screenId and waits for response.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PyChromecast-2.3.0/pychromecast/dial.py new/PyChromecast-2.5.2/pychromecast/dial.py
--- old/PyChromecast-2.3.0/pychromecast/dial.py 2018-07-10 10:42:56.000000000 +0200
+++ new/PyChromecast-2.5.2/pychromecast/dial.py 2019-02-15 18:43:54.000000000 +0100
@@ -4,8 +4,11 @@
from collections import namedtuple
from uuid import UUID
+import logging
import requests
+from .discovery import get_info_from_service, get_host_from_service_info
+
XML_NS_UPNP_DEVICE = "{urn:schemas-upnp-org:device-1-0}"
FORMAT_BASE_URL = "http://{}:8008"
@@ -28,6 +31,8 @@
'google cast group': CAST_TYPE_GROUP,
}
+_LOGGER = logging.getLogger(__name__)
+
def reboot(host):
""" Reboots the chromecast. """
@@ -35,7 +40,7 @@
data='{"params":"now"}', timeout=10)
-def get_device_status(host):
+def get_device_status(host, services=None, zconf=None):
"""
:param host: Hostname or ip to fetch status from
:type host: str
@@ -44,6 +49,14 @@
"""
try:
+ if not host:
+ for service in services.copy():
+ service_info = get_info_from_service(service, zconf)
+ host, _ = get_host_from_service_info(service_info)
+ if host:
+ _LOGGER.debug("Resolved service %s to %s", service, host)
+ break
+
req = CC_SESSION.get(
FORMAT_BASE_URL.format(host) + "/setup/eureka_info?options=detail",
timeout=10)
@@ -80,7 +93,7 @@
return DeviceStatus(friendly_name, model_name, manufacturer,
uuid, cast_type)
- except (requests.exceptions.RequestException, ValueError):
+ except (requests.exceptions.RequestException, OSError, ValueError):
return None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PyChromecast-2.3.0/pychromecast/discovery.py new/PyChromecast-2.5.2/pychromecast/discovery.py
--- old/PyChromecast-2.3.0/pychromecast/discovery.py 2018-07-10 10:42:56.000000000 +0200
+++ new/PyChromecast-2.5.2/pychromecast/discovery.py 2019-02-16 20:43:30.000000000 +0100
@@ -1,4 +1,5 @@
"""Discovers Chromecasts on the network using mDNS/zeroconf."""
+import logging
import socket
from uuid import UUID
@@ -6,13 +7,16 @@
DISCOVER_TIMEOUT = 5
+_LOGGER = logging.getLogger(__name__)
+
class CastListener(object):
"""Zeroconf Cast Services collection."""
- def __init__(self, callback=None):
+ def __init__(self, add_callback=None, remove_callback=None):
self.services = {}
- self.callback = callback
+ self.add_callback = add_callback
+ self.remove_callback = remove_callback
@property
def count(self):
@@ -27,22 +31,32 @@
# pylint: disable=unused-argument
def remove_service(self, zconf, typ, name):
""" Remove a service from the collection. """
- self.services.pop(name, None)
+ _LOGGER.debug("remove_service %s, %s", typ, name)
+ service = self.services.pop(name, None)
+
+ if not service:
+ _LOGGER.debug("remove_service unknown %s, %s", typ, name)
+ return
+
+ if self.remove_callback:
+ self.remove_callback(name, service)
def add_service(self, zconf, typ, name):
""" Add a service to the collection. """
service = None
tries = 0
+ _LOGGER.debug("add_service %s, %s", typ, name)
while service is None and tries < 4:
try:
service = zconf.get_service_info(typ, name)
except IOError:
- # If the zerconf fails to receive the necesarry data we abort
+ # If the zeroconf fails to receive the necessary data we abort
# adding the service
break
tries += 1
if not service:
+ _LOGGER.debug("add_service failed to add %s, %s", typ, name)
return
def get_value(key):
@@ -66,11 +80,11 @@
self.services[name] = (host, service.port, uuid, model_name,
friendly_name)
- if self.callback:
- self.callback(name)
+ if self.add_callback:
+ self.add_callback(name)
-def start_discovery(callback=None):
+def start_discovery(add_callback=None, remove_callback=None):
"""
Start discovering chromecasts on the network.
@@ -84,7 +98,7 @@
chromecasts. To stop discovery, call the stop_discovery method with the
ServiceBrowser object.
"""
- listener = CastListener(callback)
+ listener = CastListener(add_callback, remove_callback)
service_browser = False
try:
service_browser = zeroconf.ServiceBrowser(zeroconf.Zeroconf(),
@@ -128,3 +142,32 @@
finally:
if browser is not False:
stop_discovery(browser)
+
+
+def get_info_from_service(service, zconf):
+ """ Resolve service_info from service. """
+ service_info = None
+ try:
+ service_info = zconf.get_service_info('_googlecast._tcp.local.',
+ service)
+ if service_info:
+ _LOGGER.debug(
+ "get_info_from_service resolved service %s to service_info %s",
+ service, service_info)
+ except IOError:
+ pass
+ return service_info
+
+
+def get_host_from_service_info(service_info):
+ """ Get hostname or IP from service_info. """
+ host = None
+ port = None
+ if (service_info and service_info.port and
+ (service_info.server or service_info.address)):
+ if service_info.address:
+ host = socket.inet_ntoa(service_info.address)
+ else:
+ host = service_info.server.lower()
+ port = service_info.port
+ return (host, port)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PyChromecast-2.3.0/pychromecast/socket_client.py new/PyChromecast-2.5.2/pychromecast/socket_client.py
--- old/PyChromecast-2.3.0/pychromecast/socket_client.py 2018-07-10 10:42:56.000000000 +0200
+++ new/PyChromecast-2.5.2/pychromecast/socket_client.py 2019-02-16 20:43:30.000000000 +0100
@@ -6,7 +6,7 @@
Without him this would not have been possible.
"""
# Pylint does not understand the protobuf objects correctly
-# pylint: disable=no-member
+# pylint: disable=no-member, too-many-lines
import errno
import json
@@ -24,6 +24,7 @@
from .controllers import BaseController
from .controllers.media import MediaController
from .dial import CAST_TYPE_CHROMECAST, CAST_TYPE_AUDIO, CAST_TYPE_GROUP
+from .discovery import get_info_from_service, get_host_from_service_info
from .error import (
ChromecastConnectionError,
UnsupportedNamespace,
@@ -57,6 +58,8 @@
CONNECTION_STATUS_DISCONNECTED = "DISCONNECTED"
# Connecting to socket failed (after a CONNECTION_STATUS_CONNECTING)
CONNECTION_STATUS_FAILED = "FAILED"
+# Failed to resolve service name
+CONNECTION_STATUS_FAILED_RESOLVE = "FAILED_RESOLVE"
# The socket connection was lost and needs to be retried
CONNECTION_STATUS_LOST = "LOST"
@@ -154,6 +157,8 @@
timeout = kwargs.pop('timeout', None)
retry_wait = kwargs.pop('retry_wait', None)
self.blocking = kwargs.pop('blocking', True)
+ services = kwargs.pop('services', None)
+ zconf = kwargs.pop('zconf', None)
if self.blocking:
self.polltime = POLL_TIME_BLOCKING
@@ -169,10 +174,13 @@
self._force_recon = False
self.cast_type = cast_type
+ self.fn = None # pylint:disable=invalid-name
self.tries = tries
self.timeout = timeout or TIMEOUT_TIME
self.retry_wait = retry_wait or RETRY_TIME
self.host = host
+ self.services = services or [None]
+ self.zconf = zconf
self.port = port or 8009
self.source_id = "sender-0"
@@ -212,7 +220,7 @@
NetworkAddress(self.host, self.port)))
raise
- def initialize_connection(self):
+ def initialize_connection(self): # noqa: E501 pylint:disable=too-many-statements, too-many-branches
"""Initialize a socket to a Chromecast, retrying as necessary."""
tries = self.tries
@@ -234,51 +242,124 @@
self.connecting = True
retry_log_fun = self.logger.error
- while not self.stop.is_set() and (tries is None or tries > 0):
- try:
- self.socket = new_socket()
- self.socket.settimeout(self.timeout)
- self._report_connection_status(
- ConnectionStatus(CONNECTION_STATUS_CONNECTING,
- NetworkAddress(self.host, self.port)))
- self.socket.connect((self.host, self.port))
- self.socket = ssl.wrap_socket(self.socket)
- self.connecting = False
- self._force_recon = False
- self._report_connection_status(
- ConnectionStatus(CONNECTION_STATUS_CONNECTED,
- NetworkAddress(self.host, self.port)))
- self.receiver_controller.update_status()
- self.heartbeat_controller.ping()
- self.heartbeat_controller.reset()
+ # Dict keeping track of individual retry delay for each named service
+ retries = {}
- self.logger.debug("Connected!")
- break
- except OSError as err:
- self.connecting = True
- if self.stop.is_set():
- self.logger.error(
- "Failed to connect: %s. aborting due to stop signal.",
- err)
- raise ChromecastConnectionError("Failed to connect")
-
- self._report_connection_status(
- ConnectionStatus(CONNECTION_STATUS_FAILED,
- NetworkAddress(self.host, self.port)))
-
- # Only sleep if we have another retry remaining
- if tries is None or tries > 1:
- retry_log_fun("Failed to connect, retrying in %.1fs",
- self.retry_wait)
+ def mdns_backoff(service, retry):
+ """Exponentional backoff for service name mdns lookups."""
+ now = time.time()
+ retry['next_retry'] = now + retry['delay']
+ retry['delay'] = min(retry['delay']*2, 300)
+ retries[service] = retry
+
+ while not self.stop.is_set() and (tries is None or tries > 0): # noqa: E501 pylint:disable=too-many-nested-blocks
+ # Prune retries dict
+ retries = {key: retries[key] for key in self.services if (
+ key is not None and key in retries)}
+
+ for service in self.services.copy():
+ now = time.time()
+ retry = retries.get(
+ service, {'delay': self.retry_wait, 'next_retry': now})
+ # If we're connecting to a named service, check if it's time
+ if service and now < retry['next_retry']:
+ continue
+ try:
+ self.socket = new_socket()
+ self.socket.settimeout(self.timeout)
+ self._report_connection_status(
+ ConnectionStatus(CONNECTION_STATUS_CONNECTING,
+ NetworkAddress(self.host, self.port)))
+ # Resolve the service name. If service is None, we're
+ # connecting directly to a host name or IP-address
+ if service:
+ host = None
+ port = None
+ service_info = get_info_from_service(service,
+ self.zconf)
+ host, port = get_host_from_service_info(service_info)
+ if host and port:
+ try:
+ self.fn = service_info.properties[b'fn']\
+ .decode('utf-8')
+ except (AttributeError, KeyError, UnicodeError):
+ pass
+ self.logger.debug(
+ "[%s:%s] Resolved service %s to %s:%s",
+ self.fn or self.host, self.port, service, host,
+ port)
+ self.host = host
+ self.port = port
+ else:
+ self.logger.debug(
+ "[%s:%s] Failed to resolve service %s",
+ self.fn or self.host, self.port, service)
+ self._report_connection_status(
+ ConnectionStatus(
+ CONNECTION_STATUS_FAILED_RESOLVE,
+ NetworkAddress(service, None)))
+ mdns_backoff(service, retry)
+ # If zeroconf fails to receive the necessary data,
+ # try next service
+ continue
+
+ self.logger.debug("[%s:%s] Connecting to %s:%s",
+ self.fn or self.host, self.port,
+ self.host, self.port)
+ self.socket.connect((self.host, self.port))
+ self.socket = ssl.wrap_socket(self.socket)
+ self.connecting = False
+ self._force_recon = False
+ self._report_connection_status(
+ ConnectionStatus(CONNECTION_STATUS_CONNECTED,
+ NetworkAddress(self.host, self.port)))
+ self.receiver_controller.update_status()
+ self.heartbeat_controller.ping()
+ self.heartbeat_controller.reset()
+
+ self.logger.debug("[%s:%s] Connected!",
+ self.fn or self.host, self.port)
+ return
+ except OSError as err:
+ self.connecting = True
+ if self.stop.is_set():
+ self.logger.error(
+ "[%s:%s] Failed to connect: %s. "
+ "aborting due to stop signal.",
+ self.fn or self.host, self.port, err)
+ raise ChromecastConnectionError("Failed to connect")
+
+ self._report_connection_status(
+ ConnectionStatus(CONNECTION_STATUS_FAILED,
+ NetworkAddress(self.host, self.port)))
+ if service is not None:
+ retry_log_fun(
+ "[%s:%s] Failed to connect to service %s"
+ ", retrying in %.1fs",
+ self.fn or self.host, self.port,
+ service, retry['delay'])
+ mdns_backoff(service, retry)
+ else:
+ retry_log_fun(
+ "[%s:%s] Failed to connect, retrying in %.1fs",
+ self.fn or self.host, self.port, self.retry_wait)
retry_log_fun = self.logger.debug
- time.sleep(self.retry_wait)
- if tries:
- tries -= 1
- else:
- self.stop.set()
- self.logger.error("Failed to connect. No retries.")
- raise ChromecastConnectionError("Failed to connect")
+ # Only sleep if we have another retry remaining
+ if tries is None or tries > 1:
+ self.logger.debug(
+ "[%s:%s] Not connected, sleeping for %.1fs. Services: %s",
+ self.fn or self.host, self.port,
+ self.retry_wait, self.services)
+ time.sleep(self.retry_wait)
+
+ if tries:
+ tries -= 1
+
+ self.stop.set()
+ self.logger.error("[%s:%s] Failed to connect. No retries.",
+ self.fn or self.host, self.port)
+ raise ChromecastConnectionError("Failed to connect")
def disconnect(self):
""" Disconnect socket connection to Chromecast device """
@@ -368,11 +449,14 @@
except InterruptLoop as exc:
if self.stop.is_set():
self.logger.info(
- "Stopped while reading message, disconnecting.")
+ "[%s:%s] Stopped while reading message, "
+ "disconnecting.",
+ self.fn or self.host, self.port)
else:
self.logger.error(
- "Interruption caught without being stopped: %s",
- exc)
+ "[%s:%s] Interruption caught without being stopped: "
+ "%s",
+ self.fn or self.host, self.port, exc)
return 1
except ssl.SSLError as exc:
if exc.errno == ssl.SSL_ERROR_EOF:
@@ -381,7 +465,8 @@
raise
except socket.error:
self._force_recon = True
- self.logger.error('Error reading from socket.')
+ self.logger.error('[%s:%s] Error reading from socket.',
+ self.fn or self.host, self.port)
else:
data = _json_from_message(message)
if not message:
@@ -425,11 +510,15 @@
reset = False
if self._force_recon:
self.logger.warning(
- "Error communicating with socket, resetting connection")
+ "[%s:%s] Error communicating with socket, resetting "
+ "connection",
+ self.fn or self.host, self.port)
reset = True
elif self.heartbeat_controller.is_expired():
- self.logger.warning("Heartbeat timeout, resetting connection")
+ self.logger.warning(
+ "[%s:%s] Heartbeat timeout, resetting connection",
+ self.fn or self.host, self.port)
reset = True
if reset:
@@ -451,7 +540,8 @@
# debug messages
if message.namespace != NS_HEARTBEAT:
self.logger.debug(
- "Received: %s", _message_to_string(message, data))
+ "[%s:%s] Received: %s", self.fn or self.host, self.port,
+ _message_to_string(message, data))
# message handlers
try:
@@ -462,18 +552,20 @@
if not handled:
if data.get(REQUEST_ID) not in self._request_callbacks:
self.logger.debug(
- "Message unhandled: %s",
+ "[%s:%s] Message unhandled: %s",
+ self.fn or self.host, self.port,
_message_to_string(message, data))
except Exception: # pylint: disable=broad-except
self.logger.exception(
- ("Exception caught while sending message to "
- "controller %s: %s"),
+ ("[%s:%s] Exception caught while sending message to "
+ "controller %s: %s"), self.fn or self.host, self.port,
type(self._handlers[message.namespace]).__name__,
_message_to_string(message, data))
else:
self.logger.debug(
- "Received unknown namespace: %s",
+ "[%s:%s] Received unknown namespace: %s",
+ self.fn or self.host, self.port,
_message_to_string(message, data))
def _cleanup(self):
@@ -490,7 +582,11 @@
except Exception: # pylint: disable=broad-except
pass
- self.socket.close()
+ try:
+ self.socket.close()
+ except Exception: # pylint: disable=broad-except
+ self.logger.exception(
+ "[%s:%s] _cleanup", self.fn or self.host, self.port)
self._report_connection_status(
ConnectionStatus(CONNECTION_STATUS_DISCONNECTED,
NetworkAddress(self.host, self.port)))
@@ -500,7 +596,8 @@
""" Report a change in the connection status to any listeners """
for listener in self._connection_listeners:
try:
- self.logger.debug("connection listener: %x (%s)",
+ self.logger.debug("[%s:%s] connection listener: %x (%s)",
+ self.fn or self.host, self.port,
id(listener), type(listener).__name__)
listener.new_connection_status(status)
except Exception: # pylint: disable=broad-except
@@ -580,7 +677,9 @@
# Log all messages except heartbeat
if msg.namespace != NS_HEARTBEAT:
- self.logger.debug("Sending: %s", _message_to_string(msg, data))
+ self.logger.debug("[%s:%s] Sending: %s",
+ self.fn or self.host, self.port,
+ _message_to_string(msg, data))
if not force and self.stop.is_set():
raise PyChromecastStopped("Socket client's thread is stopped.")
@@ -596,9 +695,11 @@
except socket.error:
self._request_callbacks.pop(request_id, None)
self._force_recon = True
- self.logger.info('Error writing to socket.')
+ self.logger.info('[%s:%s] Error writing to socket.',
+ self.fn or self.host, self.port)
else:
- raise NotConnected("Chromecast is connecting...")
+ raise NotConnected("Chromecast " + self.host + ":" + self.port +
+ " is connecting...")
def send_platform_message(self, namespace, message, inc_session_id=False,
callback_function_param=False):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PyChromecast-2.3.0/requirements.txt new/PyChromecast-2.5.2/requirements.txt
--- old/PyChromecast-2.3.0/requirements.txt 2018-07-10 10:42:56.000000000 +0200
+++ new/PyChromecast-2.5.2/requirements.txt 2019-01-17 19:45:56.000000000 +0100
@@ -1,4 +1,4 @@
requests>=2.0
protobuf>=3.0.0
zeroconf>=0.17.7
-casttube>=0.1.0
+casttube>=0.2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/PyChromecast-2.3.0/setup.py new/PyChromecast-2.5.2/setup.py
--- old/PyChromecast-2.3.0/setup.py 2018-09-05 15:00:24.000000000 +0200
+++ new/PyChromecast-2.5.2/setup.py 2019-02-16 20:43:34.000000000 +0100
@@ -5,7 +5,7 @@
setup(
name='PyChromecast',
- version='2.3.0',
+ version='2.5.2',
license='MIT',
url='https://github.com/balloob/pychromecast',
author='Paulus Schoutsen',