Closed11

ポータブルエッジサーバ開発環境の製作

takumiquetakumique

作りたいもの

スマホアプリから使用する、ポータブルエッジサーバの開発環境を作成していきます。スマホとエッジサーバを同一のモバイルルータに接続し、使用時にはホストマシンなしでオペレーションできる構成にします。

takumiquetakumique

ポータブルエッジサーバの概要

ハードウェア

手元にあるRaspberry Pi 4 (RasPi4)を使用します。RasPi4の安全なシャットダウン・サーバ監視等のため、こちらも手元にあるタッチパネル付きの液晶ディスプレイ(LCD)を接続しました。

ソフトウェア

Yoctoを使用してエッジサーバソフトウェアをビルドします。コンセプトとしてはハードウェア関連の機能はホスト上(非コンテナ)に、アプリケーションに関する機能はDockerコンテナ上にPythonで実装していきます。これによりアプリケーション開発時はPC等で行い、ポータブルが必要な屋外テスト時にはDockerイメージをRasPi4にプッシュしてゴーというような環境を作りたいと思います。
なおLCD上のUIはハードウェア関連機能(非コンテナ)に含めます。またUIとアプリケーション間のメッセージングにはMQTTを使用し、コンテナ越し・ネットワーク越しでメッセージングできるようにします。

takumiquetakumique

Build host machine requirements

https://docs.yoctoproject.org/ref-manual/system-requirements.html

BSP bringup

まずはYocto 5.2のソースコードを取得します。まずはプロジェクト用のディレクトリを作り、その下にソースコードを取得します。

git clone -b walnascar-5.2 git://git.yoctoproject.org/poky
git clone -b walnascar git://git.yoctoproject.org/meta-raspberrypi
git clone -b walnascar git://git.openembedded.org/meta-openembedded

次にビルド環境を作成します。

cd poky
source oe-init-build-env ../build

これでディフォルトのbuildディレクトリが作成、環境変数がセットアップされbuildディレクトリに移動しました。../build部分のディレクトリ名はプロジェクトに応じて変更してください。

次に取得したmeta-raspberryypiおよびmeta-openembeddedのレイヤをビルドに追加します。

bitbake-layers add-layer ../meta-raspberrypi/
bitbake-layers add-layer ../meta-openembedded/meta-oe/
bitbake-layers add-layer ../meta-openembedded/meta-python/
bitbake-layers add-layer ../meta-openembedded/meta-networking/

追加したレイヤは<project top dir>/<build dir>/conf/bblayers.confに保存されますが、絶対パスで保存されるため<build dir>からの相対パスに書き換えます。

bblayers.conf
# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
POKY_BBLAYERS_CONF_VERSION = "2"

BBPATH = "${TOPDIR}"
BBFILES ?= ""

BBLAYERS ?= " \
  ${TOPDIR}/../poky/meta \
  ${TOPDIR}/../poky/meta-poky \
  ${TOPDIR}/../poky/meta-yocto-bsp \
  ${TOPDIR}/../meta-raspberrypi \
  ${TOPDIR}/../meta-openembedded/meta-oe \
  ${TOPDIR}/../meta-openembedded/meta-python \
  ${TOPDIR}/../meta-openembedded/meta-networking \
  "

プロジェクトの構成に合うようカスタマイゼーションします。<project top dir>/<build dir>/conf/local.confを編集します。

ターゲットマシンの定義します。

local.conf
MACHINE ??= "raspberrypi4-64"

今回使用するLCD解像度(800x480)は標準ドライバでは対応されていないため、ブートローダへ設定(/boot/config.txt)し、Kernelパラメータに追加します。(DMTフォーマットのカスタム解像度です)

/local.conf
# /boot/config.txt
RPI_EXTRA_CONFIG:append = "\n"
RPI_EXTRA_CONFIG:append = "hdmi_group=2\n"
RPI_EXTRA_CONFIG:append = "hdmi_mode=87\n"
RPI_EXTRA_CONFIG:append = "hdmi_cvt=800 480 60 6 0 0 0\n"

RasPiにてWiFiをenableするために、以下を追加します。

local.conf
# required for wifi
LICENSE_FLAGS_ACCEPTED = "synaptics-killswitch"

initをsystemdに変更します。

local.conf
DISTRO_FEATURES:append = " systemd"
INIT_MANAGER = "systemd"

これでビルドの準備ができました。ディレクトリ構成はこのようになります。

<project root> -+ build/
                + meta-openembedded/
                + meta-raspberrypi/
                + poky/

また、buildディレクトリには中間生成物、最終生成物が保存されます。buildディレクトリをgitで管理する場合は、以下のような.gitignoreファイルを作るとよいです。

.gitignore
/cache/
/downloads/
/sstate-cache/
/tmp/
/bitbake-cookerdaemon.log

ビルドします。後述の通り

  1. ウインドウシステムが不要
  2. WLANスタックが必要
    のため、ターゲットはcore-image-baseを使用し、必要な機能を追加していく方針とします。
bitbake core-image-base

ビルド時間はビルドマシンによりますが3時間程度でしょうか。

なお、bitbakeのエラーが発生する場合、このTipが役に立つかもしれません。

これで基本のBSPができました。

Flash and boot

ビルドされたイメージをSDカードにフラッシュします。

イメージファイルは<project top dir>/<build dir>/tmp/deploy/images/<target machine>/<build target>-<target machine>.rootfs-<timestamp>.wic.bz2となります。

SDカードをUSBリーダ・ライタにセットします。Ubuntu24では自動的にマウントされてしまうため、アンマウントします。

以下のコマンドで書き込みます。ここではSDカードは/dev/sdaとします。

sudo bmaptool copy <project top dir>/<build dir>/tmp/deploy/images/raspberrypi4-64/core-image-base-raspberrypi4-64.rootfs-<timestamp>.wic.bz2 /dev/sda

書き込みが終わったら、SDカードをRasPi4にセットしRasPi4を起動します。

うまくいけばLCDに起動ログが表示され、CLIのログインが表示されます。

takumiquetakumique

UI

MQTTブローカーとMQTTクライアントライブラリをインストールするため、build/conf/local.confに以下を追加しています。

local.conf
IMAGE_INSTALL:append = " mosquitto"
IMAGE_INSTALL:append = " paho-mqtt-c"
IMAGE_INSTALL:append = " paho-mqtt-cpp"

こちらにまとめました。
https://zenn.dev/takumique/articles/4b436162197148
ビルド対象に含めるため、以下のように追加します。

bblayers.conf
  ${TOPDIR}/../meta-sample-ui \
local.conf
IMAGE_INSTALL:append = " sample-ui"
IMAGE_INSTALL:append = " sample-ui-touchscreen"
IMAGE_INSTALL:append = " sample-ui-autorun"
takumiquetakumique

WLAN

shellスクリプトが依存するためbashとmqtt_pubコマンドをインストールするため、build/conf/local.confに以下を追加しています。

local.conf
IMAGE_INSTALL:append = " bash"
IMAGE_INSTALL:append = " mosquitto-clients"

こちらにまとめました。
https://zenn.dev/takumique/articles/d673da5a30957d
ビルド対象に含めるため、以下のように追加します。

bblayers.conf
  ${TOPDIR}/../meta-sample-connectivity \
local.conf
IMAGE_INSTALL:append = " wlan-enablers"
IMAGE_INSTALL:append = " wlan-monitor"
takumiquetakumique

ここまでで、こんなものができます。

WLANなし

DISCONNECTED

WLAN(モバイルルータ)の電源を入れて1分ほど待つと

CONNECTEDになりWLANインタフェースのIPが表示された

簡単なアプリケーションのログを表示するためにMQTTをpubすると

mosquitto_pub -d -t ui/state -m "{\"msg\":\"hello world!\"}"

takumiquetakumique

Docker CE環境

Yocto標準の仮想化関連のレシピはmeta-virtualizationに入っています。まずはこれをダウンロードします。

git clone -b walnascar git://git.yoctoproject.org/meta-virtualization

Docker CE関連をビルド対象に含めるため、以下のように追加します。

bblayers.conf
  ${TOPDIR}/../meta-openembedded/meta-filesystems \
  ${TOPDIR}/../meta-virtualization \
local.conf
DISTRO_FEATURES:append = " virtualization"

IMAGE_INSTALL:append = " packagegroup-docker"

これでターゲットデバイス上にDocker CE環境の準備ができました。

takumiquetakumique

アプリケーションDockerコンテナ

まずはDocker CE環境の上に単独のコンテナを動かします。

こちらにまとめました。
https://zenn.dev/takumique/articles/01d115c0c706d9

リンク先にもありますが、ターゲットイメージのビルド内でコンテナイメージをビルドする際、コンテナイメージに不要なパッケージを含まないために、local.confのIMAGE_INSTALL:appendCORE_IMAGE_EXTRA_INSTALL:appendに変更する必要があります。

local.conf
CORE_IMAGE_EXTRA_INSTALL:append = " bash"
CORE_IMAGE_EXTRA_INSTALL:append = " mosquitto"
CORE_IMAGE_EXTRA_INSTALL:append = " mosquitto-clients"
CORE_IMAGE_EXTRA_INSTALL:append = " paho-mqtt-c"
CORE_IMAGE_EXTRA_INSTALL:append = " paho-mqtt-cpp"
CORE_IMAGE_EXTRA_INSTALL:append = " sample-ui"
CORE_IMAGE_EXTRA_INSTALL:append = " sample-ui-touchscreen"
CORE_IMAGE_EXTRA_INSTALL:append = " sample-ui-autorun"
CORE_IMAGE_EXTRA_INSTALL:append = " wlan-enablers"
CORE_IMAGE_EXTRA_INSTALL:append = " wlan-monitor"
CORE_IMAGE_EXTRA_INSTALL:append = " docker"
CORE_IMAGE_EXTRA_INSTALL:append = " sample-api-autorun"
takumiquetakumique

実行時に必要なディスクスペースの確保

コンテナイメージのインポートなどで実行時にディスクスペースを必要とします。Yoctoでビルドされるwicはパーティション構成も含んでおり、rootfsのパーティションサイズはrootfsのサイズ+余白(IMAGE_OVERHEAD_FACTOR)となり余裕がありません。

そこでドキュメントにあるようにスペースを確保します。

私は64GBのSDカードを使っているので40GiB確保しました。これでrootfsパーティションはトータル52GiBになりました。今後の機能追加を考えても余裕があります。

local.conf
IMAGE_ROOTFS_EXTRA_SPACE = "41943040"
このスクラップは2ヶ月前にクローズされました