Nowadays we hear a lot about microcomputers and IoT, they are everywhere. You see smart home projects, smart TV, smart fridge, smart calendar? This is what I will discuss in this article. How to build a smart calendar with Raspberry Pi and .NET Core. The product will be a web app, which starts in full screen and shows a monthly calendar, Google Calendar events, holidays and birthdays (you can’t miss those), weather and images from a Google Drive folder. We will start with the hardware components and the source code necessary for this implementation which you can find in GitHub.
What I’ve used for this project
- Raspberry Pi 3 (model B+)
- 2 Heatsinks
- CPU fan
- Case
- 16 GB (8GB is fine) micro SD memory card
- Monitor with HDMI input and HDMI cable
- SSH & SFTP client (e.g. PuTTY & Bitvise SSH)
- Web app and console apps to run on the Raspberry Pi
- Google developer account, Drive and Google Photos
Follow github.com/ermirbeqiraj/digital-calendar to download the source code. Here I’ve composed 2 console apps that will download photos from Google Drive and Google Calendar respectively on a schedule, and a web app that will run fullscreen once the Raspberry Pi boots up.
Prepare the OS
Open raspberrypi.org/downloads and click Noobs, scroll to the downloads section, pick “NOOBS Lite — Network install only”. This is the lightest version at this stage.
Access your SD card from your main PC. From the Raspberry Pi docs, it is suggested to use SD Card Formatter to prepare your SD card.
Extract the NOOBS archive and paste the files in the newly formatted SD card.
Assemble physical parts
Remove the small cover under heat sinks and stick it to the CPU and Ethernet card.
- Insert the micro SD card
- Assemble the case (optional)
- Assemble the fan (if applies)
- Connect your keyboard, mouse, HDMI & Ethernet cable
- Connect the power and wait for the wizard window to select your network
The installation process is straightforward — follow all the steps. I chose the full Raspbian OS; the light version will also work. Once finished, your Pi is ready.
Software components
The solution for this topic consists of 3 projects: a web app and two console apps — one to retrieve photos, and the other to get calendar events.
For displaying pictures, I use Google Drive: save photos to a specific folder in Drive and the console app downloads them daily.
For calendar events, another console app reads the latest events and holidays on a cron schedule.
- Visit Google Developers Console and create a project
- Click Enable APIs and services and enable Google Drive API and Google Calendar API
- Head to the credentials section
- Click Create credentials → OAuth client ID
- Download the credentials file and save it in both
GetImagesandGetCalendarEventsprojects, right-click each and choose “Copy to output directory” - I named it
dd-client-id.json(demo drive client). If you choose a different name, update theCLIENT_ID_FILE_NAMEconstant.
Open your selected directory in Google Drive and note the folder ID from the URL. Update GetImages to use your folder ID:
const string DRIVE_FOLDER_ID = "1mF9vGUoGpaHLG_jnP_c2HKyL6o_8HqhZ";
Then open GetCalendarEvents and update the calendars array:
static readonly string[] CALENDARS = new string[] {
"primary",
"en.al#holiday@group.v.calendar.google.com",
"#contacts@group.v.calendar.google.com"
};
Prepare Raspbian to execute .NET Core apps
According to the Raspberry Pi .NET Core instructions, some prerequisite packages are needed first. Packages may vary by Raspbian version. To check your version:
sudo cat /etc/os-release
sudo apt-get install curl libunwind8 gettext apt-transport-https
Create the following directories:
/var/netcore/web/var/netcore/console/calendar/var/netcore/console/images
Publish all 3 projects for ARM architecture:
dotnet publish -c Release -r linux-arm
Move the contents of each publish directory to their respective folders on the Raspberry Pi, then mark each main file as executable:
cd /var/netcore/web
chmod 775 ./WebApp
cd /var/netcore/console/calendar
chmod 775 ./GetCalendarEvents
cd /var/netcore/console/images
chmod 775 ./GetImages
Calendar and Images first run
When opening the calendar and images apps for the first time, make sure you are connected to the Pi with a desktop environment or VNC Viewer. Run each as an executable: ./GetCalendarEvents and ./GetImages. Log in to your Google account and approve permissions when asked. This is a one-time action — each app will create a token.json folder in its base directory. They also need write permissions inside /var/netcore/web/wwwroot/calendar and /var/netcore/web/wwwroot/images.
Web app daemon
First, test the web app in a terminal: run ./WebApp in the web app directory and check the output. Next, create a systemd service:
cd /etc/systemd/system
sudo nano webapp.service
Paste the following:
[Unit]
Description=webapp
After=nginx.service
[Service]
Type=simple
User=pi
WorkingDirectory=/var/netcore/web
ExecStart=/var/netcore/web/WebApp
Restart=always
[Install]
WantedBy=multi-user.target
Enable and start the service:
sudo systemctl enable webapp.service
sudo systemctl start webapp.service
Installing Nginx
Download the signing key and add it to apt:
sudo wget https://nginx.org/keys/nginx_signing.key
sudo apt-key add nginx_signing.key
Edit /etc/apt/sources.list:
sudo nano /etc/apt/sources.list
Add these lines (replace stretch with your version from /etc/os-release):
deb https://nginx.org/packages/mainline/debian/ stretch nginx
deb-src https://nginx.org/packages/mainline/debian/ stretch nginx
Install nginx:
sudo apt-get update
sudo apt-get install nginx
Verify it’s running: sudo systemctl status nginx. You should see Active: active (running).
Edit the default site configuration to proxy to the web app:
sudo nano /etc/nginx/sites-available/default
Replace the contents with:
server {
listen 80 default_server;
server_name _;
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
}
}
Restart nginx: sudo systemctl restart nginx.service
Schedule image and calendar retrieval
Run crontab -e and register 2 jobs:
0 4 * * * /var/netcore/console/calendar/GetCalendarEvents
0 */6 * * * /var/netcore/console/images/GetImages
These will run on schedule without further interaction, since you authenticated manually on first run.
Startup in kiosk mode
To launch Chromium in fullscreen when the Pi boots:
sudo nano ~/.config/lxsession/LXDE-pi/autostart
Add:
@xset s off
@xset -dpms
@xset s noblank
@chromium-browser --noerrdialogs --incognito --kiosk http://<YOUR-RASPBERRY-IP>
What’s missing
- Ability to authenticate with service account type in Google Calendar and Google Drive. Currently using OAuth2InstalledApp which is the closest but still requires a manual first-run step.
- Temperature and humidity sensor support.
You can find the source code for the web app and 2 console apps at github.com/ermirbeqiraj/digital-calendar