Ankündigung

Einklappen
Keine Ankündigung bisher.

Berechnung: Betriebsminutenzähler für Lampe + zeitverzögertes Ausschalten

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

    Berechnung: Betriebsminutenzähler für Lampe + zeitverzögertes Ausschalten

    Hallo openHAB-Community.

    ich würde gerne einen Betriebsminutenzähler für eine Lampe realisieren. Darüber hinaus soll nach Erreichen eines bestimmten Schwellenwertes die Lampe nach 10s ausgehen.

    Hier mein Ansatz - teilweise als Pseudocode:

    Code:
    var int betriebsminutenzaehler = 0;
    var int schwellenwert = 200;
    var ? zeitstempelStart = 0;
    var ? zeitstempelStop = 0;
    
    rule "LightOn"
    when
       Item Light changed from OFF to ON
    then
       zeitstempelStart = aktueller Zeitstempel;
       if (betriebsminutenzaehler >= schwellenwert) {
           createTimer(now.plusSeconds(10))
           sendCommand(Light, OFF) }
    end
    
    rule "LightOff"
    when
       Item Light changed from ON to OFF
    then
       zeitstempelStop = aktueller Zeitstempel;
       betriebsminutenzaehler = betriebsminutenzaehler + (zeitstempelStop - zeitstempelStart);
       zeitstempelStart = 0;
       zeitstempelStop = 0;
    end

    Meine Frage an dieser Stelle:
    - Wie soll ich denn meine beiden Variablen zeitstempelStart und zeitstempelStop typisieren, damit ich im Nachgang den Betriebsminutenzähler realisieren kann?
    - Wie bekomme ich denn den akteullen Zeitstempel bestimmt?
    - Wie bekomme ich aus den beiden Variablen zeitstempelStop und zeitstempelStart die Differenz in Minuten oder Sekunden?
    - Ist die Wartezeit von 10 Sekunden mit dem Befehl createTimer(now.plusSeconds(10)) so ok?

    Bin für jede Hilfe dankbar (!)

    Vielen Dank.

    #2
    Den Betriebstundenzähler könnte man über eine Persistence speichern.
    Ich würde dann in einer minütlichen Rule prüfen ob die Lampe an ist und wenn ja den Zähler erhöhen.
    Also gar nicht erst irgendwelche Berechnungen anstellen.
    Das mit dem Timer sollte so ok sein, die Syntax stimmt aber nicht.

    Holger

    Kommentar


      #3
      Hallo Holger,

      vielen Dank für deine Nachricht.

      Was genau würdest du denn auf die DB ablegen, um so den BEtriebsstundenzahlen zu bekommen? Was spricht denn gegen meinen Vorschlag den Wert zur Laufzeit zu aktualisieren?

      Helf mir mal bitte kurz auf die Sprünge? Welcher Teil ist denn bei der Syntax fehlerhaft bzw. unvollständig?

      VIele Grüße,
      -sirtpx

      Kommentar


        #4
        Du must deinen Zähler ja irgendwo speichern und dazu bietet sich die Persistence an.
        Die Berechnung deiner Werte wäre futsch wenn dein System neu startet und die Lampe noch an ist.
        Ich selbst nutze für Charts usw. rrd4j. Das jetzt hier zu erklären sprengt aber den Rahmen, hier musst du dich selbst mal belesen, kannst aber gerne wieder fragen.
        Der Zähler muss dann als Number in die Items und in der Configuration in der rrd4j.persist angelegt werden.


        Die Syntax für einen Timer ist z.b (eckige Klammern beachten)
        Code:
        createTimer(now.plusSeconds(10)) [|
                    {              
                            sendCommand(Licht1,OFF)    
                            sendCommand(Licht2,OFF)              
                    }
                    ]
        Schau dir erstmal die Persistence an, speichere z.b. Temperaturen und dann kannst du mit dem Zähler weiter machen.
        Meine Meinung ;-)
        Holger

        Kommentar


          #5
          Hallo,

          ich habe meine Werte in einer mysql Datenbank Abspeichern lassen. In der mysql.persist steht z.B.
          Code:
          WOHNZIMMER_HUI_an : strategy = everyChange
          Damit ist es möglich die Werte des Schalters, also On und Off in der Datenbank mit einem Timestamp zu erfassen. Mit einer Abfrage kannst du nun die Zeit errechnen. Die Abfrage könnte so aussehen

          HTML-Code:
          select Month(Time) as Monat, Year(Time) as Jahr, Sum((TIMESTAMPDIFF(minute, Time, OffTime))) as an
          FROM
          (
          SELECT Time, Value
          ,(SELECT Time FROM `Item22` as b WHERE b.Time > a.Time AND b.Value="OFF" ORDER BY Time LIMIT 1) as OffTime
          
          FROM `Item22`  as a
          WHERE Value ="ON"
          
          )
          
           as Blupp
           GROUP BY Month(Time), Year(Time)
          Allerdings habe ich noch keine Idee wie ich diesen Wert in OpenHab anzeigen lassen kann. Ich versuche es gerade über json allerdings habe ich da noch ein kleines Problem (siehe auch diesen Link: https://knx-user-forum.de/forum/supp...lesen-von-json)

          Gruß
          Torsten

          Kommentar


            #6
            Hallo zusammen,

            vielen Dank für die zahlreichen Tipps.

            Ich würde mein Szenario allerdings ohne die Anbindung einer Persistenz lösen wollen. Oder ist das so wie ich mir das vorgestellt habe gar nicht möglich?

            (mir ist schon klar, dass die persistente Ablage beim Systemneustart Vorteile hat)

            Viele Grüße,
            sirtpx

            Kommentar


              #7
              Früher sahen bei mir die Regeln für den Betriebsstundenzähler wie folgt aus, als Beispiel hab ich jetzt nur ein Item herausgegriffen:

              Items:
              Code:
              Number Licht_Gaeste_Decke_Zaehler    "Gäste Decke [%d]"    (gOperatingHours)  
              String Licht_Gaeste_Decke_Betriebsstunden    "Gäste Decke [%s]"    (gOperatingHoursFormatted)

              Regeln:
              Code:
              import org.openhab.core.library.types.*
              import org.openhab.model.script.actions.*
              import java.util.Calendar
              import java.util.Date
              import java.util.TimeZone
              
              
              var Calendar Licht_Gaeste_Decke_OnTime   
              
              
              rule "Initialisiere Betriebsstundenzaehler"
              when
                  System started
              then
                  logInfo("operating hours rules", "Initialized Counters")
                  
                  gOperatingHours?.members.forEach(counter|
                         if (counter.state == Uninitialized) {counter.postUpdate(0)
                         //logInfo("operating hours rules", "Initialized (Uninitialized): " + counter.toString())
                         }
                  )
                  
                   
                  Licht_Gaeste_Decke_OnTime = java::util::Calendar::getInstance(TimeZone::getTimeZone("Europe/Berlin"))   
              
              end
              
              
              rule "Aktualisiere Betriebsstunden Licht_Gaeste_Decke_Schalten"
              when
                  Item Licht_Gaeste_Decke_Schalten changed
              then
                   if (Licht_Gaeste_Decke_Schalten.state == ON) {
                      Licht_Gaeste_Decke_OnTime = java::util::Calendar::getInstance(TimeZone::getTimeZone("Europe/Berlin"))  
                    } else if (Licht_Gaeste_Decke_Schalten.state == OFF && previousState == ON && Licht_Gaeste_Decke_OnTime != null) {
                      var Calendar CurTime       = java::util::Calendar::getInstance(TimeZone::getTimeZone("Europe/Berlin")) 
                      var Number Diff            =  (CurTime.getTimeInMillis() - Licht_Gaeste_Decke_OnTime.getTimeInMillis()) / 1000
                      var Number Prev            = 0
              
                      if (Licht_Gaeste_Decke_Zaehler.state instanceof DecimalType) {
                          Prev = Licht_Gaeste_Decke_Zaehler.state as DecimalType
                      }
                      var Number Zaehler = Prev + Diff
              
                      Licht_Gaeste_Decke_Zaehler.postUpdate(Zaehler)
                      
                     
                      //Aufbereitung zur Anzeige
                      var Number h = (Zaehler/3600).intValue
                      var Number m = ((Zaehler-h*3600)/60).intValue
                         var Number s = ((Zaehler-h*3600 - m*60)).intValue
                      var String TimeString = h + ":" 
                      if (m < 10) {TimeString = TimeString + "0" + m.toString + ":"} else {TimeString = TimeString + m.toString + ":"}
                      if (s < 10) {TimeString = TimeString + "0" + s.toString}       else {TimeString = TimeString + s.toString} 
                         
                      Licht_Gaeste_Decke_Betriebsstunden.postUpdate(TimeString)
                      
                      logInfo("operating hours rules", "Updated operating counter for Licht_Gaeste_Decke_Schalten: " + Zaehler + " Prev: " + Prev)
                  }
              end
              Ohne einen Persistence Service ist das natürlich nicht wirklich sinnvoll, da sollte man mindestens Licht_Gaeste_Decke_Zaehler und besser auch Licht_Gaeste_Decke_Betriebsstunden aufnehmen. Mit dem db4o brauchst Du nicht mal einen separaten Datenbankserver.


              Mein aktueller Ansatz ist, die Werte aus der MySQL Datenbank zu berechnen in die die Änderungen der Items sowieso geschrieben werden. Dazu läuft regelmäßig ein Python Skript, was die Datenbank ausliest und die Werte per REST an openHAB übermittelt:

              Hier der aktuelle Zwischenstand, der aber noch in Arbeit ist, es fehlt z.B. der REST Aufruf und eine vernünftige Fehlerbehandlung. Das Skript erwartet das Item als Parameter:


              Code:
              #!/opt/local/bin/python3.4
              
              
              import pymysql
              import argparse
              import datetime
              
              
              parser = argparse.ArgumentParser(description='Get operating hours')
              parser.add_argument('items', metavar='I', type=str, nargs='+', help='opeHAB item name')
              
              args = parser.parse_args()
              #print(args.items)
              
              conn = pymysql.connect(host='localhost', port=3306, user='user', passwd='passwd', db='openhab')
                 
              cur = conn.cursor()
              
              # Get Item Id from items table, item values are stored in tables named ItemItemId (e.g. Item4711)
              cur.execute("select ItemId from Items WHERE ItemName='" + args.items[0] + "'")
              
              ItemTable=cur.fetchone()
              print(ItemTable)
              
              
              # Get all entries for the specified item
              cur.execute("select * from Item" + str(ItemTable[0]))
              
              rows=cur.fetchall()
              
              row=0
              OperatingTime=datetime.timedelta(seconds=0)
              
              # Find ON event
              while row < len(rows):
                  if (rows[row][1] == "ON") or (rows[row][1] == 100):
                      OnTime=rows[row][0]
                      print("Found ON: ", row, " Time: ", rows[row][0], " Value: ", rows[row][1])
                          
                      # Find OFF event if previous ON event was found
                      while row < len(rows):
                          if     (rows[row][1] == "OFF") or (rows[row][1] == 0):
                              OffTime=rows[row][0]   
                              OperatingTime = OperatingTime + (OffTime-OnTime)
                              print("Found OFF: ", row, " Time: ", rows[row][0], " Value: ", rows[row][1], " Operating: ", OperatingTime)
                              break # Searching OFF loop
                          row = row + 1
                  row = row + 1
              
              cur.close()
              conn.close()

              Kommentar


                #8
                Hallo zusammen, das mit dem Betriebsstundenzähler interessiert mich ebenfalls. Ich lasse viele meiner Schalter auch in eine MySQL DB schreiben und habe mir schon überlegt wie ich den Zeit zwischen "ON" und "OFF" berechnen kann. Wäre cool wenn du deine Vorgehensweise noch etwas detailierter erklären könntest Jockel. Kann man den Code nicht in den Openhab Scripts oder Rules ausführen?

                Kommentar


                  #9
                  Ich habe mal einen Pull Request gestellt: https://github.com/openhab/openhab/pull/2879
                  Der wird aber irgendwie nicht übernommen. Neu darin ist eine Funktion: accurateAverageSince. Damit berechne ich auch die Einschaltdauer für einen bestimmten Zeitraum.

                  Kommentar


                    #10
                    Wäre cool wenn du deine Vorgehensweise noch etwas detailierter erklären könntest Jockel.
                    Viel zu erklären ist da eigentlich nicht. Das Skript sucht such aus der MySQL Datenbank die zu dem jeweiligen Item gehörige Tabelle (Item als Parameter), sucht dort das erste auftreten von ON bzw. 100 für Dimmer (das ist noch ein Fehler, müsste !=0 heißen). Dann das nächste off, die Zeitstempel stehen mit in der Tabelle, daraus wird die Zeit berechnet und dann wiederholt bis zum Ende der Tabelle. Es fehlt halt noch die Weitergabe per REST, muss mal schaue wie das in Python implementiert wird. Da werde ich wahrscheinlich zum einen den Zahlenwert für die Charts, zum anderen auch einen formatierten String zur Anzeige übergeben.

                    Der wird aber irgendwie nicht übernommen. Neu darin ist eine Funktion: accurateAverageSince. Damit berechne ich auch die Einschaltdauer für einen bestimmten Zeitraum.
                    Den Ansatz das mit durch den Persistence Service berechnen zu lassen finde ich deutlich eleganter!

                    Kann man den Code nicht in den Openhab Scripts oder Rules ausführen?
                    Das sollte gehen, man kann ja externe Skripte aufrufen.

                    Kommentar

                    Lädt...
                    X