refactor(printer): remove controller legacy and unify printer naming

This commit is contained in:
admin
2026-03-01 14:06:38 +08:00
parent e694a85997
commit 57adabaa3f
16 changed files with 111 additions and 445 deletions

View File

@@ -1,3 +1,3 @@
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(TQ_printer_controller)
project(TQ_printer)

View File

@@ -1,12 +1,12 @@
# ESP32-S3 TQ Printer Controller (Direct Thermal, No Business HTTP Server)
# ESP32-S3 TQ Thermal Printer Firmware (No Business HTTP Server)
This firmware now runs in direct-printer mode and does not expose the previous
This firmware now runs in printer mode and does not expose the previous
business REST endpoints (`/v1/*`).
## Features
- Direct thermal printer backend (`PRINTER_BACKEND_DIRECT`)
- Auto-connect direct printer during startup
- Thermal printer driver (single printer path)
- Auto-connect printer during startup
- Async print queue and worker lifecycle management
- Printer precheck (paper / battery / temperature)
- MIC key push-to-talk voice flow (button-triggered, no HTTP trigger)
@@ -44,14 +44,14 @@ idf.py -p /dev/tty.usbmodemXXXX flash monitor
## Config
In `menuconfig -> TQ Controller Config`:
In `menuconfig -> TQ Printer Config`:
- Wi-Fi provisioning:
- `TQ_WIFI_PROV_SOFTAP_SSID`
- `TQ_WIFI_PROV_SOFTAP_PASSWORD`
- `TQ_WIFI_PROV_SOFTAP_CHANNEL`
- `TQ_WIFI_PROV_SOFTAP_MAX_CONN`
- Direct thermal printer runtime and safety policy:
- Thermal printer runtime and safety policy:
- `TQ_DIRECT_PRINTER_*`
- `TQ_PRINTER_*`
- Z-Image HTTP fields:

View File

@@ -7,15 +7,15 @@
static const char *TAG = "app_main";
esp_err_t app_composition_start(void) {
return controller_lifecycle_start();
return control_plane_lifecycle_start();
}
void app_main(void) {
esp_err_t rc = app_composition_start();
if (rc != ESP_OK) {
ESP_LOGE(TAG, "Controller lifecycle start failed: %s", esp_err_to_name(rc));
ESP_LOGE(TAG, "control-plane lifecycle start failed: %s", esp_err_to_name(rc));
return;
}
ESP_LOGI(TAG, "TQ controller started");
ESP_LOGI(TAG, "TQ printer runtime started");
}

View File

@@ -1,6 +1,6 @@
idf_component_register(
SRCS
"src/controller_lifecycle.c"
"src/control_plane_lifecycle.c"
INCLUDE_DIRS
"include"
PRIV_INCLUDE_DIRS

View File

@@ -9,25 +9,25 @@ extern "C" {
#endif
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;
CONTROL_PLANE_LIFECYCLE_STATE_STOPPED = 0,
CONTROL_PLANE_LIFECYCLE_STATE_STARTING,
CONTROL_PLANE_LIFECYCLE_STATE_RUNNING,
CONTROL_PLANE_LIFECYCLE_STATE_DEGRADED,
CONTROL_PLANE_LIFECYCLE_STATE_STOPPING,
} control_plane_lifecycle_state_t;
typedef struct {
controller_lifecycle_state_t state;
control_plane_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;
} control_plane_lifecycle_status_t;
esp_err_t controller_lifecycle_start(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);
esp_err_t control_plane_lifecycle_start(void);
esp_err_t control_plane_lifecycle_stop(void);
void control_plane_lifecycle_get_status(control_plane_lifecycle_status_t *out_status);
const char *control_plane_lifecycle_state_str(control_plane_lifecycle_state_t state);
#ifdef __cplusplus
}

View File

