Slackで現実世界と繋がる


この記事は[Slack Advent Calendar 2014 - Qiita](http://qiita.com/advent-calendar/2014/slack)の20日目の記事です。

Slackを使うことで、現実世界から通知を受けたら便利だろうと思ってやってみた実験の話です。

## 現在のチャット環境

Slackでチャット、会社でも非公認ながら導入して半年以上経ちました。
毎日bot達と戯れる楽しい会話が流れています。
非公認チャットルームなので、使用するメンバーは2,3人しかおらず、誰かが喋ってもすぐに返事がこない場合もあります。
しかしそんな時でもbot達が居るおかげで、ルームに自分しか居ない時でも、ひとりぼっち感はほぼ無いですww

## 常駐チャットメンバー(bot)

- Hubot
- Slackbot

人間3に対しbotは2・・ほぼイーブンです。
というかbot達必ずルーム内に常駐してるので、彼らの方がヌシっぽい感じがしてならない。。（レスポンスもめっちゃ早いし）
HubotとSlackbotは賑やかしメンバーとして日々大活躍です。
最近はSlackbotのレスポンス追加が楽すぎるので、そっちばっかりカスタマイズが進んで、Hubotの返しのバリエーションの無さが気になるくらい。。
やはりブラウザからいろいろ返し方をカスタマイズ出来るSlackbotのユーザーフレンドリー性は凄まじい。。

## IoT(Internet Of Things)とチャット

チャットを活用している系記事を読むと、玄関と連動して人が入って来たことをチャットに通知したり、部屋の明るさをセンサーで見て、部屋に人が居るか通知したりと、現実世界と繋がる系のアツさは頭一つ飛び出てる感じがします。
やはり便利そう・・
・・てか、なにより楽しそう！！
センサー系はチャットと繋がると、一気に便利さが身近になる気がします。

現実世界と繋がるセンサー系ガジェット、私の様なメカに弱い人間でも扱える素晴らしい世の中になりました。
手を出してみない訳にはいきません！

やりたいことと出来ることを吟味した結果（出来ること側に大分寄ったけど・・）

- 給湯室のポットの状態を通知してくれるbot
- チャットから「oyu?」と聞くと、ポットのお湯が準備出来てるか、まだ水かを教えてくれる
- ポットの状態が水→お湯に変わった時、メッセージで通知してくれる
- コーヒーを飲もうと思って給湯室に行ったら、後2分でお湯が沸く状態・・とかいう残念な状況を回避出来ることを目標に

名付けて「pot-bot」を制作してみることにしました。

## とりあえず作ってみたシステム構成

![arduino-node.png](https://qiita-image-store.s3.amazonaws.com/0/5691/e82112e4-ac63-2f74-f183-f2121ce571c0.png "arduino-node.png")

### ざっくり概要

#### センサー部分

##### 構成

- Arduino（センサー側頭脳）
- photochell（照度センサー）
- XBee Wifi（無線通信）
- 携帯用充電器（電池）

##### やっていること

Arduinoの基礎的なモジュールで登場する、照度センサーからの値を毎秒読み取って黙々とサーバーに送信。（ほんとこれだけ）

![arduino-sensor-trim.png](https://qiita-image-store.s3.amazonaws.com/0/5691/7700265a-1dd8-0812-023b-5481c43c55f6.png "arduino-sensor-trim.png")

給湯室にこっそり設置することを想定して、小型化を第一目標に。

送っている値は部屋の明るさを示す数値（範囲：0~1023)
数値が高ければ部屋が明るいと判定。

前提として、給湯室が通常閉め切られ真っ暗状態なので、ポットの「保温」状態を示すランプが点灯したら、ほのかに明るくなるのではないかとの目論見。
（後述するが問題あり）

#### センサーから値受信部分（サーバー）

お勉強用に借りているさくらのVPSにNode.jsで書いたサーバープログラムを配置。
センサーから値だけが送られてくるので、Tcpサーバーを立てて刻々と値を受信する。

#### センサーの値を元にポットの状態を判定してメッセージを送信する部分（サーバー）

値を受信した時に、しきい値より大きければ明るい＝お湯状態(oyu)、小さければ暗い＝水状態(mizu)と判定する。
時々部屋に人が入って来て、しきい値より大幅に明るくなる可能性があるので、お湯の状態が判定出来ない(Unknown)の状態も用意しておいた。
サーバー起動時はUnknownからスタートする。

チャットから問い合わせがなくても、水→お湯に変わった時は通知してほしいな〜と思い、この部分でSlack Incoming WebHooksでメッセージを送る。

#### チャットからの問い合わせを受け付けてポットの状態を返す部分（サーバー）

Slack Outgoing WebHooksでチャット内のメッセージからポット状態を問い合わせる。

この辺りの詳細は準備中にブログにも書いてみました。
[Arduinoで計測したセンサー値をNode.jsのサーバーで受け取る - まりぴよこのブログ](http://mpiyok.hatenablog.com/entry/2014/11/30/002059)

## Slackとカスタムインテグレーション

Slackチャットが社内で非公式なのもあって、まだ無料プランでお世話になってます。
なのでIntegrationは5個しか使えない・・
今使ってるのは

- Hubot
- Google Drive
- IFTTT
- Incoming WebHooks
- Outgoing WebHooks

このうち、Hubotはメンバーとして認知されているので外せないし、既に使っているIncoming, Outgoingはアドベントでもちらりと出てた、[チャットで勤怠管理する「みやもとさん」をリリースしました | @masuidrive blog](http://blog.masuidrive.jp/2014/10/19/miyamoto-san/)で使用中です。
とりあえず一旦勤怠止めてみようかな〜と思ってたところ、使えるIntegrationは5個じゃなくて5種類、だったみたいですね・・
無事2個目のIncoming, Outgoingの設定が出来ました。素晴らしい♪

### Outgoing WebHooks

Slackのページがとても良く出来てるので、ページの説明通りなので、あまり意味ない記事なのですが・・

チャットルーム内からpot-botに話しかけて、お湯の状態を聞いてみるためのフックを設定します。

- Channel : どの部屋の発言を対象にするのか？（Anyで全部屋対象にも出来る）
- Trigger Word(s) : フックを発動するキーワード。上記channelの指定がしてあれば、カンマ区切りで複数ワードを指定出来る。
- URL(s): フック先のサービスのURL。改行して複数指定可。
- Token : payloadに入ってくる固有トークン。受け側でまじめにチェックするつもりがあればこれが含まれているかチェックする。
- Descripttive Label : あんま意味ないので無視で。
- Customize Name : チャネル内で発言するbotの名前になるので、最初に決めたbot名を入れる。
- Customize Icon : botのアイコン（指定した方が愛着 :arrow_heading_up: ）

送られるメッセージはPOSTでpayloadにデータが乗ってくるので、必要に応じて読み取ります。
pot-botは指定URLにPOSTアクセスがあれば、現在のポットの状態を返すだけなので、特にpayloadの中身を読みませんでした。

Outgoing WebHooks のテストで、ポットの状態を聞いてみる↓

![slack_potbot_animation.gif](https://qiita-image-store.s3.amazonaws.com/0/5691/f2bd34a9-ebd6-877a-6305-511684212281.gif "slack_potbot_animation.gif")

Slackbotとhubotがいちいち賑やかしに参加してくれますww

### Incoming WebHooks

水→お湯に状態が変わった時に、botの方からチャットルームにメッセージを送る設定です。
Slack側が発行してくれるURLをサーバープログラムの方に設定しておかなくてはいけないので、コード内にそのまま書くのもイヤだと思い、環境変数から読み取る方式にしました。
設定されてなければメッセージ通知はしない。

- Webhook URL : これをコピーしてサーバーの環境変数に設定。
- Customize Name, Icon : Outgoingのと同じのを設定して、botが同じやつ感を出します。

Incoming WebHooks のテストで、ポットのお湯が沸き、保温状態になったら教えてくれるの図↓

![oyu_message.png](https://qiita-image-store.s3.amazonaws.com/0/5691/556d9e74-aeda-ab3d-601a-a0b3b78f5bbc.png "oyu_message.png")


## とりあえず完成形のコード

サーバー側のコードだけGithubにおきました。
Github経由にすると、サーバーにコードの変更送るのも楽になる。。
[maripiyoko/pot-bot](https://github.com/maripiyoko/pot-bot)

## 問題点

コレで完成！なのですが、１点（非常に大きな）問題点があり・・
ポットのお湯沸いている判定を、電気ポットの保温ランプが点灯していることを、Arduino & 照度センサーで検知しようともくろんでいたのですが、あまりにほのかな明かりだったため、検知出来ず・・・・
照度センサーごときではポットの状態を判別出来ませんでした！！
そもそも論的に失敗している・・・
IoT側のレベルが低すぎて、実用出来てない（涙）

アドベントに間に合わせるために、実験コードのまま、ポットの状態判定でズルしています。（全然関係ない部屋の明るさを送信してポットの状態変更している）

一応第二段として、コードを挟むだけで電圧量が測定できるクリップ？みたいなものを導入してみようかな・・と思ってますが、買うブツの選定がまだ出来ていない・・・
おすすめとかあったら教えてください。。