Flow

Flow cards allow users to create advanced home automations using your the devices from your app.

With Homey Flow, Homey users can automate their home. A Flow is a series of Flow cards, which are evaluated and executed.

As a developer, you can add new functionality from your app to Flow by exposing various cards.

A Flow consists of cards in three columns: when, and, then.

  • Cards in the when... column are called triggers. Your app tells Homey to fire a trigger, which will then run all of the user's flows with this trigger.

  • Cards in the ...and... column are called conditions. The conditions must be met in order for the flow to continue. For example it is raining, or the vacuum cleaner is cleaning.

  • Cards in the ...then column are called actions. Actions are executed when the trigger has been fired, and all conditions are met.

Your app can expose any of these three card types, by defining them in your App Manifest.

Defining Flow cards

All Flow cards must at least have an id and a title property. The id is used to refer to the Flow card from your source code. The title will be shown to the users and should be a short and clear description of what the Flow card does. A Flow card can have an optional hint property that can be used to pass additional information to the user that can not be included in the title.

Often it is not necessary to define your own Flow cards because most device classes and capabilities automatically add their own Flow cards.

/.homeycompose/flow/triggers/rain_start.json
{
"title": {
"en": "It starts raining"
},
"hint": {
"en": "When it starts raining more than 0.1 mm/h."
}
}
/.homeycompose/flow/actions/stop_raining.json
{
"title": {
"en": "Make it stop raining.",
}
}

Title for Flow card with arguments

When a Flow card contains arguments it may be necessary to change the title according to these arguments. Using the titleFormatted property it is possible to integrate argument values into the title of the Flow card.

/.homeycompose/flow/conditions/raining_in.json
{
"title":
"en": "It !{{is|isn't}} going to rain in...",
},
"titleFormatted": {
"en": "It !{{is|isn't}} going to rain in [[when]]",
},
"hint": {
"en": "Checks if it will/will not rain more than 0.1 mm/h within the given amount of time.",
},
"args": [
{
"name": "when",
"type": "dropdown",
"values": [
{ "id": "5", "label": { "en": "5 minutes" } },
{ "id": "10", "label": { "en": "10 minutes" } },
{ "id": "15", "label": { "en": "15 minutes" } }
]
}
]
}

Title for Flow card condition

For conditional Flow cards it is possible to change the title if the Flow card is inverted. This can be done using the !{{ text_normal | text_inverted }} syntax.

/.homeycompose/flow/conditions/is_raining.json
{
"title": {
"en": "It !{{is|isn't}} raining"
},
"hint": {
"en": "Checks if it is/is not currently raining more than 0.1 mm/h."
}
}
Example of a Flow condition card and its inverted variant.

Triggering a Flow

To fire a trigger, run the following code from anywhere in your app:

/app.js
const Homey = require('homey');
const RainApi = require('rain-api');
class MyApp extends Homey.App {
async onInit() {
const rainStartTrigger = this.homey.flow.getTriggerCard('rain_start');
RainApi.on('raining', () => {
await rainStartTrigger.trigger();
});
}
}
module.exports = MyApp;

All of the Flows on the Homey, with the trigger rain_start will now fire. More advanced triggers can be achieved using Tokens, State and Devices.

Triggering a Flow when a custom capability changes

Custom capabilities starting with alarm_, meter_ and measure_ will automatically try to trigger a Flow. You only need to define this Flow trigger in your App Manifest.

When updating a custom number capability by calling Device#setCapabilityValue('measure_my_number', 1) Homey will automatically try to start a Flow trigger with ID measure_my_number_changed. This Flow card can have a token with the same as the capability that will be set to the current capability value.

When updating a custom boolean capability by calling Device#setCapabilityValue('alarm_my_alarm', true) Homey will automatically try to start a Flow trigger with ID alarm_my_alarm_true. This Flow card can have a token with the same as the capability that will be set to the current capability value.

This also works for sub-capabilities. For example when you update the capability measure_temperature.inside Homey will try to start a Flow trigger with ID measure_temperature.inside_changed . This Flow card can have a token with the same as the capability that will be set to the current capability value.

Listening for events

