Skip to main content

Micropython BLE and ESP32 - SwitchBot (Part 1)

SwitchBot is a device which allows a non-internet-connected device to be automated. It has a mechanical arm that can switch on or a device. At my home, I have a few remote controls that operate on weird frequencies. An example is one of my ceiling fan which operates a 300MHz remote. In order to switch on/off the fan, I have stuck a SwitchBot to the remote.

The Micropython ESP32 BLE feature has come to a stable state but the documentation is still sparse. There is a link to the Micropython APIs doc which describes the APIs and the different roles for BLE devices and the examples can be found here

I have been trying the BLE Central Role to build an interesting project to control the smart home devices. For part 1 of the series of blogpost, I shall start with SwitchBot.

I was happy for a short while and then realised that it will be better for me to switch on/off using the remote than to use a roundabout method to control my fan. I wanted to control the fan using my Openhab setup as part of my smart home setting.

There are already 2 GitHub repositories from OpenWonderlabs and nicolas-kuechler that provided Python API to control the SwitchBot.  nicolas-kuechler has a comprehensive APIs that implements the timers and encryption. In this project using EPS32 BLE and Micropython , I have ported the "pressed", "On" and "Off" capability of the SwitchBot because this is what I need at the moment. The video shows the SwitchBot in action.

BLE Handing in Micropython

In Micropython, the BLE handling is designed as interrupt events handling. To learn about the various BLE device roles, the documentation can be found here. For this article on controlling the SwitchBot, I am using Central Role (GATT Client). In this role, I am programming the ESP32 as a client to the peripheral.  

When a function is called, the results are retrieved from the interrupt handlers. To this make the code manageable in object-oriented methodology, the interrupt handler is as an object method.  In ESP32 BLE, the connection to the device is not always successful. The connection function has to cater to multiple retries and timeout. For the SwitchBot, most of the time 5 retries are good enough to establish a connection.
One unique thing about BLE device interfacing, in order to get some of the device attributes, the request has to be written to the device handles. For the SwitchBot, to get the status of the SwitchBot, the code has to write to a "Value" handler before the data is available to retrieve from the "Status" handler.

def getStatus(self):
    This is the subset of the implementation 
    if self.connected == False:
        return 9
    self.__ble.gattc_write(self.conn_handle, self.value_handle, commands["status"], 1)
    self.ops_write == False # reset the flag
    print ("write successful")

    # write successful, read back the status
    while self.ops_read == False:
    self.ops_read == False # reset the flag
    print ("Read successful")

    result = {}
    result["status"] =  self.bot_status
    result["battery"] = self.battery
    result["firmware"] = self.firmware
    return result

In the code snippet above, gattc_write has to called before gattc_read can obtained the values.  The source code can be obtained from Github.

Stay tuned to the future posts as I will write on getting the telemetry data from MiFlora and Mi Temperature and Humidity sensor and connecting to MQTT to send the data to Openhab.


Popular posts from this blog

DIY Sonoff RF Bridge

Tasmota recently supported the RF bridge by iTead which allowed for RF 433 remote devices to be controlled/controlling using Sonoff products. e.g A handphone can be used to control a remote RF device or an RF remote control can use to control a WIFI enabled device.

By using Tasmota, I can control the device using MQTT. This idea fits exactly to my smart home plan. Here is the schematic:

I cheated a bit by having ESP01 mounted on a breakout board. This breakout board converts all the external pins to 5v which simplified the wiring and I do not need to use a voltage level shifter. Moreover, the Arduino 3.3v power does not have enough current to power the ESP reliably and I have to power it via the 5V from Arduino Uno. Next, I used an Arduino Uno prototype shield with a tiny breadboard to hold all the components together. For the RF 433 transmitter/receiver, I am using the development kits when I purchased the all-in-one Arduino development kits. An antenna is added for more sensitivity.

Using ESP-Link transparent bridge (ESP-01 and Arduino Pro Mini)

Recently stumbled across an interesting open source project ESP-Link. Its main purpose is to network-enable a non-network microcontroller (MCU) such as Arduino Uno, Pro mini or Nano using ESP8266. The author termed it as "Transparent Bridge". The ESP and MCU  communicate via the serial link and there is a companion Arduino library EL-Client for the MCU to connect up the network using MQTT, REST, TCP and UDP.
Setup I have put together an ESP-01 and an Arduino Pro Mini for this experiment. I have chosen a 3.3 version Pro mini so that I do not need to do any voltage level shifting between the I/O pins. In order to have a stable voltage source, the ESP8266 is powered by Pro Mini and the Pro Mini "RAW" pin is connected to a 5v USB power source. The RAW pin can take voltage up to 12V. The reset pin of Pro Mini is connected to GPIO 0 of ESP-01. This enables the ESP-01 to reset the Pro Mini.

I have linked up an APDS 9960 sensor to it and periodically send the luminosity a…