Nature Remo のAPIを叩いて、室温をAzure FunctionsとCosmosDBで記録する


Nature Remoというスマートリモコンがあります。スマホのアプリやGoogle Homeなどから家電を操作できるもので去年くらいから愛用しています。このRemoにはセンサーが積んであり、温度、湿度、照度、人の動きをAPIから取得することができます(Remo miniは温度のみ)。今回、このAPIを叩きデータをためるところまでAzureのSaasを用いてクラウドだけで完結したいと思います。

クラウド上で完結させたかった理由

  • メンテナンスが必要ない
  • ほぼ無料で構築できる(ストレージアカウントに数円課金される)
  • 外出先でもデータが確認可能

ラズパイなどを使ったほうが構築は簡単かと思いましたが、家庭のネットワークが切れることもありますし、外から確認することも考えクラウドでやりました。

使うもの

  • Nature Remo / Remo mini
  • Remo API
  • Azure Functions(以下Functions)
  • Azure Consmos DB(以下CosomosDB)
  • Python 3系
  • VScode

事前準備

今回FunctionsをPythonで使うため、ポータル上でのコードの編集はできません。VVScodeからAzureへデプロイします。そこでVScodeと以下の拡張機能を用意します。

VScode 拡張機能

  • Azure Account
  • Azure Functions
  • Azure CLI Tools
  • Azure CosmosDB

Azure Functions Core Tool
https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-run-local?tabs=windows%2Ccsharp%2Cbash

VScodeでAzureにサインイン

上記の拡張機能をインストールしたら、VScode上でF1を押し、Azure: sign in をせんたくします。開いたブラウザ上でサインインするとVScodeでAzureのサインインができます。

Azureのリソースを準備する

CosmosDB

CosmosDBを作成します。これはポータル上から行っても、VScodeからデプロイしてもかまいません。
VScodeで作成する場合

  1. VScode上でF1を押し、CosmosDB:Create Account...を選択
  2. Account名に任意の名前を入力します。(グローバルに一意)
  3. CosomosDBのAPIをCore(SQL)と選択します。
  4. Apply Free Tier Discountをapplyとします。
  5. ほかの質問に順に回答してください。

CosmosDBは無料範囲があり、以下のFAQにあるように400RU/秒と5GBのストレージが無料で使えます。
https://azure.microsoft.com/pricing/details/cosmos-db/

Functions

Functionsは今回Pythonで構築するためVScodeから行います。

  1. VScodeでF1を押す。
  2. Functionsを検索しAzure Functions: Create New Projectをする。
  3. ローカルで開発するディレクトリを選択する
  4. Pythonを選び、ローカルにインストールしているPython本体の実行ファイルを選択します。
  5. Triggerを選択します。今回はTimerTriggerで行います。
  6. Functionの名前を入力します。
  7. TimerTriggerの実行頻度をCRON式で入力する。デフォルトの0 */5 * * * *は5分ごとの実行です。

これでローカルにプロジェクトと関数のテンプレートができました。

関数作り

まず普通にPythonでRemoのAPIを叩けることを確認します。以下の記事のPythonのコード用いました。アクセストークンを入手し、ローカルでAPIが叩けることを確認しましょう。この記事中でも注意されいているように、APIkeyを流出させないように気をつけましょう。API経由で家電が他人に操作し放題となります。
https://qiita.com/sohsatoh/items/b710ab3fa05e77ab2b0a

結果は以下のようなjsonが返ってきます。Remo miniを用いたのでnewest_eventにおいてteの項目で温度のみ出力されています。

[
    {
        "name": "Remomini",
        "id": <your remo id>,
        "created_at": "2019-07-21T13:01:54Z",
        "updated_at": "2020-04-29T05:18:05Z",
        "mac_address": <your remo mac address>,
        "serial_number": <your remo serial number>,
        "firmware_version": "Remo-mini/1.0.92-g86d241a",
        "temperature_offset": 0,
        "humidity_offset": 0,
        "users": [
            {
                "id": <your id>,
                "nickname": <your nickname>,
                "superuser": true
            }
        ],
        "newest_events": {
            "te": {
                "val": 23,
                "created_at": "2020-04-30T05:10:10Z"
            }
        }
    }
]

created_at がRemoを設定した日時、updated_at がRemoをアップデートした日時(自動でアップデートされる?)のようです。

今回知りたいのはnewest_eventなので、その中身とAPIを叩いた時間をCosmosDBに送ります。newest_eventsはセンサーの値が変化した際に更新される仕様のようなので、このcreated_atはAPIを叩いた時間とは異なります。

このコードをtimetriggerのテンプレートコードに載せていきます。

__init__.py
import datetime
import logging
import json
import requests
import azure.functions as func


