diff --git a/ems_c/clib/clib.tar.gz b/ems_c/clib/clib.tar.gz index d44f21e..8c812e2 100644 Binary files a/ems_c/clib/clib.tar.gz and b/ems_c/clib/clib.tar.gz differ diff --git a/ems_c/kernel/kit_db.c b/ems_c/kernel/kit_db.c deleted file mode 100644 index 26b9ca1..0000000 --- a/ems_c/kernel/kit_db.c +++ /dev/null @@ -1,3815 +0,0 @@ -/***************************************************************************** - * @copyright 2024-2024, . POWER SUPPLY CO., LTD. - * @file kit_db.c - * @brief sqlite3数据库操作方法 - * @author Gary - * @date 2024/09/10 - * @remark 去掉sqlite3_get_table即将过期的方法,补充了设备、协议和点位表的查询方法 - *****************************************************************************/ -#include -#include -#include -#include -#include "utextend.h" -#include "kit_log.h" -#include "kit_string.h" -#include "kit_db.h" - -#define CONFIG_SQLITE_PATH "/opt/company_ems/db/sqlite3.db" // 配置数据库 -#define BUSINESS_SQLITE_PATH "/opt/company_ems/db/business.db" // 业务数据库 - -static sqlite3 *config_db; // 全局变量,数据库句柄 -static sqlite3 *business_db; // 全局变量,业务数据库句柄 - -pthread_mutex_t config_db_mutex = PTHREAD_MUTEX_INITIALIZER; // 全局变量,配置数据库线程锁 -pthread_mutex_t business_db_mutex = PTHREAD_MUTEX_INITIALIZER; // 全局变量,业务数据库线程锁 - -// 设备配置信息icd -static UT_icd ems_dev_config_icd = -{ - sizeof(ems_dev_config_t), - NULL, - NULL, - NULL, -}; - -// 设备信息的icd -static UT_icd dev_icd = -{ - sizeof(dev_info_t), // 设备结构体大小 - NULL, // 初始化函数 - NULL, // 复制函数 - NULL, // 销毁函数 -}; - -// 点位信息icd -static UT_icd point_icd = -{ - sizeof(point_t), - NULL, - NULL, - NULL, -}; - -// 时序数据的icd -static UT_icd timed_data_config_icd = -{ - sizeof(timed_data_config_t), - NULL, - NULL, - NULL, -}; - -// 故障数据的icd -static UT_icd faults_data_config_icd = -{ - sizeof(faults_data_config_t), - NULL, - NULL, - NULL, -}; - -// 北向配置信息icd -static UT_icd north_config_icd = -{ - sizeof(north_config_t), - NULL, - NULL, - NULL, -}; - -// 削峰填谷日期配置信息icd -static UT_icd pv_date_config_icd = -{ - sizeof(pv_date_config_t), - NULL, - NULL, - NULL, -}; - -// 设备拓扑结构信息icd -static UT_icd topology_icd = -{ - sizeof(topology_t), - NULL, - NULL, - NULL, -}; - -static UT_icd advanced_setting_icd = -{ - sizeof(advanced_setting_t), - NULL, - NULL, - NULL, -}; - -// MQTT断点记录信息icd -static UT_icd break_record_icd = -{ - sizeof(break_record_t), - NULL, - NULL, - NULL, -}; - -// DIDO逻辑设置信息的icd -static UT_icd di_do_logic_set_icd = -{ - sizeof(di_do_logic_set_t), - NULL, - NULL, - NULL, -}; - -/***************************************************************************** - * @brief 检查文件夹是否存在 - * @param[in] path:文件夹路径 - * @return 存在-true,不存在-false - *****************************************************************************/ -static bool file_exists(const char *const path) -{ - struct stat buf = {0}; - if (-1 != stat(path, &buf) && S_ISDIR(buf.st_mode)) - { - return true; - } - else - { - return false; - } -} - -/***************************************************************************** - * @brief 拼接路径,将源路径拼接到目标路径的指定位置 - * @param[in] dst: 目标路径字符串 - * @param[in] offset: 拼接的起始位置(即从目标路径的何处开始拼接) - * @param[in] max_size: 目标路径的最大长度(缓冲区大小) - * @param[in] src: 源路径字符串 - * @return 返回拼接后的路径长度;如果拼接失败,则返回 -1 - *****************************************************************************/ -static int path_cat(char *dst, int offset, int max_size, const char *src) -{ - int len = strlen(src); - // 检查目标缓冲区是否足够容纳新拼接的路径 - if (offset + len >= max_size) - { - return -1; - } - // 将源路径复制到目标路径的指定位置 - strcpy(dst + offset, src); - return offset + len; -} - -/***************************************************************************** - * @brief 读取文件内容并存储为字符串 - * @param[in] path: 文件路径 - * @param[out] sql: 指向读取的字符串的指针,内存由该函数分配,调用者需负责释放 - * @return 0 表示成功,非 0 表示失败 - *****************************************************************************/ -static int read_file_string(const char *path, char **sql) -{ - FILE *fp = fopen(path, "r"); - if (fp == NULL) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "打开文件'%s'失败", path); - return 1; // 打开文件失败 - } - - // 获取文件大小 - fseek(fp, 0, SEEK_END); - long size = ftell(fp); - rewind(fp); - - // 分配足够的内存来存储文件内容 - *sql = malloc(size + 1); - if (*sql == NULL) - { - fclose(fp); - KITLOG(LOG_KIT_EN, ERROR_EN, "内存分配失败"); - return 1; // 内存分配失败 - } - - // 读取文件内容到内存中并检查读取结果 - size_t read_size = fread(*sql, 1, size, fp); - if (read_size != size) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "读取文件内容失败"); - free(*sql); - fclose(fp); - return 1; // 读取文件内容失败 - } - - (*sql)[size] = '\0'; // 添加字符串终止符 - - fclose(fp); - return 0; -} - -/***************************************************************************** - * @brief 判断字符串是否以指定后缀结尾 - * @param[in] str: 要检查的字符串 - * @param[in] suffix: 指定的后缀 - * @return 如果字符串以指定后缀结尾则返回 true,否则返回 false - *****************************************************************************/ -static bool ends_with(const char *str, const char *suffix) -{ - // 如果字符串的长度小于后缀的长度,直接返回 false - if (strlen(str) < strlen(suffix)) - { - return false; - } - // 比较字符串的结尾部分与后缀是否相等 - return strcmp(str + strlen(str) - strlen(suffix), suffix) == 0; -} - -/***************************************************************************** - * @brief 比较两个 schema 文件名,用于排序 - * @param[in] a: 第一个文件名 - * @param[in] b: 第二个文件名 - * @return 比较结果,用于排序函数 - *****************************************************************************/ -static int schema_sort_cmp(const void *a, const void *b) -{ - return strcmp(*(char **)a, *(char **)b); -} - -/***************************************************************************** - * @brief 收集目录中的所有 SQL 文件 - * @param[in] dir: 目录路径 - * @return 包含所有 SQL 文件名的 UT_array 指针;如果失败,则返回 NULL - *****************************************************************************/ -static UT_array *collect_schemas(const char *dir) -{ - DIR *dirp = NULL; - struct dirent *dent = NULL; - UT_array *files = NULL; - - // 打开目录 - if ((dirp = opendir(dir)) == NULL) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "文件夹打开失败: %s", dir); - return NULL; - } - - // 初始化 UT_array 用于存储文件名 - utarray_new(files, &ut_str_icd); - - // 遍历目录中的所有文件,筛选出以 ".sql" 结尾的文件 - while (NULL != (dent = readdir(dirp))) - { - if (ends_with(dent->d_name, ".sql")) - { - char *file = strdup(dent->d_name); // strdup 自动分配并拷贝字符串 - if (file == NULL) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "strdup 失败"); - continue; - } - // 将副本指针推入 UT_array - utarray_push_back(files, &file); - } - } - - // 关闭目录 - closedir(dirp); - return files; -} - -/***************************************************************************** - * @brief 执行目录中的所有 SQL 文件 - * @param[in] dir: 存储 SQL 文件的目录路径 - * @param[in] db: 数据库句柄 - * @return 0 表示成功,非 0 表示失败 - *****************************************************************************/ -static int execute_sql_files(const char *dir, sqlite3 *db) -{ - char *sql = NULL; - int ret = 0; - - if (!file_exists(dir)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "sql 文件 `%s` 不存在", dir); - return 1; - } - - // 获取目录下的所有 SQL 文件 - UT_array *files = collect_schemas(dir); - if (NULL == files) - { - return 1; // 目录读取失败 - } - - // 对文件名进行排序 - utarray_sort(files, schema_sort_cmp); - - // 遍历每个 SQL 文件 - utarray_foreach(files, char **, file) - { - char *path = NULL; - path = calloc(PATH_MAX_SIZE, sizeof(char)); - if (NULL == path) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "内存分配失败"); - return 1; - } - - // 拼接文件路径 - if (PATH_MAX_SIZE <= path_cat(path, 0, PATH_MAX_SIZE, dir) || - PATH_MAX_SIZE <= path_cat(path, strlen(dir), PATH_MAX_SIZE, *file)) - { // 修正了路径拼接问题 - KITLOG(LOG_KIT_EN, ERROR_EN, "路径过长: %s", path); - free(path); - return 1; - } - - // 读取 SQL 文件内容 - ret = read_file_string(path, &sql); - if (0 != ret) - { - free(path); - continue; // 读取失败,跳过该文件 - } - - // 执行 SQL 语句 - char *err_msg = NULL; - ret = sqlite3_exec(db, sql, NULL, NULL, &err_msg); - if (SQLITE_OK != ret) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "执行 %s 失败: (%d)%s", path, ret, err_msg); - sqlite3_free(err_msg); - ret = 1; - free(path); - free(sql); - continue; - } - - free(path); - free(sql); - } - - // 释放文件列表内存 - utarray_free(files); - return ret; -} - -/***************************************************************************** - * @brief 初始化 SQLite 数据库 - * @param[in] schema_dir: 存储 SQL 文件的目录路径 - * @param[in] db: 待初始化数据库 - * @return 0 表示成功,1 表示失败 - *****************************************************************************/ -static int init_db_handle(const char *schema_dir, sqlite3 *db) -{ - int ret = 0; - - // 设置忙时超时时间 - ret = sqlite3_busy_timeout(db, 120 * 1000); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "设置忙时超时失败: %s", sqlite3_errmsg(db)); - sqlite3_close(db); - return 1; - } - - // 启用外键支持 - ret = sqlite3_exec(db, "PRAGMA foreign_keys=ON", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "数据库外键启动失败: %s", sqlite3_errmsg(db)); - sqlite3_close(db); - return 1; - } - - // 设置 WAL 模式 - ret = sqlite3_exec(db, "PRAGMA journal_mode=WAL", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "数据库 journal_mode WAL 启动失败: %s", sqlite3_errmsg(db)); - sqlite3_close(db); - return 1; - } - -#ifdef INIT_DB - // 执行目录中的所有 SQL 文件 - ret = execute_sql_files(schema_dir, db); - if (ret != 0) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "执行 SQL 文件失败"); - sqlite3_close(db); - return 1; - } -#endif - - return 0; -} - -/***************************************************************************** - * @brief 根据北向上报下发设备Id获取点位信息 - * @param[in] upDisDevDbId: 上报下发设备Id - * @param[out] p_upDisDev: 用于存储北向配置信息的指针, 包含上报点位和下发设备信息 - * @return 0-成功 1-失败 - *****************************************************************************/ -static int kit_get_updis_dev_point(int upDisDevDbId, up_dis_dev_t *p_upDisDev) -{ - int ret = 0; - sqlite3_stmt *stmt = NULL; - char *query = "SELECT udd.dev_type, d.code, udp.cloud_code, " - "udp.cloud_name, udp.point_code " - "FROM up_dis_dev udd " - "LEFT JOIN device d ON udd.dev_id = d.id " - "LEFT JOIN up_dis_point udp ON udd.id = udp.up_dis_id " - "WHERE udd.id = ?"; - - if (sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL) != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询失败: %s", sqlite3_errmsg(config_db)); - return 1; - } - - if (sqlite3_bind_int(stmt, 1, upDisDevDbId) != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "绑定upDisDevDbId失败: %s", sqlite3_errmsg(config_db)); - sqlite3_finalize(stmt); - return 1; - } - - int step; - while ((step = sqlite3_step(stmt)) == SQLITE_ROW) - { - up_dis_point_t *temp = realloc(p_upDisDev->upDisPointArr, (p_upDisDev->upDisPointNum + 1) * sizeof(up_dis_point_t)); - if (temp == NULL) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "内存分配失败"); - ret = 1; - break; - } - p_upDisDev->upDisPointArr = temp; - up_dis_point_t *point = &p_upDisDev->upDisPointArr[p_upDisDev->upDisPointNum++]; - point->devType = (dev_type_e)sqlite3_column_int(stmt, 0); - point->devId = sqlite3_column_int(stmt, 1); - snprintf((char *)point->cloudCode, MAX_CODE_BUF_LEN, "%s", sqlite3_column_text(stmt, 2)); - snprintf((char *)point->cloudName, MAX_NAME_BUF_LEN, "%s", sqlite3_column_text(stmt, 3)); - point->pointId = sqlite3_column_int(stmt, 4); - } - - if (step != SQLITE_DONE && ret == 0) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询上报下发点位信息失败: %s", sqlite3_errmsg(config_db)); - ret = 1; - } - - sqlite3_finalize(stmt); - return ret; -} - -/***************************************************************************** - * @brief 根据北向配置ID获取上报下发配置信息 - * @param[in] northConfigDbId: 北向配置表数据库ID - * @param[out] northConfig: 用于存储北向配置信息的指针, 包含上报点位和下发点位信息 - * @return 0-成功 1-失败 - *****************************************************************************/ -static int kit_get_north_config_by_id(int northConfigDbId, north_config_t *northConfig) -{ - int ret = 0; - int upDisDevId; - sqlite3_stmt *stmt = NULL; - char *query = "SELECT udd.up_dis_config_type, udd.dev_type, d.code, " - "udd.id " - "FROM up_dis_dev udd " - "LEFT JOIN device d ON udd.dev_id = d.id " - "WHERE udd.north_config_id = ?"; - - // 准备 SQL 语句 - if (SQLITE_OK != sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL)) // config_db: 全局数据库连接 - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - return 1; - } - - // 绑定参数到预编译语句 - if (SQLITE_OK != sqlite3_bind_int(stmt, 1, northConfigDbId)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "绑定 northConfigId 失败: %s", sqlite3_errmsg(config_db)); - sqlite3_finalize(stmt); - return 1; // 返回错误代码 - } - - // 执行查询并处理结果 - int step = sqlite3_step(stmt); - while (SQLITE_ROW == step) - { - // 获取上报下发配置类型 - up_dis_config_type_e upDisConfigType = sqlite3_column_int(stmt, 0); - - // 根据配置类型分配内存并存储点位信息 - switch (upDisConfigType) - { - case kUp_Dis_Cfg_Type_Up: // 上报点位 - northConfig->upDevNum++; - // 分配内存以存储新的上报设备信息 - up_dis_dev_t *tempUp = (up_dis_dev_t *)realloc(northConfig->upDevArr, northConfig->upDevNum * sizeof(up_dis_dev_t)); - if (tempUp == NULL) - { - // 内存分配失败,记录错误信息并返回 - KITLOG(LOG_KIT_EN, ERROR_EN, "内存分配失败"); - ret = 1; - goto error; - } - northConfig->upDevArr = tempUp; - // 获取上报配置信息 - northConfig->upDevArr[northConfig->upDevNum - 1].devType = (dev_type_e)sqlite3_column_int(stmt, 1); // 设备类型 - northConfig->upDevArr[northConfig->upDevNum - 1].devId = sqlite3_column_int(stmt, 2); // 设备编号 - upDisDevId = sqlite3_column_int(stmt, 3); // 上报下发设备Id - kit_get_updis_dev_point(upDisDevId, &northConfig->upDevArr[northConfig->upDevNum - 1]); - break; - case kUp_Dis_Cfg_Type_Dis_Point: // 下发控制点位 - northConfig->disDevNum++; - // 分配内存以存储新的下发设备信息 - up_dis_dev_t *tempDis = (up_dis_dev_t *)realloc(northConfig->disDevArr, northConfig->disDevNum * sizeof(up_dis_dev_t)); - if (tempDis == NULL) - { - // 内存分配失败,记录错误信息并返回 - KITLOG(LOG_KIT_EN, ERROR_EN, "内存分配失败"); - ret = 1; - goto error; - } - northConfig->disDevArr = tempDis; - // 获取下发配置信息 - northConfig->disDevArr[northConfig->disDevNum - 1].devType = (dev_type_e)sqlite3_column_int(stmt, 1); // 设备类型 - northConfig->disDevArr[northConfig->disDevNum - 1].devId = sqlite3_column_int(stmt, 2); // 设备编号 - upDisDevId = sqlite3_column_int(stmt, 3); // 上报下发设备Id - kit_get_updis_dev_point(upDisDevId, &northConfig->disDevArr[northConfig->upDevNum - 1]); - break; - default: - KITLOG(LOG_KIT_EN, ERROR_EN, "未知的上报下发配置类型: %d", upDisConfigType); - ret = 1; - break; - } - - if (ret != 0) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "填充上报下发信息失败"); - sqlite3_finalize(stmt); - return 1; - } - - step = sqlite3_step(stmt); - } - - if (step != SQLITE_DONE) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询上报下发配置信息失败: %s", sqlite3_errmsg(config_db)); - ret = 1; - } - -error: - // 清理资源 - sqlite3_finalize(stmt); - return ret; -} - -/* ############################################################################### 配置数据库操作 ############################################################################### */ - -/***************************************************************************** - * @brief 初始化 SQLite 数据库 - * @param[in] schema_dir: 存储 SQL 文件的目录路径 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_init_db(const char *schema_dir) -{ - int ret = 0; - - // 打开配置数据库,如果不存在则创建 - // ret = sqlite3_open(CONFIG_SQLITE_PATH, &config_db); - ret = sqlite3_open_v2(CONFIG_SQLITE_PATH, &config_db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_WAL, NULL); - if (SQLITE_OK != ret) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "打开数据库 `%s` 失败: %s", CONFIG_SQLITE_PATH, sqlite3_errstr(ret)); - return 1; - } - char config_schema_dir[PATH_MAX_SIZE]; // 假设路径不会超过 PATH_MAX_SIZE 字符 - snprintf(config_schema_dir, PATH_MAX_SIZE, "%s/config/", schema_dir); - ret = init_db_handle(config_schema_dir, config_db); - if (0 != ret) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "初始化数据库 `%s` 失败", CONFIG_SQLITE_PATH); - return 1; - } - - // 打开业务数据库,如果不存在则创建 - // ret = sqlite3_open(BUSINESS_SQLITE_PATH, &business_db); - ret = sqlite3_open_v2(BUSINESS_SQLITE_PATH, &business_db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_WAL, NULL); - if (SQLITE_OK != ret) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "打开数据库 `%s` 失败: %s", BUSINESS_SQLITE_PATH, sqlite3_errstr(ret)); - return 1; - } - char business_schema_dir[PATH_MAX_SIZE]; // 假设路径不会超过 PATH_MAX_SIZE 字符 - snprintf(business_schema_dir, PATH_MAX_SIZE, "%s/business/", schema_dir); - ret = init_db_handle(business_schema_dir, business_db); - if (0 != ret) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "初始化数据库 `%s` 失败", BUSINESS_SQLITE_PATH); - return 1; - } - -#ifdef INIT_DB - kit_sync_dev_data(); // 同步设备信息 - kit_sync_point_data(); // 同步点位信息 -#endif - - return 0; -} - -/***************************************************************************** - * @brief 释放 SQLite 数据库连接 - * @return 0 表示成功,1 表示失败 - *****************************************************************************/ -int kit_uninit_db() -{ - if (config_db != NULL) - { - sqlite3_close(config_db); - config_db = NULL; - return 0; - } - if (business_db != NULL) - { - sqlite3_close(business_db); - business_db = NULL; - return 0; - } - return 1; -} - -/***************************************************************************** - * @brief 从 SQLite 数据库中获取数据表数据。使用准备好的语句(Prepared Statement)从 SQLite数据库中 - * 获取数据表数据,避免使用 `sqlite3_get_table`,因为它是一个过时的接口,存在安全和性能问题。 - * @param[out] outData: 用于存储查询结果的结构体指针。 - * @param[in] tableName: 数据表名称。 - * @param[in] columnsName: 要查询的列名数组,可以为 NULL 或空数组,表示查询所有列。 - * @param[in] columnNum: 要查询的列名数量。 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_db_data(db_table_data_t *outData, const char *tableName, const char *columnsName[], int columnNum) -{ - sqlite3_stmt *stmt = NULL; - int ret = 0; - char *sql = NULL; - char *sql_columns = NULL; - - // 构建 SQL 查询语句 - if (columnsName == NULL || columnNum == 0) - { - sql = sqlite3_mprintf("SELECT * FROM %s", tableName); - } - else - { - sql_columns = kit_join_text(columnNum, columnsName, ","); - if (sql_columns == NULL) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "构建列名失败"); - return 1; - } - sql = sqlite3_mprintf("SELECT %s FROM %s", sql_columns, tableName); - free(sql_columns); // 释放拼接好的列名字符串 - } - - if (sql == NULL) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "构建 SQL 语句失败: sqlite3_mprintf 失败"); - return 1; - } - - // 准备 SQL 语句 - sqlite3_free(sql); // 释放 SQL 字符串 - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备语句失败: %s", sqlite3_errmsg(config_db)); - sqlite3_finalize(stmt); // 结束语句 - return 1; - } - - // 获取查询结果 - outData->nrow = 0; - outData->ncolumn = sqlite3_column_count(stmt); // 获取列数 - - // 如果有列,继续处理 - if (outData->ncolumn > 0) - { - // 先检查有多少行 - while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) - { - outData->nrow++; - } - - // 如果没有找到行 - if (outData->nrow == 0) - { - KITLOG(LOG_KIT_EN, INFO_EN, "没有找到匹配的行"); - sqlite3_finalize(stmt); - return 0; - } - - // 为结果表分配内存 - outData->dbresult = (char **)sqlite3_malloc(outData->nrow * outData->ncolumn * sizeof(char *)); - if (outData->dbresult == NULL) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "分配结果表内存失败"); - sqlite3_finalize(stmt); - return 1; - } - - // 重置语句,重新开始读取 - sqlite3_reset(stmt); - - // 读取数据行并存储结果 - int row = 0; - while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) - { - for (int i = 0; i < outData->ncolumn; i++) - { - const char *text = (const char *)sqlite3_column_text(stmt, i); - outData->dbresult[row * outData->ncolumn + i] = text ? sqlite3_mprintf("%s", text) : NULL; - } - row++; - } - - if (ret != SQLITE_DONE) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "执行语句失败: %s", sqlite3_errmsg(config_db)); - sqlite3_finalize(stmt); - return 1; - } - } - - // 结束语句 - sqlite3_finalize(stmt); - - return 0; -} - -/***************************************************************************** - * @brief 释放 `db_table_data_t` 结构体中分配的内存。 - * 该函数用于释放 `kitGetDbData` 函数获取的查询结果数据所占用的内存。 - * 它会依次释放 `dbresult`、`errmsg` 和 `db` 指针指向的内存。 - * @param data 指向 `db_table_data_t` 结构体的指针。 - *****************************************************************************/ -void kit_free_table_data(db_table_data_t *data) -{ - if (data == NULL) - { - // 如果 `data` 指针为空,则直接返回。 - return; - } - - // 释放 `dbresult` 指向的内存,如果 `dbresult` 不为空。 - if (data->dbresult != NULL) - { - sqlite3_free_table(data->dbresult); - data->dbresult = NULL; - } - - // 释放 `errmsg` 指向的内存,如果 `errmsg` 不为空。 - if (data->errmsg != NULL) - { - sqlite3_free(data->errmsg); - data->errmsg = NULL; - } - - // 函数执行完毕,返回。 - return; -} - -/***************************************************************************** - * @brief: 执行多条 SQL 语句,函数内关闭连接。 - * 该函数用于执行多个 SQL 语句,并处理执行过程中的错误。 - * 它会依次执行传入的 SQL 语句数组,并在执行失败时记录错误信息。 - * 函数执行完毕后会关闭数据库连接。 - * @param[in] tableName: 数据表名称(未使用,可以忽略)。 - * @param[in] sql: 包含多个 SQL 语句的字符串数组。 - * @param[in] sql_num: SQL 语句的数量。 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_exec_db_data(char *tableName, char *sql[], int sql_num) -{ - sqlite3 *db = NULL; // 数据库连接指针 - int ret = 0; // sqlite3_exec 函数返回值 - char *zErrMsg = 0; // 错误信息指针 - - // 循环执行每个 SQL 语句 - for (int i = 0; i < sql_num; i++) - { - // printf("%s\n",sql[i]); // 可选:打印每个 SQL 语句 - ret = sqlite3_exec(db, sql[i], NULL, 0, &zErrMsg); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "执行 SQL 语句[%d] 失败: %s.", i, zErrMsg); - sqlite3_free(zErrMsg); // 释放错误信息内存 - return 1; - } - } - - sqlite3_free(zErrMsg); // 释放错误信息内存 - return 0; // 返回执行结果标志 -} - -/***************************************************************************** - * @brief 从数据库查询电站数据 - * @param[in] p_station:电站信息的指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_station_db_data(station_t *p_station) -{ - sqlite3_stmt *stmt = NULL; - char *query = sqlite3_mprintf("SELECT name, address, lng, lat, time_zone FROM station DESC LIMIT 1"); - - if (query == NULL) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "内存分配失败"); - return 1; - } - - if (SQLITE_OK != sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - sqlite3_free(query); - return 1; // 返回错误代码 - } - - int step = sqlite3_step(stmt); - - if (step == SQLITE_ROW) - { - snprintf((char *)p_station->name, MAX_NAME_BUF_LEN, "%s", (const char *)sqlite3_column_text(stmt, 0)); // 电站名称 - snprintf((char *)p_station->address, MAX_ADDR_BUF_LEN, "%s", (const char *)sqlite3_column_text(stmt, 1)); // 电站地址 - p_station->lng = sqlite3_column_double(stmt, 2); // 经度 - p_station->lat = sqlite3_column_double(stmt, 3); // 纬度 - snprintf((char *)p_station->timeZone, MAX_CODE_BUF_LEN, "%s", (const char *)sqlite3_column_text(stmt, 4)); // 时区 - } - else - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询失败,错误码: %d, 错误信息: %s", step, sqlite3_errmsg(config_db)); - } - - sqlite3_finalize(stmt); - sqlite3_free(query); - return (step == SQLITE_ROW) ? 0 : 1; // 返回成功或失败代码 -} - -/***************************************************************************** - * @brief 从数据库获取设备信息 - * @param[out] devPointInfo: 用于存储设备信息的 UT_array 指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_dev_db_data(UT_array **devPointInfo) -{ - sqlite3_stmt *stmt = NULL; // 预编译语句句柄 - const char *query; // 查询语句 - utarray_new(*devPointInfo, &dev_icd); // 创建新的 UT_array 用于存储设备点位信息 - - // 构建查询语句 - query = "SELECT id, type, code, protocol_type, name, " - "sort_order, template_id " - "FROM device WHERE 1=1 "; // 基础查询语句 - // 添加结果排序 - query = sqlite3_mprintf("%s ORDER BY type, protocol_type, id ASC", query); // 按 id 升序排序 - - // 准备 SQL 语句 - if (SQLITE_OK != sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - goto error; // 处理错误 - } - - // 执行查询并处理结果 - int step = sqlite3_step(stmt); - while (SQLITE_ROW == step) // 遍历每一行结果 - { - // 从数据库中获取每一列的值 - dev_info_t dev_info = {0}; // 初始化设备点位结构体 - dev_info.devDbId = sqlite3_column_int(stmt, 0); - dev_info.devType = sqlite3_column_int(stmt, 1); - dev_info.devId = sqlite3_column_int(stmt, 2); - dev_info.protocolType = sqlite3_column_int(stmt, 3); - snprintf((char *)dev_info.devName, MAX_NAME_BUF_LEN, "%s", (const char *)sqlite3_column_text(stmt, 4)); - dev_info.sortOrder = sqlite3_column_int(stmt, 5); - dev_info.templateId = sqlite3_column_int(stmt, 6); - - // 将设备点位信息添加到 UT_array 中 - utarray_push_back(*devPointInfo, &dev_info); - - // 继续处理下一行 - step = sqlite3_step(stmt); - } - - // 检查是否完成所有行的处理 - if (SQLITE_DONE != step) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询未完成,错误信息: %s", sqlite3_errmsg(config_db)); - goto error; // 处理错误 - } - - // 清理资源 - sqlite3_finalize(stmt); // 释放预编译语句 - return 0; // 成功返回 - -error: - sqlite3_finalize(stmt); // 确保释放预编译语句 - utarray_free(*devPointInfo); // 释放 UT_array - devPointInfo = NULL; // 设置为 NULL - return 1; // 返回错误代码 -} - -/***************************************************************************** - * @brief 将 config_db 中的 device 表数据复制到 business_db 中的 device 表 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_sync_dev_data() -{ - sqlite3_stmt *stmt_select = NULL; // 用于 SELECT 语句 - sqlite3_stmt *stmt_insert = NULL; // 用于 INSERT 语句 - const char *sql_delete; - const char *sql_select; - const char *sql_insert; - int ret; - - pthread_mutex_lock(&config_db_mutex); // 给配置库操作上锁 - pthread_mutex_lock(&business_db_mutex); // 给业务库操作上锁 - - // 清空 business_db 中的 device 表 - sql_delete = "DELETE FROM device"; - ret = sqlite3_exec(business_db, sql_delete, NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "清空 business_db 中的 device 表失败: %s", sqlite3_errmsg(business_db)); - goto error; - } - - // 从 config_db 中选择数据 - sql_select = "SELECT id, sn, type, code, name, protocol_type, template_id, sort_order, remark, status FROM device"; - ret = sqlite3_prepare_v2(config_db, sql_select, -1, &stmt_select, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", sql_select, sqlite3_errmsg(config_db)); - goto error; - } - - // 准备插入语句 - sql_insert = "INSERT INTO device (id, sn, type, code, name, protocol_type, template_id, sort_order, remark, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; - ret = sqlite3_prepare_v2(business_db, sql_insert, -1, &stmt_insert, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备插入语句 `%s` 失败: %s", sql_insert, sqlite3_errmsg(business_db)); - goto error; - } - - // 循环插入数据 - while ((ret = sqlite3_step(stmt_select)) == SQLITE_ROW) - { - // 绑定参数 - sqlite3_bind_int(stmt_insert, 1, sqlite3_column_int(stmt_select, 0)); - sqlite3_bind_text(stmt_insert, 2, (const char *)sqlite3_column_text(stmt_select, 1), -1, SQLITE_STATIC); - sqlite3_bind_int(stmt_insert, 3, sqlite3_column_int(stmt_select, 2)); - sqlite3_bind_int(stmt_insert, 4, sqlite3_column_int(stmt_select, 3)); - sqlite3_bind_text(stmt_insert, 5, (const char *)sqlite3_column_text(stmt_select, 4), -1, SQLITE_STATIC); - sqlite3_bind_int(stmt_insert, 6, sqlite3_column_int(stmt_select, 5)); - sqlite3_bind_int(stmt_insert, 7, sqlite3_column_int(stmt_select, 6)); - sqlite3_bind_int(stmt_insert, 8, sqlite3_column_int(stmt_select, 7)); - sqlite3_bind_text(stmt_insert, 9, (const char *)sqlite3_column_text(stmt_select, 8), -1, SQLITE_STATIC); - sqlite3_bind_int(stmt_insert, 10, sqlite3_column_int(stmt_select, 9)); - - // 执行插入 - ret = sqlite3_step(stmt_insert); - sqlite3_reset(stmt_insert); // 重置语句以进行下一次插入 - if (ret != SQLITE_DONE) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "插入数据失败: %s", sqlite3_errmsg(business_db)); - goto error; - } - } - - // 检查是否有错误发生在sqlite3_step(stmt_select)中 - if (ret != SQLITE_DONE) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询数据失败: %s", sqlite3_errmsg(config_db)); - goto error; - } - - // 清理资源 - sqlite3_finalize(stmt_select); - sqlite3_finalize(stmt_insert); - pthread_mutex_unlock(&config_db_mutex); // 给配置库操作释放锁 - pthread_mutex_unlock(&business_db_mutex); // 给业务库操作释放锁 - return 0; - -error: - sqlite3_finalize(stmt_select); - sqlite3_finalize(stmt_insert); - pthread_mutex_unlock(&config_db_mutex); // 给配置库操作释放锁 - pthread_mutex_unlock(&business_db_mutex); // 给业务库操作释放锁 - return 1; -} - -/***************************************************************************** - * @brief 从数据库获取协议信息。 - * 该函数从数据库中获取与指定设备 ID 关联的协议信息。 - * 它使用准备好的语句(Prepared Statement)来执行查询,并绑定设备 ID 参数。 - * 函数会返回获取到的协议信息,并处理查询过程中的错误。 - * @param[in] templateType: 模板类别(0设备配置, 1北向配置)。 - * @param[in] relatedId: 关联数据库 ID。 - * @param[out] protoContent: 用于存储协议信息的字符数组。 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_protocol_db_data(const template_type_e templateType, const uint64_t relatedId, char protoContent[MAX_CONFIG_CONTENT_LEN]) -{ - sqlite3_stmt *stmt = NULL; // 预编译语句句柄 - char *query = sqlite3_mprintf("SELECT content FROM protocol WHERE 1=1 AND template_type=? AND related_id=? LIMIT 1"); - - // 准备 SQL 语句 - if (SQLITE_OK != sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - sqlite3_free(query); // 释放查询字符串 - return 1; // 返回错误代码 - } - - // 绑定参数到预编译语句 - if (SQLITE_OK != sqlite3_bind_int(stmt, 1, templateType)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "绑定 template_type 失败: %s", sqlite3_errmsg(config_db)); - sqlite3_finalize(stmt); - sqlite3_free(query); // 释放查询字符串 - return 1; // 返回错误代码 - } - if (SQLITE_OK != sqlite3_bind_int64(stmt, 2, relatedId)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "绑定 related_id 失败: %s", sqlite3_errmsg(config_db)); - sqlite3_finalize(stmt); - sqlite3_free(query); // 释放查询字符串 - return 1; // 返回错误代码 - } - - // 执行查询并处理结果 - int step = sqlite3_step(stmt); - if (step == SQLITE_ROW || step == SQLITE_DONE) - { - snprintf(protoContent, MAX_CONFIG_CONTENT_LEN, "%s", sqlite3_column_text(stmt, 0)); - } - else - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询未完成,错误信息: %s", sqlite3_errmsg(config_db)); - sqlite3_finalize(stmt); - sqlite3_free(query); // 释放查询字符串 - return 1; // 返回错误代码 - } - - // 清理资源 - sqlite3_finalize(stmt); // 释放预编译语句 - sqlite3_free(query); // 释放查询字符串 - return 0; // 成功返回 -} - -/***************************************************************************** - * @brief 从数据库获取点位信息 - * @param[in] templateId: 模板Id - * @param[out] points: 用于存储点位信息的 UT_array 指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_point_db_data(const uint64_t templateId, UT_array **points) -{ - sqlite3_stmt *stmt = NULL; // 预编译语句句柄 - const char *query; // 查询语句 - utarray_new(*points, &point_icd); // 创建新的 UT_array 用于存储设备点位信息 - - // 构建查询语句 - query = "SELECT group_type, code, name, data_type, " - "attribute, func, reg_addr, bit_pos, bit_num, endian, " - "precision, ratio, offset, is_persisted, storage_interval, " - "mutate_bound, default_value, min_value, max_value, dev_type,id " - "FROM point WHERE 1=1 "; // 基础查询语句 - - // 检查并添加设备Id条件 - query = sqlite3_mprintf("%s AND template_id=?", query); // 动态添加设备Id条件 - - // 添加结果排序 - query = sqlite3_mprintf("%s ORDER BY func, reg_addr ASC", query); // 按 id 升序排序 - - // 准备 SQL 语句 - if (SQLITE_OK != sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - goto error; // 处理错误 - } - - // 绑定参数到预编译语句 - int param_index = 1; // 参数索引 - if (SQLITE_OK != sqlite3_bind_int64(stmt, param_index++, templateId)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "绑定 `%s` 的参数 dev_id 失败: %s", query, sqlite3_errmsg(config_db)); - goto error; // 处理错误 - } - - // printf("%s\n",query); - // 执行查询并处理结果 - int step = sqlite3_step(stmt); - while (SQLITE_ROW == step) // 遍历每一行结果 - { - // 从数据库中获取每一列的值 - point_t point_info = {0}; // 初始化设备点位结构体 - point_info.groupType = (point_group_type_e)sqlite3_column_int(stmt, 0); - point_info.pointId = (uint16_t)sqlite3_column_int(stmt, 1); - snprintf((char *)point_info.pointName, MAX_POINT_NAME_LEN, "%s", (const char *)sqlite3_column_text(stmt, 2)); - point_info.dataType = (data_type_e)sqlite3_column_int(stmt, 3); - point_info.attribute = (point_attribute_e)sqlite3_column_int(stmt, 4); - point_info.func = (uint32_t)sqlite3_column_int(stmt, 5); - point_info.regAddr = (uint16_t)sqlite3_column_int(stmt, 6); - point_info.bitPos = (uint8_t)sqlite3_column_int(stmt, 7); - point_info.bitNum = (uint8_t)sqlite3_column_int(stmt, 8); - point_info.endian = (data_endian_e)sqlite3_column_int(stmt, 9); - point_info.precision = sqlite3_column_double(stmt, 10); - point_info.ratio = sqlite3_column_double(stmt, 11); - point_info.offset = sqlite3_column_double(stmt, 12); - point_info.isPersisted = (uint8_t)sqlite3_column_int(stmt, 13); - point_info.storageInterval = (storage_interval_type_e)sqlite3_column_int(stmt, 14); - point_info.mutateBound = sqlite3_column_double(stmt, 15); - point_info.defaultValue = sqlite3_column_double(stmt, 16); - point_info.minValue = sqlite3_column_double(stmt, 17); - point_info.maxValue = sqlite3_column_double(stmt, 18); - point_info.devType = sqlite3_column_int(stmt, 19); - point_info.pointDbId = sqlite3_column_int(stmt, 20); - // point_info.devDbId = sqlite3_column_int(stmt, 20); - - // 将设备点位信息添加到 UT_array 中 - utarray_push_back(*points, &point_info); - - // 继续处理下一行 - step = sqlite3_step(stmt); - } - - // 检查是否完成所有行的处理 - if (SQLITE_DONE != step) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询未完成,错误信息: %s", sqlite3_errmsg(config_db)); - goto error; // 处理错误 - } - - // 清理资源 - sqlite3_finalize(stmt); // 释放预编译语句 - return 0; // 成功返回 - -error: - sqlite3_finalize(stmt); // 确保释放预编译语句 - utarray_free(*points); // 释放 UT_array - points = NULL; // 设置为 NULL - return 1; // 返回错误代码 -} - -/***************************************************************************** - * @brief 从 config_db 获取点位信息并同步到 business_db - * @param[out] 无 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_sync_point_data() -{ - sqlite3_stmt *stmt_config = NULL; // config_db 中的预编译语句句柄 - sqlite3_stmt *stmt_business = NULL; // business_db 中的预编译语句句柄 - const char *query_config; // 从 config_db 查询点位信息的 SQL 语句 - const char *query_clear = "DELETE FROM point"; // 清空 business_db 中的 point 表的 SQL 语句 - int step; // 查询结果步骤 - - pthread_mutex_lock(&config_db_mutex); // 给配置库操作上锁 - pthread_mutex_lock(&business_db_mutex); // 给业务库操作上锁 - - // 清空 business_db 中的 point 表 - if (SQLITE_OK != sqlite3_exec(business_db, query_clear, NULL, NULL, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "清空 business_db 中的 point 表失败: %s", sqlite3_errmsg(business_db)); - pthread_mutex_unlock(&config_db_mutex); // 给配置库操作释放锁 - pthread_mutex_unlock(&business_db_mutex); // 给业务库操作释放锁 - return 1; // 处理错误 - } - - // 构建查询语句从 config_db 获取所有点位信息 - query_config = "SELECT template_id, protocol_type, dev_type, group_type, code, name, " - "data_type, attribute, func, reg_addr, bit_pos, bit_num, endian, precision, " - "ratio, offset, is_persisted, storage_interval, mutate_bound, default_value, " - "min_value, max_value, unit, is_show FROM point ORDER BY id ASC"; - - // 准备从 config_db 执行查询语句 - if (SQLITE_OK != sqlite3_prepare_v2(config_db, query_config, -1, &stmt_config, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query_config, sqlite3_errmsg(config_db)); - pthread_mutex_unlock(&config_db_mutex); // 给配置库操作释放锁 - pthread_mutex_unlock(&business_db_mutex); // 给业务库操作释放锁 - return 1; // 处理错误 - } - - // 准备向 business_db 插入数据的 SQL 语句 - const char *insert_query = "INSERT INTO point (template_id, protocol_type, dev_type, group_type, " - "code, name, data_type, attribute, func, reg_addr, bit_pos, bit_num, endian, " - "precision, ratio, offset, is_persisted, storage_interval, mutate_bound, " - "default_value, min_value, max_value, unit, is_show) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; - - // 准备向 business_db 插入数据 - if (SQLITE_OK != sqlite3_prepare_v2(business_db, insert_query, -1, &stmt_business, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备插入 `%s` 失败: %s", insert_query, sqlite3_errmsg(business_db)); - sqlite3_finalize(stmt_config); // 确保释放预编译语句 - pthread_mutex_unlock(&config_db_mutex); // 给配置库操作释放锁 - pthread_mutex_unlock(&business_db_mutex); // 给业务库操作释放锁 - return 1; // 处理错误 - } - - // 执行查询并插入数据 - step = sqlite3_step(stmt_config); - while (SQLITE_ROW == step) // 遍历每一行结果 - { - // 从 config_db 中获取每一列的值 - int param_index = 1; // 参数索引 - - // 绑定参数到插入语句 - if (SQLITE_OK != sqlite3_bind_int64(stmt_business, param_index++, sqlite3_column_int64(stmt_config, 0))) // template_id - goto error; - if (SQLITE_OK != sqlite3_bind_int(stmt_business, param_index++, sqlite3_column_int(stmt_config, 1))) // protocol_type - goto error; - if (SQLITE_OK != sqlite3_bind_int(stmt_business, param_index++, sqlite3_column_int(stmt_config, 2))) // dev_type - goto error; - if (SQLITE_OK != sqlite3_bind_int(stmt_business, param_index++, sqlite3_column_int(stmt_config, 3))) // group_type - goto error; - if (SQLITE_OK != sqlite3_bind_int(stmt_business, param_index++, sqlite3_column_int(stmt_config, 4))) // code - goto error; - if (SQLITE_OK != sqlite3_bind_text(stmt_business, param_index++, sqlite3_column_text(stmt_config, 5), -1, SQLITE_STATIC)) // name - goto error; - if (SQLITE_OK != sqlite3_bind_int(stmt_business, param_index++, sqlite3_column_int(stmt_config, 6))) // data_type - goto error; - if (SQLITE_OK != sqlite3_bind_int(stmt_business, param_index++, sqlite3_column_int(stmt_config, 7))) // attribute - goto error; - if (SQLITE_OK != sqlite3_bind_int(stmt_business, param_index++, sqlite3_column_int(stmt_config, 8))) // func - goto error; - if (SQLITE_OK != sqlite3_bind_int(stmt_business, param_index++, sqlite3_column_int(stmt_config, 9))) // reg_addr - goto error; - if (SQLITE_OK != sqlite3_bind_int(stmt_business, param_index++, sqlite3_column_int(stmt_config, 10))) // bit_pos - goto error; - if (SQLITE_OK != sqlite3_bind_int(stmt_business, param_index++, sqlite3_column_int(stmt_config, 11))) // bit_num - goto error; - if (SQLITE_OK != sqlite3_bind_int(stmt_business, param_index++, sqlite3_column_int(stmt_config, 12))) // endian - goto error; - if (SQLITE_OK != sqlite3_bind_double(stmt_business, param_index++, sqlite3_column_double(stmt_config, 13))) // precision - goto error; - if (SQLITE_OK != sqlite3_bind_double(stmt_business, param_index++, sqlite3_column_double(stmt_config, 14))) // ratio - goto error; - if (SQLITE_OK != sqlite3_bind_double(stmt_business, param_index++, sqlite3_column_double(stmt_config, 15))) // offset - goto error; - if (SQLITE_OK != sqlite3_bind_int(stmt_business, param_index++, sqlite3_column_int(stmt_config, 16))) // is_persisted - goto error; - if (SQLITE_OK != sqlite3_bind_int(stmt_business, param_index++, sqlite3_column_int(stmt_config, 17))) // storage_interval - goto error; - if (SQLITE_OK != sqlite3_bind_double(stmt_business, param_index++, sqlite3_column_double(stmt_config, 18))) // mutate_bound - goto error; - if (SQLITE_OK != sqlite3_bind_double(stmt_business, param_index++, sqlite3_column_double(stmt_config, 19))) // default_value - goto error; - if (SQLITE_OK != sqlite3_bind_double(stmt_business, param_index++, sqlite3_column_double(stmt_config, 20))) // min_value - goto error; - if (SQLITE_OK != sqlite3_bind_double(stmt_business, param_index++, sqlite3_column_double(stmt_config, 21))) // max_value - goto error; - if (SQLITE_OK != sqlite3_bind_text(stmt_business, param_index++, sqlite3_column_text(stmt_config, 22), -1, SQLITE_STATIC)) // unit - goto error; - if (SQLITE_OK != sqlite3_bind_int(stmt_business, param_index++, sqlite3_column_int(stmt_config, 23))) // is_show - goto error; - - // 执行插入操作 - if (SQLITE_DONE != sqlite3_step(stmt_business)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "插入数据失败: %s", sqlite3_errmsg(business_db)); - goto error; - } - - // 重置插入语句以便于重新绑定参数 - sqlite3_reset(stmt_business); - - // 继续处理下一行 - step = sqlite3_step(stmt_config); - } - - // 检查是否完成所有行的处理 - if (SQLITE_DONE != step) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询未完成,错误信息: %s", sqlite3_errmsg(config_db)); - goto error; // 处理错误 - } - - // 清理资源 - sqlite3_finalize(stmt_config); // 释放 config_db 预编译语句 - sqlite3_finalize(stmt_business); // 释放 business_db 预编译语句 - pthread_mutex_unlock(&config_db_mutex); // 给配置库操作释放锁 - pthread_mutex_unlock(&business_db_mutex); // 给业务库操作释放锁 - return 0; // 成功返回 - -error: - sqlite3_finalize(stmt_config); // 确保释放预编译语句 - sqlite3_finalize(stmt_business); // 确保释放预编译语句 - pthread_mutex_unlock(&config_db_mutex); // 给配置库操作释放锁 - pthread_mutex_unlock(&business_db_mutex); // 给业务库操作释放锁 - return 1; // 返回错误代码 -} - -/***************************************************************************** - * @brief 从数据库获取读取时序数据配置 - * @param[out] timedDataConfigs: 用于指定存储间隔类型的的时序数据配置的数据 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_tdata_config(UT_array **timedDataConfigs) -{ - sqlite3_stmt *stmt = NULL; - char *query = sqlite3_mprintf("SELECT p.id, p.code, p.name, p.storage_interval, d.name, d.type, d.id, d.code FROM point p LEFT JOIN device d ON p.template_id = d.template_id ORDER BY p.storage_interval ASC"); - int ret; - - ret = sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - sqlite3_free(query); - return 1; - } - - utarray_new(*timedDataConfigs, &timed_data_config_icd); - - while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) - { - timed_data_config_t data_info = {0}; - data_info.pointDbId = sqlite3_column_int(stmt, 0); - data_info.pointId = sqlite3_column_int(stmt, 1); - snprintf((char *)data_info.pointName, MAX_POINT_NAME_LEN, "%s", (const char *)sqlite3_column_text(stmt, 2)); - data_info.storageInterval = (storage_interval_type_e)sqlite3_column_int(stmt, 3); - snprintf((char *)data_info.devName, MAX_NAME_BUF_LEN, "%s", (const char *)sqlite3_column_text(stmt, 4)); - data_info.devType = sqlite3_column_int(stmt, 5); - data_info.devDbId = sqlite3_column_int(stmt, 6); - data_info.devId = sqlite3_column_int(stmt, 7); - - utarray_push_back(*timedDataConfigs, &data_info); - } - - if (ret != SQLITE_DONE) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询失败: %s", sqlite3_errmsg(config_db)); - sqlite3_finalize(stmt); - sqlite3_free(query); - utarray_free(*timedDataConfigs); - *timedDataConfigs = NULL; - return 1; - } - - sqlite3_finalize(stmt); - sqlite3_free(query); - return 0; -} - -/***************************************************************************** - * @brief 从数据库获取故障点位配置 - * @param[out] faultsDataConfigs: 用于存储故障配置点位的数据 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_faults_config(UT_array **faultsDataConfigs) -{ - sqlite3_stmt *stmt = NULL; - char *query = sqlite3_mprintf("SELECT p.id, p.code, p.name, d.name, d.type, d.id, d.code FROM point p LEFT JOIN device d ON p.template_id = d.template_id WHERE p.group_type = ? ORDER BY p.storage_interval ASC"); - int ret; - - ret = sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - sqlite3_free(query); - return 1; - } - - // 绑定参数 - if (SQLITE_OK != sqlite3_bind_int(stmt, 1, kPoint_SOE)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "绑定 group_type 失败: %s", sqlite3_errmsg(config_db)); - sqlite3_finalize(stmt); - return 1; // 返回错误代码 - } - - utarray_new(*faultsDataConfigs, &faults_data_config_icd); - - while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) - { - timed_data_config_t data_info = {0}; - data_info.pointDbId = sqlite3_column_int(stmt, 0); - data_info.pointId = sqlite3_column_int(stmt, 1); - snprintf((char *)data_info.pointName, MAX_POINT_NAME_LEN, "%s", (const char *)sqlite3_column_text(stmt, 2)); - snprintf((char *)data_info.devName, MAX_NAME_BUF_LEN, "%s", (const char *)sqlite3_column_text(stmt, 3)); - data_info.devType = sqlite3_column_int(stmt, 4); - data_info.devDbId = sqlite3_column_int(stmt, 5); - data_info.devId = sqlite3_column_int(stmt, 6); - - utarray_push_back(*faultsDataConfigs, &data_info); - } - - if (ret != SQLITE_DONE) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询失败: %s", sqlite3_errmsg(config_db)); - sqlite3_finalize(stmt); - sqlite3_free(query); - utarray_free(*faultsDataConfigs); - *faultsDataConfigs = NULL; - return 1; - } - - sqlite3_finalize(stmt); - sqlite3_free(query); - return 0; -} - -/***************************************************************************** - * @brief 从数据库获取EMS设备配置信息 - * @param[out] emsDevConfigs: 用于设备配置信息的 UT_array 指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_config_db_data(UT_array **emsDevConfigs) -{ - sqlite3_stmt *stmt = NULL; // 预编译语句句柄 - const char *query; // 查询语句 - - utarray_new(*emsDevConfigs, &ems_dev_config_icd); // 创建新的 UT_array 用于存储设备点位信息 - - // 构建查询语句 - query = "SELECT id, type, content " - "FROM ems_device_config WHERE 1=1 "; // 基础查询语句 - - // 添加结果排序 - query = sqlite3_mprintf("%s ORDER BY type ASC", query); // 按 type 升序排序 - - // 准备 SQL 语句 - if (SQLITE_OK != sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - goto error; // 处理错误 - } - - // 执行查询并处理结果 - int step = sqlite3_step(stmt); - while (SQLITE_ROW == step) // 遍历每一行结果 - { - // 从数据库中获取每一列的值 - ems_dev_config_t dev_config = {0}; // 初始化设备配置结构体 - dev_config.dbId = (uint16_t)sqlite3_column_int(stmt, 0); - dev_config.type = (ems_dev_config_type_e)sqlite3_column_int(stmt, 1); - snprintf((char *)dev_config.content, MAX_CONFIG_CONTENT_LEN, "%s", (const char *)sqlite3_column_text(stmt, 2)); - - // 将设备配置信息添加到 UT_array 中 - utarray_push_back(*emsDevConfigs, &dev_config); - - // 继续处理下一行 - step = sqlite3_step(stmt); - } - - // 检查是否完成所有行的处理 - if (SQLITE_DONE != step) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询未完成,错误信息: %s", sqlite3_errmsg(config_db)); - goto error; // 处理错误 - } - - // 清理资源 - sqlite3_finalize(stmt); // 释放预编译语句 - return 0; // 成功返回 - -error: - sqlite3_finalize(stmt); // 确保释放预编译语句 - utarray_free(*emsDevConfigs); // 释放 UT_array - emsDevConfigs = NULL; // 设置为 NULL - return 1; // 返回错误代码 -} - -/***************************************************************************** - * @brief 根据指定配置类型Type从数据库获取 EMS 设备配置信息 - * @param[in] type: 配置类型 - * @param[out] emsDevConfig: 用于存储设备配置信息的指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_config_by_type(ems_dev_config_type_e type, ems_dev_config_t *emsDevConfig) -{ - int ret = 0; // 返回代码 - sqlite3_stmt *stmt = NULL; // 预编译语句句柄 - const char *query; // 查询语句 - - // 构建查询语句 - query = "SELECT content " - "FROM ems_device_config WHERE type = ? LIMIT 1"; // 根据 TYPE 查询 - - // 准备 SQL 语句 - if (SQLITE_OK != sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - return 1; // 返回错误代码 - } - - if (SQLITE_OK != sqlite3_bind_int(stmt, 1, (int)type)) // 使用 sqlite3_bind_int - { - KITLOG(LOG_KIT_EN, ERROR_EN, "绑定 `%s` 的参数 type 失败: %s", query, sqlite3_errmsg(config_db)); - sqlite3_finalize(stmt); // 确保释放预编译语句 - return 1; // 返回错误代码 - } - - // 执行查询并处理结果 - int step = sqlite3_step(stmt); - if (SQLITE_ROW == step) // 如果找到结果 - { - // 从数据库中获取每一列的值 - snprintf((char *)emsDevConfig->content, MAX_CONFIG_CONTENT_LEN, "%s", (const char *)sqlite3_column_text(stmt, 0)); - } - else if (SQLITE_DONE == step) // 如果没有找到结果 - { - KITLOG(LOG_KIT_EN, ERROR_EN, "未找到配置类型 Type 为 %d 的设备配置", type); - ret = 1; // 设置返回代码为失败 - } - else - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询未完成,错误信息: %s", sqlite3_errmsg(config_db)); - ret = 1; // 设置返回代码为失败 - } - - // 清理资源 - sqlite3_finalize(stmt); // 释放预编译语句 - return ret; // 返回结果 -} - -/***************************************************************************** - * @brief 根据协议类型获取北向配置信息 - * @param[out] northConfigs: 用于存储北向配置信息的数组, 使用 UT_array 存储 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_north_config_arr(UT_array **northConfigs) -{ - int ret = 0; - sqlite3_stmt *stmt = NULL; - const char *query = "SELECT nc.id, nc.protocol_type, nc.config_type " - "FROM north_config nc "; - - // 准备 SQL 语句 - if (SQLITE_OK != sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL)) // config_db: 全局数据库连接 - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - KITPTF(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - return 1; - } - - utarray_new(*northConfigs, &north_config_icd); // 创建新的 UT_array 用于北向信息 - - // 执行查询 - int step = sqlite3_step(stmt); - - while (SQLITE_ROW == step) - { - north_config_t northConfig = {0}; - // 获取北向配置信息 - northConfig.dbId = sqlite3_column_int(stmt, 0); - northConfig.protocolType = (protocol_type_slave_e)sqlite3_column_int(stmt, 1); - northConfig.configType = (north_config_type_e)sqlite3_column_int(stmt, 2); - - // 获取上报下发配置信息 - ret = kit_get_north_config_by_id(sqlite3_column_int(stmt, 0), &northConfig); - if (ret != 0) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "获取上报下发配置信息失败"); - goto error; // 处理错误 - } - - // 将北向配置信息添加到 UT_array 中 - utarray_push_back(*northConfigs, &northConfig); - - step = sqlite3_step(stmt); - } - - // 检查是否完成所有行的处理 - if (SQLITE_DONE != step) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询北向配置信息失败: %s", sqlite3_errmsg(config_db)); - goto error; // 处理错误 - } - - // 清理资源 - sqlite3_finalize(stmt); - return ret; - -error: - // 清理资源 - sqlite3_finalize(stmt); - utarray_free(*northConfigs); // 释放 UT_array - northConfigs = NULL; - return 1; // 返回错误代码 -} - -/***************************************************************************** - * @brief 获取所有削峰填谷的日期配置 - * @param[out] pvDateConfigs: 削峰填谷的日期配置数组, 使用 UT_array 存储 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_pv_date_cfg_db_data(UT_array **pvDateConfigs) -{ - int ret = 0; - sqlite3_stmt *stmt = NULL; - // SQL 查询语句,获取 pv_date_config 表中的数据 - const char *query = "SELECT pdc.pv_time_config_id, pdc.start_date, pdc.end_date " - "FROM pv_date_config pdc " - "ORDER BY pdc.start_date"; - - // 创建新的 UT_array 用于存储削峰填谷的日期配置, 使用 pv_date_config_icd 初始化 - utarray_new(*pvDateConfigs, &pv_date_config_icd); - - // 准备 SQL 语句 - if (SQLITE_OK != sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL)) // global_db: 全局数据库连接 - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - return 1; - } - - // 执行查询并处理结果 - int step = sqlite3_step(stmt); // 执行查询 - while (SQLITE_ROW == step) // 遍历每一行结果 - { - // 从数据库中获取每一列的值 - pv_date_config_t pv_date_config_info = {0}; // 削峰填谷的日期配置结构体 - // 获取开始日期和结束日期 - int snprintf_ret1 = snprintf((char *)pv_date_config_info.startDate, sizeof(pv_date_config_info.startDate), "%s", (const char *)sqlite3_column_text(stmt, 1)); - int snprintf_ret2 = snprintf((char *)pv_date_config_info.endDate, sizeof(pv_date_config_info.endDate), "%s", (const char *)sqlite3_column_text(stmt, 2)); - // 检查 snprintf 是否成功 - if (snprintf_ret1 < 0 || snprintf_ret2 < 0) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "格式化日期失败"); - goto error; - } - // 根据 pv_time_config_id 获取时间配置信息 - if (kit_get_pv_time_cfg_db_data(sqlite3_column_int(stmt, 0), &pv_date_config_info) != 0) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "获取时间配置信息失败"); - goto error; - } - // 将设备点位信息添加到 UT_array 中 - utarray_push_back(*pvDateConfigs, &pv_date_config_info); - - // 继续处理下一行 - step = sqlite3_step(stmt); - } - // 检查是否完成所有行的处理 - if (SQLITE_DONE != step) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询未完成,错误信息: %s", sqlite3_errmsg(config_db)); - goto error; // 处理错误 - } - - // 清理资源 - sqlite3_finalize(stmt); // 释放预编译语句 - - return ret; -error: - // 处理查询过程中出现的错误 - sqlite3_finalize(stmt); // 确保释放预编译语句 - utarray_free(*pvDateConfigs); // 释放 UT_array - pvDateConfigs = NULL; // 设置为 NULL - return 1; // 返回错误代码 -} - -/***************************************************************************** - * @brief 根据削峰填谷时间配置的数据库Id获取削峰填谷时间执行配置 - * @param[in] pvTimeCfgDbId: 削峰填谷时间配置的数据库Id - * @param[out] pvDateConfig: 用于存储削峰填谷的日期配置, 包含一个 pv_time_config_t 类型的数组 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_pv_time_cfg_db_data(int pvDateCfgDbId, pv_date_config_t *pvDateConfig) -{ - int ret = 0; - sqlite3_stmt *stmt = NULL; - // SQL 查询语句,根据 time_section_config_id 获取 pv_time_exe 表中的数据 - char *query = "SELECT pte.start_time, pte.end_time, pte.power " - "FROM pv_time_exe pte " - "WHERE pte.time_section_config_id = ? " - "ORDER BY pte.start_time"; - - // 准备 SQL 语句 - if (SQLITE_OK != sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL)) // config_db: 全局数据库连接 - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - return 1; - } - - // 绑定参数 - if (SQLITE_OK != sqlite3_bind_int(stmt, 1, pvDateCfgDbId)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "绑定 pvDateCfgDbId 失败: %s", sqlite3_errmsg(config_db)); - sqlite3_finalize(stmt); - return 1; // 返回错误代码 - } - - // 执行查询并处理结果 - int step = sqlite3_step(stmt); // 执行查询 - while (SQLITE_ROW == step) // 遍历每一行结果 - { - pvDateConfig->timeCfgLen++; - // 重新分配内存以存储新的时间配置信息 - pv_time_config_t *temp = (pv_time_config_t *)realloc(pvDateConfig->timeCfgTab, pvDateConfig->timeCfgLen * sizeof(pv_time_config_t)); - if (temp == NULL) - { - // 内存分配失败,记录错误信息并返回 - KITLOG(LOG_KIT_EN, ERROR_EN, "内存分配失败"); - ret = 1; - goto error; - } - pvDateConfig->timeCfgTab = temp; - - // 获取时间配置信息 - pvDateConfig->timeCfgTab[pvDateConfig->timeCfgLen - 1].startTime = sqlite3_column_int(stmt, 0); - pvDateConfig->timeCfgTab[pvDateConfig->timeCfgLen - 1].endTime = sqlite3_column_int(stmt, 1); - // pvDateConfig->timeCfgTab[pvDateConfig->timeCfgLen - 1].workMode = sqlite3_column_int(stmt, 2); - pvDateConfig->timeCfgTab[pvDateConfig->timeCfgLen - 1].power = sqlite3_column_double(stmt, 2); - step = sqlite3_step(stmt); - } - - // 检查查询是否完成 - if (step != SQLITE_DONE) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询削峰填谷时间配置执行信息失败: %s", sqlite3_errmsg(config_db)); - ret = 1; - } - -error: - // 清理资源 - sqlite3_finalize(stmt); - return ret; -} - -/***************************************************************************** - * @brief 设置所有削峰填谷的日期配置 - * @param[out] pvDateTimeConfigs: 削峰填谷的日期配置、时间配置数组, 使用 UT_array 存储 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_set_pv_date_time_cfg(UT_array **pvDateTimeConfigs) -{ - int ret = 0; - sqlite3_stmt* stmt_date = NULL, * stmt_time = NULL, * stmt_exe = NULL; - // SQL 删除语句,删除 pv_date_config 表中的数据 - const char* sql_delete_date = "DELETE FROM pv_date_config"; - // SQL 查询语句,删除 pv_time_config 表中的数据 - const char* sql_delete_time = "DELETE FROM pv_time_config"; - // SQL 查询语句,删除 pv_time_exe 表中的数据 - const char* sql_delete_exe = "DELETE FROM pv_time_exe"; - // SQL 插入语句,插入 pv_date_config 表中的数据 - const char* sql_insert_date = "INSERT INTO pv_date_config(pv_time_config_id, start_date, end_date, remark) VALUES (?, ?, ?, ?)"; - // SQL 插入语句,插入 pv_time_config 表中的数据 - const char* sql_insert_time = "INSERT INTO pv_time_config(name, remark) VALUES (?, ?)"; - // SQL 插入语句,插入 pv_time_exe 表中的数据 - const char* sql_insert_exe = "INSERT INTO pv_time_exe(time_section_config_id, start_time, end_time, power, remark) VALUES (?, ?, ?, ?,?)"; - - pthread_mutex_lock(&config_db_mutex); - - // 开始事务 - ret = sqlite3_exec(config_db, "BEGIN TRANSACTION", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "开启事务失败: %s", sqlite3_errmsg(config_db)); - goto cleanup; - } - - // 清空表数据 - if (sqlite3_exec(config_db, sql_delete_date, NULL, NULL, NULL) != SQLITE_OK || - sqlite3_exec(config_db, sql_delete_time, NULL, NULL, NULL) != SQLITE_OK || - sqlite3_exec(config_db, sql_delete_exe, NULL, NULL, NULL) != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "清空表失败: %s", sqlite3_errmsg(config_db)); - goto cleanup; - } - - // 准备插入语句 - if (sqlite3_prepare_v2(config_db, sql_insert_date, -1, &stmt_date, NULL) != SQLITE_OK || - sqlite3_prepare_v2(config_db, sql_insert_time, -1, &stmt_time, NULL) != SQLITE_OK || - sqlite3_prepare_v2(config_db, sql_insert_exe, -1, &stmt_exe, NULL) != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "预编译插入语句失败: %s", sqlite3_errmsg(config_db)); - goto cleanup; - } - - // 遍历需要插入的数据 - utarray_foreach(*pvDateTimeConfigs, pv_date_config_t *, p_pvDateConfig) - { - char timeConfigName[50]; // 存储时间配置名称 - snprintf(timeConfigName, sizeof(timeConfigName), "%s-%s", p_pvDateConfig->startDate, p_pvDateConfig->endDate); - - // 插入 pv_time_config - sqlite3_bind_text(stmt_time, 1, timeConfigName, -1, SQLITE_STATIC); - if (sqlite3_step(stmt_time) != SQLITE_DONE) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "插入 pv_time_config 表失败: %s", sqlite3_errmsg(config_db)); - goto cleanup; - } - long long timeConfigId = sqlite3_last_insert_rowid(config_db); // 获取最后插入行的 ID - sqlite3_reset(stmt_time); - - // 插入 pv_time_exe - for (int i = 0; i < p_pvDateConfig->timeCfgLen; i++) - { - sqlite3_bind_int64(stmt_exe, 1, timeConfigId); - sqlite3_bind_int(stmt_exe, 2, p_pvDateConfig->timeCfgTab[i].startTime); - sqlite3_bind_int(stmt_exe, 3, p_pvDateConfig->timeCfgTab[i].endTime); - sqlite3_bind_double(stmt_exe, 4, p_pvDateConfig->timeCfgTab[i].power); - - if (sqlite3_step(stmt_exe) != SQLITE_DONE) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "插入 pv_time_exe 表失败: %s", sqlite3_errmsg(config_db)); - goto cleanup; - } - sqlite3_reset(stmt_exe); - } - - // 插入 pv_date_config - sqlite3_bind_int64(stmt_date, 1, timeConfigId); - sqlite3_bind_text(stmt_date, 2, (const char *)p_pvDateConfig->startDate, -1, SQLITE_STATIC); - sqlite3_bind_text(stmt_date, 3, (const char *)p_pvDateConfig->endDate, -1, SQLITE_STATIC); - - if (sqlite3_step(stmt_date) != SQLITE_DONE) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "插入 pv_date_config 表失败: %s", sqlite3_errmsg(config_db)); - goto cleanup; - } - sqlite3_reset(stmt_date); - } - - // 提交事务 - if (sqlite3_exec(config_db, "COMMIT TRANSACTION", NULL, NULL, NULL) != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "提交事务失败: %s", sqlite3_errmsg(config_db)); - goto cleanup; - } - - ret = 0; // 成功 - -cleanup: - if (ret != 0) - { - // 回滚事务 - sqlite3_exec(config_db, "ROLLBACK TRANSACTION", NULL, NULL, NULL); - } - - // 释放资源 - sqlite3_finalize(stmt_date); - sqlite3_finalize(stmt_time); - sqlite3_finalize(stmt_exe); - pthread_mutex_unlock(&config_db_mutex); - - // 释放 UT_array 资源 - if (ret != 0) - { - utarray_free(*pvDateTimeConfigs); - *pvDateTimeConfigs = NULL; - } - - return ret; -} - -/***************************************************************************** - * @brief 从数据库获取EMS拓扑结构信息 - * @param[out] topologys: 用于存储ems拓扑信息结构体的 UT_array 指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_topology_db_data(UT_array **topologies) -{ - sqlite3_stmt *stmt = NULL; // 预编译语句句柄 - const char *query; // 查询语句 - - query = "SELECT tpy.id, tpy.parent_id, tpy.menu_tree, tpy.sort_order, " - "CASE " - " WHEN tpy.menu_tree = 0 THEN tpy.name " - " WHEN tpy.menu_tree = 1 THEN dev.name ELSE NULL " - "END AS name, " - "CASE " - " WHEN tpy.menu_tree = 0 THEN NULL " - " WHEN tpy.menu_tree = 1 THEN dev.sn ELSE NULL " - "END AS sn, " - "CASE " - " WHEN tpy.menu_tree = 0 THEN NULL " - " WHEN tpy.menu_tree = 1 THEN dev.type ELSE NULL " - "END AS dev_type " - "FROM " - "topology tpy " - "LEFT JOIN device dev ON tpy.dev_id = dev.id"; - - utarray_new(*topologies, &topology_icd); // 创建新的 UT_array 用于存储ems拓扑信息 - - // 准备 SQL 语句 - if (SQLITE_OK != sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - sqlite3_finalize(stmt); // 确保释放预编译语句 - return 1; // 返回错误代码 - } - - // 执行查询并处理结果 - int step = sqlite3_step(stmt); - while (SQLITE_ROW == step) // 遍历每一行结果 - { - // 从数据库中获取每一列的值 - topology_t topology_info = {0}; // 初始化拓扑结构的结构体 - topology_info.dbId = sqlite3_column_int(stmt, 0); - if (sqlite3_column_type(stmt, 1) == SQLITE_NULL) - { - topology_info.parentId = -999; - } - else - { - topology_info.parentId = sqlite3_column_int(stmt, 1); - } - topology_info.menuTree = (menu_tree_e)sqlite3_column_int(stmt, 2); - topology_info.sortOrder = sqlite3_column_int(stmt, 3); - const char *name = (const char *)sqlite3_column_text(stmt, 4); - snprintf((char *)topology_info.name, MAX_NAME_BUF_LEN, "%s", name ? name : ""); - const char *sn = (const char *)sqlite3_column_text(stmt, 5); - snprintf((char *)topology_info.sn, MAX_CODE_BUF_LEN, "%s", sn ? sn : ""); - topology_info.devType = (dev_type_e)sqlite3_column_int(stmt, 6); - - // 将设备点位信息添加到 UT_array 中 - utarray_push_back(*topologies, &topology_info); - - // 继续处理下一行 - step = sqlite3_step(stmt); - } - - // 检查是否完成所有行的处理 - if (SQLITE_DONE != step) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询未完成,错误信息: %s", sqlite3_errmsg(config_db)); - goto error; // 处理错误 - } - - // 清理资源 - sqlite3_finalize(stmt); // 释放预编译语句 - return 0; // 成功返回 - -error: - sqlite3_finalize(stmt); // 确保释放预编译语句 - utarray_free(*topologies); // 释放 UT_array - topologies = NULL; // 设置为 NULL - return 1; // 返回错误代码 -} - -/***************************************************************************** - * @brief 从数据库里获取保护算法的控制参数 - * @param[in] p_protectAlgo:保护算法结构体指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_protect_algorithm(protect_algorithm_t *p_protectAlgo) -{ - sqlite3_stmt *stmt = NULL; - char *query = "SELECT transformer_capacity, ol_warn_limit_value, ol_shutdown_value, " - "max_power, demand_switch, target_demand, de_warn_limit_value, " - "de_shutdown_value, backflow_switch, bf_warn_limit_value, " - "bf_shutdown_value, soc_forbid_chg, soc_forbid_dischg, " - "id " - "FROM protect_algorithm " - "ORDER BY id DESC " - "LIMIT 1"; - - if (SQLITE_OK != sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - return 1; // 返回错误代码 - } - - int step = sqlite3_step(stmt); - - if (SQLITE_ROW == step) - { - p_protectAlgo->transCapacity = sqlite3_column_double(stmt, 0); // 变压器总容量(KW) - p_protectAlgo->olWarnLimitVal = sqlite3_column_double(stmt, 1); // 过载预警限流值(KW) - p_protectAlgo->olShutdownVal = sqlite3_column_double(stmt, 2); // 过载关机值(KW) - p_protectAlgo->maxPower = sqlite3_column_double(stmt, 3); // 充放电功率上限(KW) - p_protectAlgo->demandSwitch = sqlite3_column_int(stmt, 4); // 防需量开关 - p_protectAlgo->targetDemand = sqlite3_column_double(stmt, 5); // 目标需量 - p_protectAlgo->deWarnLimitVal = sqlite3_column_double(stmt, 6); // 需量预警限流值(KW) - p_protectAlgo->deShutdownVal = sqlite3_column_double(stmt, 7); // 需量关机值(KW) - p_protectAlgo->backflowSwitch = sqlite3_column_int(stmt, 8); // 防逆流开关 - p_protectAlgo->bfWarnLimitVal = sqlite3_column_double(stmt, 9); // 防逆流预警限流值(KW) - p_protectAlgo->bfShutdownVal = sqlite3_column_double(stmt, 10); // 防逆流关机值(KW) - p_protectAlgo->socForbidChg = sqlite3_column_int(stmt, 11); // 禁充SOC [55%-100%] - p_protectAlgo->socForbidDischg = sqlite3_column_int(stmt, 12); // 禁放SOC [0%-45%] - p_protectAlgo->dbId = sqlite3_column_int(stmt, 13); // 数据库Id - } - else - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询失败或者无数据,错误码: %d, 错误信息: %s", step, sqlite3_errmsg(config_db)); - sqlite3_finalize(stmt); - return 1; // 返回错误代码 - } - - sqlite3_finalize(stmt); - return 0; // 返回成功代码 -} - -/***************************************************************************** - * @brief 更新数据库的保护算法数据 - * @param[in] p_protectAlgo:保护算法结构体指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_set_protect_algorithm(protect_algorithm_t *p_protectAlgo) -{ - int ret = 0; - sqlite3_stmt *stmt = NULL; - char *sql = sqlite3_mprintf( - "UPDATE protect_algorithm SET transformer_capacity = ?, ol_warn_limit_value = ?, ol_shutdown_value = ?, " - "max_power = ?, demand_switch = ?, target_demand = ?, de_warn_limit_value = ?, " - "de_shutdown_value = ?, backflow_switch = ?, bf_warn_limit_value = ?, " - "bf_shutdown_value = ?, soc_forbid_chg = ?, soc_forbid_dischg = ? WHERE id = ?"); - - if (SQLITE_OK != sqlite3_prepare_v2(config_db, sql, -1, &stmt, NULL)) - { - fprintf(stderr, "SQL语句预编译失败: %s\n", sqlite3_errmsg(config_db)); - sqlite3_free(sql); - return 1; - } - - sqlite3_bind_double(stmt, 1, p_protectAlgo->transCapacity); - sqlite3_bind_double(stmt, 2, p_protectAlgo->olWarnLimitVal); - sqlite3_bind_double(stmt, 3, p_protectAlgo->olShutdownVal); - sqlite3_bind_double(stmt, 4, p_protectAlgo->maxPower); - sqlite3_bind_int(stmt, 5, p_protectAlgo->demandSwitch); - sqlite3_bind_double(stmt, 6, p_protectAlgo->targetDemand); - sqlite3_bind_double(stmt, 7, p_protectAlgo->deWarnLimitVal); - sqlite3_bind_double(stmt, 8, p_protectAlgo->deShutdownVal); - sqlite3_bind_int(stmt, 9, p_protectAlgo->backflowSwitch); - sqlite3_bind_double(stmt, 10, p_protectAlgo->bfWarnLimitVal); - sqlite3_bind_double(stmt, 11, p_protectAlgo->bfShutdownVal); - sqlite3_bind_int(stmt, 12, p_protectAlgo->socForbidChg); - sqlite3_bind_int(stmt, 13, p_protectAlgo->socForbidDischg); - sqlite3_bind_int(stmt, 14, p_protectAlgo->dbId); - - pthread_mutex_lock(&config_db_mutex); - - int step = sqlite3_step(stmt); - if (step != SQLITE_DONE) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句执行失败"); - if (step == SQLITE_ERROR) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "%s", sqlite3_errmsg(config_db)); - } - else - { - KITLOG(LOG_KIT_EN, ERROR_EN, "错误代码: %d", step); - } - ret = 1; - goto cleanup; - } - - if (sqlite3_changes(config_db) == 0) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "没有更新任何行。请检查 dbId 是否正确"); - ret = 1; - goto cleanup; - } - -cleanup: - pthread_mutex_unlock(&config_db_mutex); - sqlite3_finalize(stmt); - sqlite3_free(sql); - return ret; -} - -/***************************************************************************** - * @brief 从数据库里获取调试模式算法的控制参数 - * @param[in] p_debugAlgo:调试模式算法结构体指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_debug_algorithm(debug_algorithm_t *p_debugAlgo) -{ - sqlite3_stmt *stmt = NULL; - char *query = "SELECT active_power, reactive_power, pcs_switch, id, protect_switch " - "FROM debug_algorithm " - "ORDER BY id DESC " - "LIMIT 1"; - - if (SQLITE_OK != sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - return 1; // 返回错误代码 - } - - int step = sqlite3_step(stmt); - - if (SQLITE_ROW == step) - { - p_debugAlgo->activePower = sqlite3_column_double(stmt, 0); // 目标有功功率(KW) - p_debugAlgo->reactivePower = sqlite3_column_double(stmt, 1); // 目标无功功率(KW) - p_debugAlgo->pcsSwitch = sqlite3_column_int(stmt, 2); // 充放电开关 - p_debugAlgo->dbId = sqlite3_column_int(stmt, 3); // 数据库Id - p_debugAlgo->protectSwitch = sqlite3_column_int(stmt, 4); // 保护算法开关 - } - else - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询失败,错误码: %d, 错误信息: %s", step, sqlite3_errmsg(config_db)); - sqlite3_finalize(stmt); - return 1; // 返回错误代码 - } - - sqlite3_finalize(stmt); - return 0; // 返回成功代码 -} - -/***************************************************************************** - * @brief 更新数据库的调试模式算法数据 - * @param[in] p_debugAlgo:调试模式算法结构体指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_set_debug_algorithm(debug_algorithm_t *p_debugAlgo) -{ - int ret = 0; - sqlite3_stmt *stmt = NULL; - const char *sql = sqlite3_mprintf("UPDATE debug_algorithm SET active_power = ?, reactive_power = ?, pcs_switch = ?, protect_switch = ? WHERE id = ? "); - - if (SQLITE_OK != sqlite3_prepare_v2(config_db, sql, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句预编译失败: %s", sqlite3_errmsg(config_db)); - return 1; - } - - sqlite3_bind_double(stmt, 1, p_debugAlgo->activePower); - sqlite3_bind_double(stmt, 2, p_debugAlgo->reactivePower); - sqlite3_bind_int(stmt, 3, p_debugAlgo->pcsSwitch); - sqlite3_bind_int(stmt, 4, p_debugAlgo->protectSwitch); - sqlite3_bind_int(stmt, 5, p_debugAlgo->dbId); - - pthread_mutex_lock(&config_db_mutex); // 加锁,确保单线程访问 - int step = sqlite3_step(stmt); - if (step != SQLITE_DONE) - { - if (step == SQLITE_ERROR) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句执行失败: %s", sqlite3_errmsg(config_db)); - } - else if (step == SQLITE_ROW) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "UPDATE操作中出现意外的SQLITE_ROW返回值"); - } - else - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL更新失败,错误代码: %d", step); - } - pthread_mutex_unlock(&config_db_mutex); // 解锁 - sqlite3_finalize(stmt); - return 1; - } - - // 检查是否实际更新了任何行。SQLITE_DONE 并不保证这一点。 - if (sqlite3_changes(config_db) == 0) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "没有更新任何行。请检查 dbId 是否正确。"); - pthread_mutex_unlock(&config_db_mutex); // 解锁 - return 1; - } - - pthread_mutex_unlock(&config_db_mutex); // 解锁 - sqlite3_finalize(stmt); - return ret; -} - -/***************************************************************************** - * @brief 从数据库查询功率分配数据 - * @param[in] p_allocatePower:功率分配的指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_allocate_power(allocate_power_t *p_allocatePower) -{ - sqlite3_stmt *stmt = NULL; - char *query = sqlite3_mprintf("SELECT pcs_num, chg_direction, id, allocate_mode FROM allocate_power ORDER BY id DESC LIMIT 1"); - - if (query == NULL) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "内存分配失败"); - return 1; - } - - if (SQLITE_OK != sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - sqlite3_free(query); - return 1; // 返回错误代码 - } - - int step = sqlite3_step(stmt); - - if (step == SQLITE_ROW) - { - p_allocatePower->pcsNum = sqlite3_column_int(stmt, 0); // pcs数量 - p_allocatePower->chgDirection = sqlite3_column_int(stmt, 1); // 充放电方向:1(正放 负充) -1(正充 负放) - p_allocatePower->dbId = sqlite3_column_int(stmt, 2); // 数据库Id - p_allocatePower->allocateMode = sqlite3_column_int(stmt, 3); // 下发功率开关:总功率(0),分相功率(1) - } - else - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询失败或者无数据,错误码: %d, 错误信息: %s", step, sqlite3_errmsg(config_db)); - } - - sqlite3_finalize(stmt); - sqlite3_free(query); - return (step == SQLITE_ROW) ? 0 : 1; // 返回成功或失败代码 -} - -/***************************************************************************** - * @brief 更新数据库的功率分配数据 - * @param[in] p_allocatePower:功率分配的指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_set_allocate_power(allocate_power_t *p_allocatePower) -{ - int ret = 0; - sqlite3_stmt *stmt = NULL; - const char *sql = sqlite3_mprintf("UPDATE allocate_power SET pcs_num = ?, chg_direction = ?, allocate_mode = ? WHERE id = ? "); - - if (SQLITE_OK != sqlite3_prepare_v2(config_db, sql, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句预编译失败: %s", sqlite3_errmsg(config_db)); - return 1; - } - - sqlite3_bind_int(stmt, 1, p_allocatePower->pcsNum); - sqlite3_bind_int(stmt, 2, p_allocatePower->chgDirection); - sqlite3_bind_int(stmt, 3, p_allocatePower->allocateMode); - sqlite3_bind_int(stmt, 4, p_allocatePower->dbId); - - pthread_mutex_lock(&config_db_mutex); // 加锁,确保单线程访问 - int step = sqlite3_step(stmt); - if (step != SQLITE_DONE) - { - if (step == SQLITE_ERROR) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句执行失败: %s", sqlite3_errmsg(config_db)); - } - else if (step == SQLITE_ROW) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "UPDATE操作中出现意外的SQLITE_ROW返回值"); - } - else - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL更新失败,错误代码: %d", step); - } - pthread_mutex_unlock(&config_db_mutex); // 解锁 - sqlite3_finalize(stmt); - return 1; - } - - // 检查是否实际更新了任何行。SQLITE_DONE 并不保证这一点。 - if (sqlite3_changes(config_db) == 0) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "没有更新任何行。请检查 dbId 是否正确。"); - pthread_mutex_unlock(&config_db_mutex); // 解锁 - return 1; - } - - pthread_mutex_unlock(&config_db_mutex); // 解锁 - sqlite3_finalize(stmt); - return ret; -} - -/***************************************************************************** - * @brief 从数据库查询工作模式数据 - * @param[in] p_workModeSet:工作模式的指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_work_mode_set(work_mode_set_t *p_workModeSet) -{ - sqlite3_stmt *stmt = NULL; - char *query = sqlite3_mprintf("SELECT work_mode, id FROM work_mode_set DESC LIMIT 1"); - - if (query == NULL) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "内存分配失败"); - return 1; - } - - if (SQLITE_OK != sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - sqlite3_free(query); - return 1; // 返回错误代码 - } - - int step = sqlite3_step(stmt); - - if (step == SQLITE_ROW) - { - p_workModeSet->workMode = (work_mode_e)sqlite3_column_int(stmt, 0); // 工作模式 - p_workModeSet->dbId = sqlite3_column_int(stmt, 1); // 数据库Id - } - else - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询失败,错误码: %d, 错误信息: %s", step, sqlite3_errmsg(config_db)); - } - - sqlite3_finalize(stmt); - sqlite3_free(query); - return (step == SQLITE_ROW) ? 0 : 1; // 返回成功或失败代码 -} - -/***************************************************************************** - * @brief 更新数据库的工作模式数据 - * @param[in] p_workModeSet:工作模式的指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_set_work_mode(work_mode_set_t *p_workModeSet) -{ - int ret = 0; - sqlite3_stmt *stmt = NULL; - const char *sql = sqlite3_mprintf("UPDATE work_mode_set SET work_mode = ? WHERE id = ? "); - - if (SQLITE_OK != sqlite3_prepare_v2(config_db, sql, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句预编译失败: %s", sqlite3_errmsg(config_db)); - return 1; - } - - sqlite3_bind_int(stmt, 1, (uint8_t)p_workModeSet->workMode); - sqlite3_bind_int(stmt, 2, p_workModeSet->dbId); - - pthread_mutex_lock(&config_db_mutex); // 加锁,确保单线程访问 - int step = sqlite3_step(stmt); - if (step != SQLITE_DONE) - { - if (step == SQLITE_ERROR) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句执行失败: %s", sqlite3_errmsg(config_db)); - } - else if (step == SQLITE_ROW) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "UPDATE操作中出现意外的SQLITE_ROW返回值"); - } - else - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL更新失败,错误代码: %d", step); - } - pthread_mutex_unlock(&config_db_mutex); // 解锁 - sqlite3_finalize(stmt); - return 1; - } - - // 检查是否实际更新了任何行。SQLITE_DONE 并不保证这一点。 - if (sqlite3_changes(config_db) == 0) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "没有更新任何行。请检查 dbId 是否正确。"); - pthread_mutex_unlock(&config_db_mutex); // 解锁 - return 1; - } - - pthread_mutex_unlock(&config_db_mutex); // 解锁 - sqlite3_finalize(stmt); - return ret; -} - -/***************************************************************************** - * @brief 从数据库查询DIDO逻辑设置数据 - * @param[in] diDoSets:DIDO逻辑设置结构体的 UT_array 指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_di_do_set_arr(UT_array **diDoSets) -{ - sqlite3_stmt *stmt = NULL; // 预编译语句句柄 - const char *query; // 查询语句 - - query = "SELECT seq, type, cabinet_code, strategy_seq " - "FROM di_do_set "; - - // 准备 SQL 语句 - if (SQLITE_OK != sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - return 1; - } - - utarray_new(*diDoSets, &di_do_logic_set_icd); // 创建新的 UT_array 用于存储DIDO逻辑设置信息 - - // 执行查询并处理结果 - int step = sqlite3_step(stmt); - while (SQLITE_ROW == step) // 遍历每一行结果 - { - // 从数据库中获取每一列的值 - di_do_logic_set_t di_do_set_logic_info = {0}; // 初始化DIDO逻辑设置的结构体 - di_do_set_logic_info.dIDOseq = sqlite3_column_int(stmt, 0); - di_do_set_logic_info.dIDOType = (di_do_type_e)sqlite3_column_int(stmt, 1); - di_do_set_logic_info.cabinetCode = sqlite3_column_int(stmt, 2); - if (di_do_set_logic_info.dIDOType == kDi) - { - di_do_set_logic_info.strategySeqDi = (diFuc_e)sqlite3_column_int(stmt, 3); - } - else - { - di_do_set_logic_info.strategySeqDo = (doFuc_e)sqlite3_column_int(stmt, 3); - } - - // 将DIDO逻辑设置添加到 UT_array 中 - utarray_push_back(*diDoSets, &di_do_set_logic_info); - - // 继续处理下一行 - step = sqlite3_step(stmt); - } - - // 检查是否完成所有行的处理 - if (SQLITE_DONE != step) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询未完成,错误信息: %s", sqlite3_errmsg(config_db)); - goto error; // 处理错误 - } - - // 清理资源 - sqlite3_finalize(stmt); // 释放预编译语句 - return 0; // 成功返回 - -error: - sqlite3_finalize(stmt); // 确保释放预编译语句 - utarray_free(*diDoSets); // 释放 UT_array - diDoSets = NULL; // 设置为 NULL - return 1; // 返回错误代码 -} - -/***************************************************************************** - * @brief 从数据库里获取温控算法的控制参数 - * @param[in] p_tempCtrlAlgo:温控算法结构体指针 - * @return 0-成功,非0-失败(具体错误码可通过日志或其他机制获取) - *****************************************************************************/ -int kit_get_temp_ctrl_algorithm(temp_ctrl_algorithm_t *p_tempCtrlAlgo) -{ - int ret = 0; - sqlite3_stmt *stmt = NULL; - - if (p_tempCtrlAlgo == NULL) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "传入的结构体指针为空"); - return 1; // 返回错误代码 - } - - char *query = "SELECT mod, work_cool_trig_temp, work_cool_hys, " - "work_heat_trig_temp, work_heat_hys, standby_cool_trig_temp, " - "standby_cool_hys, standby_heat_trig_temp, standby_heat_hys, " - "standby_max_limit, standby_min_limit, standby_maxback_limit, " - "standby_minback_limit, temp_cmd_normal, temp_cmd_heat, temp_cmd_cold, " - "temp_cmd_open, temp_cmd_close, id " - "FROM temp_ctrl_algorithm " - "ORDER BY id DESC " - "LIMIT 1"; - - int rc = sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL); - if (rc != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - ret = rc; // 记录sqlite3的错误码 - goto cleanup; - } - - int step = sqlite3_step(stmt); - - if (step == SQLITE_ROW) - { - p_tempCtrlAlgo->mod = (temperature_ctrl_mod_e)sqlite3_column_int(stmt, 0); - p_tempCtrlAlgo->workCoolTrigTemp = (float)sqlite3_column_double(stmt, 1); - p_tempCtrlAlgo->workCoolHys = (float)sqlite3_column_double(stmt, 2); - p_tempCtrlAlgo->workHeatTrigTemp = (float)sqlite3_column_double(stmt, 3); - p_tempCtrlAlgo->workHeatHys = (float)sqlite3_column_double(stmt, 4); - p_tempCtrlAlgo->standbyCoolTrigTemp = (float)sqlite3_column_double(stmt, 5); - p_tempCtrlAlgo->standbyCoolHys = (float)sqlite3_column_double(stmt, 6); - p_tempCtrlAlgo->standbyHeatTrigTemp = (float)sqlite3_column_double(stmt, 7); - p_tempCtrlAlgo->standbyHeatHys = (float)sqlite3_column_double(stmt, 8); - p_tempCtrlAlgo->standbyMaxLimit = (float)sqlite3_column_double(stmt, 9); - p_tempCtrlAlgo->standbyMinLimit = (float)sqlite3_column_double(stmt, 10); - p_tempCtrlAlgo->standbyMaxbackLimit = (float)sqlite3_column_double(stmt, 11); - p_tempCtrlAlgo->standbyMinbackLimit = (float)sqlite3_column_double(stmt, 12); - p_tempCtrlAlgo->tempCmdNormal = sqlite3_column_int(stmt, 13); - p_tempCtrlAlgo->tempCmdHeat = sqlite3_column_int(stmt, 14); - p_tempCtrlAlgo->tempCmdCold = sqlite3_column_int(stmt, 15); - p_tempCtrlAlgo->tempCmdOpen = sqlite3_column_int(stmt, 16); - p_tempCtrlAlgo->tempCmdClose = sqlite3_column_int(stmt, 17); - p_tempCtrlAlgo->dbId = sqlite3_column_int64(stmt, 18); - } - else - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询失败,错误码: %d, 错误信息: %s", step, sqlite3_errmsg(config_db)); - ret = step; // 记录sqlite3的错误码 - } - -cleanup: - sqlite3_finalize(stmt); - return ret; -} - -/***************************************************************************** - * @brief 更新数据库的温控算法数据 - * @param[in] p_tempCtrlAlgo:温控算法结构体指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_set_temp_ctrl_algorithm(temp_ctrl_algorithm_t *p_tempCtrlAlgo) -{ - int ret = 0; - sqlite3_stmt *stmt = NULL; - // 使用互斥锁保护数据库访问,防止多线程竞争 - pthread_mutex_lock(&config_db_mutex); - - // SQL语句,使用占位符防止SQL注入,并根据实际情况选择合适的更新策略 (UPDATE or INSERT) - char *query = "UPDATE temp_ctrl_algorithm SET mod = ?, work_cool_trig_temp = ?, work_cool_hys = ?, " - "work_heat_trig_temp = ?, work_heat_hys = ?, standby_cool_trig_temp = ?, " - "standby_cool_hys = ?, standby_heat_trig_temp = ?, standby_heat_hys = ?, " - "standby_max_limit = ?, standby_min_limit = ?, standby_maxback_limit = ?, " - "standby_minback_limit = ?, temp_cmd_normal = ?, temp_cmd_heat = ?, temp_cmd_cold = ?, " - "temp_cmd_open = ?, temp_cmd_close = ? " - "WHERE id = ?;"; // 更新最新的记录 - - // 准备SQL语句 - int rc = sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL); - if (rc != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备SQL语句失败: %s", sqlite3_errmsg(config_db)); - ret = 1; - goto unlock_and_return; - } - - // 绑定参数 - ret = sqlite3_bind_int(stmt, 1, p_tempCtrlAlgo->mod); // 温度控制模式 - if (ret != SQLITE_OK) - goto error; - ret = sqlite3_bind_double(stmt, 2, p_tempCtrlAlgo->workCoolTrigTemp); // 制冷触发温度 - if (ret != SQLITE_OK) - goto error; - ret = sqlite3_bind_double(stmt, 3, p_tempCtrlAlgo->workCoolHys); // 制冷回差 - if (ret != SQLITE_OK) - goto error; - ret = sqlite3_bind_double(stmt, 4, p_tempCtrlAlgo->workHeatTrigTemp); // 制热触发温度 - if (ret != SQLITE_OK) - goto error; - ret = sqlite3_bind_double(stmt, 5, p_tempCtrlAlgo->workHeatHys); // 制热回差 - if (ret != SQLITE_OK) - goto error; - ret = sqlite3_bind_double(stmt, 6, p_tempCtrlAlgo->standbyCoolTrigTemp); // 制冷触发温度 - if (ret != SQLITE_OK) - goto error; - ret = sqlite3_bind_double(stmt, 7, p_tempCtrlAlgo->standbyCoolHys); // 制冷回差 - if (ret != SQLITE_OK) - goto error; - ret = sqlite3_bind_double(stmt, 8, p_tempCtrlAlgo->standbyHeatTrigTemp); // 制热触发温度 - if (ret != SQLITE_OK) - goto error; - ret = sqlite3_bind_double(stmt, 9, p_tempCtrlAlgo->standbyHeatHys); // 制热回差 - if (ret != SQLITE_OK) - goto error; - ret = sqlite3_bind_double(stmt, 10, p_tempCtrlAlgo->standbyMaxLimit); // 开启自循环高温 - if (ret != SQLITE_OK) - goto error; - ret = sqlite3_bind_double(stmt, 11, p_tempCtrlAlgo->standbyMinLimit); // 开启自循环低温 - if (ret != SQLITE_OK) - goto error; - ret = sqlite3_bind_double(stmt, 12, p_tempCtrlAlgo->standbyMaxbackLimit); // 自循环高温回温 - if (ret != SQLITE_OK) - goto error; - ret = sqlite3_bind_double(stmt, 13, p_tempCtrlAlgo->standbyMinbackLimit); // 自循环低温回温 - if (ret != SQLITE_OK) - goto error; - ret = sqlite3_bind_int(stmt, 14, p_tempCtrlAlgo->tempCmdNormal); // 循环控制字 - if (ret != SQLITE_OK) - goto error; - ret = sqlite3_bind_int(stmt, 15, p_tempCtrlAlgo->tempCmdHeat); // 制热控制字 - if (ret != SQLITE_OK) - goto error; - ret = sqlite3_bind_int(stmt, 16, p_tempCtrlAlgo->tempCmdCold); // 制冷控制字 - if (ret != SQLITE_OK) - goto error; - ret = sqlite3_bind_int(stmt, 17, p_tempCtrlAlgo->tempCmdOpen); // 开控制字 - if (ret != SQLITE_OK) - goto error; - ret = sqlite3_bind_int(stmt, 18, p_tempCtrlAlgo->tempCmdClose); // 关控制字 - if (ret != SQLITE_OK) - goto error; - ret = sqlite3_bind_int64(stmt, 19, p_tempCtrlAlgo->dbId); // 数据库Id - if (ret != SQLITE_OK) - goto error; - - // 执行SQL语句 - ret = sqlite3_step(stmt); - if (ret != SQLITE_DONE) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "执行SQL语句失败: %s", sqlite3_errmsg(config_db)); - goto error; - } - - // 检查是否实际更新了任何行 - if (sqlite3_changes(config_db) == 0) - { - KITLOG(LOG_KIT_EN, WARN_EN, "没有更新任何行。请检查数据是否存在。"); - ret = 1; - } - - sqlite3_finalize(stmt); - goto unlock_and_return; - -error: - sqlite3_finalize(stmt); - ret = 1; - -unlock_and_return: - pthread_mutex_unlock(&config_db_mutex); // 解锁 - return ret; -} - -/***************************************************************************** - * @brief 从数据库获取高级设置 - * @param[out] advancedSettings: 用于存储高级设置的数据 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_advanced_setting(UT_array **advancedSettings) -{ - sqlite3_stmt *stmt = NULL; - char *query = sqlite3_mprintf("SELECT key, value FROM advanced_setting ORDER BY key ASC"); - int ret; - - ret = sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - sqlite3_free(query); - return 1; - } - - utarray_new(*advancedSettings, &advanced_setting_icd); - - while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) - { - advanced_setting_t setting_info = {0}; - snprintf((char *)setting_info.key, MAX_KEY_LEN, "%s", (const char *)sqlite3_column_text(stmt, 0)); - snprintf((char *)setting_info.value, MAX_VALUE_LEN, "%s", (const char *)sqlite3_column_text(stmt, 1)); - utarray_push_back(*advancedSettings, &setting_info); - } - - if (ret != SQLITE_DONE) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询失败: %s", sqlite3_errmsg(config_db)); - sqlite3_finalize(stmt); - sqlite3_free(query); - utarray_free(*advancedSettings); - *advancedSettings = NULL; - return 1; - } - - sqlite3_finalize(stmt); - sqlite3_free(query); - return 0; -} - -/***************************************************************************** - * @brief 从数据库查询升级记录数据 - * @param[in] p_upgradeRecord:升级记录的指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_get_upgrade_record(upgrade_record_t *p_upgradeRecord) -{ - sqlite3_stmt *stmt = NULL; - char *query = sqlite3_mprintf("SELECT id, path FROM upgrade_record Where status = 0 LIMIT 1"); - - if (query == NULL) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "内存分配失败"); - return 1; - } - - if (SQLITE_OK != sqlite3_prepare_v2(config_db, query, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "准备查询 `%s` 失败: %s", query, sqlite3_errmsg(config_db)); - sqlite3_free(query); - return 1; // 返回错误代码 - } - - int step = sqlite3_step(stmt); - - if (step == SQLITE_ROW) - { - p_upgradeRecord->dbId = sqlite3_column_int(stmt, 0); // 数据库Id - snprintf((char *)p_upgradeRecord->path, MAX_UPGRADE_PATH_LEN, "%s", sqlite3_column_text(stmt, 1)); // 升级包文件路径 - } - else - { - KITLOG(LOG_KIT_EN, ERROR_EN, "查询失败,错误码: %d, 错误信息: %s", step, sqlite3_errmsg(config_db)); - } - - sqlite3_finalize(stmt); - sqlite3_free(query); - return (step == SQLITE_ROW) ? 0 : 1; // 返回成功或失败代码 -} - -/***************************************************************************** - * @brief 更新数据库的升级记录数据 - * @param[in] p_upgradeRecord:升级记录的指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_update_upgrade_record(upgrade_record_t *p_upgradeRecord) -{ - int ret = 0; - sqlite3_stmt *stmt = NULL; - const char *sql = sqlite3_mprintf("UPDATE upgrade_record SET status = ?, err_msg = ? WHERE id = ? "); - - if (SQLITE_OK != sqlite3_prepare_v2(config_db, sql, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句预编译失败: %s", sqlite3_errmsg(config_db)); - return 1; - } - - sqlite3_bind_int(stmt, 1, (uint8_t)p_upgradeRecord->status); - sqlite3_bind_text(stmt, 2, (const char *)p_upgradeRecord->errMsg, -1, SQLITE_STATIC); - sqlite3_bind_int(stmt, 3, p_upgradeRecord->dbId); - - pthread_mutex_lock(&config_db_mutex); // 加锁,确保单线程访问 - int step = sqlite3_step(stmt); - if (step != SQLITE_DONE) - { - if (step == SQLITE_ERROR) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句执行失败: %s", sqlite3_errmsg(config_db)); - } - else if (step == SQLITE_ROW) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "UPDATE操作中出现意外的SQLITE_ROW返回值"); - } - else - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL更新失败,错误代码: %d", step); - } - pthread_mutex_unlock(&config_db_mutex); // 解锁 - sqlite3_finalize(stmt); - return 1; - } - - // 检查是否实际更新了任何行。SQLITE_DONE 并不保证这一点。 - if (sqlite3_changes(config_db) == 0) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "没有更新任何行。请检查 dbId 是否正确。"); - pthread_mutex_unlock(&config_db_mutex); // 解锁 - return 1; - } - - pthread_mutex_unlock(&config_db_mutex); // 解锁 - sqlite3_finalize(stmt); - return ret; -} - -/* ############################################################################### 业务数据库操作 ############################################################################### */ - -/***************************************************************************** - * @brief 批量插入时序数据存储 - * @param[in] timedDatas: 用于存储备份数据的 UT_array 指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_insert_timed_data(UT_array *timedDatas) -{ - sqlite3_stmt *stmt = NULL; // 预编译语句句柄 - const char *sql = "INSERT INTO timed_data_storage (dev_type, dev_id, point_id, timed_value, storage_interval, created_time) VALUES (?, ?, ?, ?, ?, strftime('%Y-%m-%d %H:%M:%S', 'now'))"; - int ret = 0; - int total_count = utarray_len(timedDatas); // 总记录数 - int batch_size = 100; // 每批插入的条数 - int i; - - pthread_mutex_lock(&business_db_mutex); // 加锁,确保单线程访问 - // 开始事务 - ret = sqlite3_exec(business_db, "BEGIN TRANSACTION;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "无法开始事务: %s", sqlite3_errmsg(business_db)); - return 1; - } - - // 预编译SQL语句 - ret = sqlite3_prepare_v2(business_db, sql, -1, &stmt, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL预编译失败: %s", sqlite3_errmsg(business_db)); - return 1; - } - - // 批量插入 - for (i = 0; i < total_count; i++) - { - timed_data_storage_t *timedData = (timed_data_storage_t *)utarray_eltptr(timedDatas, i); - - // 绑定参数 - sqlite3_bind_int(stmt, 1, timedData->devType); - sqlite3_bind_int(stmt, 2, timedData->devDbId); - sqlite3_bind_int(stmt, 3, timedData->pointDbId); - // sqlite3_bind_text(stmt, 4, (const char *)timedData->devName, -1, SQLITE_STATIC); - // sqlite3_bind_text(stmt, 5, (const char *)timedData->pointName, -1, SQLITE_STATIC); - sqlite3_bind_double(stmt, 4, timedData->timedValue); - sqlite3_bind_int(stmt, 5, timedData->storageInterval); - - // 执行插入 - ret = sqlite3_step(stmt); - if (ret != SQLITE_DONE) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "插入数据失败: %s", sqlite3_errmsg(business_db)); - sqlite3_finalize(stmt); - return 1; - } - - // 重置语句,以便下次使用 - sqlite3_reset(stmt); - - // 每 batch_size 条记录提交一次事务 - if ((i + 1) % batch_size == 0) - { - ret = sqlite3_exec(business_db, "COMMIT;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "提交事务失败: %s", sqlite3_errmsg(business_db)); - sqlite3_finalize(stmt); - return 1; - } - // 重新开始事务 - ret = sqlite3_exec(business_db, "BEGIN TRANSACTION;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "无法重新开始事务: %s", sqlite3_errmsg(business_db)); - sqlite3_finalize(stmt); - return 1; - } - } - } - - // 提交剩余数据 - ret = sqlite3_exec(business_db, "COMMIT;", NULL, NULL, NULL); - pthread_mutex_unlock(&business_db_mutex); // 解锁 - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "提交事务失败: %s", sqlite3_errmsg(business_db)); - sqlite3_finalize(stmt); - return 1; - } - - // 释放预编译语句 - sqlite3_finalize(stmt); - utarray_free(timedDatas); - - return 0; // 成功 -} - -/***************************************************************************** - * @brief 根据日期时间条件,删除该日期时间之前timed_data_storage的数据 - * @param[in] storage_interval:存储周期 - * @param[in] date_time_string:日期时间 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_del_timed_data_by_date(int storage_interval, const char *date_time_string) -{ - sqlite3_stmt *stmt = NULL; // SQLite语句句柄 - int ret = 0; // 返回值 - char sql[256]; // SQL语句缓冲区 - - // 参数校验,确保日期字符串不为NULL - if (date_time_string == NULL) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "日期时间字符串为NULL"); - return 1; - } - - // 使用sqlite3_snprintf构建SQL语句,防止SQL注入 - sqlite3_snprintf(sizeof(sql), sql, - "DELETE FROM timed_data_storage WHERE storage_interval = %d AND created_time < '%q';", - storage_interval, date_time_string); - - pthread_mutex_lock(&business_db_mutex); // 加锁,确保单线程访问 - // 开始事务,确保数据一致性 - ret = sqlite3_exec(business_db, "BEGIN TRANSACTION;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "无法开始事务: %s", sqlite3_errmsg(business_db)); - pthread_mutex_unlock(&business_db_mutex); // 解锁 - return 1; // 直接返回,不继续执行 - } - - // 准备SQL语句,避免直接使用sqlite3_exec - ret = sqlite3_prepare_v2(business_db, sql, -1, &stmt, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句准备失败: %s SQL: %s", sqlite3_errmsg(business_db), sql); - sqlite3_exec(business_db, "ROLLBACK;", NULL, NULL, NULL); // 回滚事务 - pthread_mutex_unlock(&business_db_mutex); // 解锁 - return 1; - } - - // 执行SQL语句 - ret = sqlite3_step(stmt); - if (ret != SQLITE_DONE) // SQLITE_DONE表示成功执行完语句 - { - KITLOG(LOG_KIT_EN, ERROR_EN, "删除数据失败: %s SQL: %s", sqlite3_errmsg(business_db), sql); - sqlite3_exec(business_db, "ROLLBACK;", NULL, NULL, NULL); // 回滚事务 - pthread_mutex_unlock(&business_db_mutex); // 解锁 - sqlite3_finalize(stmt); // 释放SQLite语句句柄 - return 1; - } - - // 提交事务,确保操作生效 - ret = sqlite3_exec(business_db, "COMMIT;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "提交事务失败: %s", sqlite3_errmsg(business_db)); - sqlite3_exec(business_db, "ROLLBACK;", NULL, NULL, NULL); // 回滚事务 - sqlite3_finalize(stmt); // 释放SQLite语句句柄 - pthread_mutex_unlock(&business_db_mutex); // 解锁 - return 1; - } - pthread_mutex_unlock(&business_db_mutex); // 解锁 - - // 释放SQLite语句句柄,避免内存泄漏 - sqlite3_finalize(stmt); - - return 0; // 返回0表示成功 -} - -/***************************************************************************** - * @brief 批量插入故障数据存储 - * @param[in] faultsDatas: 用于存储故障数据的 UT_array 指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_insert_faults_data(UT_array *faultsDatas) -{ - sqlite3_stmt *stmt = NULL; // 预编译语句句柄 - const char *sql = "INSERT INTO faults_record (dev_type, dev_id, point_id, faults_value, created_time) VALUES (?, ?, ?, ?, strftime('%Y-%m-%d %H:%M:%S', 'now'))"; - int ret = 0; - int total_count = utarray_len(faultsDatas); // 总记录数 - int batch_size = 100; // 每批插入的条数 - int i; - - pthread_mutex_lock(&business_db_mutex); // 加锁,确保单线程访问 - // 开始事务 - ret = sqlite3_exec(business_db, "BEGIN TRANSACTION;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "无法开始事务: %s", sqlite3_errmsg(business_db)); - return 1; - } - - // 预编译SQL语句 - ret = sqlite3_prepare_v2(business_db, sql, -1, &stmt, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL预编译失败: %s", sqlite3_errmsg(business_db)); - return 1; - } - - // 批量插入 - for (i = 0; i < total_count; i++) - { - faults_data_storage_t *faultsData = (faults_data_storage_t *)utarray_eltptr(faultsDatas, i); - - // 绑定参数 - sqlite3_bind_int(stmt, 1, faultsData->devType); - sqlite3_bind_int(stmt, 2, faultsData->devDbId); - sqlite3_bind_int(stmt, 3, faultsData->pointDbId); - sqlite3_bind_double(stmt, 4, faultsData->faultsValue); - - // 执行插入 - ret = sqlite3_step(stmt); - if (ret != SQLITE_DONE) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "插入数据失败: %s", sqlite3_errmsg(business_db)); - sqlite3_finalize(stmt); - return 1; - } - - // 重置语句,以便下次使用 - sqlite3_reset(stmt); - - // 每 batch_size 条记录提交一次事务 - if ((i + 1) % batch_size == 0) - { - ret = sqlite3_exec(business_db, "COMMIT;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "提交事务失败: %s", sqlite3_errmsg(business_db)); - sqlite3_finalize(stmt); - return 1; - } - // 重新开始事务 - ret = sqlite3_exec(business_db, "BEGIN TRANSACTION;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "无法重新开始事务: %s", sqlite3_errmsg(business_db)); - sqlite3_finalize(stmt); - return 1; - } - } - } - - // 提交剩余数据 - ret = sqlite3_exec(business_db, "COMMIT;", NULL, NULL, NULL); - pthread_mutex_unlock(&business_db_mutex); // 解锁 - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "提交事务失败: %s", sqlite3_errmsg(business_db)); - sqlite3_finalize(stmt); - return 1; - } - - // 释放预编译语句 - sqlite3_finalize(stmt); - utarray_free(faultsDatas); - - return 0; // 成功 -} - -/***************************************************************************** - * @brief 根据日期时间条件,删除该日期时间之前faults_data_storage的数据 - * @param[in] date_time_string:日期时间 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_del_faults_data_by_date(const char *date_time_string) -{ - sqlite3_stmt *stmt = NULL; // SQLite语句句柄 - int ret = 0; // 返回值 - char sql[256]; // SQL语句缓冲区 - - // 参数校验,确保日期字符串不为NULL - if (date_time_string == NULL) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "日期时间字符串为NULL"); - return 1; - } - - // 使用sqlite3_snprintf构建SQL语句,防止SQL注入 - sqlite3_snprintf(sizeof(sql), sql, "DELETE FROM faults_record WHERE created_time < '%q';", date_time_string); - - pthread_mutex_lock(&business_db_mutex); // 加锁,确保单线程访问 - // 开始事务,确保数据一致性 - ret = sqlite3_exec(business_db, "BEGIN TRANSACTION;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "无法开始事务: %s", sqlite3_errmsg(business_db)); - pthread_mutex_unlock(&business_db_mutex); // 解锁 - return 1; // 直接返回,不继续执行 - } - - // 准备SQL语句,避免直接使用sqlite3_exec - ret = sqlite3_prepare_v2(business_db, sql, -1, &stmt, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句准备失败: %s SQL: %s", sqlite3_errmsg(business_db), sql); - sqlite3_exec(business_db, "ROLLBACK;", NULL, NULL, NULL); // 回滚事务 - pthread_mutex_unlock(&business_db_mutex); // 解锁 - return 1; - } - - // 执行SQL语句 - ret = sqlite3_step(stmt); - if (ret != SQLITE_DONE) // SQLITE_DONE表示成功执行完语句 - { - KITLOG(LOG_KIT_EN, ERROR_EN, "删除数据失败: %s SQL: %s", sqlite3_errmsg(business_db), sql); - sqlite3_exec(business_db, "ROLLBACK;", NULL, NULL, NULL); // 回滚事务 - pthread_mutex_unlock(&business_db_mutex); // 解锁 - sqlite3_finalize(stmt); // 释放SQLite语句句柄 - return 1; - } - - // 提交事务,确保操作生效 - ret = sqlite3_exec(business_db, "COMMIT;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "提交事务失败: %s", sqlite3_errmsg(business_db)); - sqlite3_exec(business_db, "ROLLBACK;", NULL, NULL, NULL); // 回滚事务 - sqlite3_finalize(stmt); // 释放SQLite语句句柄 - pthread_mutex_unlock(&business_db_mutex); // 解锁 - return 1; - } - pthread_mutex_unlock(&business_db_mutex); // 解锁 - - // 释放SQLite语句句柄,避免内存泄漏 - sqlite3_finalize(stmt); - - return 0; // 返回0表示成功 -} - -/******************************************************************************* - * @brief 删除指定时间字符串之前的断点保存数据 - * @param[in] date_time_string 日期时间字符串,格式为"YYYY-MM-DD HH:MM:SS" - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_del_break_data_by_date(const char *date_time_string) -{ - char sql1[256], sql2[256]; // SQL语句缓冲区 - sqlite3_stmt *stmt1 = NULL, *stmt2 = NULL; // SQLite语句句柄 - int ret = 0; // 返回值 - - // 参数校验,确保日期时间字符串不为NULL - if (date_time_string == NULL) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "日期时间字符串为NULL"); - return 1; - } - - pthread_mutex_lock(&business_db_mutex); // 加锁,确保单线程访问 - // 开始事务,确保数据一致性 - ret = sqlite3_exec(business_db, "BEGIN TRANSACTION;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "无法开始事务: %s", sqlite3_errmsg(business_db)); - pthread_mutex_unlock(&business_db_mutex); // 解锁 - return 1; // 直接返回,不继续执行 - } - - // 使用sqlite3_snprintf构建SQL语句,防止SQL注入 - sqlite3_snprintf(sizeof(sql1), sql1, "DELETE FROM break_record WHERE created_time < ?;"); - sqlite3_snprintf(sizeof(sql2), sql2, "DELETE FROM break_data_storage WHERE created_time < ?;"); - - // 准备并执行第一个 DELETE 语句 - // 准备SQL语句 - ret = sqlite3_prepare_v2(business_db, sql1, -1, &stmt1, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句准备失败: %s SQL: %s", sqlite3_errmsg(business_db), sql1); - sqlite3_exec(business_db, "ROLLBACK;", NULL, NULL, NULL); // 回滚事务 - pthread_mutex_unlock(&business_db_mutex); // 解锁 - return 1; - } - // 绑定参数 - ret = sqlite3_bind_text(stmt1, 1, date_time_string, -1, SQLITE_STATIC); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "绑定参数失败: %s", sqlite3_errmsg(business_db)); - sqlite3_finalize(stmt1); - sqlite3_exec(business_db, "ROLLBACK;", NULL, NULL, NULL); - pthread_mutex_unlock(&business_db_mutex); // 解锁 - return 1; - } - // 执行SQL语句 - ret = sqlite3_step(stmt1); - if (ret != SQLITE_DONE) // SQLITE_DONE表示成功执行完语句 - { - KITLOG(LOG_KIT_EN, ERROR_EN, "删除数据失败: %s SQL: %s", sqlite3_errmsg(business_db), sql1); - sqlite3_exec(business_db, "ROLLBACK;", NULL, NULL, NULL); // 回滚事务 - pthread_mutex_unlock(&business_db_mutex); // 解锁 - sqlite3_finalize(stmt1); // 释放SQLite语句句柄 - return 1; - } - - // 准备并执行第二个 DELETE 语句 - // 准备SQL语句 - ret = sqlite3_prepare_v2(business_db, sql2, -1, &stmt2, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句准备失败: %s SQL: %s", sqlite3_errmsg(business_db), sql2); - sqlite3_exec(business_db, "ROLLBACK;", NULL, NULL, NULL); // 回滚事务 - pthread_mutex_unlock(&business_db_mutex); // 解锁 - return 1; - } - // 绑定参数 - ret = sqlite3_bind_text(stmt2, 1, date_time_string, -1, SQLITE_STATIC); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "绑定参数失败: %s", sqlite3_errmsg(business_db)); - sqlite3_finalize(stmt2); - sqlite3_exec(business_db, "ROLLBACK;", NULL, NULL, NULL); - pthread_mutex_unlock(&business_db_mutex); // 解锁 - return 1; - } - // 执行SQL语句 - ret = sqlite3_step(stmt2); - if (ret != SQLITE_DONE) // SQLITE_DONE表示成功执行完语句 - { - KITLOG(LOG_KIT_EN, ERROR_EN, "删除数据失败: %s SQL: %s", sqlite3_errmsg(business_db), sql2); - sqlite3_exec(business_db, "ROLLBACK;", NULL, NULL, NULL); // 回滚事务 - pthread_mutex_unlock(&business_db_mutex); // 解锁 - sqlite3_finalize(stmt2); // 释放SQLite语句句柄 - return 1; - } - - // 提交事务,确保操作生效 - ret = sqlite3_exec(business_db, "COMMIT;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "提交事务失败: %s", sqlite3_errmsg(business_db)); - sqlite3_exec(business_db, "ROLLBACK;", NULL, NULL, NULL); // 回滚事务 - pthread_mutex_unlock(&business_db_mutex); // 解锁 - return 1; - } - pthread_mutex_unlock(&business_db_mutex); // 解锁 - - // 释放SQLite语句句柄,避免内存泄漏 - sqlite3_finalize(stmt1); - - return 0; // 返回0表示成功 -} - -/***************************************************************************** - * @brief 查询MQTT断开记录,根据isUploaded字段筛选。 - * @param[in] isUploaded: 要查询的is_uploaded字段值。如果为255,则查询所有记录。 - * @param[out] breakRecord: 用于存储查询结果的UT_array指针。 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_query_break_records(uint8_t isUploaded, UT_array **breakRecord) -{ - sqlite3_stmt *stmt = NULL; - char *sql; - - if (isUploaded == 255) - { - sql = sqlite3_mprintf("SELECT id, reason, is_uploaded FROM break_record ORDER BY created_time ASC;"); - } - else - { - sql = sqlite3_mprintf("SELECT id, reason, is_uploaded FROM break_record WHERE is_uploaded = %d ORDER BY created_time ASC;", isUploaded); - } - - if (SQLITE_OK != sqlite3_prepare_v2(business_db, sql, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL预编译失败: %s", sqlite3_errmsg(business_db)); - sqlite3_free(sql); - return 1; - } - sqlite3_free(sql); - - utarray_new(*breakRecord, &break_record_icd); // 初始化UT_array - - // 执行查询并处理结果 - int step = sqlite3_step(stmt); - while (SQLITE_ROW == step) - { - break_record_t record = {0}; - /* - //永远不可能为空 - if (&record == NULL) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "内存分配失败"); - utarray_free(*breakRecord); - sqlite3_finalize(stmt); - return 1; - } - */ - record.dbId = sqlite3_column_int64(stmt, 0); - strncpy((char *)record.reason, (const char *)sqlite3_column_text(stmt, 1), MAX_NAME_BUF_LEN - 1); - record.reason[MAX_NAME_BUF_LEN - 1] = '\0'; // 确保字符串结尾为\0 - record.isUploaded = sqlite3_column_int(stmt, 2); - utarray_push_back(*breakRecord, &record); - - step = sqlite3_step(stmt); - } - - if (SQLITE_DONE != step) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL执行失败: %s", sqlite3_errmsg(business_db)); - utarray_free(*breakRecord); - sqlite3_finalize(stmt); - return 1; - } - - sqlite3_finalize(stmt); - return 0; -} - -/***************************************************************************** - * @brief 插入MQTT断开记录,包括中断原因、是否已上传以及断开开始和结束时间。返回插入记录的ID。 - * @param[in] breakRecord: 包含MQTT断开信息的结构体指针:该结构体必须包含中断原因(reason) - * @return 插入记录的ID;-1-插入记录失败(包括SQL预编译失败和SQL执行失败)。 - *****************************************************************************/ -long long kit_insert_break_record(break_record_t *breakRecord) -{ - sqlite3_stmt *stmt = NULL; - const char *sql = "INSERT INTO break_record(reason, is_uploaded, start_time) VALUES(?, 0, strftime('%Y-%m-%d %H:%M:%S', 'now'));"; // 注意分号 - - if (SQLITE_OK != sqlite3_prepare_v2(business_db, sql, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL预编译失败: %s", sqlite3_errmsg(business_db)); - return -1; // 返回-1表示失败 - } - - sqlite3_bind_text(stmt, 1, (const char *)breakRecord->reason, -1, SQLITE_STATIC); - pthread_mutex_lock(&business_db_mutex); // 加锁,确保单线程访问 - int step = sqlite3_step(stmt); - if (SQLITE_DONE != step) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "插入数据失败: %s", sqlite3_errmsg(business_db)); - sqlite3_finalize(stmt); - return -1; // 返回-1表示失败 - } - - long long last_insert_rowid = sqlite3_last_insert_rowid(business_db); // 获取最后插入行的rowid - pthread_mutex_unlock(&business_db_mutex); // 解锁 - sqlite3_finalize(stmt); - return last_insert_rowid; // 返回插入记录的ID -} - -/***************************************************************************** - * @brief 更新MQTT断开记录的上传状态。此函数更新数据库中MQTT断开记录的`is_uploaded`字段。 - * @param[in] breakRecord: 指向包含MQTT断开信息的结构体指针。该结构体必须包含断开记录在数据库中的ID (`dbId`) 和新的上传状态 (`isUploaded`)。 - * @return 0-成功更新记录;1-更新记录失败(包括SQL语句预编译失败、SQL语句执行失败或未找到匹配的记录)。如果SQL语句执行成功,但没有更新任何行(例如,`dbId`不存在),则返回1,并记录警告日志。 - *****************************************************************************/ -int kit_update_break_record(break_record_t *breakRecord) -{ - int ret = 0; - sqlite3_stmt *stmt = NULL; - const char *sql = sqlite3_mprintf("UPDATE break_record SET is_uploaded = ? WHERE id = ?"); - - if (SQLITE_OK != sqlite3_prepare_v2(business_db, sql, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句预编译失败: %s", sqlite3_errmsg(business_db)); - return 1; - } - - sqlite3_bind_int(stmt, 1, breakRecord->isUploaded); - sqlite3_bind_int64(stmt, 2, breakRecord->dbId); - - pthread_mutex_lock(&business_db_mutex); // 加锁,确保单线程访问 - int step = sqlite3_step(stmt); - if (step != SQLITE_DONE) - { - if (step == SQLITE_ERROR) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句执行失败: %s", sqlite3_errmsg(business_db)); - } - else if (step == SQLITE_ROW) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "UPDATE操作中出现意外的SQLITE_ROW返回值"); - } - else - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL更新失败,错误代码: %d", step); - } - pthread_mutex_unlock(&business_db_mutex); // 解锁 - sqlite3_finalize(stmt); - return 1; - } - - // 检查是否实际更新了任何行。SQLITE_DONE 并不保证这一点。 - if (sqlite3_changes(business_db) == 0) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "没有更新任何行。请检查 dbId 是否正确。"); - pthread_mutex_unlock(&business_db_mutex); // 解锁 - return 1; - } - - pthread_mutex_unlock(&business_db_mutex); // 解锁 - sqlite3_finalize(stmt); - return ret; -} - -/***************************************************************************** - * @brief 批量插入MQTT断联时的历史数据存储 - * @param[in] breakDbId:MQTT断联的数据库Id - * @param[in] timedDatas: 用于历史数据存储的 UT_array 指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_insert_break_data_storage(uint64_t breakDbId, UT_array **timedDatas) -{ - sqlite3_stmt *stmt = NULL; // 预编译语句句柄 - const char *sql = "INSERT INTO break_data_storage(break_id, content, is_uploaded, created_time) VALUES (?, ?, 0, strftime('%Y-%m-%d %H:%M:%S', 'now'))"; - int ret = 0; - int total_count = utarray_len(*timedDatas); // 总记录数 - int batch_size = 100; // 每批插入的条数 - int i; - - pthread_mutex_lock(&business_db_mutex); // 加锁,确保单线程访问 - // 开始事务 - ret = sqlite3_exec(business_db, "BEGIN TRANSACTION;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "无法开始事务: %s", sqlite3_errmsg(business_db)); - return 1; - } - - // 预编译SQL语句 - ret = sqlite3_prepare_v2(business_db, sql, -1, &stmt, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL预编译失败: %s", sqlite3_errmsg(business_db)); - return 1; - } - - // 批量插入 - for (i = 0; i < total_count; i++) - { - break_data_storage_t *timedData = (break_data_storage_t *)utarray_eltptr(*timedDatas, i); - - // 绑定参数 - sqlite3_bind_int64(stmt, 1, breakDbId); - sqlite3_bind_text(stmt, 2, (const char *)timedData->content, -1, SQLITE_STATIC); - - // 执行插入 - ret = sqlite3_step(stmt); - if (ret != SQLITE_DONE) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "插入数据失败: %s", sqlite3_errmsg(business_db)); - sqlite3_finalize(stmt); - return 1; - } - - // 重置语句,以便下次使用 - sqlite3_reset(stmt); - - // 每 batch_size 条记录提交一次事务 - if ((i + 1) % batch_size == 0) - { - ret = sqlite3_exec(business_db, "COMMIT;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "提交事务失败: %s", sqlite3_errmsg(business_db)); - sqlite3_finalize(stmt); - return 1; - } - // 重新开始事务 - ret = sqlite3_exec(business_db, "BEGIN TRANSACTION;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "无法重新开始事务: %s", sqlite3_errmsg(business_db)); - sqlite3_finalize(stmt); - return 1; - } - } - } - - // 提交剩余数据 - ret = sqlite3_exec(business_db, "COMMIT;", NULL, NULL, NULL); - pthread_mutex_unlock(&business_db_mutex); // 解锁 - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "提交事务失败: %s", sqlite3_errmsg(business_db)); - sqlite3_finalize(stmt); - return 1; - } - - // 释放预编译语句 - sqlite3_finalize(stmt); - - return 0; // 成功 -} - -/***************************************************************************** - * @brief 根据断开记录ID和行号范围查询断开数据。 - * @param[in] breakDbId: MQTT断开记录的数据库ID。 - * @param[out] timedDatas: 用于存储查询数据的UT_array指针。必须在调用之前初始化。 - * @return 0-成功;1-失败(数据库错误或其他问题)。 - *****************************************************************************/ -int kit_query_break_data(uint64_t breakDbId, UT_array **timedDatas) -{ - sqlite3_stmt *stmt = NULL; - char *sql = NULL; - int ret = 0; - - // 构造SQL查询语句,使用LIMIT子句进行分页 - // 将 SELECT 子句改为选择 id 和 content 两个字段 - sql = sqlite3_mprintf("SELECT id, content FROM break_data_storage WHERE break_id = %d AND is_uploaded = 0 ORDER BY created_time LIMIT 100", breakDbId); - - if (SQLITE_OK != sqlite3_prepare_v2(business_db, sql, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句预编译失败: %s", sqlite3_errmsg(business_db)); - sqlite3_free(sql); - return 1; - } - - while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) - { - break_data_storage_t timedData = {0}; - snprintf((char *)timedData.content, MAX_JSON_STR_LEN, "%s", (uint8_t *)sqlite3_column_text(stmt, 1)); - uint64_t id = sqlite3_column_int(stmt, 0); - timedData.breakDbId = id; - utarray_push_back(*timedDatas, &timedData); - } - - if (ret != SQLITE_DONE && ret != SQLITE_ROW) - { // 添加对非SQLITE_DONE和SQLITE_ROW情况的检查 - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句执行失败: %s, 错误码: %d", sqlite3_errmsg(business_db), ret); - sqlite3_finalize(stmt); - sqlite3_free(sql); - return 1; - } - - sqlite3_finalize(stmt); - sqlite3_free(sql); - return 0; -} - -/***************************************************************************** - * @brief 批量更新断开数据的上传状态,使用事务保证数据一致性。 - * @param[in] break_id: MQTT断开记录的break_id。 - * @param[in] ids: storage的id数组。 - * @param[in] length: storage的id数组长度。 - * @return 0-成功;1-失败 - *****************************************************************************/ -int kit_update_break_data(uint16_t break_id, uint64_t ids[], int length) -{ - if (length <= 0 || ids == NULL) - { - // 如果传入的id数组为空或长度为0, 无需执行更新。 - return 0; - } - - sqlite3_stmt *stmt = NULL; - int ret = 0; - int i = 0; - char *sql = NULL; - char *in_clause = NULL; - - pthread_mutex_lock(&business_db_mutex); // 加锁,确保单线程访问 - - // 开始事务 - if (SQLITE_OK != sqlite3_exec(business_db, "BEGIN TRANSACTION", NULL, NULL, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "开始事务失败: %s", sqlite3_errmsg(business_db)); - pthread_mutex_unlock(&business_db_mutex); - return 1; - } - - // 构建 IN 子句字符串 - in_clause = sqlite3_mprintf("("); - for (i = 0; i < length; i++) - { - in_clause = sqlite3_mprintf("%s%s?", in_clause, (i > 0) ? "," : ""); - } - in_clause = sqlite3_mprintf("%s)", in_clause); - - // 创建 SQL 语句 - sql = sqlite3_mprintf("UPDATE break_data_storage SET is_uploaded = 1 WHERE break_id = ? AND id IN %s", in_clause); - sqlite3_free(in_clause); - - if (SQLITE_OK != sqlite3_prepare_v2(business_db, sql, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句预编译失败: %s", sqlite3_errmsg(business_db)); - sqlite3_free(sql); - sqlite3_exec(business_db, "ROLLBACK TRANSACTION", NULL, NULL, NULL); - pthread_mutex_unlock(&business_db_mutex); - return 1; - } - sqlite3_free(sql); - - // 绑定 break_id 参数 - sqlite3_bind_int(stmt, 1, break_id); - - // 绑定 ID 参数 - for (i = 0; i < length; i++) - { - sqlite3_bind_int64(stmt, i + 2, ids[i]); // IDs 从第二个参数开始 - } - - // 执行 SQL 语句 - ret = sqlite3_step(stmt); - if (ret != SQLITE_DONE) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句执行失败: %s, 错误码: %d", sqlite3_errmsg(business_db), ret); - sqlite3_finalize(stmt); - sqlite3_exec(business_db, "ROLLBACK TRANSACTION", NULL, NULL, NULL); - pthread_mutex_unlock(&business_db_mutex); - return 1; - } - - sqlite3_finalize(stmt); - - // 提交事务 - if (SQLITE_OK != sqlite3_exec(business_db, "COMMIT TRANSACTION", NULL, NULL, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "提交事务失败: %s", sqlite3_errmsg(business_db)); - pthread_mutex_unlock(&business_db_mutex); - return 1; - } - - pthread_mutex_unlock(&business_db_mutex); - - return 0; -} - -/***************************************************************************** - * @brief 批量插入插入功率数据 - * @param[in] powerDatas: 用于存储备份数据的 UT_array 指针 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_insert_power_data(UT_array *powerDatas) -{ - sqlite3_stmt *stmt = NULL; // 预编译语句句柄 - const char *sql = "INSERT INTO power_data_storage(dev_type, dev_code, point_code, value, created_time) VALUES(?, ?, ?, ?, strftime('%Y-%m-%d %H:%M:%S', 'now'));"; - int ret = 0; - int total_count = utarray_len(powerDatas); // 总记录数 - int batch_size = 100; // 每批插入的条数 - int i; - - pthread_mutex_lock(&business_db_mutex); // 加锁,确保单线程访问 - // 开始事务 - ret = sqlite3_exec(business_db, "BEGIN TRANSACTION;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "无法开始事务: %s", sqlite3_errmsg(business_db)); - pthread_mutex_unlock(&business_db_mutex); // 解锁 - return 1; - } - - // 预编译SQL语句 - ret = sqlite3_prepare_v2(business_db, sql, -1, &stmt, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL预编译失败: %s", sqlite3_errmsg(business_db)); - pthread_mutex_unlock(&business_db_mutex); // 解锁 - return 1; - } - - // 批量插入 - for (i = 0; i < total_count; i++) - { - power_data_storage_t *powerData = (power_data_storage_t *)utarray_eltptr(powerDatas, i); - - // 绑定参数 - sqlite3_bind_int(stmt, 1, powerData->devType); - sqlite3_bind_int(stmt, 2, powerData->devId); - sqlite3_bind_int(stmt, 3, powerData->pointId); - sqlite3_bind_double(stmt, 4, powerData->value); - - // 执行插入 - ret = sqlite3_step(stmt); - if (ret != SQLITE_DONE) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "插入数据失败: %s", sqlite3_errmsg(business_db)); - pthread_mutex_unlock(&business_db_mutex); // 解锁 - sqlite3_finalize(stmt); - return 1; - } - - // 重置语句,以便下次使用 - sqlite3_reset(stmt); - - // 每 batch_size 条记录提交一次事务 - if ((i + 1) % batch_size == 0) - { - ret = sqlite3_exec(business_db, "COMMIT;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "提交事务失败: %s", sqlite3_errmsg(business_db)); - pthread_mutex_unlock(&business_db_mutex); // 解锁 - sqlite3_finalize(stmt); - return 1; - } - // 重新开始事务 - ret = sqlite3_exec(business_db, "BEGIN TRANSACTION;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "无法重新开始事务: %s", sqlite3_errmsg(business_db)); - pthread_mutex_unlock(&business_db_mutex); // 解锁 - sqlite3_finalize(stmt); - return 1; - } - } - } - - // 提交剩余数据 - ret = sqlite3_exec(business_db, "COMMIT;", NULL, NULL, NULL); - pthread_mutex_unlock(&business_db_mutex); // 解锁 - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "提交事务失败: %s", sqlite3_errmsg(business_db)); - sqlite3_finalize(stmt); - return 1; - } - - // 释放预编译语句 - sqlite3_finalize(stmt); - utarray_free(powerDatas); - - return 0; // 成功 -} - -/***************************************************************************** - * @brief 根据日期时间条件,删除该日期时间之前power_data_storage的数据 - * @param[in] date_time_string:日期时间 - * @return 0-成功 1-失败 - *****************************************************************************/ -int kit_del_power_data_by_date(const char *date_time_string) -{ - sqlite3_stmt *stmt = NULL; // SQLite语句句柄 - int ret = 0; // 返回值 - char sql[256]; // SQL语句缓冲区 - - // 参数校验,确保日期字符串不为NULL - if (date_time_string == NULL) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "日期时间字符串为NULL"); - return 1; - } - - // 使用sqlite3_snprintf构建SQL语句,防止SQL注入 - sqlite3_snprintf(sizeof(sql), sql, "DELETE FROM power_data_storage WHERE created_time < '%q';", date_time_string); - - pthread_mutex_lock(&business_db_mutex); // 加锁,确保单线程访问 - // 开始事务,确保数据一致性 - ret = sqlite3_exec(business_db, "BEGIN TRANSACTION;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "无法开始事务: %s", sqlite3_errmsg(business_db)); - pthread_mutex_unlock(&business_db_mutex); // 解锁 - return 1; // 直接返回,不继续执行 - } - - // 准备SQL语句,避免直接使用sqlite3_exec - ret = sqlite3_prepare_v2(business_db, sql, -1, &stmt, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL语句准备失败: %s SQL: %s", sqlite3_errmsg(business_db), sql); - sqlite3_exec(business_db, "ROLLBACK;", NULL, NULL, NULL); // 回滚事务 - pthread_mutex_unlock(&business_db_mutex); // 解锁 - return 1; - } - - // 执行SQL语句 - ret = sqlite3_step(stmt); - if (ret != SQLITE_DONE) // SQLITE_DONE表示成功执行完语句 - { - KITLOG(LOG_KIT_EN, ERROR_EN, "删除数据失败: %s SQL: %s", sqlite3_errmsg(business_db), sql); - sqlite3_exec(business_db, "ROLLBACK;", NULL, NULL, NULL); // 回滚事务 - pthread_mutex_unlock(&business_db_mutex); // 解锁 - sqlite3_finalize(stmt); // 释放SQLite语句句柄 - return 1; - } - - // 提交事务,确保操作生效 - ret = sqlite3_exec(business_db, "COMMIT;", NULL, NULL, NULL); - if (ret != SQLITE_OK) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "提交事务失败: %s", sqlite3_errmsg(business_db)); - sqlite3_exec(business_db, "ROLLBACK;", NULL, NULL, NULL); // 回滚事务 - pthread_mutex_unlock(&business_db_mutex); // 解锁 - sqlite3_finalize(stmt); // 释放SQLite语句句柄 - return 1; - } - pthread_mutex_unlock(&business_db_mutex); // 解锁 - - // 释放SQLite语句句柄,避免内存泄漏 - sqlite3_finalize(stmt); - - return 0; // 返回0表示成功 -} - -/***************************************************************************** - * @brief 获取指定表中特定dbId的记录数量 - * @param[in] db: SQLite3 数据库连接对象 - * @param[in] tabName: 查询表的名称 - * @param[in] dbid: 用于查询记录的dbId值 - * @return 记录数量(成功返回记录数量;失败返回-1) - *****************************************************************************/ -int kit_get_record_count_by_dbid(sqlite3 *db, const char *tabName, uint64_t dbid) -{ - sqlite3_stmt *stmt; - char sql[256]; - int result = 0; - int rc; - - // 使用 snprintf 合成 SQL 查询字符串 - snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE db_id = ?", tabName); - - // 预编译SQL语句 - rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); - if (rc != SQLITE_OK) - { - printf("Failed to prepare statement: %s\n", sqlite3_errmsg(db)); - return -1; - } - - // 绑定参数 - sqlite3_bind_int64(stmt, 1, dbid); - - // 执行SQL查询 - if ((rc = sqlite3_step(stmt)) == SQLITE_ROW) - { - result = sqlite3_column_int(stmt, 0); - } - else - { - printf("Failed to execute query: %s\n", sqlite3_errmsg(db)); - } - - // 清理和释放资源 - sqlite3_finalize(stmt); - - return result; -} - -/***************************************************************************** - * @brief 插入北向断开记录,记录最新连接状态。 - * @param[in] connectStatus: 连接状态 - * @return 0-成功 1-失败。 - *****************************************************************************/ -int kit_insert_lost_contact_record(const char* connectStatus) -{ - sqlite3_stmt *stmt = NULL; - const char *sql = "INSERT INTO lost_contact_record(connect_status, created_time) VALUES(?, strftime('%Y-%m-%d %H:%M:%S', 'now'));"; - - if (SQLITE_OK != sqlite3_prepare_v2(business_db, sql, -1, &stmt, NULL)) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "SQL预编译失败: %s", sqlite3_errmsg(business_db)); - return 1; // 返回1表示失败 - } - - sqlite3_bind_text(stmt, 1, connectStatus, -1, SQLITE_STATIC); - pthread_mutex_lock(&business_db_mutex); // 加锁,确保单线程访问 - int step = sqlite3_step(stmt); - if (SQLITE_DONE != step) - { - KITLOG(LOG_KIT_EN, ERROR_EN, "插入数据失败: %s", sqlite3_errmsg(business_db)); - sqlite3_finalize(stmt); - return 1; // 返回1表示失败 - } - - pthread_mutex_unlock(&business_db_mutex); // 解锁 - sqlite3_finalize(stmt); - return 0; -} \ No newline at end of file diff --git a/ems_c/main.c b/ems_c/main.c index f7b7f79..79553e6 100644 --- a/ems_c/main.c +++ b/ems_c/main.c @@ -28,50 +28,6 @@ int main(int argc, char *argv[]) { void *arg = NULL; // 初始化参数 int ret = 0; // 返回值 - cli_args_t args = {0}; // 命令行参数结构体初始化 - - // 解析命令行参数 - cliArgsInit(argc, argv, &args); - - // 是否开启进程守护 - if (args.daemonized) - { - daemonize(); - } - - // 加锁,防止重复运行 - if (checkDaemonRunning() == 1) - { - // 是否执行停止命令 - if (args.stop) - { - ret = stop_daemon(); - if (ret == 0) - { - KITPTF(LOG_DAEMON_EN, INFO_EN, "_EMS_C_V1.0.0 停止成功。"); - } - else - { - KITPTF(LOG_DAEMON_EN, INFO_EN, "_EMS_C_V1.0.0 停止失败。"); - } - } - else - { - KITPTF(LOG_DAEMON_EN, INFO_EN, "_EMS_C_V1.0.0 进程已经在运行中,不可重复运行,已退出。"); - ret = 1; - } - goto main_end; - } - else - { - if (args.stop) - { - ret = 0; - printf("_EMS_C_V1.0.0 不在运行中,停止失败。\n"); - goto main_end; - } - } - // EMS初始化 ret = initEmsSystem(arg);