mirror of
https://github.com/home-assistant/core.git
synced 2025-06-25 01:21:51 +02:00
Add Google pubsub component (#20049)
* Add google pubsub component * Add tests and requirements * Make python3.5 compatible * Fix linting * Fix pubsub test * Code review comments * Add missing docstrings * Update requirements_all * Code review comment - Remove pylint ignores - Don't modify global environment
This commit is contained in:
committed by
Anders Melchiorsen
parent
1ebdc2e2c2
commit
d049b521b2
99
homeassistant/components/google_pubsub/__init__.py
Normal file
99
homeassistant/components/google_pubsub/__init__.py
Normal file
@ -0,0 +1,99 @@
|
||||
"""
|
||||
Support for Google Cloud Pub/Sub.
|
||||
|
||||
For more details about this component, please refer to the documentation at
|
||||
https://home-assistant.io/components/google_pubsub/
|
||||
"""
|
||||
import datetime
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from typing import Any, Dict
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import (
|
||||
EVENT_STATE_CHANGED, STATE_UNAVAILABLE, STATE_UNKNOWN)
|
||||
from homeassistant.core import Event, HomeAssistant
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.entityfilter import FILTER_SCHEMA
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
REQUIREMENTS = ['google-cloud-pubsub==0.39.1']
|
||||
|
||||
DOMAIN = 'google_pubsub'
|
||||
|
||||
CONF_PROJECT_ID = 'project_id'
|
||||
CONF_TOPIC_NAME = 'topic_name'
|
||||
CONF_SERVICE_PRINCIPAL = 'credentials_json'
|
||||
CONF_FILTER = 'filter'
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
DOMAIN: vol.Schema({
|
||||
vol.Required(CONF_PROJECT_ID): cv.string,
|
||||
vol.Required(CONF_TOPIC_NAME): cv.string,
|
||||
vol.Required(CONF_SERVICE_PRINCIPAL): cv.string,
|
||||
vol.Required(CONF_FILTER): FILTER_SCHEMA
|
||||
}),
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
|
||||
def setup(hass: HomeAssistant, yaml_config: Dict[str, Any]):
|
||||
"""Activate Google Pub/Sub component."""
|
||||
from google.cloud import pubsub_v1
|
||||
|
||||
config = yaml_config[DOMAIN]
|
||||
project_id = config[CONF_PROJECT_ID]
|
||||
topic_name = config[CONF_TOPIC_NAME]
|
||||
service_principal_path = os.path.join(hass.config.config_dir,
|
||||
config[CONF_SERVICE_PRINCIPAL])
|
||||
|
||||
if not os.path.isfile(service_principal_path):
|
||||
_LOGGER.error("Path to credentials file cannot be found")
|
||||
return False
|
||||
|
||||
entities_filter = config[CONF_FILTER]
|
||||
|
||||
publisher = (pubsub_v1
|
||||
.PublisherClient
|
||||
.from_service_account_json(service_principal_path)
|
||||
)
|
||||
|
||||
topic_path = publisher.topic_path(project_id, # pylint: disable=E1101
|
||||
topic_name)
|
||||
|
||||
encoder = DateTimeJSONEncoder()
|
||||
|
||||
def send_to_pubsub(event: Event):
|
||||
"""Send states to Pub/Sub."""
|
||||
state = event.data.get('new_state')
|
||||
if (state is None
|
||||
or state.state in (STATE_UNKNOWN, '', STATE_UNAVAILABLE)
|
||||
or not entities_filter(state.entity_id)):
|
||||
return
|
||||
|
||||
as_dict = state.as_dict()
|
||||
data = json.dumps(
|
||||
obj=as_dict,
|
||||
default=encoder.encode
|
||||
).encode('utf-8')
|
||||
|
||||
publisher.publish(topic_path, data=data)
|
||||
|
||||
hass.bus.listen(EVENT_STATE_CHANGED, send_to_pubsub)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class DateTimeJSONEncoder(json.JSONEncoder):
|
||||
"""Encode python objects.
|
||||
|
||||
Additionally add encoding for datetime objects as isoformat.
|
||||
"""
|
||||
|
||||
def default(self, o): # pylint: disable=E0202
|
||||
"""Implement encoding logic."""
|
||||
if isinstance(o, datetime.datetime):
|
||||
return o.isoformat()
|
||||
return super().default(o)
|
@ -471,6 +471,9 @@ gntp==1.0.3
|
||||
# homeassistant.components.google
|
||||
google-api-python-client==1.6.4
|
||||
|
||||
# homeassistant.components.google_pubsub
|
||||
google-cloud-pubsub==0.39.1
|
||||
|
||||
# homeassistant.components.googlehome
|
||||
googledevices==1.0.2
|
||||
|
||||
|
22
tests/components/google_pubsub/test_pubsub.py
Normal file
22
tests/components/google_pubsub/test_pubsub.py
Normal file
@ -0,0 +1,22 @@
|
||||
"""The tests for the Google Pub/Sub component."""
|
||||
from datetime import datetime
|
||||
|
||||
from homeassistant.components.google_pubsub import (
|
||||
DateTimeJSONEncoder as victim)
|
||||
|
||||
|
||||
class TestDateTimeJSONEncoder(object):
|
||||
"""Bundle for DateTimeJSONEncoder tests."""
|
||||
|
||||
def test_datetime(self):
|
||||
"""Test datetime encoding."""
|
||||
time = datetime(2019, 1, 13, 12, 30, 5)
|
||||
assert victim().encode(time) == '"2019-01-13T12:30:05"'
|
||||
|
||||
def test_no_datetime(self):
|
||||
"""Test integer encoding."""
|
||||
assert victim().encode(42) == '42'
|
||||
|
||||
def test_nested(self):
|
||||
"""Test dictionary encoding."""
|
||||
assert victim().encode({'foo': 'bar'}) == '{"foo": "bar"}'
|
Reference in New Issue
Block a user