M5Stack の Color Sensor を UIFlow で試す

 M5Stack の拡張ユニットには色々なものがありますが、なんとなく面白そうだったので物体の色情報を取得できる Color Sensor を試してみました。ただ、先に結論を言っておくと、センサーの値を読み出すまではすごく簡単にできたのですが、そのまま値を使っても対象の色を正しく再現するところまではできませんでした。ひとまずやったことを一通り描いてみたいと思います。

www.switch-science.com

 公式のドキュメントはこちらにあります。

docs.m5stack.com

ユニット接続

 Color Sensor も他の拡張ユニットと同様に Grove コネクタで接続できますので、 M5Stack 本体左側の Grove コネクタに接続します。

f:id:akanuma-hiroaki:20190316210620j:plain

 センサー裏面にはピンアウトが記載されています。また、 PORT. A. I2C という記載もあります。私が持っている M5Stack Gray は Grove コネクタは一つだけで、 A PORT のみなので、 PORT A(I2C)用の拡張ユニットが接続できます。

f:id:akanuma-hiroaki:20190316210700j:plain

センサーの値を読む

 Color Sensor は UIFlow も対応しているので、今回は UIFlow で手軽に試してみます。ユニットを追加するために、エミュレータ下の ボタンをクリックします。

f:id:akanuma-hiroaki:20190316204437p:plain

 ユニットのリストの中から COLOR を選択し、プルダウンからは A PORT して OK をクリックします。

f:id:akanuma-hiroaki:20190316204634p:plain

 すると Color Sensor ユニットが UI Flow に追加されます。

f:id:akanuma-hiroaki:20190316204822p:plain

 Units メニューには Color メニューが追加され、 Color Sensor 用のブロックが使用できるようになります。現状確認できたのは RGB それぞれの値を読み取るブロックです。

f:id:akanuma-hiroaki:20190316204930p:plain

 上記のブロックを使用して簡単なサンプルを作成してみます。1秒ごとに Color Sensor の RGB 情報を読み出し、画面に表示します。

f:id:akanuma-hiroaki:20190316205132p:plain

動作確認

 実際に動作させてみると、下記のように Color Sensor から読み取った RGB の値が画面に表示されます。

f:id:akanuma-hiroaki:20190316205429j:plain

 動作中は色判別のための白色 LED が点灯します。

f:id:akanuma-hiroaki:20190316210726j:plain

 そして実際に読んだ値が正しいのかの確認にためにも、読み取った RGB の値で図形の色を変えてみるサンプルを下記のように作ってみたのですが、結論から言うと実際の色は正しく反映されませんでした。

f:id:akanuma-hiroaki:20190316220940p:plain

 例えば下記写真の実行例だと、対象のものは濃い黄色なのですが、読み取った RGB をそのまま使用すると茶色の表示になってしまいました。下記数字をそのまま合成すると茶色になるというのは正しいようなので、読み取った値が間違っているのか、そのまま使うのではなく何か加工が必要なのかもしれません。

f:id:akanuma-hiroaki:20190316221017j:plain

 ただ、下記オフィシャル動画を見るとそのまま使えているように見えるので、違う原因があるのかもしれません。

docs.m5stack.com

まとめ

 今回はとりあえずセンサーの値を読み出すまではできましたが、正しい色を再現するところまではできなかったので、今後何かわかれば正しく再現できるように改善してみたいと思います。正しく再現できれば何か面白ことができそうな気はしているものの、特にまだアイディアは思いついていないので、何か役に立つもののアイディアも考えてみたいと思います。

AWS Cloud9 で既存の EC2 インスタンスに接続する

 以前の記事でEC2インスタンスも同時に自動的に作成するやり方で Cloud9 の環境を作成してみましたが、仕事等で使うケースを考えると、既存のインスタンスに接続するケースもありそうだったので、試しに EC2 インスタンスを事前に別途作成して、そこに接続するやり方で Cloud9 の環境を作成してみました。

 手順はこちらで紹介されているので、この手順に沿ってやってみました。 EC2 インスタンスを作成するリージョンは Cloud9 と同様にシンガポールリージョンにしています。

docs.aws.amazon.com

VPC作成

 まずは VPC を作成します。 VPC コンソールから VPC ウィザードの起動 をクリックします。

f:id:akanuma-hiroaki:20190309215356p:plain

 VPC 内からインターネットに接続できる必要があるので、種別としては 1個のパブリックサブネットを持つ VPC を選択して 選択 ボタンをクリックします。

f:id:akanuma-hiroaki:20190309215501p:plain

 VPC の設定は基本的にデフォルトで OK なので、 VPC 名だけ任意のものを設定し、 VPC の作成 をクリックします。

f:id:akanuma-hiroaki:20190309215614p:plain

 VPC が作成されたら、 VPC コンソールからその VPC を選択し、 Description タブの Network ACL の ID のリンクをクリックします。

f:id:akanuma-hiroaki:20190309215853p:plain

 インバウンドルールを設定するために、 Inbound Rules タブの Edit inbound rules をクリックします。

f:id:akanuma-hiroaki:20190309220004p:plain

 インバウンドルールでは ssh の接続元を Cloud9 に限定するのですが、設定すべき CIDR は ip-ranges.json というファイルに記載されているので、下記のように確認することができます。今回はシンガポールリージョンなので、 region が ap-southeast-1 になっている2項目を使用します。

$ wget https://ip-ranges.amazonaws.com/ip-ranges.json
$ jq '.prefixes[] | select(.service=="CLOUD9")' < ip-ranges.json
{                              
  "ip_prefix": "13.250.186.128/27",
  "region": "ap-southeast-1",
  "service": "CLOUD9"
}                                 
{                               
  "ip_prefix": "13.250.186.160/27",
  "region": "ap-southeast-1",
  "service": "CLOUD9"
}            
〜〜〜以下略〜〜〜

 上記 CIDR をアクセス元として設定した ssh のルール2つと、Port Range で接続を許可する設定1つの合計3つのルールを設定します。最後に Save ボタンをクリックして設定を保存します。

f:id:akanuma-hiroaki:20190309220132p:plain

EC2 インスタンス作成

 続いて実際に接続する EC2 インスタンスを作成します。 EC2 コンソールから インスタンスの作成 をクリックします。

f:id:akanuma-hiroaki:20190309220344p:plain

 AMI は Amazon Linux 2 を選択します。

f:id:akanuma-hiroaki:20190309220640p:plain

 インスタンスタイプは、今回はお試しということで t2.micro を選択します。

f:id:akanuma-hiroaki:20190309220759p:plain

 インスタンスの詳細設定では、ネットワークとして先程作成した VPC を選択します。サブネットもその VPC に属する一つが選択されます。その他はデフォルト設定でOKなので、 次の手順: ストレージの追加 をクリックします。

f:id:akanuma-hiroaki:20190309221009p:plain

 今回はストレージはデフォルトのままで良いので、そのまま 次の手順: タグの追加 をクリックします。

f:id:akanuma-hiroaki:20190309221104p:plain

 今回は特にタグも追加しないので、そのまま 次の手順: セキュリティグループの設定 をクリックします。

f:id:akanuma-hiroaki:20190309221156p:plain

 セキュリティグループの割り当てでは 既存のセキュリティグループを選択する を選択し、VPC 内に作成されているセキュリティグループを選択して 確認と作成 をクリックします。

f:id:akanuma-hiroaki:20190309221342p:plain

 設定内容の確認画面が表示されますので、間違いがなければ 起動 ボタンをクリックします。

f:id:akanuma-hiroaki:20190309221513p:plain

 インスタンスに接続する際のキーペアを新たに作るか、既存のものを使用するかの選択フォームが表示されます。今回は 新しいキーペアの作成 を選択し、キーペア名を設定して キーペアのダウンロード をクリックし、プライベートキーファイルをダウンロードします。ダウンロードすると インスタンスの作成 ボタンがアクティブになりますので、クリックしてインスタンスを作成します。

f:id:akanuma-hiroaki:20190309221730p:plain

EC2 の環境設定

 冒頭で紹介したページでも説明されている通り、 Cloud9 で接続するにはいくつかの要件を満たす必要がありますので、インスタンスに接続して設定を行います。 VPC の作成中にインバウンドルールの設定で ssh の接続元を Cloud9 に限定しましたが、設定時にローカルからも接続できるように一時的に設定を追加します。設定が完了したら追加した設定は削除しておきます。

f:id:akanuma-hiroaki:20190309222144p:plain

 また、詳細な説明は割愛しますが、パブリックIPアドレスが必要になりますので Elastic IP も割り当てておきます。

 接続できるようになったら ssh でインスタンスに接続します。

$ ssh -i "cloud9.pem" ec2-user@ec2-52-XXX-XXX-XXX.ap-southeast-1.compute.amazonaws.com

 Cloud9 で接続するには Python 2.7 が必要になります。これはデフォルトでインストールされています。

$ python -V
Python 2.7.14

 次に node.js も必要になります。これはデフォルトではインストールされていませんので、下記手順でインストールします。

$ sudo yum -y update 
$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.0/install.sh | bash
$ . ~/.bashrc
$ nvm install node
$ node --version
v11.11.0

 また、 Cloud9 で接続するディレクトリの権限を設定します。ホームディレクトリを対象とする場合には下記のように権限を設定します。

$ ls -ld ~
drwx------ 5 ec2-user ec2-user 122 Mar  9 11:47 /home/ec2-user
$ 
$ sudo chmod u=rwx,g=rx,o=rx ~
$ 
$ ls -ld ~
drwxr-xr-x 5 ec2-user ec2-user 122 Mar  9 11:47 /home/ec2-user

 最後に AWS Cloud9 インストーラを実行します。 gcc が必要なので yum で Development Tools をインストールしてから、 curl でインストーラをダウンロードして実行します。

$ sudo yum -y groupinstall "Development Tools"
$ curl -L https://raw.githubusercontent.com/c9/install/master/install.sh | bash

Cloud9 の環境作成

 それでは Cloud9 の環境を作成します。 Cloud9 のコンソールから Create environment をクリックします。

f:id:akanuma-hiroaki:20190309222332p:plain

 環境名と説明を任意に入力し、 Next step をクリックします。

