-
Notifications
You must be signed in to change notification settings - Fork 2
SolarNode OCPP
SolarNode supports the Open Charge Alliance OCPP v1.5 standard for operating as an electric vehicle charging station.
For a typical for-pay OCPP setup, the SolarNode-powered charging station requires:
- The SolarNode computer.
- Internet connectivity, e.g. WiFi, mobile, etc.
- Switches to enable/disable power to the physical charging sockets (one per socket).
- Energy meters to monitor the amount of energy delivered over the charging sockets (one per socket).
- RFID receiver to identify users.
Many other components can be integrated, but these are the basic requirements for the SolarNode to operate as an OCCP charging station.
There are many SolarNode plugins that implement parts of the OCPP system. These are all named under
the net.solarnetwork.node.ocpp
namespace in the SolarNode OCPP repository, such as
the core OCPP plugin. The OCPP v1.5 SOAP binding is implemented in its own
plugin. A RFID plugin supports scanning the RFID cards via a
helper daemon.
The OCPP charge box identity reported by the SolarNode is derived from the SolarNetwork-issued X.509 certificate. The subject DN of that certificate will be used as the identity value.
An example header looks like this:
<chargeBoxIdentity xmlns="urn://Ocpp/Cs/2012/06/">UID=1013,O=SolarDev</chargeBoxIdentity>
A specialized WS-Addressing handler is included for
reporting the SolarNode's <From>
header so the OCPP server can learn the
node's IP address and be able to send OCPP messages directly to the charging
station. The handler can report on the SolarNode's assigned IP address, or be
configured with a manual one.
An example header looks like this:
<From xmlns="http://www.w3.org/2005/08/addressing">
<Address>http://192.168.1.2/ocpp/v15</Address>
</From>
The OCPP standard does not directly define network-level authentication between
charging stations and the server. To support operating over the public internet,
ideally both the SolarNode and the server would be configured to use TLS (e.g.
https
). For practical purposes, however, it may not be possible to do so, for
example on the SolarNode side.
To provide confidence that the OCPP messages going to/from the SolarNode are valid, SolarNode adds an additional SOAP header to all outbound messages that includes a cryptographic signature of the message. The signature is encrypted by a secret shared by the SolarNode and the OCPP server it is communicating with. For all messages that come from the OCPP server, the SolarNode looks for the authentication header and validates it before accepting the message.
Both clients and servers that don't support this header will simply ignore it.
An example header looks like this:
<Authentication xmlns="urn://SolarNetwork/SolarNode/WS"
ts="2015-01-01T12:00:00.000Z">doEIdjlsdkfjsopdifjso==</Authentication>
The @ts
attribute is the system's current time, in the ISO 8601 format in
the UTC time zone.
The signature is computed as a HMAC-SHA256
digest using a configurable shared
key, the result of which is Base64 encoded and added as the <Authentication>
element's content. The digest is derived from the contents of the OCPP message
itself and includes the following values:
- The OCPP charge point identity, or an empty string if not available (i.e. in server response messages).
- The current date, in ISO 8601 format in the UTC time zone.
- All top-level SOAP header elements, in DOM order. In addition, for any
top-level element in the
http://www.w3.org/2005/08/addressing
namespace (WS-Addressing) then the first of any childAddress
element is included. This is to ensure all WS-Addressing values are included in the digest. - Recursive SOAP body elements, in DOM order, including the SOAP body element itself.
For any SOAP element to be included in the digest, the syntax of the
value to add is {uri}localName=value
where uri
is the URI of the namespace
of the element, localName
is the element name, and value
is the normalized
text value of the element. If the text value is only whitespace,
however, the =value
part is omitted.
For an OCPP SOAP message like the following:
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
<S:Header>
<chargeBoxIdentity xmlns="urn://Ocpp/Cs/2012/06/">UID=1013,O=SolarDev</chargeBoxIdentity>
<To xmlns="http://www.w3.org/2005/08/addressing"
>http://localhost:9000/steve/services/CentralSystemService</To>
<Action xmlns="http://www.w3.org/2005/08/addressing">/BootNotification</Action>
<ReplyTo xmlns="http://www.w3.org/2005/08/addressing">
<Address>http://www.w3.org/2005/08/addressing/anonymous</Address>
</ReplyTo>
<MessageID xmlns="http://www.w3.org/2005/08/addressing"
>uuid:f86a3b23-5db3-4260-ab21-d72348da5ecc</MessageID>
<From xmlns="http://www.w3.org/2005/08/addressing">
<Address>http://192.168.1.44:8680/ocpp/v15</Address>
</From>
</S:Header>
<S:Body>
<bootNotificationRequest xmlns="urn://Ocpp/Cs/2012/06/">
<chargePointVendor>SolarNetwork</chargePointVendor>
<chargePointModel>SolarNode</chargePointModel>
<chargePointSerialNumber>155</chargePointSerialNumber>
<firmwareVersion>0.1.0</firmwareVersion>
</bootNotificationRequest>
</S:Body>
</S:Envelope>
The resulting canonical message value would look like this, given a message date of 16 June 2015 6:30 AM UTC:
UID=1013,O=SolarDev
2015-06-16T06:30:00.000Z
{urn://Ocpp/Cs/2012/06/}chargeBoxIdentity=UID=1013,O=SolarDev
{http://www.w3.org/2005/08/addressing}To=http://localhost:9000/steve/services/CentralSystemService
{http://www.w3.org/2005/08/addressing}Action=/BootNotification
{http://www.w3.org/2005/08/addressing}ReplyTo=http://www.w3.org/2005/08/addressing/anonymous
{http://www.w3.org/2005/08/addressing}MessageID=uuid:f86a3b23-5db3-4260-ab21-d72348da5ecc
{http://www.w3.org/2005/08/addressing}From=http://192.168.1.44:8680/ocpp/v15
{http://www.w3.org/2003/05/soap-envelope}Body
{urn://Ocpp/Cs/2012/06/}bootNotificationRequest
{urn://Ocpp/Cs/2012/06/}chargePointVendor=SolarNetwork
{urn://Ocpp/Cs/2012/06/}chargePointModel=SolarNode
{urn://Ocpp/Cs/2012/06/}chargePointSerialNumber=155
{urn://Ocpp/Cs/2012/06/}firmwareVersion=0.1.0
The date included in the computed signature is provided as the @ts
attribute
on the <Authentication>
element. This allows the receiver of the message to
compare what it knows the current date to be against what the sender reported,
and reject messages whose time difference is greater than a configurable window.
The SolarNode defaults this window to five minutes.
A complete open source Java-based implementation for this scheme is provided by SolarNetwork. This handler can also be integrated into Java-based OCPP servers, such as this example in the open source SteVe OCPP server.