見出し画像

LINE for おばあちゃん 作ってみた

はじめに

おばあちゃんダッシュボタン作ってみた」に続く、おばあちゃんのために作ってみたシリーズ第二弾です。
今回はラズパイ工作ではなくて、LINEの仕組みを使った簡単なWebシステムみたいな感じになっています。Webサーバがあれば誰でも作れるし、色々応用が利きそうな気がしているので、内容をざっくりと記録しておきます。

ちなみにこれ、産休で里帰りしていた筆者が、出産3日前に構想、2日前に設計し、出産当日に陣痛が来てる最中にプログラムを書いていた代物です。控えめに言って頭がおかしい(そして退院後、赤ちゃんのお世話の隙間に続きを作って、出産1か月後に完成)。

そんなこともあって、「とにかく早く作ること」を最優先して作った代物なので、色々雑ですが、そこら辺は大目に見ていただければと。

あと、祖母は今年100歳の誕生日を迎えました。本記事を読むにあたり、「100歳のおばあちゃん向けのシステムだ」ということを前提にお願いします。

経緯

筆者が出産のため、実家に里帰りしていた時のことです。
実家は両親と祖母の3人暮らしで、祖母はほぼ寝たきり状態なのですが、頭はしっかりしているのとトイレに行くことはできるので、両親が祖母を置いて出掛けることがたまにあります。
この時、祖母から両親に連絡を取る、もしくは両親が祖母に連絡を取ることが難しいという話が出てきました。

要因は以下の通り。

  • 祖母は携帯電話(ガラケーのらくらくホン)を持っているが、電話をかけることしかできない

  • 祖母からの電話に気付かなかったり、出られる状況じゃなかったりして電話を受けられないことがよくある

  • 祖母の携帯に電話をかけ直しても、耳が遠いから気付かない

  • もちろん祖母は着信履歴を確認して折り返すこともできない

  • そもそも電話が繋がっても耳が遠いので会話がままならない

  • 当然ながらメールの送受信もできない

そんなわけで、なんとかこういう場合に祖母と連絡を取る手段がないかと考えてみました。

LINE for おばあちゃんの構築

構想

「経緯」に書いた問題を解決するために、以下の方向でシステムを作ることを考えました。

  • 祖母には使っていないiPadかiPhoneを持たせる

  • 連絡手段はテキストベースで、両親から祖母への一方通行とする

  • 祖母用にメッセージを一覧表示するだけの簡単なWebアプリを用意する

  • 文字はなるべく大きく表示し、操作は極力シンプルにする

  • 連絡がきたことが視覚的にわかるようにする

  • 音声通知も行う(なるべく大音量で流し、祖母が気付くまで流し続けるようにする)

  • 祖母が内容を確認したことをワンタッチで相手に伝えらえるようにする

テキストベースでの連絡と言えばメールかLINE。
今時はLINEの方が手軽でいい気がしたので、LINEを使う方向で検討します。
この段階で「使ってないスマホにLINEアプリ入れて、おばあちゃんに使わせればいいのでは?」と思わなくもないですが、祖母がスマホ及びLINEを使いこなせるわけがないので、祖母に送られたメッセージを一つの画面上に表示するだけのメッセージ表示用Webアプリ(音声通知あり)を別途作成します。

イメージはこんな感じ。

メッセージ送受信イメージ

また、この後祖母がメッセージを確認したことがわかるように、メッセージ表示用サイトの「確認」ボタンを押下すると、「確認しました」というメッセージを返信するようにします。返信にはLINEのメッセージ送信APIを使用します。なお、通知音もこのタイミングで停止します。

イメージはこんな感じ。

確認メッセージ送信イメージ

実装検討① LINEメッセージの取得

LINEで受信したメッセージをメッセージ表示用Webアプリで表示するにあたり、LINEメッセージを外部から取得する必要があります。こちらは、LINEの公式アカウントの仕組みを使うことで実現可能そうでした。
簡単に言うと、公式アカウントがメッセージを受信した時に、Webhookを使って受信メッセージを自作のbotに渡すことができるようです。チャットボットとか作る時にこの仕組みを使ってるんだと思われます。
この方法だと、公式アカウントを作成するためのLINEの開発者用アカウントさえあれば良く、祖母のLINEアカウントを作る手間も省けます。

