#はじめに
『Azure IoT Centralに対応できないIoTデバイスをAzure Functionsを中継して対応させる』
という記事をみて、「こういったことも出来るんだぁ~」と思いながら、
以下の記事に纏めたものを作っているときに、外気の影響はどうなんだろうと思ったのがこの記事でやってみたことのキッカケです。
『洗濯物の乾き具合を知りたくて、M5StickCで物干し部屋の湿度を測って Azure IoT Central で分かるようにしてみた』
前は、同じデバイスをもう1台用意して、家の外に取り付ければできるなぁ~と漠然と考えていたのですが、電源や防水などを考えると少し手間だなぁと感じていて、結局何もやらずにいました。そして、そのときに見つけたのが冒頭の記事になります。こういったことが出来るのならば、WebAPIから取得してきたデータも Azure IoT Central に対応させられるのではないかと!
#やってみたこと
- OpenWeatherMap から Azure Functions を使ってデータを取得し、Azure IoT Central にアップロード
- M5StickC を使ったデバイステンプレートを流用し、あたかも外気を取得しているようなデバイスを作成
- ダッシュボードのグラフ上で、リアルデータと OpenWeatherMap のデータを比較
システム構成
このような感じでリアルデバイスのデータだけでなく、WebAPI経由で取得したデータも Azure IoT Central にアップロードしていきます。
ダッシュボードのイメージ
実線データ:M5StickC+温湿度センサ
破線データ:OpenWeatherMapから取得したデータ
※オフセットしているように見えますが、なんとなく相関はありそうです
#大まかな手順
- リアルデバイスの M5StickC と Azure IoT Central を連携
- OpenWeatherMap と Azure IoT Central を連携
- Azure IoT Central 上で同一のグラフで可視化
『Azure IoT Centralに対応できないIoTデバイスをAzure Functionsを中継して対応させる』
こちらの記事がとても参考になるので、OpenWeatherMap と Azure IoT Central を連携される場合はこちらを読むことをお勧めします。
#1. M5StickC と Azure IoT Central の連携
こちらの記事を参考にして下さい。
- M5StickCとAzure IoT Centralを連携してデータを可視化する① ~M5StickC開発環境準備編~
- M5StickCとAzure IoT Centralを連携してデータを可視化する② ~Azure IoT Central環境構築編~
- M5StickCとAzure IoT Centralを連携してデータを可視化する③ ~M5StickCとAzure IoT Central接続編~
#2. OpenWeatherMap と Azure IoT Central の連携
システムとしては、「Azure Functions → Azure IoT Central」 への接続となります。
Azure Functions上で、OpenWeatherMapへのアクセスとAzure IoT Central の接続を行います
必要なライブラリ
今回は、Azure Functions 上のコードは Node.js を使用します。
・got
・azure-iot-provisioning-device-http
・azure-iot-device-http
・azure-iot-security-symmetric-key
ソースコード
処理としては、以下の流れになります。
- OpenWeatherMapAPIで、天気情報を取得
- Azure IoT Central にデータ送信
// Copyright 2021 (c) Yuki Matsuda. All rights reserved.
// Licensed under the MIT license.
//
// Copyright 2021 (c) Kohei "Max" MATSUSHITA. All rights reserved.
// Licensed under the MIT license.
// Based on https://github.com/Azure/azure-iot-sdk-node/blob/master/provisioning/device/samples/register_symkey.js
// OpenWeatherMap
const got = require('got');
const OPENWEATHER_APP_ID = ''; // 個人で別途用意
const CITY = 'Kanazawa-shi,jp' // 必要に応じて変更
// DPS parameters from IoTC
const deviceId = ''; // Device ID
const idScope = ''; // ID Scope
const symmetricKey = ''; // SAS Token
// Libs and Param for DPS
const ProvisioningHost = 'global.azure-devices-provisioning.net';
const SymmetricKeySecurityClient = require('azure-iot-security-symmetric-key').SymmetricKeySecurityClient;
const ProvisioningDeviceClient = require('azure-iot-provisioning-device').ProvisioningDeviceClient;
const ProvisioningTransport = require('azure-iot-provisioning-device-http').Http;
// Libs for using IoT Hub
const Client = require('azure-iot-device').Client;
const Message = require('azure-iot-device').Message;
const IotHubTransport = require('azure-iot-device-http').Http;
module.exports = async function (context, myTimer) {
// OpenWeatherMap API
var URL = 'http://api.openweathermap.org/data/2.5/weather?q=' + CITY + '&units=metric' + '&appid=' + OPENWEATHER_APP_ID;
context.log('openweathermapURL : ' + URL);
const response = await got.post(URL, {json: true});
context.log(response.body);
var temp01 = JSON.parse(response.body);
var temperature = temp01.main.temp;
var humidity = temp01.main.humidity;
var pressure = temp01.main.pressure;
// Your telemetry payload
var telemetryPayload = '{temperature:' + temperature + ', humidity:' + humidity + ', pressure:' + pressure + '}';
// Get connection information via DPS (No changes required)
const provisioningSecurityClient = await new SymmetricKeySecurityClient(deviceId, symmetricKey);
const provisioningClient = await ProvisioningDeviceClient.create(ProvisioningHost, idScope, new ProvisioningTransport(), provisioningSecurityClient);
const result = await provisioningClient.register();
// Connect and Send to IoT Hub using DPS information (No changes required)
const connectionString = `HostName=${result.assignedHub};DeviceId=${result.deviceId};SharedAccessKey=${symmetricKey}`;
const iotHub = await Client.fromConnectionString(connectionString, IotHubTransport);
await iotHub.open();
const msg = await new Message(telemetryPayload);
const res = await iotHub.sendEvent(msg);
context.res = {status: 204};
}
telemetryPayload で渡すJSONパラメータは、Azure IoT Central のデバイステンプレートで設定した名前を同じにして下さい。
#3. Azure IoT Central 上で同一のグラフで可視化
以前の こちらの記事 で作成した物干し部屋のデータにプロットしています。
同じデバイステンプレートを使用することで、同じグラフ上で表示することが出来るので、比較がしやすくなります。右下の図で、破線っぽいデータが OpenWeatherMap から取得した外気の湿度になります。
OpenWeatherMapAPI のアクセス頻度を高くし過ぎると、OpenWeatherMap の無償枠の上限や Azure Functions の料金が気になるので、今回は10分に1回程度の頻度で取得しています。おそらく、そのせいで破線っぽくなっているかと思います。
実際のデバイスとOpenWeatherMapのデータがオフセットしているように見えますが、そこは何かあるんでしょう(笑) とりあえず、ある程度の相関はありそうです。
湿度・温度・気圧をそれぞれプロットしたものが、こちらになります。
グラフの始まりが、除湿機が止まった後からになりますが、それでもなんとなく相関が見えてきます。
#まとめ
Azure IoT Central に対応していなデバイスももちろんですが、サービスから取得したデータも Azure IoT Central と連携することが出来ました。純粋なデバイス管理という観点だと、WebAPIから取ってきたデータはデバイスではないよねと思いますが、ある場所に設置したデバイスがそれなりに正常に動作していることを確認するという観点ではこういった使い方もあるのかなと個人的に感じています。
あとは、M5StickCで取得しているセンサ値と外気との差分ですが、物干し部屋とはいえ肌感的にそれほど差分があるとは思いません。なので、もう少し真面目に見ようと思うなら、校正されてる温湿度計などで一度測ってみれば差分の原因もスッキリしますが、いまのところは、洗濯物が生乾きにならないような目安になればいいので、一旦は、ここまでで。(もし、測ってみたら記事に追記します)
おまけ
本記事は、以下のキャンペーンに参加しています。