まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

タグ:raspberrypi

日本での正式な発売直後に品切れになり、しばらく入手できなかったラズベリーパイ 400 (以下「ラズパイ 400」)の販売が再開されたようです:
品切れだったラズパイ内蔵キーボード「Raspberry Pi 400」日本語版、販売を再開 9790円



幸いなことに自分はこれ(日本語キーボード版)を入手することができていました。そして罰当たりなことに、このラズパイ 400 を「起動したまま SSH で使う」という使い方をしていました。SSH 接続ならなにもラズパイ 400 じゃなくて普通のラズパイでも・・・という声が聞こえてきそうです。ごめんなさい、その通りだと思いつつ使ってました。

言い訳をするつもりはないのですが、ラズパイ 400 はキーボード本体内にラズパイ4(4GBモデル)が内蔵されているもので、ここに電源とモニター(と現実的にはマウス)をつないで使うことになります。マウスは Bluetooth でもよいので物理的な接続は必須ではなく、(内蔵バッテリーがないため)電源をつながないといけないのは仕方ないとして、モニターもつながないと実質的に使えないというのが普段使いにはちょっとしたハンディキャップになっていました。本体とキーボードのセットと考えるとかなり小型化されていて持ち運びに便利な一方で、モニターも HDMI ケーブルごと持ち歩かないといけないのだとするとラズパイ 400 の機動性はかなり落ちてしまいます。モニターのある部屋からモニターのある部屋へ移動して使うにはいいんだけど、それだと利用シーンはかなり限られてしまうような気もしてしまいます。。

で、今回のブログのテーマとなります。そんなラズパイ 400 ですが、普段から持ち歩いているスマートフォン(スマホ)をモニター代わりに使うことができるのであれば、実質的にモニターを持ち歩いているようなものなので、上述の課題を解決できるのではないかと考えました。これは実現性を無視した都合のよい話ではなく、HDMI input をサポートした Android 11 以降であれば理論上はできるはず、、ということで試してみたのでした。ちなみに iOS だとまだこの機能はサポートされていない模様です。


【システム構成】
今回試したシステム構成はこのような形です:
2021091901


通常、ラズパイとディスプレイとを HDMI ケーブルで接続するのですが、そのディスプレイの代わりにスマートフォンを使うことになります。その際に HDMI ケーブルをスマートフォンの端子(USB Type-C)にアダプタで直接変換すればよいわけではなく、間にキャプチャーカードと呼ばれる機器を挟む必要があります。今回は以下の「BANANAJOY ビデオキャプチャカード」を使いました:



また、このキャプチャー結果の信号を USB Type-C 端子を持つスマホに送るための変換ケーブルとしては以下の「MacLab. USB Type-C OTG 変換 ケーブル」を使いました:



加えて、スマホ側にも単に信号を送っただけではディスプレイとして表示されないので、「スマホを外部ディスプレイ化するアプリ」が必要です。今回はこの「USB Camera」アプリをダウンロードして使いました。なおこのアプリは無料ですが、有料版(USB Camera Pro)だと広告が表示されないだけでなく、画面サイズを変更できるなどの追加機能が使えるようです:
USB Camera - Connect EasyCap or USB WebCam


ちなみに今回の実験で使ったスマホはこの Unihertz Titan Pocket です。この機種である必要はありませんが、Android 11 が搭載されている必要があると思っています:
QWERTYキー付き小型スマホ、Unihertz「Titan Pocket」が到着!

※あと今回のレビューでは使っていませんが、この機種だと標準アプリとして「USBカメラ」というものが含まれていて、これで外部ディスプレイ化できることも確認できました。


で、上述のシステム構成のようにラズパイ 400 、HDMI ケーブル、キャプチャーカード、OTG 変換ケーブル、そしてスマホを接続し、スマホにインストールした USB Camera アプリを起動した状態でラズパイ 400 に電源を入れると・・・
IMG_3924


↑ラズパイ 400 が起動し、その画面がスマホ内に表示されました!期待通り!!

↓ブラウザとターミナルを開いて使っている時の画面の様子がこちらです:
IMG_3925


あっけなく実現できてしまいました。今回スマホとして使った Unihertz Titan Pocket は決して広い画面を持っているわけではないので、実用性という観点ではあまりよくないかも(苦笑)しれません。まあ、でも普通の画面(?)の Android 11 を所有していて、有料版の USB カメラアプリで画面をポートレートモード(横)固定で使えばもう少し見やすくなりそうだと思ってます。

※ここでスマホに表示される画面はあくまで「外部ディスプレイ化されたスマホに単に表示されている画面」です。タッチ操作に対応はしていません。タッチしても何の反応もありません。


さて、ということはラズパイ 400 を持ち歩いて使う上で、かなり進展があったと思っています。何しろ「普段から外部ディスプレイ(=スマホ)を持ち歩いていた」ことになるので、接続用のケーブル類だけ持ち歩いていればどこでもラズパイを使える、ということになります!!

その接続用に持ち歩くケーブル類ですが、具体的には・・・
・電源ケーブル(USB-C ケーブルと、コンセントにつなぐ電源アウトレット)
・Micro HDMI -> HDMI 変換アダプタ
・HDMI ケーブル
・HDMI キャプチャーカード
・USB Type-C OTG 変換ケーブル
・外付けマウス(有線か、または Bluetooth)


・・・んー、意外と多いな(汗) (^^; それと結局バッテリーがないからコンセントかモバイルバッテリーに繋いで使う必要があるんですよね。これが次のネックになりそうな気がしてきました。。

※なお、HDMI キャプチャーカードが利用する電源は出力側(スマホ側)から使われる模様です。つまりこの仕組を使っている間、スマホ側のバッテリーは想定以上に消費されることになる点に注意してください。


ともあれ、Android 11 が使えるユーザーにとってはフルキーボード付きの Debian Linux 環境を持ち歩いて使える手段の目途が立つ実験結果でした。


元ネタはこの記事です:
Cloudflare の ngrok的なサービスがあるらしい ⇒ $ cloudflared tunnel --url localhost:8080 といった使い方

(特に開発中のサービスなど)ローカルホスト内で動いている状態のウェブサービスを試験的・一時的にインターネットに公開して外部から利用できるようにするものです。この手のツールとしては ngrok が有名ですが、CDN で有名な Cloudflare 社も同様のツールを公開していたんですね。。

上記ページはその導入手順を含めて紹介しています。また公式のインストールページもリンクされています:
https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation


が、残念ながらラズベリーパイ向けのインストール方法はここで書かれている方法だけではわかりにくい内容でした(要はラズパイの場合、ソースコードからビルドする必要があるのですが、ビルドの前提となる Go 言語のインストールがまた面倒で・・・)。というわけで、ラズベリーパイ環境向けの cloudflared のインストール手順を以下に紹介します。


【ラズベリーパイ向け cloudflared のインストール手順】
(1) Go 言語のインストール

この後の手順で Go 言語を使って cloudflared をビルドします。そのため Go 言語をインストールしておく必要があります。

以前に紹介した以下のサイトを参照して、ラズベリーパイに Go 言語をインストールしてください:
ラズベリーパイに Go 言語をインストールする


(2) cloudflared のビルド

Go 言語用のソースコードをダウンロードして、Go 言語でビルドしてツールを作成します。

まず GitHub からソースコードをダウンロードします:
$ git clone https://github.com/cloudflare/cloudflared.git

ダウンロードしたソースコードを Go 言語でビルド&インストールします:
$ cd cloudflared

$ make cloudflared

$ go install github.com/cloudflare/cloudflared/cmd/cloudflared

ここまでの手順で ~/go/bin/cloudflared に実行バイナリが作られています。このままだと利用が不便なので、パスの通ったフォルダ(例えば /usr/local/bin/ 以下)にこのファイルをコピーします:
$ sudo cp ~/go/bin/cloudclared /usr/local/bin/

これでインストール完了です。


【ラズベリーパイで cloudflared を使ってみる】

ではインストールした cloudflared を実際に使ってみます。そのためには何でもいいのですが、何らかのウェブアプリケーションをラズベリーパイ上で動かす必要があります。docker で nginx を動かすとか、適当なウェブアプリを動かすとかでも構いません。こちらの方法を参照いただいて Node-RED をインストールして動かす、とかでも構いません(以下は最後の方法を実行し、 $ node-red コマンドまでを実行して、Node-RED が 1880 番ポートで稼働しているという前提で説明を続けます):
2021040801
(↑プライベートアドレスの 1880 番ポートで待受け準備完了した様子)


ラズベリーパイ上で何かウェブアプリが動いていたら、ラズベリーパイの端末(既に利用中の場合は別のターミナルの画面)から cloudflared コマンドを実行します:
$ cloudflared tunnel --url localhost:1880

※上述コマンドの 1880 部分は実際にリクエストの待受けをしているポート番号を指定します

すると実行結果の画面に以下のようなメッセージが表示されます:
  :
  :
2021-04-08T05:01:22Z INF +-------------------------------------------------------+
2021-04-08T05:01:22Z INF |  Your free tunnel has started! Visit it:              |
2021-04-08T05:01:22Z INF |    https://xxxxxx-xx-xxxxxx-xxxxxx.trycloudflare.com  |
2021-04-08T05:01:22Z INF +-------------------------------------------------------+
  :
  :

この青字で表示された URL が cloudflared のトンネリングによってインターネットに公開されたアドレスです。自分の PC はもちろん、全く別のネットワークに接続された別の PC からでもウェブブラウザでこのアドレスにアクセスすると、ラズベリーパイの localhost:1880 で稼働しているアプリケーションをパブリックなインターネットから見ることができるようになります:
2021040802
(↑パブリックアドレスで https で待受け準備完了した様子)



ラズベリーパイへの Go 言語インストール、普通にリポジトリから $ sudo apt-get install go でインストールできるかと思っていたら出来なかったので手順を調べました:
go


2021/04/07 現在ではラズベリーパイに Go 言語をインストールするには最新版バイナリ(のアーカイブ)をダウンロードして展開するのがてっとり早そうでした。

まずはこのページで Go 言語の最新バージョンを確認します:
https://golang.org/dl/

2021040701


2021/04/07 時点での最新版安定(stable)バージョンは 1.16.3 のようでした。以下、このバージョンをインストールする前提で説明を続けます。

ラズベリーパイのターミナルから、ラズパイアーキテクチャ(armv6l)向け最新バイナリをダウンロードして、/usr/local 以下に展開します:
$ wget https://golang.org/dl/go1.16.3.linux-armv6l.tar.gz

$ sudo tar -C /usr/local -xzf go1.16.3.linux-armv6l.tar.gz

これで /usr/local/go フォルダ以下に Go 言語がコピーされました。実際の go コマンドは /usr/local/go/bin/go に存在している状態です。

このままだとパスが通っていなくて不便なので、パスを通します。~/.bashrc ファイルをテキストエディタで開いて、最終行に以下を追加して保存します:
export PATH=$PATH:/usr/local/go/bin

保存後、 $ source ~/.bashrc を実行するか、ターミナルを一度終了して開き直すと設定が有効になります。go version コマンドを実行して、以下のような結果が表示されればインストール成功です:
$ go version
go version go1.16.3 linux/arm

 

ラズベリーパイに Raspberry Pi OS をインストールする場合、多くのケースで Lite 版以外のデスクトップ版やサードパーティアプリまで含まれた拡張デスクトップ版を使うと思っています。この2つであれば初期セットアップの段階からデスクトップ GUI による操作が可能となり、無線LANの設定含めて便利に環境構築ができます。逆に Lite 版を選んだ場合は初期段階では CUI による操作が必要になり、ある程度まではキーボードによるコマンド実行や環境構築が必要になります(正しいキーボード設定をするまではキーボードレイアウトも合っていない可能性もあります)。慣れないと不便ですが、一方で余計なものが含まれていない状態であるとも言え、非常に軽量で動作する環境でもあります。特にラズベリーパイゼロ(以降「ラズパイゼロ」)のようにリソースの限られたハードウェアを使おうとすると、デスクトップ版だと起動の時点でリソースの多くが使われてしまい、初期セットアップ作業もかなり時間をかけて行う必要がでてきてしまいます。そんなラズパイゼロでは作業効率を考えると Lite 版で初期セットアップを行い、必要に応じて後からデスクトップ環境も導入する、という使い方も考慮する必要があります。

さて、この面倒な状況をなんとかならんか・・・と考え、短絡的に「デスクトップ環境をもっと軽量にできないか?」と試みることにしました。自分は 30 年近く UNIX を使っていて、自分が使い始めた当初は "X Window" なるウィンドウシステムが(正確には X11 が)使われ始めていた、という時期でもありました。当時の自分は今ほど CUI に理解はなく(苦笑)、GUI オペレーションが可能な X Window を使いたくて個人の環境でも試行錯誤していた時期でした。

※より正確には当時の Linux(Slackware) でもインストール時に X Window を含める選択をすることは可能でした。が、標準機能で導入される X Window は twm(Tab Window manager) と呼ばれる、見た目も操作感もイマイチ・・・な GUI で、「これじゃなくて大学の研究室で使ってるやつを使いたい」と試行錯誤していたのでした。その「大学の研究室で使ってるやつ」は現在ではオープン化された mwm(Motif Window Manager) で、当時は無料ではなかったと記憶しています。事実、僕はこれを買ってまで使っていました(メディアもまだ持ってます)。思い入れのあるウィンドウマネージャーです:
IMG_3176


話を戻すと、要は「ラズパイ(ゼロ)でも X Window だけを入れれば軽量 GUI が実現できるのではないか?」&「今なら mwm も無料で使えるので(折角なので) mwm で使いたい」と考えて、「ラズパイで X Window + mwm を使う方法」を調べたのでこのブログで共有します。なお以下の内容はラズパイゼロでも使えることを確認していますが、普通のラズパイでも動く内容です(普通のラズパイなら普通のデスクトップでもそんなに苦労はしないと思うけど)。


【ラズパイ(ゼロ)に X Window と mwm をインストールする】
まずラズパイ(ゼロ)を Raspberry Pi OSLite 版でセットアップします。ある意味、ここが一番大変だと思ってます。ここに書かれた内容を参照するなどして初期セットアップまでを終えておいてください(以下の手順では SSH 接続やシリアルコンソール接続は必須ではありません):
Raspbian Liteの初期設定 令和2年(2020年)3月版

改めて X Window と mwm を利用する上で必要なツール類を追加インストールします。必須ではありませんが、せっかく GUI を使うならウェブブラウザくらいは・・と思って最後に Chromium(chromium-browser) も含めていますが、不要であれば指定しなくても構いません:
$ sudo apt-get install libxm4 mwm xserver-xorg xinit x11-xserver-utils xterm x11-apps chromium-browser

ツール類のインストールが完了したらホームディレクトリに .xinitrc という名前のファイルを作成します。X Window 起動時の各種設定をするファイルで自分はとりあえず以下の内容にしました(上記のツール類をすべて導入していれば起動エラーは起こらないと思います):
#!/bin/sh

xset s off
xset -dpms
xset s noblank

xsetroot -solid darkslateblue

xeyes -geometry 70x70+5+5 &
xclock -geometry 70x70+105+5 &
xterm -geometry 80x20+100+100 &
exec mwm

これで準備は完了。最後に以下のコマンドを実行して X Window を起動します:
$ startx

成功するとこのような画面が表示されます(この画面で「懐かしい!」と感じる人はアラフィフ以上のオッサンだと思います(笑))。普段見慣れた GUI と比べるとかなりシンプルに感じますが、xterm のタイトル部分でラズパイ環境であることもわかります:
1

※x11-apps パッケージを導入しているので、xeyes や xclocks 以外に以下のページで紹介されているアプリも使えます:
https://packages.debian.org/stretch/x11-apps


せっかくなので導入した Chromium も起動してみます。xterm の画面から起動コマンドを最後に & を付けるのを忘れずに実行すると、指定したアプリが  X Window 内で起動し、xterm も(実行したままにならず)プロンプトが戻って続けてコマンドを実行できる状態になります:
$ chromium-browser &

2


自分の感想ですが、ラズパイゼロだと Chromium を起動すると「さすがにちと厳しいかも・・」という印象の操作感になります(現実的には日本語フォントなども追加でインストールすべきだし・・)。ただ通常のデスクトップ GUI で起動した時と比べると全体的にまだ全然軽いですね。


ちなみに X Window を終了するには背景部分を右クリックして、ポップアップメニューから "Quit" を選択、です。
3


4


昔はこの mwm って有料だったんだよなあ。その頃を知っているので、オープン化されて無料で使えるようになった mwm が簡単に使えるようになったのは改めて感慨深いものがあります。

また、.xinitrc ファイルの最後の "exec mwm" 部分で、(足りない場合は apt-get で導入してから)mwm 以外の別のウィンドウマネージャーを指定することもできます。有名どころはデフォルトだった twm や fvwm2 あたりでしょうかね。まあ使い慣れたものがあったら、それを使うのがいいと思っていますが、僕は「買ってでも欲しかった」mwm 一択です。



1台程度のマシンで、小規模な k8s(Kubernetes) 環境を構築できる MicroK8s をラズベリーパイ(以下「ラズパイ」)に導入する手順を確認してみました。MicroK8s は Ubuntu を開発&提供している Canonical 社が開発する k8s パッケージです:
MicroK8s_logo


まずラズパイ本体を用意します。後述しますが k8s はスワップメモリを無効にして稼働させる必要があるため、ラズパイ3以前のメモリ 1GB 環境だと少し厳しいかもしれません。今回はメモリ 4GB モデルのラズパイ4を使って確認しました。

次に 64bit 版ラズパイ OS をインストールします(MicroK8s は 64bit OS 向けに提供されています)。64bit 版のラズパイ OS は 2021/01/08 の時点では正式リリースされているわけではありませんが、こちらからテスト版をダウンロードすることができます:
http://downloads.raspberrypi.org/raspios_arm64/images/

2021010801


私は 2020-08-24 という日付が入ったモジュールをダウンロードしました(この記事を記述している時点では最新の 64bit モジュールです。公式の 32bit 版と比べるとたまに知らない間に再起動してたりして、少し不安定な印象はあります)。ダウンロード後に展開してマイクロ SD カードに書き込みます(このあたりは通常の手順と同様)。そしてラズパイ(4)にセットして初期セットアップを済ませておきます。

この後に MicroK8s をインストールするのですが、その前に準備作業を2つほどしておきます。まず k8s はスワップメモリが存在していると正しく動作しないため、まずはスワップを無効にします:
$ sudo swapoff -a

続けて、これも通常の k8s を導入する際にも行う必要のある手順ですが、cgroups のメモリーサブシステムを利用するため、/boot/cmdline.txt に記述されている内容の(同じ行の)最後に以下の赤字部分を追記して保存し、この段階で一度リブートします:
console=serial0,115200 console=tty1 root=PARTUUID=a3ba36bd-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles cgroup_enable=memory cgroup_memory=1

これで k8s を導入するための準備が完了しました。続けて MicroK8s をインストールします。今回は公式サイトでも紹介されている、Snapd を利用する方法でインストールします。まずは Snapd (とこの後で使う iptables-persistent)をインストールして一度リブートします:
$ sudo apt install snapd iptables-persistent 

$ sudo reboot

再起動後に再度ログインし、改めて Snap を使って MicroK8s をインストールします(この手順で少し時間がかかります):
$ sudo snap install microk8s --classic

MicroK8s のインストールが完了したら以下の3つのコマンドを実行後に(一度 exit してから)再ログインします:
$ sudo usermod -a -G microk8s $USER

$ sudo chown -f -R $USER ~/.kube

$ sudo iptables -P FORWARD ACCEPT

ここまでの作業で MicroK8s がインストールされて、MicroK8s が起動されているはずです。 以下の "get nodes" コマンドを実行して STATUS 欄が "Ready" と表示されることを確認します:
$ microk8s.kubectl get nodes

NAME          STATUS   ROLES    AGE     VERSION
raspberrypi   Ready    <none>   7h25m   v1.20.0-37+6252d1e153c00f

またサービスの一覧は "get services" コマンドで確認できます:
$ microk8s.kubectl get services

NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.152.183.1   <none>        443/TCP   9h

なお、MicroK8s の起動/終了のコマンドはそれぞれ以下の通りです:
$ microk8s start  (起動)

$ microk8s stop  (終了)

Snap パッケージになっているので、インストール時の手間が非常に簡略化されている印象でした。一方で、(これは MicroK8s というよりも 64bit OS の問題なのかもしれませんが)全体的に不安定な挙動が見受けられるように感じました。"microk8s.kubectl get nodes" コマンドの結果が READY ではなく NotReady になることがあったり、システムがいつの間にか再起動していたりして、イマイチ安定していないような気もします。

このページのトップヘ