Change ALL variables at once

Is there a way to change all variables at the same time without creating a flow with all of them on there, for example, I have A TON of variables and I’m constantly adding and deleting them. My variables, weather number, yes/no, or text pretty much control everything! I have a “KILL SWITCH” that sets all number variables to 0, all yes/no to no and all text to “-” as well as a lot of other “modes” that change other variables

The problem is, every time I create or delete a variable, I have to update my “Kill Switch” and all other affiliated flows that change multiple variables!

Use Homey Script?

Hi Luigi,indeed you can use HomeyScript,

some examples:

// Update the variable, basic
          oResult = await Homey.logic.updateVariable({
            id: sID,
            variable: { value: typedValue }
          });
allVars = await Homey.logic.getVariables();  // all variables

iterate over allVars by VarID and update all vars by ID with updateVariable with typed(!) values.

an extended example to set and get variables and tags

/*
 * ATTENTION ::::: start with bUpdateTags = false :::::
 * -!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!
 * HomeyScript to save variables to tags and get values from tags
 *
 * Current date: 2025-09-13
 *
 * Author: Ruurd van der Noord
 * Contributions: Help from Perplexity AI
 */

// Begin Arguments
// Default values if args[0] is not a string
const input = typeof args[0] === 'string' ? args[0] : 'bUpdateTags=false;bCheckTags=false;bDeleteTags=false';

// Parse the input and initialize FLAGS
const oFlags = Object.fromEntries(
  input.split(';').map(arg => arg.split('=').map((bValue, iNum) => iNum === 1 ? isBool(bValue) : bValue))
);

// Assign final values as Constants
const bUpdateTags = oFlags['bUpdateTags'] || false;
const bDeleteTags = oFlags['bDeleteTags'] || false;
const bCheckTags = oFlags['bCheckTags'] || false;

// Determine action based on flags
if (bCheckTags) {
  console.log("Checking tags...\n\n");
  // Code to check tags
} else if (bUpdateTags) {
  console.log("Updating tags...\n\n");
  // Code to update tags
} else if (bDeleteTags) {
  console.log("Deleting tags...\n\n");
  // Code to delete tags
  bUpdate = false; // Set bUpdate to false only when deleting
} else {
  console.log("No TAG action specified...\n\n");
}
// End Arguments

let aError = []; // array to push ERRORS in
const oVarHomeyAll = Object.values(await Homey.logic.getVariables());
const iVarHomeyAllLen = Object.keys(oVarHomeyAll).length;

// Filter out CONSTS (with a second character is an underscore)
const aValidConsts = filterVariables(oVarHomeyAll, true);
const iValidConstsLen = aValidConsts.length;

// Filter out variables not a CONST (without a second character is an underscore)
const aValidVars = filterVariables(oVarHomeyAll, false);
const iValidVarsLen = aValidVars.length;

const s_NotFound = "!!!!!!"; // Placeholder for not found variables and values

const var_known =
  [ // all Homey Variables
    { name: `Some name`, id: 'ID', type: `boolean`, _class: `Proprietary class`, _value: 'Some proprietary value', value: 'the TYPED value' },  // FLAG:b=OK:boolean
  ] // end var_known (201)

//-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!
//-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!
//                      END INITIATE
//-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!
//-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!
//-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!
//-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!
//                    BEGIN FUNCTIONS
//-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!
//-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!

function isBool(sValue) {
  if (typeof sValue !== 'string') {
    // Not a string or boolean - convert to string or handle error
    sValue = String(sValue);
  }
  const sNormalized = sValue.trim().toLowerCase();

  const aTruthyValues = ['true', 'yes', 'on', '1', '✓', '✔'];
  const aFalsyValues = ['false', 'no', 'off', '0', '✗', '✘'];

  if (aTruthyValues.includes(sNormalized)) return true;
  if (aFalsyValues.includes(sNormalized)) return false;

  // Unknown value: notify and treat as false for safety
  sendPush("ZonneschermA-NEER3 SCRIPT ERROR 1");
  return false;
}

// Function to filter variables based on whether they are Constants
function filterVariables(oVarHomeyAll, isConst) {
  return Object.values(oVarHomeyAll).filter(oVar =>
    oVar && typeof oVar === 'object' && 'name' in oVar && 'value' in oVar &&
    (isConst ? oVar.name[1] === '_' : oVar.name[1] !== '_')
  );
}

