mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-07-27 07:18:11 +00:00
feat(repeater): politeness controls, dedicated radio profile, and diagnostics
Settings > Radio gains a repeater toggle, 16 community-suggested radio presets plus manual Freq/SF/BW/CR tuning (digit-by-digit Freq editor), 4 persisted user preset slots, and the packet pool bumped 16->32 so queued retransmits stop starving incoming-packet allocation while relaying. Four opt-in politeness knobs (skip-advert, max-hops, yield, min-SNR), all flood-only and off by default, plus overhear suppression that cancels a queued retransmit if a peer relays the same packet first. Adaptive Power Control is suppressed while relaying (pins TX power to the ceiling) and duty-cycle RX is forced off, since a repeater needs to hear and relay at consistent power. A dedicated Tools > Repeater screen consolidates the toggle, the politeness knobs, and live forwarding stats, plus an optional "Custom" radio profile — a dedicated frequency/SF/BW/CR for relaying, separate from the companion's own network, band-matched to the companion frequency by default and used everywhere a radio change can happen (boot, on-device toggle, app-driven CMD_SET_RADIO_PARAMS, Settings radio edits) so the device never silently falls back to the wrong params mid-relay. Diagnostics gains the actually-forwarded packet count, real heap-free via mallinfo(), a reset-counters popup, and hardened loop-detect bounds. Also: a frequency-floor fix and a float-equality preset-match fix in the repeater profile logic, deduped BW-table/valCol/profile- seeding helpers shared between Settings and the Repeater screen, and a build.sh fix tolerating control characters in `pio project config`'s JSON dump. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -240,6 +240,9 @@ void Dispatcher::checkRecv() {
|
||||
logRx(pkt, pkt->getRawLength(), score); // hook for custom logging
|
||||
|
||||
n_recv_by_type[pkt->getPayloadType()]++;
|
||||
// Overhear suppression: if we just heard a flood packet that we still have
|
||||
// queued to retransmit, another node beat us to it — drop our copy.
|
||||
if (pkt->isRouteFlood() && wantsOverhearSuppress()) suppressQueuedDuplicate(pkt);
|
||||
if (pkt->isRouteFlood()) {
|
||||
n_recv_flood++;
|
||||
|
||||
@@ -261,6 +264,27 @@ void Dispatcher::checkRecv() {
|
||||
}
|
||||
}
|
||||
|
||||
void Dispatcher::suppressQueuedDuplicate(Packet* pkt) {
|
||||
uint8_t h[MAX_HASH_SIZE];
|
||||
pkt->calculatePacketHash(h);
|
||||
// Scan the whole outbound queue (not just due entries). hasSeen() already
|
||||
// keeps at most one copy queued, so the first hash match is the only one.
|
||||
int n = _mgr->getOutboundTotal();
|
||||
for (int i = 0; i < n; i++) {
|
||||
Packet* q = _mgr->getOutboundByIdx(i);
|
||||
if (q == NULL || !q->isRouteFlood()) continue; // only ever suppress a queued flood retransmit
|
||||
uint8_t qh[MAX_HASH_SIZE];
|
||||
q->calculatePacketHash(qh);
|
||||
if (memcmp(h, qh, MAX_HASH_SIZE) == 0) {
|
||||
_mgr->removeOutboundByIdx(i);
|
||||
onRetransmitCancelled(q);
|
||||
_mgr->free(q);
|
||||
MESH_DEBUG_PRINTLN("%s Dispatcher: overhear suppressed a queued retransmit", getLogDateTime());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Dispatcher::processRecvPacket(Packet* pkt) {
|
||||
DispatcherAction action = onRecvPacket(pkt);
|
||||
if (action == ACTION_RELEASE) {
|
||||
|
||||
Reference in New Issue
Block a user