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,134 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#include "errors.hpp"
#include "everest/logging.hpp"
std::tuple<bool, std::optional<ErrorDefinition>> parse_error_type(const std::string& payload) {
// parsing, getting raise
const auto e = json::parse(payload);
const auto raise = (e.value("raise", "false") == "true") ? true : false;
const auto error_type = static_cast<std::string>(e.at("error_type"));
if (error_type == "powermeter/CommunicationFault") {
return {raise, error_definitions::powermeter_CommunicationFault};
}
if (error_type == "DiodeFault") {
return {raise, error_definitions::evse_board_support_DiodeFault};
}
if (error_type == "BrownOut") {
return {raise, error_definitions::evse_board_support_BrownOut};
}
if (error_type == "EnergyManagement") {
return {raise, error_definitions::evse_board_support_EnergyManagement};
}
if (error_type == "PermanentFault") {
return {raise, error_definitions::evse_board_support_PermanentFault};
}
if (error_type == "MREC2GroundFailure") {
return {raise, error_definitions::evse_board_support_MREC2GroundFailure};
}
if (error_type == "MREC3HighTemperature") {
return {raise, error_definitions::evse_board_support_MREC3HighTemperature};
}
if (error_type == "MREC4OverCurrentFailure") {
return {raise, error_definitions::evse_board_support_MREC4OverCurrentFailure};
}
if (error_type == "MREC5OverVoltage") {
return {raise, error_definitions::evse_board_support_MREC5OverVoltage};
}
if (error_type == "MREC6UnderVoltage") {
return {raise, error_definitions::evse_board_support_MREC6UnderVoltage};
}
if (error_type == "MREC8EmergencyStop") {
return {raise, error_definitions::evse_board_support_MREC8EmergencyStop};
}
if (error_type == "MREC10InvalidVehicleMode") {
return {raise, error_definitions::evse_board_support_MREC10InvalidVehicleMode};
}
if (error_type == "MREC14PilotFault") {
return {raise, error_definitions::evse_board_support_MREC14PilotFault};
}
if (error_type == "MREC15PowerLoss") {
return {raise, error_definitions::evse_board_support_MREC15PowerLoss};
}
if (error_type == "MREC17EVSEContactorFault") {
return {raise, error_definitions::evse_board_support_MREC17EVSEContactorFault};
}
if (error_type == "MREC18CableOverTempDerate") {
return {raise, error_definitions::evse_board_support_MREC18CableOverTempDerate};
}
if (error_type == "MREC19CableOverTempStop") {
return {raise, error_definitions::evse_board_support_MREC19CableOverTempStop};
}
if (error_type == "MREC20PartialInsertion") {
return {raise, error_definitions::evse_board_support_MREC20PartialInsertion};
}
if (error_type == "MREC23ProximityFault") {
return {raise, error_definitions::evse_board_support_MREC23ProximityFault};
}
if (error_type == "MREC24ConnectorVoltageHigh") {
return {raise, error_definitions::evse_board_support_MREC24ConnectorVoltageHigh};
}
if (error_type == "MREC25BrokenLatch") {
return {raise, error_definitions::evse_board_support_MREC25BrokenLatch};
}
if (error_type == "MREC26CutCable") {
return {raise, error_definitions::evse_board_support_MREC26CutCable};
}
if (error_type == "TiltDetected") {
return {raise, error_definitions::evse_board_support_TiltDetected};
}
if (error_type == "WaterIngressDetected") {
return {raise, error_definitions::evse_board_support_WaterIngressDetected};
}
if (error_type == "EnclosureOpen") {
return {raise, error_definitions::evse_board_support_EnclosureOpen};
}
if (error_type == "ac_rcd_MREC2GroundFailure") {
return {raise, error_definitions::ac_rcd_MREC2GroundFailure};
}
if (error_type == "ac_rcd_VendorError") {
return {raise, error_definitions::ac_rcd_VendorError};
}
if (error_type == "ac_rcd_Selftest") {
return {raise, error_definitions::ac_rcd_Selftest};
}
if (error_type == "ac_rcd_AC") {
return {raise, error_definitions::ac_rcd_AC};
}
if (error_type == "ac_rcd_DC") {
return {raise, error_definitions::ac_rcd_DC};
}
if (error_type == "lock_ConnectorLockCapNotCharged") {
return {raise, error_definitions::connector_lock_ConnectorLockCapNotCharged};
}
if (error_type == "lock_ConnectorLockUnexpectedOpen") {
return {raise, error_definitions::connector_lock_ConnectorLockUnexpectedOpen};
}
if (error_type == "lock_ConnectorLockUnexpectedClose") {
return {raise, error_definitions::connector_lock_ConnectorLockUnexpectedClose};
}
if (error_type == "lock_ConnectorLockFailedLock") {
return {raise, error_definitions::connector_lock_ConnectorLockFailedLock};
}
if (error_type == "lock_ConnectorLockFailedUnlock") {
return {raise, error_definitions::connector_lock_ConnectorLockFailedUnlock};
}
if (error_type == "lock_MREC1ConnectorLockFailure") {
return {raise, error_definitions::connector_lock_MREC1ConnectorLockFailure};
}
if (error_type == "lock_VendorError") {
return {raise, error_definitions::connector_lock_VendorError};
}
EVLOG_error << "Unknown error raised via MQTT";
return {raise, std::nullopt};
}
Everest::error::Error create_error(const Everest::error::ErrorFactory& error_factory, const ErrorDefinition& def) {
return error_factory.create_error(def.type, def.sub_type, def.message, def.severity);
}

