Awattar
- udo1toni
- Beiträge: 13854
- Registriert: 11. Apr 2018 18:05
- Wohnort: Darmstadt
Re: Awattar
Das Update Interval in der http.cfg bezieht sich auf das Füllen des Caches. Das heißt, wenn man hier eine Stunde einträgt, fragt openHAB einmal stündlich die Website ab und speichert die Daten im Cache. Die erste Abfrage geschieht, sobald das http Binding gestartet wird, also nicht etwa zur vollen Stunde. Entsprechend müsste man, damit die Daten auch "aktuell" sind, openHAB möglichst immer zur vollen Stunde neu starten.
Das Update in der Sitemap bezieht sich aber auf die Darstellung des Items. Es ist durchaus sinnvoll, hier eine Minute einzutragen, das hat keinen Einfluss auf die Anzahl der Abfragen bei Awattar.
Alle Rules gehören in eine (oder auch mehrere) Datei(en) *.rules unterhalb openhab2/rules/
Die Items sollten quasi unmittelbar gültige Werte zeigen, ansonsten hast Du irgendwo einen Fehler drin.
Schau mal in openhab.log, ob dort irgendwelche Fehler angezeigt werden.
Laut Dokumentation wird kein Token gebraucht, und es dürfen bis 60 Abfragen pro Minute gestellt werden (wobei das ja eher witzlos ist) https://www.awattar.de/services/api
Das Update in der Sitemap bezieht sich aber auf die Darstellung des Items. Es ist durchaus sinnvoll, hier eine Minute einzutragen, das hat keinen Einfluss auf die Anzahl der Abfragen bei Awattar.
Alle Rules gehören in eine (oder auch mehrere) Datei(en) *.rules unterhalb openhab2/rules/
Die Items sollten quasi unmittelbar gültige Werte zeigen, ansonsten hast Du irgendwo einen Fehler drin.
Schau mal in openhab.log, ob dort irgendwelche Fehler angezeigt werden.
Laut Dokumentation wird kein Token gebraucht, und es dürfen bis 60 Abfragen pro Minute gestellt werden (wobei das ja eher witzlos ist) https://www.awattar.de/services/api
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet
-
- Beiträge: 9
- Registriert: 21. Sep 2019 22:02
Re: Awattar
meinen http.cfg sieht so aus:
Der Zeitintervall sollte ca 25 min sein. Was aber bedeutet, das mein "Awattar_Preis1" nicht immer den aktuellen Preis anzeigt.
meine Awattar.item:
Zum Umrechnen der Zeit noch die awattarzeit.rules:
Zum Anzeigen hab ich mir eine Awattar.sitemap
Und zum grafisch darstellen experimeniere ich gerade mit rrd4j.persist (muss als Addon extra installiert werden)
Soweit bin ich schon super zufrieden.
Ich bin mir nicht sicher, ob es notwenig ist einen "aktuellen Preis" auszurechnen. Warscheinlich reicht es aus, den Abfrageintervall sehr kurz zu machen und denn den "Awattar_Preis1" zu verwenden. Elegant wäre ein "aktueller Preis" aber schon.
Ich hoffe die Infos machen es etwas einfacher.
@udo1toni: Deine "Awattar.rules" werde ich gerne ausprobieren und damit weiterentwickeln. Mal sehe wann ich dazu komme....
Code: Alles auswählen
awattar.url=https://api.awattar.de/v1/marketdata
awattar.updateInterval=1500000
meine Awattar.item:
Code: Alles auswählen
// awattar
Group Awattar "Strompreise " <Awattar>
Group AwattarZeitIn
Group AwattarZeitOut
Number Awattar_Preis1 "Preis1 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[0].marketprice)]"}
Number Awattar_Preis2 "Preis2 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[1].marketprice)]"}
Number Awattar_Preis3 "Preis3 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[2].marketprice)]"}
Number Awattar_Preis4 "Preis4 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[3].marketprice)]"}
Number Awattar_Preis5 "Preis5 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[4].marketprice)]"}
Number Awattar_Preis6 "Preis6 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[5].marketprice)]"}
Number Awattar_Preis7 "Preis7 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[6].marketprice)]"}
Number Awattar_Preis8 "Preis8 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[7].marketprice)]"}
Number Awattar_Preis9 "Preis9 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[8].marketprice)]"}
Number Awattar_Preis10 "Preis10 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[9].marketprice)]"}
Number Awattar_Preis11 "Preis11 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[10].marketprice)]"}
Number Awattar_Preis12 "Preis12 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[11].marketprice)]"}
Number Awattar_Preis13 "Preis13 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[12].marketprice)]"}
Number Awattar_Preis14 "Preis14 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[13].marketprice)]"}
Number Awattar_Preis15 "Preis15 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[14].marketprice)]"}
Number Awattar_Preis16 "Preis16 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[15].marketprice)]"}
Number Awattar_Preis17 "Preis17 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[16].marketprice)]"}
Number Awattar_Preis18 "Preis18 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[17].marketprice)]"}
Number Awattar_Preis19 "Preis19 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[18].marketprice)]"}
Number Awattar_Preis20 "Preis20 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[19].marketprice)]"}
Number Awattar_Preis21 "Preis21 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[20].marketprice)]"}
Number Awattar_Preis22 "Preis22 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[21].marketprice)]"}
Number Awattar_Preis23 "Preis23 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[22].marketprice)]"}
Number Awattar_Preis24 "Preis24 [%.2f €/MWh]" (Awattar) {http="<[awattar:30000:JSONPATH($.data[23].marketprice)]"}
Number AwattarIn_Zeit1 "Zeit1" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[0].start_timestamp)]"}
Number AwattarIn_Zeit2 "Zeit2" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[1].start_timestamp)]"}
Number AwattarIn_Zeit3 "Zeit3" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[2].start_timestamp)]"}
Number AwattarIn_Zeit4 "Zeit4" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[3].start_timestamp)]"}
Number AwattarIn_Zeit5 "Zeit5" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[4].start_timestamp)]"}
Number AwattarIn_Zeit6 "Zeit6" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[5].start_timestamp)]"}
Number AwattarIn_Zeit7 "Zeit7" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[6].start_timestamp)]"}
Number AwattarIn_Zeit8 "Zeit8" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[7].start_timestamp)]"}
Number AwattarIn_Zeit9 "Zeit9" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[8].start_timestamp)]"}
Number AwattarIn_Zeit10 "Zeit10" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[9].start_timestamp)]"}
Number AwattarIn_Zeit11 "Zeit11" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[10].start_timestamp)]"}
Number AwattarIn_Zeit12 "Zeit12" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[11].start_timestamp)]"}
Number AwattarIn_Zeit13 "Zeit13" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[12].start_timestamp)]"}
Number AwattarIn_Zeit14 "Zeit14" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[13].start_timestamp)]"}
Number AwattarIn_Zeit15 "Zeit15" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[14].start_timestamp)]"}
Number AwattarIn_Zeit16 "Zeit16" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[15].start_timestamp)]"}
Number AwattarIn_Zeit17 "Zeit17" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[16].start_timestamp)]"}
Number AwattarIn_Zeit18 "Zeit18" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[17].start_timestamp)]"}
Number AwattarIn_Zeit19 "Zeit19" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[18].start_timestamp)]"}
Number AwattarIn_Zeit20 "Zeit20" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[19].start_timestamp)]"}
Number AwattarIn_Zeit21 "Zeit21" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[20].start_timestamp)]"}
Number AwattarIn_Zeit22 "Zeit22" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[21].start_timestamp)]"}
Number AwattarIn_Zeit23 "Zeit23" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[22].start_timestamp)]"}
Number AwattarIn_Zeit24 "Zeit24" <time> (AwattarZeitIn) {http="<[awattar:30000:JSONPATH($.data[23].start_timestamp)]"}
DateTime Awattar_Zeit1 "Zeit1 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit2 "Zeit2 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit3 "Zeit3 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit4 "Zeit4 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit5 "Zeit5 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit6 "Zeit6 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit7 "Zeit7 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit8 "Zeit8 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit9 "Zeit9 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit10 "Zeit10 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit11 "Zeit11 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit12 "Zeit12 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit13 "Zeit13 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit14 "Zeit14 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit15 "Zeit15 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit16 "Zeit16 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit17 "Zeit17 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit18 "Zeit18 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit19 "Zeit19 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit20 "Zeit20 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit21 "Zeit21 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit22 "Zeit22 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit23 "Zeit23 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
DateTime Awattar_Zeit24 "Zeit24 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
Code: Alles auswählen
rule "Zeit rechnen"
when
Member of AwattarZeitIn changed
then
if(triggeringItem.state instanceof Number) {
AwattarZeitOut.members.filter[m |
m.name.contains(triggeringItem.name.split("_").get(1))
].head.postUpdate((new DateTime((triggeringItem.state as Number).longValue)).toString)
}
end
Code: Alles auswählen
sitemap Awattar label="Awattar" {
Frame label="Strompreise" {
Text item=Awattar_Preis1
Text item=Awattar_Zeit1
Text item=Awattar_Preis2
Text item=Awattar_Zeit2
Text item=Awattar_Preis3
Text item=Awattar_Zeit3
Text item=Awattar_Preis4
Text item=Awattar_Zeit4
Text item=Awattar_Preis5
Text item=Awattar_Zeit5
Text item=Awattar_Preis6
Text item=Awattar_Zeit6
Text item=Awattar_Preis7
Text item=Awattar_Zeit7
Text item=Awattar_Preis8
Text item=Awattar_Zeit8
Text item=Awattar_Preis9
Text item=Awattar_Zeit9
Text item=Awattar_Preis10
Text item=Awattar_Zeit10
Text item=Awattar_Preis11
Text item=Awattar_Zeit11
Text item=Awattar_Preis12
Text item=Awattar_Zeit12
Text item=Awattar_Preis13
Text item=Awattar_Zeit13
Text item=Awattar_Preis14
Text item=Awattar_Zeit14
Text item=Awattar_Preis15
Text item=Awattar_Zeit15
Text item=Awattar_Preis16
Text item=Awattar_Zeit16
Text item=Awattar_Preis17
Text item=Awattar_Zeit17
Text item=Awattar_Preis18
Text item=Awattar_Zeit18
Text item=Awattar_Preis19
Text item=Awattar_Zeit19
Text item=Awattar_Preis20
Text item=Awattar_Zeit20
Text item=Awattar_Preis21
Text item=Awattar_Zeit21
Text item=Awattar_Preis22
Text item=Awattar_Zeit22
Text item=Awattar_Preis23
Text item=Awattar_Zeit23
Text item=Awattar_Preis24
Text item=Awattar_Zeit24
Chart item=Awattar_Preis24 label="Strompreis [%s €/MWH]" icon="Price" period=D
Chart item=Awattar_Preis23 label="Strompreis [%s €/MWH]" icon="Price" period=D
Chart item=Awattar_Preis13 label="Strompreis [%s €/MWH]" icon="Price" period=12h
}
}
Code: Alles auswählen
Strategies {
everyMinute : "0 * * * * ?"
everyHour : "0 0 * * * ?"
everyDay : "0 0 0 * * ?"
default = everyChange
}
Items
{
Awattar_Preis24 : strategy = everyMinute
Awattar_Preis23 : strategy = everyMinute
Awattar_Preis13 : strategy = everyMinute
}
Soweit bin ich schon super zufrieden.
Ich bin mir nicht sicher, ob es notwenig ist einen "aktuellen Preis" auszurechnen. Warscheinlich reicht es aus, den Abfrageintervall sehr kurz zu machen und denn den "Awattar_Preis1" zu verwenden. Elegant wäre ein "aktueller Preis" aber schon.
Ich hoffe die Infos machen es etwas einfacher.
@udo1toni: Deine "Awattar.rules" werde ich gerne ausprobieren und damit weiterentwickeln. Mal sehe wann ich dazu komme....
-
- Beiträge: 7
- Registriert: 29. Sep 2019 15:29
Re: Awattar
Ach ja, ich vergaß: Ich wohne in Österreich, hier gilt Token nötig und 100 Abfragen/Tag => https://www.awattar.com/services/api/udo1toni hat geschrieben: ↑30. Sep 2019 16:30 Laut Dokumentation wird kein Token gebraucht, und es dürfen bis 60 Abfragen pro Minute gestellt werden (wobei das ja eher witzlos ist) https://www.awattar.de/services/api
So jetzt hab ich's aber. Für alle die Awattar in Österreich nutzen wollen hier die Anleitung wie es geht:
http.cfg:
Code: Alles auswählen
awattar.url=https://api.awattar.com/v1/marketdata{Authorization=Basic TokenXYZ}
awattar.updateInterval=1500000
Andere Frage: Wie schafft man es, daß die Preisabfrage jeden Tag immer zur selben Uhrzeit, sagen wir mal 18:00, stattfindet?
lg Jürgen
- udo1toni
- Beiträge: 13854
- Registriert: 11. Apr 2018 18:05
- Wohnort: Darmstadt
Re: Awattar
Abfrage um eine bestimmte Uhrzeit wäre eine Sache, die man mit einer Rule erschlägt. Das heißt, Du legst eine Rule an, in der Du direkt die http-Abfrage mittels sendHttpGetRequest(String url) schickst. Das Ergebnis speicherst Du dann in einer Variablen, die Du dann mittels JSONPATH auf die verschiedneen Items aufteilst. Die Items sind dann alle unbound, also ohne Channel.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet
-
- Beiträge: 9
- Registriert: 21. Sep 2019 22:02
Re: Awattar
Mein Ansatz ist gerade ein anderer. Ich habe mir ein Item erstellt, dass den aktuellen Strompreis aus ausweisen soll.
Jetzt vergleiche ich nur die Zeitangaben aus meiner Abfrage mit der aktuelle Zeit und Übergebe den Preis der entsprechenden Stunde in den aktuellen Wert.
Vielleicht war ich etwas umständlich aber es funktioniert:
1. Item mit der aktuellen Zeit erstellen:
Zeit.item
2. Item mit der aktuellen Zeit Zeit.rules
3. awattaraktuell.rules
Meine Abfrage habe ich gerade auf 2 Stunden umgestellt.
Code: Alles auswählen
Number Awattar_aktuell "Preis aktuell [%.2f €/MWh]" (Awattar)
Vielleicht war ich etwas umständlich aber es funktioniert:
1. Item mit der aktuellen Zeit erstellen:
Zeit.item
Code: Alles auswählen
// aktuelle Zeit
DateTime Zeitaktuell "Zeitaktuell [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time>
Code: Alles auswählen
//===============================================================================
rule "aktuelle Zeit"
when
Time cron "0/1 * * 1/1 * ? *"
then
Zeitaktuell.sendCommand(new DateTimeType)
end
3. awattaraktuell.rules
Code: Alles auswählen
rule "Preisaktuell"
when
Time cron "0/1 * * 1/1 * ? *"
then
if((Awattar_Zeit1.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli
<
(Zeitaktuell.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli
&&
(Awattar_Zeit2.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli
>
(Zeitaktuell.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli)
{
Awattar_aktuell.sendCommand(Awattar_Preis1.state as Number)
Zeitpreisaktuell.sendCommand(new DateTimeType)
}
if((Awattar_Zeit2.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli
<
(Zeitaktuell.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli
&&
(Awattar_Zeit3.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli
>
(Zeitaktuell.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli)
{
Awattar_aktuell.sendCommand(Awattar_Preis2.state as Number)
Zeitpreisaktuell.sendCommand(new DateTimeType)
}
if((Awattar_Zeit3.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli
<
(Zeitaktuell.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli
&&
(Awattar_Zeit4.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli
>
(Zeitaktuell.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli)
{
Awattar_aktuell.sendCommand(Awattar_Preis2.state as Number)
Zeitpreisaktuell.sendCommand(new DateTimeType)
}
end
- udo1toni
- Beiträge: 13854
- Registriert: 11. Apr 2018 18:05
- Wohnort: Darmstadt
Re: Awattar
Diese Zeile:
bewirkt das gleiche wie diese Zeile:
womit beide Rules einmal pro Sekunde ausgeführt werden. Der letzte Stern steht für das Jahr, die Angabe ist optional, kann also entfallen.
Es kann sein, dass die Rule mit Deinem Trigger zwischen 0 Uhr und 1 Uhr gar nicht ausgeführt wird, da bin ich mir nicht so ganz sicher ("beginnend mit 1 Uhr").
Nicht nur ist das absoluter Overkill (der Wert ändert sich nur einmal pro Stunde), Du hast auch zwei voneinander unabhängige Rules, die beide mit dem selben Time cron Trigger ausgelöst werden.
openHAB hat default zwei Threads, die für Scheduler Events verwendet werden. Es ist also sehr wahrscheinlich, dass weitere Timer durch diese beiden Rules nachhaltig gestört werden.
Um die Zeit in einem Item zu speichern, benötigt man gar keine Rule, stattdessen greift man zum NTP Binding, welches "nebenher" auch dafür sorgt, dass die Zeit immer korrekt ist - vorausgesetzt, man hat NTP auch korrekt konfiguriert, natürlich.
new DateTimeType greift hingegen auf die Rechneruhr zurück, falls man also keinen NTP Client auf Betriebssystemebene eingerichtet hat, läuft diese Zeit abhängig von Temperatur und Rechner weg - durchaus auch mehr als eine Minute pro Tag.
Die Anzeige der Uhrzeit in der UI kann man realisieren, aber ob das sekundengenau funktioniert, wage ich zu bezweifeln, weil die UI dafür nicht ausgelegt ist.
Im Allgemeinen wird eine Auflösung von 30 Sekunden ausreichen, was man so im NTP Binding konfigurieren kann (Update des Items alle 30 Sekunden, Synchronisation mit dem Server z.B. nach 120 Aktualisierungen, also einmal pro Stunde).
Der exakte Zeitpunkt des Tarifwechsels wird vermutlich aus dem Vertrag ersichtlich sein, ich gehe jetzt mal von der vollen Stunde aus. Was dann bedeutet, dass man den aktuellen Tarif einmal stündlich umschalten muss, am besten einige Sekunden nach dem Stundenwechsel, entsprechend wäre der Time cron Ausdruck dann:
für stündlich, fünf Sekunden nach der vollen Stunde.
sendCommand() schickt ein Kommando an alle verlinkten Channel. Default wird anschließend auch ein postUpdate() auf das selbe Item ausgeführt (kann man abschalten). Sofern man den Preis nicht über ein Binding irgendwohin schickt (http, mqtt, knx... whatever), sollte ein postUpdate() ausreichen, um die Anzeige in der UI zu ändern (und man kann auch Rules darauf triggern lassen).
Die Vergleichszeilen schreien nach einer Optimierung mit Konstanten, weil bis auf zwei Werte alle Werte mindestens zweimal verwendet werden. Es trüge auch zur Lesbarkeit der Rule bei mal abgesehen von der Tatsache, dass die Rule umgehend eine null-Pointer Exception verursacht, wenn auch nur eines der Items zum Zeitpunkt der Ausführung kein gültiges Datum enthält, weil dieser Fall nicht abgefangen wird.
Zu guter Letzt ist der Vergleich des Zeitstempels ebenfalls unnötig, sofern man sicherstellt, dass die Preise tatsächlich aktuell sind, es reicht in dem Fall, die korrekte Stunde zu suchen. das geht z.B. so:
Es bietet sich dann an, gar nicht den genauen Zeitstempel zu speichern, sondern stattdessen die Stunde zu speichern oder gar immer den Preis für einen bestimmten Zeitraum im gleichen Item, dann kann man bei geschickter Namenswahl das betreffende Item direkt "errechnen". Also nicht den Preis in zwei Stunden in das Item Preis02 speichern, sondern den Preis für 2 Uhr in Preis02 speichern. alle Preise kommen in eine Gruppe gPreis. Dann reicht dies hier:
um immer den aktuellen Preis zu kopieren.
Code: Alles auswählen
Time cron "0/1 * * 1/1 * ? *"
Code: Alles auswählen
Time cron "* * * * * ?"
Es kann sein, dass die Rule mit Deinem Trigger zwischen 0 Uhr und 1 Uhr gar nicht ausgeführt wird, da bin ich mir nicht so ganz sicher ("beginnend mit 1 Uhr").
Nicht nur ist das absoluter Overkill (der Wert ändert sich nur einmal pro Stunde), Du hast auch zwei voneinander unabhängige Rules, die beide mit dem selben Time cron Trigger ausgelöst werden.
openHAB hat default zwei Threads, die für Scheduler Events verwendet werden. Es ist also sehr wahrscheinlich, dass weitere Timer durch diese beiden Rules nachhaltig gestört werden.
Um die Zeit in einem Item zu speichern, benötigt man gar keine Rule, stattdessen greift man zum NTP Binding, welches "nebenher" auch dafür sorgt, dass die Zeit immer korrekt ist - vorausgesetzt, man hat NTP auch korrekt konfiguriert, natürlich.
new DateTimeType greift hingegen auf die Rechneruhr zurück, falls man also keinen NTP Client auf Betriebssystemebene eingerichtet hat, läuft diese Zeit abhängig von Temperatur und Rechner weg - durchaus auch mehr als eine Minute pro Tag.
Die Anzeige der Uhrzeit in der UI kann man realisieren, aber ob das sekundengenau funktioniert, wage ich zu bezweifeln, weil die UI dafür nicht ausgelegt ist.
Im Allgemeinen wird eine Auflösung von 30 Sekunden ausreichen, was man so im NTP Binding konfigurieren kann (Update des Items alle 30 Sekunden, Synchronisation mit dem Server z.B. nach 120 Aktualisierungen, also einmal pro Stunde).
Der exakte Zeitpunkt des Tarifwechsels wird vermutlich aus dem Vertrag ersichtlich sein, ich gehe jetzt mal von der vollen Stunde aus. Was dann bedeutet, dass man den aktuellen Tarif einmal stündlich umschalten muss, am besten einige Sekunden nach dem Stundenwechsel, entsprechend wäre der Time cron Ausdruck dann:
Code: Alles auswählen
Time cron "5 0 0 * * ?"
sendCommand() schickt ein Kommando an alle verlinkten Channel. Default wird anschließend auch ein postUpdate() auf das selbe Item ausgeführt (kann man abschalten). Sofern man den Preis nicht über ein Binding irgendwohin schickt (http, mqtt, knx... whatever), sollte ein postUpdate() ausreichen, um die Anzeige in der UI zu ändern (und man kann auch Rules darauf triggern lassen).
Die Vergleichszeilen schreien nach einer Optimierung mit Konstanten, weil bis auf zwei Werte alle Werte mindestens zweimal verwendet werden. Es trüge auch zur Lesbarkeit der Rule bei mal abgesehen von der Tatsache, dass die Rule umgehend eine null-Pointer Exception verursacht, wenn auch nur eines der Items zum Zeitpunkt der Ausführung kein gültiges Datum enthält, weil dieser Fall nicht abgefangen wird.
Zu guter Letzt ist der Vergleich des Zeitstempels ebenfalls unnötig, sofern man sicherstellt, dass die Preise tatsächlich aktuell sind, es reicht in dem Fall, die korrekte Stunde zu suchen. das geht z.B. so:
Code: Alles auswählen
now.getHourOfDay // 0 - 23
Code: Alles auswählen
aktuellerPreis.postUpdate(gPreis.members.filter[i|i.name.endsWith(String::format("%02d",now.getHourOfDay))].head.state as Number)
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet
-
- Beiträge: 1
- Registriert: 20. Aug 2020 06:29
Re: Awattar
Hallo,
vielleicht wenn es jemand braucht, hier meine Lösung. Angepasst von den Vorschlägen aus dem Thread hier!
Ziel ist die Ermittlung von Minimum und Maximum Preisen für diverse Zeitspannen. Also wann soll Warmwasser aufgewärmt werden. Wann ist der Strompreis hoch und ich schalte die Heizung für die Wärmepumpe ab etc. etc.
1.) Laut Homepage sind die Preise für den Folgetag ab 14:00 über die API zu downloaden. Der API kann als Parameter ein Timestamp als Startzeit übergeben werden. Also in diesem Fall, 0:00 des Folgetags um die Preise für die nächsten 24 Stunden zu erhalten.
2.) Die Items sollen darauf basierend nach Uhrzeit sortiert und befüllt sein. D.h. Item Preis0=0:00-1:00, Preis1=1:00-2:00, Preis3=2:00-3:00 etc.
3.) Um den günstigsten Preis für das Aufwärmen von Warmwasser am Vormittag und am Nachmittag zu finden
4.) Ich möchte darauf basierend auch die Wärmepumpe für die Heizung in den 10 teuersten Stunden am Tag ausschalten, das programmiere ich aber erst wenn die Heizsaison beginnt
1. Items können von Tobi.wanka übernommen werden. Wichtig ist dass folgende Items noch hinzugefügt werden. Also Preis0 für Preis von 0 - 1 Uhr. Preis24 kann gelöscht werden.
2. Sitemap kann man von Tobi.wanka nehmen, bitte noch ein Item für Preis0 / Zeit0 hinzufügen
3. Rules
Wie in den Kommentaren beschrieben, die Inhalte von min_morning und min_afternoon muss selbst weiterverarbeitet werden, zB für die Steuerung der Wärmepumpe oder anderer Verbraucher. Denkbar wäre zB auch wenn der Strompreis negativ ist schaltet man halt den Fön ein
vielleicht wenn es jemand braucht, hier meine Lösung. Angepasst von den Vorschlägen aus dem Thread hier!
Ziel ist die Ermittlung von Minimum und Maximum Preisen für diverse Zeitspannen. Also wann soll Warmwasser aufgewärmt werden. Wann ist der Strompreis hoch und ich schalte die Heizung für die Wärmepumpe ab etc. etc.
1.) Laut Homepage sind die Preise für den Folgetag ab 14:00 über die API zu downloaden. Der API kann als Parameter ein Timestamp als Startzeit übergeben werden. Also in diesem Fall, 0:00 des Folgetags um die Preise für die nächsten 24 Stunden zu erhalten.
2.) Die Items sollen darauf basierend nach Uhrzeit sortiert und befüllt sein. D.h. Item Preis0=0:00-1:00, Preis1=1:00-2:00, Preis3=2:00-3:00 etc.
3.) Um den günstigsten Preis für das Aufwärmen von Warmwasser am Vormittag und am Nachmittag zu finden
4.) Ich möchte darauf basierend auch die Wärmepumpe für die Heizung in den 10 teuersten Stunden am Tag ausschalten, das programmiere ich aber erst wenn die Heizsaison beginnt
1. Items können von Tobi.wanka übernommen werden. Wichtig ist dass folgende Items noch hinzugefügt werden. Also Preis0 für Preis von 0 - 1 Uhr. Preis24 kann gelöscht werden.
Code: Alles auswählen
Number Awattar_Preis0 "Preis0 [%.2f €/MWh]" (Awattar)
...
Number AwattarIn_Zeit0 "Zeit0" <time> (AwattarZeitIn)
...
DateTime Awattar_Zeit0 "Zeit0 [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (AwattarZeitOut)
3. Rules
Code: Alles auswählen
import java.time.ZoneId
import java.time.Instant
import java.time.ZonedDateTime
import java.util.Map
rule "Awattarpreisupdate"
when
Time cron "0 30 14 ? * * *"
then
var Instant instant = Instant.now(); //timestamp / epoch herausfinden für 0:00 des aktuellen Tags und 0:00 des folgetags
var ZoneId zoneId = ZoneId.of( "Europe/Vienna" ); //Lösung ist von hier: https://stackoverflow.com/questions/10308356/how-to-obtain-the-start-time-and-end-time-of-a-day/10308430
var ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
var ZonedDateTime zdtStart = zdt.toLocalDate().atStartOfDay( zoneId );
var Number epoch_today = zdtStart.toEpochSecond() * 1000
var Number epoch_tomorrow = epoch_today + 86400000 //zum Timestamp vom aktuellen Tagesstart 24 Stunden hinzufügen um den Timestamp für die API abfrage zu erhalten
logInfo("awattar", "Start Heute: "+zdtStart+" "+epoch_today+ " Morgen: "+epoch_tomorrow)
logInfo("awattar", "Hole Daten von https://api.awattar.com/v1/marketdata?start="+epoch_tomorrow)
var Map<Number, Double> awattar_map = newHashMap //Hashmap mit Preis0 --> xx EUR, Preis1 --> xx EUR
var String data = sendHttpGetRequest("https://api.awattar.com/v1/marketdata?start="+epoch_tomorrow) //lade die Preise für den Folgetag ab 0:00 herunter, basierend auf den vorhin berechneten Timestamp
var i = 0 //das heruntergeladene Json parsen
while ( i <= 23) {
var String preis_str = transform("JSONPATH", "$.data["+i+"].marketprice", data) //parse das jeweilige Item
var String zeit_str = transform("JSONPATH", "$.data["+i+"].start_timestamp", data)
var Number preis_float = Float::parseFloat(preis_str) as Number
postUpdate("Awattar_Preis"+i,preis_str)
postUpdate("AwattarIn_Zeit"+i,zeit_str)
logInfo("awattar", "Preis"+i+"="+preis_str)
awattar_map.put(i as Number, preis_float.doubleValue()) //Füge den Preis plus Stunde der Hashmap hinzu
i=i+1
}
i = 0 //Hashmap sortieren nach Preis und das Minimum herausfinden
var Number min_morning = 0
var Number min_afternoon = 0
for (gPowerEntry : awattar_map.entrySet.sortBy[value]) {
logInfo("awattar","Key "+gPowerEntry.getKey() + " Value "+ gPowerEntry.getValue() )
if (min_morning == 0 && gPowerEntry.getKey() >=1 && gPowerEntry.getKey() <=6) {
min_morning = gPowerEntry.getKey()
}
if (min_afternoon == 0 && gPowerEntry.getKey() >=12 && gPowerEntry.getKey() <=17) {
min_afternoon = gPowerEntry.getKey()
}
i = i+1
}
logInfo("awattar","Min Morning "+min_morning + " Min Afternoon "+ min_afternoon ) // sind die Ergebnisse in Stunden, kann in Items gepostet werden
// min_morning bedeutet zB um 3:00 ist der Preis zwischen 1:00 und 6:00 am günstigsten
end
-
- Beiträge: 1
- Registriert: 9. Sep 2020 09:53
Re: Awattar
Ich habe versucht das ganze zu übernehmen, bin mir aber nicht sicher was ich hier sehe:
Nach UTC ist das der 09.09. 22 Uhr. Die API Dokumentation sagt aber nicht ob sie UTC oder Localtime erwartet. Wenn ich mir die Preise anschaue finde ich keinen Zusammenhang zu den Preisen die ich per Webseite abrufen kann:
Online sehe ich für den 10.09. folgende Werte: 0=3.45 1=3.45 2=3.48, 4=3.48, 5=3.47
Zwei Punkte die mir noch aufgefallen sind:
In der Sitemap sind alle Zeiten leer. Laut Hilfe kann ich auch auch keine Epoch an ein DateTime Item schicken?
Mit dem Ansatz verliere ich ab 14:30 Uhr alle Daten für den aktuellen Tag - einen besseren Ansatz habe ich aber auch noch nicht. Hat hier jemand eine gute Idee?
Code: Alles auswählen
2020-09-09 14:30:00.434 [INFO ] [lipse.smarthome.model.script.awattar] - Start Tag heute: 2020-09-09T00:00+02:00[Europe/Berlin] 1599602400000 Start Tag morgen: 1599688800000
2020-09-09 14:30:00.435 [INFO ] [lipse.smarthome.model.script.awattar] - Hole Daten von https://api.awattar.com/v1/marketdata?start=1599688800000
Code: Alles auswählen
2020-09-09 14:30:00.575 [INFO ] [lipse.smarthome.model.script.awattar] - Preis0=32.09
2020-09-09 14:30:00.583 [INFO ] [lipse.smarthome.model.script.awattar] - Preis1=31.2
2020-09-09 14:30:00.594 [INFO ] [lipse.smarthome.model.script.awattar] - Preis2=31.04
Zwei Punkte die mir noch aufgefallen sind:
In der Sitemap sind alle Zeiten leer. Laut Hilfe kann ich auch auch keine Epoch an ein DateTime Item schicken?
Mit dem Ansatz verliere ich ab 14:30 Uhr alle Daten für den aktuellen Tag - einen besseren Ansatz habe ich aber auch noch nicht. Hat hier jemand eine gute Idee?
-
- Beiträge: 9
- Registriert: 21. Sep 2019 22:02
Re: Awattar
Ich hab nun für jede Stunde ein Item definiert (wie oben beschrieben):
Auszug aus meiner Awatt.item:
Nun möchte ich gerne das Item "awattar_akt" mit dem Preis der aktuellen Stunde füllen.
Meine Rule läuft aber leider auf Fehler:
Folgender Fehler:
==> /var/log/openhab2/openhab.log <==
2020-12-04 21:05:26.538 [WARN ] [rthome.model.script.actions.BusEvent] - Cannot convert 'awattar_pr21' to a command type which item 'awattar_akt' accepts: [DecimalType, QuantityType, RefreshType].
2020-12-04 21:05:26.546 [INFO ] [.smarthome.model.script.awattaktuell] - awattar_akt (Type=NumberItem, State=NULL, Label=Preis aktuell, Category=Awattar)
Wie kann ich ein Item aus einem Text und einer variable zusammensetzen?
Auszug aus meiner Awatt.item:
Code: Alles auswählen
// awatt
Group awatt "Strompreise" <Awattar>
Group:Number:MIN preisminnacht "durchs.Preis [%.2f €/MWh]" <Awattar>
Number awattar_akt "Preis aktuell [%.2f €/MWh]" <Awattar>
Number awattar_pr0 "Preis0 [%.2f €/MWh]" (Awatt, preisminnacht)
Number awattar_pr1 "Preis0 [%.2f €/MWh]" (Awatt, preisminnacht)
Number awattar_pr2 "Preis0 [%.2f €/MWh]" (Awatt, preisminnacht)
Meine Rule läuft aber leider auf Fehler:
Code: Alles auswählen
rule "awattaktuell"
// Ermittlung des aktuellen Preis aus wattabfrage
when
Time cron "52 1 0/1 1/1 * ? *" or
Time cron "24 1 0/1 1/1 * ? *" or
Item Preisaktualisieren changed
then
var x = now.getHourOfDay()
sendCommand(awattar_akt, "awattar_pr"+x)
logInfo("awattaktuell", awattar_akt+"")
sendCommand(awattabfrage, "OFF")
end
==> /var/log/openhab2/openhab.log <==
2020-12-04 21:05:26.538 [WARN ] [rthome.model.script.actions.BusEvent] - Cannot convert 'awattar_pr21' to a command type which item 'awattar_akt' accepts: [DecimalType, QuantityType, RefreshType].
2020-12-04 21:05:26.546 [INFO ] [.smarthome.model.script.awattaktuell] - awattar_akt (Type=NumberItem, State=NULL, Label=Preis aktuell, Category=Awattar)
Wie kann ich ein Item aus einem Text und einer variable zusammensetzen?
- udo1toni
- Beiträge: 13854
- Registriert: 11. Apr 2018 18:05
- Wohnort: Darmstadt
Awattar
So funktioniert das nicht.
x ist eine Integer Zahl. „Awattar_akt“ ist ein String.
Es geht also schon damit los, dass Du versuchst, einen String und eine Zahl zusammenzufügen.
Gehen wir davon aus, dass Du mit x.toString aus der Zahl einen String machst, so ist das Ergebnis der Operation aber immer noch ein String. Du versuchst also, einem Number Item einen String zuzuweisen. Selbst wenn der String ein reiner Zahlenwert wäre, ginge das schief.
In Wirklichkeit willst Du natürlich, dass der errechnete String als Itemname verstanden wird, und dann willst Du auch noch den Status dieses Items auslesen.
Auch das wird so nicht funktionieren.
Die korrekte Herangehensweise: Du erzeugst ein Group Item (das kann gerne vom Typ Number sein, der Typ spielt aber für die Rule keine Rolle) und ordnest alle Stundenitems diesem Group Item zu. Nehmen wir an, das Group Item heißt dann gAwattar. Es kommen nur die Stundenwerte da rein, keine anderen Items, die mit Awattar zu tun haben!
Der Zahlenwert (also 0 bis 23) sollte in diesem Fall mit einem eigenen Unterstrich im Namen abgetrennt sein, also Awattar_akt_0 bis Awattar_akt_23.
Nun kannst Du in einer Rule das korrekte Item bestimmen:
Die lokale Konstante akt steht nun für das Item mit der aktuellen Stunde im Namen. Du kannst mit akt.state auf den Inhalt des Items zugreifen und mit awattar_akt.postUpdate(akt.state) den Status direkt in das Item awattar_akt übernehmen.
.members ist eine Liste aller unmittelbaren Member des Group Items. .filter[] filtert die Liste nach den angegebenen Bedingungen.
i| bedeutet, dass i nach dem | als Substitution für jedes einzelne Item verwendet wird.
.name ist der NAme des Items.
.split(“_“) teilt den String an den Unterstrichen auf und liefert eine Liste.
.get(2) holt aus dieser Liste den 3. Teilstring (0 ist er erste Teil)
.head liefert den erster Treffer.
Gesendet von iPad mit Tapatalk
x ist eine Integer Zahl. „Awattar_akt“ ist ein String.
Es geht also schon damit los, dass Du versuchst, einen String und eine Zahl zusammenzufügen.
Gehen wir davon aus, dass Du mit x.toString aus der Zahl einen String machst, so ist das Ergebnis der Operation aber immer noch ein String. Du versuchst also, einem Number Item einen String zuzuweisen. Selbst wenn der String ein reiner Zahlenwert wäre, ginge das schief.
In Wirklichkeit willst Du natürlich, dass der errechnete String als Itemname verstanden wird, und dann willst Du auch noch den Status dieses Items auslesen.
Auch das wird so nicht funktionieren.
Die korrekte Herangehensweise: Du erzeugst ein Group Item (das kann gerne vom Typ Number sein, der Typ spielt aber für die Rule keine Rolle) und ordnest alle Stundenitems diesem Group Item zu. Nehmen wir an, das Group Item heißt dann gAwattar. Es kommen nur die Stundenwerte da rein, keine anderen Items, die mit Awattar zu tun haben!
Der Zahlenwert (also 0 bis 23) sollte in diesem Fall mit einem eigenen Unterstrich im Namen abgetrennt sein, also Awattar_akt_0 bis Awattar_akt_23.
Nun kannst Du in einer Rule das korrekte Item bestimmen:
Code: Alles auswählen
val akt = gAwattar.members.filter[i|i.name.split(“_“).get(2) == (now.getHourOfDay.toString)].head
.members ist eine Liste aller unmittelbaren Member des Group Items. .filter[] filtert die Liste nach den angegebenen Bedingungen.
i| bedeutet, dass i nach dem | als Substitution für jedes einzelne Item verwendet wird.
.name ist der NAme des Items.
.split(“_“) teilt den String an den Unterstrichen auf und liefert eine Liste.
.get(2) holt aus dieser Liste den 3. Teilstring (0 ist er erste Teil)
.head liefert den erster Treffer.
Gesendet von iPad mit Tapatalk
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet