/** ****************************************************************************** * @file tcp_protocol.c * @brief TCP通信协议解析实现 ****************************************************************************** */ #include "tcp_protocol.h" #include "tcp_server.h" #include "cJSON.h" #include #include #include "publicdata/publicdata.h" #include "publicdata/type.h" #include "fault_cheak/fault_interface.h" #if BLE_DEBUG_EN #include "debug_link.h" #endif #if TCP_DEBUG_EN #include "system_data.h" #include "debug_files.h" #include "FreeRTOS.h" #include "task.h" /* 兼容历史代码中涉及的数据结构声明(当前实际读取逻辑已迁移到 system_data.c) */ #include "flash_file_mgr/fault_flash_impl.h" #include "flash_file_mgr/meter_calculate_flash_impl.h" #include "app_fatfs/fatfs_card.h" /* 内部函数声明 */ static void tcp_fill_default_timestamp(char *buffer, uint32_t size); int tcp_process_file_operation(const tcp_file_operation_data_t *fileOperation); /* GetCurrentTime函数声明(在项目中已定义) */ extern void GetCurrentTime(Comm_Time *time); /* v_rtc_set_time函数声明(在BSP/app_rtc/app_rtc.c中定义) */ extern void v_rtc_set_time(Comm_Time *time); /** * @brief 生成当前时间戳字符串 * @param buffer 缓冲区 * @param size 缓冲区大小 * @retval 0成功,-1失败 */ int tcp_generate_timestamp(char *buffer, uint32_t size) { Comm_Time curTime; if (buffer == NULL || size < 24) { return -1; } /* 获取当前系统时间 */ GetCurrentTime(&curTime); /* 格式化为字符串:YYYY-MM-DD HH:MM:SS.000 */ snprintf(buffer, size, "%04d-%02d-%02d %02d:%02d:%02d.000", curTime.iYear, curTime.ucMonth, curTime.ucDay, curTime.ucHour, curTime.ucMin, curTime.ucSec); return 0; } /** * @brief 填充默认时间戳(用于测试) */ static void tcp_fill_default_timestamp(char *buffer, uint32_t size) { /* 保留此函数作为备用,但主函数已使用真实时间 */ Comm_Time curTime; GetCurrentTime(&curTime); snprintf(buffer, size, "%04d-%02d-%02d %02d:%02d:%02d.000", curTime.iYear, curTime.ucMonth, curTime.ucDay, curTime.ucHour, curTime.ucMin, curTime.ucSec); } /** * @brief 生成心跳消息JSON * @param sequence 序列号 * @param source 来源字符串 * @param buffer 输出缓冲区 * @param size 缓冲区大小 * @retval JSON字符串长度,-1表示失败 */ int tcp_generate_heartbeat_json(uint32_t sequence, const char *source, char *buffer, uint32_t size) { cJSON *root = NULL; cJSON *data = NULL; char timestamp[32]; char *json_str = NULL; int json_len = 0; if (buffer == NULL || size == 0) { return -1; } /* 生成时间戳 */ if (tcp_generate_timestamp(timestamp, sizeof(timestamp)) != 0) { return -1; } /* 创建JSON对象 */ root = cJSON_CreateObject(); if (root == NULL) { return -1; } cJSON_AddStringToObject(root, "version", "2.0"); cJSON_AddStringToObject(root, "timestamp", timestamp); cJSON_AddStringToObject(root, "command", CMD_HEARTBEAT); /* 创建data对象 */ data = cJSON_CreateObject(); if (data == NULL) { cJSON_Delete(root); return -1; } cJSON_AddNumberToObject(data, "sequence", sequence); cJSON_AddStringToObject(data, "source", source); cJSON_AddItemToObject(root, "data", data); /* 生成JSON字符串 */ json_str = cJSON_PrintUnformatted(root); if (json_str == NULL) { cJSON_Delete(root); return -1; } json_len = strlen(json_str); if (json_len + 1 > size) { cJSON_free(json_str); cJSON_Delete(root); return -1; } /* 复制到输出缓冲区 */ strncpy(buffer, json_str, size); buffer[size - 1] = '\0'; /* 释放内存 */ cJSON_free(json_str); cJSON_Delete(root); return json_len; } /** * @brief 生成系统信息消息JSON * @param systemInfo 系统信息结构体指针 * @param buffer 输出缓冲区 * @param size 缓冲区大小 * @retval JSON字符串长度,-1表示失败 */ int tcp_generate_system_info_json(const tcp_system_info_data_t *systemInfo, char *buffer, uint32_t size) { cJSON *root = NULL; cJSON *data = NULL; char timestamp[32]; char *json_str = NULL; int json_len = 0; if (buffer == NULL || size == 0 || systemInfo == NULL) { return -1; } /* 生成时间戳 */ if (tcp_generate_timestamp(timestamp, sizeof(timestamp)) != 0) { return -1; } /* 创建JSON对象 */ root = cJSON_CreateObject(); if (root == NULL) { return -1; } cJSON_AddStringToObject(root, "version", "2.0"); cJSON_AddStringToObject(root, "timestamp", timestamp); cJSON_AddStringToObject(root, "command", CMD_SYSTEM_INFO); /* 创建data对象 */ data = cJSON_CreateObject(); if (data == NULL) { cJSON_Delete(root); return -1; } cJSON_AddStringToObject(data, "systemModel", systemInfo->systemModel); cJSON_AddNumberToObject(data, "gunCount", systemInfo->gunCount); cJSON_AddNumberToObject(data, "devicePower", systemInfo->devicePower); cJSON_AddNumberToObject(data, "networkStatus", systemInfo->networkStatus); cJSON_AddNumberToObject(data, "faultCount", systemInfo->faultCount); cJSON_AddStringToObject(data, "version", systemInfo->version); cJSON_AddItemToObject(root, "data", data); /* 生成JSON字符串 */ json_str = cJSON_PrintUnformatted(root); if (json_str == NULL) { cJSON_Delete(root); return -1; } json_len = strlen(json_str); if (json_len + 1 > size) { cJSON_free(json_str); cJSON_Delete(root); return -1; } /* 复制到输出缓冲区 */ strncpy(buffer, json_str, size); buffer[size - 1] = '\0'; /* 释放内存 */ cJSON_free(json_str); cJSON_Delete(root); return json_len; } /** * @brief 生成充电枪数据消息JSON * @param gunData 充电枪数据结构体指针 * @param buffer 输出缓冲区 * @param size 缓冲区大小 * @retval JSON字符串长度,-1表示失败 */ int tcp_generate_gun_data_json(const tcp_gun_data_t *gunData, char *buffer, uint32_t size) { cJSON *root = NULL; cJSON *data = NULL; char timestamp[32]; char *json_str = NULL; int json_len = 0; if (buffer == NULL || size == 0 || gunData == NULL) { return -1; } /* 生成时间戳 */ if (tcp_generate_timestamp(timestamp, sizeof(timestamp)) != 0) { return -1; } /* 创建JSON对象 */ root = cJSON_CreateObject(); if (root == NULL) { return -1; } cJSON_AddStringToObject(root, "version", "2.0"); cJSON_AddStringToObject(root, "timestamp", timestamp); cJSON_AddStringToObject(root, "command", CMD_GUN_INFO); /* 创建data对象 */ data = cJSON_CreateObject(); if (data == NULL) { cJSON_Delete(root); return -1; } cJSON_AddNumberToObject(data, "gunNumber", gunData->gunNumber); cJSON_AddNumberToObject(data, "chargingStatus", gunData->chargingStatus); cJSON_AddNumberToObject(data, "gunConnectionStatus", gunData->gunConnectionStatus); cJSON_AddNumberToObject(data, "chargingTime", gunData->charge_time); cJSON_AddNumberToObject(data, "demandVoltage", gunData->demandVoltage); cJSON_AddNumberToObject(data, "demandCurrent", gunData->demandCurrent); cJSON_AddNumberToObject(data, "actualVoltage", gunData->actualVoltage); cJSON_AddNumberToObject(data, "actualCurrent", gunData->actualCurrent); cJSON_AddNumberToObject(data, "energy", gunData->energy); cJSON_AddNumberToObject(data, "cost", gunData->cost); cJSON_AddNumberToObject(data, "batterySOC", gunData->batterySOC); cJSON_AddStringToObject(data, "userId", gunData->userId); cJSON_AddStringToObject(data, "orderNumber", gunData->orderNumber); cJSON_AddItemToObject(root, "data", data); /* 生成JSON字符串 */ json_str = cJSON_PrintUnformatted(root); if (json_str == NULL) { cJSON_Delete(root); return -1; } json_len = strlen(json_str); if (json_len + 1 > size) { cJSON_free(json_str); cJSON_Delete(root); return -1; } /* 复制到输出缓冲区 */ strncpy(buffer, json_str, size); buffer[size - 1] = '\0'; /* 释放内存 */ cJSON_free(json_str); cJSON_Delete(root); return json_len; } /** * @brief 解析接收到的JSON消息 * @param json JSON字符串 * @param message 输出消息结构体 * @retval 0成功,-1失败 */ int tcp_parse_json_message(const char *json, tcp_message_t *message) { cJSON *root = NULL; cJSON *item = NULL; cJSON *data = NULL; if (json == NULL || message == NULL) { TCP_PRINT("tcp_parse_json_message: NULL parameters\r\n"); return -1; } /* 解析JSON */ root = cJSON_Parse(json); if (root == NULL) { TCP_PRINT("tcp_parse_json_message: cJSON_Parse failed\r\n"); return -1; } /* 清空消息结构体 */ memset(message, 0, sizeof(tcp_message_t)); /* 解析version */ item = cJSON_GetObjectItem(root, "version"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->version, item->valuestring, sizeof(message->version) - 1); } /* 解析timestamp */ item = cJSON_GetObjectItem(root, "timestamp"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->timestamp, item->valuestring, sizeof(message->timestamp) - 1); } /* 解析command */ item = cJSON_GetObjectItem(root, "command"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->command, item->valuestring, sizeof(message->command) - 1); } else { cJSON_Delete(root); return -1; } /* 解析data */ data = cJSON_GetObjectItem(root, "data"); if (data == NULL || !cJSON_IsObject(data)) { TCP_PRINT("tcp_parse_json_message: missing or invalid data object\r\n"); cJSON_Delete(root); return -1; } /* 根据command类型解析data */ if (strcmp(message->command, CMD_HEARTBEAT) == 0) { /* 解析心跳数据 */ item = cJSON_GetObjectItem(data, "sequence"); if (item != NULL && cJSON_IsNumber(item)) { message->data.heartbeat.sequence = (uint32_t)item->valueint; } item = cJSON_GetObjectItem(data, "source"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->data.heartbeat.source, item->valuestring, sizeof(message->data.heartbeat.source) - 1); } } else if (strcmp(message->command, CMD_CHARGE_CONTROL) == 0) { /* 解析充电启停控制数据 */ item = cJSON_GetObjectItem(data, "gunNumber"); if (item != NULL && cJSON_IsNumber(item)) { message->data.chargeControl.gunNumber = (uint8_t)item->valueint; } item = cJSON_GetObjectItem(data, "action"); if (item != NULL && cJSON_IsNumber(item)) { message->data.chargeControl.action = (uint8_t)item->valueint; } } else if (strcmp(message->command, CMD_PARAM_QUERY) == 0) { /* 解析参数查询数据 */ item = cJSON_GetObjectItem(data, "type"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->data.paramQuery.type, item->valuestring, sizeof(message->data.paramQuery.type) - 1); } else { cJSON_Delete(root); return -1; } } else if (strcmp(message->command, CMD_PARAM_MODIFY) == 0) { /* 解析参数修改数据 */ item = cJSON_GetObjectItem(data, "type"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->data.paramModify.type, item->valuestring, sizeof(message->data.paramModify.type) - 1); } else { cJSON_Delete(root); return -1; } /* 解析参数数组 */ cJSON *params_array = cJSON_GetObjectItem(data, "params"); if (params_array != NULL && cJSON_IsArray(params_array)) { int array_size = cJSON_GetArraySize(params_array); if (array_size > 0) { /* 分配内存存储参数 */ message->data.paramModify.count = array_size; message->data.paramModify.params = (tcp_param_item_t *)pvPortMalloc( array_size * sizeof(tcp_param_item_t)); if (message->data.paramModify.params == NULL) { cJSON_Delete(root); return -1; } /* 清空参数数组 */ memset(message->data.paramModify.params, 0, array_size * sizeof(tcp_param_item_t)); /* 解析每个参数项 */ for (int i = 0; i < array_size; i++) { cJSON *param_item = cJSON_GetArrayItem(params_array, i); if (param_item != NULL && cJSON_IsObject(param_item)) { /* 解析参数名称 */ cJSON *name_item = cJSON_GetObjectItem(param_item, "name"); if (name_item != NULL && cJSON_IsString(name_item)) { strncpy(message->data.paramModify.params[i].name, name_item->valuestring, sizeof(message->data.paramModify.params[i].name) - 1); } /* 解析参数值 */ cJSON *value_item = cJSON_GetObjectItem(param_item, "value"); if (value_item != NULL && cJSON_IsString(value_item)) { strncpy(message->data.paramModify.params[i].value, value_item->valuestring, sizeof(message->data.paramModify.params[i].value) - 1); } } } } else { message->data.paramModify.count = 0; message->data.paramModify.params = NULL; } } else { message->data.paramModify.count = 0; message->data.paramModify.params = NULL; } } else if (strcmp(message->command, CMD_FIRMWARE_UPGRADE) == 0) { /* 解析固件升级数据 */ item = cJSON_GetObjectItem(data, "subCommand"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->data.firmwareUpgrade.subCommand, item->valuestring, sizeof(message->data.firmwareUpgrade.subCommand) - 1); } else { cJSON_Delete(root); return -1; } /* 根据子命令解析不同的字段 */ if (strcmp(message->data.firmwareUpgrade.subCommand, FIRMWARE_SUBCMD_START) == 0) { /* 解析Start子命令 */ item = cJSON_GetObjectItem(data, "fileSize"); if (item != NULL && cJSON_IsNumber(item)) { message->data.firmwareUpgrade.u.start.fileSize = (uint32_t)item->valueint; } item = cJSON_GetObjectItem(data, "totalPackets"); if (item != NULL && cJSON_IsNumber(item)) { message->data.firmwareUpgrade.u.start.totalPackets = (uint32_t)item->valueint; } item = cJSON_GetObjectItem(data, "packetSize"); if (item != NULL && cJSON_IsNumber(item)) { message->data.firmwareUpgrade.u.start.packetSize = (uint32_t)item->valueint; } item = cJSON_GetObjectItem(data, "firmwareVersion"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->data.firmwareUpgrade.u.start.firmwareVersion, item->valuestring, sizeof(message->data.firmwareUpgrade.u.start.firmwareVersion) - 1); } } else if (strcmp(message->data.firmwareUpgrade.subCommand, FIRMWARE_SUBCMD_DATA) == 0) { /* 解析Data子命令 */ item = cJSON_GetObjectItem(data, "packetIndex"); if (item != NULL && cJSON_IsNumber(item)) { message->data.firmwareUpgrade.u.data.packetIndex = (uint32_t)item->valueint; } else { /* 如果packetIndex字段不存在或不是数字,使用默认值0 */ message->data.firmwareUpgrade.u.data.packetIndex = 0; } item = cJSON_GetObjectItem(data, "totalPackets"); if (item != NULL && cJSON_IsNumber(item)) { message->data.firmwareUpgrade.u.data.totalPackets = (uint32_t)item->valueint; } item = cJSON_GetObjectItem(data, "data"); if (item != NULL && cJSON_IsString(item)) { /* 动态分配内存存储数据 */ const char *data_str = item->valuestring; size_t data_len = strlen(data_str); message->data.firmwareUpgrade.u.data.data = (char *)pvPortMalloc(data_len + 1); if (message->data.firmwareUpgrade.u.data.data != NULL) { strncpy(message->data.firmwareUpgrade.u.data.data, data_str, data_len); message->data.firmwareUpgrade.u.data.data[data_len] = '\0'; message->data.firmwareUpgrade.u.data.data_len = data_len; } else { TCP_PRINT("Failed to allocate memory for firmware data\r\n"); cJSON_Delete(root); return -1; } } else { message->data.firmwareUpgrade.u.data.data = NULL; message->data.firmwareUpgrade.u.data.data_len = 0; } item = cJSON_GetObjectItem(data, "crc"); if (item != NULL && cJSON_IsNumber(item)) { message->data.firmwareUpgrade.u.data.crc = (uint32_t)item->valueint; } } else if (strcmp(message->data.firmwareUpgrade.subCommand, FIRMWARE_SUBCMD_END) == 0) { /* 解析End子命令 */ item = cJSON_GetObjectItem(data, "status"); if (item != NULL && cJSON_IsNumber(item)) { message->data.firmwareUpgrade.u.end.status = (uint8_t)item->valueint; } item = cJSON_GetObjectItem(data, "errorMessage"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->data.firmwareUpgrade.u.end.errorMessage, item->valuestring, sizeof(message->data.firmwareUpgrade.u.end.errorMessage) - 1); } } else if (strcmp(message->data.firmwareUpgrade.subCommand, FIRMWARE_SUBCMD_RESPONSE) == 0) { /* 解析Response子命令 */ item = cJSON_GetObjectItem(data, "response"); if (item != NULL && cJSON_IsNumber(item)) { message->data.firmwareUpgrade.u.response.response = (uint8_t)item->valueint; } item = cJSON_GetObjectItem(data, "packetIndex"); if (item != NULL && cJSON_IsNumber(item)) { message->data.firmwareUpgrade.u.response.packetIndex = (uint32_t)item->valueint; } item = cJSON_GetObjectItem(data, "message"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->data.firmwareUpgrade.u.response.message, item->valuestring, sizeof(message->data.firmwareUpgrade.u.response.message) - 1); } } else { /* 未知子命令 */ cJSON_Delete(root); return -1; } } else if (strcmp(message->command, CMD_FILE_OPERATIONS) == 0) { /* 解析文件操作数据 */ item = cJSON_GetObjectItem(data, "subCommand"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->data.fileOperation.subCommand, item->valuestring, sizeof(message->data.fileOperation.subCommand) - 1); } else { cJSON_Delete(root); return -1; } /* 根据子命令解析不同的字段 */ if (strcmp(message->data.fileOperation.subCommand, FILE_OP_SUBCMD_QUERY) == 0) { /* 解析查询子命令 - 支持两种格式: 1. 直接格式:data中包含path字段 2. 嵌套格式:data中包含request对象,request对象中包含path和recursive字段 */ cJSON *request_obj = cJSON_GetObjectItem(data, "request"); if (request_obj != NULL && cJSON_IsObject(request_obj)) { /* 嵌套格式:从request对象中获取path */ item = cJSON_GetObjectItem(request_obj, "path"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->data.fileOperation.request.query.path, item->valuestring, sizeof(message->data.fileOperation.request.query.path) - 1); } /* 解析recursive字段(可选) */ item = cJSON_GetObjectItem(request_obj, "recursive"); if (item != NULL && cJSON_IsNumber(item)) { message->data.fileOperation.request.query.recursive = (uint8_t)item->valueint; } } else { /* 直接格式:从data对象中直接获取path */ item = cJSON_GetObjectItem(data, "path"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->data.fileOperation.request.query.path, item->valuestring, sizeof(message->data.fileOperation.request.query.path) - 1); } } } else if (strcmp(message->data.fileOperation.subCommand, FILE_OP_SUBCMD_DELETE) == 0) { /* 解析删除子命令 - 支持两种格式: 1. 直接格式:data中包含path字段(完整路径) 2. 新格式:data中包含fileName和path字段,需要组合成完整路径 */ cJSON *fileName_item = cJSON_GetObjectItem(data, "fileName"); cJSON *path_item = cJSON_GetObjectItem(data, "path"); if (fileName_item != NULL && cJSON_IsString(fileName_item) && path_item != NULL && cJSON_IsString(path_item)) { /* 新格式:组合路径和文件名 */ char full_path[256]; const char *path_str = path_item->valuestring; const char *file_name = fileName_item->valuestring; /* 构建完整路径:path + "/" + fileName */ if (path_str[0] == '\0') { /* 如果路径为空,直接使用文件名 */ snprintf(full_path, sizeof(full_path), "/%s", file_name); } else if (path_str[strlen(path_str) - 1] == '/') { /* 如果路径以斜杠结尾,直接拼接 */ snprintf(full_path, sizeof(full_path), "%s%s", path_str, file_name); } else { /* 否则添加斜杠分隔符 */ snprintf(full_path, sizeof(full_path), "%s/%s", path_str, file_name); } strncpy(message->data.fileOperation.request.delete.path, full_path, sizeof(message->data.fileOperation.request.delete.path) - 1); message->data.fileOperation.request.delete.path[sizeof(message->data.fileOperation.request.delete.path) - 1] = '\0'; TCP_PRINT("Delete request with fileName and path: path=%s, fileName=%s, fullPath=%s\r\n", path_str, file_name, message->data.fileOperation.request.delete.path); } else if (path_item != NULL && cJSON_IsString(path_item)) { /* 直接格式:使用完整的path字段 */ strncpy(message->data.fileOperation.request.delete.path, path_item->valuestring, sizeof(message->data.fileOperation.request.delete.path) - 1); message->data.fileOperation.request.delete.path[sizeof(message->data.fileOperation.request.delete.path) - 1] = '\0'; TCP_PRINT("Delete request with full path: %s\r\n", message->data.fileOperation.request.delete.path); } else { /* 两种格式都不满足,返回错误 */ TCP_PRINT("Delete request missing required fields (need either path or both fileName and path)\r\n"); cJSON_Delete(root); return -1; } /* 解析force字段(可选) */ item = cJSON_GetObjectItem(data, "force"); if (item != NULL && cJSON_IsNumber(item)) { message->data.fileOperation.request.delete.force = (uint8_t)item->valueint; } else { message->data.fileOperation.request.delete.force = 0; /* 默认不强制删除 */ } } else if (strcmp(message->data.fileOperation.subCommand, FILE_OP_SUBCMD_DOWNLOAD) == 0) { /* 解析下载子命令 - 支持两种格式: 1. 直接格式:data中包含path字段(完整路径) 2. 新格式:data中包含fileName和path字段,需要组合成完整路径 */ cJSON *fileName_item = cJSON_GetObjectItem(data, "fileName"); cJSON *path_item = cJSON_GetObjectItem(data, "path"); if (fileName_item != NULL && cJSON_IsString(fileName_item) && path_item != NULL && cJSON_IsString(path_item)) { /* 新格式:组合路径和文件名 */ char full_path[64]; const char *path_str = path_item->valuestring; const char *file_name = fileName_item->valuestring; /* 构建完整路径:path + "/" + fileName */ if (path_str[0] == '\0') { /* 如果路径为空,直接使用文件名 */ snprintf(full_path, sizeof(full_path), "/%s", file_name); } else if (path_str[strlen(path_str) - 1] == '/') { /* 如果路径以斜杠结尾,直接拼接 */ snprintf(full_path, sizeof(full_path), "%s%s", path_str, file_name); } else { /* 否则添加斜杠分隔符 */ snprintf(full_path, sizeof(full_path), "%s/%s", path_str, file_name); } strncpy(message->data.fileOperation.request.download.path, full_path, sizeof(message->data.fileOperation.request.download.path) - 1); message->data.fileOperation.request.download.path[sizeof(message->data.fileOperation.request.download.path) - 1] = '\0'; TCP_PRINT("Download request with fileName and path: path=%s, fileName=%s, fullPath=%s\r\n", path_str, file_name, message->data.fileOperation.request.download.path); } else if (path_item != NULL && cJSON_IsString(path_item)) { /* 直接格式:使用完整的path字段 */ strncpy(message->data.fileOperation.request.download.path, path_item->valuestring, sizeof(message->data.fileOperation.request.download.path) - 1); message->data.fileOperation.request.download.path[sizeof(message->data.fileOperation.request.download.path) - 1] = '\0'; TCP_PRINT("Download request with full path: %s\r\n", message->data.fileOperation.request.download.path); } else { /* 两种格式都不满足,返回错误 */ TCP_PRINT("Download request missing required fields (need either path or both fileName and path)\r\n"); cJSON_Delete(root); return -1; } item = cJSON_GetObjectItem(data, "offset"); if (item != NULL && cJSON_IsNumber(item)) { message->data.fileOperation.request.download.offset = (uint32_t)item->valueint; } item = cJSON_GetObjectItem(data, "chunkSize"); if (item != NULL && cJSON_IsNumber(item)) { message->data.fileOperation.request.download.chunk_size = (uint32_t)item->valueint; } } else if (strcmp(message->data.fileOperation.subCommand, FILE_OP_SUBCMD_UPLOAD) == 0) { /* 解析上传子命令 */ item = cJSON_GetObjectItem(data, "path"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->data.fileOperation.request.upload.path, item->valuestring, sizeof(message->data.fileOperation.request.upload.path) - 1); } item = cJSON_GetObjectItem(data, "data"); if (item != NULL && cJSON_IsString(item)) { /* 注意:data字段是uint8_t*,但我们需要将其作为char*处理 */ strncpy((char *)message->data.fileOperation.request.upload.data, item->valuestring, sizeof(message->data.fileOperation.request.upload.data) - 1); } item = cJSON_GetObjectItem(data, "offset"); if (item != NULL && cJSON_IsNumber(item)) { message->data.fileOperation.request.upload.offset = (uint32_t)item->valueint; } item = cJSON_GetObjectItem(data, "fileSize"); if (item != NULL && cJSON_IsNumber(item)) { message->data.fileOperation.request.upload.file_size = (uint32_t)item->valueint; } } else { /* 未知子命令 */ cJSON_Delete(root); return -1; } } else if (strcmp(message->command, CMD_HISTORY_OPERATIONS) == 0) { /* 解析历史记录查询/清除请求 */ item = cJSON_GetObjectItem(data, "subCommand"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->data.historyOperations.subCommand, item->valuestring, sizeof(message->data.historyOperations.subCommand) - 1); } else { cJSON_Delete(root); return -1; } item = cJSON_GetObjectItem(data, "historyType"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->data.historyOperations.historyType, item->valuestring, sizeof(message->data.historyOperations.historyType) - 1); } else { message->data.historyOperations.historyType[0] = '\0'; } item = cJSON_GetObjectItem(data, "queryId"); if (item != NULL && cJSON_IsNumber(item)) { message->data.historyOperations.queryId = (uint32_t)item->valueint; } else { message->data.historyOperations.queryId = 0; } item = cJSON_GetObjectItem(data, "startIndex"); if (item != NULL && cJSON_IsNumber(item)) { message->data.historyOperations.startIndex = (uint16_t)item->valueint; } else { message->data.historyOperations.startIndex = 0; } item = cJSON_GetObjectItem(data, "fetchCount"); if (item != NULL && cJSON_IsNumber(item)) { message->data.historyOperations.fetchCount = (uint16_t)item->valueint; } else { message->data.historyOperations.fetchCount = 0; } } else if (strcmp(message->command, CMD_FAULT_INFO) == 0) { /* 解析故障信息请求 */ item = cJSON_GetObjectItem(data, "faultCode"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->data.faultInfo.faultCode, item->valuestring, sizeof(message->data.faultInfo.faultCode) - 1); } else { /* 故障代码是可选的,如果为空表示查询所有故障 */ message->data.faultInfo.faultCode[0] = '\0'; } } else if (strcmp(message->command, CMD_CUSTOM_DATA) == 0) { /* 解析自定义数据请求 */ item = cJSON_GetObjectItem(data, "functionContent"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->data.customData.functionContent, item->valuestring, sizeof(message->data.customData.functionContent) - 1); } else { /* 如果字段不存在,设置为空字符串 */ message->data.customData.functionContent[0] = '\0'; } item = cJSON_GetObjectItem(data, "functionField"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->data.customData.functionField, item->valuestring, sizeof(message->data.customData.functionField) - 1); } else { /* 如果字段不存在,设置为空字符串 */ message->data.customData.functionField[0] = '\0'; } item = cJSON_GetObjectItem(data, "functionParams"); if (item != NULL && cJSON_IsString(item)) { strncpy(message->data.customData.functionParams, item->valuestring, sizeof(message->data.customData.functionParams) - 1); } else { /* 如果字段不存在,设置为空字符串 */ message->data.customData.functionParams[0] = '\0'; } } else { /* 未知命令 */ cJSON_Delete(root); return -1; } cJSON_Delete(root); return 0; } /** * @brief 解析时间字符串到Comm_Time结构体 * @param time_str 时间字符串,格式为"YYYY-MM-DD HH:MM:SS.xxx" * @param time 输出时间结构体 * @retval 0成功,-1失败 */ static int tcp_parse_timestamp_string(const char *time_str, Comm_Time *time) { int year, month, day, hour, minute, second, millisecond; if (time_str == NULL || time == NULL) { return -1; } /* 解析时间字符串格式:YYYY-MM-DD HH:MM:SS.xxx */ if (sscanf(time_str, "%d-%d-%d %d:%d:%d.%d", &year, &month, &day, &hour, &minute, &second, &millisecond) != 7) { /* 尝试不带毫秒的格式 */ if (sscanf(time_str, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second) != 6) { return -1; } millisecond = 0; } /* 验证时间范围 */ if (year < 2000 || year > 2100 || month < 1 || month > 12 || day < 1 || day > 31 || hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59) { return -1; } /* 填充时间结构体 */ time->iYear = (U16_T)year; time->ucMonth = (U8_T)month; time->ucDay = (U8_T)day; time->ucHour = (U8_T)hour; time->ucMin = (U8_T)minute; time->ucSec = (U8_T)second; return 0; } /** * @brief 计算两个时间之间的分钟差 * @param time1 时间1 * @param time2 时间2 * @retval 分钟差(绝对值) */ static int tcp_calculate_time_diff_minutes(const Comm_Time *time1, const Comm_Time *time2) { /* 简单计算:假设每个月30天,每年365天 */ long total_minutes1 = (long)time1->iYear * 365 * 24 * 60 + (long)time1->ucMonth * 30 * 24 * 60 + (long)time1->ucDay * 24 * 60 + (long)time1->ucHour * 60 + (long)time1->ucMin; long total_minutes2 = (long)time2->iYear * 365 * 24 * 60 + (long)time2->ucMonth * 30 * 24 * 60 + (long)time2->ucDay * 24 * 60 + (long)time2->ucHour * 60 + (long)time2->ucMin; long diff = total_minutes1 - total_minutes2; if (diff < 0) { diff = -diff; } return (int)diff; } /* 子函数声明 */ static int tcp_process_heartbeat_message(const tcp_message_t *message); static int tcp_process_charge_control_message(const tcp_message_t *message); static int tcp_process_param_query_message(const tcp_message_t *message); static int tcp_process_param_modify_message(const tcp_message_t *message); static int tcp_process_firmware_upgrade_message(const tcp_message_t *message); static int tcp_process_file_operation_message(const tcp_message_t *message); static int tcp_process_fault_info_message(const tcp_message_t *message); static int tcp_process_history_operations_message(const tcp_message_t *message); static int tcp_process_custom_data_message(const tcp_message_t *message); static int tcp_generate_fault_info_json(const tcp_fault_info_response_t *response, char *buffer, uint32_t size); /* 子函数实现 */ /** * @brief 处理心跳消息 * @param message 消息结构体指针 * @retval 0成功,-1失败 */ static int tcp_process_heartbeat_message(const tcp_message_t *message) { Comm_Time curTime; Comm_Time receivedTime; int time_diff_minutes = 0; TCP_PRINT("Received heartbeat: sequence=%u, source=%s\r\r\n", message->data.heartbeat.sequence, message->data.heartbeat.source); /* 解析消息中的时间戳并进行校时检查 */ if (message->timestamp[0] != '\0') { /* 解析接收到的消息时间戳 */ if (tcp_parse_timestamp_string(message->timestamp, &receivedTime) == 0) { /* 获取当前系统时间 */ GetCurrentTime(&curTime); /* 计算时间差(分钟) */ time_diff_minutes = tcp_calculate_time_diff_minutes(&receivedTime, &curTime); TCP_PRINT("Time check: received=%04d-%02d-%02d %02d:%02d:%02d, current=%04d-%02d-%02d %02d:%02d:%02d, diff=%d minutes\r\r\n", receivedTime.iYear, receivedTime.ucMonth, receivedTime.ucDay, receivedTime.ucHour, receivedTime.ucMin, receivedTime.ucSec, curTime.iYear, curTime.ucMonth, curTime.ucDay, curTime.ucHour, curTime.ucMin, curTime.ucSec, time_diff_minutes); /* 如果时间差大于5分钟,进行校时 */ if (time_diff_minutes > 5) { TCP_PRINT("Time difference too large (%d minutes), adjusting system time...\r\r\n", time_diff_minutes); /* 调用RTC校时函数 */ v_rtc_set_time(&receivedTime); TCP_PRINT("System time adjusted to: %04d-%02d-%02d %02d:%02d:%02d\r\r\n", receivedTime.iYear, receivedTime.ucMonth, receivedTime.ucDay, receivedTime.ucHour, receivedTime.ucMin, receivedTime.ucSec); } else { TCP_PRINT("Time difference within acceptable range (%d minutes), no adjustment needed\r\r\n", time_diff_minutes); } } else { TCP_PRINT("Failed to parse timestamp: %s\r\r\n", message->timestamp); } } return 0; } /** * @brief 处理充电控制消息 * @param message 消息结构体指针 * @retval 0成功,-1失败 */ static int tcp_process_charge_control_message(const tcp_message_t *message) { char msg[64]; TCP_PRINT("Received charge control: gun=%u, action=%u\r\r\n", message->data.chargeControl.gunNumber, message->data.chargeControl.action); /* 调用system_data模块处理充电控制 */ if (message->data.chargeControl.action == CHARGE_ACTION_STOP) { /* 停止充电 */ if (system_data_stop_charge(message->data.chargeControl.gunNumber, msg) != 0) { TCP_PRINT("Failed to stop charge: %s\r\r\n", msg); return -1; } TCP_PRINT("Charge stopped: %s\r\r\n", msg); } else if (message->data.chargeControl.action == CHARGE_ACTION_START) { /* 启动充电 */ if (system_data_start_charge(message->data.chargeControl.gunNumber, "", "", msg) != 0) { TCP_PRINT("Failed to start charge: %s\r\r\n", msg); return -1; } TCP_PRINT("Charge started: %s\r\r\n", msg); } else { TCP_PRINT("Unknown charge action: %u\r\r\n", message->data.chargeControl.action); return -1; } return 0; } /** * @brief 处理参数查询消息 * @param message 消息结构体指针 * @retval 0成功,-1失败 */ static int tcp_process_param_query_message(const tcp_message_t *message) { tcp_param_query_response_t response; char *response_json = NULL; int json_len = 0; int result = 0; /* 参数查询:按固定大小缓冲 + 分包发送 */ #define TCP_PARAM_QUERY_JSON_BUF_SIZE (2048) #define TCP_PARAM_QUERY_MAX_PARAMS_PER_PACKET (20) TCP_PRINT("Received param query: type=%s\r\r\n", message->data.paramQuery.type); /* 处理参数查询请求 */ memset(&response, 0, sizeof(response)); if (tcp_process_param_query(&message->data.paramQuery, &response) != 0) { TCP_PRINT("Failed to process param query\r\r\n"); return -1; } /* 动态分配响应JSON缓冲区(固定 2048) */ response_json = (char *)pvPortMalloc(TCP_PARAM_QUERY_JSON_BUF_SIZE); if (response_json == NULL) { TCP_PRINT("Failed to allocate memory for response JSON\r\r\n"); result = -1; goto cleanup; } /* 按“每包最多 20 个参数”分包应答 */ { uint16_t total = response.count; uint16_t offset = 0; uint16_t pkt_index = 0; uint16_t total_pkts = (total + TCP_PARAM_QUERY_MAX_PARAMS_PER_PACKET - 1) / TCP_PARAM_QUERY_MAX_PARAMS_PER_PACKET; while (offset < total) { uint16_t chunk = total - offset; if (chunk > TCP_PARAM_QUERY_MAX_PARAMS_PER_PACKET) { chunk = TCP_PARAM_QUERY_MAX_PARAMS_PER_PACKET; } tcp_param_query_response_t chunk_resp; memset(&chunk_resp, 0, sizeof(chunk_resp)); strncpy(chunk_resp.type, response.type, sizeof(chunk_resp.type) - 1); chunk_resp.count = chunk; chunk_resp.params = &response.params[offset]; json_len = tcp_generate_param_query_response(&chunk_resp, response_json, TCP_PARAM_QUERY_JSON_BUF_SIZE); if (json_len > 0) { err_t send_err = tcp_server_send_json(response_json, (uint16_t)json_len); if (send_err == ERR_OK) { TCP_PRINT("Param query response sent pkt %u/%u, params %u~%u, json %d bytes\r\r\n", (unsigned)(pkt_index + 1), (unsigned)total_pkts, (unsigned)offset, (unsigned)(offset + chunk - 1), json_len); } else { TCP_PRINT("Failed to send param query response pkt %u/%u: %d\r\r\n", (unsigned)(pkt_index + 1), (unsigned)total_pkts, send_err); result = -1; break; } } else { TCP_PRINT("Failed to generate param query response pkt %u/%u (offset=%u, chunk=%u)\r\r\n", (unsigned)(pkt_index + 1), (unsigned)total_pkts, (unsigned)offset, (unsigned)chunk); result = -1; break; } offset = (uint16_t)(offset + chunk); pkt_index++; } } cleanup: /* 释放动态分配的内存 */ if (response.params != NULL) { vPortFree(response.params); } if (response_json != NULL) { vPortFree(response_json); } return result; } /** * @brief 处理参数修改消息 * @param message 消息结构体指针 * @retval 0成功,-1失败 */ static int tcp_process_param_modify_message(const tcp_message_t *message) { tcp_param_modify_response_t response; char *response_json = NULL; int json_len = 0; int result = 0; TCP_PRINT("Received param modify: type=%s, count=%u\r\r\n", message->data.paramModify.type, message->data.paramModify.count); /* 处理参数修改请求 */ memset(&response, 0, sizeof(response)); if (tcp_process_param_modify(&message->data.paramModify, &response) != 0) { TCP_PRINT("Failed to process param modify\r\r\n"); return -1; } /* 动态分配响应JSON缓冲区 */ response_json = (char *)pvPortMalloc(2048); if (response_json == NULL) { TCP_PRINT("Failed to allocate memory for response JSON\r\r\n"); result = -1; goto cleanup; } /* 生成响应JSON */ json_len = tcp_generate_param_modify_response(&response, response_json, 2048); if (json_len > 0) { TCP_PRINT("Param modify response generated (%d bytes)\r\r\n", json_len); /* 发送响应到客户端 */ err_t send_err = tcp_server_send_json(response_json, json_len); if (send_err == ERR_OK) { TCP_PRINT("Param modify response sent successfully\r\r\n"); } else { TCP_PRINT("Failed to send param modify response: %d\r\r\n", send_err); result = -1; } } else { TCP_PRINT("Failed to generate param modify response\r\r\n"); result = -1; } cleanup: /* 注意:message->data.paramModify.params 的内存由 tcp_free_message 函数释放 这里不释放,因为 message 是 const 指针,不能修改 */ if (response_json != NULL) { vPortFree(response_json); response_json = NULL; } return result; } /** * @brief 处理固件升级消息 * @param message 消息结构体指针 * @retval 0成功,-1失败 */ static int tcp_process_firmware_upgrade_message(const tcp_message_t *message) { TCP_PRINT("Received firmware upgrade: subCommand=%s\r\r\n", message->data.firmwareUpgrade.subCommand); /* 处理固件升级请求 */ if (tcp_process_firmware_upgrade(&message->data.firmwareUpgrade) != 0) { TCP_PRINT("Failed to process firmware upgrade\r\r\n"); return -1; } return 0; } /** * @brief 处理文件操作消息 * @param message 消息结构体指针 * @retval 0成功,-1失败 */ static int tcp_process_file_operation_message(const tcp_message_t *message) { TCP_PRINT("Received file operation: subCommand=%s\r\r\n", message->data.fileOperation.subCommand); /* 处理文件操作请求 */ if (tcp_process_file_operation(&message->data.fileOperation) != 0) { TCP_PRINT("Failed to process file operation\r\r\n"); return -1; } return 0; } /** * @brief 处理接收到的消息 * @param message 消息结构体指针 * @retval 0成功,-1失败 */ int tcp_process_received_message(const tcp_message_t *message) { if (message == NULL) { return -1; } /* 根据命令类型调用相应的处理函数 */ if (strcmp(message->command, CMD_HEARTBEAT) == 0) { return tcp_process_heartbeat_message(message); } else if (strcmp(message->command, CMD_CHARGE_CONTROL) == 0) { return tcp_process_charge_control_message(message); } else if (strcmp(message->command, CMD_PARAM_QUERY) == 0) { return tcp_process_param_query_message(message); } else if (strcmp(message->command, CMD_PARAM_MODIFY) == 0) { return tcp_process_param_modify_message(message); } else if (strcmp(message->command, CMD_FIRMWARE_UPGRADE) == 0) { return tcp_process_firmware_upgrade_message(message); } else if (strcmp(message->command, CMD_FILE_OPERATIONS) == 0) { return tcp_process_file_operation_message(message); } else if (strcmp(message->command, CMD_FAULT_INFO) == 0) { return tcp_process_fault_info_message(message); } else if (strcmp(message->command, CMD_HISTORY_OPERATIONS) == 0) { return tcp_process_history_operations_message(message); } else if (strcmp(message->command, CMD_CUSTOM_DATA) == 0) { return tcp_process_custom_data_message(message); } else { TCP_PRINT("Received unknown command: %s\r\r\n", message->command); return -1; } } /** * @brief 填充参数项(辅助函数) * @param item 参数项指针 * @param name 参数名称 * @param type 参数类型 * @param value 参数值(字符串格式) * @retval 无 */ static void tcp_fill_param_item(tcp_param_item_t *item, const char *name, const char *type, const char *value) { if (item == NULL || name == NULL || type == NULL || value == NULL) { return; } strncpy(item->name, name, sizeof(item->name) - 1); strncpy(item->type, type, sizeof(item->type) - 1); strncpy(item->value, value, sizeof(item->value) - 1); } /** * @brief 处理参数查询请求(使用参数映射表) * @param request 参数查询请求 * @param response 参数查询响应 * @retval 0成功,-1失败 */ int tcp_process_param_query(const tcp_param_query_request_t *request, tcp_param_query_response_t *response) { const param_map_item_t *param_map = NULL; uint16_t param_count = 0; uint16_t i; char value_buffer[128]; if (request == NULL || response == NULL) { return -1; } /* 复制参数类型 */ strncpy(response->type, request->type, sizeof(response->type) - 1); /* 根据参数类型获取对应的映射表 */ if (strcmp(request->type, PARAM_TYPE_BASIC) == 0) { param_map = param_get_basic_map(); param_count = param_get_basic_map_size(); } else if (strcmp(request->type, PARAM_TYPE_NETWORK) == 0) { param_map = param_get_network_map(); param_count = param_get_network_map_size(); } else if (strcmp(request->type, PARAM_TYPE_METER) == 0) { param_map = param_get_meter_map(); param_count = param_get_meter_map_size(); } else if (strcmp(request->type, PARAM_TYPE_ENABLE) == 0) { param_map = param_get_enable_map(); param_count = param_get_enable_map_size(); } else if (strcmp(request->type, PARAM_TYPE_FEE) == 0) { param_map = param_get_fee_map(); param_count = param_get_fee_map_size(); } else if (strcmp(request->type, PARAM_TYPE_SDK) == 0) { param_map = param_get_sdk_map(); param_count = param_get_sdk_map_size(); } else if (strcmp(request->type, PARAM_TYPE_QRCODE) == 0) { param_map = param_get_qrcode_map(); param_count = param_get_qrcode_map_size(); } else { /* 其他参数类型暂不支持 */ response->count = 0; response->params = NULL; TCP_PRINT("Unsupported param type: %s\r\r\n", request->type); return -1; } if (param_map == NULL || param_count == 0) { response->count = 0; response->params = NULL; TCP_PRINT("No parameter map found for type: %s\r\r\n", request->type); return -1; } /* 分配参数数组内存 */ response->count = param_count; response->params = (tcp_param_item_t *)pvPortMalloc(response->count * sizeof(tcp_param_item_t)); if (response->params == NULL) { response->count = 0; return -1; } /* 填充基本参数 */ memset(response->params, 0, response->count * sizeof(tcp_param_item_t)); /* 使用参数映射表填充参数 */ for (i = 0; i < param_count; i++) { const param_map_item_t *map_item = ¶m_map[i]; /* 获取参数值字符串 */ if (param_get_value_as_string(map_item, value_buffer, sizeof(value_buffer)) != 0) { snprintf(value_buffer, sizeof(value_buffer), "error"); } /* 填充参数项 */ strncpy(response->params[i].name, map_item->param_name, sizeof(response->params[i].name) - 1); strncpy(response->params[i].type, param_type_to_string(map_item->data_type), sizeof(response->params[i].type) - 1); strncpy(response->params[i].value, value_buffer, sizeof(response->params[i].value) - 1); /* 填充描述字段(如果存在) */ if (map_item->decs != NULL) { strncpy(response->params[i].decs, map_item->decs, sizeof(response->params[i].decs) - 1); } else { response->params[i].decs[0] = '\0'; /* 设置为空字符串 */ } } return 0; } /** * @brief 生成参数查询响应JSON * @param response 参数查询响应 * @param buffer 输出缓冲区 * @param size 缓冲区大小 * @retval JSON字符串长度,-1表示失败 */ int tcp_generate_param_query_response(const tcp_param_query_response_t *response, char *buffer, uint32_t size) { cJSON *root = NULL; cJSON *data = NULL; cJSON *params_array = NULL; cJSON *param_item = NULL; char timestamp[32]; char *json_str = NULL; int json_len = 0; int i; if (buffer == NULL || size == 0 || response == NULL) { return -1; } /* 生成时间戳 */ if (tcp_generate_timestamp(timestamp, sizeof(timestamp)) != 0) { return -1; } /* 创建JSON对象 */ root = cJSON_CreateObject(); if (root == NULL) { return -1; } cJSON_AddStringToObject(root, "version", "2.0"); cJSON_AddStringToObject(root, "timestamp", timestamp); cJSON_AddStringToObject(root, "command", CMD_PARAM_QUERY); /* 创建data对象 */ data = cJSON_CreateObject(); if (data == NULL) { cJSON_Delete(root); return -1; } cJSON_AddStringToObject(data, "type", response->type); cJSON_AddNumberToObject(data, "count", response->count); /* 创建参数数组 */ params_array = cJSON_CreateArray(); if (params_array == NULL) { cJSON_Delete(data); cJSON_Delete(root); return -1; } /* 添加参数项到数组 */ for (i = 0; i < response->count; i++) { param_item = cJSON_CreateObject(); if (param_item == NULL) { cJSON_Delete(params_array); cJSON_Delete(data); cJSON_Delete(root); return -1; } cJSON_AddStringToObject(param_item, "name", response->params[i].name); cJSON_AddStringToObject(param_item, "type", response->params[i].type); cJSON_AddStringToObject(param_item, "value", response->params[i].value); cJSON_AddStringToObject(param_item, "decs", response->params[i].decs); cJSON_AddItemToArray(params_array, param_item); } cJSON_AddItemToObject(data, "params", params_array); cJSON_AddItemToObject(root, "data", data); /* 生成JSON字符串 */ json_str = cJSON_PrintUnformatted(root); if (json_str == NULL) { cJSON_Delete(root); return -1; } json_len = strlen(json_str); if (json_len + 1 > size) { cJSON_free(json_str); cJSON_Delete(root); return -1; } /* 复制到输出缓冲区 */ strncpy(buffer, json_str, size); buffer[size - 1] = '\0'; /* 释放内存 */ cJSON_free(json_str); cJSON_Delete(root); return json_len; } /** * @brief 处理参数修改请求 * @param request 参数修改请求 * @param response 参数修改响应 * @retval 0成功,-1失败 */ int tcp_process_param_modify(const tcp_param_modify_request_t *request, tcp_param_modify_response_t *response) { const param_map_item_t *param_map = NULL; uint16_t param_count = 0; uint16_t i; if (request == NULL || response == NULL) { return -1; } /* 初始化响应 */ memset(response, 0, sizeof(tcp_param_modify_response_t)); strncpy(response->type, request->type, sizeof(response->type) - 1); response->received = request->count; /* 根据参数类型获取对应的映射表 */ if (strcmp(request->type, PARAM_TYPE_BASIC) == 0) { param_map = param_get_basic_map(); param_count = param_get_basic_map_size(); } else if (strcmp(request->type, PARAM_TYPE_NETWORK) == 0) { param_map = param_get_network_map(); param_count = param_get_network_map_size(); } else if (strcmp(request->type, PARAM_TYPE_METER) == 0) { param_map = param_get_meter_map(); param_count = param_get_meter_map_size(); } else if (strcmp(request->type, PARAM_TYPE_ENABLE) == 0) { param_map = param_get_enable_map(); param_count = param_get_enable_map_size(); } else if (strcmp(request->type, PARAM_TYPE_FEE) == 0) { param_map = param_get_fee_map(); param_count = param_get_fee_map_size(); } else if (strcmp(request->type, PARAM_TYPE_SDK) == 0) { param_map = param_get_sdk_map(); param_count = param_get_sdk_map_size(); } else if (strcmp(request->type, PARAM_TYPE_QRCODE) == 0) { param_map = param_get_qrcode_map(); param_count = param_get_qrcode_map_size(); } else { /* 其他参数类型暂不支持 */ TCP_PRINT("Unsupported param type for modify: %s\r\r\n", request->type); return -1; } if (param_map == NULL || param_count == 0) { TCP_PRINT("No parameter map found for type: %s\r\r\n", request->type); return -1; } /* 处理每个参数 */ for (i = 0; i < request->count; i++) { const tcp_param_item_t *req_item = &request->params[i]; const param_map_item_t *map_item = NULL; uint16_t j; /* 在映射表中查找参数 */ for (j = 0; j < param_count; j++) { if (strcmp(param_map[j].param_name, req_item->name) == 0) { map_item = ¶m_map[j]; break; } } if (map_item == NULL) { /* 未找到参数 */ TCP_PRINT("Parameter not found: %s\r\r\n", req_item->name); response->failed++; continue; } /* 尝试设置参数值 */ if (param_set_value_from_string(map_item, req_item->value) == 0) { TCP_PRINT("Parameter set successfully: %s = %s\r\r\n", req_item->name, req_item->value); response->success++; } else { TCP_PRINT("Failed to set parameter: %s = %s\r\r\n", req_item->name, req_item->value); response->failed++; } response->processed++; } v_flash_save_cfg_data(); return 0; } /** * @brief 生成参数修改响应JSON * @param response 参数修改响应 * @param buffer 输出缓冲区 * @param size 缓冲区大小 * @retval JSON字符串长度,-1表示失败 */ int tcp_generate_param_modify_response(const tcp_param_modify_response_t *response, char *buffer, uint32_t size) { cJSON *root = NULL; cJSON *data = NULL; char timestamp[32]; char *json_str = NULL; int json_len = 0; if (buffer == NULL || size == 0 || response == NULL) { return -1; } /* 生成时间戳 */ if (tcp_generate_timestamp(timestamp, sizeof(timestamp)) != 0) { return -1; } /* 创建JSON对象 */ root = cJSON_CreateObject(); if (root == NULL) { return -1; } cJSON_AddStringToObject(root, "version", "2.0"); cJSON_AddStringToObject(root, "timestamp", timestamp); cJSON_AddStringToObject(root, "command", CMD_PARAM_MODIFY); /* 创建data对象 */ data = cJSON_CreateObject(); if (data == NULL) { cJSON_Delete(root); return -1; } cJSON_AddStringToObject(data, "type", response->type); cJSON_AddNumberToObject(data, "received", response->received); cJSON_AddNumberToObject(data, "processed", response->processed); cJSON_AddNumberToObject(data, "success", response->success); cJSON_AddNumberToObject(data, "failed", response->failed); cJSON_AddItemToObject(root, "data", data); /* 生成JSON字符串 */ json_str = cJSON_PrintUnformatted(root); if (json_str == NULL) { cJSON_Delete(root); return -1; } json_len = strlen(json_str); if (json_len + 1 > size) { cJSON_free(json_str); cJSON_Delete(root); return -1; } /* 复制到输出缓冲区 */ strncpy(buffer, json_str, size); buffer[size - 1] = '\0'; /* 释放内存 */ cJSON_free(json_str); cJSON_Delete(root); return json_len; } /** * @brief 生成固件升级消息JSON * @param firmwareUpgrade 固件升级数据结构体指针 * @param subCommand 子命令字符串 * @param buffer 输出缓冲区 * @param size 缓冲区大小 * @retval JSON字符串长度,-1表示失败 */ int tcp_generate_firmware_upgrade_json(const tcp_firmware_upgrade_data_t *firmwareUpgrade, const char *subCommand, char *buffer, uint32_t size) { cJSON *root = NULL; cJSON *data = NULL; char timestamp[32]; char *json_str = NULL; int json_len = 0; if (buffer == NULL || size == 0 || firmwareUpgrade == NULL || subCommand == NULL) { return -1; } /* 生成时间戳 */ if (tcp_generate_timestamp(timestamp, sizeof(timestamp)) != 0) { return -1; } /* 创建JSON对象 */ root = cJSON_CreateObject(); if (root == NULL) { return -1; } cJSON_AddStringToObject(root, "version", "2.0"); cJSON_AddStringToObject(root, "timestamp", timestamp); cJSON_AddStringToObject(root, "command", CMD_FIRMWARE_UPGRADE); /* 创建data对象 */ data = cJSON_CreateObject(); if (data == NULL) { cJSON_Delete(root); return -1; } cJSON_AddStringToObject(data, "subCommand", subCommand); /* 根据子命令添加不同的字段 */ if (strcmp(subCommand, FIRMWARE_SUBCMD_START) == 0) { cJSON_AddNumberToObject(data, "fileSize", firmwareUpgrade->u.start.fileSize); cJSON_AddNumberToObject(data, "totalPackets", firmwareUpgrade->u.start.totalPackets); cJSON_AddNumberToObject(data, "packetSize", firmwareUpgrade->u.start.packetSize); cJSON_AddStringToObject(data, "firmwareVersion", firmwareUpgrade->u.start.firmwareVersion); } else if (strcmp(subCommand, FIRMWARE_SUBCMD_DATA) == 0) { cJSON_AddNumberToObject(data, "packetIndex", firmwareUpgrade->u.data.packetIndex); cJSON_AddNumberToObject(data, "totalPackets", firmwareUpgrade->u.data.totalPackets); if (firmwareUpgrade->u.data.data != NULL && firmwareUpgrade->u.data.data_len > 0) { cJSON_AddStringToObject(data, "data", firmwareUpgrade->u.data.data); } else { cJSON_AddStringToObject(data, "data", ""); } cJSON_AddNumberToObject(data, "crc", firmwareUpgrade->u.data.crc); } else if (strcmp(subCommand, FIRMWARE_SUBCMD_END) == 0) { cJSON_AddNumberToObject(data, "status", firmwareUpgrade->u.end.status); cJSON_AddStringToObject(data, "errorMessage", firmwareUpgrade->u.end.errorMessage); } else if (strcmp(subCommand, FIRMWARE_SUBCMD_RESPONSE) == 0) { cJSON_AddNumberToObject(data, "response", firmwareUpgrade->u.response.response); cJSON_AddNumberToObject(data, "packetIndex", firmwareUpgrade->u.response.packetIndex); cJSON_AddStringToObject(data, "message", firmwareUpgrade->u.response.message); } else { cJSON_Delete(data); cJSON_Delete(root); return -1; } cJSON_AddItemToObject(root, "data", data); /* 生成JSON字符串 */ json_str = cJSON_PrintUnformatted(root); if (json_str == NULL) { cJSON_Delete(root); return -1; } json_len = strlen(json_str); if (json_len + 1 > size) { cJSON_free(json_str); cJSON_Delete(root); return -1; } /* 复制到输出缓冲区 */ strncpy(buffer, json_str, size); buffer[size - 1] = '\0'; /* 释放内存 */ cJSON_free(json_str); cJSON_Delete(root); return json_len; } /** 固件升级 Response:0=ACK,非0=NAK */ #define FIRMWARE_RESP_ACK 0U #define FIRMWARE_RESP_NAK 1U void tcp_firmware_upgrade_log_io(const char *dir, const char *data, uint32_t len) { uint32_t off = 0U; enum { kChunk = 480U }; if ((dir == NULL) || (data == NULL) || (len == 0U)) { return; } if (len <= kChunk) { printf("[FW_UPGRADE] %s (%u): %.*s\r\n", dir, (unsigned)len, (int)len, data); return; } printf("[FW_UPGRADE] %s (%u bytes):\r\n", dir, (unsigned)len); while (off < len) { uint32_t n = len - off; if (n > kChunk) { n = kChunk; } printf("[FW_UPGRADE] %s+%u: %.*s\r\n", dir, (unsigned)off, (int)n, data + off); off += n; } } void tcp_firmware_upgrade_log_buf(const char *dir, const uint8_t *data, uint32_t len) { uint32_t off = 0U; uint32_t i; enum { kHexShow = 48U, kChunk = 256U }; if ((dir == NULL) || (data == NULL) || (len == 0U)) { return; } printf("[FW_UPGRADE] %s (%u) HEX:", dir, (unsigned)len); for (i = 0U; i < len && i < kHexShow; i++) { printf(" %02X", (unsigned)data[i]); } if (len > kHexShow) { printf(" ..."); } printf("\r\n"); if (len <= kChunk) { printf("[FW_UPGRADE] %s TXT: %.*s\r\n", dir, (int)len, (const char *)data); return; } while (off < len) { uint32_t n = len - off; if (n > kChunk) { n = kChunk; } printf("[FW_UPGRADE] %s+%u TXT: %.*s\r\n", dir, (unsigned)off, (int)n, (const char *)(data + off)); off += n; } } void tcp_firmware_upgrade_log_meta(const char *tag, uint32_t a, uint32_t b, uint32_t c, uint32_t d) { if (tag == NULL) { return; } printf("[FW_UPGRADE] %s used=%u proc=%u cap=%u pending=%u\r\n", tag, (unsigned)a, (unsigned)b, (unsigned)c, (unsigned)d); } static int tcp_send_firmware_upgrade_response(uint8_t response_code, int packet_index, const char *message) { tcp_firmware_upgrade_data_t response_data; char response_json[512]; int json_len; err_t send_err; memset(&response_data, 0, sizeof(response_data)); strncpy(response_data.subCommand, FIRMWARE_SUBCMD_RESPONSE, sizeof(response_data.subCommand) - 1U); response_data.u.response.response = response_code; response_data.u.response.packetIndex = packet_index; if (message != NULL) { strncpy(response_data.u.response.message, message, sizeof(response_data.u.response.message) - 1U); } json_len = tcp_generate_firmware_upgrade_json(&response_data, FIRMWARE_SUBCMD_RESPONSE, response_json, sizeof(response_json)); if (json_len <= 0) { return -1; } tcp_firmware_upgrade_log_io("TX", response_json, (uint32_t)json_len); send_err = tcp_server_send_json(response_json, (uint32_t)json_len); return (send_err == ERR_OK) ? 0 : -1; } /** * @brief 处理固件升级请求 * @param firmwareUpgrade 固件升级数据结构体指针 * @retval 0成功,-1失败 */ int tcp_process_firmware_upgrade(const tcp_firmware_upgrade_data_t *firmwareUpgrade) { int ret; if (firmwareUpgrade == NULL) { return -1; } TCP_PRINT("Processing firmware upgrade: subCommand=%s\r\n", firmwareUpgrade->subCommand); if (strcmp(firmwareUpgrade->subCommand, FIRMWARE_SUBCMD_START) == 0) { TCP_PRINT("Firmware upgrade start:\r\n"); TCP_PRINT(" File size: %u bytes\r\n", firmwareUpgrade->u.start.fileSize); TCP_PRINT(" Total packets: %u\r\n", firmwareUpgrade->u.start.totalPackets); TCP_PRINT(" Packet size: %u bytes\r\n", firmwareUpgrade->u.start.packetSize); TCP_PRINT(" Firmware version: %s\r\n", firmwareUpgrade->u.start.firmwareVersion); (void)tcp_server_rx_upgrade_begin(); if (system_filetransfer_start_firmware_upgrade( firmwareUpgrade->u.start.fileSize, firmwareUpgrade->u.start.totalPackets, firmwareUpgrade->u.start.packetSize, firmwareUpgrade->u.start.firmwareVersion) != 0) { TCP_PRINT("Failed to start firmware upgrade\r\n"); tcp_server_rx_upgrade_end(); tcp_send_firmware_upgrade_response(FIRMWARE_RESP_NAK, -1, "Start rejected"); return -1; } if (system_filetransfer_commit_firmware_start() != 0) { TCP_PRINT("Failed to erase firmware area\r\n"); tcp_server_rx_upgrade_end(); tcp_send_firmware_upgrade_response(FIRMWARE_RESP_NAK, -1, "Erase failed"); return -1; } tcp_send_firmware_upgrade_response(FIRMWARE_RESP_ACK, -1, "Start accepted"); tcp_server_link_rx_drain(); } else if (strcmp(firmwareUpgrade->subCommand, FIRMWARE_SUBCMD_DATA) == 0) { int pkt = (int)firmwareUpgrade->u.data.packetIndex; TCP_PRINT("Firmware upgrade data packet:\r\n"); TCP_PRINT(" Packet index: %u/%u\r\n", firmwareUpgrade->u.data.packetIndex, firmwareUpgrade->u.data.totalPackets); TCP_PRINT(" Data length: %u bytes (Base64)\r\n", firmwareUpgrade->u.data.data_len); TCP_PRINT(" CRC: 0x%08X\r\n", firmwareUpgrade->u.data.crc); if (system_filetransfer_receive_firmware_packet( firmwareUpgrade->u.data.packetIndex, (const uint8_t *)firmwareUpgrade->u.data.data, firmwareUpgrade->u.data.data_len, firmwareUpgrade->u.data.crc) != 0) { TCP_PRINT("Failed to receive firmware packet\r\n"); tcp_send_firmware_upgrade_response(FIRMWARE_RESP_NAK, pkt, "Packet rejected"); return -1; } tcp_send_firmware_upgrade_response(FIRMWARE_RESP_ACK, pkt, "Packet received"); } else if (strcmp(firmwareUpgrade->subCommand, FIRMWARE_SUBCMD_END) == 0) { firmware_upgrade_context_t fw_ctx; TCP_PRINT("Firmware upgrade end:\r\n"); TCP_PRINT(" Status: %u\r\n", firmwareUpgrade->u.end.status); TCP_PRINT(" Error message: %s\r\n", firmwareUpgrade->u.end.errorMessage); memset(&fw_ctx, 0, sizeof(fw_ctx)); if (system_filetransfer_get_firmware_status(&fw_ctx) != 0 || fw_ctx.state == FILE_TRANSFER_IDLE) { TCP_PRINT("No active firmware upgrade session\r\n"); tcp_send_firmware_upgrade_response(FIRMWARE_RESP_NAK, 0, "No upgrade session"); return -1; } if ((firmwareUpgrade->u.end.status == FIRMWARE_STATUS_SUCCESS || firmwareUpgrade->u.end.status == FIRMWARE_STATUS_COMPLETED) && fw_ctx.received_packets == fw_ctx.total_packets && fw_ctx.received_bytes >= fw_ctx.file_size) { tcp_send_firmware_upgrade_response(FIRMWARE_RESP_ACK, 0, "Upgrade completed"); tcp_server_link_rx_drain(); vTaskDelay(pdMS_TO_TICKS(200)); (void)system_filetransfer_end_firmware_upgrade( firmwareUpgrade->u.end.status, firmwareUpgrade->u.end.errorMessage); return 0; } ret = system_filetransfer_end_firmware_upgrade( firmwareUpgrade->u.end.status, firmwareUpgrade->u.end.errorMessage); if (ret < 0) { TCP_PRINT("No active firmware upgrade session\r\n"); tcp_send_firmware_upgrade_response(FIRMWARE_RESP_NAK, 0, "No upgrade session"); return -1; } tcp_send_firmware_upgrade_response(FIRMWARE_RESP_NAK, 0, "Upgrade failed"); return -1; } else if (strcmp(firmwareUpgrade->subCommand, FIRMWARE_SUBCMD_RESPONSE) == 0) { TCP_PRINT("Firmware upgrade response from client: code=%u index=%d msg=%s\r\n", firmwareUpgrade->u.response.response, firmwareUpgrade->u.response.packetIndex, firmwareUpgrade->u.response.message); } else { TCP_PRINT("Unknown firmware upgrade subCommand: %s\r\n", firmwareUpgrade->subCommand); tcp_send_firmware_upgrade_response(FIRMWARE_RESP_NAK, -1, "Unknown subCommand"); return -1; } return 0; } /** * @brief 生成文件查询响应JSON * @param response 文件查询响应结构体指针 * @param buffer 输出缓冲区 * @param size 缓冲区大小 * @retval JSON字符串长度,-1表示失败 */ int tcp_generate_file_query_response(const tcp_file_query_response_t *response, char *buffer, uint32_t size) { cJSON *root = NULL; cJSON *data = NULL; cJSON *files_array = NULL; cJSON *file_item = NULL; char timestamp[32]; char *json_str = NULL; int json_len = 0; int i; if (buffer == NULL || size == 0 || response == NULL) { return -1; } /* 生成时间戳 */ if (tcp_generate_timestamp(timestamp, sizeof(timestamp)) != 0) { return -1; } /* 创建JSON对象 */ root = cJSON_CreateObject(); if (root == NULL) { return -1; } cJSON_AddStringToObject(root, "version", "2.0"); cJSON_AddStringToObject(root, "timestamp", timestamp); cJSON_AddStringToObject(root, "command", CMD_FILE_OPERATIONS); /* 创建data对象 */ data = cJSON_CreateObject(); if (data == NULL) { cJSON_Delete(root); return -1; } cJSON_AddStringToObject(data, "subCommand", FILE_OP_SUBCMD_QUERY); cJSON_AddStringToObject(data, "path", response->path); cJSON_AddNumberToObject(data, "fileCount", response->file_count); cJSON_AddNumberToObject(data, "dirCount", response->dir_count); cJSON_AddNumberToObject(data, "totalSize", response->total_size); /* 创建文件数组 */ if (response->file_count > 0 && response->files != NULL) { files_array = cJSON_CreateArray(); if (files_array == NULL) { cJSON_Delete(data); cJSON_Delete(root); return -1; } /* 添加文件项到数组 */ for (i = 0; i < response->file_count; i++) { file_item = cJSON_CreateObject(); if (file_item == NULL) { cJSON_Delete(files_array); cJSON_Delete(data); cJSON_Delete(root); return -1; } cJSON_AddStringToObject(file_item, "name", response->files[i].name); cJSON_AddNumberToObject(file_item, "type", response->files[i].type); cJSON_AddNumberToObject(file_item, "size", response->files[i].size); cJSON_AddStringToObject(file_item, "modifiedTime", response->files[i].modified_time); cJSON_AddStringToObject(file_item, "createdTime", response->files[i].created_time); cJSON_AddItemToArray(files_array, file_item); } cJSON_AddItemToObject(data, "files", files_array); } cJSON_AddItemToObject(root, "data", data); /* 生成JSON字符串 */ json_str = cJSON_PrintUnformatted(root); if (json_str == NULL) { cJSON_Delete(root); return -1; } json_len = strlen(json_str); if (json_len + 1 > size) { cJSON_free(json_str); cJSON_Delete(root); return -1; } /* 复制到输出缓冲区 */ strncpy(buffer, json_str, size); buffer[size - 1] = '\0'; /* 释放内存 */ cJSON_free(json_str); cJSON_Delete(root); TCP_PRINT("Generated file query response JSON (%d bytes)\r\n", json_len); return json_len; } /** * @brief 生成文件删除响应JSON * @param response 文件删除响应结构体指针 * @param buffer 输出缓冲区 * @param size 缓冲区大小 * @retval JSON字符串长度,-1表示失败 */ int tcp_generate_file_delete_response(const tcp_file_delete_response_t *response, char *buffer, uint32_t size) { cJSON *root = NULL; cJSON *data = NULL; char timestamp[32]; char *json_str = NULL; int json_len = 0; if (buffer == NULL || size == 0 || response == NULL) { return -1; } /* 生成时间戳 */ if (tcp_generate_timestamp(timestamp, sizeof(timestamp)) != 0) { return -1; } /* 创建JSON对象 */ root = cJSON_CreateObject(); if (root == NULL) { return -1; } cJSON_AddStringToObject(root, "version", "2.0"); cJSON_AddStringToObject(root, "timestamp", timestamp); cJSON_AddStringToObject(root, "command", CMD_FILE_OPERATIONS); /* 创建data对象 */ data = cJSON_CreateObject(); if (data == NULL) { cJSON_Delete(root); return -1; } cJSON_AddStringToObject(data, "subCommand", FILE_OP_SUBCMD_DELETE); cJSON_AddStringToObject(data, "path", response->path); cJSON_AddNumberToObject(data, "status", response->status); cJSON_AddStringToObject(data, "message", response->message); cJSON_AddItemToObject(root, "data", data); /* 生成JSON字符串 */ json_str = cJSON_PrintUnformatted(root); if (json_str == NULL) { cJSON_Delete(root); return -1; } json_len = strlen(json_str); if (json_len + 1 > size) { cJSON_free(json_str); cJSON_Delete(root); return -1; } /* 复制到输出缓冲区 */ strncpy(buffer, json_str, size); buffer[size - 1] = '\0'; /* 释放内存 */ cJSON_free(json_str); cJSON_Delete(root); TCP_PRINT("Generated file delete response JSON (%d bytes)\r\n", json_len); return json_len; } /** * @brief 生成文件下载响应JSON * @param response 文件下载响应结构体指针 * @param buffer 输出缓冲区 * @param size 缓冲区大小 * @retval JSON字符串长度,-1表示失败 */ int tcp_generate_file_download_response(const tcp_file_download_response_t *response, char *buffer, uint32_t size) { cJSON *root = NULL; cJSON *data = NULL; char timestamp[32]; char *json_str = NULL; int json_len = 0; if (buffer == NULL || size == 0 || response == NULL) { return -1; } /* 生成时间戳 */ if (tcp_generate_timestamp(timestamp, sizeof(timestamp)) != 0) { return -1; } /* 创建JSON对象 */ root = cJSON_CreateObject(); if (root == NULL) { return -1; } cJSON_AddStringToObject(root, "version", "2.0"); cJSON_AddStringToObject(root, "timestamp", timestamp); cJSON_AddStringToObject(root, "command", CMD_FILE_OPERATIONS); /* 创建data对象 */ data = cJSON_CreateObject(); if (data == NULL) { cJSON_Delete(root); return -1; } cJSON_AddStringToObject(data, "subCommand", FILE_OP_SUBCMD_DOWNLOAD); cJSON_AddStringToObject(data, "path", response->path); cJSON_AddNumberToObject(data, "fileSize", response->file_size); cJSON_AddNumberToObject(data, "offset", response->offset); cJSON_AddNumberToObject(data, "chunkSize", response->chunk_size); cJSON_AddNumberToObject(data, "dataLen", response->data_len); cJSON_AddNumberToObject(data, "isLastChunk", response->is_last_chunk); /* 添加数据字段:文件块经 Base64 编码后写入,避免日志中的控制字符/非 UTF-8 导致 JSON 非法 */ if (response->data != NULL && response->data_len > 0) { uint32_t b64_size = ((response->data_len + 2) / 3) * 4 + 1; char *b64_buf = (char *)pvPortMalloc(b64_size); if (b64_buf != NULL) { if (base64_encode(response->data, response->data_len, b64_buf, b64_size) > 0) { cJSON_AddStringToObject(data, "data", b64_buf); } else { cJSON_AddStringToObject(data, "data", ""); } vPortFree(b64_buf); } else { cJSON_AddStringToObject(data, "data", ""); } } else { cJSON_AddStringToObject(data, "data", ""); } cJSON_AddItemToObject(root, "data", data); /* 生成JSON字符串 */ json_str = cJSON_PrintUnformatted(root); if (json_str == NULL) { cJSON_Delete(root); return -1; } json_len = strlen(json_str); if (json_len + 1 > size) { cJSON_free(json_str); cJSON_Delete(root); return -1; } /* 复制到输出缓冲区 */ strncpy(buffer, json_str, size); buffer[size - 1] = '\0'; /* 释放内存 */ cJSON_free(json_str); cJSON_Delete(root); TCP_PRINT("Generated file download response JSON (%d bytes)\r\n", json_len); return json_len; } /** * @brief 生成文件上传响应JSON * @param response 文件上传响应结构体指针 * @param buffer 输出缓冲区 * @param size 缓冲区大小 * @retval JSON字符串长度,-1表示失败 */ int tcp_generate_file_upload_response(const tcp_file_upload_response_t *response, char *buffer, uint32_t size) { cJSON *root = NULL; cJSON *data = NULL; char timestamp[32]; char *json_str = NULL; int json_len = 0; if (buffer == NULL || size == 0 || response == NULL) { return -1; } /* 生成时间戳 */ if (tcp_generate_timestamp(timestamp, sizeof(timestamp)) != 0) { return -1; } /* 创建JSON对象 */ root = cJSON_CreateObject(); if (root == NULL) { return -1; } cJSON_AddStringToObject(root, "version", "2.0"); cJSON_AddStringToObject(root, "timestamp", timestamp); cJSON_AddStringToObject(root, "command", CMD_FILE_OPERATIONS); /* 创建data对象 */ data = cJSON_CreateObject(); if (data == NULL) { cJSON_Delete(root); return -1; } cJSON_AddStringToObject(data, "subCommand", FILE_OP_SUBCMD_UPLOAD); cJSON_AddStringToObject(data, "path", response->path); cJSON_AddNumberToObject(data, "receivedSize", response->received_size); cJSON_AddNumberToObject(data, "totalSize", response->total_size); cJSON_AddNumberToObject(data, "status", response->status); cJSON_AddStringToObject(data, "message", response->message); cJSON_AddItemToObject(root, "data", data); /* 生成JSON字符串 */ json_str = cJSON_PrintUnformatted(root); if (json_str == NULL) { cJSON_Delete(root); return -1; } json_len = strlen(json_str); if (json_len + 1 > size) { cJSON_free(json_str); cJSON_Delete(root); return -1; } /* 复制到输出缓冲区 */ strncpy(buffer, json_str, size); buffer[size - 1] = '\0'; /* 释放内存 */ cJSON_free(json_str); cJSON_Delete(root); TCP_PRINT("Generated file upload response JSON (%d bytes)\r\n", json_len); return json_len; } /** * @brief 处理文件操作请求 * @param fileOperation 文件操作数据结构体指针 * @retval 0成功,-1失败 */ int tcp_process_file_operation(const tcp_file_operation_data_t *fileOperation) { if (fileOperation == NULL) { return -1; } TCP_PRINT("Processing file operation: subCommand=%s\r\n", fileOperation->subCommand); /* 根据子命令处理 */ if (strcmp(fileOperation->subCommand, FILE_OP_SUBCMD_QUERY) == 0) { TCP_PRINT("File query operation:\r\n"); TCP_PRINT(" Path: %s\r\n", fileOperation->request.query.path); /* 调用system_filectrl模块处理文件查询 */ tcp_file_query_response_t response; memset(&response, 0, sizeof(response)); if (system_filectrl_process_query((const file_query_request_t *)&fileOperation->request.query, (file_query_response_t *)&response) != 0) { TCP_PRINT("Failed to query files\r\n"); return -1; } /* 生成响应JSON并发送 */ char response_json[2048]; int json_len = tcp_generate_file_query_response(&response, response_json, sizeof(response_json)); if (json_len > 0) { err_t send_err = tcp_server_send_json(response_json, json_len); if (send_err == ERR_OK) { TCP_PRINT("File query response sent successfully\r\n"); } else { TCP_PRINT("Failed to send file query response: %d\r\n", send_err); } } else { TCP_PRINT("Failed to generate file query response JSON\r\n"); } /* 释放动态分配的内存 - 使用专门的释放函数 */ system_filectrl_free_query_response((file_query_response_t *)&response); } else if (strcmp(fileOperation->subCommand, FILE_OP_SUBCMD_DELETE) == 0) { TCP_PRINT("File delete operation:\r\n"); TCP_PRINT(" Path: %s\r\n", fileOperation->request.delete.path); /* 调用system_filectrl模块处理文件删除 */ tcp_file_delete_response_t response; memset(&response, 0, sizeof(response)); if (system_filectrl_process_delete((const file_delete_request_t *)&fileOperation->request.delete, (file_delete_response_t *)&response) != 0) { TCP_PRINT("Failed to delete file\r\n"); return -1; } /* 生成响应JSON并发送 */ char response_json[512]; int json_len = tcp_generate_file_delete_response(&response, response_json, sizeof(response_json)); if (json_len > 0) { err_t send_err = tcp_server_send_json(response_json, json_len); if (send_err == ERR_OK) { TCP_PRINT("File delete response sent successfully\r\n"); } else { TCP_PRINT("Failed to send file delete response: %d\r\n", send_err); } } else { TCP_PRINT("Failed to generate file delete response JSON\r\n"); } } else if (strcmp(fileOperation->subCommand, FILE_OP_SUBCMD_DOWNLOAD) == 0) { TCP_PRINT("File download operation:\r\n"); TCP_PRINT(" Path: %s\r\n", fileOperation->request.download.path); TCP_PRINT(" Offset: %u\r\n", fileOperation->request.download.offset); TCP_PRINT(" Chunk size: %u\r\n", fileOperation->request.download.chunk_size); /* 调用system_filectrl模块处理文件下载 */ tcp_file_download_response_t response; memset(&response, 0, sizeof(response)); if (system_filectrl_process_download((const file_download_request_t *)&fileOperation->request.download, (file_download_response_t *)&response) != 0) { TCP_PRINT("Failed to download file\r\n"); return -1; } /* 生成响应JSON并发送 */ char response_json[2048]; /* 需要足够大以容纳Base64数据 */ int json_len = tcp_generate_file_download_response(&response, response_json, sizeof(response_json)); if (json_len > 0) { err_t send_err = tcp_server_send_json(response_json, json_len); if (send_err == ERR_OK) { TCP_PRINT("File download response sent successfully\r\n"); } else { TCP_PRINT("Failed to send file download response: %d\r\n", send_err); } } else { TCP_PRINT("Failed to generate file download response JSON\r\n"); } /* 释放动态分配的内存 - 使用专门的释放函数 */ system_filectrl_free_download_response((file_download_response_t *)&response); } else if (strcmp(fileOperation->subCommand, FILE_OP_SUBCMD_UPLOAD) == 0) { TCP_PRINT("File upload operation:\r\n"); TCP_PRINT(" Path: %s\r\n", fileOperation->request.upload.path); TCP_PRINT(" Offset: %u\r\n", fileOperation->request.upload.offset); TCP_PRINT(" File size: %u\r\n", fileOperation->request.upload.file_size); TCP_PRINT(" Data length: %u bytes (Base64)\r\n", (uint32_t)strlen((const char *)fileOperation->request.upload.data)); /* 调用system_filectrl模块处理文件上传 */ tcp_file_upload_response_t response; memset(&response, 0, sizeof(response)); if (system_filectrl_process_upload((const file_upload_request_t *)&fileOperation->request.upload, (file_upload_response_t *)&response) != 0) { TCP_PRINT("Failed to upload file\r\n"); return -1; } /* 生成响应JSON并发送 */ char response_json[512]; int json_len = tcp_generate_file_upload_response(&response, response_json, sizeof(response_json)); if (json_len > 0) { err_t send_err = tcp_server_send_json(response_json, json_len); if (send_err == ERR_OK) { TCP_PRINT("File upload response sent successfully\r\n"); } else { TCP_PRINT("Failed to send file upload response: %d\r\n", send_err); } } else { TCP_PRINT("Failed to generate file upload response JSON\r\n"); } } else { TCP_PRINT("Unknown file operation subCommand: %s\r\n", fileOperation->subCommand); return -1; } return 0; } /** * @brief 释放消息结构体中分配的内存 * @param message 消息结构体指针 */ void tcp_free_message(tcp_message_t *message) { if (message == NULL) { return; } /* 根据命令类型释放不同的动态分配内存 */ if (strcmp(message->command, CMD_PARAM_MODIFY) == 0) { /* 释放参数修改请求中的参数数组 */ if (message->data.paramModify.params != NULL) { vPortFree(message->data.paramModify.params); message->data.paramModify.params = NULL; message->data.paramModify.count = 0; } } else if (strcmp(message->command, CMD_FIRMWARE_UPGRADE) == 0) { /* 释放固件升级Data子命令中的数据 */ if (strcmp(message->data.firmwareUpgrade.subCommand, FIRMWARE_SUBCMD_DATA) == 0) { if (message->data.firmwareUpgrade.u.data.data != NULL) { vPortFree(message->data.firmwareUpgrade.u.data.data); message->data.firmwareUpgrade.u.data.data = NULL; message->data.firmwareUpgrade.u.data.data_len = 0; } } } /* 注意:文件操作中的内存由专门的释放函数处理,不需要在这里释放 */ } /** * @brief 处理故障信息消息 * @param message 消息结构体指针 * @retval 0成功,-1失败 */ static int tcp_process_fault_info_message(const tcp_message_t *message) { tcp_fault_info_response_t response; char *response_json = NULL; int json_len = 0; int result = 0; TCP_PRINT("Received fault info request: faultCode=%s\r\r\n", message->data.faultInfo.faultCode); /* 处理故障信息请求 */ memset(&response, 0, sizeof(response)); /* 调用v_get_fault_data函数获取故障数据 */ tcp_get_system_fault_data(&response); /* 动态分配响应JSON缓冲区 */ response_json = (char *)pvPortMalloc(2048); if (response_json == NULL) { TCP_PRINT("Failed to allocate memory for response JSON\r\r\n"); result = -1; goto cleanup; } /* 生成响应JSON */ json_len = tcp_generate_fault_info_json(&response, response_json, 2048); if (json_len > 0) { TCP_PRINT("Fault info response generated (%d bytes)\r\r\n", json_len); /* 发送响应到客户端 */ err_t send_err = tcp_server_send_json(response_json, json_len); if (send_err == ERR_OK) { TCP_PRINT("Fault info response sent successfully\r\r\n"); } else { TCP_PRINT("Failed to send fault info response: %d\r\r\n", send_err); result = -1; } } else { TCP_PRINT("Failed to generate fault info response\r\r\n"); result = -1; } cleanup: /* 释放动态分配的内存 */ if (response.faults != NULL) { vPortFree(response.faults); } if (response_json != NULL) { vPortFree(response_json); } return result; } /** * @brief 生成故障信息响应JSON * @param response 故障信息响应结构体指针 * @param buffer 输出缓冲区 * @param size 缓冲区大小 * @retval JSON字符串长度,-1表示失败 */ static int tcp_generate_fault_info_json(const tcp_fault_info_response_t *response, char *buffer, uint32_t size) { cJSON *root = NULL; cJSON *data = NULL; cJSON *faults_array = NULL; cJSON *fault_item = NULL; char timestamp[32]; char *json_str = NULL; int json_len = 0; int i; if (buffer == NULL || size == 0 || response == NULL) { return -1; } /* 生成时间戳 */ if (tcp_generate_timestamp(timestamp, sizeof(timestamp)) != 0) { return -1; } /* 创建JSON对象 */ root = cJSON_CreateObject(); if (root == NULL) { return -1; } cJSON_AddStringToObject(root, "version", "2.0"); cJSON_AddStringToObject(root, "timestamp", timestamp); cJSON_AddStringToObject(root, "command", CMD_FAULT_INFO); cJSON_AddNumberToObject(root, "status", 0); /* 成功状态 */ /* 创建data对象 */ data = cJSON_CreateObject(); if (data == NULL) { cJSON_Delete(root); return -1; } cJSON_AddNumberToObject(data, "faultCount", response->faultCount); /* 创建故障数组 */ if (response->faultCount > 0 && response->faults != NULL) { faults_array = cJSON_CreateArray(); if (faults_array == NULL) { cJSON_Delete(data); cJSON_Delete(root); return -1; } /* 添加故障项到数组 */ for (i = 0; i < response->faultCount; i++) { fault_item = cJSON_CreateObject(); if (fault_item == NULL) { cJSON_Delete(faults_array); cJSON_Delete(data); cJSON_Delete(root); return -1; } cJSON_AddStringToObject(fault_item, "location", response->faults[i].location); cJSON_AddStringToObject(fault_item, "code", response->faults[i].code); cJSON_AddStringToObject(fault_item, "time", response->faults[i].time); cJSON_AddStringToObject(fault_item, "description", response->faults[i].description); cJSON_AddItemToArray(faults_array, fault_item); } cJSON_AddItemToObject(data, "faults", faults_array); } cJSON_AddItemToObject(root, "data", data); /* 生成JSON字符串 */ json_str = cJSON_PrintUnformatted(root); if (json_str == NULL) { cJSON_Delete(root); return -1; } json_len = strlen(json_str); if (json_len + 1 > size) { cJSON_free(json_str); cJSON_Delete(root); return -1; } /* 复制到输出缓冲区 */ strncpy(buffer, json_str, size); buffer[size - 1] = '\0'; /* 释放内存 */ cJSON_free(json_str); cJSON_Delete(root); return json_len; } /** * @brief 处理历史记录查询/清除消息 * @param message 消息结构体指针 * @retval 0成功,-1失败 */ static int tcp_process_history_operations_message(const tcp_message_t *message) { char *response_json = NULL; int json_len = 0; int result = 0; uint16_t totalCount = 0; uint16_t startIndex = 0; uint16_t fetchCount = 0; uint16_t wantedCount = 0; uint16_t filledCount = 0; uint16_t returnedCount = 0; uint8_t isLastPacket = 1; uint8_t include_time = 0; const tcp_history_operations_data_t *req = NULL; req = &message->data.historyOperations; TCP_PRINT("Received history operations: subCommand=%s, historyType=%s, startIndex=%u, fetchCount=%u, queryId=%u\r\r\n", req->subCommand, req->historyType, req->startIndex, req->fetchCount, (unsigned int)req->queryId); /* 清除响应/查询响应最终都需要 JSON 缓冲区 */ response_json = (char *)pvPortMalloc(2048); if (response_json == NULL) { TCP_PRINT("Failed to allocate memory for history response JSON\r\r\n"); return -1; } memset(response_json, 0, 2048); /* 子命令:Query */ if (strcmp(req->subCommand, HISTORY_OP_SUBCMD_QUERY) == 0) { tcp_history_query_xfer_t *hx = NULL; char (*time_buf)[HISTORY_TIME_STR_SIZE] = NULL; char (*content_buf)[HISTORY_CONTENT_STR_SIZE] = NULL; startIndex = req->startIndex; fetchCount = req->fetchCount; /* 约 13KB+ 传输缓冲放堆上,避免任务栈溢出导致死机 */ hx = (tcp_history_query_xfer_t *)pvPortMalloc(sizeof(tcp_history_query_xfer_t)); if (hx != NULL) { memset(hx, 0, sizeof(*hx)); time_buf = hx->time_buf; content_buf = hx->content_buf; wantedCount = fetchCount; if (wantedCount > HISTORY_QUERY_MAX_RECORDS) { wantedCount = HISTORY_QUERY_MAX_RECORDS; } filledCount = tcp_history_build_records(req->historyType, startIndex, wantedCount, time_buf, content_buf, &include_time, &totalCount); } else { TCP_PRINT("tcp_process_history_operations_message: hx malloc failed (history query)\r\r\n"); totalCount = tcp_history_get_total_count(req->historyType); include_time = (strcmp(req->historyType, "fault") == 0 || strcmp(req->historyType, "charging") == 0) ? 1u : 0u; filledCount = 0u; } /* 按1024字节JSON长度限制裁剪 returnedCount */ returnedCount = 0; /* 逐步尝试:从filledCount开始往下裁剪 */ for (int tryCount = (int)filledCount; tryCount >= 0; --tryCount) { uint16_t tmpReturned = (uint16_t)tryCount; isLastPacket = ((uint16_t)(startIndex + tmpReturned) >= totalCount) ? 1u : 0u; /* 生成 QueryResponse JSON */ cJSON *root = cJSON_CreateObject(); cJSON *data = NULL; cJSON *records = NULL; char timestamp[32] = {0}; char *json_str = NULL; if (root == NULL) { continue; } cJSON_AddStringToObject(root, "version", "2.0"); if (tcp_generate_timestamp(timestamp, sizeof(timestamp)) != 0) { cJSON_Delete(root); continue; } cJSON_AddStringToObject(root, "timestamp", timestamp); cJSON_AddStringToObject(root, "command", CMD_HISTORY_OPERATIONS); cJSON_AddNumberToObject(root, "status", 0); data = cJSON_CreateObject(); if (data == NULL) { cJSON_Delete(root); continue; } cJSON_AddItemToObject(root, "data", data); cJSON_AddStringToObject(data, "subCommand", "QueryResponse"); cJSON_AddStringToObject(data, "historyType", req->historyType); cJSON_AddNumberToObject(data, "queryId", req->queryId); cJSON_AddNumberToObject(data, "startIndex", startIndex); cJSON_AddNumberToObject(data, "totalCount", totalCount); cJSON_AddNumberToObject(data, "returnedCount", tmpReturned); cJSON_AddNumberToObject(data, "isLastPacket", isLastPacket); records = cJSON_CreateArray(); if (records == NULL) { cJSON_Delete(root); continue; } cJSON_AddItemToObject(data, "records", records); for (uint16_t i = 0; i < tmpReturned; i++) { cJSON *rec = cJSON_CreateObject(); if (rec == NULL) { continue; } if (include_time != 0u && time_buf != NULL) { cJSON_AddStringToObject(rec, "time", time_buf[i]); } cJSON_AddStringToObject(rec, "content", (content_buf != NULL) ? content_buf[i] : ""); cJSON_AddItemToArray(records, rec); } json_str = cJSON_PrintUnformatted(root); if (json_str == NULL) { cJSON_Delete(root); continue; } json_len = (int)strlen(json_str); cJSON_free(json_str); /* 1024字节限制:符合才停止 */ if (json_len <= 1024) { /* 重新生成一次,拷贝到 response_json */ json_str = cJSON_PrintUnformatted(root); if (json_str != NULL) { json_len = (int)strlen(json_str); if (json_len + 1 <= 2048) { strncpy(response_json, json_str, 2047); response_json[2047] = '\0'; returnedCount = tmpReturned; } cJSON_free(json_str); } cJSON_Delete(root); break; } cJSON_Delete(root); } /* 若仍未生成合法返回,返回空records也要确保返回 */ if (returnedCount == 0) { /* 生成一个最小 QueryResponse(0条记录) */ cJSON *root = cJSON_CreateObject(); cJSON *data = cJSON_CreateObject(); cJSON *records = cJSON_CreateArray(); char timestamp[32] = {0}; cJSON_AddItemToObject(root, "data", data); cJSON_AddStringToObject(root, "version", "2.0"); if (tcp_generate_timestamp(timestamp, sizeof(timestamp)) == 0) { cJSON_AddStringToObject(root, "timestamp", timestamp); } else { cJSON_AddStringToObject(root, "timestamp", "0"); } cJSON_AddStringToObject(root, "command", CMD_HISTORY_OPERATIONS); cJSON_AddNumberToObject(root, "status", 0); cJSON_AddStringToObject(data, "subCommand", "QueryResponse"); cJSON_AddStringToObject(data, "historyType", req->historyType); cJSON_AddNumberToObject(data, "queryId", req->queryId); cJSON_AddNumberToObject(data, "startIndex", startIndex); cJSON_AddNumberToObject(data, "totalCount", totalCount); cJSON_AddNumberToObject(data, "returnedCount", 0); cJSON_AddNumberToObject(data, "isLastPacket", 1); cJSON_AddItemToObject(data, "records", records); char *json_str = cJSON_PrintUnformatted(root); if (json_str != NULL) { json_len = (int)strlen(json_str); if (json_len + 1 <= 2048) { strncpy(response_json, json_str, 2047); response_json[2047] = '\0'; } cJSON_free(json_str); } cJSON_Delete(root); } if (json_len > 0) { err_t send_err = tcp_server_send_json(response_json, (uint16_t)json_len); if (send_err != ERR_OK) { TCP_PRINT("Failed to send history query response: %d\r\r\n", send_err); result = -1; } } else { TCP_PRINT("Failed to generate history query response\r\r\n"); result = -1; } if (hx != NULL) { vPortFree(hx); hx = NULL; } } else if (strcmp(req->subCommand, HISTORY_OP_SUBCMD_CLEAR) == 0) { /* 清除记录 */ uint32_t status = 0; char message[128] = {0}; int clearRet = tcp_history_clear_records(req->historyType, message, (uint32_t)sizeof(message)); status = (clearRet == 0) ? 0u : 1u; /* 生成 ClearResponse JSON */ cJSON *root = cJSON_CreateObject(); cJSON *data = NULL; char timestamp[32] = {0}; if (root == NULL) { vPortFree(response_json); return -1; } cJSON_AddStringToObject(root, "version", "2.0"); if (tcp_generate_timestamp(timestamp, sizeof(timestamp)) == 0) { cJSON_AddStringToObject(root, "timestamp", timestamp); } else { cJSON_AddStringToObject(root, "timestamp", "0"); } cJSON_AddStringToObject(root, "command", CMD_HISTORY_OPERATIONS); cJSON_AddNumberToObject(root, "status", status); data = cJSON_CreateObject(); if (data == NULL) { cJSON_Delete(root); vPortFree(response_json); return -1; } cJSON_AddItemToObject(root, "data", data); cJSON_AddStringToObject(data, "subCommand", "ClearResponse"); cJSON_AddStringToObject(data, "historyType", req->historyType); cJSON_AddNumberToObject(data, "queryId", req->queryId); cJSON_AddNumberToObject(data, "status", status); cJSON_AddStringToObject(data, "message", message); char *json_str = cJSON_PrintUnformatted(root); if (json_str != NULL) { json_len = (int)strlen(json_str); if (json_len + 1 <= 2048) { strncpy(response_json, json_str, 2047); response_json[2047] = '\0'; } cJSON_free(json_str); } cJSON_Delete(root); if (json_len > 0) { err_t send_err = tcp_server_send_json(response_json, (uint16_t)json_len); if (send_err != ERR_OK) { TCP_PRINT("Failed to send history clear response: %d\r\r\n", send_err); result = -1; } } else { TCP_PRINT("Failed to generate history clear response\r\r\n"); result = -1; } } else { TCP_PRINT("Unknown history subCommand: %s\r\r\n", req->subCommand); result = -1; } if (response_json != NULL) { vPortFree(response_json); response_json = NULL; } return result; } /** * @brief 处理自定义数据消息 * @param message 消息结构体指针 * @retval 0成功,-1失败 */ static int tcp_process_custom_data_message(const tcp_message_t *message) { tcp_custom_data_t response_data; char *response_json = NULL; int json_len = 0; int result = 0; TCP_PRINT("Received custom data: functionContent=%s, functionField=%s, functionParams=%s\r\r\n", message->data.customData.functionContent, message->data.customData.functionField, message->data.customData.functionParams); /* 处理自定义数据请求 */ memset(&response_data, 0, sizeof(response_data)); /* 调用自定义数据处理函数 */ if (tcp_process_custom_data(&message->data.customData, &response_data) != 0) { TCP_PRINT("Failed to process custom data\r\r\n"); return -1; } /* 动态分配响应JSON缓冲区 */ response_json = (char *)pvPortMalloc(1024); if (response_json == NULL) { TCP_PRINT("Failed to allocate memory for response JSON\r\r\n"); result = -1; goto cleanup; } /* 生成响应JSON */ json_len = tcp_generate_custom_data_json(&response_data, response_json, 1024); if (json_len > 0) { TCP_PRINT("Custom data response generated (%d bytes)\r\r\n", json_len); /* 发送响应到客户端 */ err_t send_err = tcp_server_send_json(response_json, json_len); if (send_err == ERR_OK) { TCP_PRINT("Custom data response sent successfully\r\r\n"); } else { TCP_PRINT("Failed to send custom data response: %d\r\r\n", send_err); result = -1; } } else { TCP_PRINT("Failed to generate custom data response\r\r\n"); result = -1; } cleanup: /* 释放动态分配的内存 */ if (response_json != NULL) { vPortFree(response_json); } return result; } /** * @brief 生成自定义数据JSON * @param customData 自定义数据结构体指针 * @param buffer 输出缓冲区 * @param size 缓冲区大小 * @retval JSON字符串长度,-1表示失败 */ int tcp_generate_custom_data_json(const tcp_custom_data_t *customData, char *buffer, uint32_t size) { cJSON *root = NULL; cJSON *data = NULL; char timestamp[32]; char *json_str = NULL; int json_len = 0; if (buffer == NULL || size == 0 || customData == NULL) { return -1; } /* 生成时间戳 */ if (tcp_generate_timestamp(timestamp, sizeof(timestamp)) != 0) { return -1; } /* 创建JSON对象 */ root = cJSON_CreateObject(); if (root == NULL) { return -1; } cJSON_AddStringToObject(root, "version", "2.0"); cJSON_AddStringToObject(root, "timestamp", timestamp); cJSON_AddStringToObject(root, "command", CMD_CUSTOM_DATA); /* 创建data对象 */ data = cJSON_CreateObject(); if (data == NULL) { cJSON_Delete(root); return -1; } /* 添加自定义数据字段 */ cJSON_AddStringToObject(data, "functionContent", customData->functionContent); cJSON_AddStringToObject(data, "functionField", customData->functionField); cJSON_AddStringToObject(data, "functionParams", customData->functionParams); cJSON_AddItemToObject(root, "data", data); /* 生成JSON字符串 */ json_str = cJSON_PrintUnformatted(root); if (json_str == NULL) { cJSON_Delete(root); return -1; } json_len = strlen(json_str); if (json_len + 1 > size) { cJSON_free(json_str); cJSON_Delete(root); return -1; } /* 复制到输出缓冲区 */ strncpy(buffer, json_str, size); buffer[size - 1] = '\0'; /* 释放内存 */ cJSON_free(json_str); cJSON_Delete(root); return json_len; } #endif