kopia lustrzana https://github.com/meshtastic/firmware
Merge pull request #1292 from mc-hamster/router
Add weighted tx delay for flooding routerpull/1293/head
commit
abc0579e75
|
@ -27,57 +27,10 @@ bool FloodingRouter::shouldFilterReceived(MeshPacket *p)
|
||||||
return Router::shouldFilterReceived(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)
|
void FloodingRouter::sniffReceived(const MeshPacket *p, const Routing *c)
|
||||||
{
|
{
|
||||||
bool rebroadcastPacket = true;
|
|
||||||
|
|
||||||
if (radioConfig.preferences.role == Role_Repeater || radioConfig.preferences.role == Role_Router) {
|
if ((p->to == NODENUM_BROADCAST) && (p->hop_limit > 0) && (getFrom(p) != getNodeNum())) {
|
||||||
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->id != 0) {
|
if (p->id != 0) {
|
||||||
MeshPacket *tosend = packetPool.allocCopy(*p); // keep a copy because we will be sending it
|
MeshPacket *tosend = packetPool.allocCopy(*p); // keep a copy because we will be sending it
|
||||||
|
|
||||||
|
|
|
@ -52,22 +52,6 @@ class FloodingRouter : public Router, protected PacketHistory
|
||||||
*/
|
*/
|
||||||
virtual bool shouldFilterReceived(MeshPacket *p) override;
|
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
|
* Look for broadcasts we need to rebroadcast
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -180,7 +180,38 @@ uint32_t RadioInterface::getTxDelayMsec()
|
||||||
*/
|
*/
|
||||||
// const uint32_t MAX_TX_WAIT_MSEC = 2000; // stress test would still fail occasionally with 1000
|
// 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)
|
void printPacket(const char *prefix, const MeshPacket *p)
|
||||||
|
|
|
@ -129,6 +129,10 @@ class RadioInterface
|
||||||
/** The delay to use when we want to send something but the ether is busy */
|
/** The delay to use when we want to send something but the ether is busy */
|
||||||
uint32_t getTxDelayMsec();
|
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
|
* 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
|
* https://www.rs-online.com/designspark/rel-assets/ds-assets/uploads/knowledge-items/application-notes-for-the-internet-of-things/LoRa%20Design%20Guide.pdf
|
||||||
|
|
|
@ -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
|
// 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
|
// 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;
|
return res;
|
||||||
#else
|
#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()
|
void RadioLibInterface::handleTransmitInterrupt()
|
||||||
{
|
{
|
||||||
// DEBUG_MSG("handling lora TX interrupt\n");
|
// DEBUG_MSG("handling lora TX interrupt\n");
|
||||||
|
|
|
@ -148,6 +148,13 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
|
||||||
* */
|
* */
|
||||||
void startTransmitTimer(bool withDelay = true);
|
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 handleTransmitInterrupt();
|
||||||
void handleReceiveInterrupt();
|
void handleReceiveInterrupt();
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue