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,31 @@
#
# AUTO GENERATED - MARKED REGIONS WILL BE KEPT
# template version 3
#
# module setup:
# - ${MODULE_NAME}: module name
ev_setup_cpp_module()
# ev@bcc62523-e22b-41d7-ba2f-825b493a3c97:v1
target_sources(${MODULE_NAME}
PRIVATE
main/fsm_controller.cpp
)
target_link_libraries(${MODULE_NAME}
PRIVATE
slac::io
slac::fsm::ev
)
# ev@bcc62523-e22b-41d7-ba2f-825b493a3c97:v1
target_sources(${MODULE_NAME}
PRIVATE
"main/ev_slacImpl.cpp"
)
# ev@c55432ab-152c-45a9-9d2e-7281d50c69c3:v1
# insert other things like install cmds etc here
# ev@c55432ab-152c-45a9-9d2e-7281d50c69c3:v1

View File

@@ -0,0 +1,15 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#include "EvSlac.hpp"
namespace module {
void EvSlac::init() {
invoke_init(*p_main);
}
void EvSlac::ready() {
invoke_ready(*p_main);
}
} // namespace module

View File

@@ -0,0 +1,58 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#ifndef EV_SLAC_HPP
#define EV_SLAC_HPP
//
// AUTO GENERATED - MARKED REGIONS WILL BE KEPT
// template version 2
//
#include "ld-ev.hpp"
// headers for provided interface implementations
#include <generated/interfaces/ev_slac/Implementation.hpp>
// ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1
// insert your custom include headers here
// ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1
namespace module {
struct Conf {};
class EvSlac : public Everest::ModuleBase {
public:
EvSlac() = delete;
EvSlac(const ModuleInfo& info, std::unique_ptr<ev_slacImplBase> p_main, Conf& config) :
ModuleBase(info), p_main(std::move(p_main)), config(config){};
const std::unique_ptr<ev_slacImplBase> p_main;
const Conf& config;
// ev@1fce4c5e-0ab8-41bb-90f7-14277703d2ac:v1
// insert your public definitions here
// ev@1fce4c5e-0ab8-41bb-90f7-14277703d2ac:v1
protected:
// ev@4714b2ab-a24f-4b95-ab81-36439e1478de:v1
// insert your protected definitions here
// ev@4714b2ab-a24f-4b95-ab81-36439e1478de:v1
private:
friend class LdEverest;
void init();
void ready();
// ev@211cfdbe-f69a-4cd6-a4ec-f8aaa3d1b6c8:v1
// insert your private definitions here
// ev@211cfdbe-f69a-4cd6-a4ec-f8aaa3d1b6c8:v1
};
// ev@087e516b-124c-48df-94fb-109508c7cda9:v1
// insert other definitions here
// ev@087e516b-124c-48df-94fb-109508c7cda9:v1
} // namespace module
#endif // EV_SLAC_HPP

View File

