Fluxgrid cheat sheet

The short version. Search it, copy a line, get back to the board — the full usage guide has the rest.

Start here4

A complete device is about ten lines. Everything below is the rest of the ten.

The whole sketch

Docs ↗

Flash this, and the board appears online on your dashboard.

#define WIFI_SSID  "wifi"
#define WIFI_PASS  "pass"
#define FG_TOKEN   "DEVICE_TOKEN"   // one string per device, from the dashboard
#include <Fluxgrid.h>

void setup() {
  Fluxgrid.begin();                 // server, port and TLS are built in
}

void loop() {
  Fluxgrid.run();                                          // every loop
  Fluxgrid.write("temp", analogRead(4) * (50.0 / 4095.0)); // publish a reading
  digitalWrite(2, Fluxgrid.read("relay").asBool());        // read a Switch back
}

The three `#define`s go ABOVE the include

Docs ↗

Arduino compiles your sketch and the library separately, so a value defined after #include <Fluxgrid.h> is invisible to it — begin() then connects with nothing. This is the single most common first-flash failure.

#define FG_TOKEN "…"     // ✅ above
#include <Fluxgrid.h>
#define FG_TOKEN "…"     // ❌ below — ignored

One token per device

Docs ↗

Add a device → Pair device on the dashboard gives you one string. It already bundles the routing token and the device's MQTT user/password, and the library splits it — you never paste three values.

A handle is the widget's name

Docs ↗

"temp" in the code is the datastream handle the widget shows on the canvas. Drop a widget and it creates one for you; use that exact string in the sketch. If a tile stays blank, these two disagree.

Keep it in one place so the two can't drift:

#define TEMP_HANDLE "temp"        // must match the widget's handle
Fluxgrid.write(TEMP_HANDLE, 23.4);

Core API9

The calls almost every sketch uses. Everything else is in the full reference.

Fluxgrid.begin()

Docs ↗

Connect WiFi + cloud using WIFI_SSID / WIFI_PASS / FG_TOKEN.

Fluxgrid.run()

Docs ↗

Keep the link alive + deliver writes.

Fluxgrid.write(handle, value)

Docs ↗

Push telemetry to a datastream. Safe to call every loop() — the library paces it for you.

Fluxgrid.read(handle)

Docs ↗

Latest value for a datastream, as a FluxValue — convert with .asInt() / .asFloat() / .asBool() / .asString().

Fluxgrid.has(handle)

Docs ↗

true once any value has been received for the handle.

Fluxgrid.onReceive(handle, fn)

Docs ↗

Fire a callback once per incoming write. The lambda gets a FluxValue: onReceive("relay", [](FluxValue v){ … v.asBool() … }).

Fluxgrid.onConnected(fn)

Docs ↗

Runs each time the cloud connection is (re)established.

Fluxgrid.connected()

Docs ↗

true when linked to the cloud.

Fluxgrid.region(code)

Docs ↗

Point the device at a region's cloud — "com" (default) or "cn". Call before begin().

Everyday patterns8

Publish a value

Docs ↗

Call write() straight from loop() — the library paces it: an unchanged value is not resent (except a 10 s heartbeat), a change goes out at once but never faster than one per 100 ms per handle. You do not need a millis() timer, and you do not need to debounce.

void loop() {
  Fluxgrid.run();
  Fluxgrid.write("button", digitalRead(0) == LOW);   // fine, every loop
}

React to a control widget

Docs ↗

onReceive() fires once per incoming write, with the new value — the board never polls for it. Register it before begin(), so the state the cloud replays on connect finds it.

void setup() {
  Serial.begin(115200);
  Fluxgrid.onReceive("relay", [](FluxValue v) {
    if (v.asBool()) Serial.println("Switch: ON");
    else            Serial.println("Switch: OFF");
  });
  Fluxgrid.begin();
}

void loop() { Fluxgrid.run(); }   // run() is what delivers it

Give the callback a name

Docs ↗

Same call, a plain function instead of a lambda — easier to read once the handler is more than a line or two, and one function can serve several handles. Pass the name, with no ().