f:id:akanuma-hiroaki:20190309222454p:plain

 Environment type で Connect and run in remote server (SSH) を選択します。User には ec2-user、Host には先程までに作成した EC2 インスタンスのパブリックIPを設定します。 Copy key to clipboard をクリックすると Cloud9 から EC2 インスタンスに接続するためのパブリックキーがコピーされますので、インスタンス上で authorized_keys に設定します。設定できたら Next step をクリックします。

f:id:akanuma-hiroaki:20190309222729p:plain

 ちなみに authorized_keys への登録は vi などで下記のようにファイルを編集してペーストします。

$ vi ~/.ssh/authorized_keys

 設定内容の確認画面が表示されますので、問題なければ Create environment をクリックします。

f:id:akanuma-hiroaki:20190309222850p:plain

 Cloud9 の環境が作成され、追加でインストールが必要なもののリストが表示されますので、全て選択された状態のまま Next をクリックします。

f:id:akanuma-hiroaki:20190309223009p:plain

 コンポーネントのインストールが始まりますので完了するまで待ちます。ちなみに私は上記の画面から進まなくなってしまったので一度キャンセルしましたが、再度 Cloud9 環境に接続した際にインストールが行われ、無事に完了しました。

f:id:akanuma-hiroaki:20190309223100p:plain

 インストールが完了すると Cloud9 の IDE が表示され、使用できるようになります。

f:id:akanuma-hiroaki:20190309223144p:plain

まとめ

 Cloud9 で接続するためにはサーバ側がネットワーク設定やソフトウェアのインストールなどの要件を満たす必要があるのでちょっと煩雑ですが、一度設定を作ってしまって AMI として保存しておけば、誰かが同じ環境を使う場合にも AMI からインスタンスを作成すれば Cloud9 側の環境だけ新たに作れば良いので、導入時の手間が削減できそうですね。

f:id:akanuma-hiroaki:20190309233114j:plain:w400

M5Stack NeoPixel互換 LEDテープでLチカ

 先日の記事で使った距離センサを買った時に、面白そうだったのでついでに買ってみた LED テープを試してみたいと思います。

www.switch-science.com

 ドキュメントはこちらに用意されています。

docs.m5stack.com

LEDテープ接続

 まずは LED テープを M5Stack に接続します。 LED テープの両端は Grove コネクタになっているので、 Grove ケーブルで M5Stack に接続します。 LED テープは複数のテープを Grove ケーブルで連結していくことができるようになっていますが、 Input と Output の向きが決まっていますので、裏面を見て方向を確認し、 Input 側を M5Stack と接続します。今回は1本しか接続していませんが、複数接続する場合は1本目の Output が2本目の Input に接続されるようにします。

f:id:akanuma-hiroaki:20190302220746j:plain

 今回使っている LED テープは50cmのものなので、接続すると下記のような感じになります。ちなみに Grove ケーブルは付属していませんので、別途用意する必要があります。

f:id:akanuma-hiroaki:20190302220818j:plain

ユニット追加

 それでは LED を操作してみたいと思いますが、距離センサの時と同様に UI Flow で動かしてみたいと思いますので、まずは LED テープのユニットを追加します。エミュレータの左下の + ボタンをクリックします。

f:id:akanuma-hiroaki:20190302214851p:plain

 UI Flow が対応しているユニットのリストが表示されますので、 NEOPIXEL を選択します。 Port は A で、count には LED の数を設定します。50cm のテープには 72 個の LED があったので、72 を設定しています。設定したら OK をクリックします。

f:id:akanuma-hiroaki:20190302215005p:plain

 設定されるとエミュレータの左下に、追加されたユニットということで neopixel0 が表示されます。

f:id:akanuma-hiroaki:20190302215110p:plain

LED 操作

 ユニットが追加されると Units メニューに Neopixel が表示されるようになり、 LED を操作するための様々なブロックが使用できるようになります。

f:id:akanuma-hiroaki:20190302215212p:plain

 まずは LED 全体の色を1秒おきに切り替えるサンプルです。下記のようにブロックを配置します。

f:id:akanuma-hiroaki:20190302215302p:plain

 実際に動かしてみた時の様子はこちらです。この例では特に明るさは設定していませんが、デフォルトで結構明るく点灯するようになっています。

 もう一つのサンプルとして LED の明るさを徐々に変化させてみます。0 から 100 の間で明るさを増減させています。

f:id:akanuma-hiroaki:20190302215347p:plain

 実際の様子はこちらです。

まとめ

 今回使用した LED テープは 50cm のものですが、他に 10cm, 20cm, 100cm, 200cm のバリエーションがあり、さらに連結もしていけます。テープという名の通り裏側の紙を剥がせばどこかに貼り付けることも簡単にできますので、デジタルサイネージ的なものやインジケーター的なものも結構簡単に作れてしまいそうです。

 距離センサ等の他のユニットと組み合わせて使えば簡単にプロトタイピングできそうですが、 M5Stack Core や Gray では Grove コネクタが一つしかついていないので、 Grove コネクタを複数備えた他の M5Stack が欲しいところです。

SORACOM Lagoon の Free プランで Harvest のデータをグラフ表示

 前回の記事では if-up2019 で発表された Unified Endpoint のことを書きましたが、他にもいくつか発表があり、そのうちの一つとして SORACOM Lagoon に Freeプランと Proプランが追加されたという発表がありました。

blog.soracom.jp

 今までは月額で980円ということで、興味はあったものの試していなかったのですが、 Freeプランでは一人で使ってみる分には無料で使えるので、改めて使ってみました。

SORACOM Lagoon の利用開始設定

 Lagoon を使うには利用設定が必要になります。ユーザコンソールの共通メニューから ダッシュボード作成・共有 をクリックします。

f:id:akanuma-hiroaki:20190223123230p:plain

 Lagoon の利用開始設定の画面が表示されますので、 SORACOM Lagoon の利用を開始する ボタンをクリックします。

f:id:akanuma-hiroaki:20190223123507p:plain

 料金プランの選択ダイアログが表示されますので、 Freeプラン を選択して 続行する をクリックします。

f:id:akanuma-hiroaki:20190223123648p:plain

 Lagoon を利用するためのパスワードを設定します。アカウントには現在ユーザコンソールにログインしているメールアドレスが使われ、そのメールアドレスとここで設定するパスワードで Lagoon を利用できるようになります。パスワードを入力したら 利用開始 をクリックします。

f:id:akanuma-hiroaki:20190223123822p:plain

 すると Lagoon のユーザが追加されますので、 SORACOM Lagoon console にアクセス をクリックします。

f:id:akanuma-hiroaki:20190223124058p:plain

 Lagoon へのログインフォームが表示されますので、先ほど設定した時のメールアドレスとパスワードを入力して Lagoon にログインします。

f:id:akanuma-hiroaki:20190223124208p:plain

Lagoon で Harvest のデータを表示する

 Lagoon では SORACOM Harvest に収集したデータを簡単に表示することができますので試してみます。 Lagoon にログインすると下記のように Home Dashboard が表示されますが、最初は何もありません。ダッシュボードを追加するために、まずは左上の Home をクリックします。

f:id:akanuma-hiroaki:20190223124611p:plain

 Home 画面で 新しいダッシュボード をクリックします。

f:id:akanuma-hiroaki:20190223124807p:plain

 ダッシュボードには様々なパネルを追加することができます。今回はグラフ表示のために Graph を選択します。

f:id:akanuma-hiroaki:20190223124907p:plain

 パネルが追加されたら Panel Title をクリックして表示されるメニューから 編集 をクリックします。

f:id:akanuma-hiroaki:20190223161915p:plain

 Lagoon のデータソースには Harvest 以外にも Grafana が選択できます。 default だと Harvest のデータが使用されますので、今回は default のままにします。

f:id:akanuma-hiroaki:20190223162046p:plain

 今回は Harvest に前回の記事で Unified Endpoint を試した時のサンプルデータが入っていますので、そのうちの一つの項目である humidity が対象として表示されています。今回はもう一つの項目である temperature も表示しますので、 クエリを追加 をクリックして対象データを追加します。

f:id:akanuma-hiroaki:20190223204319p:plain

 追加したデータの方では temperature を選択して、下記のように2つのデータを対象とします。

f:id:akanuma-hiroaki:20190223204538p:plain

 対象データを設定すると、デフォルトでは直近6時間分のデータが表示されるのですが、今回のデータを登録したのは一週間前なので、対象期間を変更してみます。 Last 6 hours と表示されているところをクリックすると、対象期間が選択できますので、今回は 先週の今日 をクリックします。

f:id:akanuma-hiroaki:20190223204714p:plain

 すると一週間前の1日分のデータが表示されます。データは1日のうちの一部だけなので、グラフでデータが表示されている部分をドラッグして選択します。

f:id:akanuma-hiroaki:20190223204837p:plain

 すると選択した部分が拡大して表示されます。対象期間を簡単に選択できるので便利ですね。

f:id:akanuma-hiroaki:20190223205021p:plain

 グラフを見やすくする為に少し設定を変更してみます。 全般 タブを選択してタイトルと説明文を設定します。

f:id:akanuma-hiroaki:20190223164422p:plain

 次に タブで各軸のラベルを設定します。

f:id:akanuma-hiroaki:20190223171913p:plain

 ここまででひとまずの設定ができたので、設定画面からダッシュボードの名前を設定して保存しておきます。

f:id:akanuma-hiroaki:20190223172845p:plain

ダッシュボードの共有(Makerプラン以上)

 ちなみに Lagoon では他の Lagoon ユーザにダッシュボードを共有することができます。画面上部の 共有 ボタンをクリックします。

f:id:akanuma-hiroaki:20190223173426p:plain

 共有用のリンクが表示されますので、このリンクを他のユーザに共有することでダッシュボードにアクセスしてもらうことができます。

f:id:akanuma-hiroaki:20190223173827p:plain

 ただし、その為には Lagoon のユーザを追加する必要がありますが、 Freeプランでは登録できるユーザ数は一人(自分)だけなので、ユーザを追加しようとしても下記のようにエラーが表示されて追加できません。複数ユーザで使用する場合には Maker 以上のプランにする必要があります。

f:id:akanuma-hiroaki:20190223174110p:plain

