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

@samip537 an easy way is to add or replace the mqtt discovery messages in the code. instead of ‘switch’, use ‘light’

to create both a switch and light entity, you can replace this code…

  client.publish((home_assistant_mqtt_prefix + "/switch/" + deviceName + "/config").c_str(), ("{\"~\":\"" + (botTopic + deviceName) + "\", " +
                 + "\"name\":\"" + deviceName + " Switch\"," +
                 + "\"device\": {\"identifiers\":[\"switchbot_" + deviceMac + "\"],\"manufacturer\":\"" + manufacturer + "\",\"model\":\"" + botModel + "\",\"name\": \"" + deviceName + "\" }," +
                 + "\"avty_t\": \"" + lastWill + "\"," +
                 + "\"uniq_id\":\"switchbot_" + deviceMac + "\", " +
                 + "\"stat_t\":\"~/state\", " +
                 + "\"opt\":" + optiString + ", " +
                 + "\"cmd_t\": \"~/set\" }").c_str(), true);

with this…

  client.publish((home_assistant_mqtt_prefix + "/switch/" + deviceName + "/config").c_str(), ("{\"~\":\"" + (botTopic + deviceName) + "\", " +
                 + "\"name\":\"" + deviceName + " Switch\"," +
                 + "\"device\": {\"identifiers\":[\"switchbot_" + deviceMac + "\"],\"manufacturer\":\"" + manufacturer + "\",\"model\":\"" + botModel + "\",\"name\": \"" + deviceName + "\" }," +
                 + "\"avty_t\": \"" + lastWill + "\"," +
                 + "\"uniq_id\":\"switchbot_" + deviceMac + "\", " +
                 + "\"stat_t\":\"~/state\", " +
                 + "\"opt\":" + optiString + ", " +
                 + "\"cmd_t\": \"~/set\" }").c_str(), true);

  client.publish((home_assistant_mqtt_prefix + "/light/" + deviceName + "/config").c_str(), ("{\"~\":\"" + (botTopic + deviceName) + "\", " +
                 + "\"name\":\"" + deviceName + " Light\"," +
                 + "\"device\": {\"identifiers\":[\"switchbot_" + deviceMac + "\"],\"manufacturer\":\"" + manufacturer + "\",\"model\":\"" + botModel + "\",\"name\": \"" + deviceName + "\" }," +
                 + "\"avty_t\": \"" + lastWill + "\"," +
                 + "\"uniq_id\":\"switchbot_" + deviceMac + "_light\"," +
                 + "\"stat_t\":\"~/state\", " +
                 + "\"opt\":" + optiString + ", " +
                 + "\"cmd_t\": \"~/set\" }").c_str(), true);

you can remove the switch entity is all your bot devices are lights

I got some curtains recently and have no issues like that, there must be something going on in your MQTT.

I would suggest doing a clean install of your MQTT broker if it won’t break anything

But I want that only for those that have mode set to switch?

having both a switch and light entity shouldnt really affect anything, just display the entity you want in your dashboard etc

I dont currently have the code setup to individually chose per device

other option is to create your own HA light entity or group that calls the switch also

If you call it something like “Kitchen_Lights”, google/alexa may auto recognize as light also. In google/alexa you can sometimes manually change the device type also

Thanks for this @devWaves, it’s a great implementation. I have it working with two contact sensors with one small issue. The contacts are reading as TIMEOUT. They worked perfectly on the desk but now that they are fitted to doors I see this. When I open/close a door the state does change and then within a minute, it switches to Timeout.

I’ve probably done something wrong but I can not see it.

I have the esp32 unit only 3 metres away.

Any ideas?

Here is what I am seeing in MQTT Explorer.

I believe if the door is open for over a minute (or something like that) the door sensor will return a timeout value.

from the switchbot app it looks like ‘timeout’ = ‘left open’

these are the values returned from the switchbot contact sensor so I think you have it setup correctly. it has 3 possible values, and isnt a normal binary sensor of just open/closed

you can assume timeout is the same as open I guess.

At some point I will release a new version that has a normal binary door sensor where timeout just converts to open

Ah - thanks for that. I’ll just reverse my logic on the dashboard.

The use case I have is that I have this on a Dog Door that is downstairs. My plan is to know if the door is open or closed without having to go down and physically check. We open and close it from upstairs with a rope in a wardrobe, so there is no motion detected when it open and closes.

What I’m finding is as you said, the door when left open starts as “Open” and then changes to “Timeout”. Trouble is that when it enters the Timeout state, it never changes to “Closed” when I close the door. It is only when it detects motion that it updates the state.

Is there any documentation on ContactA and ContactB (lines 1793-1794)? In particular the role of the Timeout. I thought the timeout was to do with the motion, not the contact but it was quite a while ago I watched a review of this.

I’m thinking of a small change at line 1823 to see if the state is different than the previous stored state.
image
What do you think?

hey @madmat777 the code will already do what you are thinking. what is the rssi of the contact sensor? that plays a big role

I also have the code setup to send an ‘open’ message if the last motion/contact time on the sensor is different then the last captured ‘open’ message. In case an open was missed

the contact sensor is working for me and returns a closed after a timeout. If the esp32 is not picking up a closed service date update message you may need to place it closer

