feat: Add node discovery feature and improve advert notification

Implemented new "Discover Nodes" feature in Network Commands menu:
- Added .node_discover command to meshcli wrapper (cli.py)
- Created interactive modal with sortable table showing nearby repeaters
- Displays SNR, RSSI, path length, and signal quality indicators
- Added refresh functionality to rescan for nodes

Fixed advert notification to show clean "Advert sent" message
instead of full meshcli output.

Technical changes:
- app/meshcore/cli.py: Added node_discover() function with JSON parsing
- app/routes/api.py: Updated SPECIAL_COMMANDS and execute_special_command()
  to handle node_discover return type and clean advert message
- app/templates/base.html: Added "Discover Nodes" menu button and modal
- app/static/js/app.js: Added discoverNodes() and displayNodeDiscoveryResults()
- README.md: Added documentation for Discover Nodes feature

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
MarekWo
2026-01-02 14:34:02 +01:00
parent 797096b551
commit 75ec789fba
5 changed files with 282 additions and 13 deletions
+41
View File
@@ -368,6 +368,47 @@ def floodadv() -> Tuple[bool, str]:
return success, stdout or stderr
def node_discover() -> Tuple[bool, List[Dict]]:
"""
Discover nearby mesh nodes (repeaters).
Uses .node_discover command which returns JSON array of nearby repeaters
with SNR, RSSI, and other metadata.
Returns:
Tuple of (success, nodes_list)
Each node dict contains:
{
'SNR': float,
'RSSI': int,
'path_len': int,
'node_type': int (2=REP),
'SNR_in': float,
'tag': str (hex),
'pubkey': str (hex)
}
"""
success, stdout, stderr = _run_command(['.node_discover'])
if not success:
logger.error(f"node_discover failed: {stderr}")
return False, []
try:
# Parse JSON array from stdout
nodes = json.loads(stdout)
if not isinstance(nodes, list):
logger.error(f"node_discover returned non-array: {stdout}")
return False, []
logger.info(f"Discovered {len(nodes)} nearby nodes")
return True, nodes
except json.JSONDecodeError as e:
logger.error(f"Failed to parse node_discover JSON: {e}, output: {stdout}")
return False, []
# =============================================================================
# Direct Messages (DM)
# =============================================================================