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,62 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
#include <string>
#include <ieee2030/charger/session/callback.hpp>
#include <ieee2030/charger/session/session.hpp>
#include <ieee2030/charger/v20/control_event.hpp>
#include <ieee2030/common/v20/event_queue.hpp>
namespace ieee2030::charger {
enum class HwSignal {
CS1,
CS2,
CHARGE_PERMISSION,
PROX,
};
class Controller {
public:
Controller(std::string, callback::Callbacks);
~Controller(); // Todo: Adding destructor
// Collection of api ideas
// Call only if the charging session is authorized and the ev is connected
void start_session(bool, float, float, float, defs::ProtocolNumber);
// HW Signals
void update_hw_signal(HwSignal, bool);
// Update physical values
void update_present_voltage_current(float, float);
void update_available_voltage_current(float, float);
void update_isolation_status(events::IsolationStatus);
// Events
void cable_check_finished();
void stop();
// Error handling
void send_error(); // Todo: define error enums
void reset_errors();
private:
std::string can_interface;
ieee2030::events::EventQueue<events::Event> event_queue;
// HW Signals: Enable/disable CS1 & CS2 done
// EV Target voltage & current done
// EV min & max battery voltage
// Debug infos (protocol, soc)
// Fault
// Lock enable/disable?
//
const callback::Callbacks callbacks;
};
} // namespace ieee2030::charger

View File

@@ -0,0 +1,12 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
#include <ieee2030/common/messages/messages.hpp>
namespace ieee2030::charger::v20::state {
bool state_c_1(const messages::EV100&, const messages::EV101&, const messages::EV102&);
bool state_c_2(const messages::EV102&);
} // namespace ieee2030::charger::v20::state

View File

@@ -0,0 +1,124 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
#include <atomic>
#include <cstdint>
#include <functional>
#include <string>
#include <thread>
#include <vector>
#include <ieee2030/common/messages/messages.hpp>
namespace ieee2030::charger::io {
enum class CanEvent {
ACTIVE,
NEW_DATA,
INACTIVE,
};
using CanEventCallback = std::function<void(CanEvent)>;
class CanBrokerCharger {
enum class SendState {
ID_108,
ID_109,
};
public:
CanBrokerCharger();
CanBrokerCharger(const std::string&);
~CanBrokerCharger();
void set_event_callback(const CanEventCallback&);
void enable_tx_can() {
tx_active = true;
};
void disable_tx_can() {
tx_active = false;
};
bool rx_can_enabled() {
return rx_active;
}
const messages::EV100& get_can_100_message() const {
return message_100;
}
const messages::EV101& get_can_101_message() const {
return message_101;
}
const messages::EV102& get_can_102_message() const {
return message_102;
}
void init_charger_messages(bool welding_detection, float available_voltage, float available_current,
float threshold_voltage, defs::ProtocolNumber protocol) {
message_108 = messages::Charger108(welding_detection, available_voltage, available_current, threshold_voltage);
message_109 = messages::Charger109(protocol);
};
void update_present_voltage(float voltage) {
message_109.present_voltage = voltage;
}
void update_present_current(float current) {
message_109.present_current = current;
}
void update_available_voltage(float voltage) {
message_108.available_voltage = voltage;
}
void update_available_current(float current) {
message_108.available_current = current;
}
void update_threshold_voltage(float voltage) {
message_108.threshold_voltage = voltage;
}
void update_status_error_flag(defs::ChargerStatusError, bool);
void update_reamining_time_10s(uint16_t);
private:
std::atomic_bool exit_rx_loop{false};
std::atomic_bool rx_active{false};
void rx_loop();
std::thread rx_loop_thread;
void handle_can_input(uint32_t, const std::vector<uint8_t>&);
std::atomic_bool exit_tx_loop{false};
std::atomic_bool tx_active{false};
void tx_loop();
std::thread tx_loop_thread;
void send(uint32_t, const std::vector<uint8_t>&);
int can_fd{-1};
CanEventCallback event_callback{nullptr};
void publish_event(CanEvent event) {
if (!event_callback) {
return;
}
event_callback(event);
}
messages::EV100 message_100;
messages::EV101 message_101;
messages::EV102 message_102;
messages::Charger108 message_108;
messages::Charger109 message_109;
SendState tx_state{SendState::ID_108};
};
} // namespace ieee2030::charger::io

View File

@@ -0,0 +1,50 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
#include <functional>
namespace ieee2030::charger {
namespace callback {
enum class Signal {
START_CABLE_CHECK,
CHARGE_LOOP_STARTED,
CHARGE_LOOP_FINISHED,
};
enum class ChargerSequence {
CS1,
CS2,
};
enum class Status : bool {
OFF = false,
ON = true
};
struct HwSignal {
ChargerSequence signal;
Status status;
};
struct Callbacks {
std::function<void(Signal)> signal;
std::function<void(const HwSignal&)> hw_signal;
};
} // namespace callback
class Callback {
public:
Callback(callback::Callbacks);
void signal(callback::Signal) const;
void hw_signal(const callback::HwSignal&) const;
private:
callback::Callbacks callbacks;
};
} // namespace ieee2030::charger

View File

@@ -0,0 +1,58 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
#include <memory>
#include <vector>
#include <ieee2030/charger/io/can_broker_charger.hpp>
#include <ieee2030/common/messages/messages.hpp>
#include <everest/util/fsm/fsm.hpp>
#include <ieee2030/charger/v20/context.hpp>
#include <ieee2030/charger/v20/control_event.hpp>
#include <ieee2030/charger/v20/states.hpp>
namespace ieee2030::charger {
struct SessionState {
bool can_active{false};
bool new_data{false};
};
class Session {
public:
Session(std::unique_ptr<io::CanBrokerCharger>, const callback::Callbacks&);
~Session();
void update(const std::vector<events::Event>&);
bool is_session_active() const {
return session_is_active;
}
// void end_session() {
// session_is_active = false;
// }
private:
std::unique_ptr<io::CanBrokerCharger> can_broker;
std::optional<events::Event> active_event{std::nullopt};
SessionState state;
v20::Context ctx;
fsm::v2::FSM<ieee2030::charger::v20::StateBase> fsm;
bool session_is_active;
void handle_can_event(io::CanEvent);
messages::EV100 message_100;
messages::EV101 message_101;
messages::EV102 message_102;
};
} // namespace ieee2030::charger

View File

@@ -0,0 +1,85 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
#include <functional>
#include <memory>
#include <optional>
#include <ieee2030/charger/session/callback.hpp>
#include <ieee2030/charger/v20/control_event.hpp>
#include <ieee2030/common/io/time.hpp>
#include <ieee2030/common/messages/messages.hpp>
namespace ieee2030::charger::v20 {
struct CanBrokerContext {
std::function<void()> enable_can;
std::function<void()> disable_can;
std::function<void(defs::ChargerStatusError, bool)> update_status_error;
std::function<void(uint16_t)> update_reamining_time;
};
class StateBase;
using BasePointerType = std::unique_ptr<StateBase>;
class Context {
public:
Context(const std::optional<events::Event>&, callback::Callbacks, const messages::EV100&, const messages::EV101&,
const messages::EV102&);
template <typename StateType, typename... Args> BasePointerType create_state(Args&&... args) {
return std::make_unique<StateType>(*this, std::forward<Args>(args)...);
}
const auto& get_event() {
return current_event;
}
template <typename T> T const* get_event() {
if (not current_event.has_value()) {
return nullptr;
}
if (not std::holds_alternative<T>(*current_event)) {
return nullptr;
}
return &std::get<T>(*current_event);
}
const messages::EV100& message_100;
const messages::EV101& message_101;
const messages::EV102& message_102;
void set_can_broker_callback(const CanBrokerContext& callbacks_) {
can_broker_callbacks = callbacks_;
}
void enable_can() {
can_broker_callbacks.enable_can();
}
void disable_can() {
can_broker_callbacks.disable_can();
}
void update_status_error(defs::ChargerStatusError status, bool active) {
can_broker_callbacks.update_status_error(status, active);
}
void update_reaminig_time_s(uint16_t seconds) {
can_broker_callbacks.update_reamining_time(seconds);
}
const Callback callbacks;
// bool& log; // Todo: Adding log file logic and write to log file
ieee2030::io::Timeout timeout;
private:
const std::optional<events::Event>& current_event;
CanBrokerContext can_broker_callbacks;
};
} // namespace ieee2030::charger::v20

View File

@@ -0,0 +1,109 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
#include <variant>
namespace ieee2030::charger::events {
class CS1 {
public:
explicit CS1(bool status_) : status(status_) {
}
operator bool() const {
return status;
}
private:
bool status;
};
class CS2 {
public:
explicit CS2(bool status_) : status(status_) {
}
operator bool() const {
return status;
}
private:
bool status;
};
class ProximityDetection {
public:
explicit ProximityDetection(bool status_) : status(status_) {
}
operator bool() const {
return status;
}
private:
bool status;
};
class ChargePermission {
public:
explicit ChargePermission(bool status_) : status(status_) {
}
operator bool() const {
return status;
}
private:
bool status;
};
class CableCheckFinished {
public:
explicit CableCheckFinished(bool success_) : success(success_) {
}
operator bool() const {
return success;
}
private:
bool success;
};
class StopCharging {
public:
explicit StopCharging(bool stop_) : stop(stop_) {
}
operator bool() const {
return stop;
}
private:
bool stop;
};
struct PresentVoltageCurrent {
float voltage;
float current;
};
struct AvailableVoltageCurrent {
float voltage;
float current;
};
enum class IsolationStatus {
Invalid,
Valid,
Fault,
};
enum class Error {
Test,
};
using Event = std::variant<CS1, CS2, ProximityDetection, ChargePermission, CableCheckFinished, StopCharging,
PresentVoltageCurrent, AvailableVoltageCurrent, IsolationStatus, Error>;
} // namespace ieee2030::charger::events

View File

@@ -0,0 +1,22 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
#include "../states.hpp"
namespace ieee2030::charger::v20::state {
struct StateB : public StateBase {
public:
StateB(Context& ctx) : StateBase(ctx, StateID::StateB) {
}
void enter() final;
Result feed(Event) final;
private:
bool stop{false};
};
} // namespace ieee2030::charger::v20::state

View File

@@ -0,0 +1,37 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
#include "../states.hpp"
#include <ieee2030/common/messages/messages.hpp>
namespace ieee2030::charger::v20::state {
namespace state_c {
enum class InternalStates {
C_1,
C_2,
};
} // namespace state_c
struct StateC : public StateBase {
public:
StateC(Context& ctx) : StateBase(ctx, StateID::StateC) {
}
void enter() final;
Result feed(Event) final;
private:
bool stop{false};
state_c::InternalStates states{state_c::InternalStates::C_1};
messages::EV100 ev_100;
messages::EV101 ev_101;
messages::EV102 ev_102;
};
} // namespace ieee2030::charger::v20::state

View File

@@ -0,0 +1,55 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
#include "context.hpp"
namespace ieee2030::charger::v20 {
class Context;
enum class Event {
CAN_MESSAGE,
HW_SIGNAL,
EVENT,
TIMEOUT,
};
enum class StateID {
StateB,
StateC
};
struct Result {
constexpr Result() = default;
Result(BasePointerType result_state) : unhandled(false), new_state(std::move(result_state)) {
}
bool unhandled{true};
BasePointerType new_state{nullptr};
};
struct StateBase {
using ContainerType = BasePointerType;
using EventType = Event;
StateBase(Context& ctx, StateID id) : m_ctx(ctx), m_id(id){};
virtual ~StateBase() = default;
StateID get_id() const {
return m_id;
}
virtual void enter(){};
virtual Result feed(Event) = 0;
virtual void leave(){};
protected:
Context& m_ctx;
private:
StateID m_id;
};
} // namespace ieee2030::charger::v20

View File

@@ -0,0 +1,88 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2022 - 2026 Pionix GmbH and Contributors to EVerest
#pragma once
#include <cstdint>
#include <cstring>
#include <stdexcept>
#include <type_traits>
#include <vector>
#include <endian.h>
template <class T> typename std::enable_if_t<sizeof(T) == 1, T> from_raw(const std::vector<uint8_t>& raw, int idx) {
T ret = raw[idx];
return ret;
}
template <class T> typename std::enable_if_t<sizeof(T) == 2, T> from_raw(const std::vector<uint8_t>& raw, int idx) {
if (idx + sizeof(T) > raw.size()) {
throw std::out_of_range("from_raw: buffer access out of bounds");
}
uint16_t tmp{};
memcpy(&tmp, raw.data() + idx, sizeof(uint16_t)); // Safe copy from buffer
tmp = be16toh(tmp); // Convert endianness
T ret;
memcpy(&ret, &tmp, 2);
return ret;
}
template <class T> typename std::enable_if_t<sizeof(T) == 4, T> from_raw(const std::vector<uint8_t>& raw, int idx) {
if (idx + sizeof(T) > raw.size()) {
throw std::out_of_range("from_raw: buffer access out of bounds");
}
uint32_t tmp{};
memcpy(&tmp, raw.data() + idx, sizeof(uint32_t)); // Safe copy from buffer
tmp = be32toh(tmp); // Convert endianness
T ret;
memcpy(&ret, &tmp, 4);
return ret;
}
template <class T> typename std::enable_if_t<sizeof(T) == 8, T> from_raw(const std::vector<uint8_t>& raw, int idx) {
if (idx + sizeof(T) > raw.size()) {
throw std::out_of_range("from_raw: buffer access out of bounds");
}
uint64_t tmp{};
memcpy(&tmp, raw.data() + idx, sizeof(uint64_t)); // Safe copy from buffer
tmp = be64toh(tmp); // Convert endianness
T ret;
memcpy(&ret, &tmp, 8);
return ret;
}
template <class T> typename std::enable_if_t<sizeof(T) == 1> to_raw(T src, std::vector<uint8_t>& dest) {
uint8_t tmp{};
memcpy(&tmp, &src, 1);
dest.push_back(tmp);
}
// FIXME (aw): these conversions should be optimized!
template <class T> typename std::enable_if_t<sizeof(T) == 2> to_raw(T src, std::vector<uint8_t>& dest) {
uint16_t tmp{};
memcpy(&tmp, &src, 2);
tmp = htobe16(tmp);
uint8_t ret[2];
memcpy(ret, &tmp, 2);
dest.insert(dest.end(), {ret[0], ret[1]});
}
template <class T> typename std::enable_if_t<sizeof(T) == 4> to_raw(T src, std::vector<uint8_t>& dest) {
uint32_t tmp{};
memcpy(&tmp, &src, 4);
tmp = htobe32(tmp);
uint8_t ret[4];
memcpy(ret, &tmp, 4);
dest.insert(dest.end(), {ret[0], ret[1], ret[2], ret[3]});
}
template <class T> typename std::enable_if_t<sizeof(T) == 8> to_raw(T src, std::vector<uint8_t>& dest) {
uint64_t tmp{};
memcpy(&tmp, &src, 8);
tmp = htobe64(tmp);
uint8_t ret[8];
memcpy(ret, &tmp, 8);
dest.insert(dest.end(), {ret[0], ret[1], ret[2], ret[3], ret[4], ret[5], ret[6], ret[7]});
}

View File

@@ -0,0 +1,25 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
#include <cstdarg>
#include <string>
namespace ieee2030 {
void logf(const char* fmt, ...);
void vlogf(const char* fmt, va_list ap);
void log(const std::string&);
template <typename CallbackType, typename... Args> bool call_if_available(const CallbackType& callback, Args... args) {
if (not callback) {
false;
}
callback(std::forward<Args>(args)...);
return true;
}
} // namespace ieee2030

View File

