devWaves / SwitchBot-MQTT-BLE-ESP32

Allows for multiple SwitchBot bots and curtains to be controlled via MQTT sent to ESP32. ESP32 will send BLE commands to switchbots and return MQTT responses to the broker. Also supports Temperature, Motion, Contact sensors
MIT License
530 stars 66 forks source link

v7 stops updating curtains & meters. #96

Closed bennyb0i closed 1 year ago

bennyb0i commented 1 year ago

After upgrading to v7.0, it seems that after the initial boot/enable of the ESP32 (or restart of the MQTT broker), MQTT data other than lastwill is no longer updated for curtains and meters (these are all that I have to test on at the moment, so could be others experiencing the same issue).

I also tried forcing the botScanTime to a set interval (120 seconds) for the devices and used onlyActiveScan = true; but doesn't seem to make a difference. No updates for any of the device attributes come in.

This has been the case with both ESP32 library v1.0.6 (currently using) and v2.0.0.

Downgrading back to v6.12 seems to make everything work again.

devWaves commented 1 year ago

There are a bunch of settings to consider. It is working for me, but I have at least one of every device type, so it is possible I missed something if only curtain and meter are in the device lists

Note:

Settings to consider: 1.

static const int defaultCurtainScanAfterControlSecs = 30;    // Default How many seconds to wait for state/status update call after set/control command. *override with botScanTime list. Also used by scanWhileCurtainIsMoving
static const bool scanAfterControl = true;                   // perform requestInfo after successful control command (uses botScanTime).

static const bool scanWhileCurtainIsMoving = true;           // The ESP32 will scan for defaultCurtainScanAfterControlSecs seconds after control to keep the position slider in sync with the actual position

if scanAfterControl = true. when a command is sent to curtain is will scan after 30 secs for a state update. If scanWhileCurtainIsMoving = true, it will scan for the entire 30 secs while the curtain is moving

2.

static const int defaultCurtainMQTTUpdateSecs = 600;         // Used only when alwaysMQTTUpdate = false. Default MQTT Update for curtain every X seconds.  Note: a change in state will be always be published either way during active scanning
static const int defaultMeterMQTTUpdateSecs = 600;           // Used only when alwaysMQTTUpdate = false. Default MQTT Update for meter temp sensors every X seconds. Note: a change in state will be always be published either way at all times (active or passive)

MQTT will only update every 600 seconds if there is a change in state/value. This is to avoid sending overloading MQTT with messages when the state hasn't changed

3.

static const int defaultCurtainActiveScanSecs = 1800;        // Default Active Scan for curtain every X seconds if not active scanned since X seconds. *override with botScanTime list.
static const int defaultMeterActiveScanSecs = 3600;          // Default Active Scan for meter temp sensors every X seconds if not active scanned since X seconds. *override with botScanTime list.
static const bool activeScanOnSchedule = true;               // perform an active scan on decice types based on the scheduled seconds values for XXXXActiveScanSecs

If activeScanOnSchedule = true, every 1800/3600 seconds an active scan will be performed on curtain and meter. It may only MQTT update if there is a change in state/value

4.

static const bool autoRescan = true;                         // perform automatic rescan (uses rescanTime and initialScan).
static const int rescanTime = 10800;                         // Automatically perform a full active scan for device info of all devices every X seconds (default 3 hours). XXXXActiveScanSecs will also active scan on schedule

every 10800 seconds an active scan is performed, I believe it will update MQTT even if the state has not changed

5.

static const bool alwaysMQTTUpdate = false;                  // If the ESP32 is scanning, always publish MQTT data instead of using set times. ***Note: This creates a lot of MQTT traffic

If the ESP32 is scanning already, send MQTT messages even if the state hasn't changed. This will send a ton of MQTT messages and will load up HA logs etc

6.

static const bool onlyActiveScan = false;                    // Active scanning requires more battery from the BLE switchbot devices. If false, passive scanning is used when possible for contact/motion
static const bool onlyPassiveScan = false;                   // If this ESP32 is a mesh ESP32 or you only have motion/contact/meter sensors. Passive scanning uses less battery from BLE switchbot devices. Passive scanning provides less data then active scanning, but uses less battery

When scanning, it will only do one type of scanning. Only one value should be set to true if you want only one type of scanning. It will scan based on the schedules times

7.

static const bool alwaysActiveScan = false;                  // No battery optimizations. If you are using the switchbot hub or app to control devices also and you want immediate state updates for bot and curtains in MQTT set to true

if alwaysActiveScan = true, 100% of the time the ESP32 will be active scanning. The ESP32 will never be idle.

So if you want to test, and you want the ESP32 to always be active scanning, and always be MQTT updating then set: alwaysMQTTUpdate = true alwaysActiveScan = true

bennyb0i commented 1 year ago

