Improved formatting

This commit is contained in:
aceisace
2022-04-02 01:30:17 +02:00
parent 9bf4385b6b
commit 5b032d6231
42 changed files with 3644 additions and 3661 deletions

View File

@@ -1,4 +1,4 @@
# Display class (for dirving E-Paper displays)
# Display class (for driving E-Paper displays)
from inkycal.display import Display
# Default modules

View File

@@ -25,7 +25,7 @@ images = top_level + '/images/'
# Get available fonts within fonts folder
fonts = {}
for path,dirs,files in os.walk(fonts_location):
for path, dirs, files in os.walk(fonts_location):
for filename in files:
if filename.endswith('.otf'):
name = filename.split('.otf')[0]
@@ -35,7 +35,8 @@ for path,dirs,files in os.walk(fonts_location):
name = filename.split('.ttf')[0]
fonts[name] = os.path.join(path, filename)
available_fonts = [key for key,values in fonts.items()]
available_fonts = [key for key, values in fonts.items()]
def get_fonts():
"""Print all available fonts by name.
@@ -146,7 +147,7 @@ def write(image, xy, box_size, text, font=None, **kwargs):
colour = kwargs['colour'] if 'colour' in kwargs else 'black'
rotation = kwargs['rotation'] if 'rotation' in kwargs else None
x,y = xy
x, y = xy
box_width, box_height = box_size
# Increase fontsize to fit specified height and width of text box
@@ -162,12 +163,11 @@ def write(image, xy, box_size, text, font=None, **kwargs):
text_width, text_height = font.getsize(text)[0], font.getsize('hg')[1]
# Truncate text if text is too long so it can fit inside the box
if (text_width, text_height) > (box_width, box_height):
logs.debug(('truncating {}'.format(text)))
while (text_width, text_height) > (box_width, box_height):
text=text[0:-1]
text = text[0:-1]
text_width, text_height = font.getsize(text)[0], font.getsize('hg')[1]
logs.debug((text))
@@ -189,17 +189,17 @@ def write(image, xy, box_size, text, font=None, **kwargs):
# Uncomment following two lines, comment out above two lines to show
# red text-box with white text (debugging purposes)
#space = Image.new('RGBA', (box_width, box_height), color= 'red')
#ImageDraw.Draw(space).text((x, y), text, fill='white', font=font)
# space = Image.new('RGBA', (box_width, box_height), color= 'red')
# ImageDraw.Draw(space).text((x, y), text, fill='white', font=font)
if rotation != None:
space.rotate(rotation, expand = True)
space.rotate(rotation, expand=True)
# Update only region with text (add text with transparent background)
image.paste(space, xy, space)
def text_wrap(text, font=None, max_width = None):
def text_wrap(text, font=None, max_width=None):
"""Splits a very long text into smaller parts
Splits a long text to smaller lines which can fit in a line with max_width.
@@ -248,13 +248,13 @@ def internet_available():
"""
try:
urlopen('https://google.com',timeout=5)
urlopen('https://google.com', timeout=5)
return True
except URLError as err:
except:
return False
def draw_border(image, xy, size, radius=5, thickness=1, shrinkage=(0.1,0.1)):
def draw_border(image, xy, size, radius=5, thickness=1, shrinkage=(0.1, 0.1)):
"""Draws a border at given coordinates.
Args:
@@ -276,39 +276,39 @@ def draw_border(image, xy, size, radius=5, thickness=1, shrinkage=(0.1,0.1)):
border by 20%
"""
colour='black'
colour = 'black'
# size from function paramter
width, height = int(size[0]*(1-shrinkage[0])), int(size[1]*(1-shrinkage[1]))
width, height = int(size[0] * (1 - shrinkage[0])), int(size[1] * (1 - shrinkage[1]))
# shift cursor to move rectangle to center
offset_x, offset_y = int((size[0] - width)/2), int((size[1]- height)/2)
offset_x, offset_y = int((size[0] - width) / 2), int((size[1] - height) / 2)
x, y, diameter = xy[0]+offset_x, xy[1]+offset_y, radius*2
x, y, diameter = xy[0] + offset_x, xy[1] + offset_y, radius * 2
# lenght of rectangle size
a,b = (width - diameter), (height-diameter)
a, b = (width - diameter), (height - diameter)
# Set coordinates for staright lines
p1, p2 = (x+radius, y), (x+radius+a, y)
p3, p4 = (x+width, y+radius), (x+width, y+radius+b)
p5, p6 = (p2[0], y+height), (p1[0], y+height)
p7, p8 = (x, p4[1]), (x,p3[1])
p1, p2 = (x + radius, y), (x + radius + a, y)
p3, p4 = (x + width, y + radius), (x + width, y + radius + b)
p5, p6 = (p2[0], y + height), (p1[0], y + height)
p7, p8 = (x, p4[1]), (x, p3[1])
if radius != 0:
# Set coordinates for arcs
c1, c2 = (x,y), (x+diameter, y+diameter)
c3, c4 = ((x+width)-diameter, y), (x+width, y+diameter)
c5, c6 = ((x+width)-diameter, (y+height)-diameter), (x+width, y+height)
c7, c8 = (x, (y+height)-diameter), (x+diameter, y+height)
c1, c2 = (x, y), (x + diameter, y + diameter)
c3, c4 = ((x + width) - diameter, y), (x + width, y + diameter)
c5, c6 = ((x + width) - diameter, (y + height) - diameter), (x + width, y + height)
c7, c8 = (x, (y + height) - diameter), (x + diameter, y + height)
# Draw lines and arcs, creating a square with round corners
draw = ImageDraw.Draw(image)
draw.line( (p1, p2) , fill=colour, width = thickness)
draw.line( (p3, p4) , fill=colour, width = thickness)
draw.line( (p5, p6) , fill=colour, width = thickness)
draw.line( (p7, p8) , fill=colour, width = thickness)
draw.line((p1, p2), fill=colour, width=thickness)
draw.line((p3, p4), fill=colour, width=thickness)
draw.line((p5, p6), fill=colour, width=thickness)
draw.line((p7, p8), fill=colour, width=thickness)
if radius != 0:
draw.arc( (c1, c2) , 180, 270, fill=colour, width=thickness)
draw.arc( (c3, c4) , 270, 360, fill=colour, width=thickness)
draw.arc( (c5, c6) , 0, 90, fill=colour, width=thickness)
draw.arc( (c7, c8) , 90, 180, fill=colour, width=thickness)
draw.arc((c1, c2), 180, 270, fill=colour, width=thickness)
draw.arc((c3, c4), 270, 360, fill=colour, width=thickness)
draw.arc((c5, c6), 0, 90, fill=colour, width=thickness)
draw.arc((c7, c8), 90, 180, fill=colour, width=thickness)

View File

@@ -1,5 +1,5 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
9.7" driver class
Copyright by aceisace
@@ -12,7 +12,8 @@ from PIL import Image
EPD_WIDTH = 1200
EPD_HEIGHT = 825
driver_dir = top_level+'/inkycal/display/drivers/9_in_7_drivers/'
driver_dir = top_level + '/inkycal/display/drivers/9_in_7_drivers/'
class EPD:
@@ -40,11 +41,10 @@ class EPD:
def getbuffer(self, image):
"""ad-hoc"""
image = image.rotate(90, expand=True)
image.convert('RGB').save(images+'canvas.bmp', 'BMP')
command = 'sudo {}IT8951/IT8951 0 0 {}'.format(driver_dir, images+'canvas.bmp')
#print(command)
image.convert('RGB').save(images + 'canvas.bmp', 'BMP')
command = 'sudo {}IT8951/IT8951 0 0 {}'.format(driver_dir, images + 'canvas.bmp')
# print(command)
return command
def sleep(self):
pass

View File

@@ -37,10 +37,11 @@ import RPi.GPIO as GPIO
EPD_WIDTH = 400
EPD_HEIGHT = 300
GRAY1 = 0xff #white
GRAY1 = 0xff # white
GRAY2 = 0xC0
GRAY3 = 0x80 #gray
GRAY4 = 0x00 #Blackest
GRAY3 = 0x80 # gray
GRAY4 = 0x00 # Blackest
class EPD:
def __init__(self):
@@ -50,10 +51,10 @@ class EPD:
self.cs_pin = epdconfig.CS_PIN
self.width = EPD_WIDTH
self.height = EPD_HEIGHT
self.GRAY1 = GRAY1 #white
self.GRAY1 = GRAY1 # white
self.GRAY2 = GRAY2
self.GRAY3 = GRAY3 #gray
self.GRAY4 = GRAY4 #Blackest
self.GRAY3 = GRAY3 # gray
self.GRAY4 = GRAY4 # Blackest
lut_vcom0 = [
0x00, 0x17, 0x00, 0x00, 0x00, 0x02,
@@ -101,56 +102,56 @@ class EPD:
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
#******************************gray*********************************/
#0~3 gray
EPD_4IN2_4Gray_lut_vcom =[
0x00 ,0x0A ,0x00 ,0x00 ,0x00 ,0x01,
0x60 ,0x14 ,0x14 ,0x00 ,0x00 ,0x01,
0x00 ,0x14 ,0x00 ,0x00 ,0x00 ,0x01,
0x00 ,0x13 ,0x0A ,0x01 ,0x00 ,0x01,
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00
# ******************************gray*********************************/
# 0~3 gray
EPD_4IN2_4Gray_lut_vcom = [
0x00, 0x0A, 0x00, 0x00, 0x00, 0x01,
0x60, 0x14, 0x14, 0x00, 0x00, 0x01,
0x00, 0x14, 0x00, 0x00, 0x00, 0x01,
0x00, 0x13, 0x0A, 0x01, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
]
#R21
EPD_4IN2_4Gray_lut_ww =[
0x40 ,0x0A ,0x00 ,0x00 ,0x00 ,0x01,
0x90 ,0x14 ,0x14 ,0x00 ,0x00 ,0x01,
0x10 ,0x14 ,0x0A ,0x00 ,0x00 ,0x01,
0xA0 ,0x13 ,0x01 ,0x00 ,0x00 ,0x01,
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
# R21
EPD_4IN2_4Gray_lut_ww = [
0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,
0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
0x10, 0x14, 0x0A, 0x00, 0x00, 0x01,
0xA0, 0x13, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
#R22H r
EPD_4IN2_4Gray_lut_bw =[
0x40 ,0x0A ,0x00 ,0x00 ,0x00 ,0x01,
0x90 ,0x14 ,0x14 ,0x00 ,0x00 ,0x01,
0x00 ,0x14 ,0x0A ,0x00 ,0x00 ,0x01,
0x99 ,0x0C ,0x01 ,0x03 ,0x04 ,0x01,
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
# R22H r
EPD_4IN2_4Gray_lut_bw = [
0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,
0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
0x00, 0x14, 0x0A, 0x00, 0x00, 0x01,
0x99, 0x0C, 0x01, 0x03, 0x04, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
#R23H w
EPD_4IN2_4Gray_lut_wb =[
0x40 ,0x0A ,0x00 ,0x00 ,0x00 ,0x01,
0x90 ,0x14 ,0x14 ,0x00 ,0x00 ,0x01,
0x00 ,0x14 ,0x0A ,0x00 ,0x00 ,0x01,
0x99 ,0x0B ,0x04 ,0x04 ,0x01 ,0x01,
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
# R23H w
EPD_4IN2_4Gray_lut_wb = [
0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,
0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
0x00, 0x14, 0x0A, 0x00, 0x00, 0x01,
0x99, 0x0B, 0x04, 0x04, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
#R24H b
EPD_4IN2_4Gray_lut_bb =[
0x80 ,0x0A ,0x00 ,0x00 ,0x00 ,0x01,
0x90 ,0x14 ,0x14 ,0x00 ,0x00 ,0x01,
0x20 ,0x14 ,0x0A ,0x00 ,0x00 ,0x01,
0x50 ,0x13 ,0x01 ,0x00 ,0x00 ,0x01,
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
# R24H b
EPD_4IN2_4Gray_lut_bb = [
0x80, 0x0A, 0x00, 0x00, 0x00, 0x01,
0x90, 0x14, 0x14, 0x00, 0x00, 0x01,
0x20, 0x14, 0x0A, 0x00, 0x00, 0x01,
0x50, 0x13, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
# Hardware reset
@@ -176,7 +177,7 @@ class EPD:
def ReadBusy(self):
self.send_command(0x71)
while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
while (epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
self.send_command(0x71)
epdconfig.delay_ms(100)
@@ -202,31 +203,30 @@ class EPD:
self.send_data(self.lut_wb[count])
def Gray_SetLut(self):
self.send_command(0x20) #vcom
self.send_command(0x20) # vcom
for count in range(0, 42):
self.send_data(self.EPD_4IN2_4Gray_lut_vcom[count])
self.send_command(0x21) #red not use
self.send_command(0x21) # red not use
for count in range(0, 42):
self.send_data(self.EPD_4IN2_4Gray_lut_ww[count])
self.send_command(0x22) #bw r
self.send_command(0x22) # bw r
for count in range(0, 42):
self.send_data(self.EPD_4IN2_4Gray_lut_bw[count])
self.send_command(0x23) #wb w
self.send_command(0x23) # wb w
for count in range(0, 42):
self.send_data(self.EPD_4IN2_4Gray_lut_wb[count])
self.send_command(0x24) #bb b
self.send_command(0x24) # bb b
for count in range(0, 42):
self.send_data(self.EPD_4IN2_4Gray_lut_bb[count])
self.send_command(0x25) #vcom
self.send_command(0x25) # vcom
for count in range(0, 42):
self.send_data(self.EPD_4IN2_4Gray_lut_ww[count])
def init(self):
if (epdconfig.module_init() != 0):
return -1
@@ -264,7 +264,8 @@ class EPD:
self.send_data(0x28)
self.send_command(0X50) # VCOM AND DATA INTERVAL SETTING
self.send_data(0x97) # 97white border 77black border VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7
self.send_data(
0x97) # 97white border 77black border VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7
self.set_lut()
# EPD hardware init end
@@ -276,61 +277,61 @@ class EPD:
# EPD hardware init start
self.reset()
self.send_command(0x01) #POWER SETTING
self.send_data (0x03)
self.send_data (0x00) #VGH=20V,VGL=-20V
self.send_data (0x2b) #VDH=15V
self.send_data (0x2b) #VDL=-15V
self.send_data (0x13)
self.send_command(0x01) # POWER SETTING
self.send_data(0x03)
self.send_data(0x00) # VGH=20V,VGL=-20V
self.send_data(0x2b) # VDH=15V
self.send_data(0x2b) # VDL=-15V
self.send_data(0x13)
self.send_command(0x06) #booster soft start
self.send_data (0x17) #A
self.send_data (0x17) #B
self.send_data (0x17) #C
self.send_command(0x06) # booster soft start
self.send_data(0x17) # A
self.send_data(0x17) # B
self.send_data(0x17) # C
self.send_command(0x04)
self.ReadBusy()
self.send_command(0x00) #panel setting
self.send_data(0x3f) #KW-3f KWR-2F BWROTP 0f BWOTP 1f
self.send_command(0x00) # panel setting
self.send_data(0x3f) # KW-3f KWR-2F BWROTP 0f BWOTP 1f
self.send_command(0x30) #PLL setting
self.send_data (0x3c) #100hz
self.send_command(0x30) # PLL setting
self.send_data(0x3c) # 100hz
self.send_command(0x61) #resolution setting
self.send_data (0x01) #400
self.send_data (0x90)
self.send_data (0x01) #300
self.send_data (0x2c)
self.send_command(0x61) # resolution setting
self.send_data(0x01) # 400
self.send_data(0x90)
self.send_data(0x01) # 300
self.send_data(0x2c)
self.send_command(0x82) #vcom_DC setting
self.send_data (0x12)
self.send_command(0x82) # vcom_DC setting
self.send_data(0x12)
self.send_command(0X50) #VCOM AND DATA INTERVAL SETTING
self.send_command(0X50) # VCOM AND DATA INTERVAL SETTING
self.send_data(0x97)
def getbuffer(self, image):
# logging.debug("bufsiz = ",int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width / 8) * self.height)
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
# logging.debug("imwidth = %d, imheight = %d",imwidth,imheight)
if(imwidth == self.width and imheight == self.height):
if (imwidth == self.width and imheight == self.height):
logging.debug("Horizontal")
for y in range(imheight):
for x in range(imwidth):
# Set the bits for the column of pixels at the current position.
if pixels[x, y] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
elif(imwidth == self.height and imheight == self.width):
elif (imwidth == self.height and imheight == self.width):
logging.debug("Vertical")
for y in range(imheight):
for x in range(imwidth):
newx = y
newy = self.height - x - 1
if pixels[x, y] == 0:
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))
buf[int((newx + newy * self.width) / 8)] &= ~(0x80 >> (y % 8))
return buf
def getbuffer_4Gray(self, image):
@@ -339,34 +340,38 @@ class EPD:
image_monocolor = image.convert('L')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
i=0
i = 0
# logging.debug("imwidth = %d, imheight = %d",imwidth,imheight)
if(imwidth == self.width and imheight == self.height):
if (imwidth == self.width and imheight == self.height):
logging.debug("Vertical")
for y in range(imheight):
for x in range(imwidth):
# Set the bits for the column of pixels at the current position.
if(pixels[x, y] == 0xC0):
if (pixels[x, y] == 0xC0):
pixels[x, y] = 0x80
elif (pixels[x, y] == 0x80):
pixels[x, y] = 0x40
i= i+1
if(i%4 == 0):
buf[int((x + (y * self.width))/4)] = ((pixels[x-3, y]&0xc0) | (pixels[x-2, y]&0xc0)>>2 | (pixels[x-1, y]&0xc0)>>4 | (pixels[x, y]&0xc0)>>6)
i = i + 1
if (i % 4 == 0):
buf[int((x + (y * self.width)) / 4)] = (
(pixels[x - 3, y] & 0xc0) | (pixels[x - 2, y] & 0xc0) >> 2 | (
pixels[x - 1, y] & 0xc0) >> 4 | (pixels[x, y] & 0xc0) >> 6)
elif(imwidth == self.height and imheight == self.width):
elif (imwidth == self.height and imheight == self.width):
logging.debug("Horizontal")
for x in range(imwidth):
for y in range(imheight):
newx = y
newy = x
if(pixels[x, y] == 0xC0):
if (pixels[x, y] == 0xC0):
pixels[x, y] = 0x80
elif (pixels[x, y] == 0x80):
pixels[x, y] = 0x40
i= i+1
if(i%4 == 0):
buf[int((newx + (newy * self.width))/4)] = ((pixels[x, y-3]&0xc0) | (pixels[x, y-2]&0xc0)>>2 | (pixels[x, y-1]&0xc0)>>4 | (pixels[x, y]&0xc0)>>6)
i = i + 1
if (i % 4 == 0):
buf[int((newx + (newy * self.width)) / 4)] = (
(pixels[x, y - 3] & 0xc0) | (pixels[x, y - 2] & 0xc0) >> 2 | (
pixels[x, y - 1] & 0xc0) >> 4 | (pixels[x, y] & 0xc0) >> 6)
return buf
@@ -385,65 +390,65 @@ class EPD:
def display_4Gray(self, image):
self.send_command(0x10)
for i in range(0, EPD_WIDTH * EPD_HEIGHT / 8): # EPD_WIDTH * EPD_HEIGHT / 4
temp3=0
temp3 = 0
for j in range(0, 2):
temp1 = image[i*2+j]
temp1 = image[i * 2 + j]
for k in range(0, 2):
temp2 = temp1&0xC0
if(temp2 == 0xC0):
temp3 |= 0x01#white
elif(temp2 == 0x00):
temp3 |= 0x00 #black
elif(temp2 == 0x80):
temp3 |= 0x01 #gray1
else: #0x40
temp3 |= 0x00 #gray2
temp2 = temp1 & 0xC0
if (temp2 == 0xC0):
temp3 |= 0x01 # white
elif (temp2 == 0x00):
temp3 |= 0x00 # black
elif (temp2 == 0x80):
temp3 |= 0x01 # gray1
else: # 0x40
temp3 |= 0x00 # gray2
temp3 <<= 1
temp1 <<= 2
temp2 = temp1&0xC0
if(temp2 == 0xC0): #white
temp2 = temp1 & 0xC0
if (temp2 == 0xC0): # white
temp3 |= 0x01
elif(temp2 == 0x00): #black
elif (temp2 == 0x00): # black
temp3 |= 0x00
elif(temp2 == 0x80):
temp3 |= 0x01 #gray1
else : #0x40
temp3 |= 0x00 #gray2
if(j!=1 or k!=1):
elif (temp2 == 0x80):
temp3 |= 0x01 # gray1
else: # 0x40
temp3 |= 0x00 # gray2
if (j != 1 or k != 1):
temp3 <<= 1
temp1 <<= 2
self.send_data(temp3)
self.send_command(0x13)
for i in range(0, EPD_WIDTH * EPD_HEIGHT / 8): #5808*4 46464
temp3=0
for i in range(0, EPD_WIDTH * EPD_HEIGHT / 8): # 5808*4 46464
temp3 = 0
for j in range(0, 2):
temp1 = image[i*2+j]
temp1 = image[i * 2 + j]
for k in range(0, 2):
temp2 = temp1&0xC0
if(temp2 == 0xC0):
temp3 |= 0x01#white
elif(temp2 == 0x00):
temp3 |= 0x00 #black
elif(temp2 == 0x80):
temp3 |= 0x00 #gray1
else: #0x40
temp3 |= 0x01 #gray2
temp2 = temp1 & 0xC0
if (temp2 == 0xC0):
temp3 |= 0x01 # white
elif (temp2 == 0x00):
temp3 |= 0x00 # black
elif (temp2 == 0x80):
temp3 |= 0x00 # gray1
else: # 0x40
temp3 |= 0x01 # gray2
temp3 <<= 1
temp1 <<= 2
temp2 = temp1&0xC0
if(temp2 == 0xC0): #white
temp2 = temp1 & 0xC0
if (temp2 == 0xC0): # white
temp3 |= 0x01
elif(temp2 == 0x00): #black
elif (temp2 == 0x00): # black
temp3 |= 0x00
elif(temp2 == 0x80):
temp3 |= 0x00 #gray1
else: #0x40
temp3 |= 0x01 #gray2
if(j!=1 or k!=1):
elif (temp2 == 0x80):
temp3 |= 0x00 # gray1
else: # 0x40
temp3 |= 0x01 # gray2
if (j != 1 or k != 1):
temp3 <<= 1
temp1 <<= 2
self.send_data(temp3)
@@ -475,4 +480,3 @@ class EPD:
epdconfig.module_exit()
### END OF FILE ###

View File

@@ -34,6 +34,7 @@ from inkycal.display.drivers import epdconfig
EPD_WIDTH = 400
EPD_HEIGHT = 300
class EPD:
def __init__(self):
self.reset_pin = epdconfig.RST_PIN
@@ -48,7 +49,8 @@ class EPD:
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(200)
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(5) # support v2 displays in favor of v1 displays.Change this to 10 for legacy v1 display support
epdconfig.delay_ms(
5) # support v2 displays in favor of v1 displays.Change this to 10 for legacy v1 display support
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(200)
@@ -66,7 +68,7 @@ class EPD:
def ReadBusy(self):
logging.debug("e-Paper busy")
while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
while (epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
epdconfig.delay_ms(100)
logging.debug("e-Paper busy release")
@@ -77,9 +79,9 @@ class EPD:
self.reset()
self.send_command(0x06) # BOOSTER_SOFT_START
self.send_data (0x17)
self.send_data (0x17)
self.send_data (0x17) # 07 0f 17 1f 27 2F 37 2f
self.send_data(0x17)
self.send_data(0x17)
self.send_data(0x17) # 07 0f 17 1f 27 2F 37 2f
self.send_command(0x04) # POWER_ON
self.ReadBusy()
@@ -91,26 +93,26 @@ class EPD:
def getbuffer(self, image):
# logging.debug("bufsiz = ",int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width / 8) * self.height)
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
# logging.debug("imwidth = %d, imheight = %d",imwidth,imheight)
if(imwidth == self.width and imheight == self.height):
if (imwidth == self.width and imheight == self.height):
logging.debug("Horizontal")
for y in range(imheight):
for x in range(imwidth):
# Set the bits for the column of pixels at the current position.
if pixels[x, y] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
elif(imwidth == self.height and imheight == self.width):
elif (imwidth == self.height and imheight == self.width):
logging.debug("Vertical")
for y in range(imheight):
for x in range(imwidth):
newx = y
newy = self.height - x - 1
if pixels[x, y] == 0:
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))
buf[int((newx + newy * self.width) / 8)] &= ~(0x80 >> (y % 8))
return buf
def display(self, imageblack, imagered):
@@ -145,4 +147,3 @@ class EPD:
epdconfig.module_exit()
### END OF FILE ###

View File

@@ -35,6 +35,7 @@ from inkycal.display.drivers import epdconfig
EPD_WIDTH = 600
EPD_HEIGHT = 448
class EPD:
def __init__(self):
self.reset_pin = epdconfig.RST_PIN
@@ -67,7 +68,7 @@ class EPD:
def ReadBusy(self):
logging.debug("e-Paper busy")
while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
while (epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
epdconfig.delay_ms(100)
logging.debug("e-Paper busy release")
@@ -125,8 +126,8 @@ class EPD:
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
logging.debug('imwidth = %d imheight = %d ',imwidth, imheight)
if(imwidth == self.width and imheight == self.height):
logging.debug('imwidth = %d imheight = %d ', imwidth, imheight)
if (imwidth == self.width and imheight == self.height):
for y in range(imheight):
for x in range(imwidth):
# Set the bits for the column of pixels at the current position.
@@ -137,18 +138,18 @@ class EPD:
buf[int((x + y * self.width) / 4)] |= 0x40 >> (x % 4 * 2)
else: # white
buf[int((x + y * self.width) / 4)] |= 0xC0 >> (x % 4 * 2)
elif(imwidth == self.height and imheight == self.width):
elif (imwidth == self.height and imheight == self.width):
for y in range(imheight):
for x in range(imwidth):
newx = y
newy = self.height - x - 1
if pixels[x, y] < 64: # black
buf[int((newx + newy*self.width) / 4)] &= ~(0xC0 >> (y % 4 * 2))
buf[int((newx + newy * self.width) / 4)] &= ~(0xC0 >> (y % 4 * 2))
elif pixels[x, y] < 192: # convert gray to red
buf[int((newx + newy*self.width) / 4)] &= ~(0xC0 >> (y % 4 * 2))
buf[int((newx + newy*self.width) / 4)] |= 0x40 >> (y % 4 * 2)
buf[int((newx + newy * self.width) / 4)] &= ~(0xC0 >> (y % 4 * 2))
buf[int((newx + newy * self.width) / 4)] |= 0x40 >> (y % 4 * 2)
else: # white
buf[int((newx + newy*self.width) / 4)] |= 0xC0 >> (y % 4 * 2)
buf[int((newx + newy * self.width) / 4)] |= 0xC0 >> (y % 4 * 2)
return buf
def display(self, image):
@@ -166,7 +167,7 @@ class EPD:
temp2 = (temp2 << 4) & 0xFF
temp1 = (temp1 << 2) & 0xFF
j += 1
if((temp1 & 0xC0) == 0xC0):
if ((temp1 & 0xC0) == 0xC0):
temp2 |= 0x03
elif ((temp1 & 0xC0) == 0x00):
temp2 |= 0x00
@@ -196,5 +197,4 @@ class EPD:
epdconfig.module_exit()
### END OF FILE ###
### END OF FILE ###

View File

@@ -35,6 +35,7 @@ from inkycal.display.drivers import epdconfig
EPD_WIDTH = 600
EPD_HEIGHT = 448
class EPD:
def __init__(self):
self.reset_pin = epdconfig.RST_PIN
@@ -67,7 +68,7 @@ class EPD:
def ReadBusy(self):
logging.debug("e-Paper busy")
while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
while (epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
epdconfig.delay_ms(100)
logging.debug("e-Paper busy release")
@@ -118,26 +119,26 @@ class EPD:
def getbuffer(self, image):
# logging.debug("bufsiz = ",int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width / 8) * self.height)
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
logging.debug('imwidth = %d imheight = %d ',imwidth, imheight)
if(imwidth == self.width and imheight == self.height):
logging.debug('imwidth = %d imheight = %d ', imwidth, imheight)
if (imwidth == self.width and imheight == self.height):
logging.debug("Horizontal")
for y in range(imheight):
for x in range(imwidth):
# Set the bits for the column of pixels at the current position.
if pixels[x, y] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
elif(imwidth == self.height and imheight == self.width):
elif (imwidth == self.height and imheight == self.width):
logging.debug("Vertical")
for y in range(imheight):
for x in range(imwidth):
newx = y
newy = self.height - x - 1
if pixels[x, y] == 0:
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))
buf[int((newx + newy * self.width) / 8)] &= ~(0x80 >> (y % 8))
return buf
def display(self, imageblack, imagered):
@@ -148,22 +149,22 @@ class EPD:
j = 0
while (j < 8):
if ((temp2 & 0x80) == 0x00):
temp3 = 0x04 #red
temp3 = 0x04 # red
elif ((temp1 & 0x80) == 0x00):
temp3 = 0x00 #black
temp3 = 0x00 # black
else:
temp3 = 0x03 #white
temp3 = 0x03 # white
temp3 = (temp3 << 4) & 0xFF
temp1 = (temp1 << 1) & 0xFF
temp2 = (temp2 << 1) & 0xFF
j += 1
if((temp2 & 0x80) == 0x00):
temp3 |= 0x04 #red
if ((temp2 & 0x80) == 0x00):
temp3 |= 0x04 # red
elif ((temp1 & 0x80) == 0x00):
temp3 |= 0x00 #black
temp3 |= 0x00 # black
else:
temp3 |= 0x03 #white
temp3 |= 0x03 # white
temp1 = (temp1 << 1) & 0xFF
temp2 = (temp2 << 1) & 0xFF
self.send_data(temp3)
@@ -197,4 +198,3 @@ class EPD:
epdconfig.module_exit()
### END OF FILE ###

View File

@@ -35,6 +35,7 @@ from inkycal.display.drivers import epdconfig
EPD_WIDTH = 640
EPD_HEIGHT = 384
class EPD:
def __init__(self):
self.reset_pin = epdconfig.RST_PIN
@@ -67,7 +68,7 @@ class EPD:
def ReadBusy(self):
logging.debug("e-Paper busy")
while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
while (epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
epdconfig.delay_ms(100)
logging.debug("e-Paper busy release")
@@ -106,9 +107,9 @@ class EPD:
self.send_data(0x22)
self.send_command(0x61) # TCON_RESOLUTION
self.send_data(EPD_WIDTH >> 8) #source 640
self.send_data(EPD_WIDTH >> 8) # source 640
self.send_data(EPD_WIDTH & 0xff)
self.send_data(EPD_HEIGHT >> 8) #gate 384
self.send_data(EPD_HEIGHT >> 8) # gate 384
self.send_data(EPD_HEIGHT & 0xff)
self.send_command(0x82) # VCM_DC_SETTING
@@ -126,8 +127,8 @@ class EPD:
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
logging.debug('imwidth = %d imheight = %d ',imwidth, imheight)
if(imwidth == self.width and imheight == self.height):
logging.debug('imwidth = %d imheight = %d ', imwidth, imheight)
if (imwidth == self.width and imheight == self.height):
for y in range(imheight):
for x in range(imwidth):
# Set the bits for the column of pixels at the current position.
@@ -138,18 +139,18 @@ class EPD:
buf[int((x + y * self.width) / 4)] |= 0x40 >> (x % 4 * 2)
else: # white
buf[int((x + y * self.width) / 4)] |= 0xC0 >> (x % 4 * 2)
elif(imwidth == self.height and imheight == self.width):
elif (imwidth == self.height and imheight == self.width):
for y in range(imheight):
for x in range(imwidth):
newx = y
newy = self.height - x - 1
if pixels[x, y] < 64: # black
buf[int((newx + newy*self.width) / 4)] &= ~(0xC0 >> (y % 4 * 2))
buf[int((newx + newy * self.width) / 4)] &= ~(0xC0 >> (y % 4 * 2))
elif pixels[x, y] < 192: # convert gray to red
buf[int((newx + newy*self.width) / 4)] &= ~(0xC0 >> (y % 4 * 2))
buf[int((newx + newy*self.width) / 4)] |= 0x40 >> (y % 4 * 2)
buf[int((newx + newy * self.width) / 4)] &= ~(0xC0 >> (y % 4 * 2))
buf[int((newx + newy * self.width) / 4)] |= 0x40 >> (y % 4 * 2)
else: # white
buf[int((newx + newy*self.width) / 4)] |= 0xC0 >> (y % 4 * 2)
buf[int((newx + newy * self.width) / 4)] |= 0xC0 >> (y % 4 * 2)
return buf
def display(self, image):
@@ -167,7 +168,7 @@ class EPD:
temp2 = (temp2 << 4) & 0xFF
temp1 = (temp1 << 2) & 0xFF
j += 1
if((temp1 & 0xC0) == 0xC0):
if ((temp1 & 0xC0) == 0xC0):
temp2 |= 0x03
elif ((temp1 & 0xC0) == 0x00):
temp2 |= 0x00
@@ -199,4 +200,3 @@ class EPD:
epdconfig.module_exit()
### END OF FILE ###

View File

@@ -35,6 +35,7 @@ from inkycal.display.drivers import epdconfig
EPD_WIDTH = 640
EPD_HEIGHT = 384
class EPD:
def __init__(self):
self.reset_pin = epdconfig.RST_PIN
@@ -67,7 +68,7 @@ class EPD:
def ReadBusy(self):
logging.debug("e-Paper busy")
while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
while (epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
epdconfig.delay_ms(100)
logging.debug("e-Paper busy release")
@@ -89,7 +90,7 @@ class EPD:
self.send_data(0x3A) # PLL: 0-15:0x3C, 15+:0x3A
self.send_command(0x82) # VCM_DC_SETTING
self.send_data(0x28) #all temperature range
self.send_data(0x28) # all temperature range
self.send_command(0x06) # BOOSTER_SOFT_START
self.send_data(0xc7)
@@ -118,26 +119,26 @@ class EPD:
def getbuffer(self, image):
# logging.debug("bufsiz = ",int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width / 8) * self.height)
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
logging.debug('imwidth = %d imheight = %d ',imwidth, imheight)
if(imwidth == self.width and imheight == self.height):
logging.debug('imwidth = %d imheight = %d ', imwidth, imheight)
if (imwidth == self.width and imheight == self.height):
logging.debug("Horizontal")
for y in range(imheight):
for x in range(imwidth):
# Set the bits for the column of pixels at the current position.
if pixels[x, y] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
elif(imwidth == self.height and imheight == self.width):
elif (imwidth == self.height and imheight == self.width):
logging.debug("Vertical")
for y in range(imheight):
for x in range(imwidth):
newx = y
newy = self.height - x - 1
if pixels[x, y] == 0:
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))
buf[int((newx + newy * self.width) / 8)] &= ~(0x80 >> (y % 8))
return buf
def display(self, imageblack, imagered):
@@ -148,22 +149,22 @@ class EPD:
j = 0
while (j < 8):
if ((temp2 & 0x80) == 0x00):
temp3 = 0x04 #red
temp3 = 0x04 # red
elif ((temp1 & 0x80) == 0x00):
temp3 = 0x00 #black
temp3 = 0x00 # black
else:
temp3 = 0x03 #white
temp3 = 0x03 # white
temp3 = (temp3 << 4) & 0xFF
temp1 = (temp1 << 1) & 0xFF
temp2 = (temp2 << 1) & 0xFF
j += 1
if((temp2 & 0x80) == 0x00):
temp3 |= 0x04 #red
if ((temp2 & 0x80) == 0x00):
temp3 |= 0x04 # red
elif ((temp1 & 0x80) == 0x00):
temp3 |= 0x00 #black
temp3 |= 0x00 # black
else:
temp3 |= 0x03 #white
temp3 |= 0x03 # white
temp1 = (temp1 << 1) & 0xFF
temp2 = (temp2 << 1) & 0xFF
self.send_data(temp3)
@@ -198,4 +199,3 @@ class EPD:
epdconfig.module_exit()
### END OF FILE ###

View File

@@ -35,6 +35,7 @@ from inkycal.display.drivers import epdconfig
EPD_WIDTH = 800
EPD_HEIGHT = 480
class EPD:
def __init__(self):
self.reset_pin = epdconfig.RST_PIN
@@ -69,7 +70,7 @@ class EPD:
logging.debug("e-Paper busy")
self.send_command(0x71)
busy = epdconfig.digital_read(self.busy_pin)
while(busy == 0):
while (busy == 0):
self.send_command(0x71)
busy = epdconfig.digital_read(self.busy_pin)
epdconfig.delay_ms(200)
@@ -80,33 +81,33 @@ class EPD:
# EPD hardware init start
self.reset()
self.send_command(0x01) #POWER SETTING
self.send_command(0x01) # POWER SETTING
self.send_data(0x07)
self.send_data(0x07) #VGH=20V,VGL=-20V
self.send_data(0x3f) #VDH=15V
self.send_data(0x3f) #VDL=-15V
self.send_data(0x07) # VGH=20V,VGL=-20V
self.send_data(0x3f) # VDH=15V
self.send_data(0x3f) # VDL=-15V
self.send_command(0x04) #POWER ON
self.send_command(0x04) # POWER ON
epdconfig.delay_ms(100)
self.ReadBusy()
self.send_command(0X00) #PANNEL SETTING
self.send_data(0x1F) #KW-3f KWR-2F BWROTP 0f BWOTP 1f
self.send_command(0X00) # PANNEL SETTING
self.send_data(0x1F) # KW-3f KWR-2F BWROTP 0f BWOTP 1f
self.send_command(0x61) #tres
self.send_data(0x03) #source 800
self.send_command(0x61) # tres
self.send_data(0x03) # source 800
self.send_data(0x20)
self.send_data(0x01) #gate 480
self.send_data(0x01) # gate 480
self.send_data(0xE0)
self.send_command(0X15)
self.send_data(0x00)
self.send_command(0X50) #VCOM AND DATA INTERVAL SETTING
self.send_command(0X50) # VCOM AND DATA INTERVAL SETTING
self.send_data(0x10)
self.send_data(0x07)
self.send_command(0X60) #TCON SETTING
self.send_command(0X60) # TCON SETTING
self.send_data(0x22)
# EPD hardware init end
@@ -114,26 +115,26 @@ class EPD:
def getbuffer(self, image):
# logging.debug("bufsiz = ",int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width / 8) * self.height)
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
# logging.debug("imwidth = %d, imheight = %d",imwidth,imheight)
if(imwidth == self.width and imheight == self.height):
if (imwidth == self.width and imheight == self.height):
logging.debug("Vertical")
for y in range(imheight):
for x in range(imwidth):
# Set the bits for the column of pixels at the current position.
if pixels[x, y] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
elif(imwidth == self.height and imheight == self.width):
elif (imwidth == self.height and imheight == self.width):
logging.debug("Horizontal")
for y in range(imheight):
for x in range(imwidth):
newx = y
newy = self.height - x - 1
if pixels[x, y] == 0:
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))
buf[int((newx + newy * self.width) / 8)] &= ~(0x80 >> (y % 8))
return buf
def display(self, image):
@@ -167,4 +168,3 @@ class EPD:
epdconfig.module_exit()
### END OF FILE ###

View File

@@ -35,6 +35,7 @@ from inkycal.display.drivers import epdconfig
EPD_WIDTH = 800
EPD_HEIGHT = 480
class EPD:
def __init__(self):
self.reset_pin = epdconfig.RST_PIN
@@ -69,7 +70,7 @@ class EPD:
logging.debug("e-Paper busy")
self.send_command(0x71)
busy = epdconfig.digital_read(self.busy_pin)
while(busy == 0):
while (busy == 0):
self.send_command(0x71)
busy = epdconfig.digital_read(self.busy_pin)
epdconfig.delay_ms(200)
@@ -80,59 +81,59 @@ class EPD:
self.reset()
self.send_command(0x01); #POWER SETTING
self.send_command(0x01); # POWER SETTING
self.send_data(0x07);
self.send_data(0x07); #VGH=20V,VGL=-20V
self.send_data(0x3f); #VDH=15V
self.send_data(0x3f); #VDL=-15V
self.send_data(0x07); # VGH=20V,VGL=-20V
self.send_data(0x3f); # VDH=15V
self.send_data(0x3f); # VDL=-15V
self.send_command(0x04); #POWER ON
self.send_command(0x04); # POWER ON
epdconfig.delay_ms(100);
self.ReadBusy();
self.send_command(0X00); #PANNEL SETTING
self.send_data(0x0F); #KW-3f KWR-2F BWROTP 0f BWOTP 1f
self.send_command(0X00); # PANNEL SETTING
self.send_data(0x0F); # KW-3f KWR-2F BWROTP 0f BWOTP 1f
self.send_command(0x61); #tres
self.send_data(0x03); #source 800
self.send_command(0x61); # tres
self.send_data(0x03); # source 800
self.send_data(0x20);
self.send_data(0x01); #gate 480
self.send_data(0x01); # gate 480
self.send_data(0xE0);
self.send_command(0X15);
self.send_data(0x00);
self.send_command(0X50); #VCOM AND DATA INTERVAL SETTING
self.send_command(0X50); # VCOM AND DATA INTERVAL SETTING
self.send_data(0x11);
self.send_data(0x07);
self.send_command(0X60); #TCON SETTING
self.send_command(0X60); # TCON SETTING
self.send_data(0x22);
return 0
def getbuffer(self, image):
# logging.debug("bufsiz = ",int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width / 8) * self.height)
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
logging.debug('imwidth = %d imheight = %d ',imwidth, imheight)
if(imwidth == self.width and imheight == self.height):
logging.debug('imwidth = %d imheight = %d ', imwidth, imheight)
if (imwidth == self.width and imheight == self.height):
logging.debug("Horizontal")
for y in range(imheight):
for x in range(imwidth):
# Set the bits for the column of pixels at the current position.
if pixels[x, y] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
elif(imwidth == self.height and imheight == self.width):
elif (imwidth == self.height and imheight == self.width):
logging.debug("Vertical")
for y in range(imheight):
for x in range(imwidth):
newx = y
newy = self.height - x - 1
if pixels[x, y] == 0:
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))
buf[int((newx + newy * self.width) / 8)] &= ~(0x80 >> (y % 8))
return buf
def display(self, imageblack, imagered):
@@ -170,4 +171,3 @@ class EPD:
epdconfig.module_exit()
### END OF FILE ###

View File

@@ -35,6 +35,7 @@ from . import epdconfig
EPD_WIDTH = 880
EPD_HEIGHT = 528
class EPD:
def __init__(self):
self.reset_pin = epdconfig.RST_PIN
@@ -68,7 +69,7 @@ class EPD:
def ReadBusy(self):
logging.debug("e-Paper busy")
busy = epdconfig.digital_read(self.busy_pin)
while(busy == 1):
while (busy == 1):
busy = epdconfig.digital_read(self.busy_pin)
epdconfig.delay_ms(200)
@@ -79,7 +80,7 @@ class EPD:
self.reset()
self.ReadBusy();
self.send_command(0x12); #SWRESET
self.send_command(0x12); # SWRESET
self.ReadBusy();
self.send_command(0x46); # Auto Write Red RAM
@@ -96,11 +97,10 @@ class EPD:
self.send_data(0xC0);
self.send_data(0x40);
self.send_command(0x01); # Set MUX as 527
self.send_data(0xAF);
self.send_data(0x02);
self.send_data(0x01);#0x01
self.send_data(0x01); # 0x01
self.send_command(0x11); # Data entry mode
self.send_data(0x01);
@@ -122,9 +122,8 @@ class EPD:
self.send_command(0x18);
self.send_data(0X80);
self.send_command(0x22);
self.send_data(0XB1); #Load Temperature and waveform setting.
self.send_data(0XB1); # Load Temperature and waveform setting.
self.send_command(0x20);
self.ReadBusy();
@@ -139,26 +138,26 @@ class EPD:
def getbuffer(self, image):
# logging.debug("bufsiz = ",int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width / 8) * self.height)
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
# logging.debug("imwidth = %d, imheight = %d",imwidth,imheight)
if(imwidth == self.width and imheight == self.height):
if (imwidth == self.width and imheight == self.height):
logging.debug("Vertical")
for y in range(imheight):
for x in range(imwidth):
# Set the bits for the column of pixels at the current position.
if pixels[x, y] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
elif(imwidth == self.height and imheight == self.width):
elif (imwidth == self.height and imheight == self.width):
logging.debug("Horizontal")
for y in range(imheight):
for x in range(imwidth):
newx = y
newy = self.height - x - 1
if pixels[x, y] == 0:
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))
buf[int((newx + newy * self.width) / 8)] &= ~(0x80 >> (y % 8))
return buf
def display(self, image):
@@ -170,7 +169,7 @@ class EPD:
self.send_data(image[i]);
self.send_command(0x22);
self.send_data(0xF7);#Load LUT from MCU(0x32)
self.send_data(0xF7); # Load LUT from MCU(0x32)
self.send_command(0x20);
epdconfig.delay_ms(10);
self.ReadBusy();
@@ -188,7 +187,7 @@ class EPD:
self.send_data(0xff)
self.send_command(0x22);
self.send_data(0xF7);#Load LUT from MCU(0x32)
self.send_data(0xF7); # Load LUT from MCU(0x32)
self.send_command(0x20);
epdconfig.delay_ms(10);
self.ReadBusy();

View File

@@ -35,6 +35,7 @@ from inkycal.display.drivers import epdconfig
EPD_WIDTH = 880
EPD_HEIGHT = 528
class EPD:
def __init__(self):
self.reset_pin = epdconfig.RST_PIN
@@ -68,7 +69,7 @@ class EPD:
def ReadBusy(self):
logging.debug("e-Paper busy")
busy = epdconfig.digital_read(self.busy_pin)
while(busy == 1):
while (busy == 1):
busy = epdconfig.digital_read(self.busy_pin)
epdconfig.delay_ms(200)
@@ -78,16 +79,16 @@ class EPD:
self.reset()
self.send_command(0x12); #SWRESET
self.ReadBusy(); #waiting for the electronic paper IC to release the idle signal
self.send_command(0x12); # SWRESET
self.ReadBusy(); # waiting for the electronic paper IC to release the idle signal
self.send_command(0x46); # Auto Write RAM
self.send_data(0xF7);
self.ReadBusy(); #waiting for the electronic paper IC to release the idle signal
self.ReadBusy(); # waiting for the electronic paper IC to release the idle signal
self.send_command(0x47); # Auto Write RAM
self.send_data(0xF7);
self.ReadBusy(); #waiting for the electronic paper IC to release the idle signal
self.ReadBusy(); # waiting for the electronic paper IC to release the idle signal
self.send_command(0x0C); # Soft start setting
self.send_data(0xAE);
@@ -121,9 +122,9 @@ class EPD:
self.send_command(0x18);
self.send_data(0X80);
self.send_command(0x22);
self.send_data(0XB1); #Load Temperature and waveform setting.
self.send_data(0XB1); # Load Temperature and waveform setting.
self.send_command(0x20);
self.ReadBusy(); #waiting for the electronic paper IC to release the idle signal
self.ReadBusy(); # waiting for the electronic paper IC to release the idle signal
self.send_command(0x4E);
self.send_data(0x00);
@@ -136,26 +137,26 @@ class EPD:
def getbuffer(self, image):
# logging.debug("bufsiz = ",int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width / 8) * self.height)
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
logging.debug('imwidth = %d imheight = %d ',imwidth, imheight)
if(imwidth == self.width and imheight == self.height):
logging.debug('imwidth = %d imheight = %d ', imwidth, imheight)
if (imwidth == self.width and imheight == self.height):
logging.debug("Horizontal")
for y in range(imheight):
for x in range(imwidth):
# Set the bits for the column of pixels at the current position.
if pixels[x, y] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
elif(imwidth == self.height and imheight == self.width):
elif (imwidth == self.height and imheight == self.width):
logging.debug("Vertical")
for y in range(imheight):
for x in range(imwidth):
newx = y
newy = self.height - x - 1
if pixels[x, y] == 0:
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))
buf[int((newx + newy * self.width) / 8)] &= ~(0x80 >> (y % 8))
return buf
def display(self, imageblack, imagered):
@@ -166,15 +167,14 @@ class EPD:
for i in range(0, int(self.width * self.height / 8)):
self.send_data(imageblack[i]);
self.send_command(0x26)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(~imagered[i]);
self.send_command(0x22);
self.send_data(0xC7); #Load LUT from MCU(0x32)
self.send_data(0xC7); # Load LUT from MCU(0x32)
self.send_command(0x20);
epdconfig.delay_ms(200); #!!!The delay here is necessary, 200uS at least!!!
epdconfig.delay_ms(200); # !!!The delay here is necessary, 200uS at least!!!
self.ReadBusy();
def Clear(self):
@@ -185,19 +185,18 @@ class EPD:
for i in range(0, int(self.width * self.height / 8)):
self.send_data(0xff);
self.send_command(0x26)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(0x00);
self.send_command(0x22);
self.send_data(0xC7); #Load LUT from MCU(0x32)
self.send_data(0xC7); # Load LUT from MCU(0x32)
self.send_command(0x20);
epdconfig.delay_ms(200); #!!!The delay here is necessary, 200uS at least!!!
epdconfig.delay_ms(200); # !!!The delay here is necessary, 200uS at least!!!
self.ReadBusy();
def sleep(self):
self.send_command(0x10); #deep sleep
self.send_command(0x10); # deep sleep
self.send_data(0x01);
epdconfig.module_exit()

View File

@@ -35,6 +35,7 @@ import time
filename = os.path.basename(__file__).split('.py')[0]
logger = logging.getLogger(filename)
class RaspberryPi:
# Pin definition
RST_PIN = 17
@@ -76,7 +77,7 @@ class RaspberryPi:
def module_exit(self):
logger.debug("spi end")
#self.SPI.close() #removed as it causes some problems
# self.SPI.close() #removed as it causes some problems
logger.debug("close 5V, Module enters 0 power consumption ...")
self.GPIO.output(self.RST_PIN, 0)
@@ -152,5 +153,4 @@ else:
for func in [x for x in dir(implementation) if not x.startswith('_')]:
setattr(sys.modules[__name__], func, getattr(implementation, func))
### END OF FILE ###

View File

@@ -7,4 +7,4 @@ from .inkycal_image import Inkyimage
from .inkycal_jokes import Jokes
from .inkycal_stocks import Stocks
from .inkycal_slideshow import Slideshow
#from .inkycal_server import Inkyserver
# from .inkycal_server import Inkyserver

View File

@@ -1,5 +1,5 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
Third party module template (inkycal-compatible module)
@@ -13,7 +13,6 @@ Copyright by aceisace
from inkycal.modules.template import inkycal_module
from inkycal.custom import *
#############################################################################
# Built-in library imports (change as desired)
#############################################################################
@@ -21,7 +20,6 @@ from inkycal.custom import *
# Built-in libraries go here
from random import shuffle
#############################################################################
# External library imports (always use try-except)
#############################################################################
@@ -35,7 +33,6 @@ except ImportError:
print('feedparser is not installed! Please install with:')
print('pip3 install feedparser')
#############################################################################
# Filename + logging (do not remove)
#############################################################################
@@ -44,6 +41,7 @@ except ImportError:
filename = os.path.basename(__file__).split('.py')[0]
logger = logging.getLogger(filename)
#############################################################################
# Class setup
#############################################################################
@@ -65,7 +63,7 @@ class Simple(inkycal_module):
# to run correctly, e.g. if your module needs an 'api-key' and a 'name':
requires = {
# A simple text input; users can choose what to enter by keyboard
'api_key': {"label" : "Please enter your api-key from some-website"},
'api_key': {"label": "Please enter your api-key from some-website"},
# A simple text input; users can choose what to enter by keyboard
'username': {"label": "Please enter a username"},
@@ -102,6 +100,7 @@ class Simple(inkycal_module):
"default": True,
},
}
########################################################################
# Initialise the class (do not remove)
@@ -130,26 +129,26 @@ class Simple(inkycal_module):
self.api_key = config['api_key']
# if you need a integer (number) input, you have to convert this to a int
#-----------------------------------------------------------------------#
# -----------------------------------------------------------------------#
# bad example :/
self.age = int( config["age"] )
self.age = int(config["age"])
# Remember age was a optional parameter? What if no age was entered
# and there is no fallback value? Then the age would be None.
# This would cause crashing right here
# good example :)
if config["age"] and isinstance(config["age"], str):
self.age = int( config["age"] )
self.age = int(config["age"])
else:
self.age = 10 # just a joke, no offense
# -> Check if age was entered and if it's a string (entered via web-UI)
# If something was entered for age, convert it to a number
# The else statement is executed when nothing was entered for age
# You could assign a custom value now or print something.
#-----------------------------------------------------------------------#
# -----------------------------------------------------------------------#
# if you need a list of words, you have to convert the string to a list
#-----------------------------------------------------------------------#
# -----------------------------------------------------------------------#
# good example :)
if config["hobbies"] and isinstance(config["hobbies"], str):
self.hobbies = config["age"].split(",")
@@ -157,14 +156,14 @@ class Simple(inkycal_module):
# even if a single value was entered, it will be converted to a list
else:
self.hobbies = [] # empty list if nothing was entered by user
#-----------------------------------------------------------------------#
# -----------------------------------------------------------------------#
# give an OK message
print(f'{filename} loaded')
#############################################################################
# Validation of module specific parameters (optional) #
#############################################################################
#############################################################################
# Validation of module specific parameters (optional) #
#############################################################################
def _validate(self):
"""Validate module-specific parameters"""
@@ -175,10 +174,9 @@ class Simple(inkycal_module):
if not isinstance(self.age, int):
print(f"age has to be a number, but given value is {self.age}")
#############################################################################
# Generating the image #
#############################################################################
#############################################################################
# Generating the image #
#############################################################################
def generate_image(self):
"""Generate image for this module"""
@@ -194,8 +192,8 @@ class Simple(inkycal_module):
logger.info('image size: {} x {} px'.format(im_width, im_height))
# Create an image for black pixels and one for coloured pixels (required)
im_black = Image.new('RGB', size = im_size, color = 'white')
im_colour = Image.new('RGB', size = im_size, color = 'white')
im_black = Image.new('RGB', size=im_size, color='white')
im_colour = Image.new('RGB', size=im_size, color='white')
#################################################################
@@ -215,7 +213,6 @@ class Simple(inkycal_module):
# If these aren't enough, take a look at python Pillow (imaging library)'s
# documentation.
#################################################################
# return the images ready for the display
@@ -225,9 +222,6 @@ class Simple(inkycal_module):
if __name__ == '__main__':
print('running {0} in standalone mode'.format(filename))
################################################################################
# Last steps
# Wow, you made your own module for the inkycal project! Amazing :D
@@ -248,4 +242,3 @@ if __name__ == '__main__':
# How do I now import my module?
# from inkycal.modules import Class
# Where Class is the name of the class inside your module (e.g. Simple)

View File

@@ -1,5 +1,5 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
iCalendar (parsing) module for Inky-Calendar Project
Copyright by aceisace
@@ -31,10 +31,10 @@ except ModuleNotFoundError:
print('icalendar library could not be found. Please install this with:')
print('pip3 install icalendar')
filename = os.path.basename(__file__).split('.py')[0]
logger = logging.getLogger(filename)
class iCalendar:
"""iCalendar parsing moudule for inkycal.
Parses events from given iCalendar URLs / paths"""
@@ -61,8 +61,7 @@ class iCalendar:
else:
ical = [auth_ical(url, username, password)]
else:
raise Exception (f"Input: '{url}' is not a string or list!")
raise Exception(f"Input: '{url}' is not a string or list!")
def auth_ical(url, uname, passwd):
"""Authorisation helper for protected ical files"""
@@ -95,7 +94,7 @@ class iCalendar:
ical = (Calendar.from_ical(ical_file.read()))
self.icalendars += ical
else:
raise Exception (f"Input: '{filepath}' is not a string or list!")
raise Exception(f"Input: '{filepath}' is not a string or list!")
logger.info('loaded iCalendars from filepaths')
@@ -137,13 +136,12 @@ class iCalendar:
arrow.get(events.get('dtstart').dt).format('HH:mm') != '00:00')
else arrow.get(events.get('DTSTART').dt).replace(tzinfo=timezone),
'end':arrow.get(events.get("DTEND").dt).to(timezone) if (
'end': arrow.get(events.get("DTEND").dt).to(timezone) if (
arrow.get(events.get('dtstart').dt).format('HH:mm') != '00:00')
else arrow.get(events.get('DTEND').dt).replace(tzinfo=timezone)
} for ical in recurring_events for events in ical)
# if any recurring events were found, add them to parsed_events
if events: self.parsed_events += list(events)
@@ -161,7 +159,6 @@ class iCalendar:
by_date = lambda event: event['begin']
self.parsed_events.sort(key=by_date)
def clear_events(self):
"""clear previously parsed events"""

View File

@@ -1,5 +1,5 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
Custom image class for Inkycal Project
@@ -18,6 +18,7 @@ import logging
filename = os.path.basename(__file__).split('.py')[0]
logger = logging.getLogger(filename)
class Inkyimage:
"""Custom Imge class written for commonly used image operations.
"""
@@ -63,7 +64,7 @@ class Inkyimage:
logger.info(f'width: {image.width}, height: {image.height}')
image.convert(mode='RGBA') #convert to a more suitable format
image.convert(mode='RGBA') # convert to a more suitable format
self.image = image
logger.info('loaded Image')
@@ -77,18 +78,18 @@ class Inkyimage:
"""Preview the image on gpicview (only works on Rapsbian with Desktop)"""
if self._image_loaded():
path = '/home/pi/Desktop/'
self.image.save(path+'temp.png')
os.system("gpicview "+path+'temp.png')
os.system('rm '+path+'temp.png')
self.image.save(path + 'temp.png')
os.system("gpicview " + path + 'temp.png')
os.system('rm ' + path + 'temp.png')
@staticmethod
def preview(image):
""""Previews an image on gpicview (only works on Rapsbian with Desktop).
"""
path = '/home/pi/Desktop/'
image.save(path+'temp.png')
os.system("gpicview "+path+'temp.png')
os.system('rm '+path+'temp.png')
image.save(path + 'temp.png')
os.system("gpicview " + path + 'temp.png')
os.system('rm ' + path + 'temp.png')
def _image_loaded(self):
"""returns True if image was loaded"""
@@ -111,7 +112,7 @@ class Inkyimage:
logger.error('Angle must be a multiple of 90')
return
image = image.rotate(angle, expand = True)
image = image.rotate(angle, expand=True)
self.image = image
logger.info(f'flipped image by {angle} degrees')
@@ -160,7 +161,7 @@ class Inkyimage:
bg = Image.new('RGBA', (image.width, image.height), 'white')
im = Image.alpha_composite(bg, image)
self.image.paste(im, (0,0))
self.image.paste(im, (0, 0))
logger.info('removed transparency')
def resize(self, width=None, height=None):
@@ -175,8 +176,8 @@ class Inkyimage:
if width:
initial_width = image.width
wpercent = (width/float(image.width))
hsize = int((float(image.height)*float(wpercent)))
wpercent = (width / float(image.width))
hsize = int((float(image.height) * float(wpercent)))
image = image.resize((width, hsize), Image.ANTIALIAS)
logger.info(f"resized image from {initial_width} to {image.width}")
self.image = image
@@ -211,12 +212,11 @@ class Inkyimage:
return Image.fromarray(x)
image2 = clear_white(image2)
image1.paste(image2, (0,0), image2)
image1.paste(image2, (0, 0), image2)
logger.info('merged given images into one')
return image1
def to_palette(self, palette, dither=True):
"""Maps an image to a given colour palette.
@@ -246,11 +246,11 @@ class Inkyimage:
if palette == 'bwr':
# black-white-red palette
pal = [255,255,255, 0,0,0, 255,0,0]
pal = [255, 255, 255, 0, 0, 0, 255, 0, 0]
elif palette == 'bwy':
# black-white-yellow palette
pal = [255,255,255, 0,0,0, 255,255,0]
pal = [255, 255, 255, 0, 0, 0, 255, 255, 0]
elif palette == 'bw':
pal = None
@@ -263,41 +263,41 @@ class Inkyimage:
# The palette needs to have 256 colors, for this, the black-colour
# is added until the
colours = len(pal) // 3
#print(f'The palette has {colours} colours')
# print(f'The palette has {colours} colours')
if 256 % colours != 0:
#print('Filling palette with black')
pal += (256 % colours) * [0,0,0]
# print('Filling palette with black')
pal += (256 % colours) * [0, 0, 0]
#print(pal)
# print(pal)
colours = len(pal) // 3
#print(f'The palette now has {colours} colours')
# print(f'The palette now has {colours} colours')
# Create a dummy image to be used as a palette
palette_im = Image.new('P', (1,1))
palette_im = Image.new('P', (1, 1))
# Attach the created palette. The palette should have 256 colours
# equivalent to 768 integers
palette_im.putpalette(pal* (256//colours))
palette_im.putpalette(pal * (256 // colours))
# Quantize the image to given palette
quantized_im = image.quantize(palette=palette_im, dither=dither)
quantized_im = quantized_im.convert('RGB')
# get rgb of the non-black-white colour from the palette
rgb = [pal[x:x+3] for x in range(0, len(pal),3)]
rgb = [col for col in rgb if col != [0,0,0] and col != [255,255,255]][0]
rgb = [pal[x:x + 3] for x in range(0, len(pal), 3)]
rgb = [col for col in rgb if col != [0, 0, 0] and col != [255, 255, 255]][0]
r_col, g_col, b_col = rgb
#print(f'r:{r_col} g:{g_col} b:{b_col}')
# print(f'r:{r_col} g:{g_col} b:{b_col}')
# Create an image buffer for black pixels
buffer1 = numpy.array(quantized_im)
# Get RGB values of each pixel
r,g,b = buffer1[:, :, 0], buffer1[:, :, 1], buffer1[:, :, 2]
r, g, b = buffer1[:, :, 0], buffer1[:, :, 1], buffer1[:, :, 2]
# convert coloured pixels to white
buffer1[numpy.logical_and(r==r_col, g==g_col)] = [255,255,255]
buffer1[numpy.logical_and(r == r_col, g == g_col)] = [255, 255, 255]
# reconstruct image for black-band
im_black = Image.fromarray(buffer1)
@@ -306,19 +306,19 @@ class Inkyimage:
buffer2 = numpy.array(quantized_im)
# Get RGB values of each pixel
r,g,b = buffer2[:, :, 0], buffer2[:, :, 1], buffer2[:, :, 2]
r, g, b = buffer2[:, :, 0], buffer2[:, :, 1], buffer2[:, :, 2]
# convert black pixels to white
buffer2[numpy.logical_and(r==0, g==0)] = [255,255,255]
buffer2[numpy.logical_and(r == 0, g == 0)] = [255, 255, 255]
# convert non-white pixels to black
buffer2[numpy.logical_and(g==g_col, b==0)] = [0,0,0]
buffer2[numpy.logical_and(g == g_col, b == 0)] = [0, 0, 0]
# reconstruct image for colour-band
im_colour = Image.fromarray(buffer2)
#self.preview(im_black)
#self.preview(im_colour)
# self.preview(im_black)
# self.preview(im_colour)
else:
im_black = image.convert('1', dither=dither)
@@ -331,4 +331,3 @@ class Inkyimage:
if __name__ == '__main__':
print(f'running {filename} in standalone/debug mode')

View File

@@ -1,5 +1,5 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
Agenda module for Inky-Calendar Project
Copyright by aceisace
@@ -15,6 +15,7 @@ import arrow
filename = os.path.basename(__file__).split('.py')[0]
logger = logging.getLogger(filename)
class Agenda(inkycal_module):
"""Agenda class
Create agenda and show events from given icalendars
@@ -23,30 +24,29 @@ class Agenda(inkycal_module):
name = "Agenda - Display upcoming events from given iCalendars"
requires = {
"ical_urls" : {
"label":"iCalendar URL/s, separate multiple ones with a comma",
"ical_urls": {
"label": "iCalendar URL/s, separate multiple ones with a comma",
},
}
optional = {
"ical_files" : {
"label":"iCalendar filepaths, separated with a comma",
"ical_files": {
"label": "iCalendar filepaths, separated with a comma",
},
"date_format":{
"label":"Use an arrow-supported token for custom date formatting "+
"date_format": {
"label": "Use an arrow-supported token for custom date formatting " +
"see https://arrow.readthedocs.io/en/stable/#supported-tokens, e.g. ddd D MMM",
"default": "ddd D MMM",
},
"time_format":{
"label":"Use an arrow-supported token for custom time formatting "+
"time_format": {
"label": "Use an arrow-supported token for custom time formatting " +
"see https://arrow.readthedocs.io/en/stable/#supported-tokens, e.g. HH:mm",
"default":"HH:mm",
"default": "HH:mm",
},
}
def __init__(self, config):
@@ -96,8 +96,8 @@ class Agenda(inkycal_module):
logger.info(f'Image size: {im_size}')
# Create an image for black pixels and one for coloured pixels
im_black = Image.new('RGB', size = im_size, color = 'white')
im_colour = Image.new('RGB', size = im_size, color = 'white')
im_black = Image.new('RGB', size=im_size, color='white')
im_colour = Image.new('RGB', size=im_size, color='white')
# Calculate the max number of lines that can fit on the image
line_spacing = 1
@@ -112,9 +112,9 @@ class Agenda(inkycal_module):
# Create a list of dates for the next days
agenda_events = [
{'begin':today.shift(days=+_),
{'begin': today.shift(days=+_),
'title': today.shift(days=+_).format(
self.date_format,locale=self.language)}
self.date_format, locale=self.language)}
for _ in range(max_lines)]
# Load icalendar from config
@@ -133,7 +133,7 @@ class Agenda(inkycal_module):
# Sort events by beginning time
parser.sort()
#parser.show_events()
# parser.show_events()
# Set the width for date, time and event titles
date_width = int(max([self.font.getsize(
@@ -172,7 +172,7 @@ class Agenda(inkycal_module):
# Sort the combined list in chronological order of dates
by_date = lambda event: event['begin']
agenda_events.sort(key = by_date)
agenda_events.sort(key=by_date)
# Delete more entries than can be displayed (max lines)
del agenda_events[max_lines:]
@@ -187,10 +187,10 @@ class Agenda(inkycal_module):
if not 'end' in _:
ImageDraw.Draw(im_colour).line(
(0, line_pos[cursor][1], im_width, line_pos[cursor][1]),
fill = 'black')
fill='black')
write(im_black, line_pos[cursor], (date_width, line_height),
title, font = self.font, alignment='left')
title, font=self.font, alignment='left')
cursor += 1
@@ -202,11 +202,11 @@ class Agenda(inkycal_module):
if parser.all_day(_) == False:
write(im_black, (x_time, line_pos[cursor][1]),
(time_width, line_height), time,
font = self.font, alignment='left')
font=self.font, alignment='left')
write(im_black, (x_event, line_pos[cursor][1]),
(event_width, line_height),
''+title, font = self.font, alignment='left')
'' + title, font=self.font, alignment='left')
cursor += 1
# If no events were found, write only dates and lines
@@ -218,16 +218,16 @@ class Agenda(inkycal_module):
title = _['title']
ImageDraw.Draw(im_colour).line(
(0, line_pos[cursor][1], im_width, line_pos[cursor][1]),
fill = 'black')
fill='black')
write(im_black, line_pos[cursor], (date_width, line_height),
title, font = self.font, alignment='left')
title, font=self.font, alignment='left')
cursor += 1
# return the images ready for the display
return im_black, im_colour
if __name__ == '__main__':
print(f'running {filename} in standalone mode')

View File

@@ -1,5 +1,5 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
Calendar module for Inky-Calendar Project
Copyright by aceisace
@@ -23,34 +23,34 @@ class Calendar(inkycal_module):
optional = {
"week_starts_on" : {
"label":"When does your week start? (default=Monday)",
"week_starts_on": {
"label": "When does your week start? (default=Monday)",
"options": ["Monday", "Sunday"],
"default": "Monday"
},
"show_events" : {
"label":"Show parsed events? (default = True)",
"show_events": {
"label": "Show parsed events? (default = True)",
"options": [True, False],
"default": True
},
"ical_urls" : {
"label":"iCalendar URL/s, separate multiple ones with a comma",
"ical_urls": {
"label": "iCalendar URL/s, separate multiple ones with a comma",
},
"ical_files" : {
"label":"iCalendar filepaths, separated with a comma",
"ical_files": {
"label": "iCalendar filepaths, separated with a comma",
},
"date_format":{
"label":"Use an arrow-supported token for custom date formatting "+
"date_format": {
"label": "Use an arrow-supported token for custom date formatting " +
"see https://arrow.readthedocs.io/en/stable/#supported-tokens, e.g. D MMM",
"default": "D MMM",
},
"time_format":{
"label":"Use an arrow-supported token for custom time formatting "+
"time_format": {
"label": "Use an arrow-supported token for custom time formatting " +
"see https://arrow.readthedocs.io/en/stable/#supported-tokens, e.g. HH:mm",
"default": "HH:mm"
},
@@ -83,7 +83,7 @@ class Calendar(inkycal_module):
# additional configuration
self.timezone = get_system_tz()
self.num_font = ImageFont.truetype(
fonts['NotoSans-SemiCondensed'], size = self.fontsize)
fonts['NotoSans-SemiCondensed'], size=self.fontsize)
# give an OK message
print(f'{filename} loaded')
@@ -99,8 +99,8 @@ class Calendar(inkycal_module):
logger.info(f'Image size: {im_size}')
# Create an image for black pixels and one for coloured pixels
im_black = Image.new('RGB', size = im_size, color = 'white')
im_colour = Image.new('RGB', size = im_size, color = 'white')
im_black = 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.
month_name_height = int(im_height * 0.10)
@@ -136,29 +136,29 @@ class Calendar(inkycal_module):
grid_start_y = (month_name_height + weekdays_height + y_spacing_calendar)
grid_start_x = x_spacing_calendar
grid_coordinates = [(grid_start_x + icon_width*x, grid_start_y + icon_height*y)
grid_coordinates = [(grid_start_x + icon_width * x, grid_start_y + icon_height * y)
for y in range(calendar_rows) for x in range(calendar_cols)]
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)]
now = arrow.now(tz = self.timezone)
now = arrow.now(tz=self.timezone)
# Set weekstart of calendar to specified weekstart
if self.weekstart == "Monday":
cal.setfirstweekday(cal.MONDAY)
weekstart = now.shift(days = - now.weekday())
weekstart = now.shift(days=- now.weekday())
else:
cal.setfirstweekday(cal.SUNDAY)
weekstart = now.shift(days = - now.isoweekday())
weekstart = now.shift(days=- now.isoweekday())
# Write the name of current month
write(im_black, (0,0),(im_width, month_name_height),
str(now.format('MMMM',locale=self.language)), font = self.font,
autofit = True)
write(im_black, (0, 0), (im_width, month_name_height),
str(now.format('MMMM', locale=self.language)), font=self.font,
autofit=True)
# Set up weeknames in local language and add to main section
weekday_names = [weekstart.shift(days=+_).format('ddd',locale=self.language)
weekday_names = [weekstart.shift(days=+_).format('ddd', locale=self.language)
for _ in range(7)]
logger.debug(f'weekday names: {weekday_names}')
@@ -168,22 +168,22 @@ class Calendar(inkycal_module):
weekday_pos[_],
(icon_width, weekdays_height),
weekday_names[_],
font = self.font,
autofit = True,
font=self.font,
autofit=True,
fill_height=1.0
)
# Create a calendar template and flatten (remove nestings)
flatten = lambda z: [x for y in z for x in y]
calendar_flat = flatten(cal.monthcalendar(now.year, now.month))
#logger.debug(f" calendar_flat: {calendar_flat}")
# logger.debug(f" calendar_flat: {calendar_flat}")
# Map days of month to co-ordinates of grid -> 3: (row2_x,col3_y)
grid = {}
for i in calendar_flat:
if i != 0:
grid[i] = grid_coordinates[calendar_flat.index(i)]
#logger.debug(f"grid:{grid}")
# logger.debug(f"grid:{grid}")
# remove zeros from calendar since they are not required
calendar_flat = [num for num in calendar_flat if num != 0]
@@ -192,21 +192,20 @@ class Calendar(inkycal_module):
for number in calendar_flat:
if number != int(now.day):
write(im_black, grid[number], (icon_width, icon_height),
str(number), font = self.num_font, fill_height = 0.5, fill_width=0.5)
str(number), font=self.num_font, fill_height=0.5, fill_width=0.5)
# Draw a red/black circle with the current day of month in white
icon = Image.new('RGBA', (icon_width, icon_height))
current_day_pos = grid[int(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.2)
ImageDraw.Draw(icon).ellipse(
(x_circle-radius, y_circle-radius, x_circle+radius, y_circle+radius),
fill= 'black', outline=None)
write(icon, (0,0), (icon_width, icon_height), str(now.day),
font=self.num_font, fill_height = 0.5, colour='white')
(x_circle - radius, y_circle - radius, x_circle + radius, y_circle + radius),
fill='black', outline=None)
write(icon, (0, 0), (icon_width, icon_height), str(now.day),
font=self.num_font, fill_height=0.5, colour='white')
im_colour.paste(icon, current_day_pos, icon)
# If events should be loaded and shown...
if self.show_events == True:
@@ -228,11 +227,10 @@ class Calendar(inkycal_module):
# generate list of coordinates for each line
events_offset = im_height - events_height
event_lines = [(0, events_offset + int(events_height/max_event_lines*_))
event_lines = [(0, events_offset + int(events_height / max_event_lines * _))
for _ in range(max_event_lines)]
#logger.debug(f"event_lines {event_lines}")
# logger.debug(f"event_lines {event_lines}")
# timeline for filtering events within this month
month_start = arrow.get(now.floor('month'))
@@ -267,9 +265,9 @@ class Calendar(inkycal_module):
im_colour,
grid[days],
(icon_width, icon_height),
radius = 6,
thickness= 1,
shrinkage = (0.4, 0.2)
radius=6,
thickness=1,
shrinkage=(0.4, 0.2)
)
# Filter upcoming events until 4 weeks in the future
@@ -281,7 +279,6 @@ class Calendar(inkycal_module):
# delete events which won't be able to fit (more events than lines)
upcoming_events[:max_event_lines]
# Check if any events were found in the given timerange
if upcoming_events:
@@ -289,7 +286,7 @@ class Calendar(inkycal_module):
lang = self.language
date_width = int(max([self.font.getsize(
events['begin'].format(self.date_format,locale=lang))[0]
events['begin'].format(self.date_format, locale=lang))[0]
for events in upcoming_events]) * 1.1)
time_width = int(max([self.font.getsize(
@@ -311,36 +308,37 @@ class Calendar(inkycal_module):
name = event['title']
date = event['begin'].format(self.date_format, locale=lang)
time = event['begin'].format(self.time_format, locale=lang)
#logger.debug(f"name:{name} date:{date} time:{time}")
# logger.debug(f"name:{name} date:{date} time:{time}")
if now < event['end']:
write(im_colour, event_lines[cursor], (date_width, line_height),
date, font=self.font, alignment = 'left')
date, font=self.font, alignment='left')
# Check if event is all day
if parser.all_day(event) == True:
write(im_black, (date_width, event_lines[cursor][1]),
(event_width_l, line_height), name, font=self.font,
alignment = 'left')
alignment='left')
else:
write(im_black, (date_width, event_lines[cursor][1]),
(time_width, line_height), time, font=self.font,
alignment = 'left')
alignment='left')
write(im_black, (date_width+time_width,event_lines[cursor][1]),
write(im_black, (date_width + time_width, event_lines[cursor][1]),
(event_width_s, line_height), name, font=self.font,
alignment = 'left')
alignment='left')
cursor += 1
else:
symbol = '- '
while self.font.getsize(symbol)[0] < im_width*0.9:
while self.font.getsize(symbol)[0] < im_width * 0.9:
symbol += ' -'
write(im_black, event_lines[0],
(im_width, self.font.getsize(symbol)[1]), symbol,
font = self.font)
font=self.font)
# return the images ready for the display
return im_black, im_colour
if __name__ == '__main__':
print(f'running {filename} in standalone mode')

View File

@@ -1,5 +1,4 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
Feeds module for InkyCal Project
@@ -11,6 +10,7 @@ from inkycal.modules.template import inkycal_module
from inkycal.custom import *
from random import shuffle
try:
import feedparser
except ImportError:
@@ -20,6 +20,7 @@ except ImportError:
filename = os.path.basename(__file__).split('.py')[0]
logger = logging.getLogger(filename)
class Feeds(inkycal_module):
"""RSS class
parses rss/atom feeds from given urls
@@ -28,8 +29,8 @@ class Feeds(inkycal_module):
name = "RSS / Atom - Display feeds from given RSS/ATOM feeds"
requires = {
"feed_urls" : {
"label":"Please enter ATOM or RSS feed URL/s, separated by a comma",
"feed_urls": {
"label": "Please enter ATOM or RSS feed URL/s, separated by a comma",
},
}
@@ -74,7 +75,6 @@ class Feeds(inkycal_module):
if not isinstance(self.shuffle_feeds, bool):
print('shuffle_feeds has to be a boolean: True/False')
def generate_image(self):
"""Generate image for this module"""
@@ -85,8 +85,8 @@ class Feeds(inkycal_module):
logger.info(f'Image size: {im_size}')
# Create an image for black pixels and one for coloured pixels
im_black = Image.new('RGB', size = im_size, color = 'white')
im_colour = Image.new('RGB', size = im_size, color = 'white')
im_black = Image.new('RGB', size=im_size, color='white')
im_colour = Image.new('RGB', size=im_size, color='white')
# Check if internet is available
if internet_available() == True:
@@ -101,11 +101,11 @@ class Feeds(inkycal_module):
max_lines = (im_height // (self.font.getsize('hg')[1] + line_spacing))
# Calculate padding from top so the lines look centralised
spacing_top = int( im_height % line_height / 2 )
spacing_top = int(im_height % line_height / 2)
# Calculate line_positions
line_positions = [
(0, spacing_top + _ * line_height ) for _ in range(max_lines)]
(0, spacing_top + _ * line_height) for _ in range(max_lines)]
# Create list containing all feeds from all urls
parsed_feeds = []
@@ -130,7 +130,7 @@ class Feeds(inkycal_module):
filtered_feeds, counter = [], 0
for posts in parsed_feeds:
wrapped = text_wrap(posts, font = self.font, max_width = line_width)
wrapped = text_wrap(posts, font=self.font, max_width=line_width)
counter += len(wrapped)
if counter < max_lines:
filtered_feeds.append(wrapped)
@@ -148,10 +148,11 @@ class Feeds(inkycal_module):
# Write feeds on image
for _ in range(len(filtered_feeds)):
write(im_black, line_positions[_], (line_width, line_height),
filtered_feeds[_], font = self.font, alignment= 'left')
filtered_feeds[_], font=self.font, alignment='left')
# return images
return im_black, im_colour
if __name__ == '__main__':
print(f'running {filename} in standalone/debug mode')

View File

@@ -1,5 +1,4 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
Image module for Inkycal Project
@@ -14,6 +13,7 @@ from inkycal.modules.inky_image import Inkyimage as Images
filename = os.path.basename(__file__).split('.py')[0]
logger = logging.getLogger(filename)
class Inkyimage(inkycal_module):
"""Displays an image from URL or local path
"""
@@ -22,13 +22,13 @@ class Inkyimage(inkycal_module):
requires = {
"path":{
"label":"Path to a local folder, e.g. /home/pi/Desktop/images. "
"path": {
"label": "Path to a local folder, e.g. /home/pi/Desktop/images. "
"Only PNG and JPG/JPEG images are used for the slideshow."
},
"palette": {
"label":"Which palette should be used for converting images?",
"label": "Which palette should be used for converting images?",
"options": ["bw", "bwr", "bwy"]
}
@@ -36,12 +36,12 @@ class Inkyimage(inkycal_module):
optional = {
"autoflip":{
"label":"Should the image be flipped automatically?",
"autoflip": {
"label": "Should the image be flipped automatically?",
"options": [True, False]
},
"orientation":{
"orientation": {
"label": "Please select the desired orientation",
"options": ["vertical", "horizontal"]
}
@@ -68,7 +68,6 @@ class Inkyimage(inkycal_module):
# give an OK message
print(f'{filename} loaded')
def generate_image(self):
"""Generate image for this module"""
@@ -93,7 +92,7 @@ class Inkyimage(inkycal_module):
im.autoflip(self.orientation)
# resize the image so it can fit on the epaper
im.resize( width=im_width, height=im_height )
im.resize(width=im_width, height=im_height)
# convert images according to specified palette
im_black, im_colour = im.to_palette(self.palette)
@@ -104,5 +103,6 @@ class Inkyimage(inkycal_module):
# return images
return im_black, im_colour
if __name__ == '__main__':
print(f'running {filename} in standalone/debug mode')

View File

@@ -1,5 +1,4 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
iCanHazDadJoke module for InkyCal Project
@@ -11,12 +10,14 @@ from inkycal.modules.template import inkycal_module
from inkycal.custom import *
import requests
# Show less logging for request module
logging.getLogger("urllib3").setLevel(logging.WARNING)
filename = os.path.basename(__file__).split('.py')[0]
logger = logging.getLogger(filename)
class Jokes(inkycal_module):
"""Icanhazdad-api class
parses rss/atom feeds from given urls
@@ -24,7 +25,6 @@ class Jokes(inkycal_module):
name = "iCanHazDad API - grab a random joke from icanhazdad api"
def __init__(self, config):
"""Initialize inkycal_feeds module"""
@@ -45,8 +45,8 @@ class Jokes(inkycal_module):
logger.info(f'image size: {im_width} x {im_height} px')
# Create an image for black pixels and one for coloured pixels
im_black = Image.new('RGB', size = im_size, color = 'white')
im_colour = Image.new('RGB', size = im_size, color = 'white')
im_black = Image.new('RGB', size=im_size, color='white')
im_colour = Image.new('RGB', size=im_size, color='white')
# Check if internet is available
if internet_available() == True:
@@ -63,11 +63,11 @@ class Jokes(inkycal_module):
logger.debug(f"max_lines: {max_lines}")
# Calculate padding from top so the lines look centralised
spacing_top = int( im_height % line_height / 2 )
spacing_top = int(im_height % line_height / 2)
# Calculate line_positions
line_positions = [
(0, spacing_top + _ * line_height ) for _ in range(max_lines)]
(0, spacing_top + _ * line_height) for _ in range(max_lines)]
logger.debug(f'line positions: {line_positions}')
@@ -80,7 +80,7 @@ class Jokes(inkycal_module):
logger.debug(f"joke: {joke}")
# wrap text in case joke is too large
wrapped = text_wrap(joke, font = self.font, max_width = line_width)
wrapped = text_wrap(joke, font=self.font, max_width=line_width)
logger.debug(f"wrapped: {wrapped}")
# Check if joke can actually fit on the provided space
@@ -90,11 +90,11 @@ class Jokes(inkycal_module):
# Write the joke on the image
for _ in range(len(wrapped)):
if _+1 > max_lines:
if _ + 1 > max_lines:
logger.error('Ran out of lines for this joke :/')
break
write(im_black, line_positions[_], (line_width, line_height),
wrapped[_], font = self.font, alignment= 'left')
wrapped[_], font=self.font, alignment='left')
# Return images for black and colour channels
return im_black, im_colour

View File

@@ -1,5 +1,4 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
Inkycal-server module for Inkycal Project
@@ -17,6 +16,7 @@ from inkycal.modules.inky_image import Inkyimage as Images
filename = os.path.basename(__file__).split('.py')[0]
logger = logging.getLogger(filename)
class Inkyserver(inkycal_module):
"""Displays an image from URL or local path
"""
@@ -25,12 +25,12 @@ class Inkyserver(inkycal_module):
requires = {
"path":{
"path": {
"label": "Which URL should be used to get the image?"
},
"palette": {
"label":"Which palette should be used to convert the images?",
"label": "Which palette should be used to convert the images?",
"options": ['bw', 'bwr', 'bwy']
}
@@ -38,11 +38,11 @@ class Inkyserver(inkycal_module):
optional = {
"path_body":{
"label":"Send this data to the server via POST. Use a comma to "
"path_body": {
"label": "Send this data to the server via POST. Use a comma to "
"separate multiple items",
},
"dither":{
"dither": {
"label": "Dither images before sending to E-Paper? Default is False.",
"options": [False, True],
}
@@ -75,7 +75,6 @@ class Inkyserver(inkycal_module):
# give an OK message
print(f'{filename} loaded')
def generate_image(self):
"""Generate image for this module"""
@@ -110,7 +109,7 @@ class Inkyserver(inkycal_module):
im = Images(response)
# resize the image to respect padding
im.resize( width=im_width, height=im_height )
im.resize(width=im_width, height=im_height)
# convert image to given palette
im_black, im_colour = im.to_palette(self.palette, dither=self.dither)
@@ -121,6 +120,7 @@ class Inkyserver(inkycal_module):
# return images
return im_black, im_colour
if __name__ == '__main__':
print(f'running {filename} in standalone/debug mode')
@@ -131,4 +131,3 @@ if __name__ == '__main__':
##inkycal_image_path_body = [
## 'https://calendar.google.com/calendar/ical/en.usa%23holiday%40group.v.calendar.google.com/public/basic.ics',
## 'https

View File

@@ -1,5 +1,4 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
Image module for Inkycal Project
@@ -16,6 +15,7 @@ from inkycal.modules.inky_image import Inkyimage as Images
filename = os.path.basename(__file__).split('.py')[0]
logger = logging.getLogger(filename)
class Slideshow(inkycal_module):
"""Cycles through images in a local image folder
"""
@@ -23,13 +23,13 @@ class Slideshow(inkycal_module):
requires = {
"path":{
"label":"Path to a local folder, e.g. /home/pi/Desktop/images. "
"path": {
"label": "Path to a local folder, e.g. /home/pi/Desktop/images. "
"Only PNG and JPG/JPEG images are used for the slideshow."
},
"palette": {
"label":"Which palette should be used for converting images?",
"label": "Which palette should be used for converting images?",
"options": ["bw", "bwr", "bwy"]
}
@@ -37,12 +37,12 @@ class Slideshow(inkycal_module):
optional = {
"autoflip":{
"label":"Should the image be flipped automatically? Default is False",
"autoflip": {
"label": "Should the image be flipped automatically? Default is False",
"options": [False, True]
},
"orientation":{
"orientation": {
"label": "Please select the desired orientation",
"options": ["vertical", "horizontal"]
}
@@ -119,7 +119,7 @@ class Slideshow(inkycal_module):
im.autoflip(self.orientation)
# resize the image so it can fit on the epaper
im.resize( width=im_width, height=im_height )
im.resize(width=im_width, height=im_height)
# convert images according to specified palette
im_black, im_colour = im.to_palette(self.palette)
@@ -130,5 +130,6 @@ class Slideshow(inkycal_module):
# return images
return im_black, im_colour
if __name__ == '__main__':
print(f'running {filename} in standalone/debug mode')

View File

@@ -1,5 +1,5 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
Stocks Module for Inkycal Project
@@ -34,8 +34,8 @@ except ImportError:
logger = logging.getLogger(__name__)
class Stocks(inkycal_module):
class Stocks(inkycal_module):
name = "Stocks - Displays stock market infos from Yahoo finance"
# required parameters
@@ -59,7 +59,7 @@ class Stocks(inkycal_module):
# If tickers is a string from web-ui, convert to a list, else use
# tickers as-is i.e. for tests
if config['tickers'] and isinstance(config['tickers'], str):
self.tickers = config['tickers'].replace(" ", "").split(',') #returns list
self.tickers = config['tickers'].replace(" ", "").split(',') # returns list
else:
self.tickers = config['tickers']
@@ -76,8 +76,8 @@ class Stocks(inkycal_module):
logger.info(f'image size: {im_width} x {im_height} px')
# Create an image for black pixels and one for coloured pixels (required)
im_black = Image.new('RGB', size = im_size, color = 'white')
im_colour = Image.new('RGB', size = im_size, color = 'white')
im_black = Image.new('RGB', size=im_size, color='white')
im_colour = Image.new('RGB', size=im_size, color='white')
# Create tmp path
tmpPath = '/tmp/inkycal_stocks/'
@@ -85,9 +85,9 @@ class Stocks(inkycal_module):
try:
os.mkdir(tmpPath)
except OSError:
print (f"Creation of tmp directory {tmpPath} failed")
print(f"Creation of tmp directory {tmpPath} failed")
else:
print (f"Successfully created tmp directory {tmpPath} ")
print(f"Successfully created tmp directory {tmpPath} ")
# Check if internet is available
if internet_available() == True:
@@ -104,11 +104,11 @@ class Stocks(inkycal_module):
logger.debug(f"max_lines: {max_lines}")
# Calculate padding from top so the lines look centralised
spacing_top = int( im_height % line_height / 2 )
spacing_top = int(im_height % line_height / 2)
# Calculate line_positions
line_positions = [
(0, spacing_top + _ * line_height ) for _ in range(max_lines)]
(0, spacing_top + _ * line_height) for _ in range(max_lines)]
logger.debug(f'line positions: {line_positions}')
@@ -162,8 +162,8 @@ class Stocks(inkycal_module):
currentHigh = (stockHistory.tail(1)['High'].iloc[0])
currentLow = (stockHistory.tail(1)['Low'].iloc[0])
currentOpen = (stockHistory.tail(1)['Open'].iloc[0])
currentGain = currentQuote-previousQuote
currentGainPercentage = (1-currentQuote/previousQuote)*-100
currentGain = currentQuote - previousQuote
currentGainPercentage = (1 - currentQuote / previousQuote) * -100
firstQuote = stockHistory.tail(stockHistoryLen)['Close'].iloc[0]
logger.info(f'firstQuote {firstQuote} ...')
@@ -178,14 +178,16 @@ class Stocks(inkycal_module):
stockNameLine = '{} ({})'.format(stockName, stockCurrency)
stockCurrentValueLine = '{} {} {}'.format(
floatStr(precision, currentQuote), gainStr(precision, currentGain), percentageStr(currentGainPercentage))
floatStr(precision, currentQuote), gainStr(precision, currentGain),
percentageStr(currentGainPercentage))
stockDayValueLine = '1d OHL: {}/{}/{}'.format(
floatStr(precision, currentOpen), floatStr(precision, currentHigh), floatStr(precision, currentLow))
maxQuote = max(stockHistory.High)
minQuote = min(stockHistory.Low)
logger.info(f'high {maxQuote} low {minQuote} ...')
stockMonthValueLine = '{}d OHL: {}/{}/{}'.format(
stockHistoryLen,floatStr(precision, firstQuote),floatStr(precision, maxQuote),floatStr(precision, minQuote))
stockHistoryLen, floatStr(precision, firstQuote), floatStr(precision, maxQuote),
floatStr(precision, minQuote))
logger.info(stockNameLine)
logger.info(stockCurrentValueLine)
@@ -216,25 +218,25 @@ class Stocks(inkycal_module):
logger.info(f'creating chart data...')
chartData = stockHistory.reset_index()
chartCloseData = chartData.loc[:,'Close']
chartTimeData = chartData.loc[:,'Date']
chartCloseData = chartData.loc[:, 'Close']
chartTimeData = chartData.loc[:, 'Date']
logger.info(f'creating chart plot...')
fig, ax = plt.subplots() # Create a figure containing a single axes.
ax.plot(chartTimeData, chartCloseData, linewidth=8) # Plot some data on the axes.
ax.set_xticklabels([])
ax.set_yticklabels([])
chartPath = tmpPath+ticker+'.png'
chartPath = tmpPath + ticker + '.png'
logger.info(f'saving chart image to {chartPath}...')
plt.savefig(chartPath)
logger.info(f'chartSpace is...{im_width} {im_height}')
logger.info(f'open chart ...{chartPath}')
chartImage = Image.open(chartPath)
chartImage.thumbnail((im_width/4,line_height*4), Image.BICUBIC)
chartImage.thumbnail((im_width / 4, line_height * 4), Image.BICUBIC)
chartPasteX = im_width-(chartImage.width)
chartPasteY = line_height*5*_
chartPasteX = im_width - (chartImage.width)
chartPasteY = line_height * 5 * _
logger.info(f'pasting chart image with index {_} to...{chartPasteX} {chartPasteY}')
if firstQuote > currentQuote:
@@ -247,22 +249,23 @@ class Stocks(inkycal_module):
# Write/Draw something on the black image
for _ in range(len(parsed_tickers)):
if _+1 > max_lines:
if _ + 1 > max_lines:
logger.error('Ran out of lines for parsed_ticker_colour')
break
write(im_black, line_positions[_], (line_width, line_height),
parsed_tickers[_], font = self.font, alignment= 'left')
parsed_tickers[_], font=self.font, alignment='left')
# Write/Draw something on the colour image
for _ in range(len(parsed_tickers_colour)):
if _+1 > max_lines:
if _ + 1 > max_lines:
logger.error('Ran out of lines for parsed_tickers_colour')
break
write(im_colour, line_positions[_], (line_width, line_height),
parsed_tickers_colour[_], font = self.font, alignment= 'left')
parsed_tickers_colour[_], font=self.font, alignment='left')
# Save image of black and colour channel in image-folder
return im_black, im_colour
if __name__ == '__main__':
print('running module in standalone/debug mode')

View File

@@ -1,5 +1,4 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
todoist module for Inky-Calendar Project
@@ -18,6 +17,7 @@ except ImportError:
filename = os.path.basename(__file__).split('.py')[0]
logger = logging.getLogger(filename)
class Todoist(inkycal_module):
"""Todoist api class
parses todo's from api-key
@@ -27,13 +27,13 @@ class Todoist(inkycal_module):
requires = {
'api_key': {
"label":"Please enter your Todoist API-key",
"label": "Please enter your Todoist API-key",
},
}
optional = {
'project_filter': {
"label":"Show Todos only from following project (separated by a comma). Leave empty to show "+
"label": "Show Todos only from following project (separated by a comma). Leave empty to show " +
"todos from all projects",
}
}
@@ -80,8 +80,8 @@ class Todoist(inkycal_module):
logger.info(f'Image size: {im_size}')
# Create an image for black pixels and one for coloured pixels
im_black = Image.new('RGB', size = im_size, color = 'white')
im_colour = Image.new('RGB', size = im_size, color = 'white')
im_black = Image.new('RGB', size=im_size, color='white')
im_colour = Image.new('RGB', size=im_size, color='white')
# Check if internet is available
if internet_available() == True:
@@ -97,11 +97,11 @@ class Todoist(inkycal_module):
max_lines = (im_height // (self.font.getsize('hg')[1] + line_spacing))
# Calculate padding from top so the lines look centralised
spacing_top = int( im_height % line_height / 2 )
spacing_top = int(im_height % line_height / 2)
# Calculate line_positions
line_positions = [
(0, spacing_top + _ * line_height ) for _ in range(max_lines)]
(0, spacing_top + _ * line_height) for _ in range(max_lines)]
# Get all projects by name and id
all_projects = {project['id']: project['name']
@@ -128,15 +128,15 @@ class Todoist(inkycal_module):
# Create single-use generator to filter undone and non-deleted tasks
tasks = (task.data for task in self._api.state['items'] if
task['checked'] == 0 and task['is_deleted']==0)
task['checked'] == 0 and task['is_deleted'] == 0)
# Simplify the tasks for faster processing
simplified = [
{
'name':task['content'],
'due':task['due']['string'] if task['due'] != None else "",
'priority':task['priority'],
'project':all_projects[ task['project_id' ] ] if task['project_id'] in all_projects else "deleted"
'name': task['content'],
'due': task['due']['string'] if task['due'] != None else "",
'priority': task['priority'],
'project': all_projects[task['project_id']] if task['project_id'] in all_projects else "deleted"
}
for task in tasks]
@@ -147,11 +147,11 @@ class Todoist(inkycal_module):
# Get maximum width of project names for selected font
project_width = int(max([
self.font.getsize(task['project'])[0] for task in simplified ]) * 1.1)
self.font.getsize(task['project'])[0] for task in simplified]) * 1.1)
# Get maximum width of project dues for selected font
due_width = int(max([
self.font.getsize(task['due'])[0] for task in simplified ]) * 1.1)
self.font.getsize(task['due'])[0] for task in simplified]) * 1.1)
# Group tasks by project name
grouped = {name: [] for id_, name in all_projects.items()}
@@ -162,7 +162,6 @@ class Todoist(inkycal_module):
logger.debug(f"grouped: {grouped}")
# Add the parsed todos on the image
cursor = 0
for name, todos in grouped.items():
@@ -188,8 +187,8 @@ class Todoist(inkycal_module):
# Add todo name
write(
im_black,
(line_x+project_width+due_width, line_y),
(im_width-project_width-due_width, line_height),
(line_x + project_width + due_width, line_y),
(im_width - project_width - due_width, line_height),
todo['name'], font=self.font, alignment='left')
cursor += 1
@@ -200,5 +199,6 @@ class Todoist(inkycal_module):
# return the images ready for the display
return im_black, im_colour
if __name__ == '__main__':
print(f'running {filename} in standalone/debug mode')

View File

@@ -1,5 +1,5 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
Weather module for Inky-Calendar software.
Copyright by aceisace
@@ -21,6 +21,7 @@ except ImportError:
filename = os.path.basename(__file__).split('.py')[0]
logger = logging.getLogger(filename)
class Weather(inkycal_module):
"""Weather class
parses weather details from openweathermap
@@ -29,13 +30,13 @@ class Weather(inkycal_module):
requires = {
"api_key" : {
"label":"Please enter openweathermap api-key. You can create one for free on openweathermap",
"api_key": {
"label": "Please enter openweathermap api-key. You can create one for free on openweathermap",
},
"location": {
"label":"Please enter your location in the following format: City, Country-Code. "+
"You can also enter the location ID found in the url "+
"label": "Please enter your location in the following format: City, Country-Code. " +
"You can also enter the location ID found in the url " +
"e.g. https://openweathermap.org/city/4893171 -> ID is 4893171"
}
}
@@ -43,17 +44,17 @@ class Weather(inkycal_module):
optional = {
"round_temperature": {
"label":"Round temperature to the nearest degree?",
"label": "Round temperature to the nearest degree?",
"options": [True, False],
},
"round_windspeed": {
"label":"Round windspeed?",
"label": "Round windspeed?",
"options": [True, False],
},
"forecast_interval": {
"label":"Please select the forecast interval",
"label": "Please select the forecast interval",
"options": ["daily", "hourly"],
},
@@ -103,12 +104,11 @@ class Weather(inkycal_module):
self.timezone = get_system_tz()
self.locale = config['language']
self.weatherfont = ImageFont.truetype(
fonts['weathericons-regular-webfont'], size = self.fontsize)
fonts['weathericons-regular-webfont'], size=self.fontsize)
# give an OK message
print(f"{filename} loaded")
def generate_image(self):
"""Generate image for this module"""
@@ -119,8 +119,8 @@ class Weather(inkycal_module):
logger.info(f'Image size: {im_size}')
# Create an image for black pixels and one for coloured pixels
im_black = Image.new('RGB', size = im_size, color = 'white')
im_colour = Image.new('RGB', size = im_size, color = 'white')
im_black = Image.new('RGB', size=im_size, color='white')
im_colour = Image.new('RGB', size=im_size, color='white')
# Check if internet is available
if internet_available() == True:
@@ -138,9 +138,8 @@ class Weather(inkycal_module):
lunations = dec("0.20439731") + (days * dec("0.03386319269"))
position = lunations % dec(1)
index = math.floor((position * dec(8)) + dec("0.5"))
return {0: '\uf095',1: '\uf099',2: '\uf09c',3: '\uf0a0',
4: '\uf0a3',5: '\uf0a7',6: '\uf0aa',7: '\uf0ae' }[int(index) & 7]
return {0: '\uf095', 1: '\uf099', 2: '\uf09c', 3: '\uf0a0',
4: '\uf0a3', 5: '\uf0a7', 6: '\uf0aa', 7: '\uf0ae'}[int(index) & 7]
def is_negative(temp):
"""Check if temp is below freezing point of water (0°C/30°F)
@@ -163,15 +162,14 @@ class Weather(inkycal_module):
'11n': '\uf03b', '13n': '\uf038', '50n': '\uf023'
}
def draw_icon(image, xy, box_size, icon, rotation = None):
def draw_icon(image, xy, box_size, icon, rotation=None):
"""Custom function to add icons of weather font on image
image = on which image should the text be added?
xy = xy-coordinates as tuple -> (x,y)
box_size = size of text-box -> (width,height)
icon = icon-unicode, looks this up in weathericons dictionary
"""
x,y = xy
x, y = xy
box_width, box_height = box_size
text = icon
font = self.weatherfont
@@ -199,22 +197,19 @@ class Weather(inkycal_module):
ImageDraw.Draw(space).text((x, y), text, fill='black', font=font)
if rotation != None:
space.rotate(rotation, expand = True)
space.rotate(rotation, expand=True)
# Update only region with text (add text with transparent background)
image.paste(space, xy, space)
# column1 column2 column3 column4 column5 column6 column7
# |----------|----------|----------|----------|----------|----------|----------|
# | time | temperat.| moonphase| forecast1| forecast2| forecast3| forecast4|
# | current |----------|----------|----------|----------|----------|----------|
# | weather | humidity | sunrise | icon1 | icon2 | icon3 | icon4 |
# | icon |----------|----------|----------|----------|----------|----------|
# | | windspeed| sunset | temperat.| temperat.| temperat.| temperat.|
# |----------|----------|----------|----------|----------|----------|----------|
# column1 column2 column3 column4 column5 column6 column7
# |----------|----------|----------|----------|----------|----------|----------|
# | time | temperat.| moonphase| forecast1| forecast2| forecast3| forecast4|
# | current |----------|----------|----------|----------|----------|----------|
# | weather | humidity | sunrise | icon1 | icon2 | icon3 | icon4 |
# | icon |----------|----------|----------|----------|----------|----------|
# | | windspeed| sunset | temperat.| temperat.| temperat.| temperat.|
# |----------|----------|----------|----------|----------|----------|----------|
# Calculate size rows and columns
col_width = im_width // 7
@@ -226,13 +221,13 @@ class Weather(inkycal_module):
row_height = im_height // 3
else:
logger.info('Please consider decreasing the height.')
row_height = int( (im_height* (1-im_height/im_width)) / 3 )
row_height = int((im_height * (1 - im_height / im_width)) / 3)
logger.debug(f"row_height: {row_height} | col_width: {col_width}")
# Calculate spacings for better centering
spacing_top = int( (im_width % col_width) / 2 )
spacing_left = int( (im_height % row_height) / 2 )
spacing_top = int((im_width % col_width) / 2)
spacing_left = int((im_height % row_height) / 2)
# Define sizes for weather icons
icon_small = int(col_width / 3)
@@ -249,60 +244,59 @@ class Weather(inkycal_module):
col7 = col6 + col_width
# Calculate the y-axis position of each row
line_gap = int((im_height - spacing_top - 3*row_height) // 4)
line_gap = int((im_height - spacing_top - 3 * row_height) // 4)
row1 = line_gap
row2 = row1 + line_gap + row_height
row3 = row2+ line_gap + row_height
row3 = row2 + line_gap + row_height
# Draw lines on each row and border
############################################################################
## draw = ImageDraw.Draw(im_black)
## draw.line((0, 0, im_width, 0), fill='red')
## draw.line((0, im_height-1, im_width, im_height-1), fill='red')
## draw.line((0, row1, im_width, row1), fill='black')
## draw.line((0, row1+row_height, im_width, row1+row_height), fill='black')
## draw.line((0, row2, im_width, row2), fill='black')
## draw.line((0, row2+row_height, im_width, row2+row_height), fill='black')
## draw.line((0, row3, im_width, row3), fill='black')
## draw.line((0, row3+row_height, im_width, row3+row_height), fill='black')
############################################################################
############################################################################
## draw = ImageDraw.Draw(im_black)
## draw.line((0, 0, im_width, 0), fill='red')
## draw.line((0, im_height-1, im_width, im_height-1), fill='red')
## draw.line((0, row1, im_width, row1), fill='black')
## draw.line((0, row1+row_height, im_width, row1+row_height), fill='black')
## draw.line((0, row2, im_width, row2), fill='black')
## draw.line((0, row2+row_height, im_width, row2+row_height), fill='black')
## draw.line((0, row3, im_width, row3), fill='black')
## draw.line((0, row3+row_height, im_width, row3+row_height), fill='black')
############################################################################
# Positions for current weather details
weather_icon_pos = (col1, 0)
temperature_icon_pos = (col2, row1)
temperature_pos = (col2+icon_small, row1)
temperature_pos = (col2 + icon_small, row1)
humidity_icon_pos = (col2, row2)
humidity_pos = (col2+icon_small, row2)
humidity_pos = (col2 + icon_small, row2)
windspeed_icon_pos = (col2, row3)
windspeed_pos = (col2+icon_small, row3)
windspeed_pos = (col2 + icon_small, row3)
# Positions for sunrise, sunset, moonphase
moonphase_pos = (col3, row1)
sunrise_icon_pos = (col3, row2)
sunrise_time_pos = (col3+icon_small, row2)
sunrise_time_pos = (col3 + icon_small, row2)
sunset_icon_pos = (col3, row3)
sunset_time_pos = (col3+ icon_small, row3)
sunset_time_pos = (col3 + icon_small, row3)
# Positions for forecast 1
stamp_fc1 = (col4, row1)
icon_fc1 = (col4, row1+row_height)
icon_fc1 = (col4, row1 + row_height)
temp_fc1 = (col4, row3)
# Positions for forecast 2
stamp_fc2 = (col5, row1)
icon_fc2 = (col5, row1+row_height)
icon_fc2 = (col5, row1 + row_height)
temp_fc2 = (col5, row3)
# Positions for forecast 3
stamp_fc3 = (col6, row1)
icon_fc3 = (col6, row1+row_height)
icon_fc3 = (col6, row1 + row_height)
temp_fc3 = (col6, row3)
# Positions for forecast 4
stamp_fc4 = (col7, row1)
icon_fc4 = (col7, row1+row_height)
icon_fc4 = (col7, row1 + row_height)
temp_fc4 = (col7, row3)
# Create current-weather and weather-forecast objects
@@ -343,8 +337,8 @@ class Weather(inkycal_module):
hour_gap = 3
# Create timings for hourly forcasts
forecast_timings = [now.shift(hours = + hour_gap + _).floor('hour')
for _ in range(0,12,3)]
forecast_timings = [now.shift(hours=+ hour_gap + _).floor('hour')
for _ in range(0, 12, 3)]
# Create forecast objects for given timings
forecasts = [forecast.get_weather_at(forecast_time.datetime) for
@@ -357,9 +351,9 @@ class Weather(inkycal_module):
forecast.temperature(unit=temp_unit)['temp'], ndigits=dec_temp))
icon = forecast.weather_icon_name
fc_data['fc'+str(forecasts.index(forecast)+1)] = {
'temp':temp,
'icon':icon,
fc_data['fc' + str(forecasts.index(forecast) + 1)] = {
'temp': temp,
'icon': icon,
'stamp': forecast_timings[forecasts.index(forecast)].to(
get_system_tz()).format('H.00' if self.hour_format == 24 else 'h a')
}
@@ -368,7 +362,6 @@ class Weather(inkycal_module):
logger.debug("getting daily forecasts")
def calculate_forecast(days_from_today):
"""Get temperature range and most frequent icon code for forecast
days_from_today should be int from 1-4: e.g. 2 -> 2 days from today
@@ -389,7 +382,6 @@ class Weather(inkycal_module):
# Calculate min. and max. temp for this day
temp_range = f'{max(daily_temp)}°/{min(daily_temp)}°'
# Get all weather icon codes for this day
daily_icons = [_.weather_icon_name for _ in forecasts]
# Find most common element from all weather icon codes
@@ -397,20 +389,20 @@ class Weather(inkycal_module):
weekday = now.shift(days=days_from_today).format('ddd', locale=
self.locale)
return {'temp':temp_range, 'icon':status, 'stamp': weekday}
return {'temp': temp_range, 'icon': status, 'stamp': weekday}
forecasts = [calculate_forecast(days) for days in range (1,5)]
forecasts = [calculate_forecast(days) for days in range(1, 5)]
fc_data = {}
for forecast in forecasts:
fc_data['fc'+str(forecasts.index(forecast)+1)] = {
'temp':forecast['temp'],
'icon':forecast['icon'],
fc_data['fc' + str(forecasts.index(forecast) + 1)] = {
'temp': forecast['temp'],
'icon': forecast['icon'],
'stamp': forecast['stamp']
}
for key,val in fc_data.items():
logger.debug((key,val))
for key, val in fc_data.items():
logger.debug((key, val))
# Get some current weather details
temperature = '{}°'.format(round(
@@ -460,63 +452,63 @@ class Weather(inkycal_module):
'\uf053')
if is_negative(temperature):
write(im_black, temperature_pos, (col_width-icon_small, row_height),
temperature, font = self.font)
write(im_black, temperature_pos, (col_width - icon_small, row_height),
temperature, font=self.font)
else:
write(im_black, temperature_pos, (col_width-icon_small, row_height),
temperature, font = self.font)
write(im_black, temperature_pos, (col_width - icon_small, row_height),
temperature, font=self.font)
draw_icon(im_colour, humidity_icon_pos, (icon_small, row_height),
'\uf07a')
write(im_black, humidity_pos, (col_width-icon_small, row_height),
humidity+'%', font = self.font)
write(im_black, humidity_pos, (col_width - icon_small, row_height),
humidity + '%', font=self.font)
draw_icon(im_colour, windspeed_icon_pos, (icon_small, icon_small),
'\uf050')
write(im_black, windspeed_pos, (col_width-icon_small, row_height),
write(im_black, windspeed_pos, (col_width - icon_small, row_height),
wind, font=self.font)
# Fill weather details in col 3 (moonphase, sunrise, sunset)
draw_icon(im_colour, moonphase_pos, (col_width, row_height), moonphase)
draw_icon(im_colour, sunrise_icon_pos, (icon_small, icon_small), '\uf051')
write(im_black, sunrise_time_pos, (col_width-icon_small, row_height),
sunrise, font = self.font)
write(im_black, sunrise_time_pos, (col_width - icon_small, row_height),
sunrise, font=self.font)
draw_icon(im_colour, sunset_icon_pos, (icon_small, icon_small), '\uf052')
write(im_black, sunset_time_pos, (col_width-icon_small, row_height), sunset,
font = self.font)
write(im_black, sunset_time_pos, (col_width - icon_small, row_height), sunset,
font=self.font)
# Add the forecast data to the correct places
for pos in range(1, len(fc_data)+1):
for pos in range(1, len(fc_data) + 1):
stamp = fc_data[f'fc{pos}']['stamp']
icon = weathericons[fc_data[f'fc{pos}']['icon']]
temp = fc_data[f'fc{pos}']['temp']
write(im_black, eval(f'stamp_fc{pos}'), (col_width, row_height),
stamp, font = self.font)
draw_icon(im_colour, eval(f'icon_fc{pos}'), (col_width, row_height+line_gap*2),
stamp, font=self.font)
draw_icon(im_colour, eval(f'icon_fc{pos}'), (col_width, row_height + line_gap * 2),
icon)
write(im_black, eval(f'temp_fc{pos}'), (col_width, row_height),
temp, font = self.font)
temp, font=self.font)
border_h = row3 + row_height
border_w = col_width - 3 #leave 3 pixels gap
border_w = col_width - 3 # leave 3 pixels gap
# Add borders around each sub-section
draw_border(im_black, (col1, row1), (col_width*3 - 3, border_h),
shrinkage=(0,0))
draw_border(im_black, (col1, row1), (col_width * 3 - 3, border_h),
shrinkage=(0, 0))
for _ in range(4,8):
for _ in range(4, 8):
draw_border(im_black, (eval(f'col{_}'), row1), (border_w, border_h),
shrinkage=(0,0))
shrinkage=(0, 0))
# return the images ready for the display
return im_black, im_colour
if __name__ == '__main__':
print(f'running {filename} in standalone mode')

View File

@@ -1,6 +1,9 @@
#!python3
import abc
from inkycal.custom import *
class inkycal_module(metaclass=abc.ABCMeta):
"""Generic base class for inkycal modules"""
@@ -23,7 +26,7 @@ class inkycal_module(metaclass=abc.ABCMeta):
self.fontsize = conf["fontsize"]
self.font = ImageFont.truetype(
fonts['NotoSansUI-Regular'], size = self.fontsize)
fonts['NotoSansUI-Regular'], size=self.fontsize)
def set(self, help=False, **kwargs):
"""Set attributes of class, e.g. class.set(key=value)
@@ -87,6 +90,3 @@ class inkycal_module(metaclass=abc.ABCMeta):
except:
raise Exception(
'Ohoh, something went wrong while trying to get the config of this module')

View File

@@ -1,5 +1,4 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
iCalendar parser test (ical_parser)
@@ -14,10 +13,10 @@ from urllib.request import urlopen
from inkycal.modules.ical_parser import iCalendar
from helper_functions import *
ical = iCalendar()
test_ical = 'https://calendar.google.com/calendar/ical/en.usa%23holiday%40group.v.calendar.google.com/public/basic.ics'
class ical_parser_test(unittest.TestCase):
def test_load_url(self):
@@ -49,8 +48,8 @@ class ical_parser_test(unittest.TestCase):
print('OK')
os.remove('dummy.ical')
if __name__ == '__main__':
if __name__ == '__main__':
logger = logging.getLogger()
logger.level = logging.DEBUG
logger.addHandler(logging.StreamHandler(sys.stdout))

View File

@@ -1,5 +1,5 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
Agenda test (inkycal_agenda)
Copyright by aceisace
@@ -7,16 +7,16 @@ Copyright by aceisace
import unittest
from inkycal.modules import Agenda as Module
from helper_functions import *
environment = get_environment()
# Set to True to preview images. Only works on Raspberry Pi OS with Desktop
use_preview = False
sample_url = "https://www.officeholidays.com/ics-fed/usa"
tests = [
{
{
"name": "Agenda",
"config": {
"size": [400, 200],
@@ -29,8 +29,8 @@ tests = [
"fontsize": 12,
"language": "en"
}
},
{
},
{
"name": "Agenda",
"config": {
"size": [500, 800],
@@ -43,8 +43,8 @@ tests = [
"fontsize": 12,
"language": "en"
}
},
{
},
{
"position": 1,
"name": "Agenda",
"config": {
@@ -58,27 +58,27 @@ tests = [
"fontsize": 12,
"language": "en"
}
},
},
]
class module_test(unittest.TestCase):
def test_get_config(self):
print('getting data for web-ui...', end = "")
print('getting data for web-ui...', end="")
Module.get_config()
print('OK')
def test_generate_image(self):
for test in tests:
print(f'test {tests.index(test)+1} generating image..')
print(f'test {tests.index(test) + 1} generating image..')
module = Module(test)
im_black, im_colour = module.generate_image()
print('OK')
if use_preview == True and environment == 'Raspberry':
preview(merge(im_black, im_colour))
if __name__ == '__main__':
if __name__ == '__main__':
logger = logging.getLogger()
logger.level = logging.DEBUG
logger.addHandler(logging.StreamHandler(sys.stdout))

View File

@@ -1,5 +1,4 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
Calendar test (inkycal_calendar)
@@ -9,16 +8,16 @@ Copyright by aceisace
import unittest
from inkycal.modules import Calendar as Module
from helper_functions import *
environment = get_environment()
# Set to True to preview images. Only works on Raspberry Pi OS with Desktop
use_preview = False
sample_url = "https://www.officeholidays.com/ics-fed/usa"
tests = [
{
{
"name": "Calendar",
"config": {
"size": [500, 500],
@@ -27,10 +26,10 @@ tests = [
"ical_urls": sample_url,
"ical_files": None,
"date_format": "D MMM", "time_format": "HH:mm",
"padding_x": 10,"padding_y": 10,"fontsize": 12,"language": "en"
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
}
},
{
},
{
"name": "Calendar",
"config": {
"size": [400, 800],
@@ -39,10 +38,10 @@ tests = [
"ical_urls": sample_url,
"ical_files": None,
"date_format": "D MMM", "time_format": "HH:mm",
"padding_x": 10,"padding_y": 10,"fontsize": 12,"language": "en"
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
}
},
{
},
{
"name": "Calendar",
"config": {
"size": [400, 800],
@@ -51,10 +50,10 @@ tests = [
"ical_urls": sample_url,
"ical_files": None,
"date_format": "D MMM", "time_format": "HH:mm",
"padding_x": 10,"padding_y": 10,"fontsize": 12,"language": "en"
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
}
},
{
},
{
"name": "Calendar",
"config": {
"size": [400, 800],
@@ -63,28 +62,29 @@ tests = [
"ical_urls": None,
"ical_files": None,
"date_format": "D MMM", "time_format": "HH:mm",
"padding_x": 10,"padding_y": 10,"fontsize": 12,"language": "en"
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
}
},
},
]
class module_test(unittest.TestCase):
def test_get_config(self):
print('getting data for web-ui...', end = "")
print('getting data for web-ui...', end="")
Module.get_config()
print('OK')
def test_generate_image(self):
for test in tests:
print(f'test {tests.index(test)+1} generating image..', end="")
print(f'test {tests.index(test) + 1} generating image..', end="")
module = Module(test)
im_black, im_colour = module.generate_image()
print('OK')
if use_preview == True and environment == 'Raspberry':
preview(merge(im_black, im_colour))
if __name__ == '__main__':
if __name__ == '__main__':
logger = logging.getLogger()
logger.level = logging.DEBUG
logger.addHandler(logging.StreamHandler(sys.stdout))

View File

@@ -1,5 +1,4 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
Feeds test (inykcal_feeds)
@@ -9,61 +8,62 @@ Copyright by aceisace
import unittest
from inkycal.modules import Feeds as Module
from helper_functions import *
environment = get_environment()
# Set to True to preview images. Only works on Raspberry Pi OS with Desktop
use_preview = False
tests = [
{
{
"name": "Feeds",
"config": {
"size": [400,200],
"size": [400, 200],
"feed_urls": "http://feeds.bbci.co.uk/news/world/rss.xml#",
"shuffle_feeds": True,
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
}
},
{
},
{
"name": "Feeds",
"config": {
"size": [400,100],
"size": [400, 100],
"feed_urls": "http://feeds.bbci.co.uk/news/world/rss.xml#",
"shuffle_feeds": False,
"padding_x": 10, "padding_y": 10, "fontsize": 14, "language": "en"
}
},
{
},
{
"name": "Feeds",
"config": {
"size": [400,100],
"size": [400, 100],
"feed_urls": "https://www.anekdot.ru/rss/export_top.xml",
"shuffle_feeds": False,
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
}
},
},
]
class module_test(unittest.TestCase):
def test_get_config(self):
print('getting data for web-ui...', end = "")
print('getting data for web-ui...', end="")
Module.get_config()
print('OK')
def test_generate_image(self):
for test in tests:
print(f'test {tests.index(test)+1} generating image..')
print(f'test {tests.index(test) + 1} generating image..')
module = Module(test)
im_black, im_colour = module.generate_image()
print('OK')
if use_preview == True and environment == 'Raspberry':
preview(merge(im_black, im_colour))
if __name__ == '__main__':
if __name__ == '__main__':
logger = logging.getLogger()
logger.level = logging.DEBUG
logger.addHandler(logging.StreamHandler(sys.stdout))
unittest.main()

View File

@@ -1,5 +1,4 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
Image test (inkycal_image)
@@ -10,71 +9,71 @@ import unittest
from inkycal.modules import Inkyimage as Module
from inkycal.custom import top_level
from helper_functions import *
environment = get_environment()
# Set to True to preview images. Only works on Raspberry Pi OS with Desktop
use_preview = False
test_path = f'{top_level}/Gallery/coffee.png'
tests = [
{
{
"name": "Inkyimage",
"config": {
"size": [400,200],
"size": [400, 200],
"path": test_path,
"palette": "bwr",
"autoflip": True,
"orientation": "vertical",
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
}
},
{
},
{
"name": "Inkyimage",
"config": {
"size": [800,500],
"size": [800, 500],
"path": test_path,
"palette": "bwy",
"autoflip": True,
"orientation": "vertical",
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
}
},
{
},
{
"name": "Inkyimage",
"config": {
"size": [400,100],
"size": [400, 100],
"path": test_path,
"palette": "bw",
"autoflip": False,
"orientation": "vertical",
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
}
},
{
},
{
"name": "Inkyimage",
"config": {
"size": [400,100],
"size": [400, 100],
"path": test_path,
"palette": "bwr",
"autoflip": True,
"orientation": "vertical",
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
}
},
{
},
{
"name": "Inkyimage",
"config": {
"size": [400,100],
"size": [400, 100],
"path": test_path,
"palette": "bwy",
"autoflip": True,
"orientation": "horizontal",
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
}
},
{
},
{
"name": "Inkyimage",
"config": {
"size": [500, 800],
@@ -84,8 +83,8 @@ tests = [
"orientation": "vertical",
"padding_x": 0, "padding_y": 0, "fontsize": 12, "language": "en"
}
},
{
},
{
"name": "Inkyimage",
"config": {
"size": [500, 800],
@@ -95,26 +94,27 @@ tests = [
"orientation": "vertical",
"padding_x": 20, "padding_y": 20, "fontsize": 12, "language": "en"
}
},
},
]
class module_test(unittest.TestCase):
def test_get_config(self):
print('getting data for web-ui...', end = "")
print('getting data for web-ui...', end="")
Module.get_config()
print('OK')
def test_generate_image(self):
for test in tests:
print(f'test {tests.index(test)+1} generating image..')
print(f'test {tests.index(test) + 1} generating image..')
module = Module(test)
im_black, im_colour = module.generate_image()
print('OK')
if use_preview == True and environment == 'Raspberry':
preview(merge(im_black, im_colour))
if __name__ == '__main__':
if __name__ == '__main__':
logger = logging.getLogger()
logger.level = logging.DEBUG
logger.addHandler(logging.StreamHandler(sys.stdout))

View File

@@ -1,5 +1,4 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
Jokes test (inkycal_jokes)

View File

@@ -1,5 +1,4 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
Slideshow test (inkycal_slideshow)

View File

@@ -1,5 +1,4 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
Stocks test (inkycal_stocks)
@@ -9,80 +8,81 @@ Copyright by aceisace
import unittest
from inkycal.modules import Stocks as Module
from helper_functions import *
environment = get_environment()
# Set to True to preview images. Only works on Raspberry Pi OS with Desktop
use_preview = False
tests = [
{
{
"name": "Stocks",
"config": {
"size": [528, 30],
"tickers": ['TSLA', 'AMD', 'NVDA', '^DJI', 'BTC-USD', 'EURUSD=X'],
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
}
},
{
},
{
"name": "Stocks",
"config": {
"size": [528, 50],
"tickers": [],
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
}
},
{
},
{
"name": "Stocks",
"config": {
"size": [528, 200],
"tickers": ['TSLA', 'AMD', 'NVDA', '^DJI', 'BTC-USD', 'EURUSD=X'],
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
}
},
{
},
{
"name": "Stocks",
"config": {
"size": [528, 800],
"tickers": ['TSLA', 'AMD', 'NVDA', '^DJI', 'BTC-USD', 'EURUSD=X'],
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
}
},
{
},
{
"name": "Stocks",
"config": {
"size": [528, 100],
"tickers": "TSLA,AMD,NVDA,^DJI,BTC-USD,EURUSD=X",
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
}
},
{
},
{
"name": "Stocks",
"config": {
"size": [528, 400],
"tickers": ['TSLA', 'AMD', 'NVDA', '^DJI', 'BTC-USD', 'EURUSD=X'],
"padding_x": 10, "padding_y": 10, "fontsize": 14, "language": "en"
}
},
},
]
class module_test(unittest.TestCase):
def test_get_config(self):
print('getting data for web-ui...', end = "")
print('getting data for web-ui...', end="")
Module.get_config()
print('OK')
def test_generate_image(self):
for test in tests:
print(f'test {tests.index(test)+1} generating image..')
print(f'test {tests.index(test) + 1} generating image..')
module = Module(test)
im_black, im_colour = module.generate_image()
print('OK')
if use_preview == True and environment == 'Raspberry':
preview(merge(im_black, im_colour))
if __name__ == '__main__':
if __name__ == '__main__':
logger = logging.getLogger()
logger.level = logging.DEBUG
logger.addHandler(logging.StreamHandler(sys.stdout))

View File

@@ -1,2 +0,0 @@
import unittest
from inkycal.modules import Todoist as Module

View File

@@ -1,3 +1,5 @@
#!python3
import unittest
from inkycal.modules import Todoist as Module
from helper_functions import *

View File

@@ -1,3 +1,5 @@
#!python3
import unittest
from inkycal.modules import Weather as Module
from helper_functions import *

View File

@@ -1,5 +1,4 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#!python3
"""
Main test (main)

View File

@@ -1,5 +1,4 @@
#!python3
# -*- coding: utf-8 -*-
from setuptools import setup
from os import path