NEWS

Javascript: gefährliches Halbwissen + Syntaxprobleme = Frust


  • OliverIO paul53 hans_999

    Ok, dann will ich mal etwas zu meinem Projekt erzählen, um es besser verdeutlichen zu können.
    Ich nutze für für unterwegs und zur schnellen Kontrolle den iogo Adapter und die dazugehörige App. Ich mag kein VIS und brauche auch keine bunten Felder. Klarer kurzer Text. iogo zeigt alle DP die ein enum hat. Das werden mir langsam aber zu viele DP die ich schnell im Blick haben will. Deswegen habe ich mir einige scripts gebaut die mehrere Gruppen zu einer Tabelle zusammenführen.
    Beispiel: Jetzt gab es einen thread über shellys und deren Temperatur, schnell habe ich dann zum Test eine Warntemperatur erstellt um nicht ständig mir die Zahlen ansehen zu müssen. Die Grundtemperaturen sind aber Grund verschieden, je nachdem wo der shelly verbaut wurde.
    Also will ich in dem array noch für jeden shelly eine eigene Warntemperatur einstellen können. Dies will ich auch schon seit langem auch für Warnzeiten von Verbrauchern machen, aber mir fehlte noch die nötige Idee. die aber nicht übermäßig viele DP verschlingt.

    Diese Idee ist jetzt also ein dynamisches Menü aus DP. Struktur kommt dann später. Mir war aber nie klar wie ich die common.states schnell und einfach verändern kann. Dabei soll aber nicht das State selbst sondern eben die Auswahlmöglichkeit verändert werden. Durch Zufall habe ich dann einen Thread gesehen wie man Dinge im DP anpassen kann.

    Hier also das beisherige testscript:

    function listsGetSortCompare(type, direction) {
      var compareFuncs = {
        "NUMERIC": function(a, b) {
            return parseFloat(a) - parseFloat(b); },
        "TEXT": function(a, b) {
            return a.toString() > b.toString() ? 1 : -1; },
        "IGNORE_CASE": function(a, b) {
            return a.toString().toLowerCase() > b.toString().toLowerCase() ? 1 : -1; },
      };
      var compare = compareFuncs[type];
      return function(a, b) { return compare(a, b) * direction; }
    }
    
    const IDs = Array.prototype.slice.apply($("channel[state.id=linkeddevices.0.Shelly_Temp.]")).slice().sort(listsGetSortCompare("TEXT", 1));
    const test = 'messwerte.0.Hilfsdaten.test';
    var anzahl = (IDs.length - 1);
    var Werteliste = [];
    var Wertezeile = [];
    
    
    for(let i = 0; i < IDs.length; i++) {
        let id = IDs[i];
        let name = getObject(id).common.name;
       //if (i != anzahl) {
       //     Wertezeile = ['"',i,'": "',name,'",'].join(''); //hier war ich noch der Meinung die , am Schluss selbst hinzufügen zu müssen
       // } else {
       //     Wertezeile = ['"',i,'": "',name,'"'].join('');
       // };
        var Wertezeile = [i,'": "', name].join(''); //hier wurde ich dann sehr dirty
        console.log(Wertezeile);
        Werteliste[(i)] = name;
    };
     
    
    
    
    console.log(Werteliste.join('\n'));
    //extendObject(test,{common: {states: {      "0": "eins",
    //      "1": "zwei"}}});  //das ist die Form wie es aussehen sollte
    extendObject(test,{common: {states: Werteliste}});
    console.log (getObject(test).common.states);
    
    
    

    die erste Funktion sortiert nur nach Namen. Die auskommentierten Stellen sind frühere Versuche, die aber nur Probleme machten.
    Die ersten Tests haben mir dann verdeutlicht, das leider ' " ' niemals das " so reinkommt wie man es will, denn es wird automatisch ein / davor gesetzt.
    Das ganze reinsetzen wird auch mit [ ] anstatt { } , durch das testen wie man andere Klammer setzt hatte ich das System dann mal gekillt.
    klammern.png
    Wie man hier sehen kann, werden nämlich die : nicht erlaubt, das geht nur mit den { } Klammern.

    Wie man ganz unten sehen kann, will ich ein Auswahl mit Zahl und dem richtigen Begriff, leider setzt er von alleine immer um jeder Zeile eigene " ", deswegen habe ich in der "dirty" Zeile die " Bereiche unterbrochen, klappte aber wegen den / auch nicht.

    Ich schätze die join('') machen mir auch Probleme, hab aber keine Ahnung wie das anders gehen soll. Wenn man sich die ganzen console.logs ansieht, dann fällt einem auf, das das log meist dann " anzeigt, wenn man aber die Maus über die Zeile im log hält, dann wieder nur ' ankommen.

    In dem Objekt selbst sieht es manchmal dann wieder ganz anders aus.

    wenn ich pro Zeile nur name reinsetze, dann klappt das auch recht gut, aber ich hätte eben im DP lieber eine Nummer zur Weiterverarbeitung als den Namen selbst.

    So sieht das dann in iogo aus:
    Screenshot_20200326-191948_iogo.jpg Screenshot_20200326-191936_iogo.jpg

    Ich hoffe ihr könnt meiner Idee einigermaßen folgen und habt eine Idee.
    Danke schon mal


  • e-s sagte:

    habt eine Idee.

    Prinzip:

    var Werteliste = {};
    for(let i = 0; i < IDs.length; i++) {
        let id = IDs[i];
        Werteliste[i] = getObject(id).common.name;
    }
    log(JSON.stringify(Werteliste)); // Format wie im Tab "Objekte" unter RAW
    let obj = getObject(test);
    obj.common.states = Werteliste;
    obj.common.max = IDs.length - 1;
    setObject(test, obj);
    

  • paul53
    Danke, mal wieder.....

    Klappt natürlich so wie es soll.

    Aber das ist genau das was ich meine, dein Code ist wieder so simpel, das es mich aufregen könnte, aber ich weiß genau das ich nie auf diese Idee gekommen wäre.
    Ich mag es nicht, immer sofort zu fragen anstatt selbst den Kopf zu nutzen, aber es bleibt mir wohl keine andere Wahl.
    Genau das meinte ich mit Doku, wo kann ich sowas nachlesen.
    Hatte mal bei kindle unlimited ein JS Buch gelesen, aber das geht irgendwann nur noch in Richtung HTML, nichts mit DP wie sie iobroker. Und bei iobroker finde ich eben nie etwas zu solch speziellen Problemen.


  • e-s sagte:

    Doku, wo kann ich sowas nachlesen.

    Ich nutze meist selfhtml zum Nachlesen.

  • Starter

    die kunst ist die frage richtig bei google einzugeben.
    Was mir bei deinem ersten skript aufgefallen ist.
    du solltest dich nochmal mit den unterschieden von Objekten und Arrays beschäftigen.
    In Zeile 17, ich vermute du willst Werteliste initialisieren ist das x etwas komisch.
    Das bedeutet, das du ein Array anlegen willst und erst einmal genau ein Element enthält, nämlich x (als variable, nicht als Wert.
    Da x aber nicht existiert, dürfte das erste Element in diesem Array undefined sein.

    Dann bei dem nächsten bild mit den states.
    Wenn du ein Array anlegst, und der Index ist durchgängig bzw. dir egal was es für eine Nummer ist, dann reicht
    ["wert1","Wert2","Wert3"] javascript indiziert dann selber
    Wenn du den Index selber benennen möchtst und es ist entweder keine Zahl oder nicht aufsteigend von 0, dann ist es streng genommen kein Array mehr, sondern ein Objekt. d.h. Array-Schleifen (bsp forEach oder for(;;)) funktionieren dann nicht mehr, sondern man muss Objektschleifen (for item in objekt) nehmen.

    Durch die hohe flexibilität von javascript (automatische typumwandlung) entstehen of Probleme, wenn man die magie hinter javascript nicht kennt. Daher wird für den profieinsatz auch gern Typsichere Sprachen verwendet.

    Deswegen ist es gut mit einem debugger zu arbeiten. Den gibt es so nicht für die iobroker javascript engine.
    Wenn ich mit Skripten arbeite (ich versuche das zu vermeiden), dann baue ich mir das Gerüst meist im Browser auf, dort wo iobroker Spezial kommt, belege ich dumme variablen vor und teste dann in ruhe dort mit debugger durch.


  • OliverIO
    Wo da auf einmal das X herkommt ist mir schleierhaft, bei mir im script war es das nicht.
    Danke nochmal, versuche weiter zu lesen.

    Für mich war ja eben auch die Frage, wie kann der Editor verbessert werden, da die externen Editoren wieder nicht die Besonderheiten von iobroker kennen.


  • e-s sagte in Javascript: gefährliches Halbwissen + Syntaxprobleme = Frust:

    Aber das ist genau das was ich meine, dein Code ist wieder so simpel, das es mich aufregen könnte, aber ich weiß genau das ich nie auf diese Idee gekommen wäre.

    Mit mehr Erfahrung schon, ich bin noch weit von paul53 entfernt und trotzdem fallen mir die Haare aus, wenn ich meine älteren Scripte anschaue. 🙂

  • Starter

    In der "Programmierkunst" gibt es u.a. zwei zentrale Komponenten

    • die Logik: Wie soll "etwas" ablaufen, damit ein bestimmtes Ziel erreicht wird. Hierzu werden Erfahrungen, Ideen, vielleicht sogar Intuition neben elementaren Kenntnissen benötigt (siehe auch die Anmerkung von ticaki). Hier muss man von klein (im Sinne von kleinen Aufgabenstellungen) auf anfangen. Ein Versuch, mit einem ersten Programm eine Super de Luxe Lösung zu "basteln", kann nur schief gehen.

    • der Code: Ähnlich wie beim Erlernen einer natürlichen Sprache musst Du auch die Elemente einer Programmiersprache erlernen (elementare Befehle, Datentypen, Objekte, ...). Ohne (bildlich gesprochen) "Vokabel lernen" geht dies nicht ab (siehe hierzu auch den Hinweis von OliverIO). Die Methode "Trial and Error" ist dabei eine bedeutsame Methode.

    Also: Nicht entmutigen lassen, aber erst mal mit kleineren Aufgabenstellungen anfangen.


  • mal eine kurze weitere Frage, habe heute 3 neue shellys verbaut und in iobroker integriert.
    ich erstelle ja eine Liste über:

    const IDs = Array.prototype.slice.apply($("channel[state.id=linkeddevices.0.Shelly_Temp.]")).slice().sort(listsGetSortCompare("TEXT", 1));
    

    durch ein einfachen neustart des scripts habe ich die neuen devices nicht in die Liste bekommen, erst als ich unter instances den javascript adapter neu gestartet habe, waren die neuen da.


  • e-s sagte:

    erst als ich unter instances den javascript adapter neu gestartet habe, waren die neuen da.

    Es ist ein bekanntes Problem, dass die Puffer der Javascript-Instanz nicht (immer) automatisch aktualisiert werden.

Suggested Topics

  • 5
  • 2
  • 3
  • 1
  • 38
  • 20
  • 10
  • 13

2.2k
Online

34.7k
Users

40.8k
Topics

558.5k
Posts