Sonoff S20 (specs) is a smart power outlet that is controllable with a WiFi connection. The device comes with a built-in firmware and an accompanied mobile app, but it is also possible to flash it with custom firmware. This allows to control the device with standard MQTT protocol making integration to DIY home automation or IoT cloud systems easier. This post provides a step-by-step guide how to flash the device and also examples how to interface with it using MQTT.

The Sonoff S20 device is built around the popular ESP8266 WiFi module. I have the EU version, but the S20 is also available for other socket types. The firmware I’m going to install is Sonoff-Tasmota which is available in GitHub. The Sonoff device family also has other devices that are supported by this custom firmware. This guide focuses on the S20 and the instructions are for Linux host. However, the main steps should also work, with minor tweaking, with other platforms and different Sonoff devices.

Hardware preparations

Flashing this device is easy thanks to serial port pins available on the PCB and easily accessible programming mode. Therefore only a couple of things need to be done hardware-wise as preparation. Obviously the enclosure needs to be opened to access the serial port. To open the enclosure, first remove a screw that it is holding the two halves together. It is located on the back side under a small sticker (not the device info sticker). After the screw has been removed a sharp tool might be needed to wedge the enclosure open. I also removed the PCB from the back side for easier handling. To do so simply remove the two small screws inside.

Depending on your serial port adapter you might need to solder a pin header to the empty serial port connectors and use jumper wires. The USB-serial adapter I picked up from iTead already had matching pinout so I was able to flash the device without soldering (it also has selectable 3,3V and 5V IO-voltage, convenient). Make sure to use 3,3V voltage when working with these devices!

Development environment

To build the Tasmota firmware a suitable development environment is needed. I opted for Platform.IO and Visual Studio Code due to very straight forward installation. Alternatively, it is possible to use Arduino IDE. Steps to configure it are found from the Tasmota Wiki.

First download and install the VS Code by following the instructions on the site. Launch the editor and go to extensions page (Ctrl-Shift+X). Search for “PlatformIO IDE” and install the extension.

Next clone or download the Sonoff-Tasmota repository to your machine and open the project root folder in VS Code (File -> Open Folder…). The development environment is now ready to build the project.

Open platformio.ini and uncomment one of the env_default lines to select which version is built. I selected the standard: “env_default = sonoff”. Start the build. Shortcut is Ctrl+Alt+b, or you can use the command menu. Open it with Ctrl+Shift+P and type the command you’re looking for to the search, e.g. “build”. You might also want to take a look to the user_config.h to set e.g. the default MQTT configuration. This can also be done later using a Web configuration interface.

Terminal should open to the bottom of the screen and you should see build output similar to the one below.

Compiling .pioenvs/sonoff/src/sonoff.ino.o Linking .pioenvs/sonoff/firmware.elf Calculating size .pioenvs/sonoff/firmware.elf text data bss dec hex filename 471265 8260 34624 514149 7d865 .pioenvs/sonoff/firmware.elf Building .pioenvs/sonoff/firmware.bin === [SUCCESS] Took 8.54 seconds === === [SUMMARY] === Environment sonoff [SUCCESS] Environment sonoff-minimal [SKIP] Environment sonoff-ds18x20 [SKIP] === [SUCCESS] Took 8.54 seconds ===

The final firmware binary is written to .pioenvs/sonoff/firmware.bin file.

Flashing the firmware

To flash the device, the serial port needs to be connected to PC and the Sonoff needs to be started in programming mode.

Warning: never connect the serial port when the Sonoff is connected to mains power.

The image below shows how I connected the USB-serial. The one I got had matching pinout so I was able to directly connect it to the device. It was a bit fiddly but I was too lazy to solder the pin headers (the DTR line in the converter was not used so I bent it a bit and put some electric tape on it to prevent it from shorting to PCB). Depending on your converter you might need to solder the pin header and wire it to the converter. The pinout shown in the image below on the converter side is VCC, TXD, RXD and GND from left to right (DTR unused). Note that the RX and TX lines are crossed, i.e. TXD on the converter is connected to RXD on the Sonoff.

