Lowest temperature during night - how?

I’d like to list the lowest temperature seen during the night (2300-0700) and present it to the user (me) at 0700.

I’ve read multiple posts here but I haven’t seen a working configuration yet. I had previously hacked together a solution in node red which basically queried the recorder API and then just extracted the lowest value, but I’d like to redo this in Home Assistant native (due to reasons).

I tried putting together a SQL query to use a SQL sensor, but sqlite proved to require more and more workarounds so I eventually gave up, as the results were also not correct (probably my query being in the wrong, tho).

How have others done this?

Hi, you can use the statistics card to quickly set up using your sensor, and set it to show the min temp for the day. In this case it would be from midnight, but you could adjust the timespan via YAML i assume.

If you wanted to use the value in automations or send via notification, you would have to use the Statistics Integration. I haven’t set this up myself, but it seems to be pretty straightforward through the docs.

This is basically what I use, you can set the reset time to whatever you want. Where I live it is pretty rare for the lowest temp to occur prior to midnight, so that’s what I use

template:
  - trigger:
      - platform: time
        at: "00:00"
        id: reset
      - platform: state
        not_to:
          - unknown
          - unavailable
        entity_id:
          - sensor.outdoor_temp_1 
          - sensor.outdoor_temp_2
    sensor:
      - name: Outside Temperature Daily Min
        unit_of_measurement: "°F"
        unique_id: outside_temp_daily_min_001
        state: |
          {% set source = 
          ('sensor.outdoor_temp_1', 'sensor.outdoor_temp_2')
          | select('has_value') | map('states')
          | select('is_number') | map('round', 1) | min %}
          {% if trigger.id == 'reset' %}
            {{ source }}
          {% else %}
            {% set current = (this.state or trigger.to_state.state) | float(source) %}
            {{ [source, current] | min }}
          {% endif %}

I’m no SQL expert, but I think the following should work if you’re only dealing with a single sensor and really only interested in the value for your morning announcement, a hacky SQL query would be:

SELECT
  states.state
FROM
  states
  INNER JOIN states_meta ON
    states.metadata_id = states_meta.metadata_id
WHERE
  states_meta.entity_id = 'sensor.outside_temp'
  AND last_updated_ts >= strftime('%s', 'now', '-8 hours')
ORDER BY
  CAST(states.state as numeric) ASC
LIMIT 1;

Or, for the defined time span:

SELECT
  states.state
FROM
  states
  INNER JOIN states_meta ON
    states.metadata_id = states_meta.metadata_id
WHERE
  states_meta.entity_id = 'sensor.outside_temp'
  AND last_updated_ts >= strftime('%s', 'now', 'start of day',  '-1 hours')
  AND last_updated_ts <= strftime('%s', 'now', 'start of day',  '+7 hours')
ORDER BY
  CAST(states.state as numeric) ASC
LIMIT 1;

start of day is UTC so you need to adjust the hours values by adding the inverse of your timezone offset.

EDIT: Updated SQL queries to convert state strings to numbers.

1 Like

Thank you very much! I’m going to start with your template sensor even though it’s not exactly what I had in mind.

I tried the SQL sensors and they actually didn’t return the correct results, which is intriguing. :slight_smile:

[core-ssh config]$ sqlite3 home-assistant_v2.db 
SQLite version 3.44.2 2023-11-24 11:41:44
Enter ".help" for usage hints.
sqlite> SELECT
  states.state
FROM
  states
  INNER JOIN states_meta ON
    states.metadata_id = states_meta.metadata_id
WHERE
  states_meta.entity_id = 'sensor.temp_sensor_1_temperatur_garage_utomhus_ds18b20'
  AND last_updated_ts >= strftime('%s', 'now', '-8 hours')
ORDER BY
  states.state ASC
LIMIT 1;
-1.4

If I look at the graph for the sensor, the lowest temperature the last 8 hours (I’m in UTC+1) it should have returned something like -7.6 C whereas -1.4 C is the latest value.

When I tried constructing the query myself (very similar to yours, but I think I used a subquery instead of a join due to reasons) I noticed similar issues. I also had a lot of issues with float validation so I gave up…

State is always a string, so ‘strange’ ordering is to be expected.

2 Likes

As @francisp pointed out, I neglected to cast the state to a numeric value. I have addressed that in my original response.

I like the trigger-based template solution. I just recently started experimenting with those and they have the potential to really cut down on the number of automations I use, along with those templates I define just to extract a state from attributes of other sensors.

Thanks for posting that example. It can be a real struggle figuring out what does and doesn’t work with these trigger-based templates.

Yes, that did the trick - thank you very much!

In case anyone else is looking for something similar, this is how I did it!

SQL query, replace the sensor(s) in the WHERE clause with your own:

SELECT
  states.state,
  states.last_updated_ts AS last_updated_ts
FROM
  states
  INNER JOIN states_meta ON
    states.metadata_id = states_meta.metadata_id
WHERE
  (
    states_meta.entity_id = 'sensor.temp_sensor_1_temperatur_garage_utomhus_ds18b20'
    OR states_meta.entity_id = 'sensor.bedroom_temperature_2'
  )
  AND last_updated_ts >= strftime('%s', 'now', 'start of day',  '-1 hours')
  AND last_updated_ts <= strftime('%s', 'now', 'start of day',  '+7 hours')
ORDER BY
  CAST(states.state as numeric) ASC
LIMIT 1;

Copy the query, go to Home Assistant. Add an integration, search for SQL.

In the Settings popup:

  • Database URL, leave blank to use the default database
  • Column, type state
  • Query, paste the above
  • Unit of measurement, either °C or °F but this field is optional
  • State class, set to measurement to keep it long-term

Press save.

This will now update every 30s by default, which is a bit wasteful but not terrible. If you want to make this less wasteful, you can disable auto polling for the integration and build an automation that updates the entity (service homeassistant.update_entity) when you want it to - but that is left as an excerise for the reader. :slight_smile:

FWIW I had a similar need (I think): Every morning at 7 am sending a notification if the overnight temperature dipped bellow -2 (road might be icey)

- platform: statistics
  name: "Overnight Low Garden Temperature"
  entity_id: sensor.weather_station_outdoor_temperature
  state_characteristic: value_min
  max_age:
    hours: 8

The sensor is only “correct” at 7am when I send the notification but that was all I needed

1 Like