From 590b60fefb6eca38fc07fdb59be198b196868923 Mon Sep 17 00:00:00 2001 From: Dan Welch Date: Wed, 6 Dec 2023 11:52:22 -0700 Subject: [PATCH 1/3] Allow 'configure' to import yaml settings nested deepr than 2 levels Resolves meshtastic/python#466 --- meshtastic/__main__.py | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/meshtastic/__main__.py b/meshtastic/__main__.py index 1d0c248..88304da 100644 --- a/meshtastic/__main__.py +++ b/meshtastic/__main__.py @@ -128,25 +128,45 @@ def getPref(node, comp_name): def splitCompoundName(comp_name): """Split compound (dot separated) preference name into parts""" - name = comp_name.split(".", 1) - if len(name) != 2: + name = comp_name.split(".") + if len(name) < 2: name[0] = comp_name name.append(comp_name) return name +def traverseConfig(config_root, config, interface_config): + snake_name = meshtastic.util.camel_to_snake(config_root) + for pref in config: + pref_name = f"{snake_name}.{pref}" + if isinstance(config[pref], dict): + traverseConfig(pref_name, config[pref], interface_config) + else: + setPref( + interface_config, + pref_name, + str(config[pref]) + ) + + return True def setPref(config, comp_name, valStr): """Set a channel or preferences value""" name = splitCompoundName(comp_name) - snake_name = meshtastic.util.camel_to_snake(name[1]) - camel_name = meshtastic.util.snake_to_camel(name[1]) + snake_name = meshtastic.util.camel_to_snake(name[-1]) + camel_name = meshtastic.util.snake_to_camel(name[-1]) logging.debug(f"snake_name:{snake_name}") logging.debug(f"camel_name:{camel_name}") objDesc = config.DESCRIPTOR + config_part = config config_type = objDesc.fields_by_name.get(name[0]) + if config_type and config_type.message_type is not None: + for name_part in name[1:-1]: + part_snake_name = meshtastic.util.camel_to_snake((name_part)) + config_part = getattr(config, config_type.name) + config_type = config_type.message_type.fields_by_name.get(part_snake_name) pref = False if config_type and config_type.message_type is not None: pref = config_type.message_type.fields_by_name.get(snake_name) @@ -193,13 +213,13 @@ def setPref(config, comp_name, valStr): if snake_name != "ignore_incoming": try: if config_type.message_type is not None: - config_values = getattr(config, config_type.name) + config_values = getattr(config_part, config_type.name) setattr(config_values, pref.name, val) else: - setattr(config, snake_name, val) + setattr(config_part, snake_name, val) except TypeError: # The setter didn't like our arg type guess try again as a string - config_values = getattr(config, config_type.name) + config_values = getattr(config_part, config_type.name) setattr(config_values, pref.name, valStr) else: if val == 0: @@ -559,12 +579,7 @@ def onConnected(interface): if "config" in configuration: localConfig = interface.getNode(args.dest).localConfig for section in configuration["config"]: - for pref in configuration["config"][section]: - setPref( - localConfig, - f"{meshtastic.util.camel_to_snake(section)}.{pref}", - str(configuration["config"][section][pref]), - ) + traverseConfig(section, configuration["config"][section], localConfig) interface.getNode(args.dest).writeConfig( meshtastic.util.camel_to_snake(section) ) From 4af1b322da0a895114cfa961e8dfb36f1d3efd6b Mon Sep 17 00:00:00 2001 From: AeroXuk <9274396+AeroXuk@users.noreply.github.com> Date: Tue, 9 Apr 2024 12:27:08 +0100 Subject: [PATCH 2/3] Also accept nested settings in module_config. Show full config path in output when nested. --- meshtastic/__main__.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/meshtastic/__main__.py b/meshtastic/__main__.py index 3403ff7..53d2094 100644 --- a/meshtastic/__main__.py +++ b/meshtastic/__main__.py @@ -229,7 +229,7 @@ def setPref(config, comp_name, valStr) -> bool: print(f"Adding '{val}' to the ignore_incoming list") config_type.message_type.ignore_incoming.extend([val]) - prefix = f"{name[0]}." if config_type.message_type is not None else "" + prefix = f"{".".join(name[0:-1])}." if config_type.message_type is not None else "" if Globals.getInstance().get_camel_case(): print(f"Set {prefix}{camel_name} to {valStr}") else: @@ -580,12 +580,7 @@ def onConnected(interface): if "module_config" in configuration: moduleConfig = interface.getNode(args.dest).moduleConfig for section in configuration["module_config"]: - for pref in configuration["module_config"][section]: - setPref( - moduleConfig, - f"{meshtastic.util.camel_to_snake(section)}.{pref}", - str(configuration["module_config"][section][pref]), - ) + traverseConfig(section, configuration["module_config"][section], moduleConfig) interface.getNode(args.dest).writeConfig( meshtastic.util.camel_to_snake(section) ) From 03c1f08e452b9e296c2e7ad69535b30dd9010570 Mon Sep 17 00:00:00 2001 From: Dan Welch Date: Tue, 16 Apr 2024 14:46:35 -0600 Subject: [PATCH 3/3] Fix Lint Error - add docstring to traverseConfig function --- meshtastic/__main__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/meshtastic/__main__.py b/meshtastic/__main__.py index 88304da..be22a76 100644 --- a/meshtastic/__main__.py +++ b/meshtastic/__main__.py @@ -135,6 +135,7 @@ def splitCompoundName(comp_name): return name def traverseConfig(config_root, config, interface_config): + """Iterate through current config level preferences and either traverse deeper if preference is a dict or set preference""" snake_name = meshtastic.util.camel_to_snake(config_root) for pref in config: pref_name = f"{snake_name}.{pref}"