Developer Web API Playground - Notes of geeky oneliners

For the developers and geeks that want to investigate their Homey’s config.

Run from Homey Developer Tools

I write this to remember what I did but also to inspire others that I know are better JS developer that can do more magic. (and hope they share to inspire!)

WARNING: Be Careful! you can ruïne your config by deleting the wrong objects from there! Only use it if you know what you are doing !

// Get Trigger counts for Flows
Homey.flow.getFlows().then(f => Object.values(f).reduce((r,b)=>Object.assign(r, {[b.name]:b.triggerCount}), {}));

// Get broken flows
// Run and search for the result true
Homey.flow.getFlows().then(f => Object.values(f).reduce((r,b)=>Object.assign(r, {[b.name]:b.broken}), {}));

// Or Get broken flows
// Run and only the broken flows are returned ;-)
Homey.flow.getFlows().then(f => Object.values(f).reduce((r,b)=> Object.assign(r, b.broken ? {[b.name]:b.broken} : ''), {}) );

// Search for disabled flows: by Le_Cactus
Homey.flow.getFlows().then(f => Object.values(f).reduce((r,b)=>Object.assign(r, {[b.name]:b.enabled}), {}));

// Get All installed Apps with versions
Homey.apps.getApps().then(f => Object.values(f).reduce((r,b)=>Object.assign(r, 
{[b.name]:b.version}), {}));

// Get Available Updates for Apps in AppStore
Homey.apps.getApps().then(f => Object.values(f).reduce((r,b)=>Object.assign(r, {[b.name]:b.updateAvailable}), {}));

// Get Devices Names and IDs for Towanda
Homey.devices.getDevices().then(f => Object.values(f).reduce((r,b)=>Object.assign(r,{[b.name]:b.id}), {}));

// List Zone names and parent
Homey.zones.getZones().then(f => Object.values(f).reduce((r,b)=>Object.assign(r, {[b.name]:b.parent}), {}));;

// Get list all Apps with Auto Update setting
Homey.apps.getApps().then(f => Object.values(f).reduce((r,b)=>Object.assign(r, {[b.name]:b.autoupdate}), {}));

// Get list Auto Update list disabled
Homey.apps.getApps().then(f => Object.values(f).reduce((r,b)=>Object.assign(r, !b.autoupdate ? {[b.name]:b.autoupdate} : '' ), {}));

// Get list Auto Update list enabled
Homey.apps.getApps().then(f => Object.values(f).reduce((r,b)=>Object.assign(r, b.autoupdate ? {[b.name]:b.autoupdate} : '' ), {}));

// Disable Auto Update on All Apps
Homey.apps.getApps().then(f => Object.values(f).reduce((r,b)=>Object.assign(r, b.autoupdate ? Homey.apps.updateApp( { id : b.id  , "app" : { "autoupdate" : false }} ) : {[b.name]:b.autoupdate}), {}));

// Disable All Apps
// Homey.apps.getApps().then(f => Object.values(f).reduce((r,b)=>Object.assign(r, b.enabled ? Homey.apps.disableApp( { id : b.id} ) : {[b.name]:b.enabled}), {}));

// Enable All Apps
Homey.apps.getApps().then(f => Object.values(f).reduce((r,b)=>Object.assign(r, !b.enabled ? Homey.apps.enableApp( { id : b.id} ) : {[b.name]:b.enabled}), {}));

// Some ZigBee Queries Online devices:
// online receiveWhenIdle name modelId type 
Homey.zigBee.getState().then(f => Object.values(f.nodes).reduce((r,b)=> Object.assign(r, b.online ? {[b.name]:b.type} : ''), {}) );
// receiveWhenIdle  => name 
Homey.zigBee.getState().then(f => Object.values(f.nodes).reduce((r,b)=> Object.assign(r, b.receiveWhenIdle ? {[b.name]:b.type} : ''), {}) );
// receiveWhenIdle  => modelId
Homey.zigBee.getState().then(f => Object.values(f.nodes).reduce((r,b)=> Object.assign(r, b.receiveWhenIdle ? {[b.modelId ]:b.type} : ''), {}) );
9 Likes

