室温・湿度モニタIoTのラピッドプロトタイピング(死活監視機能も追加)

在宅勤務が増加すると、勤務先の状況が気になります。そこで室温と湿度を計測、記録をインターネット上で記録するIoTをラピッドプロトタイピングしてみました。

装置はM5StickCとgrove接続の湿度センサー(DHT11)です。Amazonで入手しました。

記録側はGoogle Apps Scriptを用いることにしました。Spreadsheetに1行ずつ、計測データを追記していきます。

function doPost(ee) {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
  var values = JSON.parse(ee.postData.getDataAsString());
  sheet.appendRow([new Date(), values.humi, values.temp]);
}

データ用のスプレッドシートを作成し、ツール→スクリプトエディタで、上記のようなコードを記入します。

その後、公開→Webアプリケーションとして導入し、そのURLをメモします。

M5StickC側のプログラムは以下のようなものになります。DHT11用のAdafruit社のライブラリをあらかじめインストールしてください。

#include <M5StickC.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <Wire.h>
#include "DHT.h"
 
#define DHTPIN 33
#define DHTTYPE DHT11

const char* ssid = "!!! input WiFi SSID Name !!!";
const char* password = "!!! input WiFi Password !!!";
const char* published_url = "!!! input Google Spreadsheet scripts web application URL !!!";

DHT dht(DHTPIN, DHTTYPE);
 
void setup() {
  M5.begin();

  M5.Lcd.setRotation(3);
  M5.Lcd.print("wifi connect...");

  WiFi.mode(WIFI_STA);
  WiFi.disconnect(true);
  delay(1000);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(100);
    Serial.print(".");
  }
    
  Serial.println("DHT11 init...");
  dht.begin();
  
  delay(1000);
}

void loop() {
  M5.update();
  
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  if (isnan(h) || isnan(t)) {
      Serial.println(F("Failed to read from DHT sensor!"));
  } else {
    Serial.print(h);
    Serial.print("" );
    Serial.println(t);
  
    M5.Lcd.setCursor(0, 0);
    M5.Lcd.print("humi : ");
    M5.Lcd.print(h);
    M5.Lcd.print(" temp : ");
    M5.Lcd.println(t);
  
    char json[64];
    sprintf(json, "{\"humi\": \"%f\" , \"temp\": \"%f\" }", h, t);
  
    HTTPClient http;
  
    http.begin(published_url);
    int httpCode = http.POST(json);
    if (httpCode > 0) {
      if (httpCode == HTTP_CODE_OK) {
        String payload = http.getString();
        Serial.println(payload);
      }
    } else {
      Serial.println("http fail");
    }
   
    http.end();
  }
  
  delay(60000);
}

この例では1分ごとに計測値を送信しています。末尾のdelayの引数(ms)がそれを決めています。通常は室温や湿度はそんなに急激に変化しないので、もっと長めでもよいと思います。

Google Apps Scriptで更に定期的にデータをチェックすれば死活監視もできますね、としましたが、死活監視も作成しました(2020/05/06)。

var PROPERTY_NAME = "humi_rec_locationname_prevResult";

function healthCheck() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
  var lastRow = sheet.getLastRow();
  var lastDate = sheet.getRange(lastRow, 1).getValue();
  var diffDateMinutes = ((new Date()).getTime() - lastDate.getTime()) / (1000 * 60);
  
  var properties = PropertiesService.getScriptProperties();
  var prevResult = properties.getProperty(PROPERTY_NAME);
  if (prevResult == null) {
    prevResult = "success";
  }
  if (diffDateMinutes > 60) {
    if (prevResult == "success") {
      const recipient = '送信先メールアドレス';
      const subject = 'Is your Humi IoT device stopped?';
      const body = 'Plase check your Humi IoT device. There has been no communication since then for over 60 minutes.';
      
      GmailApp.sendEmail(recipient, subject, body);
      properties.setProperty(PROPERTY_NAME, "fail");
      console.log("success to fail : send mail");
    } else {
      console.log("fail to fail : nothing");
    }
  } else {
    properties.setProperty(PROPERTY_NAME, "success");
    if (prevResult == "success") {
      console.log("success to success : nothing");
    } else {
      console.log("fail to success : nothing");
    }
  }
}

先のdoPost関数の後に上を書きます。この例では成功→失敗時にメールで通知するようにしています。失敗するたびに送信すると大量のメールが届いてたいへんなことになるので、プロパティを用いて前回のチェック結果を参照しています。

その上で、一度動作試験をしてください。メール送信のための権限が増えるのでそのチェックが入ります。途絶えた場合の処理を検証するには時間差を求めている行で+100などして実行してください(戻すことを忘れないように)。

次に「編集」→「現在のプロジェクトのトリガー」をクリックし、「トリガーを追加」します。作成した「healthCheck」関数を、時間主導型、分ベース、30分おき、今すぐ通知を受け付ける、あたりに設定します。

埃から防ぐためのケースはM5StickCの入っていたケースをそのまま再利用しました。あまり発熱はしないと思いますが、室温・気温が適切に計測できるようにするため、空気の流れを確保できるように両側に穴を開けました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です