ocppjs - An experimental OCPP Simulator

Overview

Open Charge Point Protocol (OCPP, http://ocppforum.net) is a communication protocol between multiple charging stations ("charge points") and a single management software ("central system").

Currently (december 2012), two OCPP versions (1.2 and 1.5) have been released. There is a draft in progress for a new version (2.0). Both existing versions use SOAP over HTTP as the RPC/transport protocol:

+---------------+ soap/http client      soap/http server +---------------+
|               |--------------------------------------->|               |
|               |  Operations initiated by ChargePoint   |               |
|  ChargePoint  |                                        | CentralSystem |
|               | soap/http server      soap/http client |               |
|               |<---------------------------------------|               |
+---------------+  Operations initiated by CentralSystem +---------------+

The two main problems with this solution are:

This project proposes a new RPC/transport for OCPP, that addresses these two issues, using Websocket (http://tools.ietf.org/html/rfc6455) for the transport layer, and SPRC (see Protocol Specification section below) for the RPC layer.

Architecture

This schema shows objects instances for a system with one ChargePointSimulator and one CentralSystemSimulator.

+------------------------+             +------------------------+
|  ChargePointSimulator  |             | CentralSystemSimulator |
+------------------------+             +------------------------+
  |create (param: url)                   |create (param: listening tcp port)
  V                                      V
+------------------------+   connect   +------------------------+
|     WebSocketClient    |------------>|     WebSocketServer    |
+------------------------+             +------------------------+

When a WebSocket connection (i.e. a transport layer) is established, each peer creates:

This gives two independant RPC channels on a single TCP connection:

  +------------------------+             +------------------------+
+-|  ChargePointSimulator  |             | CentralSystemSimulator |-+
| +------------------------+             +------------------------+ |
| create (param: connection)              create (param: connection)|
|                                                                   |
| +------------------------+             +------------------------+ |
+>|  WampClientConnection  |------------>|  WampServerConnection  |<+
| +------------------------+  RPC call   +------------------------+ |
|                           (e.g. MeterValue)                       |
|                                                                   |
| +------------------------+             +------------------------+ |
+>|  WampServerConnection  |<------------|  WampClientConnection  |<+
  +------------------------+  RPC call   +------------------------+
                            (e.g. Reset)

Installation & usage

This program requires Node.js (http://nodejs.org/). Third-party packages can be installed with the npm utility. Currently, ocppjs depends on 'websocket', 'xml2js', 'node-expat', 'request' and 'jayschema' packages:

% npm install

To run the OCPP.js simulator, just enter

% node gir-ocppjs.js

You will be given a prompt where you can enter commands.

Commands syntax:

Argument customization:

When typing remote_<cmd> or <cmd>, the fields of the payload can be customized individually from the command line interface using the following syntax:

argument=value ...

> bootnotification chargePointVendor="DBT"
> bootnotification chargePointVendor="DBT" chargePointModel="NQC-ACDC"

value handles string, number, object and array types.

Example - Running a CentralSytem

% node gir-ocppjs.js start_cs 9000
[2012-12-28 14:54:32] CentralSystem started.
[2012-12-28 14:54:32] cs: Server is listening on port 9000
[2012-12-28 14:54:44] cs: ChargePoint #0 connected from 127.0.0.1.

>
[2012-12-28 14:54:54] cs: <<cp#0 [2,"V7NeDL1MnbkaQcaHcYnvxOpCdcI4gpAV",
                      "BootNotification",{"chargePointVendor":"DBT",
                      "chargePointModel":"NQC-ACDC",...}]
[2012-12-28 14:54:54] cs: >>cp#0 [3,"V7NeDL1MnbkaQcaHcYnvxOpCdcI4gpAV",
                      {"status":"Accepted",
                      "currentTime":"2012-11-28T13:54:44Z",
                      "heartbeatInterval":300}]

> remote_reset type="Soft"
[2012-12-28 14:56:50] cs: >>cp#0 [2,"tU8hVs8yY6Aleie1kN8fXD7YUJ0PDuyc",
                      "Reset",{"type":"Soft"}]
[2012-12-28 14:56:50] cs: <<cp#0 [3,"tU8hVs8yY6Aleie1kN8fXD7YUJ0PDuyc",
                      {"status":"Accepted"}]

