Amazon Web Services ブログ
AWS IoT Coreを利用したOCPP対応電気自動車チャージポイントオペレーターソリューションの構築
充電器(チャージポイントまたは “CP” ) は、その運用者 (チャージポイントオペレーターまたは “CPO”) により継続的に監視・管理される必要があります。 CPO は定期的なリモートメンテナンスやオンサイトメンテナンス、ヘルスメトリクスの収集、運用設定の管理などに責任を持ちます。また CPO は CP が OCPP(Open Charge Point Protocol) や ISO 15118 といった最新の業界標準やプロトコルに適合していることを確認する責任も負っています。そして、これらすべてはスケールアップした CP をサポートできるセキュリティ対策とともに実施されなければなりません。
About AWS IoT Core
AWS IoT Core はインフラを管理することなく、何十億ものデバイスを接続し、何兆ものメッセージを AWS サービスとの間でルーティングすることができます。 AWS IoT Core はスケーリングとメッセージルーティングという大変な処理をこなし、パブリッシュとサブスクライブのパターンで通信する CP のようなリモートデバイスの大規模なフリートをサポートする必要があるお客様にとって、より簡単なものとなっています。 AWS IoT Core は MQTT , HTTPS , MQTT over WebSocket をネイティブに実装し OCPP のような他のプロトコルをサポートするように適応させることが可能です。
概要
市販の CP の多くは CPO との双方向のパブリッシュ・サブスクライブの通信手段として OCPP を実装しています。 AWS 上で CPO を運用するには CP が通信する OCPP WebSocket エンドポイントの導入が必要です。このエンドポイントは OCPP Gateway と呼ばれ OCPP と MQTT の間のプロキシとして機能し AWS IoT Core や AWS 上に構築された下流 CPO サービスとの統合を可能にします。
次のアーキテクチャ図は、このブログ記事で構築するエンドツーエンド・ソリューションの概要を示しています。
図 1: CPO サービスにプロキシされたチャージポイント OCPP メッセージと一対一の関係性の WebSocket 接続と MQTT トピック |
アーキテクチャ
以下のアーキテクチャ図は、このソリューションがお客様のアカウントに展開するリソースを示しています。
図 2: OCPP Gateway ソリューションスタックアーキテクチャ |
OCPP Gateway は AWS Fargate または Amazon Elastic Compute Cloud(EC2) 上で実行可能な Amazon ECS アプリケーションとして展開されます。AWS Fargate はインフラ管理の必要がなく、このソリューションに適したオプションです。コンテナ化されたアプリケーションは水平方向に拡張することができ、接続する CP の数の変化に応じて OCPP Gateway を自動的にスケールアップまたはスケールダウンすることが可能です。 ECS タスクは長時間実行されるため WebSocket 接続を長時間維持することができ、ネットワークトラフィックと接続オーバーヘッドを削減することができます。
ネットワークロードバランサー (NLB) は、複数の OCPP ゲートウェイコンテナの前段に配置されます。 NLB は CP が接続を開始する OCPP エンドポイントとして機能する単一の完全修飾ドメイン名 (FQDN) を提供します。接続が開始されると NLB はチャージポイント接続を OCPP ゲートウェイインスタンスの1つにルーティングし、このインスタンスは自身と CP の間で WebSocket 接続を確立します。
CP が OCPP Gateway のインスタンスとのソケット接続を確立すると、そのハンドラは CP の一意の識別子を Thing ID として AWS IoT Core への MQTT 接続をセットアップします。そのクライアントは、その CP に関連する MQTT メッセージトピックをサブスクライブします。
OCPP ゲートウェイが実装する MQTT クライアントはソケットを認識するため MQTT サブスクリプションと CP の間に一対一の関連性を持たせることができます。 CPO によって開始されたメッセージは、宛先 CP に関連付けられた MQTT クライアントに配信され、ソケットを介してその CP に転送されます。 AWS IoT Core は非常に弾力的であり、より多くの CP が搭載されれば容易に拡張することができます。
ソリューション・ウォークスルー
このソリューションは AWS IoT Core と統合する OCPP Gateway を導入することで AWS を使用してスケーラブルな CPO を構築する方法を示しています。以下のステップでは AWS アカウントへの OCPP Gateway のデプロイを説明し CP メッセージをシミュレートする方法を示し AWS リソースを使用してこれらのメッセージに対処する方法の例を提供します。
前提条件
お使いの環境が、以下の前提条件を満たしていることを確認してください:
- AWS アカウントを持っている
- AWS アカウントで
AdministratorAccess
のポリシーが付与されている(本番環境では、必要な権限に制限することを推奨します) - コンソールとプログラムへのアクセスが可能
- AWS CLI がインストールされ、その AWS アカウントの設定がされている
- NodeJS 12+ がインストールされている
- Typescript 3.8+ がインストールされている
- AWS CDK CLI がインストールされている
- Docker がインストールされている
- Python 3+ がインストールされている
CDK の準備
ソリューションは AWS Cloud Development Kit (CDK) を使用した Infrastructure-as-Code で、お客様の AWS アカウントにデプロイされます。
- リポジトリを clone します
git clone https://github.com/aws-samples/aws-ocpp-gateway.git
- ターミナル上でコンピュータ上のこのプロジェクトに移動します
cd aws-ocpp-gateway
- このコマンドを実行して、プロジェクトの依存関係をインストールします
npm install
- スタックをデプロイする対象の AWS アカウント ID とリージョンを CDKで使う環境変数に設定します
注: AWS IoT Core はこれらの AWS リージョンで利用可能です
export CDK_DEPLOY_ACCOUNT=targetAccountId (e.g. 12345678910)
export CDK_DEPLOY_REGION=targetRegion (e.g. eu-west-1)
- (オプション) 対象のアカウントとリージョンに対して AWS CDK をブートストラップします
注: このアカウントとリージョンの組み合わせで、これまで AWS CDK を使用したことがない場合に必要です。 (CDK のブートストラップに関する詳細情報)。
npx cdk bootstrap aws://{targetAccountId}/{targetRegion}
(オプション)独自ドメイン名で TLS を使用する WebSocket を有効にする
アカウントに Amazon Route 53 の hosted zone がある場合、以下のこともこのソリューションで自動的に作成できます
- サブドメイン (A レコード)
gateway.yourdomain.com
を作成 - AWS Certificate Manager (ACM) で SSL 用の証明書を作成
- ゲートウェイの
wss://gateway.yourdomain.com
で TLS を有効化 /bin/aws-ocpp-gateway.ts
のこの行のコメントを削除しyourdomain.com
を自分のドメイン名 (例:example.com
) に置き換えてください。
// domainName: 'yourdomain.com',
AWS アカウントにソリューションをデプロイ
- 以下のコマンドを実行して Docker が実行されていることを確認
docker version
注: 以下のようなエラーが表示された場合は Docker が起動していないため、再起動する必要があります
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
- 以下のコマンドで OCPP ゲートウェイをデプロイ
npx cdk deploy
注: この手順は、お使いのコンピューターとネットワークの速度によって、約 10 分かかることがあります。
- 選択したリージョンの CloudFormation コンソールで CDK のデプロイの進捗を確認できます。
スクリーンショット: AWS CloudFormation のスタックリソース |
- デプロイしたら
AwsOcppGatewayStack.websocketURL
の値をメモしておきます。
注: この WebSocket の URL は CP の構成で設定されるエントリーポイント、または後述する EV チャージポイントシミュレータのエントリーポイントです
独自ドメインを使用した場合は、以下のような出力
..
Outputs:
AwsOcppGatewayStack.loadBalancerDnsName = gateway.example.com
👉 AwsOcppGatewayStack.websocketURL = wss://gateway.example.com
...
もしくは、以下のような出力となります。
...
Outputs:
AwsOcppGatewayStack.loadBalancerDnsName = ocpp-gateway-xxxxxxx.elb.xx-xxxx-x.amazonaws.com
👉 AwsOcppGatewayStack.websocketURL = ws://ocpp-gateway-xxxxxxx.elb.xx-xxxx-x.amazonaws.com
...
CP の接続状況をシミュレート
物理的な CP を必要とせずに OCPP Gateway と AWS IoT Core の機能をテストして確認できるように simulate.py
という Python スクリプトを提供しています。 OCPP-2.0-CP-Simulator のような他の OCPP シミュレータを使用することも可能です。
シミュレーションのセットアップ
- AWS マネージメントコンソールで対象のリージョンを選択し AWS IoT Core , All devices , Things と開き Things タブ で Create a things を選択します。
- Create single thing を選択し Next で進みます
- Thing name を入力します
注: 各 EV チャージポイントは、1つの IoT Thing にマッピングする必要があります。このテストでは Thing 名を
CP1
として設定します。
スクリーンショット: IoT Thing の作成 |
- Next を選択
- Device certificate では Skip creating a certificate at this time を選択し Create thing で進みます
スクリーンショット: 証明書の作成をスキップ |
- ターミナルでこのフォルダへ移動
cd ev-charge-point-simulator
- 以下のコマンドで Python の 仮想環境を作成し、有効化します
python3 -m venv venv && source venv/bin/activate
- Python の依存関係をインストールします
pip3 install -r requirements.txt
EV チャージポイントの起動とハートビート通知をシミュレート
Python スクリプトは EV 充電ポイントの基本的な機能をシミュレートします
- CP ハードウェアに関する属性を含む
BootNotification
を送信する - CPO から指示された頻度で
Heartbeat
メッセージを送信する (これはBootNotification
への応答で返されるinterval
パラメータで定義される)
- 以下のコマンドで Python スクリプトを実行します。
--url
の値は cdk デプロイメントから返されたAwsOcppGatewayStack.websocketURL
に置き換えてください
python3 simulate.py --url {websocket URL generated from the AWS OCPP Stack} --cp-id CP1
注:
--cp-id CP1
を使用していますが、これは上記で作成した IoT Thing の値と一致する必要があります。--cp-id
が IoT Thing の名前と一致しない場合、接続は OCPP Gateway によって拒否されます。
正常な実行結果は以下のような出力があります
(venv) ev-charge-point-simulator % python3 simulate.py --url {websocket URL generated from the AWS OCPP Stack} --cp-id CP1
INFO:ocpp:CP1: send [2,"0678cb2a-a7a2-42bc-8037-d01164e77ac6","BootNotification",{"chargingStation":{"model":"ABC 123 XYZ","vendorName":"Acme Electrical Systems","firmwareVersion":"10.9.8.ABC","serialNumber":"CP1234567890A01","modem":{"iccid":"891004234814455936F","imsi":"310410123456789"}},"reason":"PowerUp"}]
INFO:ocpp:CP1: receive message [3,"0678cb2a-a7a2-42bc-8037-d01164e77ac6",{"currentTime":"2023-02-16T19:00:18.630818","interval":10,"status":"Accepted"}]
INFO:root:CP1: connected to central system
INFO:root:CP1: heartbeat interval set to 10
INFO:ocpp:CP1: send [2,"9b7933a7-5216-496d-9bb0-dae45014bb98","Heartbeat",{}]
INFO:ocpp:CP1: receive message [3,"9b7933a7-5216-496d-9bb0-dae45014bb98",{"currentTime":"2023-02-16T19:00:19.073675"}]
この実行結果は CP のシュミレーションが正しくされたことを意味します。最初に BootNotification
を送信し、その後、指定された間隔で Heartbeat
を送信することを表しています。出力には CP から AWS IoT に送信されたシミュレーション OCPP メッセージ(send
で始まる)と AWS から受信した応答(receive message
で始まる)の両方が含まれる。
- 異なる CP でシミュレーションする場合は
--cp-id
引数に異なる値を設定してください。
注:
--cp-id
の値に対応する IoT Thing がない場合 OCPP ゲートウェイは接続を拒否します。以下は IoTのThing として登録されていない CP2 を--cp-id
で渡すと失敗する例です
(venv) ev-charge-point-simulator % python3 simulate.py --url {websocket URL generated from the AWS OCPP Stack} --cp-id CP2
INFO:ocpp:CP2: send [2,"32dc5b6e-77b0-4105-b217-28e20b579ecc","BootNotification",{"chargingStation":{"model":"ABC 123 XYZ","vendorName":"Acme Electrical Systems","firmwareVersion":"10.9.8.ABC","serialNumber":"CP1234567890A01","modem":{"iccid":"891004234814455936F","imsi":"310410123456789"}},"reason":"PowerUp"}]
ERROR:root:CP2: received 1008 (policy violation) Charge Point CP2 not registered as an IoT Thing; then sent 1008 (policy violation) Charge Point CP2 not registered as an IoT Thing
AWS Consoleで OCPP のアクティビティを監視
CP との間のメッセージは AWS IoT Core を通じて仲介されます。これらのメッセージは MQTT パブリッシュ−サブスクライブ プロトコルを利用します。これらのメッセージはコンソールで確認することができます。
-
- AWS マネージメントコンソールで対象のリージョンを選択し AWS IoT Core, MQTT test client と開きます
- テストクライアントで Subscribe to a topic のタブを選択し、以下の2つのトピックを Topic filter に入力してサブスクライブします
a. CP から AWS へのすべてのメッセージを参照
+/in
b. AWS から CP へのすべてのメッセージを参照
+/out
スクリーンショット: すべてのトピックにサブスクライブ |
- Python スクリプトを実行して CP をシミュレートし MQTT テストクライアントでメッセージを確認
Device Shadow を利用してEV チャージポイントハードウエアの属性を追跡
CP が BootNotification を送信すると、そのハードウェア属性が IoT Thing に関連付けられた Device Shadow に保存されます。これらの属性は、コンソールで確認することができます。
- AWS マネージメントコンソールで対象のリージョンを選択し AWS IoT Core, All devices, Things と開きます
- 以前に作成した Thing に対してチェックボックスをにチェックを付けます
- Device Shadow のタブを選択
- リンクとなっている Classic Shadow を選択すると EV チャージポイントから報告された属性を含む Device Shadow document を確認することが出来ます
{
"state": {
"reported": {
"chargingStation": {
"model": "ABC 123 XYZ",
"vendorName": "Acme Electrical Systems",
"firmwareVersion": "10.9.8.ABC",
"serialNumber": "CP1234567890A01",
"modem": {
"iccid": "891004234814455936F",
"imsi": "310410123456789"
}
},
"reason": "PowerUp"
}
}
}
スクリーンショット: IoT Thing のシャドードキュメント |
- 異なる CP ハードウェアの属性値を
simulate.py
スクリプトの引数に渡してシミュレートし、デバイスシャドー の変化を検証します
--cp-serial
– シリアル番号を指定--cp-model
– モデルIDを指定--cp-version
– ファームウエアのバージョンを指定--cp-vendor
– ベンダー名を指定
まとめ
この投稿では AWS サービスを使用して、高スケーラブルで低レイテンシーの CPO を構築する方法について学びました。 AWS Fargate を使用して OCPP-to-MQTT プロキシである OCPP Gateway をデプロイし AWS IoT Core のマネージドルーティングとスケーリング機能を利用して AWS 上でチャージ ポイント オペレーター ソリューションを展開および運用することができます。AWS IoT Rule を使用して EV 充電ポイントからのメッセージを Amazon DynamoDB や AWS Lambda などの他の AWS サービスにフィルタリングおよびルーティングし、カスタムレポートや自動ワークフローを作成する方法について学びました。
本ソリューションとサンプルコードはオープンソースとして公開されており、お客様のビジネスニーズに合わせて容易に適用することが可能です。
この投稿が有益であり、ウォークスルーが役に立ったことを願っています。AWS はいつも通り、フィードバックを歓迎します。以下の LinkedIn のプロフィールから、著者と気軽にコンタクト/メッセージしてください。
(オプション)さらに試したい場合
このセクションでは AWS 上で OCPP に準拠した CPO を構築するために、可能な限りのシミュレーションやテストをご自身で試していただくことを提案します。
負荷試験
AWS IoT Core はフルマネージドで伸縮性の高いサービスであり、数百万のデバイス (Things) をサポートするために拡張します。 OCPP Gateway はオートスケーリングにより CP のフリートが増加しても自動的にスケールアップします。
- 負荷テストツールまたは付属の Apache JMeter の設定を使用して、数千の CP の負荷をシミュレートします
- AWS マネージメントコンソールで対象のリージョンを選択し Elastic Container Service を選択します
- Cluster の下に OCPP ゲートウェイスタックが作成したクラスタのリンクがあるので開きます(
AwsOcppGatewayStack
で始まる名前) - Metrics タブを開きます
- 負荷が大きくなるにつれて、タスクの数が1つから2つなどに増えていく様子を確認します
オートスケーリングは、平均 CPU 使用率が 60% を超えると発動するように設定されています。さらに負荷をかけたり、この閾値を下げたりして、影響をテストすることができます。
JMeter や類似のロードテスターを使用している場合は、作成するスレッド (Things) の数とテストを実行する期間に注意してください。このソリューションは、何千もの Things に容易にスケールし、無期限に実行されるため AWS アカウントに予期せぬ請求が発生する可能性があります。スケーラビリティをテストするために負荷テストを使用することをお勧めしますが、コストを削減するためにテストを迅速に停止することをお勧めします。
負荷試験を実施する際には各種制限に注意してください。
Rules for AWS IoT
AWS IoT の Rule は MQTT メッセージをフィルタリングし AWS の他のサービスにルーティングするために使用することができます。 Heartbeat
メッセージをキャプチャし DynamoDB のテーブルに記録する新しいルールを作成し、最後の既知のイベントとして使用します。
- AWS マネージメントコンソールで対象のリージョンを選択し DynamoDB を開きます
- Create table を選択します
- Table name に
chargePointHeartbeat
を入力し Partition key にchargePointId
を入力します - Create table を選択します
- AWS マネージメントコンソールで対象のリージョンを選択し AWS IoT Core, Message routing , Rules と開きます
- Create Rule を選択します
- Rule name に
chargePointHeartbeat
と入力し Next を選択します - 以下の内容を SQL statment に入力し Next を選択します
SELECT
topic(1) AS chargePointId,
timestamp() AS lastTimestamp
FROM '+/in'
WHERE get(*, 2) = 'Heartbeat'
スクリーンショット: IoT Rule SQL statement |
- Action 1 では DynamoDBv2 を選択します
- Table name では前の手順で作成した DynamoDB のテーブルを指定します
スクリーンショット: IoT Rule アクション |
- Create new role を選択し Role name に
chargePointHeartbeat
と入力し Create を選択します - Next を選択し Create を選択します
- マネージメントコンソールで DynamoDB に戻り Tables, Explore Items と開きます
- Table では前の手順で作成したテーブルを選択します
- Python スクリプトを実行して CP をシミュレートし DynamoDB テーブルにハートビートが追加・更新されるのを確認します。
コネクションのハンドリング
1つの CP は 1つの OCPP ゲートウェイと紐付けないと CPO から正しい接続への応答のルーティングが影響を受ける可能性があります。再接続の試行をシミュレートすることができます。
- (オプション)まだお持ちでない場合は
wscat
ユーティリティをダウンロードし、インストールします - ターミナルを開き WebSocket のコネクションを作成します
wscat -c {AwsOcppGatewayStack.websocketURL}/CP1 -s ocpp2.0.1
Connected (press CTRL+C to quit)
>
- 2 番目のターミナルウィンドウで同じコマンドを実行し、同じ CP を使用して別の接続を作成します。例
CP1
- この新しい接続が確立されると、以前の接続が自動的に閉じられることが確認されます
Disconnected (code: 1000, reason: "")
- IoT Thing として設定されていない CP との接続をテストすると、接続の試みは拒否されます
wscat -c {AwsOcppGatewayStack.websocketURL}/CPX -s ocpp2.0.1
Connected (press CTRL+C to quit)
Disconnected (code: 1008, reason: "Charge Point CPX not registered as an IoT Thing")
後片付け
シミュレーションの実行が終わったら、ターミナルで次のコマンドを実行して Python 仮想環境 (venv
) を停止します
deactivate
以下のコマンドを実行することで AWS アカウントに作成された OCPP Gateway Stack とすべての関連リソースを削除できます
npx cdk destroy
翻訳者について
この投稿は AWS で OCPP プロトコルをサポートするための幅広い取り組みの一部である。David Goehrig、Sergey Pugachev、Clement Rey、Ozan Cihangir にこの取り組みへの貢献を感謝します。
この記事は Building an OCPP-compliant electric vehicle charge point operator solution using AWS IoT Core の日本語訳です。プロトタイピング ソリューション アーキテクトの市川が翻訳しました。