void onSwitch(FluxValue v) {           // takes a FluxValue, returns void
  digitalWrite(2, v.asBool() ? HIGH : LOW);
}

void setup() {
  Fluxgrid.onReceive("relay", onSwitch);
  Fluxgrid.begin();
}

Poll with read() instead of a callback

Docs ↗

Right when you want the current state every loop — digitalWrite(2, Fluxgrid.read("relay").asBool()) needs no memory. Wrong for "it just changed": loop() runs thousands of times a second, so you end up writing the edge detection onReceive() already did for you.

bool last = false;
void loop() {
  Fluxgrid.run();
  bool now = Fluxgrid.read("relay").asBool();
  if (now != last) {          // without this: thousands of lines a second
    last = now;
    Serial.println(now ? "Switch: ON" : "Switch: OFF");
  }
}

Convert an incoming value

Docs ↗

read() and the onReceive() lambda both hand you a FluxValue. It converts on demand, and is empty until the first value arrives.

FluxValue v = Fluxgrid.read("speed");
if (!v.isEmpty()) analogWrite(5, v.asInt());   // .asFloat() .asBool() .asString()

Do something on a timer

delay() stalls run(), so the link goes quiet and the board can read offline. Use a millis() gate for anything slow (a DHT read, a WiFi scan, an HTTP call).

unsigned long last = 0;
void loop() {
  Fluxgrid.run();
  if (millis() - last < 2000) return;
  last = millis();
  Fluxgrid.write("temp", readSensor());
}

Widget quick reference74

What the firmware sends or receives for each widget, and the handle a freshly dropped one gets. Users rename handles freely — always use the handle the dashboard actually shows.

Gauge

The device publishes. Default handle gauge (number).

Fluxgrid.write("gauge", value);

Value

The device publishes. Default handle value (number).

Fluxgrid.write("value", value);

Chart

The device publishes. Default handle chart (number).

Fluxgrid.write("chart", value);

LED

The device publishes. Default handle led (boolean).

Fluxgrid.write("led", state);

Radial

The device publishes. Default handle radial (number).

Fluxgrid.write("radial", value);

Stat

The device publishes. Default handle stat (number).

Fluxgrid.write("stat", value);

Bar

The device publishes. Default handle bar (number).

Fluxgrid.write("bar", value);

Level

The device publishes. Default handle level (number).

Fluxgrid.write("level", value);

Battery

The device publishes. Default handle battery (number).

Fluxgrid.write("battery", value);

Table

The device publishes. Default handle table (number).

Fluxgrid.write("table", value);

7-Segment

The device publishes. Default handle segment (number).

Fluxgrid.write("segment", value);

Sensor Group

Binds 3 datastreams — sensor1, sensor2, status. Publishing only the first leaves the rest dark.

Fluxgrid.write("sensor1", state);   // Sensor 1
Fluxgrid.write("sensor2", state);   // Sensor 2
Fluxgrid.write("status", "OK");   // Status

Button

The dashboard writes, the device reacts. Default handle button (boolean).

Fluxgrid.onReceive("button", [](FluxValue v) {
  // v.asBool()
});

Switch

The dashboard writes, the device reacts. Default handle switch (boolean).

Fluxgrid.onReceive("switch", [](FluxValue v) {
  // v.asBool()
});

Slider

The dashboard writes, the device reacts. Default handle slider (number).

Fluxgrid.onReceive("slider", [](FluxValue v) {
  // v.asFloat()
});

Switch Group

Binds 3 datastreams — light1, light2, light3. Publishing only the first leaves the rest dark.

Fluxgrid.write("light1", state);   // Light 1
Fluxgrid.write("light2", state);   // Light 2
Fluxgrid.write("light3", state);   // Light 3

Knob

The dashboard writes, the device reacts. Default handle knob (number).

Fluxgrid.onReceive("knob", [](FluxValue v) {
  // v.asFloat()
});

Stepper

The dashboard writes, the device reacts. Default handle stepper (number).

