Custom Component: Generic Variable Entities

Ah, that. I was hoping I could learn from those lines how to hook the recorder component so that I could improve the SQL query feature. It turns out that that code didn’t quite do what I was hoping, and so I had to come up with a different solution.

After digging into this startup issue a bit more, it seems that all variables are being updated once on startup - even variables that don’t track any entities or events. For example, the following variable seems to reevaluate its value_template once each time Home Assistant is started. This means that the value of test is always 1 after HA starts when it should be 0.

var:
  test:
    friendly_name: "Test"
    initial_value: 0
    value_template: "{{ (states('var.test') | int ) + 1 }}"

This even happens for variables which have restore set to false.

I’m not sure of a solution yet, but I’m continuing to look into it.

Ah, I found the source of the problem. An update is being scheduled explicitly on startup. Doh!

Well, that should be easy enough to fix. I’ll push a new release (0.6.0) later today.

For those that want the old behavior, add the homeassistant_start event to the variable’s tracked_event_type list.

Update

Release 0.6.0 is out, and it should fix the issue of variables updating on startup when they shouldn’t.

@gene, let me know if this doesn’t fix your problem Thanks!

Ok, this is strange.
Just to see it fixed, I restarted to witness the issue before updating. I don’t know what’s going on, but I am not seeing the var. update during restart! It was doing it all day!

Maybe I’ve been at this too long. Let me look fresh in the morning. I do appreciate your fast response on this one.

For the life of me, I cannot figure out why this issue will not reproduce itself for me. The only thing I believe I changed on this system since reporting this issue, was upgrading the HACS component to 13.0. I can’t imagine that’s related.

I upgraded to your new version, and obviously all is fine.
Thank you.

@gene, my only thought is that if the restore state was the same as what the value_template evaluated to, then a state_change event might not have been fired. I’m not sure, but glad to hear it’s working for you now!

Hi, I’m fairly new to HA and just installed this new component. I’m trying to achieve something relative simple but can’t get it to work, so I’ hoping someone can point me to the right direction.
I have power sensor that monitors the power usage of my oven. With this I would like 2 things:

  • Set the current oven mode to Heating if it’s on or to Off when if off
  • Count the amount of times the oven is used.

I created 2 variables.:

oven_counter:
  friendly_name: 'Times turned on'
  icon: mdi:counter
oven_mode:
  friendly_name: 'Oven status'
  initial_value: 'Off'

And 3 automations:

- id: 'Oven heating power 25W or more'
  alias: Oven heating
  initial_state: 'true'
  trigger:
    platform: numeric_state
    entity_id: sensor.oven_power
    value_template: '{{ (states.sensor.oven_power.state | int) }}'
    above: 25
    for:
      seconds: 10
  condition: []
  action:
  - service: var.set
    data:
      value_template: "{{ states('var.oven_mode') = 'Heating' }}"
 
- id: 'Oven off under 20W or less'
  alias: Oven off
  initial_state: 'true'
  trigger:
    platform: numeric_state
    entity_id: sensor.oven_power
    value_template: '{{ (states.sensor.oven_power.state | int) }}'
    below: 20
  condition: []
  action:
  - service: var.set
    data:
      value_template: "{{ states('var.oven_mode') = 'Off' }}"
 
- id: 'oven_counter'
  alias: oven counter
  initial_state: 'true'
  trigger:
  - entity_id: var.oven_mode
    platform: state
    to: 'Off'
    for:
      seconds: 25
  action:
  - service: var.set
    data:
      value_template: "{{ (states('var.oven_counter') | int) + 1 }}"

The issue is that the status of the var.oven_mode does not change when the over is turned on and probable won’t change when it’s turned off again.
Also when I manually change the value of var.oven_counter it also changes the var.oven_mode to the same value, that’s something I think is really strange.

Help is much appreciated.

You want to set the value, not the value_template.

Try the following:

- service: var.set
  data:
    entity_id: var.oven_mode
    value: 'Heating'
- service: var.set
  data:
    entity_id: var.oven_mode
    value: 'Off'

For your counter, you can use an automation, but as an alternative try:

