Back // guide · observers

Set up an observer node for rflab.io & meshmapper.net

Guide · updated June 2026

An observer listens to the mesh and uplinks every packet it hears to MQTT — so CoreScope and the other analyzers can see what’s happening. Here’s how to flash one and point it at RF Lab.

What an observer does

It’s a normal MeshCore node that also has WiFi: it hears packets over LoRa and forwards them to an MQTT broker, which is what feeds the maps and analyzers. The firmware we use is the Flex MQTT-bridge build by agessaman — it gives a node six MQTT slots, so one observer can feed several networks at once. This setup uses two: mqtt1 for RF Lab (CoreScope, over WebSocket) and mqtt2 for MeshMapper.

The whole thing flashes from your browser with the MeshCore Observer Flasher — no toolchain, no command line to install.

// before you start

What you need

  • A WiFi-capable LoRa board (ESP32-class) — Heltec V3/V4, Station G2, Xiao S3 WIO, RAK boards and more. The observer needs WiFi to reach the broker.
  • The antenna for your board — attach it before powering on.
  • Chrome or Edge (the flasher uses Web Serial), and your WiFi name + password.
// step 1

Flash the firmware

  1. Open the Observer Flasher

    Go to observer.gessaman.com in Chrome or Edge and plug your board in with USB.

  2. Pick board, build & role

    Under Choose device select your board, then the MQTT Observer firmware (the Flex build), and set the role to Repeater (or Room Server). On a brand-new board, do a full erase first.

  3. Flash, then open the console

    Let it finish, then open the flasher’s Serial Console (any serial terminal works too) — that’s where you’ll paste the config next.

// step 2

Configure it for RF Lab

In the Serial Console, set the node up and point its broker slots at the analyzers — RF Lab goes in slot mqtt1. Fill in the <…> placeholders; the commented line is for restores only.

set name <OBSERVER_NAME>              # max 23 characters
set owner.info <OWNER_INFO>           # e.g. Join us on Discord at join.rflab.io
password <NODE_PASSWORD>              # the node’s admin password
set lat <LAT>                         # decimal degrees, e.g. 43.0746
set lon <LON>                         # e.g. -89.3841

# set prv.key <PRIVATE_KEY>   ← ONLY when restoring a saved node

set wifi.ssid <SSID>                  # it uplinks over WiFi
set wifi.pwd <PASS>

set repeat off                        # use this if you do not want it to act as a repeater
set radio 910.525,62.5,7,5            # RF Lab radio preset (freq,BW,SF,CR)
set path.hash.mode 2                  # advert path hash size
set tx 22                             # TX power in dBm — your call

set mqtt.iata <IATA>                  # your 3-letter airport code, e.g. MSN

# slot 1 — RF Lab / CoreScope
set mqtt1.preset rflab

# slot 2 — MeshMapper
set mqtt2.preset meshmapper

reboot

The radio line must match the mesh. set radio 910.525,62.5,7,5 is the RF Lab preset — 910.525 MHz, 62.5 kHz bandwidth, spreading factor 7, coding rate 5. An observer only hears a network it’s tuned to, so if this doesn’t match, it’ll log nothing useful.

Leave set prv.key out unless you’re restoring. The private key is the node’s identity — treat it like a master password: never share or post it. A fresh node makes its own; only paste a key when you’re bringing back a node you previously backed up.

The lines you’ll tweak

  • name — how it shows on the mesh and maps (23 characters max).
  • owner.info — free text others can see; a nice spot to point people at the community (e.g. Join us on Discord at join.rflab.io).
  • password — sets the node’s admin password. Remember it.
  • lat / lon — the node’s location in decimal degrees, so the maps can place it.
  • repeat — set off if you do not want it to act as a repeater (a pure listener); your call.
  • tx — transmit power in dBm; set to suit your board, antenna and local rules.
  • mqtt.iata — your nearest airport code (Madison is MSN); use whatever fits your location.
RF Lab broker · slot mqtt1 · preset
  • Presetrflab
  • Serverwss://mqtt.rflab.io
  • Port443
  • Loginnone (open)

The rflab preset fills in the WebSocket server and audience for you — nothing to type, no username or password. MeshMapper’s meshmapper preset works the same way.

// step 3

Confirm it’s feeding

After the reboot, log back in with your password and check WiFi, then the uplink:

get wifi.status        # should show connected, with an IP
get mqtt.status        # should report connected
get mqtt1.diag         # the last error if RF Lab (slot 1) won’t connect

Within a few minutes your node should start showing up on CoreScope as an observer, with packets flowing in. If mqtt.status isn’t connected, double-check the WiFi lines and that mqtt1 is set to the rflab preset.

// alerts · optional

Get pinged if it goes down

The Flex firmware can flood a one-line fault message over LoRa when the observer’s WiFi or an MQTT slot stays down — over the mesh, not MQTT, since MQTT is usually the thing that broke. Put it on a private channel (a PSK only you hold) so just you or your ops group see it:

