Trigger an event every time the value has changed X since last trigged

I found a lot of samples on how to trigger an event when a value goes over or under a certain limit but haven’t found any sample on how to trigger a change in the value.

As an example, lets say I have a temperature sensor and when it changed 1 degree sin last time triggered it should trigger the event again. How to do that

I think one way of doing this is by triggering using time, for example every 5 minutes.
Than you define a numeric helper to keep the last temperature value.

The condition would be that the:
absolute_value(current temperature minus the last value) >= X
In the action you store the temperature in the helper and fire the event.

I never done math in home assistant, but I’m guessing it is available?

1 Like

Thanks, that the solution I been thinking on and for example in node-red it’s easy to solve in a function but I’m curious if there is a smart HA solution for that.

I thought it was a quit common problem to check i a certain change in a value has occurred.

Trigger on the change attribute of the statistics sensor:

1 Like

I have a hx711 weight sensor under a cabinet shelf that I use to make sure no one is messing with my liquor.

The automation trigger is any state change on the sensor and the condition measures changes greater than 0.4 lbs (+ or -). Obviously you could set that to whatever you wanted. The 2nd part of the condition after ‘and’ is because the sensor randomly drops to -20ish and then spikes back up for some reason so that part forces the automation to ignore it.

Works well for me; not so much for my teenage kids…

  trigger:
    - platform: state
      entity_id: sensor.basement_liquor_scale_2
  condition: 
    - condition: or
      conditions:
        - condition: template
          value_template: "{{ trigger.from_state.state | float - trigger.to_state.state | float > 0.4 and trigger.from_state.state | float - trigger.to_state.state | float < 20 }}"
        - condition: template
          value_template: "{{ trigger.to_state.state | float - trigger.from_state.state | float > 0.4 and trigger.to_state.state | float - trigger.from_state.state | float < 20 }}"
3 Likes

@Tdw,

This, Sir, is the most brilliant use of smart home that i have ever seen. I humbly bow…

You can also use the math function “abs” instead of using 2 “or” conditions.

- condition: template
  value_template: "{{ (trigger.from_state.state | float - trigger.to_state.state | float) | abs > 0.4 and (trigger.from_state.state | float - trigger.to_state.state | float) | abs < 20 }}"

5 Likes

I really like this, my question is about timeframe. So if I have the sensor looking at PV power, and the template condition is for a change of 100 watts, the mqtt sensor is refreshing every 30 seconds, so does that mean that if the PV changes by less than 100 in 30 seconds, there is no trigger? Following this logic if the PV just happens to be slowly climbing or falling by less than 100 watts every 30 seconds, then it will not trigger??
Or is the operation such that it will trigger after is changes by 100 watts (even if this takes an hour) from the last time it triggered?

1 Like

Hello!

I want to control the screen brightness of small screen using values reported by a luminosity sensor located in the same room.

I can drive the screen brightness using the mqtt.publish service. I was thinking about an automation similar to what is described here, but I need to increase the screen brightness with higher lux values and vice versa.

This is how I was able to solve this in Python:

luxReadout_Max = 80
luxReadout_Min = 0
screenBrightness_Max = 255
screenBrightness_Min = 10
luxReadout = lux %<-- sensor values%
luxRange = (luxReadout_Max - luxReadout_Min)
screenBrightnessRange = (screenBrightness_Max - screenBrightness_Min)
screenBrighntess = ((((luxReadout - LuxReadout_Min) * screenBrightnessRange) / luxRange) + screenBrightness_Min)

Any idea how I would go about solving this in Home Assistant using an automation triggered by a state change of the lux sensor?

Any help in this regard would be greatly appreciated!

:slight_smile:
Best regards,
Andrew

You would likely need to include templates in your automation actions and not in the conditions like I had. So your trigger would be a change to the luminosity sensor and then templated actions based on how you are calculating the related brightness.

Hi!

Thanks for your prompt comment. Yes, I believe I will need templates in the trigger in order to test for a change in room luminance as well as in the action in order to calculate the new screen brightness.

I have no clue how to do either - the template syntax is very confusing to me :frowning:

Any ideas?

Best regards,
Andrew

Your post is a bit lacking in entity details, but the general method is as follows:

trigger:
  - platform: state
    entity_id: sensor.YOUR_LUX_SENSOR_ID
    not_to:
      - unknown
      - unavailable
