Raspberry Pi Picture Frame Bilderrahmen mit Cloud-Anbindung

Endlich habe ich einen Digitalen Bilderrahmen mit Anbindung an die Nextcloud zusammengestellt. Im Folgenden die Anleitung zum durchlesen.

Rpi vorbereiten

Raspbian full (aktuell Debian 10 / buster Base) ohne empfohlene Apps per image auf die SD-Karte spielen. Karte auswefen, wieder einstecken und folgende dateien anpassen:

ssh.txt erstellen – dadurch ist ssh beim boot automatisch aktiviert

Je nach Bildschirm muss dieser gedreht werden. Folgenden Befehl in die config.txt einfach am Ende eintragen. Bei 2 sind es 180 Grad Drehung. Weiterhin ist es sinnvoll, gleich overscan zu deaktivieren.

display_rotate=0
lcd_rotate=0
disable_overscan=1

WLAN automatischen Connect einrichten. wpa_supplicant.conf auf dem Laufwerk erstellen und mit folgenden Daten füttern:

update_config=1
ctrl_interface=/var/run/wpa_supplicant
network={
  scan_ssid=1
  ssid="<YOURWLANNAMEHERE>"
  psk="<YOURWIFIPASSHERE>"
}

Jetzt speichern und Karte in den rpi stecken. Booten und per ssh verbinden. Standard-Passwort ändern.

Updates aus dem Internet holen und durchführen

sudo apt update && sudo apt upgrade -y

Raspi Grundkonfiguration

sudo reboot
sudo raspi-config
  • advanced – expand filesystem
  • Hostnamen
  • Locale
  • Timezone
sudo reboot

Cloud-anbindung

rclone installieren

sudo apt install rclone -y

rclone konfigurieren

rclone config