アラートを追加する

 Lagoon ではデータの内容によってアラートを出すことが可能です。まずはアラートの通知方法を設定するために、チャンネルを作成します。左のメニューから 通知チャンネル を選択します。

f:id:akanuma-hiroaki:20190223194956p:plain

 チャンネルリストの画面が表示されますが、最初はまだチャンネルがないので、表示されている チャンネルを追加 ボタンをクリックします。

f:id:akanuma-hiroaki:20190223195138p:plain

 チャンネルの設定フォームが表示されます。通知方法としては slack や webhook など様々なものが選択可能です。今回は Email を選択します。対象のメールアドレスはセミコロンで区切って複数指定することが可能です。 送信テスト をクリックするとテストメールが送信されます。正しく設定できたら 保存 をクリックします。

f:id:akanuma-hiroaki:20190223195323p:plain

 作成されたチャンネルはリスト画面に表示されます。

f:id:akanuma-hiroaki:20190223195456p:plain

 次にダッシュボードの編集画面の アラート タブから アラートを作成 ボタンをクリックします。

f:id:akanuma-hiroaki:20190223195649p:plain

 アラートの設定画面からアラートの条件を設定します。 query では対象のデータ項目と対象の時間を設定できます。今回は温度を対象にするので、 B を対象として、5分間のデータを対象にします。条件としては平均値、最小値など様々な方法が指定できます。今回は最大値( max() )を使用して、5分間の最大値が23を超えた場合にアラートを出します。

f:id:akanuma-hiroaki:20190223200136p:plain

 通知の送り先としては先ほど作成したチャンネルを指定します。メールの文面は自由に設定できます。

f:id:akanuma-hiroaki:20190223200334p:plain

 指定した閾値を超えると下記のようなメールが送られてきます。

f:id:akanuma-hiroaki:20190223200416p:plain

まとめ

 センサー等で集めたデータを可視化するのは自分でやると結構な手間がかかる部分ですが、 Lagoon を使うことで Harvest に入っているデータであれば画面から設定するだけで簡単に可視化することができました。今回 Freeプランができたことで、開発者が自分で使うぐらいであれば無料で使うことができるので、デバイスで取得したデータは json で Unified Endpoint を経由して Harvest に投げ込んでおいて Lagoon で可視化するという、サーバサイドの一連の処理を無料で簡単に用意することができるようになりました。ますますプロトタイピングのハードルが下がりましたね。

Unified Endpoint で SORACOM の複数サービスにデータを送る

 先日 2/14 にソラコムさんの if-up2019 IoT Technology Conference に参加してきました。

if-up2019.soracom.jp

 ソラコムさんはイベントに合わせていつも新発表をされますが、今回の新発表の一つとして Unified Endpoint が発表されました。

blog.soracom.jp

 こちらは独立した新サービスではなく新機能ということで、すでに Public Beta として使えるようになっていたので早速試してみました。

機能概要

 Unified Endpoint を簡単に説明すると、 SORACOM の複数のサービスへのデータ送信を一つのURLでまとめて受け取れるようにしたものです。 SORACOM では今までに Beam, Funnel, Harvest といったサービスが提供されていて、クラウドサービスとのデータ連携や可視化が便利にできるようになっていましたが、送信先URLはそれぞれ違っています。なので後から送信先サービスを変更する場合、例えば Beam で自前のサーバに送っていたけど Funnel で AWS IoT に連携するようにする、といった場合にはデバイス上の実装に含まれているURL指定を変更する必要がありました。

 これが Unified Endpoint を利用することにより、デバイスの実装では常に Unified Endpoint の URL にデータを送っていれば、ユーザーコンソールの設定だけで送信先サービスを変更できるようになります。もちろん送信内容はあらかじめ汎用性を考慮しておく必要はありますが、設置済みデバイスの実装に手を入れずに送信先を変更できるというのはとても便利なのではないかと思います。

設定

 今回は Raspberry Pi を SORACOM Air でセルラーネットワークに接続し、温度と湿度のデータを JSON で SORACOM Harvest と SORACOM Funnel 経由で AWS IoT に送信してみます。 AWS IoT に接続するにはデバイスの認証が必要ですが、今回の認証は以前下記の記事で試した SORACOM Krypton での認証を使用します。

blog.akanumahiroaki.com

 それではそれぞれのサービスの設定を行なっていきます。まず Unified Endpoint は有効にするための設定は特に必要なく、自動的に使用されます。レスポンスの形式を変更する場合はユーザコンソールのSimグループの設定画面から設定変更を行います。今回はデフォルトの Auto 設定のまま使用してみます。

f:id:akanuma-hiroaki:20190216154948p:plain

 Harvest の設定は ON/OFF の切り替えのみですので、ユーザコンソールから ON にします。

f:id:akanuma-hiroaki:20190216155126p:plain

 Funnel から AWS IoT への転送設定は、 Funnel の利用を ON にして、転送先サービスで AWS IoT を選択します。転送先 URL には AWS IoT のエンドポイントに MQTT のトピックス名を組み合わせて指定し、認証情報は Krypton で設定した認証情報を指定します。