@@ -9,10 +9,10 @@
#include "freertos/semphr.h"
#include "freertos/task.h"
static const char *TAG = "controller_lifecycle";
static const char *TAG = "control_plane_lifecycle";
static SemaphoreHandle_t s_lock;
static controller_lifecycle_status_t s_status = {
.state = CONTROLLER_LIFECYCLE_STATE_STOPPED,
static control_plane_lifecycle_status_t s_status = {
.state = CONTROL_PLANE_LIFECYCLE_STATE_STOPPED,
.last_error = ESP_OK,
.start_attempt = 0,
.last_transition_ms = 0,
@@ -30,7 +30,7 @@ static bool lifecycle_lock_take(uint32_t timeout_ms) {
return s_lock != NULL && xSemaphoreTake(s_lock, pdMS_TO_TICKS(timeout_ms)) == pdTRUE;
}
static void lifecycle_set_state_locked(controller_lifecycle_state_t state,
static void lifecycle_set_state_locked(control_plane_lifecycle_state_t state,
esp_err_t last_error,
const char *stage) {
s_status.state = state;
@@ -40,17 +40,17 @@ static void lifecycle_set_state_locked(controller_lifecycle_state_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) {
const char *control_plane_lifecycle_state_str(control_plane_lifecycle_state_t state) {
switch (state) {
case CONTROLLER_LIFECYCLE_STATE_STOPPED:
case CONTROL_PLANE_LIFECYCLE_STATE_STOPPED:
return "stopped";
case CONTROLLER_LIFECYCLE_STATE_STARTING:
case CONTROL_PLANE_LIFECYCLE_STATE_STARTING:
return "starting";
case CONTROLLER_LIFECYCLE_STATE_RUNNING:
case CONTROL_PLANE_LIFECYCLE_STATE_RUNNING:
return "running";
case CONTROLLER_LIFECYCLE_STATE_DEGRADED:
case CONTROL_PLANE_LIFECYCLE_STATE_DEGRADED:
return "degraded";
case CONTROLLER_LIFECYCLE_STATE_STOPPING:
case CONTROL_PLANE_LIFECYCLE_STATE_STOPPING:
return "stopping";
default:
return "unknown";
@@ -124,7 +124,7 @@ static esp_err_t lifecycle_run_step_with_retry(const char *stage, lifecycle_step
return ESP_FAIL;
}
esp_err_t controller_lifecycle_start(void) {
esp_err_t control_plane_lifecycle_start(void) {
domain_diag_counter_add(DOMAIN_DIAG_COUNTER_LIFECYCLE_START_ATTEMPT, 1);
if (!lifecycle_lock_take(1000)) {
@@ -133,18 +133,18 @@ esp_err_t controller_lifecycle_start(void) {
return ESP_ERR_TIMEOUT;
}
if (s_status.state == CONTROLLER_LIFECYCLE_STATE_RUNNING) {
if (s_status.state == CONTROL_PLANE_LIFECYCLE_STATE_RUNNING) {
xSemaphoreGive(s_lock);
return ESP_OK;
}
if (s_status.state == CONTROLLER_LIFECYCLE_STATE_STARTING ||
s_status.state == CONTROLLER_LIFECYCLE_STATE_STOPPING) {
if (s_status.state == CONTROL_PLANE_LIFECYCLE_STATE_STARTING ||
s_status.state == CONTROL_PLANE_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");
lifecycle_set_state_locked(CONTROL_PLANE_LIFECYCLE_STATE_STARTING, ESP_OK, "bootstrap");
xSemaphoreGive(s_lock);
bool system_started = false;
@@ -176,12 +176,12 @@ esp_err_t controller_lifecycle_start(void) {
image_generation_schedule_prewarm();
if (lifecycle_lock_take(1000)) {
lifecycle_set_state_locked(CONTROLLER_LIFECYCLE_STATE_RUNNING, ESP_OK, "running");
lifecycle_set_state_locked(CONTROL_PLANE_LIFECYCLE_STATE_RUNNING, ESP_OK, "running");
xSemaphoreGive(s_lock);
}
domain_diag_counter_add(DOMAIN_DIAG_COUNTER_LIFECYCLE_START_SUCCESS, 1);
ESP_LOGI(TAG, "controller lifecycle started");
ESP_LOGI(TAG, "control-plane lifecycle started");
return ESP_OK;
start_failed:
@@ -196,20 +196,20 @@ start_failed:
}
if (lifecycle_lock_take(1000)) {
lifecycle_set_state_locked(CONTROLLER_LIFECYCLE_STATE_DEGRADED, rc, failed_stage);
lifecycle_set_state_locked(CONTROL_PLANE_LIFECYCLE_STATE_DEGRADED, rc, failed_stage);
xSemaphoreGive(s_lock);
}
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",
"control-plane lifecycle start failed at stage=%s, rc=0x%x",
failed_stage,
(unsigned)rc);
return rc;
}
esp_err_t controller_lifecycle_stop(void) {
esp_err_t control_plane_lifecycle_stop(void) {
domain_diag_counter_add(DOMAIN_DIAG_COUNTER_LIFECYCLE_STOP_ATTEMPT, 1);
if (!lifecycle_lock_take(1000)) {
@@ -218,17 +218,17 @@ esp_err_t controller_lifecycle_stop(void) {
return ESP_ERR_TIMEOUT;
}
if (s_status.state == CONTROLLER_LIFECYCLE_STATE_STOPPED) {
if (s_status.state == CONTROL_PLANE_LIFECYCLE_STATE_STOPPED) {
xSemaphoreGive(s_lock);
return ESP_OK;
}
if (s_status.state == CONTROLLER_LIFECYCLE_STATE_STARTING ||
s_status.state == CONTROLLER_LIFECYCLE_STATE_STOPPING) {
if (s_status.state == CONTROL_PLANE_LIFECYCLE_STATE_STARTING ||
s_status.state == CONTROL_PLANE_LIFECYCLE_STATE_STOPPING) {
xSemaphoreGive(s_lock);
return ESP_ERR_INVALID_STATE;
}
lifecycle_set_state_locked(CONTROLLER_LIFECYCLE_STATE_STOPPING, ESP_OK, "stopping");
lifecycle_set_state_locked(CONTROL_PLANE_LIFECYCLE_STATE_STOPPING, ESP_OK, "stopping");
xSemaphoreGive(s_lock);
esp_err_t first_err = ESP_OK;
@@ -250,26 +250,26 @@ esp_err_t controller_lifecycle_stop(void) {
if (lifecycle_lock_take(1000)) {
if (first_err == ESP_OK) {
lifecycle_set_state_locked(CONTROLLER_LIFECYCLE_STATE_STOPPED, ESP_OK, "stopped");
lifecycle_set_state_locked(CONTROL_PLANE_LIFECYCLE_STATE_STOPPED, ESP_OK, "stopped");
} else {
lifecycle_set_state_locked(CONTROLLER_LIFECYCLE_STATE_DEGRADED, first_err, "stop_failed");
lifecycle_set_state_locked(CONTROL_PLANE_LIFECYCLE_STATE_DEGRADED, first_err, "stop_failed");
}
xSemaphoreGive(s_lock);
}
if (first_err == ESP_OK) {
domain_diag_counter_add(DOMAIN_DIAG_COUNTER_LIFECYCLE_STOP_SUCCESS, 1);
ESP_LOGI(TAG, "controller lifecycle stopped");
ESP_LOGI(TAG, "control-plane lifecycle stopped");
} else {
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);
domain_diag_record_error("lifecycle_stop", first_err, "control-plane stop failed");
ESP_LOGE(TAG, "control-plane lifecycle stop failed, rc=0x%x", (unsigned)first_err);
}
return first_err;
}
void controller_lifecycle_get_status(controller_lifecycle_status_t *out_status) {
void control_plane_lifecycle_get_status(control_plane_lifecycle_status_t *out_status) {
if (out_status == NULL) {
return;
}

View File

@@ -25,17 +25,9 @@ bool domain_policy_is_retryable_error(esp_err_t err);
uint32_t domain_policy_printer_stop_timeout_ms(void);
uint32_t domain_policy_rest_printer_connect_timeout_ms(void);
uint32_t domain_policy_rest_printer_connect_timeout_min_ms(void);
uint32_t domain_policy_rest_printer_connect_timeout_max_ms(void);
uint32_t domain_policy_rest_label_timeout_ms(void);
uint32_t domain_policy_rest_label_timeout_min_ms(void);
uint32_t domain_policy_rest_label_timeout_max_ms(void);
uint32_t domain_policy_rest_ota_timeout_ms(void);
uint32_t domain_policy_rest_ota_timeout_min_ms(void);
uint32_t domain_policy_rest_ota_timeout_max_ms(void);
uint32_t domain_policy_printer_connect_timeout_ms(void);
uint32_t domain_policy_printer_connect_timeout_min_ms(void);
uint32_t domain_policy_printer_connect_timeout_max_ms(void);
uint32_t domain_policy_image_generation_timeout_default_ms(void);
uint32_t domain_policy_image_generation_timeout_min_ms(void);
@@ -65,8 +57,6 @@ typedef enum {
DOMAIN_DIAG_COUNTER_IMAGE_GENERATE_SUCCESS,
DOMAIN_DIAG_COUNTER_IMAGE_GENERATE_FAILED,
DOMAIN_DIAG_COUNTER_IMAGE_GENERATE_TIMEOUT,
DOMAIN_DIAG_COUNTER_REST_RESPONSES_TOTAL,
DOMAIN_DIAG_COUNTER_REST_ERRORS_TOTAL,
DOMAIN_DIAG_COUNTER_MAX,
} domain_diag_counter_t;
@@ -201,23 +191,7 @@ typedef struct {
} print_job_info_t;
typedef struct {
uint8_t major;
uint8_t minor;
uint8_t patch;
} printer_ota_version_t;
typedef enum {
PRINTER_BACKEND_DIRECT = 0,
} printer_backend_t;
typedef struct {
printer_backend_t backend;
const char *name;
uint32_t timeout_ms;
} printer_connect_options_t;
typedef struct {
// Direct backend only: bypass paper/temp/battery precheck for this print job.
// Printer-only option: bypass paper/temp/battery precheck for this print job.
bool direct_ignore_precheck;
} printer_print_options_t;
@@ -234,25 +208,13 @@ typedef struct {
} printer_direct_debug_config_t;
typedef struct {
bool supports_connect;
bool supports_gap_move;
bool supports_label_offset;
bool supports_ota;
} printer_capabilities_t;
typedef struct {
printer_backend_t backend;
bool connected;
bool transport_ready;
bool busy;
bool has_paper;
int8_t paper_gpio_level;
uint8_t paper_present_level;
uint8_t battery_percent;
float temperature;
bool supports_gap_move;
bool supports_label_offset;
bool supports_ota;
uint32_t queue_depth;
int64_t last_status_ms;
} printer_runtime_status_t;
@@ -262,13 +224,6 @@ typedef uint32_t printer_status_poll_pause_token_t;
esp_err_t printer_protocol_init(void);
esp_err_t printer_protocol_stop(uint32_t timeout_ms);
esp_err_t printer_protocol_set_backend(printer_backend_t backend, char *err, size_t err_len);
printer_backend_t printer_protocol_get_backend(void);
esp_err_t printer_protocol_connect(const char *target_name, uint32_t timeout_ms);
esp_err_t printer_protocol_connect_ex(const printer_connect_options_t *opt, char *err, size_t err_len);
void printer_protocol_disconnect(void);
void printer_protocol_get_capabilities(printer_capabilities_t *out_capabilities);
esp_err_t printer_protocol_get_direct_debug_config(printer_direct_debug_config_t *out_config,
char *err,
size_t err_len);
@@ -305,23 +260,6 @@ esp_err_t printer_protocol_cancel_job(uint32_t job_id, char *err, size_t err_len
size_t printer_protocol_cleanup_jobs(bool include_success, bool include_failed, bool include_canceled);
esp_err_t printer_protocol_gap_move(uint32_t timeout_ms, char *err, size_t err_len);
esp_err_t printer_protocol_get_label_offset(uint8_t *out_offset, uint32_t timeout_ms, char *err, size_t err_len);
esp_err_t printer_protocol_set_label_offset(uint8_t offset, uint32_t timeout_ms, char *err, size_t err_len);
esp_err_t printer_protocol_ota_jump_boot(uint32_t timeout_ms, char *err, size_t err_len);
esp_err_t printer_protocol_ota_jump_app(uint32_t timeout_ms, char *err, size_t err_len);
esp_err_t printer_protocol_ota_erase_page(uint16_t page_num, uint32_t timeout_ms, char *err, size_t err_len);
esp_err_t printer_protocol_ota_write_frame(uint16_t packet_num,
bool is_last_frame,
const uint8_t *data,
size_t data_len,
uint32_t timeout_ms,
char *err,
size_t err_len);
esp_err_t printer_protocol_ota_get_version(printer_ota_version_t *out_version,
uint32_t timeout_ms,
char *err,
size_t err_len);
const char *printer_protocol_job_state_str(print_job_state_t state);

View File

@@ -42,10 +42,6 @@ static runtime_diag_counter_t to_platform_counter(domain_diag_counter_t counter)
return RUNTIME_DIAG_COUNTER_IMAGE_GENERATE_FAILED;
case DOMAIN_DIAG_COUNTER_IMAGE_GENERATE_TIMEOUT:
return RUNTIME_DIAG_COUNTER_IMAGE_GENERATE_TIMEOUT;
case DOMAIN_DIAG_COUNTER_REST_RESPONSES_TOTAL:
return RUNTIME_DIAG_COUNTER_REST_RESPONSES_TOTAL;
case DOMAIN_DIAG_COUNTER_REST_ERRORS_TOTAL:
return RUNTIME_DIAG_COUNTER_REST_ERRORS_TOTAL;
default:
return RUNTIME_DIAG_COUNTER_MAX;
}
@@ -80,39 +76,15 @@ uint32_t domain_policy_printer_stop_timeout_ms(void) {
return runtime_policy_printer_stop_timeout_ms();
}
uint32_t domain_policy_rest_printer_connect_timeout_ms(void) {
return runtime_policy_rest_printer_connect_timeout_ms();
uint32_t domain_policy_printer_connect_timeout_ms(void) {
return runtime_policy_printer_connect_timeout_ms();
}
uint32_t domain_policy_rest_printer_connect_timeout_min_ms(void) {
uint32_t domain_policy_printer_connect_timeout_min_ms(void) {
return 1000;
}
uint32_t domain_policy_rest_printer_connect_timeout_max_ms(void) {
return 60000;
}
uint32_t domain_policy_rest_label_timeout_ms(void) {
return runtime_policy_rest_label_timeout_ms();
}
uint32_t domain_policy_rest_label_timeout_min_ms(void) {
return 500;
}
uint32_t domain_policy_rest_label_timeout_max_ms(void) {
return 30000;
}
uint32_t domain_policy_rest_ota_timeout_ms(void) {
return runtime_policy_rest_ota_timeout_ms();
}
uint32_t domain_policy_rest_ota_timeout_min_ms(void) {
return 500;
}
uint32_t domain_policy_rest_ota_timeout_max_ms(void) {
uint32_t domain_policy_printer_connect_timeout_max_ms(void) {
return 60000;
}

View File

@@ -34,7 +34,6 @@ TaskHandle_t s_worker_task;
TaskHandle_t s_status_poll_task_handle;
bool s_protocol_initialized;
bool s_protocol_stopping;
printer_backend_t s_backend = PRINTER_BACKEND_DIRECT;
static const char *TAG = "printer_protocol";
@@ -44,25 +43,7 @@ static const char *TAG = "printer_protocol";
#define PRINT_WORKER_CORE_ID 1
#endif
static printer_backend_t default_backend_on_startup(void) {
return PRINTER_BACKEND_DIRECT;
}
static void backend_capabilities_for(printer_backend_t backend, printer_capabilities_t *out_caps) {
if (out_caps == NULL) {
return;
}
memset(out_caps, 0, sizeof(*out_caps));
out_caps->supports_connect = (backend == PRINTER_BACKEND_DIRECT);
out_caps->supports_gap_move = (backend == PRINTER_BACKEND_DIRECT);
out_caps->supports_label_offset = false;
out_caps->supports_ota = false;
}
static esp_err_t ensure_backend_ready(printer_backend_t backend) {
if (backend != PRINTER_BACKEND_DIRECT) {
return ESP_ERR_NOT_SUPPORTED;
}
static esp_err_t ensure_direct_backend_ready(void) {
if (!runtime_policy_direct_printer_enabled()) {
return ESP_ERR_NOT_SUPPORTED;
}
@@ -361,16 +342,15 @@ esp_err_t printer_protocol_init(void) {
runtime_diag_set_gauge(RUNTIME_DIAG_GAUGE_PRINTER_QUEUE_DEPTH, 0);
s_protocol_initialized = true;
s_protocol_stopping = false;
s_backend = default_backend_on_startup();
esp_err_t err = ensure_backend_ready(s_backend);
esp_err_t err = ensure_direct_backend_ready();
if (err != ESP_OK) {
s_protocol_initialized = false;
destroy_runtime_objects();
return err;
}
uint32_t connect_timeout_ms = domain_policy_rest_printer_connect_timeout_ms();
uint32_t connect_timeout_ms = domain_policy_printer_connect_timeout_ms();
err = platform_direct_printer_connect(connect_timeout_ms);
if (err != ESP_OK) {
s_protocol_initialized = false;
@@ -384,7 +364,7 @@ esp_err_t printer_protocol_init(void) {
refresh_direct_status_locked();
xSemaphoreGive(s_mutex);
}
ESP_LOGI(TAG, "direct printer auto connected at startup");
ESP_LOGI(TAG, "printer auto connected at startup");
BaseType_t ok = printer_create_task_prefer_psram(printer_protocol_worker_task,
"print_worker",
@@ -484,7 +464,6 @@ esp_err_t printer_protocol_stop(uint32_t timeout_ms) {
s_status_poll_task_handle = NULL;
s_protocol_initialized = false;
s_protocol_stopping = false;
s_backend = default_backend_on_startup();
runtime_diag_set_gauge(RUNTIME_DIAG_GAUGE_STATUS_POLL_PAUSE_DEPTH, 0);
runtime_diag_set_gauge(RUNTIME_DIAG_GAUGE_PRINTER_QUEUE_DEPTH, 0);
@@ -495,129 +474,6 @@ esp_err_t printer_protocol_stop(uint32_t timeout_ms) {
return (worker_done && poll_done) ? ESP_OK : ESP_ERR_TIMEOUT;
}
esp_err_t printer_protocol_set_backend(printer_backend_t backend, char *err, size_t err_len) {
if (backend != PRINTER_BACKEND_DIRECT) {
if (err != NULL && err_len > 0) {
snprintf(err, err_len, "only direct backend is supported");
}
return ESP_ERR_NOT_SUPPORTED;
}
if (!runtime_policy_direct_printer_enabled()) {
if (err != NULL && err_len > 0) {
snprintf(err, err_len, "direct backend disabled");
}
return ESP_ERR_NOT_SUPPORTED;
}
if (!s_protocol_initialized || s_protocol_stopping || s_mutex == NULL) {
if (err != NULL && err_len > 0) {
snprintf(err, err_len, "printer protocol unavailable");
}
return ESP_ERR_INVALID_STATE;
}
if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(runtime_policy_printer_control_lock_timeout_ms())) != pdTRUE) {
if (err != NULL && err_len > 0) {
snprintf(err, err_len, "lock timeout");
}
return ESP_ERR_TIMEOUT;
}
if (s_busy_refcnt != 0 || (s_job_queue != NULL && uxQueueMessagesWaiting(s_job_queue) > 0)) {
xSemaphoreGive(s_mutex);
if (err != NULL && err_len > 0) {
snprintf(err, err_len, "printer busy");
}
return ESP_ERR_INVALID_STATE;
}
s_backend = PRINTER_BACKEND_DIRECT;
xSemaphoreGive(s_mutex);
esp_err_t rc = ensure_backend_ready(PRINTER_BACKEND_DIRECT);
if (rc != ESP_OK) {
if (err != NULL && err_len > 0) {
snprintf(err, err_len, "direct backend unavailable");
}
return rc;
}
if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(200)) == pdTRUE) {
refresh_direct_status_locked();
xSemaphoreGive(s_mutex);
}
return ESP_OK;
}
printer_backend_t printer_protocol_get_backend(void) {
if (!s_protocol_initialized || s_mutex == NULL) {
return s_backend;
}
if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(100)) != pdTRUE) {
return s_backend;
}
printer_backend_t backend = s_backend;
xSemaphoreGive(s_mutex);
return backend;
}
esp_err_t printer_protocol_connect(const char *target_name, uint32_t timeout_ms) {
printer_connect_options_t opt = {
.backend = printer_protocol_get_backend(),
.name = target_name,
.timeout_ms = timeout_ms,
};
return printer_protocol_connect_ex(&opt, NULL, 0);
}
esp_err_t printer_protocol_connect_ex(const printer_connect_options_t *opt, char *err, size_t err_len) {
if (!s_protocol_initialized || s_protocol_stopping) {
if (err != NULL && err_len > 0) {
snprintf(err, err_len, "printer protocol unavailable");
}
return ESP_ERR_INVALID_STATE;
}
printer_backend_t backend = printer_protocol_get_backend();
uint32_t timeout_ms = 0;
if (opt != NULL) {
backend = opt->backend;
timeout_ms = opt->timeout_ms;
}
esp_err_t rc = printer_protocol_set_backend(backend, err, err_len);
if (rc != ESP_OK) {
return rc;
}
rc = ensure_backend_ready(PRINTER_BACKEND_DIRECT);
if (rc != ESP_OK) {
if (err != NULL && err_len > 0) {
snprintf(err, err_len, "direct backend unavailable");
}
return rc;
}
rc = platform_direct_printer_connect(timeout_ms);
if (rc == ESP_OK && s_mutex != NULL && xSemaphoreTake(s_mutex, pdMS_TO_TICKS(200)) == pdTRUE) {
refresh_direct_status_locked();
xSemaphoreGive(s_mutex);
}
return rc;
}
void printer_protocol_disconnect(void) {
platform_direct_printer_disconnect();
}
void printer_protocol_get_capabilities(printer_capabilities_t *out_capabilities) {
if (out_capabilities == NULL) {
return;
}
backend_capabilities_for(printer_protocol_get_backend(), out_capabilities);
}
void printer_protocol_get_runtime_status(printer_runtime_status_t *out_status) {
if (out_status == NULL) {
return;
@@ -625,16 +481,8 @@ void printer_protocol_get_runtime_status(printer_runtime_status_t *out_status) {
memset(out_status, 0, sizeof(*out_status));
out_status->paper_gpio_level = -1;
out_status->backend = printer_protocol_get_backend();
printer_capabilities_t caps = {0};
backend_capabilities_for(out_status->backend, &caps);
out_status->supports_gap_move = caps.supports_gap_move;
out_status->supports_label_offset = caps.supports_label_offset;
out_status->supports_ota = caps.supports_ota;
out_status->connected = platform_direct_printer_is_connected();
out_status->transport_ready = out_status->connected;
platform_printer_sensors_t sensors = {0};
if (platform_direct_printer_get_sensors(&sensors) == ESP_OK &&

View File

@@ -9,73 +9,14 @@ static void write_err(char *err, size_t err_len, const char *msg) {
}
}
static esp_err_t unsupported_operation(char *err, size_t err_len, const char *op) {
if (err != NULL && err_len > 0) {
snprintf(err, err_len, "%s is not supported on direct backend", op);
}
return ESP_ERR_NOT_SUPPORTED;
}
esp_err_t printer_protocol_gap_move(uint32_t timeout_ms, char *err, size_t err_len) {
if (!runtime_policy_direct_printer_enabled()) {
write_err(err, err_len, "direct backend disabled");
write_err(err, err_len, "printer driver disabled");
return ESP_ERR_NOT_SUPPORTED;
}
return platform_direct_printer_gap_move(timeout_ms, err, err_len);
}
esp_err_t printer_protocol_get_label_offset(uint8_t *out_offset, uint32_t timeout_ms, char *err, size_t err_len) {
(void)out_offset;
(void)timeout_ms;
return unsupported_operation(err, err_len, "label offset");
}
esp_err_t printer_protocol_set_label_offset(uint8_t offset, uint32_t timeout_ms, char *err, size_t err_len) {
(void)offset;
(void)timeout_ms;
return unsupported_operation(err, err_len, "label offset");
}
esp_err_t printer_protocol_ota_jump_boot(uint32_t timeout_ms, char *err, size_t err_len) {
(void)timeout_ms;
return unsupported_operation(err, err_len, "ota jump boot");
}
esp_err_t printer_protocol_ota_jump_app(uint32_t timeout_ms, char *err, size_t err_len) {
(void)timeout_ms;
return unsupported_operation(err, err_len, "ota jump app");
}
esp_err_t printer_protocol_ota_erase_page(uint16_t page_num, uint32_t timeout_ms, char *err, size_t err_len) {
(void)page_num;
(void)timeout_ms;
return unsupported_operation(err, err_len, "ota erase");
}
esp_err_t printer_protocol_ota_write_frame(uint16_t packet_num,
bool is_last_frame,
const uint8_t *data,
size_t data_len,
uint32_t timeout_ms,
char *err,
size_t err_len) {
(void)packet_num;
(void)is_last_frame;
(void)data;
(void)data_len;
(void)timeout_ms;
return unsupported_operation(err, err_len, "ota write");
}
esp_err_t printer_protocol_ota_get_version(printer_ota_version_t *out_version,
uint32_t timeout_ms,
char *err,
size_t err_len) {
(void)out_version;
(void)timeout_ms;
return unsupported_operation(err, err_len, "ota version");
}
esp_err_t printer_protocol_get_direct_debug_config(printer_direct_debug_config_t *out_config,
char *err,
size_t err_len) {
@@ -84,7 +25,7 @@ esp_err_t printer_protocol_get_direct_debug_config(printer_direct_debug_config_t
return ESP_ERR_INVALID_ARG;
}
if (!runtime_policy_direct_printer_enabled()) {
write_err(err, err_len, "direct backend disabled");
write_err(err, err_len, "printer driver disabled");
return ESP_ERR_NOT_SUPPORTED;
}
@@ -98,7 +39,7 @@ esp_err_t printer_protocol_get_direct_debug_config(printer_direct_debug_config_t
&out_config->override_motor_step_us,
&out_config->override_steps_per_line);
if (rc != ESP_OK) {
write_err(err, err_len, "get direct debug config failed");
write_err(err, err_len, "get printer debug config failed");
return rc;
}
return ESP_OK;
@@ -113,7 +54,7 @@ esp_err_t printer_protocol_set_direct_debug_config(const printer_direct_debug_co
return ESP_ERR_INVALID_ARG;
}
if (!runtime_policy_direct_printer_enabled()) {
write_err(err, err_len, "direct backend disabled");
write_err(err, err_len, "printer driver disabled");
return ESP_ERR_NOT_SUPPORTED;
}

View File

@@ -104,7 +104,7 @@ static bool run_print_job_direct(job_slot_t *job) {
} else if (rc == ESP_ERR_INVALID_STATE && job->cancel_requested) {
snprintf(job->error, sizeof(job->error), "job canceled");
} else {
snprintf(job->error, sizeof(job->error), "direct print failed");
snprintf(job->error, sizeof(job->error), "printer print failed");
}
return false;
}
@@ -118,7 +118,7 @@ static bool run_print_job_direct(job_slot_t *job) {
static bool run_print_job(job_slot_t *job) {
ESP_LOGI(TAG,
"job %u print start, backend=direct, raster_bytes=%u, size=%ux%u, density=%s, ignore_precheck=%d",
"job %u print start, mode=printer, raster_bytes=%u, size=%ux%u, density=%s, ignore_precheck=%d",
(unsigned)job->id,
(unsigned)job->data_len,
(unsigned)job->width,

View File

@@ -167,10 +167,7 @@ uint16_t runtime_policy_direct_printer_battery_divider_ratio_x1000(void);
uint32_t runtime_policy_direct_printer_ntc_pullup_ohms(void);
uint32_t runtime_policy_direct_printer_ntc_r25_ohms(void);
uint32_t runtime_policy_direct_printer_ntc_beta(void);
uint32_t runtime_policy_rest_printer_connect_timeout_ms(void);
uint32_t runtime_policy_rest_label_timeout_ms(void);
uint32_t runtime_policy_rest_ota_timeout_ms(void);
uint32_t runtime_policy_printer_connect_timeout_ms(void);
uint32_t runtime_policy_image_generation_timeout_default_ms(void);
uint32_t runtime_policy_image_generation_timeout_min_ms(void);
@@ -200,8 +197,6 @@ typedef enum {
RUNTIME_DIAG_COUNTER_IMAGE_GENERATE_SUCCESS,
RUNTIME_DIAG_COUNTER_IMAGE_GENERATE_FAILED,
RUNTIME_DIAG_COUNTER_IMAGE_GENERATE_TIMEOUT,
RUNTIME_DIAG_COUNTER_REST_RESPONSES_TOTAL,
RUNTIME_DIAG_COUNTER_REST_ERRORS_TOTAL,
RUNTIME_DIAG_COUNTER_MAX,
} runtime_diag_counter_t;

View File

@@ -39,7 +39,7 @@ static const uint16_t k_default_shift_clock_low_us = 5;
static const uint16_t k_default_latch_pulse_us = 1;
static const bool k_default_strobe_active_high = true;
static const char *TAG = "direct_printer";
static const char *TAG = "printer_driver";
static const uint8_t k_print_yield_lines = 8;
static const uint16_t k_gap_yield_steps = 32;
@@ -554,7 +554,7 @@ esp_err_t platform_direct_printer_init(void) {
s_state.motor_phase = 0;
s_state.connected = false;
s_state.initialized = true;
ESP_LOGI(TAG, "direct printer initialized");
ESP_LOGI(TAG, "printer initialized");
return ESP_OK;
#endif
}
@@ -732,7 +732,7 @@ esp_err_t platform_direct_printer_set_debug_config(bool has_config,
(void)override_motor_step_us;
(void)override_steps_per_line;
(void)reset_defaults;
write_err(err, err_len, "direct backend disabled");
write_err(err, err_len, "printer driver disabled");
return ESP_ERR_NOT_SUPPORTED;
#else
if (!has_config && !reset_defaults) {
@@ -742,11 +742,11 @@ esp_err_t platform_direct_printer_set_debug_config(bool has_config,
esp_err_t init_rc = platform_direct_printer_init();
if (init_rc != ESP_OK) {
write_err(err, err_len, "direct backend not initialized");
write_err(err, err_len, "printer driver not initialized");
return init_rc;
}
if (xSemaphoreTake(s_state.lock, pdMS_TO_TICKS(1000)) != pdTRUE) {
write_err(err, err_len, "direct printer lock timeout");
write_err(err, err_len, "printer lock timeout");
return ESP_ERR_TIMEOUT;
}
@@ -808,7 +808,7 @@ esp_err_t platform_direct_printer_print(const platform_direct_print_request_t *r
char *err,
size_t err_len) {
#if !CONFIG_TQ_DIRECT_PRINTER_ENABLE
write_err(err, err_len, "direct backend disabled");
write_err(err, err_len, "printer driver disabled");
return ESP_ERR_NOT_SUPPORTED;
#else
if (request == NULL || request->raster == NULL || request->width == 0 || request->height == 0) {
@@ -828,7 +828,7 @@ esp_err_t platform_direct_printer_print(const platform_direct_print_request_t *r
}
if (!s_state.initialized || s_state.lock == NULL) {
write_err(err, err_len, "direct backend not initialized");
write_err(err, err_len, "printer driver not initialized");
return ESP_ERR_INVALID_STATE;
}
@@ -838,13 +838,13 @@ esp_err_t platform_direct_printer_print(const platform_direct_print_request_t *r
}
if (xSemaphoreTake(s_state.lock, pdMS_TO_TICKS(1000)) != pdTRUE) {
write_err(err, err_len, "direct printer lock timeout");
write_err(err, err_len, "printer lock timeout");
return ESP_ERR_TIMEOUT;
}
if (!s_state.connected) {
xSemaphoreGive(s_state.lock);
write_err(err, err_len, "direct printer not connected");
write_err(err, err_len, "printer not connected");
return ESP_ERR_INVALID_STATE;
}
@@ -852,7 +852,7 @@ esp_err_t platform_direct_printer_print(const platform_direct_print_request_t *r
if (rc != ESP_OK) {
safe_drive_off_locked(true);
xSemaphoreGive(s_state.lock);
write_err(err, err_len, "direct printer gpio setup failed");
write_err(err, err_len, "printer gpio setup failed");
return rc;
}
@@ -949,11 +949,11 @@ esp_err_t platform_direct_printer_print(const platform_direct_print_request_t *r
esp_err_t platform_direct_printer_gap_move(uint32_t timeout_ms, char *err, size_t err_len) {
#if !CONFIG_TQ_DIRECT_PRINTER_ENABLE
write_err(err, err_len, "direct backend disabled");
write_err(err, err_len, "printer driver disabled");
return ESP_ERR_NOT_SUPPORTED;
#else
if (!s_state.initialized || s_state.lock == NULL) {
write_err(err, err_len, "direct backend not initialized");
write_err(err, err_len, "printer driver not initialized");
return ESP_ERR_INVALID_STATE;
}
if (timeout_ms == 0) {
@@ -961,12 +961,12 @@ esp_err_t platform_direct_printer_gap_move(uint32_t timeout_ms, char *err, size_
}
if (xSemaphoreTake(s_state.lock, pdMS_TO_TICKS(1000)) != pdTRUE) {
write_err(err, err_len, "direct printer lock timeout");
write_err(err, err_len, "printer lock timeout");
return ESP_ERR_TIMEOUT;
}
if (!s_state.connected) {
xSemaphoreGive(s_state.lock);
write_err(err, err_len, "direct printer not connected");
write_err(err, err_len, "printer not connected");
return ESP_ERR_INVALID_STATE;
}

View File

@@ -29,8 +29,6 @@ static const char *const s_counter_names[RUNTIME_DIAG_COUNTER_MAX] = {
"image_generate_success",
"image_generate_failed",
"image_generate_timeout",
"rest_responses_total",
"rest_errors_total",
};
static const char *const s_gauge_names[RUNTIME_DIAG_GAUGE_MAX] = {

View File

@@ -106,16 +106,8 @@
#define CONFIG_TQ_DIRECT_PRINTER_NTC_BETA 3950
#endif
#ifndef CONFIG_TQ_REST_PRINTER_CONNECT_TIMEOUT_MS
#define CONFIG_TQ_REST_PRINTER_CONNECT_TIMEOUT_MS 15000
#endif
#ifndef CONFIG_TQ_REST_LABEL_TIMEOUT_MS
#define CONFIG_TQ_REST_LABEL_TIMEOUT_MS 5000
#endif
#ifndef CONFIG_TQ_REST_OTA_STEP_TIMEOUT_MS
#define CONFIG_TQ_REST_OTA_STEP_TIMEOUT_MS 5000
#ifndef CONFIG_TQ_PRINTER_CONNECT_TIMEOUT_MS
#define CONFIG_TQ_PRINTER_CONNECT_TIMEOUT_MS 15000
#endif
#ifndef CONFIG_TQ_Z_IMAGE_TIMEOUT_MS
@@ -274,16 +266,8 @@ uint32_t runtime_policy_direct_printer_ntc_beta(void) {
return clamp_u32(CONFIG_TQ_DIRECT_PRINTER_NTC_BETA, 1000, 10000);
}
uint32_t runtime_policy_rest_printer_connect_timeout_ms(void) {
return clamp_u32(CONFIG_TQ_REST_PRINTER_CONNECT_TIMEOUT_MS, 1000, 60000);
}
uint32_t runtime_policy_rest_label_timeout_ms(void) {
return clamp_u32(CONFIG_TQ_REST_LABEL_TIMEOUT_MS, 500, 30000);
}
uint32_t runtime_policy_rest_ota_timeout_ms(void) {
return clamp_u32(CONFIG_TQ_REST_OTA_STEP_TIMEOUT_MS, 500, 60000);
uint32_t runtime_policy_printer_connect_timeout_ms(void) {
return clamp_u32(CONFIG_TQ_PRINTER_CONNECT_TIMEOUT_MS, 1000, 60000);
}
uint32_t runtime_policy_image_generation_timeout_default_ms(void) {

View File

@@ -1,4 +1,4 @@
menu "TQ Controller Config"
menu "TQ Printer Config"
config TQ_WIFI_PROV_SOFTAP_SSID
string "Wi-Fi provisioning SoftAP SSID"
@@ -37,21 +37,11 @@ config TQ_LIFECYCLE_RETRY_BACKOFF_MS
range 100 10000
default 800
config TQ_REST_PRINTER_CONNECT_TIMEOUT_MS
int "REST printer connect timeout default (ms)"
config TQ_PRINTER_CONNECT_TIMEOUT_MS
int "Printer connect timeout (ms)"
range 1000 60000
default 15000
config TQ_REST_LABEL_TIMEOUT_MS
int "REST label/offset timeout default (ms)"
range 500 30000
default 5000
config TQ_REST_OTA_STEP_TIMEOUT_MS
int "REST OTA step timeout default (ms)"
range 500 60000
default 5000
config TQ_PRINTER_CONTROL_LOCK_TIMEOUT_MS
int "Printer control lane lock timeout (ms)"
range 100 5000
@@ -78,106 +68,106 @@ config TQ_PRINTER_STOP_TIMEOUT_MS
default 8000
config TQ_DIRECT_PRINTER_ENABLE
bool "Enable direct thermal printer backend"
bool "Enable thermal printer driver"
default y
config TQ_DIRECT_PRINTER_OPERATION_TIMEOUT_MS
int "Direct printer max operation timeout (ms)"
int "Printer max operation timeout (ms)"
range 1000 300000
default 90000
depends on TQ_DIRECT_PRINTER_ENABLE
config TQ_DIRECT_PRINTER_STROBE_ON_US
int "Direct printer strobe on-time (us)"
int "Printer strobe on-time (us)"
range 100 10000
default 1000
depends on TQ_DIRECT_PRINTER_ENABLE
config TQ_DIRECT_PRINTER_STROBE_INTERVAL_US
int "Direct printer strobe interval (us)"
int "Printer strobe interval (us)"
range 0 10000
default 200
depends on TQ_DIRECT_PRINTER_ENABLE
config TQ_DIRECT_PRINTER_MOTOR_STEP_US
int "Direct printer motor step delay (us)"
int "Printer motor step delay (us)"
range 100 20000
default 2000
depends on TQ_DIRECT_PRINTER_ENABLE
config TQ_DIRECT_PRINTER_MOTOR_REVERSE
bool "Direct printer motor direction reversed"
bool "Printer motor direction reversed"
default n
depends on TQ_DIRECT_PRINTER_ENABLE
config TQ_DIRECT_PRINTER_STEPS_PER_LINE
int "Direct printer motor steps per printed line"
int "Printer motor steps per printed line"
range 1 8
default 2
depends on TQ_DIRECT_PRINTER_ENABLE
config TQ_DIRECT_PRINTER_GAP_STEPS
int "Direct printer gap move steps"
int "Printer gap move steps"
range 1 2000
default 96
depends on TQ_DIRECT_PRINTER_ENABLE
config TQ_DIRECT_PRINTER_TEMP_MIN_C
int "Direct printer allowed minimum temperature (C)"
int "Printer allowed minimum temperature (C)"
range 0 120
default 15
depends on TQ_DIRECT_PRINTER_ENABLE
config TQ_DIRECT_PRINTER_TEMP_MAX_C
int "Direct printer allowed maximum temperature (C)"
int "Printer allowed maximum temperature (C)"
range 1 150
default 55
depends on TQ_DIRECT_PRINTER_ENABLE
config TQ_DIRECT_PRINTER_BATTERY_MIN_PERCENT
int "Direct printer minimum battery percent"
int "Printer minimum battery percent"
range 0 100
default 5
depends on TQ_DIRECT_PRINTER_ENABLE
config TQ_DIRECT_PRINTER_PAPER_PRESENT_LEVEL
int "Direct printer paper-present GPIO level (0/1)"
int "Printer paper-present GPIO level (0/1)"
range 0 1
default 0
depends on TQ_DIRECT_PRINTER_ENABLE
config TQ_DIRECT_PRINTER_BATTERY_EMPTY_MV
int "Direct printer battery empty voltage (mV)"
int "Printer battery empty voltage (mV)"
range 2500 5000
default 3300
depends on TQ_DIRECT_PRINTER_ENABLE
config TQ_DIRECT_PRINTER_BATTERY_FULL_MV
int "Direct printer battery full voltage (mV)"
int "Printer battery full voltage (mV)"
range 2600 6000
default 4200
depends on TQ_DIRECT_PRINTER_ENABLE
config TQ_DIRECT_PRINTER_BATTERY_DIVIDER_RATIO_X1000
int "Direct printer battery divider ratio x1000"
int "Printer battery divider ratio x1000"
range 1000 10000
default 2000
depends on TQ_DIRECT_PRINTER_ENABLE
config TQ_DIRECT_PRINTER_NTC_PULLUP_OHMS
int "Direct printer NTC pull-up resistor (ohms)"
int "Printer NTC pull-up resistor (ohms)"
range 1000 200000
default 10000
depends on TQ_DIRECT_PRINTER_ENABLE
config TQ_DIRECT_PRINTER_NTC_R25_OHMS
int "Direct printer NTC R25 resistance (ohms)"
int "Printer NTC R25 resistance (ohms)"
range 1000 200000
default 10000
depends on TQ_DIRECT_PRINTER_ENABLE
config TQ_DIRECT_PRINTER_NTC_BETA
int "Direct printer NTC beta constant"
int "Printer NTC beta constant"
range 1000 10000
default 3950
depends on TQ_DIRECT_PRINTER_ENABLE