Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Stefan-G

    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

    S
    • Profile
    • Following 0
    • Followers 1
    • Topics 0
    • Posts 17
    • Best 1
    • Groups 1

    Stefan-G

    @Stefan-G

    1
    Reputation
    26
    Profile views
    17
    Posts
    1
    Followers
    0
    Following
    Joined Last Online

    Stefan-G Follow
    Starter

    Best posts made by Stefan-G

    • RE: Einfach mal zeigen will….. :-) - Teil 2

      @Spampunk Hi Timo,
      sorry für meine späte Antwort. Bzgl. 'Home' hält mich gerade der nicht smarte Teil in Atem (buddle im Garten Tanks ein, die dann später natürlich wieder smart gesteuert werden sollen). Zu Deiner Frage hat Marc schon mal was geschrieben:

      @Marc_St said in Einfach mal zeigen will….. 🙂 - Teil 2:

      Habe auch versucht, Dein "großes" Beispiel zum Laufen zu bekommen und leider reagiert das nicht bei mir auf die Variablen. Kommt jede Variable in ein extra Basic-HTML Widget (muss ja irgendwie)? `

      Ja, und zwar mit der ID. Im Widget steht dann also
      {modbus.0.holdingRegisters.10_Kollektor} °C

      Das separate Widget ist der Workaround zur Flimmer-Vermeidung, Dafür musst Du dann mit der ID arbeiten, da ansonsten der Javascript-Code keine Change hat, der Wert so auszulesen:
      document.getElementById('kollektor_temp').innerHTML);

      Es ist so etwas wie ein indirektes Binding. Wenn Du dann auch Einheiten haben willst, muss sich die ID nur auf die Zahl beziehen und darf die Einheit nicht umfassen. Das zeigt alles der Einzeiler.

      Konkret kannst Du bei Dir den Datenpunkt in einem Basic HTML Widget darstellen:

      <span id="kollektor_temp">{javascript.0.vbus.values.Temperaturesensor1}</span>
      

      ({javascript.0.vbus.values.Temperaturesensor1} solltest Du natürlich durch was ersetuen, dass Du anzeigen willst.)

      Durch <span id="kollektor_temp"> hast Du dann etwas, dass Du im Javascipt-Teil innerhalb des SVGs nutzen kannst.

      var leitungsfarbe = color(parseInt(document.getElementById('kollektor_temp').innerHTML));
      

      Den Pufferspeicher und die Flamme findest Du im SVG (Flamme ist von Marc geklaut). Du kannst das SVG entweder mit nem entsprechenden Grafikprogramm öffnen (Marc hat da Boxy SVG empfohlen, ich war dann zu geizig und hab doch InkScape genommen, dass den Code aber etwas anders formatiert). Die SVG kannst Du auch einfach im Texteditor öffnen, dort findest Du Kommentare, wo sich der Speicher findet und wo die Flamme. Die IDs der Einzelelemente sollten helfen.

      Anbei mal ein Souce-InkScape-SVG mit den Bausteinen für den Speicher.
      speicher.svg

      posted in Praktische Anwendungen (Showcase)
      S
      Stefan-G

    Latest posts made by Stefan-G

    • RE: Einfach mal zeigen will….. :-) - Teil 2

      @Spampunk Hi Timo,
      sorry für meine späte Antwort. Bzgl. 'Home' hält mich gerade der nicht smarte Teil in Atem (buddle im Garten Tanks ein, die dann später natürlich wieder smart gesteuert werden sollen). Zu Deiner Frage hat Marc schon mal was geschrieben:

      @Marc_St said in Einfach mal zeigen will….. 🙂 - Teil 2:

      Habe auch versucht, Dein "großes" Beispiel zum Laufen zu bekommen und leider reagiert das nicht bei mir auf die Variablen. Kommt jede Variable in ein extra Basic-HTML Widget (muss ja irgendwie)? `

      Ja, und zwar mit der ID. Im Widget steht dann also
      {modbus.0.holdingRegisters.10_Kollektor} °C

      Das separate Widget ist der Workaround zur Flimmer-Vermeidung, Dafür musst Du dann mit der ID arbeiten, da ansonsten der Javascript-Code keine Change hat, der Wert so auszulesen:
      document.getElementById('kollektor_temp').innerHTML);

      Es ist so etwas wie ein indirektes Binding. Wenn Du dann auch Einheiten haben willst, muss sich die ID nur auf die Zahl beziehen und darf die Einheit nicht umfassen. Das zeigt alles der Einzeiler.

      Konkret kannst Du bei Dir den Datenpunkt in einem Basic HTML Widget darstellen:

      <span id="kollektor_temp">{javascript.0.vbus.values.Temperaturesensor1}</span>
      

      ({javascript.0.vbus.values.Temperaturesensor1} solltest Du natürlich durch was ersetuen, dass Du anzeigen willst.)

      Durch <span id="kollektor_temp"> hast Du dann etwas, dass Du im Javascipt-Teil innerhalb des SVGs nutzen kannst.

      var leitungsfarbe = color(parseInt(document.getElementById('kollektor_temp').innerHTML));
      

      Den Pufferspeicher und die Flamme findest Du im SVG (Flamme ist von Marc geklaut). Du kannst das SVG entweder mit nem entsprechenden Grafikprogramm öffnen (Marc hat da Boxy SVG empfohlen, ich war dann zu geizig und hab doch InkScape genommen, dass den Code aber etwas anders formatiert). Die SVG kannst Du auch einfach im Texteditor öffnen, dort findest Du Kommentare, wo sich der Speicher findet und wo die Flamme. Die IDs der Einzelelemente sollten helfen.

      Anbei mal ein Souce-InkScape-SVG mit den Bausteinen für den Speicher.
      speicher.svg

      posted in Praktische Anwendungen (Showcase)
      S
      Stefan-G
    • RE: Einfach mal zeigen will….. :-) - Teil 2

      Hi Timo,

      da mir Marc damals geholfen hat versuche ich mal ein paar von Deinen Fragen zu beantworten.

      @Spampunk said in Einfach mal zeigen will….. 🙂 - Teil 2:

      Ist Dein gesamtes Flussdiagramm ein einziges SVG, oder hast Du diverse SVGs im VIS zusammengefügt?

      Wenn ich mich recht erinnere hatte Marc sein SVG mal hier gepostet und es war eines, das alles außer die Labels (externe Bindings) enthielt, hat aber leider die Forum-Umstellung nicht überlebt, glaub ich. Kann Dir nur anbieten, das zu posten, was ich daraus gemacht hab (auch wenn auf Grund von Zeitmangel noch nicht fertig und noch nicht voll funktionsfähig, aber einiges geht ja doch schon)

      Heizungsanlage.png

      Das wäre das zugehörige SVG enthält alles außer die Images (Kamin, Solarstation, Ausgleichsgefäße, etc.):

      test16_noImages4IOB.svg

      Womit ich (in meinem Bild) noch Probleme habe ist das animieren der Pumpen, die springen immer an eine andere Stelle im Bild (da ist wohl noch ein Fehler drin).

      @Spampunk said in Einfach mal zeigen will….. 🙂 - Teil 2:

      Kannst Du vielleicht hierzu den Code für eine Pumpe und ein Flussschema darstellen? Wie hast Du das Flussschema animiert bekommen? Und wie funktioniert das mit dem Binding?

      Ich habe gerade noch mal das Minimalbeispiel von Marc ausgegraben dass ich damals ein bisschen angepasst hatte. Mit den folgenden Widgets (von denen das HTML-Image schon den SVG Code enthält) sollte eine Leitung und eine Pumpe gezeichnet werden:


      [{"tpl":"tplHtml","data":{"g_fixed":true,"g_visibility":false,"g_css_font_text":false,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html":"<svg>\n // Dies ist eine CSS-Definition. Sie führt später zum "Fließen" in der Leitung\n <style> \n\t\t.flow {\n animation: dash 30s linear;\n animation-iteration-count: infinite;\n \t \t}\n </style>\n\n// Dies ist eine Leitung. Die grüne Farbe ist quasi nur Kontrolle. Bei korrektem Code\n// wird die Leitung entsprechend der Temperatur koloriert.\n <path id="leitung1" fill="none" stroke="green" stroke-width="11" d="M0 15h100v10H0z"/>\n \n// Dies als Overlay. Die Grafik deutet einfach einen Fluss in der Leitung an. Es bietet sich\n// an, dies nach Bedarf ein oder auszublenden; dies erledigt der Code unten.\n \t<g id="flussanimation1" fill="none" class="flow" stroke="#fff" stroke-dasharray="4" stroke-width="4" opacity=".5">\n\t\t<path d="M 5.058 20.093 L 108.785 19.427"/>\n \t</g>\n \t\n \n// Dies ist einfach die Darstellung einer Pumpe; die wird durch den Code unten nach Bedarf gedreht (animiert) oder nicht\n <g id="pumpe1" stroke="#000" stroke-linecap="round" stroke-linejoin="bevel">\n <path fill="#fff" d="M72.2 19.756c0 6-5 11-11.2 11s-11-5-11-11c0-6.2 5-11.2 11-11.2s11.3 5 11.3 11.2z"/>\n <path stroke-width=".8" d="M66.5 10.156v19l-8.2-4.6-8.3-4.7 8.3-4.7z"/>\n </g>\n \n<script type="text/javascript">\nvar svgNS = "http://www.w3.org/2000/svg";\nsetTimeout(function () {\n\nvar trigger1 = {javascript.0.TestSVGbool};\n \n// Auslesen der Temperatur und umrechnen über die Funktion unten in eine Farbe\n// 20 = blau; 90 = rot\n var leitungsfarbe = color(parseInt(document.getElementById('kollektor_temp').innerHTML));\n\n// Einfärben der Leitung entsprechend ihrer Temperatur\n document.getElementById("leitung1").setAttribute("stroke", leitungsfarbe);\n\n// Hier jetzt die Auswertung, ob die Pumpe läuft. Wenn ja, dann wird sie gedreht und\n// die Flussanimation wird eingeblendet.\n \n if ((document.getElementById('pumpe_solar').innerHTML) === 'true') {\n document.getElementById("flussanimation1").style.display = "block";\n\t\taddRotateTransform('pumpe1',5 ,1);\n }\n else {\n document.getElementById("flussanimation1").style.display = "none";\n\t\taddRotateTransform('pumpe1',0 ,1);\n }; \n}, 1);\n\n\tfunction addRotateTransform(target_id, speed, direction) {\n\t\tvar element_to_rotate = document.getElementById(target_id);\n\t\tvar my_transform = document.createElementNS(svgNS, "animateTransform");\n\t\tvar bb = element_to_rotate.getBBox();\n\t\tvar cx = bb.x + bb.width/2;\n\t\tvar cy = bb.y + bb.height/2;\n\t\tmy_transform.setAttributeNS(null, "attributeName", "transform");\n\t\tmy_transform.setAttributeNS(null, "attributeType", "XML");\n\t\tmy_transform.setAttributeNS(null, "type", "rotate");\n\t\tmy_transform.setAttributeNS(null, "dur", speed + "s");\n\t\tmy_transform.setAttributeNS(null, "repeatCount", "indefinite");\n\t\tmy_transform.setAttributeNS(null, "from", "0 "+cx+" "+cy);\n\t\tmy_transform.setAttributeNS(null, "to", 360direction+" "+cx+" "+cy);\t\t\n\t\telement_to_rotate.appendChild(my_transform);\n\t\tmy_transform.beginElement();\n\t}\n\t \n\tfunction color(value) {\n \tvar highColor = "#ff6060";\n \tvar lowColor = "#6060ff";\n \tvar highTemp = 90;\n \tvar lowTemp = 20;\n \tif(value > highTemp) {\n \t\treturn highColor;\n \t}\n \telse if(value < lowTemp) {\n \t\treturn lowColor;\n \t}\n \telse {\n \t\tvar lr = parseInt("0x"+lowColor.substring(1,3));\n \t\tvar lg = parseInt("0x"+lowColor.substring(3,5));\n \t\tvar lb = parseInt("0x"+lowColor.substring(5,7));\n \t\tvar hr = parseInt("0x"+highColor.substring(1,3));\n \t\tvar hg = parseInt("0x"+highColor.substring(3,5));\n \t\tvar hb = parseInt("0x"+highColor.substring(5,7));\n \t\tvar cr = parseInt(lr + (hr-lr)(value-lowTemp)/(highTemp-lowTemp)).toString(16);\n \t\tvar cg = parseInt(lg + (hg-lg)(value-lowTemp)/(highTemp-lowTemp)).toString(16);\n \t\tvar cb = parseInt(lb + (hb-lb)(value-lowTemp)/(highTemp-lowTemp)).toString(16);\n \t\tcr = cr.length == 1 ? "0"+cr: cr;\n \t\tcg = cg.length == 1 ? "0"+cg: cg;\n \t\tcb = cb.length == 1 ? "0"+cb: cb;\n \t\treturn "#"+cr+cg+cb;\n \t}\n }\n </script>\n</svg>","name":"_Bild"},"style":{"left":"3px","top":"158px","width":"500px","height":"500px"},"widgetSet":"basic"},{"tpl":"tplHtml","data":{"g_fixed":true,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html":"Kollektor: <span id="kollektor_temp">{javascript.0.vbus.values.Temperaturesensor1}</span>","name":"KollektorTemp"},"style":{"left":"471px","top":"51px","width":"536px","height":"26px","color":"#545454"},"widgetSet":"basic"},{"tpl":"tplHtml","data":{"g_fixed":false,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html":"<span id="pumpe_solar">{javascript.0.TestSVGbool}</span>"},"style":{"left":"592px","top":"24px","width":"334px","height":"26px","color":"#545454"},"widgetSet":"basic"}]

      Die Variable "javascript.0.TestSVGbool" müsstest Du zum Schalten der Pumpe anlegen und die Variable "javascript.0.vbus.values.Temperaturesensor1" sollte die Temperatur für die Leitungsfarbe liefern (kannst natürlich anpassen).

      Hoffe, das hilft erst mal.

      Viele Grüße
      Stefan

      posted in Praktische Anwendungen (Showcase)
      S
      Stefan-G
    • RE: Einfach mal zeigen will….. :-) - Teil 2

      @Marc_St:

      Ich habe mir jetzt tatsächlich einmal Zeit genommen:

      […]

      Dazu wie gewünscht hier eine für Dich neu erstellte Datei mit vielen Kommentaren und nur den funktionalen Kernaspekten. So ist es bestimmt besser nachzuvollziehen. `

      Super, danke. Da hatte ich ja Erfolg beim Appell an Deine pädagogische Ader. Nach einem Tag SVG-Lernen etwas (vorläufiges) Feedback von mir. Wie immer wenn man mal kurz was in ioBroker machen will: eben war noch morgens und schon ist der Tag vorbei.

      Code hat geholfen, ist ja auch schön dokumentiert ;). Hab eigentlich alles mal hinbekommen, Animation von Pumpe und Leitungen, Farbe von Leitungen, nur bisher nicht alles zusammen. Ich geb aber noch nicht auf, muss aber erstmal wieder "normal" arbeiten… Im Minimalbeispiel scheint die Pumpe an einem anderen Platz versetzt zu werden (im nicht sichtbaren Bereich, außerhalb der View Box?) wenn sie aktiv ist. Kann aber aus dem Code nicht sagen warum.

      Habe auch versucht, Dein "großes" Beispiel zum Laufen zu bekommen und leider reagiert das nicht bei mir auf die Variablen. Kommt jede Variable in ein extra Basic-HTML Widget (muss ja irgendwie)? Kommt es auf die Reihenfolge an, in der ich diese in die View einfüge?

      Die Variablen "triggerX" verstehe ich nicht bzw sehe nicht, wo diese im Code benutzt werden.

      Du siehst, noch einiges an Fragen offen, aber ich wollte wenigstens zwischendurch mal Danke sagen.

      Viele Grüße

      Stefan

      posted in Praktische Anwendungen (Showcase)
      S
      Stefan-G
    • RE: Einfach mal zeigen will….. :-) - Teil 2

      Hi Marc,

      wirklich cool die Animationen und vielen Dank für's zur Verfügung stellen. Leider steige ich nicht vollkommen durch die SVG Datei durch, auch wenn das Grundprinzip nun mehr oder weniger klar ist. Mir sind aber zu viele Dinge gleichzeitig drin um wirklich zu lernen bzw. um eine Chance zu haben, die Datei anzupassen um so andere Heizkreise darzustellen. Und wenn ich mit z.B. InkScape bearbeite wird natürlich alles zerschossen.

      Wenn ich es recht sehe gibt es doch folgende animierte Teile:

      • Kessel mit Farbverlauf

      • Flamme

      • rotierende Pumpen

      • animierte Flussgeschwindigkeit mit Temperatur (horizontal/vertikal/links/rechts?)

      Für mich (und hoffentlich auch andere) wäre es interessant wenn Du solche "Einzelteile" mal zur Verfügung stellen könntest (müssen ja nicht gleich alle sein). Die nicht animierten Anteile kann sicherlich jeder selbst erstellen, somit könnte man dann den eigenen Heizkreis aus nicht animiertem Hintergrund und animierten kleineren SVGs zusammen stellen (jedenfalls könnte ich mir das so vorstellen).

      Nur falls Du noch etwas Zeit übrig hast oder etwas pädagogischen Antrieb würde ich mich über so was freuen… Mir ist natürlich klar, dass das etwas Arbeit ist, ich hoffe mal, vergleichsweise wenig dazu was wahrscheinlich schon in der SVG steckt...

      Schönes WE erstmal

      Stefan

      posted in Praktische Anwendungen (Showcase)
      S
      Stefan-G
    • RE: [Problem] Dream btw. Enigma2 Adapter

      Wiederholungsart für Timer (einmalig, wöchentlich, …) fänd ich auch cool, dann kann man sehen, ob's für ne Serie eine "Serientimer" ist oder nur einmalig aufgenommen wird. Dafür wäre dann auch die "Timer löschen" Funktion gut. Sonst sieht das doch schon super aus.

      posted in ioBroker Allgemein
      S
      Stefan-G
    • RE: [Problem] Dream btw. Enigma2 Adapter

      Hi zusammen,

      Code für das Bouquet/Sender-Auslesen und wechseln hatte ich mal weiter oben gepostet. Hoffe, dass man das halbwegs einfach in den Adapter einbauen könnte.

      Viele Grüße

      Stefan

      @Stefan-G:

      Hallo zusammen,

      habe mal eine Funktion zur Anzeige aller Bouquets und Kanäle und zum Umschalten implementiert:

      ! var parseString = require('xml2js').parseString;
      ! var request = require('request');
      ! var urlVUplus = 'http://192.168.1.101:82';
      ! var instanz = 'javascript.0'; instanz = instanz + '.';
      ! var pfad = 'XMLParsing'; pfad = pfad + '.'; // Pfad innerhalb der Instanz
      ! var debug = true;
      ! // VU+ Power-Status
      ! createState(pfad + 'VUplus.BouquetNames', 'init', {type: "string", name: "Names of Enigma bouquets", write:true, read:true});
      ! createState(pfad + 'VUplus.BouquetNumbers', 'init', {type: "string", name: "References of Enigma bouquets", write:true, read:true});
      ! createState(pfad + 'VUplus.NumberOfBouquets', 0, {type: "number", name: "How many bouquets are defined in Enigma", write:false, read:true});
      ! createState(pfad + 'VUplus.BouquetNumberCurrent', 0, {type: "number", name: "Number of selected Enigma bouquet", write:true, read:true});
      ! createState(pfad + 'VUplus.BouquetCurrentlySelected.BouquetName', 'init',{type: "string", name: "Name of currently selected Enigma bouquet", write:true, read:true});
      ! createState(pfad + 'VUplus.BouquetCurrentlySelected.BouquetReference', 'init',{type: "string", name: "Reference of currently selected Enigma bouquet", write:true, read:true});
      ! createState(pfad + 'VUplus.BouquetCurrentlySelected.ChannelNames', 'init',{type: "string", name: "Channel names of currently selected Enigma bouquet", write:true, read:true});
      ! createState(pfad + 'VUplus.BouquetCurrentlySelected.ChannelReferences', 'init',{type: "string", name: "Channel references of currently selected Enigma bouquet", write:true, read:true});
      ! createState(pfad + 'VUplus.ChannelReferenceCurrent', 'init', {type: "string", name: "Reference of selected channel", write:true, read:true});
      ! //example HHTP requests to obtain bouquet and channel list:
      ! //http://192.168.1.101:82/web/getservices
      ! //Favourites (TV):
      ! //http://192.168.1.101:82/web/getservices … %20bouquet
      ! //German Free SD
      ! //http://192.168.1.101:82/web/getservices ... %20bouquet
      ! //German Free HD
      ! //http://192.168.1.101:82/web/getservices ... %20bouquet
      ! //German HD+
      ! //http://192.168.1.101:82/web/getservices ... %20bouquet
      ! //------------------------------------------------------------------------------
      ! // This function collects all channel names (TV stations) and the respective
      ! // channel references and writes them into the respective states created before
      ! // (in calling function GetVUplusChannels()
      ! //------------------------------------------------------------------------------
      ! function GetVUplusBouquetChannels(strBouquetReference, iBouquetNumber) {
      ! var strAllChannelNames = '';
      ! var strAllChannelReferences = '';
      ! request(urlVUplus + '/web/getservices?sRef=' + strBouquetReference, function (error, response, body) {
      ! if (!error && response.statusCode == 200) {
      ! //if(debug){log("Body: " + body);}
      ! parseString(body, {
      ! explicitArray: false,
      ! mergeAttrs: true
      ! },
      ! function (err, result) {
      ! if (err) {
      ! log("Fehler: " + err);
      ! } else {
      ! for (var j = 0; j < result.e2servicelist.e2service.length; j++) {
      ! var strSender = result.e2servicelist.e2service[j].e2servicename;
      ! var strService = result.e2servicelist.e2service[j].e2servicereference;
      ! if(debug){ log("Sender Nr. " + j + ": " + strSender + ", Service: " + strService);}
      ! strAllChannelNames = strAllChannelNames + strSender + ';';
      ! strAllChannelReferences = strAllChannelReferences + strService + ';';
      ! }
      ! strAllChannelNames = strAllChannelNames.slice(0,strAllChannelNames.length-1); // cut away last ";"
      ! strAllChannelReferences = strAllChannelReferences.slice(0,strAllChannelReferences.length-1); // cut away last ";"
      ! if(debug){ log('All channels for Bouquet ' + iBouquetNumber +': ' + strAllChannelNames);}
      ! if(debug){ log('All channel references for Bouquet ' + iBouquetNumber + ': ' + strAllChannelReferences);}
      ! setState(instanz + pfad + 'VUplus.Bouquet' + iBouquetNumber + '.ChannelNames', strAllChannelNames);
      ! setState(instanz + pfad + 'VUplus.Bouquet' + iBouquetNumber + '.ChannelReferences', strAllChannelReferences);
      ! }
      ! });
      ! } else {
      ! if(debug){log(error);}
      ! }
      ! });
      ! }
      ! //–----------------------------------------------------------------------------
      ! // This function creates states for all bouquets with all info about the bouquet
      ! // e.g. channels (TV station) names and respective service references
      ! //------------------------------------------------------------------------------
      ! function CreateBouquetStates(NrOfBouquets) {
      ! for (var i = 0; i < NrOfBouquets; i++) {
      ! createState(pfad + 'VUplus.Bouquet' + i + '.BouquetName', 'init',{type: "string", name: "Name of Enigma bouquets number "+ i, write:true, read:true});
      ! createState(pfad + 'VUplus.Bouquet' + i + '.BouquetReference', 'init',{type: "string", name: "Reference of Enigma bouquets number "+ i, write:true, read:true});
      ! createState(pfad + 'VUplus.Bouquet' + i + '.ChannelNames', 'init',{type: "string", name: "Channel names of Enigma bouquets number "+ i, write:true, read:true});
      ! createState(pfad + 'VUplus.Bouquet' + i + '.ChannelReferences', 'init',{type: "string", name: "Channel references of Enigma bouquets number "+ i, write:true, read:true});
      ! }
      ! // TODO: here code could be added which deletes states if more bouquet states have already been created befor than bouquets exit presently, e.g. this can happen if an bouquet has been deleted on the ENIGMA system
      ! }
      ! //------------------------------------------------------------------------------
      ! // This function all available bouquets (TV station lists) for an ENIGMA system
      ! // and creates states for all bouquets filled with channel (TV station) and
      ! // respective service references for bouquets and channels
      ! //------------------------------------------------------------------------------
      ! function GetVUplusChannels() {
      ! request(urlVUplus + '/web/getservices', function (error, response, body) {
      ! if (!error && response.statusCode == 200) {
      ! //if(debug){log("Body: " + body);}
      ! parseString(body, {
      ! explicitArray: false,
      ! mergeAttrs: true
      ! },
      ! function (err, result) {
      ! if (err) {
      ! log("Fehler: " + err);
      ! } else {
      ! if(debug){ log("Anzahl Bouquets: " + result.e2servicelist.e2service.length);}
      ! var strBouquetName = '';
      ! var strBouquetReference = '';
      ! var strAllBouquetNames = '';
      ! var strAllBouquetNumbers = '';
      ! // create as many states as bouquets exist
      ! setState(instanz + pfad + 'VUplus.NumberOfBouquets', result.e2servicelist.e2service.length);
      ! CreateBouquetStates(result.e2servicelist.e2service.length);
      ! for (i = 0; i < result.e2servicelist.e2service.length; i++) {
      ! strBouquetName = result.e2servicelist.e2service__.e2servicename;
      ! strBouquetReference = result.e2servicelist.e2service__.e2servicereference.replace(/ /g, "%20").replace(/"/g, "%22");
      ! strAllBouquetNames = strAllBouquetNames + strBouquetName + ';';
      ! strAllBouquetNumbers = strAllBouquetNumbers + i + ';';
      ! if(debug){ log("Bouquet Nr. " + i + ": " + strBouquetName + ", Bouquet References: " + strBouquetReference);}
      ! setState(instanz + pfad + 'VUplus.Bouquet' + i + '.BouquetName', strBouquetName);
      ! setState(instanz + pfad + 'VUplus.Bouquet' + i + '.BouquetReference', strBouquetReference);
      ! GetVUplusBouquetChannels(strBouquetReference, i);
      ! }
      ! strAllBouquetNames = strAllBouquetNames.slice(0,strAllBouquetNames.length-1); // cut away last ";"
      ! strAllBouquetNumbers = strAllBouquetNumbers.slice(0,strAllBouquetNumbers.length-1); // cut away last ";"
      ! if(debug){ log("All Bouquets: " + strAllBouquetNames);}
      ! if(debug){ log("All Bouquet numbers: " + strAllBouquetNumbers);}
      ! setState(instanz + pfad + 'VUplus.BouquetNames', strAllBouquetNames);
      ! setState(instanz + pfad + 'VUplus.BouquetNumbers', strAllBouquetNumbers);
      ! }
      ! });
      ! } else {
      ! if(debug){log(error);}
      ! }
      ! });
      ! }
      ! on(instanz + pfad + 'VUplus.BouquetNumberCurrent', function(obj) {
      ! var ChannelNamesOfNewCurrentBouquet = getState(instanz + pfad + 'VUplus.Bouquet' + obj.newState.val + '.ChannelNames').val;
      ! var ChannelReferencesOfNewCurrentBouquet = getState(instanz + pfad + 'VUplus.Bouquet' + obj.newState.val + '.ChannelReferences').val;
      ! var FirstChannelReferenceOFNewBouquet = ChannelReferencesOfNewCurrentBouquet.slice(0, ChannelReferencesOfNewCurrentBouquet.indexOf(';'));
      ! if(debug){ log('Current bouquet number changed to: ' + obj.newState.val );}
      ! if(debug){ log('First channel in urrent bouquet: ' + ChannelNamesOfNewCurrentBouquet.slice(0, ChannelNamesOfNewCurrentBouquet.indexOf(';')) );}
      ! if(debug){ log('First channel reference in urrent bouquet: ' + FirstChannelReferenceOFNewBouquet);}
      ! // serch if the currently selected TC channel exists in the new selected bouquet
      ! if(ChannelReferencesOfNewCurrentBouquet.indexOf(getState(instanz + pfad + 'VUplus.ChannelReferenceCurrent').val) == -1) {
      ! if(debug){ log('Currently selected TC channel not found in previous bouquet, switching channel.');}
      ! setState(instanz + pfad + 'VUplus.ChannelReferenceCurrent', FirstChannelReferenceOFNewBouquet);
      ! }
      ! // set new values for selected bouquet
      ! setState(instanz + pfad + 'VUplus.BouquetCurrentlySelected.BouquetName', getState(instanz + pfad + 'VUplus.Bouquet' + obj.newState.val + '.BouquetName').val);
      ! setState(instanz + pfad + 'VUplus.BouquetCurrentlySelected.BouquetReference', getState(instanz + pfad + 'VUplus.Bouquet' + obj.newState.val + '.BouquetReference').val);
      ! setState(instanz + pfad + 'VUplus.BouquetCurrentlySelected.ChannelNames', ChannelNamesOfNewCurrentBouquet);
      ! setState(instanz + pfad + 'VUplus.BouquetCurrentlySelected.ChannelReferences', ChannelReferencesOfNewCurrentBouquet);
      ! });
      ! on(instanz + pfad + 'VUplus.ChannelReferenceCurrent', function(obj) {
      ! if(debug){ log('Chosen current channel reference: ' + obj.newState.val );}
      ! request(urlVUplus + '/api/zap?sRef=' + obj.newState.val, function (error, response, body) {
      ! if (!error && response.statusCode == 200) {
      ! //log("Body: " + body);
      ! parseString(body, {
      ! explicitArray: false,
      ! mergeAttrs: true
      ! },
      ! function (err, result) {
      ! if (err) {
      ! log("Fehler: " + err);
      ! } else {
      ! if(debug){ log(result);}
      ! }
      ! });
      ! } else {
      ! log(error);
      ! }
      ! });
      ! });
      ! // create and fill all states for bouquets and station names
      ! GetVUplusChannels();____ ____Code mag natürlich noch optimierbar sein. Ich fände es cool, wenn es diese Funktion gleich im Adapter gäbe, oder gibt es einen Grund, das dort nicht zu implementieren? Kann dann so aussehen (roter Kasten):

      VUplus.jpg

      Die Widgets dafür sind dann wie folgt:__

      ! [{"tpl":"tplJquiSelectList","data":{"oid":"javascript.0.XMLParsing.VUplus.BouquetNumberCurrent","values":"{javascript.0.XMLParsing.VUplus.BouquetNumbers}","texts":"{javascript.0.XMLParsing.VUplus.BouquetNames}","height":"170","open":false,"gestures-offsetX":0,"gestures-offsetY":0,"signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"g_visibility":false,"g_fixed":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide"},"style":{"left":"370px","top":"213px","width":"214px","height":"29px"},"widgetSet":"jqui"},{"tpl":"tplValueString","data":{"oid":"","g_fixed":false,"g_visibility":false,"g_css_font_text":true,"g_css_background":true,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html_prepend":"Bouquet:","html_append":"","test_html":"","visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide"},"style":{"left":"376px","top":"184px","color":"#ffffff","width":"186px","height":"20px","text-shadow":"rgba(0, 0, 0, 0.9) 3px 3px 4px","font-family":"Tahoma, Geneva, sans-serif"},"widgetSet":"basic"},{"tpl":"tplJquiSelectList","data":{"oid":"javascript.0.XMLParsing.VUplus.ChannelReferenceCurrent","values":"{javascript.0.XMLParsing.VUplus.BouquetCurrentlySelected.ChannelReferences}","texts":"{javascript.0.XMLParsing.VUplus.BouquetCurrentlySelected.ChannelNames}","height":"170","open":false,"gestures-offsetX":0,"gestures-offsetY":0,"signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"g_visibility":false,"g_fixed":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide"},"style":{"left":"605px","top":"212px","width":"217px","height":"29px"},"widgetSet":"jqui"},{"tpl":"tplValueString","data":{"oid":"","g_fixed":false,"g_visibility":false,"g_css_font_text":true,"g_css_background":true,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html_prepend":"Sender:","html_append":"","test_html":"","visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","values":"{javascript.0.XMLParsing.VUplus.Bouquet3.ChannelReferences}","texts":"{javascript.0.XMLParsing.VUplus.Bouquet3.ChannelNames}"},"style":{"left":"607px","top":"181px","color":"#ffffff","width":"186px","height":"20px","text-shadow":"rgba(0, 0, 0, 0.9) 3px 3px 4px","font-family":"Tahoma, Geneva, sans-serif"},"widgetSet":"basic"}] __Vielleicht mag das ja jemand einbauen (meine Git-/Adapter- Kenntnisse sind leider nicht gut genug).

      Ne Timer-Liste wäre auch cool. Vielleicht schafft das ja auch jemand schneller als ich… ;)____ `

      posted in ioBroker Allgemein
      S
      Stefan-G
    • RE: [Aufruf] DENON & Marantz Adapter

      @foxriver76:

      Danke für das ausführliche Feedback. Pause anzuzeigen war der ursprüngliche Hintergedanke, also dass man einen alternierenden Play/Pause Button visualisieren könnte. Was genau bringt dir der Indikator, wie er aktuell implementiert ist? `
      Hm, genau da funktioniert er natürlich nicht (jedenfalls nicht bei mir). Hab ich gerade noch mal ausprobiert. Ich hatte ja von meinem Problem berichtet, dass mein AVR bei Start auf Kanal IRADIO öfter mal einen Server-Fehler hat und das IRADIO nicht los legt. Dafür dachte ich, für mich brauchst Du das aber nicht drin lassen, ich bastel mir ein Skript.

      @foxriver76:

      @Stefan-G:

      Ich hab mir das jetzt erst mal über Widgets mit ExpertCommands zusammengebaut. Tut was, aber ich muss erst mal sehen, ob ich das überhaupt in VIS schön visualisiert bekomme, und ob ich damit final zum Ziel komme (Music vom Medienserver browsen oder I-Radio Stationen). `
      Bitte 0.3.3 probieren.

      Cursor Buttons, Option Button, Info Button und Back/Return Button wurden hinzugefügt. Der Setup Button ist in Form eines Indikators verfügbar (wenn es geöffnet ist, steht dieser auf true).

      beste Grüße

      fox `

      Super, das funktioniert auch. Das Bedienen des OSDs über die Cursor-Tasten ist zwar nicht wirklich intuitiv, aber funktioniert im Prinzip. Konnte sowohl IRADIO-Stationen als auch Titel vom NAS suchen und starten. Cool.

      Viele Grüße

      Stefan

      posted in Tester
      S
      Stefan-G
    • RE: [Aufruf] DENON & Marantz Adapter

      @foxriver76:

      […] Lass dir ruhig Zeit – soll nicht überstürzt werden. Das mit der eventuellen Umbenennung wäre ne Möglichkeit. Bezüglich meinem Gedankengang: Ich finde es nicht sonderlich schön, wenn da ein isPlaying Indikator verbaut ist, der nicht korrekt funktioniert. […] `

      So, hat doch länger gedauert als bis zum So. "Lass Dir ruhig Zeit" sollte man mir nie sagen 😉

      Ich habe jetzt noch mal folgendes getestet:

      • Abspielen von NAS (Medienserver)

      • solange Song spielt -> IsPlaying true -> gut 8-)

      • Stop gedrückt -> IsPlaying false -> gut 8-)

      • Pause -> IsPlaying true -> ist ok würd ich sagen

      • Song zurück -> IsPlaying false währed umschalten, true wenn's weiter geht -> sehr gut 8-)

      Mein Gesamtfazit: Wenn Du isPlaying für alle Inputkanäle außer "IRADIO" und "SERVER" auf false setzt sollte es eigentlich genau das anzeigen, was man erwartet. Sonst vielleicht in der Tat etwas verwirrend.

      @foxriver76:

      Die NM Befehle kann ich gerne implementieren, dazu am besten mal ein Issue auf Github eröffnen. `

      Ich hab mir das jetzt erst mal über Widgets mit ExpertCommands zusammengebaut. Tut was, aber ich muss erst mal sehen, ob ich das überhaupt in VIS schön visualisiert bekomme, und ob ich damit final zum Ziel komme (Music vom Medienserver browsen oder I-Radio Stationen).

      posted in Tester
      S
      Stefan-G
    • RE: [Aufruf] DENON & Marantz Adapter

      Na ja, der State tut ja was er soll, nur der (zumindest mein) AVR reagiert nicht so richtig logisch. Wenn man den State umbenennen würde in z.B. "NowPlaingInfoinOSD" dann wäre er für mich immer noch sehr hilfreich (aus im letzten Post geschriebenen Gründen). Wenn Du's wegen nicht immer nachvollziehbarer Rückmeldung raus nehmen willst versteh ich das auch (ich find's aber cool, würde mir dann die Funktion in ein Skript basteln ;))

      Ich versuch am SO noch mal genauer zu testen (auch mit Medienserver), vorher wird's wahrscheinlich zeitlich eng bei mir.

      posted in Tester
      S
      Stefan-G
    • RE: [Aufruf] DENON & Marantz Adapter

      Tja, leider nein, habe "nur" einen Marantz SR7008 (ohne HEOS). Die Änderungen für mich sind also lediglich ein paar Umsortierungen der States, kann also leider bei den neueren Funktionen nicht sehr viel hilfreicher sein. Getestet hab ich die Installation und Grundfunktionen der drei Zonen incl. Soundparameter (Änderungen gab's da ja aber eigentlich nur bei der Umsortierung in 'settings' und 'zoneMain').

      IsPlaying habe ich noch nicht genutzt. Wenn ich das richtig verstehe wäre das ein cooles Feature (scheinst Du Dir ja aus dem Display-Text zu holen). Interessant für mich weil: Bei mir kommt ab und an "Serverfehler" beim Einschalten des AV auf IRadio und dann kein Sender (hat nix mit ioBroker zu tun). Mit IRP Kommando kann man wohl einen Reconnect-Versuch machen (hat schon bei mir geklappt, intensiv getestet hab ich's noch nicht). Mit IsPlaying könnte man IRP automatisch triggern.

      Ein kurzer Test zum Verhalten von IsPlaying bei mir:

      • false wenn AV aus (macht Sinn)

      • true wenn IRadio spielt (macht Sinn)

      • Wenn ich nach IRadio auf anderen Kanal schalte (z.B. Aux wo nichts angeschlossen ist) bleibt isPlaying true (OSD bleibt auch daher wohl)

      • AV anschalten, egal auf welchem Kanal und IRadio-Info wird im OSD angezeigt (dann läuft IRADIO auch, wenn ich darauf umschalte) -> IsPlaying true (auch wenn ich bisher nicht IRadio gewählt habe

      • AV anschalten, egal auf welchem Kanal und IRadio-Info wird im OSD nicht angezeigt (dann kommt kurz die Meldung "serverfehler im OSD") -> IsPlaying false

      Fazit: Sieht nach einem guten Ansatz für mein oben geschildertes Problem aus. Hat das sonst noch jemand bei seinem AVR?

      Wenn Du schon mit einer Analyse des OSD anfängst, dann frag ich mal, ob Du Dir schon mal die

      NS und MN Befehlen angesehen hast. Ich hätte ja gerne noch eine Navigation durchs OSD ohne Beamer-Anschluss, konkret um IRadio-Stationen zu wählen (mal abseits der Favorite Stations). Das wollte ich mir immer mal angucken (auch ob die NS und MN Befehle dazu überhaupt taugen), komme aber bisher nicht dazu.

      Soweit erstmal Feedback.

      Viele Grüße

      Stefan

      posted in Tester
      S
      Stefan-G
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    The ioBroker Community 2014-2023
    logo