feat(architecture): enforce lifecycle orchestration and layered component boundaries
This commit is contained in:
@@ -1,6 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
typedef enum {
|
||||
CONTROLLER_LIFECYCLE_STATE_STOPPED = 0,
|
||||
CONTROLLER_LIFECYCLE_STATE_STARTING,
|
||||
CONTROLLER_LIFECYCLE_STATE_RUNNING,
|
||||
CONTROLLER_LIFECYCLE_STATE_DEGRADED,
|
||||
CONTROLLER_LIFECYCLE_STATE_STOPPING,
|
||||
} controller_lifecycle_state_t;
|
||||
|
||||
typedef struct {
|
||||
controller_lifecycle_state_t state;
|
||||
esp_err_t last_error;
|
||||
uint32_t start_attempt;
|
||||
int64_t last_transition_ms;
|
||||
char last_stage[32];
|
||||
} controller_lifecycle_status_t;
|
||||
|
||||
esp_err_t controller_lifecycle_start(void);
|
||||
void controller_lifecycle_stop(void);
|
||||
esp_err_t controller_lifecycle_stop(void);
|
||||
void controller_lifecycle_get_status(controller_lifecycle_status_t *out_status);
|
||||
const char *controller_lifecycle_state_str(controller_lifecycle_state_t state);
|
||||
|
||||
@@ -1,36 +1,316 @@
|
||||
#include "controller_lifecycle.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_timer.h"
|
||||
#include "image_generation.h"
|
||||
#include "printer_protocol.h"
|
||||
#include "rest_server.h"
|
||||
#include "runtime_diagnostics.h"
|
||||
#include "runtime_policy.h"
|
||||
#include "system_runtime.h"
|
||||
#include "voice_interaction.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
static const char *TAG = "controller_lifecycle";
|
||||
static SemaphoreHandle_t s_lock;
|
||||
static controller_lifecycle_status_t s_status = {
|
||||
.state = CONTROLLER_LIFECYCLE_STATE_STOPPED,
|
||||
.last_error = ESP_OK,
|
||||
.start_attempt = 0,
|
||||
.last_transition_ms = 0,
|
||||
.last_stage = "stopped",
|
||||
};
|
||||
|
||||
esp_err_t controller_lifecycle_start(void) {
|
||||
ESP_LOGI(TAG, "Starting system runtime");
|
||||
ESP_ERROR_CHECK(system_runtime_bootstrap());
|
||||
static void lifecycle_lock_init_if_needed(void) {
|
||||
if (s_lock == NULL) {
|
||||
s_lock = xSemaphoreCreateMutex();
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Starting printer protocol");
|
||||
ESP_ERROR_CHECK(printer_protocol_init());
|
||||
static bool lifecycle_lock_take(uint32_t timeout_ms) {
|
||||
lifecycle_lock_init_if_needed();
|
||||
return s_lock != NULL && xSemaphoreTake(s_lock, pdMS_TO_TICKS(timeout_ms)) == pdTRUE;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Starting voice interaction");
|
||||
ESP_ERROR_CHECK(voice_interaction_init());
|
||||
static void lifecycle_set_state_locked(controller_lifecycle_state_t state,
|
||||
esp_err_t last_error,
|
||||
const char *stage) {
|
||||
s_status.state = state;
|
||||
s_status.last_error = last_error;
|
||||
s_status.last_transition_ms = esp_timer_get_time() / 1000;
|
||||
strlcpy(s_status.last_stage, stage != NULL ? stage : "unknown", sizeof(s_status.last_stage));
|
||||
runtime_diag_set_gauge(RUNTIME_DIAG_GAUGE_LIFECYCLE_STATE, (int32_t)state);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Scheduling HTTPS prewarm");
|
||||
image_generation_schedule_prewarm();
|
||||
const char *controller_lifecycle_state_str(controller_lifecycle_state_t state) {
|
||||
switch (state) {
|
||||
case CONTROLLER_LIFECYCLE_STATE_STOPPED:
|
||||
return "stopped";
|
||||
case CONTROLLER_LIFECYCLE_STATE_STARTING:
|
||||
return "starting";
|
||||
case CONTROLLER_LIFECYCLE_STATE_RUNNING:
|
||||
return "running";
|
||||
case CONTROLLER_LIFECYCLE_STATE_DEGRADED:
|
||||
return "degraded";
|
||||
case CONTROLLER_LIFECYCLE_STATE_STOPPING:
|
||||
return "stopping";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Starting REST server");
|
||||
ESP_ERROR_CHECK(rest_server_start());
|
||||
static esp_err_t lifecycle_start_system_runtime(void) {
|
||||
return system_runtime_start();
|
||||
}
|
||||
|
||||
static esp_err_t lifecycle_start_printer_protocol(void) {
|
||||
return printer_protocol_init();
|
||||
}
|
||||
|
||||
static esp_err_t lifecycle_start_voice(void) {
|
||||
return voice_interaction_init();
|
||||
}
|
||||
|
||||
static esp_err_t lifecycle_start_rest_server(void) {
|
||||
return rest_server_start();
|
||||
}
|
||||
|
||||
static esp_err_t lifecycle_stop_rest_server(void) {
|
||||
rest_server_stop();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void controller_lifecycle_stop(void) {
|
||||
rest_server_stop();
|
||||
(void)voice_interaction_stop(NULL, 0);
|
||||
printer_protocol_disconnect();
|
||||
ESP_LOGI(TAG, "Controller lifecycle stopped");
|
||||
static esp_err_t lifecycle_stop_voice(void) {
|
||||
esp_err_t rc = voice_interaction_stop(NULL, 0);
|
||||
if (rc == ESP_OK || rc == ESP_ERR_INVALID_STATE) {
|
||||
return ESP_OK;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static esp_err_t lifecycle_stop_printer_protocol(void) {
|
||||
esp_err_t rc = printer_protocol_stop(runtime_policy_printer_stop_timeout_ms());
|
||||
if (rc == ESP_OK || rc == ESP_ERR_INVALID_STATE) {
|
||||
return ESP_OK;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static esp_err_t lifecycle_stop_system_runtime(void) {
|
||||
return system_runtime_shutdown();
|
||||
}
|
||||
|
||||
typedef esp_err_t (*lifecycle_step_fn_t)(void);
|
||||
|
||||
static esp_err_t lifecycle_run_step_with_retry(const char *stage, lifecycle_step_fn_t fn) {
|
||||
uint32_t retry_count = runtime_policy_lifecycle_start_retry_count();
|
||||
uint32_t max_attempts = retry_count + 1;
|
||||
|
||||
for (uint32_t attempt = 0; attempt < max_attempts; ++attempt) {
|
||||
esp_err_t rc = fn();
|
||||
if (rc == ESP_OK) {
|
||||
if (attempt > 0) {
|
||||
ESP_LOGW(TAG, "stage %s recovered after retries, attempt=%u", stage, (unsigned)(attempt + 1));
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool can_retry = (attempt + 1 < max_attempts) && runtime_policy_is_retryable_error(rc);
|
||||
ESP_LOGW(TAG,
|
||||
"stage %s failed, rc=0x%x, attempt=%u/%u, retry=%d",
|
||||
stage,
|
||||
(unsigned)rc,
|
||||
(unsigned)(attempt + 1),
|
||||
(unsigned)max_attempts,
|
||||
can_retry ? 1 : 0);
|
||||
|
||||
if (!can_retry) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_LIFECYCLE_START_RETRY, 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(runtime_policy_lifecycle_retry_backoff_ms(attempt)));
|
||||
}
|
||||
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t controller_lifecycle_start(void) {
|
||||
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_LIFECYCLE_START_ATTEMPT, 1);
|
||||
|
||||
if (!lifecycle_lock_take(1000)) {
|
||||
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_LIFECYCLE_START_FAILED, 1);
|
||||
runtime_diag_record_error("lifecycle_start", ESP_ERR_TIMEOUT, "lifecycle lock timeout");
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
if (s_status.state == CONTROLLER_LIFECYCLE_STATE_RUNNING) {
|
||||
xSemaphoreGive(s_lock);
|
||||
return ESP_OK;
|
||||
}
|
||||
if (s_status.state == CONTROLLER_LIFECYCLE_STATE_STARTING ||
|
||||
s_status.state == CONTROLLER_LIFECYCLE_STATE_STOPPING) {
|
||||
xSemaphoreGive(s_lock);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
s_status.start_attempt++;
|
||||
lifecycle_set_state_locked(CONTROLLER_LIFECYCLE_STATE_STARTING, ESP_OK, "bootstrap");
|
||||
xSemaphoreGive(s_lock);
|
||||
|
||||
bool system_started = false;
|
||||
bool printer_started = false;
|
||||
bool voice_started = false;
|
||||
bool rest_started = false;
|
||||
const char *failed_stage = "unknown";
|
||||
|
||||
failed_stage = "system_runtime";
|
||||
esp_err_t rc = lifecycle_run_step_with_retry("system_runtime", lifecycle_start_system_runtime);
|
||||
if (rc != ESP_OK) {
|
||||
goto start_failed;
|
||||
}
|
||||
system_started = true;
|
||||
|
||||
failed_stage = "printer_protocol";
|
||||
rc = lifecycle_run_step_with_retry("printer_protocol", lifecycle_start_printer_protocol);
|
||||
if (rc != ESP_OK) {
|
||||
goto start_failed;
|
||||
}
|
||||
printer_started = true;
|
||||
|
||||
failed_stage = "voice_interaction";
|
||||
rc = lifecycle_run_step_with_retry("voice_interaction", lifecycle_start_voice);
|
||||
if (rc != ESP_OK) {
|
||||
goto start_failed;
|
||||
}
|
||||
voice_started = true;
|
||||
|
||||
failed_stage = "rest_server";
|
||||
rc = lifecycle_run_step_with_retry("rest_server", lifecycle_start_rest_server);
|
||||
if (rc != ESP_OK) {
|
||||
goto start_failed;
|
||||
}
|
||||
rest_started = true;
|
||||
|
||||
image_generation_schedule_prewarm();
|
||||
|
||||
if (lifecycle_lock_take(1000)) {
|
||||
lifecycle_set_state_locked(CONTROLLER_LIFECYCLE_STATE_RUNNING, ESP_OK, "running");
|
||||
xSemaphoreGive(s_lock);
|
||||
}
|
||||
|
||||
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_LIFECYCLE_START_SUCCESS, 1);
|
||||
ESP_LOGI(TAG, "controller lifecycle started");
|
||||
return ESP_OK;
|
||||
|
||||
start_failed:
|
||||
if (rest_started) {
|
||||
(void)lifecycle_stop_rest_server();
|
||||
}
|
||||
if (voice_started) {
|
||||
(void)lifecycle_stop_voice();
|
||||
}
|
||||
if (printer_started) {
|
||||
(void)lifecycle_stop_printer_protocol();
|
||||
}
|
||||
if (system_started) {
|
||||
(void)lifecycle_stop_system_runtime();
|
||||
}
|
||||
|
||||
if (lifecycle_lock_take(1000)) {
|
||||
lifecycle_set_state_locked(CONTROLLER_LIFECYCLE_STATE_DEGRADED, rc, failed_stage);
|
||||
xSemaphoreGive(s_lock);
|
||||
}
|
||||
|
||||
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_LIFECYCLE_START_FAILED, 1);
|
||||
runtime_diag_record_error("lifecycle_start", rc, failed_stage);
|
||||
ESP_LOGE(TAG,
|
||||
"controller lifecycle start failed at stage=%s, rc=0x%x",
|
||||
failed_stage,
|
||||
(unsigned)rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
esp_err_t controller_lifecycle_stop(void) {
|
||||
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_LIFECYCLE_STOP_ATTEMPT, 1);
|
||||
|
||||
if (!lifecycle_lock_take(1000)) {
|
||||
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_LIFECYCLE_STOP_FAILED, 1);
|
||||
runtime_diag_record_error("lifecycle_stop", ESP_ERR_TIMEOUT, "lifecycle lock timeout");
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
if (s_status.state == CONTROLLER_LIFECYCLE_STATE_STOPPED) {
|
||||
xSemaphoreGive(s_lock);
|
||||
return ESP_OK;
|
||||
}
|
||||
if (s_status.state == CONTROLLER_LIFECYCLE_STATE_STARTING ||
|
||||
s_status.state == CONTROLLER_LIFECYCLE_STATE_STOPPING) {
|
||||
xSemaphoreGive(s_lock);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
lifecycle_set_state_locked(CONTROLLER_LIFECYCLE_STATE_STOPPING, ESP_OK, "stopping");
|
||||
xSemaphoreGive(s_lock);
|
||||
|
||||
esp_err_t first_err = ESP_OK;
|
||||
|
||||
esp_err_t rc = lifecycle_stop_rest_server();
|
||||
if (rc != ESP_OK && first_err == ESP_OK) {
|
||||
first_err = rc;
|
||||
}
|
||||
|
||||
rc = lifecycle_stop_voice();
|
||||
if (rc != ESP_OK && first_err == ESP_OK) {
|
||||
first_err = rc;
|
||||
}
|
||||
|
||||
rc = lifecycle_stop_printer_protocol();
|
||||
if (rc != ESP_OK && first_err == ESP_OK) {
|
||||
first_err = rc;
|
||||
}
|
||||
|
||||
rc = lifecycle_stop_system_runtime();
|
||||
if (rc != ESP_OK && first_err == ESP_OK) {
|
||||
first_err = rc;
|
||||
}
|
||||
|
||||
if (lifecycle_lock_take(1000)) {
|
||||
if (first_err == ESP_OK) {
|
||||
lifecycle_set_state_locked(CONTROLLER_LIFECYCLE_STATE_STOPPED, ESP_OK, "stopped");
|
||||
} else {
|
||||
lifecycle_set_state_locked(CONTROLLER_LIFECYCLE_STATE_DEGRADED, first_err, "stop_failed");
|
||||
}
|
||||
xSemaphoreGive(s_lock);
|
||||
}
|
||||
|
||||
if (first_err == ESP_OK) {
|
||||
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_LIFECYCLE_STOP_SUCCESS, 1);
|
||||
ESP_LOGI(TAG, "controller lifecycle stopped");
|
||||
} else {
|
||||
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_LIFECYCLE_STOP_FAILED, 1);
|
||||
runtime_diag_record_error("lifecycle_stop", first_err, "controller stop failed");
|
||||
ESP_LOGE(TAG, "controller lifecycle stop failed, rc=0x%x", (unsigned)first_err);
|
||||
}
|
||||
|
||||
return first_err;
|
||||
}
|
||||
|
||||
void controller_lifecycle_get_status(controller_lifecycle_status_t *out_status) {
|
||||
if (out_status == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(out_status, 0, sizeof(*out_status));
|
||||
|
||||
if (!lifecycle_lock_take(200)) {
|
||||
return;
|
||||
}
|
||||
|
||||
*out_status = s_status;
|
||||
xSemaphoreGive(s_lock);
|
||||
}
|
||||
|
||||
@@ -365,6 +365,10 @@ static esp_err_t favicon_get(httpd_req_t *req) {
|
||||
}
|
||||
|
||||
esp_err_t rest_server_start(void) {
|
||||
if (s_server != NULL) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
config.server_port = CONFIG_TQ_HTTP_PORT;
|
||||
config.uri_match_fn = httpd_uri_match_wildcard;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "esp_heap_caps.h"
|
||||
#include "mbedtls/base64.h"
|
||||
#include "runtime_diagnostics.h"
|
||||
|
||||
#define REST_SERVER_MAX_BODY_BYTES (4 * 1024 * 1024)
|
||||
|
||||
@@ -49,6 +50,7 @@ esp_err_t rest_server_send_json(httpd_req_t *req, const char *status, cJSON *roo
|
||||
httpd_resp_set_status(req, status);
|
||||
esp_err_t err = httpd_resp_sendstr(req, text);
|
||||
cJSON_free(text);
|
||||
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_REST_RESPONSES_TOTAL, 1);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -58,6 +60,8 @@ esp_err_t rest_server_send_error(httpd_req_t *req, const char *status, const cha
|
||||
cJSON_AddStringToObject(root, "error", message != NULL ? message : "unknown");
|
||||
esp_err_t err = rest_server_send_json(req, status, root);
|
||||
cJSON_Delete(root);
|
||||
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_REST_ERRORS_TOTAL, 1);
|
||||
runtime_diag_record_error("rest_api", ESP_FAIL, message != NULL ? message : "unknown");
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,49 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "controller_lifecycle.h"
|
||||
#include "printer_protocol.h"
|
||||
#include "runtime_diagnostics.h"
|
||||
#include "runtime_policy.h"
|
||||
#include "system_runtime.h"
|
||||
#include "voice_interaction.h"
|
||||
|
||||
static void fill_runtime_diag_json(cJSON *root) {
|
||||
runtime_diag_snapshot_t snapshot = {0};
|
||||
runtime_diag_get_snapshot(&snapshot);
|
||||
|
||||
cJSON *diag = cJSON_AddObjectToObject(root, "diagnostics");
|
||||
if (diag == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
cJSON *counters = cJSON_AddObjectToObject(diag, "counters");
|
||||
if (counters != NULL) {
|
||||
for (int i = 0; i < RUNTIME_DIAG_COUNTER_MAX; ++i) {
|
||||
cJSON_AddNumberToObject(counters,
|
||||
runtime_diag_counter_name((runtime_diag_counter_t)i),
|
||||
(double)snapshot.counters[i]);
|
||||
}
|
||||
}
|
||||
|
||||
cJSON *gauges = cJSON_AddObjectToObject(diag, "gauges");
|
||||
if (gauges != NULL) {
|
||||
for (int i = 0; i < RUNTIME_DIAG_GAUGE_MAX; ++i) {
|
||||
cJSON_AddNumberToObject(gauges,
|
||||
runtime_diag_gauge_name((runtime_diag_gauge_t)i),
|
||||
snapshot.gauges[i]);
|
||||
}
|
||||
}
|
||||
|
||||
cJSON *last_error = cJSON_AddObjectToObject(diag, "last_error");
|
||||
if (last_error != NULL) {
|
||||
cJSON_AddNumberToObject(last_error, "ts_ms", (double)snapshot.last_error_ms);
|
||||
cJSON_AddNumberToObject(last_error, "code", (double)snapshot.last_error_code);
|
||||
cJSON_AddStringToObject(last_error, "source", snapshot.last_error_source);
|
||||
cJSON_AddStringToObject(last_error, "message", snapshot.last_error_message);
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_runtime_json(cJSON *root) {
|
||||
char ip[32] = {0};
|
||||
system_runtime_get_ip(ip, sizeof(ip));
|
||||
@@ -44,6 +84,16 @@ static void fill_runtime_json(cJSON *root) {
|
||||
cJSON_AddNumberToObject(root, "voice_last_event_ms", (double)voice.last_event_ms);
|
||||
cJSON_AddNumberToObject(root, "voice_upstream_packets", (double)voice.upstream_packets);
|
||||
cJSON_AddNumberToObject(root, "voice_downstream_packets", (double)voice.downstream_packets);
|
||||
|
||||
controller_lifecycle_status_t lifecycle = {0};
|
||||
controller_lifecycle_get_status(&lifecycle);
|
||||
cJSON_AddStringToObject(root, "lifecycle_state", controller_lifecycle_state_str(lifecycle.state));
|
||||
cJSON_AddStringToObject(root, "lifecycle_stage", lifecycle.last_stage);
|
||||
cJSON_AddNumberToObject(root, "lifecycle_last_error", (double)lifecycle.last_error);
|
||||
cJSON_AddNumberToObject(root, "lifecycle_start_attempt", (double)lifecycle.start_attempt);
|
||||
cJSON_AddNumberToObject(root, "lifecycle_last_transition_ms", (double)lifecycle.last_transition_ms);
|
||||
|
||||
fill_runtime_diag_json(root);
|
||||
}
|
||||
|
||||
esp_err_t rest_server_health_get(httpd_req_t *req) {
|
||||
@@ -52,10 +102,13 @@ esp_err_t rest_server_health_get(httpd_req_t *req) {
|
||||
}
|
||||
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
cJSON_AddBoolToObject(root, "ok", true);
|
||||
controller_lifecycle_status_t lifecycle = {0};
|
||||
controller_lifecycle_get_status(&lifecycle);
|
||||
bool healthy = (lifecycle.state == CONTROLLER_LIFECYCLE_STATE_RUNNING);
|
||||
cJSON_AddBoolToObject(root, "ok", healthy);
|
||||
fill_runtime_json(root);
|
||||
|
||||
esp_err_t err = rest_server_send_json(req, "200 OK", root);
|
||||
esp_err_t err = rest_server_send_json(req, healthy ? "200 OK" : "503 Service Unavailable", root);
|
||||
cJSON_Delete(root);
|
||||
return err;
|
||||
}
|
||||
@@ -67,7 +120,7 @@ esp_err_t rest_server_connect_post(httpd_req_t *req) {
|
||||
|
||||
char *body = NULL;
|
||||
char name[32] = "TQPrinter";
|
||||
uint32_t timeout_ms = 15000;
|
||||
uint32_t timeout_ms = runtime_policy_rest_printer_connect_timeout_ms();
|
||||
|
||||
if (req->content_len > 0) {
|
||||
esp_err_t body_err = rest_server_read_body(req, &body);
|
||||
@@ -148,7 +201,7 @@ esp_err_t rest_server_label_gap_move_post(httpd_req_t *req) {
|
||||
return rest_server_send_error(req, "401 Unauthorized", "unauthorized");
|
||||
}
|
||||
|
||||
uint32_t timeout_ms = 5000;
|
||||
uint32_t timeout_ms = runtime_policy_rest_label_timeout_ms();
|
||||
if (req->content_len > 0) {
|
||||
char *body = NULL;
|
||||
esp_err_t body_err = rest_server_read_body(req, &body);
|
||||
@@ -189,7 +242,10 @@ esp_err_t rest_server_label_offset_get(httpd_req_t *req) {
|
||||
|
||||
uint8_t offset = 0;
|
||||
char cmd_err[128] = {0};
|
||||
esp_err_t rc = printer_protocol_get_label_offset(&offset, 3000, cmd_err, sizeof(cmd_err));
|
||||
esp_err_t rc = printer_protocol_get_label_offset(&offset,
|
||||
runtime_policy_rest_label_timeout_ms(),
|
||||
cmd_err,
|
||||
sizeof(cmd_err));
|
||||
if (rc != ESP_OK) {
|
||||
return rest_server_send_error(req, "409 Conflict", cmd_err[0] != '\0' ? cmd_err : "get offset failed");
|
||||
}
|
||||
@@ -230,7 +286,10 @@ esp_err_t rest_server_label_offset_post(httpd_req_t *req) {
|
||||
cJSON_Delete(json);
|
||||
|
||||
char cmd_err[128] = {0};
|
||||
esp_err_t rc = printer_protocol_set_label_offset(value, 3000, cmd_err, sizeof(cmd_err));
|
||||
esp_err_t rc = printer_protocol_set_label_offset(value,
|
||||
runtime_policy_rest_label_timeout_ms(),
|
||||
cmd_err,
|
||||
sizeof(cmd_err));
|
||||
if (rc != ESP_OK) {
|
||||
return rest_server_send_error(req, "409 Conflict", cmd_err[0] != '\0' ? cmd_err : "set offset failed");
|
||||
}
|
||||
@@ -251,7 +310,10 @@ esp_err_t rest_server_ota_version_get(httpd_req_t *req) {
|
||||
|
||||
printer_ota_version_t version = {0};
|
||||
char cmd_err[128] = {0};
|
||||
esp_err_t rc = printer_protocol_ota_get_version(&version, 4000, cmd_err, sizeof(cmd_err));
|
||||
esp_err_t rc = printer_protocol_ota_get_version(&version,
|
||||
runtime_policy_rest_ota_timeout_ms(),
|
||||
cmd_err,
|
||||
sizeof(cmd_err));
|
||||
if (rc != ESP_OK) {
|
||||
return rest_server_send_error(req, "409 Conflict", cmd_err[0] != '\0' ? cmd_err : "get version failed");
|
||||
}
|
||||
@@ -275,7 +337,9 @@ esp_err_t rest_server_ota_jump_boot_post(httpd_req_t *req) {
|
||||
}
|
||||
|
||||
char cmd_err[128] = {0};
|
||||
esp_err_t rc = printer_protocol_ota_jump_boot(5000, cmd_err, sizeof(cmd_err));
|
||||
esp_err_t rc = printer_protocol_ota_jump_boot(runtime_policy_rest_ota_timeout_ms(),
|
||||
cmd_err,
|
||||
sizeof(cmd_err));
|
||||
if (rc != ESP_OK) {
|
||||
return rest_server_send_error(req, "409 Conflict", cmd_err[0] != '\0' ? cmd_err : "jump boot failed");
|
||||
}
|
||||
@@ -294,7 +358,9 @@ esp_err_t rest_server_ota_jump_app_post(httpd_req_t *req) {
|
||||
}
|
||||
|
||||
char cmd_err[128] = {0};
|
||||
esp_err_t rc = printer_protocol_ota_jump_app(5000, cmd_err, sizeof(cmd_err));
|
||||
esp_err_t rc = printer_protocol_ota_jump_app(runtime_policy_rest_ota_timeout_ms(),
|
||||
cmd_err,
|
||||
sizeof(cmd_err));
|
||||
if (rc != ESP_OK) {
|
||||
return rest_server_send_error(req, "409 Conflict", cmd_err[0] != '\0' ? cmd_err : "jump app failed");
|
||||
}
|
||||
@@ -330,7 +396,7 @@ esp_err_t rest_server_ota_erase_page_post(httpd_req_t *req) {
|
||||
return rest_server_send_error(req, "400 Bad Request", "page_num must be 0..65535");
|
||||
}
|
||||
|
||||
uint32_t timeout_ms = 5000;
|
||||
uint32_t timeout_ms = runtime_policy_rest_ota_timeout_ms();
|
||||
if (cJSON_IsNumber(jtimeout) && jtimeout->valuedouble > 0 && jtimeout->valuedouble <= 30000) {
|
||||
timeout_ms = (uint32_t)jtimeout->valuedouble;
|
||||
}
|
||||
@@ -379,7 +445,7 @@ esp_err_t rest_server_ota_write_frame_post(httpd_req_t *req) {
|
||||
return rest_server_send_error(req, "400 Bad Request", "packet_num and data are required");
|
||||
}
|
||||
|
||||
uint32_t timeout_ms = 4000;
|
||||
uint32_t timeout_ms = runtime_policy_rest_ota_timeout_ms();
|
||||
if (cJSON_IsNumber(jtimeout) && jtimeout->valuedouble > 0 && jtimeout->valuedouble <= 30000) {
|
||||
timeout_ms = (uint32_t)jtimeout->valuedouble;
|
||||
}
|
||||
@@ -451,7 +517,7 @@ esp_err_t rest_server_ota_upgrade_post(httpd_req_t *req) {
|
||||
|
||||
uint16_t page_size = 1024;
|
||||
uint16_t packet_size = 236;
|
||||
uint32_t timeout_ms = 5000;
|
||||
uint32_t timeout_ms = runtime_policy_rest_ota_timeout_ms();
|
||||
if (cJSON_IsNumber(jpagesize) && jpagesize->valuedouble >= 256 && jpagesize->valuedouble <= 4096) {
|
||||
page_size = (uint16_t)jpagesize->valuedouble;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "image_generation.h"
|
||||
#include "printer_protocol.h"
|
||||
#include "raster_tools.h"
|
||||
#include "runtime_policy.h"
|
||||
|
||||
static const char *TAG = "rest_print";
|
||||
|
||||
@@ -229,8 +230,8 @@ static bool parse_image_generation_options(cJSON *json,
|
||||
}
|
||||
|
||||
memset(out, 0, sizeof(*out));
|
||||
out->timeout_ms = CONFIG_TQ_Z_IMAGE_TIMEOUT_MS;
|
||||
out->fetch_timeout_ms = CONFIG_TQ_Z_IMAGE_DOWNLOAD_TIMEOUT_MS;
|
||||
out->timeout_ms = runtime_policy_image_generation_timeout_default_ms();
|
||||
out->fetch_timeout_ms = runtime_policy_image_download_timeout_default_ms();
|
||||
|
||||
cJSON *jprompt = cJSON_GetObjectItemCaseSensitive(json, "prompt");
|
||||
if (!cJSON_IsString(jprompt) || jprompt->valuestring == NULL || jprompt->valuestring[0] == '\0') {
|
||||
@@ -289,9 +290,14 @@ static bool parse_image_generation_options(cJSON *json,
|
||||
|
||||
cJSON *jtimeout = cJSON_GetObjectItemCaseSensitive(json, "timeout_ms");
|
||||
if (cJSON_IsNumber(jtimeout)) {
|
||||
if (jtimeout->valuedouble < 5000 || jtimeout->valuedouble > 180000) {
|
||||
if (jtimeout->valuedouble < runtime_policy_image_generation_timeout_min_ms() ||
|
||||
jtimeout->valuedouble > runtime_policy_image_generation_timeout_max_ms()) {
|
||||
if (err != NULL && err_len > 0) {
|
||||
snprintf(err, err_len, "timeout_ms must be 5000..180000");
|
||||
snprintf(err,
|
||||
err_len,
|
||||
"timeout_ms must be %u..%u",
|
||||
(unsigned)runtime_policy_image_generation_timeout_min_ms(),
|
||||
(unsigned)runtime_policy_image_generation_timeout_max_ms());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -300,9 +306,14 @@ static bool parse_image_generation_options(cJSON *json,
|
||||
|
||||
cJSON *jfetch_timeout = cJSON_GetObjectItemCaseSensitive(json, "fetch_timeout_ms");
|
||||
if (cJSON_IsNumber(jfetch_timeout)) {
|
||||
if (jfetch_timeout->valuedouble < 2000 || jfetch_timeout->valuedouble > 120000) {
|
||||
if (jfetch_timeout->valuedouble < runtime_policy_image_download_timeout_min_ms() ||
|
||||
jfetch_timeout->valuedouble > runtime_policy_image_download_timeout_max_ms()) {
|
||||
if (err != NULL && err_len > 0) {
|
||||
snprintf(err, err_len, "fetch_timeout_ms must be 2000..120000");
|
||||
snprintf(err,
|
||||
err_len,
|
||||
"fetch_timeout_ms must be %u..%u",
|
||||
(unsigned)runtime_policy_image_download_timeout_min_ms(),
|
||||
(unsigned)runtime_policy_image_download_timeout_max_ms());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -411,7 +422,7 @@ static esp_err_t rest_server_print_image_generate(httpd_req_t *req) {
|
||||
image_generation_result_t *gen_result = NULL;
|
||||
uint8_t *raster = NULL;
|
||||
char request_id[80] = {0};
|
||||
bool status_poll_paused = false;
|
||||
printer_status_poll_pause_token_t status_poll_pause_token = 0;
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
|
||||
esp_err_t body_err = rest_server_read_body(req, &body);
|
||||
@@ -475,14 +486,12 @@ static esp_err_t rest_server_print_image_generate(httpd_req_t *req) {
|
||||
image_generation_result_reset(gen_result);
|
||||
|
||||
char model_err[160] = {0};
|
||||
printer_protocol_set_status_poll_paused(true);
|
||||
status_poll_paused = true;
|
||||
status_poll_pause_token = printer_protocol_status_poll_pause_acquire();
|
||||
esp_err_t gen_rc = image_generation_generate_png(&gen_req,
|
||||
gen_result,
|
||||
model_err,
|
||||
sizeof(model_err));
|
||||
printer_protocol_set_status_poll_paused(false);
|
||||
status_poll_paused = false;
|
||||
printer_protocol_status_poll_pause_release(&status_poll_pause_token);
|
||||
if (gen_rc != ESP_OK) {
|
||||
ESP_LOGW(TAG,
|
||||
"image generate failed, rc=0x%x, msg=%s",
|
||||
@@ -551,9 +560,7 @@ static esp_err_t rest_server_print_image_generate(httpd_req_t *req) {
|
||||
request_id);
|
||||
|
||||
cleanup:
|
||||
if (status_poll_paused) {
|
||||
printer_protocol_set_status_poll_paused(false);
|
||||
}
|
||||
printer_protocol_status_poll_pause_release(&status_poll_pause_token);
|
||||
if (body != NULL) {
|
||||
free(body);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user