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:
10
tools/EVerest-main/.bazelignore
Normal file
10
tools/EVerest-main/.bazelignore
Normal file
@@ -0,0 +1,10 @@
|
||||
build
|
||||
modules/framework
|
||||
lib/everest/framework/bazel-bin
|
||||
lib/everest/framework/bazel-framework
|
||||
lib/everest/framework/bazel-out
|
||||
lib/everest/framework/bazel-testlogs
|
||||
modules/framework/bazel-bin
|
||||
modules/framework/bazel-framework
|
||||
modules/framework/bazel-out
|
||||
modules/framework/bazel-testlogs
|
||||
33
tools/EVerest-main/.bazelrc
Normal file
33
tools/EVerest-main/.bazelrc
Normal file
@@ -0,0 +1,33 @@
|
||||
# Re-enable autoloading for language-specific rules that were removed from
|
||||
# Bazel 9 core. This is needed because many BCR modules haven't yet added
|
||||
# explicit load() statements for rules_cc, rules_python, and rules_shell.
|
||||
# This flag can be removed once all dependencies are updated for Bazel 9.
|
||||
build --incompatible_autoload_externally=+cc_library,+cc_binary,+cc_test,+cc_shared_library,+cc_import,+cc_toolchain,+py_binary,+py_library,+py_test,+sh_binary,+sh_library,+sh_test
|
||||
|
||||
# Force -fPIC on C/C++ compilation so static archives can be linked into PIE
|
||||
# binaries. Required because modern rustc defaults to producing PIE executables
|
||||
# on x86_64-unknown-linux-gnu, and any static C++ library mixed into a Rust
|
||||
# binary therefore has to be position-independent.
|
||||
build --copt=-fPIC
|
||||
|
||||
# CI config: smaller binaries, shared repo cache, disk cache for artifacts.
|
||||
build:ci -c opt
|
||||
build:ci --strip=always
|
||||
build:ci --copt=-g0
|
||||
build:ci --repository_cache=~/.cache/bazel-repo-cache
|
||||
build:ci --disk_cache=~/.cache/bazel-disk-cache
|
||||
|
||||
# workaround for goption.c:169:14: error: two or more data types in declaration specifiers on armv7
|
||||
build:armv7-linux-gnueabihf --repo_env=BAZEL_CONLYOPTS="-std=gnu17"
|
||||
build:aarch64-linux-gnu --repo_env=BAZEL_CONLYOPTS=""
|
||||
build:aarch64-linux-musl --repo_env=BAZEL_CONLYOPTS=""
|
||||
build:armv7-linux-musleabihf --repo_env=BAZEL_CONLYOPTS=""
|
||||
|
||||
# With our setup Bazel links every binary statically to `libframework.a` If you
|
||||
# want to link dynamically to `libframework.so` use `--dynamic_mode=fully`.
|
||||
# See https://bazel.build/docs/user-manual#dynamic-mode for more details. If
|
||||
# linking dynamically, ensure that `libframework.so` is in the
|
||||
# `LD_LIBRARY_PATH`.
|
||||
#
|
||||
# Not supported on musl targets.
|
||||
# --dynamic_mode=default
|
||||
1
tools/EVerest-main/.bazelversion
Normal file
1
tools/EVerest-main/.bazelversion
Normal file
@@ -0,0 +1 @@
|
||||
9.0.0
|
||||
39
tools/EVerest-main/.ci/e2e/docker-compose.yaml
Normal file
39
tools/EVerest-main/.ci/e2e/docker-compose.yaml
Normal file
@@ -0,0 +1,39 @@
|
||||
version: "3.6"
|
||||
|
||||
services:
|
||||
mqtt-server:
|
||||
image: eclipse-mosquitto:2.0.10
|
||||
volumes:
|
||||
- type: bind
|
||||
source: ./mosquitto/mosquitto.conf
|
||||
target: /mosquitto/config/mosquitto.conf
|
||||
logging:
|
||||
driver: none
|
||||
networks:
|
||||
- testnetwork
|
||||
|
||||
e2e-test-server:
|
||||
image: integration-image
|
||||
depends_on:
|
||||
- mqtt-server
|
||||
environment:
|
||||
- MQTT_SERVER_ADDRESS=mqtt-server
|
||||
volumes:
|
||||
- type: bind
|
||||
source: ${GITHUB_WORKSPACE}
|
||||
target: /ext
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
sysctls:
|
||||
- net.ipv6.conf.all.disable_ipv6=0
|
||||
networks:
|
||||
- testnetwork
|
||||
|
||||
networks:
|
||||
testnetwork:
|
||||
enable_ipv6: true
|
||||
driver: bridge
|
||||
ipam:
|
||||
driver: default
|
||||
config:
|
||||
- subnet: "fd00:dead:beef::/64"
|
||||
8
tools/EVerest-main/.ci/e2e/mosquitto/mosquitto.conf
Normal file
8
tools/EVerest-main/.ci/e2e/mosquitto/mosquitto.conf
Normal file
@@ -0,0 +1,8 @@
|
||||
# listener port-number [ip address/host name/unix socket path]
|
||||
listener 1883
|
||||
|
||||
|
||||
listener 9001
|
||||
protocol websockets
|
||||
|
||||
allow_anonymous true
|
||||
138
tools/EVerest-main/.clang-format
Normal file
138
tools/EVerest-main/.clang-format
Normal file
@@ -0,0 +1,138 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveMacros: true
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: AfterColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 120
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentCaseLabels: false
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
Standard: Latest
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
...
|
||||
|
||||
11
tools/EVerest-main/.clang-tidy
Normal file
11
tools/EVerest-main/.clang-tidy
Normal file
@@ -0,0 +1,11 @@
|
||||
Checks: >
|
||||
*,
|
||||
-llvmlibc*,
|
||||
-fuchsia-default-arguments-calls,
|
||||
-fuchsia-overloaded-operator,
|
||||
-fuchsia-statically-constructed-objects,
|
||||
-readability-function-cognitive-complexity,
|
||||
-modernize-use-trailing-return-type,
|
||||
-abseil-string-find-startswith,
|
||||
-abseil-string-find-str-contains
|
||||
HeaderFilterRegex: ".*"
|
||||
1
tools/EVerest-main/.devcontainer/.gitignore
vendored
Normal file
1
tools/EVerest-main/.devcontainer/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.env
|
||||
64
tools/EVerest-main/.devcontainer/docker-compose.yml
Normal file
64
tools/EVerest-main/.devcontainer/docker-compose.yml
Normal file
@@ -0,0 +1,64 @@
|
||||
volumes:
|
||||
ocpp-db-data:
|
||||
external: false
|
||||
node-red-data:
|
||||
external: false
|
||||
|
||||
services:
|
||||
mqtt-server:
|
||||
build: ../applications/containers/mosquitto
|
||||
ports:
|
||||
- 1883:1883
|
||||
- 9001:9001
|
||||
profiles:
|
||||
- all
|
||||
- mqtt
|
||||
- ocpp
|
||||
- sil
|
||||
|
||||
ocpp-db:
|
||||
image: mariadb:10.4.30 # pinned to patch-version because https://github.com/steve-community/steve/pull/1213
|
||||
volumes:
|
||||
- ocpp-db-data:/var/lib/mysql
|
||||
ports:
|
||||
- 13306:3306
|
||||
environment:
|
||||
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
|
||||
MYSQL_DATABASE: ocpp-db
|
||||
MYSQL_USER: ocpp
|
||||
MYSQL_PASSWORD: ocpp
|
||||
profiles:
|
||||
- all
|
||||
- ocpp
|
||||
steve:
|
||||
build: ../applications/containers/steve
|
||||
ports:
|
||||
- 8180:8180
|
||||
- 8443:8443
|
||||
depends_on:
|
||||
- ocpp-db
|
||||
profiles:
|
||||
- all
|
||||
- ocpp
|
||||
mqtt-explorer:
|
||||
build: ../applications/containers/mqtt-explorer
|
||||
depends_on:
|
||||
- mqtt-server
|
||||
ports:
|
||||
- 4000:4000
|
||||
profiles:
|
||||
- all
|
||||
- sil
|
||||
nodered:
|
||||
build: ../applications/containers/nodered
|
||||
ports:
|
||||
- 1880:1880
|
||||
volumes:
|
||||
- node-red-data:/data
|
||||
environment:
|
||||
- NODE_RED_ENABLE_PROJECTS=false
|
||||
- MQTT_BROKER=mqtt-server
|
||||
- MQTT_PORT=1883
|
||||
profiles:
|
||||
- all
|
||||
- sil
|
||||
@@ -0,0 +1,86 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM ghcr.io/everest/everest-ci/dev-env-base:v1.5.4
|
||||
|
||||
# Build arguments for customization
|
||||
# User and group configuration i.e. to match host user inside the container
|
||||
ARG USERNAME=docker
|
||||
ARG USER_UID=1000
|
||||
ARG USER_GID=1000
|
||||
# Configuration for everest-dev-tool's default git settings, can be overridden when working i.e. in a fork
|
||||
ARG EVEREST_DEV_TOOL_DEFAULT_GIT_ORGANIZATION_ARG=EVerest
|
||||
ARG EVEREST_DEV_TOOL_DEFAULT_GIT_HOST_ARG=github.com
|
||||
ARG EVEREST_DEV_TOOL_DEFAULT_GIT_SSH_USER_ARG=git
|
||||
|
||||
##################################################################
|
||||
# Should be moved to everest-dev-base at some point
|
||||
|
||||
# Update the package list and install dependencies (run as root)
|
||||
USER root
|
||||
RUN apt-get update && apt-get install -y \
|
||||
protobuf-compiler \
|
||||
libsystemd-dev \
|
||||
libboost-log-dev \
|
||||
tmux \
|
||||
chrpath \
|
||||
cpio \
|
||||
diffstat \
|
||||
gawk \
|
||||
wget \
|
||||
zstd \
|
||||
liblz4-tool \
|
||||
file \
|
||||
iproute2 \
|
||||
&& DEBIAN_FRONTEND=noninteractive apt-get install -y locales \
|
||||
&& sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \
|
||||
&& dpkg-reconfigure --frontend=noninteractive locales \
|
||||
&& update-locale LANG=en_US.UTF-8
|
||||
|
||||
ENV LANG en_US.UTF-8
|
||||
|
||||
|
||||
|
||||
# EVerest Development Tool - Dependencies
|
||||
RUN pip install --break-system-packages \
|
||||
nanopb \
|
||||
pytest
|
||||
|
||||
# EVerest Development Tool
|
||||
|
||||
COPY --from=everest_dev_tool_src . /tmp/everest_dev_tool
|
||||
RUN ls -al /tmp/everest_dev_tool \
|
||||
&& python3 -m pip install \
|
||||
--break-system-packages \
|
||||
/tmp/everest_dev_tool/ \
|
||||
&& rm -rf /tmp/everest_dev_tool
|
||||
|
||||
##################################################################
|
||||
|
||||
# Modify the existing docker user and group to match the host's USER_UID and USER_GID
|
||||
RUN groupmod --gid ${USER_GID} ${USERNAME} && \
|
||||
usermod --uid ${USER_UID} --gid ${USER_GID} ${USERNAME} && \
|
||||
usermod -aG dialout ${USERNAME}
|
||||
|
||||
# Switch to the docker user
|
||||
USER ${USERNAME}
|
||||
WORKDIR /workspace
|
||||
|
||||
# Add known hosts for git repositories
|
||||
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan ${EVEREST_DEV_TOOL_DEFAULT_GIT_HOST_ARG} >> ~/.ssh/known_hosts
|
||||
|
||||
# Set environment variables
|
||||
ENV EVEREST_DEV_TOOL_DEFAULT_GIT_METHOD=ssh
|
||||
ENV EVEREST_DEV_TOOL_DEFAULT_GIT_HOST=${EVEREST_DEV_TOOL_DEFAULT_GIT_HOST_ARG}
|
||||
ENV EVEREST_DEV_TOOL_DEFAULT_GIT_SSH_USER=${EVEREST_DEV_TOOL_DEFAULT_GIT_SSH_USER_ARG}
|
||||
ENV EVEREST_DEV_TOOL_DEFAULT_GIT_ORGANIZATION=${EVEREST_DEV_TOOL_DEFAULT_GIT_ORGANIZATION_ARG}
|
||||
|
||||
# Enable command line completion for devrd script by default
|
||||
RUN echo "" >> ${HOME}/.bashrc && \
|
||||
echo "# Enable devrd command completion if available" >> ${HOME}/.bashrc && \
|
||||
echo "if [ -f /workspace/applications/devrd/devrd-completion.bash ]; then" >> ${HOME}/.bashrc && \
|
||||
echo " source /workspace/applications/devrd/devrd-completion.bash" >> ${HOME}/.bashrc && \
|
||||
echo "fi" >> ${HOME}/.bashrc
|
||||
|
||||
# Set up welcome message
|
||||
RUN echo "echo \"🏔️ 🚘 Welcome to the EVerest development environment!\"" >> ${HOME}/.bashrc && \
|
||||
echo "echo \"Since you are working with the EVerest monorepo, you have all you need to get started here. 🎉🎉🎉\"" >> ${HOME}/.bashrc && \
|
||||
echo "echo \"You can find the devrd tool in applications/devrd/devrd\"" >> ${HOME}/.bashrc
|
||||
@@ -0,0 +1,80 @@
|
||||
{
|
||||
"name": "EVerest - ${localWorkspaceFolderBasename}",
|
||||
|
||||
// Compose configuration
|
||||
"dockerComposeFile": [
|
||||
"../docker-compose.yml",
|
||||
"./docker-compose.devcontainer.yml"
|
||||
],
|
||||
"service": "devcontainer",
|
||||
"runServices": [ "mqtt-server", "ocpp-db", "steve", "mqtt-explorer" ],
|
||||
|
||||
// Workspace inside the container
|
||||
"workspaceFolder": "/workspace",
|
||||
|
||||
"initializeCommand": "./applications/devrd/devrd env",
|
||||
|
||||
"updateRemoteUserUID": false,
|
||||
|
||||
// Networking / forwarded ports
|
||||
"remoteUser": "docker",
|
||||
"forwardPorts": [
|
||||
"mqtt-explorer:4000",
|
||||
"steve:8180"
|
||||
],
|
||||
"portsAttributes": {
|
||||
"mqtt-explorer:4000": {
|
||||
"label": "MQTT Explorer - WebView"
|
||||
},
|
||||
"steve:8180": {
|
||||
"label": "Steve - WebTool"
|
||||
}
|
||||
},
|
||||
"otherPortsAttributes": {
|
||||
"onAutoForward": "notify",
|
||||
"protocol": "http",
|
||||
"requireLocalPort": false
|
||||
},
|
||||
|
||||
// VS Code customizations
|
||||
"customizations": {
|
||||
|
||||
// Be aware that anything set here will not apply to the devcontainer
|
||||
// when used without VS Code (e.g., plain Docker Compose).
|
||||
"vscode": {
|
||||
"settings": {
|
||||
"terminal.integrated.profiles.linux": {
|
||||
"bash": {
|
||||
"path": "/bin/bash",
|
||||
"icon": "terminal-bash",
|
||||
"args": ["-l"]
|
||||
}
|
||||
},
|
||||
"terminal.integrated.defaultProfile.linux": "bash",
|
||||
"python.pythonPath": "/usr/bin/python3",
|
||||
"python.defaultInterpreterPath": "/usr/bin/python3",
|
||||
"editor.rulers": [79, 120],
|
||||
|
||||
// RST
|
||||
"restructuredtext.preview.scrollEditorWithPreview": false,
|
||||
"restructuredtext.pythonRecommendation.disabled": true
|
||||
},
|
||||
|
||||
"extensions": [
|
||||
// language support CPP
|
||||
"ms-vscode.cpptools",
|
||||
|
||||
// language support cmake
|
||||
"twxs.cmake",
|
||||
"ms-vscode.cmake-tools",
|
||||
|
||||
// language support python
|
||||
"ms-python.python",
|
||||
|
||||
// language support reStructuredText
|
||||
"lextudio.restructuredtext",
|
||||
"trond-snekvik.simple-rst"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
networks:
|
||||
docker-proxy-network:
|
||||
internal: true
|
||||
devcontainer-ipv6:
|
||||
enable_ipv6: true
|
||||
driver_opts:
|
||||
com.docker.network.endpoint.sysctls: "net.ipv6.conf.eth0.disable_ipv6=0"
|
||||
|
||||
volumes:
|
||||
cpm-source-cache:
|
||||
name: everest-cpm-source-cache
|
||||
|
||||
services:
|
||||
|
||||
docker-proxy:
|
||||
image: tecnativa/docker-socket-proxy:latest
|
||||
volumes:
|
||||
- type: bind
|
||||
source: /var/run/docker.sock
|
||||
target: /var/run/docker.sock
|
||||
environment:
|
||||
- CONTAINERS=1
|
||||
- IMAGES=1
|
||||
- POST=1
|
||||
- NETWORKS=1
|
||||
- VOLUMES=1
|
||||
networks:
|
||||
- docker-proxy-network
|
||||
profiles:
|
||||
- all
|
||||
- ocpp
|
||||
- sil
|
||||
|
||||
devcontainer:
|
||||
depends_on:
|
||||
- docker-proxy
|
||||
env_file:
|
||||
- .env
|
||||
build:
|
||||
dockerfile: Dockerfile
|
||||
context: ./general-devcontainer
|
||||
additional_contexts:
|
||||
everest_dev_tool_src: ../applications/everest_dev_tool
|
||||
args:
|
||||
USER_UID: ${UID:-1000}
|
||||
USER_GID: ${GID:-1000}
|
||||
EVEREST_DEV_TOOL_DEFAULT_GIT_ORGANIZATION_ARG: ${EVEREST_DEV_TOOL_DEFAULT_GIT_ORGANIZATION:-EVerest}
|
||||
EVEREST_DEV_TOOL_DEFAULT_GIT_HOST_ARG: ${EVEREST_DEV_TOOL_DEFAULT_GIT_HOST:-github.com}
|
||||
EVEREST_DEV_TOOL_DEFAULT_GIT_SSH_USER_ARG: ${EVEREST_DEV_TOOL_DEFAULT_GIT_SSH_USER:-git}
|
||||
volumes:
|
||||
- type: bind
|
||||
source: ${HOST_WORKSPACE_FOLDER:-..}
|
||||
target: /workspace
|
||||
- type: volume
|
||||
source: cpm-source-cache
|
||||
target: /home/docker/.cache/cpm
|
||||
# Mount the host's SSH agent socket into the container
|
||||
- type: bind
|
||||
source: ${SSH_AUTH_SOCK}
|
||||
target: /ssh-agent
|
||||
command: sleep infinity
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
environment:
|
||||
MQTT_SERVER_ADDRESS: mqtt-server
|
||||
MQTT_SERVER_PORT: 1883
|
||||
DOCKER_HOST: tcp://docker-proxy:2375
|
||||
CPM_SOURCE_CACHE: /home/docker/.cache/cpm
|
||||
# Tell SSH to use the forwarded agent
|
||||
SSH_AUTH_SOCK: /ssh-agent
|
||||
networks:
|
||||
- docker-proxy-network
|
||||
- default
|
||||
- devcontainer-ipv6
|
||||
sysctls:
|
||||
- net.ipv6.conf.all.disable_ipv6=0
|
||||
- net.ipv6.conf.default.disable_ipv6=0
|
||||
- net.ipv6.conf.lo.disable_ipv6=0
|
||||
profiles:
|
||||
- all
|
||||
- ocpp
|
||||
- sil
|
||||
43
tools/EVerest-main/.eslintrc.json
Normal file
43
tools/EVerest-main/.eslintrc.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"commonjs": true,
|
||||
"es2021": true
|
||||
},
|
||||
"extends": [
|
||||
"airbnb-base"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 12
|
||||
},
|
||||
"rules": {
|
||||
"camelcase": "off",
|
||||
"eqeqeq": [
|
||||
"error",
|
||||
"smart"
|
||||
],
|
||||
"comma-dangle": [
|
||||
"warn",
|
||||
{
|
||||
"objects": "always-multiline",
|
||||
"arrays": "always-multiline",
|
||||
"functions": "never"
|
||||
}
|
||||
],
|
||||
"import/no-unresolved": [
|
||||
2,
|
||||
{
|
||||
"ignore": [
|
||||
"everestjs"
|
||||
]
|
||||
}
|
||||
],
|
||||
"max-len": [
|
||||
"warn",
|
||||
{
|
||||
"code": 120,
|
||||
"tabWidth": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
74
tools/EVerest-main/.github/CODEOWNERS
vendored
Normal file
74
tools/EVerest-main/.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
# default option unless later match takes precedence
|
||||
* @pietfried @hikinggrass @corneliusclaussen @SebaLukas @andistorm @mlitre @djchhp @james-ctc @cburandt @florinmihut
|
||||
|
||||
# .ci
|
||||
/.ci/ @pietfried @hikinggrass @corneliusclaussen @andistorm
|
||||
|
||||
# .github
|
||||
/.github/ @pietfried @corneliusclaussen
|
||||
/.github/workflows/ @pietfried @corneliusclaussen @andistorm
|
||||
/.github/workflows/on_label.yaml @andistorm @nzbr
|
||||
|
||||
# applications
|
||||
/applications/pionix_chargebridge @djchhp @corneliusclaussen
|
||||
|
||||
# cmake
|
||||
/cmake/ @hikinggrass @a-w50 @corneliusclaussen @andistorm
|
||||
|
||||
# config
|
||||
/config/ @hikinggrass @pietfried @corneliusclaussen @SebaLukas @mlitre
|
||||
|
||||
# lib
|
||||
/lib/3rd_party/nanopb/ @a-w50 @corneliusclaussen @hikinggrass
|
||||
/lib/everest/can_dpm1000/ @a-w50 @corneliusclaussen @hikinggrass
|
||||
/lib/everest/evse_security/ @pietfried @hikinggrass @james-ctc
|
||||
/lib/everest/gpio/ @corneliusclaussen @hikinggrass @hikinggrass
|
||||
/lib/everest/conversions/ @hikinggrass @pietfried @corneliusclaussen @mlitre
|
||||
/lib/everest/slac/ @a-w50 @corneliusclaussen @SebaLukas
|
||||
/lib/everest/tls/ @james-ctc @mlitre @corneliusclaussen @SebaLukas @pietfried
|
||||
/lib/everest/everest_api_types/ @hikinggrass @pietfried @corneliusclaussen @djchhp @cburandt @florinmihut
|
||||
/lib/everest/io/ @djchhp @corneliusclaussen @hikinggrass @james-ctc @pietfried
|
||||
|
||||
# modules
|
||||
/modules/API/ @hikinggrass @pietfried @corneliusclaussen @djchhp @SebaLukas @james-ctc @cburandt @florinmihut
|
||||
/modules/API/RpcApi/ @FaHaGit @barsnick
|
||||
/modules/EnergyManagement/Energymanager/ @corneliusclaussen @hikinggrass @pietfried
|
||||
/modules/EnergyManagement/EnergyNode/ @corneliusclaussen @hikinggrass @pietfried
|
||||
/modules/EV/EvManager/ @SebaLukas @pietfried @james-ctc @mlitre
|
||||
/modules/EV/PyEvJosev/ @SebaLukas @corneliusclaussen @pietfried @james-ctc @mlitre
|
||||
/modules/EVSE/Auth/ @pietfried @corneliusclaussen @hikinggrass @mlitre
|
||||
/modules/EVSE/Evse15118D20/ @SebaLukas @a-w50 @corneliusclaussen @pietfried @hikinggrass @james-ctc @mlitre
|
||||
/modules/EVSE/EvseManager/ @corneliusclaussen @SebaLukas @hikinggrass @pietfried @mlitre
|
||||
/modules/EVSE/EvseSecurity/ @pietfried @hikinggrass @james-ctc @mlitre @SebaLukas
|
||||
/modules/EVSE/EvseSlac/ @a-w50 @corneliusclaussen @SebaLukas @pietfried @hikinggrass
|
||||
/modules/EVSE/EvseV2G/ @corneliusclaussen @SebaLukas @james-ctc @pietfried @hikinggrass @james-ctc @mlitre @barsnick @FaHaGit
|
||||
/modules/EVSE/OCPP/ @hikinggrass @pietfried @mlitre
|
||||
/modules/HardwareDrivers/ @pietfried @hikinggrass @corneliusclaussen @florinmihut @cburandt @djchhp
|
||||
/modules/EVSE/OCPP201/ @hikinggrass @pietfried @mlitre
|
||||
/modules/Examples/CppExamples/error-framework/ @corneliusclaussen @hikinggrass @pietfried @andistorm
|
||||
/modules/Examples/RustExamples/ @SirVer @dorezyuk
|
||||
/modules/HardwareDrivers/EVSE/PhyVersoBSP/ @pietfried @hikinggrass @corneliusclaussen @dorezyuk @rckstrh
|
||||
/modules/HardwareDrivers/EVSE/YetiDriver/ @corneliusclaussen @hikinggrass
|
||||
/modules/Misc/ErrorHistory/ @corneliusclaussen @hikinggrass @pietfried @andistorm
|
||||
/modules/Misc/PacketSniffer/ @corneliusclaussen @SebaLukas @hikinggrass
|
||||
/modules/Misc/Setup/ @hikinggrass @corneliusclaussen @pietfried
|
||||
/modules/Simulation/ @SebaLukas @pietfried @hikinggrass
|
||||
/modules/Simulation/SlacSimulator/ @SebaLukas @pietfried @corneliusclaussen @james-ctc @mlitre
|
||||
/modules/Simulation/YetiSimulator/ @SebaLukas @pietfried @corneliusclaussen @james-ctc @mlitre
|
||||
**/Cargo.toml @SirVer @dorezyuk @pietfried @hikinggrass
|
||||
**/Cargo.lock @SirVer @dorezyuk @pietfried @hikinggrass
|
||||
|
||||
|
||||
# Rust & Bazel
|
||||
*.rs @SirVer @dorezyuk @pietfried @hikinggrass
|
||||
*.bazel @SirVer @dorezyuk @pietfried @hikinggrass
|
||||
*.bzl @SirVer @dorezyuk @pietfried @hikinggrass
|
||||
|
||||
# third-party/bazel
|
||||
/third-party/bazel/deps_versions.bzl @pietfried @hikinggrass @corneliusclaussen @SebaLukas @a-w50 @SirVer @dorezyuk
|
||||
|
||||
/dependencies.yaml @hikinggrass @pietfried @corneliusclaussen @SebaLukas @james-ctc @mlitre
|
||||
/module-dependencies.cmake @hikinggrass @pietfried @corneliusclaussen @SebaLukas @james-ctc @mlitre
|
||||
|
||||
# yocto
|
||||
/yocto/ @hikinggrass @corneliusclaussen @james-ctc @andistorm @barsnick
|
||||
77
tools/EVerest-main/.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
77
tools/EVerest-main/.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
name: Bug Report
|
||||
description: Thanks for taking the time to fill out this bug report!
|
||||
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: A clear and concise description of what the bug is. If applicable, add screenshots or log files to help explain your problem.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
description: What did you expect to happen?
|
||||
|
||||
- type: dropdown
|
||||
id: affected-domain
|
||||
attributes:
|
||||
label: EVerest Domain
|
||||
description: Which domain is affected by the issue? Mark multiple if applicable.
|
||||
options:
|
||||
- Authorization
|
||||
- Build System
|
||||
- Charge Control
|
||||
- CHAdeMO
|
||||
- DIN70121
|
||||
- Documentation
|
||||
- Energy Management
|
||||
- Framework
|
||||
- Hardware Drivers
|
||||
- ISO 15118-2
|
||||
- ISO 15118-20
|
||||
- OCPP 1.6
|
||||
- OCPP 2.0.1
|
||||
- OCPP 2.1
|
||||
- Security
|
||||
- Simulation
|
||||
- SLAC
|
||||
- Testing
|
||||
- Utilities
|
||||
- Other
|
||||
multiple: true
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: affected-component
|
||||
attributes:
|
||||
label: Affected Component
|
||||
description: |
|
||||
Please specify the component where the bug is located, if known.
|
||||
Examples: a module (e.g. `modules/EnergyManagement`), a library (e.g. `lib/ocpp`, `lib/iso15118`),
|
||||
or an application (e.g. `applications/everest_dev_tool`). Leave empty if unsure.
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: EVerest Version
|
||||
description: Git tag, release version, or commit hash (e.g. `2026.02.0`, `abc1234`).
|
||||
placeholder: e.g. 2026.02.0
|
||||
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: To Reproduce
|
||||
description: |
|
||||
Describe the steps and any additional information needed to reproduce the behavior:
|
||||
EVerest configuration files, compile options, and system information.
|
||||
|
||||
- type: textarea
|
||||
id: other
|
||||
attributes:
|
||||
label: Anything else?
|
||||
placeholder: Add any other context about the bug report here.
|
||||
70
tools/EVerest-main/.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
Normal file
70
tools/EVerest-main/.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
name: Feature Request
|
||||
description: Thanks for taking the time to fill out this feature request!
|
||||
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the problem
|
||||
description: What problem is your feature request targeting and why is it a problem? Please describe.
|
||||
placeholder: A clear and concise description of what the problem is.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: affected-domain
|
||||
attributes:
|
||||
label: EVerest Domain
|
||||
description: Which domain is this feature request for? Mark multiple if applicable.
|
||||
options:
|
||||
- Authorization
|
||||
- Build System
|
||||
- Charge Control
|
||||
- CHAdeMO
|
||||
- DIN70121
|
||||
- Documentation
|
||||
- Energy Management
|
||||
- Framework
|
||||
- Hardware Drivers
|
||||
- ISO 15118-2
|
||||
- ISO 15118-20
|
||||
- OCPP 1.6
|
||||
- OCPP 2.0.1
|
||||
- OCPP 2.1
|
||||
- Security
|
||||
- Simulation
|
||||
- SLAC
|
||||
- Testing
|
||||
- Utilities
|
||||
- Other
|
||||
multiple: true
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: affected-component
|
||||
attributes:
|
||||
label: Affected Component
|
||||
description: |
|
||||
Can you specify where the feature should be implemented, if known?
|
||||
Examples: a module (e.g. `modules/EnergyManagement`), a library (e.g. `lib/ocpp`, `lib/iso15118`),
|
||||
or an application (e.g. `applications/everest_dev_tool`). Leave empty if unsure.
|
||||
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Describe your solution
|
||||
description: Describe the solution you'd like.
|
||||
placeholder: A clear and concise description of what you want to happen.
|
||||
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Alternatives considered
|
||||
description: Have you considered alternative solutions or workarounds? If so, describe them here.
|
||||
|
||||
- type: textarea
|
||||
id: other
|
||||
attributes:
|
||||
label: Additional context
|
||||
placeholder: Add any other context about the feature request here.
|
||||
9
tools/EVerest-main/.github/pull_request_template.md
vendored
Normal file
9
tools/EVerest-main/.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
## Describe your changes
|
||||
|
||||
## Issue ticket number and link
|
||||
|
||||
## Checklist before requesting a review
|
||||
- [ ] I have performed a self-review of my code
|
||||
- [ ] I have made corresponding changes to the documentation
|
||||
- [ ] I read the [contribution documentation](https://everest.github.io/nightly/project/contributing.html) and made sure that my changes meet its requirements
|
||||
|
||||
92
tools/EVerest-main/.github/workflows/job_create-coverage-badge.yml
vendored
Normal file
92
tools/EVerest-main/.github/workflows/job_create-coverage-badge.yml
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
name: Create Coverage Badge
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
runner:
|
||||
description: 'Which runner to use'
|
||||
required: false
|
||||
default: 'ubuntu-24.04'
|
||||
type: string
|
||||
ref_everest_ci:
|
||||
description: 'The ref of the everest-ci repository to checkout'
|
||||
required: true
|
||||
type: string
|
||||
is_fork:
|
||||
description: 'Whether the current repository is a fork'
|
||||
required: true
|
||||
type: string
|
||||
artifact_deploy_target_repo:
|
||||
description: 'Repository to deploy artifacts to'
|
||||
required: true
|
||||
type: string
|
||||
coverage_report_artifact_name:
|
||||
description: 'The name of the coverage report artifact to download'
|
||||
required: true
|
||||
type: string
|
||||
coverage_xml_artifact_name:
|
||||
description: 'The name of the coverage xml artifact to download'
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
coverage_deploy_token:
|
||||
description: 'The token to use to deploy the coverage report'
|
||||
required: true
|
||||
jobs:
|
||||
create-coverage-badge:
|
||||
name: Create Coverage Badge
|
||||
runs-on: ${{ inputs.runner }}
|
||||
steps:
|
||||
- name: Checkout local github actions
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ${{ github.repository_owner }}/everest-ci
|
||||
ref: ${{ inputs.ref_everest_ci }}
|
||||
path: everest-ci
|
||||
- name: Download xml coverage report
|
||||
uses: actions/download-artifact@v5.0.0
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: ${{ inputs.coverage_xml_artifact_name }}
|
||||
path: coverage-xml
|
||||
- name: Parse coverage report
|
||||
id: parse_coverage_report
|
||||
shell: python3 {0}
|
||||
run: |
|
||||
import xml.etree.ElementTree
|
||||
import os
|
||||
tree = xml.etree.ElementTree.parse("${{ github.workspace }}/coverage-xml/gcovr-coverage-xml.xml")
|
||||
line_coverage = tree.getroot().get("line-rate")
|
||||
|
||||
with open(os.environ["GITHUB_OUTPUT"], "a") as f:
|
||||
f.write(f"line_coverage={line_coverage}\n")
|
||||
f.write(f"line_coverage_percentage={float(line_coverage) * 100}\n")
|
||||
- name: Generate coverage badge
|
||||
run: |
|
||||
pip install anybadge
|
||||
mkdir -p ${{ github.workspace }}/coverage-badge/
|
||||
anybadge -o --label Coverage --value ${{ steps.parse_coverage_report.outputs.line_coverage_percentage }} -s "%" --file ${{ github.workspace }}/coverage-badge/coverage-badge.svg 20=red 40=orange 60=yellow 80=yellowgreen 100=green
|
||||
- name: Deploy coverage badge
|
||||
uses: ./everest-ci/github-actions/deploy-ci-artifact
|
||||
if: ${{ inputs.is_fork == 'false' }}
|
||||
with:
|
||||
target_repo: ${{ inputs.artifact_deploy_target_repo }}
|
||||
github_token: ${{ secrets.coverage_deploy_token }}
|
||||
artifact_name: coverage-badge
|
||||
artifact_directory: ${{ github.workspace }}/coverage-badge/
|
||||
deploy_global_artifact: true
|
||||
- name: Download html coverage report
|
||||
uses: actions/download-artifact@v5.0.0
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: ${{ inputs.coverage_report_artifact_name }}
|
||||
path: coverage-report
|
||||
- name: Deploy html coverage report
|
||||
uses: ./everest-ci/github-actions/deploy-ci-artifact
|
||||
if: ${{ inputs.is_fork == 'false' }}
|
||||
with:
|
||||
target_repo: ${{ inputs.artifact_deploy_target_repo }}
|
||||
github_token: ${{ secrets.coverage_deploy_token }}
|
||||
artifact_name: ${{ inputs.coverage_report_artifact_name }}
|
||||
artifact_directory: ${{ github.workspace }}/coverage-report/
|
||||
deploy_global_artifact: true
|
||||
35
tools/EVerest-main/.github/workflows/job_dco-check.yaml
vendored
Normal file
35
tools/EVerest-main/.github/workflows/job_dco-check.yaml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
name: DCO Check
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
runner:
|
||||
description: 'Which runner to use'
|
||||
required: false
|
||||
default: 'ubuntu-24.04'
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
dco_check:
|
||||
name: DCO Check
|
||||
runs-on: ${{ inputs.runner }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
if: github.event_name == 'pull_request'
|
||||
- name: Set up Python 3.x
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Install dco-check
|
||||
if: github.event_name == 'pull_request'
|
||||
run: pip3 install -U dco-check==0.5.0
|
||||
- name: Check DCO pull_request
|
||||
if: github.event_name == 'pull_request'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
dco-check --default-branch main -v --exclude-pattern ".*@users\.noreply\.github\.com"
|
||||
- name: Check DCO merge_group
|
||||
if: github.event_name == 'merge_group'
|
||||
run: |
|
||||
echo "DCO check is skipped for merge_group events."
|
||||
131
tools/EVerest-main/.github/workflows/job_integrations-tests.yml
vendored
Normal file
131
tools/EVerest-main/.github/workflows/job_integrations-tests.yml
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
name: Integration Tests
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
runner:
|
||||
description: 'Which runner to use'
|
||||
required: false
|
||||
default: 'ubuntu-24.04'
|
||||
type: string
|
||||
build_kit_artifact_name:
|
||||
description: 'The name of the build-kit artifact to download'
|
||||
required: true
|
||||
type: string
|
||||
build_kit_image_tag:
|
||||
description: 'The tag of the build-kit image to use for building the project'
|
||||
required: true
|
||||
type: string
|
||||
build_kit_scripts_directory:
|
||||
description: 'Directory in the repository where the build kit scripts are located'
|
||||
required: false
|
||||
default: '.ci/build-kit/scripts'
|
||||
type: string
|
||||
docker_compose_file_path:
|
||||
description: 'The path to the docker-compose file, relative to the repository root'
|
||||
required: false
|
||||
default: '.ci/e2e/docker-compose.yaml'
|
||||
type: string
|
||||
test_service_name:
|
||||
description: 'The name of the service to run integration tests on'
|
||||
required: false
|
||||
default: 'e2e-test-server'
|
||||
type: string
|
||||
result_xml_path:
|
||||
description: 'The path to the result xml file, relative to the github workspace'
|
||||
required: false
|
||||
default: 'result.xml'
|
||||
type: string
|
||||
report_html_path:
|
||||
description: 'The path to the report html file, relative to the github workspace'
|
||||
required: false
|
||||
default: 'report.html'
|
||||
type: string
|
||||
dist_artifact_name:
|
||||
description: 'The name of the dist artifact to download'
|
||||
required: true
|
||||
type: string
|
||||
wheels_artifact_name:
|
||||
description: 'The name of the wheels artifact to download'
|
||||
required: true
|
||||
type: string
|
||||
outputs:
|
||||
integration_tests_artifact_name:
|
||||
description: 'The name of the integration tests artifact'
|
||||
value: ${{ jobs.integration-tests.outputs.integration_tests_artifact_name }}
|
||||
|
||||
jobs:
|
||||
integration-tests:
|
||||
name: Run Integration Tests
|
||||
runs-on: ${{ inputs.runner }}
|
||||
env:
|
||||
INTEGRATION_IMAGE_NAME: integration-image
|
||||
BUILD_KIT_IMAGE: ${{ inputs.build_kit_image_tag }}
|
||||
INTEGRATION_TESTS_ARTIFACT_NAME: integration-tests-artifacts
|
||||
outputs:
|
||||
integration_tests_artifact_name: ${{ env.INTEGRATION_TESTS_ARTIFACT_NAME }}
|
||||
steps:
|
||||
- name: Download dist dir
|
||||
uses: actions/download-artifact@v5.0.0
|
||||
with:
|
||||
name: ${{ inputs.dist_artifact_name }}
|
||||
- name: Extract dist.tar.gz
|
||||
run: |
|
||||
tar -xzf ${{ github.workspace }}/dist.tar.gz -C ${{ github.workspace }}
|
||||
- name: Download wheels
|
||||
uses: actions/download-artifact@v5.0.0
|
||||
with:
|
||||
name: ${{ inputs.wheels_artifact_name }}
|
||||
path: wheels
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
path: source
|
||||
- name: Setup run scripts
|
||||
run: |
|
||||
mkdir scripts
|
||||
rsync -a source/${{ inputs.build_kit_scripts_directory }}/ scripts
|
||||
- name: Download build-kit image
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: ${{ inputs.build_kit_artifact_name }}
|
||||
- name: Load build-kit image
|
||||
run: |
|
||||
docker load -i build-kit.tar
|
||||
docker image tag ${{ env.BUILD_KIT_IMAGE }} build-kit
|
||||
- name: Create integration-image
|
||||
run: |
|
||||
docker run \
|
||||
--volume "${{ github.workspace }}:/ext" \
|
||||
--name integration-container \
|
||||
build-kit run-script create_integration_image
|
||||
docker commit integration-container ${{ env.INTEGRATION_IMAGE_NAME }}
|
||||
- name: Run integration tests
|
||||
id: run_integration_tests
|
||||
run: |
|
||||
docker compose \
|
||||
-f source/${{ inputs.docker_compose_file_path }} \
|
||||
run \
|
||||
${{ inputs.test_service_name }} \
|
||||
tests/run-tests.sh integration \
|
||||
--everest-prefix /ext/dist \
|
||||
--junitxml /ext/${{ inputs.result_xml_path }} \
|
||||
--html /ext/${{ inputs.report_html_path }}
|
||||
- name: Upload result and report as artifact
|
||||
if: ${{ always() && (steps.run_integration_tests.outcome == 'success' || steps.run_integration_tests.outcome == 'failure') }}
|
||||
uses: actions/upload-artifact@v4.6.2
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: ${{ env.INTEGRATION_TESTS_ARTIFACT_NAME }}
|
||||
path: |
|
||||
${{ inputs.result_xml_path }}
|
||||
${{ inputs.report_html_path }}
|
||||
- name: Render result
|
||||
if: ${{ always() && (steps.run_integration_tests.outcome == 'success' || steps.run_integration_tests.outcome == 'failure') }}
|
||||
uses: pmeier/pytest-results-action@v0.7.2
|
||||
with:
|
||||
path: ${{ inputs.result_xml_path }}
|
||||
summary: True
|
||||
display-options: fEX
|
||||
fail-on-empty: True
|
||||
title: Test results
|
||||
36
tools/EVerest-main/.github/workflows/job_lint.yml
vendored
Normal file
36
tools/EVerest-main/.github/workflows/job_lint.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: Lint Repository
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
runner:
|
||||
description: 'Which runner to use'
|
||||
required: false
|
||||
default: 'ubuntu-24.04'
|
||||
type: string
|
||||
ref_everest_ci:
|
||||
description: 'The ref of the everest-ci repository to checkout'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint Repository
|
||||
runs-on: ${{ inputs.runner }}
|
||||
steps:
|
||||
- name: Checkout local github actions
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ${{ github.repository_owner }}/everest-ci
|
||||
ref: ${{ inputs.ref_everest_ci }}
|
||||
path: everest-ci
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: source
|
||||
- name: Run clang-format
|
||||
uses: ./everest-ci/github-actions/run-clang-format
|
||||
with:
|
||||
source-dir: source/
|
||||
extensions: hpp,cpp
|
||||
exclude: cache
|
||||
115
tools/EVerest-main/.github/workflows/job_ocpp-tests.yml
vendored
Normal file
115
tools/EVerest-main/.github/workflows/job_ocpp-tests.yml
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
name: OCPP Tests
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
runner:
|
||||
description: 'Which runner to use'
|
||||
required: false
|
||||
default: 'ubuntu-24.04'
|
||||
type: string
|
||||
dist_artifact_name:
|
||||
description: 'The name of the dist artifact to download'
|
||||
required: true
|
||||
type: string
|
||||
wheels_artifact_name:
|
||||
description: 'The name of the wheels artifact to download'
|
||||
required: true
|
||||
type: string
|
||||
build_kit_artifact_name:
|
||||
description: 'The name of the build-kit artifact to download'
|
||||
required: true
|
||||
type: string
|
||||
build_kit_image_tag:
|
||||
description: 'The tag of the build-kit image to use for building the project'
|
||||
required: true
|
||||
type: string
|
||||
build_kit_scripts_directory:
|
||||
description: 'Directory in the repository where the build kit scripts are located'
|
||||
required: false
|
||||
default: '.ci/build-kit/scripts'
|
||||
type: string
|
||||
outputs:
|
||||
ocpp_tests_artifact_name:
|
||||
description: 'The name of the OCPP tests artifact'
|
||||
value: ${{ jobs.ocpp-tests.outputs.ocpp_tests_artifact_name }}
|
||||
|
||||
|
||||
jobs:
|
||||
ocpp-tests:
|
||||
name: Run OCPP Tests
|
||||
runs-on: ${{ inputs.runner }}
|
||||
env:
|
||||
OCPP_TESTS_ARTIFACT_NAME: ocpp-tests-artifacts
|
||||
outputs:
|
||||
ocpp_tests_artifact_name: ${{ env.OCPP_TESTS_ARTIFACT_NAME }}
|
||||
steps:
|
||||
- name: Download dist dir
|
||||
uses: actions/download-artifact@v4.1.8
|
||||
with:
|
||||
name: ${{ inputs.dist_artifact_name }}
|
||||
- name: Extract dist.tar.gz
|
||||
run: |
|
||||
tar -xzf ${{ github.workspace }}/dist.tar.gz -C ${{ github.workspace }}
|
||||
- name: Download wheels
|
||||
uses: actions/download-artifact@v4.1.8
|
||||
with:
|
||||
name: ${{ inputs.wheels_artifact_name }}
|
||||
path: wheels
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
path: source
|
||||
- name: Setup run scripts
|
||||
run: |
|
||||
mkdir scripts
|
||||
rsync -a source/${{ inputs.build_kit_scripts_directory }}/ scripts
|
||||
- name: Download build-kit image
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: ${{ inputs.build_kit_artifact_name }}
|
||||
- name: Load build-kit image
|
||||
run: |
|
||||
docker load -i build-kit.tar
|
||||
docker image tag ${{ inputs.build_kit_image_tag }} build-kit
|
||||
- name: Create integration-image
|
||||
run: |
|
||||
docker run \
|
||||
--volume "${{ github.workspace }}:/ext" \
|
||||
--name integration-container \
|
||||
build-kit run-script create_ocpp_tests_image
|
||||
docker commit integration-container integration-image
|
||||
- name: Run OCPP tests
|
||||
id: run_ocpp_tests
|
||||
continue-on-error: true
|
||||
run: |
|
||||
docker compose \
|
||||
-f source/.ci/e2e/docker-compose.yaml \
|
||||
run \
|
||||
e2e-test-server \
|
||||
tests/run-tests.sh ocpp \
|
||||
--everest-prefix /ext/dist \
|
||||
--junitxml /ext/ocpp-tests-result.xml \
|
||||
--html /ext/ocpp-tests-report.html
|
||||
- name: Upload result and report as artifact
|
||||
continue-on-error: true
|
||||
if: ${{ steps.run_ocpp_tests.outcome == 'success' || steps.run_ocpp_tests.outcome == 'failure' }}
|
||||
uses: actions/upload-artifact@v4.4.3
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: ${{ env.OCPP_TESTS_ARTIFACT_NAME }}
|
||||
path: |
|
||||
ocpp-tests-result.xml
|
||||
ocpp-tests-report.html
|
||||
- name: Render OCPP tests result
|
||||
if: ${{ steps.run_ocpp_tests.outcome == 'success' || steps.run_ocpp_tests.outcome == 'failure' }}
|
||||
uses: pmeier/pytest-results-action@v0.7.1
|
||||
with:
|
||||
path: ocpp-tests-result.xml
|
||||
summary: True
|
||||
display-options: fEX
|
||||
fail-on-empty: True
|
||||
title: Test results
|
||||
- name: Check if OCPP tests failed
|
||||
if: ${{ steps.run_ocpp_tests.outcome == 'failure' }}
|
||||
run: exit 1
|
||||
81
tools/EVerest-main/.github/workflows/job_setup-env.yml
vendored
Normal file
81
tools/EVerest-main/.github/workflows/job_setup-env.yml
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
name: Setup Environment
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
runner:
|
||||
description: 'Which runner to use'
|
||||
required: false
|
||||
default: 'ubuntu-24.04'
|
||||
type: string
|
||||
ref_everest_ci:
|
||||
description: 'The reference of the everest-ci repository to checkout'
|
||||
required: true
|
||||
type: string
|
||||
outputs:
|
||||
ref_everest_ci:
|
||||
description: 'The reference of the everest-ci repository to checkout'
|
||||
value: ${{ inputs.ref_everest_ci }}
|
||||
closest_tag_everest_ci:
|
||||
description: 'The closest tag of the everest-ci repository to use'
|
||||
value: ${{ jobs.setup-env.outputs.closest_tag_everest_ci }}
|
||||
is_fork:
|
||||
description: 'Whether the current repository is a fork'
|
||||
value: ${{ jobs.setup-env.outputs.is_fork }}
|
||||
|
||||
|
||||
jobs:
|
||||
setup-env:
|
||||
name: Setup Environment
|
||||
runs-on: ${{ inputs.runner }}
|
||||
outputs:
|
||||
is_fork: ${{ steps.is_fork.outputs.is_fork }}
|
||||
closest_tag_everest_ci: ${{ steps.set_tag_everest_ci.outputs.closest_tag }}
|
||||
steps:
|
||||
- name: Determine closest tag of everest-ci
|
||||
id: set_tag_everest_ci
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
TARGET_SHA="${{ steps.set_sha_everest_ci.outputs.sha }}"
|
||||
OWNER="everest"
|
||||
REPO="everest-ci"
|
||||
|
||||
COMMITS=$(gh api repos/$OWNER/$REPO/commits?sha=$TARGET_SHA\&per_page=100 --jq '.[].sha')
|
||||
for COMMIT in $COMMITS; do
|
||||
TAG=$(gh api repos/$OWNER/$REPO/tags --jq '.[] | select(.commit.sha == "'$COMMIT'") | .name')
|
||||
if [ -n "$TAG" ]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "$TAG" ]; then
|
||||
echo "No tag found for commit $TARGET_SHA (only last 100 commits were checked)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# if inputs.build_kit_base_image_tag is != "", use it as the tag
|
||||
if [ -n "${{ inputs.build_kit_base_image_tag }}" ]; then
|
||||
echo "Using inputs.build_kit_base_image_tag as tag"
|
||||
TAG="${{ inputs.build_kit_base_image_tag }}"
|
||||
fi
|
||||
|
||||
echo "closest_tag=$TAG" >> $GITHUB_OUTPUT
|
||||
- name: Determine whether the PR comes from fork
|
||||
id: is_fork
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" == "pull_request" ]; then
|
||||
if [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]; then
|
||||
is_fork=true
|
||||
else
|
||||
is_fork=false
|
||||
fi
|
||||
else
|
||||
is_fork=false
|
||||
fi
|
||||
echo "is_fork=${is_fork}" >> $GITHUB_OUTPUT
|
||||
if [ "${is_fork}" == "true" ]; then
|
||||
echo "This is a forked PR"
|
||||
else
|
||||
echo "This is not a forked PR"
|
||||
fi
|
||||
51
tools/EVerest-main/.github/workflows/on_label.yaml
vendored
Normal file
51
tools/EVerest-main/.github/workflows/on_label.yaml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
# Inspired by:
|
||||
# Nixpkgs: https://github.com/NixOS/nixpkgs/blob/a698ac1214cd924d4394ca9cd2691618765aa03c/.github/workflows/backport.yml
|
||||
# NixOS-WSL: https://github.com/nix-community/NixOS-WSL/blob/be894604b2aa2184c0b3d3b44995acd0da14dc0c/.github/workflows/on_label.yml
|
||||
|
||||
name: "Backport"
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- closed
|
||||
- labeled
|
||||
|
||||
jobs:
|
||||
backport:
|
||||
if: github.event.pull_request.labels && contains(join(github.event.pull_request.labels.*.name, ', '), 'backport ')
|
||||
name: Backport PR 🔙
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
outputs:
|
||||
created_pull_numbers: ${{ steps.backport.outputs.created_pull_numbers }}
|
||||
steps:
|
||||
- name: Check actor permissions
|
||||
id: check-permissions
|
||||
uses: prince-chrismc/check-actor-permissions-action@v3.0.2
|
||||
with:
|
||||
permission: write
|
||||
|
||||
- name: Generate App Token
|
||||
id: app-token
|
||||
uses: actions/create-github-app-token@v1
|
||||
with:
|
||||
app-id: ${{ secrets.BACKPORT_APP_ID }}
|
||||
private-key: ${{ secrets.BACKPORT_APP_PRIVATE_KEY }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Create backport PR
|
||||
id: backport
|
||||
uses: korthout/backport-action@v4.5.1
|
||||
with:
|
||||
github_token: ${{ steps.app-token.outputs.token }}
|
||||
merge_commits: "skip"
|
||||
add_author_as_assignee: true
|
||||
copy_requested_reviewers: true
|
||||
experimental: >-
|
||||
{
|
||||
"conflict_resolution": "draft_commit_conflicts"
|
||||
}
|
||||
74
tools/EVerest-main/.github/workflows/on_main.yaml
vendored
Normal file
74
tools/EVerest-main/.github/workflows/on_main.yaml
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
name: Build, Lint and Test
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
|
||||
|
||||
setup-env:
|
||||
name: Setup Environment
|
||||
uses: ./.github/workflows/job_setup-env.yml
|
||||
with:
|
||||
runner: ${{ inputs.runner || 'ubuntu-24.04' }}
|
||||
ref_everest_ci: v1.5.5
|
||||
|
||||
|
||||
build-build-kit:
|
||||
name: Build the build-kit
|
||||
uses: ./.github/workflows/job_build-build-kit.yml
|
||||
needs:
|
||||
- setup-env
|
||||
with:
|
||||
runner: ${{ inputs.runner || 'ubuntu-24.04' }}
|
||||
base_image_tag_everest_ci: ${{ needs.setup-env.outputs.closest_tag_everest_ci }}
|
||||
|
||||
|
||||
build-cmake-gcc:
|
||||
name: Build with CMake and GCC
|
||||
uses: ./.github/workflows/job_build-cmake-gcc.yml
|
||||
needs:
|
||||
- setup-env
|
||||
- build-build-kit
|
||||
secrets:
|
||||
coverage_deploy_token: "abcd"
|
||||
with:
|
||||
runner: ${{ inputs.runner || 'ubuntu-24.04' }}
|
||||
ref_everest_ci: ${{ needs.setup-env.outputs.ref_everest_ci }}
|
||||
is_fork: ${{ needs.setup-env.outputs.is_fork }}
|
||||
build-kit-artifact-name: ${{ needs.build-build-kit.outputs.build_kit_artifact_name }}
|
||||
build_kit_image_tag: ${{ needs.build-build-kit.outputs.build_kit_image_tag }}
|
||||
artifact_deploy_target_repo: ${{ github.repository_owner }}/everest.github.io
|
||||
|
||||
|
||||
# create-coverage-badge:
|
||||
# uses: ./.github/workflows/job_create-coverage-badge.yml
|
||||
# needs:
|
||||
# - setup-env
|
||||
# - build-cmake-gcc
|
||||
# secrets:
|
||||
# coverage_deploy_token: ${{ secrets.coverage_deploy_token }}
|
||||
# with:
|
||||
# runner: ${{ inputs.runner || 'ubuntu-24.04' }}
|
||||
# ref_everest_ci: ${{ needs.setup-env.outputs.ref_everest_ci }}
|
||||
# is_fork: ${{ needs.setup-env.outputs.is_fork }}
|
||||
# artifact_deploy_target_repo: ${{ github.repository_owner }}/everest.github.io
|
||||
# coverage_report_artifact_name: ${{ needs.build-cmake-gcc.outputs.coverage_report_artifact_name }}
|
||||
# coverage_xml_artifact_name: ${{ needs.build-cmake-gcc.outputs.coverage_xml_artifact_name }}
|
||||
|
||||
|
||||
build-docs:
|
||||
name: Build and Deploy Documentation
|
||||
needs:
|
||||
- setup-env
|
||||
- build-build-kit
|
||||
uses: ./.github/workflows/job_build-docs.yaml
|
||||
secrets:
|
||||
SA_GITHUB_SSH_KEY: ${{ secrets.SA_GITHUB_SSH_KEY }}
|
||||
with:
|
||||
runner: ${{ inputs.runner || 'ubuntu-24.04' }}
|
||||
is_fork: ${{ needs.setup-env.outputs.is_fork == 'true' }}
|
||||
build_kit_artifact_name: ${{ needs.build-build-kit.outputs.build_kit_artifact_name }}
|
||||
build_kit_image_tag: ${{ needs.build-build-kit.outputs.build_kit_image_tag }}
|
||||
deploy_docs: true
|
||||
139
tools/EVerest-main/.github/workflows/on_pr.yaml
vendored
Normal file
139
tools/EVerest-main/.github/workflows/on_pr.yaml
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
name: Build, Lint and Test
|
||||
on:
|
||||
pull_request: {}
|
||||
merge_group: {}
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
runner:
|
||||
description: Which runner to use
|
||||
type: choice
|
||||
default: 'ubuntu-24.04'
|
||||
required: true
|
||||
options:
|
||||
- 'ubuntu-24.04'
|
||||
- 'large-ubuntu-24.04-xxl'
|
||||
schedule:
|
||||
- cron: '37 13,1 * * *'
|
||||
|
||||
jobs:
|
||||
|
||||
|
||||
setup-env:
|
||||
name: Setup Environment
|
||||
uses: ./.github/workflows/job_setup-env.yml
|
||||
with:
|
||||
runner: ${{ inputs.runner || 'ubuntu-24.04' }}
|
||||
ref_everest_ci: v1.5.5
|
||||
|
||||
|
||||
build-build-kit:
|
||||
name: Build the build-kit
|
||||
uses: ./.github/workflows/job_build-build-kit.yml
|
||||
needs:
|
||||
- setup-env
|
||||
with:
|
||||
runner: ${{ inputs.runner || 'ubuntu-24.04' }}
|
||||
base_image_tag_everest_ci: ${{ needs.setup-env.outputs.closest_tag_everest_ci }}
|
||||
|
||||
|
||||
build-cmake-gcc:
|
||||
name: Build with CMake and GCC
|
||||
uses: ./.github/workflows/job_build-cmake-gcc.yml
|
||||
needs:
|
||||
- setup-env
|
||||
- build-build-kit
|
||||
secrets:
|
||||
coverage_deploy_token: ""
|
||||
with:
|
||||
runner: ${{ inputs.runner || 'ubuntu-24.04' }}
|
||||
ref_everest_ci: ${{ needs.setup-env.outputs.ref_everest_ci }}
|
||||
is_fork: ${{ needs.setup-env.outputs.is_fork }}
|
||||
build-kit-artifact-name: ${{ needs.build-build-kit.outputs.build_kit_artifact_name }}
|
||||
build_kit_image_tag: ${{ needs.build-build-kit.outputs.build_kit_image_tag }}
|
||||
artifact_deploy_target_repo: ${{ github.repository_owner }}/everest.github.io
|
||||
|
||||
|
||||
integration-tests:
|
||||
name: Run Integration Tests
|
||||
uses: ./.github/workflows/job_integrations-tests.yml
|
||||
needs:
|
||||
- setup-env
|
||||
- build-cmake-gcc
|
||||
- build-build-kit
|
||||
with:
|
||||
runner: ${{ inputs.runner || 'ubuntu-24.04' }}
|
||||
build_kit_artifact_name: ${{ needs.build-build-kit.outputs.build_kit_artifact_name }}
|
||||
build_kit_image_tag: ${{ needs.build-build-kit.outputs.build_kit_image_tag }}
|
||||
dist_artifact_name: ${{ needs.build-cmake-gcc.outputs.dist_artifact_name }}
|
||||
wheels_artifact_name: ${{ needs.build-cmake-gcc.outputs.wheels_artifact_name }}
|
||||
|
||||
|
||||
ocpp-tests:
|
||||
name: Run OCPP Tests
|
||||
uses: ./.github/workflows/job_ocpp-tests.yml
|
||||
needs:
|
||||
- setup-env
|
||||
- build-cmake-gcc
|
||||
- build-build-kit
|
||||
with:
|
||||
runner: ${{ inputs.runner || 'ubuntu-24.04' }}
|
||||
build_kit_artifact_name: ${{ needs.build-build-kit.outputs.build_kit_artifact_name }}
|
||||
build_kit_image_tag: ${{ needs.build-build-kit.outputs.build_kit_image_tag }}
|
||||
dist_artifact_name: ${{ needs.build-cmake-gcc.outputs.dist_artifact_name }}
|
||||
wheels_artifact_name: ${{ needs.build-cmake-gcc.outputs.wheels_artifact_name }}
|
||||
|
||||
|
||||
lint:
|
||||
name: Lint Repository
|
||||
uses: ./.github/workflows/job_lint.yml
|
||||
needs:
|
||||
- setup-env
|
||||
with:
|
||||
runner: ${{ inputs.runner || 'ubuntu-24.04' }}
|
||||
ref_everest_ci: ${{ needs.setup-env.outputs.ref_everest_ci }}
|
||||
|
||||
|
||||
build-docs:
|
||||
name: Call Build Documentation
|
||||
needs:
|
||||
- setup-env
|
||||
- build-build-kit
|
||||
uses: ./.github/workflows/job_build-docs.yaml
|
||||
secrets:
|
||||
SA_GITHUB_SSH_KEY: ${{ secrets.SA_GITHUB_SSH_KEY }}
|
||||
with:
|
||||
runner: ${{ inputs.runner || 'ubuntu-24.04' }}
|
||||
is_fork: ${{ needs.setup-env.outputs.is_fork == 'true' }}
|
||||
build_kit_artifact_name: ${{ needs.build-build-kit.outputs.build_kit_artifact_name }}
|
||||
build_kit_image_tag: ${{ needs.build-build-kit.outputs.build_kit_image_tag }}
|
||||
deploy_docs: false
|
||||
|
||||
|
||||
dco-check:
|
||||
name: DCO Check
|
||||
uses: ./.github/workflows/job_dco-check.yaml
|
||||
with:
|
||||
runner: ${{ inputs.runner || 'ubuntu-24.04' }}
|
||||
|
||||
|
||||
bazel-build-and-test:
|
||||
name: Bazel Build And Test
|
||||
uses: ./.github/workflows/job_bazel-build-test.yaml
|
||||
with:
|
||||
runner: ${{ inputs.runner || 'ubuntu-24.04' }}
|
||||
|
||||
|
||||
bazel-cross-build:
|
||||
name: Bazel Cross-Build (${{ matrix.platform }})
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform:
|
||||
- aarch64-linux-gnu
|
||||
- aarch64-linux-musl
|
||||
- armv7-linux-gnueabihf
|
||||
- armv7-linux-musleabihf
|
||||
uses: ./.github/workflows/job_bazel-cross-build.yaml
|
||||
with:
|
||||
runner: ${{ inputs.runner || 'ubuntu-24.04' }}
|
||||
platform: ${{ matrix.platform }}
|
||||
17
tools/EVerest-main/.gitignore
vendored
Normal file
17
tools/EVerest-main/.gitignore
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
*build*
|
||||
!lib/everest/*/cmake/*-build.cmake
|
||||
*dist
|
||||
.cache/
|
||||
workspace.yaml
|
||||
.vscode/
|
||||
/bazel-*
|
||||
/modules/target
|
||||
CMakeLists.txt.user
|
||||
.idea/
|
||||
MODULE.bazel.lock
|
||||
__pycache__/
|
||||
*.patch
|
||||
*.diff
|
||||
*.orig
|
||||
*.rej
|
||||
docs/source/conf.py
|
||||
3
tools/EVerest-main/.prettierrc.yaml
Normal file
3
tools/EVerest-main/.prettierrc.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
singleQuote: true
|
||||
tabWidth: 2
|
||||
quoteProps: consistent
|
||||
22
tools/EVerest-main/.prospector.yaml
Normal file
22
tools/EVerest-main/.prospector.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
pep257:
|
||||
disable:
|
||||
- D203
|
||||
- D212
|
||||
- D213
|
||||
- D214
|
||||
- D215
|
||||
- D404
|
||||
- D405
|
||||
- D406
|
||||
- D407
|
||||
- D408
|
||||
- D409
|
||||
- D410
|
||||
- D411
|
||||
- D413
|
||||
- D415
|
||||
- D416
|
||||
- D417
|
||||
pylint:
|
||||
disable:
|
||||
- logging-fstring-interpolation
|
||||
8
tools/EVerest-main/BUILD.bazel
Normal file
8
tools/EVerest-main/BUILD.bazel
Normal file
@@ -0,0 +1,8 @@
|
||||
load("@bazel_skylib//rules:write_file.bzl", "write_file")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files([
|
||||
"dependencies.yaml",
|
||||
"MODULE.bazel",
|
||||
])
|
||||
255
tools/EVerest-main/CMakeLists.txt
Normal file
255
tools/EVerest-main/CMakeLists.txt
Normal file
@@ -0,0 +1,255 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(everest-core
|
||||
VERSION 2026.02.0
|
||||
DESCRIPTION "The open operating system for e-mobility charging stations"
|
||||
LANGUAGES CXX C
|
||||
)
|
||||
|
||||
find_package(everest-cmake 0.5
|
||||
COMPONENTS bundling
|
||||
PATHS ../everest-cmake
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
find_package(everest-cmake 0.5
|
||||
COMPONENTS bundling
|
||||
)
|
||||
|
||||
if (NOT everest-cmake_FOUND)
|
||||
message(STATUS "Retrieving everest-cmake using FetchContent")
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
everest-cmake
|
||||
GIT_REPOSITORY https://github.com/EVerest/everest-cmake.git
|
||||
GIT_TAG main
|
||||
)
|
||||
FetchContent_MakeAvailable(everest-cmake)
|
||||
set(everest-cmake_DIR "${everest-cmake_SOURCE_DIR}")
|
||||
set(everest-cmake_FIND_COMPONENTS "bundling")
|
||||
include("${everest-cmake_SOURCE_DIR}/everest-cmake-config.cmake")
|
||||
endif()
|
||||
|
||||
# make own cmake modules available
|
||||
list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
# test whether linking with libatomic is required on some platforms
|
||||
include(CheckAtomic)
|
||||
if(HAVE_CXX_ATOMICS_WITH_LIB OR HAVE_CXX_ATOMICS64_WITH_LIB)
|
||||
set(ATOMIC_LIBS "atomic")
|
||||
else()
|
||||
set(ATOMIC_LIBS "")
|
||||
endif()
|
||||
|
||||
# test whether we are building on a musl based system.
|
||||
# On these we need to increase the stack size as it is very low by default
|
||||
option(USING_MUSL "Using musl" OFF)
|
||||
find_program(LDD_EXECUTABLE ldd)
|
||||
find_program(LS_EXECUTABLE ls)
|
||||
if(LDD_EXECUTABLE AND LS_EXECUTABLE)
|
||||
# we use ls as a testing executable as it is very likely to exist on any system. ldd prints the dynamic linked libraries
|
||||
# of the given executable, if musl is used it will print it as a linked object
|
||||
execute_process(COMMAND ${LDD_EXECUTABLE} ${LS_EXECUTABLE} OUTPUT_VARIABLE LDD_LS_OUTPUT ERROR_QUIET)
|
||||
if(LDD_LS_OUTPUT MATCHES "musl")
|
||||
message(STATUS "MUSL detected, increasing stack size to 8MiB")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,stack-size=8388608")
|
||||
set(USING_MUSL ON)
|
||||
endif()
|
||||
else()
|
||||
if(NOT LDD_EXECUTABLE)
|
||||
message(WARNING "ldd not found, skipping musl detection")
|
||||
endif()
|
||||
if(NOT LS_EXECUTABLE)
|
||||
message(WARNING "ls not found, skipping musl detection")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(CREATE_SYMLINKS "Create symlinks to javascript modules and auxillary files - for development purposes" OFF)
|
||||
option(CMAKE_RUN_CLANG_TIDY "Run clang-tidy" OFF)
|
||||
option(ISO15118_2_GENERATE_AND_INSTALL_CERTIFICATES "Automatically generate and install certificates for development purposes" ON)
|
||||
option(EVEREST_ENABLE_RUN_SCRIPT_GENERATION "Enables the generation of run scripts (convenience scripts for starting available configurations)" ON)
|
||||
option(EVEREST_BUILD_DOCS "Build EVerest documentation" OFF)
|
||||
option(EVEREST_SKIP_BUILD_API_DOC "Skip building the async API html doc for the EVerest API" OFF)
|
||||
option(${PROJECT_NAME}_BUILD_TESTING "Build unit tests, used if included as dependency" OFF)
|
||||
option(BUILD_TESTING "Build unit tests, used if standalone project" OFF)
|
||||
option(EVEREST_ENABLE_COMPILE_WARNINGS "Enable compile warnings set in the EVEREST_COMPILE_OPTIONS flag" OFF)
|
||||
option(EVEREST_ENABLE_GLOBAL_COMPILE_WARNINGS "Enable compile warnings set in the EVEREST_COMPILE_OPTIONS flag globally" OFF)
|
||||
option(EVEREST_ENABLE_DEBUG_BUILD "Enable debug build" OFF)
|
||||
option(EVEREST_BUILD_APPLICATIONS "Build applications like drivers for the EVerest stable API" ON)
|
||||
option(EVEREST_LIBS_ONLY "Only build libraries, skip modules/applications/config" OFF)
|
||||
option(EVEREST_IO_WITH_MQTT "Build MQTT (mosquitto) support in everest::io" ON)
|
||||
set(EVEREST_INCLUDE_LIBS "" CACHE STRING "Semicolon-separated allowlist of libraries to build (empty = all)")
|
||||
set(EVEREST_EXCLUDE_LIBS "" CACHE STRING "Semicolon-separated blocklist of libraries to skip")
|
||||
# list of compile options that are passed to modules if EVEREST_ENABLE_COMPILE_WARNINGS=ON
|
||||
# generated code has functions often not used
|
||||
set(EVEREST_COMPILE_OPTIONS "-Wall;-Wno-unused-function" CACHE STRING "A list of compile options used for building modules")
|
||||
if(EVEREST_ENABLE_GLOBAL_COMPILE_WARNINGS)
|
||||
add_compile_options(${EVEREST_COMPILE_OPTIONS})
|
||||
endif()
|
||||
if((${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME} OR ${PROJECT_NAME}_BUILD_TESTING) AND BUILD_TESTING)
|
||||
set(EVEREST_CORE_BUILD_TESTING ON)
|
||||
set(everest-framework_BUILD_TESTING ON)
|
||||
set(ISO15118_BUILD_TESTING ON)
|
||||
set(ocpp_BUILD_TESTING ON)
|
||||
set(LIBEVSE_SECURITY_BUILD_TESTING ON)
|
||||
set(everest-evse_security_BUILD_TESTING ON)
|
||||
set(everest-sqlite_BUILD_TESTING ON)
|
||||
set(everest-timer_BUILD_TESTING ON)
|
||||
set(everest-log_BUILD_TESTING ON)
|
||||
set(IEEE2030_BUILD_TESTING ON)
|
||||
endif()
|
||||
# This is a flag for building development tests, but not necessarily to run them, for expample in case
|
||||
# tests requires hardware.
|
||||
option(BUILD_DEV_TESTS "Build dev tests" OFF)
|
||||
ev_setup_cmake_variables_python_wheel()
|
||||
option(${PROJECT_NAME}_INSTALL_EV_CLI_IN_PYTHON_VENV "Install ev-cli in python venv instead of using system" ON)
|
||||
set(${PROJECT_NAME}_PYTHON_VENV_PATH "${CMAKE_BINARY_DIR}/venv" CACHE PATH "Path to python venv")
|
||||
|
||||
ev_setup_python_executable(
|
||||
USE_PYTHON_VENV ${${PROJECT_NAME}_USE_PYTHON_VENV}
|
||||
PYTHON_VENV_PATH ${${PROJECT_NAME}_PYTHON_VENV_PATH}
|
||||
)
|
||||
|
||||
# Already include CTest here to allow it to find tests defined in subdirectories like lib and modules
|
||||
if(EVEREST_CORE_BUILD_TESTING)
|
||||
include(CTest)
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
if(EVEREST_ENABLE_DEBUG_BUILD)
|
||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type" FORCE)
|
||||
else()
|
||||
set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Build type" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(ev-define-dependency)
|
||||
include(ev-lib-dependencies)
|
||||
|
||||
if(NOT EVEREST_LIBS_ONLY)
|
||||
include("module-dependencies.cmake")
|
||||
endif()
|
||||
|
||||
# this policy allows us to continue using the removed FindBoost module for now
|
||||
if(POLICY CMP0167)
|
||||
cmake_policy(SET CMP0167 OLD)
|
||||
endif()
|
||||
|
||||
find_package(Boost
|
||||
COMPONENTS
|
||||
filesystem
|
||||
program_options
|
||||
thread
|
||||
REQUIRED
|
||||
)
|
||||
|
||||
include(compatibility/boost)
|
||||
|
||||
set(everest-framework_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/everest/framework)
|
||||
set(everest-framework_BINARY_DIR ${CMAKE_BINARY_DIR}/lib/everest/framework)
|
||||
set(EVEREST_SCHEMA_DIR ${everest-framework_SOURCE_DIR}/schemas)
|
||||
set(everest-sqlite_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/everest/sqlite)
|
||||
if(NOT DEFINED EVEREST_ENABLE_PY_SUPPORT)
|
||||
set(EVEREST_ENABLE_PY_SUPPORT ON CACHE BOOL "Enable EVerest Python support" FORCE)
|
||||
endif()
|
||||
|
||||
if(NOT DISABLE_EDM)
|
||||
# FIXME (aw): this implicit definition for child projects is hacky
|
||||
set(THIRD_PARTY_APP_DST "${CMAKE_INSTALL_LIBEXECDIR}/everest/3rd_party")
|
||||
|
||||
# edm
|
||||
add_subdirectory(applications/dependency_manager)
|
||||
|
||||
evc_setup_edm()
|
||||
|
||||
if(EVEREST_DEPENDENCY_ENABLED_SDBUS_CPP AND NOT TARGET SDBusCpp::sdbus-c++)
|
||||
add_library(SDBusCpp::sdbus-c++ ALIAS sdbus-c++)
|
||||
endif()
|
||||
|
||||
# ev-cli and everest-testing
|
||||
if(NOT EVEREST_LIBS_ONLY)
|
||||
add_subdirectory(applications/utils)
|
||||
endif()
|
||||
else()
|
||||
if(NOT EVEREST_LIBS_ONLY)
|
||||
find_package(PalSigslot REQUIRED)
|
||||
find_package(libnfc-nci REQUIRED)
|
||||
find_package(pugixml REQUIRED)
|
||||
find_package(CURL 7.84.0 REQUIRED)
|
||||
find_package(ftxui 6 QUIET) # optional, if not available BringUp module will not be built
|
||||
find_package(sdbus-c++ REQUIRED)
|
||||
endif()
|
||||
|
||||
find_package(ryml REQUIRED)
|
||||
find_package(nlohmann_json REQUIRED)
|
||||
find_package(fmt REQUIRED)
|
||||
find_package(date REQUIRED)
|
||||
find_package(OpenSSL 3 REQUIRED)
|
||||
endif()
|
||||
|
||||
if(EVEREST_BUILD_DOCS)
|
||||
add_subdirectory(docs)
|
||||
endif()
|
||||
|
||||
if(EVEREST_LIBS_ONLY)
|
||||
# ev-targets provides ev_register_library_target() used by some libraries
|
||||
include(ev-targets)
|
||||
else()
|
||||
include(ev-project-bootstrap)
|
||||
|
||||
ev_add_project()
|
||||
|
||||
# create MF_ROOT_CA if not available
|
||||
if (ISO15118_2_GENERATE_AND_INSTALL_CERTIFICATES)
|
||||
file(TOUCH config/certs/ca/mf/MF_ROOT_CA.pem)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(lib)
|
||||
|
||||
if(NOT EVEREST_LIBS_ONLY)
|
||||
# config
|
||||
# FIXME (aw): this should be optional
|
||||
add_subdirectory(config)
|
||||
|
||||
if(EVEREST_BUILD_APPLICATIONS)
|
||||
add_subdirectory(applications)
|
||||
endif()
|
||||
|
||||
ev_install_project()
|
||||
endif()
|
||||
|
||||
# configure clang-tidy if requested
|
||||
if(CMAKE_RUN_CLANG_TIDY)
|
||||
message("Enabling clang-tidy")
|
||||
set(CMAKE_CXX_CLANG_TIDY clang-tidy)
|
||||
endif()
|
||||
|
||||
# build doxygen documentation if doxygen is available
|
||||
find_package(Doxygen)
|
||||
if(DOXYGEN_FOUND)
|
||||
set( DOXYGEN_OUTPUT_DIRECTORY dist/docs )
|
||||
doxygen_add_docs(doxygen-${PROJECT_NAME} everest.js include lib src)
|
||||
endif()
|
||||
|
||||
# testing
|
||||
if(EVEREST_CORE_BUILD_TESTING AND NOT EVEREST_LIBS_ONLY)
|
||||
add_subdirectory(tests)
|
||||
else()
|
||||
message("Not running unit tests")
|
||||
endif()
|
||||
|
||||
if(NOT EVEREST_LIBS_ONLY)
|
||||
# convenience target for integration tests
|
||||
add_custom_target(install_everest_testing
|
||||
COMMAND
|
||||
if [ -z "${CPM_PACKAGE_everest-utils_SOURCE_DIR}" ] \;
|
||||
then echo "Could not determine location of everest-utils, please install everest-testing manually!" \;
|
||||
else echo "Found everest-utils at ${CPM_PACKAGE_everest-utils_SOURCE_DIR}" \;
|
||||
${Python3_EXECUTABLE} -m pip install -e "${CPM_PACKAGE_everest-utils_SOURCE_DIR}/everest-testing" \;
|
||||
fi\;
|
||||
DEPENDS
|
||||
everestpy_pip_install_dist
|
||||
COMMENT
|
||||
"Installing dependencies for testing EVerest"
|
||||
)
|
||||
endif()
|
||||
3
tools/EVerest-main/CODE_OF_CONDUCT.md
Normal file
3
tools/EVerest-main/CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Code of Conduct
|
||||
|
||||
EVerest follows the [Linux Foundation Projects Code of Conduct](https://lfprojects.org/policies/code-of-conduct/).
|
||||
3
tools/EVerest-main/CONTRIBUTING.md
Normal file
3
tools/EVerest-main/CONTRIBUTING.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Contributing to EVerest
|
||||
|
||||
Please refer to our comprehensive [Contributing Guide](https://everest.github.io/nightly/project/contributing.html).
|
||||
4
tools/EVerest-main/GOVERNANCE.md
Normal file
4
tools/EVerest-main/GOVERNANCE.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# Governance
|
||||
|
||||
Please refer to our [EVerest project governance policy](https://everest.github.io/nightly/project/governance/governance.html).
|
||||
|
||||
201
tools/EVerest-main/LICENSE
Normal file
201
tools/EVerest-main/LICENSE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
235
tools/EVerest-main/MODULE.bazel
Normal file
235
tools/EVerest-main/MODULE.bazel
Normal file
@@ -0,0 +1,235 @@
|
||||
module(
|
||||
name = "everest-core",
|
||||
version = "2026.02.0",
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# B A Z E L C E N T R A L R E G I S T R Y # https://registry.bazel.build/
|
||||
###############################################################################
|
||||
|
||||
bazel_dep(name = "bazel_features", version = "1.21.0")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.7.1")
|
||||
|
||||
BOOST_VERSION = "1.87.0"
|
||||
|
||||
bazel_dep(name = "boost.asio", version = BOOST_VERSION)
|
||||
bazel_dep(name = "boost.process", version = BOOST_VERSION)
|
||||
bazel_dep(name = "boost.uuid", version = BOOST_VERSION)
|
||||
bazel_dep(name = "boost.exception", version = BOOST_VERSION)
|
||||
bazel_dep(name = "boost.log", version = BOOST_VERSION)
|
||||
bazel_dep(name = "boost.utility", version = BOOST_VERSION)
|
||||
bazel_dep(name = "boost.program_options", version = BOOST_VERSION)
|
||||
bazel_dep(name = "catch2", version = "3.13.0")
|
||||
bazel_dep(name = "cxx.rs", version = "1.0.194")
|
||||
bazel_dep(name = "fast_float", version = "6.1.6")
|
||||
bazel_dep(name = "fmt", version = "12.1.0", repo_name = "com_github_fmtlib_fmt")
|
||||
bazel_dep(name = "googletest", version = "1.17.0.bcr.2")
|
||||
bazel_dep(name = "nlohmann_json", version = "3.12.0.bcr.1", repo_name = "com_github_nlohmann_json")
|
||||
bazel_dep(name = "libcap", version = "2.27.bcr.1")
|
||||
bazel_dep(name = "libevent", version = "2.1.12-stable.bcr.0")
|
||||
bazel_dep(name = "openssl", version = "3.3.1.bcr.9")
|
||||
bazel_dep(name = "platforms", version = "0.0.11")
|
||||
bazel_dep(name = "pugixml", version = "1.15")
|
||||
bazel_dep(name = "rapidyaml", version = "0.10.0")
|
||||
bazel_dep(name = "rules_cc", version = "0.2.14")
|
||||
bazel_dep(name = "rules_foreign_cc", version = "0.14.0")
|
||||
bazel_dep(name = "rules_license", version = "0.0.7")
|
||||
bazel_dep(name = "rules_python", version = "1.3.0")
|
||||
bazel_dep(name = "rules_rust", version = "0.67.0")
|
||||
bazel_dep(name = "rules_shell", version = "0.6.1")
|
||||
bazel_dep(name = "pybind11_bazel", version = "3.0.0")
|
||||
bazel_dep(name = "sqlite3", version = "3.51.2")
|
||||
|
||||
single_version_override(
|
||||
module_name = "boost.context",
|
||||
patches = ["//third-party/bazel/patches:boost.context.patch"],
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# C R O S S - C O M P I L A T I O N T O O L C H A I N S
|
||||
###############################################################################
|
||||
|
||||
# Module extension for cross-compilation toolchain repositories
|
||||
cross_toolchains = use_extension("//third-party/bazel/toolchains:extensions.bzl", "toolchains")
|
||||
use_repo(
|
||||
cross_toolchains,
|
||||
"cc_toolchain_aarch64-linux-gnu-x86_64-linux",
|
||||
"cc_toolchain_aarch64-linux-musl-x86_64-linux",
|
||||
"cc_toolchain_armv7-linux-gnu-x86_64-linux",
|
||||
"cc_toolchain_armv7-linux-musl-x86_64-linux",
|
||||
)
|
||||
|
||||
register_toolchains("@cc_toolchain_aarch64-linux-gnu-x86_64-linux//:aarch64-linux-glibc_toolchain_toolchain")
|
||||
|
||||
register_toolchains("@cc_toolchain_aarch64-linux-musl-x86_64-linux//:aarch64-linux-musl_toolchain_toolchain")
|
||||
|
||||
register_toolchains("@cc_toolchain_armv7-linux-musl-x86_64-linux//:armv7-linux-musl_toolchain_toolchain")
|
||||
|
||||
register_toolchains("@cc_toolchain_armv7-linux-gnu-x86_64-linux//:armv7-linux-gnu_toolchain_toolchain")
|
||||
|
||||
###############################################################################
|
||||
# N O N M O D U L E
|
||||
###############################################################################
|
||||
|
||||
deps = use_extension("//third-party/bazel:extension.bzl", "deps")
|
||||
use_repo(
|
||||
deps,
|
||||
"com_github_HowardHinnant_date",
|
||||
"com_github_pboettch_json-schema-validator",
|
||||
"com_github_warmcatt_libwebsockets",
|
||||
"mosquitto",
|
||||
"openssl_source",
|
||||
"pybind11_json",
|
||||
"sigslot",
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# P Y T H O N
|
||||
###############################################################################
|
||||
|
||||
python = use_extension("@rules_python//python/extensions:python.bzl", "python")
|
||||
python.toolchain(
|
||||
is_default = True,
|
||||
python_version = "3.10",
|
||||
)
|
||||
use_repo(python, "python_3_10")
|
||||
|
||||
pip_deps = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
|
||||
pip_deps.parse(
|
||||
hub_name = "everest-testing_pip_deps",
|
||||
python_version = "3.10",
|
||||
requirements_lock = "//applications/utils:requirements-bazel.txt",
|
||||
)
|
||||
use_repo(pip_deps, "everest-testing_pip_deps")
|
||||
|
||||
###############################################################################
|
||||
# R U S T
|
||||
###############################################################################
|
||||
|
||||
RUST_EDITION = "2021"
|
||||
|
||||
RUST_VERSION = "1.86.0"
|
||||
|
||||
RUST_EXTRA_TARGET_TRIPLES = {
|
||||
"armv7-unknown-linux-musleabihf": [
|
||||
"@platforms//os:linux",
|
||||
"@platforms//cpu:armv7",
|
||||
"@everest-core//third-party/bazel/toolchains:musl",
|
||||
],
|
||||
"armv7-unknown-linux-gnueabihf": [
|
||||
"@platforms//os:linux",
|
||||
"@platforms//cpu:armv7",
|
||||
"@everest-core//third-party/bazel/toolchains:gnu",
|
||||
],
|
||||
"aarch64-unknown-linux-musl": [
|
||||
"@platforms//os:linux",
|
||||
"@platforms//cpu:aarch64",
|
||||
"@everest-core//third-party/bazel/toolchains:musl",
|
||||
],
|
||||
"aarch64-unknown-linux-gnu": [
|
||||
"@platforms//os:linux",
|
||||
"@platforms//cpu:aarch64",
|
||||
"@everest-core//third-party/bazel/toolchains:gnu",
|
||||
],
|
||||
}
|
||||
|
||||
rust = use_extension("@rules_rust//rust:extensions.bzl", "rust")
|
||||
rust.toolchain(
|
||||
edition = RUST_EDITION,
|
||||
versions = [
|
||||
RUST_VERSION,
|
||||
"nightly/2026-02-09",
|
||||
],
|
||||
)
|
||||
|
||||
[
|
||||
rust.repository_set(
|
||||
name = "rust_{}_repository_set_x86_64-unknown-linux-gnu".format(target_triple.replace("-", "_")),
|
||||
edition = RUST_EDITION,
|
||||
exec_triple = "x86_64-unknown-linux-gnu",
|
||||
target_compatible_with = target_compatible_with,
|
||||
target_triple = target_triple,
|
||||
versions = [RUST_VERSION],
|
||||
)
|
||||
for (target_triple, target_compatible_with) in RUST_EXTRA_TARGET_TRIPLES.items()
|
||||
]
|
||||
|
||||
use_repo(rust, "rust_toolchains")
|
||||
|
||||
register_toolchains("@rust_toolchains//:all")
|
||||
|
||||
everest_crate_index = use_extension("@rules_rust//crate_universe:extensions.bzl", "crate")
|
||||
everest_crate_index.from_cargo(
|
||||
name = "everest_crate_index",
|
||||
cargo_lockfile = "@everest-core//modules:Cargo.lock",
|
||||
manifests = [
|
||||
"@everest-core//modules:Cargo.toml",
|
||||
"@everest-core//modules/HardwareDrivers/PowerMeters/RsIskraMeter:Cargo.toml",
|
||||
"@everest-core//modules/HardwareDrivers/Payment/RsPaymentTerminal:Cargo.toml",
|
||||
"@everest-core//modules/Examples/RustExamples/RsExample:Cargo.toml",
|
||||
"@everest-core//modules/Examples/RustExamples/RsExampleUser:Cargo.toml",
|
||||
],
|
||||
supported_platform_triples = [
|
||||
"x86_64-unknown-linux-gnu",
|
||||
"aarch64-unknown-linux-gnu",
|
||||
"armv7-unknown-linux-gnueabihf",
|
||||
],
|
||||
)
|
||||
everest_crate_index.annotation(
|
||||
crate = "everestrs",
|
||||
crate_features = ["build_bazel"],
|
||||
repositories = ["everest_crate_index"],
|
||||
deps = [
|
||||
"//lib/everest/framework/everestrs/everestrs",
|
||||
"//lib/everest/framework/everestrs/everestrs-build",
|
||||
],
|
||||
)
|
||||
use_repo(
|
||||
everest_crate_index,
|
||||
"everest_crate_index",
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# F R A M E W O R K C R A T E I N D I C E S
|
||||
###############################################################################
|
||||
|
||||
everest_framework_crate_index = use_extension("@rules_rust//crate_universe:extensions.bzl", "crate")
|
||||
everest_framework_crate_index.from_cargo(
|
||||
name = "everest_framework_crate_index",
|
||||
cargo_lockfile = "//lib/everest/framework/everestrs:Cargo.lock",
|
||||
manifests = [
|
||||
"//lib/everest/framework/everestrs:Cargo.toml",
|
||||
"//lib/everest/framework/everestrs/everestrs:Cargo.toml",
|
||||
"//lib/everest/framework/everestrs/everestrs-build:Cargo.toml",
|
||||
"//lib/everest/framework/everestrs/everestrs-derive:Cargo.toml",
|
||||
],
|
||||
supported_platform_triples = [
|
||||
"x86_64-unknown-linux-gnu",
|
||||
"aarch64-unknown-linux-gnu",
|
||||
"armv7-unknown-linux-gnueabihf",
|
||||
],
|
||||
)
|
||||
|
||||
everest_crate_index.annotation(
|
||||
crate = "log",
|
||||
override_target_lib = "@everest_framework_crate_index//:log",
|
||||
repositories = ["everest_crate_index"],
|
||||
)
|
||||
|
||||
use_repo(
|
||||
everest_framework_crate_index,
|
||||
"everest_framework_crate_index",
|
||||
)
|
||||
|
||||
everest_framework_validate_crate_index = use_extension("@rules_rust//crate_universe:extensions.bzl", "crate")
|
||||
everest_framework_validate_crate_index.from_cargo(
|
||||
name = "everest_framework_validate_crate_index",
|
||||
cargo_lockfile = "//lib/everest/framework/bazel/validate:Cargo.lock",
|
||||
manifests = [
|
||||
"//lib/everest/framework/bazel/validate:Cargo.toml",
|
||||
],
|
||||
)
|
||||
use_repo(
|
||||
everest_framework_validate_crate_index,
|
||||
"everest_framework_validate_crate_index",
|
||||
)
|
||||
65
tools/EVerest-main/README.md
Normal file
65
tools/EVerest-main/README.md
Normal file
@@ -0,0 +1,65 @@
|
||||
|
||||

|
||||
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/6739)
|
||||
|
||||
# EVerest
|
||||
|
||||
EVerest is a [Linux Foundation Energy](https://lfenergy.org/) backed open-source modular
|
||||
framework for setting up a full stack environment for EV charging. The modular
|
||||
software architecture fosters customizablility and lets you configure your
|
||||
dedicated charging station based on interchangeable modules. All communication
|
||||
is performed by the lightweight and flexible MQTT message queueing service.
|
||||
EVerest will help to speed the adoption to e-mobility by utilizing all the
|
||||
open-source advantages for the EV charging world. It will also enable new
|
||||
features for local energy management, PV-integration and many more!
|
||||
|
||||
# Main Features
|
||||
|
||||
- Modular and extensible architecture
|
||||
- Support for AC and DC charging
|
||||
- Support for EV charging protocols
|
||||
- OCPP 1.6, OCPP 2.0.1 and OCPP 2.1
|
||||
- ISO 15118-2, -3 and -20
|
||||
- IEC 61851
|
||||
- DIN SPEC 70121
|
||||
- Ready-to-use hardware drivers for many compatible hardware components
|
||||
- BSPs for charge controllers
|
||||
- Powermeters
|
||||
- Isolation monitors
|
||||
- DC Power supplies
|
||||
- RFID/NFC readers
|
||||
- Payment terminals
|
||||
- Energy management implementations and API
|
||||
- Standardized and stable APIs to allow easy integrations
|
||||
- Bring-up modules for custom hardware testing and integration
|
||||
- Ensured standards compliance
|
||||
- OTA service to keep EV chargers up-to-date
|
||||
- Security best practices following OpenSSF
|
||||
- ISO / IEC 5230 open source license compliance
|
||||
- Secure communication channels through TPM
|
||||
- Yocto support for custom embedded Linux images
|
||||
|
||||
# Getting Started
|
||||
|
||||
See our documentation on [everest.github.io](https://everest.github.io) to get started with using or developing EVerest. The best
|
||||
way to start is with our [Getting Started Guides](https://everest.github.io/nightly/how-to-guides/getting-started/index.html).
|
||||
|
||||
# Community
|
||||
|
||||
Find more information about the community and ways to get involved [here](https://everest.github.io/nightly/project/community.html).
|
||||
|
||||
# Contributing to EVerest
|
||||
|
||||
Anyone can contribute to EVerest! Learn more about getting involved
|
||||
[here](https://everest.github.io/nightly/project/contributing.html).
|
||||
|
||||
# License
|
||||
|
||||
EVerest is licensed under the Apache License, Version 2.0.
|
||||
See [LICENSE](LICENSE) for the full license text.
|
||||
|
||||
# Background
|
||||
|
||||
The EVerest project was initiated by PIONIX GmbH to help with the
|
||||
electrification of the mobility sector.
|
||||
4
tools/EVerest-main/RELEASE.md
Normal file
4
tools/EVerest-main/RELEASE.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# Releases
|
||||
|
||||
Please refer to our [Release Documentation](https://everest.github.io/nightly/project/releases/releases-and-versioning.html).
|
||||
|
||||
3
tools/EVerest-main/SECURITY.md
Normal file
3
tools/EVerest-main/SECURITY.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Security Policy
|
||||
|
||||
Please refer to our [EVerest Security Policy](https://everest.github.io/nightly/project/governance/security.html).
|
||||
5
tools/EVerest-main/THIRD_PARTY.md
Normal file
5
tools/EVerest-main/THIRD_PARTY.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Third-party dependencies used by this project
|
||||
|
||||
- [CodeCoverage.cmake](https://github.com/bilke/cmake-modules/blob/master/CodeCoverage.cmake) licensed under [The 3-Clause BSD License](https://opensource.org/licenses/BSD-3-Clause)
|
||||
- [Nanopb - Protocol Buffers for Embedded Systems](https://github.com/nanopb/nanopb) licensed under [The zlib License](https://opensource.org/licenses/Zlib)
|
||||
- [sphinx-notfound-page](https://github.com/readthedocs/sphinx-notfound-page) licensed under [The MIT License](https://opensource.org/licenses/MIT)
|
||||
1
tools/EVerest-main/applications/CMakeLists.txt
Normal file
1
tools/EVerest-main/applications/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
||||
add_subdirectory(pionix_chargebridge)
|
||||
31
tools/EVerest-main/applications/README.md
Normal file
31
tools/EVerest-main/applications/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Applications related to EVerest
|
||||
|
||||
This directory will contain applications that are used during the EVerest build process,
|
||||
deployed to the target hardware and useful scripts for development.
|
||||
|
||||
## containers/
|
||||
|
||||
containers/ contains multiple useful Dockerfile based containers that can be used for development.
|
||||
|
||||
* `mosquittto` : An mqtt broker
|
||||
* `mqtt-explorer` : Tool to inspect messages on mqtt topics
|
||||
* `nodered` : NodeRED application to run i.e. sil flows
|
||||
* `steve` : OCPP backend
|
||||
|
||||
## dependency_manager
|
||||
|
||||
Contains the EDM (EVerest Dependency Manager) tool which is a cli to
|
||||
manage an EVerest workspace and external dependencies during building.
|
||||
|
||||
## everest_dev_tool
|
||||
|
||||
A CLI designed to provide helpful commands/aliases for developing.
|
||||
|
||||
## utils/
|
||||
|
||||
utils/ contains ev-cli and everest-testing as well as additional code integrated from everest-utils.
|
||||
This might get broken up further in the future.
|
||||
|
||||
## devrd
|
||||
|
||||
Script to manage devcontainer + containerized services in the development environment
|
||||
@@ -0,0 +1,15 @@
|
||||
FROM eclipse-mosquitto:2.0.22
|
||||
|
||||
COPY mosquitto.conf /mosquitto/config/mosquitto.conf
|
||||
|
||||
ARG TARGETARCH
|
||||
COPY entrypoint_wrapper.sh /entrypoint_wrapper.sh
|
||||
RUN if [ ${TARGETARCH} != "amd64" ]; then \
|
||||
mv /docker-entrypoint.sh /wrapped_entrypoint.sh; \
|
||||
cp /entrypoint_wrapper.sh /entrypoint.sh; \
|
||||
else \
|
||||
mv /docker-entrypoint.sh /entrypoint.sh; \
|
||||
fi; \
|
||||
rm /entrypoint_wrapper.sh
|
||||
ENTRYPOINT [ "/entrypoint.sh" ]
|
||||
CMD ["/usr/sbin/mosquitto", "-c", "/mosquitto/config/mosquitto.conf"]
|
||||
37
tools/EVerest-main/applications/containers/mosquitto/entrypoint_wrapper.sh
Executable file
37
tools/EVerest-main/applications/containers/mosquitto/entrypoint_wrapper.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/bin/ash
|
||||
|
||||
# ---------------------------------------------
|
||||
# Architecture Warning Wrapper Script
|
||||
#
|
||||
# This script is used as an entrypoint wrapper to emit a warning
|
||||
# when the container is not running on the officially supported
|
||||
# amd64 (x86_64) architecture.
|
||||
#
|
||||
# It checks for the presence of a wrapped entrypoint script
|
||||
# (/wrapped_entrypoint.sh) and executes it if found; otherwise,
|
||||
# it falls back to executing the provided command directly.
|
||||
#
|
||||
# The warning is shown both before and after the wrapped command
|
||||
# to ensure visibility.
|
||||
# ---------------------------------------------
|
||||
|
||||
function print_warning {
|
||||
echo -e "\033[0;31m"
|
||||
echo "-------------------------------------------------------------"
|
||||
echo "⚠️ WARNING: Unsupported Architecture Detected"
|
||||
echo
|
||||
echo "This Docker image is not running on the amd64 (x86_64) architecture."
|
||||
echo "It is recommended to use the amd64-based image for full compatibility."
|
||||
echo "Other architectures are not officially supported and may cause issues."
|
||||
echo
|
||||
echo "-------------------------------------------------------------"
|
||||
echo -e "\033[0m"
|
||||
}
|
||||
|
||||
print_warning
|
||||
|
||||
if [ -f /wrapped_entrypoint.sh ]; then
|
||||
exec /wrapped_entrypoint.sh "$@"
|
||||
else
|
||||
exec "$@"
|
||||
fi
|
||||
@@ -0,0 +1,876 @@
|
||||
# Config file for mosquitto
|
||||
#
|
||||
# See mosquitto.conf(5) for more information.
|
||||
#
|
||||
# Default values are shown, uncomment to change.
|
||||
#
|
||||
# Use the # character to indicate a comment, but only if it is the
|
||||
# very first character on the line.
|
||||
|
||||
# =================================================================
|
||||
# General configuration
|
||||
# =================================================================
|
||||
|
||||
# Use per listener security settings.
|
||||
#
|
||||
# It is recommended this option be set before any other options.
|
||||
#
|
||||
# If this option is set to true, then all authentication and access control
|
||||
# options are controlled on a per listener basis. The following options are
|
||||
# affected:
|
||||
#
|
||||
# password_file acl_file psk_file auth_plugin auth_opt_* allow_anonymous
|
||||
# auto_id_prefix allow_zero_length_clientid
|
||||
#
|
||||
# Note that if set to true, then a durable client (i.e. with clean session set
|
||||
# to false) that has disconnected will use the ACL settings defined for the
|
||||
# listener that it was most recently connected to.
|
||||
#
|
||||
# The default behaviour is for this to be set to false, which maintains the
|
||||
# setting behaviour from previous versions of mosquitto.
|
||||
#per_listener_settings false
|
||||
|
||||
|
||||
# This option controls whether a client is allowed to connect with a zero
|
||||
# length client id or not. This option only affects clients using MQTT v3.1.1
|
||||
# and later. If set to false, clients connecting with a zero length client id
|
||||
# are disconnected. If set to true, clients will be allocated a client id by
|
||||
# the broker. This means it is only useful for clients with clean session set
|
||||
# to true.
|
||||
#allow_zero_length_clientid true
|
||||
|
||||
# If allow_zero_length_clientid is true, this option allows you to set a prefix
|
||||
# to automatically generated client ids to aid visibility in logs.
|
||||
# Defaults to 'auto-'
|
||||
#auto_id_prefix auto-
|
||||
|
||||
# This option affects the scenario when a client subscribes to a topic that has
|
||||
# retained messages. It is possible that the client that published the retained
|
||||
# message to the topic had access at the time they published, but that access
|
||||
# has been subsequently removed. If check_retain_source is set to true, the
|
||||
# default, the source of a retained message will be checked for access rights
|
||||
# before it is republished. When set to false, no check will be made and the
|
||||
# retained message will always be published. This affects all listeners.
|
||||
#check_retain_source true
|
||||
|
||||
# QoS 1 and 2 messages will be allowed inflight per client until this limit
|
||||
# is exceeded. Defaults to 0. (No maximum)
|
||||
# See also max_inflight_messages
|
||||
#max_inflight_bytes 0
|
||||
|
||||
# The maximum number of QoS 1 and 2 messages currently inflight per
|
||||
# client.
|
||||
# This includes messages that are partway through handshakes and
|
||||
# those that are being retried. Defaults to 20. Set to 0 for no
|
||||
# maximum. Setting to 1 will guarantee in-order delivery of QoS 1
|
||||
# and 2 messages.
|
||||
#max_inflight_messages 20
|
||||
|
||||
# For MQTT v5 clients, it is possible to have the server send a "server
|
||||
# keepalive" value that will override the keepalive value set by the client.
|
||||
# This is intended to be used as a mechanism to say that the server will
|
||||
# disconnect the client earlier than it anticipated, and that the client should
|
||||
# use the new keepalive value. The max_keepalive option allows you to specify
|
||||
# that clients may only connect with keepalive less than or equal to this
|
||||
# value, otherwise they will be sent a server keepalive telling them to use
|
||||
# max_keepalive. This only applies to MQTT v5 clients. The maximum value
|
||||
# allowable is 65535. Do not set below 10.
|
||||
#max_keepalive 65535
|
||||
|
||||
# For MQTT v5 clients, it is possible to have the server send a "maximum packet
|
||||
# size" value that will instruct the client it will not accept MQTT packets
|
||||
# with size greater than max_packet_size bytes. This applies to the full MQTT
|
||||
# packet, not just the payload. Setting this option to a positive value will
|
||||
# set the maximum packet size to that number of bytes. If a client sends a
|
||||
# packet which is larger than this value, it will be disconnected. This applies
|
||||
# to all clients regardless of the protocol version they are using, but v3.1.1
|
||||
# and earlier clients will of course not have received the maximum packet size
|
||||
# information. Defaults to no limit. Setting below 20 bytes is forbidden
|
||||
# because it is likely to interfere with ordinary client operation, even with
|
||||
# very small payloads.
|
||||
#max_packet_size 0
|
||||
|
||||
# QoS 1 and 2 messages above those currently in-flight will be queued per
|
||||
# client until this limit is exceeded. Defaults to 0. (No maximum)
|
||||
# See also max_queued_messages.
|
||||
# If both max_queued_messages and max_queued_bytes are specified, packets will
|
||||
# be queued until the first limit is reached.
|
||||
#max_queued_bytes 0
|
||||
|
||||
# Set the maximum QoS supported. Clients publishing at a QoS higher than
|
||||
# specified here will be disconnected.
|
||||
#max_qos 2
|
||||
|
||||
# The maximum number of QoS 1 and 2 messages to hold in a queue per client
|
||||
# above those that are currently in-flight. Defaults to 1000. Set
|
||||
# to 0 for no maximum (not recommended).
|
||||
# See also queue_qos0_messages.
|
||||
# See also max_queued_bytes.
|
||||
#max_queued_messages 1000
|
||||
#
|
||||
# This option sets the maximum number of heap memory bytes that the broker will
|
||||
# allocate, and hence sets a hard limit on memory use by the broker. Memory
|
||||
# requests that exceed this value will be denied. The effect will vary
|
||||
# depending on what has been denied. If an incoming message is being processed,
|
||||
# then the message will be dropped and the publishing client will be
|
||||
# disconnected. If an outgoing message is being sent, then the individual
|
||||
# message will be dropped and the receiving client will be disconnected.
|
||||
# Defaults to no limit.
|
||||
#memory_limit 0
|
||||
|
||||
# This option sets the maximum publish payload size that the broker will allow.
|
||||
# Received messages that exceed this size will not be accepted by the broker.
|
||||
# The default value is 0, which means that all valid MQTT messages are
|
||||
# accepted. MQTT imposes a maximum payload size of 268435455 bytes.
|
||||
#message_size_limit 0
|
||||
|
||||
# This option allows persistent clients (those with clean session set to false)
|
||||
# to be removed if they do not reconnect within a certain time frame.
|
||||
#
|
||||
# This is a non-standard option in MQTT V3.1 but allowed in MQTT v3.1.1.
|
||||
#
|
||||
# Badly designed clients may set clean session to false whilst using a randomly
|
||||
# generated client id. This leads to persistent clients that will never
|
||||
# reconnect. This option allows these clients to be removed.
|
||||
#
|
||||
# The expiration period should be an integer followed by one of h d w m y for
|
||||
# hour, day, week, month and year respectively. For example
|
||||
#
|
||||
# persistent_client_expiration 2m
|
||||
# persistent_client_expiration 14d
|
||||
# persistent_client_expiration 1y
|
||||
#
|
||||
# The default if not set is to never expire persistent clients.
|
||||
#persistent_client_expiration
|
||||
|
||||
# Write process id to a file. Default is a blank string which means
|
||||
# a pid file shouldn't be written.
|
||||
# This should be set to /var/run/mosquitto/mosquitto.pid if mosquitto is
|
||||
# being run automatically on boot with an init script and
|
||||
# start-stop-daemon or similar.
|
||||
#pid_file
|
||||
|
||||
# Set to true to queue messages with QoS 0 when a persistent client is
|
||||
# disconnected. These messages are included in the limit imposed by
|
||||
# max_queued_messages and max_queued_bytes
|
||||
# Defaults to false.
|
||||
# This is a non-standard option for the MQTT v3.1 spec but is allowed in
|
||||
# v3.1.1.
|
||||
#queue_qos0_messages false
|
||||
|
||||
# Set to false to disable retained message support. If a client publishes a
|
||||
# message with the retain bit set, it will be disconnected if this is set to
|
||||
# false.
|
||||
#retain_available true
|
||||
|
||||
# Disable Nagle's algorithm on client sockets. This has the effect of reducing
|
||||
# latency of individual messages at the potential cost of increasing the number
|
||||
# of packets being sent.
|
||||
#set_tcp_nodelay false
|
||||
|
||||
# Time in seconds between updates of the $SYS tree.
|
||||
# Set to 0 to disable the publishing of the $SYS tree.
|
||||
#sys_interval 10
|
||||
|
||||
# The MQTT specification requires that the QoS of a message delivered to a
|
||||
# subscriber is never upgraded to match the QoS of the subscription. Enabling
|
||||
# this option changes this behaviour. If upgrade_outgoing_qos is set true,
|
||||
# messages sent to a subscriber will always match the QoS of its subscription.
|
||||
# This is a non-standard option explicitly disallowed by the spec.
|
||||
#upgrade_outgoing_qos false
|
||||
|
||||
# When run as root, drop privileges to this user and its primary
|
||||
# group.
|
||||
# Set to root to stay as root, but this is not recommended.
|
||||
# If set to "mosquitto", or left unset, and the "mosquitto" user does not exist
|
||||
# then it will drop privileges to the "nobody" user instead.
|
||||
# If run as a non-root user, this setting has no effect.
|
||||
# Note that on Windows this has no effect and so mosquitto should be started by
|
||||
# the user you wish it to run as.
|
||||
#user mosquitto
|
||||
|
||||
# =================================================================
|
||||
# Listeners
|
||||
# =================================================================
|
||||
|
||||
# Listen on a port/ip address combination. By using this variable
|
||||
# multiple times, mosquitto can listen on more than one port. If
|
||||
# this variable is used and neither bind_address nor port given,
|
||||
# then the default listener will not be started.
|
||||
# The port number to listen on must be given. Optionally, an ip
|
||||
# address or host name may be supplied as a second argument. In
|
||||
# this case, mosquitto will attempt to bind the listener to that
|
||||
# address and so restrict access to the associated network and
|
||||
# interface. By default, mosquitto will listen on all interfaces.
|
||||
# Note that for a websockets listener it is not possible to bind to a host
|
||||
# name.
|
||||
#
|
||||
# On systems that support Unix Domain Sockets, it is also possible
|
||||
# to create a # Unix socket rather than opening a TCP socket. In
|
||||
# this case, the port number should be set to 0 and a unix socket
|
||||
# path must be provided, e.g.
|
||||
# listener 0 /tmp/mosquitto.sock
|
||||
#
|
||||
# listener port-number [ip address/host name/unix socket path]
|
||||
listener 1883
|
||||
|
||||
# By default, a listener will attempt to listen on all supported IP protocol
|
||||
# versions. If you do not have an IPv4 or IPv6 interface you may wish to
|
||||
# disable support for either of those protocol versions. In particular, note
|
||||
# that due to the limitations of the websockets library, it will only ever
|
||||
# attempt to open IPv6 sockets if IPv6 support is compiled in, and so will fail
|
||||
# if IPv6 is not available.
|
||||
#
|
||||
# Set to `ipv4` to force the listener to only use IPv4, or set to `ipv6` to
|
||||
# force the listener to only use IPv6. If you want support for both IPv4 and
|
||||
# IPv6, then do not use the socket_domain option.
|
||||
#
|
||||
#socket_domain
|
||||
|
||||
# Bind the listener to a specific interface. This is similar to
|
||||
# the [ip address/host name] part of the listener definition, but is useful
|
||||
# when an interface has multiple addresses or the address may change. If used
|
||||
# with the [ip address/host name] part of the listener definition, then the
|
||||
# bind_interface option will take priority.
|
||||
# Not available on Windows.
|
||||
#
|
||||
# Example: bind_interface eth0
|
||||
#bind_interface
|
||||
|
||||
# When a listener is using the websockets protocol, it is possible to serve
|
||||
# http data as well. Set http_dir to a directory which contains the files you
|
||||
# wish to serve. If this option is not specified, then no normal http
|
||||
# connections will be possible.
|
||||
#http_dir
|
||||
|
||||
# The maximum number of client connections to allow. This is
|
||||
# a per listener setting.
|
||||
# Default is -1, which means unlimited connections.
|
||||
# Note that other process limits mean that unlimited connections
|
||||
# are not really possible. Typically the default maximum number of
|
||||
# connections possible is around 1024.
|
||||
#max_connections -1
|
||||
|
||||
# The listener can be restricted to operating within a topic hierarchy using
|
||||
# the mount_point option. This is achieved be prefixing the mount_point string
|
||||
# to all topics for any clients connected to this listener. This prefixing only
|
||||
# happens internally to the broker; the client will not see the prefix.
|
||||
#mount_point
|
||||
|
||||
# Choose the protocol to use when listening.
|
||||
# This can be either mqtt or websockets.
|
||||
# Certificate based TLS may be used with websockets, except that only the
|
||||
# cafile, certfile, keyfile, ciphers, and ciphers_tls13 options are supported.
|
||||
#protocol mqtt
|
||||
|
||||
# Set use_username_as_clientid to true to replace the clientid that a client
|
||||
# connected with with its username. This allows authentication to be tied to
|
||||
# the clientid, which means that it is possible to prevent one client
|
||||
# disconnecting another by using the same clientid.
|
||||
# If a client connects with no username it will be disconnected as not
|
||||
# authorised when this option is set to true.
|
||||
# Do not use in conjunction with clientid_prefixes.
|
||||
# See also use_identity_as_username.
|
||||
#use_username_as_clientid
|
||||
|
||||
# Change the websockets headers size. This is a global option, it is not
|
||||
# possible to set per listener. This option sets the size of the buffer used in
|
||||
# the libwebsockets library when reading HTTP headers. If you are passing large
|
||||
# header data such as cookies then you may need to increase this value. If left
|
||||
# unset, or set to 0, then the default of 1024 bytes will be used.
|
||||
#websockets_headers_size
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Certificate based SSL/TLS support
|
||||
# -----------------------------------------------------------------
|
||||
# The following options can be used to enable certificate based SSL/TLS support
|
||||
# for this listener. Note that the recommended port for MQTT over TLS is 8883,
|
||||
# but this must be set manually.
|
||||
#
|
||||
# See also the mosquitto-tls man page and the "Pre-shared-key based SSL/TLS
|
||||
# support" section. Only one of certificate or PSK encryption support can be
|
||||
# enabled for any listener.
|
||||
|
||||
# Both of certfile and keyfile must be defined to enable certificate based
|
||||
# TLS encryption.
|
||||
|
||||
# Path to the PEM encoded server certificate.
|
||||
#certfile
|
||||
|
||||
# Path to the PEM encoded keyfile.
|
||||
#keyfile
|
||||
|
||||
# If you wish to control which encryption ciphers are used, use the ciphers
|
||||
# option. The list of available ciphers can be optained using the "openssl
|
||||
# ciphers" command and should be provided in the same format as the output of
|
||||
# that command. This applies to TLS 1.2 and earlier versions only. Use
|
||||
# ciphers_tls1.3 for TLS v1.3.
|
||||
#ciphers
|
||||
|
||||
# Choose which TLS v1.3 ciphersuites are used for this listener.
|
||||
# Defaults to "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"
|
||||
#ciphers_tls1.3
|
||||
|
||||
# If you have require_certificate set to true, you can create a certificate
|
||||
# revocation list file to revoke access to particular client certificates. If
|
||||
# you have done this, use crlfile to point to the PEM encoded revocation file.
|
||||
#crlfile
|
||||
|
||||
# To allow the use of ephemeral DH key exchange, which provides forward
|
||||
# security, the listener must load DH parameters. This can be specified with
|
||||
# the dhparamfile option. The dhparamfile can be generated with the command
|
||||
# e.g. "openssl dhparam -out dhparam.pem 2048"
|
||||
#dhparamfile
|
||||
|
||||
# By default an TLS enabled listener will operate in a similar fashion to a
|
||||
# https enabled web server, in that the server has a certificate signed by a CA
|
||||
# and the client will verify that it is a trusted certificate. The overall aim
|
||||
# is encryption of the network traffic. By setting require_certificate to true,
|
||||
# the client must provide a valid certificate in order for the network
|
||||
# connection to proceed. This allows access to the broker to be controlled
|
||||
# outside of the mechanisms provided by MQTT.
|
||||
#require_certificate false
|
||||
|
||||
# cafile and capath define methods of accessing the PEM encoded
|
||||
# Certificate Authority certificates that will be considered trusted when
|
||||
# checking incoming client certificates.
|
||||
# cafile defines the path to a file containing the CA certificates.
|
||||
# capath defines a directory that will be searched for files
|
||||
# containing the CA certificates. For capath to work correctly, the
|
||||
# certificate files must have ".crt" as the file ending and you must run
|
||||
# "openssl rehash <path to capath>" each time you add/remove a certificate.
|
||||
#cafile
|
||||
#capath
|
||||
|
||||
|
||||
# If require_certificate is true, you may set use_identity_as_username to true
|
||||
# to use the CN value from the client certificate as a username. If this is
|
||||
# true, the password_file option will not be used for this listener.
|
||||
#use_identity_as_username false
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Pre-shared-key based SSL/TLS support
|
||||
# -----------------------------------------------------------------
|
||||
# The following options can be used to enable PSK based SSL/TLS support for
|
||||
# this listener. Note that the recommended port for MQTT over TLS is 8883, but
|
||||
# this must be set manually.
|
||||
#
|
||||
# See also the mosquitto-tls man page and the "Certificate based SSL/TLS
|
||||
# support" section. Only one of certificate or PSK encryption support can be
|
||||
# enabled for any listener.
|
||||
|
||||
# The psk_hint option enables pre-shared-key support for this listener and also
|
||||
# acts as an identifier for this listener. The hint is sent to clients and may
|
||||
# be used locally to aid authentication. The hint is a free form string that
|
||||
# doesn't have much meaning in itself, so feel free to be creative.
|
||||
# If this option is provided, see psk_file to define the pre-shared keys to be
|
||||
# used or create a security plugin to handle them.
|
||||
#psk_hint
|
||||
|
||||
# When using PSK, the encryption ciphers used will be chosen from the list of
|
||||
# available PSK ciphers. If you want to control which ciphers are available,
|
||||
# use the "ciphers" option. The list of available ciphers can be optained
|
||||
# using the "openssl ciphers" command and should be provided in the same format
|
||||
# as the output of that command.
|
||||
#ciphers
|
||||
|
||||
# Set use_identity_as_username to have the psk identity sent by the client used
|
||||
# as its username. Authentication will be carried out using the PSK rather than
|
||||
# the MQTT username/password and so password_file will not be used for this
|
||||
# listener.
|
||||
#use_identity_as_username false
|
||||
|
||||
listener 9001
|
||||
protocol websockets
|
||||
|
||||
# =================================================================
|
||||
# Persistence
|
||||
# =================================================================
|
||||
|
||||
# If persistence is enabled, save the in-memory database to disk
|
||||
# every autosave_interval seconds. If set to 0, the persistence
|
||||
# database will only be written when mosquitto exits. See also
|
||||
# autosave_on_changes.
|
||||
# Note that writing of the persistence database can be forced by
|
||||
# sending mosquitto a SIGUSR1 signal.
|
||||
#autosave_interval 1800
|
||||
|
||||
# If true, mosquitto will count the number of subscription changes, retained
|
||||
# messages received and queued messages and if the total exceeds
|
||||
# autosave_interval then the in-memory database will be saved to disk.
|
||||
# If false, mosquitto will save the in-memory database to disk by treating
|
||||
# autosave_interval as a time in seconds.
|
||||
#autosave_on_changes false
|
||||
|
||||
# Save persistent message data to disk (true/false).
|
||||
# This saves information about all messages, including
|
||||
# subscriptions, currently in-flight messages and retained
|
||||
# messages.
|
||||
# retained_persistence is a synonym for this option.
|
||||
#persistence false
|
||||
|
||||
# The filename to use for the persistent database, not including
|
||||
# the path.
|
||||
#persistence_file mosquitto.db
|
||||
|
||||
# Location for persistent database.
|
||||
# Default is an empty string (current directory).
|
||||
# Set to e.g. /var/lib/mosquitto if running as a proper service on Linux or
|
||||
# similar.
|
||||
#persistence_location
|
||||
|
||||
|
||||
# =================================================================
|
||||
# Logging
|
||||
# =================================================================
|
||||
|
||||
# Places to log to. Use multiple log_dest lines for multiple
|
||||
# logging destinations.
|
||||
# Possible destinations are: stdout stderr syslog topic file dlt
|
||||
#
|
||||
# stdout and stderr log to the console on the named output.
|
||||
#
|
||||
# syslog uses the userspace syslog facility which usually ends up
|
||||
# in /var/log/messages or similar.
|
||||
#
|
||||
# topic logs to the broker topic '$SYS/broker/log/<severity>',
|
||||
# where severity is one of D, E, W, N, I, M which are debug, error,
|
||||
# warning, notice, information and message. Message type severity is used by
|
||||
# the subscribe/unsubscribe log_types and publishes log messages to
|
||||
# $SYS/broker/log/M/susbcribe or $SYS/broker/log/M/unsubscribe.
|
||||
#
|
||||
# The file destination requires an additional parameter which is the file to be
|
||||
# logged to, e.g. "log_dest file /var/log/mosquitto.log". The file will be
|
||||
# closed and reopened when the broker receives a HUP signal. Only a single file
|
||||
# destination may be configured.
|
||||
#
|
||||
# The dlt destination is for the automotive `Diagnostic Log and Trace` tool.
|
||||
# This requires that Mosquitto has been compiled with DLT support.
|
||||
#
|
||||
# Note that if the broker is running as a Windows service it will default to
|
||||
# "log_dest none" and neither stdout nor stderr logging is available.
|
||||
# Use "log_dest none" if you wish to disable logging.
|
||||
#log_dest stderr
|
||||
|
||||
# Types of messages to log. Use multiple log_type lines for logging
|
||||
# multiple types of messages.
|
||||
# Possible types are: debug, error, warning, notice, information,
|
||||
# none, subscribe, unsubscribe, websockets, all.
|
||||
# Note that debug type messages are for decoding the incoming/outgoing
|
||||
# network packets. They are not logged in "topics".
|
||||
#log_type error
|
||||
#log_type warning
|
||||
#log_type notice
|
||||
#log_type information
|
||||
|
||||
|
||||
# If set to true, client connection and disconnection messages will be included
|
||||
# in the log.
|
||||
#connection_messages true
|
||||
|
||||
# If using syslog logging (not on Windows), messages will be logged to the
|
||||
# "daemon" facility by default. Use the log_facility option to choose which of
|
||||
# local0 to local7 to log to instead. The option value should be an integer
|
||||
# value, e.g. "log_facility 5" to use local5.
|
||||
#log_facility
|
||||
|
||||
# If set to true, add a timestamp value to each log message.
|
||||
#log_timestamp true
|
||||
|
||||
# Set the format of the log timestamp. If left unset, this is the number of
|
||||
# seconds since the Unix epoch.
|
||||
# This is a free text string which will be passed to the strftime function. To
|
||||
# get an ISO 8601 datetime, for example:
|
||||
# log_timestamp_format %Y-%m-%dT%H:%M:%S
|
||||
#log_timestamp_format
|
||||
|
||||
# Change the websockets logging level. This is a global option, it is not
|
||||
# possible to set per listener. This is an integer that is interpreted by
|
||||
# libwebsockets as a bit mask for its lws_log_levels enum. See the
|
||||
# libwebsockets documentation for more details. "log_type websockets" must also
|
||||
# be enabled.
|
||||
#websockets_log_level 0
|
||||
|
||||
|
||||
# =================================================================
|
||||
# Security
|
||||
# =================================================================
|
||||
|
||||
# If set, only clients that have a matching prefix on their
|
||||
# clientid will be allowed to connect to the broker. By default,
|
||||
# all clients may connect.
|
||||
# For example, setting "secure-" here would mean a client "secure-
|
||||
# client" could connect but another with clientid "mqtt" couldn't.
|
||||
#clientid_prefixes
|
||||
|
||||
# Boolean value that determines whether clients that connect
|
||||
# without providing a username are allowed to connect. If set to
|
||||
# false then a password file should be created (see the
|
||||
# password_file option) to control authenticated client access.
|
||||
#
|
||||
# Defaults to false, unless there are no listeners defined in the configuration
|
||||
# file, in which case it is set to true, but connections are only allowed from
|
||||
# the local machine.
|
||||
allow_anonymous true
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Default authentication and topic access control
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
# Control access to the broker using a password file. This file can be
|
||||
# generated using the mosquitto_passwd utility. If TLS support is not compiled
|
||||
# into mosquitto (it is recommended that TLS support should be included) then
|
||||
# plain text passwords are used, in which case the file should be a text file
|
||||
# with lines in the format:
|
||||
# username:password
|
||||
# The password (and colon) may be omitted if desired, although this
|
||||
# offers very little in the way of security.
|
||||
#
|
||||
# See the TLS client require_certificate and use_identity_as_username options
|
||||
# for alternative authentication options. If an auth_plugin is used as well as
|
||||
# password_file, the auth_plugin check will be made first.
|
||||
#password_file
|
||||
|
||||
# Access may also be controlled using a pre-shared-key file. This requires
|
||||
# TLS-PSK support and a listener configured to use it. The file should be text
|
||||
# lines in the format:
|
||||
# identity:key
|
||||
# The key should be in hexadecimal format without a leading "0x".
|
||||
# If an auth_plugin is used as well, the auth_plugin check will be made first.
|
||||
#psk_file
|
||||
|
||||
# Control access to topics on the broker using an access control list
|
||||
# file. If this parameter is defined then only the topics listed will
|
||||
# have access.
|
||||
# If the first character of a line of the ACL file is a # it is treated as a
|
||||
# comment.
|
||||
# Topic access is added with lines of the format:
|
||||
#
|
||||
# topic [read|write|readwrite|deny] <topic>
|
||||
#
|
||||
# The access type is controlled using "read", "write", "readwrite" or "deny".
|
||||
# This parameter is optional (unless <topic> contains a space character) - if
|
||||
# not given then the access is read/write. <topic> can contain the + or #
|
||||
# wildcards as in subscriptions.
|
||||
#
|
||||
# The "deny" option can used to explicity deny access to a topic that would
|
||||
# otherwise be granted by a broader read/write/readwrite statement. Any "deny"
|
||||
# topics are handled before topics that grant read/write access.
|
||||
#
|
||||
# The first set of topics are applied to anonymous clients, assuming
|
||||
# allow_anonymous is true. User specific topic ACLs are added after a
|
||||
# user line as follows:
|
||||
#
|
||||
# user <username>
|
||||
#
|
||||
# The username referred to here is the same as in password_file. It is
|
||||
# not the clientid.
|
||||
#
|
||||
#
|
||||
# If is also possible to define ACLs based on pattern substitution within the
|
||||
# topic. The patterns available for substition are:
|
||||
#
|
||||
# %c to match the client id of the client
|
||||
# %u to match the username of the client
|
||||
#
|
||||
# The substitution pattern must be the only text for that level of hierarchy.
|
||||
#
|
||||
# The form is the same as for the topic keyword, but using pattern as the
|
||||
# keyword.
|
||||
# Pattern ACLs apply to all users even if the "user" keyword has previously
|
||||
# been given.
|
||||
#
|
||||
# If using bridges with usernames and ACLs, connection messages can be allowed
|
||||
# with the following pattern:
|
||||
# pattern write $SYS/broker/connection/%c/state
|
||||
#
|
||||
# pattern [read|write|readwrite] <topic>
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# pattern write sensor/%u/data
|
||||
#
|
||||
# If an auth_plugin is used as well as acl_file, the auth_plugin check will be
|
||||
# made first.
|
||||
#acl_file
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# External authentication and topic access plugin options
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
# External authentication and access control can be supported with the
|
||||
# auth_plugin option. This is a path to a loadable plugin. See also the
|
||||
# auth_opt_* options described below.
|
||||
#
|
||||
# The auth_plugin option can be specified multiple times to load multiple
|
||||
# plugins. The plugins will be processed in the order that they are specified
|
||||
# here. If the auth_plugin option is specified alongside either of
|
||||
# password_file or acl_file then the plugin checks will be made first.
|
||||
#
|
||||
#auth_plugin
|
||||
|
||||
# If the auth_plugin option above is used, define options to pass to the
|
||||
# plugin here as described by the plugin instructions. All options named
|
||||
# using the format auth_opt_* will be passed to the plugin, for example:
|
||||
#
|
||||
# auth_opt_db_host
|
||||
# auth_opt_db_port
|
||||
# auth_opt_db_username
|
||||
# auth_opt_db_password
|
||||
|
||||
|
||||
# =================================================================
|
||||
# Bridges
|
||||
# =================================================================
|
||||
|
||||
# A bridge is a way of connecting multiple MQTT brokers together.
|
||||
# Create a new bridge using the "connection" option as described below. Set
|
||||
# options for the bridges using the remaining parameters. You must specify the
|
||||
# address and at least one topic to subscribe to.
|
||||
#
|
||||
# Each connection must have a unique name.
|
||||
#
|
||||
# The address line may have multiple host address and ports specified. See
|
||||
# below in the round_robin description for more details on bridge behaviour if
|
||||
# multiple addresses are used. Note that if you use an IPv6 address, then you
|
||||
# are required to specify a port.
|
||||
#
|
||||
# The direction that the topic will be shared can be chosen by
|
||||
# specifying out, in or both, where the default value is out.
|
||||
# The QoS level of the bridged communication can be specified with the next
|
||||
# topic option. The default QoS level is 0, to change the QoS the topic
|
||||
# direction must also be given.
|
||||
#
|
||||
# The local and remote prefix options allow a topic to be remapped when it is
|
||||
# bridged to/from the remote broker. This provides the ability to place a topic
|
||||
# tree in an appropriate location.
|
||||
#
|
||||
# For more details see the mosquitto.conf man page.
|
||||
#
|
||||
# Multiple topics can be specified per connection, but be careful
|
||||
# not to create any loops.
|
||||
#
|
||||
# If you are using bridges with cleansession set to false (the default), then
|
||||
# you may get unexpected behaviour from incoming topics if you change what
|
||||
# topics you are subscribing to. This is because the remote broker keeps the
|
||||
# subscription for the old topic. If you have this problem, connect your bridge
|
||||
# with cleansession set to true, then reconnect with cleansession set to false
|
||||
# as normal.
|
||||
#connection <name>
|
||||
#address <host>[:<port>] [<host>[:<port>]]
|
||||
#topic <topic> [[[out | in | both] qos-level] local-prefix remote-prefix]
|
||||
|
||||
# If you need to have the bridge connect over a particular network interface,
|
||||
# use bridge_bind_address to tell the bridge which local IP address the socket
|
||||
# should bind to, e.g. `bridge_bind_address 192.168.1.10`
|
||||
#bridge_bind_address
|
||||
|
||||
# If a bridge has topics that have "out" direction, the default behaviour is to
|
||||
# send an unsubscribe request to the remote broker on that topic. This means
|
||||
# that changing a topic direction from "in" to "out" will not keep receiving
|
||||
# incoming messages. Sending these unsubscribe requests is not always
|
||||
# desirable, setting bridge_attempt_unsubscribe to false will disable sending
|
||||
# the unsubscribe request.
|
||||
#bridge_attempt_unsubscribe true
|
||||
|
||||
# Set the version of the MQTT protocol to use with for this bridge. Can be one
|
||||
# of mqttv50, mqttv311 or mqttv31. Defaults to mqttv311.
|
||||
#bridge_protocol_version mqttv311
|
||||
|
||||
# Set the clean session variable for this bridge.
|
||||
# When set to true, when the bridge disconnects for any reason, all
|
||||
# messages and subscriptions will be cleaned up on the remote
|
||||
# broker. Note that with cleansession set to true, there may be a
|
||||
# significant amount of retained messages sent when the bridge
|
||||
# reconnects after losing its connection.
|
||||
# When set to false, the subscriptions and messages are kept on the
|
||||
# remote broker, and delivered when the bridge reconnects.
|
||||
#cleansession false
|
||||
|
||||
# Set the amount of time a bridge using the lazy start type must be idle before
|
||||
# it will be stopped. Defaults to 60 seconds.
|
||||
#idle_timeout 60
|
||||
|
||||
# Set the keepalive interval for this bridge connection, in
|
||||
# seconds.
|
||||
#keepalive_interval 60
|
||||
|
||||
# Set the clientid to use on the local broker. If not defined, this defaults to
|
||||
# 'local.<clientid>'. If you are bridging a broker to itself, it is important
|
||||
# that local_clientid and clientid do not match.
|
||||
#local_clientid
|
||||
|
||||
# If set to true, publish notification messages to the local and remote brokers
|
||||
# giving information about the state of the bridge connection. Retained
|
||||
# messages are published to the topic $SYS/broker/connection/<clientid>/state
|
||||
# unless the notification_topic option is used.
|
||||
# If the message is 1 then the connection is active, or 0 if the connection has
|
||||
# failed.
|
||||
# This uses the last will and testament feature.
|
||||
#notifications true
|
||||
|
||||
# Choose the topic on which notification messages for this bridge are
|
||||
# published. If not set, messages are published on the topic
|
||||
# $SYS/broker/connection/<clientid>/state
|
||||
#notification_topic
|
||||
|
||||
# Set the client id to use on the remote end of this bridge connection. If not
|
||||
# defined, this defaults to 'name.hostname' where name is the connection name
|
||||
# and hostname is the hostname of this computer.
|
||||
# This replaces the old "clientid" option to avoid confusion. "clientid"
|
||||
# remains valid for the time being.
|
||||
#remote_clientid
|
||||
|
||||
# Set the password to use when connecting to a broker that requires
|
||||
# authentication. This option is only used if remote_username is also set.
|
||||
# This replaces the old "password" option to avoid confusion. "password"
|
||||
# remains valid for the time being.
|
||||
#remote_password
|
||||
|
||||
# Set the username to use when connecting to a broker that requires
|
||||
# authentication.
|
||||
# This replaces the old "username" option to avoid confusion. "username"
|
||||
# remains valid for the time being.
|
||||
#remote_username
|
||||
|
||||
# Set the amount of time a bridge using the automatic start type will wait
|
||||
# until attempting to reconnect.
|
||||
# This option can be configured to use a constant delay time in seconds, or to
|
||||
# use a backoff mechanism based on "Decorrelated Jitter", which adds a degree
|
||||
# of randomness to when the restart occurs.
|
||||
#
|
||||
# Set a constant timeout of 20 seconds:
|
||||
# restart_timeout 20
|
||||
#
|
||||
# Set backoff with a base (start value) of 10 seconds and a cap (upper limit) of
|
||||
# 60 seconds:
|
||||
# restart_timeout 10 30
|
||||
#
|
||||
# Defaults to jitter with a base of 5 and cap of 30
|
||||
#restart_timeout 5 30
|
||||
|
||||
# If the bridge has more than one address given in the address/addresses
|
||||
# configuration, the round_robin option defines the behaviour of the bridge on
|
||||
# a failure of the bridge connection. If round_robin is false, the default
|
||||
# value, then the first address is treated as the main bridge connection. If
|
||||
# the connection fails, the other secondary addresses will be attempted in
|
||||
# turn. Whilst connected to a secondary bridge, the bridge will periodically
|
||||
# attempt to reconnect to the main bridge until successful.
|
||||
# If round_robin is true, then all addresses are treated as equals. If a
|
||||
# connection fails, the next address will be tried and if successful will
|
||||
# remain connected until it fails
|
||||
#round_robin false
|
||||
|
||||
# Set the start type of the bridge. This controls how the bridge starts and
|
||||
# can be one of three types: automatic, lazy and once. Note that RSMB provides
|
||||
# a fourth start type "manual" which isn't currently supported by mosquitto.
|
||||
#
|
||||
# "automatic" is the default start type and means that the bridge connection
|
||||
# will be started automatically when the broker starts and also restarted
|
||||
# after a short delay (30 seconds) if the connection fails.
|
||||
#
|
||||
# Bridges using the "lazy" start type will be started automatically when the
|
||||
# number of queued messages exceeds the number set with the "threshold"
|
||||
# parameter. It will be stopped automatically after the time set by the
|
||||
# "idle_timeout" parameter. Use this start type if you wish the connection to
|
||||
# only be active when it is needed.
|
||||
#
|
||||
# A bridge using the "once" start type will be started automatically when the
|
||||
# broker starts but will not be restarted if the connection fails.
|
||||
#start_type automatic
|
||||
|
||||
# Set the number of messages that need to be queued for a bridge with lazy
|
||||
# start type to be restarted. Defaults to 10 messages.
|
||||
# Must be less than max_queued_messages.
|
||||
#threshold 10
|
||||
|
||||
# If try_private is set to true, the bridge will attempt to indicate to the
|
||||
# remote broker that it is a bridge not an ordinary client. If successful, this
|
||||
# means that loop detection will be more effective and that retained messages
|
||||
# will be propagated correctly. Not all brokers support this feature so it may
|
||||
# be necessary to set try_private to false if your bridge does not connect
|
||||
# properly.
|
||||
#try_private true
|
||||
|
||||
# Some MQTT brokers do not allow retained messages. MQTT v5 gives a mechanism
|
||||
# for brokers to tell clients that they do not support retained messages, but
|
||||
# this is not possible for MQTT v3.1.1 or v3.1. If you need to bridge to a
|
||||
# v3.1.1 or v3.1 broker that does not support retained messages, set the
|
||||
# bridge_outgoing_retain option to false. This will remove the retain bit on
|
||||
# all outgoing messages to that bridge, regardless of any other setting.
|
||||
#bridge_outgoing_retain true
|
||||
|
||||
# If you wish to restrict the size of messages sent to a remote bridge, use the
|
||||
# bridge_max_packet_size option. This sets the maximum number of bytes for
|
||||
# the total message, including headers and payload.
|
||||
# Note that MQTT v5 brokers may provide their own maximum-packet-size property.
|
||||
# In this case, the smaller of the two limits will be used.
|
||||
# Set to 0 for "unlimited".
|
||||
#bridge_max_packet_size 0
|
||||
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Certificate based SSL/TLS support
|
||||
# -----------------------------------------------------------------
|
||||
# Either bridge_cafile or bridge_capath must be defined to enable TLS support
|
||||
# for this bridge.
|
||||
# bridge_cafile defines the path to a file containing the
|
||||
# Certificate Authority certificates that have signed the remote broker
|
||||
# certificate.
|
||||
# bridge_capath defines a directory that will be searched for files containing
|
||||
# the CA certificates. For bridge_capath to work correctly, the certificate
|
||||
# files must have ".crt" as the file ending and you must run "openssl rehash
|
||||
# <path to capath>" each time you add/remove a certificate.
|
||||
#bridge_cafile
|
||||
#bridge_capath
|
||||
|
||||
|
||||
# If the remote broker has more than one protocol available on its port, e.g.
|
||||
# MQTT and WebSockets, then use bridge_alpn to configure which protocol is
|
||||
# requested. Note that WebSockets support for bridges is not yet available.
|
||||
#bridge_alpn
|
||||
|
||||
# When using certificate based encryption, bridge_insecure disables
|
||||
# verification of the server hostname in the server certificate. This can be
|
||||
# useful when testing initial server configurations, but makes it possible for
|
||||
# a malicious third party to impersonate your server through DNS spoofing, for
|
||||
# example. Use this option in testing only. If you need to resort to using this
|
||||
# option in a production environment, your setup is at fault and there is no
|
||||
# point using encryption.
|
||||
#bridge_insecure false
|
||||
|
||||
# Path to the PEM encoded client certificate, if required by the remote broker.
|
||||
#bridge_certfile
|
||||
|
||||
# Path to the PEM encoded client private key, if required by the remote broker.
|
||||
#bridge_keyfile
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# PSK based SSL/TLS support
|
||||
# -----------------------------------------------------------------
|
||||
# Pre-shared-key encryption provides an alternative to certificate based
|
||||
# encryption. A bridge can be configured to use PSK with the bridge_identity
|
||||
# and bridge_psk options. These are the client PSK identity, and pre-shared-key
|
||||
# in hexadecimal format with no "0x". Only one of certificate and PSK based
|
||||
# encryption can be used on one
|
||||
# bridge at once.
|
||||
#bridge_identity
|
||||
#bridge_psk
|
||||
|
||||
|
||||
# =================================================================
|
||||
# External config files
|
||||
# =================================================================
|
||||
|
||||
# External configuration files may be included by using the
|
||||
# include_dir option. This defines a directory that will be searched
|
||||
# for config files. All files that end in '.conf' will be loaded as
|
||||
# a configuration file. It is best to have this as the last option
|
||||
# in the main file. This option will only be processed from the main
|
||||
# configuration file. The directory specified must not contain the
|
||||
# main configuration file.
|
||||
# Files within include_dir will be loaded sorted in case-sensitive
|
||||
# alphabetical order, with capital letters ordered first. If this option is
|
||||
# given multiple times, all of the files from the first instance will be
|
||||
# processed before the next instance. See the man page for examples.
|
||||
#include_dir
|
||||
@@ -0,0 +1,19 @@
|
||||
FROM smeagolworms4/mqtt-explorer:browser-1.0.3
|
||||
|
||||
COPY ./settings.json /mqtt-explorer/config/settings.json
|
||||
|
||||
ARG TARGETARCH
|
||||
COPY entrypoint_wrapper.sh /entrypoint_wrapper.sh
|
||||
RUN if [ ${TARGETARCH} != "amd64" ]; then \
|
||||
mv /entrypoint.sh /wrapped_entrypoint.sh; \
|
||||
cp /entrypoint_wrapper.sh /entrypoint.sh; \
|
||||
fi; \
|
||||
rm /entrypoint_wrapper.sh
|
||||
ENTRYPOINT [ "/entrypoint.sh" ]
|
||||
CMD node node-server/server/dist/node-server/server/src/index.js \
|
||||
--http-port=$HTTP_PORT \
|
||||
--config-path=$CONFIG_PATH \
|
||||
--http-user=$HTTP_USER \
|
||||
--http-password=$HTTP_PASSWORD\
|
||||
--ssl-key-path=$SSL_KEY_PATH\
|
||||
--ssl-cert-path=$SSL_CERT_PATH
|
||||
@@ -0,0 +1,37 @@
|
||||
#!/bin/sh
|
||||
|
||||
# ---------------------------------------------
|
||||
# Architecture Warning Wrapper Script
|
||||
#
|
||||
# This script is used as an entrypoint wrapper to emit a warning
|
||||
# when the container is not running on the officially supported
|
||||
# amd64 (x86_64) architecture.
|
||||
#
|
||||
# It checks for the presence of a wrapped entrypoint script
|
||||
# (/wrapped_entrypoint.sh) and executes it if found; otherwise,
|
||||
# it falls back to executing the provided command directly.
|
||||
#
|
||||
# The warning is shown both before and after the wrapped command
|
||||
# to ensure visibility.
|
||||
# ---------------------------------------------
|
||||
|
||||
function print_warning {
|
||||
echo -e "\033[0;31m"
|
||||
echo "-------------------------------------------------------------"
|
||||
echo "⚠️ WARNING: Unsupported Architecture Detected"
|
||||
echo
|
||||
echo "This Docker image is not running on the amd64 (x86_64) architecture."
|
||||
echo "It is recommended to use the amd64-based image for full compatibility."
|
||||
echo "Other architectures are not officially supported and may cause issues."
|
||||
echo
|
||||
echo "-------------------------------------------------------------"
|
||||
echo -e "\033[0m"
|
||||
}
|
||||
|
||||
print_warning
|
||||
|
||||
if [ -f /wrapped_entrypoint.sh ]; then
|
||||
exec /wrapped_entrypoint.sh "$@"
|
||||
else
|
||||
exec "$@"
|
||||
fi
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"ConnectionManager_connections": {
|
||||
"mqtt-server": {
|
||||
"configVersion": 1,
|
||||
"certValidation": true,
|
||||
"clientId": "mqtt-explorer-e1085971",
|
||||
"id": "mqtt-server",
|
||||
"name": "MQTT Server",
|
||||
"encryption": false,
|
||||
"subscriptions": [
|
||||
{
|
||||
"topic": "#",
|
||||
"qos": 0
|
||||
},
|
||||
{
|
||||
"topic": "$SYS/#",
|
||||
"qos": 0
|
||||
}
|
||||
],
|
||||
"type": "mqtt",
|
||||
"host": "mqtt-server",
|
||||
"port": 1883,
|
||||
"protocol": "mqtt"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
FROM nodered/node-red:4.1.2
|
||||
RUN npm install node-red-dashboard@3.6.6
|
||||
RUN npm install node-red-contrib-ui-actions@0.1.8
|
||||
RUN npm install node-red-node-ui-table@0.4.5
|
||||
RUN npm install node-red-contrib-ui-level@0.1.46
|
||||
|
||||
COPY nodered-settings.js /data/settings.js
|
||||
|
||||
USER root
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
ARG TARGETARCH
|
||||
COPY entrypoint_wrapper.sh /entrypoint_wrapper.sh
|
||||
RUN if [ ${TARGETARCH} != "amd64" ]; then \
|
||||
mv /entrypoint.sh /wrapped_entrypoint.sh; \
|
||||
cp /entrypoint_wrapper.sh /entrypoint.sh; \
|
||||
fi; \
|
||||
rm /entrypoint_wrapper.sh
|
||||
USER node-red
|
||||
ENTRYPOINT [ "/entrypoint.sh" ]
|
||||
10
tools/EVerest-main/applications/containers/nodered/entrypoint.sh
Executable file
10
tools/EVerest-main/applications/containers/nodered/entrypoint.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
exec npm \
|
||||
--no-update-notifier \
|
||||
--no-fund \
|
||||
start \
|
||||
--cache /data/.npm \
|
||||
-- \
|
||||
--userDir /data \
|
||||
"$@"
|
||||
37
tools/EVerest-main/applications/containers/nodered/entrypoint_wrapper.sh
Executable file
37
tools/EVerest-main/applications/containers/nodered/entrypoint_wrapper.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/bin/sh
|
||||
|
||||
# ---------------------------------------------
|
||||
# Architecture Warning Wrapper Script
|
||||
#
|
||||
# This script is used as an entrypoint wrapper to emit a warning
|
||||
# when the container is not running on the officially supported
|
||||
# amd64 (x86_64) architecture.
|
||||
#
|
||||
# It checks for the presence of a wrapped entrypoint script
|
||||
# (/wrapped_entrypoint.sh) and executes it if found; otherwise,
|
||||
# it falls back to executing the provided command directly.
|
||||
#
|
||||
# The warning is shown both before and after the wrapped command
|
||||
# to ensure visibility.
|
||||
# ---------------------------------------------
|
||||
|
||||
function print_warning {
|
||||
echo -e "\033[0;31m"
|
||||
echo "-------------------------------------------------------------"
|
||||
echo "⚠️ WARNING: Unsupported Architecture Detected"
|
||||
echo
|
||||
echo "This Docker image is not running on the amd64 (x86_64) architecture."
|
||||
echo "It is recommended to use the amd64-based image for full compatibility."
|
||||
echo "Other architectures are not officially supported and may cause issues."
|
||||
echo
|
||||
echo "-------------------------------------------------------------"
|
||||
echo -e "\033[0m"
|
||||
}
|
||||
|
||||
print_warning
|
||||
|
||||
if [ -f /wrapped_entrypoint.sh ]; then
|
||||
exec /wrapped_entrypoint.sh "$@"
|
||||
else
|
||||
exec "$@"
|
||||
fi
|
||||
@@ -0,0 +1,20 @@
|
||||
module.exports = {
|
||||
// Flow file location
|
||||
flowFile: 'flows.json',
|
||||
|
||||
// Enable projects
|
||||
enableProjects: process.env.NODE_RED_ENABLE_PROJECTS === 'true',
|
||||
|
||||
// HTTP settings
|
||||
httpNodeRoot: '/',
|
||||
httpAdminRoot: '/',
|
||||
|
||||
// Logging
|
||||
logging: {
|
||||
console: {
|
||||
level: "info",
|
||||
metrics: false,
|
||||
audit: false
|
||||
}
|
||||
}
|
||||
};
|
||||
30
tools/EVerest-main/applications/containers/steve/Dockerfile
Normal file
30
tools/EVerest-main/applications/containers/steve/Dockerfile
Normal file
@@ -0,0 +1,30 @@
|
||||
FROM maven:3.6.1-jdk-11
|
||||
|
||||
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
|
||||
|
||||
WORKDIR /steve
|
||||
|
||||
ENV DOCKERIZE_VERSION v0.6.1
|
||||
RUN wget --no-verbose https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
|
||||
&& tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
|
||||
&& rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz
|
||||
|
||||
RUN wget -qO- https://github.com/steve-community/steve/archive/steve-3.6.0.tar.gz | tar xz --strip-components=1
|
||||
COPY main.properties src/main/resources/config/docker
|
||||
COPY init.sh .
|
||||
COPY keystore.jks .
|
||||
|
||||
ARG TARGETARCH
|
||||
COPY entrypoint_wrapper.sh /entrypoint_wrapper.sh
|
||||
RUN if [ ${TARGETARCH} != "amd64" ]; then \
|
||||
ln -s /usr/local/bin/mvn-entrypoint.sh /wrapped_entrypoint.sh; \
|
||||
cp /entrypoint_wrapper.sh /entrypoint.sh; \
|
||||
else \
|
||||
ln -s /usr/local/bin/mvn-entrypoint.sh /entrypoint.sh; \
|
||||
fi; \
|
||||
rm /entrypoint_wrapper.sh
|
||||
ENTRYPOINT [ "/entrypoint.sh" ]
|
||||
CMD /steve/init.sh
|
||||
|
||||
|
||||
|
||||
37
tools/EVerest-main/applications/containers/steve/entrypoint_wrapper.sh
Executable file
37
tools/EVerest-main/applications/containers/steve/entrypoint_wrapper.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ---------------------------------------------
|
||||
# Architecture Warning Wrapper Script
|
||||
#
|
||||
# This script is used as an entrypoint wrapper to emit a warning
|
||||
# when the container is not running on the officially supported
|
||||
# amd64 (x86_64) architecture.
|
||||
#
|
||||
# It checks for the presence of a wrapped entrypoint script
|
||||
# (/wrapped_entrypoint.sh) and executes it if found; otherwise,
|
||||
# it falls back to executing the provided command directly.
|
||||
#
|
||||
# The warning is shown both before and after the wrapped command
|
||||
# to ensure visibility.
|
||||
# ---------------------------------------------
|
||||
|
||||
function print_warning {
|
||||
echo -e "\033[0;31m"
|
||||
echo "-------------------------------------------------------------"
|
||||
echo "⚠️ WARNING: Unsupported Architecture Detected"
|
||||
echo
|
||||
echo "This Docker image is not running on the amd64 (x86_64) architecture."
|
||||
echo "It is recommended to use the amd64-based image for full compatibility."
|
||||
echo "Other architectures are not officially supported and may cause issues."
|
||||
echo
|
||||
echo "-------------------------------------------------------------"
|
||||
echo -e "\033[0m"
|
||||
}
|
||||
|
||||
print_warning
|
||||
|
||||
if [ -f /wrapped_entrypoint.sh ]; then
|
||||
exec /wrapped_entrypoint.sh "$@"
|
||||
else
|
||||
exec "$@"
|
||||
fi
|
||||
10
tools/EVerest-main/applications/containers/steve/init.sh
Executable file
10
tools/EVerest-main/applications/containers/steve/init.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
set -e # exit on any error
|
||||
dockerize -wait tcp://ocpp-db:3306 -timeout 60s
|
||||
|
||||
if [ ! -f ".buildsuccess" ]; then
|
||||
mvn clean package -Pdocker -Djdk.tls.client.protocols="TLSv1,TLSv1.1,TLSv1.2"
|
||||
touch .buildsuccess
|
||||
fi
|
||||
|
||||
java -jar target/steve.jar
|
||||
BIN
tools/EVerest-main/applications/containers/steve/keystore.jks
Normal file
BIN
tools/EVerest-main/applications/containers/steve/keystore.jks
Normal file
Binary file not shown.
@@ -0,0 +1,57 @@
|
||||
# Just to be backwards compatible with previous versions, this is set to "steve",
|
||||
# since there might be already configured chargepoints expecting the older path.
|
||||
# Otherwise, might as well be changed to something else or be left empty.
|
||||
#
|
||||
context.path = steve
|
||||
|
||||
# Database configuration
|
||||
#
|
||||
db.ip = ocpp-db
|
||||
db.port = 3306
|
||||
db.schema = ocpp-db
|
||||
db.user = ocpp
|
||||
db.password = ocpp
|
||||
|
||||
# Credentials for Web interface access
|
||||
#
|
||||
auth.user = admin
|
||||
auth.password = 1234
|
||||
|
||||
# Jetty configuration
|
||||
#
|
||||
server.host = 0.0.0.0
|
||||
server.gzip.enabled = false
|
||||
|
||||
# Jetty HTTP configuration
|
||||
#
|
||||
http.enabled = true
|
||||
http.port = 8180
|
||||
|
||||
# Jetty HTTPS configuration
|
||||
#
|
||||
https.enabled = true
|
||||
https.port = 8443
|
||||
keystore.path = /steve/keystore.jks
|
||||
keystore.password = 123456
|
||||
|
||||
# When the WebSocket/Json charge point opens more than one WebSocket connection,
|
||||
# we need a mechanism/strategy to select one of them for outgoing requests.
|
||||
# For allowed values see de.rwth.idsg.steve.ocpp.ws.custom.WsSessionSelectStrategyEnum.
|
||||
#
|
||||
ws.session.select.strategy = ALWAYS_LAST
|
||||
|
||||
# if BootNotification messages arrive (SOAP) or WebSocket connection attempts are made (JSON) from unknown charging
|
||||
# stations, we reject these charging stations, because stations with these chargeBoxIds were NOT inserted into database
|
||||
# beforehand. by setting this property to true, this behaviour can be modified to automatically insert unknown
|
||||
# stations into database and accept their requests.
|
||||
#
|
||||
# CAUTION: setting this property to true is very dangerous, because we will accept EVERY BootNotification or WebSocket
|
||||
# connection attempt from ANY sender as long as the sender knows the URL and sends a valid message.
|
||||
#
|
||||
auto.register.unknown.stations = false
|
||||
|
||||
### DO NOT MODIFY ###
|
||||
steve.version = ${project.version}
|
||||
git.describe = ${git.commit.id.describe}
|
||||
db.sql.logging = false
|
||||
profile = prod
|
||||
3
tools/EVerest-main/applications/dependency_manager/.gitignore
vendored
Normal file
3
tools/EVerest-main/applications/dependency_manager/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
build
|
||||
__pycache__
|
||||
*.egg-info
|
||||
@@ -0,0 +1,24 @@
|
||||
ev_setup_cmake_variables_python_wheel()
|
||||
|
||||
ev_add_pip_package(
|
||||
NAME edm
|
||||
SOURCE_DIRECTORY .
|
||||
)
|
||||
|
||||
ev_is_python_venv_active(
|
||||
RESULT_VAR IS_PYTHON_VENV_ACTIVE
|
||||
)
|
||||
|
||||
if(NOT ${IS_PYTHON_VENV_ACTIVE})
|
||||
message(WARNING "Python venv is not active. Please ensure that edm is available in your environment.")
|
||||
else()
|
||||
get_target_property(SOURCE_DIRECTORY ev_pip_package_edm SOURCE_DIRECTORY)
|
||||
message(STATUS "Installing edm from: ${SOURCE_DIRECTORY}")
|
||||
ev_pip_install_local(
|
||||
PACKAGE_NAME "edm"
|
||||
PACKAGE_SOURCE_DIRECTORY "${SOURCE_DIRECTORY}"
|
||||
)
|
||||
unset(EVEREST_DEPENDENCY_MANAGER CACHE)
|
||||
find_program(EVEREST_DEPENDENCY_MANAGER edm HINTS ${EV_ACTIVATE_PYTHON_VENV_PATH_TO_VENV}/bin REQUIRED)
|
||||
message(STATUS "Using edm from: ${EDM}")
|
||||
endif()
|
||||
201
tools/EVerest-main/applications/dependency_manager/LICENSE
Normal file
201
tools/EVerest-main/applications/dependency_manager/LICENSE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
232
tools/EVerest-main/applications/dependency_manager/README.md
Normal file
232
tools/EVerest-main/applications/dependency_manager/README.md
Normal file
@@ -0,0 +1,232 @@
|
||||
# Dependency Manager for EVerest
|
||||
|
||||
- [Dependency Manager for EVerest](#dependency-manager-for-everest)
|
||||
- [Install and Quick Start](#install-and-quick-start)
|
||||
- [Installing edm](#installing-edm)
|
||||
- [Enabling CPM_SOURCE_CACHE](#enabling-cpm_source_cache)
|
||||
- [Python packages needed to run edm](#python-packages-needed-to-run-edm)
|
||||
- [Setting up CMake integration](#setting-up-cmake-integration)
|
||||
- [Setting up a workspace](#setting-up-a-workspace)
|
||||
- [Updating a workspace](#updating-a-workspace)
|
||||
- [Using the EDM CMake module and dependencies.yaml](#using-the-edm-cmake-module-and-dependenciesyaml)
|
||||
- [Modifying dependencies](#modifying-dependencies)
|
||||
- [Create a workspace config from an existing directory tree](#create-a-workspace-config-from-an-existing-directory-tree)
|
||||
- [Git information at a glance](#git-information-at-a-glance)
|
||||
|
||||
## Install and Quick Start
|
||||
To install the **edm** dependency manager for EVerest you have to perform the following steps.
|
||||
|
||||
Please make sure you are running a sufficiently recent version of **Python3 (>=3.6)** and that you are able to install Python packages from source. Usually you just have to ensure that you have **pip**, **setuptools** and **wheel** available. Refer to [the Python *Installing Packages* documentation](https://packaging.python.org/tutorials/installing-packages/#requirements-for-installing-packages) for indepth guidance if any problems arise.
|
||||
|
||||
```bash
|
||||
python3 -m pip install --upgrade pip setuptools wheel
|
||||
```
|
||||
|
||||
### Installing edm
|
||||
Now you can clone *this repository* and install **edm**:
|
||||
|
||||
(make sure you have set up your [ssh key](https://www.atlassian.com/git/tutorials/git-ssh) in github first!)
|
||||
|
||||
```bash
|
||||
git clone git@github.com:EVerest/everest-dev-environment.git
|
||||
cd everest-dev-environment/dependency_manager
|
||||
python3 -m pip install .
|
||||
edm --config ../everest-complete.yaml --workspace ~/checkout/everest-workspace
|
||||
```
|
||||
|
||||
The last command registers the [**EDM** CMake module](#setting-up-cmake-integration) and creates a workspace in the *~/checkout/everest-workspace* directory from [a config that is shipped with this repository](../everest-complete.yaml).
|
||||
The workspace will have the following structure containing all current dependencies for EVerest:
|
||||
```bash
|
||||
everest-workspace/
|
||||
├── EVerest
|
||||
├── everest-deploy-devkit
|
||||
├── everest-dev-environment
|
||||
├── everest-framework
|
||||
├── everest-utils
|
||||
├── liblog
|
||||
├── libmodbus
|
||||
├── libocpp
|
||||
├── libsunspec
|
||||
├── libtimer
|
||||
├── open-plc-utils
|
||||
├── RISE-V2G
|
||||
└── workspace-config.yaml
|
||||
```
|
||||
The *workspace-config.yaml* contains a copy of the config that was used to create this workspace.
|
||||
|
||||
### Enabling CPM_SOURCE_CACHE
|
||||
The **edm** dependency manager uses [CPM](https://github.com/cpm-cmake/CPM.cmake) for its CMake integration.
|
||||
This means you *can* and **should** set the *CPM_SOURCE_CACHE* environment variable. This makes sure that dependencies that you do not manage in the workspace are not re-downloaded multiple times. For detailed information and other useful environment variables please refer to the [CPM Documentation](https://github.com/cpm-cmake/CPM.cmake/blob/master/README.md#CPM_SOURCE_CACHE).
|
||||
```bash
|
||||
export CPM_SOURCE_CACHE=$HOME/.cache/CPM
|
||||
```
|
||||
|
||||
### Python packages needed to run edm
|
||||
The following Python3 packages are needed to run the **edm** dependency manager.
|
||||
If you installed **edm** using the guide above they were already installed automatically.
|
||||
|
||||
- Python >= 3.6
|
||||
- Jinja2 >= 3.0
|
||||
- PyYAML >= 5.4
|
||||
|
||||
## Setting up and updating a workspace
|
||||
For letting **edm** do the work of setting up an initial EVerest workspace,
|
||||
do this:
|
||||
|
||||
```bash
|
||||
edm init --workspace ~/checkout/everest-workspace
|
||||
```
|
||||
If you are currently in the *everest-workspace* directory the following command has the same effect:
|
||||
|
||||
```bash
|
||||
edm init
|
||||
```
|
||||
|
||||
For using a dedicated release version, you can do this:
|
||||
|
||||
```bash
|
||||
edm init 2023.7.0
|
||||
```
|
||||
|
||||
In this example, version 2023.7.0 is pulled from the server. This will only work if
|
||||
you previous code is not in a "dirty" state.
|
||||
|
||||
## Using the EDM CMake module and dependencies.yaml
|
||||
To use **edm** from CMake you have to add the following line to the top-level *CMakeLists.txt* file in the respective source repository:
|
||||
```cmake
|
||||
find_package(EDM REQUIRED)
|
||||
```
|
||||
The **EDM** CMake module will be discovered automatically if you [registered the CMake module in the way it described in the *Setting up CMake integration* section of this readme](#setting-up-cmake-integration).
|
||||
|
||||
To define dependencies you can now add a **dependencies.yaml** file to your source repository. It should look like this:
|
||||
```yaml
|
||||
---
|
||||
liblog:
|
||||
git: git@github.com:EVerest/liblog.git
|
||||
git_tag: main
|
||||
options: ["BUILD_EXAMPLES OFF"]
|
||||
libtimer:
|
||||
git: git@github.com:EVerest/libtimer.git
|
||||
git_tag: main
|
||||
options: ["BUILD_EXAMPLES OFF"]
|
||||
|
||||
```
|
||||
|
||||
If you want to conditionally include some dependencies, eg. for testing, you can do this in the following way:
|
||||
```yaml
|
||||
catch2:
|
||||
git: https://github.com/catchorg/Catch2.git
|
||||
git_tag: v3.4.0
|
||||
cmake_condition: "BUILD_TESTING"
|
||||
|
||||
```
|
||||
Here *cmake_condition* can be any string that CMake can use in an if() block. Please be aware that any variables you use here must be defined before a call to *evc_setup_edm()* is made in your CMakeLists.txt
|
||||
|
||||
## Selective library consumption
|
||||
|
||||
If your project only needs specific everest-core libraries (e.g. `liblog`, `everest-util`, `everest-io`, `libocpp`) without building the full module framework, use the `EVEREST_LIBS_ONLY` and `EVEREST_INCLUDE_LIBS` CMake options.
|
||||
|
||||
In your project's `dependencies.yaml`:
|
||||
```yaml
|
||||
everest-core:
|
||||
git: https://github.com/EVerest/everest-core.git
|
||||
git_tag: 2026.02.0
|
||||
options:
|
||||
- "EVEREST_LIBS_ONLY ON"
|
||||
- "EVEREST_INCLUDE_LIBS log;util;io"
|
||||
```
|
||||
|
||||
Or directly via CMake:
|
||||
```bash
|
||||
cmake -S . -B build \
|
||||
-DEVEREST_LIBS_ONLY=ON \
|
||||
-DEVEREST_INCLUDE_LIBS="log;util;io"
|
||||
```
|
||||
|
||||
| Option | Default | Description |
|
||||
|---|---|---|
|
||||
| `EVEREST_LIBS_ONLY` | OFF | Skip modules, applications, config — only build libraries |
|
||||
| `EVEREST_INCLUDE_LIBS` | (empty) | Semicolon-separated allowlist; transitive deps auto-resolved |
|
||||
| `EVEREST_EXCLUDE_LIBS` | (empty) | Semicolon-separated blocklist of libraries to skip |
|
||||
|
||||
Transitive dependencies are resolved automatically. For example, `EVEREST_INCLUDE_LIBS="ocpp"` will also build `log`, `timer`, `evse_security`, `sqlite`, and `cbv2g`.
|
||||
|
||||
See the [EDM documentation](../../docs/source/explanation/dev-tools/edm.rst) for the full list of available libraries and their dependency chains.
|
||||
|
||||
## Modifying dependencies
|
||||
|
||||
To change dependency git URLs you can set the *EVEREST_MODIFY_DEPENDENCIES_URLS* environment variable to a string containing prefixes and replacements delimited by whitespace characters.
|
||||
For example:
|
||||
```bash
|
||||
EVEREST_MODIFY_DEPENDENCIES_URLS="prefix=https://github.com/EVerest/ replace=git@github.com:EVerest/"
|
||||
```
|
||||
This would change all dependency git URLs that start with *https://github.com/EVerest/* to *git@github.com:EVerest/*.
|
||||
|
||||
Multiple prefix and replace pairs can be chained together delimited by whitespace characters.
|
||||
For example:
|
||||
```bash
|
||||
EVEREST_MODIFY_DEPENDENCIES_URLS="prefix=https://github.com/EVerest/ replace=git@github.com:EVerest/ prefix=https://github.com/EVerest/everest-framework.git replace=https://github.com/EVerest/everest-framework.git"
|
||||
```
|
||||
This would change all dependency git URLs that start with *https://github.com/EVerest/* to *git@github.com:EVerest/* as well as keeping the dependency https URL of *https://github.com/EVerest/everest-framework.git* as *https://github.com/EVerest/everest-framework.git*.
|
||||
|
||||
Additionally you can set the *EVEREST_MODIFY_DEPENDENCIES* environment variable to a file containing modifications to the projects dependencies.yaml files when running cmake:
|
||||
|
||||
```bash
|
||||
EVEREST_MODIFY_DEPENDENCIES=../dependencies_modified.yaml cmake -S . -B build
|
||||
```
|
||||
|
||||
The *dependencies_modified.yaml* file can contain something along these lines:
|
||||
|
||||
```yaml
|
||||
nlohmann_json:
|
||||
git: null # this makes edm look for nlohmann_json via find_package
|
||||
libfmt:
|
||||
rename: fmt # if find_package needs a different dependency name you can rename it
|
||||
git: null
|
||||
catch2:
|
||||
git_tag: v1.2.3 # if you want to select a different git tag for a build this is also possible
|
||||
```
|
||||
|
||||
## Create a workspace config from an existing directory tree
|
||||
Suppose you already have a directory tree that you want to save into a config file.
|
||||
You can do this with the following command:
|
||||
```bash
|
||||
edm --create-config custom-config.yaml
|
||||
```
|
||||
|
||||
This is a short form of
|
||||
```bash
|
||||
edm --create-config custom-config.yaml --include-remotes git@github.com:EVerest/*
|
||||
```
|
||||
and only includes repositories from the *EVerest* namespace. You can add as many remotes to this list as you want.
|
||||
|
||||
For example if you only want to include certain repositories you can use the following command.
|
||||
```bash
|
||||
edm --create-config custom-config.yaml --include-remotes git@github.com:EVerest/everest* git@github.com:EVerest/liblog.git
|
||||
```
|
||||
|
||||
If you want to include all repositories, including external dependencies, in the config you can use the following command.
|
||||
```bash
|
||||
edm --create-config custom-config.yaml --external-in-config
|
||||
```
|
||||
|
||||
## Git information at a glance
|
||||
You can get a list of all git repositories in the current directory and their state using the following command.
|
||||
```bash
|
||||
edm --git-info --git-fetch
|
||||
```
|
||||
If you want to know the state of all repositories in a workspace you can use the following command.
|
||||
```bash
|
||||
edm --workspace ~/checkout/everest-workspace --git-info --git-fetch
|
||||
```
|
||||
|
||||
This creates output that is similar to the following example.
|
||||
```bash
|
||||
[edm]: Git info for "~/checkout/everest-workspace":
|
||||
[edm]: Using git-fetch to update remote information. This might take a few seconds.
|
||||
[edm]: "everest-dev-environment" @ branch: main [remote: origin/main] [behind 6] [clean]
|
||||
[edm]: "everest-framework" @ branch: main [remote: origin/main] [dirty]
|
||||
[edm]: "everest-deploy-devkit" @ branch: main [remote: origin/main] [clean]
|
||||
[edm]: "libtimer" @ branch: main [remote: origin/main] [dirty]
|
||||
[edm]: 2/4 repositories are dirty.
|
||||
```
|
||||
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
##
|
||||
## SPDX-License-Identifier: Apache-2.0
|
||||
## Copyright 2020 - 2021 Pionix GmbH and Contributors to EVerest
|
||||
##
|
||||
echo "generating bash-completion file"
|
||||
SRC_DIR="$(dirname "${BASH_SOURCE[0]}")/src"
|
||||
echo "Using module found in ${SRC_DIR}"
|
||||
cd "${SRC_DIR}"
|
||||
BASH_COMPLETION_FILE_DIR="$(pwd)"
|
||||
BASH_COMPLETION_FILE="${BASH_COMPLETION_FILE_DIR}/edm_tool/edm-completion.bash"
|
||||
shtab --shell=bash -u edm_tool.get_parser --prog edm > "${BASH_COMPLETION_FILE}"
|
||||
@@ -0,0 +1,3 @@
|
||||
[build-system]
|
||||
requires = ["setuptools", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
@@ -0,0 +1,3 @@
|
||||
Jinja2>=2.11
|
||||
PyYAML>=5.3
|
||||
requests>=2
|
||||
38
tools/EVerest-main/applications/dependency_manager/setup.cfg
Normal file
38
tools/EVerest-main/applications/dependency_manager/setup.cfg
Normal file
@@ -0,0 +1,38 @@
|
||||
[metadata]
|
||||
name = edm_tool
|
||||
version = attr: edm_tool.__version__
|
||||
description= A simple dependency manager
|
||||
long_description = file: README.md
|
||||
long_description_content_type= text/markdown
|
||||
url= https://github.com/EVerest/everest-dev-environment
|
||||
author = Kai-Uwe Hermann
|
||||
author_email = kai-uwe.hermann@pionix.de
|
||||
classifiers =
|
||||
Development Status :: 3 - Alpha
|
||||
Intended Audience :: Developers
|
||||
Topic :: Software Development :: Build Tools
|
||||
License :: OSI Approved :: Apache Software License
|
||||
|
||||
[options]
|
||||
packages = edm_tool
|
||||
package_dir =
|
||||
= src
|
||||
python_requires = >=3.6
|
||||
install_requires =
|
||||
Jinja2>=2.11
|
||||
PyYAML>=5.3
|
||||
requests>=2
|
||||
|
||||
[options.entry_points]
|
||||
console_scripts =
|
||||
edm = edm_tool:main
|
||||
|
||||
[options.package_data]
|
||||
edm_tool =
|
||||
templates/cpm.jinja
|
||||
cmake/CPM.cmake
|
||||
cmake/EDMConfig.cmake
|
||||
edm-completion.bash
|
||||
|
||||
[pycodestyle]
|
||||
max-line-length = 120
|
||||
@@ -0,0 +1,9 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright 2020 - 2022 Pionix GmbH and Contributors to EVerest
|
||||
"""Everest Dependency Manager."""
|
||||
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
# see setup.cfg
|
||||
)
|
||||
@@ -0,0 +1,18 @@
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright Pionix GmbH and Contributors to EVerest
|
||||
#
|
||||
"""Everest Dependency Manager."""
|
||||
from edm_tool import edm
|
||||
|
||||
__version__ = "0.8.0"
|
||||
|
||||
|
||||
def get_parser():
|
||||
"""Return the command line parser."""
|
||||
return edm.get_parser(__version__)
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entrypoint of edm."""
|
||||
edm.main(get_parser())
|
||||
88
tools/EVerest-main/applications/dependency_manager/src/edm_tool/bazel.py
Executable file
88
tools/EVerest-main/applications/dependency_manager/src/edm_tool/bazel.py
Executable file
@@ -0,0 +1,88 @@
|
||||
"Bazel related functions for edm_tool."
|
||||
import yaml
|
||||
from typing import List, Optional, Dict
|
||||
|
||||
|
||||
def _format_optional_string(value: Optional[str]):
|
||||
"""Formats a string value as a string literal (with quotes) or `None` if the value is None."""
|
||||
if value is None:
|
||||
return "None"
|
||||
return f'"{value}"'
|
||||
|
||||
|
||||
def _is_commit(revision: str):
|
||||
# Revision is a commit if it is a hexadecimal 40-character string
|
||||
return len(revision) == 40 and all(c in "0123456789abcdef" for c in revision.lower())
|
||||
|
||||
def _get_depname_for_label(label: str) -> str:
|
||||
build, depname, bazel = label.split(":")[1].split(".")
|
||||
if build != "BUILD" or bazel != "bazel":
|
||||
raise ValueError(f"Invalid build file name: {label}")
|
||||
return depname
|
||||
|
||||
def _parse_build_file_labels(labels: Optional[List[str]]) -> Dict[str, str]:
|
||||
# For easier matching of build files with dependencies
|
||||
# we convert the list of build files:
|
||||
# ```
|
||||
# [
|
||||
# "@workspace//path/to/build:BUILD.<depname>.bazel",
|
||||
# ...
|
||||
# ]
|
||||
# ```
|
||||
# into a dictionary:
|
||||
# ```
|
||||
# {
|
||||
# "<depname>": "@workspace//path/to/build:BUILD.<depname>.bazel",
|
||||
# ...
|
||||
# }
|
||||
# ```
|
||||
# and check that all build files have proper names.
|
||||
if labels is None:
|
||||
return {}
|
||||
|
||||
return dict((_get_depname_for_label(label), label) for label in labels)
|
||||
|
||||
|
||||
def generate_deps(args):
|
||||
"Parse the dependencies.yaml and print content of *.bzl file to stdout."
|
||||
with open(args.dependencies_yaml, 'r', encoding='utf-8') as f:
|
||||
deps = yaml.safe_load(f)
|
||||
|
||||
build_files = _parse_build_file_labels(args.build_file)
|
||||
|
||||
for name in build_files:
|
||||
if name not in deps:
|
||||
raise ValueError(f"Build file {name} does not have a corresponding dependency in {args.dependencies_yaml}")
|
||||
|
||||
print("""
|
||||
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
|
||||
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
|
||||
|
||||
def edm_deps():""")
|
||||
|
||||
for name, desc in deps.items():
|
||||
repo = desc["git"]
|
||||
# The parameter is called `git_tag` but it can be a tag or a commit
|
||||
revision = desc["git_tag"]
|
||||
tag = None
|
||||
commit = None
|
||||
|
||||
if _is_commit(revision):
|
||||
commit = revision
|
||||
else:
|
||||
tag = revision
|
||||
|
||||
build_file = build_files.get(name)
|
||||
|
||||
print(
|
||||
f"""
|
||||
maybe(
|
||||
git_repository,
|
||||
name = "{name}",
|
||||
remote = "{repo}",
|
||||
tag = {_format_optional_string(tag)},
|
||||
commit = {_format_optional_string(commit)},
|
||||
build_file = {_format_optional_string(build_file)},
|
||||
)
|
||||
"""
|
||||
)
|
||||
@@ -0,0 +1,144 @@
|
||||
# AUTOMATCALLY GENERATED by `shtab`
|
||||
|
||||
|
||||
|
||||
_shtab_edm_tool_option_strings=('-h' '--help' '--version' '--workspace' '--working_dir' '--out' '--include_deps' '--config' '--create-vscode-workspace' '--update' '--cmake' '--verbose' '--nocolor' '--install-bash-completion' '--create-config' '--external-in-config' '--include-remotes' '--create-snapshot' '--git-info' '--git-fetch' '--git-pull')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
_shtab_edm_tool_pos_0_nargs=A...
|
||||
_shtab_edm_tool__h_nargs=0
|
||||
_shtab_edm_tool___help_nargs=0
|
||||
_shtab_edm_tool___version_nargs=0
|
||||
_shtab_edm_tool___include_deps_nargs=0
|
||||
_shtab_edm_tool___create_vscode_workspace_nargs=0
|
||||
_shtab_edm_tool___update_nargs=0
|
||||
_shtab_edm_tool___cmake_nargs=0
|
||||
_shtab_edm_tool___verbose_nargs=0
|
||||
_shtab_edm_tool___nocolor_nargs=0
|
||||
_shtab_edm_tool___install_bash_completion_nargs=0
|
||||
_shtab_edm_tool___external_in_config_nargs=0
|
||||
_shtab_edm_tool___include_remotes_nargs=*
|
||||
_shtab_edm_tool___create_snapshot_nargs=?
|
||||
_shtab_edm_tool___git_info_nargs=0
|
||||
_shtab_edm_tool___git_fetch_nargs=0
|
||||
_shtab_edm_tool___git_pull_nargs=*
|
||||
|
||||
|
||||
# $1=COMP_WORDS[1]
|
||||
_shtab_compgen_files() {
|
||||
compgen -f -- $1 # files
|
||||
}
|
||||
|
||||
# $1=COMP_WORDS[1]
|
||||
_shtab_compgen_dirs() {
|
||||
compgen -d -- $1 # recurse into subdirs
|
||||
}
|
||||
|
||||
# $1=COMP_WORDS[1]
|
||||
_shtab_replace_nonword() {
|
||||
echo "${1//[^[:word:]]/_}"
|
||||
}
|
||||
|
||||
# set default values (called for the initial parser & any subparsers)
|
||||
_set_parser_defaults() {
|
||||
local subparsers_var="${prefix}_subparsers[@]"
|
||||
sub_parsers=${!subparsers_var}
|
||||
|
||||
local current_option_strings_var="${prefix}_option_strings[@]"
|
||||
current_option_strings=${!current_option_strings_var}
|
||||
|
||||
completed_positional_actions=0
|
||||
|
||||
_set_new_action "pos_${completed_positional_actions}" true
|
||||
}
|
||||
|
||||
# $1=action identifier
|
||||
# $2=positional action (bool)
|
||||
# set all identifiers for an action's parameters
|
||||
_set_new_action() {
|
||||
current_action="${prefix}_$(_shtab_replace_nonword $1)"
|
||||
|
||||
local current_action_compgen_var=${current_action}_COMPGEN
|
||||
current_action_compgen="${!current_action_compgen_var}"
|
||||
|
||||
local current_action_choices_var="${current_action}_choices"
|
||||
current_action_choices="${!current_action_choices_var}"
|
||||
|
||||
local current_action_nargs_var="${current_action}_nargs"
|
||||
if [ -n "${!current_action_nargs_var}" ]; then
|
||||
current_action_nargs="${!current_action_nargs_var}"
|
||||
else
|
||||
current_action_nargs=1
|
||||
fi
|
||||
|
||||
current_action_args_start_index=$(( $word_index + 1 ))
|
||||
|
||||
current_action_is_positional=$2
|
||||
}
|
||||
|
||||
# Notes:
|
||||
# `COMPREPLY`: what will be rendered after completion is triggered
|
||||
# `completing_word`: currently typed word to generate completions for
|
||||
# `${!var}`: evaluates the content of `var` and expand its content as a variable
|
||||
# hello="world"
|
||||
# x="hello"
|
||||
# ${!x} -> ${hello} -> "world"
|
||||
_shtab_edm_tool() {
|
||||
local completing_word="${COMP_WORDS[COMP_CWORD]}"
|
||||
COMPREPLY=()
|
||||
|
||||
prefix=_shtab_edm_tool
|
||||
word_index=0
|
||||
_set_parser_defaults
|
||||
word_index=1
|
||||
|
||||
# determine what arguments are appropriate for the current state
|
||||
# of the arg parser
|
||||
while [ $word_index -ne $COMP_CWORD ]; do
|
||||
local this_word="${COMP_WORDS[$word_index]}"
|
||||
|
||||
if [[ -n $sub_parsers && " ${sub_parsers[@]} " =~ " ${this_word} " ]]; then
|
||||
# valid subcommand: add it to the prefix & reset the current action
|
||||
prefix="${prefix}_$(_shtab_replace_nonword $this_word)"
|
||||
_set_parser_defaults
|
||||
fi
|
||||
|
||||
if [[ " ${current_option_strings[@]} " =~ " ${this_word} " ]]; then
|
||||
# a new action should be acquired (due to recognised option string or
|
||||
# no more input expected from current action);
|
||||
# the next positional action can fill in here
|
||||
_set_new_action $this_word false
|
||||
fi
|
||||
|
||||
if [[ "$current_action_nargs" != "*" ]] && \
|
||||
[[ "$current_action_nargs" != "+" ]] && \
|
||||
[[ "$current_action_nargs" != *"..." ]] && \
|
||||
(( $word_index + 1 - $current_action_args_start_index >= \
|
||||
$current_action_nargs )); then
|
||||
$current_action_is_positional && let "completed_positional_actions += 1"
|
||||
_set_new_action "pos_${completed_positional_actions}" true
|
||||
fi
|
||||
|
||||
let "word_index+=1"
|
||||
done
|
||||
|
||||
# Generate the completions
|
||||
|
||||
if [[ "${completing_word}" == -* ]]; then
|
||||
# optional argument started: use option strings
|
||||
COMPREPLY=( $(compgen -W "${current_option_strings[*]}" -- "${completing_word}") )
|
||||
else
|
||||
# use choices & compgen
|
||||
local IFS=$'\n'
|
||||
COMPREPLY=( $(compgen -W "${current_action_choices}" -- "${completing_word}") \
|
||||
$([ -n "${current_action_compgen}" ] \
|
||||
&& "${current_action_compgen}" "${completing_word}") )
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
complete -o filenames -F _shtab_edm_tool edm
|
||||
1738
tools/EVerest-main/applications/dependency_manager/src/edm_tool/edm.py
Executable file
1738
tools/EVerest-main/applications/dependency_manager/src/edm_tool/edm.py
Executable file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,61 @@
|
||||
set(ENV{EVEREST_EDM_WORKSPACE} {{ workspace["workspace"] }})
|
||||
set(CPM_USE_NAMED_CACHE_DIRECTORIES ON)
|
||||
{% for dep in checkout %}
|
||||
set(CPM_{{ dep["name"] }}_SOURCE "{{ dep["path"] }}")
|
||||
{% endfor %}
|
||||
{% for name, value in dependencies.items() %}
|
||||
if("{{name}}" IN_LIST EVEREST_EXCLUDE_DEPENDENCIES)
|
||||
message(STATUS "Excluding dependency {{name}}")
|
||||
{% if "cmake_condition" in value and value["cmake_condition"]|length > 0 %}
|
||||
elseif({{ value["cmake_condition"] }})
|
||||
{% else %}
|
||||
else()
|
||||
{% endif %}
|
||||
{% if value and "git" in value %}
|
||||
CPMAddPackage(
|
||||
NAME {{ name }}
|
||||
GIT_REPOSITORY {{ value["git"] }}
|
||||
{% if "git_tag" in value %}
|
||||
GIT_TAG {{ value["git_tag"] }}
|
||||
{% endif %}
|
||||
{% if "options" in value and value["options"]|length > 0 %}
|
||||
OPTIONS
|
||||
{{value["options"]|quote|join(" ")}}
|
||||
{% endif %}
|
||||
{% if "prevent_install" in value and value["prevent_install"] %}
|
||||
EXCLUDE_FROM_ALL YES
|
||||
{% endif %}
|
||||
)
|
||||
{% else %}
|
||||
find_package(
|
||||
{{ name }}
|
||||
{% if value and "components" in value and value["components"]|length > 0 %}
|
||||
COMPONENTS
|
||||
{{value["components"]|quote|join(" ")}}
|
||||
{% endif %}
|
||||
{% if not value or "optional" not in value or not value["optional"] %}
|
||||
REQUIRED
|
||||
{% endif %}
|
||||
)
|
||||
{% endif %}
|
||||
{% if value and "alias" in value %}
|
||||
if({{name}}_ADDED)
|
||||
add_library({{value["alias"]["name"]}} ALIAS {{value["alias"]["target"]}})
|
||||
endif()
|
||||
{% endif %}
|
||||
{% if "cmake_condition" in value and value["cmake_condition"]|length > 0 %}
|
||||
else()
|
||||
message(STATUS "Excluding dependency {{name}} based on cmake_condition")
|
||||
{% endif %}
|
||||
endif()
|
||||
|
||||
{% endfor %}
|
||||
|
||||
execute_process(
|
||||
COMMAND "${EVEREST_DEPENDENCY_MANAGER}" release --everest-dir ${PROJECT_SOURCE_DIR} --build-dir ${CMAKE_BINARY_DIR} --out ${CMAKE_BINARY_DIR}/release.json
|
||||
)
|
||||
|
||||
install(
|
||||
FILES "${CMAKE_BINARY_DIR}/release.json"
|
||||
DESTINATION "${CMAKE_INSTALL_SYSCONFDIR}/everest"
|
||||
)
|
||||
690
tools/EVerest-main/applications/devrd/devrd
Executable file
690
tools/EVerest-main/applications/devrd/devrd
Executable file
@@ -0,0 +1,690 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
# Default values
|
||||
EVEREST_TOOL_BRANCH="main"
|
||||
# Script directory - where devrd is located
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# .devcontainer directory is always relative to the script location
|
||||
DEVCONTAINER_DIR="${SCRIPT_DIR}/../../.devcontainer"
|
||||
# .env file is always in the .devcontainer directory (relative to script)
|
||||
ENV_FILE="${DEVCONTAINER_DIR}/.env"
|
||||
|
||||
# Function to load HOST_WORKSPACE_FOLDER from .env file
|
||||
# Usage: load_workspace_from_env [fallback]
|
||||
# If fallback is provided and workspace not found in .env, returns fallback
|
||||
# If no fallback provided, returns empty string (for use with ${var:-default} syntax)
|
||||
load_workspace_from_env() {
|
||||
local fallback="$1"
|
||||
if [ -f "$ENV_FILE" ]; then
|
||||
local workspace=$(grep "^HOST_WORKSPACE_FOLDER=" "$ENV_FILE" 2>/dev/null | cut -d'=' -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||
if [ -n "$workspace" ]; then
|
||||
echo "$workspace"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
# If fallback provided and workspace not found, return fallback
|
||||
if [ -n "$fallback" ]; then
|
||||
echo "$fallback"
|
||||
fi
|
||||
}
|
||||
|
||||
# HOST_WORKSPACE_FOLDER is the folder that is mapped to /workspace in the container
|
||||
# Priority: 1) Command line/env var, 2) .env file, 3) Current directory
|
||||
HOST_WORKSPACE_FOLDER="${HOST_WORKSPACE_FOLDER:-$(load_workspace_from_env)}"
|
||||
HOST_WORKSPACE_FOLDER="${HOST_WORKSPACE_FOLDER:-$(pwd)}"
|
||||
|
||||
# Docker Compose project name (defaults to workspace folder name with _devcontainer suffix, can be overridden)
|
||||
# This matches VSC's naming convention: {workspace-folder-name}_devcontainer-{service-name}-1
|
||||
# If needed (and not running in VSCode), can be changed by setting the DOCKER_COMPOSE_PROJECT_NAME environment variable.
|
||||
DOCKER_COMPOSE_PROJECT_NAME="${DOCKER_COMPOSE_PROJECT_NAME:-$(basename "$HOST_WORKSPACE_FOLDER" | tr \"A-Z\" \"a-z\")_devcontainer}"
|
||||
|
||||
|
||||
# Function to detect if running inside container
|
||||
is_inside_container() {
|
||||
# Check for /.dockerenv (standard Docker indicator)
|
||||
[ -f /.dockerenv ] && return 0
|
||||
# Check if /workspace exists and is mounted (devcontainer specific)
|
||||
[ -d /workspace ] && [ -f /workspace/.devcontainer/devrd ] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
# Function to show error when command is run from inside container
|
||||
show_inside_container_error() {
|
||||
local cmd_name="${1:-this command}"
|
||||
echo "✖ Error: This command cannot be run from inside the container"
|
||||
echo ""
|
||||
echo "You are currently inside the development container."
|
||||
echo "Please run this command from the host system instead:"
|
||||
echo ""
|
||||
echo " 1. Exit the container (type 'exit' or press Ctrl+D)"
|
||||
echo " 2. Run the command from your host terminal:"
|
||||
echo " ./devrd $cmd_name"
|
||||
echo ""
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Function to run docker compose with static project name
|
||||
# Compose files are always relative to the script's .devcontainer directory
|
||||
docker_compose() {
|
||||
docker compose -p "$DOCKER_COMPOSE_PROJECT_NAME" \
|
||||
-f "${DEVCONTAINER_DIR}/docker-compose.yml" \
|
||||
-f "${DEVCONTAINER_DIR}/general-devcontainer/docker-compose.devcontainer.yml" "$@"
|
||||
}
|
||||
|
||||
# Function to validate folder path
|
||||
validate_folder() {
|
||||
local folder="$1"
|
||||
|
||||
# Convert relative path to absolute
|
||||
case "$folder" in
|
||||
/*) ;; # Already absolute
|
||||
*) folder="$(cd "$folder" && pwd)" ;; # Convert relative to absolute
|
||||
esac
|
||||
|
||||
# Check if folder exists
|
||||
if [ ! -d "$folder" ]; then
|
||||
echo "Error: Folder '$folder' does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if folder is readable
|
||||
if [ ! -r "$folder" ]; then
|
||||
echo "Error: Folder '$folder' is not accessible (permission denied)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$folder"
|
||||
}
|
||||
|
||||
|
||||
# Function to generate .env file
|
||||
generate_env() {
|
||||
if is_inside_container; then
|
||||
show_inside_container_error "env"
|
||||
fi
|
||||
# Process command line options
|
||||
if [ -n "$ENV_OPTIONS" ]; then
|
||||
set -- $ENV_OPTIONS
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-v|--version)
|
||||
EVEREST_TOOL_BRANCH="$2"
|
||||
shift 2
|
||||
;;
|
||||
-w|--workspace)
|
||||
HOST_WORKSPACE_FOLDER="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
# Set workspace folder
|
||||
if [ -n "$HOST_WORKSPACE_FOLDER" ]; then
|
||||
HOST_WORKSPACE_FOLDER=$(validate_folder "$HOST_WORKSPACE_FOLDER")
|
||||
else
|
||||
HOST_WORKSPACE_FOLDER="$(pwd)"
|
||||
fi
|
||||
|
||||
# Get commit hash
|
||||
COMMIT_HASH=$(git ls-remote https://github.com/EVerest/everest-dev-environment.git ${EVEREST_TOOL_BRANCH} | cut -f1 2>/dev/null || echo "")
|
||||
|
||||
# Check if we need to update existing file
|
||||
local needs_update=false
|
||||
if [ -f "$ENV_FILE" ] && [ -s "$ENV_FILE" ]; then
|
||||
# File exists, check if we have options that require updates
|
||||
if [ -n "$ENV_OPTIONS" ]; then
|
||||
needs_update=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "$ENV_FILE" ] || [ ! -s "$ENV_FILE" ] || [ "$needs_update" = true ]; then
|
||||
cat > "$ENV_FILE" << EOF
|
||||
# Auto-generated by devrd script
|
||||
ORGANIZATION_ARG=EVerest
|
||||
REPOSITORY_HOST=github.com
|
||||
REPOSITORY_USER=git
|
||||
COMMIT_HASH=$COMMIT_HASH
|
||||
EVEREST_TOOL_BRANCH=$EVEREST_TOOL_BRANCH
|
||||
UID=$(id -u)
|
||||
GID=$(id -g)
|
||||
HOST_WORKSPACE_FOLDER=$HOST_WORKSPACE_FOLDER
|
||||
EOF
|
||||
if [ "$needs_update" = true ]; then
|
||||
echo "Updated .env file"
|
||||
else
|
||||
echo "Generated .env file"
|
||||
fi
|
||||
else
|
||||
echo "Found existing .env file"
|
||||
cat "$ENV_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to build the container
|
||||
build_container() {
|
||||
if is_inside_container; then
|
||||
show_inside_container_error "build"
|
||||
fi
|
||||
echo "Building development container..."
|
||||
docker_compose --profile all build
|
||||
}
|
||||
|
||||
# Function to get actual port mapping from docker compose
|
||||
get_port_mapping() {
|
||||
local service_name=$1
|
||||
local internal_port=$2
|
||||
|
||||
# Get the actual port mapping from docker compose
|
||||
local port_mapping=$(docker_compose port $service_name $internal_port 2>/dev/null)
|
||||
|
||||
if [ -n "$port_mapping" ]; then
|
||||
# Extract just the host port (remove the host part)
|
||||
echo "$port_mapping" | sed 's/.*://'
|
||||
else
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Function to display container links and tips
|
||||
display_container_status() {
|
||||
echo ""
|
||||
echo "Container Services Summary:"
|
||||
echo "=============================="
|
||||
|
||||
# Get actual port mappings from docker compose
|
||||
local mqtt_explorer_port=$(get_port_mapping mqtt-explorer 4000)
|
||||
local steve_http_port=$(get_port_mapping steve 8180)
|
||||
|
||||
# Display links with actual ports
|
||||
if [ -n "$mqtt_explorer_port" ]; then
|
||||
echo "MQTT Explorer: http://localhost:$mqtt_explorer_port"
|
||||
else
|
||||
echo "MQTT Explorer: currently not running"
|
||||
fi
|
||||
|
||||
if [ -n "$steve_http_port" ]; then
|
||||
echo "Steve (HTTP): http://localhost:$steve_http_port"
|
||||
else
|
||||
echo "Steve (HTTP): currently not running"
|
||||
fi
|
||||
|
||||
# Check if Node-RED is running
|
||||
if docker_compose ps | grep -q "nodered"; then
|
||||
echo "Node-RED UI: http://localhost:1880/ui"
|
||||
else
|
||||
echo "Node-RED UI: currently not running"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Tips:"
|
||||
echo " • MQTT Explorer: Browse and debug MQTT topics"
|
||||
echo " • Steve: OCPP backend management interface"
|
||||
echo " • Node-RED: Web-based UI for SIL simulations"
|
||||
echo " • Use './devrd prompt' to access the container shell"
|
||||
echo " • Use './devrd nodered-flows' to see available flows"
|
||||
echo ""
|
||||
}
|
||||
|
||||
|
||||
# Function to start containers using profiles
|
||||
start_compose_profile() {
|
||||
if is_inside_container; then
|
||||
show_inside_container_error "start"
|
||||
fi
|
||||
local profile_or_service="$1"
|
||||
|
||||
if [ -n "$profile_or_service" ]; then
|
||||
echo "Starting containers for profile/service: $profile_or_service..."
|
||||
docker_compose --profile "$profile_or_service" up -d
|
||||
else
|
||||
echo "Starting the development container and all services..."
|
||||
docker_compose --profile all up -d
|
||||
fi
|
||||
|
||||
# Display workspace mapping
|
||||
echo "Workspace mapping: $HOST_WORKSPACE_FOLDER → /workspace"
|
||||
echo ""
|
||||
|
||||
# Display container links
|
||||
display_container_status
|
||||
}
|
||||
|
||||
# Function to stop containers using profiles or container name pattern
|
||||
stop_compose_profile() {
|
||||
if is_inside_container; then
|
||||
show_inside_container_error "stop"
|
||||
fi
|
||||
local profile_or_pattern="$1"
|
||||
|
||||
if [ -n "$profile_or_pattern" ]; then
|
||||
# Check if it's a valid profile name
|
||||
case "$profile_or_pattern" in
|
||||
mqtt|ocpp|sil|all)
|
||||
echo "Stopping containers for profile: $profile_or_pattern..."
|
||||
docker_compose --profile "$profile_or_pattern" stop
|
||||
;;
|
||||
*)
|
||||
# Treat as container name pattern
|
||||
echo "Stopping containers matching pattern: $profile_or_pattern..."
|
||||
local containers=$(docker ps --format "{{.Names}}" | grep -E "($profile_or_pattern)" || true)
|
||||
if [ -z "$containers" ]; then
|
||||
echo "No running containers found matching pattern: $profile_or_pattern"
|
||||
return 1
|
||||
fi
|
||||
echo "$containers" | while read container; do
|
||||
echo "Stopping container: $container"
|
||||
docker stop "$container" 2>/dev/null || echo "Failed to stop container: $container"
|
||||
done
|
||||
;;
|
||||
esac
|
||||
else
|
||||
echo "Stopping the development container and all services..."
|
||||
docker_compose --profile all stop
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to purge everything
|
||||
purge_everything() {
|
||||
if is_inside_container; then
|
||||
show_inside_container_error "purge"
|
||||
fi
|
||||
local purge_pattern="${1:-$(basename "$HOST_WORKSPACE_FOLDER")}"
|
||||
local current_project="$(basename "$HOST_WORKSPACE_FOLDER")"
|
||||
echo "Purging all devcontainer resources for pattern: $purge_pattern..."
|
||||
|
||||
# Only use docker_compose down if purging the current project
|
||||
if [ "$purge_pattern" = "$current_project" ]; then
|
||||
echo "Stopping and removing containers for current project..."
|
||||
docker_compose down -v --remove-orphans
|
||||
else
|
||||
echo "Purging resources for different project pattern: $purge_pattern"
|
||||
echo "Skipping docker-compose cleanup (not current project)"
|
||||
fi
|
||||
|
||||
# Remove all images related to the project
|
||||
echo "Removing devcontainer images..."
|
||||
docker images --format "table {{.Repository}}:{{.Tag}}" | grep -E "($purge_pattern)" | awk '{print $1}' | xargs -r docker rmi -f
|
||||
|
||||
# Remove all volumes related to the project (with force if needed)
|
||||
echo "Removing devcontainer volumes..."
|
||||
docker volume ls --format "{{.Name}}" | grep -E "($purge_pattern)" | while read volume; do
|
||||
echo "Removing volume: $volume"
|
||||
docker volume rm -f "$volume" 2>/dev/null || echo "Volume $volume could not be removed (may be in use)"
|
||||
done
|
||||
|
||||
# Ask user if they want to purge CPM cache volume
|
||||
echo ""
|
||||
echo "CPM source cache volume (everest-cpm-source-cache) is shared across all workspaces."
|
||||
read -p "Do you want to purge the CPM cache volume as well? [y/N]: " purge_cache
|
||||
purge_cache="${purge_cache:-N}"
|
||||
if [[ "$purge_cache" =~ ^[Yy]$ ]]; then
|
||||
echo "Removing CPM cache volume..."
|
||||
if docker volume rm everest-cpm-source-cache 2>/dev/null; then
|
||||
echo "✔ CPM cache volume removed"
|
||||
else
|
||||
echo "⚠ CPM cache volume could not be removed (may be in use or not exist)"
|
||||
fi
|
||||
else
|
||||
echo "Keeping CPM cache volume (will be reused for faster builds)"
|
||||
fi
|
||||
|
||||
# Remove any dangling images and containers
|
||||
echo ""
|
||||
echo "Cleaning up dangling resources..."
|
||||
docker system prune -f
|
||||
|
||||
echo ""
|
||||
echo "✔ Purge complete! All devcontainer resources have been removed."
|
||||
}
|
||||
|
||||
# Function to check if SSH agent is running
|
||||
check_ssh_agent() {
|
||||
if [ -z "$SSH_AUTH_SOCK" ] || ! ssh-add -l >/dev/null 2>&1; then
|
||||
echo "Error: SSH agent is not running or no keys are loaded."
|
||||
echo "Please start the SSH agent and add your keys:"
|
||||
echo " eval \$(ssh-agent)"
|
||||
echo " ssh-add ~/.ssh/id_rsa # or your private key"
|
||||
echo "Or if you're using a different key:"
|
||||
echo " ssh-add ~/.ssh/your_private_key"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to execute a command in the container
|
||||
exec_devcontainer() {
|
||||
if is_inside_container; then
|
||||
echo "✖ You're already inside the container."
|
||||
echo ""
|
||||
echo "To run a command, just execute it directly:"
|
||||
if [ $# -gt 0 ]; then
|
||||
echo " $@"
|
||||
else
|
||||
echo " <your-command>"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
echo "Checking if development container is running..."
|
||||
|
||||
# Check if the devcontainer service is running
|
||||
if ! docker_compose ps devcontainer | grep -q "Up"; then
|
||||
echo "Error: Development container is not running."
|
||||
echo "Please start the container first with: ./devrd start"
|
||||
echo "Or build and start with: ./devrd build && ./devrd start"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Executing command in development container..."
|
||||
run_in_devcontainer "$@"
|
||||
}
|
||||
|
||||
# Function to get a shell prompt in the container
|
||||
prompt_devcontainer() {
|
||||
if is_inside_container; then
|
||||
echo "✖ You're already inside the container shell."
|
||||
exit 1
|
||||
fi
|
||||
echo "Starting shell in development container..."
|
||||
exec_devcontainer /bin/bash
|
||||
}
|
||||
|
||||
# Helper function to check if Node-RED is running and get the URL
|
||||
# Sets nodered_url variable and returns 0 if running, 1 if not
|
||||
check_nodered_running() {
|
||||
if is_inside_container; then
|
||||
nodered_url="http://nodered:1880"
|
||||
curl -s "$nodered_url/flows" >/dev/null 2>&1 && return 0
|
||||
else
|
||||
nodered_url="http://localhost:1880"
|
||||
docker_compose ps | grep -q "nodered" && return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# Helper function to execute a command in the container
|
||||
# Usage: run_in_devcontainer [--no-tty] <command> [args...]
|
||||
# Executes directly if inside container, via docker_compose exec if on host
|
||||
# No error checking - assumes container is running when called from host
|
||||
# Use --no-tty for non-interactive commands that need output capture
|
||||
run_in_devcontainer() {
|
||||
local no_tty=false
|
||||
if [ "$1" = "--no-tty" ]; then
|
||||
no_tty=true
|
||||
shift
|
||||
fi
|
||||
|
||||
if is_inside_container; then
|
||||
"$@"
|
||||
else
|
||||
if [ "$no_tty" = true ]; then
|
||||
docker_compose exec -T devcontainer "$@"
|
||||
else
|
||||
docker_compose exec devcontainer "$@"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to list available flows
|
||||
list_nodered_flows() {
|
||||
echo ""
|
||||
echo "Available Node-RED Flows:"
|
||||
echo "============================="
|
||||
|
||||
# Check if Node-RED is running
|
||||
if ! check_nodered_running; then
|
||||
echo "✖ Node-RED container is not running"
|
||||
echo "Please start with './devrd start' first"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Find all flow files in the workspace
|
||||
local flows
|
||||
if is_inside_container; then
|
||||
flows=$(find /workspace -name "*-flow.json" -type f 2>/dev/null | sort)
|
||||
else
|
||||
flows=$(docker_compose exec -T devcontainer find /workspace -name "*-flow.json" -type f 2>/dev/null | sort)
|
||||
fi
|
||||
|
||||
if [ -z "$flows" ]; then
|
||||
echo "No flow files found in workspace"
|
||||
echo ""
|
||||
echo "Expected pattern: *-flow.json"
|
||||
echo "Search location: /workspace"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "Found $(echo "$flows" | wc -l) flow file(s):"
|
||||
echo ""
|
||||
for flow in $flows; do
|
||||
# Remove /workspace/ prefix to get relative path from workspace root
|
||||
local relative_path=$(echo "$flow" | sed 's|^/workspace/||')
|
||||
echo " Path: $relative_path"
|
||||
done
|
||||
echo ""
|
||||
echo "Usage: ./devrd flow <flow-file-path>"
|
||||
echo "Example: ./devrd flow EVerest/config/nodered/config-sil-dc-flow.json"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Function to switch flow using REST API
|
||||
switch_nodered_flow() {
|
||||
local flow_path="$1"
|
||||
|
||||
if [ -z "$flow_path" ]; then
|
||||
echo "Error: Please specify a flow file path"
|
||||
echo ""
|
||||
echo "Available flows:"
|
||||
list_nodered_flows
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check if Node-RED is running
|
||||
if ! check_nodered_running; then
|
||||
echo "✖ Node-RED container is not running"
|
||||
echo "Please start with './devrd start' first"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Construct full path in container
|
||||
local full_path="/workspace/$flow_path"
|
||||
|
||||
# Check if file exists and is readable, then copy to temp file
|
||||
if ! run_in_devcontainer --no-tty test -r "$full_path"; then
|
||||
echo "✖ Flow file not found or not readable: $flow_path"
|
||||
echo ""
|
||||
echo "Available flows:"
|
||||
list_nodered_flows
|
||||
return 1
|
||||
fi
|
||||
# Copy flow to temporary file
|
||||
run_in_devcontainer --no-tty cat "$full_path" > /tmp/flows.json
|
||||
|
||||
echo "Switching Node-RED to flow: $(basename "$flow_path")"
|
||||
echo "Source: $flow_path"
|
||||
|
||||
# Process environment variables in the flow JSON
|
||||
# Replace "broker": "localhost" with "broker": "mqtt-server"
|
||||
sed -i 's/"broker": "localhost"/"broker": "mqtt-server"/g' /tmp/flows.json
|
||||
|
||||
# Deploy flow via Node-RED REST API
|
||||
echo "Deploying flow via Node-RED API..."
|
||||
local response=$(curl -s -w "%{http_code}" -X POST "$nodered_url/flows" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @/tmp/flows.json)
|
||||
|
||||
local http_code="${response: -3}"
|
||||
|
||||
if [ "$http_code" = "200" ] || [ "$http_code" = "204" ]; then
|
||||
echo "✔ Node-RED flow deployed successfully via API!"
|
||||
if is_inside_container; then
|
||||
echo "Access at: http://nodered:1880/ui (from container) or http://localhost:1880/ui (from host)"
|
||||
else
|
||||
echo "Access at: http://localhost:1880/ui"
|
||||
fi
|
||||
else
|
||||
echo "✖ Failed to deploy flow via API (HTTP $http_code)"
|
||||
echo "Response: ${response%???}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Clean up temporary file
|
||||
rm -f /tmp/flows.json
|
||||
}
|
||||
|
||||
|
||||
# Function to display help
|
||||
show_help() {
|
||||
echo "Usage: $0 [COMMAND] [OPTIONS]"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " env Generate .env file with repository information (default)"
|
||||
echo " build Build the development container"
|
||||
echo " start [profile] Start containers (profiles: mqtt, ocpp, sil, all)"
|
||||
echo " stop [profile|pattern] Stop containers by profile (mqtt, ocpp, sil, all) or container name pattern"
|
||||
echo " purge [pattern] Remove all devcontainer resources (containers, images, volumes)"
|
||||
echo " Optional pattern to match (default: current folder name)"
|
||||
echo " exec <command> Execute a command in the development container (requires the container to be running)"
|
||||
echo " prompt Get a shell prompt in the development container (requires the container to be running)"
|
||||
echo " flows List available flows"
|
||||
echo " flow <path> Switch to specific flow file"
|
||||
echo ""
|
||||
echo "Options (for env command only):"
|
||||
echo " -v, --version VERSION Everest tool branch (default: $EVEREST_TOOL_BRANCH, preserves existing if not specified)"
|
||||
echo " -w, --workspace DIR Workspace directory to map to /workspace in container (default: current directory)"
|
||||
echo " --help Display this help message"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 env # Generate .env file with repository information"
|
||||
echo " $0 build # Build container"
|
||||
echo " $0 start # Start all containers"
|
||||
echo " $0 start sil # Start SIL simulation tools (Node-RED, MQTT Explorer)"
|
||||
echo " $0 start ocpp # Start OCPP services (Steve, OCPP DB, MQTT)"
|
||||
echo " $0 start mqtt # Start only MQTT server"
|
||||
echo " $0 stop sil # Stop SIL simulation tools"
|
||||
echo " $0 stop ev-ws # Stop all containers matching pattern 'ev-ws'"
|
||||
echo " $0 purge # Remove all devcontainer resources for current folder"
|
||||
echo " $0 purge my-project # Remove all devcontainer resources matching 'my-project'"
|
||||
echo " $0 exec ls -la # Execute command in container"
|
||||
echo " $0 prompt # Get shell prompt in container"
|
||||
echo " $0 flows # List available flows"
|
||||
echo " $0 flow <path> # Switch to specific Node-RED flow file"
|
||||
|
||||
echo " $0 -w ~/Documents # Map Documents folder to /workspace"
|
||||
echo " $0 --workspace /opt/tools # Map tools folder to /workspace"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Parse command line arguments
|
||||
COMMAND="env"
|
||||
ENV_OPTIONS=""
|
||||
|
||||
# First pass: collect all options
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
-v|--version|-w|--workspace)
|
||||
# Store env-specific options for later use
|
||||
ENV_OPTIONS="$ENV_OPTIONS $1 $2"
|
||||
shift 2
|
||||
;;
|
||||
--help)
|
||||
show_help
|
||||
;;
|
||||
exec)
|
||||
COMMAND="$1"
|
||||
shift
|
||||
# For exec, pass all remaining arguments to the exec function
|
||||
break
|
||||
;;
|
||||
env|build|prompt|flows)
|
||||
COMMAND="$1"
|
||||
shift
|
||||
# Don't break here, continue to collect more options
|
||||
;;
|
||||
flow)
|
||||
COMMAND="$1"
|
||||
shift
|
||||
# For flow, pass any remaining arguments as flow path
|
||||
break
|
||||
;;
|
||||
purge)
|
||||
COMMAND="$1"
|
||||
shift
|
||||
# For purge, pass any remaining arguments as pattern
|
||||
break
|
||||
;;
|
||||
start|stop)
|
||||
COMMAND="$1"
|
||||
shift
|
||||
# For start/stop, pass any remaining arguments as container name
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
show_help
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Execute the command
|
||||
case $COMMAND in
|
||||
env)
|
||||
# Check SSH agent for Git operations
|
||||
check_ssh_agent
|
||||
generate_env
|
||||
;;
|
||||
build)
|
||||
# Only generate env if .env file doesn't exist or is empty
|
||||
if [ ! -f "$ENV_FILE" ] || [ ! -s "$ENV_FILE" ]; then
|
||||
# Check SSH agent for Git operations
|
||||
check_ssh_agent
|
||||
generate_env
|
||||
fi
|
||||
build_container
|
||||
;;
|
||||
start)
|
||||
# Only generate env if .env file doesn't exist or is empty
|
||||
if [ ! -f "$ENV_FILE" ] || [ ! -s "$ENV_FILE" ]; then
|
||||
# Check SSH agent for Git operations
|
||||
check_ssh_agent
|
||||
generate_env
|
||||
fi
|
||||
start_compose_profile "$@"
|
||||
;;
|
||||
stop)
|
||||
stop_compose_profile "$@"
|
||||
;;
|
||||
purge)
|
||||
purge_everything "$@"
|
||||
;;
|
||||
exec)
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Error: exec command requires arguments"
|
||||
show_help
|
||||
fi
|
||||
exec_devcontainer "$@"
|
||||
;;
|
||||
prompt)
|
||||
prompt_devcontainer
|
||||
;;
|
||||
flows)
|
||||
list_nodered_flows
|
||||
;;
|
||||
flow)
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Error: flow command requires a flow file path"
|
||||
show_help
|
||||
fi
|
||||
switch_nodered_flow "$1"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown command: $COMMAND"
|
||||
show_help
|
||||
;;
|
||||
esac
|
||||
97
tools/EVerest-main/applications/devrd/devrd-completion.bash
Executable file
97
tools/EVerest-main/applications/devrd/devrd-completion.bash
Executable file
@@ -0,0 +1,97 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Bash completion for devrd script
|
||||
# Source this file or add to your .bashrc to enable completion
|
||||
|
||||
_devrd_completion() {
|
||||
local cur prev opts cmds
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
|
||||
# Available commands
|
||||
cmds="install env build start stop prompt purge exec flows flow"
|
||||
|
||||
# Available options
|
||||
opts="-v --version -w --workspace --help"
|
||||
|
||||
# Function to get available Node-RED flows dynamically
|
||||
_get_nodered_flows() {
|
||||
# Get the current project name (same logic as devrd script)
|
||||
local project_name="${DOCKER_COMPOSE_PROJECT_NAME:-$(basename "$(pwd)")_devcontainer}"
|
||||
|
||||
# Check if we're in the right directory and container is running
|
||||
if [ -f "devrd" ] && docker compose -p "$project_name" -f .devcontainer/docker-compose.yml -f .devcontainer/general-devcontainer/docker-compose.devcontainer.yml ps devcontainer | grep -q "Up"; then
|
||||
# Get flows from the container and return full paths (relative to workspace)
|
||||
docker compose -p "$project_name" -f .devcontainer/docker-compose.yml -f .devcontainer/general-devcontainer/docker-compose.devcontainer.yml exec -T devcontainer find /workspace -name "*-flow.json" -type f 2>/dev/null | sed 's|/workspace/||' | sort
|
||||
else
|
||||
# Fallback to common flow file paths
|
||||
echo "EVerest/config/nodered/config-sil-dc-flow.json"
|
||||
echo "EVerest/config/nodered/config-sil-dc-bpt-flow.json"
|
||||
echo "EVerest/config/nodered/config-sil-energy-management-flow.json"
|
||||
echo "EVerest/config/nodered/config-sil-two-evse-flow.json"
|
||||
echo "EVerest/config/nodered/config-sil-flow.json"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to get available container names
|
||||
_get_container_names() {
|
||||
echo "mqtt ocpp sil"
|
||||
}
|
||||
|
||||
# If the previous word is an option that takes an argument, complete based on the option
|
||||
case "$prev" in
|
||||
|
||||
-v|--version)
|
||||
# Complete with common version patterns
|
||||
COMPREPLY=( $(compgen -W "main master develop release/1.0 release/1.1" -- "$cur") )
|
||||
return 0
|
||||
;;
|
||||
-w|--workspace)
|
||||
# Complete directories
|
||||
COMPREPLY=( $(compgen -d -- "$cur") )
|
||||
return 0
|
||||
;;
|
||||
flow)
|
||||
# Complete with available flow file paths dynamically
|
||||
local flows
|
||||
flows=$(_get_nodered_flows)
|
||||
COMPREPLY=( $(compgen -W "$flows" -- "$cur") )
|
||||
return 0
|
||||
;;
|
||||
start|stop)
|
||||
# Complete with available container names
|
||||
local containers
|
||||
containers=$(_get_container_names)
|
||||
COMPREPLY=( $(compgen -W "$containers" -- "$cur") )
|
||||
return 0
|
||||
;;
|
||||
exec)
|
||||
# For exec command, complete with common commands
|
||||
COMPREPLY=( $(compgen -W "ls pwd cd cmake ninja make" -- "$cur") )
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
# If we're completing the first word (command), show commands
|
||||
if [ $COMP_CWORD -eq 1 ]; then
|
||||
COMPREPLY=( $(compgen -W "$cmds" -- "$cur") )
|
||||
return 0
|
||||
fi
|
||||
|
||||
# If we're completing an option, show options
|
||||
if [[ "$cur" == -* ]]; then
|
||||
COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
|
||||
return 0
|
||||
fi
|
||||
|
||||
# For other cases, complete with files/directories
|
||||
COMPREPLY=( $(compgen -f -- "$cur") )
|
||||
return 0
|
||||
}
|
||||
|
||||
# Register the completion function
|
||||
complete -F _devrd_completion devrd
|
||||
complete -F _devrd_completion ./devrd
|
||||
complete -F _devrd_completion ../devrd
|
||||
complete -F _devrd_completion ./applications/devrd/devrd
|
||||
90
tools/EVerest-main/applications/devrd/devrd-completion.zsh
Executable file
90
tools/EVerest-main/applications/devrd/devrd-completion.zsh
Executable file
@@ -0,0 +1,90 @@
|
||||
#!/bin/zsh
|
||||
|
||||
# Zsh completion for devrd script
|
||||
# Source this file or add to your .zshrc to enable completion
|
||||
|
||||
_devrd_completion() {
|
||||
local context state line
|
||||
typeset -A opt_args
|
||||
|
||||
# Available commands
|
||||
local commands=(
|
||||
'env:Generate .env file with repository information'
|
||||
'build:Build the development container'
|
||||
'start:Start containers (profiles: mqtt, ocpp, sil)'
|
||||
'stop:Stop containers (profiles: mqtt, ocpp, sil)'
|
||||
'purge:Remove all devcontainer resources (containers, images, volumes)'
|
||||
'exec:Execute a command in the container'
|
||||
'prompt:Get a shell prompt in the container'
|
||||
'flows:List available flows'
|
||||
'flow:Switch to specific flow file'
|
||||
)
|
||||
|
||||
# Available options
|
||||
local options=(
|
||||
'-v[Everest tool branch]:version:'
|
||||
'--version[Everest tool branch]:version:'
|
||||
'-w[Workspace directory]:directory:_files -/'
|
||||
'--workspace[Workspace directory]:directory:_files -/'
|
||||
'--help[Display help message]'
|
||||
)
|
||||
|
||||
# Function to get available Node-RED flows dynamically
|
||||
_get_nodered_flows() {
|
||||
# Get the current project name (same logic as devrd script)
|
||||
local project_name="${DOCKER_COMPOSE_PROJECT_NAME:-$(basename "$(pwd)")_devcontainer}"
|
||||
|
||||
# Check if we're in the right directory and container is running
|
||||
if [ -f "devrd" ] && docker compose -p "$project_name" -f .devcontainer/docker-compose.yml -f .devcontainer/general-devcontainer/docker-compose.devcontainer.yml ps devcontainer | grep -q "Up"; then
|
||||
# Get flows from the container and return full paths (relative to workspace)
|
||||
docker compose -p "$project_name" -f .devcontainer/docker-compose.yml -f .devcontainer/general-devcontainer/docker-compose.devcontainer.yml exec -T devcontainer find /workspace -name "*-flow.json" -type f 2>/dev/null | sed 's|/workspace/||' | sort
|
||||
else
|
||||
# Fallback to common flow file paths
|
||||
echo "EVerest/config/nodered/config-sil-dc-flow.json"
|
||||
echo "EVerest/config/nodered/config-sil-dc-bpt-flow.json"
|
||||
echo "EVerest/config/nodered/config-sil-energy-management-flow.json"
|
||||
echo "EVerest/config/nodered/config-sil-two-evse-flow.json"
|
||||
echo "EVerest/config/nodered/config-sil-flow.json"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to get available container names
|
||||
_get_container_names() {
|
||||
echo "mqtt ocpp sil"
|
||||
}
|
||||
|
||||
# Main completion logic
|
||||
_arguments -C \
|
||||
"$options[@]" \
|
||||
"1: :{_describe 'commands' commands}" \
|
||||
"*::arg:->args"
|
||||
|
||||
case $state in
|
||||
args)
|
||||
case $line[1] in
|
||||
flow)
|
||||
_values 'flow files' $(_get_nodered_flows)
|
||||
;;
|
||||
start|stop)
|
||||
_values 'profiles' $(_get_container_names)
|
||||
;;
|
||||
exec)
|
||||
_values 'commands' 'ls' 'pwd' 'cd' 'cmake' 'ninja' 'make'
|
||||
;;
|
||||
purge)
|
||||
_files
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Register the completion function
|
||||
if command -v compdef >/dev/null 2>&1; then
|
||||
compdef _devrd_completion devrd
|
||||
compdef _devrd_completion ./devrd
|
||||
compdef _devrd_completion ../devrd
|
||||
compdef _devrd_completion ./applications/devrd/devrd
|
||||
else
|
||||
echo "Warning: zsh completion system not loaded. Add 'autoload -U compinit && compinit' to your .zshrc"
|
||||
fi
|
||||
3
tools/EVerest-main/applications/everest_dev_tool/.gitignore
vendored
Normal file
3
tools/EVerest-main/applications/everest_dev_tool/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
build
|
||||
__pycache__
|
||||
*.egg-info
|
||||
201
tools/EVerest-main/applications/everest_dev_tool/LICENSE
Normal file
201
tools/EVerest-main/applications/everest_dev_tool/LICENSE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,9 @@
|
||||
[project]
|
||||
name = "everest_dev_tool"
|
||||
version = "0.1.0"
|
||||
description = "This tool provides helpful commands to setup/control your dev environment"
|
||||
license = { text="Apache-2.0" }
|
||||
dependencies = []
|
||||
|
||||
[project.scripts]
|
||||
everest = "everest_dev_tool:main"
|
||||
@@ -0,0 +1,9 @@
|
||||
__version__ = "0.1.0"
|
||||
|
||||
from . import parser
|
||||
|
||||
def get_parser():
|
||||
return parser.get_parser(__version__)
|
||||
|
||||
def main():
|
||||
parser.main(get_parser())
|
||||
@@ -0,0 +1,30 @@
|
||||
import argparse
|
||||
import subprocess
|
||||
|
||||
def clone_handler(args: argparse.Namespace):
|
||||
log = args.logger
|
||||
|
||||
log.info(
|
||||
f"Cloning repository:\n"
|
||||
f" Method: {args.method}\n"
|
||||
f" Host: {args.host}\n"
|
||||
f" SSH User (if ssh): {args.ssh_user}\n"
|
||||
f" Organization: {args.organization}\n"
|
||||
f" Repository Name: {args.repository_name}\n"
|
||||
f" Branch: {args.branch}\n"
|
||||
)
|
||||
repository_url = ""
|
||||
if args.method == 'https':
|
||||
repository_url = f"https://{args.host}/"
|
||||
else:
|
||||
repository_url = f"{args.ssh_user}@{args.host}:"
|
||||
repository_url = repository_url + f"{ args.organization }/{ args.repository_name }.git"
|
||||
|
||||
cmd_args = ["git", "clone", "-b", args.branch, repository_url]
|
||||
|
||||
log.debug(f"Command to execute: {' '.join(cmd_args)}")
|
||||
|
||||
if args.dry:
|
||||
log.info(f"Dry run: Would execute: {' '.join(cmd_args)}")
|
||||
else:
|
||||
subprocess.run(cmd_args, check=True)
|
||||
@@ -0,0 +1,83 @@
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
|
||||
from . import git_handlers
|
||||
|
||||
log = logging.getLogger("EVerest's Development Tool")
|
||||
|
||||
def get_parser(version: str) -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter,
|
||||
description="EVerest's Development Tool",)
|
||||
parser.add_argument('--version', action='version', version=f'%(prog)s { version }')
|
||||
parser.add_argument('-v', '--verbose', action='store_true', help="Verbose output")
|
||||
parser.set_defaults(action_handler=lambda _: parser.print_help())
|
||||
|
||||
subparsers = parser.add_subparsers(help="available commands")
|
||||
|
||||
# Git related commands
|
||||
clone_parser = subparsers.add_parser("clone", help="Clone a repository", add_help=True)
|
||||
clone_parser.add_argument('-v', '--verbose', action='store_true', help="Verbose output")
|
||||
default_git_host = os.environ.get("EVEREST_DEV_TOOL_DEFAULT_GIT_HOST", "github.com")
|
||||
clone_parser.add_argument(
|
||||
'--host',
|
||||
default=default_git_host,
|
||||
help=(
|
||||
"Git host to use, default is 'github.com' "
|
||||
"(can be overridden by the environment variable "
|
||||
"EVEREST_DEV_TOOL_DEFAULT_GIT_HOST)"
|
||||
),
|
||||
)
|
||||
default_git_method = os.environ.get("EVEREST_DEV_TOOL_DEFAULT_GIT_METHOD", "ssh")
|
||||
clone_parser.add_argument(
|
||||
'--method',
|
||||
default=default_git_method,
|
||||
choices=['https', 'ssh'],
|
||||
help=(
|
||||
"Git method to use, default is 'ssh' "
|
||||
"(can be overridden by the environment variable "
|
||||
"EVEREST_DEV_TOOL_DEFAULT_GIT_METHOD)"
|
||||
)
|
||||
)
|
||||
default_git_ssh_user = os.environ.get("EVEREST_DEV_TOOL_DEFAULT_GIT_SSH_USER", "git")
|
||||
clone_parser.add_argument(
|
||||
'--ssh-user',
|
||||
default=default_git_ssh_user,
|
||||
help=(
|
||||
"SSH user to use, default is 'git' "
|
||||
"(can be overridden by the environment variable "
|
||||
"EVEREST_DEV_TOOL_DEFAULT_GIT_SSH_USER)"
|
||||
)
|
||||
)
|
||||
default_git_organization = os.environ.get("EVEREST_DEV_TOOL_DEFAULT_GIT_ORGANIZATION", "EVerest")
|
||||
clone_parser.add_argument(
|
||||
'--organization', '--org',
|
||||
default=default_git_organization,
|
||||
help=(
|
||||
"Github Organization name, default is 'EVerest'"
|
||||
" (can be overridden by the environment variable "
|
||||
"EVEREST_DEV_TOOL_DEFAULT_GIT_ORGANIZATION)"
|
||||
)
|
||||
)
|
||||
clone_parser.add_argument('--branch', '-b', default="main", help="Branch to checkout, default is 'main'")
|
||||
clone_parser.add_argument('--dry', action='store_true', help="Dry run, do not execute the clone command")
|
||||
clone_parser.add_argument("repository_name", help="Name of the repository to clone")
|
||||
clone_parser.set_defaults(action_handler=git_handlers.clone_handler)
|
||||
|
||||
return parser
|
||||
|
||||
def setup_logging(verbose: bool):
|
||||
if verbose:
|
||||
log.setLevel(logging.DEBUG)
|
||||
else:
|
||||
log.setLevel(logging.INFO)
|
||||
console_handler = logging.StreamHandler()
|
||||
log.addHandler(console_handler)
|
||||
|
||||
def main(parser: argparse.ArgumentParser):
|
||||
args = parser.parse_args()
|
||||
args.logger = log
|
||||
|
||||
setup_logging(args.verbose)
|
||||
|
||||
args.action_handler(args)
|
||||
@@ -0,0 +1,73 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
if(DEFINED EVEREST_IO_WITH_MQTT AND NOT EVEREST_IO_WITH_MQTT)
|
||||
message(FATAL_ERROR "pionix_chargebridge requires MQTT support in everest::io. "
|
||||
"Set EVEREST_IO_WITH_MQTT=ON or disable EVEREST_BUILD_APPLICATIONS.")
|
||||
endif()
|
||||
|
||||
find_package(ryml QUIET)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
|
||||
add_executable(pionix_chargebridge
|
||||
src/everest_api/api_connector.cpp
|
||||
src/everest_api/evse_bsp_api.cpp
|
||||
src/everest_api/ovm_api.cpp
|
||||
src/everest_api/ev_bsp_api.cpp
|
||||
|
||||
src/firmware_update/sync_fw_updater.cpp
|
||||
|
||||
src/utilities/filesystem.cpp
|
||||
src/utilities/logging.cpp
|
||||
src/utilities/parse_config.cpp
|
||||
src/utilities/print_config.cpp
|
||||
src/utilities/string.cpp
|
||||
src/utilities/symlink.cpp
|
||||
src/utilities/sync_udp_client.cpp
|
||||
src/utilities/type_converters.cpp
|
||||
|
||||
src/can_bridge.cpp
|
||||
src/charge_bridge.cpp
|
||||
src/bsp_bridge.cpp
|
||||
src/gpio_bridge.cpp
|
||||
src/heartbeat_service.cpp
|
||||
src/plc_bridge.cpp
|
||||
src/serial_bridge.cpp
|
||||
src/discovery.cpp
|
||||
|
||||
main.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(pionix_chargebridge
|
||||
everest::io
|
||||
everest::everest_api_types
|
||||
nlohmann_json::nlohmann_json
|
||||
ryml::ryml
|
||||
)
|
||||
|
||||
target_include_directories(pionix_chargebridge
|
||||
PRIVATE include
|
||||
PRIVATE shared
|
||||
)
|
||||
|
||||
set(cb_firmware_binary config/firmware/charge-bridge-fw_complete.cbfw)
|
||||
|
||||
add_custom_command(
|
||||
TARGET pionix_chargebridge
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${cb_firmware_binary}"
|
||||
"$<TARGET_FILE_DIR:pionix_chargebridge>/"
|
||||
COMMENT "Copying Pionix ChargeBridge firmware binary..."
|
||||
)
|
||||
|
||||
|
||||
install (TARGETS pionix_chargebridge)
|
||||
install (FILES "${CMAKE_CURRENT_SOURCE_DIR}/${cb_firmware_binary}" DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/chargebridge/firmware)
|
||||
install (FILES "${CMAKE_CURRENT_SOURCE_DIR}/config/config-CB-EVAL.yaml" DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/chargebridge RENAME "config-CB-EVAL.yaml-example")
|
||||
install (FILES "${CMAKE_CURRENT_SOURCE_DIR}/config/config-CB-SAT-AC.yaml" DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/chargebridge RENAME "config-CB-SAT-AC.yaml-example")
|
||||
install (FILES "${CMAKE_CURRENT_SOURCE_DIR}/config/config-CB-EVAL-EV.yaml" DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/chargebridge RENAME "config-CB-EVAL-EV.yaml-example")
|
||||
install (FILES "${CMAKE_CURRENT_SOURCE_DIR}/config/config-CB-EVAL-SIM.yaml" DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/chargebridge RENAME "config-CB-EVAL-SIM.yaml-example")
|
||||
@@ -0,0 +1,154 @@
|
||||
charge_bridge:
|
||||
name: cb_eval_ev
|
||||
ip: ANY_EV
|
||||
#ip: chargebridge-44b7d0c99629.local
|
||||
fw_file: ./firmware/charge-bridge-fw_complete.cbfw
|
||||
fw_update_on_start: true
|
||||
mdns_name: ""
|
||||
|
||||
heartbeat:
|
||||
interval_s: 1
|
||||
connection_to_s: 10
|
||||
|
||||
safety:
|
||||
pp_mode: "disabled"
|
||||
cp_avg_ms: 10
|
||||
inverted_emergency_input: 0
|
||||
relay_1:
|
||||
relay_mode: "PowerRelay"
|
||||
feedback_enabled: false
|
||||
feedback_delay_ms: 200
|
||||
feedback_inverted: true
|
||||
# PWM not supported yet
|
||||
pwm_dc: 100
|
||||
pwm_delay_ms: 0
|
||||
switchoff_delay_ms: 10
|
||||
relay_2:
|
||||
relay_mode: "PowerRelay"
|
||||
feedback_enabled: false
|
||||
feedback_delay_ms: 200
|
||||
feedback_inverted: true
|
||||
pwm_dc: 100
|
||||
pwm_delay_ms: 0
|
||||
switchoff_delay_ms: 10
|
||||
relay_3:
|
||||
relay_mode: "UserRelay"
|
||||
feedback_enabled: false
|
||||
feedback_delay_ms: 10
|
||||
feedback_inverted: false
|
||||
pwm_dc: 100
|
||||
pwm_delay_ms: 0
|
||||
switchoff_delay_ms: 10
|
||||
|
||||
can_0:
|
||||
enable: true
|
||||
local: "cb_ev_can"
|
||||
baudrate: 125000
|
||||
|
||||
serial_1:
|
||||
enable: true
|
||||
local: "/dev/cb_ev_uart"
|
||||
baudrate: 115200
|
||||
stopbits: OneStopBit
|
||||
parity: None
|
||||
|
||||
serial_2:
|
||||
enable: true
|
||||
local: "/dev/cb_ev_rs485"
|
||||
baudrate: 19200
|
||||
stopbits: OneStopBit
|
||||
parity: Even
|
||||
|
||||
plc:
|
||||
enable: true
|
||||
tap: "cb_ev_plc"
|
||||
ip: 172.25.6.1
|
||||
netmask: 255.255.255.0
|
||||
mtu: 1518
|
||||
powersaving_mode: 1
|
||||
|
||||
ev_bsp:
|
||||
enable: true
|
||||
module_id: "ev_bsp_1"
|
||||
mqtt_remote: 127.0.0.1
|
||||
mqtt_port: 1883
|
||||
mqtt_bind: 127.0.0.1
|
||||
ovm_enabled: false
|
||||
ovm_module_id: "ovm_1"
|
||||
|
||||
evse_bsp:
|
||||
enable: false
|
||||
module_id: "bsp_1"
|
||||
mqtt_remote: 127.0.0.1
|
||||
mqtt_port: 1883
|
||||
mqtt_bind: 127.0.0.1
|
||||
capabilities:
|
||||
max_current_A_import: 16
|
||||
min_current_A_import: 6
|
||||
max_phase_count_import: 3
|
||||
min_phase_count_import: 3
|
||||
max_current_A_export: 16
|
||||
min_current_A_export: 6
|
||||
max_phase_count_export: 3
|
||||
min_phase_count_export: 3
|
||||
supports_changing_phases_during_charging: false
|
||||
connector_type: "IEC62196Type2Cable"
|
||||
max_plug_temperature_C: 250
|
||||
ovm_enabled: true
|
||||
ovm_module_id: "ovm_1"
|
||||
|
||||
gpio:
|
||||
enable: true
|
||||
interval_s: 1
|
||||
mqtt_remote: "localhost"
|
||||
mqtt_port: 1883
|
||||
mqtt_ping_interval_ms: 5000
|
||||
gpio_0:
|
||||
mode: "Input"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_1:
|
||||
mode: "Input"
|
||||
pulls: "NoPull"
|
||||
config: 32767
|
||||
gpio_2:
|
||||
mode: "Input"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_3:
|
||||
mode: "Input"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_4:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 1000
|
||||
gpio_5:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_6:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_7:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_8:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_9:
|
||||
mode: "Input"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
@@ -0,0 +1,153 @@
|
||||
charge_bridge:
|
||||
name: cb_eval
|
||||
ip: ANY_EVSE
|
||||
#ip: chargebridge-44b7d0c99629.local
|
||||
fw_file: ./firmware/charge-bridge-fw_complete.cbfw
|
||||
fw_update_on_start: true
|
||||
mdns_name: ""
|
||||
|
||||
heartbeat:
|
||||
interval_s: 1
|
||||
connection_to_s: 10
|
||||
|
||||
safety:
|
||||
pp_mode: "disabled"
|
||||
cp_avg_ms: 10
|
||||
inverted_emergency_input: 0
|
||||
relay_1:
|
||||
relay_mode: "PowerRelay"
|
||||
feedback_enabled: false
|
||||
feedback_delay_ms: 200
|
||||
feedback_inverted: true
|
||||
# PWM not supported yet
|
||||
pwm_dc: 100
|
||||
pwm_delay_ms: 0
|
||||
switchoff_delay_ms: 10
|
||||
relay_2:
|
||||
relay_mode: "PowerRelay"
|
||||
feedback_enabled: false
|
||||
feedback_delay_ms: 200
|
||||
feedback_inverted: true
|
||||
pwm_dc: 100
|
||||
pwm_delay_ms: 0
|
||||
switchoff_delay_ms: 10
|
||||
relay_3:
|
||||
relay_mode: "PowerRelay"
|
||||
feedback_enabled: false
|
||||
feedback_delay_ms: 10
|
||||
feedback_inverted: true
|
||||
pwm_dc: 100
|
||||
pwm_delay_ms: 0
|
||||
switchoff_delay_ms: 10
|
||||
|
||||
can_0:
|
||||
enable: true
|
||||
local: "cb_can"
|
||||
baudrate: 125000
|
||||
|
||||
serial_1:
|
||||
enable: true
|
||||
local: "/dev/cb_uart"
|
||||
baudrate: 115200
|
||||
stopbits: OneStopBit
|
||||
parity: None
|
||||
|
||||
serial_2:
|
||||
enable: true
|
||||
local: "/dev/cb_rs485"
|
||||
baudrate: 19200
|
||||
stopbits: OneStopBit
|
||||
parity: Even
|
||||
|
||||
plc:
|
||||
enable: true
|
||||
tap: "cb_plc"
|
||||
ip: 172.25.6.1
|
||||
netmask: 255.255.255.0
|
||||
mtu: 1518
|
||||
powersaving_mode: 1
|
||||
|
||||
ev_bsp:
|
||||
enable: false
|
||||
module_id: "ev_bsp_1"
|
||||
mqtt_remote: 127.0.0.1
|
||||
mqtt_port: 1883
|
||||
mqtt_bind: 127.0.0.1
|
||||
ovm_enabled: false
|
||||
ovm_module_id: "ovm_1"
|
||||
|
||||
evse_bsp:
|
||||
enable: true
|
||||
module_id: "cb_bsp"
|
||||
mqtt_remote: "localhost"
|
||||
mqtt_port: 1883
|
||||
mqtt_ping_interval_ms: 5000
|
||||
ovm_enabled: true
|
||||
ovm_module_id: "cb_ovm"
|
||||
capabilities:
|
||||
max_current_A_import: 16
|
||||
min_current_A_import: 0
|
||||
max_phase_count_import: 3
|
||||
min_phase_count_import: 3
|
||||
max_current_A_export: 16
|
||||
min_current_A_export: 0
|
||||
max_phase_count_export: 3
|
||||
min_phase_count_export: 3
|
||||
supports_changing_phases_during_charging: false
|
||||
connector_type: "IEC62196Type2Cable"
|
||||
|
||||
gpio:
|
||||
enable: true
|
||||
interval_s: 1
|
||||
mqtt_remote: "localhost"
|
||||
mqtt_port: 1883
|
||||
mqtt_ping_interval_ms: 5000
|
||||
gpio_0:
|
||||
mode: "Input"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_1:
|
||||
mode: "Input"
|
||||
pulls: "NoPull"
|
||||
config: 32767
|
||||
gpio_2:
|
||||
mode: "Input"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_3:
|
||||
mode: "Input"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_4:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 1000
|
||||
gpio_5:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_6:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_7:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_8:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_9:
|
||||
mode: "Input"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
@@ -0,0 +1,147 @@
|
||||
charge_bridge:
|
||||
name: cb_eval
|
||||
ip: ANY_EVSE
|
||||
#ip: chargebridge-44b7d0c9bcc0.local^
|
||||
#ip: chargebridge-44b7d0c99629.local
|
||||
fw_file: ./firmware/charge-bridge-fw_complete.cbfw
|
||||
fw_update_on_start: true
|
||||
mdns_name: ""
|
||||
|
||||
heartbeat:
|
||||
interval_s: 1
|
||||
connection_to_s: 10
|
||||
|
||||
safety:
|
||||
pp_mode: "disabled"
|
||||
cp_avg_ms: 10
|
||||
inverted_emergency_input: 0
|
||||
relay_1:
|
||||
relay_mode: "PowerRelay"
|
||||
feedback_enabled: true
|
||||
feedback_delay_ms: 200
|
||||
feedback_inverted: true
|
||||
# PWM not supported yet
|
||||
pwm_dc: 100
|
||||
pwm_delay_ms: 0
|
||||
switchoff_delay_ms: 10
|
||||
relay_2:
|
||||
relay_mode: "PowerRelay"
|
||||
feedback_enabled: true
|
||||
feedback_delay_ms: 200
|
||||
feedback_inverted: true
|
||||
pwm_dc: 100
|
||||
pwm_delay_ms: 0
|
||||
switchoff_delay_ms: 10
|
||||
relay_3:
|
||||
relay_mode: "UserRelay"
|
||||
feedback_enabled: false
|
||||
feedback_delay_ms: 10
|
||||
feedback_inverted: false
|
||||
pwm_dc: 100
|
||||
pwm_delay_ms: 0
|
||||
switchoff_delay_ms: 10
|
||||
|
||||
can_0:
|
||||
enable: true
|
||||
local: "cb_can"
|
||||
baudrate: 125000
|
||||
|
||||
serial_1:
|
||||
enable: true
|
||||
local: "/dev/cb_uart"
|
||||
baudrate: 115200
|
||||
stopbits: OneStopBit
|
||||
parity: None
|
||||
|
||||
serial_2:
|
||||
enable: true
|
||||
local: "/dev/cb_rs485"
|
||||
baudrate: 19200
|
||||
stopbits: OneStopBit
|
||||
parity: Even
|
||||
|
||||
plc:
|
||||
enable: true
|
||||
tap: "cb_plc"
|
||||
ip: 172.25.6.2
|
||||
netmask: 255.255.255.0
|
||||
mtu: 1518
|
||||
powersaving_mode: 1
|
||||
|
||||
evse_bsp:
|
||||
enable: true
|
||||
module_id: "cb_bsp"
|
||||
mqtt_remote: "localhost"
|
||||
mqtt_port: 1883
|
||||
mqtt_bind: 127.0.0.1
|
||||
mqtt_ping_interval_ms: 5000
|
||||
ovm_enabled: true
|
||||
ovm_module_id: "cb_ovm"
|
||||
capabilities:
|
||||
max_current_A_import: 16
|
||||
min_current_A_import: 0
|
||||
max_phase_count_import: 3
|
||||
min_phase_count_import: 3
|
||||
max_current_A_export: 16
|
||||
min_current_A_export: 0
|
||||
max_phase_count_export: 3
|
||||
min_phase_count_export: 3
|
||||
supports_changing_phases_during_charging: false
|
||||
connector_type: "IEC62196Type2Cable"
|
||||
|
||||
gpio:
|
||||
enable: true
|
||||
interval_s: 1
|
||||
mqtt_remote: "localhost"
|
||||
mqtt_port: 1883
|
||||
mqtt_bind: 127.0.0.1
|
||||
mqtt_ping_interval_ms: 5000
|
||||
gpio_0:
|
||||
mode: "Input"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_1:
|
||||
mode: "Input"
|
||||
pulls: "NoPull"
|
||||
config: 32767
|
||||
gpio_2:
|
||||
mode: "Input"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_3:
|
||||
mode: "Input"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_4:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 1000
|
||||
gpio_5:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_6:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_7:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_8:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_9:
|
||||
mode: "Input"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
@@ -0,0 +1,169 @@
|
||||
charge_bridge:
|
||||
name: cb_sat_ac
|
||||
ip: ANY_EVSE
|
||||
fw_file: ./firmware/charge-bridge-fw_complete.cbfw
|
||||
fw_update_on_start: true
|
||||
mdns_name: ""
|
||||
|
||||
heartbeat:
|
||||
interval_s: 1
|
||||
connection_to_s: 10
|
||||
|
||||
safety:
|
||||
pp_mode: "disabled"
|
||||
cp_avg_ms: 10
|
||||
inverted_emergency_input: 0
|
||||
relay_1:
|
||||
relay_mode: "PowerRelay"
|
||||
# Auxilary contact is connected from the OMRON relay
|
||||
feedback_enabled: true
|
||||
# The Omron relay switches in less than 100ms, use 200ms here
|
||||
feedback_delay_ms: 200
|
||||
# Only for PCB version 1.1, set to false for PCB version 1.2 and up
|
||||
feedback_inverted: true
|
||||
# PWM not supported yet
|
||||
pwm_dc: 100
|
||||
pwm_delay_ms: 0
|
||||
switchoff_delay_ms: 10
|
||||
relay_2:
|
||||
# Not connected on PCB
|
||||
relay_mode: "UserRelay"
|
||||
feedback_enabled: false
|
||||
feedback_delay_ms: 10
|
||||
feedback_inverted: false
|
||||
pwm_dc: 100
|
||||
pwm_delay_ms: 0
|
||||
switchoff_delay_ms: 10
|
||||
relay_3:
|
||||
# Not connected on PCB
|
||||
relay_mode: "UserRelay"
|
||||
feedback_enabled: false
|
||||
feedback_delay_ms: 10
|
||||
feedback_inverted: false
|
||||
pwm_dc: 100
|
||||
pwm_delay_ms: 0
|
||||
switchoff_delay_ms: 10
|
||||
|
||||
can_0:
|
||||
enable: true
|
||||
local: "cb_can"
|
||||
baudrate: 250000
|
||||
|
||||
serial_1:
|
||||
enable: true
|
||||
local: "/dev/cb_uart"
|
||||
baudrate: 115200
|
||||
stopbits: OneStopBit
|
||||
parity: None
|
||||
|
||||
serial_2:
|
||||
enable: true
|
||||
local: "/dev/cb_rs485"
|
||||
baudrate: 9600
|
||||
stopbits: OneStopBit
|
||||
parity: None
|
||||
|
||||
plc:
|
||||
enable: true
|
||||
tap: "cb_plc"
|
||||
ip: 172.25.6.1
|
||||
netmask: 255.255.255.0
|
||||
mtu: 1518
|
||||
powersaving_mode: 1
|
||||
|
||||
evse_bsp:
|
||||
enable: true
|
||||
module_id: "cb_bsp"
|
||||
mqtt_remote: "localhost"
|
||||
mqtt_port: 1883
|
||||
mqtt_bind: 127.0.0.1
|
||||
mqtt_ping_interval_ms: 1000
|
||||
capabilities:
|
||||
max_current_A_import: 16
|
||||
min_current_A_import: 6
|
||||
max_phase_count_import: 3
|
||||
min_phase_count_import: 3
|
||||
max_current_A_export: 16
|
||||
min_current_A_export: 6
|
||||
max_phase_count_export: 3
|
||||
min_phase_count_export: 3
|
||||
supports_changing_phases_during_charging: false
|
||||
connector_type: "IEC62196Type2Cable"
|
||||
ovm_enabled: false
|
||||
ovm_module_id: cb_ovm
|
||||
|
||||
gpio:
|
||||
enable: true
|
||||
interval_s: 1
|
||||
mqtt_remote: "localhost"
|
||||
mqtt_port: 1883
|
||||
mqtt_bind: 127.0.0.1
|
||||
mqtt_ping_interval_ms: 1000
|
||||
gpio_0:
|
||||
# RCD.TEST
|
||||
#mode: "Rcd_Selftest_Output"
|
||||
# Self test not fully supported yet
|
||||
mode: "Input"
|
||||
pulls: "NoPull"
|
||||
mdns: false
|
||||
# RCD self test duration (ignore emergency input signals for this time after self test)
|
||||
# and show reason of safety decision on host somehow to simplify debugging
|
||||
config: 1000
|
||||
gpio_1:
|
||||
# RCD.ERROR
|
||||
mode: "Input"
|
||||
pulls: "NoPull"
|
||||
mdns: false
|
||||
config: 0
|
||||
gpio_2:
|
||||
# MOTOR_1
|
||||
# simple Motor lock with only 2 wires (no feedback contacts)
|
||||
mode: "MotorLock_1"
|
||||
pulls: "NoPull"
|
||||
mdns: false
|
||||
# 1000 ms motor drive time for locking/unlocking
|
||||
config: 1000
|
||||
gpio_3:
|
||||
# MOTOR_2
|
||||
# simple Motor lock with only 2 wires (no feedback contacts)
|
||||
mode: "MotorLock_2"
|
||||
pulls: "NoPull"
|
||||
mdns: false
|
||||
config: 1000
|
||||
gpio_4:
|
||||
# RCD.PWM
|
||||
# not supported yet
|
||||
mode: "Input"
|
||||
pulls: "NoPull"
|
||||
mdns: false
|
||||
config: 0
|
||||
gpio_5:
|
||||
# External GPIO on connector J4 pin 9 (10kOhm I/O)
|
||||
mode: "Input"
|
||||
pulls: "NoPull"
|
||||
mdns: false
|
||||
config: 0
|
||||
gpio_6:
|
||||
# External GPIO on connector J4 pin 10 (10kOhm I/O)
|
||||
mode: "Input"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 0
|
||||
gpio_7:
|
||||
# External GPIO on connector J3 pin 11 (10kOhm I/O)
|
||||
mode: "Input"
|
||||
pulls: "NoPull"
|
||||
mdns: false
|
||||
config: 0
|
||||
gpio_8:
|
||||
# External GPIO on connector J3 pin 12 (10kOhm I/O)
|
||||
mode: "Input"
|
||||
pulls: "PullDown"
|
||||
mdns: false
|
||||
config: 0
|
||||
gpio_9:
|
||||
# Not connected
|
||||
mode: "Input"
|
||||
pulls: "PullDown"
|
||||
mdns: false
|
||||
config: 0
|
||||
@@ -0,0 +1,143 @@
|
||||
charge_bridge_ip_list : [ "192.168.188.65", "192.168.188.65"]
|
||||
|
||||
charge_bridge:
|
||||
name: cb_##
|
||||
ip: ""
|
||||
fw_file: ./firmware/charge-bridge-fw_complete.cbfw
|
||||
fw_update_on_start: false
|
||||
mdns_name: "pionix_cb_##"
|
||||
|
||||
heartbeat:
|
||||
interval_s: 1
|
||||
connection_to_s: 10
|
||||
|
||||
safety:
|
||||
pp_mode: "disabled"
|
||||
cp_avg_ms: 10
|
||||
relay_1:
|
||||
relay_mode: "PowerRelay"
|
||||
feedback_enabled: false
|
||||
feedback_delay_ms: 10
|
||||
feedback_inverted: false
|
||||
pwm_dc: 100
|
||||
pwm_delay_ms: 0
|
||||
switchoff_delay_ms: 10
|
||||
relay_2:
|
||||
relay_mode: "PowerRelay"
|
||||
feedback_enabled: false
|
||||
feedback_delay_ms: 10
|
||||
feedback_inverted: false
|
||||
pwm_dc: 100
|
||||
pwm_delay_ms: 0
|
||||
switchoff_delay_ms: 10
|
||||
relay_3:
|
||||
relay_mode: "PowerRelay"
|
||||
feedback_enabled: false
|
||||
feedback_delay_ms: 10
|
||||
feedback_inverted: false
|
||||
pwm_dc: 100
|
||||
pwm_delay_ms: 0
|
||||
switchoff_delay_ms: 10
|
||||
|
||||
can_0:
|
||||
enable: true
|
||||
local: "cb_##_can0"
|
||||
baudrate: 250000
|
||||
|
||||
serial_1:
|
||||
enable: true
|
||||
local: "/dev/cb_##_serial_1"
|
||||
baudrate: 19200
|
||||
stopbits: OneStopBit
|
||||
parity: None
|
||||
|
||||
serial_2:
|
||||
enable: false
|
||||
local: "/dev/cb_##_serial_2"
|
||||
baudrate: 19200
|
||||
stopbits: OneStopBit
|
||||
parity: None
|
||||
|
||||
plc:
|
||||
enable: false
|
||||
tap: "cb_##_tap0"
|
||||
ip: 172.25.6.1
|
||||
netmask: 255.255.255.0
|
||||
mtu: 1518
|
||||
powersaving_mode: 1
|
||||
|
||||
evse_bsp:
|
||||
enable: false
|
||||
module_id: "bsp_##"
|
||||
mqtt_remote: "localhost"
|
||||
mqtt_port: 1883
|
||||
mqtt_ping_interval_ms: 1000
|
||||
capabilities:
|
||||
max_current_A_import: 16
|
||||
min_current_A_import: 6
|
||||
max_phase_count_import: 3
|
||||
min_phase_count_import: 3
|
||||
max_current_A_export: 16
|
||||
min_current_A_export: 6
|
||||
max_phase_count_export: 3
|
||||
min_phase_count_export: 3
|
||||
supports_changing_phases_during_charging: false
|
||||
connector_type: "IEC62196Type2Cable"
|
||||
ovm_enabled: true
|
||||
ovm_module_id: "ovm_1"
|
||||
|
||||
gpio:
|
||||
enable: false
|
||||
interval_s: 4
|
||||
mqtt_remote: "localhost"
|
||||
mqtt_port: 1883
|
||||
mqtt_ping_interval_ms: 1000
|
||||
gpio_0:
|
||||
mode: "Input"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_1:
|
||||
mode: "Input"
|
||||
pulls: "NoPull"
|
||||
config: 32767
|
||||
gpio_2:
|
||||
mode: "Input"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_3:
|
||||
mode: "Input"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_4:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_5:
|
||||
mode: "Output"
|
||||
pulls: "NoPull"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_6:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_7:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_8:
|
||||
mode: "Output"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
gpio_9:
|
||||
mode: "Input"
|
||||
pulls: "PullUp"
|
||||
mdns: false
|
||||
config: 32767
|
||||
Binary file not shown.
@@ -0,0 +1,37 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2026 Pionix GmbH and Contributors to EVerest
|
||||
#pragma once
|
||||
|
||||
#include <charge_bridge/everest_api/api_connector.hpp>
|
||||
#include <everest/io/event/fd_event_register_interface.hpp>
|
||||
#include <everest/io/udp/udp_client.hpp>
|
||||
#include <everest_api_types/evse_board_support/API.hpp>
|
||||
|
||||
namespace charge_bridge {
|
||||
|
||||
struct bsp_bridge_config {
|
||||
std::string cb;
|
||||
std::string item;
|
||||
std::uint16_t cb_port;
|
||||
std::string cb_remote;
|
||||
evse_bsp::everest_api_config api;
|
||||
};
|
||||
|
||||
class bsp_bridge : public everest::lib::io::event::fd_event_register_interface {
|
||||
public:
|
||||
bsp_bridge(bsp_bridge_config const& config);
|
||||
~bsp_bridge() = default;
|
||||
|
||||
bool register_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
bool unregister_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
|
||||
private:
|
||||
void handle_timer_event();
|
||||
|
||||
evse_bsp::api_connector m_api;
|
||||
everest::lib::io::udp::udp_client m_udp;
|
||||
everest::lib::io::event::timer_fd m_timer;
|
||||
bool m_udp_on_error{false};
|
||||
};
|
||||
|
||||
} // namespace charge_bridge
|
||||
@@ -0,0 +1,45 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <everest/io/can/can_payload.hpp>
|
||||
#include <everest/io/can/socket_can.hpp>
|
||||
#include <everest/io/event/fd_event_register_interface.hpp>
|
||||
#include <everest/io/event/timer_fd.hpp>
|
||||
#include <everest/io/udp/udp_client.hpp>
|
||||
#include <memory>
|
||||
|
||||
extern "C" struct cb_can_message;
|
||||
|
||||
namespace charge_bridge {
|
||||
|
||||
struct can_bridge_config {
|
||||
std::string cb;
|
||||
std::string item;
|
||||
std::uint16_t cb_port;
|
||||
std::string cb_remote;
|
||||
std::string can_device;
|
||||
};
|
||||
|
||||
class can_bridge : public everest::lib::io::event::fd_event_register_interface {
|
||||
public:
|
||||
can_bridge(can_bridge_config const& config);
|
||||
~can_bridge();
|
||||
|
||||
bool register_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
bool unregister_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
|
||||
private:
|
||||
void handle_error_timer();
|
||||
void handle_heartbeat_timer();
|
||||
void send_can_to_udp(cb_can_message const& pl);
|
||||
std::unique_ptr<everest::lib::io::can::socket_can> m_can;
|
||||
everest::lib::io::udp::udp_client m_udp;
|
||||
std::string m_can_device;
|
||||
std::string m_identifier;
|
||||
everest::lib::io::event::timer_fd m_heartbeat_timer;
|
||||
std::chrono::steady_clock::time_point m_last_msg_to_cb;
|
||||
};
|
||||
|
||||
} // namespace charge_bridge
|
||||
@@ -0,0 +1,90 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2026 Pionix GmbH and Contributors to EVerest
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <charge_bridge/bsp_bridge.hpp>
|
||||
#include <charge_bridge/can_bridge.hpp>
|
||||
#include <charge_bridge/discovery.hpp>
|
||||
#include <charge_bridge/firmware_update/sync_fw_updater.hpp>
|
||||
#include <charge_bridge/gpio_bridge.hpp>
|
||||
#include <charge_bridge/heartbeat_service.hpp>
|
||||
#include <charge_bridge/plc_bridge.hpp>
|
||||
#include <charge_bridge/serial_bridge.hpp>
|
||||
#include <charge_bridge/utilities/symlink.hpp>
|
||||
#include <everest/io/event/fd_event_handler.hpp>
|
||||
#include <everest/io/serial/event_pty.hpp>
|
||||
#include <everest/io/tun_tap/tap_client.hpp>
|
||||
#include <everest/util/async/monitor.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
namespace charge_bridge {
|
||||
|
||||
struct charge_bridge_status {
|
||||
bool is_connected{false};
|
||||
bool discovery_pending{false};
|
||||
};
|
||||
|
||||
struct charge_bridge_config {
|
||||
std::string cb_name;
|
||||
std::uint16_t cb_port;
|
||||
std::string cb_remote;
|
||||
std::optional<can_bridge_config> can0;
|
||||
std::optional<serial_bridge_config> serial1;
|
||||
std::optional<serial_bridge_config> serial2;
|
||||
std::optional<serial_bridge_config> serial3;
|
||||
std::optional<plc_bridge_config> plc;
|
||||
std::optional<bsp_bridge_config> bsp;
|
||||
std::optional<heartbeat_config> heartbeat;
|
||||
std::optional<gpio_config> gpio;
|
||||
firmware_update::fw_update_config firmware;
|
||||
};
|
||||
|
||||
void print_charge_bridge_config(charge_bridge_config const& config);
|
||||
|
||||
class charge_bridge : public everest::lib::io::event::fd_event_register_interface {
|
||||
public:
|
||||
charge_bridge(charge_bridge_config const& config);
|
||||
~charge_bridge();
|
||||
|
||||
bool update_firmware(bool force);
|
||||
|
||||
std::string get_pty_1_slave_path();
|
||||
std::string get_pty_2_slave_path();
|
||||
std::string get_pty_3_slave_path();
|
||||
|
||||
void print_config();
|
||||
|
||||
bool register_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
bool unregister_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
|
||||
void manage(everest::lib::io::event::fd_event_handler& handler, std::atomic_bool const& exit, bool force_update);
|
||||
|
||||
private:
|
||||
void init();
|
||||
void init_discovery(discovery_device_type type, std::set<std::string> const& interfaces, bool excluding);
|
||||
void handle_discovery(std::string const& ip);
|
||||
|
||||
private:
|
||||
std::unique_ptr<can_bridge> m_can_0_client;
|
||||
std::unique_ptr<serial_bridge> m_pty_1;
|
||||
std::unique_ptr<serial_bridge> m_pty_2;
|
||||
std::unique_ptr<serial_bridge> m_pty_3;
|
||||
std::unique_ptr<bsp_bridge> m_bsp;
|
||||
std::unique_ptr<plc_bridge> m_plc;
|
||||
std::unique_ptr<heartbeat_service> m_heartbeat;
|
||||
std::unique_ptr<gpio_bridge> m_gpio;
|
||||
std::unique_ptr<discovery> m_discovery;
|
||||
|
||||
everest::lib::io::event::fd_event_handler* m_event_handler{nullptr};
|
||||
bool m_force_firmware_update{false};
|
||||
everest::lib::util::monitor<charge_bridge_status> m_cb_status;
|
||||
bool m_was_connected{false};
|
||||
bool m_discovery_active{false};
|
||||
|
||||
charge_bridge_config m_config;
|
||||
};
|
||||
|
||||
} // namespace charge_bridge
|
||||
@@ -0,0 +1,45 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2026 Pionix GmbH and Contributors to EVerest
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <everest/io/event/fd_event_register_interface.hpp>
|
||||
#include <everest/io/event/timer_fd.hpp>
|
||||
#include <everest/io/mdns/mdns.hpp>
|
||||
#include <everest/io/mdns/mdns_client.hpp>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
|
||||
namespace charge_bridge {
|
||||
|
||||
enum class discovery_device_type {
|
||||
CB_EVSE,
|
||||
CB_EV
|
||||
};
|
||||
|
||||
class discovery : public everest::lib::io::event::fd_event_register_interface {
|
||||
public:
|
||||
using discovery_cb = std::function<void(std::string const&)>;
|
||||
|
||||
discovery(discovery_device_type type);
|
||||
discovery(discovery_device_type type, std::set<std::string> const& interfaces, bool excluding);
|
||||
|
||||
bool register_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
bool unregister_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
|
||||
void set_discovery_callback(discovery_cb const& cb);
|
||||
|
||||
private:
|
||||
void add_client(std::string const& interface);
|
||||
void query_registry();
|
||||
|
||||
std::vector<std::unique_ptr<everest::lib::io::mdns::mdns_client>> m_mdns;
|
||||
everest::lib::io::event::timer_fd m_timer;
|
||||
discovery_cb m_on_discover;
|
||||
everest::lib::io::mdns::mDNS_registry m_registry;
|
||||
discovery_device_type m_type;
|
||||
static const std::string discovery_id;
|
||||
};
|
||||
|
||||
} // namespace charge_bridge
|
||||
@@ -0,0 +1,76 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2026 Pionix GmbH and Contributors to EVerest
|
||||
#pragma once
|
||||
|
||||
#include <charge_bridge/everest_api/ev_bsp_api.hpp>
|
||||
#include <charge_bridge/everest_api/evse_bsp_api.hpp>
|
||||
#include <charge_bridge/everest_api/ovm_api.hpp>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <everest/io/event/fd_event_register_interface.hpp>
|
||||
#include <everest/io/event/timer_fd.hpp>
|
||||
#include <everest/io/mqtt/mqtt_client.hpp>
|
||||
#include <everest_api_types/evse_board_support/API.hpp>
|
||||
#include <everest_api_types/evse_manager/API.hpp>
|
||||
#include <everest_api_types/utilities/Topics.hpp>
|
||||
#include <functional>
|
||||
#include <protocol/cb_common.h>
|
||||
#include <protocol/evse_bsp_cb_to_host.h>
|
||||
#include <protocol/evse_bsp_host_to_cb.h>
|
||||
#include <string>
|
||||
|
||||
namespace charge_bridge::evse_bsp {
|
||||
|
||||
namespace API_BSP = everest::lib::API::V1_0::types::evse_board_support;
|
||||
|
||||
struct everest_api_config {
|
||||
std::string mqtt_remote;
|
||||
std::string mqtt_bind;
|
||||
uint16_t mqtt_port;
|
||||
uint32_t mqtt_ping_interval_ms;
|
||||
evse_bsp_config evse;
|
||||
evse_ovm_config ovm;
|
||||
evse_ev_bsp_config ev;
|
||||
};
|
||||
|
||||
class api_connector : public everest::lib::io::event::fd_event_register_interface {
|
||||
using tx_ftor = std::function<void(evse_bsp_host_to_cb const&)>;
|
||||
using rx_ftor = std::function<void(evse_bsp_cb_to_host const&)>;
|
||||
|
||||
public:
|
||||
api_connector(everest_api_config const& config, std::string const& cb_identifier);
|
||||
void set_cb_tx(tx_ftor const& handler);
|
||||
void set_cb_message(evse_bsp_cb_to_host const& msg);
|
||||
|
||||
bool register_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
bool unregister_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
|
||||
private:
|
||||
void handle_mqtt_connect();
|
||||
void handle_cb_connection_state();
|
||||
bool check_cb_heartbeat();
|
||||
|
||||
std::string m_cb_identifier;
|
||||
everest::lib::io::mqtt::mqtt_client m_mqtt;
|
||||
tx_ftor m_tx;
|
||||
std::chrono::steady_clock::time_point m_last_cb_heartbeat;
|
||||
everest::lib::io::event::timer_fd m_sync_timer;
|
||||
|
||||
std::string m_evse_bsp_receive_topic;
|
||||
std::string m_evse_bsp_send_topic;
|
||||
std::string m_ovm_receive_topic;
|
||||
std::string m_ovm_send_topic;
|
||||
std::string m_ev_bsp_receive_topic;
|
||||
std::string m_ev_bsp_send_topic;
|
||||
bool m_evse_bsp_enabled{false};
|
||||
bool m_ovm_enabled{false};
|
||||
bool m_ev_bsp_enabled{false};
|
||||
bool m_cb_initial_comm_check{true};
|
||||
bool m_cb_connected{false};
|
||||
evse_bsp_host_to_cb m_host_status;
|
||||
|
||||
evse_bsp_api m_evse_bsp;
|
||||
ovm_api m_ovm;
|
||||
ev_bsp_api m_ev_bsp;
|
||||
};
|
||||
} // namespace charge_bridge::evse_bsp
|
||||
@@ -0,0 +1,101 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2026 Pionix GmbH and Contributors to EVerest
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <everest/io/event/fd_event_register_interface.hpp>
|
||||
#include <everest/io/event/timer_fd.hpp>
|
||||
#include <everest_api_types/ev_board_support/API.hpp>
|
||||
#include <everest_api_types/evse_board_support/API.hpp>
|
||||
#include <everest_api_types/evse_manager/API.hpp>
|
||||
#include <everest_api_types/generic/API.hpp>
|
||||
#include <everest_api_types/utilities/Topics.hpp>
|
||||
#include <functional>
|
||||
#include <protocol/cb_common.h>
|
||||
#include <protocol/evse_bsp_cb_to_host.h>
|
||||
#include <protocol/evse_bsp_host_to_cb.h>
|
||||
#include <string>
|
||||
|
||||
namespace charge_bridge::evse_bsp {
|
||||
namespace API_EVSE_BSP = everest::lib::API::V1_0::types::evse_board_support;
|
||||
namespace API_EV_BSP = everest::lib::API::V1_0::types::ev_board_support;
|
||||
namespace API_EVM = everest::lib::API::V1_0::types::evse_manager;
|
||||
namespace API_GENERIC = everest::lib::API::V1_0::types::generic;
|
||||
// namespace API_OVM = everest::lib::API::V1_0::types::over_voltage_monitor;
|
||||
|
||||
struct evse_ev_bsp_config {
|
||||
bool enabled{false};
|
||||
std::string module_id;
|
||||
};
|
||||
|
||||
class ev_bsp_api : public everest::lib::io::event::fd_event_register_interface {
|
||||
using tx_ftor = std::function<void(evse_bsp_host_to_cb const&)>;
|
||||
using rx_ftor = std::function<void(evse_bsp_cb_to_host const&)>;
|
||||
using mqtt_ftor = std::function<void(std::string const&, std::string const&)>;
|
||||
|
||||
public:
|
||||
ev_bsp_api(evse_ev_bsp_config const& config, std::string const& cb_identifier, evse_bsp_host_to_cb& host_status);
|
||||
void set_cb_tx(tx_ftor const& handler);
|
||||
void set_cb_message(evse_bsp_cb_to_host const& msg);
|
||||
void set_mqtt_tx(mqtt_ftor const& tx);
|
||||
|
||||
bool register_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
bool unregister_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
void dispatch(std::string const& operation, std::string const& payload);
|
||||
|
||||
void raise_comm_fault();
|
||||
void clear_comm_fault();
|
||||
void sync(bool cb_connected);
|
||||
|
||||
private:
|
||||
void tx(evse_bsp_host_to_cb const& msg);
|
||||
|
||||
void send_bsp_event(API_EVSE_BSP::Event data);
|
||||
void send_bsp_measurement(API_EV_BSP::BspMeasurement data);
|
||||
void send_ev_info(API_EVM::EVInfo data);
|
||||
|
||||
void send_raise_error(API_GENERIC::ErrorEnum error, std::string const& subtype, std::string const& msg);
|
||||
void send_clear_error(API_GENERIC::ErrorEnum error, std::string const& subtype);
|
||||
|
||||
void send_communication_check();
|
||||
|
||||
void send_mqtt(std::string const& topic, std::string const& message);
|
||||
|
||||
void send_event(API_EVSE_BSP::Event data);
|
||||
|
||||
void receive_enable(std::string const& payload);
|
||||
void receive_set_cp_state(std::string const& payload);
|
||||
void receive_allow_power_on(std::string const& payload);
|
||||
void receive_diode_fail(std::string const& payload);
|
||||
void receive_set_ac_max_current(std::string const& payload);
|
||||
void receive_set_three_phases(std::string const& payload);
|
||||
void receive_set_rcd_error(std::string const& payload);
|
||||
void receive_heartbeat(std::string const& pl);
|
||||
|
||||
void handle_error(const SafetyErrorFlags& data);
|
||||
void handle_event_cp(std::uint8_t cp);
|
||||
void handle_event_relay(std::uint8_t relay);
|
||||
void handle_bsp_measurement(uint16_t cp, uint8_t pp_1, uint8_t pp2);
|
||||
|
||||
bool check_everest_heartbeat();
|
||||
void handle_everest_connection_state();
|
||||
|
||||
evse_bsp_host_to_cb& host_status;
|
||||
evse_bsp_cb_to_host m_cb_status;
|
||||
|
||||
tx_ftor m_tx;
|
||||
bool m_everest_connected{false};
|
||||
bool m_cb_connected{false};
|
||||
bool m_cb_initial_comm_check{true};
|
||||
bool m_bc_initial_comm_check{true};
|
||||
std::string m_cb_identifier;
|
||||
std::chrono::steady_clock::time_point last_everest_heartbeat;
|
||||
|
||||
mqtt_ftor m_mqtt_tx;
|
||||
std::size_t m_last_hb_id{0};
|
||||
everest::lib::API::V1_0::types::evse_board_support::Event last_cp_event{
|
||||
everest::lib::API::V1_0::types::evse_board_support::Event::Disconnected};
|
||||
};
|
||||
|
||||
} // namespace charge_bridge::evse_bsp
|
||||
@@ -0,0 +1,103 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2026 Pionix GmbH and Contributors to EVerest
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <everest/io/event/fd_event_register_interface.hpp>
|
||||
#include <everest/io/event/timer_fd.hpp>
|
||||
#include <everest_api_types/evse_board_support/API.hpp>
|
||||
#include <everest_api_types/evse_manager/API.hpp>
|
||||
#include <everest_api_types/utilities/Topics.hpp>
|
||||
#include <functional>
|
||||
#include <protocol/cb_common.h>
|
||||
#include <protocol/evse_bsp_cb_to_host.h>
|
||||
#include <protocol/evse_bsp_host_to_cb.h>
|
||||
#include <string>
|
||||
|
||||
namespace charge_bridge::evse_bsp {
|
||||
namespace API_BSP = everest::lib::API::V1_0::types::evse_board_support;
|
||||
namespace API_EVM = everest::lib::API::V1_0::types::evse_manager;
|
||||
|
||||
struct evse_bsp_config {
|
||||
std::string module_id;
|
||||
bool enabled{false};
|
||||
API_BSP::HardwareCapabilities capabilities;
|
||||
};
|
||||
|
||||
class evse_bsp_api : public everest::lib::io::event::fd_event_register_interface {
|
||||
using tx_ftor = std::function<void(evse_bsp_host_to_cb const&)>;
|
||||
using rx_ftor = std::function<void(evse_bsp_cb_to_host const&)>;
|
||||
using mqtt_ftor = std::function<void(std::string const&, std::string const&)>;
|
||||
|
||||
public:
|
||||
evse_bsp_api(evse_bsp_config const& config, std::string const& cb_identifier, evse_bsp_host_to_cb& host_status);
|
||||
void set_cb_tx(tx_ftor const& handler);
|
||||
void set_cb_message(evse_bsp_cb_to_host const& msg);
|
||||
void set_mqtt_tx(mqtt_ftor const& tx);
|
||||
|
||||
bool register_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
bool unregister_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
void dispatch(std::string const& operation, std::string const& payload);
|
||||
|
||||
void raise_comm_fault();
|
||||
void clear_comm_fault();
|
||||
void sync(bool cb_connected);
|
||||
|
||||
private:
|
||||
void tx(evse_bsp_host_to_cb const& msg);
|
||||
|
||||
void handle_event_cp(std::uint8_t cp);
|
||||
void handle_event_relay(std::uint8_t relay);
|
||||
void handle_error(const SafetyErrorFlags& data);
|
||||
void handle_pp_type1(std::uint8_t data);
|
||||
void handle_pp_type2(std::uint8_t data);
|
||||
void handle_stop_button(std::uint8_t data);
|
||||
|
||||
void send_event(API_BSP::Event data);
|
||||
void send_ac_nr_of_phases(std::uint8_t data);
|
||||
void send_capabilities();
|
||||
void send_ac_pp_amapcity(API_BSP::Ampacity data);
|
||||
void send_request_stop_transaction(API_EVM::StopTransactionReason data);
|
||||
void send_rcd_current(std::uint8_t data);
|
||||
void send_raise_error(API_BSP::ErrorEnum error, std::string const& subtype, std::string const& msg);
|
||||
void send_clear_error(API_BSP::ErrorEnum error, std::string const& subtype, std::string const& msg);
|
||||
void send_communication_check();
|
||||
void send_reply_reset(std::string const& replyTo);
|
||||
|
||||
void send_mqtt(std::string const& topic, std::string const& message);
|
||||
|
||||
void receive_enable(std::string const& payload);
|
||||
void receive_pwm_on(std::string const& payload);
|
||||
void receive_cp_state_X1(std::string const& payload);
|
||||
void receive_cp_state_F(std::string const& payload);
|
||||
void receive_allow_power_on(std::string const& payload);
|
||||
void receive_ac_switch_three_phases_while_charging(std::string const& payload);
|
||||
void receive_ac_overcurrent_limit(std::string const& payload);
|
||||
void receive_lock();
|
||||
void receive_unlock();
|
||||
void receive_self_test(std::string const& payload);
|
||||
void receive_request_reset(std::string const& payload);
|
||||
void receive_heartbeat(std::string const& pl);
|
||||
|
||||
bool check_everest_heartbeat();
|
||||
void handle_everest_connection_state();
|
||||
|
||||
evse_bsp_host_to_cb& host_status;
|
||||
evse_bsp_cb_to_host cb_status;
|
||||
|
||||
tx_ftor m_tx;
|
||||
everest::lib::io::event::timer_fd m_capabilities_timer;
|
||||
API_BSP::HardwareCapabilities m_capabilities;
|
||||
bool m_enabled{false};
|
||||
bool everest_connected{false};
|
||||
bool m_cb_connected{false};
|
||||
bool m_bc_initial_comm_check{true};
|
||||
std::string m_cb_identifier;
|
||||
std::chrono::steady_clock::time_point last_everest_heartbeat;
|
||||
|
||||
mqtt_ftor m_mqtt_tx;
|
||||
std::size_t m_last_hb_id{0};
|
||||
};
|
||||
|
||||
} // namespace charge_bridge::evse_bsp
|
||||
@@ -0,0 +1,85 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2026 Pionix GmbH and Contributors to EVerest
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <everest/io/event/fd_event_register_interface.hpp>
|
||||
#include <everest/io/event/timer_fd.hpp>
|
||||
#include <everest_api_types/evse_manager/API.hpp>
|
||||
#include <everest_api_types/over_voltage_monitor/API.hpp>
|
||||
#include <everest_api_types/utilities/Topics.hpp>
|
||||
#include <functional>
|
||||
#include <protocol/cb_common.h>
|
||||
#include <protocol/evse_bsp_cb_to_host.h>
|
||||
#include <protocol/evse_bsp_host_to_cb.h>
|
||||
#include <string>
|
||||
|
||||
namespace charge_bridge::evse_bsp {
|
||||
namespace API_OVM = everest::lib::API::V1_0::types::over_voltage_monitor;
|
||||
|
||||
struct evse_ovm_config {
|
||||
bool enabled{false};
|
||||
std::string module_id;
|
||||
};
|
||||
|
||||
class ovm_api : public everest::lib::io::event::fd_event_register_interface {
|
||||
using tx_ftor = std::function<void(evse_bsp_host_to_cb const&)>;
|
||||
using rx_ftor = std::function<void(evse_bsp_cb_to_host const&)>;
|
||||
using mqtt_ftor = std::function<void(std::string const&, std::string const&)>;
|
||||
|
||||
public:
|
||||
ovm_api(evse_ovm_config const& config, std::string const& cb_identifier, evse_bsp_host_to_cb& host_status);
|
||||
void set_cb_tx(tx_ftor const& handler);
|
||||
void set_cb_message(evse_bsp_cb_to_host const& msg);
|
||||
void set_mqtt_tx(mqtt_ftor const& tx);
|
||||
|
||||
bool register_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
bool unregister_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
void dispatch(std::string const& operation, std::string const& payload);
|
||||
|
||||
void raise_comm_fault();
|
||||
void clear_comm_fault();
|
||||
void sync(bool cb_connected);
|
||||
|
||||
private:
|
||||
void tx(evse_bsp_host_to_cb const& msg);
|
||||
|
||||
void send_voltage_measurement_V(double data);
|
||||
void send_raise_error(API_OVM::ErrorEnum error, std::string const& subtype, std::string const& msg,
|
||||
API_OVM::ErrorSeverityEnum severity);
|
||||
void send_clear_error(API_OVM::ErrorEnum error, std::string const& subtype);
|
||||
void send_communication_check();
|
||||
|
||||
void send_mqtt(std::string const& topic, std::string const& message);
|
||||
|
||||
void handle_dc_hv_ov_emergency(bool high);
|
||||
void handle_dc_hv_ov_error(bool high);
|
||||
void handle_cp_state(CpState state);
|
||||
|
||||
void receive_set_limits(std::string const& payload);
|
||||
void receive_start();
|
||||
void receive_stop();
|
||||
void receive_reset_over_voltage_error();
|
||||
void receive_heartbeat(std::string const& pl);
|
||||
|
||||
bool check_everest_heartbeat();
|
||||
void handle_everest_connection_state();
|
||||
|
||||
evse_bsp_host_to_cb& host_status;
|
||||
evse_bsp_cb_to_host m_cb_status;
|
||||
|
||||
tx_ftor m_tx;
|
||||
bool m_everest_connected{false};
|
||||
bool m_cb_connected{false};
|
||||
bool m_cb_initial_comm_check{true};
|
||||
bool m_bc_initial_comm_check{true};
|
||||
std::string m_cb_identifier;
|
||||
std::chrono::steady_clock::time_point last_everest_heartbeat;
|
||||
|
||||
API_OVM::OverVoltageLimits m_limits{0, 0};
|
||||
mqtt_ftor m_mqtt_tx;
|
||||
std::size_t m_last_hb_id{0};
|
||||
};
|
||||
|
||||
} // namespace charge_bridge::evse_bsp
|
||||
@@ -0,0 +1,56 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
#pragma once
|
||||
|
||||
#include <charge_bridge/utilities/filesystem.hpp>
|
||||
#include <charge_bridge/utilities/sync_udp_client.hpp>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace charge_bridge::firmware_update {
|
||||
|
||||
struct fw_update_config {
|
||||
std::string cb;
|
||||
std::uint16_t cb_port;
|
||||
std::string cb_remote;
|
||||
std::string fw_path;
|
||||
bool fw_update_on_start;
|
||||
};
|
||||
|
||||
class sync_fw_updater {
|
||||
public:
|
||||
sync_fw_updater(fw_update_config const& config);
|
||||
~sync_fw_updater() = default;
|
||||
|
||||
std::optional<std::string> get_fw_version();
|
||||
bool switch_bank();
|
||||
bool ping();
|
||||
bool upload_fw();
|
||||
|
||||
void print_fw_version();
|
||||
bool print_switch_bank();
|
||||
bool quick_check_connection();
|
||||
bool check_connection();
|
||||
bool check_if_correct_fw_installed();
|
||||
|
||||
private:
|
||||
bool check_reply(utilities::sync_udp_client::reply const& val);
|
||||
|
||||
bool upload_firmware();
|
||||
|
||||
bool upload_init(const fs::path& file_path, std::uint32_t& offset,
|
||||
charge_bridge::filesystem_utils::CryptSignedHeader& hdr);
|
||||
bool upload_transfer(const fs::path& file_path, std::uint16_t& sector, std::uint32_t offset,
|
||||
std::uint32_t& total_bytes);
|
||||
bool upload_finish(const fs::path& file_path, std::uint32_t total_bytes,
|
||||
const charge_bridge::filesystem_utils::CryptSignedHeader& hdr);
|
||||
|
||||
everest::lib::io::udp::udp_payload make_fw_chunk(std::uint16_t sector, std::uint8_t last_chunk,
|
||||
std::vector<std::uint8_t> const& data);
|
||||
|
||||
utilities::sync_udp_client m_udp;
|
||||
fw_update_config m_config;
|
||||
static const std::uint32_t app_udp_sector_size;
|
||||
static const std::uint16_t sub_chunk_size;
|
||||
};
|
||||
} // namespace charge_bridge::firmware_update
|
||||
@@ -0,0 +1,56 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
#pragma once
|
||||
|
||||
#include "everest/io/mqtt/mosquitto_cpp.hpp"
|
||||
#include <array>
|
||||
#include <everest/io/can/can_payload.hpp>
|
||||
#include <everest/io/event/fd_event_register_interface.hpp>
|
||||
#include <everest/io/event/timer_fd.hpp>
|
||||
#include <everest/io/mqtt/mqtt_client.hpp>
|
||||
#include <everest/io/udp/udp_client.hpp>
|
||||
#include <protocol/cb_management.h>
|
||||
|
||||
namespace charge_bridge {
|
||||
|
||||
struct gpio_config {
|
||||
std::string cb;
|
||||
std::string item;
|
||||
std::uint16_t cb_port;
|
||||
std::string cb_remote;
|
||||
std::uint16_t interval_s;
|
||||
std::string mqtt_remote;
|
||||
std::string mqtt_bind;
|
||||
std::uint16_t mqtt_port;
|
||||
std::uint32_t mqtt_ping_interval_ms;
|
||||
};
|
||||
|
||||
class gpio_bridge : public everest::lib::io::event::fd_event_register_interface {
|
||||
public:
|
||||
gpio_bridge(gpio_config const& config);
|
||||
~gpio_bridge();
|
||||
|
||||
bool register_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
bool unregister_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
|
||||
private:
|
||||
void handle_error_timer();
|
||||
void handle_heartbeat_timer();
|
||||
void handle_udp_rx(everest::lib::io::udp::udp_payload const& payload);
|
||||
void dispatch(everest::lib::io::mqtt::mqtt_client::message const& data);
|
||||
void send_mqtt(std::string const& topic, std::string const& message);
|
||||
void send_udp();
|
||||
|
||||
everest::lib::io::udp::udp_client m_udp;
|
||||
bool m_udp_on_error{false};
|
||||
everest::lib::io::event::timer_fd m_heartbeat_timer;
|
||||
std::chrono::steady_clock::time_point last_heartbeat;
|
||||
CbManagementPacket<CbGpioPacket> m_message;
|
||||
std::string m_identifier;
|
||||
bool m_mqtt_on_error{false};
|
||||
everest::lib::io::mqtt::mqtt_client m_mqtt;
|
||||
std::string m_receive_topic;
|
||||
std::string m_send_topic;
|
||||
};
|
||||
|
||||
} // namespace charge_bridge
|
||||
@@ -0,0 +1,54 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
#pragma once
|
||||
|
||||
#include "protocol/cb_management.h"
|
||||
#include <chrono>
|
||||
#include <everest/io/can/can_payload.hpp>
|
||||
#include <everest/io/event/fd_event_register_interface.hpp>
|
||||
#include <everest/io/event/timer_fd.hpp>
|
||||
#include <everest/io/udp/udp_client.hpp>
|
||||
#include <memory>
|
||||
#include <protocol/cb_config.h>
|
||||
|
||||
namespace charge_bridge {
|
||||
|
||||
struct heartbeat_config {
|
||||
std::string cb;
|
||||
std::string item;
|
||||
std::uint16_t cb_port;
|
||||
std::string cb_remote;
|
||||
std::uint16_t interval_s;
|
||||
std::uint16_t connection_to_s;
|
||||
CbConfig cb_config;
|
||||
};
|
||||
|
||||
class heartbeat_service : public everest::lib::io::event::fd_event_register_interface {
|
||||
public:
|
||||
heartbeat_service(heartbeat_config const& config, std::function<void(bool)> const& publish_connection_status);
|
||||
~heartbeat_service();
|
||||
|
||||
bool register_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
bool unregister_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
|
||||
private:
|
||||
void handle_error_timer();
|
||||
void handle_heartbeat_timer();
|
||||
void handle_udp_rx(everest::lib::io::udp::udp_payload const& payload);
|
||||
|
||||
everest::lib::io::udp::udp_client m_udp;
|
||||
bool m_udp_on_error{false};
|
||||
everest::lib::io::event::timer_fd m_heartbeat_timer;
|
||||
std::string m_identifier;
|
||||
CbManagementPacket<CbConfig> m_config_message;
|
||||
std::chrono::steady_clock::time_point m_last_heartbeat_reply;
|
||||
bool m_cb_connected{false};
|
||||
bool m_inital_cb_commcheck{true};
|
||||
std::chrono::milliseconds m_heartbeat_interval;
|
||||
std::chrono::milliseconds m_connection_to;
|
||||
std::function<void(bool)> m_publish_connection_status;
|
||||
std::uint32_t m_mcu_timestamp{0};
|
||||
int m_mcu_reset_count{0};
|
||||
};
|
||||
|
||||
} // namespace charge_bridge
|
||||
@@ -0,0 +1,41 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
#pragma once
|
||||
|
||||
#include <everest/io/event/fd_event_register_interface.hpp>
|
||||
#include <everest/io/event/timer_fd.hpp>
|
||||
#include <everest/io/tun_tap/tap_client.hpp>
|
||||
#include <everest/io/udp/udp_client.hpp>
|
||||
|
||||
namespace charge_bridge {
|
||||
|
||||
struct plc_bridge_config {
|
||||
std::string cb;
|
||||
std::string item;
|
||||
std::uint16_t cb_port;
|
||||
std::string cb_remote;
|
||||
std::string plc_tap;
|
||||
std::string plc_ip;
|
||||
std::string plc_netmaks;
|
||||
int plc_mtu;
|
||||
};
|
||||
|
||||
class plc_bridge : public everest::lib::io::event::fd_event_register_interface {
|
||||
public:
|
||||
plc_bridge(plc_bridge_config const& config);
|
||||
~plc_bridge() = default;
|
||||
|
||||
bool register_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
bool unregister_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
|
||||
private:
|
||||
void handle_timer_event();
|
||||
|
||||
everest::lib::io::tun_tap::tap_client m_tap;
|
||||
everest::lib::io::udp::udp_client m_udp;
|
||||
everest::lib::io::event::timer_fd m_timer;
|
||||
bool m_udp_on_error{false};
|
||||
bool m_tap_on_error{false};
|
||||
};
|
||||
|
||||
} // namespace charge_bridge
|
||||
@@ -0,0 +1,39 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 - 2025 Pionix GmbH and Contributors to EVerest
|
||||
#pragma once
|
||||
|
||||
#include <charge_bridge/utilities/symlink.hpp>
|
||||
#include <everest/io/event/fd_event_register_interface.hpp>
|
||||
#include <everest/io/event/timer_fd.hpp>
|
||||
#include <everest/io/serial/event_pty.hpp>
|
||||
#include <everest/io/tcp/tcp_client.hpp>
|
||||
|
||||
namespace charge_bridge {
|
||||
|
||||
struct serial_bridge_config {
|
||||
std::string cb;
|
||||
std::string item;
|
||||
std::uint16_t cb_port;
|
||||
std::string cb_remote;
|
||||
std::string serial_device;
|
||||
};
|
||||
|
||||
class serial_bridge : public everest::lib::io::event::fd_event_register_interface {
|
||||
public:
|
||||
serial_bridge(serial_bridge_config const& config);
|
||||
~serial_bridge() = default;
|
||||
|
||||
bool register_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
bool unregister_events(everest::lib::io::event::fd_event_handler& handler) override;
|
||||
std::string get_slave_path();
|
||||
|
||||
private:
|
||||
void reset_tcp();
|
||||
|
||||
everest::lib::io::serial::event_pty m_pty;
|
||||
everest::lib::io::tcp::tcp_client m_tcp;
|
||||
utilities::symlink m_symlink;
|
||||
int m_tcp_last_error_id = -1;
|
||||
};
|
||||
|
||||
} // namespace charge_bridge
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user