2017/08/24
来訪者向け受付システムを作った話

経緯
2017年7月22日、弊社は神泉町から南平台 (住所は道玄坂) に引っ越しました。 〒150-0043 東京都渋谷区道玄坂1丁目16-10 渋谷DTビル 7F 新しいオフィスの入り口にはインターホンが付いておらず、来訪者のための呼び鈴に相当するものを何かしら用意する必要がありました。そこで社内で検討した結果、以下の 3 案が上がりました。- 一般的なドアホン
- 電話機
- iPad を使った受付システム
要件
時間もリソースも限られているので最小限な要件を作りました。- 来訪者が iPad をタッチする
- 待合室、執務室双方にチャイム音が鳴る
- Slack に来訪者が来た旨を通知する
- 来訪者の顔をキャプチャして Slack に通知する
- 来訪者にスタッフを呼び出している旨を伝える
システム構成
まず試したのは、iPad と Bluetooth スピーカーを使った構成です。 この構成には 3 つの問題がありました。
この構成には 3 つの問題がありました。
- iPad のスピーカーで音が出せない
- Bluetooth 接続が途切れる
- 音声信号が乱れる
1. iPad のスピーカーで音が出せない
Bluetooth スピーカーを執務室に設置し、iPad の音声出力を Bluetooth スピーカーに向けた場合、待合室に設置した iPad からは音が出なくなるため、来訪者は呼び出しが正常に行われたことを視覚のみでしかフィードバックを得られません。実際に体験してみると、聴覚によるフィードバックもあった方が安心感が得られることがわかりました。2. Bluetooth 接続が途切れる
実装方法の問題かも知れませんが、一旦 Bluetooth スピーカーに接続し、オーディオファイルを再生したのち、しばらくすると Bluetooth スピーカーの接続が自動的に切れる現象に遭遇しました。Bluetooth スピーカーとの接続を監視してみると、おおよそ10〜15分程度で接続が解除されることがわかりました。これについては解決策がわからなかったため、30 秒毎に超音波を鳴らして接続をキープするという方法を取ることにしました。3. 音声信号が乱れる
空っぽの新オフィスで実験している時は問題なかったのですが、実際に什器が設置され、人が入り、Wi-Fi が飛ぶようになると Bluetooth で飛ばした音声信号が乱れる現象に遭遇しました。これについては解決の糸口がすら見出せずに終わりました。 以上の 3 点から、システム構成を考え直すことにしました。 Raspberry Pi を経由することで、無線通信は API 呼び出しのみ、音声信号は有線で接続という構成を作りました。 構成がやや複雑になったものの、初期の構成で問題になった 3 点はいずれも解消します。
構成がやや複雑になったものの、初期の構成で問題になった 3 点はいずれも解消します。
レシピ
材料
ハードウェア
- iPad
- Raspberry Pi 3
- Bluetooth スピーカー
- iPad スタンド
ソフトウェア
- オーディオファイル
- API サーバー
- iPad アプリ
1. オーディオファイルファイルを作る
一般的なドアホンのようなチャイム音のオーディオファイルについて、初めはフリー素材を探してみました。ところがいざやってみるとちょうど良いフリーのオーディオファイルを探すというのは案外面倒でした。そこで Ableton Live を使い手元で作ってしまうことにしました。ピアノロールで MIDI を書く
前オフィスのドアホンの音を耳コピしてみたところ、メジャースケールで3度、1度の順で鳴らせば良さそうなことがわかりました。なんとなく気分でC#メジャースケールを採用することにしました。 音色はシンプルにサイン波を使います。立ち上がり (Attack) が速くて、余韻 (Release) を少し長め (3秒) にすると良いです。
音色はシンプルにサイン波を使います。立ち上がり (Attack) が速くて、余韻 (Release) を少し長め (3秒) にすると良いです。
 出来たものを Live から .wav で書き出し、iOS で再生するために .caf ファイルも作っておきます。.caf ファイルへの変換は Mac に入っている (要 Xcode?) afconvert を使います。
