mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-07-05 09:22:04 +02:00
Always used shortest path in advert burst
This commit is contained in:
+17
-11
@@ -531,13 +531,12 @@ The `POST /api/contacts/{key}/telemetry` endpoint fetches status, neighbors, and
|
||||
### Request Flow
|
||||
|
||||
1. Verify contact exists and is a repeater (type=2)
|
||||
2. Sync contacts from radio with `ensure_contacts()`
|
||||
3. Remove and re-add contact with flood mode (clears stale auth state)
|
||||
4. Send login with password
|
||||
5. Request status with retries (3 attempts, 10s timeout)
|
||||
6. Fetch neighbors with `fetch_all_neighbours()` (handles pagination)
|
||||
7. Fetch ACL with `req_acl_sync()`
|
||||
8. Resolve pubkey prefixes to contact names from database
|
||||
2. Add contact to radio with stored path data (from advertisements)
|
||||
3. Send login with password
|
||||
4. Request status with retries (3 attempts, 10s timeout)
|
||||
5. Fetch neighbors with `fetch_all_neighbours()` (handles pagination)
|
||||
6. Fetch ACL with `req_acl_sync()`
|
||||
7. Resolve pubkey prefixes to contact names from database
|
||||
|
||||
### ACL Permission Levels
|
||||
|
||||
@@ -626,7 +625,14 @@ if txt_type == 1:
|
||||
### Helper Function
|
||||
|
||||
`prepare_repeater_connection()` handles the login dance:
|
||||
1. Sync contacts from radio
|
||||
2. Remove contact if exists (clears stale auth)
|
||||
3. Re-add with flood mode (`out_path_len=-1`)
|
||||
4. Send login with password
|
||||
1. Add contact to radio with stored path from DB (`out_path`, `out_path_len`)
|
||||
2. Send login with password
|
||||
3. Wait for key exchange to complete
|
||||
|
||||
### Contact Path Tracking
|
||||
|
||||
When advertisements are received, path data is extracted and stored:
|
||||
- `last_path`: Hex string of routing path bytes
|
||||
- `last_path_len`: Number of hops (-1=flood/unknown, 0=direct, >0=hops through repeaters)
|
||||
|
||||
**Shortest path selection**: When receiving echoed advertisements within 60 seconds, the shortest path is kept. This ensures we use the most efficient route when multiple paths exist.
|
||||
|
||||
+29
-5
@@ -309,17 +309,41 @@ async def _process_advertisement(
|
||||
return
|
||||
|
||||
# Extract path info from packet
|
||||
path_len = packet_info.path_length
|
||||
path_hex = packet_info.path.hex() if packet_info.path else ""
|
||||
new_path_len = packet_info.path_length
|
||||
new_path_hex = packet_info.path.hex() if packet_info.path else ""
|
||||
|
||||
# Try to find existing contact
|
||||
existing = await ContactRepository.get_by_key(advert.public_key)
|
||||
|
||||
# Determine which path to use: keep shorter path if heard recently (within 60s)
|
||||
# This handles advertisement echoes through different routes
|
||||
PATH_FRESHNESS_SECONDS = 60
|
||||
use_existing_path = False
|
||||
|
||||
if existing and existing.last_seen:
|
||||
path_age = timestamp - existing.last_seen
|
||||
existing_path_len = existing.last_path_len if existing.last_path_len >= 0 else float('inf')
|
||||
|
||||
# Keep existing path if it's fresh and shorter (or equal)
|
||||
if path_age <= PATH_FRESHNESS_SECONDS and existing_path_len <= new_path_len:
|
||||
use_existing_path = True
|
||||
logger.debug(
|
||||
"Keeping existing shorter path for %s (existing=%d, new=%d, age=%ds)",
|
||||
advert.public_key[:12], existing_path_len, new_path_len, path_age
|
||||
)
|
||||
|
||||
if use_existing_path:
|
||||
path_len = existing.last_path_len
|
||||
path_hex = existing.last_path or ""
|
||||
else:
|
||||
path_len = new_path_len
|
||||
path_hex = new_path_hex
|
||||
|
||||
logger.debug(
|
||||
"Parsed advertisement from %s: %s (role=%d, lat=%s, lon=%s, path_len=%d)",
|
||||
advert.public_key[:12], advert.name, advert.device_role, advert.lat, advert.lon, path_len
|
||||
)
|
||||
|
||||
# Try to find existing contact
|
||||
existing = await ContactRepository.get_by_key(advert.public_key)
|
||||
|
||||
# Use device_role from advertisement for contact type (1=Chat, 2=Repeater, 3=Room, 4=Sensor)
|
||||
# Use advert.timestamp for last_advert (sender's timestamp), receive timestamp for last_seen
|
||||
contact_type = advert.device_role if advert.device_role > 0 else (existing.type if existing else 0)
|
||||
|
||||
Reference in New Issue
Block a user