Add extracted tools: CitrineOS, OpenOCPP, ShapeShifter

- 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
This commit is contained in:
Eric F
2026-06-08 00:38:27 -04:00
parent 468cfeaa50
commit d398a6ced2
7326 changed files with 1177561 additions and 7 deletions

View File

@@ -0,0 +1,208 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright chargebyte GmbH and Contributors to EVerest
#include "Conversions.hpp"
namespace types {
namespace json_rpc_api {
EVSEStateEnum evse_manager_session_event_to_evse_state(types::evse_manager::SessionEvent state) {
using Event = types::evse_manager::SessionEventEnum;
switch (state.event) {
case Event::Enabled:
return EVSEStateEnum::Unplugged;
case Event::Disabled:
return EVSEStateEnum::Disabled;
case Event::AuthRequired:
return EVSEStateEnum::AuthRequired;
case Event::PrepareCharging:
[[fallthrough]];
case Event::SessionStarted:
[[fallthrough]];
case Event::SessionResumed:
[[fallthrough]];
case Event::TransactionStarted:
return EVSEStateEnum::Preparing;
case Event::ChargingStarted:
return EVSEStateEnum::Charging;
case Event::ChargingPausedEV:
return EVSEStateEnum::ChargingPausedEV;
case Event::ChargingPausedEVSE:
return EVSEStateEnum::ChargingPausedEVSE;
case Event::ChargingFinished:
return EVSEStateEnum::Finished;
case Event::StoppingCharging:
return EVSEStateEnum::FinishedEV;
case Event::TransactionFinished: {
if (state.transaction_finished.has_value() &&
state.transaction_finished->reason == types::evse_manager::StopTransactionReason::Local) {
return EVSEStateEnum::FinishedEVSE;
} else {
return EVSEStateEnum::Finished;
}
break;
}
case Event::PluginTimeout:
return EVSEStateEnum::AuthTimeout;
case Event::ReservationStart:
return EVSEStateEnum::Reserved;
case Event::ReservationEnd:
[[fallthrough]];
case Event::SessionFinished:
return EVSEStateEnum::Unplugged;
case Event::SwitchingPhases:
return EVSEStateEnum::SwitchingPhases;
case Event::Authorized:
[[fallthrough]];
case Event::Deauthorized:
[[fallthrough]];
default:
return EVSEStateEnum::Unknown;
}
}
ChargeProtocolEnum evse_manager_protocol_to_charge_protocol(const std::string& protocol) {
if (protocol == "IEC61851-1") {
return ChargeProtocolEnum::IEC61851;
} else if (protocol == "DIN70121") {
return ChargeProtocolEnum::DIN70121;
} else if (protocol.compare(0, 11, "ISO15118-20") == 0) {
return ChargeProtocolEnum::ISO15118_20;
}
// This check must be after the ISO15118-20 check
else if (protocol.compare(0, 10, "ISO15118-2") == 0) {
return ChargeProtocolEnum::ISO15118;
} else {
return ChargeProtocolEnum::Unknown;
}
}
ErrorObj everest_error_to_rpc_error(const Everest::error::Error& error_object) {
ErrorObj rpc_error;
rpc_error.type = error_object.type;
rpc_error.description = error_object.description;
rpc_error.message = error_object.message;
switch (error_object.severity) {
case Everest::error::Severity::High:
rpc_error.severity = Severity::High;
break;
case Everest::error::Severity::Medium:
rpc_error.severity = Severity::Medium;
break;
case Everest::error::Severity::Low:
rpc_error.severity = Severity::Low;
break;
default:
throw std::out_of_range("Provided severity " + std::to_string(static_cast<int>(error_object.severity)) +
" could not be converted to enum of type SeverityEnum");
}
rpc_error.origin.module_id = error_object.origin.module_id;
rpc_error.origin.implementation_id = error_object.origin.implementation_id;
rpc_error.origin.evse_index = 0;
rpc_error.origin.connector_index = 0;
if (error_object.origin.mapping.has_value()) {
rpc_error.origin.evse_index = error_object.origin.mapping.value().evse;
if (error_object.origin.mapping.value().connector.has_value()) {
rpc_error.origin.connector_index = error_object.origin.mapping.value().connector.value();
}
}
rpc_error.timestamp = Everest::Date::to_rfc3339(error_object.timestamp);
rpc_error.uuid = error_object.uuid.to_string();
return rpc_error;
}
std::vector<EnergyTransferModeEnum> iso15118_energy_transfer_modes_to_json_rpc_api(
const std::vector<types::iso15118::EnergyTransferMode>& supported_energy_transfer_modes,
bool& is_ac_transfer_mode) {
std::vector<EnergyTransferModeEnum> tmp{};
if (supported_energy_transfer_modes.empty()) {
// in case EvseManager lists no transfer modes at all
is_ac_transfer_mode = true;
return tmp;
}
is_ac_transfer_mode = false;
for (const auto& mode : supported_energy_transfer_modes) {
switch (mode) {
case types::iso15118::EnergyTransferMode::AC_single_phase_core:
tmp.push_back(EnergyTransferModeEnum::AC_single_phase_core);
is_ac_transfer_mode = true;
break;
case types::iso15118::EnergyTransferMode::AC_two_phase:
tmp.push_back(EnergyTransferModeEnum::AC_two_phase);
is_ac_transfer_mode = true;
break;
case types::iso15118::EnergyTransferMode::AC_three_phase_core:
tmp.push_back(EnergyTransferModeEnum::AC_three_phase_core);
is_ac_transfer_mode = true;
break;
case types::iso15118::EnergyTransferMode::DC_core:
tmp.push_back(EnergyTransferModeEnum::DC_core);
break;
case types::iso15118::EnergyTransferMode::DC_extended:
tmp.push_back(EnergyTransferModeEnum::DC_extended);
break;
case types::iso15118::EnergyTransferMode::DC_combo_core:
tmp.push_back(EnergyTransferModeEnum::DC_combo_core);
break;
case types::iso15118::EnergyTransferMode::DC_unique:
tmp.push_back(EnergyTransferModeEnum::DC_unique);
break;
case types::iso15118::EnergyTransferMode::DC:
tmp.push_back(EnergyTransferModeEnum::DC);
break;
case types::iso15118::EnergyTransferMode::AC_BPT:
tmp.push_back(EnergyTransferModeEnum::AC_BPT);
is_ac_transfer_mode = true;
break;
case types::iso15118::EnergyTransferMode::AC_BPT_DER:
tmp.push_back(EnergyTransferModeEnum::AC_BPT_DER);
is_ac_transfer_mode = true;
break;
case types::iso15118::EnergyTransferMode::AC_DER:
tmp.push_back(EnergyTransferModeEnum::AC_DER);
is_ac_transfer_mode = true;
break;
case types::iso15118::EnergyTransferMode::DC_BPT:
tmp.push_back(EnergyTransferModeEnum::DC_BPT);
break;
case types::iso15118::EnergyTransferMode::DC_ACDP:
tmp.push_back(EnergyTransferModeEnum::DC_ACDP);
break;
case types::iso15118::EnergyTransferMode::DC_ACDP_BPT:
tmp.push_back(EnergyTransferModeEnum::DC_ACDP_BPT);
break;
case types::iso15118::EnergyTransferMode::WPT:
tmp.push_back(EnergyTransferModeEnum::WPT);
is_ac_transfer_mode = true; // TBD
break;
case types::iso15118::EnergyTransferMode::MCS:
tmp.push_back(EnergyTransferModeEnum::MCS);
break;
case types::iso15118::EnergyTransferMode::MCS_BPT:
tmp.push_back(EnergyTransferModeEnum::MCS_BPT);
break;
default:
throw std::invalid_argument("Unsupported energy transfer mode");
}
}
return tmp;
}
void to_json(json& j, const EnergyTransferModeEnum& k) {
// the required parts of the type
j = energy_transfer_mode_enum_to_string(k);
}
} // namespace json_rpc_api
} // namespace types

