You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-**src/dev/**: Development tools (excluded from production builds)
96
-
-**test/**: Test files matching source structure
49
+
This project follows a strict layered architecture. Refer to [../docs/architecture.md](../docs/architecture.md)
97
50
98
51
### Build Configurations
99
52
@@ -766,6 +719,13 @@ const enum SaveConsts {
766
719
}
767
720
```
768
721
722
+
### Routing Feedback Loop (keep MAC/NWK changes in sync)
723
+
724
+
-`MACHandler.sendFrameDirect()`**must** clear `StackContext.macNoACKs` and call `NWKHandler.markRouteSuccess()` when a unicast ACK succeeds, and increment `macNoACKs` plus call `markRouteFailure()` when a NO_ACK error occurs.
725
+
-`StackContext.sourceRouteTable` stores **multiple**`SourceRouteTableEntry` objects per destination; `NWKHandler.findBestSourceRoute()` re-sorts them on every lookup using: path cost + staleness penalty + failure penalty − recency bonus, and filters out relays whose `macNoACKs` entry exceeds `CONFIG_NWK_CONCENTRATOR_DELIVERY_FAILURE_THRESHOLD`.
726
+
- Whenever all routes are purged (expired/blacklisted) the NWK handler must immediately trigger `sendPeriodicManyToOneRouteRequest()` so the coordinator refreshes routes.
727
+
- Link-status frames reuse the computed path costs so any tweak to the heuristic must stay consistent across `sendPeriodicZigbeeNWKLinkStatus()` and the source-route scorer.
Recent refactors introduced a closed-loop routing controller that keeps concentrator behavior stable even when radio quality fluctuates:
514
+
515
+
1. **MAC delivery feedback** – Every unicast tracks whether the RCP reported an ACK. Success clears the destination entry in `StackContext.macNoACKs`, while a NO_ACK increments it and immediately calls `NWKHandler.markRouteFailure()`.
516
+
2. **Source-route scoring** – `NWKHandler.findBestSourceRoute()` re-sorts all candidate paths on every lookup. The score combines hop count, staleness penalty, failure penalty, a recency bonus, and a hard filter that rejects any relay currently above the NO_ACK threshold.
517
+
3. **Automatic recovery** – When the handler purges all routes (expired, blacklisted, or unhealthy relays), it schedules a many-to-one route discovery so the coordinator re-advertises itself and rebuilds source routes.
518
+
4. **Link status integration** – Periodic link-status frames piggyback the same computed path costs so neighbors receive up-to-date metrics derived from LQA + routing penalties.
519
+
520
+
Together these steps ensure routing decisions remain deterministic and reflect the host's richer telemetry without waiting for devices to age routes out on their own.
0 commit comments