Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 24 additions & 46 deletions examples/companion_radio/DataStore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,30 +189,35 @@ bool DataStore::saveMainIdentity(const mesh::LocalIdentity &identity) {
return identity_store.save("_main", identity);
}

void DataStore::loadPrefs(NodePrefs& prefs, double& node_lat, double& node_lon) {
if (_fs->exists("/new_prefs")) {
loadPrefsInt("/new_prefs", prefs, node_lat, node_lon); // new filename
} else if (_fs->exists("/node_prefs")) {
loadPrefsInt("/node_prefs", prefs, node_lat, node_lon);
savePrefs(prefs, node_lat, node_lon); // save to new filename
_fs->remove("/node_prefs"); // remove old
void DataStore::loadPrefs(NodePrefs& prefs) {
if (_fs->exists("/prefs.json")) {
File file = openRead(_fs, "/prefs.json");
if (file) {
prefs.loadSerial(file); // new Serial prefs
file.close();
}
} else if (_fs->exists("/new_prefs")) {
loadPrefsInt("/new_prefs", prefs);
if (savePrefs(prefs) ) { // save to new format
//_fs->remove("/new_prefs"); // remove old
}
}
}

void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& node_lat, double& node_lon) {
void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs) {
File file = openRead(_fs, filename);
if (file) {
uint8_t pad[8];

file.read((uint8_t *)&_prefs.airtime_factor, sizeof(float)); // 0
file.read((uint8_t *)_prefs.node_name, sizeof(_prefs.node_name)); // 4
file.read(pad, 4); // 36
file.read((uint8_t *)&node_lat, sizeof(node_lat)); // 40
file.read((uint8_t *)&node_lon, sizeof(node_lon)); // 48
file.read((uint8_t *)&_prefs.node_lat, sizeof(_prefs.node_lat)); // 40
file.read((uint8_t *)&_prefs.node_lon, sizeof(_prefs.node_lon)); // 48
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.cr, sizeof(_prefs.cr)); // 61
file.read((uint8_t *)&_prefs.client_repeat, sizeof(_prefs.client_repeat)); // 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.bw, sizeof(_prefs.bw)); // 64
file.read((uint8_t *)&_prefs.tx_power_dbm, sizeof(_prefs.tx_power_dbm)); // 68
Expand All @@ -234,48 +239,21 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no
file.read((uint8_t *)_prefs.default_scope_name, sizeof(_prefs.default_scope_name)); // 90
file.read((uint8_t *)_prefs.default_scope_key, sizeof(_prefs.default_scope_key)); // 121

// migrate old fields
_prefs.setRepeatEn(_prefs._client_repeat != 0);

file.close();
}
}

void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_lon) {
File file = openWrite(_fs, "/new_prefs");
bool DataStore::savePrefs(NodePrefs& _prefs) {
File file = openWrite(_fs, "/prefs.json");
if (file) {
uint8_t pad[8];
memset(pad, 0, sizeof(pad));

file.write((uint8_t *)&_prefs.airtime_factor, sizeof(float)); // 0
file.write((uint8_t *)_prefs.node_name, sizeof(_prefs.node_name)); // 4
file.write(pad, 4); // 36
file.write((uint8_t *)&node_lat, sizeof(node_lat)); // 40
file.write((uint8_t *)&node_lon, sizeof(node_lon)); // 48
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.cr, sizeof(_prefs.cr)); // 61
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.bw, sizeof(_prefs.bw)); // 64
file.write((uint8_t *)&_prefs.tx_power_dbm, sizeof(_prefs.tx_power_dbm)); // 68
file.write((uint8_t *)&_prefs.telemetry_mode_base, sizeof(_prefs.telemetry_mode_base)); // 69
file.write((uint8_t *)&_prefs.telemetry_mode_loc, sizeof(_prefs.telemetry_mode_loc)); // 70
file.write((uint8_t *)&_prefs.telemetry_mode_env, sizeof(_prefs.telemetry_mode_env)); // 71
file.write((uint8_t *)&_prefs.rx_delay_base, sizeof(_prefs.rx_delay_base)); // 72
file.write((uint8_t *)&_prefs.advert_loc_policy, sizeof(_prefs.advert_loc_policy)); // 76
file.write((uint8_t *)&_prefs.multi_acks, sizeof(_prefs.multi_acks)); // 77
file.write((uint8_t *)&_prefs.path_hash_mode, sizeof(_prefs.path_hash_mode)); // 78
file.write(pad, 1); // 79
file.write((uint8_t *)&_prefs.ble_pin, sizeof(_prefs.ble_pin)); // 80
file.write((uint8_t *)&_prefs.buzzer_quiet, sizeof(_prefs.buzzer_quiet)); // 84
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.autoadd_max_hops, sizeof(_prefs.autoadd_max_hops)); // 88
file.write((uint8_t *)&_prefs.rx_boosted_gain, sizeof(_prefs.rx_boosted_gain)); // 89
file.write((uint8_t *)_prefs.default_scope_name, sizeof(_prefs.default_scope_name)); // 90
file.write((uint8_t *)_prefs.default_scope_key, sizeof(_prefs.default_scope_key)); // 121

bool success = _prefs.saveSerial(file);
file.close();
return success;
}
return false;
}

void DataStore::loadContacts(DataStoreHost* host) {
Expand Down
6 changes: 3 additions & 3 deletions examples/companion_radio/DataStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class DataStore {
mesh::RTCClock* _clock;
IdentityStore identity_store;

void loadPrefsInt(const char *filename, NodePrefs& prefs, double& node_lat, double& node_lon);
void loadPrefsInt(const char *filename, NodePrefs& prefs);
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
void checkAdvBlobFile();
#endif
Expand All @@ -33,8 +33,8 @@ class DataStore {
FILESYSTEM* getSecondaryFS() const { return _fsExtra; }
bool loadMainIdentity(mesh::LocalIdentity &identity);
bool saveMainIdentity(const mesh::LocalIdentity &identity);
void loadPrefs(NodePrefs& prefs, double& node_lat, double& node_lon);
void savePrefs(const NodePrefs& prefs, double node_lat, double node_lon);
void loadPrefs(NodePrefs& prefs);
bool savePrefs(NodePrefs& prefs);
void loadContacts(DataStoreHost* host);
void saveContacts(DataStoreHost* host, bool (*filter)(const ContactInfo& c) = NULL);
void loadChannels(DataStoreHost* host);
Expand Down
12 changes: 7 additions & 5 deletions examples/companion_radio/MyMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ bool MyMesh::filterRecvFloodPacket(mesh::Packet* packet) {
}

bool MyMesh::allowPacketForward(const mesh::Packet* packet) {
return _prefs.client_repeat != 0;
return _prefs.isRepeatEn();
}

void MyMesh::sendFloodScoped(const TransportKey& scope, mesh::Packet* pkt, uint32_t delay_millis) {
Expand Down Expand Up @@ -876,7 +876,6 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
send_unscoped = false;

// defaults
memset(&_prefs, 0, sizeof(_prefs));
_prefs.airtime_factor = 1.0;
strcpy(_prefs.node_name, "NONAME");
_prefs.freq = LORA_FREQ;
Expand All @@ -887,6 +886,7 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
_prefs.gps_enabled = 0; // GPS disabled by default
_prefs.gps_interval = 0; // No automatic GPS updates by default
//_prefs.rx_delay_base = 10.0f; enable once new algo fixed
_prefs.setRepeatEn(false);
#if defined(USE_SX1262) || defined(USE_SX1268)
#ifdef SX126X_RX_BOOSTED_GAIN
_prefs.rx_boosted_gain = SX126X_RX_BOOSTED_GAIN;
Expand Down Expand Up @@ -931,7 +931,9 @@ void MyMesh::begin(bool has_display) {
#endif

// load persisted prefs
_store->loadPrefs(_prefs, sensors.node_lat, sensors.node_lon);
_store->loadPrefs(_prefs);
sensors.node_lat = _prefs.node_lat;
sensors.node_lon = _prefs.node_lon;

// sanitise bad pref values
_prefs.rx_delay_base = constrain(_prefs.rx_delay_base, 0, 20.0f);
Expand Down Expand Up @@ -1031,7 +1033,7 @@ void MyMesh::handleCmdFrame(size_t len) {
i += 40;
StrHelper::strzcpy((char *)&out_frame[i], FIRMWARE_VERSION, 20);
i += 20;
out_frame[i++] = _prefs.client_repeat; // v9+
out_frame[i++] = _prefs.isRepeatEn() ? 1 : 0; // v9+
out_frame[i++] = _prefs.path_hash_mode; // v10+
_serial->writeFrame(out_frame, i);
} else if (cmd_frame[0] == CMD_APP_START &&
Expand Down Expand Up @@ -1393,7 +1395,7 @@ void MyMesh::handleCmdFrame(size_t len) {
_prefs.cr = cr;
_prefs.freq = (float)freq / 1000.0;
_prefs.bw = (float)bw / 1000.0;
_prefs.client_repeat = repeat;
_prefs.setRepeatEn(repeat != 0);
savePrefs();

radio_driver.setParams(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr);
Expand Down
6 changes: 5 additions & 1 deletion examples/companion_radio/MyMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,11 @@ class MyMesh : public BaseChatMesh, public DataStoreHost {
}

public:
void savePrefs() { _store->savePrefs(_prefs, sensors.node_lat, sensors.node_lon); }
void savePrefs() {
_prefs.node_lat = sensors.node_lat;
_prefs.node_lon = sensors.node_lon;
_store->savePrefs(_prefs);
}

#if ENV_INCLUDE_GPS == 1
void applyGpsPrefs() {
Expand Down
145 changes: 122 additions & 23 deletions examples/companion_radio/NodePrefs.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once
#include <cstdint> // For uint8_t, uint32_t
#include <helpers/ConfigSerializer.h>

#define TELEM_MODE_DENY 0
#define TELEM_MODE_ALLOW_FLAGS 1 // use contact.flags
Expand All @@ -8,30 +9,128 @@
#define ADVERT_LOC_NONE 0
#define ADVERT_LOC_SHARE 1

struct NodePrefs { // persisted to file
float airtime_factor;
class NodePrefs : public ConfigSerializer { // persisted to file
public:
float airtime_factor = 0;
char node_name[32];
float freq;
uint8_t sf;
uint8_t cr;
uint8_t multi_acks;
uint8_t manual_add_contacts;
float bw;
int8_t tx_power_dbm;
uint8_t telemetry_mode_base;
uint8_t telemetry_mode_loc;
uint8_t telemetry_mode_env;
float rx_delay_base;
uint32_t ble_pin;
uint8_t advert_loc_policy;
uint8_t buzzer_quiet;
uint8_t gps_enabled; // GPS enabled flag (0=disabled, 1=enabled)
uint32_t gps_interval; // GPS read interval in seconds
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)
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)
double node_lat = 0, node_lon = 0;
float freq = 0;
uint8_t sf = 0;
uint8_t cr = 0;
uint8_t multi_acks = 0;
uint8_t manual_add_contacts = 0;
float bw = 0;
int8_t tx_power_dbm = 0;
uint8_t telemetry_mode_base = 0;
uint8_t telemetry_mode_loc = 0;
uint8_t telemetry_mode_env = 0;
float rx_delay_base = 0;
uint32_t ble_pin = 0;
uint8_t advert_loc_policy = 0;
uint8_t buzzer_quiet = 0;
uint8_t gps_enabled = 0; // GPS enabled flag (0=disabled, 1=enabled)
uint32_t gps_interval = 0; // GPS read interval in seconds
uint8_t autoadd_config = 0; // bitmask for auto-add contacts config
uint8_t rx_boosted_gain = 0; // SX126x RX boosted gain mode (0=power saving, 1=boosted)
uint8_t _client_repeat = 0; // DEPRECATED -> use repeat.disable_fwd
uint8_t path_hash_mode = 0; // which path mode to use when sending
uint8_t autoadd_max_hops = 0; // 0 = no limit, 1 = direct (0 hops), N = up to N-1 hops (max 64)
char default_scope_name[31];
uint8_t default_scope_key[16];

private:
class RadioPrefs : public ConfigSerializer { // COPIED from CommonCLI (for now)
NodePrefs* _parent;
protected:
void structure() override {
def("freq", _parent->freq);
def("bw", _parent->bw);
def("sf", _parent->sf);
def("cr", _parent->cr);
//def("cad", _parent->cad_enabled);
//def("int_thr", _parent->interference_threshold);
def("rxgain", _parent->rx_boosted_gain);
def("fem_rxgain", _parent->rx_boosted_gain);
def("tx", _parent->tx_power_dbm);
def("af", _parent->airtime_factor);
def("rxdelay", _parent->rx_delay_base);
//def("f_txdelay", _parent->tx_delay_factor); currently hard-coded
//def("d_txdelay", _parent->direct_tx_delay_factor); currently hard-coded
//def("agc_int", _parent->agc_reset_interval);
def("hash_mode", _parent->path_hash_mode);
def("multi_ack", _parent->multi_acks);
}
public:
RadioPrefs(NodePrefs* parent) : _parent(parent) { }
};
RadioPrefs radio;

class GPSPrefs : public ConfigSerializer { // COPIED from CommonCLI (for now)
NodePrefs* _parent;
protected:
void structure() override {
def("en", _parent->gps_enabled); // boolean
def("int", _parent->gps_interval); // interval in seconds
def("adv_loc", _parent->advert_loc_policy);
}
public:
GPSPrefs(NodePrefs* parent) : _parent(parent) { }
};
GPSPrefs gps;

class RepeatPrefs : public ConfigSerializer { // COPIED from CommonCLI (for now)
public:
uint8_t disable_fwd = 1;
protected:
void structure() override {
def("disable", disable_fwd);
//def("f_max", flood_max);
//def("f_max_uns", flood_max_unscoped);
//def("f_max_adv", flood_max_advert);
//def("loop", loop_detect);
}
};
RepeatPrefs repeat;

class CompanionPrefs : public ConfigSerializer {
NodePrefs* _parent;
protected:
void structure() override {
def("auto_max", _parent->autoadd_max_hops); // 0 = no limit, 1 = direct (0 hops), N = up to N-1 hops (max 64)
def("defs_nm", _parent->default_scope_name, sizeof(_parent->default_scope_name));
def("defs_key", (void *) _parent->default_scope_key, sizeof(_parent->default_scope_key));
def("pin", _parent->ble_pin);
def("buzz_q", _parent->buzzer_quiet);
def("auto_add", _parent->autoadd_config); // bitmask for auto-add contacts config
def("man_add", _parent->manual_add_contacts);
def("tel_base", _parent->telemetry_mode_base);
def("tel_loc", _parent->telemetry_mode_loc);
def("tel_env", _parent->telemetry_mode_env);
}
public:
CompanionPrefs(NodePrefs* parent) : _parent(parent) { }
};
CompanionPrefs companion;

protected:
void structure() override {
def("name", node_name, sizeof(node_name));
//def("adv_int", advert_interval);
//def("f_adv_int", flood_advert_interval);
def("lat", node_lat);
def("lon", node_lon);
def("radio", radio);
def("gps", gps);
def("repeat", repeat);
def("comp", companion);
}
public:
NodePrefs() : radio(this), gps(this), companion(this) {
node_name[0] = 0;
default_scope_name[0] = 0;
memset(default_scope_key, 0, sizeof(default_scope_key));
}
// new accessor methods
bool isRepeatEn() const { return repeat.disable_fwd == 0; }
void setRepeatEn(bool en) { repeat.disable_fwd = en ? 0 : 1; }
};
1 change: 0 additions & 1 deletion examples/simple_repeater/MyMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -872,7 +872,6 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
#endif

// defaults
memset(&_prefs, 0, sizeof(_prefs));
_prefs.airtime_factor = 1.0;
_prefs.rx_delay_base = 0.0f; // turn off by default, was 10.0;
_prefs.tx_delay_factor = 0.5f; // was 0.25f
Expand Down
1 change: 0 additions & 1 deletion examples/simple_room_server/MyMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,6 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
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;
Expand Down
1 change: 0 additions & 1 deletion examples/simple_sensor/SensorMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,6 @@ SensorMesh::SensorMesh(mesh::MainBoard& board, mesh::Radio& radio, mesh::Millise
set_radio_at = revert_radio_at = 0;

// defaults
memset(&_prefs, 0, sizeof(_prefs));
_prefs.airtime_factor = 1.0;
_prefs.rx_delay_base = 0.0f; // turn off by default, was 10.0;
_prefs.tx_delay_factor = 0.5f; // was 0.25f
Expand Down
5 changes: 3 additions & 2 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ lib_deps =
extends = arduino_base
upload_protocol = picotool
board_build.core = earlephilhower
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#4e22a0d ; framework-arduinopico @ 1.50600.0+sha.6a1d13e9
platform = https://github.com/maxgerhardt/platform-raspberrypi.git ; framework-arduinopico @ 1.50600.0+sha.6a1d13e9
build_flags = ${arduino_base.build_flags}
-D RP2040_PLATFORM

Expand Down Expand Up @@ -163,11 +163,12 @@ build_flags = -std=c++17
-I src
-I test/mocks
test_build_src = yes
test_filter = test_utils
test_ignore = test_kiss_modem
build_src_filter =
-<*>
+<../src/Utils.cpp>
+<../src/Packet.cpp>
+<../src/helpers/ConfigSerializer.cpp>
lib_deps =
google/googletest @ 1.17.0

Expand Down
Loading
Loading