Compare commits

..

1 Commits

Author SHA1 Message Date
Matthias Wientapper
22f3fb4d4d platformio.ini: Adjust defaults for LoRa frequency and advert interval limits 2026-01-18 11:42:38 +01:00
12 changed files with 36 additions and 98 deletions

View File

@@ -390,14 +390,6 @@ bool MyMesh::allowPacketForward(const mesh::Packet *packet) {
MESH_DEBUG_PRINTLN("allowPacketForward: unknown transport code, or wildcard not allowed for FLOOD packet");
return false;
}
// Limit flood advert paket forwarding using a probabilistic reduction defined by P(h) = 0.308^(hops-1)
// https://github.com/meshcore-dev/MeshCore/issues/1223
double_t roll_dice = (double)rand() / RAND_MAX;
double_t forw_prob = pow(_prefs.flood_advert_base, packet->path_len - 1);
if (packet->getPayloadType() == PAYLOAD_TYPE_ADVERT && packet->isRouteFlood() && roll_dice > forw_prob)
return false;
// all other packets
return true;
}
@@ -719,12 +711,6 @@ bool MyMesh::onPeerPathRecv(mesh::Packet *packet, int sender_idx, const uint8_t
#define CTL_TYPE_NODE_DISCOVER_RESP 0x90
void MyMesh::onControlDataRecv(mesh::Packet* packet) {
if (!packet->payload) {
MESH_DEBUG_PRINTLN("onControlDataRecv: packet->payload is null");
return;
}
#if !defined(STEALTH_MODE)
uint8_t type = packet->payload[0] & 0xF0; // just test upper 4 bits
if (type == CTL_TYPE_NODE_DISCOVER_REQ && packet->payload_len >= 6
&& !_prefs.disable_fwd && discover_limiter.allow(rtc_clock.getCurrentTime())
@@ -753,7 +739,6 @@ void MyMesh::onControlDataRecv(mesh::Packet* packet) {
}
}
}
#endif
}
MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondClock &ms, mesh::RNG &rng,
@@ -796,9 +781,8 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
_prefs.bw = LORA_BW;
_prefs.cr = LORA_CR;
_prefs.tx_power_dbm = LORA_TX_POWER;
_prefs.advert_interval = DEF_LOCAL_ADVERT_INTERVAL;
_prefs.flood_advert_interval = DEF_FLOOD_ADVERT_INTERVAL;
_prefs.flood_advert_base = 0.308f;
_prefs.advert_interval = 1; // default to 2 minutes for NEW installs
_prefs.flood_advert_interval = 12; // 12 hours
_prefs.flood_max = 64;
_prefs.interference_threshold = 0; // disabled
@@ -870,14 +854,10 @@ bool MyMesh::formatFileSystem() {
#endif
}
void MyMesh::sendSelfAdvertisement(int delay_millis, bool flood) {
void MyMesh::sendSelfAdvertisement(int delay_millis) {
mesh::Packet *pkt = createSelfAdvert();
if (pkt) {
if (flood) {
sendFlood(pkt, delay_millis);
} else {
sendZeroHop(pkt, delay_millis);
}
sendFlood(pkt, delay_millis);
} else {
MESH_DEBUG_PRINTLN("ERROR: unable to create advertisement packet!");
}

View File

@@ -186,7 +186,7 @@ public:
void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) override;
bool formatFileSystem() override;
void sendSelfAdvertisement(int delay_millis, bool flood = true) override;
void sendSelfAdvertisement(int delay_millis) override;
void updateAdvertTimer() override;
void updateFloodAdvertTimer() override;

View File

@@ -87,10 +87,8 @@ void setup() {
ui_task.begin(the_mesh.getNodePrefs(), FIRMWARE_BUILD_DATE, FIRMWARE_VERSION);
#endif
#if !defined(STEALTH_MODE) && !defined(NO_BOOT_ADVERT)
// send out initial Zero Hop Advertisement to the mesh
the_mesh.sendSelfAdvertisement(16000, false);
#endif
// send out initial Advertisement to the mesh
the_mesh.sendSelfAdvertisement(16000);
}
void loop() {

View File

@@ -275,15 +275,6 @@ uint32_t MyMesh::getDirectRetransmitDelay(const mesh::Packet *packet) {
bool MyMesh::allowPacketForward(const mesh::Packet *packet) {
if (_prefs.disable_fwd) return false;
if (packet->isRouteFlood() && packet->path_len >= _prefs.flood_max) return false;
// Limit flood advert paket forwarding using a probabilistic reduction defined by P(h) = 0.308^(hops-1)
// https://github.com/meshcore-dev/MeshCore/issues/1223
double_t roll_dice = (double)rand() / RAND_MAX;
double_t forw_prob = pow(_prefs.flood_advert_base, packet->path_len - 1);
if (packet->getPayloadType() == PAYLOAD_TYPE_ADVERT && packet->isRouteFlood() && roll_dice > forw_prob)
return false;
// all other packets
return true;
}
@@ -620,9 +611,8 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
_prefs.cr = LORA_CR;
_prefs.tx_power_dbm = LORA_TX_POWER;
_prefs.disable_fwd = 1;
_prefs.advert_interval = DEF_LOCAL_ADVERT_INTERVAL;
_prefs.flood_advert_interval = DEF_FLOOD_ADVERT_INTERVAL;
_prefs.flood_advert_base = 0.308f;
_prefs.advert_interval = 1; // default to 2 minutes for NEW installs
_prefs.flood_advert_interval = 12; // 12 hours
_prefs.flood_max = 64;
_prefs.interference_threshold = 0; // disabled
#ifdef ROOM_PASSWORD
@@ -685,14 +675,10 @@ bool MyMesh::formatFileSystem() {
#endif
}
void MyMesh::sendSelfAdvertisement(int delay_millis, bool flood) {
void MyMesh::sendSelfAdvertisement(int delay_millis) {
mesh::Packet *pkt = createSelfAdvert();
if (pkt) {
if (flood) {
sendFlood(pkt, delay_millis);
} else {
sendZeroHop(pkt, delay_millis);
}
sendFlood(pkt, delay_millis);
} else {
MESH_DEBUG_PRINTLN("ERROR: unable to create advertisement packet!");
}

View File

@@ -177,7 +177,7 @@ public:
void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) override;
bool formatFileSystem() override;
void sendSelfAdvertisement(int delay_millis, bool flood = true) override;
void sendSelfAdvertisement(int delay_millis) override;
void updateAdvertTimer() override;
void updateFloodAdvertTimer() override;

View File

@@ -76,10 +76,8 @@ void setup() {
ui_task.begin(the_mesh.getNodePrefs(), FIRMWARE_BUILD_DATE, FIRMWARE_VERSION);
#endif
#if !defined(STEALTH_MODE) && !defined(NO_BOOT_ADVERT)
// send out initial Zero Hop Advertisement to the mesh
the_mesh.sendSelfAdvertisement(16000, false);
#endif
// send out initial Advertisement to the mesh
the_mesh.sendSelfAdvertisement(16000);
}
void loop() {

View File

@@ -718,7 +718,7 @@ SensorMesh::SensorMesh(mesh::MainBoard& board, mesh::Radio& radio, mesh::Millise
_prefs.bw = LORA_BW;
_prefs.cr = LORA_CR;
_prefs.tx_power_dbm = LORA_TX_POWER;
_prefs.advert_interval = DEF_LOCAL_ADVERT_INTERVAL;
_prefs.advert_interval = 1; // default to 2 minutes for NEW installs
_prefs.flood_advert_interval = 0; // disabled
_prefs.disable_fwd = true;
_prefs.flood_max = 64;
@@ -788,14 +788,10 @@ void SensorMesh::applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t
revert_radio_at = futureMillis(2000 + timeout_mins*60*1000); // schedule when to revert radio params
}
void SensorMesh::sendSelfAdvertisement(int delay_millis, bool flood) {
void SensorMesh::sendSelfAdvertisement(int delay_millis) {
mesh::Packet* pkt = createSelfAdvert();
if (pkt) {
if (flood) {
sendFlood(pkt, delay_millis);
} else {
sendZeroHop(pkt, delay_millis);
}
sendFlood(pkt, delay_millis);
} else {
MESH_DEBUG_PRINTLN("ERROR: unable to create advertisement packet!");
}

View File

@@ -60,7 +60,7 @@ public:
NodePrefs* getNodePrefs() { return &_prefs; }
void savePrefs() override { _cli.savePrefs(_fs); }
bool formatFileSystem() override;
void sendSelfAdvertisement(int delay_millis, bool flood = true) override;
void sendSelfAdvertisement(int delay_millis) override;
void updateAdvertTimer() override;
void updateFloodAdvertTimer() override;
void setLoggingOn(bool enable) override { }

View File

@@ -110,10 +110,8 @@ void setup() {
ui_task.begin(the_mesh.getNodePrefs(), FIRMWARE_BUILD_DATE, FIRMWARE_VERSION);
#endif
#if !defined(STEALTH_MODE) && !defined(NO_BOOT_ADVERT)
// send out initial Zero Hop Advertisement to the mesh
the_mesh.sendSelfAdvertisement(16000, false);
#endif
// send out initial Advertisement to the mesh
the_mesh.sendSelfAdvertisement(16000);
}
void loop() {

View File

@@ -24,9 +24,10 @@ lib_deps =
melopero/Melopero RV3028 @ ^1.1.0
electroniccats/CayenneLPP @ 1.6.1
build_flags = -w -DNDEBUG
-D LORA_FREQ=869.525
-D LORA_BW=250
-D LORA_SF=11
-D LORA_FREQ=869.618
-D LORA_BW=62.5
-D LORA_SF=8
-D LORA_CR=8
;
-D ENABLE_PRIVATE_KEY_IMPORT=1 ; NOTE: comment these out for more secure firmware
-D ENABLE_PRIVATE_KEY_EXPORT=1
@@ -49,10 +50,10 @@ build_flags = -w -DNDEBUG
-D RADIOLIB_EXCLUDE_SSTV=1
;
-D MIN_LOCAL_ADVERT_INTERVAL=60
-D MAX_LOCAL_ADVERT_INTERVAL=10000
-D MAX_LOCAL_ADVERT_INTERVAL=10080 ; weekly
-D DEF_LOCAL_ADVERT_INTERVAL=1 ; default to 2 minutes for NEW installs
-D MIN_FLOOD_ADVERT_INTERVAL=48
-D MAX_FLOOD_ADVERT_INTERVAL=10000
-D MAX_FLOOD_ADVERT_INTERVAL=8064 ; yearly
-D DEF_FLOOD_ADVERT_INTERVAL=48 ; default to 12 hours for NEW installs
; -D NO_BOOT_ADVERT=1 ; disable boot advertisement
; -D STEALTH_MODE=1 ; disable all advertisements and DISCOVER_REQ

View File

@@ -81,9 +81,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
file.read((uint8_t *)&_prefs->discovery_mod_timestamp, sizeof(_prefs->discovery_mod_timestamp)); // 162
file.read((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166
file.read((uint8_t *)_prefs->owner_info, sizeof(_prefs->owner_info)); // 170
file.read((uint8_t *)&_prefs->flood_advert_base, sizeof(_prefs->flood_advert_base)); // 290
// 294
// 290
// sanitise bad pref values
_prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f);
@@ -110,8 +108,6 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
_prefs->gps_enabled = constrain(_prefs->gps_enabled, 0, 1);
_prefs->advert_loc_policy = constrain(_prefs->advert_loc_policy, 0, 2);
_prefs->flood_advert_base = constrain(_prefs->flood_advert_base, 0, 1);
file.close();
}
}
@@ -169,14 +165,14 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
file.write((uint8_t *)&_prefs->discovery_mod_timestamp, sizeof(_prefs->discovery_mod_timestamp)); // 162
file.write((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166
file.write((uint8_t *)_prefs->owner_info, sizeof(_prefs->owner_info)); // 170
file.write((uint8_t *)&_prefs->flood_advert_base, sizeof(_prefs->flood_advert_base)); // 290
// 294
// 290
file.close();
}
}
#define MIN_LOCAL_ADVERT_INTERVAL 60
void CommonCLI::savePrefs() {
if (_prefs->advert_interval * 2 < MIN_LOCAL_ADVERT_INTERVAL) {
_prefs->advert_interval = 0; // turn it off, now that device has been manually configured
@@ -201,7 +197,6 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
if (memcmp(command, "reboot", 6) == 0) {
_board->reboot(); // doesn't return
} else if (memcmp(command, "advert", 6) == 0) {
// Keep "advert" as flood for backward compatibility
_callbacks->sendSelfAdvertisement(1500); // longer delay, give CLI response time to be sent first
strcpy(reply, "OK - Advert sent");
} else if (memcmp(command, "clock sync", 10) == 0) {
@@ -222,7 +217,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
uint32_t now = getRTCClock()->getCurrentTime();
DateTime dt = DateTime(now);
sprintf(reply, "%02d:%02d - %d/%d/%d UTC", dt.hour(), dt.minute(), dt.day(), dt.month(), dt.year());
} else if (memcmp(command, "time ", 5) == 0) { // set time (to epoch seconds)
} else if (memcmp(command, "time ", 5) == 0) { // set time (to epoch seconds)
uint32_t secs = _atoi(&command[5]);
uint32_t curr = getRTCClock()->getCurrentTime();
if (secs > curr) {
@@ -369,8 +364,6 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
} else {
sprintf(reply, "> %.3f", adc_mult);
}
} else if (memcmp(config, "flood.advert.base", 17) == 0) {
sprintf(reply, "> %s", StrHelper::ftoa(_prefs->flood_advert_base));
} else {
sprintf(reply, "??: %s", config);
}
@@ -401,9 +394,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
strcpy(reply, "OK");
} else if (memcmp(config, "flood.advert.interval ", 22) == 0) {
int hours = _atoi(&config[22]);
if ((hours > 0 && hours < MIN_FLOOD_ADVERT_INTERVAL) || (hours > MAX_FLOOD_ADVERT_INTERVAL)) {
sprintf(reply, "Error: interval range is %d-%d hours", MIN_FLOOD_ADVERT_INTERVAL,
MAX_FLOOD_ADVERT_INTERVAL);
if ((hours > 0 && hours < 3) || (hours > 48)) {
strcpy(reply, "Error: interval range is 3-48 hours");
} else {
_prefs->flood_advert_interval = (uint8_t)(hours);
_callbacks->updateFloodAdvertTimer();
@@ -412,9 +404,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
}
} else if (memcmp(config, "advert.interval ", 16) == 0) {
int mins = _atoi(&config[16]);
if ((mins > 0 && mins < MIN_LOCAL_ADVERT_INTERVAL) || (mins > MAX_LOCAL_ADVERT_INTERVAL)) {
sprintf(reply, "Error: interval range is %d-%d minutes",MIN_LOCAL_ADVERT_INTERVAL,
MAX_LOCAL_ADVERT_INTERVAL);
if ((mins > 0 && mins < MIN_LOCAL_ADVERT_INTERVAL) || (mins > 240)) {
sprintf(reply, "Error: interval range is %d-240 minutes", MIN_LOCAL_ADVERT_INTERVAL);
} else {
_prefs->advert_interval = (uint8_t)(mins / 2);
_callbacks->updateAdvertTimer();
@@ -592,15 +583,6 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
_prefs->adc_multiplier = 0.0f;
strcpy(reply, "Error: unsupported by this board");
};
} else if (memcmp(config, "flood.advert.base ", 18) == 0) {
float f = atof(&config[18]);
if((f > 0) || (f<1)) {
_prefs->flood_advert_base = f;
savePrefs();
strcpy(reply, "OK");
} else {
strcpy(reply, "Error: base must be between 0 and 1");
}
} else {
sprintf(reply, "unknown config: %s", config);
}

View File

@@ -35,7 +35,6 @@ struct NodePrefs { // persisted to file
uint8_t flood_max;
uint8_t interference_threshold;
uint8_t agc_reset_interval; // secs / 4
float flood_advert_base;
// Bridge settings
uint8_t bridge_enabled; // boolean
uint16_t bridge_delay; // milliseconds (default 500 ms)
@@ -61,7 +60,7 @@ public:
virtual const char* getBuildDate() = 0;
virtual const char* getRole() = 0;
virtual bool formatFileSystem() = 0;
virtual void sendSelfAdvertisement(int delay_millis, bool flood = true) = 0;
virtual void sendSelfAdvertisement(int delay_millis) = 0;
virtual void updateAdvertTimer() = 0;
virtual void updateFloodAdvertTimer() = 0;
virtual void setLoggingOn(bool enable) = 0;