Hi all,
I have a xiaomi scale sensor.weight sensor that has the following attributes:
state_class: measurement
weight: 78
weight_unit: kg
bmi: 33.39
basal_metabolism: 1964.87
visceral_fat: 30.01
timestamp: '2023-02-02T20:30:08+00:00'
unit_of_measurement: kg
icon: mdi:scale-bathroom
friendly_name: Test Weight
I would like to, whenever the timestamp attribute changes (it changes every time someone steps on the scale), to trigger a copy of that weight to a value called previous_weight. I’d also only like to do this in the morning, say from 8 - 10 so i can check what my weight was the previous morning at the same time.
I tried something like this but it’s not really working as of yet. Also tried with an automation but not sure how to add triggering on a attribute there.
A template sensor alone is not really conducive to doing what you are asking because the sensor will update every time you step on the scale. There’s no way AFAIK , in a template trigger, to differentiate between an update to a specific attribute in a specific time frame. Your likely going to need to employee either an automation or a SQL sensor.
The following Trigger-based Template Sensor maintains a record of the last 5 weight and BMI measurements in an attribute named history. Each measurement is time-stamped.
template:
- trigger:
- platform: state
entity_id: sensor.test_weight
attribute: timestamp
sensor:
- name: Weight History
state: "{{ now().timestamp() | timestamp_custom() }}"
attributes:
history: >
{% set current = this.attributes.get('history', []) %}
{% set new = [{
"weight": trigger.to_state.attributes.weight,
"bmi": trigger.to_state.attributes.bmi,
"time": now().timestamp() | timestamp_custom() }] %}
{{ (new + current)[:5] }}
If you don’t want to record BMI, just remove this line:
"bmi": trigger.to_state.attributes.bmi,
If you want to record another parameter like basal_metabolism, just add this line after the one that records weight:
I was just thinking about how i would store the previous state of the weight once the triggers happens.
Where can i read more about this magic history attribute.
Mainly what does:
{% set current = this.attributes.get('history', []) %}
It’s important to keep in mind that the attribute’s name “history” is just something I chose for your application. For another user, who wanted a record of the most recent music that was played, I called the attribute “tracks”.
The template’s first line gets the current value of the sensor’s history attribute and assigns it to a variable named current. If the history attribute doesn’t exist (which is the case when the sensor was just created) it uses an empty list as the default value.
The template’s last line appends the current value of the sensor’s history attribute to a new value (containing the latest measurement of weight, bmi, etc). In other words, it’s growing the list of measurements. The list could grow indefinitely if it were not for the [:5] which ensures only the first 5 items of the list are retained.
FWIW, I have experimented with more sophisticated versions of this type of Trigger-based Template Sensor that support services to purge all of, or a specific value in, the history attribute. Personally, I haven’t found a practical need for these services beyond ‘proof of concept’. All this to say that Trigger-based Template Sensors can be used in creative ways.
I overlooked to implement the time constraint requirement.
Yes, your enhanced version of the last line should do the trick.
FWIW, I would implement it as an Inline If, instead of an Immediate If, only because an iif always computes its if_true and if_false values regardless of the test.
In other words, even if the hour is not between 8 and 10, it’ll report current but still process (new + current)[:5].
I know, I know, it’s non-critical in this situation and only saves a few microseconds of processing time so, yeah, maybe fretting over nothing but there it is.
Thanks both. I’ll see if i can merge that in there as well.
BTW I should probably open another topic for the following, but i’m trying to use the above construct with a condition value template of:
{{ states('sensor.atv_weight') != 'unknown' or 'unavailable' }}
{% set w=state_attr('sensor.atv_weight_history','history') %}
{{ w[0].weight if w is iterable and w|count > 0 and w[0].weight is defined }}
{{ states('sensor.{{atv.id}}_weight') < states('w[0].weight') and
state_attr('sensor.{{atv.id}}_weight','timestamp')[8:10] < states('w[0].time')[8:10] }}
For some reason, the state of w[0].time is always unknown. The last line just compares if the date we are comparing against was yesterday (< then today).
Hi, I’m trying to save a dynamic created input select and then restore it after HA restart, i understand it can be done using “Trigger-based Template Sensor” I did not find any examples similar with what i need is there a way someone here can help me?
I’m generating the lists like this:
service: input_select.set_options
data:
options: >-
({% set ns = namespace(list=[]) %} {% for option in
state_attr("input_select.type_of_meal_filtered", "options") if option !=
states("input_text.type_of_meal_random") %} {% set ns.list =
ns.list+[option] %} {%endfor%} {{ns.list}})
target:
entity_id: input_select.type_of_meal_filtered
enabled: true
If I can just add the “options” to a sensor attributes and after restart red them and add them back to the input select.
OR
Just replace the input select altogether if “Template Sensor” survives restart and is possible to add/remove attributes then randomly pick from them. I’m only using input select because that is what I can adapt from the code I found.