mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-22 02:32:23 +00:00
Add new ROUTER_LATE role (#5528)
Will always rebroadcast packets, but will do so after all other modes. Intended for router nodes that are there to provide additional coverage in areas not already covered by other routers, or to bridge around problematic terrain, but should not be given priority over other routers in order to avoid unnecessaraily consuming hops. By default, this role will rebroadcast during the normal client window. However, if another node is overheard rebroadcasting the packet, then it will be moved to a second window *after* the normal client one, with the same timing behaviour.
This commit is contained in:
@@ -235,12 +235,12 @@ void RadioLibInterface::onNotify(uint32_t notification)
|
||||
case ISR_TX:
|
||||
handleTransmitInterrupt();
|
||||
startReceive();
|
||||
startTransmitTimer();
|
||||
setTransmitDelay();
|
||||
break;
|
||||
case ISR_RX:
|
||||
handleReceiveInterrupt();
|
||||
startReceive();
|
||||
startTransmitTimer();
|
||||
setTransmitDelay();
|
||||
break;
|
||||
case TRANSMIT_DELAY_COMPLETED:
|
||||
|
||||
@@ -250,23 +250,32 @@ void RadioLibInterface::onNotify(uint32_t notification)
|
||||
if (!canSendImmediately()) {
|
||||
setTransmitDelay(); // currently Rx/Tx-ing: reset random delay
|
||||
} else {
|
||||
if (isChannelActive()) { // check if there is currently a LoRa packet on the channel
|
||||
startReceive(); // try receiving this packet, afterwards we'll be trying to transmit again
|
||||
setTransmitDelay();
|
||||
meshtastic_MeshPacket *txp = txQueue.getFront();
|
||||
assert(txp);
|
||||
long delay_remaining = txp->tx_after ? txp->tx_after - millis() : 0;
|
||||
if (delay_remaining > 0) {
|
||||
// There's still some delay pending on this packet, so resume waiting for it to elapse
|
||||
notifyLater(delay_remaining, TRANSMIT_DELAY_COMPLETED, false);
|
||||
} else {
|
||||
// Send any outgoing packets we have ready as fast as possible to keep the time between channel scan and
|
||||
// actual transmission as short as possible
|
||||
meshtastic_MeshPacket *txp = txQueue.dequeue();
|
||||
assert(txp);
|
||||
bool sent = startSend(txp);
|
||||
if (sent) {
|
||||
// Packet has been sent, count it toward our TX airtime utilization.
|
||||
uint32_t xmitMsec = getPacketTime(txp);
|
||||
airTime->logAirtime(TX_LOG, xmitMsec);
|
||||
if (isChannelActive()) { // check if there is currently a LoRa packet on the channel
|
||||
startReceive(); // try receiving this packet, afterwards we'll be trying to transmit again
|
||||
setTransmitDelay();
|
||||
} else {
|
||||
// Send any outgoing packets we have ready as fast as possible to keep the time between channel scan and
|
||||
// actual transmission as short as possible
|
||||
txp = txQueue.dequeue();
|
||||
assert(txp);
|
||||
bool sent = startSend(txp);
|
||||
if (sent) {
|
||||
// Packet has been sent, count it toward our TX airtime utilization.
|
||||
uint32_t xmitMsec = getPacketTime(txp);
|
||||
airTime->logAirtime(TX_LOG, xmitMsec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Do nothing, because the queue is empty
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -277,15 +286,24 @@ void RadioLibInterface::onNotify(uint32_t notification)
|
||||
void RadioLibInterface::setTransmitDelay()
|
||||
{
|
||||
meshtastic_MeshPacket *p = txQueue.getFront();
|
||||
if (!p) {
|
||||
return; // noop if there's nothing in the queue
|
||||
}
|
||||
|
||||
// We want all sending/receiving to be done by our daemon thread.
|
||||
// We use a delay here because this packet might have been sent in response to a packet we just received.
|
||||
// So we want to make sure the other side has had a chance to reconfigure its radio.
|
||||
|
||||
/* We assume if rx_snr = 0 and rx_rssi = 0, the packet was generated locally.
|
||||
* This assumption is valid because of the offset generated by the radio to account for the noise
|
||||
* floor.
|
||||
*/
|
||||
if (p->rx_snr == 0 && p->rx_rssi == 0) {
|
||||
if (p->tx_after) {
|
||||
unsigned long add_delay = p->rx_rssi ? getTxDelayMsecWeighted(p->rx_snr) : getTxDelayMsec();
|
||||
unsigned long now = millis();
|
||||
p->tx_after = max(p->tx_after + add_delay, now + add_delay);
|
||||
notifyLater(now - p->tx_after, TRANSMIT_DELAY_COMPLETED, false);
|
||||
} else if (p->rx_snr == 0 && p->rx_rssi == 0) {
|
||||
/* We assume if rx_snr = 0 and rx_rssi = 0, the packet was generated locally.
|
||||
* This assumption is valid because of the offset generated by the radio to account for the noise
|
||||
* floor.
|
||||
*/
|
||||
startTransmitTimer(true);
|
||||
} else {
|
||||
// If there is a SNR, start a timer scaled based on that SNR.
|
||||
@@ -312,6 +330,20 @@ void RadioLibInterface::startTransmitTimerSNR(float snr)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the packet is not already in the late rebroadcast window, move it there
|
||||
*/
|
||||
void RadioLibInterface::clampToLateRebroadcastWindow(NodeNum from, PacketId id)
|
||||
{
|
||||
// Look for non-late packets only, so we don't do this twice!
|
||||
meshtastic_MeshPacket *p = txQueue.remove(from, id, true, false);
|
||||
if (p) {
|
||||
p->tx_after = millis() + getTxDelayMsecWeightedWorst(p->rx_snr);
|
||||
txQueue.enqueue(p);
|
||||
LOG_DEBUG("Move existing queued packet to the late rebroadcast window %dms from now", p->tx_after - millis());
|
||||
}
|
||||
}
|
||||
|
||||
void RadioLibInterface::handleTransmitInterrupt()
|
||||
{
|
||||
// This can be null if we forced the device to enter standby mode. In that case
|
||||
|
||||
Reference in New Issue
Block a user