Compare commits

..

10 commits

3 changed files with 235 additions and 116 deletions

View file

@ -1 +1,4 @@
# 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 Normal file
View file

@ -0,0 +1,9 @@
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...

View file

@ -1,50 +1,76 @@
from datetime import datetime from datetime import datetime, date, time, timezone, timedelta
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 import sys, os
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
import getopt caldav_url = ''
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
inputfile = '' on_e_paper = False
outputfile = '' if(on_e_paper):
try: from waveshare_epd import epd7in5b_V2
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
f = open("./calendarlib.p") if not (len(datafile) == 0):
f = open(datafile)
server_reached = True server_reached = True
client_established = True client_established = True
@ -58,79 +84,107 @@ except (requests.ConnectionError, requests.Timeout) as exception:
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 = my_principal.calendars() calendars_fetched = 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
if(not birthdaycal == ''):
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({ day_events.append({
"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])), "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), "SUMMARY":str(event.vobject_instance.vevent.summary.value),
"CALENDAR":c.name "CALENDAR":c.name
}) })
else: else:
#otherwise it has to be a time event
sd = event_start_str.split(" ")[0] sd = event_start_str.split(" ")[0]
st = event_start_str.split(" ")[1] st = event_start_str.split(" ")[1]
sh = int(st.split(":")[0])+timezone[0]+int(st.split(":")[2][2:4]) sh = int(st.split(":")[0])+int(st.split(":")[2][2:4])
sm = int(st.split(":")[1])+timezone[1]+int(st.split(":")[3]) sm = int(st.split(":")[1])+int(st.split(":")[3])
ss = int(st.split(":")[2][0:1]) ss = int(st.split(":")[2][0:1])
ed = event_end_str.split(" ")[0] ed = event_end_str.split(" ")[0]
et = event_end_str.split(" ")[1] et = event_end_str.split(" ")[1]
eh = int(et.split(":")[0])+timezone[0]+int(st.split(":")[2][2:4]) eh = int(et.split(":")[0])+int(st.split(":")[2][2:4])
em = int(et.split(":")[1])+timezone[1]+int(et.split(":")[3]) em = int(et.split(":")[1])+int(et.split(":")[3])
es = int(et.split(":")[2][0:1]) es = int(et.split(":")[2][0:1])
time_events.append({ time_events.append({
"START":datetime(int(sd.split("-")[0]),int(sd.split("-")[1]),int(sd.split("-")[2]), hour = sh, minute = sm, second = ss), "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), "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
}) })
for event in day_events: #if the user wants one calendar to be treated as a birthday calendar, these are sorted into an extra library
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")
#back up the data received to a local copy so that it can be displayed if needed
if(len(datafile)!= 0):
calendarlib = {"DAY_EVENTS":day_events,"TIME_EVENTS":time_events,"BIRTHDAYS":birthdays} calendarlib = {"DAY_EVENTS":day_events,"TIME_EVENTS":time_events,"BIRTHDAYS":birthdays}
#f = open("./calendarlib.p")
p.dump( calendarlib, open( "calendarlib.p", "wb" )) p.dump( calendarlib, open( "calendarlib.p", "wb" ))
f.close() f.close()
else: else:
#if the server is not available, instead load information from datafile
if(len(datafile)!= 0):
print("Loading caldata from last time...") print("Loading caldata from last time...")
calendarlib = p.load(open("calendarlib.p","rb")) calendarlib = p.load(open(datafile,"rb"))
time_events = calendarlib["TIME_EVENTS"] time_events = calendarlib["TIME_EVENTS"]
day_events = calendarlib["DAY_EVENTS"] day_events = calendarlib["DAY_EVENTS"]
birthdays = calendarlib["BIRTHDAYS"] birthdays = calendarlib["BIRTHDAYS"]
else:
print("No data available!")
#get principal file 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
@ -155,19 +209,29 @@ 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
@ -182,6 +246,11 @@ 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
@ -202,56 +271,79 @@ 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"
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) w_str = (weekdays[language][weekday_l_key][j]+", "+str((monday+timedelta(days=j)).day)+"."+str((monday+timedelta(days=j)).month)+".")
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"
draw.text((left_border_grid+j*width_day+5, upper_border_grid), weekdays[language][weekday_l_key][j], font = weekdayfont, fill = 0) w_str = (weekdays[language][weekday_l_key][j])
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_grid+weekday_height+2),(right_border_grid, upper_border_grid+weekday_height+2)], fill=0, width=2) draw.line([(left_border_grid, upper_border_writable+2),(right_border_grid, upper_border_writable+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_grid+weekday_height+2,lower_border_grid,two_hour_space): for y in range(upper_border_writable+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_grid+weekday_height+4,lower_border_grid,two_hour_space): for y in range(upper_border_writable+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
events_on_weekday = [0,0,0,0,0,0,0] already_an_event = np.zeros((7,lower_border_grid - upper_border_grid))
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:
row = width_day*event["DATE"].weekday()+left_border_grid+4 for d in range(event["START"].weekday(),event["END"].weekday()):
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
@ -259,26 +351,34 @@ 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
left_border_event = row_start+(events_on_weekday[event["START"].weekday()]*(6+(eventfont.getsize(event["SUMMARY"])[1]))) right_border_event = row_start+width_day-6
right_border_event = row_start+width_day-6-((events_on_weekday[event["START"].weekday()])>0)*3 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)))
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))) 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)))
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))) left_border_event = row_start+((np.amax(already_an_event[event["START"].weekday(),upper_border_event:lower_border_event]))*6)
#blank out everything already_an_event[event["START"].weekday(),upper_border_event:lower_border_event] +=1
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)
else:
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): 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,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([(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([(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:
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)
#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"]]
@ -286,13 +386,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(lower_border_event-upper_border_event-2 < hi): 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:
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(lower_border_event-upper_border_event-2 < hi*2): 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:
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]
@ -311,8 +411,12 @@ 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_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)))) 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))))
if(now_time < lower_border_grid and now_time > upper_border_grid+weekday_height+2): if(now_time < lower_border_grid and now_time > upper_border_writable+2):
if has_color:
draw_r.line([(now_row,now_time),(now_row+width_day-2,now_time)], width = 2, 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.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.ellipse((now_row, now_time, now_row+10, now_time+4), fill = 0)
@ -322,4 +426,7 @@ 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))