2019-04-03 15:40:03 +00:00
|
|
|
"""Support for the DirecTV receivers."""
|
2018-10-29 20:06:37 +00:00
|
|
|
import logging
|
2019-12-05 05:23:05 +00:00
|
|
|
|
|
|
|
from DirectPy import DIRECTV
|
2017-08-29 22:08:56 +00:00
|
|
|
import requests
|
2018-09-09 12:26:06 +00:00
|
|
|
import voluptuous as vol
|
2016-07-26 06:20:56 +00:00
|
|
|
|
2019-12-05 05:23:05 +00:00
|
|
|
from homeassistant.components.media_player import PLATFORM_SCHEMA, MediaPlayerDevice
|
2019-02-08 22:18:18 +00:00
|
|
|
from homeassistant.components.media_player.const import (
|
2019-07-31 19:25:30 +00:00
|
|
|
MEDIA_TYPE_CHANNEL,
|
|
|
|
MEDIA_TYPE_MOVIE,
|
|
|
|
MEDIA_TYPE_TVSHOW,
|
|
|
|
SUPPORT_NEXT_TRACK,
|
|
|
|
SUPPORT_PAUSE,
|
|
|
|
SUPPORT_PLAY,
|
|
|
|
SUPPORT_PLAY_MEDIA,
|
|
|
|
SUPPORT_PREVIOUS_TRACK,
|
|
|
|
SUPPORT_STOP,
|
|
|
|
SUPPORT_TURN_OFF,
|
|
|
|
SUPPORT_TURN_ON,
|
|
|
|
)
|
2016-07-26 06:20:56 +00:00
|
|
|
from homeassistant.const import (
|
2019-07-31 19:25:30 +00:00
|
|
|
CONF_DEVICE,
|
|
|
|
CONF_HOST,
|
|
|
|
CONF_NAME,
|
|
|
|
CONF_PORT,
|
|
|
|
STATE_OFF,
|
|
|
|
STATE_PAUSED,
|
|
|
|
STATE_PLAYING,
|
|
|
|
)
|
2016-09-05 15:39:21 +00:00
|
|
|
import homeassistant.helpers.config_validation as cv
|
2018-10-29 20:06:37 +00:00
|
|
|
import homeassistant.util.dt as dt_util
|
2016-07-26 06:20:56 +00:00
|
|
|
|
2018-10-29 20:06:37 +00:00
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
ATTR_MEDIA_CURRENTLY_RECORDING = "media_currently_recording"
|
|
|
|
ATTR_MEDIA_RATING = "media_rating"
|
|
|
|
ATTR_MEDIA_RECORDED = "media_recorded"
|
|
|
|
ATTR_MEDIA_START_TIME = "media_start_time"
|
2018-10-29 20:06:37 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
DEFAULT_DEVICE = "0"
|
2018-09-09 12:26:06 +00:00
|
|
|
DEFAULT_NAME = "DirecTV Receiver"
|
2016-07-26 06:20:56 +00:00
|
|
|
DEFAULT_PORT = 8080
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
SUPPORT_DTV = (
|
|
|
|
SUPPORT_PAUSE
|
|
|
|
| SUPPORT_TURN_ON
|
|
|
|
| SUPPORT_TURN_OFF
|
|
|
|
| SUPPORT_PLAY_MEDIA
|
|
|
|
| SUPPORT_STOP
|
|
|
|
| SUPPORT_NEXT_TRACK
|
|
|
|
| SUPPORT_PREVIOUS_TRACK
|
|
|
|
| SUPPORT_PLAY
|
|
|
|
)
|
|
|
|
|
|
|
|
SUPPORT_DTV_CLIENT = (
|
|
|
|
SUPPORT_PAUSE
|
|
|
|
| SUPPORT_PLAY_MEDIA
|
|
|
|
| SUPPORT_STOP
|
|
|
|
| SUPPORT_NEXT_TRACK
|
|
|
|
| SUPPORT_PREVIOUS_TRACK
|
|
|
|
| SUPPORT_PLAY
|
|
|
|
)
|
|
|
|
|
|
|
|
DATA_DIRECTV = "data_directv"
|
|
|
|
|
|
|
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
|
|
|
{
|
|
|
|
vol.Required(CONF_HOST): cv.string,
|
|
|
|
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
|
|
|
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
|
|
|
|
vol.Optional(CONF_DEVICE, default=DEFAULT_DEVICE): cv.string,
|
|
|
|
}
|
|
|
|
)
|
2016-09-05 15:39:21 +00:00
|
|
|
|
2016-07-26 06:20:56 +00:00
|
|
|
|
2018-08-24 14:37:30 +00:00
|
|
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
2017-05-02 16:18:47 +00:00
|
|
|
"""Set up the DirecTV platform."""
|
2018-11-05 18:33:59 +00:00
|
|
|
known_devices = hass.data.get(DATA_DIRECTV, set())
|
2020-02-23 18:26:34 +00:00
|
|
|
entities = []
|
2016-07-26 06:20:56 +00:00
|
|
|
|
2017-08-29 22:08:56 +00:00
|
|
|
if CONF_HOST in config:
|
2020-02-23 18:26:34 +00:00
|
|
|
name = config[CONF_NAME]
|
|
|
|
host = config[CONF_HOST]
|
|
|
|
port = config[CONF_PORT]
|
|
|
|
device = config[CONF_DEVICE]
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
_LOGGER.debug(
|
2020-02-23 18:26:34 +00:00
|
|
|
"Adding configured device %s with client address %s", name, device,
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
2016-07-26 06:20:56 +00:00
|
|
|
|
2020-02-23 18:26:34 +00:00
|
|
|
dtv = DIRECTV(host, port, device)
|
|
|
|
dtv_version = _get_receiver_version(dtv)
|
|
|
|
|
|
|
|
entities.append(DirecTvDevice(name, device, dtv, dtv_version,))
|
|
|
|
known_devices.add((host, device))
|
|
|
|
|
2017-08-29 22:08:56 +00:00
|
|
|
elif discovery_info:
|
2019-07-31 19:25:30 +00:00
|
|
|
host = discovery_info.get("host")
|
2020-02-24 16:47:52 +00:00
|
|
|
name = f"DirecTV_{discovery_info.get('serial', '')}"
|
2017-08-29 22:08:56 +00:00
|
|
|
|
2018-09-09 12:26:06 +00:00
|
|
|
# Attempt to discover additional RVU units
|
2018-11-05 15:19:03 +00:00
|
|
|
_LOGGER.debug("Doing discovery of DirecTV devices on %s", host)
|
|
|
|
|
|
|
|
dtv = DIRECTV(host, DEFAULT_PORT)
|
2020-02-23 18:26:34 +00:00
|
|
|
|
2017-08-29 22:08:56 +00:00
|
|
|
try:
|
2020-02-23 18:26:34 +00:00
|
|
|
dtv_version = _get_receiver_version(dtv)
|
2018-11-05 15:19:03 +00:00
|
|
|
resp = dtv.get_locations()
|
|
|
|
except requests.exceptions.RequestException as ex:
|
2018-09-09 12:26:06 +00:00
|
|
|
# Bail out and just go forward with uPnP data
|
2018-11-05 15:19:03 +00:00
|
|
|
# Make sure that this device is not already configured
|
|
|
|
# Comparing based on host (IP) and clientAddr.
|
|
|
|
_LOGGER.debug("Request exception %s trying to get locations", ex)
|
2019-07-31 19:25:30 +00:00
|
|
|
resp = {"locations": [{"locationName": name, "clientAddr": DEFAULT_DEVICE}]}
|
2018-11-05 15:19:03 +00:00
|
|
|
|
|
|
|
_LOGGER.debug("Known devices: %s", known_devices)
|
|
|
|
for loc in resp.get("locations") or []:
|
|
|
|
if "locationName" not in loc or "clientAddr" not in loc:
|
|
|
|
continue
|
|
|
|
|
2020-02-23 18:26:34 +00:00
|
|
|
loc_name = str.title(loc["locationName"])
|
|
|
|
|
2018-11-05 15:19:03 +00:00
|
|
|
# Make sure that this device is not already configured
|
|
|
|
# Comparing based on host (IP) and clientAddr.
|
2018-11-05 18:33:59 +00:00
|
|
|
if (host, loc["clientAddr"]) in known_devices:
|
2019-07-31 19:25:30 +00:00
|
|
|
_LOGGER.debug(
|
|
|
|
"Discovered device %s on host %s with "
|
|
|
|
"client address %s is already "
|
|
|
|
"configured",
|
2020-02-23 18:26:34 +00:00
|
|
|
loc_name,
|
2019-07-31 19:25:30 +00:00
|
|
|
host,
|
|
|
|
loc["clientAddr"],
|
|
|
|
)
|
2018-11-05 18:33:59 +00:00
|
|
|
else:
|
2019-07-31 19:25:30 +00:00
|
|
|
_LOGGER.debug(
|
2020-01-02 19:17:10 +00:00
|
|
|
"Adding discovered device %s with client address %s",
|
2020-02-23 18:26:34 +00:00
|
|
|
loc_name,
|
2019-07-31 19:25:30 +00:00
|
|
|
loc["clientAddr"],
|
|
|
|
)
|
2020-02-23 18:26:34 +00:00
|
|
|
|
|
|
|
entities.append(
|
|
|
|
DirecTvDevice(
|
|
|
|
loc_name,
|
2019-07-31 19:25:30 +00:00
|
|
|
loc["clientAddr"],
|
2020-02-23 18:26:34 +00:00
|
|
|
DIRECTV(host, DEFAULT_PORT, loc["clientAddr"]),
|
|
|
|
dtv_version,
|
|
|
|
)
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
2020-02-23 18:26:34 +00:00
|
|
|
known_devices.add((host, loc["clientAddr"]))
|
2017-08-29 22:08:56 +00:00
|
|
|
|
2020-02-23 18:26:34 +00:00
|
|
|
add_entities(entities)
|
2016-07-26 06:20:56 +00:00
|
|
|
|
|
|
|
|
2020-02-23 18:26:34 +00:00
|
|
|
def _get_receiver_version(client):
|
|
|
|
"""Return the version of the DirectTV receiver."""
|
|
|
|
try:
|
|
|
|
return client.get_version()
|
|
|
|
except requests.exceptions.RequestException as ex:
|
|
|
|
_LOGGER.debug("Request exception %s trying to get receiver version", ex)
|
|
|
|
return None
|
2016-07-26 06:20:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
class DirecTvDevice(MediaPlayerDevice):
|
2017-09-23 15:15:46 +00:00
|
|
|
"""Representation of a DirecTV receiver on the network."""
|
2016-07-26 06:20:56 +00:00
|
|
|
|
2020-02-23 18:26:34 +00:00
|
|
|
def __init__(self, name, device, dtv, version_info=None):
|
2016-07-26 06:20:56 +00:00
|
|
|
"""Initialize the device."""
|
2020-02-23 18:26:34 +00:00
|
|
|
self.dtv = dtv
|
2016-07-26 06:20:56 +00:00
|
|
|
self._name = name
|
2020-02-23 18:26:34 +00:00
|
|
|
self._unique_id = None
|
2016-07-26 06:20:56 +00:00
|
|
|
self._is_standby = True
|
|
|
|
self._current = None
|
2018-10-29 20:06:37 +00:00
|
|
|
self._last_update = None
|
|
|
|
self._paused = None
|
|
|
|
self._last_position = None
|
|
|
|
self._is_recorded = None
|
2019-07-31 19:25:30 +00:00
|
|
|
self._is_client = device != "0"
|
2018-10-29 20:06:37 +00:00
|
|
|
self._assumed_state = None
|
2018-11-05 15:19:03 +00:00
|
|
|
self._available = False
|
2018-12-07 06:26:49 +00:00
|
|
|
self._first_error_timestamp = None
|
2018-10-29 20:06:37 +00:00
|
|
|
|
2020-02-23 18:26:34 +00:00
|
|
|
if device != "0":
|
|
|
|
self._unique_id = device
|
|
|
|
elif version_info:
|
|
|
|
self._unique_id = "".join(version_info.get("receiverId").split())
|
|
|
|
|
2018-11-19 10:47:00 +00:00
|
|
|
if self._is_client:
|
2019-07-31 19:25:30 +00:00
|
|
|
_LOGGER.debug("Created DirecTV client %s for device %s", self._name, device)
|
2018-11-19 10:47:00 +00:00
|
|
|
else:
|
|
|
|
_LOGGER.debug("Created DirecTV device for %s", self._name)
|
2016-07-26 06:20:56 +00:00
|
|
|
|
|
|
|
def update(self):
|
|
|
|
"""Retrieve latest state."""
|
2018-12-07 06:26:49 +00:00
|
|
|
_LOGGER.debug("%s: Updating status", self.entity_id)
|
2018-11-05 15:19:03 +00:00
|
|
|
try:
|
|
|
|
self._available = True
|
|
|
|
self._is_standby = self.dtv.get_standby()
|
|
|
|
if self._is_standby:
|
|
|
|
self._current = None
|
|
|
|
self._is_recorded = None
|
|
|
|
self._paused = None
|
|
|
|
self._assumed_state = False
|
|
|
|
self._last_position = None
|
|
|
|
self._last_update = None
|
|
|
|
else:
|
|
|
|
self._current = self.dtv.get_tuned()
|
2019-07-31 19:25:30 +00:00
|
|
|
if self._current["status"]["code"] == 200:
|
2018-12-07 06:26:49 +00:00
|
|
|
self._first_error_timestamp = None
|
2019-07-31 19:25:30 +00:00
|
|
|
self._is_recorded = self._current.get("uniqueId") is not None
|
|
|
|
self._paused = self._last_position == self._current["offset"]
|
2018-11-05 15:19:03 +00:00
|
|
|
self._assumed_state = self._is_recorded
|
2019-07-31 19:25:30 +00:00
|
|
|
self._last_position = self._current["offset"]
|
|
|
|
self._last_update = (
|
|
|
|
dt_util.utcnow()
|
|
|
|
if not self._paused or self._last_update is None
|
|
|
|
else self._last_update
|
|
|
|
)
|
2018-11-05 15:19:03 +00:00
|
|
|
else:
|
2018-12-07 06:26:49 +00:00
|
|
|
# If an error is received then only set to unavailable if
|
|
|
|
# this started at least 1 minute ago.
|
2020-02-24 16:47:52 +00:00
|
|
|
log_message = f"{self.entity_id}: Invalid status {self._current['status']['code']} received"
|
2018-12-07 06:26:49 +00:00
|
|
|
if self._check_state_available():
|
|
|
|
_LOGGER.debug(log_message)
|
|
|
|
else:
|
|
|
|
_LOGGER.error(log_message)
|
|
|
|
|
2018-11-05 15:19:03 +00:00
|
|
|
except requests.RequestException as ex:
|
2019-07-31 19:25:30 +00:00
|
|
|
_LOGGER.error(
|
2020-01-02 19:17:10 +00:00
|
|
|
"%s: Request error trying to update current status: %s",
|
2019-07-31 19:25:30 +00:00
|
|
|
self.entity_id,
|
|
|
|
ex,
|
|
|
|
)
|
2018-12-07 06:26:49 +00:00
|
|
|
self._check_state_available()
|
|
|
|
|
|
|
|
except Exception as ex:
|
2019-07-31 19:25:30 +00:00
|
|
|
_LOGGER.error(
|
|
|
|
"%s: Exception trying to update current status: %s", self.entity_id, ex
|
|
|
|
)
|
2018-11-05 15:19:03 +00:00
|
|
|
self._available = False
|
2018-12-07 06:26:49 +00:00
|
|
|
if not self._first_error_timestamp:
|
|
|
|
self._first_error_timestamp = dt_util.utcnow()
|
2018-11-05 15:19:03 +00:00
|
|
|
raise
|
2018-10-29 20:06:37 +00:00
|
|
|
|
2018-12-07 06:26:49 +00:00
|
|
|
def _check_state_available(self):
|
|
|
|
"""Set to unavailable if issue been occurring over 1 minute."""
|
|
|
|
if not self._first_error_timestamp:
|
|
|
|
self._first_error_timestamp = dt_util.utcnow()
|
|
|
|
else:
|
|
|
|
tdelta = dt_util.utcnow() - self._first_error_timestamp
|
|
|
|
if tdelta.total_seconds() >= 60:
|
|
|
|
self._available = False
|
|
|
|
|
|
|
|
return self._available
|
|
|
|
|
2018-10-29 20:06:37 +00:00
|
|
|
@property
|
|
|
|
def device_state_attributes(self):
|
|
|
|
"""Return device specific state attributes."""
|
|
|
|
attributes = {}
|
|
|
|
if not self._is_standby:
|
2019-07-31 19:25:30 +00:00
|
|
|
attributes[ATTR_MEDIA_CURRENTLY_RECORDING] = self.media_currently_recording
|
2018-10-29 20:06:37 +00:00
|
|
|
attributes[ATTR_MEDIA_RATING] = self.media_rating
|
|
|
|
attributes[ATTR_MEDIA_RECORDED] = self.media_recorded
|
|
|
|
attributes[ATTR_MEDIA_START_TIME] = self.media_start_time
|
|
|
|
|
|
|
|
return attributes
|
2016-07-26 06:20:56 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self):
|
|
|
|
"""Return the name of the device."""
|
|
|
|
return self._name
|
|
|
|
|
2020-02-23 18:26:34 +00:00
|
|
|
@property
|
|
|
|
def unique_id(self):
|
|
|
|
"""Return a unique ID to use for this media player."""
|
|
|
|
return self._unique_id
|
|
|
|
|
2016-07-26 06:20:56 +00:00
|
|
|
# MediaPlayerDevice properties and methods
|
|
|
|
@property
|
|
|
|
def state(self):
|
|
|
|
"""Return the state of the device."""
|
|
|
|
if self._is_standby:
|
|
|
|
return STATE_OFF
|
2018-10-29 20:06:37 +00:00
|
|
|
|
|
|
|
# For recorded media we can determine if it is paused or not.
|
|
|
|
# For live media we're unable to determine and will always return
|
|
|
|
# playing instead.
|
|
|
|
if self._paused:
|
|
|
|
return STATE_PAUSED
|
|
|
|
|
2017-07-06 03:02:16 +00:00
|
|
|
return STATE_PLAYING
|
2016-07-26 06:20:56 +00:00
|
|
|
|
2018-11-05 15:19:03 +00:00
|
|
|
@property
|
|
|
|
def available(self):
|
|
|
|
"""Return if able to retrieve information from DVR or not."""
|
|
|
|
return self._available
|
|
|
|
|
2018-10-29 20:06:37 +00:00
|
|
|
@property
|
|
|
|
def assumed_state(self):
|
|
|
|
"""Return if we assume the state or not."""
|
|
|
|
return self._assumed_state
|
|
|
|
|
2016-07-26 06:20:56 +00:00
|
|
|
@property
|
|
|
|
def media_content_id(self):
|
2017-05-02 16:18:47 +00:00
|
|
|
"""Return the content ID of current playing media."""
|
2016-07-26 06:20:56 +00:00
|
|
|
if self._is_standby:
|
|
|
|
return None
|
2018-10-29 20:06:37 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
return self._current["programId"]
|
2016-07-26 06:20:56 +00:00
|
|
|
|
2018-10-29 20:06:37 +00:00
|
|
|
@property
|
|
|
|
def media_content_type(self):
|
|
|
|
"""Return the content type of current playing media."""
|
|
|
|
if self._is_standby:
|
|
|
|
return None
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
if "episodeTitle" in self._current:
|
2018-10-29 20:06:37 +00:00
|
|
|
return MEDIA_TYPE_TVSHOW
|
|
|
|
|
|
|
|
return MEDIA_TYPE_MOVIE
|
|
|
|
|
2016-07-26 06:20:56 +00:00
|
|
|
@property
|
|
|
|
def media_duration(self):
|
2017-05-02 16:18:47 +00:00
|
|
|
"""Return the duration of current playing media in seconds."""
|
2016-07-26 06:20:56 +00:00
|
|
|
if self._is_standby:
|
|
|
|
return None
|
2018-10-29 20:06:37 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
return self._current["duration"]
|
2016-07-26 06:20:56 +00:00
|
|
|
|
2018-10-29 20:06:37 +00:00
|
|
|
@property
|
|
|
|
def media_position(self):
|
|
|
|
"""Position of current playing media in seconds."""
|
|
|
|
if self._is_standby:
|
|
|
|
return None
|
|
|
|
|
|
|
|
return self._last_position
|
|
|
|
|
|
|
|
@property
|
|
|
|
def media_position_updated_at(self):
|
|
|
|
"""When was the position of the current playing media valid.
|
|
|
|
|
|
|
|
Returns value from homeassistant.util.dt.utcnow().
|
|
|
|
"""
|
|
|
|
if self._is_standby:
|
|
|
|
return None
|
|
|
|
|
|
|
|
return self._last_update
|
|
|
|
|
2016-07-26 06:20:56 +00:00
|
|
|
@property
|
|
|
|
def media_title(self):
|
2017-05-02 16:18:47 +00:00
|
|
|
"""Return the title of current playing media."""
|
2016-07-26 06:20:56 +00:00
|
|
|
if self._is_standby:
|
|
|
|
return None
|
2018-10-29 20:06:37 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
return self._current["title"]
|
2016-07-26 06:20:56 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def media_series_title(self):
|
2017-05-02 16:18:47 +00:00
|
|
|
"""Return the title of current episode of TV show."""
|
2016-07-26 06:20:56 +00:00
|
|
|
if self._is_standby:
|
|
|
|
return None
|
2018-10-29 20:06:37 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
return self._current.get("episodeTitle")
|
2018-10-29 20:06:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def media_channel(self):
|
|
|
|
"""Return the channel current playing media."""
|
|
|
|
if self._is_standby:
|
|
|
|
return None
|
|
|
|
|
2020-02-24 16:47:52 +00:00
|
|
|
return f"{self._current['callsign']} ({self._current['major']})"
|
2018-10-29 20:06:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def source(self):
|
|
|
|
"""Name of the current input source."""
|
|
|
|
if self._is_standby:
|
|
|
|
return None
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
return self._current["major"]
|
2016-07-26 06:20:56 +00:00
|
|
|
|
|
|
|
@property
|
2017-02-08 04:42:45 +00:00
|
|
|
def supported_features(self):
|
|
|
|
"""Flag media player features that are supported."""
|
2018-11-19 10:47:00 +00:00
|
|
|
return SUPPORT_DTV_CLIENT if self._is_client else SUPPORT_DTV
|
2016-07-26 06:20:56 +00:00
|
|
|
|
|
|
|
@property
|
2018-10-29 20:06:37 +00:00
|
|
|
def media_currently_recording(self):
|
|
|
|
"""If the media is currently being recorded or not."""
|
|
|
|
if self._is_standby:
|
|
|
|
return None
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
return self._current["isRecording"]
|
2016-07-26 06:20:56 +00:00
|
|
|
|
|
|
|
@property
|
2018-10-29 20:06:37 +00:00
|
|
|
def media_rating(self):
|
|
|
|
"""TV Rating of the current playing media."""
|
2016-07-26 06:20:56 +00:00
|
|
|
if self._is_standby:
|
|
|
|
return None
|
2017-07-06 06:30:01 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
return self._current["rating"]
|
2018-10-29 20:06:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def media_recorded(self):
|
|
|
|
"""If the media was recorded or live."""
|
|
|
|
if self._is_standby:
|
|
|
|
return None
|
|
|
|
|
|
|
|
return self._is_recorded
|
|
|
|
|
|
|
|
@property
|
|
|
|
def media_start_time(self):
|
|
|
|
"""Start time the program aired."""
|
|
|
|
if self._is_standby:
|
|
|
|
return None
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
return dt_util.as_local(dt_util.utc_from_timestamp(self._current["startTime"]))
|
2016-07-26 06:20:56 +00:00
|
|
|
|
|
|
|
def turn_on(self):
|
2017-05-02 16:18:47 +00:00
|
|
|
"""Turn on the receiver."""
|
2018-11-19 10:47:00 +00:00
|
|
|
if self._is_client:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
2018-10-29 20:06:37 +00:00
|
|
|
_LOGGER.debug("Turn on %s", self._name)
|
2019-07-31 19:25:30 +00:00
|
|
|
self.dtv.key_press("poweron")
|
2016-07-26 06:20:56 +00:00
|
|
|
|
|
|
|
def turn_off(self):
|
2017-05-02 16:18:47 +00:00
|
|
|
"""Turn off the receiver."""
|
2018-11-19 10:47:00 +00:00
|
|
|
if self._is_client:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
2018-10-29 20:06:37 +00:00
|
|
|
_LOGGER.debug("Turn off %s", self._name)
|
2019-07-31 19:25:30 +00:00
|
|
|
self.dtv.key_press("poweroff")
|
2016-07-26 06:20:56 +00:00
|
|
|
|
|
|
|
def media_play(self):
|
2017-05-02 16:18:47 +00:00
|
|
|
"""Send play command."""
|
2018-10-29 20:06:37 +00:00
|
|
|
_LOGGER.debug("Play on %s", self._name)
|
2019-07-31 19:25:30 +00:00
|
|
|
self.dtv.key_press("play")
|
2016-07-26 06:20:56 +00:00
|
|
|
|
|
|
|
def media_pause(self):
|
2017-05-02 16:18:47 +00:00
|
|
|
"""Send pause command."""
|
2018-10-29 20:06:37 +00:00
|
|
|
_LOGGER.debug("Pause on %s", self._name)
|
2019-07-31 19:25:30 +00:00
|
|
|
self.dtv.key_press("pause")
|
2016-07-26 06:20:56 +00:00
|
|
|
|
|
|
|
def media_stop(self):
|
2017-05-02 16:18:47 +00:00
|
|
|
"""Send stop command."""
|
2018-10-29 20:06:37 +00:00
|
|
|
_LOGGER.debug("Stop on %s", self._name)
|
2019-07-31 19:25:30 +00:00
|
|
|
self.dtv.key_press("stop")
|
2016-07-26 06:20:56 +00:00
|
|
|
|
|
|
|
def media_previous_track(self):
|
2017-05-02 16:18:47 +00:00
|
|
|
"""Send rewind command."""
|
2018-10-29 20:06:37 +00:00
|
|
|
_LOGGER.debug("Rewind on %s", self._name)
|
2019-07-31 19:25:30 +00:00
|
|
|
self.dtv.key_press("rew")
|
2016-07-26 06:20:56 +00:00
|
|
|
|
|
|
|
def media_next_track(self):
|
2017-05-02 16:18:47 +00:00
|
|
|
"""Send fast forward command."""
|
2018-10-29 20:06:37 +00:00
|
|
|
_LOGGER.debug("Fast forward on %s", self._name)
|
2019-07-31 19:25:30 +00:00
|
|
|
self.dtv.key_press("ffwd")
|
2018-10-29 20:06:37 +00:00
|
|
|
|
2018-11-20 23:05:25 +00:00
|
|
|
def play_media(self, media_type, media_id, **kwargs):
|
2018-10-29 20:06:37 +00:00
|
|
|
"""Select input source."""
|
2018-11-20 23:05:25 +00:00
|
|
|
if media_type != MEDIA_TYPE_CHANNEL:
|
2019-07-31 19:25:30 +00:00
|
|
|
_LOGGER.error(
|
|
|
|
"Invalid media type %s. Only %s is supported",
|
|
|
|
media_type,
|
|
|
|
MEDIA_TYPE_CHANNEL,
|
|
|
|
)
|
2018-11-20 23:05:25 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
_LOGGER.debug("Changing channel on %s to %s", self._name, media_id)
|
|
|
|
self.dtv.tune_channel(media_id)
|