| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  | #!/usr/bin/python3 | 
					
						
							|  |  |  | # -*- coding: utf-8 -*- | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | E-Paper Software (main script) for the 3-colour and 2-Colour E-Paper display | 
					
						
							|  |  |  | A full and detailed breakdown for this code can be found in the wiki. | 
					
						
							|  |  |  | If you have any questions, feel free to open an issue at Github. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Copyright by aceisace | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | from __future__ import print_function | 
					
						
							|  |  |  | import calendar | 
					
						
							| 
									
										
										
										
											2019-02-25 22:14:16 +01:00
										 |  |  | from datetime import datetime, date, timedelta | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  | from time import sleep | 
					
						
							| 
									
										
										
										
											2019-03-02 19:07:36 +01:00
										 |  |  | from dateutil.rrule import * | 
					
						
							|  |  |  | from dateutil.parser import parse | 
					
						
							|  |  |  | import re | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  | import random | 
					
						
							|  |  |  | import gc | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     import feedparser | 
					
						
							|  |  |  | except ImportError: | 
					
						
							|  |  |  |     print("Please install feedparser with: sudo pip3 install feedparser") | 
					
						
							|  |  |  |     print("and") | 
					
						
							|  |  |  |     print("pip3 install feedparser") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     import numpy as np | 
					
						
							|  |  |  | except ImportError: | 
					
						
							| 
									
										
										
										
											2019-03-12 18:21:00 +01:00
										 |  |  |     print("Please install numpy with: sudo apt-get install python3-numpy") | 
					
						
							| 
									
										
										
										
											2019-03-02 19:07:36 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  | from settings import * | 
					
						
							|  |  |  | from icon_positions_locations import * | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  | from PIL import Image, ImageDraw, ImageFont, ImageOps | 
					
						
							|  |  |  | import pyowm | 
					
						
							|  |  |  | from ics import Calendar | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     from urllib.request import urlopen | 
					
						
							|  |  |  | except Exception as e: | 
					
						
							|  |  |  |     print("Something didn't work right, maybe you're offline?"+e.reason) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if display_colours == "bwr": | 
					
						
							|  |  |  |     import epd7in5b | 
					
						
							|  |  |  |     epd = epd7in5b.EPD() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if display_colours == "bw": | 
					
						
							|  |  |  |     import epd7in5 | 
					
						
							|  |  |  |     epd = epd7in5.EPD() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from calibration import calibration | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EPD_WIDTH = 640 | 
					
						
							|  |  |  | EPD_HEIGHT = 384 | 
					
						
							|  |  |  | font = ImageFont.truetype(path+'Assistant-Regular.ttf', 18) | 
					
						
							|  |  |  | im_open = Image.open | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  | possible_update_values = [10, 15, 20, 30, 60] | 
					
						
							|  |  |  | if int(update_interval) not in possible_update_values: | 
					
						
							|  |  |  |     print('Selected update-interval: ',update_interval, 'minutes') | 
					
						
							|  |  |  |     print('Please select an update interval from these values:', possible_update_values) | 
					
						
							|  |  |  |     raise ValueError | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  | """Main loop starts from here""" | 
					
						
							|  |  |  | def main(): | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |     calibration_countdown = 60//int(update_interval) - 60//int(datetime.now().strftime("%M")) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |     while True: | 
					
						
							|  |  |  |         time = datetime.now() | 
					
						
							|  |  |  |         hour = int(time.strftime("%-H")) | 
					
						
							|  |  |  |         month = int(time.now().strftime('%-m')) | 
					
						
							|  |  |  |         year = int(time.now().strftime('%Y')) | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |         mins = int(time.strftime("%M")) | 
					
						
							|  |  |  |         seconds = int(time.strftime("%S")) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for i in range(1): | 
					
						
							|  |  |  |             print('_________Starting new loop___________'+'\n') | 
					
						
							| 
									
										
										
										
											2019-02-25 22:14:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |             """Start by printing the date and time for easier debugging""" | 
					
						
							|  |  |  |             print('Date:', time.strftime('%a %-d %b %y'), 'Time: '+time.strftime('%H:%M')+'\n') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             """At the hours specified in the settings file,
 | 
					
						
							|  |  |  |             calibrate the display to prevent ghosting"""
 | 
					
						
							|  |  |  |             if hour in calibration_hours: | 
					
						
							|  |  |  |                 print('Current countdown:',calibration_countdown) | 
					
						
							|  |  |  |                 calibration_countdown -= 1 | 
					
						
							|  |  |  |                 print('counts left until calibration:',calibration_countdown) | 
					
						
							| 
									
										
										
										
											2019-03-12 18:14:24 +01:00
										 |  |  |                 if calibration_countdown <= 1: | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |                     calibration() | 
					
						
							|  |  |  |                     print('Resetting Countdown') | 
					
						
							|  |  |  |                     calibration_countdown = 60//int(update_interval) | 
					
						
							|  |  |  |                     print('Calibration countdown:',calibration_countdown) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             """Create a blank white page first""" | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  |             image = Image.new('RGB', (EPD_HEIGHT, EPD_WIDTH), 'white') | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |             """Add the icon with the current month's name""" | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |             image.paste(im_open(mpath+str(time.strftime("%B")+'.jpeg')), monthplace) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |             """Add the line seperating the weather and Calendar section""" | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |             image.paste(seperator, seperatorplace) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |             """Add weekday-icons (Mon, Tue...) and draw a circle on the
 | 
					
						
							|  |  |  |             current weekday"""
 | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |             if (week_starts_on == "Monday"): | 
					
						
							|  |  |  |                 calendar.setfirstweekday(calendar.MONDAY) | 
					
						
							|  |  |  |                 image.paste(weekmon, weekplace) | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  |                 image.paste(weekday, weekdaysmon[(time.strftime("%a"))], weekday) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |             """For those whose week starts on Sunday, change accordingly""" | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |             if (week_starts_on == "Sunday"): | 
					
						
							|  |  |  |                 calendar.setfirstweekday(calendar.SUNDAY) | 
					
						
							|  |  |  |                 image.paste(weeksun, weekplace) | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  |                 image.paste(weekday, weekdayssun[(time.strftime("%a"))], weekday) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             """Using the built-in calendar function, draw icons for each
 | 
					
						
							|  |  |  |                number of the month (1,2,3,...28,29,30)"""
 | 
					
						
							|  |  |  |             cal = calendar.monthcalendar(time.year, time.month) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for numbers in cal[0]: | 
					
						
							|  |  |  |                 image.paste(im_open(dpath+str(numbers)+'.jpeg'), positions['a'+str(cal[0].index(numbers)+1)]) | 
					
						
							|  |  |  |             for numbers in cal[1]: | 
					
						
							|  |  |  |                 image.paste(im_open(dpath+str(numbers)+'.jpeg'), positions['b'+str(cal[1].index(numbers)+1)]) | 
					
						
							|  |  |  |             for numbers in cal[2]: | 
					
						
							|  |  |  |                 image.paste(im_open(dpath+str(numbers)+'.jpeg'), positions['c'+str(cal[2].index(numbers)+1)]) | 
					
						
							|  |  |  |             for numbers in cal[3]: | 
					
						
							|  |  |  |                 image.paste(im_open(dpath+str(numbers)+'.jpeg'), positions['d'+str(cal[3].index(numbers)+1)]) | 
					
						
							|  |  |  |             for numbers in cal[4]: | 
					
						
							|  |  |  |                 image.paste(im_open(dpath+str(numbers)+'.jpeg'), positions['e'+str(cal[4].index(numbers)+1)]) | 
					
						
							| 
									
										
										
										
											2019-02-25 22:14:16 +01:00
										 |  |  |             if len(cal) == 6: | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |                 for numbers in cal[5]: | 
					
						
							|  |  |  |                     image.paste(im_open(dpath+str(numbers)+'.jpeg'), positions['f'+str(cal[5].index(numbers)+1)]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             """Custom function to display text on the E-Paper.
 | 
					
						
							|  |  |  |             Tuple refers to the x and y coordinates of the E-Paper display, | 
					
						
							|  |  |  |             with (0, 0) being the top left corner of the display."""
 | 
					
						
							|  |  |  |             def write_text(box_width, box_height, text, tuple): | 
					
						
							|  |  |  |                 text_width, text_height = font.getsize(text) | 
					
						
							|  |  |  |                 if (text_width, text_height) > (box_width, box_height): | 
					
						
							|  |  |  |                     raise ValueError('Sorry, your text is too big for the box') | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     x = int((box_width / 2) - (text_width / 2)) | 
					
						
							|  |  |  |                     y = int((box_height / 2) - (text_height / 2)) | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  |                     space = Image.new('RGB', (box_width, box_height), color='white') | 
					
						
							|  |  |  |                     ImageDraw.Draw(space).text((x, y), text, fill='black', font=font) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |                     image.paste(space, tuple) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |             """Connect to Openweathermap API to fetch weather data""" | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |             print("Connecting to Openweathermap API servers...") | 
					
						
							|  |  |  |             owm = pyowm.OWM(api_key) | 
					
						
							|  |  |  |             if owm.is_API_online() is True: | 
					
						
							|  |  |  |                 observation = owm.weather_at_place(location) | 
					
						
							|  |  |  |                 print("weather data:") | 
					
						
							|  |  |  |                 weather = observation.get_weather() | 
					
						
							|  |  |  |                 weathericon = weather.get_weather_icon_name() | 
					
						
							|  |  |  |                 Humidity = str(weather.get_humidity()) | 
					
						
							|  |  |  |                 cloudstatus = str(weather.get_clouds()) | 
					
						
							|  |  |  |                 weather_description = (str(weather.get_status())) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if units == "metric": | 
					
						
							|  |  |  |                     Temperature = str(int(weather.get_temperature(unit='celsius')['temp'])) | 
					
						
							|  |  |  |                     windspeed = str(int(weather.get_wind()['speed'])) | 
					
						
							|  |  |  |                     write_text(50, 35, Temperature + " °C", (334, 0)) | 
					
						
							|  |  |  |                     write_text(100, 35, windspeed+" km/h", (114, 0)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if units == "imperial": | 
					
						
							|  |  |  |                     Temperature = str(int(weather.get_temperature('fahrenheit')['temp'])) | 
					
						
							|  |  |  |                     windspeed = str(int(weather.get_wind()['speed']*0.621)) | 
					
						
							|  |  |  |                     write_text(50, 35, Temperature + " °F", (334, 0)) | 
					
						
							|  |  |  |                     write_text(100, 35, windspeed+" mph", (114, 0)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if hours == "24": | 
					
						
							|  |  |  |                     sunrisetime = str(datetime.fromtimestamp(int(weather.get_sunrise_time(timeformat='unix'))).strftime('%-H:%M')) | 
					
						
							|  |  |  |                     sunsettime = str(datetime.fromtimestamp(int(weather.get_sunset_time(timeformat='unix'))).strftime('%-H:%M')) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if hours == "12": | 
					
						
							|  |  |  |                     sunrisetime = str(datetime.fromtimestamp(int(weather.get_sunrise_time(timeformat='unix'))).strftime('%-I:%M')) | 
					
						
							|  |  |  |                     sunsettime = str(datetime.fromtimestamp(int(weather.get_sunset_time(timeformat='unix'))).strftime('%-I:%M')) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 print('Temperature: '+Temperature+' °C') | 
					
						
							|  |  |  |                 print('Humidity: '+Humidity+'%') | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |                 #print('Icon code: '+weathericon) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |                 print('weather-icon name: '+weathericons[weathericon]) | 
					
						
							|  |  |  |                 print('Wind speed: '+windspeed+'km/h') | 
					
						
							|  |  |  |                 print('Sunrise-time: '+sunrisetime) | 
					
						
							|  |  |  |                 print('Sunset time: '+sunsettime) | 
					
						
							|  |  |  |                 print('Cloudiness: ' + cloudstatus+'%') | 
					
						
							|  |  |  |                 print('Weather description: '+weather_description+'\n') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |                 """Add the weather icon at the top left corner""" | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |                 image.paste(im_open(wpath+weathericons[weathericon]+'.jpeg'), wiconplace) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |                 """Add the temperature icon at it's position""" | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |                 image.paste(tempicon, tempplace) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |                 """Add the humidity icon and display the humidity""" | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |                 image.paste(humicon, humplace) | 
					
						
							|  |  |  |                 write_text(50, 35, Humidity + " %", (334, 35)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |                 """Add the sunrise icon and display the sunrise time""" | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |                 image.paste(sunriseicon, sunriseplace) | 
					
						
							|  |  |  |                 write_text(50, 35, sunrisetime, (249, 0)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |                 """Add the sunset icon and display the sunrise time""" | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |                 image.paste(sunseticon, sunsetplace) | 
					
						
							|  |  |  |                 write_text(50, 35, sunsettime, (249, 35)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |                 """Add the wind icon at it's position""" | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |                 image.paste(windicon, windiconspace) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |                 """Add a short weather description""" | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |                 write_text(144, 35, weather_description, (70, 35)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             else: | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |                 """If no response was received from the openweathermap
 | 
					
						
							|  |  |  |                 api server, add the cloud with question mark"""
 | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |                 image.paste(no_response, wiconplace) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |             """Algorithm for filtering and sorting events from your
 | 
					
						
							|  |  |  |             iCalendar/s"""
 | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |             print('Fetching events from your calendar'+'\n') | 
					
						
							|  |  |  |             events_this_month = [] | 
					
						
							|  |  |  |             upcoming = [] | 
					
						
							| 
									
										
										
										
											2019-02-25 22:14:16 +01:00
										 |  |  |             today = date.today() | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             """Create a time span using the events_max_range value (in days)
 | 
					
						
							|  |  |  |             to filter events in that range"""
 | 
					
						
							| 
									
										
										
										
											2019-02-25 22:14:16 +01:00
										 |  |  |             time_span = today + timedelta(days=int(events_max_range)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |             for icalendars in ical_urls: | 
					
						
							| 
									
										
										
										
											2019-02-14 15:27:41 +01:00
										 |  |  |                 decode = str(urlopen(icalendars).read().decode()) | 
					
						
							| 
									
										
										
										
											2019-02-21 20:11:16 +01:00
										 |  |  |                 fix_e_1 = decode.replace('BEGIN:VALARM\r\nACTION:NONE','BEGIN:VALARM\r\nACTION:DISPLAY\r\nDESCRIPTION:') | 
					
						
							|  |  |  |                 fix_e_2 = fix_e_1.replace('BEGIN:VALARM\r\nACTION:EMAIL','BEGIN:VALARM\r\nACTION:DISPLAY\r\nDESCRIPTION:') | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |                 # print(fix_e_2) #print iCal as string | 
					
						
							| 
									
										
										
										
											2019-02-21 20:11:16 +01:00
										 |  |  |                 ical = Calendar(fix_e_2) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |                 for events in ical.events: | 
					
						
							| 
									
										
										
										
											2019-03-07 15:31:45 +01:00
										 |  |  |                     if events.begin.date().month == today.month: | 
					
						
							|  |  |  |                         if int((events.begin).format('D')) not in events_this_month: | 
					
						
							|  |  |  |                             events_this_month.append(int((events.begin).format('D'))) | 
					
						
							|  |  |  |                         if today <= events.begin.date() <= time_span: | 
					
						
							|  |  |  |                             upcoming.append({'date':events.begin.format('YYYY MM DD'), 'event':events.name}) | 
					
						
							| 
									
										
										
										
											2019-02-14 15:27:41 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             def takeDate(elem): | 
					
						
							|  |  |  |                 return elem['date'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             upcoming.sort(key=takeDate) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |             #print('Upcoming events:',upcoming) #Display fetched events | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             def write_text_left(box_width, box_height, text, tuple): | 
					
						
							|  |  |  |                 text_width, text_height = font.getsize(text) | 
					
						
							| 
									
										
										
										
											2019-02-14 15:27:41 +01:00
										 |  |  |                 while (text_width, text_height) > (box_width, box_height): | 
					
						
							|  |  |  |                     text=text[0:-1] | 
					
						
							|  |  |  |                     text_width, text_height = font.getsize(text) | 
					
						
							|  |  |  |                 y = int((box_height / 2) - (text_height / 2)) | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  |                 space = Image.new('RGB', (box_width, box_height), color='white') | 
					
						
							|  |  |  |                 ImageDraw.Draw(space).text((0, y), text, fill='black', font=font) | 
					
						
							| 
									
										
										
										
											2019-02-14 15:27:41 +01:00
										 |  |  |                 image.paste(space, tuple) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             """Write event dates and names on the E-Paper""" | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |             if additional_feature == "events": | 
					
						
							|  |  |  |                 if len(cal) == 5: | 
					
						
							|  |  |  |                     del upcoming[6:] | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |                     for dates in range(len(upcoming)): | 
					
						
							|  |  |  |                         readable_date = datetime.strptime(upcoming[dates]['date'], '%Y %m %d').strftime('%-d %b') | 
					
						
							|  |  |  |                         write_text(70, 25, readable_date, date_positions['d'+str(dates+1)]) | 
					
						
							|  |  |  |                     for events in range(len(upcoming)): | 
					
						
							|  |  |  |                         write_text_left(314, 25, (upcoming[events]['event']), event_positions['e'+str(events+1)]) | 
					
						
							| 
									
										
										
										
											2019-02-25 22:14:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |                 if len(cal) == 6: | 
					
						
							|  |  |  |                     del upcoming[4:] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     for dates in range(len(upcoming)): | 
					
						
							|  |  |  |                         readable_date = datetime.strptime(upcoming[dates]['date'], '%Y %m %d').strftime('%-d %b') | 
					
						
							|  |  |  |                         write_text(70, 25, readable_date, date_positions['d'+str(dates+3)]) | 
					
						
							|  |  |  |                     for events in range(len(upcoming)): | 
					
						
							|  |  |  |                         write_text_left(314, 25, (upcoming[events]['event']), event_positions['e'+str(events+3)]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             """Add rss-feeds at the bottom section of the Calendar""" | 
					
						
							|  |  |  |             if additional_feature == "rss": | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 def multiline_text(text, max_width): | 
					
						
							|  |  |  |                     lines = [] | 
					
						
							|  |  |  |                     if font.getsize(text)[0] <= max_width: | 
					
						
							|  |  |  |                         lines.append(text) | 
					
						
							|  |  |  |                     else: | 
					
						
							|  |  |  |                         words = text.split(' ') | 
					
						
							|  |  |  |                         i = 0 | 
					
						
							|  |  |  |                         while i < len(words): | 
					
						
							|  |  |  |                             line = '' | 
					
						
							|  |  |  |                             while i < len(words) and font.getsize(line + words[i])[0] <= max_width: | 
					
						
							|  |  |  |                                 line = line + words[i] + " " | 
					
						
							|  |  |  |                                 i += 1 | 
					
						
							|  |  |  |                             if not line: | 
					
						
							|  |  |  |                                 line = words[i] | 
					
						
							|  |  |  |                                 i += 1 | 
					
						
							|  |  |  |                             lines.append(line) | 
					
						
							|  |  |  |                     return lines | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 rss_feed = [] | 
					
						
							|  |  |  |                 for feeds in rss_feeds: | 
					
						
							|  |  |  |                     text = feedparser.parse(feeds) | 
					
						
							|  |  |  |                     for posts in text.entries: | 
					
						
							|  |  |  |                         rss_feed.append(posts.title) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 random.shuffle(rss_feed) | 
					
						
							|  |  |  |                 news = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if len(cal) == 5: | 
					
						
							| 
									
										
										
										
											2019-03-12 16:13:55 +01:00
										 |  |  |                     del rss_feed[6:] | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 if len(cal) == 6: | 
					
						
							| 
									
										
										
										
											2019-03-12 16:13:55 +01:00
										 |  |  |                     del rss_feed[4:] | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 for title in range(len(rss_feeds)): | 
					
						
							|  |  |  |                     news.append(multiline_text(rss_feed[title], 384)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 news = [j for i in news for j in i] | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |                 if len(cal) == 5: | 
					
						
							|  |  |  |                     if len(news) > 6: | 
					
						
							|  |  |  |                         del news[6:] | 
					
						
							|  |  |  |                     for lines in range(len(news)): | 
					
						
							|  |  |  |                         write_text_left(384, 25, news[lines], rss_places['line_'+str(lines+1)]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if len(cal) == 6: | 
					
						
							|  |  |  |                     if len(news) > 4: | 
					
						
							|  |  |  |                         del news[4:] | 
					
						
							|  |  |  |                     for lines in range(len(news)): | 
					
						
							|  |  |  |                         write_text_left(384, 25, news[lines], rss_places['line_'+str(lines+3)]) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             """Draw smaller squares on days with events""" | 
					
						
							|  |  |  |             for numbers in events_this_month: | 
					
						
							|  |  |  |                 if numbers in cal[0]: | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  |                     image.paste(eventicon, positions['a'+str(cal[0].index(numbers)+1)], eventicon) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |                 if numbers in cal[1]: | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  |                     image.paste(eventicon, positions['b'+str(cal[1].index(numbers)+1)], eventicon) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |                 if numbers in cal[2]: | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  |                     image.paste(eventicon, positions['c'+str(cal[2].index(numbers)+1)], eventicon) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |                 if numbers in cal[3]: | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  |                     image.paste(eventicon, positions['d'+str(cal[3].index(numbers)+1)], eventicon) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |                 if numbers in cal[4]: | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  |                     image.paste(eventicon, positions['e'+str(cal[4].index(numbers)+1)], eventicon) | 
					
						
							| 
									
										
										
										
											2019-02-25 22:14:16 +01:00
										 |  |  |                 if len(cal) == 6: | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |                     if numbers in cal[5]: | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  |                         image.paste(eventicon, positions['f'+str(cal[5].index(numbers)+1)], eventicon) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             """Draw a larger square on today's date""" | 
					
						
							|  |  |  |             today = time.day | 
					
						
							|  |  |  |             if today in cal[0]: | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  |                 image.paste(dateicon, positions['a'+str(cal[0].index(today)+1)], dateicon) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |             if today in cal[1]: | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  |                 image.paste(dateicon, positions['b'+str(cal[1].index(today)+1)], dateicon) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |             if today in cal[2]: | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  |                 image.paste(dateicon, positions['c'+str(cal[2].index(today)+1)], dateicon) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |             if today in cal[3]: | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  |                 image.paste(dateicon, positions['d'+str(cal[3].index(today)+1)], dateicon) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |             if today in cal[4]: | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  |                 image.paste(dateicon, positions['e'+str(cal[4].index(today)+1)], dateicon) | 
					
						
							| 
									
										
										
										
											2019-02-25 22:14:16 +01:00
										 |  |  |             if len(cal) == 6: | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |                 if today in cal[5]: | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  |                     image.paste(dateicon, positions['f'+str(cal[5].index(today)+1)], dateicon) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             """
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |             Map all pixels of the generated image to red, white and black | 
					
						
							|  |  |  |             so that the image can be displayed 'correctly' on the E-Paper | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  |             """
 | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |             buffer = np.array(image) | 
					
						
							|  |  |  |             r,g,b = buffer[:,:,0], buffer[:,:,1], buffer[:,:,2] | 
					
						
							|  |  |  |             if display_colours == "bwr": | 
					
						
							|  |  |  |                 buffer[np.logical_and(r > 240, g > 240)] = [255,255,255] #white | 
					
						
							|  |  |  |                 buffer[np.logical_and(r > 240, g < 240)] = [255,0,0] #red | 
					
						
							|  |  |  |                 buffer[np.logical_and(r != 255, r ==g )] = [0,0,0] #black | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if display_colours == "bw": | 
					
						
							|  |  |  |                 buffer[np.logical_and(r > 240, g > 240)] = [255,255,255] #white | 
					
						
							| 
									
										
										
										
											2019-03-11 21:42:35 +01:00
										 |  |  |                 buffer[g < 255] = [0,0,0] #black | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |              | 
					
						
							|  |  |  |             improved_image = Image.fromarray(buffer).rotate(270, expand=True) | 
					
						
							|  |  |  |             print('Initialising E-Paper Display') | 
					
						
							|  |  |  |             epd.init() | 
					
						
							|  |  |  |             sleep(5) | 
					
						
							|  |  |  |             print('Converting image to data and sending it to the display') | 
					
						
							|  |  |  |             epd.display_frame(epd.get_frame_buffer(improved_image)) | 
					
						
							|  |  |  |             print('Data sent successfully') | 
					
						
							|  |  |  |             print('______Powering off the E-Paper until the next loop______'+'\n') | 
					
						
							|  |  |  |             epd.sleep() | 
					
						
							| 
									
										
										
										
											2019-03-04 20:22:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |             del events_this_month[:] | 
					
						
							|  |  |  |             del upcoming[:] | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |             del rss_feed[:] | 
					
						
							|  |  |  |             del news[:] | 
					
						
							|  |  |  |             del buffer | 
					
						
							|  |  |  |             del image | 
					
						
							|  |  |  |             del improved_image | 
					
						
							|  |  |  |             gc.collect() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  |             for i in range(1): | 
					
						
							| 
									
										
										
										
											2019-03-11 18:12:15 +01:00
										 |  |  |                 timings = [] | 
					
						
							|  |  |  |                 updates_per_hour = 60//int(update_interval) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 for times in range(updates_per_hour): | 
					
						
							|  |  |  |                     interval = 60-(times*int(update_interval)) | 
					
						
							|  |  |  |                     if interval >= mins: | 
					
						
							|  |  |  |                         time_left = (mins-interval)*(-1) | 
					
						
							|  |  |  |                         timings.append(time_left) | 
					
						
							|  |  |  |                 next_update = min(timings)*60 + (60-seconds) | 
					
						
							|  |  |  |                 print(min(timings),'Minutes and ', (60-seconds),'Seconds left until next loop') | 
					
						
							|  |  |  |                 del timings | 
					
						
							|  |  |  |                 print('sleeping for',next_update, 'seconds') | 
					
						
							|  |  |  |                 sleep(next_update) | 
					
						
							| 
									
										
										
										
											2019-02-03 16:26:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |     main() |