Skip to content

feat(companion): SNMP, pull OTA and MAC commands (stacked on #18) - #20

Merged
Elektr0Vodka merged 5 commits into
dmc-devfrom
enhancement/dmc-dev-companion-snmp-ota
Oct 16, 2026
Merged

Elektr0Vodka merged 5 commits into
dmc-devfrom
enhancement/dmc-dev-companion-snmp-ota

Conversation

@Elektr0Vodka

Copy link
Copy Markdown

Stacked on #18 (companion receive filter). Merge #18 first; until then this PR's diff also shows #18's 5 commits. The SNMP filter counters (.10) use #18's filter.

Adds SNMP, pull OTA and MAC commands to the DMC companion, ported from meshcomod and the DMC observer firmware. Reference: docs/companion_snmp_ota_reference.md.

What

  • SNMP: read-only SNMPv2c on UDP 161, off until set snmp on. Observer OID layout (.1-.5, same meaning/type/unit), companion values in .9, receive-filter counters in .10 (same numbers as meshcomod). Unsupported OIDs read noSuchObject. The community is never returned over remote CLI. 0neblock/SNMP_Agent @ 2.1.0 added to the 31 Wi-Fi capable ESP32 companion envs.
  • OTA: ota check | update | status | branch [stable|dev|default] against the DutchMeshCore OTA server (/companion/v, /companion/dev/v). The check reads the manifest over plain HTTP; an update refetches it and downloads the image over HTTPS, verified against pinned roots (CompanionOtaCerts.h, regenerate with scripts/gen_companion_ota_certs.py). Refused on a partition-table change (partSig) or single app slot. ota update replies first and flashes a few seconds later from the main loop (24 KB task), then reboots. Decision logic in src/helpers/OtaManifest.h (from meshcomod) with 33 native tests, plus a tiny manifest field reader (no ArduinoJson).
  • No OTA on 4 MB flash boards (ThinkNode M2/M5, Xiao C3, LilyGo T-LoRa V2.1, DMC_COMPANION_NO_OTA): the TLS stack costs ~180 KB and left them at 95-97%. They keep SNMP and MAC.
  • MAC: get mac, get wifi.mac, get ble.mac (factory MACs from eFuse; n/a off ESP32).
  • build.sh: for *_companion_radio_(wifi|ble) envs bakes COMPANION_OTA_VARIANT and the stable/dev/native bases (native = dev for DMC_CHANNEL=dev, COMPANION_OTA_URL overrides), writes out/<env>.partsig (scripts/partition_signature.py, same as dmc-observer-dev). build_firmware now restores PLATFORMIO_BUILD_FLAGS so per-env flags don't leak across a multi-env build. The release button (ci(release): add DMC companion filter firmware to the release button #19) uploads the .partsig files unchanged.
  • Settings in /cnet.json; MyMesh only gets one-line hooks (CompanionNet.cpp, CompanionOta.cpp, CompanionSNMP.cpp).
  • Docs: reference page, docs/cli_commands.md, dmc-docs nl/en/de, AGENTS.md.

Which builds: SNMP + OTA on 22 ESP32 *_companion_radio_wifi (minus the 4 MB ones for OTA) and 9 ESP32 *_companion_radio_ble boards that also have Wi-Fi (Heltec V3/WSL3/V4/V4 R8/Wireless Paper, RAK3112, ThinkNode M7, Xiao S3/S3 WIO; Wi-Fi via set wifi.enabled 1). nRF52/RP2040: unchanged apart from get mac = n/a.

Depends on

OTA only works once the DutchMeshCore-OTA server serves the /companion feed (dmc-companion-v* stable, dmc-companion-dev dev, prereleases allowed), Cloudflare gets the /companion/* rules, and a dmc-companion-* release is published.

Verification

  • pio test -e native: all suites pass, incl. new test_ota_manifest (33 tests).
  • Built via build.sh: Heltec_v3_companion_radio_wifi (40.1%), Heltec_v3_companion_radio_ble, Xiao_C3_companion_radio_wifi (81.5%), ThinkNode_M2_companion_radio_wifi (84.0%), LilyGo_TLora_V2_1_1_6_companion_radio_wifi, LilyGo_T3S3_sx1262_companion_radio_ble, RAK_4631_companion_radio_ble, PicoW_companion_radio_wifi. .partsig produced.
  • Not tested on hardware, and OTA not tested end to end (server feed not deployed yet).

Note: upstream's set wifi.enabled uses atoi, so set wifi.enabled on turns Wi-Fi off; docs say 1. Not changed here.

🤖 Generated with Claude Code

Ported from meshcomod's OtaManifest.h (version compare, partition
signature, firmware URL allowlist) with its native tests, plus what the DMC
companion needs on top: a small reader for the manifest's string fields
(no JSON library on the companion), an https check for the image URL and
the stable/dev/default channel selector used by `ota branch`.
For DMC companion builds that can join Wi-Fi (ESP32 *_companion_radio_wifi
and the ESP32 *_companion_radio_ble boards with Wi-Fi), ported from
meshcomod and the DMC observer:

- SNMP: read-only SNMPv2c on UDP 161, off until `set snmp on`. Observer
  OID layout (.1-.5), companion-only values in .9 and the receive filter
  counters in .10, as on meshcomod. The community never leaves over the
  mesh. 0neblock/SNMP_Agent added to the 31 Wi-Fi capable envs.
- OTA: `ota check|update|status|branch` against the DutchMeshCore OTA
  server (/companion/v, /companion/dev/v). The check reads the manifest
  over plain HTTP; an update refetches it and downloads the image over
  HTTPS, verified against pinned roots (CompanionOtaCerts.h, generated by
  scripts/gen_companion_ota_certs.py). Refused on a partition layout
  change or a single app slot. The flash starts from the main loop a few
  seconds after the reply, in a 24 KB task.
- `get mac`, `get wifi.mac`, `get ble.mac`: factory MACs (n/a off ESP32).

Settings in /cnet.json. MyMesh only carries one-line hooks.
For *_companion_radio_wifi and *_companion_radio_ble envs, build.sh passes
COMPANION_OTA_VARIANT (the env name) and the stable, dev and native OTA
bases (native = dev for DMC_CHANNEL=dev; COMPANION_OTA_URL overrides the
server), and writes out/<env>.partsig with scripts/partition_signature.py
(same as dmc-observer-dev) for the server's manifest.

build_firmware now restores PLATFORMIO_BUILD_FLAGS on return, so one env's
-D flags no longer leak into the next env of a multi-env build.
The TLS stack the OTA download needs costs ~180 KB of flash and left the
1.25 MB app slot boards at 95-97%. ThinkNode M2, ThinkNode M5, Xiao C3 and
LilyGo T-LoRa V2.1 (Wi-Fi) now set DMC_COMPANION_NO_OTA: they keep SNMP and
the MAC commands, and `ota` answers that they update over USB.
Xiao C3 back to 81.5%, ThinkNode M2 84.0%.
@Elektr0Vodka
Elektr0Vodka merged commit bd8aef7 into dmc-dev Oct 16, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant