#!/usr/bin/env python # coding: utf-8 # #################################################################################### # # this file is deprecated and replaced by the c implementation for performance reasons # # #################################################################################### # import re import time import json from datetime import datetime, timedelta from PIL import Image import errno from socket import error as socket_error from luma.led_matrix.device import max7219 from luma.core.interface.serial import spi, noop from luma.core.render import canvas from luma.core.virtual import viewport from luma.core.legacy import text, show_message, textsize from luma.core.sprite_system import framerate_regulator from luma.core.legacy.font import proportional, CP437_FONT, TINY_FONT, SINCLAIR_FONT, LCD_FONT #import context # Ensures paho is in PYTHONPATH import paho.mqtt.client as mqtt # create matrix device serial = spi(port=0, device=0, gpio=noop()) device = max7219(serial, cascaded=4, block_orientation=-90, rotate=0) print("Created device") umlauts = { u'\xe4': u'ae', #CP437 \x84 u'\xf6': u'oe', #CP437 \x94 u'\xfc': u'ue', #CP437 \x81 u'\xc4': u'Ae', #CP437 \x8e u'\xd6': u'Oe', #CP437 \x99 u'\xdc': u'Ue', #CP437 \x9a u'\xdf': u'ss', #CP437 \xe1 u'\xb0': u'\x7f', # LCD ° } # start demo txt = [] status = "" c = 0 sleep = 0 bar = [50, 25] device.contrast(0) def on_message(mqttc, obj, msg): global txt, c, bar, status, sleep if msg.topic == "Minecraft/log": txt.append(msg.payload.decode("utf-8")[33:]) elif msg.topic == "Room/display": txt.append(msg.payload.decode("utf-8")) elif msg.topic == "Timer/weather": w = json.loads(msg.payload) txt.append(u"{} {}°C".format(w["detail"], w["tempc"])) #txt.append(str(w["mintemp"]-273.15) + u'\x7fC - ' + str(w["maxtemp"]-273.15) + u'\x7fC') txt.append(u"LF {}%".format(w["humidity"])) txt.append(u"WLK {}%".format(w["clouds"])) txt.append(u"{} m/s".format(w["windspeed"])) elif msg.topic == "Timer/forecast": return pass #w = json.loads(str(msg.payload)) #print(msg.topic + " " + str(w)) elif msg.topic == "Timer/alert/1" and msg.payload != "-1": txt.append("Wecker: " + msg.payload.decode("utf-8")[0:5]) elif msg.topic == "Timer/isDark": c &= ~2 c |= (msg.payload == "0") * 2 elif msg.topic == "Timer/isNight": c &= ~1 c |= (msg.payload == "0") elif msg.topic == "Relaybox/3": sleep = 1 if msg.payload == "1" else 0 else: print(msg.topic + " " + msg.payload.decode("utf-8")) #device.contrast(c * 32) def on_log(mqttc, obj, level, string): print(string) def on_connect(client, userdata, flags, rc): print("Connected with result code "+str(rc)) mqttc.subscribe("Relaybox/3", 2) mqttc.subscribe("Timer/#", 2) mqttc.subscribe("Minecraft/log", 2) mqttc.subscribe("Room/display", 2) mqttc = mqtt.Client() mqttc.on_message = on_message mqttc.on_connect = on_connect # Uncomment to enable debug messages #mqttc.on_log = on_log mqttc.connect_async("localhost", 1883, 60) mqttc.loop_start() pos = 0 words = [] t = datetime.now() class TimeDisplay: def __init__(self, y): self.y = y self.current_y = 1 self.isAnimating = False self.t = None self.draw = None def helper(self): hours = self.t.strftime('%H') minutes = self.t.strftime('%M') if hours[0] == "0": text(self.draw, (7, self.y+1), hours[1], fill="white", font=LCD_FONT) else: text(self.draw, (0, self.y+1), hours, fill="white", font=LCD_FONT) if self.t.second % 2: text(self.draw, (15, self.y+1), ":", fill="white", font=proportional(TINY_FONT)) text(self.draw, (17, self.y+self.current_y), minutes, fill="white", font=LCD_FONT) def show(self, draw, t, currentLine): self.t = t self.draw = draw if t.second == 59 and not self.isAnimating and currentLine == self.y: self.isAnimating = True self.current_y = 1 if self.isAnimating: self.helper() minutes = (self.t + timedelta(0,1)).strftime('%M') text(self.draw, (17, self.y+self.current_y-8), minutes, fill="white", font=LCD_FONT) self.current_y += 1 if self.current_y > 9: self.current_y = 1 self.isAnimating = False return False return True elif currentLine > self.y-8 and currentLine < self.y+8: self.helper() return False class DateDisplay: def __init__(self, y): self.y = y def show(self, draw, t, currentLine): if currentLine > self.y-8 and currentLine < self.y+8: day = t.strftime("%d") month = t.strftime("%m") text(draw, (0, self.y+1), day, fill="white", font=LCD_FONT) text(draw, (14, self.y+2), ".", fill="white", font=proportional(TINY_FONT)) text(draw, (16, self.y+1), month, fill="white", font=LCD_FONT) text(draw, (31, self.y+2), ".", fill="white", font=proportional(TINY_FONT)) return False class ScrollText: def __init__(self, y): self.font = proportional(LCD_FONT) self.y = y self.draw = None self.setText("LED Matrix") def helper(self, x, chars): text(self.draw, (x, self.y), chars, fill="white", font=self.font) def show(self, draw, t, currentLine): self.draw = draw if currentLine <= self.y-8 or currentLine >= self.y+8: return False self.helper(self.x + self.headLen, self.txt[self.charIndex:self.charIndex+8]) if self.len >= 32: self.x -= 1 else: self.x = 0 if self.x + self.headLen <= -self.currentCharWidth and self.charIndex + 1 < len(self.txt): self.charIndex += 1 self.headLen += self.currentCharWidth self.currentCharWidth, _ = textsize(self.txt[self.charIndex], self.font) if self.x <= -self.len: self.x = 31 self.currentCharWidth, _ = textsize(self.txt[0], self.font) self.charIndex = 0 self.headLen = 0 if self.x == 0: return False return True def setText(self, txt): self.len, _ = textsize(txt, self.font) self.txt = txt + " " self.x = 0 self.currentCharWidth, _ = textsize(self.txt[0], self.font) self.charIndex = 0 self.headLen = 0 class NightDisplay: def __init__(self, y): self.y = y self.t = None self.draw = None def helper(self): hours = self.t.strftime('%H') minutes = self.t.strftime('%M') for i in range(6): if self.t.hour & (2**i): self.draw.point((28 - i*5, self.y), fill="white") if self.t.minute & (2**i): self.draw.point((28 - i*5, self.y+3), fill="white") if self.t.second & (2**i): self.draw.point((28 - i*5, self.y+6), fill="white") def show(self, draw, t, currentLine): self.t = t self.draw = draw if currentLine <= self.y-8 or currentLine >= self.y+8: return False self.helper() return False lines = [ (TimeDisplay(0), 1), (DateDisplay(8), 30), (ScrollText(16), 20), (TimeDisplay(24), 10), (NightDisplay(32), 5) ] virtual = viewport(device, width=device.width, height=device.height*len(lines), mode="1") currentLine = 0 targetLine = 0 regulator = framerate_regulator(30) nextElem = datetime.now() try: while True: #if len(txt) == 0: if datetime.now().second != t.second: t = datetime.now() i = int(targetLine/8) line, secs = lines[i] if t >= nextElem: targetLine = (targetLine+8) % 32 if sleep == 1: targetLine = 32 i = int(targetLine/8) line, secs = lines[i] print("{} line={} time={}".format(t.strftime('%H:%M:%S'), i, secs)) nextElem = t + timedelta(0,secs) if i == 2 and len(txt) > 0: msg = u" +++ ".join(txt) txt = [] print(msg.encode('utf-8')) if len(msg) > 0: msg = list(msg) for i in range(len(msg)): if msg[i] in umlauts: msg[i] = umlauts[msg[i]] line.setText("".join(msg)) while True: animate = True if currentLine == 24 and targetLine < 12: currentLine = 0 elif currentLine == 0 and targetLine > 12: currentLine = 24 elif currentLine < targetLine: currentLine += 1 elif currentLine > targetLine: currentLine -= 1 else: animate = False virtual._position = (0, currentLine) with regulator: with canvas(virtual) as draw: for line, _ in lines: animate |= line.show(draw, t, currentLine) if not animate: break else: time.sleep(1.0 - datetime.now().microsecond/1000000.0) except KeyboardInterrupt: pass