Skip to content

Controller Configuration

In Reactor, controllers are interfaces to other systems that publish entities in the Reactor environment. Reactor comes with a handful of controllers for various HA systems, so you can access the devices controlled there.

  • VeraController — for Vera systems;
  • HassController — for Home Assistant;
  • HubitatController — for Hubitat home automation systems;
  • eZLO Controller — for eZLO hubs;
  • CameraController — a generic interface for IP cameras that makes them available in the dashboard;
  • OWMWeatherController — an interface to OpenWeatherMap to publish per-location entities for weather data;
  • SystemController — a controller that gives you information about your system runtime environment (memory usage, CPU load, etc.).

Your configuration can contain any mix of these controllers, and you may have multiple of any of them (although practically speaking there should only be one SystemController).

Eventually, the author and others (hopefully) will write additional controllers to interface to other systems. As you can infer from the list above, a "controller" does not necessarily map to a home automation system, it's really a generic object that communicates with some kind of remote API/endpoint, and publishes what it learns as entities inside of Reactor.

To configure a controller in your Reactor system, you need to add an entry in your reactor.yaml file in the controllers section. The following keys are known:

  • id — The ID of the controller; this is a unique string (alphanumeric and underscore allowed only, no spaces or other punctuation) to identify a specific instance of a controller. It must be unique across all configured controllers (no other controller can be assigned the same ID).
  • implementation — name of the controller class that provides the implementation of the controller (i.e. the code). The list above shows the names of the included controller classes. If you an additional class you want to use, you place the implementation file into the local subfolder of your Reactor installation and restart Reactor.
  • name — a friendly name for your controller (this may contain spaces and punctuation);
  • enabled — a (boolean) flag that lets you enable or disable a controller. To disable a controller without having to remove its entire configuration, simply set enabled to false. To re-enable it, set enabled to true or remove the enabled key altogether (true is the default).
  • config — an object that contains the controller-specific configuration data.

Each controller has its own configuration rules and data requirements for the config section, so in order to configure a controller, you'll need to follow specific instructions for each.


Configuring a VeraController instance is straight-forward: the only required configuration key is source, to which you should assign the base URL to access the Vera system. For example:

  # reactor configuration section not shown

- id: vera
  enabled: true
  implementation: VeraController
  name: Vera System
    source: ""


You may use either the http://ip:port form or the http://ip/port_3480 form for the source value when linking a Vera system.

openLuup Support

OpenLuup is an emulation of Vera Luup and is supported by VeraController to the degree that openLuup conforms with the behavior of Vera Luup in all respects necessary for VeraController to operate. There is no direct, official support for openLuup. Disparities in functionality between openLuup and Vera Luup should really be addressed in openLuup, as this improves that system for all of its current and future users. But it is up to the author of the openLuup project to decide if he wants to address these issues or not, but if he chooses not, it may leave the system unable to meet the needs of MSR. As a result, support for openLuup is strictly as-is and as-available, and may not be possible in future versions of MSR.

How VeraController Maps Devices

As a controller, VeraController's primary duty is to collect data from the Vera system and publish it within MSR as entities. It does this by mapping between the two systems. This mapping is principally done in a pair of configuration files: server/lib/vera_devices.json and server/lib/vera_capabilities.json. The latter defines any capabilities that are specific to Vera devices — those that are not generic enough to have been defined as system-wide capabilities shared by all controllers. The former is the real workhorse, containing the rules by which entities are assigned capabilities based on properties of their respective Vera devices. It's not important to know the details of this, but do know that because this process is driven largely by configuration files, it is possible for you to create additional user-space configuration to describe devices not yet included in the standard mapping — you don't need to wait for upgrades. More on that later.

Don't Edit the System Files!

Never modify the system-standard device mapping files. These will be overwritten on every upgrade. See TBD for instructions on the proper way to define your own device mappings.

Help Me Triage/Prioritize!

At the moment, I obviously haven't mapped out every possible device, which includes devices created and managed by every plugin ever written for Vera. I'll tackle them as they come up, and because configuration drives it, I'm hoping it will be as easy as I've planned it to be to just publish updates mapping files. Since it's also possible for users to create their own mappings, I'm hoping some Vera users, and particularly the various plugin developers, will contribute mappings they create themselves. Please let me know when you find an entity you need a full mapping for!

Special Configuration for VeraController

This section is informational only. It is not usually necessary to specify these values or modify their defaults.

  • PollTimeout — Vera uses a technique called "long polling" for quick data access. When a request is made for data, the Vera can be told to pause until something has changed before it replies, and this value controls the length of that pause. The default value is 15000 (milliseconds), which is 15 seconds. It is not recommended that you change this value in most circumstances.
  • PollMinimumDelay — a partner of PollTimeout, this value sets the minimum time that Vera must wait before responding. Often, when one thing changes in the system, other things quickly follow. This minimum delay causes the Vera to hold off responding to the query for the prescribed period (again in milliseconds), so that the response that it eventually makes can bundle several changes at once, rather than handing them over singly. This improves performance and responsiveness of the integration. Much testing has shown that the default 50 milliseconds is a good value.
  • ActionPace — Controls the rate at which actions are sent to the Vera. Vera system stability demands that we don't throw too many things at it simultaneously, so all actions are pipelined. This value sets the minimum delay between action requests sent via that pipeline. The value is expressed in milliseconds, and is 25 by default. If you find that your Vera deadlocks and reloads while trying to execute long reactions, try increasing this value (some devices and plugins just need more time).


HassController is the interface to Home Assistant systems. It uses Home Assistant's WebSocket API to implement the communications layer. This approach significantly reduces the load of communication on both systems, even in periods of high activity when a lot of data is being exchanged. You will need to make sure that the WebSocket API is enabled in your HomeAssistant configuration. See their documentation for that.

Because Home Assistant sometimes makes breaking changes to its API, only specific version of Home Assistant are supported by this interface. Currently, only Home Assistant versions 2021.1.5 through 2021.9.6 are supported. Versions outside this range may not work at all, or exhibit errant behaviors that are not immediately obvious. Bug reports and fixes for versions outside this range are not accepted/handled.

The only required fields for HassController are source and access_token:

  # reactor configuration section not shown

- id: hass
  enabled: true
  implementation: HassController
  name: Home Assistant
    source: "ws://"
    access_token: "place long-lived access token within"

Note that the source field must contain a URI in the form ws://ip-address:port. The access_token value is a "long-lived access token" from Home Assistant. To get a LLAT, log in to the Home Assistant UI and click on your username in the bottom-left corner. Then scoll down your profile until you find the "Long-Lived Access Tokens" section. Create a new token there, and copy/paste it into your Reactor controller configuration, keeping it surrounded in quotes as shown above.

Mapping Home Assistant Devices

Like VeraController, HassController tries to do as much of the work of mapping between Hass entities and Reactor entities as possible through configuration files. The configuration files hass_devices.yaml and hass_capabilities.yaml (in server/lib) provide this data. Additionally, you may create your own mappings and capabilities by creating configuration files in the local subdirectory of your Reactor installation.

Don't Edit the System Files!

Never modify the system-standard device mapping files. These will be overwritten on every upgrade. See TBD for instructions on the proper way to define your own device mappings.

Special Configuration for HassController

This section is informational only. It is not usually necessary to specify these values or modify their defaults.

  • Timeout — this value sets the length of time HassController will wait for a successful connection to Home Assistant before throwing an error. The default is 15000 (milliseconds, 15 seconds).


HubitatController is the interface to Hubitat Elevation home automation controllers. Setup for Hubitat is a little more involved than some of the other controllers, because it involves installing add-on applications to enable their API.


If you have another integration that is already using Maker API, you will need to install another instance of Maker API for Reactor's use exclusively. This will not disrupt your other integration(s). When you create the new Maker API instance, you can give it a name that is distinct so you know it used by Reactor (e.g. "Maker API for Reactor")

  1. Open the Hubitat user interface in a browser locally;
  2. Go to the "Apps" section.
  3. Create a Maker API instance by clicking the "Add Built-in App" button, typing "Maker" in the search box, and clicking "Maker API". This will open a detail dialog for the new instance.
  4. Assign the new instance a name that lets you easily discern that it's for Reactor (see Tip above).
  5. Turn on "Allow Access via Local IP Address". It is not necessary to turn on "Allow Access via Remote / Cloud" (and it is recommended that you leave it off).
  6. Leave "Create new access token" selected (unless you know what you are doing and you want to reuse an existing token).
  7. Click on "Select device" and choose all devices (or only those devices you want available in Reactor).
  8. Turn on "Include location events to be sent by POST", and if you use modes or HSM, turn on the "Allow control of" switches for those as well.
  9. Turn on "Allow control of modes" and "Allow control of HSM".
  10. You're almost finished. Before you leave this page, right-click the "Get All Devices" link under the *Local URLs" heading and choose "Copy link location..." (or your browser's nearest equivalent). You will be pasting this into your reactor.yaml configuration file in a future step.
  11. Click the "Done" button at the bottom of the page to create your new instance. You can get back to these settings any time (and you may need to when you add devices) by going to Apps in the left navigation and then clicking the instance name.
  12. Open reactor.yaml (in the config subdirectory) in your text/code editor and find the Hubitat entry. Go to the source key under config in this section, and paste the entire URL copied from two steps ago (remove the default/placeholder URL). Make sure the URL is surrounded in double-quotes (see example below).
  13. Go up to the enabled key for this controller and change the value to true (no quotes around the value).
  14. Save the configuration file.

