|
|
@ -16,197 +16,171 @@ |
|
|
#include <dbhelper.h> |
|
|
#include <dbhelper.h> |
|
|
#define DB_NAME "/SC828.db" |
|
|
#define DB_NAME "/SC828.db" |
|
|
int db_HelperInit; |
|
|
int db_HelperInit; |
|
|
|
|
|
rt_mq_t db_mq = RT_NULL; //
|
|
|
sqlite3 **db; |
|
|
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 = |
|
|
static const char *sql_upgrade_workorder_steps = |
|
|
"CREATE TABLE WorkorderSteps (" |
|
|
"CREATE TABLE WorkorderSteps (WorkOrder VARCHAR,DYELOT VARCHAR,ProgramID VARCHAR,Program VARCHAR,ReDye INT DEFAULT (0)," |
|
|
"WorkOrder VARCHAR," |
|
|
"Mode VARCHAR,Step INT,StepID VARCHAR,StepName VARCHAR,ParameterName VARCHAR,P1 DOUBLE,P2 DOUBLE,P3 DOUBLE," |
|
|
"DYELOT VARCHAR," |
|
|
"P4 DOUBLE,P5 DOUBLE,P6 INT,P7 INT,P8 INT,P9 INT,P10 INT,Remark VARCHAR,StepTime INT,StepID_S1 VARCHAR," |
|
|
"ProgramID VARCHAR," |
|
|
"StepID_S2 VARCHAR,StepID_S3 VARCHAR,StepName_S1 VARCHAR,StepName_S2 VARCHAR,StepName_S3 VARCHAR,P1_S1 DOUBLE," |
|
|
"Program VARCHAR," |
|
|
"P1_S2 DOUBLE,P1_S3 DOUBLE,P2_S1 DOUBLE,P2_S2 DOUBLE,P2_S3 DOUBLE,P3_S1 DOUBLE,P3_S2 DOUBLE,P3_S3 DOUBLE," |
|
|
"ReDye INT DEFAULT (0)," |
|
|
"P4_S1 DOUBLE,P4_S2 DOUBLE,P4_S3 DOUBLE,P5_S1 DOUBLE,P5_S2 DOUBLE,P5_S3 DOUBLE); "; |
|
|
"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" |
|
|
|
|
|
"); "; |
|
|
|
|
|
|
|
|
|
|
|
static const char *sql_upgrade_workorder_set = |
|
|
static const char *sql_upgrade_workorder_set = |
|
|
"CREATE TABLE WorkOrderSet (" |
|
|
"CREATE TABLE WorkOrderSet (WorkOrder VARCHAR,ReDye INT DEFAULT (0),PumpSpeed INT,Blower INT,Swing INT,ClothWheel INT,Nozzle INT); "; |
|
|
"WorkOrder VARCHAR," |
|
|
|
|
|
"ReDye INT DEFAULT (0)," |
|
|
|
|
|
"PumpSpeed INT," |
|
|
|
|
|
"Blower INT," |
|
|
|
|
|
"Swing INT," |
|
|
|
|
|
"ClothWheel INT," |
|
|
|
|
|
"Nozzle INT" |
|
|
|
|
|
"); "; |
|
|
|
|
|
|
|
|
|
|
|
static const char *sql_upgrade_workorder = |
|
|
static const char *sql_upgrade_workorder = |
|
|
"CREATE TABLE WorkOrder (" |
|
|
"CREATE TABLE WorkOrder (WorkOrder VARCHAR,Dyelot VARCHAR,ReDyeINT DEFAULT (0),ProgramNameVARCHAR,StartTime DATETIME,EndTime DATETIME," |
|
|
"WorkOrder VARCHAR," |
|
|
"Time TEXT,lock INT,State INT,ProgramID VARCHAR,Machines VARCHAR,color VARCHAR,ColorNumber VARCHAR,Client VARCHAR,ClothWeight VARCHAR," |
|
|
"Dyelot VARCHAR," |
|
|
"ClothSpecies VARCHAR,BathRatio VARCHAR,Total VARCHAR,USER VARCHAR,ColorName VARCHAR,Remark TEXT); "; |
|
|
"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" |
|
|
|
|
|
"); "; |
|
|
|
|
|
|
|
|
|
|
|
static const char *sql_upgrade_run_table = |
|
|
static const char *sql_upgrade_run_table = |
|
|
// "PRAGMA foreign_keys = OFF; "
|
|
|
"CREATE TABLE RUN (WorkOrder VARCHAR,DYELOT VARCHAR,ProgramID VARCHAR,Program VARCHAR,ReDye INT DEFAULT (0)," |
|
|
// "BEGIN TRANSACTION; "
|
|
|
"Mode VARCHAR,Step INT,StepID VARCHAR,StepName VARCHAR,ParameterName VARCHAR,P1 DOUBLE,P2 DOUBLE,P3 DOUBLE," |
|
|
// "CREATE TABLE sqlitestudio_temp_table AS SELECT * FROM RUN; "
|
|
|
"P4 DOUBLE,P5 DOUBLE,P6 INT,P7 INT,P8 INT,P9 INT,P10 INT,Remark VARCHAR,StepTime INT,StepID_S1 VARCHAR," |
|
|
// "DROP TABLE RUN; "
|
|
|
"StepID_S2 VARCHAR,StepID_S3 VARCHAR,StepName_S1 VARCHAR,StepName_S2 VARCHAR,StepName_S3 VARCHAR,P1_S1 DOUBLE," |
|
|
"CREATE TABLE RUN (" |
|
|
"P1_S2 DOUBLE,P1_S3 DOUBLE,P2_S1 DOUBLE,P2_S2 DOUBLE,P2_S3 DOUBLE,P3_S1 DOUBLE,P3_S2 DOUBLE,P3_S3 DOUBLE," |
|
|
"WorkOrder VARCHAR," |
|
|
"P4_S1 DOUBLE,P4_S2 DOUBLE,P4_S3 DOUBLE,P5_S1 DOUBLE,P5_S2 DOUBLE,P5_S3 DOUBLE); "; |
|
|
"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" |
|
|
|
|
|
");"; |
|
|
|
|
|
|
|
|
|
|
|
static const char *sql_upgrade_dyelot_table = |
|
|
static const char *sql_upgrade_dyelot_table = |
|
|
"CREATE TABLE Dyelot (" |
|
|
"CREATE TABLE Dyelot (WorkOrder VARCHAR,Dyelot VARCHAR,ReDye INT,Machine VARCHAR,Step INT,Tank INT,State INT,ProductCode VARCHAR," |
|
|
"WorkOrder VARCHAR," |
|
|
"ProductName VARCHAR,ProductType INT,Grams FLOAT,Amount FLOAT,CALL_TIME VARCHAR,DispenseEndTime VARCHAR,Type INT); "; |
|
|
"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 = |
|
|
static const char *sql_upgrade_iolog_table = |
|
|
// "CREATE TABLE sqlitestudio_temp_table AS SELECT * FROM IOLog; "
|
|
|
"CREATE TABLE IOLog (ID varchar,IOName varchar,type varchar,Value DOUBLE DEFAULT (0),DIO BOOLEAN,AIO INTEGER DEFAULT (0),PLC varchar); "; |
|
|
// "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)" |
|
|
|
|
|
"); "; |
|
|
|
|
|
|
|
|
|
|
|
static const char *sql_upgrade_chart_table = |
|
|
static const char *sql_upgrade_chart_table = |
|
|
"CREATE TABLE Chart (" |
|
|
"CREATE TABLE Chart (WorkOrder varchar,DYELOT varchar,ReDye INTEGER,Name varchar,Time varchar,MTT DOUBLE DEFAULT (0),MTL DOUBLE DEFAULT (0)," |
|
|
"WorkOrder varchar(32)," |
|
|
"STTA DOUBLE DEFAULT (0),STLA DOUBLE DEFAULT (0),STTB DOUBLE DEFAULT (0),STLB DOUBLE DEFAULT (0),STTC DOUBLE DEFAULT (0)," |
|
|
"DYELOT varchar(32)," |
|
|
"STLC DOUBLE DEFAULT (0),MTH DOUBLE DEFAULT (0),MST DOUBLE DEFAULT (0),MSL DOUBLE DEFAULT (0),MUT DOUBLE DEFAULT (0)); "; |
|
|
"ReDye INTEGER ," |
|
|
|
|
|
"Name varchar(32)," |
|
|
// ------------------------
|
|
|
"Time varchar(32)," |
|
|
// 内部工具函数
|
|
|
"MTT DOUBLE DEFAULT (0)," |
|
|
// ------------------------
|
|
|
"MTL DOUBLE DEFAULT (0)," |
|
|
|
|
|
"STTA DOUBLE DEFAULT (0)," |
|
|
/**
|
|
|
"STLA DOUBLE DEFAULT (0)," |
|
|
* @brief 返回超时错误(排队时间过长) |
|
|
"STTB DOUBLE DEFAULT (0)," |
|
|
*/ |
|
|
"STLB DOUBLE DEFAULT (0)," |
|
|
static void return_timeout(struct db_command *cmd) { |
|
|
"STTC DOUBLE DEFAULT (0)," |
|
|
cmd->result_code = -RT_ETIMEOUT; |
|
|
"STLC DOUBLE DEFAULT (0)," |
|
|
rt_strncpy(cmd->result, "Cmd timeout: waited too long in queue", MAX_RESULT_LEN - 1); |
|
|
"MTH DOUBLE DEFAULT (0)," |
|
|
if (cmd->reply_sem) { |
|
|
"MST DOUBLE DEFAULT (0)," |
|
|
rt_sem_release(cmd->reply_sem); |
|
|
"MSL DOUBLE DEFAULT (0)," |
|
|
} |
|
|
"MUT DOUBLE DEFAULT (0)" |
|
|
} |
|
|
"); "; |
|
|
|
|
|
|
|
|
/**
|
|
|
void db_sqlite(void *parameter) |
|
|
* @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); |
|
|
|
|
|
{ |
|
|
|
|
|
if (g_db) { |
|
|
|
|
|
sqlite3_close(g_db); |
|
|
|
|
|
g_db = RT_NULL; |
|
|
|
|
|
} |
|
|
|
|
|
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) |
|
|
if (access(DB_NAME, F_OK) == 0) |
|
|
{ |
|
|
{ |
|
|
@ -241,7 +215,8 @@ void db_sqlite(void *parameter) |
|
|
{rt_kprintf("Chart Created successfully \n");}else{rt_kprintf("Chart Creation failed \n");} |
|
|
{rt_kprintf("Chart Created successfully \n");}else{rt_kprintf("Chart Creation failed \n");} |
|
|
} |
|
|
} |
|
|
}else{ |
|
|
}else{ |
|
|
rt_kprintf("DB open failed \n"); |
|
|
rt_kprintf("DB ok\n"); |
|
|
|
|
|
db_connect(DB_NAME); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
}else{ |
|
|
}else{ |
|
|
@ -256,34 +231,188 @@ void db_sqlite(void *parameter) |
|
|
db_create_database(sql_upgrade_iolog_table); |
|
|
db_create_database(sql_upgrade_iolog_table); |
|
|
db_create_database(sql_upgrade_chart_table); |
|
|
db_create_database(sql_upgrade_chart_table); |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @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; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 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; |
|
|
|
|
|
} |
|
|
|
|
|
// 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); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
rt_mutex_release(state_mutex); |
|
|
|
|
|
|
|
|
|
|
|
// 5. 执行命令
|
|
|
|
|
|
handle_db_command(&cmd); |
|
|
|
|
|
|
|
|
|
|
|
// 6. 返回结果
|
|
|
|
|
|
if (cmd.reply_sem) { |
|
|
|
|
|
rt_sem_release(cmd.reply_sem); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 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; |
|
|
|
|
|
|
|
|
// db_HelperInit = db_helper_init();
|
|
|
// 1. 创建临时信号量用于同步
|
|
|
// if(db_HelperInit =RT_EOK){
|
|
|
sem = rt_sem_create("db_rep", 0, RT_IPC_FLAG_FIFO); |
|
|
// rt_kprintf("HelperInit database\n");
|
|
|
if (sem == RT_NULL) |
|
|
// }else {
|
|
|
{ |
|
|
// sqlite3_open(DB_NAME, db);
|
|
|
rt_kprintf("Failed to create reply semaphore!\n"); |
|
|
// db_ = db_create_database("CREATE TABLE student(id INTEGER PRIMARY KEY AUTOINCREMENT,name varchar(32) NOT NULL,score INT NOT NULL);");
|
|
|
return -RT_ENOMEM; |
|
|
// if(db_=0){rt_kprintf("database ok\n");}else{rt_kprintf("database no\n");}
|
|
|
} |
|
|
// }
|
|
|
|
|
|
/* int fd = 0;
|
|
|
// 2. 构造命令
|
|
|
const char *dbname = db_get_name(); |
|
|
rt_memset(&cmd, 0, sizeof(cmd)); |
|
|
fd = open(dbname, O_RDONLY); |
|
|
cmd.type = type; |
|
|
if (fd > 0) |
|
|
rt_strncpy(cmd.sql, sql, MAX_SQL_LEN - 1); |
|
|
rt_kprintf("%s exist\r\n", dbname); |
|
|
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 |
|
|
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);"; |
|
|
result = rt_sem_take(sem, RT_WAITING_FOREVER); // 永久等待(慎用)
|
|
|
rt_kprintf("sql cmd: %s\r\n\r\n", sql); |
|
|
} |
|
|
int ret = db_create_database(sql); |
|
|
|
|
|
rt_kprintf("sql ret: %d\r\n", ret);*/ |
|
|
// 5. 检查结果
|
|
|
|
|
|
if (result == RT_EOK) |
|
|
// sqlite3_os_init();
|
|
|
{ |
|
|
/* int rc = db_connect("/rt.db");
|
|
|
rt_kprintf("SQL executed: code=%d\n", cmd.result_code); |
|
|
if (rc <0) { |
|
|
if (type == DB_CMD_SELECT || strlen(cmd.result) > 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); |
|
|
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); |
|
|
|
|
|
|
|
|
|
|
|
return result; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* 线程 */ |
|
|
/* 线程 */ |
|
|
@ -291,7 +420,7 @@ void thread_DB_SQLite(void) |
|
|
{ |
|
|
{ |
|
|
/* 初始化线程 1,名称是 thread1,入口是 thread1_entry*/ |
|
|
/* 初始化线程 1,名称是 thread1,入口是 thread1_entry*/ |
|
|
rt_thread_t tid; |
|
|
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) |
|
|
if (tid != RT_NULL) |
|
|
{ |
|
|
{ |
|
|
|