Switchbot local control using ESP32. no switchbot hub used/required. works with any smarthub that supports MQTT
https://github.com/devWaves/SwitchBot-MQTT-BLE-ESP32
v7.1
Created: on Aug 17 2022
Author: devWaves
Contributions from:
Code can be installed using Arduino IDE OR using Visual Studio Code PlatformIO
Allows for "unlimited" switchbots devices to be controlled via MQTT sent to ESP32. ESP32 will send BLE commands to switchbots and return MQTT responses to the broker
based off of the work from https://github.com/combatistor/ESP32_BLE_Gateway
Notes:
\<ESPMQTTTopic> = \<mqtt_main_topic>/\<host>
- Default = switchbot/esp32
ESP32 will subscribe to MQTT 'set' topic for every configure device
- <ESPMQTTTopic>/bot/<name>/set
- <ESPMQTTTopic>/curtain/<name>/set
- <ESPMQTTTopic>/meter/<name>/set
- <ESPMQTTTopic>/contact/<name>/set
- <ESPMQTTTopic>/motion/<name>/set
Send a payload to the 'set' topic of the device you want to control
Strings:
- "PRESS"
- "ON"
- "OFF"
- "OPEN"
- "CLOSE"
- "PAUSE"
- "STATEOFF" (Only for bots in simulated ON/OFF mode)
- "STATEON" (Only for bots in simulated ON/OFF mode)
Integer 0-100 (for curtain position) Example: 50
Integer 0-100 (for setting bot hold seconds) Example: 5 (for bot only) Does the same thing as <ESPMQTTTopic>/setHold
Strings:
- "REQUESTINFO" or "GETINFO" (for bot and curtain) Does the same thing as calling <ESPMQTTTopic>/requestInfo
- "REQUESTSETTINGS" or "GETSETTINGS" (for bot only) Does the same thing as calling <ESPMQTTTopic>/requestSettings . requires getBotResponse = true
- "MODEPRESS","MODESWITCH","MODEPRESSINV","MODESWITCHINV" (for bot only) Does the same thing as <ESPMQTTTopic>/setMode
ESP32 will respond with MQTT on 'status' topic for every configured device
- <ESPMQTTTopic>/bot/<name>/status
- <ESPMQTTTopic>/curtain/<name>/status
- <ESPMQTTTopic>/meter/<name>/status
Example payload:
- {"status":"connected", "command":"ON"}
- {"status":"errorConnect", "command":"ON"}
- {"status":"errorCommand", "command":"NOTVALID"}
- {"status":"commandSent", "command":"ON"}
- {"status":"busy", "value":3, "command":"ON"}
- {"status":"failed", "value":9, "command":"ON"}
- {"status":"success", "value":1, "command":"ON"}
- {"status":"success", "value":5, "command":"PRESS"}
- {"status":"success", "command":"REQUESTINFO"}
ESP32 will respond with MQTT on 'state' topic for every configured device
- <ESPMQTTTopic>/bot/<name>/state
- <ESPMQTTTopic>/curtain/<name>/state
Example payload:
- "ON"
- "OFF"
- "OPEN"
- "CLOSE"
ESP32 will respond with MQTT on 'position' topic for every configured device
- <ESPMQTTTopic>/curtain/<name>/position
Example payload:
- {"pos":0}
- {"pos":100}
- {"pos":50}
ESP32 will Subscribe to MQTT topic to rescan for all device information
- <ESPMQTTTopic>/rescan
send a JSON payload of how many seconds you want to rescan for
example payloads =
{"sec":30}
{"sec":"30"}
ESP32 will Subscribe to MQTT topic for device information
- <ESPMQTTTopic>/requestInfo
send a JSON payload of the device you want to control
example payloads =
{"id":"switchbotone"}
ESP32 will respond with MQTT on
- <ESPMQTTTopic>/#
Example attribute responses per device are detected:
- <ESPMQTTTopic>/bot/<name>/attributes
- <ESPMQTTTopic>/curtain/<name>/attributes
- <ESPMQTTTopic>/meter/<name>/attributes
- <ESPMQTTTopic>/contact/<name>/attributes
- <ESPMQTTTopic>/motion/<name>/attributes
Example payloads:
- {"rssi":-78,"mode":"Press","state":"OFF","batt":94}
- {"rssi":-66,"calib":true,"batt":55,"pos":50,"state":"open","light":1}
- {"rssi":-66,"scale":"c","batt":55,"C":"21.5","F":"70.7","hum":"65"}
- {"rssi":-77,"batt":89,"motion":"NO MOTION","led":"OFF","sensedistance":"LONG","light":"DARK"}
- {"rssi":-76,"batt":91,"motion":"NO MOTION","contact":"CLOSED","light":"DARK","incount":1,"outcount":3,"buttoncount":4}
Example attribute responses per device are detected:
- <ESPMQTTTopic>/bot/<name>/state
- <ESPMQTTTopic>/curtain/<name>/state
- <ESPMQTTTopic>/meter/<name>/state
Example payload:
- "ON"
- "OFF"
- "OPEN"
- "CLOSE"
ESP32 will respond with MQTT on 'position' topic for every configured device
- <ESPMQTTTopic>/curtain/<name>/position
Example payload:
- {"pos":0}
- {"pos":100}
- {"pos":50}
Example topic responses specific to motion/contact sensors:
- <ESPMQTTTopic>/motion/<name>/motion Example response payload: "MOTION", "NO MOTION"
- <ESPMQTTTopic>/motion/<name>/illuminance Example response payload: "LIGHT", "DARK"
- <ESPMQTTTopic>/contact/<name>/contact Example response payload: "OPEN", "CLOSED"
- <ESPMQTTTopic>/contact/<name>/motion Example response payload: "MOTION", "NO MOTION"
- <ESPMQTTTopic>/contact/<name>/illuminance Example response payload: "LIGHT", "DARK"
- <ESPMQTTTopic>/contact/<name>/in Example response payload: "IDLE", "ENTERED"
- <ESPMQTTTopic>/contact/<name>/out Example response payload: "IDLE", "EXITED"
- <ESPMQTTTopic>/contact/<name>/button Example response payload: "IDLE", "PUSHED"
Note: You can use the button on the contact sensor to trigger other non-switchbot devices from your smarthub
When <ESPMQTTTopic>/contact/<name>/button = "PUSHED"
ESP32 will Subscribe to MQTT topic for device settings information (requires getBotResponse = true) - BOT ONLY
- <ESPMQTTTopic>/requestSettings
send a JSON payload of the device you want to control
example payloads =
{"id":"switchbotone"}
ESP32 will respond with MQTT on
- <ESPMQTTTopic>/#
Example responses per device are detected:
- <ESPMQTTTopic>/bot/<name>/settings
Example payloads:
- {"firmware":4.9,"timers":0,"inverted":false,"hold":5}
ESP32 will Subscribe to MQTT topic setting hold time on bots
- <ESPMQTTTopic>/setHold
send a JSON payload of the device you want to control
example payloads =
{"id":"switchbotone", "hold":5}
{"id":"switchbotone", "hold":"5"}
ESP32 will respond with MQTT on
- <ESPMQTTTopic>/#
ESP32 will respond with MQTT on 'status' topic for every configured device
- <ESPMQTTTopic>/bot/<name>/status
Example reponses:
- <ESPMQTTTopic>/bot/<name>/status
Example payload:
- {"status":"connected", "command":"5"}
- {"status":"errorConnect", "command":"5"}
- {"status":"errorCommand", "command":"NOTVALID"}
- {"status":"commandSent", "command":"5"}
- {"status":"busy", "value":3, "command":"5"}
- {"status":"failed", "value":9, "command":"5"}
- {"status":"success", "value":1, "command":"5"}
- {"status":"success", "value":5, "command":"5"}
- {"status":"success", "command":"REQUESTSETTINGS"}
ESP32 will Subscribe to MQTT topic to holdPress on bots. holdPress = set bot hold value, then call press on bot without disconnecting in between
- <ESPMQTTTopic>/holdPress
send a JSON payload of the device you want to control
example payloads =
{"id":"switchbotone", "hold":5}
{"id":"switchbotone", "hold":"5"}
ESP32 will respond with MQTT on
- <ESPMQTTTopic>/#
ESP32 will respond with MQTT on 'status' topic for every configured device
- <ESPMQTTTopic>/bot/<name>/status
Example reponses:
- <ESPMQTTTopic>/bot/<name>/status
Example payload:
- {"status":"connected", "command":"5"}
- {"status":"errorConnect", "command":"5"}
- {"status":"errorCommand", "command":"NOTVALID"}
- {"status":"commandSent", "command":"5"}
- {"status":"busy", "value":3, "command":"5"}
- {"status":"failed", "value":9, "command":"5"}
- {"status":"success", "value":1, "command":"5"}
- {"status":"success", "value":5, "command":"5"}
- {"status":"success", "command":"REQUESTSETTINGS"}
- {"status":"connected", "command":"PRESS"}
- {"status":"errorConnect", "command":"PRESS"}
- {"status":"commandSent", "command":"PRESS"}
- {"status":"busy", "value":3, "command":"PRESS"}
- {"status":"failed", "value":9, "command":"PRESS"}
- {"status":"success", "value":1, "command":"PRESS"}
- {"status":"success", "value":5, "command":"PRESS"}
ESP32 will Subscribe to MQTT topic setting mode for bots
- <ESPMQTTTopic>/setMode
send a JSON payload of the device you want to control
example payloads =
{"id":"switchbotone", "mode":"MODEPRESS"}
{"id":"switchbotone", "mode":"MODESWITCH"}
{"id":"switchbotone", "mode":"MODEPRESSINV"}
{"id":"switchbotone", "mode":"MODESWITCHINV"}
ESP32 will respond with MQTT on 'status' topic for every configured device
- <ESPMQTTTopic>/bot/<name>/status
Example reponses:
- <ESPMQTTTopic>/bot/<name>/status
Example payload:
- {"status":"connected", "command":"MODEPRESS"}
- {"status":"errorConnect", "command":"MODEPRESS"}
- {"status":"errorCommand", "command":"NOTVALID"}
- {"status":"commandSent", "command":"MODEPRESS"}
- {"status":"busy", "value":3, "command":"MODEPRESS"}
- {"status":"failed", "value":9, "command":"MODEPRESS"}
- {"status":"success", "value":1, "command":"MODEPRESS"}
- {"status":"success", "value":5, "command":"MODEPRESS"}
ESP32 will respond with MQTT on ESPMQTTTopic with ESP32 status
- <ESPMQTTTopic>
example payloads:
{status":"idle"}
{status":"scanning"}
{status":"boot"}
{status":"controlling"}
{status":"getsettings"}
Errors that cannot be linked to a specific device will be published to
- <ESPMQTTTopic>
Modify code for your Wifi and MQTT configurations and SwitchBot MAC addresses
Configurations to change can be found in the code under these line...
/****************** CONFIGURATIONS TO CHANGE *******************/
/********** REQUIRED SETTINGS TO CHANGE **********/
Stop when you see this line...
/********** ADVANCED SETTINGS - ONLY NEED TO CHANGE IF YOU WANT TO TWEAK SETTINGS **********/
Modify SwitchBot-BLE2MQTT-ESP32.cpp code for your Wifi and MQTT configurations and SwitchBot MAC addresses
Configurations to change can be found in the code under these line...
/****************** CONFIGURATIONS TO CHANGE *******************/
/********** REQUIRED SETTINGS TO CHANGE **********/
Stop when you see this line...
/********** ADVANCED SETTINGS - ONLY NEED TO CHANGE IF YOU WANT TO TWEAK SETTINGS **********/
static const char* host = "esp32";
static const char* host = "esp32mesh1";
static const char* meshHost = "esp32";
NOTES:
In a MESH setup, messages will be routed through the primary ESP32. The primary ESP32 will keep counts of things like contact/motion/button pushes to ensure duplicates messages are not sent out. Each ESP32 will receive the BLE data from the device, so performance is greatly increased. The first ESP32 to detect the data change will result in a faster MQTT data publish
*Meshing only works for motion sensors, contact sensors and temp meters. Add the motion/contact/meter MAC address to all or most meshed ESP32s. Add the Bot and Curtain and Plug MACs only once on the ESP32 closest to the device
Active Scanning:
- Active Scanning uses more battery on switchbot devices. It requests a read response from the switchbot devices
- Active Scanning provides more data like battery info
- Active Scanning is required by Bots and Curtains
Passive Scanning:
- Passive Scanning uses less battery on switchbot devices. It does not request a read response from the switchbot devices
- Passive Scanning does not provide battery info in most cases, but provides state (ON/OFF, temp, contact, motion, humidity ... etc)
- Passive Scanning is good enough for Motion, Contact, Meter and Plugs
by KPeyanski (Language English. based on v6.4. Home Assistant)
https://www.youtube.com/watch?v=ZskFhma8atc
by CTech&Media (Language German. based on v1.5. Home Assistant)
https://www.youtube.com/watch?v=HiBZb-IAbD8
by BangerTech (Language German. based on v6.1. OpenHab)
https://www.youtube.com/watch?v=TmtCwZbDJIU
ESP32 models that I can confirm work
ESP32 models/boards that the community has confirmed as working
ESP32 models that may not work
Known Supported SwitchBot devices and firmware versions