Skip to content

feat: publish device on the LAN via mDNS / Bonjour#22

Open
PAzter1101 wants to merge 3 commits intojrl290:mainfrom
PAzter1101:feat/mdns-discovery
Open

feat: publish device on the LAN via mDNS / Bonjour#22
PAzter1101 wants to merge 3 commits intojrl290:mainfrom
PAzter1101:feat/mdns-discovery

Conversation

@PAzter1101
Copy link
Copy Markdown

Summary

Adds mDNS / Bonjour publishing so the device is reachable as <hostname>.local from any machine on the same LAN, without needing a static IP or a router-side DHCP reservation. The Local TCP Server (when enabled) is also advertised as a _reticulum._tcp service for auto-discovery by Reticulum-aware tooling.

In configuration-portal AP mode the captive portal is reachable as rtnode.local, removing the need to remember 10.0.0.1.

Motivation

Right now the only way to point an external rnsd (or Sideband) at a transport node's Local TCP Server is to look the address up in the router admin and either set up a DHCP reservation or hard-code the lease. Both break the moment the lease changes hands or the user moves to a different network. mDNS solves it with a stable, human-readable name.

What's in the patch

Configuration portal

New Local Network Name (mDNS) section:

  • mDNS — Enable / Disable (default Enabled). When disabled, the device suppresses all multicast announcements and is only reachable by IP.
  • Hostname — optional custom hostname. Empty falls back to rtnode<XXXX> where XXXX is the last 4 hex chars of the device MAC. Input is normalised to lowercase + [a-z0-9-] and stripped of leading/trailing hyphens before save.

OLED display

When mDNS is enabled, the right-panel lower area shows three rows: hostname, IP, port. The previous bottom separator line is dropped to free the row.

When mDNS is disabled, the original two-row layout (IP + port + separator) is preserved unchanged.

EEPROM additions

Address Size Purpose
0x151 1 byte mDNS enable flag
0x152 33 bytes Custom hostname (null-terminated)

Both default to "enabled / auto-generated name" when the bytes are unprogrammed (0xFF), so existing installations keep working without any factory reset.

Implementation

mDNS itself is a thin header-only wrapper around ESPmDNS in MdnsService.h. It is started lazily from the main loop once WiFi finishes its asynchronous association, and torn down before switching the radio into config-portal AP mode so the ESPmDNS state never survives a WiFi mode change.

Build fix (separate commit)

platformio.ini had MsgPack@^0.4.2 which is now ambiguous between hideakitai/MsgPack and mbed-yihui/msgpack and stalls the Library Manager. Pinned to hideakitai/MsgPack@^0.4.2 to keep the same version range while removing the prompt. This is its own commit so you can pick it up or skip it.

Backwards compatibility

  • New EEPROM bytes default to enabled-with-auto-name on uninitialised (0xFF) reads, so users who flash this build over an existing install get mDNS automatically without losing any saved settings.
  • Users who don't want mDNS can disable it in the portal — the OLED layout reverts to the original look in that case.
  • No changes to the LoRa, TCP backbone, or Local TCP Server code paths.

Testing

Tested on a Heltec V4 (V4.3 revision):

  • mDNS resolves rtnode<XXXX>.local from a Linux host (avahi-resolve, getent hosts)
  • _reticulum._tcp service appears in avahi-browse -art _reticulum._tcp with the correct port and address
  • rnsd connects to the Local TCP Server using the .local name as target_host
  • Custom hostname round-trips through the portal save/load
  • Disabling mDNS cleanly stops the service and reverts the OLED layout
  • Config-portal AP mode reachable as rtnode.local

Not tested on Heltec V3 — the implementation only touches the WiFi/Boundary path and uses standard ESPmDNS APIs supported on all ESP32-S3 board variants in this repo, so I expect it to work, but a V3 owner would need to confirm.

Notes

  • Routers with strict AP/client isolation or aggressive IGMP snooping may swallow the multicast and prevent resolution. This is an environmental thing, not a firmware bug — the same setting also blocks any other mDNS device on the network.
  • mDNS adds roughly ~2 KB of flash and a few hundred bytes of heap. Did not observe any memory regressions on the V4 (16 MB / 2 MB PSRAM).

PAzter1101 added 3 commits May 5, 2026 18:02
PlatformIO Library Manager finds two libraries matching `MsgPack@^0.4.2`
(hideakitai/MsgPack and mbed-yihui/msgpack) and stalls with an
ambiguous-package prompt that fails the build. Pinning the owner keeps
the same version range while removing the prompt.
In Boundary mode, advertise the node as `<hostname>.local` and (when the
Local TCP Server is enabled) register a `_reticulum._tcp` service so
LAN-side Reticulum tools can find it without a static IP or DHCP
reservation. In configuration-portal AP mode the captive portal is
reachable as `rtnode.local` for users who don't want to remember the
`10.0.0.1` AP address.

Configuration portal additions:

* New "Local Network Name (mDNS)" section with Enable / Disable toggle
  (default Enabled) and an optional custom Hostname field. Empty
  hostname falls back to `rtnode<XXXX>` where `XXXX` is the last 4 hex
  chars of the device MAC.
* Hostname input is normalised to lowercase + `[a-z0-9-]` and stripped
  of leading / trailing hyphens before being saved.

EEPROM additions:

* `ADDR_CONF_MDNS_EN`   @ 0x151 (1 byte)
* `ADDR_CONF_MDNS_NAME` @ 0x152 (33 bytes, null-terminated)

Both default to "enabled / auto-generated name" when the bytes are
unprogrammed (0xFF), so existing installations keep working without a
factory reset.

OLED layout:

* When mDNS is enabled, the right panel shows three rows in the lower
  area: hostname (`rtnode.local`), IP, port. The previous bottom
  separator line is dropped to free the row.
* When mDNS is disabled, the original two-row layout (IP + port +
  separator) is preserved unchanged.

The mDNS service is implemented as a thin header-only wrapper around
`ESPmDNS` in `MdnsService.h`. It is started lazily from the main loop
once WiFi finishes its asynchronous association, and is torn down
before switching the radio into config-portal AP mode so the ESPmDNS
state never survives a WiFi mode change.

README updated with the new section, the corrected AP address
(`10.0.0.1` / `rtnode.local`), and a hint that `target_host` in the
Reticulum interface config can be the device's `.local` name instead
of an IP.
@jrl290
Copy link
Copy Markdown
Owner

jrl290 commented May 6, 2026

I'll check this out. Probably closer to the weekend

Just fyi, the IP address is printed on the device screen

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.

2 participants