From d1a4296867fb8d48d06de1f05761fe6db2f2fe20 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Thu, 20 Jul 2023 09:51:08 +0200 Subject: [PATCH] New DEEPSLEEP topic for HA + Battery Level % support (#19134) * New LWT on deepsleep To allow better integration into HA LWT topic will report details of sleep status: 16:54:04.388 MQT: hm/tele/ESP_3284D1/LWT = {"Sleep":{"Time":"2023-07-17T16:55:03","Sleep":1689612844,"Wakeup":1689612903}} * Revert LWT back to non JSON Send DeelSleep on LWT Send Deepsleep parameters on topic DeepSleep * Setting default for batteryLevel * Enable BatteryPercentSet Changing the battery level e.g. by rule * Added Battery % to status message * added battery_level_percent * Added battery % support in STATE message * Enable setting battery level 101 is reserved for power-plug. No battery Level reported * Setting default for battery Level 101 is reserved for power plug 0..100 normal battery values * Revert back LWT to Offline Removed "DeepSleep" LWT status until further decision is made. Current implementation is technical sufficient for HA to detect a battery powered device * Added discovery message after deepsleep change * Added discovery for battery and deepsleep --- tasmota/include/tasmota_types.h | 4 +-- tasmota/tasmota_support/settings.ino | 1 + tasmota/tasmota_support/support_command.ino | 10 ++++++ tasmota/tasmota_support/support_tasmota.ino | 7 +++++ .../tasmota_xdrv_driver/xdrv_12_discovery.ino | 7 ++++- .../tasmota_xdrv_driver/xdrv_29_deepsleep.ino | 31 ++++++++++--------- 6 files changed, 42 insertions(+), 18 deletions(-) diff --git a/tasmota/include/tasmota_types.h b/tasmota/include/tasmota_types.h index 71176d653..ef5fc44f4 100644 --- a/tasmota/include/tasmota_types.h +++ b/tasmota/include/tasmota_types.h @@ -733,8 +733,8 @@ typedef struct { uint16_t artnet_universe; // 734 uint16_t modbus_sbaudrate; // 736 uint16_t shutter_motorstop; // 738 - - uint8_t free_73A[3]; // 73A + uint8_t battery_level_percent; // 73A + uint8_t free_73B[2]; // 73B uint8_t novasds_startingoffset; // 73D uint8_t web_color[18][3]; // 73E diff --git a/tasmota/tasmota_support/settings.ino b/tasmota/tasmota_support/settings.ino index 4e796b400..d1a75ff7f 100644 --- a/tasmota/tasmota_support/settings.ino +++ b/tasmota/tasmota_support/settings.ino @@ -980,6 +980,7 @@ void SettingsDefaultSet2(void) { if (Settings->sleep < 50) { Settings->sleep = 50; // Default to 50 for sleep, for now } + Settings->battery_level_percent = 101; // Module flag.interlock |= APP_INTERLOCK_MODE; diff --git a/tasmota/tasmota_support/support_command.ino b/tasmota/tasmota_support/support_command.ino index e18143040..523376296 100644 --- a/tasmota/tasmota_support/support_command.ino +++ b/tasmota/tasmota_support/support_command.ino @@ -34,6 +34,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix D_CMND_DEVICENAME "|" D_CMND_FN "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|" D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_LEDPWM_ON "|" D_CMND_LEDPWM_OFF "|" D_CMND_LEDPWM_MODE "|" D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" D_CMND_HUMOFFSET "|" D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM"|" D_CMND_GLOBAL_PRESS "|" D_CMND_SWITCHTEXT "|" D_CMND_WIFISCAN "|" D_CMND_WIFITEST "|" + D_CMND_ZIGBEE_BATTPERCENT "|" #ifdef USE_I2C D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|" #endif @@ -73,6 +74,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = { &CmndDevicename, &CmndFriendlyname, &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd, &CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndLedPwmOn, &CmndLedPwmOff, &CmndLedPwmMode, &CmndWifiPower, &CmndTempOffset, &CmndHumOffset, &CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum, &CmndGlobalPress, &CmndSwitchText, &CmndWifiScan, &CmndWifiTest, + &CmndBatteryPercent, #ifdef USE_I2C &CmndI2cScan, &CmndI2cDriver, #endif @@ -245,6 +247,14 @@ void CmndWifiTest(void) #endif //USE_WEBSERVER } +void CmndBatteryPercent(void) { + if (XdrvMailbox.payload > 101) XdrvMailbox.payload = 100; + if (XdrvMailbox.payload >= 0) { + Settings->battery_level_percent = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings->battery_level_percent); +} + #endif // not defined FIRMWARE_MINIMAL_ONLY void ResponseCmndNumber(int value) { diff --git a/tasmota/tasmota_support/support_tasmota.ino b/tasmota/tasmota_support/support_tasmota.ino index b7f51569f..c035f77ca 100644 --- a/tasmota/tasmota_support/support_tasmota.ino +++ b/tasmota/tasmota_support/support_tasmota.ino @@ -829,6 +829,13 @@ void MqttShowState(void) ResponseAppendTime(); ResponseAppend_P(PSTR(",\"" D_JSON_UPTIME "\":\"%s\",\"UptimeSec\":%u"), GetUptime().c_str(), UpTime()); + +// Battery Level expliciet for deepsleep devices +if (Settings->battery_level_percent != 101) { + ResponseAppend_P(PSTR(",\"" D_CMND_ZIGBEE_BATTPERCENT "\":%d"), Settings->battery_level_percent); +} + + #ifdef ESP8266 #ifdef USE_ADC_VCC dtostrfd((double)ESP.getVcc()/1000, 3, stemp1); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_12_discovery.ino b/tasmota/tasmota_xdrv_driver/xdrv_12_discovery.ino index 6fb523dc0..f5fa3a3f7 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_12_discovery.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_12_discovery.ino @@ -185,6 +185,8 @@ void TasDiscoverMessage(void) { "\"117\":%d}," "\"lk\":%d," // Light CTRGB linked "\"lt_st\":%d," // Light SubType + "\"bat\":%d," // Battery operates yes/no + "\"dslp\":%d," // Deepsleep configured yes/no "\"sho\":["), // Shutter Options (start) Settings->flag.mqtt_response, Settings->flag.button_swap, @@ -198,7 +200,10 @@ void TasDiscoverMessage(void) { Settings->flag5.mqtt_switches, Settings->flag5.fade_fixed_duration, light_controller_isCTRGBLinked, - light_subtype); + light_subtype, + Settings->battery_level_percent==101?0:1, + Settings->deepsleep==0?0:1 + ); for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) { #ifdef USE_SHUTTER diff --git a/tasmota/tasmota_xdrv_driver/xdrv_29_deepsleep.ino b/tasmota/tasmota_xdrv_driver/xdrv_29_deepsleep.ino index a607fa0e9..244ece57e 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_29_deepsleep.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_29_deepsleep.ino @@ -1,7 +1,7 @@ /* xdrv_29_deepsleep.ino - DeepSleep support for Tasmota - Copyright (C) 2022 Stefan Bode + Copyright (C) 2023 Stefan Bode This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -89,8 +89,9 @@ void DeepSleepReInit(void) RtcSettings.ultradeepsleep = 0; } -void DeepSleepPrepare(void) +void DeepSleepStart(void) { + char stopic[TOPSZ]; // Deepsleep_slip is ideally 10.000 == 100% // Typically the device has up to 4% slip. Anything else is a wrong setting in the deepsleep_slip // Therefore all values >110% or <90% will be resetted to 100% to avoid crazy sleep times. @@ -133,16 +134,17 @@ void DeepSleepPrepare(void) // uint32_t deepsleep_sleeptime = DEEPSLEEP_MAX_CYCLE < (RtcSettings.nextwakeup - LocalTime()) ? (uint32_t)DEEPSLEEP_MAX_CYCLE : RtcSettings.nextwakeup - LocalTime(); deepsleep_sleeptime = tmin((uint32_t)DEEPSLEEP_MAX_CYCLE ,RtcSettings.nextwakeup - LocalTime()); - // stat/tasmota/DEEPSLEEP = {"DeepSleep":{"Time":"2019-11-12T21:33:45","Epoch":1573590825}} - Response_P(PSTR("{\"" D_PRFX_DEEPSLEEP "\":{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%d}}"), (char*)dt.c_str(), RtcSettings.nextwakeup); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_PRFX_DEEPSLEEP)); + // Sending Deepsleep parameters to automation for react + Response_P(PSTR("{\"" D_PRFX_DEEPSLEEP "\":{\"" D_JSON_TIME "\":\"%s\",\"" D_PRFX_DEEPSLEEP "\":%d,\"Wakeup\":%d}}"), (char*)dt.c_str(), LocalTime(), RtcSettings.nextwakeup); + MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_PRFX_DEEPSLEEP), true); -// Response_P(S_LWT_OFFLINE); -// MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_LWT), true); // Offline or remove previous retained topic -} + // Change LWT Topic to Sleep to ensure automation see different state + //GetTopic_P(stopic, TELE, TasmotaGlobal.mqtt_topic, S_LWT); + //Response_P(PSTR(D_PRFX_DEEPSLEEP)); + //MqttPublish(stopic, true); -void DeepSleepStart(void) -{ + //MqttClient.disconnect(true); + //EspClient.stop(); WifiShutdown(); RtcSettings.ultradeepsleep = RtcSettings.nextwakeup - LocalTime(); RtcSettingsSave(); @@ -155,8 +157,10 @@ void DeepSleepStart(void) esp_deep_sleep_start(); #endif // ESP32 yield(); + } + void DeepSleepEverySecond(void) { //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("Wifi Info: up %d, wifidown %d, wifistatus %d, flag %d"),TasmotaGlobal.uptime, TasmotaGlobal.global_state.wifi_down, Wifi.status , deepsleep_flag); @@ -168,12 +172,8 @@ void DeepSleepEverySecond(void) if (!deepsleep_flag) { return; } if (DeepSleepEnabled()) { - if (DEEPSLEEP_START_COUNTDOWN == deepsleep_flag) { // Allow 4 seconds to update web console before deepsleep + if (DEEPSLEEP_START_COUNTDOWN == deepsleep_flag) { SettingsSaveAll(); - DeepSleepPrepare(); - } - deepsleep_flag--; - if (deepsleep_flag <= 0) { DeepSleepStart(); } } else { @@ -197,6 +197,7 @@ void CmndDeepsleepTime(void) Settings->tele_period = TELE_PERIOD; // Need teleperiod to go back to sleep } } + TasDiscovery(); } ResponseCmndNumber(Settings->deepsleep); }