Projects

MQTT Light Switch

Tim Blythman

Issue 3, September 2017

This article includes additional downloadable resources.
Please log in to access.

Log in

Everything has an app to control it these days, but wiring in electrical hardware to control a mains light switch is still beyond the reach of most people who aren’t actually qualified electricians. Here we put together some hardware and software, which makes controlling light switches (and other devices) a less shocking option.

For mains devices that run from a power point, it’s not quite as difficult to add some sort of remote controlled power point without worrying about messing with risky wiring, because the options are, literally, plug and play. If you want to interface into a light switch it usually means directly connecting to the wiring, with a relay to switch the power. Adding some extra hardware usually makes manual control more difficult as well.

This project creates a workaround, avoiding these two problems. The interface to the light switch does not require any mains wiring, and still allows manual control of the switch. This project uses the MQTT protocol because there are apps available that can be customised to do what we need, and it’s also a very simple protocol that an Arduino board can handle.

OVERVIEW

There are three separate parts to this project, which correspond to the three different roles that can exist in a system that operates on the MQTT protocol. A topic and message are published to a broker, which then forwards that message on to a subscriber (provided the subscriber has subscribed to that topic). In this case, I use an Android app to publish the custom data by sending a message to a topic, which is received by a single board computer running a broker program. An Arduino connected to a WiFi shield subscribes to the topic on the broker, and if it receives a message that corresponds to a command, it moves a servo motor to briefly operate a switch. It then moves the servo arm out of the way so that the switch can be manually operated. The way that MQTT can transmit different topics means that different devices can be configured to control or be controlled, while all passing through the same broker. This system lends itself to many small, simple devices like an Arduino attaching themselves to a single more sophisticated broker, which can do all the hard work of managing the messages.

HOW IT WORKS

The heart of any system using MQTT is a broker which mediates all communication. In this project, it is nothing more than a program running on a device on the network. For the sake of security, it is best that the broker is kept to being accessible only from inside the network. For testing purposes there are also MQTT brokers on the internet which can be used, such as test.mosquitto.org. If you don’t have your own broker set up, you can use this broker [1].

1
Broker

To control this project, we need something that can publish messages to the broker. I found an Android app called MQTT Dashboard [2], which was easy to configure and operate, and lets me operate the switches from a mobile device. After setting the address of the broker, a number of buttons (or sliders and other controls) can be configured to publish custom messages to any topic. The app can also be configured to subscribe to topics as well; for example, it could be set up to monitor a sensor variable such as temperature. If you don’t have this app or another one, there are also command line alternatives, which could be activated from a shortcut on a computer, and are also handy for testing.

2
MQTT Dashboard

Probably the most involved part of the build is the Arduino-based subscriber, which responds to messages from the broker. To help understand the MQTT protocol better, I worked to build the implementation from scratch. See the What the Tech article for a detailed discussion about the MQTT protocol and how it works.

The general sequence of events is that the Arduino connects to the WiFi network, then connects to the broker and sends it a connect message. When the broker sends the “connack” message, the Arduino sends a subscribe request, to which the broker replies with a “suback” message. The Arduino is now waiting for incoming messages, and when it receives a notification that matches one that it’s looking for, it activates one of the servo motors to operate the switch. The Arduino also occasionally sends a ping request to keep the connection alive. If the connection is broken, the Arduino attempts to reconnect.

The electronics are easy to build - the WiFi shield simply stacks on top of the Leonardo, and the servos can be plugged straight into the digital pin header breakouts, as they have the same pinout as the servo motors I’m using. I needed to extend the servo wires a short distance, so I used plug-socket jumper wires to do this.

The mechanical side of hardware is made of two 9G servo motors, which operate to actuate opposite sides of the switch. I had initially thought it might work with just one servo, but these have a throw of barely 180°, which isn’t enough to swing all the way around and operate both sides of the switch toggle.

Each of the servos is only activated for a second, while it moves the switch and then gets returned out of the way and into an idle position, which saves on power and also means that the servo horns are free to move if they get in the way.

THE BUILD

Parts Required: Jaycar Altronics
1 x Arduino UNO XC4410 Z6280
1 x ESP8266 Based WiFi Shield XC4614 -
2 x 9G Servo Motor YM2758 Z6392
Double Sided Tape NM2823 T2985

MQTT BROKER

