Local Broadcast (UDP/OSC)
ESPGeiger can broadcast click events and periodic stats to a UDP multicast group using the Open Sound Control (OSC) 1.0 wire format. Any OSC-aware tool on the same LAN (Pure Data, TouchDesigner, python-osc, Max/MSP, Node-RED) can subscribe and react to live radiation events without polling MQTT or HTTP.
A matching receiver firmware variant (UDP-Receiver) lets a tubeless ESP device mirror another ESPGeiger over the air. Display, MQTT, WebAPI, OLED and blip-LED all work as if a real tube were attached.
- Multicast group:
239.255.86.86(configurable) - UDP port:
57340(configurable) - Service announced via mDNS as
_osc._udp
Quick Start
You need two devices on the same WiFi: one ESPGeiger with a tube (the producer) and one with a *_udp build (the receiver).
On the producer:
- Note its 6-hex chipid, visible on the home page or
/info. - Go to Config → Local Broadcast, set Mode to
2(telemetry + blips), Save.
On the receiver:
- Flash an
esp8266_udp/esp8266oled_udp/esp32_udp/esp32c3_udp/esp32s3_udpbuild via the Web Installer. - Join your WiFi via the captive portal, same network as the producer.
- Open the device’s web UI and go to Config → Input.
- (Optional) Set udprx_chipid to the producer’s 6-hex ID. Leave blank to auto-latch onto the first producer heard.
- Save.
Within a few seconds the receiver’s OLED page 2 (or /status) should show RX <chipid> and a loss percentage and the CPM number should track the producer’s.
Not working?
- Same WiFi network and subnet. Multicast does not cross routers or guest networks; both devices need to be on the same AP / SSID.
- Producer in Mode 2. Mode 1 only sends stats every 30 s and produces no clicks.
- Receiver actually flashed as
*_udp. Check/infoon the receiver shows a UDP build target. - Loss percentage high or clicks missing (ESP32 receivers). With WiFi power save on (the default), the classic ESP32 can miss most multicast packets on some access points. CPM still tracks, since each packet carries the running total, but clicks are lost. Set the producer’s group to the receiver’s IP address instead: unicast isn’t affected. Failing that,
udprx_rxmode = 2keeps the radio always on (runs warmer). - Wrong producer locked. In auto-mode the receiver latches onto the first producer heard. Set the chipid explicitly if you have multiple.
Output Modes (Producer)
Configured on the Config → Local Broadcast page.
| Mode | Behaviour |
|---|---|
0 (off) | No packets sent. Default. |
1 (telemetry only) | /rad, /hv, /sys periodic bursts. No per-click traffic. |
2 (telemetry + blips) | Periodic telemetry plus one /click per radiation event. |
Source Modes (Receiver)
Configured on the Config → Input page (udprx_mode).
| Mode | Behaviour |
|---|---|
0 (specific) | Accept clicks from a specific producer. With udprx_chipid blank, auto-latch onto the first producer heard and lock to it. |
1 (sum) | Aggregate clicks from every producer heard. Up to 8 tracked. |
Build Targets
| Target | Platform | Display |
|---|---|---|
esp8266_udp | ESP8266 | headless |
esp8266oled_udp | ESP8266 | OLED |
esp32_udp | ESP32 | OLED auto-detected |
esp32c3_udp | ESP32-C3 | OLED auto-detected |
esp32s3_udp | ESP32-S3 | OLED auto-detected |
OSC Message Schema
/espg/<chipid>/click
Emitted on every accepted click in mode 2.
,ii
counter : int32 monotonic click number on the producer
ts_ms : int32 producer millis() at emit
/espg/<chipid>/rad
Radiation telemetry. Periodic heartbeat (~30 s).
,ffsi
cpm : float 1-minute average
usv : float µSv/h
state : string "warming" | "healthy" | "warning" | "alert"
total_clicks : int32 producer's lifetime click count
/espg/<chipid>/hv
HV telemetry (HV-equipped builds only, same cadence as /rad).
,ffii
reading_v : float measured HV (smoothed)
target_v : float HV setpoint
duty : int32 PWM duty (0-1023)
trim : int32 autotrim adjustment in duty units (signed)
/espg/<chipid>/sys
System telemetry. Every other /rad (~60 s).
,iiii
uptime_s : int32 producer seconds since boot
rssi : int32 WiFi signal strength
lps : int32 main loops per second
tick_max_us : int32 worst main-loop iteration in last window
/espg/<chipid>/env
Environment telemetry. Only emitted when a supported environment sensor is wired in. Same cadence as /sys (~60 s).
,fff
temp_c : float Temperature in °C, NaN when absent
humidity : float Relative humidity %, NaN on BMP280-only builds
pressure : float Atmospheric pressure in hPa, NaN on AHT-only builds
Fields that the local sensor doesn’t provide are encoded as IEEE 754 NaN, not omitted - the tag string is always ,fff. Receivers should check isnan() on each value.
Receive Examples
python-osc
from pythonosc import dispatcher, osc_server
def on_click(addr, counter, ts_ms):
print(f"{addr} counter={counter} ts_ms={ts_ms}")
def on_rad(addr, cpm, usv, state, total_clicks):
print(f"{addr} {cpm:.1f} CPM ({usv:.3f} uSv/h) {state}")
d = dispatcher.Dispatcher()
d.map("/espg/*/click", on_click)
d.map("/espg/*/rad", on_rad)
server = osc_server.ThreadingOSCUDPServer(
("239.255.86.86", 57340), d, multicast=True)
server.serve_forever()
Pure Data / TouchDesigner / Max
Subscribe to multicast group 239.255.86.86 on port 57340. Filter on path /espg/*/click for live events, /espg/*/rad for radiation telemetry, /espg/*/hv for HV readings, or /espg/*/sys for system health.
Discovery (mDNS)
When mode > 0 the producer announces an _osc._udp service with the configured port. TXT records: id (6-hex chipid), fname (friendly name), group (multicast IP). Discovery is optional; pre-configured receivers just need the group and port.
Reliability and tuning
- Loss handling: every
/clickcarries a running counter so the receiver detects loss as a sequence gap and gap-fills automatically. Cumulative loss % is on the OLED and/status. - Send throttle: high-CPS producers cap
/clickemit rate at 20 pps. Counter accuracy is preserved because each packet carries the producer’s running total. - RX sleep mode (
udprx_rxmode):1(modem sleep, default) suits most networks.0saves more power.2keeps the radio always on and runs warmer; try unicast first if packets go missing. The original ESP32 (not C3/S3) defaults to2: on modem sleep it misses most multicast.
Build Flags
Custom builds can change the defaults (group, port, intervals, throttle). See Build Options.