Navigation

    egnite Forum
    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    1. Home
    2. Marco T
    • Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Best
    • Groups

    Marco T

    @Marco T

    14
    Reputation
    49
    Posts
    579
    Profile views
    0
    Followers
    0
    Following
    Joined Last Online

    Marco T Follow

    Posts made by Marco T

    • RE: Windows 11, Webinterface zeigt Momentanwerte nicht sofort

      Ein unter WSL 2 laufender Firefox auf demselben Computer ist nicht betroffen. Dies ergibt insofern Sinn, als dass mit WSL 2 ein komplettes, virtualisiertes Linux unter Windows läuft.
      Win11 QuerxQuirk
      Links Firefox nativ Windows 11, Rechts Firefox unter Debian in Windows Subsystem for Linux 2

      Unter WSL 1, das den Netzwerkstack von Windows zu nutzen scheint, kann ich es nicht so leicht testen, da dort das Laufelassen von GUI Applikationen nicht ohne weiteres möglich ist (Ja, es gibt Workarounds)

      posted in Generelle Diskussion
      Marco T
    • Windows 11, Webinterface zeigt Momentanwerte nicht sofort

      Wenn ich auf meinem neuen Gerät mit Windows 11 das Webinterface des Querx THP aufrufe (getestet mit Firmware 5.0.14.1 und 5.0.16.1) werden die Momentanwerte nicht angezeigt.
      2022-05-09_08h06_53.png
      Nach 1 Minute werden die Werte dann angezeigt (hängt von der eingestellten refersh-rate des Webinterface ab, ich hab es normal auf 1min eingestellt. Stelle ich es auf 10s bekomme ich die Werte nach 10s).
      2022-05-09_08h07_38.png

      Überraschend: auf meinem alten Gerät mit Windows 10 tritt das Phänomen nicht auf. Auf beiden Geräten läuft Firefox Version 100.

      Getestet:
      Windows 10: Firefox 100, Chrome 101.0.4951.54, Edge 101.0.1210.39 -> Momentanwerte werden sofort dargestellt
      Windows 11: Forefox 100, Edge 101.0.1210.39 -> Momentanwerte werden erst angezeigt, wenn die Seite das Erste mal sich selber aktualisiert

      Durch Reload der Website (mit F5 oder Reload-Symbol) wird das Verhalten von Neuem getriggert (Auf Windows 11 werden die Momentanwerte dann nicht mehr dargestellt).

      Ein für mich völlig unerklärliches Phänomen das ich nicht "Bug" oder "Fehler" nennen will. Aber möglicherweise von Interesse für euch.

      posted in Generelle Diskussion
      Marco T
    • RE: Python / Datenbank / Querx Beispiel

      Und wer den Taupunkt wissen will, kann den SQL-Server rechnen lassen. Der macht das sehr effizient :). Bei der Abfrage von 19'000 Zeilen aus der DB lag der Zeitunterschied für die Verarbeitung der Abfrage unterhalb der mehr oder weniger zufälligen Varianz zwischen mehreren Anfragen.

      SELECT *,  ROUND(-4283.58 / ((LN( HumidityAvg / 100 ) + ((17.625*TemperatureAvg) / (243.04+TemperatureAvg))) - 17.625) - 243.04, 1) AS DewPoint
        FROM ClimateData
        WHERE TIME BETWEEN '2022-01-1 00:00' AND '2022-03-11 09:00'
      

      Die Resultate der Rechnung stimmen mit jenen überein, die vom Querx-Sensor selber ausgegeben werden.
      Die ursprünglich Formel war:

      ROUND( (243.04 * (LN( HumidityAvg / 100) + ((17.625 * TemperatureAvg) / (243.04 + TemperatureAvg)))) / (17.625 - (LN( HumidityAvg / 100 ) + ((17.625*TemperatureAvg) / (243.04+TemperatureAvg)))), 1) AS DewPoint
      

      Da ist aber (LN( HumidityAvg / 100) + ((17.625 * TemperatureAvg) / (243.04 + TemperatureAvg)) 2 mal drin, deshalb habe ich mit WolframAlpha rumgespielt, bis etwas kürzeres heraus kam 🙂 Die Ergebnisse sind identisch, die umgestellte Rechung ist aber deutlich kürzer und sollte auch effizienter sein.

      posted in Generelle Diskussion
      Marco T
    • RE: Python / Datenbank / Querx Beispiel

      Etwas flexibler als die 1. Abfrage ist folgende Abfrage, die die Maximal-, Minimal- und Durchschnittswerte über beliebige Zeitintervalle anzeigt:

      SELECT Sensor, Time, MIN(TemperatureLow), ROUND(AVG(TemperatureAvg), 1) , MAX(TemperatureHigh), MIN(HumidityLow), ROUND(AVG(HumidityAvg), 1), MAX(HumidityHigh), MIN(PressureLow), ROUND(AVG(PressureAvg), 1), MAX(PressureHigh) 
        FROM ClimateData
        WHERE Time BETWEEN '2022-01-01 00:00' AND '2022-02-01 00:00'
        GROUP BY UNIX_TIMESTAMP(TIME) DIV 3600
      

      Die 3. Zeile mit BETWEEN wählt den Zeitbereich, von welchem Daten angezeigt werden sollen.
      Die 3600 in der 4. Zeile ist das Intervall in Sekunden, über welches die Minimal-, Maximal- und Durchschnittswerte ermittelt werden.
      Mit der obigen Abfrage erhalte ich alle Werte vom Januar 2022 mit einem Intervall von 1h. Mit dieser Methode kann ich recht bequem die Daten reduzieren bevor ich sie z.B. in einer Tabellenkalkulation weiter verarbeite.
      Die Abfrage ist auch recht schnell. Alle Daten aus 2021 mit 1h Intervall abzufragen hat gerade mal 2.23s gedauert (MariaDB unter WSL auf einem Intel I5 3320 M mit 2.6GHz). Von diesen 2.23 wurden 2.17s für das Übertragen des Resultates zum Client benötigt 🙂

      Bei Abfragen mit grösseren Intervallen (z.B. 86400 für 1 Tag) ist zu beachten, dass unix_timestamp immer in UTC ist. Das muss man ev. manuell korrigieren.

      GROUP BY (UNIX_TIMESTAMP(TIME)+3600) DIV 86400
      

      zB wenn man UTC+1 (Mitteleuropäische Zeit) als Lokalzeit hat.

      posted in Generelle Diskussion
      Marco T
    • Druckwelle Vulkanesplosion Tonga

      Die Druckwelle der Vulkanexplosion bei Tonga war auch bei uns trotz 17000km Distanz gut messabar. Die Zeitschritte von 5min die ich für unseren Querx gewählt habe, reichen gerade um die Druckwelle zu erfassen. Mit +1.4hPa und -1.2hPa war die erste Welle um ca. 20:30 MEZ sehr gut von den natürlich auftretenden Luftdruckänderungen zu unterscheiden. Die 2. Welle um ca. 02:00 war da schon weniger deutlich.
      Druckwelle_Vulkanexplosion_Tonga.png
      Position: Arbon (Schweiz) 47.516669°, 9.433338°, 400müM (Luftdruck auf Stationshöhe)

      Wer hat die Welle auch gemessen und mag seine Daten teilen?

      posted in Generelle Diskussion
      Marco T
    • RE: Sommer / Winterzeit, csv export

      @Harald-Kipp ok. Danke für die Information.
      Ein weiterer Grund, endlich diese leidige Umstellung der Uhren 2 mal im Jahr abzuschaffen 🙂

      Dass time_local und time_gmt identisch sind, sollte meiner Meinung nach trotzdem nicht sein. Weder in Sommer- noch in Winterzeit.

       <part timestamp="1635638212">
        <date_local>31.10.2021</date_local>
        <time_local>01:56:52</time_local>
        <date_gmt>31.10.2021</date_gmt>
        <time_gmt>01:56:52</time_gmt>
       </part>
       <part timestamp="1635638512">
        <date_local>31.10.2021</date_local>
        <time_local>01:01:52</time_local>
        <date_gmt>31.10.2021</date_gmt>
        <time_gmt>01:01:52</time_gmt>
       </part>
      
      posted in Generelle Diskussion
      Marco T
    • Sommer / Winterzeit, csv export

      Guten Morgen

      Ich habe gerade meine Daten bezüglich Probleme mit Sommer/Winterzeit angeschaut und dafür auf meinem QuerxTHP mit FW 4.4.29 einen CVS-Export veranlasst. Der Export sowohl der csv als auch der xml daten erfolgte in diesem Fall über das Webinterface des Querx (was interessanterweise zu einem komplett anderen xml format führt als eine Anfrage per Web-Request).

      31.10.2021 00:56:52;23.0;23.1;23.1;41;41;41;965.9;966.0;966.1
      31.10.2021 01:01:52;23.0;23.1;23.1;41;41;41;966.0;966.1;966.2
      31.10.2021 01:06:52;23.0;23.1;23.1;41;41;41;966.1;966.3;966.3
      31.10.2021 01:11:52;23.0;23.1;23.1;41;41;41;966.2;966.2;966.3
      31.10.2021 01:16:52;23.0;23.1;23.1;41;41;41;966.3;966.3;966.4
      31.10.2021 01:21:52;23.0;23.1;23.1;41;41;41;966.2;966.3;966.5
      31.10.2021 01:26:52;23.0;23.1;23.1;41;41;41;966.3;966.4;966.5
      31.10.2021 01:31:52;23.0;23.1;23.1;41;41;41;966.3;966.3;966.4
      31.10.2021 01:36:52;23.0;23.1;23.1;41;41;41;966.3;966.4;966.4
      31.10.2021 01:41:52;23.0;23.1;23.1;41;41;41;966.3;966.3;966.4
      31.10.2021 01:46:52;23.0;23.1;23.1;41;41;41;966.3;966.4;966.6
      31.10.2021 01:51:52;23.0;23.1;23.1;41;41;41;966.5;966.6;966.7
      31.10.2021 01:56:52;23.0;23.1;23.1;41;41;41;966.5;966.6;966.6
      31.10.2021 01:01:52;23.0;23.0;23.1;41;41;41;966.6;966.6;966.7
      31.10.2021 01:06:52;23.0;23.0;23.1;41;41;41;966.6;966.7;966.7
      31.10.2021 01:11:52;23.0;23.0;23.1;41;41;41;966.6;966.8;966.9
      31.10.2021 01:16:52;23.0;23.0;23.1;41;41;41;966.8;966.9;967.0
      31.10.2021 01:21:52;23.0;23.0;23.1;41;41;41;966.8;966.9;966.9
      31.10.2021 01:26:52;23.0;23.0;23.1;41;41;41;966.7;966.8;966.9
      31.10.2021 01:31:52;23.0;23.0;23.1;41;41;41;966.7;966.8;966.9
      31.10.2021 01:36:52;23.0;23.0;23.1;41;41;41;966.8;966.9;966.9
      31.10.2021 01:41:52;23.0;23.0;23.1;41;41;41;966.8;966.9;967.0
      31.10.2021 01:46:52;23.0;23.0;23.1;41;41;41;966.9;967.0;967.1
      31.10.2021 01:51:52;23.0;23.0;23.1;41;41;41;967.0;967.1;967.1
      31.10.2021 01:56:52;23.0;23.0;23.1;41;41;41;966.9;967.0;967.1
      31.10.2021 02:01:52;23.0;23.0;23.1;41;41;41;966.8;966.9;967.0
      31.10.2021 02:06:52;23.0;23.0;23.1;41;41;41;966.7;966.8;966.9
      

      Es scheint, dass die Zeit beim Export nach 01:59:59 auf 01:00:00 zurück springt. Meiner Meinung nach müsste dies aber eine Stunde später erfolgen.

      Hier meine Zeiteinstellungen:
      2022-01-14_10h32_59.png

      Auch im xml-Export ist dieses Verhalten zu sehen:

       <part timestamp="1635638512">
        <date_local>31.10.2021</date_local>
        <time_local>01:01:52</time_local>
        <date_gmt>31.10.2021</date_gmt>
        <time_gmt>01:01:52</time_gmt>
        <temperature>
         <max>23.1</max>
         <average>23.0</average>
         <min>23.0</min>
        </temperature>
        <humidity>
         <max>41</max>
         <average>41</average>
         <min>41</min>
        </humidity>
        <pressure>
         <max>966.7</max>
         <average>966.6</average>
         <min>966.6</min>
        </pressure>
       </part>
      

      Die Timestamp ist ergibt: Sun Oct 31 2021 02:01:52 GMT+0200 (Mitteleuropäische Sommerzeit)

      posted in Generelle Diskussion
      Marco T
    • RE: Python / Datenbank / Querx Beispiel

      Daten aus der SQL-DB ziehen ist ganz einfach... Mit der Zeit wird die Datenmenge aber erheblich. Aber wir können den SQL-Server für uns arbeiten lassen.
      Wenn ich z.B. nur einen Wert pro Tag abfragen will ermittelt dieses Snippet den Tagesdurchschnitt sowie die Minimal- und Maximalwerte.

      SELECT TIME, round(avg(PressureAvg), 1) AS 'avg pressure', MAX(PressureHigh) AS 'max pressure', MIN(PressureLow) AS 'min pressure'
          FROM ClimateData
          GROUP BY CAST(Time AS DATE)
      

      Aber vielleicht will man wissen, wie schnell sich ein Wert geändert hat. Hier kommt die Funktion "LAG()" wie gerufen.

      WITH pressure_lag AS (SELECT Time, PressureAvg,
        LAG(PressureAVG, 11) OVER (ORDER BY Time) AS Pressure1h
        FROM ClimateData)
        SELECT *, COALESCE(ROUND(PressureAVG - Pressure1h,1)) AS Pdiff FROM pressure_lag
        ORDER BY Pdiff DESC
      

      In diesem Beispiel wird eine temporäre Tabelle angelegt in welcher die Zeit, der Luftdruckwert sowie der Luftdruckwert von 11 zeilen davor (1h früher) als Spalten enthalten sind. Der 2. Teil rechnet dann pro Zeile die Differenz aus und gibt das Ergebnis absteigend sortiert aus. So bekommt man die höchsten Werte zuerst angezeigt. Will man die kleinsten Werte zuerst sehen, lässt man einfach das "DESC" am Ende weg.

      posted in Generelle Diskussion
      Marco T
    • RE: Python / Datenbank / Querx Beispiel

      Danke an @tim für die inputs. Ich habe etwas weiter gearbeitet und eine (hoffentlich) verbesserte Version erstellt.

      Die Zeit wird nun in UTC in der DB abgelegt und die Daten werden in sichererer (und schnellerer) weise in der DB gespeichert (wobei das Speichern in der DB schon vorher nicht den grössten Teil der Zeit beanspruchte).
      Die neue Version nimmt die Ausführungszeiten der einzelnen Arbeitsschritte auf und zeigt diese am Ende an.

      #!/usr/bin/python3
      
      
      # transfer the data from the querx sesor into the mariadb / mysql-DB
      # procedure:
      # - get the time of the latest data in the database as a Unix Timestamp
      # - forge a request string for the querx http interface and get the data in xml format
      # - convert the data from xml to SQL and store it in the SQL DB
      #
      # by Marco Tedaldi, m.tedaldi aequator.ch 12.2021
      # 20220113 MTE time is stored in UTC in DB
      # 20220112 MTE switched from using mysql to mariadb
      #              split parsing and storing into two separate actions
      #              using .executemany to store all data in one go instead of using many separate SQL statements
      # 20220104 MTE added collection and display of timing information
      
      
      import sys
      import mariadb # mariadb
      import http.client  # to get the data from the querx
      import xml.etree.ElementTree as ET  # to parse the XML from the querx
      from datetime import datetime  # to conver the timestamps to datetime for the DB
      import time  # to measure execution time
      import math
      
      # access information for the Querx (copied from https://www.egnite.de/support/tutorials/tutorial-zugriff-auf-querx-messdaten-mit-python/)
      querx_address = "192.0.2.24"  # name or address of the Querx Sensor
      querx_http_port = 80
      xml_url = "/tpl/document.cgi?tpl/j/datalogger.tpl&format=xml"
      
      # databse access information
      conn_params= {
          "host" : "localhost",
          "user" : "username",
          "password" : "verysecurepassword",
          "database" : "phys_data",
      }
      db_table = "ClimateData"
      
      #copied from https://stackoverflow.com/questions/17973278/python-decimal-engineering-notation-for-mili-10e-3-and-micro-10e-6
      # function to display values in engineering or technical notation
      def eng_string(x, format='%s', si=False):
          '''
          Returns float/int value <x> formatted in a simplified engineering format -
          using an exponent that is a multiple of 3.
      
          format: printf-style string used to format the value before the exponent.
      
          si: if true, use SI suffix for exponent, e.g. k instead of e3, n instead of
          e-9 etc.
      
          E.g. with format='%.2f':
              1.23e-08 => 12.30e-9
                   123 => 123.00
                1230.0 => 1.23e3
            -1230000.0 => -1.23e6
      
          and with si=True:
                1230.0 => 1.23k
            -1230000.0 => -1.23M
          '''
          sign = ''
          if x < 0:
              x = -x
              sign = '-'
          exp = int(math.floor(math.log10(x)))
          exp3 = exp - (exp % 3)
          x3 = round(x / (10 ** exp3), 2)
      
          if si and exp3 >= -24 and exp3 <= 24 and exp3 != 0:
              exp3_text = 'yzafpnum kMGTPEZY'[exp3 // 3 + 8]
          elif exp3 == 0:
              exp3_text = ''
          else:
              exp3_text = 'e%s' % exp3
      
          return ('%s'+format+'%s') % (sign, x3, exp3_text)
      
      
      # function to get the timestamp of the last entry
      def get_lastTS(cursor):
          try:
              cursor.execute("SELECT UNIX_TIMESTAMP(MAX(Time)) FROM ClimateData")
              result = cursor.fetchone()
              ts = int(result[0])
          except:
              print("could not get timestamp from database, using 1.1.1970 00:00")
              ts = 0
          return(ts)
      
      
      # copied from https://www.egnite.de/support/tutorials/tutorial-zugriff-auf-querx-messdaten-mit-python/
      # adapted to get historical values
      def get_xml(address, port, url):
          try:
              # Python 3.x: httplib => http.client
              conn = http.client.HTTPConnection(address, port)
              conn.request("GET", url)
              res = conn.getresponse()
              xml = res.read()
              return(xml)
          except Exception as e:
              print("Error: " + str(e))
              sys.exit(1)
      
      
      # main program
      if __name__ == "__main__":
          runtime = [time.monotonic()]
          print('connecting to SQL database')
          db = mariadb.connect(**conn_params)
          cursor = db.cursor()
          runtime.append(time.monotonic())
          print('connected to SQL database')
          print('getting date and time of last entry')
          lastdata = get_lastTS(cursor)
          runtime.append(time.monotonic())
          date = datetime.fromtimestamp(lastdata).strftime('%d.%m.%Y %H:%M:%S')
          print('timestamp of last data: ' + str(lastdata) + " (" + date + ")")
          xml_url = xml_url + "&start=" + str(lastdata) + "&step=300"
          print("Getting data from http://" + querx_address + xml_url)
          climatedata = get_xml(querx_address, querx_http_port, xml_url)
          runtime.append(time.monotonic())
          print("Data received, now starting to parse")
          root = ET.fromstring(climatedata)
          sensorname = root.findtext('hostname')
          data = root.find('data')
          print("Number of records = " + str(len(data) - 1))
          datalist=[]
          query = 'INSERT INTO ' + str(db_table) + ' VALUES (?,?'
          for rnr, record in enumerate(data):
              if rnr == 0:
                  for entry in record:
                      query = query + ',?'
                  query = query + ')'
              else:
                  datatuple = ()
                  dtime = datetime.utcfromtimestamp(int(record.get('timestamp'))).strftime('%Y-%m-%d %H:%M:%S')
                  row = [ str(sensorname), dtime]
                  for entry in record:
                      row.append(str(entry.get('value')))
                  datatuple = tuple(row)
                  datalist.append(datatuple)
                  print('Records processed: ' + str(rnr), end='\r')
          runtime.append(time.monotonic())
          print("\nWriting data do DB")
          cursor.executemany(query, datalist)
          db.commit()
          runtime.append(time.monotonic())
          cursor.close()
          db.close()
          runtime.append(time.monotonic())
          print('\n')
          print("Runtimes:")
          print("Total Runtime = " +
                eng_string(runtime[5]-runtime[0], si=True) + "s")
          print("Connecting to DB took " +
                eng_string(runtime[1]-runtime[0], si=True) + "s")
          print("Getting Timestamp of last entry took " +
                eng_string(runtime[2]-runtime[1], si=True) + "s")
          print("Getting Data from Querx took " +
                eng_string(runtime[3]-runtime[2], si=True) + "s")
          print("Parsing and converting the data took " +
                eng_string(runtime[4]-runtime[3], si=True) + "s")
          print("Storing the data to DB took " +
                eng_string(runtime[5]-runtime[4], si=True) + "s")
          print("Disconnecting from DB took " +
                eng_string(runtime[6]-runtime[5], si=True) + "s")
      
      
      posted in Generelle Diskussion
      Marco T
    • RE: Python / Datenbank / Querx Beispiel

      @tim Oh, das sind gute Einwände! Danke.
      Die Timestamp im xml scheint in UTC zu sein was die Verarbeitung eigentich sehr einfach machen sollte. Einfach statt datetime.fromstimestamp() durch datetime.utcfromtimestamp() verwenden... allerdings muss ich dann alle Daten aus der Vergangenheit (die aus anderen Backups stammen) ich noch konvertieren...
      Der Aufwand dürfte sich lohnen um zukünftigen Problemen aus dem Weg zu gehen... Am Besten wohl gleich in der DB selbst Timestamp speichern.
      Es wird wohl Zeit für Version 0.2 (die dann wohl auch gar keine Abfrage macht, wenn der neueste Record in der DB weniger als timestep sekunden in der Verganenheit liegt.

      Das mit der Sicherheit stimmt natürlich. Und auch wenn der Zeitgewinn nicht gross sein dürfte, könnte das Zusammenfassen der Anfragen mit Library-Funktionen die Anzahl der Requests auf dem DB-Server u.U. deutlich Reduzieren.
      Andererseits ist soweit ich weiss schon der XML-Parser eigentlich nur für vertrauenswürdiges XML geeignet. D.h. wenn ich das Thema "Sicherheit" ernst nehmen will, muss ich auch dort vorkehrungen treffen.

      posted in Generelle Diskussion
      Marco T