src/platforms/shared/ui/json/readme.md
The JsonUI system provides a platform-agnostic way to create interactive UI components that communicate via JSON. This guide explains how to integrate JsonUI into your platform.
JsonUI components emit JSON events when they are added, destroyed, or updated. A JsonUIManager manages internal state and handles bidirectional communication between the sketch and the platform.
The JsonUI system consists of several key components:
The JsonUI system makes extensive use of FastLED's Internal Template Library:
fl::WeakPtr<T>: Weak references allow UI elements to be removed on the client side and removed by the UIManager on the next frame.fl::function<T>: Function objects for callbacksfl::vector<T>: Dynamic arrays for component storagefl::string: String handlingfl::mutex / fl::unique_lock: Thread-safe operationsfl::EngineEvents::Listener: Lifecycle event handlingfl::Singleton<T>: Singleton pattern for managersfl::FixedSet<T, N>: Fixed-size sets for component trackingYour platform needs a UI manager that inherits from JsonUiManager:
#include "platforms/shared/ui/json/ui_manager.h"
class MyPlatformUiManager : public fl::JsonUiManager {
public:
MyPlatformUiManager() : JsonUiManager(myUpdateJsFunction) {}
static MyPlatformUiManager& instance() {
return fl::Singleton<MyPlatformUiManager>::instance();
}
private:
static void myUpdateJsFunction(const char* jsonStr) {
// Platform-specific code to send JSON to your UI system
// This is called when components are added/updated
}
};
Define these global functions that UI components will call:
void addJsonUiComponent(fl::WeakPtr<JsonUiInternal> component) {
MyPlatformUiManager::instance().addComponent(component);
}
void removeJsonUiComponent(fl::WeakPtr<JsonUiInternal> component) {
MyPlatformUiManager::instance().removeComponent(component);
}
These functions have __attribute__((weak)) declarations, so your implementation will override the default no-op versions.
When your platform UI sends updates back to the sketch:
void handleUiUpdate(const std::string& jsonStr) {
MyPlatformUiManager::instance().updateUiComponents(jsonStr.c_str());
}
The JSON format for updates should be:
{
"id_123": {"value": 42},
"id_456": {"pressed": true}
}
Where id_XXX corresponds to component IDs returned by JsonUiInternal::id().
The JsonUiManager automatically integrates with FastLED's EngineEvents system:
When components are added, the JsonUiManager sends a JSON array:
[
{
"name": "brightness",
"type": "slider",
"id": 123,
"value": 128,
"min": 0,
"max": 255,
"group": "lighting"
},
{
"name": "reset",
"type": "button",
"id": 456,
"pressed": false,
"group": "controls"
}
]
Platform UI sends updates back using component IDs:
{
"id_123": {"value": 200},
"id_456": {"pressed": true}
}
The WASM platform provides a complete reference implementation:
// Required interface implementation
void addJsonUiComponent(fl::WeakPtr<JsonUiInternal> component) {
// YOUR UI MANAGER GETS CALLED HERE.
}
void removeJsonUiComponent(fl::WeakPtr<JsonUiInternal> component) {
// YOUR UI MANAGER GETS CALLED HERE.
}
The JsonUiManager uses fl::mutex for thread-safe operations. Key considerations:
The system provides these built-in components:
Each component follows the same pattern: