見出し画像

Raspberry Piで子供用に時計サイネージを作ってみた(続編)

Raspberry Piに13インチのモニタを接続して、子供がいつでも見られる時計サイネージを作った話の続編である。前回の話は、以下の記事を参照されたい。

前回の記事では、時計サイネージとしてカレンダー、アナログ時計、メッセージ表示、天気予報の4つの機能を一つの画面に表示させ、それを食卓の上に設置したところまで紹介した。記事公開以降も機能の改良を続けたため、本記事ではそれを紹介する。

今回紹介する機能のコードも一部を除きほぼ全てGitHubに載せているので、詳細はコードを参考にされたい。

サイネージ機能の改良

背景色で季節感を出す

まず1つ目は、些細な機能であるが、背景パターンの色が月ごとに自動的に切り替わるようにしてみた。当初の時計サイネージ画面ではカレンダーを表示してはいたものの、常に同じ色でいまいち季節感を感じることができなかったため、背景色をその季節にちなんだ色にして、月日の変化を感じられるようにした。

いろいろイメージを膨らませた結果、以下の12のパターンを各月に設定した。縞模様はCSSの直線グラデーションによって実現している。

図1.月ごとの背景パターン
図2.3月の背景になった時計サイネージのスクリーンショット

色の変化は子供もすぐに気づき、それ以降月が変わるたびに「今日から○月だね」と月の変化を認識するようになった。

時報でサウンド再生

これまで音に関して一切触れていなかったが、時報などが実現できればよいと思い、サウンド再生の機能も実装することにした。

サウンド再生は、メッセージ表示の機能として実装し、任意のメッセージの表示のタイミングで任意のサウンドが鳴らせるようにした。毎時00分と30分にはすでに時報のメッセージを表示する設定を入れているので、ここにサウンドファイルの指定を追加するだけという形だ。

サウンド再生にあたっては、まずブラウザの設定が必要だった。近年のブラウザではウェブページ上でのサウンドの自動再生が厳しく制限されているため、事前に設定でlocalhostを自動再生の許可サイトに登録しておく必要がある。具体的には、Chromiumの設定から「プライバシーとセキュリティ>サイトの設定>音声」とたどり、許可サイトに「http://localhost:ポート番号」を追加しておかなければならない。

また、今回スピーカーはモニタに内蔵のものを使用するため、イヤホンジャックではなくHDMIで音声が出力される必要がある。そのためには、raspi-configコマンドを使用してRaspberry Piからのオーディオの出力をHDMIに設定しておく必要がある。私のRaspberry Piでは最初からHDMIに設定されていたようだった。

以下は時報のチャイムが鳴るときの様子である。時計ではなくあくまでメッセージの機能として実装したため、鳴るタイミングは最大15秒(=メッセージの表示間隔)の遅れがあるが、そこまでの精度は必要ないのでこれで十分だ。

帰宅時間の通知

メッセージ機能にさらに追加で、任意のサーバー上に設置されたメッセージを読み取って表示できるようにした。Raspberry Piは自宅の閉じたネットワークにしか繋がっていないため、自宅の外から直接アクセスすることができないが、この機能により「外出先からメッセージを登録し、それをRaspberry Piが読み取って表示する」ということが可能となる。

これを使って実現したのが、帰宅時間の通知機能だ。子供が家で親の帰りを待っているときに、「あと何分で家に着くか」を外出先からサイネージに通知できるようにした。

(注:メッセージを登録する機能は別途外部サーバー上に実装する必要がある。メッセージ登録機能のコードは時計サイネージのリポジトリには含めていない。)

システム自体の改良

サーバーのNode.js化

前回の記事では、「ウェブサーバーはこだわりポイントではないのでPythonの簡易サーバーを使った」と書いた。しかし、機能の追加を検討するにつれ、やはりウェブサーバーも自由にコントロールできた方がよいと思い、Node.jsで自作することにした。

Node.jsでウェブサーバーを作成するにあたっては、静的にファイルを返す以外に以下の機能を実装した。なお、フレームワークはExpress.jsを使用している。

  • キャッシュ制御のHTTPヘッダ出力。変更が必ず反映されるようブラウザキャッシュが無効となるようにした。

  • WebSocketによる双方向通信。次の節で紹介する「リモコン機能」を実現するためのもの。

  • 任意のシェルスクリプトを実行できる機能。さらに後の節で紹介する「再起動/シャットダウン機能」を実現するためのもの。いかにも脆弱性になりそうな機能であるが、自宅ネットワーク内のみでの運用なので特に問題は無い。

リモコンの作成

当初から「時計サイネージ以外のアプリも追加していきたい」と考えていた。その場合、モニタのみで何も入力を受け付けないシステム上で、どうやってアプリを切り替えるかが問題だった。

そこで考えたのが、リモコン機能である。リモコンのウェブページをRaspberry Pi上に用意しておき、それをスマホやタブレットなどの自宅ネットワークに接続した別デバイスで表示する。リモコンページ上のボタンを押すと、WebSocketでNode.jsのサーバーを経由してRaspberry Piで表示しているページにリクエストが届き、<iframe>内で表示するページを切り替える。

図3.リモコン機能の構成

これで、あたかもテレビのチャンネルを切り替えるかのように、複数のアプリの切り替えができるようになった。以下は、スマホでリモコンを表示させて、時計サイネージと後述の作成したアプリを切り替えている様子である。

Node.jsのサーバーでキャッシュ無効の制御を入れたため、アプリを修正した場合などのページリロードも、リモコンのボタンを押すだけで簡単にできるようになった。そのため、前回の記事で説明した更新方法は全て廃止とした。

