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,23 @@
#
# 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
# insert your custom targets and additional config variables here
list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(PCAP REQUIRED)
target_link_libraries(${MODULE_NAME}
PRIVATE
${PCAP_LIBRARY}
)
# ev@bcc62523-e22b-41d7-ba2f-825b493a3c97:v1
# 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,113 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#include "PacketSniffer.hpp"
#include <fmt/core.h>
#include <fmt/chrono.h>
namespace module {
const bool PROMISC_MODE = true;
const int PACKET_BUFFER_TIMEOUT_MS = 1000;
const int ALL_PACKETS_PROCESSED = -1;
const int WAIT_FOR_MS = 10;
const int BUFFERSIZE = 8192;
void PacketSniffer::init() {
p_handle = pcap_open_live(config.device.c_str(), BUFFERSIZE, PROMISC_MODE, PACKET_BUFFER_TIMEOUT_MS, errbuf);
std::string errb{errbuf};
if (p_handle == nullptr) {
EVLOG_error << fmt::format("Could not open device \"{}\", Sniffing disabled.{}", config.device,
errb.size() > 0 ? (std::string(" Error: ") + errb) : "");
return;
}
if (config.device != "any" && pcap_datalink(p_handle) != DLT_EN10MB) {
EVLOG_error << fmt::format("Device \"{}\" doesn't provide Ethernet headers - not supported. Sniffing disabled.",
config.device);
pcap_close(p_handle);
return;
}
EVLOG_info << fmt::format("Sniffing on device \"{}\"", config.device);
r_evse_manager->subscribe_session_event([this](types::evse_manager::SessionEvent session_event) {
if (session_event.event == types::evse_manager::SessionEventEnum::SessionStarted) {
if (!already_started) {
if (!session_event.session_started.has_value()) {
EVLOG_warning
<< "SessionStarted event type doesn't contain session_started data. Ignoring this event.";
return;
}
std::string logging_path;
if (!config.session_logging_path.empty()) {
logging_path = config.session_logging_path;
} else if (session_event.session_started->logging_path.has_value()) {
logging_path = session_event.session_started->logging_path.value();
} else {
EVLOG_warning << "No logging path configured and none provided in SessionStarted event. "
"Skipping capture.";
return;
}
capturing_stopped = false;
std::thread(&PacketSniffer::capture, this, logging_path, session_event.uuid).detach();
} else {
EVLOG_warning << fmt::format("Capturing already started. Ignoring this SessionStarted event");
}
} else if (session_event.event == types::evse_manager::SessionEventEnum::SessionFinished) {
capturing_stopped = true;
pcap_breakloop(p_handle);
}
});
}
void PacketSniffer::ready() {
}
void PacketSniffer::capture(const std::string& logpath, const std::string& session_id) {
already_started = true;
std::string fn = fmt::format("{}/ethernet-traffic.pcap", logpath);
if (not config.session_logging_path.empty()) {
const auto now = std::chrono::system_clock::now();
const auto time_t_now = std::chrono::system_clock::to_time_t(now);
std::tm local_tm{};
localtime_r(&time_t_now, &local_tm);
const auto timestamp = fmt::format("{:%Y-%m-%d_%H-%M-%S%z}", local_tm);
fn = fmt::format("{}/{}_{}.pcap", logpath, timestamp, session_id);
}
EVLOG_info << fmt::format("Starting capturing to {}", fn);
if ((pdumpfile = pcap_dump_open(p_handle, fn.c_str())) == nullptr) {
EVLOG_error << fmt::format("Error opening savefile {} for writing: {}", fn, pcap_geterr(p_handle));
return;
}
while (!capturing_stopped) {
const int ret =
pcap_dispatch(p_handle, ALL_PACKETS_PROCESSED, &pcap_dump, reinterpret_cast<u_char*>(pdumpfile));
if (ret <= PCAP_ERROR) {
const std::string base_msg = fmt::format("Error reading packets from interface \"{}\"", config.device);
if (ret == PCAP_ERROR) {
EVLOG_error << fmt::format("{}, error: {}", base_msg, pcap_geterr(p_handle));
} else if (ret == PCAP_ERROR_BREAK) {
EVLOG_warning << fmt::format("{}, interrupted but no packets received", base_msg);
} else {
EVLOG_error << fmt::format("{}, unexpected error: {}", base_msg, ret);
}
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_FOR_MS));
}
pcap_dump_close(pdumpfile);
EVLOG_info << fmt::format("Stopped capturing to {}", fn);
already_started = false;
}
} // namespace module

View File

