Files
CCU621M/app/plat_comm/ocpp/bs_ocpp_configuration.c
T

1684 lines
80 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.
#include "BS_ocpp_configuration.h"
#include "plat_comm/plat_comm_task.h"
#include "bsp_include.h"
#include "publicdata/publicdata.h"
#include "app_fatfs/fatfs_card.h"
#define OCPP_CONFIG_PRINTF_LOG(fmt, ...) \
MYLOG_MSG(OCPP_PRINT_FLAG,fmt, ##__VA_ARGS__) //任务打印
#if BS_OCPP_EN
S_OCPP_FLASH_CFG_DATA s_ocpp_flash_cfg_data;
OCPP_CONFIG *private_config_data = &s_ocpp_flash_cfg_data.s_ocpp_config_data; //内部指针引用,初始化时赋值全局变量的值
//保存unknown的Key串
char *unknown_tmpbuf[GetConfiguration_NUM] = {NULL};
static const char *phase_to_str(OCPP_CONNECTOR_PHASE phase)
{
switch (phase) {
case ENUM_NotApplicable: return "NotApplicable";
case ENUM_Unknown: return "Unknown";
case ENUM_RST: return "RST";
case ENUM_RTS: return "RTS";
case ENUM_SRT: return "SRT";
case ENUM_STR: return "STR";
case ENUM_TRS: return "TRS";
case ENUM_TSR: return "TSR";
default: return "NotApplicable";
}
}
static U8_T str_to_phase(const char *value, OCPP_CONNECTOR_PHASE *phase)
{
if (value == NULL || phase == NULL) return 0;
if (strcmp(value, "0") == 0 || strcmp(value, "NotApplicable") == 0) { *phase = ENUM_NotApplicable; return 1; }
if (strcmp(value, "1") == 0 || strcmp(value, "Unknown") == 0) { *phase = ENUM_Unknown; return 1; }
if (strcmp(value, "RST") == 0) { *phase = ENUM_RST; return 1; }
if (strcmp(value, "RTS") == 0) { *phase = ENUM_RTS; return 1; }
if (strcmp(value, "SRT") == 0) { *phase = ENUM_SRT; return 1; }
if (strcmp(value, "STR") == 0) { *phase = ENUM_STR; return 1; }
if (strcmp(value, "TRS") == 0) { *phase = ENUM_TRS; return 1; }
if (strcmp(value, "TSR") == 0) { *phase = ENUM_TSR; return 1; }
return 0;
}
static U8_T extract_phase_item(const char *src, char index, char *out, U16_T out_len)
{
char pattern[4] = {0};
const char *start;
U16_T i = 0;
if (src == NULL || out == NULL || out_len == 0) return 0;
pattern[0] = index;
pattern[1] = '.';
pattern[2] = '\0';
start = strstr(src, pattern);
if (start == NULL) return 0;
start += 2;
while (*start && *start != ',' && i < (out_len - 1)) {
out[i++] = *start++;
}
out[i] = '\0';
return (i > 0) ? 1 : 0;
}
static U8_T parse_connector_phase_rotation(const char *value, OCPP_CONNECTOR_PHASE phase_out[3], const OCPP_CONNECTOR_PHASE phase_curr[3])
{
OCPP_CONNECTOR_PHASE p0 = phase_curr[0];
OCPP_CONNECTOR_PHASE p1 = phase_curr[1];
OCPP_CONNECTOR_PHASE p2 = phase_curr[2];
char v0[24] = {0};
char v1[24] = {0};
char v2[24] = {0};
U8_T has_indexed = 0;
has_indexed |= extract_phase_item(value, '0', v0, sizeof(v0));
has_indexed |= extract_phase_item(value, '1', v1, sizeof(v1));
has_indexed |= extract_phase_item(value, '2', v2, sizeof(v2));
if (has_indexed) {
if ((v0[0] != '\0' && str_to_phase(v0, &p0) == 0) ||
(v1[0] != '\0' && str_to_phase(v1, &p1) == 0) ||
(v2[0] != '\0' && str_to_phase(v2, &p2) == 0)) {
return 0;
}
phase_out[0] = p0;
phase_out[1] = p1;
phase_out[2] = p2;
return 1;
}
if (str_to_phase(value, &p1) == 0) return 0;
phase_out[0] = p1;
phase_out[1] = p1;
phase_out[2] = p1;
return 1;
}
/** 去掉字符串首尾空格/制表(就地) */
static void str_trim_inplace(char *s)
{
size_t len;
size_t start = 0;
if (s == NULL || s[0] == '\0')
return;
len = strlen(s);
while (start < len && (s[start] == ' ' || s[start] == '\t'))
start++;
if (start > 0)
memmove(s, s + start, len - start + 1);
len = strlen(s);
while (len > 0 && (s[len - 1] == ' ' || s[len - 1] == '\t' || s[len - 1] == '\r' || s[len - 1] == '\n'))
s[--len] = '\0';
}
/** 逗号分隔 CSL 中与 measurand 完全一致的 token 是否存在(避免 strstr 子串误匹配,如 Current.Import 命中 Current.Offered */
static U8_T meter_values_csl_has_token(const char *value_csl, const char *measurand_str)
{
const char *p;
char token[160];
U16_T ti;
if (value_csl == NULL || measurand_str == NULL || measurand_str[0] == '\0')
return 0;
p = value_csl;
while (*p != '\0')
{
while (*p == ' ' || *p == '\t')
p++;
ti = 0;
while (*p != '\0' && *p != ',' && ti + 1 < sizeof(token))
token[ti++] = *p++;
token[ti] = '\0';
str_trim_inplace(token);
if (token[0] != '\0' && strcmp(token, measurand_str) == 0)
return 1;
if (*p == ',')
p++;
}
return 0;
}
/** 统计逗号分隔列表中非空 token 数量(去首尾空格后) */
static U16_T meter_values_csl_count_nonempty_tokens(const char *value_csl)
{
const char *p;
char token[160];
U16_T ti;
U16_T n = 0;
if (value_csl == NULL)
return 0;
p = value_csl;
while (*p != '\0')
{
while (*p == ' ' || *p == '\t')
p++;
ti = 0;
while (*p != '\0' && *p != ',' && ti + 1 < sizeof(token))
token[ti++] = *p++;
token[ti] = '\0';
str_trim_inplace(token);
if (token[0] != '\0')
n++;
if (*p == ',')
p++;
}
return n;
}
// MeterValues测量项 串数组(标准字符串 只读不可修改。顺序对应枚举顺序,固定不可变更)
const char *OCPP_measurand_str[] =
{
// ------------------- 能量累计类(Register- 文档7.31 核心计费累计项 -------------------
/*{ENUM_EnergyActiveExportRegister, */OCPP_STR_EnergyActiveExportRegister ,//},
/*{ENUM_EnergyActiveImportRegister, */OCPP_STR_EnergyActiveImportRegister ,//},
/*{ENUM_EnergyReactiveExportRegister, */OCPP_STR_EnergyReactiveExportRegister ,//},
/*{ENUM_EnergyReactiveImportRegister, */OCPP_STR_EnergyReactiveImportRegister ,//},
// ------------------- 能量时段类(Interval- 文档7.31 时钟对齐时段项 -------------------
/*{ENUM_EnergyActiveExportInterval, */OCPP_STR_EnergyActiveExportInterval ,//},
/*{ENUM_EnergyActiveImportInterval, */OCPP_STR_EnergyActiveImportInterval ,//},
/*{ENUM_EnergyReactiveExportInterval, */OCPP_STR_EnergyReactiveExportInterval ,//},
/*{ENUM_EnergyReactiveImportInterval, */OCPP_STR_EnergyReactiveImportInterval ,//},
// ------------------- 功率类 - 文档7.31 实时功率监控项 -------------------
/*{ENUM_PowerActiveExport, */OCPP_STR_PowerActiveExport ,//},
/*{ENUM_PowerActiveImport, */OCPP_STR_PowerActiveImport ,//},
/*{ENUM_PowerOffered, */OCPP_STR_PowerOffered ,//},
/*{ENUM_PowerReactiveExport, */OCPP_STR_PowerReactiveExport ,//},
/*{ENUM_PowerReactiveImport, */OCPP_STR_PowerReactiveImport ,//},
/*{ENUM_PowerFactor, */OCPP_STR_PowerFactor ,//},
// ------------------- 电流类 - 文档7.31 实时电流监控项 -------------------
/*{ENUM_CurrentImport, */OCPP_STR_CurrentImport ,//},
/*{ENUM_CurrentExport, */OCPP_STR_CurrentExport ,//},
/*{ENUM_CurrentOffered, */OCPP_STR_CurrentOffered ,//},
// ------------------- 电气参数类 - 文档7.31 基础电气特性项 -------------------
/*{ENUM_Voltage, */OCPP_STR_Voltage ,//},
/*{ENUM_Frequency, */OCPP_STR_Frequency ,//},
// ------------------- 物理/状态量类 - 文档7.31 非电气计量项 -------------------
/*{ENUM_Temperature, */OCPP_STR_Temperature ,//},
/*{ENUM_SoC, */OCPP_STR_SOC ,//},
/*{ENUM_RPM, */OCPP_STR_RPM ,//},
};
//OCPP可配置参数结构体数组
const OCPP_CONFIG_INFO OCPP_config_info[] =
{
{ENUM_NULL, ENUM_SUPPORT_NOT, ENUM_TYPE_INT, "NULL"},
// --------------------------------------------------------
// 核心配置参数(数据类型与功能说明)
// --------------------------------------------------------
{ENUM_ALLOW_OFFLINE_TX_FOR_UNKNOWN_ID, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_ALLOW_OFFLINE_TX_FOR_UNKNOWN_ID}, /* 可选 允许未知用户ID的离线交易 (布尔: 0/1) */
{ENUM_AUTHORIZATION_CACHE_ENABLED, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_AUTHORIZATION_CACHE_ENABLED}, /* 可选 启用本地授权缓存 (布尔: 0/1) */
{ENUM_AUTHORIZE_REMOTE_TX_REQUESTS, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_AUTHORIZE_REMOTE_TX_REQUESTS}, /* 必选 允许远程启动充电事务 (布尔: 0/1) */
{ENUM_BLINK_REPEAT, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_BLINK_REPEAT}, /* 可选 充电桩指示灯闪烁次数 (整数: 次数) */
{ENUM_CLOCK_ALIGNED_DATA_INTERVAL, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_CLOCK_ALIGNED_DATA_INTERVAL}, /* 必选 时钟对齐的数据上报间隔 (整数: 秒) */
{ENUM_CONNECTION_TIME_OUT, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_CONNECTION_TIMEOUT}, /* 必选 TCP连接超时时间 (整数: 秒) */
{ENUM_CONNECTOR_PHASE_ROTATION, ENUM_SUPPORT_YES, ENUM_TYPE_CSL, KEY_CONNECTOR_PHASE_ROTATION}, /* 必选 连接器相位旋转配置 (字符串: L1/L2/L3顺序) */
{ENUM_CONNECTOR_PHASE_ROTATION_MAX_LENGTH, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_CONNECTOR_PHASE_ROTATION_MAX_LENGTH}, /* 可选 相位旋转配置最大长度 (整数: 字节数) */
{ENUM_GET_CONFIGURATION_MAX_KEYS, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_GET_CONFIGURATION_MAX_KEYS}, /* 必选 GetConfiguration请求最大返回Key数 (整数: 数量) */
{ENUM_HEARTBEAT_INTERVAL, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_HEARTBEAT_INTERVAL}, /* 必选 心跳间隔 (整数: 秒) */
{ENUM_LIGHT_INTENSITY, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_LIGHT_INTENSITY}, /* 可选 充电桩灯光亮度 (整数: 百分比) */
{ENUM_LOCAL_AUTHORIZE_OFFLINE, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_LOCAL_AUTHORIZE_OFFLINE}, /* 必选 本地离线授权模式 (布尔: 0/1) */
{ENUM_LOCAL_PRE_AUTHORIZE, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_LOCAL_PRE_AUTHORIZE}, /* 必选 本地预授权模式 (布尔: 0/1) */
{ENUM_MAX_ENERGY_ON_INVALID_ID, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_MAX_ENERGY_ON_INVALID_ID}, /* 可选 无效ID用户的最大允许充电能量 (整数: Wh) */
{ENUM_METER_VALUES_ALIGNED_DATA, ENUM_SUPPORT_YES, ENUM_TYPE_CSL, KEY_METER_VALUES_ALIGNED_DATA}, /* 必选 对齐数据上报的测量项列表 (字符串: 逗号分隔的measurand值) */
{ENUM_METER_VALUES_ALIGNED_DATA_MAX_LENGTH, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_METER_VALUES_ALIGNED_DATA_MAX_LENGTH}, /* 可选 对齐数据列表最大长度 (整数: 字符数) */
{ENUM_METER_VALUES_SAMPLED_DATA, ENUM_SUPPORT_YES, ENUM_TYPE_CSL, KEY_METER_VALUES_SAMPLED_DATA}, /* 必选 采样数据上报的测量项列表 (字符串: 逗号分隔的measurand值) */
{ENUM_METER_VALUES_SAMPLED_DATA_MAX_LENGTH, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_METER_VALUES_SAMPLED_DATA_MAX_LENGTH}, /* 可选 采样数据列表最大长度 (整数: 字符数) */
{ENUM_METER_VALUE_SAMPLE_INTERVAL, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_METER_VALUE_SAMPLE_INTERVAL}, /* 必选 采样间隔 (整数: 秒) */
{ENUM_MINIMUM_STATUS_DURATION, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_MINIMUM_STATUS_DURATION}, /* 可选 状态最小持续时间 (整数: 秒) */
{ENUM_NUMBER_OF_CONNECTORS, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_NUMBER_OF_CONNECTORS}, /* 必选 充电桩连接器数量 (整数: 数量) */
{ENUM_RESET_RETRIES, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_RESET_RETRIES}, /* 必选 复位重试次数 (整数: 次数) */
{ENUM_STOP_TRANSACTION_ON_EV_SIDE_DISCONNECT, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_STOP_TXN_ON_EV_SIDE_DISCONNECT}, /* 必选 EV端断开时停止事务 (布尔: 0/1) */
{ENUM_STOP_TRANSACTION_ON_INVALID_ID, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_STOP_TXN_ON_INVALID_ID}, /* 必选 无效ID时停止事务 (布尔: 0/1) */
{ENUM_STOP_TXN_ALIGNED_DATA, ENUM_SUPPORT_YES, ENUM_TYPE_CSL, KEY_STOP_TXN_ALIGNED_DATA}, /* 必选 事务停止时的对齐数据项 (字符串: 逗号分隔的measurand值) */
{ENUM_STOP_TXN_ALIGNED_DATA_MAX_LENGTH, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_STOP_TXN_ALIGNED_DATA_MAX_LENGTH}, /* 可选 停止事务对齐数据最大长度 (整数: 字符数) */
{ENUM_STOP_TXN_SAMPLED_DATA, ENUM_SUPPORT_YES, ENUM_TYPE_CSL, KEY_STOP_TXN_SAMPLED_DATA}, /* 必选 停止事务时的采样数据项 (字符串: 逗号分隔的measurand值) */
{ENUM_STOP_TXN_SAMPLED_DATA_MAX_LENGTH, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_STOP_TXN_SAMPLED_DATA_MAX_LENGTH}, /* 可选 停止事务采样数据最大长度 (整数: 字符数) */
{ENUM_SUPPORTED_FEATURE_PROFILES, ENUM_SUPPORT_YES, ENUM_TYPE_CSL, KEY_SUPPORTED_FEATURE_PROFILES}, /* 必选 支持的功能配置文件 (字符串: 逗号分隔的FeatureProfile值) */
{ENUM_SUPPORTED_FEATURE_PROFILES_MAX_LENGTH, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_SUPPORTED_FEATURE_PROFILES_MAX_LENGTH}, /* 可选 功能配置文件列表最大长度 (整数: 字符数) */
{ENUM_TRANSACTION_MESSAGE_ATTEMPTS, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_TRANSACTION_MESSAGE_ATTEMPTS}, /* 必选 事务消息重试次数 (整数: 次数) */
{ENUM_TRANSACTION_MESSAGE_RETRY_INTERVAL, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_TRANSACTION_MESSAGE_RETRY_INTERVAL}, /* 必选 事务消息重试间隔 (整数: 秒) */
{ENUM_UNLOCK_CONNECTOR_ON_EV_SIDE_DISCONNECT, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_UNLOCK_CONNECTOR_ON_EV_DISCONNECT}, /* 必选 EV端断开时解锁连接器 (布尔: 0/1) */
{ENUM_WEB_SOCKET_PING_INTERVAL, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_WEBSOCKET_PING_INTERVAL}, /* 可选 WebSocket Ping间隔 (整数: 秒) */
// --------------------------------------------------------
// 本地授权与充电配置管理
// --------------------------------------------------------
{ENUM_LOCAL_AUTH_LIST_ENABLED, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_LOCAL_AUTH_LIST_ENABLED}, /* 必选 启用本地授权列表 (布尔: 0/1) */
{ENUM_LOCAL_AUTH_LIST_MAX_LENGTH, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_LOCAL_AUTH_LIST_MAX_LENGTH}, /* 必选 本地授权列表的最大条目数 (整数) */
{ENUM_SEND_LOCAL_LIST_MAX_LENGTH, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_SEND_LOCAL_LIST_MAX_LENGTH}, /* 必选 发送本地列表的最大条目数 (整数) */
// --------------------------------------------------------
// 连接器与充电行为控制
// --------------------------------------------------------
{ENUM_RESERVE_CONNECTOR_ZERO_SUPPORTED, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_RESERVE_CONNECTOR_ZERO_SUPPORTED}, /* 可选 是否支持预留连接器0 (布尔: 0/1) */
// --------------------------------------------------------
// 充电计划与配置限制
// --------------------------------------------------------
{ENUM_CHARGE_PROFILE_MAX_STACK_LEVEL, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_CHARGE_PROFILE_MAX_STACK_LEVEL}, /* 必选 充电配置最大堆叠层级 (整数) */
{ENUM_CHARGING_SCHEDULE_ALLOWED_RATE_UNIT, ENUM_SUPPORT_YES, ENUM_TYPE_CSL, KEY_CHARGING_SCHEDULE_ALLOWED_RATE_UNIT}, /* 必选 充电速率允许单位 (字符串: "A"或"W") */
{ENUM_CHARGING_SCHEDULE_MAX_PERIODS, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_CHARGING_SCHEDULE_MAX_PERIODS}, /* 必选 充电计划最大时段数 (整数) */
{ENUM_CONNECTOR_SWITCH_3TO1_PHASE_SUPPORTED, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_CONNECTOR_SWITCH_3TO1_PHASE_SUPPORTED}, /* 可选 是否支持三相切单相充电 (布尔: 0/1) */
{ENUM_MAX_CHARGING_PROFILES_INSTALLED, ENUM_SUPPORT_YES, ENUM_TYPE_INT, KEY_MAX_CHARGING_PROFILES_INSTALLED}, /* 必选 最大可安装充电配置数 (整数) */
// --------------------------------------------------------
// 各平台私有配置
// --------------------------------------------------------
{ENUM_QRCODE_TEXT_CONNECTOR1, ENUM_SUPPORT_YES, ENUM_TYPE_CSL, KEY_QRCODE_TEXT_CONNECTOR1}, /* 枪1二维码 */
{ENUM_QRCODE_TEXT_CONNECTOR2, ENUM_SUPPORT_YES, ENUM_TYPE_CSL, KEY_QRCODE_TEXT_CONNECTOR2}, /* 枪2二维码 */
};
/*******************************************************************************
* 名称: u8_find_OCPP_configID
* 功能: 根据字符串查找对应OCPP配置参数的枚举变量
* 参数: *mag OCPP配置参数的键的字符串
* 返回: 返回该键在OCPP_CONFIG_KEY_ID的对应枚举量,若返回ENUM_NULL则未找到该键
* 说明:
******************************************************************************/
OCPP_CONFIG_KEY_ID u8_find_OCPP_configID(const char *mag)
{
if(mag == NULL)
return ENUM_NULL;
OCPP_CONFIG_KEY_ID ret = ENUM_NULL;
for(U8_T i = 1; i < ENUM_OCPP_CONFIG; i++)
{
if(strcmp(OCPP_config_info[i].str_data, mag) == 0)
{
ret = OCPP_config_info[i].u8_keyID;
break;
}
}
return ret;
}
/*******************************************************************************
* 名称: find_OCPP_configMag
* 功能: 根据配置参数的枚举号 找对应字符串 并赋值
* 参数: keyID 配置参数的枚举号
* *mag 要赋值串的指针头
* u16_len 被赋值的key串最大长度
* 返回: -
* 说明:
******************************************************************************/
void find_OCPP_configMag(OCPP_CONFIG_KEY_ID keyID, char *mag, U16_T u16_len)
{
if(mag == NULL)
return;
for(U8_T i = 1; i < ENUM_OCPP_CONFIG; i++)
{
if(OCPP_config_info[i].u8_keyID == keyID)
{
memset(mag , 0, u16_len);
snprintf(mag , u16_len , "%s" , OCPP_config_info[i].str_data);
break;
}
}
return;
}
/*******************************************************************************
* 名称: u8_check_OCPP_configSupport
* 功能: 根据配置参数的枚举号 找是否支持
* 参数: keyID 配置参数的枚举号
* 返回: 是否支持标志
* 说明:
******************************************************************************/
OCPP_CONFIG_SUPPORT u8_check_OCPP_configSupport(OCPP_CONFIG_KEY_ID keyID)
{
OCPP_CONFIG_SUPPORT ret = ENUM_SUPPORT_NOT;
for(U8_T i = 1; i < ENUM_OCPP_CONFIG; i++)
{
if(OCPP_config_info[i].u8_keyID == keyID)
{
ret = OCPP_config_info[i].u8_support;
break;
}
}
return ret;
}
/*******************************************************************************
* 名称: u8_get_bool_value
* 功能: 根据字符串查找对应bool值
* 参数: *mag bool字符串
* 返回: 0-false1-true0xff-非bool值
* 说明:
******************************************************************************/
U8_T u8_get_bool_value(const char *mag)
{
if(strcmp(STR_TRUE, mag) == 0)
return 1;
if(strcmp(STR_true, mag) == 0)
return 1;
if(strcmp(STR_1 , mag) == 0)
return 1;
if(strcmp(STR_FALSE, mag) == 0)
return 0;
if(strcmp(STR_false, mag) == 0)
return 0;
if(strcmp(STR_0 , mag) == 0)
return 0;
return 0xff;
}
/*******************************************************************************
* 名称: operate_get_bool
* 功能: bool类型键的获取值操作,将键值转为字符串,并赋值到应答value串
* 参数: value 键值
* *value_mag 配置参数值的字符串
* u16_len 配置参数值的字符串的最大长度
* 返回:
* 说明:
******************************************************************************/
void operate_get_bool(U8_T value, char *value_mag , U16_T u16_len)
{
// 将布尔值(U8_T)转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%s" , value ? STR_true : STR_false);
}
/*******************************************************************************
* 名称: operate_set_bool
* 功能: bool类型键的修改值操作,将字符串转为bool值,并赋值到value
* 参数: *value 需要被修改的参数
* *value_mag bool字符串
* ocpp_key 被修改的键
* 返回: 参数修改结果 0-Rejected 1-Accepted 2-RebootRequired 3-NotSupported
* 说明:
******************************************************************************/
OCPP_SETCONFIG_RET operate_set_bool(U8_T *value, char *value_mag, OCPP_CONFIG_KEY_ID ocpp_key)
{
// 布尔值解析,0=false1=true0xff=非布尔值
U8_T res_data = u8_get_bool_value(value_mag);
//无效bool值,无法修改参数,返回0-Rejected
if(res_data == 0xff)
{
OCPP_CONFIG_PRINTF_LOG("Set keyID(%d): invalid bool (%s), reject\n", ocpp_key, value_mag);
return ENUM_Rejected;
}
// 赋值
*value = res_data;
OCPP_CONFIG_PRINTF_LOG("Set keyID(%d): bool=%d\n", ocpp_key, res_data);
return ENUM_Accepted;
}
/*******************************************************************************
* 名称: operate_set_integer
* 功能: integer类型键的修改值操作,将字符串转为integer值,并赋值到value
* 参数: *value 需要被修改的参数
* *value_mag integer字符串
* ocpp_key 被修改的键
* 返回: 参数修改结果 0-Rejected 1-Accepted 2-RebootRequired 3-NotSupported
* 说明:
******************************************************************************/
OCPP_SETCONFIG_RET operate_set_integer(U16_T *value, char *value_mag, OCPP_CONFIG_KEY_ID ocpp_key)
{
//将字符串转化为整数
int res_data = atoi(value_mag);
//判断有效性
if(res_data < 0 || res_data > 0xffff)
{
OCPP_CONFIG_PRINTF_LOG("Set keyID(%d): invalid int (%d), reject\n", ocpp_key, res_data);
return ENUM_Rejected;
}
//赋值
*value = res_data;
OCPP_CONFIG_PRINTF_LOG("Set keyID(%d): int=%d\n", ocpp_key, res_data);
return ENUM_Accepted;
}
/*******************************************************************************
* 名称: u8_OCPP_config_operate
* 功能: 对OCPP配置参数进行读或写
* 参数: operate_type 操作类型,ENUM_TYPE_GET--获取参数,ENUM_TYPE_GET--设置参数
* *key_mag 配置参数键的字符串
* *value_mag 配置参数值的字符串
* u16_len 配置参数值的字符串的最大长度
* 返回: 参数修改时:0-Rejected 1-Accepted 2-RebootRequired 3-NotSupported
* 参数获取时 0-readonly-false 1-readonly-ture
* 说明:
******************************************************************************/
U8_T u8_OCPP_config_operate(OCPP_CONFIG_OPERATE operate_type, const char *key_mag, char *value_mag , U16_T u16_len)
{
//空指针 或 操作类型不存在 则return 3
if(key_mag == NULL || value_mag == NULL || (operate_type != ENUM_TYPE_GET && operate_type != ENUM_TYPE_SET))
return ENUM_NotSupported;
OCPP_CONFIG_KEY_ID ocpp_key = u8_find_OCPP_configID(key_mag); //获取键
//ENUM_TYPE_SET:未找到键或不支持键则return 3
if(operate_type == ENUM_TYPE_SET && OCPP_config_info[ocpp_key].u8_support == ENUM_SUPPORT_NOT)
return ENUM_NotSupported;
int res_data;
U8_T ret = ENUM_Accepted;
switch (ocpp_key)
{
////////////////////////////////////////////////////////////////
//必选 bool类型
////////////////////////////////////////////////////////////////
case ENUM_AUTHORIZE_REMOTE_TX_REQUESTS: // 必选 远程启动交易是否需要预授权 (布尔: 0=不需要/1=需要)
{
if(operate_type == ENUM_TYPE_GET) // 获取值
{
//bool类型键的获取值操作
operate_get_bool(private_config_data->u8_AuthorizeRemoteTxRequests, value_mag, u16_len);
ret = ENUM_RnW; //可读写
}
else // 修改值
{
//bool类型键的修改值操作
ret = operate_set_bool(&(private_config_data->u8_AuthorizeRemoteTxRequests), value_mag, ocpp_key);
}
}
break;
case ENUM_LOCAL_AUTHORIZE_OFFLINE: // 必选 离线时是否允许本地授权启动交易 (布尔: 0=不允许/1=允许)
{
if(operate_type == ENUM_TYPE_GET) // 获取值
{
//bool类型键的获取值操作
operate_get_bool(private_config_data->u8_LocalAuthorizeOffline, value_mag, u16_len);
ret = ENUM_RnW; //可读写
}
else // 修改值
{
//bool类型键的修改值操作
ret = operate_set_bool(&(private_config_data->u8_LocalAuthorizeOffline), value_mag, ocpp_key);
}
}
break;
case ENUM_LOCAL_PRE_AUTHORIZE: // 必选 在线时是否无需等待中央系统授权即可本地启动交易 (布尔: 0=需要等待/1=无需等待)
{
if(operate_type == ENUM_TYPE_GET) // 获取值
{
//bool类型键的获取值操作
operate_get_bool(private_config_data->u8_LocalPreAuthorize, value_mag, u16_len);
ret = ENUM_RnW; //可读写
}
else // 修改值
{
//bool类型键的修改值操作
ret = operate_set_bool(&(private_config_data->u8_LocalPreAuthorize), value_mag, ocpp_key);
}
}
break;
case ENUM_STOP_TRANSACTION_ON_EV_SIDE_DISCONNECT: // 必选 EV端断开时是否自动停止交易 (布尔: 0=不自动停止/1=自动停止)
{
if(operate_type == ENUM_TYPE_GET) // 获取值
{
//bool类型键的获取值操作
operate_get_bool(private_config_data->u8_StopTransactionOnEVSideDisconnect, value_mag, u16_len);
ret = ENUM_RnW; //可读写
}
else // 修改值
{
//bool类型键的修改值操作
ret = operate_set_bool(&(private_config_data->u8_StopTransactionOnEVSideDisconnect), value_mag, ocpp_key);
}
}
break;
case ENUM_STOP_TRANSACTION_ON_INVALID_ID: // 必选 收到无效授权状态时是否停止当前交易 (布尔: 0=不停止/1=停止)
{
if(operate_type == ENUM_TYPE_GET) // 获取值
{
//bool类型键的获取值操作
operate_get_bool(private_config_data->u8_StopTransactionOnInvalidId, value_mag, u16_len);
ret = ENUM_RnW; //可读写
}
else // 修改值
{
//bool类型键的修改值操作
ret = operate_set_bool(&(private_config_data->u8_StopTransactionOnInvalidId), value_mag, ocpp_key);
}
}
break;
case ENUM_UNLOCK_CONNECTOR_ON_EV_SIDE_DISCONNECT: // 必选 EV端断开时是否解锁充电点侧连接器 (布尔: 0=不解锁/1=解锁)
{
if(operate_type == ENUM_TYPE_GET) // 获取值
{
//bool类型键的获取值操作
operate_get_bool(private_config_data->u8_UnlockConnectorOnEVSideDisconnect, value_mag, u16_len);
ret = ENUM_RnW; //可读写
}
else // 修改值
{
//bool类型键的修改值操作
ret = operate_set_bool(&(private_config_data->u8_UnlockConnectorOnEVSideDisconnect), value_mag, ocpp_key);
}
}
break;
case ENUM_LOCAL_AUTH_LIST_ENABLED: // 必选 是否启用本地授权列表 (布尔: 0=不启用/1=启用)
{
if(operate_type == ENUM_TYPE_GET) // 获取值
{
//bool类型键的获取值操作
operate_get_bool(private_config_data->u8_LocalAuthListEnabled, value_mag, u16_len);
ret = ENUM_RnW; //可读写
}
else // 修改值
{
//bool类型键的修改值操作
ret = operate_set_bool(&(private_config_data->u8_LocalAuthListEnabled), value_mag, ocpp_key);
}
}
break;
////////////////////////////////////////////////////////////////
//必选 integer类型
////////////////////////////////////////////////////////////////
case ENUM_CLOCK_ALIGNED_DATA_INTERVAL: // 必选 时钟对齐数据间隔 (整数: 秒)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_ClockAlignedDataInterval;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_RnW; //可读写
}
else //修改值
{
//integer类型键的修改值操作
ret = operate_set_integer(&(private_config_data->u16_ClockAlignedDataInterval), value_mag, ocpp_key);
}
}
break;
case ENUM_CONNECTION_TIME_OUT: // 必选 准备状态超时自动取消交易时间 (整数: 秒)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_ConnectionTimeOut;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_RnW; //可读写
}
else //修改值
{
//integer类型键的修改值操作
ret = operate_set_integer(&(private_config_data->u16_ConnectionTimeOut), value_mag, ocpp_key);
}
}
break;
case ENUM_GET_CONFIGURATION_MAX_KEYS: // 必选 单个GetConfiguration请求最大键数量 (整数: 个)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_GetConfigurationMaxKeys;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_R_Only; //只读
}
else //修改值
{
//只读键不支持修改
OCPP_CONFIG_PRINTF_LOG("RO keyId:%d, set NS\n",ocpp_key);
ret = ENUM_NotSupported;
}
}
break;
case ENUM_HEARTBEAT_INTERVAL: // 必选 心跳间隔 (整数: 秒)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_HeartbeatInterval;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_RnW; //可读写
}
else //修改值
{
//integer类型键的修改值操作
ret = operate_set_integer(&(private_config_data->u16_HeartbeatInterval), value_mag, ocpp_key);
}
}
break;
case ENUM_METER_VALUE_SAMPLE_INTERVAL: // 必选 计量数据采样间隔 (整数: 秒)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_MeterValueSampleInterval;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_RnW; //可读写
}
else //修改值
{
//integer类型键的修改值操作
ret = operate_set_integer(&(private_config_data->u16_MeterValueSampleInterval), value_mag, ocpp_key);
}
}
break;
case ENUM_NUMBER_OF_CONNECTORS: // 必选 充电点物理连接器数量 (整数: 个)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_NumberOfConnectors;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_R_Only; //只读
}
else //修改值
{
//只读键不支持修改
OCPP_CONFIG_PRINTF_LOG("RO keyId:%d, set NS\n",ocpp_key);
ret = ENUM_NotSupported;
}
}
break;
case ENUM_RESET_RETRIES: // 必选 充电点复位失败后重试次数 (整数: 次)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_ResetRetries;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_RnW; //可读写
}
else //修改值
{
//integer类型键的修改值操作
ret = operate_set_integer(&(private_config_data->u16_ResetRetries), value_mag, ocpp_key);
}
}
break;
case ENUM_TRANSACTION_MESSAGE_ATTEMPTS: // 必选 交易消息提交失败后重试次数 (整数: 次)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_TransactionMessageAttempts;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_RnW; //可读写
}
else //修改值
{
//integer类型键的修改值操作
ret = operate_set_integer(&(private_config_data->u16_TransactionMessageAttempts), value_mag, ocpp_key);
}
}
break;
case ENUM_TRANSACTION_MESSAGE_RETRY_INTERVAL: // 必选 交易消息重试间隔 (整数: 秒)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_TransactionMessageRetryInterval;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_RnW; //可读写
}
else //修改值
{
//integer类型键的修改值操作
ret = operate_set_integer(&(private_config_data->u16_TransactionMessageRetryInterval), value_mag, ocpp_key);
}
}
break;
case ENUM_LOCAL_AUTH_LIST_MAX_LENGTH: // 必选 本地授权列表最大存储条目数 (整数: 条)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_LocalAuthListMaxLength;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_R_Only; //只读
}
else //修改值
{
//只读键不支持修改
OCPP_CONFIG_PRINTF_LOG("RO keyId:%d, set NS\n",ocpp_key);
ret = ENUM_NotSupported;
}
}
break;
case ENUM_SEND_LOCAL_LIST_MAX_LENGTH: // 必选 单个SendLocalList请求最大发送条目数 (整数: 条)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_SendLocalListMaxLength;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_R_Only; //只读
}
else //修改值
{
//只读键不支持修改
OCPP_CONFIG_PRINTF_LOG("RO keyId:%d, set NS\n",ocpp_key);
ret = ENUM_NotSupported;
}
}
break;
case ENUM_CHARGE_PROFILE_MAX_STACK_LEVEL: // 必选 充电配置最大堆叠层级 (整数: 层)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_ChargeProfileMaxStackLevel;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_R_Only; //只读
}
else //修改值
{
//只读键不支持修改
OCPP_CONFIG_PRINTF_LOG("RO keyId:%d, set NS\n",ocpp_key);
ret = ENUM_NotSupported;
}
}
break;
case ENUM_CHARGING_SCHEDULE_MAX_PERIODS: // 必选 单个充电计划最大时段数 (整数: 个)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_ChargingScheduleMaxPeriods;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_R_Only; //只读
}
else //修改值
{
//只读键不支持修改
OCPP_CONFIG_PRINTF_LOG("RO keyId:%d, set NS\n",ocpp_key);
ret = ENUM_NotSupported;
}
}
break;
case ENUM_MAX_CHARGING_PROFILES_INSTALLED: // 必选 同时可安装的充电配置最大数量 (整数: 个)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_MaxChargingProfilesInstalled;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_R_Only; //只读
}
else //修改值
{
//只读键不支持修改
OCPP_CONFIG_PRINTF_LOG("RO keyId:%d, set NS\n",ocpp_key);
ret = ENUM_NotSupported;
}
}
break;
////////////////////////////////////////////////////////////////
//必选 CSL类型
////////////////////////////////////////////////////////////////
case ENUM_CONNECTOR_PHASE_ROTATION: // 必选 停止事务时的采样数据项 (字符串: 逗号分隔的measurand值)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
memset(value_mag , 0, u16_len);
snprintf(value_mag, u16_len, "0.%s,1.%s,2.%s",
phase_to_str(private_config_data->enum_ConnectorPhaseRotation[0]),
phase_to_str(private_config_data->enum_ConnectorPhaseRotation[1]),
phase_to_str(private_config_data->enum_ConnectorPhaseRotation[2]));
ret = ENUM_RnW; //可读写
}
else //修改值
{
OCPP_CONNECTOR_PHASE phase_new[3] = {0};
if (parse_connector_phase_rotation(value_mag, phase_new, private_config_data->enum_ConnectorPhaseRotation))
{
private_config_data->enum_ConnectorPhaseRotation[0] = phase_new[0];
private_config_data->enum_ConnectorPhaseRotation[1] = phase_new[1];
private_config_data->enum_ConnectorPhaseRotation[2] = phase_new[2];
ret = ENUM_Accepted;
}
else
{
OCPP_CONFIG_PRINTF_LOG("Set meter phase seq unsupported(%s), reject\n", value_mag);
ret = ENUM_Rejected;
}
}
}
break;
case ENUM_METER_VALUES_ALIGNED_DATA: // 必选 对齐数据上报的测量项列表 (字符串: 逗号分隔的measurand值)
case ENUM_METER_VALUES_SAMPLED_DATA: // 必选 采样数据上报的测量项列表 (字符串: 逗号分隔的measurand值)
case ENUM_STOP_TXN_ALIGNED_DATA: // 必选 事务停止时的对齐数据项 (字符串: 逗号分隔的measurand值)
case ENUM_STOP_TXN_SAMPLED_DATA: // 必选 停止事务时的采样数据项 (字符串: 逗号分隔的measurand值)
{
//不同数据单元对应不同bit位 计算对应bit是哪一位
U8_T p_bit = 0;
switch(ocpp_key)
{
case ENUM_METER_VALUES_ALIGNED_DATA:
p_bit = 0;
break;
case ENUM_METER_VALUES_SAMPLED_DATA:
p_bit = 1;
break;
case ENUM_STOP_TXN_ALIGNED_DATA:
p_bit = 2;
break;
case ENUM_STOP_TXN_SAMPLED_DATA:
p_bit = 3;
break;
default:
break;
}
if(operate_type == ENUM_TYPE_GET) //获取值
{
//遍历所有测量项 遇到需要的则拼接字符串
for(U8_T i = 0; i < ENUM_measurand_Num; i++)
{
//当前遍历到的测量项 需要包含在该数据单元
if(private_config_data->u8_MeterValuesMeasurandNeed[i] & (1 << p_bit))
{
U16_T value_len = strlen(value_mag);
//已拼接过字符串,从后面加逗号继续拼接
if(value_len)
{
snprintf(value_mag + value_len, u16_len - value_len , ",%s" , OCPP_measurand_str[i]);
}
else //第一次 直接赋值
{
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%s" , OCPP_measurand_str[i]);
}
}
}
ret = ENUM_RnW; //可读写
}
else //修改值
{
U16_T max_allowed = 0;
if (ocpp_key == ENUM_METER_VALUES_SAMPLED_DATA)
max_allowed = private_config_data->u16_MeterValuesSampledDataMaxLength;
else if (ocpp_key == ENUM_METER_VALUES_ALIGNED_DATA)
max_allowed = private_config_data->u16_MeterValuesAlignedDataMaxLength;
else if (ocpp_key == ENUM_STOP_TXN_SAMPLED_DATA)
max_allowed = private_config_data->u16_StopTxnSampledDataMaxLength;
else if (ocpp_key == ENUM_STOP_TXN_ALIGNED_DATA)
max_allowed = private_config_data->u16_StopTxnAlignedDataMaxLength;
if (max_allowed > 0)
{
U16_T tok_cnt = meter_values_csl_count_nonempty_tokens(value_mag);
if (tok_cnt > max_allowed)
{
OCPP_CONFIG_PRINTF_LOG("CSL key %d: measurand cnt %u > MaxLength %u, reject\n",
ocpp_key, (unsigned)tok_cnt, (unsigned)max_allowed);
ret = ENUM_Rejected;
break;
}
}
OCPP_CONFIG_PRINTF_LOG("Set cfg: ENUM_measurand_Num list:\n");
for (U8_T i = 0, str_find; i < ENUM_measurand_Num; i++)
{
str_find = meter_values_csl_has_token(value_mag, OCPP_measurand_str[i]) ? 1 : 0;
private_config_data->u8_MeterValuesMeasurandNeed[i] &= ~(1 << p_bit);
if (str_find)
{
private_config_data->u8_MeterValuesMeasurandNeed[i] |= (1 << p_bit);
OCPP_CONFIG_PRINTF_LOG("%d, ", i);
}
}
OCPP_CONFIG_PRINTF_LOG("\n");
}
}
break;
case ENUM_SUPPORTED_FEATURE_PROFILES: // 必选 停止事务时的采样数据项 (字符串: 逗号分隔的measurand值)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//只读键 固定回复
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%s" , "Core,FirmwareManagement,LocalAuthListManagement,Reservation,SmartCharging,RemoteTrigger");
ret = ENUM_R_Only; //只读
}
else //修改值
{
//只读键不支持修改
OCPP_CONFIG_PRINTF_LOG("RO keyId:%d, set NS\n",ocpp_key);
ret = ENUM_NotSupported;
}
}
break;
case ENUM_CHARGING_SCHEDULE_ALLOWED_RATE_UNIT: // 必选 停止事务时的采样数据项 (字符串: 逗号分隔的measurand值)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//只读键 固定回复
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%s" , "Power");
ret = ENUM_R_Only; //只读
}
else //修改值
{
//只读键不支持修改
OCPP_CONFIG_PRINTF_LOG("RO keyId:%d, set NS\n",ocpp_key);
ret = ENUM_NotSupported;
}
}
break;
////////////////////////////////////////////////////
//可选 bool类型
////////////////////////////////////////////////////
case ENUM_ALLOW_OFFLINE_TX_FOR_UNKNOWN_ID: // 可选 是否允许未知ID用户离线启动交易 (布尔: 0=不允许/1=允许)
{
if(operate_type == ENUM_TYPE_GET) // 获取值
{
//bool类型键的获取值操作
operate_get_bool(private_config_data->u8_AllowOfflineTxForUnknownId, value_mag, u16_len);
ret = ENUM_RnW; //可读写
}
else // 修改值
{
//bool类型键的修改值操作
ret = operate_set_bool(&(private_config_data->u8_AllowOfflineTxForUnknownId), value_mag, ocpp_key);
}
}
break;
case ENUM_AUTHORIZATION_CACHE_ENABLED: // 可选 是否启用本地授权缓存 (布尔: 0=不启用/1=启用)
{
if(operate_type == ENUM_TYPE_GET) // 获取值
{
//bool类型键的获取值操作
operate_get_bool(private_config_data->u8_AuthorizationCacheEnabled, value_mag, u16_len);
ret = ENUM_RnW; //可读写
}
else // 修改值
{
//bool类型键的修改值操作
ret = operate_set_bool(&(private_config_data->u8_AuthorizationCacheEnabled), value_mag, ocpp_key);
}
}
break;
case ENUM_RESERVE_CONNECTOR_ZERO_SUPPORTED: // 可选 是否支持对0号连接器进行预约 (布尔: 0=不支持/1=支持)
{
if(operate_type == ENUM_TYPE_GET) // 获取值
{
//bool类型键的获取值操作
operate_get_bool(private_config_data->u8_ReserveConnectorZeroSupported, value_mag, u16_len);
ret = ENUM_R_Only; //只读
}
else //修改值
{
//只读键不支持修改
OCPP_CONFIG_PRINTF_LOG("RO keyId:%d, set NS\n",ocpp_key);
ret = ENUM_NotSupported;
}
}
break;
case ENUM_CONNECTOR_SWITCH_3TO1_PHASE_SUPPORTED: // 可选 是否支持交易期间三相切单相充电 (布尔: 0=不支持/1=支持)
{
if(operate_type == ENUM_TYPE_GET) // 获取值
{
//bool类型键的获取值操作
operate_get_bool(private_config_data->u8_ConnectorSwitch3to1PhaseSupported, value_mag, u16_len);
ret = ENUM_R_Only; //只读
}
else //修改值
{
//只读键不支持修改
OCPP_CONFIG_PRINTF_LOG("RO keyId:%d, set NS\n",ocpp_key);
ret = ENUM_NotSupported;
}
}
break;
////////////////////////////////////////////////////
//可选 integer类型
////////////////////////////////////////////////////
case ENUM_BLINK_REPEAT: // 可选 充电点指示灯闪烁次数 (整数: 次)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_BlinkRepeat;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_RnW; //可读写
}
else //修改值
{
//integer类型键的修改值操作
ret = operate_set_integer(&(private_config_data->u16_BlinkRepeat), value_mag, ocpp_key);
}
}
break;
case ENUM_CONNECTOR_PHASE_ROTATION_MAX_LENGTH: // 可选 相位旋转配置最大条目数 (整数: 条)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_ConnectorPhaseRotationMaxLength;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_R_Only; //只读
}
else //修改值
{
//只读键不支持修改
OCPP_CONFIG_PRINTF_LOG("RO keyId:%d, set NS\n",ocpp_key);
ret = ENUM_NotSupported;
}
}
break;
case ENUM_LIGHT_INTENSITY: // 可选 充电点灯光亮度 (整数: 百分比)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_LightIntensity;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_RnW; //可读写
}
else //修改值
{
//integer类型键的修改值操作
ret = operate_set_integer(&(private_config_data->u16_LightIntensity), value_mag, ocpp_key);
}
}
break;
case ENUM_MAX_ENERGY_ON_INVALID_ID: // 可选 无效ID用户最大允许充电能量 (整数: Wh)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_MaxEnergyOnInvalidId;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_RnW; //可读写
}
else //修改值
{
//integer类型键的修改值操作
ret = operate_set_integer(&(private_config_data->u16_MaxEnergyOnInvalidId), value_mag, ocpp_key);
}
}
break;
case ENUM_METER_VALUES_ALIGNED_DATA_MAX_LENGTH: // 可选 时钟对齐计量项列表最大长度 (整数: 条)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
res_data = private_config_data->u16_MeterValuesAlignedDataMaxLength;
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_RnW;
}
else
{
ret = operate_set_integer(&(private_config_data->u16_MeterValuesAlignedDataMaxLength), value_mag, ocpp_key);
if (ret == ENUM_Accepted)
{
if (private_config_data->u16_MeterValuesAlignedDataMaxLength > MeterValuesRequest_SV_NUM)
private_config_data->u16_MeterValuesAlignedDataMaxLength = MeterValuesRequest_SV_NUM;
if (private_config_data->u16_MeterValuesAlignedDataMaxLength == 0)
private_config_data->u16_MeterValuesAlignedDataMaxLength = MeterValuesRequest_SV_NUM;
}
}
}
break;
case ENUM_METER_VALUES_SAMPLED_DATA_MAX_LENGTH: // 可选 采样计量项列表最大长度 (整数: 条)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
res_data = private_config_data->u16_MeterValuesSampledDataMaxLength;
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_RnW;
}
else
{
ret = operate_set_integer(&(private_config_data->u16_MeterValuesSampledDataMaxLength), value_mag, ocpp_key);
if (ret == ENUM_Accepted)
{
if (private_config_data->u16_MeterValuesSampledDataMaxLength > MeterValuesRequest_SV_NUM)
private_config_data->u16_MeterValuesSampledDataMaxLength = MeterValuesRequest_SV_NUM;
if (private_config_data->u16_MeterValuesSampledDataMaxLength == 0)
private_config_data->u16_MeterValuesSampledDataMaxLength = MeterValuesRequest_SV_NUM;
}
}
}
break;
case ENUM_MINIMUM_STATUS_DURATION: // 可选 状态稳定后发送通知的最短持续时间 (整数: 秒)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_MinimumStatusDuration;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_RnW; //可读写
}
else //修改值
{
//integer类型键的修改值操作
ret = operate_set_integer(&(private_config_data->u16_MinimumStatusDuration), value_mag, ocpp_key);
}
}
break;
case ENUM_STOP_TXN_ALIGNED_DATA_MAX_LENGTH: // 可选 交易停止时对齐计量项最大长度 (整数: 条)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_StopTxnAlignedDataMaxLength;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_R_Only; //只读
}
else //修改值
{
//只读键不支持修改
OCPP_CONFIG_PRINTF_LOG("RO keyId:%d, set NS\n",ocpp_key);
ret = ENUM_NotSupported;
}
}
break;
case ENUM_STOP_TXN_SAMPLED_DATA_MAX_LENGTH: // 可选 交易停止时采样计量项最大长度 (整数: 条)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_StopTxnSampledDataMaxLength;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_R_Only; //只读
}
else //修改值
{
//只读键不支持修改
OCPP_CONFIG_PRINTF_LOG("RO keyId:%d, set NS\n",ocpp_key);
ret = ENUM_NotSupported;
}
}
break;
case ENUM_SUPPORTED_FEATURE_PROFILES_MAX_LENGTH: // 可选 支持功能配置文件列表最大长度 (整数: 条)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_SupportedFeatureProfilesMaxLength;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_R_Only; //只读
}
else //修改值
{
//只读键不支持修改
OCPP_CONFIG_PRINTF_LOG("RO keyId:%d, set NS\n",ocpp_key);
ret = ENUM_NotSupported;
}
}
break;
case ENUM_WEB_SOCKET_PING_INTERVAL: // 可选 WebSocket Ping间隔 (整数: 秒)
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//获取 赋值给value_mag
res_data = private_config_data->u16_WebSocketPingInterval;
//将整数转化为字符串并赋值给应答value
memset(value_mag , 0, u16_len);
snprintf(value_mag , u16_len , "%d" , res_data);
ret = ENUM_RnW; //可读写
}
else //修改值
{
//integer类型键的修改值操作
ret = operate_set_integer(&(private_config_data->u16_WebSocketPingInterval), value_mag, ocpp_key);
}
}
break;
//
//私有
//
case ENUM_QRCODE_TEXT_CONNECTOR1: // 私有 枪1二维码
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//将二维码字符串赋值给应答value
snprintf(value_mag , NUM_64 , "%s" , private_config_data->QRCodeConnector1);
ret = ENUM_RnW; //可读写
}
else //修改值
{
//将二维码字符串赋值
snprintf(private_config_data->QRCodeConnector1 , NUM_64 , "%s" , value_mag);
ret = ENUM_Accepted;
}
}
break;
case ENUM_QRCODE_TEXT_CONNECTOR2: // 私有 枪2二维码
{
if(operate_type == ENUM_TYPE_GET) //获取值
{
//将二维码字符串赋值给应答value
snprintf(value_mag , NUM_64 , "%s" , private_config_data->QRCodeConnector2);
ret = ENUM_RnW; //可读写
}
else //修改值
{
//将二维码字符串赋值
snprintf(private_config_data->QRCodeConnector2 , NUM_64 , "%s" , value_mag);
ret = ENUM_Accepted;
}
}
break;
default:
break;
}
return ret;
}
/**
* ************************************************************************
* @brief - OCPP flash 存储数据 写入
*
*
*
* @author jiankalka
* @date 2026-01-15
* ************************************************************************
*/
void v_flash_save_ocpp_cfg_data(void)
{
U8_T u8_head[8],err;
U16_T u16_len, u16_crc, i, j;
U32_T u32_addr = DATAFLASH_OCPP_CFG_DATA_ADDR;
u16_len = sizeof(S_OCPP_FLASH_CFG_DATA); //数据长度
u8_head[0] = 0x55;
u8_head[1] = 0xAA;
u8_head[2] = CFG_DATA_VERSION_H;
u8_head[3] = CFG_DATA_VERSION_L;
u8_head[4] = (U8_T)(u16_len >> 8);
u8_head[5] = (U8_T)u16_len;
s32_flash_dataflash_erase_sector(u32_addr); //清空扇区
mSleep(10);
GetCurrentTime(&s_ocpp_flash_cfg_data.time); //获取当前时间
u16_crc = u16_crc_checksum((U8_T *)(&(s_ocpp_flash_cfg_data)), u16_len);
u8_head[6] = (U8_T)(u16_crc >> 8);
u8_head[7] = (U8_T)u16_crc;
for (j=0; j<3; j++) //如果写失败,则重试3次
{
if ((s32_flash_dataflash_write(u32_addr, u8_head, 8) != 0)
|| (s32_flash_dataflash_write(u32_addr+8, (U8_T *)(&(s_ocpp_flash_cfg_data)), u16_len) != 0))
{
continue;
}
else
{
break;
}
}
}
S32_T s32_flash_read_ocpp_cfg_data(void)
{
U8_T u8_head[8],err;
U16_T u16_len, i, j, k;
U32_T u32_addr = DATAFLASH_OCPP_CFG_DATA_ADDR;
u16_len = sizeof(S_OCPP_FLASH_CFG_DATA);
for (i=0; i<3; i++)
{
if ((s32_flash_dataflash_read(u32_addr, u8_head, 8) == 0)
&& (s32_flash_dataflash_read(u32_addr+8, (U8_T *)(&(s_ocpp_flash_cfg_data)), u16_len) == 0))
{
if ((u8_head[0] == 0x55)
&& (u8_head[1] == 0xAA)
&&(u8_head[2] == CFG_DATA_VERSION_H) //版本相同
&& (u8_head[3] == CFG_DATA_VERSION_L)
&& (u16_len == ((u8_head[4]<<8) | u8_head[5])) //长度相同
&& (((u8_head[6]<<8) | u8_head[7]) == u16_crc_checksum((U8_T *)(&(s_ocpp_flash_cfg_data)), u16_len))) //CRC校验正确
{
break;
}
}
}
if (i >= 3) //三份配置数据都没有读取成功,则退出
{
return -1;
}
return 0;
}
void v_flash_ocpp_data_restore()
{
s_ocpp_flash_cfg_data.s_ocpp_charge_data.card_ver = 0;
s_ocpp_flash_cfg_data.s_ocpp_charge_data.s8_ChangeAvailability[0] = 0;
s_ocpp_flash_cfg_data.s_ocpp_charge_data.s8_ChangeAvailability[1] = 0;
strncpy(s_ocpp_flash_cfg_data.s_ocpp_charge_data.chargePointVendor,"iECharge",
sizeof(s_ocpp_flash_cfg_data.s_ocpp_charge_data.chargePointVendor)-1);
// ------------------- 必选boolean类型(U8_T -------------------
private_config_data->u8_AuthorizeRemoteTxRequests = 0; // 只读 远程启动交易是否需要预授权
private_config_data->u8_LocalAuthorizeOffline = 1; // ! 离线时是否允许本地授权启动交易
private_config_data->u8_LocalPreAuthorize = 0; // !在线时是否无需等待中央系统授权即可本地启动交易
private_config_data->u8_StopTransactionOnEVSideDisconnect = 1; // - EV端断开时是否自动停止交易
private_config_data->u8_StopTransactionOnInvalidId = 1; // ! √ 收到无效授权状态时是否停止当前交易
private_config_data->u8_UnlockConnectorOnEVSideDisconnect = 0; // - EV端断开时是否解锁充电点侧连接器
private_config_data->u8_LocalAuthListEnabled = 1; // ! 是否启用本地授权列表
// ------------------- 必选integer类型(U16_T -------------------
private_config_data->u16_ClockAlignedDataInterval = 0; // - 时钟对齐数据间隔(秒)
private_config_data->u16_ConnectionTimeOut = 0; // - 准备状态超时自动取消交易时间(秒)
private_config_data->u16_GetConfigurationMaxKeys = GetConfiguration_NUM;// 只读 单个GetConfiguration请求最大键数量
private_config_data->u16_HeartbeatInterval = 30; // 心跳间隔(秒)
private_config_data->u16_MeterValueSampleInterval = 30; // ! 计量数据采样间隔(秒)
private_config_data->u16_NumberOfConnectors =
g_t_share_data.t_sys_fix_cfg.u8_gunCnt; // 只读 充电点物理连接器数量
private_config_data->u16_ResetRetries = 0; // - 充电点复位失败后重试次数
private_config_data->u16_TransactionMessageAttempts = 0; // - 交易消息提交失败后重试次数
private_config_data->u16_TransactionMessageRetryInterval = 20; // - 交易消息重试间隔(秒)
private_config_data->u16_LocalAuthListMaxLength = CARD_MAX_COUNT; // 只读 本地授权列表最大存储条目数
private_config_data->u16_SendLocalListMaxLength = 10; //只读 单个SendLocalList请求最大发送条目数
private_config_data->u16_ChargeProfileMaxStackLevel = 0; // - 充电配置最大堆叠层级
private_config_data->u16_ChargingScheduleMaxPeriods = 0; // - 单个充电计划最大时段数
private_config_data->u16_MaxChargingProfilesInstalled = 0; // - 同时可安装的充电配置最大数量
// ------------------- 必选CSL类型 -------------------------------
//OCPP_CONNECTOR_PHASE enum_ConnectorPhaseRotation[3]; //各枪电表的连接相序 0整桩 1枪A 2枪B
private_config_data->enum_ConnectorPhaseRotation[0] = ENUM_NotApplicable; // 不适用(单相交流/直流充电桩,非三相场景)
private_config_data->enum_ConnectorPhaseRotation[1] = ENUM_NotApplicable;
private_config_data->enum_ConnectorPhaseRotation[2] = ENUM_NotApplicable;
/*合并 MeterValuesAlignedData、
MeterValuesSampledData、
StopTxnAlignedData、
StopTxnSampledData
MeterValues测量项在以上数据单元是否需要
bit 0 MeterValuesAlignedData是否需要 时钟定点上送
bit 1 MeterValuesSampledData是否需要 周期上送
bit 2 StopTxnAlignedData是否需要 时钟定点上送
bit 3 StopTxnSampledData是否需要 周期上送
*/
// U8_T u8_MeterValuesMeasurandNeed[ENUM_measurand_Num]; // !
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_EnergyActiveExportRegister ] = 0; // 有功电能输出累计值(Wh)- 设备向电网输出的总有功电能累计
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_EnergyActiveImportRegister ] =
E_CFG_MVMN_MeterValuesAlignedData | E_CFG_MVMN_MeterValuesSampledData; // 有功电能输入累计值(Wh)- 电网向设备输入的总有功电能累计
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_EnergyReactiveExportRegister ] = 0; // 无功电能输出累计值(VARh)- 设备向电网输出的总无功电能累计
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_EnergyReactiveImportRegister ] = 0; // 无功电能输入累计值(VARh)- 电网向设备输入的总无功电能累计
// ------------------- 能量时段值(Interval- 文档7.31时段能量类 -------------------
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_EnergyActiveExportInterval ] = 0; // 有功电能输出时段值(Wh)- 单个时钟对齐时段内输出的有功电能
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_EnergyActiveImportInterval ] = 0; // 有功电能输入时段值(Wh)- 单个时钟对齐时段内输入的有功电能
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_EnergyReactiveExportInterval ] = 0; // 无功电能输出时段值(VARh)- 单个时钟对齐时段内输出的无功电能
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_EnergyReactiveImportInterval ] = 0; // 无功电能输入时段值(VARh)- 单个时钟对齐时段内输入的无功电能
// ------------------- 功率类 - 文档7.31功率计量类 -------------------
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_PowerActiveExport ] = 0; // 有功功率输出(W)- 设备向电网输出的实时有功功率
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_PowerActiveImport ] =
E_CFG_MVMN_MeterValuesAlignedData | E_CFG_MVMN_MeterValuesSampledData; // 有功功率输入(W)- 电网向设备输入的实时有功功率
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_PowerOffered ] = 0; // 提供的功率(W)- 充电桩可向EV提供的最大可用有功功率
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_PowerReactiveExport ] = 0; // 无功功率输出(VAR)- 设备向电网输出的实时无功功率
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_PowerReactiveImport ] = 0; // 无功功率输入(VAR)- 电网向设备输入的实时无功功率
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_PowerFactor ] = 0; // 功率因数(无单位,0~1)- 实时有功功率与视在功率的比值
// ------------------- 电流类 - 文档7.31电流计量类 -------------------
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_CurrentImport ] =
E_CFG_MVMN_MeterValuesAlignedData | E_CFG_MVMN_MeterValuesSampledData; // 输入电流(A)- 电网向设备输入的实时电流
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_CurrentExport ] = 0; // 输出电流(A)- 设备向电网输出的实时电流
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_CurrentOffered ] = 0; // 提供的电流(A)- 充电桩可向EV提供的最大可用电流
// ------------------- 电气参数类 - 文档7.31基础电气参数 -------------------
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_Voltage ] =
E_CFG_MVMN_MeterValuesAlignedData | E_CFG_MVMN_MeterValuesSampledData; // 电压(V)- 充电桩输出端的实时线电压
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_Frequency ] = 0; // 电网频率(Hz)- 接入电网的实时频率(50/60Hz)
// ------------------- 物理/状态量类 - 文档7.31非电气计量项 -------------------
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_Temperature ] = 0; // 温度(℃)- 充电桩/EV电池的实时温度(文档标注为℃/℉,默认℃)
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_SoC ] =
E_CFG_MVMN_MeterValuesAlignedData | E_CFG_MVMN_MeterValuesSampledData |
E_CFG_MVMN_StopTxnAlignedData | E_CFG_MVMN_StopTxnSampledData; // 电池剩余电量(%- EV电池的State of Charge0~100%
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_RPM ] = 0; // 转速(转/分钟)- 冷却风扇/泵等设备的实时转速
/*支持的功能配置文件列表
bit 0 :Core(核心) 是否支持
bit 1 FirmwareManagement(固件管理) 是否支持
bit 2 LocalAuthListManagement(本地授权列表管理) 是否支持
bit 3 Reservation(预约) 是否支持
bit 4 SmartCharging(智能充电) 是否支持
bit 5 RemoteTrigger(远程触发) 是否支持
*/
private_config_data->u8_SupportedFeatureProfiles = 0; // - 只读 默认获取时写死
/*充电调度支持的物理量列表
bit 0 'Current'(电流) 是否支持
bit 1 'Power'(功率) 是否支持
*/
private_config_data->ChargingScheduleAllowedChargingRateUnit = 0; // -
// ------------------- 可选boolean类型(U8_T0=false,非0=true -------------------
private_config_data->u8_AllowOfflineTxForUnknownId = 0; //! 是否允许未知ID用户离线启动交易 -离线时直接启动不鉴权
private_config_data->u8_AuthorizationCacheEnabled = 0; //- 是否启用本地授权缓存 (一次充电成功自动在授权缓存保存ID)
private_config_data->u8_ReserveConnectorZeroSupported = 0; //- 是否支持对0号连接器进行预约
private_config_data->u8_ConnectorSwitch3to1PhaseSupported = 0; //- 是否支持交易期间三相切单相充电
// ------------------- 可选integer类型(U16_T,单位见注释) -------------------
private_config_data->u16_BlinkRepeat = 0; //- 充电点指示灯闪烁次数
private_config_data->u16_ConnectorPhaseRotationMaxLength = 0; //- 相位旋转配置最大条目数(补充:可选核心项)
private_config_data->u16_LightIntensity = 0; //- 充电点灯光亮度(百分比)
private_config_data->u16_MaxEnergyOnInvalidId = 0; //- 无效ID用户最大允许充电能量(Wh)
private_config_data->u16_MeterValuesAlignedDataMaxLength = 0; //- 时钟对齐计量项列表最大长度(可选)
private_config_data->u16_MeterValuesSampledDataMaxLength =
MeterValuesRequest_SV_NUM; //! 采样计量项列表最大长度(可选)
private_config_data->u16_MinimumStatusDuration = 0; //- 状态稳定后发送通知的最短持续时间(秒)
private_config_data->u16_StopTxnAlignedDataMaxLength =
MeterValuesRequest_SV_NUM; //- 交易停止时对齐计量项最大长度(可选)
private_config_data->u16_StopTxnSampledDataMaxLength =
MeterValuesRequest_SV_NUM; //- 交易停止时采样计量项最大长度(可选)
private_config_data->u16_SupportedFeatureProfilesMaxLength = 0; //- 支持功能配置文件列表最大长度(可选)
private_config_data->u16_WebSocketPingInterval = 0; //- WebSocket Ping间隔(秒,0表示禁用)
//------------------私有配置------------------------
strncpy(&private_config_data->QRCodeConnector1[0] ,&g_t_share_data.t_sys_var_cfg.QRDisplay[0][0], NUM_64); //√
strncpy(&private_config_data->QRCodeConnector2[0] ,&g_t_share_data.t_sys_var_cfg.QRDisplay[1][0], NUM_64); //√
v_flash_save_ocpp_cfg_data(); //保存参数到flash
}
static void v_ocpp_fix_legacy_meter_values_default(void)
{
U8_T sampled_energy = (private_config_data->u8_MeterValuesMeasurandNeed[ENUM_EnergyActiveImportRegister] & E_CFG_MVMN_MeterValuesSampledData) ? 1 : 0;
U8_T sampled_power = (private_config_data->u8_MeterValuesMeasurandNeed[ENUM_PowerActiveImport] & E_CFG_MVMN_MeterValuesSampledData) ? 1 : 0;
U8_T sampled_current = (private_config_data->u8_MeterValuesMeasurandNeed[ENUM_CurrentImport] & E_CFG_MVMN_MeterValuesSampledData) ? 1 : 0;
U8_T sampled_voltage = (private_config_data->u8_MeterValuesMeasurandNeed[ENUM_Voltage] & E_CFG_MVMN_MeterValuesSampledData) ? 1 : 0;
U8_T sampled_soc = (private_config_data->u8_MeterValuesMeasurandNeed[ENUM_SoC] & E_CFG_MVMN_MeterValuesSampledData) ? 1 : 0;
// 兼容历史固件仅默认上送3项的情况:自动补齐Voltage和SoC
if(sampled_energy && sampled_power && sampled_current && !sampled_voltage && !sampled_soc)
{
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_Voltage] |= (E_CFG_MVMN_MeterValuesAlignedData | E_CFG_MVMN_MeterValuesSampledData);
private_config_data->u8_MeterValuesMeasurandNeed[ENUM_SoC] |= (E_CFG_MVMN_MeterValuesAlignedData | E_CFG_MVMN_MeterValuesSampledData);
v_flash_save_ocpp_cfg_data();
OCPP_CONFIG_PRINTF_LOG("Fix legacy MeterValues default: add Voltage,SoC\n");
}
}
/****************************************************
*函数名称: v_ocpp_init_config_data()
*功能说明: 程序运行前 配置参数初始化
*参数说明:
* 输入参数:
* 输出参数:
****************************************************/
void v_ocpp_init_config_data()
{
memset(&s_ocpp_flash_cfg_data,0,sizeof(S_OCPP_FLASH_CFG_DATA));
private_config_data = &s_ocpp_flash_cfg_data.s_ocpp_config_data; //指针数据初始化 必选配置参数
//读可变配置参数
//v_flash_ocpp_data_restore();//默认使用初始化参数
if (s32_flash_read_ocpp_cfg_data() == -1)
{
v_flash_ocpp_data_restore();
printf("ocpp flash fail,read new\n");
}
else
{
v_ocpp_fix_legacy_meter_values_default();
}
}
#endif