Initial commit: CCU621_M firmware project with BLE debug link support.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,853 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file system_data.c
|
||||
* @brief 系统数据交互模块实现(简化版)
|
||||
*
|
||||
* 该模块负责系统信息、充电信息获取、充电控制等功能
|
||||
* 为参数配置、文件获取等功能预留接口
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "system_data.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
#include "publicdata/type.h"
|
||||
#include "publicdata/public_define.h"
|
||||
|
||||
#if TCP_DEBUG_EN
|
||||
|
||||
#include "tcp_ser/tcp_server.h"
|
||||
#include "tcp_ser/tcp_protocol.h"
|
||||
#include "flash_file_mgr/fault_flash_impl.h"
|
||||
#include "plat_comm/impl/bs_public_impl.h"
|
||||
#include "publicdata/publicdata.h"
|
||||
#include "flowctrl/flowctrl_task.h"
|
||||
#include "collect_ctrl/collect_task.h"
|
||||
#include "bms/bms_interface.h"
|
||||
#include "meter_calculate/meter_calculate_impl.h"
|
||||
#include "flash_file_mgr/meter_calculate_flash_impl.h"
|
||||
#include "fault_cheak/fault_interface.h"
|
||||
#include "app_fatfs/fatfs_card.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取默认系统信息(从system_data模块获取)
|
||||
* @param systemInfo 输出系统信息结构体
|
||||
*/
|
||||
void tcp_get_default_system_info(tcp_system_info_data_t *systemInfo)
|
||||
{
|
||||
REAL_FAULT_DATA_T rl_data;
|
||||
|
||||
if (systemInfo == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
v_get_fault_data(&rl_data);
|
||||
memset(systemInfo, 0, sizeof(tcp_system_info_data_t));
|
||||
|
||||
/* 从system_data模块获取系统信息 */
|
||||
strcpy(systemInfo->systemModel, (char *)Device_Model); //设备型号
|
||||
systemInfo->gunCount = GUN_MAX_CNT; //最大支持枪数量
|
||||
systemInfo->devicePower = g_t_share_data.t_sys_fix_cfg.u16_ratePow; //设备功率 kW
|
||||
systemInfo->networkStatus = u8_bs_get_log_on_flag();
|
||||
systemInfo->faultCount = rl_data.u8_fault_cnt;
|
||||
strcpy(systemInfo->version, (char *)Software_Version);
|
||||
}
|
||||
|
||||
static void tcp_copy_log_field(char *dst, size_t dst_sz, const U8_T *src, size_t src_sz)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if ((dst == NULL) || (dst_sz == 0U)) {
|
||||
return;
|
||||
}
|
||||
dst[0] = '\0';
|
||||
if (src == NULL) {
|
||||
return;
|
||||
}
|
||||
for (i = 0U; i + 1U < dst_sz && i < src_sz; i++) {
|
||||
U8_T b = src[i];
|
||||
if (b == 0U) {
|
||||
break;
|
||||
}
|
||||
if (b < 0x20U || b > 0x7EU) {
|
||||
break;
|
||||
}
|
||||
dst[i] = (char)b;
|
||||
}
|
||||
dst[i] = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取默认充电枪数据(从system_data模块获取)
|
||||
* @param gunData 输出充电枪数据结构体
|
||||
* @param gunNumber 枪编号 (1-2)
|
||||
*/
|
||||
void tcp_get_default_gun_data(tcp_gun_data_t *gunData, uint8_t gunNumber)
|
||||
{
|
||||
U8_T u8_gunNo = gunNumber -1;
|
||||
U8_T u8_gunState = u16_flow_put_data(u8_gunNo , E_FLOW_PUT_DATA_GUN_REAL_STATE,0); //0空闲 1充电启动 2绝缘启动 3绝缘计算完成 4绝缘检测模块停止 5开始预充 6预充完成 7充电中 8BMS通讯超时 9充电停止 10充电停止完成
|
||||
U8_T u8_gunLink = u8_get_gun_yx_data(YX_GUN_LINK,u8_gunNo);
|
||||
U16_T u16_needVol = u16_bms_put_data(u8_gunNo,E_BMS_PUT_DATA_BMS_NEED_VOL,0);
|
||||
U16_T u16_needCur = u16_bms_put_data(u8_gunNo,E_BMS_PUT_DATA_BMS_NEED_CUR,0);
|
||||
U16_T u16_outVol = (U16_T)(u64_get_meter_data(u8_gunNo,0,E_METER_DATA_VOL)/1000); //充电电压 精度 0.1V
|
||||
U16_T u16_outCur = (U16_T)(u64_get_meter_data(u8_gunNo,0,E_METER_DATA_CUR)/1000); //充电电流 精度 0.1A
|
||||
S_LOG_DATA s_log;
|
||||
char user_field[32];
|
||||
|
||||
memset(&s_log , 0 ,sizeof(S_LOG_DATA));
|
||||
v_meterlog_put_char_log_data(u8_gunNo,&s_log); //获取订单信息
|
||||
|
||||
if (gunData == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(gunData, 0, sizeof(tcp_gun_data_t));
|
||||
|
||||
/* 设置枪编号 */
|
||||
gunData->gunNumber = gunNumber;
|
||||
|
||||
/* 从system_data模块获取枪信息 */
|
||||
if(u8_gunState == 0 && u8_gunLink == 0)
|
||||
gunData->chargingStatus = CHARGING_STATUS_IDLE; /* 空闲 */
|
||||
else if(u8_gunState == 0 && u8_gunLink == 1)
|
||||
gunData->chargingStatus = CHARGING_STATUS_CONNECTED; /* 已连接 */
|
||||
else if(u8_gunState > 0 && u8_gunState < 7)
|
||||
gunData->chargingStatus = CHARGING_STATUS_STARTING; /* 启动中 */
|
||||
else if(u8_gunState >= 7 && u8_gunState <= 8)
|
||||
gunData->chargingStatus = CHARGING_STATUS_CHARGING; /* 充电中 */
|
||||
else if(u8_gunState > 8)
|
||||
gunData->chargingStatus = CHARGING_STATUS_FINISHED; /* 充电完成 */
|
||||
|
||||
|
||||
|
||||
gunData->gunConnectionStatus = u8_gunLink;
|
||||
gunData->demandVoltage = u16_needVol / 10.0f;
|
||||
gunData->demandCurrent = u16_needCur / 10.0f;
|
||||
gunData->actualVoltage = u16_outVol / 10.0f;
|
||||
gunData->actualCurrent = u16_outCur / 10.0f;
|
||||
|
||||
/* 空闲/仅插枪:不上送无效订单残留,避免 JSON 过长导致 BLE 分片异常 */
|
||||
if (gunData->chargingStatus <= CHARGING_STATUS_CONNECTED) {
|
||||
gunData->energy = 0.0f;
|
||||
gunData->cost = 0.0f;
|
||||
gunData->batterySOC = 0.0f;
|
||||
gunData->charge_time = 0U;
|
||||
gunData->userId[0] = '\0';
|
||||
gunData->orderNumber[0] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
gunData->energy = (float)s_log.u32_used_energy * 0.0001f;
|
||||
gunData->cost = (float)s_log.u32_used_money * 0.0001f;
|
||||
gunData->batterySOC = (s_log.u8_endSoc <= 100U) ? (float)s_log.u8_endSoc : 100.0f;
|
||||
gunData->charge_time = s_log.u16_ChargedTime;
|
||||
|
||||
tcp_copy_log_field(user_field, sizeof(user_field), s_log.u8_user_id, sizeof(s_log.u8_user_id));
|
||||
if (user_field[0] != '\0') {
|
||||
(void)snprintf(gunData->userId, sizeof(gunData->userId), "USER_%s", user_field);
|
||||
}
|
||||
|
||||
tcp_copy_log_field(gunData->orderNumber, sizeof(gunData->orderNumber),
|
||||
s_log.u8_preTradeNo, sizeof(s_log.u8_preTradeNo));
|
||||
|
||||
//测试
|
||||
// if(u8_gunNo == 0) gunData->chargingStatus = CHARGING_STATUS_CONNECTED;
|
||||
// else gunData->chargingStatus = CHARGING_STATUS_CHARGING;
|
||||
// gunData->gunConnectionStatus = 1;
|
||||
}
|
||||
|
||||
void v_mydebug_char_ctrl(U8_T u8_gunNo, U8_T u8_flag, U16_T u16_res)
|
||||
{
|
||||
S_FLOW_CHARGE_CTRL_INFO e_charge_ctrl_info;
|
||||
|
||||
memset(&e_charge_ctrl_info, 0, sizeof(S_FLOW_CHARGE_CTRL_INFO));
|
||||
e_charge_ctrl_info.e_cmd = u8_flag;
|
||||
|
||||
if (u8_flag == CMD_ON) {
|
||||
e_charge_ctrl_info.e_start_res = CTR_CMD_DEBUG;
|
||||
e_charge_ctrl_info.e_sdk_chargMode = E_SDK_CHGMOD_NONE;
|
||||
} else {
|
||||
e_charge_ctrl_info.e_stop_res = E_NORMAL_1001;
|
||||
}
|
||||
|
||||
v_flow_start_stop_ctrl(u8_gunNo, &e_charge_ctrl_info);
|
||||
|
||||
TCP_PRINT("[%d]gun charge ctrl[%d],[%d]\n", u8_gunNo, u8_flag, u16_res);
|
||||
|
||||
if (u8_flag == CMD_OFF) {
|
||||
v_meterlog_set_stop_char_log_info(u8_gunNo, E_NORMAL_1001);
|
||||
} else {
|
||||
S_CHAR_LOG_START_DATA s_log_start_data;
|
||||
memset(&s_log_start_data, 0, sizeof(S_CHAR_LOG_START_DATA));
|
||||
s_log_start_data.e_start_reason = e_charge_ctrl_info.e_start_res;
|
||||
strncpy((char *)s_log_start_data.u8_user_id, "DEBUG_001", EVS_MAX_TRADE_LEN);
|
||||
v_meterlog_set_start_char_log_info(u8_gunNo, &s_log_start_data);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief 停止充电(模拟实现)
|
||||
* @param gunNumber 枪编号 (1-2)
|
||||
* @param message 输出消息
|
||||
* @retval 0成功,-1失败
|
||||
*/
|
||||
int system_data_stop_charge(uint8_t gunNumber, char *message)
|
||||
{
|
||||
if (gunNumber < 1 || gunNumber > GUN_MAX_CNT) {
|
||||
if (message) strcpy(message, "参数错误:枪编号无效");
|
||||
return -1;
|
||||
}
|
||||
|
||||
v_mydebug_char_ctrl(gunNumber-1 , CMD_OFF ,0);
|
||||
|
||||
if (message) strcpy(message, "充电停止成功(模拟)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 启动充电(模拟实现)
|
||||
* @param gunNumber 枪编号 (1-2)
|
||||
* @param userId 用户ID
|
||||
* @param orderNumber 订单号
|
||||
* @param message 输出消息
|
||||
* @retval 0成功,-1失败
|
||||
*/
|
||||
int system_data_start_charge(uint8_t gunNumber, const char *userId,
|
||||
const char *orderNumber, char *message)
|
||||
{
|
||||
if (gunNumber < 1 || gunNumber > GUN_MAX_CNT) {
|
||||
if (message) strcpy(message, "参数错误:枪编号无效");
|
||||
return -1;
|
||||
}
|
||||
|
||||
v_mydebug_char_ctrl(gunNumber-1 , CMD_ON ,0);
|
||||
|
||||
if (message) strcpy(message, "充电启动成功(模拟)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取系统故障数据
|
||||
* @param response 输出故障信息响应结构体
|
||||
* @retval 无
|
||||
*/
|
||||
void tcp_get_system_fault_data(tcp_fault_info_response_t *response)
|
||||
{
|
||||
REAL_FAULT_DATA_T rl_data;
|
||||
U8_T valid_fault_count = 0;
|
||||
int i, j;
|
||||
|
||||
if (response == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(response, 0, sizeof(tcp_fault_info_response_t));
|
||||
v_get_fault_data(&rl_data); //获取故障信息
|
||||
|
||||
|
||||
/* 首先统计有效故障数量(e_mag != 0) */
|
||||
for (i = 0; i < CURR_FAULT_MAX_CNT; i++) {
|
||||
if (rl_data.fault_data[i].e_mag != 0) {
|
||||
valid_fault_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* 填充响应结构体 */
|
||||
response->faultCount = valid_fault_count;
|
||||
|
||||
/* 分配故障项数组内存 */
|
||||
if (valid_fault_count > 0) {
|
||||
response->faults = (tcp_fault_item_t *)pvPortMalloc(valid_fault_count * sizeof(tcp_fault_item_t));
|
||||
if (response->faults == NULL) {
|
||||
TCP_PRINT("Failed to allocate memory for fault items\r\r\n");
|
||||
response->faultCount = 0;
|
||||
return;
|
||||
}
|
||||
memset(response->faults, 0, valid_fault_count * sizeof(tcp_fault_item_t));
|
||||
|
||||
/* 转换故障数据格式 */
|
||||
for (i = 0, j = 0; i < CURR_FAULT_MAX_CNT && j < valid_fault_count; i++) {
|
||||
Fault_data *fault = &rl_data.fault_data[i];
|
||||
|
||||
/* 跳过无效故障(e_mag == 0) */
|
||||
if (fault->e_mag == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 转换故障位置 */
|
||||
/*
|
||||
E_WHOLE_PILE = 0, //整桩-终端
|
||||
E_WHOLE_HOST = 500, //整桩-主机-功率分配
|
||||
E_GUN = 1000, //枪地址
|
||||
E_CHAR_MDU = 2000, //充电模块地址
|
||||
E_SWH_MDU = 3000, //开关模块地址
|
||||
E_OTHER = 4000, //其他位置
|
||||
*/
|
||||
/* 根据E_FAULT_SITE枚举值判断故障位置 */
|
||||
|
||||
if (fault->e_ingun >= E_OTHER) {
|
||||
snprintf(response->faults[j].location,sizeof(response->faults[j].location) -1,
|
||||
"其他故障");
|
||||
} else if (fault->e_ingun >= E_SWH_MDU) {
|
||||
snprintf(response->faults[j].location,sizeof(response->faults[j].location) -1,
|
||||
"开关模块 %d",fault->e_ingun - E_SWH_MDU);
|
||||
}
|
||||
else if (fault->e_ingun >= E_CHAR_MDU) {
|
||||
snprintf(response->faults[j].location,sizeof(response->faults[j].location) -1,
|
||||
"充电模块 %d",fault->e_ingun - E_CHAR_MDU);
|
||||
}
|
||||
else if (fault->e_ingun >= E_GUN) {
|
||||
snprintf(response->faults[j].location,sizeof(response->faults[j].location) -1,
|
||||
"充电枪 %d",fault->e_ingun - E_GUN);
|
||||
}
|
||||
else if (fault->e_ingun >= E_WHOLE_HOST) {
|
||||
snprintf(response->faults[j].location,sizeof(response->faults[j].location) -1,
|
||||
"整桩主机 %d",fault->e_ingun - E_WHOLE_HOST);
|
||||
}
|
||||
else {
|
||||
snprintf(response->faults[j].location,sizeof(response->faults[j].location) -1,
|
||||
"整桩终端 %d",fault->e_ingun);
|
||||
}
|
||||
|
||||
snprintf(response->faults[j].code,sizeof(response->faults[j].code) -1,
|
||||
"%d",fault->e_mag);
|
||||
|
||||
char mag[FAULT_GET_MAG_MAX_LEN]= {0};
|
||||
v_get_fault_info(fault->e_mag , mag ,FAULT_GET_MAG_MAX_LEN);
|
||||
|
||||
snprintf(response->faults[j].description,sizeof(response->faults[j].description) -1,
|
||||
"%s",mag);
|
||||
|
||||
|
||||
/* 转换时间格式 */
|
||||
snprintf(response->faults[j].time, sizeof(response->faults[j].time),
|
||||
"%04d-%02d-%02d %02d:%02d:%02d",
|
||||
fault->time.iYear, fault->time.ucMonth, fault->time.ucDay,
|
||||
fault->time.ucHour, fault->time.ucMin, fault->time.ucSec);
|
||||
|
||||
j++; /* 移动到下一个有效故障项 */
|
||||
}
|
||||
} else {
|
||||
response->faults = NULL;
|
||||
}
|
||||
|
||||
TCP_PRINT("Got %u valid faults from 0 total faults\r\r\n", valid_fault_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 处理自定义数据
|
||||
* @param request 自定义数据请求
|
||||
* @param response 自定义数据响应
|
||||
* @retval 0成功,-1失败
|
||||
*/
|
||||
int tcp_process_custom_data(const tcp_custom_data_t *request, tcp_custom_data_t *response)
|
||||
{
|
||||
if (request == NULL || response == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
TCP_PRINT("Processing custom data:\r\r\n");
|
||||
TCP_PRINT(" functionContent: %s\r\r\n", request->functionContent);
|
||||
TCP_PRINT(" functionField: %s\r\r\n", request->functionField);
|
||||
TCP_PRINT(" functionParams: %s\r\r\n", request->functionParams);
|
||||
|
||||
/* 复制请求数据到响应(根据用户要求,字段内容可以自定义) */
|
||||
memset(response, 0, sizeof(tcp_custom_data_t));
|
||||
|
||||
/* 这里可以根据实际需求处理自定义数据 */
|
||||
/* 示例:如果functionContent是"哈哈哈",则回复"呵呵呵" */
|
||||
if(request->functionField[0] == '\0') //无数据
|
||||
{
|
||||
TCP_PRINT("functionField is null\r\n");
|
||||
//request->functionField
|
||||
//response->functionContent
|
||||
//request->functionParams
|
||||
}
|
||||
else if(strcmp(request->functionField, "reboot") == 0)
|
||||
{
|
||||
v_sys_reboot();
|
||||
}
|
||||
else if(strcmp(request->functionField, "paramInit") == 0)
|
||||
{
|
||||
v_public_param_init();
|
||||
strncpy(response->functionField , request->functionField , sizeof(response->functionField)-1);
|
||||
strncpy(response->functionContent , "success" , sizeof(response->functionContent)-1);
|
||||
strncpy(response->functionParams , "success" , sizeof(response->functionParams)-1);
|
||||
}
|
||||
#if BS_OCPP_EN
|
||||
else if(strcmp(request->functionField, "ocpp_cfg") == 0) //
|
||||
{
|
||||
strncpy(response->functionField , request->functionField , sizeof(response->functionField)-1);
|
||||
strncpy(response->functionContent , request->functionContent , sizeof(response->functionContent)-1);
|
||||
|
||||
if(strcmp(request->functionContent, "getInfo") == 0) //获取信息
|
||||
{
|
||||
v_get_ocpp_cfg_info(response->functionParams ,sizeof(response->functionParams)-1);
|
||||
}
|
||||
else if(request->functionContent[0] != '\0') //不为空 则是设置命令
|
||||
{
|
||||
if(u8_set_ocpp_cfg_info(request->functionContent,request->functionParams) == 1)
|
||||
{
|
||||
strncpy(response->functionParams ,success , sizeof(response->functionContent)-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(response->functionParams ,failure , sizeof(response->functionContent)-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
strncpy(response->functionField , request->functionField , sizeof(response->functionField)-1);
|
||||
strncpy(response->functionContent , "unknown" , sizeof(response->functionContent)-1);
|
||||
}
|
||||
|
||||
TCP_PRINT("Custom data processed:\r\r\n");
|
||||
TCP_PRINT(" functionContent: %s\r\r\n", response->functionContent);
|
||||
TCP_PRINT(" functionField: %s\r\r\n", response->functionField);
|
||||
TCP_PRINT(" functionParams: %s\r\r\n", response->functionParams);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t tcp_history_get_total_count(const char *historyType)
|
||||
{
|
||||
if (historyType == NULL) {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
if (strcmp(historyType, "fault") == 0) {
|
||||
return u16_fault_get_his_count();
|
||||
}
|
||||
|
||||
if (strcmp(historyType, "charging") == 0) {
|
||||
v_chg_order_flash_init();
|
||||
return v_get_chg_order_count();
|
||||
}
|
||||
|
||||
if (strcmp(historyType, "card") == 0) {
|
||||
uint32_t cnt = 0u;
|
||||
card_init();
|
||||
if (card_get_count(&cnt) == CARD_STATUS_OK) {
|
||||
if (cnt > 0xFFFFu) {
|
||||
return 0xFFFFu;
|
||||
}
|
||||
return (uint16_t)cnt;
|
||||
}
|
||||
return 0u;
|
||||
}
|
||||
|
||||
return 0u;
|
||||
}
|
||||
|
||||
static void tcp_history_sanitize_commas(char *s)
|
||||
{
|
||||
/* 协议content字段内不得出现英文逗号,否则上位机会split(',')解析出错 */
|
||||
if (s == NULL) {
|
||||
return;
|
||||
}
|
||||
while (*s != '\0') {
|
||||
if (*s == ',') {
|
||||
*s = ';';
|
||||
}
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
static void tcp_history_format_comm_time(const Comm_Time *t, char *buf, size_t bufSize)
|
||||
{
|
||||
if (t == NULL || buf == NULL || bufSize == 0u) {
|
||||
return;
|
||||
}
|
||||
(void)snprintf(buf, bufSize,
|
||||
"%04d-%02d-%02d %02d:%02d:%02d",
|
||||
(int)t->iYear,
|
||||
(int)t->ucMonth,
|
||||
(int)t->ucDay,
|
||||
(int)t->ucHour,
|
||||
(int)t->ucMin,
|
||||
(int)t->ucSec);
|
||||
buf[bufSize - 1u] = '\0';
|
||||
}
|
||||
|
||||
/* 将订单中的停止原因转为可读文本:仅取 e_stop_reason[] 中第一个非空项(与多条 | 拼接相比更短,利于协议长度) */
|
||||
static void tcp_history_build_stop_reason_text(const S_LOG_DATA *order, char *dst, size_t dstSize)
|
||||
{
|
||||
if (order == NULL || dst == NULL || dstSize == 0u) {
|
||||
return;
|
||||
}
|
||||
dst[0] = '\0';
|
||||
|
||||
for (int i = 0; i < NUM_1; i++) {
|
||||
E_FAULT_INFO code = order->e_stop_reason[i];
|
||||
if (code == E_FAULT_NULL) {
|
||||
continue;
|
||||
}
|
||||
char frag[128] = {0};
|
||||
v_get_fault_info(code, frag, (U16_T)sizeof(frag));
|
||||
if (frag[0] == '\0') {
|
||||
(void)snprintf(frag, sizeof(frag), "%d", (int)code);
|
||||
}
|
||||
tcp_history_sanitize_commas(frag);
|
||||
(void)strncpy(dst, frag, dstSize - 1u);
|
||||
dst[dstSize - 1u] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
(void)strncpy(dst, "-", dstSize - 1u);
|
||||
dst[dstSize - 1u] = '\0';
|
||||
}
|
||||
|
||||
uint16_t tcp_history_build_records(const char *historyType,
|
||||
uint16_t startIndex,
|
||||
uint16_t fetchCount,
|
||||
char (*time_buf)[HISTORY_TIME_STR_SIZE],
|
||||
char (*content_buf)[HISTORY_CONTENT_STR_SIZE],
|
||||
uint8_t *outIncludeTime,
|
||||
uint16_t *outTotalCount)
|
||||
{
|
||||
uint16_t totalCount = 0u;
|
||||
uint16_t wantedCount = 0u;
|
||||
uint16_t filledCount = 0u;
|
||||
uint8_t includeTime = 0u;
|
||||
|
||||
if (historyType == NULL || time_buf == NULL || content_buf == NULL || outIncludeTime == NULL || outTotalCount == NULL) {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
memset(time_buf, 0, (size_t)HISTORY_QUERY_MAX_RECORDS * (size_t)HISTORY_TIME_STR_SIZE);
|
||||
memset(content_buf, 0, (size_t)HISTORY_QUERY_MAX_RECORDS * (size_t)HISTORY_CONTENT_STR_SIZE);
|
||||
|
||||
if (strcmp(historyType, "fault") == 0) {
|
||||
includeTime = 1u;
|
||||
totalCount = u16_fault_get_his_count();
|
||||
} else if (strcmp(historyType, "charging") == 0) {
|
||||
includeTime = 1u;
|
||||
v_chg_order_flash_init();
|
||||
totalCount = v_get_chg_order_count();
|
||||
} else if (strcmp(historyType, "card") == 0) {
|
||||
includeTime = 0u;
|
||||
uint32_t cnt = 0u;
|
||||
card_init();
|
||||
if (card_get_count(&cnt) == CARD_STATUS_OK) {
|
||||
totalCount = (cnt > 0xFFFFu) ? 0xFFFFu : (uint16_t)cnt;
|
||||
} else {
|
||||
totalCount = 0u;
|
||||
}
|
||||
} else {
|
||||
*outIncludeTime = 0u;
|
||||
*outTotalCount = 0u;
|
||||
return 0u;
|
||||
}
|
||||
|
||||
*outIncludeTime = includeTime;
|
||||
*outTotalCount = totalCount;
|
||||
|
||||
if (fetchCount == 0u || totalCount == 0u) {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
wantedCount = fetchCount;
|
||||
if (wantedCount > HISTORY_QUERY_MAX_RECORDS) {
|
||||
wantedCount = HISTORY_QUERY_MAX_RECORDS;
|
||||
}
|
||||
|
||||
if (startIndex >= totalCount) {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
if (wantedCount > (uint16_t)(totalCount - startIndex)) {
|
||||
wantedCount = (uint16_t)(totalCount - startIndex);
|
||||
}
|
||||
|
||||
if (strcmp(historyType, "fault") == 0) {
|
||||
HIS_FAULT_DATA_T hisFault;
|
||||
memset(&hisFault, 0, sizeof(hisFault));
|
||||
|
||||
for (uint16_t i = 0u; i < wantedCount; i++) {
|
||||
uint16_t newest_pos = (uint16_t)(startIndex + i);
|
||||
if (u8_fault_read_his_by_newest(newest_pos, &hisFault) == 0u) {
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(time_buf[i], HISTORY_TIME_STR_SIZE,
|
||||
"%04d-%02d-%02d %02d:%02d:%02d",
|
||||
hisFault.s_occur_time.iYear,
|
||||
hisFault.s_occur_time.ucMonth,
|
||||
hisFault.s_occur_time.ucDay,
|
||||
hisFault.s_occur_time.ucHour,
|
||||
hisFault.s_occur_time.ucMin,
|
||||
hisFault.s_occur_time.ucSec);
|
||||
|
||||
char location[64] = {0};
|
||||
char code[16] = {0};
|
||||
char desc[128] = {0};
|
||||
char actionTypeStr[16] = {0};
|
||||
char value1Str[32] = {0};
|
||||
char value2Str[32] = {0};
|
||||
char field_content[HISTORY_CONTENT_STR_SIZE] = {0};
|
||||
|
||||
if (hisFault.e_site >= E_OTHER) {
|
||||
snprintf(location, sizeof(location), "其他故障");
|
||||
} else if (hisFault.e_site >= E_SWH_MDU) {
|
||||
snprintf(location, sizeof(location), "开关模块 %d", hisFault.e_site - E_SWH_MDU);
|
||||
} else if (hisFault.e_site >= E_CHAR_MDU) {
|
||||
snprintf(location, sizeof(location), "充电模块 %d", hisFault.e_site - E_CHAR_MDU);
|
||||
} else if (hisFault.e_site >= E_GUN) {
|
||||
snprintf(location, sizeof(location), "充电枪 %d", hisFault.e_site - E_GUN);
|
||||
} else if (hisFault.e_site >= E_WHOLE_HOST) {
|
||||
snprintf(location, sizeof(location), "整桩主机 %d", hisFault.e_site - E_WHOLE_HOST);
|
||||
} else {
|
||||
snprintf(location, sizeof(location), "整桩终端 %d", hisFault.e_site);
|
||||
}
|
||||
|
||||
snprintf(code, sizeof(code), "%d", (int)hisFault.e_fault_info);
|
||||
|
||||
v_get_fault_info(hisFault.e_fault_info, desc, (U16_T)sizeof(desc));
|
||||
snprintf(actionTypeStr, sizeof(actionTypeStr), "%d", (int)hisFault.ActType);
|
||||
snprintf(value1Str, sizeof(value1Str), "%d", (int)hisFault.s16_value1);
|
||||
snprintf(value2Str, sizeof(value2Str), "%d", (int)hisFault.s16_value2);
|
||||
|
||||
tcp_history_sanitize_commas(location);
|
||||
tcp_history_sanitize_commas(desc);
|
||||
|
||||
snprintf(field_content, sizeof(field_content),
|
||||
"%s,%s,%s,%s,%s,%s",
|
||||
location,
|
||||
code,
|
||||
desc,
|
||||
actionTypeStr,
|
||||
value1Str,
|
||||
value2Str);
|
||||
|
||||
strncpy(content_buf[i], field_content, HISTORY_CONTENT_STR_SIZE - 1);
|
||||
content_buf[i][HISTORY_CONTENT_STR_SIZE - 1] = '\0';
|
||||
filledCount++;
|
||||
}
|
||||
} else if (strcmp(historyType, "charging") == 0) {
|
||||
S_LOG_DATA order;
|
||||
memset(&order, 0, sizeof(order));
|
||||
|
||||
U32_T lastIndex = v_get_chg_order_last_index();
|
||||
if (lastIndex == 0u) {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
for (uint16_t i = 0u; i < wantedCount; i++) {
|
||||
U32_T offset = (U32_T)(startIndex + i);
|
||||
if (lastIndex <= offset) {
|
||||
break;
|
||||
}
|
||||
U32_T index = lastIndex - offset;
|
||||
if (v_read_chg_order_record(&order, index) != 0u) {
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(time_buf[i], HISTORY_TIME_STR_SIZE,
|
||||
"%04d-%02d-%02d %02d:%02d:%02d",
|
||||
order.EndChargeTime.iYear,
|
||||
order.EndChargeTime.ucMonth,
|
||||
order.EndChargeTime.ucDay,
|
||||
order.EndChargeTime.ucHour,
|
||||
order.EndChargeTime.ucMin,
|
||||
order.EndChargeTime.ucSec);
|
||||
|
||||
char userId[40] = {0};
|
||||
char stopCmd[16] = {0};
|
||||
char tradeNoStr[EVS_MAX_TRADE_LEN + 4] = {0};
|
||||
char preTradeStr[EVS_MAX_TRADE_LEN + 4] = {0};
|
||||
char startTimeStr[HISTORY_TIME_STR_SIZE] = {0};
|
||||
char stopTimeStr[HISTORY_TIME_STR_SIZE] = {0};
|
||||
char stopReasonText[256] = {0};
|
||||
|
||||
const char *uid_src = (const char *)order.u8_user_id;
|
||||
uint16_t n = 0u;
|
||||
while (n < 32u && n < (uint16_t)(sizeof(userId) - 1u) && uid_src[n] != '\0') {
|
||||
userId[n] = uid_src[n];
|
||||
n++;
|
||||
}
|
||||
userId[n] = '\0';
|
||||
|
||||
/* 停机码为 4 字节原始码,可能含 0x00,不能按 C 字符串拷贝,否则上位机看到为空 */
|
||||
(void)snprintf(stopCmd, sizeof(stopCmd), "%d",
|
||||
(unsigned int)order.e_stop_reason[0]);
|
||||
|
||||
{
|
||||
const char *ts = (const char *)order.u8_tradeNo;
|
||||
n = 0u;
|
||||
while (n < (uint16_t)(EVS_MAX_TRADE_LEN - 1u) && n < (uint16_t)(sizeof(tradeNoStr) - 1u) && ts[n] != '\0') {
|
||||
tradeNoStr[n] = ts[n];
|
||||
n++;
|
||||
}
|
||||
tradeNoStr[n] = '\0';
|
||||
}
|
||||
{
|
||||
const char *ps = (const char *)order.u8_preTradeNo;
|
||||
n = 0u;
|
||||
while (n < (uint16_t)(EVS_MAX_TRADE_LEN - 1u) && n < (uint16_t)(sizeof(preTradeStr) - 1u) && ps[n] != '\0') {
|
||||
preTradeStr[n] = ps[n];
|
||||
n++;
|
||||
}
|
||||
preTradeStr[n] = '\0';
|
||||
}
|
||||
|
||||
tcp_history_format_comm_time(&order.StartChargeTime, startTimeStr, sizeof(startTimeStr));
|
||||
tcp_history_format_comm_time(&order.EndChargeTime, stopTimeStr, sizeof(stopTimeStr));
|
||||
|
||||
tcp_history_sanitize_commas(userId);
|
||||
tcp_history_sanitize_commas(stopCmd);
|
||||
tcp_history_sanitize_commas(tradeNoStr);
|
||||
tcp_history_sanitize_commas(preTradeStr);
|
||||
|
||||
tcp_history_build_stop_reason_text(&order, stopReasonText, sizeof(stopReasonText));
|
||||
tcp_history_sanitize_commas(stopReasonText);
|
||||
|
||||
char usedMoneyStr[64] = {0};
|
||||
char usedEnergyStr[64] = {0};
|
||||
snprintf(usedMoneyStr, sizeof(usedMoneyStr), "%u.%04u",
|
||||
(unsigned int)(order.u32_used_money / 10000u),
|
||||
(unsigned int)(order.u32_used_money % 10000u));
|
||||
snprintf(usedEnergyStr, sizeof(usedEnergyStr), "%u.%04u",
|
||||
(unsigned int)(order.u32_used_energy / 10000u),
|
||||
(unsigned int)(order.u32_used_energy % 10000u));
|
||||
|
||||
/*
|
||||
* content 逗号分隔字段顺序(上位机表格不单独展示“停止时间”,与 JSON time 同源):
|
||||
* 订单索引,枪号,开始时间,停止时间,充电时长(分钟),开始SOC,停止SOC,用电量,金额,
|
||||
* 用户ID,设备流水号,平台流水号,停机原因(仅e_stop_reason首条),停机码(u8_stop_cmd四字节HEX共8位)
|
||||
*/
|
||||
char field_content[HISTORY_CONTENT_STR_SIZE] = {0};
|
||||
snprintf(field_content, sizeof(field_content),
|
||||
"%u,%u,%s,%s,%u,%u,%u,%s,%s,%s,%s,%s,%s,%s",
|
||||
(unsigned int)order.u32_index,
|
||||
(unsigned int)order.u8_gunNo,
|
||||
startTimeStr,
|
||||
stopTimeStr,
|
||||
(unsigned int)order.u16_ChargedTime,
|
||||
(unsigned int)order.u8_startSoc,
|
||||
(unsigned int)order.u8_endSoc,
|
||||
usedEnergyStr,
|
||||
usedMoneyStr,
|
||||
userId,
|
||||
tradeNoStr,
|
||||
preTradeStr,
|
||||
stopReasonText,
|
||||
stopCmd);
|
||||
|
||||
strncpy(content_buf[i], field_content, HISTORY_CONTENT_STR_SIZE - 1);
|
||||
content_buf[i][HISTORY_CONTENT_STR_SIZE - 1] = '\0';
|
||||
filledCount++;
|
||||
}
|
||||
} else if (strcmp(historyType, "card") == 0) {
|
||||
uint32_t cnt = 0u;
|
||||
CardInfo *card_list = NULL;
|
||||
|
||||
if (totalCount == 0u) {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
card_list = (CardInfo *)pvPortMalloc(sizeof(CardInfo) * (size_t)totalCount);
|
||||
if (card_list == NULL) {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
memset(card_list, 0, sizeof(CardInfo) * (size_t)totalCount);
|
||||
|
||||
if (card_get_all(card_list, &cnt, totalCount) != CARD_STATUS_OK) {
|
||||
vPortFree(card_list);
|
||||
return 0u;
|
||||
}
|
||||
|
||||
uint16_t u16_cnt = (uint16_t)cnt;
|
||||
if (u16_cnt < totalCount) {
|
||||
totalCount = u16_cnt;
|
||||
*outTotalCount = totalCount;
|
||||
}
|
||||
|
||||
for (uint16_t i = 0u; i < wantedCount; i++) {
|
||||
uint16_t ascPos = (uint16_t)(totalCount - 1u - (uint16_t)(startIndex + i));
|
||||
if (ascPos >= u16_cnt) {
|
||||
break;
|
||||
}
|
||||
|
||||
char cardNum[40] = {0};
|
||||
strncpy(cardNum, card_list[ascPos].card_num, 31);
|
||||
cardNum[31] = '\0';
|
||||
tcp_history_sanitize_commas(cardNum);
|
||||
|
||||
char field_content[HISTORY_CONTENT_STR_SIZE] = {0};
|
||||
snprintf(field_content, sizeof(field_content),
|
||||
"%s,%u,%u",
|
||||
cardNum,
|
||||
(unsigned int)card_list[ascPos].balance,
|
||||
(unsigned int)card_list[ascPos].status);
|
||||
|
||||
strncpy(content_buf[i], field_content, HISTORY_CONTENT_STR_SIZE - 1);
|
||||
content_buf[i][HISTORY_CONTENT_STR_SIZE - 1] = '\0';
|
||||
filledCount++;
|
||||
}
|
||||
|
||||
vPortFree(card_list);
|
||||
card_list = NULL;
|
||||
}
|
||||
|
||||
return filledCount;
|
||||
}
|
||||
|
||||
int tcp_history_clear_records(const char *historyType, char *outMessage, uint32_t outMessageSize)
|
||||
{
|
||||
if (historyType == NULL) {
|
||||
if (outMessage && outMessageSize > 0u) {
|
||||
strncpy(outMessage, "未知historyType", outMessageSize - 1u);
|
||||
outMessage[outMessageSize - 1u] = '\0';
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(historyType, "fault") == 0) {
|
||||
v_fault_clear_his_fault();
|
||||
if (outMessage && outMessageSize > 0u) {
|
||||
strncpy(outMessage, "Fault records cleared", outMessageSize - 1u);
|
||||
outMessage[outMessageSize - 1u] = '\0';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(historyType, "charging") == 0) {
|
||||
v_chg_order_clear_all();
|
||||
if (outMessage && outMessageSize > 0u) {
|
||||
strncpy(outMessage, "Charge records cleared", outMessageSize - 1u);
|
||||
outMessage[outMessageSize - 1u] = '\0';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(historyType, "card") == 0) {
|
||||
CardStatus st = card_clear_all();
|
||||
if (st == CARD_STATUS_OK) {
|
||||
if (outMessage && outMessageSize > 0u) {
|
||||
strncpy(outMessage, "卡信息已清除", outMessageSize - 1u);
|
||||
outMessage[outMessageSize - 1u] = '\0';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (outMessage && outMessageSize > 0u) {
|
||||
snprintf(outMessage, outMessageSize, "Card info clear failed: %d", (int)st);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (outMessage && outMessageSize > 0u) {
|
||||
strncpy(outMessage, "未知historyType", outMessageSize - 1u);
|
||||
outMessage[outMessageSize - 1u] = '\0';
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user