※この記事は「enebular Advent Calendar 2016」12/22の分です。
はじめに
前回、GCPのAPIを使って、ポケモン生活を快適にしました。
そして、応用編でアイドルを召喚しました。
さいかわアイドルあのちゃん↓

これをweb上のボタン
ではなく、最も癒してほしいタイミングで自動で召喚される、そんなIoTチックなことをWio-Nodeを使って実装しました。
成果物
どうなってるの?
- カップの下に光センサがございます。
- n秒の単位でWio-Nodeが光量データを送信いたします。
- 光量データを前回値と比較し、カップが持ち上がったことを検出します。
-
あのちゃんが微笑みます
めっちゃトイレ行く頻度増えそうですね!!![]()
デバイス側

これただ頂いたものを繋げて置いてるだけなのでかっこよくどうにかしたいですね。
レシピ
- 前回のフロー(GCP+SlackBot)
- Wio-Node
- Light Sensor
- 美味しいコーヒー(gifでは水飲んでます)
Wio-Nodeとは
小型のwifi対応開発ボードです。
iOS及びAndroidのモバイルアプリで設定が可能なので、プログラミングさっぱりでも開発できちゃう優れものです。
APIの発行もアプリで楽チンですよ。
タップで、それぞれの接続機器をセットして、アップデートするだけ!
画面下部の「View API」からAPIの発行を行うことができます。
先日、弊社で@tseigoさんによるWio-Nodeハンズオンが行われ、参加いたしました!その際はありがとうございました!
(開催概要:IoTLT番外編! WioNodeハンズオン at ウフル)
(Wio-Nodeとenebularについては@tseigoさんのアドカレ3日目の記事へ:enebularでデータを取りやすいWio Nodeへのシンプルな取得方法)
msg変数とflow変数とglobal変数
こっからenebularの話ですが、まずは上記の3つの変数の仕様確認を行いました。
のPropertyを見ると、普段扱うmsgのほかにflowとglobalがあります。

どう違うのか、検証用にこんなFlowを組んでみました。

上からmsg, flow, globalの3つに分かれていて、
上のtimestampを押すとhoge.payloadに値がセットされ、
下のtimestampを押すとhoge.payloadをmsg.paloadへセットし現在値をログから見れるようになっています。
(下手な日本語なので、検証結果見てもらった方が早いです
)
msg
このようにmsgはつながっているnode上でしか保存されない変数ということがわかります。
`msg.payload.hoge`に何かが入っている状態で、`msg.paylod`に値を代入されるとhogeが円環の理に導かれて消えてしまいますflow
flow変数は同一Flowの画面上なら共有されるようです。タブが変わってしまうと値は参照されません。
一次的に値を保存したいときなど、`flow.hoge`に逃がしておくとよさそうですglobal
global変数は、別のタブでも値が参照できました。
繰り返し使う関数などをglobalに代入しておくと、便利そうですね今回は、光センサを使って前回取得値との比較を行ったので、flow変数を用いました。
実際のFlow
ノードで取得値(msg.payload)をflow変数に逃がしてめっちゃ一時保存しています。
前回のおさらい
Flowの下のとこです。(前回詳しく解説していなかったので、少し書きます。)
光センサから受け取る光量を前回取得時の比べ、閾値を超えていたら、画像検索が走ります。
画像検索は「あのちゃん+
」で行っています。↓中身

"ゆるめるモ!","私服","インスタ","かわいい","悪魔","咲","ようなぴ","けちょん","しふぉん","ほぼほぼ","舌","白い",
こんな感じの配列をUTF-8に変換して突っ込んでます。
関数走らせれば、直入力でもいけそうなのですが。。
この配列からランダムで一つとってきて、検索してます。
var word = msg.payload.word[Math.random() * msg.payload.word.length | 0];
ここで、先ほどの配列から1つのワードだけランダムで引っ張っています。
url=のあとですが'クオートでも"ダブルクオートでもなく、アクサングラーブ(@の上のやつ、インラインになっちゃってうまく表示できない)を使っています。
そうすると${hoge}で変数渡せます~
すごい!(こなみ)
現在値と前回値を比較する
でWioNodeからの光量データを取得します。
アプリから発行されたURL置いてるだけなので、中身は割愛。
こんな感じ。
`msg.before`に前回値が代入されている`flow.before`の値をセット。前回値の保存については後続のフローで行っています。
`msg.payload.analog`に光量データがはいっているので、`msg.latest`に逃がします。
先ほどセットした値を計算しているだけですね。
で、閾値を超えているかを
で判定しています。

これで、「あらかじめコーヒーカップが置いてあって、持ち上げたとき」だけ後続のフローに流れるようになります。
これだけで回すとゴミがあってうまく回らなかったので、
でズルをしました。

ダミー値を代入しています。後続のフローに影響するものを取り除きました。
で、現在値をflow変数に保存しています。今回の肝ですね。

flow.startでスタート時の制御を行っています。
flow.beforeに取得した光量値を代入し、次回取得時との比較に使います。
頭の一発目チェック付近へ参ります。flow.startを扱っているところです。
で分岐をしています。

2回以降の取得であれば、ここのフローはスルーして流れます。
1回目の取得の時に前回値が存在しないので、ダミーデータの代入の必要があります。
ここでやってます。

これがないとうまく回らずで詰まっていました![]()
まとめ
前回のポケモン生活快適化をしている最中に思いついたものでしたが、自分の構想通りに実装できました。
今までは
のようなfunctionノードで値の比較や、代入を行っていましたが、
を使うことにより、ノードの中身を見ずとも、データの流れをデザインしていくことができるので、エラーの特定なども容易にすることができました!![]()
「functionを使ったら負け」と以前言われたのですが、その意味が少しわかった気がしました。










