Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide an ISO 15118-2 AC plus OCPP 1.6J demo #7

Merged
merged 13 commits into from
Dec 7, 2023
Merged
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1 +1 @@
TAG=0.0.6
TAG=0.0.8
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ The use cases supported by the three demos are summarized in conceptual block di
- 🚨 ISO 15118 DC Charging ⚡: `curl https://raw.githubusercontent.com/everest/everest-demo/main/demo-iso15118-2-dc.sh | bash`
- 🚨 Two EVSE Charging ⚡: `curl https://raw.githubusercontent.com/everest/everest-demo/main/demo-two-evse.sh | bash`
- 🚨 E2E Automated Tests ⚡: `curl https://raw.githubusercontent.com/everest/everest-demo/main/demo-automated-testing.sh | bash`
- 🚨 Basic and ISO 15118-2 AC Charging with OCPP 1.6J CSMS ⚡: `curl https://raw.githubusercontent.com/everest/everest-demo/main/demo-iso15118-2-ac-plus-ocpp16j.sh | bash`

### STEP 2: Interact with the demo
- Open the `nodered` flows to understand the module flows at http://127.0.0.1:1880
Expand Down
34 changes: 34 additions & 0 deletions demo-iso15118-2-ac-plus-ocpp16j.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env bash

DEMO_COMPOSE_FILE_NAME='docker-compose.ocpp16j.yml'
DEMO_DIR="$(mktemp -d)"

delete_temporary_directory() { rm -rf "${DEMO_DIR}"; }
trap delete_temporary_directory EXIT

if [[ ! "${DEMO_DIR}" || ! -d "${DEMO_DIR}" ]]; then
echo 'Error: Failed to create a temporary directory for the demo.'
exit 1
fi

download_demo_file() {
local -r repo_file_path="$1"
local -r repo_raw_url='https://raw.githubusercontent.com/everest/everest-demo/main'
local -r destination_path="${DEMO_DIR}/${repo_file_path}"

mkdir -p "$(dirname ${destination_path})"
curl -s -o "${destination_path}" "${repo_raw_url}/${repo_file_path}"
if [[ "$?" != 0 ]]; then
echo "Error: Failed to retrieve \"${repo_file_path}\" from the demo"
echo 'repository. If this issue persists, please report this as an'
echo 'issue in the EVerest project:'
echo ' https://github.com/EVerest/EVerest/issues'
exit 1
fi
}

download_demo_file "${DEMO_COMPOSE_FILE_NAME}"
download_demo_file .env

docker compose --project-name everest-ac-demo \
--file "${DEMO_DIR}/${DEMO_COMPOSE_FILE_NAME}" up
4 changes: 2 additions & 2 deletions docker-compose.automated-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ version: "3.6"

services:
mqtt-server:
image: ghcr.io/us-joet/everest-demo/mqtt-server:${TAG}
image: ghcr.io/everest/everest-demo/mqtt-server:${TAG}
logging:
driver: none

manager:
image: ghcr.io/us-joet/everest-demo/manager:${TAG}
image: ghcr.io/everest/everest-demo/manager:${TAG}
depends_on:
- mqtt-server
environment:
Expand Down
35 changes: 27 additions & 8 deletions docker-compose.build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,48 @@ services:
mqtt-server:
image: ghcr.io/everest/everest-demo/mqtt-server:${TAG}
build: mosquitto
platform: linux/x86_64
logging:
driver: none

manager:
image: ghcr.io/everest/everest-demo/manager:${TAG}
build: manager
platform: linux/x86_64
depends_on:
- mqtt-server
environment:
- MQTT_SERVER_ADDRESS=mqtt-server
entrypoint: "sh ./build/run-scripts/run-sil.sh"
entrypoint: "sh ./build/run-scripts/run-sil-ocpp.sh"
sysctls:
- net.ipv6.conf.all.disable_ipv6=0

node-red:
image: ghcr.io/everest/everest-demo/nodered:${TAG}
ocpp-db:
image: mariadb:10.4.30
command: [ "--datadir", "/var/lib/mysql-no-volume" ]
ports:
- 13306:3306
environment:
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
MYSQL_DATABASE: ocpp-db
MYSQL_USER: ocpp
MYSQL_PASSWORD: ocpp

steve:
build: steve
ports:
- 8180:8180
- 8443:8443
depends_on:
- ocpp-db

nodered:
build: nodered
image: ghcr.io/everest/everest-demo/nodered:${TAG}
depends_on:
- mqtt-server
environment:
- MQTT_SERVER_ADDRESS=mqtt-server
- FLOWS=/config/config-sil-flow.json
ports:
- 1880:1880
sysctls:
- net.ipv6.conf.all.disable_ipv6=0
environment:
- MQTT_SERVER_ADDRESS=mqtt-server
- FLOWS=/config/config-sil-two-evse-flow.json
48 changes: 48 additions & 0 deletions docker-compose.ocpp16j.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
version: "3.6"

services:
mqtt-server:
image: ghcr.io/everest/everest-demo/mqtt-server:${TAG}
platform: linux/x86_64
logging:
driver: none

manager:
image: ghcr.io/everest/everest-demo/manager:${TAG}
platform: linux/x86_64
depends_on:
- mqtt-server
environment:
- MQTT_SERVER_ADDRESS=mqtt-server
entrypoint: "sh ./build/run-scripts/run-sil-ocpp.sh"
sysctls:
- net.ipv6.conf.all.disable_ipv6=0

