OCPI v2.2.1 message routing issues in multi-tenant topologies
Authors: Robert Gliguroski | Petar Jovevski
Overview
Goals
- Propose a solution which will enable any roaming implementation to support all topologies and still follow the protocol specification
- The solution should be the recommended approach for implementers facing this issue
- Publish this paper so it’s available to anyone facing this challenge
- Get an approval and recommendation from the EV Roaming foundation on the proposed approach
Introduction
The main purpose of the Open Charge Point Interface (OCPI) protocol is to enable EV roaming between Charge Point Operators (CPOs) and e-Mobility Service Providers (eMSPs). It supports authorization, exchange of information about charging locations, charging sessions, pricing tariffs and much more. The OCPI protocol was initially developed and designed to handle peer-to-peer communication between CPOs and eMSPs. Let us briefly identify the main roles that exist in the EV roaming world.
EV Charging Market Roles
As stated in the OCPI specification, different market roles can be identified in the EV Charging landscape. The following roles are relevant for this discussion:
- CPO – Charging Point Operator. Operates a network of Charge Points
- eMSP – e-Mobility Service Provider. Gives EV drivers access to charging services
- Roaming Hub – Can connect one or more CPOs to one or more eMSPs
In addition to these formally identified market roles, an additional one can be identified – a platform providing services for multiple entities in the same or different role, for example: a platform offering charging solutions for multiple CPOs. However, the platform, in this context, cannot be considered a role.
Definition of roles in OCPI v2.1.1
OCPI v2.1.1 has a very strict definition of roles, it only supports CPOs and eMSPs. But this is rare in the real world. There are very few companies that are strictly a CPO or an eMSP and have their own platform. Instead, there are many companies that provide services to CPOs that do not have their own platform. A lot of CPOs are also eMSPs at the same time.
This is what the Credentials object looks like in v2.1.1:
We can see that the authorization token is on the same level as the party_id and country_code properties, which aligns with the intention of connecting CPOs to eMSPs directly in a one-to-one mapping. Example data for a credentials object representing the “Example Operator” with party_id = EXA and country_code = NL:
7.2.2 Example
{
“url”: “https://example.com/ocpi/cpo/versions/”,
“token”: “ebf3b399-779f-4497-9b9d-ac6ad3cc44d2”,
“party_id”: “EXA”,
“country_code”: “NL”,
“business_details”: {
“name”: “Example Operator”,
“logo”: {
“url”: “https://example.com/img/logo.jpg”,
“thumbnail”: “https://example.com/img/logo_thumb.jpg”,
“category”: “OPERATOR”,
“type”: “jpeg”,
“width”: 512,
“height”: 512
},
“website”: “http://example.com”
}
}
Using OCPI v2.1.1 (and earlier versions), companies would need to set up separate OCPI connections per role. So, if a multi-tenant platform which hosts e.g. 10 CPOs wants to roam with a multi-tenant platform hosting 5 eMSPs, it would need to set up 50 separate OCPI connections and exchange 50 pairs of authorization tokens. If some of those CPOs are eMSPs at the same time (or vice versa), this number would need to be additionally increased. Furthermore, when any roaming partner wants to send updates (new/changed Location, Token etc.) – it would need to send those same updates n times for each roaming partner on the other side, even though all those partners are hosted under the same platform.
Solution in OCPI 2.2.1
OCPI 2.2.1 recognizes this problem, that’s why it talks about connecting platform-to-platform. It abstracts the role from the OCPI connection itself. The Credentials object in v2.2.1 looks like this:
The “CredentialsRole” list is the structure that contains the “party_id” and “country_code” identifiers of each tenant (CPO or eMSP). This means that a multi-tenant platform hosting multiple CPOs will be identified by a token in the roaming partner’s system (the platform itself, not the CPOs). Here’s an example for a Credentials object representing a platform that hosts 3 CPOs:
“token”: “9e80aca8-28be-1le9-b210-d663bd873d93”,
“url”: “https://ocpi.example.com/versions/”,
“roles”: [{
“role”: “CPO”,
“party_id”: “EXO”,
“country_code”: “NL”,
“business_details”: {
“name”: “Excellent Operator”
}
},
{
“role”: “CPO”,
“party_id”: “PFC”,
“country_code”: “NL”,
“business_details”: {
“name”: “Plug Flex Charging”
}
},
{
“role”: “CPO”,
“party_id”: “CGP”,
“country_code”: “NL”,
“business_details”: {
“name”: “Charging Green Power”
}
}]
The authorization token is the same for all CPOs under this platform.
Roaming Hubs
For Roaming Hubs, OCPI v2.2.1 states that Hubs should represent themselves as role: Hub, and must not report all the other connected parties (tenants). The Hub will thus only send one element in the CredentialsRole list.
Message routing headers
OCPI v2.2.1 introduced the concept of “Message routing headers” in order to support multi-tenant platforms sending requests only to/from certain tenants hosted on the other end of the roaming integration. All requests to/from a functional OCPI module must include the following headers:
These headers enable both Platforms and Roaming Hubs to route requests to their tenants, and be able to determine which CPO is talking to which eMSP. This is needed because of the introduction of Platforms and Hubs, which puts the authorization token on the top level of the platform/hub, so there is no way to determine which tenant(CPO, eMSP) is initiating the communication, because they will all share the same authorization token assigned to their host platform or hub.
Broadcast Push
Hubs have the option to implement “Broadcast push” support, meaning – roaming partners can send data to the Hub so it can “broadcast” it to all connected clients(tenants). This is useful when e.g. a CPO platform wants to notify all the Hub tenants (all eMSPs) that a new Location/EVSE/Connector has been added. This means that only one request to the Hub is necessary, then the Hub will further communicate this with the connected clients.
To send a Broadcast Push, the platform uses the party_id and country_code of the Hub in the “OCPI-To” headers. The Hub then internally routes this request to the connected eMSPs.
The problem with this setup
The “Broadcast push” approach, described above, works well for Hubs, mainly because a Hub registers itself by sending one element in the CredentialsRole list with its own party_id and country_code identifiers and the role “Hub”. That is what enables platforms to send one request to the Hub, thus notifying all the Hub tenants about the newly added entity.
Broadcast push for Platforms?
The multi-tenant platforms, in contrast, do not have the requirement to register themselves using only one element in the CredentialsRole list. OCPI states that explicitly for Hubs, but not for platforms. In practice, a multi-tenant platform will usually behave in one of the following two ways:
– Send only one element
– Send all tenants
Both approaches can work, but both come with their own set of problems:
Problems with sending only one element
It is possible for a platform (e.g. a CPO platform) to send only one element in the CredentialsRole list, identifying the platform only. However, this means the receiving roaming partner will not have a way to know which tenants(CPOs) exist under the CPO platform.
- If we develop our OCPI implementation to only return one element representing the Platform itself, we are making the assumption that all of our future roaming partners (eMSPs or eMSP platforms) will be OK with us not sharing the underlying tenants (CPOs)
- Unless everyone is OK with sharing/receiving the “tenants” information in a channel outside of the OCPI protocol when signing the business agreement (e.g. e-mail etc., then inserting the data about the underlying platform CPOs in the database manually). This way – the eMSP platform/HUB will be able to validate the Party IDs they extract from the objects with this data
Another approach is to include the specific CPOs’ data in the “evse_id” property of the EVSE object. OCPI recommends that this property be formatted according to the eMI3 standard, which would mean it will include the actual CPO operating the station
- The problem with this approach is that we are again making an assumption that all our eMSP partners will have implemented logic to extract CPO identifiers from the evse_id property (or contract_id, for tokens). This eMI3 syntax is a recommendation only, no eMSP is obligated to follow it or implement logic to extract CPO information from the EVSE Id. If a party doesn’t follow this recommendation, there might not be a way to identify the real owner of the location
Some platforms (one of them is a popular roaming hub operating in Europe) require their roaming partners to include the OCPI-from message routing headers in all requests and for those requests to include the real CPO operating the station
- This means we cannot send only one element to the Hub, because they need to have received all our CPOs so they can later verify an incoming Message routing OCPi-from header contains a valid value (a CPO they have received and that belongs to us, is connected to the location we’re sending etc..)
Problems with sending all the tenants
Sending all the tenants (CPOs) to the roaming partner in the CredentialsRole list means that the roaming partner will be aware of all our underlying CPOs hosted by our multi-tenant platform. However, because we are now missing an element identifying the platform itself, we cannot send only one request to the multi-tenant eMSP platform on the other side, and have all of its tenants notified about that (since the platform is not a Hub and thus cannot use the role Hub and identify itself by sending one element only).
In reality, when multi-tenant platforms choose to send/receive all of their tenants when registering, they then settle for the approach of sending/receiving multiple requests, example:
- CPO platform has a new location, it then makes multiple requests to all tenants living under the same eMSP platform. The problem is – all those requests are being sent to the same receiving API (the eMSP platform).
This way, we’re losing the benefits that OCPI v2.2.1 brings – the Platform-to-Platform registration and we’re going back to the peer-to-peer communication of OCPI v2.1.1.
Solutions
One solution is to combine these two approaches, but be upfront about it when agreeing the technical details, before the two parties start the integration process. This might seem obvious at first, but in our experience – it was counter-intuitive. No one seemed to think there’s a need to combine the two approaches. Parties (including ourselves at first) – went with the assumption that either one of these approaches would work, as long as the implementers choose the appropriate one for their scenario.
However, in reality – different parties choose to focus on different aspects of the protocol’s specification. Some parties rely strongly on the Message routing headers, but their Credentials implementation doesn’t align very well with all cases these headers have defined. Also, these headers are mandatory in most cases, which means a lot of our requests are rejected by the roaming partner because they cannot pass their validation.
The combination of the two approaches would mean for parties to agree upfront on what information each party wants to know about the other party, for example:
- If they care about all the underlying ‘tenants’ the platform hosts
- If they want to have the ability to send requests to individual tenants, as well as requests to the whole platform (which the platform would need to internally handle in terms of connecting the incoming entity to the connected CPOs/eMSPs)
- Whether they follow the specification in implementing the Message routing headers as mandatory
When all of the above conditions are met, then the party and the implementers will face a ‘roadblock’, which can be solved by them agreeing to:
- Send “n + 1” elements in the CredentialsRole list when registering
- Agree upon which position the “+1” (or default) element should hold in that list (our recommendation is for this element to always be the first element in the list)
- Agree that this default element would represent the platform itself, while all the other elements in the list would represent the tenants hosted under the platform
This would result in both parties being able to target both individual tenants, and the platform itself (thus, effectively – targeting all hosted tenants). In our example, partners would then be able to include those default party_id and country_code in the “OCPI-To” headers when targeting our platform, and use a specific CPO’s party_id and country_code when targeting one tenant.
Going back to the example of a platform that hosts 3 CPOs, this is what it would look like if it follows this recommendation:
{
“token”: “9e80aca8-28be-11e9-b210-d663bd873d93”,
“url”: “https://ocpi.example.com/versions/”,
“roles”: [
{
“role”: “CPO”,
“party_id”: “PLF”,
“country_code”: “NL”,
“business_details”: {
“name”: “The multi-tenant Platform”
}
},
{
“role”: “CPO”,
“party_id”: “EXO”,
“country_code”: “NL”,
“business_details”: {
“name”: “Excellent Operator”
}
},
{
“role”: “CPO”,
“party_id”: “PFC”,
“country_code”: “NL”,
“business_details”: {
“name”: “Plug Flex Charging”
}
},
{
“role”: “CPO”,
“party_id”: “CGP”,
“country_code”: “NL”,
“business_details”: {
“name”: “Charging Green Power”
}
}
]
}
We can see the difference: we’ve added a default element as the first element in the list. This element can be used to target the platform, while still keeping the option to target each CPO individually.
Conclusion
After presenting the problem and the potential solution in front of the EV Roaming Foundation on the OCPI development workgroup meeting and having an extensive discussion with Reinier Lamers, as well as representatives from Gireve and Optimile, Reinier and the EV Roaming Foundation decided to acknowledge the problem and go one step further and include a modified version of the solution in the new OCPI version (v2.3.0).
In this approach, a multi-tenant platform would be expected to behave almost in the same way as a hub. To achieve this, a new property will be added to the Credentials object (hub_party_id, to represent the platform itself, it will be the country code and party Id of the platform, concatenated in this new field).
Then the platform would be expected to include all the parties hosted under it in the list of roles.
This effectively solves all the issues described in this document (Message routing headers, targeting the platform itself vs its tenants, parties on both sides being aware of all involved entities).
Note: For implementations not upgrading to OCPI v2.3.0 and still using OCPI v2.2.1 – it would be best to contact the EV Roaming Foundation and describe your specific use case / problem and reference this document.
