From 49408b075b9f96aca0e174b664d0f7eed10e8c1f Mon Sep 17 00:00:00 2001 From: redfast00 Date: Mon, 20 Jan 2020 19:00:50 +0100 Subject: [PATCH] Replace single-threaded model with producer/consumer multithreaded model --- server.py | 241 +++++++++++++++++++++++++++++------------------------- 1 file changed, 129 insertions(+), 112 deletions(-) diff --git a/server.py b/server.py index a6c4cfe..10a8cab 100644 --- a/server.py +++ b/server.py @@ -7,148 +7,165 @@ from http.server import HTTPServer, BaseHTTPRequestHandler from io import BytesIO import string import base64 +from queue import Queue +from threading import Thread NULL_CHAR = chr(0) -file = open('/dev/hidg0', 'rb+') - -alphabet_lower = set(string.ascii_lowercase) -alphabet_upper = set(string.ascii_uppercase) - -colors = { - "Z": "a", # Black - "B": "b", # Blue - "G": "c", # Green - "M": "d", # Magenta - "R": "e", # Red - "P": "f", # Pink - "Y": "g", # Yellow - "W": "h", # White - "z": "i", # Light/blink Black - "b": "j", # Light/blink Blue - "g": "k", # Light/blink Green - "m": "l", # Light/blink Magenta - "r": "m", # Light/blink Red - "p": "n", # Light/blink Pink - "y": "o", # Light/blink Yellow - "w": "p" # Light/blink White -} - -special_chars = { - ' ': [NULL_CHAR, chr(44)], - '\n': [NULL_CHAR, chr(40)], - '\\': [NULL_CHAR, chr(0x31)], - '.': [NULL_CHAR, chr(0x37)], - '/': [NULL_CHAR, chr(0x38)], - ';': [NULL_CHAR, chr(0x33)], - '-': [NULL_CHAR, chr(0x2d)], - '=': [NULL_CHAR, chr(0x2e)], - '[': [NULL_CHAR, chr(0x2f)], - ']': [NULL_CHAR, chr(0x30)], - '*': [NULL_CHAR, chr(0x55)], - ',': [NULL_CHAR, chr(0x36)], - '!': [chr(32), chr(0x1e)], - '<': [chr(32), chr(0x36)], - '>': [chr(32), chr(0x37)], - '?': [chr(32), chr(0x38)], - ':': [chr(32), chr(0x33)], - '(': [chr(32), chr(0x26)], - ')': [chr(32), chr(0x27)], - '&': [chr(32), chr(0x24)], - '%': [chr(32), chr(0x22)], - '#': [chr(32), chr(0x20)], - '@': [chr(32), chr(0x1f)], - '$': [chr(32), chr(0x21)], - '_': [chr(32), chr(0x2d)], - '+': [chr(32), chr(0x2e)], - '{': [chr(32), chr(0x2f)], - '}': [chr(32), chr(0x30)], - '|': [chr(32), chr(0x31)], - '~': [chr(32), chr(0x35)], -} -def write_report(report): - file.write(report.encode()) +class KeyboardHandler: + + def __init__(self, hidfile='/dev/hidg0'): + # Open keyboard device for binary appending + self.file = open(hidfile, 'ba') + + colors = { + "Z": "a", # Black + "B": "b", # Blue + "G": "c", # Green + "M": "d", # Magenta + "R": "e", # Red + "P": "f", # Pink + "Y": "g", # Yellow + "W": "h", # White + "z": "i", # Light/blink Black + "b": "j", # Light/blink Blue + "g": "k", # Light/blink Green + "m": "l", # Light/blink Magenta + "r": "m", # Light/blink Red + "p": "n", # Light/blink Pink + "y": "o", # Light/blink Yellow + "w": "p" # Light/blink White + } + + special_chars = { + ' ': [NULL_CHAR, chr(44)], + '\n': [NULL_CHAR, chr(40)], + '\\': [NULL_CHAR, chr(0x31)], + '.': [NULL_CHAR, chr(0x37)], + '/': [NULL_CHAR, chr(0x38)], + ';': [NULL_CHAR, chr(0x33)], + '-': [NULL_CHAR, chr(0x2d)], + '=': [NULL_CHAR, chr(0x2e)], + '[': [NULL_CHAR, chr(0x2f)], + ']': [NULL_CHAR, chr(0x30)], + '*': [NULL_CHAR, chr(0x55)], + ',': [NULL_CHAR, chr(0x36)], + '!': [chr(32), chr(0x1e)], + '<': [chr(32), chr(0x36)], + '>': [chr(32), chr(0x37)], + '?': [chr(32), chr(0x38)], + ':': [chr(32), chr(0x33)], + '(': [chr(32), chr(0x26)], + ')': [chr(32), chr(0x27)], + '&': [chr(32), chr(0x24)], + '%': [chr(32), chr(0x22)], + '#': [chr(32), chr(0x20)], + '@': [chr(32), chr(0x1f)], + '$': [chr(32), chr(0x21)], + '_': [chr(32), chr(0x2d)], + '+': [chr(32), chr(0x2e)], + '{': [chr(32), chr(0x2f)], + '}': [chr(32), chr(0x30)], + '|': [chr(32), chr(0x31)], + '~': [chr(32), chr(0x35)], + } + + alphabet_lower = set(string.ascii_lowercase) + alphabet_upper = set(string.ascii_uppercase) -def release_keys(): - write_report(NULL_CHAR * 8) + def write_report(self, report): + self.file.write(report.encode()) -def printchar(c): - if c in alphabet_lower: - write_report(NULL_CHAR * 2 + chr(4 + ord(c) - ord('a')) + NULL_CHAR * 5) - elif c in alphabet_upper: - write_report(chr(32) + NULL_CHAR + chr(4 + ord(c) - ord('A')) + NULL_CHAR * 5) - elif c.isdigit(): - write_report(NULL_CHAR * 2 + chr(0x1e + ((ord(c) - ord('0') - 1) % 10)) + NULL_CHAR * 5) - elif c in special_chars: - write_report(special_chars[c][0] + NULL_CHAR + special_chars[c][1] + NULL_CHAR * 5) - else: - write_report(chr(32) + NULL_CHAR + chr(0x38) + NULL_CHAR * 5) - release_keys() + def release_keys(self): + self.write_report(NULL_CHAR * 8) + + def printchar(self, c): + if c in self.alphabet_lower: + self.write_report(NULL_CHAR * 2 + chr(4 + ord(c) - ord('a')) + NULL_CHAR * 5) + elif c in self.alphabet_upper: + self.write_report(chr(32) + NULL_CHAR + chr(4 + ord(c) - ord('A')) + NULL_CHAR * 5) + elif c.isdigit(): + self.write_report(NULL_CHAR * 2 + chr(0x1e + ((ord(c) - ord('0') - 1) % 10)) + NULL_CHAR * 5) + elif c in self.special_chars: + self.write_report(self.special_chars[c][0] + NULL_CHAR + self.special_chars[c][1] + NULL_CHAR * 5) + else: + self.write_report(chr(32) + NULL_CHAR + chr(0x38) + NULL_CHAR * 5) + self.release_keys() -def change_color(background, foreground): - if background in colors and foreground in colors: - # DELETE keypress - write_report(NULL_CHAR * 2 + chr(0x2a) + NULL_CHAR * 5) - release_keys() - write_report(NULL_CHAR * 2 + chr(4 + ord(colors[background]) - ord('a')) + NULL_CHAR * 5) - release_keys() - write_report(NULL_CHAR * 2 + chr(4 + ord(colors[foreground]) - ord('a')) + NULL_CHAR * 5) - else: - print('Malformed Color code: §' + background + foreground) - write_report(chr(32) + NULL_CHAR + chr(0x38) + NULL_CHAR * 5) - release_keys() + def change_color(self, background, foreground): + if background in self.colors and foreground in self.colors: + # DELETE keypress + self.write_report(NULL_CHAR * 2 + chr(0x2a) + NULL_CHAR * 5) + self.release_keys() + self.write_report(NULL_CHAR * 2 + chr(4 + ord(self.colors[background]) - ord('a')) + NULL_CHAR * 5) + self.release_keys() + self.write_report(NULL_CHAR * 2 + chr(4 + ord(self.colors[foreground]) - ord('a')) + NULL_CHAR * 5) + else: + print('Malformed Color code: §' + background + foreground) + self.write_report(chr(32) + NULL_CHAR + chr(0x38) + NULL_CHAR * 5) + self.release_keys() -def printstring(s): - last_c = '' - last_last_c = '' - for c in s: - if last_last_c == '§': - change_color(last_c, c) - elif c != '§' and last_c != '§': - printchar(c) - last_c, last_last_c = c, last_c + def printstring(self, s): + last_c = '' + last_last_c = '' + for c in s: + if last_last_c == '§': + self.change_color(last_c, c) + elif c != '§' and last_c != '§': + self.printchar(c) + last_c, last_last_c = c, last_c -def reset_color(): - change_color('Z', 'g') - release_keys() + def reset_color(self): + self.change_color('Z', 'g') + self.release_keys() -def beep(code='fff'): - write_report(NULL_CHAR * 2 + chr(0x29) + NULL_CHAR * 5) - release_keys() - for char in code: - printchar(char) + def beep(self, code='fff'): + self.write_report(NULL_CHAR * 2 + chr(0x29) + NULL_CHAR * 5) + self.release_keys() + for char in code: + self.printchar(char) class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): + def __init__(self, request, client_address, server): + self.messagequeue = server.messagequeue + super().__init__(request, client_address, server) + def do_GET(self): self.send_response(200) self.end_headers() - self.wfile.write(b'Hello, world!') + self.wfile.write(b'TAp reporting for duty!') def do_POST(self): - print(self.headers) message = base64.b64decode(self.headers['X-Messages']).decode('utf8') self.send_response(200) self.end_headers() - response = BytesIO() - response.write(b'This is POST request. ') - response.write(b'Received: ') - self.wfile.write(response.getvalue()) + self.messagequeue.put_nowait(message) + self.wfile.write(b'Received message') + +def message_collector(messagequeue): + keyboard = KeyboardHandler() + while True: + message = messagequeue.get() if message == 'reset': - printstring('\n' * 32) + keyboard.printstring('\n' * 32) else: - printstring(message + '\n') - beep() - reset_color() - file.flush() + keyboard.printstring(message + '\n') + keyboard.beep() + keyboard.reset_color() + keyboard.file.flush() +shared_messagequeue = Queue() httpd = HTTPServer(('0.0.0.0', 8000), SimpleHTTPRequestHandler) +httpd.messagequeue = shared_messagequeue +thread = Thread(target = message_collector, args = (shared_messagequeue, )) +thread.start() httpd.serve_forever()