Sending and receiving
Every widget sits on a virtual pin, V0 to V124. Send to a pin to update the widget there; register a callback on a pin to react when a user uses the control there. Ask the organization which widget is on which pin.
The functions are the same for WiFi (ThingsLinker) and 4G (ThingsLinkerGSM).
Send values (device → dashboard)
| Function | Widget | Value |
|---|---|---|
iot.gauge("V1", value) | Gauge | number |
iot.chart("V1", value) | Chart | number, recorded for history |
iot.display("V1", value) | Value Display | number, text or on/off |
iot.label("V1", value) | Label | text, number or on/off |
iot.terminal("V1", text) | Terminal | a line of text |
iot.led("V1", on) | LED | true / false |
iot.button("V1", on) | Button | true / false, for example after a physical button press |
iot.slider("V1", value) | Slider | number, to move the slider |
iot.map("V1", lat, lng) | Map | latitude and longitude |
iot.status("V1", value) | Status | number or text, shown as a named state |
iot.progress("V1", value) | Progress Bar | number |
iot.selector("V1", value) | Selector | the option that is active now |
iot.numberInput("V1", value) | Number Input | the current number |
iot.publish("Type", "V1", value) | any widget, by its type name in the portal | number, text or on/off |
iot.gauge("V3", 52.6);
iot.label("V4", "Door open");
iot.led("V5", relayOn);
iot.map("V12", 23.0225, 72.5714);
Send on a timer with millis(), not on every loop. Every few seconds is plenty for most readings; on 4G, every message uses mobile data.
Receive commands (dashboard → device)
Register callbacks in setup(), before iot.begin():
| Function | Widget | Callback receives |
|---|---|---|
iot.onSwitch("V1", cb) | Switch | bool on |
iot.onButton("V1", cb) | Button | bool pressed |
iot.onLED("V1", cb) | LED | bool on |
iot.onSlider("V1", cb) | Slider | float value |
iot.onValue("V1", cb) | Value Display | float value |
iot.onTerminal("V1", cb) | Terminal | const char* text |
iot.onSelector("V1", cb) | Selector with number values | float option |
iot.onSelectorText("V1", cb) | Selector with text values | const char* option |
iot.onNumberInput("V1", cb) | Number Input | float value |
iot.onTextInput("V1", cb) | Text Input | const char* text |
iot.onKeypad("V1", cb) | Keypad with number values | float key |
iot.onKeypadText("V1", cb) | Keypad with text values | const char* key |
iot.onRGB("V1", cb) | RGB | uint8_t r, g, b, bool on, uint16_t count, const char* pattern |
iot.onTimer("V1", cb) | Timer | float value |
iot.onJoystick("V1", cb) | Joystick | float x, float y |
iot.onWidget("Type", "V1", cb) | any widget type that sends a number | float value |
iot.onWidgetText("Type", "V1", cb) | any widget type that sends text | const char* text |
void onBrightness(float value) {
analogWrite(LED_PIN, map((int)value, 0, 100, 0, 255));
}
void onMode(const char* option) {
Serial.printf("Mode: %s\n", option);
}
void setup() {
iot.onSlider("V7", onBrightness);
iot.onSelectorText("V9", onMode);
iot.begin();
}
Notes:
- A
const char*passed to a callback is only valid during the callback. Copy it if you need it later. - Up to 20 callbacks of each kind (number, on/off, text) can be registered.
- Keep callbacks short: set a variable or switch an output, and do longer work in
loop(). - RGB:
patternis the name picked in the widget's Effect list, such asDefault,BlinkingorRainbow Cycle; your firmware draws the effect. The07_All_Widgets_Testand08_ESP32S3_Full_Dashboardexamples includeRGBEffects.h, which draws every effect in the list on a NeoPixel strip and gamma-corrects the colour so the LEDs match the colour on screen. Copy it into your sketch folder to use it.
Data types
Each widget has a Data Type, set by the organization. The library sends the JSON type that matches the C++ value you pass: 42 is an Integer, 23.5 a Float, true a Boolean and "Running" a String. Nothing is guessed from the content, so "123" stays text.
iot.display("V3", 42); // {"v":42}
iot.display("V3", 23.5f); // {"v":23.5}
iot.display("V3", true); // {"v":1}
iot.display("V3", "Running"); // {"v":"Running"}
Send the type the widget expects. A chart only plots numbers, and alerts only compare numbers. Text values can be up to about 300 characters; longer values are not sent and an error is logged. The full table is in Widget types.
Settings come back after a reconnect
The app and the User Portal ask ThingsLinker to keep the last command sent to most controls. When your device connects, it receives those commands again and can return to the user's chosen settings:
| Widget | On connect |
|---|---|
| Switch, Button, LED, Slider, Selector, Number Input, RGB, Timer, Joystick | The last command arrives again. |
| Keypad, Text Input | Nothing arrives: each press or message is sent once. Use these for one-off actions such as "restart". |
| Terminal | The last line typed arrives again, so do not trigger one-off actions directly from onTerminal(). |
So a device can restore its outputs from the dashboard after a restart. To keep settings even while it is offline, save them in flash as well; see Saving settings.
Your own messages are ignored
A device also listens on the pins it sends to. The library recognises its own messages coming back from the broker and ignores them, so a callback only runs for commands from the dashboard. You can, for example, call iot.led("V5", state) and handle iot.onLED("V5", cb) in the same sketch.