View File

@@ -0,0 +1,147 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
#include <optional>
#include <tuple>
#include <utils/error.hpp>
#include <utils/error/error_factory.hpp>
enum class ErrorTarget {
BoardSupport,
ConnectorLock,
Rcd,
Powermeter
};
struct ErrorDefinition {
const char* type;
const char* sub_type{""};
const char* message{""};
Everest::error::Severity severity{Everest::error::Severity::High};
ErrorTarget error_target;
};
Everest::error::Error create_error(const Everest::error::ErrorFactory& error_factory, const ErrorDefinition& def);
std::tuple<bool, std::optional<ErrorDefinition>> parse_error_type(const std::string& payload);
template <typename T> void forward_error(T& target, const Everest::error::Error& error, bool raise) {
if (raise) {
target->raise_error(error);
} else {
target->clear_error(error.type);
}
}
namespace error_definitions {
inline const auto connector_lock_ConnectorLockUnexpectedClose =
ErrorDefinition{"connector_lock/ConnectorLockUnexpectedClose"};
inline const auto evse_board_support_DiodeFault =
ErrorDefinition{"evse_board_support/DiodeFault", "", "Simulated fault event"};
inline const auto evse_board_support_BrownOut =
ErrorDefinition{"evse_board_support/BrownOut", "", "Simulated fault event"};
inline const auto evse_board_support_EnergyManagement =
ErrorDefinition{"evse_board_support/EnergyManagement", "", "Simulated fault event"};
inline const auto evse_board_support_PermanentFault =
ErrorDefinition{"evse_board_support/PermanentFault", "", "Simulated fault event"};
inline const auto evse_board_support_MREC2GroundFailure =
ErrorDefinition{"evse_board_support/MREC2GroundFailure", "", "Simulated fault event"};
inline const auto evse_board_support_MREC3HighTemperature =
ErrorDefinition{"evse_board_support/MREC3HighTemperature", "", "Simulated fault event"};
inline const auto evse_board_support_MREC4OverCurrentFailure =
ErrorDefinition{"evse_board_support/MREC4OverCurrentFailure", "", "Simulated fault event"};
inline const auto evse_board_support_MREC5OverVoltage =
ErrorDefinition{"evse_board_support/MREC5OverVoltage", "", "Simulated fault event"};
inline const auto evse_board_support_MREC6UnderVoltage =
ErrorDefinition{"evse_board_support/MREC6UnderVoltage", "", "Simulated fault event"};
inline const auto evse_board_support_MREC8EmergencyStop =
ErrorDefinition{"evse_board_support/MREC8EmergencyStop", "", "Simulated fault event"};
inline const auto evse_board_support_MREC10InvalidVehicleMode =
ErrorDefinition{"evse_board_support/MREC10InvalidVehicleMode", "", "Simulated fault event"};
inline const auto evse_board_support_MREC14PilotFault =
ErrorDefinition{"evse_board_support/MREC14PilotFault", "", "Simulated fault event"};
inline const auto evse_board_support_MREC15PowerLoss =
ErrorDefinition{"evse_board_support/MREC15PowerLoss", "", "Simulated fault event"};
inline const auto evse_board_support_MREC17EVSEContactorFault =
ErrorDefinition{"evse_board_support/MREC17EVSEContactorFault", "", "Simulated fault event"};
inline const auto evse_board_support_MREC18CableOverTempDerate =
ErrorDefinition{"evse_board_support/MREC18CableOverTempDerate", "", "Simulated fault event"};
inline const auto evse_board_support_MREC19CableOverTempStop =
ErrorDefinition{"evse_board_support/MREC19CableOverTempStop", "", "Simulated fault event"};
inline const auto evse_board_support_MREC20PartialInsertion =
ErrorDefinition{"evse_board_support/MREC20PartialInsertion", "", "Simulated fault event"};
inline const auto evse_board_support_MREC23ProximityFault =
ErrorDefinition{"evse_board_support/MREC23ProximityFault", "", "Simulated fault event"};
inline const auto evse_board_support_MREC24ConnectorVoltageHigh =
ErrorDefinition{"evse_board_support/MREC24ConnectorVoltageHigh", "", "Simulated fault event"};
inline const auto evse_board_support_MREC25BrokenLatch =
ErrorDefinition{"evse_board_support/MREC25BrokenLatch", "", "Simulated fault event"};
inline const auto evse_board_support_MREC26CutCable =
ErrorDefinition{"evse_board_support/MREC26CutCable", "", "Simulated fault event"};
inline const auto evse_board_support_TiltDetected =
ErrorDefinition{"evse_board_support/TiltDetected", "", "Simulated fault event"};
inline const auto evse_board_support_WaterIngressDetected =
ErrorDefinition{"evse_board_support/WaterIngressDetected", "", "Simulated fault event"};
inline const auto evse_board_support_EnclosureOpen =
ErrorDefinition{"evse_board_support/EnclosureOpen", "", "Simulated fault event"};
inline const auto ac_rcd_VendorError = ErrorDefinition{"ac_rcd/VendorError", "", "Simulated fault event"};
inline const auto ac_rcd_Selftest = ErrorDefinition{"ac_rcd/Selftest", "", "Simulated fault event"};
inline const auto ac_rcd_AC = ErrorDefinition{"ac_rcd/AC", "", "Simulated fault event"};
inline const auto ac_rcd_DC = ErrorDefinition{"ac_rcd/DC", "", "Simulated fault event"};
inline const auto ac_rcd_MREC2GroundFailure = ErrorDefinition{"ac_rcd/MREC2GroundFailure", "", "Simulated fault event"};
inline const auto connector_lock_ConnectorLockCapNotCharged =
ErrorDefinition{"connector_lock/ConnectorLockCapNotCharged", "", "Simulated fault event"};
inline const auto connector_lock_ConnectorLockUnexpectedOpen =
ErrorDefinition{"connector_lock/ConnectorLockUnexpectedOpen", "", "Simulated fault event"};
inline const auto connector_lock_ConnectorLockFailedLock =
ErrorDefinition{"connector_lock/ConnectorLockFailedLock", "", "Simulated fault event"};
inline const auto connector_lock_ConnectorLockFailedUnlock =
ErrorDefinition{"connector_lock/ConnectorLockFailedUnlock", "", "Simulated fault event"};
inline const auto connector_lock_MREC1ConnectorLockFailure =
ErrorDefinition{"connector_lock/MREC1ConnectorLockFailure", "", "Simulated fault event"};
inline const auto connector_lock_VendorError =
ErrorDefinition{"connector_lock/VendorError", "", "Simulated fault event"};
inline const auto powermeter_CommunicationFault =
ErrorDefinition{"powermeter/CommunicationFault", "", "Simulated fault event", Everest::error::Severity::High,
ErrorTarget::Powermeter};
} // namespace error_definitions

View File

@@ -0,0 +1,84 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#include "state.hpp"
#include <chrono>
#include <cstdint>
#include <nlohmann/json_fwd.hpp>
#include <string>
namespace module::state {
using std::chrono::milliseconds;
using std::chrono::system_clock;
using std::chrono::time_point_cast;
TimeStamp::TimeStamp() :
time_stamp{time_point_cast<milliseconds>(system_clock::now()).time_since_epoch().count() / milliseconds_in_second} {
}
TimeStamp& TimeStamp::operator=(const double value) {
time_stamp = static_cast<int64_t>(value);
return *this;
}
TimeStamp::operator int64_t() const {
return time_stamp;
}
std::string state_to_string(const ModuleState& module_state) {
using state::State;
const auto pwm = module_state.pwm_running ? '2' : '1';
switch (module_state.current_state) {
case State::STATE_DISABLED:
return "Disabled";
case State::STATE_A:
return "A" + std::to_string(pwm);
case State::STATE_B:
return "B" + std::to_string(pwm);
case State::STATE_C:
return "C" + std::to_string(pwm);
case State::STATE_D:
return "D" + std::to_string(pwm);
case State::STATE_E:
return "E" + std::to_string(pwm);
case State::STATE_F:
return "F" + std::to_string(pwm);
default:
return "";
}
}
void to_json(nlohmann::json& json, const PowermeterData& powermeter_data) {
json = nlohmann::json{{"time_stamp", static_cast<uint64_t>(powermeter_data.time_stamp)},
{"total_importWattHr", powermeter_data.import_totalWattHr},
{"total_exportWattHr", powermeter_data.export_totalWattHr},
{"wattL1", powermeter_data.wattL1},
{"vrmsL1", powermeter_data.vrmsL1},
{"irmsL1", powermeter_data.irmsL1},
{"import_wattHrL1", powermeter_data.import_wattHrL1},
{"export_wattHrL1", powermeter_data.export_wattHrL1},
{"tempL1", powermeter_data.tempL1},
{"freqL1", powermeter_data.freqL1},
{"wattL2", powermeter_data.wattL2},
{"vrmsL2", powermeter_data.vrmsL2},
{"irmsL2", powermeter_data.irmsL2},
{"import_wattHrL2", powermeter_data.import_wattHrL2},
{"export_wattHrL2", powermeter_data.export_wattHrL2},
{"tempL2", powermeter_data.tempL2},
{"freqL2", powermeter_data.freqL2},
{"wattL3", powermeter_data.wattL3},
{"vrmsL3", powermeter_data.vrmsL3},
{"irmsL3", powermeter_data.irmsL3},
{"import_wattHrL3", powermeter_data.import_wattHrL3},
{"export_wattHrL3", powermeter_data.export_wattHrL3},
{"tempL3", powermeter_data.tempL3},
{"freqL3", powermeter_data.freqL3},
{"irmsN", powermeter_data.irmsN}};
}
} // namespace module::state

