Skip to content
Matt Magoffin edited this page Jun 4, 2019 · 7 revisions

SolarNode OCPP support

SolarNode supports the Open Charge Alliance OCPP v1.5 standard for operating as an electric vehicle charging station.

Hardware setup

For a typical for-pay OCPP setup, the SolarNode-powered charging station requires:

  1. The SolarNode computer.
  2. Internet connectivity, e.g. WiFi, mobile, etc.
  3. Switches to enable/disable power to the physical charging sockets (one per socket).
  4. Energy meters to monitor the amount of energy delivered over the charging sockets (one per socket).
  5. 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.

Software setup

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.

Charge box identity

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>

WS-Addressing From handler

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>

Authentication SOAP header

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.

SolarNode authentication signature details

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:

  1. The OCPP charge point identity, or an empty string if not available (i.e. in server response messages).
  2. The current date, in ISO 8601 format in the UTC time zone.
  3. 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 child Address element is included. This is to ensure all WS-Addressing values are included in the digest.
  4. 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.

Example authentication signature message

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

Replay attacks and time skew

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.

Implementation code

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.

Clone this wiki locally