snarky-snark / home-assistant-variables

A custom Home Assistant component for declaring and setting generic variable entities dynamically.
Apache License 2.0
278 stars 16 forks source link

Example how to store and retrieve dictionary #48

Closed ehendrix23 closed 3 years ago

ehendrix23 commented 3 years ago

Per another issue posted here, one is supposed to be able to store not just a string but also, for example, a list or a dictionary for value. I've been trying to do this, but unable to then retrieve it.

I've tried:

  initial_value: "{'value': 0, 'day_value': 0, 'date': -1}"
  initial_value: {'value': 0, 'day_value': 0, 'date': -1}
  initial_value:
    value: 0,
    day_value: 0
    date': -1

{{ states(test).state }} returns what seems to be a string: OrderedDict([('value', 0), ('day_value', 0), ('date', -1)]) Trying to retrieve for example date with: {{ states(test).state.date }} returns nothing.

Using: {{ states(test).state['date`] }} also nothing.

{{ states(test).state[0] }} Returns: O

{{ states.var.test.state is string }} returns True

So it seems what is being returned is a string and not a dictionary.

What am I doing wrong?

snarky-snark commented 3 years ago

Thanks for the report. I'm looking into this.

One clarification from the HA templating docs, states('var.test') will return the state string, not the object. Though, states.var.test should return the object.

snarky-snark commented 3 years ago

That said, it does appear that states.var.test resolves to a string which seems wrong...

snarky-snark commented 3 years ago

https://developers.home-assistant.io/docs/dev_101_states/

Reading through the above documentation, it seems that HA will automatically convert the value to a string before storing it in the variable entity's state.

It looks like storing non-string objects in var entities will require some involvement of state attributes. I'll have to look into this more.

ehendrix23 commented 3 years ago

Good point on the string. This is part of something more complex where the entity id is a variable as well. But already changed that part then to states['var.test'] which would be returning the object then.

ehendrix23 commented 3 years ago

FYI, I tried to store a dict in a value based on comment in another issue about not planning to support attributes and instead to just use value and store a dict in there.

snarky-snark commented 3 years ago

Thanks, I updated that ticket to point to this one.

In order to resolve this ticket, I think it needs to be determined if it is possible to store a non-string value in an entity's state. The documentation above makes it sound unlikely that that is possible.

As a workaround, it may be possible to serialize a dict to a string in jinja and then deserialize it before using it. That is an ugly workaround, though.

I still don't anticipate having time to dedicate to supporting attributes on var entities, so that workaround might be the best bet on the short term.

snarky-snark commented 3 years ago

See the to/from JSON examples at the link below to see how to serialize and deserialize an object to and from JSON. you should be able to use that to store a dict in a var entity.

https://www.home-assistant.io/docs/configuration/templating/

Does that make sense?

ehendrix23 commented 3 years ago

For those reading this:

initial_value does not seem to be set as a template and hence you'll need to pick something else. I chose "unknown".

To store a dictionary, here is an example on what to set value to when calling var.set:

value: >
  {{ {"value": new_value, "day_value": states(trigger.entity_id)|float, "date": date} | to_json }}

And then when retrieving, use:

      {% if states('test') == 'unknown' %}
        {% set value_json = '{"value":0, "day_value": 0, "date": "20000101"}' | from_json %}
      {% else %}
        {% set value_json = states('test') | from_json %}
      {% endif %}  

And then you can use:

value_json['value']
value_json['day_value']
value_json['date']
snarky-snark commented 3 years ago

initial_value does not seem to be set as a template and hence you'll need to pick something else. I chose "unknown".

If you're serializing a dict anyway, couldn't you set initial_value to something like

initial_value: '{"value":0, "day_value": 0, "date": "20000101"}'

rather than 'unknown'?

snarky-snark commented 3 years ago

initial_value does not seem to be set as a template and hence you'll need to pick something else. I chose "unknown".

Alternatively, if you want the initial value to be evaluated on each startup using value_template, you can track the home assistant startup event.

tracked_event_type:
- homeassistant_start