Öffnungszeiten von Fenstern aus der Datenbank ziehen mit flux

Hallo zusammen,
ich verwende influxdb 2.0 mit flux.
In der Datenbank landen immer die Ereignisse wenn ein Fenster geöffnet oder geschlossen wird. Mit dem Code bekomme ich die Liste der Ereignisse:

from(bucket: "home_assistant")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["domain"] == "binary_sensor")
  |> filter(fn: (r) => r["_field"] == "value")
  |> filter(fn: (r) => r["_measurement"] == "binary_sensor.bd_r_fensterkontakt_state")
  |> filter(fn: (r) => r["entity_id"] == "bd_r_fensterkontakt_state")
  |> yield(name: "last")
||binary_sensor.bd_r_fensterkontakt_state|value|1|2024-01-15T16:36:30.622Z|2024-01-22T16:36:30.622Z|2024-01-16T08:45:39.106Z|binary_sensor|bd_r_fensterkontakt_state|
|---|---|---|---|---|---|---|---|---|
|0|binary_sensor.bd_r_fensterkontakt_state|value|0|2024-01-15T16:36:30.622Z|2024-01-22T16:36:30.622Z|2024-01-16T11:00:03.016Z|binary_sensor|bd_r_fensterkontakt_state|
|0|binary_sensor.bd_r_fensterkontakt_state|value|1|2024-01-15T16:36:30.622Z|2024-01-22T16:36:30.622Z|2024-01-16T17:58:22.980Z|binary_sensor|bd_r_fensterkontakt_state|
|0|binary_sensor.bd_r_fensterkontakt_state|value|0|2024-01-15T16:36:30.622Z|2024-01-22T16:36:30.622Z|2024-01-16T18:13:23.664Z|binary_sensor|bd_r_fensterkontakt_state|
|0|binary_sensor.bd_r_fensterkontakt_state|value|1|2024-01-15T16:36:30.622Z|2024-01-22T16:36:30.622Z|2024-01-17T11:17:44.634Z|binary_sensor|bd_r_fensterkontakt_state|

Gibt es hier einen begabten “Fluxer” der mir sagen kann wie ich die Öffnungsdauer (also die Zeit zwischen dem Übergang von 1 auf 0) mit den vorhandenen Daten sichtbar machen kann ? Ich möchte das Problem nicht in HA selbst lösen, weil ja eigentlich alle infos in der Datenbank stecken.

Danke Peter

Moin,

habe keine vergleichbaren Daten, oder müsste mir erst welche erstellen, aber vielleicht bring Dich das ja schon weiter → elapsed() function | Flux Documentation

from(bucket: "home_assistant")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["domain"] == "binary_sensor")
  |> filter(fn: (r) => r["_field"] == "contact")
  |> filter(fn: (r) => r["_measurement"] == "units")
  |> filter(fn: (r) => r["entity_id"] == "dg_wohnzimmer_dachfenster_nord_contact")
  |> filter(fn: (r) => r["friendly_name"] == "Dachfenster")
  |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false)
  |> yield(name: "last")
  |> drop(columns: ["_measurement", "_start", "_stop", "domain"])
  |> elapsed(unit: 1s)

Ergibt:

table_result _field _value _time elapsed entity_id friendly_name source
0 contact 1 2024-01-15T21:00:00.000Z 3600 dg_wohnzimmer_dachfenster_nord_contact Dachfenster HA
0 contact 1 2024-01-15T22:00:00.000Z 3600 dg_wohnzimmer_dachfenster_nord_contact Dachfenster HA
0 contact 1 2024-01-15T22:30:00.000Z 1800 dg_wohnzimmer_dachfenster_nord_contact Dachfenster HA
0 contact 1 2024-01-15T23:30:00.000Z 3600 dg_wohnzimmer_dachfenster_nord_contact Dachfenster HA
0 contact 1 2024-01-16T00:30:00.000Z 3600 dg_wohnzimmer_dachfenster_nord_contact Dachfenster HA
0 contact 1 2024-01-16T01:00:00.000Z 1800 dg_wohnzimmer_dachfenster_nord_contact Dachfenster HA
0 contact 1 2024-01-16T02:00:00.000Z 3600 dg_wohnzimmer_dachfenster_nord_contact Dachfenster HA

Wobei die Spalte elapsed die Zeit in Sekunden ausgibt, das Du wiederum so anpassen kannst

  |> elapsed(unit: 1s)     // Sekunden
  |> elapsed(unit: 1m)     // Minuten
  |> elapsed(unit: 1h)     // Stunde, usw.

Keine Ahnung, ob das so korrekt ist.

VG
Bernd

Vielen Dank Berd, das war der Stups in die richtige Richtung.

from(bucket: "home_assistant")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["domain"] == "binary_sensor")
  |> filter(fn: (r) => r["_field"] == "value")
  |> filter(fn: (r) => r["_measurement"] == "binary_sensor.bd_r_fensterkontakt_state")
  |> filter(fn: (r) => r["entity_id"] == "bd_r_fensterkontakt_state")
  // delete all columns whih are not needed for the following
  |> drop(columns: ["_measurement", "_start", "_stop", "domain"])
  // sort by timestamp 
  |> sort(columns: ["_time"], desc: false)
  // create an additional column based on the column "_value" with the name "_winstate"
  |> duplicate(column: "_value", as: "_winstate")
  // calculate the difference between two rows of the column "_winstate"
  // "_winstate" can have the value 0 or 1 so the difference can be -1, 0 or 1
  // we need the time when the windows has closed  -> from 0 to 1 -> difference of -1 shows a closed window
  |> difference(columns: ["_winstate"], keepFirst: true)
  // add a column "elapsed"  with the calculated time difference between two rows  
  |> elapsed(unit: 1m)
  // filter for all rows where "_winstate" == -1 (the window has been closed)
  |> filter(fn: (r) => r["_winstate"] == -1)
  // drop all unused columns
  |> drop(columns: ["_value", "_winstate"])
  // sum up the opening time for a complete day
  |> aggregateWindow(every: 1d, fn: sum, column: "elapsed", createEmpty: false)
  |> yield(name: "last")

Das Ergebnis scheint zu passen.
Mit der Abfrage gibt es die Summe aller Öffnungszeiten über einen Tag.
Wenn man das letzte aggregateWindow weg lässt, dann bekommt man die einzelnen Öffnungszeiten.

Ich hoffe das können auch Andere brauchen.

Gruß Peter

1 „Gefällt mir“