というわけで、今回は「おばあちゃんへのメッセージ」という公式アカウントを作成し、祖母へのメッセージはそこに送信する方式とします。
ちなみに公式アカウントだと第三者に見つかってしまいそうな気がしますが、公式アカウントを検索不可の設定にしておけば実質非公開で使えます。

Webhook用のbot内では、取得したメッセージを何らかの方法で保存しておきます。メッセージ表示用Webアプリは、そのメッセージを一覧表示するだけのイメージです。

余談ですが、LINEアプリでは相手がメッセージを開くと「既読」がつきますが、Webhookを使うと、呼び出されたbotが200 OKを返した段階で既読がついてしまうので、注意が必要です(それもあって、今回は確実に確認したことがわかるように「確認」ボタンをつけることにしました)。

実装検討② メッセージの表示方法

メッセージは送信者名と受信日時を添えて、メッセージ表示用Webアプリに一覧表示させます。
新着メッセージを視覚的にわかりやすくするために、メッセージごとに「確認」ボタンを付与し、以下のように未読と既読で背景色およびボタンの内容を変更します。

  • 「確認」ボタンが押されるまではメッセージの背景を緑にする

  • 「確認」ボタンが押されたらメッセージの背景をグレーにし、「確認」ボタンを「削除」ボタンに変更する

  • 「削除」ボタンが押されたら一覧から削除する

あと、メッセージの受信日は、日付ではなくて、以下の表記とすることで、いつ来たメッセージなのかが感覚的にわかるようにします(日付をきちんと確認せず、大昔のメッセージを今来たものと勘違いする可能性が高いため)。

  • 当日→「今日」

  • 前日→「昨日」

  • 2日前~1週間前→「〇日前」表記

  • 1週間より前→「年月日」表記

以上を踏まえて、画面イメージはこんな感じになります。

画面イメージ

また、音声通知もしたいので、未読のメッセージがあれば自動で音声を鳴らし、一覧画面上のすべてのメッセージが既読状態になったら音声を止めるようにします。

ちなみに視覚的&聴覚的にわかりやすい通知方法として、業務でよく使っているパトライトが思い浮かびましたが、「これは一般家庭に置くものではない」と思いとどまりました。

システム構成

前述の通り、メッセージの送信はLINEで行うので、LINEの仕組みがそのまま使えます。
この他、Webhookで呼び出すbotやメッセージ表示用Webアプリを置く場所としてWebサーバが必要になるため、Webサーバを適当に用意します。
WebサーバはAWSでWebサーバを構築しても良かったんですが、ちょうどCGI使用可能なWebサーバ(XServer)をレンタルしてたので、そちらを使うことにしました。

取得したメッセージの保存方法ですが、本来ならDBとか使うべきと思うのですが、今回は簡易に済ませたかったのもあって、Webサーバ上にファイルを保存する形式とします。

全体構成はこんな感じ。

全体構成イメージ

Webサーバには主に以下の3つを置くことになります。

  • メッセージ取得用bot

  • メッセージ保存用ファイル(データ)

  • メッセージ表示用サイト

このうち、メッセージ取得用botはLINE側から呼び出せるように公開しておく必要がありますが、メッセージ保存用ファイルとメッセージ表示用サイトは非公開にしたいので、ざっくりと以下のようなディレクトリ構成にします。

ディレクトリ構成

下準備(LINE側の設定)

まずはLINEの公式アカウントを作ります。
公式アカウントは、LINE Developersでプロバイダとチャネルを設定することによって作成できます。
その辺のやり方については以下が参考になりましたので、詳しくは割愛。

あと、Webhookの設定等で、この辺りも参考にしました。

プログラム作成

プログラムは以下の4つを作成します。

①メッセージ取得用bot
②確認メッセージ送信用API
③メッセージ削除用API
④メッセージ表示用Webアプリ

botとAPIはPerlとかPythonとかPHPとかで作ればよいですが、今回はPerlで作りました(一番書き慣れてたので)。

それぞれの詳細な動作は以下の通り。

①メッセージ取得用bot

LINEの公式アカウントのWebhookが呼び出すbotです。
公式アカウントがメッセージを受信したら自動で起動します。

色々調べていたところ、PerlでLINE APIを呼び出してメッセージを取得してそのまま返信するオウム返しbotのソースを公開している記事があったので、メッセージの取得部分はこちらを参考にしました。

メッセージ取得用bot内では、メッセージデータを取得したら、メッセージのID・メッセージの内容・受信時刻・送信者の名前・返信用トークンを取得して、「|」区切りCSV形式で、メッセージ保存用ファイルに追記していきます(メッセージ内に絶対に登場しないであろう記号で区切るのがポイント)。CSVには既読フラグ欄も設けておき、falseにしておきます。

なお、送信者の名前だけは受信メッセージデータ内から取得できません(送信者のIDみたいなやつは取得できます)。
なので、名前を取得するために、LINEのアカウント情報取得APIを別途呼び出して名前を取得する必要があります。この辺の取得方法については、LINE APIのリファレンスを参考にして実装します。

また、メッセージ保存用ファイルの他に最終更新時刻保存用ファイルも作成して、Web画面側の自動更新時の更新有無の判定に使います。

ちなみに同時に複数メッセージを受信した時に各種保存用ファイルが壊れないよう、更新時に排他制御をかけておくと安心ですが、今回はその可能性は低かったので、排他制御はしませんでした。

②確認メッセージ送信用API

Web画面側から、「確認」ボタンを押下した時にJavaScript側から呼び出されます。
メッセージ保存用ファイルから、確認対象メッセージの返信用トークンを取得し、LINE APIを使って「確認しました」のメッセージを送信します(こちらのやり方は先に紹介したオウム返しbotのソースが参考になります)。

また、送信後はメッセージ保存用ファイルの既読フラグをtrueにし、更新時刻保存用ファイルの更新時刻を更新します。

③メッセージ削除用API
Web画面側から、「削除」ボタンを押下した時にJavaScript側から呼び出されます。
該当メッセージのメッセージ保存用ファイル内から、対象メッセージ行を削除します。

また、削除後は更新時刻保存用ファイルの更新時刻を更新します。

④メッセージ表示用Webアプリ
メッセージ保存用ファイルの内容を、メッセージ受信時刻の降順に(最新が一番上にくるように)縦に並べて表示します。
画面や画面遷移のイメージは、「実装検討② メッセージの表示方法」に記載の通りです。

また、数秒おきに更新時刻保存用ファイルの内容を確認し、前回確認時から更新があれば、メッセージ保存用ファイルを読み込んで画面を再作成します。
この際、既読フラグがfalseのものが1つでもあれば、音声を流し、1つもなければ音声を止めます。

動作確認

というわけで、一通り作成してWebサーバに配置したら、いよいよ動作確認に入ります。

実際に動かした時の画面はこんな感じになりました。

動作確認

この通り、おおむね想定通りに動いたのですが、一部ちょっと苦戦したところがあったので、以下に記載しておきます。

問題点① Webサーバのキャッシュ問題

Webアプリ側で、10秒おきに更新時刻保存用ファイルを参照し、更新があればメッセージ保存用ファイルを読み込み直して画面を再作成するようにしていましたが、更新時刻保存用ファイルを更新しても、なぜか更新前の時刻が取れてくる事象が多発しました。

レンタルサーバのキャッシュの設定の問題かなと思って、キャッシュを無効にしてみましたが変わらず。
JavaScriptのfetchのオプションにcache;no-storeをつけてもダメ。
試しに直接ファイルを読まないでファイル参照用APIをかますようにしてもダメ。

レンタルサーバの仕様か何なのか、どう頑張っても最終参照から60秒はキャッシュを見に行ってしまうようでした。
仕方がないので画面を70秒更新にしつつ、更新時刻保存ファイルは使わずにメッセージ保存ファイルを読み込んで、画面を毎回再作成することで解決しました(本当は画面に即時反映させたかったのですが、どうせ使うの祖母だし、1分程度のタイムラグならいいかなと妥協)。

