// SPDX-License-Identifier: Apache-2.0 // Copyright chargebyte GmbH and Contributors to EVerest #ifndef DATASTORE_HPP #define DATASTORE_HPP #include "GenericInfoStore.hpp" #include "SessionInfo.hpp" #include #include #include #include #include #include namespace RPCDataTypes = types::json_rpc_api; namespace data { enum class EVSEStatusField { ActiveConnectorIndex, ChargingAllowed, State, ErrorPresent, ChargeProtocol, ChargingDurationS, ChargedEnergyWh, DischargedEnergyWh, Available, Count }; template constexpr auto to_underlying_value(T value) { return static_cast>(value); } static constexpr auto NUMBER_OF_EVSE_STATUS_FIELDS = to_underlying_value(EVSEStatusField::Count); static_assert(NUMBER_OF_EVSE_STATUS_FIELDS == to_underlying_value(EVSEStatusField::Available) + 1, "NUMBER_OF_EVSE_STATUS_FIELDS should be in sync with EVSEStatusField enum definition"); class ChargerInfoStore : public GenericInfoStore { public: // we currently don't get this info from the system yet, so allow setting to unknown void set_unknown(); }; class ChargerErrorsStore : public GenericInfoStore> { public: void add_error(const types::json_rpc_api::ErrorObj& error); void clear_error(const types::json_rpc_api::ErrorObj& error); }; class EVSEInfoStore : public GenericInfoStore { public: void set_supported_energy_transfer_modes( const std::vector& supported_energy_transfer_modes); void set_index(int32_t index); void set_id(const std::string& id); void set_available_connectors(const std::vector& connectors); void set_available_connector(types::json_rpc_api::ConnectorInfoObj& available_connector); void set_is_ac_transfer_mode(bool is_ac); bool get_is_ac_transfer_mode() const; int32_t get_index(); std::vector get_available_connectors() const; private: std::atomic is_ac_transfer_mode; }; class EVSEStatusStore : public GenericInfoStore { private: std::bitset field_status{0}; std::condition_variable cv_current_limit_applied; std::mutex mtx_current_limit_applied; float requested_current_limit{0.0f}; float configured_current_limit{0.0f}; void update_data_is_valid(); void set_field_status(EVSEStatusField field); // Internal method to set the current limit in the AC charge parameters without checking for pending requests void set_ac_charge_param_evse_current_limit_internal(float max_current); public: EVSEStatusStore(); // Set the active connector index void set_active_connector_index(int32_t active_connector_index); // set the charging allowed flag void set_charging_allowed(bool charging_allowed); // set the EVSE state void set_state(types::json_rpc_api::EVSEStateEnum state); // set EVSE errors void set_error_present(const bool error_present); // set the charge protocol void set_charge_protocol(types::json_rpc_api::ChargeProtocolEnum charge_protocol); // set the charging duration in seconds void set_charging_duration_s(int32_t charging_duration_s); // set the charged energy in Wh void set_charged_energy_wh(float charged_energy_wh); // set the discharged energy in Wh void set_discharged_energy_wh(float discharged_energy_wh); // set the available flag void set_available(bool available); // set the AC charge parameters void set_ac_charge_param(const std::optional& ac_charge_param); // set the DC charge parameters void set_dc_charge_param(const std::optional& dc_charge_param); // set the AC charge status void set_ac_charge_status(const std::optional& ac_charge_status); // set the DC charge status void set_dc_charge_status(const std::optional& dc_charge_status); // set the display parameters void set_display_parameters(const std::optional& display_parameters); // set the AC max phase count in the AC charge parameters void set_ac_charge_param_evse_max_phase_count(int32_t phase_count); // set the AC current limit and notify any waiting request threads void set_ac_charge_param_evse_max_current(float current_limit); // wait until the current limit is applied or timeout occurs bool wait_until_current_limit_applied(float current_limit, std::chrono::milliseconds timeout_ms); types::json_rpc_api::EVSEStateEnum get_state() const; std::optional get_ac_charge_param(); std::optional get_dc_charge_param(); }; class HardwareCapabilitiesStore : public GenericInfoStore {}; class MeterDataStore : public GenericInfoStore {}; // This is the data store for a single EVSE. An EVSE can have multiple connectors. struct DataStoreEvse { EVSEInfoStore evseinfo; EVSEStatusStore evsestatus; MeterDataStore meterdata; HardwareCapabilitiesStore hardwarecapabilities; SessionInfoStore sessioninfo; }; // This is the main data store for the charger. A charger can have multiple EVSEs, each with multiple connectors. // For more information see 3-Tier model definition of OCPP 2.0. struct DataStoreCharger { ChargerInfoStore chargerinfo; ChargerErrorsStore chargererrors; std::string everest_version; std::vector> evses; // get the EVSE data with a specific id data::DataStoreEvse* get_evse_store(const int32_t evse_index) { if (evses.empty()) { EVLOG_error << "No EVSEs found in the data store."; return nullptr; } for (const auto& evse : evses) { const auto tmp_index = evse->evseinfo.get_index(); if (tmp_index == evse_index) { return evse.get(); } } EVLOG_error << "EVSE index " << evse_index << " not found in data store."; return nullptr; } }; } // namespace data #endif // DATASTORE_HPP