From 64d820b24c91b64d05b7489fc117d1139566bbf9 Mon Sep 17 00:00:00 2001
From: sc <2401809606@qq.com>
Date: Sun, 26 Oct 2025 01:34:18 +0800
Subject: [PATCH] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E6=93=8D=E4=BD=9C?=
=?UTF-8?q?=EF=BC=88810=EF=BC=8C811=EF=BC=89=E6=8C=87=E4=BB=A4=EF=BC=8C?=
=?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E8=AF=BB=E5=86=99=E5=AE=9E=E7=8E=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.config | 4 +-
.cproject | 2 +-
applications/DATA/DATA_comm.c | 152 +++++---
applications/DATA/Variable.c | 54 +--
applications/DATA/Variable.h | 54 +--
applications/DBSQL/DB_SQLite.c | 615 ++++++++++++++++++++-------------
applications/DBSQL/DB_SQLite.h | 107 ++++++
rtconfig.h | 2 +
8 files changed, 640 insertions(+), 350 deletions(-)
diff --git a/.config b/.config
index a338552..a8f14f1 100644
--- a/.config
+++ b/.config
@@ -174,7 +174,9 @@ CONFIG_RT_USING_PIN=y
# CONFIG_RT_USING_MTD_NOR is not set
# CONFIG_RT_USING_MTD_NAND is not set
# CONFIG_RT_USING_PM is not set
-# CONFIG_RT_USING_RTC is not set
+CONFIG_RT_USING_RTC=y
+# CONFIG_RT_USING_ALARM is not set
+CONFIG_RT_USING_SOFT_RTC=y
CONFIG_RT_USING_SDIO=y
CONFIG_RT_SDIO_STACK_SIZE=1024
CONFIG_RT_SDIO_THREAD_PRIORITY=15
diff --git a/.cproject b/.cproject
index 2bf3637..df1c29d 100644
--- a/.cproject
+++ b/.cproject
@@ -892,7 +892,7 @@
-
+
diff --git a/applications/DATA/DATA_comm.c b/applications/DATA/DATA_comm.c
index a79984f..e75c88b 100644
--- a/applications/DATA/DATA_comm.c
+++ b/applications/DATA/DATA_comm.c
@@ -17,6 +17,7 @@
#include "language.h"
#include "Variable.h"
#include "SC828_DATA_table.h"
+#include "DB_SQLite.h"
rt_mq_t proc_mq;
@@ -59,15 +60,29 @@ int extract_between(const char *src, const char *start, const char *end, char *b
} \
} while(0)
// 提取浮点数
-#define GET_FLOAT_VAR(var, obj, key, default_val) do { \
- cJSON* _item = cJSON_GetObjectItem(obj, key); \
- (var) = cJSON_IsNumber(_item) ? (float)_item->valuedouble : (default_val); \
+#define GET_FLOAT_VAR(var, obj, key, default_val)do { \
+ cJSON *_item = cJSON_GetObjectItem((obj), (key)); \
+ (var) = (_item && cJSON_IsNumber(_item)) ? (float)(_item->valuedouble) : (default_val); \
} while(0)
// 提取整数(int 类型)
#define GET_INT_VAR(var, obj, key, default_val) do { \
cJSON* _item = cJSON_GetObjectItem(obj, key); \
(var) = cJSON_IsNumber(_item) ? (int)_item->valueint : (default_val); \
} while(0)
+#define GET_INT_FROM_ANY(var, obj, key, default_val)do { \
+ cJSON *_item = cJSON_GetObjectItem((obj), (key)); \
+ if (_item) { \
+ if (cJSON_IsNumber(_item)) { \
+ (var) = (int)(_item->valueint); \
+ } else if (cJSON_IsString(_item) && _item->valuestring) { \
+ (var) = atoi(_item->valuestring); \
+ } else { \
+ (var) = (default_val); \
+ } \
+ } else { \
+ (var) = (default_val); \
+ } \
+} while(0)
// ===== cJSON分析 =====//
void pasre_DAT(const char *api, const char *json_str)
@@ -102,46 +117,76 @@ void pasre_DAT(const char *api, const char *json_str)
}
else if (strcmp(api, "SC810") == 0)
{
+ char STime[25];
+ char pTime[10];
+ // 字符串赋值
+ GET_STRING(Work, root, "Work", sizeof(Work));
+ GET_STRING(Dye, root, "Dye", sizeof(Dye));
+ GET_STRING(STime, root, "STime", sizeof(STime));
+ GET_STRING(pTime, root, "Time", sizeof(pTime));
+
+ // 定义足够大的缓冲区
+ char sql[512] = {0}; // 初始化为 0
+ // 安全格式化
+ rt_snprintf(sql, sizeof(sql),
+ "INSERT INTO WorkorderSteps(WorkOrder,DYELOT,ReDye,StartTime,Time)"
+ "VALUES('%s','%s',0,%s,%s,)",
+ Work, Dye, STime,pTime);
+ if( db_send_command(DB_CMD_EXEC, sql, 500)==RT_EOK) //
+ {
+ cJSON_AddItemToObject(dat,"Work",cJSON_CreateString(Work));
+ cJSON_AddItemToObject(dat,"ReDye",cJSON_CreateNumber(Redye));
+ }
}
else if (strcmp(api, "SC811") == 0)
{//工单明细
- // === 解析整数变量 StepN ===
- GET_INT_VAR(StepN, root, "StepN", 0);
- // 字符串赋值
- GET_STRING(Work, root, "Work", sizeof(Work));
- GET_STRING(Dye, root, "Dye", sizeof(Dye));
- GET_STRING(StepID, root, "StepID", sizeof(StepID));
- GET_STRING(SIDS1, root, "SIDS1", sizeof(SIDS1));
- GET_STRING(SIDS2, root, "SIDS2", sizeof(SIDS2));
- GET_STRING(SIDS3, root, "SIDS3", sizeof(SIDS3));
- // 浮点数赋值
- GET_FLOAT_VAR(P1, root, "P1", 0.0f);
- GET_FLOAT_VAR(P2, root, "P2", 0.0f);
- GET_FLOAT_VAR(P3, root, "P3", 0.0f);
- GET_FLOAT_VAR(P4, root, "P4", 0.0f);
- GET_FLOAT_VAR(P5, root, "P5", 0.0f);
- GET_FLOAT_VAR(P1S1, root, "P1S1", 0.0f);
- GET_FLOAT_VAR(P2S1, root, "P2S1", 0.0f);
- GET_FLOAT_VAR(P3S1, root, "P3S1", 0.0f);
- GET_FLOAT_VAR(P4S1, root, "P4S1", 0.0f);
- GET_FLOAT_VAR(P5S1, root, "P5S1", 0.0f);
- GET_FLOAT_VAR(P1S2, root, "P1S2", 0.0f);
- GET_FLOAT_VAR(P2S2, root, "P2S2", 0.0f);
- GET_FLOAT_VAR(P3S2, root, "P3S2", 0.0f);
- GET_FLOAT_VAR(P4S2, root, "P4S2", 0.0f);
- GET_FLOAT_VAR(P5S2, root, "P5S2", 0.0f);
- GET_FLOAT_VAR(P1S3, root, "P1S3", 0.0f);
- GET_FLOAT_VAR(P2S3, root, "P2S3", 0.0f);
- GET_FLOAT_VAR(P3S3, root, "P3S3", 0.0f);
- GET_FLOAT_VAR(P4S3, root, "P4S3", 0.0f);
- GET_FLOAT_VAR(P5S3, root, "P5S3", 0.0f);
+ // 字符串赋值
+ GET_STRING(Work, root, "Work", sizeof(Work));
+ GET_STRING(Dye, root, "Dye", sizeof(Dye));
+ GET_STRING(StepID, root, "StepID", sizeof(StepID));
+ GET_STRING(SIDS1, root, "SIDS1", sizeof(SIDS1));
+ //GET_STRING(SIDS2, root, "SIDS2", sizeof(SIDS2));
+ //GET_STRING(SIDS3, root, "SIDS3", sizeof(SIDS3));
+ //整数
+ GET_INT_FROM_ANY(StepN, root, "Step", 0);
+ GET_INT_FROM_ANY(P1, root, "P1", 0);
+ GET_INT_FROM_ANY(P2, root, "P2", 0);
+ GET_INT_FROM_ANY(P3, root, "P3", 0);
+ GET_INT_FROM_ANY(P4, root, "P4", 0);
+ GET_INT_FROM_ANY(P5, root, "P5", 0);
+ GET_INT_FROM_ANY(P1S1, root, "P1S1",0);
+ GET_INT_FROM_ANY(P2S1, root, "P2S1",0);
+ GET_INT_FROM_ANY(P3S1, root, "P3S1",0);
+ GET_INT_FROM_ANY(P4S1, root, "P4S1",0);
+ GET_INT_FROM_ANY(P5S1, root, "P5S1",0);
+ //GET_INT_FROM_ANY(P1S2, root, "P1S2",0);
+ //GET_INT_FROM_ANY(P2S2, root, "P2S2",0);
+ //GET_INT_FROM_ANY(P3S2, root, "P3S2",0);
+ //GET_INT_FROM_ANY(P4S2, root, "P4S2",0);
+ //GET_INT_FROM_ANY(P5S2, root, "P5S2",0);
+ //GET_INT_FROM_ANY(P1S3, root, "P1S3",0);
+ //GET_INT_FROM_ANY(P2S3, root, "P2S3",0);
+ //GET_INT_FROM_ANY(P3S3, root, "P3S3",0);
+ //GET_INT_FROM_ANY(P4S3, root, "P4S3",0);
+ //GET_INT_FROM_ANY(P5S3, root, "P5S3",0);
+
+ // 定义足够大的缓冲区
+ char sql[512] = {0}; // 初始化为 0
- cJSON_AddItemToObject(dat,"Work",cJSON_CreateString(Work));
- cJSON_AddItemToObject(dat,"ReDye",cJSON_CreateNumber(Redye));
- cJSON_AddItemToObject(dat,"StepN",cJSON_CreateNumber(StepN));
+ // 安全格式化
+ rt_snprintf(sql, sizeof(sql),
+ "INSERT INTO WorkorderSteps(WorkOrder,DYELOT,ReDye,Step,StepID,P1,P2,P3,P4,P5,StepID_S1,P1_S1,P2_S1,P3_S1,P4_S1,P5_S1)"
+ "VALUES('%s','%s',0,%d,%s,%d,%d,%d,%d,%d,'%s',%d,%d,%d,%d,%d)",
+ Work, Dye, StepN,StepID,P1, P2, P3, P4, P5,SIDS1,P1S1,P2S1,P3S1,P4S1,P5S1 );
+ if( db_send_command(DB_CMD_EXEC, sql, 500)==RT_EOK) //
+ {
+ cJSON_AddItemToObject(dat,"Work",cJSON_CreateString(Work));
+ cJSON_AddItemToObject(dat,"ReDye",cJSON_CreateNumber(Redye));
+ cJSON_AddItemToObject(dat,"Step",cJSON_CreateNumber(StepN));
+ }
}
else if (strcmp(api, "SC812") == 0) {
- printf("Processing:SC812\n");
+ //工单设定
}
else if (strcmp(api, "SC813") == 0) {
printf("Processing:SC813\n");
@@ -296,22 +341,27 @@ void proc_thread_entry(void *parameter)
{
if (!req) continue;
memcpy(DATA_api,req->input,5);
- extract_between(req->input, "[", "]", machine_ID, sizeof(machine_ID));
+ extract_between(req->input, "[", "]", DATA_machins, sizeof(DATA_machins));
+ if(strcmp(DATA_machins,machine_ID)==0)
+ {
+ char *p=strstr(req->input,"]");
+ if(!p){cjson_falg=0;}
+ else {
+ p += strlen("]");
+ }
- char *p=strstr(req->input,"]");
- if(!p){cjson_falg=0;}
- else {
- p += strlen("]");
- }
+ //处理指令分析
+ pasre_DAT(DATA_api,p);
- //处理指令分析
- pasre_DAT(DATA_api,p);
- // 回复
- int16_t total_len = strlen(machine_ID) + strlen(json_buffer) + 8;
- char t_buffer[total_len];
- snprintf(t_buffer,total_len,"%s[%s]%s\n",DATA_api,machine_ID,json_buffer);
- req->output_len = rt_snprintf(req->output, sizeof(req->output),t_buffer);
+ // 回复
+ int16_t total_len = strlen(machine_ID) + strlen(json_buffer) + 8;
+ char t_buffer[total_len];
+ snprintf(t_buffer,total_len,"%s[%s]%s\n",DATA_api,machine_ID,json_buffer);
+ req->output_len = rt_snprintf(req->output, sizeof(req->output),t_buffer);
+ }else{
+ req->output_len=0;
+ }
// 通知 UART 线程可以发送了
if (req->sem)
@@ -332,7 +382,7 @@ int data_comm_init(void)
}
rt_thread_t tid = rt_thread_create("data_comm", proc_thread_entry, RT_NULL,
- 1024*5, 20, 10);
+ 1024*4, 20, 10);
if (tid != RT_NULL)
{
rt_thread_startup(tid);
diff --git a/applications/DATA/Variable.c b/applications/DATA/Variable.c
index 940c16d..2716314 100644
--- a/applications/DATA/Variable.c
+++ b/applications/DATA/Variable.c
@@ -5,7 +5,7 @@
// 动态数据缓冲区(初始化为 NULL,后续分配)
char *DATA_dat;
-char *DATA_machins;
+char DATA_machins[3];
char DATA_api[5];
char *machine_name = "Q109";
char machine_ID[3] = "23";
@@ -17,8 +17,8 @@ char MACHINE_CALL = 0;
char MACHINE_USER = 0;
// 字符串变量(RAM 中可修改)
-char Work[15];
-char Dye[15];
+char Work[25];
+char Dye[25];
char Process[50];
char Message[40];
char Step[60];
@@ -61,32 +61,32 @@ unsigned int P9 = 0;
unsigned int P10 = 0;
// 步骤功能参数
-float P1 = 0.0f;
-float P2 = 0.0f;
-float P3 = 0.0f;
-float P4 = 0.0f;
-float P5 = 0.0f;
-float P1S1 = 0.0f;
-float P2S1 = 0.0f;
-float P3S1 = 0.0f;
-float P4S1 = 0.0f;
-float P5S1 = 0.0f;
-float P1S2 = 0.0f;
-float P2S2 = 0.0f;
-float P3S2 = 0.0f;
-float P4S2 = 0.0f;
-float P5S2 = 0.0f;
-float P1S3 = 0.0f;
-float P2S3 = 0.0f;
-float P3S3 = 0.0f;
-float P4S3 = 0.0f;
-float P5S3 = 0.0f;
+unsigned int P1 = 0;
+unsigned int P2 =0;
+unsigned int P3 =0;
+unsigned int P4 =0;
+unsigned int P5 =0;
+unsigned int P1S1 =0;
+unsigned int P2S1 =0;
+unsigned int P3S1 =0;
+unsigned int P4S1 =0;
+unsigned int P5S1 =0;
+unsigned int P1S2 =0;
+unsigned int P2S2 =0;
+unsigned int P3S2 =0;
+unsigned int P4S2 =0;
+unsigned int P5S2 =0;
+unsigned int P1S3 =0;
+unsigned int P2S3 =0;
+unsigned int P3S3 =0;
+unsigned int P4S3 =0;
+unsigned int P5S3 =0;
// 步骤编号字符串
-char StepID[3];
-char SIDS1[3];
-char SIDS2[3];
-char SIDS3[3];
+char StepID[4];
+char SIDS1[4];
+char SIDS2[4];
+char SIDS3[4];
// ===== 初始化函数 =====
void init_global_vars(void) {
diff --git a/applications/DATA/Variable.h b/applications/DATA/Variable.h
index 53c3ad9..c11f5fd 100644
--- a/applications/DATA/Variable.h
+++ b/applications/DATA/Variable.h
@@ -5,7 +5,7 @@
// ===== 字符串变量 =====
extern char *DATA_dat;
-extern char *DATA_machins;
+extern char DATA_machins[3];
extern char DATA_api[5];
extern char *machine_name;
extern char machine_ID[3];
@@ -17,8 +17,8 @@ extern char MACHINE_CALL;
extern char MACHINE_USER;
// ===== 字符串 =====
-extern char Work[15];
-extern char Dye[15];
+extern char Work[25];
+extern char Dye[25];
extern char Process[50];
extern char Message[40];
extern char Step[60];
@@ -57,31 +57,31 @@ extern float STTB;
extern float STLB;
extern float STTC;
extern float STLC;
-extern float P1;
-extern float P2;
-extern float P3;
-extern float P4;
-extern float P5;
-extern float P1S1;
-extern float P2S1;
-extern float P3S1;
-extern float P4S1;
-extern float P5S1;
-extern float P1S2;
-extern float P2S2;
-extern float P3S2;
-extern float P4S2;
-extern float P5S2;
-extern float P1S3;
-extern float P2S3;
-extern float P3S3;
-extern float P4S3;
-extern float P5S3;
+extern unsigned int P1;
+extern unsigned int P2;
+extern unsigned int P3;
+extern unsigned int P4;
+extern unsigned int P5;
+extern unsigned int P1S1;
+extern unsigned int P2S1;
+extern unsigned int P3S1;
+extern unsigned int P4S1;
+extern unsigned int P5S1;
+extern unsigned int P1S2;
+extern unsigned int P2S2;
+extern unsigned int P3S2;
+extern unsigned int P4S2;
+extern unsigned int P5S2;
+extern unsigned int P1S3;
+extern unsigned int P2S3;
+extern unsigned int P3S3;
+extern unsigned int P4S3;
+extern unsigned int P5S3;
-extern char StepID[3];
-extern char SIDS1[3];
-extern char SIDS2[3];
-extern char SIDS3[3];
+extern char StepID[4];
+extern char SIDS1[4];
+extern char SIDS2[4];
+extern char SIDS3[4];
void init_global_vars(void);
diff --git a/applications/DBSQL/DB_SQLite.c b/applications/DBSQL/DB_SQLite.c
index ddda5c8..aba6272 100644
--- a/applications/DBSQL/DB_SQLite.c
+++ b/applications/DBSQL/DB_SQLite.c
@@ -16,274 +16,403 @@
#include
#define DB_NAME "/SC828.db"
int db_HelperInit;
+rt_mq_t db_mq = RT_NULL; //
sqlite3 **db;
+// 消息队列对象与缓冲区(静态分配)
+//static struct rt_mq db_mq;
+//static char mq_pool[DB_QUEUE_SIZE * sizeof(struct db_command)];
+
+// 全局数据库连接与状态
+static sqlite3 *g_db = RT_NULL;
+static rt_bool_t db_enabled = RT_FALSE; // 是否允许数据库操作
+static rt_mutex_t state_mutex = RT_NULL; // 状态访问锁
+
+// 函数前向声明
+static void return_timeout(struct db_command *cmd);
+static void return_disabled(struct db_command *cmd);
+static void handle_db_command(struct db_command *cmd);
+static int callback(void *result_str, int argc, char **argv, char **azColName);
static const char *sql_upgrade_workorder_steps =
- "CREATE TABLE WorkorderSteps ("
- "WorkOrder VARCHAR,"
- "DYELOT VARCHAR,"
- "ProgramID VARCHAR,"
- "Program VARCHAR,"
- "ReDye INT DEFAULT (0),"
- "Mode VARCHAR,"
- "Step INT,"
- "StepID VARCHAR,"
- "StepName VARCHAR,"
- "ParameterName VARCHAR,"
- "Parameter1 DOUBLE,"
- "Parameter2 DOUBLE,"
- "Parameter3 DOUBLE,"
- "Parameter4 DOUBLE,"
- "Parameter5 DOUBLE,"
- "Parameter6 INT,"
- "Parameter7 INT,"
- "Parameter8 INT,"
- "Parameter9 INT,"
- "Parameter10 INT,"
- "Remark VARCHAR,"
- "StepTime INT,"
- "StepID_S1 VARCHAR,"
- "StepID_S2 VARCHAR,"
- "StepID_S3 VARCHAR,"
- "StepName_S1 VARCHAR,"
- "StepName_S2 VARCHAR,"
- "StepName_S3 VARCHAR,"
- "Parameter1_S1 DOUBLE,"
- "Parameter1_S2 DOUBLE,"
- "Parameter1_S3 DOUBLE,"
- "Parameter2_S1 DOUBLE,"
- "Parameter2_S2 DOUBLE,"
- "Parameter2_S3 DOUBLE,"
- "Parameter3_S1 DOUBLE,"
- "Parameter3_S2 DOUBLE,"
- "Parameter3_S3 DOUBLE,"
- "Parameter4_S1 DOUBLE,"
- "Parameter4_S2 DOUBLE,"
- "Parameter4_S3 DOUBLE,"
- "Parameter5_S1 DOUBLE,"
- "Parameter5_S2 DOUBLE,"
- "Parameter5_S3 DOUBLE"
- "); ";
+ "CREATE TABLE WorkorderSteps (WorkOrder VARCHAR,DYELOT VARCHAR,ProgramID VARCHAR,Program VARCHAR,ReDye INT DEFAULT (0),"
+ "Mode VARCHAR,Step INT,StepID VARCHAR,StepName VARCHAR,ParameterName VARCHAR,P1 DOUBLE,P2 DOUBLE,P3 DOUBLE,"
+ "P4 DOUBLE,P5 DOUBLE,P6 INT,P7 INT,P8 INT,P9 INT,P10 INT,Remark VARCHAR,StepTime INT,StepID_S1 VARCHAR,"
+ "StepID_S2 VARCHAR,StepID_S3 VARCHAR,StepName_S1 VARCHAR,StepName_S2 VARCHAR,StepName_S3 VARCHAR,P1_S1 DOUBLE,"
+ "P1_S2 DOUBLE,P1_S3 DOUBLE,P2_S1 DOUBLE,P2_S2 DOUBLE,P2_S3 DOUBLE,P3_S1 DOUBLE,P3_S2 DOUBLE,P3_S3 DOUBLE,"
+ "P4_S1 DOUBLE,P4_S2 DOUBLE,P4_S3 DOUBLE,P5_S1 DOUBLE,P5_S2 DOUBLE,P5_S3 DOUBLE); ";
static const char *sql_upgrade_workorder_set =
- "CREATE TABLE WorkOrderSet ("
- "WorkOrder VARCHAR,"
- "ReDye INT DEFAULT (0),"
- "PumpSpeed INT,"
- "Blower INT,"
- "Swing INT,"
- "ClothWheel INT,"
- "Nozzle INT"
- "); ";
+ "CREATE TABLE WorkOrderSet (WorkOrder VARCHAR,ReDye INT DEFAULT (0),PumpSpeed INT,Blower INT,Swing INT,ClothWheel INT,Nozzle INT); ";
static const char *sql_upgrade_workorder =
- "CREATE TABLE WorkOrder ("
- "WorkOrder VARCHAR,"
- "Dyelot VARCHAR,"
- "ReDye INT DEFAULT (0),"
- "ProgramName VARCHAR,"
- "StartTime DATETIME,"
- "EndTime DATETIME,"
- "Time TEXT,"
- "lock INT,"
- "State INT,"
- "ProgramID VARCHAR,"
- "Machines VARCHAR,"
- "color VARCHAR,"
- "ColorNumber VARCHAR,"
- "Client VARCHAR,"
- "ClothWeight VARCHAR,"
- "ClothSpecies VARCHAR,"
- "BathRatio VARCHAR,"
- "Total VARCHAR,"
- "USER VARCHAR,"
- "ColorName VARCHAR,"
- "Remark TEXT"
- "); ";
+ "CREATE TABLE WorkOrder (WorkOrder VARCHAR,Dyelot VARCHAR,ReDyeINT DEFAULT (0),ProgramNameVARCHAR,StartTime DATETIME,EndTime DATETIME,"
+ "Time TEXT,lock INT,State INT,ProgramID VARCHAR,Machines VARCHAR,color VARCHAR,ColorNumber VARCHAR,Client VARCHAR,ClothWeight VARCHAR,"
+ "ClothSpecies VARCHAR,BathRatio VARCHAR,Total VARCHAR,USER VARCHAR,ColorName VARCHAR,Remark TEXT); ";
static const char *sql_upgrade_run_table =
- // "PRAGMA foreign_keys = OFF; "
- // "BEGIN TRANSACTION; "
- // "CREATE TABLE sqlitestudio_temp_table AS SELECT * FROM RUN; "
- // "DROP TABLE RUN; "
- "CREATE TABLE RUN ("
- "WorkOrder VARCHAR,"
- "DYELOT VARCHAR,"
- "ReDye INT DEFAULT (0),"
- "RUN INT,"
- "Mode VARCHAR,"
- "ProgramID VARCHAR,"
- "Program VARCHAR,"
- "StepID VARCHAR,"
- "Step INT,"
- "StepName VARCHAR,"
- "ParameterName VARCHAR,"
- "Parameter1 DOUBLE,"
- "Parameter2 DOUBLE,"
- "Parameter3 DOUBLE,"
- "Parameter4 DOUBLE,"
- "Parameter5 DOUBLE,"
- "Parameter6 INT,"
- "Parameter7 INT,"
- "Parameter8 INT,"
- "Parameter9 INT,"
- "Parameter10 INT,"
- "Remark VARCHAR,"
- "StepTime INT,"
- "StepID_S1 VARCHAR,"
- "StepID_S2 VARCHAR,"
- "StepID_S3 VARCHAR,"
- "StepName_S1 VARCHAR,"
- "StepName_S2 VARCHAR,"
- "StepName_S3 VARCHAR,"
- "Parameter1_S1 DOUBLE,"
- "Parameter1_S2 DOUBLE,"
- "Parameter1_S3 DOUBLE,"
- "Parameter2_S1 DOUBLE,"
- "Parameter2_S2 DOUBLE,"
- "Parameter2_S3 DOUBLE,"
- "Parameter3_S1 DOUBLE,"
- "Parameter3_S2 DOUBLE,"
- "Parameter3_S3 DOUBLE,"
- "Parameter4_S1 DOUBLE,"
- "Parameter4_S2 DOUBLE,"
- "Parameter4_S3 DOUBLE,"
- "Parameter5_S1 DOUBLE,"
- "Parameter5_S2 DOUBLE,"
- "Parameter5_S3 DOUBLE"
- ");";
+ "CREATE TABLE RUN (WorkOrder VARCHAR,DYELOT VARCHAR,ProgramID VARCHAR,Program VARCHAR,ReDye INT DEFAULT (0),"
+ "Mode VARCHAR,Step INT,StepID VARCHAR,StepName VARCHAR,ParameterName VARCHAR,P1 DOUBLE,P2 DOUBLE,P3 DOUBLE,"
+ "P4 DOUBLE,P5 DOUBLE,P6 INT,P7 INT,P8 INT,P9 INT,P10 INT,Remark VARCHAR,StepTime INT,StepID_S1 VARCHAR,"
+ "StepID_S2 VARCHAR,StepID_S3 VARCHAR,StepName_S1 VARCHAR,StepName_S2 VARCHAR,StepName_S3 VARCHAR,P1_S1 DOUBLE,"
+ "P1_S2 DOUBLE,P1_S3 DOUBLE,P2_S1 DOUBLE,P2_S2 DOUBLE,P2_S3 DOUBLE,P3_S1 DOUBLE,P3_S2 DOUBLE,P3_S3 DOUBLE,"
+ "P4_S1 DOUBLE,P4_S2 DOUBLE,P4_S3 DOUBLE,P5_S1 DOUBLE,P5_S2 DOUBLE,P5_S3 DOUBLE); ";
static const char *sql_upgrade_dyelot_table =
- "CREATE TABLE Dyelot ("
- "WorkOrder VARCHAR,"
- "Dyelot VARCHAR,"
- "ReDye INT,"
- "Machine VARCHAR,"
- "Step INT,"
- "Tank INT,"
- "State INT,"
- "ProductCode VARCHAR,"
- "ProductName VARCHAR,"
- "ProductType INT,"
- "Grams FLOAT,"
- "Amount FLOAT,"
- "CALL_TIME VARCHAR,"
- "DispenseEndTime VARCHAR,"
- "Type INT"
- "); ";
+ "CREATE TABLE Dyelot (WorkOrder VARCHAR,Dyelot VARCHAR,ReDye INT,Machine VARCHAR,Step INT,Tank INT,State INT,ProductCode VARCHAR,"
+ "ProductName VARCHAR,ProductType INT,Grams FLOAT,Amount FLOAT,CALL_TIME VARCHAR,DispenseEndTime VARCHAR,Type INT); ";
static const char *sql_upgrade_iolog_table =
- // "CREATE TABLE sqlitestudio_temp_table AS SELECT * FROM IOLog; "
- // "DROP TABLE IOLog; "
- "CREATE TABLE IOLog ("
- "ID varchar(32),"
- "IOName varchar(32),"
- "type varchar(32),"
- "Value DOUBLE DEFAULT (0),"
- "DIO BOOLEAN,"
- "AIO INTEGER DEFAULT (0),"
- "PLC varchar(32)"
- "); ";
+ "CREATE TABLE IOLog (ID varchar,IOName varchar,type varchar,Value DOUBLE DEFAULT (0),DIO BOOLEAN,AIO INTEGER DEFAULT (0),PLC varchar); ";
static const char *sql_upgrade_chart_table =
- "CREATE TABLE Chart ("
- "WorkOrder varchar(32),"
- "DYELOT varchar(32),"
- "ReDye INTEGER ,"
- "Name varchar(32),"
- "Time varchar(32),"
- "MTT DOUBLE DEFAULT (0),"
- "MTL DOUBLE DEFAULT (0),"
- "STTA DOUBLE DEFAULT (0),"
- "STLA DOUBLE DEFAULT (0),"
- "STTB DOUBLE DEFAULT (0),"
- "STLB DOUBLE DEFAULT (0),"
- "STTC DOUBLE DEFAULT (0),"
- "STLC DOUBLE DEFAULT (0),"
- "MTH DOUBLE DEFAULT (0),"
- "MST DOUBLE DEFAULT (0),"
- "MSL DOUBLE DEFAULT (0),"
- "MUT DOUBLE DEFAULT (0)"
- "); ";
-
-void db_sqlite(void *parameter)
-{
- if (access(DB_NAME, F_OK) == 0)
+ "CREATE TABLE Chart (WorkOrder varchar,DYELOT varchar,ReDye INTEGER,Name varchar,Time varchar,MTT DOUBLE DEFAULT (0),MTL DOUBLE DEFAULT (0),"
+ "STTA DOUBLE DEFAULT (0),STLA DOUBLE DEFAULT (0),STTB DOUBLE DEFAULT (0),STLB DOUBLE DEFAULT (0),STTC DOUBLE DEFAULT (0),"
+ "STLC DOUBLE DEFAULT (0),MTH DOUBLE DEFAULT (0),MST DOUBLE DEFAULT (0),MSL DOUBLE DEFAULT (0),MUT DOUBLE DEFAULT (0)); ";
+
+// ------------------------
+// 内部工具函数
+// ------------------------
+
+/**
+ * @brief 返回超时错误(排队时间过长)
+ */
+static void return_timeout(struct db_command *cmd) {
+ cmd->result_code = -RT_ETIMEOUT;
+ rt_strncpy(cmd->result, "Cmd timeout: waited too long in queue", MAX_RESULT_LEN - 1);
+ if (cmd->reply_sem) {
+ rt_sem_release(cmd->reply_sem);
+ }
+}
+
+/**
+ * @brief 返回“数据库已禁用”错误
+ */
+static void return_disabled(struct db_command *cmd) {
+ cmd->result_code = -RT_ENODEV;
+ rt_strncpy(cmd->result, "Error: Database is disabled", MAX_RESULT_LEN - 1);
+ if (cmd->reply_sem) {
+ rt_sem_release(cmd->reply_sem);
+ }
+}
+
+/**
+ * @brief SELECT 查询回调函数
+ */
+static int callback(void *result_str, int argc, char **argv, char **azColName) {
+ char *str = (char *)result_str;
+ int len = rt_strlen(str);
+ for (int i = 0; i < argc; i++) {
+ rt_snprintf(str + len, MAX_RESULT_LEN - len, "%s=%s|",
+ azColName[i], argv[i] ? argv[i] : "NULL");
+ len = rt_strlen(str);
+ }
+ return 0;
+}
+
+/**
+ * @brief 执行具体 SQL 操作
+ */
+static void handle_db_command(struct db_command *cmd) {
+ char *err_msg = 0;
+ int rc;
+
+ switch (cmd->type) {
+ case DB_CMD_INSERT:
+ case DB_CMD_DELETE:
+ case DB_CMD_UPDATE:
+ case DB_CMD_EXEC:
+ rc = sqlite3_exec(g_db, cmd->sql, 0, 0, &err_msg);
+ if (rc != SQLITE_OK) {
+ cmd->result_code = rc;
+ rt_strncpy(cmd->result, err_msg, MAX_RESULT_LEN - 1);
+ sqlite3_free(err_msg);
+ } else {
+ cmd->result_code = 0;
+ rt_strncpy(cmd->result, "OK", MAX_RESULT_LEN - 1);
+ }
+ break;
+
+ case DB_CMD_SELECT:
+ cmd->result[0] = '\0';
+ rc = sqlite3_exec(g_db, cmd->sql, callback, cmd->result, &err_msg);
+ if (rc != SQLITE_OK) {
+ cmd->result_code = rc;
+ rt_strncpy(cmd->result, err_msg, MAX_RESULT_LEN - 1);
+ sqlite3_free(err_msg);
+ } else {
+ cmd->result_code = 0;
+ if (cmd->result[0] == '\0')
+ rt_strncpy(cmd->result, "No data", MAX_RESULT_LEN - 1);
+ }
+ break;
+
+ case DB_CMD_EXIT:
+ rt_strncpy(cmd->result, "Exit", MAX_RESULT_LEN - 1);
+ cmd->result_code = 0;
+ break;
+
+ default:
+ cmd->result_code = -1;
+ rt_strncpy(cmd->result, "Invalid command", MAX_RESULT_LEN - 1);
+ break;
+ }
+}
+
+// ------------------------
+// 外部接口实现
+// ------------------------
+
+/**
+ * @brief 外部调用:立即关闭数据库并禁用所有操作
+ */
+void close_db_immediately(void) {
+ if (!state_mutex) return;
+
+ rt_mutex_take(state_mutex, RT_WAITING_FOREVER);
{
- rt_kprintf("DB open\n");
- if (db_connect(DB_NAME) == RT_EOK){
- if(db_table_is_exist("WorkorderSteps")<=0){
- if(db_create_database(sql_upgrade_workorder_steps)==0)
- {rt_kprintf("WorkorderSteps Created successfully \n");}else{rt_kprintf("WorkorderSteps Creation failed \n");}
+ if (g_db) {
+ sqlite3_close(g_db);
+ g_db = RT_NULL;
}
- if(db_table_is_exist("WorkOrderSet")<=0){
- if(db_create_database(sql_upgrade_workorder_set)==0)
- {rt_kprintf("WorkOrderSet Created successfully \n");}else{rt_kprintf("WorkOrderSet Creation failed \n");}
- }
- if(db_table_is_exist("WorkOrder")<=0){
- if(db_create_database(sql_upgrade_workorder)==0)
- {rt_kprintf("WorkOrder Created successfully \n");}else{rt_kprintf("WorkOrder Creation failed \n");}
- }
- if(db_table_is_exist("RUN")<=0){
- if(db_create_database(sql_upgrade_run_table)==0)
- {rt_kprintf("RUN Created successfully \n");}else{rt_kprintf("RUN Creation failed \n");}
+ db_enabled = RT_FALSE;
+ }
+ rt_mutex_release(state_mutex);
+ rt_kprintf("Database disabled.\n");
+}
+
+void db_sqlite_init_full(void)
+{
+ if (access(DB_NAME, F_OK) == 0)
+ {
+ rt_kprintf("DB open\n");
+ if (db_connect(DB_NAME) == RT_EOK){
+ if(db_table_is_exist("WorkorderSteps")<=0){
+ if(db_create_database(sql_upgrade_workorder_steps)==0)
+ {rt_kprintf("WorkorderSteps Created successfully \n");}else{rt_kprintf("WorkorderSteps Creation failed \n");}
+ }
+ if(db_table_is_exist("WorkOrderSet")<=0){
+ if(db_create_database(sql_upgrade_workorder_set)==0)
+ {rt_kprintf("WorkOrderSet Created successfully \n");}else{rt_kprintf("WorkOrderSet Creation failed \n");}
+ }
+ if(db_table_is_exist("WorkOrder")<=0){
+ if(db_create_database(sql_upgrade_workorder)==0)
+ {rt_kprintf("WorkOrder Created successfully \n");}else{rt_kprintf("WorkOrder Creation failed \n");}
+ }
+ if(db_table_is_exist("RUN")<=0){
+ if(db_create_database(sql_upgrade_run_table)==0)
+ {rt_kprintf("RUN Created successfully \n");}else{rt_kprintf("RUN Creation failed \n");}
+ }
+ if(db_table_is_exist("Dyelot")<=0){
+ if(db_create_database(sql_upgrade_dyelot_table)==0)
+ {rt_kprintf("Dyelot Created successfully \n");}else{rt_kprintf("Dyelot Creation failed \n");}
+ }
+ if(db_table_is_exist("IOLog")<=0){
+ if(db_create_database(sql_upgrade_iolog_table)==0)
+ {rt_kprintf("IOLog Created successfully \n");}else{rt_kprintf("IOLog Creation failed \n");}
+ }
+ if(db_table_is_exist("Chart")<=0){
+ if(db_create_database(sql_upgrade_chart_table)==0)
+ {rt_kprintf("Chart Created successfully \n");}else{rt_kprintf("Chart Creation failed \n");}
+ }
+ }else{
+ rt_kprintf("DB ok\n");
+ db_connect(DB_NAME);
+ }
+
+ }else{
+ rt_kprintf("DB open failed \n");
+ sqlite3_open(DB_NAME, db);
+ //创建表
+ db_create_database(sql_upgrade_workorder_steps);
+ db_create_database(sql_upgrade_workorder_set);
+ db_create_database(sql_upgrade_workorder);
+ db_create_database(sql_upgrade_run_table);
+ db_create_database(sql_upgrade_dyelot_table);
+ db_create_database(sql_upgrade_iolog_table);
+ db_create_database(sql_upgrade_chart_table);
}
- if(db_table_is_exist("Dyelot")<=0){
- if(db_create_database(sql_upgrade_dyelot_table)==0)
- {rt_kprintf("Dyelot Created successfully \n");}else{rt_kprintf("Dyelot Creation failed \n");}
+}
+
+/**
+ * @brief 数据库处理线程入口函数
+ */
+static void db_sqlite(void *parameter) {
+ struct db_command cmd;
+ rt_tick_t max_wait_ticks = rt_tick_from_millisecond(DB_MAX_WAITING_MS);
+
+ // 检查并初始化数据库文件
+ db_sqlite_init_full();
+
+ // ✅ 使用 rt_mq_create 动态创建消息队列
+ db_mq = rt_mq_create("db_mq", sizeof(struct db_command), DB_QUEUE_SIZE, RT_IPC_FLAG_FIFO);
+ if (db_mq == RT_NULL) {
+ rt_kprintf("Failed to create message queue 'db_mq'!\n");
+ return;
+ }
+
+ // 创建状态锁
+ state_mutex = rt_mutex_create("db_lock", RT_IPC_FLAG_FIFO);
+ if (!state_mutex) {
+ rt_kprintf("Failed to create db_lock mutex!\n");
+ rt_mq_delete(db_mq); // 创建失败要清理
+ db_mq = RT_NULL;
+ return;
+ }
+
+ // 默认启用数据库
+ db_enabled = RT_TRUE;
+
+ rt_kprintf("Database handler started. Path: %s\n", DB_NAME);
+
+ while (1) {
+ // 接收命令
+ if (rt_mq_recv(db_mq, &cmd, sizeof(struct db_command), RT_WAITING_FOREVER) != RT_EOK)
+ continue;
+
+ // 1. 检查排队超时
+ rt_tick_t now = rt_tick_get();
+ if ((now - cmd.send_tick) > max_wait_ticks) {
+ int wait_ms = (now - cmd.send_tick) * 1000 / RT_TICK_PER_SECOND;
+ rt_kprintf("DROP cmd[type=%d]: waited %dms > limit(%dms)\n", cmd.type, wait_ms, DB_MAX_WAITING_MS);
+ return_timeout(&cmd);
+ continue;
}
- if(db_table_is_exist("IOLog")<=0){
- if(db_create_database(sql_upgrade_iolog_table)==0)
- {rt_kprintf("IOLog Created successfully \n");}else{rt_kprintf("IOLog Creation failed \n");}
+
+ // 2. 获取当前启用状态
+ rt_bool_t current_enabled;
+ rt_mutex_take(state_mutex, RT_WAITING_FOREVER);
+ current_enabled = db_enabled;
+ rt_mutex_release(state_mutex);
+
+ // 3. 若已禁用 → 返回错误
+ if (!current_enabled) {
+ rt_kprintf("Rejected cmd[type=%d]: database is disabled\n", cmd.type);
+ return_disabled(&cmd);
+ if (cmd.type == DB_CMD_EXIT) break;
+ continue;
}
- if(db_table_is_exist("Chart")<=0){
- if(db_create_database(sql_upgrade_chart_table)==0)
- {rt_kprintf("Chart Created successfully \n");}else{rt_kprintf("Chart Creation failed \n");}
+ // 4. 打开数据库(如果未打开)
+ rt_mutex_take(state_mutex, RT_WAITING_FOREVER);
+ {
+ if (!g_db && current_enabled) {
+ int rc = sqlite3_open(DB_NAME, &g_db);
+ if (rc != SQLITE_OK) {
+ rt_kprintf("Failed to open DB at %s: %s\n", DB_NAME, sqlite3_errmsg(g_db));
+ sqlite3_close(g_db);
+ g_db = RT_NULL;
+ rt_mutex_release(state_mutex);
+ return_disabled(&cmd);
+ continue;
+ } else {
+ rt_kprintf("Opened database: %s\n", DB_NAME);
+ }
+ }
}
- }else{
- rt_kprintf("DB open failed \n");
+ rt_mutex_release(state_mutex);
+
+ // 5. 执行命令
+ handle_db_command(&cmd);
+
+ // 6. 返回结果
+ if (cmd.reply_sem) {
+ rt_sem_release(cmd.reply_sem);
}
- }else{
- rt_kprintf("DB open failed \n");
- sqlite3_open(DB_NAME, db);
- //创建表
- db_create_database(sql_upgrade_workorder_steps);
- db_create_database(sql_upgrade_workorder_set);
- db_create_database(sql_upgrade_workorder);
- db_create_database(sql_upgrade_run_table);
- db_create_database(sql_upgrade_dyelot_table);
- db_create_database(sql_upgrade_iolog_table);
- db_create_database(sql_upgrade_chart_table);
+ // 7. 退出命令
+ if (cmd.type == DB_CMD_EXIT) break;
+ }
+
+ // ✅ 清理资源
+ if (g_db) {
+ sqlite3_close(g_db);
+ g_db = RT_NULL;
+ }
+ db_enabled = RT_FALSE;
+
+ if (state_mutex) {
+ rt_mutex_delete(state_mutex);
+ state_mutex = RT_NULL;
+ }
+
+ // ✅ 删除动态消息队列
+ if (db_mq) {
+ rt_mq_delete(db_mq);
+ db_mq = RT_NULL;
+ }
+
+ rt_kprintf("Database handler exited.\n");
+}
+
+/**
+ * @brief 向数据库发送命令并等待响应
+ *
+ * @param type 命令类型(INSERT/SELECT等)
+ * @param sql SQL 语句字符串
+ * @param timeout_ms 超时时间(毫秒),0 表示不等待
+ * @return RT_EOK 成功,RT_ETIMEOUT 超时,RT_ERROR 失败
+ */
+rt_err_t db_send_command(enum db_cmd_type type, const char* sql, rt_int32_t timeout_ms)
+{
+ struct db_command cmd;
+ rt_sem_t sem = RT_NULL;
+ rt_err_t result = RT_EOK;
+
+ // 1. 创建临时信号量用于同步
+ sem = rt_sem_create("db_rep", 0, RT_IPC_FLAG_FIFO);
+ if (sem == RT_NULL)
+ {
+ rt_kprintf("Failed to create reply semaphore!\n");
+ return -RT_ENOMEM;
+ }
+
+ // 2. 构造命令
+ rt_memset(&cmd, 0, sizeof(cmd));
+ cmd.type = type;
+ rt_strncpy(cmd.sql, sql, MAX_SQL_LEN - 1);
+ cmd.reply_sem = sem;
+ cmd.send_tick = rt_tick_get();
+
+ // 3. 发送命令到消息队列
+ if (rt_mq_send(db_mq, &cmd, sizeof(cmd)) != RT_EOK)
+ {
+ rt_kprintf("Failed to send command to db_mq!\n");
+ rt_sem_delete(sem);
+ return -RT_ERROR;
+ }
+
+ // 4. 等待数据库线程处理完成(超时保护)
+ if (timeout_ms > 0)
+ {
+ rt_int32_t tick = rt_tick_from_millisecond(timeout_ms);
+ result = rt_sem_take(sem, tick);
+ }
+ else
+ {
+ result = rt_sem_take(sem, RT_WAITING_FOREVER); // 永久等待(慎用)
+ }
+
+ // 5. 检查结果
+ if (result == RT_EOK)
+ {
+ rt_kprintf("SQL executed: code=%d\n", cmd.result_code);
+ if (type == DB_CMD_SELECT || strlen(cmd.result) > 0)
+ {
+ rt_kprintf("Result: %s\n", cmd.result);
+ }
+ }
+ else if (result == -RT_ETIMEOUT)
+ {
+ rt_kprintf("Database response timeout!\n");
+ }
+ else
+ {
+ rt_kprintf("Wait failed: %d\n", result);
}
+ // 6. 删除信号量
+ rt_sem_delete(sem);
- // db_HelperInit = db_helper_init();
- // if(db_HelperInit =RT_EOK){
- // rt_kprintf("HelperInit database\n");
- // }else {
- // sqlite3_open(DB_NAME, db);
- // db_ = db_create_database("CREATE TABLE student(id INTEGER PRIMARY KEY AUTOINCREMENT,name varchar(32) NOT NULL,score INT NOT NULL);");
- // if(db_=0){rt_kprintf("database ok\n");}else{rt_kprintf("database no\n");}
- // }
- /* int fd = 0;
- const char *dbname = db_get_name();
- fd = open(dbname, O_RDONLY);
- if (fd > 0)
- rt_kprintf("%s exist\r\n", dbname);
- else
- rt_kprintf("%s not exist\r\n");
- const char *sql = "CREATE TABLE IF NOT EXISTS student(id INTEGER PRIMARY KEY AUTOINCREMENT,name varchar(32) NOT NULL,score INT NOT NULL);";
- rt_kprintf("sql cmd: %s\r\n\r\n", sql);
- int ret = db_create_database(sql);
- rt_kprintf("sql ret: %d\r\n", ret);*/
-
- // sqlite3_os_init();
- /* int rc = db_connect("/rt.db");
- if (rc <0) {
- const char *sql = "CREATE TABLE student(id INTEGER PRIMARY KEY AUTOINCREMENT,name varchar(32) NOT NULL,score INT NOT NULL);";
- int db_create_database(sql);
- }*/
+ return result;
}
/* 线程 */
@@ -291,7 +420,7 @@ void thread_DB_SQLite(void)
{
/* 初始化线程 1,名称是 thread1,入口是 thread1_entry*/
rt_thread_t tid;
- tid = rt_thread_create("db_sqlite", db_sqlite, RT_NULL, 1024*64, 3, 15);
+ tid = rt_thread_create("db_sqlite", db_sqlite, RT_NULL, 1024*16, 3, 15);
if (tid != RT_NULL)
{
diff --git a/applications/DBSQL/DB_SQLite.h b/applications/DBSQL/DB_SQLite.h
index 34de0eb..6551beb 100644
--- a/applications/DBSQL/DB_SQLite.h
+++ b/applications/DBSQL/DB_SQLite.h
@@ -10,6 +10,113 @@
#ifndef APPLICATIONS_DB_DB_SQLITE_H_
#define APPLICATIONS_DB_SQLITE_SYS_H_
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ========================
+ * 配置参数
+ * ======================== */
+#ifndef MAX_SQL_LEN
+#define MAX_SQL_LEN (1024) /**< SQL 语句最大长度 */
+#endif
+
+#ifndef MAX_RESULT_LEN
+#define MAX_RESULT_LEN (1024) /**< 结果字符串最大长度 */
+#endif
+
+#ifndef DB_MAX_WAITING_MS
+#define DB_MAX_WAITING_MS (5000) /**< 命令最大等待时间(毫秒),默认 5 秒 */
+#endif
+
+#ifndef DB_QUEUE_SIZE
+#define DB_QUEUE_SIZE (8) /**< 消息队列容量(最多缓存 8 条命令) */
+#endif
+
+/* 补充常见错误码(如果 RT-Thread 未定义) */
+#ifndef RT_ENODEV
+#define RT_ENODEV (-5)
+#endif
+
+#ifndef RT_ETIMEOUT
+#define RT_ETIMEOUT (-4)
+#endif
+
+
+/* ========================
+ * 命令类型枚举
+ * ======================== */
+enum db_cmd_type
+{
+ DB_CMD_INSERT, /**< 插入数据 */
+ DB_CMD_DELETE, /**< 删除数据 */
+ DB_CMD_UPDATE, /**< 更新数据 */
+ DB_CMD_SELECT, /**< 查询数据(返回结果字符串) */
+ DB_CMD_EXEC, /**< 执行任意 SQL(无结果集) */
+ DB_CMD_EXIT /**< 退出数据库线程(内部使用) */
+};
+
+/* ========================
+ * 数据库命令结构体
+ * ======================== */
+struct db_command
+{
+ enum db_cmd_type type; /**< 命令类型 */
+ char sql[MAX_SQL_LEN]; /**< SQL 语句内容 */
+ rt_uint32_t result_code; /**< 返回码(SQLite code 或负的 RT-Error) */
+ char result[MAX_RESULT_LEN]; /**< 结果或错误信息 */
+ rt_sem_t reply_sem; /**< 回应信号量(由调用方创建,用于同步) */
+ rt_tick_t send_tick; /**< 发送时刻的系统 tick,用于超时检测 */
+};
+
+/* ========================
+ * 全局变量声明
+ * ======================== */
+/**
+ * 消息队列句柄:用于向数据库线程发送命令
+ * 必须在 .c 文件中定义为:rt_mq_t db_mq = RT_NULL;
+ */
+extern rt_mq_t db_mq;
+
+
+/* ========================
+ * 函数接口声明
+ * ======================== */
+
+/**
+ * @brief 启动数据库处理线程
+ *
+ * 创建一个名为 "data_sqlite" 的线程,初始化 SQLite 数据库,
+ * 并开始监听 db_mq 中的 SQL 请求。
+ *
+ * @note 若已运行,多次调用无效。
+ */
void thread_DB_SQLite(void);
+/**
+ * @brief 立即关闭数据库并禁止后续操作
+ *
+ * 关闭当前数据库连接,并设置禁用标志。
+ * 之后所有新请求将立即失败,返回“数据库已禁用”。
+ *
+ * @note 此函数是线程安全的。
+ */
+void close_db_immediately(void);
+
+/**
+ * @brief 向数据库发送命令并等待响应
+ *
+ * @param type 命令类型(INSERT/SELECT等)
+ * @param sql SQL 语句字符串
+ * @param timeout_ms 超时时间(毫秒),0 表示不等待
+ * @return RT_EOK 成功,RT_ETIMEOUT 超时,RT_ERROR 失败
+ */
+rt_err_t db_send_command(enum db_cmd_type type, const char* sql, rt_int32_t timeout_ms);
+
+#ifdef __cplusplus
+}
+#endif
+
#endif /* APPLICATIONS_DB_DB_SQLITE_H_ */
diff --git a/rtconfig.h b/rtconfig.h
index cce01d1..4cfa15d 100644
--- a/rtconfig.h
+++ b/rtconfig.h
@@ -109,6 +109,8 @@
#define RT_SERIAL_USING_DMA
#define RT_SERIAL_RB_BUFSZ 64
#define RT_USING_PIN
+#define RT_USING_RTC
+#define RT_USING_SOFT_RTC
#define RT_USING_SDIO
#define RT_SDIO_STACK_SIZE 1024
#define RT_SDIO_THREAD_PRIORITY 15