With the core of any MQTT system being the broker, it is a good idea to set this up first, as you’ll need the address of the broker, at least, to set up the app and Arduino. As noted above, all that’s necessary is to install the “mosquitto” package of the broker and clients for a device on the network, and make sure it is running as a service that will be activated when that device boots. The address you will need to use for the rest of the setup is simply the IP address of this device. To test the broker, you can manually run commands. These same commands can also be used to test the Arduino later if you can’t get the app working. I’ve used these on the Yun shield, but they might be slightly different on other versions of the mosquitto software.

Open one console and run the following, replacing the IP address with your broker’s IP address (or domain name if using a public service):

  mosquitto_sub -h 192.168.0.223 -t "#'

This will display all messages coming into the broker - we’ve subscribed to the “#” wildcard (all topics) on the broker. Open another console, and issue these commands, again replacing the I address with your broker’s IP address:

  mosquitto_pub -h 192.168.0.223 -t
                lightswitch -m off
  mosquitto_pub -h 192.168.0.223 -t
                lightswitch -m on

These have the effect of publishing the messages “off” and “on” to the “lightswitch” topic. You should see “on” and “off” appear in the other console window. If you are getting this, then your broker is probably working fine.

THE CONTROLLER

The Controller

The Arduino hardware is next. Most of the assembly is quite straightforward. The first tricky part I found was positioning the servo motors to consistently actuate the switch. In my home I have the older style light switches, which have a smaller toggle than some of the newer switches, so you may find this is easier if your house is newer. If you have one of the newer “Clipsal” removable type plates, it might be feasible to glue the servo motors in place once everything is working. However, we need to be able to return ours to original condition, so have just used some double-sided tape to mount them. With some experimentation in trying to tweak the angles, I quickly found that the 0° and 180° positions were adequate; it was just a case of working out which one corresponds to “actuate” and which one corresponds to “idle”. The below code cycles between the two positions.

#include <Servo.h>
Servo s;
void setup() {
  s.attach(2);
}
void loop() {
  s.write(0);
  delay(2000);
  s.write(180);
  delay(2000);
}  

The servo motors have a serrated shaft, so it was fairly easy to set the servo motor to the “actuate” position, then reposition the arm to a suitable location.

Once the correct position is found, the arms can be fixed in place with a screw that’s included in the pack.

The next step is to attach the servos to the WiFi Shield, then plug the WiFi Shield into the Leonardo. Check the polarity of the servos: the brown wire goes into the “G” row, red into the “5V” row and signal wire into the “D” row. I’ve used D2 and D3 but these can be changed in the code. The other changes you will probably need to make to the code will be the name and password of your WiFi network, and the IP address of your broker.

//spec WIFI network and MQTT server
#define SSIDNAME "SSID"
#define SSIDPWD "PASSWORD"
#define MQTTBROKER "BROKER"
#define MQTTPORT "1883"

The MQTT port of 1883 should be the default, but can be changed if necessary. Upload the sketch to the Leonardo and monitor the serial port for debugging messages [3]. If the subscribe part completes successfully, try the publish commands on the console from earlier. These should be detected by the Arduino and displayed in the serial port. If you have the servo motors attached, they should try to move.

3
serial debug

The “1” after each item indicates that the item has completed successfully. A “0” indicates that a failure has occurred, and that command is where your troubleshooting should begin.

MQTT DASHBOARD APP

If using the MQTT Dashboard app, open the app and click the + symbol to create a new client. The only data you will need are Client ID (which is arbitrary, but it does appear as the name in the menu), broker (server) address, and broker port (1883 by default).

Tap on the new connection, and it should try to connect. If you don’t see the “Connected to…” message, then check you are connected to the WiFi network. Tap on the “Publish” tab, then the + symbol. You can use the “Subscribe” tab to monitor messages, but any topics under the “Publish” tab are also subscribed, so it’s easier to just have them on one tab. Tap on “Switch” and enter the parameters [4]. Tap “Save’, and you should see the following [5] (except for the two buttons, which I’ve added).

4
serial debug
5
serial debug

Now tap the switch, and you should see the Arduino respond. If you have a console open with the subscribe command, you should see the messages showing there as well. If you don’t have an Android device, then there are other options such as using the command line, or even using another Arduino as the controller.

WHERE TO NEXT?

The beauty of MQTT is that it allows small devices to communicate easily by having the broker do all the hard work in managing the connections and where the messages need to go.

