Hujjatlar
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", &t, &h, &p); // gauge + metric + chart
// Tune the template: a trend chart per quantity, or bigger readouts.
dash.sensor("ina219", &v, &i, &w).chart();
dash.sensor("ld2410", &pr, &d, &m).size(RSIZE_L); 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 / UZ / AR ship in the library. The device serves all four at runtime; users switch live in the appbar Settings (the choice sticks per browser). Your own widget titles follow via dash.translate():
dash.lang("ru"); // default UI language: en · ru · uz · ar (ar → RTL)
// users switch live in the appbar Settings; the choice sticks per browser.
// translate the strings YOU write — widget titles, page names, options:
dash.translate([](const char *s, const char *l) {
if (!strcmp(l, "ru") && !strcmp(s, "Temperature")) return "Температура";
return s; // fall back to the original for anything unmapped
}); Arabic gets full RTL via logical CSS properties. On a mono LCD panel the stock font is Latin-only, so the screen shows en / uz natively and falls back to English for ru / ar — while the web dashboard serves all four.
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) A real exchange — read a value, decide, act, all through the same tools: