#!/usr/bin/env python3 import math import time import sqlite3 from datetime import datetime from pathlib import Path import serial import click seg_map = { " ": 0x00, "a": 0x2e, "b": 0xd6, "c": 0xd0, "d": 0xc5, "e": 0x59, "f": 0x98, "g": 0xd4, "h": 0x8c, "i": 0x5c, "j": 0x78, "k": 0x8e, "l": 0xc0, "m": 0xa3, "n": 0xa5, "o": 0xf0, "p": 0x93, "q": 0xf4, "r": 0x9e, "s": 0x55, "t": 0xc8, "u": 0xe0, "v": 0x8a, "w": 0xac, "x": 0x0f, "y": 0x0b, "z": 0x5a, "0": 0x13, "1": 0x20, "2": 0x16, "3": 0x56, "4": 0x23, "5": 0x1c, "6": 0x4e, "7": 0x1a, "8": 0x5f, "9": 0x33, "/": 0x0a, "\\": 0x05, ".": 0x04, ",": 0x08, "_": 0x40, "!": 0x53, "?": 0x52, "*": 0x0f, ":": 0x50, "(": 0x06, "<": 0x06, "[": 0xd0, ")": 0x09, ">": 0x09, "]": 0x70, "|": 0x20, "#": 0xff, } def shuffle_segments(d): bits_in = [7, 6, 5, 4, 3, 2, 1, 0] bits_out = [7, 6, 5, 4, 3, 2, 1, 0] out = 0 for bit_in, bit_out in zip(bits_in, bits_out): if d & (1< 0: idle_seconds -= 1 else: if idle_rotation.is_file(): idle_messages = idle_rotation.read_text().splitlines() else: idle_messages = ['10:37C3', '10:UNLOCKED'] if idle_index >= len(idle_messages): idle_index = 0 interval, _, message = idle_messages[idle_index].partition(':') idle_seconds = int(interval) idle_index += 1 log(f' [Idle {idle_index}/{len(idle_messages)}] {message}') set_display(ser, message, 0, display_width, global_brightness) time.sleep(1) continue queue_pressure = max(0, min((math.log10(max(1, count-3)) - 0.3) * message_interval*2/3, message_interval*1/3)) interval = message_interval - queue_pressure log(f' Waiting interval of {message_interval:.1f} s with queue pressure {queue_pressure:.1f} from n={count} items for a total of {interval:.1f} s') rowid, message, timestamp, remote_ip, suppress_display = db.execute(''' SELECT rowid, message, timestamp_received, remote_ip, suppress_display FROM messages WHERE timestamp_displayed IS NULL ORDER BY timestamp_received LIMIT 1 ''').fetchone() timestamp = datetime.fromisoformat(timestamp) delta = (datetime.utcnow() - timestamp).total_seconds() db.execute('UPDATE messages SET timestamp_displayed = datetime("now") WHERE rowid=?', (rowid,)) db.commit() if suppress_display: discard += 1 else: if discard > 0: log(f'Discarded {discard} messages.') discard = 0 log(f'Queueing message by {remote_ip} received at {timestamp} ({delta//60:.0f}m {delta%60:.0f}s ago):') log(' ', repr(message)) idle_seconds = 0 interval = max(5, interval/len(message.splitlines())) set_display(ser, message, interval, display_width, global_brightness) if __name__ == '__main__': cli()