GASで作ったAPIにM5StackからPOSTする方法
M5Stack君の仕事を減らしてあげよう
前回まででできたシステム
前回まででできたシステムの概略図を描いてみました。
今後機能を拡張していくことを考えると、この構成だと若干扱いづらい点があります。
それは、M5Stack君にとって通信相手が二人いることです(よくエンジニア業界ではモノやサービスを擬人化したりするので敬称をつけてみました笑)。
もちろん、通信相手が二人いたとしても動作としては問題はないのですが、今後3つ目、4つ目と通信相手が増えていったときに、M5Stack君を毎回アップデートしていかなければなりません。
M5Stack君は今一人しかいませんが、今後複数のM5Stack君を用意して各部屋に設置した場合、通信相手を増やすたびに全M5Stack君のファームウェアをアップデートする必要が出てきます。
これでは結構面倒くさいですよね…
ということで、M5Stack君の仕事量を減らしてあげたいと思います!(よっ、有能管理職!)
目指すシステム
今回の記事で目指すシステムはこちらのようになります。
M5Stack君はGAS(Google Apps Script)先輩にCO2濃度(と温度)をひたすら投げ続けます。
GAS先輩は受け取ったデータを、決められた手順に従って各通信相手に転送します。
こうすることで、M5Stack君はデータをGAS先輩に送信するという作業に集中できるようになります。
よって、今後通信相手を増やしたとしてもGAS先輩の仕事になりますので、M5Stack君のアップデートは不要!
GAS先輩コード一つ書き換えれば、システム全体に反映することができるようになります!
GASプロジェクトをWebアプリとしてデプロイする
GASのプロジェクト作成方法は以下の記事で紹介していますので、その手順に従ってプロジェクトを作成しておきましょう。
POST用のAPIを作成する
POST用のAPIを立てるのはめちゃめちゃ簡単です。
「エディタ」画面に行き、「doPost」という関数を作成します。これはM5Stackからデータを飛ばす際に使用するAPIとなります。
ちなみに、GASはJavaScriptをベースとしています。
function doPost(e) {
const body = JSON.parse(e.postData.contents);
const co2 = body.co2;
const temp = body.temp;
console.log(`CO2濃度: ${co2}ppm`);
console.log(`温度:${temp}℃`);
}
デプロイする(本番環境に反映する)
「デプロイ」ボタンを押し、「新しいデプロイ」を選択します。
デプロイタイプは「ウェブアプリ」とします。
説明文を適当に入力、「次のユーザーとして実行」は「自分」、「アクセスできるユーザー」は「全員」とします。
「デプロイ」ボタンを押します。
ウェブアプリのURLが表示されるので必ず「コピー」しておきましょう。
これでAPIが公開されました!
今回はAPIキーなど何もかけていないのでリンクを知っている人であればだれでもアクセスできるようになっています。むやみにURLは公開しないようにしましょう!
ちなみに、2回目以降のデプロイの場合は少し手順が異なります。以下の記事を参照ください。
M5StackからPOSTしてみる
今回は「ArduinoJson.h」というライブラリを追加します。
今回のプログラムのポイントは下記です。これまでのLINE NotifyやAmbientにデータを送る部分はGAS側に移行するため削除してあります。
- 「GAS_API_URL」という変数にコピーしておいたAPIのURLを設定する
- 「post_co2」という関数を作る
- CO2濃度を測定した直後に「post_co2」を実行する
#include <M5Stack.h>
#include <MHZ19_uart.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#define ARDUINO_ARCH_ESP32
#define PERIOD 60
#define THPPM 1000
WiFiClient client;
const char* ssid = "WiFiのSSID";
const char* password = "WiFiのパスワード";
const char* GAS_API_URL = "GASのAPI URLを入力(デプロイ時に表示されたもの)";
const int rx_pin = 16; //Serial rx pin no
const int tx_pin = 17; //Serial tx pin no
MHZ19_uart mhz19;
/*----------------------------------------------------------
MH-Z19 CO2 sensor setup
----------------------------------------------------------*/
void setup() {
M5.begin();
delay(100);
Serial.println("Hello");
mhz19.begin(rx_pin, tx_pin);
mhz19.setAutoCalibration(false);
int i = 500;
WiFi.begin(ssid, password); // Wi-Fi APに接続
while (WiFi.status() != WL_CONNECTED) { // Wi-Fi AP接続待ち
M5.Lcd.setTextSize(3);
M5.Lcd.setCursor(20,120);
M5.Lcd.printf("Connecting...");
i--;
if(i<0){
delay(250);
M5.Power.reset();
}
}
M5.Lcd.setTextSize(3);
M5.Lcd.setCursor(20,120);
M5.Lcd.printf("Connected!\n");
M5.Lcd.clear();
M5.Lcd.setBrightness(50);
}
/*----------------------------------------------------------
MH-Z19 CO2 sensor loop
----------------------------------------------------------*/
void loop() {
unsigned long startt = millis(); // loopの開始時刻を記録
int co2ppm = mhz19.getPPM();
int temp = mhz19.getTemperature();
Serial.print("co2: "); Serial.println(co2ppm);
Serial.print("temp: "); Serial.println(temp);
M5.Lcd.clear();
M5.Lcd.setTextSize(10);
M5.Lcd.setCursor(20,120);
M5.Lcd.printf("%dppm\n", (int)co2ppm);
M5.Lcd.setTextSize(2);
M5.Lcd.setCursor(20,0);
M5.Lcd.printf("RSSI:%d dBm", WiFi.RSSI());
post_co2(String(co2ppm), String(temp));
delay(PERIOD*1000);
wifi_lan_check();
}
/*
* GASにPOSTする
*
*/
void post_co2(String co2, String temp) {
StaticJsonDocument<200> doc;
doc["co2"] = co2;
doc["temp"] = temp;
char json_string[255];
serializeJson(doc, json_string, sizeof(json_string));
Serial.printf(json_string);
HTTPClient http;
http.begin(GAS_API_URL);
http.addHeader("Content-Type", "application/json");
int status_code = http.POST((uint8_t *)json_string, strlen(json_string));
if (status_code == 200) {
Serial.printf("[POST] end to server");
} else {
Serial.printf("[POST]failed to send to server");
}
}
/*
* void wifi_lan_check()
* WiFi Lan の監視をします。
* WiFi.status() で判断するよりも、ping で応答をチェックした方が、早いかも。
*/
void wifi_lan_check(){
int i;
if(WiFi.status() != WL_CONNECTED){
M5.Lcd.clear();
M5.Lcd.setTextSize(3);
M5.Lcd.setCursor(20,120);
M5.Lcd.printf("Connecting...");
WiFi.disconnect();
delay(50);
WiFi.begin(ssid, password);
i=50;
while (WiFi.status() != WL_CONNECTED) {
delay(250);
i--;
if(i<0){
delay(250);
M5.Power.reset();
}
}
}
}
動作確認
M5Stackに書き込んで、GCPのログを見てみましょう。
GCPのロギングページにアクセスします。
ログエクスプローラという画面が開くので確認します
CO2と温度が受信できています!やったね!
これでGAS側でデータを受け取ることができることを確認できました!
このデータを受信できていれば、「1000ppmを超えていたらLINE Notifyに通知」したり、「Ambientにデータを転送」したりすることも自由にできるので、次回はそのあたりをやっていきます!
まとめ
GASからLINE NotifyやAmbientにデータを飛ばす部分は次回にしようと思います。
今回のまとめ