Ich auch, habe schon Sensoren erstellt und Vergleiche mal morgen. ![]()
Danke an alle.
Hallo, ich benötige nochmals eure Hilfe.
Der sql sensor für PV1 funktioniert:
WITH riemann_52 AS (
SELECT
CAST(state AS REAL) AS watt,
last_updated_ts,
LEAD(last_updated_ts) OVER (ORDER BY last_updated_ts) AS next_ts
FROM states
WHERE metadata_id = (
SELECT sm.metadata_id
FROM states_meta sm
WHERE sm.entity_id = 'sensor.kostal_wechselrichter_dc1_power'
LIMIT 1
)
AND datetime(last_updated_ts, 'unixepoch') >= date('now')
AND state NOT IN ('unknown', 'unavailable')
AND state GLOB '[0-9]*'
)
SELECT ROUND(
COALESCE(
SUM(
watt * (COALESCE(next_ts, last_updated_ts + 300) - last_updated_ts) / 3600.0 / 1000.0
),
0
),
2
) AS state
FROM riemann_52
WHERE watt >= 0;
Der für die Summe aus PV1 +PV2 nicht. Was ist hier falsch?
WITH combined_power AS (
SELECT
last_updated_ts,
SUM(CAST(state AS REAL)) AS total_watt
FROM states
WHERE metadata_id IN (
SELECT sm.metadata_id
FROM states_meta sm
WHERE sm.entity_id IN (
'sensor.kostal_wechselrichter_dc1_power',
'sensor.kostal_wechselrichter_dc2_power'
)
)
AND datetime(last_updated_ts, 'unixepoch') >= date('now')
AND state NOT IN ('unknown', 'unavailable')
AND state GLOB '[0-9]*'
GROUP BY last_updated_ts
),
riemann AS (
SELECT
total_watt AS watt,
last_updated_ts,
LEAD(last_updated_ts) OVER (ORDER BY last_updated_ts) AS next_ts
FROM combined_power
)
SELECT ROUND(
COALESCE(
SUM(
watt * (COALESCE(next_ts, last_updated_ts + 300) - last_updated_ts) / 3600.0 / 1000.0
),
0
),
2
) AS state
FROM riemann
WHERE watt >= 0;
@nightrunner cool das Du dich dran gewagt hast!
Der Fehler ist klar.. und ist der Selbe der SFML aus dem Takt gebracht hat ![]()
Die beiden Sensoren (dc1_power und dc2_power) aktualisieren nicht exakt gleichzeitig. Dadurch haben sie fast nie denselben last_updated_ts.
GROUP BY last_updated_ts
Lösung (sollte gehen):
Zuerst für jeden Sensor die Energie separat berechnen und dann zu summieren:
WITH energy_dc1 AS (
SELECT
ROUND(
COALESCE(
SUM(
CAST(state AS REAL) *
(COALESCE(LEAD(last_updated_ts) OVER (ORDER BY last_updated_ts), last_updated_ts + 300) - last_updated_ts)
/ 3600.0 / 1000.0
),
0
),
2
) AS kwh
FROM states
WHERE metadata_id = (SELECT metadata_id FROM states_meta WHERE entity_id = 'sensor.kostal_wechselrichter_dc1_power' LIMIT 1)
AND datetime(last_updated_ts, 'unixepoch') >= date('now')
AND state NOT IN ('unknown', 'unavailable')
AND state GLOB '[0-9]*'
AND CAST(state AS REAL) >= 0
),
energy_dc2 AS (
SELECT
ROUND(
COALESCE(
SUM(
CAST(state AS REAL) *
(COALESCE(LEAD(last_updated_ts) OVER (ORDER BY last_updated_ts), last_updated_ts + 300) - last_updated_ts)
/ 3600.0 / 1000.0
),
0
),
2
) AS kwh
FROM states
WHERE metadata_id = (SELECT metadata_id FROM states_meta WHERE entity_id = 'sensor.kostal_wechselrichter_dc2_power' LIMIT 1)
AND datetime(last_updated_ts, 'unixepoch') >= date('now')
AND state NOT IN ('unknown', 'unavailable')
AND state GLOB '[0-9]*'
AND CAST(state AS REAL) >= 0
)
SELECT ROUND((COALESCE(dc1.kwh, 0) + COALESCE(dc2.kwh, 0)), 2) AS state
FROM energy_dc1 dc1
CROSS JOIN energy_dc2 dc2;
Wir bekommen das schon hin ![]()
WITH dc1_rows AS (
SELECT
CAST(state AS REAL) AS power_w,
last_updated_ts AS ts,
LEAD(last_updated_ts) OVER (ORDER BY last_updated_ts) AS next_ts
FROM states
WHERE metadata_id = (
SELECT metadata_id
FROM states_meta
WHERE entity_id = 'sensor.kostal_wechselrichter_dc1_power'
LIMIT 1
)
AND datetime(last_updated_ts, 'unixepoch', 'localtime') >= date('now', 'localtime')
AND state NOT IN ('unknown', 'unavailable')
AND state GLOB '[0-9]*'
AND CAST(state AS REAL) >= 0
),
dc2_rows AS (
SELECT
CAST(state AS REAL) AS power_w,
last_updated_ts AS ts,
LEAD(last_updated_ts) OVER (ORDER BY last_updated_ts) AS next_ts
FROM states
WHERE metadata_id = (
SELECT metadata_id
FROM states_meta
WHERE entity_id = 'sensor.kostal_wechselrichter_dc2_power'
LIMIT 1
)
AND datetime(last_updated_ts, 'unixepoch', 'localtime') >= date('now', 'localtime')
AND state NOT IN ('unknown', 'unavailable')
AND state GLOB '[0-9]*'
AND CAST(state AS REAL) >= 0
),
energy_dc1 AS (
SELECT
ROUND(
COALESCE(
SUM(
power_w *
(COALESCE(next_ts, CAST(strftime('%s', 'now') AS INTEGER)) - ts)
/ 3600.0 / 1000.0
),
0
),
2
) AS kwh
FROM dc1_rows
),
energy_dc2 AS (
SELECT
ROUND(
COALESCE(
SUM(
power_w *
(COALESCE(next_ts, CAST(strftime('%s', 'now') AS INTEGER)) - ts)
/ 3600.0 / 1000.0
),
0
),
2
) AS kwh
FROM dc2_rows
)
SELECT ROUND(COALESCE(dc1.kwh, 0) + COALESCE(dc2.kwh, 0), 2) AS state
FROM energy_dc1 dc1
CROSS JOIN energy_dc2 dc2;
Geb mal feedback bitte..
Alternativ (GROK)
WITH dc1 AS (
SELECT
CAST(state AS REAL) AS power_w,
last_updated_ts AS ts,
LEAD(last_updated_ts) OVER (ORDER BY last_updated_ts) AS next_ts
FROM states
WHERE metadata_id = (SELECT metadata_id FROM states_meta WHERE entity_id = 'sensor.kostal_wechselrichter_dc1_power' LIMIT 1)
AND datetime(last_updated_ts, 'unixepoch') >= date('now')
AND state NOT IN ('unknown', 'unavailable')
AND state GLOB '[0-9]*'
AND CAST(state AS REAL) >= 0
),
dc2 AS (
SELECT
CAST(state AS REAL) AS power_w,
last_updated_ts AS ts,
LEAD(last_updated_ts) OVER (ORDER BY last_updated_ts) AS next_ts
FROM states
WHERE metadata_id = (SELECT metadata_id FROM states_meta WHERE entity_id = 'sensor.kostal_wechselrichter_dc2_power' LIMIT 1)
AND datetime(last_updated_ts, 'unixepoch') >= date('now')
AND state NOT IN ('unknown', 'unavailable')
AND state GLOB '[0-9]*'
AND CAST(state AS REAL) >= 0
),
energy_dc1 AS (
SELECT ROUND(
COALESCE(
SUM(
power_w * (COALESCE(next_ts, ts + 300) - ts) / 3600.0 / 1000.0
),
0
), 2) AS kwh
FROM dc1
),
energy_dc2 AS (
SELECT ROUND(
COALESCE(
SUM(
power_w * (COALESCE(next_ts, ts + 300) - ts) / 3600.0 / 1000.0
),
0
), 2) AS kwh
FROM dc2
)
SELECT ROUND(COALESCE(dc1.kwh, 0) + COALESCE(dc2.kwh, 0), 2) AS state
FROM energy_dc1 dc1
CROSS JOIN energy_dc2 dc2;
Hi @Tom-HA
die erste Variante läßt sich anlegen, aber!
Die Summe stimmt nicht, siehe screenshot:
Was mir noch aufgefallen ist, der SQL Sensor PV 2 sinkt um 16.21 Uhr zwischenzeitlich???
Die zweite Variante genannt Test, passt deutlich besser, aber!
In dem screenshots sieht man das zu unterschiedlichen Zeitpunkten, es mal passt dann wieder nicht???
Also ich habe mal getestet.
Vergleich HA Integral + Verbrauchszähler gegen SQL
Morgens läuft es minimal auseinander und bleibt über den Tag so
Um dann Abends Fast gleichauf zu sein. Siehe hier “Rundungsfehler” da ich SQL eine Dezimalstelle mehr anzeigen lasse.
@Tom-HA Siehst du eine Relevanz zu Wechseln ?
Weil hier sieht man gut, das SQL erst um 0:00:21 auf 0 zurücksetzt.
Spannend wird es noch, wenn wechselhaftes Wetter ist.
→ ich lasse mal den Vergleich weiterlaufen.
SQL, ich verstehe es nicht mehr:
Rücksetzer um 2 Uhr bei PV1, PV2 und Test?
Gut das HA keine Augenlaser steuert.
Das scheint ein Problem mit deiner Zeitzone zu sein, aber ich habe keine Ahnung wo das überall konfiguriert werden kann.
2:00 lokaler Zeit wären 0:00 UTC
Nur als kleiner Tip
Danke für den Hinweis, aber ich habe da schlicht zu wenig know how vom Thema.
Ich gehe da als Nichtinformatiker eher mit gesundem Menschenverstand dran.
Die SQL Sensoren setzen zurück wann sie wollen, die Addition ist eher zufällig, zumindest mein Eindruck.
Da kann ich besser bei den Kostalsensoren bleiben, zumal sfml ja inzwischen Fehler kompensiert.
Sie setzen sich also nicht um 02:00:10 zurück sondern auch zu anderen Zeiten?
Das kann aber nicht sein. SQL-Sensoren setzen sich nicht zurück, sondern die Daten die berechnet werden sind die Daten von Heute. Deshalb ist da die Zeile
AND datetime(last_updated_ts, 'unixepoch') >= date('now')
Post geändert: Es muß so lauten:
AND date(last_updated_ts, 'unixepoch', 'localtime') >= date('now', 'localtime')
Edit Ende
drin, also nimm nur Daten, wo last_update_ts >= Heutiger Tag 0:00:00 ist.
Wenn du wenig Erfahrung in der Informatik hast, impliziere ich, das du die in HA integrierte Datenbank SQLite benutzt. Dann kann es auch kein Zeitfehler sein. Bitte zeige mir mal deine SQL-Abfrage. Flinte ins Korn werfen gilt es nicht, wir helfen dir da schon durch.
Wenn es schwierig für dich ist die kombinierte Abfrage für Total zu erstellen, dann erstell dir einen Sensor der String1 und String2 einfach addiert. Das mußt du ja sowieso bauen, wenn du auf die andere Lösung schwenken willst. Dann setzt du genau die selbe Abfrage den du für die Gruppen genommen hast auch auf diesen Totalen Sensor ein.
Ich hatte weiter oben bereits meinen SQL-Sensor für Energie aus Leistung berechnen gezeigt. Den habe ich auf der SQLite Datenbank bei mir im Einsatz, nur die ObjektID austauschen fertig.
WITH riemann_calc AS (
SELECT
CAST(s.state AS REAL) AS watt,
s.last_updated_ts,
LEAD(s.last_updated_ts) OVER (ORDER BY s.last_updated_ts) AS next_ts
FROM states s
WHERE s.metadata_id = (
SELECT sm.metadata_id
FROM states_meta sm
WHERE sm.entity_id = 'sensor.inverter_leistung_dc_total'
LIMIT 1
)
AND datetime(s.last_updated_ts, 'unixepoch', 'localtime') >= date('now', 'localtime')
AND s.state NOT IN ('unknown', 'unavailable')
AND s.state GLOB '[0-9]*'
AND s.state NOT GLOB '*[^0-9.]*'
AND (s.state NOT LIKE '%.%.%')
)
SELECT
ROUND(COALESCE(SUM(
watt *
(COALESCE(next_ts, last_updated_ts + 300) - last_updated_ts) / 3600.0 / 1000.0
), 0), 2) AS state
FROM riemann_calc
WHERE watt >= 0;
Aber zeige mal welche Abfrage du im SQL-Sensor drin hast, dann können wir den Fehler suchen.
@alteMade Danke für das Angebot! Ja ich verwende die integrierte SQLite Datenbank.
Folgende sql Sensoren habe ich mit eurer und Toms Hilfe angelegt.
Für PV1 daily:
WITH riemann_52 AS (
SELECT
CAST(state AS REAL) AS watt,
last_updated_ts,
LEAD(last_updated_ts) OVER (ORDER BY last_updated_ts) AS next_ts
FROM states
WHERE metadata_id = (
SELECT sm.metadata_id
FROM states_meta sm
WHERE sm.entity_id = 'sensor.kostal_wechselrichter_dc1_power'
LIMIT 1
)
AND datetime(last_updated_ts, 'unixepoch') >= date('now')
AND state NOT IN ('unknown', 'unavailable')
AND state GLOB '[0-9]*'
)
SELECT ROUND(
COALESCE(
SUM(
watt * (COALESCE(next_ts, last_updated_ts + 300) - last_updated_ts) / 3600.0 / 1000.0
),
0
),
2
) AS state
FROM riemann_52
WHERE watt >= 0;
Für PV2 daily:
WITH riemann_52 AS (
SELECT
CAST(state AS REAL) AS watt,
last_updated_ts,
LEAD(last_updated_ts) OVER (ORDER BY last_updated_ts) AS next_ts
FROM states
WHERE metadata_id = (
SELECT sm.metadata_id
FROM states_meta sm
WHERE sm.entity_id = 'sensor.kostal_wechselrichter_dc2_power'
LIMIT 1
)
AND datetime(last_updated_ts, 'unixepoch') >= date('now')
AND state NOT IN ('unknown', 'unavailable')
AND state GLOB '[0-9]*'
)
SELECT ROUND(
COALESCE(
SUM(
watt * (COALESCE(next_ts, last_updated_ts + 300) - last_updated_ts) / 3600.0 / 1000.0
),
0
),
2
) AS state
FROM riemann_52
WHERE watt >= 0;
Für die Summe von PV1+2 daily zum einen den
“SQL PV1+2 daily”
WITH dc1_rows AS (
SELECT
CAST(state AS REAL) AS power_w,
last_updated_ts AS ts,
LEAD(last_updated_ts) OVER (ORDER BY last_updated_ts) AS next_ts
FROM states
WHERE metadata_id = (
SELECT metadata_id
FROM states_meta
WHERE entity_id = 'sensor.kostal_wechselrichter_dc1_power'
LIMIT 1
)
AND datetime(last_updated_ts, 'unixepoch', 'localtime') >= date('now', 'localtime')
AND state NOT IN ('unknown', 'unavailable')
AND state GLOB '[0-9]*'
AND CAST(state AS REAL) >= 0
),
dc2_rows AS (
SELECT
CAST(state AS REAL) AS power_w,
last_updated_ts AS ts,
LEAD(last_updated_ts) OVER (ORDER BY last_updated_ts) AS next_ts
FROM states
WHERE metadata_id = (
SELECT metadata_id
FROM states_meta
WHERE entity_id = 'sensor.kostal_wechselrichter_dc2_power'
LIMIT 1
)
AND datetime(last_updated_ts, 'unixepoch', 'localtime') >= date('now', 'localtime')
AND state NOT IN ('unknown', 'unavailable')
AND state GLOB '[0-9]*'
AND CAST(state AS REAL) >= 0
),
energy_dc1 AS (
SELECT
ROUND(
COALESCE(
SUM(
power_w *
(COALESCE(next_ts, CAST(strftime('%s', 'now') AS INTEGER)) - ts)
/ 3600.0 / 1000.0
),
0
),
2
) AS kwh
FROM dc1_rows
),
energy_dc2 AS (
SELECT
ROUND(
COALESCE(
SUM(
power_w *
(COALESCE(next_ts, CAST(strftime('%s', 'now') AS INTEGER)) - ts)
/ 3600.0 / 1000.0
),
0
),
2
) AS kwh
FROM dc2_rows
)
SELECT ROUND(COALESCE(dc1.kwh, 0) + COALESCE(dc2.kwh, 0), 2) AS state
FROM energy_dc1 dc1
CROSS JOIN energy_dc2 dc2;
und den “Test” aus den Vorschlägen von Tom für die Summe PV1+2 daily
WITH dc1 AS (
SELECT
CAST(state AS REAL) AS power_w,
last_updated_ts AS ts,
LEAD(last_updated_ts) OVER (ORDER BY last_updated_ts) AS next_ts
FROM states
WHERE metadata_id = (SELECT metadata_id FROM states_meta WHERE entity_id = 'sensor.kostal_wechselrichter_dc1_power' LIMIT 1)
AND datetime(last_updated_ts, 'unixepoch') >= date('now')
AND state NOT IN ('unknown', 'unavailable')
AND state GLOB '[0-9]*'
AND CAST(state AS REAL) >= 0
),
dc2 AS (
SELECT
CAST(state AS REAL) AS power_w,
last_updated_ts AS ts,
LEAD(last_updated_ts) OVER (ORDER BY last_updated_ts) AS next_ts
FROM states
WHERE metadata_id = (SELECT metadata_id FROM states_meta WHERE entity_id = 'sensor.kostal_wechselrichter_dc2_power' LIMIT 1)
AND datetime(last_updated_ts, 'unixepoch') >= date('now')
AND state NOT IN ('unknown', 'unavailable')
AND state GLOB '[0-9]*'
AND CAST(state AS REAL) >= 0
),
energy_dc1 AS (
SELECT ROUND(
COALESCE(
SUM(
power_w * (COALESCE(next_ts, ts + 300) - ts) / 3600.0 / 1000.0
),
0
), 2) AS kwh
FROM dc1
),
energy_dc2 AS (
SELECT ROUND(
COALESCE(
SUM(
power_w * (COALESCE(next_ts, ts + 300) - ts) / 3600.0 / 1000.0
),
0
), 2) AS kwh
FROM dc2
)
SELECT ROUND(COALESCE(dc1.kwh, 0) + COALESCE(dc2.kwh, 0), 2) AS state
FROM energy_dc1 dc1
CROSS JOIN energy_dc2 dc2;
alle zusätzlich:
Ich rate: Du hast den zweiten PV1+2 daily oben gezeigt?
Denn beim ersten sollte es stimmen.
AND datetime(last_updated_ts, 'unixepoch') >= date('now')
ich fürchte, das hier die Vermischung auftritt, besser wäre wohl beide Seiten zwingend auf localtime zu bringen. Darauf deutet die Verschiebung um genau 2 Stunden hin.
ersetze das überall durch folgendes, so wird überall die lokale Zeit erzwungen.
AND date(last_updated_ts, 'unixepoch', 'localtime') >= date('now', 'localtime')
Bitte dann morgen noch einmal Rückmeldung geben ![]()
Gruß Ralf
Hallo Ralf,
Danke! Ich habe alle
AND datetime(last_updated_ts, 'unixepoch') >= date('now')
durch
AND date(last_updated_ts, 'unixepoch', 'localtime') >= date('now', 'localtime')
ersetzt im Code. Ich gebe morgen Rückmeldung.
Gruß Stefan
Guten Morgen,
hier sind die Ergebnisse:
PV1daily geht um 00:00:01 auf 0
PV2 daily geht um 00:00:21 auf 0
PV1+2 daily geht um 00:00:22 auf 0
Test geht um 00:00:22 auf 0
Wieso und weshalb diese Unterschiede, das würde sfml doch irritieren? Oder?
===================
Hier noch die Zwischenwerte der beteiligten Sensoren:
Um 9.18 Uhr:
PV1+2 Summe falsch;
Test halbwegs korrekt, aber 0,03 zu wenig
Um 9.23 Uhr:
PV1+2 Summe falsch;
Test Addition korrekt
Um 9.32 Uhr:
PV1+2 Summe falsch;
Test mit Differenz, 0,04 zu wenig
Das sind Schwankungen die ich nicht verstehe.
Eigentlich müsste ich mit dem code aus “Test” einen neuen PV1+2 erstellen.
=========================================================
Zusätzlich habe ich mir mal die Ergebnisse aus der Kostal Integration angeschaut:
Um exakt 00:00:00 setzen die drei von mir erstellten HA Sensoren zurück:
Kostal Wechselrichter Energy PV1 täglich für sfml
Kostal Wechselrichter Energy PV2 täglich für sfml
Kostal Wechselrichter Energy PV1+2 täglich für sfml
PV1 und PV2 sind Verbrauchszähler auf die jeweiligen Totalzähler 1 bzw. 2 aus der
Kostalintegration.
Der PV1+2 ist ein templatesensor
der “PV1 täglich für sfml” und ”PV2 täglich für sfml” addiert.
Allerdings ist teilweise der Additionsensor um wenige Sekunden verspätet, dann aber korrekt addiert.
Spannendes Thema, bei dem ich inzwischen nicht mehr weiß was wichtiger ist, der Zeitpunkt Rückstellung 0:00 Uhr oder die paßgenaue Addition.
Dazu muß Zara etwas sagen.
Warum die Unterschiede in den Sekunden?
Antwort: Die SQL-Sensoren updaten ihren Wert dann, wenn ein neuer Wert im zugrundeliegenden Sensor kommt. Erst bei der Neuberechnung wird dann der neue Tag berücksichtigt.
@Tom-HA kannst du seine eigentliche Frage beantworten, was ist wichtiger? So wie ich das verstanden habe, wird um 00:05:00 der neue Groundlevel ermittelt, da sollten die Sekunden doch egal sein, oder?
Gruß Ralf
Ganz genauso ist es! Danke Ralf für Deine Unterstützung


