Hier eine „new remote“ erstellen – ich wählte den namen „bilderrahmen“ – mit 22 – webdav und den notwendigen Einstellungen. Achtung, bei Nextcloud den richtigen Pfad angeben (bswp. https://xyz.example/nextcloud/remote.php/dav/files/bilderrahmen/ ).

Script „rclone-cron.sh“ für automatische synchronisation erstellen:

nano rclone-cron.sh

Und folgenden Text füttern (Pfade ggf. anpassen):

#!/bin/bash
if pidof -o %PPID -x “rclone-cron.sh”; then
 exit 1
fi

rclone sync bilderrahmen:Pictures-bilderrahmen/ /home/pi/Pictures/
exit

Das ganze ausführbar machen

chmod +x rclone-cron.sh

Cronjob erstellen – edit Cronjob Liste

crontab -e

Folgende Zeile ergänzen (Zeiten selber definieren). In dieser Ausgestaltung alle 15 Minuten Sync mit Cloud.

*/15 * * * * sh /home/pi/rclone-cron.sh

Bilderrahmen

Hier müssen zwei unterschiedliche Vorbereitungen je nach RAM Menge umgesetzt werden.

Raspberry Pi 4

sudo raspi-config nonint do_boot_behaviour B2 && sudo raspi-config nonint do_memory_split 256 && sudo raspi-config

7 Advanced Options > A8 GL Driver > Choose G2 GL Fake KMS

Raspberry Pi 2 und 3

sudo raspi-config nonint do_boot_behaviour B4 && sudo raspi-config nonint do_memory_split 128 && sudo raspi-config 

6 Advanced Options > A2 GL Driver > Choose G1 (Legacy)

Für beide Varianten geht es nun weiter.

Swapfile vergößern

sudo dphys-swapfile swapoff
sudo nano /etc/dphys-swapfile

Swapsize in der Datei setzen, bspw. 1G
CONF_SWAPSIZE=1024
Speichern, exit

sudo dphys-swapfile setup
sudo dphys-swapfile swapon

Danach Picframe installieren und starten.

sudo apt install cmake
sudo python3 -m pip install --upgrade pip
sudo python3 -m pip install -U pip
sudo python3 -m pip install picframe --no-cache-dir --force-reinstall
sudo reboot
picframe -i .

Per Enter alles bestätigen

Applikation testen mit der Ausführung des folgenden Befehls. Dadurch erscheint das erste Bild auf dem Screen.

picframe ~/picframe_data/config/configuration.yaml

Mit Strg+C beenden

Die config kann hier angepasst werden:

nano ./picframe_data/config/configuration.yaml

Meine Start-Konfiguration sieht folgendermaßen aus:

viewer:
  blur_amount: 10                          # default=12,  larger values than 12 will increase processing load quite a bit
  blur_zoom: 1.0                          # default=1.0, must be >= 1.0 which expands the backgorund to just fill the space around the image
  blur_edges: True                        # default=False, use blurred version of image to fill edges - will override FIT = False
  edge_alpha: 0.7                         # default=0.5, background colour at edge. 1.0 would show reflection of image
  fps: 20.0                               # default=20.0
  background: [0.2, 0.2, 0.3, 1.0]        # default=[0.2, 0.2, 0.3, 1.0], RGBA to fill edges when fitting
  blend_type: "blend"                     # default="blend", choices={"blend", "burn", "bump"}, type of blend the shader can do
  font_file: "/home/pi/picframe_data/data/fonts/NotoSans-Regular.ttf"
  shader: "/home/pi/picframe_data/data/shaders/blend_new"
  show_text_fm: "%d %b %Y"               # default "%b %d, %Y", format to show date over the image
  show_text_tm: 20.0                       # default=20.0, time to show text over image with file name
  show_text_sz: 10                        # default=40, text character size
  show_text: "date folder"  # default="title caption name date folder location", show text, include combination of words: title, caption name, date, location, folder
  text_justify: "C"                       # text justification L, C or R
  fit: True                              # default=False, True => scale image so all visible and leave 'gaps'
                                          #                False => crop image so no 'gaps'
  auto_resize: True                       # default=True, set this to False if you want to use 4K resolution on Raspberry Pi 4.
                                          # You should ensure your images are the correct size for the display")
  kenburns: False                         # default=False, will set fit->False and blur_edges->False
  display_x: 0                            # offset from left of screen (can be negative)
  display_y: 0                            # offset from top of screen (can be negative)
  display_w: null                         # width of display surface (null->None will use max returned by hardware)
  display_h: null                         # height of display surface
  use_glx: False                          # default=False. Set to True on linux with xserver running

  mat_images: False                        # default=0.01, True, automatically mat all images. False, don't automatically mat any images. Real value, auto-mat all images with aspect ratio difference > than value
  mat_type: null                          # default=null, A string containing the mat types to choose from when matting images. It can consist of any or
                                          # all of 'float float_polaroid float_color_wrap single_bevel double_bevel double_flat' (null or '' will use all mat types)
  outer_mat_color: null                   # default=null, Color of the outer mat as an RGB list. null will auto-select a reasonable color based on the image.
  inner_mat_color: null                   # default=null, Color of the inner mat as an RGB list. null will auto-select a reasonable color based on the image.
  outer_mat_border: 75                    # default=75, Minimum outer mat border in pixels
  inner_mat_border: 40                    # default=40, Minimum inner mat border in pixels (for styles that use it)
  outer_mat_use_texture: True             # default=True, True uses a texture for the outer mat. False creates a solid-color outer mat.
  inner_mat_use_texture: False            # default=False, True uses a texture for the inner mat. False creates a solid-color inner mat.
  mat_resource_folder: "/home/pi/picframe_data/data/mat" # Folder containing mat image files

  #codepoints: "1234567890AÄÀÆÅÃBCÇDÈÉÊEËFGHIÏÍJKLMNÑOÓÖÔŌØPQRSTUÚÙÜVWXYZaáàãæåäbcçdeéèêëfghiíïjklmnñoóôōøöpqrsßtuúüvwxyz., _-+*()&/`´'•" # limit to 121 ie 11x11 grid_size

model:
  pic_dir: "/home/pi/Pictures"                   # default="/home/pi/Pictures", root folder for images
  deleted_pictures: "/home/pi/DeletedPictures"   # move deleted pictures here
  no_files_img: "/home/pi/picframe_data/data/no_pictures.jpg" # default="PictureFrame2020img.jpg", image to show if none selected
  subdirectory: ""                        # default="", subdir of pic_dir - can be changed by MQTT"
  recent_n: 30                             # default=7 (days), when shuffling file change date more recent than this number of days play before the rest
  reshuffle_num: 1                        # default=1, times through before reshuffling
  time_delay: 30.0                       # default=200.0, time between consecutive slide starts - can be changed by MQTT
  fade_time: 8.0                         # default=10.0, change time during which slides overlap - can be changed by MQTT"
  shuffle: True                           # default=True, shuffle on reloading image files - can be changed by MQTT"
  sort_cols: 'fname ASC'                  # default='fname ASC' can be any columns in the table with optional ASC or DESC separated by commas
                                          # fname, last_modified, file_id, orientation, exif_datetime, f_number,
                                          # exposure_time, iso, focal_length, make, model, lens, rating,
                                          # latitude, longitude, width, height, title, caption, tags,
                                          # is_portrait, location
  image_attr: [                           # image attributes send by MQTT, Keys are taken from exifread library, "PICFRAME GPS" is special to retrieve GPS lon/lat, "PICFRAME LOCATION" is special to retrieve geo reverse (load_geoloc hast to be True)
    "PICFRAME GPS",
    "PICFRAME LOCATION",
    "EXIF FNumber",
    "EXIF ExposureTime",
    "EXIF ISOSpeedRatings",
    "EXIF FocalLength",
    "EXIF DateTimeOriginal",
    "Image Model",
    "IPTC Caption/Abstract",
    "IPTC Object Name",
    "IPTC Keywords"]
  load_geoloc: False                      # get location information from open street map NB if you switch this on (recommended)
  geo_key: "this_needs_to@be_changed"     # then you **MUST** change the geo_key to something unique to you
                                          # i.e. use your email address
  locale: "de_DE.utf8"                    # "locale -a" shows the installed locales which could used
  key_list: [
    ["tourism","amenity","isolated_dwelling"],
    ["suburb","village"],
    ["city","county"],
    ["region","state","province"],
    ["country"]]
  db_file: "/home/pi/picframe_data/data/pictureframe.db3" # database used by PictureFrame
  portrait_pairs: False
  log_level: "WARNING"                    # default=WARNING, could beDEBUG, INFO, WARNING, ERROR, CRITICAL

mqtt:
  use_mqtt: False                         # default=False. Set True true, to enable mqtt
  server: "your_mqtt_broker"              # No defaults for server
  port: 8883                              # default=8883 for tls, 1883 else (tls must be "" then !!!!!)
  login: "name"                           # your mqtt user
  password: "your_password"               # password for mqtt user
  tls: "/path/to/your/ca.crt"             # filename including path to your ca.crt. If not used, must be set to "" !!!!
  device_id: "picframe"                   # default="picframe" unique id of device. change if there is more than one PictureFrame

http:
  use_http: False                          # default=False. Set True to enable http NB THIS SERVER IS FOR LOCAL NETWORK AND SHOULD NOT BE EXPOSED TO EXTERNAL ACCESS
  path: "/home/pi/picframe_data/html"            # path to where html files are located
  port: 9000                              # port used to serve pages by http server < 1024 requires root which is *bad* idea
  use_ssl: False
  keyfile: "path/to/key.pem"              # private-key
  certfile: "path/to/cert.pem"            # server certificate
peripherals:
  input_type: null

Autostart und fixes

Unclutter installieren, dadurch lässt sich er Mauszeiger deaktivieren:

sudo apt install unclutter -y

Autostart – Variante ab 02-2023

Bei einem Raspberry Pi Zero W wird der Service-Start der offiziellen Anleitung von picframe verwendet, zu finden hier:

https://github.com/helgeerbe/picframe/wiki/Running%20As%20Service

mkdir ~/.config/systemd/user/ -p
nano ~/.config/systemd/user/picframe.service

Und folgenden Inhalt hinzufügen:

[Unit]
Description=PictureFrame on Pi3

[Service]
ExecStart=/home/pi/.local/bin/picframe ~/picframe_data/config/configuration.yaml
Restart=always

[Install]
WantedBy=default.target

Danach Service aktivieren und starten. Dann sollten die ersten Bilder auf dem Schirm auftauchen.

systemctl --user enable picframe.service
systemctl --user start picframe.service

Autostart – Ursprügliche Variante

Die Autostart Datei des Benutzers „pi“ anpassen:

sudo nano /etc/xdg/lxsession/LXDE-pi/autostart

Folgenden Inhalt einfügen:

#Disable screensaver:
@xset s noblank 
@xset s off 
@xset -dpms
#Disable old settings:
#@lxpanel --profile LXDE-pi #
#@pcmanfm --desktop --profile LXDE-pi
#@xscreensaver -no-splash
#@point-rpi

#Mauszeiger Ausblenden
@unclutter

#Autostart picframe
picframe ~/picframe_data/config/configuration.yaml

Hier geht es für beide Varianten weiter …

Das ganze speichern und die Datei schließen. Reboot und testen.

sudo reboot

Bildschirmschoner ausschalten via:

sudo raspi-config

Display options -> Screen Blanking -> Enable -> No —-> Reboot required

sudo nano /boot/cmdline.txt

Ändern des Eintrags von console=tty1 hin zu console=serial0 Dann speichern und wieder raus in die Console.

echo hide boot messages
sudo sed -i "1 s|$| quiet splash|" /boot/cmdline.txt

echo disable login prompt
sudo systemctl disable getty@tty1.service

echo hide undervoltage message
sudo sed -i "1 s|$| loglevel=1|" /boot/cmdline.txt

sudo sed -i "1 s|$| vt.global_cursor_default=0|" /boot/cmdline.txt

echo hide undervoltage lightning bolt icon
sudo sed -i -e '$aavoid_warnings=1' /boot/config.txt

echo disable splash screen
sudo sed -i -e '$adisable_splash=1' /boot/config.txt

Und jetzt noch den Welcome Wizard entfernen

sudo rm /etc/xdg/autostart/piwiz.desktop
sudo reboot

Quellen