Digitaler IKEA-Bilderrahmen mit dem Raspberry Pi – Erstellen der Kalenderanzeige

Dieser Artikel „Erstellen der Kalenderanzeige“ beschreibt wie ich die Kalenderanzeige realisiert habe und wie ich die Daten von einem ownCloud-Server auslese.

Die Anzeige des Bildschirms erfolgt über zwei Skripte. Das erste Skript holt die Daten vom owncloud-Server und erzeugt ein Bild. Das zweite Skript zeigt das Bild an.

Erstellen einer VCAL-Datei aus dem Kalender

#!/usr/bin/python
# -*-coding: utf-8 -*-
'''
Python Skript to get the next appointments from owncloud database 
'''

import time
import mysql.connector
from PIL import Image, ImageDraw, ImageFont
from icalendar import Calendar, Event
from datetime import datetime, timedelta
from pytz import UTC # timezone
from dateutil.rrule import rrulestr, rruleset
from PIL import Image, ImageDraw, ImageFont
import os,sys

#Anzahl der Tage für Termine in der Vergangenheit
NUMBER_OF_DAYS_BEFORE = 10
# Anzahl der Tage für Termine in der Zukunft
NUMBER_OF_DAYS_AFTER  = 30
# die ID des Kalenders in owncloud
CALENDAR_ID = 1

NOW  = int (time.time()+0.5)
FROM = (NOW - ( NUMBER_OF_DAYS_BEFORE * 24 * 60 *60) )
TO   = (NOW + ( NUMBER_OF_DAYS_AFTER * 24 * 60 *60) )

# set screenwidth
if (len(sys.argv) > 1):
        screenwidth=int(sys.argv[1])
else:
        screenwidth=640

if (screenwidth != 640):
        screenheight=624
else:
        screenheight=480

header = """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//SabreDAV//SabreDAV//EN
X-WR-CALNAME:Personal (kiosk)
BEGIN:VTIMEZONE
TZID:Europe/Berlin
BEGIN:DAYLIGHT
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
TZNAME:CEST
DTSTART:19700329T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
TZNAME:CET
DTSTART:19701025T030000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
END:STANDARD
END:VTIMEZONE
"""

#
# get the current serverstatus from the mysql db on rpi0
# and write it to a ics file
#
# Bitte die Parameter für die Datenbankverbindung ersetzen
cnx = mysql.connector.connect(user='myusername', password='mypassword', host='myhostname', database='mydatabasename')

cursor = cnx.cursor()

query_template ="select calendarid, from_unixtime(firstoccurence) as start, from_unixtime(lastoccurence) as ende, calendardata as event from oc_calendarobjects where calendarid = '%s' and lastoccurence >= '%s' and firstoccurence <= '%s' and componenttype = 'VEVENT'"

query = query_template % (CALENDAR_ID, FROM, TO)

cursor.execute(query)

file = open("curr_cal1.ics","w+") 
file.write(header)

for (calendarid, start, ende, event) in cursor:
	spos = event.find("BEGIN:VEVENT")
	epos = event.find("END:VEVENT")
	event = event[ spos : epos ] +"END:VEVENT\n"
	if event != "":
		file.write(event)

file.write("END:VCALENDAR\n")
file.close()
cursor.close()
cnx.close()

Das Skript verbindet sich mit der owncloud-Datenbank, liest die Kalendereinträge aus und schreibt sie im VCAL-Format in die Datei curr_cal1.ics. Dafür wird das Python icalendar-Modul verwendet. Der Code muss bzgl. der Parameter für die Datenbankverbindung angepasst werden (s.o.). Weiterhin können die Einstellungen für den Zeitraum der auszulesenden Termine und die Kalender-ID eingetragen werden. Der zweite Teil des Skripts erzeugt ein Bild mit den ausgelesenen Daten.

Die Kalenderanzeige erzeugen

#
# parse ics file and store relevant calendar entries to dict
#

edict={}
today     = datetime.today()
date_from = (today - timedelta(days=NUMBER_OF_DAYS_BEFORE)).strftime("%Y%m%d%H%M")
date_to   = (today + timedelta(days=NUMBER_OF_DAYS_AFTER )).strftime("%Y%m%d%H%M")

