Drivers & Devices

In Homey Apps the Device classes represent the physical devices paired with Homey.

For every device paired with Homey, a Device class will be created and a device tile will be shown in the interface. Every Device class is associated with a Driver class. All Driver classes of your app will be instantiated when your app is started, even if there are no devices of that type paired with Homey. This allows the driver to be responsible for pairing new devices and defining Flow cards.

You can use the Homey CLI to interactively create a driver, this will create a basic driver manifest and all the required files for your driver:

homey app driver create

This command will ask a number of questions about the driver you want to create, and will then create a new folder in your drivers/ directory which will look like this:

com.athom.example/driver/<driver_id>/
├─ assets/
│ └─ ...
├─ device.js
├─ driver.js
└─ driver.compose.json

The /drivers/<driver_id>/driver.js file contains the Driver class. This class is responsible for pairing devices and describes the functionality for the devices belonging to the driver such as Flow cards.

/drivers/<driver_id>/driver.js
const Homey = require("homey");

class Driver extends Homey.Driver {
  // this method is called when the app is started and the Driver is inited
  async onInit() {
    const showToastActionCard = this.homey.flow.getActionCard('show_toast');
  
    showToastActionCard.registerRunListener(async ({ device, message }) => {
      await device.createToast(message);
    });
  }
  
  // This method is called when a user is adding a device
  // and the 'list_devices' view is called
  async onPairListDevices() {
    return [
      {
        name: "Foo Device",
        data: {
          id: "abcd1234",
        },
      },
    ];
  }
}

module.exports = Driver;

The shown onPairListDevices is a heavily simplified example. Learn more about pairing in the Pairing documentation.

The /drivers/<driver_id>/device.js file contains the Device class. This class implements the device's functionality such as its capabilities and Flows.

/drivers/<driver_id>/device.js
const Homey = require("homey");
const DeviceApi = require("device-api");

class Device extends Homey.Device {
  // this method is called when the Device is inited
  async onInit() {
    this.log("Device init");
    this.log("Name:", this.getName());
    this.log("Class:", this.getClass());

    // register a capability listener
    this.registerCapabilityListener("onoff", this.onCapabilityOnoff.bind(this));
  }

  // this method is called when the Device has requested a state change (turned on or off)
  async onCapabilityOnoff(value, opts) {
    // ... set value to real device, e.g.
    // await setMyDeviceState({ on: value });
    // or, throw an error
    // throw new Error('Switching the device failed!');
  }
  
  // this is a custom method for the 'show_toast' Action Flow card as
  // shown in the Driver example above
  async createToast(message) {
    await DeviceApi.createToast(message);
  }
}

module.exports = Device;

Driver Manifest

The /drivers/<driver_id>/driver.compose.json file is the driver manifest, when building your app all the driver.compose.json files will be bundled into your App Manifest. A basic driver manifest looks like this:

/drivers/<driver_id>/driver.compose.json
{
  "name": { "en": "My Driver" },
  "class": "socket",
  "capabilities": ["onoff", "dim"],
  "images": {
    "small": "/drivers/my_driver/assets/images/small.png",
    "large": "/drivers/my_driver/assets/images/large.png",
    "xlarge": "/drivers/my_driver/assets/images/xlarge.png"
  },
  "platforms": ["local", "cloud"],
  "connectivity": ["lan"],
  "pair": [
    {
      "id": "list_devices",
      "template": "list_devices",
      "navigation": { "next": "add_devices" }
    },
    {
      "id": "add_devices",
      "template": "add_devices"
    }
  ]
}

Icon

The driver icon location cannot be specified in the driver manifest, instead the driver's icon is always expected to be located at /drivers/<driver_id>/assets/icon.svg. Read the app store guidelines for more information about the driver icon.

Platforms

"platforms": ["local", "cloud"]

An array containing the driver's supported platforms. Read the Homey Cloud guide for more information.

Device Class

"class": "light"

The device class tells Homey what type of device your driver adds support for. Examples of device classes are socket, light, lock etc. When a specific device is not supported by Homey, you can use the class other.

Find your device's class in the Device Class Reference.

Capabilities

"capabilities": ["onoff", "dim"]

The capabilities of a device describe the states and actions a device supports. For example, a light may have the capability onoff which allows users to toggle the light on or off. It can also support the dim capability which would allow the user to change the lights brightness.

Capabilities all have a data type, for example the onoff capability has the type boolean and can thus be either true or false. The capability dim is of type number and can be any number between 0 - 1, as defined in the capability's definition.

Homey ships with many system capabilities. For other cases, app-specific capabilities can be defined in the App Manifest.

Homey has built-in Flow cards for every system capability.

Read more about Capabilities.

Energy

"energy": {...}

A device can use or generate power. To keep track of the data related to power usage and generation a device can have an energy object. This object contains power usage approximation data and flags to indicate a device generates power or should be omitted from automatic shutdown.

Read more about Energy.

Settings

"settings": [ ... ]

A device can have user-configurable settings, such as the orientation of a curtain or a poll-interval. Settings are shown to the user in the front-end, or can be changed programmatically (see Device#setSettings).

Read more about Settings.

Pairing

"pair": [ ... ]

A device can be added to Homey through pairing. Pairing is started when the user selects the device they want to add from the Homey app. The pair property of the device manifest describes the steps necessary to add the device to Homey.

For most devices a few simple pair steps are enough. For more advanced devices, where more user-steps are required, custom pairing views can be provided.

Read more about Pairing.

Deprecated

"deprecated": true

Sometimes a Driver that has been available in the past should be removed. To not break compatibility for users that were using it, add "deprecated": true to your driver in your App Manifest. It will still work, but won't show up anymore in the 'Add Device' list.

Connectivity

"connectivity": [ ... ]

Specify how the Driver connects to your device in the real world. You can specify multiple values, for example [ "infrared", "lan" ] for a TV that is turned on by Infrared, and then controlled over Wi-Fi LAN.

Allowed Values

Value

Description

lan

Local (Wi-Fi/Ethernet)

cloud

Cloud-connected (Wi-Fi/Ethernet)

ble

Bluetooth Low Energy

zwave

Z-Wave

zigbee

Zigbee

infrared

Infrared

rf433

433 MHz

rf868

868 MHz

Device identifier

During pairing, you must provide a data property. This property contains a unique identifier for the device. This object cannot be changed after pairing. This data property is an object containing any properties of the types String, Number or Object. Homey uses this object to identify your device, together with the driver's ID. Read more in the Device pairing documentation.

Only put the essential properties needed to identify a device in the data object. For example, a MAC address is a good property, an IP address is not, because it can change over time.

Any properties that could change over time should be kept in-memory or saved in the device's store.

Availability

A device can be marked as unavailable using Device#setUnavailable(). This shows to the user that they cannot interacting with the device for example because the device is offline.

When a device is marked as unavailable, all capabilities and Flow actions will be prevented. When a device is available again, use Device#setAvailable() to mark the device as available.

/drivers/<driver_id>/device.js
class Device extends Homey.Device {
  async onInit() {
    await this.setUnavailable();

    DeviceApi.on("connected", (address) => {
      this.setAvailable().catch(this.error);
    });
    
    DeviceApi.on("disconnected", (address) => {
      this.setUnavailable().catch(this.error);
    });    
  }
}

module.exports = Device;

Assets

Your drivers /assets/ folder contains the icon and images for that driver. These images should be clean marketing pictures of the device that this driver implements, these are shown in the Homey App Store.

Read more about driver images and icons in the Homey App Store guidelines.

Store

In some cases you may want to store some information about the device that persists across reboots. For example you may need to store the device's IP address. The device's store is a persistent storage to save device properties. This store can be set during pairing and programmatically read and updated after the device is paired with Homey.

/drivers/<driver_id>/device.js
const Homey = require("homey");
const DeviceApi = require("device-api");

class Device extends Homey.Device {
  async onInit() {
    this.currentAddress = this.getStoreValue("address");

    DeviceApi.on("address-changed", (address) => {
      this.currentAddress = address;
      this.setStoreValue("address", address).catch(this.error);
    });
  }
}

module.exports = Device;

Using the store is pretty rare, usually there are other solutions. For example if you want users to be able to update these values easily you should use device settings instead. See the device settings documentation for more information. And instead of storing the devices IP address in the device store you could use the local network device discovery functionality that is built into Homey.

Last updated