mirror of
https://github.com/home-assistant/core.git
synced 2025-07-13 08:17:08 +00:00
Add sonos alarm clock update service (#7521)
* Add sonos alarm clock update service * Add tests and break lines * Fix style errors * Make test work with python<3.6 * Fix last two pylint errors * fix new line to long errors
This commit is contained in:
parent
5c4a21efac
commit
4da91d6a8b
@ -51,6 +51,7 @@ SERVICE_SNAPSHOT = 'sonos_snapshot'
|
|||||||
SERVICE_RESTORE = 'sonos_restore'
|
SERVICE_RESTORE = 'sonos_restore'
|
||||||
SERVICE_SET_TIMER = 'sonos_set_sleep_timer'
|
SERVICE_SET_TIMER = 'sonos_set_sleep_timer'
|
||||||
SERVICE_CLEAR_TIMER = 'sonos_clear_sleep_timer'
|
SERVICE_CLEAR_TIMER = 'sonos_clear_sleep_timer'
|
||||||
|
SERVICE_UPDATE_ALARM = 'sonos_update_alarm'
|
||||||
|
|
||||||
DATA_SONOS = 'sonos'
|
DATA_SONOS = 'sonos'
|
||||||
|
|
||||||
@ -62,6 +63,11 @@ CONF_INTERFACE_ADDR = 'interface_addr'
|
|||||||
|
|
||||||
# Service call validation schemas
|
# Service call validation schemas
|
||||||
ATTR_SLEEP_TIME = 'sleep_time'
|
ATTR_SLEEP_TIME = 'sleep_time'
|
||||||
|
ATTR_ALARM_ID = 'alarm_id'
|
||||||
|
ATTR_VOLUME = 'volume'
|
||||||
|
ATTR_ENABLED = 'enabled'
|
||||||
|
ATTR_INCLUDE_LINKED_ZONES = 'include_linked_zones'
|
||||||
|
ATTR_TIME = 'time'
|
||||||
ATTR_MASTER = 'master'
|
ATTR_MASTER = 'master'
|
||||||
ATTR_WITH_GROUP = 'with_group'
|
ATTR_WITH_GROUP = 'with_group'
|
||||||
|
|
||||||
@ -90,6 +96,14 @@ SONOS_SET_TIMER_SCHEMA = SONOS_SCHEMA.extend({
|
|||||||
vol.All(vol.Coerce(int), vol.Range(min=0, max=86399))
|
vol.All(vol.Coerce(int), vol.Range(min=0, max=86399))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
SONOS_UPDATE_ALARM_SCHEMA = SONOS_SCHEMA.extend({
|
||||||
|
vol.Required(ATTR_ALARM_ID): cv.positive_int,
|
||||||
|
vol.Optional(ATTR_TIME): cv.time,
|
||||||
|
vol.Optional(ATTR_VOLUME): cv.small_float,
|
||||||
|
vol.Optional(ATTR_ENABLED): cv.boolean,
|
||||||
|
vol.Optional(ATTR_INCLUDE_LINKED_ZONES): cv.boolean,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
"""Set up the Sonos platform."""
|
"""Set up the Sonos platform."""
|
||||||
@ -166,6 +180,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
device.set_sleep_timer(service.data[ATTR_SLEEP_TIME])
|
device.set_sleep_timer(service.data[ATTR_SLEEP_TIME])
|
||||||
elif service.service == SERVICE_CLEAR_TIMER:
|
elif service.service == SERVICE_CLEAR_TIMER:
|
||||||
device.clear_sleep_timer()
|
device.clear_sleep_timer()
|
||||||
|
elif service.service == SERVICE_UPDATE_ALARM:
|
||||||
|
device.update_alarm(**service.data)
|
||||||
|
|
||||||
device.schedule_update_ha_state(True)
|
device.schedule_update_ha_state(True)
|
||||||
|
|
||||||
@ -193,6 +209,11 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
DOMAIN, SERVICE_CLEAR_TIMER, service_handle,
|
DOMAIN, SERVICE_CLEAR_TIMER, service_handle,
|
||||||
descriptions.get(SERVICE_CLEAR_TIMER), schema=SONOS_SCHEMA)
|
descriptions.get(SERVICE_CLEAR_TIMER), schema=SONOS_SCHEMA)
|
||||||
|
|
||||||
|
hass.services.register(
|
||||||
|
DOMAIN, SERVICE_UPDATE_ALARM, service_handle,
|
||||||
|
descriptions.get(SERVICE_UPDATE_ALARM),
|
||||||
|
schema=SONOS_UPDATE_ALARM_SCHEMA)
|
||||||
|
|
||||||
|
|
||||||
def _parse_timespan(timespan):
|
def _parse_timespan(timespan):
|
||||||
"""Parse a time-span into number of seconds."""
|
"""Parse a time-span into number of seconds."""
|
||||||
@ -1034,6 +1055,30 @@ class SonosDevice(MediaPlayerDevice):
|
|||||||
"""Clear the timer on the player."""
|
"""Clear the timer on the player."""
|
||||||
self._player.set_sleep_timer(None)
|
self._player.set_sleep_timer(None)
|
||||||
|
|
||||||
|
@soco_error
|
||||||
|
@soco_coordinator
|
||||||
|
def update_alarm(self, **data):
|
||||||
|
"""Set the alarm clock on the player."""
|
||||||
|
from soco import alarms
|
||||||
|
a = None
|
||||||
|
for alarm in alarms.get_alarms(self.soco):
|
||||||
|
# pylint: disable=protected-access
|
||||||
|
if alarm._alarm_id == str(data[ATTR_ALARM_ID]):
|
||||||
|
a = alarm
|
||||||
|
if a is None:
|
||||||
|
_LOGGER.warning("did not find alarm with id %s",
|
||||||
|
data[ATTR_ALARM_ID])
|
||||||
|
return
|
||||||
|
if ATTR_TIME in data:
|
||||||
|
a.start_time = data[ATTR_TIME]
|
||||||
|
if ATTR_VOLUME in data:
|
||||||
|
a.volume = int(data[ATTR_VOLUME] * 100)
|
||||||
|
if ATTR_ENABLED in data:
|
||||||
|
a.enabled = data[ATTR_ENABLED]
|
||||||
|
if ATTR_INCLUDE_LINKED_ZONES in data:
|
||||||
|
a.include_linked_zones = data[ATTR_INCLUDE_LINKED_ZONES]
|
||||||
|
a.save()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_state_attributes(self):
|
def device_state_attributes(self):
|
||||||
"""Return device specific state attributes."""
|
"""Return device specific state attributes."""
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
"""The tests for the Demo Media player platform."""
|
"""The tests for the Demo Media player platform."""
|
||||||
|
import datetime
|
||||||
import socket
|
import socket
|
||||||
import unittest
|
import unittest
|
||||||
import soco.snapshot
|
import soco.snapshot
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
import soco
|
import soco
|
||||||
|
from soco import alarms
|
||||||
|
|
||||||
from homeassistant.setup import setup_component
|
from homeassistant.setup import setup_component
|
||||||
from homeassistant.components.media_player import sonos, DOMAIN
|
from homeassistant.components.media_player import sonos, DOMAIN
|
||||||
@ -307,6 +309,36 @@ class TestSonosMediaPlayer(unittest.TestCase):
|
|||||||
device.set_sleep_timer(None)
|
device.set_sleep_timer(None)
|
||||||
set_sleep_timerMock.assert_called_once_with(None)
|
set_sleep_timerMock.assert_called_once_with(None)
|
||||||
|
|
||||||
|
@mock.patch('soco.SoCo', new=SoCoMock)
|
||||||
|
@mock.patch('soco.alarms.Alarm')
|
||||||
|
@mock.patch('socket.create_connection', side_effect=socket.error())
|
||||||
|
def test_update_alarm(self, soco_mock, alarm_mock, *args):
|
||||||
|
"""Ensuring soco methods called for sonos_set_sleep_timer service."""
|
||||||
|
sonos.setup_platform(self.hass, {}, fake_add_device, {
|
||||||
|
'host': '192.0.2.1'
|
||||||
|
})
|
||||||
|
device = self.hass.data[sonos.DATA_SONOS][-1]
|
||||||
|
device.hass = self.hass
|
||||||
|
alarm1 = alarms.Alarm(soco_mock)
|
||||||
|
alarm1.configure_mock(_alarm_id="1", start_time=None, enabled=False,
|
||||||
|
include_linked_zones=False, volume=100)
|
||||||
|
with mock.patch('soco.alarms.get_alarms', return_value=[alarm1]):
|
||||||
|
attrs = {
|
||||||
|
'time': datetime.time(12, 00),
|
||||||
|
'enabled': True,
|
||||||
|
'include_linked_zones': True,
|
||||||
|
'volume': 0.30,
|
||||||
|
}
|
||||||
|
device.update_alarm(alarm_id=2)
|
||||||
|
alarm1.save.assert_not_called()
|
||||||
|
device.update_alarm(alarm_id=1, **attrs)
|
||||||
|
self.assertEqual(alarm1.enabled, attrs['enabled'])
|
||||||
|
self.assertEqual(alarm1.start_time, attrs['time'])
|
||||||
|
self.assertEqual(alarm1.include_linked_zones,
|
||||||
|
attrs['include_linked_zones'])
|
||||||
|
self.assertEqual(alarm1.volume, 30)
|
||||||
|
alarm1.save.assert_called_once_with()
|
||||||
|
|
||||||
@mock.patch('soco.SoCo', new=SoCoMock)
|
@mock.patch('soco.SoCo', new=SoCoMock)
|
||||||
@mock.patch('socket.create_connection', side_effect=socket.error())
|
@mock.patch('socket.create_connection', side_effect=socket.error())
|
||||||
@mock.patch.object(soco.snapshot.Snapshot, 'snapshot')
|
@mock.patch.object(soco.snapshot.Snapshot, 'snapshot')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user