Azure Log AnalyticsにSwitchBotのテレメトリ情報を記録する

2022/12/07に公開

はじめに

2022年末のAmazonブラックフライデーで、ついSwitchBotハブミニと、温湿度計をポチってしまいました(あとEcho Showも)。

SwitchBotのアプリでは、IFTTTやアレクサなど主要なサービスに標準で対応しているのですが、各種SwitchBotの操作の為のAPIが公開されているので使ってみました。

本記事は今回の検証の中で培った技術ノウハウの説明をAzure側メインに行います。

実際のソースコードやAzureデプロイスクリプト(bicep)は以下のGitHubレポジトリに公開済なので、そちらを参照してください。

https://github.com/katakura/azure-switchbot-monitor

SwitchBotとAzureサブスクリプション契約を持っている人はぜひ自身でデプロイして動作を確認することをお勧めします!

今回の目的と構成概要

えっと、Azureは長年やっていますが主にインフラ寄りが得意で、あまりアプリケーションの開発には携わっていません。

Azure Functions周りのインフラをbicepで作ってサクっとデプロイする事は出来ますが、動作確認レベルのアプリを作って動作させるのは正直苦手だったので克服します。

インフラ構成としては以下の感じです。

img
インフラ構成

仕事場にあるSwitchBot Hub miniと温湿度計は、スマホアプリの初期設定済みで、Alexa経由で外からも仕事場の温湿度が参照できる状態です。

Azure Functionsが中心となり、Timerトリガで定期的にSwitchBotの情報をLog Analyticsに格納する構成です。

特徴

以下に特徴を示します。

SwitchBot APIは最新の「v1.1」を利用

2022年9月にAPI v1.1が公開されました。

【API】新バージョンAPI v1.1を公開しました

巷の記事ではAPI v1.0を使った接続記事が多い中で、より高機能・高セキュリティであるAPI v1.1を使っています。

とはいえ、自分はPython初心者なので、以下の記事とサンプルソースを参考にさせて頂きました。

[Switchbot API v1.1が登場] APIでSwitchBotロックを遠隔操作する

Azure Monitor(Log Analytics)の新しい収集方法を利用

Azure Monitorは日々進化していますが、その中でもデータ収集の方法が大きく変わってきています。

今回のようなSwitchBotのテレメトリは、Log Analyticsでもカスタムログを使うのですが、「データ収集エンドポイント(Data Collection Endpoint)」「データ収集ルール(Data Collection Rule)」を使うことで、色々捗ります(雑な説明)。

Azure Monitor でのデータ収集

技術説明

前述の構成図を見ながらそれぞれについて説明します。

SwitchBot

SwitchBotハブミニを介さずに直接温湿度計の情報を取得するとかいったマニアックなことはせずに、素直にSwitchBotのSaaSをそのまま利用します。

前述した通り、API 1.1を使っています。API 1.0は今後新機能の追加は行われない他、セキュリティ的にも1.1のほうが優秀らしいので、どんどん新しいものを活用していきます。

APIの操作方法は基本的には公式のGitHubリポジトリに載っており、「Getting Started」に書かれている操作にてシークレットとトークンを先に控えておきます。

SwitchBot API v1.1

  1. App StoreまたはGoogle Play StoreでSwitchBotアプリをダウンロード
  2. SwitchBotのアカウント登録とアカウントへのログイン
  3. アプリ内でOpen Tokenを生成
    • Profile > Preferenceに移動
    • App Versionを10回タップ。開発者向けオプションが表示されます
    • 開発者向けオプションをタップ
    • トークンを取得をタップ
  4. SwitchBot OpenAPIを使いこなしましょう

Functionsアプリ

今回はPython 3.7ベースで作成しています。Log Analyticsへの認証と操作はAzure SDK for Pythonを利用しています。

Azure Monitor Ingestion client library for Pythonのuploadメソッドを使うことで、カスタムログに情報の登録が行えます。

認証はAzure Identity client library for Pythonにて良しなに認証してくれるので、ローカルデバッグもAzure上でのManaged Identity利用でもプログラムに手を加えなくて切り替えられるので便利ですね。

プログラム中では以下の感じでまるっとOKでした。

from azure.identity import DefaultAzureCredential

token_credential = DefaultAzureCredential()

カスタムログをLog Analyticsに送る際には以下の感じで。

import os
import azure.monitor.ingestion as azlog

log = azlog.LogsIngestionClient(os.environ['AZURE_MONITOR_ENDPOINT'], token_credential)
rule_id = os.environ['AZURE_MONITOR_IMMUTABLEID']
stream_name = os.environ['AZURE_MONITOR_STREAMNAME']

log_body = [
    {
        'TimeGenerated': '2022-12-07T00:50:02.007374Z',
        'deviceName': 'hoge',
        'deviceId': 'fuga',
        'body': {
            'humidity': 58,
            'temperature': 14.1
        }
    }
]

log.upload(rule_id=rule_id, stream_name=stream_name, logs=log_body)

AZURE_MONITOR_ENDPOINT, AZURE_MONITOR_IMMUTABLEID, AZURE_MONITOR_STREAMNAMEに設定する内容は後述します。

今回動かしたコードはGitHubの以下のリポジトリ内に公開しています。いかんせんPython初心者なので、エラー処理や配列ループ処理などがダメダメなので、PR歓迎します[1]

https://github.com/katakura/azure-switchbot-monitor/blob/20221207/SwitchbotMonitor/__init__.py

Log Analytics、データ収集エンドポイント、データ収集ルール

今までは、例えば仮想マシン上で動作するLog Analytics Agentは、直接Log AnalyticsのワークスペースIDと認証キーを使って各種ログを登録(追加?インジェスト?)していました。

カスタムログも一応対応していましたが、Log Analytics側の設定で「OS種別(Linux or Windows」「ログのパス」「ログのカラム情報」を管理していたため、仮想マシンの用途(提供サービス)が異なった場合でも同じログ情報しかLog Analyticsに送ることができませんでした。

他にもいろいろありますが、新しいAzure Monitorの仕組みでは、データ収集エンドポイント(DCE)、データ収集ルール(DCR)が登場して以下のようにカスタムログログの収集までの役割を分担する事になりました。

Log Analytics

  • カスタムログのスキーマを管理
  • テーブル名の末尾には「_CL」が必ず付与される
  • 今はAzureポータルからも新規カスタムテーブルの作成が可能

img
Azureポータルによるカスタムログ定義の例

bicepではこう書きます。

https://github.com/katakura/azure-switchbot-monitor/blob/20221207/template/deploy.bicep#L102-L129

データ収集エンドポイント(DCE)

  • ログを送り込むためのエンドポイント(URL)を準備
  • 指定するプロパティはそれほど多くなく最低限以下の感じ
    • エンドポイントを配置するリージョン
    • パブリックアクセスの許可・不許可
  • Pythonアプリの環境変数「AZURE_MONITOR_ENDPOINT」にはこちらのproperties.logsIngestion.endpointを設定します

これもAzureポータルから作成できますが、ARM若しくはBicepテンプレートで作ってしまうのが楽です。

bicepではこう書きます。

https://github.com/katakura/azure-switchbot-monitor/blob/20221207/template/deploy.bicep#L131-L140

データ収集ルール(DCR)

  • DCEを指定して送信元のエンドポイントを決める
  • 送信元から送られてくるカスタムログの形式を宣言する(今回はLog Analytics上のスキーマと同一にしている)
  • (必要ならば)ログ形式の変換ルールをKQLで記述する(ETL的な操作)
  • DCRリソースのIAMにRBACを付与して送信元のアクセス制限を行う
  • 送信先のLog Analytics及びカスタムテーブルを指定する
  • Puthonアプリの環境変数「AZURE_MONITOR_IMMUTABLEID」にはこちらのproperties.immutableIdを設定します。「AZURE_MONITOR_STREAMNAME」には「Custom-(テーブル名)」を設定します

カスタムログの定義周り含めて現状ではAzureポータルでは定義できません。

以下のチュートリアルでもPowerShellですが実際のリソース作成部分ではARMテンプレートを使っていますね。

チュートリアル: REST API (Resource Manager テンプレート) を使って Azure Monitor ログにデータを送信する

bicepではこう書きます。

https://github.com/katakura/azure-switchbot-monitor/blob/20221207/template/deploy.bicep#L142-L194

FunctionsからDCE→DCR→Log Analyticsにカスタムログを送るために、DCRのIAMにFunctionsのシステム割り当てマネージドID(System Assigned Managed Identity)を「監視メトリック発行者(Monitoring Metrics Publisher)」ロールで割り当てています。

bicepではこう書きます。

https://github.com/katakura/azure-switchbot-monitor/blob/20221207/template/deploy.bicep#L259-L272

ロールID「3913510d-42f4-4e42-8a64-420c390055eb」が該当ロールです。

Azure 組み込みロール

動作結果

本記事執筆中の仕事部屋の温度変換です。

朝7時前までは無人だったので10℃くらいまで下がった部屋が、エアコン投入でぬくぬくになったことがわかりますね。

img
室内温度の変化をLog Analyticsで確認

チナみにアレクサのスキルにSwitchBotを入れたおかげで、「アレクサ、エアコンつけて」の一言でスイッチが入るのは感動ものです。こりゃ便利。

おわりに

「なんでCosmosDBとかではなく、Log Analyticsに?」という意見もあるかと思います。

ただ単に、Azure Monitor周りにもっと詳しくなりたかったという事と、多分CosmosDBだったら他にもっと優秀な記事がたくさんあると考えて、わざわざ選択しました。

実用性は低いかと思いますが、Azure Monitorの新機能であるデータ収集エンドポイントと、データ収集ルールについて、少しは皆さんの理解が深まれば幸いです。

以前にも別記事でAzure Monitorについて軽く触れていますので、そちらも参照ください。

https://zenn.dev/yotan/articles/c6263f2217354e

以上です。

脚注
  1. 皆さんが知見を広めるだけではなく、皆さんが私を育てるのです ↩︎

Discussion