From 802368ba4cb4291b0b147e447aa3a1d17906be7f Mon Sep 17 00:00:00 2001 From: Shy Date: Tue, 14 Mar 2017 14:46:51 +0100 Subject: [PATCH] Initial commit --- kitchentext.py | 138 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100755 kitchentext.py diff --git a/kitchentext.py b/kitchentext.py new file mode 100755 index 0000000..6cc6472 --- /dev/null +++ b/kitchentext.py @@ -0,0 +1,138 @@ +#!/bin/python +# +# kitchentext: Read text from stdin and put it on the Kitchenlight + +def kitchentext(delay=200, single=False, wait=False, restore=False, poweron=False, + verbose=False, debug=False): + + import sys + from c4ctrl import C4Interface, Kitchenlight + + charwidth = { # Width of characters + 'a' : 5, 'A' : 5, 'b' : 4, 'B' : 5, + 'c' : 3, 'C' : 5, 'd' : 4, 'D' : 5, + 'e' : 4, 'E' : 5, 'f' : 3, 'F' : 5, + 'g' : 3, 'G' : 5, 'h' : 3, 'H' : 5, + 'i' : 1, 'I' : 5, 'j' : 2, 'J' : 5, + 'k' : 3, 'K' : 5, 'l' : 3, 'L' : 5, + 'm' : 5, 'M' : 5, 'n' : 4, 'N' : 5, + 'o' : 3, 'O' : 5, 'p' : 3, 'P' : 5, + 'q' : 3, 'Q' : 5, 'r' : 3, 'R' : 5, + 's' : 4, 'S' : 5, 't' : 3, 'T' : 5, + 'u' : 3, 'U' : 5, 'v' : 3, 'V' : 5, + 'w' : 5, 'W' : 5, 'x' : 3, 'X' : 5, + 'y' : 3, 'Y' : 5, 'z' : 3, 'Z' : 5, + '0' : 5, '1' : 4, '2' : 5, '3' : 5, + '4' : 5, '5' : 5, '6' : 5, '7' : 5, + '8' : 5, '9' : 5, '@' : 5, '=' : 3, + '!' : 1, '"' : 3, '_' : 5, '-' : 3, + '.' : 2, ',' : 2, '*' : 5, ':' : 2, + '\'' : 1, '/' : 5, '(' : 2, ')' : 2, + '{' : 3, '}' : 3, '[' : 2, ']' : 2, + '<' : 3, '>' : 4, '+' : 5, '#' : 5, + '$' : 5, '%' : 5, '$' : 5, '~' : 5, + '?' : 3, ';' : 2, '\\' : 5, '^' : 3, + '|' : 1, '`' : 2, ' ' : 3, '\t' : 5 + } + + C4Interface.debug = debug + kl = Kitchenlight(autopower=poweron) + + # Enforce wait=True if restore=True or single=False + wait = wait or restore or not single + + # Store previous state + if restore: + c4 = C4Interface([kl.topic, kl.powertopic]) + safe = c4.fetch() + + try: + stop = False + while not stop: + # Only itarate once if single is set + stop = single + + try: + text = sys.stdin.readline() + except KeyboardInterrupt: # Exit a bit more graceful on CTRL-C + verbose and sys.stderr.write("\rInterrupted by user\n") + sys.exit(1) + + if single and text.rstrip('\n') == "": + verbose and sys.stderr.write("Error: empty input!\n") + sys.exit(1) + elif text == "\n": # Empty line + verbose and print("Info: skipping empty line") + continue + elif text == "": # EOF + break + + # Strip chars Kitchenlight can not display + text = text.rstrip('\n').encode("ascii", "ignore").decode("ascii") + + try: # We might well get interrupted while waiting + kl.text(text, delay) + + if wait: + from time import sleep + # How long shall we wait? + # Kitchenlight has 30 columns, each char uses 2-5 columns followed by an empty + # one. The traversal of one column takes 30 * ms. + twidth = 0 + for c in text: + try: + twidth += (charwidth[c] + 1) + except KeyError: + twidth += 4 # Fallback + wait_for = ((30 * delay) + (twidth * delay))/1000 + verbose and print("Waiting for {} seconds ...".format(wait_for)) + sleep(wait_for) + + except KeyboardInterrupt: + verbose and sys.stderr.write("\rInterrupted by user\n") + sys.exit(1) + + finally: + # Always restore privious state if "restore" is set + if restore: + re = [] + for top in safe: re.append((top.topic, top.payload)) + c4.update(re) + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser( + description="Read text from stdin and put it on the Kitchenlight") + parser.add_argument( + "-d", "--delay", type=int, default=200, + help="delay in ms (speed of the text, default is 200)") + parser.add_argument( + "-s", "--single", action="store_true", + help="only read a single line") + parser.add_argument( + "-w", "--wait", action="store_true", default=False, + help="wait until the text has been displayed") + parser.add_argument( + "-r", "--restore", action="store_true", default=False, + help="restore the Kitchenlight to its prior state after the text has been displayed (implies --wait)") + parser.add_argument( + "-p", "--power-on", action="store_true", default=False, + help="turn on Kitchenlight if it is powered off") + parser.add_argument( + "-v", "--verbose", action="store_true", + help="be (not much) more verbose") + parser.add_argument( + "--debug", action="store_true", + help="display what would be send to the MQTT broker, but do not actually connect") + args = parser.parse_args() + + kitchentext(delay=args.delay, + single=args.single, + wait=args.wait, + restore=args.restore, + poweron=args.power_on, + verbose=args.verbose, + debug=args.debug) +