ocpp-db:
image: ghcr.io/us-joet/everest-demo/ocpp-db-compiled:0.0.1
command: [ "--datadir", "/var/lib/mysql-no-volume" ]
ports:
- 13306:3306
environment:
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
MYSQL_DATABASE: ocpp-db
MYSQL_USER: ocpp
MYSQL_PASSWORD: ocpp

steve:
image: ghcr.io/us-joet/everest-demo/steve-configured:0.0.1
ports:
- 8180:8180
- 8443:8443
depends_on:
- ocpp-db

nodered:
image: ghcr.io/everest/everest-demo/nodered:${TAG}
depends_on:
- mqtt-server
ports:
- 1880:1880
environment:
- MQTT_SERVER_ADDRESS=mqtt-server
- FLOWS=/config/config-sil-two-evse-flow.json
17 changes: 17 additions & 0 deletions steve/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
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/RWTH-i5-IDSG/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 .

CMD /steve/init.sh
57 changes: 57 additions & 0 deletions steve/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# SteVe Image

The [SteVe](https://github.com/steve-community/steve) image provides a simulated
OCPP Central System for the OCPP 1.6J demo.

## Looking for the SteVe OCPP 1.6J demo?
You've gone to far! Please visit the root directory of this repository to find the OCPP 1.6J Docker Compose file and a one-liner in the README.md for executing it.

## For Demo Developers Only: Build & Configuration Process
There are currently automated and manual steps to building this image.

First, a SteVe image is created without chargers or OCPP ID tags configured and stood up as a service using Docker Compose. This can be done by running the following command from the root of this Git repository:
```shell
docker compose -f docker-compose.build.yml up -d steve
```

The build process is fairly long, taking anywhere from 5--30 minutes on a modern system. Once an image is built, a SteVe server will be running in a container alongside a MariaDB instance configured to provide a database layer for SteVe.

The remainder of the setup process is manual:
1. With SteVe and MariaDB containers still running, visit http://localhost:8180
2. Log into the SteVe server with username `admin` and password `1234` when prompted.
3. Visit http://localhost:8180/steve/manager/chargepoints/add
4. Enter a `ChargeBox ID` of `cp001` and set `Registration status` to `Accepted`.
5. Click the `Add` button at the bottom of the form.
6. Visit http://localhost:8180/steve/manager/ocppTags/add
7. Enter an `ID Tag` value of `DEADBEEF` and a `Max. Active Transaction Count` of `2`.
8. Click the `Add` button at the bottom of the form.
9. Repeat steps 6--8 for two additional OCPP ID tags with the following attributes:
- `ID Tag`: `ABC12345`, `Max. Active Transaction Count`: `1`
- `ID Tag`: `VID:AABBCCDDEEFF`, `Max. Active Transaction Count`: `0`
10. Visit the [EVerest steve-configured package page](https://github.com/EVerest/everest-demo/pkgs/container/everest-demo%2Fsteve-configured) on GitHub and determine the most recent `A.B.C` tag for this image.
11. Use [semantic versioning](https://semver.org) to determine what the appropriate updated tag is for your new version of the `steve-configured` image.
12. From a terminal, commit the running SteVe container using
```shell
docker commit everest-demo-steve-1 ghcr.io/everest/everest-demo/steve-configured:X.Y.Z
```
where `X.Y.Z` should be replaced with the new semantic version for the image you determined in step 11.
13. Repeat steps 10--12 for the running MariaDB container and [EVerest `ocpp-db-compiled` image](https://github.com/EVerest/everest-demo/pkgs/container/everest-demo%2Focpp-db-compiled). Your Docker Commit command should look like the following:
```shell
docker commit everest-demo-ocpp-db-1 ghcr.io/everest/everest-demo/ocpp-db-compiled:X.Y.Z

```
again replacing `X.Y.Z` with the relevant semantic version from step 11.
14. Push each of these newly-created image versions to the EVerest project with
```shell
# Remember to replace the X.Y.Z with your new version tag!
docker push ghcr.io/everest/everest-demo/steve-configured:X.Y.Z
```
and
```shell
# Remember to replace the X.Y.Z with your new version tag!
docker push ghcr.io/everest/everest-demo/ocpp-db-compiled:X.Y.Z
```

> **Note:** The OCPP ID tags are configured so that `DEADBEEF` (the default) can authenticate against two chargers simultaneously (that is, can be involved in two concurrent transactions). In contrast, `ABC12345` can only work one charger at a time, and `VID:AABBCCDDEEFF` is blocked entirely from charging vehicles. Choosing different combinations of demo connectors and OCPP tags (as well as authenticating before/after plugging in a simulated vehicle) can demonstrate a variety of basic authentication scenarios. The configurations for these IDs can be modified within the SteVe administration webapp to support other scenarios.
>
> The OCPP Tag IDs themselves are defined in the Node-Red flows for the two EVSE demo.
10 changes: 10 additions & 0 deletions steve/init.sh
Original file line number Diff line number Diff line change
@@ -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
Binary file added steve/keystore.jks
Binary file not shown.
57 changes: 57 additions & 0 deletions steve/main.properties
Original file line number Diff line number Diff line change
@@ -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