Firmware vom Fließband

IoT für Webentwickler: Continuous Integration im Internet der Dinge
Keine Kommentare

Im letzten Teil dieser Artikelserie ging es um die Grundlagen von PlatformIO: vom Projektbeginn über die Auswahl von Boards bis hin zum Kompilieren von Firmware für das Flashen und Monitoring. Alle Schritte mit der IDE erforderten Handarbeit des Entwicklers, doch haben wir uns in Zeiten von CI und CD an Automatisierung im Softwareentwicklungsprozess gewöhnt. Dieser Teil zeigt nun, wie CI und CD auch für Embedded möglich sind.

Mit PlatformIO liegt ein mächtiges Entwicklungswerkzeug vor, das viele Set-up-Schritte von der Auswahl bis zur Installation der notwendigen Toolchain-Teile wie Crosscompiler, Linker, Flashtools usw. automatisiert und dem Entwickler die Anpassung von Firmware code auf unterschiedliche Zielhardware erleichtert. Neben der Fähigkeit, verschiedene Embedded-Entwicklungsplattformen zu integrieren, zeichnet sich Platform IO dadurch aus, dass es die Aufgabenbereiche entlang der Wertschöpfungskette der Softwareentwicklung nachzeichnet. Dazu gehören u.a. automatisierte Verfahren zum Unit Testing und das automatische Bauen und Deployen von Software: alles Bestandteile von Continuous Integration (CI).

API Summit 2018

From Bad to Good – OpenID Connect/OAuth

mit Daniel Wagner (VERBUND) und Anton Kalcik (business.software.engineering)

Aufgaben von Continuous Integration

Dabei gehört CI im Bereich der Softwareentwicklung von Web- und Desktopapplikationen zum festen Werkzeugrepertoire. Fortlaufend werden in Build-Schritten Komponenten aus vorherigen Schritten mit den aktuellen
zusammengefügt, integriert, getestet, gegebenenfalls paketiert und bilden damit die Artefakte für die Folgeschritte. Ein Ziel ist unter anderem, durch den Automatisierungsprozess die Qualität der Ergebnisse zu erhöhen: Laufen alle Schritte automatisiert nach gleichem, qualitätsgesichertem Schema ab, steigt das Vertrauen in die Lieferfähigkeit.

Code stammt aus Code- und Artefakt- Repositories, wird automatisch kompiliert und gelinkt, getestet und optional auch Metriken sowie statischen und dynamischen Codeanalysen unterzogen. CI-Server sind meist direkt mit den Repositories verbunden, sodass jeder Code-Push einen CI-Lauf triggert. Somit kann für jede einzelne Codeänderung gezeigt werden, ob sie die Qualität verbessert oder verschlechtert. Mit Continuous Deployment wird der Automatisierungsschritt auch bis auf die Produktionssysteme ausgeweitet, d.h. die neu gebaute und durch Tests für gut befundene Anwendung lässt sich automatisch auf einem Server deployen.

CI für Embedded

Für den Bereich der Embedded-Entwicklung gilt es nun, einige Herausforderungen bezüglich CI zu meistern, da die Rahmenbedingung teils stark variieren. Die Integration in Code-Repositories kann dabei wohl alsidentisch angesehen werden, das Kompilieren des Firmwarecodes erfordert im Fall von C/C++ geeignete Compiler, die aber ebenfalls verfügbar und automatisch installierbar sind. Einzig die Existenz spezieller Compiler kann auf bestimmte Plattformen eingeschränkt sein, was für die Auswahl der CI Worker Nodes interessant ist.

Die ersten Unterschiede ergeben sich beim Testen: Vom Firmwarecode lassen sich die Teile, die unabhängig von der Hardware und dem Embedded-Betriebssystem sind, auch auf einem Intel- oder ARM-basierten Server oder Notebook testen. Code, der Bibliotheken des Embedded-OS oder der Hardwareabstraktionsschicht nutzt, muss in der Regel auf dem Embedded-Gerät bzw. einem äquivalenten Entwicklerboard laufen. Das ist nicht unbedingt schwierig zu realisieren, aber zu berücksichtigen.

Das Verwalten der Artefakte ist fast identisch: Kompilierte/gelinkte Firmwareteile sind Binärdateien. Das Deployment wiederum ist grundverschieden: Im letzten Teil dieser Serie haben wir das NodeMcu-Board über ein USB-Kabel geflasht. Alternativ kann– je nach Board und Einstellungen– ein USB-Programmer zum Einsatz kommen. Entsprechend vorbereitete Embedded- Geräte können auch over the Air, z.B. über Wi-Fi,ihre Firmware erhalten. Auf jeden Fall müssen dazu der CI-Server und das Board (räumlich) enger miteinander kommunizieren als z.B. ein CI-Server mit einem Applikationsserver in der Cloud. PlatformIO bietet auch hierfür eine Lösung an.

CI in der Cloud

In diesem Teil der Artikelserie zeigen wir anhand von zwei Cloud-basierten CI-Diensten, wie sich Firmware vom CI-Dienst kompilieren, testen und remote auf ein Embedded-Device flashen lässt. Als Basis dient Platform IO mit dem Codebeispiel des letzten Teils. Es befindet sich zum Download auf GitHub . Als CIDienst kommt CircleCI zum Einsatz. CircleCI kann Projekte von u.a. GitHub und BitBucket einbinden. Um das Beispiel nachzuvollziehen, ist ein Account bei den jeweiligen Providern sinnvoll, die Anmeldung bei Circle-CI kann dann über OAuth geschehen. Zum Auffrischen und Einstieg in PlatformIO (PIO) schauen wir noch kurz auf die Kommandos zum Kompilieren und Flashen des Democodes. Listing 1 gibt eine kompakte Übersicht.

 
# Auschecken des Democodes
$ git clone https://github.com/thingforward/entwicklermagazin2018
-pio-repo.git
# Kompilieren und Linken
$ pio run
# "Upload" == Flashen
$ pio run –t upload
# Überwachung der Ausgabe auf dem seriellen Port
$ pio device monitor

Eine relevante Funktion für CI ist das Remote Flashing, sie ist Teil von PlatformIO Plus (PIOPlus) und erlaubt es, die PIO-Instanz auf einem fernen PC über ein Access Token fernzusteuern. Für CI bedeutet es, dass der CI-Service in der Cloud autorisiert werden kann, eine Firmware auf ein Device zu flashen, das über USB an einem ganz anderen Server/Notebook angeschlossen ist. PIO Remote erfordert eine Registrierung bei Platform-IO (Listing 2), kann aber in der Communityvariante mit einem Agent und einer begrenzten Anzahl von Updates pro Monat ausprobiert werden.

 
# Registrierung zu PIOPlus
$ pio account register
PlatformIO Plus (https://pioplus.com) v1.1.6
E-Mail: ……
Successfully registered!
Please check your E-Mail for the further instructions
$ pio account login
PlatformIO Plus (https://pioplus.com) v1.1.6
E-Mail: ...
# Starten des Remote Agents mit Namen "remote-1"
$ pio remote agent start --name "remote-1"
PlatformIO Plus (https://pioplus.com) v1.1.6
2018-04-12 14:11:47 [info] Name: remote-1
2018-04-12 14:11:47 [info] Connecting to PIO Remote Cloud
2018-04-12 14:11:47 [info] Successfully connected
2018-04-12 14:11:47 [info] Authenticating
2018-04-12 14:11:47 [info] Successfully authorized
# Erzeugen eines Tokens
$ pio account token
PlatformIO Plus (https://pioplus.com) v1.1.6
Password:
Personal Authentication Token:
2adf3778a01e4bff6688677908ea9705d5f9ab91

Die letzten beiden Befehle aus Listing 2 stellen die Verbindung der Remote-Enden dar: Pio remote agent start startet den Remote Agent und registriert ihn als Endpunkt in der PlatformIO-Cloud unter remote-1. Die Anweisung pio account token erzeugt ein Access Token. Um Firmware remote zu flashen, wird dem run-Kommando das remote-Kommando vorangestellt, und die kompilierte Firmware wandert übers Netz an den Agent. Das Token wird als Environment-Variable vorangestellt:

$ PLATFORMIO_AUTH_TOKEN=2ad…91 pio remote -a remote-1 run -t upload

Auf der Seite des Agent sieht man Empfang und Ausführung des Kommandos:

2018-04-12 14:21:13 [info] Remote command received: psync
2018-04-12 14:21:18 [info] Remote command received: run

Integration in CircleCI

Um nun die Firmware mit CircleCI bauen und re mote flashen zu können, erfolgt der Log-in zu CircleCI in O Auth-Verbindung zum Repository, z.B. GitHub. Um das Demoprojekt durchzuspielen, empfiehlt es sich, das Repository des Beispiels in den eigenen GitHub-Account zu forken. Auf dem Dashboard bringt in der linken Buttonleiste ein Klick auf Add Projects die aktiven Repositories auf den Schirm, ein weiterer Klick auf Set Up Project beim richtigen Projekt triggert das Einrichten.

Im folgenden Schritt können Betriebssystem und Sprachumgebung ausgewählt werden. In unserem Fall läuft PlatformIO als Python-Projekt unter Linux. An dieser Stelle muss CircleCI wissen, wie eigentlich gebaut, getestet und geflasht wird. Das Ganze lässt sich aus dem Code-Repository heraus mit einer Konfigurationsdatei steuern. CircleCI unterstützt zwei Varianten: 1.0 und 2.0. Erstere ist die ältere, aber in PlatformIO dokumentierte Variante . Dafür wird im PIO-Projektverzeichnis eine YAML-Datei circle.yml erstellt und mit den Befehlen für den Aufbau der Build-Umgebung, für das Bauen des Projekts und des Remote-Flashens erstellt (Listing 3).

1 dependencies:
2 pre:
3 # Install the latest stable PlatformIO
4 - sudo pip install -U platformio
5 # preinstall esp8266 platform
6 - platformio platform install espressif8266
7 compile:
8 override:
9 - pio run -e nodemcuv2
10 deployment:
11 override:
12 - pio remote -a remote-1 run -t upload

Im pre-Teil (Zeilen 1-6) liegen die für die Installation von PlatformIO notwendigen Shell-Befehle: PIO selbst wird über pip, den Python Package Index Manager, installiert. Als Beispiel für weitere pre-Schritte fügen wir die espressif8266-Platform hinzu, um die Compiler-Toolchain zu erhalten. Der compile-Teil (Zeilen 7-9) kompiliert und linkt, der deployment-Teil am Ende nutzt das Kommando pio remote flash, um das Board zu flashen. Hierfür muss am anderen Enpunkt der PIO Remote Agent gestartet und das Development Board über USB angeschlossen werden (in unserem Fall ein Node-Mcu).

Eine Einstellung muss nach Anlage des Projekts noch gewählt werden, CircleCI muss nämlich das PLATFORMIO_AUTH_TOKEN erfahren. Das lässt sich in den Projekteinstellungen unter Settings|Organization/Projects, dann mit Klick auf das Zahnrad des Projekts vornehmen. Das Access Token lässt sich unter Enviroment  Variables, Add Variables hinzufügen.

CircleCI wird nun bei jedem Git Push in den Master bzw. in Branches aktiv und das Projekt automatisch bauen. Alternativ kann ein Neubauen manuell aus dem Dashboard heraus getriggert werden. Ein einzelner Build besteht aus mehreren Schritten, die der Reihe nach ausgeführt werden. Man kann einem Build-Vorgang live zuschauen oder sich im Nachgang die Logs ansehen, indem die Bereiche aufgeklappt werden. Abbildung 1 zeigt die Bereiche compile und deployment mit den entsprechenden PIO-Kommandos, Abbildung 2 das erfolgreiche Remote-Deployment. CircleCI verwendet das Auth-Token, um die erstellte Firmware über das Netz an den eigenen Remote Agent zu senden und sie zu flashen. Damit lassen sich auch komplexere Set-ups ermöglichen, sodass sich z.B. unterschiedliche Versionen/Branches auf unterschiedliche Devices einer Device/Test Fleet installieren lassen.

Abb. 1: CircleCI: Konfigurierte Build-Schritte im Dashboard

Abb. 1: CircleCI: Konfigurierte Build-Schritte im Dashboard

 

Abb.2: CircleCI: Remote-Flashen der Firmware

Abb. 2: CircleCI: Remote-Flashen der Firmware

Fazit

Continuous Integration für Embedded in der Cloud ist möglich. CircleCI ist dafür nur ein Beispiel. PlatformIO unterstützt weitere CI-Dienste in der Cloud oder in einer lokalen Installation wie z.B. Jenkins. Aufmerksame Leser und Beobachter des CircleCI-Dashboards werden gemerkt haben, dass wir einen wichtigen Schritt unterschlagen haben: das Testen. Im nächsten Teil der Serie zeigen wir, wie sich Unit-Tests für Embedded-Geräte einfach aufsetzen lassen.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -