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
This commit is contained in:
stefanbode 2023-07-20 09:51:08 +02:00 committed by GitHub
parent 3da5124348
commit d1a4296867
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 42 additions and 18 deletions

View File

@ -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

View File

@ -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;

View File

@ -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) {

View File

@ -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);

View File

@ -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

View File

@ -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);
}