#pragma once #include // For uint8_t, uint32_t #include #include #include #define TELEM_MODE_DENY 0 #define TELEM_MODE_ALLOW_FLAGS 1 // use contact.flags #define TELEM_MODE_ALLOW_ALL 2 #define ADVERT_LOC_NONE 0 #define ADVERT_LOC_SHARE 1 class NodePrefs : public ConfigSerializer { // persisted to file public: float airtime_factor = 0; char node_name[32]; 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; float tx_delay_factor = 0; float direct_tx_delay_factor = 0; uint32_t ble_pin = 0; uint8_t advert_loc_policy = 0; uint8_t buzzer_quiet = 0; uint8_t vibe_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 radio_fem_rxgain = 0; // external LoRa FEM RX gain (LNA) uint8_t radio_fem_txgain = 0; // external LoRa FEM TX gain (low by default) 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) uint8_t cad_enabled = 0; uint8_t interference_threshold = 0; uint8_t agc_reset_interval = 0; // secs / 4 char default_scope_name[31]; uint8_t default_scope_key[16]; int8_t tz_offset = 0; #ifdef ENABLE_WIFI_INTERFACE #ifndef WIFI_SSID #define WIFI_SSID "" #endif char wifi_ssid[33] = {0}; // if empty, the compile-time WIFI_SSID is used char wifi_pwd[64] = {0}; uint8_t wifi_enabled = 1; // enabled by default to allow wifi only builds to work. wifi won't be started if ssid is empty // use ssid from prefs, or fallback to ssid from build flags const char* getWifiSSID() const { return wifi_ssid[0] ? wifi_ssid : WIFI_SSID; } #endif private: class RadioPrefs : public CommonRadioPrefs { 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->radio_fem_rxgain); // fem_rxgain WAS mapped to wrong JSON property previously def("fem_txgain", _parent->radio_fem_txgain); def("tx", _parent->tx_power_dbm); def("af", _parent->airtime_factor); def("rxdelay", _parent->rx_delay_base); def("f_txdelay", _parent->tx_delay_factor); def("d_txdelay", _parent->direct_tx_delay_factor); 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) { } // CommonRadioPrefs interface float getFreq() const override { return _parent->freq; } void setFreq(float f) override { _parent->freq = f; markDirty(); } float getBandwidth() const override { return _parent->bw; } void setBandwidth(float bw) override { _parent->bw = bw; markDirty(); } uint8_t getSpreadFactor() const override { return _parent->sf; } void setSpreadFactor(uint8_t sf) override { _parent->sf = sf; markDirty(); } uint8_t getCodingRate() const override { return _parent->cr; } void setCodingRate(uint8_t cr) override { _parent->cr = cr; markDirty(); } float getAirtimeFactor() const override { return _parent->airtime_factor; } void setAirtimeFactor(float af) override { _parent->airtime_factor = af; markDirty(); } bool isCadEnabled() const override { return _parent->cad_enabled; } void setCadEnabled(bool en) override { _parent->cad_enabled = en; markDirty(); } uint8_t getIntThresh() const override { return _parent->interference_threshold; } void setIntThresh(uint8_t t) override { _parent->interference_threshold = t; markDirty(); } uint8_t getRxGain() const override { return _parent->rx_boosted_gain; } void setRxGain(uint8_t g) override { _parent->rx_boosted_gain = g; markDirty(); } uint8_t getTxPower() const override { return _parent->tx_power_dbm; } void setTxPower(uint8_t dbm) override { _parent->tx_power_dbm = dbm; markDirty(); } float getRxDelay() const override { return _parent->rx_delay_base; } void setRxDelay(float d) override { _parent->rx_delay_base = d; markDirty(); } uint16_t getAgcResetInt() const override { return _parent->agc_reset_interval * 4; } void setAgcResetInt(uint16_t secs) override { _parent->agc_reset_interval = secs / 4; markDirty(); } uint8_t getHashMode() const override { return _parent->path_hash_mode; } void setHashMode(uint8_t m) override { _parent->path_hash_mode = m; markDirty(); } uint8_t getMultiAcks() const override { return _parent->multi_acks; } void setMultiAcks(uint8_t m) override { _parent->multi_acks = m; markDirty(); } float getFloodTxDelay() const override { return _parent->tx_delay_factor; } void setFloodTxDelay(float d) override { _parent->tx_delay_factor = d; markDirty(); } float getDirectTxDelay() const override { return _parent->direct_tx_delay_factor; } void setDirectTxDelay(float d) override { _parent->direct_tx_delay_factor = d; markDirty(); } uint8_t getFEMRxGain() const override { return _parent->radio_fem_rxgain; } void setFEMRxGain(uint8_t g) override { _parent->radio_fem_rxgain = g; markDirty(); } uint8_t getFEMTxGain() const override { return _parent->radio_fem_txgain; } void setFEMTxGain(uint8_t g) override { _parent->radio_fem_txgain = g; markDirty(); } }; 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("vibe_q", _parent->vibe_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); def("tz_offset", _parent->tz_offset); } public: CompanionPrefs(NodePrefs* parent) : _parent(parent) { } }; CompanionPrefs companion; DynamicConfigSerializer custom; #ifdef ENABLE_WIFI_INTERFACE class WiFiPrefs : public ConfigSerializer { NodePrefs* _parent; protected: void structure() override { def("ssid", _parent->wifi_ssid, sizeof(_parent->wifi_ssid)); def("pwd", _parent->wifi_pwd, sizeof(_parent->wifi_pwd)); def("enabled", _parent->wifi_enabled); } public: WiFiPrefs(NodePrefs* parent) : _parent(parent) { } }; WiFiPrefs wifi; #endif 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); def("custom", custom); #ifdef ENABLE_WIFI_INTERFACE def("wifi", wifi); #endif } public: NodePrefs() : radio(this), gps(this), companion(this), custom(&radio) #ifdef ENABLE_WIFI_INTERFACE , wifi(this) #endif { 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; } CommonRadioPrefs* getRadioPrefs() { return &radio; } KeyValueStore* getCustom() { return &custom; } bool isDirty() const override { return ConfigSerializer::isDirty() || radio.isDirty() || custom.isDirty(); } void clearDirty() override { ConfigSerializer::clearDirty(); radio.clearDirty(); custom.clearDirty(); } };