# Pairing

![](https://998911913-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPk9cn4V7WnnKt7fbry%2Fuploads%2Fgit-blob-6d0376778b439b523762790d1b1dee388af29903%2Fdriver-pairing.png?alt=media)

Pairing is started when the user selects the device they want to add from the Homey app. The `pair` property of the driver defines a list of views, which the user navigates through. These views are called pairing templates. Homey includes a set of system templates that implement consistent pairing steps for most devices.

{% hint style="info" %}
Homey already knows how to pair Zigbee and Z-Wave devices so it is not possible to implement your own pairing for those devices. Read the [Zigbee](https://apps.developer.homey.app/wireless/zigbee) and [Z-Wave](https://apps.developer.homey.app/wireless/z-wave) documentations to learn how to pair devices using those technologies with Homey.
{% endhint %}

## Basic pairing example

This example is a basic way to enable pairing in your driver. To add pairing to your driver, add the following to your `driver.compose.json`:

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

```javascript
{
  "name": { "en": "My Driver" },
  "images": {
    "small": "/drivers/my_driver/assets/images/small.png",
    "large": "/drivers/my_driver/assets/images/large.png"
  },
  "class": "socket",
  "capabilities": ["onoff"],
  "platforms": ["local", "cloud"],
  "connectivity": "cloud",
  "pair": [
    {
      "id": "list_my_devices",
      // we use a system template here, for consistency, and less work for us!
      "template": "list_devices",
      // show pair view with id 'add_my_devices' when clicked 'Next'
      "navigation": { "next": "add_my_devices" }
    },
    {
      "id": "add_my_devices",
      // again, use a template
      "template": "add_devices"
    }
  ]
}
```

{% endcode %}

This defines a pairing process with 2 steps. The first step requires the user to pick the devices to add from a list and the second step will automatically add these devices to Homey. Both these steps use Homey's built-in pairing templates `list_devices` and `add_devices`. The navigation option determines which of the steps the pairing will go to when the user presses the "Next" button.

{% hint style="info" %}
The `navigation` object also supports a `prev` option for when a user can go back to the previous screen. This can be useful, for example, with a `login_credentials` system templates to allow users to retry logging-in.
{% endhint %}

{% tabs %}
{% tab title="JavaScript" %}
If your pairing only uses the `list_devices` and `add_devices` templates you can use the [`Driver#onPairListDevices()`](https://apps-sdk-v3.developer.homey.app/Driver.html#onPairListDevices) method to quickly implement a pairing process. From this method you can return a list of devices that will be presented to the user.

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

```javascript
const Homey = require("homey");
const DeviceApi = require("device-api");

class Driver extends Homey.Driver {
  async onPairListDevices() {
    const devices = await DeviceApi.discoverDevices();
    return devices;
  }
}

module.exports = Driver;
```

{% endcode %}
{% endtab %}

{% tab title="TypeScript" %}
If your pairing only uses the `list_devices` and `add_devices` templates you can use the [`Driver#onPairListDevices()`](https://apps-sdk-v3.developer.homey.app/Driver.html#onPairListDevices) method to quickly implement a pairing process. From this method you can return a list of devices that will be presented to the user.

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

```mts
import Homey from "homey";
import DeviceApi from "./device-api.mjs";

export default class Driver extends Homey.Driver {
  async onPairListDevices(): Promise<object[]> {
    const devices = await DeviceApi.discoverDevices();
    return devices;
  }
}

```

{% endcode %}
{% endtab %}

{% tab title="Python" %}
If your pairing only uses the `list_devices` and `add_devices` templates you can use the [`Driver#on_pair_list_devices()`](https://python-apps-sdk-v3.developer.homey.app/driver.html#homey.driver.Driver.on_pair_list_devices) method to quickly implement a pairing process. From this method you can return a list of devices that will be presented to the user.

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

```python
from device_api import DeviceApi
from homey import driver
from homey.driver import ListDeviceProperties


class Driver(driver.Driver):
    async def on_pair_list_devices(self, view_data: dict) -> list[ListDeviceProperties]:
        devices = await DeviceApi.discover_devices()
        return devices


homey_export = Driver

```

{% endcode %}
{% endtab %}
{% endtabs %}

## Device pairing data

{% tabs %}
{% tab title="JavaScript" %}
The following is an overview of the data you can supply for a device to be added, you should return an array of objects like this from [`Driver#onPairListDevices()`](https://apps-sdk-v3.developer.homey.app/Driver.html#onPairListDevices) or `session.setHandler("list_devices")`.
{% endtab %}

{% tab title="TypeScript" %}
The following is an overview of the data you can supply for a device to be added, you should return an array of objects like this from [`Driver#onPairListDevices()`](https://apps-sdk-v3.developer.homey.app/Driver.html#onPairListDevices) or `session.setHandler("list_devices")`.
{% endtab %}

{% tab title="Python" %}
The following is an overview of the data you can supply for a device to be added, you should return an array of objects like this from [`Driver#on_pair_list_devices()`](https://python-apps-sdk-v3.developer.homey.app/driver.html#homey.driver.Driver.on_pair_list_devices) or `session.set_handler("list_devices")`.
{% endtab %}
{% endtabs %}

```javascript
{
  // The name of the device that will be displayed
  name: "My Device",

  // The data object is required and should be unique for the device.
  // So a device's MAC address would be good, but an IP address would
  // be bad since it can change over time.
  data: {
    id: "abcd",
  },

  // Optional: The store is dynamic and persistent storage for your device
  store: {
    // For example store the IP address of your device
    address: "127.0.0.1",
  },

  // Optional: sets the devices initial settings, this allows users to change
  // them after pairing in the device settings screen.
  settings: {
    pincode: "1234",
  },

  // Optional: These properties overwrite the defaults
  // that you specified in the driver manifest:
  icon: "/my_icon.svg", // relative to: /drivers/<driver_id>/assets/
  capabilities: ["onoff", "target_temperature"],
  capabilitiesOptions: {
    target_temperature: {
      min: 5,
      max: 35,
    },
  },
}
```

{% hint style="info" %}
Note that it is also supported that icons are referenced from the `/userdata` folder. This is the only exception to the rule that all icons are relative to: `/drivers/<driver_id>/assets/` e.g. `/userdata/my_icon.svg`.\
\
This allows apps to upload icons to the userdata folder and reference them later during pairing. This feature is supported since Homey `v12.3.0`
{% endhint %}

## System Views

The pairing templates are built with HTML, CSS and JavaScript. Most drivers will suffice using the system templates that are provided by Homey.

{% content-ref url="pairing/system-views/devices-list" %}
[devices-list](https://apps.developer.homey.app/the-basics/devices/pairing/system-views/devices-list)
{% endcontent-ref %}

{% content-ref url="pairing/system-views/add-devices" %}
[add-devices](https://apps.developer.homey.app/the-basics/devices/pairing/system-views/add-devices)
{% endcontent-ref %}

{% content-ref url="pairing/system-views/oauth2-login" %}
[oauth2-login](https://apps.developer.homey.app/the-basics/devices/pairing/system-views/oauth2-login)
{% endcontent-ref %}

{% content-ref url="pairing/system-views/credentials-login" %}
[credentials-login](https://apps.developer.homey.app/the-basics/devices/pairing/system-views/credentials-login)
{% endcontent-ref %}

{% content-ref url="pairing/system-views/pincode" %}
[pincode](https://apps.developer.homey.app/the-basics/devices/pairing/system-views/pincode)
{% endcontent-ref %}

{% content-ref url="pairing/system-views/loading" %}
[loading](https://apps.developer.homey.app/the-basics/devices/pairing/system-views/loading)
{% endcontent-ref %}

{% content-ref url="pairing/system-views/done" %}
[done](https://apps.developer.homey.app/the-basics/devices/pairing/system-views/done)
{% endcontent-ref %}

## Custom Views

Most drivers will suffice using the provided templates. In certain cases you may want, or need, to create pairing screens that are more suited to your driver. For these cases it is possible to create custom pairing views, to learn more read the [custom pairing view guide](https://apps.developer.homey.app/advanced/custom-views/custom-pairing-views).

## Repairing

To ensure users with a great experience, your app's devices should always stay available without user interaction.

However, sometimes when a device explicitly needs user interaction to be fixed (for example an OAuth2 token has been revoked and the user needs to authenticate again), the user can initiate a *repair* process.

To enable repairing, you must add support for this to your driver by adding `repair` to your App Manifest:

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

```javascript
{
  "name": { "en": "My Driver" },
  "images": {
    "small": "/drivers/my_driver/assets/images/small.png",
    "large": "/drivers/my_driver/assets/images/large.png"
  },
  "repair": [
    {
      "id": "login_oauth2",
      "template": "login_oauth2"
    }
  ]
}
```

{% endcode %}

It is also possible to use custom pairing views for repairing. To learn more about custom pairing templates read the [custom pairing view guide](https://apps.developer.homey.app/advanced/custom-views/custom-pairing-views).

{% tabs %}
{% tab title="JavaScript" %}
Note that when repairing the `Homey.createDevice()` method is not available in the custom view and you can add a `onRepair` method to your driver, which is similar to the `onPair` method.

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

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

class Driver extends Homey.Driver {
  onRepair(session, device) {
    // Argument session is a PairSocket, similar to Driver.onPair
    // Argument device is a Homey.Device that's being repaired

    session.setHandler("my_event", (data) => {
      // Your code
    });

    session.setHandler("disconnect", () => {
      // Cleanup
    });
  }
}

module.exports = Driver;
```

{% endcode %}
{% endtab %}

{% tab title="TypeScript" %}
Note that when repairing the `Homey.createDevice()` method is not available in the custom view and you can add a `onRepair` method to your driver, which is similar to the `onPair` method.

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

```mts
import Homey from "homey";
import type Device from "./device.mjs";

export default class Driver extends Homey.Driver {
  async onRepair(session: Homey.Driver.PairSession, device: Device): Promise<void> {
    // Argument device is the device that's being repaired

    session.setHandler("my_event", async data => {
      // Your code
    });

    session.setHandler("disconnect", async () => {
      // Cleanup
    });
  }
}

```

{% endcode %}
{% endtab %}

{% tab title="Python" %}
Note that when repairing the `Homey.createDevice()` method is not available in the custom view and you can add a `on_repair` method to your driver, which is similar to the `on_pair` method.

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

```python
from homey import driver
from homey.pair_session import PairSession

from .device import Device


class Driver(driver.Driver[Device]):
    async def on_repair(self, session: PairSession, device: Device):
        # Argument device is the device that's being repaired

        async def on_my_event(*args):
            # Your code
            ...

        async def on_disconnect():
            # Cleanup
            ...

        session.set_handler("my_event", on_my_event)
        session.set_handler("disconnect", on_disconnect)


homey_export = Driver

```

{% endcode %}
{% endtab %}
{% endtabs %}
