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 and mosquitto_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-hostand --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:

  1. Line 1 shows the version of the Smart Charging Service: 0.1.8

  2. Line 2 shows the connection details of the MQTT connection.

  3. In line 3, the Smart Charging Service announces that it is “starting” using a ServiceStatusUpdate .

  4. The service is stateless. In lines 4 and 6 the service sends a CsParametersRequest and a CsStatusAndLimitsRequest to discover the technical layout of the charger.

  5. 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.

  6. 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