タイトルガバガバですみません。本当は「56Kアナログモデムとラズパイで着信に気づかない問題を解決した」が正しいタイトルです。ダイヤルアップっておっさんホイホイワードなので釣りタイトルになっています。
さて本題。アナログモデムを使用して電話の着信を検出し、何らかの動作をソフトウェアで定義する(Software-Defined)ということをしてみましたのでご紹介します。
課題
会社のエントランスにある受付の電話は、ターミナルアダプタの「AtermIT31L」に接続されていて、ターミナルアダプタの内線通話機能を使用して執務エリアの電話と通話できるようになっています。
課題は、この執務エリアの電話の呼び出し音に気が付かないということです。その理由は、ヘッドホンで音楽を聞いているから。音楽を聞いているときに呼び出し音に気づかず、遠い座席から職員が走ってくることがこれまでに何度もありました。
解決方法
要するに、電話の着信を検出して音以外で知覚できる通知方法を使えばいいわけです。
今回は、アナログモデムとラズパイを使用して電話着信を検出し、回転灯・Slack・社内サイネージから通知をするように構成しました。
実装
使用した機材一覧です。
- Raspberry Pi 3 + 適当なmicroSDカード
- USB 56K アナログモデム「PL-US56K」(生産打ち切り)
- 回転灯「OHM LED回転灯 小 ORL 2(橙)・07-1576」
- ソリッド・ステート・リレー(SSR)キット「秋月電子 K-00203」
- モジュラ2分岐延長アダプタ 「ELECOM AD-MJFBE」
- モジュラーケーブル「ELECOM MJ-T1WH」
Amazon のリンクを貼っていますがヨドバシ・ドット・コムでもほとんど揃えられると思います。
Raspberry Pi のセットアップは省略します。
2分岐アダプタを取り付ける
ターミナルアダプタから出ている電話の着信(執務室)側のモジュラーケーブルを2分岐延長アダプタに挿し、分岐アダプタから2つに分岐している部分に、これまで使用していた電話とアナログモデムを接続します。
これで、これまで使用していた電話とアナログモデムに同じ信号が流れます。着信するとこれまで使用していた電話も鳴動できます。
usbserial として認識させる
USB接続したアナログモデム PL-US56K をLinux上でUSBシリアルとして認識させます。
# modprobe usbserial vendor=0x2019 product=0xab27
このコマンドで /dev/ttyUSB0 のように認識されます。このまま再起動するとこの状態が失われるため、ブート時に自動的に認識できるよう systemd を設定します。ベンダーとプロダクトIDは、lsusb
するとわかります。
/etc/systemd/system/usbserial.service
[Unit]
Description=USB Serial Service
After=udev.target
After=dbus.target
After=avahi.target
After=syslog.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/modprobe usbserial vendor=0x2019 product=0xab27
ExecStop=/sbin/rmmod usbserial vendor=0x2019 product=0xab27
[Install]
WantedBy=multi-user.target
このようなワンショットサービスを定義して、次のコマンドを実行します。
$ sudo systemctl enable usbserial
$ sudo systemctl start usbserial
着信をハンドリングする
この USB シリアルに着信があると「\r\nRING\r\n」が送られてきますので、Node.js を使用してこのRINGをハンドリングします。
※Node.js 環境は予めご自身でセットアップしてください。
Node.js でシリアルポートを扱うライブラリをインストールします。
$ npm install serialport
シリアルポートからの読み出しサンプルコード
var SerialPort = require('serialport');
var dev = '/dev/ttyUSB0';
var options = {
baudRate: 115200
};
var serialPort = new SerialPort(dev, options);
serialPort.on('open', function() {
console.log(dev + ' opened');
serialPort.on('data', function(data) {
if (data.toString().trim() == 'RING') {
//ここに処理を書く
console.log("RING!");
}
});
serialPort.on('close', function() {
console.log(dev + ' closed');
});
});
data.toString() で渡されるRINGは「\r\nRING\r\n」なので、trim() を使用して、両側の改行コードを削除しています。
GPIOでソリッドステートリレーを制御する
$ npm install rpio
GPIOでSSRを制御するサンプルコード
var rpio = require('rpio');
var TIMEOUT = 15;
var PIN = 7;
rpio.open(PIN, rpio.OUTPUT);
rpio.write(PIN, rpio.HIGH); // PIN 7 をHIGHにする
setTimeout(function(){
rpio.write(PIN, rpio.LOW);
}, TIMEOUT * 1000);
SSR で回転灯に通電させてから15秒後に切るような動作をしています。
SSR を組み込んだ AC ケーブルはゲヒルンのエンジニア 9SQ さんに作ってもらいました。
エントランスサービスを systemd に登録する
次のようなサービスを作ります。 usbserial.service の起動を待ってからサービスを起動させます。
/etc/systemd/system/entrance.service
[Unit]
Description = Entrance Ring Manager
After=usbserial.service
[Service]
ExecStart = /usr/bin/node /home/pi/entrance/main.js
WorkingDirectory=/home/pi/entrance/
Restart = always
Type = simple
User=pi
Group=pi
[Install]
WantedBy = multi-user.target
次のコマンドでエントランスサービスを登録します。
$ sudo systemctl enable entrance
$ sudo systemctl start entrance
さいごに
上記実装に、社内サイネージ通知とSlackインテグレーションを加えて、課題を解決したぞ!
※多分、今流行りのタブレットで受付できる製品を導入するほうがいい。