Ankündigung

Einklappen
Keine Ankündigung bisher.

Temperaturen vom OneWire Bus per Smarthome.py auslesen und in einer Datei speichern

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    Temperaturen vom OneWire Bus per Smarthome.py auslesen und in einer Datei speichern

    Meine Wohnung wird z.Z. renoviert. Der Estrich ist gerade rein gekommen und ich habe Temperatursensoren per OneWire im Estrich.
    Ich habe im Moment noch keinen KNX Bus, der funktioniert, mit dem ich loggen könnte. Das Einzige was ich benötige ist eine vorübergehende Kontrolle der Temperaturwerte. Deshalb möchte ich das Script recht einfach halten.

    Ich benötige ein Script, welches stündlich eine Datei erstellt (mit Uhrzeit im Namen), die Temperaturwerte rein schreibt (zusammen mit entweder der KNX Bus Adresse oder der Temperatursensor ID), und diese Datei speichert.

    Bisher habe ich folgendes:

    Für /usr/local/smarthome/items habe ich eine Datei erstellt: beaglebone.conf:

    Code:
    [beaglebone]
      [[temperature]]
        type = num
        knx_dpt = 9
        knx_send = 12/0/1
        knx_reply = 12/0/1
        ow_addr = 28.FFF33C... (Die Adresse des Temperatursensors)
        sqlite = yes #keine Ahnung wofür der Befehl ist um Ehrlich zu sein
    
      [[temp2]]
      #genau das gleiche mit einem anderen Sensor und anderer Gruppenadresse
    Dann gibt es eine Datei in /usr/local/smarthome/logics namens tempwatch.py, was die eigentliche Logik enthält

    Code:
    import time #für die Zeit
    timestr = time.strftime("%d-%m-%Y_%H-%M-%S")
    
    filename = "/home/smarthome/tempwatch/tempwatch_"timestr+".txt"
    with open(filename,'w') as f:
        for item in sh.match_items('beaglebone.*'):
            f.write(item())
    Was bisher erst einmal die Temperatur schreiben sollte. Da fehlt also noch die Adresse die geschrieben werden soll.

    Ausserdem in der /usr/local/smarthome/etc/logic.conf folgender Eintrag damit die Logik ausgeführt wird

    Code:
    [tempwatch]
        filename = tempwatch.py
        crontab = init
        watch_item = beaglebone.*
        cycle = 1
    Im Moment ist cycle auf 1 gestellt, zm Testen dass es klappt. Wird dann auf 60 gestellt für die Stündliche ausgabe.

    Um die Logik zu starten bin ich nun in /usr/local/smarthome/bin und habe smarthome.py -s zum Stoppen, sowie smarthome.py --start zum Starten des Smarthome.py Prozesses ausgeführt.

    Leider werden keine Dateien erstellt. Ein Blick auf smarthome.py -f (zum Lesen der Ausgaben des Prozesses) hat mir als Anfänger natürlich auch nicht weiter geholfen.

    Vielleicht weiss ja jemand was ich falsch mache, und wie ich meinen Code ändern muss um die oben genannte Aufgabe zu lösen, nämlich meine Temperaturen zu loggen.


    Noch einmal als Erinnerung. Die Lösung ist keinesfalls langfristig gedacht, sondern lediglich für die nächsten Tage als Kontrolle. Sonst würde ich natürlich ein besseres Logging in Betracht ziehen und nicht einfach Dateien erstellen. Ich möchte es so einfach wie möglich halten und lediglich die Daten zur Kontrolle speichern und denke dass diese Lösung mit eine der Einfachsten ist.

    Vielen Dank
    Zuletzt geändert von Loki; 02.05.2016, 22:23.

    #2
    Hi,

    führe smarthome mal im Debug Modus aus ( -d), achte bitte darauf, das es keine weitere schon laufende Instanz gibt (ps -ax | grep smart).
    Solltest Du ein Zugriffsproblem haben, wird vermutlich eine exception auftreten, die Du im Debug Modus sehen kannst.

    Gruß,
    Bernd

    Kommentar


      #3
      Hi,

      um zu sehen, was potentiell falsch ist, solltest Du Bernds Vorschlag befolgen. Ich liste mal die Fehler bzw. Fehlannahmen auf, die im obigen Posting sind:
      • Wenn Du kein funktionierendes KNX hast, dann lass in den Items die knx_dpt, knx_send und knx_reply Attribute weg
      • Wenn Du nicht weißt, was sqlite macht, warum setzt Du es dann? sqlite (in Verbindung mit dem sqlite-Plugin) logged die Item-Werte in einer sqlite-DB.
      • Zum ow_addr Attribut gehört immer ein ow_sensor, für Temperatursensoren ein ow_sensor = T. Hast Du das 1-Wire-Plugin eingebunden?
      • Wieso willst Du jede Stunde eine neue Datei haben? Wenn es einfach bleiben soll, dann mach eine Datei, in die jede Stunde das Item und der Temperaturwert geschrieben werden
      • cycle = 1 bedeutet jede Sekunde, nicht jede Minute, somit brauchst Du cycle = 3600 und nicht cycle = 60
      • mit watch_item = beaglebone.* triggerst Du die Logik auch noch bei jeder Temperaturänderung, nicht nur jede Stunde (also watch_item weglassen)
      So, das wars erstmal. Ich würde erstmal dafür sorgen, dass Du alle Temperaturwerte sauber empfangen kannst, bevor Du mit einer Logik kämpfst, die Sachen wegschreibt. Dazu kannst Du das CLI-Plugin verwenden, mit dem Du die aktuellen Zustände von Items sehen kannst.

      Gruß, Waldemar
      OpenKNX www.openknx.de

      Kommentar


        #4
        Loki
        Wie gestern im Chat vorgeschlagen mach das über cron:

        Code:
        [tempwatch]
            filename = tempwatch.py
            crontab = 0 * * *
        bzw.
        Code:
        [tempwatch]
            filename = tempwatch.py
            crontab = * * * *
        Das was du hast reagiert auf alles, wie Waldemar schon geschrieben hat ;-)


        ow_sensor muss natürlich gesetzt sein damit das Plugin ne Idee davon bekommt was es abfragen und interpretieren soll.

        Das Log müsste den Fehler auch anzeigen.

        Kommentar


          #5
          Danke schon mal für die Antworten. Der oben stehende Code ist nicht mehr der aktuelle, ich kann den neuen wenn ich zu Hause bin gerne mal zeigen. Dennoch ein kurzes Update mit Hilfe von deinem Post mumpf


          Zitat von mumpf Beitrag anzeigen
          Hi,

          um zu sehen, was potentiell falsch ist, solltest Du Bernds Vorschlag befolgen. Ich liste mal die Fehler bzw. Fehlannahmen auf, die im obigen Posting sind:
          • Wenn Du kein funktionierendes KNX hast, dann lass in den Items die knx_dpt, knx_send und knx_reply Attribute weg
          • Wenn Du nicht weißt, was sqlite macht, warum setzt Du es dann? sqlite (in Verbindung mit dem sqlite-Plugin) logged die Item-Werte in einer sqlite-DB.
          • Zum ow_addr Attribut gehört immer ein ow_sensor, für Temperatursensoren ein ow_sensor = T. Hast Du das 1-Wire-Plugin eingebunden?
          • Wieso willst Du jede Stunde eine neue Datei haben? Wenn es einfach bleiben soll, dann mach eine Datei, in die jede Stunde das Item und der Temperaturwert geschrieben werden
          • cycle = 1 bedeutet jede Sekunde, nicht jede Minute, somit brauchst Du cycle = 3600 und nicht cycle = 60
          • mit watch_item = beaglebone.* triggerst Du die Logik auch noch bei jeder Temperaturänderung, nicht nur jede Stunde (also watch_item weglassen)
          So, das wars erstmal. Ich würde erstmal dafür sorgen, dass Du alle Temperaturwerte sauber empfangen kannst, bevor Du mit einer Logik kämpfst, die Sachen wegschreibt. Dazu kannst Du das CLI-Plugin verwenden, mit dem Du die aktuellen Zustände von Items sehen kannst.

          Gruß, Waldemar
          • Da ich das KNX schon vorbereite habe ich auch schon die Werte drinnen. Aber ok, könnte man weg lassen
          • fair enough. Mir wurde das in einem anderen Beitrag so genannt, deshalb war/ist es gesetzt.
          • ow_sensor ist bei mir drinnen, hatte ich beim Übertragen in den Code aber leider vergessen. Nein ich konnte nicht kopieren da ich auf einem anderen Rechner gearbeitet habe. Also ow_sensor ist korrekt gesetzt.
          • Ich habe den Code mittlerweile umgestellt, dass er alles in eine Datei logt, mit Zeitstempeln, also genau so wie du hier sagst
          • cycle ist mittlerweile ersetzt. Der Eintrag bei logic.conf sieht ähnlich aus wie von cmalo gezeigt. Läuft im Moment auch ein Mal die Minute. Später dann ein Mal die Stunde.
          • watch_item ist mittlerweile wie gesagt nicht mehr vorhanden


          Ich habe im Moment ein fast funktionierendes System. Es gibt leider noch ein paar Sachen die mir fehlen, aber vielleicht könnt ihr mir damit helfen.

          Wenn ich mit sh.match_items('beaglebone.*') meine Werte durchgehe (also hier als item), mit welchem Code kann ich den aktuellen Wert auslesen? Bisher habe ich nur über item.id() geschafft den Namen des items auszulesen
          Code:
          for item in sh.match_items('beaglebone.*'):
              f.write(item.id()+"\n") #die ID
              f.write(item.value()+"\n")# Wie kann ich den Wert lesen? Da es ein Temperatur Sensor ist erwarte ich einen 2byte Wert im hex format. Wobei ich natürlich lieber einen für Menschen lesbaren Temperatur Wert hätte
          Also wie kann ich den Wert lesen? Und wie bekomme ich einen normalen Temperatur Wert (C°) daraus?

          Das sind die zwei Dinge die mir noch fehlen.

          Vielen Dank

          Kommentar


            #6
            Hi,

            den Wert bekommst Du durch item(). also ohne irgendwelche Zusätze, nur mit Klammern dahinter.
            Soviel ich weiß, steht im Item schon der Temperaturwert, muss nicht mehr umgerechnet werden.

            Gruß, Waldemar

            OpenKNX www.openknx.de

            Kommentar


              #7
              Vielen Dank an alle, für die Hilfe. Ich habe es nun zum Laufen gebracht. Mein Script funktioniert nun so, dass es in einer Datei mit Zeitstempel alle 5 Minuten die Temperatur der am OW angeschlossenen Temperatursensoren logt.

              Für alle, die wie ich neu in dem Bereich sind und etwas Anlaufschwierigkeiten haben habe ich hier meine 3 Dateien, wodurch die Logik konfiguriert ist. Ich hoffe es hilft jemandem weiter.

              /usr/local/smarthome/items/beaglebone.conf <-- Die Datei mit den Temperatursensoren am OneWire / Die Items Datei für die Sensoren
              Code:
              #/usr/local/smarthome/items/beaglebone.conf
              [beaglebone] #namespace beaglebone
                      [[onboard]] #onboard Temp Sensor des Beaglebones
                              type = num
                              knx_dpt = 9
                              knx_send = 12/0/1
                              knx_reply = 12/0/1
                              ow_addr = 28.FFF33C641402
                              ow_sensor = T
                              sqlite = yes
                      [[weitereSensoren]] # Per OW angeschlossen, gleich definiert wie oben
              /usr/local/smarthome/logics/tempwatch.py
              Code:
              #/usr/local/smarthome/logics/tempwatch.py
              #!/usr/bin/env python
              
              import time #für den Zeitstempel
              timestr = time.strftime("%d.%m.%Y %H:%M:%S") #der Zeitstempel als String
              
              filename = "/home/smarthome/tempwatch/tempwatch.txt" #Pfad zur Datei, die geloggt werden soll
              with open(filename,'a+') as f: #Öffnen der Datei im Append Mode
                  f.write(timestr+"\n") #Zeitstempel schreiben
                  for item in sh.match_items('beaglebone.*'): #Für alle im beaglebone namespace vorhandenen Items (Im Moment nur Temperatursensoren)
                      if item(): #Wenn das Item einen Wert hat (für den Fall das ein Temperatursensor zwar in Items definiert ist, aber nicht angeschlossen ist)
                          f.write("ID: "+item.id()) #Schreiben der ID Bsp. Ausgabe: ID: beaglebone.onboard
                          f.write(" - Value: "+str(item())+"\n") #Schreiben des Wertes. Bsp. Ausgabe:  - Value: 28.41
              Hier möchte ich ausserdem erwähnen, was ich falsch gemacht habe. Der Temperatur Wert ist eine Zahl und kann nicht ohne Umwandlung in einen String als String in die Datei geschrieben werden. Deshalb ganz wichtig str(item()). item() gibt den Wert als Zahl, str() wandelt sie in einen String um.

              /usr/local/smarthome/etc/logic.conf
              Code:
              #/usr/local/smarthome/etc/logic.conf
              [tempwatch]
                  filename = tempwatch.py #Dateiname der Logik
                  crontab = init #Beim Starten von smarthome.py direkt ausführen
                  cycle = 300 #Nach 300 Sekunden = 5 Minuten erneut ausführen

              Ich hoffe mit meinen Fehlern und der gezeigten Lösung kann ich auch anderen Anfängern ein bisschen helfen. Ich bin zwar in der Lage Python zu programmieren, mache dies aber nicht regelmässig, weshalb ich immer wieder online nachschlagen muss. Dabei kann man leicht mal auf die Schnauze fallen, wie bei mir der Versuch item() ohne String convertion ausgeben zu wollen.

              Nun ja, vielen Dank noch einmal an alle, die mir beim Erstellen der Logik geholfen haben.

              Kommentar


                #8
                Hallo Loki,

                spannend wäre nun noch die Auswertung...
                Temperaturen spaltenweise für mehrere Sensoren kann man ja als CSV prima in Excel einlesen und daraus Kurven bauen.
                Wie sieht denn Deine Datei aus?

                Gruß Jürgen

                Kommentar


                  #9
                  Hallo Jürgen,

                  ich kann im Moment leider gerade nicht die neusten Scripte besorgen (da mein Beaglebone nicht bei mir ist und leider nur darauf die neuste Version läuft)

                  Aber meine Logik erstellt mir mittlerweile pro Temperatursensor eine json-Datei im folgenden Format:

                  Code:
                  {
                      "name":"beaglebone.onboard",
                      "data":[
                          {
                              "time":"05.13.2016 11:08:42",
                              "data":23.512
                          },
                          {
                              "time":"05.13.2016 11:13:42",
                              "data":24.01
                          }
                      ]
                  }

                  Diese Daten wiederum speise ich in eine kleine Webseite ein, und nutze chart.js zum Erstellen eines Graphen.

                  Ich kann den kompletten Code gerne noch bereitstellen, aber das schaffe ich denke ich eher am Wochenende. Ausserdem gibt es noch ein paar Verbesserungen die ich gerne implementieren würde (z.B. Zeitauswahl beim plotten über Eingabefelder)


                  Leider läuft die Webseite nicht gerade performant. chart.js braucht leider seine Zeit zum plotten.

                  Kommentar


                    #10
                    Darf ich noch mal fragen welche Vorteile du dir gegenüber dem sqlite und VISU Plugin versprichst?
                    Für Graphen wird zuätzlich an Infux-DB mit Graphana gearbeitet und JSON Abfragen kommen auch mit dem REST Plugin von mir, wenn es fertig ist. Hat den Vorteil, dass nicht alles in Files existieren muss sondern aus der Datenbank kommt.
                    Zuletzt geändert von cmalo; 13.05.2016, 12:01.

                    Kommentar


                      #11
                      Vorteil ist ganz einfach:
                      Quick and dirty

                      Ich brauche die Daten jetzt, schnell, ohne mich viel in irgendwas einarbeiten zu müssen. Es geht hier um Kontrolle, damit ich die Infos 1. habe, 2. weiter an einen Handwerker geben kann. Es geht noch bis Dienstag so, dann schmeiss ich meine Logik weg.

                      Da die Wohnung noch im Bau ist ist das für mich der einfachste und schnellste Weg.

                      Wenn es dann irgendwann darum geht eine gute Visualisierung zu machen, nutze ich auch eine Datenbank sowie Visualisierungstools die schon existieren.

                      Kommentar


                        #12
                        Ist halt nur die Frage was am Ende aufwendiger war. Die Implementierung oder kurz Visu, sqlite zu aktivieren und ne kleine Webseite aus den Beispielen zu kopieren.

                        Nur so für den Thread, es gibt auch das DataLog Plugin:
                        Code:
                        # DataLog
                        
                        
                        Plugin to dump the item data into files on the file system. It can be used
                        to configure different logs and log patterns and assign them to the
                        items. These items will be logged to the files.
                        
                        [datalog]
                           class_name = DataLog
                           class_path = plugins.datalog
                        #   path = var/log/data
                        #   filepatterns = default:{log}-{year}-{month}-{day}.csv | yearly:{log}-{year}.csv
                        #   logpatterns = csv:{time};{item};{value}\n
                        #   cycle = 300
                        
                        
                        [some]
                            [[item1]]
                                type = str
                                datalog = default
                            [[item2]]
                                type = num
                                datalog = default | custom
                            [[item3]]
                                type = num
                                datalog = custom
                        </pre>
                        
                        This will log the items
                        
                           * `some.item1` to the `default` log
                           * `some.item2` to the `default` and `custom` log
                           * `some.item3` to the `custom` log
                        Zuletzt geändert von cmalo; 13.05.2016, 13:14.

                        Kommentar

                        Lädt...
                        X