2019-08-22 01:26:15 +00:00
|
|
|
#!/usr/bin/env python3
|
2019-08-22 18:33:57 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
2019-09-30 22:08:56 +00:00
|
|
|
import datetime
|
|
|
|
import time
|
2019-08-22 01:26:15 +00:00
|
|
|
import string
|
|
|
|
from http.server import HTTPServer, BaseHTTPRequestHandler
|
|
|
|
from io import BytesIO
|
2019-09-09 20:03:49 +00:00
|
|
|
import string
|
2019-08-22 01:26:15 +00:00
|
|
|
import base64
|
2020-01-20 18:00:50 +00:00
|
|
|
from queue import Queue
|
|
|
|
from threading import Thread
|
2019-08-22 01:26:15 +00:00
|
|
|
|
|
|
|
NULL_CHAR = chr(0)
|
2020-01-20 18:00:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
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 write_report(self, report):
|
|
|
|
self.file.write(report.encode())
|
|
|
|
|
|
|
|
|
|
|
|
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(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(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(self):
|
|
|
|
self.change_color('Z', 'g')
|
|
|
|
self.release_keys()
|
|
|
|
|
|
|
|
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)
|
2019-09-30 22:08:56 +00:00
|
|
|
|
2019-08-22 01:26:15 +00:00
|
|
|
|
|
|
|
class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
|
|
|
|
|
2020-01-20 18:00:50 +00:00
|
|
|
def __init__(self, request, client_address, server):
|
|
|
|
self.messagequeue = server.messagequeue
|
|
|
|
super().__init__(request, client_address, server)
|
|
|
|
|
2019-08-22 01:26:15 +00:00
|
|
|
def do_GET(self):
|
|
|
|
self.send_response(200)
|
|
|
|
self.end_headers()
|
2020-01-20 18:00:50 +00:00
|
|
|
self.wfile.write(b'TAp reporting for duty!')
|
2019-08-22 01:26:15 +00:00
|
|
|
|
|
|
|
def do_POST(self):
|
2019-08-22 17:45:52 +00:00
|
|
|
message = base64.b64decode(self.headers['X-Messages']).decode('utf8')
|
2019-08-22 01:26:15 +00:00
|
|
|
self.send_response(200)
|
|
|
|
self.end_headers()
|
2020-01-20 18:00:50 +00:00
|
|
|
self.messagequeue.put_nowait(message)
|
2020-01-22 19:19:34 +00:00
|
|
|
self.wfile.write(b'Received message\n')
|
2020-01-20 18:00:50 +00:00
|
|
|
|
|
|
|
def message_collector(messagequeue):
|
|
|
|
keyboard = KeyboardHandler()
|
|
|
|
while True:
|
|
|
|
message = messagequeue.get()
|
2019-08-22 01:26:15 +00:00
|
|
|
if message == 'reset':
|
2020-01-20 18:00:50 +00:00
|
|
|
keyboard.printstring('\n' * 32)
|
2019-08-22 01:26:15 +00:00
|
|
|
else:
|
2020-01-20 18:00:50 +00:00
|
|
|
keyboard.printstring(message + '\n')
|
|
|
|
keyboard.reset_color()
|
|
|
|
keyboard.file.flush()
|
2020-01-22 19:19:34 +00:00
|
|
|
if messagequeue.empty():
|
|
|
|
keyboard.beep()
|
|
|
|
keyboard.file.flush()
|
|
|
|
|
2019-08-22 01:26:15 +00:00
|
|
|
|
|
|
|
|
2020-01-20 18:00:50 +00:00
|
|
|
shared_messagequeue = Queue()
|
2019-08-22 01:26:15 +00:00
|
|
|
httpd = HTTPServer(('0.0.0.0', 8000), SimpleHTTPRequestHandler)
|
2020-01-20 18:00:50 +00:00
|
|
|
httpd.messagequeue = shared_messagequeue
|
|
|
|
thread = Thread(target = message_collector, args = (shared_messagequeue, ))
|
|
|
|
thread.start()
|
2019-08-22 01:26:15 +00:00
|
|
|
httpd.serve_forever()
|