Raspberry Pi + YoctoでWLAN自動接続・状況監視の実装
作りたいものの全体像から参照しています
作りたいもの
Raspberry Pi 4 (RasPi4)にYoctoを載せて、WLAN(WiFi)に自動接続させます。また接続状況と現在のIPを監視しUIに表示させます。
動作する全ソースコードをGitHubで公開しています。
ハードウェア
RasPi4のWLANをそのまま使います。HDMIと同時に使う場合ハードウェアの問題でWLANが接続できない場合があります。私の場合、HDMIケーブルを変えることで回避できました。
デバイスドライバ
デバイスドライバはYocto 5.2のRasPi4ターゲット標準のデバイスドライバを使用します。
local.confに下記のおまじないが必要です。これはRasPi(Broadcom)のWiFiファームウェアのライセンスにSynaptics has the right, in its sole discretion, to terminate this agreement immediately by giving written notice of termination to you.
という文言が含まれており、このリスクを了承するという意味合いです。
# required for wifi
LICENSE_FLAGS_ACCEPTED = "synaptics-killswitch"
wpa supplicant
wpa supplicantもYocto 5.2のRasPi4ターゲット標準のwpa supplicantを使用します。
実装
それでは作っていきます。meta-sample-connectivityレポジトリを作成し、その下にrecipes-wlanディレクトリを作成してここにレシピを作っていきます。なお、initマネージャはsystemdを前提にしています。
WLAN enablers
実際のレシピはこちらです。
wpa_supplicant.conf
簡単のためWPA2などは設定していません。必要に応じて変更してください。
wpa_supplicant自動起動
systemd-serviceとしてwpa_supplicantを起動します。
systemd-networkd
systemd-networkdを設定し、DHCPクライアントを設定してもらいます。
WLAN接続状況監視
実際のレシピはこちらです。
shellスクリプトを作成し、cronのかわりにsystemd timerから定期的に実行することで実現します。
定期的ip
コマンドでwlan0
のインタフェース情報を取得+パースしてIPアドレスが表示されていたら接続状態として、そうでなければ未接続状態としてMQTTメッセージを送信しているだけです。
一点わかりにくいのがwhileの中はサブシェル(子プロセス)で実行されるため、普通にexitしても親プロセスは実行を継続する点(結果ループ継続→最後の"DISCONNECTED"送信)です。これを回避するため親プロセスでサブシェルの異常終了(ここではexit 1
)をトラップして、親プロセスを正常終了させています。
#!/bin/sh
# trap subshell error, code 1 is SUCCESS_PUBLISH
set -E
trap '[ "$?" -ne 1 ] || exit 0' ERR
DEVICE=wlan0
ip addr show dev ${DEVICE} |
while read row; do
col1=`echo ${row} | cut -d ' ' -f 1`
col2=`echo ${row} | cut -d ' ' -f 2`
if [[ "${col1}" == "inet" ]]; then
/usr/bin/mosquitto_pub -d -t ui/state -m "{\"wlan\":\"CONNECTED: ${col2}\"}"
# return error to exit main shell safely
exit 1
fi
done
/usr/bin/mosquitto_pub -d -t ui/state -m "{\"wlan\":\"DISCONNECTED\"}"
Yoctoターゲットのビルド対象への追加
最後にこれまでのレシピをYoctoターゲットのビルド対象に追加します。
${TOPDIR}/../meta-sample-connectivity \
CORE_IMAGE_EXTRA_INSTALL:append = " wlan-enablers"
CORE_IMAGE_EXTRA_INSTALL:append = " wlan-monitor"
Discussion