Getting the device by its id takes a long time

Hi!

The code snippet below used inside my advanced flows takes 1-2 seconds to execute depending on the mood of the homey. It will take even longer when I add more lights to it.

The code snippet is a part of my code that cycles dim levels up to five steps depending on how many times I click the on-button. So dimming it the full five steps takes about 8-10 seconds to perform.

Any ideas of how to speed up this code snippet?

Tnx!

console.log("starting getdevice()")

const plafond11 = await Homey.devices.getDevice({$skipCache: false, id: '755de4f1-cc89-4b02-b845-636b9b06d052'});

const plafond12 = await Homey.devices.getDevice({$skipCache: false, id: '07b91ff5-17ee-4772-b76a-ddebcdc515d2'});

const plafond13 = await Homey.devices.getDevice({$skipCache: false, id: '3c541407-073e-49ce-91f1-923b4b36ed84'});

console.log("ended getdevice()")

Why are you skipping the cache? Perhaps that executes a cache rebuild.

It says $skipCache : false which, presumably, means it shouldn’t skip the cache.

yes, you are right :relaxed:

Yes, and to be certain I’ve tested with both false and true in case I misunderstood the argument.

There was no subjective difference in time. Maybe the cacheing is broken?

Are you testing the script in an Advanced Flow? From what I hear, advanced flow tests can run very slowly, but the actual flow itself (when run unattended) runs fine.

Hi Robert,

I’ve tested it both in AF and in real life clicking my on/off wireless switch. Testing it right now and each switch-click takes about one second to execute, even if I click e.g multiple times trying to speed up the dimming.

I have timed the other elements in my code and they execute more or less immediately.

If you’re sure the issue is with await Homey.devices.getDevice(), have you tried removing the $skipCache property entirely? So:

const plafond11 = await Homey.devices.getDevice({id: '755de4f1-cc89-4b02-b845-636b9b06d052'});

Yes, I have. That is how I started until I found that there was a cache option hoping that to be my solution.

I have even tried to store the return value in a global variable and use that instead, but this didn’t work either since the return value is converted into a text object.

If I could perform that entire block as an async and then await its completion it might become fast enough, but this is outside of my knowledge in homey scripting.

You (somewhat) can:

const plafonds = await Promise.all([
  Homey.devices.getDevice({$skipCache: false, id: '755de4f1-cc89-4b02-b845-636b9b06d052'}),
  Homey.devices.getDevice({$skipCache: false, id: '07b91ff5-17ee-4772-b76a-ddebcdc515d2'}),
  Homey.devices.getDevice({$skipCache: false, id: '3c541407-073e-49ce-91f1-923b4b36ed84'}),
])
1 Like

Tnx Robert!

That was enough to shorten the time to a resonable latency. It would have been nice to avoid it at all though :innocent:.

Btw, how do you tell the forum editor to format the code the way you do it?

You use the </> button on the toolbar for preformatted text. So paste in the text, select it and then click on the </> button.

1 Like

Tnx Adrian!

I thought that I already tried that option. Obviously I did something in error :blush:

1 Like

In case someone finds this topic and is interested. Here is my current full (test)code that now works quite well. It is triggered by a ‘on button was pressed’.

// Plafond Steps - DIM
// Dim (ikea)lights in 5 steps based on their ID's and global variable 'plafondDim'.
// Choose a plafondDim value between 5 and 100 to turn the lights on and 0 to turn them off.

// Specify the device ID for the specific lamps in the plafond. I wish that we could look up the ID's in the device advanced section.....

console.log("starting getdevice()")
const plafond = await Promise.all([
    Homey.devices.getDevice({$skipCache: false, id: '755de4f1-cc89-4b02-b845-636b9b06d052'}),
    Homey.devices.getDevice({$skipCache: false, id: '07b91ff5-17ee-4772-b76a-ddebcdc515d2'}),
    Homey.devices.getDevice({$skipCache: false, id: '3c541407-073e-49ce-91f1-923b4b36ed84'}),
]);
console.log("ended getdevice()");