Based around a single broker, it is possible to create a network of sensors and actuators to create an automation network. A temperature sensor can read an analog value and report it to the broker, while an app can be used to set a setpoint. An Arduino based subscriber can compare the temperature reading and setpoint and decide whether a heater should be on or off. The app can also report the reading from the temperature sensor via its subscribe tab, and if the Arduino can report the heater status back to the broker, this can be viewed in the app as well.

To add extra “responses” into the Arduino code, look for the following code in the dotopics() function, and add them below:

if(strmatch(topic,"lightswitch")
      &&strmatch(message,"on")){
  DEBUG.println("Lights on");
  doservo(3,0,180,500);
}
if(strmatch(topic,"lightswitch")
      &&strmatch (message,"off")){
  DEBUG.println("Lights off");
  doservo(2,180,0,500);
}

The if() statements simply match the topic and message to fixed strings, so it is straightforward to replace these with your own, or create extra ones. To read a numeric value, use the atoi() function, which converts a character array to an integer:

if(strmatch(topic,"temperature")
      &&(atoi message)>25)){
  Serial.println("Temperature is high");
}

If you want to publish data to the broker, there is a function WIFIsendpub() which can be used for this. For example, another Arduino on the network can have a push button, which has the effect of remotely operating the lightswitch:

if(onbuttonpressed()){
  WIFIsendpub("lightswitch","on");
}

You can even add publish functions to desktop devices, by making shortcuts for the test commands we used earlier.

MQTT BROKER INSTALLATION

At the heart of any system using MQTT is a broker, which mediates all communication. In this project it is nothing more than a program running on a device on the network. For the sake of security, it is best that the broker is accessible only from inside the network; but for testing purposes, there are also MQTT brokers on the internet that can be used, such as test.mosquitto.org. If you don’t have your own broker set up, you can use this broker, but be aware that there might be a lot of traffic on it, which could interfere with your project’s operation.

There are versions for many operating systems at Mosquitto, including Windows, Mac and many flavours of Linux. As long as the device it is installed on is available on the network all the time, then it doesn’t matter where it is installed.

For Debian Linux, which will include a Raspberry Pi running Raspbian, the following commands should be run on a terminal window:

sudo apt-get update
sudo apt-get install mosquitto-clients

The first line updates the package list with the latest versions. The process can take a few minutes or up to half-an-hour on a newly created image. The second command should run quite quickly. The end of the output should look something like this:

output

The version numbers might be different, but everything should be fine if you don’t get any error messages. I found the service was set up to run by default, which is necessary for the broker to be available after a reboot. The https://mosquitto.org/download/ page lists some basic instructions for other Linux distributions.

I found installing on Windows a bit more complicated, as it doesn’t automatically handle library dependencies. The following was tested on Windows 10, but should work on Windows 7 or later.

Download Win32OpenSSL_Light-1_0_2L from Shining Light Productions and install it using the default settings. Also download pthreadVC2.dll, and note where the file is saved.

Then download and run the Windows mosquitto installer. The installer will probably error when it tries to run mosquitto for the first time. Copy the pthreadVC2.dll file to the mosquitto folder (C:Program Files (x86)mosquitto on my system), so that it looks like this:

folder windows

To check if the mosquitto service is running, press Win+R and type ‘services.msc’. You should see the mosquitto service running. If it is not present, try rerunning the mosquitto installer (it will recognise that the .dll’s are in the right place and configure the service correctly). If it is present but not running, select it and press “Start” so that it looks like below:

windows service

Another way to test that the service is running correctly under Windows is to run the command “netstat –an” from a command prompt to check that there is a TCP service running on port 1883 (the MQTT default).

netstat test

For my version of the MQTT Light Switch project, I’ve got it set up to run on an OpenWRT router (an Arduino Yun), and this was simply a case of running these two commands to install:

opkg update
opkg install mosquitto mosquitto-client

Then go into the web configuration interface, find services settings, and make sure that the mosquitto service is enabled.

Mosquitto

A good idea is to also ensure that your broker has a consistent IP address, either through setting it to use a static IP address, or to configure your router to always allocate the same IP address with DHCP - these setting vary between routers, but might be called “DHCP Reservation” or “DHCP Allocation”. Check your router’s manual for how to do this.

If you would like to understand more about MQTT as a fundamental protocol, check out What the Tech. We have a full glossary of terms and functions using MQTT so you can expand this technology further.