Improved formatting
This commit is contained in:
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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 ###
|
||||
|
||||
|
@@ -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 ###
|
||||
|
||||
|
@@ -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 ###
|
||||
|
@@ -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 ###
|
||||
|
||||
|
@@ -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 ###
|
||||
|
||||
|
@@ -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 ###
|
||||
|
||||
|
@@ -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 ###
|
||||
|
||||
|
@@ -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 ###
|
||||
|
||||
|
@@ -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();
|
||||
|
@@ -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()
|
||||
|
@@ -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 ###
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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"""
|
||||
|
||||
|
@@ -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')
|
||||
|
||||
|
@@ -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')
|
||||
|
@@ -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')
|
||||
|
@@ -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')
|
||||
|
@@ -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')
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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')
|
||||
|
@@ -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')
|
||||
|
@@ -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')
|
||||
|
@@ -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')
|
||||
|
@@ -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')
|
||||
|
||||
|
||||
|
||||
|
@@ -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))
|
||||
|
@@ -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))
|
||||
|
@@ -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))
|
||||
|
@@ -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()
|
||||
|
||||
|
@@ -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))
|
||||
|
@@ -1,5 +1,4 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#!python3
|
||||
|
||||
"""
|
||||
Jokes test (inkycal_jokes)
|
||||
|
@@ -1,5 +1,4 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#!python3
|
||||
|
||||
"""
|
||||
Slideshow test (inkycal_slideshow)
|
||||
|
@@ -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))
|
||||
|
@@ -1,2 +0,0 @@
|
||||
import unittest
|
||||
from inkycal.modules import Todoist as Module
|
@@ -1,3 +1,5 @@
|
||||
#!python3
|
||||
|
||||
import unittest
|
||||
from inkycal.modules import Todoist as Module
|
||||
from helper_functions import *
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#!python3
|
||||
|
||||
import unittest
|
||||
from inkycal.modules import Weather as Module
|
||||
from helper_functions import *
|
||||
|
@@ -1,5 +1,4 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#!python3
|
||||
|
||||
"""
|
||||
Main test (main)
|
||||
|
Reference in New Issue
Block a user