Ungenutzte Logik-Variablen

Hallo zusammen,

gibt es eine Möglichkeit ungenutzte Variablen (Mehr → Logik) ausfindig zu machen?
Im Laufe der Zeit haben sich eine ganze Menge Variablen angesammelt, wobei definitiv nicht mehr alle Variablen in Flows genutzt werden.

Ist jmd. in der Lage ein Script zu schreiben? Meine Programmierkenntnisse gehen leider gegen 0.

1 Like

dto, gleiches Problem…

@RonnyW, kannst Du da nicht was zaubern?

Ich kann ja mal in der WebAPI schauen, ob man überhaupt auf Flow-Eigenschaften zugreifen kann. Ich fürchte aber, das beschränkt sich eher auf allgemeine Aktionen wie aktivieren/deaktivieren.

1 Like

Wäre echt klasse von Dir. :+1:t3:

Ich habe mal ein kleines Skript zusammengestrickt.
Es durchsucht alle Logik-Variablen und sucht nach Verwendung in Flows.
Es gibt allerdinge eine Einschränkung:
Es werden aktuell nur Fundstellen geliefert, wo die Logik-Variable direkt verwendet wird, also über die Auswahl Logik/Variable in einen Flow eingefügt wurde (z.B. Prüfung auf Variable, Änderung einer Variable.
Was nicht gefunden wird sind Stellen, wo die Logikvariable als Tag in einem Flow verwendet wird (z.B: wenn man eine Lokiv-Variabke in einer Berechnung verwendet). Das muss ich noch ergänzen. Das ist etwas aufwändiger, weil die Tag-Variable nur mit einer generischen ID (GUID) im Flow eingetragen ist.

Hier schon mal die erste Version.
Verwendung: In my.homey.app im Bereich HomeyScript ein Skript anlegen und diesen Code einfügen. Dann mit “Test” starten. Im Log-Fenster werden die Ergebnisse angezeigt.

log('=============================================================');
log('Flow-Suche nach Logik-Variablen');
log('=============================================================');
const flows = await Homey.flow.getFlows();
const logicVars = await Homey.logic.getVariables();
let flowMatches;
let position = [];

for (var iLogicVar in logicVars){
  log('=============================================================');
  log('Logik-Variable: '+logicVars[iLogicVar].name);
  log('=============================================================');
  logicVar = logicVars[iLogicVar].name;

  for (var iFlow in flows){
    flowMatches = false;
    position = [];
    // Such nach Variablenname in Trigger
    if (flows[iFlow].trigger.uri == "homey:manager:logic")
      for (var iArgs in flows[iFlow].trigger.args){
        if (flows[iFlow].trigger.args[iArgs].name == logicVar){
          position.push("Trigger");
          flowMatches = true;
        }
      }
    // Such nach Variablenname in Bedingungen
    for(var iCond in flows[iFlow].conditions){
      if ( flows[iFlow].conditions[iCond] &&
          flows[iFlow].conditions[iCond].uri == "homey:manager:logic")
        for (var iArgs in flows[iFlow].conditions[iCond].args){
          if (flows[iFlow].conditions[iCond].args[iArgs].name == logicVar){
            position.push("Bedingung");
            flowMatches = true;
          }
        }
    }
    // Such nach Variablenname in Aktionen
    for(var iAct in flows[iFlow].actions){
      if ( flows[iFlow].actions[iAct] &&
          flows[iFlow].actions[iAct].uri == "homey:manager:logic")
        for (var iArgs in flows[iFlow].actions[iAct].args){
          //log(flows[iFlow].actions[iAct].args[iArgs]);
          if (flows[iFlow].actions[iAct].args[iArgs].name == logicVar){
            position.push("Aktion");
            flowMatches = true;
          }
        }
    }

  // Ausgabe des gefundenen Flows:
    if (flowMatches == true){
      log("---------------------------------------------------");
      log("Gefunden in Flow: "+flows[iFlow].name);
      log("Position:");
      log(position);
      //log("---------------------------------------------------");
      //log("Flow:");
      //log(flows[iFlow]);
    }
  }
}
3 Likes

Neue Version…die findet nun auch als Tags verwendete Logik-Variablen in Bedingungen oder Aktionen:

log("=============================================================");
log("Flow-Suche nach Logik-Variablen");
log("=============================================================");
log(" ");
const flows = await Homey.flow.getFlows();
const logicVars = await Homey.logic.getVariables();
let flowMatches;
let varUsed;
let position = [];

for (var iLogicVar in logicVars){
  log(" ");
  log("=============================================================");
  log("Logik-Variable: "+logicVars[iLogicVar].name);
  //log('ID: '+logicVars[iLogicVar].id);
  //log("=============================================================");
  let logicVar = logicVars[iLogicVar].name;
  let logicVarId = logicVars[iLogicVar].id;
  varUsed = false;

  for (var iFlow in flows){
    flowMatches = false;
    position = [];
    // Such nach Variablenname in Trigger
    if (flows[iFlow].trigger.uri == "homey:manager:logic"){
      for (var iArgs in flows[iFlow].trigger.args){
        if (    flows[iFlow].trigger.args[iArgs].name == logicVar
             || flows[iFlow].trigger.args[iArgs].id == logicVarId){
          position.push("Trigger");
          flowMatches = true;
        }
      }
    }
    // Such nach Variablenname in Bedingungen
    for(var iCond in flows[iFlow].conditions){
      if ( flows[iFlow].conditions[iCond] &&
          flows[iFlow].conditions[iCond].uri == "homey:manager:logic"){
        //log(flows[iFlow].conditions[iCond].args);
        for (var iArgs in flows[iFlow].conditions[iCond].args){
          if (    flows[iFlow].conditions[iCond].args[iArgs].name == logicVar
                || flows[iFlow].conditions[iCond].args[iArgs].id == logicVarId ){
            position.push("Bedingung - direkte Verwendung");
            flowMatches = true;
          }
        }
      }
      for (var iArgs in flows[iFlow].conditions[iCond].args){
        if ( flows[iFlow].conditions[iCond].args[iArgs] &&
            JSON.stringify( flows[iFlow].conditions[iCond].args[iArgs] ).indexOf( logicVarId ) > 0 &&
            JSON.stringify( flows[iFlow].conditions[iCond].args[iArgs] ).indexOf( "homey:manager:logic" ) > 0 ){
          position.push("Bedingung - indirekte Verwendung (Tag)");
          flowMatches = true;
        }
      }
    }
    // Such nach Variablenname in Aktionen
    for(var iAct in flows[iFlow].actions){
      if ( flows[iFlow].actions[iAct] &&
          flows[iFlow].actions[iAct].uri == "homey:manager:logic"){

        for (var iArgs in flows[iFlow].actions[iAct].args){
          if (    flows[iFlow].actions[iAct].args[iArgs].name == logicVar
                || flows[iFlow].actions[iAct].args[iArgs].id == logicVarId ){
            position.push("Aktion - direkte Verwendung");
            flowMatches = true;
          }
        }
      }
      for (var iArgs in flows[iFlow].actions[iAct].args){
        if ( flows[iFlow].actions[iAct].args[iArgs] &&
            JSON.stringify( flows[iFlow].actions[iAct].args[iArgs] ).indexOf( logicVarId ) > 0 &&
            JSON.stringify( flows[iFlow].actions[iAct].args[iArgs] ).indexOf( "homey:manager:logic" ) > 0 ){
          position.push("Aktion - indirekte Verwendung (Tag)");
          flowMatches = true;
        }
      }
    }

  // Ausgabe des gefundenen Flows:
    if (flowMatches == true){
      varUsed = true;
      log("-------------------------------------------------------------");
      log("Gefunden in Flow:");
      log(flows[iFlow].name);
      log("Position:");
      for (iPos in position){
        log("  "+position[iPos]);
      }
    }
  }
  if (!varUsed){
    log("Keine Verwendung!");
  }
}
6 Likes

Prima, vielen vielen Dank! :+1:t4:

Edit: Werde mal 2, 3 ungenutzte Variablen überwachen bevor ich wild drauf los lösche.

Gern geschehen. Ich habe damit auch zwei überflüssige Variablen gefunden :slight_smile:

Ich habe im letzten Beitrag den Code nochmal bezüglich der Ausgabe etwas überarbeitet, damit es besser lesbar ist.

1 Like

Jepp, ist deutlich besser lesbar. :+1:t4:

Vielen Dank, Ronny! Ich habe lange nach so einem Script gesucht! Es wurden 66 verwaiste Variablen gefunden, und was für ein Nervenkitzel, sehen zu können, in welchen Flows eine Variable verwendet wird.

Jetzt habe ich versucht, die Ausgabe in eine String-Variable zu schreiben, aber ich komme nicht mit JSON.stringify der Ausgabe in eine Variable. Falls jemand einen Hinweis hat, ich bin ganz Ohr :wink:

1 Like

Hi Peter,
die Ausgabe erfolgt als Test jeweils mit log(…) in die Konsole.
Es sollte daher genügen, alle Zeilen mit log( ) mit einer Übernahme in den String zu ergänzen.

// First define your variable
let result;
// add collecting of your string after each log(…)
log("…")
result = result + “…”;

evtl. muss du noch jeweils mit \n einen Zeilenumbruch ergänzen.

Am Ende kann man das als Flow-Tag zurückgeben. Ich nehme an, das willst du damit machen.
Dafür hast du ja schon Beispiele aus anderen Sktipten :slight_smile:

Das Skript durchläuft mehrere geschachtelte Schleifen (Variablen, Flows, Positionen) und gibt jeweils die aktuellen Daten als Text aus. Deshalb gibt es keine Variable, die alles beinhaltet.

Wo reiner Text oder einfache Variablen werden, sollte das funktionieren.
Falls noch irgendwo JSON-Objekte verwendet werden, müsste man die mit JSON.stringify( variable ) in einen String konvertieren.

Viel Erfolg :wink:

1 Like

Super!! Danke, Ronny @RonnyW . Ich habe es geschafft, die Skriptausgabe in eine Variable zu schießen.
Wirklich schön, dass es in der Timeline (oder was auch immer) meldet, welche Variablen sich nicht in einem Flow befinden.
Die Timeline wird sehr zähflüssig :wink:
Was ich jetzt gebacken habe, ist nicht das Schönste, reicht mir aber vorerst :wink:

  • Skript: (nur die Variablen ohne Flows anzeigen):
// FindOrphanedLogicsVars.js
//
// Script to find Homey Logics orphaned Variables (by RonnyW)
// Adjusted somewhat, when called from a flow, it returns the output in a Variable
const flows = await Homey.flow.getFlows();
const logicVars = await Homey.logic.getVariables();
let flowMatches;
let varUsed;
let position = [];
let results2Var; // To be able to build a string to output the results to 
                 //  a variable [OrphanedLogicsVars], for usage in flows
results2Var = ("*** Orphaned Logics Variables found ***\n\n script: FindOrphanedLogicsVars.js\n\n");                 
for (var iLogicVar in logicVars){
  results2Var = results2Var + "**VARIABLE:** ["+logicVars[iLogicVar].name + "]\n";
  let logicVar = logicVars[iLogicVar].name;
  let logicVarId = logicVars[iLogicVar].id;
  varUsed = false;

  for (var iFlow in flows){
    flowMatches = false;
    position = [];
    // Search for variable name in Triggers
    if (flows[iFlow].trigger.uri == "homey:manager:logic"){
      for (var iArgs in flows[iFlow].trigger.args){
        if (    flows[iFlow].trigger.args[iArgs].name == logicVar
             || flows[iFlow].trigger.args[iArgs].id == logicVarId){
          position.push("Trigger card (IF)");
          flowMatches = true;
        }
      }
    }
    // Search for variable name in Condition cards
    for(var iCond in flows[iFlow].conditions){
      if ( flows[iFlow].conditions[iCond] &&
          flows[iFlow].conditions[iCond].uri == "homey:manager:logic"){
        //log(flows[iFlow].conditions[iCond].args);
        for (var iArgs in flows[iFlow].conditions[iCond].args){
          if (    flows[iFlow].conditions[iCond].args[iArgs].name == logicVar
                || flows[iFlow].conditions[iCond].args[iArgs].id == logicVarId ){
            position.push("Condition (AND) - direct reference");
            flowMatches = true;
          }
        }
      }
      for (var iArgs in flows[iFlow].conditions[iCond].args){
        if ( flows[iFlow].conditions[iCond].args[iArgs] &&
            JSON.stringify( flows[iFlow].conditions[iCond].args[iArgs] ).indexOf( logicVarId ) > 0 &&
            JSON.stringify( flows[iFlow].conditions[iCond].args[iArgs] ).indexOf( "homey:manager:logic" ) > 0 ){
          position.push("Condition (AND) - indirect reference (Tag)");
          flowMatches = true;
        }
      }
    }
    // Search for variable name in Action cards
    for(var iAct in flows[iFlow].actions){
      if ( flows[iFlow].actions[iAct] &&
          flows[iFlow].actions[iAct].uri == "homey:manager:logic"){

        for (var iArgs in flows[iFlow].actions[iAct].args){
          if (    flows[iFlow].actions[iAct].args[iArgs].name == logicVar
                || flows[iFlow].actions[iAct].args[iArgs].id == logicVarId ){
            position.push("Action (THEN) - direct reference");
            flowMatches = true;
          }
        }
      }
      for (var iArgs in flows[iFlow].actions[iAct].args){
        if ( flows[iFlow].actions[iAct].args[iArgs] &&
            JSON.stringify( flows[iFlow].actions[iAct].args[iArgs] ).indexOf( logicVarId ) > 0 &&
            JSON.stringify( flows[iFlow].actions[iAct].args[iArgs] ).indexOf( "homey:manager:logic" ) > 0 ){
          position.push("Action (THEN) - indirect reference (Tag)");
          flowMatches = true;
        }
      }
    }

  // Results of Flows found:
    if (flowMatches == true){
      varUsed = true;
    }
  }
  if (!varUsed){
    results2Var = results2Var +"*** NOT FOUND IN FLOWS *** \n\n";
  } 
}
// Output to a StringVariable [OrphanedLogicsVars]
await tag( "OrphanedLogicsVars", results2Var );
//
// Output (just test to view the result data in 'results2Var')
// console.log(results2Var)
return(true);

Timeline:

  • Und ein Skript mit allen Infos:
// FindLogicsVarsInFlows.js
//
// Script to find Homey Logics Variables in Flows, and orphaned Variables (by RonnyW)
// Adjusted somewhat, when called from a flow, it returns the output in a Variable (PD)
const flows = await Homey.flow.getFlows();
const logicVars = await Homey.logic.getVariables();
let flowMatches;
let varUsed;
let position = [];
let results2Var; // To be able to build a string to output the results to 
                 //  a variable [FoundLogicsVarsInFlows], for usage in flows
results2Var = ("*** Logics Variables found in Flows ***\n\n script: FindLogicsVarsInFlows.js\n\n");                 

for (var iLogicVar in logicVars){
  results2Var = results2Var + "\n**VARIABLE:** ["+logicVars[iLogicVar].name + "]\n";
  let logicVar = logicVars[iLogicVar].name;
  let logicVarId = logicVars[iLogicVar].id;
  varUsed = false;

  for (var iFlow in flows){
    flowMatches = false;
    position = [];
    // Search for variable name in Triggers
    if (flows[iFlow].trigger.uri == "homey:manager:logic"){
      for (var iArgs in flows[iFlow].trigger.args){
        if (    flows[iFlow].trigger.args[iArgs].name == logicVar
             || flows[iFlow].trigger.args[iArgs].id == logicVarId){
          position.push("Trigger card (IF)");
          flowMatches = true;
        }
      }
    }
    // Search for variable name in Condition cards
    for(var iCond in flows[iFlow].conditions){
      if ( flows[iFlow].conditions[iCond] &&
          flows[iFlow].conditions[iCond].uri == "homey:manager:logic"){
        //log(flows[iFlow].conditions[iCond].args);
        for (var iArgs in flows[iFlow].conditions[iCond].args){
          if (    flows[iFlow].conditions[iCond].args[iArgs].name == logicVar
                || flows[iFlow].conditions[iCond].args[iArgs].id == logicVarId ){
            position.push("Condition (AND) - direct reference");
            flowMatches = true;
          }
        }
      }
      for (var iArgs in flows[iFlow].conditions[iCond].args){
        if ( flows[iFlow].conditions[iCond].args[iArgs] &&
            JSON.stringify( flows[iFlow].conditions[iCond].args[iArgs] ).indexOf( logicVarId ) > 0 &&
            JSON.stringify( flows[iFlow].conditions[iCond].args[iArgs] ).indexOf( "homey:manager:logic" ) > 0 ){
          position.push("Condition (AND) - indirect reference (Tag)");
          flowMatches = true;
        }
      }
    }
    // Search for variable name in Action cards
    for(var iAct in flows[iFlow].actions){
      if ( flows[iFlow].actions[iAct] &&
          flows[iFlow].actions[iAct].uri == "homey:manager:logic"){

        for (var iArgs in flows[iFlow].actions[iAct].args){
          if (    flows[iFlow].actions[iAct].args[iArgs].name == logicVar
                || flows[iFlow].actions[iAct].args[iArgs].id == logicVarId ){
            position.push("Action (THEN) - direct reference");
            flowMatches = true;
          }
        }
      }
      for (var iArgs in flows[iFlow].actions[iAct].args){
        if ( flows[iFlow].actions[iAct].args[iArgs] &&
            JSON.stringify( flows[iFlow].actions[iAct].args[iArgs] ).indexOf( logicVarId ) > 0 &&
            JSON.stringify( flows[iFlow].actions[iAct].args[iArgs] ).indexOf( "homey:manager:logic" ) > 0 ){
          position.push("Action (THEN) - indirect reference (Tag)");
          flowMatches = true;
        }
      }
    }

  // Results of Flows found:
    if (flowMatches == true){
      varUsed = true;
      results2Var = results2Var + " - ";
      results2Var = results2Var + "**Flowname:** " + "\"" + flows[iFlow].name + "\" \n";
      results2Var = results2Var +"   -Position: \n";
      for (iPos in position){
        results2Var = results2Var + "       -" +position[iPos] + " / \n";
      }
    }
  }
  if (!varUsed){
    results2Var = results2Var +"*** NOT FOUND IN FLOWS *** \n\n";
  } 
}
// Output to a StringVariable [FoundLogicsVarsInFlows]
await tag( "FoundLogicsVarsInFlows", results2Var );
//
// Output (just test to view the result data in 'results2Var')
// console.log(results2Var)
return(true);

Timeline:


2 Likes

Dieser ist manchmal auch ganz praktisch :wink:
Dieses Skript listet nur Flows auf, die: einen ‘Start as Flow’-Trigger haben, nur von HomeyScript gestartet werden oder nur als FavFlow verwendet werden.

// 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.
// Source: https://community.homey.app/t/developer-web-api-playground-notes-of-geeky-oneliners/24392/8
// Altered somewhat afterwards, to output results into a HomeyScript Variable.

'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() 
let UnUsedflows = (`Result of search in all of your ${flows.length} Flows, which are Unused or TriggeredbyHomeyScript or StartedAsFavFlow:\n\n`);

function getFolder(id) { if (folders[id]) { 
  if (folders[id].parent) { 
    return `${getFolder(folders[id].parent)} > "${folders[id].name}"` 
    } 
    return `"${folders[id].name}"` 
    } 
    return ''; 
    } 
    
    //log(`Result of search through ${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}`))
            UnUsedflows = UnUsedflows + (`${getFolder(flow.folder)} > ${flow.name}\n\n`))
            //creating new HomeyScriptTag 'UnusedFlows'
            await tag("UnusedFlows", UnUsedflows )

            //Console test
            //  log(UnUsedflows)

return(true);

Die neueste Beta Version von Flow Checker, findet jetzt auch ungenutzte Variablen.

2 Likes

Du bist mir gerade voraus, Uwe :grin:. Danke für das Update!

Ich habe es Martijn vorgeschlagen, ich dachte, das gehört wirklich in die FlowChecker-App.
Genau wie das Skript “ungenutzte Flows”.
Und am nächsten Tag hat er es schon in der App verarbeitet! :stopwatch::racing_car::beers:

1 Like