SetCapabilityValue

Hi,

I’m trying to create a script that turns on all lights in a zone with a delay of x milliseconds between each light. I use one dimmer pr light (still cheaper than DALI).
I then noticed that when calling the setCapabilityValue method, it only updates once the script returns, thus, all lights turn on at the same time.

Is there a way to actually execute the setCapabilityValue prior to script completion?

PS: The reason for this script is because the delay in a standard flow card is set to seconds as it’s lowest input (integer). I would like to go bellow that.

My code looks like this:

// This script turns on all lights in the Garden zone in a cascade with
// the time of delayInMilliseconds in between each light.
var delayInMilliseconds = 250;
let devices = await Homey.devices.getDevices();
let zones = await Homey.zones.getZones();

for(var i in zones)
{
    if(zones[i].name == 'Garden')
    {
        var gardenId = zones[i];
        console.log('Garden found in id: ', zones[i].id);
    }  
}

for(var i in devices)
{
    if(devices[i].zone == gardenId.id)
    {
        console.log(devices[i].name);
        devices[i].setCapabilityValue('onoff', true);
        sleep(delayInMilliseconds);
    }
} 
return true;

function sleep(ms) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > ms){
      break;
    }
  }
}

setCapabilityValue is asynchronous, so you have to wait for it to complete before continuing the loop:

await devices[i].setCapabilityValue('onoff', true);

Also, your sleep function won’t work (properly) because it blocks the event loop. You need to create an async version for it:

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms))
}
// to use, you need to use `await` as well:
// await sleep(delayInMilliseconds);

And lastly: if you’re getting syntax errors regarding to use of await, you need to wrap your entire script in an IIFE that marks the top-level function as async, allowing you to use async within its block:

void async function() {
  ... your script here ...
}();
1 Like

Moved to developers.

1 Like