diff --git a/.coveragerc b/.coveragerc index ec649517113..181a5fa3f8c 100644 --- a/.coveragerc +++ b/.coveragerc @@ -243,6 +243,7 @@ omit = homeassistant/components/media_player/mpd.py homeassistant/components/media_player/nad.py homeassistant/components/media_player/onkyo.py + homeassistant/components/media_player/openhome.py homeassistant/components/media_player/panasonic_viera.py homeassistant/components/media_player/pandora.py homeassistant/components/media_player/philips_js.py diff --git a/homeassistant/components/discovery.py b/homeassistant/components/discovery.py index 51bdd2ce271..1ea019c7fc2 100644 --- a/homeassistant/components/discovery.py +++ b/homeassistant/components/discovery.py @@ -41,6 +41,7 @@ SERVICE_HANDLERS = { 'yeelight': ('light', 'yeelight'), 'flux_led': ('light', 'flux_led'), 'apple_tv': ('media_player', 'apple_tv'), + 'openhome': ('media_player', 'openhome'), } CONFIG_SCHEMA = vol.Schema({ diff --git a/homeassistant/components/media_player/openhome.py b/homeassistant/components/media_player/openhome.py new file mode 100644 index 00000000000..46e8263999b --- /dev/null +++ b/homeassistant/components/media_player/openhome.py @@ -0,0 +1,221 @@ +""" +Support for Openhome Devices. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/media_player.openhome/ +""" +import logging + +from homeassistant.components.media_player import ( + SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, SUPPORT_PREVIOUS_TRACK, SUPPORT_TURN_ON, + SUPPORT_TURN_OFF, SUPPORT_VOLUME_SET, SUPPORT_VOLUME_MUTE, + SUPPORT_VOLUME_STEP, SUPPORT_STOP, SUPPORT_PLAY, SUPPORT_SELECT_SOURCE, + MediaPlayerDevice) +from homeassistant.const import ( + STATE_IDLE, STATE_PAUSED, STATE_PLAYING, STATE_OFF) + +REQUIREMENTS = ['openhomedevice==0.2'] + +SUPPORT_OPENHOME = SUPPORT_SELECT_SOURCE | \ + SUPPORT_VOLUME_STEP | SUPPORT_VOLUME_MUTE | SUPPORT_VOLUME_SET | \ + SUPPORT_TURN_OFF | SUPPORT_TURN_ON + +_LOGGER = logging.getLogger(__name__) + +# List of devices that have been registered +DEVICES = [] + + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup Openhome Platform.""" + from openhomedevice.Device import Device + + if discovery_info: + _LOGGER.info('Openhome device found, (%s)', discovery_info[0]) + device = Device(discovery_info[1]) + + # if device has already been discovered + if device.Uuid() in [x.unique_id for x in DEVICES]: + return True + + device = OpenhomeDevice(hass, device) + + add_devices([device], True) + DEVICES.append(device) + + return True + + return True + + +class OpenhomeDevice(MediaPlayerDevice): + """Representation of an Openhome device.""" + + def __init__(self, hass, device): + """Initialise the Openhome device.""" + self.hass = hass + self._device = device + self._track_information = {} + self._in_standby = None + self._transport_state = None + self._track_information = None + self._volume_level = None + self._volume_muted = None + self._supported_features = SUPPORT_OPENHOME + self._source_names = list() + self._source_index = {} + self._source = {} + self._name = None + self._state = STATE_PLAYING + + def update(self): + """Update state of device.""" + self._in_standby = self._device.IsInStandby() + self._transport_state = self._device.TransportState() + self._track_information = self._device.TrackInfo() + self._volume_level = self._device.VolumeLevel() + self._volume_muted = self._device.IsMuted() + self._source = self._device.Source() + self._name = self._device.Room().decode('utf-8') + self._supported_features = SUPPORT_OPENHOME + source_index = {} + source_names = list() + + for source in self._device.Sources(): + source_names.append(source["name"]) + source_index[source["name"]] = source["index"] + + self._source_index = source_index + self._source_names = source_names + + if self._source["type"] == "Radio": + self._supported_features |= SUPPORT_STOP | SUPPORT_PLAY + if self._source["type"] == "Playlist": + self._supported_features |= SUPPORT_PREVIOUS_TRACK | \ + SUPPORT_NEXT_TRACK | SUPPORT_PAUSE | SUPPORT_PLAY + + if self._in_standby: + self._state = STATE_OFF + elif self._transport_state == 'Paused': + self._state = STATE_PAUSED + elif self._transport_state in ('Playing', 'Buffering'): + self._state = STATE_PLAYING + elif self._transport_state == 'Stopped': + self._state = STATE_IDLE + else: + # Device is playing an external source with no transport controls + self._state = STATE_PLAYING + + def turn_on(self): + """Bring device out of standby.""" + self._device.SetStandby(False) + + def turn_off(self): + """Put device in standby.""" + self._device.SetStandby(True) + + def media_pause(self): + """Send pause command.""" + self._device.Pause() + + def media_stop(self): + """Send stop command.""" + self._device.Stop() + + def media_play(self): + """Send play commmand.""" + self._device.Play() + + def media_next_track(self): + """Send next track command.""" + self._device.Skip(1) + + def media_previous_track(self): + """Send previous track command.""" + self._device.Skip(-1) + + def select_source(self, source): + """Select input source.""" + self._device.SetSource(self._source_index[source]) + + @property + def name(self): + """Return the name of the device.""" + return self._name + + @property + def supported_features(self): + """Flag of features commands that are supported.""" + return self._supported_features + + @property + def should_poll(self): + """Polling needed.""" + return True + + @property + def unique_id(self): + """Return an unique ID.""" + return self._device.Uuid() + + @property + def state(self): + """Return the state of the device.""" + return self._state + + @property + def source_list(self): + """List of available input sources.""" + return self._source_names + + @property + def media_image_url(self): + """Image url of current playing media.""" + return self._track_information["albumArt"] + + @property + def media_artist(self): + """Artist of current playing media, music track only.""" + return self._track_information["artist"] + + @property + def media_album_name(self): + """Album name of current playing media, music track only.""" + return self._track_information["album"] + + @property + def media_title(self): + """Title of current playing media.""" + return self._track_information["title"] + + @property + def source(self): + """Name of the current input source.""" + return self._source["name"] + + @property + def volume_level(self): + """Volume level of the media player (0..1).""" + return self._volume_level / 100.0 + + @property + def is_volume_muted(self): + """Return true if volume is muted.""" + return self._volume_muted + + def volume_up(self): + """Volume up media player.""" + self._device.IncreaseVolume() + + def volume_down(self): + """Volume down media player.""" + self._device.DecreaseVolume() + + def set_volume_level(self, volume): + """Set volume level, range 0..1.""" + self._device.SetVolumeLevel(int(volume * 100)) + + def mute_volume(self, mute): + """Mute (true) or unmute (false) media player.""" + self._device.SetMute(mute) diff --git a/requirements_all.txt b/requirements_all.txt index e95f13fcb62..8462175a933 100755 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -364,6 +364,9 @@ oemthermostat==1.1 # homeassistant.components.sensor.openevse openevsewifi==0.4 +# homeassistant.components.media_player.openhome +openhomedevice==0.2 + # homeassistant.components.switch.orvibo orvibo==1.1.1