ラズパイと警告灯で派手にアラートを通知する

こんにちは新卒インフラエンジニアです．
新規事業のインフラ・監視の設計・構築・運用を主にやっております．

さて，弊プロダクトでは，システムに何か異常が起こると監視サービスからslackへ通知が飛んできます．
しかしなんかまぁ…「味気ないな…派手さが欲しいな…」と思いまして，**アラート時に警告灯が光るようラズパイで組んでみました．**
本記事はその実装手順です．色々端折ってますがご容赦ください．
(実装は自己責任でお願いします．電子パーツ，特に電源の取り扱いにはご注意ください)

# 完成イメージ

監視サービス → slack → nginx+php-fpm → 警告灯
slackにアラートが通知されるとランプが点灯し，復旧などが通知されると消灯します．
(以下の動画では手打ちでslackに投稿しています)

![ezgif-3-e839dd9d24f5.gif](https://qiita-image-store.s3.amazonaws.com/0/63946/c4189999-d8cb-926b-c6c6-106c20b44686.gif)


# 手順

1. 準備(パーツ購入)
1. 配線(後日上げます，すいません)
1. ラズパイ設定(webサーバセットアップ，ページ配置)
1. slackのOutgoing Webhooks設定
1. ルータのポートフォワーディング設定

を行います．

- ラズパイの開封～初回起動～ネット疎通
- slackアカウント作成

など前提部分は本記事では取り扱いません．
raspberry piやnginxを少しでも触ったことある人向けに書いているので，端折ってる部分あります．

### 準備

以下を購入しておきます．サブ項目は私が使用したものです．

- Raspberry Pi(GPIOピンが使いたいだけなのでモデルはどれでもよいです)
  - https://www.amazon.co.jp/dp/B07BFH96M3
- 警告灯(今回は12V駆動のものを使います)
  - https://www.amazon.co.jp/dp/B07G94V381
- 電源(購入した警告灯の定格に従いましょう)
  - http://akizukidenshi.com/catalog/g/gM-01804
  - プラグが邪魔な場合は切ってください
- リレー(ラズパイで動かしたいのでトリガー電圧が5Vのものを使います)
  - https://www.amazon.co.jp/dp/B0116IZ9FK

この他，Raspberry Piを動かすためにmicroSDカードやLANケーブルなど要りますが，本記事では割愛します．

### 配線

購入したパーツによりますが，今回は以下のように配線しました．

(力尽きたので後日上げます)

### ラズパイセットアップ

- raspbianを使っています．
- 初回起動の方はインターネットにつなげるところまで設定を進めてください．

**1. GPIOの操作をよしなにやるためにWiringPiというユーティリティをインストールします．**

```shell-session
$ sudo apt-get install wiringpi
```

**2. 確認**

ラズパイ上で`gpio -v`と叩いて，バージョン情報など表示されればインストールできています．

```shell-session
$ gpio -v
gpio version: 2.46
Copyright (c) 2012-2018 Gordon Henderson
This is free software with ABSOLUTELY NO WARRANTY.
For details type: gpio -warranty

Raspberry Pi Details:
  Type: Pi 3, Revision: 02, Memory: 1024MB, Maker: Sony
  * Device tree is enabled.
  *--> Raspberry Pi 3 Model B Rev 1.2
  * This Raspberry Pi supports user-level GPIO access.
```

### nginxセットアップとページ実装

**1. nginxとphp-fpmをインストールします．**

```shell-session
$ sudo apt-get install nginx php-fpm
```

**2. nginxのconfigをいじって，php-fpmを使えるようにしておきます．**
`/etc/nginx/sites-available/default`の`location ~\.php$`部分のコメントを外し，`index`に`index.php`を指定します．
ドキュメントルートは`/var/www/html`です．

```/etc/nginx/sites-available/default
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/html;
        index index.php;
        server_name _;

        location / {
                try_files $uri $uri/ =404;
        }

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        }
}

```

**3. 以下のコードを`index.php`という名前で保存し，上記で指定したドキュメントルートに置いておきます．**
(今回は`/var/www/html/`)

```index.php
<?php
exec("gpio -g mode 2 out");
if (strpos($_POST["text"], "Triggered") !== false){
    exec("gpio -g write 2 1");
}else{
    exec("gpio -g write 2 0");
}
```
<details><summary>コード解説</summary>
`gpio -g mode 2 out`: 2番ピンを出力モードに設定
`strpos($_POST["text"], "Triggered")`: bodyに含まれる"text"部分を抽出，その内容が"Trigger"という文字列を含むかどうかboolで返す
`gpio -g write 2 1`: 2番ピンの値を1にする
</details>

**4. nginxを再起動します．**

```shell-session
sudo service nginx restart
sudo service php-fpm restart
```

**5. 動作確認**

ラズパイ上で`curl -X POST -d "text=Trigger" localhost` と打ってみて，ライトが光ればOKです．
(光らない場合は記事最下部のトラブルシュートをみてください…)

### ポートフォワーディング

- SlackのOutgoing Webhooksを使うために，ルータの適当なポートに穴あけしておいて，LAN外からラズパイへアクセスできるようしておきます．
- ルータによって設定方法が異なるため本記事では説明しませんが，`<ルータの型番> ポートフォワード`で検索すると設定方法が見つかるかと思います．

### Slackの設定

- Outgoing Webhooksを使います．
- これを使うと，「特定のチャンネルに特定キーワードがポストされると，指定したURLへリクエストが送信される」という挙動が実現できます．

**1. Outgoing Webhooksの設定ページまで移動します。**

`https://<ワークスペース名>.slack.com/apps/manage/custom-integrations`

**画面上部の検索窓に「Outgoing Webhooks」と入力してアプリケーションのページへ移動します**
<img width="634" alt="スクリーンショット 2018-12-16 22.01.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/63946/d6b08bca-55cf-1d24-ec4b-d36189ba95e8.png">

**2. Add Configurationより構成を追加します**

- 下記赤枠部分が必須ですので、埋めてください．
  - Channel: 投稿を監視するチャネルを指定します．
  - Trigger Word(s): アラート通知に含まれる文言など入力しておきます．「,」 区切りで複数選択できます。
  - URL(s): ラズパイ上で`curl inet-ip.info` を叩いて返ってくるIPアドレスとポートフォワーディングの設定をしたポート番号を入力します．
     - (9999番を使う例: `123.45.67.89:9999`)
  - 上記入力後、Save Settingsを押します．
  
<img width="614" alt="スクリーンショット 2018-12-16 22.04.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/63946/863874cb-f355-1d86-37c8-ff5a6f0baa06.png">

設定したチャネルに以下のようなメッセージがポストされていればOutgoing Webhooksの設定は完了です。
<img width="552" alt="スクリーンショット 2018-12-16 22.30.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/63946/c0ac4fd7-5145-0737-ad6c-0b027412c766.png">


# 動作確認

outgoing webhooksにて設定したchannelで，トリガーの文言を投げてみましょう．

![ezgif-3-5d07a754b229.gif](https://qiita-image-store.s3.amazonaws.com/0/63946/897d7437-d8ab-8cf2-18b9-1fcb45bc0601.gif)

光ったり消えたりしたら成功です．

動かないときは

- webサーバ，コードの動作状況確認
  - `sudo service nginx status`，`sudo service php-fpm status`
  - `php /var/www/html/index.php`
  - `/sys/class/gpio/gpio2/value` のファイルパーミッション確認
  - など試してみましょう．
- 配線の確認
  - ちゃんとコンセントにさしていますか?
- outgoing webhooksの設定確認
  - トリガーの文言typoしていませんか?
- ポートフォワーディングの設定確認
  - ラズパイ上で`curl -X POST -d "text=トリガーの文言" localhost`を叩くと切り分けできるかと思います．

などみてみましょう．

# 最後に

- 派手でいいね!
- 安上りでいいね!(パトライト，電源，リレーで2000円ちょい程度)
- 先駆者様のおかげで思ったより簡単に実装できた!(実装1時間程度)

# 参考

- [Raspberry Piでスマート照明を作ってみる(リレーモジュールでUSBライトON・OFF編)](https://www.toomath.net/entry/2018/07/22/raspberry-pi-smart-led-control)
- [nginx と PHP-FPM の仕組みをちゃんと理解しながら PHP の実行環境を構築する](https://qiita.com/kotarella1110/items/634f6fafeb33ae0f51dc)
- [SlackのOutgoing Webhooksを使って投稿に反応するbotを作る](https://qiita.com/chike0905/items/58222a99be460f325ab8)