Techに戻る

OCPPスマート充電(SetChargingProfile)の実装

2025-08-12
電力網の負荷を最適化する SetChargingProfile の実装ポイントを C++17 で 5〜10 分で解説

OCPPのスマート充電は、電力網全体の負荷を平準化したり、特定の時間帯に充電を集中させたりするための重要機能です。本記事ではその中核メッセージである SetChargingProfile の実装ポイントをC++17で解説します。

1. スマート充電とは

スマート充電は、CSMSからの指示に基づき、CS(充電器)が充電電力や電流を動的に制御する仕組みです。

  • デマンドレスポンス: 電力需要が高い時間帯に充電を抑制
  • 負荷分散: 複数台の充電器で利用可能な総電力を分け合う
  • 時間帯別料金連携: 電気料金が安い夜間に充電をスケジュール

これらは SetChargingProfile メッセージで送信される充電プロファイルによって実現されます。

アクターと役割(誰が)

  • CSMS(Charging Station Management System): 充電器群を集中管理し、中央スマート充電の主要な制御主体。
  • 充電ステーション(Charging Station, CS): 1台以上のEVSEを持つ実機。受信したプロファイルに従い出力を制御。
  • EV(Electric Vehicle): ISO 15118対応時は自身の充電ニーズを提供可能。
  • ローカルコントローラー(Local Controller, LC): 複数のCSを束ねてローカルに制御する論理コンポーネント。
  • 外部制御システム(EMS/DSO 等): OCPP以外(OpenADR/OSCP等)で容量制限を指示。

制御形態とフロー(どのように)

  • 内部負荷分散(Internal Load Balancing)
    • CS内部でEVSE間の出力を最適配分。
    • CSMSは ChargingStationMaxProfile で装置全体の上限を与え、CSはその範囲で局所最適化。
  • 中央スマート充電(Central Smart Charging)
    • CSMSが外部要因(系統容量、料金等)を加味してスケジュールを計算し、SetChargingProfile で各EVSE/トランザクションに TxProfile を適用。
  • ローカルスマート充電(Local Smart Charging)
    • LCが駐車場などの接続容量をグループ内のCSに配分。CSMSからLCへ上限設定、あるいはLC独自ロジックで分配。
  • 外部制御信号(External Control Signals)
    • EMS/DSO等がOCPP外プロトコルで制限を付与。CSは NotifyChargingLimit でCSMSへ報告。

2. 主要メッセージ

メッセージ方向目的
SetChargingProfileCSMS → CS充電プロファイル(電力・電流スケジュール)を設定
ClearChargingProfileCSMS → CS設定済みのプロファイルを削除
GetChargingProfilesCSMS → CS現在適用中のプロファイル一覧を問い合わせ
ClearedChargingProfileCS → CSMS(v2.0.1) プロファイルが自動的にクリアされたことを通知
NotifyChargingLimitCS → CSMS外部/ローカル要因で課せられた充電上限を通知
NotifyEVChargingNeedsCS → CSMSISO 15118経由で得たEVの充電ニーズを通知
NotifyEVChargingScheduleCS → CSMSEVが選択/合意したスケジュールを通知

3. ChargingProfile データ構造の要点

SetChargingProfile のペイロードは複雑ですが、主要なパラメーターは次の通りです。

  • chargingProfileId: プロファイルの一意なID
  • stackLevel: 複数のプロファイルが競合した場合の優先度(数値が大きいほど優先)
  • chargingProfilePurpose: ChargingStationMaxProfile(装置全体の上限)、TxDefaultProfile(トランザクションの既定)、TxProfile(進行中トランザクションの上限)
  • chargingProfileKind: Absolute(絶対値)、Recurring(繰り返し)、Relative(相対値)
  • chargingSchedule: 時間ごとの電力/電流上限を定義する配列(chargingSchedulePeriod)。chargingRateUnitA もしくは W

評価ルールの要点:

  • 有効な複数プロファイルとローカル/ハード的な制限が同時に存在する場合、最終的に適用されるのはその中の「最小の上限」。
  • 同一目的内で複数プロファイルが重なる場合は stackLevel の高いものが優先される。

chargingSchedulePeriod

json
"chargingSchedule": [{
    "duration": 3600,
    "startSchedule": "2025-08-04T22:00:00Z",
    "chargingRateUnit": "A",
    "chargingSchedulePeriod": [
        {"startPeriod": 0, "limit": 16.0},
        {"startPeriod": 1800, "limit": 8.0}
    ]
}]

上記は「22:00から30分間は16A、次の30分間は8A」を意味します。

4. 実装アーキテクチャ

  1. Handler: 受信したプロファイルを検証し、ProfileStore に保存。
  2. ProfileStore: chargingProfileId をキーにプロファイルを管理。stackLevel(降順)と purpose でソートする機能を持つ。
  3. Scheduler: 1秒ごとなど定期的にProfileStoreを評価。もっとも優先度の高いプロファイルのlimitを計算し、EVSE Controllerに指示を出す。

5. C++ 実装のポイント

プロファイルストア

std::vectorstd::map を組み合わせ、stackLevel でソート済みの状態を維持します。

cpp
class ProfileStore {
    std::map<int, ChargingProfile> profiles_by_id_;
    std::vector<std::shared_ptr<ChargingProfile>> sorted_profiles_;

public:
    void add_profile(const ChargingProfile& p) {
        // ... id重複チェック、挿入 ...
        sort_by_stack_level();
    }
    // ...
};

スケジューラ

現在時刻にもっとも合致するlimitを返します。

cpp
double Scheduler::calculate_limit(std::time_t now) {
    // 1. Get highest priority profile from store
    auto profile = store_.get_highest_priority_profile();
    if (!profile) return default_limit;

    // 2. Find the active period in the schedule
    for (const auto& period : profile->chargingSchedule.periods) {
        if (now >= period.start && now < period.start + period.duration) {
            return period.limit;
        }
    }
    return default_limit;
}

6. ISO 15118 連携(任意)

  • EVは希望エネルギー量・出発予定などのニーズを提供し、CSはこれを NotifyEVChargingNeeds でCSMSへ転送。
  • CSMSはニーズや系統制約を考慮し、最大3つの料金プランを含むスケジュール(SAScheduleList)をEVへ提示。EVは選択結果を NotifyEVChargingSchedule で通知。
  • 充電中にスケジュール/プロファイルの再交渉が発生しうる。

7. オフライン時の動作

  • CSがオフラインになっても、事前に受信した TxProfile はトランザクション終了まで有効。
  • 通信断でトランザクションを開始する場合でも、装置に設定済みのTxDefaultProfileがあればそれに従い充電可能。

8. まとめ

  • スマート充電の実装は プロファイルの管理スケジューリングロジック が肝。
  • stackLevel(大きい方が優先)と chargingProfilePurposeChargingStationMaxProfile/TxDefaultProfile/TxProfile)のルールを正確に解釈する。
  • 有効なプロファイルとローカル制限の最小値が最終的な上限となる評価を正しく実装する。
  • 2.0.1固有の電文(NotifyChargingLimitNotifyEVChargingNeedsNotifyEVChargingSchedule 等)との連携やオフライン時の挙動も考慮する。