>
[2012-12-28 14:58:22] cs: <<cp#0 [2,"Shfrho1gR2NmsjCVeHpCOjImdNxhPPXq",
                      "MeterValues",{"connectorId":1,values:[{
                      "timestamp":"2012-12-28T13:58:22Z","value":0}]}]
[2012-12-28 14:58:22] cs: >>cp#0 [3,"Shfrho1gR2NmsjCVeHpCOjImdNxhPPXq",
                      {}]

>
[2012-12-28 14:59:44] cs: <<cp#0 [2,"yUtxCAuRRv26dKRuQ1fy1AYvE0fZTZ2Z",
                      "Heartbeat",{}]
[2012-12-28 14:59:44] cs: >>cp#0 [3,"yUtxCAuRRv26dKRuQ1fy1AYvE0fZTZ2Z",
                      {"currentTime":"2012-12-28T13:59:44Z"}]

Example - Running a ChargePoint

% node gir-ocppjs.js start_cp ws://localhost:9000 0
[2012-12-28 14:54:44] ChargePoint #0 started.
[2012-12-28 14:54:44] cp#0: Connected to CentralSystem.

> bootnotification chargePointVendor="DBT" chargePointModel="NQC-ACDC"
[2012-12-28 14:54:54] cp#0: >>cs [2,"V7NeDL1MnbkaQcaHcYnvxOpCdcI4gpAV",
                      "BootNotification",{"chargePointVendor":"DBT",
                      "chargePointModel":"NQC-ACDC",...}]
[2012-12-28 14:54:54] cp#0: <<cs [3,"V7NeDL1MnbkaQcaHcYnvxOpCdcI4gpAV",
                      {"status":"Accepted",
                      "currentTime":"2012-12-28T13:54:44Z",
                      "heartbeatInterval":300}]

>
[2012-12-28 14:56:50] cp#0: <<cs [2,"tU8hVs8yY6Aleie1kN8fXD7YUJ0PDuyc",
                      "Reset",{"type":"Soft"}]
[2012-12-28 14:56:50] cp#0: >>cs [3,"tU8hVs8yY6Aleie1kN8fXD7YUJ0PDuyc",
                      {"status":"Accepted"}]

> metervalues
[2012-12-28 14:58:22] cp#0: >>cs [2,"Shfrho1gR2NmsjCVeHpCOjImdNxhPPXq",
                      "MeterValues", {"connectorId":2,
                      values:[{"timestamp":"2012-12-28T13:58:22Z",
                      "value":0}]}]
[2012-12-28 14:58:22] cp#0: <<cs [3,"Shfrho1gR2NmsjCVeHpCOjImdNxhPPXq",
                      {}]

> heartbeat
[2012-12-28 14:59:44] cp#0: >>cs [2,"yUtxCAuRRv26dKRuQ1fy1AYvE0fZTZ2Z",
                      "Heartbeat",{}]
[2012-12-28 14:59:44] cp#0: <<cs [3,"yUtxCAuRRv26dKRuQ1fy1AYvE0fZTZ2Z",
                      {"currentTime":"2012-12-28T13:59:44Z"}]

Example - Running a CentralSystem in SOAP mode

% node gir-ocppjs.js start_cs 9000 -t soap
[2013-04-22 16:44:44] cs: SOAP Server listening on port 9000
[2013-04-22 16:44:44] CentralSystem started.

[2013-04-22 16:57:52] cs: ChargePoint #boxid connected.
[2013-04-22 16:57:52] cs: <<cp#boxid /BootNotification {"chargePointVendor":
                      "DBT","chargePointModel":"NQC-ACDC", ...}
[2013-04-22 16:57:52] cs: >>cp#boxid /BootNotification {"status":"Accepted",
                      "currentTime":"2013-02-01T15:09:18.000Z",
                      "heartbeatInterval":1200}

> remote_starttransaction
[2013-04-22 17:01:48] cs: >>cp#boxid /RemoteStartTransaction {"idTag":
                      "044943121F1D80","connectorId":2}
[2013-04-22 17:01:48] cs: <<cp#boxid /RemoteStartTransaction {"status":
                      "Accepted"}

Example - Running a ChargePoint in SOAP mode

% node gir-ocppjs.js start_cp http://localhost:9000 boxid -t soap \
    -f http://localhost:9001
[2013-04-09 14:27:14] cs: SOAP Server listening on port 9001

