Merge branch 'meshcore-dev:dev' into dev

This commit is contained in:
Michael Gjelsø 2026-02-14 12:16:34 +01:00 committed by GitHub
commit 64e89359e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 55 additions and 10 deletions

View file

@ -212,7 +212,7 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no
file.read((uint8_t *)&_prefs.freq, sizeof(_prefs.freq)); // 56 file.read((uint8_t *)&_prefs.freq, sizeof(_prefs.freq)); // 56
file.read((uint8_t *)&_prefs.sf, sizeof(_prefs.sf)); // 60 file.read((uint8_t *)&_prefs.sf, sizeof(_prefs.sf)); // 60
file.read((uint8_t *)&_prefs.cr, sizeof(_prefs.cr)); // 61 file.read((uint8_t *)&_prefs.cr, sizeof(_prefs.cr)); // 61
file.read(pad, 1); // 62 file.read((uint8_t *)&_prefs.client_repeat, sizeof(_prefs.client_repeat)); // 62
file.read((uint8_t *)&_prefs.manual_add_contacts, sizeof(_prefs.manual_add_contacts)); // 63 file.read((uint8_t *)&_prefs.manual_add_contacts, sizeof(_prefs.manual_add_contacts)); // 63
file.read((uint8_t *)&_prefs.bw, sizeof(_prefs.bw)); // 64 file.read((uint8_t *)&_prefs.bw, sizeof(_prefs.bw)); // 64
file.read((uint8_t *)&_prefs.tx_power_dbm, sizeof(_prefs.tx_power_dbm)); // 68 file.read((uint8_t *)&_prefs.tx_power_dbm, sizeof(_prefs.tx_power_dbm)); // 68
@ -247,7 +247,7 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_
file.write((uint8_t *)&_prefs.freq, sizeof(_prefs.freq)); // 56 file.write((uint8_t *)&_prefs.freq, sizeof(_prefs.freq)); // 56
file.write((uint8_t *)&_prefs.sf, sizeof(_prefs.sf)); // 60 file.write((uint8_t *)&_prefs.sf, sizeof(_prefs.sf)); // 60
file.write((uint8_t *)&_prefs.cr, sizeof(_prefs.cr)); // 61 file.write((uint8_t *)&_prefs.cr, sizeof(_prefs.cr)); // 61
file.write(pad, 1); // 62 file.write((uint8_t *)&_prefs.client_repeat, sizeof(_prefs.client_repeat)); // 62
file.write((uint8_t *)&_prefs.manual_add_contacts, sizeof(_prefs.manual_add_contacts)); // 63 file.write((uint8_t *)&_prefs.manual_add_contacts, sizeof(_prefs.manual_add_contacts)); // 63
file.write((uint8_t *)&_prefs.bw, sizeof(_prefs.bw)); // 64 file.write((uint8_t *)&_prefs.bw, sizeof(_prefs.bw)); // 64
file.write((uint8_t *)&_prefs.tx_power_dbm, sizeof(_prefs.tx_power_dbm)); // 68 file.write((uint8_t *)&_prefs.tx_power_dbm, sizeof(_prefs.tx_power_dbm)); // 68

View file