View File

@@ -0,0 +1,250 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
// NOLINTBEGIN: ignore things like public access or magic values
#include "nlohmann/json.hpp"
#include <string>
namespace module::state {
struct TimeStamp {
TimeStamp();
TimeStamp& operator=(const double value);
operator int64_t() const;
int64_t time_stamp;
};
struct PowermeterData {
TimeStamp time_stamp;
double import_totalWattHr = 0.0;
double export_totalWattHr = 0.0;
double wattL1 = 0.0;
double vrmsL1 = 230.0;
double irmsL1 = 0.0;
double import_wattHrL1 = 0.0;
double export_wattHrL1 = 0.0;
double tempL1 = 25.0;
double freqL1 = 50.0;
double wattL2 = 0.0;
double vrmsL2 = 230.0;
double irmsL2 = 0.0;
double import_wattHrL2 = 0.0;
double export_wattHrL2 = 0.0;
double tempL2 = 25.0;
double freqL2 = 50.0;
double wattL3 = 0.0;
double vrmsL3 = 230.0;
double irmsL3 = 0.0;
double import_wattHrL3 = 0.0;
double export_wattHrL3 = 0.0;
double tempL3 = 25.0;
double freqL3 = 50.0;
double irmsN = 0.0;
};
struct SimulationData {
double cp_voltage = 12.0;
bool diode_fail = false;
bool error_e = false;
double pp_resistor = 220.1;
double rcd_current = 0.1;
struct Currents {
double L1 = 0.0;
double L2 = 0.0;
double L3 = 0.0;
double N = 0.0;
};
Currents currents;
struct Voltages {
double L1 = 230.0;
double L2 = 230.0;
double L3 = 230.0;
};
Voltages voltages;
struct Frequencies {
double L1 = 50.0;
double L2 = 50.0;
double L3 = 50.0;
};
Frequencies frequencies;
};
struct SimdataSetting {
double cp_voltage = 12.0;
double pp_resistor = 220.1;
double impedance = 500.0;
double rcd_current = 0.1;
bool diode_fail = false;
bool error_e = false;
struct Voltages {
double L1 = 230.0;
double L2 = 230.0;
double L3 = 230.0;
};
Voltages voltages;
struct Currents {
double L1 = 0.0;
double L2 = 0.0;
double L3 = 0.0;
double N = 0.0;
};
Currents currents;
struct Frequencies {
double L1 = 50.0;
double L2 = 50.0;
double L3 = 50.0;
};
Frequencies frequencies;
};
struct WattHr {
double L1 = 0.0;
double L2 = 0.0;
double L3 = 0.0;
};
struct TelemetryData {
struct PowerPathControllerVersion {
std::string timestamp;
std::string type = "power_path_controller_version";
int hardware_version = 3;
std::string software_version = "1.01";
std::string date_manufactured = "20220304";
int64_t operating_time_h = 2330;
int64_t operating_time_h_warning = 5000;
int64_t operating_time_h_error = 6000;
bool error = false;
};
PowerPathControllerVersion power_path_controller_version;
struct PowerPathController {
std::string timestamp;
std::string type = "power_path_controller";
double cp_voltage_high = 0.0;
double cp_voltage_low = 0.0;
double cp_pwm_duty_cycle = 0.0;
std::string cp_state = "A1";
double pp_ohm = 220.1;
double supply_voltage_12V = 12.1;
double supply_voltage_minus_12V = -11.9;
double temperature_controller = 33;
double temperature_car_connector = 65;
int64_t watchdog_reset_count = 1;
bool error = false;
};
PowerPathController power_path_controller;
struct PowerSwitch {
std::string timestamp;
std::string type = "power_switch";
int64_t switching_count = 0;
int64_t switching_count_warning = 30000;
int64_t switching_count_error = 50000;
bool is_on = false;
int64_t time_to_switch_on_ms = 110;
int64_t time_to_switch_off_ms = 100;
double temperature_C = 20;
bool error = false;
bool error_over_current = false;
};
PowerSwitch power_switch;
struct Rcd {
std::string timestamp;
std::string type = "rcd";
bool enabled = true;
double current_mA = 2.5;
bool triggered = false;
bool error = false;
};
Rcd rcd;
};
enum class State {
STATE_DISABLED = 0,
STATE_A = 1,
STATE_B = 2,
STATE_C = 3,
STATE_D = 4,
STATE_E = 5,
STATE_F = 6,
Event_PowerOn = 8,
Event_PowerOff = 9,
};
struct ModuleState {
PowermeterData powermeter_data;
SimulationData simulation_data;
SimdataSetting simdata_setting;
TelemetryData telemetry_data;
int64_t pubCnt = 0;
bool power_on_allowed = false;
bool relais_on = false;
State current_state = State::STATE_DISABLED;
State last_state = State::STATE_DISABLED;
TimeStamp time_stamp;
bool use_three_phases = true;
bool simplified_mode = false;
bool has_ventilation = false;
bool rcd_error = false;
bool simulation_enabled = false;
double pwm_duty_cycle = 0;
bool pwm_running = false;
bool pwm_error_f = false;
bool last_pwm_running = false;
bool use_three_phases_confirmed = true;
double pwm_voltage_hi = 12.1;
double pwm_voltage_lo = 12.1;
std::string country_code = "DE";
int64_t last_pwm_update = 0;
WattHr export_watt_hr;
WattHr import_watt_hr;
int64_t powermeter_sim_last_time_stamp = 0L;
double ev_max_current = 0.0;
int ev_phases = 3;
bool republish_state = false;
};
std::string state_to_string(const state::ModuleState& module_state);
void to_json(nlohmann::json& json, const PowermeterData& powermeter_data);
constexpr inline auto milliseconds_in_second = 1000;
} // namespace module::state
// NOLINTEND

View File

@@ -0,0 +1,23 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#include "util.hpp"
#include <chrono>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <string>
namespace module::util {
std::string get_current_iso_time_string() {
using std::chrono::system_clock;
const auto date = system_clock::to_time_t(system_clock::now());
auto string_stream = std::stringstream{};
// NOLINTNEXTLINE(concurrency-mt-unsafe)
string_stream << std::put_time(gmtime(&date), "%FT%TZ");
const auto iso_time_string = string_stream.str();
return iso_time_string;
}
} // namespace module::util

View File

@@ -0,0 +1,10 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
#include <string>
namespace module::util {
std::string get_current_iso_time_string();
} // namespace module::util