> bootnotification
[2013-04-09 14:57:29] cp#boxid: >>cs /BootNotification {"chargePointVendor":
                      "DBT", "chargePointModel":"NQC-ACDC", ...}
[2013-04-09 14:57:29] cs: >>boxid /BootNotification {"status":"Accepted",
                      "currentTime":"2013-02-01T15:09:18.000Z",
                      "heartbeatInterval":1200}
...

[2013-04-22 17:01:48] cs: <<cp#boxid /RemoteStartTransaction {"idTag":
                      "044943121F1D80","connectorId":2}
[2013-04-22 17:01:48] cs: >>cp#boxid /RemoteStartTransaction {"status":
                      "Accepted"}

> set cp print_xml=true

> heartbeat
[2013-04-09 15:03:02] cp#boxid: >>cs <soap:Envelope ...>
                      <soap:Header>...</soap:Header><soap:Body>
                      <tns:heartbeatRequest></tns:heartbeatRequest>
                      </soap:Body></soap:Envelope>
[2013-04-09 15:03:02] cs: >>boxid <?xml version="1.0" encoding="utf-8"?>
                      <soap:Envelope ...><soap:Body><tns:HeartbeatResponse>
                      <currentTime>2013-02-01T15:09:18Z</currentTime>
                      </tns:HeartbeatResponse></soap:Body></soap:Envelope>

Unit testing

ocppjs provides a framework and four example files (in the test/ folder) for writing unit tests. If a test fails, the errors are printed on the standard output. If it succeeds then nothing is displayed.

Example - Running a test

% cd test/
% node test-cp-1.2.js
%

Plugins

ocppjs provides a plugin system which allows developers to define the simulator behavior without modifying the program source code. Plugins consist of extern JavaScript files listed in the plugins/ folder.

From the prompt of the simulator, 3 commands are available:

Documentation

The gir-ocppjs-doc.js program generates JSON examples from WSDL files. Run it with:

% npm install xml2js
% cd doc
% make

Output files generated:

Protocol specification

A draft specification for a WebSocket-based OCPP transport is available: http://www.gir.fr/ocppjs/ocpp_srpc_spec.shtml

Download

http://www.gir.fr/ocppjs/gir-ocppjs-1.0.2.zip

Mailing list

Interested in hearing about our latest updates? Subscribe to our mailing list.

Versions history

09 oct 2013; ocppjs 1.0.2

  * Added constraints in JSON Schema (enumerations, maxLength, etc)
    documentation. Simulator now enforces these constraints when verifying
    incoming messages.
  * Added JSON Schema control for MeterValues & StopTransaction message.
  * Fixed missing namespace for nested object in SOAP.
  * Fixed missing value in the "To" header for SOAP remote actions.

04 oct 2013; ocppjs 1.0.1

  * Added JSON Schema for requests and responses in the documentation files.
  * Changed the way XML attributes are mapped to JSON. In practice, this only
    changes the format for OCPP1.5 MeterValues & StopTransaction request
    messages.
    The central system simulator doesn't enforce this format yet, and will
    accept anything under the StopTransactionRequest.transactionData and
    MeterValuesRequest.values fields when receiving a message.
  * Added package.json file for easier installation.
  * Fixed invalid JSON example for OCPP1.2 MeterValuesRequest.
  * Fixed action name and namespaces issues with SOAP transport.

03 jun 2013; ocppjs 1.0.0

  * Fixed ocpp1.5 JSON payload structure for:
    . GetConfiguration request: "key" was a string instead of an array of
      strings
    . GetConfiguration response: "unknownKey" was a string instead of an array
      of strings
    . MeterValues & StopTransaction request: "value" was an int instead of
      an array of strings, "@value" was a object instead of an array of objects
  * Added websocket protocol name when accepting a new connection.
  * Added a plugin system allowing to define the behavior of a CS or CP
    simulator:
    . 'plugins', 'load' and 'unload' commands for listing, loading
      and unloading plugins.
    . Plugin API documentation and tutorial in
      plugins/getting_started_with_plugins.html.
    . 'cbxs' chargepoint plugin example with connectors management.
  * Minor fixes

02 may 2013; ocppjs 0.0.11

  * Added: framework for writing unit tests and 4 example files (in test/).
  * Payload errors are now supported in SOAP mode.
  * 'send_raw' and 'remote_send_raw' commands are now available in SOAP mode.
    . Added parameter -h for printing http headers.
  * In SOAP mode, header 'From' retrieves the local IP address instead of using
    'localhost'.

