# 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",
"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)