ASP.NET Core auf dem Pi unter Linux

Bisher habe ich meine Hobby-Projekte immer mit Python auf der Pi geschrieben. Wenn man hier einen kleinen WebServer verwenden will, dann bietet sich z.B. Flask Microframework an und funktioniert prima. Mit dotnet ergibt sich eine Alternative – ASP.NET Core. Grund genug einmal auszuprobieren, wie man z.B. eine API zum Auslesen von Daten oder steuern der GPIO Pins auf dem Pi verwenden kann.

Erster Schritt – .NET Core Installieren

Eine sehr gute Anleitung gibt es z.B. hier in diesem Blog von Scott Hanselman. Der Einfachheit halber hier die notwendige Schritte und Kommandos nochmal aufgelistet.

Zuerst installieren wir die Voraussetzungen für .NET Core.

sudo apt-get install curl libunwind8 gettext

Dann laden wir die dotnet-core runtime für ARM32 herunter. Um den URL zu bekommen, kann man – wie Scott schreibt – auf dieser Seite Download .NET die Runtime auswählen. Und dann den Link über „click here to download manually“ herausfinden.

Bei mir ist das die Version 2.2.300 für ARM32 die man unter diesem Link findet.

Wir laden sie mit wget auf der pi herunter:

wget https://download.visualstudio.microsoft.com/download/pr/da881751-01f9-4ea0-8021-0b9c61d0cef6/87c4620dc5af2085d54e9860fad13552/dotnet-sdk-2.2.300-linux-arm.tar.gz

Jetzt müssen wir das SDK auspacken und die Pfade anpassen, damit wir es aufrufen können. Dazu wird ein Verzeichnis erstellt und darin ausgepackt.

mkdir $HOME/dotnet
tar zxf dotnet-sdk-2.2.300-linux-arm.tar.gz -C $HOME/dotnet

Auf die gleiche Art und Weise holen und installieren wir noch die ASP.NET Core Runtime, die wir hier finden.

wget https://download.visualstudio.microsoft.com/download/pr/cd6635b9-f6f8-4c2d-beda-2e381fe39586/740973b83c199bf863a51c83a2432151/aspnetcore-runtime-2.2.5-linux-arm.tar.gz
tar zxf aspnetcore-runtime-2.2.5-linux-arm.tar.gz -C $HOME/dotnet

Jetzt müssen wir dotnet noch in Pfad eintragen, damit wir das Kommando verwenden können. Das geht am einfachsten mit „nano“ und in der Datei „.profile“. Wir fügen am Ende folgendes ein:

# add dotnet to path
if [ -d "$HOME/dotnet" ] ; then
    PATH="$HOME/dotnet:$PATH"
fi

Die Datei kann man mit folgender Zeile neu einlesen, dann muss man sich nicht aus und wieder einloggen.

. ./.profile

Jetzt können wir testen, ob dotnet korrekt installiert ist. Dazu geben wir folgendes ein:

dotnet --info

Wir sehen, dotnet ist auf der pi installiert und läuft. ASP.NET Core ist auch drauf. Als nächsten Schritt bauen wir eine kleine WebAPI und rufen diese von aussen auf.

Zweiter Schritt – eine WebAPI für den Zugriff

Zuerst erstellen wir mit dotnet einen Rahmen der Applikation, dass nimmt uns einiges an Arbeit ab. Den Namen bekommt die Applikation durch den Verzeichnisnamen. Ich erstelle sowas immer in einem Unterordner dev, da finde ich mich dann leichter zurecht.

cd dev
mkdir MyVoltageWebAPI
cd MyVoltageWebAPI
dotnet new webapi

Danach haben wir folgende Dateien erstellt bekommen.

Wir wollen z.B. eine Funktion anbieten, die eine Spannung über einen AD Wandler ausliest. Hierfür brauchen wir zwei Dinge – einen Service der uns die Daten liefert und einen Controller, der die Schnittstelle anbietet.

Zunächst erstellen wir den Controller. Wir entfernen den Dummy-Controller für „Values“ und erstellen unseren eigenen für das Auslesen einer Spannung.

rm Controllers/ValuesController.cs
nano Controllers/CurrentVoltageController.cs

Hier packen wir folgenden Code rein:

namespace MyVoltageWebAPI.Controllers
{
    using System;
    using Microsoft.AspNetCore.Mvc;
    using Services;

    [ApiController]
    [Route("[controller]")]
    public class VoltageController : ControllerBase
    {
        private readonly IVoltageService _voltageService;
        
        public VoltageController(IVoltageService voltageService)
        {
            _voltageService = voltageService ?? throw new ArgumentNullException(nameof(voltageService));
        }
        
        [HttpGet("/voltage/current") ]
        public double Current()
        {
            return _voltageService.CurrentVoltage();
        }
    }
}

Damit dieser funktioniert brauchen wir noch den Service, den wir zuerst mal nur als Stub implementieren.

mkdir Services
nano Services/VoltageService.cs

Hier die Implementierung des Service:

namespace MyVoltageWebAPI.Services
{
    public class VoltageService : IVoltageService
    {
        public double CurrentVoltage()
        {
             return 1.1;
        }
    }
}

Wir geben hier einfach einen konstanten Wert zurück. Im dritten Schritt binden wir hier ein sinnvolles Backend an.

Dazu kommt noch ein Service-Interface über das wir den Service im Controller verwenden wollen:

nano Services/IVoltageService.cs

Mit folgenden Inhalt:

namespace MyVoltageWebAPI.Services
{
    public interface IVoltageService
    {
        double CurrentVoltage();
    }
}

Damit der Service jetzt als „Dependency“ in den Controller übergeben wird können wir diesen noch in der Datei startup.cs registrieren.

nano Startup.cs

Hierfür fügen wir in der Funktion ConfigureServices die Zeile für den VoltageService hinzu:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IVoltageService>(new VoltageService());
    services.AddControllers();
}

Nicht vergessen – das using für Services auch in Startup.cs einzutragen sonst findet der Compiler den VoltageService nicht.

using MyVoltageWebAPI.Services;

So das wars – probieren wir mal ob wir alles richtig gemacht haben.

dotnet publish -c Release -r linux-arm

Danach starten wir die API – diese horcht standardmäßig auf https://localhost:5001.

Unser Controller ist unter voltage/current zu erreichen:

curl -k -O https://localhost:5001/voltage/current
cat current

Wie wir sehen, wird von curl eine Datei heruntergeladen, die als Inhalt unseren Wert enthält, den wir im Service-Dummy zurückgeben haben. Great!

Dritter Schritt – ein sinnvolles Backend Zugriff auf den AD Wandler

Im dritten Teil ersetzen wir das Backend durch einen sinnvollen Aufruf zum Auslesen eines AD Wandlers der an dem I2C Bus der Raspberry angeschlossen ist.

Stay tuned…

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.