- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
168 lines
6.4 KiB
C++
168 lines
6.4 KiB
C++
// 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 <atomic>
|
|
#include <bitset>
|
|
#include <chrono>
|
|
#include <condition_variable>
|
|
#include <everest/logging.hpp>
|
|
#include <type_traits>
|
|
|
|
namespace RPCDataTypes = types::json_rpc_api;
|
|
|
|
namespace data {
|
|
|
|
enum class EVSEStatusField {
|
|
ActiveConnectorIndex,
|
|
ChargingAllowed,
|
|
State,
|
|
ErrorPresent,
|
|
ChargeProtocol,
|
|
ChargingDurationS,
|
|
ChargedEnergyWh,
|
|
DischargedEnergyWh,
|
|
Available,
|
|
Count
|
|
};
|
|
|
|
template <typename T> constexpr auto to_underlying_value(T value) {
|
|
return static_cast<std::underlying_type_t<T>>(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<RPCDataTypes::ChargerInfoObj> {
|
|
public:
|
|
// we currently don't get this info from the system yet, so allow setting to unknown
|
|
void set_unknown();
|
|
};
|
|
|
|
class ChargerErrorsStore : public GenericInfoStore<std::vector<types::json_rpc_api::ErrorObj>> {
|
|
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<RPCDataTypes::EVSEInfoObj> {
|
|
public:
|
|
void set_supported_energy_transfer_modes(
|
|
const std::vector<types::json_rpc_api::EnergyTransferModeEnum>& supported_energy_transfer_modes);
|
|
void set_index(int32_t index);
|
|
void set_id(const std::string& id);
|
|
void set_available_connectors(const std::vector<RPCDataTypes::ConnectorInfoObj>& 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<types::json_rpc_api::ConnectorInfoObj> get_available_connectors() const;
|
|
|
|
private:
|
|
std::atomic<bool> is_ac_transfer_mode;
|
|
};
|
|
|
|
class EVSEStatusStore : public GenericInfoStore<RPCDataTypes::EVSEStatusObj> {
|
|
private:
|
|
std::bitset<NUMBER_OF_EVSE_STATUS_FIELDS> 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<RPCDataTypes::ACChargeParametersObj>& ac_charge_param);
|
|
// set the DC charge parameters
|
|
void set_dc_charge_param(const std::optional<RPCDataTypes::DCChargeParametersObj>& dc_charge_param);
|
|
// set the AC charge status
|
|
void set_ac_charge_status(const std::optional<RPCDataTypes::ACChargeStatusObj>& ac_charge_status);
|
|
// set the DC charge status
|
|
void set_dc_charge_status(const std::optional<RPCDataTypes::DCChargeStatusObj>& dc_charge_status);
|
|
// set the display parameters
|
|
void set_display_parameters(const std::optional<RPCDataTypes::DisplayParametersObj>& 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<RPCDataTypes::ACChargeParametersObj> get_ac_charge_param();
|
|
std::optional<RPCDataTypes::DCChargeParametersObj> get_dc_charge_param();
|
|
};
|
|
class HardwareCapabilitiesStore : public GenericInfoStore<RPCDataTypes::HardwareCapabilitiesObj> {};
|
|
class MeterDataStore : public GenericInfoStore<RPCDataTypes::MeterDataObj> {};
|
|
|
|
// 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<std::unique_ptr<DataStoreEvse>> 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
|