Navigation

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

    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

    • Profile
    • Following 0
    • Followers 10
    • Topics 58
    • Posts 7256
    • Best 1188
    • Groups 4

    OliverIO

    @OliverIO

    Meine Adapter und Widgets:
    TVProgram Github Forum
    Squeezebox Github Forum
    OpenLiga Github Forum
    RSSFeed Github Forum
    MyTime Github Forum

    1458
    Reputation
    1022
    Profile views
    7256
    Posts
    10
    Followers
    0
    Following
    Joined Last Online

    OliverIO Follow
    Developer Pro Starter Most Active

    Best posts made by OliverIO

    • Test Adapter tvprogram
      Aktuelle Test Version 0.0.1 und größer
      Veröffentlichungsdatum Januar 2021
      Github Link https://github.com/oweitman/iobroker.tvprogram

      Was kann der Adapter bereits:
      Server

      • die notwendigen TV-Daten aus dem Internet abrufen und als Datenpunkt abspeichern

      Widget
      -Darstellung des TV-Programms in der Zeitstrahl-Ansicht
      -Aufruf von Detailinformationen zu jeder einzelnen Sendung, soweit die Daten vorhanden sind.

      • Scrollen über einen ganzen Tag
      • Senderauswahl konfigurieren

      Was kann das Widget noch nicht:

      • Konfiguration der Darstellung, größerer/kleinerer Bereich je Stunde, ggfs auch hinein/hinauszoomen
      • Farbanpassung an das gewünschte Farbschema, aktuell nur Dunkel-Darstellung
      • Hervorhebung Favoritensendungen

      Weitere Punkte auf der Roadmap

      • Ideen für weitere Widgets auf Basis des bereits existierenden TVprogram-Skripts
      • sendungserinnerungen
      • ansteuern datenpunkt zum umschalten nach Klick auf senderlogo
      • Datenadapter für weitere Quellen (Internet, Hardware wie Enigma,VU-Box)

      Darüber hinaus wird in diesem Thread weiter unten immer aktuell über den Fortschritt berichtet

      Hier ein kleines Video des bisherigen Entwicklungsstandes.
      tvprogram.gif

      posted in Tester
      OliverIO
      OliverIO
    • Test/Support für Adapter rssfeed und vis-2-widgets-rssfeed

      Unter Abteilung Tester konnte ich kein Topic anlegen. Bitte dort hin verschieben.

      Nachdem ich immer weider lese, wie sich die Leute mit rss-Feeds abmühen,
      habe ich einen Adapter dazu geschrieben.
      Dieser hat aktuell minimale Fähigkeiten, man kann damit aber
      schon annehmbare Ergebnisse erzielen.

      Verwendete Bausteine
      Um die Flexibilität bei der Anzeige der Feeds bieten zu können, erfolgt die Formatierung der Ausgabe
      über ein template-system.
      Eine Vorlage werde ich hier weiter unten kopieren.
      Beschreibung der Formatierung und Syntax finden sich auf den folgenden Seiten
      https://ejs.co/ und https://github.com/mde/ejs

      Einlesen der Feeds.
      Dazu verwende ich ein node modul namens feedparser.
      Dieses Modul kann verschiedene RSS-Standards (RSS, Atom, and RDF).
      Dazu ist er noch dazu in der Lage, die Attribute zu normalisieren, so das es in der Ausgabe egal ist,
      wie der jeweilige Standard ein bestimmtes Feld nennt.
      https://github.com/danmactough/node-feedparser

      Installation und Einrichtung

      Schritt 1 - Installation
      Der Adapter ist aktuell nur auf github verfügbar.
      Name des Repository ist https://github.com/oweitman/iobroker.rssfeed

      Schritt 2 - Instanz hinzufügen
      Der Adapter müsste dann im Abschnitt adapter im iobroker angezeigt werden.
      Manchmal kommt es vor, das insbesondere bei Webänderungen (Widgets/Konfigurationsdialog) die Änderungen nicht sichtbar sind, muss evtl. auf der Kommandozeile folgender Befehl ausgeführt werden:
      iobroker upload rssfeed
      Im rechten Bereich in der Zeile des Adapters kann über den Plus-Knopf eine Instanz hinzugefügt werden

      Schritt 3 - Konfiguration

      Die Konfiguration ist relativ simpel. Es gibt nur wenige Felder

      Refresh: ist die generelle Vorgabe, wie oft in Minuten der Feed neu abgerufen werden soll. Voreinstellung ist 60
      Maximale Artikel im Datenpunkt: Hier kann die Gesamtmenge der zu verarbeitenden Daten begrenz werden.

      Dann je neuen Feed:
      Name: Ein eindeutiger Name, darf nicht doppelt vorkommen
      Url: Die vollständige Adresse des Feed (mit http:// oder https://)
      Refresh: Bei Erfassung kann ein abweichender Wert angegeben werden. Ansonsten wird die generelle Vorgabe genommen

      Nach Neustart und Abruf der Daten ist der Feed als JSON-Datenpunkt im Objektbaum zu finden.

      Schritt 4 - vis und widgets

      Um die Feeds anzuzeigen gibt es ein widget. Dieses kann über den Suchfilter in vis mittels rssfeed gefunden werden.

      Das widget hat folgende Einstellmöglichkeiten

      rss_oid Hier wird der JSON-Datenpunkt des gewünschten feeds ausgewählt. Ich habe festgestellt, das der Objektbrowser hier nicht imnmer zufriedenstellend funktioniert, da er die im JSON enthaltenen HTML-Anteile versucht dazustellen.
      Alternativ die Datenpunkt ID direkt aus vis kopieren.
      template: Hier kann ein template erfasst werden, welches javascript und html gemischt enthalten kann.

      maxarticles: Hier kann widget individuell die Anzahl der Artikel begrenzt werden.

      Alle anderen Einstellungen sind identisch zu den anderen widgets, Die Formatvorgaben gellten generell für alle widgetinhalte

      Die widgets rssfeed Meta helper und rssfeed Article helper unterstützen bei der Erstellung eines Templates,
      indem dort komfortabel die meta-Informationen und die Attribute eines Artikels angezeigt werden.
      Im widget rssfeed Article Helper kann man den Artikel auswählen, dessen Attribute angezeigt werden soll, sowie das Präfix anpassen, so dass es einfacher ist dieses in das Template zu kopieren.

      Ein weiteres widget hat nichts direkt mir rssfeed zu tun und ist in diesem adapter voraussichtlich temporär zu Gast.

      Template anhand von Beispielen
      Ein Beispiel, welches ich mit den folgenden RSS Feeds getestet habe:

      • http://www.tagesschau.de/xml/rss2
      • https://www.bild.de/rssfeeds/rss3-20745882,feed=alles.bild.html
      <%= meta.title %> 
      <% articles.forEach(function(item){ %>
      <p><small><%- vis.formatDate(item.pubdate, "TT.MM.JJJJ SS:mm") %></small></p>
      <h3><%- item.title %></h3>
      <p><%- item.description %></p>
      <div style="clear:both;" />
      <% }); %>
      

      Das Templatesystem arbeitet mit bestimmten Tags.
      Die verwendeten Tags bedeuten das folgenden
      <%= Der Inhalt des enthaltenen Ausdrucks/Variable wird escaped ausgegenen.
      <%- Der Inhalt des enthaltenen Ausdrucks/Variable wird unescaped ausgegenen.
      <% Tag ohne Ausgabe, wird für javascriptanweisungen verwendet
      %> ist generell ein schließender Tag um eines der vorherigen abzuschließen
      Alles was außerhalb dieser Tags ist, wird genau so dann angezeigt bzw. wenn es HTML ist als HTML interpretiert ausgegeben. (siehe bspw das p-tag,div-tag,small-tag

      Innerhalb des Templates habt ihr 2 vorgegebene variablen zur Verfügung

      meta: Hier sind alle Metainformationen zum Feed enthalten. Die folgenden Inhalte stehen zur Verfügung. Ich denke die Bezeichner sind selbst erklärend. In der Hilfe werde ich diese noch genauer Beschreiben. bzw den Inhalt spezifizieren (manche sind Arrays)

      meta.title
      meta.description
      meta.link
      meta.xmlurl
      meta.date
      meta.pubdate
      meta.author
      meta.language
      meta.image
      meta.favicon
      meta.copyright
      meta.generator
      meta.categories

      articles: Ist ein Array mit einzelnen Elementen (javascript array). Jedes Element hat die folgenden Eigenschaften.
      Damit es zum Beispiel passt mache ich hier mal das Prefix item davor. Aber wenn ihr wollt könnt ihr das selbst wählen. Es muss dann nur in der Schleife (forEach) entsprechend benannt werden. Auch hjier sind die Bezeichner erst einmal selbst erklärend. Nicht in jedem Feed sind alle attribute auch gefüllt. Die wichtigsten sind im obigen Template bereits enthalten.

      item.title
      item.description
      item.summary
      item.link
      item.origlink
      item.permalink
      item.date
      item.pubdate
      item.author
      item.guid
      item.comments
      item.image
      item.categories
      item.source
      item.enclosures"

      <%= meta.title %> 
      <% articles.forEach(function(item){ %>
      <p><small><%- vis.formatDate(item.pubdate, "TT.MM.JJJJ SS:mm") %></small></p>
      <h3><%- item.title %></h3>
      <p><%- item.description %></p>
      <div style="clear:both;" />
      <% }); %>
      

      Kurze Beschreibung was in den einzelnen Zeilen passiert
      Z1: Der Feed-titel wird ausgegeben
      Z2: Ohne Ausgabe. Schleife über alle articles, bei jedem Durchgang wird das aktuelle Element der variable item zugewiesen.
      Z3: Datum und Uhrzeit wird ausgegeben und wird in einem p/small-Tag eingeschlossen zur Formatierung. Zur Formatierung wird die vis-eigene Datumsformatfunktion verwendet. Beschreibung ist im adapter vis zu finden.
      Z4: Der Titel des Artikels wird ausgegeben. Zur Formatierung wird der Tag für Überschrift 3 verwendet
      Z5: Der Inhalt des Artikels wird ausgegeben und in einem p-Tag eingeschlossen. Hier ist, zumindest bei den beiden Beispielen, HTML-code enthalten, der meist ein Bild, sowie beschreibenden Text mitbringt
      Z6: Ein div-Tag, das ausgegeben werden muss, um eine spezielle Formatierung im Feed wieder aufzuheben.
      Z7: Ohne Ausgabe. Hier wird die Schleife geschlossen. Alles was zwischen Z2 und Z7 definiert wurde, wird für jeden einzelnen Artikel wiederholt.

      Ich freue mich über reges testen und Vorschlag von Erweiterungen.

      Fehler können hier, aber auch auf github https://github.com/oweitman/ioBroker.rssfeed
      gemeldet werden.

      posted in Tester
      OliverIO
      OliverIO
    • Test Adapter OpenLigaDB

      Unter Abteilung Tester konnte ich kein Topic anlegen. Bitte dort hin verschieben.

      ich bitte um Test eines neuen Adapters zur Anzeige von
      Sportergebnissen und Spielinformationen von OpenLigaDB.

      Installation und Einrichtung

      Schritt 1 - Installation
      Der Adapter ist unter OpenLigaDB im Latest-Repository verfügbar und kann normal werden.

      Schritt 2 - Instanz hinzufügen

      • Der Adapter müsste dann im Abschnitt adapter im iobroker angezeigt werden.
        Manchmal kommt es vor, das insbesondere bei Webänderungen (Widgets/Konfigurationsdialog) die Änderungen nicht sichtbar sind, muss evtl. auf der Kommandozeile folgender Befehl ausgeführt werden:
      iobroker upload openligadb
      
      • Im rechten Bereich in der Zeile des Adapters kann über den Plus-Knopf eine Instanz hinzugefügt werden

      Schritt 3 - Konfiguration

      • Im Abschnitt Instanzen im iobroker müsste dann die erzeugte Instanz angezeigt werden

      • Über das Schraubenschlüsselsymbol kommt man in die Konfiguration

      • Dort müssen die verschiedenen Ligen und Saisons erfasst werden.

      • Das jeweilige Kürzel (Shortcut) kann auf der Seite openligadb.de nachgeschaut werden.

      • Die Saison ist bspw bei Fußball immer das Startjahr.

      • Beide Informationen müssen exakt so eingegeben werden, wie dort angezeigt.
        Bspw zum Test:
        Aktuelle 1. Bundesliga, Kürzel bl1 und Saison 2019
        Aktuelle 2. Bundesliga, Kürzel bl2 und Saison 2019

      • Der Entwicklertest ist genau mit diesen Ligen erfolgt. andere Ligen habe ich bisher noch nicht ausprobiert.

      • Nach Erfassung und speichern der Konfiguration wird der Adapter neu gestartet und für jede Liga werden verschiedene Datenpunkte mit JSON-Informationen angelegt und regelmäßig (refresh) aktualisiert.

      weitere durch Tester bereits verwendete Ligen sind bl2,bl3 und cl1920german die für
      Saison 2019 verfügbar sind.

      Schritt 4 - vis und widgets

      • Aktuell habe ich 3 widgets gebaut
      • Diese können gefunden werden, wenn man im widget-Filter openligadb auswählt/eingibt

      Table zeigt den aktuellen Tabellenstand an.

      • Nach dem Hinzufügen des Widgets in einer view, muss der entsprechende Datenpunkt ausgewählt werden (Datenpunkbezeichnung table in dem jeweiligen Liga/Season-Unterverzeichnis)
      • Die Schrift kann über die bekannten CSS-Einstellungen im rechten Bereich vorgenommen werden.
      • Über die Eigenschaft maxicon kann die Icongröße des Mannschaftslogos unabhängig eingestellt werden. maximale Pixel in horizontal wie auch waagerecht
      • Manchmal (Nicht immer) ist ein Kurzname für die Manschaft gefplegt. der kann über shortname gewählt werden

      Gameday zeigt den aktuellen Spieltag mit Datum/Uhrzeit und Ergebnissen an.

      • Vorgehensweise ist ähnlich wie bei Table.
      • Auswahl des Datenpunktes (hier heißt er currgameday)
      • Die restlichen Einstellungen sind identisch zu Table
      • Dazu am besten in die Widget-Hilfe in vis gehen.

      FavGame Anzeige der Zeiten Deiner Lieblingsmannschaften

      • Einstellungen sind fast analog zu GameDay
      • Dazu am besten in die Widget-Hilfe in vis gehen.
        10b3b7fb-627a-45f6-966e-14a15189fbb1-image.png

      Ich freue mich über reges testen und Vorschlag von Erweiterungen.
      Testet bitte auch mal die anderen Ligen von anderen Sportarten.
      Allerdings weiß ich nicht wie vollständig diese gepflegt sind. Die guten sind wohl mit einem gelben Stern (Top-Liga) markiert.

      Fehler können hier, aber auch auf github https://github.com/oweitman/ioBroker.openligadb
      gemeldet werden.

      posted in Tester
      OliverIO
      OliverIO
    • Wetter- / Stadt-Visualisierung mit KI

      Ich habe ein Prompt entdeckt, das ganz Nette Bilder für Wetter oder auch einfach nur ein Orts-Icons erstellen kann.
      Meine 3 Versuche mit dem jeweiligen Prompt poste ich hier einfach mal. Alle Bildgenerierungen sind der erste Versuch. Alles wurde in ChatGPT gemacht.

      A physically based reality (PBR) rendering of a miniature 3D city model placed in the center of a clean, soft background [pastel background color recommended]. The model features a compact grid with a detailed [Frankfurt Opera] and [Sachsenhausen] surrounded by green trees and streets. Above the model, the [Frankfurt am Main], [sunny], and [26] Celsius are displayed in clear white text, along with a [weather icon]. Realistic lighting with soft shadows highlights the model's architecture and materials, emphasizing clarity, simplicity, and aesthetic precision. Portrait ratio.

      ed3b9acb-7003-4d2b-9d9d-384930747d51-image.png

      A physically based reality (PBR) rendering of a miniature 3D city model placed in the center of a clean, soft background [light blue pastel]. The model features a compact grid with a detailed [Stuttgart Königsbau] and [Fernsehturm] surrounded by green trees and streets. Above the model, the [Stuttgart], [sonnig], and [26] Celsius are displayed in clear white text, along with a [weather icon]. Realistic lighting with soft shadows highlights the model's architecture and materials, emphasizing clarity, simplicity, and aesthetic precision. Portrait ratio.

      1258e8a6-4a5d-4b4f-bec7-e2e0d6911c2f-image.png

      A physically based reality (PBR) rendering of a miniature 3D city model placed in the center of a clean, soft background [light blue pastel]. The model features a compact grid with a detailed [Berlin Alexanderplatz] and [Berliner Fernsehturm] surrounded by green trees and streets. Above the model, the [Berlin], [sonnig], and [26] Celsius are displayed in clear white text, along with a [weather icon]. Realistic lighting with soft shadows highlights the model's architecture and materials, emphasizing clarity, simplicity, and aesthetic precision. Portrait ratio.

      7c364f89-2c54-49b0-ad84-2fcbf44d02b6-image.png

      posted in Visualisierung
      OliverIO
      OliverIO
    • Test Adapter mytime

      Mein neuer Adapter soll sich um das Thema Zeit kümmern.
      Als erster Funktionsbaustein habe ich einen Countdown-Timer
      inklusive 2 Widgets umgesetzt.
      Eine detaillierte Beschreibung der Möglichkeiten ist in der Readme auf github zu finden

      Installation und Einrichtung

      Schritt 1 - Installation
      Der Adapter ist aktuell nur auf github verfügbar.
      Name des Repository ist https://github.com/oweitman/iobroker.mytime

      Schritt 2 - Instanz hinzufügen
      Der Adapter müsste dann im Abschnitt adapter im iobroker angezeigt werden.
      Manchmal kommt es vor, das insbesondere bei einem neuen Release mit Webänderungen (Widgets/Konfigurationsdialog) die Änderungen nicht sichtbar sind, muss evtl. auf der Kommandozeile folgender Befehl ausgeführt werden:
      iobroker upload mytime
      Im rechten Bereich in der Zeile des Adapters kann über den Plus-Knopf eine Instanz hinzugefügt werden

      Schritt 3 - Konfiguration

      Die Konfiguration ist relativ simpel. Es gibt nur wenige Felder.
      In den Eingabefeldern muss dem neuen Countdowntimer ein Name gegeben werden, sowie zur Erstkonfiguration die Angabe über die Dauer. diese kann aber später jederzeit über bestimmte Befehle auch von vis aus geändert werden.

      Über den Plus Knopf kann der Eintrag dann hinzugefügt werden. Das ändern und löschen eines Eintrags ist dann über die angezeigten Knöpfe hinter dem jeweiligen Countdown möglich.

      Schritt 4 - vis und widgets
      Aktuell gibt es 2 widgets

      • Countdown Plain (reine Textanzeige, formatierbar über einen Templatestring)
      • Countdown Circle (Ein Ring oder Kreis, der gemäß des Countdowns entsprechend abläuft.

      Eine detaillierte Beschreibung über die verfügbaren Datenpunkte, den verwertbaren States, die Verwendung der widgets inklusive einer Beispiel widgetgruppe für eine komplette Steuerung ist auf englisch in der Readme zu finden.

      Bei Fragen wie immer hier im Forum schreiben.

      Ich freue mich über reges testen und Vorschlag von Erweiterungen.

      Fehler können hier, aber auch auf github https://github.com/oweitman/ioBroker.mytime
      gemeldet werden.

      posted in Tester
      OliverIO
      OliverIO
    • Lösung für den Fehler EISGIT

      Wer seinen adapter direkt im Verzeichnis /opt/iobroker/node_modules entwickeln möchte
      und dort ein git Repository initialisiert, könnte den Fehler EISGIT beim aktualisieren/installieren eines anderen Adapters erhalten.
      Dafür funktioniert folgende Lösung:

      1. Seinen eine Ebene direkt unter /opt/iobroker kopieren.
        Ein vorheriger Versuch den Adapter unter /home/pi zu kopieren scheiterte leider an der Auflösung von dependencys

      Die Option -r steht für rekursiv
      Die Option -p steht für alle Rechte und Infos über Eigentümer mitkopieren.

      cd /opt/iobroker/node_modules/
      sudo cp -rp <VerzeichnisnameAdapter>/ /opt/iobroker/
      
      1. Zur Sicherheit macht ihr dann noch eine Sicherheitskopie und löscht dann das Verzeichnis
      cd /opt/iobroker/node_modules/
      tar -cvpf /home/pi/<adaptername>.tar <VerzeichnisnameAdapter>/
      rm -r /opt/iobroker/node_modules/<VerzeichnisnameAdapter>
      
      1. Dann geht ihr in das Verzeichnis mit der Kopie und legt einen npm link an.
        Dadurch wird ein symlink ins globale Modulverzeichnis angelegt
      cd /opt/iobroker/<VerzeichnisnameAdapter>
      sudo npm link
      
      1. Zum Schluss dann in das Programmverzeichnis von iobroker
        Dort führt ihr wieder npm link plus den Paketnamen des Adapters aus (also das was in package.json drin steht.
        Das legt letztendlich einen symlink in das node_modules Verzeichnis an, so dass euer adapter an gewohnter Stelle verfügbar ist
      cd /opt/iobroker/
      npm link <AdapterPackagename>
      

      Danach habt ihr unter node_modules einen symlink zum anderen Verzeichnis.
      Ihr könnt dann ganz normal wieder im Adapterverzeichnis unter node_modulse arbeiten und npm
      stört sich nicht mehr an dem git-Repository.

      posted in Entwicklung
      OliverIO
      OliverIO
    • Dashboard für Temp/Hum mit Flot im grafana-Stil

      Hallo,

      ich habe mir ein neues Dashboard für meine Temperatur und Feuchtigkeitswerte gebaut.
      Da mir der Stil von Grafana sehr gut gefallen hat, aber zum einen Grafana für mein kleines Anzeigetablet zu viel Overhead mitschleift, habe ich das mittels Flot nachgebaut.
      Übrigens nutzt grafana unter der Oberfläche ebenfalls flot, allerdings unter mehreren logischen Schichten an modulen verborgen (flot->businesscharts->react ->angular).

      Mein dashboard sieht wie folgt aus:
      ff994e87-6862-4fa1-ae3d-8306a09df9c2-image.png
      Durch touch auf die jeweilige Anzeige kommt die Detailanzeige, die durch einen erneuten Touch auch wieder geschlossen wird. Aktuell hier immer nur die 24h Sicht. Erweitern will ich das noch mit 2 oder 3 anderen durch Knopf umschaltbare Zeiten.
      9d4f1403-3839-43b9-ba4d-005328fa8822-image.png

      Um felxibel in der Anpassung zu sein hab ich mir hier keine eigenen Widgets gebaut, sondern
      die Umsetzung mittels eines Adapters und verschiedenen basic HTML-widgets gelöst, die HTML und javascript-Befehle enthalten.
      Im Adapter sind die ganzen Bibliotheken für flot, flot-gauge und meinen ganzen Backendcode mit den Floteinstellungen enthalten.
      In den Basic-Html widgets zum einen eines, in dem die ganzen Bibliotheken ins vis geladen werden und dann für jede einzelne Anzeige ein kurzer javascript-Block mit den Parametern, die dort angezeigt werden sollen.

      Inhalt html widget zum libs-laden

      <script type="text/javascript" src="http://192.168.1.61:8082/mydashboard/js/flot.gauge/js/jquery.flot.js"></script>
      <script type="text/javascript" src="http://192.168.1.61:8082/mydashboard/js/flot/jquery.flot.time.js"></script>
      <script type="text/javascript" src="http://192.168.1.61:8082/mydashboard/js/flot.gauge/jquery.flot.gauge.grafana.js"></script>
      <script type="text/javascript" src="http://192.168.1.61:8082/mydashboard/js/index.js"></script>
      
      </div>
      <script>
      getGauge('Küche','humidity','#gaugekitchen',200,220);
      getTemp('Küche','temperature','#tempkitchen',200,220);
      </script>
      
      


      Beispiel html-widget zur Anzeige der Feuchtigkeitsanzeige

      <div id="gaugekitchen" style=""></div>
      


      Beispiel html-widget zur Anzeige der Temperaturanzeige

      <div id="tempkitchen" class="tempValue"></div>
      

      Mein Backendjavascript im Adapter sieht so aus:

      function getSQLDate(device,parameter,callback,type) {
        
          var range12h = 1000*60*60*12;
          var range24h = 1000*60*60*24;
          if (type=='24h') var myQuery = "SELECT ts, parameter, val FROM iobroker.mihome_th where device = '" + device +"' and parameter in ('humidity','temperature') AND val is not null AND ts > unix_timestamp()*1000-((60*60*24)*1000) ORDER BY parameter,ts";
          if (type=='last') var myQuery = "SELECT ts,val FROM iobroker.mihome_th where device = '" + device +"' and parameter = '" + parameter +"' and val is not NULL order by ts desc limit 1";
          
          vis.conn._socket.emit('sendTo', 'sql.0', 'query', myQuery, function (callback,type,result) {
      
              if (result.error) {
                  console.error(result.error);
              } else {
                  
                  if (type=='last') {
                      var datapoints = Object.keys(result.result).map(function(key) {
                          return [result.result[key].ts, result.result[key].val];
                      });
                  }
                  if (type=='24h') {
                      var datapoints = result.result.reduce(function(acc,obj) {
                          var key = obj['parameter'];
                              if(!acc[key]) {
                                  acc[key] = [];
                              }
                              acc[key].push([obj.ts,obj.val]);
                              return acc;
                      },[]);
                  }
                  callback(datapoints);
                  
              }
          }.bind(this,callback,type));
      
      }
      function humFormatter(v, axis) {
          return v.toFixed(axis.tickDecimals) + " %H";
      }
      function tempFormatter(v, axis) {
          return v.toFixed(axis.tickDecimals) + " °C";
      }    
      
      
                          
                         function getTemp(device,parameter,placeholder,width,height) {
                              var data = {};
                              data.device = device;
                              data.parameter = parameter;
                              data.placeholder = placeholder;
                              getSQLDate(device,parameter,doTemp.bind(data),'last');                                                
                          }
                           function doTemp(sqldata) {
                              var data = this;
                              $(data.placeholder).html(tempFormatter(sqldata[0][1]));
                              getTempUpdate(data);
                          }
                          function getTempUpdate(data) {
                              getSQLDate(data.device,data.parameter,doTempUpdate.bind(data),'last');                        
                          }
                          function doTempUpdate(sqldata) {
                              var data = this;
                              $(data.placeholder).html(tempFormatter(sqldata[0][1]));
                              setTimeout(function() {
                                  getTempUpdate(data);
                              }.bind(data),5000);
                          }
                          
                          function tempFormatter(value) {
                              return Math.round(value) + "&deg;C";
                          }
                          
                          function getTempchart(device,parameter,placeholder,width,height,type='inside') {
                              var data = {};
                              data.placeholder = placeholder;
                              data.width = width;                        
                              data.height = height;
                              data.device = device;
                              data.type = type;
                              getSQLDate(device,parameter,doTempchart.bind(data),'24h');  
                          }
                          function doTempchart(sqldata) {
                              var data = this;
                              var new_tempdata = $.extend(true,{},temp_data);
                              new_tempdata[0].data = sqldata.temperature;
                              new_tempdata[1].data = sqldata.humidity;
                              debugger;
                              $(data.placeholder).width(data.width)
                                  .height(data.height);
                              if (data.type=='inside') data.options = $.extend(true,{},temp_inside_options);
                              if (data.type=='outside') data.options = $.extend(true,{},temp_outside_options);
                              data.plot = $.plot(data.placeholder,[new_tempdata[0],new_tempdata[1]], data.options);
      
                          }
      
                          
                          function getGauge(device,parameter,placeholder,width,height,type='inside') {
                              var data = {};
                              data.placeholder = placeholder;
                              data.width = width;                        
                              data.height = height;
                              data.device = device;
                              data.parameter = parameter;
                              data.type = type;
                              getSQLDate(device,parameter,doGauge.bind(data),'last');                        
                          }
                          function doGauge(sqldata) {
                              var data = this;
                              var new_humdata = hum_data.slice(0);
                              new_humdata[0].data = sqldata;
                              new_humdata[0].label = this.device;
                              
                              if (data.type=='inside') data.options = $.extend(true,{},hum_threshold_inside,hum_options);
                              if (data.type=='outside') data.options = $.extend(true,{},hum_threshold_outside,hum_options);
                              $(this.placeholder).width(this.width)
                                  .height(this.height);
                              data.plot = $.plot(this.placeholder,new_humdata, data.options);
                                  $(this.placeholder).click(function() {
                                      getTempchart(data.device,null,'#tempdialog',880,500,data.type);
                                      $('#tempdialog').dialog({
                                          dialogClass: 'noTitle',
                                          minHeight: 527,
                                          maxHeight: 527,
                                          minWidth: 900,
                                          maxWidth: 900,
                                          position: [0,28],
                                      }).on('click',function(event){
                                          $('#tempdialog').dialog('close');
                                      });
                                      return false;
                                  });
                              getGaugeUpdate(data);
                          }
                          function getGaugeUpdate(data) {
                              getSQLDate(data.device,data.parameter,doGaugeUpdate.bind(data),'last');                        
                          }
                          function doGaugeUpdate(sqldata) {
                              
                              var data = this;
                              var new_humdata = hum_data.slice(0);
                              new_humdata[0].data = sqldata;
                              new_humdata[0].label = this.device;
                              data.options.series.gauges.value.color = getColor(data.options.series.gauges,new_humdata[0].data[0][1]);
                              data.plot = $.plot(this.placeholder,new_humdata, data.options);
                              setTimeout(function() {
                                  getGaugeUpdate(data);
                              }.bind(data),5000);
                          }
                          function getColor(gaugeOptionsi, data) {
                              var color;
                              for (var i = 0; i < gaugeOptionsi.threshold.values.length; i++) {
                                  var threshold = gaugeOptionsi.threshold.values[i];
                                  color = threshold.color;
                                  if (data < threshold.value) {
                                      break;
                                  }
                              }
                              return color;
                          }
         
        
      
      var hum_data = [
                          {
                          label: "device",
                          data: [[0, 50]]
                          }
                        ];
                                
                        
      var hum_options = {
          series: {
            gauges: {
              frame: false,
              gauge: {
                  min: 30,
                  max: 70,
                  width: 15,
                  background: {
                      color: "#2f2f32"
                  },
                  border: {
                      color: "#2f2f32",
                      width: 0
                  },
                  shadow: {
                      show: false,
                  }
              },
              value: {
                  background: {
                      color: null
                  },
                  font: {
                      size: 40, // a specified number, or 'auto'
                      family: ",sans-serif"
                  },
      //            color: "#73bf69"
              },
              cell: {
                  background: {
                      color: null
                  },
                  border: {
                      show: false,
                  },
                  margin: 5,
                  vAlign: "middle" // 'top' or 'middle' or 'bottom'
              },
              debug: {
                  log: true,
                  layout: true
              },
              show: true,
              label: {
                  show: true,
                  color: "#d8d9da",
                  margin: 0,
                  font: {
                      size: 20, // a specified number, or 'auto'
                      family: ",sans-serif"
                  }
              }
            }
          }
        };                    
      var hum_threshold_outside = {
          series: {
            gauges: {
              threshold: {
                  values: [
                      {
                          value: 40,
                          color: "#73bf69"
                      }, {
                          value: 60,
                          color: "#73bf69"
                      }, {
                          value: 100,
                          color: "#73bf69"
                      },
                  ]
              }
            }
          }
      };
      var hum_threshold_inside = {
          series: {
            gauges: {
              threshold: {
                  values: [
                      {
                          value: 40,
                          color: "#ee485a"
                      }, {
                          value: 60,
                          color: "#73bf69"
                      }, {
                          value: 100,
                          color: "#ee485a"
                      },
                  ]
              }
            }
          }
      };
      
      var temp_data =  [
                      { 
                          data: null, 
                          color: "#F2495C",
                          bars: {
                              fillColor: "#F2495C"
                          },                    
                          label: "temp"
                      },
                      {   data: null,
                          color: "#5794F2",
                          bars: {
                              fillColor: "#5794F2"
                          },                    
                          label: "hum", 
                          yaxis: 2 
                      }
                  ];
      var temp_inside_options =  {
                          series: {
                              lines: {
                                  lineWidth: 2,
                                  fill: 0.1
                              }
                          },
                          xaxes:  [ 
                                      { 
                                          mode: "time", 
                                          timeformat: "%H:%M",
                                          color: "#464648",
                                          font: {
                                              color: "#d8d9da"
                                          }
                                      } 
                          ],
                          yaxes:  [ 
                                      { 
                                          min: 5,
                                          max: 35,
                                          tickFormatter: tempFormatter,
                                          color: "#464648",
                                          font: {
                                              color: "#d8d9da"
                                          }
      
                                      }, 
                                      {
                                          min: 30,
                                          max: 90,
                                          alignTicksWithAxis: 1,
                                          position: "rigth",
                                          tickFormatter: humFormatter,
                                          color: "#464648",
                                          font: {
                                              color: "#d8d9da"
                                          }
      
                                      } 
                          ],
                          legend: { position: "sw" },
                          grid: {
                              borderWidth:    0,
                              color:          "#464648",
                              labelMarginX:   0,
      
                          }
                          };
      var temp_outside_options =  {
                          series: {
                              lines: {
                                  lineWidth: 2,
                                  fill: 0.1
                              }
                          },
                          xaxes:  [ 
                                      { 
                                          mode: "time", 
                                          timeformat: "%H:%M",
                                          color: "#464648",
                                          font: {
                                              color: "#d8d9da"
                                          }
                                      } 
                          ],
                          yaxes:  [ 
                                      { 
                                          min: -15,
                                          max: 35,
                                          tickFormatter: tempFormatter,
                                          color: "#464648",
                                          font: {
                                              color: "#d8d9da"
                                          }
      
                                      }, 
                                      {
                                          min: 30,
                                          max: 100,
                                          alignTicksWithAxis: 1,
                                          position: "rigth",
                                          tickFormatter: humFormatter,
                                          color: "#464648",
                                          font: {
                                              color: "#d8d9da"
                                          }
      
                                      } 
                          ],
                          legend: { position: "sw" },
                          grid: {
                              borderWidth:    0,
                              color:          "#464648",
                              labelMarginX:   0,
      
                          }
                          };
      
      

      Für die Historydaten habe ich mir auf Basis der iobroker-Daten noch eine eigene View gebaut, da ich mit den kryptischen Datenpunktbezeichnungen nicht arbeiten wollte, die mit der Xiaomi mihome-Adapter da produziert.

      Auch bei der Erstellung des dashboards in vis sind noch ein paar Dinge zu beachten, da die iobroker-App zusätzlich geladene Bibiotheken direkt nicht mag. Daher muss man die erstellte view nochmals über eine weitere view in einem iframe anzeigen. dann klappt es.

      Meine Lösung ist etwas frickelig und der Code auch nicht optimal strukturiert. Daher bei Übernahme des Konzeptes sollte man sich etwas besser mit javascript, html, sql und vis auskennen. Es ist keine CopyPaste-Lösung.

      Bei Interesse kann ich die anderen Bibliotheken ebenfalls bereitstellen (github).
      Bei noch mehr Interesse könnte ich das auch mal per teamviewer vorstellen oder gar per WebEx mehreren gleichzeitig.

      posted in Visualisierung
      OliverIO
      OliverIO
    • RE: Adapter debuggen mit Chrome

      ich würde das hier gerne noch ergänzen für remote debugging, das heißt iobroker läuft nicht auf dem gleichen Rechner wie chrome, dann lautet der befehl in Anlehnung an dem obigen beispiel:

      node --inspect-brk=<ip-adresse iobroker>:9229 node_modules/iobroker.sayit/main.js --force --logs

      der parameter --inspect-brk sorgt im vergleich zu oben,
      das gleich zum start des debuggers auf der ersten Zeile deines Adapters ein breakpoint gesetzt wird
      Wer nicht immer den link zum start des debugs einzeln kopieren will, kann auch im chrome
      die folgende Seite aufrufen:
      chrome://inspect
      dann einmalig über configure die ip und port eures remotrechners genau wie beim inspect befehl eingeben.
      dort wird dann die debug session nach start des befehls angezeigt und kann mit einem klick gestartet werden.
      die chrome debug möglichkeiten finde ich fantastisch. ihr habt alle möglichkeiten, die ihr auch aus dem web-debugging kennt (breakpoints, auch mit Bedingungen, watch, callstack, scope inspection, consolenausgabe,etc.)
      bilder und englische Beschreibung befindet sich hier
      https://software.intel.com/en-us/xdk/articles/using-chrome-devtools-to-debug-your-remote-iot-nodejs-application

      falls noch nicht installiert ist auf dem iobroker rechner noch der node-inspector notwendig

      posted in Entwicklung
      OliverIO
      OliverIO
    • RE: JS-Adapter startet ständig neu: heap out of memory

      @smhrambo

      puh, jetzt wird es aber anstrengend

      posted in JavaScript
      OliverIO
      OliverIO
    • RE: Test/Support für Adapter rssfeed und vis-2-widgets-rssfeed

      Neue Version 0.0.23

      • Der Konfigurationsdialog wurde verbessert. Die Konfiguration kann nun in eine Datei gespeichert und auch wieder hochgeladen werden.
      • Das noch vorhandene admintab wurde entfernt. allerdings kann es sich noch in iobroker caches befinden. Unter Umständen muss der Adapter gelöscht und neu installiert werden. Tut aber auch nicht weh wenn das ausgeblendet bleibt.
      • Es gibt ein neues widget, mit dem man mehrere RSS Feeds aggregiert in einem widget darstellen kann. Das bisherige RSS Feed widget bleibt bestehen, da es durch die Aggregation Unterschiede im Template geben kann, wie mit den Variablen umgegangen wird. Mehr dazu in der Hilfe zum Multi widget. @jackblackson
      • Das RSS Feed Multi widget, sowie das JSON Template widget wurde so erweitert, das die Werte einer beliebigen Anzahl von Datenpunkten im Template verfügbar und verwendet werden kann. @Oli
      • Das bestehende Marquee widget 2 soll nicht mehr benützt werden. Dafür gibt es nun ein Marquee widget 3, welches ebenfalls ein Multi widget ist, in dem man mehrere RSS Feeds aggregieren kann.
      • Die folgenden veralteten widgets wurden aus dem Code entfernt. Wer diese bisher aus seinen Views noch nicht auf die neueren umgestellt hat, findet nun in der widget Auflistung in vis diese nur noch als undefined wieder.
      posted in Tester
      OliverIO
      OliverIO

    Latest posts made by OliverIO

    • RE: Skript im Widget?

      @ralf-2

      dann soll er es erst einmal so probieren wie bei vis1
      und dann schaut man mal wo probleme entstehen.
      er hat nach einem neuen widget gefragt

      posted in ioBroker Allgemein
      OliverIO
      OliverIO
    • RE: Skript im Widget?

      @gerdternes

      also ein neues widget wird normalerweise im Rahmen eines Adapter erstellt.
      Das ist allerdings eine etwas aufwändigere Geschichte. Hier mal der Link zum template Projekt welches man als Vorlage nehmen kann:
      https://github.com/ioBroker/ioBroker.vis-2-widgets-react-template

      Wenn du nur etwas visualisieren willst, dann könntest du

      A) ein html widget nehmen. da drin kannst du theoretisch auch ein script-tag einfügen, aber da gibt es glaube ich Einschränkungen

      B) du nimmst das widget jsontemplate für vis 2 befindet sich das aktuell noch im adapter vis-2-widgets-ovarious, kommt aber demnächst in einen eigenen adapter.
      darin kannst du mit dem ejs template syntax html,css und javascript ausführen lassen. daten aus json-datenpunkte sowie weitere datenpunkte kann an das widget übergeben werden. beispiele sind in der widget doku enthalten.

      posted in ioBroker Allgemein
      OliverIO
      OliverIO
    • RE: Elegante Methode um mehrere IF-Abfragen zu gestalten

      @dapanic

      Ich würde auch so wie der 3. Fall von @Asgothian machen.
      Eine Datenstrukturen aufbauen wo alle notwendigen Informationen enthalten sind und dann nur eine kleine programmlogik, welche anhand Input die entsprechenden Daten aus der Datenstrukturen auswählt und anhand der Parameter dann die Aktionen ausführt.
      Das ist sehr flexibel und für zukünftiger Erweiterungen offen.
      Auch durch minimierten Programmcode weniger Fehleranfälligkeit, was nachher die Suche schwierig macht.

      posted in Blockly
      OliverIO
      OliverIO
    • RE: [GELÖST] Auflistung MHD mit EPaper-Display am Kühlschrank

      @haselchen
      Fertig ist Zuviel gesagt.
      Es gab immer die Forderung nach Adapter. Dafür ist aber grocy zu komplex und gui müsste nachprogrammiert werden.
      Wird halt per iFrame in einer View eingeblendet.
      Es gab noch das Problem mit dem anmelden im Iframe. Das hatte ich aber gelöst.

      Dein Display müsstest dann halt per Script und Rest api individuell zusammenbauen.

      posted in Off Topic
      OliverIO
      OliverIO
    • RE: [GELÖST] Auflistung MHD mit EPaper-Display am Kühlschrank

      @haselchen
      Da gab es hier die Diskussion und Einbindung per Iframe
      https://forum.iobroker.net/topic/53024/lösung-für-liste-einkaufen-und-vorratskammer-gesucht

      posted in Off Topic
      OliverIO
      OliverIO
    • RE: Timeout in JS einbinden

      @peterfido
      Besser:
      Den Ende timestamp in einem datenpunkt merken und dann regelmäßig prüfen, ob er erreicht wird. Bzw. der datenpunkt existiert nur falls der Adapter neu gestartet wird, damit man wieder neu aufsetzen kann.
      Dann schreibt man nicht so oft in der Datenbank herum.

      posted in JavaScript
      OliverIO
      OliverIO
    • RE: [GELÖST] Auflistung MHD mit EPaper-Display am Kühlschrank

      @haselchen
      Und "morgen" wird das MHD abgeschafft.
      Ist leider schon zu lange in der Diskussion.

      posted in Off Topic
      OliverIO
      OliverIO
    • RE: [GELÖST] Auflistung MHD mit EPaper-Display am Kühlschrank

      @haselchen

      Wir vertrauen unseren Augen und Nase

      posted in Off Topic
      OliverIO
      OliverIO
    • RE: Timeout in JS einbinden

      @ubecker sagte in Timeout in JS einbinden:

      console.log('Gesamtanforderung:', gesamt_value);

      wie gesagt, das skript ist nicht von mir überarbeitet worden, sondern von chatGPT
      nach Definition ist das richtig
      https://developer.mozilla.org/en-US/docs/Web/API/console/log_static
      https://nodejs.org/api/console.html#consolelogdata-args
      console.log nimmt 1 bis N parameter. jeder parameter wird gemäß typ so ausgegeben

      mit + wird automatisch von javascript der typ aus gesamt_value nach string gewandelt und dann das ergebnis angehängt.

      da scheint es im javascript adapter noch was geben
      hier die ausgabe aus der browser console
      4e69704f-ced3-4f57-b243-1db1d37289bd-image.png

      und aus der node repl (einfach node starten)
      d774bb97-a55f-42fd-a7be-ae1477382e26-image.png

      habe mal geschaut.
      da ist die typdefinition im javascript adapter nicht ganz korrekt.
      die console befehle kennen alle nur einen parameter.
      allerdings ist das auch nicht die priorität, ist ja eh nur für debugging
      https://github.com/ioBroker/ioBroker.javascript/blob/64c375ea0e0840f21a7cc12582c970022f061fa2/src/types.d.ts#L570

      posted in JavaScript
      OliverIO
      OliverIO
    • RE: Timeout in JS einbinden

      @paul53 das was copy/paste aus chatgpt

      posted in JavaScript
      OliverIO
      OliverIO
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    The ioBroker Community 2014-2023
    logo