set alert.psk <32-HEX-CHARS>      # 16-byte secret = your private alert channel
set alert.wifi 30                 # alert if WiFi stays down 30 min
set alert.mqtt 240                # alert if an MQTT slot stays down 4 h
set alert on
alert test                        # fire a test message right now

Watch that channel from any MeshCore client holding the same PSK. Recovery messages send themselves once it reconnects, and re-fires are rate-limited (60 min minimum). Full reference: the alerts docs.

// update

Update your observer

Already running an observer? Just update it with the Observer Flasher to pick up the latest build and the new rflab preset.

// alternative · python

On a Raspberry Pi instead? Feed us with pyMC

No ESP32 to flash? pyMC is a Python MeshCore repeater/observer that runs on a Raspberry Pi or any Linux box with an SPI LoRa radio. It’s driven by a YAML config — add RF Lab’s WebSocket broker to its mqtt_brokers list and it uplinks everything it hears.

Open your pyMC config — /etc/pymc_repeater/config.yaml — and add RF Lab under mqtt_brokersbrokers:

mqtt_brokers:
  iata_code: <IATA>              # your nearest 3-letter airport code, e.g. MSN
  status_interval: 300
  brokers:
    # RF Lab — over WebSocket
    - name: RF Lab
      enabled: true
      host: mqtt.rflab.io
      port: 443
      transport: websockets
      format: letsmesh
      use_jwt_auth: true
      audience: mqtt.rflab.io
      retain_status: false
      tls:
        enabled: true
        insecure: false

No username or password. RF Lab’s WebSocket broker uses key-based auth — pyMC signs with its own MeshCore identity (use_jwt_auth: true, audience: mqtt.rflab.io), exactly like the firmware observer. Leave username / password out. Already have an mqtt_brokers block? Just add the - name: RF Lab entry under brokers:.

Save, restart pyMC, and confirm it connected:

sudo systemctl restart pymc-repeater
sudo journalctl -u pymc-repeater.service -f | grep "RF Lab"

pyMC ships two built-in presets (letsmesh, waev); RF Lab is a custom broker, so paste the full block above. The letsmesh format matches the analyzer / MeshMapper broker family that RF Lab runs. The project is also known as openHop — full install in the pyMC_Repeater repo and the MeshMapper pyMC guide.

// alternative · home assistant

Already running Home Assistant? Uplink from there

The MeshCore integration for Home Assistant can publish everything your node hears straight to RF Lab — no second device, no separate observer. If HA is already talking to a node over BLE, USB or TCP, this is the least-effort way to feed us.

It isn’t in the default HACS index, so add it as a custom repository (HACS → Integrations → ⋮ → Custom repositories → github.com/meshcore-dev/meshcore-ha, category Integration), install MeshCore, and restart. Then set up your node and open:

Settings → Devices & Services → MeshCore → Configure → Manage MQTT Brokers

Add a broker and fill it in like this:

SettingValue
Servermqtt.rflab.io
Port443
Transportwebsockets
Use TLS / TLS Verifyboth on
Keepalive60 (default)
Username / Passwordleave blank
Use MeshCore Auth Token✓ checked
Token Audiencemqtt.rflab.io
Owner Public Key / Owner Emailoptional — see below
Payload ModePacket (LetsMesh-compatible)
Auth Token TTL3600 (default)
Status Topicmeshcore/{IATA}/{PUBLIC_KEY}/status
Packets Topicmeshcore/{IATA}/{PUBLIC_KEY}/packets
Broker IATA Code<IATA>

Change the port and transport — the defaults won’t reach us. The dialog opens on 1883 over plain tcp. RF Lab is WebSocket on 443 with TLS, so set Server, Port, Transport and TLS before you submit. Leave the two topic templates exactly as they come — they’re already right — and put your nearest 3-letter airport code in Broker IATA Code (Madison is MSN). That code is substituted into the topics, so it has to match the code your node publishes under.

Auth Token needs a key-export firmware build. Ticking Use MeshCore Auth Token makes the integration mint a short-lived token signed with your node’s own MeshCore identity — which is why no username or password is needed. To do that it has to read the node’s private key once, so the node must be running firmware built with ENABLE_PRIVATE_KEY_EXPORT=1. If the token can’t be signed, that’s the first thing to check.

Owner Public Key (64 hex characters) and Owner Email are optional claims that attribute the feed to you — handy if you want your uplink recognisable, skippable if you don’t. They’re only sent when Use TLS and TLS Verify are both enabled. Payload Mode matters more: Packet (LetsMesh-compatible) normalises what your node hears into the packet format our analyzers expect, while Raw Event emits raw MeshCore events — pick Packet.

Feeding the mesh?

Tell us your observer’s name in #meshcore — we’ll watch for it on the map.