var:
  oven_counter:
    initial_value: 0
    tracked_entity_id: var.oven_mode
    value_template:
      {% if states('var.oven_mode') == 'Off' %}
        "{{ (states('var.oven_counter') | int) + 1 }}"
      {% else %}
        "{{ states('var.oven_counter')}}"
      {% endif %}

Also, make sure to use states('sensor.oven_power') and not states.sensor.oven_power.state. See here for more information.

And see here for documentation on the variable integration.

Thanks for your quick reply!
The status now change accordingly from ‘Off’ to ‘Heating’ and vice versa, but the automation part doesn’t work like it should.

When the oven turns from ‘Heating’ to ‘Off’ the counter is increased with 1 as in the value_template, but then the oven_mode suddenly changes from ‘Off’ to the same number as the counter. So it quickly changes from ‘Off’ to an integer state as oven_counter.

I really would like to use the automation instead of your alternative because I need the 25 seconds delay before increasing the counter +1.

Can you take another look, or maybe try it yourself in a similar automation.

- id: 'oven_counter'
  alias: oven counter
  initial_state: 'true'
  trigger:
  - entity_id: var.oven_mode
    platform: state
    from: "Heating"
    to: "Off"
    for:
      seconds: 25
  action:
  - service: var.set
    data:
      value_template: "{{ (states('var.oven_counter') | int) + 1 }}"

You need to specify the entity_id of the variable to set when using the var.set service. Your automation does not specify the entity_id under data.

And you need to use value and not value_template.

I would suggest looking over the examples from my previous post and the examples in the documentation to get a better idea of how to use the component. The value_template parameter is used to specify a template that will be evaluated and stored whenever the variable is updated. It is uncommon to change value_template using var.set, it is usually only specified in the configuration for variable entities that auto update.

To be explicit:

- id: 'oven_counter'
  alias: oven counter
  initial_state: 'true'
  trigger:
  - entity_id: var.oven_mode
    platform: state
    from: "Heating"
    to: "Off"
    for:
      seconds: 25
  action:
  - service: var.set
    data_template:
      entity_id: var.oven_counter
      value: "{{ (states('var.oven_counter') | int) + 1 }}"

Thanks, works like a charm now. Still figuring out those things and of course I checked your examples but couldn’t think of above solution.
Things a getting clearer now, will try some more things with you component.

You’re not the first one to be tripped up by the template parameters. I should really update the docs to be more clear regarding them.

Release 0.8.0 is now available.

Hopefully, the documentation regarding templates is more helpful now.

Great component. I like it very much.

I’m struggling to figure out if there’s a way to add custom attributes to a variable, preferably within template.

Anybody knows how to do this?

There is an open ticket for this feature. As a workaround, you could try storing an array or dict in a variable. Home Assistant also supports scenes now, which may also be of use.

Not to take away from the author here but there is another variable custom component that I use and it will already do what you want.

Yes, rogro82’s component allows for a dict to be stored along with the variable.

The same behavior can be achieved with this var component by simply storing a dict of attributes in a separate variable. This approach allows for the attributes to be persisted across restarts of Home Assistant which rogro82’s component does not support.

1 Like

Actually, it does. I use it like that right now for an array of attributes and survives restarts just fine…

And it’s more compact and therefore easier to maintain since it can be all done in the same variable.

Again, not trying to step on your toes here. I’m just throwing out alternatives to answer the question.

It looks like that feature was added since I last tried that component. Unfortunately, rogro82 doesn’t seem to keep the tickets up to date. This ticket should really be closed.

Nevertheless, I disagree that that approach is easier to maintain. It’s more a question of the service API, and I find the json attribute approach to be ugly in rogro82’s component. It doesn’t conform to Home Assistant conventions for yaml.

In any case, I don’t think yaml is a good approach for Home Assistant in general. YAML is limited in what it can express, and it is not meant for expressing code or logic which is how it is being used now by most people. I don’t know why anybody uses it over NodeRed or pure Python. I created this var component before I realized that NodeRed existed, and before I had attempted complex automatons in yaml. In hindsight, I should not have created it, since I think it encourages people toward the wrong approach to creating automatons.

The real value I see in this var component is in the event-based updating of variable values. Variables can serve as a more succinct replacement for automation in certain cases. Though, again, I’m not sure why anybody uses yaml in the first place.