refactor(architecture): enforce component layering constraints

- move runtime policy/diag contracts to domain-owned facade and remove control_plane leapfrog usage

- enforce single declaration point for direct debug config in domain public API (constraint #6)

- harden timeout/idempotent semantics in REST/voice/printer/wifi/ble paths
This commit is contained in:
admin
2026-02-28 14:21:17 +08:00
parent 8a55ca0005
commit a549989332
23 changed files with 718 additions and 331 deletions

View File

@@ -37,7 +37,7 @@ static void lifecycle_set_state_locked(controller_lifecycle_state_t 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);
domain_diag_set_gauge(DOMAIN_DIAG_GAUGE_LIFECYCLE_STATE, (int32_t)state);
}
const char *controller_lifecycle_state_str(controller_lifecycle_state_t state) {
@@ -87,7 +87,7 @@ static esp_err_t lifecycle_stop_voice(void) {
}
static esp_err_t lifecycle_stop_printer_protocol(void) {
esp_err_t rc = printer_protocol_stop(runtime_policy_printer_stop_timeout_ms());
esp_err_t rc = printer_protocol_stop(domain_policy_printer_stop_timeout_ms());
if (rc == ESP_OK || rc == ESP_ERR_INVALID_STATE) {
return ESP_OK;
}
@@ -101,7 +101,7 @@ static esp_err_t lifecycle_stop_system_runtime(void) {
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 retry_count = domain_policy_lifecycle_start_retry_count();
uint32_t max_attempts = retry_count + 1;
for (uint32_t attempt = 0; attempt < max_attempts; ++attempt) {
@@ -113,7 +113,7 @@ static esp_err_t lifecycle_run_step_with_retry(const char *stage, lifecycle_step
return ESP_OK;
}
bool can_retry = (attempt + 1 < max_attempts) && runtime_policy_is_retryable_error(rc);
bool can_retry = (attempt + 1 < max_attempts) && domain_policy_is_retryable_error(rc);
ESP_LOGW(TAG,
"stage %s failed, rc=0x%x, attempt=%u/%u, retry=%d",
stage,
@@ -126,19 +126,19 @@ static esp_err_t lifecycle_run_step_with_retry(const char *stage, lifecycle_step
return rc;
}
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_LIFECYCLE_START_RETRY, 1);
vTaskDelay(pdMS_TO_TICKS(runtime_policy_lifecycle_retry_backoff_ms(attempt)));
domain_diag_counter_add(DOMAIN_DIAG_COUNTER_LIFECYCLE_START_RETRY, 1);
vTaskDelay(pdMS_TO_TICKS(domain_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);
domain_diag_counter_add(DOMAIN_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");
domain_diag_counter_add(DOMAIN_DIAG_COUNTER_LIFECYCLE_START_FAILED, 1);
domain_diag_record_error("lifecycle_start", ESP_ERR_TIMEOUT, "lifecycle lock timeout");
return ESP_ERR_TIMEOUT;
}
@@ -197,7 +197,7 @@ esp_err_t controller_lifecycle_start(void) {
xSemaphoreGive(s_lock);
}
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_LIFECYCLE_START_SUCCESS, 1);
domain_diag_counter_add(DOMAIN_DIAG_COUNTER_LIFECYCLE_START_SUCCESS, 1);
ESP_LOGI(TAG, "controller lifecycle started");
return ESP_OK;
@@ -220,8 +220,8 @@ start_failed:
xSemaphoreGive(s_lock);
}
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_LIFECYCLE_START_FAILED, 1);
runtime_diag_record_error("lifecycle_start", rc, failed_stage);
domain_diag_counter_add(DOMAIN_DIAG_COUNTER_LIFECYCLE_START_FAILED, 1);
domain_diag_record_error("lifecycle_start", rc, failed_stage);
ESP_LOGE(TAG,
"controller lifecycle start failed at stage=%s, rc=0x%x",
failed_stage,
@@ -230,11 +230,11 @@ start_failed:
}
esp_err_t controller_lifecycle_stop(void) {
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_LIFECYCLE_STOP_ATTEMPT, 1);
domain_diag_counter_add(DOMAIN_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");
domain_diag_counter_add(DOMAIN_DIAG_COUNTER_LIFECYCLE_STOP_FAILED, 1);
domain_diag_record_error("lifecycle_stop", ESP_ERR_TIMEOUT, "lifecycle lock timeout");
return ESP_ERR_TIMEOUT;
}
@@ -283,11 +283,11 @@ esp_err_t controller_lifecycle_stop(void) {
}
if (first_err == ESP_OK) {
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_LIFECYCLE_STOP_SUCCESS, 1);
domain_diag_counter_add(DOMAIN_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");
domain_diag_counter_add(DOMAIN_DIAG_COUNTER_LIFECYCLE_STOP_FAILED, 1);
domain_diag_record_error("lifecycle_stop", first_err, "controller stop failed");
ESP_LOGE(TAG, "controller lifecycle stop failed, rc=0x%x", (unsigned)first_err);
}

View File

@@ -50,7 +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);
domain_diag_counter_add(DOMAIN_DIAG_COUNTER_REST_RESPONSES_TOTAL, 1);
return err;
}
@@ -60,8 +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");
domain_diag_counter_add(DOMAIN_DIAG_COUNTER_REST_ERRORS_TOTAL, 1);
domain_diag_record_error("rest_api", ESP_FAIL, message != NULL ? message : "unknown");
return err;
}

