diff --git a/__init__.py b/__init__.py index f82fb28..76b001f 100644 --- a/__init__.py +++ b/__init__.py @@ -16,11 +16,10 @@ import config from messageprovider import MessageProvider -CLOCK_FONT = CP437_FONT -MSG_FONT = proportional(LCD_FONT) LONG_MSG_LEN = 11 -class HoursMinutes: + +class Timestamp: def __init__(self): self.ts = datetime.now() self._set_hm() @@ -28,76 +27,71 @@ def __init__(self): def next(self): self.ts = self.ts + timedelta(seconds=1) self._set_hm() - + def _set_hm(self): - self.hours = self.ts.strftime('%H') - self.minutes = self.ts.strftime('%M') + self.hours = self.ts.strftime("%H") + self.minutes = self.ts.strftime("%M") + self.date = self.ts.strftime("%d.%m.%Y") + self.day_of_week = ["MO", "DI", "MI", "DO", "FR", "SA", "SO"][ + self.ts.today().weekday() + ] def now(): - return HoursMinutes() + return Timestamp() -def day_of_week(): - return ["MO", "DI", "MI", "DO", "FR", "SA", "SO"][datetime.today().weekday()] +def draw_time(draw, ts, x_offset=0, y_offset=0, minute_y_offset=0, toggle=True): + def txt(x,y, value, font=CP437_FONT): + text(draw, (x + x_offset, 1 + y + y_offset), value, fill="white", font=font) + + txt(0, 0, ts.hours) + txt(15, 0,":" if toggle else " ", font=proportional(TINY_FONT)) + txt(17, minute_y_offset, ts.minutes) + txt(48, 0, ts.day_of_week, font=proportional(CP437_FONT)) -def cp437_encode(str): - return [c.encode('cp437') for c in str] def minute_change(device): """When we reach a minute change, animate it.""" - ts = now() - + timestamp = now() + def helper(current_y): with canvas(device) as draw: - text(draw, (0, 1), ts.hours, fill="white", font=CLOCK_FONT) - text(draw, (15, 1), ":", fill="white", font=proportional(TINY_FONT)) - text(draw, (17, current_y), ts.minutes, fill="white", font=CLOCK_FONT) - text(draw, (device.width - 2 * 8, 1), day_of_week(), fill="white", font=proportional(CLOCK_FONT)) - + draw_time(draw=draw, ts=timestamp, minute_y_offset=current_y, toggle=False) time.sleep(0.08) - - for current_y in range(1, 9): + + for current_y in range(0, 9): helper(current_y) - ts.next() - for current_y in range(9, 1, -1): + timestamp.next() + for current_y in range(9, 0, -1): helper(current_y) def animation(device, from_y, to_y): """Animate the whole thing, moving it into/out of the abyss.""" - ts = now() + timestamp = now() current_y = from_y while current_y != to_y: with canvas(device) as draw: - text(draw, (0, current_y), ts.hours, fill="white", font=CLOCK_FONT) - text(draw, (15, current_y), ":", fill="white", font=proportional(TINY_FONT)) - text(draw, (17, current_y), ts.minutes, fill="white", font=CLOCK_FONT) - text(draw, (device.width - 2 * 8, current_y + 1), day_of_week(), fill="white", font=proportional(CLOCK_FONT)) + draw_time(draw=draw, ts=timestamp, y_offset=current_y, toggle=False) time.sleep(0.065) current_y += 1 if to_y > from_y else -1 def vertical_scroll(device, words): - ts = now() + timestamp = now() messages = [" "] + words + [" "] virtual = viewport(device, width=device.width, height=len(messages) * 12) - + first_y_index = 0 last_y_index = (len(messages) - 1) * 12 - + with canvas(virtual) as draw: for i, word in enumerate(messages): - text(draw, (0, i * 12), word, fill="white", font=MSG_FONT) - text(draw, (0, first_y_index), ts.hours, fill="white", font=CLOCK_FONT) - text(draw, (15, first_y_index), ":", fill="white", font=proportional(TINY_FONT)) - text(draw, (17, first_y_index), ts.minutes, fill="white", font=CLOCK_FONT) - text(draw, (device.width - 2 * 8, first_y_index + 1), day_of_week(), fill="white", font=proportional(CLOCK_FONT)) - text(draw, (0, last_y_index), ts.hours, fill="white", font=CLOCK_FONT) - text(draw, (15, last_y_index), ":", fill="white", font=proportional(TINY_FONT)) - text(draw, (17, last_y_index), ts.minutes, fill="white", font=CLOCK_FONT) - text(draw, (device.width - 2 * 8, last_y_index), day_of_week(), fill="white", font=proportional(CLOCK_FONT)) - + text(draw, (0, i * 12), word, fill="white", font=proportional(LCD_FONT)) + draw_time(draw=draw, ts=timestamp, y_offset=first_y_index) + draw_time(draw=draw, ts=timestamp, y_offset=last_y_index) + for i in range(virtual.height - 12): virtual.set_position((0, i)) if i > 0 and i % 12 == 0: @@ -105,52 +99,64 @@ def vertical_scroll(device, words): time.sleep(0.022) +def horizontal_scroll(device, messages): + def cp437_encode(str): + return [c.encode("cp437") for c in str] + + animation(device, 1, 8) + for msg in messages: + show_message( + device, + cp437_encode(msg), + fill="white", + font=proportional(CP437_FONT), + scroll_delay=0.024, + ) + animation(device, 8, 1) + + def main(): serial = spi(port=0, device=0, gpio=noop()) - device = max7219(serial, cascaded=8, block_orientation=-90, blocks_arranged_in_reverse_order=False) + device = max7219( + serial, + cascaded=8, + block_orientation=-90, + blocks_arranged_in_reverse_order=False, + ) device.contrast(0) - + msg = str(chr(177) * 8) show_message(device, msg, fill="white", font=CP437_FONT) - + # Start mqtt message subscription msg_provider = MessageProvider(config) msg_provider.loop_start() - + # The time ascends from the abyss... animation(device, 8, 1) - + toggle = False # Toggle the second indicator every second while True: try: toggle = not toggle - sec = datetime.now().second + timestamp = now() + sec = timestamp.ts.second if sec == 59: # When we change minutes, animate the minute change minute_change(device) elif sec == 10: - today = date.today() - messages = [today.strftime("%2d.%2m.%4Y")] + [m for m in msg_provider.messages() if len(m) <= LONG_MSG_LEN] + messages = [timestamp.date] + msg_provider.short_messages(LONG_MSG_LEN) vertical_scroll(device, messages) elif sec == 40: - today = date.today() - long_messages = [ m for m in msg_provider.messages() if len(m) > LONG_MSG_LEN ] + long_messages = msg_provider.long_messages(LONG_MSG_LEN) if len(long_messages) > 0: - messages = long_messages - animation(device, 1, 8) - for full_msg in messages: - show_message(device, cp437_encode(full_msg), fill="white", font=proportional(CLOCK_FONT), scroll_delay=0.024) - animation(device, 8, 1) + horizontal_scroll(device, long_messages) else: - messages = [today.strftime("%2d.%2m.%4Y")] + [m for m in msg_provider.messages() if len(m) <= LONG_MSG_LEN] + messages = [timestamp.date] + msg_provider.short_messages(LONG_MSG_LEN) vertical_scroll(device, messages) else: - ts = now() with canvas(device) as draw: - text(draw, (0, 1), ts.hours, fill="white", font=CLOCK_FONT) - text(draw, (15, 1), ":" if toggle else " ", fill="white", font=proportional(TINY_FONT)) - text(draw, (17, 1), ts.minutes, fill="white", font=CLOCK_FONT) - text(draw, (device.width - 2 * 8, 1), day_of_week(), fill="white", font=proportional(CLOCK_FONT)) + draw_time(draw=draw, ts=timestamp, toggle=toggle) time.sleep(0.5) except KeyboardInterrupt: msg_provider.loop_stop() diff --git a/messageprovider/__init__.py b/messageprovider/__init__.py index 94e6f1b..366e5da 100644 --- a/messageprovider/__init__.py +++ b/messageprovider/__init__.py @@ -41,6 +41,12 @@ def messages(self): [pair[1] for pair in self.ttl_cache.items()], key=lambda json_object: json_object["weight"]) return [self._format(json_obj) for json_obj in sorted_sensor_json_obj_list] + + def long_messages(self,limit): + return [m for m in self.messages() if len(m) > limit] + + def short_messages(self,limit): + return [m for m in self.messages() if len(m) <= limit] @staticmethod def _format(json_obj):