Merge branch 'dev' into solar-watchdog

This commit is contained in:
Quency-D 2026-02-09 10:15:50 +08:00 committed by GitHub
commit 9df34e09d0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
254 changed files with 5226 additions and 972 deletions

View file

@ -226,7 +226,7 @@ int MyMesh::handleRequest(ClientInfo *sender, uint32_t sender_timestamp, uint8_t
stats.n_direct_dups = ((SimpleMeshTables *)getTables())->getNumDirectDups();
stats.n_flood_dups = ((SimpleMeshTables *)getTables())->getNumFloodDups();
stats.total_rx_air_time_secs = getReceiveAirTime() / 1000;
stats.n_recv_errors = radio_driver.getPacketsRecvErrors();
memcpy(&reply_data[4], &stats, sizeof(stats));
return 4 + sizeof(stats); // reply_len
@ -744,7 +744,7 @@ void MyMesh::onControlDataRecv(mesh::Packet* packet) {
MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondClock &ms, mesh::RNG &rng,
mesh::RTCClock &rtc, mesh::MeshTables &tables)
: mesh::Mesh(radio, ms, rng, rtc, *new StaticPoolPacketManager(32), tables),
_cli(board, rtc, sensors, &_prefs, this), telemetry(MAX_PACKET_PAYLOAD - 4), region_map(key_store), temp_map(key_store),
_cli(board, rtc, sensors, acl, &_prefs, this), telemetry(MAX_PACKET_PAYLOAD - 4), region_map(key_store), temp_map(key_store),
discover_limiter(4, 120), // max 4 every 2 minutes
anon_limiter(4, 180) // max 4 every 3 minutes
#if defined(WITH_RS232_BRIDGE)
@ -808,7 +808,7 @@ void MyMesh::begin(FILESYSTEM *fs) {
_fs = fs;
// load persisted prefs
_cli.loadPrefs(_fs);
acl.load(_fs);
acl.load(_fs, self_id);
// TODO: key_store.begin();
region_map.load(_fs);
@ -854,10 +854,14 @@ bool MyMesh::formatFileSystem() {
#endif
}
void MyMesh::sendSelfAdvertisement(int delay_millis) {
void MyMesh::sendSelfAdvertisement(int delay_millis, bool flood) {
mesh::Packet *pkt = createSelfAdvert();
if (pkt) {
sendFlood(pkt, delay_millis);
if (flood) {
sendFlood(pkt, delay_millis);
} else {
sendZeroHop(pkt, delay_millis);
}
} else {
MESH_DEBUG_PRINTLN("ERROR: unable to create advertisement packet!");
}
@ -895,7 +899,7 @@ void MyMesh::dumpLogFile() {
}
}
void MyMesh::setTxPower(uint8_t power_dbm) {
void MyMesh::setTxPower(int8_t power_dbm) {
radio_set_tx_power(power_dbm);
}
@ -968,7 +972,6 @@ void MyMesh::formatPacketStatsReply(char *reply) {
}
void MyMesh::saveIdentity(const mesh::LocalIdentity &new_id) {
self_id = new_id;
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
IdentityStore store(*_fs, "");
#elif defined(ESP32)
@ -978,7 +981,7 @@ void MyMesh::saveIdentity(const mesh::LocalIdentity &new_id) {
#else
#error "need to define saveIdentity()"
#endif
store.save("_main", self_id);
store.save("_main", new_id);
}
void MyMesh::clearStats() {
@ -1069,8 +1072,8 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, char *command, char *reply
const char* parts[4];
int n = mesh::Utils::parseTextParts(command, parts, 4, ' ');
if (n == 1 && sender_timestamp == 0) {
region_map.exportTo(Serial);
if (n == 1) {
region_map.exportTo(reply, 160);
} else if (n >= 2 && strcmp(parts[1], "load") == 0) {
temp_map.resetFrom(region_map); // rebuild regions in a temp instance
memset(load_stack, 0, sizeof(load_stack));
@ -1143,6 +1146,25 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, char *command, char *reply
} else {
strcpy(reply, "Err - not found");
}
} else if (n >= 3 && strcmp(parts[1], "list") == 0) {
uint8_t mask = 0;
bool invert = false;
if (strcmp(parts[2], "allowed") == 0) {
mask = REGION_DENY_FLOOD;
invert = false; // list regions that DON'T have DENY flag
} else if (strcmp(parts[2], "denied") == 0) {
mask = REGION_DENY_FLOOD;
invert = true; // list regions that DO have DENY flag
} else {
strcpy(reply, "Err - use 'allowed' or 'denied'");
return;
}
int len = region_map.exportNamesTo(reply, 160, mask, invert);
if (len == 0) {
strcpy(reply, "-none-");
}
} else {
strcpy(reply, "Err - ??");
}
@ -1197,5 +1219,8 @@ void MyMesh::loop() {
// To check if there is pending work
bool MyMesh::hasPendingWork() const {
#if defined(WITH_BRIDGE)
if (bridge.isRunning()) return true; // bridge needs WiFi radio, can't sleep
#endif
return _mgr->getOutboundCount(0xFFFFFFFF) > 0;
}

View file

@ -54,6 +54,7 @@ struct RepeaterStats {
int16_t last_snr; // x 4
uint16_t n_direct_dups, n_flood_dups;
uint32_t total_rx_air_time_secs;
uint32_t n_recv_errors;
};
#ifndef MAX_CLIENTS
@ -68,11 +69,11 @@ struct NeighbourInfo {
};
#ifndef FIRMWARE_BUILD_DATE
#define FIRMWARE_BUILD_DATE "30 Nov 2025"
#define FIRMWARE_BUILD_DATE "29 Jan 2026"
#endif
#ifndef FIRMWARE_VERSION
#define FIRMWARE_VERSION "v1.11.0"
#define FIRMWARE_VERSION "v1.12.0"
#endif
#define FIRMWARE_ROLE "repeater"
@ -86,11 +87,11 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
unsigned long next_local_advert, next_flood_advert;
bool _logging;
NodePrefs _prefs;
ClientACL acl;
CommonCLI _cli;
uint8_t reply_data[MAX_PACKET_PAYLOAD];
uint8_t reply_path[MAX_PATH_SIZE];
int8_t reply_path_len;
ClientACL acl;
TransportKeyStore key_store;
RegionMap region_map, temp_map;
RegionEntry* load_stack[8];
@ -186,7 +187,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) override;
void sendSelfAdvertisement(int delay_millis, bool flood) override;
void updateAdvertTimer() override;
void updateFloodAdvertTimer() override;
@ -197,7 +198,7 @@ public:
}
void dumpLogFile() override;
void setTxPower(uint8_t power_dbm) override;
void setTxPower(int8_t power_dbm) override;
void formatNeighborsReply(char *reply) override;
void removeNeighbor(const uint8_t* pubkey, int key_len) override;
void formatStatsReply(char *reply) override;

View file

@ -29,8 +29,10 @@ void setup() {
board.begin();
#ifdef HAS_EX_WATCHDOG
ex_watchdog.begin();
#if defined(MESH_DEBUG) && defined(NRF52_PLATFORM)
// give some extra time for serial to settle so
// boot debug messages can be seen on terminal
delay(5000);
#endif
// For power saving
@ -46,6 +48,7 @@ void setup() {
#endif
if (!radio_init()) {
MESH_DEBUG_PRINTLN("Radio init failed!");
halt();
}
@ -91,8 +94,10 @@ void setup() {
ui_task.begin(the_mesh.getNodePrefs(), FIRMWARE_BUILD_DATE, FIRMWARE_VERSION);
#endif
// send out initial Advertisement to the mesh
the_mesh.sendSelfAdvertisement(16000);
// send out initial zero hop Advertisement to the mesh
#if ENABLE_ADVERT_ON_BOOT == 1
the_mesh.sendSelfAdvertisement(16000, false);
#endif
}
void loop() {
@ -128,15 +133,12 @@ void loop() {
ui_task.loop();
#endif
rtc_clock.tick();
#ifdef HAS_EX_WATCHDOG
ex_watchdog.loop();
#endif
if (the_mesh.getNodePrefs()->powersaving_enabled && // To check if power saving is enabled
the_mesh.millisHasNowPassed(lastActive + nextSleepinSecs * 1000)) { // To check if it is time to sleep
if (!the_mesh.hasPendingWork()) { // No pending work. Safe to sleep
#ifdef HAS_EX_WATCHDOG
board.sleep(ex_watchdog.getIntervalMs()>1800?1800:ex_watchdog.getIntervalMs()); // To sleep. Wake up after 30 minutes or when receiving a LoRa packet
#else
if (the_mesh.getNodePrefs()->powersaving_enabled && !the_mesh.hasPendingWork()) {
#if defined(NRF52_PLATFORM)
board.sleep(1800); // nrf ignores seconds param, sleeps whenever possible
#else
if (the_mesh.millisHasNowPassed(lastActive + nextSleepinSecs * 1000)) { // To check if it is time to sleep
board.sleep(1800); // To sleep. Wake up after 30 minutes or when receiving a LoRa packet
#endif
lastActive = millis();
@ -144,5 +146,6 @@ void loop() {
} else {
nextSleepinSecs += 5; // When there is pending work, to work another 5s
}
#endif
}
}