Add extracted tools: CitrineOS, OpenOCPP, ShapeShifter

- CitrineOS core extracted (CSMS OCPP 2.0.1)
- OpenOCPP extracted (firmware OCPP 1.6J/2.0.1)
- ShapeShifter library installed (pip install -e)
- ShapeShifter specification extracted
- EVerest extracted

TODO updated with progress
This commit is contained in:
Eric F
2026-06-08 00:38:27 -04:00
parent 468cfeaa50
commit d398a6ced2
7326 changed files with 1177561 additions and 7 deletions

View File

@@ -0,0 +1,11 @@
ARG EVEREST_IMAGE_TAG="2025.6.1-dt-esdp"
FROM ghcr.io/everest/everest-demo/manager:${EVEREST_IMAGE_TAG}
WORKDIR /workspace
RUN npm i -g http-server
EXPOSE 8888
COPY ./start.sh /tmp/start.sh
RUN chmod +x /tmp/start.sh
ENTRYPOINT ["/tmp/start.sh"]

View File

@@ -0,0 +1,62 @@
# Testing with EVerest
In the case you don't have a charger that supports OCPP 2.0.1 to experiment with, we can recommend using the Linux
Foundation Energy project EVerest. [See here](https://github.com/EVerest) for the repository. They have built an open source version of
charger firmware and also allow for using it as a simulator. They support OCPP 2.0.1 which makes it a great testing
opportunity with CitrineOS. For the long route of setting up EVerst you can follow their documentation and build
the project yourself. [See here for Docs](https://everest.github.io/latest/how-to-guides/getting-started/index.html)
# Running EVerest
In order to alleviate some of the complexities that may arise when starting EVerest, we have created
some helpful commands that should help in getting the EVerest charger simulator running locally and targeting
CitrineOS.
You will notice in the `apps/Server/everest` directory the files created to support running EVerest within Docker.
In addition, we created some helpful package scripts (run from the `apps/Server` directory):
- `pnpm run start-everest` — starts EVerest for OCPP 2.x (defaults to `OCPP_VERSION=2.1`)
- `pnpm run start-everest-16` — starts EVerest for OCPP 1.6
Both scripts `cd` into `everest` and trigger the `docker compose up` command (below) from within the
`apps/Server/everest` directory so that it can pick up the `Dockerfile` and the `docker-compose.yml` files.
You will notice that there are two args that are configurable:
- `EVEREST_IMAGE_TAG` - The image tag that will be used for the EVerest image (ghcr.io/everest/everest-demo/manager).
- `OCPP_VERSION` - The version of OCPP to run EVerest for. `start-everest` handles all 2.x versions for the given 2.x `OCPP_VERSION`, and `start-everest-16` is for OCPP 1.6 only.
After running `pnpm run start-everest` (or `pnpm run start-everest-16`), you should see 3 running EVerest containers
and the `manager` container should have the appropriate EVerest logs.
### EVerest UI
Now that the 3 containers are running in Docker, you should be able to navigate to `[localhost|ip]:1880/ui/` to view
the EVerest simulator UI. There, you should be able to simulate the pause/resume and plug/unplug events among others.
### EVerest NodeRed
You can also view the EVerest NodeRed UI `[localhost|ip]:1880/`, but it is not advisable to make any adjustments here
unless you have a good understanding of this configuration.
### Viewing OCPP logs in EVerest
To view the OCPP logs in EVerest, we have utilized Node `http-server`, which you will see being initialized
in the Dockerfile. We initialize a simple HTTP server on port `8888` and expose this port so that it is
mapped in the compose file allowing you to navigate to `localhost:8888`. This HTTP server is configured to
serve the contents of the `/tmp/everest_ocpp_logs` which is where EVerest stores the OCPP logs in the
Docker container. Conveniently, the logs are in HTML format, so we can easily view them in the browser.
# Running EVerest Manually
You can also use their demo repository that hosts a Docker packaged EVerest image. [See here for Github Repo](https://github.com/EVerest/everest-demo)
To get EVerest running on the side while developing and making changes, you can follow the steps below.
1. Run your CitrineOS instance locally with `docker compose up -d` in the CitrineOS repository.
1. Clone the [EVerest Demo](https://github.com/EVerest/everest-demo) repository and `cd` into the repo.
1. With CitrineOS running execute an "add charger" script at `./citrineos/add-charger.sh` This adds a charger, location and password for the charger to CitrineOS.
1. Bring up EVerest with `docker compose --project-name everest-ac-demo --file "docker-compose.ocpp201.yml" up -d`.
1. Copy over the appropriate device model with `docker cp manager/device_model_storage_citrineos_sp1.db \
everest-ac-demo-manager-1:/ext/source/build/dist/share/everest/modules/OCPP201/device_model_storage.db`.
1. Start EVerst having OCPP2.0.1 support with `docker exec everest-ac-demo-manager-1 sh /ext/source/build/run-scripts/run-sil-ocpp201.sh`.

View File

@@ -0,0 +1,56 @@
# SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project
#
# SPDX-License-Identifier: Apache-2.0
version: '3.6'
services:
mqtt-server:
image: ghcr.io/everest/everest-demo/mqtt-server:${EVEREST_IMAGE_TAG}
platform: linux/x86_64
logging:
driver: none
networks:
- everest_net
manager:
build:
dockerfile: Dockerfile
args:
- EVEREST_IMAGE_TAG=${EVEREST_IMAGE_TAG}
platform: linux/x86_64
ports:
- 8888:8888
deploy:
resources:
limits:
cpus: '2'
memory: '4G'
depends_on:
- mqtt-server
environment:
- MQTT_SERVER_ADDRESS=mqtt-server
- EVEREST_IMAGE_TAG=${EVEREST_IMAGE_TAG}
- OCPP_VERSION=${OCPP_VERSION}
sysctls:
- net.ipv6.conf.all.disable_ipv6=0
extra_hosts:
- 'host.docker.internal:host-gateway'
networks:
- everest_net
nodered:
image: ghcr.io/everest/everest-demo/nodered:${EVEREST_IMAGE_TAG}
depends_on:
- mqtt-server
ports:
- 1880:1880
environment:
- MQTT_SERVER_ADDRESS=mqtt-server
- FLOWS=/config/config-sil-two-evse-flow.json
networks:
- everest_net
networks:
everest_net:
driver: bridge
enable_ipv6: true

View File

@@ -0,0 +1,75 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project
#
# SPDX-License-Identifier: Apache-2.0
_OCPP_VERSION=$OCPP_VERSION
OCPP_VERSION_ENUM="OCPP201"
EVEREST_TARGET_URL="ws://host.docker.internal:8081/cp001"
case "$_OCPP_VERSION" in
"1.6")
OCPP_VERSION_ENUM="OCPP16"
;;
"2.0.1")
OCPP_VERSION_ENUM="OCPP201"
;;
"2.1")
OCPP_VERSION_ENUM="OCPP21"
;;
*)
# NOT in the list
_OCPP_VERSION="2.0.1"
OCPP_VERSION_ENUM="OCPP201"
;;
esac
echo $OCPP_VERSION_ENUM
if [ "$_OCPP_VERSION" != "1.6" ]; then
#There are two different configs in Everest that default their settings that we need to override for Citrine.
#The first is a temp file that may or may not be used by Everest, but to be safe we change the config there.
#The second is the config used by Everest when setting up their image, and this is the primary driver for the configuration of the image.
CONFIG="$(cat <<JSON
[{"configurationSlot": 1, "connectionData": {"messageTimeout": 30, "ocppCsmsUrl": "$EVEREST_TARGET_URL", "ocppInterface": "Wired0", "ocppTransport": "JSON", "ocppVersion": "$OCPP_VERSION_ENUM", "securityProfile": 1}}, {"configurationSlot": 2, "connectionData": {"messageTimeout": 30, "ocppCsmsUrl": "$EVEREST_TARGET_URL", "ocppInterface": "Wired0", "ocppTransport": "JSON", "ocppVersion": "$OCPP_VERSION_ENUM", "securityProfile": 2}}]
JSON
)"
chmod +x /tmp/config.json
jq --argjson config "$CONFIG" '
(.[]
| select(.name == "InternalCtrlr")
| .variables.NetworkConnectionProfiles.attributes.Actual
) = $config
' "/tmp/config.json" > /tmp/config_citrine.json && mv /tmp/config_citrine.json "/tmp/config.json"
chmod -x /tmp/config.json
chmod +x /ext/dist/share/everest/modules/OCPP201/component_config/standardized/InternalCtrlr.json
jq --argjson config "$CONFIG" '
(.
| .properties
| .NetworkConnectionProfiles
| .attributes[]
| select(.type == "Actual")
| .value
) = $config
' "/ext/dist/share/everest/modules/OCPP201/component_config/standardized/InternalCtrlr.json" \
> /tmp/config_citrine_dist.json && mv /tmp/config_citrine_dist.json "/ext/dist/share/everest/modules/OCPP201/component_config/standardized/InternalCtrlr.json"
chmod -x /ext/dist/share/everest/modules/OCPP201/component_config/standardized/InternalCtrlr.json
fi
/entrypoint.sh
http-server /tmp/everest_ocpp_logs -p 8888 &
if [ "$_OCPP_VERSION" = "1.6" ]; then
chmod +x /ext/build/run-scripts/run-sil-ocpp.sh
sed -i "0,/127.0.0.1:8180\/steve\/websocket\/CentralSystemService\// s|127.0.0.1:8180/steve/websocket/CentralSystemService/|${EVEREST_TARGET_URL}|" /ext/dist/share/everest/modules/OCPP/config-docker.json
/ext/build/run-scripts/run-sil-ocpp.sh
else
#Works for all 2.x versions
rm /ext/dist/share/everest/modules/OCPP201/component_config/custom/EVSE_2.json
rm /ext/dist/share/everest/modules/OCPP201/component_config/custom/Connector_2_1.json
chmod +x /ext/build/run-scripts/run-sil-ocpp201-pnc.sh
/ext/build/run-scripts/run-sil-ocpp201-pnc.sh
fi