Cool, thanks for sharing! For the new apps example, is it possible to exclude the ones where there are no updates? (NULL)

Think this would be possible then to set up in Homeyscript to trigger eg. every day(?).

1 Like

Thanks, very usefull!

Used this one in search for disabled flows:

Homey.flow.getFlows().then(f => Object.values(f).reduce((r,b)=>Object.assign(r, {[b.name]:b.enabled}), {}));

1 Like

//Get SDK version of Apps - SDK v2 and higher needed for Homey firmware 5.x
Homey.apps.getApps().then(f => Object.values(f).reduce((r,b)=>Object.assign(r, {[b.name]:b.sdk}), {}));

2 Likes

Get all devices in json from a specific app:

var promise = 

Homey.devices.getDevices()
.then(f => {
   return Object.values(f).filter((device) => device.driverUri === 'homey:app:com.mi.flora');
  });

Promise.resolve(promise).then(devices => console.log(JSON.stringify(devices)));
1 Like

This can be shortened to promise.then(…) :slight_smile:

Or this:

Homey.devices.getDevices()
.then(f => {
   return Object.values(f).filter((device) => device.driverUri === 'homey:app:com.mi.flora');
})
.then(devices => console.log(JSON.stringify(devices)));
3 Likes

Thanks! I was looking for this, but now I found it :wink:

I would like to add one of my favorites. It’s not a one liner but still useful.
This script lists all unused flows along with its folder path.

However be carefull if you want to use this script to remove all unused flows. Flows may be used from HomeyScript or set as favorite. This script only list flows that has a ‘Start as flow’ trigger and for which it can’t find a flow with a flowcard to trigger.

'use strict';
const folders = await Homey.flow.getFlowFolders(); 
const flowsDic = await Homey.flow.getFlows();
const flows = Object.values(flowsDic)
const triggers = flows.map(f => f.actions.filter(a => a.uri === 'homey:manager:flow' && 
                                                      a.id === 'programmatic_trigger').map(a => a.args.flow)).flat()
function getFolder(id) {
  if (folders[id]) {
    if (folders[id].parent) {
      return `${getFolder(folders[id].parent)} > "${folders[id].name}"`
    }
    return `"${folders[id].name}"`
  }
  return '';
}
log(`Searching in ${flows.length} flows\n---------------------\n`)
flows.filter(f => f.trigger.uri === 'homey:manager:flow' && 
                  f.trigger.id === 'programmatic_trigger' &&  
                  !triggers.find(t => t.id === f.id)
            ).forEach(flow => log(`${getFolder(flow.folder)} > ${flow.name}`));
2 Likes

Has anyone a hint how to get the device onoff history by cli?
Preferrably of all onoff devices at once :grin:

Check if your Apps are SDK 2 and if they have Updates available

// Search and display app SDk version. 3 is OK, 2 is deprecated
Homey.apps.getApps().then(f => Object.values(f).reduce((r,b)=>Object.assign(r,b.sdk == 2 ? {[b.name]:b.updateAvailable} : ''), {}));


// Some other simple one-liners
// Get All installed Apps with versions
Homey.apps.getApps().then(f => Object.values(f).reduce((r,b)=>Object.assign(r, {[b.name]:b.version}), {}));

// Get Available Updates for Apps in AppStore
Homey.apps.getApps().then(f => Object.values(f).reduce((r,b)=>Object.assign(r, {[b.name]:b.updateAvailable}), {}));

// Get list Apps on SDK 2 list disabled
Homey.apps.getApps().then(f => Object.values(f).reduce((r,b)=>Object.assign(r, b.sdk === 2 ? {[b.name]:b.sdk} : '' ), {}));
6 Likes

How are you guys using await in the Web API playground? I’m just getting await is only valid in async functions and the top level bodies of modules

Sounds as if you are using arrow functions. Define as async, then you can use await inside.

myHandler( async () =>{
await … ();
});

Wrap your code with an IIFE:

void async function() {
  await ...;
}();
1 Like

Awesome, that worked @robertklep !

void async function() {
  const devices = await Homey.devices.getDevices(); 
  for (const device of Object.values(devices)) {
    console.log(device.name);
  }
}();
2 Likes