Getting the three highest values from a sensor

Hello.

I am trying to get the three highest readings from one energy sensor into three new sensors. The readings must be from the last month. I’ve tried with the statistics sensor, but I can only create a sensor with the highest max value. I also believe that the data is from the last 30 days, not monthly.

  - platform: statistics
    name: "Hourly consumption top 1"
    entity_id: sensor.accumulated_consumption_current_hour
    state_characteristic: value_max
    max_age:
      days: 30

Hourly consumption top 2?
Hourly consumption top 3?

Don’t know if this is even possible? Sorry for bad English

Do you store a month off data in your recorder database?

The default is only 10 days. And the stats sensor uses this database for its calculations.

If you do store that much, then one way might be to use three SQL sensors to query the recorder database to get the last months data, sort it by value then pick the 1st, 2nd and 3rd values in each sensor.

I have no idea what the syntax of the query would be. Maybe an SQL wizard here on the forum can help.

Thanks for reply.
I think the recorder setting was default. Tried this in configuration.yaml:

recorder:
  purge_keep_days: 30

Hope this works.
Will this slow down home assistant and how much storage space do I need? HA runs on a raspberry pi 3 with around 30 GB of free space.
I will look into SQL-sensors.

Your other alternative is to record them going forwards with an automation. When you say “from the last month” do you mean “in the last 30 days” or “during the previous calendar month to the current one”?

I mean the current calendar month

So set up three input_number helpers with initial value zero and this automation should handle things, I think. Not tested in full but individual bits seem to work.

trigger:
  - platform: state
    entity_id: sensor.accumulated_consumption_current_hour
  - platform: time
    at: "00:01:00"
condition:
  - or:
    - "{{ trigger.platform == 'state' and states('sensor.accumulated_consumption_current_hour')|float(0) > states('input_number.consumption_3')|float(0) }}"
    - "{{ trigger.platform == 'time' and now().day == 1 }}"
action:
  - choose:
      - conditions: "{{ trigger.platform == 'time' }}"
        sequence:
          - service: input_number.set_value
            data:
              entity_id: input_number.consumption_3
              value: 0
          - service: input_number.set_value
            data:
              entity_id: input_number.consumption_2
              value: 0
          - service: input_number.set_value
            data:
              entity_id: input_number.consumption_1
              value: 0
    default:
      - service: input_number.set_value
        data:
          entity_id: input_number.consumption_3
          value: >
            {{ ([states('sensor.accumulated_consumption_current_hour')|float(0),
                 states('input_number.consumption_3')|float(0),
                 states('input_number.consumption_2')|float(0),
                 states('input_number.consumption_1')|float(0)]
                 |sort|reverse|list)[2] }}
      - service: input_number.set_value
        data:
          entity_id: input_number.consumption_2
          value: >
            {{ ([states('sensor.accumulated_consumption_current_hour')|float(0),
                 states('input_number.consumption_3')|float(0),
                 states('input_number.consumption_2')|float(0),
                 states('input_number.consumption_1')|float(0)]
                 |sort|reverse|list)[1] }}
      - service: input_number.set_value
        data:
          entity_id: input_number.consumption_1
          value: >
            {{ ([states('sensor.accumulated_consumption_current_hour')|float(0),
                 states('input_number.consumption_3')|float(0),
                 states('input_number.consumption_2')|float(0),
                 states('input_number.consumption_1')|float(0)]
                 |sort|reverse|list)[0] }}

It should populate the helpers in the first three hours, and then start doing so selectively when new higher values come in. Resets on the first of the month.

1 Like

And you don’t even want to know when those peaks happened?
Just wondering what usage you could do with such (pretty much random) energy statistics…

Probably looks very useless, but this is how the electricity bill is calculated in my country. If the average of 3 peaks every hour in a month is greater than 2/5/10/15/20 etc. kwh, the electricity bill will increase.

2 Likes

Thank you very much! I will definitely try this out.

Made the helpers and trying to input the automation (from UI in Yaml). Getting this message when trying to save:

Message malformed: Unable to determine action @ data['action'][0]['default'][0]

Apologies, there shouldn’t have been a sequence under default. Edited above.

Automation is running now. I have no idea if it works as it should yet. Time will tell. Input number 1 is now increasing.

Thanks for your help!

Oh hang on. Does your sensor continually increase to the end of each hour and then reset to zero? If it does, this might need rethinking as a new peak value will wipe out the second and third peaks on the way up.