Fluxgrid.onReceive("stepper", [](FluxValue v) {
  // v.asFloat()
});

Segmented

The dashboard writes, the device reacts. Default handle segmented (boolean).

Fluxgrid.onReceive("segmented", [](FluxValue v) {
  // v.asBool()
});

Joystick

Binds 2 datastreams — x, y. Publishing only the first leaves the rest dark.

Fluxgrid.write("x", value);   // Joystick X
Fluxgrid.write("y", value);   // Joystick Y

Color

The dashboard writes, the device reacts. Default handle color (number).

Fluxgrid.onReceive("color", [](FluxValue v) {
  // v.asFloat()
});

RGB

Binds 3 datastreams — red, green, blue. Publishing only the first leaves the rest dark.

Fluxgrid.write("red", value);   // R
Fluxgrid.write("green", value);   // G
Fluxgrid.write("blue", value);   // B

Icon Tile

The dashboard writes, the device reacts. Default handle tile (boolean).

Fluxgrid.onReceive("tile", [](FluxValue v) {
  // v.asBool()
});

Time Input

The dashboard writes, the device reacts. Default handle time (number).

Fluxgrid.onReceive("time", [](FluxValue v) {
  // v.asFloat()
});

Keypad

The dashboard writes, the device reacts. Default handle setpoint (number).

Fluxgrid.onReceive("setpoint", [](FluxValue v) {
  // v.asFloat()
});

Binds 2 datastreams — note, seq. Publishing only the first leaves the rest dark.

Fluxgrid.write("note", value);   // Piano Note
Fluxgrid.write("seq", "OK");   // Piano Seq

Jukebox

Docs ↗

Binds 2 datastreams — song, play. Publishing only the first leaves the rest dark.

Fluxgrid.write("song", "OK");   // Jukebox Song
Fluxgrid.write("play", state);   // Jukebox Play

Remote Control

The dashboard writes, the device reacts. Default handle remote (text).

Fluxgrid.onReceive("remote", [](FluxValue v) {
  // v.asString()
});

Health

Binds 3 datastreams — heartrate, spo2, pi. Publishing only the first leaves the rest dark.

Fluxgrid.write("heartrate", value);   // Heart Rate
Fluxgrid.write("spo2", value);   // Blood Oxygen
Fluxgrid.write("pi", value);   // Perfusion Index

Terminal

The device publishes. Default handle log (text).

Fluxgrid.write("log", "OK");

JSON

The device publishes. Default handle data (json). The payload is a fixed JSON shape — the editor's Sample Code window has it.

Fluxgrid.write("data", payload);

LCD 1602

The device publishes. Default handle lcd (text).

Fluxgrid.write("lcd", "OK");

Camera

The device publishes. Default handle camera (number).

Fluxgrid.write("camera", value);

The device publishes. Default handle map (json). The payload is a fixed JSON shape — the editor's Sample Code window has it.

Fluxgrid.write("map", payload);

Fleet Map

The device publishes. Default handle fleetmap (json). The payload is a fixed JSON shape — the editor's Sample Code window has it.

Fluxgrid.write("fleetmap", payload);

Status Grid

The device publishes. Default handle statusgrid (number).

Fluxgrid.write("statusgrid", value);

Alarm Table

The device publishes. Default handle alarmtable (number).

Fluxgrid.write("alarmtable", value);

Breathalyzer

The device publishes. Default handle breathalyzer (number).

Fluxgrid.write("breathalyzer", value);

Reverse Sensor

The device publishes. Default handle parking (number).

Fluxgrid.write("parking", value);

Radar

Binds 2 datastreams — radar, scan. Publishing only the first leaves the rest dark.

Fluxgrid.write("radar", payload);   // Radar Data
Fluxgrid.write("scan", state);   // Radar Control

Compass

Binds 3 datastreams — heading, field, cal. Publishing only the first leaves the rest dark.

Fluxgrid.write("heading", value);   // Heading
Fluxgrid.write("field", value);   // Field Strength
Fluxgrid.write("cal", value);   // Calibration

