Need precise seconds of switch ON state from history statistics

hi.

how did you manage to change into seconds?

original code:

    def pretty_duration(hours)
        Format a duration in days, hours, minutes, seconds.
        seconds = int(3600  hours)
        if days  0
            return %dd %dh %dm % (days, hours, minutes)
        if hours  0
            return %dh %dm % (hours, minutes)
        return %dm % minutes 

what shall we delete?

tnx

In my opinion…Something like this is much better done on the switch device itself.
Then report the data to HA as soon as the event has completed.

If you were using a Tasmota switch you could do this with ‘rules’ I feel certain.

Something like this I think?
Rule 1 (triggered by the switch turning on) would start the timer and save the elapsed time to a variable.
On the switch turning off Rule 2 would ‘publish’ the elapsed time as a sensor value.

Thats the way I would try to tackle that anyway.

@novitibo

Make a custom_component from history_stats.py by copying it to history_stats_in_seconds.py

Then open history_stats_in_seconds.py and search for the following section and remark out:

    @staticmethod
    def pretty_duration(hours):
        """Format a duration in days, hours, minutes, seconds."""
        seconds = int(hours)
#        days, seconds = divmod(seconds, 86400)
#        hours, seconds = divmod(seconds, 3600)
#        minutes, seconds = divmod(seconds, 60)
#        if days > 0:
#            return '%dd %dh %dm' % (days, hours, minutes)
#        elif hours > 0:
#            return '%dh %dm' % (hours, minutes)
        return seconds

Then where you need the default behaviour, you can still call “history_stats” in your YAML config files, but when you need history in seconds, you just call “history_stats_in_seconds” in your platform: declaration.

Like this:

  - platform: history_stats_in_seconds
    name: Reefdoser1 Pump1 Dosage Today
    entity_id: switch.reefdoser1_pump1
    state: 'on'
    start: '{{ as_timestamp(now().replace(hour=0).replace(minute=0).replace(second=0)) }}'
    end: '{{ as_timestamp(now()) }}'
    unit_of_measurement: 's'
2 Likes

Unfortunately, that doesn’t work out nearly as accurate as the way I do it now. The reason for having history_stats_in_seconds custom component is so HASS can know in (near) real time when to flip the off switch. If for some reason, the switch doesn’t toggle off despite the command being sent, I then raise an alarm condition & take other automated actions.

For instance, I’ve already had it that a cat went mountaineering on the rack that holds my AquaDosers (controlled by the 4 way Sonoff) and activated one of the switches to a pump. In my setup now, my HASS saw this manual flip of the pump & shutdown the pump & raised an audible alarm to the Cat-ccident. :wink:

To achieve that the way you’re talking about, along with the flexibility of configuration & monitoring alarms, I think it would have to be a bit more complicated setup / code on both sides of the equation.

The way I have it now, let’s me get both pretty accurate ( can handle say just 68ml of dosing per day, split up 24 times in a single day) with just about +/- 1ml variance per day.

I have a total of 10 Sonoff controlled dosing pumps this way for a year, and been very pleased with the performance of it.

@cowboy Ok it sounds like you have developed a fairly comprehensive control system for what sounds like a very critical task there. Any chance of posting a photo of your dosing pump installation?
Do you have all your dosing equipment running on UPS protected supply as well?
What about your Hass server and network are they also on UPS protected supply?

Cheers for your reply!

Posted a whole HOWTO last year.

And the UPS answer and the reason I ranked it a lower priority is explained here. In short, it only covers one element of risk failure. So I embraced a solution that could cover for more types of failures than just power failures, offering a higher return on investment with a better fail-proof design.

Aha…I didn’t realise that was you…I have had a quick look at that project “Going to next level” but never really studied it all as it isn’t what I am doing…maybe I should have a better look I think.
Never seen the “Peristaltic” one before so I’ll study up on both of them.

Cheers!

how can I use the rules to get time how long the sensor measures energy > 0kWh?
need to calculate pellets loader consumption. grams/minute

tnx!

@novitibo In the rules document I believe there is an example which could be reworked to give you the time a sensor measures energy >0 I believe

The trigger would need to be in the form:

[SensorName]#[ValueName][comparison][value]


So ON [SensorName]#state>0 DO Var1 %timestamp% ENDON
And ON [SensorName]#state<1 DO Var2 %timestamp% ENDON

The final trigger and calculation of elapsed time I would need to spend some time on but note that the result is published so there is a great place to start.
EDIT: I think it needs to be based on %time% not %timestamp%. %time% is minutes from midnight.

ON mqtt#connected DO Publish stat/your_topic/your_sensor_name {"From":"%Var1%","To":"%Var2%"} ENDON

NOTE: That this is all ‘appended’ to be the one rule.

Example found at the bottom of the page here

ON wifi#disconnected DO Var1 %timestamp% ENDON
ON wifi#connected DO Var2 %timestamp% ENDON
ON mqtt#connected DO Publish stat/topic/BLACKOUT {"From":"%Var1%","To":"%Var2%"} ENDON

The final published ‘string’ just needs to be reworked to get a time value in minutes…not something I have done as yet but I would love to see what you come up with?

Hope that helps!

It works perfectly!
Tasmota rules:

Rule1 ON Energy#Power>0 DO Backlog Publish stat/loader/on {"Time":"%timestamp%"}; Rule2 1 ENDON 
Rule2 ON Energy#Power==0 DO Backlog Publish stat/loader/off {"Time":"%timestamp%"}; Rule2 0 ENDON

Home assistant sensors:

- platform: mqtt
  name: "loaderon"
  state_topic: "stat/loader/on"
  value_template: "{{value_json.Time}}"
  
- platform: mqtt
  name: "loaderoff"
  state_topic: "stat/loader/off"
  value_template: "{{value_json.Time}}"  
  
- platform: template
  sensors:
    loadertime:
      value_template: "{{ (as_timestamp(states.sensor.loaderoff.state)) | int  - (as_timestamp(states.sensor.loaderon.state)) | int}}"
      unit_of_measurement: "s"
  
- platform: history_stats
  name: loadertimeall
  entity_id: input_boolean.loadertime
  state: 'on'
  type: time
  start: '{{ 0 }}'
  end: '{{ now() }}' 

and automations:

- alias: loadertimeon
  trigger:
    platform: numeric_state
    entity_id: sensor.loadertime  
    below: 0         
  action:
    - service: input_boolean.turn_on
      entity_id: input_boolean.loadertime    
- alias: loadertimeoff
  trigger:
    platform: numeric_state
    entity_id: sensor.loadertime  
    above: 0    
  action:
    - service: input_boolean.turn_off
      entity_id: input_boolean.loadertime  

THANK U ALL!

2 Likes

@novitibo Well done!

I would be interested to see if the Tasmota device could do the maths as well though but your solution is neat.

Yeah, I tried with

{"From":"%Var1%","To":"%Var2%"}

but value of From and To did not include any timestamp. Any clue?

1 Like

@novitibo If I get time I will try this example you have working because there are actually a few areas I could probably use something like this. Cheers!

RE: this does not include values {“From”:"%Var1%",“To”:"%Var2%"}

Could you post the whole Rule you developed please?

In the meantime…If I find anything I will post again.

I used this alternative (splitted into two rules and then calculated in home assistant):

Rule1 ON Energy#Power>0 DO Backlog Publish stat/loader/on {"Time":"%timestamp%"}; Rule2 1 ENDON 
Rule2 ON Energy#Power==0 DO Backlog Publish stat/loader/off {"Time":"%timestamp%"}; Rule2 0 ENDON
1 Like

@novitibo yes I saw that above and thats what I am going to try out when I get time (I like how you use the rule to change whether the other rule is on or not as well).

But what I was looking for was how you were using the below snippet you mentioned?
And if you could post the whole rule it was in?

