シニアジョブのオフィスの引越にあたり、セキュリティの面からも来客の記録システムが必要になりました。
最初すでにいろんな会社が作ってると思ったので、それ使えばいいじゃんと思いましたが、仕様を聞くとたしかに超簡易的なものなのでまあいいかということで作りました。
とりあえず一通り動くまで2,3日、あとCIとかの環境まわり、デザイナーさんの工数とか入れたら1週間ぐらい?
できたもの
iPadでこんな感じに表示されていて
名前とかいれて呼び出しすると「ピンポーン」という音がして
\ピンポーン/
スプレッドシートに記録されて
Chatworkにも送信されます
システム的には
- Google App Engineで公開されたNuxtJSアプリ(静的ファイル配信のみ)
- GASウェブアプリ(REST API的なもの)で来客リクエスト受け付け + iPadでピンポーン鳴らす
- GASでスプレッドシートにログ書き込み & Chatworkにメッセージ送信
- 備え付けたiPadでこれを開く
だけのシンプルな構成です。
iPadの選定
まずこれから頼まれた。
生まれてからMac製品買ったこと無い人間なので、いろいろ調べてこんな条件で中古で選んで買ってもらいました。
3万ちょっとだった気がする。
- 新しめ(2019)
- 大きめ(10.2インチ)
- WiFiで厚さとかストレージ気にしない
Raspbery Pi + タッチディスプレイも考えたけどめんどいよね。
インフラ選定
NetlifyとかVercelとか便利だけど、スプレッドシートへの書き込みなので、Google内が良さそう。
常時起動の必要はなく、必要なときだけ起動するGoogle App Engine(スタンダード環境)を選びました。
NuxtJSで普通に作ってローカルで動かしたあとapp.yaml作るだけでデプロイ出来ました。
休日開けとかの起動時間がちょっとネックだけど10秒はいかない感じなので今の所常時起動とかはまあいいかなと。
おそらく無料枠に収まるので実質無料では?
サーバー側選定
この記事で詳しく書いたけど結局サーバーサイド的な処理はGASのウェブアプリだけで完結していましました。
もともとGoogle Workplaceはつかってるので実質無料では?
uyamazak.hatenablog.com
CI、デプロイ
これもGitHubのmainブランチへのプッシュをフックにGCPのCloud Buildを設定しました。
権限周りでちょっとハマったけど、無料枠以上デプロイする気がしないので実質無料では?
uyamazak.hatenablog.com
小技集
ピンポーン鳴らす
もしネットが切れてるときにお客さんが操作するとただエラー画面が表示されるだけで、Chatworkにもスプレッドシートにも飛ばないので人をイラだたせる板になってしまいます。
そこでエラー時にも音出せば原始的なチャイムとして機能する?と思ってつけました。
音量最大にしてオフィスの中聞こえるかはまだ新オフィス行ったこと無いのでわかりません。
音はmp3などでネットで無料でライセンス的にも問題なさそうなのを拾ってきます。
ブラウザで音鳴らすの随分久しぶりな気がしましたが、この関数だけで動きました。
リモートなので実機テストはデザイナーの方に頼みましたが問題なかったそう。
ping-pong.ts
let audio: HTMLAudioElement export const pingPong = () => { if (!audio) { audio = new Audio('pingpong.mp3') } audio.pause() audio.currentTime = 0 audio.play() console.log('pinpong') }
エラーページ出たらしばらくしたらトップにもどる
ネットワーク等なにかの問題でエラー画面がでてそのままだったらうざいので、自動でトップに戻るようにしました。
せっかくなので新しいcomposition-apiでプラグイン的に作りました
手で戻った場合に備えてonUnmountedでキャンセルするのも忘れない。
plugins/setup-auto-back-top
import { onMounted, onUnmounted, useRouter } from '@nuxtjs/composition-api' export const setupAutoBackToTop = (timeout: number) => { return () => { const router = useRouter() let timeoutId: number onMounted(() => { timeoutId = window.setTimeout(() => { router.push('/') }, timeout) }) onUnmounted(() => { window.clearTimeout(timeoutId) }) } }
これをエラーページのテンプレートでsetupに時間(ミリ秒)を付けて入れるだけ。
15秒でトップに自動で戻ります。
error.vue
<script lang="ts"> import { defineComponent } from '@nuxtjs/composition-api' import { setupAutoBackToTop } from '@/plugins/setup-auto-back-top' export default defineComponent({ setup: setupAutoBackToTop(15000), }) </script>
PWAでiPadにインストール&アドレスバー無しを実現する
そのままだとアドレスバーとか出ててダサいのでアプリっぽく動くようにします。
といってもNuxtJSのモジュール入れて、アイコンとか設定するだけ。
IP制限でオフィスからだけ見れるようにする
App Engineということでお気づきの方はいるかもしれませんが、グローバルに公開されちゃいます。
知らない国の知らない人に来客通知送られても困るので制限します。
メニューのファイアウォールで、デフォルト拒否にして、許可するIP追加するだけなので簡単。
ファイアウォールによるアクセスの制御 | Python 2 の App Engine スタンダード環境 | Google Cloud
ベーシック認証とかも考えたけど、認証切れたりした画面をお客さんに見せたくない&新オフィスは固定IPがあるのでIP制限にしました。
そういえばApp Engineの選定理由にこれもありました。
あともし同じIPを使われてURLを知っていて悪意がある人がいても、できるのはスプレッドシートへのログ書き込みとChatwork通知だけで、個人情報漏洩とかの心配はなかったものあり。
なにかあってもすぐGASのウェブアプリを止めればOK。
たぶん実運用が始まってからいろいろと問題が出ると思いますが、ご来社の際は触ってみてください(画面消毒用のアイテム用意しないと)