@ -56,6 +56,7 @@
#define CMD_SEND_ANON_REQ 57 #define CMD_SEND_ANON_REQ 57
#define CMD_SET_AUTOADD_CONFIG 58 #define CMD_SET_AUTOADD_CONFIG 58
#define CMD_GET_AUTOADD_CONFIG 59 #define CMD_GET_AUTOADD_CONFIG 59
#define CMD_GET_ALLOWED_REPEAT_FREQ 60
// Stats sub-types for CMD_GET_STATS // Stats sub-types for CMD_GET_STATS
#define STATS_TYPE_CORE 0 #define STATS_TYPE_CORE 0
@ -88,6 +89,7 @@
#define RESP_CODE_TUNING_PARAMS 23 #define RESP_CODE_TUNING_PARAMS 23
#define RESP_CODE_STATS 24 // v8+, second byte is stats type #define RESP_CODE_STATS 24 // v8+, second byte is stats type
#define RESP_CODE_AUTOADD_CONFIG 25 #define RESP_CODE_AUTOADD_CONFIG 25
#define RESP_ALLOWED_REPEAT_FREQ 26
#define SEND_TIMEOUT_BASE_MILLIS 500 #define SEND_TIMEOUT_BASE_MILLIS 500
#define FLOOD_SEND_TIMEOUT_FACTOR 16.0f #define FLOOD_SEND_TIMEOUT_FACTOR 16.0f
@ -455,6 +457,10 @@ bool MyMesh::filterRecvFloodPacket(mesh::Packet* packet) {
return false; return false;
} }
bool MyMesh::allowPacketForward(const mesh::Packet* packet) {
return _prefs.client_repeat != 0;
}
void MyMesh::sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis) { void MyMesh::sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis) {
// TODO: dynamic send_scope, depending on recipient and current 'home' Region // TODO: dynamic send_scope, depending on recipient and current 'home' Region
if (send_scope.isNull()) { if (send_scope.isNull()) {
@ -881,6 +887,24 @@ uint32_t MyMesh::getBLEPin() {
return _active_ble_pin; return _active_ble_pin;
} }
struct FreqRange {
uint32_t lower_freq, upper_freq;
};
static FreqRange repeat_freq_ranges[] = {
{ 433000, 433000 },
{ 869000, 869000 },
{ 918000, 918000 }
};
bool MyMesh::isValidClientRepeatFreq(uint32_t f) const {
for (int i = 0; i < sizeof(repeat_freq_ranges)/sizeof(repeat_freq_ranges[0]); i++) {
auto r = &repeat_freq_ranges[i];
if (f >= r->lower_freq && f <= r->upper_freq) return true;
}
return false;
}
void MyMesh::startInterface(BaseSerialInterface &serial) { void MyMesh::startInterface(BaseSerialInterface &serial) {
_serial = &serial; _serial = &serial;
serial.enable(); serial.enable();
@ -904,6 +928,7 @@ void MyMesh::handleCmdFrame(size_t len) {
i += 40; i += 40;
StrHelper::strzcpy((char *)&out_frame[i], FIRMWARE_VERSION, 20); StrHelper::strzcpy((char *)&out_frame[i], FIRMWARE_VERSION, 20);
i += 20; i += 20;
out_frame[i++] = _prefs.client_repeat; // v9+
_serial->writeFrame(out_frame, i); _serial->writeFrame(out_frame, i);
} else if (cmd_frame[0] == CMD_APP_START && } else if (cmd_frame[0] == CMD_APP_START &&
len >= 8) { // sent when app establishes connection, respond with node ID len >= 8) { // sent when app establishes connection, respond with node ID
@ -1208,13 +1233,20 @@ void MyMesh::handleCmdFrame(size_t len) {
i += 4; i += 4;
uint8_t sf = cmd_frame[i++]; uint8_t sf = cmd_frame[i++];
uint8_t cr = cmd_frame[i++]; uint8_t cr = cmd_frame[i++];
uint8_t repeat = 0; // default - false
if (len > i) {
repeat = cmd_frame[i++]; // FIRMWARE_VER_CODE 9+
}
if (freq >= 300000 && freq <= 2500000 && sf >= 5 && sf <= 12 && cr >= 5 && cr <= 8 && bw >= 7000 && if (repeat && !isValidClientRepeatFreq(freq)) {
writeErrFrame(ERR_CODE_ILLEGAL_ARG);
} else if (freq >= 300000 && freq <= 2500000 && sf >= 5 && sf <= 12 && cr >= 5 && cr <= 8 && bw >= 7000 &&
bw <= 500000) { bw <= 500000) {
_prefs.sf = sf; _prefs.sf = sf;
_prefs.cr = cr; _prefs.cr = cr;
_prefs.freq = (float)freq / 1000.0; _prefs.freq = (float)freq / 1000.0;
_prefs.bw = (float)bw / 1000.0; _prefs.bw = (float)bw / 1000.0;
_prefs.client_repeat = repeat;
savePrefs(); savePrefs();
radio_set_params(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr); radio_set_params(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr);
@ -1741,6 +1773,15 @@ void MyMesh::handleCmdFrame(size_t len) {
out_frame[i++] = RESP_CODE_AUTOADD_CONFIG; out_frame[i++] = RESP_CODE_AUTOADD_CONFIG;
out_frame[i++] = _prefs.autoadd_config; out_frame[i++] = _prefs.autoadd_config;
_serial->writeFrame(out_frame, i); _serial->writeFrame(out_frame, i);
} else if (cmd_frame[0] == CMD_GET_ALLOWED_REPEAT_FREQ) {
int i = 0;
out_frame[i++] = RESP_ALLOWED_REPEAT_FREQ;
for (int k = 0; k < sizeof(repeat_freq_ranges)/sizeof(repeat_freq_ranges[0]) && i + 8 < sizeof(out_frame); k++) {
auto r = &repeat_freq_ranges[k];
memcpy(&out_frame[i], &r->lower_freq, 4); i += 4;
memcpy(&out_frame[i], &r->upper_freq, 4); i += 4;
}
_serial->writeFrame(out_frame, i);
} else { } else {
writeErrFrame(ERR_CODE_UNSUPPORTED_CMD); writeErrFrame(ERR_CODE_UNSUPPORTED_CMD);
MESH_DEBUG_PRINTLN("ERROR: unknown command: %02X", cmd_frame[0]); MESH_DEBUG_PRINTLN("ERROR: unknown command: %02X", cmd_frame[0]);

View file

@ -5,7 +5,7 @@
#include "AbstractUITask.h" #include "AbstractUITask.h"
/*------------ Frame Protocol --------------*/ /*------------ Frame Protocol --------------*/
#define FIRMWARE_VER_CODE 8 #define FIRMWARE_VER_CODE 9
#ifndef FIRMWARE_BUILD_DATE #ifndef FIRMWARE_BUILD_DATE
#define FIRMWARE_BUILD_DATE "29 Jan 2026" #define FIRMWARE_BUILD_DATE "29 Jan 2026"
@ -108,6 +108,7 @@ protected:
int calcRxDelay(float score, uint32_t air_time) const override; int calcRxDelay(float score, uint32_t air_time) const override;
uint8_t getExtraAckTransmitCount() const override; uint8_t getExtraAckTransmitCount() const override;
bool filterRecvFloodPacket(mesh::Packet* packet) override; bool filterRecvFloodPacket(mesh::Packet* packet) override;
bool allowPacketForward(const mesh::Packet* packet) override;
void sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis=0) override; void sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis=0) override;
void sendFloodScoped(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t delay_millis=0) override; void sendFloodScoped(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t delay_millis=0) override;
@ -176,6 +177,7 @@ private:
void checkCLIRescueCmd(); void checkCLIRescueCmd();
void checkSerialInterface(); void checkSerialInterface();
bool isValidClientRepeatFreq(uint32_t f) const;
// helpers, short-cuts // helpers, short-cuts
void saveChannels() { _store->saveChannels(this); } void saveChannels() { _store->saveChannels(this); }

View file

@ -28,4 +28,5 @@ struct NodePrefs { // persisted to file
uint8_t gps_enabled; // GPS enabled flag (0=disabled, 1=enabled) uint8_t gps_enabled; // GPS enabled flag (0=disabled, 1=enabled)
uint32_t gps_interval; // GPS read interval in seconds uint32_t gps_interval; // GPS read interval in seconds
uint8_t autoadd_config; // bitmask for auto-add contacts config uint8_t autoadd_config; // bitmask for auto-add contacts config
uint8_t client_repeat;
}; };

View file

@ -7,6 +7,7 @@ build_flags =
-I variants/rak3112 -I variants/rak3112
-D RAK_3112=1 -D RAK_3112=1
-D ESP32_CPU_FREQ=80 -D ESP32_CPU_FREQ=80
-D ARDUINO_USB_CDC_ON_BOOT=1
-D P_LORA_DIO_1=47 -D P_LORA_DIO_1=47
-D P_LORA_NSS=7 -D P_LORA_NSS=7
-D P_LORA_RESET=8 -D P_LORA_RESET=8
@ -131,14 +132,14 @@ lib_deps =
extends = rak3112 extends = rak3112
build_flags = build_flags =
${rak3112.build_flags} ${rak3112.build_flags}
-I examples/companion_radio/ui-new -I examples/companion_radio/ui-orig
-D MAX_CONTACTS=350 -D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40 -D MAX_GROUP_CHANNELS=40
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 ; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 ; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1
build_src_filter = ${rak3112.build_src_filter} build_src_filter = ${rak3112.build_src_filter}
+<../examples/companion_radio/*.cpp> +<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp> +<../examples/companion_radio/ui-orig/*.cpp>
lib_deps = lib_deps =
${rak3112.lib_deps} ${rak3112.lib_deps}
densaugeo/base64 @ ~1.4.0 densaugeo/base64 @ ~1.4.0
@ -147,7 +148,7 @@ lib_deps =
extends = rak3112 extends = rak3112
build_flags = build_flags =
${rak3112.build_flags} ${rak3112.build_flags}
-I examples/companion_radio/ui-new -I examples/companion_radio/ui-orig
-D MAX_CONTACTS=350 -D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40 -D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456 ; dynamic, random PIN -D BLE_PIN_CODE=123456 ; dynamic, random PIN
@ -159,7 +160,7 @@ build_flags =
build_src_filter = ${rak3112.build_src_filter} build_src_filter = ${rak3112.build_src_filter}
+<helpers/esp32/*.cpp> +<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp> +<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp> +<../examples/companion_radio/ui-orig/*.cpp>
lib_deps = lib_deps =
${rak3112.lib_deps} ${rak3112.lib_deps}
densaugeo/base64 @ ~1.4.0 densaugeo/base64 @ ~1.4.0
@ -168,7 +169,7 @@ lib_deps =
extends = rak3112 extends = rak3112
build_flags = build_flags =
${rak3112.build_flags} ${rak3112.build_flags}
-I examples/companion_radio/ui-new -I examples/companion_radio/ui-orig
-D MAX_CONTACTS=350 -D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40 -D MAX_GROUP_CHANNELS=40
-D WIFI_DEBUG_LOGGING=1 -D WIFI_DEBUG_LOGGING=1
@ -180,7 +181,7 @@ build_flags =
build_src_filter = ${rak3112.build_src_filter} build_src_filter = ${rak3112.build_src_filter}
+<helpers/esp32/*.cpp> +<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp> +<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp> +<../examples/companion_radio/ui-orig/*.cpp>
lib_deps = lib_deps =
${rak3112.lib_deps} ${rak3112.lib_deps}
densaugeo/base64 @ ~1.4.0 densaugeo/base64 @ ~1.4.0