g = open('/home/pi/kiosk/curr_cal1.ics','rb')
gcal = Calendar.from_ical(g.read())
for component in gcal.walk():
    if component.name == "VEVENT":
	if component.get('rrule'):
		rules = rruleset()
		first_rule = rrulestr(component.get('rrule').to_ical(), dtstart=component.get('dtstart').dt)

		# in some entries, tzinfo is missing
		if first_rule._until and first_rule._until.tzinfo is None:
			first_rule._until = first_rule._until.replace(tzinfo=CET)

		rules.rrule(first_rule)
		
		exdates = component.get('exdate')

		if not isinstance(exdates, list):  # apparently this isn't a list when
		    exdates = [exdates]            # there is only one EXDATE

		for exdate in exdates:
		    try:
		        rules.exdate(exdate.dts[0].dt)
		    except AttributeError:  # sometimes there is a None entry here
			pass

		now = datetime.now(tz=UTC)
		dff = now - timedelta(days=NUMBER_OF_DAYS_BEFORE)
		dft = now + timedelta(days=NUMBER_OF_DAYS_AFTER)
		dfr = rules.between(dff,dft)
		if dfr != []:
			for i in dfr:
				event_key = i.strftime("%Y%m%d%H%M")
				entry= i.strftime("%d.%m.%y %H:%M") + "                " + component.get('summary')
				edict[event_key]=entry

	else:
		event_key = component.get('dtstart').dt.strftime("%Y%m%d%H%M")
		if (event_key >= date_from and event_key <= date_to):
			entry = component.get('dtstart').dt.strftime("%d.%m.%y %H:%M") + " " + component.get('dtend').dt.strftime("%d.%m.%y %H:%M") + " " + component.get('summary')
			edict[event_key]=entry
g.close()

#
# draw image with calendar entries on it
#
img = Image.new('RGB', (screenwidth, screenheight), color = (73, 109, 137))
 
fnt = ImageFont.truetype('/usr/share/fonts/truetype/noto/NotoMono-Regular.ttf', 18)

d = ImageDraw.Draw(img)

x=20

d.text((x,10), "Unsere Termine", font=fnt, fill=(255, 255, 0))
d.text((x,20), "_________________________________", font=fnt, fill=(255, 255, 0))

now = today.strftime("%Y%m%d%H%M")
nowout=0

y=44
for key in sorted(edict):
	#print "%s: %s" % (key, edict[key])
	if (key >= now and nowout==0):
		d.text((x,y), edict[key], font=fnt, fill=(  0, 255, 0))
		nowout=1
	else:
		d.text((x,y), edict[key], font=fnt, fill=(255, 255, 0))
	y += 22
 
img.save('/tmp/curr_cal1.png')

Jetzt steht das Bild im Verzeichnis /tmp mit dem Namen curr_cal1.png und muss nur noch angezeigt werden.

#!/bin/bash

# display current calendar image
sudo fbi -d /dev/fb0 -T 1 -a --noverbose /tmp/curr_cal1.png 

Dieses kleine Skript zeigt das Bild mittels fbi an. Das Programm fbi muss mit sudo ausgeführt werden, da der Framebuffer root-Rechte für den Schreibzugriff benötigt.

Grundsätzlich ist es möglich das Skript so anzupassen, dass es auch aus anderen Kalendern die Termine ausliest. Um den Rest des Skripts weiter zu verwenden, ist es am Einfachsten, die Daten ebenfalls im VCAL-Format abzulegen und dann mit den vorhandenen Code weiter zu verarbeiten.

Die Artikelserie besteht aus acht Teilen. Dem Überblick „Digitaler IKEA-Bilderrahmen mit dem Raspberry Pi“ und den sieben Artikeln zum Bau des digitalen Bilderrahmens mit dem Raspberry Pi.

  1. Einbau der Teile in den IKEA-Rahmen
  2. Grundlegende Einstellungen für den Raspberry Pi
  3. Steuerung der Anzeige
  4. Automatische Dia-Show
  5. Erstellen der Kalenderanzeige
  6. Generieren der Wetteranzeige
  7. Ermitteln und Anzeigen des Server-Status

Keine Antworten

    Schreibe einen Kommentar

    Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

    :bye: 
    :good: 
    :negative:  
    :scratch: 
    :wacko:  
    :yahoo: 
    B-) 
    mehr...
     

       Mit der Nutzung dieses Formulars erklärst Du Dich mit der Speicherung und Verarbeitung Deiner Daten durch diese Website einverstanden. Mehr Informationen dazu findest Du in der Datenschutzerklärung.

    ALL-INKL.COM - Webhosting Server Hosting Domain Provider TinyURL.com - Free URL Shortener

    Diese Seite verwendet Cookies. Mit der Nutzung von tuxlog erklärst Du Dich mit der Verwendung von Cookies einverstanden. Detaillierte Informationen über die Verwendung von Cookies auf dieser Website findest Du in der Datenschutzerklärung.