line 1856…

        std::map<std::string, std::string>::iterator itC = contactStates.find(deviceMac);
        if (itC != contactStates.end())
        {
          std::string contactState = itC->second.c_str();
          if (strcmp(contactState.c_str(), contact.c_str()) != 0) {
            shouldPublish = true;
          }

        }
        contactStates[deviceMac] = contact;

the contact sensors are set to always update if there is a state change in the service data scanned for contact or motion. motion/contact are a special case where they always need to be scanned for latest updates

the timeout documentation is here Contact Sensor BLE open API · OpenWonderLabs/python-host Wiki · GitHub

Bit[1:2]:Hal State 0:door close 1:door open 2:timeout not close
...
Byte: 8		Door Status 0:Close 1:Open 2:Timeout not close

Just following up.

It seems that the change is working for me.

Looking at the app with a new contact sensor I can see that there are 3 states that it reports
Open
Left Open (what is currently TIMEOUT in the code)
Closed

cool. I actually like the contact sensor because it has a button on it. I’ve set up the esp32 code so the button can be used. I have moved my previous zwave sensors to other doors, and use the switchbot ones on my house entrances to turn off all light/enable alarm etc when I leave

Missed your reply.

rssi is around -70

Thanks for the documentation link.

I’ve set up the esp32 code so the button can be used.

I have not purchased the contact sensor yet, but this button will be automatically created in HA as a switch?

The contact sensor button will have 2 entities auto created for the button

  1. buttonCount = a rotating number of the number of button pushes

  2. button = binary sensor possible values “IDLE” and “PUSHED”

the contact sensor data only provides the button count, but in the code I made it so if the button count changes that will create a ‘PUSHED’ action for a binary sensor

Hey guys,

The integration has been working pretty well lately except 2 things:

  1. I’ve noticed 1 of my 2 curtains sometimes open itself when not requested. I saw another user posting about the same issue few days ago. It happens very rarely, maybe once a week and upon further investigation I noticed it usually happens after it goes unavailable. I tried moving the ESP32 to a different location (within 3 meters) thinking it might be clashing with other BLE devices nearby. I’ll see if it helps.

  2. On both curtains, yesterday for 1 and today for the other curtain I noticed they just didn’t respond anymore for some reason (tested open). When checking the chip it was quite hot and the blue and red light were both on (see screenshot). Couldn’t find anything suspicious in the HA or MQTT (Supervisor Logs). Is there any other type of log I could check see what the issue was?

It worked right away after unplugging/replugging the power cable and sending the open command.

It’s been running fine overall though, much better than the API integration!!

hey @notownblues. So my curtains don’t have any issues like that

  1. My only suspicion is that the mqtt set message is being retained. whenever the esp32 connects to the mqtt broker it subscribes to the ‘set’ topic of each device. If a message is retained on a topic it receives this message the same way as a new message and will process it

you can test this behaviour by shutting down the mqtt broker and restarting it. when the esp32 reconnects it will subscribe to the topics

the fact thay it only happens to one curtain also hits that it is a retained mqtt message for that curtain

you would want qos = 0 also

  1. the red led light is power. that will always be on. the blue led light will be on anytime the esp32 is busy doing something. if you only have curtains (no motion or contact sensors) the blue light will turn off and should only be on when a ‘set’ command is received and when it is scanning. if you have contact or motion sensors the blue led light will be on all the time because it is scanning all the time

when scanning the blue light will stay on until it finds the device. the blue light will also stay on while a ‘set’ message command is being performed

if you want to see the serial output of the esp32 from your pc you can set printSerialOutputForDebugging = true in the code to see more output

1 Like

First of all: thank you for this fantastic project. I have installed it and it is up and running. With a main topic of switchbot and a host name of esp32bot. For me it looks like it is up and running and communicating with my SwitchBot. But I can’t seem to understand what to publish to control it.

I have tried sending the payload PRESS and ON to the topic switchbot/esp32bot/bot/switchbotone/set

But nothing happens.

@eirikso what u have looks correct. does your bot have a password? if yes remember to add it in the code

if you are using HA though you shouldnt have to manually send MQTT messages. the code supports MQTT discovery so you should see devices show up automatically in HA

you can watch the bot topic to see the status of commands sent. if they were sent, and successful

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

you should see 3 messages.

  1. connected 2. commandSent 3. success

I’m currently just testing, so that’s why I do this manually in MQTT Explorer. I was sure I did not set a password in my bot, but was wrong. So once I added the password to the code now and uploaded everything works fine!

Thank you again!

Hello @devWaves

First of all thanks for all the past help. I now have two ESP32 you sent me privately.
For the moment, because I only have meters, I use an ESPHome implementation I’ve found to get temperature, humidity, battery and RSSI.
And now you provide a platform.io code, it is really easier to build using command line only which is perfect for me.

Do you think I could have some benefits to migrate to your solution from ESPHome?
When (or if) Switchbot release BLE documentation for humidifier I would surely migrate, for now I would loke to know if it could change anything, especially on Home Assistant side.

If I migrate, is there a way to choose host name for the ESP32? It is the case with ESPHome which is really good.
Do you think it could be possible to add mdns to access the ESP32? Which would be very good for OTA, avoiding using IP address.