mirror of
https://github.com/mudita/MuditaOS.git
synced 2026-07-18 12:04:03 -04:00
299 lines
6.7 KiB
Python
299 lines
6.7 KiB
Python
# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
|
|
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
|
|
|
|
import time
|
|
from enum import Enum
|
|
|
|
from harness.interface.CDCSerial import Keytype
|
|
from harness.interface.defs import key_codes
|
|
|
|
|
|
# assuming that the harness is actually in the menu
|
|
application_keypath = {
|
|
"calllog": [
|
|
"enter"
|
|
],
|
|
"contacts": [
|
|
"right",
|
|
"enter"
|
|
],
|
|
"messages": [
|
|
"right",
|
|
"right",
|
|
"enter"
|
|
],
|
|
"music": [
|
|
"down",
|
|
"enter"
|
|
],
|
|
"meditation": [
|
|
"down",
|
|
"right",
|
|
"enter"
|
|
],
|
|
"settings": [
|
|
"down",
|
|
"right",
|
|
"right",
|
|
"enter"
|
|
],
|
|
"tools": [
|
|
"up",
|
|
"enter"
|
|
],
|
|
"alarm": [
|
|
"up",
|
|
"right",
|
|
"enter"
|
|
],
|
|
"calendar": [
|
|
"up",
|
|
"left",
|
|
"left",
|
|
"enter"
|
|
]
|
|
}
|
|
|
|
keymap = {
|
|
"A": "2",
|
|
"B": "22",
|
|
"C": "222",
|
|
"D": "3",
|
|
"E": "33",
|
|
"F": "333",
|
|
"G": "4",
|
|
"H": "44",
|
|
"I": "444",
|
|
"J": "5",
|
|
"K": "55",
|
|
"L": "555",
|
|
"M": "6",
|
|
"N": "66",
|
|
"O": "666",
|
|
"P": "7",
|
|
"Q": "77",
|
|
"R": "777",
|
|
"S": "7777",
|
|
"T": "8",
|
|
"U": "88",
|
|
"V": "888",
|
|
"W": "9",
|
|
"X": "99",
|
|
"Y": "999",
|
|
"Z": "9999",
|
|
" ": "0",
|
|
".": "1",
|
|
",": "11",
|
|
"_": "111",
|
|
":": "1111",
|
|
";": "11111",
|
|
")": "111111",
|
|
"(": "1111111",
|
|
"?": "11111111",
|
|
"!": "111111111",
|
|
"#": "1111111111",
|
|
"/": "11111111111",
|
|
"*": "111111111111",
|
|
"+": "1111111111111",
|
|
"del": key_codes["#"],
|
|
"caps": key_codes["*"],
|
|
}
|
|
|
|
special_chars_keymap = {
|
|
U'.': "",
|
|
U',': "d",
|
|
U'\'': "dd",
|
|
U'?': "ddd",
|
|
U'!': "dddd",
|
|
U'"': "ddddd",
|
|
U'-': "dddddd",
|
|
U'(': "s",
|
|
U')': "sd",
|
|
U'@': "sdd",
|
|
U'/': "sddd",
|
|
U':': "sdddd",
|
|
U'_': "sddddd",
|
|
U';': "sdddddd",
|
|
U'': "ss",
|
|
U'+': "ssd",
|
|
U'&': "ssdd",
|
|
U'%': "ssddd",
|
|
U'*': "ssdddd",
|
|
U'<': "ssddddd",
|
|
U'>': "ssdddddd",
|
|
U'=': "sss",
|
|
U'£': "sssd",
|
|
U'€': "sssdd",
|
|
U'$': "sssddd",
|
|
U'[': "sssdddd",
|
|
U']': "sssddddd",
|
|
U'{': "sssdddddd",
|
|
U'}': "ssss",
|
|
U'\'': "ssssd",
|
|
U'^': "ssssdd",
|
|
U'~': "ssssddd",
|
|
U'`': "ssssdddd",
|
|
U'į': "ssssddddd",
|
|
U'§': "ssssdddddd",
|
|
U'…': "sssss",
|
|
U'#': "sssssd",
|
|
U'|': "sssssdd",
|
|
U'÷': "sssssddd",
|
|
U'·': "sssssdddd",
|
|
U'°': "sssssddddd",
|
|
U'¿': "sssssdddddd",
|
|
U'¡': "ssssss",
|
|
U'ą': "ssssssd",
|
|
U'à': "ssssssdd",
|
|
U'á': "ssssssddd",
|
|
U'ä': "ssssssdddd",
|
|
U'â': "ssssssddddd",
|
|
U'ć': "ssssssdddddd",
|
|
U'ç': "sssssss",
|
|
U'ę': "sssssssd",
|
|
U'é': "sssssssdd",
|
|
U'è': "sssssssddd",
|
|
U'ê': "sssssssdddd",
|
|
U'ë': "sssssssddddd",
|
|
U'î': "sssssssdddddd",
|
|
U'ï': "ssssssss",
|
|
U'í': "ssssssssd",
|
|
U'ł': "ssssssssdd",
|
|
U'ń': "ssssssssddd",
|
|
U'ñ': "ssssssssdddd",
|
|
U'ó': "ssssssssddddd",
|
|
U'ô': "ssssssssdddddd",
|
|
U'ö': "sssssssss",
|
|
U'ś': "sssssssssd",
|
|
U'û': "sssssssssdd",
|
|
U'ú': "sssssssssddd",
|
|
U'ù': "sssssssssdddd",
|
|
U'ü': "sssssssssddddd",
|
|
U'ÿ': "sssssssssdddddd",
|
|
U'ż': "ssssssssss",
|
|
U'ź': "ssssssssssd",
|
|
U'ß': "ssssssssssdd"
|
|
}
|
|
|
|
emojis_keymap = {
|
|
U'😁': "",
|
|
U'😂': "d",
|
|
U'😃': "dd",
|
|
U'😄': "ddd",
|
|
U'😅': "dddd",
|
|
U'😆': "ddddd",
|
|
U'😉': "dddddd",
|
|
U'😊': "s",
|
|
U'😋': "sd",
|
|
U'😌': "sdd",
|
|
U'😍': "sddd",
|
|
U'😏': "sdddd",
|
|
U'😒': "sddddd",
|
|
U'😓': "sdddddd",
|
|
U'😔': "ss",
|
|
U'😖': "ssd",
|
|
U'😘': "ssdd",
|
|
U'😚': "ssddd",
|
|
U'😜': "ssdddd",
|
|
U'😝': "ssddddd",
|
|
U'😼': "ssdddddd"
|
|
}
|
|
|
|
def send_keystoke(keypath, connection):
|
|
for key in keypath:
|
|
connection.send_key_code(key_codes[key])
|
|
time.sleep(0.3)
|
|
|
|
|
|
last_char = '\0'
|
|
|
|
|
|
def clear_last_char():
|
|
global last_char
|
|
last_char = '\0'
|
|
|
|
|
|
def send_char(char: str, connection):
|
|
global last_char
|
|
key_type = Keytype.short_press
|
|
if char.isascii():
|
|
if char.isdigit():
|
|
key_type = Keytype.long_press
|
|
if last_char is char:
|
|
print("repeated key!")
|
|
connection.send_key_code(key_codes["right"])
|
|
connection.send_key_code(int(char), key_type)
|
|
connection.send_key_code(key_codes["right"])
|
|
last_char = char
|
|
elif char.islower():
|
|
tmp = char.upper()
|
|
# toggle to lowercase mode
|
|
connection.send_key_code(key_codes["*"], key_type)
|
|
if last_char is keymap[tmp][0]:
|
|
print("repeated key!")
|
|
connection.send_key_code(key_codes["right"], key_type)
|
|
for key in keymap[tmp]:
|
|
connection.send_key_code(int(key), key_type)
|
|
last_char = keymap[tmp][0]
|
|
# toggle to uppercase mode
|
|
connection.send_key_code(key_codes["*"], key_type)
|
|
connection.send_key_code(key_codes["*"], key_type)
|
|
else:
|
|
if last_char is keymap[char][0]:
|
|
print("repeated key!")
|
|
connection.send_key_code(key_codes["right"], key_type)
|
|
for key in keymap[char]:
|
|
connection.send_key_code(int(key), key_type)
|
|
last_char = keymap[char][0]
|
|
else:
|
|
connection.send_key_code(key_codes["*"], Keytype.long_press)
|
|
if char in special_chars_keymap:
|
|
for key in special_chars_keymap[char]:
|
|
connection.send_key_code(ord(key), key_type)
|
|
elif char in emojis_keymap:
|
|
connection.send_key_code(key_codes["fnLeft"], Keytype.short_press)
|
|
for key in emojis_keymap[char]:
|
|
connection.send_key_code(ord(key), key_type)
|
|
else:
|
|
print("Not supported char {} !!!".format(char))
|
|
connection.send_key_code(key_codes["enter"], key_type)
|
|
|
|
|
|
def send_number(number: str, connection):
|
|
if number.isnumeric():
|
|
for digit in number:
|
|
connection.send_key_code(int(digit))
|
|
time.sleep(0.3)
|
|
|
|
|
|
### timeout from https://stackoverflow.com/a/601168/5752094
|
|
|
|
from contextlib import contextmanager
|
|
|
|
import signal
|
|
|
|
|
|
class Timeout(Exception):
|
|
'''
|
|
usage:
|
|
try:
|
|
with Timeout.limit(10):
|
|
long_function_call()
|
|
except Timeout as e:
|
|
print("Timed out!")
|
|
'''
|
|
|
|
@classmethod
|
|
@contextmanager
|
|
def limit(cls, seconds: int):
|
|
assert seconds >= 1, "Timeout must be at least 1 second !"
|
|
def signal_handler(signum, frame):
|
|
raise Timeout("Timed out!")
|
|
|
|
signal.signal(signal.SIGALRM, signal_handler)
|
|
signal.alarm(seconds)
|
|
try:
|
|
yield
|
|
finally:
|
|
signal.alarm(0)
|