Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. Anfänger benötigt diverse Hilfestellungen

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    Anfänger benötigt diverse Hilfestellungen

    This topic has been deleted. Only users with topic management privileges can see it.
    • B
      BamBam89 last edited by

      Hallo zusammen,

      ich weiß, der Titel ist leider wenig aussagekräftig, dieses Topic wird aber vermutlich über mehrere Themen gehen.

      Vorab, ich bin was Java angeht absoluter Neuling. Alles was ich bis dato machen musste konnte ich gut mit Blockly abfertigen. Aber bei meinem jetzigen Vorhaben stößt Blockly vermutlich an seine Grenzen.
      Zum Thema.

      Ich bin derzeit dabei mir einen Cocktailautomaten zu bauen. Die Hardware und das Skript zur Ausgabe (Blockly) ist bereits fertig. Nun bin ich dabei die Sache zu Visualisieren.
      Zur Visualisierung möchte ich in Teilen Widget IconList + Select Icon von @Scrounger verwenden. Diese Visualisierung dynamisch zu gestalten finde ich super.
      Dazu habe ich auch bereit einige Hilfe von Ihm bekommen, sonst wäre ich erst gar nicht so weit gekommen.

      Aktuell nutze ich den folgenden Code. Ist erstmal nur ein Beispiel mit 5 Cocktails.

      let idDatenpunkt_IconList = '0_userdata.0.Steuerung.JSON.JSON_Cocktails'
      let idDatenpunkt_Select_Sort = '0_userdata.0.Steuerung.JSON.Cocktail_sortieren'
      let idDatenpunkt_Select_Filter = '0_userdata.0.Steuerung.JSON.Cocktail_filtern'
       
      let iconList = [
          {
              image: "/vis.0/main/Bilder Cocktails Beschreibungen/PlantersPunch_Beschreibung.png",
              listType: "buttonToggle",
              objectId: "0_userdata.0.Cocktails.Alkoholfrei.Ananascocktail",
              background: "linear-gradient(0deg, grey, white)",
              inhalt: "Wodka"
          }, {
              image: "/vis.0/main/Symbole/Falsche_voll_2.png",
              listType: "buttonToggle",
              objectId: "0_userdata.0.Cocktails.Alkoholfrei.Babyface",
              background: "linear-gradient(0deg, grey, white)",
              inhalt: "Gin"
          }, {
              image: "/vis.0/main/Bilder Cocktails Beschreibungen/PlantersPunch_Beschreibung.png",
              listType: "buttonToggle",
              background: "linear-gradient(0deg, grey, white)",
              inhalt: "Rum"
          }, {
              image: "/vis.0/main/Symbole/Falsche_voll_2.png",
              listType: "buttonToggle",
              background: "linear-gradient(0deg, grey, white)",
              inhalt: "Wodka"
          }, {
              image: "/vis.0/main/Symbole/Falsche_voll_2.png",
              listType: "buttonToggle",
              background: "linear-gradient(0deg, grey, white)",
              inhalt: "Tequila"
          }
      ]
       
      // auf Änderungen des Datenpunktes zum sortieren hören
      on({ id: idDatenpunkt_Select_Sort, change: 'any' }, updateIconList);
       
      // auf Änderungen des Datenpunktes zum filtern hören
      on({ id: idDatenpunkt_Select_Filter, change: 'any' }, updateIconList);
       
      updateIconList();
      async function updateIconList(obj) {
          try {
              if (obj && obj.id === idDatenpunkt_Select_Sort) {
                  // wir wollen sortieren nach einer Property der iconList, z.B. inhalt, background, etc. -> muss im Datenpunkt des select widgets als Wert stehen
                  let sortMode = obj.state.val;
                  list.sort(function (a, b) {
                      return (a[sortMode].toLowerCase() == b[sortMode].toLowerCase() ? 0 : +(a[sortMode].toLowerCase() > b[sortMode].toLowerCase()));
                  });
              } else if (obj && obj.id === idDatenpunkt_Select_Filter) {
                  // wir wollen filtern nach inhalt, Filterwort Wodka, Gin, etc -> muss im Datenpunkt des select widgets als Wert stehen 
                  list = list.filter(function (item) {
                      return item.inhalt === obj.state.val;
                  });
              }
       
              await setStateAsync(idDatenpunkt_IconList, JSON.stringify(iconList), true);
          } catch (error) {
              console.error(`[updateIconList] error: ${error.message}, stack: ${error.stack}`);
          }
      }
      
      

      Die entsprechenden Datenpunkte sind angelegt:

      6399b7d0-87a6-465c-92b4-7c4038ce8a43-image.png

      und werden vom Script bzw vom Select Widget auch entsprechend gefüllt.
      Allerdings laufe ich auf einen Fehler. Lt. Log ist die Tabelle nicht definiert:

      javascript.0	2021-03-24 06:58:09.284	error	(1269) script.js.JSON.Cocktail_filtern_sortieren: [updateIconList] error: list is not defined, stack: ReferenceError: list is not defined at Object.updateIconList (script.js.JSON.Cocktail_filtern_
      

      Ich hab nun schon eine ganze Zeit versucht den Fehler selber zu finden. Leider vergebens....
      Wäre schön wenn ihr mir hier etwas Hilfestellung geben könntet.

      Vielen Dank euch.
      Gruß Christian

      Asgothian 1 Reply Last reply Reply Quote 0
      • Asgothian
        Asgothian Developer @BamBam89 last edited by

        @bambam89 sagte in Anfänger benötigt diverse Hilfestellungen:

        Ich hab nun schon eine ganze Zeit versucht den Fehler selber zu finden. Leider vergebens....
        Wäre schön wenn ihr mir hier etwas Hilfestellung geben könntet.

        • Bitte die vollständigen Log Zeilen Posten. Deine Fehlermeldung ist am hinteren Ende abgehackt. Genau da steht aber wo sich der Fehler befindet.
        • In der Meldung steht auch was der "Fehler" ist: "list not defined". Du nutzt also irgendwo ein Objekt mit dem Namen "list".
        • Das ist in der Funktion updateIconList der Fall, und zwar in den Zeilen 48 und 53.
        • Ohne das Skript vollständig analysiert zu haben gehe ich davon aus das an diesen Stellen An Stelle von "list." "iconList." stehen muss

        A.

        B 1 Reply Last reply Reply Quote 0
        • B
          BamBam89 @Asgothian last edited by

          @asgothian said in Anfänger benötigt diverse Hilfestellungen:

          @bambam89 sagte in Anfänger benötigt diverse Hilfestellungen:

          • Ohne das Skript vollständig analysiert zu haben gehe ich davon aus das an diesen Stellen An Stelle von "list." "iconList." stehen muss

          Diese Antwort war richtig 🙂 Super besten Dank.
          Allerdings kommt nun schon wieder das nächste Problem. Das Sortieren funktioniert nur einmalig.
          Ich vermute mal, das wenn ich die Liste einmal nach einem bestimmten Inhalt gefiltert habe z.B. Gin und danach nochmal nach Wodka filter, er nichts mehr finden wir, da die Tabelle ja bereits nur noch Getränke mit Gin anzeigt. Das zeigt auch so der Code

          Das ist der Inhalt des Datenpunktes vor dem ersten Filter (nach Skript Neustart):

          [{"image":"/vis.0/main/Bilder Cocktails Beschreibungen/PlantersPunch_Beschreibung.png","listType":"buttonToggle","objectId":"0_userdata.0.Cocktails.Alkoholfrei.Ananascocktail","background":"linear-gradient(0deg, grey, white)","inhalt":"Wodka"},{"image":"/vis.0/main/Symbole/Falsche_voll_2.png","listType":"buttonToggle","objectId":"0_userdata.0.Cocktails.Alkoholfrei.Babyface","background":"linear-gradient(0deg, grey, white)","inhalt":"Gin"},{"image":"/vis.0/main/Bilder Cocktails Beschreibungen/PlantersPunch_Beschreibung.png","listType":"buttonToggle","background":"linear-gradient(0deg, grey, white)","inhalt":"Rum"},{"image":"/vis.0/main/Symbole/Falsche_voll_2.png","listType":"buttonToggle","background":"linear-gradient(0deg, grey, white)","inhalt":"Wodka"},{"image":"/vis.0/main/Symbole/Falsche_voll_2.png","listType":"buttonToggle","background":"linear-gradient(0deg, grey, white)","inhalt":"Tequila"}]
          

          Und das nach dem ersten mal filtern:

          [{"image":"/vis.0/main/Bilder Cocktails Beschreibungen/PlantersPunch_Beschreibung.png","listType":"buttonToggle","objectId":"0_userdata.0.Cocktails.Alkoholfrei.Ananascocktail","background":"linear-gradient(0deg, grey, white)","inhalt":"Wodka"},{"image":"/vis.0/main/Symbole/Falsche_voll_2.png","listType":"buttonToggle","background":"linear-gradient(0deg, grey, white)","inhalt":"Wodka"}]
          

          Wie bekomme ich das denn nun so hin, das die Tabelle, wenn ein neues Filterkriterium gesetzt wird, erst wieder auf den Ursprung zurückgesetzt wird?
          Oder macht es Sinn die JSON Tabelle irgend wo fix stehen zu haben, auf die das Skript dann immer wieder zurück greift?
          Wenn das überhaupt geht?! 🙂 Wie gesagt, Anfänger eben.

          Asgothian 1 Reply Last reply Reply Quote 0
          • Asgothian
            Asgothian Developer @BamBam89 last edited by

            @bambam89

            Du brauchst eine 'lokale' Kopie der Liste.

            Auch hier - ich hab mir das nicht bis ins Detail angeschaut, aber wenn Du in deiner Funktion updateIconList am Anfang

            let localList = iconList;
            

            machst, und dann innerhalb der Funktion überall iconList durch localList ersetzt sollte es gehen.

            A.

            B 1 Reply Last reply Reply Quote 0
            • B
              BamBam89 @Asgothian last edited by

              @asgothian

              Da scheint was nicht zu funktionieren:
              Du sagtest in die Funktion soll der Deklaration der Variablen. Das sollte hier sein.

              updateIconList();
              let localList = iconList
              async function updateIconList(obj) {
                  try {
              

              Die iconList habe ich auf localList geändert:

                  try {
                      if (obj && obj.id === idDatenpunkt_Select_Sort) {
                          // wir wollen sortieren nach einer Property der iconList, z.B. inhalt, background, etc. -> muss im Datenpunkt des select widgets als Wert stehen
                          let sortMode = obj.state.val;
                          localList.sort(function (a, b) {
                              return (a[sortMode].toLowerCase() == b[sortMode].toLowerCase() ? 0 : +(a[sortMode].toLowerCase() > b[sortMode].toLowerCase()));
                          });
                      } else if (obj && obj.id === idDatenpunkt_Select_Filter) {
                          // wir wollen filtern nach inhalt, Filterwort Wodka, Gin, etc -> muss im Datenpunkt des select widgets als Wert stehen 
                          localList = localList.filter(function (item) {
                              return item.inhalt === obj.state.val;
                          });
                      }
               
                      await setStateAsync(idDatenpunkt_IconList, JSON.stringify(localList), true);
                  } catch (error) {
                      console.error(`[updateIconList] error: ${error.message}, stack: ${error.stack}`);
                  }
              

              Dann bekomme ich folgenden Fehler:

              	javascript.0 (1269) script.js.JSON.Cocktails_filtern_sortieren: [updateIconList] error: Cannot access 'localList' before initialization, stack: ReferenceError: Cannot access 'localList' before initialization at updateIconList (script.js.JSON.Cocktails_filtern_sortieren:60:67) at script.js.JSON.Cocktails_filtern_sortieren:43:1 at script.js.JSON.Cocktails_filtern_sortieren:66:3 at Script.runInContext (vm.js:130:18) at Script.runInNewContext (vm.js:135:17) at execute (/opt/iobroker/node_modules/iobroker.javascript/main.js:1423:27) at prepareScript (/opt/iobroker/node_modules/iobroker.javascript/main.js:1622:38) at /opt/iobroker/node_modules/iobroker.javascript/main.js:1722:17 at Immediate._onImmediate (/opt/iobroker/node_modules/iobroker.javascript/main.js:1238:17) at processImmediate (internal/timers.js:463:21)
              
              Asgothian 1 Reply Last reply Reply Quote 0
              • Asgothian
                Asgothian Developer @BamBam89 last edited by Asgothian

                @bambam89 sagte in Anfänger benötigt diverse Hilfestellungen:

                @asgothian

                Da scheint was nicht zu funktionieren:
                Du sagtest in die Funktion soll der Deklaration der Variablen. Das sollte hier sein.

                updateIconList();
                let localList = iconList
                async function updateIconList(obj) {
                    try {
                

                In, nicht vor:

                updateIconList();
                async function updateIconList(obj) {
                    try {
                          let localList = iconList
                

                Kontext: Die Fehlermeldung "cannot access... before initialisation" kommt daher das in deiner Version die Funktion updateIconList aufgerufen wird bevor der Variable localList ein Wert zugewiesen wird.

                A.

                B 1 Reply Last reply Reply Quote 0
                • B
                  BamBam89 @Asgothian last edited by

                  @asgothian said in Anfänger benötigt diverse Hilfestellungen:

                  @bambam89 sagte in Anfänger benötigt diverse Hilfestellungen:

                  @asgothian

                  In, nicht vor:

                  updateIconList();
                  async function updateIconList(obj) {
                      try {
                            let localList = iconList
                  

                  Kontext: Die Fehlermeldung "cannot access... before initialisation" kommt daher das in deiner Version die Funktion updateIconList aufgerufen wird bevor der Variable localList ein Wert zugewiesen wird.

                  A.

                  Ach verflixt. OK mit deiner Erklärung hat es nun gefunkt. Verstanden. Ok super funktioniert. Schon einmal vielen Dank dafür

                  Nun habe ich noch eine weitere Baustelle und ich hab überhaupt keine Ahnung wo ich da ansetzen muss.
                  Ist auch nur NicetoHave wenn eigentlich auch nicht ganz unwichtig.

                  Die iconList würde ich gerne von den Zutaten abhängig machen. Kleine Erklärung dazu.
                  Die ganze Anlage wird später 28 Zutaten ausgeben können. Jetzt kann es natürlich sein, das während einer Feier mal eine Flasche leer wird, für die man keinen Ersatz hat. Angenommen O-Saft ginge aus und es gibt keinen Nachschub.

                  Nun wird das zwar in meinem Blockly-Ausgabeskript abgefragt ob die Restmengen in den Flaschen ausreichend sind, um den gewählten Cocktail zuzubereiten, elegant ist das natürlich nicht. Es wird dann eben eine Meldung ausgegeben sollte die Menge nicht ausreichen.
                  Gerade bei solch einer Hauptzutat könnte es dann durchaus passieren, das sich ein Gast diverse Cocktails aussucht und alle nicht zubereitet werden können, da überall O-Saft benötigt wird.
                  Eleganter wäre das z.B. in gewissen Intervallen abgefragt wird, ob noch alle Zutaten für Cocktail xy zu Verfügung stehen.
                  Für jede Zutat gibt es einen Datenpunkt:

                  e84df6d7-3eb6-423d-97ec-f77325359308-image.png

                  Vermutlich müsste die JSON Tabelle dann von jedem Cocktail alle Zutaten enthalten.

                  Also in etwas:

                  let iconList = [
                      {
                          image: "/vis.0/main/Bilder Cocktails Beschreibungen/PlantersPunch_Beschreibung.png",
                          listType: "buttonToggle",
                          objectId: "0_userdata.0.Cocktails.Alkoholfrei.Ananascocktail",
                          background: "linear-gradient(0deg, grey, white)",
                          Zutat_1: "O-Saft",
                          Zutat_2: "Wodka",
                          Zutat_3: "Grenadin"
                      }
                  

                  Der Wunsch ist, das dann eben nur die Cocktails auch angezeigt werden, die auch tatsächlich zubereitet werden können.
                  So könnte man die Anlage z.b. auch für eine kleine Poolparty mit weniger Zutaten betreiben.

                  Wäre so etwas denkbar? Oder müsste man das anders lösen? Oder ist aufgrund der Komplexität davon abzuraten?

                  Asgothian 1 Reply Last reply Reply Quote 0
                  • Asgothian
                    Asgothian Developer @BamBam89 last edited by Asgothian

                    @bambam89

                    Ich würde es umgekehrt anlegen.

                    • Mach pro Zutat eine Liste in der die Cocktails angegeben sind die diese Zutat benötigen.
                    • Definier Dir eine Liste die alle Cocktails mit image und allem beinhaltet (hast du da ja schon, ist "liste der erlaubten Cocktails")
                    • Zu beginn des Skriptes: Lies den Status von jeder Zutat aus. Wenn die Flasche leer ist entferne alle Cocktails die diese Zutat brauchen aus deiner Liste der erlaubten
                    • Auf jede Zutat einen Trigger:
                      --Wenn Änderung falsch auf wahr: entferne alle Cocktails die diese Zutat brauchen aus deiner Liste der erlaubten (a)
                      --Wenn Änderung wahr auf falsch: prüfe für jeden Cocktail der die Zutat braucht: Ist er noch nicht in der Liste der erlaubten Cocktails => füge ihn hinzu. (b)

                    Damit hast du letztendlich alle Infos, und die Liste der "erlaubten" Cocktails kannst du dann wie iconList in deinem Beispiel verwenden.

                    Für die Funktion bei (a) kannst du einen einfachen Weg wählen. Annahme: allowedList sind alle cocktails die du mischen kannst. requireComponent ist die Liste der Cocktails die eine bestimmten Inhaltsstoff benötigen

                    allowedList = RemoveCocktails(allowedList, requireComponent);
                    
                    function RemoveCocktails(ListToRemoveFrom, ListToRemove) {
                      return ListToRemoveFrom.filter(function(item) { return ListToRemove.indexOf(item)>0 });
                    }
                    

                    bei (b) sieht die Funktion so aus:

                    allowedList = AddCocktails(allowedList, requireComponent);
                    
                    function AddCocktails(ListToAddTo, ListToAdd) {
                      let tempList = ListToAddTo.concat(ListToAdd)
                      return = tempList.filter(item, index) { return tempList.IndexOf(item)== index; }
                    }
                    
                    B 1 Reply Last reply Reply Quote 0
                    • B
                      BamBam89 @Asgothian last edited by

                      Halt, eins nach dem anderen 🙂

                      @asgothian said in Anfänger benötigt diverse Hilfestellungen:

                      @bambam89

                      Ich würde es umgekehrt anlegen.

                      • Mach pro Zutat eine Liste in der die Cocktails angegeben sind die diese Zutat benötigen.

                      Für mein Verständnis würde das für zwei Cocktails so aussehen:

                      {
                          "Tabelle1": [
                              {
                                  "Wodka": "Wodka Sunrise"
                              },
                              {
                                  "Wodka": "Long Island Icetea"
                              }
                          ],
                          "Tabelle2": [
                              {
                                  "Rum": "Long Island Icetea"
                              }
                          ],
                          "Tabelle3": [
                              {
                                  "Tequila": "Long Island Icetea"
                              }
                          ],
                          "Tabelle4": [
                              {
                                  "Gin": "Long Island Icetea"
                              }
                          ],
                          "Tabelle5": [
                              {
                                  "Cointreau": "Long Island Icetea"
                              }
                          ],
                          "Tabelle6": [
                              {
                                  "Limettensaft": "Long Island Icetea"
                              }
                          ],
                          "Tabelle7": [
                              {
                                  "Cola": "Long Island Icetea"
                              }
                          ],
                          "Tabelle8": [
                              {
                                  "Grenadine": "Wodka Sunrise"
                              }
                          ],
                          "Tabelle9": [
                              {
                                  "Orangensaft": "Wodka Sunrise"
                              }
                          ]
                      }
                      

                      Oder was muss ich unter "mache eine Liste" verstehen?

                      • Definier Dir eine Liste die alle Cocktails mit image und allem beinhaltet (hast du da ja schon, ist "liste der erlaubten Cocktails")

                      Korrekt, das ist ja aktuell die iconList

                      Asgothian 1 Reply Last reply Reply Quote 0
                      • Asgothian
                        Asgothian Developer @BamBam89 last edited by

                        @bambam89

                        Viel einfacher:

                        let NeedsVodka = [ "Wodka Sunrise", "long Island Icetea" ]
                        let NeedsCola = [ "whateverneedsthatstuff", "whatevqrelseneedsthatstuff"]
                        
                        
                        on({id:"Flasche_Vodka_leer", change:"ne"}, function(obj) {
                          if (obj.state.value) {
                            allowedList = RemoveCocktails(allowedList, NeedsVodka);
                          }
                         else {
                           allowedList = AddCocktails(allowedList, NeedsVodka);
                        } 
                        
                        on({id:"Flasche_Cola_leer", change:"ne"}, function(obj) {
                          if (obj.state.value) {
                            allowedList = RemoveCocktails(allowedList, NeedsCola);
                          }
                         else {
                           allowedList = AddCocktails(allowedList, NeedsCola);
                        } 
                        
                        }); 
                        

                        A.

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

                        Support us

                        ioBroker
                        Community Adapters
                        Donate

                        393
                        Online

                        31.9k
                        Users

                        80.2k
                        Topics

                        1.3m
                        Posts

                        2
                        10
                        312
                        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