> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hyperwisor.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Lesson 3 — Control Hardware

> Receive a command from a dashboard Switch and drive a GPIO.

**Goal:** flip a Switch on the dashboard and toggle a pin on the device.

## 1. Add a Switch

In the designer, drop a **Switch** and configure the command it sends in the
**Triggers** tab. A command arrives at the device as structured JSON, for example:

```json theme={null}
{
  "from": "controller-xyz",
  "payload": {
    "commands": [
      {
        "command": "GPIO_MANAGEMENT",
        "actions": [
          { "action": "ON", "params": { "gpio": 12, "pinmode": "OUTPUT", "status": "HIGH" } }
        ]
      }
    ]
  }
}
```

## 2. Handle the command in firmware

Register a handler and use the JSON helpers to pull out the command, action, and
params:

```cpp theme={null}
void setup() {
  Serial.begin(115200);

  device.setUserCommandHandler([](JsonObject &msg) {
    JsonObject params = device.findParams(msg, "GPIO_MANAGEMENT", "ON");
    if (!params.isNull()) {
      int pin = params["gpio"];
      pinMode(pin, OUTPUT);
      digitalWrite(pin, params["status"] == "HIGH" ? HIGH : LOW);
    }
  });

  device.begin();
}

void loop() {
  device.loop();
}
```

<Note>
  `findCommand`, `findAction`, and `findParams` navigate the incoming payload so you
  don't parse it by hand. See the
  [API reference](/firmware/arduino/api-reference#json-helpers).
</Note>

## 3. Test it

Flip the Switch in Preview. The device receives the command and toggles the pin.

## How it works

This is the **down** half of the [core loop](/learn/how-it-works): a control
widget → `setUserCommandHandler` on the device. Combined with Lesson 2, you now
have a full two-way device.

<Card title="Next: store readings" icon="arrow-right" href="/learn/lessons/04-store-data">
  Persist data to the product database.
</Card>
