mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 12:47:08 +00:00
Add data/data_template/title to alert component (#17616)
* Add data/data_template/title to alert component * Fix line length * Fix tests * Fix lint * fix line length * Fix tests, make title templatable * Fix test * Fix test * Optimize data, make title templated * Fix line length * Add title template * typo * Fix tests
This commit is contained in:
parent
3484e506e8
commit
db277ad023
@ -5,19 +5,19 @@ For more details about this component, please refer to the documentation at
|
|||||||
https://home-assistant.io/components/alert/
|
https://home-assistant.io/components/alert/
|
||||||
"""
|
"""
|
||||||
import asyncio
|
import asyncio
|
||||||
from datetime import datetime, timedelta
|
|
||||||
import logging
|
import logging
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.components.notify import (
|
from homeassistant.components.notify import (
|
||||||
ATTR_MESSAGE, DOMAIN as DOMAIN_NOTIFY)
|
ATTR_MESSAGE, ATTR_TITLE, ATTR_DATA, DOMAIN as DOMAIN_NOTIFY)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_ENTITY_ID, STATE_IDLE, CONF_NAME, CONF_STATE, STATE_ON, STATE_OFF,
|
CONF_ENTITY_ID, STATE_IDLE, CONF_NAME, CONF_STATE, STATE_ON, STATE_OFF,
|
||||||
SERVICE_TURN_ON, SERVICE_TURN_OFF, SERVICE_TOGGLE, ATTR_ENTITY_ID)
|
SERVICE_TURN_ON, SERVICE_TURN_OFF, SERVICE_TOGGLE, ATTR_ENTITY_ID)
|
||||||
from homeassistant.helpers.entity import ToggleEntity
|
|
||||||
from homeassistant.helpers import service, event
|
from homeassistant.helpers import service, event
|
||||||
import homeassistant.helpers.config_validation as cv
|
from homeassistant.helpers.entity import ToggleEntity
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -30,6 +30,8 @@ CONF_REPEAT = 'repeat'
|
|||||||
CONF_SKIP_FIRST = 'skip_first'
|
CONF_SKIP_FIRST = 'skip_first'
|
||||||
CONF_ALERT_MESSAGE = 'message'
|
CONF_ALERT_MESSAGE = 'message'
|
||||||
CONF_DONE_MESSAGE = 'done_message'
|
CONF_DONE_MESSAGE = 'done_message'
|
||||||
|
CONF_TITLE = 'title'
|
||||||
|
CONF_DATA = 'data'
|
||||||
|
|
||||||
DEFAULT_CAN_ACK = True
|
DEFAULT_CAN_ACK = True
|
||||||
DEFAULT_SKIP_FIRST = False
|
DEFAULT_SKIP_FIRST = False
|
||||||
@ -43,13 +45,14 @@ ALERT_SCHEMA = vol.Schema({
|
|||||||
vol.Required(CONF_SKIP_FIRST, default=DEFAULT_SKIP_FIRST): cv.boolean,
|
vol.Required(CONF_SKIP_FIRST, default=DEFAULT_SKIP_FIRST): cv.boolean,
|
||||||
vol.Optional(CONF_ALERT_MESSAGE): cv.template,
|
vol.Optional(CONF_ALERT_MESSAGE): cv.template,
|
||||||
vol.Optional(CONF_DONE_MESSAGE): cv.template,
|
vol.Optional(CONF_DONE_MESSAGE): cv.template,
|
||||||
|
vol.Optional(CONF_TITLE): cv.template,
|
||||||
|
vol.Optional(CONF_DATA): dict,
|
||||||
vol.Required(CONF_NOTIFIERS): cv.ensure_list})
|
vol.Required(CONF_NOTIFIERS): cv.ensure_list})
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
DOMAIN: cv.schema_with_slug_keys(ALERT_SCHEMA),
|
DOMAIN: cv.schema_with_slug_keys(ALERT_SCHEMA),
|
||||||
}, extra=vol.ALLOW_EXTRA)
|
}, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
|
|
||||||
ALERT_SERVICE_SCHEMA = vol.Schema({
|
ALERT_SERVICE_SCHEMA = vol.Schema({
|
||||||
vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
|
||||||
})
|
})
|
||||||
@ -77,12 +80,14 @@ async def async_setup(hass, config):
|
|||||||
done_message_template = cfg.get(CONF_DONE_MESSAGE)
|
done_message_template = cfg.get(CONF_DONE_MESSAGE)
|
||||||
notifiers = cfg.get(CONF_NOTIFIERS)
|
notifiers = cfg.get(CONF_NOTIFIERS)
|
||||||
can_ack = cfg.get(CONF_CAN_ACK)
|
can_ack = cfg.get(CONF_CAN_ACK)
|
||||||
|
title_template = cfg.get(CONF_TITLE)
|
||||||
|
data = cfg.get(CONF_DATA)
|
||||||
|
|
||||||
entities.append(Alert(hass, object_id, name,
|
entities.append(Alert(hass, object_id, name,
|
||||||
watched_entity_id, alert_state, repeat,
|
watched_entity_id, alert_state, repeat,
|
||||||
skip_first, message_template,
|
skip_first, message_template,
|
||||||
done_message_template, notifiers,
|
done_message_template, notifiers,
|
||||||
can_ack))
|
can_ack, title_template, data))
|
||||||
|
|
||||||
if not entities:
|
if not entities:
|
||||||
return False
|
return False
|
||||||
@ -127,12 +132,14 @@ class Alert(ToggleEntity):
|
|||||||
|
|
||||||
def __init__(self, hass, entity_id, name, watched_entity_id,
|
def __init__(self, hass, entity_id, name, watched_entity_id,
|
||||||
state, repeat, skip_first, message_template,
|
state, repeat, skip_first, message_template,
|
||||||
done_message_template, notifiers, can_ack):
|
done_message_template, notifiers, can_ack, title_template,
|
||||||
|
data):
|
||||||
"""Initialize the alert."""
|
"""Initialize the alert."""
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self._name = name
|
self._name = name
|
||||||
self._alert_state = state
|
self._alert_state = state
|
||||||
self._skip_first = skip_first
|
self._skip_first = skip_first
|
||||||
|
self._data = data
|
||||||
|
|
||||||
self._message_template = message_template
|
self._message_template = message_template
|
||||||
if self._message_template is not None:
|
if self._message_template is not None:
|
||||||
@ -142,6 +149,10 @@ class Alert(ToggleEntity):
|
|||||||
if self._done_message_template is not None:
|
if self._done_message_template is not None:
|
||||||
self._done_message_template.hass = hass
|
self._done_message_template.hass = hass
|
||||||
|
|
||||||
|
self._title_template = title_template
|
||||||
|
if self._title_template is not None:
|
||||||
|
self._title_template.hass = hass
|
||||||
|
|
||||||
self._notifiers = notifiers
|
self._notifiers = notifiers
|
||||||
self._can_ack = can_ack
|
self._can_ack = can_ack
|
||||||
|
|
||||||
@ -251,9 +262,20 @@ class Alert(ToggleEntity):
|
|||||||
await self._send_notification_message(message)
|
await self._send_notification_message(message)
|
||||||
|
|
||||||
async def _send_notification_message(self, message):
|
async def _send_notification_message(self, message):
|
||||||
|
|
||||||
|
msg_payload = {ATTR_MESSAGE: message}
|
||||||
|
|
||||||
|
if self._title_template is not None:
|
||||||
|
title = self._title_template.async_render()
|
||||||
|
msg_payload.update({ATTR_TITLE: title})
|
||||||
|
if self._data:
|
||||||
|
msg_payload.update({ATTR_DATA: self._data})
|
||||||
|
|
||||||
|
_LOGGER.debug(msg_payload)
|
||||||
|
|
||||||
for target in self._notifiers:
|
for target in self._notifiers:
|
||||||
await self.hass.services.async_call(
|
await self.hass.services.async_call(
|
||||||
DOMAIN_NOTIFY, target, {ATTR_MESSAGE: message})
|
DOMAIN_NOTIFY, target, msg_payload)
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs):
|
async def async_turn_on(self, **kwargs):
|
||||||
"""Async Unacknowledge alert."""
|
"""Async Unacknowledge alert."""
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
"""The tests for the Alert component."""
|
"""The tests for the Alert component."""
|
||||||
|
import unittest
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
import unittest
|
|
||||||
|
|
||||||
from homeassistant.setup import setup_component
|
|
||||||
from homeassistant.core import callback
|
|
||||||
from homeassistant.components.alert import DOMAIN
|
|
||||||
import homeassistant.components.alert as alert
|
import homeassistant.components.alert as alert
|
||||||
import homeassistant.components.notify as notify
|
import homeassistant.components.notify as notify
|
||||||
|
from homeassistant.components.alert import DOMAIN
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID, CONF_ENTITY_ID, STATE_IDLE, CONF_NAME, CONF_STATE,
|
ATTR_ENTITY_ID, CONF_ENTITY_ID, STATE_IDLE, CONF_NAME, CONF_STATE,
|
||||||
SERVICE_TOGGLE, SERVICE_TURN_OFF, SERVICE_TURN_ON, STATE_ON, STATE_OFF)
|
SERVICE_TOGGLE, SERVICE_TURN_OFF, SERVICE_TURN_ON, STATE_ON, STATE_OFF)
|
||||||
|
from homeassistant.core import callback
|
||||||
|
from homeassistant.setup import setup_component
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant
|
||||||
|
|
||||||
NAME = "alert_test"
|
NAME = "alert_test"
|
||||||
@ -19,6 +18,13 @@ DONE_MESSAGE = "alert_gone"
|
|||||||
NOTIFIER = 'test'
|
NOTIFIER = 'test'
|
||||||
TEMPLATE = "{{ states.sensor.test.entity_id }}"
|
TEMPLATE = "{{ states.sensor.test.entity_id }}"
|
||||||
TEST_ENTITY = "sensor.test"
|
TEST_ENTITY = "sensor.test"
|
||||||
|
TITLE = "{{ states.sensor.test.entity_id }}"
|
||||||
|
TEST_TITLE = "sensor.test"
|
||||||
|
TEST_DATA = {
|
||||||
|
'data': {
|
||||||
|
'inline_keyboard': ['Close garage:/close_garage']
|
||||||
|
}
|
||||||
|
}
|
||||||
TEST_CONFIG = \
|
TEST_CONFIG = \
|
||||||
{alert.DOMAIN: {
|
{alert.DOMAIN: {
|
||||||
NAME: {
|
NAME: {
|
||||||
@ -28,10 +34,13 @@ TEST_CONFIG = \
|
|||||||
CONF_STATE: STATE_ON,
|
CONF_STATE: STATE_ON,
|
||||||
alert.CONF_REPEAT: 30,
|
alert.CONF_REPEAT: 30,
|
||||||
alert.CONF_SKIP_FIRST: False,
|
alert.CONF_SKIP_FIRST: False,
|
||||||
alert.CONF_NOTIFIERS: [NOTIFIER]}
|
alert.CONF_NOTIFIERS: [NOTIFIER],
|
||||||
|
alert.CONF_TITLE: TITLE,
|
||||||
|
alert.CONF_DATA: {}
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
TEST_NOACK = [NAME, NAME, "sensor.test",
|
TEST_NOACK = [NAME, NAME, "sensor.test",
|
||||||
STATE_ON, [30], False, None, None, NOTIFIER, False]
|
STATE_ON, [30], False, None, None, NOTIFIER, False, None, None]
|
||||||
ENTITY_ID = alert.ENTITY_ID_FORMAT.format(NAME)
|
ENTITY_ID = alert.ENTITY_ID_FORMAT.format(NAME)
|
||||||
|
|
||||||
|
|
||||||
@ -286,6 +295,34 @@ class TestAlert(unittest.TestCase):
|
|||||||
last_event = events[-1]
|
last_event = events[-1]
|
||||||
self.assertEqual(last_event.data[notify.ATTR_MESSAGE], TEST_ENTITY)
|
self.assertEqual(last_event.data[notify.ATTR_MESSAGE], TEST_ENTITY)
|
||||||
|
|
||||||
|
def test_sending_titled_notification(self):
|
||||||
|
"""Test notifications."""
|
||||||
|
events = self._setup_notify()
|
||||||
|
|
||||||
|
config = deepcopy(TEST_CONFIG)
|
||||||
|
config[alert.DOMAIN][NAME][alert.CONF_TITLE] = TITLE
|
||||||
|
assert setup_component(self.hass, alert.DOMAIN, config)
|
||||||
|
|
||||||
|
self.hass.states.set(TEST_ENTITY, STATE_ON)
|
||||||
|
self.hass.block_till_done()
|
||||||
|
self.assertEqual(1, len(events))
|
||||||
|
last_event = events[-1]
|
||||||
|
self.assertEqual(last_event.data[notify.ATTR_TITLE], TEST_TITLE)
|
||||||
|
|
||||||
|
def test_sending_data_notification(self):
|
||||||
|
"""Test notifications."""
|
||||||
|
events = self._setup_notify()
|
||||||
|
|
||||||
|
config = deepcopy(TEST_CONFIG)
|
||||||
|
config[alert.DOMAIN][NAME][alert.CONF_DATA] = TEST_DATA
|
||||||
|
assert setup_component(self.hass, alert.DOMAIN, config)
|
||||||
|
|
||||||
|
self.hass.states.set(TEST_ENTITY, STATE_ON)
|
||||||
|
self.hass.block_till_done()
|
||||||
|
self.assertEqual(1, len(events))
|
||||||
|
last_event = events[-1]
|
||||||
|
self.assertEqual(last_event.data[notify.ATTR_DATA], TEST_DATA)
|
||||||
|
|
||||||
def test_skipfirst(self):
|
def test_skipfirst(self):
|
||||||
"""Test skipping first notification."""
|
"""Test skipping first notification."""
|
||||||
config = deepcopy(TEST_CONFIG)
|
config = deepcopy(TEST_CONFIG)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user