Raspberry Pi OS - GUI in C#

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:

  1. Installazione di Raspberry Pi OS Lite
  2. Installazione di .NET7
  3. Servizio per l'avvio dell'app Blazor
  4. 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.

Configure network on Raspberry pi zero 2W
Enable ssh on Raspberry pi zero 2W

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:

Ssh error Raspberry pi zero 2W

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

Ssh error confirm Raspberry pi zero 2W

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:

 

VS2022 Publish profile for Raspberry Pi 2W

Utilizzo FileZilla per caricare i files dell'app sul Raspberry.

Carico quindi i files nella mia home del Raspberry /testblazorapp

Blazor app on Raspberry Pi 2W (files)

A questo punto posso avviare l'app Blazor eseguendo il seguente comando:

 dotnet ./BlazorApp1.dll
Blazor app on Raspberry Pi 2W (on execution)

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

it/Xorg - Debian Wiki

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".