mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 00:37:53 +00:00
Add discovery notify support and mysensors notify (#5219)
* Add mysensors notify platform * Make add_devices optional in platform callback function. * Use new argument structure for all existing mysensors platforms. * Add notify platform. * Update mysensors gateway. * Refactor notify setup * Enable discovery of notify platforms. * Update and add tests for notify component and some platforms. * Continue setup of notify platforms if a platform fails setup. * Remove notify tests that check platform config. These tests are not needed when config validation is used. * Add config validation to APNS notify platform. * Use discovery to set up mysensors notify platform. * Add discovery_info to get_service and update tests * Add discovery_info as keyword argument to the get_service function signature and update all notify platforms. * Update existing notify tests to check config validation using test helper. * Add removed tests back in that checked config in apns, command_line and file platforms, but use config validation test helper to verify config. * Add a test for notify file to increase coverage. * Fix some PEP issues. * Fix comments and use more constants * Move apns notify service under notify domain
This commit is contained in:
parent
3b9fb6ccf5
commit
9db1aa7629
@ -47,7 +47,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
|
||||
devices = {}
|
||||
gateway.platform_callbacks.append(mysensors.pf_callback_factory(
|
||||
map_sv_types, devices, add_devices, MySensorsBinarySensor))
|
||||
map_sv_types, devices, MySensorsBinarySensor, add_devices))
|
||||
|
||||
|
||||
class MySensorsBinarySensor(
|
||||
|
@ -39,7 +39,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
}
|
||||
devices = {}
|
||||
gateway.platform_callbacks.append(mysensors.pf_callback_factory(
|
||||
map_sv_types, devices, add_devices, MySensorsHVAC))
|
||||
map_sv_types, devices, MySensorsHVAC, add_devices))
|
||||
|
||||
|
||||
class MySensorsHVAC(mysensors.MySensorsDeviceEntity, ClimateDevice):
|
||||
|
@ -35,7 +35,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
})
|
||||
devices = {}
|
||||
gateway.platform_callbacks.append(mysensors.pf_callback_factory(
|
||||
map_sv_types, devices, add_devices, MySensorsCover))
|
||||
map_sv_types, devices, MySensorsCover, add_devices))
|
||||
|
||||
|
||||
class MySensorsCover(mysensors.MySensorsDeviceEntity, CoverDevice):
|
||||
|
@ -58,7 +58,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
})
|
||||
devices = {}
|
||||
gateway.platform_callbacks.append(mysensors.pf_callback_factory(
|
||||
map_sv_types, devices, add_devices, device_class_map))
|
||||
map_sv_types, devices, device_class_map, add_devices))
|
||||
|
||||
|
||||
class MySensorsLight(mysensors.MySensorsDeviceEntity, Light):
|
||||
|
@ -9,10 +9,10 @@ import socket
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.bootstrap import setup_component
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.const import (ATTR_BATTERY_LEVEL, CONF_OPTIMISTIC,
|
||||
EVENT_HOMEASSISTANT_START,
|
||||
from homeassistant.bootstrap import setup_component
|
||||
from homeassistant.const import (ATTR_BATTERY_LEVEL, CONF_NAME,
|
||||
CONF_OPTIMISTIC, EVENT_HOMEASSISTANT_START,
|
||||
EVENT_HOMEASSISTANT_STOP, STATE_OFF, STATE_ON)
|
||||
from homeassistant.helpers import discovery
|
||||
from homeassistant.loader import get_component
|
||||
@ -169,10 +169,13 @@ def setup(hass, config):
|
||||
'cover']:
|
||||
discovery.load_platform(hass, component, DOMAIN, {}, config)
|
||||
|
||||
discovery.load_platform(
|
||||
hass, 'notify', DOMAIN, {CONF_NAME: DOMAIN}, config)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def pf_callback_factory(map_sv_types, devices, add_devices, entity_class):
|
||||
def pf_callback_factory(map_sv_types, devices, entity_class, add_devices=None):
|
||||
"""Return a new callback for the platform."""
|
||||
def mysensors_callback(gateway, node_id):
|
||||
"""Callback for mysensors platform."""
|
||||
@ -187,7 +190,10 @@ def pf_callback_factory(map_sv_types, devices, add_devices, entity_class):
|
||||
value_type not in map_sv_types[child.type]:
|
||||
continue
|
||||
if key in devices:
|
||||
devices[key].update_ha_state(True)
|
||||
if add_devices:
|
||||
devices[key].schedule_update_ha_state(True)
|
||||
else:
|
||||
devices[key].update()
|
||||
continue
|
||||
name = '{} {} {}'.format(
|
||||
gateway.sensors[node_id].sketch_name, node_id, child.id)
|
||||
@ -197,11 +203,12 @@ def pf_callback_factory(map_sv_types, devices, add_devices, entity_class):
|
||||
device_class = entity_class
|
||||
devices[key] = device_class(
|
||||
gateway, node_id, child.id, name, value_type, child.type)
|
||||
|
||||
_LOGGER.info('Adding new devices: %s', devices[key])
|
||||
add_devices([devices[key]])
|
||||
if key in devices:
|
||||
devices[key].update_ha_state(True)
|
||||
if add_devices:
|
||||
_LOGGER.info('Adding new devices: %s', devices[key])
|
||||
add_devices([devices[key]])
|
||||
devices[key].schedule_update_ha_state(True)
|
||||
else:
|
||||
devices[key].update()
|
||||
return mysensors_callback
|
||||
|
||||
|
||||
|
@ -14,7 +14,7 @@ import homeassistant.bootstrap as bootstrap
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.config import load_yaml_config_file
|
||||
from homeassistant.const import CONF_NAME, CONF_PLATFORM
|
||||
from homeassistant.helpers import config_per_platform
|
||||
from homeassistant.helpers import config_per_platform, discovery
|
||||
from homeassistant.util import slugify
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -66,27 +66,32 @@ def send_message(hass, message, title=None, data=None):
|
||||
|
||||
def setup(hass, config):
|
||||
"""Setup the notify services."""
|
||||
success = False
|
||||
|
||||
descriptions = load_yaml_config_file(
|
||||
os.path.join(os.path.dirname(__file__), 'services.yaml'))
|
||||
|
||||
targets = {}
|
||||
|
||||
for platform, p_config in config_per_platform(config, DOMAIN):
|
||||
def setup_notify_platform(platform, p_config=None, discovery_info=None):
|
||||
"""Set up a notify platform."""
|
||||
if p_config is None:
|
||||
p_config = {}
|
||||
if discovery_info is None:
|
||||
discovery_info = {}
|
||||
|
||||
notify_implementation = bootstrap.prepare_setup_platform(
|
||||
hass, config, DOMAIN, platform)
|
||||
|
||||
if notify_implementation is None:
|
||||
_LOGGER.error("Unknown notification service specified")
|
||||
continue
|
||||
return False
|
||||
|
||||
notify_service = notify_implementation.get_service(hass, p_config)
|
||||
notify_service = notify_implementation.get_service(
|
||||
hass, p_config, discovery_info)
|
||||
|
||||
if notify_service is None:
|
||||
_LOGGER.error("Failed to initialize notification service %s",
|
||||
platform)
|
||||
continue
|
||||
return False
|
||||
|
||||
def notify_message(notify_service, call):
|
||||
"""Handle sending notification message service calls."""
|
||||
@ -112,7 +117,9 @@ def setup(hass, config):
|
||||
service_call_handler = partial(notify_message, notify_service)
|
||||
|
||||
if hasattr(notify_service, 'targets'):
|
||||
platform_name = (p_config.get(CONF_NAME) or platform)
|
||||
platform_name = (
|
||||
p_config.get(CONF_NAME) or discovery_info.get(CONF_NAME) or
|
||||
platform)
|
||||
for name, target in notify_service.targets.items():
|
||||
target_name = slugify('{}_{}'.format(platform_name, name))
|
||||
targets[target_name] = target
|
||||
@ -121,15 +128,29 @@ def setup(hass, config):
|
||||
descriptions.get(SERVICE_NOTIFY),
|
||||
schema=NOTIFY_SERVICE_SCHEMA)
|
||||
|
||||
platform_name = (p_config.get(CONF_NAME) or SERVICE_NOTIFY)
|
||||
platform_name = (
|
||||
p_config.get(CONF_NAME) or discovery_info.get(CONF_NAME) or
|
||||
SERVICE_NOTIFY)
|
||||
platform_name_slug = slugify(platform_name)
|
||||
|
||||
hass.services.register(
|
||||
DOMAIN, platform_name_slug, service_call_handler,
|
||||
descriptions.get(SERVICE_NOTIFY), schema=NOTIFY_SERVICE_SCHEMA)
|
||||
success = True
|
||||
|
||||
return success
|
||||
return True
|
||||
|
||||
for platform, p_config in config_per_platform(config, DOMAIN):
|
||||
if not setup_notify_platform(platform, p_config):
|
||||
_LOGGER.error("Failed to set up platform %s", platform)
|
||||
continue
|
||||
|
||||
def platform_discovered(platform, info):
|
||||
"""Callback to load a platform."""
|
||||
setup_notify_platform(platform, discovery_info=info)
|
||||
|
||||
discovery.listen_platform(hass, DOMAIN, platform_discovered)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class BaseNotificationService(object):
|
||||
|
@ -11,18 +11,29 @@ import voluptuous as vol
|
||||
from homeassistant.helpers.event import track_state_change
|
||||
from homeassistant.config import load_yaml_config_file
|
||||
from homeassistant.components.notify import (
|
||||
ATTR_TARGET, ATTR_DATA, BaseNotificationService)
|
||||
ATTR_TARGET, ATTR_DATA, BaseNotificationService, DOMAIN)
|
||||
from homeassistant.const import CONF_NAME, CONF_PLATFORM
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers import template as template_helper
|
||||
|
||||
DOMAIN = "apns"
|
||||
APNS_DEVICES = "apns.yaml"
|
||||
CONF_CERTFILE = "cert_file"
|
||||
CONF_TOPIC = "topic"
|
||||
CONF_SANDBOX = "sandbox"
|
||||
DEVICE_TRACKER_DOMAIN = "device_tracker"
|
||||
SERVICE_REGISTER = "apns_register"
|
||||
|
||||
ATTR_PUSH_ID = "push_id"
|
||||
ATTR_NAME = "name"
|
||||
|
||||
PLATFORM_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_PLATFORM): 'apns',
|
||||
vol.Required(CONF_NAME): cv.string,
|
||||
vol.Required(CONF_CERTFILE): cv.isfile,
|
||||
vol.Required(CONF_TOPIC): cv.string,
|
||||
vol.Optional(CONF_SANDBOX, default=False): cv.boolean,
|
||||
})
|
||||
|
||||
REGISTER_SERVICE_SCHEMA = vol.Schema({
|
||||
vol.Required(ATTR_PUSH_ID): cv.string,
|
||||
vol.Optional(ATTR_NAME, default=None): cv.string,
|
||||
@ -31,31 +42,19 @@ REGISTER_SERVICE_SCHEMA = vol.Schema({
|
||||
REQUIREMENTS = ["apns2==0.1.1"]
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Return push service."""
|
||||
descriptions = load_yaml_config_file(
|
||||
os.path.join(os.path.dirname(__file__), 'services.yaml'))
|
||||
|
||||
name = config.get("name")
|
||||
if name is None:
|
||||
logging.error("Name must be specified.")
|
||||
return None
|
||||
|
||||
cert_file = config.get('cert_file')
|
||||
if cert_file is None:
|
||||
logging.error("Certificate must be specified.")
|
||||
return None
|
||||
|
||||
topic = config.get('topic')
|
||||
if topic is None:
|
||||
logging.error("Topic must be specified.")
|
||||
return None
|
||||
|
||||
sandbox = bool(config.get('sandbox', False))
|
||||
name = config.get(CONF_NAME)
|
||||
cert_file = config.get(CONF_CERTFILE)
|
||||
topic = config.get(CONF_TOPIC)
|
||||
sandbox = config.get(CONF_SANDBOX)
|
||||
|
||||
service = ApnsNotificationService(hass, name, topic, sandbox, cert_file)
|
||||
hass.services.register(DOMAIN,
|
||||
name,
|
||||
'apns_{}'.format(name),
|
||||
service.register,
|
||||
descriptions.get(SERVICE_REGISTER),
|
||||
schema=REGISTER_SERVICE_SCHEMA)
|
||||
@ -202,8 +201,6 @@ class ApnsNotificationService(BaseNotificationService):
|
||||
def register(self, call):
|
||||
"""Register a device to receive push messages."""
|
||||
push_id = call.data.get(ATTR_PUSH_ID)
|
||||
if push_id is None:
|
||||
return False
|
||||
|
||||
device_name = call.data.get(ATTR_NAME)
|
||||
current_device = self.devices.get(push_id)
|
||||
|
@ -35,7 +35,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the AWS Lambda notification service."""
|
||||
context_str = json.dumps({'hass': hass.config.as_dict(),
|
||||
'custom': config[CONF_CONTEXT]})
|
||||
|
@ -33,7 +33,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the AWS SNS notification service."""
|
||||
# pylint: disable=import-error
|
||||
import boto3
|
||||
|
@ -32,7 +32,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the AWS SQS notification service."""
|
||||
# pylint: disable=import-error
|
||||
import boto3
|
||||
|
@ -22,7 +22,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the Command Line notification service."""
|
||||
command = config[CONF_COMMAND]
|
||||
|
||||
|
@ -9,7 +9,7 @@ from homeassistant.components.notify import BaseNotificationService
|
||||
EVENT_NOTIFY = "notify"
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the demo notification service."""
|
||||
return DemoNotificationService(hass)
|
||||
|
||||
|
@ -24,7 +24,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the Ecobee notification service."""
|
||||
index = config.get(CONF_INDEX)
|
||||
return EcobeeNotificationService(index)
|
||||
|
@ -25,7 +25,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the file notification service."""
|
||||
filename = config[CONF_FILENAME]
|
||||
timestamp = config[CONF_TIMESTAMP]
|
||||
|
@ -23,7 +23,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the Free Mobile SMS notification service."""
|
||||
return FreeSMSNotificationService(config[CONF_USERNAME],
|
||||
config[CONF_ACCESS_TOKEN])
|
||||
|
@ -39,7 +39,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the GNTP notification service."""
|
||||
if config.get(CONF_APP_ICON) is None:
|
||||
icon_file = os.path.join(os.path.dirname(__file__), "..", "frontend",
|
||||
|
@ -38,13 +38,13 @@ def update(input_dict, update_source):
|
||||
return input_dict
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the Group notification service."""
|
||||
return GroupNotifyPlatform(hass, config.get(CONF_SERVICES))
|
||||
|
||||
|
||||
class GroupNotifyPlatform(BaseNotificationService):
|
||||
"""Implement the notification service for the group notify playform."""
|
||||
"""Implement the notification service for the group notify platform."""
|
||||
|
||||
def __init__(self, hass, entities):
|
||||
"""Initialize the service."""
|
||||
|
@ -97,7 +97,7 @@ HTML5_SHOWNOTIFICATION_PARAMETERS = ('actions', 'badge', 'body', 'dir',
|
||||
'vibrate')
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the HTML5 push notification service."""
|
||||
json_path = hass.config.path(REGISTRATIONS_FILE)
|
||||
|
||||
|
@ -32,7 +32,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the Instapush notification service."""
|
||||
headers = {'x-instapush-appid': config[CONF_API_KEY],
|
||||
'x-instapush-appsecret': config[CONF_APP_SECRET]}
|
||||
|
@ -39,7 +39,7 @@ def log_rate_limits(target, resp, level=20):
|
||||
str(resetsAtTime).split(".")[0])
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the iOS notification service."""
|
||||
if "notify.ios" not in hass.config.components:
|
||||
# Need this to enable requirements checking in the app.
|
||||
|
@ -27,7 +27,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
|
||||
|
||||
# pylint: disable=unused-variable
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the Join notification service."""
|
||||
device_id = config.get(CONF_DEVICE_ID)
|
||||
api_key = config.get(CONF_API_KEY)
|
||||
|
@ -29,7 +29,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
ATTR_DISPLAYTIME = 'displaytime'
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Return the notify service."""
|
||||
url = '{}:{}'.format(config.get(CONF_HOST), config.get(CONF_PORT))
|
||||
|
||||
|
@ -20,13 +20,13 @@ CONF_DEVICE = 'device'
|
||||
_RESOURCE = 'https://llamalab.com/automate/cloud/message'
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_API_KEY): cv.string,
|
||||
vol.Required(CONF_TO): cv.string,
|
||||
vol.Optional(CONF_DEVICE): cv.string,
|
||||
vol.Required(CONF_API_KEY): cv.string,
|
||||
vol.Required(CONF_TO): cv.string,
|
||||
vol.Optional(CONF_DEVICE): cv.string,
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the LlamaLab Automate notification service."""
|
||||
secret = config.get(CONF_API_KEY)
|
||||
recipient = config.get(CONF_TO)
|
||||
|
@ -34,7 +34,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the Matrix notification service."""
|
||||
if not AUTH_TOKENS:
|
||||
load_token(hass.config.path(SESSION_FILE))
|
||||
|
@ -25,7 +25,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the MessageBird notification service."""
|
||||
import messagebird
|
||||
|
||||
|
65
homeassistant/components/notify/mysensors.py
Normal file
65
homeassistant/components/notify/mysensors.py
Normal file
@ -0,0 +1,65 @@
|
||||
"""
|
||||
MySensors notification service.
|
||||
|
||||
For more details about this platform, please refer to the documentation
|
||||
https://home-assistant.io/components/notify.mysensors/
|
||||
"""
|
||||
from homeassistant.components import mysensors
|
||||
from homeassistant.components.notify import (ATTR_TARGET,
|
||||
BaseNotificationService)
|
||||
|
||||
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the MySensors notification service."""
|
||||
if discovery_info is None:
|
||||
return
|
||||
platform_devices = []
|
||||
gateways = hass.data.get(mysensors.MYSENSORS_GATEWAYS)
|
||||
if not gateways:
|
||||
return
|
||||
|
||||
for gateway in gateways:
|
||||
pres = gateway.const.Presentation
|
||||
set_req = gateway.const.SetReq
|
||||
map_sv_types = {
|
||||
pres.S_INFO: [set_req.V_TEXT],
|
||||
}
|
||||
devices = {}
|
||||
gateway.platform_callbacks.append(mysensors.pf_callback_factory(
|
||||
map_sv_types, devices, MySensorsNotificationDevice))
|
||||
platform_devices.append(devices)
|
||||
|
||||
return MySensorsNotificationService(platform_devices)
|
||||
|
||||
|
||||
class MySensorsNotificationDevice(mysensors.MySensorsDeviceEntity):
|
||||
"""Represent a MySensors Notification device."""
|
||||
|
||||
def send_msg(self, msg):
|
||||
"""Send a message."""
|
||||
for sub_msg in [msg[i:i + 25] for i in range(0, len(msg), 25)]:
|
||||
# Max mysensors payload is 25 bytes.
|
||||
self.gateway.set_child_value(
|
||||
self.node_id, self.child_id, self.value_type, sub_msg)
|
||||
|
||||
|
||||
class MySensorsNotificationService(BaseNotificationService):
|
||||
"""Implement MySensors notification service."""
|
||||
|
||||
# pylint: disable=too-few-public-methods
|
||||
|
||||
def __init__(self, platform_devices):
|
||||
"""Initialize the service."""
|
||||
self.platform_devices = platform_devices
|
||||
|
||||
def send_message(self, message="", **kwargs):
|
||||
"""Send a message to a user."""
|
||||
target_devices = kwargs.get(ATTR_TARGET)
|
||||
devices = []
|
||||
for gw_devs in self.platform_devices:
|
||||
for device in gw_devs.values():
|
||||
if target_devices is None or device.name in target_devices:
|
||||
devices.append(device)
|
||||
|
||||
for device in devices:
|
||||
device.send_msg(message)
|
@ -83,7 +83,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the Notifications for Android TV notification service."""
|
||||
remoteip = config.get(CONF_IP)
|
||||
duration = config.get(CONF_DURATION)
|
||||
|
@ -24,7 +24,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the NMA notification service."""
|
||||
parameters = {
|
||||
'apikey': config[CONF_API_KEY],
|
||||
|
@ -25,7 +25,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the PushBullet notification service."""
|
||||
from pushbullet import PushBullet
|
||||
from pushbullet import InvalidKeyError
|
||||
|
@ -27,7 +27,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the Pushetta notification service."""
|
||||
pushetta_service = PushettaNotificationService(config[CONF_API_KEY],
|
||||
config[CONF_CHANNEL_NAME],
|
||||
|
@ -27,7 +27,7 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
||||
|
||||
|
||||
# pylint: disable=unused-variable
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the Pushover notification service."""
|
||||
from pushover import InitError
|
||||
|
||||
|
@ -39,7 +39,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the RESTful notification service."""
|
||||
resource = config.get(CONF_RESOURCE)
|
||||
method = config.get(CONF_METHOD)
|
||||
|
@ -25,7 +25,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the SendGrid notification service."""
|
||||
api_key = config.get(CONF_API_KEY)
|
||||
sender = config.get(CONF_SENDER)
|
||||
|
@ -25,7 +25,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the Simplepush notification service."""
|
||||
return SimplePushNotificationService(config.get(CONF_DEVICE_KEY))
|
||||
|
||||
|
@ -29,7 +29,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
|
||||
|
||||
# pylint: disable=unused-variable
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the Slack notification service."""
|
||||
import slacker
|
||||
|
||||
|
@ -47,7 +47,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the mail notification service."""
|
||||
mail_service = MailNotificationService(
|
||||
config.get(CONF_SERVER),
|
||||
|
@ -67,7 +67,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the syslog notification service."""
|
||||
import syslog
|
||||
|
||||
|
@ -37,7 +37,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the Telegram notification service."""
|
||||
import telegram
|
||||
|
||||
|
@ -27,7 +27,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the Telstra SMS API notification service."""
|
||||
consumer_key = config.get(CONF_CONSUMER_KEY)
|
||||
consumer_secret = config.get(CONF_CONSUMER_SECRET)
|
||||
|
@ -28,7 +28,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the Twilio SMS notification service."""
|
||||
# pylint: disable=import-error
|
||||
from twilio.rest import TwilioRestClient
|
||||
|
@ -29,7 +29,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the Twitter notification service."""
|
||||
return TwitterNotificationService(
|
||||
config[CONF_CONSUMER_KEY], config[CONF_CONSUMER_SECRET],
|
||||
|
@ -24,7 +24,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Return the notify service."""
|
||||
from pylgtv import WebOsClient
|
||||
from pylgtv import PyLGTVPairException
|
||||
|
@ -30,7 +30,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
})
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
def get_service(hass, config, discovery_info=None):
|
||||
"""Get the Jabber (XMPP) notification service."""
|
||||
return XmppNotificationService(
|
||||
config.get('sender'),
|
||||
|
@ -83,7 +83,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
|
||||
devices = {}
|
||||
gateway.platform_callbacks.append(mysensors.pf_callback_factory(
|
||||
map_sv_types, devices, add_devices, MySensorsSensor))
|
||||
map_sv_types, devices, MySensorsSensor, add_devices))
|
||||
|
||||
|
||||
class MySensorsSensor(mysensors.MySensorsDeviceEntity, Entity):
|
||||
|
@ -89,7 +89,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
|
||||
devices = {}
|
||||
gateway.platform_callbacks.append(mysensors.pf_callback_factory(
|
||||
map_sv_types, devices, add_devices, device_class_map))
|
||||
map_sv_types, devices, device_class_map, add_devices))
|
||||
platform_devices.append(devices)
|
||||
|
||||
def send_ir_code_service(service):
|
||||
|
@ -399,7 +399,7 @@ def assert_setup_component(count, domain=None):
|
||||
|
||||
Use as a context manager aroung bootstrap.setup_component
|
||||
with assert_setup_component(0) as result_config:
|
||||
setup_component(hass, start_config, domain)
|
||||
setup_component(hass, domain, start_config)
|
||||
# using result_config is optional
|
||||
"""
|
||||
config = {}
|
||||
|
@ -1,14 +1,26 @@
|
||||
"""The tests for the APNS component."""
|
||||
import unittest
|
||||
import os
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import Mock
|
||||
|
||||
from apns2.errors import Unregistered
|
||||
|
||||
import homeassistant.components.notify as notify
|
||||
from homeassistant.core import State
|
||||
from homeassistant.bootstrap import setup_component
|
||||
from homeassistant.components.notify.apns import ApnsNotificationService
|
||||
from tests.common import get_test_home_assistant
|
||||
from homeassistant.config import load_yaml_config_file
|
||||
from unittest.mock import patch
|
||||
from apns2.errors import Unregistered
|
||||
from homeassistant.core import State
|
||||
from tests.common import assert_setup_component, get_test_home_assistant
|
||||
|
||||
CONFIG = {
|
||||
notify.DOMAIN: {
|
||||
'platform': 'apns',
|
||||
'name': 'test_app',
|
||||
'topic': 'testapp.appname',
|
||||
'cert_file': 'test_app.pem'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TestApns(unittest.TestCase):
|
||||
@ -22,6 +34,13 @@ class TestApns(unittest.TestCase):
|
||||
"""Stop everything that was started."""
|
||||
self.hass.stop()
|
||||
|
||||
@patch('os.path.isfile', Mock(return_value=True))
|
||||
@patch('os.access', Mock(return_value=True))
|
||||
def _setup_notify(self):
|
||||
with assert_setup_component(1) as handle_config:
|
||||
assert setup_component(self.hass, notify.DOMAIN, CONFIG)
|
||||
assert handle_config[notify.DOMAIN]
|
||||
|
||||
def test_apns_setup_full(self):
|
||||
"""Test setup with all data."""
|
||||
config = {
|
||||
@ -41,53 +60,49 @@ class TestApns(unittest.TestCase):
|
||||
config = {
|
||||
'notify': {
|
||||
'platform': 'apns',
|
||||
'sandbox': 'True',
|
||||
'topic': 'testapp.appname',
|
||||
'cert_file': 'test_app.pem'
|
||||
'cert_file': 'test_app.pem',
|
||||
}
|
||||
}
|
||||
self.assertFalse(notify.setup(self.hass, config))
|
||||
with assert_setup_component(0) as handle_config:
|
||||
assert setup_component(self.hass, notify.DOMAIN, config)
|
||||
assert not handle_config[notify.DOMAIN]
|
||||
|
||||
def test_apns_setup_missing_certificate(self):
|
||||
"""Test setup with missing name."""
|
||||
"""Test setup with missing certificate."""
|
||||
config = {
|
||||
'notify': {
|
||||
'platform': 'apns',
|
||||
'name': 'test_app',
|
||||
'topic': 'testapp.appname',
|
||||
'name': 'test_app'
|
||||
}
|
||||
}
|
||||
self.assertFalse(notify.setup(self.hass, config))
|
||||
with assert_setup_component(0) as handle_config:
|
||||
assert setup_component(self.hass, notify.DOMAIN, config)
|
||||
assert not handle_config[notify.DOMAIN]
|
||||
|
||||
def test_apns_setup_missing_topic(self):
|
||||
"""Test setup with missing topic."""
|
||||
config = {
|
||||
'notify': {
|
||||
'platform': 'apns',
|
||||
'name': 'test_app',
|
||||
'cert_file': 'test_app.pem',
|
||||
'name': 'test_app'
|
||||
}
|
||||
}
|
||||
self.assertFalse(notify.setup(self.hass, config))
|
||||
with assert_setup_component(0) as handle_config:
|
||||
assert setup_component(self.hass, notify.DOMAIN, config)
|
||||
assert not handle_config[notify.DOMAIN]
|
||||
|
||||
def test_register_new_device(self):
|
||||
"""Test registering a new device with a name."""
|
||||
config = {
|
||||
'notify': {
|
||||
'platform': 'apns',
|
||||
'name': 'test_app',
|
||||
'topic': 'testapp.appname',
|
||||
'cert_file': 'test_app.pem'
|
||||
}
|
||||
}
|
||||
|
||||
devices_path = self.hass.config.path('test_app_apns.yaml')
|
||||
with open(devices_path, 'w+') as out:
|
||||
out.write('5678: {name: test device 2}\n')
|
||||
|
||||
notify.setup(self.hass, config)
|
||||
self.assertTrue(self.hass.services.call('apns',
|
||||
'test_app',
|
||||
self._setup_notify()
|
||||
self.assertTrue(self.hass.services.call(notify.DOMAIN,
|
||||
'apns_test_app',
|
||||
{'push_id': '1234',
|
||||
'name': 'test device'},
|
||||
blocking=True))
|
||||
@ -107,21 +122,12 @@ class TestApns(unittest.TestCase):
|
||||
|
||||
def test_register_device_without_name(self):
|
||||
"""Test registering a without a name."""
|
||||
config = {
|
||||
'notify': {
|
||||
'platform': 'apns',
|
||||
'name': 'test_app',
|
||||
'topic': 'testapp.appname',
|
||||
'cert_file': 'test_app.pem'
|
||||
}
|
||||
}
|
||||
|
||||
devices_path = self.hass.config.path('test_app_apns.yaml')
|
||||
with open(devices_path, 'w+') as out:
|
||||
out.write('5678: {name: test device 2}\n')
|
||||
|
||||
notify.setup(self.hass, config)
|
||||
self.assertTrue(self.hass.services.call('apns', 'test_app',
|
||||
self._setup_notify()
|
||||
self.assertTrue(self.hass.services.call(notify.DOMAIN, 'apns_test_app',
|
||||
{'push_id': '1234'},
|
||||
blocking=True))
|
||||
|
||||
@ -137,23 +143,14 @@ class TestApns(unittest.TestCase):
|
||||
|
||||
def test_update_existing_device(self):
|
||||
"""Test updating an existing device."""
|
||||
config = {
|
||||
'notify': {
|
||||
'platform': 'apns',
|
||||
'name': 'test_app',
|
||||
'topic': 'testapp.appname',
|
||||
'cert_file': 'test_app.pem'
|
||||
}
|
||||
}
|
||||
|
||||
devices_path = self.hass.config.path('test_app_apns.yaml')
|
||||
with open(devices_path, 'w+') as out:
|
||||
out.write('1234: {name: test device 1}\n')
|
||||
out.write('5678: {name: test device 2}\n')
|
||||
|
||||
notify.setup(self.hass, config)
|
||||
self.assertTrue(self.hass.services.call('apns',
|
||||
'test_app',
|
||||
self._setup_notify()
|
||||
self.assertTrue(self.hass.services.call(notify.DOMAIN,
|
||||
'apns_test_app',
|
||||
{'push_id': '1234',
|
||||
'name': 'updated device 1'},
|
||||
blocking=True))
|
||||
@ -173,15 +170,6 @@ class TestApns(unittest.TestCase):
|
||||
|
||||
def test_update_existing_device_with_tracking_id(self):
|
||||
"""Test updating an existing device that has a tracking id."""
|
||||
config = {
|
||||
'notify': {
|
||||
'platform': 'apns',
|
||||
'name': 'test_app',
|
||||
'topic': 'testapp.appname',
|
||||
'cert_file': 'test_app.pem'
|
||||
}
|
||||
}
|
||||
|
||||
devices_path = self.hass.config.path('test_app_apns.yaml')
|
||||
with open(devices_path, 'w+') as out:
|
||||
out.write('1234: {name: test device 1, '
|
||||
@ -189,9 +177,9 @@ class TestApns(unittest.TestCase):
|
||||
out.write('5678: {name: test device 2, '
|
||||
'tracking_device_id: tracking456}\n')
|
||||
|
||||
notify.setup(self.hass, config)
|
||||
self.assertTrue(self.hass.services.call('apns',
|
||||
'test_app',
|
||||
self._setup_notify()
|
||||
self.assertTrue(self.hass.services.call(notify.DOMAIN,
|
||||
'apns_test_app',
|
||||
{'push_id': '1234',
|
||||
'name': 'updated device 1'},
|
||||
blocking=True))
|
||||
@ -216,30 +204,20 @@ class TestApns(unittest.TestCase):
|
||||
def test_send(self, mock_client):
|
||||
"""Test updating an existing device."""
|
||||
send = mock_client.return_value.send_notification
|
||||
config = {
|
||||
'notify': {
|
||||
'platform': 'apns',
|
||||
'name': 'test_app',
|
||||
'topic': 'testapp.appname',
|
||||
'cert_file': 'test_app.pem'
|
||||
}
|
||||
}
|
||||
|
||||
devices_path = self.hass.config.path('test_app_apns.yaml')
|
||||
with open(devices_path, 'w+') as out:
|
||||
out.write('1234: {name: test device 1}\n')
|
||||
|
||||
notify.setup(self.hass, config)
|
||||
self._setup_notify()
|
||||
|
||||
self.assertTrue(self.hass.services.call('notify', 'test_app',
|
||||
{'message': 'Hello',
|
||||
'data': {
|
||||
'badge': 1,
|
||||
'sound': 'test.mp3',
|
||||
'category': 'testing'
|
||||
}
|
||||
},
|
||||
blocking=True))
|
||||
self.assertTrue(self.hass.services.call(
|
||||
'notify', 'test_app',
|
||||
{'message': 'Hello', 'data': {
|
||||
'badge': 1,
|
||||
'sound': 'test.mp3',
|
||||
'category': 'testing'}},
|
||||
blocking=True))
|
||||
|
||||
self.assertTrue(send.called)
|
||||
self.assertEqual(1, len(send.mock_calls))
|
||||
@ -257,30 +235,20 @@ class TestApns(unittest.TestCase):
|
||||
def test_send_when_disabled(self, mock_client):
|
||||
"""Test updating an existing device."""
|
||||
send = mock_client.return_value.send_notification
|
||||
config = {
|
||||
'notify': {
|
||||
'platform': 'apns',
|
||||
'name': 'test_app',
|
||||
'topic': 'testapp.appname',
|
||||
'cert_file': 'test_app.pem'
|
||||
}
|
||||
}
|
||||
|
||||
devices_path = self.hass.config.path('test_app_apns.yaml')
|
||||
with open(devices_path, 'w+') as out:
|
||||
out.write('1234: {name: test device 1, disabled: True}\n')
|
||||
|
||||
notify.setup(self.hass, config)
|
||||
self._setup_notify()
|
||||
|
||||
self.assertTrue(self.hass.services.call('notify', 'test_app',
|
||||
{'message': 'Hello',
|
||||
'data': {
|
||||
'badge': 1,
|
||||
'sound': 'test.mp3',
|
||||
'category': 'testing'
|
||||
}
|
||||
},
|
||||
blocking=True))
|
||||
self.assertTrue(self.hass.services.call(
|
||||
'notify', 'test_app',
|
||||
{'message': 'Hello', 'data': {
|
||||
'badge': 1,
|
||||
'sound': 'test.mp3',
|
||||
'category': 'testing'}},
|
||||
blocking=True))
|
||||
|
||||
self.assertFalse(send.called)
|
||||
|
||||
@ -328,20 +296,11 @@ class TestApns(unittest.TestCase):
|
||||
send = mock_client.return_value.send_notification
|
||||
send.side_effect = Unregistered()
|
||||
|
||||
config = {
|
||||
'notify': {
|
||||
'platform': 'apns',
|
||||
'name': 'test_app',
|
||||
'topic': 'testapp.appname',
|
||||
'cert_file': 'test_app.pem'
|
||||
}
|
||||
}
|
||||
|
||||
devices_path = self.hass.config.path('test_app_apns.yaml')
|
||||
with open(devices_path, 'w+') as out:
|
||||
out.write('1234: {name: test device 1}\n')
|
||||
|
||||
notify.setup(self.hass, config)
|
||||
self._setup_notify()
|
||||
|
||||
self.assertTrue(self.hass.services.call('notify', 'test_app',
|
||||
{'message': 'Hello'},
|
||||
|
@ -6,7 +6,7 @@ from unittest.mock import patch
|
||||
|
||||
from homeassistant.bootstrap import setup_component
|
||||
import homeassistant.components.notify as notify
|
||||
from tests.common import get_test_home_assistant
|
||||
from tests.common import assert_setup_component, get_test_home_assistant
|
||||
|
||||
|
||||
class TestCommandLine(unittest.TestCase):
|
||||
@ -22,34 +22,41 @@ class TestCommandLine(unittest.TestCase):
|
||||
|
||||
def test_setup(self):
|
||||
"""Test setup."""
|
||||
assert setup_component(self.hass, 'notify', {
|
||||
'notify': {
|
||||
'name': 'test',
|
||||
'platform': 'command_line',
|
||||
'command': 'echo $(cat); exit 1',
|
||||
}})
|
||||
with assert_setup_component(1) as handle_config:
|
||||
assert setup_component(self.hass, 'notify', {
|
||||
'notify': {
|
||||
'name': 'test',
|
||||
'platform': 'command_line',
|
||||
'command': 'echo $(cat); exit 1', }
|
||||
})
|
||||
assert handle_config[notify.DOMAIN]
|
||||
|
||||
def test_bad_config(self):
|
||||
"""Test set up the platform with bad/missing configuration."""
|
||||
self.assertFalse(setup_component(self.hass, notify.DOMAIN, {
|
||||
'notify': {
|
||||
config = {
|
||||
notify.DOMAIN: {
|
||||
'name': 'test',
|
||||
'platform': 'bad_platform',
|
||||
'platform': 'command_line',
|
||||
}
|
||||
}))
|
||||
}
|
||||
with assert_setup_component(0) as handle_config:
|
||||
assert setup_component(self.hass, notify.DOMAIN, config)
|
||||
assert not handle_config[notify.DOMAIN]
|
||||
|
||||
def test_command_line_output(self):
|
||||
"""Test the command line output."""
|
||||
with tempfile.TemporaryDirectory() as tempdirname:
|
||||
filename = os.path.join(tempdirname, 'message.txt')
|
||||
message = 'one, two, testing, testing'
|
||||
self.assertTrue(setup_component(self.hass, notify.DOMAIN, {
|
||||
'notify': {
|
||||
'name': 'test',
|
||||
'platform': 'command_line',
|
||||
'command': 'echo $(cat) > {}'.format(filename)
|
||||
}
|
||||
}))
|
||||
with assert_setup_component(1) as handle_config:
|
||||
self.assertTrue(setup_component(self.hass, notify.DOMAIN, {
|
||||
'notify': {
|
||||
'name': 'test',
|
||||
'platform': 'command_line',
|
||||
'command': 'echo $(cat) > {}'.format(filename)
|
||||
}
|
||||
}))
|
||||
assert handle_config[notify.DOMAIN]
|
||||
|
||||
self.assertTrue(
|
||||
self.hass.services.call('notify', 'test', {'message': message},
|
||||
@ -63,13 +70,15 @@ class TestCommandLine(unittest.TestCase):
|
||||
@patch('homeassistant.components.notify.command_line._LOGGER.error')
|
||||
def test_error_for_none_zero_exit_code(self, mock_error):
|
||||
"""Test if an error is logged for non zero exit codes."""
|
||||
self.assertTrue(setup_component(self.hass, notify.DOMAIN, {
|
||||
'notify': {
|
||||
'name': 'test',
|
||||
'platform': 'command_line',
|
||||
'command': 'echo $(cat); exit 1'
|
||||
}
|
||||
}))
|
||||
with assert_setup_component(1) as handle_config:
|
||||
self.assertTrue(setup_component(self.hass, notify.DOMAIN, {
|
||||
'notify': {
|
||||
'name': 'test',
|
||||
'platform': 'command_line',
|
||||
'command': 'echo $(cat); exit 1'
|
||||
}
|
||||
}))
|
||||
assert handle_config[notify.DOMAIN]
|
||||
|
||||
self.assertTrue(
|
||||
self.hass.services.call('notify', 'test', {'message': 'error'},
|
||||
|
@ -1,13 +1,19 @@
|
||||
"""The tests for the notify demo platform."""
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.bootstrap import setup_component
|
||||
import homeassistant.components.notify as notify
|
||||
from homeassistant.bootstrap import setup_component
|
||||
from homeassistant.components.notify import demo
|
||||
from homeassistant.helpers import script
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers import discovery, script
|
||||
from tests.common import assert_setup_component, get_test_home_assistant
|
||||
|
||||
from tests.common import get_test_home_assistant
|
||||
CONFIG = {
|
||||
notify.DOMAIN: {
|
||||
'platform': 'demo'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TestNotifyDemo(unittest.TestCase):
|
||||
@ -16,11 +22,6 @@ class TestNotifyDemo(unittest.TestCase):
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
"""Setup things to be run when tests are started."""
|
||||
self.hass = get_test_home_assistant()
|
||||
self.assertTrue(setup_component(self.hass, notify.DOMAIN, {
|
||||
'notify': {
|
||||
'platform': 'demo'
|
||||
}
|
||||
}))
|
||||
self.events = []
|
||||
self.calls = []
|
||||
|
||||
@ -35,6 +36,59 @@ class TestNotifyDemo(unittest.TestCase):
|
||||
""""Stop down everything that was started."""
|
||||
self.hass.stop()
|
||||
|
||||
def _setup_notify(self):
|
||||
with assert_setup_component(1) as config:
|
||||
assert setup_component(self.hass, notify.DOMAIN, CONFIG)
|
||||
assert config[notify.DOMAIN]
|
||||
|
||||
def test_setup(self):
|
||||
"""Test setup."""
|
||||
self._setup_notify()
|
||||
|
||||
@patch('homeassistant.bootstrap.prepare_setup_platform')
|
||||
def test_no_prepare_setup_platform(self, mock_prep_setup_platform):
|
||||
"""Test missing notify platform."""
|
||||
mock_prep_setup_platform.return_value = None
|
||||
with self.assertLogs('homeassistant.components.notify',
|
||||
level='ERROR') as log_handle:
|
||||
self._setup_notify()
|
||||
self.hass.block_till_done()
|
||||
assert mock_prep_setup_platform.called
|
||||
self.assertEqual(
|
||||
log_handle.output,
|
||||
['ERROR:homeassistant.components.notify:'
|
||||
'Unknown notification service specified',
|
||||
'ERROR:homeassistant.components.notify:'
|
||||
'Failed to set up platform demo'])
|
||||
|
||||
@patch('homeassistant.components.notify.demo.get_service')
|
||||
def test_no_notify_service(self, mock_demo_get_service):
|
||||
"""Test missing platform notify service instance."""
|
||||
mock_demo_get_service.return_value = None
|
||||
with self.assertLogs('homeassistant.components.notify',
|
||||
level='ERROR') as log_handle:
|
||||
self._setup_notify()
|
||||
self.hass.block_till_done()
|
||||
assert mock_demo_get_service.called
|
||||
self.assertEqual(
|
||||
log_handle.output,
|
||||
['ERROR:homeassistant.components.notify:'
|
||||
'Failed to initialize notification service demo',
|
||||
'ERROR:homeassistant.components.notify:'
|
||||
'Failed to set up platform demo'])
|
||||
|
||||
@patch('homeassistant.components.notify.demo.get_service')
|
||||
def test_discover_notify(self, mock_demo_get_service):
|
||||
"""Test discovery of notify demo platform."""
|
||||
assert notify.DOMAIN not in self.hass.config.components
|
||||
discovery.load_platform(
|
||||
self.hass, 'notify', 'demo', {'test_key': 'test_val'}, {})
|
||||
self.hass.block_till_done()
|
||||
assert notify.DOMAIN in self.hass.config.components
|
||||
assert mock_demo_get_service.called
|
||||
assert mock_demo_get_service.call_args[0] == (
|
||||
self.hass, {}, {'test_key': 'test_val'})
|
||||
|
||||
@callback
|
||||
def record_calls(self, *args):
|
||||
"""Helper for recording calls."""
|
||||
@ -42,12 +96,14 @@ class TestNotifyDemo(unittest.TestCase):
|
||||
|
||||
def test_sending_none_message(self):
|
||||
"""Test send with None as message."""
|
||||
self._setup_notify()
|
||||
notify.send_message(self.hass, None)
|
||||
self.hass.block_till_done()
|
||||
self.assertTrue(len(self.events) == 0)
|
||||
|
||||
def test_sending_templated_message(self):
|
||||
"""Send a templated message."""
|
||||
self._setup_notify()
|
||||
self.hass.states.set('sensor.temperature', 10)
|
||||
notify.send_message(self.hass, '{{ states.sensor.temperature.state }}',
|
||||
'{{ states.sensor.temperature.name }}')
|
||||
@ -58,6 +114,7 @@ class TestNotifyDemo(unittest.TestCase):
|
||||
|
||||
def test_method_forwards_correct_data(self):
|
||||
"""Test that all data from the service gets forwarded to service."""
|
||||
self._setup_notify()
|
||||
notify.send_message(self.hass, 'my message', 'my title',
|
||||
{'hello': 'world'})
|
||||
self.hass.block_till_done()
|
||||
@ -71,6 +128,7 @@ class TestNotifyDemo(unittest.TestCase):
|
||||
|
||||
def test_calling_notify_from_script_loaded_from_yaml_without_title(self):
|
||||
"""Test if we can call a notify from a script."""
|
||||
self._setup_notify()
|
||||
conf = {
|
||||
'service': 'notify.notify',
|
||||
'data': {
|
||||
@ -97,6 +155,7 @@ class TestNotifyDemo(unittest.TestCase):
|
||||
|
||||
def test_calling_notify_from_script_loaded_from_yaml_with_title(self):
|
||||
"""Test if we can call a notify from a script."""
|
||||
self._setup_notify()
|
||||
conf = {
|
||||
'service': 'notify.notify',
|
||||
'data': {
|
||||
@ -127,12 +186,14 @@ class TestNotifyDemo(unittest.TestCase):
|
||||
|
||||
def test_targets_are_services(self):
|
||||
"""Test that all targets are exposed as individual services."""
|
||||
self._setup_notify()
|
||||
self.assertIsNotNone(self.hass.services.has_service("notify", "demo"))
|
||||
service = "demo_test_target_name"
|
||||
self.assertIsNotNone(self.hass.services.has_service("notify", service))
|
||||
|
||||
def test_messages_to_targets_route(self):
|
||||
"""Test message routing to specific target services."""
|
||||
self._setup_notify()
|
||||
self.hass.bus.listen_once("notify", self.record_calls)
|
||||
|
||||
self.hass.services.call("notify", "demo_test_target_name",
|
||||
|
@ -9,7 +9,7 @@ from homeassistant.components.notify import (
|
||||
ATTR_TITLE_DEFAULT)
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from tests.common import get_test_home_assistant, assert_setup_component
|
||||
from tests.common import assert_setup_component, get_test_home_assistant
|
||||
|
||||
|
||||
class TestNotifyFile(unittest.TestCase):
|
||||
@ -25,36 +25,38 @@ class TestNotifyFile(unittest.TestCase):
|
||||
|
||||
def test_bad_config(self):
|
||||
"""Test set up the platform with bad/missing config."""
|
||||
with assert_setup_component(0):
|
||||
assert not setup_component(self.hass, notify.DOMAIN, {
|
||||
'notify': {
|
||||
'name': 'test',
|
||||
'platform': 'file',
|
||||
},
|
||||
})
|
||||
config = {
|
||||
notify.DOMAIN: {
|
||||
'name': 'test',
|
||||
'platform': 'file',
|
||||
},
|
||||
}
|
||||
with assert_setup_component(0) as handle_config:
|
||||
assert setup_component(self.hass, notify.DOMAIN, config)
|
||||
assert not handle_config[notify.DOMAIN]
|
||||
|
||||
@patch('homeassistant.components.notify.file.os.stat')
|
||||
@patch('homeassistant.util.dt.utcnow')
|
||||
def test_notify_file(self, mock_utcnow, mock_stat):
|
||||
def _test_notify_file(self, timestamp, mock_utcnow, mock_stat):
|
||||
"""Test the notify file output."""
|
||||
mock_utcnow.return_value = dt_util.as_utc(dt_util.now())
|
||||
mock_stat.return_value.st_size = 0
|
||||
|
||||
m_open = mock_open()
|
||||
with patch(
|
||||
'homeassistant.components.notify.file.open',
|
||||
m_open, create=True
|
||||
'homeassistant.components.notify.file.open',
|
||||
m_open, create=True
|
||||
):
|
||||
filename = 'mock_file'
|
||||
message = 'one, two, testing, testing'
|
||||
self.assertTrue(setup_component(self.hass, notify.DOMAIN, {
|
||||
'notify': {
|
||||
'name': 'test',
|
||||
'platform': 'file',
|
||||
'filename': filename,
|
||||
'timestamp': False,
|
||||
}
|
||||
}))
|
||||
with assert_setup_component(1) as handle_config:
|
||||
self.assertTrue(setup_component(self.hass, notify.DOMAIN, {
|
||||
'notify': {
|
||||
'name': 'test',
|
||||
'platform': 'file',
|
||||
'filename': filename,
|
||||
'timestamp': timestamp,
|
||||
}
|
||||
}))
|
||||
assert handle_config[notify.DOMAIN]
|
||||
title = '{} notifications (Log started: {})\n{}\n'.format(
|
||||
ATTR_TITLE_DEFAULT,
|
||||
dt_util.utcnow().isoformat(),
|
||||
@ -68,7 +70,26 @@ class TestNotifyFile(unittest.TestCase):
|
||||
self.assertEqual(m_open.call_args, call(full_filename, 'a'))
|
||||
|
||||
self.assertEqual(m_open.return_value.write.call_count, 2)
|
||||
self.assertEqual(
|
||||
m_open.return_value.write.call_args_list,
|
||||
[call(title), call(message + '\n')]
|
||||
)
|
||||
if not timestamp:
|
||||
self.assertEqual(
|
||||
m_open.return_value.write.call_args_list,
|
||||
[call(title), call('{}\n'.format(message))]
|
||||
)
|
||||
else:
|
||||
self.assertEqual(
|
||||
m_open.return_value.write.call_args_list,
|
||||
[call(title), call('{} {}\n'.format(
|
||||
dt_util.utcnow().isoformat(), message))]
|
||||
)
|
||||
|
||||
@patch('homeassistant.components.notify.file.os.stat')
|
||||
@patch('homeassistant.util.dt.utcnow')
|
||||
def test_notify_file(self, mock_utcnow, mock_stat):
|
||||
"""Test the notify file output without timestamp."""
|
||||
self._test_notify_file(False, mock_utcnow, mock_stat)
|
||||
|
||||
@patch('homeassistant.components.notify.file.os.stat')
|
||||
@patch('homeassistant.util.dt.utcnow')
|
||||
def test_notify_file_timestamp(self, mock_utcnow, mock_stat):
|
||||
"""Test the notify file output with timestamp."""
|
||||
self._test_notify_file(True, mock_utcnow, mock_stat)
|
||||
|
@ -19,7 +19,7 @@ class TestNotifyGroup(unittest.TestCase):
|
||||
self.service1 = MagicMock()
|
||||
self.service2 = MagicMock()
|
||||
|
||||
def mock_get_service(hass, config):
|
||||
def mock_get_service(hass, config, discovery_info=None):
|
||||
if config['name'] == 'demo1':
|
||||
return self.service1
|
||||
else:
|
||||
|
Loading…
x
Reference in New Issue
Block a user