Skip to main content
Include the umbrella header to access the full API:
Everything outbound takes a target_id — where the message is routed. Inside a command handler that is the from argument, so a reply, a widget update and a dialog all go back to whoever asked. Widget calls also take a widget_id. Most functions return esp_err_t (ESP_OK on success). The *_with_response variants return a cJSON * you own and must cJSON_Delete().

Lifecycle

Register handlers before hyperwisor_start(). A command arriving on the first connection is otherwise answered with “Unknown command”.

Device state

The struct carries device_id, ssid, user_id, product_id, version, and the flags wifi_connected, ip_ready, ws_connected, ap_mode_active, ntp_initialized, plus uptime_seconds. Take the lock if you read it from a task other than your handler.
Gate anything that needs the network on ip_ready, not wifi_connected. The latter goes true at association, roughly 850 ms before DHCP hands over an address — DNS cannot resolve in that window.

Connection state

Receiving commands

register_user_msg_cb sees every inbound message — useful for debugging or a protocol of your own. cmd_process feeds a message in by hand. The handler gets the whole envelope, so use the helpers to dig into it:
The dashboard sends parameters as strings — "true", not true. Write cJSON_IsBool() and nothing will happen.

Responding and emitting

emit takes ownership of params — do not delete it yourself.

Updating widgets

Push a value to a dashboard widget by its widget ID (needs HYPERWISOR_ENABLE_WIDGET).
Where do I get the widgetId? Select the widget in the Dashboard Designer and open General → Basic. The Widget ID field holds the value — use the copy button and paste it into your updateWidget / widget.* call. See Binding Data for the full model.
Widget ID in the General tab

Copy a widget's ID from General → Basic — this is the value your update calls reference.

Specialised widgets

hyperwisor_update_widget_position moves, resizes and rotates a widget from the device — r is rotation in degrees.

Telemetry and status

DEVICE_STATUS is answered by the library automatically — you do not need to register a handler for it. send_device_status is there for reporting unprompted.

Dialogs

Identity and security

Each device generates an ECDSA P-256 keypair in NVS. On connect the platform issues a challenge, the device signs it, and nothing the application sends leaves before auth_ok. The private key never leaves the chip; only the public key is ever shared.
hyperwisor_hsc_register() registers the key against an account without the app — for a factory jig, or a device you provision yourself.
hyperwisor_hsc_erase() destroys the identity. The device generates a new keypair on the next boot and is an unknown device to the platform until that new key is registered.

Credentials

Everything is persisted in NVS. Normally you set none of this — the app writes it during provisioning.
Setting credentials in code does not replace provisioning. A device that skips it never registers its public key and is refused as unknown device, with no setup access point to fall back to. If you provision in code, call hyperwisor_hsc_register() as well.

Database

Read and write a product’s cloud tables straight from the device (needs HYPERWISOR_ENABLE_HTTP).
Each has a *_with_response variant returning cJSON * that you must delete.

Users

For devices with their own sign-in screen — a panel shared by several people.

SMS

Sends through the product’s configured SMS provider — see SMS in the Studio.

Onboarding from the device

Registers the device against a user’s account from firmware, for flows that do not go through the app — a factory jig, or a device with its own screen.

Persistent storage

Your own key/value store in NVS, separate from the credentials above.

Time

Wi-Fi

The callback fires on HYPERWISOR_WIFI_EVT_CONNECTED, _DISCONNECTED, _AP_START, _AP_STOP and _GOT_IP.

GPIO

Needs HYPERWISOR_ENABLE_GPIO.
The allowlist is required. Without one, cloud GPIO commands are refused — deliberately, so a command from the internet can never reach a pin driving something you did not intend.
save_state / restore_all_states persist output levels across a reboot.

OTA

Needs HYPERWISOR_ENABLE_OTA. See OTA updates for the partition table.

Board port

A struct of function pointers describing your board — GPIO allowlist, display backlight, device name. The library never knows how your hardware works; it calls what you provide. Register it before hyperwisor_init().

Feature headers

The umbrella header pulls these in — their signatures are the source of truth.

Examples

A real project walkthrough.

OTA updates

Enable over-the-air firmware.