昭和育ちなおっさんたちは黒電話を携帯する夢を実現する...


黒電話魂
メンバー
user
TakSan
@taksan
user
yama_moto250R
@t_yam297
作品ページ
ラズパイにつながればこっちのものです。
と思っていましたが、そうもいきません…

### 4-3. 次に待っていたのはTwilio と格闘 ラズパイにさえつながれば後は余裕だと思っていたのもつかの間、草々にも Twilio との格闘が始まります。

組み込み屋からすると、ネットワーク系の技術は不得意。Webhook 等 Web技術もあまり馴染みなく、もちろんTwilioもド初心者です。
何ができるのかくらいはわかるものの、どこから手を付ければいいかもわからない状況です。
Twilio は様々なことが様々な言語でできるのでドキュメントの量も半端なく、調べ始めると情報の海に飲み込まれてしまいます。 電話の基本機能である通話機能の実装なのだから、パパっと簡単にできると勝手に勘違いしていましたが、実際やってみると結構大変でした。
まずは、とりあえずいくつかサンプルを動かしながらPython使って制御すればいいのかなと、普通に通話になるところまでは動作させれました。
すんなりいったのはここまでで、その後は些細なことでいろいろ日々つまづきつつ少しずつ進めていたのですが、大きく以下の3つの壁につまづきました。

