mirror of
https://github.com/home-assistant/core
synced 2024-10-15 06:15:47 +00:00
Add a group notify platform (#2842)
* Add a group notify platform which allows sending a single notification to multiple platforms. * Correctly sort group.py * Clean up the payload logic * Make name and entity id required in the schema * Deep update the dictionary to fix a bug where data wasnt merging. * Add notify.group tests. * Improve docstrings. * Change entities to services and entity_id to service * Make service a slug without a default value * Update tests for entities->services, entity_id->service * vol.Any(cv.slug) -> cv.slug
This commit is contained in:
parent
c1ce6855c5
commit
848781fbb7
|
@ -173,6 +173,7 @@ omit =
|
|||
homeassistant/components/notify/aws_sqs.py
|
||||
homeassistant/components/notify/free_mobile.py
|
||||
homeassistant/components/notify/gntp.py
|
||||
homeassistant/components/notify/group.py
|
||||
homeassistant/components/notify/instapush.py
|
||||
homeassistant/components/notify/joaoapps_join.py
|
||||
homeassistant/components/notify/message_bird.py
|
||||
|
|
65
homeassistant/components/notify/group.py
Normal file
65
homeassistant/components/notify/group.py
Normal file
|
@ -0,0 +1,65 @@
|
|||
"""
|
||||
Group platform for notify component.
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/notify.group/
|
||||
"""
|
||||
import collections
|
||||
import logging
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import (CONF_PLATFORM, CONF_NAME, ATTR_SERVICE)
|
||||
from homeassistant.components.notify import (DOMAIN, ATTR_MESSAGE, ATTR_DATA,
|
||||
BaseNotificationService)
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_SERVICES = "services"
|
||||
|
||||
PLATFORM_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_PLATFORM): "group",
|
||||
vol.Required(CONF_NAME): vol.Coerce(str),
|
||||
vol.Required(CONF_SERVICES): vol.All(cv.ensure_list, [{
|
||||
vol.Required(ATTR_SERVICE): cv.slug,
|
||||
vol.Optional(ATTR_DATA): dict,
|
||||
}])
|
||||
})
|
||||
|
||||
|
||||
def update(input_dict, update_source):
|
||||
"""Deep update a dictionary."""
|
||||
for key, val in update_source.items():
|
||||
if isinstance(val, collections.Mapping):
|
||||
recurse = update(input_dict.get(key, {}), val)
|
||||
input_dict[key] = recurse
|
||||
else:
|
||||
input_dict[key] = update_source[key]
|
||||
return input_dict
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
"""Get the Group notification service."""
|
||||
return GroupNotifyPlatform(hass, config.get(CONF_SERVICES))
|
||||
|
||||
|
||||
# pylint: disable=too-few-public-methods
|
||||
class GroupNotifyPlatform(BaseNotificationService):
|
||||
"""Implement the notification service for the group notify playform."""
|
||||
|
||||
def __init__(self, hass, entities):
|
||||
"""Initialize the service."""
|
||||
self.hass = hass
|
||||
self.entities = entities
|
||||
|
||||
def send_message(self, message="", **kwargs):
|
||||
"""Send message to all entities in the group."""
|
||||
payload = {ATTR_MESSAGE: message}
|
||||
payload.update({key: val for key, val in kwargs.items() if val})
|
||||
|
||||
for entity in self.entities:
|
||||
sending_payload = payload.copy()
|
||||
if entity.get(ATTR_DATA) is not None:
|
||||
update(sending_payload, entity.get(ATTR_DATA))
|
||||
self.hass.services.call(DOMAIN, entity.get(ATTR_SERVICE),
|
||||
sending_payload)
|
82
tests/components/notify/test_group.py
Normal file
82
tests/components/notify/test_group.py
Normal file
|
@ -0,0 +1,82 @@
|
|||
"""The tests for the notify.group platform."""
|
||||
import unittest
|
||||
|
||||
import homeassistant.components.notify as notify
|
||||
from homeassistant.components.notify import group
|
||||
|
||||
from tests.common import get_test_home_assistant
|
||||
|
||||
|
||||
class TestNotifyGroup(unittest.TestCase):
|
||||
"""Test the notify.group platform."""
|
||||
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
"""Setup things to be run when tests are started."""
|
||||
self.hass = get_test_home_assistant()
|
||||
self.events = []
|
||||
self.assertTrue(notify.setup(self.hass, {
|
||||
'notify': {
|
||||
'name': 'demo1',
|
||||
'platform': 'demo'
|
||||
}
|
||||
}))
|
||||
self.assertTrue(notify.setup(self.hass, {
|
||||
'notify': {
|
||||
'name': 'demo2',
|
||||
'platform': 'demo'
|
||||
}
|
||||
}))
|
||||
|
||||
self.service = group.get_service(self.hass, {'services': [
|
||||
{'service': 'demo1'},
|
||||
{'service': 'demo2',
|
||||
'data': {'target': 'unnamed device',
|
||||
'data': {'test': 'message'}}}]})
|
||||
|
||||
assert self.service is not None
|
||||
|
||||
def record_event(event):
|
||||
"""Record event to send notification."""
|
||||
self.events.append(event)
|
||||
|
||||
self.hass.bus.listen("notify", record_event)
|
||||
|
||||
def tearDown(self): # pylint: disable=invalid-name
|
||||
""""Stop everything that was started."""
|
||||
self.hass.stop()
|
||||
|
||||
def test_send_message_to_group(self):
|
||||
"""Test sending a message to a notify group."""
|
||||
self.service.send_message('Hello', title='Test notification')
|
||||
self.hass.pool.block_till_done()
|
||||
self.assertTrue(len(self.events) == 2)
|
||||
last_event = self.events[-1]
|
||||
self.assertEqual(last_event.data[notify.ATTR_TITLE],
|
||||
'Test notification')
|
||||
self.assertEqual(last_event.data[notify.ATTR_MESSAGE], 'Hello')
|
||||
|
||||
def test_send_message_with_data(self):
|
||||
"""Test sending a message with to a notify group."""
|
||||
notify_data = {'hello': 'world'}
|
||||
self.service.send_message('Hello', title='Test notification',
|
||||
data=notify_data)
|
||||
self.hass.pool.block_till_done()
|
||||
last_event = self.events[-1]
|
||||
self.assertEqual(last_event.data[notify.ATTR_TITLE],
|
||||
'Test notification')
|
||||
self.assertEqual(last_event.data[notify.ATTR_MESSAGE], 'Hello')
|
||||
self.assertEqual(last_event.data[notify.ATTR_DATA], notify_data)
|
||||
|
||||
def test_entity_data_passes_through(self):
|
||||
"""Test sending a message with data to merge to a notify group."""
|
||||
notify_data = {'hello': 'world'}
|
||||
self.service.send_message('Hello', title='Test notification',
|
||||
data=notify_data)
|
||||
self.hass.pool.block_till_done()
|
||||
data = self.events[-1].data
|
||||
assert {
|
||||
'message': 'Hello',
|
||||
'target': 'unnamed device',
|
||||
'title': 'Test notification',
|
||||
'data': {'hello': 'world', 'test': 'message'}
|
||||
} == data
|
Loading…
Reference in a new issue