Home Assistantでの JSONからのデータ抽出

ESPHome の ble_scanner から受信したJSONデータから必要な要素の値を取り出すことを試したが、思ったよりも時間がかかったので、備忘録を残しておく。

背景

ESPHomeから構造をもったデータをHome Assistantに送って、Home Assistantで蓄積や表示などの処理をしたい。構造をもっているということと、個々の要素を送る方式では、データのタイムスタンプと要素の間の関連が曖昧になるためである。これは、Home Assistantが受信したデータのタイムスタンプがHome Assistantのクロックに基づくタイムスタンプになってしまい、同一構造内のデータでも個別に送るとHome Assistantでは受信時点が異なると異なるタイムスタンプになってしまい。タイムスタンプが近いという曖昧な基準でしか同じ構造データの要素であるという判定ができないためである。

まず、練習として ESPHome の ble_scannerの以下のような比較的単純な構造のJSONデータからタグ付けされた要素の値をHome Assistantで抽出して、Home Assistantのオーバービューにカードで表示する。


環境

  • M5Stack Atom Lite
  • Windows 11 Pro 22H2 22621.1702
    • CP210x Universal Windows Driver v11.2.0 (10/21/2022)
  • ESPHome version: 2023.6.0-dev
  • Home Assistant 2023.5.3 (Supervisor 2023.04.1, Operating System 10.1, フロントエンド: 20230503.3)

ESPHome BLE Scanner

JSON形式のデータを出力するコンポーネントとして ESPHome の ESP32 Bluetooth Low Energy Scanner を利用する。

ESPHome で利用した yaml ファイル(87fb58.blescanner.yaml)は以下の通り 。 text_sensor: – platform: ble_scanner name: "BLE Scan" のところで、ble_scanner を利用している。

esp32_ble_tracker の scan_parameters で interval: 2000ms として、2秒ごとに BLE の scan をするように指定している。

BLEのscanが先に行われると WiFiの接続がされないままにある場合が頻発したので、WiFiが接続してから(wifi.connected が成立してから) BLE scan を行うようにしている (id(ble_tracker).start_scan())。この条件判定を interval: の部分で10秒ごとに行うようにしていて、WiFi接続に時間がかかる場合でも、WiFi接続がされてから BLE scanが開始されるようにしている。このままだと、BLE scanが開始されてからも10秒ごとに BLE scanを開始しようとしてすでに開始しているという warning がログに出る ([W][esp32_ble_tracker:228]: Scan requested when a scan is already in progress. Ignoring.)。一度は、BLE Scanの開始した状態を記憶して、一度開始した後は、start_scan()を呼び出さないようにしてみたが、BLE Scanが止まってしまう場合があり、定期的に start_scan() を呼び出した方が安定しているので、以下のプログラムに示すようにしている。

yamlの初期生成

上記のyamlファイルは、Home Assistantで生成した yaml ファイルを修正して作ったものである。api: encryption: key: ("Owuf3MWnoaRnBG8e/tq991ghF2egw4gUUnqZxLTbnhQ=")や ap: password: ("xX7uJTmmdIVy") は、Home Assistantによって自動生成されたものをそのまま使っている。

Home Assistant の「設定」→「アドオン」で ESPHome をインストールした後に、 ESPHome を選択し、「Web UIを開く」をしてから「+ New Device」をクリックする。

「Create configuration」で名前を付ける()。Select your device type で適切なものを選択する(この例では ESP32を選択している)。そうすると Configuration created! が表示され、Encription key も表示される(Home Assistantへ登録する際に必要となるが、yamlファイルなどをから参照できる)。「INSTALL」をクリックすると インストールがされる。

How do you want to install <名前>.yaml on you device? というメッセージが表示されるので、接続方法を選択する。Over-The-Air (OTA) のファームウェアが書き込まれていないデバイスでは、USB接続が必要である。ここでは、Plug into this computer を選択し、Webブラウザを起動しているローカルコンピュータとESP32デバイスがUSBで接続されているとする。

Install ESPHome via the browser の 1. Download project をクリックすると <名前>-factory.bin ()がローカルコンピュータにダウンロードされる。 2. Open ESPHome Web をクリックして、ESP Deviceの CONNECT をクリックする。Web Serialでの接続ポートの選択が求められる。適切なデバイスドライバがインストールされ、Webブラウザで Serial の利用が許可されている必要がある。

