The Flow Editor is where users create Flows for their Homey. As a developer, you can add new functionality from your app to the Flow Editor 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
. These are things that must be true, for the flow to continue. For example it is raining, or the vacuum cleaner is cleaning. - Cards in the ...then column are called
actions
. These are fired 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.json
.
If your app contains one or more drivers, please note that most device classes already have their own flow cards. So most of the time it's not necessary to create them yourself.
/app.json
"id": "com.weather.example",
...
"flow": {
"triggers": [
{
"id": "rain_start",
"title": {
"en": "It starts raining"
},
"hint": {
"en": "When it will start raining more than 0.1 mm/h."
},
},
{
"id": "rain_stop",
"title": {
"en": "It stops raining"
},
"hint": {
"en": "When it stops raining."
},
}
],
"conditions": [
{
"id": "is_raining",
"title": {
"en": "It !{{is|isn't}} raining"
},
"hint": {
"en": "This Flow will continue if it is/is not currently raining more than 0.1 mm/h."
}
},
{
"id": "raining_in",
"title": {
"en": "It's going to rain in..."
},
"titleFormatted": {
"en": "It !{{is|isn't}} going to rain in [[when]]"
},
"hint": {
"en": "This Flow will continue 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"
}
}
]
}
]
}
],
"actions": [
{
"id": "stop_raining",
"title": {
"en": "Make it stop raining. Haha."
}
}
]
}
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.
{
"id": "rain_start",
"title": {
"en": "It starts raining"
},
"hint": {
"en": "When it starts raining more than 0.1 mm/h."
},
},
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.
{
"titleFormatted": {
"en": "Send a notification to [[person]]"
}
}
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.
{
"titleFormatted": {
"en": "This Flow !{{is|is not}} inverted"
}
}
Triggering a Flow
To fire a trigger, run the following code from anywhere in your app:
/app.js
let rainStartTrigger = this.homey.flow.getTriggerCard('rain_start');
rainStartTrigger.trigger()
.catch(this.error)
.then(this.log);
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.
Listening for events
In your app, you should register a run
listener for each Flow card. Conditions and Actions should always do this, and Triggers only when they have one or more Arguments.
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, the Flow stops executing as well.
/app.js
let rainingCondition = this.homey.flow.getConditionCard('is_raining');
rainingCondition.registerRunListener(async (args, state) => {
let raining = rain.isRaining(); // true or false
return raining;
});
let stopRainingAction = this.homey.flow.getActionCard('stop_raining');
stopRainingAction.registerRunListener(async (args, state) => {
let isStopped = rain.stop(); // true or false
return isStopped;
});
Deprecating cards
Sometimes a Flow card 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 Flow card in /app.json
. It will still work, but won't show up anymore in the 'Add Card' list.