🗼
ECHONET Liteを初めて触るときに読む記事(2025 Summer)
はじめに
ユアスタンドでハードウェア・ファームウェア開発担当をしている吉田です。今回はECHONET Liteについてです。
ECHONET Liteを初めて触るときにサクッと概要を知りたい人向けの内容です。先人たちの記事なども貼りまくるので参考程度にどうぞ!
公式ドキュメント
一番お世話になった記事
ECHONET Liteとは
- エコーネットコンソーシアムが策定し、ISO/IECの国際標準にもなっています
- センサー、白物家電から太陽光発電、蓄電池、スマートメータまで、120種類以上の機器を「機器オブジェクト」として定義
- 軽量化・高い相互運用性を追求しており、OSIモデルの第5層以上にフォーカスして設計されています。Modbusと比べると高レイヤーのプロトコルに位置する。
📡 ECHONET Lite 電文構造(例付き)
電文例
フィールド名 | 例(16進) | 説明 |
---|---|---|
EHD1 | 0x10 |
ECHONET Lite使用の宣言(固定値) |
EHD2 | 0x81 |
フォーマット1(ECHONET Lite仕様) |
TID | 0x01 |
トランザクションID(任意) |
SEOJ | 05ff01 |
送信元オブジェクト(クラス:管理クラス=0x05ff、01:インスタンス) |
DEOJ | 027e01 |
送信先オブジェクト(クラス例:充放電器クラス=0x7e、01:インスタンス) ※他例:蓄電池=0x7d、太陽光発電=0x79 |
ESV |
0x60 / 0x61 / 0x62
|
サービスコード(Set/SetC/Getなど) |
OPC | 0x01 |
プロパティ数(EPC以下のセット数) |
EPC |
0x80 など |
プロパティコード(例:動作状態、蓄電残量など) |
PDC |
0x01 など |
EDTのバイト数(例:1バイト) |
EDT |
0x30 など |
設定値 or 読み出された値(例:ON=0x30, OFF=0x31) |
対応機器(オブジェクトグループ)の例
家電から産業機器まで広く対応するわけです。
それに対してグループコードが振られていています。(後ほど活用)
引用元:ECHONET Consortium ECHONET Lite 通信ミドルウェア仕様
EHD1,EHD2,THD
- EHD1/EHD2 = 0x10/0x81で固定です。ECHONET Liteということを宣言します。
- TIDはTransactionIDなので任意となります。デフォルトで0x01としておきます。
EDATA(SEOJ~EDT1)
ここが実質プロトコルのメインメッセージ群となります。
SEOJ (送信元オブジェクト)
-
05FF01
は、管理クラス(Controller/Node Profile)である "自分自身(コントローラ)" を示します。💻-
05FF
: コントローラー(HEMS制御コントローラーなど)💻 -
01
: インスタンス(送信元識別番号)
-
DEOJ(送信先オブジェクト)
- クラスコードにより種別機能を特定します。例:
-
0x027E01
: 充放電器クラス(0x7E)⚡ -
0x027D01
: 蓄電池(0x7D)🔋 -
0x027901
: 太陽光発電(0x79)☀️
-
- 0x02はグループコード、0x01はインスタンス
ESV(サービスコード)
-
0x60
= Set(書き込み、応答不要)📝 -
0x61
= SetC(書き込み+確認応答)📝✅ -
0x62
= Get(読み出し要求)📖
Set(0x60)
設定値を書き込む指示
[ コントローラ: 05FF01 ] 💻
▶ 0x60: 書き込み指示
(応答は不要)
-----------------------------------> [ 充放電器クラス:0x027E01 ] ⚡
SetC(0x61)
Set+応答依頼を行う。設定したパラメータを返すことが多い
[ コントローラ: 05FF01 ] 💻
▶ 0x61: 書き込み + 応答依頼
-----------------------------------> [ 充放電器クラス:0x027E01 ] ⚡
◀ 0x71: 応答(例: 充電出力)
Get(0x62)
状態や設定値を読み出す
[ コントローラ: 05FF01 ] 💻
▶ 0x62: 読み出し要求
-----------------------------------> [ 充放電器クラス:0x027E01 ] ⚡
◀ 0x72: 状態応答 (例: 運転状態)
OPC(プロパティ数)
- 1つの電文で送信するプロパティの数を指定します 🔢
- 例:
0x01
= 1つのプロパティ、0x02
= 2つのプロパティ - 通常は1つのプロパティを扱うことが多いため、
0x01
が一般的
EPC(プロパティコード)
- 操作対象のプロパティを指定するコード 🔧
- 機器の種類によって利用可能なプロパティが異なります
機器固有のプロパティ例:
- 蓄電池(0x7D):
0xE0
= 蓄電残量🔋、0xE1
= 運転モード⚙️ - 充放電器(0x7E):
0xE0
= 充電出力⚡、0xE1
= 放電出力⚡ - 太陽光発電(0x79):
0xE0
= 発電電力☀️、0xE1
= 発電電力量☀️
PDC (EDTのバイト数)
- EDT(設定値)のデータ長をバイト数で指定 📏
- 例:
0x01
= 1バイト、0x02
= 2バイト、0x04
= 4バイト
EDT(設定値)
- 実際のデータ値が格納される部分 💾
- データ型やプロパティによって形式が異なります
よく使われる値の例:
- 動作状態(0x80):
-
0x30
= ON 🟢 -
0x31
= OFF 🔴
-
- 真偽値:
-
0x41
= TRUE ✅ -
0x42
= FALSE ❌
-
- 数値:直接の値(例:
0x64
= 100)🔢 - 文字列:ASCIIコードで格納 📝
ソースコード例
シナリオ
コントローラーから充放電器に対してON/OFFを設定する
コントローラーから充放電器に対してON/OFFを設定する
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import socket
import struct
import datetime
# ECHONET Lite設定
TARGET_IP = "127.0.0.1" # 接続先IP
PORT_ECHONET_LITE = 3610 # ECHONET Liteはポート3610で通信
EL_INSTANCE = 0x01 # インスタンスは0x01
# 電文構築関数
def build_echonet_message(esv, epc, pdc, edt):
"""ECHONET Lite電文を構築"""
return struct.pack(">2B H 11B",
0x10, 0x81, 0x01, # EHD1, EHD2, TID
0x05, 0xFF, 0x01, # SEOJ (コントローラー)
0x02, 0x7E, EL_INSTANCE, # DEOJ (充放電器)
esv, 0x01, epc, pdc, edt # ESV, OPC, EPC, PDC, EDT
)
def send_message(sock, message, description):
"""メッセージ送信"""
print(f"=== {description} ===")
print(f"送信: {message.hex()}")
sock.sendto(message, (TARGET_IP, PORT_ECHONET_LITE))
# 応答受信
try:
sock.settimeout(5.0)
response, addr = sock.recvfrom(1500)
print(f"受信: {response.hex()}")
return response
except socket.timeout:
print("応答なし")
return None
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 1. Get命令: 動作状態を読み取り
get_message = build_echonet_message(
esv=0x62, # Get
epc=0x80, # 動作状態
pdc=0x00, # データなし
edt=0x00
)
send_message(sock, get_message, "Get: 動作状態読み取り")
# 2. Set命令: 動作状態をONに設定
set_message = build_echonet_message(
esv=0x60, # Set
epc=0x80, # 動作状態
pdc=0x01, # 1バイト
edt=0x30 # ON
)
send_message(sock, set_message, "Set: 動作状態ON")
# 3. SetC命令: 運転モードを充電に設定(応答あり)
setc_message = build_echonet_message(
esv=0x61, # SetC
epc=0xDA, # 運転モード(標準プロパティ)
pdc=0x01, # 1バイト
edt=0x42 # 充電(標準値)
)
send_message(sock, setc_message, "SetC: 運転モード充電")
sock.close()
if __name__ == "__main__":
main()
実行結果例:
=== Get: 動作状態読み取り ===
送信: 10810105ff01027e0162018000
受信: 108101027e0105ff017201800130
=== Set: 動作状態ON ===
送信: 10810105ff01027e016001800130
応答なし
=== SetC: 運転モード充電 ===
送信: 108101027e0105ff016101da0142
受信: 108101027e0105ff017101da0142
受信電文の解説:
Get応答例: 108101027e0105ff017201800130
10 81 01 # EHD1, EHD2, TID
02 7e 01 # SEOJ (送信元: 充放電器)
05 ff 01 # DEOJ (送信先: コントローラー)
72 # ESV (Get_Res: 読み出し応答)
01 # OPC (プロパティ数: 1個)
80 # EPC (動作状態)
01 # PDC (データ長: 1バイト)
30 # EDT (ON=0x30)
SetC応答例: 108101027e0105ff017101da0142
10 81 01 # EHD1, EHD2, TID
02 7e 01 # SEOJ (送信元: 充放電器)
05 ff 01 # DEOJ (送信先: コントローラー)
71 # ESV (Set_Res: 設定応答)
01 # OPC (プロパティ数: 1個)
da # EPC (運転モード)
01 # PDC (データ長: 1バイト)
42 # EDT (充電=0x42)
応答のESVコード:
-
0x72
: Get_Res (読み出し応答) -
0x71
: Set_Res (設定応答) -
0x73
: SetC_Res (設定応答、確認あり)
引用(公式ドキュメント)
各種スクショの引用元です。
開発背景とかも書いてますよ。
Discussion