Remove deprecated remote classes (#7011)
* Remove deprecated remote classes * Lint * Fix tests * Lintpull/6888/merge
parent
ab247b0f4d
commit
d081e5ab3a
|
@ -17,9 +17,9 @@ from homeassistant.bootstrap import ERROR_LOG_FILENAME
|
|||
from homeassistant.const import (
|
||||
EVENT_HOMEASSISTANT_STOP, EVENT_TIME_CHANGED,
|
||||
HTTP_BAD_REQUEST, HTTP_CREATED, HTTP_NOT_FOUND,
|
||||
HTTP_UNPROCESSABLE_ENTITY, MATCH_ALL, URL_API, URL_API_COMPONENTS,
|
||||
MATCH_ALL, URL_API, URL_API_COMPONENTS,
|
||||
URL_API_CONFIG, URL_API_DISCOVERY_INFO, URL_API_ERROR_LOG,
|
||||
URL_API_EVENT_FORWARD, URL_API_EVENTS, URL_API_SERVICES,
|
||||
URL_API_EVENTS, URL_API_SERVICES,
|
||||
URL_API_STATES, URL_API_STATES_ENTITY, URL_API_STREAM, URL_API_TEMPLATE,
|
||||
__version__)
|
||||
from homeassistant.exceptions import TemplateError
|
||||
|
@ -48,7 +48,6 @@ def setup(hass, config):
|
|||
hass.http.register_view(APIEventView)
|
||||
hass.http.register_view(APIServicesView)
|
||||
hass.http.register_view(APIDomainServicesView)
|
||||
hass.http.register_view(APIEventForwardingView)
|
||||
hass.http.register_view(APIComponentsView)
|
||||
hass.http.register_view(APITemplateView)
|
||||
|
||||
|
@ -319,79 +318,6 @@ class APIDomainServicesView(HomeAssistantView):
|
|||
return self.json(changed_states)
|
||||
|
||||
|
||||
class APIEventForwardingView(HomeAssistantView):
|
||||
"""View to handle EventForwarding requests."""
|
||||
|
||||
url = URL_API_EVENT_FORWARD
|
||||
name = "api:event-forward"
|
||||
event_forwarder = None
|
||||
|
||||
@asyncio.coroutine
|
||||
def post(self, request):
|
||||
"""Setup an event forwarder."""
|
||||
_LOGGER.warning('Event forwarding is deprecated. '
|
||||
'Will be removed by 0.43')
|
||||
hass = request.app['hass']
|
||||
try:
|
||||
data = yield from request.json()
|
||||
except ValueError:
|
||||
return self.json_message("No data received.", HTTP_BAD_REQUEST)
|
||||
|
||||
try:
|
||||
host = data['host']
|
||||
api_password = data['api_password']
|
||||
except KeyError:
|
||||
return self.json_message("No host or api_password received.",
|
||||
HTTP_BAD_REQUEST)
|
||||
|
||||
try:
|
||||
port = int(data['port']) if 'port' in data else None
|
||||
except ValueError:
|
||||
return self.json_message("Invalid value received for port.",
|
||||
HTTP_UNPROCESSABLE_ENTITY)
|
||||
|
||||
api = rem.API(host, api_password, port)
|
||||
|
||||
valid = yield from hass.loop.run_in_executor(
|
||||
None, api.validate_api)
|
||||
if not valid:
|
||||
return self.json_message("Unable to validate API.",
|
||||
HTTP_UNPROCESSABLE_ENTITY)
|
||||
|
||||
if self.event_forwarder is None:
|
||||
self.event_forwarder = rem.EventForwarder(hass)
|
||||
|
||||
self.event_forwarder.async_connect(api)
|
||||
|
||||
return self.json_message("Event forwarding setup.")
|
||||
|
||||
@asyncio.coroutine
|
||||
def delete(self, request):
|
||||
"""Remove event forwarder."""
|
||||
try:
|
||||
data = yield from request.json()
|
||||
except ValueError:
|
||||
return self.json_message("No data received.", HTTP_BAD_REQUEST)
|
||||
|
||||
try:
|
||||
host = data['host']
|
||||
except KeyError:
|
||||
return self.json_message("No host received.", HTTP_BAD_REQUEST)
|
||||
|
||||
try:
|
||||
port = int(data['port']) if 'port' in data else None
|
||||
except ValueError:
|
||||
return self.json_message("Invalid value received for port.",
|
||||
HTTP_UNPROCESSABLE_ENTITY)
|
||||
|
||||
if self.event_forwarder is not None:
|
||||
api = rem.API(host, None, port)
|
||||
|
||||
self.event_forwarder.async_disconnect(api)
|
||||
|
||||
return self.json_message("Event forwarding cancelled.")
|
||||
|
||||
|
||||
class APIComponentsView(HomeAssistantView):
|
||||
"""View to handle Components requests."""
|
||||
|
||||
|
|
|
@ -361,7 +361,6 @@ URL_API_EVENTS = '/api/events'
|
|||
URL_API_EVENTS_EVENT = '/api/events/{}'
|
||||
URL_API_SERVICES = '/api/services'
|
||||
URL_API_SERVICES_SERVICE = '/api/services/{}/{}'
|
||||
URL_API_EVENT_FORWARD = '/api/event_forwarding'
|
||||
URL_API_COMPONENTS = '/api/components'
|
||||
URL_API_ERROR_LOG = '/api/error_log'
|
||||
URL_API_LOG_OUT = '/api/log_out'
|
||||
|
|
|
@ -7,23 +7,19 @@ HomeAssistantError will be raised.
|
|||
For more details about the Python API, please refer to the documentation at
|
||||
https://home-assistant.io/developers/python_api/
|
||||
"""
|
||||
import asyncio
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from datetime import datetime
|
||||
import enum
|
||||
import json
|
||||
import logging
|
||||
import time
|
||||
import threading
|
||||
import urllib.parse
|
||||
|
||||
from typing import Optional
|
||||
|
||||
import requests
|
||||
|
||||
from homeassistant import setup, core as ha
|
||||
from homeassistant import core as ha
|
||||
from homeassistant.const import (
|
||||
HTTP_HEADER_HA_AUTH, SERVER_PORT, URL_API, URL_API_EVENT_FORWARD,
|
||||
HTTP_HEADER_HA_AUTH, SERVER_PORT, URL_API,
|
||||
URL_API_EVENTS, URL_API_EVENTS_EVENT, URL_API_SERVICES, URL_API_CONFIG,
|
||||
URL_API_SERVICES_SERVICE, URL_API_STATES, URL_API_STATES_ENTITY,
|
||||
HTTP_HEADER_CONTENT_TYPE, CONTENT_TYPE_JSON)
|
||||
|
@ -116,195 +112,6 @@ class API(object):
|
|||
self.base_url, 'yes' if self.api_password is not None else 'no')
|
||||
|
||||
|
||||
class HomeAssistant(ha.HomeAssistant):
|
||||
"""Home Assistant that forwards work."""
|
||||
|
||||
# pylint: disable=super-init-not-called
|
||||
def __init__(self, remote_api, local_api=None, loop=None):
|
||||
"""Initalize the forward instance."""
|
||||
_LOGGER.warning('Remote instances of Home Assistant are deprecated. '
|
||||
'Will be removed by 0.43')
|
||||
if not remote_api.validate_api():
|
||||
raise HomeAssistantError(
|
||||
"Remote API at {}:{} not valid: {}".format(
|
||||
remote_api.host, remote_api.port, remote_api.status))
|
||||
|
||||
self.remote_api = remote_api
|
||||
|
||||
self.loop = loop or asyncio.get_event_loop()
|
||||
self.executor = ThreadPoolExecutor(max_workers=5)
|
||||
self.loop.set_default_executor(self.executor)
|
||||
self.loop.set_exception_handler(ha.async_loop_exception_handler)
|
||||
self._pending_tasks = []
|
||||
self._pending_sheduler = None
|
||||
|
||||
self.bus = EventBus(remote_api, self)
|
||||
self.services = ha.ServiceRegistry(self)
|
||||
self.states = StateMachine(self.bus, self.loop, self.remote_api)
|
||||
self.config = ha.Config()
|
||||
# This is a dictionary that any component can store any data on.
|
||||
self.data = {}
|
||||
self.state = ha.CoreState.not_running
|
||||
self.exit_code = None
|
||||
self.config.api = local_api
|
||||
|
||||
def start(self):
|
||||
"""Start the instance."""
|
||||
# Ensure a local API exists to connect with remote
|
||||
if 'api' not in self.config.components:
|
||||
if not setup.setup_component(self, 'api'):
|
||||
raise HomeAssistantError(
|
||||
'Unable to setup local API to receive events')
|
||||
|
||||
self.state = ha.CoreState.starting
|
||||
# pylint: disable=protected-access
|
||||
ha._async_create_timer(self)
|
||||
|
||||
self.bus.fire(ha.EVENT_HOMEASSISTANT_START,
|
||||
origin=ha.EventOrigin.remote)
|
||||
|
||||
# Ensure local HTTP is started
|
||||
self.block_till_done()
|
||||
self.state = ha.CoreState.running
|
||||
time.sleep(0.05)
|
||||
|
||||
# Setup that events from remote_api get forwarded to local_api
|
||||
# Do this after we are running, otherwise HTTP is not started
|
||||
# or requests are blocked
|
||||
if not connect_remote_events(self.remote_api, self.config.api):
|
||||
raise HomeAssistantError((
|
||||
'Could not setup event forwarding from api {} to '
|
||||
'local api {}').format(self.remote_api, self.config.api))
|
||||
|
||||
def stop(self):
|
||||
"""Stop Home Assistant and shuts down all threads."""
|
||||
_LOGGER.info("Stopping")
|
||||
self.state = ha.CoreState.stopping
|
||||
|
||||
self.bus.fire(ha.EVENT_HOMEASSISTANT_STOP,
|
||||
origin=ha.EventOrigin.remote)
|
||||
|
||||
# Disconnect master event forwarding
|
||||
disconnect_remote_events(self.remote_api, self.config.api)
|
||||
self.state = ha.CoreState.not_running
|
||||
|
||||
|
||||
class EventBus(ha.EventBus):
|
||||
"""EventBus implementation that forwards fire_event to remote API."""
|
||||
|
||||
def __init__(self, api, hass):
|
||||
"""Initalize the eventbus."""
|
||||
super().__init__(hass)
|
||||
self._api = api
|
||||
|
||||
def fire(self, event_type, event_data=None, origin=ha.EventOrigin.local):
|
||||
"""Forward local events to remote target.
|
||||
|
||||
Handles remote event as usual.
|
||||
"""
|
||||
# All local events that are not TIME_CHANGED are forwarded to API
|
||||
if origin == ha.EventOrigin.local and \
|
||||
event_type != ha.EVENT_TIME_CHANGED:
|
||||
|
||||
fire_event(self._api, event_type, event_data)
|
||||
|
||||
else:
|
||||
super().fire(event_type, event_data, origin)
|
||||
|
||||
|
||||
class EventForwarder(object):
|
||||
"""Listens for events and forwards to specified APIs."""
|
||||
|
||||
def __init__(self, hass, restrict_origin=None):
|
||||
"""Initalize the event forwarder."""
|
||||
_LOGGER.warning('API forwarding is deprecated. '
|
||||
'Will be removed by 0.43')
|
||||
|
||||
self.hass = hass
|
||||
self.restrict_origin = restrict_origin
|
||||
|
||||
# We use a tuple (host, port) as key to ensure
|
||||
# that we do not forward to the same host twice
|
||||
self._targets = {}
|
||||
|
||||
self._lock = threading.Lock()
|
||||
self._async_unsub_listener = None
|
||||
|
||||
@ha.callback
|
||||
def async_connect(self, api):
|
||||
"""Attach to a Home Assistant instance and forward events.
|
||||
|
||||
Will overwrite old target if one exists with same host/port.
|
||||
"""
|
||||
if self._async_unsub_listener is None:
|
||||
self._async_unsub_listener = self.hass.bus.async_listen(
|
||||
ha.MATCH_ALL, self._event_listener)
|
||||
|
||||
key = (api.host, api.port)
|
||||
|
||||
self._targets[key] = api
|
||||
|
||||
@ha.callback
|
||||
def async_disconnect(self, api):
|
||||
"""Remove target from being forwarded to."""
|
||||
key = (api.host, api.port)
|
||||
|
||||
did_remove = self._targets.pop(key, None) is None
|
||||
|
||||
if len(self._targets) == 0:
|
||||
# Remove event listener if no forwarding targets present
|
||||
self._async_unsub_listener()
|
||||
self._async_unsub_listener = None
|
||||
|
||||
return did_remove
|
||||
|
||||
def _event_listener(self, event):
|
||||
"""Listen and forward all events."""
|
||||
with self._lock:
|
||||
# We don't forward time events or, if enabled, non-local events
|
||||
if event.event_type == ha.EVENT_TIME_CHANGED or \
|
||||
(self.restrict_origin and event.origin != self.restrict_origin):
|
||||
return
|
||||
|
||||
for api in self._targets.values():
|
||||
fire_event(api, event.event_type, event.data)
|
||||
|
||||
|
||||
class StateMachine(ha.StateMachine):
|
||||
"""Fire set events to an API. Uses state_change events to track states."""
|
||||
|
||||
def __init__(self, bus, loop, api):
|
||||
"""Initalize the statemachine."""
|
||||
super().__init__(bus, loop)
|
||||
self._api = api
|
||||
self.mirror()
|
||||
|
||||
bus.listen(ha.EVENT_STATE_CHANGED, self._state_changed_listener)
|
||||
|
||||
def remove(self, entity_id):
|
||||
"""Remove the state of an entity.
|
||||
|
||||
Returns boolean to indicate if an entity was removed.
|
||||
"""
|
||||
return remove_state(self._api, entity_id)
|
||||
|
||||
def set(self, entity_id, new_state, attributes=None, force_update=False):
|
||||
"""Call set_state on remote API."""
|
||||
set_state(self._api, entity_id, new_state, attributes, force_update)
|
||||
|
||||
def mirror(self):
|
||||
"""Discard current data and mirrors the remote state machine."""
|
||||
self._states = {state.entity_id: state for state
|
||||
in get_states(self._api)}
|
||||
|
||||
def _state_changed_listener(self, event):
|
||||
"""Listen for state changed events and applies them."""
|
||||
if event.data['new_state'] is None:
|
||||
self._states.pop(event.data['entity_id'], None)
|
||||
else:
|
||||
self._states[event.data['entity_id']] = event.data['new_state']
|
||||
|
||||
|
||||
class JSONEncoder(json.JSONEncoder):
|
||||
"""JSONEncoder that supports Home Assistant objects."""
|
||||
|
||||
|
@ -352,59 +159,6 @@ def validate_api(api):
|
|||
return APIStatus.CANNOT_CONNECT
|
||||
|
||||
|
||||
def connect_remote_events(from_api, to_api):
|
||||
"""Setup from_api to forward all events to to_api."""
|
||||
_LOGGER.warning('Event forwarding is deprecated. '
|
||||
'Will be removed by 0.43')
|
||||
data = {
|
||||
'host': to_api.host,
|
||||
'api_password': to_api.api_password,
|
||||
'port': to_api.port
|
||||
}
|
||||
|
||||
try:
|
||||
req = from_api(METHOD_POST, URL_API_EVENT_FORWARD, data)
|
||||
|
||||
if req.status_code == 200:
|
||||
return True
|
||||
else:
|
||||
_LOGGER.error(
|
||||
"Error setting up event forwarding: %s - %s",
|
||||
req.status_code, req.text)
|
||||
|
||||
return False
|
||||
|
||||
except HomeAssistantError:
|
||||
_LOGGER.exception("Error setting up event forwarding")
|
||||
return False
|
||||
|
||||
|
||||
def disconnect_remote_events(from_api, to_api):
|
||||
"""Disconnect forwarding events from from_api to to_api."""
|
||||
_LOGGER.warning('Event forwarding is deprecated. '
|
||||
'Will be removed by 0.43')
|
||||
data = {
|
||||
'host': to_api.host,
|
||||
'port': to_api.port
|
||||
}
|
||||
|
||||
try:
|
||||
req = from_api(METHOD_DELETE, URL_API_EVENT_FORWARD, data)
|
||||
|
||||
if req.status_code == 200:
|
||||
return True
|
||||
else:
|
||||
_LOGGER.error(
|
||||
"Error removing event forwarding: %s - %s",
|
||||
req.status_code, req.text)
|
||||
|
||||
return False
|
||||
|
||||
except HomeAssistantError:
|
||||
_LOGGER.exception("Error removing an event forwarder")
|
||||
return False
|
||||
|
||||
|
||||
def get_event_listeners(api):
|
||||
"""List of events that is being listened for."""
|
||||
try:
|
||||
|
|
|
@ -337,81 +337,6 @@ class TestAPI(unittest.TestCase):
|
|||
|
||||
self.assertEqual(400, req.status_code)
|
||||
|
||||
def test_api_event_forward(self):
|
||||
"""Test setting up event forwarding."""
|
||||
req = requests.post(
|
||||
_url(const.URL_API_EVENT_FORWARD),
|
||||
headers=HA_HEADERS)
|
||||
self.assertEqual(400, req.status_code)
|
||||
|
||||
req = requests.post(
|
||||
_url(const.URL_API_EVENT_FORWARD),
|
||||
data=json.dumps({'host': '127.0.0.1'}),
|
||||
headers=HA_HEADERS)
|
||||
self.assertEqual(400, req.status_code)
|
||||
|
||||
req = requests.post(
|
||||
_url(const.URL_API_EVENT_FORWARD),
|
||||
data=json.dumps({'api_password': 'bla-di-bla'}),
|
||||
headers=HA_HEADERS)
|
||||
self.assertEqual(400, req.status_code)
|
||||
|
||||
req = requests.post(
|
||||
_url(const.URL_API_EVENT_FORWARD),
|
||||
data=json.dumps({
|
||||
'api_password': 'bla-di-bla',
|
||||
'host': '127.0.0.1',
|
||||
'port': 'abcd'
|
||||
}),
|
||||
headers=HA_HEADERS)
|
||||
self.assertEqual(422, req.status_code)
|
||||
|
||||
req = requests.post(
|
||||
_url(const.URL_API_EVENT_FORWARD),
|
||||
data=json.dumps({
|
||||
'api_password': 'bla-di-bla',
|
||||
'host': '127.0.0.1',
|
||||
'port': get_test_instance_port()
|
||||
}),
|
||||
headers=HA_HEADERS)
|
||||
self.assertEqual(422, req.status_code)
|
||||
|
||||
# Setup a real one
|
||||
req = requests.post(
|
||||
_url(const.URL_API_EVENT_FORWARD),
|
||||
data=json.dumps({
|
||||
'api_password': API_PASSWORD,
|
||||
'host': '127.0.0.1',
|
||||
'port': SERVER_PORT
|
||||
}),
|
||||
headers=HA_HEADERS)
|
||||
self.assertEqual(200, req.status_code)
|
||||
|
||||
# Delete it again..
|
||||
req = requests.delete(
|
||||
_url(const.URL_API_EVENT_FORWARD),
|
||||
data=json.dumps({}),
|
||||
headers=HA_HEADERS)
|
||||
self.assertEqual(400, req.status_code)
|
||||
|
||||
req = requests.delete(
|
||||
_url(const.URL_API_EVENT_FORWARD),
|
||||
data=json.dumps({
|
||||
'host': '127.0.0.1',
|
||||
'port': 'abcd'
|
||||
}),
|
||||
headers=HA_HEADERS)
|
||||
self.assertEqual(422, req.status_code)
|
||||
|
||||
req = requests.delete(
|
||||
_url(const.URL_API_EVENT_FORWARD),
|
||||
data=json.dumps({
|
||||
'host': '127.0.0.1',
|
||||
'port': SERVER_PORT
|
||||
}),
|
||||
headers=HA_HEADERS)
|
||||
self.assertEqual(200, req.status_code)
|
||||
|
||||
def test_stream(self):
|
||||
"""Test the stream."""
|
||||
listen_count = self._listen_count()
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
"""Test Home Assistant remote methods and classes."""
|
||||
# pylint: disable=protected-access
|
||||
import asyncio
|
||||
import threading
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant import remote, setup, core as ha
|
||||
import homeassistant.components.http as http
|
||||
|
@ -11,18 +8,17 @@ from homeassistant.const import HTTP_HEADER_HA_AUTH, EVENT_STATE_CHANGED
|
|||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from tests.common import (
|
||||
get_test_instance_port, get_test_home_assistant, get_test_config_dir)
|
||||
get_test_instance_port, get_test_home_assistant)
|
||||
|
||||
API_PASSWORD = 'test1234'
|
||||
MASTER_PORT = get_test_instance_port()
|
||||
SLAVE_PORT = get_test_instance_port()
|
||||
BROKEN_PORT = get_test_instance_port()
|
||||
HTTP_BASE_URL = 'http://127.0.0.1:{}'.format(MASTER_PORT)
|
||||
|
||||
HA_HEADERS = {HTTP_HEADER_HA_AUTH: API_PASSWORD}
|
||||
|
||||
broken_api = remote.API('127.0.0.1', "bladybla", port=get_test_instance_port())
|
||||
hass, slave, master_api = None, None, None
|
||||
hass, master_api = None, None
|
||||
|
||||
|
||||
def _url(path=''):
|
||||
|
@ -32,8 +28,8 @@ def _url(path=''):
|
|||
|
||||
# pylint: disable=invalid-name
|
||||
def setUpModule():
|
||||
"""Initalization of a Home Assistant server and Slave instance."""
|
||||
global hass, slave, master_api
|
||||
"""Initalization of a Home Assistant server instance."""
|
||||
global hass, master_api
|
||||
|
||||
hass = get_test_home_assistant()
|
||||
|
||||
|
@ -51,30 +47,10 @@ def setUpModule():
|
|||
|
||||
master_api = remote.API('127.0.0.1', API_PASSWORD, MASTER_PORT)
|
||||
|
||||
# Start slave
|
||||
loop = asyncio.new_event_loop()
|
||||
|
||||
# FIXME: should not be a daemon
|
||||
threading.Thread(name='SlaveThread', daemon=True,
|
||||
target=loop.run_forever).start()
|
||||
|
||||
slave = remote.HomeAssistant(master_api, loop=loop)
|
||||
slave.async_track_tasks()
|
||||
slave.config.config_dir = get_test_config_dir()
|
||||
slave.config.skip_pip = True
|
||||
setup.setup_component(
|
||||
slave, http.DOMAIN,
|
||||
{http.DOMAIN: {http.CONF_API_PASSWORD: API_PASSWORD,
|
||||
http.CONF_SERVER_PORT: SLAVE_PORT}})
|
||||
|
||||
with patch.object(ha, '_async_create_timer', return_value=None):
|
||||
slave.start()
|
||||
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
def tearDownModule():
|
||||
"""Stop the Home Assistant server and slave."""
|
||||
slave.stop()
|
||||
"""Stop the Home Assistant server."""
|
||||
hass.stop()
|
||||
|
||||
|
||||
|
@ -83,7 +59,6 @@ class TestRemoteMethods(unittest.TestCase):
|
|||
|
||||
def tearDown(self):
|
||||
"""Stop everything that was started."""
|
||||
slave.block_till_done()
|
||||
hass.block_till_done()
|
||||
|
||||
def test_validate_api(self):
|
||||
|
@ -228,89 +203,3 @@ class TestRemoteMethods(unittest.TestCase):
|
|||
|
||||
now = dt_util.utcnow()
|
||||
self.assertEqual(now.isoformat(), ha_json_enc.default(now))
|
||||
|
||||
|
||||
class TestRemoteClasses(unittest.TestCase):
|
||||
"""Test the homeassistant.remote module."""
|
||||
|
||||
def tearDown(self):
|
||||
"""Stop everything that was started."""
|
||||
slave.block_till_done()
|
||||
hass.block_till_done()
|
||||
|
||||
def test_home_assistant_init(self):
|
||||
"""Test HomeAssistant init."""
|
||||
# Wrong password
|
||||
self.assertRaises(
|
||||
ha.HomeAssistantError, remote.HomeAssistant,
|
||||
remote.API('127.0.0.1', API_PASSWORD + 'A', 8124))
|
||||
|
||||
# Wrong port
|
||||
self.assertRaises(
|
||||
ha.HomeAssistantError, remote.HomeAssistant,
|
||||
remote.API('127.0.0.1', API_PASSWORD, BROKEN_PORT))
|
||||
|
||||
def test_statemachine_init(self):
|
||||
"""Test if remote.StateMachine copies all states on init."""
|
||||
self.assertEqual(sorted(hass.states.all()),
|
||||
sorted(slave.states.all()))
|
||||
|
||||
def test_statemachine_set(self):
|
||||
"""Test if setting the state on a slave is recorded."""
|
||||
slave.states.set("remote.test", "remote.statemachine test")
|
||||
|
||||
# Wait till slave tells master
|
||||
slave.block_till_done()
|
||||
# Wait till master gives updated state
|
||||
hass.block_till_done()
|
||||
|
||||
self.assertEqual("remote.statemachine test",
|
||||
slave.states.get("remote.test").state)
|
||||
|
||||
def test_statemachine_remove_from_master(self):
|
||||
"""Remove statemachine from master."""
|
||||
hass.states.set("remote.master_remove", "remove me!")
|
||||
hass.block_till_done()
|
||||
slave.block_till_done()
|
||||
|
||||
self.assertIn('remote.master_remove', slave.states.entity_ids())
|
||||
|
||||
hass.states.remove("remote.master_remove")
|
||||
hass.block_till_done()
|
||||
slave.block_till_done()
|
||||
|
||||
self.assertNotIn('remote.master_remove', slave.states.entity_ids())
|
||||
|
||||
def test_statemachine_remove_from_slave(self):
|
||||
"""Remove statemachine from slave."""
|
||||
hass.states.set("remote.slave_remove", "remove me!")
|
||||
hass.block_till_done()
|
||||
|
||||
self.assertIn('remote.slave_remove', slave.states.entity_ids())
|
||||
|
||||
self.assertTrue(slave.states.remove("remote.slave_remove"))
|
||||
slave.block_till_done()
|
||||
hass.block_till_done()
|
||||
|
||||
self.assertNotIn('remote.slave_remove', slave.states.entity_ids())
|
||||
|
||||
def test_eventbus_fire(self):
|
||||
"""Test if events fired from the eventbus get fired."""
|
||||
hass_call = []
|
||||
slave_call = []
|
||||
|
||||
hass.bus.listen("test.event_no_data", lambda _: hass_call.append(1))
|
||||
slave.bus.listen("test.event_no_data", lambda _: slave_call.append(1))
|
||||
slave.bus.fire("test.event_no_data")
|
||||
|
||||
# Wait till slave tells master
|
||||
slave.block_till_done()
|
||||
# Wait till master gives updated event
|
||||
hass.block_till_done()
|
||||
|
||||
self.assertEqual(1, len(hass_call))
|
||||
self.assertEqual(1, len(slave_call))
|
||||
|
||||
def test_get_config(self):
|
||||
"""Test the return of the configuration."""
|
||||
self.assertEqual(hass.config.as_dict(), remote.get_config(master_api))
|
||||
|
|
Loading…
Reference in New Issue