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 1
    • Followers 10
    • Topics 59
    • Posts 7395
    • Best 1206
    • Groups 4

    OliverIO

    @OliverIO

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

    1482
    Reputation
    1030
    Profile views
    7395
    Posts
    10
    Followers
    1
    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
    • 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
    • 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
    • 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
    • Neuer Adapter pi-hole2 für pihole>=V6
      Aktuelle Test Version 0.0.1
      Veröffentlichungsdatum Juni 2025
      Github Link https://github.com/oweitman/ioBroker.pi-hole2

      Nach dem der alte Adapter ab pihole v6 nicht mehr funktioniert, habe ich mich da mal dran gemacht. vgl auch forum.iobroker.net/topic/79939/pihole-adapter-ohne-funktion-nach-pi-hole-update-auf-v6

      Hier Adapter Beschreibung, Changelog etc.

      Funktionen

      Blockierung aktivieren oder deaktivieren

      Um die Werbung zu blockieren oder die Blockierung zu deaktivieren, kannst du einfach den Schalter im Datenpunkt Blocking verwenden.
      Der Datenpunkt BlockingTime ist dafür gedacht, die Blockierung vorübergehend zu deaktivieren – nach Ablauf der Zeit wird sie automatisch wieder eingeschaltet.
      Wenn du die Blockierung manuell aktivierst, passiert das sofort.

      Detaillierte Informationen – Übersicht

      Einige Informationen aus der Übersicht („Summary“) werden als eigene Datenpunkte unter Data.Summary angezeigt.
      Du kannst in der Adapterkonfiguration festlegen, ob diese Funktion aktiviert oder deaktiviert ist.
      Wenn sie aktiv ist, werden die entsprechenden Datenpunkte grün markiert – andernfalls rot.

      Detaillierte Informationen – Version

      Auch einige Daten aus dem Bereich „Version“ werden als einzelne Datenpunkte unter Data.Version bereitgestellt.
      Ob diese angezeigt werden, kannst du ebenfalls in der Konfiguration einstellen.
      Aktivierte Datenpunkte sind grün hervorgehoben, deaktivierte rot.

      Allgemeine sendTo-Funktion

      Mit der sendTo-Funktion kannst du Befehle direkt an dein Pi-hole-Gerät senden.
      Wenn du die API lokal ausprobieren möchtest, rufe einfach die Seite http://pi.hole/api/docs/# auf, gib dein Passwort ein und klicke auf den „Login“-Button.

      Weiteres

      Wer weitere Vorschläge zur Integration wichtiger Informationen machen möchte, kann gerne in seiner piholev6 installation die folgende Seite aufrufen: http://pi.hole/api/docs/, trägt dann oben sein Passwort ein und kann dann alle API-Endpunkte durchprobieren.

      gerne kann der adapter nun aus dem beta channel installiert werden.

      Fehler, Ideen, Anregungen dann bitte hier.

      Test nach Release im Beta bearbeitet

      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
    • RE: JS-Adapter startet ständig neu: heap out of memory

      @smhrambo

      puh, jetzt wird es aber anstrengend

      posted in JavaScript
      OliverIO
      OliverIO

    Latest posts made by OliverIO

    • RE: [geklärt] Hetzner API, nutzt die jemand von Euch?

      @metaxa sagte in [geklärt] Hetzner API, nutzt die jemand von Euch?:

      @OliverIO ich fürchte ich werde dich noch mit trivalen Dingen wie
      @oliverio sagte in [geklärt] Hetzner API, nutzt die jemand von Euch?:

      kann er mit den normalen Betriebssystem Mittel (df) den Stand abrufen und in einen Datenpunkt schreiben

      um dem schon einmal vorzugreifen. hier ein script zum abfragen der informationen von der shell im iobroker.

      in zeile 1 siehst du den befehl, der eigentlich aus 2 teilen besteht,
      da musst du ggfs die pfadangabe anpassen

      df --output=avail / | tail -n 1
      

      Teil1

      df --output=avail /
      
      df bedeutet disk free
      --output=avail bedeutet, das nur der Anteil zum freien speicher ausgegeben werden soll
      / ist die Pfadangaben. hier das komplette Hauptverzeichnis. wenn du nur den speicher eines gemounteten verzeichnis haben willst, musst du dann den pfad zum verzeichnis, wo das eingehängt worden ist. also bspw /mnt/entfernteslaufwerk
      xxxxxxxxxxxxxxxxxxxx zeile um den blöden zeilenumbruch wegzubekommen

      Teil2

      tail -n 1
      

      Da die Ausgabe mindestens 2zeilig ist (Überschrift+Daten) nimmt tail einfach nur die letzte Zeile, in der dann die Zahl enthalten ist.
      Da musst du nix verändern

      Hier das komplette Skript.
      Du musst dann noch den Datenpunkt bei dir anlegen und den Namen in Zeile 4 ggfs. anpassen.

      let cmd = "df --output=avail / | tail -n 1";
      exec(cmd, function (error, stdout, stderr) { 
          console.log(stdout); 
          setState('javascript.0.freierSpeicher',stdout);
      }); 
      
      
      posted in ioBroker Allgemein
      OliverIO
      OliverIO
    • RE: Mal wieder zerschossen

      @chaot

      Erst mal den physischen Status feststellen. Es können auch logische Fehler des Dateisystem sein, die sich reparieren lassen.
      Wenn die Platte schon ein wenig älter ist, dann ja, ansonsten werden die Probleme nicht besser.

      Der interessanteste Wert von Smart um den physischen plattenstatus zu bewerten bei ssd ist TBW total bytes written, reallocated sector count und uncorrectable error count

      posted in Error/Bug
      OliverIO
      OliverIO
    • RE: Mal wieder zerschossen

      @chaot
      Wenn du genug ram hast ist Redis schneller.
      Beide Systeme halten die Daten im ram und Speichern verzögert im Hintergrund. Redis hat das optimiertere Datenformat (binär) auf der Platte und ist in C geschrieben. Jsonl speichert als json und ist in JavaScript geschrieben.

      Daher ist Redis insgesamt besser.

      Gut, das keine offenen Ports, dann schließt sich das aus, das jemand fremdes sich da Scherze erlaubt.

      Probiere evtl. Mal mit der physischen Platte (also nicht im Container) einen Smart Festplatten Test durchzuführen um beginnende Schäden der Platte/ssd auszuschließen. Ergebnisse kannst du durch ChatGPT interpretieren lassen.

      Nachtrag
      Dringend die Platte prüfen
      Hier sind Fehler und Warnungen drin

      Messages concerning ext4 filesystem in dmesg:
      
      [Mon Jul 21 14:08:51 2025] EXT4-fs (loop1): error count since last fsck: 2
      [Mon Jul 21 14:08:51 2025] EXT4-fs (loop1): initial error at time 1666345607: ext4_check_bdev_write_error:217
      [Mon Jul 21 14:08:51 2025] EXT4-fs (loop1): last error at time 1666426664: ext4_journal_check_start:83
      [Mon Jul 21 14:09:38 2025] EXT4-fs (dm-12): unmounting filesystem 32a22a38-9374-43d2-a490-0d49504c12c9.
      [Mon Jul 21 14:09:41 2025] EXT4-fs (dm-12): mounted filesystem 32a22a38-9374-43d2-a490-0d49504c12c9 r/w with ordered data mode. Quota mode: none.
      
      posted in Error/Bug
      OliverIO
      OliverIO
    • RE: Mal wieder zerschossen

      @chaot

      Hinweis 1, was nichts mit dem eigentlichen Problem zu tun hat:
      Warum hast du json und Redis gemischt. Wenn dann würde ich auch die objects auf Redis umstellen.

      Hinweis2:
      Hast Du evtl. Ports am Router geöffnet?

      posted in Error/Bug
      OliverIO
      OliverIO
    • RE: Iobroker skill in Alexa nicht verfügbar

      @samson71
      Welche Gründe hast du da?
      Gut wenn Geräten kein ipv6 unterstützen, gehts nicht, aber ansonsten ist es im LAN kein Nachteil.

      posted in Cloud Dienste
      OliverIO
      OliverIO
    • RE: tvprogram Adapter

      @gerdternes
      Ja er funktioniert auch in vis2. Vis2 musste noch um etwas erweitert werden, was eine Weile gedauert hat, aber das Ostseite einiger Zeit ebenfalls erledigt.
      https://github.com/ioBroker/ioBroker.vis-2/pull/444

      Gibts dabei Probleme? Welche?

      oweitman created this issue in ioBroker/ioBroker.vis-2

      closed some changes to vis-2 #444

      posted in Einsteigerfragen
      OliverIO
      OliverIO
    • RE: Javascript Schedule Start-End wann ist der letzte Lauf

      @trojanhector

      Du könntest natürlich, so wie du es machst, immer den nächsten Start berechnen und wenn der Zeitpunkt erreicht ist, wiederum den darauf folgenden Start neu berechnen.
      Ich habe auch noch nicht ganz verstanden, was du überhaupt erreichen möchtest:

      Du möchtest innerhalb einer Zeitspanne, dann immer wieder was erneut ausführen?
      Also ein schedule in einem schedule?

      posted in ioBroker Allgemein
      OliverIO
      OliverIO
    • RE: Javascript Schedule Start-End wann ist der letzte Lauf

      @trojanhector

      Für recurring musst du andere Eigenschaften verwenden. Nicht Start und end, sondern

      RecurrenceRule properties
      second (0-59)
      minute (0-59)
      hour (0-23)
      date (1-31)
      month (0-11)
      year
      dayOfWeek (0-6) Starting with Sunday
      tz

      posted in ioBroker Allgemein
      OliverIO
      OliverIO
    • RE: Javascript Schedule Start-End wann ist der letzte Lauf

      @trojanhector

      Soweit ich das grob überblicke, liegt das Problem in deiner Funktion calcSecondsFromTime
      Das berechnet sozusagen die Anzahl der Sekunden seit Mitternacht
      Node-schedule möchte aber ein Jahr was Skript Datum Objekt, was die Anzahl an Millisekunden seit dem 1.1.1970 beinhaltet. Das musst du noch berücksichtigen.
      Aus diesem Grund funktioniert auch das Beispiel, welches du aus der Dokumentation kopiert hast.
      Dort wird das Date Objekt verwendet, welches du nicht verwändest

      So wie du es jetzt verwändest, wird der Job auch nur einmalig gestartet.
      Wenn du es wiederholt gestartet haben möchtest, musst du unter Recurring schauen

      Wenn du es noch einfacher machen möchtest, schaue meinen Adapter
      Mytime an.
      Dort kannst du beliebige Zeitreihen definieren, zu denen dann ein Datenpunkt für eine definierbar a Zeit lang getriggert wird. Auf diesen Daten. Kannst du dann reagieren und beliebige Aktionen ausführen.

      posted in ioBroker Allgemein
      OliverIO
      OliverIO
    • RE: [{DEPRECTED] Adapter ioBroker.iwg-vpn wurde gelöscht

      @mcm1957

      Das war sowieso ein etwas seltsamer Adapter.
      Closed source
      WireGuard über relay server ohne es direkt bzw. erst auf Nachfrage zu erwähnen.

      Wenn er daraus ein Geschäftsmodell entwickeln wollte, à la tailscale
      Hätte er es offen kommunizieren können
      So blieb halt ein geschmäckle.

      Gab es da viele Installationen? Ich denke nicht

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