feat(ota): defer updates when battery is low
This commit is contained in:
@@ -69,6 +69,7 @@ typedef enum {
|
||||
CONTROL_PLANE_OTA_STATE_WAITING_FOR_RESOURCES,
|
||||
CONTROL_PLANE_OTA_STATE_CHECKING,
|
||||
CONTROL_PLANE_OTA_STATE_WAITING_FOR_CONFIRMATION,
|
||||
CONTROL_PLANE_OTA_STATE_WAITING_FOR_POWER,
|
||||
CONTROL_PLANE_OTA_STATE_DOWNLOADING,
|
||||
CONTROL_PLANE_OTA_STATE_READY_TO_REBOOT,
|
||||
CONTROL_PLANE_OTA_STATE_ERROR,
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "esp_attr.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_timer.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "sdkconfig.h"
|
||||
@@ -57,6 +58,12 @@
|
||||
#ifndef CONFIG_TQ_OTA_MIN_LARGEST_DMA_BYTES
|
||||
#define CONFIG_TQ_OTA_MIN_LARGEST_DMA_BYTES 4096
|
||||
#endif
|
||||
#ifndef CONFIG_TQ_OTA_MIN_BATTERY_PERCENT
|
||||
#define CONFIG_TQ_OTA_MIN_BATTERY_PERCENT 20
|
||||
#endif
|
||||
#ifndef CONFIG_TQ_OTA_POWER_RETRY_MS
|
||||
#define CONFIG_TQ_OTA_POWER_RETRY_MS 60000
|
||||
#endif
|
||||
#ifndef CONFIG_TQ_NETWORK_TASK_CORE
|
||||
#define CONFIG_TQ_NETWORK_TASK_CORE 0
|
||||
#endif
|
||||
@@ -87,6 +94,12 @@ typedef struct {
|
||||
domain_ota_report_request_t request;
|
||||
} control_plane_ota_report_context_t;
|
||||
|
||||
typedef enum {
|
||||
CONTROL_PLANE_OTA_POWER_READY = 0,
|
||||
CONTROL_PLANE_OTA_POWER_LOW,
|
||||
CONTROL_PLANE_OTA_POWER_UNAVAILABLE,
|
||||
} control_plane_ota_power_state_t;
|
||||
|
||||
static const char *TAG = "cp_ota";
|
||||
static portMUX_TYPE s_ota_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
static TaskHandle_t s_ota_task;
|
||||
@@ -310,6 +323,49 @@ static bool control_plane_ota_runtime_is_idle(void)
|
||||
!state.local_responding_started;
|
||||
}
|
||||
|
||||
static control_plane_ota_power_state_t control_plane_ota_get_power_state(
|
||||
domain_battery_status_t *out_status,
|
||||
int64_t *out_age_ms,
|
||||
esp_err_t *out_error)
|
||||
{
|
||||
if (out_status == NULL || out_age_ms == NULL || out_error == NULL) {
|
||||
return CONTROL_PLANE_OTA_POWER_UNAVAILABLE;
|
||||
}
|
||||
|
||||
memset(out_status, 0, sizeof(*out_status));
|
||||
*out_age_ms = -1;
|
||||
*out_error = ESP_OK;
|
||||
|
||||
#if CONFIG_TQ_BATTERY_ENABLE
|
||||
esp_err_t err = domain_battery_get_status(out_status);
|
||||
if (err != ESP_OK) {
|
||||
*out_error = err;
|
||||
return CONTROL_PLANE_OTA_POWER_UNAVAILABLE;
|
||||
}
|
||||
|
||||
int64_t now_ms = esp_timer_get_time() / 1000;
|
||||
if (out_status->last_valid_sample_time_ms > 0 &&
|
||||
now_ms >= out_status->last_valid_sample_time_ms) {
|
||||
*out_age_ms = now_ms - out_status->last_valid_sample_time_ms;
|
||||
}
|
||||
|
||||
int64_t max_age_ms = (int64_t)CONFIG_TQ_BATTERY_SAMPLE_INTERVAL_SEC * 3000LL;
|
||||
if (max_age_ms < 30000LL) {
|
||||
max_age_ms = 30000LL;
|
||||
}
|
||||
if (!out_status->valid || *out_age_ms < 0 || *out_age_ms > max_age_ms) {
|
||||
return CONTROL_PLANE_OTA_POWER_UNAVAILABLE;
|
||||
}
|
||||
if (out_status->percentage < CONFIG_TQ_OTA_MIN_BATTERY_PERCENT) {
|
||||
return CONTROL_PLANE_OTA_POWER_LOW;
|
||||
}
|
||||
#else
|
||||
(void)out_status;
|
||||
#endif
|
||||
|
||||
return CONTROL_PLANE_OTA_POWER_READY;
|
||||
}
|
||||
|
||||
static void control_plane_ota_set_voice_services_reserved(bool reserved)
|
||||
{
|
||||
portENTER_CRITICAL(&s_ota_lock);
|
||||
@@ -720,6 +776,39 @@ static void control_plane_ota_worker(void *arg)
|
||||
continue;
|
||||
}
|
||||
|
||||
domain_battery_status_t battery = {0};
|
||||
int64_t battery_age_ms = -1;
|
||||
esp_err_t battery_err = ESP_OK;
|
||||
control_plane_ota_power_state_t power_state =
|
||||
control_plane_ota_get_power_state(&battery,
|
||||
&battery_age_ms,
|
||||
&battery_err);
|
||||
if (power_state != CONTROL_PLANE_OTA_POWER_READY) {
|
||||
initial_check_pending = false;
|
||||
control_plane_ota_release_voice_window(&voice_window);
|
||||
control_plane_ota_set_state(CONTROL_PLANE_OTA_STATE_WAITING_FOR_POWER,
|
||||
ESP_OK,
|
||||
response->http_status);
|
||||
if (power_state == CONTROL_PLANE_OTA_POWER_LOW) {
|
||||
ESP_LOGW(TAG,
|
||||
"OTA %s deferred: battery=%u%% minimum=%u%% charging=%d",
|
||||
response->firmware.version,
|
||||
(unsigned)battery.percentage,
|
||||
(unsigned)CONFIG_TQ_OTA_MIN_BATTERY_PERCENT,
|
||||
battery.charge_state == DOMAIN_BATTERY_CHARGE_CHARGING ? 1 : 0);
|
||||
} else {
|
||||
ESP_LOGW(TAG,
|
||||
"OTA %s deferred: battery status unavailable valid=%d age_ms=%lld err=%s",
|
||||
response->firmware.version,
|
||||
battery.valid ? 1 : 0,
|
||||
(long long)battery_age_ms,
|
||||
esp_err_to_name(battery_err));
|
||||
}
|
||||
heap_caps_free(response);
|
||||
control_plane_ota_wait_interruptible(CONFIG_TQ_OTA_POWER_RETRY_MS);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!control_plane_ota_runtime_is_idle()) {
|
||||
ESP_LOGI(TAG, "OTA approved; waiting for active interaction to finish");
|
||||
initial_check_pending = false;
|
||||
|
||||
Reference in New Issue
Block a user