init
This commit is contained in:
659
main/control_plane/src/rest_server_print.c
Normal file
659
main/control_plane/src/rest_server_print.c
Normal file
@@ -0,0 +1,659 @@
|
||||
#include "rest_server_internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "printer_protocol.h"
|
||||
#include "raster_tools.h"
|
||||
static esp_err_t submit_raster_job_and_reply(httpd_req_t *req,
|
||||
const uint8_t *raw,
|
||||
size_t raw_len,
|
||||
uint16_t width,
|
||||
uint16_t height,
|
||||
const char *density,
|
||||
const char *warning) {
|
||||
char submit_err[128] = {0};
|
||||
uint32_t job_id = 0;
|
||||
esp_err_t submit_rc = printer_protocol_submit_raster_job(raw,
|
||||
raw_len,
|
||||
width,
|
||||
height,
|
||||
density,
|
||||
&job_id,
|
||||
submit_err,
|
||||
sizeof(submit_err));
|
||||
if (submit_rc != ESP_OK) {
|
||||
return rest_server_send_error(req,
|
||||
"400 Bad Request",
|
||||
submit_err[0] != '\0' ? submit_err : "submit failed");
|
||||
}
|
||||
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
cJSON_AddBoolToObject(root, "ok", true);
|
||||
cJSON_AddNumberToObject(root, "job_id", job_id);
|
||||
cJSON_AddStringToObject(root, "state", "queued");
|
||||
if (warning != NULL && warning[0] != '\0') {
|
||||
cJSON_AddStringToObject(root, "warning", warning);
|
||||
}
|
||||
|
||||
esp_err_t err = rest_server_send_json(req, "202 Accepted", root);
|
||||
cJSON_Delete(root);
|
||||
return err;
|
||||
}
|
||||
|
||||
static esp_err_t decode_image_json_to_raster(cJSON *json,
|
||||
uint16_t *out_width,
|
||||
uint16_t *out_height,
|
||||
uint8_t **out_raster,
|
||||
size_t *out_len,
|
||||
char *err,
|
||||
size_t err_len) {
|
||||
if (json == NULL || out_width == NULL || out_height == NULL || out_raster == NULL || out_len == NULL) {
|
||||
if (err != NULL && err_len > 0) {
|
||||
snprintf(err, err_len, "invalid args");
|
||||
}
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
*out_width = 0;
|
||||
*out_height = 0;
|
||||
*out_raster = NULL;
|
||||
*out_len = 0;
|
||||
|
||||
cJSON *jwidth = cJSON_GetObjectItemCaseSensitive(json, "width");
|
||||
cJSON *jheight = cJSON_GetObjectItemCaseSensitive(json, "height");
|
||||
cJSON *jencoding = cJSON_GetObjectItemCaseSensitive(json, "encoding");
|
||||
cJSON *jdata = cJSON_GetObjectItemCaseSensitive(json, "data");
|
||||
|
||||
if (!cJSON_IsNumber(jwidth) || !cJSON_IsNumber(jheight) ||
|
||||
!cJSON_IsString(jencoding) || !cJSON_IsString(jdata)) {
|
||||
if (err != NULL && err_len > 0) {
|
||||
snprintf(err, err_len, "missing required image fields");
|
||||
}
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
uint16_t width = (uint16_t)jwidth->valuedouble;
|
||||
uint16_t height = (uint16_t)jheight->valuedouble;
|
||||
if (width == 0 || height == 0) {
|
||||
if (err != NULL && err_len > 0) {
|
||||
snprintf(err, err_len, "invalid image size");
|
||||
}
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (strcmp(jencoding->valuestring, "base64_msb_1bpp") == 0) {
|
||||
uint8_t *raw = NULL;
|
||||
size_t raw_len = 0;
|
||||
esp_err_t b64_rc = rest_server_base64_decode_alloc(jdata->valuestring, &raw, &raw_len);
|
||||
if (b64_rc != ESP_OK) {
|
||||
if (err != NULL && err_len > 0) {
|
||||
snprintf(err, err_len, "invalid base64");
|
||||
}
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
*out_width = width;
|
||||
*out_height = height;
|
||||
*out_raster = raw;
|
||||
*out_len = raw_len;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (strcmp(jencoding->valuestring, "base64_gray8") == 0) {
|
||||
uint8_t *gray = NULL;
|
||||
size_t gray_len = 0;
|
||||
esp_err_t b64_rc = rest_server_base64_decode_alloc(jdata->valuestring, &gray, &gray_len);
|
||||
if (b64_rc != ESP_OK) {
|
||||
if (err != NULL && err_len > 0) {
|
||||
snprintf(err, err_len, "invalid base64");
|
||||
}
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
size_t expected = (size_t)width * height;
|
||||
if (gray_len != expected) {
|
||||
free(gray);
|
||||
if (err != NULL && err_len > 0) {
|
||||
snprintf(err, err_len, "gray8 size mismatch");
|
||||
}
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
cJSON *jscale = cJSON_GetObjectItemCaseSensitive(json, "scale_to_width");
|
||||
cJSON *jthreshold = cJSON_GetObjectItemCaseSensitive(json, "threshold");
|
||||
cJSON *jinvert = cJSON_GetObjectItemCaseSensitive(json, "invert");
|
||||
cJSON *jmaxh = cJSON_GetObjectItemCaseSensitive(json, "max_height");
|
||||
|
||||
bool scale_to_width = rest_server_json_bool_with_default(jscale, true);
|
||||
bool invert = rest_server_json_bool_with_default(jinvert, false);
|
||||
uint8_t threshold = 160;
|
||||
uint16_t max_height = 2200;
|
||||
if (cJSON_IsNumber(jthreshold) && jthreshold->valuedouble >= 0 && jthreshold->valuedouble <= 255) {
|
||||
threshold = (uint8_t)jthreshold->valuedouble;
|
||||
}
|
||||
if (cJSON_IsNumber(jmaxh) && jmaxh->valuedouble >= 64 && jmaxh->valuedouble <= 3000) {
|
||||
max_height = (uint16_t)jmaxh->valuedouble;
|
||||
}
|
||||
|
||||
uint16_t out_w = 0;
|
||||
uint16_t out_h = 0;
|
||||
uint8_t *raster = NULL;
|
||||
size_t raster_len = 0;
|
||||
esp_err_t conv_rc = raster_tools_convert_gray8_to_raster_384(gray,
|
||||
width,
|
||||
height,
|
||||
scale_to_width,
|
||||
threshold,
|
||||
invert,
|
||||
max_height,
|
||||
&out_w,
|
||||
&out_h,
|
||||
&raster,
|
||||
&raster_len,
|
||||
err,
|
||||
err_len);
|
||||
free(gray);
|
||||
if (conv_rc != ESP_OK) {
|
||||
return conv_rc;
|
||||
}
|
||||
|
||||
*out_width = out_w;
|
||||
*out_height = out_h;
|
||||
*out_raster = raster;
|
||||
*out_len = raster_len;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (err != NULL && err_len > 0) {
|
||||
snprintf(err, err_len, "unsupported encoding");
|
||||
}
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_err_t rest_server_print_raster_post(httpd_req_t *req) {
|
||||
if (!rest_server_auth_ok(req)) {
|
||||
return rest_server_send_error(req, "401 Unauthorized", "unauthorized");
|
||||
}
|
||||
|
||||
char *body = NULL;
|
||||
esp_err_t body_err = rest_server_read_body(req, &body);
|
||||
if (body_err != ESP_OK) {
|
||||
return rest_server_send_error(req, "400 Bad Request", "invalid request body");
|
||||
}
|
||||
|
||||
cJSON *json = cJSON_Parse(body);
|
||||
free(body);
|
||||
if (json == NULL) {
|
||||
return rest_server_send_error(req, "400 Bad Request", "invalid json");
|
||||
}
|
||||
|
||||
cJSON *jwidth = cJSON_GetObjectItemCaseSensitive(json, "width");
|
||||
cJSON *jheight = cJSON_GetObjectItemCaseSensitive(json, "height");
|
||||
cJSON *jencoding = cJSON_GetObjectItemCaseSensitive(json, "encoding");
|
||||
cJSON *jdata = cJSON_GetObjectItemCaseSensitive(json, "data");
|
||||
cJSON *jdensity = cJSON_GetObjectItemCaseSensitive(json, "density");
|
||||
|
||||
if (!cJSON_IsNumber(jwidth) || !cJSON_IsNumber(jheight) ||
|
||||
!cJSON_IsString(jencoding) || !cJSON_IsString(jdata)) {
|
||||
cJSON_Delete(json);
|
||||
return rest_server_send_error(req, "400 Bad Request", "missing required fields");
|
||||
}
|
||||
|
||||
if (strcmp(jencoding->valuestring, "base64_msb_1bpp") != 0) {
|
||||
cJSON_Delete(json);
|
||||
return rest_server_send_error(req, "400 Bad Request", "unsupported encoding");
|
||||
}
|
||||
|
||||
const char *density = (cJSON_IsString(jdensity) && jdensity->valuestring != NULL)
|
||||
? jdensity->valuestring
|
||||
: "中等";
|
||||
|
||||
uint8_t *raw = NULL;
|
||||
size_t raw_len = 0;
|
||||
esp_err_t b64_rc = rest_server_base64_decode_alloc(jdata->valuestring, &raw, &raw_len);
|
||||
if (b64_rc != ESP_OK) {
|
||||
cJSON_Delete(json);
|
||||
return rest_server_send_error(req, "400 Bad Request", "invalid base64");
|
||||
}
|
||||
|
||||
esp_err_t submit_rc = submit_raster_job_and_reply(req,
|
||||
raw,
|
||||
raw_len,
|
||||
(uint16_t)jwidth->valuedouble,
|
||||
(uint16_t)jheight->valuedouble,
|
||||
density,
|
||||
NULL);
|
||||
free(raw);
|
||||
cJSON_Delete(json);
|
||||
return submit_rc;
|
||||
}
|
||||
|
||||
esp_err_t rest_server_print_image_post(httpd_req_t *req) {
|
||||
if (!rest_server_auth_ok(req)) {
|
||||
return rest_server_send_error(req, "401 Unauthorized", "unauthorized");
|
||||
}
|
||||
|
||||
char *body = NULL;
|
||||
esp_err_t body_err = rest_server_read_body(req, &body);
|
||||
if (body_err != ESP_OK) {
|
||||
return rest_server_send_error(req, "400 Bad Request", "invalid request body");
|
||||
}
|
||||
|
||||
cJSON *json = cJSON_Parse(body);
|
||||
free(body);
|
||||
if (json == NULL) {
|
||||
return rest_server_send_error(req, "400 Bad Request", "invalid json");
|
||||
}
|
||||
|
||||
cJSON *jdensity = cJSON_GetObjectItemCaseSensitive(json, "density");
|
||||
const char *density = (cJSON_IsString(jdensity) && jdensity->valuestring != NULL)
|
||||
? jdensity->valuestring
|
||||
: "中等";
|
||||
|
||||
uint16_t width = 0;
|
||||
uint16_t height = 0;
|
||||
uint8_t *raster = NULL;
|
||||
size_t raster_len = 0;
|
||||
char decode_err[128] = {0};
|
||||
esp_err_t decode_rc = decode_image_json_to_raster(json,
|
||||
&width,
|
||||
&height,
|
||||
&raster,
|
||||
&raster_len,
|
||||
decode_err,
|
||||
sizeof(decode_err));
|
||||
cJSON_Delete(json);
|
||||
if (decode_rc != ESP_OK) {
|
||||
return rest_server_send_error(req,
|
||||
"400 Bad Request",
|
||||
decode_err[0] != '\0' ? decode_err : "decode image failed");
|
||||
}
|
||||
|
||||
esp_err_t submit_rc = submit_raster_job_and_reply(req,
|
||||
raster,
|
||||
raster_len,
|
||||
width,
|
||||
height,
|
||||
density,
|
||||
NULL);
|
||||
free(raster);
|
||||
return submit_rc;
|
||||
}
|
||||
|
||||
esp_err_t rest_server_print_qr_post(httpd_req_t *req) {
|
||||
if (!rest_server_auth_ok(req)) {
|
||||
return rest_server_send_error(req, "401 Unauthorized", "unauthorized");
|
||||
}
|
||||
|
||||
char *body = NULL;
|
||||
esp_err_t body_err = rest_server_read_body(req, &body);
|
||||
if (body_err != ESP_OK) {
|
||||
return rest_server_send_error(req, "400 Bad Request", "invalid request body");
|
||||
}
|
||||
|
||||
cJSON *json = cJSON_Parse(body);
|
||||
free(body);
|
||||
if (json == NULL) {
|
||||
return rest_server_send_error(req, "400 Bad Request", "invalid json");
|
||||
}
|
||||
|
||||
cJSON *jtext = cJSON_GetObjectItemCaseSensitive(json, "text");
|
||||
cJSON *jdensity = cJSON_GetObjectItemCaseSensitive(json, "density");
|
||||
cJSON *jecc = cJSON_GetObjectItemCaseSensitive(json, "ecc");
|
||||
cJSON *jscale = cJSON_GetObjectItemCaseSensitive(json, "module_scale");
|
||||
cJSON *jmargin = cJSON_GetObjectItemCaseSensitive(json, "margin_modules");
|
||||
cJSON *jmaxh = cJSON_GetObjectItemCaseSensitive(json, "max_height");
|
||||
|
||||
if (!cJSON_IsString(jtext) || jtext->valuestring == NULL || jtext->valuestring[0] == '\0') {
|
||||
cJSON_Delete(json);
|
||||
return rest_server_send_error(req, "400 Bad Request", "text is required");
|
||||
}
|
||||
|
||||
const char *density = (cJSON_IsString(jdensity) && jdensity->valuestring != NULL)
|
||||
? jdensity->valuestring
|
||||
: "中等";
|
||||
|
||||
uint8_t ecc_level = 3; /* default H */
|
||||
if (cJSON_IsString(jecc) && jecc->valuestring != NULL) {
|
||||
if (strcasecmp(jecc->valuestring, "L") == 0) {
|
||||
ecc_level = 0;
|
||||
} else if (strcasecmp(jecc->valuestring, "M") == 0) {
|
||||
ecc_level = 1;
|
||||
} else if (strcasecmp(jecc->valuestring, "Q") == 0) {
|
||||
ecc_level = 2;
|
||||
} else if (strcasecmp(jecc->valuestring, "H") == 0) {
|
||||
ecc_level = 3;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t module_scale = 0;
|
||||
uint8_t margin_modules = 2;
|
||||
uint16_t max_height = 2200;
|
||||
if (cJSON_IsNumber(jscale) && jscale->valuedouble >= 0 && jscale->valuedouble <= 16) {
|
||||
module_scale = (uint8_t)jscale->valuedouble;
|
||||
}
|
||||
if (cJSON_IsNumber(jmargin) && jmargin->valuedouble >= 1 && jmargin->valuedouble <= 12) {
|
||||
margin_modules = (uint8_t)jmargin->valuedouble;
|
||||
}
|
||||
if (cJSON_IsNumber(jmaxh) && jmaxh->valuedouble >= 64 && jmaxh->valuedouble <= 3000) {
|
||||
max_height = (uint16_t)jmaxh->valuedouble;
|
||||
}
|
||||
|
||||
uint16_t width = 0;
|
||||
uint16_t height = 0;
|
||||
uint8_t *raster = NULL;
|
||||
size_t raster_len = 0;
|
||||
char render_msg[128] = {0};
|
||||
esp_err_t qr_rc = raster_tools_render_qr_384(jtext->valuestring,
|
||||
module_scale,
|
||||
margin_modules,
|
||||
ecc_level,
|
||||
max_height,
|
||||
&width,
|
||||
&height,
|
||||
&raster,
|
||||
&raster_len,
|
||||
render_msg,
|
||||
sizeof(render_msg));
|
||||
cJSON_Delete(json);
|
||||
if (qr_rc != ESP_OK) {
|
||||
return rest_server_send_error(req, "400 Bad Request", render_msg[0] != '\0' ? render_msg : "qr render failed");
|
||||
}
|
||||
|
||||
esp_err_t submit_rc = submit_raster_job_and_reply(req,
|
||||
raster,
|
||||
raster_len,
|
||||
width,
|
||||
height,
|
||||
density,
|
||||
NULL);
|
||||
free(raster);
|
||||
return submit_rc;
|
||||
}
|
||||
|
||||
esp_err_t rest_server_print_label_post(httpd_req_t *req) {
|
||||
if (!rest_server_auth_ok(req)) {
|
||||
return rest_server_send_error(req, "401 Unauthorized", "unauthorized");
|
||||
}
|
||||
|
||||
char *body = NULL;
|
||||
esp_err_t body_err = rest_server_read_body(req, &body);
|
||||
if (body_err != ESP_OK) {
|
||||
return rest_server_send_error(req, "400 Bad Request", "invalid request body");
|
||||
}
|
||||
|
||||
cJSON *json = cJSON_Parse(body);
|
||||
free(body);
|
||||
if (json == NULL) {
|
||||
return rest_server_send_error(req, "400 Bad Request", "invalid json");
|
||||
}
|
||||
|
||||
cJSON *jdensity = cJSON_GetObjectItemCaseSensitive(json, "density");
|
||||
cJSON *jgap = cJSON_GetObjectItemCaseSensitive(json, "gap_move_before");
|
||||
cJSON *joffset = cJSON_GetObjectItemCaseSensitive(json, "offset_tenths_mm");
|
||||
|
||||
bool gap_move_before = rest_server_json_bool_with_default(jgap, true);
|
||||
bool has_offset = cJSON_IsNumber(joffset);
|
||||
uint8_t offset_value = 0;
|
||||
if (has_offset) {
|
||||
if (joffset->valuedouble < 0 || joffset->valuedouble > 254) {
|
||||
cJSON_Delete(json);
|
||||
return rest_server_send_error(req, "400 Bad Request", "offset_tenths_mm must be 0..254");
|
||||
}
|
||||
offset_value = (uint8_t)joffset->valuedouble;
|
||||
}
|
||||
|
||||
if (has_offset) {
|
||||
char cmd_err[128] = {0};
|
||||
esp_err_t offset_rc = printer_protocol_set_label_offset(offset_value, 3000, cmd_err, sizeof(cmd_err));
|
||||
if (offset_rc != ESP_OK) {
|
||||
cJSON_Delete(json);
|
||||
return rest_server_send_error(req,
|
||||
"409 Conflict",
|
||||
cmd_err[0] != '\0' ? cmd_err : "set label offset failed");
|
||||
}
|
||||
}
|
||||
|
||||
if (gap_move_before) {
|
||||
char cmd_err[128] = {0};
|
||||
esp_err_t gap_rc = printer_protocol_gap_move(5000, cmd_err, sizeof(cmd_err));
|
||||
if (gap_rc != ESP_OK) {
|
||||
cJSON_Delete(json);
|
||||
return rest_server_send_error(req,
|
||||
"409 Conflict",
|
||||
cmd_err[0] != '\0' ? cmd_err : "gap move failed");
|
||||
}
|
||||
}
|
||||
|
||||
const char *density = (cJSON_IsString(jdensity) && jdensity->valuestring != NULL)
|
||||
? jdensity->valuestring
|
||||
: "中等";
|
||||
|
||||
uint16_t width = 0;
|
||||
uint16_t height = 0;
|
||||
uint8_t *raster = NULL;
|
||||
size_t raster_len = 0;
|
||||
char decode_err[128] = {0};
|
||||
esp_err_t decode_rc = decode_image_json_to_raster(json,
|
||||
&width,
|
||||
&height,
|
||||
&raster,
|
||||
&raster_len,
|
||||
decode_err,
|
||||
sizeof(decode_err));
|
||||
cJSON_Delete(json);
|
||||
if (decode_rc != ESP_OK) {
|
||||
return rest_server_send_error(req,
|
||||
"400 Bad Request",
|
||||
decode_err[0] != '\0' ? decode_err : "decode image failed");
|
||||
}
|
||||
|
||||
esp_err_t submit_rc = submit_raster_job_and_reply(req,
|
||||
raster,
|
||||
raster_len,
|
||||
width,
|
||||
height,
|
||||
density,
|
||||
NULL);
|
||||
free(raster);
|
||||
return submit_rc;
|
||||
}
|
||||
|
||||
esp_err_t rest_server_print_text_post(httpd_req_t *req) {
|
||||
if (!rest_server_auth_ok(req)) {
|
||||
return rest_server_send_error(req, "401 Unauthorized", "unauthorized");
|
||||
}
|
||||
|
||||
char *body = NULL;
|
||||
esp_err_t body_err = rest_server_read_body(req, &body);
|
||||
if (body_err != ESP_OK) {
|
||||
return rest_server_send_error(req, "400 Bad Request", "invalid request body");
|
||||
}
|
||||
|
||||
cJSON *json = cJSON_Parse(body);
|
||||
free(body);
|
||||
if (json == NULL) {
|
||||
return rest_server_send_error(req, "400 Bad Request", "invalid json");
|
||||
}
|
||||
|
||||
cJSON *jtext = cJSON_GetObjectItemCaseSensitive(json, "text");
|
||||
cJSON *jdensity = cJSON_GetObjectItemCaseSensitive(json, "density");
|
||||
cJSON *jscale = cJSON_GetObjectItemCaseSensitive(json, "scale");
|
||||
cJSON *jline = cJSON_GetObjectItemCaseSensitive(json, "line_spacing");
|
||||
cJSON *jmaxh = cJSON_GetObjectItemCaseSensitive(json, "max_height");
|
||||
|
||||
if (!cJSON_IsString(jtext) || jtext->valuestring == NULL) {
|
||||
cJSON_Delete(json);
|
||||
return rest_server_send_error(req, "400 Bad Request", "text is required");
|
||||
}
|
||||
|
||||
const char *density = (cJSON_IsString(jdensity) && jdensity->valuestring != NULL)
|
||||
? jdensity->valuestring
|
||||
: "中等";
|
||||
uint8_t scale = 2;
|
||||
uint8_t line_spacing = 2;
|
||||
uint16_t max_height = 2000;
|
||||
|
||||
if (cJSON_IsNumber(jscale) && jscale->valuedouble >= 1 && jscale->valuedouble <= 6) {
|
||||
scale = (uint8_t)jscale->valuedouble;
|
||||
}
|
||||
if (cJSON_IsNumber(jline) && jline->valuedouble >= 0 && jline->valuedouble <= 12) {
|
||||
line_spacing = (uint8_t)jline->valuedouble;
|
||||
}
|
||||
if (cJSON_IsNumber(jmaxh) && jmaxh->valuedouble >= 64 && jmaxh->valuedouble <= 3000) {
|
||||
max_height = (uint16_t)jmaxh->valuedouble;
|
||||
}
|
||||
|
||||
uint16_t width = 0;
|
||||
uint16_t height = 0;
|
||||
uint8_t *raster = NULL;
|
||||
size_t raster_len = 0;
|
||||
char render_msg[128] = {0};
|
||||
|
||||
esp_err_t render_rc = raster_tools_render_text_384(jtext->valuestring,
|
||||
scale,
|
||||
line_spacing,
|
||||
max_height,
|
||||
&width,
|
||||
&height,
|
||||
&raster,
|
||||
&raster_len,
|
||||
render_msg,
|
||||
sizeof(render_msg));
|
||||
cJSON_Delete(json);
|
||||
|
||||
if (render_rc != ESP_OK) {
|
||||
return rest_server_send_error(req, "400 Bad Request", render_msg[0] != '\0' ? render_msg : "text render failed");
|
||||
}
|
||||
|
||||
esp_err_t submit_rc = submit_raster_job_and_reply(req,
|
||||
raster,
|
||||
raster_len,
|
||||
width,
|
||||
height,
|
||||
density,
|
||||
render_msg);
|
||||
free(raster);
|
||||
return submit_rc;
|
||||
}
|
||||
|
||||
esp_err_t rest_server_print_receipt_post(httpd_req_t *req) {
|
||||
if (!rest_server_auth_ok(req)) {
|
||||
return rest_server_send_error(req, "401 Unauthorized", "unauthorized");
|
||||
}
|
||||
|
||||
char *body = NULL;
|
||||
esp_err_t body_err = rest_server_read_body(req, &body);
|
||||
if (body_err != ESP_OK) {
|
||||
return rest_server_send_error(req, "400 Bad Request", "invalid request body");
|
||||
}
|
||||
|
||||
cJSON *json = cJSON_Parse(body);
|
||||
free(body);
|
||||
if (json == NULL) {
|
||||
return rest_server_send_error(req, "400 Bad Request", "invalid json");
|
||||
}
|
||||
|
||||
cJSON *jtitle = cJSON_GetObjectItemCaseSensitive(json, "title");
|
||||
cJSON *jitems = cJSON_GetObjectItemCaseSensitive(json, "items");
|
||||
cJSON *jfooter = cJSON_GetObjectItemCaseSensitive(json, "footer");
|
||||
cJSON *jdensity = cJSON_GetObjectItemCaseSensitive(json, "density");
|
||||
cJSON *jscale = cJSON_GetObjectItemCaseSensitive(json, "scale");
|
||||
|
||||
const char *title = (cJSON_IsString(jtitle) && jtitle->valuestring != NULL)
|
||||
? jtitle->valuestring
|
||||
: "LYF RECEIPT";
|
||||
const char *footer = (cJSON_IsString(jfooter) && jfooter->valuestring != NULL)
|
||||
? jfooter->valuestring
|
||||
: "Thank you";
|
||||
const char *density = (cJSON_IsString(jdensity) && jdensity->valuestring != NULL)
|
||||
? jdensity->valuestring
|
||||
: "中等";
|
||||
uint8_t scale = 2;
|
||||
if (cJSON_IsNumber(jscale) && jscale->valuedouble >= 1 && jscale->valuedouble <= 4) {
|
||||
scale = (uint8_t)jscale->valuedouble;
|
||||
}
|
||||
|
||||
size_t text_cap = 8192;
|
||||
char *text = (char *)calloc(1, text_cap);
|
||||
if (text == NULL) {
|
||||
cJSON_Delete(json);
|
||||
return rest_server_send_error(req, "500 Internal Server Error", "no memory");
|
||||
}
|
||||
|
||||
size_t off = 0;
|
||||
rest_server_appendf(text, text_cap, &off, "%s\n", title);
|
||||
rest_server_appendf(text, text_cap, &off, "--------------------------------\n");
|
||||
|
||||
double total = 0.0;
|
||||
if (cJSON_IsArray(jitems)) {
|
||||
int n = cJSON_GetArraySize(jitems);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
cJSON *it = cJSON_GetArrayItem(jitems, i);
|
||||
if (!cJSON_IsObject(it)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cJSON *jname = cJSON_GetObjectItemCaseSensitive(it, "name");
|
||||
cJSON *jqty = cJSON_GetObjectItemCaseSensitive(it, "qty");
|
||||
cJSON *jprice = cJSON_GetObjectItemCaseSensitive(it, "price");
|
||||
|
||||
const char *name = (cJSON_IsString(jname) && jname->valuestring != NULL)
|
||||
? jname->valuestring
|
||||
: "item";
|
||||
int qty = cJSON_IsNumber(jqty) ? (int)jqty->valuedouble : 1;
|
||||
double price = cJSON_IsNumber(jprice) ? jprice->valuedouble : 0.0;
|
||||
double line_total = qty * price;
|
||||
total += line_total;
|
||||
|
||||
rest_server_appendf(text,
|
||||
text_cap,
|
||||
&off,
|
||||
"%-16.16s x%-3d %8.2f\n",
|
||||
name,
|
||||
qty,
|
||||
line_total);
|
||||
}
|
||||
} else {
|
||||
rest_server_appendf(text, text_cap, &off, "(no items)\n");
|
||||
}
|
||||
|
||||
rest_server_appendf(text, text_cap, &off, "--------------------------------\n");
|
||||
rest_server_appendf(text, text_cap, &off, "TOTAL: %.2f\n", total);
|
||||
rest_server_appendf(text, text_cap, &off, "%s\n", footer);
|
||||
|
||||
uint16_t width = 0;
|
||||
uint16_t height = 0;
|
||||
uint8_t *raster = NULL;
|
||||
size_t raster_len = 0;
|
||||
char render_msg[128] = {0};
|
||||
|
||||
esp_err_t render_rc = raster_tools_render_text_384(text,
|
||||
scale,
|
||||
2,
|
||||
2200,
|
||||
&width,
|
||||
&height,
|
||||
&raster,
|
||||
&raster_len,
|
||||
render_msg,
|
||||
sizeof(render_msg));
|
||||
free(text);
|
||||
cJSON_Delete(json);
|
||||
|
||||
if (render_rc != ESP_OK) {
|
||||
return rest_server_send_error(req, "400 Bad Request", render_msg[0] != '\0' ? render_msg : "receipt render failed");
|
||||
}
|
||||
|
||||
esp_err_t submit_rc = submit_raster_job_and_reply(req,
|
||||
raster,
|
||||
raster_len,
|
||||
width,
|
||||
height,
|
||||
density,
|
||||
render_msg);
|
||||
free(raster);
|
||||
return submit_rc;
|
||||
}
|
||||
Reference in New Issue
Block a user