feat(mesh): operator-configurable Meshcore LoRa PHY params (freq/bw/sf/cr)
Archy set no radio params on Meshcore devices — SF/CR/BW/freq lived only in device firmware, so a radio on the wrong preset could not be fixed from the node (it hears RF energy but demodulates nothing; the fleet hit exactly this on an RNode: docs/RETICULUM-TRANSPORT-PROGRESS.md item 4). - protocol.rs: build_set_radio_params — wire format verified against the MeshCore companion firmware handler (CMD_SET_RADIO_PARAMS=11: [11][freq:u32 LE MHz*1000][bw:u32 LE kHz*1000][sf][cr]); byte-layout test pinned to the Portugal preset 869.618 MHz / 62.5 kHz / SF8 / CR8. - serial.rs: MeshcoreDevice::set_radio_params (device reboots on OK). - MeshConfig.lora_radio_params: Option — None (default) leaves the radio untouched, so only explicitly-configured deployments are affected. - session.rs: provision on connect, gated on a persisted last-applied marker (SELF_INFO offsets shift across firmware versions) + the same attempt cap as region/channel so a refusing radio never reboot-loops. - mesh.configure RPC: lora_radio_params arm with firmware-range validation. mesh tests: 114/114 pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
c1dfc6672c
commit
4c3cd4b6ad
@@ -158,6 +158,29 @@ impl RpcHandler {
|
||||
anyhow::bail!("Unknown LoRa region: {trimmed}");
|
||||
}
|
||||
}
|
||||
// Meshcore LoRa PHY params (freq/bw/sf/cr, firmware field units — see
|
||||
// mesh::LoraRadioParams). Validated against the firmware's accepted
|
||||
// ranges here so a bad value errors at the API instead of being sent
|
||||
// to the radio and rejected on-device. `null` clears the setting.
|
||||
if let Some(rp) = params.get("lora_radio_params") {
|
||||
if rp.is_null() {
|
||||
config.lora_radio_params = None;
|
||||
} else {
|
||||
let parsed: mesh::LoraRadioParams = serde_json::from_value(rp.clone())
|
||||
.map_err(|e| anyhow::anyhow!("Invalid lora_radio_params: {e}"))?;
|
||||
anyhow::ensure!(
|
||||
(150_000..=2_500_000).contains(&parsed.freq_khz),
|
||||
"freq_khz out of range (150000..=2500000)"
|
||||
);
|
||||
anyhow::ensure!(
|
||||
(7_000..=500_000).contains(&parsed.bw_hz),
|
||||
"bw_hz out of range (7000..=500000)"
|
||||
);
|
||||
anyhow::ensure!((5..=12).contains(&parsed.sf), "sf out of range (5..=12)");
|
||||
anyhow::ensure!((5..=8).contains(&parsed.cr), "cr out of range (5..=8)");
|
||||
config.lora_radio_params = Some(parsed);
|
||||
}
|
||||
}
|
||||
// Firmware pin: probe only the named firmware on the port ("auto"/""
|
||||
// clears the pin and restores strict-probe auto-detect).
|
||||
if let Some(kind) = params.get("device_kind").and_then(|v| v.as_str()) {
|
||||
|
||||
Reference in New Issue
Block a user