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,68 @@
add_library(everest_log)
add_library(everest::log ALIAS everest_log)
target_sources(everest_log
PRIVATE
logging.cpp
trace.cpp
)
target_include_directories(everest_log
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
set_target_properties(everest_log
PROPERTIES
POSITION_INDEPENDENT_CODE ON
)
target_link_libraries(everest_log
PUBLIC
Boost::log
PRIVATE
Boost::log_setup
)
if (LIBLOG_USE_BOOST_FILESYSTEM)
target_link_libraries(everest_log
PRIVATE
Boost::filesystem
)
target_compile_definitions(everest_log
PRIVATE
LIBLOG_USE_BOOST_FILESYSTEM
)
endif()
# FIXME (aw): in case FindBoost.cmake was used we need to add things
# this should be removed no support for Boost < 1.74 is needed
if (NOT Boost_DIR)
target_compile_definitions(everest_log
PUBLIC
BOOST_LOG_DYN_LINK
)
target_link_libraries(everest_log
PUBLIC
rt dl
)
endif()
if (BUILD_BACKTRACE_SUPPORT)
target_link_libraries(everest_log
PRIVATE
backtrace
)
target_compile_definitions(everest_log PRIVATE WITH_LIBBACKTRACE)
endif()
if (EVEREST_DISABLE_VERBOSE_LOGGING)
target_compile_definitions(everest_log PUBLIC EVEREST_DISABLE_VERBOSE_LOGGING)
endif ()
if (EVEREST_DISABLE_DEBUG_LOGGING)
target_compile_definitions(everest_log PUBLIC EVEREST_DISABLE_DEBUG_LOGGING)
endif ()
target_compile_features(everest_log PUBLIC cxx_std_17)

View File

@@ -0,0 +1,241 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#ifdef LIBLOG_USE_BOOST_FILESYSTEM
#include <boost/filesystem.hpp>
#else
#include <filesystem>
#endif
#include <boost/log/attributes/current_process_id.hpp>
#include <boost/log/attributes/current_process_name.hpp>
#include <boost/log/attributes/current_thread_id.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/expressions/attr.hpp>
#include <boost/log/expressions/formatter.hpp>
#include <boost/log/expressions/formatters/c_decorator.hpp>
#include <boost/log/expressions/formatters/format.hpp>
#include <boost/log/expressions/formatters/stream.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/filter_parser.hpp>
#include <boost/log/utility/setup/formatter_parser.hpp>
#include <boost/log/utility/setup/from_settings.hpp>
#include <boost/log/utility/setup/from_stream.hpp>
#include <boost/log/utility/setup/settings.hpp>
#include <boost/log/utility/setup/settings_parser.hpp>
#include <fstream>
#include <everest/exceptions.hpp>
#include <everest/logging.hpp>
// this will only be used while bootstrapping our logging (e.g. the logging settings aren't yet applied)
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define EVEREST_INTERNAL_LOG_AND_THROW(exception) \
do { \
BOOST_LOG_TRIVIAL(fatal) << (exception).what(); \
throw(exception); \
} while (0);
#ifdef LIBLOG_USE_BOOST_FILESYSTEM
namespace fs = boost::filesystem;
#else
namespace fs = std::filesystem;
#endif
namespace logging = boost::log::BOOST_LOG_VERSION_NAMESPACE;
namespace attrs = logging::attributes;
namespace expr = logging::expressions;
namespace Everest {
namespace Logging {
namespace {
bool is_initialized = false;
}
std::array<std::string, 6> severity_strings = {
"VERB", //
"DEBG", //
"INFO", //
"WARN", //
"ERRO", //
"CRIT", //
};
std::array<std::string, 6> severity_strings_colors = {
"", //
"", //
"", //
"", //
"", //
"", //
};
std::string process_name_padding(const std::string& process_name) {
const unsigned int process_name_padding_length = 15;
std::string padded_process_name = process_name;
if (process_name_padding_length > padded_process_name.size())
padded_process_name.insert(padded_process_name.size(), process_name_padding_length, ' ');
if (padded_process_name.size() > process_name_padding_length)
padded_process_name = padded_process_name.substr(0, process_name_padding_length);
return padded_process_name;
}
attrs::mutable_constant<std::string> current_process_name(process_name_padding(logging::aux::get_process_name()));
// The operator puts a human-friendly representation of the severity level to the stream
std::ostream& operator<<(std::ostream& strm, severity_level level) {
if (static_cast<std::size_t>(level) < severity_strings.size()) {
strm << severity_strings_colors.at(level) << severity_strings.at(level) << "\033[0m";
} else {
strm << static_cast<int>(level);
}
return strm;
}
// The operator parses the severity level from the stream
std::istream& operator>>(std::istream& strm, severity_level& level) {
if (strm.good()) {
std::string str;
strm >> str;
for (unsigned int i = 0; i < severity_strings.size(); ++i) {
if (str == severity_strings.at(i)) {
level = static_cast<severity_level>(i);
return strm;
}
}
strm.setstate(std::ios_base::failbit);
}
return strm;
}
/// Custom formatter for escaped messages.
///
/// Not really clear but just a wrapper around the c_decor formatter.
struct escaped_message_formatter {
explicit escaped_message_formatter(logging::attribute_name const& name) :
f_{expr::stream << expr::c_decor[expr::stream << expr::smessage]} {
}
void operator()(logging::record_view const& rec, logging::formatting_ostream& strm) const {
f_(rec, strm);
}
private:
/// @brief The formatter itself.
boost::log::formatter f_;
};
/// The factory for the EscMessage formatter.
struct escaped_message_formatter_factory : public logging::formatter_factory<char> {
formatter_type create_formatter(logging::attribute_name const& attr_name, args_map const& args) {
return formatter_type(escaped_message_formatter(attr_name));
}
};
int init() {
logging::core::get()->remove_all_sinks();
logging::core::get()->set_logging_enabled(false);
return -1;
}
int init(const std::string& logconf) {
return init(logconf, "");
}
int init(const std::string& logconf, std::string process_name) {
BOOST_LOG_FUNCTION();
if (is_initialized) {
// this prevents us from registering the sinks multiple times which would lead to duplicate output
logging::core::get()->remove_all_sinks();
}
// First thing - register the custom formatter for EscMessage
logging::register_formatter_factory("EscapedMessage", boost::make_shared<escaped_message_formatter_factory>());
// add useful attributes
logging::add_common_attributes();
std::string padded_process_name;
if (!process_name.empty()) {
padded_process_name = process_name_padding(process_name);
}
logging::core::get()->add_global_attribute("Process", current_process_name);
if (!padded_process_name.empty()) {
current_process_name.set(padded_process_name);
}
logging::core::get()->add_global_attribute("Scope", attrs::named_scope());
// Before initializing the library from settings, we need to register any custom filter and formatter factories
logging::register_simple_filter_factory<severity_level>("Severity");
logging::register_simple_formatter_factory<severity_level, char>("Severity");
// open logging.ini config file located at our base_dir and use it to configure boost::log logging (filters and
// format)
fs::path logging_path = fs::path(logconf);
std::ifstream logging_config(logging_path.c_str());
if (!logging_config.is_open()) {
EVEREST_INTERNAL_LOG_AND_THROW(EverestConfigError(std::string("Could not open logging config file at ") +
std::string(fs::absolute(logging_path).c_str())));
}
auto settings = logging::parse_settings(logging_config);
auto sink = settings["Sinks.Console"].get_section();
severity_strings_colors[severity_level::verbose] =
sink["SeverityStringColorTrace"].get<std::string>().get_value_or("");
severity_strings_colors[severity_level::debug] =
sink["SeverityStringColorDebug"].get<std::string>().get_value_or("");
severity_strings_colors[severity_level::info] = sink["SeverityStringColorInfo"].get<std::string>().get_value_or("");
severity_strings_colors[severity_level::warning] =
sink["SeverityStringColorWarning"].get<std::string>().get_value_or("");
severity_strings_colors[severity_level::error] =
sink["SeverityStringColorError"].get<std::string>().get_value_or("");
severity_strings_colors[severity_level::critical] =
sink["SeverityStringColorCritical"].get<std::string>().get_value_or("");
logging::init_from_settings(settings);
logging::core::get()->set_logging_enabled(true);
EVLOG_debug << "Logger " << (is_initialized ? "re" : "") << "initialized (using " << logconf << ")...";
is_initialized = true;
// Probe the installed filter to find the minimum accepted severity level.
for (int level = static_cast<int>(verbose); level <= static_cast<int>(critical); ++level) {
auto rec =
global_logger::get().open_record(boost::log::keywords::severity = static_cast<severity_level>(level));
if (rec) {
return level;
}
}
return -1;
}
void update_process_name(std::string process_name) {
if (!process_name.empty()) {
std::string padded_process_name;
padded_process_name = process_name_padding(process_name);
current_process_name.set(padded_process_name);
}
}
void ffi_log(int level, int line, const std::string& file, const std::string& message) {
// Logging is off.
if (level < 0) {
return;
}
const auto logging_level = static_cast<severity_level>(level);
BOOST_LOG_SEV(::global_logger::get(), logging_level)
<< boost::log::BOOST_LOG_VERSION_NAMESPACE::add_value("file", file)
<< boost::log::BOOST_LOG_VERSION_NAMESPACE::add_value("line", line) << message;
}
} // namespace Logging
} // namespace Everest

View File

@@ -0,0 +1,90 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2020 - 2022 Pionix GmbH and Contributors to EVerest
#include <everest/logging.hpp>
#ifdef WITH_LIBBACKTRACE
#include <backtrace/backtrace-supported.h>
#include <backtrace/backtrace.h>
#include <cxxabi.h>
#include <mutex>
static backtrace_state* bt_state;
static bool tried_to_initialize;
static std::mutex init_mtx;
struct StackTrace {
int frame_count{0};
std::string info;
};
inline int frame_handler(void* data, uintptr_t pc, const char* filename, int lineno, const char* function) {
// FIXME(aw): we might have unknown frames everywhere in the call
// stack, it probably only make sense to skip the
// contigeous set of the top/root frames, that are all
// unknown
// if ((filename == nullptr) && (lineno == 0) && (function == nullptr)) {
// return 1; // stop backtracing
// }
auto& trace = *static_cast<StackTrace*>(data);
std::string function_name = "<function unknown>";
if (function != nullptr) {
// try to demangle
int status;
size_t length;
auto demangled_function = __cxxabiv1::__cxa_demangle(function, nullptr, &length, &status);
if (status == 0) {
// successfully demangled
function_name = std::string(demangled_function);
} else {
function_name = std::string(function);
}
}
trace.info += ("#" + std::to_string(trace.frame_count) + ": ");
trace.info += (function_name + " at ");
trace.info += (filename != nullptr) ? filename : "<filename unknown>";
trace.info += (":" + std::to_string(lineno));
trace.info += "\n";
trace.frame_count++;
return 0; // continue backtracing
}
#endif
namespace Everest {
namespace Logging {
std::string trace() {
#ifdef WITH_LIBBACKTRACE
{
std::lock_guard<std::mutex> lck(init_mtx);
if (!tried_to_initialize) {
// 1 means support threaded
bt_state = backtrace_create_state(nullptr, 1, nullptr, nullptr);
tried_to_initialize = true;
}
}
if (bt_state == nullptr) {
return "Backtrace functionality not available\n";
}
StackTrace trace;
// FIXME (aw): 1 means we're skipping this functions frame, can this
// be optimized away by the compiler, so we are going to
// miss the first frame?
backtrace_full(bt_state, 1, frame_handler, nullptr, &trace);
return trace.info;
#else
return "Backtrace functionality not built in\n";
#endif
}
} // namespace Logging
} // namespace Everest