Why the heck don't we have global variables?

OK, thanks! For a second there I thought I’ve been missing out on some neat shorthand for the last 2 years!

1 Like

One more thing and I suspect there’s not much anyone can do about it: allow for setting globals within a template.

Pretty sure that’s a big N O. What happens in Jinja, stays in Jinja. The template has no “reach” outside its curly boundaries.

That’s right. I could see possibly inventing a new Jinja function that accesses this mechanism, but that’s definitely post-MVP.

1 Like

And please add the ability to create/remove attributes of those variables via a service call.

There are two custom variable integrations that exist right now - one that allows attributes to be created and the other doesn’t. I find the one that allows the attributes to be set extremely much more useful than the one that doesn’t.

What’s an example use case? Variables in this model are straight key/value pairs.

see post #27 above.

As of right now I use it exclusively for a convenient list of the variable state history. Then I use those attributes in automations or just display them in lovelace with the attributes card.

If the only purpose of attributes is to keep track of previous values of the variable, that seems unwieldy. These variables entities will have states that change over time; those entities can be used in the history_stats component for more robust analysis of state changes.

The only time the states will change is if you change them via a service call. Then the user will also have control over which state history they want to keep track of by writing whatever it is they want to the attribute they want.

it ends up in a clean concise and easily accessible list of history that the user actually wants to keep.

forcing the user to create a history stats sensor to extract the state history is the thing that seems unwieldy and overly complicated.

Or it could be whatever other information related to that variable that the user might want to keep - it doesn’t have to be history. that was just an example. So a history stats sensor wouldn’t work in that case.

This seems beyond the MVP. We’re not wanting to create an endless list for each variable. I’ll sleep on it. :wink:

I guess I don’t know what an “MVP” means in this context.

Who is we?

And no one is talking about an “endless list”. I’m not sure where that came from.

So instead “we” want to create an endless list of history_stats sensors?

Seems counter productive…

If bachya’s variables can hold a dictionary then it provides all the flexibility of attributes and then some. For example, it could be something like this for your application:

{ 'state': '4392060', 'history': ['4392032','3664534','unknown','unknown','3660850'], 'previous': 'none' }

You can access the variable’s values like this:

{% set x = states('variables.foo') %}
{{ x.state }} {{ x.history[0] }} {{ x.previous }}

In other words, a variable doesn’t need explicit attributes when it’s capable of storing a dict whose structure you can define.

1 Like

And I agree that would be a viable alternative. as long as the 255 character limit wouldn’t preclude adding adequate desired information. The attributes don’t have that limitation.

The other drawback to maintaining all information in a single dictionary in the state (and it would be even moreso if the 255 character limit was removed) is that the dictionary structure would become unwieldy (seems to be the word of the hour :wink: ).

And I can’t work out in my mind how I would easily update the dictionary with new desired information.

I would have to extract the state of the variable and then add the desired key/value pair in at the proper place then save that back to the variable state. Again, overly complex and unwieldy. Especially when considering in the current situation using the rogro82 integration updating the attribute is as easy as a “variable.set_variable” service call with the appropriate data.

it can be as complex as:

      service: variable.set_variable
      data:
        variable: nws_alerts_event_ids
        attributes_template: >
          {
            "history_1": "{{ variable.state }}",
            "history_2": "{{ variable.attributes.history_1 }}",
            "history_3": "{{ variable.attributes.history_2 }}",
            "history_4": "{{ variable.attributes.history_3 }}",
            "history_5": "{{ variable.attributes.history_4 }}",
            "history_6": "{{ variable.attributes.history_5 }}",
            "history_7": "{{ variable.attributes.history_6 }}",
            "history_8": "{{ variable.attributes.history_7 }}",
            "history_9": "{{ variable.attributes.history_8 }}",
            "history_10": "{{ variable.attributes.history_9 }}"
          }
      data_template:
        value: "{{ (trigger.to_state.attributes.event_id).split('-')[0] }}"

