mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-09-14 15:16:40 +00:00
Merge upstream companion-v1.17.1 into power-saving
Pulls in real fixes: scoped-reply routing, RX boosted-gain restored correctly after AGC reset, T-Echo Lite/Card SPI pin corrections (unused pins now map to NRFX_SPIM_PIN_NOT_USED via 0 instead of -1) and TCXO voltage fix, Heltec T096/T1 and MeshPocket pin fixes, T-beam Supreme S3 display fix, LR2021 preamble/IRQ timeout handling. None of the touched variants overlap with our active Heltec V3/V4, Cardputer ADV, GAT562, or WioTracker builds. # Conflicts: # examples/companion_radio/MyMesh.cpp # examples/companion_radio/MyMesh.h # examples/companion_radio/NodePrefs.h # src/helpers/radiolib/CustomSX1262Wrapper.h # src/helpers/radiolib/RadioLibWrappers.cpp # src/helpers/ui/SH1106Display.cpp # variants/lilygo_techo_lite/platformio.ini # variants/lilygo_techo_lite/variant.h
This commit is contained in:
@@ -1608,6 +1608,8 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
|
||||
seedDefaultRepeaterProfile(_prefs);
|
||||
_prefs.gps_enabled = 0; // GPS disabled by default
|
||||
_prefs.gps_interval = 0; // No automatic GPS updates by default
|
||||
_prefs.radio_fem_rxgain = 1;
|
||||
_prefs.radio_fem_txgain = 0;
|
||||
_prefs.display_brightness = 2; // medium brightness by default
|
||||
_prefs.buzzer_volume = 4; // max volume by default
|
||||
_prefs.ringtone_bpm_idx = 2; // 120 bpm default
|
||||
@@ -1729,6 +1731,8 @@ void MyMesh::begin(bool has_display) {
|
||||
applyApc(); // sets TX power to the ceiling and arms APC if enabled
|
||||
radio_driver.setRxBoostedGainMode(_prefs.rx_boosted_gain);
|
||||
radio_driver.setPowerSaving(_prefs.rx_powersave && !_prefs.client_repeat); // duty-cycle RX off while repeating (must hear all traffic)
|
||||
board.setLoRaFemLnaEnabled(_prefs.radio_fem_rxgain);
|
||||
board.setLoRaFemPaGainEnabled(_prefs.radio_fem_txgain);
|
||||
MESH_DEBUG_PRINTLN("RX Boosted Gain Mode: %s",
|
||||
radio_driver.getRxBoostedGainMode() ? "Enabled" : "Disabled");
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ class UITask;
|
||||
#define FIRMWARE_VER_CODE 13
|
||||
|
||||
#ifndef FIRMWARE_BUILD_DATE
|
||||
#define FIRMWARE_BUILD_DATE "12 Aug 2026"
|
||||
#define FIRMWARE_BUILD_DATE "14 Aug 2026"
|
||||
#endif
|
||||
|
||||
// Fallback only -- every real build (local or CI) goes through build.sh, which
|
||||
|
||||
@@ -65,6 +65,14 @@ struct NodePrefs { // persisted to file
|
||||
uint32_t gps_interval; // GPS duty-cycle sleep window in seconds (0 = disabled, GPS stays continuous)
|
||||
uint8_t autoadd_config; // bitmask for auto-add contacts config
|
||||
uint8_t rx_boosted_gain; // SX126x RX boosted gain mode (0=power saving, 1=boosted)
|
||||
// External LoRa FEM gain (LNA/PA), from upstream companion-v1.17.1 —
|
||||
// board-level only right now (BaseCustomBoard::setLoRaFemLnaEnabled/
|
||||
// PaGainEnabled, both default no-op false), no companion CLI/UI to set
|
||||
// these yet, so — matching upstream's own decision — NOT persisted here:
|
||||
// always reset to the constructor default (MyMesh.cpp) on boot. Not part
|
||||
// of the DataStore save/load tripwire below.
|
||||
uint8_t radio_fem_rxgain;
|
||||
uint8_t radio_fem_txgain;
|
||||
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)
|
||||
|
||||
@@ -411,24 +411,31 @@ bool MyMesh::isLooped(const mesh::Packet* packet, const uint8_t max_counters[])
|
||||
}
|
||||
|
||||
void MyMesh::sendFloodReply(mesh::Packet* packet, unsigned long delay_millis, uint8_t path_hash_size) {
|
||||
if (recv_pkt_region && !recv_pkt_region->isWildcard()) { // if _request_ packet scope is known, send reply with same scope
|
||||
TransportKey scope;
|
||||
if (region_map.getTransportKeysFor(*recv_pkt_region, &scope, 1) > 0) {
|
||||
sendFloodScoped(scope, packet, delay_millis, path_hash_size);
|
||||
} else {
|
||||
TransportKey req_scope;
|
||||
bool is_wildcard = recv_pkt_region != NULL && recv_pkt_region->isWildcard();
|
||||
bool req_scope_known = recv_pkt_region != NULL && !is_wildcard
|
||||
&& region_map.getTransportKeysFor(*recv_pkt_region, &req_scope, 1) > 0;
|
||||
|
||||
switch (mesh::chooseReplyScope(req_scope_known, is_wildcard, !default_scope.isNull())) {
|
||||
case mesh::REPLY_SCOPE_REQUEST:
|
||||
sendFloodScoped(req_scope, packet, delay_millis, path_hash_size); // reply with same scope as request
|
||||
break;
|
||||
case mesh::REPLY_SCOPE_DEFAULT:
|
||||
// requester's scope is unknown: DIRECT request (no transport codes), or code matched no Region.
|
||||
// un-scoped would be dropped at hop 0 by repeaters running flood.max.unscoped=0
|
||||
sendFloodScoped(default_scope, packet, delay_millis, path_hash_size);
|
||||
break;
|
||||
case mesh::REPLY_SCOPE_NONE:
|
||||
sendFlood(packet, delay_millis, path_hash_size); // send un-scoped
|
||||
}
|
||||
} else {
|
||||
sendFlood(packet, delay_millis, path_hash_size); // send un-scoped
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool MyMesh::allowPacketForward(const mesh::Packet *packet) {
|
||||
if (_prefs.disable_fwd) return false;
|
||||
if (packet->isRouteFlood()) {
|
||||
if (packet->getPathHashCount() >= _prefs.flood_max) return false;
|
||||
if (packet->getRouteType() == ROUTE_TYPE_FLOOD && packet->getPathHashCount() >= _prefs.flood_max_unscoped) return false;
|
||||
if (packet->getPayloadType() == PAYLOAD_TYPE_ADVERT && packet->getPathHashCount() >= _prefs.flood_max_advert) return false;
|
||||
if (packet->isRouteFlood()
|
||||
&& mesh::isFloodHopLimitExceeded(packet, _prefs.flood_max, _prefs.flood_max_unscoped, _prefs.flood_max_advert)) {
|
||||
return false;
|
||||
}
|
||||
if (packet->isRouteFlood() && recv_pkt_region == NULL) {
|
||||
MESH_DEBUG_PRINTLN("allowPacketForward: unknown transport code, or wildcard not allowed for FLOOD packet");
|
||||
@@ -586,17 +593,29 @@ void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const m
|
||||
|
||||
if (reply_len == 0) return; // invalid request
|
||||
|
||||
if (packet->isRouteFlood()) {
|
||||
// a DIRECT login can reply via the stored out_path, as onPeerDataRecv() does for REQ
|
||||
ClientInfo* client = acl.getClient(sender.pub_key, PUB_KEY_SIZE);
|
||||
bool have_out_path = client != NULL && client->out_path_len != OUT_PATH_UNKNOWN;
|
||||
|
||||
auto route = mesh::chooseReplyRoute(packet->isRouteFlood(), reply_path_len != 0xFF, have_out_path);
|
||||
|
||||
if (route == mesh::REPLY_ROUTE_PATH_RETURN) {
|
||||
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
|
||||
mesh::Packet* path = createPathReturn(sender, secret, packet->path, packet->path_len,
|
||||
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len);
|
||||
if (path) sendFloodReply(path, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
|
||||
} else if (reply_path_len == 0xFF) {
|
||||
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len);
|
||||
if (reply) sendFloodReply(reply, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
|
||||
return;
|
||||
}
|
||||
|
||||
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len);
|
||||
if (reply == NULL) return;
|
||||
|
||||
if (route == mesh::REPLY_ROUTE_DIRECT_SUPPLIED) {
|
||||
sendDirect(reply, reply_path, reply_path_len, SERVER_RESPONSE_DELAY);
|
||||
} else if (route == mesh::REPLY_ROUTE_DIRECT_OUT_PATH) {
|
||||
sendDirect(reply, client->out_path, client->out_path_len, SERVER_RESPONSE_DELAY);
|
||||
} else {
|
||||
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len);
|
||||
if (reply) sendDirect(reply, reply_path, reply_path_len, SERVER_RESPONSE_DELAY);
|
||||
sendFloodReply(reply, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -913,6 +932,7 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
|
||||
#endif
|
||||
#endif
|
||||
_prefs.radio_fem_rxgain = 1;
|
||||
_prefs.radio_fem_txgain = 0;
|
||||
|
||||
pending_discover_tag = 0;
|
||||
pending_discover_until = 0;
|
||||
@@ -962,6 +982,7 @@ void MyMesh::begin(FILESYSTEM *fs) {
|
||||
MESH_DEBUG_PRINTLN("RX Boosted Gain Mode: %s",
|
||||
radio_driver.getRxBoostedGainMode() ? "Enabled" : "Disabled");
|
||||
board.setLoRaFemLnaEnabled(_prefs.radio_fem_rxgain);
|
||||
board.setLoRaFemPaGainEnabled(_prefs.radio_fem_txgain);
|
||||
|
||||
updateAdvertTimer();
|
||||
updateFloodAdvertTimer();
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <helpers/StatsFormatHelper.h>
|
||||
#include <helpers/TxtDataHelpers.h>
|
||||
#include <helpers/RegionMap.h>
|
||||
#include <helpers/RoutingPolicy.h>
|
||||
#include "RateLimiter.h"
|
||||
|
||||
#ifdef WITH_BRIDGE
|
||||
@@ -70,11 +71,11 @@ struct NeighbourInfo {
|
||||
};
|
||||
|
||||
#ifndef FIRMWARE_BUILD_DATE
|
||||
#define FIRMWARE_BUILD_DATE "9 Aug 2026"
|
||||
#define FIRMWARE_BUILD_DATE "14 Aug 2026"
|
||||
#endif
|
||||
|
||||
#ifndef FIRMWARE_VERSION
|
||||
#define FIRMWARE_VERSION "v1.17.0"
|
||||
#define FIRMWARE_VERSION "v1.17.1"
|
||||
#endif
|
||||
|
||||
#define FIRMWARE_ROLE "repeater"
|
||||
|
||||
@@ -299,10 +299,9 @@ uint32_t MyMesh::getDirectRetransmitDelay(const mesh::Packet *packet) {
|
||||
|
||||
bool MyMesh::allowPacketForward(const mesh::Packet *packet) {
|
||||
if (_prefs.disable_fwd) return false;
|
||||
if (packet->isRouteFlood()) {
|
||||
if (packet->getPathHashCount() >= _prefs.flood_max) return false;
|
||||
if (packet->getRouteType() == ROUTE_TYPE_FLOOD && packet->getPathHashCount() >= _prefs.flood_max_unscoped) return false;
|
||||
if (packet->getPayloadType() == PAYLOAD_TYPE_ADVERT && packet->getPathHashCount() >= _prefs.flood_max_advert) return false;
|
||||
if (packet->isRouteFlood()
|
||||
&& mesh::isFloodHopLimitExceeded(packet, _prefs.flood_max, _prefs.flood_max_unscoped, _prefs.flood_max_advert)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -683,6 +682,7 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
|
||||
#endif
|
||||
#endif
|
||||
_prefs.radio_fem_rxgain = 1;
|
||||
_prefs.radio_fem_txgain = 0;
|
||||
|
||||
next_post_idx = 0;
|
||||
next_client_idx = 0;
|
||||
@@ -726,6 +726,7 @@ void MyMesh::begin(FILESYSTEM *fs) {
|
||||
radio_driver.setTxPower(_prefs.tx_power_dbm);
|
||||
radio_driver.setRxBoostedGainMode(_prefs.rx_boosted_gain);
|
||||
board.setLoRaFemLnaEnabled(_prefs.radio_fem_rxgain);
|
||||
board.setLoRaFemPaGainEnabled(_prefs.radio_fem_txgain);
|
||||
|
||||
updateAdvertTimer();
|
||||
updateFloodAdvertTimer();
|
||||
@@ -749,15 +750,23 @@ void MyMesh::sendFloodScoped(const TransportKey& scope, mesh::Packet* pkt, uint3
|
||||
}
|
||||
|
||||
void MyMesh::sendFloodReply(mesh::Packet* packet, unsigned long delay_millis, uint8_t path_hash_size) {
|
||||
if (recv_pkt_region && !recv_pkt_region->isWildcard()) { // if _request_ packet scope is known, send reply with same scope
|
||||
TransportKey scope;
|
||||
if (region_map.getTransportKeysFor(*recv_pkt_region, &scope, 1) > 0) {
|
||||
sendFloodScoped(scope, packet, delay_millis, path_hash_size);
|
||||
} else {
|
||||
TransportKey req_scope;
|
||||
bool is_wildcard = recv_pkt_region != NULL && recv_pkt_region->isWildcard();
|
||||
bool req_scope_known = recv_pkt_region != NULL && !is_wildcard
|
||||
&& region_map.getTransportKeysFor(*recv_pkt_region, &req_scope, 1) > 0;
|
||||
|
||||
switch (mesh::chooseReplyScope(req_scope_known, is_wildcard, !default_scope.isNull())) {
|
||||
case mesh::REPLY_SCOPE_REQUEST:
|
||||
sendFloodScoped(req_scope, packet, delay_millis, path_hash_size); // reply with same scope as request
|
||||
break;
|
||||
case mesh::REPLY_SCOPE_DEFAULT:
|
||||
// requester's scope is unknown: DIRECT request (no transport codes), or code matched no Region.
|
||||
// un-scoped would be dropped at hop 0 by repeaters running flood.max.unscoped=0
|
||||
sendFloodScoped(default_scope, packet, delay_millis, path_hash_size);
|
||||
break;
|
||||
case mesh::REPLY_SCOPE_NONE:
|
||||
sendFlood(packet, delay_millis, path_hash_size); // send un-scoped
|
||||
}
|
||||
} else {
|
||||
sendFlood(packet, delay_millis, path_hash_size); // send un-scoped
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,17 +21,18 @@
|
||||
#include <helpers/StatsFormatHelper.h>
|
||||
#include <helpers/ClientACL.h>
|
||||
#include <helpers/RegionMap.h>
|
||||
#include <helpers/RoutingPolicy.h>
|
||||
#include <RTClib.h>
|
||||
#include <target.h>
|
||||
|
||||
/* ------------------------------ Config -------------------------------- */
|
||||
|
||||
#ifndef FIRMWARE_BUILD_DATE
|
||||
#define FIRMWARE_BUILD_DATE "9 Aug 2026"
|
||||
#define FIRMWARE_BUILD_DATE "14 Aug 2026"
|
||||
#endif
|
||||
|
||||
#ifndef FIRMWARE_VERSION
|
||||
#define FIRMWARE_VERSION "v1.17.0"
|
||||
#define FIRMWARE_VERSION "v1.17.1"
|
||||
#endif
|
||||
|
||||
#ifndef LORA_FREQ
|
||||
|
||||
@@ -735,6 +735,7 @@ SensorMesh::SensorMesh(mesh::MainBoard& board, mesh::Radio& radio, mesh::Millise
|
||||
_prefs.gps_interval = 0;
|
||||
_prefs.advert_loc_policy = ADVERT_LOC_PREFS;
|
||||
_prefs.radio_fem_rxgain = 1;
|
||||
_prefs.radio_fem_txgain = 0;
|
||||
|
||||
memset(default_scope.key, 0, sizeof(default_scope.key));
|
||||
}
|
||||
@@ -771,6 +772,7 @@ void SensorMesh::begin(FILESYSTEM* fs) {
|
||||
radio_driver.setParams(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr);
|
||||
radio_driver.setTxPower(_prefs.tx_power_dbm);
|
||||
board.setLoRaFemLnaEnabled(_prefs.radio_fem_rxgain);
|
||||
board.setLoRaFemPaGainEnabled(_prefs.radio_fem_txgain);
|
||||
|
||||
updateAdvertTimer();
|
||||
updateFloodAdvertTimer();
|
||||
|
||||
@@ -34,11 +34,11 @@
|
||||
#define PERM_RECV_ALERTS_HI (1 << 7) // high priority alerts
|
||||
|
||||
#ifndef FIRMWARE_BUILD_DATE
|
||||
#define FIRMWARE_BUILD_DATE "9 Aug 2026"
|
||||
#define FIRMWARE_BUILD_DATE "14 Aug 2026"
|
||||
#endif
|
||||
|
||||
#ifndef FIRMWARE_VERSION
|
||||
#define FIRMWARE_VERSION "v1.17.0"
|
||||
#define FIRMWARE_VERSION "v1.17.1"
|
||||
#endif
|
||||
|
||||
#define FIRMWARE_ROLE "sensor"
|
||||
|
||||
Reference in New Issue
Block a user