@@ -0,0 +1,11 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
#include <functional>
#include <string>
namespace ieee2030::io {
void set_logging_callback(const std::function<void(std::string)>&);
} // namespace ieee2030::io

View File

@@ -0,0 +1,34 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
#include <chrono>
#include <optional>
namespace ieee2030::io {
using TimePoint = std::chrono::steady_clock::time_point;
inline TimePoint get_current_time_point() {
return std::chrono::steady_clock::now();
}
inline TimePoint offset_time_point_by_ms(const TimePoint& time_point, int32_t offset) {
return time_point + std::chrono::milliseconds(offset);
}
// Todo: How to handle parallel timeouts?
class Timeout {
public:
Timeout(){};
void start(float timeout_s); // Todo: Perhaps change that chrono::seconds
void reset();
std::optional<bool> timeout_reached();
private:
std::optional<TimePoint> timeout_point;
};
} // namespace ieee2030::io

View File

@@ -0,0 +1,150 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2022 - 2026 Pionix GmbH and Contributors to EVerest
#pragma once
// #include <linux/can.h>
#include <optional>
#include <ostream>
#include <stdint.h>
#include <vector>
namespace ieee2030 {
namespace defs {
static constexpr auto CHARGED_RATE_REFERENCE = 100;
enum class ProtocolNumber : uint8_t {
VERSION_0_9_1 = 0,
VERSION_1_X_X = 1,
VERSION_2_0 = 2,
};
enum class EVStatusFault : uint8_t {
FAULT_BATTERY_OVER_VOLTAGE,
FAULT_BATTERY_UNDER_VOTLAGE,
FAULT_BATTER_CURRENT_DEVIATION_ERROR,
FAULT_HIGH_BATTERY_TEMPERATURE,
FAULT_BATTERY_VOLTAGE_DEVIATION_ERROR,
STATUS_CHARGING_ENABLED,
STATUS_SHIFT_POSITION,
STATUS_SYSTEM_FAULT,
STATUS_VEHICLE_STATUS,
STATUS_STOP_REQUEST,
};
enum class ChargerStatusError : uint8_t {
CHARGER_STATUS,
CHARGER_MALFUNCTION,
CONNECTOR_LOCK,
BATTERY_INCOMPATIBILITY,
SYSTEM_MALFUNCTION,
STOP_CONTROL,
};
} // namespace defs
namespace messages {
static constexpr auto EV_ID_100 = 0x100;
static constexpr auto EV_ID_101 = 0x101;
static constexpr auto EV_ID_102 = 0x102;
struct EV100 {
EV100(){};
EV100(const std::vector<uint8_t> raw);
friend std::ostream& operator<<(std::ostream&, const EV100&);
operator std::vector<uint8_t>();
float max_battery_voltage;
uint8_t charged_rate{defs::CHARGED_RATE_REFERENCE};
};
struct EV101 {
EV101(){};
EV101(const std::vector<uint8_t> raw);
friend std::ostream& operator<<(std::ostream&, const EV101&);
operator std::vector<uint8_t>();
uint8_t max_charging_time_10s; // 0xFF -> use of time_1min
uint8_t max_charging_time_1min;
uint8_t estimated_charging_time_1min;
std::optional<float> total_capacity; // 0.1kWh/bit
};
struct EV102 {
EV102(){};
EV102(const std::vector<uint8_t> raw);
friend std::ostream& operator<<(std::ostream&, const EV102&);
operator std::vector<uint8_t>();
defs::ProtocolNumber protocol;
float target_voltage;
float target_current;
bool fault_battery_over_voltage;
bool fault_battery_under_voltage;
bool fault_battery_current_deviation_error;
bool fault_high_battery_temperature;
bool fault_battery_voltage_deviation_error;
bool status_charging_enabled;
bool status_shift_position;
bool status_system_fault;
bool status_vehicle_status;
bool status_stop_request;
uint8_t soc; // 0% - 100%
};
namespace v1_2 {} // namespace v1_2
namespace v2_0 {} // namespace v2_0
static constexpr auto CHARGER_ID_108 = 0x108;
static constexpr auto CHARGER_ID_109 = 0x109;
struct Charger108 {
Charger108(){};
Charger108(const std::vector<uint8_t> raw);
Charger108(bool welding_detection_, float voltage_, float current_, float threshold_voltage_) :
identifier_welding_detection(welding_detection_),
available_voltage(voltage_),
available_current(current_),
threshold_voltage(threshold_voltage_){};
friend std::ostream& operator<<(std::ostream&, const Charger108&);
operator std::vector<uint8_t>();
uint8_t identifier_welding_detection; // 0: not supported, 1-255: supported
float available_voltage;
float available_current;
float threshold_voltage;
};
struct Charger109 {
Charger109(){};
Charger109(const std::vector<uint8_t> raw);
Charger109(defs::ProtocolNumber protocol_) : protocol(protocol_){};
friend std::ostream& operator<<(std::ostream&, const Charger109&);
operator std::vector<uint8_t>();
defs::ProtocolNumber protocol;
float present_voltage;
float present_current;
bool charger_status;
bool charger_malfunction;
bool connector_lock;
bool battery_incompatibility;
bool system_malfunction;
bool stop_control{true};
uint8_t reamining_time_10s; // 0xFF -> use of time_1min
uint8_t reamining_time_1min;
};
namespace v1_2 {} // namespace v1_2
namespace v2_0 {} // namespace v2_0
} // namespace messages
} // namespace ieee2030

