NEWS
[gelöst] mit setState von Zahl auf bool
-
on('javascript.0.Technikraum.Homeduino.homeduino_001_D26', function(dp) { if(dp.state.val) setState('hm-rega.0.15057', true); else setState('hm-rega.0.15057', false); });
oder
on('javascript.0.Technikraum.Homeduino.homeduino_001_D26', function(dp) { setState('hm-rega.0.15057', toBoolean(dp.state.val)); });
oder
on('javascript.0.Technikraum.Homeduino.homeduino_001_D26', function(dp) { setState('hm-rega.0.15057', !!dp.state.val); });
-
Super, danke Paul.
Gruß Johnny
-
Hallo mitsammen!
Hatte auch schon Probleme damit da man ja annimmt wenn ein state als boolean definiert ist dass er nur boolean's speichert (und so ähnlich mit strings und Zahlen).
Leider wandelt setState aber den Wert nicht um und wenn dann irgend ein Programm 'false' als string hineinschreibt und ein anderes auf false (boolean) prüft dann stimmts nicht zusammen. Leider funktioniert dann auch kein !!val, dies fu8nktioniert aber besser bei Zahlen wo 0 als false und <>0 als true gewandelt wird.
In meinen Adaptern schau ich dass die Werte richtig gesetzt werden, aber wenn setState das richtig umwandeln und abspeichern würde wäre es weniger Fehleranfällig.
-
@fsjoke:…'false' als string hineinschreibt und ein anderes auf false (boolean) prüft dann stimmts nicht zusammen. `
Dafür gibt es die (undokumentierte) Funktion toBoolean(val) des Javascript-Adapters.
@fsjoke:In meinen Adaptern schau ich dass die Werte richtig gesetzt werden, … `
Das sollte jeder Programmierer machen. Wenn direkt angekoppelte Hardware (Homedunio) nicht typgerechte Werte liefert, muss man wandeln. Erfolgt die Ankopplung über einen Adapter, ist dies die Aufgabe des Adapters. -
Paul,
es geht mir nicht darum ob ich es umwandeln kann, es geht darum dass ich ein ioBroker-Objekt definiere das ein boolean ist (oder ein string oder sonst was) aber trotzdem im was anderes abgespeichert ist/werden kann.
Das ist einfach falsch da ich dann ja auch keine Objekttypen definieren brauch und bei jeder Abfrage immer zur Vorsicht konvertieren muss.
Also, wenn schon objekt-typen definiert sind soll die Konvertierung beim Speichern auf diesen Typ vorgenommen werden uund eben nur solche Werte akzeptiert werden.
Es gibt ja auch den Objekttype wo man alles speichern kann.
p.s.: Der History-Adapter konvertiert die Daten vorm Abspeichern…
-
@fsjoke:…dass ich ein ioBroker-Objekt definiere das ein boolean ist (oder ein string oder sonst was) aber trotzdem im was anderes abgespeichert ist/werden kann. `
Mein Vorschlag an Bluefox vor einiger Zeit ging dahin, die Speicherung eines falschen Datentyps zu verhindern und stattdessen eine Fehlermeldung zu erzeugen. Da es aber zu dem Zeitpunkt schon zu viele fehlerhafte Skripte gab, die dann nicht mehr funktioniert hätten, hat Bluefox zwar die Prüfung eingeführt, die bei falschem Datentyp die mittlerweile bekannte Warnmeldung erzeugt, die Speicherung aber (noch) nicht verhindert.Außerdem hat Bluefox es nur im Javascript-Adapter realisiert. Mein Vorschlag ging jedoch in Richtung js-controller, damit die Typkontrolle alle Adapter betrifft. Einige Adapter würden dann wohl nicht mehr funktionieren.
-
Oh, hab das schon mal gesehen mit der Warnung.
Ich würde es ja nicht verbieten, aber halt eben konvertieren!
Also bei anstatt state.val = newval mal eben state.val = Boolean(newval) ? !!newval : false;
und bei Zahlen checken ob's Integer ist und dann mit parseInt/parseFloat(newval)
und strings mit newval.toString()
Dann kann man auf das Warning verzichten.
-
Was macht man mit Werten, die sich nicht konvertieren lassen ?
Beispiel: "mein Text" –> boolean
oder: "" --> number
-
Der Type einer Variablen kann sich ändern. Auch wenn man ihn anfangs ausdrücklich festlegt, darf der Typ in Javascript nachträglich geändert werden. Das ist sicherlich nicht schön und birgt Risiken. Dies ist in Javascript so gewollt.
Schön fände ich es in der Tat, wenn setState manche falsche Typen verzeihen würde. Trotzdem ist die jetzige Lösung wahrscheinlich nicht die Schlechteste. Gerade umgekehrt gibt es nämlich dieselben Probleme. Stellen wir uns vor, ein getState gibt die Zahl 1 zurück. Wir prüfen dann, ob das Ergebnis true ist. Damit wird dann das Programm nicht mehr so funktionieren wie gewollt.
Es bleibt letztendlich keine andere Möglichkeit, als auf den Datentyp zu achten. Übrigens, auch VIS-Widgets können den Datentyp ändern. Hier lauert eine häßliche Falle.
-
Dies ist in Javascript so gewollt. `
Ein Datenpunkt ist keine Javascript-Variable, die man nur ohne Typbindung deklarieren kann. Wenn der Datenpunkttyp vorgegeben ist, sollte der Wert auch diesem Typ entsprechen. Will man wechselnde Datentypen erlauben, kann man als Typ 'mixed' vorgeben, was allerdings schlechter Programmierstil wäre.
@gst666:Stellen wir uns vor, ein getState gibt die Zahl 1 zurück. Wir prüfen dann, ob das Ergebnis true ist. Damit wird dann das Programm nicht mehr so funktionieren wie gewollt. `
Wenn bekannt ist, dass getState(id).val auch Zahlen (0 / 1) liefern kann, testet man mitif(getState(id).val)
-
Übrigens, mein Beispiel von Boolean oben müsste abgeändert werden um für alle Fälle zu gelten.
Egal, grundsätzlich erlaubt Javascript selbst beliebige Typen für die Variablen aber wenn man im ioBroker eine Type festlegt dann sollte der Wert auch als solche gespeichert werden (nicht nur im History wo es richtig gemacht wird).
Ein Beispiel: Booleans (ein/Aus-states) werden in der Visualisierung als solche behandelt aber eben meist mit Standardabfragen wie
if(xxx) oder if(!xxx) behandelt.
if('false') erzeugt dabei true!
if('true oder sonst was') auch
if('') erzeugt hingegen false.
Bei Zahlen ist's einfacher, 0 erzeugt false, alles andere true.
Umgekehrt ist es schon schwieriger, verschiedene Adapter müssen unterschiedliche Strategien anwenden. Ich habe z.B. ein Gerät bei dem true 100 ist (für 100%) und false 0.
Da das Gerät auch Dimmer bedienen kann sind bei diesen 0-100 möglich, bei Schaltern aber nur 0 oder 100. Deshalb muss ich bei Dimmern einen Zahlen-Datentyp mit min/0 ,max/100 und bei Schaltern einen binären Wert vorsehen. Wandelt man nun 'true' auf eine Zahl (z.B. mit 0+'true') ergibt das 1. Mit 1 würde der Dimmer aber nicht eingeschaltet werden.
Wird dieser Wert nun in den State als Zahl geschrieben kann er zwar richtig in einen boolean umgewandelt werden, aber wenn wer 'true' hineinschreibt kennt sich das Gerät nicht aus obwohl das script glaubt es ist true.
Deshalb ist es wichtig wenigstens zu wissen wie sich ioBroker selbst verhält und Adaptern oder scripts vorzugeben wie sie sich zu verhalten haben.
Deswegen sollten auch Default klar definiert sein, wie "" oder "false"== false und "was auch immer" == true genauso wie 0 == false und nicht 0 == true