From af73e54aee51944c72ce2afd54c90cf617273ab4 Mon Sep 17 00:00:00 2001 From: Heine Furubotten Date: Thu, 7 Nov 2019 14:47:44 +0100 Subject: [PATCH] Add azure servicebus notify service (#27566) * Add azure servicebus notify service * files added to .coveragerc * fix: import content type from const * Moved imports to top level * Code review fixes + added code owner + fixed config validation with has at least one + seperate attributes for dto to asb * fixed doc link * async setup instead of sync * rename all the things - removed too many ifs * changed setup back to sync + comment about sync IO in lib * More informative logging * logging exception -> error --- .coveragerc | 1 + CODEOWNERS | 1 + .../components/azure_service_bus/__init__.py | 1 + .../azure_service_bus/manifest.json | 12 ++ .../components/azure_service_bus/notify.py | 106 ++++++++++++++++++ requirements_all.txt | 3 + 6 files changed, 124 insertions(+) create mode 100644 homeassistant/components/azure_service_bus/__init__.py create mode 100644 homeassistant/components/azure_service_bus/manifest.json create mode 100644 homeassistant/components/azure_service_bus/notify.py diff --git a/.coveragerc b/.coveragerc index e6f09d60eff..169b73b7899 100644 --- a/.coveragerc +++ b/.coveragerc @@ -69,6 +69,7 @@ omit = homeassistant/components/avea/light.py homeassistant/components/avion/light.py homeassistant/components/azure_event_hub/* + homeassistant/components/azure_service_bus/* homeassistant/components/baidu/tts.py homeassistant/components/beewi_smartclim/sensor.py homeassistant/components/bbb_gpio/* diff --git a/CODEOWNERS b/CODEOWNERS index 27e06d874e1..0a02fbc5321 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -43,6 +43,7 @@ homeassistant/components/awair/* @danielsjf homeassistant/components/aws/* @awarecan @robbiet480 homeassistant/components/axis/* @kane610 homeassistant/components/azure_event_hub/* @eavanvalkenburg +homeassistant/components/azure_service_bus/* @hfurubotten homeassistant/components/beewi_smartclim/* @alemuro homeassistant/components/bitcoin/* @fabaff homeassistant/components/bizkaibus/* @UgaitzEtxebarria diff --git a/homeassistant/components/azure_service_bus/__init__.py b/homeassistant/components/azure_service_bus/__init__.py new file mode 100644 index 00000000000..f18dc9eb66c --- /dev/null +++ b/homeassistant/components/azure_service_bus/__init__.py @@ -0,0 +1 @@ +"""The Azure Service Bus integration.""" diff --git a/homeassistant/components/azure_service_bus/manifest.json b/homeassistant/components/azure_service_bus/manifest.json new file mode 100644 index 00000000000..fa6d1c20b7f --- /dev/null +++ b/homeassistant/components/azure_service_bus/manifest.json @@ -0,0 +1,12 @@ +{ + "domain": "azure_service_bus", + "name": "Azure Service Bus", + "documentation": "https://www.home-assistant.io/integrations/azure_service_bus", + "requirements": [ + "azure-servicebus==0.50.1" + ], + "dependencies": [], + "codeowners": [ + "@hfurubotten" + ] +} \ No newline at end of file diff --git a/homeassistant/components/azure_service_bus/notify.py b/homeassistant/components/azure_service_bus/notify.py new file mode 100644 index 00000000000..e7c85adede8 --- /dev/null +++ b/homeassistant/components/azure_service_bus/notify.py @@ -0,0 +1,106 @@ +"""Support for azure service bus notification.""" +import json +import logging + +from azure.servicebus.aio import Message, ServiceBusClient +from azure.servicebus.common.errors import ( + MessageSendFailed, + ServiceBusConnectionError, + ServiceBusResourceNotFound, +) +import voluptuous as vol + +from homeassistant.components.notify import ( + ATTR_DATA, + ATTR_TARGET, + ATTR_TITLE, + PLATFORM_SCHEMA, + BaseNotificationService, +) +from homeassistant.const import CONTENT_TYPE_JSON +import homeassistant.helpers.config_validation as cv + +CONF_CONNECTION_STRING = "connection_string" +CONF_QUEUE_NAME = "queue" +CONF_TOPIC_NAME = "topic" + +ATTR_ASB_MESSAGE = "message" +ATTR_ASB_TITLE = "title" +ATTR_ASB_TARGET = "target" + +PLATFORM_SCHEMA = vol.All( + cv.has_at_least_one_key(CONF_QUEUE_NAME, CONF_TOPIC_NAME), + PLATFORM_SCHEMA.extend( + { + vol.Required(CONF_CONNECTION_STRING): cv.string, + vol.Exclusive( + CONF_QUEUE_NAME, "output", "Can only send to a queue or a topic." + ): cv.string, + vol.Exclusive( + CONF_TOPIC_NAME, "output", "Can only send to a queue or a topic." + ): cv.string, + } + ), +) + +_LOGGER = logging.getLogger(__name__) + + +def get_service(hass, config, discovery_info=None): + """Get the notification service.""" + connection_string = config[CONF_CONNECTION_STRING] + queue_name = config.get(CONF_QUEUE_NAME) + topic_name = config.get(CONF_TOPIC_NAME) + + # Library can do synchronous IO when creating the clients. + # Passes in loop here, but can't run setup on the event loop. + servicebus = ServiceBusClient.from_connection_string( + connection_string, loop=hass.loop + ) + + try: + if queue_name: + client = servicebus.get_queue(queue_name) + else: + client = servicebus.get_topic(topic_name) + except (ServiceBusConnectionError, ServiceBusResourceNotFound) as err: + _LOGGER.error( + "Connection error while creating client for queue/topic '%s'. %s", + queue_name or topic_name, + err, + ) + return None + + return ServiceBusNotificationService(client) + + +class ServiceBusNotificationService(BaseNotificationService): + """Implement the notification service for the service bus service.""" + + def __init__(self, client): + """Initialize the service.""" + self._client = client + + async def async_send_message(self, message, **kwargs): + """Send a message.""" + dto = {ATTR_ASB_MESSAGE: message} + + if ATTR_TITLE in kwargs: + dto[ATTR_ASB_TITLE] = kwargs[ATTR_TITLE] + if ATTR_TARGET in kwargs: + dto[ATTR_ASB_TARGET] = kwargs[ATTR_TARGET] + + data = kwargs.get(ATTR_DATA) + if data: + dto.update(data) + + queue_message = Message(json.dumps(dto)) + queue_message.properties.content_type = CONTENT_TYPE_JSON + try: + await self._client.send(queue_message) + except MessageSendFailed as err: + _LOGGER.error( + "Could not send service bus notification to %s. %s", + self._client.name, + err, + ) diff --git a/requirements_all.txt b/requirements_all.txt index ca1ae68e4a6..8843a6693ab 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -263,6 +263,9 @@ axis==25 # homeassistant.components.azure_event_hub azure-eventhub==1.3.1 +# homeassistant.components.azure_service_bus +azure-servicebus==0.50.1 + # homeassistant.components.baidu baidu-aip==1.6.6