Skip to content

Control vacuum

Radosław Kubera edited this page Oct 16, 2026 · 4 revisions

vacuum control

Control catalogue · Documentation home

Portal vacuum control

Minimal field JSON:

{
  "id": "vacuum",
  "type": "vacuum",
  "name": "Vacuum"
}

Full field JSON:

{
  "id": "vacuum",
  "type": "vacuum",
  "name": "Vacuum",
  "default": {
    "state": "docked",
    "fan_speed": "normal"
  },
  "controls": [
    {
      "key": "",
      "type": "action",
      "label": "ui_133",
      "command": "",
      "payload": "start"
    },
    {
      "key": "",
      "type": "action",
      "label": "ui_119",
      "command": "",
      "payload": "stop"
    },
    {
      "key": "",
      "type": "action",
      "label": "ui_134",
      "command": "",
      "payload": "pause"
    },
    {
      "key": "",
      "type": "action",
      "label": "ui_135",
      "command": "",
      "payload": "return_to_base"
    },
    {
      "key": "",
      "type": "action",
      "label": "ui_136",
      "command": "",
      "payload": "locate"
    },
    {
      "key": "",
      "type": "action",
      "label": "ui_137",
      "command": "",
      "payload": "clean_spot"
    },
    {
      "key": "fan_speed",
      "type": "select",
      "label": "ui_104",
      "command": "fan",
      "options": [
        "quiet",
        "normal",
        "turbo"
      ]
    },
    {
      "key": "",
      "type": "action_json",
      "label": "ui_138",
      "command": "custom"
    }
  ],
  "ha": {
    "command_topic": "$command",
    "state_topic": "$state",
    "supported_features": [
      "start",
      "stop",
      "pause",
      "return_home",
      "status",
      "locate",
      "clean_spot",
      "fan_speed",
      "send_command"
    ],
    "set_fan_speed_topic": "$command:fan",
    "fan_speed_list": [
      "quiet",
      "normal",
      "turbo"
    ],
    "send_command_topic": "$command:custom"
  }
}

Properties in the full example:

Property Required? Meaning / default
id Required Stable application key; unique across registered pages.
type Required Enabled field type.
name Required title¹ Display title; may be replaced by a nonempty names object.
default Optional Omit to use the built-in initial value.
controls Optional Omit to use the preset controls; supplying an array replaces them.
ha Optional Omit to use automatic HA discovery; supplied properties override defaults.

¹ name can be replaced by names. Other shared optional properties are listed in the catalogue.

The control provides Clean, Stop, Pause, Return to base, Locate and Clean spot buttons, a fan-speed selector, and a JSON custom-command input. Its default state is {"state":"docked","fan_speed":"normal"}. Base-topic action payloads are start, stop, pause, return_to_base, locate and clean_spot. Fan speed accepts quiet, normal or turbo on _fan; custom JSON uses _custom. States such as cleaning, idle, paused, returning and docked highlight matching operating buttons. The program can additionally report an optional action property (start, stop, pause, return_to_base, locate, or clean_spot) using setAppConfigStateValue. When present, this property selects the active button, including Locate and Clean spot, until the program updates it. There is no automatic timeout or local selection based on a click. The demo callback reports both operating state and the selected action. Raw state text is hidden.

Integration with Home Assistant

MQTT component: vacuum. Requires the control’s feature flag, dynamic pages, MQTT and HA support to be enabled. ArdPortal registers MQTT Discovery and routes state/commands; the sketch implements device behavior. Action callbacks acknowledge acceptance, not physical completion.

Supported by ArdPortal: Start, stop, pause, return-to-base, locate and spot-clean actions; fan selection (quiet/normal/turbo); custom JSON command callback. The state object includes reported status and fan speed.

Not provided by the built-in integration / limits: No navigation, mapping, room selection, schedules, consumable tracking, cleaning history or robot driver. The built-in descriptor does not advertise battery support; additional telemetry/capabilities need matching metadata and application implementation.

Explicit ha properties can override Discovery metadata. They do not create additional hardware behavior, application value properties or command handlers by themselves. See HA integration for the shared setup.

Integration with Zigbee

