/* * Copyright (c) 2025 Linumiz GmbH * * SPDX-License-Identifier: Apache-2.0 */ #include "ocpp_i.h" #if defined(CONFIG_OCPP_PROFILE_SMART_CHARGE) #define CP_SC ",SmartCharging" #else #define CP_SC "" #endif #if defined(CONFIG_OCPP_PROFILE_REMOTE_TRIG) #define CP_RT ",RemoteTrigger" #else #define CP_RT "" #endif #if defined(CONFIG_OCPP_PROFILE_RESERVATION) #define CP_RE ",Reservation" #else #define CP_RE "" #endif #if defined(CONFIG_OCPP_PROFILE_LOCAL_AUTH_LIST) #define CP_LAL ",LocalAuthListManagement" #else #define CP_LAL "" #endif #if defined(CONFIG_OCPP_PROFILE_FIRMWARE_MGNT) #define CP_FM ",FirmwareManagement" #else #define CP_FM "" #endif #define CP_CORE "Core" struct ocpp_cfg_info { enum ocpp_key_type type; bool is_rw; enum ocpp_key key; char *skey; union ocpp_keyval val; }; #define FILL_KEY_TABLE(_type, _rw, _key, _skey, _val)[_key] = \ {.type = _type, .is_rw = _rw, .key = _key, .skey = _skey, .val = {_val}} static struct ocpp_cfg_info cached_key_cfg[OCPP_CFG_END] = { FILL_KEY_TABLE(KEY_TYPE_BOOL, 1, CFG_ALLOW_OFFLINE_TX_FOR_UNKN_ID, "AllowOfflineTxForUnknownId", false), FILL_KEY_TABLE(KEY_TYPE_BOOL, 1, CFG_AUTH_CACHE_ENABLED, "AuthorizationCacheEnabled", false), FILL_KEY_TABLE(KEY_TYPE_BOOL, 0, CFG_AUTH_REMOTE_TX_REQ, "AuthorizeRemoteTxRequests", true), FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_BLINK_REPEAT, "BlinkRepeat", 0), FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_CLK_ALIGN_DATA_INTERVAL, "ClockAlignedDataInterval", 0), FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_CONN_TIMEOUT, "ConnectionTimeOut", 0), FILL_KEY_TABLE(KEY_TYPE_INT, 0, CFG_GETCFG_MAX_KEY, "GetConfigurationMaxKeys", 1), FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_HEARTBEAT_INTERVAL, "HeartbeatInterval", 0), FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_LIGHT_INTENSITY, "LightIntensity", 0), FILL_KEY_TABLE(KEY_TYPE_BOOL, 1, CFG_LOCAL_AUTH_OFFLINE, "LocalAuthorizeOffline", 0), FILL_KEY_TABLE(KEY_TYPE_BOOL, 1, CFG_LOCAL_PREAUTH, "LocalPreAuthorize", 0), FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_MAX_ENERGYON_INVL_ID, "MaxEnergyOnInvalidId", 0), FILL_KEY_TABLE(KEY_TYPE_CSL, 1, CFG_MTR_VAL_ALGIN_DATA, "MeterValuesAlignedData", .str = "0"), FILL_KEY_TABLE(KEY_TYPE_INT, 0, CFG_MTR_VAL_ALGIN_DATA_MAXLEN, "MeterValuesAlignedDataMaxLength", 1), FILL_KEY_TABLE(KEY_TYPE_CSL, 1, CFG_MTR_VAL_SAMPLED_DATA, "MeterValuesSampledData", .str = "0"), FILL_KEY_TABLE(KEY_TYPE_INT, 0, CFG_MTR_VAL_SAMPLED_DATA_MAXLEN, "MeterValuesSampledDataMaxLength", 1), FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_MTR_VAL_SAMPLE_INTERVAL, "MeterValueSampleInterval", 5), FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_MIN_STATUS_DURATION, "MinimumStatusDuration", 0), FILL_KEY_TABLE(KEY_TYPE_INT, 0, CFG_NO_OF_CONNECTORS, "NumberOfConnectors", 0), FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_REST_RETRIES, "ResetRetries", 0), FILL_KEY_TABLE(KEY_TYPE_CSL, 1, CFG_CONN_PHASE_ROT, "ConnectorPhaseRotation", .str = "0"), FILL_KEY_TABLE(KEY_TYPE_INT, 0, CFG_CONN_PHASE_ROT_MAXLEN, "ConnectorPhaseRotationMaxLength", 1), FILL_KEY_TABLE(KEY_TYPE_BOOL, 1, CFG_STOP_TXN_ON_EVSIDE_DISCON, "StopTransactionOnEVSideDisconnect", 0), FILL_KEY_TABLE(KEY_TYPE_BOOL, 1, CFG_STOP_TXN_ON_INVL_ID, "StopTransactionOnInvalidId", 0), FILL_KEY_TABLE(KEY_TYPE_CSL, 1, CFG_STOP_TXN_ALIGNED_DATA, "StopTxnAlignedData", .str = "0"), FILL_KEY_TABLE(KEY_TYPE_INT, 0, CFG_STOP_TXN_ALIGNED_DATA_MAXLEN, "StopTxnAlignedDataMaxLength", 1), FILL_KEY_TABLE(KEY_TYPE_CSL, 0, CFG_SUPPORTED_FEATURE_PROFILE, "SupportedFeatureProfiles", .str = CP_CORE CP_SC CP_RT CP_RE CP_LAL CP_FM), FILL_KEY_TABLE(KEY_TYPE_INT, 0, CFG_SUPPORTED_FEATURE_PROFILE_MAXLEN, "SupportedFeatureProfilesMaxLength", 6), FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_TXN_MSG_ATTEMPTS, "TransactionMessageAttempts", 0), FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_TXN_MSG_RETRY_INTERVAL, "TransactionMessageRetryInterval", 0), FILL_KEY_TABLE(KEY_TYPE_BOOL, 1, CFG_UNLOCK_CONN_ON_EVSIDE_DISCON, "UnlockConnectorOnEVSideDisconnect", 0), FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_WEBSOCK_PING_INTERVAL, "WebSocketPingInterval", 0), /* optional */ }; enum ocpp_key_type ocpp_get_keyval_type(enum ocpp_key key) { return cached_key_cfg[key].type; } enum ocpp_key ocpp_key_to_cfg(const char *skey) { int i; struct ocpp_cfg_info *cfg = cached_key_cfg; for (i = 0; i < OCPP_CFG_END; i++) { if (strncmp(cfg[i].skey, skey, strlen(cfg[i].skey)) == 0) { break; } } return i; } bool ocpp_is_key_rw(enum ocpp_key key) { return cached_key_cfg[key].is_rw; } union ocpp_keyval *ocpp_get_key_val(enum ocpp_key key) { if (key >= OCPP_CFG_END) { return NULL; } return &cached_key_cfg[key].val; } char *ocpp_get_key_literal(enum ocpp_key key) { if (key >= OCPP_CFG_END) { return NULL; } return cached_key_cfg[key].skey; } int ocpp_set_cfg_val(enum ocpp_key key, union ocpp_keyval *val) { enum ocpp_key_type type; struct ocpp_cfg_info *key_cfg; key_cfg = &cached_key_cfg[key]; type = ocpp_get_keyval_type(key); if (type < KEY_TYPE_STR) { key_cfg->val.ival = val->ival; } else { if (key_cfg->val.str) { free(key_cfg->val.str); } key_cfg->val.str = strdup(val->str); } return 0; } int ocpp_update_cfg_val(enum ocpp_key key, union ocpp_keyval *val) { if (key >= OCPP_CFG_END || !cached_key_cfg[key].is_rw) { return -EINVAL; } return ocpp_set_cfg_val(key, val); }