Many thanks for your help! I removed the spaces, but the sensor is still showing up as unavailable.
Any ideas?
Many thanks for your help! I removed the spaces, but the sensor is still showing up as unavailable.
Any ideas?
I just realized that you need to replace “value_template” with “state”. I missed that earlier.
Thought you might find this interesting. I went from using Phil’s integration to your template to getting an actual illuminance sensor. Here’s a 5 day graph comparing your sensor to the physical illuminance sensor (weatherflow weather station if you’re curious). So I’m officially retiring the illuminance template now, but it did what it was supposed to do when I needed it. Thanks!
I spent a few hours trying to get this working but kept getting error:
UndefinedError: 'None' has no attribute 'last_updated'
.
It looks like states.sensor.time.last_updated.timestamp()
no longer works with my version of HA 2022.3.3. I tried changing the following:
{%- set right_now = states.sensor.time.last_updated.timestamp() %}
to
{%- set right_now = as_timestamp(now()) %}
And the sensor is now available, it’s midnight here and the value is 10 so I assume it’s working, will check in the morning.
I recall the intention of the use of sensor.time to give the template an entity to trigger an update when changed. There has been many changes to the way template work in Home Assistant since then, and this may be necessary no longer. When I tested both of your examples of code in the template developer tool, it says that the first one will update when sensor.time
changes. While as_timestamp(now())
triggers “updates at the start of each minute.”
P.S. I just confirmed it still works. However, I did have to define a sensor.time
.
sensor:
- platform: time_date
display_options:
- 'time'
I think you’re getting a little ahead of yourself here
Hahaha… oopsie daisy. Thank you. I corrected that.
P.S. I just confirmed it still works. However, I did have to define a sensor.time.
Thanks! I missed there’s a sensor required. I’ll try changing over to your original sensor, it was working for me but I was getting odd large spikes.
It can be normal. It completely depends on what the weather integration is returning as the current condition. This can change every time it updates.
Is there any reason I shouldn’t continue to use
{%- set right_now = now() | as_timestamp %}
It’s still working fine…
It’s still working fine…
No continue to use the original code is fine, I had to add the time_date sensor manually in order for it to work as @BrianHanifin mentioned above.
I have never used that. Is there a reason I should use {%- set right_now = as_timestamp(now()) %} when I have always used {%- set right_now = now() | as_timestamp %} and it has always worked correctly. I’m looking for a reason not a statement.
actually I meant to ask @BrianHanifin as I think we have discussed this exact thing before in this thread
What is the maximum lx detected by the phillips hue sensor ?
My aqara sensor is maxed out at 891 lx which is not sufficient
Thanks (I’m in France)
For anyone visiting in 2024, I converted this code to the “modern” Home Assistant format and verified it’s working. Some sun2 entity names had also changed and needed updating in the code.
Prerequisites:
# Outdoor Illumination - Home Assistant 2024
# This presumes you've set up sun2 and AccuWeather integrations with the location of 'home'
# Take this out if you're already using Time & Date integration
sensor:
- platform: time_date
display_options:
- 'time'
# pnbruckner's sensor component as a template.
# https://github.com/pnbruckner/ha-illuminance/blob/8ba9f76709a6cb1fee2a7b73edfff0507a21acad/custom_components/illuminance/sensor.py
# https://community.home-assistant.io/t/outdoor-illuminance-template-sensor
template:
- sensor:
- name: "Outdoor Illuminance Educated Guessor"
unique_id: 2
unit_of_measurement: "lx"
icon: "mdi:brightness-auto"
state: >-
{% set factors = namespace(condition='',sun='') %}
{#- Retrieve the current condition and normalize the value #}
{% set current_condition = states("weather.home") %}
{% set current_condition = current_condition|lower|replace("partly cloudy w/ ","")|replace("mostly cloudy w/ ","")|replace("freezing","")|replace("and","")|replace("-", " ")|replace("_", " ")|replace("(","")|replace(")","")|replace(" ", "") %}
{#- Assign a seemingly arbitrary number to the condition factor #}
{% set condition_factors = {
"10000": ("clear", "clearnight", "sunny", "windy", "exceptional"),
"7500": ("partlycloudy", "partlysunny", "mostlysunny", "mostlyclear", "hazy", "hazysunshine", "intermittentclouds"),
"2500": ("cloudy", "mostlycloudy"),
"1000": ("fog", "rainy", "showers", "pouring", "snowy", "snowyheavy", "snowyrainy", "flurries", "chanceflurries", "chancerain", "chancesleet", "drearyovercast", "sleet"),
"200": ("hail", "lightning", "tstorms")
} %}
{% for factor in condition_factors if current_condition in condition_factors[factor] %}
{% set factors.condition = factor %}
{% endfor %}
{#- Compute Sun Factor #}
{% set right_now = states.sensor.time.last_updated.timestamp() %}
{% set sunrise = states("sensor.home_sun_rising") | as_timestamp %}
{% set sunrise_begin = states("sensor.home_sun_dawn") | as_timestamp %}
{% set sunrise_end = sunrise + (40 * 60) %}
{% set sunset = states("sensor.home_sun_setting") | as_timestamp %}
{% set sunset_begin = sunset - (40 * 60) %}
{% set sunset_end = states("sensor.home_sun_dusk") | as_timestamp %}
{% if sunrise_end < right_now and right_now < sunset_begin %}
{% set factors.sun = 1 %}
{% elif sunset_end < right_now or right_now < sunrise_begin %}
{% set factors.sun = 0 %}
{% elif right_now <= sunrise_end %}
{% set factors.sun = (right_now - sunrise_begin) / (60*60) %}
{% else %}
{% set factors.sun = (sunset_end - right_now) / (60*60) %}
{% endif %}
{% set factors.sun = 1 if factors.sun > 1 else factors.sun %}
{# Take an educated guess #}
{% set illuminance = (factors.sun|float * factors.condition|float) | round %}
{% set illuminance = 10 if illuminance < 10 else illuminance %}
{{ illuminance }}
Actually, scratch that—while the code is correct in terms of registering the sensor in HA, the readings it gives are not accurate. I’m not sure whether it’s the original code, an integration of mine, or something else I changed, so proceed with caution.
Putting this here as i have just noticed the incorrect result i’ve been getting with this. With the help of AI i have this… It’s untested but seems more sensible:
My hunch was that it does not handle the fact that right_now
can be before next_rising
because it’s the prior evening to sunrise, so this takes that into account.
It also include sun elevation with it’s calculations.
{%- set factors = namespace(condition=0, sun=0) %}
{# Normalize current weather condition #}
{%- set current_condition = states("weather.openweathermap") %}
{%- set current_condition = current_condition | lower
| replace("-day", "") | replace("_day", "")
| replace("-night", "") | replace("_night", "")
| replace("and", "") | replace("-", " ") | replace("_", " ")
| replace("(", "") | replace(")", "") | replace(".", "")
| replace(" ", "") %}
{# Map condition to factor #}
{%- set condition_factors = {
"10000": ("clear", "clearnight", "sunny", "windy", "wind", "windyvariant", "exceptional"),
"7500": ("partlycloudy", "partlysunny", "mostlysunny", "mostlyclear", "hazy", "hazey", "hazysunshine", "intermittentclouds", "lightrain"),
"2500": ("cloudy", "mostlycloudy"),
"1000": ("fog", "foggy", "dust", "dusty", "rainy", "pouring", "rain", "lightshower", "lightshowers", "showers", "shower", "snowy", "snow", "snowyheavy", "snowyrainy", "flurries", "chanceflurries", "chancerain", "chancesleet", "drearyovercast", "sleet", "frost"),
"200": ("hail", "lightning", "lightningrainy", "tstorms", "thunderstorm", "storm", "stormy", "heavyshower", "heavyshowers", "tropicalcyclone")
} %}
{%- for factor, keywords in condition_factors.items() %}
{%- if current_condition in keywords %}
{%- set factors.condition = factor | int %}
{%- endif %}
{%- endfor %}
{%- if factors.condition == 0 %}
{%- set factors.condition = 2500 %}
{%- endif %}
{# Timezone-aware sun events #}
{%- set now_dt = now() %}
{%- set now_ts = now_dt.timestamp() %}
{%- set next_rising = state_attr('sun.sun', 'next_rising') | as_datetime | as_local %}
{%- set next_setting = state_attr('sun.sun', 'next_setting') | as_datetime | as_local %}
{%- set next_dawn = state_attr('sun.sun', 'next_dawn') | as_datetime | as_local %}
{%- set next_dusk = state_attr('sun.sun', 'next_dusk') | as_datetime | as_local %}
{%- set prev_rising = next_rising - timedelta(days=1) %}
{%- set prev_setting = next_setting - timedelta(days=1) %}
{%- set prev_dawn = next_dawn - timedelta(days=1) %}
{%- set prev_dusk = next_dusk - timedelta(days=1) %}
{# Corrected logic: pick the next event if now is between prev and next, else prev #}
{%- if now_dt >= prev_rising and now_dt < next_rising %}
{%- set sunrise = next_rising %}
{%- else %}
{%- set sunrise = prev_rising %}
{%- endif %}
{%- if now_dt >= prev_setting and now_dt < next_setting %}
{%- set sunset = next_setting %}
{%- else %}
{%- set sunset = prev_setting %}
{%- endif %}
{%- if now_dt >= prev_dawn and now_dt < next_dawn %}
{%- set dawn = next_dawn %}
{%- else %}
{%- set dawn = prev_dawn %}
{%- endif %}
{%- if now_dt >= prev_dusk and now_dt < next_dusk %}
{%- set dusk = next_dusk %}
{%- else %}
{%- set dusk = prev_dusk %}
{%- endif %}
{# Transition windows (40 minutes) #}
{%- set sunrise_end = sunrise + timedelta(minutes=40) %}
{%- set sunset_begin = sunset - timedelta(minutes=40) %}
{# Calculate sun factor #}
{%- if now_dt >= sunrise_end and now_dt <= sunset_begin %}
{%- set factors.sun = 1 %}
{%- elif now_dt >= dawn and now_dt < sunrise_end %}
{%- set factors.sun = (now_dt - dawn).total_seconds() / (sunrise_end - dawn).total_seconds() %}
{%- elif now_dt >= sunset_begin and now_dt <= dusk %}
{%- set factors.sun = (dusk - now_dt).total_seconds() / (dusk - sunset_begin).total_seconds() %}
{%- else %}
{%- set factors.sun = 0 %}
{%- endif %}
{# Clamp sun factor to [0, 1] #}
{%- if factors.sun > 1 %}
{%- set factors.sun = 1 %}
{%- elif factors.sun < 0 %}
{%- set factors.sun = 0 %}
{%- endif %}
{%- set sun_elev = state_attr('sun.sun', 'elevation') | float(0) %}
{%- if sun_elev <= -6 %}
{%- set elev_factor = 0 %}
{%- elif sun_elev >= 10 %}
{%- set elev_factor = 1 %}
{%- else %}
{%- set elev_factor = (sun_elev + 6) / 16 %}
{%- endif %}
{# Blend elevation factor with previous sun factor #}
{%- set factors.sun = (factors.sun + elev_factor) / 2 %}
{# Final illuminance estimate (lux) #}
{%- set illuminance = (factors.sun * factors.condition) | round %}
{%- if illuminance < 10 %}
{%- set illuminance = 0 %}
{%- endif %}
{{ illuminance }}