f:id:akanuma-hiroaki:20190216160208p:plain

 これで設定は一通り完了です。データ送信については今回は擬似的に温度と湿度データを生成して送信する Ruby スクリプトを実装してデータを送信してみます。送信先の URL には Unified Endpoint の URL を指定し、30秒ごとにデータを送信してみます。

require 'bundler/setup'
require 'httpclient'
require 'logger'

UNIFIED_ENDPOINT = 'http://uni.soracom.io'
LOG_FILE = 'env_monitor.log'

class ENV_MONITOR
  def initialize(interval)
    @interval = interval
    @http_client = HTTPClient.new
    @logger = Logger.new(LOG_FILE)
    @temperature_range = 20.0..25.0
    @humidity_range = 40..60
  end

  def execute
    loop do
      temperature = Random.rand(@temperature_range)
      humidity = Random.rand(@humidity_range)
      payload = '{"temperature": "%.1f", "humidity": "%.1f"}' % [temperature, humidity]
      res = @http_client.post(UNIFIED_ENDPOINT, payload, 'Content-Type' => 'application/json')
      @logger.info("PAYLOAD: #{payload} / Response: #{res.status}")
      @logger.info(res.body)

      sleep(@interval)
    end
  end
end

if __FILE__ == $PROGRAM_NAME
  monitor = ENV_MONITOR.new(30)
  monitor.execute
end

動作確認

 それでは SORACOM Air でネットワーク接続した上でスクリプトを動かして動作を確認してみます。スクリプトを動かすと下記のようにログに出力されます。今回は Unified Endpoint のレスポンスの設定を Auto にしていますので、レスポンスの detail には Funnel と Harvest それぞれからの statusCode が含まれます。 Funnel からは 204、 Harvest からは 201 が返って来ていますので、それぞれへのデータ送信は成功しているようです。

