Commit Graph
11 Commits
Author SHA1 Message Date
agessaman fc361ca94b feat(display): add R8 portrait observer layouts 2026-08-28 09:21:38 -07:00
agessaman 3666cb6da9 fix(mqtt): preserve WiFi outage state for alerts 2026-08-20 19:46:44 -07:00
agessaman 75f3e446e0 feat(mqtt): persist observer preferences as JSON 2026-08-14 09:09:05 -07:00
agessaman 616fe96d1e feat(mqtt): publish all message types except raw to MeshRank
MeshRank slots previously took packets only. The broker tolerates status and
neighbors (and its maintainer intends to look at using the neighbors data), so
those now publish under meshrank/uplink/{token}/{device}/{type}, using the same
type suffixes as the MeshCore layout. Raw stays excluded: it is the
highest-volume topic and the broker does not consume it, so `set mqtt.raw on`
has no effect on a MeshRank slot.

All MeshRank gating funnels through the topic router, so relaxing that single
guard was sufficient - publishStatusToSlot, publishStatus, publishRaw,
publishNeighbors, and eligiblePacketSlots already skip slots that cannot form a
topic. A per-slot token is still required. Because eligiblePacketSlots resolves
topic support before serialising, raw JSON is never built for a MeshRank slot
rather than built and discarded.

observer-firmware sends raw to MeshRank; this supersedes that decision, so raw
must stay excluded when the branches merge. MeshRankTakesEveryTypeExceptRaw
fails if a merge re-enables it.
2026-07-29 15:51:28 -07:00
agessaman 52bd27190f feat(mqtt): enhance packet filter functionality with named types
Add support for named packet types in per-slot filters, allowing users
to specify packet types using descriptive names alongside numeric values.
This improves usability and clarity in configuring MQTT slot filters.
Updates include modifications to the parsing logic, WebConfig interface,
and related documentation to reflect the new naming conventions.
2026-07-27 22:29:11 -07:00
agessaman e00b29b4b8 feat(mqtt): add per-slot packet filters for MQTT slots
Introduce per-slot packet filters to allow users to specify which
packet types are uploaded for each MQTT slot. This feature enhances
the flexibility of the MQTT bridge by enabling users to configure
allowlists for packet types, improving the efficiency of data
transmissions. The implementation includes updates to the WebConfig
interface, internal handling of packet filters, and necessary
modifications to the MQTT preferences structure.
2026-07-27 18:34:04 -07:00
agessaman 675bc6b55b feat(webconfig): manage the admin password from the portal
Adds an admin-password field to the setup wizard and the LAN editor, so a
node's password can be set during onboarding and rotated later without a
serial console.

The key maps to the top-level `password` CLI command rather than a `set`
handler, so it is classified separately from WC_ALLOWED_SET_KEYS. It is the
only key granted that treatment, which keeps the allowlist the sole route to
`set` and leaves no general path from a batch to arbitrary CLI commands.

Accepted in both modes: MODE_OFF is refused earlier in handleConfigPost, LAN
required a login to get that far, and the setup AP implies physical proximity.
Restricting rotation to the AP would have forced a bridge outage (`set bridge
off` + `start webconfig ap`) just to change a password.

First onboarding is gated server-side: while the setup AP is up and no WiFi is
configured, a batch that reboots or sets wifi.ssid must also carry a password,
so neither the Advanced editor nor a crafted request can save WiFi and strand
the node on the factory password. The flag is latched at AP start, so a save
that fails partway cannot drop the requirement on retry.

The CLI's `password` command echoes the new secret back in its reply, and
replies are served to the client over the open setup AP, so the reply is
overwritten with "OK" before it can be serialized.

UI: the field lives with the other NodePrefs settings (wizard step 2, and the
Node card on the Radio tab) rather than beside the WiFi password, which is a
different credential. Confirm fields mirror their password twin and are cleared
whenever it is, so a stale confirm value cannot fail a later save as a spurious
mismatch. Validation runs ahead of the WiFi-changed split so a password-only
save is still checked, and reveals the Radio tab before reporting, since the
save bar spans every tab.
2026-07-21 19:00:18 -07:00
agessaman 1be09b9bd6 fix(mqtt): harden /mqtt_prefs migration (atomic durability, tests)
Rework the /mqtt_prefs load/save path so preference migrations are
crash-safe and, for the first time, unit-testable on the host.

Most of this is extraction. The multi-format migration that previously
lived inline in CommonCLI.cpp (and could only run on-device) is moved
into three dependency-free headers so it can be exercised without
Arduino, a filesystem, or the radio stack:

  - MQTTPrefsStorage.h  frozen layout structs for every /mqtt_prefs
                        format ever shipped, with static_asserts that
                        fail the build if any on-flash offset changes.
  - MQTTPrefsCodec.h    pure format classification, field-copy
                        migration, and plausibility validation.
  - MQTTPrefsAtomicStore.h  transactional writer plus the power-cut
                        upgrade gate, both host-testable.

New behavior, beyond the refactor:

  - Atomic writes: /mqtt_prefs is written to /mqtt_prefs.tmp, verified,
    then published with an atomic rename; the writer never removes the
    existing file. A failed or interrupted save leaves the current
    config intact.
  - Power-cut ordering: LegacyUpgradeGate guarantees /mqtt_prefs is
    durably committed before the legacy /com_prefs (or /node_prefs)
    carrying the observer tail is compacted or removed, so an
    interrupted two-file upgrade retries on the next boot without
    losing settings.
  - Corrupt, unsupported-version, and newer-than-known files are
    preserved and the device boots on in-RAM defaults, rather than
    overwriting a file this firmware cannot fully decode.
  - Headerless legacy formats are validated for plausibility before
    they are trusted and rewritten (raw prefs carry no checksum).

The full historical format matrix is migrated forward to the versioned
v1 layout: pre-slot (including pre-wifi-power), 3-slot (base and
token/topic tails), and headerless 6-slot (base, audience, rx, ntp).

Scope note: only /mqtt_prefs and the one-time /node_prefs -> /com_prefs
name migration use the atomic path. Ordinary /com_prefs saves remain a
direct rewrite, unchanged by this commit.

Tests: adds two host GoogleTest suites (pio test -e native).
  - test_mqtt_prefs_codec: format classification, migration fixtures,
    v1 header integrity, downgrade preservation.
  - test_mqtt_prefs_atomic_store: transactional writes, short-write
    detection, begin/finish/rename failure cleanup, original-file
    preservation.
2026-07-18 18:44:37 -07:00
agessaman b5deaf93fc fix(mqtt): restore PSRAM buffers after restart 2026-07-18 16:41:27 -07:00
agessaman 26a8a3cb58 feat(mqtt): refactor message building to use MQTTPayloadBuilder
Replace direct JSON construction in MQTTMessageBuilder with calls to
MQTTPayloadBuilder for building status, packet, and raw messages.
This change improves code maintainability and reduces duplication by
centralizing message formatting logic. Additionally, update platformio.ini
to include ArduinoJson dependency for JSON handling.
2026-07-18 15:47:11 -07:00
agessaman cbbd01b620 feat(docs): add local testing instructions for MQTT functionality
Include detailed instructions for local testing of observer and WiFi
functionality without hardware. Document the use of a mock backend and
Wokwi ESP32-S3 simulation for easier development and testing.
Enhance the MQTT implementation documentation to improve developer
experience and facilitate testing workflows.
2026-07-18 13:19:27 -07:00