Measure time between peaks in a graph

So I have a sensor that creates a graph like this:

2021-08-08 20_00_16-Wasserstand - Home Assistant

Now I want a new sensor that outputs the duration between the peaks in minutes.

Therefore, I already have created a binary sensor that is “on” when the value is rising and “off” when it is falling. So, more specifically, what I want to measure is the duration between this binary sensor changing from “on” to “off”.

I think I need to use the template engine to achieve this, but I don’t have any clue how to do it. Any ideas?

1 Like

So you want the latest peak to peak value or an average of the day/week etc?

Also. Does it have to be a template sensor?
I think it will be very hard if even possible with templates.
In Nose red you can get the history of the binary with timestamps and it can be outputted to a sensor.

yep, latest peak to peak value, no averages.

Nope, definitely not. Any solution is appreciated!

Damn, seems to be about time that I have to dive into Node Red. Well, I knew that day would come and… there seems to be it :wink: Thanks, I’ll have a look.

Sure…
For this you will most likely need to JavaScript a code in a function node to give you the time between the peaks.
It’s possible you could do it without, but I don’t know how that would be done.

I believe you will need some more assistance with this.
Let me just get something to eat and I’ll see if I can figure out the JavaScript you need.

Get it installed and running in the meantime and see if you can get some basics.

This seems to work on one of my binary sensors.

[{"id":"d219dae1.b6c198","type":"trigger-state","z":"ebaa69a9.649708","name":"","server":"4bbca37b.1700ec","exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityid":"binary_sensor.<Your_Sensor>","entityidfiltertype":"exact","debugenabled":false,"constraints":[{"id":"g6fxg4ibdyk","targetType":"this_entity","targetValue":"","propertyType":"current_state","propertyValue":"new_state.state","comparatorType":"is","comparatorValueDatatype":"str","comparatorValue":"off"}],"constraintsmustmatch":"all","outputs":2,"customoutputs":[],"outputinitially":false,"state_type":"str","x":250,"y":780,"wires":[["58009c5e.d64514"],[]]},{"id":"58009c5e.d64514","type":"api-get-history","z":"ebaa69a9.649708","name":"","server":"4bbca37b.1700ec","startdate":"","enddate":"","entityid":"binary_sensor.<Your_Sensor>","entityidtype":"is","useRelativeTime":false,"relativeTime":"","flatten":true,"output_type":"array","output_location_type":"msg","output_location":"payload","x":590,"y":780,"wires":[["b46cd3b0.ccca5"]]},{"id":"f61838d3.b51388","type":"inject","z":"ebaa69a9.649708","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":430,"y":840,"wires":[["58009c5e.d64514"]]},{"id":"b46cd3b0.ccca5","type":"function","z":"ebaa69a9.649708","name":"","func":"var last = msg.payload[msg.payload.length - 1].last_changed;\nvar second_to_last = msg.payload[msg.payload.length - 2].last_changed;\n\nmsg.minutes = Math.round(((new Date(last).getTime()/1000) - (new Date(second_to_last).getTime()/1000))/60);\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":760,"y":780,"wires":[["69aa17fd.ff1b78","adcb26bb.e663f8"]]},{"id":"69aa17fd.ff1b78","type":"debug","z":"ebaa69a9.649708","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":970,"y":820,"wires":[]},{"id":"adcb26bb.e663f8","type":"ha-entity","z":"ebaa69a9.649708","name":"Peak to peak","server":"4bbca37b.1700ec","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"peak_to_peak"},{"property":"device_class","value":""},{"property":"icon","value":""},{"property":"unit_of_measurement","value":"minutes"}],"state":"minutes","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":980,"y":760,"wires":[[]]},{"id":"4bbca37b.1700ec","type":"server","name":"Home Assistant","legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]

The blue nodes is the ones you need to edit or in peak to peak, look if it seems correct.

You need this custom component in order to create the sensor in HA.

(this is the blue last node in the sequence)

The inject node ( the grey one) has a button on the side which forces the sequence to run and if you open the debug window then you will see the msg.minutes in the debug window, the last peak to peak time.

Wow great, thanks a million times! That was really helpful! I now have the peak_to_peak sensor that outputs this data:

2021-08-09 09_40_27-Wasserstand - Home Assistant

I will now figure out why the duration between the minimal turning points are stored in the variable too, which is not that bad actually - but as soon as i know the reason, I’m going to create another sensor in Node Red that will output just the duration between the low points, so I have both information neatly presented.

Thanks again!

If you use a derivative sensor it should ne zero at a peak, although with the discontinuities in your graph it might not work.

Are you sure that is what it is?
What does the binary sensor look like in a short time span using the history tab. Does it do a fast on/off at the low points also?

Try and add this to the first node.


and click on “Add Constraint”.

It should only trigger on current state off, but lets add previous state on also.
It should be the same thing since it’s binary. But lets see what happens.

EDIT.

Looking at the original sensor. The drop seems to happen at around 27-28 cm each time.
Is that constant-ish?

We could filter the sequence to not trigger if the value is less than say 24 cm…

I tried to reconfigure the first node, resulting in the flow not running at all (possibly my fault). However, I also tried replacing the first node with a “events: state” node. I also reconfigured my sensor to only deliver one decimal place (instead of two) so there is fewer data to work with, and also to output an average of 6 measurements.

Right now, it works, nearly as intended: It outputs not the time between peaks, but the time between the low and high points. Which is quite good, actually even better then what I wanted, because it’s more intuitive. I could change it by adapting your javascript function, but I’ll leave it like that for now. Maybe I’ll create another flow someday that also outputs the time it takes from a high point to the next low point…

Thanks again for your support.

1 Like

So I’m trying to do the same thing with my ultrasonic sensor that measures the height of the water level in the sump pit.

However, my data is a bit noisier.

I tried make a derivative sensor but near the maximum the slope is so small compared to the noise it’s not giving my a consistent positive slope. Even if I mess with time averaging the derivative, I think I’m still running into the same issue. (The different colors are for different sensors I’m trying with different time increments to take the average derivative.)

Anyone have any ideas on how to address this?

Any progress? I want to do something simular but with my water softener.

For a water softener? Wouldn’t the cycles be on the order of weeks or months, rather than minutes? Not sure it’s worth the effort, as you’d have to store the data somewhere as HA won’t keep it around that long. I was able to get it working fairly well with my sump pumps though.

This is what I did in ESPHome:

sensor:
#Sump Pump Pit 1
  - platform: ultrasonic
    trigger_pin: GPIO15
    echo_pin: GPIO16
    name: "Sump Pump Water Depth Pit 1"
    id: water_depth_pit_2
    update_interval: 1s
    accuracy_decimals: 1
    timeout: 1m
    unit_of_measurement: cm
    filters:
      - lambda: return (0.55 - x)*100;
      - sliding_window_moving_average:
         window_size: 5
         send_every: 5

  - platform: copy
    source_id: water_depth_pit_2
    name: "Sump Pump Water Depth Pit 1 Throttled"
    filters:
      - throttle: 10s

I think I had to fiddle with the derivative sensor in HA, but those settings are just trial and error and will depend on the data. Same with these, I did some trial and error to see what will work.

Glad you got it working. It recharges every week or so. I have the data normalized but now I would like to track frequency.

So it looks like I used two helpers in Home Assistant. One was the derivative of the water depth. The other was a threshold sensor to look at when the derivative was over (well, actually under, as it was negative) a certain value.