Self-referencing template sensors: Is it a good idea?

The idea

I’ve experimented a bit with self-referencing sensors. They might be useful for example for hysteresis. (I am aware of hysteresis sensors, but we can do more advanced things with this.) For example, we might have a sensor that produces on/off/keep values and then a binary sensor that takes those values:

  private val binaryWindowOpenDef = BinarySensorDef.selfReferencing(
    name = s"${friendlyName} window open",
    stateFactory = self => windowOpenHysteresis.matches(
      HysteresisStatus.Off -> Const(false),
      HysteresisStatus.On -> Const(true),
      HysteresisStatus.Keep -> self,
    ),
  )

This generated a binary sensor like this (a bit manually polished output from Hagen; be aware of the difference between binary_sensor.my_room_window_open and sensor.my_room_window_open):

- "binary_sensor":
    "name": "my room window open"
    "state": '{{ \
      (
        false if (states("binary_sensor.my_room_window_open") == "off") \
        else (true if (states("binary_sensor.my_room_window_open") == "on") \
        else (unexpected_value)) \
      ) if (states("sensor.my_room_window_open") == "keep") \
      \ else (\
        true if (states("sensor.my_room_window_open") == "on") \
        else (false if (states("sensor.my_room_window_open") == "off") \
        else (unexpected_value)) \
      )\
      }}'

The key part is that the definition of the sensor binary_sensor.my_room_window_open references itself if the source sensor’s value is keep, so only on and off values change its state. I know one could do the same with an input_boolean and some automation that changes the values, but this is simpler and more declarative.

A recursive experiment

One might ask what happens when the source sensor has initially a keep value. We can do a simple experiment:

  private val selfReferencingExp = BinarySensorDef.selfReferencing(
    name = "self referencing experiment",
    stateFactory = self => self
  )

which roughly translates to:

- "binary_sensor":
    "name": "self referencing experiment"
    "state": '{{ \
      false if (states("binary_sensor.self_referencing_experiment") == "off") else \
      (true if (states("binary_sensor.self_referencing_experiment") == "on") else \
      (unexpected_value)) \
    }}'

I appologize for the verbosity. It comes from the defensive way Hagen handles conversion from String to Boolean.

The binary_sensor.self_referencing_experiment is always off. This looks like the initial state of the template-based binary sensor is off, so it just keeps the value forever.

The questions

  1. Is self-referencing officially supported by Home Assistant? I haven’t found any evidence of it either being supported or not being supported. (Or even encouraging/discouraging the self-referencing.)
  2. Can I rely on the initial value, as I do in the recursive experiment?

this variable.

1 Like

Cool, but I think that the usage of this in the referenced example is a bit different. It just reads its own attributes. I read the entity value, sometimes even if the entity has no previous value. Which is a bit edgy.

I don’t know anything “official” but I do it in several sensors and even recommended it to others in the forums and I’ve never noticed nor heard of any issues.

It’s not. It’s referencing the state object in the state machine. Perfectly fine, does not cause recursive loop.

There is no initial value, this will be undefined, you have to account for that on startup.