Skip to content

Command & Action

Commands (writable properties) and actions (stateless operations) let the UI control physical/backend state. They round-trip through your Python handler.

Purpose

Enable write-back from UI to your backend with authorization and audit. Commands set a value; actions trigger an operation.

Flow

UI switch → POST /commands → on_write handler → your backend → result
UI button → POST /actions  → on_action handler → your backend → result

Command (writable property)

python
@pump.on_write("power")
async def set_power(value: bool):
    await existing_backend.set_power(value)
    return value
POST /commands
{ "entity": "pump-01", "property": "power", "value": false }

Action (stateless)

python
pump.action("reset", label="Reset Pump", severity="danger")

@pump.on_action("reset")
async def do_reset():
    await existing_backend.reset()
POST /actions
{ "entity": "pump-01", "action": "reset" }

Actions have no state, no value — they run an operation (reset, calibrate, start, stop, acknowledge, emergency-stop).

Automation uses the same pipeline

Automation rules trigger commands through the exact same on_write handlers — never direct state writes.

State machine

pending → succeeded
pending → failed

Constraints

  • Default timeout: 10 seconds (handlers must complete within)
  • Only writable=True properties can be commanded
  • Only admin role can send commands/actions (enforced server-side)
  • Handler return value becomes the new state (commands only)
  • Automation may only set properties where automation={"allow_set": True}

Common mistakes

  • Handler taking >10s → failed with timeout error
  • Expecting viewer role to command → 403 Forbidden
  • Not returning the value → state updated with input value anyway
  • Registering on_action before device.action()ValueError

Audit

Every command and action logs: timestamp, workspace, user (or automation:<rule>), entity, property, requested value, result.

Built for self-hosted IoT runtimes.