UIFlowを使ってM5StackからGoogleのスプレッドシートに環境センサーのデータを送る

この資料は2024/6/17開催の高校生向けハンズオンの資料です。
今回はM5StackからGoogleのスプレッドシートに環境センサーのデータを送信します

# 使うもの
* M5Core2
* ENV.Ⅲ Sensor
* Chromebook
* Google スプレッドシート
* Google Apps Script
* UIFlow1.0

※本来は新しいUIFlow2.0を使用するほうが良いですが、2.0はデバイス認証のためアカウント登録が必要で、ファームウェア書き込み時のアカウントと一致している必要があるため、今回のハンズオンのように不特定のユーザ、かつ2人で1台を共有する場合などの状況とは相性が悪いため今回は1.0を使用します

# 前提
M5Stackはファームウェアを書き換えて画面にAPI KEYが表示されてる状態としておきます。
余談ですが、ファームウェアの書き換えについてはこちらの資料を見てください。

https://qiita.com/t-sho/items/338c1447f6c8b2b6d801

# UIFlowにアクセスする
下記のリンクテキストからUIFlowにアクセスしてください。

https://flow.m5stack.com/

# 初期設定
この画面は左のUIFlow1.0を選択して、右下のConfirmボタンをクリックしてください。
※選択してる方は左上が緑色になってるのでそれで判断してください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/cdad51f8-c6c5-12ac-eda4-93a748f02b45.png)

Welcomeのメッセージが出たらSkipをクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/1eaa7cee-810c-2719-9cdf-603e686f854d.png)

画面構成はこんな感じです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/84d26fc1-79e2-b23f-bf7b-cc000da74f94.png)

画面左下のAPI Keyをクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/f75b4ecb-b069-1c35-e5ef-f3c2285fe45b.png)

Settingの画面が起動するので以下のように入力し、OKボタンをクリックします

* Api key：M5Core2の画面に表示してある8桁の文字を入力してください
    * 16進数なので、数字の0～9とアルファベットA～Fまでしか登場しませんので注意してください
* Server：Japanのもの
* Language：日本語
* Device：Core2

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/d76c7699-4ab9-c883-cb67-690359a898d9.png)

OKボタンをクリックしてSetting画面が閉じた後、画面左下の表示が「接続済み」になっていれば成功です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/ca7a4550-d1bd-9a6f-5075-45dcebf2d3ba.png)

# M5Core2本体に環境センサーを接続する
本体側面のこの赤色のポートにGroveコネクタの4色ケーブルを接続します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/b10f0a39-527f-6c89-7d21-0e12019555c3.png)

環境センサーと接続したらこんな感じです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/c904bd73-5555-e731-e2ec-99fad0f4483e.png)

### 【補足】
本体側面の赤色のGroveポートはポートAと呼ばれ、I2Cという通信方式を使ってデータをやり取りするためのものです。
拡張パーツを使えばポートB(黒色)やC(水色)といったI2C以外の通信方式のポートを使うことが可能になります。
接続するセンサーによって通信方式が異なるため、ポートAを使用するタイプのセンサーはポートAに接続する必要があります。

センサー側のポートにも色がついてるため、迷った場合はこの色で判別してもだ丈夫です。
例えば、今回使用する環境センサーは赤色なので、ポートAに繋げばよいということがわかります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/12198e5a-dc87-abe8-4734-7983a2c49fcd.png)

変換して使う術もなくはないですが、今回のメインからは逸れてしまうため割愛します
# M5本体に環境データを表示する
## ラベルを配置する
画面左上のLabelをドラッグ&ドロップで画面に配置します。
Fontは日本語が表示できるようUnicode24を選択します（24はおそらく表示する文字の大きさです）
![Animation000009.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/c59f1b72-c652-0cdf-615e-2d410dcc440c.gif)


同様の手順でラベルを6個配置します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/c28753cb-6164-5973-c208-3ad73bc34300.png)

## ラベルの初期化を行う
コードブロックの中からラベルの表示に関するブロックを使用して初期化を行います
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/7d206f9d-9ae4-a1db-e7f5-d9fd6d59b232.png)

下記のようにブロックをSetupブロックの下に連結する形で配置します
このsetupより下に配置したブロックはプログラム実行時に１度だけ実行されます。
![Animation000010.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/36be2688-dd48-8bb0-f922-c4c46d2f630d.gif)

同じようにラベル6個分配置します。(ctrlキー＋Cとctrlキー+Vでコピペして配置してもOK）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/677243a8-c804-0dcb-b4ff-812ad023bc4f.png)

全てlabel0になってるので、画面に配置した通りlabel0～label5までの6個のラベルの設定に変えます
![Animation000011.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/cbe0039a-09f4-8bce-d1b6-6051080107bd.gif)

ラベルに表示すする値が全て「Hello M5」になってるので、下記のように変更する

| label | 値 |
| ---- | ---- |
|label0|温度(℃):|
|label1|湿度(%):|
|label2|気圧(hPa):|
|label3|0|
|label4|0|
label5|0|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/82e344a4-d3cb-a314-a60d-908fbd4a8f3b.png)

## 変数を作成して初期化する
環境センサーから取得した値を代入するために変数を定義します
変数のグループから変数の作成をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/7261ae53-d7b6-b964-3d84-1b712f03a532.png)

以下の3つの変数を作成します
|変数名|用途|
|--|--|
|tmp|温度データを代入する|
|hum|湿度データを代入する|
|atm|気圧データを代入する|

順番に作成するため、まずは温度用にtmpと入力し、OKをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/2e678ea5-813d-fff8-b2fe-f5ecdb981ad4.png)

作成後は同様の手順で3つの変数を作成します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/72a73bc9-6af9-9149-518b-2c6a2b52eb7a.png)

作成した変数を初期さするためブロックを配置します
配置後、ドロップダウンの中を選択し、tmp、hum、atmがそれぞれ１つずつ表示されてる状態にしてください
![Animation000012.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/f2b98b48-6665-9c7a-f823-c2b2d99b0d5c.gif)

変数の初期として0をセットします
![Animation000013.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/0b868e69-5390-2229-059b-903ff103b64c.gif)

これでsetupの処理はひとまず完成です。

## 繰り返しブロックを配置する
イベントの中から「ずっと」というブロックを選択して配置します
※基本的にはこのブロックの中身がプロフラム終了まで繰り返し実行されます
![Animation000014.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/e7a17766-0889-aaf7-dcd7-0083cd692fc5.gif)

## ユニット(環境センサー)を追加する
画面レイアウトの下の「＋」から環境センサーを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/f125a129-d0ff-8bb5-9b00-fd3db2f9a708.png)

今回のハンズオンで使用する環境センサーは下記の物ですが、種類が混ざっていますので注意してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/be961cec-4ab7-1c49-0d03-1d45d6be3b9c.png)
センサーに書かれているものと同じものを選択してください。
例えば下記の写真のセンサーだと、
* 左のセンサーは、ユニット一覧の一番左の「ENV」です
* 右のセンサーは、ユニット一覧の左から３番目にある「ENV Ⅲ」です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/d58e23cf-14fe-476f-3f93-45505644eba4.png)

実際にユニットを追加して見ましょう
※この資料はENVⅢをベースに進めますが、他の物でも基本的には同じです
![Animation000015.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/3e926b47-7bec-b30d-e04d-d5715fa056f2.gif)

## 変数にセンサーから取得したデータを代入する
tmp、hum、atmの変数ブロックを「ずっと」ブロックの中に追加します
![Animation000017.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/212592ac-1eef-2feb-b447-85a88f5ba2fa.gif)

追加したユニットから環境センサーのブロックを追加すします
変数とブロックの組み合わせは下記の通りです。

|変数|ブロック|
|--|--|
|tmp|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/bddd89f5-7f1b-8a8c-003c-58563990e8fd.png)|
|hum|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/9468cd21-25a8-d8f3-9e0a-9e0ece4427be.png)|
|atm|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/7fa0cb9f-61c6-2c09-b5f1-c08612551f5f.png)|

では、実際に追加して見ましょう
![Animation000018.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/d6023a5f-8250-0fec-a17e-b63ce7e6b654.gif)

## 変数の値をラベルに表示する
ラベルのブロックを追加します
![Animation000019.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/4dbd33a8-ae56-e6c5-30e3-dd143bd6cf6a.gif)

ラベルの値に変数を代入します
![Animation000020.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/4878c881-6fea-22be-c0cd-6ab4c1cf951e.gif)

setupから順にこうなっていればOKです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/dfb8c095-d3df-1ee9-070d-5835a039fc46.png)

## プログラムを実行する
画面右下のRUNボタンをクリックして実行してみます
デバイスは順番に譲り合って試してください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/7ada03d6-9ea9-9606-b51c-3a15dae48adf.png)

M5の画面に環境データが表示されたら成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/12e50f41-03f6-ec59-6471-0dc5c8de1e22.png)
　
ここまで出来たら、次はM5本体から送信された環境データをGoogleのスプレッドシートにデータを送ってみましょう　
# M5から受信した環境データをGoogleのスプレッドシートに書き込むプログラムを作成する  
まずは受信側の処理を作ります（送信側の処理は後から）

## Googleのスプレッドシートを新規に作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/e5e22983-cbad-98a6-bc1b-84dd1550d39f.png)

A～E列に下記のように項目タイトルを設定します
※ファイル名は何でもいいのでつけておいてください
※シート名は初期値のままにします
|列|値|
|--|--|
|A|受信日時|
|B|受信データ|
|C|温度|
|D|湿度|
|E|気圧|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/2ca6c50e-6a02-8b56-338c-df3563ca2ce7.png)

## Apps Scriptでプログラムを作る
ここでは、M5から送信されたデータを受信し、スプレッドシートに書き込むプログラムを作成します。
メニューの中の拡張機能をクリックし、Apps Scriptをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/7f52b553-4541-53a5-9839-ac6611b05e2b.png)

下記のプログラムを書き込む

``` js
function doPost(e) {
  console.log('catch post')
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1');  // 操作する対象のシートを指定
  var params = JSON.parse(e.postData.getDataAsString());                       // 受信したデータをJSON形式で分解して変数に代入
  var temp = params.tmp;                                                       // 温度の値を取得
  var hum = params.hum;                                                        // 湿度の値を取得
  var atmos = params.atm;                                                      // 気圧の値を取得

  sheet.insertRows(2,1);                                                       // ２行目に行を挿入
  sheet.getRange(2, 1).setValue(new Date());                                   // A列に受信日時を書き込む
  sheet.getRange(2, 2).setValue(params);                                       // B列に受信データを書き込む
  sheet.getRange(2, 3).setValue(temp);                                         // C列に温度を書き込む
  sheet.getRange(2, 4).setValue(hum);                                          // D列に湿度を書き込む
  sheet.getRange(2, 5).setValue(atmos);                                        // E列に気圧を書き込む
  
}
```

プロジェクトを保存します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/609c05ac-bb4a-e452-a9a5-7acf2d212984.png)

## 関数アプリをデプロイする
画面右上の「デプロイ」から「新しいデプロイ」をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/5e229461-e4c4-d66a-7220-abfcb134d2d3.png)

歯車のアイコンから、ウェブアプリをクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/7f9dd992-ce1a-b5ea-2a9d-dd24d047a8dd.png)

M5からデータを送信できるように、アクセスできるユーザを「全員」にしてデプロイボタンをクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/08cf8c0d-2065-84a7-d9c0-a95811d9f496.png)


アクセスを承認をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/200d7f52-bdbc-4822-6b36-8e3e23fbdc27.png)

自分のGoogleのアカウントを選択してサインインします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/522933d2-9d81-1089-d347-4fcb15dfd9f8.png)

advancedをクリックします
【補足】この警告は「Googleが正式に実行確認したプログラムじゃないけど大丈夫？」というもので、Apps Scriptを開発する際によく出てくる警告文です。今回、このプログラムがあなたのスプレッドシートにアクセスするため、「実行しても大丈夫なもの？」と確認のため表示しているものです。今回のプログラムはもちろん問題ありませんので手順の通りに進めて大丈夫です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/e8c4f3dc-53ce-501a-e703-64795a54e203.png)


一番下の、go to ～をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/8af8194a-df6f-2977-d25f-aef2939f26a3.png)


Allowをクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/b24af8a0-f931-b9ed-9ad9-95ee9b537973.png)

ここに表示されたURLを後ほど使います
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/8e81fdf0-4e99-6515-c695-f75f7730a0fd.png)

これで、M5から送信されたデータをスプレッドシートに書き込むプログラムは完成です
次はUIFlowに戻ってM5からデータを送信するプログラムを作りましょう

# M5からGoogleのスプレッドシートに環境データを送信数するプログラムを作成する
## 30秒に1回データを送信するタイマー関数を作る
タイマーブロックを追加します
![Animation000021.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/4e6266f0-0a5c-cec8-62ff-a275cadd9a4a.gif)

setupの処理の最後に30秒に１回タイマーを呼び出すブロックを追加します
※末尾が「生成」と「開始」があるので注意してください。使いのは「開始」の方です
※30秒に1回実行したいので、「30000」ミリ秒に設定してください
![Animation000022.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/b444da69-9dea-9306-345d-b7e58bee2b21.gif)

これで「timer1」が30秒ごとに1回呼び出され、右の「timer1」が呼び出された時のブロックが実行されるようになります。
最後はこのブロックの中身を作っていきましょう

## HTTPリクエストのブロックを追加する
高度なブロックの中にあるHTTPリクエストのブロックを追加します
メソッドはGETからPOSTに変更します
![Animation000023.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/08bfcd06-9d75-29b6-71bb-ff6cdef0114c.gif)

URLには先ほどデプロイしたApps ScriptのウェブアプリのURLをコピーして貼り付けます
【補足】Apps Scriptのプログラムを修正したら必ず新しくデプロイしてください。新しくデプロイする度にURLが変わるので、このブロックのURLの値も修正してください

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/1142a581-c87c-f4f5-e359-77f1487a2732.png)

データにマップを追加します
マップを作成の下の「＋」アイコンをクリックしてブロックを追加します。
追加ブロックのKeyはそれぞれ

* tmp
* hum
* atm

とします
![Animation000024.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/233609e1-4b0f-9603-9c02-6e2a36ffd1b5.gif)

追加ブロックのValueにはKeyと同じ名前の変数ブロックを追加します
![Animation000026.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/19fae3c2-5b05-f9e8-0798-62c9b3f9bef0.gif)

## プログラムを実行する
RUNボタンをクリックして実行してみましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/689f12af-c437-a042-b4a0-9575db389cb2.png)

うまくいけば30秒に1回スプレッドシートにデータが蓄積されていきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261327/6798c32b-d327-d9a6-5e33-dfd625e8e909.png)


# 時間が余ったら
順調にいって時間が余った方は以下のポイントについて追加でプログラム作成してみてください

 * 温度がX度を超えた場合、画面の背景色を赤系統の色に変わるようプログラムを修正してみてください
     * X度の具体的な値は好きに決めてよいです


今回のハンズオンはこれで完了です。
お疲れ様でした。