Twilio番号でFAXの送受信を行う（Twilio SIP Registration ＋ VoIP アダプターを利用） 

# はじめに
この投稿は[Twilioを使った面白いこと・Twilioの無駄遣いを共有しよう【PR】Twilio Advent Calendar 2021](https://qiita.com/advent-calendar/2021/twilio-build)の16日目の投稿になります。
Twilio Programmable Faxの解説のようなタイトルになっていますが、この記事は主にTwilio SIP Registration ＋ VoIP アダプターを使って、Twilio番号を固定電話のような形で使う方法の解説となります。
この記事にでてくる[Twilio Programmable Fax](https://jp.twilio.com/docs/fax)は、明日(2021年12月17日)をもちまして、[サービス提供を終了](https://cloudapi.kddi-web.com/news/latest/twilio-programmable-fax-end-of-life-on-december-17-2021)します。今までありがとうございました。
※Twilio Programmable Faxがサービス終了するので、Twilio番号でFAX送受信できる方法を考えました。（というか、密やかにTwilio Programmable Faxの追悼式をおこないましたｗ）


# 実装
さっそく作っていきます。

## SIPレジストレーションの設定

### SIPドメインにアクセスするためのIPアクセス制御リストを作成
今回は、自宅の固定FAX機として利用するため、自宅のIPアドレスからのみ接続できるようにします。
「Programmable Voice」→「SIPドメイン」→「IPアクセス制御リスト」→「Create new Access Control List」をクリック
![スクリーンショット 2021-12-15 22.47.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110436/818fef5c-be65-4e8c-710c-4c461f3abc8d.png)
以下の値を入力します。

| 項目 | 内容 |
|:-----------|:------------|
| ACL Friendly Name | IPアドレスリストにつける名前 |
| IP Address Range Friendly Name | IPアドレスにつける名前 |
| CIDR Network Address | 接続元のIPアドレス　※今回は自宅IP |

![スクリーンショット 2021-12-15 22.55.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110436/4ca88f34-37a0-47d6-cde5-9cce7cfda740.png)
ちなみに、作ったACLに、IPアドレスを追加する場合は、該当のACLの詳細画面から「Create new IP Address Range」をクリックします。

### SIPドメインにアクセスするためのユーザー（クレデンシャル）を作成
「Programmable Voice」→「SIPドメイン」→「クレデンシャルリスト」→「Create new Access Control List」をクリック
![スクリーンショット 2021-12-15 23.03.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110436/913a5e55-2af3-7551-2cc0-b81632491552.png)
以下の値を入力します。

| 項目 | 内容 |
|:-----------|:------------|
| Friendly Name | ユーザー（クレデンシャル）リストにつける名前 |
| Username | 接続するためのユーザー名 |
| Password | 接続するためのパスワード ※複雑なものを設定すること。 |

![スクリーンショット 2021-12-15 23.08.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110436/dd822be5-051b-01b2-064f-cdaaa202980d.png)

### SIPドメインの作成
「Programmable Voice」→「SIPドメイン」→「ドメイン」→「Create new Access Control List」をクリック
![スクリーンショット 2021-12-15 23.13.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110436/871033d1-4bc7-d977-d1ca-1232599ae63a.png)
以下の値を入力します。

| 項目 | 内容 |
|:-----------|:------------|
| Friendly Name | SIPドメインの名前 |
| SIP URI | SIPで利用するURI ※重複不可 |
| IP ACCESS CONTROL LISTS | 上記で設定したIPアドレスリスト |
| CREDENTIAL LISTS | 上記で設定したユーザー(クレデンシャル)リスト |
| IP ACCESS CONTROL LISTS | 上記で設定したIPアドレスリスト |
| SIP Registration | ENABLEDを設定 (SIPレジストレーションを利用するかどうか） |
| SIP Registration CREDENTIAL LISTS | 上記で設定したユーザー(クレデンシャル)リスト |
※Call Control Configurationは後で設定します。
![スクリーンショット 2021-12-15 23.27.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110436/d76276d8-5e60-e02e-6bc0-6a737f81c64d.png)
![スクリーンショット 2021-12-15 23.28.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110436/bbfc70e9-9e1f-ba3e-8536-102314db7fc5.png)

## 着信・発信の処理を作る
今回はTwilio Functionsを利用して作成します。
「Functions」→「Services」→「Create Service」をクリック
![スクリーンショット 2021-12-16 0.40.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110436/0cb70949-7cae-9c8a-4c24-9b4eca0f4054.png)
Service Nameには、サービス名を入力します。

### 着信をSIPへ転送する
Twilio番号に着信があったものをSIPへ転送するための処理を作成します。
「Add」→「Add Function」をクリック
![スクリーンショット 2021-12-16 0.59.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110436/a74753d5-7670-e0f7-9f9d-924558456c15.png)

Functionを作成します。パスを指定し、以下のソースコードを入力し、saveをします。

```javascript:/incoming
exports.handler = function(context, event, callback) {
	let twiml = new Twilio.twiml.VoiceResponse();
  twiml.dial().sip('sip:ユーザー名@SIPドメイン名.sip.twilio.com');
  return callback(null, twiml);
};
```

### SIPから発信する
SIPからの発信は、Twilioから呼び出されたWebhookで電話発信するTwiMLを返すことで、電話を発信することができます。上記と同様にFunctionを作成します。パスを指定し、以下のソースコードを入力し、saveをします。

```javascript:/outgoing
exports.handler = function(context, event, callback) {

  // 宛先を取得
  const to = event.To || '';
  const toNumber = to.indexOf("@") > 0 ? to.substring(4, to.indexOf("@")) : '';
  const to_number = (toNumber.substring(0,1) === '+' ? toNumber : '+81' + toNumber.substring(1));

  // 宛先に外線発信
  let twiml = new Twilio.twiml.VoiceResponse();
  const dial = twiml.dial({
    callerId: 'Twilioで購入した電話番号'
  });
  dial.number(to_number);
  return callback(null, twiml);
};
```

### 着信・発信の処理に割当
まず、Functionsをdeployします。
![スクリーンショット 2021-12-16 1.17.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110436/92a70906-7153-dff7-f933-01c086684570.png)

### 着信を割り当て
着信したい電話番号に、割り当てます。
「Phone Numbers」→「該当電話番号を選択」→「Voice & Fax」に以下を入力


| 項目 | 内容 |
|:-----------|:------------|
| A CALL COMES IN | Function |
| SERVICE | 上記で作ったFunctions名 |
| ENVIRONMENT | ui |
| FUNCTION PATH | 着信用に作ったパス |

![スクリーンショット 2021-12-16 1.24.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110436/c9d86824-b757-2786-3b6c-a80373e3a93a.png)


### 発信を割り当て
SIPドメインに、割り当てます。
「Programmable Voice」→「SIPドメイン」→「ドメイン」→「該当ドメイン」を選択。
Call Control Configurationを設定します。
※SIPドメイン設定画面では、FunctionsはFunctions(Classic)しか選択ができないので、URLを指定することにします。
 
上記で作ったFunctionsの発信用FunctionのURLをコピーします。
![スクリーンショット 2021-12-16 1.20.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110436/7336f2ee-2f2c-6187-af37-cdf63aa14acb.png)

そのURLを「Call Control Configuration」の「A CALL COMES IN」に設定します。
![スクリーンショット 2021-12-16 1.34.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110436/54a7c279-98a3-c3fc-4a10-2e93a59cbb33.png)


##　VoIPアダプターの設定
今回、VoIPアダプターは、[Grandstream HT801](https://www.amazon.co.jp/dp/B0764DKC91)を使います。
![スクリーンショット 2021-12-16 1.47.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110436/60553d1a-844d-aeb9-544a-2e9a8862180f.png)
マニュアルなどは以下。
[User Guide](https://www.grandstream.com/hubfs/Product_Documentation/ht80x_user_guide.pdf?hsLang=en)
[Administration Guide](https://www.grandstream.com/hubfs/Product_Documentation/ht80x_administration_guide.pdf)

### IPアドレスの確認
設定画面にアクセスするため、IPアドレスを確認します。
電源、LANケーブル、モジュラーケーブルを接続します。モジュラーケーブルの先は普通の電話機に接続します。
電話機の受話器をとり、＊(アスタリスク）を3回pushします。
「ENTER A MENU OPTION」という音声が聞こえるので「02」とpushします。
「IP ADDRESS」という音声の後で、英語でIPアドレスが音声で聞こえます。

### ブラウザで設定画面にアクセス。
http://（IPアドレス) にアクセスします。
ユーザーIDとパスワードを聞いてくるので、両方とも「admin」と入力します。
※初期設定の場合は、その様になっています。

### 設定をする
[FXS PORT]の設定画面で、以下の部分を変更する。他はデフォルト。

| 項目 | 内容 |
|:-----------|:------------|
| Primary SIP Server | 登録したSIPドメインのURI |
| SIP User ID | 上記で作ったユーザー名 |
| Authenticate ID | 上記で作ったユーザー名 |
| Authenticate Password | 上記で作ったユーザーのパスワード |
| Name | 上記で作ったユーザー名 |
| Fax Mode | Pass-Through ※電話機によっては必要ないかも？|

※余談ですが、設定に「Enable Pulse Dialing」というものがあり、これを設定すると、黒電話も接続可能なのでは？と思っています。知らんけど。

## Twilio Programmable FAXでFAXを送信、SIPで受信してみる。
Twilio Programmable FAXはTwilio CLIで簡単にFAXを送信することができます。
※送信内容はPDF形式でTwilioからインターネットを介してアクセスできる場所に設置する必要あります。

```
twilio api:fax:v1:faxes:create \
    --from (FAX送信元番号)\
    --to (FAX送信先番号\
    --media-url (PDFファイルのURL)
```

# 動作確認
以下のような感じです。
<iframe width="560" height="315" src="https://www.youtube.com/embed/52cO58tiUQs?rel=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

# 最後に
さようなら、Twilio Programmable Fax。とても良いサービスだったと思います。感謝。

# 参考
Twilio Programmable Fax
https://jp.twilio.com/docs/fax

Twilio Programmable Fax リリース時の動画
<iframe width="560" height="315" src="https://www.youtube.com/embed/9PEg7qlPxH0?t=102&rel=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

Twilio Programmable Fax サービス終了のお知らせ
https://jp.twilio.com/changelog/programmable-fax-disabled-new-and-non-active-accounts
https://cloudapi.kddi-web.com/news/latest/twilio-programmable-fax-end-of-life-on-december-17-2021