diff options
author | Sébastien Dailly <sebastien@dailly.me> | 2025-07-20 15:26:58 +0200 |
---|---|---|
committer | Sébastien Dailly <sebastien@dailly.me> | 2025-07-20 15:26:58 +0200 |
commit | c31148f482adf44ded7cec1d683e01d995294850 (patch) | |
tree | 42dc4032085fc1466bbdeb5bf71076436a3844ef | |
parent | cc2c9c0bd9d646a33f0324eae024618bd2a68983 (diff) |
Added some tests, and a handle commands in the json (only 'layer' for now)
-rw-r--r-- | boot.py | 7 | ||||
-rw-r--r-- | code.py | 33 | ||||
-rw-r--r-- | ff.json | 8 | ||||
-rw-r--r-- | json_layer.py | 62 | ||||
-rw-r--r-- | serial_conn.py | 90 |
5 files changed, 124 insertions, 76 deletions
@@ -2,9 +2,12 @@ import usb_cdc usb_cdc.enable(data=True) import layout +import storage if layout.check_key(): print("Key pressed") + storage.remount("/", readonly=False) + storage.enable_usb_drive() else: - import storage + # Remount in read only + storage.remount("/", readonly=True) storage.disable_usb_drive() - storage.remount("/", False) @@ -1,12 +1,15 @@ import board +from supervisor import runtime +import json +from serial_conn import Client +import oled from supervisor import runtime # Do not reload the application when the files are changed runtime.autoreload = False # Initialize the BEPO layout import kmk.handlers.stock as handlers -#from kmk.key_validators import key_seq_sleep_validator from kmk import keys keys.KC.clear() keys.KEY_GENERATORS=( @@ -18,6 +21,7 @@ keys.KEY_GENERATORS=( keys.maybe_make_no_key, ) KC=keys.KC + import kmk_frnb from kmk.kmk_keyboard import KMKKeyboard @@ -26,29 +30,34 @@ keyboard = KMKKeyboard() import layout layout.set_keyboard(keyboard) -import oled oled.main(keyboard) import json_layer def load_json(file): - with open("ff.json", "r") as ff_conf: - s = ff_conf.read() - layer = json_layer.Layer(s) - return layer + with open(file, "r") as conf: + file_data = conf.read() + key_layer = json_layer.Layer() + json_data = json.loads(file_data.strip()) + key_layer.load(json_data) + return key_layer from kmk.modules.macros import Macros from kmk.modules.mouse_keys import MouseKeys + +# Create the first layer in the keyboard. The object will be reused later when +# receiving commands from the serial connection. +layer = load_json("ff.json") + +keyboard.keymap = [ + layer +] + keyboard.modules = [ Macros(), - json_layer.JsonLayer(), + Client(), MouseKeys(), ] -firefox = load_json("ff.json") - -keyboard.keymap = [ - firefox -] if __name__ == '__main__': keyboard.go() @@ -1,6 +1,6 @@ -{ "Firefox": [ - {"seq": ["A", "B", "C"]}, ["^", "R"], ["^", "T"], ["^", "W"], - null, null, ["^", "PAGE_UP"], ["^", "PAGE_DOWN"], - null, null, ["^", "WINDOWS", "LEFT_ARROW"], ["^", "WINDOWS", "RIGHT_ARROW"], +{ "Initialized": [ + null, null, null, null + null, null, null, null + null, null, null, null null, null, null, null ]} diff --git a/json_layer.py b/json_layer.py index 91699b5..8d12681 100644 --- a/json_layer.py +++ b/json_layer.py @@ -7,12 +7,8 @@ # {"get_layer"} # -from usb_cdc import data -import json -from kmk.modules import Module from kmk.keys import Key, KC -#from kmk.handlers.sequences import simple_key_sequence from kmk.modules.macros import Delay, Macros, Tap # This dictionnary is a sort of point of function. @@ -48,7 +44,7 @@ def key_of_json(element, inside=False): if isinstance(element, dict): for key, value in element.items(): return operators[key](value) - pass + return def encode_macro(element): """ Encode the result of the function key_of_json in order to build a macro @@ -89,9 +85,9 @@ class Layer(object): This class gives the property name in addition of the keymap list """ - def __init__(self, jdata): - json_data = json.loads(jdata.strip()) - self.load(json_data) + def __init__(self): + self.name = "" + self.keys = [] def load(self, json_data): """ Load the json dictionnary into the layer. The dictionnary shall be @@ -118,53 +114,3 @@ class Layer(object): """ Compare two layer by the name only """ return self.name == other.name - -class JsonLayer(Module): - - def during_bootup(self, keyboard): - try: - # Do not set any timeout, we check before reading a string if there - # is any content to read, but block to be sure to read everything. - data.timeout = None - except AttributeError: - pass - - def before_matrix_scan(self, keyboard): - pass - - def after_matrix_scan(self, keyboard): - pass - - def process_key(self, keyboard, key, is_pressed, int_coord): - return key - - def before_hid_send(self, keyboard): - # Serial.data isn't initialized. - if not data: - return - - if not data.connected: - keyboard.keymap[0].name = "Disconnected" - return - - # Nothing to parse. - if data.in_waiting <= 0: - return - line = data.readline() - if not line: - return - - try: - jdata = json.loads(line.decode().strip()) - keyboard.keymap[0].load(jdata) - except Exception as err: - print(err) - - def after_hid_send(self, keyboard): - pass - - def on_powersave_enable(self, keyboard): - pass - - def on_powersave_disable(self, keyboard): - pass diff --git a/serial_conn.py b/serial_conn.py new file mode 100644 index 0000000..4e885b2 --- /dev/null +++ b/serial_conn.py @@ -0,0 +1,90 @@ +from kmk.modules import Module +from usb_cdc import data +import json + +import json_layer + +class Client(Module): + """ Listen the connections from host, and apply the actions depending of + the json command. + """ + + def during_bootup(self, keyboard): + try: + # Do not set any timeout, we check before reading a string if there + # is any content to read, but block to be sure to read everything. + data.timeout = None + except AttributeError: + pass + + def process_key(self, keyboard, key, is_pressed, int_coord): + return key + + def before_hid_send(self, keyboard): + + # Serial.data isn't initialized yet. + if not data: + return + + if not data.connected: + keyboard.keymap[0].name = "Disconnected" + return + + # Nothing to parse. + if data.in_waiting <= 0: + return + line = data.readline() + if not line: + return + + try: + content = line.decode().strip() + if not content: + # If strip produced an empty string, stop here. + return + jdata = json.loads(content) + except ValueError as err: + # In circuitPython, json error are reported as ValueError. + # seet https://docs.circuitpython.org/en/latest/docs/library/json.html#json.load + print(err, line) + return + + # Json is valid, try to read the command, and consider the input is a + # direct raw layer instruction if this does not work. + + actions = { + "layer" : lambda x : keyboard.keymap[0].load(x), + } + + try: + for action, args in jdata.items(): + actions[action](args) + return + except Exception as err: + pass + + try: + keyboard.keymap[0].load(jdata) + except Exception as err: + print("rawdata:", err) + return + + def before_matrix_scan(self, keyboard): + """ Default implementation, do nothing. + """ + + def after_matrix_scan(self, keyboard): + """ Default implementation, do nothing. + """ + + def after_hid_send(self, keyboard): + """ Default implementation, do nothing. + """ + + def on_powersave_enable(self, keyboard): + """ Default implementation, do nothing. + """ + + def on_powersave_disable(self, keyboard): + """ Default implementation, do nothing. + """ |