mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-10-15 07:19:56 +00:00
server roles, event loops, companion transports, storage and prefs.json
Server roles (slice 7) - CommonCLI split into upstream's shape; region CLI moved into CommonCLI; ClientACL, RegionMap, TransportKeyStore and both server meshes in upstream shape over an Arduino compat shim (helpers/compat: Arduino.h, Stream/Print, Serial, SHA256, FILESYSTEM/File over Zephyr fs) - room server processAck port; `get acl` prints as upstream - room: default name Room-XXXX, display/input rotation, live radio UI refresh Event loops (slice 7b) - repeater and room server share server_main_common with a ServerRole descriptor; shared event bits in src/mesh_events.h - room server deadline-driven (idle wakes 2.2/s -> 0.08/s); companion loop() runs on housekeeping (closes the lazy contact-flush gap) - `get loop.wakes` in debug builds (CONFIG_ZEPHCORE_LOOP_WAKE_STATS) Companion transports and WiFi (slice 8) - upstream MultiSerialInterface: BLE, USB/UART and TCP are each a BaseSerialInterface, every connected transport gets every frame; CompanionSerial holds a lossless reply; shared frame_txq for BLE/TCP - SerialCompanionTransport and LinuxTCPTransport replaced by TcpCompanionTransport; ZephyrBLE split (gatt layout, DFU) - WiFi companion (upstream wifi.ssid/pwd/enabled CLI, TCP port 5000) on boards declaring `capabilities: wifi` in zephcore.yml: the PSRAM ESP32-S3 boards, plus Heltec V3 (140 contacts), Wireless Tracker (130) and both C6 boards (280); ESP32-S3 without PSRAM gets bounded WiFi buffers and a measured 72 KB heap; PSRAM boards' internal heap 72 KB - TCP queues: own depth (ZEPHCORE_TCP_QUEUE_SIZE=8), RX waits instead of dropping - RAM: companion ClientACL dropped; main/BT-TX/TCP stacks sized from measured peaks (-7 KB nRF companions, -9 KB ESP32 companions) - ESP32 WiFi stopped working under ~200 frames/s unicast. Fixed by: patches/zephyr/0017 never block the WiFi task in the RX callback; patches/zephyr/0018 lock shared_multi_heap (heap corruption with the WiFi heap in PSRAM); patches/modules/hal_espressif/0001 backport of hal_espressif af97fb02df (PSRAM realloc) Storage and prefs (slice 9) - prefs are now prefs.json through upstream's ConfigSerializer (ported verbatim), with upstream's key names for shared fields and ZephCore's own under "zc"; on first boot the binary new_prefs / repeater prefs is migrated and kept, so a downgrade still boots with the old settings - helpers/PrefsCodec: both legacy binary layouts (companion 272 B, server 311 B) as Zephyr-free codecs; sanitizeNodePrefs is the only validator - fix: server prefs could be replaced by a truncated file when a write failed; identity, prefs and channel writes go through one checked atomic replace (ZephyrFsUtil) - fix: a corrupt cad_auto byte turned adaptive CAD off instead of the default on - fix: a deliberate 300 s GPS duty on a repeater was rewritten to 48 h on every boot (that migration now runs on legacy files only) - one identity loader for all roles (IdentityFile); an unusable key file is always parked as .bad before regenerating - server store no longer stamps repeater defaults on room server and observer; companion first-boot volume policy moved into the store (adoptVolume) - ZephyrDataStore 1435 -> ~850 lines
This commit is contained in:
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* PrefsJson - prefs.json for both roles. See PrefsJson.h.
|
||||
*/
|
||||
|
||||
#include "PrefsJson.h"
|
||||
|
||||
namespace {
|
||||
|
||||
/* radio{} and gps{}: the same keys in both of upstream's trees. Not written:
|
||||
* "cad" (ZephCore always runs CAD), "agc_int" (periodic AGC reset removed),
|
||||
* "fem_txgain" (no such setting here). */
|
||||
class RadioJson : public ConfigSerializer {
|
||||
NodePrefs *_p;
|
||||
|
||||
protected:
|
||||
void structure() override
|
||||
{
|
||||
def("freq", _p->freq);
|
||||
def("bw", _p->bw);
|
||||
def("sf", _p->sf);
|
||||
def("cr", _p->cr);
|
||||
def("int_thr", _p->interference_threshold);
|
||||
def("rxgain", _p->rx_boost);
|
||||
def("fem_rxgain", _p->fem_rxgain);
|
||||
def("tx", _p->tx_power_dbm);
|
||||
def("af", _p->airtime_factor);
|
||||
def("rxdelay", _p->rx_delay_base);
|
||||
def("f_txdelay", _p->tx_delay_factor);
|
||||
def("d_txdelay", _p->direct_tx_delay_factor);
|
||||
def("hash_mode", _p->path_hash_mode);
|
||||
def("multi_ack", _p->multi_acks);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit RadioJson(NodePrefs *p) : _p(p) {}
|
||||
};
|
||||
|
||||
class GpsJson : public ConfigSerializer {
|
||||
NodePrefs *_p;
|
||||
|
||||
protected:
|
||||
void structure() override
|
||||
{
|
||||
def("en", _p->gps_enabled);
|
||||
def("int", _p->gps_interval);
|
||||
def("adv_loc", _p->advert_loc_policy);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit GpsJson(NodePrefs *p) : _p(p) {}
|
||||
};
|
||||
|
||||
/* zc{}: ZephCore's own settings, common to both roles */
|
||||
class ZcCommonJson : public ConfigSerializer {
|
||||
protected:
|
||||
NodePrefs *_p;
|
||||
|
||||
void structure() override
|
||||
{
|
||||
def("leds_off", _p->leds_disabled);
|
||||
def("leds_radio", _p->leds_radio_mode);
|
||||
def("leds_hb", _p->leds_hb_mode);
|
||||
def("rx_dc", _p->rx_duty_cycle);
|
||||
def("mts", _p->meshtimesync);
|
||||
def("cad_auto", _p->cad_auto);
|
||||
def("cad_off", _p->cad_offset);
|
||||
def("cad_base", _p->cad_base);
|
||||
def("probe_int", _p->probe_interval);
|
||||
def("busycap", _p->cad_busycap);
|
||||
def("xsf", (void *)_p->extra_sf, EXTRA_SF_MAX);
|
||||
def("disp_rot", _p->display_rotate);
|
||||
def("in_rot", _p->input_rotate);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit ZcCommonJson(NodePrefs *p) : _p(p) {}
|
||||
};
|
||||
|
||||
/* ── Companion: upstream examples/companion_radio/NodePrefs.h ──────── */
|
||||
|
||||
class RepeatDisableJson : public ConfigSerializer {
|
||||
protected:
|
||||
void structure() override { def("disable", disable); }
|
||||
|
||||
public:
|
||||
uint8_t disable = 1;
|
||||
};
|
||||
|
||||
class CompJson : public ConfigSerializer {
|
||||
NodePrefs *_p;
|
||||
|
||||
protected:
|
||||
void structure() override
|
||||
{
|
||||
def("auto_max", _p->autoadd_max_hops);
|
||||
def("defs_nm", _p->default_scope_name, sizeof(_p->default_scope_name));
|
||||
def("defs_key", (void *)_p->default_scope_key, sizeof(_p->default_scope_key));
|
||||
def("pin", _p->ble_pin);
|
||||
def("buzz_q", _p->buzzer_quiet);
|
||||
def("auto_add", _p->autoadd_config);
|
||||
def("man_add", _p->manual_add_contacts);
|
||||
def("tel_base", _p->telemetry_mode_base);
|
||||
def("tel_loc", _p->telemetry_mode_loc);
|
||||
def("tel_env", _p->telemetry_mode_env);
|
||||
def("tz_offset", _p->tz_offset);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit CompJson(NodePrefs *p) : _p(p) {}
|
||||
};
|
||||
|
||||
class WifiJson : public ConfigSerializer {
|
||||
NodePrefs *_p;
|
||||
|
||||
protected:
|
||||
void structure() override
|
||||
{
|
||||
def("ssid", _p->wifi_ssid, sizeof(_p->wifi_ssid));
|
||||
def("pwd", _p->wifi_pwd, sizeof(_p->wifi_pwd));
|
||||
def("enabled", _p->wifi_enabled);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit WifiJson(NodePrefs *p) : _p(p) {}
|
||||
};
|
||||
|
||||
class ZcCompanionJson : public ZcCommonJson {
|
||||
protected:
|
||||
void structure() override
|
||||
{
|
||||
ZcCommonJson::structure();
|
||||
def("ble_off", _p->ble_disabled);
|
||||
def("bright", _p->display_brightness);
|
||||
def("wake", _p->wake_on_msg);
|
||||
def("scr_off", _p->screen_off_secs);
|
||||
def("auto_off_mv", _p->auto_shutdown_mv);
|
||||
def("vc_en", _p->v_contact_enabled);
|
||||
def("vc_flags", _p->v_contact_flags);
|
||||
def("vbat_mv", _p->v_battery_alert_mv);
|
||||
def("adc_mult", _p->adc_multiplier);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit ZcCompanionJson(NodePrefs *p) : ZcCommonJson(p) {}
|
||||
};
|
||||
|
||||
class CompanionJson : public ConfigSerializer {
|
||||
NodePrefs *_p;
|
||||
RadioJson _radio;
|
||||
GpsJson _gps;
|
||||
RepeatDisableJson _repeat;
|
||||
CompJson _comp;
|
||||
WifiJson _wifi;
|
||||
ZcCompanionJson _zc;
|
||||
|
||||
protected:
|
||||
void structure() override
|
||||
{
|
||||
def("name", _p->node_name, sizeof(_p->node_name));
|
||||
def("lat", _p->node_lat);
|
||||
def("lon", _p->node_lon);
|
||||
def("radio", _radio);
|
||||
def("gps", _gps);
|
||||
def("repeat", _repeat);
|
||||
def("comp", _comp);
|
||||
def("wifi", _wifi);
|
||||
def("zc", _zc);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit CompanionJson(NodePrefs *p)
|
||||
: _p(p), _radio(p), _gps(p), _comp(p), _wifi(p), _zc(p)
|
||||
{
|
||||
/* upstream: repeat.disable; ours: client_repeat (1 = forward) */
|
||||
_repeat.disable = p->client_repeat ? 0 : 1;
|
||||
}
|
||||
|
||||
bool save(Stream &s) { return saveSerial(s); }
|
||||
bool load(Stream &s)
|
||||
{
|
||||
bool ok = loadSerial(s);
|
||||
|
||||
_p->client_repeat = _repeat.disable ? 0 : 1;
|
||||
return ok;
|
||||
}
|
||||
};
|
||||
|
||||
/* ── Servers: upstream helpers/CommonCLI.h ──────────────────────────── */
|
||||
|
||||
class RepeatJson : public ConfigSerializer {
|
||||
NodePrefs *_p;
|
||||
|
||||
protected:
|
||||
void structure() override
|
||||
{
|
||||
def("disable", _p->disable_fwd);
|
||||
def("f_max", _p->flood_max);
|
||||
def("f_max_uns", _p->flood_max_unscoped);
|
||||
def("f_max_adv", _p->flood_max_advert);
|
||||
def("loop", _p->loop_detect);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit RepeatJson(NodePrefs *p) : _p(p) {}
|
||||
};
|
||||
|
||||
class RoomJson : public ConfigSerializer {
|
||||
NodePrefs *_p;
|
||||
|
||||
protected:
|
||||
void structure() override { def("rd_only", _p->allow_read_only); }
|
||||
|
||||
public:
|
||||
explicit RoomJson(NodePrefs *p) : _p(p) {}
|
||||
};
|
||||
|
||||
class PowerJson : public ConfigSerializer {
|
||||
NodePrefs *_p;
|
||||
|
||||
protected:
|
||||
void structure() override
|
||||
{
|
||||
def("adc_mult", _p->adc_multiplier);
|
||||
def("pwr_sav_en", _p->powersaving_enabled);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit PowerJson(NodePrefs *p) : _p(p) {}
|
||||
};
|
||||
|
||||
class ZcServerJson : public ZcCommonJson {
|
||||
protected:
|
||||
void structure() override
|
||||
{
|
||||
ZcCommonJson::structure();
|
||||
def("tz_offset", _p->tz_offset);
|
||||
def("backoff", _p->backoff_multiplier);
|
||||
def("disc_ts", _p->discovery_mod_timestamp);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit ZcServerJson(NodePrefs *p) : ZcCommonJson(p) {}
|
||||
};
|
||||
|
||||
class ServerJson : public ConfigSerializer {
|
||||
NodePrefs *_p;
|
||||
RadioJson _radio;
|
||||
GpsJson _gps;
|
||||
RepeatJson _repeat;
|
||||
RoomJson _room;
|
||||
PowerJson _power;
|
||||
ZcServerJson _zc;
|
||||
|
||||
protected:
|
||||
void structure() override
|
||||
{
|
||||
def("name", _p->node_name, sizeof(_p->node_name));
|
||||
def("pass", _p->password, sizeof(_p->password));
|
||||
def("guest", _p->guest_password, sizeof(_p->guest_password));
|
||||
def("owner", _p->owner_info, sizeof(_p->owner_info));
|
||||
def("adv_int", _p->advert_interval);
|
||||
def("f_adv_int", _p->flood_advert_interval);
|
||||
def("lat", _p->node_lat);
|
||||
def("lon", _p->node_lon);
|
||||
def("radio", _radio);
|
||||
def("gps", _gps);
|
||||
def("repeat", _repeat);
|
||||
def("room", _room);
|
||||
def("power", _power);
|
||||
def("zc", _zc);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit ServerJson(NodePrefs *p)
|
||||
: _p(p), _radio(p), _gps(p), _repeat(p), _room(p), _power(p), _zc(p) {}
|
||||
|
||||
bool save(Stream &s) { return saveSerial(s); }
|
||||
bool load(Stream &s) { return loadSerial(s); }
|
||||
};
|
||||
|
||||
void saneRadio(NodePrefs &p)
|
||||
{
|
||||
if (p.freq < ZC_RADIO_FREQ_MIN_MHZ || p.freq > ZC_RADIO_FREQ_MAX_MHZ ||
|
||||
p.sf < 5 || p.sf > 12 ||
|
||||
p.bw < ZC_RADIO_BW_MIN_KHZ || p.bw > ZC_RADIO_BW_MAX_KHZ) {
|
||||
p.freq = mesh::LoRaConfig::FREQ_MHZ;
|
||||
p.bw = mesh::LoRaConfig::BANDWIDTH_KHZ;
|
||||
p.sf = mesh::LoRaConfig::SPREADING_FACTOR;
|
||||
p.cr = mesh::LoRaConfig::CODING_RATE;
|
||||
p.tx_power_dbm = mesh::LoRaConfig::TX_POWER_DBM;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/* Writing only reads the struct; the serializer API takes references. */
|
||||
|
||||
bool companionPrefsToJson(const NodePrefs &p, Stream &out)
|
||||
{
|
||||
CompanionJson j(const_cast<NodePrefs *>(&p));
|
||||
|
||||
return j.save(out);
|
||||
}
|
||||
|
||||
bool serverPrefsToJson(const NodePrefs &p, Stream &out)
|
||||
{
|
||||
ServerJson j(const_cast<NodePrefs *>(&p));
|
||||
|
||||
return j.save(out);
|
||||
}
|
||||
|
||||
bool companionPrefsFromJson(NodePrefs &p, Stream &in)
|
||||
{
|
||||
NodePrefs t = p;
|
||||
CompanionJson j(&t);
|
||||
|
||||
if (!j.load(in)) {
|
||||
return false;
|
||||
}
|
||||
saneRadio(t);
|
||||
sanitizeNodePrefs(&t);
|
||||
p = t;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool serverPrefsFromJson(NodePrefs &p, Stream &in)
|
||||
{
|
||||
NodePrefs t = p;
|
||||
ServerJson j(&t);
|
||||
|
||||
if (!j.load(in)) {
|
||||
return false;
|
||||
}
|
||||
saneRadio(t);
|
||||
sanitizeNodePrefs(&t);
|
||||
p = t;
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user