Files
cariflex/tools/EVerest-main/modules/EVSE/Evse15118D20/charger/session_logger.cpp
Eric F d398a6ced2 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
2026-06-08 00:38:27 -04:00

142 lines
4.5 KiB
C++

// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#include "session_logger.hpp"
#include <chrono>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <stdexcept>
#include <date/date.h>
#include <iso15118/session/logger.hpp>
#include <everest/logging.hpp>
using LogEvent = iso15118::session::logging::Event;
std::string get_filename_for_current_time() {
const auto now = std::chrono::system_clock::now();
const auto now_t = std::chrono::system_clock::to_time_t(now);
std::tm now_tm;
gmtime_r(&now_t, &now_tm);
char buffer[64];
strftime(buffer, sizeof(buffer), "%y%m%d_%H-%M-%S.yaml", &now_tm);
return buffer;
}
// static auto timepoint_to_string(const iso15118::session::logging::TimePoint& timepoint) {
// using namespace date;
// return static_cast<std::string>(timepoint);
// }
std::ostream& operator<<(std::ostream& os, const iso15118::session::logging::ExiMessageDirection& direction) {
using Direction = iso15118::session::logging::ExiMessageDirection;
switch (direction) {
case Direction::FROM_EV:
return os << "FROM_EV";
case Direction::TO_EV:
return os << "TO_EV";
}
return os;
}
class SessionLog {
public:
SessionLog(const std::string& file_name) : file(file_name.c_str(), std::ios::out) {
if (not file.good()) {
throw std::runtime_error("Failed to open file " + file_name + " for writing iso15118 session log");
}
EVLOG_info << "Created logfile at: " << file_name;
}
void operator()(const iso15118::session::logging::SimpleEvent& event) {
file << "- type: INFO\n";
add_timestamp(event.time_point);
file << " info: \"" << event.info << "\"\n";
}
void operator()(const iso15118::session::logging::ExiMessageEvent& event) {
file << "- type: EXI\n";
add_timestamp(event.time_point);
file << " direction: " << event.direction << "\n";
file << " sdp_payload_type: " << event.payload_type << "\n";
add_hex_encoded_data(event.data, event.len);
}
void flush() {
file.flush();
}
private:
std::fstream file;
void add_timestamp(const iso15118::session::logging::TimePoint& timestamp) {
if (not timestamp_initialized) {
last_timestamp = timestamp;
timestamp_initialized = true;
}
const auto offset_ms = std::chrono::duration_cast<std::chrono::milliseconds>(timestamp - last_timestamp);
file << " timestamp_offset: " << offset_ms.count() << "\n";
const auto dp = date::floor<date::days>(timestamp);
const auto time = date::make_time(timestamp - dp);
const auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(time.subseconds());
file << " timestamp: \"";
file << std::setfill('0') << std::setw(2) << time.hours().count() << ":";
file << std::setfill('0') << std::setw(2) << time.minutes().count() << ":";
file << std::setfill('0') << std::setw(2) << time.seconds().count() << ".";
file << std::setfill('0') << std::setw(4) << milliseconds.count();
file << "\"\n";
last_timestamp = timestamp;
}
void add_hex_encoded_data(const uint8_t* data, size_t len) {
file << " data: \"";
const auto flags = file.flags();
file << std::hex;
for (int i = 0; i < len; ++i) {
file << std::setfill('0') << std::setw(2) << static_cast<int>(data[i]);
}
file.flags(flags);
file << "\"\n";
}
iso15118::session::logging::TimePoint last_timestamp;
bool timestamp_initialized{false};
};
SessionLogger::SessionLogger(std::filesystem::path output_dir_) : output_dir(std::filesystem::absolute(output_dir_)) {
// FIXME (aw): this is quite brute force ...
if (not std::filesystem::exists(output_dir)) {
std::filesystem::create_directory(output_dir);
}
iso15118::session::logging::set_session_log_callback([this](std::uintptr_t id, const LogEvent& event) {
auto log_it = logs.find(id);
if (log_it == logs.end()) {
const auto log_file_name = output_dir / get_filename_for_current_time();
const auto emplaced = logs.emplace(id, std::make_unique<SessionLog>(log_file_name.string()));
log_it = emplaced.first;
}
auto& log = *log_it->second;
std::visit(log, event);
log.flush();
});
}
SessionLogger::~SessionLogger() = default;