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

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":[]}]

2 Likes

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" }
};

I got it working, very happy! The mistake was a dumb one: I missed the /* and */ in the code before Curtains. I just changed ‘allBots’ to ‘allCurtains’ and put the mac’s there. Working very well now. Thank you for your help!

cool cool

if you are not using a specific device type (example meter/temp sensor) you will still need the variable for the allMeters map collection but you can either comment out the inside MAC addresses like in my code, or you can set it to an empty map list = { }

so if you dont have button bots, make sure it isnt scanning for the “xx:xx:xx:xx:xx:xx” bot from the default code. it will still work, but the scans will always take the max time because it will never find “xx:xx:xx:xx:xx:xx”

if you only had one curtain…

static std::map<std::string, String> allBots = {};

static std::map<std::string, String> allMeters = {};

static std::map<std::string, String> allCurtains = {
  { "curtainone", "xx:xx:xx:xx:xx:xx" }
};

This should do fine, right?


static std::map<std::string, String> allCurtains = {
  { "curtainone", "d9:d2:ea:17:af:94" },
  { "curtaintwo", "fb:ad:73:cf:25:38" }
};

static std::map<std::string, String> allMeters = {
  /*{ "meterone", "xx:xx:xx:xx:xx:xx" },
    { "metertwo", "yy:yy:yy:yy:yy:yy" }*/
};

static std::map<std::string, String> allBots = {
  /*{ "curtainone", "d9:d2:ea:17:af:94" },
    { "curtaintwo", "fb:ad:73:cf:25:38" }*/
};

yes. all good. order of variables does not matter

new version 0.17

I have added support for bot and curtain passwords

I tested the bot with password, but I would need someone else to test passwords with curtains. Please let me know

Set the password up in the app, then add your password to the Arduino code in 0.17

it will require a new arduino library installed: CRC32 (not to be confused with Arduino_CRC32)

If anyone has a switchbot humidifier and wants to help me test, I can look into implementing it

I can’t find the bluetooth calls required for the humidifier online or github, so I would be somewhat guessing. Unless someone can point me to humidifier documentation

Don’t think there is a password for the curtain bot. I can’t find the tabs for it in the app.

oh… thats weird. I just assumed there would be

maybe someone else can confirm with the app. I looked everywhere, maybe I missed a hidden tab?

cannot error when I tried to compile v.17. doing again now.

with the bot it is straight forward to set a password. weird they wouldnt have that with curtain