Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. [gelöst] - Learning JS - ein erster Versuch

    NEWS

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    • Minor js-controller 7.0.7 Update in latest repo

    [gelöst] - Learning JS - ein erster Versuch

    This topic has been deleted. Only users with topic management privileges can see it.
    • Codierknecht
      Codierknecht Developer Most Active last edited by Codierknecht

      Basierend auf dem Thread script-funzt-nicht-mehr habe ich mich mal daran versucht, das umzubauen.
      Zu "verbessern" würde ich jetzt nicht sagen - ich will ja lediglich lernen.
      Also hier bitte keine fertigen Lösungen posten, sondern nur mitteilen, in welcher Zeile ein Fehler steckt oder wie man bestimmte Dinge besser löst.

      Gegegeben war folgendes Script:

      schedule('*/15 5-22 * * *', RunScript);
      
      function RunScript() {
        exec('python /opt/SunnyPortal/SunnyPortal.py 192.168.178.20', function (error, result, stderr) {
        console.log(result, true);
        array = result.split(' ')
      
          console.warn(array[21] + array[22]);
          console.warn(array[36] + array[37]);
          console.warn(array[51] + array[52]);
          createState('SunnyPortal-Watt', array[21] + array[22], true;
          createState('SunnyPortal-Heute', array[36] + array[37], true;
          createState('SunnyPortal-Gesamt', array[51] + array[52], true;
      });
      }
      

      Im ersten Wurf habe ich daraus jetzt mal das hier produziert:
      (wird laufend korrigiert und ergänzt)

      const execPython = 'python /opt/SunnyPortal/SunnyPortal.py 192.168.178.20';
      const dpPrefix = '0_userdata.0.SunnyPortal.';
      const arraySize = 6;
      const position = {"watt": 1, "today": 2, "total": 3};
      
      createState(dpPrefix + 'Watt', 0, {name: 'Aktuelle Leistung', type: 'number', unit: 'W'});
      createState(dpPrefix + 'Heute', 0, {name: 'Produziert heute', type: 'number', unit: 'kWh'});
      createState(dpPrefix + 'Gesamt', 0, {name: 'Produziert gesamt', type: 'number', unit: 'kWh'});
      
      function parseValue(value) {
        var result = parseFloat(value);
        if (!isNaN(result)) {
          return result;
        } else {
          throw Error('Value <' + value + '> could not be converted');  
        }
      }
      
      function writeValues(watts, today, total) {
        setState(dpPrefix + 'Watt', watts, true);
        setState(dpPrefix + 'Heute', today, true);
        setState(dpPrefix + 'Gesamt', total, true);
      };
      
      function getData() {
        try {
          exec(execPython, function (error, result) {
            if (!error) {
              console.log(result, true);
              var valueArray = result.split('):');
              if (valueArray.length != arraySize ) throw Error("Result does not match expected length");
              writeValues(parseValue(valueArray[position.watt]), parseValue(valueArray[position.today]), parseValue(valueArray[position.total]));
            } else {
              throw error;
            }
          });
        } catch (error) {
          console.error(error);
        }
      }
      
      schedule('*/15 5-22 * * *', getData);
      
      • Sinnvoll eingerückt
      • Die Variable array umbenannt und deklariert
      • Stringliterale an den Anfang, damit man die an einer zentralen Stelle ggf. ändern kann
      • createState nur 1x beim Start des Script, dann aber unterhalb von 0_userdata und mit Namen und Einheiten
      • Lesen der Daten und Schreiben der DP in eigene Methoden ausgelagert

      Und jetzt kommt ihr:

      • Ist hier noch etwas grundlegend falsch? Wenn ja: Was und warum?
      • Was könnte man noch optimieren?
      OliverIO Codierknecht paul53 5 Replies Last reply Reply Quote 1
      • OliverIO
        OliverIO @Codierknecht last edited by

        @codierknecht
        um die blöden nicht lesbaren Indexnummern wegzubekommen könnte man den JS enum Ersatz nehmen

        const position = {
          "watt":    21,
          "today":   36,
          "total":   51
        };
        
        

        und dann so adressieren

        valueArray[position.watt]
        
        Codierknecht A 2 Replies Last reply Reply Quote 1
        • Codierknecht
          Codierknecht Developer Most Active @Codierknecht last edited by

          Meine erste Frage wäre:
          Die anonyme Methode beim exec wird mit 3 Parametern aufgerufen.
          Kann man den 3. Parameter stderr einfach weglassen?

          Zweite Frage (auch zum "exec"):
          Wie würde man hier grundsätzlich ein Error-Handling einbauen?

          paul53 OliverIO 2 Replies Last reply Reply Quote 0
          • paul53
            paul53 @Codierknecht last edited by paul53

            @codierknecht sagte: createState nur 1x beim Start des Script, dann aber unterhalb von 0_userdata und mit Namen und Einheiten

            Sehr gut, aber es fehlt type: 'number'

            1 Reply Last reply Reply Quote 1
            • OliverIO
              OliverIO @Codierknecht last edited by

              @codierknecht sagte in Learning JS - ein erster Versuch:

              execCall

              würde ich liebe execPython nennen

              1 Reply Last reply Reply Quote 1
              • Codierknecht
                Codierknecht Developer Most Active @OliverIO last edited by Codierknecht

                Gute Idee, ich ziehe das im Eingangspost nach.

                1 Reply Last reply Reply Quote 0
                • A
                  Ahnungsbefreit @OliverIO last edited by

                  @oliverio @Codierknecht Gute Idee von @OliverIO aber ich würde auch erst einmal prüfen, wie groß das Array ist und ob an den Stellen auch wirklich eine Zahl steht. Sonst steigt das Script aus oder Du schreibst Müll in den Datenpunkt

                  Codierknecht 2 Replies Last reply Reply Quote 1
                  • paul53
                    paul53 @Codierknecht last edited by paul53

                    @codierknecht sagte: Kann man den 3. Parameter stderr einfach weglassen?

                    Ja.

                    @codierknecht sagte: Wie würde man hier grundsätzlich ein Error-Handling einbauen?

                    Einfachste Version:

                    if(!error) {
                        // Auswertung von stdout / result
                    }
                    
                    1 Reply Last reply Reply Quote 1
                    • OliverIO
                      OliverIO @Codierknecht last edited by OliverIO

                      @codierknecht sagte in Learning JS - ein erster Versuch:

                      Die anonyme Methode beim exec wird mit 3 Parametern aufgerufen.
                      Kann man den 3. Parameter stderr einfach weglassen?

                      ja, kann man weglassen.
                      Notfalls kann man die möglichen Paramter auch diese auch über das Parameter-Array arguments entnehmen.
                      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments?retiredLocale=de

                      Kommt aber darauf an, wie die 'Fehlerbehandlung genau läuft.
                      Bin da jetzt kein Spezialist, da ich mit exec noch nicht so oft gearbeitet habe.

                      1. Fall 1: Programm gibt keinen Rückgabe Status, dann wurde es für node ohne Fehler ausgeführt. Wenn Programm den Fehler nur in stderr schreibt, dann muss da geparst werden
                      2. Fall 2: Programm gibt Rückgabe code für Fehler zurück, der müsste dann in error drin stehen. Die Fehlerbearbeitung müsste dann so aussehen
                      if (error) {
                      }
                      
                      1 Reply Last reply Reply Quote 0
                      • Codierknecht
                        Codierknecht Developer Most Active @Ahnungsbefreit last edited by

                        @ahnungsbefreit
                        Das Array sollte dabei ja fix sein. Ein

                        if (array.length != 99) throw "Result does not match expected length";
                        

                        sollte funktionieren, oder?

                        OK, die tatsächliche Größe des Array kenne ich aktuell nicht, da ich das Result aus dem Original-Post nie gesehen habe (oder zu faul bin das abzutippen).

                        Ich werde die Ergänzungen im im Eingangspost nachziehen, damit das hier nicht zu unübersichtlich wird.

                        1 Reply Last reply Reply Quote 0
                        • Codierknecht
                          Codierknecht Developer Most Active @Ahnungsbefreit last edited by

                          @ahnungsbefreit sagte in Learning JS - ein erster Versuch:

                          ob an den Stellen auch wirklich eine Zahl

                          Wirft parseInt() einen Fehler, wenn keine Zahl drin steht?

                          paul53 1 Reply Last reply Reply Quote 0
                          • paul53
                            paul53 @Codierknecht last edited by

                            @codierknecht sagte: Wirft parseInt() einen Fehler, wenn keine Zahl drin steht?

                            Nein, es liefert NaN (Not a Number).

                            Codierknecht 1 Reply Last reply Reply Quote 0
                            • Codierknecht
                              Codierknecht Developer Most Active @paul53 last edited by

                              @paul53 sagte in Learning JS - ein erster Versuch:

                              Nein, es liefert NaN (Not a Number).

                              Wie prüft man dann möglichst elegant?

                              if (isNaN(parseInt(valueArray[position.watt]) || isNaN(parseInt(valueArray[position.today]) ... 
                              

                              sieht irgendwie reichlich sperrig aus.
                              OK, man könnte das auch noch in eine Prüfmethode auslagern.

                              Ihr seit mir schon fast zu schnell. Ich komme ja kaum noch nach 😉

                              paul53 1 Reply Last reply Reply Quote 0
                              • paul53
                                paul53 @Codierknecht last edited by paul53

                                @codierknecht sagte: Wie prüft man dann möglichst elegant?

                                Ich würde es so machen:

                                  if(!isNaN(watts)) setState(dpPrefix + 'Watt', watts, true);
                                // usw.
                                
                                Codierknecht 1 Reply Last reply Reply Quote 1
                                • Codierknecht
                                  Codierknecht Developer Most Active @paul53 last edited by

                                  @paul53 sagte in Learning JS - ein erster Versuch:

                                  @codierknecht sagte: Wie prüft man dann möglichst elegant?

                                  Ich würde es so machen:

                                    if(!isNaN(watts)) setState(dpPrefix + 'Watt', watts, true);
                                  // usw.
                                  

                                  Ist oben eingebaut.
                                  Das Problem das ich da sehe: Wenn da mal "NaN" drinsteht, wird lediglich nix in den DP geschrieben.
                                  Eleganter wäre ja, wenn das iwie auch zu 'nem Fehler führen würde, der geloggt werden kann.
                                  Ich bau oben mal eine Variante dafür ein. Mal sehen, was ihr davon haltet.

                                  1 Reply Last reply Reply Quote 0
                                  • paul53
                                    paul53 @Codierknecht last edited by paul53

                                    @codierknecht
                                    Übrigens: Bei den Werten, die im ursprünglichen Thema zu sehen sind, darf man nicht mit parseInt() wandeln, sondern mit parseFloat().
                                    Außerdem stehen die Werte laut Log immer hinter einem "):". Damit würde ich splitten.

                                    Codierknecht 2 Replies Last reply Reply Quote 0
                                    • Codierknecht
                                      Codierknecht Developer Most Active @paul53 last edited by

                                      @paul53 sagte in Learning JS - ein erster Versuch:

                                      @codierknecht
                                      Übrigens: Bei den Werten, die im ursprünglichen Thema zu sehen sind, darf man nicht mit parseInt() wandeln, sondern mit parseFloat().
                                      Außerdem stehen die Werte laut Log immer hinter einem "):". Damit würde ich splitten.

                                      Natürlich … werde ich oben ändern.

                                      @paul53 sagte in Learning JS - ein erster Versuch:

                                      @codierknecht
                                      Übrigens: Bei den Werten, die im ursprünglichen Thema zu sehen sind, darf man nicht mit parseInt() wandeln, sondern mit parseFloat().
                                      Außerdem stehen die Werte laut Log immer hinter einem "):". Damit würde ich splitten.

                                      Klingt auch etwas handlicher als mit Leerzeichen zu splitten.

                                      1 Reply Last reply Reply Quote 0
                                      • Codierknecht
                                        Codierknecht Developer Most Active @paul53 last edited by

                                        @paul53 sagte in Learning JS - ein erster Versuch:

                                        Außerdem stehen die Werte laut Log immer hinter einem "):". Damit würde ich splitten.

                                        Auch das habe ich oben geändert.
                                        Damit ist das mit den Array-Indizes 1,2 und 3 schon fast so einfach, dass man das enum auch wieder weglassen könnte.
                                        Ich lasse es aber wegen Wart- und Erweiterbarkeit mal drin.

                                        Codierknecht 1 Reply Last reply Reply Quote 0
                                        • Codierknecht
                                          Codierknecht Developer Most Active @Codierknecht last edited by

                                          @codierknecht
                                          Aktueller Stand für heute im Eingangspost.
                                          Das Konvertieren und Prüfen der Werte habe ich in eine eigene Funktion ausgelagert.

                                          Für heute lasse ich das erstmal so stehen. Morgen ist auch noch ein Tag.

                                          Letzte Erkenntnis für heute:
                                          Für mehr als 2-3 Zeilen JS lohnt sich auf jeden Fall die Installation von VSCode.

                                          Codierknecht 1 Reply Last reply Reply Quote 0
                                          • Codierknecht
                                            Codierknecht Developer Most Active @Codierknecht last edited by

                                            @codierknecht
                                            Warum meckert VSCode hier?
                                            f347a38c-68df-48d0-b36a-071ec9ef02b8-image.png

                                            OliverIO 1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post

                                            Support us

                                            ioBroker
                                            Community Adapters
                                            Donate

                                            577
                                            Online

                                            31.6k
                                            Users

                                            79.5k
                                            Topics

                                            1.3m
                                            Posts

                                            5
                                            31
                                            854
                                            Loading More Posts
                                            • Oldest to Newest
                                            • Newest to Oldest
                                            • Most Votes
                                            Reply
                                            • Reply as topic
                                            Log in to reply
                                            Community
                                            Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                                            The ioBroker Community 2014-2023
                                            logo