// Function to check Hungarian notation compliance
function checkHungarianNotation(oVariable) {
  const cFirstChar = oVariable.name.charAt(0);
  const sExpectedPrefix = (oVariable.type === 'number') ? 'i' :
    (oVariable.type === 'string') ? 's' : 'b';
  return cFirstChar === sExpectedPrefix;
}

async function getValidArray() {
  try {
    const validVariables1 = [];
    if (oVarHomeyAll && typeof oVarHomeyAll === 'object') {
      for (const key in oVarHomeyAll) {
        const oVar = oVarHomeyAll[key];
        if (oVar && typeof oVar === 'object' && 'name' in oVar && 'value' in oVar) {
          validVariables1.push({ name: oVar.name, value: oVar.value, id: oVar.id });
        } else {
          aError.push(`Invalid variable structure at key ${key}: ${oVar}`);
          console.error(`Invalid variable structure at key ${key}:`, oVar); // , oVar
        }
      }
    } else {
      aError.push("Error: oVarHomeyAll is not a valid object.");
      console.error("Error: oVarHomeyAll is not a valid object.");
    }
    return validVariables1;
  } catch (oError) {
    aError.push(`An error occurred while fetching variables: ${oError}`);
    console.error("An error occurred while fetching variables:", oError);
  }
}

// Function to get variable value by name
function getVarValueByName(sName, oVariables) {
  const oVariable = Object.values(oVariables).find(({ name }) => name === sName);
  if (!oVariable) {
    log('add: ' + sName);
    aError.push(`Variable with name "${sName}" not found.`);
    throw new Error(`Variable with name "${sName}" not found.`);
  }
  return oVariable.value;
}

// Helper function to format values based on their type
function formatValue(uValue) {
  if (typeof uValue === 'number' || typeof uValue === 'boolean') {
    return uValue;
  } else if (typeof uValue === 'string') {
    return uValue.length <= 20 ? `\`${uValue}\`` : '`>20`';
  }
  return '';
}

// Initialize output variable for logging
let sOutput = '\nconst aConstNames = // *CONST NAMES*\n[\n'; // in global scope ... Begin *CONST NAMES*

async function setAndGetTags(allConstants) {
  const iTotalConstants = allConstants.length; // Total number of oConstants
  let currentIndex = 0; // Index for tracking the current oConstant
  allConstants.sort((a, b) => a.name.localeCompare(b.name)); // Sort oConstants alphabetically by name

  try {
    log(`let allCONST  =\n[`); // Log the start of the oConstant list

    // Iterate through each oConstant in the provided array
    for (const oConstant of allConstants) {
      currentIndex++; // Increment the index for each variable

      // Validate oConstant properties
      if (!oConstant || !oConstant.name || !oConstant.id || !oConstant.type) {
        aError.push(`Invalid variable at index ${currentIndex}: ${oConstant}`);
        console.error(`Invalid variable at index ${currentIndex}:`, oConstant); // Log error for invalid variable
        continue; // Skip this iteration if the variable is invalid
      }

      // Set or delete tags based on the flags
      if (bUpdateTags) {
        await global.set(oConstant.name, oConstant.value); // Set the tag value
      } else if (bDeleteTags) {
        await global.set(oConstant.name, null); // Delete the tag value
      }

      const oKnownVariable = var_known.find(({ name }) => name === oConstant.name);
      // log(`NAME... ${oKnownVariable.name}`);
      //const oNewVar = oVarHomeyAll.find({ name: oConstant.name });

      // Check if oKnownVariable is found in known variables
      if (!oKnownVariable) {
        aError.push(`No known variable found for: ${oConstant.name} - ${oConstant.id}`);
        // console.error(`No known variable found for: ${oConstant.name}`); // Log error for unknown variable
      }

      // Check Hungarian notation validity for the current variable
      const isValidNotation = checkHungarianNotation(oConstant);
      const sFlagComment = `// FLAG:${oConstant.name.charAt(0)}=${isValidNotation ? 'OK' : 'NOT OK'}:${oConstant.type}`;

      const sClassName = oKnownVariable ? oKnownVariable._class : s_NotFound;
      const sObjectValue = oKnownVariable ? oKnownVariable.value : s_NotFound;

      console.log(`{ name: \`${oConstant.name}\`, id: '${oConstant.id}', type: \`${oConstant.type}\`, _class: \`${sClassName}\`, _value: ${formatValue(sObjectValue)}, value: ${formatValue(oConstant.value)} }${(currentIndex === iTotalConstants) ? '' : ','} ${sFlagComment}\n`);

      // Update output string for oConstants (adding *CONST NAMES*)
      sOutput += `\`${oConstant.name}\`${(currentIndex === iTotalConstants) ? '' : ', '}`;

      // Retrieve the tag value if checking tags is enabled
      if (bCheckTags) {
        const tagValue = await global.get(oConstant.name); // Get TAG value from global context
        const expectedValue = getVarValueByName(oConstant.name, aValidConsts); // Get expected Value

        if (typeof tagValue === 'undefined') {
          console.log(`\t*** Tag: ${oConstant.name}, Value: undefined **`); // Log undefined tag values
        } else if (expectedValue !== tagValue) {
          aError.push(`ERROR: ${expectedValue} != ${tagValue} (${oConstant.name})\n`);
          log(`ERROR: ${expectedValue} != ${tagValue} (${oConstant.name})\n`);
          // Log discrepancies between expected and actual tag values
        }
        console.log(`${bUpdateTags ? '' : `\t`}\t** GET Tag: ${oConstant.name}, Value: ${tagValue} **`);
      }
    } // End of for loop

    log(`]// end allCONST  (${iTotalConstants})\n\n`); // Log end of oConstant list

  } catch (oError) {
    aError.push(`ERROR in setAndGetTags(): ${oError}`);
    console.error(`ERROR in setAndGetTags():`, oError); // Log any errors that occur during execution
  }
}

// Initialize output variable names for logging
let sVarNames = ''; // *VARALL NAMES* in global scope
async function allVariables() {
  const validVariables = await getValidArray();
  sVarNames = `const aVarNames = // *VARALL NAMES*\n[\n`;

  validVariables.sort((a, b) => a.name.localeCompare(b.name));

  let currentIndex = 0;

  sOutput += `\n] // end aConstNames\n\nconst var_known =\n[ // all Homey Variables\n`; // END *CONST NAMES* ;;;;;;;;;; BEGIN var_known

  try {
    for (const variable of validVariables) {
      currentIndex++;

      const oKnownVariable = var_known.find(({ name }) => name === variable.name);
      const sObjectValue = oKnownVariable ? oKnownVariable.value : s_NotFound;
      const sClassName = oKnownVariable ? oKnownVariable._class : s_NotFound;

      const isValidNotation = checkHungarianNotation(variable);
      const sFlagComment = `// FLAG:${oKnownVariable ? oKnownVariable.name.charAt(0) : ''}=${isValidNotation ? 'OK' : 'NOT OK'}:${oKnownVariable ? oKnownVariable.type : ''}`;

      sOutput += (`{ name: \`${variable.name}\`, id: '${variable.id}', type: \`${oKnownVariable?.type || ''}\`, _class: \`${sClassName}\`, _value: ${formatValue(sObjectValue)}, value: ${formatValue(variable.value)} }${(currentIndex === validVariables.length) ? '' : ', '} ${sFlagComment}\n`);

      // Update output string for Constants (adding *VARALL NAMES*)
      sVarNames += `${variable.name}\`${(currentIndex === validVariables.length) ? '' : ', '}`;
    }
    sVarNames += `\n] // end aVarNames\n`; // END *VARALL NAMES*

    sOutput += `] // end var_known (${currentIndex})`;

    return `${sOutput}\n`;

  } catch (error) {
    aError.push(`ERROR - allVariables: ${error}`);
    console.error(`ERROR - allVariables: ${error}\n`);
  }
}

await Homey.logic.updateVariable({
  id: `e4036857-790c-4bbc-825f-301568f41505`, // s_ERROR
  variable: {
    value: `⍉`
  }
});

log(`// Check variable s_ERROR
//-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!

`);

// Call the functions
await setAndGetTags(aValidConsts);
await allVariables();

log(sVarNames);
log(sOutput); // FROM aConstNames & adding *CONST NAMES*  TO var_known

if (aError.length > 0)
  await Homey.logic.updateVariable({
    id: `e4036857-790c-4bbc-825f-301568f41505`, // s_ERROR
    variable: {
      value: aError.join('||')
    }
  });

return (iVarHomeyAllLen === iValidVarsLen + iValidConstsLen) && aError.length === 0;

1 Like

I have not yet messed with scripts, but I’ve been meaning to start! Thank you!