refactor(control_plane): remove business http server stack
This commit is contained in:
250
README.md
250
README.md
@@ -1,42 +1,26 @@
|
||||
# ESP32-S3 TQ Printer Controller (Wi-Fi REST API)
|
||||
# ESP32-S3 TQ Printer Controller (Direct Thermal, No Business HTTP Server)
|
||||
|
||||
ESP32-S3 works as a Wi-Fi REST controller and replaces Android App logic:
|
||||
- REST client -> ESP32-S3 (`esp_http_server`)
|
||||
- ESP32-S3 -> onboard direct thermal printer driver
|
||||
This firmware now runs in direct-printer mode and does not expose the previous
|
||||
business REST endpoints (`/v1/*`).
|
||||
|
||||
## Features
|
||||
|
||||
- Wi-Fi STA-only mode (configured SSID/password; no SoftAP fallback)
|
||||
- Built-in minimal web UI at `/` for voice status and MIC_KEY guidance
|
||||
- Direct thermal printer control with sensor precheck
|
||||
- Async print queue with jobs (`queued/running/success/failed/canceled`)
|
||||
- Direct thermal printer backend (`PRINTER_BACKEND_DIRECT`)
|
||||
- Auto-connect direct printer during startup
|
||||
- Async print queue and worker lifecycle management
|
||||
- Printer precheck (paper / battery / temperature)
|
||||
- Built-in UTF-8 text rendering with Chinese support (GB2312 character set, 16x16 bitmap)
|
||||
- Push2talk multimodal voice interaction over DashScope WebSocket:
|
||||
- ES8311 microphone/speaker via `esp_codec_dev`
|
||||
- raw-opus uplink/downlink via `esp_audio_codec`
|
||||
- WebSocket transport via `esp_websocket_client`
|
||||
- REST APIs:
|
||||
- Root:
|
||||
- `GET /`
|
||||
- Health/connection:
|
||||
- `GET /v1/health`
|
||||
- `POST /v1/printer/connect`
|
||||
- `POST /v1/printer/disconnect`
|
||||
- `GET /v1/printer/status`
|
||||
- Print:
|
||||
- `POST /v1/print/raster`
|
||||
- `POST /v1/print/image` (JSON prompt -> generate image -> print, also compatible with direct PNG binary upload)
|
||||
- `POST /v1/print/text`
|
||||
- Jobs:
|
||||
- `GET /v1/jobs`
|
||||
- `GET /v1/jobs/{id}`
|
||||
- Voice:
|
||||
- `GET /v1/voice/status`
|
||||
- `POST /v1/voice/session/start`
|
||||
- `POST /v1/voice/session/stop`
|
||||
- `POST /v1/voice/tap/start`
|
||||
- `POST /v1/voice/tap/cancel`
|
||||
- MIC key push-to-talk voice flow (button-triggered, no HTTP trigger)
|
||||
- Wi-Fi STA with SoftAP provisioning fallback
|
||||
- Provisioning portal page at `http://192.168.4.1` (unchanged)
|
||||
- Optional DashScope Z-Image integration for image generation
|
||||
|
||||
## What Was Removed
|
||||
|
||||
- Business HTTP server in `control_plane` (including previous `/`, `/v1/health`,
|
||||
`/v1/printer/*`, `/v1/print/*`, `/v1/jobs*`, `/v1/voice/*` endpoints)
|
||||
- Related Kconfig items:
|
||||
- `TQ_HTTP_PORT`
|
||||
- `TQ_API_KEY`
|
||||
|
||||
## Build
|
||||
|
||||
@@ -51,33 +35,35 @@ idf.py menuconfig
|
||||
idf.py build
|
||||
```
|
||||
|
||||
## Flash
|
||||
|
||||
```bash
|
||||
cd ai_printer
|
||||
idf.py -p /dev/tty.usbmodemXXXX flash monitor
|
||||
```
|
||||
|
||||
## Config
|
||||
|
||||
In `menuconfig -> TQ Controller Config`:
|
||||
- `TQ_WIFI_PROV_SOFTAP_SSID`
|
||||
- `TQ_WIFI_PROV_SOFTAP_PASSWORD`
|
||||
- `TQ_WIFI_PROV_SOFTAP_CHANNEL`
|
||||
- `TQ_WIFI_PROV_SOFTAP_MAX_CONN`
|
||||
- `TQ_HTTP_PORT`
|
||||
- `TQ_API_KEY` (optional)
|
||||
- Z-Image HTTP auth and model fields:
|
||||
|
||||
- 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:
|
||||
- `TQ_DIRECT_PRINTER_*`
|
||||
- `TQ_PRINTER_*`
|
||||
- Z-Image HTTP fields:
|
||||
- `TQ_Z_IMAGE_API_KEY` (optional, empty means fallback to `TQ_VOICE_API_KEY`)
|
||||
- `TQ_Z_IMAGE_API_ENDPOINT`
|
||||
- `TQ_Z_IMAGE_MODEL`
|
||||
- `TQ_Z_IMAGE_DEFAULT_SIZE`
|
||||
- `TQ_Z_IMAGE_TIMEOUT_MS`
|
||||
- `TQ_Z_IMAGE_DOWNLOAD_TIMEOUT_MS`
|
||||
- Voice WebSocket auth and app fields:
|
||||
- `TQ_VOICE_API_KEY`
|
||||
- `TQ_VOICE_WORKSPACE_ID`
|
||||
- `TQ_VOICE_APP_ID`
|
||||
- Voice audio and codec fields:
|
||||
- `TQ_VOICE_SAMPLE_RATE`
|
||||
- `TQ_VOICE_OPUS_FRAME_MS`
|
||||
- `TQ_VOICE_OPUS_BITRATE_KBPS`
|
||||
- `TQ_VOICE_I2C_*` / `TQ_VOICE_I2S_*`
|
||||
- `TQ_VOICE_CODEC_*`
|
||||
- Board GPIO map fields:
|
||||
- Voice and audio fields (used by MIC key push-to-talk flow):
|
||||
- `TQ_VOICE_*`
|
||||
- Board GPIO map:
|
||||
- `TQ_POWER_*`, `TQ_LED_*`, `TQ_SCREEN_*`, `TQ_PRINT_*`, `TQ_SPI_*`
|
||||
- `TQ_KEY_PRINT_BOOST_ENABLE_ON_BOOT` / `TQ_KEY_PRINT_BOOST_ACTIVE_HIGH`
|
||||
- ST7789 screen fields:
|
||||
@@ -96,157 +82,23 @@ In `menuconfig -> TQ Controller Config`:
|
||||
Board pin assignment reference:
|
||||
- [`docs/gpio-map.md`](docs/gpio-map.md)
|
||||
|
||||
When `TQ_API_KEY` is not empty, each request must include:
|
||||
## Wi-Fi Provisioning Behavior
|
||||
|
||||
```text
|
||||
X-API-Key: <your-key>
|
||||
```
|
||||
|
||||
Wi-Fi provisioning behavior:
|
||||
- Device first tries saved STA credentials from NVS (`wifi_cfg` namespace).
|
||||
- If no valid credentials exist or STA connect fails, device starts a SoftAP portal.
|
||||
- Connect to the SoftAP and open `http://192.168.4.1`; the static page auto-scans nearby SSIDs for selection.
|
||||
- Provisioning page supports Chinese/English switching and remembers the selected language in browser local storage.
|
||||
- Credentials are written to NVS only after STA connect succeeds.
|
||||
|
||||
## Flash
|
||||
|
||||
```bash
|
||||
cd ai_printer
|
||||
idf.py -p /dev/tty.usbmodemXXXX flash monitor
|
||||
```
|
||||
|
||||
## Web UI
|
||||
|
||||
Open the controller IP in a browser:
|
||||
|
||||
```text
|
||||
http://<esp-ip>/
|
||||
```
|
||||
|
||||
The page provides a minimal voice console:
|
||||
- MIC_KEY(IO14) trigger guide (press to talk, release to process)
|
||||
- voice status display
|
||||
|
||||
## REST Examples
|
||||
|
||||
### Health
|
||||
```bash
|
||||
curl http://<esp-ip>/v1/health
|
||||
```
|
||||
|
||||
### Connect printer
|
||||
```bash
|
||||
curl -X POST http://<esp-ip>/v1/printer/connect \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"timeout_ms":15000}'
|
||||
# Optional explicit backend field:
|
||||
# -d '{"backend":"direct","timeout_ms":15000}'
|
||||
```
|
||||
|
||||
### Raster print
|
||||
```bash
|
||||
curl -X POST http://<esp-ip>/v1/print/raster \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"width":384,
|
||||
"height":200,
|
||||
"density":"中等",
|
||||
"encoding":"base64_msb_1bpp",
|
||||
"data":"<BASE64_BYTES>"
|
||||
}'
|
||||
```
|
||||
|
||||
### Image print (generate with prompt, then print)
|
||||
```bash
|
||||
curl -X POST http://<esp-ip>/v1/print/image \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"prompt":"一只坐在窗边的橘猫,午后阳光,胶片质感,写实风格。",
|
||||
"size":"1120*1440",
|
||||
"prompt_extend":false,
|
||||
"threshold":160,
|
||||
"max_height":2200,
|
||||
"scale_to_width":true,
|
||||
"invert":false,
|
||||
"density":"中等",
|
||||
"timeout_ms":45000,
|
||||
"fetch_timeout_ms":15000
|
||||
}'
|
||||
```
|
||||
|
||||
### Image print (direct PNG upload, backward-compatible)
|
||||
```bash
|
||||
curl -X POST 'http://<esp-ip>/v1/print/image?scale_to_width=1&threshold=160&invert=0&max_height=2200&density=medium' \
|
||||
-H 'Content-Type: image/png' \
|
||||
--data-binary @./sample.png
|
||||
```
|
||||
|
||||
Request constraints:
|
||||
- Request body limit: 4 MB
|
||||
- Suggested image size: <= 3 MB when using direct PNG upload compatibility mode
|
||||
|
||||
### Text print
|
||||
```bash
|
||||
curl -X POST http://<esp-ip>/v1/print/text \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"text":"欢迎使用TQ打印机\\n订单号: A1024\\n谢谢惠顾",
|
||||
"density":"中等",
|
||||
"scale":2,
|
||||
"line_spacing":2,
|
||||
"max_height":1800
|
||||
}'
|
||||
```
|
||||
|
||||
### Jobs
|
||||
```bash
|
||||
curl http://<esp-ip>/v1/jobs
|
||||
curl http://<esp-ip>/v1/jobs/1
|
||||
```
|
||||
|
||||
### Voice push2talk
|
||||
Start session:
|
||||
|
||||
```bash
|
||||
curl -X POST http://<esp-ip>/v1/voice/session/start
|
||||
```
|
||||
|
||||
Press-to-talk start (sends `SendSpeech` when entering `Listening`):
|
||||
|
||||
```bash
|
||||
curl -X POST http://<esp-ip>/v1/voice/tap/start
|
||||
```
|
||||
|
||||
Release-to-stop (sends `StopSpeech`):
|
||||
|
||||
```bash
|
||||
curl -X POST http://<esp-ip>/v1/voice/tap/cancel
|
||||
```
|
||||
|
||||
Get voice status:
|
||||
|
||||
```bash
|
||||
curl http://<esp-ip>/v1/voice/status
|
||||
```
|
||||
|
||||
Stop session:
|
||||
|
||||
```bash
|
||||
curl -X POST http://<esp-ip>/v1/voice/session/stop
|
||||
```
|
||||
- Device first tries saved STA credentials from NVS (`wifi_cfg` namespace)
|
||||
- If credentials are invalid or STA connect fails, device starts SoftAP portal
|
||||
- Open `http://192.168.4.1` and submit credentials from the provisioning page
|
||||
- Provisioning page supports Chinese/English switching and local language cache
|
||||
- Credentials are written to NVS only after STA connect succeeds
|
||||
|
||||
## Notes
|
||||
|
||||
- `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.
|
||||
- Characters outside embedded glyph set are rendered as square fallback boxes.
|
||||
- Large buffers for image upload/decode prefer PSRAM first, then fallback to internal RAM.
|
||||
- Partition table uses `partitions.csv` with a 4MB `factory` app partition on 16MB flash modules.
|
||||
- Voice flow uses `push2talk`: client sends `SendSpeech` to start uplink and `StopSpeech` on release to end input.
|
||||
- Voice flow is now single-round: after recognition/response completes, `LocalRespondingEnded` and `Stop` are sent after local playback drain.
|
||||
- Voice flow blocks starting the next round while voice is Thinking/Responding, marker image generation is running, or printer queue is still busy.
|
||||
- This project no longer provides business HTTP API endpoints for print/voice/job
|
||||
control.
|
||||
- SoftAP provisioning HTTP service remains enabled by design.
|
||||
- UTF-8 Chinese text rendering uses embedded 16x16 GB2312 glyphs.
|
||||
- Large image buffers prefer PSRAM, then fall back to internal RAM.
|
||||
- Partition table uses `partitions.csv` with a 4MB `factory` app partition on
|
||||
16MB flash modules.
|
||||
|
||||
## Font Assets
|
||||
|
||||
|
||||
Reference in New Issue
Block a user