diff --git a/.coveragerc b/.coveragerc index aec863174b8..29dd544f911 100644 --- a/.coveragerc +++ b/.coveragerc @@ -128,6 +128,9 @@ omit = homeassistant/components/media_player/sonos.py homeassistant/components/media_player/squeezebox.py homeassistant/components/media_player/yamaha.py + homeassistant/components/notify/aws_lambda.py + homeassistant/components/notify/aws_sns.py + homeassistant/components/notify/aws_sqs.py homeassistant/components/notify/free_mobile.py homeassistant/components/notify/gntp.py homeassistant/components/notify/googlevoice.py diff --git a/homeassistant/components/notify/aws_lambda.py b/homeassistant/components/notify/aws_lambda.py new file mode 100644 index 00000000000..2c73462d92b --- /dev/null +++ b/homeassistant/components/notify/aws_lambda.py @@ -0,0 +1,89 @@ +""" +AWS Lambda platform for notify component. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/notify.aws_lambda/ +""" +import logging +import json +import base64 +import voluptuous as vol + +from homeassistant.const import ( + CONF_PLATFORM, CONF_NAME) +from homeassistant.components.notify import ( + ATTR_TARGET, BaseNotificationService) + +_LOGGER = logging.getLogger(__name__) +REQUIREMENTS = ["boto3==1.3.1"] + +CONF_REGION = "region_name" +CONF_ACCESS_KEY_ID = "aws_access_key_id" +CONF_SECRET_ACCESS_KEY = "aws_secret_access_key" +CONF_PROFILE_NAME = "profile_name" +CONF_CONTEXT = "context" + +PLATFORM_SCHEMA = vol.Schema({ + vol.Required(CONF_PLATFORM): "aws_lambda", + vol.Optional(CONF_NAME): vol.Coerce(str), + vol.Optional(CONF_REGION, default="us-east-1"): vol.Coerce(str), + vol.Inclusive(CONF_ACCESS_KEY_ID, "credentials"): vol.Coerce(str), + vol.Inclusive(CONF_SECRET_ACCESS_KEY, "credentials"): vol.Coerce(str), + vol.Exclusive(CONF_PROFILE_NAME, "credentials"): vol.Coerce(str), + vol.Optional(CONF_CONTEXT, default=dict()): vol.Coerce(dict) +}) + + +def get_service(hass, config): + """Get the AWS Lambda notification service.""" + context_str = json.dumps({'hass': hass.config.as_dict(), + 'custom': config[CONF_CONTEXT]}) + context_b64 = base64.b64encode(context_str.encode("utf-8")) + context = context_b64.decode("utf-8") + + # pylint: disable=import-error + import boto3 + + aws_config = config.copy() + + del aws_config[CONF_PLATFORM] + del aws_config[CONF_NAME] + del aws_config[CONF_CONTEXT] + + if aws_config[CONF_PROFILE_NAME]: + boto3.setup_default_session(profile_name=aws_config[CONF_PROFILE_NAME]) + del aws_config[CONF_PROFILE_NAME] + + lambda_client = boto3.client("lambda", **aws_config) + + return AWSLambda(lambda_client, context) + + +# pylint: disable=too-few-public-methods +class AWSLambda(BaseNotificationService): + """Implement the notification service for the AWS Lambda service.""" + + def __init__(self, lambda_client, context): + """Initialize the service.""" + self.client = lambda_client + self.context = context + + def send_message(self, message="", **kwargs): + """Send notification to specified LAMBDA ARN.""" + targets = kwargs.get(ATTR_TARGET) + + if not targets: + _LOGGER.info("At least 1 target is required") + return + + if not isinstance(targets, list): + targets = [targets] + + for target in targets: + cleaned_kwargs = dict((k, v) for k, v in kwargs.items() if v) + payload = {"message": message} + payload.update(cleaned_kwargs) + + self.client.invoke(FunctionName=target, + Payload=json.dumps(payload), + ClientContext=self.context) diff --git a/homeassistant/components/notify/aws_sns.py b/homeassistant/components/notify/aws_sns.py new file mode 100644 index 00000000000..d6727b3de23 --- /dev/null +++ b/homeassistant/components/notify/aws_sns.py @@ -0,0 +1,78 @@ +""" +AWS SNS platform for notify component. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/notify.aws_sns/ +""" +import logging +import json +import voluptuous as vol + +from homeassistant.const import ( + CONF_PLATFORM, CONF_NAME) +from homeassistant.components.notify import ( + ATTR_TITLE, ATTR_TARGET, BaseNotificationService) + +_LOGGER = logging.getLogger(__name__) +REQUIREMENTS = ["boto3==1.3.1"] + +CONF_REGION = "region_name" +CONF_ACCESS_KEY_ID = "aws_access_key_id" +CONF_SECRET_ACCESS_KEY = "aws_secret_access_key" +CONF_PROFILE_NAME = "profile_name" + +PLATFORM_SCHEMA = vol.Schema({ + vol.Required(CONF_PLATFORM): "aws_sns", + vol.Optional(CONF_NAME): vol.Coerce(str), + vol.Optional(CONF_REGION, default="us-east-1"): vol.Coerce(str), + vol.Inclusive(CONF_ACCESS_KEY_ID, "credentials"): vol.Coerce(str), + vol.Inclusive(CONF_SECRET_ACCESS_KEY, "credentials"): vol.Coerce(str), + vol.Exclusive(CONF_PROFILE_NAME, "credentials"): vol.Coerce(str) +}) + + +def get_service(hass, config): + """Get the AWS SNS notification service.""" + # pylint: disable=import-error + import boto3 + + aws_config = config.copy() + + del aws_config[CONF_PLATFORM] + del aws_config[CONF_NAME] + + if aws_config[CONF_PROFILE_NAME]: + boto3.setup_default_session(profile_name=aws_config[CONF_PROFILE_NAME]) + del aws_config[CONF_PROFILE_NAME] + + sns_client = boto3.client("sns", **aws_config) + + return AWSSNS(sns_client) + + +# pylint: disable=too-few-public-methods +class AWSSNS(BaseNotificationService): + """Implement the notification service for the AWS SNS service.""" + + def __init__(self, sns_client): + """Initialize the service.""" + self.client = sns_client + + def send_message(self, message="", **kwargs): + """Send notification to specified SNS ARN.""" + targets = kwargs.get(ATTR_TARGET) + + if not targets: + _LOGGER.info("At least 1 target is required") + return + + if not isinstance(targets, list): + targets = [targets] + + message_attributes = {k: {"StringValue": json.dumps(v), + "DataType": "String"} + for k, v in kwargs.items() if v} + for target in targets: + self.client.publish(TargetArn=target, Message=message, + Subject=kwargs.get(ATTR_TITLE), + MessageAttributes=message_attributes) diff --git a/homeassistant/components/notify/aws_sqs.py b/homeassistant/components/notify/aws_sqs.py new file mode 100644 index 00000000000..122f667959b --- /dev/null +++ b/homeassistant/components/notify/aws_sqs.py @@ -0,0 +1,82 @@ +""" +AWS SQS platform for notify component. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/notify.aws_sqs/ +""" +import logging +import json +import voluptuous as vol + +from homeassistant.const import ( + CONF_PLATFORM, CONF_NAME) +from homeassistant.components.notify import ( + ATTR_TARGET, BaseNotificationService) + +_LOGGER = logging.getLogger(__name__) +REQUIREMENTS = ["boto3==1.3.1"] + +CONF_REGION = "region_name" +CONF_ACCESS_KEY_ID = "aws_access_key_id" +CONF_SECRET_ACCESS_KEY = "aws_secret_access_key" +CONF_PROFILE_NAME = "profile_name" + +PLATFORM_SCHEMA = vol.Schema({ + vol.Required(CONF_PLATFORM): "aws_sqs", + vol.Optional(CONF_NAME): vol.Coerce(str), + vol.Optional(CONF_REGION, default="us-east-1"): vol.Coerce(str), + vol.Inclusive(CONF_ACCESS_KEY_ID, "credentials"): vol.Coerce(str), + vol.Inclusive(CONF_SECRET_ACCESS_KEY, "credentials"): vol.Coerce(str), + vol.Exclusive(CONF_PROFILE_NAME, "credentials"): vol.Coerce(str) +}) + + +def get_service(hass, config): + """Get the AWS SQS notification service.""" + # pylint: disable=import-error + import boto3 + + aws_config = config.copy() + + del aws_config[CONF_PLATFORM] + del aws_config[CONF_NAME] + + if aws_config[CONF_PROFILE_NAME]: + boto3.setup_default_session(profile_name=aws_config[CONF_PROFILE_NAME]) + del aws_config[CONF_PROFILE_NAME] + + sqs_client = boto3.client("sqs", **aws_config) + + return AWSSQS(sqs_client) + + +# pylint: disable=too-few-public-methods +class AWSSQS(BaseNotificationService): + """Implement the notification service for the AWS SQS service.""" + + def __init__(self, sqs_client): + """Initialize the service.""" + self.client = sqs_client + + def send_message(self, message="", **kwargs): + """Send notification to specified SQS ARN.""" + targets = kwargs.get(ATTR_TARGET) + + if not targets: + _LOGGER.info("At least 1 target is required") + return + + if not isinstance(targets, list): + targets = [targets] + + for target in targets: + cleaned_kwargs = dict((k, v) for k, v in kwargs.items() if v) + message_body = {"message": message} + message_body.update(cleaned_kwargs) + message_attributes = {} + for key, val in cleaned_kwargs.items(): + message_attributes[key] = {"StringValue": json.dumps(val), + "DataType": "String"} + self.client.send_message(QueueUrl=target, + MessageBody=json.dumps(message_body), + MessageAttributes=message_attributes) diff --git a/requirements_all.txt b/requirements_all.txt index 9a876cbe012..a3e2e7f2939 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -37,6 +37,11 @@ blockchain==1.3.1 # homeassistant.components.thermostat.eq3btsmart # bluepy_devices>=0.2.0 +# homeassistant.components.notify.aws_lambda +# homeassistant.components.notify.aws_sns +# homeassistant.components.notify.aws_sqs +boto3==1.3.1 + # homeassistant.components.notify.xmpp dnspython3==1.12.0