出来たものを Live から .wav で書き出し、iOS で再生するために .caf ファイルも作っておきます。.caf ファイルへの変換は Mac に入っている (要 Xcode?) afconvert を使います。
% afconvert -f caff -d LEI16 sound.wav sound.caf 
2. API サーバーを作る
Perl と Dwarf (Web Application Framework) を使って JSON API を作成します。サーバーは Raspberry Pi 3 です。Raspberry Pi を使うのが初めてだったので、OS は標準の raspbian を使い、Perl もプリインストールされているものをそのまま使います。 必要な CPAN モジュールは Carton でインストールします。あらかじめlibssl-dev だけ apt-get でインストールしました。
作った API は一つだけです。呼び出されたらオーディオファイルをバックグラウンドで再生するという非常にシンプルな API を用意しました。
package App::Controller::Api::Visitor;
use Dwarf::Pragma;
use parent 'App::Controller::ApiBase';
use Dwarf::DSL;
use Class::Method::Modifiers;
after will_dispatch => sub {
    self->validate(
        mention => [qw//],
        sound   => [[DEFAULT => 'sound'], qw/NOT_BLANK/, [CHOICE => qw/sound test/]],
    );
};
sub post {
    my $sound = param('sound');
    my $path = c->base_dir . "/assets/$sound.wav";
    my $cmd = conf('/audio_player/cmd');
    if ($cmd) {
        system "$cmd $path&"
    }
    return {
    };
}
1;
[Unit]
Description = S2 Reception API Server
[Service]
ExecStart=/home/pi/Desktop/s2-reception/app/script/start_server.sh
Restart=always
Type=simple
[Install]
WantedBy=multi-user.target
3. iPad アプリを作る
まずは簡単な画面イメージを描きました。 iPad 以下に必要な機能は以下です。
iPad 以下に必要な機能は以下です。
- 表示周りの実装
- 音声ファイルの再生
- 静止画のキャプチャ (ただしステルス)
- API に POST
1. 表示周りの実装
Storyboard で画面イメージと同じ画面構成を作り、Segue で遷移を定義します。呼び出し完了画面を表示したら 10 秒で元の画面に戻すためのタイマーを実装しました。var timer:Timer?
override func viewDidAppear(_ animated: Bool) {
    if let t = timer {
        t.invalidate()
    }
    timer = Timer.scheduledTimer(withTimeInterval: 10.0, repeats: false) { [unowned self] (timer) in
        self.performSegue(withIdentifier: "unwindToViewControllerSegue", sender: nil)
    }
}
override func viewWillDisappear(_ animated: Bool) {
    if let t = timer {
        t.invalidate()
    }
}
2. 音声ファイルの再生
AVAudioPlayer を使い、オーディオファイルを再生します。var player:AVAudioPlayer!
func initAudio() {
    if let url = Bundle.main.url(forResource: "sound", withExtension: "caf") {
        do {
            player = try AVAudioPlayer(contentsOf: url)
            player.prepareToPlay()
            player.numberOfLoops = 0
            player.volume = 1.0
        }
        catch {
            print(error)
        }
    }
}
func playSound() {
    if let p = self.player {
        p.currentTime = 0
        p.play()
    }
}
3. 静止画のキャプチャ (ただしステルス)
受付が行われるタイミングで画像を撮影します。ただし、「カシャッ」という音が鳴ると来客を不穏な気持ちにさせるので、ステルスで撮影を行います。詳しい実装は割愛しますが、AVFoundation を使い動画のフレームを AVCaptureVideoDataOutput で取り出し、来客が呼び出しボタンを押したタイミングで動画のフレームを静止画に変換する方法を使いました。4. API に POST
URLSession で API 呼び出しを実装します。class func postToAPI() {
    let url = URL(string: "http://reception-sound-rpi.s2factory.co.jp:11022/api/visitor")!
    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    let task = session.dataTask(with: request, completionHandler: {
        (data, response, error) in
    })
    task.resume()
}
var data = Data()
data.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
data.append("Content-Disposition: form-data; name=\"channels\"\r\n".data(using: String.Encoding.utf8)!)
data.append("\r\n".data(using: String.Encoding.utf8)!)
data.append("#reception\r\n".data(using: String.Encoding.utf8)!)
data.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
data.append("Content-Disposition: form-data; name=\"file\"; filename=\"reception.jpg\"\r\n".data(using: String.Encoding.utf8)!)
data.append("Content-Type: image/jpeg\r\n".data(using: String.Encoding.utf8)!)
data.append("\r\n".data(using: String.Encoding.utf8)!)
data.append(UIImageJPEGRepresentation(image, 0.7)!)
data.append("\r\n".data(using: String.Encoding.utf8)!)
data.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
雑感
引っ越して約1ヶ月。作ったシステムは今のところ安定して稼働しています。今後の改善案として、画像認識技術などを使って「誰が来た」という情報を自動で判別するようなことに挑戦してみたいです。現状 Slack には「誰か来たよ」といった程度の情報しか流せていないのですが、もう少し具体的に「佐川さんが来たよ」「ヤマトさんが来たよ」という情報を流せると良さそうです。一般的に来訪者に「目的」を選ばせる形で実現させるものが多いかと思いますが、来訪者の負担にせずに自動的にシステムで解決する、と少しだけ未来を感じられそうです。 また、今回のシステム制作の過程で Bluetooth オーディオは少し距離が離れると難しいということが体感出来たのは良い収穫でした。 ちょっとした社内システムを実際に作ってみることで技術習得を行うという手法はあらゆる面でオススメです。
S2ファクトリー株式会社
様々な分野のスペシャリストが集まり、Webサイトやスマートフォンアプリの企画・設計から制作、システム開発、インフラ構築・運用などの業務を行っているウェブ制作会社です。
実績
案件のご依頼、ご相談、その他ご質問はこちらからお問い合わせください。