手元の環境ではWeb Serial での接続が高い頻度で失敗してフラストレーションが溜まった。

compile と upload

PowerShell では、以下のコマンドを実行することで、コンパイルとアップロードがされる。compile と upload に分けてもよい。

ファームウェアの書き込みは、初回は USB接続で行う必要がある。以下のようにアップロード方法の選択が求められたら1 を選ぶ。もちろん、2回目以降もUSB接続で書き込むことが可能だが、M5Stack Atom Lite では、INFO Upload with baud rate 460800 failed. Trying again with baud rate 115200.という表示が出て通信速度 115200bpsでアップロードがされるので遅い。

一度 OTA用のファームウェアを書き込み済みで、デバイス名も同じならUSB接続は必要なく、以下のように Over The Air を選択することができる。OTAの方が速い。

Home AssistantでJSONから値を抽出するセンサー

BLE Scanner からのJSONデータから値を抽出し、Home Assistant のセンサーとして機能させるようにする。

Home Assistantへの登録

Home Assistantの「設定」→「デバイスとサービス」で「+ 統合を追加」をクリックし、ブランド名「ESPHome」で検索し、ESPHomeを選択する。

ホスト名は、ESPHomeのyaml (87fb58.blescanner.yaml)の中で esphome: name: で指定したもの( esphome-web-87fb58 )を基に、Multicast DNS (mDNS)で名前解決されるように .local をつける( esphome-web-87fb58.local )。

ESPHome で設定した暗号化キーには、ESPHomeのyaml (87fb58.blescanner.yaml)の api: encryption: key にあるものを指定する。

デフォルトのデバイス名は、ESPHomeの yaml (87fb58.blescanner.yaml)の中でesphome: friendly_name: で指定したもの (87fb58 Atom Lite)になる。デバイス名は変更することができる。

Home Assistant でのエンティティ名

エンティティ名は domain.id の形式であり、BLE Scan (text sensor) の domainはsensor である。BLE Scanner のエンティティ名は、 esphome: friendly_name: で定めた "87fb58 Atom Lite" と text_sensor: – platform: ble_scanner name:で指定した "BLE Scan"を「_」で連結したものがエンティティ名の基になる。大文字は小文字に変換され、空白はアンダースコアに変換される。この場合には、連結したものは sensor.87fb58_atom_lite_ble_scan となる。

JSON形式データからのセンサーデータ抽出

BLE Scanner からのJSONデータから値を抽出し、Home Assistant のセンサーとして機能させるためには、Template Sensor を利用する。 Home Assistantのtemplateは、jinja2 を使用している。

Home Assistantで利用できるようにするセンサーの名前は、JSONデータ全体を ble_json_data、タイムスタンプ(timestamp)を timestamp、MACアドレス(address)を ble_address、RSSI (rssi)を ble_rssi、名前(name)を ble_nameとする。

Home Assistantの /config/configuration.yaml に以下を追加した。

states を使って受信したデータを取り出しているが、他によりよい方法があるかははっきりしていない。sensor.87fb58_atom_lite_ble_scan はHome AssistantでBLE scannerを参照するエンティティ名であり、適切に変更する必要がある。

ble_json_data は、BLE scannerからのデータそのままである。ble_timestamp、ble_address、ble_rssi、ble_name は、BLE scanner のデータをstates を使って取得し、それをJSONに変換し(| from_json)、JSONオブジェクトから必要な属性(timestamp、address、rssi、name)の値を取り出している。もっとすっきりした方法があってもよさそうである。

Home Assistantのオーバービュー

Home Assistantのダッシュボードへのエンティティカード追加

Home Assistantのダッシュボードにエンティティカードを追加する。BLE Scanからのデータをそのまま文字列として表示するには、エンティティ名 ( sensor.87fb58_atom_lite_ble_scan ) を選択する。

ble_json_data など、先に Home Assistantのyamlで定義したセンサーを表示するには、sensor.ble_json_data を選択する。他の ble_timestamp、ble_address、ble_rssi、ble_nameも同様に、それぞれ、sensor.ble_timestamp、sensor.ble_address、sensor.ble_rssi、sensor.ble_nameを選択する。

Home Assistantのオーバービュー表示

オーバービューでは次のように表示され、データを受信すると更新されることがわかる。エンティティカードでは、エンティティ名ではなく、friendly_nameが表示されている。