RisalDash RisalDash

Docs

Documentation

Quick start

Arduino IDE: Library Manager → RisalDash. PlatformIO:

; platformio.ini
lib_deps =
    RisalDash
    ESP Async WebServer
    AsyncTCP            ; ESP32

A minimal sketch — five widgets, an access point, live over WebSocket:

#include <RisalUI.h>

RisalUI dash("Greenhouse");
float temp, volts; bool pump = false;

void setup() {
  dash.gauge ("Voltage", &volts, 0, 14, "V");
  dash.chart ("Temp", &temp, "°C").history(30);
  dash.toggle("Pump", &pump, [](bool on){ digitalWrite(PUMP_PIN, on); });
  dash.beginAP("Greenhouse", "12345678");   // access point
}

void loop() {
  temp = readTemp(); volts = readVolts();
  dash.update();   // pushes changes over WebSocket
}

Open http://192.168.4.1/ after joining the AP. No front-end code, no HTML files.

Core concepts

Zero-Waste UI

The linker (--gc-sections) strips the code of widgets you never instantiate. CSS/JS for a widget reaches flash only if its class is used. Empty core is < 8 KB flash / < 2 KB RAM; a new widget costs ~200–400 bytes.

Offline-first

Everything is served from the device — system fonts, zero external requests. The dashboard renders with no internet, which is the normal state on first boot.

WebSocket protocol

The device pushes only changed values as compact JSON ({ "Temp": 24.3 }); the client sends commands in the same shape. dash.update() diffs and pushes.

Widgets & sensors

30+ chainable widgets across display, control and layout — see the full catalog. A widget binds to a variable by pointer and configures via chaining:

dash.metric("CPU", &cpu, "%").zone(70, 90);

Sensors are a composition of quantities — presets expand to the right widgets automatically:

// One line drops the right widgets, units, ranges and icon:
dash.sensor("bme280");   // temperature + humidity + pressure
dash.sensor("ina219");   // voltage + current + power

First boot & Wi-Fi

On first power-up the client has no internet. beginAP() raises a SoftAP with a captive portal (catch-all DNS + OS probes) that auto-opens the dashboard. A provisioning page scans networks, takes credentials, stores them in NVS, then switches to station mode — falling back to AP if the connection fails.

Languages & RTL

EN / RU / AR ship in the library. Languages are picked at compile time, so unused ones cost nothing:

; choose languages at compile time (only these reach flash)
build_flags = -D RISAL_LANG_RU -D RISAL_LANG_AR

Arabic gets full RTL via logical CSS properties; translations live in separate per-language files.

AI control (MCP)

Each widget automatically becomes an MCP tool, so Claude/Cursor can read sensors and flip relays by voice — same actions as the browser buttons, just driven by AI.

dash.enableMCP("risal_pat_xxx");
// metric/gauge -> get_*  (read) ; toggle/slider -> set_*  (write)