def main(mytimer: func.TimerRequest, doc: func.Out[func.Document]) -> func.HttpResponse:
    utc_timestamp = datetime.datetime.utcnow().replace(
        tzinfo=datetime.timezone.utc).isoformat()

    if mytimer.past_due:
        logging.info('The timer is past due!')

    apikey= "<your remo API key>"
    # get JSON
    headers = {
        'accept' : 'application/json',
        'Authorization' : 'Bearer ' + apikey ,
    }
    response = requests.get('https://api.nature.global/1/devices', headers= headers, verify=False)
    rjson = response.json()
    res_json = rjson[0]["newest_events"]["te"]
    res_json["request_time"]= utc_timestamp
    res_json = json.dumps(res_json,indent=2)
    logging.info('Python timer trigger function ran at %s', utc_timestamp)
    doc.set(func.Document.from_json(res_json))

mytimer: func.TimerRequestはazure.functionsのモジュールからのタイマー
doc: func.Out[func.Document]はazure.functionsの出力を意味しています。

今設定したdocという変数に値をセットすることで出力することができます。docという変数は関数作成時に生成されたfunction.jsonにCosmosDBへ送る値だということを記述します。

関数アプリの設定

  1. F1キーでコマンドターミナルを出し、bindingと入力し、Azure Functions: Add bindingを選択します。(サイドバーのAzureロゴからローカルの先ほど作成した関数を右クリックすることでもできます。)
  2. 先ほど作成した関数を選択します。
  3. 今回は出力なのでoutを選択します。
  4. Azure CosmosDBを選択します。
  5. 関数の中で用いる変数名を入力します。今回はdocとします。
  6. CosmosDB内のデータベース名を入力します。今回はhomeとします。
  7. データベース内のcollection名を入力します。今回はtemperatureにします。
  8. DBが存在しない場合に作成するかについて、trueとします。
  9. ローカル環境の設定について聞かれるのでCreate new local app settingで作成します。
  10. データベースのアカウントを聞かれるので、作成したhomeを選択します。
  11. Partitionkeyは任意なのでスルーします。

! Database名はグローバルに一意でないといけないため、任意の名前としてください

これでfunction.jsonに以下の内容が追加されます。

    {
      "type": "cosmosDB",
      "direction": "out",
      "name": "doc",
      "databaseName": "home",
      "collectionName": "temperature",
      "createIfNotExists": "true",
      "connectionStringSetting": "cielohome_DOCUMENTDB"
    }

これで出力の設定ができました。なおCosmosDBのconnectionStringは同ディレクトリのlocal.settings.jsonに記載されています。

"cielohome_DOCUMENTDB": "AccountEndpoint=https://hogehoge.documents.azure.com:443/;AccountKey=fugafuga;"

ローカルでテスト

ローカルでテストするために、必要なモジュールを入手します。今回は必要なモジュールはazure-functions, requestsなので同ディレクトリのrequirements.txtに記載します。

azure-functions
requests

これをpip install requirements.txtで入手します。

F5キーを押すとデバッグできます。

Functionsにデプロイする

  1. F1キーでコマンドターミナルを出し、deployと検索し、Azure Functions: deploy to function app ....を選択する。
  2. Create new Function App in Azure (Advanced)を選択
  3. 任意のリソース名を入力する。(グローバルに一意の名前)
  4. Python 3.7を選択する。
  5. Coonsumptionを選択する。従量課金です。Functionsも無料枠があるため5分に一回程度であれば基本的に課金されません。
  6. リソースグループ選択する。CosmosDBと同じリソースグループとします。違うものでも大丈夫です。リソースグループがLinuxで作っていないとPythonのアプリが動かないので注意する。
  7. storage accountを選択します。
  8. Application insightsを選択します。ログを見たりするSaasです。

これでデプロイが完了しています。

CosmosDBでデータを確認する

関数のデプロイができたら、データを見てみましょう。
VScode上からAzureのロゴをクリックしてサイドバーのCosmosDBを確認します。データベースを開くとtemperatureにドキュメントとしてできています。

  "val": 24.2,
  "created_at": "2020-05-02T13:49:12Z",
  "request_time": "2020-05-02T14:00:00.007771+00:00"

これで完成です。

まとめ

これでAzureでFunctionsとCosmosDBを用いてデータを格納することができました。次回はこのデータを可視化してみたいと思います。

参考

https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-integrate-store-unstructured-data-cosmosdb?tabs=javascript
https://docs.microsoft.com/ja-jp/azure/azure-functions/
https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-reference-python
Nature スマートリモコン Nature Remo mini 家電コントロール Amazon Alexa / Google Home / Siri 対応 GPS連携 温度センサー Remo-2W1

おまけ

MicrosoftのPowerBI Desktopというソフトがあるので、それで簡単に簡単に可視化してみるとこんな感じでした。Azureとの連携が簡単なので楽でいいですね。