(注:リモコンで切り替えやリロードができるのは上図の<iframe>内のページだけで、display.html自体のリロードはできない。)

サイネージ以外の機能の追加

スクリーンセーバー

サーバーとリモコンが完成したので、時計サイネージ以外のアプリを考えてみることにした。

最初に思いついたのは、スクリーンセーバーである。かつてブラウン管モニタが主流だった頃は、画面を保護するためのスクリーンセーバーが人気だったが、私はあれが大好きだった。手始めに、昔どこかで見たことがある、デジタル時計のスクリーンセーバーを作ってみることにした。

オリジナリティを加えた部分として、数字の形のデザインと、数字が変化するアニメーションにはこだわった。私はこういう類のプログラムを書くのが好きなのだが、なかなか活かせる機会が少ない。以下が完成したデジタル時計のスクリーンセーバーである。

再起動/シャットダウン機能

Raspberry Pi本体の再起動とシャットダウンは、SSHでログインしてコマンドを叩く必要があり、当初から面倒であった。そこでこれもアプリの一つとしてリモコンから簡単にできるようにした。

設計にあたっては、リモコンのボタンを押した瞬間に即再起動(またはシャットダウン)が実行されると、誤操作が多発しそうであるため、ボタンを押すごとに確認画面が表示され、一定時間内にもう一度ボタンを押さないと実行されないようにした。

再起動およびシャットダウン自体は、シェルスクリプトで実行するようにしておき、ウェブページから特定のURLを叩いたときにこのシェルスクリプトが実行されるようにNode.jsのウェブサーバーに仕込んだ。

以下が実際にリモコンから再起動を実行している様子である。

写真スライドショー

子供がいると写真が爆発的に増えていってしまいがちであるが、我が家も御多分にもれずこれまでに撮った子供の写真が山ほど溜まっている。そこで、これをランダムに表示してデジタルフォトフレーム的な機能を作ってみることにした。

写真は全て自宅のNASに保存してある。Raspberry PiからNASのマウントはmountコマンドで簡単にできた。ただ、ウェブページからNAS上のファイルの一覧を直接自動で取得することはできない(もしそのようなことができたらウェブサイトからPC内が丸見えということになってしまう)ので、あらかじめ作っておくか、サーバー側で動的に作る必要がある。ここでは再起動のときと同じ手法で、サーバー経由で動的にシェルスクリプトを叩いて一覧を作成し、それをウェブページから読み込んで使う形にした。

ウェブページで画像を表示するのは簡単であるが、ただ表示するだけだとつまらないので、ここもオリジナリティを発揮してこだわってみた。CSSのtransformによる3D変形とtransitionによるアニメーションを使い、写真が奥から次々と登場しては消えていくようなアニメーションを実装した。以下の動画ではサンプル画像を表示しているが、実際は子供の写真を表示している。

一点だけ気になったのは、Raspberry Piはやはり通常のPCに比べると非力なようで、3Dのアニメーションはやや滑らかさを欠いているようだった。

子供の写真というのは、つい撮りためるばかりになってしまうが、これのおかげで家族で一緒に今までの写真を簡単に見ることができるようになった。食卓での話題も増え、この機能は家族には好評だった。

その他

USB分岐ケーブル

Raspberry Piがフリーズしたときや、Raspberry Pi上のブラウザの設定を変更するときなどは、モニタの裏に貼り付けてある本体に有線のキーボードとマウスを接続する必要がある。しかし、不安定なモニターアーム上でのUSBの抜き差しは毎回非常にやりにくかった。そこで、短いUSBの分岐ケーブル(ハブ機能付き)を購入し、それをぶら下げておくことにした。

図4.分岐ケーブルを介してキーボードとマウスを接続したところ

モニターやRaspberry Pi本体をしっかり固定できていれば必要無いと思われるが、モニターアームや本体の固定が不安定だったり、手が届かない場所に設置したりした場合は重宝するだろう。

ちなみに、Raspberry Piはこれまで約7ヶ月間連続稼働してきているが、フリーズして気がついたら止まってたということが数回あった。気づかなかった時間が長かったこともあったので、稼働率はおそらく99.0%程度になると思われるが、個人的には「十分安定してるな」という印象である。

おわりに

ここまで紹介してきたように、少しずつ機能が増えてきている我が家のRaspberry Pi製サイネージであるが、まだモニター・キーボード・マウス以外のものは何も接続できていない。Raspberry Piを買ったからにはやはりセンサー類の接続を試してみたいと思っている。13インチの画面に表示する機構はすでに整っているのだから、例えば、温湿度センサーを接続して、室温を画面で表示といった使い方がイメージできる。気圧や二酸化炭素濃度など、あまり普段計測したことのない数値も計測して表示させてみたら面白そうだ。あとは、カメラを接続すれば画像認識などと組み合わせてこちらも何か面白そうなことができそうである。まだ具体的なアイデアは無いが、今後時機を見て挑戦していきたいと思う。

当初は子供のためにと作った時計サイネージであったが、今では完全に私がいろいろ作って試して遊ぶためのものとなってしまっている(こうなることは予想できていた)。それでも、写真スライドショーの機能などは、家族に気に入ってもらえたので、引き続き子供や家族が楽しめる機能を考えて増やしていきたいと思っている。

(最後までお読みいただきありがとうございました。)


※2023/07/02追記:
続編第2弾を公開しました。よろしければこちらもご覧下さい。


この記事が気に入ったらサポートをしてみませんか?