NEWS
Anfänger benötigt diverse Hilfestellungen
-
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:
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 -
@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.
-
@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 CodeDas 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.
-
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.
-
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)
-
@bambam89 sagte in Anfänger benötigt diverse Hilfestellungen:
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.
-
@asgothian said in Anfänger benötigt diverse Hilfestellungen:
@bambam89 sagte in Anfänger benötigt diverse Hilfestellungen:
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: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?
-
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; } }
-
Halt, eins nach dem anderen
@asgothian said in Anfänger benötigt diverse Hilfestellungen:
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
-
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.