Cheers!

Example:

ON wifi#disconnected DO Var1 %timestamp% ENDON
ON wifi#connected DO Var2 %timestamp% ENDON
ON mqtt#connected DO Publish stat/topic/BLACKOUT {"From":"%Var1%","To":"%Var2%"} ENDON

@novitibo It works with a very basic trigger:

ON POWER1#state=0 DO Var1 %timestamp% ENDON

and in the console I then see

14:43:34 RUL: POWER1#STATE=0 performs "Var1 2019-10-21T14:43:34"
14:43:34 MQT: stat/sonoff33/RESULT = {"Var1":"2019-10-21T14:43:34"}

So I moved on and have now developed this:

`
ON POWER1#state=1 DO Var2 %timestamp% ENDON
ON POWER1#state=0 DO Var1 %timestamp% ENDON
ON Rules#Timer=1 DO Var1 ENDON
ON Rules#Timer=1 DO Var2 ENDON

`
NOTE1 Above is all ‘appended’ to become one rule
NOTE2: This is just testing on a movement sensor I have which is good because its outside and the wind is turning it on and off atm…very handy!
NOTE3: I use the ruletimer as a trigger so I can manually trigger it by inputting:

ruletime 3 at the console…then that just quickly counts down to ‘1’

Sonoff Web Console output:
PS: Dont be confused by the other output sending EVENT’s to sonnoff13…just look for the Var1 and Var2 output

