#!/usr/bin/env python3 import random import time import sys import threading from PIL import Image, ImageDraw, ImageFont, ImageColor import requests from framebuffer import Framebuffer import subprocess class TextBox: def __init__(self, pos, size, max_jitter, color, background, fitting_text): self.color = color self.background = background self.pos = pos self.bounds = (size[0]+1, size[1]+1) font_size = 100 while (self.bounds[0] > size[0]-max_jitter) or (self.bounds[1] > size[1]-max_jitter): font_size-=1 self.font = ImageFont.truetype("/usr/share/fonts/truetype/noto/NotoMono-Regular.ttf", font_size) self.bounds = self.font.getsize(fitting_text) self.size = size self.img = Image.new("RGB", self.bounds) self.draw = ImageDraw.Draw(self.img) self.offset = (int((self.size[0]-self.bounds[0])/2), int((self.size[1]-self.bounds[1])/2)) def draw_text(self, target_img, text, jitter_pos): self.draw.rectangle((0, 0, self.img.width-1, self.img.height-1), self.background, self.background, 1) self.draw.text((jitter_pos[0],0), text, font=self.font, fill=self.color) x=self.pos[0]+self.offset[0] y=self.pos[1]+self.offset[1] target_img.paste(self.img, (x,y)) ### # CONFIGURATION ### DISPLAY_SIZE=(320,240) CLOCK_FORMAT = "%H:%M" TEMP_FORMAT = "% 3.1f°C" BKGND_COLOR=(0,0,0) LINE_COLOR=(255,255,255) JITTER=5 DELAY=0.3 TEMP_DELAY=10 GPIO_TOOL=['gpio','-g'] PWM_MODE=['mode','18','pwm'] DAY_BRIGHT=['pwm','18','800'] NIGHT_BRIGHT=['pwm','18','200'] now_parts=time.localtime() time_str = time.strftime(CLOCK_FORMAT, now_parts) temp_str = TEMP_FORMAT % -10.0 clock_box=TextBox( (10,10), (300,120), JITTER, (255,255,255), BKGND_COLOR, time_str) temp_box =TextBox( (100,160), (200,60), JITTER, (255,0,0), BKGND_COLOR, temp_str) display = Framebuffer(1) fb_img = Image.new(mode="RGB", size=DISPLAY_SIZE) fb_draw = ImageDraw.Draw(fb_img) mean_temp = 0 def fetch_temp(bridge, user, sensor): try: r=requests.get(f"http://{bridge}/api/{user}/sensors/{str(sensor)}") except requests.exceptions.ConnectionError: r=None if r: json = r.json() if 'state' in json and 'temperature' in json['state'] and json['state']['temperature']: return json["state"]["temperature"]/100 return None def jitter(): return (random.randint(0,JITTER), random.randint(0,JITTER)) def set_brightness(now_parts): if now_parts.tm_hour > 7 and now_parts.tm_hour < 19: subprocess.run(GPIO_TOOL+DAY_BRIGHT) else: subprocess.run(GPIO_TOOL+NIGHT_BRIGHT) # Main loop: jitter_pos = jitter() old_time="" old_temp="" subprocess.run(GPIO_TOOL+PWM_MODE) set_brightness(now_parts) fb_draw.rectangle(((0,0),DISPLAY_SIZE),BKGND_COLOR, BKGND_COLOR,1) temp_time=time.time() try: while True: changed = False now = time.time() now_parts = time.localtime(now) time_str = time.strftime(CLOCK_FORMAT, now_parts) if now-temp_time > TEMP_DELAY: cur_temp = fetch_temp("philips-hue", "GQ03rw1saUS0n88G5yj9j7-TsteFIE1yxtlBOgzD", 71) if cur_temp: mean_temp = cur_temp temp_time = now temp_str = TEMP_FORMAT % mean_temp else: temp_str = "---" if now_parts.tm_sec == 0: jitter_pos = jitter() if now_parts.tm_min == 0: set_brightness(now_parts) if time_str != old_time: clock_box.draw_text(fb_img, time_str, jitter_pos) old_time = time_str changed = True if temp_str != old_temp: temp_box.draw_text(fb_img, temp_str, jitter_pos) old_temp = temp_str changed=True if changed: display.show(fb_img) while time.time() - now < DELAY: time.sleep(DELAY) except KeyboardInterrupt: clock_box.draw_text(fb_img, "off" ,(0,0)) temp_box.draw_text(fb_img,"",(0,0)) display.show(fb_img) subprocess.run(GPIO_TOOL+NIGHT_BRIGHT)