freeeの開発情報ポータルサイト

みんな大好きパトランプもクラウドの時代

会計freee のエンジニアをしている id:him0 (@him0net) です。最近、配達をしたり、某社と大乱闘したりと忙しない日々を送っています。普段は、マイクロサービスを含むバックエンドやフロントエンドの開発をメインに開発しているのですが、普段とは違う IoT なお話を書こうかと思います。

この記事は freee Developers Advent Calendar 2019 14日目の記事です。

オフィスに欲しいは、パトランプ

パトランプのイラスト
パトランプ

やはり視覚に訴えるものをオフィスに置きたい。

パトランプがあれば、CI が落ちたときであったり、サービスが不調になったときに、即座に気がつける気がします。ロマンあふれる存在それがパトランプです。

ネットワーク接続機能と API を備えたものがあったりするけど流石にお値段が張る印象。

そして、なにより、自分で作ることが面白いってことだろ?ってことで、既製品でなくパーツを買って自作してみることにしました。

パトランプの配線をする

Raspberry Pi が手元に余っていたので、どうにか Raspberry Pi からパトランプにつなぎ込んで制御したいと思いインターネットの海を泳いでいると、同じことを考えている人はいるもので先駆者の記事を発見。

Raspberry Piで携帯パトランプを作る (障害アラート通知)

この記事を参考に

パトランプ

パトランプ
パトランプ

リレー

リレー
リレー

電池ケース

電池ケース
電池ケース

の3点を購入。動作確認を行いつつつないだ様子がこちらです。

パトランプ配線
パトランプ配線
これらをつなぎこむとこんな感じになりました。

GPIO は、1ピン制御できればよかったので、Pin3 を選択しました。

Raspberry Pi に入って、動作確認(一番かんたんな shell スクリプトから value を書き換える方法で動作確認)

$ sudo su -l

# echo 3 > /sys/class/gpio/export
# echo "out" > /sys/class/gpio/gpio3/direction

# echo 0 > /sys/class/gpio/gpio3/value # 光る
# echo 1 > /sys/class/gpio/gpio3/value # 止まる

# echo 3 > /sys/class/gpio/unexport

value が、low のときに、パトランプは動き、 high のときにパトランプが止まることが確認できました。

パカパカするパトランプ
パカパカするパトランプ

AWS IoT Core でデバイスの状態を管理する

AWS IoT Core には、Shadow Divice という概念があり、クラウドでデバイスの状態を定義して持つことができます。

デバイスに対する操作は、仮想のデバイスの状態を変更し。IoT デバイスは、仮想のデバイスと自身の状態を同期することで、メモリのリフレッシュが発生しても、状態を復旧することができるという仕組みになっています。

AWS の公式ドキュメントで、RaspberryPi を AWS IoT Core に登録するチュートリアルがあるのでこれをもとに設定を行いました。

Raspberry Pi で AWS IoT SDKを使用する - AWS IoT

クラウドで状態が管理されるパトランプ

デバイスのシャドウの設定
デバイスのシャドウの設定

デバイスシャドウでは、desired reported delta の3状態が管理されます。

パトランプを点灯状態を lightning という boolean で管理する場合、 パトランプオフが設定され、実際オフになってい状態だとデバイスのシャドウの状態は

{
  "desired":  { "lighting": false },
  "reported": { "lighting": false }
}

となります。desiredreported 差分がない状態なので、delta は無し。

AWS IoT の テスト画面などの MQTT クライアントより

$aws/things/RaspberryPiBplus/shadow/update に対して、

{ "state": { "desired": { "lighting": true } } }

のメッセージを発行すると差分が検知されシャドウのステータスは、

{
  "desired":  { "lighting": true  },
  "reported": { "lighting": false },
  "delta":    { "lighting": true  }
}

になります。ここで、デバイス(Raspberry Pi)は、パトランプを点灯させ

{ "state": { "reported": { "lighting": true } } }

のメッセージを発行することで、デバイスシャドウの状態は

{
  "desired":  { "lighting": true },
  "reported": { "lighting": true }
}

となり、パトランプオンが設定され、実際オンになってい状態として安定化します。

Raspberry Pi で動かすプログラム

完成品がこちら github.com

AWS IoT Core とのつなぎこみは、RubyDevInc/aws-iot-device-sdk-ruby を利用しました。

Node.js の SDK を利用したかったのですが、npm package が依存関係の問題でうまく入らず、一旦、ruby の SDK で開発を行いました。ruby sdk は、有志の gem でインタフェースも、Node.js ものと比べると足りない部分もあったため、再度時間をもうけて Node.js に SDK で書き直したいと思います。

Raspberry Pi の GPIO の制御には、servebox/taopaipai をという gem を利用しました。

jwhitehorn/pi_piper という、gem がドキュメントも多く、扱いやすそうではあったのですが、ネイティブのライブラリのビルドが必要であったり、/dev/gpiomem に対応しておらず、root 権限でないと GPIO の制御ができないように見えたので、軽量かつ、/dev/gpiomem を制御し、root 権限が不要な servebox/taopaipai を利用しました。

参考 Raspberry Pi でLチカする方法がたくさんありすぎる件について

残課題

Delta の検知からのコールバックが、一定時間立つと動作しなくなってしまう問題

設定の見直しや、SDK を変えて、オプションを渡してみて、調整するしか無いのかという感じです。難航

shadow_client.register_delta_callback(delta_callback)

実用に向けた AWS Stack からのつなぎ込み

IoT Core のデバイスは、単体では意味ないのでいずれかの AWS Stack へのつなぎ込みが必要だと思います。

Lambda と API Gateway とつなぎこめば、REST のリクエストで呼び出すことができるようになり気軽にパトランプが回せるようになるので、最初の目標はそこにしたいと思っています。

おわり

課題はまだあるのですが、アドベントカレンダードリブンで、開発が進められたので良かったです。AWS IoT Core はインターネットの世界から物理デバイスに干渉する手段を与えてくれます。また、AWS Stack に乗っかってしまえば Amazon Alexa とのつなぎ込みもできりゃいます。ワクワクします。普段業務で使う ASW Stack 以外も面白いものはたくさんあるし、まさかこれを使うなんてという日が来るかもしれません。いろいろさわって遊んでみて、損はないなーと思いました。

明日は、@miyarappo さんがサブスクリプションビジネスのお話を書く様です。

お楽しみにー