const plafondDim = global.get('plafondDim');

if (plafondDim > 20)
{
    global.set('plafondDim', plafondDim - 20);
} else {
    global.set('plafondDim', 100);
}

// TODO: replace with a loop
plafond[0].setCapabilityValue('dim', plafondDim/100);
plafond[1].setCapabilityValue('dim', plafondDim/100);
plafond[2].setCapabilityValue('dim', plafondDim/100);

return plafondDim;
1 Like

Just an example of how you can use the device name instead of its ID

/*
 * In this script we turn a light on.
 */

// User input 
var myLight = "Plafond1"; /* enter the exact device name */
// User input end

// Get all devices
const devices = await Homey.devices.getDevices();

  // Loop over all devices
  for (const device of Object.values(devices)) {
  if (device.name == myLight) {
 
    // If this device is a light (class)
    // Or this is a 'What's plugged in?'-light (virtualClass)
    if (device.class === 'light' || device.virtualClass === 'light' || device.class == 'button') {
    log(`\nTurning '${device.name}' on...`);

    // Turn the light on by setting the capability `onoff` to `true`
    await device.setCapabilityValue('onoff', true)
      .then(() => log('OK'))
      .catch(error => log(`Error:`, error));
    }
  }
}
return(true);
1 Like

just in addtion cause I don’t see the buildin filter too often and hope it is permanently optimized in comparison to fetch all devices and loop through.

const devices = await Homey.devices.getDevices({ filter: {name: 'Droide'} });
Object.values(devices).forEach(device => {
log(device.name + ':', device.id)
});
1 Like

Hi Peter,

For single occasional runs this should probably be nice. However, my concern is that you need to fetch all of the registered/connected devices and then filter out the ones you want to perform an operation on each time you run the script.

As I mentioned in my first post those three device fetches took between 1-2 seconds to complete and for a script that reacts on multiple button presses this was therefor not working well.

I will try and see how long getdevices() takes using your suggested way though. Maybe it does some magic in the background that might not take as long to complete…?

Hi Joka,

Interesting. I’ll try this out as well and time it the next time I can sit down and experiment with my lights.

I was told by my family that they didn’t like it when the lights start to erratically flash for 15 minutes before finding the bug. I was also able at times to hang the script engine so the homey essentially stopped working. So I better do script tests when I’m home alone :innocent:.

I like performace tests:

Bulid a view setup flows:

const device_name = (typeof args[0] === 'string')
? args[0]
: 'dummy';

let device_id
const devices = await Homey.devices.getDevices({ filter: {name: device_name} });
_.forEach(devices, device => {
log(device.name + ':', device.id)
device_id = device.id
});

return device_id

Be carefull, you should start the flow from your mobile to get a real life stop time.

Play with the filter, in my test I found out that the filter is 8-10 times faster in compression to collect all devices and loop through. Depends on the amount of devices of course.

It takes 0.09 sec to identify the id by name of the device.

2 Likes

Wow, that makes a huge difference, it’s around 1sec faster than looping over all devices. (I have 281 devices).
Thanks for digging into this.

// run 1
TurnLightOn start 2022-07-09T12:59:25.988Zs
TurnLightOn_FilterDevices runtime: 2022-07-09T12:59:26.517Zs
471ms
TurnLightOn_LoopOverDevices runtime: 2022-07-09T12:59:27.219Zs
1769ms

// run 2
TurnLightOn start 2022-07-09T13:12:29.312Zs
TurnLightOn_FilterDevices runtime: 2022-07-09T13:12:29.929Zs
617ms
TurnLightOn_LoopOverDevices runtime:2022-07-09T13:12:30.813Zs
1501ms

Screenshot from 2022-07-09 15-31-25

Oh, and, you can start a flow like this too:

Screenshot from 2022-07-09 12-40-21

1 Like