diff --git a/README.md b/README.md
index 5ae5de1cf84637376fe5f370166cecf18cd94c75..f52bc381f22e9b5e485e4a7d41227961c4a54da5 100644
--- a/README.md
+++ b/README.md
@@ -40,6 +40,86 @@ Installation instructions
 
 Done. Start it now by running `python start.py`
 
+Architecture
+------------
+The core of Home Assistant exists of three parts; an EventBus for firing events, a StateMachine that keeps track of the state of things and a ServiceRegistry to manage services.
+
+![home assistant architecture](https://raw.github.com/balloob/home-assistant/master/docs/architecture.png)
+
+For example to control the lights there are two components. One is the device_tracker that polls the wireless router for connected devices and updates the state of the tracked devices in the State Machine to be either 'Home' or 'Not Home'.
+
+When a state is changed a state_changed event is fired for which the device_sun_light_trigger component is listening. Based on the new state of the device combined with the state of the sun it will decide if it should turn the lights on or off:
+
+    In the event that the state of device 'Paulus Nexus 5' changes to the 'Home' state:
+      If the sun has set and the lights are not on:
+        Turn on the lights
+    
+    In the event that the combined state of all tracked devices changes to 'Not Home':
+      If the lights are on:
+        Turn off the lights
+        
+    In the event of the sun setting:
+      If the lights are off and the combined state of all tracked device equals 'Home':
+        Turn on the lights
+
+By using the Bus as a central communication hub between components it is easy to replace components or add functionality. For example if you would want to change the way devices are detected you only have to write a component that updates the device states in the State Machine.
+
+### Components
+
+**sun**
+Tracks the state of the sun and when the next sun rising and setting will occur.
+Depends on: latitude and longitude
+Action: maintains state of `weather.sun` including attributes `next_rising` and `next_setting`
+
+**device_tracker**
+Keeps track of which devices are currently home.
+Action: sets the state per device and maintains a combined state called `all_devices`. Keeps track of known devices in the file `known_devices.csv`. 
+
+**Light**
+Keeps track which lights are turned on and can control the lights.
+
+**WeMo**
+Keeps track which WeMo switches are in the network and allows you to control them.
+
+**device_sun_light_trigger**
+Turns lights on or off using a light control component based on state of the sun and devices that are home.
+Depends on: light control, track_sun, DeviceTracker
+Action: 
+ * Turns lights off when all devices leave home. 
+ * Turns lights on when a device is home while sun is setting. 
+ * Turns lights on when a device gets home after sun set.
+
+Registers services `light_control/turn_light_on` and `light_control/turn_light_off` to turn a or all lights on or off.
+
+Optional service data:
+  - `light_id` - only act on specific light. Else targets all.
+  - `transition_seconds` - seconds to take to swithc to new state.
+
+**chromecast**
+Registers three services to start playing YouTube video's on the ChromeCast.
+
+Service `chromecast/play_youtube_video` starts playing the specified video on the YouTube app on the ChromeCast. Specify video using `video` in service_data.
+
+Service `chromecast/start_fireplace` will start a YouTube movie simulating a fireplace and the `chromecast/start_epic_sax` service will start playing Epic Sax Guy 10h version.
+
+**media_buttons**
+Registers services that will simulate key presses on the keyboard. It currently offers the following Buttons as a Service (BaaS): `keyboard/volume_up`, `keyboard/volume_down` and `keyboard/media_play_pause`
+This actor depends on: PyUserInput
+
+**downloader**
+Registers service `downloader/download_file` that will download files. File to download is specified in the `url` field in the service data.
+
+**browser**
+Registers service `browser/browse_url` that opens `url` as specified in event_data in the system default browser.
+
+### Multiple connected instances
+
+Home Assistant supports running multiple synchronzied instances using a master-slave model. Slaves forward all local events fired and states set to the master instance which will then replicate it to each slave.
+
+Because each slave maintains it's own ServiceRegistry it is possible to have multiple slaves respond to one service call.
+
+![home assistant master-slave architecture](https://raw.github.com/balloob/home-assistant/master/docs/architecture-remote.png)
+
 Web interface and API
 ---------------------
 Home Assistent runs a webserver accessible on port 8123. 
@@ -50,6 +130,8 @@ Home Assistent runs a webserver accessible on port 8123.
 A screenshot of the debug interface:
 ![screenshot-debug-interface](https://raw.github.com/balloob/home-assistant/master/docs/screenshot-debug-interface.png)
 
+In the package `homeassistant.remote` a Python API on top of the HTTP API can be found.
+
 All API calls have to be accompanied by an 'api_password' parameter (as specified in `home-assistant.conf`) and will
 return JSON encoded objects. If successful calls will return status code 200 or 201.
 
@@ -61,19 +143,6 @@ Other status codes that can occur are:
 
 The api supports the following actions:
 
-**/api/states - GET**<br>
-Returns a list of entity ids for which a state is available
-
-```json
-{
-    "entity_ids": [
-        "Paulus_Nexus_4", 
-        "weather.sun", 
-        "all_devices"
-    ]
-}
-```
-
 **/api/events - GET**<br>
 Returns a dict with as keys the events and as value the number of listeners.
 
@@ -103,6 +172,29 @@ Returns a dict with as keys the domain and as value a list of published services
 }
 ```
 
+**/api/states - GET**<br>
+Returns a dict with as keys the entity_ids and as value the state.
+
+```json
+{
+    "sun.sun": {
+        "attributes": {
+            "next_rising": "07:04:15 29-10-2013", 
+            "next_setting": "18:00:31 29-10-2013"
+        }, 
+        "entity_id": "sun.sun", 
+        "last_changed": "23:24:33 28-10-2013", 
+        "state": "below_horizon"
+    },
+    "process.Dropbox": {
+        "attributes": {}, 
+        "entity_id": "process.Dropbox", 
+        "last_changed": "23:24:33 28-10-2013", 
+        "state": "on"
+    }
+}
+```
+
 **/api/states/&lt;entity_id>** - GET<br>
 Returns the current state from an entity
 
@@ -112,7 +204,7 @@ Returns the current state from an entity
         "next_rising": "07:04:15 29-10-2013", 
         "next_setting": "18:00:31 29-10-2013"
     }, 
-    "entity_id": "weather.sun", 
+    "entity_id": "sun.sun", 
     "last_changed": "23:24:33 28-10-2013", 
     "state": "below_horizon"
 }
@@ -155,6 +247,31 @@ optional parameter: service_data - JSON encoded object
 }
 ```
 
+**/api/event_forwarding** - POST<br>
+Setup event forwarding to another Home Assistant instance.<br>
+parameter: host - string<br>
+parameter: api_password - string<br>
+optional parameter: port - int<br>
+
+```json
+{
+    "message": "Event forwarding setup."
+}
+```
+
+**/api/event_forwarding** - DELETE<br>
+Cancel event forwarding to another Home Assistant instance.<br>
+parameter: host - string<br>
+optional parameter: port - int<br>
+
+If your client does not support DELETE HTTP requests you can add an optional attribute _METHOD and set its value to DELETE.
+
+```json
+{
+    "message": "Event forwarding cancelled."
+}
+```
+
 Android remote control
 ----------------------
 
@@ -166,75 +283,3 @@ An app has been built using [Tasker for Android](https://play.google.com/store/a
 The [APK](https://raw.github.com/balloob/home-assistant/master/android-tasker/Home_Assistant.apk) and [Tasker project XML](https://raw.github.com/balloob/home-assistant/master/android-tasker/Home_Assistant.prj.xml) can be found in [/android-tasker/](https://github.com/balloob/home-assistant/tree/master/android-tasker)
 
 ![screenshot-android-tasker.jpg](https://raw.github.com/balloob/home-assistant/master/docs/screenshot-android-tasker.png)
-
-Architecture
-------------
-The core of Home Assistant exists of two parts; a Bus for calling services and firing events and a State Machine that keeps track of the state of things.
-
-![screenshot-android-tasker.jpg](https://raw.github.com/balloob/home-assistant/master/docs/architecture.png)
-
-For example to control the lights there are two components. One is the device_tracker that polls the wireless router for connected devices and updates the state of the tracked devices in the State Machine to be either 'Home' or 'Not Home'.
-
-When a state is changed a state_changed event is fired for which the device_sun_light_trigger component is listening. Based on the new state of the device combined with the state of the sun it will decide if it should turn the lights on or off:
-
-    In the event that the state of device 'Paulus Nexus 5' changes to the 'Home' state:
-      If the sun has set and the lights are not on:
-        Turn on the lights
-    
-    In the event that the combined state of all tracked devices changes to 'Not Home':
-      If the lights are on:
-        Turn off the lights
-        
-    In the event of the sun setting:
-      If the lights are off and the combined state of all tracked device equals 'Home':
-        Turn on the lights
-
-By using the Bus as a central communication hub between components it is easy to replace components or add functionality. For example if you would want to change the way devices are detected you only have to write a component that updates the device states in the State Machine.
-
-### Components
-
-**sun**
-Tracks the state of the sun and when the next sun rising and setting will occur.
-Depends on: latitude and longitude
-Action: maintains state of `weather.sun` including attributes `next_rising` and `next_setting`
-
-**device_tracker**
-Keeps track of which devices are currently home.
-Action: sets the state per device and maintains a combined state called `all_devices`. Keeps track of known devices in the file `known_devices.csv`. 
-
-**Light**
-Keeps track which lights are turned on and can control the lights.
-
-**WeMo**
-Keeps track which WeMo switches are in the network and allows you to control them.
-
-**device_sun_light_trigger**
-Turns lights on or off using a light control component based on state of the sun and devices that are home.
-Depends on: light control, track_sun, DeviceTracker
-Action: 
- * Turns lights off when all devices leave home. 
- * Turns lights on when a device is home while sun is setting. 
- * Turns lights on when a device gets home after sun set.
-
-Registers services `light_control/turn_light_on` and `light_control/turn_light_off` to turn a or all lights on or off.
-
-Optional service data:
-  - `light_id` - only act on specific light. Else targets all.
-  - `transition_seconds` - seconds to take to swithc to new state.
-
-**chromecast**
-Registers three services to start playing YouTube video's on the ChromeCast.
-
-Service `chromecast/play_youtube_video` starts playing the specified video on the YouTube app on the ChromeCast. Specify video using `video` in service_data.
-
-Service `chromecast/start_fireplace` will start a YouTube movie simulating a fireplace and the `chromecast/start_epic_sax` service will start playing Epic Sax Guy 10h version.
-
-**media_buttons**
-Registers services that will simulate key presses on the keyboard. It currently offers the following Buttons as a Service (BaaS): `keyboard/volume_up`, `keyboard/volume_down` and `keyboard/media_play_pause`
-This actor depends on: PyUserInput
-
-**downloader**
-Registers service `downloader/download_file` that will download files. File to download is specified in the `url` field in the service data.
-
-**browser**
-Registers service `browser/browse_url` that opens `url` as specified in event_data in the system default browser.
diff --git a/docs/architecture-remote.png b/docs/architecture-remote.png
new file mode 100644
index 0000000000000000000000000000000000000000..3109c92184675a0542757e43a006fe019ae50b50
Binary files /dev/null and b/docs/architecture-remote.png differ
diff --git a/docs/architecture.png b/docs/architecture.png
index 927410ee87575f54c9608431a3f411b7cbecf180..8a53f65c7cac9e399f43b9b821d7c2d18a6a66f8 100644
Binary files a/docs/architecture.png and b/docs/architecture.png differ
diff --git a/home-assistant.conf.default b/home-assistant.conf.default
index d0ae2c4738c7bbbc86ed3c4e70256e45e2ddfb9f..5227d34ef9967538ebedfe9f584e21e09a4392a3 100644
--- a/home-assistant.conf.default
+++ b/home-assistant.conf.default
@@ -2,7 +2,7 @@
 latitude=32.87336
 longitude=-117.22743
 
-[httpinterface]
+[http]
 api_password=mypass
 
 [light.hue]
diff --git a/homeassistant/__init__.py b/homeassistant/__init__.py
index 75204036e17ac6087610d87c67b5ae3c3f3ea392..b796244250185197cd9e8eb4d88c3c05e8090b55 100644
--- a/homeassistant/__init__.py
+++ b/homeassistant/__init__.py
@@ -9,6 +9,7 @@ of entities and react to changes.
 import time
 import logging
 import threading
+import enum
 import datetime as dt
 import functools as ft
 
@@ -40,24 +41,21 @@ class HomeAssistant(object):
     """ Core class to route all communication to right components. """
 
     def __init__(self):
-        self._pool = pool = _create_worker_pool()
+        self._pool = pool = create_worker_pool()
 
         self.bus = EventBus(pool)
-        self.states = StateMachine(self.bus)
         self.services = ServiceRegistry(self.bus, pool)
+        self.states = StateMachine(self.bus)
 
-    def start(self, non_blocking=False):
-        """ Start home assistant.
-            Set non_blocking to True if you don't want this method to block
-            as long as Home Assistant is running. """
-
+    def start(self):
+        """ Start home assistant. """
         Timer(self)
 
         self.bus.fire(EVENT_HOMEASSISTANT_START)
 
-        if non_blocking:
-            return
-
+    def block_till_stopped(self):
+        """ Will register service homeassistant/stop and
+            will block until called. """
         request_shutdown = threading.Event()
 
         self.services.register(DOMAIN, SERVICE_HOMEASSISTANT_STOP,
@@ -96,6 +94,7 @@ class HomeAssistant(object):
         def state_listener(event):
             """ The listener that listens for specific state changes. """
             if entity_id == event.data['entity_id'] and \
+                    'old_state' in event.data and \
                     _matcher(event.data['old_state'].state, from_state) and \
                     _matcher(event.data['new_state'].state, to_state):
 
@@ -235,7 +234,7 @@ class JobPriority(util.OrderedEnum):
             return JobPriority.EVENT_DEFAULT
 
 
-def _create_worker_pool(thread_count=POOL_NUM_THREAD):
+def create_worker_pool(thread_count=POOL_NUM_THREAD):
     """ Creates a worker pool to be used. """
     logger = logging.getLogger(__name__)
 
@@ -264,22 +263,37 @@ def _create_worker_pool(thread_count=POOL_NUM_THREAD):
     return util.ThreadPool(thread_count, job_handler, busy_callback)
 
 
+class EventOrigin(enum.Enum):
+    """ Distinguish between origin of event. """
+    # pylint: disable=no-init
+
+    local = "LOCAL"
+    remote = "REMOTE"
+
+    def __str__(self):
+        return self.value
+
+
 # pylint: disable=too-few-public-methods
 class Event(object):
     """ Represents an event within the Bus. """
 
-    __slots__ = ['event_type', 'data']
+    __slots__ = ['event_type', 'data', 'origin']
 
-    def __init__(self, event_type, data=None):
+    def __init__(self, event_type, data=None, origin=EventOrigin.local):
         self.event_type = event_type
         self.data = data or {}
+        self.origin = origin
 
     def __repr__(self):
+        # pylint: disable=maybe-no-member
         if self.data:
-            return "<Event {}: {}>".format(
-                self.event_type, util.repr_helper(self.data))
+            return "<Event {}[{}]: {}>".format(
+                self.event_type, self.origin.value[0],
+                util.repr_helper(self.data))
         else:
-            return "<Event {}>".format(self.event_type)
+            return "<Event {}[{}]>".format(self.event_type,
+                                           self.origin.value[0])
 
 
 class EventBus(object):
@@ -291,7 +305,7 @@ class EventBus(object):
         self._listeners = {}
         self._logger = logging.getLogger(__name__)
         self._lock = threading.Lock()
-        self._pool = pool or _create_worker_pool()
+        self._pool = pool or create_worker_pool()
 
     @property
     def listeners(self):
@@ -302,7 +316,7 @@ class EventBus(object):
             return {key: len(self._listeners[key])
                     for key in self._listeners}
 
-    def fire(self, event_type, event_data=None):
+    def fire(self, event_type, event_data=None, origin=EventOrigin.local):
         """ Fire an event. """
         with self._lock:
             # Copy the list of the current listeners because some listeners
@@ -311,7 +325,7 @@ class EventBus(object):
             get = self._listeners.get
             listeners = get(MATCH_ALL, []) + get(event_type, [])
 
-            event = Event(event_type, event_data)
+            event = Event(event_type, event_data, origin)
 
             self._logger.info("Bus:Handling {}".format(event))
 
@@ -390,7 +404,9 @@ class State(object):
         """ Static method to create a state from a dict.
         Ensures: state == State.from_json_dict(state.to_json_dict()) """
 
-        if 'entity_id' not in json_dict and 'state' not in json_dict:
+        if not (json_dict and
+                'entity_id' in json_dict and
+                'state' in json_dict):
             return None
 
         last_changed = json_dict.get('last_changed')
@@ -429,6 +445,11 @@ class StateMachine(object):
         """ List of entity ids that are being tracked. """
         return list(self._states.keys())
 
+    def all(self):
+        """ Returns a dict mapping all entity_ids to their state. """
+        return {entity_id: state.copy() for entity_id, state
+                in self._states.items()}
+
     def get(self, entity_id):
         """ Returns the state of the specified entity. """
         state = self._states.get(entity_id)
@@ -456,24 +477,22 @@ class StateMachine(object):
         attributes = attributes or {}
 
         with self._lock:
-            if entity_id in self._states:
-                old_state = self._states[entity_id]
+            old_state = self._states.get(entity_id)
 
-                if old_state.state != new_state or \
-                   old_state.attributes != attributes:
+            # If state did not exist or is different, set it
+            if not old_state or \
+               old_state.state != new_state or \
+               old_state.attributes != attributes:
 
-                    state = self._states[entity_id] = \
-                        State(entity_id, new_state, attributes)
+                state = self._states[entity_id] = \
+                    State(entity_id, new_state, attributes)
 
-                    self._bus.fire(EVENT_STATE_CHANGED,
-                                   {'entity_id': entity_id,
-                                    'old_state': old_state,
-                                    'new_state': state})
+                event_data = {'entity_id': entity_id, 'new_state': state}
 
-            else:
-                # If state did not exist yet
-                self._states[entity_id] = State(entity_id, new_state,
-                                                attributes)
+                if old_state:
+                    event_data['old_state'] = old_state
+
+                self._bus.fire(EVENT_STATE_CHANGED, event_data)
 
 
 # pylint: disable=too-few-public-methods
@@ -501,7 +520,7 @@ class ServiceRegistry(object):
     def __init__(self, bus, pool=None):
         self._services = {}
         self._lock = threading.Lock()
-        self._pool = pool or _create_worker_pool()
+        self._pool = pool or create_worker_pool()
         bus.listen(EVENT_CALL_SERVICE, self._event_to_service_call)
 
     @property
diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py
index 7f63d72596420f9d4acaf18c930d159bf8cc48ab..5d089aa31c63365d4f5e2a1ea430619f01323b1d 100644
--- a/homeassistant/bootstrap.py
+++ b/homeassistant/bootstrap.py
@@ -194,13 +194,12 @@ def from_config_file(config_path, enable_logging=True):
         add_status("Keyboard", load_module('keyboard').setup(hass))
 
     # Init HTTP interface
-    if has_opt("httpinterface", "api_password"):
-        httpinterface = load_module('httpinterface')
+    if has_opt("http", "api_password"):
+        http = load_module('http')
 
-        httpinterface.HTTPInterface(
-            hass, get_opt("httpinterface", "api_password"))
+        http.setup(hass, get_opt("http", "api_password"))
 
-        add_status("HTTPInterface", True)
+        add_status("HTTP", True)
 
     # Init groups
     if has_section("group"):
diff --git a/homeassistant/components/httpinterface/__init__.py b/homeassistant/components/http/__init__.py
similarity index 80%
rename from homeassistant/components/httpinterface/__init__.py
rename to homeassistant/components/http/__init__.py
index be20e5be228c56305d2a0d137e4d99b14731aba0..2cd5a67f3f4edaab739cb98904bc77d78d76a3bd 100644
--- a/homeassistant/components/httpinterface/__init__.py
+++ b/homeassistant/components/http/__init__.py
@@ -73,13 +73,13 @@ import logging
 import re
 import os
 from http.server import BaseHTTPRequestHandler, HTTPServer
+from socketserver import ThreadingMixIn
 from urllib.parse import urlparse, parse_qs
 
 import homeassistant as ha
+import homeassistant.remote as rem
 import homeassistant.util as util
 
-SERVER_PORT = 8123
-
 HTTP_OK = 200
 HTTP_CREATED = 201
 HTTP_MOVED_PERMANENTLY = 301
@@ -92,46 +92,49 @@ HTTP_UNPROCESSABLE_ENTITY = 422
 URL_ROOT = "/"
 URL_CHANGE_STATE = "/change_state"
 URL_FIRE_EVENT = "/fire_event"
-
-URL_API_STATES = "/api/states"
-URL_API_STATES_ENTITY = "/api/states/{}"
-URL_API_EVENTS = "/api/events"
-URL_API_EVENTS_EVENT = "/api/events/{}"
-URL_API_SERVICES = "/api/services"
-URL_API_SERVICES_SERVICE = "/api/services/{}/{}"
+URL_CALL_SERVICE = "/call_service"
 
 URL_STATIC = "/static/{}"
 
 
-class HTTPInterface(threading.Thread):
-    """ Provides an HTTP interface for Home Assistant. """
+def setup(hass, api_password, server_port=None, server_host=None):
+    """ Sets up the HTTP API and debug interface. """
+    server_port = server_port or rem.SERVER_PORT
+
+    # If no server host is given, accept all incoming requests
+    server_host = server_host or '0.0.0.0'
 
-    # pylint: disable=too-many-arguments
-    def __init__(self, hass, api_password, server_port=None, server_host=None):
-        threading.Thread.__init__(self)
+    server = HomeAssistantHTTPServer((server_host, server_port),
+                                     RequestHandler, hass, api_password)
 
-        self.daemon = True
+    hass.listen_once_event(
+        ha.EVENT_HOMEASSISTANT_START,
+        lambda event:
+        threading.Thread(target=server.start, daemon=True).start())
 
-        server_port = server_port or SERVER_PORT
 
-        # If no server host is given, accept all incoming requests
-        server_host = server_host or '0.0.0.0'
+class HomeAssistantHTTPServer(ThreadingMixIn, HTTPServer):
+    """ Handle HTTP requests in a threaded fashion. """
 
-        self.server = HTTPServer((server_host, server_port), RequestHandler)
+    def __init__(self, server_address, RequestHandlerClass,
+                 hass, api_password):
+        super().__init__(server_address, RequestHandlerClass)
 
-        self.server.flash_message = None
-        self.server.logger = logging.getLogger(__name__)
-        self.server.hass = hass
-        self.server.api_password = api_password
+        self.hass = hass
+        self.api_password = api_password
+        self.logger = logging.getLogger(__name__)
 
-        hass.listen_once_event(ha.EVENT_HOMEASSISTANT_START,
-                               lambda event: self.start())
+        # To store flash messages between sessions
+        self.flash_message = None
 
-    def run(self):
-        """ Start the HTTP interface. """
-        self.server.logger.info("Starting")
+        # We will lazy init this one if needed
+        self.event_forwarder = None
 
-        self.server.serve_forever()
+    def start(self):
+        """ Starts the server. """
+        self.logger.info("Starting")
+
+        self.serve_forever()
 
 
 # pylint: disable=too-many-public-methods
@@ -139,13 +142,15 @@ class RequestHandler(BaseHTTPRequestHandler):
     """ Handles incoming HTTP requests """
 
     PATHS = [  # debug interface
-        ('GET', '/', '_handle_get_root'),
-        ('POST', re.compile(r'/change_state'), '_handle_change_state'),
-        ('POST', re.compile(r'/fire_event'), '_handle_fire_event'),
-        ('POST', re.compile(r'/call_service'), '_handle_call_service'),
+        ('GET', URL_ROOT, '_handle_get_root'),
+        # These get compiled as RE because these methods are reused
+        # by other urls that use url parameters
+        ('POST', re.compile(URL_CHANGE_STATE), '_handle_change_state'),
+        ('POST', re.compile(URL_FIRE_EVENT), '_handle_fire_event'),
+        ('POST', re.compile(URL_CALL_SERVICE), '_handle_call_service'),
 
         # /states
-        ('GET', '/api/states', '_handle_get_api_states'),
+        ('GET', rem.URL_API_STATES, '_handle_get_api_states'),
         ('GET',
          re.compile(r'/api/states/(?P<entity_id>[a-zA-Z\._0-9]+)'),
          '_handle_get_api_states_entity'),
@@ -154,19 +159,24 @@ class RequestHandler(BaseHTTPRequestHandler):
          '_handle_change_state'),
 
         # /events
-        ('GET', '/api/events', '_handle_get_api_events'),
+        ('GET', rem.URL_API_EVENTS, '_handle_get_api_events'),
         ('POST',
          re.compile(r'/api/events/(?P<event_type>[a-zA-Z\._0-9]+)'),
          '_handle_fire_event'),
 
         # /services
-        ('GET', '/api/services', '_handle_get_api_services'),
+        ('GET', rem.URL_API_SERVICES, '_handle_get_api_services'),
         ('POST',
          re.compile((r'/api/services/'
                      r'(?P<domain>[a-zA-Z\._0-9]+)/'
                      r'(?P<service>[a-zA-Z\._0-9]+)')),
          '_handle_call_service'),
 
+        # /event_forwarding
+        ('POST', rem.URL_API_EVENT_FORWARD, '_handle_post_api_event_forward'),
+        ('DELETE', rem.URL_API_EVENT_FORWARD,
+            '_handle_delete_api_event_forward'),
+
         # Statis files
         ('GET', re.compile(r'/static/(?P<file>[a-zA-Z\._\-0-9/]+)'),
          '_handle_get_static')
@@ -193,6 +203,9 @@ class RequestHandler(BaseHTTPRequestHandler):
         except KeyError:
             api_password = ''
 
+        if '_METHOD' in data:
+            method = data['_METHOD'][0]
+
         if url.path.startswith('/api/'):
             self.use_json = True
 
@@ -327,11 +340,9 @@ class RequestHandler(BaseHTTPRequestHandler):
                "<th>Attributes</th><th>Last Changed</th>"
                "</tr>").format(self.server.api_password))
 
-        for entity_id in \
-            sorted(self.server.hass.states.entity_ids,
-                   key=lambda key: key.lower()):
-
-            state = self.server.hass.states.get(entity_id)
+        for entity_id, state in \
+            sorted(self.server.hass.states.all().items(),
+                   key=lambda item: item[0].lower()):
 
             attributes = "<br>".join(
                 ["{}: {}".format(attr, state.attributes[attr])
@@ -512,7 +523,7 @@ class RequestHandler(BaseHTTPRequestHandler):
                 self._write_json(state.as_dict(),
                                  status_code=HTTP_CREATED,
                                  location=
-                                 URL_API_STATES_ENTITY.format(entity_id))
+                                 rem.URL_API_STATES_ENTITY.format(entity_id))
             else:
                 self._message(
                     "State of {} changed to {}".format(entity_id, new_state))
@@ -534,21 +545,33 @@ class RequestHandler(BaseHTTPRequestHandler):
         This handles the following paths:
         /fire_event
         /api/events/<event_type>
+
+        Events from /api are threated as remote events.
         """
         try:
             try:
                 event_type = path_match.group('event_type')
+                event_origin = ha.EventOrigin.remote
             except IndexError:
                 # If group event_type does not exist in path_match
                 event_type = data['event_type'][0]
+                event_origin = ha.EventOrigin.local
 
-            try:
+            if 'event_data' in data:
                 event_data = json.loads(data['event_data'][0])
-            except KeyError:
-                # Happens if key 'event_data' does not exist
+            else:
                 event_data = None
 
-            self.server.hass.bus.fire(event_type, event_data)
+            # Special case handling for event STATE_CHANGED
+            # We will try to convert state dicts back to State objects
+            if event_type == ha.EVENT_STATE_CHANGED and event_data:
+                for key in ('old_state', 'new_state'):
+                    state = ha.State.from_dict(event_data.get(key))
+
+                    if state:
+                        event_data[key] = state
+
+            self.server.hass.bus.fire(event_type, event_data, event_origin)
 
             self._message("Event {} fired.".format(event_type))
 
@@ -598,9 +621,8 @@ class RequestHandler(BaseHTTPRequestHandler):
 
     # pylint: disable=unused-argument
     def _handle_get_api_states(self, path_match, data):
-        """ Returns the entitie ids which state are being tracked. """
-        self._write_json(
-            {'entity_ids': list(self.server.hass.states.entity_ids)})
+        """ Returns a dict containing all entity ids and their state. """
+        self._write_json(self.server.hass.states.all())
 
     # pylint: disable=unused-argument
     def _handle_get_api_states_entity(self, path_match, data):
@@ -609,10 +631,9 @@ class RequestHandler(BaseHTTPRequestHandler):
 
         state = self.server.hass.states.get(entity_id)
 
-        try:
-            self._write_json(state.as_dict())
-        except AttributeError:
-            # If state for entity_id does not exist
+        if state:
+            self._write_json(state)
+        else:
             self._message("State does not exist.", HTTP_UNPROCESSABLE_ENTITY)
 
     def _handle_get_api_events(self, path_match, data):
@@ -623,6 +644,60 @@ class RequestHandler(BaseHTTPRequestHandler):
         """ Handles getting overview of services. """
         self._write_json({'services': self.server.hass.services.services})
 
+    def _handle_post_api_event_forward(self, path_match, data):
+        """ Handles adding an event forwarding target. """
+
+        try:
+            host = data['host'][0]
+            api_password = data['api_password'][0]
+
+            port = int(data['port'][0]) if 'port' in data else None
+
+            if self.server.event_forwarder is None:
+                self.server.event_forwarder = \
+                    rem.EventForwarder(self.server.hass)
+
+            api = rem.API(host, api_password, port)
+
+            self.server.event_forwarder.connect(api)
+
+            self._message("Event forwarding setup.")
+
+        except KeyError:
+            # Occurs if domain or service does not exist in data
+            self._message("No host or api_password received.",
+                          HTTP_BAD_REQUEST)
+
+        except ValueError:
+            # Occurs during error parsing port
+            self._message(
+                "Invalid value received for port", HTTP_UNPROCESSABLE_ENTITY)
+
+    def _handle_delete_api_event_forward(self, path_match, data):
+        """ Handles deleting an event forwarding target. """
+
+        try:
+            host = data['host'][0]
+
+            port = int(data['port'][0]) if 'port' in data else None
+
+            if self.server.event_forwarder is not None:
+                api = rem.API(host, None, port)
+
+                self.server.event_forwarder.disconnect(api)
+
+            self._message("Event forwarding cancelled.")
+
+        except KeyError:
+            # Occurs if domain or service does not exist in data
+            self._message("No host or api_password received.",
+                          HTTP_BAD_REQUEST)
+
+        except ValueError:
+            # Occurs during error parsing port
+            self._message(
+                "Invalid value received for port", HTTP_UNPROCESSABLE_ENTITY)
+
     def _handle_get_static(self, path_match, data):
         """ Returns a static file. """
         req_file = util.sanitize_filename(path_match.group('file'))
@@ -680,4 +755,5 @@ class RequestHandler(BaseHTTPRequestHandler):
 
         if data:
             self.wfile.write(
-                json.dumps(data, indent=4, sort_keys=True).encode("UTF-8"))
+                json.dumps(data, indent=4, sort_keys=True,
+                           cls=rem.JSONEncoder).encode("UTF-8"))
diff --git a/homeassistant/components/httpinterface/www_static/favicon.ico b/homeassistant/components/http/www_static/favicon.ico
similarity index 100%
rename from homeassistant/components/httpinterface/www_static/favicon.ico
rename to homeassistant/components/http/www_static/favicon.ico
diff --git a/homeassistant/components/httpinterface/www_static/style.css b/homeassistant/components/http/www_static/style.css
similarity index 100%
rename from homeassistant/components/httpinterface/www_static/style.css
rename to homeassistant/components/http/www_static/style.css
diff --git a/homeassistant/remote.py b/homeassistant/remote.py
index 26641b113c994510c2ab7544b7972c60fda5cbe8..b5f246205086679a52f55b487cf41ad751fa7541 100644
--- a/homeassistant/remote.py
+++ b/homeassistant/remote.py
@@ -17,24 +17,37 @@ import urllib.parse
 import requests
 
 import homeassistant as ha
-import homeassistant.components.httpinterface as hah
+
+SERVER_PORT = 8123
+
+URL_API_STATES = "/api/states"
+URL_API_STATES_ENTITY = "/api/states/{}"
+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"
 
 METHOD_GET = "get"
 METHOD_POST = "post"
 
 
-def _setup_call_api(host, port, api_password):
-    """ Helper method to setup a call api method. """
-    port = port or hah.SERVER_PORT
+class API(object):
+    """ Object to pass around Home Assistant API location and credentials. """
+    # pylint: disable=too-few-public-methods
 
-    base_url = "http://{}:{}".format(host, port)
+    def __init__(self, host, api_password, port=None):
+        self.host = host
+        self.port = port or SERVER_PORT
+        self.api_password = api_password
+        self.base_url = "http://{}:{}".format(host, self.port)
 
-    def _call_api(method, path, data=None):
+    def __call__(self, method, path, data=None):
         """ Makes a call to the Home Assistant api. """
         data = data or {}
-        data['api_password'] = api_password
+        data['api_password'] = self.api_password
 
-        url = urllib.parse.urljoin(base_url, path)
+        url = urllib.parse.urljoin(self.base_url, path)
 
         try:
             if method == METHOD_GET:
@@ -46,7 +59,134 @@ def _setup_call_api(host, port, api_password):
             logging.getLogger(__name__).exception("Error connecting to server")
             raise ha.HomeAssistantError("Error connecting to server")
 
-    return _call_api
+
+class HomeAssistant(ha.HomeAssistant):
+    """ Home Assistant that forwards work. """
+    # pylint: disable=super-init-not-called
+
+    def __init__(self, local_api, remote_api):
+        self.local_api = local_api
+        self.remote_api = remote_api
+
+        self._pool = pool = ha.create_worker_pool()
+
+        self.bus = EventBus(remote_api, pool)
+        self.services = ha.ServiceRegistry(self.bus, pool)
+        self.states = StateMachine(self.bus, self.remote_api)
+
+    def start(self):
+        ha.Timer(self)
+
+        # Setup that events from remote_api get forwarded to local_api
+        connect_remote_events(self.remote_api, self.local_api)
+
+        self.bus.fire(ha.EVENT_HOMEASSISTANT_START,
+                      origin=ha.EventOrigin.remote)
+
+
+class EventBus(ha.EventBus):
+    """ EventBus implementation that forwards fire_event to remote API. """
+
+    def __init__(self, api, pool=None):
+        super().__init__(pool)
+        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):
+        self.hass = hass
+        self.restrict_origin = restrict_origin
+        self.logger = logging.getLogger(__name__)
+
+        # 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()
+
+    def connect(self, api):
+        """
+        Attach to a HA instance and forward events.
+
+        Will overwrite old target if one exists with same host/port.
+        """
+        with self._lock:
+            if len(self._targets) == 0:
+                # First target we get, setup listener for events
+                self.hass.bus.listen(ha.MATCH_ALL, self._event_listener)
+
+            key = (api.host, api.port)
+
+            self._targets[key] = api
+
+    def disconnect(self, api):
+        """ Removes target from being forwarded to. """
+        with self._lock:
+            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.hass.bus.remove_listener(ha.MATCH_ALL,
+                                              self._event_listener)
+
+            return did_remove
+
+    def _event_listener(self, event):
+        """ Listen and forwards 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, self.logger)
+
+
+class StateMachine(ha.StateMachine):
+    """
+    Fires set events to an API.
+    Uses state_change events to track states.
+    """
+
+    def __init__(self, bus, api):
+        super().__init__(None)
+
+        self.logger = logging.getLogger(__name__)
+
+        self._api = api
+
+        self.mirror()
+
+        bus.listen(ha.EVENT_STATE_CHANGED, self._state_changed_listener)
+
+    def set(self, entity_id, new_state, attributes=None):
+        """ Calls set_state on remote API . """
+        set_state(self._api, entity_id, new_state, attributes)
+
+    def mirror(self):
+        """ Discards current data and mirrors the remote state machine. """
+        self._states = get_states(self._api, self.logger)
+
+    def _state_changed_listener(self, event):
+        """ Listens for state changed events and applies them. """
+        self._states[event.data['entity_id']] = event.data['new_state']
 
 
 class JSONEncoder(json.JSONEncoder):
@@ -61,212 +201,168 @@ class JSONEncoder(json.JSONEncoder):
         return json.JSONEncoder.default(self, obj)
 
 
-class EventBus(object):
-    """ Allows to interface with a Home Assistant EventBus via the API. """
+def connect_remote_events(from_api, to_api):
+    """ Sets up from_api to forward all events to to_api. """
 
-    def __init__(self, host, api_password, port=None):
-        self.logger = logging.getLogger(__name__)
+    data = {'host': to_api.host, 'api_password': to_api.api_password}
 
-        self._call_api = _setup_call_api(host, port, api_password)
+    if to_api.port is not None:
+        data['port'] = to_api.port
 
-    @property
-    def listeners(self):
-        """ List of events that is being listened for. """
-        try:
-            req = self._call_api(METHOD_GET, hah.URL_API_EVENTS)
+    try:
+        from_api(METHOD_POST, URL_API_EVENT_FORWARD, data)
 
-            if req.status_code == 200:
-                data = req.json()
+    except ha.HomeAssistantError:
+        pass
 
-                return data['event_listeners']
-
-            else:
-                raise ha.HomeAssistantError(
-                    "Got unexpected result (3): {}.".format(req.text))
 
-        except ValueError:  # If req.json() can't parse the json
-            self.logger.exception("Bus:Got unexpected result")
-            raise ha.HomeAssistantError(
-                "Got unexpected result: {}".format(req.text))
-
-        except KeyError:  # If not all expected keys are in the returned JSON
-            self.logger.exception("Bus:Got unexpected result (2)")
-            raise ha.HomeAssistantError(
-                "Got unexpected result (2): {}".format(req.text))
-
-    def fire(self, event_type, event_data=None):
-        """ Fire an event. """
-
-        if event_data:
-            data = {'event_data': json.dumps(event_data, cls=JSONEncoder)}
-        else:
-            data = None
+def disconnect_remote_events(from_api, to_api):
+    """ Disconnects forwarding events from from_api to to_api. """
+    data = {'host': to_api.host, '_METHOD': 'DELETE'}
 
-        req = self._call_api(METHOD_POST,
-                             hah.URL_API_EVENTS_EVENT.format(event_type),
-                             data)
+    if to_api.port is not None:
+        data['port'] = to_api.port
 
-        if req.status_code != 200:
-            error = "Error firing event: {} - {}".format(
-                    req.status_code, req.text)
+    try:
+        from_api(METHOD_POST, URL_API_EVENT_FORWARD, data)
 
-            self.logger.error("Bus:{}".format(error))
-            raise ha.HomeAssistantError(error)
+    except ha.HomeAssistantError:
+        pass
 
 
-class StateMachine(object):
-    """ Allows to interface with a Home Assistant StateMachine via the API. """
+def get_event_listeners(api, logger=None):
+    """ List of events that is being listened for. """
+    try:
+        req = api(METHOD_GET, URL_API_EVENTS)
 
-    def __init__(self, host, api_password, port=None):
-        self._call_api = _setup_call_api(host, port, api_password)
+        return req.json()['event_listeners'] if req.status_code == 200 else {}
 
-        self.lock = threading.Lock()
-        self.logger = logging.getLogger(__name__)
+    except (ha.HomeAssistantError, ValueError, KeyError):
+        # ValueError if req.json() can't parse the json
+        # KeyError if 'event_listeners' not found in parsed json
+        if logger:
+            logger.exception("Bus:Got unexpected result")
 
-    @property
-    def entity_ids(self):
-        """ List of entity ids which states are being tracked. """
+        return {}
 
-        try:
-            req = self._call_api(METHOD_GET, hah.URL_API_STATES)
 
-            return req.json()['entity_ids']
+def fire_event(api, event_type, event_data=None, logger=None):
+    """ Fire an event at remote API. """
 
-        except requests.exceptions.ConnectionError:
-            self.logger.exception("StateMachine:Error connecting to server")
-            return []
+    if event_data:
+        data = {'event_data': json.dumps(event_data, cls=JSONEncoder)}
+    else:
+        data = None
 
-        except ValueError:  # If req.json() can't parse the json
-            self.logger.exception("StateMachine:Got unexpected result")
-            return []
+    try:
+        req = api(METHOD_POST, URL_API_EVENTS_EVENT.format(event_type), data)
 
-        except KeyError:  # If 'entity_ids' key not in parsed json
-            self.logger.exception("StateMachine:Got unexpected result (2)")
-            return []
+        if req.status_code != 200 and logger:
+            logger.error(
+                "Error firing event: {} - {}".format(
+                    req.status_code, req.text))
 
-    def set(self, entity_id, new_state, attributes=None):
-        """ Set the state of a entity, add entity if it does not exist.
+    except ha.HomeAssistantError:
+        pass
 
-        Attributes is an optional dict to specify attributes of this state. """
 
-        attributes = attributes or {}
+def get_state(api, entity_id, logger=None):
+    """ Queries given API for state of entity_id. """
 
-        self.lock.acquire()
+    try:
+        req = api(METHOD_GET,
+                  URL_API_STATES_ENTITY.format(entity_id))
 
-        data = {'new_state': new_state,
-                'attributes': json.dumps(attributes)}
+        # req.status_code == 422 if entity does not exist
 
-        try:
-            req = self._call_api(METHOD_POST,
-                                 hah.URL_API_STATES_ENTITY.format(entity_id),
-                                 data)
+        return ha.State.from_dict(req.json()) \
+            if req.status_code == 200 else None
 
-            if req.status_code != 201:
-                error = "Error changing state: {} - {}".format(
-                        req.status_code, req.text)
+    except (ha.HomeAssistantError, ValueError):
+        # ValueError if req.json() can't parse the json
+        if logger:
+            logger.exception("Error getting state")
 
-                self.logger.error("StateMachine:{}".format(error))
-                raise ha.HomeAssistantError(error)
+        return None
 
-        except requests.exceptions.ConnectionError:
-            self.logger.exception("StateMachine:Error connecting to server")
-            raise ha.HomeAssistantError("Error connecting to server")
 
-        finally:
-            self.lock.release()
+def get_states(api, logger=None):
+    """ Queries given API for all states. """
 
-    def get(self, entity_id):
-        """ Returns the state of the specified entity. """
+    try:
+        req = api(METHOD_GET,
+                  URL_API_STATES)
 
-        try:
-            req = self._call_api(METHOD_GET,
-                                 hah.URL_API_STATES_ENTITY.format(entity_id))
+        json_result = req.json()
+        states = {}
 
-            if req.status_code == 200:
-                data = req.json()
+        for entity_id, state_dict in json_result.items():
+            state = ha.State.from_dict(state_dict)
 
-                return ha.State.from_dict(data)
+            if state:
+                states[entity_id] = state
 
-            elif req.status_code == 422:
-                # Entity does not exist
-                return None
+        return states
 
-            else:
-                raise ha.HomeAssistantError(
-                    "Got unexpected result (3): {}.".format(req.text))
+    except (ha.HomeAssistantError, ValueError, AttributeError):
+        # ValueError if req.json() can't parse the json
+        # AttributeError if parsed JSON was not a dict
+        if logger:
+            logger.exception("Error getting state")
 
-        except requests.exceptions.ConnectionError:
-            self.logger.exception("StateMachine:Error connecting to server")
-            raise ha.HomeAssistantError("Error connecting to server")
+        return {}
 
-        except ValueError:  # If req.json() can't parse the json
-            self.logger.exception("StateMachine:Got unexpected result")
-            raise ha.HomeAssistantError(
-                "Got unexpected result: {}".format(req.text))
 
-        except KeyError:  # If not all expected keys are in the returned JSON
-            self.logger.exception("StateMachine:Got unexpected result (2)")
-            raise ha.HomeAssistantError(
-                "Got unexpected result (2): {}".format(req.text))
+def set_state(api, entity_id, new_state, attributes=None, logger=None):
+    """ Tells API to update state for entity_id. """
 
-    def is_state(self, entity_id, state):
-        """ Returns True if entity exists and is specified state. """
-        try:
-            return self.get(entity_id).state == state
-        except AttributeError:
-            # get returned None
-            return False
+    attributes = attributes or {}
 
+    data = {'new_state': new_state,
+            'attributes': json.dumps(attributes)}
 
-class ServiceRegistry(object):
-    """ Allows to interface with a Home Assistant ServiceRegistry
-        via the API. """
+    try:
+        req = api(METHOD_POST,
+                  URL_API_STATES_ENTITY.format(entity_id),
+                  data)
 
-    def __init__(self, host, api_password, port=None):
-        self.logger = logging.getLogger(__name__)
+        if req.status_code != 201 and logger:
+            logger.error(
+                "Error changing state: {} - {}".format(
+                    req.status_code, req.text))
 
-        self._call_api = _setup_call_api(host, port, api_password)
+    except ha.HomeAssistantError:
+        if logger:
+            logger.exception("Error setting state to server")
 
-    @property
-    def services(self):
-        """ List the available services. """
-        try:
-            req = self._call_api(METHOD_GET, hah.URL_API_SERVICES)
 
-            if req.status_code == 200:
-                data = req.json()
+def is_state(api, entity_id, state, logger=None):
+    """ Queries API to see if entity_id is specified state. """
+    cur_state = get_state(api, entity_id, logger)
 
-                return data['services']
+    return cur_state and cur_state.state == state
 
-            else:
-                raise ha.HomeAssistantError(
-                    "Got unexpected result (3): {}.".format(req.text))
 
-        except ValueError:  # If req.json() can't parse the json
-            self.logger.exception("ServiceRegistry:Got unexpected result")
-            raise ha.HomeAssistantError(
-                "Got unexpected result: {}".format(req.text))
+def get_services(api, logger=None):
+    """ Returns a dict with per domain the available services at API. """
+    try:
+        req = api(METHOD_GET, URL_API_SERVICES)
 
-        except KeyError:  # If not all expected keys are in the returned JSON
-            self.logger.exception("ServiceRegistry:Got unexpected result (2)")
-            raise ha.HomeAssistantError(
-                "Got unexpected result (2): {}".format(req.text))
+        return req.json()['services'] if req.status_code == 200 else {}
 
-    def call_service(self, domain, service, service_data=None):
-        """ Calls a service. """
+    except (ha.HomeAssistantError, ValueError, KeyError):
+        # ValueError if req.json() can't parse the json
+        # KeyError if not all expected keys are in the returned JSON
+        if logger:
+            logger.exception("ServiceRegistry:Got unexpected result")
 
-        if service_data:
-            data = {'service_data': json.dumps(service_data)}
-        else:
-            data = None
+        return {}
 
-        req = self._call_api(METHOD_POST,
-                             hah.URL_API_SERVICES_SERVICE.format(
-                                 domain, service),
-                             data)
 
-        if req.status_code != 200:
-            error = "Error calling service: {} - {}".format(
-                    req.status_code, req.text)
+def call_service(api, domain, service, service_data=None, logger=None):
+    """ Calls a service at the remote API. """
+    event_data = service_data or {}
+    event_data[ha.ATTR_DOMAIN] = domain
+    event_data[ha.ATTR_SERVICE] = service
 
-            self.logger.error("ServiceRegistry:{}".format(error))
+    fire_event(api, ha.EVENT_CALL_SERVICE, event_data, logger)
diff --git a/homeassistant/test.py b/homeassistant/test.py
index c193e2df7b257337d2391e6b1c964d126e36f568..b61b17f32d23aea211d6055bebfd834688f9353f 100644
--- a/homeassistant/test.py
+++ b/homeassistant/test.py
@@ -13,11 +13,11 @@ import requests
 
 import homeassistant as ha
 import homeassistant.remote as remote
-import homeassistant.components.httpinterface as hah
+import homeassistant.components.http as http
 
 API_PASSWORD = "test1234"
 
-HTTP_BASE_URL = "http://127.0.0.1:{}".format(hah.SERVER_PORT)
+HTTP_BASE_URL = "http://127.0.0.1:{}".format(remote.SERVER_PORT)
 
 
 def _url(path=""):
@@ -28,6 +28,7 @@ def _url(path=""):
 class HAHelper(object):  # pylint: disable=too-few-public-methods
     """ Helper class to keep track of current running HA instance. """
     hass = None
+    slave = None
 
 
 def ensure_homeassistant_started():
@@ -39,9 +40,9 @@ def ensure_homeassistant_started():
         hass.bus.listen('test_event', len)
         hass.states.set('test', 'a_state')
 
-        hah.HTTPInterface(hass, API_PASSWORD)
+        http.setup(hass, API_PASSWORD)
 
-        hass.bus.fire(ha.EVENT_HOMEASSISTANT_START)
+        hass.start()
 
         # Give objects time to startup
         time.sleep(1)
@@ -51,6 +52,26 @@ def ensure_homeassistant_started():
     return HAHelper.hass
 
 
+def ensure_slave_started():
+    """ Ensure a home assistant slave is started. """
+
+    if not HAHelper.slave:
+        local_api = remote.API("127.0.0.1", API_PASSWORD, 8124)
+        remote_api = remote.API("127.0.0.1", API_PASSWORD)
+        slave = remote.HomeAssistant(local_api, remote_api)
+
+        http.setup(slave, API_PASSWORD, 8124)
+
+        slave.start()
+
+        # Give objects time to startup
+        time.sleep(1)
+
+        HAHelper.slave = slave
+
+    return HAHelper.slave
+
+
 # pylint: disable=too-many-public-methods
 class TestHTTPInterface(unittest.TestCase):
     """ Test the HTTP debug interface and API. """
@@ -75,12 +96,12 @@ class TestHTTPInterface(unittest.TestCase):
         """ Test if we get access denied if we omit or provide
             a wrong api password. """
         req = requests.get(
-            _url(hah.URL_API_STATES_ENTITY.format("test")))
+            _url(remote.URL_API_STATES_ENTITY.format("test")))
 
         self.assertEqual(req.status_code, 401)
 
         req = requests.get(
-            _url(hah.URL_API_STATES_ENTITY.format("test")),
+            _url(remote.URL_API_STATES_ENTITY.format("test")),
             params={"api_password": "not the password"})
 
         self.assertEqual(req.status_code, 401)
@@ -89,7 +110,7 @@ class TestHTTPInterface(unittest.TestCase):
         """ Test if we can change a state from the debug interface. """
         self.hass.states.set("test.test", "not_to_be_set")
 
-        requests.post(_url(hah.URL_CHANGE_STATE),
+        requests.post(_url(http.URL_CHANGE_STATE),
                       data={"entity_id": "test.test",
                             "new_state": "debug_state_change2",
                             "api_password": API_PASSWORD})
@@ -110,7 +131,7 @@ class TestHTTPInterface(unittest.TestCase):
         self.hass.listen_once_event("test_event_with_data", listener)
 
         requests.post(
-            _url(hah.URL_FIRE_EVENT),
+            _url(http.URL_FIRE_EVENT),
             data={"event_type": "test_event_with_data",
                   "event_data": '{"test": 1}',
                   "api_password": API_PASSWORD})
@@ -122,18 +143,20 @@ class TestHTTPInterface(unittest.TestCase):
 
     def test_api_list_state_entities(self):
         """ Test if the debug interface allows us to list state entities. """
-        req = requests.get(_url(hah.URL_API_STATES),
+        req = requests.get(_url(remote.URL_API_STATES),
                            data={"api_password": API_PASSWORD})
 
-        data = req.json()
+        remote_data = req.json()
 
-        self.assertEqual(list(self.hass.states.entity_ids),
-                         data['entity_ids'])
+        local_data = {entity_id: state.as_dict() for entity_id, state
+                      in self.hass.states.all().items()}
+
+        self.assertEqual(local_data, remote_data)
 
     def test_api_get(self):
         """ Test if the debug interface allows us to get a state. """
         req = requests.get(
-            _url(hah.URL_API_STATES_ENTITY.format("test")),
+            _url(remote.URL_API_STATES_ENTITY.format("test")),
             data={"api_password": API_PASSWORD})
 
         data = ha.State.from_dict(req.json())
@@ -147,7 +170,7 @@ class TestHTTPInterface(unittest.TestCase):
     def test_api_get_non_existing_state(self):
         """ Test if the debug interface allows us to get a state. """
         req = requests.get(
-            _url(hah.URL_API_STATES_ENTITY.format("does_not_exist")),
+            _url(remote.URL_API_STATES_ENTITY.format("does_not_exist")),
             params={"api_password": API_PASSWORD})
 
         self.assertEqual(req.status_code, 422)
@@ -157,7 +180,7 @@ class TestHTTPInterface(unittest.TestCase):
 
         self.hass.states.set("test.test", "not_to_be_set")
 
-        requests.post(_url(hah.URL_API_STATES_ENTITY.format("test.test")),
+        requests.post(_url(remote.URL_API_STATES_ENTITY.format("test.test")),
                       data={"new_state": "debug_state_change2",
                             "api_password": API_PASSWORD})
 
@@ -172,7 +195,7 @@ class TestHTTPInterface(unittest.TestCase):
         new_state = "debug_state_change"
 
         req = requests.post(
-            _url(hah.URL_API_STATES_ENTITY.format(
+            _url(remote.URL_API_STATES_ENTITY.format(
                 "test_entity_that_does_not_exist")),
             data={"new_state": new_state,
                   "api_password": API_PASSWORD})
@@ -195,7 +218,7 @@ class TestHTTPInterface(unittest.TestCase):
         self.hass.listen_once_event("test.event_no_data", listener)
 
         requests.post(
-            _url(hah.URL_API_EVENTS_EVENT.format("test.event_no_data")),
+            _url(remote.URL_API_EVENTS_EVENT.format("test.event_no_data")),
             data={"api_password": API_PASSWORD})
 
         # Allow the event to take place
@@ -217,7 +240,7 @@ class TestHTTPInterface(unittest.TestCase):
         self.hass.listen_once_event("test_event_with_data", listener)
 
         requests.post(
-            _url(hah.URL_API_EVENTS_EVENT.format("test_event_with_data")),
+            _url(remote.URL_API_EVENTS_EVENT.format("test_event_with_data")),
             data={"event_data": '{"test": 1}',
                   "api_password": API_PASSWORD})
 
@@ -238,7 +261,7 @@ class TestHTTPInterface(unittest.TestCase):
         self.hass.listen_once_event("test_event_with_bad_data", listener)
 
         req = requests.post(
-            _url(hah.URL_API_EVENTS_EVENT.format("test_event")),
+            _url(remote.URL_API_EVENTS_EVENT.format("test_event")),
             data={"event_data": 'not json',
                   "api_password": API_PASSWORD})
 
@@ -250,7 +273,7 @@ class TestHTTPInterface(unittest.TestCase):
 
     def test_api_get_event_listeners(self):
         """ Test if we can get the list of events being listened for. """
-        req = requests.get(_url(hah.URL_API_EVENTS),
+        req = requests.get(_url(remote.URL_API_EVENTS),
                            params={"api_password": API_PASSWORD})
 
         data = req.json()
@@ -259,7 +282,7 @@ class TestHTTPInterface(unittest.TestCase):
 
     def test_api_get_services(self):
         """ Test if we can get a dict describing current services. """
-        req = requests.get(_url(hah.URL_API_SERVICES),
+        req = requests.get(_url(remote.URL_API_SERVICES),
                            params={"api_password": API_PASSWORD})
 
         data = req.json()
@@ -277,7 +300,7 @@ class TestHTTPInterface(unittest.TestCase):
         self.hass.services.register("test_domain", "test_service", listener)
 
         requests.post(
-            _url(hah.URL_API_SERVICES_SERVICE.format(
+            _url(remote.URL_API_SERVICES_SERVICE.format(
                 "test_domain", "test_service")),
             data={"api_password": API_PASSWORD})
 
@@ -299,7 +322,7 @@ class TestHTTPInterface(unittest.TestCase):
         self.hass.services.register("test_domain", "test_service", listener)
 
         requests.post(
-            _url(hah.URL_API_SERVICES_SERVICE.format(
+            _url(remote.URL_API_SERVICES_SERVICE.format(
                 "test_domain", "test_service")),
             data={"service_data": '{"test": 1}',
                   "api_password": API_PASSWORD})
@@ -310,7 +333,7 @@ class TestHTTPInterface(unittest.TestCase):
         self.assertEqual(len(test_value), 1)
 
 
-class TestRemote(unittest.TestCase):
+class TestRemoteMethods(unittest.TestCase):
     """ Test the homeassistant.remote module. """
 
     @classmethod
@@ -318,134 +341,115 @@ class TestRemote(unittest.TestCase):
         """ things to be run when tests are started. """
         cls.hass = ensure_homeassistant_started()
 
-        cls.remote_sm = remote.StateMachine("127.0.0.1", API_PASSWORD)
-        cls.remote_eb = remote.EventBus("127.0.0.1", API_PASSWORD)
-        cls.remote_sr = remote.ServiceRegistry("127.0.0.1", API_PASSWORD)
-        cls.sm_with_remote_eb = ha.StateMachine(cls.remote_eb)
-        cls.sm_with_remote_eb.set("test", "a_state")
-
-    # pylint: disable=invalid-name
-    def test_remote_sm_list_state_entities(self):
-        """ Test if the debug interface allows us to list state entity ids. """
+        cls.api = remote.API("127.0.0.1", API_PASSWORD)
 
-        self.assertEqual(list(self.hass.states.entity_ids),
-                         self.remote_sm.entity_ids)
+    def test_get_event_listeners(self):
+        """ Test Python API get_event_listeners. """
 
-    def test_remote_sm_get(self):
-        """ Test if debug interface allows us to get state of an entity. """
-        remote_state = self.remote_sm.get("test")
+        self.assertEqual(
+            remote.get_event_listeners(self.api), self.hass.bus.listeners)
 
-        state = self.hass.states.get("test")
-
-        self.assertEqual(remote_state.state, state.state)
-        self.assertEqual(remote_state.last_changed, state.last_changed)
-        self.assertEqual(remote_state.attributes, state.attributes)
-
-    def test_remote_sm_get_non_existing_state(self):
-        """ Test remote state machine to get state of non existing entity. """
-        self.assertEqual(self.remote_sm.get("test_does_not_exist"), None)
-
-    def test_remote_sm_state_change(self):
-        """ Test if we can change the state of an existing entity. """
-
-        self.remote_sm.set("test", "set_remotely", {"test": 1})
-
-        state = self.hass.states.get("test")
-
-        self.assertEqual(state.state, "set_remotely")
-        self.assertEqual(state.attributes['test'], 1)
-
-    def test_remote_eb_listening_for_same(self):
-        """ Test if remote EB correctly reports listener overview. """
-        self.assertEqual(self.hass.bus.listeners,
-                         self.remote_eb.listeners)
-
-   # pylint: disable=invalid-name
-    def test_remote_eb_fire_event_with_no_data(self):
-        """ Test if the remote bus allows us to fire an event. """
+    def test_fire_event(self):
+        """ Test Python API fire_event. """
         test_value = []
 
         def listener(event):   # pylint: disable=unused-argument
             """ Helper method that will verify our event got called. """
             test_value.append(1)
 
-        self.hass.listen_once_event("test_event_no_data", listener)
+        self.hass.listen_once_event("test.event_no_data", listener)
 
-        self.remote_eb.fire("test_event_no_data")
+        remote.fire_event(self.api, "test.event_no_data")
 
         # Allow the event to take place
         time.sleep(1)
 
         self.assertEqual(len(test_value), 1)
 
-    # pylint: disable=invalid-name
-    def test_remote_eb_fire_event_with_data(self):
-        """ Test if the remote bus allows us to fire an event. """
-        test_value = []
+    def test_get_state(self):
+        """ Test Python API get_state. """
 
-        def listener(event):   # pylint: disable=unused-argument
-            """ Helper method that will verify our event got called. """
-            if event.data["test"] == 1:
-                test_value.append(1)
+        self.assertEqual(
+            remote.get_state(self.api, 'test'), self.hass.states.get('test'))
 
-        self.hass.listen_once_event("test_event_with_data", listener)
+    def test_get_states(self):
+        """ Test Python API get_state_entity_ids. """
 
-        self.remote_eb.fire("test_event_with_data", {"test": 1})
+        self.assertEqual(
+            remote.get_states(self.api), self.hass.states.all())
 
-        # Allow the event to take place
-        time.sleep(1)
+    def test_set_state(self):
+        """ Test Python API set_state. """
+        remote.set_state(self.api, 'test', 'set_test')
 
-        self.assertEqual(len(test_value), 1)
+        self.assertEqual(self.hass.states.get('test').state, 'set_test')
 
-   # pylint: disable=invalid-name
-    def test_remote_sr_call_service_with_no_data(self):
-        """ Test if the remote bus allows us to fire a service. """
+    def test_is_state(self):
+        """ Test Python API is_state. """
+
+        self.assertEqual(
+            remote.is_state(self.api, 'test',
+                            self.hass.states.get('test').state),
+            True)
+
+    def test_get_services(self):
+        """ Test Python API get_services. """
+
+        self.assertEqual(
+            remote.get_services(self.api), self.hass.services.services)
+
+    def test_call_service(self):
+        """ Test Python API call_service. """
         test_value = []
 
         def listener(service_call):   # pylint: disable=unused-argument
-            """ Helper method that will verify our service got called. """
+            """ Helper method that will verify that our service got called. """
             test_value.append(1)
 
         self.hass.services.register("test_domain", "test_service", listener)
 
-        self.remote_sr.call_service("test_domain", "test_service")
+        remote.call_service(self.api, "test_domain", "test_service")
 
-        # Allow the service call to take place
+        # Allow the event to take place
         time.sleep(1)
 
         self.assertEqual(len(test_value), 1)
 
-    # pylint: disable=invalid-name
-    def test_remote_sr_call_service_with_data(self):
-        """ Test if the remote bus allows us to fire an event. """
-        test_value = []
 
-        def listener(service_call):   # pylint: disable=unused-argument
-            """ Helper method that will verify our service got called. """
-            if service_call.data["test"] == 1:
-                test_value.append(1)
+class TestRemoteClasses(unittest.TestCase):
+    """ Test the homeassistant.remote module. """
 
-        self.hass.services.register("test_domain", "test_service", listener)
+    @classmethod
+    def setUpClass(cls):    # pylint: disable=invalid-name
+        """ things to be run when tests are started. """
+        cls.hass = ensure_homeassistant_started()
+        cls.slave = ensure_slave_started()
 
-        self.remote_sr.call_service("test_domain", "test_service", {"test": 1})
+    def test_statemachine_init(self):
+        """ Tests if remote.StateMachine copies all states on init. """
+        self.assertEqual(self.hass.states.all(), self.slave.states.all())
 
-        # Allow the event to take place
+    def test_statemachine_set(self):
+        """ Tests if setting the state on a slave is recorded. """
+        self.slave.states.set("test", "remote.statemachine test")
+
+        # Allow interaction between 2 instances
         time.sleep(1)
 
-        self.assertEqual(len(test_value), 1)
+        self.assertEqual(self.slave.states.get("test").state,
+                         "remote.statemachine test")
 
-    def test_local_sm_with_remote_eb(self):
-        """ Test if we get the event if we change a state on a
-        StateMachine connected to a remote bus. """
+    def test_eventbus_fire(self):
+        """ Test if events fired from the eventbus get fired. """
         test_value = []
 
         def listener(event):   # pylint: disable=unused-argument
             """ Helper method that will verify our event got called. """
             test_value.append(1)
 
-        self.hass.listen_once_event(ha.EVENT_STATE_CHANGED, listener)
+        self.slave.listen_once_event("test.event_no_data", listener)
 
-        self.sm_with_remote_eb.set("test", "local sm with remote eb")
+        self.slave.bus.fire("test.event_no_data")
 
         # Allow the event to take place
         time.sleep(1)
diff --git a/start.py b/start.py
index eeb29a27a12f81fe74cdf2e8cabb136645a6b2d3..527110856df9c125c5fa29cf6fbfe45c845f83ad 100644
--- a/start.py
+++ b/start.py
@@ -3,4 +3,6 @@
 import homeassistant
 import homeassistant.bootstrap
 
-homeassistant.bootstrap.from_config_file("home-assistant.conf").start()
+hass = homeassistant.bootstrap.from_config_file("home-assistant.conf")
+hass.start()
+hass.block_till_stopped()