State Controller ESP32

by Ben Jones

SKU: OXRS-SHA-STATECONTROLLER-ESP32-FW

Introduction

A binary state controller for DIY home automation projects.

Listens for MQTT messages and send on/off binary output signals using MCP23017 I2C I/O buffers.

Typically the output signals would be used to drive relay coils in order to switch larger voltages - e.g. light circuits.


How does it work?

Outputs can be switched by publishing an MQTT message to the configured MQTT broker.

Each output can be configured as a relay, for simple on/off control. A motor, again with on/off control but longer interlock delays if interlocking is configured. Or a timer, for on and then timed off control.

The firmware is designed to run on hardware using MCP23017 I/O buffer chips via I2C, e.g. the 16 Channel Relay Driveropen in new window.

A single I2C bus can only support up to a maximum of 8x MCP23017 chips (addresses 0x20-0x27). Therefore the maximum number of supported outputs is 128 (i.e. 8x MCP23017s * 16x I/O pins).

Interlocking

Interlocking two outputs allows them to control equipment such as roller blinds, garage doors, louvre roofing etc.

However if you are planning to control a motor of any sort then it is important that the two outputs are configured as type motor and that both are interlocked with each other. This is to ensure that both outputs will not be commanded to operate at the same time and adds a 2 second delay between any changes of output.

Example payload to configure outputs 4 & 5 to control a set of roller blinds;

{
  "outputs": [
    { "index": 4, "type": "motor", "interlockIndex": 5 },
    { "index": 5, "type": "motor", "interlockIndex": 4 }
  ]
}

The operation of the interlocked outputs should be verified before connecting to any external equipment. External interlocking equipment may be required for some equipment. Most importantly, the manufacturers wiring and installation guides must be adhered to.

Timers

Timers allow an output to automatically turn off a set number of seconds after being turned on (configurable via timerSeconds, which defaults to 60 seconds).

If another on command is sent while the timer is running, it will reset to zero and begin counting down again. If an off command is sent the timer will be cancelled and the output turned off immediately.

Configuration

The firmware can be configured by publishing an MQTT message to this topic;

[PREFIX/]conf/CLIENTID[/SUFFIX]

where:

  • PREFIX: Optional topic prefix if required
  • CLIENTID: Client id of device, defaults to <MACADDRESS>
  • SUFFIX: Optional topic suffix if required

The message payload should be JSON and it's format is defined in a JSON schema document included in the adoption payload published here;

[PREFIX/]stat/CLIENTID[/SUFFIX]/adopt

See the config value in the /adopt payload.

MCP Config

This firmware is compatible with I/O boards with MCPs driving 8 or 16 output relays (see Supported Hardware links below). If you are using a board which is only driving 8 output relays you need to tell the firmware to ignore pins 9-16 on each MCP.

KeyMandatoryValue
outputsPerMcpOptionalNumber of outputs connected to each MCP (either 8 or 16, defaults to 16)

Your device MUST be restarted after any changes to this configuration, before it will take effect.

Examples

To configure for use with 8 Channel Relay Driver Shieldopen in new window;

{ 
  "outputsPerMcp": 8
}

WARNING

This config should be set using the REST API and NOT a retained MQTT message. This config is used when initialising the device and is needed by the firmware before a connection to the MQTT broker is made. Setting this via the REST API will ensure it is persisted to SPIFFS and loaded early enough in the boot sequence.

TIP

You can set this config via the REST API using curl (substitute your device IP address);

curl -X POST http://<DEVICE_IP>/config -H 'Content-Type: application/json' -d '{"outputsPerMcp":8}'

Default Output Type

By default all outputs are initialised as type relay. Individual outputs can then be configured as required (see below). However it is also possible to change this default. For example, if you are intending to control roller blinds throughout your home, instead of setting individual config for each output, you can simply set the defaultOutputType to motor and be done with it.

KeyMandatoryValue
defaultOutputTypeOptionalEither motor, relay, or timer

Examples

To configure the default output type to be motor;

{ 
  "defaultOutputType": "motor"
}

TIP

You can still override the default output type with specific configuration for individual outputs, see below.

Output Config

Each OUTPUT can be configured via the following properties;

KeyMandatoryValue
indexMandatoryIndex of the output to configure
typeOptionalEither motor, relay, or timer
interlockIndexOptionalIndex to interlock with (lock the opposite for interlocking both ways or self-lock to disable interlocking)
timerSecondsOptionalNumber of seconds an output stays on when type set to timer (defaults to 60 seconds)

The only difference between motor and relay outputs is the interlock delay (if an interlock is configured).

Output TypeInterlock delay
motor2000ms
relay500ms

Examples

To configure output 4 to be a 30 second timer and outputs 6 & 7 to drive a motor and be interlocked;

{ 
  "outputs": [
    { "index": 4, "type": "timer", "timerSeconds": 30 },
    { "index": 6, "type": "motor", "interlockIndex": 7 },
    { "index": 7, "type": "motor", "interlockIndex": 6 }
  ]
}

TIP

A retained message will ensure the device auto-configures on startup.

Commands

Each OUTPUT can be controlled by publishing an MQTT message to the topic;

[PREFIX/]cmnd/CLIENTID[/SUFFIX]

where;

  • PREFIX: Optional topic prefix if required
  • CLIENTID: Client id of device, defaults to <MACADDRESS>
  • SUFFIX: Optional topic suffix if required

The message payload should be JSON and it's format is defined in a JSON schema document included in the adoption payload published here;

[PREFIX/]stat/CLIENTID[/SUFFIX]/adopt

See the command value in the /adopt payload.

KeyMandatoryValue
indexMandatoryIndex of the output to switched
commandMandatoryEither on, off, or query

TIP

The query command will cause an event to be published, with the current state of that output.

Examples

To turn on output 4 and query the state of output 7;

{ 
  "outputs": [
    { "index": 4, "command": "on" },
    { "index": 7, "command": "query" }
  ]
}

Events

An output STATE CHANGE is reported to a topic of the form;

[PREFIX/]stat/CLIENTID[/SUFFIX]

where;

  • PREFIX: Optional topic prefix if required
  • CLIENTID: Client id of device, defaults to <MACADDRESS>
  • SUFFIX: Optional topic suffix if required

The message payload is JSON and contains:

KeyValue
indexIndex of this event (1-128)
typeEvent type (see below)
eventEvent (see below)
Event TypeEvent
motoron or off
relayon or off
timeron or off

Examples

A relay turning on for output 6;

{
  "index": 6, 
  "type": "relay", 
  "event": "on"
}

A timer turning off for output 12;

{
  "index": 12, 
  "type": "timer", 
  "event": "off"
}

Downloads

Download the latest version of the firmware on Githubopen in new window.

Supported Hardware

This firmware is compatible with the boards;

And is designed to run on the RACK32 as part of the OXRSopen in new window eco-system.

Credits

License

Copyright 2020-present SuperHouse Automation Pty Ltd www.superhouse.tv

The software portion of this project is licensed under the Simplified BSD License. The "licence" folder within this project contains a copy of this license in plain text format.