OCPIプロトコルとは?
OCPIプロトコルとはOpen Charge Point Interfaceの略で電気自動車(以下EVと略す)と充電インフラとのやり取りを定義した仕様です。仕様書はGithubにホストされているので誰でも読め、間違い等があったりしたらPRを送ることができます。
OCPIが生まれた背景
EVインフラが世界中に急速に広まっています。米国ではセブンイレブンが7Chargeという充電施設を運営しています。今後も様々な企業が参入し、EVインフラを提供していくでしょう。これらEV充電施設事業者が独自のネットワークを構成して、ユーザー向けのサービスを提供していますが、これらサービスを横断してアクセスする手段がないとユーザーにとっての利便性は低いといえるでしょう。またEVメーカーや国ごとにコネクタ仕様等も異なることもガソリン車とは違いユーザーの負担になります。
OCPIはこれらの課題を解決するべく、充電インフラとユーザー間のやり取りを標準化するために作られました。
概要
OCPIはCPOとeMSPのやり取りを定義した仕様です。CPO (Charging Point Operator)とはEV充電施設事業者であり、EVの充電インフラを管理・運営する組織を意味します。eMSP (e-Mobility Service Provider)はeモビリティサービス事業者を意味し、複数のCPOを集約し、ユーザーに充電に関する様々な付加価値を提供する組織を意味します。
携帯電話回線で例えるとCPOはNTTドコモ、Softbank、KDDIやのような携帯キャリアで、全国に携帯電話回線を整備します。eMSPはMVNOのような企業で携帯キャリアの回線を借りてユーザーにサービスを提供します。eMSPが複数のCPOに接続するのは、MVNOのIIJmioでユーザーがDocomoかauの回線を選ぶことができることに似ています。また、CPOは必ずしもインフラだけを提供するわけではなくeMSPを兼ねている場合もあります。これも携帯電話回線で例えると、Softbankが携帯キャリアとして自身の料金プランを提供している感じです。
出典: https://github.com/ocpi/ocpi/blob/master/topology.asciidoc
OCPIにはHubという概念もあり、Hubは複数のeMSPとCPOを仲介します。携帯電話回線で例えると、HubはNTTドコモとソフトバンクをつなぐ交換局や、海外のキャリアとつなぐ国際ローミングと捉えていいでしょう。
出典: https://github.com/ocpi/ocpi/blob/master/topology.asciidoc
また、OCPIの説明からは脱線しますが、eMSPとHubは以下のようにOCPI以外の標準プロトコルやプロプライエタリなプロトコルでサービス提供するCPOとのプロトコル変換をすることもあります。
通信仕様
OCPIはデータモデル以外にも通信仕様を含みます。OCPIの通信仕様は標準的なHTTP/JSONを使います。つまりRESTfulなWebAPIなのでWeb開発者には馴染みやすいかと思います。
モジュールとは?
モジュールとはOCPIのオブジェクト及びI/Fの役割別の仕様です。OCPI 2.2では以下のモジュールがあります。
- CDRs: 充電セッションのインボイス的な情報
- Charging Profiles: EVSEの充電プロファイル(duration, 充電速度等)
- Commands: EVからCPOに送られるイベント(開始、終了、予約等)
- Credentials: CPOやeMSPのサービス同士のプロトコルネゴシエーションとcredentialsの交換(ハンドシェイク)
- HubInfo: Hubへの接続状況等
- Locations: 充電施設(EVSE, Connector等)の情報
- Sessions: 充電セッション
- Tariffs: 充電料金(タリフ)
- Tokens: 充電施設とユーザーとの認証トークン(RFID, Mobileアプリトークン等)
- Versions: OCPIのサポートするバージョンとエンドポイント取得
SenderとReceiver
OCPIにはモジュール毎にSenderとReceiverのI/Fが定義されています。常にCPOがSenderでeMSPがReceiverになるわけではなく、eMSPがSenderでCPOがReceiverになることもあるので、どちらがSender/Receiverになるかしっかりと認識して仕様書を読みましょう。
以下のテーブルはモジュール別にCPO, eMSP, HubがSender/Receiverになり得るかをまとめています。基本的な捉え方として、どちらがデータのオーナーかを考えます。例えば、充電施設を管理運営しているのはCPOで、eMSPは充電施設を持っていませんのでLocationsモジュールではSenderがCPO、ReceiverがeMSPとされています。一方、Commandsモジュールではユーザーの充電に関するイベントをCPOに通知する仕組みなので、SenderがeMSP、ReceiverがCPOとなります。
Modules | CPO | eMSP | Hub |
---|---|---|---|
CDRs | Sender | Receiver | Both |
Charging Profiles | Receiver | Both | |
Commands | Receiver | Sender | Both |
Credentials | Both | Both | Both |
HubInfo | Receiver | Receiver | Sender |
Locations | Sender | Receiver | Both |
Sessions | Sender | Receiver | Both |
Tariffs | Sender | Receiver | Both |
Tokens | Receiver | Sender | Both |
Versions | Both | Both | Both |
PushとPull
OCPIはモジュールによってはPushとPull型があります。Push型はSender側からHTTP/POSTやHTTP/PUT, HTTP/PATCH等でReceiverにデータを送信することを意味します。Pull型はReceiver側がSenderに対してHTTP/GETでデータをフェッチすることを意味します。OCPIではモジュールによりますが、PushとPullの両方をサポートする場合もあり、どちらを使うかは実装者が選択可能です。ただし、後述するDynamicデータの取得に関しては、Pull型を使用するとポーリングになるのでOCPIとしてはPush型を使うことが推奨されています。
StaticとDynamicデータ
OCPIにはStatic/Dynamicデータという定義は存在しませんが、StaticとDynamicデータに分けて考えると理解の助けになるので解説します。
StaticデータとはeMSPがCPOからバルクで取得する各モジュールの全データのスナップショットになります。eMSPはCPOが所有しているデータと同期を取るためにStaticデータを取得します。eMSPはCPOのGETインターフェイスを使ってStaticデータを取得しますが、一度に全件返すことはできないので、何回もpaginateされたリクエストを送ることになります。
DynamicデータはCPOから送られる各モジュールの更新情報となります。例えば、EVSEやコネクタの利用状況(Availability)やEVSEの新規追加・変更・削除があります。DynamicデータはeMSPからpull型で都度取得する方法とCPOからpush型で受け取る2つの方法があります。pull型の場合は、HTTP/GETでリクエストし、リクエストパラメータにdate_from
とdate_to
クエリパラメータを指定します。CPOはfrom/toの間に変更されたオブジェクトをだけを返します。push型ではCPOが変更されたオブジェクトをeMSPにHTTP/PUTもしくはHTTP/PATCHで送信します。pullとpushの大きな違いは、pull型の場合は変更されたオブジェクト全体が返るのに対し、push型の場合は、PATCHで受け取るデータは以下のように変更されたプロパティだけを送ることになっています。
{
"status": "CHARGING",
"last_update": "2019-06-24T12:39:09Z""
}
pull型だとポーリングになってしまい、即時性がないのでpush型を使うことが推奨されています。push型は即時性が高く、かつ差分プロパティのみ送信するためデータ転送量的にも有利なのですが、いかんせん送信側、受信側ともに実装コストが高く広く普及しているとは言えません。特にpushが失敗した場合の再送の設計が必要なことや、また何かしらの原因でデータを取りこぼした際の保険で定期的にpartial syncのために結局pull型が必要な場合もあり、だったら即時性は少し目をつむってpullだけ実装したほうがいいんじゃない?ってことになってる現場が多そうです。
Credentials and Versions
VersionsモジュールはサービスのサポートしているOCPIバージョン及び、そのURLを返すモジュールです。Credentialsは通信に使うOCPIプロトコルバージョンのネゴシエーション及びアクセストークンの交換をするモジュールになります。図では3つの種類のトークンが登場します。
- Token A: SenderがReceiverのバージョンモジュールに問い合わせするために使うトークン
- Token B: ReceiverがSenderにリクエストをするためのアクセストークン
- Token C: SenderがReceiverにリクエストをするためのアクセストークン
要はお互いのアクセストークンを交換するために手続きを細かく規定しているわけですが、実際にはこのフローに則ってなく、オフラインでToken B/Cを予め交換される場合もあるようです。
出典: https://github.com/ocpi/ocpi/blob/master/credentials.asciidoc
Locations
Locationは1つの充電ステーションを表します。Locationは複数のEVSEを持ち(1:n)、各EVSEは複数のコネクタ(1:n)を持つことができます。
Push型の場合
CPOに新しいLocationオブジェクトが登録されると、CPOはeMSPにHTTP/PUTで追加されたオブジェクトを送信します。CPOがLocationを置き換えた場合はCPOは、eMSPにHTTP/PUTでオブジェクトを送信します。Locationオブジェクトが一部更新された場合は、CPOはeMSPにHTTP/PATCHで更新されたプロパティのみを送信します。もしEVSEがなくなった場合は、CPOはEVSEのstatus
をREMOVED
に変え、eMSPにHTTP/PUTもしくはHTTP/PATCHで送信します。ActiveなEVSEが存在しないLocationは実質"expired"なので表示しないでください。LocationはSession等の他のモジュールから参照されるため、論理削除されることはあってもデータストアの中から消してはいけません。
Pull型の場合
eMSPはCPOのHTTP/GETですべてのLocationsを取得できます。GETインターフェイスのdate_from
及びdate_to
を指定するとその間に更新されたオブジェクトのみを取得できるので、eMSPは数秒〜数分に一回、date_from
、date_to
を少しずつずらしながらCPOにポーリングすることで継続的に最新の情報を取得することができます。
Tariffs
Tariffは充電料金に関するモジュールです。
Push型の場合
Locationsモジュールと同様で、Tariffが新規作成や変更された場合はCPOからeMSPへHTTP/PUTでオブジェクトが送信されます。Tariffが削除された場合はCPOからeMSPにHTTP/DELETEで削除するオブジェクトのIDが送信されます。
Pull型の場合
Locationsモジュールと同様で、eMSPはHTTP/GETでCPOのすべてのTariffを取得できます。GETインターフェイスのdate_from
及びdate_to
を指定するとその間に更新されたオブジェクトのみを取得できるので、eMSPは数分〜数時間に一回、date_from
、date_to
を少しずつずらしながらCPOにポーリングすることで継続的に最新の情報を取得することができます。
Commands
CommandsモジュールはEV及び充電ステーションからの充電開始、停止、予約といった命令に関するモジュールです。eMSPからCPOへHTTP/POSTでCommandのオブジェクトが送信されます。CPOは充電ステーションにcommandを渡し、充電ステーションからの返答をHTTP/POSTでeMSPに送信します。Commandsモジュールが他のモジュールと異なる点としては、Pull型が仕様にないことがあげられます。おそらく、EVからの命令のやり取りなので即時性を持たせたかったのだと思います。
Sessions
SessionはEVの充電セッションを表すオブジェクトで、EVの充電が開始されるとCPOで作成されます。
Push型の場合
Locationsモジュールと同様で、Sessionが新規作成された場合はCPOからeMSPへHTTP/PUTでオブジェクトが送信されます。Sessionが更新された場合はCPOからeMSPにHTTP/PATCHでオブジェクトが送信されます。
Pull型の場合
Locationsモジュールと同様で、eMSPはHTTP/GETでCPOのすべてのSessionを取得できます。GETインターフェイスのdate_from
及びdate_to
を指定するとその間に更新されたオブジェクトのみを取得できるので、eMSPは数秒〜数分間に一回、date_from
、date_to
を少しずつずらしながらCPOにポーリングすることで継続的に最新の情報を取得することができます。
CDRs
CDR (Charge Detail Record)とはすでに完了した充電セッションのインボイス的な情報です。CDRはセッション終了後にCPOからeMSPに送信されます。
Push型の場合
Locationsモジュールとほぼ同様で、CDRが新規作成された場合はCPOからeMSPへHTTP/POSTでオブジェクトが送信されます。CDRは更新や削除されることはないので、PATCHのインターフェイスは存在しないです。
Pull型の場合
Locationsモジュールと同様で、eMSPはHTTP/GETでCPOのすべてのCDRを取得できます。GETインターフェイスのdate_from
及びdate_to
を指定するとその間に更新されたオブジェクトのみを取得できるので、eMSPは数十秒〜数分間に一回、date_from
、date_to
を少しずつずらしながらCPOにポーリングすることで継続的に最新の情報を取得することができます。
OCPIの拡張
OCPIで表現できないようなデータモデルがある場合は、しばしばOCPIを拡張することがあります。ある程度の規模のCPOやeMSPであればたいてい何らかの拡張があるようです。OCPI v3ではそのような拡張を定義するため仕様が検討されているようです。[1]
日本での普及度合
とあるCPOの中の人に聞いてみたんですが、2023年時点では日本のCPOでOCPIに対応しているっていうのは聞いたことがないそうです。
OCPI v3
現時点ではまだ公開されていませんが、以下の機能及び改善が検討されています。
- ISO 15118 Plug&Charge [2]
- Eichrecht support (ドイツのEVに関するレギュレーション?)
- 性能改善
- 前述のExtensionsのためのMetadata
MapboxとEV
MapboxはEVの各種API、SDKを開発しています。ご興味ある方はこちらのURL(https://www.mapbox.com/ev)のContact Salesからお問い合わせください。
EV Charge Finder API
EV Routing API
Discussion