Count (in seconds) how long a value is '1'

dear all,

I want to measuere how long we are using our smartphones during the day,
so eveytime the smartphone is active a ‘1’ is sent to the influx database, and when the phone is not active anymore, a value ‘0’ is sent., so i want the sum of all the times (in seconds) during a certain timeperiod (1 day) t that the value is ‘1’: for example
10:15:05 → 1
10:16:05 → 0
10:30:30 → 1
10:30:45 → 0

so the flux querry should return ‘75’ (60 + 15) .

can someone help me with this?
regards,
Thomas

Hi @Thomas_Decock

How about something like this?

Test data that I created:

Add an elapsed() function to the query:

from(bucket: "junkbucket")
  |> range(start: 2023-02-11T11:35:04.493Z, stop: 2023-02-11T11:38:57.369Z)
  |> filter(fn: (r) => r["_measurement"] == "BinaryData")
  |> filter(fn: (r) => r["_field"] == "value")
  |> filter(fn: (r) => r["device"] == "smartphone")
  |> filter(fn: (r) => r["person"] == "Thomas")
  |> elapsed(unit: 1s)
  |> yield(name: "sum")

gives us an additional column called elapsed that shows the number of seconds from each consecutive record:

Next, add a filter statement after the elapsed function to filter out only those whose _value = 0. This is because the “active” time (when the state 1 goes to state 0) is captured in those records where _value = 0. If you wanted to know the time when the phone is NOT active, you would set the filter where _value = 1.

  |> filter(fn: (r) => r["_value"] == 0)

Lastly, sum up the values in the “elapsed” column:

from(bucket: "junkbucket")
  |> range(start: 2023-02-11T11:35:04.493Z, stop: 2023-02-11T11:38:57.369Z)
  |> filter(fn: (r) => r["_measurement"] == "BinaryData")
  |> filter(fn: (r) => r["_field"] == "value")
  |> filter(fn: (r) => r["device"] == "smartphone")
  |> filter(fn: (r) => r["person"] == "Thomas")
  |> elapsed(unit: 1s)
  |> filter(fn: (r) => r["_value"] == 0)
  |> sum(column:"elapsed")
  |> yield(name: "sum")

1 Like

Thank you a lot for this!
This works great! This is what I wanted.

If I want to see for each day how much the smartphone was active I guess I have to use the:
'aggregateWindow" function?

let’s say I have the range set to ‘last week’, and i want to see for every day what the useage of the phone was, i will need to use this i think?
|> aggregateWindow(every: 1d , fn:last, createEmpty: false)

but this does not seems to work. I am not sure where to put this function.

Hi @Thomas_Decock

Remove the line:

  |> sum(column:"elapsed")

and replace with this:

  |> aggregateWindow(every: 1d, fn: sum, column:"elapsed")

thank you a lot for this!
I thought of it when i was in bed to do it this way! But great to hear I was thinking the correct way to do it.

I sitll have a follow up queston… (i allready tried several things but I am not able to do it…)
now i have for each day the total seconds a phone was used.
but if i want to convert this to ‘hours’…
i was thinking about using this function:

|> map(fn: (r) => ({_time: r._time, hours: r.elapsed/3600.0} ))

but the r.elapsed value is not an integer/float so it’s not possible to do this kind of operation with it…
i also tried using the int() or float() fuction for the r.elapsed… but this does not work

Hi @Thomas_Decock
I think this will work. There may be a more elegant way to just have one single column called elapsed which has the float value, but I created a second column called elapsedFloat and then divided by 3600.0 to get the decimal hours.

from(bucket: "junkbucket")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "BinaryData")
  |> filter(fn: (r) => r["_field"] == "value")
  |> filter(fn: (r) => r["device"] == "smartphone")
  |> filter(fn: (r) => r["person"] == "Thomas")
  |> elapsed(unit: 1s)
  |> map(fn: (r) => ({ r with elapsedFloat: float(v: r.elapsed)/3600.0 }))
  |> filter(fn: (r) => r["_value"] == 0)
  |> aggregateWindow(every: 1d, fn: sum, column:"elapsedFloat")
  |> yield(name: "sum")

1 Like

Thanks a lot for all of your help!
I learned a lot! I sure like the possibilities of ‘Flux’ but it’s a lot to learn.

Hello, this exact solution is what I have also been searching for, however I am using influxdb cloud serverless, so querying with flux is not available, is there an SQL solution?

Wow!
Thanks for your educational help here.
I’ve learned a lot.
I have a question though.
When the state is 1 currently it seems that this query would not capture the active time. (the current chunk that did not go to 0 yet).
How can I add that to the result?
Many thanks!

Hi @Sepp and welcome to the InfluxDB forum.

It has been a while since I crafted that query, so I no longer have the test data lying around, but I am sure there is a way to capture the current state (up to the time that the query is run) when that value is “1”. What happens if you modify the aggregateWindow function to include timeSrc: "start" ?

|> aggregateWindow(every: 1d, fn: sum, timeSrc:"_start", column: "elapsedFloat")

More info here: aggregateWindow() function | Flux Documentation