From cb4ca87abe85a35715fa3e0c1cd9db2d3c00946d Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Sat, 12 Mar 2022 07:22:59 -0800 Subject: [PATCH 1/3] remove role from flooding router --- src/mesh/FloodingRouter.cpp | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index ab7136237..3c60f2d84 100644 --- a/src/mesh/FloodingRouter.cpp +++ b/src/mesh/FloodingRouter.cpp @@ -58,26 +58,8 @@ bool FloodingRouter::isPacketLocal(const MeshPacket *p) void FloodingRouter::sniffReceived(const MeshPacket *p, const Routing *c) { - bool rebroadcastPacket = true; - if (radioConfig.preferences.role == Role_Repeater || radioConfig.preferences.role == Role_Router) { - rebroadcastPacket = true; - - } else if ((radioConfig.preferences.role == Role_Default)) { - - - if (inRangeOfRouter()) { - // In Range of a router - rebroadcastPacket = false; - - } else if (!isPacketLocal(p)) { - // The packet did not come from a local source - rebroadcastPacket = false; - - } - } - - if ((p->to == NODENUM_BROADCAST) && (p->hop_limit > 0) && (getFrom(p) != getNodeNum() && rebroadcastPacket)) { + if ((p->to == NODENUM_BROADCAST) && (p->hop_limit > 0) && (getFrom(p) != getNodeNum())) { if (p->id != 0) { MeshPacket *tosend = packetPool.allocCopy(*p); // keep a copy because we will be sending it From 82591b2a697d60f3db25b185e96d39397a7b107f Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Sun, 13 Mar 2022 14:50:27 -0700 Subject: [PATCH 2/3] Remove more old router role work. --- src/mesh/FloodingRouter.cpp | 29 ----------------------------- src/mesh/FloodingRouter.h | 16 ---------------- 2 files changed, 45 deletions(-) diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index 3c60f2d84..1ee08bad4 100644 --- a/src/mesh/FloodingRouter.cpp +++ b/src/mesh/FloodingRouter.cpp @@ -27,35 +27,6 @@ bool FloodingRouter::shouldFilterReceived(MeshPacket *p) return Router::shouldFilterReceived(p); } -bool FloodingRouter::inRangeOfRouter() -{ - - uint32_t maximum_router_sec = 300; - - // FIXME : Scale minimum_snr to accomodate different modem configurations. - float minimum_snr = 2; - - for (int i = 0; i < myNodeInfo.router_count; i++) { - // A router has been seen and the heartbeat was heard within the last 300 seconds - if ( - ((myNodeInfo.router_sec[i] > 0) && (myNodeInfo.router_sec[i] < maximum_router_sec)) && - (myNodeInfo.router_snr[i] > minimum_snr) - ) { - return true; - } - } - - return false; -} - -bool FloodingRouter::isPacketLocal(const MeshPacket *p) -{ - - // TODO: Figure out if a packet is from a local node - - return false; -} - void FloodingRouter::sniffReceived(const MeshPacket *p, const Routing *c) { diff --git a/src/mesh/FloodingRouter.h b/src/mesh/FloodingRouter.h index 299ad690e..387b4576b 100644 --- a/src/mesh/FloodingRouter.h +++ b/src/mesh/FloodingRouter.h @@ -52,22 +52,6 @@ class FloodingRouter : public Router, protected PacketHistory */ virtual bool shouldFilterReceived(MeshPacket *p) override; - /** - * Are we in range of a router? - * - * "range" here may not be the right term. - * @return true if we're in range of a router - */ - virtual bool inRangeOfRouter(); - - /** - * Is the packet from a device that is physically near this node? - * - * Calculated based on the received SNR. - * @return true if the received packet is physically close to this node. - */ - virtual bool isPacketLocal(const MeshPacket *p); - /** * Look for broadcasts we need to rebroadcast */ From 3816a2fbe05bd3a6fb7d03dd4272d1cefcd8abf4 Mon Sep 17 00:00:00 2001 From: Jm Casler Date: Mon, 14 Mar 2022 17:47:01 -0700 Subject: [PATCH 3/3] Add weighted tx delay for flooding router --- src/mesh/RadioInterface.cpp | 33 ++++++++++++++++++++++++++++++++- src/mesh/RadioInterface.h | 4 ++++ src/mesh/RadioLibInterface.cpp | 24 +++++++++++++++++++++++- src/mesh/RadioLibInterface.h | 7 +++++++ 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 1a5802863..a371d8f26 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -180,7 +180,38 @@ uint32_t RadioInterface::getTxDelayMsec() */ // const uint32_t MAX_TX_WAIT_MSEC = 2000; // stress test would still fail occasionally with 1000 - return random(MIN_TX_WAIT_MSEC, shortPacketMsec); + return random((MIN_TX_WAIT_MSEC), (MIN_TX_WAIT_MSEC + shortPacketMsec)); +} + + +/** The delay to use when we want to send something but the ether is busy */ +uint32_t RadioInterface::getTxDelayMsecWeighted(float snr) +{ + /** At the low end we want to pick a delay large enough that anyone who just completed sending (some other node) + * has had enough time to switch their radio back into receive mode. + */ + const uint32_t MIN_TX_WAIT_MSEC = 100; + + // The minimum value for a LoRa SNR + const uint32_t SNR_MIN = -20; + + // The maximum value for a LoRa SNR + const uint32_t SNR_MAX = 15; + + // high SNR = Long Delay + // low SNR = Short Delay + uint32_t delay = 0; + + if (radioConfig.preferences.role == Role_Router) { + delay = map(snr, SNR_MIN, SNR_MAX, MIN_TX_WAIT_MSEC, (MIN_TX_WAIT_MSEC + (shortPacketMsec / 2))); + DEBUG_MSG("rx_snr found in packet. As a router, setting tx delay:%d\n", delay); + } else { + delay = map(snr, SNR_MIN, SNR_MAX, MIN_TX_WAIT_MSEC + (shortPacketMsec / 2), (MIN_TX_WAIT_MSEC + shortPacketMsec * 2)); + DEBUG_MSG("rx_snr found in packet. Setting tx delay:%d\n", delay); + } + + + return delay; } void printPacket(const char *prefix, const MeshPacket *p) diff --git a/src/mesh/RadioInterface.h b/src/mesh/RadioInterface.h index 6b286bef8..af05bf1a0 100644 --- a/src/mesh/RadioInterface.h +++ b/src/mesh/RadioInterface.h @@ -129,6 +129,10 @@ class RadioInterface /** The delay to use when we want to send something but the ether is busy */ uint32_t getTxDelayMsec(); + /** The delay to use when we want to send something but the ether is busy. Use a weighted scale based on SNR */ + uint32_t getTxDelayMsecWeighted(float snr); + + /** * Calculate airtime per * https://www.rs-online.com/designspark/rel-assets/ds-assets/uploads/knowledge-items/application-notes-for-the-internet-of-things/LoRa%20Design%20Guide.pdf diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index 67c1ad4a6..0e55e23b0 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -113,7 +113,19 @@ ErrorCode RadioLibInterface::send(MeshPacket *p) // 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 - startTransmitTimer(true); + + /* We assume if rx_snr = 0 and rx_rssi = 0, the packet was not 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) { + startTransmitTimer(true); + } else { + // If there is a SNR, start a timer scaled based on that SNR. + DEBUG_MSG("rx_snr found. hop_limit:%d rx_snr:%f\n", p->hop_limit, p->rx_snr); + startTransmitTimerSNR(p->rx_snr); + } + return res; #else @@ -208,6 +220,16 @@ void RadioLibInterface::startTransmitTimer(bool withDelay) } } +void RadioLibInterface::startTransmitTimerSNR(float snr) +{ + // If we have work to do and the timer wasn't already scheduled, schedule it now + if (!txQueue.empty()) { + uint32_t delay = getTxDelayMsecWeighted(snr); + // DEBUG_MSG("xmit timer %d\n", delay); + notifyLater(delay, TRANSMIT_DELAY_COMPLETED, false); // This will implicitly enable + } +} + void RadioLibInterface::handleTransmitInterrupt() { // DEBUG_MSG("handling lora TX interrupt\n"); diff --git a/src/mesh/RadioLibInterface.h b/src/mesh/RadioLibInterface.h index a394c5f9f..68dfe96d0 100644 --- a/src/mesh/RadioLibInterface.h +++ b/src/mesh/RadioLibInterface.h @@ -148,6 +148,13 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified * */ void startTransmitTimer(bool withDelay = true); + /** if we have something waiting to send, start a short scaled timer based on SNR so we can come check for collision before actually doing + * the transmit + * + * If the timer was already running, we just wait for that one to occur. + * */ + void startTransmitTimerSNR(float snr); + void handleTransmitInterrupt(); void handleReceiveInterrupt();