@@ -0,0 +1,92 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#include "ev_slacImpl.hpp"
#include <fmt/core.h>
#include <everest/slac/io.hpp>
#include "fsm_controller.hpp"
static std::promise<void> module_ready;
// FIXME (aw): this is ugly, but due to the design of the auto-generated module skeleton ..
static std::unique_ptr<FSMController> fsm_ctrl{nullptr};
namespace module {
namespace main {
void ev_slacImpl::init() {
// setup evse fsm thread
std::thread(&ev_slacImpl::run, this).detach();
}
void ev_slacImpl::ready() {
module_ready.set_value();
}
void ev_slacImpl::run() {
// wait until ready
module_ready.get_future().get();
// initialize slac i/o
SlacIO slac_io;
try {
slac_io.init(config.device);
} catch (const std::exception& e) {
EVLOG_error << fmt::format("Couldn't open device {} for SLAC communication. Reason: {}", config.device,
e.what());
raise_error(
error_factory->create_error("generic/CommunicationFault", "", "Could not open device " + config.device));
return;
}
// setup callbacks
slac::fsm::ev::ContextCallbacks callbacks;
callbacks.send_raw_slac = [&slac_io](slac::messages::HomeplugMessage& msg) { slac_io.send(msg); };
callbacks.signal_state = [this](const std::string& value) {
if (value == "MATCHED") {
publish_dlink_ready(true);
} else if (value == "UNMATCHED") {
publish_dlink_ready(false);
}
try {
publish_state(types::slac::string_to_state(value));
} catch (const std::exception& e) {
EVLOG_error << fmt::format("Tried to publish unknown SLAC state '{}'. Error: {}", value, e.what());
}
};
callbacks.log_debug = [](const std::string& text) { EVLOG_debug << "EvSlac: " << text; };
callbacks.log_info = [](const std::string& text) { EVLOG_info << "EvSlac: " << text; };
callbacks.log_warn = [](const std::string& text) { EVLOG_warning << "EvSlac: " << text; };
callbacks.log_error = [](const std::string& text) { EVLOG_error << "EvSlac: " << text; };
const uint8_t* if_mac = slac_io.get_mac_addr();
std::array<uint8_t, ETH_ALEN> ev_host_mac;
std::copy(if_mac, if_mac + ETH_ALEN, ev_host_mac.begin());
auto fsm_ctx = slac::fsm::ev::Context(callbacks, ev_host_mac);
// fsm_ctx.slac_config.set_key_timeout_ms = config.set_key_timeout_ms;
// fsm_ctx.slac_config.ac_mode_five_percent = config.ac_mode_five_percent;
// fsm_ctx.slac_config.sounding_atten_adjustment = config.sounding_attenuation_adjustment;
// fsm_ctx.slac_config.generate_nmk();
fsm_ctrl = std::make_unique<FSMController>(fsm_ctx);
slac_io.run([](slac::messages::HomeplugMessage& msg) { fsm_ctrl->signal_new_slac_message(msg); });
fsm_ctrl->run();
}
void ev_slacImpl::handle_reset() {
fsm_ctrl->signal_reset();
}
bool ev_slacImpl::handle_trigger_matching() {
fsm_ctrl->signal_trigger_matching();
return true;
}
} // namespace main
} // namespace module

View File

@@ -0,0 +1,65 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#ifndef MAIN_EV_SLAC_IMPL_HPP
#define MAIN_EV_SLAC_IMPL_HPP
//
// AUTO GENERATED - MARKED REGIONS WILL BE KEPT
// template version 3
//
#include <generated/interfaces/ev_slac/Implementation.hpp>
#include "../EvSlac.hpp"
// ev@75ac1216-19eb-4182-a85c-820f1fc2c091:v1
// insert your custom include headers here
// ev@75ac1216-19eb-4182-a85c-820f1fc2c091:v1
namespace module {
namespace main {
struct Conf {
std::string device;
int set_key_timeout_ms;
};
class ev_slacImpl : public ev_slacImplBase {
public:
ev_slacImpl() = delete;
ev_slacImpl(Everest::ModuleAdapter* ev, const Everest::PtrContainer<EvSlac>& mod, Conf& config) :
ev_slacImplBase(ev, "main"), mod(mod), config(config){};
// ev@8ea32d28-373f-4c90-ae5e-b4fcc74e2a61:v1
// insert your public definitions here
// ev@8ea32d28-373f-4c90-ae5e-b4fcc74e2a61:v1
protected:
// command handler functions (virtual)
virtual void handle_reset() override;
virtual bool handle_trigger_matching() override;
// ev@d2d1847a-7b88-41dd-ad07-92785f06f5c4:v1
void run();
// ev@d2d1847a-7b88-41dd-ad07-92785f06f5c4:v1
private:
const Everest::PtrContainer<EvSlac>& mod;
const Conf& config;
virtual void init() override;
virtual void ready() override;
// ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1
// insert your private definitions here
// ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1
};
// ev@3d7da0ad-02c2-493d-9920-0bbbd56b9876:v1
// insert other definitions here
// ev@3d7da0ad-02c2-493d-9920-0bbbd56b9876:v1
} // namespace main
} // namespace module
#endif // MAIN_EV_SLAC_IMPL_HPP

