Netatmo APIを利用して二酸化炭素濃度を取得する

時節柄、人が集まった場合に換気を促すようにしようと思った。

そこで、現在使っている Netatmo Weather Station のCO2濃度の情報を基に、合成音声を出力することを試すことにした。

最初は、Raspberry Pi などの Linux を使おうかと思ったが、ESP32 でも必要なライブラリがあり、比較的容易にプログラムが作成できそうなので、スピーカーのついている M5Atom Echo で動作させることにした。

まずは、Netatmo のAPIを利用してCO2濃度を取得する部分を作成した。

機能的には単純なプログラムだが、JSONの処理に使った ArduinoJson のバッファサイズが不足していて、正常に動作せず、原因がわかるまでに時間がかかった。後で示すプログラム例では、4096にしているが、Netatmoのステーションに接続されているデバイスが多い場合には不足する可能性があるので、調整が必要である。

また、Netatmo の API では、access token を取得し、それを利用して観測データを取得するようになっている。access token には有効期限があることになり、refresh token を利用して、access token をリフレッシュすることになっている。

しかし、access token、refresh token はいつも同じで、リフレッシュをしても access token が変わらない。それで良いものなのか?

また、予想よりも Netatmoへの HTTP request がタイムアウトを含めた失敗率が高く、エラー時のリトライをそれなりにしないと、処理が進まなくなったりした。

備忘録として残しておく。

使用機材と環境

資料機材

Netatmo weather station

M5Atom Echo

開発環境

Visual Studio Code   1.51.1

PlatformIO IDE for VSCode      Core 5.0.3 Home 3.3.1

利用したライブラリの依存グラフ

プログラム

Netatmo Weather Station のCO2濃度の情報を取得する部分をまず実装した。

https://dev.netatmo.com/ に記載されている API を利用して、Netatmo から情報を取得する。https の post request によって、認証を行い、access token を取得する。

OAuth2を利用したインタフェースが用意されているが、M5Atomのようなブラウザを持たないデバイス向きのインタフェースがない。

しかたがないので、「This method should only be used for personal use and testing purpose. 」と書いてあるユーザ名とパスワードを指定する方法を使うことにした。

https でのアクセスのためには、WiFiClientSecureを利用した。 arduino-esp32 に含まれるサンプルプログラム BasicHttpsClient.ino を基にしてネットワーク部分を作成する。

request に対する response は JSON形式である。必要なデータを抽出するために ArduinoJson ライブラリを用いた。

netatmo-access.cpp

netatmo APIを利用して二酸化炭素濃度を取得するための関数を含んでいる。

String getAccessToken(WiFiClientSecure *client) は、access token を取得するための関数である。テストプログラムでは使っていない。
String   getRefreshToken(WiFiClientSecure *client) は、refresh token を取得するための関数である。
String   refreshAccessToken(WiFiClientSecure *client, String refreshToken) は、refresh token から access token を取得するための関数である。
int      getCO2value(WiFiClientSecure *client, String accessToken, String locationName) は、access token を使って、locationNameで指定されたデバイスの二酸化炭素濃度を取得するための関数である。JSONの処理のバッファの大きさを JSON_DOC_SIZE で指定している。対象のNetatmo weatherステーションに接続されている機器が多い場合には、例で指定している4096よりも大きくしなければならないかもしれない。
void     cleanupClient(WiFiClientSecure *client) は WiFiClientSecure の後始末をするための関数である。

m5atom-netatmo.cpp

m5atom-netatmo.cpp は、netatmo-access.cppで定義されている関数のテストプログラムである。二酸化炭素濃度を取得して、テキストとして出力する。10分おきに取得とテキスト出力を繰り返すようにしている。

テストプログラムでは access token のリフレッシュの確認を行うために、まず最初に 関数getRefreshTokenを使ってrefresh token を取得し、それを使用した関数 refreshAccessTokenによって (リフレッシュした)access token を取得している。

このような使い方の場合には、refresh token やリフレッシュは不要であり、関数 getAccessTokenによって最初から access token を取得すれば良い。

access token を使い、関数getCO2value によって、Netatmo weather station のデータを取得する。

関数 decrementFuse はエラー時に呼び出し、エラーの回数が INITIAL_RESET_FUSE を超えた場合には、システムをリセットし、プログラムを最初から実行する。

関数 restoreFuse は、エラーの回数をリセットする。

m5stack atom echo/lite の 1つの(最初の)LED を初期状態でBlue、正常動作中はGreen、エラー発生時はRed、待ち時間中はYellowになるようにしている。

netatmo-access.h

m5atom-netatmo.cppで定義している外部から利用する関数のプロトタイプ宣言を含んでいる。

mysettings.h

環境に依存する値などを設定するヘッダファイルである。このファイルに含まれるマクロには適切な値を環境に合わせて適切に行う必要がある。

MY_WIFI_SSID、MY_WIFI_PASSWORD には WiFiのSSID 、パスワードを設定する。

MY_NETATMO_CLIENT_ID と MY_NETATMO_CLIENT_SECRET には、dev.netatmo.com にログインして作成したAppの情報を設定する。例をこの後に示す。

MY_NETATMO_USERNAME、MY_NETATMO_PASSWORD には、netatmo に登録してあるユーザ名(メールアドレス)とパスワードを設定する。

MY_NETATMO_DEVICE_ID には、NetatmoのステーションのMACアドレスを指定する。取得方法は後に示す。NetatmoのMACアドレスは、70:ee:50で始まるはず。「:」を「%3A」に変換して指定する。下の例では??の部分に対象のステーションに合わせた16進数を設定すれば良いはず。

MY_TARGET_LOCATION には、二酸化炭素濃度を取得したいデバイス名を指定する。次の例では、「ダイニング」になっているが、環境に合わせて設定する必要がある。

dev.netatmo.com の My Apps に作成したAppの例

dev.netatmo.com のAPIを利用するためには、client id と client secret を取得する必要があり、そのためには、My Apps で App を作成する必要がある。

ここでは co2warning という App を作成した例を示す。MY_NETATMO_USERNAME、MY_NETATMO_CLIENT_ID、MY_NETATMO_CLIENT_SECRETに設定する値が示されているはずである。

Netatmo Weather Station の MACアドレスの取得

Netatmoのサイトにログインし、「設定」から「家を管理」を選択し、そこからステーションを選択する。

ステーションのモジュールを選択する。この例では「ダイニング」がステーションになっている。

最後の方にある MACアドレスの欄に記載の値がステーションのMACアドレスとなる。