diff --git a/.config b/.config index 2194d37..f49f7f6 100644 --- a/.config +++ b/.config @@ -945,6 +945,7 @@ CONFIG_PKG_LITTLEFS_VER="v2.11.2" # CONFIG_PKG_USING_GD32_ARM_CMSIS_DRIVER is not set # CONFIG_PKG_USING_GD32_ARM_SERIES_DRIVER is not set # CONFIG_PKG_USING_GD32_RISCV_SERIES_DRIVER is not set +# CONFIG_PKG_USING_GD32VW55X_WIFI is not set # end of GD32 Drivers # @@ -1230,7 +1231,12 @@ CONFIG_PKG_RS485_VER="v1.06" # CONFIG_PKG_USING_TINYSQUARE is not set # end of entertainment: terminal games and other interesting software packages -# CONFIG_PKG_USING_LIBCSV is not set +CONFIG_PKG_USING_LIBCSV=y +CONFIG_PKG_LIBCSV_PATH="/packages/misc/libcsv" +CONFIG_PKG_USING_LIBCSV_V303=y +# CONFIG_PKG_USING_LIBCSV_LATEST_VERSION is not set +CONFIG_PKG_LIBCSV_VER="v3.0.3" +# CONFIG_LIBCSV_USING_DEMO is not set # CONFIG_PKG_USING_OPTPARSE is not set # CONFIG_PKG_USING_FASTLZ is not set # CONFIG_PKG_USING_MINILZO is not set diff --git a/.cproject b/.cproject index b85ef55..76aef81 100644 --- a/.cproject +++ b/.cproject @@ -147,6 +147,7 @@ + @@ -333,6 +334,7 @@ + @@ -491,6 +493,7 @@ + @@ -655,6 +658,7 @@ + @@ -812,6 +816,7 @@ + @@ -978,6 +983,7 @@ + @@ -1143,6 +1149,7 @@ + @@ -1310,6 +1317,7 @@ + @@ -1464,6 +1472,7 @@ + @@ -1506,7 +1515,7 @@ - + diff --git a/.settings/.rtmenus b/.settings/.rtmenus index 876b936..6e16816 100644 Binary files a/.settings/.rtmenus and b/.settings/.rtmenus differ diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml index 4b8021f..971f0cd 100644 --- a/.settings/language.settings.xml +++ b/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/applications/data/DATA_comm.c b/applications/data/DATA_comm.c index d2d142d..b56cf49 100644 --- a/applications/data/DATA_comm.c +++ b/applications/data/DATA_comm.c @@ -30,7 +30,7 @@ struct rt_messagequeue *response_mq; // Proc → UART char cjson_falg=0;//是否解析cjson char *json_buffer=NULL;// -char select_data[1024] = {0}; +char select_data[4096] = {0}; /** * 截取两个指定子串之间的内容 * @param src 源字符串 @@ -378,7 +378,8 @@ void pasre_DAT(const char *api, const char *json_str) } else if (strcmp(api, "SC822") == 0) { - db_send_select(DB_CMD_SELECT, "SELECT WorkOrder,ReDye,ProgramName FROM WorkOrder LIMIT 10;", 500,select_data); + db_send_select(DB_CMD_SELECT, "SELECT * FROM WorkOrder WHERE State=101 LIMIT 16;", 500,select_data); + cJSON_AddItemToObject(dat,"ERR",cJSON_CreateString(select_data)); } else if (strcmp(api, "SC827") == 0) diff --git a/applications/lvgl/ui_data_labels.c b/applications/lvgl/ui_data_labels.c index 1223773..3ef48aa 100644 --- a/applications/lvgl/ui_data_labels.c +++ b/applications/lvgl/ui_data_labels.c @@ -21,6 +21,7 @@ #include #include "lvgl.h" #include +#include "libcsv.h" // 全局或静态数组 char buf[8]; diff --git a/applications/sql/DB_SQLite.c b/applications/sql/DB_SQLite.c index e9382c3..ac19fa4 100644 --- a/applications/sql/DB_SQLite.c +++ b/applications/sql/DB_SQLite.c @@ -14,6 +14,7 @@ #include "DB_SQLite.h" #include "sqlite3.h" #include +#include "libcsv.h" #define DB_NAME "/sddisk/SC828.db" int db_HelperInit; @@ -96,34 +97,136 @@ static void return_disabled(struct db_command *cmd) { /** * @brief SELECT 查询回调函数 */ -static int callback(void *result_str, int argc, char **argv, char **azColName) { - //char *buf = (char *)result_str; - int written = rt_strlen(result_str); // 当前已写入长度(假设 buf 是 \0 结尾的) - int remaining = MAX_RESULT_LEN - written - 1; // -1 留给最终 \0 +// 辅助函数:将单个字段转义为 CSV 字符串(原地写入 out,需足够大) +static int csv_escape_field(const char *field, char *out, int out_size) +{ + if (!field) { + field = ""; + } + + // 检查是否需要引号:包含 delimiter(,)、quote(")、换行(\n\r) 或首尾空格 + int need_quote = 0; + const char *p = field; + while (*p) { + if (*p == ',' || *p == '"' || *p == '\n' || *p == '\r') { + need_quote = 1; + break; + } + p++; + } - if (remaining <= 0) { - return 0; // 缓冲区已满,不再写入 + // 首尾空格也建议加引号(可选) + if (!need_quote && (field[0] == ' ' || field[rt_strlen(field)-1] == ' ')) { + need_quote = 1; } - for (int i = 0; i < argc && remaining > 0; i++) { - const char *val = argv[i] ? argv[i] : "NULL"; - // 预估所需长度(保守估计) - int needed = rt_strlen(azColName[i]) + rt_strlen(val) + 2; // + "=...\0" 至少 2 字节(= 和 |) + if (!need_quote) { + // 直接复制 + int len = rt_strlen(field); + if (len >= out_size) return -1; + rt_memcpy(out, field, len + 1); + return len; + } - if (needed > remaining) { - break; // 空间不足,停止 + // 需要加引号:先写开头引号 + if (out_size < 2) return -1; + *out++ = '"'; + out_size--; + + // 复制内容,双写引号 + p = field; + int written = 1; // 已写入开头 " + while (*p && out_size > 1) { + if (*p == '"') { + if (out_size < 3) return -1; // 需要 ""\0 + *out++ = '"'; + *out++ = '"'; + out_size -= 2; + written += 2; + } else { + *out++ = *p; + out_size--; + written++; } + p++; + } + + if (*p != '\0') return -1; // 缓冲区不足 + + // 写结尾引号 + if (out_size < 2) return -1; + *out++ = '"'; + *out = '\0'; + return written + 1; // +1 for closing " +} - int n = rt_snprintf(result_str + written, remaining + 1, "%s=%s|", azColName[i], val); - if (n < 0 || n > remaining) { - break; // 写入失败或超限 +// 第一次调用:写入列名 header +static int first_call = 1; +static int callback(void *result_str, int argc, char **argv, char **azColName) { + char *buf = (char *)result_str; + int written = rt_strlen(buf); // 当前长度(\0 结尾) + int remaining = MAX_RESULT_LEN - written - 1; // 留 \0 + + if (remaining <= 0) { + return 1; // 停止查询(缓冲区满) } - written += n; - remaining -= n; - } - //buf[MAX_RESULT_LEN - 1] = '\0'; // 强制终止,防止意外 - return 0; + if (first_call) { + first_call = 0; + + for (int i = 0; i < argc; i++) { + char temp[128]; + int esc_len = csv_escape_field(azColName[i], temp, sizeof(temp)); + if (esc_len < 0) continue; // 跳过超长列名 + + int needed = esc_len + (i < argc - 1 ? 1 : 0); // + 逗号 + if (needed > remaining) break; + + int n = rt_snprintf(buf + written, remaining + 1, "%s%s", temp, (i < argc - 1) ? "," : ""); + if (n <= 0 || n > remaining) break; + + written += n; + remaining -= n; + } + + // 添加换行 + if (remaining >= 2) { + buf[written++] = '\n'; + buf[written] = '\0'; + remaining--; + } + } + + // 写入数据行 + for (int i = 0; i < argc; i++) { + const char *val = argv[i] ? argv[i] : ""; // NULL 视为空字符串(CSV 标准) + char temp[256]; // 足够大以容纳转义后字段 + int esc_len = csv_escape_field(val, temp, sizeof(temp)); + if (esc_len < 0) { + // 字段太长,截断或跳过 + rt_strncpy(temp, val, sizeof(temp) - 1); + temp[sizeof(temp)-1] = '\0'; + esc_len = rt_strlen(temp); + } + + int needed = esc_len + (i < argc - 1 ? 1 : 0); // + 逗号 + if (needed > remaining) break; + + int n = rt_snprintf(buf + written, remaining + 1, "%s%s", temp, (i < argc - 1) ? "," : ""); + if (n <= 0 || n > remaining) break; + + written += n; + remaining -= n; + } + + // 行尾加换行 + if (remaining >= 2) { + buf[written++] = '\n'; + buf[written] = '\0'; + remaining--; + } + + return 0; // } /** @@ -152,6 +255,7 @@ static void handle_db_command(struct db_command *cmd_dat) { case DB_CMD_SELECT: cmd_dat->result[0] = '\0'; + first_call=1; rc = sqlite3_exec(g_db, cmd_dat->sql, callback, cmd_dat->result, &err_msg); if (rc != SQLITE_OK) { cmd_dat->result_code = rc; diff --git a/applications/sql/DB_SQLite.h b/applications/sql/DB_SQLite.h index bd4315b..62ac537 100644 --- a/applications/sql/DB_SQLite.h +++ b/applications/sql/DB_SQLite.h @@ -25,7 +25,7 @@ extern "C" { #endif #ifndef MAX_RESULT_LEN -#define MAX_RESULT_LEN (1024) /**< 结果字符串最大长度 */ +#define MAX_RESULT_LEN (4096) /**< 结果字符串最大长度 */ #endif #ifndef DB_MAX_WAITING_MS diff --git a/packages/libcsv-v3.0.3 b/packages/libcsv-v3.0.3 new file mode 160000 index 0000000..3643d18 --- /dev/null +++ b/packages/libcsv-v3.0.3 @@ -0,0 +1 @@ +Subproject commit 3643d18e2d7a4a0cbd5cb20b811487a0085fee3c diff --git a/packages/pkgs.json b/packages/pkgs.json index 0971442..4a9ce78 100644 --- a/packages/pkgs.json +++ b/packages/pkgs.json @@ -33,5 +33,10 @@ "path": "/packages/peripherals/rs485", "ver": "v1.06", "name": "RS485" + }, + { + "path": "/packages/misc/libcsv", + "ver": "v3.0.3", + "name": "LIBCSV" } ] \ No newline at end of file diff --git a/rtconfig.h b/rtconfig.h index 30580f7..2bd636c 100644 --- a/rtconfig.h +++ b/rtconfig.h @@ -398,6 +398,8 @@ /* entertainment: terminal games and other interesting software packages */ /* end of entertainment: terminal games and other interesting software packages */ +#define PKG_USING_LIBCSV +#define PKG_USING_LIBCSV_V303 /* end of miscellaneous packages */ /* Arduino libraries */