Files
CCU621M/app/tcp_ser/tcp_protocol.c
T

3052 lines
109 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
******************************************************************************
* @file tcp_protocol.c
* @brief TCP通信协议解析实现
******************************************************************************
*/
#include "tcp_protocol.h"
#include "tcp_server.h"
#include "cJSON.h"
#include <string.h>
#include <stdio.h>
#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 = &param_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 = &param_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;
}
/** 固件升级 Response0=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) {
/* 生成一个最小 QueryResponse0条记录) */
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