Raspberry Pi OS - GUI in C#
Da quando ho iniziato a utilizzare Raspberry (praticamente tutte le versioni), ho sempre avuto una domanda:
"Posso sviluppare un'applicazione con una GUI in C# per Raspberry?"
La risposta è Si! E' possibile. In questo articolo illustro come installare .NET7 su un Raspberry Pi 2W (ma vale per qualsiasi versione), far girare un'applicazione Blazor e avviare il Raspberry in modalità Kiosk aprendo il browser all'indirizzo dell'app Blazor.
Gli step da eseguire sono:
- Installazione di Raspberry Pi OS Lite
- Installazione di .NET7
- Servizio per l'avvio dell'app Blazor
- Impostazione della modalità Kiosk e apertura del browser
Alla fine di questo articolo trovi i 3 script da eseguire. Di seguito invece la spiegazione passo passo.
Installazione di Raspberry Pi OS Lite
Il primo passo consiste nell'installare Raspberry Pi OS Lite. Ho optato per la versione Lite ovvero senza desktop.
Per la scrittura della SD Card utilizzo "Pi Imager" scaricabile da Raspberry Pi OS – Raspberry Pi
Avviato Pi Imager, basta selezionare il device, il tipo di sistema operativo e la Sd Card.
Cliccando CTRL+SHIFT+x si aprirà la finestra che consente di impostare i valori iniziali della rete e abilitare l'accesso tramite SSH.


Conosco l'IP, ma conviene impostare l'hostname. Nel mio caso sarà myrasp.local
A questo punto è possibile avviare la scrittura della SD Card e attendere il completamento dell'operazione.
Una volta terminato il processo di scrittura e verifica è possibile inserire l' SD Card nel nostro Raspberry e collegare l'alimentazione.
Io ho utilizzato un Raspberry Pi Zero 2W.
Configurazione al primo avvio di Raspberry Pi OS Lite su Raspberry Pi Zero 2W
Appena collegato all'alimentazione, il Raspberry Pi Zero 2W eseguirà il primo avvio e impiegherà un po più del solito ad avviarsi.
Per praticità ho momentaneamente connesso uno schermo HDMI da 7 pollici.
Eseguirò i vari comandi sul Raspberry dal mio pc Windows tramite SSH.
Si parte!
ssh pi@https://myrasp.local
Ecco il primo intoppo:

Questo errore deriva dal fatto che avevo già connesso il mio PC al Raspberry (che ha mantenuto lo stesso IP) e quindi sono state scritte delle righe nel file C:\Users\giuse\.ssh\known_hosts
Per risolvere il problema basta aprire il suddetto file e rimuovere le righe che iniziano con l'IP myrasp.local, salvare e riprovare

Una volta connesso al Raspberry tramite SSH conviene lanciare i classici comandi per aggiornare il software.
sudo apt update
sudo apt full-upgrade
In base ai pacchetti da installare potrebbe essere richiesta una conferma. In tal caso premere "y" e invio (eventualmente è possibile usare il comando "sudo apt full-upgrade --yes --force-yes").
Il tempo necessario potrebbe essere di svariati minuti. Nel mio caso una decina.
Alla fine del processo riavviare utilizzando il comando:
sudo reboot
Installazione di DotNet Core 7
Per l'installazione del Microsoft .NET 7 mi baserò sul seguente articolo:
Install .NET on Linux without using a package manager - .NET | Microsoft Learn
sudo mkdir /home/downloads
sudo wget https://download.visualstudio.microsoft.com/download/pr/560e89a4-c731-430a-a810-4e88a846494e/d8b477e0c06c8324769ed3c94703a9ee/dotnet-sdk-7.0.403-linux-arm.tar.gz -O /home/downloads/dotnet-sdk-7.0.403-linux-arm.tar.gz
sudo wget https://download.visualstudio.microsoft.com/download/pr/c22fa1bc-42ce-45c1-b1fd-0f496ed4409e/64ec95fb21e37872e36ccd04521acf5c/aspnetcore-runtime-7.0.13-linux-arm.tar.gz -O /home/downloads/aspnetcore-runtime-7.0.13-linux-arm.tar.gz
sudo mkdir /.dotnet
sudo tar -xvf /home/downloads/dotnet-sdk-7.0.403-linux-arm.tar.gz -C /.dotnet
sudo tar -xvf /home/downloads/aspnetcore-runtime-7.0.13-linux-arm.tar.gz -C /.dotnet
echo 'export DOTNET_ROOT=/.dotnet' >> ~/.bashrc
echo 'export PATH=$PATH:/.dotnet' >> ~/.bashrc
Riavviare con il solito sudo reboot.
Per verificare la corretta installazione utilizzare il comando:
dotnet --version
L'output dovrebbe essere il seguente:
pi@raspberrypi:~ $ dotnet --version
7.0.403
Pubblicazione dell'app Blazor su Raspberry Pi Zero 2W
Userò come applicazione da pubblicare un'app Blazor Server con framework .NET 7.
Ne creo una con il template di default offerto da Visual Studio 2022 e faccio una piccola modifica.
Nel file Program.cs, aggiungere alla riga 12:
builder.WebHost.UseUrls("https://*:5001");
In realtà avrei potuto indicare un hostname e così avrei evitato l'ip.
Lo step fondamentale è la creazione del profilo di pubblicazione.
Scelgo di pubblicare su una folder locale ("D:\temp\BlazorTestApp\releases") col il seguente profilo di pubblicazione:

