# Settings

Devices can have settings that can be changed by the user. These are presented to the user as *Advanced settings*. The device settings are defined in the `/drivers/<driver_id>/driver.settings.compose.json` file.

<div align="center"><figure><img src="https://998911913-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPk9cn4V7WnnKt7fbry%2Fuploads%2Fgit-blob-c72c5108d33dcac5075bf399d9c4824aa82b5bc7%2Fdriver-settings.png?alt=media" alt="" width="375"><figcaption></figcaption></figure></div>

{% code title="/drivers/\<driver\_id>/driver.settings.compose.json" %}

```javascript
[
  {
    "id": "username",
    "type": "text",
    "label": { "en": "Username" },
    "value": "John Doe",
    "hint": { "en": "The name of the user." }
  },
  {
    "id": "password",
    "type": "password",
    "label": { "en": "Password" },
    "value": "Secret",
    "hint": { "en": "The password of the user." }
  }
]
```

{% endcode %}

## Defining settings

Every setting has a `type` property that determines what values it can have and how it is presented to the user. The `value` property of each setting is the initial value of the setting, this property is required for all settings. The following setting types are supported:

### Text

This is a single line text input whose value is a `string`. You can optionally validate the value using a regex pattern by adding a `pattern` property. For example adding `"pattern": "[a-zA-Z]"` to the setting definition will make sure the user can only input letters.

```javascript
{
  "id": "username",
  "type": "text",
  "label": { "en": "Username" },
  "value": "John Doe",
  "hint": { "en": "The name of the user." }
}
```

### Password

Settings with the type `password` behave the same as `text` but the input is visually hidden.

```javascript
{
  "id": "password",
  "type": "password",
  "label": { "en": "Password" },
  "value": "Secret",
  "hint": { "en": "The password of the user." }
}
```

### Text area

`textarea` type settings behave the same as `text` but allow multi-line input.

```javascript
{
  "id": "description",
  "type": "textarea",
  "label": { "en": "Description" },
  "value": "Initial description",
  "hint": { "en": "A custom device description." }
}
```

### Number

The `number` type settings can only contain numbers, this means that the `value` must also be a number. Number settings also support `min` `max` and `step` properties. You can also optionally provide the unit of the setting by setting the `units` property.

```javascript
{
  "id": "duration",
  "type": "number",
  "label": { "en": "Duration" },
  "value": 3,
  "min": 0,
  "max": 5,
  "units": { "en": "minutes" }
}
```

### Checkbox

`checkbox` settings can be `true` or `false`.

```javascript
{
  "id": "allow_override",
  "type": "checkbox",
  "value": true,
  "label": { "en": "Allow override" }
}
```

### Dropdown

Settings with the type `dropdown` allow the user to pick a value from a predefined set of choices. The values of the checkbox must be strings.

```javascript
{
  "id": "mode",
  "type": "dropdown",
  "value": "heating",
  "label": { "en": "Default mode" },
  "values": [
    {
      "id": "heating",
      "label": { "en": "Heating" }
    },
    {
      "id": "cooling",
      "label": { "en": "Cooling" }
    }
  ]
}
```

### Group

You can add a `type` group to your settings to group multiple settings together with a label.

```javascript
{
  "type": "group",
  "label": { "en": "Login details" },
  "children": [
    {
      "id": "username",
      "type": "text",
      "label": { "en": "Username" },
      "value": "John Doe",
      "hint": { "en": "The name of the user." }
    },
    {
      "id": "password",
      "type": "password",
      "label": { "en": "Password" },
      "value": "Secret",
      "hint": { "en": "The password of the user." }
    }
  ]
}
```

### Label

You can add additional explanation or headings to the device settings page by adding a setting with the type `label`. This acts as a read-only text field and can only be updated by your app.

```javascript
{
  "id": "label",
  "type": "label",
  "label": { "en": "IP address" },
  "value": "192.168.0.10",
  "hint": { "en": "The IP address of the device." }
}
```

## Highlighted settings

<figure><img src="https://998911913-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPk9cn4V7WnnKt7fbry%2Fuploads%2Fgit-blob-43a863b79fcacd15997db67265b7cd69ee72a10f%2Fdriver-settings-highlighted.png?alt=media" alt="" width="375"><figcaption><p>Highlighted settings for a camera device.</p></figcaption></figure>

In an app with an extensive list of settings, it can be challenging for users to locate the most important ones. To address this, there's an option to display key settings in a separate list during the pairing of a new device. This feature, called "Highlighted Settings," helps users quickly find the most essential settings.

To highlight a settings item, simply add `"highlight": true` to the item in your settings JSON file.

{% hint style="warning" %}
Be selective when choosing highlighted settings. The goal is to feature a few frequently used items. Highlighting too many settings can make the highlighted list just as difficult to navigate as the full list of settings.
{% endhint %}

## Using settings

{% tabs fullWidth="false" %}
{% tab title="JavaScript" %}
Once you have defined what settings your device has you can read the settings in from your `Device` class. You can retrieve the current values of all settings as follows:

{% code title="/drivers/\<driver\_id>/device.js" %}

```javascript
const Homey = require('homey');

class Device extends Homey.Device {
  async onInit() {
    const settings = this.getSettings();
    console.log(settings.username);
  }
}

module.exports = Device;
```

{% endcode %}

When settings are changed by a user, [`Device#onSettings()`](https://apps-sdk-v3.developer.homey.app/Device.html#onSettings) will be called. You can overwrite the method in your `device.js` to react to changes to the settings. It is also possible to throw an error from this method if the settings are invalid. The thrown error will be shown to the user and they be asked to change their settings in order to store them.

{% code title="/drivers/\<driver\_id>/device.js" %}

```javascript
const Homey = require('homey');

class Device extends Homey.Device {
  async onSettings({ oldSettings, newSettings, changedKeys }) {
    // run when the user has changed the device's settings in Homey.
    // changedKeysArr contains an array of keys that have been changed
    // if the settings must not be saved for whatever reason:
    // throw new Error('Your error message');
  }
}

module.exports = Device;
```

{% endcode %}

It is also possible to update the settings from your `Device` by calling [`Device#setSetting()`](https://apps-sdk-v3.developer.homey.app/Device.html#setSetting).

{% code title="/drivers/\<driver\_id>/device.js" %}

```javascript
const Homey = require('homey');

class Device extends Homey.Device {
  async onInit() {
    await this.setSettings({
      // only provide the settings you want to change
      username: "Jane Doe",
    });
  }
}

module.exports = Device;
```

{% endcode %}

{% hint style="info" %}
When changing device settings programmatically using [`Device#setSettings()`](https://apps-sdk-v3.developer.homey.app/Device.html#setSettings), the [`Device#onSettings()`](https://apps-sdk-v3.developer.homey.app/Device.html#onSettings) function is not fired.
{% endhint %}
{% endtab %}

{% tab title="TypeScript" %}
Once you have defined what settings your device has you can read the settings in from your `Device` class. You can retrieve the current values of all settings as follows:

{% code title="/drivers/\<driver\_id>/device.mts" %}

```mts
import Homey from "homey";

export default class Device extends Homey.Device {
  async onInit(): Promise<void> {
    const settings = this.getSettings();
    console.log(settings.username);
  }
}

```

{% endcode %}

When settings are changed by a user, [`Device#onSettings()`](https://apps-sdk-v3.developer.homey.app/Device.html#onSettings) will be called. You can overwrite the method in your `device.js` to react to changes to the settings. It is also possible to throw an error from this method if the settings are invalid. The thrown error will be shown to the user and they be asked to change their settings in order to store them.

{% code title="/drivers/\<driver\_id>/device.mts" %}

```mts
import Homey from "homey";

type SettingsEvent<T> = {
  oldSettings: T;
  newSettings: T;
  changedKeys: (keyof T)[];
};

type Settings = {
  username: string;
};

export default class Device extends Homey.Device {
  async onSettings({ oldSettings, newSettings, changedKeys }: SettingsEvent<Settings>): Promise<string | void> {
    // runs when the user has changed the device's settings in Homey.
    // changedKeys contains the keys that have been changed
    // if the settings must not be saved for whatever reason:
    // throw new Error('Your error message');
  }
}

```

{% endcode %}

It is also possible to update the settings from your `Device` by calling [`Device#setSetting()`](https://apps-sdk-v3.developer.homey.app/Device.html#setSetting).

{% code title="/drivers/\<driver\_id>/device.mts" %}

```mts
import Homey from "homey";

export default class Device extends Homey.Device {
  async onInit(): Promise<void> {
    await this.setSettings({
      // only provide the settings you want to change
      username: "Jane Doe",
    });
  }
}

```

{% endcode %}

{% hint style="info" %}
When changing device settings programmatically using [`Device#setSettings()`](https://apps-sdk-v3.developer.homey.app/Device.html#setSettings), the [`Device#onSettings()`](https://apps-sdk-v3.developer.homey.app/Device.html#onSettings) function is not fired.
{% endhint %}
{% endtab %}

{% tab title="Python" %}
Once you have defined what settings your device has you can read the settings in from your `Device` class. You can retrieve the current values of all settings as follows:

{% code title="/drivers/\<driver\_id>/device.mts" %}

```python
from homey import device


class Device(device.Device):
    async def on_init(self) -> None:
        settings = self.get_settings()
        print(settings.get("username"))


homey_export = Device

```

{% endcode %}

When settings are changed by a user, [`Device#on_settings()`](https://python-apps-sdk-v3.developer.homey.app/device.html#homey.device.Device.on_settings) will be called. You can overwrite the method in your `device.js` to react to changes to the settings. It is also possible to throw an error from this method if the settings are invalid. The thrown error will be shown to the user and they be asked to change their settings in order to store them.

{% code title="/drivers/\<driver\_id>/device.py" %}

```python
from homey import device


class Device(device.Device):
    async def on_settings(
        self,
        old_settings,
        new_settings,
        changed_keys,
    ):
        # runs when the user has changed the device's settings in Homey.
        # changed_keys contains the keys of settings that have been changed
        # if the settings must not be saved for whatever reason:
        # raise Exception("Your error message")
        ...


homey_export = Device

```

{% endcode %}

It is also possible to update the settings from your `Device` by calling [`Device#set_setting()`](https://python-apps-sdk-v3.developer.homey.app/device.html#homey.device.Device.set_settings).

{% code title="/drivers/\<driver\_id>/device.py" %}

```python
from homey import device


class Device(device.Device):
    async def on_init(self) -> None:
        await self.set_settings(
            {
                # only provide the settings you want to change
                "username": "Jane Doe",
            }
        )


homey_export = Device

```

{% endcode %}

{% hint style="info" %}
When changing device settings programmatically using [`Device#set_settings()`](https://python-apps-sdk-v3.developer.homey.app/device.html#homey.device.Device.set_settings), the [`Device#on_settings()`](https://python-apps-sdk-v3.developer.homey.app/device.html#homey.device.Device.on_settings) function is not fired.
{% endhint %}
{% endtab %}
{% endtabs %}

## Reserved Settings

The following prefixes are **reserved** by Homey and **must not** be used as the beginning of your setting `id`:

* `homey:`
* `zw_`
* `zb_`
* `mtr_`
* `thread_`
* `zone_`
* `energy_`
* `satellite_mode_`
* `homekit_`
