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,425 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#include <everest/conversions/ocpp/ocpp_conversions.hpp>
#include <everest/logging.hpp>
#include "generated/types/display_message.hpp"
namespace ocpp_conversions {
types::display_message::MessagePriorityEnum
to_everest_display_message_priority(const ocpp::v2::MessagePriorityEnum& priority) {
switch (priority) {
case ocpp::v2::MessagePriorityEnum::AlwaysFront:
return types::display_message::MessagePriorityEnum::AlwaysFront;
case ocpp::v2::MessagePriorityEnum::InFront:
return types::display_message::MessagePriorityEnum::InFront;
case ocpp::v2::MessagePriorityEnum::NormalCycle:
return types::display_message::MessagePriorityEnum::NormalCycle;
}
throw std::out_of_range(
"Could not convert ocpp::v2::MessagePriorityEnum to types::display_message::MessagePriorityEnum");
}
ocpp::v2::MessagePriorityEnum
to_ocpp_201_message_priority(const types::display_message::MessagePriorityEnum& priority) {
switch (priority) {
case types::display_message::MessagePriorityEnum::AlwaysFront:
return ocpp::v2::MessagePriorityEnum::AlwaysFront;
case types::display_message::MessagePriorityEnum::InFront:
return ocpp::v2::MessagePriorityEnum::InFront;
case types::display_message::MessagePriorityEnum::NormalCycle:
return ocpp::v2::MessagePriorityEnum::NormalCycle;
}
throw std::out_of_range(
"Could not convert types::display_message::MessagePriorityEnum to ocpp::v2::MessagePriorityEnum");
}
types::display_message::MessageStateEnum to_everest_display_message_state(const ocpp::v2::MessageStateEnum& state) {
switch (state) {
case ocpp::v2::MessageStateEnum::Charging:
return types::display_message::MessageStateEnum::Charging;
case ocpp::v2::MessageStateEnum::Faulted:
return types::display_message::MessageStateEnum::Faulted;
case ocpp::v2::MessageStateEnum::Idle:
return types::display_message::MessageStateEnum::Idle;
case ocpp::v2::MessageStateEnum::Unavailable:
return types::display_message::MessageStateEnum::Unavailable;
case ocpp::v2::MessageStateEnum::Suspended:
return types::display_message::MessageStateEnum::Suspending;
case ocpp::v2::MessageStateEnum::Discharging:
return types::display_message::MessageStateEnum::Discharging;
}
throw std::out_of_range("Could not convert ocpp::v2::MessageStateEnum to types::display_message::MessageStateEnum");
}
ocpp::v2::MessageStateEnum to_ocpp_201_display_message_state(const types::display_message::MessageStateEnum& state) {
switch (state) {
case types::display_message::MessageStateEnum::Charging:
return ocpp::v2::MessageStateEnum::Charging;
case types::display_message::MessageStateEnum::Faulted:
return ocpp::v2::MessageStateEnum::Faulted;
case types::display_message::MessageStateEnum::Idle:
return ocpp::v2::MessageStateEnum::Idle;
case types::display_message::MessageStateEnum::Unavailable:
return ocpp::v2::MessageStateEnum::Unavailable;
case types::display_message::MessageStateEnum::Suspending:
return ocpp::v2::MessageStateEnum::Suspended;
case types::display_message::MessageStateEnum::Discharging:
return ocpp::v2::MessageStateEnum::Discharging;
}
throw std::out_of_range("Could not convert types::display_message::MessageStateEnum to ocpp::v2::MessageStateEnum");
}
types::text_message::MessageFormat
to_everest_display_message_format(const ocpp::v2::MessageFormatEnum& message_format) {
switch (message_format) {
case ocpp::v2::MessageFormatEnum::ASCII:
return types::text_message::MessageFormat::ASCII;
case ocpp::v2::MessageFormatEnum::HTML:
return types::text_message::MessageFormat::HTML;
case ocpp::v2::MessageFormatEnum::URI:
return types::text_message::MessageFormat::URI;
case ocpp::v2::MessageFormatEnum::UTF8:
return types::text_message::MessageFormat::UTF8;
case ocpp::v2::MessageFormatEnum::QRCODE:
return types::text_message::MessageFormat::QRCODE;
}
throw std::out_of_range("Could not convert ocpp::v2::MessageFormat to types::display_message::MessageFormatEnum");
}
ocpp::v2::MessageFormatEnum to_ocpp_201_message_format_enum(const types::text_message::MessageFormat& format) {
switch (format) {
case types::text_message::MessageFormat::ASCII:
return ocpp::v2::MessageFormatEnum::ASCII;
case types::text_message::MessageFormat::HTML:
return ocpp::v2::MessageFormatEnum::HTML;
case types::text_message::MessageFormat::URI:
return ocpp::v2::MessageFormatEnum::URI;
case types::text_message::MessageFormat::UTF8:
return ocpp::v2::MessageFormatEnum::UTF8;
case types::text_message::MessageFormat::QRCODE:
return ocpp::v2::MessageFormatEnum::QRCODE;
}
throw std::out_of_range("Could not convert types::display_message::MessageFormat to ocpp::v2::MessageFormatEnum");
}
ocpp::IdentifierType to_ocpp_identifiertype_enum(const types::display_message::IdentifierType identifier_type) {
switch (identifier_type) {
case types::display_message::IdentifierType::IdToken:
return ocpp::IdentifierType::IdToken;
case types::display_message::IdentifierType::SessionId:
return ocpp::IdentifierType::SessionId;
case types::display_message::IdentifierType::TransactionId:
return ocpp::IdentifierType::TransactionId;
}
throw std::out_of_range("types::display_message::Identifier_type to ocpp::IdentierType");
}
types::display_message::IdentifierType to_everest_identifier_type_enum(const ocpp::IdentifierType identifier_type) {
switch (identifier_type) {
case ocpp::IdentifierType::SessionId:
return types::display_message::IdentifierType::SessionId;
case ocpp::IdentifierType::IdToken:
return types::display_message::IdentifierType::IdToken;
case ocpp::IdentifierType::TransactionId:
return types::display_message::IdentifierType::TransactionId;
}
throw std::out_of_range("ocpp::IdentierType to types::display_message::Identifier_type");
}
types::text_message::MessageContent
to_everest_display_message_content(const ocpp::DisplayMessageContent& message_content) {
types::text_message::MessageContent message;
message.content = message_content.message;
if (message_content.message_format.has_value()) {
message.format = to_everest_display_message_format(message_content.message_format.value());
}
message.language = message_content.language;
return message;
}
types::display_message::DisplayMessage to_everest_display_message(const ocpp::DisplayMessage& display_message) {
types::display_message::DisplayMessage m;
m.id = display_message.id;
m.message.content = display_message.message.message;
if (display_message.message.message_format.has_value()) {
m.message.format = to_everest_display_message_format(display_message.message.message_format.value());
}
m.message.language = display_message.message.language;
if (display_message.priority.has_value()) {
m.priority = ocpp_conversions::to_everest_display_message_priority(display_message.priority.value());
}
m.qr_code = display_message.qr_code;
m.identifier_id = display_message.identifier_id;
if (display_message.identifier_type.has_value()) {
m.identifier_type = to_everest_identifier_type_enum(display_message.identifier_type.value());
}
if (display_message.state.has_value()) {
m.state = to_everest_display_message_state(display_message.state.value());
}
if (display_message.timestamp_from.has_value()) {
m.timestamp_from = display_message.timestamp_from.value().to_rfc3339();
}
if (display_message.timestamp_to.has_value()) {
m.timestamp_to = display_message.timestamp_to.value().to_rfc3339();
}
return m;
}
ocpp::DisplayMessage to_ocpp_display_message(const types::display_message::DisplayMessage& display_message) {
ocpp::DisplayMessage m;
m.id = display_message.id;
m.message.message = display_message.message.content;
m.message.language = display_message.message.language;
if (display_message.message.format.has_value()) {
m.message.message_format = to_ocpp_201_message_format_enum(display_message.message.format.value());
}
if (display_message.priority.has_value()) {
m.priority = ocpp_conversions::to_ocpp_201_message_priority(display_message.priority.value());
}
m.qr_code = display_message.qr_code;
m.identifier_id = display_message.identifier_id;
if (display_message.identifier_type.has_value()) {
m.identifier_type = to_ocpp_identifiertype_enum(display_message.identifier_type.value());
}
if (display_message.state.has_value()) {
m.state = to_ocpp_201_display_message_state(display_message.state.value());
}
try {
if (display_message.timestamp_from.has_value()) {
m.timestamp_from = ocpp::DateTime(display_message.timestamp_from.value());
}
if (display_message.timestamp_to.has_value()) {
m.timestamp_to = ocpp::DateTime(display_message.timestamp_to.value());
}
} catch (const ocpp::TimePointParseException& e) {
EVLOG_warning << "Could not parse timestamp when converting DisplayMessage: " << e.what();
}
return m;
}
types::session_cost::TariffMessage to_everest_tariff_message(const ocpp::TariffMessage& tariff_message) {
types::session_cost::TariffMessage m;
m.ocpp_transaction_id = tariff_message.ocpp_transaction_id;
m.identifier_id = tariff_message.identifier_id;
if (tariff_message.identifier_type.has_value()) {
m.identifier_type = to_everest_identifier_type_enum(tariff_message.identifier_type.value());
}
for (const auto& message : tariff_message.message) {
types::text_message::MessageContent content = to_everest_display_message_content(message);
m.messages.push_back(content);
}
return m;
}
types::session_cost::DefaultPrice to_everest_default_price(const std::vector<ocpp::DisplayMessageContent>& messages) {
types::session_cost::DefaultPrice default_price;
for (const auto& message : messages) {
default_price.messages.push_back(to_everest_display_message_content(message));
}
return default_price;
}
types::session_cost::SessionStatus to_everest_running_cost_state(const ocpp::RunningCostState& state) {
switch (state) {
case ocpp::RunningCostState::Charging:
return types::session_cost::SessionStatus::Running;
case ocpp::RunningCostState::Idle:
return types::session_cost::SessionStatus::Idle;
case ocpp::RunningCostState::Finished:
return types::session_cost::SessionStatus::Finished;
}
throw std::out_of_range("Could not convert ocpp::RunningCostState to types::session_cost::SessionStatus");
}
types::session_cost::SessionCostChunk create_session_cost_chunk(const double& price, const uint32_t& number_of_decimals,
const std::optional<ocpp::DateTime>& timestamp,
const std::optional<uint32_t>& meter_value) {
types::session_cost::SessionCostChunk chunk;
chunk.cost = types::money::MoneyAmount();
chunk.cost->value = static_cast<int>(price * (pow(10, number_of_decimals)));
if (timestamp.has_value()) {
chunk.timestamp_to = timestamp.value().to_rfc3339();
}
chunk.metervalue_to = meter_value;
return chunk;
}
types::money::Price create_price(const double& price, const uint32_t& number_of_decimals,
std::optional<types::money::CurrencyCode> currency_code) {
types::money::Price p;
types::money::Currency currency;
currency.code = currency_code;
currency.decimals = number_of_decimals;
p.currency = currency;
p.value.value = static_cast<int>(price * (pow(10, number_of_decimals)));
return p;
}
types::session_cost::ChargingPriceComponent
create_charging_price_component(const double& price, const uint32_t& number_of_decimals,
const types::session_cost::CostCategory category,
std::optional<types::money::CurrencyCode> currency_code) {
types::session_cost::ChargingPriceComponent c;
c.category = category;
c.price = create_price(price, number_of_decimals, currency_code);
return c;
}
types::session_cost::SessionCost create_session_cost(const ocpp::RunningCost& running_cost,
const uint32_t number_of_decimals,
std::optional<types::money::CurrencyCode> currency_code) {
types::session_cost::SessionCost cost;
cost.session_id = running_cost.transaction_id;
cost.currency.code = currency_code;
cost.currency.decimals = static_cast<int32_t>(number_of_decimals);
cost.status = to_everest_running_cost_state(running_cost.state);
cost.qr_code = running_cost.qr_code_text;
if (running_cost.cost_messages.has_value()) {
cost.message = std::vector<types::text_message::MessageContent>();
for (const ocpp::DisplayMessageContent& message : running_cost.cost_messages.value()) {
const auto m = to_everest_display_message_content(message);
cost.message->push_back(m);
}
}
types::session_cost::SessionCostChunk chunk = create_session_cost_chunk(
running_cost.cost, number_of_decimals, running_cost.timestamp, running_cost.meter_value);
cost.cost_chunks = std::vector<types::session_cost::SessionCostChunk>();
cost.cost_chunks->push_back(chunk);
if (running_cost.charging_price.has_value()) {
cost.charging_price = std::vector<types::session_cost::ChargingPriceComponent>();
const ocpp::RunningCostChargingPrice& price = running_cost.charging_price.value();
if (price.hour_price.has_value()) {
types::session_cost::ChargingPriceComponent hour_price = create_charging_price_component(
price.hour_price.value(), number_of_decimals, types::session_cost::CostCategory::Time, currency_code);
cost.charging_price->push_back(hour_price);
}
if (price.kWh_price.has_value()) {
types::session_cost::ChargingPriceComponent energy_price = create_charging_price_component(
price.kWh_price.value(), number_of_decimals, types::session_cost::CostCategory::Energy, currency_code);
cost.charging_price->push_back(energy_price);
}
if (price.flat_fee.has_value()) {
types::session_cost::ChargingPriceComponent flat_fee_price = create_charging_price_component(
price.flat_fee.value(), number_of_decimals, types::session_cost::CostCategory::FlatFee, currency_code);
cost.charging_price->push_back(flat_fee_price);
}
}
if (running_cost.idle_price.has_value()) {
types::session_cost::IdlePrice idle_price;
const ocpp::RunningCostIdlePrice& ocpp_idle_price = running_cost.idle_price.value();
if (ocpp_idle_price.idle_hour_price.has_value()) {
idle_price.hour_price =
create_price(ocpp_idle_price.idle_hour_price.value(), number_of_decimals, currency_code);
}
if (ocpp_idle_price.idle_grace_minutes.has_value()) {
idle_price.grace_minutes = ocpp_idle_price.idle_grace_minutes.value();
}
cost.idle_price = idle_price;
}
if (running_cost.next_period_at_time.has_value() || running_cost.next_period_charging_price.has_value() ||
running_cost.next_period_idle_price.has_value()) {
types::session_cost::NextPeriodPrice next_period;
if (running_cost.next_period_at_time.has_value()) {
next_period.timestamp_from = running_cost.next_period_at_time.value().to_rfc3339();
}
if (running_cost.next_period_idle_price.has_value()) {
types::session_cost::IdlePrice next_period_idle_price;
const ocpp::RunningCostIdlePrice& ocpp_next_period_idle_price = running_cost.next_period_idle_price.value();
if (ocpp_next_period_idle_price.idle_hour_price.has_value()) {
next_period_idle_price.hour_price = create_price(ocpp_next_period_idle_price.idle_hour_price.value(),
number_of_decimals, currency_code);
}
if (ocpp_next_period_idle_price.idle_grace_minutes.has_value()) {
next_period_idle_price.grace_minutes = ocpp_next_period_idle_price.idle_grace_minutes.value();
}
next_period.idle_price = next_period_idle_price;
}
if (running_cost.next_period_charging_price.has_value()) {
const ocpp::RunningCostChargingPrice& next_period_charging_price =
running_cost.next_period_charging_price.value();
next_period.charging_price = std::vector<types::session_cost::ChargingPriceComponent>();
if (next_period_charging_price.hour_price.has_value()) {
types::session_cost::ChargingPriceComponent hour_price =
create_charging_price_component(next_period_charging_price.hour_price.value(), number_of_decimals,
types::session_cost::CostCategory::Time, currency_code);
next_period.charging_price.push_back(hour_price);
}
if (next_period_charging_price.kWh_price.has_value()) {
types::session_cost::ChargingPriceComponent energy_price =
create_charging_price_component(next_period_charging_price.kWh_price.value(), number_of_decimals,
types::session_cost::CostCategory::Energy, currency_code);
next_period.charging_price.push_back(energy_price);
}
if (next_period_charging_price.flat_fee.has_value()) {
types::session_cost::ChargingPriceComponent flat_fee_price =
create_charging_price_component(next_period_charging_price.flat_fee.value(), number_of_decimals,
types::session_cost::CostCategory::FlatFee, currency_code);
next_period.charging_price.push_back(flat_fee_price);
}
}
cost.next_period = next_period;
}
return cost;
}
ocpp::DateTime to_ocpp_datetime_or_now(const std::string& datetime_string) {
std::optional<ocpp::DateTime> timestamp;
try {
return ocpp::DateTime(datetime_string);
} catch (const ocpp::TimePointParseException& e) {
EVLOG_warning << "Could not parse datetime string: " << e.what() << ". Using current DateTime instead";
}
return ocpp::DateTime();
}
ocpp::ReservationCheckStatus
to_ocpp_reservation_check_status(const types::reservation::ReservationCheckStatus& status) {
switch (status) {
case types::reservation::ReservationCheckStatus::NotReserved:
return ocpp::ReservationCheckStatus::NotReserved;
case types::reservation::ReservationCheckStatus::ReservedForToken:
return ocpp::ReservationCheckStatus::ReservedForToken;
case types::reservation::ReservationCheckStatus::ReservedForOtherToken:
return ocpp::ReservationCheckStatus::ReservedForOtherToken;
case types::reservation::ReservationCheckStatus::ReservedForOtherTokenAndHasParentToken:
return ocpp::ReservationCheckStatus::ReservedForOtherTokenAndHasParentToken;
}
EVLOG_warning << "Could not convert reservation check status. Returning default 'NotReserved.";
return ocpp::ReservationCheckStatus::NotReserved;
}
} // namespace ocpp_conversions