SwitchBot bot/curtain/meter/contact/motion MQTT ESP32 bridge - Local control

To test in HA using developer tool. Change the id to your curtain name.

I made a MQTT Cover just for open/close

cover:
  - platform: mqtt
    name: "MQTT Cover"
    command_topic: "switchbotMQTT/control"
    qos: 0
    retain: true
    payload_open: "{\"id\":\"Curtain_Name\",\"value\":\"open\"}"
    payload_close: "{\"id\":\"Curtain_Name\",\"value\":\"close\"}"
    payload_stop: "{\"id\":\"Curtain_Name\",\"value\":\"pause\"}"

Thanks for help - best support ever :slight_smile:

1 Like

I found one wired behavior of ESP32.
It’s look like reconnecting WiFi every 30minutes.
There is a screen shot after this night. Rozłączono = disconnected and podłączono = connected

I will leave mine plugged in for 30 min and see what happens. I don’t have any 30 min settings though

according to my router mine has been connected for 42 hours.

is anyone else noticing 30 minute wifi reconnects?

Its a very short disconnect.
I set up a push notification for ESP32 on my Deco App (Tplink Mesh App)

I made a test now. I disabled mesh network for ESP32. Maybe I recive this notification because it’s change access point connected to.

ya not sure. mine still shows connected. havent done a 30 min test yet, but my guess is something with your network

the code does reconnect, but should only when it fails

is the esp32 rebooting? is overheating? would it be in direct sunlight?

you should see mqtt rescan on reconnect…i think. every time a connection is established the rescan occurs and the esp32 subcribs to mqtt topics

I left mine plugged into pc for 2h, no reboots, no wifi reconnects

Great development!

I am wondering if there should be any delay between sending the MQTT commant to open the curtain and actually open the curtain? Is anyone able to share their expierence with this? Assuming the bluetooth connection is fine.

With the bot, it is somewhat instantaneous but you can get a second or two delay depending on the distance between the esp32 and the bot. My esp32 is close to my coffee switchbot, it works basically instantly. My printer switchbot which is across the house takes a couple secs

the esp32 will send connect ble commands until it connects, and then will send the control commands. the process of connecting is where a delay might occur. sending the control command is instantaneous

but from testing, the switchbot app is no better in terms of delay. When you open the switchbot app I believe it performs the connect commands, sometimes this can take a long time. Once connected you can click the buttons to controls, this part is fast, just like my esp32 setup

the esp32 has to scan all ble network mac addresses, so if you have a ton of ble devices around you the scan may take longer

the bot and curtain ble calls work basically the same

1 Like

I can also confirm, that I don’t notice any reconnects.

Compiling in Arduino 1.8.12 gives me this error:

image

Any clue what I am doing wrong?

did u accidentally add or delete a curly bracket? { or } somewhere?

it is saying it cant find the sendtodevice method

1 Like

Thanks, not sure what happend, but started with a clean project which is compiled without any issues now.

Thank you for making this awesome BT Bridge. I’ve gotten a long way, but I can’t get it working. The ESP is connected to the WiFi, I see this in the router… I see that it has also connected to my MQTT, but after that, nothing.

I’ve tried the cover that MaRith made. And I tried the developer tool like duceduc showed (though pasting the code with the { } in the Payload Template gives an error}. I’ve also tried doing the mac address for the curtains in lower and upper case

Is there any way to check if the ESP is connected to the Switchbots? In Node Red I’ve made a MQTT-node that reports to a debugnode, but I see nothing. Do I need to pair the curtainbots to the ESP first?

What would be a good next step?

After you uploaded the code to esp32, unplug the esp32 from pc and plug it back in. From MQTT Explorer (if you are using that), you should see data (batt, position, etc) for your curtain bot. ESP does an initial scan for any bots you have added to the code.

The screenshot I provided above is for moving the bot and not the curtain. If you have the curtain bot change the id name to the name you have added to the code and change press to either open or close.

At the very least, you should see something like this. Bot will say curtain for you and there should be some data. If not, check to make sure your mac is typed correctly.
2021-03-27_9-34-07

if u are using node red, if u have the mqtt settings correct, at a minimum you should see some traffic on switchbotMQTT/# even if the bots arent configured correctly

so an “mqtt in” node on switchbotMQTT/# connected to debug node should show at least a scanning payload