Your configuration for Hubitat should now look something like this:

  # ...other controller configuration not shown for clarity

- id: hubitat
  enabled: true
  implementation: HubtitatController
  name: Hubitat
    source: ""

You may now restart Reactor. Refresh any browser windows open to the Reactor UI, and go to the Entities list. You should see your Hubitat devices listed.


Remember, any time you add a device to Hubitat, if you want to see it in Reactor, you need to add your new device(s) to the "allowed" list in the Maker API instance, or Reactor will not be able to see it/them.

Hubitat with Hub Login Security Enabled

Hubitat's Hub Login Security causes its event notification WebSocket connections to issue no events or data at all until a login to the hub is performed (this is presumably a security feature, but it's a pretty weak one at best). If you have Hub Login Security enabled, you will notice that MSR frequently reconnects to your hub (visible in log messages about every six minutes by default) and is slow to detect device changes. This is particularly seen after a hub reboot, where there is a gap in time between the hub starting up and your first login to it.

The following solutions are available:

  1. Set the username and password fields in the controller's config section of reactor.yaml. The HubitatController will do its own login and thus enable the WebSocket API to function as needed.
  2. Turn off "Hub Login Security" in your hub settings.
  3. Don't let the HubitatController use the WebSocket API and have it use the old "POST URL" mechanism. This can be done by adding use_posturl: true to the controller's config section of reactor.yaml. This is the least desirable of the three solutions as it has been shown to be less reliable than using the WebSocket API, but it's a trade-off between security and performance/reliability.


EzloController integrates eZLO Plus and similar (new, post-Vera firmware) hubs with Reactor. It is currently in development status — you may use it, but please report bugs and clarify issues or ask questions via the Smart Home Community forums or, if you have an account, the Reactor Mantis Bug Tracker. The EzloController may in future not be included as a standard Reactor component (i.e. not included in the standard distribution packages), but offered separately as an extra-cost add-on.


Ezlo has not formally documented any of their login procedures for the their API, either for local or remote access. The EzloController class therefore must use well-known and commonly-used but undocumented methods to establish API connections; some of these have been communicated in informal channels by eZLO engineers, and some have been "discovered" by other means. I'm not sure why they have chosen to do a fairly detailed job of documenting their API, yet not documented the procedure necessary to gain access to that API, but so be it as of this writing. Since such documentation is, in effect, a guideline and specification that tempers future changes, there is no way to know if future updates to the eZLO cloud or hub firmware will continue to support the login method used.

Before starting:

  1. Make sure you are using a supported hub. The following are supported: eZLO Plus; eZLO Secure; Vera Edge running eZLO firmware; generation 2 or higher eZLO Atom or PlugHub. You can use first-generation eZLO Atoms, but they must use cloud access, there is no local access to the hub (see the callout below for more details). Other eZLO hubs may work but are not explicitly supported.
  2. Your eZLO Plus/Secure/Edge should be running firmware or higher; Atom/Plughub must be running 0.8.539 or higher.
  3. Make sure your hub is registered and accessible via the VeraMobile mobile app.
  4. Except first-generation Atom, the hub should be configured with either a static IP address or using a DHCP reservation, so that its IP address is stable and never changes.

Atom Support

First-generation Atom hubs do not offer local access to the hub API, so cloud/relay access is the only way to contact the hub. This makes your configuration vulnerable to failures of your Internet access, eZLO's cloud services, and even your local network. For this reason, the use of eZLO first-generation hubs is not recommended. It's fine for experimentation, however, and may be adequate for certain less important tasks. How do you know what generation of Atom you have? You may be able to tell by the serial number alone: according to eZLO, if the first four digits of your Atom's serial number are between 7000 and 7009 (inclusive), you have a "generation 1" atom, which does not support local access to the API, so only cloud/remote access is available for these units. Serial numbers 7500 to 7599 and 7600 to 7699 are EU and US version 3 hardware Atoms, respectively, and these support both local and remote access to the API. Serial numbers starting 7010 to 7499 are version 2 hardware, but may not be "generation 2" operationally and so may or may not support local API access — you're just going to have to try it. If you're serious about using an Atom in your home automation, it is strongly recommended you use at least version 3 hardware and use local API access. The final judgement of risk tolerance is, of course, your own.

