diff --git a/lib/everest/ocpp/include/ocpp/v16/config_key_mapping.hpp b/lib/everest/ocpp/include/ocpp/v16/config_key_mapping.hpp new file mode 100644 index 0000000000..c933939461 --- /dev/null +++ b/lib/everest/ocpp/include/ocpp/v16/config_key_mapping.hpp @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Pionix GmbH and Contributors to EVerest + +#pragma once + +#include +#include +#include +#include + +#include + +namespace ocpp { +namespace v16 { + +/// \brief Represents a mapping from OCPP 1.6 configuration key to OCPP 2.x ComponentVariable +struct V16ToV2Mapping { + std::string v16_key; + v2::ComponentVariable component_variable; +}; + +/// \brief Static mappings from OCPP 1.6 configuration keys to OCPP 2.x ComponentVariable +static const std::vector OCPP16_TO_V2_MAPPINGS = { + // ============================================================================ + // Standard OCPP 1.6 keys + // ============================================================================ + + {"AllowOfflineTxForUnknownId", v2::ControllerComponentVariables::OfflineTxForUnknownIdEnabled}, + {"AuthorizationCacheEnabled", v2::ControllerComponentVariables::AuthCacheCtrlrEnabled}, + {"AuthorizeRemoteTxRequests", v2::ControllerComponentVariables::AuthorizeRemoteStart}, + {"ClockAlignedDataInterval", v2::ControllerComponentVariables::AlignedDataInterval}, + {"ConnectionTimeOut", v2::ControllerComponentVariables::EVConnectionTimeOut}, + {"HeartbeatInterval", v2::ControllerComponentVariables::HeartbeatInterval}, + {"LocalAuthorizeOffline", v2::ControllerComponentVariables::LocalAuthorizeOffline}, + {"LocalPreAuthorize", v2::ControllerComponentVariables::LocalPreAuthorize}, + {"MaxEnergyOnInvalidId", v2::ControllerComponentVariables::MaxEnergyOnInvalidId}, + {"MeterValuesAlignedData", v2::ControllerComponentVariables::AlignedDataMeasurands}, + {"MeterValuesSampledData", v2::ControllerComponentVariables::SampledDataTxUpdatedMeasurands}, + {"MeterValueSampleInterval", v2::ControllerComponentVariables::SampledDataTxUpdatedInterval}, + {"ResetRetries", v2::ControllerComponentVariables::ResetRetries}, + {"StopTransactionOnInvalidId", v2::ControllerComponentVariables::StopTxOnInvalidId}, + {"StopTxnAlignedData", v2::ControllerComponentVariables::AlignedDataTxEndedMeasurands}, + {"StopTxnSampledData", v2::ControllerComponentVariables::SampledDataTxEndedMeasurands}, + {"TransactionMessageAttempts", v2::ControllerComponentVariables::MessageAttempts}, + {"TransactionMessageRetryInterval", v2::ControllerComponentVariables::MessageAttemptInterval}, + {"WebSocketPingInterval", v2::ControllerComponentVariables::WebSocketPingInterval}, + {"LocalAuthListEnabled", v2::ControllerComponentVariables::LocalAuthListCtrlrEnabled}, + {"ChargeProfileMaxStackLevel", v2::ControllerComponentVariables::ChargingProfileMaxStackLevel}, + {"ChargingScheduleAllowedChargingRateUnit", v2::ControllerComponentVariables::ChargingScheduleChargingRateUnit}, + {"ChargingScheduleMaxPeriods", v2::ControllerComponentVariables::PeriodsPerSchedule}, + {"ConnectorSwitch3to1PhaseSupported", v2::ControllerComponentVariables::Phases3to1}, + {"SupportedFileTransferProtocols", v2::ControllerComponentVariables::FileTransferProtocols}, + + // ============================================================================ + // Internal configuration keys + // ============================================================================ + + {"ChargePointId", v2::ControllerComponentVariables::ChargePointId}, + {"ChargeBoxSerialNumber", v2::ControllerComponentVariables::ChargeBoxSerialNumber}, + {"ChargePointModel", v2::ControllerComponentVariables::ChargePointModel}, + {"ChargePointSerialNumber", v2::ControllerComponentVariables::ChargePointSerialNumber}, + {"ChargePointVendor", v2::ControllerComponentVariables::ChargePointVendor}, + {"FirmwareVersion", v2::ControllerComponentVariables::FirmwareVersion}, + {"ICCID", v2::ControllerComponentVariables::ICCID}, + {"IFace", v2::ControllerComponentVariables::IFace}, + {"IMSI", v2::ControllerComponentVariables::IMSI}, + {"MeterSerialNumber", v2::ControllerComponentVariables::MeterSerialNumber}, + {"MeterType", v2::ControllerComponentVariables::MeterType}, + {"SupportedCiphers12", v2::ControllerComponentVariables::SupportedCiphers12}, + {"SupportedCiphers13", v2::ControllerComponentVariables::SupportedCiphers13}, + {"UseTPM", v2::ControllerComponentVariables::UseTPM}, + {"UseTPMSeccLeafCertificate", v2::ControllerComponentVariables::UseTPMSeccLeafCertificate}, + {"RetryBackoffRandomRange", v2::ControllerComponentVariables::RetryBackOffRandomRange}, + {"RetryBackoffRepeatTimes", v2::ControllerComponentVariables::RetryBackOffRepeatTimes}, + {"AuthorizeConnectorZeroOnConnectorOne", v2::ControllerComponentVariables::AuthorizeConnectorZeroOnConnectorOne}, + {"LogMessages", v2::ControllerComponentVariables::LogMessages}, + {"LogMessagesRaw", v2::ControllerComponentVariables::LogMessagesRaw}, + {"LogMessagesFormat", v2::ControllerComponentVariables::LogMessagesFormat}, + {"LogRotation", v2::ControllerComponentVariables::LogRotation}, + {"LogRotationDateSuffix", v2::ControllerComponentVariables::LogRotationDateSuffix}, + {"LogRotationMaximumFileSize", v2::ControllerComponentVariables::LogRotationMaximumFileSize}, + {"LogRotationMaximumFileCount", v2::ControllerComponentVariables::LogRotationMaximumFileCount}, + {"SupportedChargingProfilePurposeTypes", v2::ControllerComponentVariables::SupportedChargingProfilePurposeTypes}, + {"IgnoredProfilePurposesOffline", v2::ControllerComponentVariables::IgnoredProfilePurposesOffline}, + {"MaxCompositeScheduleDuration", v2::ControllerComponentVariables::MaxCompositeScheduleDuration}, + {"CompositeScheduleDefaultLimitAmps", v2::ControllerComponentVariables::CompositeScheduleDefaultLimitAmps}, + {"CompositeScheduleDefaultLimitWatts", v2::ControllerComponentVariables::CompositeScheduleDefaultLimitWatts}, + {"CompositeScheduleDefaultNumberPhases", v2::ControllerComponentVariables::CompositeScheduleDefaultNumberPhases}, + {"SupplyVoltage", v2::ControllerComponentVariables::SupplyVoltage}, + {"WebsocketPingPayload", v2::ControllerComponentVariables::WebsocketPingPayload}, + {"WebsocketPongTimeout", v2::ControllerComponentVariables::WebsocketPongTimeout}, + {"UseSslDefaultVerifyPaths", v2::ControllerComponentVariables::UseSslDefaultVerifyPaths}, + {"VerifyCsmsCommonName", v2::ControllerComponentVariables::VerifyCsmsCommonName}, + {"VerifyCsmsAllowWildcards", v2::ControllerComponentVariables::VerifyCsmsAllowWildcards}, + {"OcspRequestInterval", v2::ControllerComponentVariables::OcspRequestInterval}, + {"SeccLeafSubjectCommonName", v2::ControllerComponentVariables::ISO15118CtrlrSeccId}, + {"SeccLeafSubjectCountry", v2::ControllerComponentVariables::ISO15118CtrlrCountryName}, + {"SeccLeafSubjectOrganization", v2::ControllerComponentVariables::ISO15118CtrlrOrganizationName}, + {"QueueAllMessages", v2::ControllerComponentVariables::QueueAllMessages}, + {"MessageTypesDiscardForQueueing", v2::ControllerComponentVariables::MessageTypesDiscardForQueueing}, + {"MessageQueueSizeThreshold", v2::ControllerComponentVariables::MessageQueueSizeThreshold}, + {"MaxMessageSize", v2::ControllerComponentVariables::MaxMessageSize}, + {"TLSKeylogFile", v2::ControllerComponentVariables::TLSKeylogFile}, + {"EnableTLSKeylog", v2::ControllerComponentVariables::EnableTLSKeylog}, + {"NumberOfConnectors", v2::ControllerComponentVariables::NumberOfConnectors}, + + // ============================================================================ + // Security Section + // ============================================================================ + + {"AdditionalRootCertificateCheck", v2::ControllerComponentVariables::AdditionalRootCertificateCheck}, + {"AuthorizationKey", v2::ControllerComponentVariables::BasicAuthPassword}, + {"CertificateSignedMaxChainSize", v2::ControllerComponentVariables::MaxCertificateChainSize}, + {"CpoName", v2::ControllerComponentVariables::OrganizationName}, + {"SecurityProfile", v2::ControllerComponentVariables::SecurityProfile}, + {"CertSigningWaitMinimum", v2::ControllerComponentVariables::CertSigningWaitMinimum}, + {"CertSigningRepeatTimes", v2::ControllerComponentVariables::CertSigningRepeatTimes}, + + // ============================================================================ + // PnC Section + // ============================================================================ + + {"ISO15118PnCEnabled", v2::ControllerComponentVariables::PnCEnabled}, + {"CentralContractValidationAllowed", v2::ControllerComponentVariables::CentralContractValidationAllowed}, + {"ContractValidationOffline", v2::ControllerComponentVariables::ContractValidationOffline}, + + // ============================================================================ + // CostAndPrice Section + // ============================================================================ + + {"NumberOfDecimalsForCostValues", v2::ControllerComponentVariables::NumberOfDecimalsForCostValues}, + {"TimeOffset", v2::ControllerComponentVariables::TimeOffset}, + {"NextTimeOffsetTransitionDateTime", v2::ControllerComponentVariables::NextTimeOffsetTransitionDateTime}, + {"TimeOffsetNextTransition", v2::ControllerComponentVariables::TimeOffsetNextTransition}, + + // ============================================================================ + // Mavericks Section - OCPP 1.6 keys without direct OCPP 2.x equivalents + // ============================================================================ + + {"BlinkRepeat", v2::ControllerComponentVariables::BlinkRepeat}, + {"ConnectorPhaseRotationMaxLength", v2::ControllerComponentVariables::ConnectorPhaseRotationMaxLength}, + {"GetConfigurationMaxKeys", v2::ControllerComponentVariables::GetConfigurationMaxKeys}, + {"LightIntensity", v2::ControllerComponentVariables::LightIntensity}, + {"MinimumStatusDuration", v2::ControllerComponentVariables::MinimumStatusDuration}, + {"StopTransactionOnEVSideDisconnect", v2::ControllerComponentVariables::StopTransactionOnEVSideDisconnect}, + {"SupportedFeatureProfiles", v2::ControllerComponentVariables::SupportedFeatureProfiles}, + {"SupportedFeatureProfilesMaxLength", v2::ControllerComponentVariables::SupportedFeatureProfilesMaxLength}, + {"UnlockConnectorOnEVSideDisconnect", v2::ControllerComponentVariables::UnlockConnectorOnEVSideDisconnect}, + {"ReserveConnectorZeroSupported", v2::ControllerComponentVariables::ReserveConnectorZeroSupported}, + {"HostName", v2::ControllerComponentVariables::HostName}, + {"AllowChargingProfileWithoutStartSchedule", + v2::ControllerComponentVariables::AllowChargingProfileWithoutStartSchedule}, + {"WaitForStopTransactionsOnResetTimeout", v2::ControllerComponentVariables::WaitForStopTransactionsOnResetTimeout}, + {"StopTransactionIfUnlockNotSupported", v2::ControllerComponentVariables::StopTransactionIfUnlockNotSupported}, + {"MeterPublicKeys", v2::ControllerComponentVariables::MeterPublicKeys}, // FIXME + {"DisableSecurityEventNotifications", v2::ControllerComponentVariables::DisableSecurityEventNotifications}, + {"ISO15118CertificateManagementEnabled", v2::ControllerComponentVariables::ISO15118CertificateManagementEnabled}, + {"CustomDisplayCostAndPrice", v2::ControllerComponentVariables::CustomDisplayCostAndPrice}, + {"DefaultPrice", v2::ControllerComponentVariables::DefaultPrice}, + {"DefaultPriceText", v2::ControllerComponentVariables::DefaultPriceText}, + {"CustomIdleFeeAfterStop", v2::ControllerComponentVariables::CustomIdleFeeAfterStop}, + {"SupportedLanguages", v2::ControllerComponentVariables::SupportedLanguages}, + {"CustomMultiLanguageMessages", v2::ControllerComponentVariables::CustomMultiLanguageMessages}, + {"Language", v2::ControllerComponentVariables::Language}, + {"WaitForSetUserPriceTimeout", v2::ControllerComponentVariables::WaitForSetUserPriceTimeout}, +}; + +/// \brief Build a lookup map from OCPP 1.6 key to OCPP 2.x ComponentVariable +/// \return Map of v16_key -> ComponentVariable +inline std::map build_v16_to_v2_lookup() { + std::map lookup; + for (const auto& mapping : OCPP16_TO_V2_MAPPINGS) { + lookup[mapping.v16_key] = mapping.component_variable; + } + return lookup; +} + +/// \brief Get OCPP 2.x ComponentVariable for a given OCPP 1.6 configuration key +/// \param v16_key The OCPP 1.6 configuration key +/// \return Optional ComponentVariable if found +inline std::optional get_v2_component_variable(const std::string& v16_key) { + static const auto lookup = build_v16_to_v2_lookup(); + auto it = lookup.find(v16_key); + if (it != lookup.end()) { + return it->second; + } + return std::nullopt; +} + +} // namespace v16 +} // namespace ocpp \ No newline at end of file diff --git a/lib/everest/ocpp/include/ocpp/v16/known_keys.hpp b/lib/everest/ocpp/include/ocpp/v16/known_keys.hpp index c349e530ed..6bc7daa3e3 100644 --- a/lib/everest/ocpp/include/ocpp/v16/known_keys.hpp +++ b/lib/everest/ocpp/include/ocpp/v16/known_keys.hpp @@ -4,13 +4,209 @@ #ifndef OCPP_V16_KNOWN_KEYS_HPP #define OCPP_V16_KNOWN_KEYS_HPP +#include "ocpp/v16/types.hpp" +#include "ocpp/v2/ocpp_types.hpp" + #include #include #include +#include namespace ocpp::v16::keys { // clang-format off +// ============================================================================ +// Standard OCPP 1.6 keys +// ============================================================================ + +#define MAPPING_STANDARD(mapping) \ + mapping(AllowOfflineTxForUnknownId, OfflineTxForUnknownIdEnabled) \ + mapping(AuthorizationCacheEnabled, AuthCacheCtrlrEnabled) \ + mapping(AuthorizeRemoteTxRequests, AuthorizeRemoteStart) \ + mapping(ClockAlignedDataInterval, AlignedDataInterval) \ + mapping(ConnectionTimeOut, EVConnectionTimeOut) \ + mapping(HeartbeatInterval, HeartbeatInterval) \ + mapping(LocalAuthorizeOffline, LocalAuthorizeOffline) \ + mapping(LocalPreAuthorize, LocalPreAuthorize) \ + mapping(MaxEnergyOnInvalidId, MaxEnergyOnInvalidId) \ + mapping(MeterValuesAlignedData, AlignedDataMeasurands) \ + mapping(MeterValuesSampledData, SampledDataTxUpdatedMeasurands) \ + mapping(MeterValueSampleInterval, SampledDataTxUpdatedInterval) \ + mapping(ResetRetries, ResetRetries) \ + mapping(StopTransactionOnInvalidId, StopTxOnInvalidId) \ + mapping(StopTxnAlignedData, AlignedDataTxEndedMeasurands) \ + mapping(StopTxnSampledData, SampledDataTxEndedMeasurands) \ + mapping(TransactionMessageAttempts, MessageAttempts) \ + mapping(TransactionMessageRetryInterval, MessageAttemptInterval) \ + mapping(WebSocketPingInterval, WebSocketPingInterval) \ + mapping(LocalAuthListEnabled, LocalAuthListCtrlrEnabled) \ + mapping(ChargeProfileMaxStackLevel, ChargingProfileMaxStackLevel) \ + mapping(ChargingScheduleAllowedChargingRateUnit, ChargingScheduleChargingRateUnit) \ + mapping(ChargingScheduleMaxPeriods, PeriodsPerSchedule) \ + mapping(ConnectorSwitch3to1PhaseSupported, Phases3to1) \ + mapping(SupportedFileTransferProtocols, FileTransferProtocols) + +// ============================================================================ +// Internal configuration keys +// ============================================================================ + +#define MAPPING_INTERNAL(mapping) \ + mapping(ChargePointId, ChargePointId) \ + mapping(ChargeBoxSerialNumber, ChargeBoxSerialNumber) \ + mapping(ChargePointModel, ChargePointModel) \ + mapping(ChargePointSerialNumber, ChargePointSerialNumber) \ + mapping(ChargePointVendor, ChargePointVendor) \ + mapping(FirmwareVersion, FirmwareVersion) \ + mapping(ICCID, ICCID) \ + mapping(IFace, IFace) \ + mapping(IMSI, IMSI) \ + mapping(MeterSerialNumber, MeterSerialNumber) \ + mapping(MeterType, MeterType) \ + mapping(SupportedCiphers12, SupportedCiphers12) \ + mapping(SupportedCiphers13, SupportedCiphers13) \ + mapping(UseTPM, UseTPM) \ + mapping(UseTPMSeccLeafCertificate, UseTPMSeccLeafCertificate) \ + mapping(RetryBackoffRandomRange, RetryBackOffRandomRange) \ + mapping(RetryBackoffRepeatTimes, RetryBackOffRepeatTimes) \ + mapping(AuthorizeConnectorZeroOnConnectorOne,AuthorizeConnectorZeroOnConnectorOne) \ + mapping(LogMessages, LogMessages) \ + mapping(LogMessagesRaw, LogMessagesRaw) \ + mapping(LogMessagesFormat, LogMessagesFormat) \ + mapping(LogRotation, LogRotation) \ + mapping(LogRotationDateSuffix, LogRotationDateSuffix) \ + mapping(LogRotationMaximumFileSize, LogRotationMaximumFileSize) \ + mapping(LogRotationMaximumFileCount, LogRotationMaximumFileCount) \ + mapping(SupportedChargingProfilePurposeTypes,SupportedChargingProfilePurposeTypes) \ + mapping(IgnoredProfilePurposesOffline, IgnoredProfilePurposesOffline) \ + mapping(MaxCompositeScheduleDuration, MaxCompositeScheduleDuration) \ + mapping(CompositeScheduleDefaultLimitAmps, CompositeScheduleDefaultLimitAmps) \ + mapping(CompositeScheduleDefaultLimitWatts, CompositeScheduleDefaultLimitWatts) \ + mapping(CompositeScheduleDefaultNumberPhases, CompositeScheduleDefaultNumberPhases) \ + mapping(SupplyVoltage, SupplyVoltage) \ + mapping(WebsocketPingPayload, WebsocketPingPayload) \ + mapping(WebsocketPongTimeout, WebsocketPongTimeout) \ + mapping(UseSslDefaultVerifyPaths, UseSslDefaultVerifyPaths) \ + mapping(VerifyCsmsCommonName, VerifyCsmsCommonName) \ + mapping(VerifyCsmsAllowWildcards, VerifyCsmsAllowWildcards) \ + mapping(OcspRequestInterval, OcspRequestInterval) \ + mapping(SeccLeafSubjectCommonName, ISO15118CtrlrSeccId) \ + mapping(SeccLeafSubjectCountry, ISO15118CtrlrCountryName) \ + mapping(SeccLeafSubjectOrganization, ISO15118CtrlrOrganizationName) \ + mapping(QueueAllMessages, QueueAllMessages) \ + mapping(MessageTypesDiscardForQueueing, MessageTypesDiscardForQueueing) \ + mapping(MessageQueueSizeThreshold, MessageQueueSizeThreshold) \ + mapping(MaxMessageSize, MaxMessageSize) \ + mapping(TLSKeylogFile, TLSKeylogFile) \ + mapping(EnableTLSKeylog, EnableTLSKeylog) \ + mapping(NumberOfConnectors, NumberOfConnectors) + +// ============================================================================ +// Security Section +// ============================================================================ + +#define MAPPING_SECURITY(mapping) \ + mapping(AdditionalRootCertificateCheck, AdditionalRootCertificateCheck) \ + mapping(AuthorizationKey, BasicAuthPassword) \ + mapping(CertificateSignedMaxChainSize, MaxCertificateChainSize) \ + mapping(CpoName, OrganizationName) \ + mapping(SecurityProfile, SecurityProfile) \ + mapping(CertSigningWaitMinimum, CertSigningWaitMinimum) \ + mapping(CertSigningRepeatTimes, CertSigningRepeatTimes) + +// ============================================================================ +// PnC Section +// ============================================================================ + +#define MAPPING_PNC(mapping) \ + mapping(ISO15118PnCEnabled, PnCEnabled) \ + mapping(CentralContractValidationAllowed, CentralContractValidationAllowed) \ + mapping(ContractValidationOffline, ContractValidationOffline) + +// ============================================================================ +// CostAndPrice Section +// ============================================================================ + +#define MAPPING_COST(mapping) \ + mapping(NumberOfDecimalsForCostValues, NumberOfDecimalsForCostValues) \ + mapping(TimeOffset, TimeOffset) \ + mapping(NextTimeOffsetTransitionDateTime, NextTimeOffsetTransitionDateTime) \ + mapping(TimeOffsetNextTransition, TimeOffsetNextTransition) + +// ============================================================================ +// Mavericks Section - OCPP 1.6 keys without direct OCPP 2.x equivalents +// ============================================================================ + +#define MAPPING_MISC(mapping) \ + mapping(BlinkRepeat, BlinkRepeat) \ + mapping(ConnectorPhaseRotationMaxLength, ConnectorPhaseRotationMaxLength) \ + mapping(GetConfigurationMaxKeys, GetConfigurationMaxKeys) \ + mapping(LightIntensity, LightIntensity) \ + mapping(MinimumStatusDuration, MinimumStatusDuration) \ + mapping(StopTransactionOnEVSideDisconnect, StopTransactionOnEVSideDisconnect) \ + mapping(SupportedFeatureProfiles, SupportedFeatureProfiles) \ + mapping(SupportedFeatureProfilesMaxLength, SupportedFeatureProfilesMaxLength) \ + mapping(UnlockConnectorOnEVSideDisconnect, UnlockConnectorOnEVSideDisconnect) \ + mapping(ReserveConnectorZeroSupported, ReserveConnectorZeroSupported) \ + mapping(HostName, HostName) \ + mapping(AllowChargingProfileWithoutStartSchedule, AllowChargingProfileWithoutStartSchedule) \ + mapping(WaitForStopTransactionsOnResetTimeout, WaitForStopTransactionsOnResetTimeout) \ + mapping(StopTransactionIfUnlockNotSupported, StopTransactionIfUnlockNotSupported) \ + mapping(MeterPublicKeys, MeterPublicKeys) \ + mapping(DisableSecurityEventNotifications, DisableSecurityEventNotifications) \ + mapping(ISO15118CertificateManagementEnabled, ISO15118CertificateManagementEnabled) \ + mapping(CustomDisplayCostAndPrice, CustomDisplayCostAndPrice) \ + mapping(DefaultPrice, DefaultPrice) \ + mapping(DefaultPriceText, DefaultPriceText) \ + mapping(CustomIdleFeeAfterStop, CustomIdleFeeAfterStop) \ + mapping(SupportedLanguages, SupportedLanguages) \ + mapping(CustomMultiLanguageMessages, CustomMultiLanguageMessages) \ + mapping(Language, Language) \ + mapping(WaitForSetUserPriceTimeout, WaitForSetUserPriceTimeout) + +// TODO(james-ctc): check if there is a mapping to the V2 device model +#define MAPPING_MISC_ADDITIONAL(mapping) \ + mapping(AuthorizeRemoteTxRequests, AuthorizeRemoteTxRequests) \ + mapping(CentralSystemURI, CentralSystemURI) \ + mapping(CertificateStoreMaxLength, CertificateStoreMaxLength) \ + mapping(ChargeProfileMaxStackLevel, ChargeProfileMaxStackLevel) \ + mapping(ChargingScheduleAllowedChargingRateUnit, ChargingScheduleAllowedChargingRateUnit) \ + mapping(ChargingScheduleMaxPeriods, ChargingScheduleMaxPeriods) \ + mapping(ClockAlignedDataInterval, ClockAlignedDataInterval) \ + mapping(ConnectionTimeOut, ConnectionTimeOut) \ + mapping(ConnectorEvseIds, ConnectorEvseIds) \ + mapping(ConnectorPhaseRotation, ConnectorPhaseRotation) \ + mapping(ISO15118PnCEnabled, ISO15118PnCEnabled) \ + mapping(LocalAuthListEnabled, LocalAuthListEnabled) \ + mapping(LocalAuthListMaxLength, LocalAuthListMaxLength) \ + mapping(MaxChargingProfilesInstalled, MaxChargingProfilesInstalled) \ + mapping(MeterValueSampleInterval, MeterValueSampleInterval) \ + mapping(MeterValuesAlignedData, MeterValuesAlignedData) \ + mapping(MeterValuesAlignedDataMaxLength, MeterValuesAlignedDataMaxLength) \ + mapping(MeterValuesSampledData, MeterValuesSampledData) \ + mapping(MeterValuesSampledDataMaxLength, MeterValuesSampledDataMaxLength) \ + mapping(RetryBackoffRandomRange, RetryBackoffRandomRange) \ + mapping(RetryBackoffRepeatTimes, RetryBackoffRepeatTimes) \ + mapping(RetryBackoffWaitMinimum, RetryBackoffWaitMinimum) \ + mapping(SendLocalListMaxLength, SendLocalListMaxLength) \ + mapping(StopTransactionOnInvalidId, StopTransactionOnInvalidId) \ + mapping(StopTxnAlignedData, StopTxnAlignedData) \ + mapping(StopTxnAlignedDataMaxLength, StopTxnAlignedDataMaxLength) \ + mapping(StopTxnSampledData, StopTxnSampledData) \ + mapping(StopTxnSampledDataMaxLength, StopTxnSampledDataMaxLength) \ + mapping(SupportedFileTransferProtocols, SupportedFileTransferProtocols) \ + mapping(SupportedMeasurands, SupportedMeasurands) \ + mapping(TransactionMessageAttempts, TransactionMessageAttempts) \ + mapping(TransactionMessageRetryInterval, TransactionMessageRetryInterval) + +#define MAPPING_ALL(mapping) \ + MAPPING_MISC_ADDITIONAL(mapping) \ + MAPPING_MISC(mapping) \ + MAPPING_STANDARD(mapping) \ + MAPPING_INTERNAL(mapping) \ + MAPPING_SECURITY(mapping) \ + MAPPING_PNC(mapping) \ + MAPPING_COST(mapping) + #define FOR_ALL_KEYS(key) \ key(Core, AllowOfflineTxForUnknownId) \ key(Core, AuthorizationCacheEnabled) \ @@ -137,7 +333,6 @@ key(SmartCharging, ChargingScheduleAllowedChargingRateUnit) \ key(SmartCharging, ChargingScheduleMaxPeriods) \ key(SmartCharging, ConnectorSwitch3to1PhaseSupported) \ key(SmartCharging, MaxChargingProfilesInstalled) - // clang-format on #define VALUE(a, b) b, @@ -170,6 +365,12 @@ inline bool is_in_section(sections section, valid_keys key) { return to_section(key) == section; } bool is_hidden(valid_keys key); +std::optional get_profile(valid_keys key); + +using DeviceModel_CV = std::optional>; +DeviceModel_CV convert_v2(const std::string_view& str); +DeviceModel_CV convert_v2(valid_keys key); +std::string convert_v2(const ocpp::v2::Component& component, const ocpp::v2::Variable& variable); } // namespace ocpp::v16::keys diff --git a/lib/everest/ocpp/include/ocpp/v2/ctrlr_component_variables.hpp b/lib/everest/ocpp/include/ocpp/v2/ctrlr_component_variables.hpp index 9a4872b9ac..e0728c27ad 100644 --- a/lib/everest/ocpp/include/ocpp/v2/ctrlr_component_variables.hpp +++ b/lib/everest/ocpp/include/ocpp/v2/ctrlr_component_variables.hpp @@ -88,6 +88,8 @@ extern const Component SecurityCtrlr; extern const Component SmartChargingCtrlr; extern const Component TariffCostCtrlr; extern const Component TxCtrlr; +extern const Component + OCPP16MavericksCtrlr; // This controller contains OCPP1.6 configuration keys without a clear mapping to OCPP2.x. } // namespace ControllerComponents namespace StandardizedVariables { @@ -310,6 +312,73 @@ extern const ComponentVariable TxBeforeAcceptedEnabled; extern const RequiredComponentVariable TxStartPoint; extern const RequiredComponentVariable TxStopPoint; extern const ComponentVariable ISO15118CtrlrAvailable; + +// OCPP1.6 mavericks: The following ComponentVariable definitions are required because some CPP1.6 configuration keys +// do not map to any existing component variable combination in OCPP2.x. The following definitions only control the +// OCPP1.6 implementation +extern const ComponentVariable BlinkRepeat; +extern const ComponentVariable ConnectorPhaseRotationMaxLength; +extern const RequiredComponentVariable GetConfigurationMaxKeys; +extern const ComponentVariable LightIntensity; +extern const ComponentVariable MinimumStatusDuration; +extern const RequiredComponentVariable NumberOfConnectors; +extern const ComponentVariable StopTransactionOnEVSideDisconnect; +extern const RequiredComponentVariable SupportedFeatureProfiles; +extern const ComponentVariable SupportedFeatureProfilesMaxLength; +extern const RequiredComponentVariable UnlockConnectorOnEVSideDisconnect; +extern const ComponentVariable ReserveConnectorZeroSupported; +extern const ComponentVariable HostName; +extern const ComponentVariable AllowChargingProfileWithoutStartSchedule; +extern const ComponentVariable WaitForStopTransactionsOnResetTimeout; +extern const ComponentVariable StopTransactionIfUnlockNotSupported; +extern const ComponentVariable MeterPublicKeys; +extern const ComponentVariable DisableSecurityEventNotifications; +extern const ComponentVariable ISO15118CertificateManagementEnabled; +extern const ComponentVariable CustomDisplayCostAndPrice; // Required only if CaliforniaPricing enabled +extern const ComponentVariable DefaultPrice; +extern const ComponentVariable DefaultPriceText; +extern const ComponentVariable CustomIdleFeeAfterStop; +extern const ComponentVariable SupportedLanguages; +extern const ComponentVariable CustomMultiLanguageMessages; +extern const ComponentVariable Language; +extern const ComponentVariable WaitForSetUserPriceTimeout; + +// Additional OCPP1.6 Mavericks - Configuration keys without direct OCPP 2.x equivalents +// TODO(james-ctc): double check there is no V2 mapping + +extern const ComponentVariable AuthorizeRemoteTxRequests; +extern const ComponentVariable CentralSystemURI; +extern const ComponentVariable CertificateStoreMaxLength; +extern const ComponentVariable ChargeProfileMaxStackLevel; +extern const ComponentVariable ChargingScheduleAllowedChargingRateUnit; +extern const ComponentVariable ChargingScheduleMaxPeriods; +extern const ComponentVariable ClockAlignedDataInterval; +extern const ComponentVariable ConnectionTimeOut; +extern const ComponentVariable ConnectorEvseIds; +extern const ComponentVariable ConnectorPhaseRotation; +extern const ComponentVariable ISO15118PnCEnabled; +extern const ComponentVariable LocalAuthListEnabled; +extern const ComponentVariable LocalAuthListMaxLength; +extern const ComponentVariable MaxChargingProfilesInstalled; +extern const ComponentVariable MeterValueSampleInterval; +extern const ComponentVariable MeterValuesAlignedData; +extern const ComponentVariable MeterValuesAlignedDataMaxLength; +extern const ComponentVariable MeterValuesSampledData; +extern const ComponentVariable MeterValuesSampledDataMaxLength; +extern const ComponentVariable RetryBackoffRandomRange; +extern const ComponentVariable RetryBackoffRepeatTimes; +extern const ComponentVariable RetryBackoffWaitMinimum; +extern const ComponentVariable SendLocalListMaxLength; +extern const ComponentVariable StopTransactionOnInvalidId; +extern const ComponentVariable StopTxnAlignedData; +extern const ComponentVariable StopTxnAlignedDataMaxLength; +extern const ComponentVariable StopTxnSampledData; +extern const ComponentVariable StopTxnSampledDataMaxLength; +extern const ComponentVariable SupportedFileTransferProtocols; +extern const ComponentVariable SupportedMeasurands; +extern const ComponentVariable TransactionMessageAttempts; +extern const ComponentVariable TransactionMessageRetryInterval; + } // namespace ControllerComponentVariables namespace EvseComponentVariables { diff --git a/lib/everest/ocpp/lib/ocpp/v16/charge_point_configuration_devicemodel.cpp b/lib/everest/ocpp/lib/ocpp/v16/charge_point_configuration_devicemodel.cpp index bcce6bf619..547d6d1bbb 100644 --- a/lib/everest/ocpp/lib/ocpp/v16/charge_point_configuration_devicemodel.cpp +++ b/lib/everest/ocpp/lib/ocpp/v16/charge_point_configuration_devicemodel.cpp @@ -24,6 +24,7 @@ namespace { using namespace ocpp; using SetResult = v16::ChargePointConfigurationDeviceModel::SetResult; using DeviceModelInterface = v2::DeviceModelInterface; +using SupportedFeatureProfiles = v16::SupportedFeatureProfiles; constexpr const char* custom_component = "Custom"; @@ -120,12 +121,10 @@ std::optional isReadOnly(DeviceModelInterface& storage, const std::string_ } template -std::optional get_optional(DeviceModelInterface& storage, const std::string_view& component, - const std::string_view& variable) { - const v2::Component component_v{std::string{component}}; - const v2::Variable variable_v{std::string{variable}}; +std::optional get_optional(DeviceModelInterface& storage, const v2::Component& component, + const v2::Variable& variable) { std::string value; - const auto get_result = storage.get_variable(component_v, variable_v, v2::AttributeEnum::Actual, value); + const auto get_result = storage.get_variable(component, variable, v2::AttributeEnum::Actual, value); if (get_result == v2::GetVariableStatusEnum::Accepted) { try { if constexpr (std::is_same_v) { @@ -136,17 +135,30 @@ std::optional get_optional(DeviceModelInterface& storage, const std::string_v return v2::to_specific_type(value); } } catch (const std::exception& ex) { - EVLOG_warning << component_v.name << '[' << variable_v.name << "] '" << value + EVLOG_warning << component.name << '[' << variable.name << "] '" << value << "' to_specific_type exception: " << ex.what(); } } return std::nullopt; } +template +std::optional get_optional(DeviceModelInterface& storage, const std::string_view& component, + const std::string_view& variable) { + const v2::Component component_v{std::string{component}}; + const v2::Variable variable_v{std::string{variable}}; + return get_optional(storage, component_v, variable_v); +} + template std::optional get_optional(DeviceModelInterface& storage, v16::keys::valid_keys key) { - const auto component = v16::keys::to_section_string_view(key); - const auto variable = v16::keys::convert(key); - return get_optional(storage, component, variable); + std::optional result; + const auto cv = v16::keys::convert_v2(key); + if (cv) { + const auto& component = std::get(*cv); + const auto& variable = std::get(*cv); + result = get_optional(storage, component, variable); + } + return result; } template T inline get_value(DeviceModelInterface& storage, v16::keys::valid_keys key) { @@ -166,17 +178,26 @@ template inline void get_value(T& value, DeviceModelInterface& stor value = get_value(storage, key); } +bool key_exists(DeviceModelInterface& storage, const v2::Component& component, const v2::Variable& variable) { + const auto result = storage.get_variable_meta_data(component, variable); + return result.has_value(); +} + bool key_exists(DeviceModelInterface& storage, const std::string_view& component, const std::string_view& variable) { const v2::Component component_v{std::string{component}}; const v2::Variable variable_v{std::string{variable}}; - const auto result = storage.get_variable_meta_data(component_v, variable_v); - return result.has_value(); + return key_exists(storage, component_v, variable_v); } bool key_exists(DeviceModelInterface& storage, v16::keys::valid_keys key) { - const auto component = v16::keys::to_section_string_view(key); - const auto variable = v16::keys::convert(key); - return key_exists(storage, component, variable); + bool result{false}; + const auto cv = v16::keys::convert_v2(key); + if (cv) { + const auto& component = std::get(*cv); + const auto& variable = std::get(*cv); + result = key_exists(storage, component, variable); + } + return result; } std::optional get_key_value_optional(DeviceModelInterface& storage, v16::keys::valid_keys key) { @@ -205,17 +226,27 @@ inline v16::KeyValue get_key_value(DeviceModelInterface& storage, v16::keys::val } /// set known key to specified value +SetResult set_value(DeviceModelInterface& storage, const v2::Component& component, const v2::Variable& variable, + const std::string& value) { + return storage.set_value(component, variable, v2::AttributeEnum::Actual, value, "OCPP 1.6"); +} + SetResult set_value(DeviceModelInterface& storage, const std::string_view& component, const std::string_view& variable, const std::string& value) { const v2::Component component_v{std::string{component}}; const v2::Variable variable_v{std::string{variable}}; - return storage.set_value(component_v, variable_v, v2::AttributeEnum::Actual, value, "OCPP 1.6"); + return set_value(storage, component_v, variable_v, value); } SetResult set_value(DeviceModelInterface& storage, v16::keys::valid_keys key, const std::string& value) { - const v2::Component component{std::string{v16::keys::to_section_string_view(key)}}; - const v2::Variable variable{std::string{v16::keys::convert(key)}}; - return storage.set_value(component, variable, v2::AttributeEnum::Actual, value, "OCPP 1.6"); + auto result = SetResult::UnknownVariable; + const auto cv = v16::keys::convert_v2(key); + if (cv) { + const auto& component = std::get(*cv); + const auto& variable = std::get(*cv); + result = set_value(storage, component, variable, value); + } + return result; } /// set known key to optional specified value @@ -328,7 +359,7 @@ bool key_exists(DeviceModelInterface& storage, const std::string_view& name) { SetResult set_value(DeviceModelInterface& storage, const std::string_view& name, const std::string& value) { const v2::Component component{custom_component}; const v2::Variable variable{std::string{name}}; - return storage.set_value(component, variable, v2::AttributeEnum::Actual, value, "OCPP 1.6"); + return set_value(storage, component, variable, value); } /// \brief set custom value @@ -936,8 +967,8 @@ ChargePointConfigurationDeviceModel::ChargePointConfigurationDeviceModel( } #else // TODO(james-ctc): remove these - just added for unit tests - initial.insert(conversions::string_to_supported_feature_profiles("PnC")); - initial.insert(conversions::string_to_supported_feature_profiles("CostAndPrice")); + initial.insert(SupportedFeatureProfiles::PnC); + initial.insert(SupportedFeatureProfiles::CostAndPrice); #endif initialise(initial, profiles, measurands); @@ -2607,11 +2638,21 @@ std::vector ChargePointConfigurationDeviceModel::get_all_key_value() { const auto& component = entry.component; const auto& variable = entry.variable; try { - const auto feature = conversions::string_to_supported_feature_profiles(component.name); - if (const auto it = supported_feature_profiles.find(feature); it != supported_feature_profiles.end()) { - auto kv = get(variable.name); - if (kv) { - all.push_back(std::move(kv.value())); + // ensure key is valid against the supported profiles + const auto v16_key = keys::convert_v2(component, variable); + if (!v16_key.empty()) { + const auto key = keys::convert(v16_key); + if (key) { + const auto feature = keys::get_profile(*key); + if (feature) { + if (const auto it = supported_feature_profiles.find(*feature); + it != supported_feature_profiles.end()) { + auto kv = get(variable.name); + if (kv) { + all.push_back(std::move(kv.value())); + } + } + } } } } catch (std::exception& ex) { diff --git a/lib/everest/ocpp/lib/ocpp/v16/known_keys.cpp b/lib/everest/ocpp/lib/ocpp/v16/known_keys.cpp index 48540f35ac..90a9570879 100644 --- a/lib/everest/ocpp/lib/ocpp/v16/known_keys.cpp +++ b/lib/everest/ocpp/lib/ocpp/v16/known_keys.cpp @@ -1,10 +1,16 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright 2020 - 2026 Pionix GmbH and Contributors to EVerest +#include #include +#include #include #include +#include +#include +#include +#include namespace { using ocpp::v16::keys::valid_keys; @@ -98,6 +104,75 @@ constexpr valid_keys read_only[] = {FOR_ALL_READONLY(VALUE)}; constexpr valid_keys hidden[] = {FOR_ALL_HIDDEN(VALUE)}; #undef VALUE + +class V2ConfigMap { +private: + bool configured{false}; + std::map map; + std::map reverse_map; + + void configure(const std::string_view& v16, const ocpp::v2::ComponentVariable& cv); + void configure(); + +public: + ocpp::v16::keys::DeviceModel_CV convert_v2(const std::string_view& v16_key); + std::string convert_v2(const ocpp::v2::Component& component, const ocpp::v2::Variable& variable); +}; + +void V2ConfigMap::configure(const std::string_view& v16, const ocpp::v2::ComponentVariable& cv) { + const auto& variable = cv.variable; + if (variable) { + if (const auto it = map.find(v16); it != map.end()) { + if (it->second->variable) { + EVLOG_warning << "V16 " << v16 << ": '" << it->second->variable->name << "' replaced with '" + << variable->name << '\''; + } + } + map.insert({v16, &cv}); + std::string name = std::string{cv.component.name} + std::string{variable->name}; + if (variable->instance) { + name += std::string{variable->instance.value()}; + } + if (const auto it = reverse_map.find(name); it != reverse_map.end()) { + std::cerr << "V2 " << name << ": '" << it->second << "' replaced with '" << v16 << '\''; + } + reverse_map.insert({std::move(name), v16}); + } +} + +#define VALUE(a, b) configure(#a, ocpp::v2::ControllerComponentVariables::b); +void V2ConfigMap::configure() { + if (!configured) { + configured = true; + MAPPING_ALL(VALUE) + } +} +#undef VALUE + +ocpp::v16::keys::DeviceModel_CV V2ConfigMap::convert_v2(const std::string_view& v16_key) { + configure(); + ocpp::v16::keys::DeviceModel_CV result; + std::string name{v16_key}; + if (const auto it = map.find(name); it != map.end()) { + if (it->second->variable) { + result = std::make_pair(it->second->component, it->second->variable.value()); + } + } + return result; +} + +std::string V2ConfigMap::convert_v2(const ocpp::v2::Component& component, const ocpp::v2::Variable& variable) { + configure(); + std::string result = variable.name; + const std::string name = std::string{component.name} + std::string{variable.name}; + if (const auto it = reverse_map.find(name); it != reverse_map.end()) { + result = it->second; + } + return result; +} + +V2ConfigMap v2_map; + } // namespace namespace ocpp::v16::keys { @@ -164,4 +239,32 @@ bool is_hidden(valid_keys key) { return std::find(std::cbegin(hidden), std::cend(hidden), key) != std::cend(hidden); } +#undef VALUE +#define VALUE(a, b) \ + case valid_keys::b: \ + return ocpp::v16::SupportedFeatureProfiles::a; + +std::optional get_profile(valid_keys key) { + switch (key) { + FOR_ALL_KEYS(VALUE) + default: + break; + } + return std::nullopt; +} + +#undef VALUE + +DeviceModel_CV convert_v2(const std::string_view& str) { + return v2_map.convert_v2(str); +} + +DeviceModel_CV convert_v2(valid_keys key) { + return convert_v2(convert(key)); +} + +std::string convert_v2(const ocpp::v2::Component& component, const ocpp::v2::Variable& variable) { + return v2_map.convert_v2(component, variable); +} + } // namespace ocpp::v16::keys diff --git a/lib/everest/ocpp/lib/ocpp/v2/ctrlr_component_variables.cpp b/lib/everest/ocpp/lib/ocpp/v2/ctrlr_component_variables.cpp index 2f6a43c17a..f34f75c02e 100644 --- a/lib/everest/ocpp/lib/ocpp/v2/ctrlr_component_variables.cpp +++ b/lib/everest/ocpp/lib/ocpp/v2/ctrlr_component_variables.cpp @@ -27,6 +27,7 @@ const Component SecurityCtrlr = {"SecurityCtrlr"}; const Component SmartChargingCtrlr = {"SmartChargingCtrlr"}; const Component TariffCostCtrlr = {"TariffCostCtrlr"}; const Component TxCtrlr = {"TxCtrlr"}; +const Component OCPP16MavericksCtrlr = {"OCPP16MavericksCtrlr"}; } // namespace ControllerComponents namespace StandardizedVariables { @@ -1215,6 +1216,354 @@ const ComponentVariable ISO15118CtrlrAvailable = { }), }; +// OCPP1.6 Mavericks - Configuration keys without direct OCPP 2.x equivalents +const ComponentVariable BlinkRepeat = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "BlinkRepeat", + }), +}; +const ComponentVariable ConnectorPhaseRotationMaxLength = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "ConnectorPhaseRotationMaxLength", + }), +}; +const RequiredComponentVariable GetConfigurationMaxKeys = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "GetConfigurationMaxKeys", + }), +}; +const ComponentVariable LightIntensity = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "LightIntensity", + }), +}; +const ComponentVariable MinimumStatusDuration = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "MinimumStatusDuration", + }), +}; +const ComponentVariable StopTransactionOnEVSideDisconnect = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "StopTransactionOnEVSideDisconnect", + }), +}; +const RequiredComponentVariable SupportedFeatureProfiles = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "SupportedFeatureProfiles", + }), +}; +const ComponentVariable SupportedFeatureProfilesMaxLength = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "SupportedFeatureProfilesMaxLength", + }), +}; +const RequiredComponentVariable UnlockConnectorOnEVSideDisconnect = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "UnlockConnectorOnEVSideDisconnect", + }), +}; +const ComponentVariable ReserveConnectorZeroSupported = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "ReserveConnectorZeroSupported", + }), +}; +const ComponentVariable HostName = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "HostName", + }), +}; +const ComponentVariable AllowChargingProfileWithoutStartSchedule = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "AllowChargingProfileWithoutStartSchedule", + }), +}; +const ComponentVariable WaitForStopTransactionsOnResetTimeout = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "WaitForStopTransactionsOnResetTimeout", + }), +}; +const ComponentVariable StopTransactionIfUnlockNotSupported = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "StopTransactionIfUnlockNotSupported", + }), +}; +const ComponentVariable MeterPublicKeys = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "MeterPublicKeys", + }), +}; +const ComponentVariable DisableSecurityEventNotifications = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "DisableSecurityEventNotifications", + }), +}; +const ComponentVariable ISO15118CertificateManagementEnabled = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "ISO15118CertificateManagementEnabled", + }), +}; +const ComponentVariable CustomDisplayCostAndPrice = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "CustomDisplayCostAndPrice", + }), +}; +const ComponentVariable DefaultPrice = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "DefaultPrice", + }), +}; +const ComponentVariable DefaultPriceText = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "DefaultPriceText", + }), +}; +const ComponentVariable CustomIdleFeeAfterStop = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "CustomIdleFeeAfterStop", + }), +}; +const ComponentVariable SupportedLanguages = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "SupportedLanguages", + }), +}; +const ComponentVariable CustomMultiLanguageMessages = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "CustomMultiLanguageMessages", + }), +}; +const ComponentVariable Language = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "Language", + }), +}; +const ComponentVariable WaitForSetUserPriceTimeout = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "WaitForSetUserPriceTimeout", + }), +}; + +// Additional OCPP1.6 Mavericks - Configuration keys without direct OCPP 2.x equivalents +// TODO(james-ctc): double check there is no V2 mapping + +const ComponentVariable AuthorizeRemoteTxRequests = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "AuthorizeRemoteTxRequests", + }), +}; +const ComponentVariable CentralSystemURI = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "CentralSystemURI", + }), +}; +const ComponentVariable CertificateStoreMaxLength = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "CertificateStoreMaxLength", + }), +}; +const ComponentVariable ChargeProfileMaxStackLevel = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "ChargeProfileMaxStackLevel", + }), +}; +const ComponentVariable ChargingScheduleAllowedChargingRateUnit = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "ChargingScheduleAllowedChargingRateUnit", + }), +}; +const ComponentVariable ChargingScheduleMaxPeriods = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "ChargingScheduleMaxPeriods", + }), +}; +const ComponentVariable ClockAlignedDataInterval = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "ClockAlignedDataInterval", + }), +}; +const ComponentVariable ConnectionTimeOut = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "ConnectionTimeOut", + }), +}; +const ComponentVariable ConnectorEvseIds = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "ConnectorEvseIds", + }), +}; +const ComponentVariable ConnectorPhaseRotation = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "ConnectorPhaseRotation", + }), +}; +const ComponentVariable ISO15118PnCEnabled = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "ISO15118PnCEnabled", + }), +}; +const ComponentVariable LocalAuthListEnabled = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "LocalAuthListEnabled", + }), +}; +const ComponentVariable LocalAuthListMaxLength = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "LocalAuthListMaxLength", + }), +}; +const ComponentVariable MaxChargingProfilesInstalled = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "MaxChargingProfilesInstalled", + }), +}; +const ComponentVariable MeterValueSampleInterval = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "MeterValueSampleInterval", + }), +}; +const ComponentVariable MeterValuesAlignedData = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "MeterValuesAlignedData", + }), +}; +const ComponentVariable MeterValuesAlignedDataMaxLength = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "MeterValuesAlignedDataMaxLength", + }), +}; +const ComponentVariable MeterValuesSampledData = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "MeterValuesSampledData", + }), +}; +const ComponentVariable MeterValuesSampledDataMaxLength = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "MeterValuesSampledDataMaxLength", + }), +}; +const ComponentVariable RetryBackoffRandomRange = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "RetryBackoffRandomRange", + }), +}; +const ComponentVariable RetryBackoffRepeatTimes = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "RetryBackoffRepeatTimes", + }), +}; +const ComponentVariable RetryBackoffWaitMinimum = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "RetryBackoffWaitMinimum", + }), +}; +const ComponentVariable SendLocalListMaxLength = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "SendLocalListMaxLength", + }), +}; +const ComponentVariable StopTransactionOnInvalidId = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "StopTransactionOnInvalidId", + }), +}; +const ComponentVariable StopTxnAlignedData = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "StopTxnAlignedData", + }), +}; +const ComponentVariable StopTxnAlignedDataMaxLength = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "StopTxnAlignedDataMaxLength", + }), +}; +const ComponentVariable StopTxnSampledData = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "StopTxnSampledData", + }), +}; +const ComponentVariable StopTxnSampledDataMaxLength = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "StopTxnSampledDataMaxLength", + }), +}; +const ComponentVariable SupportedFileTransferProtocols = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "SupportedFileTransferProtocols", + }), +}; +const ComponentVariable SupportedMeasurands = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "SupportedMeasurands", + }), +}; +const ComponentVariable TransactionMessageAttempts = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "TransactionMessageAttempts", + }), +}; +const ComponentVariable TransactionMessageRetryInterval = { + ControllerComponents::OCPP16MavericksCtrlr, + std::optional({ + "TransactionMessageRetryInterval", + }), +}; + } // namespace ControllerComponentVariables namespace EvseComponentVariables { diff --git a/lib/everest/ocpp/tests/lib/ocpp/v16/v2config/memory_storage.cpp b/lib/everest/ocpp/tests/lib/ocpp/v16/v2config/memory_storage.cpp index 57c9696ab1..74248e70e9 100644 --- a/lib/everest/ocpp/tests/lib/ocpp/v16/v2config/memory_storage.cpp +++ b/lib/everest/ocpp/tests/lib/ocpp/v16/v2config/memory_storage.cpp @@ -4,9 +4,11 @@ #include "memory_storage.hpp" #include +#include #include #include +#include #include #include @@ -133,30 +135,40 @@ const std::map required_vars_california_pricing = { // initial values are from the JSON unit test config files // Do not add additional values const std::map required_vars_custom = {}; - -std::map vars_internal; -std::map vars_core; -std::map vars_firmware_management; -std::map vars_smart_charging; -std::map vars_security; -std::map vars_local_auth_list; -std::map vars_pnc; -std::map vars_california_pricing; -std::map vars_custom; +using MemoryStorage = ocpp::v16::stubs::MemoryStorage; +MemoryStorage::Storage vars_internal; +MemoryStorage::Storage vars_core; +MemoryStorage::Storage vars_firmware_management; +MemoryStorage::Storage vars_smart_charging; +MemoryStorage::Storage vars_security; +MemoryStorage::Storage vars_local_auth_list; +MemoryStorage::Storage vars_pnc; +MemoryStorage::Storage vars_california_pricing; +MemoryStorage::Storage vars_custom; +MemoryStorage::Storage vars_additional; + +const std::vector vars_list = { + &vars_internal, &vars_core, &vars_firmware_management, &vars_smart_charging, &vars_security, + &vars_local_auth_list, &vars_pnc, &vars_california_pricing, &vars_custom, &vars_additional, +}; const ocpp::v2::VariableCharacteristics characteristics = {ocpp::v2::DataEnum::string, false, {}, {}, {}, {}, {}, {}}; const ocpp::v2::VariableMetaData meta_data = {characteristics, {}, {}}; void add_to_report(std::vector& report, const std::string_view& name, const std::map& vars) { - ocpp::v2::Component component{std::string{name}, {}, {}, {}}; - for (const auto& i : vars) { - ocpp::v2::Variable variable{i.first, {}, {}}; - ocpp::v2::ReportData data; - data.component = component; - data.variable = variable; - report.push_back(std::move(data)); + const auto cv = ocpp::v16::keys::convert_v2(i.first); + if (cv) { + auto component = std::get(*cv); + auto variable = std::get(*cv); + ocpp::v2::ReportData data; + data.component = std::move(component); + data.variable = std::move(variable); + report.push_back(std::move(data)); + } else { + std::cerr << "add_to_report: missing '" << i.first << "'\n"; + } } } @@ -188,21 +200,115 @@ MemoryStorage::MemoryStorage() { vars_california_pricing = required_vars_california_pricing; vars_custom = required_vars_custom; + vars_additional.clear(); read_only.clear(); } +std::optional MemoryStorage::locate_v16(const std::string& name) const { + // since V16 items are unique, just search through the storage items + // to locate it + for (auto& i : vars_list) { + if (auto it = i->find(name); it != i->end()) { + return it; + } + } + return std::nullopt; +} + +std::optional MemoryStorage::get_v16(const std::string& name) const { + // since V16 items are unique, just search through the storage items + // to locate it + auto it = locate_v16(name); + if (it) { + return it.value()->second; + } else { + std::cout << "get_v16: unable to locate '" << name << "'\n"; + } + return std::nullopt; +} + +MemoryStorage::SetVariableStatusEnum MemoryStorage::set_v16(const std::string& name, const std::string& value) { + // since V16 items are unique, just search through the storage items + // to locate it + SetVariableStatusEnum result{SetVariableStatusEnum::UnknownVariable}; + + auto it = locate_v16(name); + if (it) { + it.value()->second = value; + result = SetVariableStatusEnum::Accepted; + } else { + auto found = keys::convert(name); + bool create = found.has_value(); + + if (name.find("MeterPublicKey[") == 0) { + create = true; + } + + if (create) { + std::cout << "set_v16: unable to locate '" << name << "' creating\n"; + vars_additional.insert({name, value}); + result = SetVariableStatusEnum::Accepted; + + } else { + std::cout << "set_v16: unable to locate '" << name << "' ignoring\n"; + } + } + + return result; +} + +MemoryStorage::SetVariableStatusEnum MemoryStorage::set_v16_custom(const std::string& name, const std::string& value) { + // since V16 items are unique, just search through the storage items + // to locate it + + auto it = locate_v16(name); + if (it) { + it.value()->second = value; + } else { + vars_additional.insert({name, value}); + } + + return SetVariableStatusEnum::Accepted; +} + void MemoryStorage::set_readonly(const std::string& key) { read_only.insert(key); } void MemoryStorage::set(const std::string_view& component, const std::string_view& variable, const std::string_view& value) { - Component component_id; - Variable variable_id; - - component_id.name = std::string{component}; - variable_id.name = std::string{variable}; - (void)set_value(component_id, variable_id, AttributeEnum::Actual, std::string{value}, "TestCase"); + const std::string variable_v{variable}; + std::cout << "set " << component << '[' << variable << "] = '" << value << "'\n"; + if (component == "Internal") { + // std::cout << "Internal[" << variable_id.name << "]=" << value << '\n'; + vars_internal[variable_v] = value; + } else if (component == "Core") { + // std::cout << "Core[" << variable << "]=" << value << '\n'; + vars_core[variable_v] = value; + } else if (component == "FirmwareManagement") { + // std::cout << "FirmwareManagement[" << variable << "]=" << value << '\n'; + vars_firmware_management[variable_v] = value; + } else if (component == "SmartCharging") { + // std::cout << "SmartCharging[" << variable << "]=" << value << '\n'; + vars_smart_charging[variable_v] = value; + } else if (component == "Security") { + // std::cout << "Security[" << variable << "]=" << value << '\n'; + vars_security[variable_v] = value; + } else if (component == "LocalAuthListManagement") { + // std::cout << "LocalAuthListManagement[" << variable << "]=" << value << '\n'; + vars_local_auth_list[variable_v] = value; + } else if (component == "PnC") { + // std::cout << "PnC[" << variable << "]=" << value << '\n'; + vars_pnc[variable_v] = value; + } else if (component == "CostAndPrice") { + // std::cout << "CostAndPrice[" << variable << "]=" << value << '\n'; + vars_california_pricing[variable_v] = value; + } else if (component == "Custom") { + // std::cout << "Custom[" << variable << "]=" << value << '\n'; + vars_custom[variable_v] = value; + } else { + std::cerr << "set not implemented for: " << component << '\n'; + } } std::string MemoryStorage::get(const std::string_view& component, const std::string_view& variable) { @@ -247,75 +353,21 @@ MemoryStorage::GetVariableStatusEnum MemoryStorage::get_variable(const Component const AttributeEnum& attribute_enum, std::string& value, bool allow_write_only) const { auto result = GetVariableStatusEnum::UnknownVariable; - if (component_id.name == "Internal") { - if (const auto it = vars_internal.find(variable_id.name); it != vars_internal.end()) { - MemoryStorage::VariableAttribute va; - // std::cout << "Internal[" << it->first << "]==" << it->second << '\n'; - value = it->second; - result = GetVariableStatusEnum::Accepted; - } - } else if (component_id.name == "Core") { - if (const auto it = vars_core.find(variable_id.name); it != vars_core.end()) { - MemoryStorage::VariableAttribute va; - // std::cout << "Core[" << it->first << "]==" << it->second << '\n'; - value = it->second; - result = GetVariableStatusEnum::Accepted; - } - } else if (component_id.name == "FirmwareManagement") { - if (const auto it = vars_firmware_management.find(variable_id.name); it != vars_firmware_management.end()) { - MemoryStorage::VariableAttribute va; - // std::cout << "FirmwareManagement[" << it->first << "]==" << it->second << '\n'; - value = it->second; - result = GetVariableStatusEnum::Accepted; - } - } else if (component_id.name == "SmartCharging") { - if (const auto it = vars_smart_charging.find(variable_id.name); it != vars_smart_charging.end()) { - MemoryStorage::VariableAttribute va; - // std::cout << "SmartCharging[" << it->first << "]==" << it->second << '\n'; - value = it->second; - result = GetVariableStatusEnum::Accepted; - } - } else if (component_id.name == "Security") { - if (const auto it = vars_security.find(variable_id.name); it != vars_security.end()) { - MemoryStorage::VariableAttribute va; - // std::cout << "Security[" << it->first << "]==" << it->second << '\n'; - value = it->second; - result = GetVariableStatusEnum::Accepted; - } - } else if (component_id.name == "LocalAuthListManagement") { - if (const auto it = vars_local_auth_list.find(variable_id.name); it != vars_local_auth_list.end()) { - MemoryStorage::VariableAttribute va; - // std::cout << "LocalAuthListManagement[" << it->first << "]==" << it->second << '\n'; - value = it->second; - result = GetVariableStatusEnum::Accepted; - } - } else if (component_id.name == "Pnc") { - if (const auto it = vars_pnc.find(variable_id.name); it != vars_pnc.end()) { - MemoryStorage::VariableAttribute va; - // std::cout << "Pnc[" << it->first << "]==" << it->second << '\n'; - value = it->second; - result = GetVariableStatusEnum::Accepted; - } - } else if (component_id.name == "CostAndPrice") { - if (const auto it = vars_california_pricing.find(variable_id.name); it != vars_california_pricing.end()) { - MemoryStorage::VariableAttribute va; - // std::cout << "CostAndPrice[" << it->first << "]==" << it->second << '\n'; - value = it->second; - result = GetVariableStatusEnum::Accepted; - } - } else if (component_id.name == "Custom") { - if (const auto it = vars_custom.find(variable_id.name); it != vars_custom.end()) { - MemoryStorage::VariableAttribute va; - // std::cout << "Custom[" << it->first << "]==" << it->second << '\n'; - value = it->second; - result = GetVariableStatusEnum::Accepted; - } + const auto name = keys::convert_v2(component_id, variable_id); + std::optional retrieved; + if (name.empty()) { + retrieved = get_v16(variable_id.name); } else { - result = GetVariableStatusEnum::Rejected; - std::cerr << "get_variable_attribute not implemented for: " << component_id.name << '\n'; + retrieved = get_v16(name); + } + if (retrieved) { + value = *retrieved; + result = GetVariableStatusEnum::Accepted; + std::cout << component_id.name << '[' << name << "] has value: '" << *retrieved << "'\n"; + } else { + std::cerr << "get_variable not implemented for: " << component_id.name << ':' << variable_id.name << " (" + << name << ")\n"; } - - // std::cout << component_id.name << '[' << variable_id.name << "] has value: " << result.has_value() << '\n'; return result; } @@ -324,48 +376,13 @@ MemoryStorage::SetVariableStatusEnum MemoryStorage::set_value(const Component& c const AttributeEnum& attribute_enum, const std::string& value, const std::string& source, bool allow_read_only) { - auto result = SetVariableStatusEnum::Accepted; - if (component_id.name == "Internal") { - // std::cout << "Internal[" << variable_id.name << "]=" << value << '\n'; - vars_internal[variable_id.name] = value; - result = SetVariableStatusEnum::Accepted; - } else if (component_id.name == "Core") { - // std::cout << "Core[" << variable_id.name << "]=" << value << '\n'; - vars_core[variable_id.name] = value; - result = SetVariableStatusEnum::Accepted; - } else if (component_id.name == "FirmwareManagement") { - // std::cout << "FirmwareManagement[" << variable_id.name << "]=" << value << '\n'; - vars_firmware_management[variable_id.name] = value; - result = SetVariableStatusEnum::Accepted; - } else if (component_id.name == "SmartCharging") { - // std::cout << "SmartCharging[" << variable_id.name << "]=" << value << '\n'; - vars_smart_charging[variable_id.name] = value; - result = SetVariableStatusEnum::Accepted; - } else if (component_id.name == "Security") { - // std::cout << "Security[" << variable_id.name << "]=" << value << '\n'; - vars_security[variable_id.name] = value; - result = SetVariableStatusEnum::Accepted; - } else if (component_id.name == "LocalAuthListManagement") { - // std::cout << "LocalAuthListManagement[" << variable_id.name << "]=" << value << '\n'; - vars_local_auth_list[variable_id.name] = value; - result = SetVariableStatusEnum::Accepted; - } else if (component_id.name == "PnC") { - // std::cout << "PnC[" << variable_id.name << "]=" << value << '\n'; - vars_pnc[variable_id.name] = value; - result = SetVariableStatusEnum::Accepted; - } else if (component_id.name == "CostAndPrice") { - // std::cout << "CostAndPrice[" << variable_id.name << "]=" << value << '\n'; - vars_california_pricing[variable_id.name] = value; - result = SetVariableStatusEnum::Accepted; - } else if (component_id.name == "Custom") { - // std::cout << "Custom[" << variable_id.name << "]=" << value << '\n'; - vars_custom[variable_id.name] = value; - result = SetVariableStatusEnum::Accepted; + const auto key_str = keys::convert_v2(component_id, variable_id); + MemoryStorage::SetVariableStatusEnum result; + if (key_str.empty()) { + result = set_v16_custom(variable_id.name, value); } else { - result = SetVariableStatusEnum::Rejected; - std::cerr << "set_variable_attribute not implemented for: " << component_id.name << '\n'; + result = set_v16(key_str, value); } - return result; } @@ -381,24 +398,26 @@ std::optional MemoryStorage::get_mutability(const const Variable& variable_id, const AttributeEnum& attribute_enum) { std::optional result; - const auto key_str = std::string{variable_id.name}; - std::string value; - if (get_variable(component_id, variable_id, attribute_enum, value) == v2::GetVariableStatusEnum::Accepted) { - const auto sv_key_opt = keys::convert(key_str); - if (sv_key_opt) { - const auto sv_key = sv_key_opt.value(); - if (sv_key == keys::valid_keys::AuthorizationKey) { - result = MemoryStorage::MutabilityEnum::WriteOnly; - } else { - result = (keys::is_readonly(sv_key)) ? MemoryStorage::MutabilityEnum::ReadOnly - : MemoryStorage::MutabilityEnum::ReadWrite; - } + auto key_str = keys::convert_v2(component_id, variable_id); + const auto sv_key_opt = keys::convert(key_str); + if (sv_key_opt) { + const auto sv_key = sv_key_opt.value(); + if (sv_key == keys::valid_keys::AuthorizationKey) { + result = MemoryStorage::MutabilityEnum::WriteOnly; } else { - if (const auto it = read_only.find(key_str); it == read_only.end()) { + result = (keys::is_readonly(sv_key)) ? MemoryStorage::MutabilityEnum::ReadOnly + : MemoryStorage::MutabilityEnum::ReadWrite; + } + } else { + if (const auto it = read_only.find(key_str); it == read_only.end()) { + // check if key exists (not in the read only list) + const std::string name = (key_str.empty()) ? std::string{variable_id.name} : key_str; + auto found = locate_v16(name); + if (found) { result = MemoryStorage::MutabilityEnum::ReadWrite; - } else { - result = MemoryStorage::MutabilityEnum::ReadOnly; } + } else { + result = MemoryStorage::MutabilityEnum::ReadOnly; } } return result; @@ -407,12 +426,16 @@ std::optional MemoryStorage::get_mutability(const std::optional MemoryStorage::get_variable_meta_data(const Component& component_id, const Variable& variable_id) { std::optional result; - std::string value; - if (get_variable(component_id, variable_id, AttributeEnum::Actual, value) == GetVariableStatusEnum::Accepted) { + const auto key_str = keys::convert_v2(component_id, variable_id); + const auto retrieved = get_v16(key_str); + if (retrieved) { MemoryStorage::VariableMetaData md; md.characteristics.dataType = v2::DataEnum::string; md.characteristics.supportsMonitoring = false; result = std::move(md); + } else { + std::cerr << "get_variable_meta_data not implemented for: " << component_id.name << ':' << variable_id.name + << " (" << key_str << ")\n"; } return result; } diff --git a/lib/everest/ocpp/tests/lib/ocpp/v16/v2config/memory_storage.hpp b/lib/everest/ocpp/tests/lib/ocpp/v16/v2config/memory_storage.hpp index cb14d75912..26b39d0bd3 100644 --- a/lib/everest/ocpp/tests/lib/ocpp/v16/v2config/memory_storage.hpp +++ b/lib/everest/ocpp/tests/lib/ocpp/v16/v2config/memory_storage.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -16,10 +17,8 @@ namespace ocpp::v16::stubs { class MemoryStorage : public ocpp::v2::DeviceModelInterface { -private: - std::set read_only; - public: + using Storage = std::map; using VariableAttribute = ocpp::v2::VariableAttribute; using Component = ocpp::v2::Component; using ComponentVariable = ocpp::v2::ComponentVariable; @@ -43,6 +42,15 @@ class MemoryStorage : public ocpp::v2::DeviceModelInterface { using ReportData = ocpp::v2::ReportData; using ReportBaseEnum = ocpp::v2::ReportBaseEnum; +private: + std::set read_only; + + std::optional locate_v16(const std::string& name) const; + std::optional get_v16(const std::string& name) const; + SetVariableStatusEnum set_v16(const std::string& name, const std::string& value); + SetVariableStatusEnum set_v16_custom(const std::string& name, const std::string& value); + +public: MemoryStorage(); void set_readonly(const std::string& key); @@ -137,65 +145,67 @@ class MemoryStorageProxy : public ocpp::v2::DeviceModelInterface { GetVariableStatusEnum get_variable(const Component& component_id, const Variable& variable_id, const AttributeEnum& attribute_enum, std::string& value, - bool allow_write_only = false) const { - return storage.get_variable(component_id, variable_id, attribute_enum, value); + bool allow_write_only) const override { + return storage.get_variable(component_id, variable_id, attribute_enum, value, allow_write_only); } SetVariableStatusEnum set_value(const Component& component_id, const Variable& variable_id, const AttributeEnum& attribute_enum, const std::string& value, - const std::string& source, bool allow_read_only = false) { - return storage.set_value(component_id, variable_id, attribute_enum, value, source); + const std::string& source, bool allow_read_only) override { + return storage.set_value(component_id, variable_id, attribute_enum, value, source, allow_read_only); } SetVariableStatusEnum set_read_only_value(const Component& component_id, const Variable& variable_id, const AttributeEnum& attribute_enum, const std::string& value, - const std::string& source) { + const std::string& source) override { return storage.set_read_only_value(component_id, variable_id, attribute_enum, value, source); } std::optional get_mutability(const Component& component_id, const Variable& variable_id, - const AttributeEnum& attribute_enum) { + const AttributeEnum& attribute_enum) override { return storage.get_mutability(component_id, variable_id, attribute_enum); } - std::optional get_variable_meta_data(const Component& component_id, const Variable& variable_id) { + std::optional get_variable_meta_data(const Component& component_id, + const Variable& variable_id) override { return storage.get_variable_meta_data(component_id, variable_id); } - std::vector get_base_report_data(const ReportBaseEnum& report_base) { + std::vector get_base_report_data(const ReportBaseEnum& report_base) override { return storage.get_base_report_data(report_base); } - std::vector get_custom_report_data( - const std::optional>& component_variables = std::nullopt, - const std::optional>& component_criteria = std::nullopt) { + std::vector + get_custom_report_data(const std::optional>& component_variables, + const std::optional>& component_criteria) override { return storage.get_custom_report_data(component_variables, component_criteria); } - std::vector set_monitors(const std::vector& requests, - const VariableMonitorType type = VariableMonitorType::CustomMonitor) { + std::vector + set_monitors(const std::vector& requests, + const VariableMonitorType type = VariableMonitorType::CustomMonitor) override { return storage.set_monitors(requests); } - bool update_monitor_reference(std::int32_t monitor_id, const std::string& reference_value) { + bool update_monitor_reference(std::int32_t monitor_id, const std::string& reference_value) override { return storage.update_monitor_reference(monitor_id, reference_value); } - std::vector get_periodic_monitors() { + std::vector get_periodic_monitors() override { return storage.get_periodic_monitors(); } std::vector get_monitors(const std::vector& criteria, - const std::vector& component_variables) { + const std::vector& component_variables) override { return storage.get_monitors(criteria, component_variables); } std::vector clear_monitors(const std::vector& request_ids, - bool allow_protected = false) { - return storage.clear_monitors(request_ids); + bool allow_protected) override { + return storage.clear_monitors(request_ids, allow_protected); } - std::int32_t clear_custom_monitors() { + std::int32_t clear_custom_monitors() override { return storage.clear_custom_monitors(); } @@ -203,18 +213,18 @@ class MemoryStorageProxy : public ocpp::v2::DeviceModelInterface { std::function& monitors, const Component& component, const Variable& variable, const VariableCharacteristics& characteristics, const VariableAttribute& attribute, - const std::string& value_previous, const std::string& value_current)>&& listener) { + const std::string& value_previous, const std::string& value_current)>&& listener) override { return storage.register_variable_listener(std::move(listener)); } void register_monitor_listener( std::function&& listener) { + const VariableAttribute& attribute, const std::string& current_value)>&& listener) override { return storage.register_monitor_listener(std::move(listener)); } - void check_integrity(const std::map& evse_connector_structure) { + void check_integrity(const std::map& evse_connector_structure) override { return storage.check_integrity(evse_connector_structure); } }; diff --git a/lib/everest/ocpp/tests/lib/ocpp/v16/v2config/test_config.cpp b/lib/everest/ocpp/tests/lib/ocpp/v16/v2config/test_config.cpp index ae46f28538..2f1efd19d3 100644 --- a/lib/everest/ocpp/tests/lib/ocpp/v16/v2config/test_config.cpp +++ b/lib/everest/ocpp/tests/lib/ocpp/v16/v2config/test_config.cpp @@ -4,6 +4,8 @@ #include #include "configuration_stub.hpp" +#include "ocpp/v16/known_keys.hpp" +#include "ocpp/v2/ocpp_types.hpp" #include #include @@ -38,4 +40,37 @@ TEST(ConnectorID, Build) { EXPECT_EQ(CPCB::MeterPublicKey_string(123), "MeterPublicKey[123]"); } +using namespace ocpp; + +TEST(V2Mapping, V16ToV2) { + using namespace ocpp::v16::keys; + using namespace ocpp::v2; + + auto res = convert_v2(valid_keys::CpoName); + ASSERT_TRUE(res); + auto component = std::get(res.value()); + auto variable = std::get(res.value()); + EXPECT_EQ(component.name, "SecurityCtrlr"); + EXPECT_EQ(variable.name, "OrganizationName"); + + res = convert_v2("CpoName"); + ASSERT_TRUE(res); + component = std::get(res.value()); + variable = std::get(res.value()); + EXPECT_EQ(component.name, "SecurityCtrlr"); + EXPECT_EQ(variable.name, "OrganizationName"); +} + +TEST(V2Mapping, V2ToV16) { + using namespace ocpp::v16::keys; + using namespace ocpp::v2; + + Component comp; + comp.name = "SecurityCtrlr"; + Variable var; + var.name = "OrganizationName"; + auto res = convert_v2(comp, var); + EXPECT_EQ(res, "CpoName"); +} + } // namespace