17:18:22 MQT: stat/sonoff33/POWER1 = ON
17:18:22 RUL: POWER1#STATE=1 performs "backlog publish cmnd/sonoff13/Event Movement_Patio"
17:18:22 RUL: POWER1#STATE=1 performs "Var2 2019-10-21T17:18:22"
17:18:22 MQT: stat/sonoff33/RESULT = {"Var2":"2019-10-21T17:18:22"}
17:18:22 MQT: cmnd/sonoff13/Event = Movement_Patio
17:18:24 MQT: stat/sonoff33/RESULT = {"POWER1":"OFF"}
17:18:24 MQT: stat/sonoff33/POWER1 = OFF
17:18:25 RUL: POWER1#STATE=0 performs "Var1 2019-10-21T17:18:25"
17:18:25 MQT: stat/sonoff33/RESULT = {"Var1":"2019-10-21T17:18:25"}
17:18:46 MQT: stat/sonoff33/RESULT = {"POWER1":"ON"}
17:18:46 MQT: stat/sonoff33/POWER1 = ON
17:18:46 RUL: POWER1#STATE=1 performs "backlog publish cmnd/sonoff13/Event Movement_Patio"
17:18:46 RUL: POWER1#STATE=1 performs "Var2 2019-10-21T17:18:46"
17:18:46 MQT: stat/sonoff33/RESULT = {"Var2":"2019-10-21T17:18:46"}
17:18:46 MQT: cmnd/sonoff13/Event = Movement_Patio
17:18:48 MQT: stat/sonoff33/RESULT = {"POWER1":"OFF"}
17:18:48 MQT: stat/sonoff33/POWER1 = OFF
17:18:48 RUL: POWER1#STATE=0 performs "Var1 2019-10-21T17:18:48"
17:18:48 MQT: stat/sonoff33/RESULT = {"Var1":"2019-10-21T17:18:48"}
17:19:19 RSL: tele/sonoff33/STATE = {"Time":"2019-10-21T17:19:19","Uptime":"7T02:20:30","Vcc":3.462,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"POWER1":"OFF","POWER2":"OFF","POWER3":"OFF","POWER4":"OFF","POWER5":"OFF","Wifi":{"AP":1,"SSId":"Bugwire","BSSId":"E0:3F:49:72:B8:E0","Channel":6,"RSSI":92,"LinkCount":10,"Downtime":"0T00:00:35"}}
17:19:19 MQT: tele/sonoff33/SENSOR = {"Time":"2019-10-21T17:19:19","Switch1":"OFF","Switch5":"OFF"}17:34:00 MQT: stat/sonoff33/RESULT = {"Var2":"2019-10-21T17:34:00"}
17:34:00 MQT: cmnd/sonoff13/Event = Movement_Patio
17:34:02 MQT: stat/sonoff33/RESULT = {"POWER1":"OFF"}
17:34:02 MQT: stat/sonoff33/POWER1 = OFF
17:34:02 RUL: POWER1#STATE=0 performs "Var1 2019-10-21T17:34:02"
17:34:02 MQT: stat/sonoff33/RESULT = {"Var1":"2019-10-21T17:34:02"}
17:34:19 RSL: tele/sonoff33/STATE = {"Time":"2019-10-21T17:34:19","Uptime":"7T02:35:30","Vcc":3.462,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"POWER1":"OFF","POWER2":"OFF","POWER3":"OFF","POWER4":"OFF","POWER5":"OFF","Wifi":{"AP":1,"SSId":"Bugwire","BSSId":"E0:3F:49:72:B8:E0","Channel":6,"RSSI":100,"LinkCount":10,"Downtime":"0T00:00:35"}}
17:34:19 MQT: tele/sonoff33/SENSOR = {"Time":"2019-10-21T17:34:19","Switch1":"OFF","Switch5":"OFF"}
17:35:30 MQT: stat/sonoff33/RESULT = {"POWER1":"ON"}
17:35:30 MQT: stat/sonoff33/POWER1 = ON
17:35:30 RUL: POWER1#STATE=1 performs "backlog publish cmnd/sonoff13/Event Movement_Patio"
17:35:30 RUL: POWER1#STATE=1 performs "Var2 2019-10-21T17:35:30"
17:35:30 MQT: stat/sonoff33/RESULT = {"Var2":"2019-10-21T17:35:30"}
17:35:30 MQT: cmnd/sonoff13/Event = Movement_Patio
17:35:32 MQT: stat/sonoff33/RESULT = {"POWER1":"OFF"}
17:35:32 MQT: stat/sonoff33/POWER1 = OFF
17:35:32 RUL: POWER1#STATE=0 performs "Var1 2019-10-21T17:35:32"
17:35:32 MQT: stat/sonoff33/RESULT = {"Var1":"2019-10-21T17:35:32"}
17:39:19 RSL: tele/sonoff33/STATE = {"Time":"2019-10-21T17:39:19","Uptime":"7T02:40:30","Vcc":3.462,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"POWER1":"OFF","POWER2":"OFF","POWER3":"OFF","POWER4":"OFF","POWER5":"OFF","Wifi":{"AP":1,"SSId":"Bugwire","BSSId":"E0:3F:49:72:B8:E0","Channel":6,"RSSI":90,"LinkCount":10,"Downtime":"0T00:00:35"}}
17:39:19 MQT: tele/sonoff33/SENSOR = {"Time":"2019-10-21T17:39:19","Switch1":"OFF","Switch5":"OFF"}
17:39:22 MQT: stat/sonoff33/RESULT = {"POWER1":"ON"}
17:39:22 MQT: stat/sonoff33/POWER1 = ON
17:39:22 RUL: POWER1#STATE=1 performs "backlog publish cmnd/sonoff13/Event Movement_Patio"
17:39:22 RUL: POWER1#STATE=1 performs "Var2 2019-10-21T17:39:22"
17:39:22 MQT: stat/sonoff33/RESULT = {"Var2":"2019-10-21T17:39:22"}
17:39:23 MQT: cmnd/sonoff13/Event = Movement_Patio
17:39:25 MQT: stat/sonoff33/RESULT = {"POWER1":"OFF"}
17:39:25 MQT: stat/sonoff33/POWER1 = OFF
17:39:25 RUL: POWER1#STATE=0 performs "Var1 2019-10-21T17:39:25"
17:39:25 MQT: stat/sonoff33/RESULT = {"Var1":"2019-10-21T17:39:25"}
17:40:24 MQT: stat/sonoff33/RESULT = {"POWER1":"ON"}
17:40:24 MQT: stat/sonoff33/POWER1 = ON
17:40:24 RUL: POWER1#STATE=1 performs "backlog publish cmnd/sonoff13/Event Movement_Patio"
17:40:24 RUL: POWER1#STATE=1 performs "Var2 2019-10-21T17:40:24"
17:40:24 MQT: stat/sonoff33/RESULT = {"Var2":"2019-10-21T17:40:24"}
17:40:25 MQT: cmnd/sonoff13/Event = Movement_Patio
17:40:27 MQT: stat/sonoff33/RESULT = {"POWER1":"OFF"}
17:40:27 MQT: stat/sonoff33/POWER1 = OFF
17:40:27 RUL: POWER1#STATE=0 performs "Var1 2019-10-21T17:40:27"
17:40:27 MQT: stat/sonoff33/RESULT = {"Var1":"2019-10-21T17:40:27"}
17:40:38 MQT: stat/sonoff33/RESULT = {"POWER1":"ON"}
17:40:38 MQT: stat/sonoff33/POWER1 = ON
17:40:38 RUL: POWER1#STATE=1 performs "backlog publish cmnd/sonoff13/Event Movement_Patio"
17:40:38 RUL: POWER1#STATE=1 performs "Var2 2019-10-21T17:40:38"
17:40:38 MQT: stat/sonoff33/RESULT = {"Var2":"2019-10-21T17:40:38"}
17:40:38 MQT: cmnd/sonoff13/Event = Movement_Patio
17:40:40 MQT: stat/sonoff33/RESULT = {"POWER1":"OFF"}
17:40:40 MQT: stat/sonoff33/POWER1 = OFF
17:40:40 RUL: POWER1#STATE=0 performs "Var1 2019-10-21T17:40:40"
17:40:40 MQT: stat/sonoff33/RESULT = {"Var1":"2019-10-21T17:40:40"}

Triggering with ruletimer 3

08:32:28 CMD: ruletimer 3
08:32:28 MQT: stat/sonoff33/RESULT = {"T1":3,"T2":0,"T3":0,"T4":0,"T5":0,"T6":0,"T7":0,"T8":0}
08:32:31 RUL: RULES#TIMER=1 performs "Var1"
08:32:31 MQT: stat/sonoff33/RESULT = {"Var1":"2019-10-22T08:31:18"}
08:32:31 RUL: RULES#TIMER=1 performs "Var2"
08:32:31 MQT: stat/sonoff33/RESULT = {"Var2":"2019-10-22T08:31:15"}

Example misleading

I believe the example is misleading in how this must be written up as a rule.
I have worked on this since last night and just finally figured out how to do it a short while ago. Yeah…I’m a bit slow!

Have a go yourself and see if you can use this as I can see Var and Mem values being useful (Mem retains over a reboot) which is very handy I think.

Maths?

Also…it appears that maths is not possible BUT I HOPE I’M WRONG ABOUT THAT?

I am also interested in measuring duration in seconds. I have a well pump monitor, and measure the amount of time the pump is on. This can be converted (approximately) to litres of water pumped, but it would only be useful if I can measure seconds and not 0.01 hour resolution.

It would be most useful if the history_stats could be configured to do seconds.

I have now created a patch to history_stats giving the option of returning the history time in seconds and then made a pull request. Hopefully this will get in to a future release soon.

For applications like the one described in this thread, or my own pump monitor where you have to calibrate liquid volume flow, and then multiply by a higher resolution value, this will be useful.

Decimal hours was not a good option for me.

Hi all, I changed the history_stats in seconds, and copied it in the custom components folder, but my configuration still won’t accept this file i keep getting messages, : "Platform error sensor.history_stats_in_seconds - No module named ‘custom_components.history_stats_in_seconds.sensor’; ‘custom_components.history_stats_in_seconds’ is not a package.
can you point me in the right direction i am fairly new to HA