From 0226c00de0edca0e569085087e9359a5657e4c55 Mon Sep 17 00:00:00 2001 From: "Maciek \"mab122\" Bator" Date: Thu, 23 Apr 2026 14:00:14 +0200 Subject: [PATCH] feat: --lora flag for LoRa-safe announce/poll defaults Adds --lora to bridge, seed, and gossip commands. When set, overrides announce-retry-delays to 60,300,900s and poll-interval to 120s, matching LoRa duty-cycle limits. Explicit user flags always take precedence over the LoRa defaults, so --lora --announce-retry-delays=30,60 still works. Co-Authored-By: Claude Sonnet 4.6 --- src/radicle_reticulum/cli.py | 51 +++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/src/radicle_reticulum/cli.py b/src/radicle_reticulum/cli.py index 354f061..37f21be 100644 --- a/src/radicle_reticulum/cli.py +++ b/src/radicle_reticulum/cli.py @@ -49,6 +49,24 @@ def detect_radicle_nid() -> Optional[str]: return None +LORA_ANNOUNCE_DELAYS = "60,300,900" +LORA_POLL_INTERVAL = 120 + + +def _apply_lora_defaults(args) -> None: + """Override delay/poll defaults with LoRa-safe values when --lora is set. + + Only overrides fields that were left at their defaults (argparse default + strings), so explicit user flags always take precedence. + """ + if not getattr(args, "lora", False): + return + if getattr(args, "announce_retry_delays", None) == "5,15,30": + args.announce_retry_delays = LORA_ANNOUNCE_DELAYS + if getattr(args, "poll_interval", None) == 30: + args.poll_interval = LORA_POLL_INTERVAL + + def _parse_delays(s: str) -> Tuple[int, ...]: try: return tuple(int(x.strip()) for x in s.split(",") if x.strip()) @@ -246,6 +264,7 @@ def _detect_rid(repo_path: Path) -> Optional[str]: def cmd_gossip(args): """Run the gossip relay daemon.""" + _apply_lora_defaults(args) identity = RadicleIdentity.load_or_generate(args.identity) _print_identity_info(args.identity) @@ -318,6 +337,7 @@ def cmd_gossip(args): def cmd_seed(args): """Start a dedicated seed radicle-node, bridge, and gossip relay.""" + _apply_lora_defaults(args) seed_home = Path(args.seed_home) # Validate args before starting any processes @@ -439,6 +459,7 @@ def cmd_seed(args): def cmd_bridge(args): """Run Radicle-Reticulum bridge.""" + _apply_lora_defaults(args) print("Starting Radicle-Reticulum bridge...") identity = RadicleIdentity.load_or_generate(args.identity) @@ -759,8 +780,14 @@ def main(): "--announce-retry-delays", default="5,15,30", metavar="SECONDS", - help="Startup re-announce delays, comma-separated (default: 5,15,30). " - "Use longer values on LoRa, e.g. 60,300,900", + help="Startup re-announce delays, comma-separated (default: 5,15,30 for " + "WiFi/Ethernet). On LoRa use 60,300,900 to respect duty-cycle limits.", + ) + gossip_parser.add_argument( + "--lora", + action="store_true", + help="Shortcut for LoRa-safe settings: sets --announce-retry-delays=60,300,900 " + "and --poll-interval=120 (unless overridden explicitly).", ) add_identity_arg(gossip_parser) @@ -800,8 +827,14 @@ def main(): "--announce-retry-delays", default="5,15,30", metavar="SECONDS", - help="Startup re-announce delays, comma-separated (default: 5,15,30). " - "Use longer values on LoRa, e.g. 60,300,900", + help="Startup re-announce delays, comma-separated (default: 5,15,30 for " + "WiFi/Ethernet). On LoRa use 60,300,900 to respect duty-cycle limits.", + ) + seed_parser.add_argument( + "--lora", + action="store_true", + help="Shortcut for LoRa-safe settings: sets --announce-retry-delays=60,300,900 " + "and --poll-interval=120 (unless overridden explicitly).", ) add_identity_arg(seed_parser) @@ -864,10 +897,16 @@ def main(): default="5,15,30", metavar="SECONDS", help=( - "Comma-separated delays for startup re-announces (default: 5,15,30). " - "On LoRa use longer values to respect duty cycle, e.g. 60,300,900" + "Comma-separated delays for startup re-announces (default: 5,15,30 for " + "WiFi/Ethernet). On LoRa use 60,300,900 to respect duty-cycle limits." ), ) + bridge_parser.add_argument( + "--lora", + action="store_true", + help="Shortcut for LoRa-safe settings: sets --announce-retry-delays=60,300,900 " + "(unless overridden explicitly).", + ) add_identity_arg(bridge_parser) args = parser.parse_args()