mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-09-17 16:46:37 +00:00
Merge upstream companion-v1.17.0 (CAD) into power-saving
Adopts hardware Channel Activity Detection (wired into RadioLibWrapper::isChannelActive() alongside our RSSI-threshold check and RX duty-cycle power-save), MCU temperature telemetry, LR2021 standby workaround, DISPLAY_SCALE/FLIP overrides, NRF52Board shutdownPeripherals() refactor, and misc upstream fixes. Declines upstream's ConfigSerializer-based NodePrefs rewrite, MultiSerialInterface/interface_manager, and UIColor palette system — each would have broken large parts of the Solo-specific feature set (NodePrefs fields, per-variant single serial_interface, enum-based DisplayDriver::Color). Flagged as candidate follow-up migrations, not permanent no's. Also fixes several pre-existing bugs surfaced while chasing silent merge breaks (stale newMsg() override signature in ui-tiny/ui-orig, dead UIEventType::newContactMessage case, missing ContactsIterator init), bumps FIRMWARE_VERSION/MESHCORE_VERSION to 1.17, and fixes a missing <cstdlib> include that broke the native ConfigSerializer unit tests. Verified via 13+ pio run builds across ESP32/nRF52, all 3 companion UI variants, and 7 display drivers, plus the full native unit test suite (33/33 passing). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -39,18 +39,35 @@ struct ServerStats {
|
||||
};
|
||||
|
||||
void MyMesh::addPost(ClientInfo *client, const char *postData) {
|
||||
// TODO: suggested postData format: <title>/<descrption>
|
||||
posts[next_post_idx].author = client->id; // add to cyclic queue
|
||||
StrHelper::strncpy(posts[next_post_idx].text, postData, MAX_POST_TEXT_LEN);
|
||||
storePost(client->id, postData);
|
||||
}
|
||||
|
||||
posts[next_post_idx].post_timestamp = getRTCClock()->getCurrentTimeUnique();
|
||||
void MyMesh::addSystemPost(const char *postData) {
|
||||
if (!postData || postData[0] == 0) return;
|
||||
|
||||
MESH_DEBUG_PRINTLN("room.post: addSystemPost: %s", postData);
|
||||
|
||||
storePost(self_id, postData);
|
||||
}
|
||||
|
||||
void MyMesh::storePost(const mesh::Identity &author, const char *postData) {
|
||||
int idx = next_post_idx;
|
||||
// TODO: suggested postData format: <title>/<descrption>
|
||||
posts[idx].author = author; // add to cyclic queue
|
||||
StrHelper::strncpy(posts[idx].text, postData, MAX_POST_TEXT_LEN);
|
||||
|
||||
posts[idx].post_timestamp = getRTCClock()->getCurrentTimeUnique();
|
||||
MESH_DEBUG_PRINTLN("room.post: storePost idx=%d text=%s", idx, posts[idx].text);
|
||||
MESH_DEBUG_PRINTLN("room.post: timestamp=%u", posts[idx].post_timestamp);
|
||||
next_post_idx = (next_post_idx + 1) % MAX_UNSYNCED_POSTS;
|
||||
|
||||
next_push = futureMillis(PUSH_NOTIFY_DELAY_MILLIS);
|
||||
_num_posted++; // stats
|
||||
MESH_DEBUG_PRINTLN("room.post: next_post_idx=%d num_posted=%d push scheduled", next_post_idx, _num_posted);
|
||||
}
|
||||
|
||||
void MyMesh::pushPostToClient(ClientInfo *client, PostInfo &post) {
|
||||
MESH_DEBUG_PRINTLN("room.post: pushPostToClient text=%s", post.text);
|
||||
int len = 0;
|
||||
memcpy(&reply_data[len], &post.post_timestamp, 4);
|
||||
len += 4; // this is a PAST timestamp... but should be accepted by client
|
||||
@@ -290,8 +307,7 @@ bool MyMesh::allowPacketForward(const mesh::Packet *packet) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MyMesh::filterRecvFloodPacket(mesh::Packet* pkt) {
|
||||
// just try to determine region for packet (apply later in allowPacketForward())
|
||||
mesh::DispatcherAction MyMesh::onRecvPacket(mesh::Packet* pkt) {
|
||||
if (pkt->getRouteType() == ROUTE_TYPE_TRANSPORT_FLOOD) {
|
||||
recv_pkt_region = region_map.findMatch(pkt, REGION_DENY_FLOOD);
|
||||
} else if (pkt->getRouteType() == ROUTE_TYPE_FLOOD) {
|
||||
@@ -303,8 +319,7 @@ bool MyMesh::filterRecvFloodPacket(mesh::Packet* pkt) {
|
||||
} else {
|
||||
recv_pkt_region = NULL;
|
||||
}
|
||||
// do normal processing
|
||||
return false;
|
||||
return Mesh::onRecvPacket(pkt);
|
||||
}
|
||||
|
||||
void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const mesh::Identity &sender,
|
||||
@@ -627,9 +642,9 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
|
||||
_logging = false;
|
||||
region_load_active = false;
|
||||
set_radio_at = revert_radio_at = 0;
|
||||
recv_pkt_region = NULL;
|
||||
|
||||
// defaults
|
||||
memset(&_prefs, 0, sizeof(_prefs));
|
||||
_prefs.airtime_factor = 1.0;
|
||||
_prefs.rx_delay_base = 0.0f; // off by default, was 10.0
|
||||
_prefs.tx_delay_factor = 0.5f; // was 0.25f;
|
||||
@@ -650,6 +665,7 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
|
||||
_prefs.flood_max_unscoped = 64;
|
||||
_prefs.flood_max_advert = 8;
|
||||
_prefs.interference_threshold = 0; // disabled
|
||||
_prefs.cad_enabled = 0; // hardware CAD before TX (off by default; 'set cad on')
|
||||
#ifdef ROOM_PASSWORD
|
||||
StrHelper::strncpy(_prefs.guest_password, ROOM_PASSWORD, sizeof(_prefs.guest_password));
|
||||
#endif
|
||||
@@ -659,6 +675,15 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
|
||||
_prefs.gps_interval = 0;
|
||||
_prefs.advert_loc_policy = ADVERT_LOC_PREFS;
|
||||
|
||||
#if defined(USE_SX1262) || defined(USE_SX1268)
|
||||
#ifdef SX126X_RX_BOOSTED_GAIN
|
||||
_prefs.rx_boosted_gain = SX126X_RX_BOOSTED_GAIN;
|
||||
#else
|
||||
_prefs.rx_boosted_gain = 1; // enabled by default;
|
||||
#endif
|
||||
#endif
|
||||
_prefs.radio_fem_rxgain = 1;
|
||||
|
||||
next_post_idx = 0;
|
||||
next_client_idx = 0;
|
||||
next_push = 0;
|
||||
@@ -699,6 +724,8 @@ void MyMesh::begin(FILESYSTEM *fs) {
|
||||
|
||||
radio_driver.setParams(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr);
|
||||
radio_driver.setTxPower(_prefs.tx_power_dbm);
|
||||
radio_driver.setRxBoostedGainMode(_prefs.rx_boosted_gain);
|
||||
board.setLoRaFemLnaEnabled(_prefs.radio_fem_rxgain);
|
||||
|
||||
updateAdvertTimer();
|
||||
updateFloodAdvertTimer();
|
||||
@@ -805,6 +832,10 @@ void MyMesh::setTxPower(int8_t power_dbm) {
|
||||
radio_driver.setTxPower(power_dbm);
|
||||
}
|
||||
|
||||
bool MyMesh::setRxBoostedGain(bool enable) {
|
||||
return radio_driver.setRxBoostedGainMode(enable);
|
||||
}
|
||||
|
||||
void MyMesh::saveIdentity(const mesh::LocalIdentity &new_id) {
|
||||
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
||||
IdentityStore store(*_fs, "");
|
||||
@@ -934,6 +965,15 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, char *command, char *reply
|
||||
Serial.printf("\n");
|
||||
}
|
||||
reply[0] = 0;
|
||||
} else if (strncmp(command, "room.post", 9) == 0) {
|
||||
char* msg = command + 9;
|
||||
while (*msg == ' ') msg++;
|
||||
if (*msg == 0) {
|
||||
snprintf(reply, MAX_POST_TEXT_LEN, "ERR empty message");
|
||||
} else {
|
||||
addSystemPost(msg);
|
||||
snprintf(reply, MAX_POST_TEXT_LEN, "OK");
|
||||
}
|
||||
} else{
|
||||
_cli.handleCommand(sender_timestamp, command, reply); // common CLI commands
|
||||
}
|
||||
|
||||
@@ -27,11 +27,11 @@
|
||||
/* ------------------------------ Config -------------------------------- */
|
||||
|
||||
#ifndef FIRMWARE_BUILD_DATE
|
||||
#define FIRMWARE_BUILD_DATE "6 Jun 2026"
|
||||
#define FIRMWARE_BUILD_DATE "9 Aug 2026"
|
||||
#endif
|
||||
|
||||
#ifndef FIRMWARE_VERSION
|
||||
#define FIRMWARE_VERSION "v1.16.0"
|
||||
#define FIRMWARE_VERSION "v1.17.0"
|
||||
#endif
|
||||
|
||||
#ifndef LORA_FREQ
|
||||
@@ -119,6 +119,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
|
||||
int matching_peer_indexes[MAX_CLIENTS];
|
||||
|
||||
void addPost(ClientInfo* client, const char* postData);
|
||||
void storePost(const mesh::Identity& author, const char* postData);
|
||||
void pushPostToClient(ClientInfo* client, PostInfo& post);
|
||||
uint8_t getUnsyncedCount(ClientInfo* client);
|
||||
bool processAck(const uint8_t *data);
|
||||
@@ -144,6 +145,9 @@ protected:
|
||||
int getInterferenceThreshold() const override {
|
||||
return _prefs.interference_threshold;
|
||||
}
|
||||
bool getCADEnabled() const override {
|
||||
return _prefs.cad_enabled;
|
||||
}
|
||||
int getAGCResetInterval() const override {
|
||||
return ((int)_prefs.agc_reset_interval) * 4000; // milliseconds
|
||||
}
|
||||
@@ -151,7 +155,7 @@ protected:
|
||||
return _prefs.multi_acks;
|
||||
}
|
||||
|
||||
bool filterRecvFloodPacket(mesh::Packet* pkt) override;
|
||||
mesh::DispatcherAction onRecvPacket(mesh::Packet* pkt) override;
|
||||
|
||||
bool allowPacketForward(const mesh::Packet* packet) override;
|
||||
void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override;
|
||||
@@ -173,6 +177,7 @@ public:
|
||||
MyMesh(mesh::MainBoard& board, mesh::Radio& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::MeshTables& tables);
|
||||
|
||||
void begin(FILESYSTEM* fs);
|
||||
void addSystemPost(const char* postData);
|
||||
|
||||
const char* getFirmwareVer() override { return FIRMWARE_VERSION; }
|
||||
const char* getBuildDate() override { return FIRMWARE_BUILD_DATE; }
|
||||
@@ -203,6 +208,7 @@ public:
|
||||
|
||||
void dumpLogFile() override;
|
||||
void setTxPower(int8_t power_dbm) override;
|
||||
bool setRxBoostedGain(bool enable) override;
|
||||
|
||||
void formatNeighborsReply(char *reply) override {
|
||||
strcpy(reply, "not supported");
|
||||
|
||||
@@ -41,7 +41,8 @@ void UITask::begin(NodePrefs* node_prefs, const char* build_date, const char* fi
|
||||
}
|
||||
|
||||
// v1.2.3 (1 Jan 2025)
|
||||
sprintf(_version_info, "%s (%s)", version, build_date);
|
||||
snprintf(_version_info, sizeof(_version_info), "%s (%s)", version, build_date);
|
||||
free(version);
|
||||
}
|
||||
|
||||
void UITask::renderCurrScreen() {
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
|
||||
#include "MyMesh.h"
|
||||
|
||||
#ifdef ETHERNET_ENABLED
|
||||
#define ETHERNET_CLI_BANNER "MeshCore Room Server CLI"
|
||||
#include <helpers/nrf52/EthernetCLI.h>
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
#include "UITask.h"
|
||||
static UITask ui_task(display);
|
||||
@@ -17,6 +22,9 @@ void halt() {
|
||||
}
|
||||
|
||||
static char command[MAX_POST_TEXT_LEN+1];
|
||||
#ifdef ETHERNET_ENABLED
|
||||
static char ethernet_command[MAX_POST_TEXT_LEN+1];
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
@@ -24,6 +32,10 @@ void setup() {
|
||||
|
||||
board.begin();
|
||||
|
||||
#ifdef HAS_EXTERNAL_WATCHDOG
|
||||
external_watchdog.begin();
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
if (display.begin()) {
|
||||
display.startFrame();
|
||||
@@ -67,6 +79,9 @@ void setup() {
|
||||
mesh::Utils::printHex(Serial, the_mesh.self_id.pub_key, PUB_KEY_SIZE); Serial.println();
|
||||
|
||||
command[0] = 0;
|
||||
#ifdef ETHERNET_ENABLED
|
||||
ethernet_command[0] = 0;
|
||||
#endif
|
||||
|
||||
sensors.begin();
|
||||
|
||||
@@ -76,6 +91,10 @@ void setup() {
|
||||
ui_task.begin(the_mesh.getNodePrefs(), FIRMWARE_BUILD_DATE, FIRMWARE_VERSION);
|
||||
#endif
|
||||
|
||||
#ifdef ETHERNET_ENABLED
|
||||
ethernet_start_task();
|
||||
#endif
|
||||
|
||||
// send out initial zero hop Advertisement to the mesh
|
||||
#if ENABLE_ADVERT_ON_BOOT == 1
|
||||
the_mesh.sendSelfAdvertisement(16000, false);
|
||||
@@ -101,7 +120,14 @@ void loop() {
|
||||
if (len > 0 && command[len - 1] == '\r') { // received complete line
|
||||
command[len - 1] = 0; // replace newline with C string null terminator
|
||||
char reply[160];
|
||||
reply[0] = 0;
|
||||
#ifdef ETHERNET_ENABLED
|
||||
if (!ethernet_handle_command(command, reply)) {
|
||||
the_mesh.handleCommand(0, command, reply);
|
||||
}
|
||||
#else
|
||||
the_mesh.handleCommand(0, command, reply); // NOTE: there is no sender_timestamp via serial!
|
||||
#endif
|
||||
if (reply[0]) {
|
||||
Serial.print(" -> "); Serial.println(reply);
|
||||
}
|
||||
@@ -109,10 +135,26 @@ void loop() {
|
||||
command[0] = 0; // reset command buffer
|
||||
}
|
||||
|
||||
#ifdef ETHERNET_ENABLED
|
||||
ethernet_loop_maintain();
|
||||
if (ethernet_read_line(ethernet_command, sizeof(ethernet_command))) {
|
||||
char reply[160];
|
||||
reply[0] = 0;
|
||||
if (!ethernet_handle_command(ethernet_command, reply)) {
|
||||
the_mesh.handleCommand(0, ethernet_command, reply);
|
||||
}
|
||||
ethernet_send_reply(reply);
|
||||
ethernet_command[0] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
the_mesh.loop();
|
||||
sensors.loop();
|
||||
#ifdef DISPLAY_CLASS
|
||||
ui_task.loop();
|
||||
#endif
|
||||
rtc_clock.tick();
|
||||
#ifdef HAS_EXTERNAL_WATCHDOG
|
||||
external_watchdog.loop();
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user