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:
Type mismatch: cannot convert from int to Long
Hier habe ich dann
verwendet.
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
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.
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'
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;