How to boot the Smart Charging Service?
This document teaches:
How to start the Smart Charging Service.
How to configure the Smart Charging Service using its command line interface.
What is required to bring the service to a “ready” state.
For this guide, you need:
A Smart Charging Service binary.
An MQTT broker.
The tools
mosquitto_sub
andmosquitto_pub
. On Debian and derivatives, these tools are part of the mosquitto-clients package. On Mac, you can install the tools using Homebrew.The script at the bottom of this document that mocks the charging station. In a real scenario, the messages MQTT messages generated by this script are generated by the OEM instead.
The Smart Charging Service is part of Josev Pro Unified Bundle. However, the service can also operate as an isolated service.
Configuration
By default, smart-charging-service
tries to connect to an MQTT broker at [localhost](http://localhost)
at port 1883. You can change the connection parameters using the command line flags --mqtt-host
and --mqtt-port
. Alternatively, you can use the environment variables MQTT_HOST
and MQTT_PORT
.
Run smart-charging-service --help
to list all configuration options:
$ ./smart-charging-service --help
Usage: smart-charging-service [OPTIONS]
Options:
--mqtt-host <MQTT_HOST> The address of the MQTT broker to connect to [env: MQTT_HOST=] [default: localhost]
--mqtt-port <MQTT_PORT> The port of the MQTT broker to connect to [env: MQTT_PORT=] [default: 1883]
--log-level <LOG_LEVEL> The verbosity of the application, options are TRACE, DEBUG, INFO, WARN and ERROR [env: LOG_LEVEL=] [default: INFO]
-h, --help Print help
-V, --version Print version
Start script that simulate OEM
Before starting the Smart Charging Service, open a terminal and start the script that is included at the bottom of this document. That script simulates the messages that are normally generated by the OEM.
You can use the environment variables MQTT_HOST
and MQTT_PORT
to control the connection details. By default, the script connects to a broker at localhost:1883
.
terminal 1$ ./simulate_oem.sh
Connecting to localhost:1883
Start Smart Charging Service
In a new terminal, invoke the smart-charging-service
. You should see something like this:
terminal 2$ ./smart-charging-service
2023-12-13T15:58:19.979904Z INFO smart_charging_service: VERSION="0.1.8"
2023-12-13T15:58:19.979953Z INFO smart_charging_service: Connect to MQTT broker. host="localhost" port=1883
2023-12-13T15:58:19.980211Z INFO smart_charging_service: Outbound MQTT message. topic=josev/cs request=MqttMessage { id: 89a748b1-d81c-4f6a-b99b-dc4f0a03229d, body: ServiceStatus(Update(ServiceStatusUpdate { service: SmartCharging, software_version: "0.1.5", api_version: "1.5.14", status: Starting })) }
2023-12-13T15:58:19.980322Z INFO smart_charging_service: Outbound MQTT message. topic=josev/cs request=MqttMessage { id: a458e252-e295-47ca-8120-5daf6c776a28, body: CsParameters(Request(CsParametersRequest)) }
2023-12-13T15:58:20.026220Z INFO smart_charging_service: Inbound MQTT message. topic=cs/josev body=MqttMessage { id: a458e252-e295-47ca-8120-5daf6c776a28, body: CsParameters(Response(CsParametersResponse { sw_version: "v1.0.1", hw_version: "v2.0.0", number_of_evses: 1, parameters: [CsParametersResponseEntry { evse_id: "GB*SEV*E123456789", supports_eim: false, network_interface: "eth2", connectors: [CsParametersConnector { id: 1, services: CsParametersConnectorService { ac: Some(CsParametersConnectorServiceAc { common: CsParametersConnectorServiceCommon { connector_type: ACThreePhaseCore, control_mode: None }, nominal_voltage: 230 }), ac_bpt: None, dc: None, dc_bpt: None } }] }] })) }
2023-12-13T15:58:20.026471Z INFO smart_charging_service: Outbound MQTT message. topic=josev/cs request=MqttMessage { id: ab0f970c-804d-41c9-9d17-6aa826e3a073, body: CsStatusAndLimits(Request(CsStatusAndLimitsRequest)) }
2023-12-13T15:58:20.070008Z INFO smart_charging_service: Inbound MQTT message. topic=cs/josev body=MqttMessage { id: ab0f970c-804d-41c9-9d17-6aa826e3a073, body: CsStatusAndLimits(Response(CsStatusAndLimitsResponse { evses: [CsStatusAndLimitsEvse { evse_id: "GB*SEV*E123456789", status_code: EvseReady, ac: Some(CsStatusAndLimitsEvseAcLimits { ac: CsStatusAndLimitsAc { max_current: AcMaxCurrent { l1: 16.0, l2: 16.0, l3: 16.0 }, nominal_voltage: 230.0, rcd_error: false }, ac_bpt: None }), dc: None }] })) }
2023-12-13T15:58:20.070398Z INFO smart_charging_service: Outbound MQTT message. topic=josev/cs request=MqttMessage { id: 5f68db5a-1e3e-45cd-8437-b7a0d1c2d960, body: ServiceStatus(Update(ServiceStatusUpdate { service: SmartCharging, software_version: "0.1.5", api_version: "1.5.14", status: Ready })) }
Let’s go through this:
Line 1 shows the version of the Smart Charging Service:
0.1.8
Line 2 shows the connection details of the MQTT connection.
In line 3, the Smart Charging Service announces that it is “starting” using a
ServiceStatusUpdate
.The service is stateless. In lines 4 and 6 the service sends a
CsParametersRequest
and aCsStatusAndLimitsRequest
to discover the technical layout of the charger.The script in terminal 1 responds to these requests, as you can see in lines 5 and 7. The responses carry information about the number of EVSEs, their names, the number of connectors and the rated limits of all the electronics. In this particular example, the charger has 1 EVSE that delivers power to 1 AC connector. The connector is rated for a maximum current of 16A on each phase.
In line 7, the service reports that it’s “ready”. From now on the service is ready to impose charge limits on the EVSE.
Terminal 1 should show something like this:
terminal 1$ ./simulate_oem.sh
Connecting to localhost:1883
Smart Charging Service is "starting".
Responding to cs_paramaters request with id c714ccbc-6c39-4ff6-a2e0-01ff6ddfd8a1.
Responding to cs_status_and_limits request with id 26560c8b-8717-4a3c-a648-cfa07a103072.
Smart Charging Service is "ready".
You’re done: the Smart Charging Service booted successfully. Now continue with How to control the limit imposed by the Smart Charging Service?
Script simulating charger OEM
This is a script that simulates the OEM. The script subscribes to the MQTT topic “josev/cs” and responds to the requests “cs_paramaters” and “cs_status_and_limits”.
#!/bin/sh
type mosquitto_sub > /dev/null && type mosquitto_pub > /dev/null
if [ $? -ne 0 ]; then
echo "This script requires 'mosquitto_sub' and 'mosquitto_pub'."
echo "These tools are not found. To install those on Ubuntu"
echo "or alike, run:"
echo ""
echo " sudo apt install mosquitto-clients"
exit 1
fi
set -e
mqtt_host=${MQTT_HOST:-"localhost"}
mqtt_port=${MQTT_PORT:-1883}
topic_cs_josev="cs/josev"
topic_josev_cs="josev/cs"
# Filter the UUID of a message.
filter_message_id() {
message=$1
# Thanks to https://unix.stackexchange.com/a/561833
echo $message | grep -Eo "([a-f0-9-]+-){4}[a-f0-9-]+"
}
# Publish a CsParamaters response.
publish_cs_paramaters_response() {
message_id=$1
response=$(cat <<EOF
{
"id": "$message_id",
"type": "response",
"name": "cs_parameters",
"data": {
"sw_version": "v1.0.1",
"hw_version": "v2.0.0",
"number_of_evses": 1,
"parameters": [
{
"evse_id": "GB*SEV*E123456789",
"connectors": [
{
"id": 1,
"services": {
"ac": {
"connector_type": "AC_three_phase_core",
"nominal_voltage": 230
}
}
}
],
"supports_eim": false,
"network_interface": "eth2"
}
]
}
}
EOF
)
echo "Responding to cs_paramaters request with id $message_id."
mosquitto_pub -t $topic_cs_josev -m "$response"
}
publish_cs_status_and_limits_response() {
message_id=$1
response=$(cat <<EOF
{
"id": "$message_id",
"type": "response",
"name": "cs_status_and_limits",
"data": {
"evses": [
{
"evse_id": "GB*SEV*E123456789",
"status_code": "evse_ready",
"ac": {
"max_current": {
"l1": 16,
"l2": 16,
"l3": 16
},
"nominal_voltage": 230,
"rcd_error": false
}
}
]
}
}
EOF
)
echo "Responding to cs_status_and_limits request with id $message_id."
mosquitto_pub -h $mqtt_host -p $mqtt_port -t $topic_cs_josev -m "$response"
}
process_message() {
message=$1
message_id=$(filter_message_id $message)
if [ $(echo $message | grep -c -e "cs_parameters") -eq 1 ]; then
publish_cs_paramaters_response $message_id
fi
if [ $(echo $message | grep -c -e "cs_status_and_limits") -eq 1 ]; then
publish_cs_status_and_limits_response $message_id
fi
if [ $(echo $message | grep "service_status" | grep -c -e "smart_charging") -eq 1 ]; then
status=$(echo $message | grep -Po '"status": *\K"[^"]*"')
echo "Smart Charging Service is $status."
fi
}
echo "Connecting to $mqtt_host:$mqtt_port"
mosquitto_sub -h $mqtt_host -p $mqtt_port -t $topic_josev_cs | grep "id" --line-buffered | while read line; do process_message $line; done