ラズパイ+タクトスイッチでSlack用へぇボタン作成してみた

ラズパイに接続されたタクトスイッチを押した時にSlackに「へぇ」と発言するトリビアの泉風のボタンを作ってみました

# できたもの

ブレッドボードに接続されたボタンを押すと以下のようにSlackの特定チャンネルに「へぇ」と発言します。複数回押せばその回数「へぇ」と発言します。

![Screen Shot 2016-03-31 at 11.43.22 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/1eb99968-505a-e3b5-35f2-6f67c4140d56.png "Screen Shot 2016-03-31 at 11.43.22 AM.png")

# 環境

+ ラズパイ3。別に3でなくても良いはず
+ タクトスイッチ
+ ブレッドボード
+ 1kΩの抵抗
+ オスメスジャンパー線3本

# 配線する

以下のように配線しました。
ここは本に書いてあったのをそのままですね。
配線図は[fritzing](http://fritzing.org/home/)というソフトを使って描いてみました。

![qiitatest_bb.jpg](https://qiita-image-store.s3.amazonaws.com/0/20193/f283bdbd-08b5-9a04-2c65-8b258422098c.jpeg "qiitatest_bb.jpg")

実際、こんな感じですね。

![reduce.jpg](https://qiita-image-store.s3.amazonaws.com/0/20193/077b304f-658f-d11a-57e9-b431da84e920.jpeg "reduce.jpg")


# Pythonでボタンが押されたかを取得する

以下のようなプログラムを書きます。

```inputsw.py
# おまじない
import RPi.GPIO as GPIO
import time
import signal
import sys

# Ctrl+CによってSIGINTシグナルが送信された時のハンドラ。終了前にGPIO.cleanupを呼び出す
def handler(signum, frame):
  print 'Signal handler called with signal', signum
  GPIO.cleanup()
  sys.exit(0)

# ハンドラの登録
signal.signal(signal.SIGINT, handler)

# GPIO9を入力として利用
GPIO.setmode(GPIO.BCM)
GPIO.setup(9, GPIO.IN)
before = 0

# 無限ループ
while True:
  # 押された場合には1、押されていない場合0を返す
  now = GPIO.input(9)
  if before == 0 and now == 1:
    print("Push!!!")
  time.sleep(0.1)
  before = now
```

これでプログラム実行中にスイッチが押されたタイミングで標準出力に **Push!!!** と表示されます。中断したい場合には`Ctrl + C`でシグナルを送信して中断します。

```bash
$python inputsw.py
Push!!!
Push!!!
Push!!!
^CSignal handler called with signal 2
```
# Slackの特定チャンネルにへぇと呟かせる

最初から上記に組み込んでもいいのですが、PythonからSlackへの通知は初めてだったので最初はこちらだけのものを実装しました。

確認するとSlackでメンテナンスされているSlack用のライブラリがあったのでこれを使うようにします。

[slackhq/python-slackclient](https://github.com/slackhq/python-slackclient)

まずはインストールします。

```bash
$sudo pip install slackclient
```

公式のReadmeの内容で動くか確認してみます。
なお、`token`の部分については事前に以下のURLにアクセスしてtokenを発行し、発行されたtokenを設定してください。

[slack-token](https://api.slack.com/web#authentication)


```slack.py
import time
from slackclient import SlackClient

token = "xoxp-xxxxx"
sc = SlackClient(token)
print sc.api_call(
  "chat.postMessage", channel="#general", text="Hello from Python! :tada:",
  username='pybot', icon_emoji=':robot_face:'
)
```

実行してみます。

```bash
$python slack.py
```

設定があっていれば以下のようにSlackで表示されます。

![Screen Shot 2016-03-31 at 10.56.07 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/a6dc457e-8372-91c5-143f-7bab90a84b81.png "Screen Shot 2016-03-31 at 10.56.07 AM.png")

メッセージを変えてみます。
日本語を書いているのでUTF-8である旨も追記しています。

```slack.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time
from slackclient import SlackClient

token = "xoxp-xxxx"
sc = SlackClient(token)
print sc.api_call(
  "chat.postMessage", channel="#general", text="へぇ :neutral_face:",
  username='pybot', icon_emoji=':robot_face:'
)
```

![Screen Shot 2016-03-31 at 11.21.28 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/c7d7e9d0-e658-ea7c-6c78-0a1b6a5b0bd6.png "Screen Shot 2016-03-31 at 11.21.28 AM.png")

できましたね。

# ボタンを押したタイミングでSlackでへぇと発言させる

単純に先ほどのプログラミング内容を最初に作成した`inputsw.py`に持って行きます。

```inputsw.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import RPi.GPIO as GPIO
import time
import signal
import sys
from slackclient import SlackClient

def post(sc):
  print sc.api_call(
    "chat.postMessage", channel="#general", text="へぇ :neutral_face:",
    username='pybot', icon_emoji=':robot_face:'
  )

def handler(signum, frame):
  print 'Signal handler called with signal', signum
  GPIO.cleanup()
  sys.exit(0)

signal.signal(signal.SIGINT, handler)

GPIO.setmode(GPIO.BCM)
GPIO.setup(9, GPIO.IN)
before = 0
token = "xoxp-xxxxx"
sc = SlackClient(token)

while True:
  now = GPIO.input(9)
  if before == 0 and now == 1:
    print("Push!!!")
    post(sc)
  time.sleep(0.1)
  before = now
```

今回はバックグラウンドで実行してみます。

```bash
$python inputsw.py &
```

この状態でボタンを押すとSlackで発言されます。
複数押せば、押した数分だけ発言されます。

![Screen Shot 2016-03-31 at 11.43.22 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/1eb99968-505a-e3b5-35f2-6f67c4140d56.png "Screen Shot 2016-03-31 at 11.43.22 AM.png")

うざい。

終わらせる時はプロセスをkillしましょう。

```bash
# プロセスIDを確認
$ps aux |grep python
pi        2630  0.4  1.4  18940 13872 pts/0    S    17:41   0:00 python inputsw.py
pi        2639  0.0  0.1   5724  1852 pts/0    S+   17:44   0:00 grep --color=auto python

# シグナルを送信
$kill -KILL 2630

# 終了を確認
$ps aux |grep python
pi        2641  0.0  0.1   5724  1832 pts/0    S+   17:44   0:00 grep --color=auto python
[1]+  強制終了            python inputsw.py

# ボタンを押しても何も発言されない
```

LEDやセンサーと組み合わせて色々するのもやってみたいですね!