Seite 1 von 2

Betriebsstundenzähler auf Number:Time umstellen

Verfasst: 4. Okt 2023 11:33
von TomW80
Hallo,

Ich erfasse die Betriebsstunden meiner Zirkulationspumpe aktuell so:

Item

Code: Alles auswählen

Number          Zirkulationspumpe_BSZ     "Betriebsstunden Zirkulationspumpe [%.1f h]"
rule

Code: Alles auswählen

rule "Betriebsstunden bestimmen"
when
    Item Zirkulationspumpe changed
then
    if(previousState == NULL) {
        logInfo("duration","Alter Wert war NULL, Abbruch!")
        return;
    }
    if(Zirkulationspumpe.state == ON) {
        nStart = now.toInstant().toEpochMilli()
        logInfo("duration","Zirkulationspumpe wurde eingeschaltet. Startwert {}",nStart)
    }
    if(Zirkulationspumpe.state == OFF) {
        var Number nDiff = now.toInstant().toEpochMilli() - nStart
        logInfo("duration","Zirkulationspumpe wurde ausgeschaltet. Differenz {}",nDiff)
        if (Zirkulationspumpe_BSZ.state==NULL)
           Zirkulationspumpe_BSZ.postUpdate(nDiff/3600000)
        else
           Zirkulationspumpe_BSZ.postUpdate((Zirkulationspumpe_BSZ.state as Number) + nDiff/3600000)
    }
end
Wie kann ich das Item " Zirkulationspumpe_BSZ" auf Number:Time umstellen? Es reicht ja sicher nicht die Itemkonfiguration anzupassen.
Aber wie muss ich meine Rule anpassen?

Gruß Tom

Re: Betriebsstundenzähler auf Number:Time umstellen

Verfasst: 4. Okt 2023 16:19
von nw378
Das sollte so klappen. Unter OH 4 sieht mein Betriebsstundenzähler so aus:

Code: Alles auswählen

 / Triggers:
// - When Sonne changed

// context: knx-3

    if (Sonne.state == ON) dtStart = now.toEpochSecond                     
    else if (Sonne.state==OFF) {  
      var Integer iSum = 0                                                
      if (Sonnen_std.state instanceof Number) iSum = (Sonnen_std.state as Number).intValue                         
      else logWarn("Sonenn_std", "wird initialisiert!")                     
      iSum = iSum + ((now.toEpochSecond - dtStart)).intValue                 
      Sonnen_std.postUpdate(iSum)  }
Das item ist Number:Time und wird in Sekunden gespeichert.

Mit [%.1f h] gibst du dann die Zeit in Stunden an.

Allerdings würdest du dann einen Sprung in deiner Datenbank haben, da du zuvor Stunden gespeichert hast.

Versuchsweise kannst du mal {%unit%=h} (oder so ähnlich) hinter dem Item eingeben.

Re: Betriebsstundenzähler auf Number:Time umstellen

Verfasst: 4. Okt 2023 16:19
von nw378
.

Re: Betriebsstundenzähler auf Number:Time umstellen

Verfasst: 4. Okt 2023 17:27
von udo1toni
Als Textdefinition so:

Code: Alles auswählen

Number:Time Zirkulationspumpe_BSZ "Betriebsstunden Zirkulationspumpe" {unit="h", stateDescription=""[pattern="%.1f h"]}
unit="h" sorgt dafür, dass das Item den Wert als Stunden speichert, stateDescription=""[pattern="%.1f h"] sorgt dafür, dass der Wert in Stunden und deren Bruchteilen angezeigt wird.

In der Rule musst Du allerdings als Wert dann auch QuantityType verwenden, also z.B. so:

Code: Alles auswählen

var Long nStart = 0

rule "Betriebsstunden bestimmen"
when
    Item Zirkulationspumpe changed
then
    if(previousState == NULL) {
        logInfo("duration","Alter Wert war NULL, Abbruch!")
        return;
    }
    val qAlt = if(Zirkulationspumpe_BSZ.state instanceof Number) (Zirkulationspumpe_BSZ.state as Number) else 0 | h

    if(Zirkulationspumpe.state == ON) {
        nStart = now.toInstant().toEpochMilli()
        logInfo("duration","Zirkulationspumpe wurde eingeschaltet. Startwert {}",nStart)
    } else {
        val nDiff = now.toInstant().toEpochMilli() - nStart
        val nQuan = (nDiff / 3600000) | h
        logInfo("duration","Zirkulationspumpe wurde ausgeschaltet. Differenz {}",nDiff)
        Zirkulationspumpe_BSZ.postUpdate(qAlt + nQuan)
    }
end
Die Prüfung auf Number ist etwas schlampig :) aber QuantityType<Time> ist eine Teilmenge von Number, das reicht also gewöhnlich vollkommen aus.

Re: Betriebsstundenzähler auf Number:Time umstellen

Verfasst: 6. Okt 2023 20:05
von TomW80
udo1toni hat geschrieben: 4. Okt 2023 17:27 Als Textdefinition so:

Code: Alles auswählen

NumberTime Zirkulationspumpe_BSZ "Betriebsstunden Zirkulationspumpe" {unit="h", stateDescription=""[pattern="%.1f h"]}
Es muss Number:Time heißen ;)

Bei der Rule bekomme ich folgende Fehler angezeigt:
udo1toni hat geschrieben: 4. Okt 2023 17:27

Code: Alles auswählen

var Long nStart = 0
Type mismatch: cannot convert from int to Long

Hier habe ich dann

Code: Alles auswählen

var Long nStart = null
verwendet.
udo1toni hat geschrieben: 4. Okt 2023 17:27

Code: Alles auswählen

        val nQuan = (nDiff / 3600000) | h
no viable alternative at input '|'
The method or field h is undefined

Re: Betriebsstundenzähler auf Number:Time umstellen

Verfasst: 6. Okt 2023 20:28
von udo1toni
TomW80 hat geschrieben: 6. Okt 2023 20:05Es muss Number:Time heißen ;)
Korrekt. Ich wollte Dich testen... (Spaß, einfach ein Tippfehler, den ich übersehen habe... hab's oben verbessert)
TomW80 hat geschrieben: 6. Okt 2023 20:05
Type mismatch: cannot convert from int to Long
Hier habe ich dann

Code: Alles auswählen

var Long nStart = null
verwendet.
Ja, das kommt davon, wenn man zu faul ist, noch mal nachzuschauen... für die globale Definition ist null ohnehin die bessere Option :), steht auhc bei mir so drin...
TomW80 hat geschrieben: 6. Okt 2023 20:05no viable alternative at input '|'
Hmm... Eventuell stören die Leerzeichen, und/oder das h muss in Anführungszeichen stehen.

Notfalls könntest Du es auch so probieren:

Code: Alles auswählen

        val nQuan = new QuantityType((nDiff / 3600000).toString + " h")
hier ist dann das Leerzeichen im String vor dem h wichtig :) Units of Measurement kann etwas mit Ausprobieren verbunden sein...

Re: Betriebsstundenzähler auf Number:Time umstellen

Verfasst: 7. Okt 2023 17:51
von TomW80
udo1toni hat geschrieben: 6. Okt 2023 20:28 Hmm... Eventuell stören die Leerzeichen, und/oder das h muss in Anführungszeichen stehen.
hatte ich schon probiert, funktioniert auch nicht.
Da stört die Klammer, denn so beschwert sich VSC nicht.

Code: Alles auswählen

val nQuan = nDiff / 3600000 | h
Aber ob das so gut geht?
Ich teste mal.
udo1toni hat geschrieben: 6. Okt 2023 20:28 Notfalls könntest Du es auch so probieren:

Code: Alles auswählen

        val nQuan = new QuantityType((nDiff / 3600000).toString + " h")
hier ist dann das Leerzeichen im String vor dem h wichtig :) Units of Measurement kann etwas mit Ausprobieren verbunden sein...
Da erhalte ich den Fehler:

Bounds mismatch: The type argument <Quantity<?>> is not a valid substitute for the bounded type parameter <T extends Quantity<T>> of the constructor QuantityType<T>(String)

Kann das an openhab 3.4.5 liegen?

Re: Betriebsstundenzähler auf Number:Time umstellen

Verfasst: 7. Okt 2023 22:35
von udo1toni
TomW80 hat geschrieben: 7. Okt 2023 17:51 Kann das an openhab 3.4.5 liegen?
Sollte es nicht...
Probiere bitte noch dies:

Code: Alles auswählen

        val nQuan = new QuantityType<Time>((nDiff / 3600000).toString + " h")

Re: Betriebsstundenzähler auf Number:Time umstellen

Verfasst: 8. Okt 2023 19:54
von TomW80
udo1toni hat geschrieben: 7. Okt 2023 22:35
TomW80 hat geschrieben: 7. Okt 2023 17:51 Kann das an openhab 3.4.5 liegen?
Sollte es nicht...
Probiere bitte noch dies:

Code: Alles auswählen

        val nQuan = new QuantityType<Time>((nDiff / 3600000).toString + " h")
Kommt auch der Fehler:

Bounds mismatch: The type argument <Quantity<?>> is not a valid substitute for the bounded type parameter <T extends Quantity<T>> of the constructor QuantityType<T>(String)


und

no viable alternative at input 'Time'

Code: Alles auswählen

val nQuan = nDiff / 3600000 | h
Scheint auch nicht zu funktionieren, denn bei einer Laufzeit von 5 Min schreibt mir openhab:
Item 'Zirkulationspumpe_BSZ_Test2' changed from 0.08335842731481481 s to 0.0833816799382716 s
Man beachte auch das s. 5 Minuten sind ja eigentlich 0,08 h.

Re: Betriebsstundenzähler auf Number:Time umstellen

Verfasst: 13. Okt 2023 12:10
von nw378
QuantityType<Time> funktioniert nicht. QuantityType<?> hingegen schon.
Ich habe meinen (Sonnen-) Betriebsstundenzähler nun auch auf Stunden umgestellt.

So funktioniert's; Du musst nur Deine Items anpassen:

.items:

Code: Alles auswählen

Number:Time Sonnen_std  "Sonnenstunden"  {unit="h", stateDescription=""[pattern="%.3f h"]} 
.rules:

Code: Alles auswählen

var long dtStart = now.toEpochSecond  

rule "Sonnenstunden"
  when Item Sonne changed  then                                               
    if (Sonne.state == ON) dtStart = now.toEpochSecond                     
    else if (Sonne.state == OFF) {  
      if(previousState == NULL) return;
      var double dSum = (Sonnen_std.state as QuantityType<?>).doubleValue                                              
      dSum = dSum + ((now.toEpochSecond - dtStart).doubleValue / 3600.0)
      Sonnen_std.postUpdate(dSum)  }    
end

Ergebnis im Log-file:

[code]2023-10-13 12:05:56.954 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Sonnen_std' changed from 0.24055555555555555 h to 0.26722222129503886 h
EDIT:
1. von float auf double umgestellt; zuvor hatte mit VSC eine Fehlermeldung geliefert.
2. Ich habe noch einen Abbruch hinzugefügt, falls der triggernde Schalter zuvor nicht initialisiert war:
if(previousState == NULL) return;