thomasgalliker / PiWeatherStation

Weather Station for RasperryPi and Waveshare ePaper Displays

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

PiWeatherStation

This is a demo project which uses a Raspberry Pi 4 / Zero 2 to draw some basic weather information to a 7.5" Waveshare ePaper display. The code is based on .NET 6 and there are two runtime projects you can chose from: A console client (WeatherDisplay.ConsoleApp) and an ASP.NET Core Web API (WeatherDisplay.Api).

Quick Setup

The script file update_weatherdisplay_api.sh contains all necessary steps to prepare a new Raspberry Pi to run WeatherDisplay.Api:

  • Downloads and installs the .NET SDK.
  • Downloads and installs WeatherDisplay.Api as a service.
  • Adjusts the Raspberry Pi hardware configuration. (Enables SPI, sets dtoverlays).
  • Configures the wifi to become an access point.
  • Sets environment variables.

Log-in to the Raspberry Pi and run the script file as follows.

curl -sSL https://raw.githubusercontent.com/thomasgalliker/PiWeatherStation/develop/WeatherDisplay.Api/Scripts/update_weatherdisplay_api.sh | sudo bash /dev/stdin

Append script parameters if needed:

Parameter Description
--pre Downloads pre-releases of WeatherDisplay.Api.
--debug Writes verbose log messages to the console (mainly used for debugging purposes).
--host Sets the hostname. By default, a portion of the hardware serial number is used as hostname. The hostname can be changed later.
--keyboard Sets the keyboard layout (e.g. "us" or "de").
--locale Sets the localization/language.
--timezone Sets the timezone.
--no-reboot After the setup, a full reboot cycle is required. This parameter suppresses the reboot. This is mainly used of debugging purposes.
curl -sSL https://raw.githubusercontent.com/thomasgalliker/PiWeatherStation/develop/WeatherDisplay.Api/Scripts/update_weatherdisplay_api.sh | sudo bash /dev/stdin --debug --pre

Extended Setup / Troubleshooting

The following steps are fully automated in update_weatherdisplay_api.sh. Follow these steps if the update script cause troubles.

Prepare the Raspberry Pi

  • Before we install any additional library, make sure the Raspberry OS as well as the installed libraries are on the latest stable releases. apt update updates the package sources list to get the latest list of available packages in the repositories. apt upgrade updates all the packages presently installed in our Linux system to their latest versions.
sudo apt update
sudo apt upgrade
  • Install the GDI+ library. This library is later used to render images via SkiaSharp.
sudo apt-get install -y libgdiplus
  • Reboot the system.
sudo reboot
  • Set correct timezone. Run command timedatectl list-timezones in order to find your timezone.
sudo timedatectl set-timezone Europe/Zurich

Install .NET on Raspberry Pi

  • Go to Microsoft's dotnet download page and download the appropriate version of .NET. I usually use the 32bit Version of Raspbian OS, so the appropriate .NET architecture should be ARM32.
  • The following dotnet-install.sh script simplifies the automated installation of dotnet on Linux:
curl -sSL https://dot.net/v1/dotnet-install.sh | sudo bash /dev/stdin --version latest --channel 8.0 --install-dir /home/pi/.dotnet
  • Edit the bash profile and add following lines to the end of the file. If export PATH already exists, extend it instead of creating a new export. Use sudo nano ~/.bashrc to double check if everything is fine.
echo 'export DOTNET_ROOT=$HOME/.dotnet' >> ~/.bashrc
echo 'export PATH=$PATH:$HOME/.dotnet' >> ~/.bashrc
  • Reload the ~/.bashrc file with the command:
source ~/.bashrc
  • Reboot the system.
sudo reboot
  • Run dotnet --info to check if your .NET installation works as expected:
pi@raspberrypi:~ $ dotnet --info
.NET SDK (reflecting any global.json):
 Version:   8.x.xxx
 Commit:    ...

Runtime Environment:
 OS Name:     raspbian
 OS Version:  11
 OS Platform: Linux
 RID:         linux-arm
 Base Path:   /home/pi/.dotnet/sdk/8.x.xxx/
 ...

Attach the Waveshare Display & enable GPIO

  • Shutdown the the Raspberry using sudo shutdown -h "now". Disconnect the Raspberry from all power sources.
  • Attach the Waveshare Display Hat to the GPIO port of the Raspberry. Start the Raspberry up again.
  • Edit the config.txt in order to enable the SPI interface.
sudo nano /boot/config.txt
  • Enable the SPI interface.
dtparam=spi=on
  • Add this line if you get IOException: Device or resource busy : '/sys/class/gpio/export'. More info here.
#dtoverlay=spi0-1cs,cs0_pin=28
  • Reboot the system.
sudo reboot

Deploy WeatherDisplay.Api

  • Prepare the project folder on the Raspberry Pi:
cd ~
mkdir WeatherDisplay.Api
  • Download the latest stable release from https://github.com/thomasgalliker/PiWeatherStation/releases. Extract the zip to the target directory /home/pi/WeatherDisplay.Api.
  • Alternatively, you can build the WeatherDisplay.Api project with RELEASE build configuration and copy the binaries to the Raspberry Pi using WinSCP (or any other file transfer tool). There are also other ways (like dotnet publish) to get a set of release-ready binaries.
  • Take ownership of the folder and file.
sudo chown pi -R /home/pi/WeatherDisplay.Api
  • Update permissions to allow execution of the executable file WeatherDisplay.Api.
sudo chmod +x /home/pi/WeatherDisplay.Api/WeatherDisplay.Api
  • Test the ASP.NET Core web service by starting it manually. (Alternatively, you can also run the executable by calling: ./WeatherDisplay.Api)
dotnet WeatherDisplay.Api.dll

Create background service for WeatherDisplay.Api

If everything works fine so far, we can setup the WeatherDisplay.Api as a service. This ensures that the display is regularly updated with latest information even if the ssh console is closed. Services are also automatically started if the system is rebooted.

  • Navigate to /etc/systemd/system and create a new service definition:
sudo nano /etc/systemd/system/weatherdisplay.api.service
  • Create a service definition which automatically starts the web API service when the operating system is started.
[Unit]
Description=WeatherDisplay.Api
After=network-online.target firewalld.service
Wants=network-online.target

[Service]
Type=simple
WorkingDirectory=/home/pi/WeatherDisplay.Api
ExecStart=sudo /home/pi/.dotnet/dotnet /home/pi/WeatherDisplay.Api/WeatherDisplay.Api.dll
ExecStop=/bin/kill $MAINPID
KillSignal=SIGTERM
KillMode=process
SyslogIdentifier=WeatherDisplay.Api
TimeoutStartSec=60
TimeoutStopSec=20

User=pi
Group=pi

Restart=no

Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
Environment=DOTNET_ROOT=/home/pi/.dotnet

[Install]
WantedBy=multi-user.target

Explanations for some of the configuration values:

Attribute Description
WorkingDirectory Will set the current working directory.
ExecStart Systemd will run this executable to start the service.
ExecStop Defines the way the service is stopped when systemctl stop is called on this service. Together with KillSignal, this value is responsible for a graceful shutdown.
KillSignal Is a very important value to determine how the ASP.NET Core web service is stopped. If the wrong value is used, the service is killed without gracefully shutting down it's services (e.g. BackgroundService, IHostedService, IDispose, etc).
KillMode Setting KillMode to process instead of control-group (default) allows to shutdown the main process and spawn new processes (e.g. for automatic update service).
SyslogIdentifier Primary identifier of this service. This name is used to run systemctl start/stop operations as well as to read the service log (journalctl).
Restart Ensure the service restarts after crashing. Takes one of no, on-success, on-failure, on-abnormal, on-watchdog, on-abort, or always.
RestartSec Amount of time to wait before restarting the service.
  • Enable the service definition:
sudo systemctl enable weatherdisplay.api
  • Start the service:
sudo systemctl daemon-reload
sudo systemctl start weatherdisplay.api

Run PiWeatherStation

  • Connect to the access point with the SSID "Pi_..." and the wifi password given during setup.
  • Access the web API with the browser: https://192.168.10.1:5001/swagger/index.html.
  • Use the API method /api/identity/login to get an authentication token. Press the Swagger authorize button to use the authentication token.
  • Call any other API method after successful login.

Troubleshooting & Maintenance

Update and restart the service

If anything in the service definition (weatherdisplay.api.service file) is changed, the service needs to be stopped and restarted. The same procedure is necessary if we want to re-deploy the WeatherDisplay.Api binaries.

  • Stop the service to release any file locks or http listeners.
sudo systemctl stop weatherdisplay.api
  • Rebuild the web API project and copy the output to the raspberry.
  • Restart the weatherdisplay.api.service.
sudo systemctl daemon-reload
sudo systemctl start weatherdisplay.api

Service Operations

sudo systemctl start weatherdisplay.api
sudo systemctl stop weatherdisplay.api
sudo systemctl restart weatherdisplay.api

Check Service Log

journalctl -u weatherdisplay.api.service -f -n 400 -o short-iso-precise

Check Listening Network Ports

sudo netstat -tulpn | grep LISTEN

Call URL using cURL

curl -I -k https://localhost:5000/swagger/index.html

HTTP/2 200
content-type: text/html
date: Wed, 23 Feb 2022 16:35:52 GMT
server: Kestrel
accept-ranges: bytes
etag: "1d7c28cf574c2b4"
last-modified: Sat, 16 Oct 2021 12:54:30 GMT
content-length: 1460

Images

  • Weather Display Rendering Image Rendering Image

  • Weather Display Photo Display Photo

Links

Similar projects / Waveshare / IoT

Raspberry Pi Resources

Microsoft .NET

Linux and ASP.NET Core related sources

OpenWeatherMap API

BME680

Linux Shell Scripts

Other sources

About

Weather Station for RasperryPi and Waveshare ePaper Displays


Languages

Language:C# 97.8%Language:Shell 2.1%Language:Batchfile 0.0%Language:CSS 0.0%