mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-30 14:16:32 +00:00
Refactor deepsleep
Refactor deepsleep allowing time to update GUI before going to sleep (#6890)
This commit is contained in:
parent
584a25de6b
commit
fa03f57ca8
@ -603,13 +603,18 @@ void WifiDisconnect(void)
|
||||
WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters
|
||||
}
|
||||
|
||||
void EspRestart(void)
|
||||
void WifiShutdown(void)
|
||||
{
|
||||
delay(100); // Allow time for message xfer - disabled v6.1.0b
|
||||
if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT
|
||||
MqttDisconnect();
|
||||
}
|
||||
WifiDisconnect();
|
||||
}
|
||||
|
||||
void EspRestart(void)
|
||||
{
|
||||
WifiShutdown();
|
||||
// ESP.restart(); // This results in exception 3 on restarts on core 2.3.0
|
||||
ESP.reset();
|
||||
}
|
||||
|
@ -116,6 +116,8 @@ const uint16_t SYSLOG_TIMER = 600; // Seconds to restore syslog_level
|
||||
const uint16_t SERIALLOG_TIMER = 600; // Seconds to disable SerialLog
|
||||
const uint8_t OTA_ATTEMPTS = 5; // Number of times to try fetching the new firmware
|
||||
|
||||
const uint16_t TELE_PERIOD_START = 10000; // Initial tele_period until wifi connected
|
||||
|
||||
const uint16_t INPUT_BUFFER_SIZE = 520; // Max number of characters in (serial and http) command buffer
|
||||
const uint16_t FLOATSZ = 16; // Max number of characters in float result from dtostrfd (max 32)
|
||||
const uint16_t CMDSZ = 24; // Max number of characters in command
|
||||
|
@ -104,7 +104,6 @@ int ota_state_flag = 0; // OTA state flag
|
||||
int ota_result = 0; // OTA result
|
||||
int restart_flag = 0; // Tasmota restart flag
|
||||
int wifi_state_flag = WIFI_RESTART; // Wifi state flag
|
||||
int tele_period = 1; // Tele period timer
|
||||
int blinks = 201; // Number of LED blinks
|
||||
uint32_t uptime = 0; // Counting every second until 4294967295 = 130 year
|
||||
uint32_t loop_load_avg = 0; // Indicative loop load average
|
||||
@ -114,6 +113,7 @@ float global_temperature = 9999; // Provide a global temperature to b
|
||||
float global_humidity = 0; // Provide a global humidity to be used by some sensors
|
||||
float global_pressure = 0; // Provide a global pressure to be used by some sensors
|
||||
char *ota_url; // OTA url string pointer
|
||||
uint16_t tele_period = TELE_PERIOD_START; // Tele period timer
|
||||
uint16_t mqtt_cmnd_publish = 0; // ignore flag for publish command
|
||||
uint16_t blink_counter = 0; // Number of blink cycles
|
||||
uint16_t seriallog_timer = 0; // Timer to disable Seriallog
|
||||
@ -846,8 +846,13 @@ void PerformEverySecond(void)
|
||||
ResetGlobalValues();
|
||||
|
||||
if (Settings.tele_period) {
|
||||
if (tele_period >= TELE_PERIOD_START) {
|
||||
if (!global_state.wifi_down) {
|
||||
tele_period = 0; // Allow teleperiod once wifi is connected
|
||||
}
|
||||
}
|
||||
tele_period++;
|
||||
if (tele_period >= Settings.tele_period) {
|
||||
if (tele_period == Settings.tele_period) {
|
||||
tele_period = 0;
|
||||
|
||||
MqttPublishTeleState();
|
||||
|
@ -558,7 +558,9 @@ void MqttConnected(void)
|
||||
Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":\"%s\"}"), (GetResetReason() == "Exception") ? ESP.getResetInfo().c_str() : GetResetReason().c_str());
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "3"));
|
||||
MqttPublishAllPowerState();
|
||||
if (Settings.tele_period) { tele_period = Settings.tele_period -9; } // Enable TelePeriod in 9 seconds
|
||||
if (Settings.tele_period) {
|
||||
tele_period = Settings.tele_period -5; // Enable TelePeriod in 5 seconds
|
||||
}
|
||||
rules_flag.system_boot = 1;
|
||||
XdrvCall(FUNC_MQTT_INIT);
|
||||
}
|
||||
|
@ -42,9 +42,12 @@ const char kDeepsleepCommands[] PROGMEM = D_PRFX_DEEPSLEEP "|"
|
||||
void (* const DeepsleepCommand[])(void) PROGMEM = {
|
||||
&CmndDeepsleepTime };
|
||||
|
||||
uint32_t deepsleep_sleeptime = 0;
|
||||
uint8_t deepsleep_flag = 0;
|
||||
|
||||
bool DeepSleepEnabled(void)
|
||||
{
|
||||
if (0 == Settings.deepsleep) {
|
||||
if (Settings.deepsleep < 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -77,59 +80,81 @@ void DeepSleepInit(void)
|
||||
|
||||
void DeepSleepCheck(void)
|
||||
{
|
||||
// new function AFTER_TELEPERIOD can take some time therefore <2
|
||||
if (DeepSleepEnabled() && (Settings.deepsleep > 10) && (Settings.deepsleep < 4294967295)) {
|
||||
SettingsSaveAll();
|
||||
// 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.
|
||||
// This should normally never executed, but can happen an manual wakeup and problems during wakeup
|
||||
if ((RtcSettings.nextwakeup == 0) || (RtcSettings.deepsleep_slip < 9000) || (RtcSettings.deepsleep_slip > 11000) || (RtcSettings.nextwakeup > (UtcTime() + Settings.deepsleep))) {
|
||||
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DSL: Reset wrong settings wakeup: %ld, slip %ld"), RtcSettings.nextwakeup, RtcSettings.deepsleep_slip );
|
||||
RtcSettings.nextwakeup = 0;
|
||||
RtcSettings.deepsleep_slip = 10000;
|
||||
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("new settings wakeup: %ld, slip %ld"), RtcSettings.nextwakeup, RtcSettings.deepsleep_slip );
|
||||
}
|
||||
// timeslip in 0.1 seconds between the real wakeup and the calculated wakeup
|
||||
// because deepsleep is in second and timeslip in 0.1 sec the compare always check if the slip is in the 10% range
|
||||
int16_t timeslip = (int16_t)(RtcSettings.nextwakeup+millis()/1000-UtcTime())*10;
|
||||
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("DSL: Timeslip 0.1 sec:? %d < %d < %ld"), -Settings.deepsleep, timeslip, Settings.deepsleep );
|
||||
//allow 10% of deepsleep error to count as valid deepsleep; expecting 3-4%
|
||||
// if more then 10% timeslip = 0 == non valid wakeup; maybe manual
|
||||
timeslip = (timeslip < -(int32_t)Settings.deepsleep) ? 0 : (timeslip > (int32_t)Settings.deepsleep) ? 0 : 1;
|
||||
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("DSL: Normal deepsleep? %d"), timeslip );
|
||||
if (timeslip) {
|
||||
RtcSettings.deepsleep_slip = (Settings.deepsleep + RtcSettings.nextwakeup-UtcTime()) * RtcSettings.deepsleep_slip / (Settings.deepsleep - (millis() / 1000));
|
||||
//Avoid crazy numbers. Again maximum 10% deviation.
|
||||
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("DSL: %% calculate drift %ld"), RtcSettings.deepsleep_slip );
|
||||
RtcSettings.deepsleep_slip = tmin(tmax(RtcSettings.deepsleep_slip, 9000),11000);
|
||||
// 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.
|
||||
// This should normally never executed, but can happen an manual wakeup and problems during wakeup
|
||||
if ((RtcSettings.nextwakeup == 0) ||
|
||||
(RtcSettings.deepsleep_slip < 9000) ||
|
||||
(RtcSettings.deepsleep_slip > 11000) ||
|
||||
(RtcSettings.nextwakeup > (UtcTime() + Settings.deepsleep))) {
|
||||
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DSL: Reset wrong settings wakeup: %ld, slip %ld"),
|
||||
RtcSettings.nextwakeup, RtcSettings.deepsleep_slip );
|
||||
RtcSettings.nextwakeup = 0;
|
||||
RtcSettings.deepsleep_slip = 10000;
|
||||
}
|
||||
|
||||
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("DSL: %% new drift %ld"), RtcSettings.deepsleep_slip );
|
||||
RtcSettings.nextwakeup += Settings.deepsleep;
|
||||
// Timeslip in 0.1 seconds between the real wakeup and the calculated wakeup
|
||||
// Because deepsleep is in second and timeslip in 0.1 sec the compare always check if the slip is in the 10% range
|
||||
int16_t timeslip = (int16_t)(RtcSettings.nextwakeup + millis() / 1000 - UtcTime()) * 10;
|
||||
|
||||
// Allow 10% of deepsleep error to count as valid deepsleep; expecting 3-4%
|
||||
// if more then 10% timeslip = 0 == non valid wakeup; maybe manual
|
||||
timeslip = (timeslip < -(int32_t)Settings.deepsleep) ? 0 : (timeslip > (int32_t)Settings.deepsleep) ? 0 : 1;
|
||||
if (timeslip) {
|
||||
RtcSettings.deepsleep_slip = (Settings.deepsleep + RtcSettings.nextwakeup - UtcTime()) * RtcSettings.deepsleep_slip / (Settings.deepsleep - (millis() / 1000));
|
||||
// Avoid crazy numbers. Again maximum 10% deviation.
|
||||
RtcSettings.deepsleep_slip = tmin(tmax(RtcSettings.deepsleep_slip, 9000), 11000);
|
||||
RtcSettings.nextwakeup += Settings.deepsleep;
|
||||
}
|
||||
|
||||
// It may happen that wakeup in just <5 seconds in future
|
||||
// In this case also add deepsleep to nextwakeup
|
||||
if (RtcSettings.nextwakeup <= (UtcTime() - MIN_DEEPSLEEP_TIME)) {
|
||||
// ensure nextwakeup is at least in the future
|
||||
RtcSettings.nextwakeup += (((UtcTime() + MIN_DEEPSLEEP_TIME - RtcSettings.nextwakeup) / Settings.deepsleep) + 1) * Settings.deepsleep;
|
||||
}
|
||||
|
||||
String dt = GetDT(RtcSettings.nextwakeup + LocalTime() - UtcTime()); // 2017-03-07T11:08:02
|
||||
// Limit sleeptime to MAX_DEEPSLEEP_CYCLE
|
||||
// uint32_t deepsleep_sleeptime = MAX_DEEPSLEEP_CYCLE < (RtcSettings.nextwakeup - UtcTime()) ? (uint32_t)MAX_DEEPSLEEP_CYCLE : RtcSettings.nextwakeup - UtcTime();
|
||||
deepsleep_sleeptime = tmin((uint32_t)MAX_DEEPSLEEP_CYCLE ,RtcSettings.nextwakeup - UtcTime());
|
||||
|
||||
// stat/tasmota/STATUS = {"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);
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_STATUS));
|
||||
|
||||
// Response_P(S_OFFLINE);
|
||||
// MqttPublishPrefixTopic_P(TELE, PSTR(D_LWT), true); // Offline or remove previous retained topic
|
||||
}
|
||||
|
||||
void DeepSleepStart(void)
|
||||
{
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Sleeping")); // Won't show in GUI
|
||||
|
||||
WifiShutdown();
|
||||
RtcSettings.ultradeepsleep = RtcSettings.nextwakeup - UtcTime();
|
||||
RtcSettingsSave();
|
||||
|
||||
ESP.deepSleep(100 * RtcSettings.deepsleep_slip * deepsleep_sleeptime);
|
||||
yield();
|
||||
}
|
||||
|
||||
void DeepSleepEverySecond(void)
|
||||
{
|
||||
if (!deepsleep_flag) { return; }
|
||||
|
||||
if (DeepSleepEnabled()) {
|
||||
if (4 == deepsleep_flag) { // Allow 4 seconds to update web console before deepsleep
|
||||
SettingsSaveAll();
|
||||
DeepSleepCheck();
|
||||
}
|
||||
// it may happen that wakeup in just <5 seconds in future
|
||||
// in this case also add deepsleep to nextwakeup
|
||||
if (RtcSettings.nextwakeup <= (UtcTime() - MIN_DEEPSLEEP_TIME)) {
|
||||
// ensure nextwakeup is at least in the future
|
||||
RtcSettings.nextwakeup += (((UtcTime() + MIN_DEEPSLEEP_TIME - RtcSettings.nextwakeup) / Settings.deepsleep) + 1) * Settings.deepsleep;
|
||||
deepsleep_flag--;
|
||||
if (deepsleep_flag <= 0) {
|
||||
DeepSleepStart();
|
||||
}
|
||||
String dt = GetDT(RtcSettings.nextwakeup + LocalTime() - UtcTime()); // 2017-03-07T11:08:02
|
||||
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("DSL: Next wakeup %s"), (char*)dt.c_str());
|
||||
//limit sleeptime to MAX_DEEPSLEEP_CYCLE
|
||||
//uint32_t sleeptime = MAX_DEEPSLEEP_CYCLE < (RtcSettings.nextwakeup - UtcTime()) ? (uint32_t)MAX_DEEPSLEEP_CYCLE : RtcSettings.nextwakeup - UtcTime();
|
||||
uint32_t sleeptime = tmin((uint32_t)MAX_DEEPSLEEP_CYCLE , RtcSettings.nextwakeup - UtcTime());
|
||||
Response_P(PSTR("{\"" D_PRFX_DEEPSLEEP "\":{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%d}}"), (char*)dt.c_str(), RtcSettings.nextwakeup);
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_STATUS "1"), false);
|
||||
Response_P(S_OFFLINE);
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_LWT), true); // Offline or remove previous retained topic
|
||||
yield();
|
||||
MqttDisconnect();
|
||||
RtcSettings.ultradeepsleep = RtcSettings.nextwakeup - UtcTime();
|
||||
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("DSL: Sleeptime %d sec, deepsleep_slip %ld"), sleeptime, RtcSettings.deepsleep_slip);
|
||||
RtcSettingsSave();
|
||||
ESP.deepSleep(100 * RtcSettings.deepsleep_slip * sleeptime);
|
||||
yield();
|
||||
// Sleeping
|
||||
} else {
|
||||
deepsleep_flag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,11 +164,11 @@ void DeepSleepCheck(void)
|
||||
|
||||
void CmndDeepsleepTime(void)
|
||||
{
|
||||
if ((XdrvMailbox.payload == 0) ||
|
||||
if ((0 == XdrvMailbox.payload) ||
|
||||
((XdrvMailbox.payload > 10) && (XdrvMailbox.payload < (10 * 366 * 24 * 60 * 60)))) { // Allow max 10 years sleep
|
||||
Settings.deepsleep = XdrvMailbox.payload;
|
||||
RtcSettings.nextwakeup = 0;
|
||||
tele_period = Settings.tele_period -1; // Initiate start DeepSleep on next finish of forced TelePeriod
|
||||
deepsleep_flag = (0 == XdrvMailbox.payload) ? 0 : 4;
|
||||
}
|
||||
Response_P(S_JSON_COMMAND_NVALUE, XdrvMailbox.command, Settings.deepsleep);
|
||||
}
|
||||
@ -157,8 +182,13 @@ bool Xdrv29(uint8_t function)
|
||||
bool result = false;
|
||||
|
||||
switch (function) {
|
||||
case FUNC_EVERY_SECOND:
|
||||
DeepSleepEverySecond();
|
||||
break;
|
||||
case FUNC_AFTER_TELEPERIOD:
|
||||
DeepSleepCheck();
|
||||
if (!deepsleep_flag) {
|
||||
deepsleep_flag = 4; // Start deepsleep in 4 seconds
|
||||
}
|
||||
break;
|
||||
case FUNC_COMMAND:
|
||||
result = DecodeCommand(kDeepsleepCommands, DeepsleepCommand);
|
||||
|
Loading…
x
Reference in New Issue
Block a user