初心者向けガイド:EV充電アプリはどうやって充電器と通信し、充電量と料金を計算しているのか?
電気自動車(EV)が普及する中で、ユーザーはスマートで直感的な充電体験を求めています。本記事では、Flaskを使ってEV充電システムを開発している方や初心者向けに、次のようなポイントをわかりやすく解説します。
- モバイルアプリがバックエンドとEVSE(充電器)とどう連携しているのか
- 充電セッションのエネルギー消費をどう測定するか
- 料金はどう計算されるのか
- SOC(State of Charge/バッテリー残量)をどう有効化するか
- FlaskとOCPPを使った実装例つき
🧩 EV充電システムの基本構成(4つの要素)
コンポーネント | 役割 |
---|---|
モバイルアプリ | ユーザーが充電器を探して、充電を開始・停止するために使用 |
Flaskバックエンド | アプリとEVSEの間の橋渡しをするサーバ |
EVSE(Charger) | 実際に電気を車に供給するハードウェア |
OCPPプロトコル | バックエンドと充電器が通信するための業界標準のプロトコル |
🔄 通信の流れ(図解)
アプリが直接EVSE(充電器)と通信するわけではありません。実際には以下のような流れです:
sequenceDiagram
participant User
participant App
participant Flask Backend
participant EVSE (Charger)
User->>App: Start Charging
App->>Flask Backend: POST /start_session
Flask Backend->>EVSE (Charger): OCPP RemoteStartTransaction
EVSE (Charger)-->>Flask Backend: MeterStart = 154200 Wh
Flask Backend-->>App: Charging session started
Note over EVSE (Charger): Charging in progress...
User->>App: Stop Charging
App->>Flask Backend: POST /stop_session
Flask Backend->>EVSE (Charger): OCPP RemoteStopTransaction
EVSE (Charger)-->>Flask Backend: MeterStop = 156700 Wh
Flask Backend-->>App: Energy used = 2.5 kWh
⚡ MeterStart
と MeterStop
によるエネルギー追跡
EVSE(Charger)は内蔵されたメーターで、充電開始と終了時の電力量を測定します。
値 | 内容 |
---|---|
MeterStart | 充電開始時の電力量(Wh) |
MeterStop | 充電終了時の電力量(Wh) |
計算例:
MeterStart = 154200 Wh
MeterStop = 156700 Wh
使用電力量 = (156700 - 154200) / 1000 = 2.5 kWh
💰 料金の計算方法
基本的な料金計算式:
料金 = 使用電力量 (kWh) × 単価(kWhあたりの料金)
Flaskのサンプルコード:
def calculate_cost(meter_start, meter_stop, rate_per_kwh=0.25):
energy_wh = meter_stop - meter_start
energy_kwh = energy_wh / 1000
return round(energy_kwh * rate_per_kwh, 2)
出力例:
{
"energy_kwh": 2.5,
"rate_per_kwh": 0.25,
"total_cost": 0.63
}
🔋 ボーナス:SOC(バッテリー残量)を有効化する方法
SOC(State of Charge)はEVのバッテリー残量(例:74%)を示すデータです。対応する充電器であれば、OCPPコマンドでSOCのレポート機能を有効化できます。
✅ ステップ1:SOCがサポートされているか確認
@app.route('/station/<cp_id>/check-soc', methods=['GET'])
def check_soc(cp_id):
ws = get_websocket(cp_id) # WebSocket接続を取得
request = call.GetConfigurationPayload(key=["MeterValuesSampledData"])
asyncio.run(ws.send(request))
response = asyncio.run(ws.receive())
for item in response.configuration_key:
if "StateOfCharge" in item.value:
return jsonify({"soc_supported": True})
return jsonify({"soc_supported": False})
✅ ステップ2:SOCを有効化する
@app.route('/station/<cp_id>/enable-soc', methods=['POST'])
def enable_soc(cp_id):
ws = get_websocket(cp_id)
request = call.ChangeConfigurationPayload(
key="MeterValuesSampledData",
value="StateOfCharge,Energy.Active.Import.Register"
)
asyncio.run(ws.send(request))
response = asyncio.run(ws.receive())
if response.status == "Accepted":
return jsonify({"status": "success", "message": "SOC enabled"})
return jsonify({"status": "failed", "message": "Change rejected"})
📊 MeterValues にSOCが含まれるようになる
{
"meterValue": [{
"timestamp": "2025-05-26T03:25:00Z",
"sampledValue": [
{"measurand": "Energy.Active.Import.Register", "value": "156300"},
{"measurand": "StateOfCharge", "value": "74"}
]
}]
}
アプリ画面の表示例:
🔋 バッテリー:74%
⚡ 使用電力量:2.1 kWh
💰 料金:$0.53
📱 アプリ側へのAPIレスポンス例
{
"session_id": "sess_001",
"meter_start": 154200,
"meter_stop": 156700,
"energy_kwh": 2.5,
"rate_per_kwh": 0.25,
"total_cost": 0.63,
"soc": 74,
"start_time": "2025-05-26T03:14:00Z",
"end_time": "2025-05-26T03:54:00Z"
}
🧱 推奨される技術スタック(バックエンド)
層 | 推奨技術 |
---|---|
Webフレームワーク | Flask |
EVSE通信プロトコル | OCPP 1.6(Mobility Houseライブラリ) |
データベース | PostgreSQL または MongoDB |
モバイルアプリ | Flutter または React Native |
決済ゲートウェイ | Stripe、PayPal、PromptPay(タイ向け) |
✅ まとめ
このガイドで、以下の内容が理解できたと思います:
- FlaskバックエンドがアプリとEVSE(Charger)をつなぐ役割
MeterStart
とMeterStop
によるエネルギー追跡と料金計算- SOC(State of Charge)機能の有効化方法
- OCPPとFlaskを組み合わせて、実用的なEV充電アプリの構築が可能
🚀 EV充電プラットフォームの開発を始めませんか?
初めてのシステム構築でも、ネットワーク運用でも、お気軽にご相談ください。
📬 お問い合わせ:www.simplico.net
💬 技術サポートや連携のご相談も可能です!
Related Posts
- Wazuhを理解する:その背後にあるオープンソースプロジェクトを探る
- アプリの認証を OCPP 中央システムに統合する方法
- Flask[async]・WebSocket・MongoDB を使って OCPP 1.6 中央システムを構築する
- AIはOdooの会計・在庫管理システムをどう強化するのか(開発視点付き)
- JavaScriptでフルスタックのEコマースシステムを開発しよう
- Python・Langchain・OllamaでエージェンティックAIを構築する方法(eコマース & 工場自動化向け)
- PythonとOBD-IIライブデータでP0420の根本原因を診断する
- スタートアップのアイデアを正しく検証するための『The Mom Test』の活用法
- RasaとLangchain、どちらを選ぶべきか?チャットボット開発の選択基準
- OCR Document Managerのご紹介:書類を簡単にテキスト化できるWebアプリ
- まだバズっていない「売れ筋商品」をAIで発見するツールを作っています ― 興味ありますか?
- あなたのウェブサイトがリードを失っている理由 — それは「沈黙」です
- スマート農業を革新するAgentic AIとは?あなたの農場が今すぐ導入すべき理由
- LangChain + Ollama で RAGチャットボットを作る方法
- SCPI を使った EXFO 機器の自動化:実践ガイド
- レガシーコードを扱いやすくするためのデザインパターン
- 🧠 レガシーコードに安全に新機能を追加する方法
- レガシーソフトウェアを安全に近代化 — 全面リライト不要!
- OpenSearchの仕組みとは?リアルタイム検索エンジンの内部構造を解説
- DjangoでBasicとPremium機能を分けるベストな戦略とは?
Our Products
Related Posts
- Wazuhを理解する:その背後にあるオープンソースプロジェクトを探る
- アプリの認証を OCPP 中央システムに統合する方法
- Flask[async]・WebSocket・MongoDB を使って OCPP 1.6 中央システムを構築する
- AIはOdooの会計・在庫管理システムをどう強化するのか(開発視点付き)
- JavaScriptでフルスタックのEコマースシステムを開発しよう
- Python・Langchain・OllamaでエージェンティックAIを構築する方法(eコマース & 工場自動化向け)
- PythonとOBD-IIライブデータでP0420の根本原因を診断する
- スタートアップのアイデアを正しく検証するための『The Mom Test』の活用法
- RasaとLangchain、どちらを選ぶべきか?チャットボット開発の選択基準
- OCR Document Managerのご紹介:書類を簡単にテキスト化できるWebアプリ
- まだバズっていない「売れ筋商品」をAIで発見するツールを作っています ― 興味ありますか?
- あなたのウェブサイトがリードを失っている理由 — それは「沈黙」です
- スマート農業を革新するAgentic AIとは?あなたの農場が今すぐ導入すべき理由
- LangChain + Ollama で RAGチャットボットを作る方法
- SCPI を使った EXFO 機器の自動化:実践ガイド
- レガシーコードを扱いやすくするためのデザインパターン
- 🧠 レガシーコードに安全に新機能を追加する方法
- レガシーソフトウェアを安全に近代化 — 全面リライト不要!
- OpenSearchの仕組みとは?リアルタイム検索エンジンの内部構造を解説
- DjangoでBasicとPremium機能を分けるベストな戦略とは?