Thanks for the feedback. I should have also mentioned in my original post that the curtain actually updates as it should when given a command to open/close (per your note #1) so this seems to be working fine.

That said, I tested with alwaysMQTTUpdate = true and alwaysActiveScan = true and confirmed that the devices do get polled and this data is being sent to MQTT (indeed the curtain spews out MQTT traffic like crazy, while the meters are only a few times every minute), so that's good.

I then set alwaysMQTTUpdate = false while leaving alwaysActiveScan = true and MQTT updates slowed down and only came in at the expected intervals (akin to your note #2). I assume, though, that keeping alwaysActiveScan on is unecessarily wasting energy.

So, setting alwaysMQTTUpdate = true and alwaysActiveScan = false, but also setting defaultMeterActiveScanSecs = 60 (akin to your note #3), the ESP32 just sat there with status "idle" the entire time and never changed to "activescanning" in the 15 or so minutes I tested it. I can confirm that the actual temperature meter readings had changed in that interval.

Finally, setting rescanTime = 60 with alwaysMQTTUpdate = true and alwaysActiveScan = false, the ESP32 status flipped to "activescanning" every 60 seconds or so, and all devices reported updates to MQTT each time as expected during the testing interval.

Anecdotally it seems that at least defaultXXXXActiveScanSecs is being ignored in favor of rescanTime, and without explicitly requesting an active update (or alternatively sending a command in the case of the curtains), the devices won't publish their update to MQTT.

devWaves commented 1 year ago

I then set alwaysMQTTUpdate = false while leaving alwaysActiveScan = true and MQTT updates slowed down and only came in at the expected intervals (akin to your note #2). I assume, though, that keeping alwaysActiveScan on is unecessarily wasting energy.

correct alwaysActiveScan would technically use more battery on the devices. I am using undocumented features to passive scan. in v6.10 and before the esp32 is always active scanning if contact and motion were included

So, setting alwaysMQTTUpdate = true and alwaysActiveScan = false, but also setting defaultMeterActiveScanSecs = 60 (akin to your note #3), the ESP32 just sat there with status "idle" the entire time and never changed to "activescanning" in the 15 or so minutes I tested it. I can confirm that the actual temperature meter readings had changed in that interval.

if meters are included you should see updates using passive scanning, so ensure activeScanOnly is set to false. Let me know, if it isnt I will take a look why. Meters/contact/motion can get data using passive scanning

Finally, setting rescanTime = 60 with alwaysMQTTUpdate = true and alwaysActiveScan = false, the ESP32 status flipped to "activescanning" every 60 seconds or so, and all devices reported updates to MQTT each time as expected during the testing interval.

Anecdotally it seems that at least defaultXXXXActiveScanSecs is being ignored in favor of rescanTime, and without explicitly requesting an active update (or alternatively sending a command in the case of the curtains), the devices won't publish their update to MQTT.

if rescanTime is a smaller value than all the values of defaultXXXXActiveScanSecs then yes they will basically be ignored. defaultXXXXActiveScanSecs will active scan only if it hasnt for that long. a full rescanTime will reset the timer to 0

bennyb0i commented 1 year ago

if meters are included you should see updates using passive scanning, so ensure activeScanOnly is set to false. Let me know, if it isnt I will take a look why. Meters/contact/motion can get data using passive scanning

Yep, onlyActiveScan = false was set for all of these last tests.

if rescanTime is a smaller value than all the values of defaultXXXXActiveScanSecs then yes they will basically be ignored. defaultXXXXActiveScanSecs will active scan only if it hasnt for that long. a full rescanTime will reset the timer to 0

Right, that makes sense. In my test cases, I just left the rescanTime set at the default 10800 seconds, while I adjusted the defaultMeterActiveScanSecs to 60 seconds to see if it would override the rescanTime setting which it seems it didn't.

devWaves commented 1 year ago

ok cool, I will take a look and try with just curtain and meters to see if I can reproduce

devWaves commented 1 year ago

@bennyb0i thanks for testing. I believe i fixed the issues in my v7.1 branch here https://github.com/devWaves/SwitchBot-MQTT-BLE-ESP32/tree/v7.1

I will release this later today, but should be good for testing and will be the same once released. Cheers

bennyb0i commented 1 year ago

Cool, I'll give it a whirl after work today. Thanks!

devWaves commented 1 year ago

Thanks. I just decided to add another change before releasing v7.1. To cover the scenario where a device can't be found, I don't want it to continually active scanning trying to find it. Shouldn't be long

DrRSatzteil commented 1 year ago

Should have read this thread before installing the 7.0 version 😅 I have the same issues but I'm happy to test 7.1 once it's ready 😊

devWaves commented 1 year ago

Hey. The code for v7.1 is released. It should have the issues reported here fixed

I didn't get around to finishing the new additions to stop active scanning if a device cannot be found. It's a bit more complicated then I originally thought

Use Arduino ESP32 core v1.0.6 as it has been determined there are issues with version 2.0 and greater. I will release v7.1 as a packaged release once I confirm the other PR for platform IO https://github.com/devWaves/SwitchBot-MQTT-BLE-ESP32/pull/93 works with version 3.5.0 of the Platform IO ESP32 library

DrRSatzteil commented 1 year ago

Works for me! Thank you for this quick fix and this great firmware :)

bennyb0i commented 1 year ago

Hey there, finally had a chance to update the firmware to v7.1, and just wanted to drop a note that it's working perfectly for me now too. Thanks so much for your hard work! 😄