概要
製作意図はRaspberry PiをSIP電話またはインターホンシステムのエントリーパネル(ドアホン)として利用(試験用)するためです。 SIP-VoIP機能により、SIP電話として利用する場合は、室内モニターや家族との通話手段として、ドアホンとして利用する場合は、訪問者の確認や訪問者との通話、ドアロックの解除などを遠隔から行えます。組み込み向けLinuxディストリビューションを構築できるYoctoを使用して、Raspberry Pi 2 向けのカスタム専用イメージを作成します。モバイル側のアプリにはLinhomeを使用します。
-
コンピュータボード:Raspberry Pi 2(カメラ、ボタン、ドアスイッチ、マイク、スピーカ)
-
モバイルアプリ:Android Linhome(ドアの開閉、ビデオによる訪問者の確認、通話)
マイクとスピーカの接続にはI2S(Inter-IC Sound)インターフェイスを利用するため、I2S音声入出力に対応したサウンドデバイス googlevoicehat-soundcard を採用します。( hifiberry-dac はI2Sの音声入力に対応していないため採用しません。)
-
マイク: INMP441 Datasheet
-
DAC: MAX98357 I2S Class-D Mono Amp
-
サウンドデバイス:googlevoicehat-soundcard
-
picamera v1.3: Hardware Specification
注)ボタンおよびドアスイッチは接続せず、SSH接続によるリモートからのGPIOピンのステータス確認や操作で代替します。
Yocto Project
バージョン5.0.4 Scarthgap を使用。
The Yocto Project ® 5.0.4 documentation
10 Images — The Yocto Project ® 5.0.4 documentation
11 Features — The Yocto Project ® 5.0.4 documentation
ビルドにはビルドツールであるPokyとビルドに必要な レイヤー(meta-xxx) を組入れたDockerコンテナを利用します。
Yoctoで使用されるレシピとは、機能ごとまたは機種ごとに分割されたビルト条件と手順が記述されたファイル群で、これを纏めたものがレイヤーとなります。
Dockerイメージの作成
Linphoneのビルドに必要なレシピとビルド環境を一つのコンテナに纏めます。このためのdockerfileを作成します。
以下、任意で作成したディレクトリ scarthgap-raspberrypi2/ の中での作業とします。
scarthgap-raspberrypi2/dockerfile
FROM debian:11
ARG YOCTO_VERSION=scarthgap
ARG BITBAKE_TARGET=core-image-sato
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get -y upgrade
# Required Packages for the Host Development System
# https://docs.yoctoproject.org/ref-manual/system-requirements.html#required-packages-for-the-build-host
RUN apt-get update && \
apt-get install -y gawk wget git diffstat unzip texinfo gcc build-essential chrpath socat \
cpio python3 python3-pip python3-pexpect xz-utils debianutils iputils-ping python3-git \
python3-jinja2 libegl1-mesa libsdl1.2-dev pylint3 xterm python3-subunit mesa-common-dev \
zstd liblz4-tool screen nano && \
apt-get clean
# Additional host packages needed for build
RUN apt-get update && \
apt-get install -y file && \
apt-get clean
# Additional host packages needed for qemu
RUN apt-get update && \
apt-get install -y iproute2 && \
apt-get clean
# Additional host packages required by poky/scripts/wic
RUN apt-get update && \
apt-get install -y curl dosfstools mtools parted syslinux tree zip && \
apt-get clean
# Create a non-root user that will perform the actual build
RUN id build 2>/dev/null || useradd --uid 30000 --create-home build
RUN apt-get install -y sudo
RUN echo "build ALL=(ALL) NOPASSWD: ALL" | tee -a /etc/sudoers
# Fix error "Please use a locale setting which supports utf-8."
# See https://wiki.yoctoproject.org/wiki/TipsAndTricks/ResolvingLocaleIssues
RUN apt-get install -y locales
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
echo 'LANG="en_US.UTF-8"'>/etc/default/locale && \
dpkg-reconfigure --frontend=noninteractive locales && \
update-locale LANG=en_US.UTF-8
ENV LC_ALL=en_US.UTF-8
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US.UTF-8
USER build
WORKDIR /home/build
# Clone yocto
RUN git clone -b "${YOCTO_VERSION}" git://git.yoctoproject.org/poky
WORKDIR poky
RUN git clone -b "${YOCTO_VERSION}" git://git.openembedded.org/meta-openembedded
RUN git clone -b "${YOCTO_VERSION}" git://git.yoctoproject.org/meta-raspberrypi
WORKDIR /home/build/poky
#RUN bash -c 'source oe-init-build-env && bitbake ${BITBAKE_TARGET}'
CMD ["bash"]
上記dockerfileでイメージ作成
$ docker build scarthgap-raspberrypi2 -t raspberrypi2
ホストとコンテナ間の共有フォルダにbuildを指定し、上記イメージからコンテナraspi2を起動、buildディレクトリのアクセス権を変更します。
$ docker run --name raspi2 -v ./build:/home/build/poky/build -ti raspberrypi2 bash
# sudo chown -R build:build build
linphone-sdkのmetaレイヤーであるmeta-bcのyoctoブランチをダウンロード( /home/build/poky 内)し、meta-bc/conf/layer.conf 内で
LAYERSERIES_COMPAT_bc = “scarthgap”
とします。
# git clone https://gitlab.linphone.org/BC/public/meta-bc.git -b feature/yocto-kirkstone
meta-bc/conf/layer.conf
LAYERSERIES_COMPAT_bc = "scarthgap"
ビルド環境の初期化コマンドを実行します。
# source oe-init-build-env
You had no conf/local.conf file. This configuration file has therefore been
created for you from /home/build/poky/meta-poky/conf/templates/default/local.conf.sample
You may wish to edit it to, for example, select a different MACHINE (target
hardware).
You had no conf/bblayers.conf file. This configuration file has therefore been
created for you from /home/build/poky/meta-poky/conf/templates/default/bblayers.conf.sample
To add additional metadata layers into your configuration please add entries
to conf/bblayers.conf.
The Yocto Project has extensive documentation about OE including a reference
manual which can be found at:
https://docs.yoctoproject.org
For more information about OpenEmbedded see the website:
https://www.openembedded.org/
This is the default build configuration for the Poky reference distribution.
### Shell environment set up for builds. ###
You can now run 'bitbake <target>'
Common targets are:
core-image-minimal
core-image-full-cmdline
core-image-sato
core-image-weston
meta-toolchain
meta-ide-support
You can also run generated qemu images with a command like 'runqemu qemux86-64'.
Other commonly useful commands are:
- 'devtool' and 'recipetool' handle common recipe tasks
- 'bitbake-layers' handles common layer tasks
- 'oe-pkgdata-util' handles common target package tasks
注)# source oe-init-build-env を実行すると自動的にhome/build/poxy/buildディレクトリに移動し、build/confディレクトリに設定ファイルが作成されます。
ビルド設定ファイルの編集
レイヤーリスト(Scarthgap Ver5.0)
レイヤー “meta-raspberrypi” レシピ(マシン)リスト(Scarthgap Ver5.0)
ホストと共有した build/conf ディレクトリに作成された bblayers.conf, local.conf ファイルを編集します。
bblayers.conf : イメージビルドに必要なmetaレイヤーを指定
build/conf/bblayers.conf
# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
POKY_BBLAYERS_CONF_VERSION = "2"
BSPDIR := "${@os.path.abspath(os.path.dirname(d.getVar('FILE', True)) + '/../..')}"
BBPATH = "${TOPDIR}"
BBFILES ?= ""
BBLAYERS ?= " \
${BSPDIR}/meta \
${BSPDIR}/meta-poky \
${BSPDIR}/meta-openembedded/meta-oe \
${BSPDIR}/meta-openembedded/meta-networking \
${BSPDIR}/meta-openembedded/meta-python \
${BSPDIR}/meta-openembedded/meta-multimedia \
${BSPDIR}/meta-yocto-bsp \
${BSPDIR}/meta-raspberrypi \
${BSPDIR}/meta-bc \
"
local.conf : イメージへの追加レシピや対象機種、ビルド条件などを設定
追加レシピ
IMAGE_INSTALL:append = …
ここでmeta-bcのlinphone-sdkをビルドするためのオプションも追加します。以下参照。
対象機種
MACHINE = “raspberrypi2”
ビデオ拡張機能
VIDEO_CAMERA = “1”
他の機能も必要であれば、下記 meta-raspberrypi ドキュメントを参照し有効化して下さい。
build/conf/local.conf
MACHINE = "raspberrypi2"
VIDEO_CAMERA = "1"
DISTRO ?= "poky"
PACKAGE_CLASSES ?= "package_ipk"
EXTRA_IMAGE_FEATURES ?= "debug-tweaks ssh-server-openssh"
USER_CLASSES ?= "buildstats"
PATCHRESOLVE = "noop"
BB_DISKMON_DIRS ??= "\
STOPTASKS,${TMPDIR},1G,100K \
STOPTASKS,${DL_DIR},1G,100K \
STOPTASKS,${SSTATE_DIR},1G,100K \
STOPTASKS,/tmp,100M,100K \
HALT,${TMPDIR},100M,1K \
HALT,${DL_DIR},100M,1K \
HALT,${SSTATE_DIR},100M,1K \
HALT,/tmp,10M,1K"
CONF_VERSION = "2"
# Additional configuration, added recipes of Branch: kirkstone https://layers.openembedded.org/layerindex/branch/kirkstone/recipes
IMAGE_INSTALL:append = " alsa-plugins alsa-utils alsa-lib boost gettext glew libopus libsrtp libvpx pulseaudio v4l-utils raspi-gpio linphone-sdk openssl mpg123"
LICENSE_FLAGS_ACCEPTED = "commercial"
PACKAGE_CLASSES ?= "package_ipk"
PACKAGECONFIG:append:pn-linphone-sdk = " h264 mdns"
PACKAGECONFIG:append:pn-avahi = " libdns_sd"
BB_NUMBER_THREADS ?= "8"
CORE_IMAGE_EXTRA_INSTALL += "dhcpcd"
CORE_IMAGE_EXTRA_INSTALL += "init-ifupdown"
INHERIT += "rm_work"
イメージのビルド:Bitbake
bitbakeコマンドでlinphone(-sdk)のビルドを実行します(ホストマシンのスペックにより、終了するまで数時間を要します)。ここでの単独ビルドを省略しても、linphone-sdkはlocal.confのIMAGE_INSTALL:appendで指定しているので、この作業は最終ビルドイメージ作成時に実行されます。事前に単独ビルドすることで、エラー発生時のリカバリコストを最小限に抑えることができると思います。
BitBake User Manual
# bitbake linphone-sdk
core-image-satoを指定して最終イメージをビルド
# bitbake core-image-sato
ビルドイメージは下記フォルダに出力されます。以下圧縮ファイルを展開
build/tmp/deploy/images/raspberrypi2/core-image-sato-raspberrypi2-2024xxxxxxxxxx.rootfs.wic.bz2
$ bzip2 -d core-image-sato-raspberrypi2-2024xxxxxxxxxx.rootfs.wic.bz2
SDカードへの書込み
$ sudo dd if=core-image-sato-raspberrypi2-2024xxxxxxxxxx.rootfs.wic of=/dev/sda bs=1024
イメージファイルの容量は1-2GBのため、SD容量を有効活用するため、ディスクユーティリティーでSDの最大容量までrootディレクトリの拡張を行って下さい。
googlevoicehatオーバレイの作成
googlevoicehat-soundcard.dtbo は、マイクとDACをGPIOのI2Sインターフェイスで利用するためのデバイスツリーオーバレイですが、デフォルトではコンパイルされていないため、手動でデバイスツリーソースファイルからコンパイルします。
googlevouicehat の dts ファイルからオーバレイファイルを手動でコンパイル(raspi2コンテナ内で実行)。
# find . -name "*.dts" | grep googlevoicehat
./build/tmp/work-shared/raspberrypi2/kernel-source/arch/arm/boot/dts/overlays/googlevoicehat-soundcard-overlay.dts
# sudo apt install device-tree-compiler
# dtc -@ -I dts -O dtb -o googlevoicehat-soundcard.dtbo build/tmp/work-shared/raspberrypi2/kernel-source/arch/arm/boot/dts/overlays/googlevoicehat-soundcard-overlay.dts
注) dtc (Device Tree Compiler) は、多くの Linux システムで利用可能なユーティリティで、デバイスツリーソース(DTS)ファイルをコンパイルしてバイナリ形式のデバイスツリーブロブ(DTB/DTBO)ファイルを生成します。
作成されたデバイスツリーオーバレイ googlevoicehat-soundcard-overlay.dtbo を SDカードの /boot/ovelays にコピーします。
config.txt による起動条件
起動時の追加条件を/boot/config.txtで設定します。
https://www.raspberrypi.com/documentation/computers/config_txt.html
ビデオメモリ指定
gpu_mem=128
オーバレイ追加
dtoverlay=googlevoicehat-soundcard
起動・動作確認(ビデオ・サウンド出力)
イメージを書き込んだSDカードをRaspberry Piにセットし起動します。
ビデオ・カメラ動作
カメラ接続確認
# v4l2-ctl --all
Driver Info:
Driver name : bcm2835 mmal
Card type : mmal service 16.1
Bus info : platform:bcm2835_v4l2-0
Driver version : 6.6.22
Capabilities : 0x85200005
Video Capture
Video Overlay
Read/Write
Streaming
Extended Pix Format
Device Capabilities
.......
.......
テストショット
# v4l2-ctl --stream-mmap --stream-count=1 --stream-to=capture.jpeg
フォーマット確認
# v4l2-ctl --list-formats
ioctl: VIDIOC_ENUM_FMT
Type: Video Capture
[0]: 'YU12' (Planar YUV 4:2:0)
[1]: 'YUYV' (YUYV 4:2:2)
[2]: 'RGB3' (24-bit RGB 8-8-8)
[3]: 'JPEG' (JFIF JPEG, compressed)
[4]: 'H264' (H.264, compressed)
[5]: 'MJPG' (Motion-JPEG, compressed)
[6]: 'YVYU' (YVYU 4:2:2)
[7]: 'VYUY' (VYUY 4:2:2)
[8]: 'UYVY' (UYVY 4:2:2)
[9]: 'NV12' (Y/UV 4:2:0)
[10]: 'BGR3' (24-bit BGR 8-8-8)
[11]: 'YV12' (Planar YVU 4:2:0)
[12]: 'NV21' (Y/VU 4:2:0)
[13]: 'RX24' (32-bit XBGR 8-8-8-8)
ストリームテスト
# v4l2-ctl --stream-mmap --stream-count=10
<<<<<<< 5.55 fps
<<<
サウンド関連
Playback, Captureデバイスの確認
# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: vc4hdmi [vc4-hdmi], device 0: MAI PCM i2s-hifi-0 [MAI PCM i2s-hifi-0]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: sndrpigooglevoi [snd_rpi_googlevoicehat_soundcar], device 0: Google voiceHAT SoundCard HiFi voicehat-hifi-0 [Google voiceHAT SoundCard HiFi voicehat-hifi-0]
Subdevices: 1/1
Subdevice #0: subdevice #0
# arecord -l
**** List of CAPTURE Hardware Devices ****
card 1: sndrpigooglevoi [snd_rpi_googlevoicehat_soundcar], device 0: Google voiceHAT SoundCard HiFi voicehat-hifi-0 [Google voiceHAT SoundCard HiFi voicehat-hifi-0]
Subdevices: 1/1
Subdevice #0: subdevice #0
上記出力を受けて、ALSA設定ファイル(dmixer対応 ~/.asoundrc)をここで作成します。
.asoundrc
pcm.!default {
type asym
playback.pcm "plug:softvol"
capture.pcm "plug:capture_level"
}
ctl.!default {
type hw
card 1
}
pcm.voicehat_playback {
type hw
card 1
device 0
format S32_LE
}
pcm.voicehat_capture {
type hw
card 1
device 0
format S32_LE
}
pcm.softvol {
type softvol
slave.pcm "dmixed_playback"
control.name "Softvol Playback Volume"
control.card 1
min_dB -3.0
max_dB 30.0
}
pcm.dmixed_playback {
type dmix
ipc_key 1024
slave {
pcm "voicehat_playback"
period_time 0
period_size 1024
buffer_size 8192
rate 48000
format S32_LE
}
bindings {
0 0
1 1
}
}
pcm.capture_level {
type softvol
slave.pcm "voicehat_capture"
control.name "Level Capture"
control.card 1
min_dB -3.0
max_dB 30.0
}
スピーカテスト
# speaker-test -D plughw:1,0 -c2
# speaker-test -D plughw:1,0 -c2 --test=wav -w /usr/share/sounds/alsa/Front_Center.wav
注) plughw:1,0 はカード1、デバイス0 を指定。~/.asound.conf : card 1 を指定
録音・再生テスト
# arecord -d 5 -f cd -V mono test.wav
# aplay test.wav
音量・マイク感度はalsamixerで調整して下さい。
# alsamixer
Linphoneの起動
初回起動時に必要なデータベースファイル(ディレクトリ)を予め作成すること。
# cd /opt/belledonne-communications/bin/
# mkdir -p /home/root/.local/share/linphone
# touch /home/root/.local/share/linphone/x3dh.c25519.sqlite3
# touch /home/root/.local/share/linphone/linphone.db
起動
# /opt/belledonne-communications/bin/linphone-daemon
daemon-linphone>
起動オプション
# /opt/belledonne-communications/bin/linphone-daemon --help
daemon-linphone [<options>]
Licence: Commercial
where options are :
--help Print this notice.
--dump-commands-help Dump the help of every available commands.
--dump-commands-html-help Dump the help of every available commands.
--pipe <pipepath> Create an unix server socket in the specified path to receive commands from. For Windows just use a name instead of a path.
--log <path> Supply a file where the log will be saved.
--factory-config <path> Supply a readonly linphonerc style config file to start with.
--config <path> Supply a linphonerc style config file to start with.
--disable-stats-events Do not automatically raise RTP statistics events.
--enable-lsd Use the linphone sound daemon.
-C Enable video capture.
-D Enable video display.
--auto-answer Automatically answer incoming calls.
ビデオキャプチャ、自動応答ON、ログ取得オプションを有効にして起動
# linphone-daemon --config linphonerc -C --auto-answer --log ./linphone_log
Linhoneデーモンヘルプ
daemon-linphone>help
Status: Ok
adaptive-jitter-compensation [audio|video] [enable|disable]
answer <call_id>
audio-codec-disable <payload_type_number>|<mime_type>|ALL
audio-codec-enable <payload_type_number>|<mime_type>|ALL
audio-codec-get <payload_type_number>|<mime_type>
audio-codec-move <payload_type_number>|<mime_type> <index>
......
......
ユーザ認証とその確認
daemon-linphone>register sip:[email protected] sip.linphone.org password
Status: Ok
Id: 1
daemon-linphone>register-status ALL
Status: Ok
Id: 1
State: LinphoneRegistrationOk
呼出
daemon-linphone>call [email protected]
呼び出し元が同一ドメインである場合:@以降省略可
daemon-linphone>call capitalfuse
Linhomeクライアントとの送受信確認
Linhomeの設定は Linhome Free SIP Service へのプロビジョニングによって固定されているため、設定を変更するには、独自のアカウントマネージャを用意し、カスタムURLを含むQRコードを生成して読み込む必要があります。