AHRS

Binds 1 datastreams — attitude. Publishing only the first leaves the rest dark.

Fluxgrid.write("attitude", payload);   // Attitude Data

Bike Computer

The device publishes. Default handle bike (json). The payload is a fixed JSON shape — the editor's Sample Code window has it.

Fluxgrid.write("bike", payload);

Speedometer

Binds 6 datastreams — speed, dist, sat, hdop, hdg, fix. Publishing only the first leaves the rest dark.

Fluxgrid.write("speed", value);   // Speed
Fluxgrid.write("dist", value);   // Distance
Fluxgrid.write("sat", value);   // Satellites
Fluxgrid.write("hdop", value);   // HDOP
Fluxgrid.write("hdg", value);   // Track
Fluxgrid.write("fix", value);   // Fix Type

Device Info

Docs ↗

Binds a device, not a datastream. It fills in from the board's retained meta message — nothing to publish.

File Explorer

Docs ↗

Binds a device. You mount the filesystem; the library exposes it — see File explorer.

LittleFS.begin(true);
Fluxgrid.addVolume("flash", LittleFS, FG_FLASH);
Fluxgrid.enableFiles();   // before begin()

Memory

Docs ↗

Binds 3 datastreams — free_heap, min_free_heap, max_alloc. Publishing only the first leaves the rest dark.

Fluxgrid.write("free_heap", value);   // Free Heap
Fluxgrid.write("min_free_heap", value);   // Min Free Heap
Fluxgrid.write("max_alloc", value);   // Max Alloc Block

Memory Chart

Docs ↗

Binds a device. Call reportMemory() once and the library publishes heap (and PSRAM) on a timer.

Fluxgrid.reportMemory(5000);   // in setup(); 0 turns it off

Power Monitor

Docs ↗

Binds 2 datastreams — voltage, current. Publishing only the first leaves the rest dark.

Fluxgrid.write("voltage", value);   // Bus Voltage
Fluxgrid.write("current", value);   // Shunt Current

Power Monitor 3CH

Docs ↗

Binds 6 datastreams — ch1_v, ch1_a, ch2_v, ch2_a, ch3_v, ch3_a. Publishing only the first leaves the rest dark.

Fluxgrid.write("ch1_v", value);   // CH1 Voltage
Fluxgrid.write("ch1_a", value);   // CH1 Current
Fluxgrid.write("ch2_v", value);   // CH2 Voltage
Fluxgrid.write("ch2_a", value);   // CH2 Current
Fluxgrid.write("ch3_v", value);   // CH3 Voltage
Fluxgrid.write("ch3_a", value);   // CH3 Current

Music Player

Binds 9 datastreams — music, play, prev, next, volume, seek, shuffle, repeat, mute. Publishing only the first leaves the rest dark.

Fluxgrid.write("music", payload);   // Music State
Fluxgrid.write("play", state);   // Music Play
Fluxgrid.write("prev", value);   // Music Prev
Fluxgrid.write("next", value);   // Music Next
Fluxgrid.write("volume", value);   // Music Volume
Fluxgrid.write("seek", value);   // Music Seek

WS2812 Panel

The dashboard writes, the device reacts. Default handle matrix (json). The payload is a fixed JSON shape — the editor's Sample Code window has it.

Fluxgrid.onReceive("matrix", [](FluxValue v) {
  // v.asString()
});

WiFi RSSI

Docs ↗

The device publishes. Default handle rssi (number).

Fluxgrid.write("rssi", value);

WiFi Scan

Docs ↗

The device publishes. Default handle wifi (json). The payload is a fixed JSON shape — the editor's Sample Code window has it.

Fluxgrid.write("wifi", payload);

Network Monitor

The device publishes. Default handle netscan (json). The payload is a fixed JSON shape — the editor's Sample Code window has it.

Fluxgrid.write("netscan", payload);

Text Input

The dashboard writes, the device reacts. Default handle text (text).

Fluxgrid.onReceive("text", [](FluxValue v) {
  // v.asString()
});

Password

The dashboard writes, the device reacts. Default handle secret (text).

Fluxgrid.onReceive("secret", [](FluxValue v) {
  // v.asString()
});

Range Slider

Binds 2 datastreams — min, max. Publishing only the first leaves the rest dark.

Fluxgrid.write("min", value);   // Range Low
Fluxgrid.write("max", value);   // Range High

Dropdown

The dashboard writes, the device reacts. Default handle select (number).

Fluxgrid.onReceive("select", [](FluxValue v) {
  // v.asFloat()
});

Week Selector

The dashboard writes, the device reacts. Default handle days (number).

Fluxgrid.onReceive("days", [](FluxValue v) {
  // v.asFloat()
});

Time Sync

The dashboard writes, the device reacts. Default handle clock (number).

Fluxgrid.onReceive("clock", [](FluxValue v) {
  // v.asFloat()
});

File Upload

The dashboard writes, the device reacts. Default handle file (text).

Fluxgrid.onReceive("file", [](FluxValue v) {
  // v.asString()
});

Time Difference

The device publishes. Default handle since (number).

Fluxgrid.write("since", value);

Pie Chart

The device publishes. Default handle pie (json). The payload is a fixed JSON shape — the editor's Sample Code window has it.

Fluxgrid.write("pie", payload);

Doughnut

The device publishes. Default handle donut (json). The payload is a fixed JSON shape — the editor's Sample Code window has it.

Fluxgrid.write("donut", payload);

Bar Chart

The device publishes. Default handle bars (json). The payload is a fixed JSON shape — the editor's Sample Code window has it.

Fluxgrid.write("bars", payload);

Feedback

The device publishes. Default handle status (text).

Fluxgrid.write("status", "OK");

Temperature

The device publishes. Default handle temp (number).

Fluxgrid.write("temp", value);

Humidity

The device publishes. Default handle humidity (number).

Fluxgrid.write("humidity", value);

Air Quality

The device publishes. Default handle air (number).

Fluxgrid.write("air", value);

Energy

The device publishes. Default handle energy (number).

Fluxgrid.write("energy", value);

Card

The device publishes. Default handle card (number).

Fluxgrid.write("card", value);

ESP Partition

A browser-side tool: it computes a partitions.csv for your board. No device, no datastream, no firmware.

OTA Update

Binds a device. Shows whether the board is ready for a wireless update — arm it with enableOTA() before begin().

Fluxgrid.enableOTA("ota-password");

When it doesn't work6

The device never comes online

Docs ↗

In order: the three #defines are above the #include; the token is this device's (each device has its own); the WiFi is 2.4 GHz; the region matches the dashboard you are signed in to. Turn on Fluxgrid.debug(1) and watch the USB serial monitor — it says which step failed.

A tile stays blank

Docs ↗

Almost always a handle mismatch: the string in write() is not the handle on the widget. Open More → Datastreams and compare. For a widget that binds several datastreams, every slot has its own handle — publishing only the first leaves the rest dark.

A control widget does nothing

Docs ↗

In order: the handle in onReceive() is the widget's; it was registered before begin(); loop() still calls run() every pass; and nothing in the callback blocks — it runs inside run(), so a delay() or a wait loop there stalls the link. Set a flag and do the slow work in loop(). A second onReceive() on the same handle replaces the first, it does not chain.

You are on the China cloud

Docs ↗

A device belongs to exactly one region; its credentials do not exist on the other. One line, before begin():

Fluxgrid.region("cn");

A big payload never arrives

Docs ↗

MQTT messages are capped by a buffer that defaults small. Raise it above the include — a WiFi scan or a long JSON object silently exceeds the default.

#define FLUXGRID_MQTT_BUFFER 2048
#include <Fluxgrid.h>

Re-flashing over WiFi

Docs ↗

Call before begin(), then pick the board's network port in the IDE. The board needs an OTA-capable partition scheme, or the update has nowhere to land.

Fluxgrid.enableOTA("ota-password");