多模态
This commit is contained in:
@@ -44,3 +44,9 @@ esp_err_t rest_server_ota_jump_app_post(httpd_req_t *req);
|
||||
esp_err_t rest_server_ota_erase_page_post(httpd_req_t *req);
|
||||
esp_err_t rest_server_ota_write_frame_post(httpd_req_t *req);
|
||||
esp_err_t rest_server_ota_upgrade_post(httpd_req_t *req);
|
||||
|
||||
esp_err_t rest_server_voice_status_get(httpd_req_t *req);
|
||||
esp_err_t rest_server_voice_session_start_post(httpd_req_t *req);
|
||||
esp_err_t rest_server_voice_session_stop_post(httpd_req_t *req);
|
||||
esp_err_t rest_server_voice_tap_start_post(httpd_req_t *req);
|
||||
esp_err_t rest_server_voice_tap_cancel_post(httpd_req_t *req);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "printer_protocol.h"
|
||||
#include "rest_server.h"
|
||||
#include "system_runtime.h"
|
||||
#include "voice_interaction.h"
|
||||
|
||||
static const char *TAG = "controller_lifecycle";
|
||||
|
||||
@@ -14,6 +15,9 @@ esp_err_t controller_lifecycle_start(void) {
|
||||
ESP_LOGI(TAG, "Starting printer protocol");
|
||||
ESP_ERROR_CHECK(printer_protocol_init());
|
||||
|
||||
ESP_LOGI(TAG, "Starting voice interaction");
|
||||
ESP_ERROR_CHECK(voice_interaction_init());
|
||||
|
||||
ESP_LOGI(TAG, "Starting REST server");
|
||||
ESP_ERROR_CHECK(rest_server_start());
|
||||
|
||||
@@ -22,6 +26,7 @@ esp_err_t controller_lifecycle_start(void) {
|
||||
|
||||
void controller_lifecycle_stop(void) {
|
||||
rest_server_stop();
|
||||
(void)voice_interaction_stop(NULL, 0);
|
||||
printer_protocol_disconnect();
|
||||
ESP_LOGI(TAG, "Controller lifecycle stopped");
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ static const char *s_web_index =
|
||||
"<head>\n"
|
||||
" <meta charset='utf-8'>\n"
|
||||
" <meta name='viewport' content='width=device-width,initial-scale=1'>\n"
|
||||
" <title>LYF Printer Controller</title>\n"
|
||||
" <title>TQ Printer Controller</title>\n"
|
||||
" <style>\n"
|
||||
" :root { color-scheme: light; }\n"
|
||||
" body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; margin: 16px; background:#f7f8fb; color:#1b2430; }\n"
|
||||
@@ -37,7 +37,7 @@ static const char *s_web_index =
|
||||
"</head>\n"
|
||||
"<body>\n"
|
||||
" <div class='box'>\n"
|
||||
" <h1>LYF Printer Controller</h1>\n"
|
||||
" <h1>TQ Printer Controller</h1>\n"
|
||||
" <p>ESP32-S3 local control page. This page calls the onboard REST API directly.</p>\n"
|
||||
"\n"
|
||||
" <label>API Key (optional)</label>\n"
|
||||
@@ -50,7 +50,7 @@ static const char *s_web_index =
|
||||
" </div>\n"
|
||||
"\n"
|
||||
" <label>Printer Name</label>\n"
|
||||
" <input id='printerName' type='text' value='lyfPrinter'>\n"
|
||||
" <input id='printerName' type='text' value='TQPrinter'>\n"
|
||||
" <div class='row'>\n"
|
||||
" <button id='btnConnect'>Connect Printer</button>\n"
|
||||
" <button id='btnAutoConnect' class='alt'>Auto Connect</button>\n"
|
||||
@@ -206,7 +206,7 @@ static const char *s_web_index =
|
||||
" document.getElementById('btnJobs').onclick = () => run(() => callApi('/v1/jobs', 'GET'));\n"
|
||||
"\n"
|
||||
" document.getElementById('btnConnect').onclick = () => run(() => callApi('/v1/printer/connect', 'POST', {\n"
|
||||
" name: printerNameEl.value.trim() || 'lyfPrinter',\n"
|
||||
" name: printerNameEl.value.trim() || 'TQPrinter',\n"
|
||||
" timeout_ms: 15000\n"
|
||||
" }));\n"
|
||||
"\n"
|
||||
@@ -249,7 +249,7 @@ static esp_err_t favicon_get(httpd_req_t *req) {
|
||||
|
||||
esp_err_t rest_server_start(void) {
|
||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
config.server_port = CONFIG_LYF_HTTP_PORT;
|
||||
config.server_port = CONFIG_TQ_HTTP_PORT;
|
||||
config.uri_match_fn = httpd_uri_match_wildcard;
|
||||
config.max_uri_handlers = 32;
|
||||
|
||||
@@ -301,6 +301,41 @@ esp_err_t rest_server_start(void) {
|
||||
};
|
||||
httpd_register_uri_handler(s_server, &status);
|
||||
|
||||
httpd_uri_t voice_status = {
|
||||
.uri = "/v1/voice/status",
|
||||
.method = HTTP_GET,
|
||||
.handler = rest_server_voice_status_get,
|
||||
};
|
||||
httpd_register_uri_handler(s_server, &voice_status);
|
||||
|
||||
httpd_uri_t voice_session_start = {
|
||||
.uri = "/v1/voice/session/start",
|
||||
.method = HTTP_POST,
|
||||
.handler = rest_server_voice_session_start_post,
|
||||
};
|
||||
httpd_register_uri_handler(s_server, &voice_session_start);
|
||||
|
||||
httpd_uri_t voice_session_stop = {
|
||||
.uri = "/v1/voice/session/stop",
|
||||
.method = HTTP_POST,
|
||||
.handler = rest_server_voice_session_stop_post,
|
||||
};
|
||||
httpd_register_uri_handler(s_server, &voice_session_stop);
|
||||
|
||||
httpd_uri_t voice_tap_start = {
|
||||
.uri = "/v1/voice/tap/start",
|
||||
.method = HTTP_POST,
|
||||
.handler = rest_server_voice_tap_start_post,
|
||||
};
|
||||
httpd_register_uri_handler(s_server, &voice_tap_start);
|
||||
|
||||
httpd_uri_t voice_tap_cancel = {
|
||||
.uri = "/v1/voice/tap/cancel",
|
||||
.method = HTTP_POST,
|
||||
.handler = rest_server_voice_tap_cancel_post,
|
||||
};
|
||||
httpd_register_uri_handler(s_server, &voice_tap_cancel);
|
||||
|
||||
httpd_uri_t print_raster = {
|
||||
.uri = "/v1/print/raster",
|
||||
.method = HTTP_POST,
|
||||
@@ -434,7 +469,7 @@ esp_err_t rest_server_start(void) {
|
||||
};
|
||||
httpd_register_uri_handler(s_server, &ota_upgrade);
|
||||
|
||||
ESP_LOGI(TAG, "REST server started on port %d", CONFIG_LYF_HTTP_PORT);
|
||||
ESP_LOGI(TAG, "REST server started on port %d", CONFIG_TQ_HTTP_PORT);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ static void *calloc_prefer_psram(size_t n, size_t size) {
|
||||
return ptr;
|
||||
}
|
||||
bool rest_server_auth_ok(httpd_req_t *req) {
|
||||
if (strlen(CONFIG_LYF_API_KEY) == 0) {
|
||||
if (strlen(CONFIG_TQ_API_KEY) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ bool rest_server_auth_ok(httpd_req_t *req) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return strcmp(buf, CONFIG_LYF_API_KEY) == 0;
|
||||
return strcmp(buf, CONFIG_TQ_API_KEY) == 0;
|
||||
}
|
||||
|
||||
esp_err_t rest_server_send_json(httpd_req_t *req, const char *status, cJSON *root) {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "printer_protocol.h"
|
||||
#include "system_runtime.h"
|
||||
#include "voice_interaction.h"
|
||||
static void fill_runtime_json(cJSON *root) {
|
||||
char ip[32] = {0};
|
||||
system_runtime_get_ip(ip, sizeof(ip));
|
||||
@@ -26,6 +27,23 @@ static void fill_runtime_json(cJSON *root) {
|
||||
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};
|
||||
voice_interaction_get_status(&voice);
|
||||
cJSON_AddBoolToObject(root, "voice_ready", voice.ready);
|
||||
cJSON_AddBoolToObject(root, "voice_session_active", voice.session_active);
|
||||
cJSON_AddBoolToObject(root, "voice_ws_connected", voice.ws_connected);
|
||||
cJSON_AddBoolToObject(root, "voice_started", voice.started);
|
||||
cJSON_AddBoolToObject(root, "voice_tap_active", voice.tap_active);
|
||||
cJSON_AddStringToObject(root,
|
||||
"voice_dialog_state",
|
||||
voice_interaction_dialog_state_str(voice.dialog_state));
|
||||
cJSON_AddStringToObject(root, "voice_task_id", voice.task_id);
|
||||
cJSON_AddStringToObject(root, "voice_dialog_id", voice.dialog_id);
|
||||
cJSON_AddStringToObject(root, "voice_last_error", voice.last_error);
|
||||
cJSON_AddNumberToObject(root, "voice_last_event_ms", (double)voice.last_event_ms);
|
||||
cJSON_AddNumberToObject(root, "voice_upstream_packets", (double)voice.upstream_packets);
|
||||
cJSON_AddNumberToObject(root, "voice_downstream_packets", (double)voice.downstream_packets);
|
||||
}
|
||||
|
||||
esp_err_t rest_server_health_get(httpd_req_t *req) {
|
||||
@@ -48,7 +66,7 @@ esp_err_t rest_server_connect_post(httpd_req_t *req) {
|
||||
}
|
||||
|
||||
char *body = NULL;
|
||||
char name[32] = "lyfPrinter";
|
||||
char name[32] = "TQPrinter";
|
||||
uint32_t timeout_ms = 15000;
|
||||
|
||||
if (req->content_len > 0) {
|
||||
|
||||
@@ -688,7 +688,7 @@ esp_err_t rest_server_print_receipt_post(httpd_req_t *req) {
|
||||
|
||||
const char *title = (cJSON_IsString(jtitle) && jtitle->valuestring != NULL)
|
||||
? jtitle->valuestring
|
||||
: "LYF RECEIPT";
|
||||
: "TQ RECEIPT";
|
||||
const char *footer = (cJSON_IsString(jfooter) && jfooter->valuestring != NULL)
|
||||
? jfooter->valuestring
|
||||
: "Thank you";
|
||||
|
||||
167
main/control_plane/src/rest_server_voice.c
Normal file
167
main/control_plane/src/rest_server_voice.c
Normal file
@@ -0,0 +1,167 @@
|
||||
#include "rest_server_internal.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "voice_interaction.h"
|
||||
|
||||
static void rest_server_add_voice_status(cJSON *root) {
|
||||
voice_interaction_status_t st = {0};
|
||||
voice_interaction_get_status(&st);
|
||||
|
||||
cJSON_AddBoolToObject(root, "voice_ready", st.ready);
|
||||
cJSON_AddBoolToObject(root, "voice_session_active", st.session_active);
|
||||
cJSON_AddBoolToObject(root, "voice_ws_connected", st.ws_connected);
|
||||
cJSON_AddBoolToObject(root, "voice_started", st.started);
|
||||
cJSON_AddBoolToObject(root, "voice_tap_active", st.tap_active);
|
||||
cJSON_AddStringToObject(root,
|
||||
"voice_dialog_state",
|
||||
voice_interaction_dialog_state_str(st.dialog_state));
|
||||
cJSON_AddStringToObject(root, "voice_task_id", st.task_id);
|
||||
cJSON_AddStringToObject(root, "voice_dialog_id", st.dialog_id);
|
||||
cJSON_AddStringToObject(root, "voice_last_error", st.last_error);
|
||||
cJSON_AddNumberToObject(root, "voice_last_event_ms", (double)st.last_event_ms);
|
||||
cJSON_AddNumberToObject(root, "voice_upstream_packets", (double)st.upstream_packets);
|
||||
cJSON_AddNumberToObject(root, "voice_downstream_packets", (double)st.downstream_packets);
|
||||
}
|
||||
|
||||
esp_err_t rest_server_voice_status_get(httpd_req_t *req) {
|
||||
if (!rest_server_auth_ok(req)) {
|
||||
return rest_server_send_error(req, "401 Unauthorized", "unauthorized");
|
||||
}
|
||||
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
cJSON_AddBoolToObject(root, "ok", true);
|
||||
rest_server_add_voice_status(root);
|
||||
|
||||
esp_err_t err = rest_server_send_json(req, "200 OK", root);
|
||||
cJSON_Delete(root);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t rest_server_voice_session_start_post(httpd_req_t *req) {
|
||||
if (!rest_server_auth_ok(req)) {
|
||||
return rest_server_send_error(req, "401 Unauthorized", "unauthorized");
|
||||
}
|
||||
|
||||
if (req->content_len > 0) {
|
||||
char *body = NULL;
|
||||
esp_err_t body_err = rest_server_read_body(req, &body);
|
||||
if (body_err != ESP_OK) {
|
||||
return rest_server_send_error(req, "400 Bad Request", "invalid request body");
|
||||
}
|
||||
free(body);
|
||||
}
|
||||
|
||||
char start_err[128] = {0};
|
||||
esp_err_t rc = voice_interaction_start(start_err, sizeof(start_err));
|
||||
if (rc != ESP_OK) {
|
||||
return rest_server_send_error(req,
|
||||
"409 Conflict",
|
||||
start_err[0] != '\0' ? start_err : "voice session start failed");
|
||||
}
|
||||
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
cJSON_AddBoolToObject(root, "ok", true);
|
||||
cJSON_AddStringToObject(root, "message", "voice session started");
|
||||
rest_server_add_voice_status(root);
|
||||
|
||||
esp_err_t err = rest_server_send_json(req, "200 OK", root);
|
||||
cJSON_Delete(root);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t rest_server_voice_session_stop_post(httpd_req_t *req) {
|
||||
if (!rest_server_auth_ok(req)) {
|
||||
return rest_server_send_error(req, "401 Unauthorized", "unauthorized");
|
||||
}
|
||||
|
||||
if (req->content_len > 0) {
|
||||
char *body = NULL;
|
||||
esp_err_t body_err = rest_server_read_body(req, &body);
|
||||
if (body_err != ESP_OK) {
|
||||
return rest_server_send_error(req, "400 Bad Request", "invalid request body");
|
||||
}
|
||||
free(body);
|
||||
}
|
||||
|
||||
char stop_err[128] = {0};
|
||||
esp_err_t rc = voice_interaction_stop(stop_err, sizeof(stop_err));
|
||||
if (rc != ESP_OK) {
|
||||
return rest_server_send_error(req,
|
||||
"409 Conflict",
|
||||
stop_err[0] != '\0' ? stop_err : "voice session stop failed");
|
||||
}
|
||||
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
cJSON_AddBoolToObject(root, "ok", true);
|
||||
cJSON_AddStringToObject(root, "message", "voice session stopped");
|
||||
rest_server_add_voice_status(root);
|
||||
|
||||
esp_err_t err = rest_server_send_json(req, "200 OK", root);
|
||||
cJSON_Delete(root);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t rest_server_voice_tap_start_post(httpd_req_t *req) {
|
||||
if (!rest_server_auth_ok(req)) {
|
||||
return rest_server_send_error(req, "401 Unauthorized", "unauthorized");
|
||||
}
|
||||
|
||||
if (req->content_len > 0) {
|
||||
char *body = NULL;
|
||||
esp_err_t body_err = rest_server_read_body(req, &body);
|
||||
if (body_err != ESP_OK) {
|
||||
return rest_server_send_error(req, "400 Bad Request", "invalid request body");
|
||||
}
|
||||
free(body);
|
||||
}
|
||||
|
||||
char tap_err[128] = {0};
|
||||
esp_err_t rc = voice_interaction_tap_start(tap_err, sizeof(tap_err));
|
||||
if (rc != ESP_OK) {
|
||||
return rest_server_send_error(req,
|
||||
"409 Conflict",
|
||||
tap_err[0] != '\0' ? tap_err : "tap start failed");
|
||||
}
|
||||
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
cJSON_AddBoolToObject(root, "ok", true);
|
||||
cJSON_AddStringToObject(root, "message", "tap started");
|
||||
rest_server_add_voice_status(root);
|
||||
|
||||
esp_err_t err = rest_server_send_json(req, "200 OK", root);
|
||||
cJSON_Delete(root);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t rest_server_voice_tap_cancel_post(httpd_req_t *req) {
|
||||
if (!rest_server_auth_ok(req)) {
|
||||
return rest_server_send_error(req, "401 Unauthorized", "unauthorized");
|
||||
}
|
||||
|
||||
if (req->content_len > 0) {
|
||||
char *body = NULL;
|
||||
esp_err_t body_err = rest_server_read_body(req, &body);
|
||||
if (body_err != ESP_OK) {
|
||||
return rest_server_send_error(req, "400 Bad Request", "invalid request body");
|
||||
}
|
||||
free(body);
|
||||
}
|
||||
|
||||
char tap_err[128] = {0};
|
||||
esp_err_t rc = voice_interaction_tap_cancel(tap_err, sizeof(tap_err));
|
||||
if (rc != ESP_OK) {
|
||||
return rest_server_send_error(req,
|
||||
"409 Conflict",
|
||||
tap_err[0] != '\0' ? tap_err : "tap cancel failed");
|
||||
}
|
||||
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
cJSON_AddBoolToObject(root, "ok", true);
|
||||
cJSON_AddStringToObject(root, "message", "tap canceled");
|
||||
rest_server_add_voice_status(root);
|
||||
|
||||
esp_err_t err = rest_server_send_json(req, "200 OK", root);
|
||||
cJSON_Delete(root);
|
||||
return err;
|
||||
}
|
||||
Reference in New Issue
Block a user