Change source, add attributes, and improve state of DirecTV (#17536)
* Enhancements for DirecTV media player Following enhancements have been made: 1. Added debug logging 2. Added ability to change channel using select_source service of the remote platform. 3. State will now show paused if a recorded program is paused, for live TV playing will always be returned. 4. Added the following attributes: a. media_position: current position of the media (in seconds) b. media_position_updated_at: timestamp when media_position was updated. c. source: current source (channel). d. media_isbeingrecorded: if current media is being recorded or not. e. media_rating: TV/Movie rating of the media f. media_recorded: if current media is recorded or live TV g. media_starttime: Timestamp media was aired Reordered properties to follow same order as how they are in __init__.py of remote platform. * Fixed error and cleaned up few items Fixed an issue when determining if a program is recorded or not. Cleaned up some coding. * Attribute last position update only updated when position changed. The attribute media_position_updated_at will only be updated if the position changed (thus media is playing for recorded or live TV). Added assumed_state; will be set to False if in standby or when a recorded show is watched. For live TV it will be set to True. * Added some empty lines for easier reading Added some empty lines before returns to improve readability. * Seperated words in constants Seperated the words in constants. * Fix _lastupdate to _last_update Split words in _lastupdate to _last_update as I missed it.
This commit is contained in:
parent
d6913c6914
commit
deeb288daf
1 changed files with 151 additions and 19 deletions
|
@ -4,26 +4,37 @@ Support for the DirecTV receivers.
|
||||||
For more details about this platform, please refer to the documentation at
|
For more details about this platform, please refer to the documentation at
|
||||||
https://home-assistant.io/components/media_player.directv/
|
https://home-assistant.io/components/media_player.directv/
|
||||||
"""
|
"""
|
||||||
|
import logging
|
||||||
import requests
|
import requests
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.media_player import (
|
from homeassistant.components.media_player import (
|
||||||
MEDIA_TYPE_MOVIE, MEDIA_TYPE_TVSHOW, PLATFORM_SCHEMA, SUPPORT_NEXT_TRACK,
|
MEDIA_TYPE_MOVIE, MEDIA_TYPE_TVSHOW, PLATFORM_SCHEMA, SUPPORT_NEXT_TRACK,
|
||||||
SUPPORT_PAUSE, SUPPORT_PLAY, SUPPORT_PLAY_MEDIA, SUPPORT_PREVIOUS_TRACK,
|
SUPPORT_PAUSE, SUPPORT_PLAY, SUPPORT_PLAY_MEDIA, SUPPORT_PREVIOUS_TRACK,
|
||||||
SUPPORT_STOP, SUPPORT_TURN_OFF, SUPPORT_TURN_ON, MediaPlayerDevice)
|
SUPPORT_SELECT_SOURCE, SUPPORT_STOP, SUPPORT_TURN_OFF, SUPPORT_TURN_ON,
|
||||||
|
MediaPlayerDevice)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_DEVICE, CONF_HOST, CONF_NAME, CONF_PORT, STATE_OFF, STATE_PLAYING)
|
CONF_DEVICE, CONF_HOST, CONF_NAME, CONF_PORT, STATE_OFF, STATE_PAUSED,
|
||||||
|
STATE_PLAYING)
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
REQUIREMENTS = ['directpy==0.5']
|
REQUIREMENTS = ['directpy==0.5']
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
ATTR_MEDIA_CURRENTLY_RECORDING = 'media_currently_recording'
|
||||||
|
ATTR_MEDIA_RATING = 'media_rating'
|
||||||
|
ATTR_MEDIA_RECORDED = 'media_recorded'
|
||||||
|
ATTR_MEDIA_START_TIME = 'media_start_time'
|
||||||
|
|
||||||
DEFAULT_DEVICE = '0'
|
DEFAULT_DEVICE = '0'
|
||||||
DEFAULT_NAME = "DirecTV Receiver"
|
DEFAULT_NAME = "DirecTV Receiver"
|
||||||
DEFAULT_PORT = 8080
|
DEFAULT_PORT = 8080
|
||||||
|
|
||||||
SUPPORT_DTV = SUPPORT_PAUSE | SUPPORT_TURN_ON | SUPPORT_TURN_OFF | \
|
SUPPORT_DTV = SUPPORT_PAUSE | SUPPORT_TURN_ON | SUPPORT_TURN_OFF | \
|
||||||
SUPPORT_PLAY_MEDIA | SUPPORT_STOP | SUPPORT_NEXT_TRACK | \
|
SUPPORT_PLAY_MEDIA | SUPPORT_SELECT_SOURCE | SUPPORT_STOP | \
|
||||||
SUPPORT_PREVIOUS_TRACK | SUPPORT_PLAY
|
SUPPORT_NEXT_TRACK | SUPPORT_PREVIOUS_TRACK | SUPPORT_PLAY
|
||||||
|
|
||||||
DATA_DIRECTV = 'data_directv'
|
DATA_DIRECTV = 'data_directv'
|
||||||
|
|
||||||
|
@ -88,14 +99,46 @@ class DirecTvDevice(MediaPlayerDevice):
|
||||||
self._name = name
|
self._name = name
|
||||||
self._is_standby = True
|
self._is_standby = True
|
||||||
self._current = None
|
self._current = None
|
||||||
|
self._last_update = None
|
||||||
|
self._paused = None
|
||||||
|
self._last_position = None
|
||||||
|
self._is_recorded = None
|
||||||
|
self._assumed_state = None
|
||||||
|
|
||||||
|
_LOGGER.debug("Created DirecTV device for %s", self._name)
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
"""Retrieve latest state."""
|
"""Retrieve latest state."""
|
||||||
|
_LOGGER.debug("Updating state for %s", self._name)
|
||||||
self._is_standby = self.dtv.get_standby()
|
self._is_standby = self.dtv.get_standby()
|
||||||
if self._is_standby:
|
if self._is_standby:
|
||||||
self._current = None
|
self._current = None
|
||||||
|
self._is_recorded = None
|
||||||
|
self._paused = None
|
||||||
|
self._assumed_state = False
|
||||||
|
self._last_position = None
|
||||||
|
self._last_update = None
|
||||||
else:
|
else:
|
||||||
self._current = self.dtv.get_tuned()
|
self._current = self.dtv.get_tuned()
|
||||||
|
self._is_recorded = self._current.get('uniqueId') is not None
|
||||||
|
self._paused = self._last_position == self._current['offset']
|
||||||
|
self._assumed_state = self._is_recorded
|
||||||
|
self._last_position = self._current['offset']
|
||||||
|
self._last_update = dt_util.now() if not self._paused or\
|
||||||
|
self._last_update is None else self._last_update
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_state_attributes(self):
|
||||||
|
"""Return device specific state attributes."""
|
||||||
|
attributes = {}
|
||||||
|
if not self._is_standby:
|
||||||
|
attributes[ATTR_MEDIA_CURRENTLY_RECORDING] =\
|
||||||
|
self.media_currently_recording
|
||||||
|
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
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
|
@ -108,28 +151,72 @@ class DirecTvDevice(MediaPlayerDevice):
|
||||||
"""Return the state of the device."""
|
"""Return the state of the device."""
|
||||||
if self._is_standby:
|
if self._is_standby:
|
||||||
return STATE_OFF
|
return STATE_OFF
|
||||||
# Haven't determined a way to see if the content is paused
|
|
||||||
|
# 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
|
||||||
|
|
||||||
return STATE_PLAYING
|
return STATE_PLAYING
|
||||||
|
|
||||||
|
@property
|
||||||
|
def assumed_state(self):
|
||||||
|
"""Return if we assume the state or not."""
|
||||||
|
return self._assumed_state
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def media_content_id(self):
|
def media_content_id(self):
|
||||||
"""Return the content ID of current playing media."""
|
"""Return the content ID of current playing media."""
|
||||||
if self._is_standby:
|
if self._is_standby:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return self._current['programId']
|
return self._current['programId']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def media_content_type(self):
|
||||||
|
"""Return the content type of current playing media."""
|
||||||
|
if self._is_standby:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if 'episodeTitle' in self._current:
|
||||||
|
return MEDIA_TYPE_TVSHOW
|
||||||
|
|
||||||
|
return MEDIA_TYPE_MOVIE
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def media_duration(self):
|
def media_duration(self):
|
||||||
"""Return the duration of current playing media in seconds."""
|
"""Return the duration of current playing media in seconds."""
|
||||||
if self._is_standby:
|
if self._is_standby:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return self._current['duration']
|
return self._current['duration']
|
||||||
|
|
||||||
|
@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
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def media_title(self):
|
def media_title(self):
|
||||||
"""Return the title of current playing media."""
|
"""Return the title of current playing media."""
|
||||||
if self._is_standby:
|
if self._is_standby:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return self._current['title']
|
return self._current['title']
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -137,21 +224,8 @@ class DirecTvDevice(MediaPlayerDevice):
|
||||||
"""Return the title of current episode of TV show."""
|
"""Return the title of current episode of TV show."""
|
||||||
if self._is_standby:
|
if self._is_standby:
|
||||||
return None
|
return None
|
||||||
if 'episodeTitle' in self._current:
|
|
||||||
return self._current['episodeTitle']
|
|
||||||
return None
|
|
||||||
|
|
||||||
@property
|
return self._current.get('episodeTitle')
|
||||||
def supported_features(self):
|
|
||||||
"""Flag media player features that are supported."""
|
|
||||||
return SUPPORT_DTV
|
|
||||||
|
|
||||||
@property
|
|
||||||
def media_content_type(self):
|
|
||||||
"""Return the content type of current playing media."""
|
|
||||||
if 'episodeTitle' in self._current:
|
|
||||||
return MEDIA_TYPE_TVSHOW
|
|
||||||
return MEDIA_TYPE_MOVIE
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def media_channel(self):
|
def media_channel(self):
|
||||||
|
@ -162,30 +236,88 @@ class DirecTvDevice(MediaPlayerDevice):
|
||||||
return "{} ({})".format(
|
return "{} ({})".format(
|
||||||
self._current['callsign'], self._current['major'])
|
self._current['callsign'], self._current['major'])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def source(self):
|
||||||
|
"""Name of the current input source."""
|
||||||
|
if self._is_standby:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self._current['major']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def supported_features(self):
|
||||||
|
"""Flag media player features that are supported."""
|
||||||
|
return SUPPORT_DTV
|
||||||
|
|
||||||
|
@property
|
||||||
|
def media_currently_recording(self):
|
||||||
|
"""If the media is currently being recorded or not."""
|
||||||
|
if self._is_standby:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self._current['isRecording']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def media_rating(self):
|
||||||
|
"""TV Rating of the current playing media."""
|
||||||
|
if self._is_standby:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self._current['rating']
|
||||||
|
|
||||||
|
@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
|
||||||
|
|
||||||
|
return dt_util.as_local(
|
||||||
|
dt_util.utc_from_timestamp(self._current['startTime']))
|
||||||
|
|
||||||
def turn_on(self):
|
def turn_on(self):
|
||||||
"""Turn on the receiver."""
|
"""Turn on the receiver."""
|
||||||
|
_LOGGER.debug("Turn on %s", self._name)
|
||||||
self.dtv.key_press('poweron')
|
self.dtv.key_press('poweron')
|
||||||
|
|
||||||
def turn_off(self):
|
def turn_off(self):
|
||||||
"""Turn off the receiver."""
|
"""Turn off the receiver."""
|
||||||
|
_LOGGER.debug("Turn off %s", self._name)
|
||||||
self.dtv.key_press('poweroff')
|
self.dtv.key_press('poweroff')
|
||||||
|
|
||||||
def media_play(self):
|
def media_play(self):
|
||||||
"""Send play command."""
|
"""Send play command."""
|
||||||
|
_LOGGER.debug("Play on %s", self._name)
|
||||||
self.dtv.key_press('play')
|
self.dtv.key_press('play')
|
||||||
|
|
||||||
def media_pause(self):
|
def media_pause(self):
|
||||||
"""Send pause command."""
|
"""Send pause command."""
|
||||||
|
_LOGGER.debug("Pause on %s", self._name)
|
||||||
self.dtv.key_press('pause')
|
self.dtv.key_press('pause')
|
||||||
|
|
||||||
def media_stop(self):
|
def media_stop(self):
|
||||||
"""Send stop command."""
|
"""Send stop command."""
|
||||||
|
_LOGGER.debug("Stop on %s", self._name)
|
||||||
self.dtv.key_press('stop')
|
self.dtv.key_press('stop')
|
||||||
|
|
||||||
def media_previous_track(self):
|
def media_previous_track(self):
|
||||||
"""Send rewind command."""
|
"""Send rewind command."""
|
||||||
|
_LOGGER.debug("Rewind on %s", self._name)
|
||||||
self.dtv.key_press('rew')
|
self.dtv.key_press('rew')
|
||||||
|
|
||||||
def media_next_track(self):
|
def media_next_track(self):
|
||||||
"""Send fast forward command."""
|
"""Send fast forward command."""
|
||||||
|
_LOGGER.debug("Fast forward on %s", self._name)
|
||||||
self.dtv.key_press('ffwd')
|
self.dtv.key_press('ffwd')
|
||||||
|
|
||||||
|
def select_source(self, source):
|
||||||
|
"""Select input source."""
|
||||||
|
_LOGGER.debug("Changing channel on %s to %s", self._name, source)
|
||||||
|
self.dtv.tune_channel(source)
|
||||||
|
|
Loading…
Add table
Reference in a new issue