/usr/lib/python3/dist-packages/pychromecast/dial.py is in python3-pychromecast 0.8.1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | """
Implements the DIAL-protocol to communicate with the Chromecast
"""
import xml.etree.ElementTree as ET
from collections import namedtuple
from uuid import UUID
import requests
import six
XML_NS_UPNP_DEVICE = "{urn:schemas-upnp-org:device-1-0}"
FORMAT_BASE_URL = "http://{}:8008"
CC_SESSION = requests.Session()
CC_SESSION.headers['content-type'] = 'application/json'
# Regular chromecast, supports video/audio
CAST_TYPE_CHROMECAST = 'cast'
# Cast Audio device, supports only audio
CAST_TYPE_AUDIO = 'audio'
# Cast Audio group device, supports only audio
CAST_TYPE_GROUP = 'group'
CAST_TYPES = {
u'chromecast': CAST_TYPE_CHROMECAST,
u'chromecast audio': CAST_TYPE_AUDIO,
u'google cast group': CAST_TYPE_GROUP,
}
def reboot(host):
""" Reboots the chromecast. """
CC_SESSION.post(FORMAT_BASE_URL.format(host) + "/setup/reboot",
data='{"params":"now"}', timeout=10)
def get_device_status(host):
"""
:param host: Hostname or ip to fetch status from
:type host: str
:return: The device status as a named tuple.
:rtype: pychromecast.dial.DeviceStatus or None
"""
try:
req = CC_SESSION.get(
FORMAT_BASE_URL.format(host) + "/ssdp/device-desc.xml",
timeout=10)
# The Requests library will fall back to guessing the encoding in case
# no encoding is specified in the response headers - which is the case
# for the Chromecast.
# The standard mandates utf-8 encoding, let's fall back to that instead
# if no encoding is provided, since the autodetection does not always
# provide correct results.
if req.encoding is None:
req.encoding = 'utf-8'
status_el = ET.fromstring(req.text.encode("UTF-8"))
device_info_el = status_el.find(XML_NS_UPNP_DEVICE + "device")
api_version_el = status_el.find(XML_NS_UPNP_DEVICE + "specVersion")
friendly_name = _read_xml_element(device_info_el, XML_NS_UPNP_DEVICE,
"friendlyName", "Unknown Chromecast")
model_name = _read_xml_element(device_info_el, XML_NS_UPNP_DEVICE,
"modelName", "Unknown model name")
manufacturer = _read_xml_element(device_info_el, XML_NS_UPNP_DEVICE,
"manufacturer",
"Unknown manufacturer")
udn = _read_xml_element(device_info_el, XML_NS_UPNP_DEVICE,
"UDN",
None)
api_version = (int(_read_xml_element(api_version_el,
XML_NS_UPNP_DEVICE, "major", -1)),
int(_read_xml_element(api_version_el,
XML_NS_UPNP_DEVICE, "minor", -1)))
cast_type = CAST_TYPES.get(model_name.lower(),
CAST_TYPE_CHROMECAST)
uuid = None
if udn and udn.startswith('uuid:'):
uuid = UUID(udn[len('uuid:'):].replace("-", ""))
return DeviceStatus(friendly_name, model_name, manufacturer,
api_version, uuid, cast_type)
except (requests.exceptions.RequestException, ET.ParseError):
return None
def _read_xml_element(element, xml_ns, tag_name, default=""):
""" Helper method to read text from an element. """
try:
text = element.find(xml_ns + tag_name).text
if isinstance(text, six.text_type):
return text
else:
return text.decode('utf-8')
except AttributeError:
return default
DeviceStatus = namedtuple("DeviceStatus",
["friendly_name", "model_name",
"manufacturer", "api_version",
"uuid", "cast_type"])
|