Serie: Embedded Linux - SpotyPee

  Götz   Lesezeit: 13 Minuten  🗪 4 Kommentare

Ein Beispielprojekt für Yocto, welches mit einem Raspberry-Pi 3B und Audio-Dongle eine alte Anlage Spotify tauglich aufrüstet.

serie: embedded linux - spotypee

Dies ist Teil 3 und der letzte Teil der Serie zu Yocto. Es wird ein Beispiel zu Yocto vorgestellt, welches von dem Autor als Privatprojekt entwickelt wurde, um seine alte Anlage Spotify tauglich zu machen.

Die verwendete Hardware ist:

  • Raspberry-Pi 3B
  • Raspberry-Pi Netzteil
  • UGREEN USB Audio 3.5mm mit dem Realtek ALC4030
  • Aux Kabel 3,5-mm Audiokabel Klinke auf Klinke
  • 4 GB SD-Karte

Für das Bauen des Images sind mindestens 60 GB freier Speicherplatz notwendig. Der Buildprozess dauert mit einem mittelklassigem Desktopsystem 8h. Die Belastung des Systems ist immer um die 90-100%.

Schnellanleitung

Wer nur das Projekt reproduzieren möchte, der kann mit der Schnellanleitung arbeiten, die Hintergründe werden weiter unten im Text erläutert:

  1. Klone das Repository SpotyPee.

  2. Das Buildsystem ist in Docker-Container verpackt. Diese sind auf dem Dockerhub verfügbar, können aber auch mit den verwendeten Dockerfiles aus dem Repository lokal gebaut werden. Die aktuelle Yocto Version ist kirkstone und der zu verwendete Tag des Dockercontainers und Branch des Projekts sind gleichnamig.

  3. Im Repository ist nach dem Klonen der Default-Branch kirkstone, dieser ist die aktuelle und zu verwendete Version. Die Buildumgebung kann mit dem darin enthaltenen Docker-Compose Datei docker-compose.yml einfach instantiiert werden: docker-compose run yocto_build bash erzeugt die Buildumgebung und öffnet eine Shell in der Buildumgebung.

  4. In der Buildumgebung muss das Buildverzeichnis unter home/yocto/build erzeugt werden. Dazu wechselt man in das Verzeichnis home/yocto/SpotyPee/spotypee_build und erzeugt das Buildverzeichnis mit source oe-init-build-env /home/yocto/yocto/build. Sollte man den Buildvorgang abbrechen, so kann mit dem gleichen Befehl in den Kontext des alten Buildverzeichnis wechseln. Damit werden die bisherigen Fortschritte wiederverwendet.

  5. Im Buildverzeichnis home/yocto/yocto/build liegt der die Datei conf/local.conf. In dieser Datei sind die zwei Variablen WLAN_SSID und WLAN_PASSWORD zu setzten.

    Diese werden dem Image automatisch hinzugefügt und melden den Raspberry im lokalen WLAN Netzwerk an.

  6. Der Buildprozess wird mit BitBake gestartet bitbake spotypee erzeugt das Image, welches später mit einem beliebigen Imager auf die SD-Karte geschrieben werden kann.

  7. Nach dem Abschluss des Vorgangs kann aus dem Buildordner unter tmp/deploy/images/raspberrypi3-64/ das *.rpi-image kopiert werden. Das Image muss aus dem Docker-Volume extrahiert werden. Es gibt hierfür viele Methoden, der Autor erzeugt ein zusätzliches Volume, welches auf einen Ordner im lokalen Dateisystem mappt und ergänze damit das docker-compose.yml. Im Container kopiere der Autor das Image in das lokale Volume.

  8. Das extrahierte Image ist auf die SD-Karte zu übertragen und damit dem vorbereiteten Raspberry-Pi zu füttern. Sobald die Stromversorgung steht und die WLAN-Verbindung aufgebaut wurde, sollte in deiner Spotify-App ein neues Abspielgerät auftauchen.

Aufbau

Alle Dateien unterhalb des Ordners meta-rpi-config bilden den Layer, der das Image für den Raspberry-Pi 3B baut. Der Layer beschreibt neben den einzelnen Rezepten auch eine Distribution. Für das Projekt wird nicht die Standarddistribution Poky verwendet, sondern aufbauend darauf die Distribution standard.

Der Layer ist von dem Projekt meta-raspberrypi zusätzlich abhängig. Dieses bietet eine Hardwarebeschreibung, Kernel und Userland die für die Verwendung eines Raspberry-Pis notwendig sind. Kurz: Es ist ein Yocto BSP für den Raspberry-Pi.

Die Rezepte lassen sich auch in zwei Unterkategorien unterteilen:

  • System: Alle Programme & Anpassungen die für die Applikation notwendig sind.
  • Applikation: Rezept, welches den eigentlichen «Nutzen» erbringt.

Distribution: standard

Die Distribution ist von Poky abgeleitet. Es definiert die Verwendung von Systemd als init-System und aktiviert aus dem Standardbaukasten von Yocto einige Funktionen. Dazu gehört:

  • wifi: Eine generelle Unterstützung von WLAN.
  • pam: Eine grundsätzliche Bereitstellung für PAM (Pluggable Authentication Modules). Ist in Kombination mit SSH sehr nützlich.
  • pulseaudio: Ist das Audio Backend für die Wiedergabe über den USB-Audio-Wandler.
  • linux-firmware-rpidistro: Spielt die Raspberry-Pi spezifische Firmware in das Image. Wird durch das externe BSP Layer meta-raspberrypi bereitgestellt.
  • security: Ein externer Security-Layer stellt sicherheitsspezifische Einstellungen und Pakete bereit. Es arbeitet eng mit Yocto und OpenEmbedded zusammenarbeitet und erhöht das Security-Niveau eines erzeugten Images.
  • largefile: Unterstützt grosse Dateien unter Linux. Ist per Default immer gesetzt, wenn es nicht verfügbar ist so ist das Verhalten, laut Dokumentation, "unvorhersehbar".
  • systemd: Muss aktiviert sein, wenn standardmässig Systemd als init-System verwendet werden soll.

Daneben werden auch noch einige hardwarespezifische Anpassungen gemacht. Sämtliche Programme und Funktionen, die für das grafische Darstellen von Informationen notwendig sind, werden explizit entfernt. Ebenso wird, durch Schalter in der config.txt, der GPU-Speicher auf 16 MB reduziert und die Bussysteme I2C und SPI abgeschaltet. Für den USB-Audio-Dongle wird das Feature max_usb_current=1 aktiviert. Damit wird die Strombegrenzung aufgehoben. Dies ist für den spezifischen Dongle notwendig, da ansonsten die Ausgangsleistung der Endstufe zu gering ist.

Es gibt weitere Einstellungen, diese sind aber für die Applikation nicht relevant.

Distribution: Beispielkonfigurationen

Die bblayers.conf.sample beschreibt den Pfad aller Layer in eurem Dateisystem. Ist es dort nicht aufgeführt "findet" es BitBake nicht. Es wird für jede neue Buildinstanz neu in das Konfigurationsverzeichnis kopiert. Es liegt im gleichen Verzeichnis wie die Konfiguration, bekannt aus der Schnellanleitung.

Das local.conf.sample ist die Blaupause für jede Buildinstanz. Darin werden zentrale Konfigurationen und in diesem Projekt zusätzlich die Zugangsdaten für WLAN abgelegt. Entsprechende Platzhalter sind definiert.

Rezept: recipes-bsp

In diesem Rezept wird von der config.txt die Option

  • disable_overscan=1: Kein Display vorhanden
  • dtparam=audio=on: Nutze nicht das Hardware-Audio

Rezept: recipes-core

Diese Rezepte sind teilweise auch in den oberen Layern vorhanden. Mit der hier abgebildeten Struktur wird die aus dem oberen Layer nachgebildet. Die Rezepte mit .bbappend erweitern die ursprünglichen Rezepte. Es ergänzt das Rezept und erweitert, überschreibt oder sogar redefiniert verwendete Variablen und Funktionen.

Busybox

Das Rezept ändert die Einstellungen der Busybox auf des Autors Ansprüche für eingebettete Systeme ab. Es sind eine Reihe von Funktionen betreffend Swap ab und welche für das Arbeiten mit Hardwarefunktionen eingeschaltet. Die Konfiguration entspricht dem des Makefiles der Konfigurationsdatei der Busybox.

Images

Das Rezept spotypee.bb erzeugt das abschliessende Image, welches auf dem Raspberry-Pi 3B aufgespielt wird. Dabei werden alle Rezepte referenziert, die zusätzlich zur Distribution hinzukommen.

In dem Rezept wird auch das Passwort für den Nutzer "root" auf "root" gesetzt. Dies kann nach dem Booten geändert werden oder direkt im Rezept. Eine Anleitung im Rezept ist enthalten. Man kann sich nicht mit root über SSH anmelden.

Pulseaudio-volume

Das Rezept installiert einen Systemd-Autostart, welcher die Lautsärke für die Audioquelle 0 (USB-Audio Stick) auf 100 % setzt.

Spotify

Das Rezept erzeugt einen Systemd-Autostart für die Applikation librespot. Die Applikation wird mit den Rechten des in dem Rezept erzeugten Nutzer spotify mit dem Standardpasswort spotify gestartet. Man kann sich mit dem Nutzer auf dem Pi über SSH aufschalten. Die im Autostart verwendeten Einstellungen können aus der Dokumentation für librespot nachvollzogen werden. Da kann man sich auch den etwas kindischen Namen des Clients im Netzwerk anpassen.

Möchte man das Passwort ändern, so kann man das direkt in dem Rezept anpassen (Anleitung enthalten) oder kann dies nach dem erstmaligen Anmelden direkt ändern.

Rezept: linux-kernel

Dieses Rezept ändert einige Einstellungen für den Kernel, basierend auf der Standardkonfiguration von Raspberry-Pi. Ähnlich zu Busybox sind die Änderungen der Konfiguration gleich dem der Kernel Konfiguration. Die Änderungen umfassen:

  • Das ALSA System wird als Teil des Kernels gebaut und nicht in ein Modul ausgelagert. Der Treiber für USB-Audio und dem entsprechenden Dongle wird ebenfalls dem Kernel hinzugefügt.
  • Die Treiber für den Audioanschluss des Raspberry-Pis, den SPI und I2C Bus werden deaktiviert.
  • Zusätzlich werden die Treiber für nicht verwendete Dateisysteme, Hardwarefunktionen und weitere Treiber deaktiviert. Dadurch verringert sich die Größe des Kernels beträchtlich.
  • Der Governor ist im Standard auf Powersave, dies kann aber zu stockender Wiedergabe führen. Deswegen wird der Governor auf Ondemand umgestellt, damit sich der CPU Takt zur benötigten Leistung anpasst. Damit bleibt die Wiedergabe flüssig.
  • Der Kernel wird auf Größe optimiert gebaut.

Rezept: librespot

Das Rezept baut den freien Spotify Client. Dieser lässt sich durch einen weiteren, beliebigen Spotify Client im Netzwerk steuern.

Das librespot Projekt ist ein FOSS Client für Spotify. Es erlaubt die Wiedergabe von Musik von Spotify und bietet dazu eine Reihe von Einstellungen an. So kann z.B. die Qualität, der Name des Gerätes im Netzwerk gesetzt und verschiedene Backends selektiert werden.

Rezept: Wlan-config

Das Rezept generiert für eine gegebene SSID und ein Passwort eine wpa_supplicant Konfiguration. Das Passwort wird mit dem PBKDF2 Verfahren verschlüsselt und im Image abgelegt. Damit kann aus dem Image nicht das Passwort für das WLAN im Klartext ausgelesen werden. Zusätzlich wird beim Systemstart versucht sich mit dem entsprechenden WLAN zu verbinden.

Bemerkungen

Im Dauerbetrieb benötigt der Raspberry-Pi 3B sehr wenig Energie. Es sollte auch möglich sein auf einem schwächeren Raspberry-Pi 2 oder Zero W zu wechseln. Die entsprechenden Konfigurationen wurden von mir nicht getestet.

