Connecting Sensors and Switches

A project log for Spider, a Tiny Home Automation Hub

Low-cost modular MQTT devices

Danny HavenithDanny Havenith 06/11/2017 at 22:040 Comments

Today, two spider devices communicated with each other for the first time, and it worked! In this setup, an AVR with IR sensor detects motion at the front door and signals this to an MQTT broker. A Spider device listens to the message and switches on a light inside the house using an RF socket switch. Schematically:

The following video shows the system in action.

Of course this is not a realistic setup, but it shows the concept and there's something very satisfying in seeing the system react in a fairly sophisticated way.

The Software Setup

Being a software developer, I can't help but explain in some detail how the software for this project is now set up. To be honest, this example is somewhat hacked. To start with, the sensor board was programmed to directly publish to the MQTT topic of the light switches:

    using esp_link::mqtt::setup;
    using esp_link::mqtt::publish;
    const char topic[] = "spider/switch/0";

    while (not esp.sync()) /*repeat*/;
    esp.execute( setup, nullptr, nullptr, nullptr, nullptr);

    for (;;)
        esp.execute( publish, topic, "0", 0, 0);
        fade( leds, true); // fade in

        esp.execute( publish, topic, "1", 0, 0);
        fade( leds, false); // fade out
This code will publish a "0" to topic "spider/switch/0" and then wait for the PIR sensor to show movement. As soon as movement is detected, it will publish a "1" to that same topic and then wait until an (arbitrarily chosen) 30s period passes without movement, after which it will send a "0" again, etc.

This direct connection between sensor and switch is not supposed to happen. Really, the sensor should just publish to its own topic, e.g. "spider/sensor/<n>" and the home automation software should take over from there and publish to the switch topic.

The spider software for the switch had already been programmed before. As stated previously, it subscribes to the topic "spider/switch/+" and will react to messages by sending "on" and "off" pulse trains to the 433 Mhz transmitter. The setup looks like this:

    using esp_link::mqtt::setup;
    using esp_link::mqtt::subscribe;

    // get startup logging of the uart out of the way.
    _delay_ms( 5000); // wait for an eternity.
    while (not esp.sync()) toggle( led);

    esp.execute( setup,     nullptr, nullptr, nullptr, &update);
    esp.execute( subscribe, "spider/switch/+", 0);

    for (;;)
This code registers the function update() as a callback for new messages. The update function itself checks whether the topic of the message is the one it expects and will then parse the switch number and the number in the message:
void update( const esp_link::packet *p, uint16_t size)
    using namespace esp_link;
    packet_parser parser{ p};

    string_ref topic;
    string_ref message;
    parser.get( topic);
    parser.get( message);

    const char *topic_ptr = topic.buffer;
    const char *topic_end = topic_ptr + topic.len;

    // if the topic is indeed the expected one...
    if (consume(topic_ptr, topic_end, "spider/switch/"))
        // ...try to parse the switch number from the topic and the
        // on/off number from the message.
        uint8_t sw = parse_uint16( topic_ptr, topic_end);
        uint8_t onoff = parse_uint16(message.buffer, message.buffer + message.len);

        // ... and send the corresponding code.
        sendcode( sw, onoff);
More details about the implementation of sendcode() are in the source file and were described in the previous log.