Compare commits
No commits in common. "80c72914087bb2396b338a09ea147afbe49f6654" and "7acfebb33110d705b2c630c2cd4440a23b83e61e" have entirely different histories.
80c7291408
...
7acfebb331
3 changed files with 124 additions and 243 deletions
|
@ -1,4 +1 @@
|
||||||
# e-inkCal
|
# e-inkCal
|
||||||
|
|
||||||
this small script is supposed to be run on a raspberry pi with an SPI e-ink display attached to it.
|
|
||||||
it will then display a weekcalendar on the e-ink display, which is fetched from a calDAV resource.
|
|
||||||
|
|
9
TODO.md
9
TODO.md
|
@ -1,9 +0,0 @@
|
||||||
ToDo:
|
|
||||||
|
|
||||||
1. catching exceptions for caldav unauthorized
|
|
||||||
2. options:
|
|
||||||
-w show week calendar
|
|
||||||
-m show month calendar
|
|
||||||
|
|
||||||
3. include birthdays from another calendar
|
|
||||||
4. make other views, e.g. month, day, year...
|
|
|
@ -1,190 +1,136 @@
|
||||||
from datetime import datetime, date, time, timezone, timedelta
|
from datetime import datetime
|
||||||
|
from datetime import date
|
||||||
|
from datetime import timedelta
|
||||||
from PIL import Image,ImageDraw,ImageFont
|
from PIL import Image,ImageDraw,ImageFont
|
||||||
import pickle as p
|
import pickle as p
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
import requests
|
import requests
|
||||||
import sys, os
|
import sys
|
||||||
|
import getopt
|
||||||
sys.path.insert(0, './caldav')
|
sys.path.insert(0, './caldav')
|
||||||
sys.path.insert(0, './e-Paper/RaspberryPi_JetsonNano/python/lib')
|
|
||||||
import caldav
|
import caldav
|
||||||
from caldav.lib.error import AuthorizationError
|
from caldav.lib.error import AuthorizationError
|
||||||
|
|
||||||
|
#look for commandline args
|
||||||
|
|
||||||
caldav_url = ''
|
import getopt
|
||||||
username = ''
|
|
||||||
password = ''
|
|
||||||
datafile = ''
|
|
||||||
selected_cals = []
|
|
||||||
birthdaycal = ''
|
|
||||||
language="EN"
|
|
||||||
weekday_l_key = "FULL"
|
|
||||||
draw_date = False
|
|
||||||
has_color = False
|
|
||||||
#open config file, load configs
|
|
||||||
|
|
||||||
if (os.path.isfile("./config")):
|
|
||||||
configfile = open("./config", "r")
|
|
||||||
conf = configfile.readlines()
|
|
||||||
print(conf)
|
|
||||||
for l in conf:
|
|
||||||
l = l.strip()
|
|
||||||
if(l.startswith("server")):
|
|
||||||
caldav_url = l[7:]
|
|
||||||
elif(l.startswith("user")):
|
|
||||||
username = l[5:]
|
|
||||||
elif(l.startswith("password")):
|
|
||||||
password = l[9:]
|
|
||||||
elif(l.startswith("birthdays")):
|
|
||||||
birthdaycal = l[10:]
|
|
||||||
elif(l.startswith("datafile")):
|
|
||||||
datafile = l[9:]
|
|
||||||
elif(l.startswith("calendars")):
|
|
||||||
selected_cals = l[10:].split(";")
|
|
||||||
#here the configs for drawing the calendar start
|
|
||||||
elif(l.startswith("language")):
|
|
||||||
language = l[9:]
|
|
||||||
elif(l.startswith("weekday_format")):
|
|
||||||
weekday_l_key = l[15:]
|
|
||||||
elif(l.startswith("draw_date")):
|
|
||||||
k = l[10:]
|
|
||||||
trueish = ["true","TRUE","1","True","T"]
|
|
||||||
draw_date = (k in trueish)
|
|
||||||
elif(l.startswith("colormode")):
|
|
||||||
if l[10:] == "2color":
|
|
||||||
has_color = True
|
|
||||||
|
|
||||||
on_e_paper = False
|
inputfile = ''
|
||||||
if(on_e_paper):
|
outputfile = ''
|
||||||
from waveshare_epd import epd7in5b_V2
|
try:
|
||||||
|
opts, args = getopt.getopt(sys.argv[1:],"h:i:o",["ifile=","ofile="])
|
||||||
|
except getopt.GetoptError:
|
||||||
|
print('test.py -i <inputfile> -o <outputfile>')
|
||||||
|
sys.exit(2)
|
||||||
|
for opt, arg in opts:
|
||||||
|
if opt == '-h':
|
||||||
|
print ('test.py -i <inputfile> -o <outputfile>')
|
||||||
|
sys.exit()
|
||||||
|
elif opt in ("-i", "--ifile"):
|
||||||
|
inputfile = arg
|
||||||
|
elif opt in ("-o", "--ofile"):
|
||||||
|
outputfile = arg
|
||||||
|
print ('Input file is "', inputfile)
|
||||||
|
print ('Output file is "', outputfile)
|
||||||
|
|
||||||
|
|
||||||
#print(selected_cals)
|
|
||||||
#look if server and user are set
|
|
||||||
if(len(caldav_url) == 0):
|
|
||||||
print("Please provide a calDAV link")
|
|
||||||
if(len(username) == 0):
|
|
||||||
print("Please provide a username")
|
|
||||||
|
|
||||||
#calDAV setup
|
#calDAV setup
|
||||||
|
caldav_url = 'https://www.kuhl-mann.de/nextcloud/remote.php/dav'
|
||||||
|
username = 'Justus'
|
||||||
|
password = 'Alphabeth1forB2;'
|
||||||
|
timezone = [2,0]
|
||||||
|
|
||||||
timeout = 5
|
timeout = 5
|
||||||
|
|
||||||
if not (len(datafile) == 0):
|
f = open("./calendarlib.p")
|
||||||
f = open(datafile)
|
|
||||||
|
|
||||||
server_reached = True
|
server_reached = True
|
||||||
client_established = True
|
client_established = True
|
||||||
|
|
||||||
print("Looking for server...")
|
print("Looking for server...")
|
||||||
try:
|
try:
|
||||||
request = requests.get(caldav_url, timeout=timeout)
|
request = requests.get(caldav_url, timeout=timeout)
|
||||||
except (requests.ConnectionError, requests.Timeout) as exception:
|
except (requests.ConnectionError, requests.Timeout) as exception:
|
||||||
print("didn't find server, showing data from last successful connection")
|
print("didn't find server, showing data from last successful connection")
|
||||||
server_reached = False
|
server_reached = False
|
||||||
else:
|
else:
|
||||||
print("found server")
|
print("found server")
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
client = caldav.DAVClient(url=caldav_url, username=username, password=password)
|
client = caldav.DAVClient(url=caldav_url, username=username, password=password)
|
||||||
except (Exception) as ex:
|
except (Exception) as ex:
|
||||||
client_established = False
|
client_established = False
|
||||||
|
|
||||||
#check in which time zone we are
|
|
||||||
tz = timedelta(minutes = round((datetime.now()-datetime.utcnow()).seconds/60))
|
|
||||||
|
|
||||||
if(server_reached and client_established):
|
if(server_reached and client_established):
|
||||||
#if server is available, download new information from server
|
|
||||||
print("Successfully connected to server, starting to download calendars...")
|
print("Successfully connected to server, starting to download calendars...")
|
||||||
my_principal = client.principal()
|
my_principal = client.principal()
|
||||||
calendars_fetched = my_principal.calendars()
|
calendars = my_principal.calendars()
|
||||||
calendars = []
|
|
||||||
if not (len(selected_cals) == 0 or len(selected_cals[0]) == 0):
|
|
||||||
for c in calendars_fetched:
|
|
||||||
if c.name in selected_cals:
|
|
||||||
calendars.append(c)
|
|
||||||
else:
|
|
||||||
calendars = calendars_fetched
|
|
||||||
print("selected calendars:")
|
|
||||||
for c in calendars:
|
|
||||||
print(c.name)
|
|
||||||
|
|
||||||
time_events = []
|
time_events = []
|
||||||
day_events = []
|
day_events = []
|
||||||
birthdays = []
|
birthdays = []
|
||||||
#go through all calendars to look for events
|
|
||||||
for c in calendars:
|
for c in calendars:
|
||||||
current_calendar = my_principal.calendar(name=c.name)
|
current_calendar = my_principal.calendar(name=c.name)
|
||||||
events_fetched = current_calendar.date_search(
|
events_fetched = current_calendar.date_search(
|
||||||
start=datetime.today()-timedelta(days = datetime.today().weekday()), end=datetime.today()+timedelta(days = 6-datetime.today().weekday()), expand=True)
|
start=datetime.today()-timedelta(days = datetime.today().weekday()), end=datetime.today()+timedelta(days = 6-datetime.today().weekday()), expand=True)
|
||||||
|
|
||||||
if len(events_fetched)> 0:
|
if len(events_fetched)> 0:
|
||||||
for event in events_fetched:
|
for event in events_fetched:
|
||||||
event_start_str = str(event.vobject_instance.vevent.dtstart)[10:-1]
|
event_start_str = str(event.vobject_instance.vevent.dtstart)[10:-1]
|
||||||
event_end_str = str(event.vobject_instance.vevent.dtend)[8:-1]
|
event_end_str = str(event.vobject_instance.vevent.dtend)[8:-1]
|
||||||
#print(event.vobject_instance.vevent)
|
|
||||||
|
|
||||||
if(event_start_str.startswith("VALUE")):
|
if(event_start_str.startswith("VALUE")):
|
||||||
#if it is an event over a whole day, sort it into the day events
|
day_events.append({
|
||||||
if(not birthdaycal == ''):
|
"DATE":date(int(event_start_str.split("}")[1].split("-")[0]),int(event_start_str.split("}")[1].split("-")[1]),int(event_start_str.split("}")[1].split("-")[2])),
|
||||||
if(c.name == birthdaycal):
|
|
||||||
summary = str(event.vobject_instance.vevent.summary.value)
|
|
||||||
pieces = summary.split(" ")
|
|
||||||
age = date.today().year - int(pieces[2][2:-1])
|
|
||||||
birthdays.append({
|
|
||||||
"START":date(int(event_start_str.split("}")[1].split("-")[0]),int(event_start_str.split("}")[1].split("-")[1]),int(event_start_str.split("}")[1].split("-")[2])),
|
|
||||||
"END":date(int(event_end_str.split("}")[1].split("-")[0]),int(event_end_str.split("}")[1].split("-")[1]),int(event_end_str.split("}")[1].split("-")[2])),
|
|
||||||
"SUMMARY":pieces[1]+" "+pieces[0][:-1]+" ("+str(age)+")",
|
|
||||||
"CALENDAR":c.name
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
day_events.append({
|
|
||||||
"START":date(int(event_start_str.split("}")[1].split("-")[0]),int(event_start_str.split("}")[1].split("-")[1]),int(event_start_str.split("}")[1].split("-")[2])),
|
|
||||||
"END":date(int(event_end_str.split("}")[1].split("-")[0]),int(event_end_str.split("}")[1].split("-")[1]),int(event_end_str.split("}")[1].split("-")[2])),
|
|
||||||
"SUMMARY":str(event.vobject_instance.vevent.summary.value),
|
|
||||||
"CALENDAR":c.name
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
#otherwise it has to be a time event
|
|
||||||
sd = event_start_str.split(" ")[0]
|
|
||||||
st = event_start_str.split(" ")[1]
|
|
||||||
sh = int(st.split(":")[0])+int(st.split(":")[2][2:4])
|
|
||||||
sm = int(st.split(":")[1])+int(st.split(":")[3])
|
|
||||||
ss = int(st.split(":")[2][0:1])
|
|
||||||
ed = event_end_str.split(" ")[0]
|
|
||||||
et = event_end_str.split(" ")[1]
|
|
||||||
eh = int(et.split(":")[0])+int(st.split(":")[2][2:4])
|
|
||||||
em = int(et.split(":")[1])+int(et.split(":")[3])
|
|
||||||
es = int(et.split(":")[2][0:1])
|
|
||||||
time_events.append({
|
|
||||||
"START":datetime(int(sd.split("-")[0]),int(sd.split("-")[1]),int(sd.split("-")[2]), hour = sh, minute = sm, second = ss)+tz,
|
|
||||||
"END":datetime(int(ed.split("-")[0]),int(ed.split("-")[1]),int(ed.split("-")[2]), hour = eh, minute = em, second = es)+tz,
|
|
||||||
"SUMMARY":str(event.vobject_instance.vevent.summary.value),
|
"SUMMARY":str(event.vobject_instance.vevent.summary.value),
|
||||||
"CALENDAR":c.name
|
"CALENDAR":c.name
|
||||||
})
|
})
|
||||||
#if the user wants one calendar to be treated as a birthday calendar, these are sorted into an extra library
|
else:
|
||||||
|
sd = event_start_str.split(" ")[0]
|
||||||
|
st = event_start_str.split(" ")[1]
|
||||||
|
sh = int(st.split(":")[0])+timezone[0]+int(st.split(":")[2][2:4])
|
||||||
|
sm = int(st.split(":")[1])+timezone[1]+int(st.split(":")[3])
|
||||||
|
ss = int(st.split(":")[2][0:1])
|
||||||
|
ed = event_end_str.split(" ")[0]
|
||||||
|
et = event_end_str.split(" ")[1]
|
||||||
|
eh = int(et.split(":")[0])+timezone[0]+int(st.split(":")[2][2:4])
|
||||||
|
em = int(et.split(":")[1])+timezone[1]+int(et.split(":")[3])
|
||||||
|
es = int(et.split(":")[2][0:1])
|
||||||
|
time_events.append({
|
||||||
|
"START":datetime(int(sd.split("-")[0]),int(sd.split("-")[1]),int(sd.split("-")[2]), hour = sh, minute = sm, second = ss),
|
||||||
|
"END":datetime(int(ed.split("-")[0]),int(ed.split("-")[1]),int(ed.split("-")[2]), hour = eh, minute = em, second = es),
|
||||||
|
"SUMMARY":str(event.vobject_instance.vevent.summary.value),
|
||||||
|
"CALENDAR":c.name
|
||||||
|
})
|
||||||
|
for event in day_events:
|
||||||
|
if event["CALENDAR"] == "Geburtstage von Kontakten":
|
||||||
|
pieces = event["SUMMARY"].split(" ")
|
||||||
|
age = date.today().year - int(pieces[2][2:-1])
|
||||||
|
event["SUMMARY"] = pieces[1]+" "+pieces[0][:-1]+" ("+str(age)+")"
|
||||||
|
birthdays.append(event)
|
||||||
|
day_events.remove(event)
|
||||||
print("Download complete")
|
print("Download complete")
|
||||||
|
calendarlib = {"DAY_EVENTS":day_events,"TIME_EVENTS":time_events,"BIRTHDAYS":birthdays}
|
||||||
#back up the data received to a local copy so that it can be displayed if needed
|
#f = open("./calendarlib.p")
|
||||||
if(len(datafile)!= 0):
|
p.dump( calendarlib, open( "calendarlib.p", "wb" ))
|
||||||
calendarlib = {"DAY_EVENTS":day_events,"TIME_EVENTS":time_events,"BIRTHDAYS":birthdays}
|
f.close()
|
||||||
p.dump( calendarlib, open( "calendarlib.p", "wb" ))
|
|
||||||
f.close()
|
|
||||||
else:
|
else:
|
||||||
#if the server is not available, instead load information from datafile
|
print("Loading caldata from last time...")
|
||||||
if(len(datafile)!= 0):
|
calendarlib = p.load(open("calendarlib.p","rb"))
|
||||||
print("Loading caldata from last time...")
|
time_events = calendarlib["TIME_EVENTS"]
|
||||||
calendarlib = p.load(open(datafile,"rb"))
|
day_events = calendarlib["DAY_EVENTS"]
|
||||||
time_events = calendarlib["TIME_EVENTS"]
|
birthdays = calendarlib["BIRTHDAYS"]
|
||||||
day_events = calendarlib["DAY_EVENTS"]
|
|
||||||
birthdays = calendarlib["BIRTHDAYS"]
|
|
||||||
else:
|
#get principal file
|
||||||
print("No data available!")
|
|
||||||
exit()
|
|
||||||
|
|
||||||
print(birthdays)
|
print(birthdays)
|
||||||
print(day_events)
|
print(day_events)
|
||||||
print(time_events)
|
print(time_events)
|
||||||
|
|
||||||
|
|
||||||
#with this information now the week calendar can be painted on a b/w 800x480 bitmap.
|
#with this information now the week calendar can be painted on a b/w 800x480 bitmap.
|
||||||
|
|
||||||
#define function to insert text at a 90 degree angle
|
#define function to insert text at a 90 degree angle
|
||||||
|
@ -209,29 +155,19 @@ def draw_text_90_into (text: str, into, at):
|
||||||
# Note that we don't need a mask
|
# Note that we don't need a mask
|
||||||
into.paste (img, at)
|
into.paste (img, at)
|
||||||
|
|
||||||
#only for testing purposes
|
|
||||||
has_color = True
|
|
||||||
|
|
||||||
#define fonts to be used
|
#define fonts to be used
|
||||||
eventfont = ImageFont.truetype("./resource/bf_mnemonika_regular.ttf", 16)
|
eventfont = ImageFont.truetype("./resource/bf_mnemonika_regular.ttf", 16)
|
||||||
weekdayfont = ImageFont.truetype("./resource/bf_mnemonika_regular.ttf", 16)
|
weekdayfont = ImageFont.truetype("./resource/bf_mnemonika_regular.ttf", 16)
|
||||||
timefont = ImageFont.truetype("./resource/bf_mnemonika_regular.ttf", 12)
|
timefont = ImageFont.truetype("./resource/bf_mnemonika_regular.ttf", 12)
|
||||||
birthdayfont = weekdayfont
|
|
||||||
|
|
||||||
if(on_e_paper):
|
|
||||||
#initialise epd for the e-ink display
|
|
||||||
epd = epd7in5b_V2.EPD()
|
|
||||||
epd.init()
|
|
||||||
epd.Clear()
|
|
||||||
#create image buffer
|
#create image buffer
|
||||||
Himage = Image.new('1', (800,480), 255) # 255: clear the frame
|
Himage = Image.new('1', (800,480), 255) # 255: clear the frame
|
||||||
draw = ImageDraw.Draw(Himage)
|
draw = ImageDraw.Draw(Himage)
|
||||||
if(has_color):
|
|
||||||
HRimage = Image.new('1', (800,480), 255) # 255: clear the frame
|
|
||||||
draw_r = ImageDraw.Draw(HRimage)
|
|
||||||
|
|
||||||
#define language, and if abbreviations for weekdays should be used
|
#define language, and if abbreviations for weekdays should be used
|
||||||
|
language = "EN"
|
||||||
|
weekday_l_key = "FULL"
|
||||||
|
draw_date = True
|
||||||
#define grid coordinates
|
#define grid coordinates
|
||||||
upper_border_grid = 0
|
upper_border_grid = 0
|
||||||
lower_border_grid = 465
|
lower_border_grid = 465
|
||||||
|
@ -246,11 +182,6 @@ width_grid = right_border_grid-left_border_grid
|
||||||
width_day = round(width_grid/7)
|
width_day = round(width_grid/7)
|
||||||
height_grid = lower_border_grid-upper_border_grid
|
height_grid = lower_border_grid-upper_border_grid
|
||||||
weekday_height = weekdayfont.getsize("Monday")[1]
|
weekday_height = weekdayfont.getsize("Monday")[1]
|
||||||
if(birthdaycal == ''):
|
|
||||||
upper_border_writable = upper_border_grid+weekday_height
|
|
||||||
else:
|
|
||||||
birthday_height = birthdayfont.getsize("ABCDEFGHIJKLMNOPQRSTUVWXYZÄÜÖabcdefghijklmnpqrstuvwxyzäüö")[1]
|
|
||||||
upper_border_writable = upper_border_grid+weekday_height+birthday_height+3
|
|
||||||
two_hour_space = round(2*(lower_border_grid-(upper_border_grid+weekday_height+2))/hours_in_day)
|
two_hour_space = round(2*(lower_border_grid-(upper_border_grid+weekday_height+2))/hours_in_day)
|
||||||
last_hour_line = round((hours_in_day-(hours_in_day%2))*two_hour_space/2+upper_border_grid+weekday_height+2)
|
last_hour_line = round((hours_in_day-(hours_in_day%2))*two_hour_space/2+upper_border_grid+weekday_height+2)
|
||||||
#write down weekdays, makes next step easier
|
#write down weekdays, makes next step easier
|
||||||
|
@ -271,79 +202,56 @@ weekdays = {
|
||||||
|
|
||||||
#draw the weekdays
|
#draw the weekdays
|
||||||
monday = datetime.today()-timedelta(days = datetime.today().weekday())
|
monday = datetime.today()-timedelta(days = datetime.today().weekday())
|
||||||
free_days = [5,6]
|
|
||||||
|
|
||||||
for j in range(len(weekdays[language][weekday_l_key])):
|
for j in range(len(weekdays[language][weekday_l_key])):
|
||||||
if draw_date:
|
if draw_date:
|
||||||
if(max([(weekdayfont.getsize(i+", "+str((monday+timedelta(days=j)).day)+"."+str((monday+timedelta(days=j)).month)+".")[0]>width_day-7) for i in weekdays[language]["FULL"]])):
|
if(max([(weekdayfont.getsize(i+", "+str((monday+timedelta(days=j)).day)+"."+str((monday+timedelta(days=j)).month)+".")[0]>width_day-7) for i in weekdays[language]["FULL"]])):
|
||||||
weekday_l_key = "SHORT"
|
weekday_l_key = "SHORT"
|
||||||
w_str = (weekdays[language][weekday_l_key][j]+", "+str((monday+timedelta(days=j)).day)+"."+str((monday+timedelta(days=j)).month)+".")
|
draw.text((left_border_grid+j*width_day+5, upper_border_grid), (weekdays[language][weekday_l_key][j]+", "+str((monday+timedelta(days=j)).day)+"."+str((monday+timedelta(days=j)).month)+"."), font = weekdayfont, fill = 0)
|
||||||
else:
|
else:
|
||||||
if(max([(weekdayfont.getsize(i)[0]>width_day-7) for i in weekdays[language]["FULL"]])):
|
if(max([(weekdayfont.getsize(i)[0]>width_day-7) for i in weekdays[language]["FULL"]])):
|
||||||
weekday_l_key = "SHORT"
|
weekday_l_key = "SHORT"
|
||||||
w_str = (weekdays[language][weekday_l_key][j])
|
draw.text((left_border_grid+j*width_day+5, upper_border_grid), weekdays[language][weekday_l_key][j], font = weekdayfont, fill = 0)
|
||||||
if has_color and j in free_days:
|
|
||||||
draw_r.text((left_border_grid+j*width_day+5, upper_border_grid),w_str, font = weekdayfont, fill = 0)
|
|
||||||
else:
|
|
||||||
draw.text((left_border_grid+j*width_day+5, upper_border_grid),w_str, font = weekdayfont, fill = 0)
|
|
||||||
|
|
||||||
# draw birthdays
|
|
||||||
for event in birthdays:
|
|
||||||
cropped_ev_str = (event["SUMMARY"])
|
|
||||||
if (birthdayfont.getsize(cropped_ev_str)[0] > width_day-4):
|
|
||||||
p_list = cropped_ev_str.split(" ")
|
|
||||||
p_list[-2] = p_list[-2][0]+"."
|
|
||||||
cropped_ev_str = ""
|
|
||||||
for l in p_list:
|
|
||||||
cropped_ev_str += l+" "
|
|
||||||
print(cropped_ev_str)
|
|
||||||
while (birthdayfont.getsize(cropped_ev_str)[0] > width_day-4):
|
|
||||||
cropped_ev_str = cropped_ev_str.split("(")[0][:-1]+"("+cropped_ev_str.split("(")[1]
|
|
||||||
d = event["START"].weekday()
|
|
||||||
if has_color:
|
|
||||||
draw_r.text((left_border_grid+d*width_day+5, upper_border_grid+weekday_height+2),cropped_ev_str, font = weekdayfont, fill = 0)
|
|
||||||
else:
|
|
||||||
draw.text((left_border_grid+d*width_day+5, upper_border_grid+weekday_height+2),cropped_ev_str, font = weekdayfont, fill = 0)
|
|
||||||
|
|
||||||
#draw a grid
|
#draw a grid
|
||||||
draw.line([(left_border_grid, upper_border_writable+2),(right_border_grid, upper_border_writable+2)], fill=0, width=2)
|
draw.line([(left_border_grid, upper_border_grid+weekday_height+2),(right_border_grid, upper_border_grid+weekday_height+2)], fill=0, width=2)
|
||||||
for y in range(width_day,width_grid,width_day):
|
for y in range(width_day,width_grid,width_day):
|
||||||
draw.line([(y+left_border_grid, upper_border_grid),(y+left_border_grid, lower_border_grid)], fill=0, width=2)
|
draw.line([(y+left_border_grid, upper_border_grid),(y+left_border_grid, lower_border_grid)], fill=0, width=2)
|
||||||
|
|
||||||
for y in range(upper_border_writable+2,lower_border_grid,two_hour_space):
|
for y in range(upper_border_grid+weekday_height+2,lower_border_grid,two_hour_space):
|
||||||
for x in range(left_border_grid, right_border_grid, 6):
|
for x in range(left_border_grid, right_border_grid, 6):
|
||||||
draw.line([(x, y), (x+2, y)], fill = 0, width = 1)
|
draw.line([(x, y), (x+2, y)], fill = 0, width = 1)
|
||||||
|
|
||||||
#draw times for orientation
|
#draw times for orientation
|
||||||
i = 0
|
i = 0
|
||||||
for y in range(upper_border_writable+4,lower_border_grid,two_hour_space):
|
for y in range(upper_border_grid+weekday_height+4,lower_border_grid,two_hour_space):
|
||||||
draw.text((left_border_grid-timefont.getsize(str(i*2+first_hour))[0], y), str(i*2+first_hour), font = timefont, fill = 0)
|
draw.text((left_border_grid-timefont.getsize(str(i*2+first_hour))[0], y), str(i*2+first_hour), font = timefont, fill = 0)
|
||||||
i +=1
|
i +=1
|
||||||
|
|
||||||
already_an_event = np.zeros((7,lower_border_grid - upper_border_grid))
|
events_on_weekday = [0,0,0,0,0,0,0]
|
||||||
|
|
||||||
known_calendars = {"DLRG Kalendar" : "DLRG", "Uni Kalendar" : "UNI", "Persönlich" : "PER"}
|
known_calendars = {"DLRG Kalendar" : "DLRG", "Uni Kalendar" : "UNI", "Persönlich" : "PER"}
|
||||||
|
|
||||||
for event in day_events:
|
for event in day_events:
|
||||||
for d in range(event["START"].weekday(),event["END"].weekday()):
|
row = width_day*event["DATE"].weekday()+left_border_grid+4
|
||||||
row = width_day*d+left_border_grid+4
|
if event["CALENDAR"] in known_calendars:
|
||||||
if event["CALENDAR"] in known_calendars:
|
cal = known_calendars[event["CALENDAR"]]
|
||||||
cal = known_calendars[event["CALENDAR"]]
|
else:
|
||||||
else:
|
cal = event["CALENDAR"]
|
||||||
cal = event["CALENDAR"]
|
if(events_on_weekday[event["DATE"].weekday()]== 0):
|
||||||
if(np.amax(already_an_event[d,:])== 0):
|
draw.rectangle((row,upper_border_grid+weekday_height+5,row+width_day-6,lower_border_grid-1),fill = 255)
|
||||||
draw.rectangle((row,upper_border_writable+5,row+width_day-6,lower_border_grid-1),fill = 255)
|
draw.line([(row,upper_border_grid+weekday_height+5),(row,lower_border_grid-1)], width = 4, fill = 0)
|
||||||
draw.line([(row,upper_border_writable+5),(row,lower_border_grid-1)], width = 4, fill = 0)
|
draw.line([(row,lower_border_grid-2),(row+width_day-6,lower_border_grid-2)], width = 2, fill = 0)
|
||||||
draw.line([(row,lower_border_grid-2),(row+width_day-6,lower_border_grid-2)], width = 2, fill = 0)
|
draw.line([(row,upper_border_grid+weekday_height+5),(row+width_day-6,upper_border_grid+weekday_height+5)], width = 2, fill = 0)
|
||||||
draw.line([(row,upper_border_writable+5),(row+width_day-6,upper_border_writable+5)], width = 2, fill = 0)
|
draw.line([(row+width_day-7,upper_border_grid+weekday_height+5),(row+width_day-7,lower_border_grid-1)], width = 2, fill = 0)
|
||||||
draw.line([(row+width_day-7,upper_border_writable+5),(row+width_day-7,lower_border_grid-1)], width = 2, fill = 0)
|
wi, hi = eventfont.getsize (event["SUMMARY"])
|
||||||
wi, hi = eventfont.getsize (event["SUMMARY"])
|
draw_text_90_into("["+cal+"] "+event["SUMMARY"], Himage, (row+4,height_grid-(weekday_height+5)-round(wi/2)))
|
||||||
draw_text_90_into("["+cal+"] "+event["SUMMARY"], Himage, (row+4,round(height_grid/2-(weekday_height+5)-wi/2)))
|
else:
|
||||||
else:
|
wi, hi = eventfont.getsize(event["SUMMARY"])
|
||||||
wi, hi = eventfont.getsize(event["SUMMARY"])
|
draw.line([(row+6+hi,upper_border_grid+weekday_height+9),(row+6+hi,lower_border_grid-4)], width = 2, fill = 0)
|
||||||
draw.line([(row+6+hi,upper_border_writable+9),(row+6+hi,lower_border_grid-4)], width = 2, fill = 0)
|
draw_text_90_into("["+cal+"] "+event["SUMMARY"], Himage, (row+10+hi,-round(wi/2)))
|
||||||
draw_text_90_into("["+cal+"] "+event["SUMMARY"], Himage, (row+10+hi,round(height_grid/2-(weekday_height+5)-wi/2)))
|
events_on_weekday[event["DATE"].weekday()] += 1
|
||||||
already_an_event[d,:] += 1
|
|
||||||
|
|
||||||
for event in time_events:
|
for event in time_events:
|
||||||
#draw rectangle
|
#draw rectangle
|
||||||
|
@ -351,34 +259,26 @@ for event in time_events:
|
||||||
|
|
||||||
row_start = width_day*event["START"].weekday()+left_border_grid+4
|
row_start = width_day*event["START"].weekday()+left_border_grid+4
|
||||||
row_end = width_day*event["END"].weekday()+left_border_grid+4
|
row_end = width_day*event["END"].weekday()+left_border_grid+4
|
||||||
right_border_event = row_start+width_day-6
|
left_border_event = row_start+(events_on_weekday[event["START"].weekday()]*(6+(eventfont.getsize(event["SUMMARY"])[1])))
|
||||||
upper_border_event = round(upper_border_writable+5+((lower_border_grid-(upper_border_writable+5))/hours_in_day)*(event["START"].hour-first_hour+(event["START"].minute/60)))
|
right_border_event = row_start+width_day-6-((events_on_weekday[event["START"].weekday()])>0)*3
|
||||||
lower_border_event = round(upper_border_writable+5+((lower_border_grid-(upper_border_writable+5))/hours_in_day)*(event["END"].hour-first_hour+(event["END"].minute/60)))
|
upper_border_event = round(upper_border_grid+weekday_height+5+((lower_border_grid-(upper_border_grid+weekday_height+5))/hours_in_day)*(event["START"].hour-first_hour+(event["START"].minute/60)))
|
||||||
left_border_event = row_start+((np.amax(already_an_event[event["START"].weekday(),upper_border_event:lower_border_event]))*6)
|
lower_border_event = round(upper_border_grid+weekday_height+5+((lower_border_grid-(upper_border_grid+weekday_height+5))/hours_in_day)*(event["END"].hour-first_hour+(event["END"].minute/60)))
|
||||||
already_an_event[event["START"].weekday(),upper_border_event:lower_border_event] +=1
|
#blank out everything
|
||||||
if (row_start == row_end):
|
if (row_start == row_end):
|
||||||
draw.rectangle((left_border_event,upper_border_event,right_border_event,lower_border_event),fill = 255)
|
draw.rectangle((left_border_event,upper_border_event,right_border_event,lower_border_event),fill = 255)
|
||||||
if(lower_border_event<lower_border_grid):
|
|
||||||
draw.line([(left_border_event,lower_border_event),(right_border_event,lower_border_event)], width = 2, fill = 0)
|
|
||||||
draw.line([(left_border_event,upper_border_event),(left_border_event, min(lower_border_event,lower_border_grid))], width = 4, fill = 0)
|
|
||||||
draw.line([(right_border_event-1,upper_border_event),(right_border_event-1,min(lower_border_event,lower_border_grid))], width = 2, fill = 0)
|
|
||||||
draw.line([(left_border_event,upper_border_event),(right_border_event,upper_border_event)], width = 2, fill = 0)
|
|
||||||
else:
|
else:
|
||||||
draw.rectangle((left_border_event,upper_border_event,right_border_event,lower_border_grid),fill = 255)
|
|
||||||
draw.line([(left_border_event,upper_border_event),(left_border_event,lower_border_grid-1)], width = 4, fill = 0)
|
|
||||||
draw.line([(right_border_event-1,upper_border_event),(right_border_event-1,lower_border_grid-2)], width = 2, fill = 0)
|
|
||||||
draw.line([(left_border_event,upper_border_event),(right_border_event,upper_border_event)], width = 2, fill = 0)
|
|
||||||
for d in range(event["START"].weekday()+1,event["END"].weekday()):
|
|
||||||
draw.rectangle((left_border_event+(d*width_day),upper_border_writable+5,right_border_event+(d*width_day),lower_border_grid),fill = 255)
|
|
||||||
draw.line([(left_border_event+(d*width_day),upper_border_writable+5),(left_border_event+(d*width_day),lower_border_grid-1)], width = 4, fill = 0)
|
|
||||||
draw.line([(right_border_event-1+(d*width_day),upper_border_writable+5),(right_border_event-1+(d*width_day),lower_border_grid-2)], width = 2, fill = 0)
|
|
||||||
if(event["END"].hour> first_hour):
|
|
||||||
draw.rectangle((left_border_event+((event["END"].weekday()-event["START"].weekday())*width_day),upper_border_writable+5,right_border_event+((event["END"].weekday()-event["START"].weekday())*width_day),lower_border_event),fill = 255)
|
|
||||||
draw.line([(left_border_event+((event["END"].weekday()-event["START"].weekday())*width_day),upper_border_writable+5),(left_border_event+((event["END"].weekday()-event["START"].weekday())*width_day),lower_border_event)], width = 4, fill = 0)
|
|
||||||
draw.line([(right_border_event-1+((event["END"].weekday()-event["START"].weekday())*width_day),upper_border_writable+5),(right_border_event-1+((event["END"].weekday()-event["START"].weekday())*width_day),lower_border_event)], width = 2, fill = 0)
|
|
||||||
if(lower_border_event<lower_border_grid):
|
|
||||||
draw.line([(left_border_event+((event["END"].weekday()-event["START"].weekday())*width_day),lower_border_event),(right_border_event+((event["END"].weekday()-event["START"].weekday())*width_day),lower_border_event)], width = 2, fill = 0)
|
|
||||||
|
|
||||||
|
for d in range(event["START"].weekday()+1,event["END"].weekday()):
|
||||||
|
draw.rectangle((left_border_event+(d*width_day),upper_border_grid+weekday_height+5,right_border_event+(d*width_day),lower_border_grid),fill = 255)
|
||||||
|
draw.line([(left_border_event+(d*width_day),upper_border_grid+weekday_height+5),(left_border_event+(d*width_day),lower_border_grid-1)], width = 4, fill = 0)
|
||||||
|
draw.line([(right_border_event-1+(d*width_day),lower_border_grid-2),(right_border_event-1+(d*width_day),lower_border_grid-2)], width = 2, fill = 0)
|
||||||
|
|
||||||
|
#draw borders
|
||||||
|
draw.line([(left_border_event,upper_border_event),(left_border_event, min(lower_border_event,lower_border_grid))], width = 4, fill = 0)
|
||||||
|
if(lower_border_event<lower_border_grid):
|
||||||
|
draw.line([(left_border_event,lower_border_event),(right_border_event,lower_border_event)], width = 2, fill = 0)
|
||||||
|
draw.line([(left_border_event,upper_border_event),(right_border_event,upper_border_event)], width = 2, fill = 0)
|
||||||
|
draw.line([(right_border_event-1,upper_border_event),(right_border_event-1,min(lower_border_event,lower_border_grid))], width = 2, fill = 0)
|
||||||
#use abbreviations for some calendars...
|
#use abbreviations for some calendars...
|
||||||
if event["CALENDAR"] in known_calendars:
|
if event["CALENDAR"] in known_calendars:
|
||||||
cal = known_calendars[event["CALENDAR"]]
|
cal = known_calendars[event["CALENDAR"]]
|
||||||
|
@ -386,13 +286,13 @@ for event in time_events:
|
||||||
cal = event["CALENDAR"]
|
cal = event["CALENDAR"]
|
||||||
wi,hi = eventfont.getsize(event["SUMMARY"])
|
wi,hi = eventfont.getsize(event["SUMMARY"])
|
||||||
#format event title, calendar and time to fit into the rectangle
|
#format event title, calendar and time to fit into the rectangle
|
||||||
if(event["START"].day == event["END"].day and lower_border_event-upper_border_event-2 < hi) or lower_border_grid-upper_border_event-2 < hi:
|
if(lower_border_event-upper_border_event-2 < hi):
|
||||||
cropped_ev_str = ('{:2d}'.format(event["START"].hour)+":"+'{:02d}'.format(event["START"].minute)+ " " +event["SUMMARY"])
|
cropped_ev_str = ('{:2d}'.format(event["START"].hour)+":"+'{:02d}'.format(event["START"].minute)+ " " +event["SUMMARY"])
|
||||||
while (eventfont.getsize(cropped_ev_str)[0] > right_border_event-left_border_event-4):
|
while (eventfont.getsize(cropped_ev_str)[0] > right_border_event-left_border_event-4):
|
||||||
cropped_ev_str = cropped_ev_str[:-1]
|
cropped_ev_str = cropped_ev_str[:-1]
|
||||||
draw.text((left_border_event+6, lower_border_event+4),cropped_ev_str, font = eventfont, fill = 0)
|
draw.text((left_border_event+6, lower_border_event+4),cropped_ev_str, font = eventfont, fill = 0)
|
||||||
|
|
||||||
elif(event["START"].day == event["END"].day and lower_border_event-upper_border_event-2 < hi*2) or lower_border_grid-upper_border_event-2 < hi*2:
|
elif(lower_border_event-upper_border_event-2 < hi*2):
|
||||||
cropped_ev_str = ('{:2d}'.format(event["START"].hour)+":"+'{:02d}'.format(event["START"].minute)+ " " +event["SUMMARY"])
|
cropped_ev_str = ('{:2d}'.format(event["START"].hour)+":"+'{:02d}'.format(event["START"].minute)+ " " +event["SUMMARY"])
|
||||||
while (eventfont.getsize(cropped_ev_str)[0] > right_border_event-left_border_event-4):
|
while (eventfont.getsize(cropped_ev_str)[0] > right_border_event-left_border_event-4):
|
||||||
cropped_ev_str = cropped_ev_str[:-1]
|
cropped_ev_str = cropped_ev_str[:-1]
|
||||||
|
@ -411,14 +311,10 @@ for event in time_events:
|
||||||
|
|
||||||
# draw a line for current date and time
|
# draw a line for current date and time
|
||||||
now_row = width_day*datetime.now().weekday()+left_border_grid
|
now_row = width_day*datetime.now().weekday()+left_border_grid
|
||||||
now_time = round(upper_border_writable+5+(((last_hour_line-(upper_border_writable+5))/(hours_in_day-(hours_in_day%2)))*(datetime.now().hour-first_hour+(datetime.now().minute/60))))
|
now_time = round(upper_border_grid+weekday_height+5+(((last_hour_line-(upper_border_grid+weekday_height+5))/(hours_in_day-(hours_in_day%2)))*(datetime.now().hour-first_hour+(datetime.now().minute/60))))
|
||||||
if(now_time < lower_border_grid and now_time > upper_border_writable+2):
|
if(now_time < lower_border_grid and now_time > upper_border_grid+weekday_height+2):
|
||||||
if has_color:
|
draw.line([(now_row,now_time),(now_row+width_day-2,now_time)], width = 2, fill = 0)
|
||||||
draw_r.line([(now_row,now_time),(now_row+width_day-2,now_time)], width = 2, fill = 0)
|
draw.ellipse((now_row, now_time, now_row+10, now_time+4), fill = 0)
|
||||||
draw_r.ellipse((now_row, now_time, now_row+10, now_time+4), fill = 0)
|
|
||||||
else:
|
|
||||||
draw.line([(now_row,now_time),(now_row+width_day-2,now_time)], width = 2, fill = 0)
|
|
||||||
draw.ellipse((now_row, now_time, now_row+10, now_time+4), fill = 0)
|
|
||||||
|
|
||||||
#draw warnings, if something went wrong with the connection
|
#draw warnings, if something went wrong with the connection
|
||||||
if(not server_reached):
|
if(not server_reached):
|
||||||
|
@ -426,7 +322,4 @@ if(not server_reached):
|
||||||
if(not client_established):
|
if(not client_established):
|
||||||
Himage.paste(Image.open("./resource/unauthorized.png"), (right_border_grid-40,lower_border_grid-40))
|
Himage.paste(Image.open("./resource/unauthorized.png"), (right_border_grid-40,lower_border_grid-40))
|
||||||
Himage.save("./canvas.bmp")
|
Himage.save("./canvas.bmp")
|
||||||
HRimage.save("./r_canvas.bmp")
|
|
||||||
|
|
||||||
if(on_e_paper):
|
|
||||||
epd.display(epd.getbuffer(Himage), epd.getbuffer(HRimage))
|
|
Loading…
Add table
Add a link
Reference in a new issue