Alright, alright, the title is a bit of a click-bait.
BUT, I was able to create a Homey Script that generates triggers. The script generates an advanced Flow, which in turn has generates trigger cards.
This is where my question started
I think it’s not the cleanest way to work, but I did reach my goal. And that was to generate a triggers for devices. This way, if you have about 15 settings, you don’t have to manually click and create the flow. Why? If I have 15 scenes and I change my logic I might have to recreate 15 scenes * 4 triggers = 60 cards… Yeah, no way.
This way I can rethink my logic and re-generate the whole flow. I would still have preferred to have this all in HS but hey, it’s a start.
This is the generated flow:
And this is part of 3 Homey Scripts for the actions.
let settings = await Homey.apps.getApp({ id: 'com.athom.homeyscript' })
.then(homeyScript => { return homeyScript.apiPost('script/11e33a58-bc05-4110-993e-da8759dec050/run'); });
settings = settings.returns;
const cardDistXBase = 0;
const cardDistX = 400;
const cardDistYBase = 100;
const cardDistY = 120;
const scriptID = '58fbd2be-15ac-4cac-81ce-61a8ff9064c5';
const globalSettings = settings['global'];
let flowObject = {
advancedflow: {
"name": "motion_alarm_test",
"enabled": false,
"cards": {}
}
}
const addMotionTriggerCard = (sceneIndex, sceneKey, scene, sensorID, command) => {
flowObject.advancedflow.cards[`${sceneIndex}-${sceneKey.toLowerCase().replaceAll(' ', '-')}-${sensorID}-${command}`] = {
ownerUri: `homey:device:${sensorID}`,
id: `homey:device:${sensorID}:alarm_motion_${(command === 'on').toString()}`,
type: 'trigger',
x: cardDistXBase + (colIndex * cardDistX),
y: cardDistYBase + (rowIndex * cardDistY),
outputSuccess: [`${sceneIndex}-${sceneKey.toLowerCase().replaceAll(' ', '-')}-homeyscript-${command}`]
}
}
const addMotionThenCardScript = (sceneIndex, sceneKey, scene, command) => {
flowObject.advancedflow.cards[`${sceneIndex}-${sceneKey.toLowerCase().replaceAll(' ', '-')}-homeyscript-${command}`] = {
ownerUri: 'homey:app:com.athom.homeyscript',
id: 'homey:app:com.athom.homeyscript:runWithArg',
args: {
script: {
id: scriptID,
name: 'light-motion-sensors'
},
argument: `{"scene":"${sceneKey}","command":"${command}"}`
},
type: 'action',
x: cardDistXBase + (colIndex * cardDistX),
y: cardDistYBase + (rowIndex * cardDistY),
}
}
const addButtonTriggerCard = (sceneIndex, sceneKey, scene, deviceID, button) => {
let buttonID = null;
switch (button) {
case 's2':
buttonID = '26'
break;
case 's1':
default:
buttonID = '16'
break;
}
flowObject.advancedflow.cards[`${sceneIndex}-${sceneKey.toLowerCase().replaceAll(' ', '-')}-${deviceID}-${button}`] = {
ownerUri: `homey:device:${deviceID}`,
id: `homey:device:${deviceID}:FGD-212_momentary`,
args: { scene: buttonID },
type: 'trigger',
x: cardDistXBase + (colIndex * cardDistX),
y: cardDistYBase + (rowIndex * cardDistY),
outputSuccess: [`${sceneIndex}-${sceneKey.toLowerCase().replaceAll(' ', '-')}-${deviceID}-is-on`]
}
}
const addButtonConditionCard = (sceneIndex, sceneKey, scene, deviceID, command) => {
flowObject.advancedflow.cards[`${sceneIndex}-${sceneKey.toLowerCase().replaceAll(' ', '-')}-${deviceID}-is-on`] = {
ownerUri: `homey:device:${deviceID}`,
id: `homey:device:${deviceID}:on`,
type: 'condition',
x: cardDistXBase + (colIndex * cardDistX),
y: cardDistYBase + (rowIndex * cardDistY),
outputFalse: [`${sceneIndex}-${sceneKey.toLowerCase().replaceAll(' ', '-')}-homeyscript-${command}`]
}
}
const addMotionFlows = (sceneIndex, sceneKey, scene, command) => {
let sensorCount = 0;
for (const [sensorKey, sensorID] of Object.entries(scene.multisensors)) {
addMotionTriggerCard(sceneIndex, sceneKey, scene, sensorID, command)
if (sensorCount === scene.multisensors.length - 1) {
colIndex++;
addMotionThenCardScript(sceneIndex, sceneKey, scene, command)
}
rowIndex++;
sensorCount++;
}
}
const addButtonFlows = (sceneIndex, sceneKey, scene, command) => {
let lightCount = 0;
for (const [lightKey, deviceID] of Object.entries(scene.lights)) {
addButtonTriggerCard(sceneIndex, sceneKey, scene, deviceID, 's1')
rowIndex++;
addButtonTriggerCard(sceneIndex, sceneKey, scene, deviceID, 's2')
colIndex++;
addButtonConditionCard (sceneIndex, sceneKey, scene, deviceID, command);
if (lightCount === scene.multisensors.length - 1) {
colIndex++;
addMotionThenCardScript(sceneIndex, sceneKey, scene, command)
}
colIndex--;
rowIndex++;
lightCount++;
}
}
let sceneIndex = 0;
let rowIndex = 0;
let colIndex = 0;
const createCards = () => {
for (const [sceneKey, scene] of Object.entries(settings.scenes)) {
colIndex = 0;
if (scene.enabled || true) {
addMotionFlows(sceneIndex, sceneKey, scene, 'on')
}
sceneIndex++;
}
sceneIndex = 0;
rowIndex = 0;
for (const [sceneKey, scene] of Object.entries(settings.scenes)) {
colIndex = 2;
if (scene.enabled || true) {
addMotionFlows(sceneIndex, sceneKey, scene, 'off')
}
sceneIndex++;
}
sceneIndex = 0;
rowIndex = 0;
for (const [sceneKey, scene] of Object.entries(settings.scenes)) {
colIndex = 4;
if (scene.enabled || true) {
addButtonFlows(sceneIndex, sceneKey, scene, 'off_by_user')
}
sceneIndex++;
}
}
createCards();
let advancedFlowId = null;
const flows = await Homey.flow.getAdvancedFlows()
for (const flow of Object.values(flows)) {
if (flow.name === flowObject.advancedflow.name) {
advancedFlowId = flow.id;
}
}
let result = false;
if (advancedFlowId) {
flowObject.id = advancedFlowId;
result = await Homey.flow.updateAdvancedFlow(flowObject)
} else {
result = await Homey.flow.createAdvancedFlow(flowObject)
}
Yes, it’s messy as hell. But that’s best I could do in my lunch-break
I’ll clean up the code later.
The input is this script:
return {
"global": {
"enabledID": "48726aca-1784-4328-9fd0-2ee6b9d33e4e" // virtual device to enable/disable global motion sensor use
},
"scenes": {
"Keuken": {
"enabled": true,
"multisensors": [
"9d4348de-c1c3-4341-a6e7-7f33c20b63dd",//"keuken multisensor",
"319d966f-638e-44b0-9f76-7610ced72ee9",//"bijkeuken multisensor"
],
"min_lux": 0,
"max_lux": 20,
"lights": [
"94254ea1-4e87-4763-991d-6eedc52a36aa",//"keuken lamp",
"433639e7-bc41-4a2a-a701-eb383da1ea19",//"bijkeuken lamp"
],
"dim_min": 1,
"dim_max": 10,
"on_time": 1,
"debouce_time": 1,
},
"Gang Beneden": {
"enabled": true,
"multisensors": [
"f996edfb-06af-4f14-be03-fd9288645ded",//"gang beneden multisensor"// TODO: add device ID
],
"min_lux": 0,
"max_lux": 10,
"lights": [
"06b25af3-c93e-46d6-b1d5-fa7e6a0f18ee",//"gang beneden lamp"// TODO: add device ID
],
"dim_min": 1,
"dim_max": 15,
"on_time": 1,
"debouce_time": 1,
},
"Gang Boven": {
"enabled": false,
"multisensors": [
"5823806e-2fd7-4eae-b88f-6e4ea5957f95",//"gang boven multisensor voor",// TODO: add device ID
],
"min_lux": 0,
"max_lux": 10,
"lights": [
"ce713301-f469-484c-b455-196c20063dab",//"gang boven lamp"// TODO: add device ID
],
"dim_min": 1,
"dim_max": 3,
"on_time": 1,
"debouce_time": 1,
},
"Toilet": {
"enabled": true,
"multisensors": [
"83e6b629-076c-4be6-b2d2-a633374f9b97",//"toilet multisensor"// TODO: add device ID
],
"min_lux": 0,
"max_lux": 20,
"lights": [
"4d8f4ec9-4540-411e-ad94-5eeaa689420f",//"gang boven lamp"// TODO: add device ID
],
"dim_min": 1,
"dim_max": 5,
"on_time": 10,
"debouce_time": 1,
}
}
}