Dyson Speed Control

Hi all,

I have a problem and I cannot seem to figure out why this problem existst.
Can somebody have a look and let me know if you have any ideas.

- alias: Dyson Fan Control
  hide_entity: true
  trigger:
    - platform: time_pattern 
      seconds: '/30'
  action:
    - service: dyson.set_speed
      data_template:
        entity_id: fan.woonkamer
        dyson_speed: >
          {% if state_attr('air_quality.woonkamer', 'air_quality_index') > 0 and state_attr('air_quality.woonkamer', 'air_quality_index') < 25 %}
              1
          {% elif state_attr('air_quality.woonkamer', 'air_quality_index') > 25 and state_attr('air_quality.woonkamer', 'air_quality_index') < 50 %}
              2
          {% elif state_attr('air_quality.woonkamer', 'air_quality_index') > 50 and state_attr('air_quality.woonkamer', 'air_quality_index') < 100 %}
              3
          {% elif state_attr('air_quality.woonkamer', 'air_quality_index') > 100 and state_attr('air_quality.woonkamer', 'air_quality_index') < 125 %}
              5
          {% elif state_attr('air_quality.woonkamer', 'air_quality_index') > 125 and state_attr('air_quality.woonkamer', 'air_quality_index') < 200 %}
              7
          {% elif state_attr('air_quality.woonkamer', 'air_quality_index') > 200 %}
              9 
          {% endif %}

To my best abbilities the speed settings 1,2…9 are int numbers.

Regards Jordy

This is the error I have:

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

This is a string:

state_attr('air_quality.woonkamer', 'air_quality_index') 

You cant do numeric comparisons (correctly) with strings.

Convert it to a number:

state_attr('air_quality.woonkamer', 'air_quality_index')|int

or this if the air quality is measured to grater than 0 decimal places.

state_attr('air_quality.woonkamer', 'air_quality_index')|float

Also what does the template evaluate to it the air quality is exactly 25?

You need some >= tests. I suggest:

        dyson_speed: >
          {% if 0 =< state_attr('air_quality.woonkamer', 'air_quality_index')|int =< 25 %}
              1
          {% elif 25 < state_attr('air_quality.woonkamer', 'air_quality_index')|int =< 50 %}
              2
          {% elif 50 < state_attr('air_quality.woonkamer', 'air_quality_index')|int =< 100 %}
              3
          {% elif 100 < state_attr('air_quality.woonkamer', 'air_quality_index')|int =< 125 %}
              5
          {% elif 125 < state_attr('air_quality.woonkamer', 'air_quality_index')|int =< 200 %}
              7
          {% else %}
              9 
          {% endif %}

No need to test that last one, if it has skipped all the other tests it is going to be >200.

Though you might have to be careful about the ‘unknown’ state turning the fan on full.

I have applied your suggestion.
But up on reloading the automation I get this error message

Invalid config for [automation]: invalid template (TemplateSyntaxError: expected token ‘end of statement block’, got ‘=’) for dictionary value @ data[‘action’][0][‘data_template’][‘dyson_speed’]. Got None. (See /config/configuration.yaml, line 0). Please check the docs at https://home-assistant.io/integrations/automation/

I have changed the code to this, now the previous error is resolved.

- alias: Dyson Fan Control
  hide_entity: true
  trigger:
    - platform: time_pattern 
      seconds: '/30'
  action:
    - service: dyson.set_speed
      data_template:
        entity_id: fan.woonkamer
        dyson_speed: >
          {% if 0 > state_attr('air_quality.woonkamer', 'air_quality_index')|int < 25 %}
              1
          {% elif 25 > state_attr('air_quality.woonkamer', 'air_quality_index')|int < 50 %} 
              2
          {% elif 50 > state_attr('air_quality.woonkamer', 'air_quality_index')|int < 100 %}
              3
          {% elif 100 > state_attr('air_quality.woonkamer', 'air_quality_index')|int < 125 %}
              5
          {% elif 125 > state_attr('air_quality.woonkamer', 'air_quality_index')|int < 200 %}
              7
          {% else %}
              9 
          {% endif %}

It may be technically correct, but it wont work.

For example, this:

{% elif 25 > state_attr('air_quality.woonkamer', 'air_quality_index')|int < 50 %}

will only be true when the air quality is less than 25 and less than 50. What you want is greater than 25 and less than or equal to 50.

Also I got the = and < round the wrong way. Try this:

        dyson_speed: >
          {% if 0 <= state_attr('air_quality.woonkamer', 'air_quality_index')|int <= 25 %}
              1
          {% elif 25 < state_attr('air_quality.woonkamer', 'air_quality_index')|int <= 50 %}
              2
          {% elif 50 < state_attr('air_quality.woonkamer', 'air_quality_index')|int <= 100 %}
              3
          {% elif 100 < state_attr('air_quality.woonkamer', 'air_quality_index')|int <= 125 %}
              5
          {% elif 125 < state_attr('air_quality.woonkamer', 'air_quality_index')|int <= 200 %}
              7
          {% else %}
              9 
          {% endif %}

Greater than is this symbol >
And less than is this symbol <

So by saying this:


{% elif 25 > state_attr('air_quality.woonkamer', 'air_quality_index')|int < 50 %}

I say if 25 is greater than X and less than 50 set speed to Y

I think my code is correct.

Nope.

25 > X < 50

Means X is less than 25 and X is less than 50.

25 < X < 50

Means X is grater than 25 and less than 50.

Easy way to remember: the small (pointy) end of the symbol < or > always points to the smallest value. X is less than Y here, X < Y and here Y > X.

Also you are still not testing for the possibility of the air quality exactly equalling any of the values, 0, 25, 50, 100, 150 or 200. What does your template resolve to in these cases?

It’s 9 now that we are using {% else %} as a ‘catch all other states’.

The error you got:

Was because I was using =< which is incorrect, it should have been <=. I corrected this in my second post.

To sum up, you need this:

        dyson_speed: >
          {% if 0 <= state_attr('air_quality.woonkamer', 'air_quality_index')|int <= 25 %}
              1
          {% elif 25 < state_attr('air_quality.woonkamer', 'air_quality_index')|int <= 50 %}
              2
          {% elif 50 < state_attr('air_quality.woonkamer', 'air_quality_index')|int <= 100 %}
              3
          {% elif 100 < state_attr('air_quality.woonkamer', 'air_quality_index')|int <= 125 %}
              5
          {% elif 125 < state_attr('air_quality.woonkamer', 'air_quality_index')|int <= 200 %}
              7
          {% else %}
              9 
          {% endif %}

Ok I understand, I have changed to code from using =< to <= and now it seems to work correctly.
Thanks for your help.

1 Like