core/homeassistant/components/notify/__init__.py

188 lines
5.8 KiB
Python
Raw Normal View History

"""Provides functionality to notify people."""
import asyncio
import logging
from functools import partial
from typing import Optional
import voluptuous as vol
from homeassistant.setup import async_prepare_setup_platform
from homeassistant.exceptions import HomeAssistantError
import homeassistant.helpers.config_validation as cv
from homeassistant.const import CONF_NAME, CONF_PLATFORM
from homeassistant.helpers import config_per_platform, discovery
from homeassistant.helpers.typing import HomeAssistantType
from homeassistant.util import slugify
# mypy: allow-untyped-defs, no-check-untyped-defs
_LOGGER = logging.getLogger(__name__)
# Platform specific data
2019-07-31 19:25:30 +00:00
ATTR_DATA = "data"
# Text to notify user of
2019-07-31 19:25:30 +00:00
ATTR_MESSAGE = "message"
# Target of the notification (user, device, etc)
2019-07-31 19:25:30 +00:00
ATTR_TARGET = "target"
# Title of notification
2019-07-31 19:25:30 +00:00
ATTR_TITLE = "title"
ATTR_TITLE_DEFAULT = "Home Assistant"
2019-07-31 19:25:30 +00:00
DOMAIN = "notify"
2019-07-31 19:25:30 +00:00
SERVICE_NOTIFY = "notify"
2019-07-31 19:25:30 +00:00
PLATFORM_SCHEMA = vol.Schema(
{vol.Required(CONF_PLATFORM): cv.string, vol.Optional(CONF_NAME): cv.string},
extra=vol.ALLOW_EXTRA,
)
2019-07-31 19:25:30 +00:00
NOTIFY_SERVICE_SCHEMA = vol.Schema(
{
vol.Required(ATTR_MESSAGE): cv.template,
vol.Optional(ATTR_TITLE): cv.template,
vol.Optional(ATTR_TARGET): vol.All(cv.ensure_list, [cv.string]),
vol.Optional(ATTR_DATA): dict,
}
)
async def async_setup(hass, config):
"""Set up the notify services."""
targets = {}
async def async_setup_platform(p_type, p_config=None, discovery_info=None):
"""Set up a notify platform."""
if p_config is None:
p_config = {}
2019-07-31 19:25:30 +00:00
platform = await async_prepare_setup_platform(hass, config, DOMAIN, p_type)
if platform is None:
_LOGGER.error("Unknown notification service specified")
return
_LOGGER.info("Setting up %s.%s", DOMAIN, p_type)
notify_service = None
try:
2019-07-31 19:25:30 +00:00
if hasattr(platform, "async_get_service"):
notify_service = await platform.async_get_service(
hass, p_config, discovery_info
)
elif hasattr(platform, "get_service"):
notify_service = await hass.async_add_job(
2019-07-31 19:25:30 +00:00
platform.get_service, hass, p_config, discovery_info
)
else:
raise HomeAssistantError("Invalid notify platform.")
if notify_service is None:
Stable and asynchronous KNX library. (#8725) * First draft of XKNX module for Home-Assistant * XKNX does now take path of xknx.yaml as parameter * small fix, telegram_received_callback has different signature * changed method of registering callbacks of devices * removed non async command lines from xknx * telegram_received_cb not needed within HASS module * updated requirements * Configuration if XKNX should connect via Routing or Tunneling * bumping version to 0.6.1 * small fix within xknx plugin * bumped version * XKNX-Switches are now BinarySensors and Logic from Sensor was moved to BinarySensor * renamed Outlet to Switch * pylint * configuration of KNX lights via HASS config, yay! * changed name of attribute * Added configuration for xknx to switch component * added support for sensors within hass configuration * added support for climate within hass configuration * Thermostat -> Climate * added configuration support for binary_sensors * renamed Shutter to Cover * added configuration support for cover * restructured file structure according to HASS requirements * pylint * pylint * pylint * pylint * pylint * pylint * updated version * pylint * pylint * pylint * added setpoint support for climate devices * devices are now in a different module * more asyncio :-) * pydocstyle * pydocstyle * added actions to binary_sensor * allow more than one automation * readded requirement * Modifications suggested by hound * Modifications suggested by hound * Modifications suggested by hound * Modifications suggested by hound * xknx now imported as local import * hound *sigh* * lint * 'fixed' coverage. * next try for getting gen_requirements_all.py working * removed blank line * XKNX 0.7.1 with logging functionality, replaced some print() calls with _LOGGER * updated requirements_all.txt * Fixes issue https://github.com/XKNX/xknx/issues/51 * https://github.com/XKNX/xknx/issues/52 added raw access to KNX bus from HASS component. * bumped version - 0.7.3 contains some bugfixes * bumped version - 0.7.3 contains some bugfixes * setting setpoint within climate device has to be async * bumped version to 0.7.4 * bumped version * https://github.com/XKNX/xknx/issues/48 Adding HVAC support. * pylint suggestions * Made target temperature and set point required attributes * renamed value_type to type within sensor configuration * Issue https://github.com/XKNX/xknx/issues/52 : added filter functionality for not flooding the event bus. * suggestions by pylint * Added notify support for knx platform. * logging error if discovery_info is None. * review suggestions by @armills * line too long * Using discovery_info to notifiy component which devices should be added. * moved XKNX automation to main level. * renamed xknx component to knx. * reverted change within .coveragerc * changed dependency * updated docstrings. * updated version of xknx within requirements_all.txt * moved requirement to correct position * renamed configuration attribute * added @callback-decorator and async_prefix. * added @callback decorator and async_ prefix to register_callbacks functions * fixed typo * pylint suggestions * added angle position and invert_position and invert_angle to cover.knx * typo * bumped version within requirements_all.txt * bumped version * Added support for HVAC controller status
2017-09-07 07:11:55 +00:00
# Platforms can decide not to create a service based
# on discovery data.
if discovery_info is None:
_LOGGER.error(
2019-07-31 19:25:30 +00:00
"Failed to initialize notification service %s", p_type
)
return
except Exception: # pylint: disable=broad-except
2019-07-31 19:25:30 +00:00
_LOGGER.exception("Error setting up platform %s", p_type)
return
notify_service.hass = hass
Stable and asynchronous KNX library. (#8725) * First draft of XKNX module for Home-Assistant * XKNX does now take path of xknx.yaml as parameter * small fix, telegram_received_callback has different signature * changed method of registering callbacks of devices * removed non async command lines from xknx * telegram_received_cb not needed within HASS module * updated requirements * Configuration if XKNX should connect via Routing or Tunneling * bumping version to 0.6.1 * small fix within xknx plugin * bumped version * XKNX-Switches are now BinarySensors and Logic from Sensor was moved to BinarySensor * renamed Outlet to Switch * pylint * configuration of KNX lights via HASS config, yay! * changed name of attribute * Added configuration for xknx to switch component * added support for sensors within hass configuration * added support for climate within hass configuration * Thermostat -> Climate * added configuration support for binary_sensors * renamed Shutter to Cover * added configuration support for cover * restructured file structure according to HASS requirements * pylint * pylint * pylint * pylint * pylint * pylint * updated version * pylint * pylint * pylint * added setpoint support for climate devices * devices are now in a different module * more asyncio :-) * pydocstyle * pydocstyle * added actions to binary_sensor * allow more than one automation * readded requirement * Modifications suggested by hound * Modifications suggested by hound * Modifications suggested by hound * Modifications suggested by hound * xknx now imported as local import * hound *sigh* * lint * 'fixed' coverage. * next try for getting gen_requirements_all.py working * removed blank line * XKNX 0.7.1 with logging functionality, replaced some print() calls with _LOGGER * updated requirements_all.txt * Fixes issue https://github.com/XKNX/xknx/issues/51 * https://github.com/XKNX/xknx/issues/52 added raw access to KNX bus from HASS component. * bumped version - 0.7.3 contains some bugfixes * bumped version - 0.7.3 contains some bugfixes * setting setpoint within climate device has to be async * bumped version to 0.7.4 * bumped version * https://github.com/XKNX/xknx/issues/48 Adding HVAC support. * pylint suggestions * Made target temperature and set point required attributes * renamed value_type to type within sensor configuration * Issue https://github.com/XKNX/xknx/issues/52 : added filter functionality for not flooding the event bus. * suggestions by pylint * Added notify support for knx platform. * logging error if discovery_info is None. * review suggestions by @armills * line too long * Using discovery_info to notifiy component which devices should be added. * moved XKNX automation to main level. * renamed xknx component to knx. * reverted change within .coveragerc * changed dependency * updated docstrings. * updated version of xknx within requirements_all.txt * moved requirement to correct position * renamed configuration attribute * added @callback-decorator and async_prefix. * added @callback decorator and async_ prefix to register_callbacks functions * fixed typo * pylint suggestions * added angle position and invert_position and invert_angle to cover.knx * typo * bumped version within requirements_all.txt * bumped version * Added support for HVAC controller status
2017-09-07 07:11:55 +00:00
if discovery_info is None:
discovery_info = {}
async def async_notify_message(service):
2016-02-23 20:06:50 +00:00
"""Handle sending notification message service calls."""
2016-09-10 14:36:55 +00:00
kwargs = {}
message = service.data[ATTR_MESSAGE]
title = service.data.get(ATTR_TITLE)
2016-09-10 14:36:55 +00:00
if title:
title.hass = hass
kwargs[ATTR_TITLE] = title.async_render()
if targets.get(service.service) is not None:
kwargs[ATTR_TARGET] = [targets[service.service]]
elif service.data.get(ATTR_TARGET) is not None:
kwargs[ATTR_TARGET] = service.data.get(ATTR_TARGET)
2016-09-10 14:36:55 +00:00
message.hass = hass
kwargs[ATTR_MESSAGE] = message.async_render()
kwargs[ATTR_DATA] = service.data.get(ATTR_DATA)
await notify_service.async_send_message(**kwargs)
2019-07-31 19:25:30 +00:00
if hasattr(notify_service, "targets"):
platform_name = (
2019-07-31 19:25:30 +00:00
p_config.get(CONF_NAME) or discovery_info.get(CONF_NAME) or p_type
)
for name, target in notify_service.targets.items():
2019-07-31 19:25:30 +00:00
target_name = slugify("{}_{}".format(platform_name, name))
targets[target_name] = target
hass.services.async_register(
2019-07-31 19:25:30 +00:00
DOMAIN,
target_name,
async_notify_message,
schema=NOTIFY_SERVICE_SCHEMA,
)
platform_name = (
2019-07-31 19:25:30 +00:00
p_config.get(CONF_NAME) or discovery_info.get(CONF_NAME) or SERVICE_NOTIFY
)
platform_name_slug = slugify(platform_name)
hass.services.async_register(
2019-07-31 19:25:30 +00:00
DOMAIN,
platform_name_slug,
async_notify_message,
schema=NOTIFY_SERVICE_SCHEMA,
)
2019-07-31 19:25:30 +00:00
hass.config.components.add("{}.{}".format(DOMAIN, p_type))
return True
2019-07-31 19:25:30 +00:00
setup_tasks = [
async_setup_platform(p_type, p_config)
for p_type, p_config in config_per_platform(config, DOMAIN)
]
if setup_tasks:
await asyncio.wait(setup_tasks)
async def async_platform_discovered(platform, info):
"""Handle for discovered platform."""
await async_setup_platform(platform, discovery_info=info)
discovery.async_listen_platform(hass, DOMAIN, async_platform_discovered)
return True
class BaseNotificationService:
2016-03-08 10:46:32 +00:00
"""An abstract class for notification services."""
hass: Optional[HomeAssistantType] = None
def send_message(self, message, **kwargs):
2016-03-08 10:46:32 +00:00
"""Send a message.
kwargs can contain ATTR_TITLE to specify a title.
"""
raise NotImplementedError()
def async_send_message(self, message, **kwargs):
"""Send a message.
kwargs can contain ATTR_TITLE to specify a title.
This method must be run in the event loop and returns a coroutine.
"""
2019-07-31 19:25:30 +00:00
return self.hass.async_add_job(partial(self.send_message, message, **kwargs))