View File

@@ -39,8 +39,8 @@ static bool parse_printer_backend(const cJSON *json, printer_backend_t *out_back
}
static void fill_runtime_diag_json(cJSON *root) {
runtime_diag_snapshot_t snapshot = {0};
runtime_diag_get_snapshot(&snapshot);
domain_diag_snapshot_t snapshot = {0};
domain_diag_get_snapshot(&snapshot);
cJSON *diag = cJSON_AddObjectToObject(root, "diagnostics");
if (diag == NULL) {
@@ -49,18 +49,18 @@ static void fill_runtime_diag_json(cJSON *root) {
cJSON *counters = cJSON_AddObjectToObject(diag, "counters");
if (counters != NULL) {
for (int i = 0; i < RUNTIME_DIAG_COUNTER_MAX; ++i) {
for (int i = 0; i < DOMAIN_DIAG_COUNTER_MAX; ++i) {
cJSON_AddNumberToObject(counters,
runtime_diag_counter_name((runtime_diag_counter_t)i),
domain_diag_counter_name((domain_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) {
for (int i = 0; i < DOMAIN_DIAG_GAUGE_MAX; ++i) {
cJSON_AddNumberToObject(gauges,
runtime_diag_gauge_name((runtime_diag_gauge_t)i),
domain_diag_gauge_name((domain_diag_gauge_t)i),
snapshot.gauges[i]);
}
}
@@ -139,7 +139,7 @@ esp_err_t rest_server_health_get(httpd_req_t *req) {
cJSON *root = cJSON_CreateObject();
controller_lifecycle_status_t lifecycle = {0};
controller_lifecycle_get_status(&lifecycle);
bool healthy = (lifecycle.state == CONTROLLER_LIFECYCLE_STATE_RUNNING);
bool healthy = (lifecycle.state == CONTROLLER_LIFECYCLE_STATE_RUNNING) && system_runtime_wifi_ready();
cJSON_AddBoolToObject(root, "ok", healthy);
fill_runtime_json(root);
@@ -155,7 +155,7 @@ esp_err_t rest_server_connect_post(httpd_req_t *req) {
char *body = NULL;
char name[32] = "TQPrinter";
uint32_t timeout_ms = runtime_policy_rest_printer_connect_timeout_ms();
uint32_t timeout_ms = domain_policy_rest_printer_connect_timeout_ms();
printer_backend_t backend = printer_protocol_get_backend();
bool backend_specified = false;
@@ -177,8 +177,16 @@ esp_err_t rest_server_connect_post(httpd_req_t *req) {
}
cJSON *jtimeout = cJSON_GetObjectItemCaseSensitive(json, "timeout_ms");
if (cJSON_IsNumber(jtimeout) && jtimeout->valuedouble > 0) {
timeout_ms = (uint32_t)jtimeout->valuedouble;
if (cJSON_IsNumber(jtimeout)) {
uint32_t min_ms = domain_policy_rest_printer_connect_timeout_min_ms();
uint32_t max_ms = domain_policy_rest_printer_connect_timeout_max_ms();
if (jtimeout->valuedouble >= (double)min_ms && jtimeout->valuedouble <= (double)max_ms) {
timeout_ms = (uint32_t)jtimeout->valuedouble;
} else {
cJSON_Delete(json);
free(body);
return rest_server_send_error(req, "400 Bad Request", "timeout_ms out of range");
}
}
cJSON *jbackend = cJSON_GetObjectItemCaseSensitive(json, "backend");
@@ -490,7 +498,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 = runtime_policy_rest_label_timeout_ms();
uint32_t timeout_ms = domain_policy_rest_label_timeout_ms();
if (req->content_len > 0) {
char *body = NULL;
esp_err_t body_err = rest_server_read_body(req, &body);
@@ -503,7 +511,13 @@ esp_err_t rest_server_label_gap_move_post(httpd_req_t *req) {
return rest_server_send_error(req, "400 Bad Request", "invalid json");
}
cJSON *jtimeout = cJSON_GetObjectItemCaseSensitive(json, "timeout_ms");
if (cJSON_IsNumber(jtimeout) && jtimeout->valuedouble > 0 && jtimeout->valuedouble <= 30000) {
if (jtimeout != NULL) {
if (!cJSON_IsNumber(jtimeout) ||
jtimeout->valuedouble < (double)domain_policy_rest_label_timeout_min_ms() ||
jtimeout->valuedouble > (double)domain_policy_rest_label_timeout_max_ms()) {
cJSON_Delete(json);
return rest_server_send_error(req, "400 Bad Request", "timeout_ms out of range");
}
timeout_ms = (uint32_t)jtimeout->valuedouble;
}
cJSON_Delete(json);
@@ -532,7 +546,7 @@ 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,
runtime_policy_rest_label_timeout_ms(),
domain_policy_rest_label_timeout_ms(),
cmd_err,
sizeof(cmd_err));
if (rc != ESP_OK) {
@@ -576,7 +590,7 @@ esp_err_t rest_server_label_offset_post(httpd_req_t *req) {
char cmd_err[128] = {0};
esp_err_t rc = printer_protocol_set_label_offset(value,
runtime_policy_rest_label_timeout_ms(),
domain_policy_rest_label_timeout_ms(),
cmd_err,
sizeof(cmd_err));
if (rc != ESP_OK) {
@@ -600,7 +614,7 @@ 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,
runtime_policy_rest_ota_timeout_ms(),
domain_policy_rest_ota_timeout_ms(),
cmd_err,
sizeof(cmd_err));
if (rc != ESP_OK) {
@@ -626,7 +640,7 @@ 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(runtime_policy_rest_ota_timeout_ms(),
esp_err_t rc = printer_protocol_ota_jump_boot(domain_policy_rest_ota_timeout_ms(),
cmd_err,
sizeof(cmd_err));
if (rc != ESP_OK) {
@@ -647,7 +661,7 @@ 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(runtime_policy_rest_ota_timeout_ms(),
esp_err_t rc = printer_protocol_ota_jump_app(domain_policy_rest_ota_timeout_ms(),
cmd_err,
sizeof(cmd_err));
if (rc != ESP_OK) {
@@ -685,8 +699,14 @@ 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 = runtime_policy_rest_ota_timeout_ms();
if (cJSON_IsNumber(jtimeout) && jtimeout->valuedouble > 0 && jtimeout->valuedouble <= 30000) {
uint32_t timeout_ms = domain_policy_rest_ota_timeout_ms();
if (jtimeout != NULL) {
if (!cJSON_IsNumber(jtimeout) ||
jtimeout->valuedouble < (double)domain_policy_rest_ota_timeout_min_ms() ||
jtimeout->valuedouble > (double)domain_policy_rest_ota_timeout_max_ms()) {
cJSON_Delete(json);
return rest_server_send_error(req, "400 Bad Request", "timeout_ms out of range");
}
timeout_ms = (uint32_t)jtimeout->valuedouble;
}
@@ -734,8 +754,14 @@ 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 = runtime_policy_rest_ota_timeout_ms();
if (cJSON_IsNumber(jtimeout) && jtimeout->valuedouble > 0 && jtimeout->valuedouble <= 30000) {
uint32_t timeout_ms = domain_policy_rest_ota_timeout_ms();
if (jtimeout != NULL) {
if (!cJSON_IsNumber(jtimeout) ||
jtimeout->valuedouble < (double)domain_policy_rest_ota_timeout_min_ms() ||
jtimeout->valuedouble > (double)domain_policy_rest_ota_timeout_max_ms()) {
cJSON_Delete(json);
return rest_server_send_error(req, "400 Bad Request", "timeout_ms out of range");
}
timeout_ms = (uint32_t)jtimeout->valuedouble;
}
bool is_last = rest_server_json_bool_with_default(jlast, false);
@@ -775,134 +801,7 @@ esp_err_t rest_server_ota_upgrade_post(httpd_req_t *req) {
if (!rest_server_auth_ok(req)) {
return rest_server_send_error(req, "401 Unauthorized", "unauthorized");
}
char *body = NULL;
esp_err_t body_err = rest_server_read_body(req, &body);
if (body_err != ESP_OK) {
return rest_server_send_error(req, "400 Bad Request", "invalid request body");
}
cJSON *json = cJSON_Parse(body);
free(body);
if (json == NULL) {
return rest_server_send_error(req, "400 Bad Request", "invalid json");
}
cJSON *jfirmware = cJSON_GetObjectItemCaseSensitive(json, "firmware");
cJSON *jjumpboot = cJSON_GetObjectItemCaseSensitive(json, "jump_boot");
cJSON *jjumpapp = cJSON_GetObjectItemCaseSensitive(json, "jump_app");
cJSON *jpagesize = cJSON_GetObjectItemCaseSensitive(json, "page_size");
cJSON *jpacketsize = cJSON_GetObjectItemCaseSensitive(json, "packet_size");
cJSON *jtimeout = cJSON_GetObjectItemCaseSensitive(json, "timeout_ms_per_step");
cJSON *jreadversion = cJSON_GetObjectItemCaseSensitive(json, "read_version_after");
if (!cJSON_IsString(jfirmware) || jfirmware->valuestring == NULL) {
cJSON_Delete(json);
return rest_server_send_error(req, "400 Bad Request", "firmware(base64) is required");
}
bool jump_boot = rest_server_json_bool_with_default(jjumpboot, true);
bool jump_app = rest_server_json_bool_with_default(jjumpapp, true);
bool read_version_after = rest_server_json_bool_with_default(jreadversion, true);
uint16_t page_size = 1024;
uint16_t packet_size = 236;
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;
}
if (cJSON_IsNumber(jpacketsize) && jpacketsize->valuedouble >= 16 && jpacketsize->valuedouble <= 236) {
packet_size = (uint16_t)jpacketsize->valuedouble;
}
if (cJSON_IsNumber(jtimeout) && jtimeout->valuedouble >= 500 && jtimeout->valuedouble <= 60000) {
timeout_ms = (uint32_t)jtimeout->valuedouble;
}
uint8_t *firmware = NULL;
size_t firmware_len = 0;
esp_err_t b64_rc = rest_server_base64_decode_alloc(jfirmware->valuestring, &firmware, &firmware_len);
cJSON_Delete(json);
if (b64_rc != ESP_OK || firmware_len == 0) {
free(firmware);
return rest_server_send_error(req, "400 Bad Request", "invalid firmware base64");
}
char cmd_err[128] = {0};
if (jump_boot) {
esp_err_t rc = printer_protocol_ota_jump_boot(timeout_ms, cmd_err, sizeof(cmd_err));
if (rc != ESP_OK) {
free(firmware);
return rest_server_send_error(req, "409 Conflict", cmd_err[0] != '\0' ? cmd_err : "jump boot failed");
}
}
uint32_t total_pages = (uint32_t)((firmware_len + page_size - 1) / page_size);
for (uint32_t page = 0; page < total_pages; ++page) {
esp_err_t rc = printer_protocol_ota_erase_page((uint16_t)page, timeout_ms, cmd_err, sizeof(cmd_err));
if (rc != ESP_OK) {
free(firmware);
return rest_server_send_error(req,
"409 Conflict",
cmd_err[0] != '\0' ? cmd_err : "erase page failed");
}
}
uint32_t total_packets = (uint32_t)((firmware_len + packet_size - 1) / packet_size);
for (uint32_t packet = 0; packet < total_packets; ++packet) {
size_t start = (size_t)packet * packet_size;
size_t remain = firmware_len - start;
size_t len = remain > packet_size ? packet_size : remain;
bool is_last = (packet + 1) == total_packets;
esp_err_t rc = printer_protocol_ota_write_frame((uint16_t)packet,
is_last,
firmware + start,
len,
timeout_ms,
cmd_err,
sizeof(cmd_err));
if (rc != ESP_OK) {
free(firmware);
return rest_server_send_error(req,
"409 Conflict",
cmd_err[0] != '\0' ? cmd_err : "write frame failed");
}
}
if (jump_app) {
esp_err_t rc = printer_protocol_ota_jump_app(timeout_ms, cmd_err, sizeof(cmd_err));
if (rc != ESP_OK) {
free(firmware);
return rest_server_send_error(req, "409 Conflict", cmd_err[0] != '\0' ? cmd_err : "jump app failed");
}
}
printer_ota_version_t version = {0};
bool version_ok = false;
if (read_version_after) {
if (printer_protocol_ota_get_version(&version, timeout_ms, cmd_err, sizeof(cmd_err)) == ESP_OK) {
version_ok = true;
}
}
free(firmware);
cJSON *root = cJSON_CreateObject();
cJSON_AddBoolToObject(root, "ok", true);
cJSON_AddNumberToObject(root, "firmware_len", (double)firmware_len);
cJSON_AddNumberToObject(root, "page_size", page_size);
cJSON_AddNumberToObject(root, "packet_size", packet_size);
cJSON_AddNumberToObject(root, "total_pages", total_pages);
cJSON_AddNumberToObject(root, "total_packets", total_packets);
cJSON_AddBoolToObject(root, "jump_boot", jump_boot);
cJSON_AddBoolToObject(root, "jump_app", jump_app);
if (version_ok) {
cJSON *v = cJSON_AddObjectToObject(root, "version");
cJSON_AddNumberToObject(v, "major", version.major);
cJSON_AddNumberToObject(v, "minor", version.minor);
cJSON_AddNumberToObject(v, "patch", version.patch);
}
esp_err_t err = rest_server_send_json(req, "200 OK", root);
cJSON_Delete(root);
return err;
return rest_server_send_error(req,
"409 Conflict",
"bulk ota upgrade endpoint disabled; use jump/erase/write/version step APIs");
}

View File

@@ -244,8 +244,8 @@ static bool parse_image_generation_options(cJSON *json,
}
memset(out, 0, sizeof(*out));
out->timeout_ms = runtime_policy_image_generation_timeout_default_ms();
out->fetch_timeout_ms = runtime_policy_image_download_timeout_default_ms();
out->timeout_ms = domain_policy_image_generation_timeout_default_ms();
out->fetch_timeout_ms = domain_policy_image_download_timeout_default_ms();
cJSON *jprompt = cJSON_GetObjectItemCaseSensitive(json, "prompt");
if (!cJSON_IsString(jprompt) || jprompt->valuestring == NULL || jprompt->valuestring[0] == '\0') {
@@ -304,14 +304,14 @@ static bool parse_image_generation_options(cJSON *json,
cJSON *jtimeout = cJSON_GetObjectItemCaseSensitive(json, "timeout_ms");
if (cJSON_IsNumber(jtimeout)) {
if (jtimeout->valuedouble < runtime_policy_image_generation_timeout_min_ms() ||
jtimeout->valuedouble > runtime_policy_image_generation_timeout_max_ms()) {
if (jtimeout->valuedouble < domain_policy_image_generation_timeout_min_ms() ||
jtimeout->valuedouble > domain_policy_image_generation_timeout_max_ms()) {
if (err != NULL && err_len > 0) {
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());
(unsigned)domain_policy_image_generation_timeout_min_ms(),
(unsigned)domain_policy_image_generation_timeout_max_ms());
}
return false;
}
@@ -320,14 +320,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 < runtime_policy_image_download_timeout_min_ms() ||
jfetch_timeout->valuedouble > runtime_policy_image_download_timeout_max_ms()) {
if (jfetch_timeout->valuedouble < domain_policy_image_download_timeout_min_ms() ||
jfetch_timeout->valuedouble > domain_policy_image_download_timeout_max_ms()) {
if (err != NULL && err_len > 0) {
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());
(unsigned)domain_policy_image_download_timeout_min_ms(),
(unsigned)domain_policy_image_download_timeout_max_ms());
}
return false;
}

View File

@@ -266,28 +266,6 @@ esp_err_t rest_server_print_label_post(httpd_req_t *req) {
offset_value = (uint8_t)joffset->valuedouble;
}
if (has_offset) {
char cmd_err[128] = {0};
esp_err_t offset_rc = printer_protocol_set_label_offset(offset_value, 3000, cmd_err, sizeof(cmd_err));
if (offset_rc != ESP_OK) {
cJSON_Delete(json);
return rest_server_send_error(req,
"409 Conflict",
cmd_err[0] != '\0' ? cmd_err : "set label offset failed");
}
}
if (gap_move_before) {
char cmd_err[128] = {0};
esp_err_t gap_rc = printer_protocol_gap_move(5000, cmd_err, sizeof(cmd_err));
if (gap_rc != ESP_OK) {
cJSON_Delete(json);
return rest_server_send_error(req,
"409 Conflict",
cmd_err[0] != '\0' ? cmd_err : "gap move failed");
}
}
const char *density = (cJSON_IsString(jdensity) && jdensity->valuestring != NULL)
? jdensity->valuestring
: "中等";
@@ -312,6 +290,33 @@ esp_err_t rest_server_print_label_post(httpd_req_t *req) {
decode_err[0] != '\0' ? decode_err : "decode image failed");
}
if (has_offset) {
char cmd_err[128] = {0};
esp_err_t offset_rc = printer_protocol_set_label_offset(offset_value,
domain_policy_rest_label_timeout_ms(),
cmd_err,
sizeof(cmd_err));
if (offset_rc != ESP_OK) {
free(raster);
return rest_server_send_error(req,
"409 Conflict",
cmd_err[0] != '\0' ? cmd_err : "set label offset failed");
}
}
if (gap_move_before) {
char cmd_err[128] = {0};
esp_err_t gap_rc = printer_protocol_gap_move(domain_policy_rest_label_timeout_ms(),
cmd_err,
sizeof(cmd_err));
if (gap_rc != ESP_OK) {
free(raster);
return rest_server_send_error(req,
"409 Conflict",
cmd_err[0] != '\0' ? cmd_err : "gap move failed");
}
}
esp_err_t submit_rc = rest_server_print_submit_raster_job_and_reply(req,
raster,
raster_len,

View File

@@ -4,6 +4,45 @@
#include "domain.h"
#define VOICE_CONTROL_TIMEOUT_MIN_MS 500
#define VOICE_CONTROL_TIMEOUT_MAX_MS 30000
static esp_err_t rest_server_parse_voice_timeout(httpd_req_t *req, uint32_t *out_timeout_ms) {
if (out_timeout_ms == NULL) {
return ESP_ERR_INVALID_ARG;
}
*out_timeout_ms = 0;
if (req->content_len <= 0) {
return ESP_OK;
}
char *body = NULL;
esp_err_t body_err = rest_server_read_body(req, &body);
if (body_err != ESP_OK) {
return body_err;
}
cJSON *json = cJSON_Parse(body);
free(body);
if (json == NULL) {
return ESP_ERR_INVALID_ARG;
}
cJSON *jtimeout = cJSON_GetObjectItemCaseSensitive(json, "timeout_ms");
if (jtimeout != NULL) {
if (!cJSON_IsNumber(jtimeout) ||
jtimeout->valuedouble < VOICE_CONTROL_TIMEOUT_MIN_MS ||
jtimeout->valuedouble > VOICE_CONTROL_TIMEOUT_MAX_MS) {
cJSON_Delete(json);
return ESP_ERR_INVALID_ARG;
}
*out_timeout_ms = (uint32_t)jtimeout->valuedouble;
}
cJSON_Delete(json);
return ESP_OK;
}
static void rest_server_add_voice_status(cJSON *root) {
voice_interaction_status_t st = {0};
voice_interaction_get_status(&st);
@@ -48,18 +87,19 @@ esp_err_t rest_server_voice_session_start_post(httpd_req_t *req) {
return rest_server_send_error(req, "401 Unauthorized", "unauthorized");
}
if (req->content_len > 0) {
char *body = NULL;
esp_err_t body_err = rest_server_read_body(req, &body);
if (body_err != ESP_OK) {
return rest_server_send_error(req, "400 Bad Request", "invalid request body");
}
free(body);
uint32_t timeout_ms = 0;
if (rest_server_parse_voice_timeout(req, &timeout_ms) != ESP_OK) {
return rest_server_send_error(req, "400 Bad Request", "invalid request body");
}
char start_err[128] = {0};
esp_err_t rc = voice_interaction_start(start_err, sizeof(start_err));
esp_err_t rc = voice_interaction_start_with_timeout(timeout_ms, start_err, sizeof(start_err));
if (rc != ESP_OK) {
if (rc == ESP_ERR_TIMEOUT) {
return rest_server_send_error(req,
"504 Gateway Timeout",
start_err[0] != '\0' ? start_err : "voice session start timeout");
}
return rest_server_send_error(req,
"409 Conflict",
start_err[0] != '\0' ? start_err : "voice session start failed");
@@ -80,18 +120,19 @@ esp_err_t rest_server_voice_session_stop_post(httpd_req_t *req) {
return rest_server_send_error(req, "401 Unauthorized", "unauthorized");
}
if (req->content_len > 0) {
char *body = NULL;
esp_err_t body_err = rest_server_read_body(req, &body);
if (body_err != ESP_OK) {
return rest_server_send_error(req, "400 Bad Request", "invalid request body");
}
free(body);
uint32_t timeout_ms = 0;
if (rest_server_parse_voice_timeout(req, &timeout_ms) != ESP_OK) {
return rest_server_send_error(req, "400 Bad Request", "invalid request body");
}
char stop_err[128] = {0};
esp_err_t rc = voice_interaction_stop(stop_err, sizeof(stop_err));
esp_err_t rc = voice_interaction_stop_with_timeout(timeout_ms, stop_err, sizeof(stop_err));
if (rc != ESP_OK) {
if (rc == ESP_ERR_TIMEOUT) {
return rest_server_send_error(req,
"504 Gateway Timeout",
stop_err[0] != '\0' ? stop_err : "voice session stop timeout");
}
return rest_server_send_error(req,
"409 Conflict",
stop_err[0] != '\0' ? stop_err : "voice session stop failed");