Utilizzo FileZilla per caricare i files dell'app sul Raspberry.
Carico quindi i files nella mia home del Raspberry /testblazorapp

A questo punto posso avviare l'app Blazor eseguendo il seguente comando:
dotnet ./BlazorApp1.dll

Dal browser del pc adesso dovrebbe essere possibile navigare sull'indirizzo https://myrasp.local:5001/
A questo punto siamo sicuri che Blazor viene eseguito correttamente dal Raspberry.
Avvio dell'app Blazor all startup
Per una spiegazione più dettagliata fare riferimento a Creating an Autostart .NET 6 Service on a Raspberry Pi (nikouusitalo.com)
Creare il file mykiosk.service con i seguente comando:
sudo nano /etc/systemd/system/mykiosk.service
e incollare le seguenti linee
[Unit]
Description=My Blazor App
[Service]
ExecStart=/.dotnet/dotnet ./BlazorApp1.dll
WorkingDirectory=/home/pi/testblazorapp
Restart=always
RestartSec=10
User=pi
Group=pi
[Install]
WantedBy=multi-user.target
Adesso eseguire i seguenti comandi:
sudo systemctl enable mykiosk.service #enables autostart
sudo systemctl start mykiosk.service #runs now
sudo systemctl status mykiosk.service #checks status
Installazione di Xserver
sudo apt-get install --no-install-recommends xserver-xorg
sudo apt-get install --no-install-recommends xinit
sudo apt-get install --no-install-recommends x11-xserver-utils
Installazione di Chromium
Ho scelto Chromium perchè offre un'ottima esperienza nella modalità "Kiosk".
sudo apt-get install chromium-browser
sudo apt-get install matchbox-window-manager xautomation unclutter
NOTA: l'installazione durerà parecchi minuti.Nel mio caso una ventina
Configurazione Autostart
Adesso non resta che configurare come Raspberry Pi OS dovrà comportarsi all'avvio.
Creare un file chiamato ~/mykiosk nella home dell'utente pi
nano ~/mykiosk
e incollare le seguenti linee
#!/bin/sh
xset -dpms # disable DPMS (Energy Star) features.
xset s off # disable screen saver
xset s noblank # don't blank the video device
matchbox-window-manager -use_titlebar no &
unclutter & # hide X mouse cursor unless mouse activated
chromium-browser --display=:0 --kiosk --window-position=0,0 https://iemma.it
Poi è necessario dare i permessi di esecuzione al file con il comando:
sudo chmod 755 ~/mykiosk
Adesso è necessario aggiungere lo script appena creato al file .bashrc
nano ~/.bashrc
Aggiungere la seguente riga
xinit /home/pi/mykiosk -- vt$(fgconsole)
Adesso riavviare con il solito "sudo reboot".
Potrebbe essere necessario diverso tempo perchè Rasberry avvierà il browser e caricherà il sito.
A riavvio completato, riconnettersi con SSH e lanciare il comando
sudo raspi-config
Nel menu Display Options -> Selezionare D2 e poi confermare
Nel menu System Options -> S5 Boot/Auto Login selezionare "B2 Console Autologin Text console, automatically logged in as 'pi' user".
Gli script completi
Copia dei file
mkdir /home/pi/testblazorapp
Copiare binari application Blazor in /home/pi/testblazorapp
Primo script
sudo apt update
sudo apt full-upgrade --yes --force-yes
sudo reboot
Secondo script
sudo mkdir /home/downloads
sudo wget https://download.visualstudio.microsoft.com/download/pr/560e89a4-c731-430a-a810-4e88a846494e/d8b477e0c06c8324769ed3c94703a9ee/dotnet-sdk-7.0.403-linux-arm.tar.gz -O /home/downloads/dotnet-sdk-7.0.403-linux-arm.tar.gz
sudo wget https://download.visualstudio.microsoft.com/download/pr/c22fa1bc-42ce-45c1-b1fd-0f496ed4409e/64ec95fb21e37872e36ccd04521acf5c/aspnetcore-runtime-7.0.13-linux-arm.tar.gz -O /home/downloads/aspnetcore-runtime-7.0.13-linux-arm.tar.gz
sudo mkdir /.dotnet
sudo tar -xvf /home/downloads/dotnet-sdk-7.0.403-linux-arm.tar.gz -C /.dotnet
sudo tar -xvf /home/downloads/aspnetcore-runtime-7.0.13-linux-arm.tar.gz -C /.dotnet
echo 'export DOTNET_ROOT=/.dotnet' >> ~/.bashrc
echo 'export PATH=$PATH:/.dotnet' >> ~/.bashrc
/.dotnet/dotnet dev-certs https --trust
sudo reboot
Terzo script
echo '[Unit]' | sudo tee -a /etc/systemd/system/mykiosk.service
echo 'Description=My Blazor App' | sudo tee -a /etc/systemd/system/mykiosk.service
echo '' | sudo tee -a /etc/systemd/system/mykiosk.service
echo '[Service]' | sudo tee -a /etc/systemd/system/mykiosk.service
echo 'ExecStart=/.dotnet/dotnet ./BlazorApp1.dll' | sudo tee -a /etc/systemd/system/mykiosk.service
echo 'WorkingDirectory=/home/pi/testblazorapp' | sudo tee -a /etc/systemd/system/mykiosk.service
echo 'Restart=always' | sudo tee -a /etc/systemd/system/mykiosk.service
echo 'RestartSec=10' | sudo tee -a /etc/systemd/system/mykiosk.service
echo 'User=pi' | sudo tee -a /etc/systemd/system/mykiosk.service
echo 'Group=pi' | sudo tee -a /etc/systemd/system/mykiosk.service
echo '' | sudo tee -a /etc/systemd/system/mykiosk.service
echo '[Install]' | sudo tee -a /etc/systemd/system/mykiosk.service
echo 'WantedBy=multi-user.target' | sudo tee -a /etc/systemd/system/mykiosk.service
sudo systemctl enable mykiosk.service #enables autostart
sudo systemctl start mykiosk.service #runs now
sudo systemctl status mykiosk.service #checks status
sudo apt-get -y install --no-install-recommends xserver-xorg
sudo apt-get -y install --no-install-recommends xinit
sudo apt-get -y install --no-install-recommends x11-xserver-utils
sudo apt-get -y install chromium-browser
sudo apt-get -y install matchbox-window-manager xautomation unclutter
echo '#!/bin/sh' | sudo tee -a ~/mykiosk
echo 'xset -dpms # disable DPMS (Energy Star) features.' | sudo tee -a ~/mykiosk
echo 'xset s off # disable screen saver' | sudo tee -a ~/mykiosk
echo 'xset s noblank # don t blank the video device' | sudo tee -a ~/mykiosk
echo 'matchbox-window-manager -use_titlebar no &' | sudo tee -a ~/mykiosk
echo 'unclutter & # hide X mouse cursor unless mouse activated' | sudo tee -a ~/mykiosk
echo 'chromium-browser --display=:0 --kiosk --window-position=0,0 https://myrasp.local:5001/' | sudo tee -a ~/mykiosk
sudo chmod 755 ~/mykiosk
echo 'xinit /home/pi/mykiosk -- vt$(fgconsole)' >> ~/.bashrc
sudo raspi-config
Nel menu Display Options -> Selezionare D2 e poi confermare
Nel menu System Options -> S5 Boot/Auto Login selezionare "B2 Console Autologin Text console, automatically logged in as 'pi' user".