For every Flow card your app includes, you should register a "run" listener. Such a listener gets called when a Flow containing the card is activated. Conditions and Actions need a listener to function, however the listener is only necessary for a Trigger card when it has one or more Arguments.

Condition cards must resolve with a true value for the Flow to continue, or a false value to stop the Flow from executing. When the card is rejected (e.g. by throwing inside a Promise), the Flow stops executing as well.

/app.js
const Homey = require('homey');
const RainApi = require('rain-api');
class MyApp extends Homey.App {
async onInit() {
const rainingCondition = this.homey.flow.getConditionCard('is_raining');
rainingCondition.registerRunListener(async (args, state) => {
const raining = await RainApi.isItRaining(); // true or false
return raining;
});
const stopRainingAction = this.homey.flow.getActionCard('stop_raining');
stopRainingAction.registerRunListener(async (args, state) => {
await RainApi.makeItStopRaining();
});
}
}
module.exports = MyApp;

Device cards

Often you will want to add Flow cards that operate on a specific device. For example you want to trigger a Flow when a button is pressed on a specific switch, not when a button is pressed on any of the switches you own. We call these types of Flow cards "device cards". These Flow cards are displayed to users as belonging to a specific device as opposed to belonging to the App.

If your driver has a class that Homey already has support for, like light or socket, your custom card will be added to those cards. For example, if your driver supports a light bulb that has a special disco mode, the user will see "Turn on", "Turn off", "Dim", "Set color", "Disco mode".

Device cards are defined in /drivers/<driver_id>/driver.flow.compose.json. Flow cards defined in this file are only shown for devices belonging to that specific driver.

/drivers/<driver_id>/driver.flow.compose.json
{
"actions": [
{
"id": "disco_mode",
"title": { "en": "Disco mode" }
}
]
}

Device Trigger Flow cards

When creating a Flow Trigger card that is triggered by a device you need to use ManagerFlow#getDeviceTriggerCard() instead of ManagerFlow#getTriggerCard(). A Device Trigger card allows you to pass the device to the trigger() method so Homey knows to only start the Flows for that specific device.

/drivers/<driver_id>/driver.js
class MyDriver extends Homey.Driver {
async onInit() {
this._deviceTurnedOn = this.homey.flow.getDeviceTriggerCard("turned_on");
}
triggerMyFlow(device, tokens, state) {
this._deviceTurnedOn
.trigger(device, tokens, state)
.then(this.log)
.catch(this.error);
}
}
/drivers/<driver_id>/device.js
class MyDevice extends Homey.Device {
async onInit() {
let device = this; // We're in a Device instance
let tokens = {};
let state = {};
this.driver.ready().then(() => {
this.driver.triggerMyFlow(device, tokens, state);
});
}
}

Flow Card Device filters

If necessary you can add filters to choose for which devices the specific flow card will be available. The $filter option supports the following properties:

  • class filtering based on the device class

  • capabilities allows based on available capabilities (note that calls to addCapability and removeCapability don't update this filter)

  • flags filters based on additional device properties, will be explained below

A simple filter might look like this:

/drivers/<driver_id>/driver.flow.compose.json
{
"actions": [
{
"id": "disco_mode",
"title": { "en": "Disco mode" },
"$filter": "class=socket"
}
]
}

Filters can match one of multiple values by separating values with a pipe (|), for example: "class=socket|light" will match devices with a device class of either socket or light.

capabilities and flags also support matching on multiple values by separating the values with a comma (,), for example "capabilities=onoff,dim" will match devices that have both onoff and dim capabilities.

Multiple properties can be filtered on by combining them in the $filter separated by an ampersand (&), for example this filter will match devices belonging to the basic driver with a socket or light device class and onoff and dim capabilities.

"$filter": "class=socket|light&capabilities=onoff,dim"

The following filters can be applied to Z-Wave devices:

Target only multi channel node devices:

"$filter": "flags=zwaveMultiChannel"

Target only root node devices:

"$filter": "flags=zwaveRoot"

The following filters can be applied to Zigbee devices:

Target only sub devices:

"$filter": "flags=zigbeeSubDevice"

Deprecating cards

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