View File

@@ -0,0 +1,33 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright chargebyte GmbH and Contributors to EVerest
#ifndef CONVERSIONS_HPP
#define CONVERSIONS_HPP
#include <generated/types/evse_manager.hpp>
#include <types/json_rpc_api/json_rpc_api.hpp>
#include <utils/error.hpp>
namespace types {
namespace json_rpc_api {
EVSEStateEnum evse_manager_session_event_to_evse_state(types::evse_manager::SessionEvent state);
ChargeProtocolEnum evse_manager_protocol_to_charge_protocol(const std::string& protocol);
types::json_rpc_api::ErrorObj everest_error_to_rpc_error(const Everest::error::Error& error_object);
std::vector<types::json_rpc_api::EnergyTransferModeEnum> iso15118_energy_transfer_modes_to_json_rpc_api(
const std::vector<types::iso15118::EnergyTransferMode>& supported_energy_transfer_modes, bool& is_ac_transfer_mode);
/**
* @brief Serializes an EnergyTransferModeEnum object to a JSON representation.
*
* This function converts the given EnergyTransferModeEnum value into its corresponding
* JSON format and assigns it to the provided json object. This function is necessary
* for properly serializing the data for JSON-RPC API responses.
*
* @param j Reference to a json object where the serialized data will be stored.
* @param k The EnergyTransferModeEnum value to be serialized.
*/
void to_json(json& j, const types::json_rpc_api::EnergyTransferModeEnum& k);
} // namespace json_rpc_api
} // namespace types
#endif // CONVERSIONS_HPP

View File

@@ -0,0 +1,56 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright chargebyte GmbH and Contributors to EVerest
#include "ErrorHandler.hpp"
#include <everest/logging.hpp>
namespace helpers {
void handle_error_raised(data::DataStoreCharger& data, const types::json_rpc_api::ErrorObj& error) {
try {
data.chargererrors.add_error(error);
} catch (const std::runtime_error& e) {
EVLOG_warning << "Error while adding error to the data store: " << e.what();
}
// only set error present for EVSE specific errors. Index 0 is reserved for the charger itself
if (!error.origin.evse_index.has_value() || error.origin.evse_index.value() == 0) {
return;
}
auto tmp_evse_store = data.get_evse_store(error.origin.evse_index.value());
if (tmp_evse_store != nullptr) {
EVLOG_debug << "Setting error present for EVSE index: " << error.origin.evse_index.value();
tmp_evse_store->evsestatus.set_error_present(true);
} else {
EVLOG_error << "Cannot set error present for EVSE index: " << error.origin.evse_index.value();
}
}
void handle_error_cleared(data::DataStoreCharger& data, const types::json_rpc_api::ErrorObj& error) {
try {
data.chargererrors.clear_error(error);
} catch (const std::runtime_error& e) {
EVLOG_warning << "Error while clearing error from the data store: " << e.what();
}
// only clear error present for EVSE specific errors. Index 0 is reserved for the charger itself
if (!error.origin.evse_index.has_value() || error.origin.evse_index.value() == 0) {
return;
}
auto tmp_charger_errors = data.chargererrors.get_data();
if (tmp_charger_errors.has_value()) {
for (const auto& charger_error : tmp_charger_errors.value()) {
if (charger_error.origin.evse_index.has_value() &&
charger_error.origin.evse_index.value() == error.origin.evse_index.value()) {
return;
}
}
}
auto tmp_evse_store = data.get_evse_store(error.origin.evse_index.value());
if (tmp_evse_store != nullptr) {
tmp_evse_store->evsestatus.set_error_present(false);
}
}
} // namespace helpers

View File

@@ -0,0 +1,12 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright chargebyte GmbH and Contributors to EVerest
#ifndef ERROR_HANDLER_HPP
#define ERROR_HANDLER_HPP
#include "../data/DataStore.hpp"
namespace helpers {
void handle_error_raised(data::DataStoreCharger& data, const types::json_rpc_api::ErrorObj& error);
void handle_error_cleared(data::DataStoreCharger& data, const types::json_rpc_api::ErrorObj& error);
} // namespace helpers
#endif // ERROR_HANDLER_HPP

View File

@@ -0,0 +1,37 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright chargebyte GmbH and Contributors to EVerest
#include "LimitDecimalPlaces.hpp"
#include <cmath>
#include <iomanip>
#include <sstream>
namespace helpers {
// This function formats and rounds a double value to a specified number of decimal places
double round_double(double value, double step, int precision) {
double rounded = std::round(value / step) * step;
std::ostringstream oss;
oss << std::fixed << std::setprecision(precision) << rounded;
return std::stod(oss.str());
}
// This function recursively rounds all float values in a JSON object or array
void round_floats_in_json(nlohmann::json& j, int precision) {
if (precision == 0) {
return; // No rounding needed if precision is 0
}
if (j.is_object() || j.is_array()) {
for (auto& el : j) {
round_floats_in_json(el, precision);
}
} else if (j.is_number_float()) {
const double step = std::pow(10.0, -precision);
const double value = j.get<double>();
j = round_double(value, step, precision);
}
}
} // namespace helpers

View File

@@ -0,0 +1,13 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright chargebyte GmbH and Contributors to EVerest
#ifndef LIMIT_DECIMAL_PLACES_HPP
#define LIMIT_DECIMAL_PLACES_HPP
#include <nlohmann/json.hpp>
namespace helpers {
double round_double(double value, int precision = 3);
void round_floats_in_json(nlohmann::json& j, int precision = 3);
} // namespace helpers
#endif // LIMIT_DECIMAL_PLACES_HPP