forked from home-assistant/core
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7d334783de | |||
| 027fcf269b | |||
| e1509bcc0c | |||
| 9a13aafeea | |||
| 5f2d209dec | |||
| b0200cdbfe | |||
| c9f64af85a | |||
| e4d45bf53a | |||
| e984868762 | |||
| e5835eb7c8 |
@@ -11,7 +11,7 @@ import voluptuous as vol
|
||||
from homeassistant.config_entries import SOURCE_IMPORT
|
||||
from homeassistant.const import (
|
||||
ATTR_NAME, ATTR_LOCATION, CONF_API_KEY, CONF_MONITORED_CONDITIONS,
|
||||
CONF_UNIT_SYSTEM, EVENT_HOMEASSISTANT_STOP)
|
||||
EVENT_HOMEASSISTANT_STOP)
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers import aiohttp_client, config_validation as cv
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
@@ -19,8 +19,7 @@ from homeassistant.helpers.event import async_call_later
|
||||
|
||||
from .config_flow import configured_instances
|
||||
from .const import (
|
||||
ATTR_LAST_DATA, CONF_APP_KEY, DATA_CLIENT, DOMAIN, TOPIC_UPDATE, UNITS_SI,
|
||||
UNITS_US)
|
||||
ATTR_LAST_DATA, CONF_APP_KEY, DATA_CLIENT, DOMAIN, TOPIC_UPDATE)
|
||||
|
||||
REQUIREMENTS = ['aioambient==0.1.0']
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@@ -28,36 +27,36 @@ _LOGGER = logging.getLogger(__name__)
|
||||
DEFAULT_SOCKET_MIN_RETRY = 15
|
||||
|
||||
SENSOR_TYPES = {
|
||||
'24hourrainin': ['24 Hr Rain', 'in'],
|
||||
'baromabsin': ['Abs Pressure', 'inHg'],
|
||||
'baromrelin': ['Rel Pressure', 'inHg'],
|
||||
'battout': ['Battery', ''],
|
||||
'co2': ['co2', 'ppm'],
|
||||
'dailyrainin': ['Daily Rain', 'in'],
|
||||
'dewPoint': ['Dew Point', ['°F', '°C']],
|
||||
'eventrainin': ['Event Rain', 'in'],
|
||||
'feelsLike': ['Feels Like', ['°F', '°C']],
|
||||
'hourlyrainin': ['Hourly Rain Rate', 'in/hr'],
|
||||
'humidity': ['Humidity', '%'],
|
||||
'humidityin': ['Humidity In', '%'],
|
||||
'lastRain': ['Last Rain', ''],
|
||||
'maxdailygust': ['Max Gust', 'mph'],
|
||||
'monthlyrainin': ['Monthly Rain', 'in'],
|
||||
'solarradiation': ['Solar Rad', 'W/m^2'],
|
||||
'tempf': ['Temp', ['°F', '°C']],
|
||||
'tempinf': ['Inside Temp', ['°F', '°C']],
|
||||
'totalrainin': ['Lifetime Rain', 'in'],
|
||||
'uv': ['uv', 'Index'],
|
||||
'weeklyrainin': ['Weekly Rain', 'in'],
|
||||
'winddir': ['Wind Dir', '°'],
|
||||
'winddir_avg10m': ['Wind Dir Avg 10m', '°'],
|
||||
'winddir_avg2m': ['Wind Dir Avg 2m', 'mph'],
|
||||
'windgustdir': ['Gust Dir', '°'],
|
||||
'windgustmph': ['Wind Gust', 'mph'],
|
||||
'windspdmph_avg10m': ['Wind Avg 10m', 'mph'],
|
||||
'windspdmph_avg2m': ['Wind Avg 2m', 'mph'],
|
||||
'windspeedmph': ['Wind Speed', 'mph'],
|
||||
'yearlyrainin': ['Yearly Rain', 'in'],
|
||||
'24hourrainin': ('24 Hr Rain', 'in'),
|
||||
'baromabsin': ('Abs Pressure', 'inHg'),
|
||||
'baromrelin': ('Rel Pressure', 'inHg'),
|
||||
'battout': ('Battery', ''),
|
||||
'co2': ('co2', 'ppm'),
|
||||
'dailyrainin': ('Daily Rain', 'in'),
|
||||
'dewPoint': ('Dew Point', '°F'),
|
||||
'eventrainin': ('Event Rain', 'in'),
|
||||
'feelsLike': ('Feels Like', '°F'),
|
||||
'hourlyrainin': ('Hourly Rain Rate', 'in/hr'),
|
||||
'humidity': ('Humidity', '%'),
|
||||
'humidityin': ('Humidity In', '%'),
|
||||
'lastRain': ('Last Rain', ''),
|
||||
'maxdailygust': ('Max Gust', 'mph'),
|
||||
'monthlyrainin': ('Monthly Rain', 'in'),
|
||||
'solarradiation': ('Solar Rad', 'W/m^2'),
|
||||
'tempf': ('Temp', '°F'),
|
||||
'tempinf': ('Inside Temp', '°F'),
|
||||
'totalrainin': ('Lifetime Rain', 'in'),
|
||||
'uv': ('uv', 'Index'),
|
||||
'weeklyrainin': ('Weekly Rain', 'in'),
|
||||
'winddir': ('Wind Dir', '°'),
|
||||
'winddir_avg10m': ('Wind Dir Avg 10m', '°'),
|
||||
'winddir_avg2m': ('Wind Dir Avg 2m', 'mph'),
|
||||
'windgustdir': ('Gust Dir', '°'),
|
||||
'windgustmph': ('Wind Gust', 'mph'),
|
||||
'windspdmph_avg10m': ('Wind Avg 10m', 'mph'),
|
||||
'windspdmph_avg2m': ('Wind Avg 2m', 'mph'),
|
||||
'windspeedmph': ('Wind Speed', 'mph'),
|
||||
'yearlyrainin': ('Yearly Rain', 'in'),
|
||||
}
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
@@ -70,8 +69,6 @@ CONFIG_SCHEMA = vol.Schema({
|
||||
vol.Optional(
|
||||
CONF_MONITORED_CONDITIONS, default=list(SENSOR_TYPES)):
|
||||
vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]),
|
||||
vol.Optional(CONF_UNIT_SYSTEM):
|
||||
vol.In([UNITS_SI, UNITS_US]),
|
||||
})
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
@@ -111,8 +108,7 @@ async def async_setup_entry(hass, config_entry):
|
||||
config_entry.data[CONF_API_KEY],
|
||||
config_entry.data[CONF_APP_KEY], session),
|
||||
config_entry.data.get(
|
||||
CONF_MONITORED_CONDITIONS, list(SENSOR_TYPES)),
|
||||
config_entry.data.get(CONF_UNIT_SYSTEM))
|
||||
CONF_MONITORED_CONDITIONS, list(SENSOR_TYPES)))
|
||||
hass.loop.create_task(ambient.ws_connect())
|
||||
hass.data[DOMAIN][DATA_CLIENT][config_entry.entry_id] = ambient
|
||||
except WebsocketConnectionError as err:
|
||||
@@ -139,9 +135,7 @@ async def async_unload_entry(hass, config_entry):
|
||||
class AmbientStation:
|
||||
"""Define a class to handle the Ambient websocket."""
|
||||
|
||||
def __init__(
|
||||
self, hass, config_entry, client, monitored_conditions,
|
||||
unit_system):
|
||||
def __init__(self, hass, config_entry, client, monitored_conditions):
|
||||
"""Initialize."""
|
||||
self._config_entry = config_entry
|
||||
self._hass = hass
|
||||
@@ -149,7 +143,6 @@ class AmbientStation:
|
||||
self.client = client
|
||||
self.monitored_conditions = monitored_conditions
|
||||
self.stations = {}
|
||||
self.unit_system = unit_system
|
||||
|
||||
async def ws_connect(self):
|
||||
"""Register handlers and connect to the websocket."""
|
||||
|
||||
@@ -8,6 +8,3 @@ CONF_APP_KEY = 'app_key'
|
||||
DATA_CLIENT = 'data_client'
|
||||
|
||||
TOPIC_UPDATE = 'update'
|
||||
|
||||
UNITS_SI = 'si'
|
||||
UNITS_US = 'us'
|
||||
|
||||
@@ -12,14 +12,11 @@ from homeassistant.const import ATTR_NAME
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
|
||||
from .const import (
|
||||
ATTR_LAST_DATA, DATA_CLIENT, DOMAIN, TOPIC_UPDATE, UNITS_SI, UNITS_US)
|
||||
from .const import ATTR_LAST_DATA, DATA_CLIENT, DOMAIN, TOPIC_UPDATE
|
||||
|
||||
DEPENDENCIES = ['ambient_station']
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
UNIT_SYSTEM = {UNITS_US: 0, UNITS_SI: 1}
|
||||
|
||||
|
||||
async def async_setup_platform(
|
||||
hass, config, async_add_entities, discovery_info=None):
|
||||
@@ -31,20 +28,10 @@ async def async_setup_entry(hass, entry, async_add_entities):
|
||||
"""Set up an Ambient PWS sensor based on a config entry."""
|
||||
ambient = hass.data[DOMAIN][DATA_CLIENT][entry.entry_id]
|
||||
|
||||
if ambient.unit_system:
|
||||
sys_units = ambient.unit_system
|
||||
elif hass.config.units.is_metric:
|
||||
sys_units = UNITS_SI
|
||||
else:
|
||||
sys_units = UNITS_US
|
||||
|
||||
sensor_list = []
|
||||
for mac_address, station in ambient.stations.items():
|
||||
for condition in ambient.monitored_conditions:
|
||||
name, unit = SENSOR_TYPES[condition]
|
||||
if isinstance(unit, list):
|
||||
unit = unit[UNIT_SYSTEM[sys_units]]
|
||||
|
||||
sensor_list.append(
|
||||
AmbientWeatherSensor(
|
||||
ambient, mac_address, station[ATTR_NAME], condition, name,
|
||||
@@ -58,7 +45,7 @@ class AmbientWeatherSensor(Entity):
|
||||
|
||||
def __init__(
|
||||
self, ambient, mac_address, station_name, sensor_type, sensor_name,
|
||||
units):
|
||||
unit):
|
||||
"""Initialize the sensor."""
|
||||
self._ambient = ambient
|
||||
self._async_unsub_dispatcher_connect = None
|
||||
@@ -67,7 +54,7 @@ class AmbientWeatherSensor(Entity):
|
||||
self._sensor_type = sensor_type
|
||||
self._state = None
|
||||
self._station_name = station_name
|
||||
self._units = units
|
||||
self._unit = unit
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
@@ -87,7 +74,7 @@ class AmbientWeatherSensor(Entity):
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
"""Return the unit of measurement."""
|
||||
return self._units
|
||||
return self._unit
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
|
||||
@@ -15,7 +15,7 @@ from homeassistant.helpers import config_validation as cv
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
REQUIREMENTS = ['pyfoscam==1.2']
|
||||
REQUIREMENTS = ['libpyfoscam==1.0']
|
||||
|
||||
CONF_IP = 'ip'
|
||||
|
||||
@@ -43,7 +43,7 @@ class FoscamCam(Camera):
|
||||
|
||||
def __init__(self, device_info):
|
||||
"""Initialize a Foscam camera."""
|
||||
from foscam import FoscamCamera
|
||||
from libpyfoscam import FoscamCamera
|
||||
|
||||
super(FoscamCam, self).__init__()
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ from homeassistant.core import callback
|
||||
from homeassistant.helpers.translation import async_get_translations
|
||||
from homeassistant.loader import bind_hass
|
||||
|
||||
REQUIREMENTS = ['home-assistant-frontend==20190202.0']
|
||||
REQUIREMENTS = ['home-assistant-frontend==20190203.0']
|
||||
|
||||
DOMAIN = 'frontend'
|
||||
DEPENDENCIES = ['api', 'websocket_api', 'http', 'system_log',
|
||||
|
||||
@@ -25,8 +25,7 @@ from .auth import setup_auth
|
||||
from .ban import setup_bans
|
||||
from .cors import setup_cors
|
||||
from .real_ip import setup_real_ip
|
||||
from .static import (
|
||||
CachingFileResponse, CachingStaticResource, staticresource_middleware)
|
||||
from .static import CachingFileResponse, CachingStaticResource
|
||||
|
||||
# Import as alias
|
||||
from .const import KEY_AUTHENTICATED, KEY_REAL_IP # noqa
|
||||
@@ -192,8 +191,7 @@ class HomeAssistantHTTP:
|
||||
use_x_forwarded_for, trusted_proxies, trusted_networks,
|
||||
login_threshold, is_ban_enabled, ssl_profile):
|
||||
"""Initialize the HTTP Home Assistant server."""
|
||||
app = self.app = web.Application(
|
||||
middlewares=[staticresource_middleware])
|
||||
app = self.app = web.Application(middlewares=[])
|
||||
|
||||
# This order matters
|
||||
setup_real_ip(app, use_x_forwarded_for, trusted_proxies)
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
"""Static file handling for HTTP component."""
|
||||
|
||||
import re
|
||||
|
||||
from aiohttp import hdrs
|
||||
from aiohttp.web import FileResponse, middleware
|
||||
from aiohttp.web import FileResponse
|
||||
from aiohttp.web_exceptions import HTTPNotFound
|
||||
from aiohttp.web_urldispatcher import StaticResource
|
||||
from yarl import URL
|
||||
|
||||
_FINGERPRINT = re.compile(r'^(.+)-[a-z0-9]{32}\.(\w+)$', re.IGNORECASE)
|
||||
|
||||
|
||||
class CachingStaticResource(StaticResource):
|
||||
"""Static Resource handler that will add cache headers."""
|
||||
@@ -56,19 +51,3 @@ class CachingFileResponse(FileResponse):
|
||||
|
||||
# Overwriting like this because __init__ can change implementation.
|
||||
self._sendfile = sendfile
|
||||
|
||||
|
||||
@middleware
|
||||
async def staticresource_middleware(request, handler):
|
||||
"""Middleware to strip out fingerprint from fingerprinted assets."""
|
||||
path = request.path
|
||||
if not path.startswith('/static/') and not path.startswith('/frontend'):
|
||||
return await handler(request)
|
||||
|
||||
fingerprinted = _FINGERPRINT.match(request.match_info['filename'])
|
||||
|
||||
if fingerprinted:
|
||||
request.match_info['filename'] = \
|
||||
'{}.{}'.format(*fingerprinted.groups())
|
||||
|
||||
return await handler(request)
|
||||
|
||||
@@ -19,7 +19,7 @@ from homeassistant.helpers.typing import ConfigType, HomeAssistantType
|
||||
from .config_flow import SmartThingsFlowHandler # noqa
|
||||
from .const import (
|
||||
CONF_APP_ID, CONF_INSTALLED_APP_ID, DATA_BROKERS, DATA_MANAGER, DOMAIN,
|
||||
SIGNAL_SMARTTHINGS_UPDATE, SUPPORTED_PLATFORMS)
|
||||
EVENT_BUTTON, SIGNAL_SMARTTHINGS_UPDATE, SUPPORTED_PLATFORMS)
|
||||
from .smartapp import (
|
||||
setup_smartapp, setup_smartapp_endpoint, validate_installed_app)
|
||||
|
||||
@@ -154,6 +154,19 @@ class DeviceBroker:
|
||||
continue
|
||||
device.status.apply_attribute_update(
|
||||
evt.component_id, evt.capability, evt.attribute, evt.value)
|
||||
|
||||
# Fire events for buttons
|
||||
if evt.capability == 'button' and evt.attribute == 'button':
|
||||
data = {
|
||||
'component_id': evt.component_id,
|
||||
'device_id': evt.device_id,
|
||||
'location_id': evt.location_id,
|
||||
'value': evt.value,
|
||||
'name': device.label
|
||||
}
|
||||
self._hass.bus.async_fire(EVENT_BUTTON, data)
|
||||
_LOGGER.debug("Fired button event: %s", data)
|
||||
|
||||
updated_devices.add(device.device_id)
|
||||
_LOGGER.debug("Update received with %s events and updated %s devices",
|
||||
len(req.events), len(updated_devices))
|
||||
|
||||
@@ -12,6 +12,7 @@ CONF_LOCATION_ID = 'location_id'
|
||||
DATA_MANAGER = 'manager'
|
||||
DATA_BROKERS = 'brokers'
|
||||
DOMAIN = 'smartthings'
|
||||
EVENT_BUTTON = "smartthings.button"
|
||||
SIGNAL_SMARTTHINGS_UPDATE = 'smartthings_update'
|
||||
SIGNAL_SMARTAPP_PREFIX = 'smartthings_smartap_'
|
||||
SETTINGS_INSTANCE_ID = "hassInstanceId"
|
||||
@@ -25,6 +26,7 @@ SUPPORTED_PLATFORMS = [
|
||||
]
|
||||
SUPPORTED_CAPABILITIES = [
|
||||
'accelerationSensor',
|
||||
'button',
|
||||
'colorControl',
|
||||
'colorTemperature',
|
||||
'contactSensor',
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"""Constants used by Home Assistant components."""
|
||||
MAJOR_VERSION = 0
|
||||
MINOR_VERSION = 87
|
||||
PATCH_VERSION = '0b2'
|
||||
PATCH_VERSION = '0b5'
|
||||
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
|
||||
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
|
||||
REQUIRED_PYTHON_VER = (3, 5, 3)
|
||||
|
||||
@@ -526,7 +526,7 @@ hole==0.3.0
|
||||
holidays==0.9.9
|
||||
|
||||
# homeassistant.components.frontend
|
||||
home-assistant-frontend==20190202.0
|
||||
home-assistant-frontend==20190203.0
|
||||
|
||||
# homeassistant.components.zwave
|
||||
homeassistant-pyozw==0.1.2
|
||||
@@ -605,6 +605,9 @@ libnacl==1.6.1
|
||||
# homeassistant.components.dyson
|
||||
libpurecoollink==0.4.2
|
||||
|
||||
# homeassistant.components.camera.foscam
|
||||
libpyfoscam==1.0
|
||||
|
||||
# homeassistant.components.device_tracker.mikrotik
|
||||
librouteros==2.2.0
|
||||
|
||||
@@ -1014,9 +1017,6 @@ pyflunearyou==1.0.1
|
||||
# homeassistant.components.light.futurenow
|
||||
pyfnip==0.2
|
||||
|
||||
# homeassistant.components.camera.foscam
|
||||
pyfoscam==1.2
|
||||
|
||||
# homeassistant.components.fritzbox
|
||||
pyfritzhome==0.4.0
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ hdate==0.8.7
|
||||
holidays==0.9.9
|
||||
|
||||
# homeassistant.components.frontend
|
||||
home-assistant-frontend==20190202.0
|
||||
home-assistant-frontend==20190203.0
|
||||
|
||||
# homeassistant.components.homekit_controller
|
||||
homekit==0.12.2
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
"""The test for the History Statistics sensor platform."""
|
||||
# pylint: disable=protected-access
|
||||
from datetime import timedelta
|
||||
from datetime import datetime, timedelta
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
import pytest
|
||||
import pytz
|
||||
from homeassistant.helpers import template
|
||||
|
||||
from homeassistant.const import STATE_UNKNOWN
|
||||
from homeassistant.setup import setup_component
|
||||
@@ -12,7 +15,6 @@ from homeassistant.helpers.template import Template
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from tests.common import init_recorder_component, get_test_home_assistant
|
||||
import pytest
|
||||
|
||||
|
||||
class TestHistoryStatsSensor(unittest.TestCase):
|
||||
@@ -50,19 +52,22 @@ class TestHistoryStatsSensor(unittest.TestCase):
|
||||
|
||||
def test_period_parsing(self):
|
||||
"""Test the conversion from templates to period."""
|
||||
today = Template('{{ now().replace(hour=0).replace(minute=0)'
|
||||
'.replace(second=0) }}', self.hass)
|
||||
duration = timedelta(hours=2, minutes=1)
|
||||
now = datetime(2019, 1, 1, 23, 30, 0, tzinfo=pytz.utc)
|
||||
with patch.dict(template.ENV.globals, {'now': lambda: now}):
|
||||
print(dt_util.now())
|
||||
today = Template('{{ now().replace(hour=0).replace(minute=0)'
|
||||
'.replace(second=0) }}', self.hass)
|
||||
duration = timedelta(hours=2, minutes=1)
|
||||
|
||||
sensor1 = HistoryStatsSensor(
|
||||
self.hass, 'test', 'on', today, None, duration, 'time', 'test')
|
||||
sensor2 = HistoryStatsSensor(
|
||||
self.hass, 'test', 'on', None, today, duration, 'time', 'test')
|
||||
sensor1 = HistoryStatsSensor(
|
||||
self.hass, 'test', 'on', today, None, duration, 'time', 'test')
|
||||
sensor2 = HistoryStatsSensor(
|
||||
self.hass, 'test', 'on', None, today, duration, 'time', 'test')
|
||||
|
||||
sensor1.update_period()
|
||||
sensor1_start, sensor1_end = sensor1._period
|
||||
sensor2.update_period()
|
||||
sensor2_start, sensor2_end = sensor2._period
|
||||
sensor1.update_period()
|
||||
sensor1_start, sensor1_end = sensor1._period
|
||||
sensor2.update_period()
|
||||
sensor2_start, sensor2_end = sensor2._period
|
||||
|
||||
# Start = 00:00:00
|
||||
assert sensor1_start.hour == 0
|
||||
|
||||
@@ -254,14 +254,16 @@ def device_factory_fixture():
|
||||
@pytest.fixture(name="event_factory")
|
||||
def event_factory_fixture():
|
||||
"""Fixture for creating mock devices."""
|
||||
def _factory(device_id, event_type="DEVICE_EVENT"):
|
||||
def _factory(device_id, event_type="DEVICE_EVENT", capability='',
|
||||
attribute='Updated', value='Value'):
|
||||
event = Mock()
|
||||
event.event_type = event_type
|
||||
event.device_id = device_id
|
||||
event.component_id = 'main'
|
||||
event.capability = ''
|
||||
event.attribute = 'Updated'
|
||||
event.value = 'Value'
|
||||
event.capability = capability
|
||||
event.attribute = attribute
|
||||
event.value = value
|
||||
event.location_id = str(uuid4())
|
||||
return event
|
||||
return _factory
|
||||
|
||||
@@ -269,11 +271,15 @@ def event_factory_fixture():
|
||||
@pytest.fixture(name="event_request_factory")
|
||||
def event_request_factory_fixture(event_factory):
|
||||
"""Fixture for creating mock smartapp event requests."""
|
||||
def _factory(device_ids):
|
||||
def _factory(device_ids=None, events=None):
|
||||
request = Mock()
|
||||
request.installed_app_id = uuid4()
|
||||
request.events = [event_factory(id) for id in device_ids]
|
||||
request.events.append(event_factory(uuid4()))
|
||||
request.events.append(event_factory(device_ids[0], event_type="OTHER"))
|
||||
if events is None:
|
||||
events = []
|
||||
if device_ids:
|
||||
events.extend([event_factory(id) for id in device_ids])
|
||||
events.append(event_factory(uuid4()))
|
||||
events.append(event_factory(device_ids[0], event_type="OTHER"))
|
||||
request.events = events
|
||||
return request
|
||||
return _factory
|
||||
|
||||
@@ -6,9 +6,10 @@ real HTTP calls are not initiated during testing.
|
||||
"""
|
||||
from pysmartthings import Attribute, Capability
|
||||
|
||||
from homeassistant.components.binary_sensor import DEVICE_CLASSES
|
||||
from homeassistant.components.smartthings import DeviceBroker, binary_sensor
|
||||
from homeassistant.components.smartthings.const import (
|
||||
DATA_BROKERS, DOMAIN, SIGNAL_SMARTTHINGS_UPDATE)
|
||||
DATA_BROKERS, DOMAIN, SIGNAL_SMARTTHINGS_UPDATE, SUPPORTED_CAPABILITIES)
|
||||
from homeassistant.config_entries import (
|
||||
CONN_CLASS_CLOUD_PUSH, SOURCE_USER, ConfigEntry)
|
||||
from homeassistant.const import ATTR_FRIENDLY_NAME
|
||||
@@ -32,6 +33,18 @@ async def _setup_platform(hass, *devices):
|
||||
return config_entry
|
||||
|
||||
|
||||
async def test_mapping_integrity():
|
||||
"""Test ensures the map dicts have proper integrity."""
|
||||
# Ensure every CAPABILITY_TO_ATTRIB key is in SUPPORTED_CAPABILITIES
|
||||
# Ensure every CAPABILITY_TO_ATTRIB value is in ATTRIB_TO_CLASS keys
|
||||
for capability, attrib in binary_sensor.CAPABILITY_TO_ATTRIB.items():
|
||||
assert capability in SUPPORTED_CAPABILITIES, capability
|
||||
assert attrib in binary_sensor.ATTRIB_TO_CLASS.keys(), attrib
|
||||
# Ensure every ATTRIB_TO_CLASS value is in DEVICE_CLASSES
|
||||
for device_class in binary_sensor.ATTRIB_TO_CLASS.values():
|
||||
assert device_class in DEVICE_CLASSES
|
||||
|
||||
|
||||
async def test_async_setup_platform():
|
||||
"""Test setup platform does nothing (it uses config entries)."""
|
||||
await binary_sensor.async_setup_platform(None, None, None)
|
||||
@@ -58,15 +71,15 @@ async def test_entity_and_device_attributes(hass, device_factory):
|
||||
# Act
|
||||
await _setup_platform(hass, device)
|
||||
# Assert
|
||||
entity = entity_registry.async_get('binary_sensor.motion_sensor_1_motion')
|
||||
assert entity
|
||||
assert entity.unique_id == device.device_id + '.' + Attribute.motion
|
||||
device_entry = device_registry.async_get_device(
|
||||
entry = entity_registry.async_get('binary_sensor.motion_sensor_1_motion')
|
||||
assert entry
|
||||
assert entry.unique_id == device.device_id + '.' + Attribute.motion
|
||||
entry = device_registry.async_get_device(
|
||||
{(DOMAIN, device.device_id)}, [])
|
||||
assert device_entry
|
||||
assert device_entry.name == device.label
|
||||
assert device_entry.model == device.device_type_name
|
||||
assert device_entry.manufacturer == 'Unavailable'
|
||||
assert entry
|
||||
assert entry.name == device.label
|
||||
assert entry.model == device.device_type_name
|
||||
assert entry.manufacturer == 'Unavailable'
|
||||
|
||||
|
||||
async def test_update_from_signal(hass, device_factory):
|
||||
|
||||
@@ -8,7 +8,8 @@ import pytest
|
||||
|
||||
from homeassistant.components import smartthings
|
||||
from homeassistant.components.smartthings.const import (
|
||||
DATA_BROKERS, DOMAIN, SIGNAL_SMARTTHINGS_UPDATE, SUPPORTED_PLATFORMS)
|
||||
DATA_BROKERS, DOMAIN, EVENT_BUTTON, SIGNAL_SMARTTHINGS_UPDATE,
|
||||
SUPPORTED_PLATFORMS)
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
|
||||
@@ -181,3 +182,31 @@ async def test_event_handler_ignores_other_installed_app(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert not called
|
||||
|
||||
|
||||
async def test_event_handler_fires_button_events(
|
||||
hass, device_factory, event_factory, event_request_factory):
|
||||
"""Test the event handler fires button events."""
|
||||
device = device_factory('Button 1', ['button'])
|
||||
event = event_factory(device.device_id, capability='button',
|
||||
attribute='button', value='pushed')
|
||||
request = event_request_factory(events=[event])
|
||||
called = False
|
||||
|
||||
def handler(evt):
|
||||
nonlocal called
|
||||
called = True
|
||||
assert evt.data == {
|
||||
'component_id': 'main',
|
||||
'device_id': device.device_id,
|
||||
'location_id': event.location_id,
|
||||
'value': 'pushed',
|
||||
'name': device.label
|
||||
}
|
||||
hass.bus.async_listen(EVENT_BUTTON, handler)
|
||||
broker = smartthings.DeviceBroker(
|
||||
hass, [device], request.installed_app_id)
|
||||
await broker.event_handler(request, None, None)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert called
|
||||
|
||||
Reference in New Issue
Block a user