@@ -349,10 +349,40 @@ ProcessMessage SignalRoutingModule::handleReceived(const meshtastic_MeshPacket &
349349 }
350350
351351 updateNeighborInfo (mp.from , mp.rx_rssi , mp.rx_snr , mp.rx_time );
352+ } else if (notViaMqtt && !isDirectFromSender && mp.relay_node != 0 ) {
353+ // Process relayed packets to infer network topology
354+ // We don't have direct signal info to the original sender, but we can infer connectivity
355+ NodeNum inferredRelayer = resolveRelayIdentity (mp.relay_node );
356+
357+ if (inferredRelayer != 0 && inferredRelayer != mp.from ) {
358+ // We know that inferredRelayer relayed a packet from mp.from
359+ // This suggests connectivity between mp.from and inferredRelayer
360+ LOG_DEBUG (" SignalRouting: Inferred connectivity: %08x -> %08x (relayed via %02x)" ,
361+ mp.from , inferredRelayer, mp.relay_node );
362+
363+ // Track that both the original sender and relayer are active
364+ trackNodeCapability (mp.from , CapabilityStatus::Unknown);
365+ trackNodeCapability (inferredRelayer, CapabilityStatus::Unknown);
366+
367+ // If we have signal data to the relayer, we can update that edge
368+ if (hasSignalData) {
369+ updateNeighborInfo (inferredRelayer, mp.rx_rssi , mp.rx_snr , mp.rx_time );
370+ }
371+
372+ // Record transmission for contention window tracking
373+ if (routingGraph) {
374+ uint32_t currentTime = getValidTime (RTCQualityFromNet);
375+ if (!currentTime) {
376+ currentTime = getTime ();
377+ }
378+ routingGraph->recordNodeTransmission (mp.from , mp.id , currentTime);
379+ routingGraph->recordNodeTransmission (inferredRelayer, mp.id , currentTime);
380+ }
381+ }
352382 }
353383
354384 if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
355- handleSniffedPayload (mp, hasSignalData && notViaMqtt && isDirectFromSender);
385+ handleSniffedPayload (mp, isDirectFromSender);
356386 }
357387
358388 // Periodic graph maintenance
0 commit comments