I am collecting data from various sensors which may occasionally report values with small fluctuations, e.g. 17.1°C, 17.2°C, 17.05°C, 17.1°C where the temperature doesn’t really change.
Some of these sensors are counters which may overlap, so I am doing statistics with these sensors using increase()
and derivative(nonNegative: true)
. However, combined with noisy data this leads to huge errors in my reports, because when tiny constant fluctuations occur, increase()
always only counts the positive part of these fluctuations. This way, e.g. a water meter will report 50 cubic meters of water used on one day instead of the (correct) 500 liters.
This is an except of the dataset:
,,0,2021-08-13T23:30:08Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-13T23:40:10Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-13T23:50:10Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T00:00:07Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T00:10:10Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T00:20:08Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T00:30:08Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T00:40:08Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T00:50:07Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T01:00:09Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T01:10:07Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T01:20:07Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T01:30:07Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T01:40:07Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T01:50:08Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T02:00:07Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T02:10:07Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T02:20:08Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T02:30:07Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T02:40:07Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T02:50:07Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T03:00:08Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T03:10:09Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T03:20:07Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T03:30:10Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T03:40:07Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T03:50:07Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T04:00:09Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T04:10:08Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T04:20:08Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T04:30:11Z,756.5649,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T04:40:07Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T04:50:10Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T05:00:08Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T05:10:08Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T05:20:12Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T05:30:08Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T05:40:07Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T05:50:07Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T06:00:07Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T06:10:10Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T06:20:07Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T06:30:07Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T06:40:08Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T06:50:08Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T07:00:08Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T07:10:07Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
,,0,2021-08-14T07:20:11Z,756.5659,value,mqtt.0.wasserzaehler.main.value,true,system.adapter.mqtt.0,0
This is my query:
from(bucket: "Home")
|> range(start: v.timeRangeStart, stop:v.timeRangeStop)
|> filter(fn: (r) => r._measurement == "mqtt.0.wasserzaehler.main.value" and r._field == "value")
|> aggregateWindow(every: 5m, fn: last, timeSrc: "_start", createEmpty: false)
|> increase()
|> aggregateWindow(every: 24h, fn: last, timeSrc: "_start", createEmpty: false)
|> derivative(unit: 24h, nonNegative: true)
|> keep(columns: ["_measurement", "_value", "_time"])
|> set(key: "_measurement", value: "Verbrauch alle 24h")
|> sort(columns: ["_time"])
I need increase()
with a small enough aggregation window to find counter wraps without losing (too much) data. (Using it without aggregation window is far too slow.)
I need derivative
with a larger aggregation window to then calculate the change over time.
How can I denoise this data in a way so that I lose neither counter wraps nor real increases? movingAverage()
will not help because it destroys the counter wrap detection of increase()
.
Thank you!