View File

@@ -0,0 +1,75 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2023 - 2023 Pionix GmbH and Contributors to EVerest
#include "fsm_controller.hpp"
#include <everest/slac/fsm/ev/states/others.hpp>
FSMController::FSMController(slac::fsm::ev::Context& context) : ctx(context){};
void FSMController::signal_new_slac_message(slac::messages::HomeplugMessage& msg) {
if (running == false) {
return;
}
{
const std::lock_guard<std::mutex> feed_lck(feed_mtx);
ctx.slac_message = msg;
fsm.handle_event(slac::fsm::ev::Event::SLAC_MESSAGE);
}
new_event = true;
new_event_cv.notify_all();
}
void FSMController::signal_reset() {
signal_simple_event(slac::fsm::ev::Event::RESET);
}
void FSMController::signal_trigger_matching() {
signal_simple_event(slac::fsm::ev::Event::TRIGGER_MATCHING);
}
bool FSMController::signal_simple_event(slac::fsm::ev::Event ev) {
const std::lock_guard<std::mutex> feed_lck(feed_mtx);
auto event_result = fsm.handle_event(ev);
new_event = true;
new_event_cv.notify_all();
return event_result == fsm::HandleEventResult::SUCCESS;
}
void FSMController::run() {
ctx.log_info("Starting the SLAC state machine");
fsm.reset<slac::fsm::ev::ResetState>(ctx);
std::unique_lock<std::mutex> feed_lck(feed_mtx);
running = true;
while (true) {
auto feed_result = fsm.feed();
if (feed_result.transition()) {
// call immediately again
continue;
} else if (feed_result.internal_error() || feed_result.unhandled_event()) {
// FIXME (aw): would need to log here!
} else if (feed_result.has_value() == true) {
const auto timeout = *feed_result;
if (timeout == 0) {
// call feed directly again
continue;
}
new_event_cv.wait_for(feed_lck, std::chrono::milliseconds(timeout), [this] { return new_event; });
} else {
// nothing happened, no return value -> wait for new event
new_event_cv.wait(feed_lck, [this] { return new_event; });
}
if (new_event) {
// we got a new event, reset it and let run feed again
new_event = false;
}
}
}

View File

@@ -0,0 +1,32 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2023 - 2023 Pionix GmbH and Contributors to EVerest
#ifndef EVSE_SLAC_FSM_CONTROLLER_HPP
#define EVSE_SLAC_FSM_CONTROLLER_HPP
#include <everest/slac/fsm/ev/fsm.hpp>
#include <condition_variable>
#include <mutex>
class FSMController {
public:
explicit FSMController(slac::fsm::ev::Context& ctx);
void signal_new_slac_message(slac::messages::HomeplugMessage&);
void signal_reset();
void signal_trigger_matching();
void run();
private:
bool signal_simple_event(slac::fsm::ev::Event ev);
slac::fsm::ev::Context& ctx;
slac::fsm::ev::FSM fsm;
bool running{false};
std::mutex feed_mtx;
std::condition_variable new_event_cv;
bool new_event{false};
};
#endif // EVSE_SLAC_FSM_CONTROLLER_HPP

View File

@@ -0,0 +1,19 @@
description: Implementation of EV SLAC data link negotiation according to ISO15118-3.
provides:
main:
interface: ev_slac
description: SLAC interface implementation.
config:
device:
description: Ethernet device used for PLC.
type: string
default: eth1
set_key_timeout_ms:
description: Timeout for CM_SET_KEY.REQ. Default works for QCA7000/QCA7005/CG5317.
type: integer
default: 500
metadata:
base_license: https://directory.fsf.org/wiki/License:BSD-3-Clause-Clear
license: https://opensource.org/licenses/Apache-2.0
authors:
- aw@pionix.de