22 apr 2013; ocppjs 0.0.10

  * Added SOAP transport support in Central system simulator.
  * Added SOAP remote actions support:
    . Added parameter -r in 'start_cp' command, defining the listening
      port for remote actions. If not defined, it defaults to the port specifed
      in the 'wsa5:From' URL.
    . Added parameter -f in 'start_cp' command, defining the "wsa5:From"
      URL in SOAP header. If not defined, it defaults to
      'http://localhost:random_port'.
    . 'send' and 'send_raw' commands have been disabled for the SOAP mode.
    . This version does not detect SOAP payload errors yet.

09 apr 2013; ocppjs 0.0.9

  * SOAP client integration:
    . Requires third-party libraries: 'node-expat' and 'request'.
    . Added parameter -t for the 'start_cp' command in order to choose the
      simulator transport layer (websocket or SOAP).
    . Added 'set print_xml' command for displaying SOAP envelopes in XML format.
    . Remote actions and Central system simulator are not supported yet with
      soap transport.
  * New JSON attributes syntax: {"node":"value","@node":{"attr1": "value1"}}.

14 mar 2013; ocppjs 0.0.8

  * WebSocket ping enhancements :
    . Added client websocket ping.
    . Added parameter '-i' for the 'start_cp' command in order to set the
      WebSocket ping frequency.
    . Added 'websocket_ping_cs' and 'websocket_ping_cp' commands for manually
      sending one WebSocket ping from a central system simulator or a charge
      point simulator.
    . Added 'set' command for modifying the WebSocket ping frequency without
      interrupting the simulator (0 for disabling WebSocket pings).
  * 'tns:MeterValue' type is now supported. doc/gir-ocppjs-doc.js has been
  updated with the expected JSON structure for types with XML schema attributes
  attributes. The MeterValue type in ocpp 1.5 is currently the only one with
  such a structure.
  * Added 'InternalError' support when a procedure raises an exception.
  * Added payload error checking for CALLRESULT messages.
  * Prompt '>' now shows up right after entering a command.

07 mar 2013; ocppjs 0.0.7

  * Payload parsing now supports complex types and simple type restrictions.
  * Procedure call messages can be customized from command line interface using
    the new 'argument=value' syntax.
  * OCPP 1.2 & OCPP 1.5 commands are completely covered with the addition of
    firmware and diagnostics messages.
  * Enhancement of the command line interface reliability: bugfixes and
    deletion of multiple spaces.
  * Simulator is now tolerant to WSDL absence and can be launched from
    any directory.

27 feb 2013; ocppjs 0.0.6

  * Basic payload parsing (Property/Occurence/TypeConstraintViolation for
    simple types). Complex types and restrictions are not checked yet.
  * Commands schema is now loaded from wsdl files. This requires:
    . An additional third-party library: xml2js.
    . Valid ocpp wsdl files in doc/wdsl subdirectory. They are provided in the
      zip file.
  * A CentralSystem simulator can now support multiple comma-separated protocol
    versions on a single endpoint.
  * New commands:
    . 'send' & 'remote_send' to send a custom message in a valid envelope, to
      simulate invalid procedure names and payloads.
    . 'send_raw' & 'remote_send_raw' to send a custom string, to simulate
      invalid envelopes.

20 feb 2013; ocppjs 0.0.5

  * Conformance to DRAFT1 specification.
  * Updated command-line interface. start_cp & start_cs commands can now be
    passed directly as shell arguments.
  * Removed automatic bootnotification & heartbeat. All messages are
    triggered manually (type 'help' to get the list), except websocket ping.
  * Completed the command set to cover usual ocpp1.2 and ocpp1.5 commands (not
    available yet: firmware & diagnotics messages).

14 feb 2013; DRAFT1

  * First public draft specificaton.
  * Removed chargeBoxIdentity from message payload.

01 feb 2013; ocppjs 0.0.4

  * Added doc/gir-ocppjs-doc.js: autogenerate JSON examples from OCPP wsdl.

23 jan 2013; ocppjs 0.0.3

  * Added websocket ping interval in centralsystem simulator.
  * Added websocket logging for ping/pong frames.

11 jan 2013; ocppjs 0.0.2

  * Updated logs.
  * Bugfixes.

28 dec 2012; ocppjs 0.0.1

  * Initial version.