NEWS
[Vorlage] Variable Zeitsteuerung mit VIS Editor
-
@Zoidberg
Update gibt's heute noch. -
Neue Version ist hochgeladen. Einfach- und Doppel-Klick ist über zusätzliche Variable (optional) einstellbar.
Hatte zuletzt meinen PopUp-Editor überarbeitet, siehe Screenshot im ersten Post. Ohne PNGs bleibt mehr Platz für die Zeile der Gruppen-Darstellung, ist nicht mehr so "gequetscht".Hoffe mit dieser Version einen guten Mittelweg gefunden zu haben. Werde selbst die Variante mit "Einfach-Klick" anwenden.
Bei Einfach-Klick ist eine kurze Verzögerung bis zur Ausführung bemerkbar, weil die Schrittkette [Auswahl Timer] -> [Funktion ausführen] eingehalten werden muss. Falls als störend empfunden, kann diese evtl. verkürzt werden.
Changelog 15.04.2020
- PopUp-Editor ohne zusätzliche PNGs für Tage, rein als HTML-Button (siehe Screenshot)
- Funktionen innerhalb Tabelle können nun wahlweise mit Einfach-Klick statt Doppelklick ausgeführt werden (außer in Spalte "Device", diese Spalte dient als Haupt-Markierung für ADD/DEL, hier wird immer mit Doppelklick der Editor geöffnet).
- Neue Variable "oneClick" im Variablen-Bereich hinzugefügt (Default: oneClick = false)
- Neue Variablen müssen ab dieser Version bei einem manuellen Update nicht zwingend übernommen werden!
Falls neue Variablen im oberen Bereich nicht existieren, wird der Default-Wert der neuen Variable angenommen. So soll sichergestellt werden, dass neue Funktionen die Funktionsweise älterer Versionen nicht beeinflusst
EDIT:
Hatte einen Bug bemerkt und behebe ihn noch schnell. Lade es dann nochmal hoch. Ist gerade entfernt...
-
Bug behoben. Korrigierte Version wieder hochgeladen...
-
@GiuseppeS sagte in [Vorlage] Variable Zeitsteuerung mit VIS Editor:
Korrigierte Version wieder hochgeladen...
..... hatte das Update schon eingefügt ...
-
Warte kurz lade dir die Änderung direkt hier hoch, war nur eine Kleinigkeit
EDIT: Am besten die Funktion komplett übernehmen, sicherer als einzelne Zeilen. Geht los ab Zeile ca. 618
// One-Click Aktion aus Tabelle zur Auswahl des Timers on({id: "javascript.0.Timer." + path + ".clickTarget", change: "any"}, function (obj) { if (dblClickBlocker) {return}; // Doppelte Ausführung One-Click bei Double-Click vermeiden dblClickBlocker = true; setTimeout(function(){ dblClickBlocker = false; }, 600); if (debugLog){console.log("Klick aus Tabelle erkannt. Übergebener Wert: " + obj.state.val)}; setState("javascript.0.Timer.ActiveTable", path); var tmp = obj.state.val.split("~"); if (tmp[0] != "all") { // "all" ist ein Tag der Überschriften, daher folgt keine Timer-Auswahl setState("javascript.0.Timer." + path + ".Editor.Device", tmp[0]); setStateDelayed("javascript.0.Timer." + path + ".Editor.Nummer", parseInt(tmp[1]), 50, false); } if (oneClick == true){ // Wenn Tabellen Funktionen mit One-Click gewünscht werden ... setTimeout(function(){ var btnSource = obj.state.val.split("~")[2]; // Button-Funktion wird eingelesen if (btnSource == "time"){ // Edit-Dialog öffnen bei Doppelklick IST-Zeit-Button setState("vis.0.control.data"/*Data for control vis*/, DlgWidget); setState('vis.0.control.instance'/*Control vis*/, "FFFFFFFF"); setState("vis.0.control.command"/*Command for vis*/, 'dialog'); delFocusOnTimer(false); // Auswahl des Timers nicht automatisch zurücksetzen! } if (btnSource == "nr"){ // Aktivieren/Deaktivieren des Timers setState("javascript.0.Timer." + path + ".Editor.Aktiv", !getState("javascript.0.Timer." + path + ".Editor.Aktiv").val); } if (btnSource == "cond"){ // Aktivieren/Deaktivieren des Timers resetBackgroundTimers(obj.state.val.split("~")[0]); } }, 100) } });
-
Keine Panik ...mach langsam ..
..... die Rollladen fahren erst heute Abend runter -
Update funktioniert ... ( noch kein Fehler gefunden )
Ohhh... mit einem Popup Fenster beim Klick .. nicht schlecht
-
@Glasfaser
Das Editieren mit Einfach-Klick war zweitrangig. Im Großen und Ganzen eigentlich kein Hexenwerk, könnte man meinen, aber da passiert viel im Hintergrund.
Wichtiger und nützlicher war mir, das Aktivieren/Deaktivieren mit einem Klick machbar ist. Habe da ein/zwei Timer, die ich gerne toggle. Naja, es tut nicht jeder Klick weh. Aber bei dem Aufwand, der im Skript steckt, könnte man das meinen -
-
@Glasfaser
Das passt. Kann auch alles auf github hochladen, wenn jemand Interesse hat daraus einen Adapter zu machen.
Finde den Adapter nur mit VIS Widgets sinnvoll, und das PopUp als einzelnes Widget zu erstellen trau ich mir dann doch nicht zu. Bzw. der Aufwand und der Mehrwert steht in keinem guten Verhältnis. -
@GiuseppeS sagte in [Vorlage] Variable Zeitsteuerung mit VIS Editor:
Finde den Adapter nur mit VIS Widgets sinnvoll
Und deshalb nutze ich dein Script und kein anderes !!!!
-
@GiuseppeS
Super werde gleich mal die neue Version bei mir testen -
@GiuseppeS Sorry für die verspätete Rückmeldung... aber jetzt ist es prima .. funktioniert perfekt der Einzel-Click.. Vielen Dank.
jetzt muss ich nur noch den dämlichen rechtsclick am Touch-Display loswerden
Gruss Ulrich
-
Guten Morgen zusammen.
Ich lasse mir beim editieren der Timer den Zustand der Bedingungen anzeigen.
Eventuell findet das der eine oder andere nützlich.
Hier die Änderungen:
im Script ab ca. Zeile 700, jeweils die letzte Zeile:// Trigger zum Erstellen der Bedingungen als String für späteres eval() (3x) on({id: new RegExp('javascript\\.0\\.Timer\\.' + path + '\\.Editor\\.Cond1Comp' + "|" + 'javascript\\.0\\.Timer\\.' + path + '\\.Editor\\.Cond1State' + "|" + 'javascript\\.0\\.Timer\\.' + path + '\\.Editor\\.Cond1Value'), change: "any", ack: false}, function (obj) { var ConditionJSON = JSON.parse(getState("javascript.0.Timer." + path + ".ConditionJSON").val); var Cond1State = getState("javascript.0.Timer." + path + ".Editor.Cond1State").val var Cond1Comp = getState("javascript.0.Timer." + path + ".Editor.Cond1Comp").val var Cond1Value = getState("javascript.0.Timer." + path + ".Editor.Cond1Value").val var strCond1 = "getState(\"" + ConditionJSON[Cond1State] + "\").val " + Cond1Comp + " " + Cond1Value setState("javascript.0.Timer." + path + ".Editor.Condition1", strCond1); setState("javascript.0.Timer." + path + ".Editor.Cond1Result", eval(strCond1)); }); on({id: new RegExp('javascript\\.0\\.Timer\\.' + path + '\\.Editor\\.Cond2Comp' + "|" + 'javascript\\.0\\.Timer\\.' + path + '\\.Editor\\.Cond2State' + "|" + 'javascript\\.0\\.Timer\\.' + path + '\\.Editor\\.Cond2Value'), change: "any", ack: false}, function (obj) { var ConditionJSON = JSON.parse(getState("javascript.0.Timer." + path + ".ConditionJSON").val); var Cond2State = getState("javascript.0.Timer." + path + ".Editor.Cond2State").val var Cond2Comp = getState("javascript.0.Timer." + path + ".Editor.Cond2Comp").val var Cond2Value = getState("javascript.0.Timer." + path + ".Editor.Cond2Value").val var strCond2 = "getState(\"" + ConditionJSON[Cond2State] + "\").val " + Cond2Comp + " " + Cond2Value setState("javascript.0.Timer." + path + ".Editor.Condition2", strCond2); setState("javascript.0.Timer." + path + ".Editor.Cond2Result", eval(strCond2)); }); on({id: new RegExp('javascript\\.0\\.Timer\\.' + path + '\\.Editor\\.Cond3Comp' + "|" + 'javascript\\.0\\.Timer\\.' + path + '\\.Editor\\.Cond3State' + "|" + 'javascript\\.0\\.Timer\\.' + path + '\\.Editor\\.Cond3Value'), change: "any", ack: false}, function (obj) { var ConditionJSON = JSON.parse(getState("javascript.0.Timer." + path + ".ConditionJSON").val); var Cond3State = getState("javascript.0.Timer." + path + ".Editor.Cond3State").val var Cond3Comp = getState("javascript.0.Timer." + path + ".Editor.Cond3Comp").val var Cond3Value = getState("javascript.0.Timer." + path + ".Editor.Cond3Value").val var strCond3 = "getState(\"" + ConditionJSON[Cond3State] + "\").val " + Cond3Comp + " " + Cond3Value setState("javascript.0.Timer." + path + ".Editor.Condition3", strCond3); setState("javascript.0.Timer." + path + ".Editor.Cond3Result", eval(strCond3)); });
und ab Zeile ca 1000:
createState("Timer.ActiveTable"); createState("Timer." + path + ".NextDevice"); createState("Timer." + path + ".FilterDevice"); createState("Timer." + path + ".NextDevices"); createState("Timer." + path + ".clickTarget"); createState("Timer." + path + ".dblClickTarget"); createState("Timer." + path + ".AstroJSON"); createState("Timer." + path + ".DropDownDevice"); createState("Timer." + path + ".DropDownGruppe"); createState("Timer." + path + ".Editor.DropDownMinutes"); createState("Timer." + path + ".Editor.Gruppe"); createState("Timer." + path + ".Editor.Del"); createState("Timer." + path + ".Editor.OK"); createState("Timer." + path + ".Editor.CopyAll"); createState("Timer." + path + ".Editor.CopyCond"); createState("Timer." + path + ".Editor.DropDownAstro"); createState("Timer." + path + ".Editor.DropDownAstroWerte"); createState("Timer." + path + ".Editor.DropDownAstroTexte"); createState("Timer." + path + ".Editor.Device"); createState("Timer." + path + ".Editor.Nummer"); createState("Timer." + path + ".TimerJSON"); createState("Timer." + path + ".Editor.Aktiv"); createState("Timer." + path + ".Editor.Zeit"); createState("Timer." + path + ".Editor.Cron"); createState("Timer." + path + ".Editor.TageVIS"); createState("Timer." + path + ".Editor.CronTage"); createState("Timer." + path + ".Editor.WTagMo"); createState("Timer." + path + ".Editor.WTagDi"); createState("Timer." + path + ".Editor.WTagMi"); createState("Timer." + path + ".Editor.WTagDo"); createState("Timer." + path + ".Editor.WTagFr"); createState("Timer." + path + ".Editor.WTagSa"); createState("Timer." + path + ".Editor.WTagSo"); createState("Timer." + path + ".Editor.Std"); createState("Timer." + path + ".Editor.Min"); createState("Timer." + path + ".Editor.Sollwert"); createState("Timer." + path + ".Editor.SollwertDropDown"); createState("Timer." + path + ".Editor.Random"); createState("Timer." + path + ".Editor.RandPM"); createState("Timer." + path + ".Editor.Offset"); createState("Timer." + path + ".Editor.OffsetPM"); createState("Timer." + path + ".Editor.RememberTimer"); createState("Timer." + path + ".Editor.ConditionKeyDropDown"); createState("Timer." + path + ".Editor.Condition"); createState("Timer." + path + ".Editor.ConditionsNr"); createState("Timer." + path + ".Editor.Condition1"); createState("Timer." + path + ".Editor.Cond1State"); createState("Timer." + path + ".Editor.Cond1Comp"); createState("Timer." + path + ".Editor.Cond1Value"); createState("Timer." + path + ".Editor.Cond1Result"); createState("Timer." + path + ".Editor.Condition2"); createState("Timer." + path + ".Editor.Cond2State"); createState("Timer." + path + ".Editor.Cond2Comp"); createState("Timer." + path + ".Editor.Cond2Value"); createState("Timer." + path + ".Editor.Cond2Result"); createState("Timer." + path + ".Editor.Condition3"); createState("Timer." + path + ".Editor.Cond3State"); createState("Timer." + path + ".Editor.Cond3Comp"); createState("Timer." + path + ".Editor.Cond3Value"); createState("Timer." + path + ".Editor.Cond3Result");
Jeweils die Zeile mit "Result"
Im Edit-View bei den Bedingungen als Hintergrundfarbe dann
{w:javascript.0.Timer.Devices.Editor.Cond1Result; w == "true" ? "#00AA00" : "#AA0000"}
eintragen ("Cond1Result" entsprechend ändern)
-
@HelmutS
Hi, die Idee finde ich richtig gut. Bei der Umsetzung müsste man evtl. noch etwas beachten:Was passiert, wenn du gerade eine Bedingung "neu eingibst? D.h. Zeile der Bedingungen ist leer und tippst von links nach rechts deine Werte ein. Gut möglich, dass aktuell Error angezeigt werden, bis die Zeile vollständig ist, oder? Kannst Du das bitte testen?
Ansonsten würde ich die Zeilen direkt übernehmen. -
Nachtrag
Im Script ab ca. Zeile 820 noch folgende Änderung:setState("javascript.0.Timer." + path + ".Editor.Aktiv", TimerJSON[device][nr].Aktiv, true); setState("javascript.0.Timer." + path + ".Editor.Zeit", TimerJSON[device][nr].Zeit, true); setState("javascript.0.Timer." + path + ".Editor.Cron", TimerJSON[device][nr].Cron, true); setState("javascript.0.Timer." + path + ".Editor.TageVIS", TimerJSON[device][nr].TageVIS, true); setState("javascript.0.Timer." + path + ".Editor.CronTage", TimerJSON[device][nr].CronTage, true); setState("javascript.0.Timer." + path + ".Editor.WTagMo", TimerJSON[device][nr].Mo, true); setState("javascript.0.Timer." + path + ".Editor.WTagDi", TimerJSON[device][nr].Di, true); setState("javascript.0.Timer." + path + ".Editor.WTagMi", TimerJSON[device][nr].Mi, true); setState("javascript.0.Timer." + path + ".Editor.WTagDo", TimerJSON[device][nr].Do, true); setState("javascript.0.Timer." + path + ".Editor.WTagFr", TimerJSON[device][nr].Fr, true); setState("javascript.0.Timer." + path + ".Editor.WTagSa", TimerJSON[device][nr].Sa, true); setState("javascript.0.Timer." + path + ".Editor.WTagSo", TimerJSON[device][nr].So, true); setState("javascript.0.Timer." + path + ".Editor.Std", TimerJSON[device][nr].Std, true); setState("javascript.0.Timer." + path + ".Editor.Min", TimerJSON[device][nr].Min, true); setState("javascript.0.Timer." + path + ".Editor.Sollwert", TimerJSON[device][nr].Sollwert, true); setState("javascript.0.Timer." + path + ".Editor.DropDownAstro", TimerJSON[device][nr].Astro, true); setState("javascript.0.Timer." + path + ".Editor.Random", TimerJSON[device][nr].Random, true); setState("javascript.0.Timer." + path + ".Editor.RandPM", TimerJSON[device][nr].RandPM, true); setState("javascript.0.Timer." + path + ".Editor.Offset", TimerJSON[device][nr].Offset, true); setState("javascript.0.Timer." + path + ".Editor.OffsetPM", TimerJSON[device][nr].OffsetPM, true); setState("javascript.0.Timer." + path + ".Editor.RememberTimer", TimerJSON[device][nr].RememberTimer, true); setState("javascript.0.Timer." + path + ".Editor.ConditionsNr", TimerJSON[device][nr].ConditionsNr, true); setState("javascript.0.Timer." + path + ".Editor.Condition1", TimerJSON[device][nr].Conditions[1].ConditionStr, true); setState("javascript.0.Timer." + path + ".Editor.Cond1State", TimerJSON[device][nr].Conditions[1].CondState, true); setState("javascript.0.Timer." + path + ".Editor.Cond1Comp", TimerJSON[device][nr].Conditions[1].CondComp, true); setState("javascript.0.Timer." + path + ".Editor.Cond1Value", TimerJSON[device][nr].Conditions[1].CondValue, true); setState("javascript.0.Timer." + path + ".Editor.Condition2", TimerJSON[device][nr].Conditions[2].ConditionStr, true); setState("javascript.0.Timer." + path + ".Editor.Cond2State", TimerJSON[device][nr].Conditions[2].CondState, true); setState("javascript.0.Timer." + path + ".Editor.Cond2Comp", TimerJSON[device][nr].Conditions[2].CondComp, true); setState("javascript.0.Timer." + path + ".Editor.Cond2Value", TimerJSON[device][nr].Conditions[2].CondValue, true); setState("javascript.0.Timer." + path + ".Editor.Condition3", TimerJSON[device][nr].Conditions[3].ConditionStr, true); setState("javascript.0.Timer." + path + ".Editor.Cond3State", TimerJSON[device][nr].Conditions[3].CondState, true); setState("javascript.0.Timer." + path + ".Editor.Cond3Comp", TimerJSON[device][nr].Conditions[3].CondComp, true); setState("javascript.0.Timer." + path + ".Editor.Cond3Value", TimerJSON[device][nr].Conditions[3].CondValue, true); setState("javascript.0.Timer." + path + ".Editor.Gruppe", TimerJSON[device][nr].Gruppe, true); if (TimerJSON[device][nr].Conditions[1].ConditionStr != ""){ setState("javascript.0.Timer." + path + ".Editor.Cond1Result", eval(TimerJSON[device][nr].Conditions[1].ConditionStr)); } if (TimerJSON[device][nr].Conditions[2].ConditionStr != ""){ setState("javascript.0.Timer." + path + ".Editor.Cond2Result", eval(TimerJSON[device][nr].Conditions[2].ConditionStr)); } if (TimerJSON[device][nr].Conditions[3].ConditionStr != ""){ setState("javascript.0.Timer." + path + ".Editor.Cond3Result", eval(TimerJSON[device][nr].Conditions[3].ConditionStr)); }
-
@GiuseppeS
Stimmt, beim ersten Aufruf kommt ein Fehler.
Ich habe es jetzt so gelöst:// Trigger zum Erstellen der Bedingungen als String für späteres eval() (3x) on({id: new RegExp('javascript\\.0\\.Timer\\.' + path + '\\.Editor\\.Cond1Comp' + "|" + 'javascript\\.0\\.Timer\\.' + path + '\\.Editor\\.Cond1State' + "|" + 'javascript\\.0\\.Timer\\.' + path + '\\.Editor\\.Cond1Value'), change: "any", ack: false}, function (obj) { var ConditionJSON = JSON.parse(getState("javascript.0.Timer." + path + ".ConditionJSON").val); var Cond1State = getState("javascript.0.Timer." + path + ".Editor.Cond1State").val var Cond1Comp = getState("javascript.0.Timer." + path + ".Editor.Cond1Comp").val var Cond1Value = getState("javascript.0.Timer." + path + ".Editor.Cond1Value").val var strCond1 = "getState(\"" + ConditionJSON[Cond1State] + "\").val " + Cond1Comp + " " + Cond1Value setState("javascript.0.Timer." + path + ".Editor.Condition1", strCond1); if (Cond1State != "" && Cond1Comp != "" && Cond1Value != "") { setState("javascript.0.Timer." + path + ".Editor.Cond1Result", eval(strCond1)); } }); on({id: new RegExp('javascript\\.0\\.Timer\\.' + path + '\\.Editor\\.Cond2Comp' + "|" + 'javascript\\.0\\.Timer\\.' + path + '\\.Editor\\.Cond2State' + "|" + 'javascript\\.0\\.Timer\\.' + path + '\\.Editor\\.Cond2Value'), change: "any", ack: false}, function (obj) { var ConditionJSON = JSON.parse(getState("javascript.0.Timer." + path + ".ConditionJSON").val); var Cond2State = getState("javascript.0.Timer." + path + ".Editor.Cond2State").val var Cond2Comp = getState("javascript.0.Timer." + path + ".Editor.Cond2Comp").val var Cond2Value = getState("javascript.0.Timer." + path + ".Editor.Cond2Value").val var strCond2 = "getState(\"" + ConditionJSON[Cond2State] + "\").val " + Cond2Comp + " " + Cond2Value setState("javascript.0.Timer." + path + ".Editor.Condition2", strCond2); if (Cond2State != "" && Cond2Comp != "" && Cond2Value != "") { setState("javascript.0.Timer." + path + ".Editor.Cond2Result", eval(strCond2)); } }); on({id: new RegExp('javascript\\.0\\.Timer\\.' + path + '\\.Editor\\.Cond3Comp' + "|" + 'javascript\\.0\\.Timer\\.' + path + '\\.Editor\\.Cond3State' + "|" + 'javascript\\.0\\.Timer\\.' + path + '\\.Editor\\.Cond3Value'), change: "any", ack: false}, function (obj) { var ConditionJSON = JSON.parse(getState("javascript.0.Timer." + path + ".ConditionJSON").val); var Cond3State = getState("javascript.0.Timer." + path + ".Editor.Cond3State").val var Cond3Comp = getState("javascript.0.Timer." + path + ".Editor.Cond3Comp").val var Cond3Value = getState("javascript.0.Timer." + path + ".Editor.Cond3Value").val var strCond3 = "getState(\"" + ConditionJSON[Cond3State] + "\").val " + Cond3Comp + " " + Cond3Value setState("javascript.0.Timer." + path + ".Editor.Condition3", strCond3); if (Cond3State != "" && Cond3Comp != "" && Cond3Value != "") { setState("javascript.0.Timer." + path + ".Editor.Cond3Result", eval(strCond3)); } });
Oder fällt dir eine bessere Lösung ein? Du kennst den Script besser
-
Ich überlege auch schon, wie man das am effektivsten anpasst. Ich denke, den Fehler einfach mit try/catch abzufangen, wird die einfachste Lösung sein, ohne zuviel komplexen Code zu nutzen.
Werde deinen Code daher weitestgehend übernehmen und innerhalb des if-Statements ein try/catch einbauen. Muss aber ehrlich gesagt testen, ob es mit eval() überhaupt funktioniert. Habe es noch nie getestet...
-
Habe den Code von dir nun 1:1 übernommen. Try/Catch habe ich mal weggelassen. Wenn jemand seinen Boolean-State mit einem Zahlenwert vergleichen würde, würde dieser Fehler auch abgefangen werden, was nicht für die Fehlersuche im Nachgang nicht sinnvoll wäre.
Meine einzige Anpassung war nur folgende. Statt
if (TimerJSON[device][nr].Conditions[1].ConditionStr != ""){ setState("javascript.0.Timer." + path + ".Editor.Cond1Result", eval(TimerJSON[device][nr].Conditions[1].ConditionStr)); } if (TimerJSON[device][nr].Conditions[2].ConditionStr != ""){ setState("javascript.0.Timer." + path + ".Editor.Cond2Result", eval(TimerJSON[device][nr].Conditions[2].ConditionStr)); } if (TimerJSON[device][nr].Conditions[3].ConditionStr != ""){ setState("javascript.0.Timer." + path + ".Editor.Cond3Result", eval(TimerJSON[device][nr].Conditions[3].ConditionStr)); }
habe ich folgendes eingesetzt:
for (let i = 1; i <= 3; i++){ setState("javascript.0.Timer." + path + ".Editor.Cond" + i + "Result", eval(TimerJSON[device][nr].Conditions[i].ConditionStr)); // weitere States werden gesetzt.... weiter oben entfernt }
Werde jetzt allgemein nur eine Kleinigkeit ergänzen: Wenn die Anzahl der Bedingungen verringert wird, möchte ich die nicht mehr genutzten States leeren. Aktuell stehen weiterhin Werte in den States bzw. im Main-JSON, was mich schon länger stört.
-
So Update ist hochgeladen. Für ein manuelles Update einfach das Skript unterhalb des Variablen-Bereichs übernehmen (Falls vom letzten Update kommend). Zusätzlich könnt ihr das PopUp View neu importieren. Alternativ können auch die Farbeinstellungen der 9 Bedingungs-Widgets übernommen werden.
Changelog 26.04.2020
- Minütliches Flackern der nächsten Timer abgestellt. Nur noch bei Änderungen gibts ein Flackern
- Bedingungen werden während der Eingabe ausgewertet und farblich im Editor hervorgehoben (Danke an HelmutS)
- Wenn Bedingungen leer oder fehlerhaft sind, wird das PopUp-Fenster nicht geschlossen. Log wird ausgegeben.
Wenn Bedingungen fehlerhaft sind, wird das PopUp beim Schließen über Button "Übernehmen" nicht geschlossen. Im iobroker Log wird auch entsprechend eine Ausgabe erzeugt. Hatte jetzt bestimmt eine Stunde versucht, diese Ausgabe dynamisch im PopUp direkt anzeigen zu lassen, aber erfolglos. Wollte das Error-Textfeld über html-Widget und dynamischer Sichtbarkeit realisieren, aber leider werden dahinterliegende Widgets überdeckt (Steuerung nicht möglich) trotz "Unsichtbarkeit" des zusätzlichen Widgets.
Danke @HelmutS