[toc]
Introduction
Got a few ITEAD Sonoff WiFi switches to automate my home. Why use the boring software, so I tried to hack the switches. This is a reference manual for me, but quite useful for anyone else if they want to use micropython, mqtt, web server and control the switches.
Required items
- Sonoff switch
- VCP: FTDI Cable
- yeah, 5x pin headers to solder on the board
- few jumper wires for debugging
Flashing micropython
Make sure the FTDI cable is set to 3V which is very important. Then connect the cable as detailed in the table.
Programmer | Sonoff (counting from the switch to bottom) |
3V3 | 1 |
TX | 2 (RX) |
RX | 3 (TX) |
GND | 4 |
5 |
The easiest way to flash the firmware is to use the nodemcu-flasher available. Unfortunately available only for windows. The micropython-flash image esp8266-20170108-v1.8.7.bin can be downloaded from the website. On the config tab add the image. Sometimes it helps to first flash a blank image to the WiFi switch.
INTERNAL://BLANK
Installing MQTT
Install mosquitto, an open source MQTT broker. It is very easy to install, follow the installation instructions in the link or copy paste the following commands.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key sudo | |
apt-key add mosquitto-repo.gpg.key | |
cd /etc/apt/sources.list.d/ | |
sudo wget http://repo.mosquitto.org/debian/mosquitto-wheezy.list | |
sudo wget http://repo.mosquitto.org/debian/mosquitto-jessie.list | |
sudo apt-get update | |
sudo apt-get install mosquitto |
Programming MQTT
MQTT service is started and running on the machine. I will deal with the basic programming initially. May be later, MQTT will be tightened up with security like auth, base64 encoded message etc.
there are few things to know first hand. That would be, the pins for the physical objects on the switch. There is a relay, led and a button. I want to use the button in case I m not connected to internet to be able to toggle the switch. Led is concealed inside the housing, so doesn’t matter. Relay is very important which will be switching the on off the device that is connect. This pin configuration is specific to micro python firmware. In LUA it might be different.
PIN 12-----------------replay PIN 13-----------------LED PIN 0------------Button
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from umqtt.simple import MQTTClient | |
from machine import Pin | |
import ubinascii | |
import machine | |
import micropython | |
global switch_state | |
switch_state = True | |
CLIENT_ID = ubinascii.hexlify(machine.unique_id()) | |
SERVER = 'localhost' | |
TOPIC = b"home/tv" | |
#– Pin which the relay is connected to | |
relayPin = 12 | |
p6 = Pin(relayPin, Pin.OUT) # create output pin on GPIO6 | |
#– Connected to switch with internal pullup enabled | |
# buttonPin = 0 | |
# buttonDebounce = 0 | |
# p3 = Pin(buttonPin, Pin.OUT) # create output pin on GPIO3 | |
#– MQTT led | |
mqttLed=13 | |
p13 = Pin(mqttLed, Pin.OUT) # create output pin on GPIO7 | |
p13.low() | |
def sub_cb(topic,msg): | |
global switch_state | |
print((topic, msg)) | |
if msg == b"on": | |
p13.value(0) | |
p6.value(1) | |
switch_state = 1 | |
elif msg == b"off": | |
p13.value(1) | |
p6.value(0) | |
switch_state = 0 | |
def main(server=SERVER): | |
c = MQTTClient(CLIENT_ID, server) | |
# Subscribed messages will be delivered to this callback | |
c.set_callback(sub_cb) | |
c.connect() | |
c.subscribe(TOPIC) | |
print("Connected to %s, subscribed to %s topic" % (server, TOPIC)) | |
try: | |
while 1: | |
# micropython.mem_info() | |
c.wait_msg() | |
finally: | |
c.disconnect() | |
if __name__ == '__main__': | |
main() |
Diving in to the code, there are only three parts that are done. One is the variable that is used around in all functions declared as global to keep the state known at all times. Then connect to mqtt and subscribe to a certain topic. Here I m controlling the switch for the TV system. The call back function will handle if the switch should be turned off or on. This means, just a if loop with toggling the pin 12 where the relay is connected and storing the current action in the global variable.
Securing MQTT:
coming soon
References
- http://micropython.org/webrepl/
- https://micropython.org
- http://captain-slow.dk/2016/05/22/replacing-the-itead-sonoff-firmware/
- https://docs.micropython.org/en/latest/esp8266/esp8266/tutorial/pins.html
- https://home-assistant.io/blog/2016/08/31/esp8266-and-micropython-part2/
- https://github.com/micropython/micropython-lib/tree/master/umqtt.simple