From 9deeab738e7066a506f92e7c2cdbac608a872149 Mon Sep 17 00:00:00 2001 From: admin Date: Sat, 28 Feb 2026 22:35:08 +0800 Subject: [PATCH] refactor(printer): remove BLE backend and dependencies --- README.md | 28 +- .../control_plane/src/rest_server_ops.c | 19 +- components/domain/include/domain.h | 5 +- .../internal/printer_protocol_internal.h | 55 +- components/domain/src/printer_protocol.c | 483 ++---------- .../domain/src/printer_protocol_commands.c | 347 +-------- .../domain/src/printer_protocol_worker.c | 213 +----- components/platform/CMakeLists.txt | 3 - components/platform/README.md | 2 +- components/platform/include/platform.h | 18 - components/platform/src/ble_printer_client.c | 706 ------------------ components/platform/src/runtime_policy.c | 8 - main/Kconfig.projbuild | 5 - sdkconfig.defaults | 6 +- 14 files changed, 115 insertions(+), 1783 deletions(-) delete mode 100644 components/platform/src/ble_printer_client.c diff --git a/README.md b/README.md index 1d68011..93f31d7 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,13 @@ ESP32-S3 works as a Wi-Fi REST controller and replaces Android App logic: - REST client -> ESP32-S3 (`esp_http_server`) -- ESP32-S3 -> BLE printer (`TQPrinter` / `lyfPrinter`, `FFF2` write / `FFF1` notify) -- Command compatibility: - - Print path: `0x00~0x07` - - OTA path: `0xA0~0xA4` +- ESP32-S3 -> onboard direct thermal printer driver ## Features - Wi-Fi STA-only mode (configured SSID/password; no SoftAP fallback) - Built-in minimal web UI at `/` for voice tap2talk -- BLE central client auto-scan/connect to printer name +- Direct thermal printer control with sensor precheck - Async print queue with jobs (`queued/running/success/failed/canceled`) - Printer precheck (paper / battery / temperature) - Built-in UTF-8 text rendering with Chinese support (GB2312 character set, 16x16 bitmap) @@ -19,12 +16,6 @@ ESP32-S3 works as a Wi-Fi REST controller and replaces Android App logic: - ES8311 microphone/speaker via `esp_codec_dev` - raw-opus uplink/downlink via `esp_audio_codec` - WebSocket transport via `esp_websocket_client` -- Android-compatible print flow: - - `0x00` power on - - `0x03` set print param - - `0x04` chunked raster send + ACK - - `0x00` power off - - `0x02` feed paper - REST APIs: - Root: - `GET /` @@ -148,17 +139,9 @@ curl http:///v1/health ```bash curl -X POST http:///v1/printer/connect \ -H 'Content-Type: application/json' \ - -d '{"name":"TQPrinter","timeout_ms":15000}' -# Legacy device name is also supported: -# -d '{"name":"lyfPrinter","timeout_ms":15000}' -``` - -Auto-match a compatible printer (by BLE service `0xFFF0`): - -```bash -curl -X POST http:///v1/printer/connect \ - -H 'Content-Type: application/json' \ - -d '{"name":"*","timeout_ms":20000}' + -d '{"timeout_ms":15000}' +# Optional explicit backend field: +# -d '{"backend":"direct","timeout_ms":15000}' ``` ### Raster print @@ -255,7 +238,6 @@ curl -X POST http:///v1/voice/session/stop ## Notes -- BLE side is central/client role, not printer peripheral role. - `base64_msb_1bpp` uses Android-compatible bit order (MSB first). - `/v1/print/image` supports two modes: JSON prompt generation (DashScope Z-Image) and raw `image/png` upload (no base64 wrapper). - `/v1/print/text` supports UTF-8 Chinese via embedded 16x16 GB2312 glyphs. diff --git a/components/control_plane/src/rest_server_ops.c b/components/control_plane/src/rest_server_ops.c index 7678c96..9b567d1 100644 --- a/components/control_plane/src/rest_server_ops.c +++ b/components/control_plane/src/rest_server_ops.c @@ -9,8 +9,6 @@ static const char *printer_backend_str(printer_backend_t backend) { switch (backend) { - case PRINTER_BACKEND_BLE: - return "ble"; case PRINTER_BACKEND_DIRECT: return "direct"; default: @@ -26,10 +24,6 @@ static bool parse_printer_backend(const cJSON *json, printer_backend_t *out_back if (!cJSON_IsString(jbackend) || jbackend->valuestring == NULL) { return false; } - if (strcasecmp(jbackend->valuestring, "ble") == 0) { - *out_backend = PRINTER_BACKEND_BLE; - return true; - } if (strcasecmp(jbackend->valuestring, "direct") == 0) { *out_backend = PRINTER_BACKEND_DIRECT; return true; @@ -87,8 +81,6 @@ static void fill_runtime_json(cJSON *root) { cJSON_AddStringToObject(root, "printer_backend", printer_backend_str(st.backend)); cJSON_AddBoolToObject(root, "printer_connected", st.connected); cJSON_AddBoolToObject(root, "printer_transport_ready", st.transport_ready); - cJSON_AddBoolToObject(root, "ble_connected", st.backend == PRINTER_BACKEND_BLE && st.connected); - cJSON_AddBoolToObject(root, "ble_notify_ready", st.backend == PRINTER_BACKEND_BLE && st.notify_ready); cJSON_AddBoolToObject(root, "printer_busy", st.busy); cJSON_AddBoolToObject(root, "has_paper", st.has_paper); cJSON_AddNumberToObject(root, "paper_gpio_level", st.paper_gpio_level); @@ -99,7 +91,6 @@ static void fill_runtime_json(cJSON *root) { cJSON_AddBoolToObject(root, "supports_label_offset", st.supports_label_offset); cJSON_AddBoolToObject(root, "supports_ota", st.supports_ota); cJSON_AddNumberToObject(root, "queue_depth", st.queue_depth); - cJSON_AddNumberToObject(root, "mtu", st.mtu); cJSON_AddNumberToObject(root, "last_status_ms", (double)st.last_status_ms); voice_interaction_status_t voice = {0}; @@ -153,7 +144,6 @@ esp_err_t rest_server_connect_post(httpd_req_t *req) { } char *body = NULL; - char name[32] = "TQPrinter"; uint32_t timeout_ms = domain_policy_rest_printer_connect_timeout_ms(); printer_backend_t backend = printer_protocol_get_backend(); bool backend_specified = false; @@ -170,11 +160,6 @@ esp_err_t rest_server_connect_post(httpd_req_t *req) { return rest_server_send_error(req, "400 Bad Request", "invalid json"); } - cJSON *jname = cJSON_GetObjectItemCaseSensitive(json, "name"); - if (cJSON_IsString(jname) && jname->valuestring != NULL) { - strlcpy(name, jname->valuestring, sizeof(name)); - } - cJSON *jtimeout = cJSON_GetObjectItemCaseSensitive(json, "timeout_ms"); if (cJSON_IsNumber(jtimeout)) { uint32_t min_ms = domain_policy_rest_printer_connect_timeout_min_ms(); @@ -194,7 +179,7 @@ esp_err_t rest_server_connect_post(httpd_req_t *req) { if (!parse_printer_backend(json, &backend)) { cJSON_Delete(json); free(body); - return rest_server_send_error(req, "400 Bad Request", "backend must be ble or direct"); + return rest_server_send_error(req, "400 Bad Request", "backend must be direct"); } } @@ -204,7 +189,7 @@ esp_err_t rest_server_connect_post(httpd_req_t *req) { printer_connect_options_t opt = { .backend = backend, - .name = backend == PRINTER_BACKEND_BLE ? name : NULL, + .name = NULL, .timeout_ms = timeout_ms, }; char connect_err[96] = {0}; diff --git a/components/domain/include/domain.h b/components/domain/include/domain.h index ed79e28..6241f25 100644 --- a/components/domain/include/domain.h +++ b/components/domain/include/domain.h @@ -219,8 +219,7 @@ typedef struct { } printer_ota_version_t; typedef enum { - PRINTER_BACKEND_BLE = 0, - PRINTER_BACKEND_DIRECT = 1, + PRINTER_BACKEND_DIRECT = 0, } printer_backend_t; typedef struct { @@ -257,14 +256,12 @@ typedef struct { printer_backend_t backend; bool connected; bool transport_ready; - bool notify_ready; bool busy; bool has_paper; int8_t paper_gpio_level; uint8_t paper_present_level; uint8_t battery_percent; float temperature; - uint16_t mtu; bool supports_gap_move; bool supports_label_offset; bool supports_ota; diff --git a/components/domain/internal/printer_protocol_internal.h b/components/domain/internal/printer_protocol_internal.h index 211d765..3dbe71c 100644 --- a/components/domain/internal/printer_protocol_internal.h +++ b/components/domain/internal/printer_protocol_internal.h @@ -13,26 +13,9 @@ #include "freertos/semphr.h" #include "freertos/task.h" -#define PROTO_ADDR 0x01 - -#define CMD_POWER 0x00 -#define CMD_GET_STATUS 0x01 -#define CMD_SET_DISTANCE 0x02 -#define CMD_SET_PARAM 0x03 -#define CMD_SEND_DATA 0x04 -#define CMD_GAP_MOVE 0x05 -#define CMD_GET_OFFSET 0x06 -#define CMD_SET_OFFSET 0x07 -#define CMD_BOOT_JUMP_BOOT 0xA0 -#define CMD_BOOT_ERASE_PAGE 0xA1 -#define CMD_BOOT_WRITE_DATA 0xA2 -#define CMD_BOOT_JUMP_APP 0xA3 -#define CMD_BOOT_GET_VERSION 0xA4 - -#define EVT_ACK BIT0 -#define EVT_SHUTDOWN BIT1 -#define EVT_WORKER_EXITED BIT2 -#define EVT_STATUS_POLL_EXITED BIT3 +#define EVT_SHUTDOWN BIT0 +#define EVT_WORKER_EXITED BIT1 +#define EVT_STATUS_POLL_EXITED BIT2 #define JOB_QUEUE_LEN 8 #define JOB_SLOT_MAX 16 @@ -40,8 +23,6 @@ #define STATUS_POLL_PAUSE_SLOT_MAX 8 #define PRINTER_JOB_SENTINEL_STOP 0u -#define OTA_MAX_DATA_PER_FRAME 236u - typedef struct { bool used; bool cancel_requested; @@ -74,9 +55,6 @@ extern QueueHandle_t s_job_queue; extern EventGroupHandle_t s_evt; extern uint32_t s_busy_refcnt; extern parsed_status_t s_status; -extern uint8_t s_last_rsp_cmd; -extern uint16_t s_last_rsp_payload_len; -extern uint8_t s_last_rsp_payload[252]; extern uint32_t s_status_poll_pause_next_token; extern uint32_t s_status_poll_pause_tokens[STATUS_POLL_PAUSE_SLOT_MAX]; extern uint32_t s_next_job_id; @@ -88,33 +66,6 @@ extern bool s_protocol_stopping; bool printer_protocol_acquire_control_lane(uint32_t timeout_ms, char *err, size_t err_len); void printer_protocol_release_control_lane(void); -esp_err_t printer_protocol_send_cmd_wait_response(uint8_t cmd, - const uint8_t *payload, - uint16_t payload_len, - bool with_checksum, - uint32_t timeout_ms, - bool expect_ack, - bool reset_transport_on_timeout, - uint8_t *out_payload, - size_t out_payload_cap, - uint16_t *out_payload_len, - char *err, - size_t err_len); -esp_err_t printer_protocol_send_frame(uint8_t cmd, - const uint8_t *payload, - uint16_t payload_len, - bool with_checksum); -bool printer_protocol_wait_response(uint8_t cmd, - uint8_t *out_payload, - size_t out_payload_cap, - uint16_t *out_payload_len, - uint32_t timeout_ms); -bool printer_protocol_send_cmd_with_ack(uint8_t cmd, - const uint8_t *payload, - uint16_t payload_len, - bool with_checksum, - uint32_t timeout_ms, - bool reset_transport_on_timeout); int printer_protocol_find_job_idx_locked(uint32_t id); int printer_protocol_alloc_job_slot_locked(void); diff --git a/components/domain/src/printer_protocol.c b/components/domain/src/printer_protocol.c index 0bc499d..5d069ea 100644 --- a/components/domain/src/printer_protocol.c +++ b/components/domain/src/printer_protocol.c @@ -28,18 +28,13 @@ parsed_status_t s_status = { .updated_ms = 0, }; -uint8_t s_last_rsp_cmd; -uint16_t s_last_rsp_payload_len; -uint8_t s_last_rsp_payload[252]; - uint32_t s_next_job_id = 1; job_slot_t s_jobs[JOB_SLOT_MAX]; 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_BLE; -bool s_ble_client_initialized; +printer_backend_t s_backend = PRINTER_BACKEND_DIRECT; static const char *TAG = "printer_protocol"; @@ -49,14 +44,8 @@ static const char *TAG = "printer_protocol"; #define PRINT_WORKER_CORE_ID 1 #endif -static void on_rx_frame(const uint8_t *data, size_t len); - static printer_backend_t default_backend_on_startup(void) { - // This hardware has a first-class direct path; BLE remains opt-in via API. - if (runtime_policy_direct_printer_enabled()) { - return PRINTER_BACKEND_DIRECT; - } - return PRINTER_BACKEND_BLE; + return PRINTER_BACKEND_DIRECT; } static void backend_capabilities_for(printer_backend_t backend, printer_capabilities_t *out_caps) { @@ -64,43 +53,23 @@ static void backend_capabilities_for(printer_backend_t backend, printer_capabili return; } memset(out_caps, 0, sizeof(*out_caps)); - out_caps->supports_connect = true; - out_caps->supports_gap_move = true; - if (backend == PRINTER_BACKEND_BLE) { - out_caps->supports_label_offset = true; - out_caps->supports_ota = true; - } -} - -static esp_err_t ensure_ble_client_ready(void) { - if (s_ble_client_initialized) { - return ESP_OK; - } - esp_err_t err = ble_printer_client_init(on_rx_frame); - if (err == ESP_OK) { - s_ble_client_initialized = true; - } - return err; + 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_BLE) { - return ensure_ble_client_ready(); + if (backend != PRINTER_BACKEND_DIRECT) { + return ESP_ERR_NOT_SUPPORTED; } - if (backend == PRINTER_BACKEND_DIRECT) { - if (!runtime_policy_direct_printer_enabled()) { - return ESP_ERR_NOT_SUPPORTED; - } - return platform_direct_printer_init(); + if (!runtime_policy_direct_printer_enabled()) { + return ESP_ERR_NOT_SUPPORTED; } - return ESP_ERR_NOT_SUPPORTED; + return platform_direct_printer_init(); } static void refresh_direct_status_locked(void) { - if (s_backend != PRINTER_BACKEND_DIRECT) { - return; - } - platform_printer_sensors_t sensors = {0}; if (platform_direct_printer_get_sensors(&sensors) == ESP_OK) { s_status.has_paper = sensors.has_paper; @@ -136,9 +105,6 @@ static void reset_jobs_locked(void) { static void reset_runtime_state_locked(void) { s_busy_refcnt = 0; - s_last_rsp_cmd = 0; - s_last_rsp_payload_len = 0; - memset(s_last_rsp_payload, 0, sizeof(s_last_rsp_payload)); status_poll_pause_slots_clear_locked(); s_status_poll_pause_next_token = 1; @@ -314,232 +280,16 @@ void printer_protocol_release_control_lane(void) { xSemaphoreGive(s_mutex); } -static uint8_t checksum8(const uint8_t *data, size_t len) { - uint32_t sum = 0; - for (size_t i = 0; i < len; ++i) { - sum += data[i]; - } - return (uint8_t)(sum & 0xFF); -} - -esp_err_t printer_protocol_send_frame(uint8_t cmd, - const uint8_t *payload, - uint16_t payload_len, - bool with_checksum) { - if (!s_protocol_initialized || printer_protocol_is_stopping()) { - return ESP_ERR_INVALID_STATE; - } - if (s_backend != PRINTER_BACKEND_BLE) { - return ESP_ERR_NOT_SUPPORTED; - } - - uint8_t frame[260]; - size_t total = 4 + payload_len + (with_checksum ? 1 : 0); - if (total > sizeof(frame)) { - return ESP_ERR_INVALID_SIZE; - } - - frame[0] = PROTO_ADDR; - frame[1] = cmd; - frame[2] = (uint8_t)((payload_len >> 8) & 0xFF); - frame[3] = (uint8_t)(payload_len & 0xFF); - - if (payload_len > 0 && payload != NULL) { - memcpy(&frame[4], payload, payload_len); - } - - if (with_checksum) { - frame[4 + payload_len] = checksum8(frame, 4 + payload_len); - } - - return ble_printer_client_write(frame, total); -} - -static void clear_ack_signal(void) { - if (s_evt != NULL) { - xEventGroupClearBits(s_evt, EVT_ACK); - } -} - -bool printer_protocol_wait_response(uint8_t cmd, - uint8_t *out_payload, - size_t out_payload_cap, - uint16_t *out_payload_len, - uint32_t timeout_ms) { - if (timeout_ms == 0 || s_evt == NULL) { - return false; - } - - int64_t deadline = esp_timer_get_time() / 1000 + timeout_ms; - - while (true) { - if (printer_protocol_is_stopping()) { - return false; - } - - int64_t now = esp_timer_get_time() / 1000; - if (now >= deadline) { - return false; - } - - uint32_t wait_ms = (uint32_t)(deadline - now); - if (wait_ms > 100) { - wait_ms = 100; - } - - EventBits_t bits = xEventGroupWaitBits(s_evt, - EVT_ACK | EVT_SHUTDOWN, - pdFALSE, - pdFALSE, - pdMS_TO_TICKS(wait_ms)); - if (bits & EVT_SHUTDOWN) { - return false; - } - - if (!(bits & EVT_ACK)) { - continue; - } - xEventGroupClearBits(s_evt, EVT_ACK); - - if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(200)) != pdTRUE) { - continue; - } - - uint8_t rsp_cmd = s_last_rsp_cmd; - uint16_t rsp_len = s_last_rsp_payload_len; - uint8_t rsp_copy[sizeof(s_last_rsp_payload)]; - if (rsp_len > sizeof(rsp_copy)) { - rsp_len = sizeof(rsp_copy); - } - if (rsp_len > 0) { - memcpy(rsp_copy, s_last_rsp_payload, rsp_len); - } - xSemaphoreGive(s_mutex); - - if (rsp_cmd == cmd) { - if (out_payload != NULL && out_payload_cap > 0 && rsp_len > 0) { - size_t copy_len = rsp_len; - if (copy_len > out_payload_cap) { - copy_len = out_payload_cap; - } - memcpy(out_payload, rsp_copy, copy_len); - } - if (out_payload_len != NULL) { - *out_payload_len = rsp_len; - } - return true; - } - } -} - -static bool wait_ack(uint8_t cmd, uint32_t timeout_ms) { - uint8_t payload[252]; - uint16_t payload_len = 0; - if (!printer_protocol_wait_response(cmd, payload, sizeof(payload), &payload_len, timeout_ms)) { - return false; - } - return payload_len >= 1 && payload[0] == 0x01; -} - -static void reset_transport_after_timeout(void) { - if (printer_protocol_is_stopping()) { - return; - } - if (printer_protocol_get_backend() == PRINTER_BACKEND_BLE) { - ble_printer_client_disconnect(); - } -} - -bool printer_protocol_send_cmd_with_ack(uint8_t cmd, - const uint8_t *payload, - uint16_t payload_len, - bool with_checksum, - uint32_t timeout_ms, - bool reset_transport_on_timeout) { - clear_ack_signal(); - if (printer_protocol_send_frame(cmd, payload, payload_len, with_checksum) != ESP_OK) { - return false; - } - bool ok = wait_ack(cmd, timeout_ms); - if (!ok && reset_transport_on_timeout) { - reset_transport_after_timeout(); - } - return ok; -} - -esp_err_t printer_protocol_send_cmd_wait_response(uint8_t cmd, - const uint8_t *payload, - uint16_t payload_len, - bool with_checksum, - uint32_t timeout_ms, - bool expect_ack, - bool reset_transport_on_timeout, - uint8_t *out_payload, - size_t out_payload_cap, - uint16_t *out_payload_len, - char *err, - size_t err_len) { - clear_ack_signal(); - if (printer_protocol_send_frame(cmd, payload, payload_len, with_checksum) != ESP_OK) { - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "send frame failed"); - } - return ESP_FAIL; - } - - uint8_t rsp[252]; - uint16_t rsp_len = 0; - if (!printer_protocol_wait_response(cmd, rsp, sizeof(rsp), &rsp_len, timeout_ms)) { - bool stopping = printer_protocol_is_stopping(); - if (!stopping && reset_transport_on_timeout) { - reset_transport_after_timeout(); - } - if (err != NULL && err_len > 0) { - if (stopping) { - snprintf(err, err_len, "protocol stopping"); - } else { - snprintf(err, - err_len, - reset_transport_on_timeout ? "response timeout, transport reset" - : "response timeout"); - } - } - return stopping ? ESP_ERR_INVALID_STATE : ESP_ERR_TIMEOUT; - } - - if (expect_ack && (rsp_len < 1 || rsp[0] != 0x01)) { - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "cmd 0x%02X rejected", cmd); - } - return ESP_FAIL; - } - - if (out_payload != NULL && out_payload_cap > 0 && rsp_len > 0) { - size_t copy_len = rsp_len; - if (copy_len > out_payload_cap) { - copy_len = out_payload_cap; - } - memcpy(out_payload, rsp, copy_len); - } - if (out_payload_len != NULL) { - *out_payload_len = rsp_len; - } - - return ESP_OK; -} - static void status_poll_task(void *arg) { (void)arg; while (true) { bool should_stop = false; bool can_poll = false; - printer_backend_t backend = PRINTER_BACKEND_BLE; if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(50)) == pdTRUE) { should_stop = s_protocol_stopping; can_poll = (s_busy_refcnt == 0) && (status_poll_pause_depth_locked() == 0); - backend = s_backend; xSemaphoreGive(s_mutex); } @@ -547,20 +297,12 @@ static void status_poll_task(void *arg) { break; } - if (can_poll) { - if (backend == PRINTER_BACKEND_BLE) { - if (ble_printer_client_is_connected()) { - uint8_t dummy = 0x00; - (void)printer_protocol_send_frame(CMD_GET_STATUS, &dummy, 0, true); - } - } else if (backend == PRINTER_BACKEND_DIRECT) { - if (platform_direct_printer_is_connected() && - xSemaphoreTake(s_mutex, pdMS_TO_TICKS(100)) == pdTRUE) { - refresh_direct_status_locked(); - xSemaphoreGive(s_mutex); - } - } + if (can_poll && platform_direct_printer_is_connected() && + xSemaphoreTake(s_mutex, pdMS_TO_TICKS(100)) == pdTRUE) { + refresh_direct_status_locked(); + xSemaphoreGive(s_mutex); } + vTaskDelay(pdMS_TO_TICKS(runtime_policy_printer_status_poll_interval_ms())); } @@ -571,59 +313,6 @@ static void status_poll_task(void *arg) { vTaskDelete(NULL); } -static void on_rx_frame(const uint8_t *data, size_t len) { - if (data == NULL || len < 4 || s_mutex == NULL) { - return; - } - - if (data[0] != PROTO_ADDR) { - return; - } - - uint8_t cmd = data[1]; - uint16_t payload_len = ((uint16_t)data[2] << 8) | data[3]; - size_t required = (size_t)payload_len + 4; - if (len < required) { - return; - } - - const uint8_t *payload = &data[4]; - - if (cmd == CMD_GET_STATUS && payload_len >= 5) { - bool has_paper = payload[0] != 0; - uint8_t battery = payload[1]; - int sign = (payload[2] == 0x2D) ? -1 : 1; - int temp_x10 = ((int)payload[3] << 8) | payload[4]; - float temperature = (float)(sign * temp_x10) / 10.0f; - - if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(100)) == pdTRUE) { - s_status.has_paper = has_paper; - s_status.paper_gpio_level = -1; - s_status.paper_present_level = 0; - s_status.battery = battery; - s_status.temperature = temperature; - s_status.updated_ms = esp_timer_get_time() / 1000; - xSemaphoreGive(s_mutex); - } - return; - } - - if (payload_len >= 1) { - if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(100)) == pdTRUE) { - s_last_rsp_cmd = cmd; - s_last_rsp_payload_len = payload_len; - if (s_last_rsp_payload_len > sizeof(s_last_rsp_payload)) { - s_last_rsp_payload_len = sizeof(s_last_rsp_payload); - } - memcpy(s_last_rsp_payload, payload, s_last_rsp_payload_len); - xSemaphoreGive(s_mutex); - } - if (s_evt != NULL) { - xEventGroupSetBits(s_evt, EVT_ACK); - } - } -} - static void destroy_runtime_objects(void) { if (s_job_queue != NULL) { vQueueDelete(s_job_queue); @@ -672,7 +361,6 @@ 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_ble_client_initialized = false; s_backend = default_backend_on_startup(); esp_err_t err = ensure_backend_ready(s_backend); @@ -682,24 +370,22 @@ esp_err_t printer_protocol_init(void) { return err; } - if (s_backend == PRINTER_BACKEND_DIRECT) { - uint32_t connect_timeout_ms = domain_policy_rest_printer_connect_timeout_ms(); - err = platform_direct_printer_connect(connect_timeout_ms); - if (err != ESP_OK) { - s_protocol_initialized = false; - platform_direct_printer_disconnect(); - platform_direct_printer_deinit(); - destroy_runtime_objects(); - return err; - } - - if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(200)) == pdTRUE) { - refresh_direct_status_locked(); - xSemaphoreGive(s_mutex); - } - ESP_LOGI(TAG, "direct printer auto connected at startup"); + uint32_t connect_timeout_ms = domain_policy_rest_printer_connect_timeout_ms(); + err = platform_direct_printer_connect(connect_timeout_ms); + if (err != ESP_OK) { + s_protocol_initialized = false; + platform_direct_printer_disconnect(); + platform_direct_printer_deinit(); + destroy_runtime_objects(); + return err; } + if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(200)) == pdTRUE) { + refresh_direct_status_locked(); + xSemaphoreGive(s_mutex); + } + ESP_LOGI(TAG, "direct printer auto connected at startup"); + BaseType_t ok = printer_create_task_prefer_psram(printer_protocol_worker_task, "print_worker", 6144, @@ -757,7 +443,6 @@ esp_err_t printer_protocol_stop(uint32_t timeout_ms) { (void)xQueueSend(s_job_queue, &sentinel, 0); } - ble_printer_client_disconnect(); platform_direct_printer_disconnect(); bool worker_done = (s_worker_task == NULL); @@ -795,14 +480,10 @@ esp_err_t printer_protocol_stop(uint32_t timeout_ms) { s_busy_refcnt = 0; s_status_poll_pause_next_token = 1; memset(s_status_poll_pause_tokens, 0, sizeof(s_status_poll_pause_tokens)); - memset(s_last_rsp_payload, 0, sizeof(s_last_rsp_payload)); - s_last_rsp_cmd = 0; - s_last_rsp_payload_len = 0; s_worker_task = NULL; s_status_poll_task_handle = NULL; s_protocol_initialized = false; s_protocol_stopping = false; - s_ble_client_initialized = false; s_backend = default_backend_on_startup(); runtime_diag_set_gauge(RUNTIME_DIAG_GAUGE_STATUS_POLL_PAUSE_DEPTH, 0); @@ -815,18 +496,20 @@ 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) { - if (backend != PRINTER_BACKEND_BLE && backend != PRINTER_BACKEND_DIRECT) { + if (backend != PRINTER_BACKEND_DIRECT) { if (err != NULL && err_len > 0) { - snprintf(err, err_len, "invalid backend"); + snprintf(err, err_len, "only direct backend is supported"); } - return ESP_ERR_INVALID_ARG; + return ESP_ERR_NOT_SUPPORTED; } - if (backend == PRINTER_BACKEND_DIRECT && !runtime_policy_direct_printer_enabled()) { + + 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"); @@ -841,12 +524,6 @@ esp_err_t printer_protocol_set_backend(printer_backend_t backend, char *err, siz return ESP_ERR_TIMEOUT; } - printer_backend_t old_backend = s_backend; - if (old_backend == backend) { - xSemaphoreGive(s_mutex); - return ESP_OK; - } - if (s_busy_refcnt != 0 || (s_job_queue != NULL && uxQueueMessagesWaiting(s_job_queue) > 0)) { xSemaphoreGive(s_mutex); if (err != NULL && err_len > 0) { @@ -855,26 +532,18 @@ esp_err_t printer_protocol_set_backend(printer_backend_t backend, char *err, siz return ESP_ERR_INVALID_STATE; } - s_backend = backend; + s_backend = PRINTER_BACKEND_DIRECT; xSemaphoreGive(s_mutex); - ble_printer_client_disconnect(); - platform_direct_printer_disconnect(); - - esp_err_t rc = ensure_backend_ready(backend); + esp_err_t rc = ensure_backend_ready(PRINTER_BACKEND_DIRECT); if (rc != ESP_OK) { - if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(200)) == pdTRUE) { - s_backend = old_backend; - xSemaphoreGive(s_mutex); - } - (void)ensure_backend_ready(old_backend); if (err != NULL && err_len > 0) { - snprintf(err, err_len, "backend init failed"); + snprintf(err, err_len, "direct backend unavailable"); } return rc; } - if (backend == PRINTER_BACKEND_DIRECT && xSemaphoreTake(s_mutex, pdMS_TO_TICKS(200)) == pdTRUE) { + if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(200)) == pdTRUE) { refresh_direct_status_locked(); xSemaphoreGive(s_mutex); } @@ -911,11 +580,9 @@ esp_err_t printer_protocol_connect_ex(const printer_connect_options_t *opt, char } printer_backend_t backend = printer_protocol_get_backend(); - const char *name = NULL; uint32_t timeout_ms = 0; if (opt != NULL) { backend = opt->backend; - name = opt->name; timeout_ms = opt->timeout_ms; } @@ -924,36 +591,23 @@ esp_err_t printer_protocol_connect_ex(const printer_connect_options_t *opt, char return rc; } - if (backend == PRINTER_BACKEND_BLE) { - rc = ensure_backend_ready(PRINTER_BACKEND_BLE); - if (rc != ESP_OK) { - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "ble backend unavailable"); - } - 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 ble_printer_client_connect(name, timeout_ms); + return rc; } - if (backend == PRINTER_BACKEND_DIRECT) { - 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; - } - return platform_direct_printer_connect(timeout_ms); + 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); } - - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "unsupported backend"); - } - return ESP_ERR_NOT_SUPPORTED; + return rc; } void printer_protocol_disconnect(void) { - ble_printer_client_disconnect(); platform_direct_printer_disconnect(); } @@ -979,31 +633,20 @@ void printer_protocol_get_runtime_status(printer_runtime_status_t *out_status) { out_status->supports_label_offset = caps.supports_label_offset; out_status->supports_ota = caps.supports_ota; - if (out_status->backend == PRINTER_BACKEND_BLE) { - ble_link_state_t link = {0}; - ble_printer_client_get_link_state(&link); - out_status->connected = link.connected; - out_status->notify_ready = link.notify_ready; - out_status->transport_ready = link.connected && link.notify_ready; - out_status->mtu = link.mtu; - } else if (out_status->backend == PRINTER_BACKEND_DIRECT) { - out_status->connected = platform_direct_printer_is_connected(); - out_status->transport_ready = out_status->connected; - out_status->notify_ready = false; - out_status->mtu = 0; + 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 && - s_mutex != NULL && - xSemaphoreTake(s_mutex, pdMS_TO_TICKS(100)) == pdTRUE) { - s_status.has_paper = sensors.has_paper; - s_status.paper_gpio_level = sensors.paper_gpio_level; - s_status.paper_present_level = sensors.paper_present_level; - s_status.battery = sensors.battery_percent; - s_status.temperature = sensors.temperature_c; - s_status.updated_ms = sensors.updated_ms; - xSemaphoreGive(s_mutex); - } + platform_printer_sensors_t sensors = {0}; + if (platform_direct_printer_get_sensors(&sensors) == ESP_OK && + s_mutex != NULL && + xSemaphoreTake(s_mutex, pdMS_TO_TICKS(100)) == pdTRUE) { + s_status.has_paper = sensors.has_paper; + s_status.paper_gpio_level = sensors.paper_gpio_level; + s_status.paper_present_level = sensors.paper_present_level; + s_status.battery = sensors.battery_percent; + s_status.temperature = sensors.temperature_c; + s_status.updated_ms = sensors.updated_ms; + xSemaphoreGive(s_mutex); } if (s_mutex != NULL && xSemaphoreTake(s_mutex, pdMS_TO_TICKS(200)) == pdTRUE) { diff --git a/components/domain/src/printer_protocol_commands.c b/components/domain/src/printer_protocol_commands.c index 924210c..b1477fe 100644 --- a/components/domain/src/printer_protocol_commands.c +++ b/components/domain/src/printer_protocol_commands.c @@ -2,18 +2,6 @@ #include "printer_protocol_internal.h" #include -#include - -static bool is_direct_backend(void) { - return printer_protocol_get_backend() == PRINTER_BACKEND_DIRECT; -} - -static esp_err_t unsupported_for_direct(char *err, size_t err_len, const char *op) { - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "%s not supported on direct backend", op); - } - return ESP_ERR_NOT_SUPPORTED; -} static void write_err(char *err, size_t err_len, const char *msg) { if (err != NULL && err_len > 0) { @@ -21,229 +9,47 @@ 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 (is_direct_backend()) { - return platform_direct_printer_gap_move(timeout_ms, err, err_len); + if (!runtime_policy_direct_printer_enabled()) { + write_err(err, err_len, "direct backend disabled"); + return ESP_ERR_NOT_SUPPORTED; } - - if (!ble_printer_client_is_connected()) { - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "printer not connected"); - } - return ESP_ERR_INVALID_STATE; - } - - if (!printer_protocol_acquire_control_lane(runtime_policy_printer_control_lock_timeout_ms(), err, err_len)) { - return ESP_ERR_INVALID_STATE; - } - - uint8_t payload = 0x01; - esp_err_t rc = printer_protocol_send_cmd_wait_response(CMD_GAP_MOVE, - &payload, - 1, - true, - timeout_ms, - true, - true, - NULL, - 0, - NULL, - err, - err_len); - printer_protocol_release_control_lane(); - return rc; + 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) { - if (is_direct_backend()) { - return unsupported_for_direct(err, err_len, "label offset"); - } - - if (out_offset == NULL) { - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "invalid args"); - } - return ESP_ERR_INVALID_ARG; - } - - if (!ble_printer_client_is_connected()) { - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "printer not connected"); - } - return ESP_ERR_INVALID_STATE; - } - - if (!printer_protocol_acquire_control_lane(runtime_policy_printer_control_lock_timeout_ms(), err, err_len)) { - return ESP_ERR_INVALID_STATE; - } - - uint8_t req = 0x01; - uint8_t rsp[16]; - uint16_t rsp_len = 0; - esp_err_t rc = printer_protocol_send_cmd_wait_response(CMD_GET_OFFSET, - &req, - 1, - true, - timeout_ms, - false, - false, - rsp, - sizeof(rsp), - &rsp_len, - err, - err_len); - printer_protocol_release_control_lane(); - if (rc != ESP_OK) { - return rc; - } - if (rsp_len < 1) { - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "invalid offset response"); - } - return ESP_FAIL; - } - if (rsp[0] == 0xFF) { - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "offset unavailable"); - } - return ESP_FAIL; - } - - *out_offset = rsp[0]; - return ESP_OK; + (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) { - if (is_direct_backend()) { - return unsupported_for_direct(err, err_len, "label offset"); - } - - if (!ble_printer_client_is_connected()) { - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "printer not connected"); - } - return ESP_ERR_INVALID_STATE; - } - - if (!printer_protocol_acquire_control_lane(runtime_policy_printer_control_lock_timeout_ms(), err, err_len)) { - return ESP_ERR_INVALID_STATE; - } - - esp_err_t rc = printer_protocol_send_cmd_wait_response(CMD_SET_OFFSET, - &offset, - 1, - true, - timeout_ms, - true, - true, - NULL, - 0, - NULL, - err, - err_len); - printer_protocol_release_control_lane(); - return rc; + (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) { - if (is_direct_backend()) { - return unsupported_for_direct(err, err_len, "ota jump boot"); - } - - if (!ble_printer_client_is_connected()) { - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "printer not connected"); - } - return ESP_ERR_INVALID_STATE; - } - - if (!printer_protocol_acquire_control_lane(runtime_policy_printer_control_lock_timeout_ms(), err, err_len)) { - return ESP_ERR_INVALID_STATE; - } - - esp_err_t rc = printer_protocol_send_cmd_wait_response(CMD_BOOT_JUMP_BOOT, - NULL, - 0, - true, - timeout_ms, - true, - true, - NULL, - 0, - NULL, - err, - err_len); - printer_protocol_release_control_lane(); - return rc; + (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) { - if (is_direct_backend()) { - return unsupported_for_direct(err, err_len, "ota jump app"); - } - - if (!ble_printer_client_is_connected()) { - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "printer not connected"); - } - return ESP_ERR_INVALID_STATE; - } - - if (!printer_protocol_acquire_control_lane(runtime_policy_printer_control_lock_timeout_ms(), err, err_len)) { - return ESP_ERR_INVALID_STATE; - } - - esp_err_t rc = printer_protocol_send_cmd_wait_response(CMD_BOOT_JUMP_APP, - NULL, - 0, - true, - timeout_ms, - true, - true, - NULL, - 0, - NULL, - err, - err_len); - printer_protocol_release_control_lane(); - return rc; + (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) { - if (is_direct_backend()) { - return unsupported_for_direct(err, err_len, "ota erase"); - } - - if (!ble_printer_client_is_connected()) { - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "printer not connected"); - } - return ESP_ERR_INVALID_STATE; - } - - if (!printer_protocol_acquire_control_lane(runtime_policy_printer_control_lock_timeout_ms(), err, err_len)) { - return ESP_ERR_INVALID_STATE; - } - - uint8_t payload[2] = { - (uint8_t)((page_num >> 8) & 0xFF), - (uint8_t)(page_num & 0xFF), - }; - - esp_err_t rc = printer_protocol_send_cmd_wait_response(CMD_BOOT_ERASE_PAGE, - payload, - sizeof(payload), - true, - timeout_ms, - true, - true, - NULL, - 0, - NULL, - err, - err_len); - printer_protocol_release_control_lane(); - return rc; + (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, @@ -253,108 +59,21 @@ esp_err_t printer_protocol_ota_write_frame(uint16_t packet_num, uint32_t timeout_ms, char *err, size_t err_len) { - if (is_direct_backend()) { - return unsupported_for_direct(err, err_len, "ota write"); - } - - if ((data_len > 0 && data == NULL) || data_len > OTA_MAX_DATA_PER_FRAME) { - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "invalid frame length"); - } - return ESP_ERR_INVALID_ARG; - } - - if (!ble_printer_client_is_connected()) { - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "printer not connected"); - } - return ESP_ERR_INVALID_STATE; - } - - if (!printer_protocol_acquire_control_lane(runtime_policy_printer_control_lock_timeout_ms(), err, err_len)) { - return ESP_ERR_INVALID_STATE; - } - - uint8_t payload[3 + OTA_MAX_DATA_PER_FRAME]; - payload[0] = (uint8_t)((packet_num >> 8) & 0xFF); - payload[1] = (uint8_t)(packet_num & 0xFF); - payload[2] = is_last_frame ? 0x01 : 0x00; - if (data_len > 0) { - memcpy(&payload[3], data, data_len); - } - - esp_err_t rc = printer_protocol_send_cmd_wait_response(CMD_BOOT_WRITE_DATA, - payload, - (uint16_t)(3 + data_len), - true, - timeout_ms, - true, - true, - NULL, - 0, - NULL, - err, - err_len); - printer_protocol_release_control_lane(); - return rc; + (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) { - if (is_direct_backend()) { - return unsupported_for_direct(err, err_len, "ota version"); - } - - if (out_version == NULL) { - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "invalid args"); - } - return ESP_ERR_INVALID_ARG; - } - - if (!ble_printer_client_is_connected()) { - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "printer not connected"); - } - return ESP_ERR_INVALID_STATE; - } - - if (!printer_protocol_acquire_control_lane(runtime_policy_printer_control_lock_timeout_ms(), err, err_len)) { - return ESP_ERR_INVALID_STATE; - } - - uint8_t rsp[16]; - uint16_t rsp_len = 0; - esp_err_t rc = printer_protocol_send_cmd_wait_response(CMD_BOOT_GET_VERSION, - NULL, - 0, - true, - timeout_ms, - false, - false, - rsp, - sizeof(rsp), - &rsp_len, - err, - err_len); - printer_protocol_release_control_lane(); - if (rc != ESP_OK) { - return rc; - } - - if (rsp_len < 3) { - if (err != NULL && err_len > 0) { - snprintf(err, err_len, "invalid version response"); - } - return ESP_FAIL; - } - - out_version->major = rsp[0]; - out_version->minor = rsp[1]; - out_version->patch = rsp[2]; - return ESP_OK; + (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, diff --git a/components/domain/src/printer_protocol_worker.c b/components/domain/src/printer_protocol_worker.c index df44d2e..2d8f246 100644 --- a/components/domain/src/printer_protocol_worker.c +++ b/components/domain/src/printer_protocol_worker.c @@ -1,8 +1,8 @@ #include "domain.h" #include "printer_protocol_internal.h" -#include #include +#include #include #include "esp_log.h" @@ -12,51 +12,6 @@ static const char *TAG = "printer_protocol"; -static bool request_status_sync(uint32_t timeout_ms) { - int64_t old_ms; - - if (printer_protocol_get_backend() != PRINTER_BACKEND_BLE) { - return false; - } - - if (printer_protocol_is_stopping()) { - return false; - } - - if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(200)) != pdTRUE) { - return false; - } - old_ms = s_status.updated_ms; - xSemaphoreGive(s_mutex); - - uint8_t payload = 0x00; - if (printer_protocol_send_frame(CMD_GET_STATUS, &payload, 0, true) != ESP_OK) { - return false; - } - - int64_t deadline = esp_timer_get_time() / 1000 + timeout_ms; - while ((esp_timer_get_time() / 1000) < deadline) { - if (printer_protocol_is_stopping()) { - return false; - } - - vTaskDelay(pdMS_TO_TICKS(20)); - - if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(100)) != pdTRUE) { - continue; - } - - bool updated = s_status.updated_ms > old_ms; - xSemaphoreGive(s_mutex); - - if (updated) { - return true; - } - } - - return false; -} - static uint16_t density_to_hot_time(const char *density) { if (density == NULL) { return 2000; @@ -77,38 +32,6 @@ static uint16_t density_to_hot_time(const char *density) { } static bool precheck_printer_ready(bool direct_ignore_precheck, char *err, size_t err_len) { - if (printer_protocol_get_backend() == PRINTER_BACKEND_BLE) { - if (!request_status_sync(1200)) { - snprintf(err, err_len, "status timeout"); - return false; - } - - parsed_status_t status; - if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(200)) != pdTRUE) { - snprintf(err, err_len, "status lock failed"); - return false; - } - - status = s_status; - xSemaphoreGive(s_mutex); - - if (!status.has_paper) { - snprintf(err, err_len, "printer out of paper"); - return false; - } - - if (status.battery <= 40) { - snprintf(err, err_len, "battery too low"); - return false; - } - - if (status.temperature >= 60.0f) { - snprintf(err, err_len, "temperature too high"); - return false; - } - return true; - } - if (direct_ignore_precheck) { return true; } @@ -140,126 +63,6 @@ static bool precheck_printer_ready(bool direct_ignore_precheck, char *err, size_ return true; } -static bool run_print_job_ble(job_slot_t *job) { - char err[96]; - err[0] = '\0'; - uint8_t next_progress_log = 25; - - if (!ble_printer_client_is_connected()) { - snprintf(job->error, sizeof(job->error), "printer not connected"); - ESP_LOGW(TAG, "job %u print aborted: %s", (unsigned)job->id, job->error); - return false; - } - - if (!precheck_printer_ready(false, err, sizeof(err))) { - snprintf(job->error, sizeof(job->error), "%s", err); - ESP_LOGW(TAG, "job %u print aborted: %s", (unsigned)job->id, job->error); - return false; - } - - if (job->cancel_requested) { - snprintf(job->error, sizeof(job->error), "job canceled"); - ESP_LOGW(TAG, "job %u print canceled before start", (unsigned)job->id); - return false; - } - - uint8_t power_on = 0x01; - if (!printer_protocol_send_cmd_with_ack(CMD_POWER, &power_on, 1, true, 1500, true)) { - snprintf(job->error, sizeof(job->error), "power on failed"); - ESP_LOGW(TAG, "job %u print aborted: %s", (unsigned)job->id, job->error); - return false; - } - - uint16_t hot_time = density_to_hot_time(job->density); - uint8_t param[4] = { - 0x01, - 0x02, - (uint8_t)((hot_time >> 8) & 0xFF), - (uint8_t)(hot_time & 0xFF), - }; - - if (!printer_protocol_send_cmd_with_ack(CMD_SET_PARAM, param, sizeof(param), true, 1500, true)) { - snprintf(job->error, sizeof(job->error), "set print param failed"); - ESP_LOGW(TAG, "job %u print aborted: %s", (unsigned)job->id, job->error); - return false; - } - - const size_t chunk_max = 240; - size_t total_chunks = (size_t)ceil((double)job->data_len / (double)chunk_max); - ESP_LOGI(TAG, - "job %u data transfer start, chunks=%u, chunk_bytes=%u, hot_time=%u", - (unsigned)job->id, - (unsigned)total_chunks, - (unsigned)chunk_max, - (unsigned)hot_time); - - for (size_t i = 0; i < total_chunks; ++i) { - if (printer_protocol_is_stopping()) { - snprintf(job->error, sizeof(job->error), "protocol stopping"); - return false; - } - - if (job->cancel_requested) { - snprintf(job->error, sizeof(job->error), "job canceled"); - ESP_LOGW(TAG, - "job %u print canceled at chunk %u/%u", - (unsigned)job->id, - (unsigned)(i + 1), - (unsigned)total_chunks); - return false; - } - - size_t start = i * chunk_max; - size_t remain = job->data_len - start; - size_t chunk_len = remain > chunk_max ? chunk_max : remain; - - if (!printer_protocol_send_cmd_with_ack(CMD_SEND_DATA, - &job->data[start], - (uint16_t)chunk_len, - false, - 2500, - true)) { - snprintf(job->error, sizeof(job->error), "send chunk timeout at %u", (unsigned)i); - ESP_LOGW(TAG, "job %u print aborted: %s", (unsigned)job->id, job->error); - return false; - } - - if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(200)) == pdTRUE) { - job->progress = (uint8_t)(((i + 1) * 90) / total_chunks); - if (job->progress < 5) { - job->progress = 5; - } - xSemaphoreGive(s_mutex); - } - - while (job->progress >= next_progress_log && next_progress_log <= 90) { - ESP_LOGI(TAG, - "job %u print progress=%u%% (%u/%u chunks)", - (unsigned)job->id, - (unsigned)job->progress, - (unsigned)(i + 1), - (unsigned)total_chunks); - next_progress_log = (uint8_t)(next_progress_log + 25); - } - } - - ESP_LOGI(TAG, "job %u data transfer done", (unsigned)job->id); - - uint8_t power_off = 0x00; - (void)printer_protocol_send_cmd_with_ack(CMD_POWER, &power_off, 1, true, 1200, false); - - uint8_t feed_payload[3] = {0x2B, 0x00, 0x0C}; - (void)printer_protocol_send_cmd_with_ack(CMD_SET_DISTANCE, - feed_payload, - sizeof(feed_payload), - true, - 1200, - false); - - ESP_LOGI(TAG, "job %u print command sequence done", (unsigned)job->id); - return true; -} - static bool run_print_job_direct(job_slot_t *job) { if (!platform_direct_printer_is_connected()) { snprintf(job->error, sizeof(job->error), "printer not connected"); @@ -294,7 +97,7 @@ static bool run_print_job_direct(job_slot_t *job) { char direct_err[96] = {0}; esp_err_t rc = platform_direct_printer_print(&req, direct_err, sizeof(direct_err)); if (rc != ESP_OK) { - if (direct_err[0] != '\0') { + if (direct_err[0] != 0) { snprintf(job->error, sizeof(job->error), "%s", direct_err); } else if (rc == ESP_ERR_TIMEOUT) { snprintf(job->error, sizeof(job->error), "print timeout"); @@ -315,9 +118,8 @@ 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=%s, raster_bytes=%u, size=%ux%u, density=%s, ignore_precheck=%d", + "job %u print start, backend=direct, raster_bytes=%u, size=%ux%u, density=%s, ignore_precheck=%d", (unsigned)job->id, - printer_protocol_get_backend() == PRINTER_BACKEND_BLE ? "ble" : "direct", (unsigned)job->data_len, (unsigned)job->width, (unsigned)job->height, @@ -329,9 +131,6 @@ static bool run_print_job(job_slot_t *job) { return false; } - if (printer_protocol_get_backend() == PRINTER_BACKEND_BLE) { - return run_print_job_ble(job); - } return run_print_job_direct(job); } @@ -417,11 +216,11 @@ void printer_protocol_worker_task(void *arg) { if (ok) { s_jobs[idx].state = PRINT_JOB_STATE_SUCCESS; - s_jobs[idx].error[0] = '\0'; + s_jobs[idx].error[0] = 0; runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_PRINTER_JOB_SUCCESS, 1); } else if (s_jobs[idx].cancel_requested || printer_protocol_is_stopping()) { s_jobs[idx].state = PRINT_JOB_STATE_CANCELED; - if (s_jobs[idx].error[0] == '\0') { + if (s_jobs[idx].error[0] == 0) { strlcpy(s_jobs[idx].error, "job canceled", sizeof(s_jobs[idx].error)); } runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_PRINTER_JOB_CANCELED, 1); @@ -446,7 +245,7 @@ void printer_protocol_worker_task(void *arg) { (unsigned)s_jobs[idx].id, printer_protocol_job_state_str(s_jobs[idx].state), (long long)duration_ms, - s_jobs[idx].error[0] != '\0' ? s_jobs[idx].error : "-"); + s_jobs[idx].error[0] != 0 ? s_jobs[idx].error : "-"); } free(s_jobs[idx].data); diff --git a/components/platform/CMakeLists.txt b/components/platform/CMakeLists.txt index 7831655..d63d758 100644 --- a/components/platform/CMakeLists.txt +++ b/components/platform/CMakeLists.txt @@ -2,7 +2,6 @@ idf_component_register( SRCS "src/platform_bootstrap.c" "src/wifi_manager.c" - "src/ble_printer_client.c" "src/direct_thermal_printer.c" "src/display_st7789.c" "src/display_lcd_module.c" @@ -16,8 +15,6 @@ idf_component_register( PRIV_INCLUDE_DIRS "internal" REQUIRES - bt - esp_coex esp_wifi esp_netif esp_event diff --git a/components/platform/README.md b/components/platform/README.md index b571305..65af268 100644 --- a/components/platform/README.md +++ b/components/platform/README.md @@ -3,7 +3,7 @@ Purpose: hardware and system resource abstraction only. Allowed examples: -- Wi-Fi/BLE driver wrappers +- Wi-Fi and board-level driver wrappers - NVS/time/RTOS/system adapters - board-specific IO and transport bindings diff --git a/components/platform/include/platform.h b/components/platform/include/platform.h index d573a1c..68cc495 100644 --- a/components/platform/include/platform.h +++ b/components/platform/include/platform.h @@ -20,23 +20,6 @@ esp_err_t wifi_manager_stop(void); bool wifi_manager_is_ready(void); void wifi_manager_get_ip(char *buf, size_t buf_len); -// ---------- ble_printer_client ---------- -typedef void (*ble_frame_rx_cb_t)(const uint8_t *data, size_t len); - -typedef struct { - bool connected; - bool notify_ready; - uint16_t mtu; -} ble_link_state_t; - -esp_err_t ble_printer_client_init(ble_frame_rx_cb_t rx_cb); -esp_err_t ble_printer_client_connect(const char *target_name, uint32_t timeout_ms); -void ble_printer_client_disconnect(void); - -bool ble_printer_client_is_connected(void); -void ble_printer_client_get_link_state(ble_link_state_t *out_state); -esp_err_t ble_printer_client_write(const uint8_t *data, size_t len); - // ---------- direct_thermal_printer ---------- typedef struct { bool has_paper; @@ -153,7 +136,6 @@ uint32_t runtime_policy_printer_worker_queue_wait_ms(void); uint32_t runtime_policy_printer_queue_retry_delay_ms(void); uint32_t runtime_policy_printer_status_poll_interval_ms(void); uint32_t runtime_policy_printer_stop_timeout_ms(void); -uint8_t runtime_policy_printer_default_backend(void); bool runtime_policy_direct_printer_enabled(void); uint32_t runtime_policy_direct_printer_operation_timeout_ms(void); diff --git a/components/platform/src/ble_printer_client.c b/components/platform/src/ble_printer_client.c deleted file mode 100644 index eb3af89..0000000 --- a/components/platform/src/ble_printer_client.c +++ /dev/null @@ -1,706 +0,0 @@ -#include "platform.h" - -#include -#include - -#include "esp_err.h" -#include "esp_log.h" -#include "esp_nimble_hci.h" -#include "freertos/FreeRTOS.h" -#include "freertos/event_groups.h" -#include "freertos/semphr.h" -#include "host/ble_gatt.h" -#include "host/ble_hs.h" -#include "nimble/nimble_port.h" -#include "nimble/nimble_port_freertos.h" -#include "os/os_mbuf.h" -#include "services/gap/ble_svc_gap.h" -#include "services/gatt/ble_svc_gatt.h" - -#define PRINTER_SERVICE_UUID16 0xFFF0 -#define PRINTER_NOTIFY_UUID16 0xFFF1 -#define PRINTER_WRITE_UUID16 0xFFF2 -#define CCCD_UUID16 0x2902 -#define PRINTER_NAME_PRIMARY "TQPrinter" -#define PRINTER_NAME_LEGACY "lyfPrinter" - -#define EVT_CONNECTED BIT0 -#define EVT_READY BIT1 -#define EVT_FAILED BIT2 - -static const char *TAG = "ble_client"; - -static EventGroupHandle_t s_evt_group; -static SemaphoreHandle_t s_lock; - -static ble_frame_rx_cb_t s_rx_cb; - -static uint8_t s_addr_type; -static ble_addr_t s_target_addr; -static char s_target_name[32] = PRINTER_NAME_PRIMARY; -static bool s_match_any_compatible; - -static uint16_t s_conn_handle = BLE_HS_CONN_HANDLE_NONE; -static uint16_t s_service_start; -static uint16_t s_service_end; -static uint16_t s_notify_val_handle; -static uint16_t s_write_val_handle; -static uint16_t s_cccd_handle; -static uint16_t s_mtu = 23; - -static bool s_scanning; -static bool s_notify_ready; -static bool s_host_synced; -static bool s_initialized; -static bool s_connecting; -static uint32_t s_connect_timeout_ms = 15000; - -static uint16_t uuid16(const ble_uuid_t *uuid) { - if (uuid == NULL || uuid->type != BLE_UUID_TYPE_16) { - return 0; - } - return BLE_UUID16(uuid)->value; -} - -static bool adv_has_uuid16(const struct ble_hs_adv_fields *fields, uint16_t target_uuid) { - if (fields == NULL || fields->uuids16 == NULL || fields->num_uuids16 == 0) { - return false; - } - for (uint8_t i = 0; i < fields->num_uuids16; ++i) { - if (fields->uuids16[i].value == target_uuid) { - return true; - } - } - return false; -} - -static size_t normalize_name(const char *in, char *out, size_t out_cap) { - if (in == NULL || out == NULL || out_cap == 0) { - return 0; - } - - const char *start = in; - while (*start != '\0' && isspace((unsigned char)*start)) { - ++start; - } - if (*start == '"' || *start == '\'') { - ++start; - } - - size_t len = strlen(start); - while (len > 0 && isspace((unsigned char)start[len - 1])) { - --len; - } - if (len > 0 && (start[len - 1] == '"' || start[len - 1] == '\'')) { - --len; - } - - size_t out_len = 0; - for (size_t i = 0; i < len && out_len + 1 < out_cap; ++i) { - unsigned char c = (unsigned char)start[i]; - if (isupper(c)) { - c = (unsigned char)tolower(c); - } - out[out_len++] = (char)c; - } - out[out_len] = '\0'; - return out_len; -} - -static bool normalized_name_match(const char *adv_name, const char *target_name) { - char adv[40] = {0}; - char target[40] = {0}; - size_t adv_len = normalize_name(adv_name, adv, sizeof(adv)); - size_t target_len = normalize_name(target_name, target, sizeof(target)); - if (adv_len == 0 || target_len == 0) { - return false; - } - if (strcmp(adv, target) == 0) { - return true; - } - // Be tolerant of shortened or prefixed names. - return (strstr(adv, target) != NULL) || (strstr(target, adv) != NULL); -} - -static bool is_known_printer_name(const char *name) { - return normalized_name_match(name, PRINTER_NAME_PRIMARY) || - normalized_name_match(name, PRINTER_NAME_LEGACY); -} - -static bool target_name_match_with_alias(const char *adv_name, const char *target_name) { - if (normalized_name_match(adv_name, target_name)) { - return true; - } - if (!is_known_printer_name(target_name)) { - return false; - } - return is_known_printer_name(adv_name); -} - -static void reset_discovery_state(void) { - s_service_start = 0; - s_service_end = 0; - s_notify_val_handle = 0; - s_write_val_handle = 0; - s_cccd_handle = 0; - s_notify_ready = false; - s_mtu = 23; -} - -static void signal_failure(void) { - xEventGroupSetBits(s_evt_group, EVT_FAILED); -} - -static void signal_ready(void) { - xEventGroupSetBits(s_evt_group, EVT_READY); -} - -static int dsc_disc_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - uint16_t chr_val_handle, - const struct ble_gatt_dsc *dsc, - void *arg); - -static int chr_disc_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - const struct ble_gatt_chr *chr, - void *arg); - -static int svc_disc_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - const struct ble_gatt_svc *service, - void *arg); - -static int cccd_write_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - struct ble_gatt_attr *attr, - void *arg) { - (void)conn_handle; - (void)attr; - (void)arg; - - if (error->status != 0) { - ESP_LOGE(TAG, "CCCD write failed status=%d", error->status); - signal_failure(); - return 0; - } - - s_notify_ready = true; - ESP_LOGI(TAG, "Notify subscription enabled"); - signal_ready(); - return 0; -} - -static int dsc_disc_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - uint16_t chr_val_handle, - const struct ble_gatt_dsc *dsc, - void *arg) { - (void)chr_val_handle; - (void)arg; - - if (error->status == 0 && dsc != NULL) { - if (uuid16(&dsc->uuid.u) == CCCD_UUID16) { - s_cccd_handle = dsc->handle; - ESP_LOGI(TAG, "Found CCCD handle=%u", s_cccd_handle); - } - return 0; - } - - if (error->status == BLE_HS_EDONE) { - if (s_cccd_handle == 0) { - ESP_LOGW(TAG, "CCCD not found, fallback to val_handle+1"); - s_cccd_handle = s_notify_val_handle + 1; - } - - uint8_t cccd[2] = {0x01, 0x00}; - int rc = ble_gattc_write_flat(conn_handle, s_cccd_handle, cccd, sizeof(cccd), cccd_write_cb, NULL); - if (rc != 0) { - ESP_LOGE(TAG, "ble_gattc_write_flat CCCD failed rc=%d", rc); - signal_failure(); - } - return 0; - } - - ESP_LOGE(TAG, "Descriptor discovery failed status=%d", error->status); - signal_failure(); - return 0; -} - -static int chr_disc_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - const struct ble_gatt_chr *chr, - void *arg) { - (void)arg; - - if (error->status == 0 && chr != NULL) { - uint16_t id = uuid16(&chr->uuid.u); - if (id == PRINTER_NOTIFY_UUID16) { - s_notify_val_handle = chr->val_handle; - ESP_LOGI(TAG, "Found notify char handle=%u", s_notify_val_handle); - } else if (id == PRINTER_WRITE_UUID16) { - s_write_val_handle = chr->val_handle; - ESP_LOGI(TAG, "Found write char handle=%u", s_write_val_handle); - } - return 0; - } - - if (error->status == BLE_HS_EDONE) { - if (s_notify_val_handle == 0 || s_write_val_handle == 0) { - ESP_LOGE(TAG, - "Characteristic discovery incomplete notify=%u write=%u", - s_notify_val_handle, - s_write_val_handle); - signal_failure(); - return 0; - } - - uint16_t end_handle = (s_write_val_handle > s_notify_val_handle) - ? (uint16_t)(s_write_val_handle - 1) - : s_service_end; - - if (end_handle <= s_notify_val_handle) { - end_handle = s_service_end; - } - - int rc = ble_gattc_disc_all_dscs(conn_handle, - s_notify_val_handle, - end_handle, - dsc_disc_cb, - NULL); - if (rc != 0) { - ESP_LOGE(TAG, "Descriptor discovery start failed rc=%d", rc); - signal_failure(); - } - return 0; - } - - ESP_LOGE(TAG, "Characteristic discovery failed status=%d", error->status); - signal_failure(); - return 0; -} - -static int svc_disc_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - const struct ble_gatt_svc *service, - void *arg) { - (void)arg; - - if (error->status == 0 && service != NULL) { - if (uuid16(&service->uuid.u) == PRINTER_SERVICE_UUID16) { - s_service_start = service->start_handle; - s_service_end = service->end_handle; - ESP_LOGI(TAG, "Found printer service [%u, %u]", s_service_start, s_service_end); - } - return 0; - } - - if (error->status == BLE_HS_EDONE) { - uint16_t start = s_service_start; - uint16_t end = s_service_end; - if (start == 0 || end == 0) { - // Android app searches all services/chars for FFF1/FFF2. - // Use a global fallback range for broader compatibility. - start = 1; - end = 0xFFFF; - ESP_LOGW(TAG, "Printer service 0x%04x not found; fallback char discovery in full handle range", PRINTER_SERVICE_UUID16); - } - - int rc = ble_gattc_disc_all_chrs(conn_handle, - start, - end, - chr_disc_cb, - NULL); - if (rc != 0) { - ESP_LOGE(TAG, "Start characteristic discovery failed rc=%d", rc); - signal_failure(); - } - return 0; - } - - ESP_LOGE(TAG, "Service discovery failed status=%d", error->status); - signal_failure(); - return 0; -} - -static void start_service_discovery(void) { - int rc = ble_gattc_disc_all_svcs(s_conn_handle, svc_disc_cb, NULL); - if (rc != 0) { - ESP_LOGE(TAG, "ble_gattc_disc_all_svcs failed rc=%d", rc); - signal_failure(); - } -} - -static void start_scan(void); - -static void stop_scan_if_running(void) { - if (s_scanning) { - ble_gap_disc_cancel(); - s_scanning = false; - } -} - -static int gap_event_cb(struct ble_gap_event *event, void *arg) { - (void)arg; - - switch (event->type) { - case BLE_GAP_EVENT_DISC: { - if (!s_scanning) { - return 0; - } - struct ble_hs_adv_fields fields; - memset(&fields, 0, sizeof(fields)); - - int rc = ble_hs_adv_parse_fields(&fields, - event->disc.data, - event->disc.length_data); - if (rc != 0) { - return 0; - } - - char name[32] = {0}; - bool has_name = (fields.name_len > 0 && fields.name != NULL); - if (has_name) { - size_t n = fields.name_len < sizeof(name) - 1 ? fields.name_len : sizeof(name) - 1; - memcpy(name, fields.name, n); - } - - if (s_match_any_compatible) { - bool uuid_match = adv_has_uuid16(&fields, PRINTER_SERVICE_UUID16); - bool name_match = has_name && is_known_printer_name(name); - if (!uuid_match && !name_match) { - return 0; - } - ESP_LOGI(TAG, - "Found compatible device '%s' RSSI=%d (uuid_match=%d)", - has_name ? name : "", - event->disc.rssi, - uuid_match ? 1 : 0); - } else { - if (!has_name || !target_name_match_with_alias(name, s_target_name)) { - return 0; - } - ESP_LOGI(TAG, "Found target device '%s' RSSI=%d", name, event->disc.rssi); - } - - s_target_addr = event->disc.addr; - stop_scan_if_running(); - - struct ble_gap_conn_params conn_params; - memset(&conn_params, 0, sizeof(conn_params)); - conn_params.scan_itvl = 0x0010; - conn_params.scan_window = 0x0010; - conn_params.itvl_min = 0x0018; - conn_params.itvl_max = 0x0028; - conn_params.latency = 0; - conn_params.supervision_timeout = 0x0100; - conn_params.min_ce_len = 0x0010; - conn_params.max_ce_len = 0x0300; - - rc = ble_gap_connect(s_addr_type, - &s_target_addr, - s_connect_timeout_ms > 30000 ? 30000 : s_connect_timeout_ms, - &conn_params, - gap_event_cb, - NULL); - if (rc != 0) { - ESP_LOGE(TAG, "ble_gap_connect failed rc=%d", rc); - s_connecting = false; - signal_failure(); - } else { - ESP_LOGI(TAG, "Connecting..."); - } - - return 0; - } - - case BLE_GAP_EVENT_DISC_COMPLETE: - s_scanning = false; - return 0; - - case BLE_GAP_EVENT_CONNECT: - if (event->connect.status == 0) { - if (!s_connecting) { - (void)ble_gap_terminate(event->connect.conn_handle, BLE_ERR_REM_USER_CONN_TERM); - return 0; - } - s_connecting = false; - s_conn_handle = event->connect.conn_handle; - xEventGroupSetBits(s_evt_group, EVT_CONNECTED); - ESP_LOGI(TAG, "Connected handle=%u", s_conn_handle); - - ble_gattc_exchange_mtu(s_conn_handle, NULL, NULL); - start_service_discovery(); - } else { - s_connecting = false; - ESP_LOGE(TAG, "Connect failed status=%d", event->connect.status); - signal_failure(); - } - return 0; - - case BLE_GAP_EVENT_DISCONNECT: - ESP_LOGW(TAG, "Disconnected reason=%d", event->disconnect.reason); - s_connecting = false; - s_conn_handle = BLE_HS_CONN_HANDLE_NONE; - s_notify_ready = false; - reset_discovery_state(); - return 0; - - case BLE_GAP_EVENT_MTU: - s_mtu = event->mtu.value; - ESP_LOGI(TAG, "MTU updated to %u", s_mtu); - return 0; - - case BLE_GAP_EVENT_NOTIFY_RX: { - if (event->notify_rx.om == NULL || s_rx_cb == NULL) { - return 0; - } - - uint16_t data_len = OS_MBUF_PKTLEN(event->notify_rx.om); - if (data_len == 0) { - return 0; - } - - uint8_t buf[256]; - uint16_t out_len = 0; - if (data_len > sizeof(buf)) { - ESP_LOGW(TAG, "Notify packet too large len=%u", data_len); - return 0; - } - - int rc = ble_hs_mbuf_to_flat(event->notify_rx.om, buf, sizeof(buf), &out_len); - if (rc != 0) { - ESP_LOGW(TAG, "ble_hs_mbuf_to_flat notify failed rc=%d", rc); - return 0; - } - - s_rx_cb(buf, out_len); - return 0; - } - - default: - return 0; - } -} - -static void start_scan(void) { - struct ble_gap_disc_params params; - memset(¶ms, 0, sizeof(params)); - // Keep duplicates so we can receive scan response updates carrying full local name. - params.filter_duplicates = 0; - params.passive = 0; - params.itvl = 0x0010; - params.window = 0x0010; - - stop_scan_if_running(); - - int rc = ble_gap_disc(s_addr_type, BLE_HS_FOREVER, ¶ms, gap_event_cb, NULL); - if (rc != 0) { - ESP_LOGE(TAG, "ble_gap_disc failed rc=%d", rc); - signal_failure(); - return; - } - - s_scanning = true; - if (s_match_any_compatible) { - ESP_LOGI(TAG, "Scanning for compatible printer (service 0x%04x)", PRINTER_SERVICE_UUID16); - } else { - ESP_LOGI(TAG, "Scanning for %s", s_target_name); - } -} - -static void ble_on_reset(int reason) { - ESP_LOGE(TAG, "BLE reset reason=%d", reason); -} - -static void ble_on_sync(void) { - int rc = ble_hs_id_infer_auto(0, &s_addr_type); - if (rc != 0) { - ESP_LOGE(TAG, "ble_hs_id_infer_auto failed rc=%d", rc); - } - s_host_synced = true; -} - -static void nimble_host_task(void *param) { - (void)param; - nimble_port_run(); - nimble_port_freertos_deinit(); -} - -esp_err_t ble_printer_client_init(ble_frame_rx_cb_t rx_cb) { - s_rx_cb = rx_cb; - - if (s_initialized) { - reset_discovery_state(); - return ESP_OK; - } - - // NimBLE emits very chatty INFO logs during each chunk write. - // Lowering these logs reduces serial I/O overhead and improves runtime smoothness. - esp_log_level_set("NimBLE", ESP_LOG_WARN); - esp_log_level_set("BLE_INIT", ESP_LOG_WARN); - - s_evt_group = xEventGroupCreate(); - if (s_evt_group == NULL) { - return ESP_ERR_NO_MEM; - } - - s_lock = xSemaphoreCreateMutex(); - if (s_lock == NULL) { - vEventGroupDelete(s_evt_group); - s_evt_group = NULL; - return ESP_ERR_NO_MEM; - } - - esp_err_t err = nimble_port_init(); - if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { - return err; - } - ble_hs_cfg.reset_cb = ble_on_reset; - ble_hs_cfg.sync_cb = ble_on_sync; - - ble_svc_gap_init(); - ble_svc_gatt_init(); - - nimble_port_freertos_init(nimble_host_task); - - reset_discovery_state(); - s_initialized = true; - return ESP_OK; -} - -esp_err_t ble_printer_client_connect(const char *target_name, uint32_t timeout_ms) { - if (!s_initialized || s_lock == NULL || s_evt_group == NULL) { - return ESP_ERR_INVALID_STATE; - } - - uint32_t effective_timeout_ms = timeout_ms; - if (effective_timeout_ms < 1000) { - effective_timeout_ms = 1000; - } else if (effective_timeout_ms > 60000) { - effective_timeout_ms = 60000; - } - - s_match_any_compatible = false; - if (target_name != NULL && target_name[0] != '\0') { - if (strcmp(target_name, "*") == 0) { - s_match_any_compatible = true; - } else { - strlcpy(s_target_name, target_name, sizeof(s_target_name)); - } - } - - if (xSemaphoreTake(s_lock, pdMS_TO_TICKS(3000)) != pdTRUE) { - return ESP_ERR_TIMEOUT; - } - - if (s_conn_handle != BLE_HS_CONN_HANDLE_NONE && s_notify_ready) { - xSemaphoreGive(s_lock); - return ESP_OK; - } - if (s_connecting) { - xSemaphoreGive(s_lock); - return ESP_ERR_INVALID_STATE; - } - - xEventGroupClearBits(s_evt_group, EVT_CONNECTED | EVT_READY | EVT_FAILED); - reset_discovery_state(); - s_connect_timeout_ms = effective_timeout_ms; - s_connecting = true; - - int wait_sync_ms = 3000; - while (!s_host_synced && wait_sync_ms > 0) { - vTaskDelay(pdMS_TO_TICKS(20)); - wait_sync_ms -= 20; - } - if (!s_host_synced) { - xSemaphoreGive(s_lock); - return ESP_ERR_INVALID_STATE; - } - - start_scan(); - xSemaphoreGive(s_lock); - - EventBits_t bits = xEventGroupWaitBits(s_evt_group, - EVT_READY | EVT_FAILED, - pdFALSE, - pdFALSE, - pdMS_TO_TICKS(effective_timeout_ms)); - - if (bits & EVT_READY) { - return ESP_OK; - } - if (xSemaphoreTake(s_lock, pdMS_TO_TICKS(1000)) == pdTRUE) { - stop_scan_if_running(); - if (s_conn_handle != BLE_HS_CONN_HANDLE_NONE) { - (void)ble_gap_terminate(s_conn_handle, BLE_ERR_REM_USER_CONN_TERM); - } - s_connecting = false; - reset_discovery_state(); - xSemaphoreGive(s_lock); - } - - if (bits & EVT_FAILED) { - return ESP_FAIL; - } - return ESP_ERR_TIMEOUT; -} - -void ble_printer_client_disconnect(void) { - if (!s_initialized || s_lock == NULL) { - return; - } - - if (xSemaphoreTake(s_lock, pdMS_TO_TICKS(2000)) != pdTRUE) { - return; - } - - stop_scan_if_running(); - - if (s_conn_handle != BLE_HS_CONN_HANDLE_NONE) { - ble_gap_terminate(s_conn_handle, BLE_ERR_REM_USER_CONN_TERM); - } - - s_connecting = false; - s_conn_handle = BLE_HS_CONN_HANDLE_NONE; - reset_discovery_state(); - xSemaphoreGive(s_lock); -} - -bool ble_printer_client_is_connected(void) { - if (!s_initialized) { - return false; - } - return (s_conn_handle != BLE_HS_CONN_HANDLE_NONE) && s_notify_ready; -} - -void ble_printer_client_get_link_state(ble_link_state_t *out_state) { - if (out_state == NULL) { - return; - } - - out_state->connected = (s_conn_handle != BLE_HS_CONN_HANDLE_NONE); - out_state->notify_ready = s_notify_ready; - out_state->mtu = s_mtu; -} - -esp_err_t ble_printer_client_write(const uint8_t *data, size_t len) { - if (data == NULL || len == 0) { - return ESP_ERR_INVALID_ARG; - } - - if (!ble_printer_client_is_connected() || s_write_val_handle == 0) { - return ESP_ERR_INVALID_STATE; - } - - int rc = ble_gattc_write_no_rsp_flat(s_conn_handle, - s_write_val_handle, - data, - len); - if (rc != 0) { - ESP_LOGW(TAG, "write_no_rsp failed rc=%d", rc); - return ESP_FAIL; - } - - return ESP_OK; -} diff --git a/components/platform/src/runtime_policy.c b/components/platform/src/runtime_policy.c index eeb6d30..cd1b7a6 100644 --- a/components/platform/src/runtime_policy.c +++ b/components/platform/src/runtime_policy.c @@ -34,10 +34,6 @@ #define CONFIG_TQ_PRINTER_STOP_TIMEOUT_MS 8000 #endif -#ifndef CONFIG_TQ_PRINTER_DEFAULT_BACKEND -#define CONFIG_TQ_PRINTER_DEFAULT_BACKEND 0 -#endif - #ifndef CONFIG_TQ_DIRECT_PRINTER_ENABLE #define CONFIG_TQ_DIRECT_PRINTER_ENABLE 1 #endif @@ -201,10 +197,6 @@ uint32_t runtime_policy_printer_stop_timeout_ms(void) { return clamp_u32(CONFIG_TQ_PRINTER_STOP_TIMEOUT_MS, 1000, 30000); } -uint8_t runtime_policy_printer_default_backend(void) { - return (uint8_t)clamp_u32(CONFIG_TQ_PRINTER_DEFAULT_BACKEND, 0, 1); -} - bool runtime_policy_direct_printer_enabled(void) { return CONFIG_TQ_DIRECT_PRINTER_ENABLE != 0; } diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index a89225b..b261e11 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -81,11 +81,6 @@ config TQ_PRINTER_STOP_TIMEOUT_MS range 1000 30000 default 8000 -config TQ_PRINTER_DEFAULT_BACKEND - int "Printer default backend (0=BLE, 1=Direct)" - range 0 1 - default 0 - config TQ_DIRECT_PRINTER_ENABLE bool "Enable direct thermal printer backend" default y diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 9f82439..fe746ab 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -1,9 +1,5 @@ CONFIG_IDF_TARGET="esp32s3" -CONFIG_BT_ENABLED=y -CONFIG_BT_NIMBLE_ENABLED=y -CONFIG_BT_BLUEDROID_ENABLED=n -CONFIG_BT_NIMBLE_ROLE_CENTRAL=y -CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=247 +# CONFIG_BT_ENABLED is not set CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE=n CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=24