9ceb218f80
Co-authored-by: Cursor <cursoragent@cursor.com>
1684 lines
80 KiB
C
1684 lines
80 KiB
C
#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-false,1-true,0xff-非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=false,1=true,0xff=非布尔值
|
||
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 Charge,0~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_T:0=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 |