Navigation

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

    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

    W
    • Profile
    • Following 0
    • Followers 0
    • Topics 6
    • Posts 14
    • Best 0
    • Groups 1

    wberger

    @wberger

    Starter

    0
    Reputation
    21
    Profile views
    14
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    wberger Follow
    Starter

    Latest posts made by wberger

    • RE: Sonoff Adapter mit Tasmota H801, oszillierende Werte

      Sollte vielleicht erwähnen, dass ich auf den Tasmota Geräten setoption20 ausgeführt habe (Ändern von Helligkeit schaltet nicht Power an). Da würde ich jetzt aber keinen Zusammenhang erwarten.

      posted in ioBroker Allgemein
      W
      wberger
    • Sonoff Adapter mit Tasmota H801, oszillierende Werte

      Der Sonoff Adapter treibt mich in den Wahnsinn. Ich habe einige Tunable White LED stripes an H801 LED Treibern rennen. Die H801 sind mit Tasmota geflasht. Im Iobroker über den Sonoff Adapter eingebunden und die Ansteuerung erfolgt über Slider aus VIS. Die prinzipielle Funktion ist da. Manchmal passiert es allerdings, dass entweder Helligkeit oder Farbton stelle. Danach oszilliert der Wert ungefähr im Sekundentakt zwischen Altem und Neuem hin- und her. Der Effekt ist sehr dauerhaft. Ich kann den Oszillator abwürgen entweder durch Stopp vom Sonoff Adapter oder durch einen Spannungsreset vom H801 Controller. Kennt dieses Problem jemand?

      Getestet habe ich: Tasmota 8.4 und 9.1
      Ich kann ausschließen, dass eins meiner Skripte die Änderung bewirkt. VIS pausieren durchbricht die Oszillation ebenfalls nicht. In den Events gehen die Änderungen vom Sonoff Adapter aus. Bei mir läuft normalerweise parallel der MQTT Adapter (auf anderem Port für einige ESP Easy Geräte). Testweise Abschalten bringt nichts.

      Am liebsten würde ich die Tasmota Geräte auch auf den MQTT Adapter bringen. Da tauchen aber per Default nur die Power Commands auf. Wie bekomme ich da die weiteren Stati rein?

      Ich bin schon so verzweifelt, dass ich angefangen habe die Hardware auf Shelly RGBW umzurüsten. Die funktionieren perfekt 😉

      posted in ioBroker Allgemein
      W
      wberger
    • Ladezeit (Sanduhr) von VIS

      Ich habe IOBroker schon seit geraumer Zeit laufen und bin damit ziemlich zufrieden. Auch die Möglichkeiten die Darstellung in VIS frei zu gestalten gefallen mir. Allerdings ist die Sanduhr von VIS nervig. Bei der Darstellung auf dem Tablett (aktuelles iPAD) reicht es schon wenn sich der Bildschirm kurz sperrt. Nach dem Entsperren sehe ich die VIS Oberfläche, bevor dann die Sanduhr kommt und ca. 5-10s lädt. Interessanterweise werden die Schaltbefehle die ich davor durch Knopfdruck tätige danach noch ausgeführt, Es scheint also nicht alles neu zu laden (nach Entsperren des Bildschirms sehe ich kurz die Vis Oberfläche, drücke einen Knopf, nichts passiert, Sanduhr kommt, wenn alles geladen wurde, dann wird der Schaltbefehl ausgeführt). Das kann doch nicht sein, dass die Seite ständig neu laden muss und das so lange dauert. Gibt es Möglichkeiten das zu beschleunigen?

      posted in Visualisierung
      W
      wberger
    • VIS Lizenz plötzlich ungültig Prüfung aber ok

      mein ioBroker lief bisher super. Ohne irgendeine Änderung sind aber heute Nacht die Webinterfaces abgeschmiert. Die Basics liefen wohl noch, da weiterhin Daten in der Influx DB aufgelaufen sind. Aber weder VIS noch die Admin Oberflächen waren erreichbar. Ich hatte dann den Raspberry neu gestartet.

      Nun zeigt VIS: keine gültige Lizenz!
      Wenn ich aber in der Admin Oberfläche beim VIS Adapter die Lizenz prüfe kommt die Meldung Lizenz ok.

      Jemand ne Idee?

      posted in Visualisierung
      W
      wberger
    • Counter, Reset bei Stromausfall "monotonic" Parameter

      Ich habe meinen Erdgaszähler digitalisiert. Als Sensor wird der Reedkontakt von Elster verwendet. Dieser ist an einem Eingang vom Wemos D1 Mini angeschlossen, auf welchem ESP Easy rennt. Die Daten laufen auch über MQTT bereits im ioBroker ein soweit so gut.

      Allerdings ist der Zähler im ESP Easy nicht persistent. Sprich nach Stromausfall startet dieser wieder bei Null. Nach etwas Recherche habe ich gelesen, dass in FHEM Parameter / States genau für diesen Zweck als "monotonic" definiert werden können. Daraus wird dann automatisch ein Wert gerechnet der monoton steigend ist und damit ein sinnvoller Zähler. Beginnt der Sensor zwischendurch wieder bei Null wird dieser Wert also zum alten dazu gezählt. Gibt es in ioBroker ebenfalls eine passende Lösung? Oder muss ich mir das selbst per Skript basteln?

      posted in ioBroker Allgemein
      W
      wberger
    • RE: [gelöst] Meteohub Daten, XML parsen, JSON durchsuchen

      Die Notation mit XML2JSON ist hier etwas schöner, da sich die Objekte nicht ganz so oft hinter einem zusätzlichen Dollarzeichen verstecken.
      Aber den Aussschlag für die Nutzung dieser Version gab dann die Performance. Ich habe die Ausführungszeit im Skript mitgestoppt (Nur Parsen der Daten und setzen der States, kein Abrufen der XML Datei).

      XML2JS: 346ms
      XML2JSON: 146ms
      Beides auf einem Raspberry Pi 4. Ich persönlich hab mich damit für XML2JSON entschieden.

      posted in Skripten / Logik
      W
      wberger
    • RE: [gelöst] Meteohub Daten, XML parsen, JSON durchsuchen

      Der ursprüngliche Post ist schon ein paar Tage her und die Lösung steht auch schon hier. Zwischenzeitlich habe ich das Skript fertiggestellt und etwas aufgehübscht. Außerdem habe ich nochmals beide Varianten XML2JS und XML2JSON verglichen. Falls jemand das selbe Problem hat findet ihr hier den fertigen Code.

      Zuerst per XML2JS Modul.

      /* Meteohub
      Skript holt Daten aus Meteohub XML Datei, bereitet sie auf und stellt einige Datenpunkte zur Verfügung
      erstellt: 2020 Wolfgang Berger
      V 0.1 Initiale Version. Hartcodierte Zuordnung. Wird nicht funktionieren sobald der Windmesser online ist.
      V 0.2 jetzt Sensoren in Liste
      V 0.3 Kosmetische Überarbeitung
      */
      
      // Settings   ################################################################
      var mh_URL = 'http://localhost/all-sensors-xml.txt';
      
      // Includes    ################################################################
      const request = require('request');    
      var xml2js = require('xml2js');
      const util = require('util');
      
      parser = new xml2js.Parser();
      
      // Type definitions  ################################################################
      var state_temp = {      type: 'number',  unit: '°C',  read: true,  write: false,role: 'value.temperature' };
      var state_json = {                                     read: true,  write: false,role: 'mh.json' };    
      var state_humidity = {  type: 'number',  unit: '%rH',  read: true,  write: false,role: 'value.humidity' };                                  
      var state_speed = {     type: 'number',  unit: 'km/h',  read: true,  write: false,role: 'value.speed' };                                  
      var state_direction = { type: 'number',  unit: '°',  read: true,  write: false,role: 'value.direction' };                                  
      var state_pressure  = { type: 'number',  unit: 'mbar',  read: true,  write: false,role: 'value.pressure' };     
      var state_rainrate  = { type: 'number',  unit: 'mm/h',  read: true,  write: false,role: 'value.precipitation.hour' };         
      var state_rain  = {     type: 'number',  unit: 'mm',  read: true,  write: false,role: 'value.precipitation.today' };             
      
      // Now build State Tree ################################################################
      
      // Meteohub main branch for states
      
      createState('meteohubjs.json', { name: 'Meteohub',  desc: 'Meteohub Daten Juergen', type:'object' });
      // all the functions ################################################################
      
      function parseXML(xmldata,do_init) {
        parser.parseString(xmldata, function(err,obj){ 
          let data = obj.meteohub.data;        // only use the data section of the object. We ignore the config section for now.
          
          // Loop through data sections. each data[i] contains data for a given timeframe like actual, like 1h, 1day, etc.
          for(let i = 0; i < data.length; i++) {
            let folder = 'meteohubjs.' + data[i].$.timeframe + '.';       // timeframe can be "actual", "alltime" and much more. Each datasection only contains one timeframe value
            let item = data[i].item;
            //log(util.inspect(data[i].$.timeframe));
      
            // Now we have selected one timeframe and loop through all items
            // instead of building a state tree with hundreds of values, we pick only the ones that are interesting.
            for(let j = 0; j < item.length; j++) {
              let id = folder + item[j].$.sensor + '.' + item[j].$.cat;
      
              // Temperature Value in degrees Celsius
              if( (item[j].$.cat == 'temp') && (item[j].$.unit == 'c')) {
                  if (do_init==true) {    createState(id,parseFloat(item[j]._),state_temp); }
                    else {    setState(id,parseFloat(item[j]._)); }
              }
      
              // Humidity as relative humidity
              if( (item[j].$.cat == 'hum') && (item[j].$.unit == 'rel')) {
                  if (do_init==true) {   createState(id,parseFloat(item[j]._),state_humidity); }
                    else  {   setState(id,parseFloat(item[j]._)); }          
              }
      
              // Air pressure refered to sealevel
              if( (item[j].$.cat == 'sealevel') && (item[j].$.unit == 'hpa')) {   
                  if (do_init==true) {   createState(id,parseFloat(item[j]._),state_pressure); }
                    else  {   setState(id,parseFloat(item[j]._)); }          
              }        
      
              // rain values in mm
              if( (item[j].$.sensor == 'rain0') && (item[j].$.unit == 'mm')) {
                  if (do_init==true) { createState(id,parseFloat(item[j]._),state_rain);  }
                    else { setState(id,parseFloat(item[j]._));  }
              }
      
              // for windsensor currently we tend to catch nearly all, because the whitelist could be long. For example windspeed is interesting in different units.
              // Therefore instead of whitelisting the values we do the oposit and use a blacklist for the ones we don't like.
              if( (item[j].$.sensor == 'wind0') ) {
                  if ((item[j].$.unit == 'time')) {
                      let dat = item[j]._;
                      let d = new Date(dat.substring(0,4) + '-' + dat.substring(4,6) + '-' + dat.substring(6,8) + 'T' + dat.substring(8,10) +':' + dat.substring(10,12) + ':'+ dat.substring(12,14) );
                      if (do_init==true) {    createState(id+'.'+item[j].$.unit,  d);    }
                        else {    setState(id+'.'+item[j].$.unit,  d);    }
                  }
                  else {
                      // first catch values in degrees celsius. Because there we can set the unit. Leave the others without unit.
                      if (item[j].$.unit == 'c') {
                        if (do_init==true) { createState(id+'.'+item[j].$.unit,  parseFloat(item[j]._),state_temp); }                           
                          else  { setState(id+'.'+item[j].$.unit,  parseFloat(item[j]._)); }               
                      }
                      else {
                          // Blacklisting for values we don't like
                          if (!(item[j].$.unit == 'f' || item[j].$.unit == 'en' || item[j].$.unit == 'nl' || item[j].$.unit == 'mph')) {
                          if (do_init==true) { createState(id+'.'+item[j].$.unit,  parseFloat(item[j]._)); }                           
                              else  { setState(id+'.'+item[j].$.unit,  parseFloat(item[j]._)); }               
                          }
                      }
                  }
              }        
      
      
            }
      
      
      
          }
        
         //log('end build tree');
      
        });
      }  // end parseXML()
       
      
      function getXML(do_init) {
          // loads full meteohub xml file from the mh_URL and calls the parse function.
          // on very first execution do_init is true and all states are created. Each successive call only sets the state values.
          log('meteohub query data from '+mh_URL); // Debug output
          request(mh_URL, function (error, response, body) {
              if (error) log("Fehler beim Herunterladen Meteohub XML: " + error, 'error');
              else {
                  //var start = new Date();
                  parseXML(body,do_init);
                  //var time = new Date() - start;            
                  //log('Meteohub XML2JS Durchlaufzeit: '+time); 
              };
          });
      }
      
      // On first script execution, create the states
       let do_init=true;
       getXML(do_init);
      
      // Regular Update
      schedule('*/1 * * * *', function () {
          let do_init=false;
          getXML(do_init);  // regelmäßiger Update
      }); 
      

      Und nun noch der selbe Spass Alternativ per XML2JSON

      /* Meteohub
      Skript holt Daten aus Meteohub XML Datei, bereitet sie auf und stellt einige Datenpunkte zur Verfügung
      erstellt: 2020 Wolfgang Berger
      
      V 0.1 Initiale Version. Hartcodierte Zuordnung. Wird nicht funktionieren sobald der Windmesser online ist.
      V 0.2 jetzt Sensoren in Liste
      V 0.3 kosmetische Aufbereitung. Altlasten entfernt.
      */
      
      // Settings   ################################################################
      const mh_URL = 'http://localhost/all-sensors-xml.txt';
      
      
      // End of settings ###########################################################
      
      
      // Includes    ################################################################
      const request = require('request');    
      var parser = require('xml2json');
      const util = require('util');      // for debugging. Use log(util.inspect(obj));
      
      // Type definitions  ################################################################
      var state_temp = {      type: 'number',  unit: '°C',  read: true,  write: false,role: 'value.temperature' };
      var state_json = {                                     read: true,  write: false,role: 'mh.json' };    
      var state_humidity = {  type: 'number',  unit: '%rH',  read: true,  write: false,role: 'value.humidity' };                                  
      var state_speed = {     type: 'number',  unit: 'km/h',  read: true,  write: false,role: 'value.speed' };                                  
      var state_direction = { type: 'number',  unit: '°',  read: true,  write: false,role: 'value.direction' };                                  
      var state_pressure  = { type: 'number',  unit: 'mbar',  read: true,  write: false,role: 'value.pressure' };     
      var state_rainrate  = { type: 'number',  unit: 'mm/h',  read: true,  write: false,role: 'value.precipitation.hour' };         
      var state_rain  = {     type: 'number',  unit: 'mm',  read: true,  write: false,role: 'value.precipitation.today' };             
      
      // Now build State Tree ################################################################
      
      function parseXML(xmldata,do_init) {
         var mh_json = parser.toJson(xmldata);    // convert XML to JSON
         var mh_data = JSON.parse(mh_json);       // parse JSON into JS object
        
         let data = mh_data.meteohub.data;        // only use the data section of the object. We ignore the config section for now.
      
         // Loop through data sections. each data[i] contains data for a given timeframe like actual, like 1h, 1day, etc.
         for(let i = 0; i < data.length; i++) {
           let folder = 'meteohub.' + data[i].timeframe + '.';       // timeframe is can be "actual", "alltime" and much more. Each datasection only contains one timeframe value
           let item = data[i].item;
           //   log(util.inspect(data[i]));
      
           // Now we have selected one timeframe and loop through all items
           // instead of building a state tree with hundreds of values, we pick only the ones that are interesting.
           for(let j = 0; j < item.length; j++) {
              let id = folder + item[j].sensor + '.' + item[j].cat;
      
              // Temperature Value in degrees Celsius
              if( (item[j].cat == 'temp') && (item[j].unit == 'c')) {
                  if (do_init==true) {    createState(id,parseFloat(item[j].$t),state_temp); }
                    else {    setState(id,parseFloat(item[j].$t)); }
              }
      
              // Humidity as relative humidity
              if( (item[j].cat == 'hum') && (item[j].unit == 'rel')) {
                  if (do_init==true) {   createState(id,parseFloat(item[j].$t),state_humidity); }
                    else  {   setState(id,parseFloat(item[j].$t)); }          
              }
      
              // Air pressure refered to sealevel
              if( (item[j].cat == 'sealevel') && (item[j].unit == 'hpa')) {   
                  if (do_init==true) {   createState(id,parseFloat(item[j].$t),state_pressure); }
                    else  {   setState(id,parseFloat(item[j].$t)); }          
              }        
      
              // rain values in mm
              if( (item[j].sensor == 'rain0') && (item[j].unit == 'mm')) {
                  if (do_init==true) { createState(id,parseFloat(item[j].$t),state_rain);  }
                    else { setState(id,parseFloat(item[j].$t));  }
              }
      
              // for windsensor currently we tend to catch nearly all, because the whitelist could be long. For example windspeed is interesting in different units.
              // Therefore instead of whitelisting the values we do the oposit and use a blacklist for the ones we don't like.
              if( (item[j].sensor == 'wind0') ) {
                  if ((item[j].unit == 'time')) {
                      let dat = item[j].$t;
                      let d = new Date(dat.substring(0,4) + '-' + dat.substring(4,6) + '-' + dat.substring(6,8) + 'T' + dat.substring(8,10) +':' + dat.substring(10,12) + ':'+ dat.substring(12,14) );
                      if (do_init==true) {    createState(id+'.'+item[j].unit,  d);    }
                        else {    setState(id+'.'+item[j].unit,  d);    }
                  }
                  else {
                      // first catch values in degrees celsius. Because there we can set the unit. Leave the others without unit.
                      if (item[j].unit == 'c') {
                        if (do_init==true) { createState(id+'.'+item[j].unit,  parseFloat(item[j].$t),state_temp); }                           
                          else  { setState(id+'.'+item[j].unit,  parseFloat(item[j].$t)); }               
                      }
                      else {
                          // Blacklisting for values we don't like
                          if (!(item[j].unit == 'f' || item[j].unit == 'en' || item[j].unit == 'nl' || item[j].unit == 'mph')) {
                          if (do_init==true) { createState(id+'.'+item[j].unit,  parseFloat(item[j].$t)); }                           
                              else  { setState(id+'.'+item[j].unit,  parseFloat(item[j].$t)); }               
                          }
                      }
                  }
              }
      
           }
          }
      
      }  // end parseXML()
       
      function getXML(do_init) {
          // loads full meteohub xml file from the mh_URL and calls the parse function.
          // on very first execution do_init is true and all states are created. Each successive call only sets the state values.
          log('meteohub query data from '+mh_URL); // Debug output
          request(mh_URL, function (error, response, body) {
              if (error) log("Fehler beim Herunterladen Meteohub XML: " + error, 'error');
              else {
                  var start = new Date();            
                  parseXML(body,do_init);
                  var time = new Date() - start;            
                  log('Meteohub XML2JSON Durchlaufzeit: '+time);             
              };
          });
      }
      
      // On first script execution, create the states
       let do_init=true;
       getXML(do_init);
      
      // Regular Update
      schedule('*/1 * * * *', function () {
          let do_init=false;
          getXML(do_init);  // regelmäßiger Update
      });
       
       
      
      posted in Skripten / Logik
      W
      wberger
    • RE: [gelöst] Meteohub Daten, XML parsen, JSON durchsuchen

      @paul53 Danke das war der Gedankenanstoß, den ich gebraucht hatte. Zwar keine fertige Funktion, aber ein schöner Ansatz für die Indizierung der Daten.
      Ich hab das mal noch auf die Schnelle ausprobiert. Ich muss noch etwas mehr filtern, da sonst mehrere Datenpunkte sich überschreiben (was du natürlich bei dem gekürzten file nicht sehen konntest). Außerdem baue ich den Baum etwas anders auf, da ein Sensor zum Beispiel "th0" immer Temperatur, Feuchte und manchmal auch Luftdruck hat. Danach möchte ich gruppieren. Aber das Prinzip bleibt das Selbe. Hier mal der quick'n'dirty adaptierte Code, der funktioniert und dann auch das Ergebniss entsprechend Screenshot liefert. Top. Ich mach das morgen mal noch etwas schön und berichte weiter.

      let data = mh_data.meteohub.data;  
      for(let i = 0; i < data.length; i++) {
        let folder = 'meteohub.' + data[i].timeframe + '.';
        let item = data[i].item;
        for(let j = 0; j < item.length; j++) {
           let id = folder + item[j].sensor + '.' + item[j].cat;
      
           if( (item[j].cat == 'temp') && (item[j].unit == 'c')) {
              createState(id,parseFloat(item[j].$t),state_temp);
           }
           if( (item[j].cat == 'hum') && (item[j].unit == 'rel')) {
              createState(id,parseFloat(item[j].$t));            
           }
        }
      }
      

      mh.jpg

      posted in Skripten / Logik
      W
      wberger
    • RE: [gelöst] Meteohub Daten, XML parsen, JSON durchsuchen

      Als letzte Info noch ein Beispiel wie die konvertierte JSON Struktur nach XML2JSON aussieht (auch stark verkürzt). Vielleicht kann ja auch jemand der mit obigen Modulen keinerlei Erfahrung hat mir trotzdem behilflich sein mit dem Durchsuchen der Javascript Objekte.

          "meteohub": {
              "config": {
                  "language": "de",
                  "temp_sensor": {
                      "unit": "c",
                      "print": "°C",
                      "$t": "th0"
                  },
                  "hum_sensor": {
                      "unit": "rel",
                      "print": "%",
                      "$t": "th0"
                  }
               },
              "data": [
                  {
                      "timeframe": "actual",
                      "item": [
                          {
                              "sensor": "th0",
                              "cat": "temp",
                              "unit": "c",
                              "$t": "7.3"
                          },
                          {
                              "sensor": "th0",
                              "cat": "hum",
                              "unit": "rel",
                              "$t": "20"
                          }
      	            ]
      	        },
                  {
                      "timeframe": "alltime",
                      "item": [
                          {
                              "sensor": "th0",
                              "cat": "temp",
                              "unit": "c",
                              "$t": "7.3"
                          },
                          {
                              "sensor": "th0",
                              "cat": "hum",
                              "unit": "rel",
                              "$t": "20"
                          }
                       ]
                   }
               ]
           }
      }
      
      ich bräuchte eine Funktion, die mir zum Beispiel den Wert für timeframe=="actual" und sensor=="th0" mit cat=="temp" und unit=="c" zurück gibt.
      posted in Skripten / Logik
      W
      wberger
    • RE: [gelöst] Meteohub Daten, XML parsen, JSON durchsuchen

      Um die Daten nun zu zerlegen habe ich zwei Methoden die eingeschränkt funktionieren.

      XML2JS

      var xml2js = require('xml2js');
      parser = new xml2js.Parser();
      parser.parseString(xmldata, function(err,obj) {
        setState("meteohub.th0.temp.val", parseFloat(obj.meteohub.data[0].item[71]._));
      }
      

      oder XML2JSON

      var parser = require('xml2json');
      var mh_json = parser.toJson(xmldata);  // Convert XML to JSON
      var mh_data = JSON.parse(mh_json);     // Parse JSON into JS object
      setState("meteohub.th0.temp.val",mh_data.meteohub.data[0].item[50].$t);
      
      

      Beide Varianten funktionieren. Jetzt ist es aber durchaus unschön, über hart kodierte Indizes zuzugreifen, da diese sich auch immer wieder ändern. Gibt es eine schöne Möglichkeit die Daten zu durchsuchen oder zu adressieren? Klar kann ich mir selbst eine Funktion schreiben die mit vielen Schleifen den gesammten Objektbaum durchläuft und sich die Infos zusammen sammelt. Aber da gibt es doch bestimmt etwas schönes in der Art der indexOf() Funktion oder ähnlichem?

      posted in Skripten / Logik
      W
      wberger
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    The ioBroker Community 2014-2023
    logo