I have a weather station that sometimes loses its connection due to distance from the router.
All the values it posses turn to “unknown” for a few seconds, even a minute and it’s very annoying to see it on the UI.
Is there anything I can do to let it display the last known value (without cloning all the sensors using templates or something like that?)
Without knowing how it is integrated, no.
I’m not sure how you could really do this without templates. If it loses connection there’s not much you can do about it because the integration (presumably) is populating those sensors and you have no control, so a template weather device and/or a series of sensors is likely the only way to control it.
Thought that might be the case, how would one look, let’s say something like sensor.outside_temp?
I suppose you can do an if/else in the template but how do you set the last known value before it goes to unknown?
Use this.state
to get the last known value.
In the following example (a fragment of a Template Sensor), if the value of sensor.outside_temp
is not unknown
or unavailable
then that value is reported. Otherwise the Template Sensor uses its existing value (this.state
).
state: >
{% set x = states('sensor.outside_temp') %}
{{ x if has_value(x) else this.state | default(0, true) }}
The default
is there for this reason:
When you first create the Template Sensor, it won’t have an existing value for this.state
. So if at that moment sensor.outside_temp
has the bad luck of being unknown
or unavailable
then default
will be used to report 0
.
NOTE
Perhaps a better way to do this is to create a Trigger-based Template Sensor with a State Trigger that listens for changes to sensor.outside_temp
but ignores any state-change to unknown
or unavailable
(using the not_to
option). A Trigger-based Template Sensor retains its value after a restart.
template:
- trigger:
- platform: state
entity_id: sensor.outside_temp
not_to:
- unknown
- unavailable
sensor:
- name: Outside Temperature
state: '{{ trigger.to_state.state }}'
device_class: temperature
unit_of_measurement: '°C'
EDIT
Corrected typo.
This isn’t quite correct. A sensor could legitimately go unknown or unavailable. What we need is for HA not to declare a sensor unavailable or unknown across a reboot or restart for deep-sleeping ESP Home sensors that only report periodically. We need a user-settable time period without a report before a sensor state is set as unknown or unavailable. Of course, this could be set up with messy complicated maintenance intense helpers and global state variables but it should be built-in because HA restarts are SOP. I’m sure HA already has the last report time for every sensor. I have lots of integrated devices that maintain last-state across reboots. It’s the ESP Home API sensors that forget.
The logic would be something like save and report the last known state until changes or there is no update for xx seconds where xx can be 1 to 9999999
Can you identify the part of what I wrote that was incorrect? I don’t recall saying that unknown
or unavailable
are not legitimate states.
The way I read it, your trigger would ignore changes to unknown or unavailable. Without a set time period for a sensor to become unknown or unavailable, the concept is incomplete
What I posted wasn’t passing judgment on the legitimacy of unknown
or unavailable
, it was merely a means to fulfill sd_dracula’s requirement to report the ‘last known (numeric) value’ in lieu of those two states.
The weather station’s sensors can still report unknown
or unavailable
(thereby indicating a problem with the physical device and/or integration) but the suggested Template Sensor will, as per the OP’s choice, mask the occurrence by reporting the previous state
value.
So how would you create a template that does keep the last state for a set period of time but wouldn’t persist if the device was offline for whatever reason?
I don’t know of any way other than to store the value into a helper.
You can do all of this with trigger-based template sensors. Explain exactly what you want to happen.
For example, you can trigger off a sensor going offline:
- trigger:
- platform: state
entity_id: sensor.outside_temp
to:
- unknown
- unavailable
or off the state not changing for a given time:
- trigger:
- platform: state
entity_id: sensor.outside_temp
for: "00:10:00"
You can set id
s for these triggers and use them in the state-setting template. Test the last change of a sensor like this (last state change in seconds):
{{ (now() - states['sensor.ID']['last_changed']).total_seconds() }}
How you combine those depends on how your sensor behaves and what you want to achieve.
If anyone needs more specific support:
I solved it this way (according to your inspiration): updating the value to a numerical value every time the input sensor is updated. If the value has not changed for half an hour, the value is set to 0. I also created a frequent changing attribute here (time since last measurement) to feed the influxdb - in this case every 30 minutes - for a consistent display of the diagram (fill-below-to function in Grafana)
- trigger:
- platform: state
entity_id: sensor.symo_12_5_3_m_power_ac
not_to:
- unknown
- unavailable
id: online
- platform: state
entity_id: sensor.stromleistung_pv
for: 00:30:00
id: offline
sensor:
- name: Stromleistung PV
unique_id: "stromleistung_pv"
state_class: "measurement"
unit_of_measurement: "W"
device_class: "power"
state: >
{% if trigger.id == "online" %}
{{trigger.to_state.state}}
{% elif trigger.id == "offline" %}
{{0}}
{% endif %}
attributes: #für regelmäßige Werte in der Nacht
Letzter Messwert (h): >
{{ ((now().timestamp() - as_timestamp(states.sensor.stromleistung_pv.last_changed))/3600)|round(0) }}
Status: >
{{trigger.id}}
Maybe an expert among you can tell me whether the sensor can be made simpler in some way, it seems relatively “inflated” to me now.
I started my first attempts with a normal template sensor and the lambda function, but it failed because as soon as the input sensor was set to “unavailable” or was no longer updated and accordingly the template sensor was no longer updated, although when a template sensor was created via the graphical interface it was specified that the sensor would be updated “at the beginning of every minute” as soon as a time function (timestamp) is applied - so the timestamp of the sensor no longer produced any output:
state: >
{% set current_timestamp = now().timestamp() %}
{% set fronius_state = states.sensor.symo_12_5_3_m_power_ac.state %}
{% set fronius_timestamp = as_timestamp(states.sensor.symo_12_5_3_m_power_ac.last_changed) %}
{% if fronius_state != 'unavailable' %}
{{fronius_state}}
{% elif current_timestamp - fronius_timestamp > 1800 %}
{{0}}
{% endif %}
I ask for help. what am I missing?
unknown
there is a sensor “sensor.light_sensor_new_bh1750_illuminance” sometimes when the network is lost (Ping) it returns the value unknown
I want it to show the latest value instead of unknown
- trigger:
- platform: state
entity_id: sensor.light_sensor_new_bh1750_illuminance
not_to:
- unknown
- unavailable
sensor:
- name: Outside_illuminance
device_class: illuminance
unit_of_measurement: 'lx'
state: >
{% set x = states('sensor.light_sensor_new_bh1750_illuminance') %}
{{ x if has_value(x) else unknown | default(0, true) }}
Follow the second example shown in the Solution post. Compare its state
template to what you did in your version.
I have implemented the Trigger-based template sensor as suggested and it works great for holding the last good value of a sometimes unreliable sensor.
- trigger:
- platform: state
entity_id: sensor.stikkontakt_varna_power
not_to:
- 'unknown'
- 'unavailable'
sensor:
# the value of this sensor is only updated
# if the state of the entity_id is NOT 'unknown' or 'unavailable'
- name: lawn_mower_latest_power_consumption
state: '{{ trigger.to_state.state }}'
device_class: power
unit_of_measurement: 'W'
But how can I repeat this for other sensors as well?
I have a template.yaml file in which I have defined all my binary sensors and sensors.
I added the trigger-based sensor to this file, but I can’t figure out how to add several trigger-based sensors in one file.
Can you please give me some advise on how to do that?
- trigger:
- platform: state
entity_id: sensor.stikkontakt_varna_power
not_to:
- 'unknown'
- 'unavailable'
sensor:
# the value of this sensor is only updated
# if the state of the entity_id is NOT 'unknown' or 'unavailable'
- name: lawn_mower_latest_power_consumption
state: '{{ trigger.to_state.state }}'
device_class: power
unit_of_measurement: 'W'
- trigger:
- platform: state
entity_id: xxxx
not_to:
- 'unknown'
- 'unavailable'
sensor:
- name: xxxxx
state: '{{ trigger.to_state.state }}'
device_class: power
unit_of_measurement: 'W'
oh, I missed that.
Thanks