I, [2019-02-16T06:34:37.185769 #23241]  INFO -- : PAYLOAD: {"temperature": "20.8", "humidity": "58.0"} / Response: 200
I, [2019-02-16T06:34:37.186107 #23241]  INFO -- : {"result":"ok","detail":{"SoracomFunnel":{"statusCode":204},"SoracomHarvest":{"statusCode":201}}}
I, [2019-02-16T06:35:09.495921 #23241]  INFO -- : PAYLOAD: {"temperature": "25.0", "humidity": "41.0"} / Response: 200
I, [2019-02-16T06:35:09.496257 #23241]  INFO -- : {"result":"ok","detail":{"SoracomFunnel":{"statusCode":204},"SoracomHarvest":{"statusCode":201}}}
I, [2019-02-16T06:35:43.716117 #23241]  INFO -- : PAYLOAD: {"temperature": "20.1", "humidity": "52.0"} / Response: 200
I, [2019-02-16T06:35:43.716453 #23241]  INFO -- : {"result":"ok","detail":{"SoracomFunnel":{"statusCode":204},"SoracomHarvest":{"statusCode":201}}}
I, [2019-02-16T06:36:15.356277 #23241]  INFO -- : PAYLOAD: {"temperature": "23.3", "humidity": "47.0"} / Response: 200
I, [2019-02-16T06:36:15.356612 #23241]  INFO -- : {"result":"ok","detail":{"SoracomFunnel":{"statusCode":204},"SoracomHarvest":{"statusCode":201}}}
I, [2019-02-16T06:36:49.526506 #23241]  INFO -- : PAYLOAD: {"temperature": "20.4", "humidity": "52.0"} / Response: 200
I, [2019-02-16T06:36:49.526851 #23241]  INFO -- : {"result":"ok","detail":{"SoracomFunnel":{"statusCode":204},"SoracomHarvest":{"statusCode":201}}}
I, [2019-02-16T06:37:21.146493 #23241]  INFO -- : PAYLOAD: {"temperature": "23.7", "humidity": "47.0"} / Response: 200
I, [2019-02-16T06:37:21.146824 #23241]  INFO -- : {"result":"ok","detail":{"SoracomFunnel":{"statusCode":204},"SoracomHarvest":{"statusCode":201}}}
I, [2019-02-16T06:37:58.956850 #23241]  INFO -- : PAYLOAD: {"temperature": "22.3", "humidity": "59.0"} / Response: 200
I, [2019-02-16T06:37:58.957189 #23241]  INFO -- : {"result":"ok","detail":{"SoracomFunnel":{"statusCode":204},"SoracomHarvest":{"statusCode":201}}}
I, [2019-02-16T06:38:30.626827 #23241]  INFO -- : PAYLOAD: {"temperature": "21.2", "humidity": "50.0"} / Response: 200
I, [2019-02-16T06:38:30.627169 #23241]  INFO -- : {"result":"ok","detail":{"SoracomFunnel":{"statusCode":204},"SoracomHarvest":{"statusCode":201}}}
I, [2019-02-16T06:39:03.247368 #23241]  INFO -- : PAYLOAD: {"temperature": "21.7", "humidity": "59.0"} / Response: 200
I, [2019-02-16T06:39:03.247702 #23241]  INFO -- : {"result":"ok","detail":{"SoracomFunnel":{"statusCode":204},"SoracomHarvest":{"statusCode":201}}}
I, [2019-02-16T06:39:34.887067 #23241]  INFO -- : PAYLOAD: {"temperature": "22.1", "humidity": "55.0"} / Response: 200
I, [2019-02-16T06:39:34.887410 #23241]  INFO -- : {"result":"ok","detail":{"SoracomFunnel":{"statusCode":204},"SoracomHarvest":{"statusCode":201}}}

 レスポンスのフォーマットについては下記公式ドキュメントに詳しく書かれていますのでご参照ください。

Unified Endpoint : 機能の説明 | 開発者ガイド | SORACOM Developers

 Harvest の画面でも送信されたデータが確認できます。

f:id:akanuma-hiroaki:20190216160003p:plain

まとめ

 Unified Endpoint から転送可能なのは Beam, Funnel, Harvest の3つですが、 Beam に転送できるということは実質的には何処へでも転送できるということになりますので、実装時にはとりあえず Unified Endpoint 宛に JSON でデータを送るようにしておけば、後からの変更はかなり柔軟にできるのではないでしょうか。認証でも Krypton 等を組み合わせることができますし、様々な処理をデバイスからクラウド側へオフロードできるようになって、どんどん便利になってきました。プロトタイプ段階からこういったサービスを活用してアーキテクチャを考えていくことが重要になってきますね。

M5Stack 用の距離センサと UIFlow でプロトタイピング

 M5Stack には GPIO にジャンパーコードを接続して色々なセンサーなどを接続することができますが、 GROVE コネクタで簡単に接続できる M5Stack 用のユニットパーツが色々と販売されています。 UIFlow でも色々なユニットパーツに対応していて気になっていたのですが、今まで試していなかったので、今回は距離センサを試してみました。

www.switch-science.com

 ユニットについてのドキュメントも用意されていて、下記で参照できます。 Arduino IDE でのサンプルコード等も掲載されています。

docs.m5stack.com

測定方式

 距離センサにも色々な方式がありますが、このセンサは ToF(Time-of-Flight)方式と言われるもので、赤外線が物体に反射して戻ってくるまでの時間から距離を計算するタイプのものです。搭載されているセンサモジュールは下記のモジュールです。

www.switch-science.com

 ちなみに以前下記の記事で使用したセンサも方式としてはToF方式ですが、赤外線ではなく超音波を使ったものになります。

blog.akanumahiroaki.com

距離センサを接続

 それでは距離センサを M5Stack に接続してみます。センサには本体とGROVEコネクタ用のケーブルがセットになっています。

f:id:akanuma-hiroaki:20190209140134j:plain

 センサ本体の裏面は下記のような感じで、センサモジュールの型番やピンアウトが記載されています。

f:id:akanuma-hiroaki:20190209140203j:plain

 接続はセンサユニットを M5Stack 本体の GROVE コネクタに接続するだけで、それ以外にジャンパーコードを使ったり半田付けをする必要はありません。

f:id:akanuma-hiroaki:20190209140304j:plain

距離を表示

 今回は UIFlow を使って処理を実装してみます。 UIFlow の M5Stack エミュレータの下にユニット追加ボタンがあるのでクリックします。

f:id:akanuma-hiroaki:20190209142955p:plain

 すると UIFlow が対応しているユニットパーツのリストが表示されますので、下の方にスクロールして ToF を選択します。 Port は A を選択します。

f:id:akanuma-hiroaki:20190209143211p:plain

 追加するとエミュレータの下に ToF が表示されるようになります。

f:id:akanuma-hiroaki:20190209143319p:plain

 ToF が追加されるとメニューの UnitsTOF が追加され、センサから距離を読み取るためのブロックが使用できるようになります。

f:id:akanuma-hiroaki:20190209143443p:plain

 これを使用して今回は、無限ループで一秒毎に距離情報を読み出してラベルの位置に表示する簡単な処理を作ってみました。

f:id:akanuma-hiroaki:20190209151125p:plain

 これを実際に M5Stack の実機で動かして、実際の距離と読み出した値の差を簡単に確認してみました。読み取った数字の単位が何なのかは少し調べてみた感じではわからなかったのですが、やってみた感じでは ミリメートル と思って良さそうです。数ミリの誤差はあるものの、検証の仕方も適当ですし、大幅に外れた値が取れることはなかったので、かなり精度は良さそうに感じています。

まとめ

 センサーユニットの物理的な接続も GROVE コネクタで繋ぐだけですし、モニタも M5Stack 本体についていて、さらに UIFlow を使うことで直接コードも書かずに簡単に距離センサーのプロトタイピングができてしまいました。 IoT のプロトタイピングでは如何に電子工作せずにコードを書かずに手軽に実行するかというのが重要だと思いますので、その点 M5Stack とそのユニットパーツはかなり有効に使えそうに思います。今回簡易に試した限りでは距離センサの精度も高そうなので、アイディア次第では十分実用的に使えそうです。

M5Stack UIFlow の Custom Function を試す

 数日前に Twitter で M5Stack の UIFlow で Custom Function というのがリリースされたのを見たので、今回は試しに触ってみました。Custom Function というのは内容を自由に設定してブロックを作ることができる機能です。

UIFlow 用のファームウェアを Mac で Flash する

 UIFllow を使うには M5Stack に UIFlow 用のファームウェアを Flash しておく必要があります。以前は Mac からファームウェアを Flash するにはターミナルからコマンドで操作する必要がありましたが、最近では Windows と同じように Flash 用のツールが提供されているのでそれを使ってみます。ツールは UIFlow の設定画面からダウンロードすることができますので、 UIFlow にアクセスして設定画面を開きます。

f:id:akanuma-hiroaki:20190202214739p:plain

 設定画面に M5Burner-Flow-For-MacOS というリンクがありますので、これをクリックするとファイルのダウンロードダイアログが開きます。

f:id:akanuma-hiroaki:20190202214801p:plain

 デフォルトでは M5Burner_MacOS.zip というファイル名で保存されますので、これを解凍すると M5Burner_MacOS.app というアプリケーションになります。これを実行するとツールが起動するのですが、起動時に下記のようなダイアログが表示されて、ツールが起動できないことがあります。

f:id:akanuma-hiroaki:20190202214828p:plain

 これは MacOS のセキュリティ設定によるもので、製造者が信頼できない場合は実行することができなくなっています。以前の MacOS ではセキュリティ設定で、全てのアプリケーションを実行可能にすることもできたのですが、最近の MacOS ではその選択肢がなくなっています。

f:id:akanuma-hiroaki:20190202214947p:plain

 これを変更するには、ターミナルから下記のようにコマンドを実行し、全てのアプリケーションの実行を許可します。

$ sudo spctl --master-disable

 するとセキュリティ設定画面にもそれが反映されて、項目が追加で表示されます。

f:id:akanuma-hiroaki:20190202215039p:plain

 ちなみにずっとこのままの設定にしておくのは良くないので、ツールの実行が終わったら下記のようにコマンドを実行するか、セキュリティ設定画面から設定を戻しておくのが良いかと思います。

$ sudo spctl --master-enable

 ツールが起動すると下記のようなフォームが表示されます。執筆時の UIFlow の最新のバージョンは 1.1.2 なので、ファームウェアのバージョンも同じバージョンを選択して、 Flash ボタンをクリックします。しばらく待つとファームウェアが M5Stack に Flash されます。

f:id:akanuma-hiroaki:20190202215147p:plain

 これ以降の操作は以前と同様です。下記記事でも手順を書いていますので、よろしければご参照ください。

blog.akanumahiroaki.com

Custom Function を試す

 それでは Custom Function を試してみます。 UIFlow の 1.1.2 では下記のようにメニューに Custom (Beta) という項目が追加になっています。内容としては Create *.m5b fileOpen *.m5b file という2つがあります。まずは Create *.m5b file をクリックします。

f:id:akanuma-hiroaki:20190202215529p:plain

 すると UIFlow Block Maker というサイトに遷移します。

f:id:akanuma-hiroaki:20190202215627p:plain

 この UIFlow Block Maker で Custom Function の内容を指定し、ブロックを作成するわけです。今回はとりあえず画面に「Hello World!」のような文字列を表示する Function を実装してみます。「World」の部分は引数として指定できるようにします。設定項目は下記のようにしました。

  • Namespace: greeting

  • Block Color: 青

  • Name: hello

  • Type: Executable

  • Parameter: name (String)

 Block Code は実際に実行されるソースコードを設定しておくところで、今回は下記のようにしています。 UIFlow でラベルを指定した時に実行されるコードと同じものです。

label0 = M5TextBox(51, 39, "Hello ${name}!!", lcd.FONT_Default, 0xFFFFFF)

 画面左側の内容を変更していくと、右側のソースコードにリアルタイムに反映されていきます。今回のケースでは最終的には下記のような設定になります。設定が終わったら Download ボタンをクリックします。

f:id:akanuma-hiroaki:20190202220013p:plain

 するとファイルのダウンロード用のダイアログが開きます。今回は greeting.m5b というファイル名で保存しておきます。

 ファイルを保存したら、今度は Custom (Beta) の項目から Open *.m5b lib を選択します。するとファイルのアップロード用のダイアログが開きますので、先ほど保存した greeting.m5b を選択します。

f:id:akanuma-hiroaki:20190202220140p:plain

 m5b ファイルがアップロードされると、下記のように Custom (Beta) の項目に先ほど UIFlow Block Maker で作成した Custom Function のブロックが追加されます。

f:id:akanuma-hiroaki:20190202220307p:plain

 今回作成した Custom Function では表示する名前を引数として取ることにしていますので、その内容と共にブロックを設定して、実行ボタンをクリックします。

f:id:akanuma-hiroaki:20190202220508p:plain

 すると M5Stack で下記のように文字列が表示されます。

f:id:akanuma-hiroaki:20190202220609j:plain

まとめ

 手順として一度 .m5b ファイルをローカルに保存してそれをアップロードするという手順が直感的ではない気はしましたが、 UIFlow 自体にはまだファイルを保存しておくことができない中で、複数のアプリで汎用的に使用するコードをまとめておけるようになったのは便利かと思います。まだ Beta ということで、ブロックに表示されるのがパラメータの変数名だったりとまだわかりづらいところはありますが、今後使いやすくなっていくのではないかと思います。