Switching lights with MQTT

A project log for Spider, a Tiny Home Automation Hub

Low-cost modular MQTT devices

Danny HavenithDanny Havenith 06/10/2017 at 22:440 Comments

MQTT is working!

Spider can now successfully subscribe to an MQTT topic and switch RF wall switches.

There are still some hard-coded constants that need to become configurable in EEPROM in the future, but in essence switching the lights works as intended.

The software consists of a firmware and a library that contains the esp-link client code to talk MQTT with the outside world.

The new firmware subscribes to the topic "spider/switch/+" and expects messages to "spider/switch/<switch number>" the message itself should be either "0" (off) or "1" (on). What happens when such a message arrives is determined by a data structure that is currently constant, but should be stored in EEPROM in a later stage.

Sending to RF switches

The <switch number> part of the topic is used to index into an array that is initialized as follows:

const Switch switches[] =
        { quigg,  { 0b01000001000000001101,     // off
                    0b11001001000000001101}     // on
        { impuls, { 0b1011101010101110000000000,// off
                    0b1110101010101110000000000}// on
        { impuls, { 0b1011101011101010000000000,// off
                    0b1110101011101010000000000}// on

Each element of this array defines a pair of codes (one for "off" (0) and one for "on" (1)) to be sent and an index into an array that describes the protocols to be used. The MQTT message, 0 or 1 is used to select one of the two codes in the structures above. "quigg" and "impuls" are just constants that represent two brands of inexpensive (3 for €10,-) RF controlled switches:

constexpr int quigg  = 0;
constexpr int impuls = 1;
I had reverse engineered the protocols for these switches earlier and that gives me a data structure to describe the protocols for these switches:
struct Encoding
    /// how long to wait between sending the same signal again in units of
    /// 4 microseconds.
    uint16_t us4_between_repeats;
    /// how many bits in one transmission
    uint8_t bits;
    /// whether to invert the signal and if so: how long to wait after inversion
    /// in units of 4 microseconds
    uint16_t us4_delay_after_invert;
    /// describes a single symbol, usually a 1 or a 0
    typedef uint16_t Symbol[2];
    /// describes the symbols for a 0 bit and for a 1 bit
    Symbol alphabet[2];

This video shows how I reverse engineer the signals for my switches using a horrible contraption that I made earlier:

...and this gives me the following numbers for my switches:

// describe the known protocols
constexpr Encoding symbols[] = {
    // quigg
    { 17000,    20,     175,{ { 175, 350 }, { 350, 175 } } },

    // impuls
    { 1500,     25,     0,  { { 140, 49 }, { 42, 147 } } }