Next the Sonoff device is booted to programming mode. This is done by holding down the button while powering the device (the device is powered from the serial port VCC). I did it by holding the button while inserting the serial converter USB cable to PC.

Now the firmware can be uploaded using PlatformIO development environment. The shortcut is Ctrl+Alt+U. Though, for me the PlatformIO tried to use a wrong serial port, so I just decided to use esptool.py Python loader instead. Below is an example command for the python tool. The firmware.bin is the one from the PlatformIO build earlier.

sudo python esptool.py --port /dev/ttyUSB0 write_flash 0x00000 firmware.bin

If the device is in the programming mode, the flashing should start immediately. Below is an example log from the esptool. If the device is not detected, just power it down and try again.

esptool.py v2.0.1 Connecting.... Detecting chip type... ESP8266 Chip is ESP8266 Uploading stub... Running stub... Stub running... Configuring flash size... Auto-detected Flash size: 1MB Compressed 483680 bytes to 330894... Wrote 483680 bytes (330894 compressed) at 0x00000000 in 29.3 seconds (effective 132.3 kbit/s)... Hash of data verified. Leaving... Hard resetting...

The device now has a custom firmware! The Tasmota firmware support over-the-air update so next time you won’t be needed the serial cable.

Configuration

You should now remove the USB-serial cable and connect the device to mains power. I would also strongly recommend to assemble the device before the mains are connected.

First the WiFi needs to be configured. If you already set the correct settings to user_config.h before compilation, you can skip this step. When the device is powered up, press the button 4 times to enter the configuration mode. The LED starts to flash when the configuration mode is active. The device then creates a WiFi access point and the configuration UI is available in IP 192.168.4.1. Set the credentials and restart the device.

When the device is running in normal mode, you can connect to it’s Web interface from your WiFi. I checked the IP address from my router. The image below shows the configuration view. Here you can try to toggle the relay and more importantly set the MQTT settings in the configuration page.

I installed mosquitto MQTT broker to my laptop for testing purposes. So I just configured my laptop IP to the Sonoff device as the broker. You should also set a unique topic for each device so they don’t send messages to same topics. I set mine, imaginatively, to “sonoff1”.

Testing the MQTT interface

You can now control the relay by sending the device MQTT commands. I named my device “sonoff1” so it’s output can be toggled by sending toggle command (the command is simply ascii text “toggle”) to topic cmnd/sonoff1/power. Below is an example with mosquitto_pub command line MQTT client.

mosquitto_pub -h localhost -t "cmnd/sonoff1/power" -m toggle

Here the MQTT broker address is localhost because I ran the command from same laptop where I had the mosquitto broker running. Obviously you need to change this to match with the broker you are using. For other topics the Tasmota firmware supports, see the MQTT topic specification here. In addition to controlling the device you can also subscribe to status and telemetry topics to receive messages from the device.

mosquitto_sub -h localhost -t "tele/sonoff1/#"

This command subscribes (starts to listen) to all telemetry messages from the sonoff1 device (# is a wildcard).

I have also done a minimal standalone JavaScript example that shows an another example how to control these devices. The example code can be found here.

This is a standalone web page so you can just download the file and open it in a browser. In this example the browser connects directly to the broker, and when the button is pressed it sends a toggle message to the device. Make sure to edit the broker address on line 22 and the device command topic on line 32 to match with your configuration.

The JavaScript MQTT client library uses Web-sockets (hence the port 1884) so make sure your broker supports them. If you are using mosquitto, Web-socket can be enabled by adding the following lines to the configuration (most likely found from /etc/mosquitto/mosquitto.conf)

listener 1883 listener 1884 protocol websockets

These were just two examples how you can interface with these devices. MQTT clients are available for many different languages (C, C++, Java, C#, Python and JavaScript to name a few) so you can pick your favourite technology. Alternative you could connect these devices to many IoT cloud systems that support MQTT or use a ready-made MQTT app. One possible approach is to have a local MQTT broker and bridge selected topics to and from the cloud system. This allows more control over what data is exposed and what functions are possible from the remote system. All in all, with the MQTT support the Sonoff S20 seems like a pretty solid and cost-efficient component for DIY home automation.