View File

@@ -0,0 +1,37 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
#include <mutex>
#include <optional>
#include <queue>
namespace ieee2030::events {
template <class T> class EventQueue {
public:
std::optional<T> pop() {
std::lock_guard<std::mutex> lck(mutex);
if (queue.empty()) {
return std::nullopt;
}
auto event = std::make_optional<T>(std::move(queue.front()));
queue.pop();
return event;
};
void push(T event) {
std::lock_guard<std::mutex> lck(mutex);
queue.push(std::move(event));
};
private:
std::queue<T> queue;
std::mutex mutex;
};
} // namespace ieee2030::events

View File

@@ -0,0 +1,92 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
#include <atomic>
#include <cstdint>
#include <functional>
#include <string>
#include <thread>
#include <vector>
#include <ieee2030/common/messages/messages.hpp>
namespace ieee2030::ev::io {
enum class CanEvent {
ACTIVE,
NEW_DATA,
INACTIVE,
};
using CanEventCallback = std::function<void(CanEvent)>;
// Todo(sl): Check if refactoring with CanBrokerCharger is possible
class CanBrokerEv {
enum class SendState {
ID_100,
ID_101,
ID_102,
};
public:
CanBrokerEv(){}; // Todo(sl): Check if needed
CanBrokerEv(const std::string&);
~CanBrokerEv();
void set_event_callback(const CanEventCallback&);
void enable_tx_can() {
tx_active = true;
};
void disable_tx_can() {
tx_active = false;
};
const messages::Charger108& get_can_108_message() const {
return message_108;
};
const messages::Charger109& get_can_109_message() const {
return message_109;
}
void init_messages(); // Todo(sl): Define init arguments
// Todo(sl): define update functions
private:
std::atomic_bool exit_rx_loop{false};
std::atomic_bool rx_active{false};
void rx_loop();
std::thread rx_loop_thread;
void handle_can_input(uint32_t, const std::vector<uint8_t>&);
std::atomic_bool exit_tx_loop{false};
std::atomic_bool tx_active{false};
void tx_loop();
std::thread tx_loop_thread;
void send(uint32_t, const std::vector<uint8_t>&);
int can_fd{-1};
CanEventCallback event_callback{nullptr};
void publish_event(CanEvent event) {
if (!event_callback) {
return;
}
event_callback(event);
}
messages::EV100 message_100;
messages::EV101 message_101;
messages::EV102 message_102;
messages::Charger108 message_108;
messages::Charger109 message_109;
SendState tx_state{SendState::ID_100};
};
} // namespace ieee2030::ev::io