The following examples will guide you through administration of an SCN Node, as well as basic Open Charge Point Interface implementation guidelines to aid with development of eMobility Service Provider (eMSP) or Charge Point Operator (CPO) backoffices.
To follow and run the examples, there are a few dependencies that must first be met:
You will first need to install Docker and docker-compose on your chosen platform to run the local network.
Next, ensure that the SCN Registry and Node repositories are cloned under the same parent directory:
git clone git@bitbucket.org:smartcharging/scn-registry.git
git clone git@bitbucket.org:smartcharging/scn-node.git
The directory structure should look like so:
- scn/
| - scn-registry/
| - scn-node/
Then change directory to scn-node and run the network:
cd scn-node
./gradlew -Pprofile=docker -x test build
docker-compose up
The first build will take a few minutes but subsequent docker-compose up commands will be much faster. Whilst the Docker
images are being built, you may look over the details of the network below, which may or may not mean anything depending
on prior knowledge of Ethereum blockchain technology. Don't worry if they do not, as they will be explained in the following
section when we walk through the example requests.
- SCN Registry smart contract deployed on a local development Ethereum blockchain (ganache)
- address:
0x7ab1a34dEb3209a1d6Fd57Ae5f2f81E857bc5ba1 - owner:
0x627306090abaB3A6e1400e9345bC60c78a8BEf57
- address:
- A Wallet containing 20 addresses each pre-funded with 100 ETH
- mnemonic:
candy maple cake sugar pudding cream honey rich smooth crumble sweet treat
- mnemonic:
- Reachable blockchain JSON RPC API
- provider:
http://localhost:8544
- provider:
- Two SCN Nodes connected to the same SCN Registry as above
- node 1 address:
http://localhost:8080 - node 2 address:
http://localhost:8081 - admin API keys for both nodes:
randomkey
- node 1 address:
Once the images are built and the containers are running, we will see information about the two nodes displayed in stdout, for example its API key, wallet address and public URL.
The node checks its own health endpoint on start to make sure it is configured correctly. We can also manually ensure that both nodes are running, like so:
curl localhost:8080/health
curl localhost:8081/health
Both requests should return 200 OK. Now leave the network running and open a new terminal session.
The SCN Demo repository contains mock eMSP and CPO backoffices, as well as a script which will allow us to register to the SCN Registry. Clone it by returning to the parent directory:
cd ..
git clone git@bitbucket.org:smartcharging/scn-demo.git
cd scn-demo
npm install
The demo contains two Charge Point Operators (CPOs) and one eMobility Service Provider (EMSP). Starting the demo will start the respective backends and register the CPOs to the Smart Charging Network that we have running in the background:
npm start
Observe the requests that are made to ganache, the scn-node and the CPO server. This gives a quick overview of how the SCN registration process using SCPI and the SCN Registry looks. For those familiar with SCPI, you will see the CPOs receiving versions and version detail requests, as the SCN node processes the credentials registration.
Leave the servers running in the background, alongside the network. The next step is to install Postman so that we can register our EMSP to the network.
In order to visualize HTTP API requests, we can use Postman. Once installed, simply import the JSON collection and environment files provided in this directory. You will need to change your environment to the provided "SCN Node" environment that you just imported, by selecting it from the dropdown menu in the top right corner of Postman. This will allow you to easily change common variables across all your requests in the future.
In this tutorial, we will create an SCPI 2.2 connection with the SCN Node at http:localhost:8080. If you completed the above step, there should be one CPO already registered with our SCN Node and another at http://localhost:8081, which gives us a chance to make different requests across the network.
Before we create a connection to an SCN Node, we must enter our party into the SCN Registry to become visible on the network. To do this, we must sign a transaction which states our party's country code and party ID as well as the public information of the SCN Node we will connect to. The SCN Node information that we need is its Ethereum wallet address.
Provided in the Postman collection is a request GET Node Info under the SCN directory. Note that there is no
authorization needed to make this request and the variable {{NODE_URL}} has been configured to http://localhost:8080
within the "SCN Node" environment that you imported. To change environment variables, click the eye symbol button next
to the dropdown menu where you selected the environment. The response should be the following:
{
"url": "http://localhost:8080",
"address": "0x9bc1169ca09555bf2721a5c9ec6d69c8073bfeb4"
}You might recall briefly seeing the same information printed to stdout when running the local SCN. As we are also
running our node, we already know this information. If connecting to a remote node, we can use this request to provide
the same information. Now that we have the node's wallet address, we can use the SCN Registry Command Line Interface (CLI)
to add our EMSP party to the Registry, linking it to the node on http://localhost:8080. As we already have the
registry repository, we can use the CLI from the source code directly:
cd scn-registry
npm install
export SIGNER=0x49b2e2b48cfc25fda1d1cbdb2197b83902142c6da502dcf1871c628ea524f11b
npx ts-node src set-party -c DE MSP -r EMSP -o 0x9bc1169ca09555bf2721a5c9ec6d69c8073bfeb4
Here, we are adding a party to the registry with SCPI credentials (country_code and party_id) DE MSP. Our wallet
(the signer) has address 0xcb0236B37Ff19001633E38808bd124b60B1fE1ba. We have one role: EMSP. Our SCN Node operator has
the wallet address 0x9bc1169ca09555bf2721a5c9ec6d69c8073bfeb4 and has already listed their node in the registry. You
can validate node and party listings as follows:
npx ts-node src get-party -c DE MSP
npx ts-node src get-party -a 0xcb0236B37Ff19001633E38808bd124b60B1fE1ba
npx ts-node src get-node 0x9bc1169ca09555bf2721a5c9ec6d69c8073bfeb4
Now that we have listed ourselves in the SCN Registry smart contract, we need to create a connection with our SCN Node.
In order to connect to an SCN Node, the administrator first must generate a token to be used in the SCPI credentials
registration flow. This, described as CREDENTIALS_TOKEN_A, will be used to obtain information about the SCN Node,
e.g. the version of SCPI it is using and the modules it incorporates.
In Postman, simply go to the GET Generate Registration Token request in the Admin directory of the SCN Node
collection and hit Send to make the request. The authorization token ({{ADMIN_API_KEY}}) has already been declared in
the "SCN Node" environment.
You should see the following response:
{
"token": {{CREDENTIALS_TOKEN_A}},
"versions": "http://localhost:8080/scpi/versions"
}
Taking the provided token, we can now set our environment variable, using the eye symbol button in Postman, as described before.
Our EMSP backend runs on SCPI 2.2. As such we would like to establish a connection to the SCN Node using the same
SCPI version. In Postman, navigate to the Versions directory and send the GET versions request.
This is our first chance to see the SCPI JSON response format, containing the SCPI status code of the response, the
timestamp, and (optionally) any data returned. If the request is made with an incorrect token, the HTTP status code
will be 401 rather than 200, and the data field will be (optionally) replaced with status_message.
The data field should provide an array of supported versions and a url that will provide information regarding how to use this version.
Do the same for the next request in the directory, for retrieving version details. The response will contain an array
of endpoints supported by the node. The one we are most interested in for now is the credentials module:
{
"identifier": "credentials",
"role": "SENDER",
"url": "http://localhost:8080/scpi/2.2/credentials"
}Now that we know where to send our credentials, we can open the POST credentials request in the credentials directory.
This request contains a JSON body of our own credentials to be sent to the SCN Node. This includes the token that the
SCN Node should use to authorize itself on our server, should it need to forward a request to us from a CPO (i.e. if
the CPO is pushing session or location updates to us). We also provide a url to our versions endpoint, such that the
SCN Node can go through the same process we just did, in finding a common SCPI version and obtaining a list of the
endpoints we have. Lastly, we describe the roles that we employ. Notice how this is an array. SCPI 2.2 adds the ability
for a platform operating multiple roles to communicate on a single SCPI connection. Therefore a platform that is both an
EMSP and CPO needs not register twice.
{
"status_code": 1000,
"data": {
"token": "ef4c3b29-5679-4bb9-8a59-4c53fc3dacef",
"url": "http://localhost:8080/scpi/versions",
"roles": [
{
"role": "HUB",
"business_details": {
"name": "Smart Charging Network Node"
},
"party_id": "SCN",
"country_code": "DE"
}
]
},
"timestamp": "2020-01-15T09:56:56.547Z"
}Once sent, you should see the SCN Node's credentials returned to you. There is a new token in the body: this is what's
known as token C and will be used to authorize any subsequent SCPI requests you make to your SCN Node.
The previous token is now discarded and will not be used again, so make sure to save this new token under the
environment variable CREDENTIALS_TOKEN_C.
In addition, you should see that there were two requests made to the EMSP server in the logs of the SCN demo. This shows that the SCN Node has requested and stored your SCPI module endpoints for future use.
This now completes the registration to the SCN Node.
Now that we have registered to our SCN Node, we can send requests to one of the registered CPOs on the SCN. In this
request, we wish to fetch a list of the CPO's locations (i.e. charging stations under SCPI terminology). To do so,
send the GET locations list request in the locations directory of the Postman collection.
The result should look like the following:
{
"status_code": 1000,
"data": [
{
"country_code": "DE",
"party_id": "CPO",
"id": "LOC1",
"publish": true,
"address": "somestreet 1",
"city": "Essen",
"country": "DEU",
"coordinates": {
"latitude": "52.232",
"longitude": "0.809"
},
"evses": [
{
"uid": "1234",
"status": "AVAILABLE",
"connectors": [
{
"id": "1",
"standard": "IEC_62196_T2",
"format": "SOCKET",
"power_type": "AC_3_PHASE",
"max_voltage": 400,
"max_amperage": 32,
"tariff_ids": [
"xxx-123"
],
"last_updated": "2019-08-13T14:44:25.561Z"
}
],
"last_updated": "2019-08-13T14:44:25.561Z"
},
{
"uid": "4567",
"status": "RESERVED",
"connectors": [
{
"id": "1",
"standard": "IEC_62196_T2",
"format": "SOCKET",
"power_type": "AC_3_PHASE",
"max_voltage": 400,
"max_amperage": 32,
"tariff_ids": [
"xyz-456"
],
"last_updated": "2019-08-13T14:44:25.561Z"
}
],
"last_updated": "2019-08-13T14:44:25.561Z"
}
],
"last_updated": "2019-08-13T14:44:25.561Z"
}
],
"timestamp": "2019-08-13T15:25:24.435Z"
}We see that the request was successfully processed, returning an array of a single location. The SCPI location data
type follows a hierarchy of location -> evse -> connector. We can make also make requests that fetch a single
location, or a specific EVSE or connector. Take a look at the other requests in the locations directory to see how they
work.
The headers prefixed with SCPI- describe the desired routing of the message. The SCPI-from-country-code and
SCPI-from-party-id describe the SCPI party on the platform which is making the request (in our case we only have one
party per platform, but it could be the case that a CPO and EMSP role share the same platform connection with an SCN
node). Likewise, the SCPI-to-country-code and SCPI-to-party-id headers describe the recipient of the request. In
our case we are making requests to a CPO with country code DE and party ID CPO. This CPO is registered to the same
SCN Node as our EMSP, but what if we want to contact a "remote" party connected to a different SCN Node? We can
try this out by changing the request headers to the following:
SCPI-to-country-code: NL
SCPI-to-party-id: CPX
Note also the X-Request-ID and X-Correlation-ID headers. They don't play a role in our demonstration (both being
set to "1" for all requests, but in production it is strongly advised to generate unique IDs (uuid version 4 preferred)
for all requests, in order to help with any potential debugging. The request ID is unique for every request: in
forwarding such a request: an SCN Node will actually set a new request ID when forwarding a message. The correlation
ID meanwhile, is unique for every request-response: an SCN Node will never change the correlation ID.
Let's check out the other request types we can make now. Notice how on the Connector object there is a tariff_ids array.
What does this mean?
Navigate to the tariffs directory and send the GET tariffs request. You should see in the response's body an array of
tariffs provided by the CPO, with IDs matching those found on the Connector object. This is an example of a dependency
between SCPI modules.
However, all SCPI modules aside from credentials are optional (for the purpose of the demo the
EMSP and CPOs have not implemented the credentials interface, but it is important to do so, as the SCN Node could
need to update its credentials on your system). It is up to the EMSP/CPO (or any other role) to implement the modules
themselves. Therefore if we try to make, for instance, a sessions request to the CPO, we might receive a message
telling us that the CPO has not implemented the module (yet).
Our EMSP has actually implemented two SCPI modules: commands and cdrs. The first of which is the SENDER interface
which allows the CPO to asynchronously notify the EMSP of a command result, i.e. a session has been started by a charge
point. The second allows the CPO to push Charge Detail Records (CDRs), containing the final price of a charging session,
to the EMSP. This reduces the load on the CPO backend as the EMSP doesn't need to poll for new CDRs.
We can see this first hand by sending the requests in the commands directory. The first, POST START_SESSION, will
send a start session request on behalf of a driver on the EMSP system. For this request, we can also monitor the output
of our demo servers. The initial response from our Postman request contains only an acknowledgement of the request.
After 5 seconds the CPO will send the async command result (the response from the charge point):
CPO [DE CPO] sending async STOP_SESSION response
EMSP [DE MSP] received async command response: {"result":"ACCEPTED"}
EMSP [DE MSP] -- POST /scpi/emsp/2.2/commands/STOP_SESSION/2 200 59 - 0.734 ms
Likewise, when we make a POST STOP_SESSION request, we see the following a further 5 seconds after the async response
has been sent to the EMSP:
CPO [DE CPO] sending cdr after session end
EMSP [DE MSP] -- POST /scpi/emsp/2.2/cdrs 200 59 - 0.487 ms
EMSP [DE MSP] -- GET /scpi/emsp/2.2/cdrs/1 200 1124 - 0.784 ms
CPO [DE CPO] acknowledges cdr correctly stored on EMSP system
In this case, the CPO has sent a POST cdrs request to the EMSP, the response of which will contain a Location header
set by the EMSP describing where the CPO can find this charge detail record on the EMSP system. The CPO can then make
a GET request to this location to verify that the CDR was stored correctly by the EMSP.
That marks the end of this tutorial. More examples and use cases will be added to this tutorial in the future, but for now this should be enough to get started on creating an SCPI 2.2 platform that is ready to join the Smart Charging Network.
See the SCN Node HTTP API documentation for more requests, including a link to the full SCPI API.