@@ -0,0 +1,68 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#ifndef PACKET_SNIFFER_HPP
#define PACKET_SNIFFER_HPP
//
// AUTO GENERATED - MARKED REGIONS WILL BE KEPT
// template version 2
//
#include "ld-ev.hpp"
// headers for required interface implementations
#include <generated/interfaces/evse_manager/Interface.hpp>
// ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1
// insert your custom include headers here
#include <pcap.h>
// ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1
namespace module {
struct Conf {
std::string device;
std::string session_logging_path;
};
class PacketSniffer : public Everest::ModuleBase {
public:
PacketSniffer() = delete;
PacketSniffer(const ModuleInfo& info, std::unique_ptr<evse_managerIntf> r_evse_manager, Conf& config) :
ModuleBase(info), r_evse_manager(std::move(r_evse_manager)), config(config){};
const std::unique_ptr<evse_managerIntf> r_evse_manager;
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
void capture(const std::string& logpath, const std::string& session_id);
pcap_t* p_handle{nullptr};
pcap_dumper_t* pdumpfile{nullptr};
char errbuf[PCAP_ERRBUF_SIZE]{""};
std::atomic_bool capturing_stopped{false};
std::atomic_bool already_started{false};
// 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 // PACKET_SNIFFER_HPP

View File

@@ -0,0 +1,118 @@
# FindPCAP.cmake
# ===========================================
# See https://github.com/zeek/cmake/FindPCAP.cmake for usage and update instructions.
#
# BSD License
# -----------
#[[
Copyright (c) 1995-2017, The Regents of the University of California
through the Lawrence Berkeley National Laboratory and the
International Computer Science Institute. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
(1) Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
(2) Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
(3) Neither the name of the University of California, Lawrence Berkeley
National Laboratory, U.S. Dept. of Energy, International Computer
Science Institute, nor the names of contributors may be used to endorse
or promote products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Note that some files in the distribution may carry their own copyright
notices.
]]
# - Try to find libpcap include dirs and libraries
#
# Usage of this module as follows:
#
# find_package(PCAP)
#
# Variables used by this module, they can change the default behaviour and need
# to be set before calling find_package:
#
# PCAP_ROOT_DIR Set this variable to the root installation of
# libpcap if the module has problems finding the
# proper installation path.
#
# Variables defined by this module:
#
# PCAP_FOUND System has libpcap, include and library dirs found
# PCAP_INCLUDE_DIR The libpcap include directories.
# PCAP_LIBRARY The libpcap library (possibly includes a thread
# library e.g. required by pf_ring's libpcap)
# HAVE_PF_RING If a found version of libpcap supports PF_RING
find_path(PCAP_ROOT_DIR
NAMES include/pcap.h
)
find_path(PCAP_INCLUDE_DIR
NAMES pcap.h
HINTS ${PCAP_ROOT_DIR}/include
)
find_library(PCAP_LIBRARY
NAMES pcap
HINTS ${PCAP_ROOT_DIR}/lib
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(PCAP DEFAULT_MSG
PCAP_LIBRARY
PCAP_INCLUDE_DIR
)
include(CheckCSourceCompiles)
set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY})
check_c_source_compiles("int main() { return 0; }" PCAP_LINKS_SOLO)
set(CMAKE_REQUIRED_LIBRARIES)
# check if linking against libpcap also needs to link against a thread library
if (NOT PCAP_LINKS_SOLO)
find_package(Threads)
if (THREADS_FOUND)
set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
check_c_source_compiles("int main() { return 0; }" PCAP_NEEDS_THREADS)
set(CMAKE_REQUIRED_LIBRARIES)
endif ()
if (THREADS_FOUND AND PCAP_NEEDS_THREADS)
set(_tmp ${PCAP_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
list(REMOVE_DUPLICATES _tmp)
set(PCAP_LIBRARY ${_tmp}
CACHE STRING "Libraries needed to link against libpcap" FORCE)
else ()
message(FATAL_ERROR "Couldn't determine how to link against libpcap")
endif ()
endif ()
include(CheckFunctionExists)
set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY})
check_function_exists(pcap_get_pfring_id HAVE_PF_RING)
check_function_exists(pcap_dump_open_append HAVE_PCAP_DUMP_OPEN_APPEND)
set(CMAKE_REQUIRED_LIBRARIES)
mark_as_advanced(
PCAP_ROOT_DIR
PCAP_INCLUDE_DIR
PCAP_LIBRARY
)

View File

@@ -0,0 +1,23 @@
description: >-
Using the "PacketSniffer" EVerest module it is possible to capture and
store the different packets on the PLC interface.
config:
device:
description: >-
The ethernet device on which the messages are to be captured
type: string
default: eth1
session_logging_path:
description: >-
Output directory for session capture dump files. Will be used only if not empty.
If empty, the logging path provided in the SessionStarted event will be used.
If no logging path is provided there either, no capture will be performed.
type: string
default: /tmp
requires:
evse_manager:
interface: evse_manager
metadata:
license: https://opensource.org/licenses/Apache-2.0
authors:
- Sebastian Lukas