Alexaに部屋の温度と湿度を教えてもらう

#はじめに
Amazon Echoに温度計の搭載が噂されていますが、一足お先にAlexaと温度計の組み合わせを体験してみます。温度計と湿度計が一体化されたセンサーを使って、Alexaに部屋の温度と湿度の両方をも教えてもらいます。センサーの呼び出しと、Alexaスキルのエンドポイントはラズパイで実装します。


##使用環境
- Amazon Echo
- Raspberry PI 3B
- 温湿度センサーモジュールキット(SHT31-DIS使用) 

温湿度センサーは[秋月電子通商](http://akizukidenshi.com/catalog/g/gK-12125/)で購入しました。（通販コード: K-12125）

##おおまかな作業のながれ
1. センサーキットの組み立てとラズパイの配線
2. I2Cインターフェースの有効化
3. Pythonコードの実装
4. Webサーバーの外部公開
5. Alexaスキルの作成

ではやっていきます。

#センサーキットの組み立て

組み立てと言ってもセンサー基盤にピンヘッダを取り付けるだけです。基盤にピンヘッダを通して、基盤の裏面に半田付けします。

![IMG_2265.jpg](https://qiita-image-store.s3.amazonaws.com/0/77444/b4ec13db-65f2-faba-b885-deaa6c8045f3.jpeg)

## 結線方法
センサーとラズパイのピンヘッダの対応です。

|SHT31<br>ピン番号|ラズパイ<br>ピン番号|メモ|
|---|---|---|
|1 (VDD) |1 (3.3V)  ||
|2 (SDA) |3 (SDA) |  |
|3 (SCL) |5 (SCL) |  |
|4 (ADR) |-  |未使用。開放時はアドレスが0x45になる。|
|5 (GND) |6 (GND) |  |

配線例

![IMG_2266 (1).jpg](https://qiita-image-store.s3.amazonaws.com/0/77444/f049df73-4ea1-6a88-9174-5046816c38bb.jpeg)

## 動作確認
I2Cライブラリをインストールします。

```console:Raspbian
$ sudo apt-get install i2c-tools
```

ラズパイのデフォルトではI2Cが無効化されているので、I2Cインターフェースを有効化します。

```console:Raspbian
$ sudo raspi-config
```

「5 Interfacing Options」を選択

![image.png](https://qiita-image-store.s3.amazonaws.com/0/77444/9ef8af33-a605-01a3-dee7-231981e2730f.png)

「P5 I2C」を選択。表示された画面で「はい」を選択。「Finish」でツールを終了します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/77444/caf8aabf-574b-a6f4-2eb0-4e6e57860edb.png)

i2cdetectで信号が取れているか確認します。

```console:Raspbian
$ sudo i2cdetect -r -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- 45 -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
```
アドレス0x45が検出されていれば、機材の準備はこれでOKです。

# Alexaスキルのエンドポイントの実装
ここからは、Alexaスキルと対話するためのエンドポイントを実装します。今回はAWSのLambdaは使用せずに、ラズパイ上にWebサーバを立てて、ngrokを使って外部に公開する方法を取ります。温湿度センサーはPythonコードでアクセスするため、ついでにWebサーバもPythonの簡易HTTPサーバーで手軽に実装しました。

## Python3の簡易HTTPサーバーを使う
ラズベリ側の~/app/sht31ディレクトリにWebサーバーを配置します。

```python:~/app/sht31/server.py
import http.server

server_address = ("", 8000)
handler_class = http.server.CGIHTTPRequestHandler #ハンドラを設定
simple_server = http.server.HTTPServer(server_address, handler_class)
simple_server.serve_forever()
```

いちおうindex.htmlを作成しておきます。

```html:~/app/sht31/index.html
<html>
<body>
  Hello HTTPServer.
</body>
</html>
```

#Alexaスキルの応答コード

PythonのCGIでセンサーの読み取りとAlexaスキルの応答を実装します。コードの前半は温湿度センサーSHT31から値を読みコードです。I2Cのクロックストレッチで1回の転送で6バイトの温湿度データを受信します（[ラズパイマガジン2018年2月号](https://www.nikkeibp.co.jp/atclpubmkt/book/18/265790/)のP111を参考にしました）。後半は読み取った値をAlexaスキルに返すためのJSONを生成しています。

```python:~/app/sht31/cgi-bin/sht31.py
#!/usr/bin/env python3

import datetime
import pigpio
import json

pi = pigpio.pi()
pi.bb_i2c_open(2, 3, 100000)

result = pi.bb_i2c_zip(2, [4, 0x45, 2, 7, 2, 0x2c, 0x10, 2, 6, 6, 3, 0])

if result[0] == 6:
  temp = -45 + 175 * int.from_bytes(result[1][0:2], 'big') / 65535
  humi = 100 * int.from_bytes(result[1][3:5], 'big') / 65535

pi.bb_i2c_close(2)

speak = "この部屋の温度は{0}度。湿度は{1}パーセントです。".format(int(temp), int(humi))

resp = {
  "version": "1.0",
  "response": {
    "outputSpeech": {
      "ssml": "<speak>" + speak + "</speak>",
      "type": "SSML"
    },
    "speechletResponse": {
      "outputSpeech": {
      "ssml": "<speak>" + speak + "</speak>"
      },
      "shouldEndSession": True
    }
  },
  "sessionAttributes": {}
}

print("Content-type: application/json\n")
print(json.dumps(resp))
```

## Webサーバーの起動
pigpioデーモンを立ち上げてから、PythonでWebサーバーを起動します。

```console:Raspbian
$ sudo pigpiod
$ cd /home/pi/app/sht31
$ python3 server.py
```

ngrokで外部に公開します。ngrokのセットアップ方法は「[LINEからGoogle Homeを喋らせる](https://qiita.com/yuppejp/items/64f7769015c8245ee451)」を参考にしてください。

```console:Raspbian
$ ngrok 8000
```

# Alexaスキルの作成
いよいよ、Alexaスキルを作成していきます。[Alexa Skills Kit Developer Console](https://developer.amazon.com/alexa/console/)でポチポチとやっていきます。コードを書いたりする必要はありません。

###新しいスキルの作成

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/77444/3dd56175-02a5-e4d2-0914-c7bbe021512c.png)|
|:-:|

###呼び出し名
「アレクサ、室温」でAlexaが反応するように設定します。

|　![image.png](https://qiita-image-store.s3.amazonaws.com/0/77444/5755eb92-ca4b-3f29-0acf-98d803420b36.png)|
|:-:|

###インテント
今回はカスタムインテントは使用しないのですが、対話モデルに最低1つ要求されるようですので、適当にダミーを作成しておきます。（自信なし）

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/77444/d971767e-34dc-bddf-d64d-9ef36a8c65dc.png)|
|:-:|

###エンドポイント
「HTTPS」を選択し、ngrockのURLに/cgi-bin/sht31.pyを付けたものを指定します。証明書の種類は「開発用のエンドポイントは、証明期間が発行したワイルドカード証明書をもつドメインのサブドメインです」を選択します。

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/77444/1ffeab49-f361-0acb-cafe-915fb41bedba.png)|
|:-:|


## テストしてみる
alexa developer consoleの「テスト」タブで試してみます。入力欄に「室温」と入力すると、温度と湿度が返ってくるはずです。

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/77444/656b194c-a538-598c-790a-e91f0671ffd8.png)|
|:-:|

#完成
これで完成です。自分のアカウントに紐づいたEcho実機に「アレクサ、室温」と呼びかけると、アレクサたんが応答してくれるはずです。温度といっしょに湿度もわかるのは意外と便利です。お試しあれ。