if all that fails you can try the serial monitor in arduino ide while the esp32 is plugged into your pc. it will show the scanning process on boot.

Here is a node red flow of all the possible commands

[{"id":"e928d895.b4f3f8","type":"mqtt out","z":"78a02b1d.cd6ac4","name":"","topic":"switchbotMQTT/control","qos":"0","retain":"","broker":"","x":750,"y":340,"wires":[]},{"id":"1ad39652.5f243a","type":"inject","z":"78a02b1d.cd6ac4","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"switchbotone Press","payloadType":"str","x":210,"y":200,"wires":[["32663f84.07ab3"]]},{"id":"32663f84.07ab3","type":"change","z":"78a02b1d.cd6ac4","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.id","pt":"msg","to":"switchbotone","tot":"str"},{"t":"set","p":"payload.value","pt":"msg","to":"press","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":200,"wires":[["e928d895.b4f3f8"]]},{"id":"847d33a1.22f14","type":"mqtt in","z":"78a02b1d.cd6ac4","name":"","topic":"switchbotMQTT/#","qos":"0","datatype":"auto","broker":"","x":200,"y":940,"wires":[["cdc2ab45.0ed848"]]},{"id":"cdc2ab45.0ed848","type":"debug","z":"78a02b1d.cd6ac4","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":390,"y":940,"wires":[]},{"id":"c355d116.11846","type":"change","z":"78a02b1d.cd6ac4","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.id","pt":"msg","to":"switchbotone","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":740,"wires":[["1b91e65c.a4718a"]]},{"id":"f5242df7.717d8","type":"inject","z":"78a02b1d.cd6ac4","name":"requestInfo switchbotone","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":250,"y":740,"wires":[["c355d116.11846"]]},{"id":"1b91e65c.a4718a","type":"mqtt out","z":"78a02b1d.cd6ac4","name":"","topic":"switchbotMQTT/requestInfo","qos":"0","retain":"","broker":"","x":740,"y":780,"wires":[]},{"id":"f42a2207.f00dd","type":"change","z":"78a02b1d.cd6ac4","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.sec","pt":"msg","to":"30","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":600,"wires":[["a3de9e49.0406d"]]},{"id":"73a70d2f.fc4194","type":"inject","z":"78a02b1d.cd6ac4","name":"rescan all devices for 30 sec","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":220,"y":600,"wires":[["f42a2207.f00dd"]]},{"id":"a3de9e49.0406d","type":"mqtt out","z":"78a02b1d.cd6ac4","name":"","topic":"switchbotMQTT/rescan","qos":"0","retain":"","broker":"","x":670,"y":600,"wires":[]},{"id":"a468aac3.31c578","type":"inject","z":"78a02b1d.cd6ac4","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"switchbotone On","payloadType":"str","x":220,"y":260,"wires":[["a8e3176e.192fa8"]]},{"id":"ea2ac66f.14f768","type":"inject","z":"78a02b1d.cd6ac4","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"switchbotone Off","payloadType":"str","x":220,"y":300,"wires":[["7aba0887.ec3d88"]]},{"id":"7b0f894.ddb5478","type":"inject","z":"78a02b1d.cd6ac4","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"curtainone open","payloadType":"str","x":220,"y":360,"wires":[["77bcf34c.534e2c"]]},{"id":"59fbb969.69e6f8","type":"inject","z":"78a02b1d.cd6ac4","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"curtainone close","payloadType":"str","x":220,"y":400,"wires":[["fb7f49ec.f7ea28"]]},{"id":"8fe869a3.b62668","type":"inject","z":"78a02b1d.cd6ac4","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"curtainone pause","payloadType":"str","x":220,"y":440,"wires":[["fbe31aee.45e908"]]},{"id":"91ea7890.619c58","type":"inject","z":"78a02b1d.cd6ac4","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"curtainone 50%","payloadType":"str","x":220,"y":480,"wires":[["f797e20.bae152"]]},{"id":"a8e3176e.192fa8","type":"change","z":"78a02b1d.cd6ac4","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.id","pt":"msg","to":"switchbotone","tot":"str"},{"t":"set","p":"payload.value","pt":"msg","to":"on","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":260,"wires":[["e928d895.b4f3f8"]]},{"id":"7aba0887.ec3d88","type":"change","z":"78a02b1d.cd6ac4","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.id","pt":"msg","to":"switchbotone","tot":"str"},{"t":"set","p":"payload.value","pt":"msg","to":"off","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":300,"wires":[["e928d895.b4f3f8"]]},{"id":"77bcf34c.534e2c","type":"change","z":"78a02b1d.cd6ac4","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.id","pt":"msg","to":"curtainone","tot":"str"},{"t":"set","p":"payload.value","pt":"msg","to":"open","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":360,"wires":[["e928d895.b4f3f8"]]},{"id":"fb7f49ec.f7ea28","type":"change","z":"78a02b1d.cd6ac4","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.id","pt":"msg","to":"curtainone","tot":"str"},{"t":"set","p":"payload.value","pt":"msg","to":"close","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":400,"wires":[["e928d895.b4f3f8"]]},{"id":"fbe31aee.45e908","type":"change","z":"78a02b1d.cd6ac4","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.id","pt":"msg","to":"curtainone","tot":"str"},{"t":"set","p":"payload.value","pt":"msg","to":"pause","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":440,"wires":[["e928d895.b4f3f8"]]},{"id":"f797e20.bae152","type":"change","z":"78a02b1d.cd6ac4","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.id","pt":"msg","to":"curtainone","tot":"str"},{"t":"set","p":"payload.value","pt":"msg","to":"50","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":480,"wires":[["e928d895.b4f3f8"]]},{"id":"d9df9544.5351d8","type":"change","z":"78a02b1d.cd6ac4","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.id","pt":"msg","to":"curtainone","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":780,"wires":[["1b91e65c.a4718a"]]},{"id":"3492d070.7cec8","type":"inject","z":"78a02b1d.cd6ac4","name":"requestInfo curtainone","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":240,"y":780,"wires":[["d9df9544.5351d8"]]},{"id":"f2bc46c2.e5a7a8","type":"change","z":"78a02b1d.cd6ac4","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.id","pt":"msg","to":"meterone","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":820,"wires":[["1b91e65c.a4718a"]]},{"id":"a02603ec.10dcf","type":"inject","z":"78a02b1d.cd6ac4","name":"requestInfo meterone","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":240,"y":820,"wires":[["f2bc46c2.e5a7a8"]]},{"id":"501dcb12.6cbd14","type":"comment","z":"78a02b1d.cd6ac4","name":"Control","info":"","x":90,"y":140,"wires":[]},{"id":"43f1d529.bc8d4c","type":"comment","z":"78a02b1d.cd6ac4","name":"rescan","info":"","x":90,"y":540,"wires":[]},{"id":"2ffa267f.a3c9ca","type":"comment","z":"78a02b1d.cd6ac4","name":"requestInfo","info":"","x":80,"y":680,"wires":[]},{"id":"aea4d397.24f91","type":"comment","z":"78a02b1d.cd6ac4","name":"main topic debugging","info":"","x":120,"y":880,"wires":[]}]

Thank you both, this was very helpfull. I haven’t got it working though.

When the ESP is plugged in to my pc and I look in the serial monitor, I see that is working; it sees the curtains and it even sees the bluetooth of the neighbors television. So the bluetooth is working. When I try to send a command, the ESP sees it, but it gives me an error, I’ve pasted it below. I’ve redacted the numbers, but the name was already empty

Starting NimBLE Client
Advertised Device found: Name: , Address: d9:**, manufacturer data: 5**, serviceUUID: cb**
Service Data:
UUID: 0x0d00, Data: c⸮Ec1
Advertised Device found: Name: , Address: fb:**, manufacturer data: 5**, serviceUUID: cb**
Service Data:
Processing Control MQTT...
Device: curtainone
Device value: close
Parsing failed = device not from list

I’ve pasted your flows in Node Red and the MQTT is connected. I’m getting these errors. Any clues of where I might of made a mistake?

27-3-2021 10:01:59node: cdc2ab45.0ed848
switchbotMQTT/ESP32 : msg.payload : string[24]
"{"status":"errorJSONId"}"
27-3-2021 10:06:20node: cdc2ab45.0ed848
switchbotMQTT/ESP32 : msg.payload : string[28]
"{"status":"errorJSONDevice"}"

The formatting for your devices are inputted correctly?

static std::map<std::string, std::string> allBots = {
  { "24hr_fan", "fa:67:52:87:50:r4" },
  { "floor_heat", "e7:p4:41:cc:k8:ea" },
  { "jcom_tv_box", "f4:8f:09:cd:e2:c2" }
};