WTH can't input helpers be read only in UI

Very nice application of a Trigger-based Template Sensor! :+1: :+1:

Going forward, I will be suggesting this technique to others who require easily storing data “somewhere” that’s read-only in the UI and is automatically restored after startup.

You could even create one sensor.variables and store all the variables in a dictionary in the attributes

Can you post an example of that?

When triggered, all templates in sensor.variables are evaluated. My concern is that when sensor.variables receives data meant for one of its many variables, the templates for the other variables don’t get the data they need and, unless mitigated, will report errors or replace their existing values with none.

Working on it as we speak :slight_smile:

Big support on this request. I often use input helpers (mostly numbers and strings) as generic variables, to hold states evaluated by external Python scripts from other sensors. Like for example the battery state of charge from a battery voltage sensor. Or the rate of change for a barometric pressure sensor. They all end up being editable on the UI, which makes no sense. Giving the input helpers a read-only flag would make this much nicer and would not require some convoluted template based workarounds.

here you go:

Trigger based template sensor:

template:
  - trigger:
      - platform: event
        event_type: set_variable
      - platform: event
        event_type: remove_variable
    sensor:
      - unique_id: 4a4c8e53-9e68-4198-9cc5-b336e228ea4d
        name: Variables
        state: Variables
        attributes:
          variables: >
            {% set current = this.attributes.get('variables', {}) %}
            {% if trigger.event.event_type == 'set_variable' %}
              {% set new = {trigger.event.data.key: trigger.event.data.value} %}
              {{ dict(current, **new) }}
            {% elif trigger.event.event_type == 'remove_variable' %}
              {{ dict(current.items() | rejectattr('0', 'eq', trigger.event.data.key)) }}
            {% endif %}

To set a variable (reusing the key will overwrite the previous value)

action:
- alias:  Set a variable
  event: set_variable
  event_data:
    key: test
    value: 26

To remove a variable from the sensor:

action:
- alias:  Remove a variable
  event: remove_variable
  event_data:
    key: test

My sensor.variables after a few tests:

friendly_name: Variables
variables:
  test_int: 10
  test_float: 9.99
  test_list:
    - a
    - list
  test_dict:
    foo: bar
    whale: petunia
14 Likes

Thanks! Now I have a better understanding of what you meant. :+1:

The sensor doesn’t contain multiple attributes (one for each variable) but a single attribute whose value is a dictionary (whose keys represent each variable).

A very handy feature of your proposal is that, once sensor.variables has been defined, it can store a variable that’s defined ‘on the fly’ by an automation merely by using the set_variable event. In a manner of speaking, sensor.variables is a storage object with methods for setting/removing properties.


NOTE

Your first Feature Request

Automatically add a timestamp key to each variable when the set_variable event is processed. EDIT: Complicates retrieval.

Whoa. Jinja supports the ** syntax to expand a dictionary into kwargs?! I did not know that, that is exciting. I can definitely use that in a lot of places.

That would require it to be a list with dictionaries instead of a dictionary, and that would make it harder to get the variable out of the sensor

variables:
  test: 99
  test2: hello

Could be retrieved with state_attr('sensor.variables', 'variables').test

With this WTH implemented it could even be an attribute directly

variables:
  - key: test
    value: 99
    timestamp: 2022-10-01 21:54:01.944622+02:00
  - key: test2
    value: hello
    timestamp: 2022-10-01 20:51:01.933622+02:00

This requires state_attr('sensor.variables', 'variables') | selectattr('key', 'eq', 'test') | map(attribute='value') | list | first

2 Likes

Agreed; should’ve seen that one. Best to keep it as-is to simplify retrieval.

If someone needs to track the time when a variable’s value changes they can implement it as a standalone sensor entity like in CentralCommand’s example.

Uhh… May I quote Frenck from this post ?

In general, attributes are something we nowadays try to avoid. Mostly you’ll see them from “older” or custom integration. For new integrations and in our review process, we generally don’t allow for attributes that have value/could have been their own entities.

And you guys propose a convoluted template with Jinja mess that stores everything into attributes as a ‘solution’ to a very basic feature that should be lightweight, easy to use and built into core ? No wonder HA gets more and more resource hungry with every release. And what about the HA for the masses thing ? Where a simple variable requires something like that ? I mean sorry, no offense, but this makes exactly zero sense to me. Of course there are ways and workarounds to achieve this behavior now. That doesn’t mean they’re desirable. I could write a value into a file with a shell command and then retrieve it back into a sensor by polling with another shell command. Will it work ? Sure ! That doesn’t mean it’s a good way to replace this missing feature.

The reason of this WTH (and the other one about variables) is exactly to avoid these kind of hacky workarounds. What we need is a good native implementation that follows current best development practices for HA. Giving the input helpers a read only flag would be an easy first step.

2 Likes

You are right, chill down a bit, there is a tendency here around to achieve things independent of complexity, but at least, they are getting included and sharing their points.

Agree on making things simple and streamlined so HA should get easier for a new joiner.

So, let’s continue voting

You’re right, sorry. But this overengineering / overcomplexifying simple things mentality is really something that triggers me (and not only in HA :slight_smile:)

1 Like

I don’t believe Frenck’s post, that you quoted above, is about entities created by the Template, MQTT, REST, etc integrations. All of those official integrations allow the user to decide, based on their intended application, whether to employ attributes or not.

The advantage the attributes property has over an entity’s state property is that it’s not limited to just a 255-character string; it’s a dictionary whose values can contain other data types with no size limitation (other than the host’s hardware limits).

The comment by Frenck that does apply is the one he posted above:

A read only input helper would be a sensor… not an input.

Based on that opinion, CentralCommand and TheFes offered straightforward ways of employing a Trigger-based Template Sensor whose value can be easily set by a service call, just like for an Input helper. CentralCommand’s example offers the additional advantage of supporting device_class and unit_of_measurement so the value’s appearance in the UI can be influenced (not possible with Input helpers).

I entirely disagree, but this is clearly not the place to discuss this. So I will leave it at that and not drag this WTH any further offtopic.

Just one thing : input helpers do absolutely support unit_of_measurement. I use it all the time.

Yes, you’re correct; Input Number supports unit_of_measurement but not device_class. All other Input helpers support neither (nor icon); a Template Sensor offers far more control over its value’s appearance.

Input number, input text and input select all support icon. I don’t really see the point of UoM on anything other than a number. The lack of device_class and state_class configurability is indeed a shortcoming and could / should be addressed in the future.

Template Sensors also supports all the attributes needed for long term energy measurement so that would be useful for someone who wants to create a “variable” for that purpose.

I suspect it may face the same objection that Frenck posted earlier.

? I didn’t. There’s no attributes at all in here:

I mentioned if you wanted attributes you could do that too since I know the variables component supports that. But this entity just has a state.

For reference I have nothing wrong with fes’s solution. It’s a pretty creative way to make it so you can easily create and manage variables on the fly with no changes to yaml. But if you don’t like attributes you don’t need them.

Right, I was mostly referring to fes’s code. Yours is certainly a better approach imo. But in the end it all boils down to the same point: all that should not even be necessary. All these are workarounds. They’re reimplementing the concept of a variable with unneeded overhead and boilerplate code. All that should be abstracted away in an easy, intuitive and simple to use way over the UI, in the HA core. As far as I see it, input_* are almost there, at least for the common use cases.