Difficulty implementing brightness controls - "expected int for dictionary value"

So I’m completely new to HA, and I’m just diving in.

I’m running hass.io on an a RP4 with the nortek Zigbee/Z-wave stick. I’ve added two Sengled Element Classic bulbs and a Hue dimmer switch. I’ve gotten the on and off buttons working famously, but I’m struggling with adding the dimming functionality.

I’ve tried what I’ve found in several other posts about dimming:

But I keep running into the same error - when I try to get the current value of the brightness, I repeatedly get this error:

Error while executing automation automation.ken_brightness_up. Invalid data for call_service at pos 1: expected int for dictionary value @ data[‘brightness’]

Here’s the device info:

2020-01-28 08_25_35-Home Assistant

And here’s my current automation. I’ve confirmed that hardcoded brightness settings work (e.g. 10, 255), and this was the simplest step I could think of to get the programmatic value and add 10 to it:

- id: '1580190674095'
  alias: Left Brightness Up
  description: ''
  trigger:
  - device_id: a772cc70a8e444fc946ef52b5b6d0d20
    domain: zha
    platform: device
    subtype: dim_up
    type: remote_button_short_press
  condition:
  - condition: device
    device_id: 20083f936bdb4194a9c7d123ec63e18a
    domain: light
    entity_id: light.left_level_on_off
    type: is_on
  action:
  - data:
      brightness: {{states.light.left_level_on_off.attributes.brightness + 10}}
    entity_id: light.ken_level_on_off
    service: light.turn_on

I fear I’m missing something very basic. Any help would be greatly appreciated!

1 Like
brightness: {{states.light.ken_level_on_off.attributes.brightness + 10}}

it looks like this to me.
All values in HA are stored as strings
You need to convert this to a number before adding 10 (question what happens if it’s already at say 250 and you add 10 ?)

Try : -

brightness: {{ states.light.ken_level_on_off.attributes.brightness | int + 10 }}

I tried your change, but then the configuration would no longer validate -

Error loading /config/configuration.yaml: invalid key: “OrderedDict([(‘states.light.ken_level_on_off.attributes.brightness | int + 10’, None)])”
in “/config/automations.yaml”, line 48, column 0

Paste you whole (modified) automation

Edit: I think you need quotes around the template ie : -

brightness: "{{ states.light.ken_level_on_off.attributes.brightness | int + 10 }}"

And before burning gets in : - )) data: needs to be data_template:

2 Likes
  alias: Ken Brightness Up
  description: ''
  trigger:
  - device_id: a772cc70a8e444fc946ef52b5b6d0d20
    domain: zha
    platform: device
    subtype: dim_up
    type: remote_button_short_press
  condition:
  - condition: device
    device_id: 20083f936bdb4194a9c7d123ec63e18a
    domain: light
    entity_id: light.ken_level_on_off
    type: is_on
  action:
  - data:
      brightness: {{ states.light.ken_level_on_off.attributes.brightness | int + 10 }}
    entity_id: light.ken_level_on_off
    service: light.turn_on

I’ve found that my previous configuration showed the same “invalid key” error… It really doesn’t like my referencing somehow…

And change data to data_template as well.
Edit: also try to avoid the states.xxx notation and rather use state_attr(xxx), this will not give you an error when the entity is unavailable as recommended here in the docs.

1 Like

Progress! Casting to an int didn’t change the behavior - it still threw the same “expected int for dictionary value” error.

However, changing data to data_template suddenly made it work! Is there a doc somewhere that explains the differences between data and data_template?

Every time you use a template in the data part, you need to use data_template. Don’t know if it is documented explicitly smewhere, but you see in the examples of the templating docs that they always use data_template

Yeah data: contains data and
data_template: contains data in a template form

same with service; and service_template:
errr ! there must be more I’ve missed ??? Burning ???

Interesting. I was just copying snippets, so I’m not super clear on what a template is. I’ll do more reading…

and… burning?

Burning = Burningstone
Its just a quick reference to someone else on the thread without having to use their full name
eg we often call pnbruckner - Phil
you can’t shorten Mutt much though ! :rofl:

A template is a statement that ‘has’ to be evaluated at run time (ie you want the level at the time of the trigger not some arbitrary ‘set value’), it’s offered up in jinja format (a print method used to format text), in this case it’s basically passing up a bit of python to the sandbox
Anything like {% set var = sensor.time %} - this is an evaluation statement
{{ var }} or “{{ var }}” - these are print statements - the quotes are dependent upon usage, try to use double quotes on the outside and only single quotes on the inside.
Curley Brackets usually indicate a template

Edit: another tip. You as the owner of a thread get notified when anyone posts to it, to engage with another member (so they are notified) you have to use the reply button in their post

Edit2: Burning is also correct about errors at startup (and its generally a lot shorter too) so you ‘should’ replace : -

  - data:
      brightness: {{ states.light.ken_level_on_off.attributes.brightness | int + 10 }}
    entity_id: light.ken_level_on_off
    service: light.turn_on

with

  - data_template:
      brightness: "{{ state_attr('light.ken_level_on_off', 'brightness') | int + 10 }}"
    entity_id: light.ken_level_on_off
    service: light.turn_on

this avoids any ‘unknown state’ whilst the entity initialises

1 Like

Thanks @Burningstone and @Mutt for all of the help!

For future readers, here’s what I ended up with:

- id: '1580190674095'
  alias: left Brightness Up
  description: ''
  trigger:
  - device_id: a772cc70a8e444fc946ef52b5b6d0d20
    domain: zha
    platform: device
    subtype: dim_up
    type: remote_button_long_press
  condition:
  - condition: device
    device_id: 20083f936bdb4194a9c7d123ec63e18a
    domain: light
    entity_id: light.left_level_on_off
    type: is_on
  action:
  - data_template:
      transition: '1'
      brightness: "{% set n = state_attr('light.left_level_on_off', 'brightness') +\
        \ 25 %} {% if n > 255 %}\n  255\n{% else %}\n  {{ n }}\n{% endif %}\n"
    entity_id: light.left_level_on_off
    service: light.turn_on
- id: '1580190674096'
  alias: left Brightness Down
  description: ''
  trigger:
  - device_id: a772cc70a8e444fc946ef52b5b6d0d20
    domain: zha
    platform: device
    subtype: dim_down
    type: remote_button_long_press
  condition:
  - condition: device
    device_id: 20083f936bdb4194a9c7d123ec63e18a
    domain: light
    entity_id: light.left_level_on_off
    type: is_on
  action:
  - data_template:
      transition: '1'
      brightness: "{% set n = state_attr('light.left_level_on_off', 'brightness') -\
        \ 25 %} {% if n < 1 %}\n  1\n{% else %}\n  {{ n }}\n{% endif %}\n"
    entity_id: light.left_level_on_off
    service: light.turn_on
2 Likes

I’ve only seen it as a rule in the automation templating.

2 Likes

This may not work as you intend, you have not converted the strings to numbers.
Eg 2 > ‘100’ = true
You also have a lot of unnecessary \n bits
Not quite sure what you want us to do ?

1 Like

Nothing more needed, thank you! I believe the \n bits are put there by the Configurator plugin when given multi-line input. I haven’t yet set up Samba to allow me to edit the files in a more traditional way…

Haha totally missed that comment xD It’s always the data_template :stuck_out_tongue:

If I understand the docs correctly, he doesn’t need to do this with state_attr(xxx)

From the docs:

states('device_tracker.paulus') will return the state string (not the object) of the given entity or unknown if it doesn’t exist

state_attr('device_tracker.paulus', 'battery') will return the value of the attribute or None if it doesn’t exist.

The subtle difference is states(xxx) returns “state string” and state_attr(xxx,xxx) returns “value of the attribute”. Don’t know if my understanding of this is correct, however I can confirm that it works for me with state_attr(xxx) without casting it to an int first.

Ah that’s interesting, but without something (template editor) to check with, I’d always go with belt,
braces and a bit of string :man_shrugging:

Edit: casting a string to int gives you a number (as long as its not “Beware of the Zombies !” (or such) casting a number to int still gives you a number (hence the multiple methods of holding your pants up)

1 Like

Yeah, same here. I thought as well that it doesn’t work, that’s why I investigated a bit more.

If I remember correctly, state_attr(xxx,xxx) does an attribute gathering operation that will eventually box the returned value to it’s “correct” data type. I’d have to go back and look at /helpers/template.py to be 100% sure of that though.

1 Like

This is from the code:

def state_attr(hass, entity_id, name):
    """Get a specific attribute from a state."""
    state_obj = _get_state(hass, entity_id)
    if state_obj is not None:
        return state_obj.attributes.get(name)
    return None