ゼロからOCPPへ:ホワイトラベルEV充電プラットフォームの構築

はじめに

日本のEV充電市場は急速に拡大しています。政府は2035年までに新車販売を電動車のみに限定する方針を掲げており、トヨタ・日産・ホンダをはじめとする国内メーカーも電動化へのシフトを加速させています。充電インフラの需要は今後さらに高まることが確実です。

しかし、真の競争優位性を生み出すのはハードウェアではなく、その背後にあるソフトウェアの層です。モビリティスタートアップ、エネルギー会社、あるいは社用車向け充電ソリューションを展開する企業であれば、独自のホワイトラベルOCPPプラットフォームを構築することで、完全なコントロール・スケーラビリティ・ブランドオーナーシップを手に入れることができます。これは既製品のSaaSには実現できないことです。

本ガイドでは、ゼロから本番稼働可能なホワイトラベルEV充電管理システムを構築するために必要なすべてのステップを解説します。プロトコルの基礎、システムアーキテクチャ、バックエンド実装、ブランディング層、そして日本市場向けのGo-to-Market戦略まで、包括的に説明します。


1. OCPPとは何か、なぜ重要なのか

OCPP(Open Charge Point Protocol)は、EV充電ポイント(ハードウェア)とCentral System(バックエンド)の間の通信における事実上の標準オープンプロトコルです。Open Charge Alliance(OCA)によって維持管理されており、充電器の接続・認証・ステータス報告・トランザクション処理の方法を定義しています。

日本市場では、パナソニック・東芝・三菱電機などの国内メーカーや、ABB・Wallboxなどの海外ブランドがすでにOCPPに対応しています。OCPPベースの設計はハードウェアに依存しない柔軟性を持つため、日本の充電インフラ事業者にとって最適な選択肢です。

主要バージョンの概要

  • OCPP 1.6 — 最も広く普及しているバージョン。WebSocket上でSOAPまたはJSONを使用。現在も業界のベースラインとして機能し、大多数のハードウェアベンダーがサポート
  • OCPP 2.0.1 — 最新標準。WebSocket上でJSONのみ使用。セキュリティプロファイル、スマート充電、デバイス管理が大幅に強化。新しいコンプライアンス認証に必要

独自プラットフォームを構築すべき理由

アプローチ コントロール スケール時のコスト ブランドオーナーシップ
既製品SaaS なし
ホワイトラベル再販 一部
カスタムOCPPプラットフォーム 完全 完全

数百台以上の充電ポイントを想定している場合、または自社のプロダクトエコシステムと深く統合する必要がある場合、独自プラットフォームの構築はほぼ常に長期的に正しい投資です。日本市場では特に、日本語UI対応・円建て請求・Suicaや交通系ICカードとの連携など、既製品SaaSでは対応が難しいローカライゼーション要件があります。


2. システムアーキテクチャの概要

本番品質のホワイトラベルOCPPプラットフォームは、5つのコアレイヤーで構成されます。

graph TD
    A["🖥️ ホワイトラベルフロントエンド\nオペレーターダッシュボード / ドライバーアプリ"]
    B["🔀 APIゲートウェイ層\nREST / GraphQL APIs"]
    C["⚡ OCPP Central System\nWebSocketサーバー"]
    D["⚙️ ビジネスロジック & イベントバス\nセッション · 請求 · 通知"]
    E["🗄️ データ & インフラ\nPostgreSQL · Redis · Kafka · S3"]

    A -->|"オペレーター / ドライバーリクエスト"| B
    B -->|"OCPPコマンド"| C
    C -->|"充電器イベント"| D
    D -->|"Read / Write"| E

    style A fill:#1A6FBF,color:#fff,stroke:#0d4d8a
    style B fill:#2E86C1,color:#fff,stroke:#1a5276
    style C fill:#2874A6,color:#fff,stroke:#1a4f72
    style D fill:#21618C,color:#fff,stroke:#154360
    style E fill:#1B4F72,color:#fff,stroke:#0e2f44

各コンポーネントの詳細

コンポーネント 役割 推奨技術
OCPP WebSocketサーバー 充電器からの接続を処理 Node.js / Python(ocppライブラリ)
REST API オペレーター・ドライバー向けエンドポイント FastAPI / Express
セッションマネージャー アクティブな充電セッションの追跡 Redis + PostgreSQL
イベントバス 充電器イベントの非同期処理 Kafka / RabbitMQ
請求エンジン 使用量計算・請求書発行 カスタム実装 + Stripe(または GMO ペイメント)
通知サービス メール・SMS・プッシュによるアラート SendGrid / Firebase
フロントエンドダッシュボード オペレーター向けホワイトラベルUI React / Next.js
ドライバーモバイルアプリ エンドユーザー向けアプリ(オプション) React Native / Flutter

日本市場向け注記: 決済には GMOペイメントゲートウェイStripe Japan の利用を検討してください。また、日本のEVユーザーの多くが充電時にICカード認証(Suica等)を期待しているため、OCPPの認証フローにICカードリーダーとの連携を組み込むことが重要です。


3. OCPP Central Systemのセットアップ

Central Systemはプラットフォームのコアであり、すべてのCharge PointとのWebSocket接続を永続的に維持します。

3.1 WebSocketライブラリの選択

Node.js の場合、コミュニティの ocpp パッケージが有力な選択肢です。Python では、mobilityhouse製の ocpp ライブラリが本番環境での実績があり、1.6と2.0.1の両方をサポートしています。

# mobilityhouse/ocppを使ったPythonの例
pip install ocpp websockets

3.2 PythonによるCentral Systemの基本実装

import asyncio
import websockets
from ocpp.routing import on
from ocpp.v16 import ChargePoint as cp
from ocpp.v16 import call_result
from ocpp.v16.enums import Action, RegistrationStatus

class ChargePoint(cp):

    @on(Action.BootNotification)
    async def on_boot_notification(self, charge_point_vendor, charge_point_model, **kwargs):
        return call_result.BootNotificationPayload(
            current_time=datetime.utcnow().isoformat(),
            interval=10,
            status=RegistrationStatus.accepted
        )

    @on(Action.Heartbeat)
    async def on_heartbeat(self):
        return call_result.HeartbeatPayload(
            current_time=datetime.utcnow().isoformat()
        )

async def on_connect(websocket, path):
    charge_point_id = path.strip("/")
    cp = ChargePoint(charge_point_id, websocket)
    await cp.start()

async def main():
    server = await websockets.serve(
        on_connect,
        "0.0.0.0",
        9000,
        subprotocols=["ocpp1.6"]
    )
    await server.wait_closed()

asyncio.run(main())

3.3 実装すべき主要OCPPメッセージ

コアプロファイル(必須)

  • BootNotification — 充電器がシステムに登録
  • Heartbeat — 定期的なキープアライブ
  • Authorize — トークン / RFIDの検証
  • StartTransaction / StopTransaction — セッションのライフサイクル管理
  • MeterValues — 電力消費量の報告
  • StatusNotification — 充電器のステータス変化

リモートコントロール(オペレーターに必須)

  • RemoteStartTransaction — ダッシュボードからセッションを開始
  • RemoteStopTransaction — リモートでセッションを停止
  • ChangeAvailability — コネクターの有効 / 無効化
  • Reset — 充電器のソフトまたはハードリセット

スマート充電(OCPP 2.0.1 / 高度な機能)

  • SetChargingProfile — 電力制限やスケジュールの適用
  • GetCompositeSchedule — 現在アクティブなスケジュールの照会

4. マルチテナンシー:ホワイトラベルのコア

ホワイトラベル化には堅牢なマルチテナンシーモデルが必要です。各オペレーター(テナント)は以下を持つべきです。

  • 独自のブランドドメイン(例:app.your-ev-operator.co.jp
  • 分離されたデータ(充電ポイント・セッション・ユーザー)
  • カスタムブランディング(ロゴ・カラー・アプリ名)
  • 設定可能な料金モデル

4.1 テナントデータモデル

-- テナント(オペレーター)
CREATE TABLE tenants (
    id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    slug        TEXT UNIQUE NOT NULL,       -- 例:"toyota-ev", "eneos-charge"
    name        TEXT NOT NULL,
    domain      TEXT,                       -- カスタムドメイン
    logo_url    TEXT,
    theme       JSONB,                      -- { primary_color, font など }
    locale      TEXT DEFAULT 'ja',          -- 表示言語
    currency    TEXT DEFAULT 'JPY',         -- 通貨
    created_at  TIMESTAMPTZ DEFAULT NOW()
);

-- 充電ポイントはテナントに属する
CREATE TABLE charge_points (
    id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id   UUID REFERENCES tenants(id),
    ocpp_id     TEXT UNIQUE NOT NULL,       -- WebSocketパスで使用するID
    name        TEXT,
    location    JSONB,
    status      TEXT DEFAULT 'Unknown',
    created_at  TIMESTAMPTZ DEFAULT NOW()
);

4.2 テナント接続のルーティング

充電器がWebSocket経由で接続する際に、パスからOCPP IDを取得し、どのテナントに属するかを検索します。

async def on_connect(websocket, path):
    ocpp_id = path.strip("/")

    # 充電ポイントレジストリからテナントを解決
    tenant = await db.get_tenant_by_ocpp_id(ocpp_id)
    if not tenant:
        await websocket.close(code=1008, reason="Unknown charge point")
        return

    cp = TenantAwareChargePoint(ocpp_id, websocket, tenant)
    await cp.start()

5. セッション管理と課金

5.1 セッションのライフサイクル

sequenceDiagram
    participant CP as 充電ポイント
    participant CS as Central System
    participant DB as データベース
    participant BE as 請求エンジン

    CP->>CS: Authorize(idTag)
    CS->>DB: トークン検証
    DB-->>CS: 承認済み
    CS-->>CP: AuthorizeResponse(Accepted)

    CP->>CS: StartTransaction(connectorId, idTag, meterStart)
    CS->>DB: セッションレコードを開く
    CS-->>CP: StartTransactionResponse(transactionId)

    loop 60秒ごと
        CP->>CS: MeterValues(transactionId, energy)
        CS->>DB: メーター値を保存
    end

    CP->>CS: StopTransaction(transactionId, meterStop, reason)
    CS->>DB: セッションを閉じる
    CS->>BE: 料金を計算
    BE-->>CS: 請求書作成完了
    CS-->>CP: StopTransactionResponse

5.2 メーター値の保存

@on(Action.MeterValues)
async def on_meter_values(self, connector_id, meter_value, **kwargs):
    for reading in meter_value:
        for sampled in reading.get("sampledValue", []):
            await db.insert_meter_reading({
                "session_id": self.active_session_id,
                "timestamp": reading["timestamp"],
                "measurand": sampled.get("measurand", "Energy.Active.Import.Register"),
                "value": float(sampled["value"]),
                "unit": sampled.get("unit", "Wh")
            })

5.3 対応すべき料金モデル

  • kWh単位 — 最も一般的。充電した電力量に基づいて課金
  • 分単位 — 時間ベースの課金(駐車管理に有効)
  • セッション定額 — 1充電あたり固定料金
  • ハイブリッド — 例:¥30/kWh + 60分超過後は¥5/分
  • 月額会員制 — 月定額で充電し放題(日本のサービスモデルとの親和性が高い)

料金はJSONBコンフィグとしてテナントまたは充電ポイント単位で保存し、柔軟性を最大化します。


6. セキュリティと認証

6.1 充電ポイントの認証

OCPP 1.6はWebSocket URLを通じたBasic Authをサポートしています。

ws://username:password@yourplatform.com/ocpp/CP001

OCPP 2.0.1では、本番環境へのデプロイに セキュリティプロファイル3 とTLSクライアント証明書を使用してください。

6.2 認証 & RBACフロー

flowchart LR
    CP["⚡ 充電ポイント"] -->|"WSS + Basic Auth\nOCPP 1.6"| WS["WebSocketサーバー"]
    CP2["⚡ 充電ポイント"] -->|"WSS + TLS証明書\nOCPP 2.0.1"| WS
    OP["👤 オペレーターアプリ"] -->|"HTTPS + JWT"| API["REST API"]
    API -->|"RBACチェック\nAdmin / Operator / Viewer"| BL["ビジネスロジック"]
    WS -->|"イベント転送"| BL

    style CP fill:#27AE60,color:#fff,stroke:#1e8449
    style CP2 fill:#27AE60,color:#fff,stroke:#1e8449
    style OP fill:#8E44AD,color:#fff,stroke:#6c3483
    style WS fill:#1A6FBF,color:#fff,stroke:#0d4d8a
    style API fill:#1A6FBF,color:#fff,stroke:#0d4d8a
    style BL fill:#1B4F72,color:#fff,stroke:#0e2f44
  • オペレーターAPIにはテナントスコープのクレームを持つ JWTトークン を使用
  • テナントごとに RBAC(Admin・Operator・Viewerロール)を実装
  • すべての公開エンドポイントにレート制限を適用
  • 充電器へのすべてのリモートコマンドを監査ログに記録

7. ホワイトラベルフロントエンドの構築

オペレーターダッシュボードは顧客が毎日目にするものです。高速で、リブランド可能で、機能的である必要があります。

7.1 ダッシュボードのコア機能

  • ライブマップ — マップビューでのリアルタイム充電器ステータス(日本語対応の Google Maps / Mapbox 推奨)
  • セッションモニター — 電力量と所要時間を含むアクティブセッションの監視
  • 充電ポイント管理 — 充電器の追加・設定・有効 / 無効化
  • ユーザー管理 — ICカード・ドライバーアカウント・アクセス制御
  • アナリティクス — 売上・稼働率・充電電力量の経時変化
  • 料金設定 — 拠点またはコネクター単位の料金ルール
  • リモートアクション — セッションの開始 / 停止・充電器の再起動

7.2 テーミングシステム

CSS変数とテナント設定エンドポイントを使って、テーマの切り替えをシームレスに実現します。

// アプリ起動時にテナントテーマを取得
const { data: tenant } = await api.get('/api/v1/tenant/config');

document.documentElement.style.setProperty('--color-primary', tenant.theme.primary_color);
document.documentElement.style.setProperty('--color-secondary', tenant.theme.secondary_color);
document.title = tenant.name;

7.3 ホワイトラベルデプロイメントオプション

オプション 複雑さ データ分離
テナントごとのサブドメイン(tenant.yourplatform.jp 共有インフラ
カスタムドメイン + SSL(app.eneos-charge.co.jp 共有インフラ
テナントごとの専用デプロイメント 完全分離

多くのSaaSユースケースでは、サブドメインルーティングから始め、顧客基盤の拡大に伴ってNginx + Let’s Encryptによるカスタムドメインのサポートを追加するのが現実的です。


8. インフラとスケーリング

8.1 初期アーキテクチャ(0〜500台)

graph LR
    CH["⚡ 充電器"] -->|"WebSocket"| WS["WebSocketサーバー\n1ノード"]
    OP["👤 オペレーター"] -->|"HTTPS"| API["REST API\n1〜2ノード"]

    WS -->|"Read / Write"| PG[("PostgreSQL")]
    WS -->|"セッションキャッシュ"| RD[("Redis\nSession Cache")]
    API -->|"Read / Write"| PG
    API -->|"ログ保存"| S3[("S3\nLogs / Reports")]

    style CH fill:#27AE60,color:#fff,stroke:#1e8449
    style OP fill:#8E44AD,color:#fff,stroke:#6c3483
    style WS fill:#1A6FBF,color:#fff,stroke:#0d4d8a
    style API fill:#1A6FBF,color:#fff,stroke:#0d4d8a
    style PG fill:#1B4F72,color:#fff,stroke:#0e2f44
    style RD fill:#C0392B,color:#fff,stroke:#922b21
    style S3 fill:#D68910,color:#fff,stroke:#9a6709

8.2 10,000台以上へのスケーリング

大規模になるとWebSocketレイヤーがボトルネックになります。各充電器は永続的な接続を維持するため、以下が必要です。

  • 共有セッションストア(Redis)を持つWebSocketサーバーの 水平スケーリング
  • 充電器イベントをダウンストリームサービスに配信する メッセージブローカー(KafkaまたはRabbitMQ)
  • リモートコマンドを充電器のソケットを保持する正しいノードに届けるための 接続ルーティング
graph TD
    CH["⚡ 充電器"] -->|"WebSocket"| LB["ロードバランサー"]
    LB -->|"スティッキーセッション"| WS1["WSノード 1"]
    LB -->|"スティッキーセッション"| WS2["WSノード 2"]
    LB -->|"スティッキーセッション"| WS3["WSノード N"]

    WS1 & WS2 & WS3 -->|"イベント発行"| KF[["Kafka\ncharger.events"]]
    WS1 & WS2 & WS3 -->|"ソケット登録"| RD[("Redis\n接続レジストリ")]

    KF -->|"session.started/stopped"| SS["セッションサービス"]
    KF -->|"meter.values"| BS["請求サービス"]
    KF -->|"status.changed"| NS["通知サービス"]

    SS & BS & NS -->|"永続化"| PG[("PostgreSQL")]

    style CH fill:#27AE60,color:#fff,stroke:#1e8449
    style LB fill:#566573,color:#fff,stroke:#2c3e50
    style WS1 fill:#1A6FBF,color:#fff,stroke:#0d4d8a
    style WS2 fill:#1A6FBF,color:#fff,stroke:#0d4d8a
    style WS3 fill:#1A6FBF,color:#fff,stroke:#0d4d8a
    style KF fill:#E67E22,color:#fff,stroke:#ca6f1e
    style RD fill:#C0392B,color:#fff,stroke:#922b21
    style SS fill:#21618C,color:#fff,stroke:#154360
    style BS fill:#21618C,color:#fff,stroke:#154360
    style NS fill:#21618C,color:#fff,stroke:#154360
    style PG fill:#1B4F72,color:#fff,stroke:#0e2f44

8.3 オブザーバビリティチェックリスト

  • WebSocket接続数・メッセージレイテンシ・エラー率のPrometheusメトリクス
  • 充電器 / テナント単位の構造化JSONロギング
  • 充電器切断スパイクのアラート
  • リアルタイムの充電器ヘルスを可視化するGrafanaダッシュボード

9. OCPIによるローミング統合

プラットフォームが稼働したら、オペレーターは ローミング を求めるでしょう。これにより、他のネットワークのドライバーが自社ステーションで充電できるようになります。これは OCPI(Open Charge Point Interface) によって実現します。

日本では、eモビリティパワー(eMPS)をはじめとする充電ネットワーク事業者間のローミング連携が進んでいます。外国からの観光客や出張者を取り込むためにも、OCPI対応は重要な差別化要素になります。

flowchart LR
    DR["🚗 ドライバー\n他のネットワーク"] -->|"認証トークン"| EM["eMSP\nモビリティプロバイダー"]
    EM -->|"OCPI 2.2.1"| HUB["OCPIハブ /\nアグリゲーター"]
    HUB -->|"CDR / 拠点情報 / 料金"| YOUR["あなたのプラットフォーム\nCPOロール"]
    YOUR -->|"OCPP"| CP["⚡ 充電ポイント"]

    style DR fill:#27AE60,color:#fff,stroke:#1e8449
    style EM fill:#8E44AD,color:#fff,stroke:#6c3483
    style HUB fill:#E67E22,color:#fff,stroke:#ca6f1e
    style YOUR fill:#1A6FBF,color:#fff,stroke:#0d4d8a
    style CP fill:#1B4F72,color:#fff,stroke:#0e2f44

OCPIによってプラットフォームが実現できること:

  • PlugShare・GoGoEV等の公共アグリゲーターへの拠点情報・料金の掲載
  • パートナーネットワークのドライバーからの決済受け入れ
  • カーナビアプリへのリアルタイム空き情報の提供

CPO(充電ポイントオペレーター)ロールとしてOCPI 2.2.1を実装することが、最初のステップとして一般的です。


10. 日本市場向けGo-to-Market戦略

プラットフォームのポジショニング

  • ハードウェア非依存 — OCPP準拠のあらゆる充電器をサポート(これが最大の強みで、パナソニック・東芝・ABBなど複数ベンダーの混在環境に対応)
  • 日本語ネイティブUI — 充電器の操作画面・ダッシュボード・アプリのすべてを日本語で提供
  • ICカード連携 — Suica / PASMO等の交通系ICカードによる認証をRFIDレイヤーで対応
  • コンプライアンス対応 — OCAのOCPP適合認証を取得することで信頼性を向上
  • セルフサービスオンボーディング — オペレーターがサポートに電話することなく充電ポイントを追加できる仕組み

プラットフォームの料金モデル

  • 充電ポイントごとの月額費用(最も予測しやすい)
  • セッション料金からのレベニューシェア(インセンティブの一致)
  • 初期導入費用 + 年間ライセンス(エンタープライズ向け)

ローンチロードマップ

gantt
    title プラットフォームローンチロードマップ
    dateFormat  YYYY-MM-DD
    section Phase 1 - コア構築
    OCPP 1.6 Central System       :p1, 2024-01-01, 30d
    基本セッション管理             :p2, after p1, 20d
    オペレーターダッシュボード v1  :p3, after p1, 30d
    section Phase 2 - ビジネス
    マルチテナント & 課金          :p4, after p2, 30d
    ホワイトラベルテーミング       :p5, after p3, 20d
    ICカード認証対応               :p6, after p4, 15d
    section Phase 3 - スケール
    スマート充電 OCPP 2.0.1        :p7, after p6, 30d
    OCPI ローミング統合            :p8, after p6, 30d
    Kafka 水平スケーリング         :p9, after p7, 20d
    section Phase 4 - 成長
    ドライバー向けモバイルアプリ   :p10, after p8, 45d
    アナリティクス & レポーティング :p11, after p9, 20d

日本市場での初期ターゲット顧客

  • 自動車メーカー・ディーラー網 — トヨタ・日産・ホンダ系ディーラーが販売店への充電器設置を進めており、管理システムの需要が急増
  • 大手不動産・デベロッパー — 三井不動産・住友不動産・野村不動産などのマンション・商業施設での充電設備義務化の流れ
  • エネルギー会社 — ENEOSやシェルジャパンなど既存の給油スタンドがEV充電に参入するケース
  • コンビニ・量販店チェーン — セブン-イレブンやイオンなど駐車場を持つ小売チェーンの充電サービス展開
  • 高速道路・パーキング事業者 — NEXCO・イオンモール・三井のリパークなど、大容量急速充電の需要が高い拠点

まとめ

ホワイトラベルOCPPプラットフォームの構築は相応の工数が必要ですが、一度稼働すれば強力な参入障壁となります。主要なマイルストーンは以下の通りです。

  1. OCPP 1.6 Central Systemを動作させる — BootNotification・Authorize・トランザクション処理を含む
  2. マルチテナンシーをデータ層・ルーティング層に早期に組み込む — 後から追加するのはコストが高い
  3. オペレーターダッシュボードを構築する — ライブステータス・リモートアクション・基本アナリティクスを含む
  4. 課金・スマート充電・OCPIを順次追加する — プラットフォームの成熟に合わせて
  5. オブザーバビリティに投資する — 充電器がオフラインになった瞬間、日本のオペレーターは必ず連絡してくる

日本のEV充電ソフトウェア市場はまだ黎明期にあります。素早く出荷し、ハードウェアに依存せず、ホワイトラベルを通じて顧客との関係を自社で持つチームが、市場の加速とともに強固な地位を築くことができます。2035年に向けた規制の追い風も、このチャンスをさらに大きくするでしょう。


Python · Node.js · PostgreSQL · Redis · OCPP 1.6 / 2.0.1 · Open Charge Alliance · GMOペイメント · Firebase


Get in Touch with us

Chat with Us on LINE

iiitum1984

Speak to Us or Whatsapp

(+66) 83001 0222

Related Posts

Our Products