#### 1. Twilio050電話を呼出すと即繋がる問題 普通の電話の通り呼出ベルが鳴りだして、受話器を持ち上げてから通話を始めるようにしたいのですが、対抗スマホから電話して呼び出すとすぐにつながってしまいます。
⇒一旦キューに入れて、受話器を上げてからキューから取り出す方法を教えてもらい対応しました。 #### 2. 切れてしまう問題 電話が繋がったら受話器を置くまでは通話したいのに、TwiML に何も書かないとすぐに、切れまうし、無音の音声等を再生すると再生が終わると切れてしまうし、を書いて特定時間待たせるとタイムアウトまでは続くけどその後切れるし、といった具合です。
⇒解決はしませんでしたが、途中から 3. の問題で SIPフォンに転送することになったので、対応不要となりました。SIPフォンに転送後は通話が終わるまで通話が継続してくれるようになりました。 #### 3. 音声が通らない問題 回線はつながるようになったのですが、普通に音声が通りません。スマホとの会話してみても全く音が流れません。
スマホに入れたブラウザフォンでは会話ができたし、回線さえつながれば会話できるものと勝手に勘違いしていました。 問題となるのは音声ストリームです。スマホ(Android/iPhone)では音声ストリームを Twilioの回線に流す仕組みが備わっているが、PC等はブラウザの機能で実装されていて Java で実装を行わないといけないそうです。
⇒SIPフォンに転送して、音声通話はSIPフォン上でやると良いという事を助言いただき対応しました。
Twilio の使いこなしに、色々と迷走しなんだかんだと2か月以上かかってしまいました。
でも、なんと言っても相談できるエバンジェリストの存在は貴重です。QAやWeb会議での相談まで大変お世話になりました。
### 4-4. SIP phone もなんだかんだ苦労しました。 ラズパイのSIPクライアントには、実用例の多い「PJSIP」にて設定を行っていましたが、なぜか着信時の「自動応答」オプションが正常に動作しないため「Linphone」に変更したところ、「自動応答」が正常に動作しました。
またGUIモードでは「録音」「発着信履歴」「音量調整」など操作が簡単でしたので「Linphone」に変更して、作業を進めることになりました。
##### [参考]
[「PJSIP」 NanoPi NEOをSIP電話機にする 前編](https://gato.intaa.net/archives/8276)
[「Linphone」 NanoPi NEOをSIP電話機にする 中編](https://gato.intaa.net/archives/8579)

ラズパイ上でLinphonを起動するとこのような待機状態となります。
ラズパイ上でLinphonを テスト用のSIPサーバーとして「RasPBX – Asterisk for Raspberry Pi」を設定した別のラズパイを用意し、「Linphone」を導入したラズパイと、SIPアプリの「AGEphone」を導入したスマホの間で、通話できることを確認しました。
##### [参考]
[「RasPBX 」](http://www.raspberry-asterisk.org/downloads/)
[「AGEphone」](https://www.ageet.com/agephone)

今回はTwilioのSIPサービスを利用するため、ユーザーコンソール で設定した「SIPドメイン」を確認し

TwilioのSIPサービス設定 ***.sip.twilio.com アドレスをLinphoneにSipサーバーの設定します。

LinphoneにSipサーバーの設定 - 通信方法 050 のSIP通信は通常グローバルIPアドレスが必要となりますが、今回はプライベートIPアドレスで通話可能とするために ngrok のサービスを利用し解決しました。
しかし無料プランでは発行されるURLが固定できず「黒電話ユニット」を通話待機状態にするためには ラズパイをリモートし毎回変化するURLをコマンドに追加する必要がありました。
当初は「モバイルルーター」+「OCNモバイルSIM」を使用し「ラズパイ」と「PC」を接続して、 テストを行ってきましたが、途中からラズパイ+USBモデム+ソラコムSimに変更しました。

- SORACOMでネットに接続しリモートも可能に SORACOMには、 Napterというサービスがあり、ソラコムユーザーコンソール の SIM 管理メニューからポートと有効時間を指定すると「一時的にアクセス元が限定されたIPアドレスとポート」が構成されます。

IPアドレスとポート ラズパイ起動時に「USBモデムでソラコムに自動接続する」ように設定しておくと、SORACOMの回線経由で直接ラズパイをVCNでリモート可能になります。

## 5. まとめ そんなこんなで、無事に黒電話の電話化に見事に成功しました。 Twilio 様様ですね。
ノイズやエコー問題等課題はあるので、ハードはもう少しチューニングが必要そうですが、アナログ回路なので長い戦いになりそうですが、そのあたりはおいおい。

というわけで、役目を終えそうになっていた黒電話も、昭和育ちのおじさんたちも共に大満足です。
共にまだまだ出番はありそうです。
苦労しただけあり Twilioの使い方コツみたいなのがわかった気がしますし、他の用途や活用法等可能性も感じられるようになりました。また是非他にも使ってみたくなりました。
## 6. ギャラリー - 何処へでも持っていきたくなる黒電話♥ 小道 道脇 小山 木陰

- 何処へ持って行っても映える黒電話♫ 地蔵尊 滑り台 ベンチ

- まだまだ増殖、攻めの予感🎉
勢ぞろい ピンク電話 ## 過去の動画 [Twilioコンテスト応募時の動画](https://youtu.be/QMdDVPmwybA) ## 7. Wow 古き良きアナログ技術に触れ、 Twilio という素晴らしいサービスで大満足です!
**夢の為にとてつもない労力**を使い果たしてしまいました(゚Д゚;)
### 【変更履歴】 - 10/9 図や写真を大幅に入れ替え。 - 11/15 ヒーローズリーグに向けて、動画を差し替え - 11/24 インフラ担当さんが書いてくれた記事を関連リンクに追加。 - 11/28 インフラ担当により 4-4 を追記 。 - 12/4 全体見直し・追記。

メーカーサイト製品ページ: [PIC疑似電話交換機キット](https://www.tristate.ne.jp/etc02.htm) メーカー: [(有)トライステート様](https://www.tristate.ne.jp/) これは、2つの電話機を繋ぐと、呼出ベルを鳴らしたり通話ができる、インターフォンの様な機能を持つ製品です。一般のアナログ電話機を直接つなぐことができるインターフェースがあるので、それを改造することにしました。
- 制御CPUである Arduinoからの制御で動く - 制御信号を Arduino に出力する - 音声分離回路を介して音声の入出力を行う。
オリジナルは PICマイコンに入っているソフトウェアで制御していますが、中身は未公開のブラックボックス状態ですので、解析し代わりの制御ソフトを自作しました。
なお、本記事作成に当たって、本キットの開発製造元である (有)トライステート様に、以下の条件の基回路図の使用や改造した物を使っての記事の投稿と、コンテストへの応募について許諾頂いています。もし、記事を見て参考に制作等される場合はご留意ください。

許諾条件:
1. トライステート製の「PIC疑似電話交換機キット」を使用した旨。 2. 改造で起こった諸問題は、自己責任である旨。
### 1-3. Arduino

黒電話インターフェースのハードウェア制御にArduinoを使用しています。
主に以下の機能を実装しています
- 受話器状態と回線状態の監視 - ダイヤルパルスの検知 - ベル音やトーン音のパルス出力 - リレーによる回線の切り替え制御 - エラーやキャンセルに伴う状態遷移制御 - ラズパイとのシリアルインターフェース (ATコマンドもどき)
ラズパイとUSBシリアルでつなぎやすかったので PICマイコンではなく、Arduinoに載せ替えました。
ラズパイとはUSBケーブルで接続されていて、シリアル通信にてカスタムATコマンドベースで会話しています。
| ATコマンド | 動作 | |:-----------|:------------| | AT\\ | 待ち受けに戻す | | ATDPxxxxxx\\ | xxxxxxにダイヤルする | | ATA\\ | 着信に応答する | | ATH\\ | 切断する | | 結果コード | 意味 | |:-----------|:------------| | \\OK\\ | OK応答 | | \\ERROR\\ | エラー応答 | | \\CONNECT\\ | 接続完了 | | \\RING\\ | 着信アリ | | \\NO CARRIER\\ | 切断された | ### 1-4. ラズパイ #### 1-4-1. サーバー部 Pythonベースで自作したサーバ簡易WebサーバーでArduinoとの通信をおこないます。 主に以下の機能が実装されています。 - Webhookを受信して動作し TwilioやSIPフォンからの POST/GETメッセージを処理する。 - TwiML 等の XML ファイルのGET要求に対してファイルを送信する。 - Arduino とシリアル制御信号を送受信し、受け取ったATコマンドに応じて TwilioやSIPフォンで回線制御を行う。
つまりはラズパイがモデムのように動く感じです。

#### 1-4-2. SIPクライアント LinphoneというSIPクライアントソフトウェアを使用。
ラズパイから通話音声ストリームを流すために使用します。 Twilioで回線制御はできるものの、音声ストリームの通信自体はスマホ向けでしか実装されておらず 他はブラウザの機能に頼っているとのことです。そしてラズパイではその実装がなかったため、SIPフォンに転送することで音声通話を実現しています。 Twilio にはSIPフォンとしてレジストしておき、接続できてから転送する形で使用します。 #### 1-4-3. ngrok Webhook使用者の間ではお馴染み(?)の、ローカルアドレスを外部グローバルアドレスとして公開できるサービスを使用しました。
Twilioのサンプル等でも使用されています。 - グローバルアドレスへのアクセスをラズパイ内部の特定ポートへと通信を通すために使用。
今のところフリーだと時間制限があってアドレスが変わってしまうので、課金して時間制限解除を検討中 #### 1-4-4. USBオーディオ ラズパイには標準ではオーディオ出力インタフェースしかなく音声を入力できません。そこで、USBに刺すピンジャック入出力タイプの音源を外付けし音声分離回路に接続しました。 - ALSA準拠のオーディオとして認識され、音声の入出力インタフェースとして動作。 音声分離回路 ### 1-5. 音声分離回路 電話機からの信号は基本2本線ですがその信号ラインには、スピーカーとマイクの信号が一緒に乗っています。それを分離するための回路です。こちらは自作しました。 - 受話器のマイクからの信号をラズパイに繋いだ USBオーディオのマイクジャックに接続。 - ラズパイに繋いだ USBオーディオのスピーカージャックからの信号を受話器のスピーカーへの信号に接続。 ## 2. 処理の流れ 番号エラーや話し中を含め、途中で発呼をやめるパターン等、異常系を全て載せたら切りがないため、以下正常系の2パターンで説明します。 - 黒電話からかけて黒電話から切断 - 相手側スマホからかけてスマホから切断 ### 2-1. 黒電話からかけて黒電話から切断 シーケンス図1 #### ①ダイヤル開始 (1)~(2) 受話器を持ち上げると、Arduino 側で検知して音声ラインからトーン音を出す #### ②発呼番号確定 (3)~(5) ダイヤルパルスを数えて、発呼先の電話番号を確定させダイヤルコマンドを送る。 #### ③発呼 (5)~(7) ラズパイから Twilioを呼び出して発呼先電話を呼び出す。 #### ④呼び出し (8)~(9) 相手が受話器を取ったらそれをTwilio経由でラズパイに通知する。 #### ⑤保留 (10)~(11) 相手に繋がったら転送をキューに入れて保留し、SIP電話に転送する。 #### ⑥応答 (12)~(13) SIP電話は自動応答にしているのでTwilioを通じてラズパイまで繋がったという応答が返る。 #### ⑦通話開始 (14)~(15) ラズパイから ATコマンド応答で接続を通知し、回路反転リレーと通話リレーを切り替えて通話状態になる #### ⑧受話器を置く (16)~(19) 受話器を置いたことをきっかけに切断の ATコマンドをラズパイに送り、回路反転リレーと通話リレーを切断状態にする。 #### ⑨切断指示 (20)~(21) Twilio から SIP電話へ切断を指示する。 #### ⑩切断応答 (22)~(24) 切断応答を返して通話を終了。 ### 2-2. 相手側スマホからかけてスマホから切断 シーケンス設計の一部2 #### ①着信開始 (1)~(2) 相手側が電話の受話器を上げ Twilioで管理されている電話を呼び出す。 #### ②ベル鳴動 (3)~(5) Twilio からラズパイ経由して疑似交換機まで着信信号を伝えベルを鳴らす。 #### ③呼び出し側は保留 (6) Twilio にはいったん着信を指示してキューに入れ呼び出している間保留する。 #### ④応答 (7)~(8) 黒電話が応答の為に受話器を上げると、応答したことがラズパイに伝わる。 #### ⑤転送 (9),(11) 保留になっていた呼び出しを SIP電話に転送して呼び出す。 #### ⑥通話切替 (10),(12) ラズパイからの応答により回路反転リレーと通話リレーを切り替えて通話状態になる。 #### ⑦相手が応答 (13)~(14) SIP電話は自動応答にしているのでTwilioを通じてラズパイまで繋がったという応答が返り通話が開始される。 #### ⑧通話開始 (14)~(15) ラズパイから ATコマンド応答で接続を通知しリレーを切り替えて通話状態になる #### ⑨相手が切断 (16)~(19) 相手側が受話器を置くとSIP電話に切断が指示されTwilio経由で通話終了が通知される。 #### ⑩終話 (20)ラズパイ側からATコマンド応答で疑似交換機まで切断が通知される。 #### ⑪終話音再生 (21) 受話器が上がっている間、ツーツーという終話音を再生します。 #### ⑫切断 (22)~(24) 受話器がおかれて 回路反転リレーと通話リレーを切断状態にして通話を終了する。 ## 3. 構成写真 構成部品の写真は以下の通りです。 構成写真