or as simple as:

      - service: variable.set_variable
        data:
          variable: test_variable
          value: "not normal"
          attributes: 
            previous: 'normal'

and you can update an attribute individually:

service: variable.set_variable
      data:
        variable: nws_alerts_event_ids
        attributes_template: >
          {
            "history_4": "{{ variable.attributes.history_3 }}",
            "history_6": "{{ variable.attributes.history_5 }}",
            "history_7": "{{ variable.attributes.history_6 }}",
            "history_10": "{{ variable.attributes.history_9 }}"
          }
      data_template:
        value: "{{ (trigger.to_state.attributes.event_id).split('-')[0] }}"

I don’t think dynamically updating the variable state with that type of information will be quite so straight forward.

I’m not saying that custom integration is the end all for functionality. I’m sure it could be improved (maybe…) But it’s pretty useful.

2 Likes

No argument; updating the suggested dictionary wouldn’t be nearly as easy as the way the custom component allows (with its bespoke services).

In its basic form, a variable is a simple storage space. The variable’s type can be inferred from its value (a strongly typed language requires that you explicitly indicate the type).

For example, in Jinja2 (and python), the value is inferred:

{% set v = 42 %} # integer
{% set w = 18.56 %} # float
{% set x = 'foo' %} # string
{% set y = ['foo', 'bar'] %} # list
{% set z = {'key1': 42, 'key2': 18.56, 'key3': 'foo', 'key4': ['foo', 'bar']} %} # dict

The global variables by custom components aren’t truly providing pure variables. They use entities currently available in Home Assistant and present them with different names and even services. Nevertheless, under the hood, it’s an entity with a state and attributes which, effectively, is a predefined data structure (short strings in state and pretty much anything in attributes) .

I guess it will up to bachya to decide if a global variable should be a blank slate or come with a pre-defined data structure. I think the guiding principle should be that using the variable should be easy and convenient. Regardless of its data structure, it won’t find an audience if it’s difficult to set and/or get values.

1 Like

I assume Minimum Viable Product.

1 Like

I have a similar request, which is somehow related to this request and which I think would be solved with the the PR from bachya if it includes the posibility to have attributes like finity suggested.

For a long time I wanted to be able to create my own virtual entities, which are not tied directly to any hardware. I’m currently doing this sucessfully with AppDaemon, but would love to have something native to Home Assistant.

One useful example for such a virtual entity would be a room. In AppDaemon I created entities like area.bathroom, area.bedroom etc. This entities have multiple attributes that I set through different automations. For example they have an attribute “persons” that shows a list of the persons currently in the room. They also have an attribute for the occupany state of the room etc, etc. I then use these attributes in various automations as condition or trigger. I also use this to take snapshots of the current state of an area (which survive a HA restart by the way) and restore it afterwards.

Maybe I’m overthinking and making it all way more complex than it needs to be, but this works really well for me.

1 Like

Yes, this would be helpful when you want a variable/boolean for script/automation logic, but is otherwise completely useless to expose in the UI or database as a yet another sensor.

Alrighty – slept on it and I can see the value of being able to modify attributes on a variable (especially since using an entity to represent that variable gives us attributes for free). The latest push to the PR allows for variables.set schemas like this:

key: my_var
value: 123
attributes:
  attr_1: abc
  attr_2: def
  attr_3:
    - 1
    - 2
    - 3

The attributes key must be a dictionary; underneath that, you can have as little or as much complexity as you want.

Note that this is all still draft; we’ll see if the core review team approves the direction.

3 Likes

Ho-ho! So it’s based on an entity, except an entity whose state doesn’t have a 255 character limit. Interesting.

It can be used to store some value that should be calculated only once: e.g. creating a camera snapshot with a timestamp in the filename and using it in notifications (although it would be also possible with local variables in scripts).

Some autopromotion:

I have also created a custom component that can be used as a global variables storage.
The main difference between my solution and ones mentioned above (home-assistant-variables and hass-variables) is that it doesn’t create dedicated entities and it can create (and delete) variables on the fly with service calls.

You can check it out here: