Device Shadow
Device Shadowは、EMQX Fleetsがクラウドの意図とデバイスの現実を同期させるために使用する仕組みです。デバイスがオフラインでも常に利用可能な、デバイスの状態を永続的かつバージョン管理された形で表現します。
3つの状態モデル
各Thingは、3つの状態を含む1つのシャドウドキュメントを持ちます。
| 状態 | 所有者 | 意味 |
|---|---|---|
| Reported | デバイス | デバイス自身が最後に報告した実際の現在の状態 |
| Desired | クラウド | クラウドがデバイスに到達してほしい目標状態 |
| Delta | Fleetsによる計算 | DesiredとReportedの差分、つまりデバイスがまだ適用すべき内容 |
クラウドがDesired状態を書き込むと、FleetsがDeltaを計算してデバイスにプッシュします。デバイスはDeltaを適用し、新しい状態を報告します。Fleetsはシャドウを更新し、Deltaを再計算します(DesiredとReportedが一致するとDeltaは空になります)。
クラウドがDesiredを書き込む → FleetsがDeltaを計算 → デバイスがDeltaを受信
↓
クラウドがReportedを読み取る ← FleetsがReportedを保存 ← デバイスが状態を報告シャドウのバージョニング
各シャドウドキュメントには単調増加するバージョン番号があります。DesiredまたはReportedの状態が変わるたびにバージョンがインクリメントされます。デバイスはこのバージョンを使って古い更新を検出し、順序が逆の変更を適用しないようにできます。
コンソールでシャドウを確認する
- Fleetsのデプロイメントで、左メニューのShadow Syncに移動します。
- 左側のリストからThingを選択します。各エントリにはThing名とそのMQTTクライアントIDが表示されます。
- 右側のパネルには以下が表示されます:
- Thing ID、Thing Type、現在のVersion、およびUpdated Atのタイムスタンプ
- Current state (Reported):デバイスが最後に報告した状態
- Target state (Desired):クラウドがデバイスに到達してほしい状態
デバイスがまだ状態を報告していない場合、Reportedパネルには「Device has not reported any state yet.」と表示されます。
最新のシャドウデータを再読み込みするには、Refresh(リフレッシュアイコン)をクリックしてください。

Desired状態を更新する
デバイスにDesired状態の変更をプッシュするには:
- Shadow Syncに移動し、Thingを選択します。
- **Target state (Desired)**パネルにJSONオブジェクト形式でDesired状態を入力します:json
{ "targetTemperature": 22, "mode": "cooling" } - Update Desiredをクリックします。
FleetsはDesired状態を保存し、Deltaを計算してMQTT経由でデバイスにパブリッシュします。
REST APIを使ってプログラムからDesired状態を更新することも可能です:
PATCH /api/v1/things/{id}/shadowデバイスが状態変更を受け取る方法
クラウドがDesired状態を更新すると、Fleetsは2つのMQTTトピックにパブリッシュします:
| トピック | 内容 |
|---|---|
$emqx/things/{thingName}/shadow/update | Desired状態の全ペイロード |
$emqx/things/{thingName}/shadow/update/delta | Reportedと異なるフィールドのみ |
デバイスはDeltaトピックをサブスクライブし、異なるフィールドのみを適用してから更新された状態を報告するべきです。
デバイスがDesired状態更新時にオフラインの場合、Deltaはデバイスが再接続してトピックをサブスクライブした際に配信されます(永続的なMQTTセッションを使用)。
デバイスが状態を報告する方法
デバイスは現在の状態を以下のトピックにパブリッシュして報告します:
$emqx/things/{thingName}/shadow/updateペイロード例:
{
"state": {
"reported": {
"temperature": 21.5,
"targetTemperature": 22,
"mode": "cooling"
}
},
"clientToken": "optional-correlation-id",
"version": 3
}EMQXはこのメッセージをFleetsにルーティングし、Fleetsは以下を行います:
- GreptimeDB(時系列履歴)とPostgreSQL(最新コピー)にReported状態を保存
- Deltaを再計算
- シャドウのバージョンを更新
また、デバイスはHTTPS経由で状態を報告することも可能です:
POST /api/v1/thing-datas/shadow/reportedプロトコルの詳細はMQTT IntegrationまたはHTTPS Integrationを参照してください。
Desired状態をクリアする
Desired状態を削除するには(例えばデバイスが収束した後):
- Shadow Syncに移動し、Thingを選択します。
- Clear Desired(リフレッシュボタンの隣のアイコン)をクリックします。
REST APIを使う場合は以下を実行します:
DELETE /api/v1/things/{id}/shadowシャドウ履歴
Reported状態はGreptimeDBに時系列データとして保存されます。過去のシャドウ値はDevice Queryの時系列フィルターでtsFrom、tsTo、tsFieldNameパラメータを使ってクエリ可能です。