Merge remote-tracking branch 'upstream/dev' into 2026/remote-lna

This commit is contained in:
João Brázio 2026-03-05 17:21:38 +00:00
commit 8df87d5609
No known key found for this signature in database
GPG key ID: 56A1490716A324DD
37 changed files with 308 additions and 73 deletions

View file

@ -229,7 +229,8 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no
file.read((uint8_t *)&_prefs.gps_enabled, sizeof(_prefs.gps_enabled)); // 85
file.read((uint8_t *)&_prefs.gps_interval, sizeof(_prefs.gps_interval)); // 86
file.read((uint8_t *)&_prefs.autoadd_config, sizeof(_prefs.autoadd_config)); // 87
file.read((uint8_t *)&_prefs.sx126x_rx_boosted_gain, sizeof(_prefs.sx126x_rx_boosted_gain)); // 88
file.read((uint8_t *)&_prefs.autoadd_max_hops, sizeof(_prefs.autoadd_max_hops)); // 88
file.read((uint8_t *)&_prefs.sx126x_rx_boosted_gain, sizeof(_prefs.sx126x_rx_boosted_gain)); // 89
file.close();
}
@ -266,7 +267,8 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_
file.write((uint8_t *)&_prefs.gps_enabled, sizeof(_prefs.gps_enabled)); // 85
file.write((uint8_t *)&_prefs.gps_interval, sizeof(_prefs.gps_interval)); // 86
file.write((uint8_t *)&_prefs.autoadd_config, sizeof(_prefs.autoadd_config)); // 87
file.write((uint8_t *)&_prefs.sx126x_rx_boosted_gain, sizeof(_prefs.sx126x_rx_boosted_gain)); // 88
file.write((uint8_t *)&_prefs.autoadd_max_hops, sizeof(_prefs.autoadd_max_hops)); // 88
file.write((uint8_t *)&_prefs.sx126x_rx_boosted_gain, sizeof(_prefs.sx126x_rx_boosted_gain)); // 89
file.close();
}

View file

@ -318,6 +318,10 @@ bool MyMesh::shouldOverwriteWhenFull() const {
return (_prefs.autoadd_config & AUTO_ADD_OVERWRITE_OLDEST) != 0;
}
uint8_t MyMesh::getAutoAddMaxHops() const {
return _prefs.autoadd_max_hops;
}
void MyMesh::onContactOverwrite(const uint8_t* pub_key) {
_store->deleteBlobByKey(pub_key, PUB_KEY_SIZE); // delete from storage
if (_serial->isConnected()) {
@ -1797,12 +1801,16 @@ void MyMesh::handleCmdFrame(size_t len) {
}
} else if (cmd_frame[0] == CMD_SET_AUTOADD_CONFIG) {
_prefs.autoadd_config = cmd_frame[1];
if (len >= 3) {
_prefs.autoadd_max_hops = min(cmd_frame[2], (uint8_t)64);
}
savePrefs();
writeOKFrame();
writeOKFrame();
} else if (cmd_frame[0] == CMD_GET_AUTOADD_CONFIG) {
int i = 0;
out_frame[i++] = RESP_CODE_AUTOADD_CONFIG;
out_frame[i++] = _prefs.autoadd_config;
out_frame[i++] = _prefs.autoadd_max_hops;
_serial->writeFrame(out_frame, i);
} else if (cmd_frame[0] == CMD_GET_ALLOWED_REPEAT_FREQ) {
int i = 0;

View file

@ -119,6 +119,7 @@ protected:
bool isAutoAddEnabled() const override;
bool shouldAutoAddContactType(uint8_t type) const override;
bool shouldOverwriteWhenFull() const override;
uint8_t getAutoAddMaxHops() const override;
void onContactsFull() override;
void onContactOverwrite(const uint8_t* pub_key) override;
bool onContactPathRecv(ContactInfo& from, uint8_t* in_path, uint8_t in_path_len, uint8_t* out_path, uint8_t out_path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override;

View file

@ -31,4 +31,5 @@ struct NodePrefs { // persisted to file
uint8_t sx126x_rx_boosted_gain; // SX126x RX boosted gain mode (0=power saving, 1=boosted)
uint8_t client_repeat;
uint8_t path_hash_mode; // which path mode to use when sending
uint8_t autoadd_max_hops; // 0 = no limit, 1 = direct (0 hops), N = up to N-1 hops (max 64)
};

View file

@ -396,6 +396,23 @@ File MyMesh::openAppend(const char *fname) {
#endif
}
static uint8_t max_loop_minimal[] = { 0, /* 1-byte */ 4, /* 2-byte */ 2, /* 3-byte */ 1 };
static uint8_t max_loop_moderate[] = { 0, /* 1-byte */ 2, /* 2-byte */ 1, /* 3-byte */ 1 };
static uint8_t max_loop_strict[] = { 0, /* 1-byte */ 1, /* 2-byte */ 1, /* 3-byte */ 1 };
bool MyMesh::isLooped(const mesh::Packet* packet, const uint8_t max_counters[]) {
uint8_t hash_size = packet->getPathHashSize();
uint8_t hash_count = packet->getPathHashCount();
uint8_t n = 0;
const uint8_t* path = packet->path;
while (hash_count > 0) { // count how many times this node is already in the path
if (self_id.isHashMatch(path, hash_size)) n++;
hash_count--;
path += hash_size;
}
return n >= max_counters[hash_size];
}
bool MyMesh::allowPacketForward(const mesh::Packet *packet) {
if (_prefs.disable_fwd) return false;
if (packet->isRouteFlood() && packet->getPathHashCount() >= _prefs.flood_max) return false;
@ -403,6 +420,20 @@ bool MyMesh::allowPacketForward(const mesh::Packet *packet) {
MESH_DEBUG_PRINTLN("allowPacketForward: unknown transport code, or wildcard not allowed for FLOOD packet");
return false;
}
if (packet->isRouteFlood() && _prefs.loop_detect != LOOP_DETECT_OFF) {
const uint8_t* maximums;
if (_prefs.loop_detect == LOOP_DETECT_MINIMAL) {
maximums = max_loop_minimal;
} else if (_prefs.loop_detect == LOOP_DETECT_MODERATE) {
maximums = max_loop_moderate;
} else {
maximums = max_loop_strict;
}
if (isLooped(packet, maximums)) {
MESH_DEBUG_PRINTLN("allowPacketForward: FLOOD packet loop detected!");
return false;
}
}
return true;
}

View file

@ -128,6 +128,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
mesh::Packet* createSelfAdvert();
File openAppend(const char* fname);
bool isLooped(const mesh::Packet* packet, const uint8_t max_counters[]);
protected:
float getAirtimeBudgetFactor() const override {