I’ve wanted to track heating degree days for a while. It’s come up before, like here, here and here. I took some of these ideas and came up with my own solution.
I decided to go for a real-time calculation, rather than simply taking the mean between the high and low for the day. I created an automation which triggers each time the temperature changes. This automation calculates the following:
- What portion of the day has elapsed since the last time the temperature changed.
- The “old” temperature which was recorded at the start of this period.
- The number of degrees above the base temperature.
- The number of degree days experienced during this time period.
This value is added to an input_number
which keeps a running total for the day.
I already have an automation which records my heating system daily runtime data. To this I added two actions; save this daily heating degree days number, and zero it out for the next day.
The first step is to create an input_number in configuration.yaml to store the accumulated heating degree days:
input_number:
# Store heating degree days today
heating_dd:
name: "Heating Degree Days"
min: 0
max: 999
step: 0.1
mode: box
unit_of_measurement: "°F"
Next, the automation to update that number each time the temperature changes:
- id: id_heating_degree_days
alias: Heating Degree Days
trigger:
- platform: state
entity_id: sensor.nws_currenttemp
condition:
- condition: template
value_template: "{{ trigger.from_state.state|int < 65 }}"
action:
- service: input_number.set_value
target:
entity_id: input_number.heating_dd
data:
value: >
{% set elapsed_d = ((as_timestamp(trigger.to_state.last_changed) - as_timestamp(trigger.from_state.last_changed)) / 60) / (24 * 60) %}
{% set old_temp = (trigger.from_state.state | float) %}
{% set delta_h = 65 - old_temp %}
{% set partial_hdd = delta_h * elapsed_d %}
{% set new_hdd = (states("input_number.heating_dd") | float) + partial_hdd %}
{{ new_hdd }}
Yes, I know all the set statements are unnecessary. I tried doing it all in one long calculation, but there were so many expressions nested so deep in parenthesis that it was hard to follow.
That should be enough to get anyone started. I’ll fill in some more details in another post.