あと確認ボタンや削除ボタンを押した時に、メッセージ保存用ファイルを更新し、それを読み込み直して画面を再作成する実装にしていましたが、こちらも更新直後にファイルを読み込み直すと更新前の内容を取得してしまうため、メモリ上にメッセージ一覧データを持たせて、このタイミングではメモリ上のデータを更新して画面に反映させるようにしました。

問題点② 音声の自動再生できない問題

Webアプリで自動音声or動画再生をしようとしたことのある人には周知の事実なのかもしれませんが、最近のブラウザは、音声や動画を自動再生できないようになっているようです(ページを開いた時にいきなり音が鳴るのを防ぐためと思われる)。

こちらはPCのChromeの設定で、「自動再生を許可するURL」にWebアプリのURLを追加して一瞬解決したのですが、iPadやiPhoneではこの設定ができないことが発覚したため、別の方法を考えることにしました。

やり方は色々あるようですが、とりあえず1回でいいので何かしらボタンを押して音声を再生しておくと、その後はJavaScript側で自由に音声再生&停止ができるようになるらしいので、画面表示直後に以下のようなモーダルウィンドウを表示し、「OK」ボタンをタップすると音声を再生してすぐに停止する作りにしました(ちょっとダサいけど、個人的に使うものなので妥協)。

モーダルウィンドウイメージ

問題点③ 古いiPadで表示できない問題

ここまでやってようやくいい感じに動くようになったと思ったら、祖母に渡そうと思っていた使っていないiPadが古すぎて、Safariでメッセージ表示用Webアプリが全く表示されないという問題が発生しました。
※なぜかはわからないけど、おそらくJavaScriptの非同期処理にawait/asyncを使ってたのが原因(そこだけコメントアウトしたら表示された)。

これについては、使っていないiPhone(6s)で表示されたので、それを渡すことで解決(本当は画面の大きいiPadにしたかったけど、iPhoneでも字は読めそうだったので妥協)。

運用開始

問題点をすべて解決後、正常に動くようになったので、祖母の枕元にiPhoneを置いて使い方をレクチャーしてみました。
で、ここで発覚しましたが、iPhoneの音量を最大にしていても、補聴器をつけていない状態(寝てる時とか)の祖母には全く聞こえない模様。
まあとりあえず視覚的にもわかるようにしてあるので、通知音声は流すだけ流しておき、両親が出かける時にはちょこちょこ見といてもらうことにしました(ちなみに延々流れていてもうざくないよう、通知音声はショパンの「華麗なる大円舞曲」にしました)。

あと、祖母がタブレット的なものを使い慣れていないため、ボタンを押し込んでしまう(長押し判定になってテキスト選択状態になる。お年寄りあるある)という問題や、爪で押してしまうため反応しないという問題が発生しましたが、それは何回か練習しているうちに少し慣れたようでした。

ちなみにiPhoneでは特定の画面を固定表示にする機能があるので、それを使ってメッセージ表示用サイトを固定表示にしています。ただ、これをやると画面ロックがかけられなくなるので、24時間365日画面つけっぱです。常に充電状態にしてあるけど、バッテリーが少し心配。

おわりに

このシステムですが、
・スタンプは対応していない
・画像送信も対応していない
という少し残念な点があります。
スタンプは難しそうですが、画像に関してはやればできそうな雰囲気があったので、いつか暇な時に機能強化したいと思っています。

また、今回は早く作ることを最優先にしたので、botとAPIはPerl、Webアプリは生のJavaScriptでゴリゴリ書いたんですが(それもあって、ちょっと恥ずかしいのでコードは公開していません)、勉強のためにAPIをPythonで、WebアプリはVue.jsで作り直したいなーと思っていたりします。
いつか余裕があったら頑張ってみます。

ちなみにこのシステム、本来は両親から祖母への連絡用として作ったのですが、私が祖母にテスト送信した時に、メッセージを「赤ちゃんは今日も元気です」としてしまったがために、祖母が「家に帰ったらこんな感じで赤ちゃんのこと教えてくれるの?いいよーそんなわざわざ送らなくてー」と若干勘違いして嬉しそうにしてたので、たまにメッセージを送ってあげようと思った次第です。長生きしてね。