ひかり電話に着信があったら、相手さんの名をGoogle Homeで叫ぶようにしてみた

事始め
---

家庭用電話機は、取扱説明書の分厚さでわかる通り、とにかく多機能です。（とはいえ、中身はあまり見ていませんが．．．）
とりわけ特殊詐欺、勧誘電話、迷惑電話などのガード機能はとても役立ちます。電話帳に登録しているか否かで鳴り分けもできます。
しっかり設定しておけば犯罪に巻き込まれることは少ないと思いますが．．．
でも残念かな、所詮家庭用電話機はレガシィ・デバイス。そんな家庭用電話機とGoogle Homeをコラボさせ、電話システムをちょっとスマートな感じにさせてみました。

↓こんな感じにです。
「**着信したら相手さんの名を叫ぶよ feat. Google Home**」

感謝その１
---

実現するにあたり下記記事を参考にしました。その内容を~~ほぼコピペ~~若干修正した内容になっています。わかりやすい内容でとても助かりました。ありがとうございます。

- [Raspberry Piで自宅にかかってきた電話番号をLine通知してみた](https://qiita.com/haradaj/items/c3669e14d430bf234a42)


感謝その２
---

PythonやSQLiteについて**ずぶの素人**なので、下記を~~ほぼコピペ~~参考にしました。ありがとうございます。

- [SQLite3でのCSVファイルのインポート](https://qiita.com/Kunikata/items/61b5ee2c6a715f610493)
- [PythonでSQLite3を使う](http://www.mwsoft.jp/programming/python/sqlite3.html)
- [Python の HTTP クライアントは urllib.request で十分](https://qiita.com/hoto17296/items/8fcf55cc6cd823a18217)
- [Python文字列操作マスター](https://qiita.com/tomotaka_ito/items/594ee1396cf982ba9887)

流れ
---

着信がありました。
↓
Asteriskでスクリプトを起動します。
:one:電話帳データベースを検索します。
:two:相手さんの名を三回叫びます。[Google HomeとText-to-Speechで一斉放送システムを作ってみた](
https://qiita.com/somainit/items/1852858c58ea1700eef2)を使います。
:three:IFTTT/Webhooksを呼び出します。着信をいろんなサービスに通知できます。
↓
相手さんの名でもって、**居留守するかどうか**決めます。



ひかり電話ルータを設定します。
---

[Raspberry Piで自宅にかかってきた電話番号をLine通知してみた](https://qiita.com/haradaj/items/c3669e14d430bf234a42)の「宅内ルータの設定」の通りに設定します。

ラズパイを設定をします。
---

####ラズパイのOSバージョンを確認します。

```shell-session
$ lsb_release -a
No LSB modules are available.
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 9.6 (stretch)
Release:	9.6
Codename:	stretch
```

####必要なパッケージをインストールします。

Python2を削除しPython3のみにし、python3-pip、asterisk、sqlite3をインストールします。
旧式ラズパイだとAsteriskインストールに失敗する場合があります。本環境ではRaspberry Pi Zero Wを利用しています。

参考：

- [Raspbian - Bug](https://bugs.launchpad.net/raspbian/+bug/1754306)

```shell-session
$ cd
$ sudo apt-get update
$ sudo apt-get remove python
$ sudo apt autoremove
$ sudo apt-get install python3-pip
$ sudo apt-get install asterisk
$ sudo apt-get install sqlite3
```

####[pyst2](https://pypi.org/project/pyst2/)をインストールします。

Python3版Pystがないので、対応したpyst2をソースコードからコンパイル、インストールします。
PystとはPythonからAsteriskをプログラミングするためのインターフェースとライブラリです。

```shell-session
$ wget https://files.pythonhosted.org/packages/8b/30/e6cafcdd565e857dbc6640a07ab727af9d90c0173a6cac2085e4813bc8ad/pyst2-0.5.0.tar.gz
$ tar -zxvf pyst2-0.5.0.tar.gz
$ cd pyst2-0.5.0
$ sudo python3 setup.py install --prefix=/usr/local
```

####Asteriskを設定をします。

```shell-session
$ sudo mv /etc/asterisk /etc/asterisk.bak
$ sudo mkdir /etc/asterisk
$ sudo chown asterisk:asterisk /etc/asterisk
$ cd /etc/asterisk
```

下記6ファイルは、[Raspberry Piで自宅にかかってきた電話番号をLine通知してみた](https://qiita.com/haradaj/items/c3669e14d430bf234a42)の「Asteriskの設定」の通りに設定します。

```shell-session
$ sudo vi sip.conf
$ sudo vi extensions.conf
$ sudo vi asterisk.conf
$ sudo vi features.conf
$ sudo vi logger.conf
$ sudo vi modules.conf
```

```shell-session
$ sudo chown asterisk.asterisk sip.conf extensions.conf asterisk.conf features.conf logger.conf modules.conf
$ sudo chmod 640 sip.conf extensions.conf asterisk.conf features.conf logger.conf modules.conf
$ sudo systemctl status asterisk.service
```

####SQLite3で電話帳データベースを作成します。

:one:テーブルを作成します。

|テーブル名|説明|補足|
|:--|:--|:--|
|caller_id|電話番号||
|caller_hiragana|氏名（ひらがな）|相手さんの名を叫ぶ時に使います。|
|caller_kanji|氏名（漢字）|IFTTT/Webhooksを呼び出す時に使います。|

```
$ cd /var/lib/asterisk
$ sudo vi caller_table.sql
```

```sql:/var/lib/asterisk/caller_table.sql
create table caller
(
        caller_id       text primary key,
        caller_hiragana text,
        caller_kanji    text
);
```

```shell-session
$ sudo sqlite3 caller.sqlite3
SQLite version 3.16.2 2017-01-06 16:32:41
Enter ".help" for usage hints.
sqlite> .read caller_table.sql
sqlite> .quit
$ sudo chown asterisk:asterisk caller.sqlite3
$ ls -l caller.sqlite3
-rw-r--r-- 1 asterisk asterisk 12288  3月  9 22:44 caller.sqlite3
```

:two:信頼できる相手の電話帳データをcsv形式で作成します。

```shell-session
$ sudo vi phone_book.csv
```

```shell:/var/lib/asterisk/phone_book.csv
09012345678,あおもり たろう,青森太郎
819012345678,あおもり たろう,青森太郎
0171234567,あおもり じろう,青森次郎
```

:three:電話帳データをインポートし、データベースを作成します。

```shell-session
$ sudo sqlite3 caller.sqlite3
sqlite> .mode csv
sqlite> .import phone_book.csv caller
sqlite> SELECT * FROM caller;
09011112222|あおもり たろう|青森太郎
819011112222|あおもり たろう|青森太郎
0171234567|あおもり じろう|青森次郎
sqlite> .quit
```

:four:電話帳データを一件ずつ追加・更新・削除する方法は下記の通りです。

```shell-session
$ cd /var/lib/asterisk

$ sudo sqlite3 caller.sqlite3

sqlite> SELECT * FROM caller;
09011112222|あおもり たろう|青森太郎
819011112222|あおもり たろう|青森太郎
0171234567|あおもり じろう|青森次郎

sqlite> INSERT INTO caller VALUES('0171111111','あおもり さぶ','青森三');
sqlite> SELECT * FROM caller;
09011112222|あおもり たろう|青森太郎
819011112222|あおもり たろう|青森太郎
0171234567|あおもり じろう|青森次郎
0171111111|あおもり さぶ|青森三

sqlite> UPDATE caller SET caller_hiragana='あおもり さぶろう', caller_kanji='青森 三郎' WHERE caller_id='0171111111';
sqlite> SELECT * FROM caller;
09011112222|あおもり たろう|青森太郎
819011112222|あおもり たろう|青森太郎
0171234567|あおもり じろう|青森次郎
0171111111|あおもり さぶろう|青森三郎

sqlite> DELETE FROM caller WHERE caller_id='0171111111';
sqlite> SELECT * FROM caller;
09011112222|あおもり たろう|青森太郎
819011112222|あおもり たろう|青森太郎
0171234567|あおもり じろう|青森次郎

sqlite> .quit
```

####Asteriskのスクリプトを作成します。

```shell-session
$ sudo mkdir /var/lib/asterisk/agi-bin
$ sudo chown asterisk.asterisk /var/lib/asterisk/agi-bin
$ cd /var/lib/asterisk/agi-bin
$ sudo vi incoming.py
```

```python:/var/lib/asterisk/agi-bin/incoming.py
#!/usr/bin/python3
"""
Example to get and set variables via AGI.
You can call directly this script with AGI() in Asterisk dialplan.
"""
from datetime import datetime
from asterisk.agi import *
import sqlite3
import urllib.request

### 相手さんの名をGoogle Homeで叫ぶためのURLを設定します。
###     Google HomeとText-to-Speechで一斉放送システムを作ってみた
###     https://qiita.com/somainit/items/1852858c58ea1700eef2
url_say     = 'http://192.168.3.230:5000/say/?lang=ja&text='

### IFTTT/WebhooksのURLを設定します。
ifttt_event = 'YOUR_EVENT'
ifttt_key   = 'YOUR_KEY'
url_ifttt   = 'https://maker.ifttt.com/trigger/' + ifttt_event + '/with/key/' + ifttt_key + '?'

### Asteriskから着信電話番号を取得します。
agi = AGI()
callerId = agi.env['agi_callerid']

### 電話帳データベースに接続します。
conn = sqlite3.connect('caller.sqlite3')
cur = conn.cursor()

### 着信電話番号を電話帳データベースに保存します。
### 登録済みなら何もしません。未登録なら着信電話番号を登録します。
cur.execute("INSERT INTO caller(caller_id,caller_hiragana,caller_kanji) SELECT ?,?,? WHERE NOT EXISTS(SELECT 1 FROM caller WHERE caller_id=?);", (callerId, None, None, callerId))
conn.commit()

### 着信電話番号を電話帳データベースから検索します。
cur.execute("SELECT * FROM caller WHERE caller_id=?;", (callerId,))
ret = cur.fetchone()
cur.close()

conn.close()

### もし電話帳データベースに「氏名」が登録されている電話番号なら
if ret[1] is not None:
    param_say   = (ret[1] + ' さんから電話です。') * 3
    param_ifttt = 'value1=' + ret[0] + '&value2=' + urllib.parse.quote(ret[2])
### 否なら
else:
    param_say   = '知らない人 から電話です。' * 3
    param_ifttt = 'value1=' + ret[0] + '&value2=' + urllib.parse.quote('知らない人') + '&value3=' + urllib.parse.quote('電話帳データベースに「名前」を登録してください。')

### 相手さんの名をGoogle Homeで叫ぶためのURLを呼び出します。
req_say = urllib.request.Request(url_say + urllib.parse.quote(param_say))
with urllib.request.urlopen(req_say) as res_say:
    body_say= res_say.read()

### IFTTT/WebhooksのURLを呼び出します。
req_line = urllib.request.Request(url_ifttt + param_ifttt)
with urllib.request.urlopen(req_line) as res_line:
    body_line= res_line.read()

sys.exit()
```


```shell-session
$ sudo chown asterisk.asterisk incoming.py
$ sudo chmod 755 incoming.py
```

使ってもらった感想は
---

これ年老いた母親のために作りました。電話機本体の表示部の文字が小さく見づらいので、音声で伝えたほうが便利かな、と思ったからです。
きっと喜んでくれると思ったのですが「うるさいからいらない」と一蹴されました。(=^・^=)