condition: []
action:
  - variables:
      screenBrighntess:
        {% set luxReadout_Max = 80 %}
        {% set luxReadout_Min = 0 %}
        {% set screenBrightness_Max = 255 %}
        {% set screenBrightness_Min = 10 %}
        {% set luxReadout = trigger.to_state.state | int
        {% set luxRange = (luxReadout_Max - luxReadout_Min)  %}
        {% set screenBrightnessRange = (screenBrightness_Max - screenBrightness_Min) %}
        {{ (((luxReadout - LuxReadout_Min) * screenBrightnessRange) / luxRange) + screenBrightness_Min }}
  - service: YOUR_SCREEN_BRIGHTNESS_SERVICE
    data:
      brightness: "{{screenBrighntess}}"

If you find the screen brightness changes to be too frequent you could add a duration to the trigger and/or add a throttling condition.

Hi Drew,

Thanks so much for this… Reading it, I can kind of make sense of the variables section…

What does the pipe in {% set luxReadout = trigger.to_state.state | int do? … I guess it converts the calculation result to an integer? … and is there a %} missing at the end of that line?

And, I guess the result of the last line:

{{ (((luxReadout - LuxReadout_Min) * screenBrightnessRange) / luxRange) + screenBrightness_Min }}

… is written into the variable screenBrighntess: listed at the very top.

However, sadly, when I pop this into a new automation using YAML editor mode, The bar on the left hand side is red and the block of code under screenBrighntess: is not saved.

Below is the automation with my entities inserted.

alias: W32 adjust screen brightness
description: "W32 adjust screen brightness"
trigger:
  - platform: state
    entity_id: sensor.zoe_lux
    not_to:
      - unknown
      - unavailable
condition: []
action:
  - variables:
      screenBrighntess:
        {% set luxReadout_Max = 80 %}
        {% set luxReadout_Min = 0 %}
        {% set screenBrightness_Max = 255 %}
        {% set screenBrightness_Min = 10 %}
        {% set luxReadout = trigger.to_state.state | int %}
        {% set luxRange = (luxReadout_Max - luxReadout_Min) %}
        {% set screenBrightnessRange = (screenBrightness_Max - screenBrightness_Min) %}
        {{ (((luxReadout - LuxReadout_Min) * screenBrightnessRange) / luxRange) + screenBrightness_Min }}
  - service: mqtt.publish
    data:
      qos: 0
      retain: false
      topic: hasp/w32screen1/command
      payload: backlight "{{screenBrighntess}}"
mode: single

Can you tell me what I’m doing wrong?

Best regards,
Andrew

Hi there…

Sadly, I’m still stuck with this… Any ideas?

Thanks!

Best regards,
Andrew

Hello All!

I’m really banging my head against a wall here. I’ve reduced the list of % set… commands to a single line:

action:
  - variables:
      screenBrightness: {{ ((trigger.to_state.state * 245) / 80) + 10 }}

or

action:
  - variables:
      screenBrightness:
        {{ ((trigger.to_state.state * 245) / 80) + 10 }}

The line on the editor’s left hand side is blue (i.e. the code parses correctly) and I can hit the Save button. But after exiting and re-entering the yaml-editor, the code always reverts to:

action:
  - variables:
      screenBrightness:
        "[object Object]": null

Please help! I’m losing my mind… :-/

EDIT:

Without the math, this code:

alias: W32 adjust screen brightness
description: W32 adjust screen brightness
trigger:
  - platform: state
    entity_id: sensor.zoe_lux
    not_to:
      - unknown
      - unavailable
condition: []
action:
  - alias: "Set lux value to variable"
    variables:
      screenBrightness: "{{ states('sensor.zoe_lux') }}"
  - service: mqtt.publish
    data:
      qos: 0
      retain: false
      topic: hasp/w32screen1/command
      payload: "backlight {{ screenBrightness }}"
mode: single

… pushes the current lux value of the sensor to the screen’s backlight. Now, I need to scale it somehow…

Using the Template tab in the Developer Tools, I got this code to work:

{% if (((states('sensor.zoe_lux')|float * 245) / 80) + 10) > 255 %}
    screenBrightness: "255"
{% elif (((states('sensor.zoe_lux')|float * 245) / 80) + 10) < 10 %}
    screenBrightness: "10"
{% else %}
    screenBrightness: "{{ ((states('sensor.zoe_lux')|float * 245) / 80) + 10 }}"
{% endif %}

In my automation I tried:

action:
  - alias: "Set lux value to variable"
    variables_templates: >-
      {% if (((states('sensor.zoe_lux')|float * 245) / 80) + 10) > 255 %}
        screenBrightness: "255"
      {% elif (((states('sensor.zoe_lux')|float * 245) / 80) + 10) < 10 %}
        screenBrightness: "10"
      {% else %}
        screenBrightness: "{{ ((states('sensor.zoe_lux')|float * 245) / 80) + 10 }}"
      {% endif %}

But am met with the error message: Message malformed: Unable to determine action @ data['action'][0]

… I feel like I’m close. Any ideas?

Don’t template the keys, only the values. And, variables_templates is not a thing anymore… those were dark days :scream:

action:
  - alias: "Set lux value to variable"
    variables:
      screenBrightness: |
        {% set current = ((states('sensor.zoe_lux')|float * 245) / 80) + 10 %}
        {% if  current > 255 %}
          "255"
        {% elif current < 10 %}
          "10"
        {% else %}
          {{ current | string }}
        {% endif %}

Thanks Drew! I finally got around to trying this out and it works as intended. Amazing! :slight_smile: