-
Notifications
You must be signed in to change notification settings - Fork 7
/
epaper-clock.py
executable file
·179 lines (147 loc) · 6.36 KB
/
epaper-clock.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#!/usr/bin/env python3
##
# epaper-clock.py - smart clock / system monitor and more
#
# Copyright (C) Emanuele Goldoni 2020
#
# Released under the Apache License, Version 2.0
##
import epd2in7
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
import RPi.GPIO as GPIO
from datetime import datetime
import time
import locale
import subprocess
import psutil
import socket
import os
import json
import random
import textwrap
RES_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'resources/')
DATEFORMAT = "%a %x"
TIMEFORMAT = "%H:%M"
FONT = os.path.join(RES_DIR, 'FreeMono.ttf')
FONTBOLD = os.path.join(RES_DIR, 'FreeMonoBold.ttf')
BOUNCETIME = 500
NOBELPRIZE_JSON = os.path.join(RES_DIR, 'prize.json')
RASPBERRY_BMP_LOGO = os.path.join(RES_DIR, 'raspberry.bmp')
PIN_BTN1 = 5
PIN_BTN2 = 6
PIN_BTN3 = 13
PIN_BTN4 = 19
DISPMODE_LOGO = 1
DISPMODE_SYSSTATS = 2
DISPMODE_CLOCK = 3
DISPMODE_NOBEL = 4
class Fonts:
def __init__(self, timefont_size, datefont_size, infofont_size, smallfont_size):
self.timefont = ImageFont.truetype(FONTBOLD, timefont_size)
self.datefont = ImageFont.truetype(FONTBOLD, datefont_size)
self.infofont = ImageFont.truetype(FONTBOLD, infofont_size)
self.smallfont = ImageFont.truetype(FONT, smallfont_size)
class Display:
epd = None
fonts = None
mode = DISPMODE_LOGO
nobeldata = None
def __init__(self):
locale.setlocale(locale.LC_ALL, '')
self.fonts = Fonts(timefont_size = 75, datefont_size = 26, infofont_size = 18, smallfont_size=16)
with open(NOBELPRIZE_JSON) as f:
self.nobeldata = json.load(f)
self.epd = epd2in7.EPD()
self.epd.init()
self.read_buttons()
def start(self, start_mode = DISPMODE_LOGO):
self.mode = start_mode
while True:
if DISPMODE_SYSSTATS == self.mode:
self.draw_system_data()
elif DISPMODE_CLOCK == self.mode:
self.draw_clock_data()
elif DISPMODE_NOBEL == self.mode:
self.draw_rnd_nobel_info()
else:
self.mode = DISPMODE_LOGO
self.draw_rpi_logo()
self.sleep_until_next_min()
def sleep_until_next_min(self):
now = datetime.now()
seconds_until_next_minute = 60 - now.time().second
time.sleep(seconds_until_next_minute)
def draw_rpi_logo(self):
Himage = Image.open(RASPBERRY_BMP_LOGO)
self.epd.display(self.epd.getbuffer(Himage))
def draw_clock_data(self):
datetime_now = datetime.now()
datestring = datetime_now.strftime(DATEFORMAT).capitalize()
timestring = datetime_now.strftime(TIMEFORMAT)
Limage = Image.new('1', (self.epd.height, self.epd.width), 255) # 255: clear the frame
draw = ImageDraw.Draw(Limage)
draw.text((20, 20), timestring, font = self.fonts.timefont, fill = 0)
draw.text((20, 100), datestring, font = self.fonts.datefont, fill = 0)
self.epd.display(self.epd.getbuffer(Limage))
def draw_system_data(self):
corestring = 'CPU freq: ' + str(psutil.cpu_freq().current) + ' MHz';
usagestring = 'CPU usage: ' + str(psutil.cpu_percent());
tempstring = 'CPU temp. ' + str(round(psutil.sensors_temperatures(fahrenheit=False)['cpu_thermal'][0].current)) + ' \u00b0C';
memstring = 'Free RAM: ' + str(int(psutil.virtual_memory().available/(1024*1024))) + ' MiB';
psstring = 'Running ps: ' + str(len(psutil.pids()))
#iflist = [name for name in psutil.net_if_addrs().keys()]
ifaddresses = [ifname+' '+str(ip.address) for ifname in psutil.net_if_addrs().keys() for ip in psutil.net_if_addrs()[ifname] if ip.family == socket.AF_INET]
sysstring = corestring + '\n' + usagestring + '\n' + tempstring + '\n' + memstring + '\n' + psstring
netstring = '\n'.join(ifaddresses)
Limage = Image.new('1', (self.epd.height, self.epd.width), 255)
draw = ImageDraw.Draw(Limage)
draw.text((10, 10), sysstring, font = self.fonts.infofont, fill = 0)
draw.text((10, 110), netstring, font = self.fonts.infofont, fill = 0)
self.epd.display(self.epd.getbuffer(Limage))
def draw_rnd_nobel_info(self):
p = random.choice(self.nobeldata['prizes'])
#print(p) #just debugging
y = p['year']
c = p['category'].title()
if ('laureates' in p.keys()):
w = random.choice(p['laureates'])
n = w['firstname']
n += ' '+w['surname'] if 'surname' in w.keys() else ""
m = w['motivation']
else:
n = ""
m = p['overallMotivation']
Limage = Image.new('1', (self.epd.height, self.epd.width), 255)
draw = ImageDraw.Draw(Limage)
draw.text((5, 5), c + ' (' + y + ')', font = self.fonts.infofont, fill = 0)
draw.text((5, 27), n, font = self.fonts.infofont, fill = 0)
draw.text((5, 50), textwrap.fill(textwrap.shorten(m, 140), 25), font = self.fonts.smallfont, fill = 0)
self.epd.display(self.epd.getbuffer(Limage))
def read_buttons(self):
GPIO.setmode(GPIO.BCM)
GPIO.setup(PIN_BTN1, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(PIN_BTN1, GPIO.FALLING, callback=self.button_pressed, bouncetime=BOUNCETIME)
GPIO.setup(PIN_BTN2, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(PIN_BTN2, GPIO.FALLING, callback=self.button_pressed, bouncetime=BOUNCETIME)
GPIO.setup(PIN_BTN3, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(PIN_BTN3, GPIO.FALLING, callback=self.button_pressed, bouncetime=BOUNCETIME)
GPIO.setup(PIN_BTN4, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(PIN_BTN4, GPIO.FALLING, callback=self.button_pressed, bouncetime=BOUNCETIME)
def button_pressed(self, pin):
if PIN_BTN1 == pin:
self.mode = DISPMODE_LOGO
self.draw_rpi_logo()
elif PIN_BTN2 == pin:
self.mode = DISPMODE_SYSSTATS
self.draw_system_data()
elif PIN_BTN3 == pin:
self.mode = DISPMODE_CLOCK
self.draw_clock_data()
elif PIN_BTN4 == pin:
self.mode = DISPMODE_NOBEL
self.draw_rnd_nobel_info()
if __name__ == '__main__':
display = Display()
display.start(DISPMODE_CLOCK)