Custom panels from your own device

Every built-in Firefly driver covers the sensors the factory ships with. But Firefly is a development board, so you may already have your own hardware: a custom ESP32 firmware running your own sensor driver, a Raspberry Pi reading a serial device, a Python service polling a USB / GPIO bus, a Node.js box talking to a serial gadget — anything that can run on a LAN and speak UDP or HTTP.

Because Firefly already has a board-to-board panel transport (the same one it uses to mirror sensors from other Firefly boards), you can attach any device as a first-class Firefly panel — dashboard value, automation source/target, OLED display, MQTT publish — without touching firmware. This page documents that contract.

The transport: UDP board-to-board

The publisher (your device) broadcasts a single UDP packet to the Firefly board's data port (default 8422, set via udp_data_port):

FF <MAC> <panel_name> {"": 23.5, "temperature": 23.5, "humidity": 60.0}

Where:

  • FF — packet type marker.
  • <MAC> — the publishing device's MAC address (uppercase hex, colons). Firefly ignores its own MAC to avoid self-mirroring.
  • <panel_name> — the panel name this value belongs to.
  • {...} — JSON object of numeric values. Key "" is the default/primary value; named keys are sub-values (e.g. temperature, humidity).

Set up the receiver

  1. On the Firefly board, create a new panel: type input, hardware udp_remote.
  2. Set the MAC field to the publishing device's MAC address and the remote panel field to the panel name you used in the packet.
  3. Save. The panel appears in the dashboard like any other input — calibratable, automatable, displayable on the OLED, publishable over MQTT.

Example: publish temperature + humidity from a Raspberry Pi

import socket, json

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
payload = b"FF AA:BB:CC:DD:EE:FF sensor1 " + json.dumps(
    {"": 23.5, "temperature": 23.5, "humidity": 60.0}
).encode()
sock.sendto(payload, ("192.168.2.100", 8422))  # firefly's data port

Example: publish from an ESP32 firmware

// In your ESP32 firmware, on your chosen cadence:
String json = "{\"\":"; json += String(value, 3); json += ",\"temperature\":" + String(value, 3); json += ",\"humidity\":" + String(humidity, 3) + "}";
udp.beginPacket("255.255.255.255", dataPort);
udp.print("FF " + WiFi.macAddress() + " sensor1 " + json);
udp.endPacket();

Operational notes

  • Firefly listens on udp_port (discovery, default 8421) and udp_data_port (data, default 8422).
  • A receiver only gets packets whose MAC and panel match what it configured — no self-mirroring, no cross-talk.
  • Data packets are lossy (UDP). For critical control loops prefer a polled HTTP source; for ambient sensor mirrors UDP broadcast is fine.
  • For low-friction custom sensors, HTTP pull is now a first-class option (see the firmware page). Both plugs into the same panel model.

That is the complete custom-panel story on the current build: any network device that speaks UDP in that shape becomes a Firefly panel with zero firmware changes on the Firefly side.