Sensor offset template

Hello! I’m trying to get started with YAML based automation instead of using Node Red (because it just feels a bit complicated for what I want). As part of a script/automation I need the previous value of the brightness of a smart bulb. I believe the correct way of doing this is with a template, so I wrote the following:

template:
  - trigger:
    - platform: state
      entity_id:
        - light.bedside_lights
      attribute: brightness
      not_to:
        - "unknown"
        - "Unknown"
        - "none"
        - "None"
        - "unavailable"
    sensor:
      - name: Bedside Lights Brightness History
        state: "{{ this.attributes['val1'] }}"
        attributes:
          val0: "{{ state_attr('light.bedside_lights', 'brightness') }}"
          val1: "{{ this.attributes['val0'] }}"

As I understand it, this should:

  • Trigger any time the brightness value updates
  • Not trigger if the light turns off, in which case the value appears as “None” or “Unknown”, depending where I look
  • Update the value of val0 to the current value of the brightness
  • Update the value of val1 to the current value of val0 (before it is updated)
  • Give me a sensor whose state is the previous or current value of val1, I don’t really care which, as I can remove a value if it’s not what I expect.

However, it doesn’t work. When I watch the values changing in the sensor history they’re just a mess, but as far as I can follow them:

  1. All three values (state, val0 and val1) update every time the value of brightness changes, regardless of whether the light has been turned off, thus transitioning the brightness to None, or Undefined.
  2. If I only update the brightness, val0 updates to the latest value, as expected, state updates to the previous value (sort of as expected?) and val1 does it’s own thing. I think it may be getting an intermediate value between the previous and next brightness.
  3. If I switch off the light, val0 updates to undefined, val1 updates to the previous value of val0, states updates to the value of val1. If I switch it on again, val0 takes on the new value, val1 changes to undefined, state changes to the value of val1. If I turn it off again, state goes undefined, however if I just update the brightness, state gets the value from val0.

Basically, what I’m saying is, I’m lost, and would appreciate any help anyone can give!

I think you would be better off if you re-frame your question to focus on the automation instead. There may be better ways to accomplish your goal than this particular method.

Trigger-based template sensors have a particular order in which values are assigned to the this variable, state, and attributes. Since the values are only updated once for any given trigger event, this can lead to unexpected outcomes. You can read about this in this previous thread.

none is not the same as “none”…

template:
  - trigger:
      - platform: state
        entity_id:
          - light.bedside_lights
        attribute: brightness
        not_to:
          - null
        variables:
          from_br: "{{ trigger.from_state.attributes.brightness }}"
    sensor:
      - name: Bedside Lights Brightness History
        state: "{{ from_br if from_br is not none else this.state|default(0, 1) }}"  
1 Like

Thanks you! Your solution worked as I had specified, however it didn’t actually do what I needed it to do (once I added it into the rest of the system), so I did as you suggested and switched to using automations.

Actually @Didgeridrew, I worked out that I could significantly simplify my logic by using scripts, so I took another look at your templating solution. It appears that it that the value stored in this variable is taken at some point during the transition. For example, if the light is at 40% and I set it to 80%, it might set this value to 60%. Any thoughts on why this is happening? If I set a number variable with an automation as you suggested, it works correctly, so I guess it’s not particularly important. I’d just like to understand it better.

Do you use a transition period? That could explain it, but I’m not sure how you could avoid it without removing the transition. Maybe adding a delay action to the sensors… I’ve never tried using a delay for that purpose, so it would need testing.

I didn’t suggest that, but if it works… :smile:

My suggestion was that you re-frame the request of this thread to focus on the goal of the automation you are trying to create, instead of focusing on the method of the template sensor… The “what”, not the “how”. If you clearly describe what you are trying to achieve and what problems you are experiencing, it’s more likely that you will receive an answer that addresses the root issue.

1 Like

Thanks for your reply! Ok, you’re probably right that I would have got the answer more quickly, however I have found that working through a worse solution myself means I’m more likely to get what I want done in future. But I take your point, it is a bit of an XY question!

Regardless, I have now got it working as intended. To help anyone else who might be trying to do something similar, I’ll explain what I was trying to do and how I solved it (yes, there was a much better way of doing it!).

I want my bedside lights to turn on slowly to 100% brightness in the morning before my alarm. I use Sleep as Android, so I can easily trigger something 45 minutes before the alarm. However, next time I turn them on, I want them to go back to the previous brightness.

One fairly simple solution would be to use an independent control which updates the value of the lights when I turn them on and off manually, which I can then bypass when I turn them on from the alarm. However, I didn’t like this as I imagined it would cause other issues.

Instead, I thought I could store the brightness value every time it updates, and then switch back to this after the lights are turned off after the alarm (this last bit is trivial and works perfectly, reseting the “default” brightness back to what it was). In order to keep the previous value I decided to create a template which followed the brightness value. This didn’t work, as described. I then switched to using an automation to update a helper value every time the brightness changed, unless another boolean helper was true, indicating that the light had been turned on by the alarm. This did work, however it felt overly complex and required two helper values and about three separate automations.

The best way to do it is with a script. The script is triggered every time the brightness changes. It stores the updated value in a script variable. It then waits for the webhook from Sleep as Android. Once received it slowly turns on the lights, then waits for them to be turned off again, then it switches them on again to the brightness in the stored variable and off again. This results in a slight “blip” as the lights are dimming to off after the alarm, which I’m ok with. Critically, the script is set to restart mode. This means that, if instead of receiving the webhook, the script is triggered again by a change in brightness, it stops waiting, set sthe variable in a new script run and goes back to waiting. It took me a while to figure it out, but it works very well and doesn’t require any extra complexity.

And yes, I imagine you could have suggested this solution to me earlier on! Sorry!