Die Hardwareplattform wird in der "local.conf" angepasst. Die Variable "MACHINE" wird von "raspberrypi3-64" zu "raspberrypi0-wifi" für ein Raspberry Pi Zero W geändert. Dies gilt auch für eine Nutzung anderer Raspberry-Pi Versionen. Dazu bitte auf die passende Maschinenkonfiguration wechseln.

Die Dokumentation auf dem Repository ist noch dürftig wird aber mit der Zeit von mir ergänzt werden.

Tags

Embedded, Yocto, OpenEmbedded, Bitbake, System-Builder, SpotyPee

understater
Geschrieben von understater am 12. Juli 2022 um 10:23

Da in diesem Artikel sehr viele Details sind, kann ich nicht alles nachvollziehen. Alles in allem sicher eine sehr ambitionierte Lösung! Lasst mich trotzdem Anmerkungen machen:

  • Der genannte "USB to Klinke" Adapter scheint nicht mehr gelistet zu sein, jedenfalls geht der Link ins leere. Es gibt auch andere, die "out of the box" linuxtauglich sind. Ich weiß nur nicht, ob die notwendigen Treiber automatisch mit in diesem Docker sind.

  • Wie wird Spotify hier bedient? Ist es nicht einfacher einen "Bluetooth to Klinke" Adapter an die Anlage zu stecken und Spotify auf dem Handy zu betreiben? Oder wie ich es mache: Volumio auf dem RasPi. Der kann Spotify und die (sofern vorhanden) lokale Musiksammlung, plus Internetradio. Also auch Musik hören wenn das Internet mal "kaputt" ist. Volumio kann vom Browser auf jedem Gerät im Heimnetz bedient werden.

  • Spotify? Ist auch nur eine Firma auf dem Weg nach oben um alles drumherum platt zu machen. Und tut immer so als sei es der einzige Zugang zu Podcasts.

Goetz
Geschrieben von Goetz am 13. Juli 2022 um 23:59

Das Linux verwendet hier den Treiber welcher für USB-Audio verfügbar ist. Also den Standardtreiber mit dem Standardprotokoll, entsprechend sollte jeder Dongle funktionieren der damit wirbt auf praktisch allem, ohne zusätzliche Treiber zu benötigen, zu laufen. Ich kann dir leider keinen neuen Link anbieten, die komplette Sparte scheint von UGREEN "weg" zu sein. Ich kann dir nur das Angebot machen einen Amazon-Link reinzuposten. Aber eigentlich möchte ich Amazon nicht unterstützten und Werbung für ihr System machen. Andere Verkaufsplattformen konnte ich nicht finden die den vertreiben. Spotify wird hier über die Spotify-App bedient. Du kannst jedes Gerät mit Applikation von einem anderen Client im gleichen W-LAN Netz fernsteuern. Ist meistens rechts unten direkt neben dem Lautstärkeregler, dass Hamburger-Menü. Man braucht hier keine GUI, läuft alles über das Spotify Protokoll. Warum Spotify? Ich höre viel Musik über Spotify, dabei entdecke ich Neues, die entsprechenden Algorithmen machen hier einen guten Dienst. Leider ist auch Spotify nicht fair im Umgang mit den Nutzern (DRM) und auch nicht fair mit seinen Mitbewerbern (Podcasts, Spotify-Originals). Ich kaufe auch die Musik die mir gefällt, vielleicht mache ich dazu auch mal ein Image, welches genau diese Bedürfnisse erfüllt? Volumio kenne ich bis jetzt noch nicht. Ich schaue es mir mal an.

gerriet
Geschrieben von gerriet am 12. Juli 2022 um 12:13

Die UGreen seite zeigt ne schöne 404 seite 🤣

Goetz
Geschrieben von Goetz am 14. Juli 2022 um 00:00

Leider ja, ich weiss nicht warum. Den einzigen Link den ich noch habe zeigt zu Amazon. Den würde ich ungern einstellen, da ich keine Werbung für ihre Plattform machen möchte.