This might work as a fix: it triggers when the accumulated sensor drops to zero and uses the value it had immediately beforehand in the comparison:

trigger:
  - platform: state
    entity_id: sensor.accumulated_consumption_current_hour
    to: 0
  - platform: time
    at: "00:01:00"
condition:
  - or:
    - "{{ trigger.platform == 'state' and trigger.from_state.state|float(0) > states('input_number.consumption_3')|float(0) }}"
    - "{{ trigger.platform == 'time' and now().day == 1 }}"
action:
  - choose:
      - conditions: "{{ trigger.platform == 'time' }}"
        sequence:
          - service: input_number.set_value
            data:
              entity_id: input_number.consumption_3
              value: 0
          - service: input_number.set_value
            data:
              entity_id: input_number.consumption_2
              value: 0
          - service: input_number.set_value
            data:
              entity_id: input_number.consumption_1
              value: 0
    default:
      - service: input_number.set_value
        data:
          entity_id: input_number.consumption_3
          value: >
            {{ ([trigger.from_state.state|float(0),
                 states('input_number.consumption_3')|float(0),
                 states('input_number.consumption_2')|float(0),
                 states('input_number.consumption_1')|float(0)]
                 |sort|reverse|list)[2] }}
      - service: input_number.set_value
        data:
          entity_id: input_number.consumption_2
          value: >
            {{ ([trigger.from_state.state|float(0),
                 states('input_number.consumption_3')|float(0),
                 states('input_number.consumption_2')|float(0),
                 states('input_number.consumption_1')|float(0)]
                 |sort|reverse|list)[1] }}
      - service: input_number.set_value
        data:
          entity_id: input_number.consumption_1
          value: >
            {{ ([trigger.from_state.state|float(0),
                 states('input_number.consumption_3')|float(0),
                 states('input_number.consumption_2')|float(0),
                 states('input_number.consumption_1')|float(0)]
                 |sort|reverse|list)[0] }}

Yes, the sensor increases until the end of each hour. Unfortunately, the value is slightly higher when the next hour starts, if consumption is high. So I tried using timepattern. This seems to work great. Have also tested the reset function.

Many thanks for the help. Here is the working automation in case anyone want something similar:

trigger:
  - platform: time
    at: "00:01:00"
  - platform: time_pattern
    minutes: "59"
    seconds: "59"
condition:
  - or:
      - >-
        {{ trigger.platform == 'time_pattern' and
        states('sensor.accumulated_consumption_current_hour')|float(0)
        > states('input_number.timeforbruk_topp_3')|float(0) }}
      - "{{ trigger.platform == 'time' and now().day == 1 }}"
action:
  - choose:
      - conditions: "{{ trigger.platform == 'time' }}"
        sequence:
          - service: input_number.set_value
            data:
              entity_id: input_number.timeforbruk_topp_3
              value: 0
          - service: input_number.set_value
            data:
              entity_id: input_number.timeforbruk_topp_2
              value: 0
          - service: input_number.set_value
            data:
              entity_id: input_number.timeforbruk_topp_1
              value: 0
    default:
      - service: input_number.set_value
        data:
          entity_id: input_number.timeforbruk_topp_3
          value: >
            {{
            ([states('sensor.accumulated_consumption_current_hour')|float(0),
                 states('input_number.timeforbruk_topp_3')|float(0),
                 states('input_number.timeforbruk_topp_2')|float(0),
                 states('input_number.timeforbruk_topp_1')|float(0)]
                 |sort|reverse|list)[2] }}
      - service: input_number.set_value
        data:
          entity_id: input_number.timeforbruk_topp_2
          value: >
            {{
            ([states('sensor.accumulated_consumption_current_hour')|float(0),
                 states('input_number.timeforbruk_topp_3')|float(0),
                 states('input_number.timeforbruk_topp_2')|float(0),
                 states('input_number.timeforbruk_topp_1')|float(0)]
                 |sort|reverse|list)[1] }}
      - service: input_number.set_value
        data:
          entity_id: input_number.timeforbruk_topp_1
          value: >
            {{
            ([states('sensor.accumulated_consumption_current_hour')|float(0),
                 states('input_number.timeforbruk_topp_3')|float(0),
                 states('input_number.timeforbruk_topp_2')|float(0),
                 states('input_number.timeforbruk_topp_1')|float(0)]
                 |sort|reverse|list)[0] }}