minor improvements
fixed a few things in rss module, minor improvements to other modules. Added test file for use without installing
This commit is contained in:
parent
d1c3acaca2
commit
7970c4c517
26
dev_tests.py
Normal file
26
dev_tests.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
from inkycal.modules.inkycal_rss import rss
|
||||||
|
from inkycal.modules.inkycal_calendar import calendar
|
||||||
|
from inkycal.modules.inkycal_agenda import agenda
|
||||||
|
|
||||||
|
# Test rss module:
|
||||||
|
rss_size = (384, 160)
|
||||||
|
rss_config = {'rss_urls': ['http://feeds.bbci.co.uk/news/world/rss.xml#']}
|
||||||
|
rss = rss(rss_size, rss_config)
|
||||||
|
rss.generate_image()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Test calendar module:
|
||||||
|
|
||||||
|
calendar_size = (400, 520)
|
||||||
|
calendar_config = {'week_starts_on': 'Monday', 'ical_urls': ['https://calendar.google.com/calendar/ical/en.usa%23holiday%40group.v.calendar.google.com/public/basic.ics']}
|
||||||
|
calendar = calendar(calendar_size, calendar_config)
|
||||||
|
calendar.generate_image()
|
||||||
|
|
||||||
|
|
||||||
|
# Test agenda module:
|
||||||
|
|
||||||
|
agenda_size = (400, 520)
|
||||||
|
agenda_config = {'week_starts_on': 'Monday', 'ical_urls': ['https://calendar.google.com/calendar/ical/en.usa%23holiday%40group.v.calendar.google.com/public/basic.ics']}
|
||||||
|
agenda = agenda(agenda_size, agenda_config)
|
||||||
|
agenda.generate_image()
|
@ -8,7 +8,7 @@ Copyright by aceisace
|
|||||||
from inkycal.custom import *
|
from inkycal.custom import *
|
||||||
import calendar as cal
|
import calendar as cal
|
||||||
import arrow
|
import arrow
|
||||||
from ical_parser import icalendar
|
from inkycal.modules.ical_parser import icalendar
|
||||||
|
|
||||||
size = (400, 520)
|
size = (400, 520)
|
||||||
config = {'week_starts_on': 'Monday', 'ical_urls': ['https://calendar.google.com/calendar/ical/en.usa%23holiday%40group.v.calendar.google.com/public/basic.ics']}
|
config = {'week_starts_on': 'Monday', 'ical_urls': ['https://calendar.google.com/calendar/ical/en.usa%23holiday%40group.v.calendar.google.com/public/basic.ics']}
|
||||||
|
@ -26,15 +26,14 @@ class calendar:
|
|||||||
self.name = os.path.basename(__file__).split('.py')[0]
|
self.name = os.path.basename(__file__).split('.py')[0]
|
||||||
self.config = section_config
|
self.config = section_config
|
||||||
self.width, self.height = section_size
|
self.width, self.height = section_size
|
||||||
|
|
||||||
self.background_colour = 'white'
|
|
||||||
self.font_colour = 'black'
|
|
||||||
self.fontsize = 12
|
self.fontsize = 12
|
||||||
self.font = ImageFont.truetype(
|
self.font = ImageFont.truetype(
|
||||||
fonts['NotoSans-SemiCondensed'], size = self.fontsize)
|
fonts['NotoSans-SemiCondensed'], size = self.fontsize)
|
||||||
self.padding_x = 0.02
|
self.padding_x = 0.02
|
||||||
self.padding_y = 0.05
|
self.padding_y = 0.05
|
||||||
|
|
||||||
|
self.num_font = ImageFont.truetype(
|
||||||
|
fonts['NotoSans-SemiCondensed'], size = self.fontsize)
|
||||||
self.weekstart = 'Monday'
|
self.weekstart = 'Monday'
|
||||||
self.show_events = True
|
self.show_events = True
|
||||||
self.date_format = 'D MMM' # used for dates
|
self.date_format = 'D MMM' # used for dates
|
||||||
@ -42,9 +41,7 @@ class calendar:
|
|||||||
self.language = 'en' # Grab from settings file?
|
self.language = 'en' # Grab from settings file?
|
||||||
|
|
||||||
self.timezone = get_system_tz()
|
self.timezone = get_system_tz()
|
||||||
# urls of icalendars
|
|
||||||
self.ical_urls = config['ical_urls']
|
self.ical_urls = config['ical_urls']
|
||||||
# filepaths of icalendar files
|
|
||||||
self.ical_files = []
|
self.ical_files = []
|
||||||
print('{0} loaded'.format(self.name))
|
print('{0} loaded'.format(self.name))
|
||||||
|
|
||||||
@ -84,7 +81,7 @@ class calendar:
|
|||||||
logging.info('Image size: {0}'.format(im_size))
|
logging.info('Image size: {0}'.format(im_size))
|
||||||
|
|
||||||
# Create an image for black pixels and one for coloured pixels
|
# Create an image for black pixels and one for coloured pixels
|
||||||
im_black = Image.new('RGB', size = im_size, color = self.background_colour)
|
im_black = Image.new('RGB', size = im_size, color = 'white')
|
||||||
im_colour = Image.new('RGB', size = im_size, color = 'white')
|
im_colour = Image.new('RGB', size = im_size, color = 'white')
|
||||||
|
|
||||||
# Allocate space for month-names, weekdays etc.
|
# Allocate space for month-names, weekdays etc.
|
||||||
@ -105,11 +102,11 @@ class calendar:
|
|||||||
|
|
||||||
# Create grid and calculate icon sizes
|
# Create grid and calculate icon sizes
|
||||||
calendar_rows, calendar_cols = 6, 7
|
calendar_rows, calendar_cols = 6, 7
|
||||||
icon_width = self.width // calendar_cols
|
icon_width = im_width // calendar_cols
|
||||||
icon_height = calendar_height // calendar_rows
|
icon_height = calendar_height // calendar_rows
|
||||||
|
|
||||||
# Calculate spacings for calendar area
|
# Calculate spacings for calendar area
|
||||||
x_spacing_calendar = int((im_width % icon_width) / 2)
|
x_spacing_calendar = int((im_width % calendar_cols) / 2)
|
||||||
y_spacing_calendar = int((im_height % calendar_rows) / 2)
|
y_spacing_calendar = int((im_height % calendar_rows) / 2)
|
||||||
|
|
||||||
# Calculate positions for days of month
|
# Calculate positions for days of month
|
||||||
@ -122,7 +119,6 @@ class calendar:
|
|||||||
weekday_pos = [(grid_start_x + icon_width*_, month_name_height) for _ in
|
weekday_pos = [(grid_start_x + icon_width*_, month_name_height) for _ in
|
||||||
range(calendar_cols)]
|
range(calendar_cols)]
|
||||||
|
|
||||||
|
|
||||||
now = arrow.now(tz = self.timezone)
|
now = arrow.now(tz = self.timezone)
|
||||||
|
|
||||||
# Set weekstart of calendar to specified weekstart
|
# Set weekstart of calendar to specified weekstart
|
||||||
@ -169,28 +165,27 @@ class calendar:
|
|||||||
grid[i],
|
grid[i],
|
||||||
(icon_width,icon_height),
|
(icon_width,icon_height),
|
||||||
str(calendar_flat[i]),
|
str(calendar_flat[i]),
|
||||||
font = self.font,
|
font = self.num_font, fill_height = 0.5
|
||||||
)
|
)
|
||||||
|
|
||||||
# Draw a red/black circle with the current day of month in white
|
# Draw a red/black circle with the current day of month in white
|
||||||
icon = Image.new('RGBA', (icon_width, icon_height))
|
icon = Image.new('RGBA', (icon_width, icon_height))
|
||||||
current_day_pos = grid[calendar_flat.index(now.day)]
|
current_day_pos = grid[calendar_flat.index(now.day)]
|
||||||
x_circle,y_circle = int(icon_width/2), int(icon_height/2)
|
x_circle,y_circle = int(icon_width/2), int(icon_height/2)
|
||||||
radius = int(icon_width * 0.25)
|
radius = int(icon_width * 0.3)
|
||||||
text_width, text_height = self.font.getsize(str(now.day))
|
ImageDraw.Draw(icon).ellipse(
|
||||||
x_text = int((icon_width / 2) - (text_width / 2))
|
(x_circle-radius, y_circle-radius, x_circle+radius, y_circle+radius),
|
||||||
y_text = int((icon_height / 2) - (text_height / 1.7))
|
fill= 'black', outline=None)
|
||||||
ImageDraw.Draw(icon).ellipse((x_circle-radius, y_circle-radius,
|
write(icon, (0,0), (icon_width, icon_height), str(now.day),
|
||||||
x_circle+radius, y_circle+radius), fill= 'black', outline=None)
|
font=self.num_font, fill_height = 0.5, colour='white')
|
||||||
ImageDraw.Draw(icon).text((x_text, y_text), str(now.day), fill='white',
|
|
||||||
font=self.font)
|
|
||||||
im_colour.paste(icon, current_day_pos, icon)
|
im_colour.paste(icon, current_day_pos, icon)
|
||||||
|
|
||||||
|
|
||||||
# If events should be loaded and shown...
|
# If events should be loaded and shown...
|
||||||
if self.show_events == True:
|
if self.show_events == True:
|
||||||
|
|
||||||
# import the ical-parser
|
# import the ical-parser
|
||||||
from ical_parser import icalendar
|
from inkycal.modules.ical_parser import icalendar
|
||||||
|
|
||||||
# find out how many lines can fit at max in the event section
|
# find out how many lines can fit at max in the event section
|
||||||
line_spacing = 0
|
line_spacing = 0
|
||||||
@ -215,7 +210,7 @@ class calendar:
|
|||||||
# Filter events for full month (even past ones) for drawing event icons
|
# Filter events for full month (even past ones) for drawing event icons
|
||||||
month_events = parser.get_events(month_start, month_end)
|
month_events = parser.get_events(month_start, month_end)
|
||||||
parser.sort()
|
parser.sort()
|
||||||
# parser.show_events() # uncomment to show events
|
self.month_events = month_events
|
||||||
|
|
||||||
# find out on which days of this month events are taking place
|
# find out on which days of this month events are taking place
|
||||||
days_with_events = [int(events['begin'].format('D')) for events in
|
days_with_events = [int(events['begin'].format('D')) for events in
|
||||||
@ -223,12 +218,7 @@ class calendar:
|
|||||||
|
|
||||||
# remove duplicates (more than one event in a single day)
|
# remove duplicates (more than one event in a single day)
|
||||||
list(set(days_with_events)).sort()
|
list(set(days_with_events)).sort()
|
||||||
print('days with events:', days_with_events)
|
self._days_with_events = days_with_events
|
||||||
|
|
||||||
## # calculate sizes for event-markers
|
|
||||||
## square_size = int(icon_width * 0.6)
|
|
||||||
## center_x = int((icon_width - square_size) / 2)
|
|
||||||
## center_y = int((icon_height - square_size) / 2)
|
|
||||||
|
|
||||||
# Draw a border with specified parameters around days with events
|
# Draw a border with specified parameters around days with events
|
||||||
for days in days_with_events:
|
for days in days_with_events:
|
||||||
@ -236,23 +226,15 @@ class calendar:
|
|||||||
im_colour,
|
im_colour,
|
||||||
grid[calendar_flat.index(days)],
|
grid[calendar_flat.index(days)],
|
||||||
(icon_width, icon_height),
|
(icon_width, icon_height),
|
||||||
radius = 4,
|
radius = 6,
|
||||||
thickness= 1,
|
thickness= 1,
|
||||||
shrinkage = (0.4, 0.4)
|
shrinkage = (0.4, 0.4)
|
||||||
)
|
)
|
||||||
|
|
||||||
##
|
|
||||||
## draw_square((int(grid[calendar_flat.index(days)][0]+center_x),
|
|
||||||
## int(grid[calendar_flat.index(days)][1] + center_y )),
|
|
||||||
## 8, square_size , square_size, colour='black')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Filter upcoming events until 4 weeks in the future
|
# Filter upcoming events until 4 weeks in the future
|
||||||
parser.clear_events()
|
parser.clear_events()
|
||||||
upcoming_events = parser.get_events(now, now.shift(weeks=4))
|
upcoming_events = parser.get_events(now, now.shift(weeks=4))
|
||||||
parser.show_events()
|
self._upcoming_events = upcoming_events
|
||||||
|
|
||||||
# delete events which won't be able to fit (more events than lines)
|
# delete events which won't be able to fit (more events than lines)
|
||||||
upcoming_events[max_event_lines:]
|
upcoming_events[max_event_lines:]
|
||||||
@ -313,11 +295,6 @@ class calendar:
|
|||||||
(im_width, self.font.getsize(symbol)[1]), symbol,
|
(im_width, self.font.getsize(symbol)[1]), symbol,
|
||||||
font = self.font)
|
font = self.font)
|
||||||
|
|
||||||
|
|
||||||
###################################################################
|
|
||||||
## Exception handling
|
|
||||||
#################################################################
|
|
||||||
|
|
||||||
# Save image of black and colour channel in image-folder
|
# Save image of black and colour channel in image-folder
|
||||||
im_black.save(images+self.name+'.png')
|
im_black.save(images+self.name+'.png')
|
||||||
im_colour.save(images+self.name+'_colour.png')
|
im_colour.save(images+self.name+'_colour.png')
|
||||||
@ -325,3 +302,6 @@ class calendar:
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print('running {0} in standalone mode'.format(
|
print('running {0} in standalone mode'.format(
|
||||||
os.path.basename(__file__).split('.py')[0]))
|
os.path.basename(__file__).split('.py')[0]))
|
||||||
|
|
||||||
|
##a = calendar(size, config)
|
||||||
|
##a.generate_image()
|
||||||
|
179
inkycal/modules/inkycal_image.py
Normal file
179
inkycal/modules/inkycal_image.py
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Image module for inkycal Project
|
||||||
|
Copyright by aceisace
|
||||||
|
Development satge: Beta
|
||||||
|
"""
|
||||||
|
|
||||||
|
from os import path
|
||||||
|
from PIL import ImageOps
|
||||||
|
import requests
|
||||||
|
import numpy
|
||||||
|
|
||||||
|
"""----------------------------------------------------------------"""
|
||||||
|
#path = 'https://github.com/aceisace/Inky-Calendar/raw/master/Gallery/Inky-Calendar-logo.png'
|
||||||
|
#path ='/home/pi/Inky-Calendar/images/canvas.png'
|
||||||
|
path = inkycal_image_path
|
||||||
|
path_body = inkycal_image_path_body
|
||||||
|
mode = 'auto' # 'horizontal' # 'vertical' # 'auto'
|
||||||
|
upside_down = False # Flip image by 180 deg (upside-down)
|
||||||
|
alignment = 'center' # top_center, top_left, center_left, bottom_right etc.
|
||||||
|
colours = 'bwr' # bwr # bwy # bw
|
||||||
|
render = True # show image on E-Paper?
|
||||||
|
"""----------------------------------------------------------------"""
|
||||||
|
|
||||||
|
# First determine dimensions
|
||||||
|
if mode == 'horizontal':
|
||||||
|
display_width, display_height == display_height, display_width
|
||||||
|
|
||||||
|
if mode == 'vertical':
|
||||||
|
raise NotImplementedError('Vertical mode is not currenctly supported')
|
||||||
|
|
||||||
|
# .. Then substitute possibly parameterized path
|
||||||
|
# TODO Get (assigned) panel dimensions instead of display dimensions
|
||||||
|
path = path.replace('{model}', model).replace('{width}',str(display_width)).replace('{height}',str(display_height))
|
||||||
|
print(path)
|
||||||
|
|
||||||
|
"""Try to open the image if it exists and is an image file"""
|
||||||
|
try:
|
||||||
|
if 'http' in path:
|
||||||
|
if path_body is None:
|
||||||
|
# Plain GET
|
||||||
|
im = Image.open(requests.get(path, stream=True).raw)
|
||||||
|
else:
|
||||||
|
# POST request, passing path_body in the body
|
||||||
|
im = Image.open(requests.post(path, json=path_body, stream=True).raw)
|
||||||
|
else:
|
||||||
|
im = Image.open(path)
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('Your file could not be found. Please check the path to your file.')
|
||||||
|
raise
|
||||||
|
except OSError:
|
||||||
|
print('Please check if the path points to an image file.')
|
||||||
|
raise
|
||||||
|
|
||||||
|
"""Turn image upside-down if specified"""
|
||||||
|
if upside_down == True:
|
||||||
|
im.rotate(180, expand = True)
|
||||||
|
|
||||||
|
if mode == 'auto':
|
||||||
|
if (im.width > im.height) and (display_width < display_height):
|
||||||
|
print('display vertical, image horizontal -> flipping image')
|
||||||
|
im = im.rotate(90, expand=True)
|
||||||
|
if (im.width < im.height) and (display_width > display_height):
|
||||||
|
print('display horizontal, image vertical -> flipping image')
|
||||||
|
im = im.rotate(90, expand=True)
|
||||||
|
|
||||||
|
def fit_width(image, width):
|
||||||
|
"""Resize an image to desired width"""
|
||||||
|
print('resizing width from', image.width, 'to', end = ' ')
|
||||||
|
wpercent = (display_width/float(image.width))
|
||||||
|
hsize = int((float(image.height)*float(wpercent)))
|
||||||
|
img = image.resize((width, hsize), Image.ANTIALIAS)
|
||||||
|
print(img.width)
|
||||||
|
return img
|
||||||
|
|
||||||
|
def fit_height(image, height):
|
||||||
|
"""Resize an image to desired height"""
|
||||||
|
print('resizing height from', image.height, 'to', end = ' ')
|
||||||
|
hpercent = (height / float(image.height))
|
||||||
|
wsize = int(float(image.width) * float(hpercent))
|
||||||
|
img = image.resize((wsize, height), Image.ANTIALIAS)
|
||||||
|
print(img.height)
|
||||||
|
return img
|
||||||
|
|
||||||
|
if im.width > display_width:
|
||||||
|
im = fit_width(im, display_width)
|
||||||
|
if im.height > display_height:
|
||||||
|
im = fit_height(im, display_height)
|
||||||
|
|
||||||
|
if alignment == 'center':
|
||||||
|
x,y = int((display_width-im.width)/2), int((display_height-im.height)/2)
|
||||||
|
elif alignment == 'center_right':
|
||||||
|
x, y = display_width-im.width, int((display_height-im.height)/2)
|
||||||
|
elif alignment == 'center_left':
|
||||||
|
x, y = 0, int((display_height-im.height)/2)
|
||||||
|
|
||||||
|
elif alignment == 'top_center':
|
||||||
|
x, y = int((display_width-im.width)/2), 0
|
||||||
|
elif alignment == 'top_right':
|
||||||
|
x, y = display_width-im.width, 0
|
||||||
|
elif alignment == 'top_left':
|
||||||
|
x, y = 0, 0
|
||||||
|
|
||||||
|
elif alignment == 'bottom_center':
|
||||||
|
x, y = int((display_width-im.width)/2), display_height-im.height
|
||||||
|
elif alignment == 'bottom_right':
|
||||||
|
x, y = display_width-im.width, display_height-im.height
|
||||||
|
elif alignment == 'bottom_left':
|
||||||
|
x, y = display_width-im.width, display_height-im.height
|
||||||
|
|
||||||
|
if len(im.getbands()) == 4:
|
||||||
|
print('removing transparency')
|
||||||
|
bg = Image.new('RGBA', (im.width, im.height), 'white')
|
||||||
|
im = Image.alpha_composite(bg, im)
|
||||||
|
|
||||||
|
image.paste(im, (x,y))
|
||||||
|
im = image
|
||||||
|
|
||||||
|
if colours == 'bw':
|
||||||
|
"""For black-white images, use monochrome dithering"""
|
||||||
|
black = im.convert('1', dither=True)
|
||||||
|
elif colours == 'bwr':
|
||||||
|
"""For black-white-red images, create corresponding palette"""
|
||||||
|
pal = [255,255,255, 0,0,0, 255,0,0, 255,255,255]
|
||||||
|
elif colours == 'bwy':
|
||||||
|
"""For black-white-yellow images, create corresponding palette"""
|
||||||
|
pal = [255,255,255, 0,0,0, 255,255,0, 255,255,255]
|
||||||
|
|
||||||
|
|
||||||
|
"""Map each pixel of the opened image to the Palette"""
|
||||||
|
if colours != 'bw':
|
||||||
|
palette_im = Image.new('P', (3,1))
|
||||||
|
palette_im.putpalette(pal * 64)
|
||||||
|
quantized_im = im.quantize(palette=palette_im)
|
||||||
|
quantized_im.convert('RGB')
|
||||||
|
|
||||||
|
"""Create buffer for coloured pixels"""
|
||||||
|
buffer1 = numpy.array(quantized_im.convert('RGB'))
|
||||||
|
r1,g1,b1 = buffer1[:, :, 0], buffer1[:, :, 1], buffer1[:, :, 2]
|
||||||
|
|
||||||
|
"""Create buffer for black pixels"""
|
||||||
|
buffer2 = numpy.array(quantized_im.convert('RGB'))
|
||||||
|
r2,g2,b2 = buffer2[:, :, 0], buffer2[:, :, 1], buffer2[:, :, 2]
|
||||||
|
|
||||||
|
if colours == 'bwr':
|
||||||
|
"""Create image for only red pixels"""
|
||||||
|
buffer2[numpy.logical_and(r2 == 0, b2 == 0)] = [255,255,255] # black->white
|
||||||
|
buffer2[numpy.logical_and(r2 == 255, b2 == 0)] = [0,0,0] #red->black
|
||||||
|
colour = Image.fromarray(buffer2)
|
||||||
|
"""Create image for only black pixels"""
|
||||||
|
buffer1[numpy.logical_and(r1 == 255, b1 == 0)] = [255,255,255]
|
||||||
|
black = Image.fromarray(buffer1)
|
||||||
|
|
||||||
|
if colours == 'bwy':
|
||||||
|
"""Create image for only yellow pixels"""
|
||||||
|
buffer2[numpy.logical_and(r2 == 0, b2 == 0)] = [255,255,255] # black->white
|
||||||
|
buffer2[numpy.logical_and(g2 == 255, b2 == 0)] = [0,0,0] #yellow -> black
|
||||||
|
colour = Image.fromarray(buffer2)
|
||||||
|
"""Create image for only black pixels"""
|
||||||
|
buffer1[numpy.logical_and(g1 == 255, b1 == 0)] = [255,255,255]
|
||||||
|
black = Image.fromarray(buffer1)
|
||||||
|
##
|
||||||
|
##if render == True:
|
||||||
|
## epaper = driver.EPD()
|
||||||
|
## print('Initialising E-Paper...', end = '')
|
||||||
|
## epaper.init()
|
||||||
|
## print('Done')
|
||||||
|
##
|
||||||
|
## print('Sending image data and refreshing display...', end='')
|
||||||
|
## if three_colour_support == True:
|
||||||
|
## epaper.display(epaper.getbuffer(black), epaper.getbuffer(colour))
|
||||||
|
## else:
|
||||||
|
## epaper.display(epaper.getbuffer(black))
|
||||||
|
## print('Done')
|
||||||
|
##
|
||||||
|
## print('Sending E-Paper to deep sleep...', end = '')
|
||||||
|
## epaper.sleep()
|
||||||
|
print('Done')
|
@ -18,7 +18,8 @@ except ImportError:
|
|||||||
# Debug Data (not for production use!)
|
# Debug Data (not for production use!)
|
||||||
size = (384, 160)
|
size = (384, 160)
|
||||||
config = {'rss_urls': ['http://feeds.bbci.co.uk/news/world/rss.xml#']}
|
config = {'rss_urls': ['http://feeds.bbci.co.uk/news/world/rss.xml#']}
|
||||||
|
#config = {'rss_urls': ['http://www.tagesschau.de/xml/atom/']}
|
||||||
|
#https://www.tagesschau.de/xml/rss2
|
||||||
|
|
||||||
class rss:
|
class rss:
|
||||||
"""RSS class
|
"""RSS class
|
||||||
@ -34,14 +35,15 @@ class rss:
|
|||||||
self.name = os.path.basename(__file__).split('.py')[0]
|
self.name = os.path.basename(__file__).split('.py')[0]
|
||||||
self.config = section_config
|
self.config = section_config
|
||||||
self.width, self.height = section_size
|
self.width, self.height = section_size
|
||||||
|
|
||||||
self.background_colour = 'white'
|
|
||||||
self.font_colour = 'black'
|
|
||||||
self.fontsize = 12
|
self.fontsize = 12
|
||||||
self.font = ImageFont.truetype(fonts['NotoSans-SemiCondensed'],
|
|
||||||
size = self.fontsize)
|
|
||||||
self.padding_x = 0.02
|
self.padding_x = 0.02
|
||||||
self.padding_y = 0.05
|
self.padding_y = 0.05
|
||||||
|
self.font = ImageFont.truetype(fonts['NotoSans-SemiCondensed'],
|
||||||
|
size = self.fontsize)
|
||||||
|
|
||||||
|
# module specifc config
|
||||||
|
self.shuffle_feeds = True
|
||||||
|
|
||||||
print('{0} loaded'.format(self.name))
|
print('{0} loaded'.format(self.name))
|
||||||
|
|
||||||
def set(self, **kwargs):
|
def set(self, **kwargs):
|
||||||
@ -76,15 +78,14 @@ class rss:
|
|||||||
logging.info('image size: {} x {} px'.format(im_width, im_height))
|
logging.info('image size: {} x {} px'.format(im_width, im_height))
|
||||||
|
|
||||||
# Create an image for black pixels and one for coloured pixels
|
# Create an image for black pixels and one for coloured pixels
|
||||||
im_black = Image.new('RGB', size = im_size, color = self.background_colour)
|
im_black = Image.new('RGB', size = im_size, color = 'white')
|
||||||
im_colour = Image.new('RGB', size = im_size, color = 'white')
|
im_colour = Image.new('RGB', size = im_size, color = 'white')
|
||||||
|
|
||||||
# Check if internet is available
|
# Check if internet is available
|
||||||
if internet_available() == True:
|
if internet_available() == True:
|
||||||
logging.info('Connection test passed')
|
logging.info('Connection test passed')
|
||||||
else:
|
else:
|
||||||
logging.error('Network could not be reached :/')
|
raise Exception('Network could not be reached :/')
|
||||||
raise Exception('Network could not be reached :(')
|
|
||||||
|
|
||||||
|
|
||||||
# Set some parameters for formatting rss feeds
|
# Set some parameters for formatting rss feeds
|
||||||
@ -101,46 +102,48 @@ class rss:
|
|||||||
(0, spacing_top + _ * line_height ) for _ in range(max_lines)]
|
(0, spacing_top + _ * line_height ) for _ in range(max_lines)]
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Create list containing all rss-feeds from all rss-feed urls
|
|
||||||
parsed_feeds = []
|
|
||||||
for feeds in self.config['rss_urls']:
|
|
||||||
text = feedparser.parse(feeds)
|
|
||||||
for posts in text.entries:
|
|
||||||
parsed_feeds.append('•{0}: {1}'.format(posts.title, posts.summary))
|
|
||||||
# print(parsed_feeds)
|
|
||||||
|
|
||||||
# Shuffle the list to prevent showing the same content
|
# Create list containing all rss-feeds from all rss-feed urls
|
||||||
|
parsed_feeds = []
|
||||||
|
for feeds in self.config['rss_urls']:
|
||||||
|
text = feedparser.parse(feeds)
|
||||||
|
for posts in text.entries:
|
||||||
|
parsed_feeds.append('•{0}: {1}'.format(posts.title, posts.summary))
|
||||||
|
|
||||||
|
self._parsed_feeds = parsed_feeds
|
||||||
|
|
||||||
|
# Shuffle the list to prevent showing the same content
|
||||||
|
if self.shuffle_feeds == True:
|
||||||
shuffle(parsed_feeds)
|
shuffle(parsed_feeds)
|
||||||
|
|
||||||
# Trim down the list to the max number of lines
|
# Trim down the list to the max number of lines
|
||||||
del parsed_feeds[max_lines:]
|
del parsed_feeds[max_lines:]
|
||||||
|
|
||||||
|
# Wrap long text from feeds (line-breaking)
|
||||||
|
flatten = lambda z: [x for y in z for x in y]
|
||||||
|
filtered_feeds, counter = [], 0
|
||||||
|
|
||||||
# Wrap long text from feeds (line-breaking)
|
for posts in parsed_feeds:
|
||||||
flatten = lambda z: [x for y in z for x in y]
|
wrapped = text_wrap(posts, font = self.font, max_width = line_width)
|
||||||
filtered_feeds, counter = [], 0
|
counter += len(wrapped)
|
||||||
|
if counter < max_lines:
|
||||||
for posts in parsed_feeds:
|
filtered_feeds.append(wrapped)
|
||||||
wrapped = text_wrap(posts, font = self.font, max_width = line_width)
|
filtered_feeds = flatten(filtered_feeds)
|
||||||
counter += len(filtered_feeds) + len(wrapped)
|
self._filtered_feeds = filtered_feeds
|
||||||
if counter < max_lines:
|
|
||||||
filtered_feeds.append(wrapped)
|
|
||||||
filtered_feeds = flatten(filtered_feeds)
|
|
||||||
|
|
||||||
|
# Check if feeds could be parsed and can be displayed
|
||||||
|
if len(filtered_feeds) == 0 and len(parsed_feeds) > 0:
|
||||||
|
print('Feeds could be parsed, but the text is too long to be displayed:/')
|
||||||
|
elif len(filtered_feeds) == 0 and len(parsed_feeds) == 0:
|
||||||
|
print('No feeds could be parsed :/')
|
||||||
|
else:
|
||||||
# Write rss-feeds on image
|
# Write rss-feeds on image
|
||||||
"""Write the correctly formatted text on the display"""
|
|
||||||
for _ in range(len(filtered_feeds)):
|
for _ in range(len(filtered_feeds)):
|
||||||
write(im_black, line_positions[_], (line_width, line_height),
|
write(im_black, line_positions[_], (line_width, line_height),
|
||||||
filtered_feeds[_], font = self.font, alignment= 'left')
|
filtered_feeds[_], font = self.font, alignment= 'left')
|
||||||
|
|
||||||
# Cleanup
|
# Cleanup
|
||||||
del filtered_feeds, parsed_feeds, wrapped, counter, text
|
del filtered_feeds, parsed_feeds, wrapped, counter, text
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print('Error in {0}'.format(self.name))
|
|
||||||
print('Reason: ',e)
|
|
||||||
write(im_black, (0,0), (im_width, im_height), str(e), font = self.font)
|
|
||||||
|
|
||||||
# Save image of black and colour channel in image-folder
|
# Save image of black and colour channel in image-folder
|
||||||
im_black.save(images+self.name+'.png', 'PNG')
|
im_black.save(images+self.name+'.png', 'PNG')
|
||||||
@ -149,3 +152,6 @@ class rss:
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print('running {0} in standalone mode'.format(
|
print('running {0} in standalone mode'.format(
|
||||||
os.path.basename(__file__).split('.py')[0]))
|
os.path.basename(__file__).split('.py')[0]))
|
||||||
|
|
||||||
|
##a = rss(size, config)
|
||||||
|
##a.generate_image()
|
||||||
|
Loading…
Reference in New Issue
Block a user