From 885eb4898deddc76ebe8a13c8ef2c0822e069720 Mon Sep 17 00:00:00 2001 From: pdxlocations Date: Sat, 26 Jul 2025 22:20:19 -0700 Subject: [PATCH 1/5] init --- .vscode/launch.json | 9 +++++++++ meshtastic/__main__.py | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/.vscode/launch.json b/.vscode/launch.json index 4103a6a5..7d8fa485 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,6 +4,7 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { "name": "meshtastic BLE", "type": "debugpy", @@ -262,6 +263,14 @@ "justMyCode": true, "args": ["--nodes", "--show-fields", "AKA,Pubkey,Role,Role,Role,Latitude,Latitude,deviceMetrics.voltage"] } + { + "name": "meshtastic --export-config", + "type": "debugpy", + "request": "launch", + "module": "meshtastic", + "justMyCode": true, + "args": ["--export-config", "config.json"] + }, ] } diff --git a/meshtastic/__main__.py b/meshtastic/__main__.py index 978da0ab..b46d5126 100644 --- a/meshtastic/__main__.py +++ b/meshtastic/__main__.py @@ -1122,11 +1122,31 @@ def subscribe() -> None: # pub.subscribe(onNode, "meshtastic.node") +def ensure_true_defaults(config_dict: dict, true_defaults: set[tuple[str, ...]]) -> None: + """Ensure that default=True keys are present in the config_dict and set to True.""" + for path in true_defaults: + d = config_dict + for key in path[:-1]: + if key not in d or not isinstance(d[key], dict): + d[key] = {} + d = d[key] + if path[-1] not in d: + d[path[-1]] = True def export_config(interface) -> str: """used in --export-config""" configObj = {} + true_defaults = { + ("bluetooth", "enabled"), + ("lora", "sx126xRxBoostedGain"), + ("lora", "txEnabled"), + ("lora", "usePreset"), + ("position", "positionBroadcastSmartEnabled"), + ("security", "serialEnabled"), + ("mqtt", "encryptionEnabled"), + } + owner = interface.getLongName() owner_short = interface.getShortName() channel_url = interface.localNode.getURL() @@ -1185,6 +1205,8 @@ def export_config(interface) -> str: else: configObj["config"] = config + ensure_true_defaults(configObj["config"], true_defaults) + module_config = MessageToDict(interface.localNode.moduleConfig) if module_config: # Convert inner keys to correct snake/camelCase From eb85439000a2c6b597f64666e503f8d1f45dbaa7 Mon Sep 17 00:00:00 2001 From: pdxlocations Date: Sat, 26 Jul 2025 22:27:10 -0700 Subject: [PATCH 2/5] rename function --- meshtastic/__main__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/meshtastic/__main__.py b/meshtastic/__main__.py index b46d5126..8889a5bc 100644 --- a/meshtastic/__main__.py +++ b/meshtastic/__main__.py @@ -1122,8 +1122,8 @@ def subscribe() -> None: # pub.subscribe(onNode, "meshtastic.node") -def ensure_true_defaults(config_dict: dict, true_defaults: set[tuple[str, ...]]) -> None: - """Ensure that default=True keys are present in the config_dict and set to True.""" +def set_missing_flags_false(config_dict: dict, true_defaults: set[tuple[str, ...]]) -> None: + """Ensure that mission default=True keys are present in the config_dict and set to False.""" for path in true_defaults: d = config_dict for key in path[:-1]: @@ -1131,7 +1131,7 @@ def ensure_true_defaults(config_dict: dict, true_defaults: set[tuple[str, ...]]) d[key] = {} d = d[key] if path[-1] not in d: - d[path[-1]] = True + d[path[-1]] = False def export_config(interface) -> str: """used in --export-config""" @@ -1205,7 +1205,7 @@ def export_config(interface) -> str: else: configObj["config"] = config - ensure_true_defaults(configObj["config"], true_defaults) + set_missing_flags_false(configObj["config"], true_defaults) module_config = MessageToDict(interface.localNode.moduleConfig) if module_config: From 66e32f812a73da066337b6bcb5d6fcd94bccbb18 Mon Sep 17 00:00:00 2001 From: pdxlocations Date: Sat, 26 Jul 2025 22:35:18 -0700 Subject: [PATCH 3/5] fix launch.json punctuation --- .vscode/launch.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 7d8fa485..1df777fd 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -262,7 +262,7 @@ "module": "meshtastic", "justMyCode": true, "args": ["--nodes", "--show-fields", "AKA,Pubkey,Role,Role,Role,Latitude,Latitude,deviceMetrics.voltage"] - } + }, { "name": "meshtastic --export-config", "type": "debugpy", @@ -271,6 +271,5 @@ "justMyCode": true, "args": ["--export-config", "config.json"] }, - ] } From c1a62346946d0057c43bf81f89742615dcc47ed7 Mon Sep 17 00:00:00 2001 From: pdxlocations Date: Sat, 26 Jul 2025 23:16:50 -0700 Subject: [PATCH 4/5] make tuple type hint explicit --- meshtastic/__main__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/meshtastic/__main__.py b/meshtastic/__main__.py index 8889a5bc..a5d7c85f 100644 --- a/meshtastic/__main__.py +++ b/meshtastic/__main__.py @@ -1122,8 +1122,8 @@ def subscribe() -> None: # pub.subscribe(onNode, "meshtastic.node") -def set_missing_flags_false(config_dict: dict, true_defaults: set[tuple[str, ...]]) -> None: - """Ensure that mission default=True keys are present in the config_dict and set to False.""" +def set_missing_flags_false(config_dict: dict, true_defaults: set[tuple[str, str]]) -> None: + """Ensure that missing default=True keys are present in the config_dict and set to False.""" for path in true_defaults: d = config_dict for key in path[:-1]: @@ -1137,6 +1137,7 @@ def export_config(interface) -> str: """used in --export-config""" configObj = {} + # A list of configuration keys that should be set to False if they are missing true_defaults = { ("bluetooth", "enabled"), ("lora", "sx126xRxBoostedGain"), From 0261313fc592b498c4614fa297f65c6504d08f70 Mon Sep 17 00:00:00 2001 From: pdxlocations Date: Sun, 27 Jul 2025 12:10:05 -0700 Subject: [PATCH 5/5] add test --- meshtastic/tests/test_main.py | 36 +++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/meshtastic/tests/test_main.py b/meshtastic/tests/test_main.py index 811c8064..1e24dc2d 100644 --- a/meshtastic/tests/test_main.py +++ b/meshtastic/tests/test_main.py @@ -18,6 +18,7 @@ onNode, onReceive, tunnelMain, + set_missing_flags_false, ) from meshtastic import mt_config @@ -1897,6 +1898,41 @@ def test_main_export_config(capsys): # mo.assert_called() +@pytest.mark.unit +def test_set_missing_flags_false(): + """Test set_missing_flags_false() function""" + config = { + "bluetooth": { + "enabled": True + }, + "lora": { + "txEnabled": True + } + } + + false_defaults = { + ("bluetooth", "enabled"), + ("lora", "sx126xRxBoostedGain"), + ("lora", "txEnabled"), + ("lora", "usePreset"), + ("position", "positionBroadcastSmartEnabled"), + ("security", "serialEnabled"), + ("mqtt", "encryptionEnabled"), + } + + set_missing_flags_false(config, false_defaults) + + # Preserved + assert config["bluetooth"]["enabled"] is True + assert config["lora"]["txEnabled"] is True + + # Added + assert config["lora"]["usePreset"] is False + assert config["lora"]["sx126xRxBoostedGain"] is False + assert config["position"]["positionBroadcastSmartEnabled"] is False + assert config["security"]["serialEnabled"] is False + assert config["mqtt"]["encryptionEnabled"] is False + @pytest.mark.unit @pytest.mark.usefixtures("reset_mt_config") def test_main_gpio_rd_no_gpio_channel(capsys):