Implemented as a composite mapping. The functions below are separate standard endpoints on the same physical Zigbee device. The optional generated Zigbee2MQTT converter and ZHA quirk add names and option/state semantics; a composite mapping does not guarantee one combined gateway entity. Requires ESP32-C5/C6/H2, Zigbee and dynamic pages enabled, and the field’s control flag enabled. MQTT/HA is not required.

Standard mapping: Six momentary On/Off actions + Multistate Output + Multistate Input.

Supported by ArdPortal: ON activates start, stop, pause, return_to_base, locate or clean_spot. Fan speed is selected by ordinal (preset: 1=quiet, 2=normal, 3=turbo). Activity: 1=idle, 2=cleaning, 3=docked, 4=paused, 5=returning, 6=error.

Not provided / limits: The custom JSON command control is not mapped. No native vacuum UI, navigation, room selection, consumables or battery endpoint is added. Generic fan/activity endpoints may be omitted by the gateway.

Endpoint IDs follow registration order, then the preset’s controls order; read-only measurement/status endpoints follow the editable/action endpoints. Composite fields consume multiple slots in the shared 239-endpoint budget. Startup stages one endpoint per loop and reports one endpoint per loop. Values and action callbacks use the existing AppConfig routes and persist; accepting an action is not hardware completion.

Standard Basic ProductLabel contains field name / property or action, truncated to 63 UTF-8 bytes; Analog/Multistate endpoints also carry their Description. A gateway is not required to use these labels or expose all these clusters. Option/state names are documented here but are not currently sent as StateText. Unknown discrete readings set the standard status fault flag and leave the last representable ordinal unchanged.

visibleWhen does not remove endpoints or create a dynamic Zigbee form. Dependency rules do not affect Zigbee control visibility or command acceptance. Native endpoint definitions freeze at startup; changes need restart. Physical coordinator interoperability is still unverified.

See Zigbee integration and page/order limitations.

Read and update values from C++

These examples use the field ID from the JSON above and an existing ArdPortal portal. Run them after page registration has finished and portal.portalAndAppConfigReady() is true. Call portal.loop() frequently. Register callbacks once in setup(); do not repeat setters on every loop iteration.

Set the value with automatic ArdFS persistence

Set "persist": true on this field in its page JSON. It is optional for editable fields whose preset already persists settings, but required to override a RAM-only preset such as a sensor. Calling setAppConfigValue() sets the control value and ArdPortal automatically saves AppConfig through its integrated ArdFS storage. Do not create an ArdFS object or call a separate write/flush method. The automatic save is coalesced and advanced by subsequent portal.loop() calls.

// Use this path when the value is a setting that should survive restart.
ArdJSON::JSONVar next = ArdJSON::JSON.parse(R"JSON({"state":"docked","fan_speed":"normal"})JSON");
if (!next.isValid() || !portal.setAppConfigValue("vacuum", next)) {
  Serial.println("Setting rejected or storage temporarily unavailable");
}

true from the setter means acceptance, not a completed flash write. Configure this callback once to observe the result:

portal.onPortalAndAppConfigSaved([](bool ok, const String& error) {
  if (!ok) Serial.println(error);
});

Update only RAM

// Use this alternative for live readings/status; never writes ArdFS.
ArdJSON::JSONVar next = ArdJSON::JSON.parse(R"JSON({"state":"docked","fan_speed":"normal"})JSON");
if (!next.isValid() || !portal.setAppConfigStateValue("vacuum", next, false)) {
  Serial.println("Runtime value rejected");
}

The third argument false avoids queuing an immediate MQTT publication. Use true or omit it to queue changed state. RAM updates work regardless of persist. Alternatively, with "persist": false, setAppConfigValue() also follows the RAM-only path.

Read the current value

const ArdJSON::JSONVar current = portal.getAppConfigValue("vacuum");
if (!current.isUndefined() && current.isValid()) {
  Serial.println(ArdJSON::JSON.stringify(current));
}

The getter returns the effective field value: RAM override first, then saved AppConfig, then the definition default. A RAM-only update is lost on restart; the saved value/default becomes effective again. Choose the persistent or RAM path for a given value. A RAM override can mask a later persistent change for the same ID; there is no API to clear just that override. Prefer separate setting and telemetry IDs when both are needed.

Back to control catalogue

Clone this wiki locally