Setting Logic Variable by HomeyScript

Very nice, now i don’t need to copy/paste al those ID’s. Here an example how i get all those Id’s at once in a script;

var varName = ['varName0','varName1','varName2'];
var logicId = []
var count = 0;

while(count <= varName.length -1)
{
var Logic = await Homey.logic.getVariables();
let idArr = Object.entries(Logic);
let filtered = idArr.filter(([key, value]) => value.name==varName[count]);
let [ [ ,{ id: varNameId }]] = filtered;
logicId.splice(count, 1,varNameId);
count++
}
1 Like

Here I have created two functions which you can add to your scripts.

//Name of Logic Variable
var name = "TVProgramma";

//Read Logic Var
var value = await ReadLogicVar(name);
console.log("The parameter '"+name+"' has a value '"+value+"'");

//Write Logic Var
var new_value = "NOS Journaal";
await WriteLogicVar(name,new_value);

async function ReadLogicVar(name){
  let Logic = await Homey.logic.getVariables();
  let idArr = Object.entries(Logic);
  let filtered = idArr.filter(([key,value]) => value.name==name);
  let [[,{id:varID}]] = filtered;

  var varArr = await Homey.logic.getVariable({id:varID});

  return varArr.value;
}

async function WriteLogicVar(name,value){
  let Logic = await Homey.logic.getVariables();
  let idArr = Object.entries(Logic);
  let filtered = idArr.filter(([key,value]) => value.name==name);
  let [[,{id:varID}]] = filtered;
  
  var varArr = await Homey.logic.getVariable({id:varID});

  if (typeof(value) == varArr.type){
    await Homey.logic.updateVariable({id:varID,variable:{value:value}})
    //console.log("Value has been updated")
    return true;
  }
  else{
    console.log("New value has the wrong type! Expected type is '"+varArr.type+"', not '"+typeof(value)+"'. Value has NOT been updated!")
    return false;
  }
}
4 Likes

ReadLogicVar and WriteLogicVar functions seems very useful to me as has been using JSONs as arguments earlier, but as many data needed also in trends decided to recode current approach with these funtions

Can someone advice how to make these functions “global”, so all of my codes/Scripts would be able to use them w/o repeating same in each one?

You can’t.

Okay, you can, with a hack:

// homeyscript-a.js
_.myFunc = function() { ... };

// homeyscript-b.js
_.myFunc();

However, this requires homeyscript-a.js to be run first, otherwise _.myFunc() doesn’t exist.

It’s also a hack because it changes the _ object (which is the Lodash module that is made available to every script).

Excelent.

Sufficient to run 2nd one only once at star-up of Homey?

The first one (which declares the function and makes it available to other scripts) can be run once at startup.

Got bit mixed results:
This is working fine (i.e. value changed as planned:

_.myWriteLogicVar(“Test_Var”,“abcd”)

where (as conbination from above messages):

//myWriteLogicVar

_.myWriteLogicVar = async function (name,value) {

let Logic = await Homey.logic.getVariables();
let idArr = Object.entries(Logic);
let filtered = idArr.filter(([key,value]) => value.name==name);
let [[,{id:varID}]] = filtered;

var varArr = await Homey.logic.getVariable({id:varID});

if (typeof(value) == varArr.type){
await Homey.logic.updateVariable({id:varID,variable:{value:value}})
//console.log(“Value has been updated”)
return true;
}
else{
console.log(“New value has the wrong type! Expected type is '”+varArr.type+“', not '”+typeof(value)+“'. Value has NOT been updated!”)
return false;
}
}

But having issue with reading-test:

let value = _.myReadLogicVar(“Test_Var”)
console.log(“value :”, value)

and (with similar mods):

//myReadLogicVar

_.myReadLogicVar = async function (name){

let Logic = await Homey.logic.getVariables();
let idArr = Object.entries(Logic);
let filtered = idArr.filter(([key,value]) => value.name==name);
let [[,{id:varID}]] = filtered;

var varArr = await Homey.logic.getVariable({id:varID});

return varArr.value;
}

but getting only ('-marks added to show full message)):

value : Promise { ‘<pending’> }

Any quickfix?

Since myReadLogicVar is marked async, it will always return a promise, which means you have to use await to retrieve the value:

let value = await _.myReadLogicVar("Test_Var");
console.log("value :", value)

Thanks, made the trick… now both works like a dream :slight_smile:

Would be also great to automatize even creation of variables - e.g. when creating identical “environment”.

i.e. Any command I could use in script to create variable named based on text-combo like “def1”&“def2”&“def3”.

Just is case some other newbees (like me) around, made one also for sensors (as need those values as well in several scripts), combined above advice and Homey example-script:

_.myReadSensor = async function (sensorName, capabilityName) {
const devices = await Homey.devices.getDevices();

for (const device of Object.values(devices)) {
if (!device.capabilitiesObj || device.class !== ‘sensor’) continue;

if (device.name === sensorName) {
  const sensorCapability = device.capabilitiesObj[capabilityName];
  if (sensorCapability) {
    return sensorCapability.value;
  } else {
    return null; 
  }
}

}
return null;
}

1 Like

To get a variable you can use the filter property of getVariables().

_.myReadLogicVar = async function ( name ) {
  return Homey.logic.getVariables( { filter: { name } } ).then( itm => Object.values( itm )[0] );
};

The same goes for getDevices().

_.myReadSensor = async function ( sensorName, capabilityName ) {
  return Homey.devices.getDevices( { filter: { name: sensorName, class: 'sensor' } } )
    .then( itm => Object.values( itm )[0] )
    .then( itm => itm.capabilitiesObj?.[capabilityName]?.value ?? null );
};
5 Likes

Looks great, need to test soonest :slight_smile:

Would it be possible also to simplify write commands with filtering, pls ?

Sure. Note that you don’t need the type checking, because Homey will throw an ‘invalid_value_type’ error. Though you can catch it if you want to adjust your scripts behavior in that case.

_.myWriteLogicVar = async function ( name, value ) {
  const thevar = await _.myReadLogicVar( name );
  return Homey.logic.updateVariable( {
    id: thevar.id,
    variable: { value },
  } );
};

Use it like this:

await _.myWriteLogicVar( 'Test stuff', 123 );
2 Likes