To configure your hub in Reactor, you will add configuration with your hub serial number and account credentials (username and password) to the reactor.yaml file's controllers section. For all hubs except first-generation Atom, also include the source key, putting in the IP address of your hub where shown (omit the source key entirely for first-generation Atoms). Remember that all indenting is done with spaces, not tabs, in YAML files.

# other configuration sections not shown

- id: ezlo
  enabled: true
  implementation: EzloController
  name: "My Ezlo Hub"
    source: "wss://"  # change the IP address
    serial: "12345678"    # put your hub's serial # here
    username: "somebody"  # put your username here betw quotes
    password: "????????"  # and password

Restart Reactor. If your credentials and IP address are correct, Reactor will connect to the hub and inventory its devices. Go to the Reactor UI, to the Entities list (left navigation), and you should be able to see your eZLO devices as entities in the list (make sure you clear any filters you may have previously applied). If you don't see your devices, check your settings, and examine the reactor.log file for messages. The most common error is not providing all four configuration elements: source, serial, username and password (and second most common is an error in the username or password values).

All good? Excellent, please read on...

Getting Rid of the eZLO Cloud Login Requirement

Wait! Cloud Login First!

DO NOT perform the procedure below until you have successfully connected your eZLO hub using cloud authentication. Get that working first. Once that works, then you can follow this procedure.

Not for Atom/PlugHub (RTOS hubs)

Local anonymous access (accessing the API locally without cloud login or authentication tokens) is available only on Linux-based eZLO hubs (i.e. not any version of Atom or PlugHub, which are RTOS-based).

By default, eZLO hubs are configued for authenticated access. That means Reactor needs to log in to the eZLO cloud services and request an access token that it can then use to log in to the hub locally. The access token has a defined lifetime, and when it expires, a new token must be requested from the cloud services. If your Internet access goes down, however, Reactor will be unable to reach the cloud services, and therefore unable to access your hub. This creates a critical-path dependency on Internet access (and the stability/availability of eZLO's cloud services) for your home automation rules.

eZLO hubs have the ability to enable anonymous access so that they can be accessed locally (from within your own network) without the cloud service's tokens. In this mode, reconnection to the hub is immediate and reliable even when Internet access is unavailable. Enabling anonymous access on the hub is relatively easy.

  1. Confirm that your eZLO hub is connected for local access using cloud authentication. The controller's system entity in the Entities list will have true values for both sys_system.state and x_ezlo_sys.using_cloud_auth. The x_ezlo_sys.using_cloud_relay attribute should be false. If it is true, you have not correctly configured source with the IP address of the hub. Correct this, restart Reactor, and recheck these values before proceeding.
  2. Add the line indicated below (do not remove or modify any other config lines yet), indented the same as the password: line:

    password: "whateverItIs"
    set_anonymous_access: true   <--- add this using same indent (spaces) as "password"
  3. Restart Reactor. Reactor will log in one more time using the cloud services, but when it gets into the hub, it will reconfigure the hub up for anonymous access. It takes up to two minutes for this process to complete, and your eZLO hub may reboot one or two times, so wait at least a full two minutes before continuing.

  4. Refresh your browser, and open the Entities list again. Go to the system entity for the eZLO hub, expand it, and confirm that the attribute x_ezlo_sys.anonymous_access_enabled is now true (again, this takes several minutes, so if it's still false, wait another minute or two). You will also receive an alert on the Status view telling you that anonymous access has been enabled.
  5. Now that anonymous access is enabled on the hub, we need to tell Reactor to use anonymous access rather than cloud authorization. Reactor will always use cloud authentication when username and password are set in your configuration, so your final step in this process is to comment out the username and password entries in your config as shown below, and restart Reactor. You can also comment out the set_anonymous_access line. Then restart Reactor one more time. To comment out the lines, just insert a # at the first (non-space) character.
    #username: "yourusername"
    #password: "whateverItIs"
    #set_anonymous_access: true

Remember to restart Reactor after making this final change. After restart, Reactor should be connected with anonymous access (no cloud auth). To confirm, go back to the Entities list and check the eZLO hub's system entity. The value of x_ezlo_sys.using_cloud_auth should now be false, indicating that Reactor is connected anonymously.

Security Risk!

Enabling anonymous access creates certain security risks that only you can assess and accept. It allows any person on your network to access and control the hub. If any host in your network is compromised or your network is otherwise accessed by an unauthorized person or device, it would be possible for them to access and control your hub as well. The risk of enabling anonymous access is yours entirely.

If you later wish to restore authenticated access to your hub (i.e. disable anonymous access), simply uncomment the username, password and set_anonymous_access lines (remove the # in front of them), and set set_anonymous_access to false. Then restart Reactor, and it will reconfigure the hub with anonymous access disabled.


OWMWeatherController is not an integration with a home automation gateway/hub, but rather an interface to OpenWeatherMap's API for weather data. OWMWeatherController publishes weather information for each location you configure in an entity per location. These entities can be used to support automations just like any other entity in Reactor.

This is the simplest configuration for OWMWeatherController:

- id: weather
  enabled: true
  implementation: OWMWeatherController
  name: OWM Weather
    appid: "own-api-key"

In this simple form, OWMWeatherController gathers weather for the system location (as defined by the location subkey in reactor.yaml). All you need to provide to get weather information for your home location is your OWM API key, which you get from their web interface.

If you want to set a specific location different from the system location, or get weather for additional locations (which will be published to additional entities), add a locations section with the location information formatted as shown:

- id: weather
  enabled: true
  implementation: OWMWeatherController
  name: OWM Weather
    appid: "owm-api-key"
    - id: home
      name: Home Current Weather
      # Set the location by specifying ONE OF: latitude+longitude, OWN city
      # ID, or location (as postal,country). If none is set, the system
      # location will be used.
      #latitude: 33.400876
      #longitude: -84.581101
      #city_id: 4215110
      #location: "30269,us"
      # Enable "save_full_response" to save the full response (you may have
      # need to use parts of the response that are not part of the wx
      # capability in your dashboard widgets).
      #save_full_response: false

To determine the location, you must provide one of the following:

  • The latitude and longitude of the location, in fields latitude and longitude respectively; or
  • The OWM City ID for the location, in the city_id field; or
  • The postal code and ISO 3166-1 country code (two character) formatted postcode,county (e.g. "30269,us") in the location field.

You may have multiple locations, as many locations as you want; just realize that each location increases the number of API calls (which counts against your quota). To add locations, simply duplicate the structure from -id: to the end of the example above and append it after the last location, then uncomment and modify the new location values as needed.

Use OWM City IDs

The OWM City IDs are published in a list that can be downloaded from their web site. Go to their site, select the "API" navigation at the top of the page, click on the "API doc" button under "Current Weather Data", and then scroll down to "By city ID". You'll find the link to download the list in the text there. Using these IDs removes ambiguity and speeds up responses.




SystemController is Reactor's own controller to publish memory and CPU usage to a single entity for access by automations and the dashboard. It also publishes the "Sun Information" entity (capability suninfo) with data about today's sunrise/sunset, day length (in hours), solar noon (transit) time, and current sun angle (-90 at sunrise, 0 at solar noon, 90 at sunset).

The update_interval value is the time (in milliseconds) between updates to the system data entity. The default is 60000, which is 60 seconds (one minute), and there should be little cause to change it.

The protect_controller_group flag (boolean) determines whether the controller's default group exists or not. Since SystemController publishes only one entity, it's a bit of a waste to have it in a group by itself, so by default, SystemController will remove the one-member group. However, there are cases, such as on the dashboard, where having the group can aid navigation and access to the entity. To address this need when it arises, protect_controller_group can be set to true.

The report_volumes key may, optionally, define an array objects describing zero or more storage volumes to be monitored for available space. If not set, Reactor base directory, logs directory, and storage directory will be monitored. Monitored volumes/directories will present as additional attributes in the reactor_system>system entity. Each volume will have a reactor_system.volume_<id> attribute, where <id> is the identifier associated with the volume (explained shortly). Custom configuration of volumes looks like this:

  # other controllers and config redacted for clarity
  - id: reactor_system
    enabled: true
    implementation: SystemController
    name: Reactor System
        - id: root
          path: /
          critical: 10%
        - id: home
          path: /home
          critical: 5%

In the above example configuration, the directories (presumably mount points for volumes) / and /home are monitored, and assigned IDs root and home respectively. The reactor_system.system entity will have attributes reactor_system.volume_root and reactor_system.volume_home, the value of each being an array of four elements: the free space of the volume (in KB), the total space of the volume (in KB), the percentage of free space (expressed as fractional 0.0 to 1.0), and the path monitored. In addition, because each of these contains the optional critical key and value, additional boolean attributes reactor_system.volume_critical_root and reactor_system.volume_critical_home will be present and true if the free space of the volume is less than the configured critical value (which may be given as a percentage as shown, or a fixed number of KB).

Other Controllers

Other controllers that you may find as add-ins will each have their own specific configuration instructions. Please refer to their accompanying documentation.

Updated: 2021-Sep-13