IR FAN (Dyson AM07) Harmony Full Control

Hello, i wanted to include my Dyson Fan into HASSIO. Initially i thought about opening it up, and connecting an arduino to it… but i’m too chicken to try it out… fear of breaking and lack of knowledge…

So, i tried to include it into HASSIO using my Harmony Bridge. It took some time to figure it all out, but im very happy with the function right now.

It basically gives you 2 Sliders (1 for Speed, 1 for Timer) & 2 Switches (1 for Power, 1 for Oscilliate)
I tried to copy the functionality and logic of the original remote with several automations.
For example: You can turn on the Fan by just pressing oscillate button. Or by just pressing Fan Up button. This is all represented now and for now i have not found a breaking issue :slight_smile:

Functions:

Turn on Fan via Slider or Switch (Fan automatically goes to the desired Level)
Turn On / Off Ocillation (Power On is toggled as well from Off state)
Adjust Speed
Turn Off via Slider or Button (The Fan will always go down to 1 first, and then turn off)
Timer is not using the built in Dyson Timer, but actually a more flexible Timer builtin Hassio

I’d like to add a countdown timer as well so you can see how much time is left… But so far every attempt has failed. Any ideas welcome :slight_smile:

However, it requires you to ditch the remote, as this is IR based, and cannot report outside states into HASSIO.

This is how it looks right now:
Capture

As I am still very much new to HASSIO, have no coding experience and am constantly wondering why something works or doesnt work… i’d be very happy for some good advice on how to streamline all of these below:

So this is what you need to do to copy it:

configuration.yaml

#Dyson LivingRoom
# Define input_slider
input_slider:
  livingroom_fanspeed:
    name: Speed
    initial: 0
    min: 0
    max: 10
    step: 1
    icon: mdi:fan
# Define input_slider
  livingroom_fantime:
    name: Timer
    initial: 0
    min: 0
    max: 120
    step: 5
    icon: mdi:timer
#Switches
    input_boolean:
      livingroomfanpower:
        name: PowerToggle
        initial: off
        icon: mdi:power
      livingroomfanoscillate:
        name: Oscillate
        initial: off
        icon: mdi:code-tags

automations.yaml

# Dyson LR FanSpeedUP Slider
- action:
  - data_template:
      command: FanSpeedUp
      delay_secs: '0.25'
      device: '37767707'
      entity_id: remote.living_room
      num_repeats: '{{ trigger.to_state.state | int - trigger.from_state.state | int
        }}'
    service: remote.send_command
  alias: FanSpeedUpDL
  condition:
    condition: and
    conditions:
    - condition: template
      value_template: '{{ trigger.from_state.state | int < trigger.to_state.state
        | int  }}'
    - condition: template
      value_template: '{{ 0 < trigger.from_state.state | int }}'
  id: '1505854845181'
  trigger:
  - entity_id: input_slider.livingroom_fanspeed
    platform: state
# Dyson LR FanSpeedDOWN Slider
- action:
  - data_template:
      command: FanSpeedDown
      delay_secs: '0.25'
      device: '37767707'
      entity_id: remote.living_room
      num_repeats: '{{ trigger.from_state.state | int - trigger.to_state.state | int
        }}'
    service: remote.send_command
  alias: FanSpeedDownDL
  condition:
    condition: and
    conditions:
    - condition: template
      value_template: '{{ trigger.from_state.state | int > trigger.to_state.state
        | int }}'
    - condition: template
      value_template: '{{ 0 < trigger.to_state.state | int }}'
  id: '1505854845193'
  trigger:
  - entity_id: input_slider.livingroom_fanspeed
    platform: state
# Dyson LR Oscillate
- action:
  - data_template:
      command: Oscillate
      delay_secs: '0.25'
      device: '37767707'
      entity_id: remote.living_room
    service: remote.send_command
  alias: OscillateDL
  id: '1505854845197'
  trigger:
  - entity_id: input_boolean.livingroomfanoscillate
    platform: state
#Dyson LR Speed up to sliderstate from 0
- action:
  - data_template:
      command: FanSpeedUp
      delay_secs: '0.25'
      device: '37767707'
      entity_id: remote.living_room
      num_repeats: '{{ trigger.to_state.state | int - trigger.from_state.state | int
        - 1 }}'
    service: remote.send_command
  alias: Turn on from zero
  condition:
    condition: and
    conditions:
    - condition: template
      value_template: '{{ trigger.from_state.state | int < 1 }}'
    - condition: template
      value_template: '{{ trigger.to_state.state | int > 1 }}'
  id: '1505854845189'
  trigger:
  - entity_id: input_slider.livingroom_fanspeed
    platform: state
#Dyson LR Turn on to 1 from 0
- action:
  - data_template:
      command: PowerToggle
      delay_secs: '0.25'
      device: '37767707'
      entity_id: remote.living_room
    service: remote.send_command
  alias: Turn on to one
  condition:
    condition: and
    conditions:
    - condition: template
      value_template: '{{ trigger.from_state.state | int < 1 }}'
    - condition: template
      value_template: '{{ trigger.to_state.state | int < 2 }}'
  id: '1505854845198'
  trigger:
  - entity_id: input_slider.livingroom_fanspeed
    platform: state
#Dyson LR Turn Down Speed to 1 and then turn off 
- action:
  - data_template:
      command: FanSpeedDown
      delay_secs: '0.25'
      device: '37767707'
      entity_id: remote.living_room
      num_repeats: '{{ trigger.from_state.state | int - trigger.to_state.state | int
        }}'
    service: remote.send_command
  - data_template:
      command: PowerToggle
      delay_secs: '0.25'
      device: '37767707'
      entity_id: remote.living_room
    service: remote.send_command
  alias: Turn off when zero
  condition:
    condition: template
    value_template: '{{ trigger.to_state.state | int < 1 }}'
  id: '1505854845190'
  trigger:
  - entity_id: input_slider.livingroom_fanspeed
    platform: state
#Dyson LR Turn On Power if Oscillate is turned on
- action:
  - service: input_boolean.turn_on
    data:
      entity_id: input_boolean.livingroomfanpower
  alias: OscillatePower
  id: '1505854845101'
  trigger:
    platform: state
    entity_id: input_boolean.livingroomfanoscillate
    to: 'on'
#Dyson LR Turn Off Oscillate if Power is turned off
- action:
  - service: input_boolean.turn_off
    data:
      entity_id: input_boolean.livingroomfanoscillate
  alias: OscillatePower
  id: '1505854845101'
  trigger:
    platform: state
    entity_id: input_boolean.livingroomfanpower
    to: 'off'
#Dyson LR Turn Slider to 0 if PowerButton is Off
- action:
  - service: input_slider.select_value
    data_template:
      entity_id: input_slider.livingroom_fanspeed
      value: '0'
  alias: PowerOff
  id: '1505854845102'
  trigger:
    platform: state
    entity_id: input_boolean.livingroomfanpower
    to: 'off'
#Dyson LR Turn Off Power if Slider is turned to 0
- action:
  - service: input_boolean.turn_off
    data:
      entity_id: input_boolean.livingroomfanpower
  alias: PowerOff
  id: '1505854845108'
  trigger:
    platform: state
    entity_id: input_slider.livingroom_fanspeed
    to: '0.0'
#Dyson LR Turn Slider to 1 if Power is on
- action:
  - service: input_slider.select_value
    data_template:
      entity_id: input_slider.livingroom_fanspeed
      value: '1'
  alias: PowerOn
  condition:
    condition: template
    value_template: '{{ states.input_slider.livingroom_fanspeed.state | int < 1 }}'
  id: '1505854845107'
  trigger:
    platform: state
    entity_id: input_boolean.livingroomfanpower
    to: 'on'
#Dyson LR Turn on Power if Slider > 1
- action:
  - service: input_boolean.turn_on
    data:
      entity_id: input_boolean.livingroomfanpower
  alias: PowerOn
  id: '1505854845109'
  trigger:
    platform: state
    entity_id: input_slider.livingroom_fanspeed
  condition:
    condition: template
    value_template: '{{ trigger.to_state.state | int > 0 }}'
#Dyson LR Timer LR Dyson
- action:
  - delay: '00:{{ states.input_slider.livingroom_fantime.state | int }}:00'
  - service: input_boolean.turn_off
    data:
      entity_id: input_boolean.livingroomfanpower
  alias: PowerOff Timer
  id: '1505854845158'
  trigger:
    platform: state
    entity_id: input_slider.livingroom_fantime
  condition:
    condition: template
    value_template: '{{ trigger.to_state.state | int > 0 }}'  

groups.yaml

#LivingRoomFan
card_dysonlr:
  name: Dyson Wohnzimmer
  entities:
    - input_boolean.livingroomfanoscillate
    - input_boolean.livingroomfanpower
    - input_slider.livingroom_fanspeed
    - input_slider.livingroom_fantime
5 Likes

Great idea! I’m going to give this a try this weekend. Thanks for sharing!!

Finally was able to add the desired timer :slight_smile:
Mainly using the idea of tboyce1 Stopwatch. Slightly modifiying it, and using a 3rd Sensor to display the remaining time in minutes.

Capture

The addtiional code:

configuration.yaml

input_boolean:
  stopwatch:
    name: Stopwatch
    initial: off
  dummy:
    name: Dummy
    initial: off

groups.yaml

card_dysonlr:
  name: Dyson Wohnzimmer
  entities:
    - input_boolean.livingroomfanoscillate
    - input_boolean.livingroomfanpower
    - input_slider.livingroom_fanspeed
    - input_slider.livingroom_fantime
    - sensor.timedyson

customize.yaml

> sensor.timedyson:
>   icon: mdi:timelapse

automations.yaml

- alias: Stopwatch start
  trigger:
    platform: state
    entity_id: input_boolean.stopwatch
    to: "on"
  action:
    - service: input_boolean.toggle
      entity_id: input_boolean.dummy

- alias: Stopwatch stop
  trigger:
    platform: state
    entity_id: input_boolean.stopwatch
    to: 'off'
  action:
    - service: input_boolean.toggle
      entity_id: input_boolean.dummy

- alias: Stopwatch update
  trigger:
    platform: time
    seconds: '/30'
  condition:
    condition: state
    entity_id: input_boolean.stopwatch
    state: 'on'
  action:
    service: input_boolean.toggle
    entity_id: input_boolean.dummy

######################################################Dyson LR Turn Timer Slider to 0 if PowerButton is Off###########################################
- action:
  - service: input_slider.select_value
    data_template:
      entity_id: input_slider.livingroom_fantime
      value: '0'
  alias: PowerOff
  id: '1505854845302'
  trigger:
    platform: state
    entity_id: input_boolean.livingroomfanpower
    to: 'off'
############################################################### TURN ON STOPWATCH IF TIMER IS BIGGER THAN 0 ############################################
- action:
  - service: input_boolean.turn_on
    data:
      entity_id: input_boolean.stopwatch
  alias: PowerOn
  id: '1505854865109'
  trigger:
    platform: state
    entity_id: input_slider.livingroom_fantime
  condition:
    condition: template
    value_template: '{{ trigger.to_state.state | int > 0 }}'
################################################################ TURN OFF STOPWATCH IF POWER IS OFF ####################################################
- action:
  - service: input_boolean.turn_off
    data:
      entity_id: input_boolean.stopwatch
  alias: OscillatePower
  id: '1505854845101'
  trigger:
    platform: state
    entity_id: input_boolean.livingroomfanpower
    to: 'off'

sensors.yaml

  - platform: template
    sensors:
      stopwatch:
        friendly_name: "Stopwatch"
        value_template: >
          {% if is_state('input_boolean.stopwatch', 'on') %}
            {{ (now() - states.automation.stopwatch_start.attributes.last_triggered).total_seconds() | int }}
          {%-elif is_state('sensor.stopwatch', 'unknown') %}
            0
          {% else %}
            {{ states.sensor.stopwatch.state }}
          {% endif %}
        unit_of_measurement: 'sec'
        entity_id:
          - automation.stopwatch_start
          - automation.stopwatch_update
          - automation.stopwatch_stop
  - platform: template
    sensors:
      timedyson:
        friendly_name: "Time Left"
        value_template: '{{ (states.input_slider.livingroom_fantime.state | int - states.sensor.stopwatch.state | int / 60)| round }}'
        unit_of_measurement: 'min'

So I took the general idea but decided to modify to make a much simpler implementation. This version requires just 2 scripts, and 2 automations. Also uses a default fan speed when turning the switch on. I didn’t include a timer, as I never use that feature myself.

EDIT: latest version has a breaking change from input_slider to input_number. Updated with change.

Input_Number:

  dyson_fan_speed:
    name: Fan Speed
    icon: mdi:fan
    min: 0
    max: 10
    step: 1

Input_Select (for default speed):

  default_fan_speed:
    name: Default Fan Speed
    icon: mdi:speedometer
    options:
      - 1
      - 2
      - 3
      - 4
      - 5
      - 6
      - 7
      - 8
      - 9
      - 10

Switch Template:

  dyson_fan_power:
    value_template: "{{ states('input_number.dyson_fan_speed') | int > 0 }}"
    turn_on:
      service: script.turn_on
      entity_id: script.dyson_on
    turn_off:
      service: script.turn_on
      entity_id: script.dyson_off

Scripts:

  dyson_on:
    sequence:
      - service: remote.send_command
        entity_id: remote.bedroom
        data:
          device: "37710632"
          command: "PowerToggle"
      - service: input_number.select_value
        data_template:
          entity_id: input_number.dyson_fan_speed
          value: '{{ states.input_select.default_fan_speed.state | int }}'
      - service: remote.send_command
        entity_id: remote.bedroom
        data:
          device: "37710632"
          command: "Oscillate"

  dyson_off:
    sequence:
      - service: input_number.select_value
        data_template:
          entity_id: input_number.dyson_fan_speed
          value: 0
      - delay:
          seconds: 5
      - service: remote.send_command
        entity_id: remote.bedroom
        data:
          device: "37710632"
          command: "PowerToggle"

Automations:

  - alias: "Dyson Fan Speed Up"
    initial_state: on
    trigger:
      - platform: state
        entity_id: input_number.dyson_fan_speed
    condition:
      condition: and
      conditions:
        - condition: template
          value_template: '{{ trigger.from_state.state | int < trigger.to_state.state | int }}'
    action:
      - service: remote.send_command
        entity_id: remote.bedroom
        data_template:
          command: FanSpeedUp
          delay_secs: '0.25'
          device: '37710632'
          num_repeats: >
            {% set from_speed = (trigger.from_state.state | int) %}
            {% set to_speed = (trigger.to_state.state | int) %}
            {% if  from_speed == 0 %}
              {% set repeats = (to_speed - 1) %}
            {% else %}
              {% set repeats = to_speed - from_speed %}
            {% endif %}
            {{repeats}}

  - alias: "Dyson Fan Speed Down"
    initial_state: on
    trigger:
      - platform: state
        entity_id: input_number.dyson_fan_speed
    condition:
      condition: and
      conditions:
        - condition: template
          value_template: '{{ trigger.from_state.state | int > trigger.to_state.state | int }}'
        - condition: template
          value_template: '{{ 0 < trigger.from_state.state | int }}'
    action:
      - service: remote.send_command
        entity_id: remote.bedroom
        data_template:
          command: FanSpeedDown
          delay_secs: '0.25'
          device: '37710632'
          num_repeats: >
            {% set from_speed = (trigger.from_state.state | int) %}
            {% set to_speed = (trigger.to_state.state | int) %}
            {% if  to_speed == 0 %}
              {% set repeats = 10 %}
            {% else %}
              {% set repeats = from_speed - to_speed %}
            {% endif %}
            {{repeats}}

Group:

  dyson_fan:
    control: hidden
    view: no
    name: Dyson Fan
    entities:
      - switch.dyson_fan_power
      - input_select.default_fan_speed
      - input_number.dyson_fan_speed
      - script.dyson_oscillate
1 Like

My Dyson AM08 - works with harmony perfecty to do the initial turn-ON or any other intial command. It i received by Dyson .

But the OFF command (or any second command) is being ignored… It only works when I bring Dyson right next to harmony or its own remote for that matter. And need to point EXACTLY at the base of it. Only then it turns off.

So the first command works with pointing the remote vaugly in any direction and harmony can turn it on as well from the corner of the room, but off only works with exact pointing…

did anybody experience the same issue?

Yes same for me. The On command is easily recognized. All the other require close proximity. What works well are the small ir externer you can Plug into the Hub

1 Like

My hub happens to be very close to the fan and maybe that’s the reason I have no problems with it. Maybe it needs a delay in between commands?

Even the original remote only works if you point it directly at the sensor on the bottom of the fan, and you are at least 2-3meters close to it…

Hello Jer78, i would like if ti’s possible to adapt your Dyson automation from the IR to Wifi command.

I tried to do it myself but of course from the “data_template” line nothing’s working.

I can set the fan speed from the dev tools Dervice Data with this kind of command(working from 1 to 10, 0 don’t turn off the fan):

{
  "entity_id": "fan.salon","speed":"5"
}

How could i adapt this kind of command to your automations?

Here are my settings:

  dyson_fan_speed:
    icon: mdi:fan
    name: Speed
    initial: 0
    min: 0
    max: 10
    step: 1

 - alias: "Dyson Fan Speed Up"
   initial_state: on
   trigger:
     - platform: state
       entity_id: input_number.dyson_fan_speed
   condition:
     condition: and
     conditions:
       - condition: template
         value_template: '{{ trigger.from_state.state | int < trigger.to_state.state | int }}'
   action:
     - service: fan.set_speed
       entity_id: fan.salon
       data_template:
         delay_secs: '0.25'
         num_repeats: >
           {% set from_speed = (trigger.from_state.state | int) %}
           {% set to_speed = (trigger.to_state.state | int) %}
           {% if  from_speed == 0 %}
             {% set repeats = (to_speed - 1) %}
           {% else %}
             {% set repeats = to_speed - from_speed %}
           {% endif %}
           {{repeats}}

 - alias: "Dyson Fan Speed Down"
   initial_state: on
   trigger:
     - platform: state
       entity_id: input_number.dyson_fan_speed
   condition:
     condition: and
     conditions:
       - condition: template
         value_template: '{{ trigger.from_state.state | int > trigger.to_state.state | int }}'
       - condition: template
         value_template: '{{ 0 < trigger.from_state.state | int }}'
   action:
     - service: fan.set_speed
       entity_id: fan.salon
       data_template:
         delay_secs: '0.25'
         num_repeats: >
           {% set from_speed = (trigger.from_state.state | int) %}
           {% set to_speed = (trigger.to_state.state | int) %}
           {% if  to_speed == 0 %}
             {% set repeats = 10 %}
           {% else %}
             {% set repeats = from_speed - to_speed %}
           {% endif %}
           {{repeats}}

Thank you

@Romquenin

So for the Wifi connected fans, it should be much easier to do. Without having one myself, I can’t test this, but this should work.

Input Number (since there’s a power on/off function, we won’t need the 0 setting)

  dyson_fan_speed:
    icon: mdi:fan
    name: Speed
    min: 1
    max: 10
    step: 1

We will need 2 different automations. One to update the fan and the other to update the input_number. Let’s try this first with templates in the automation but if it doesn’t work, we may need to make template sensors instead.

 - alias: "Dyson Fan Speed From Input Boolean"
   initial_state: on
   trigger:
     - platform: state
       entity_id: input_number.dyson_fan_speed
   condition:
     condition: and
     conditions:
       - condition: template
         value_template: '{{ (trigger.to_state.state | int) != (states.fan.salon.attributes.speed|int) }}'
   action:
     - service: fan.set_speed
       entity_id: fan.salon
       data_template:
         speed: '{{states.input_number.dyson_fan_speed.state|int}}'

 - alias: "Dyson Fan Speed From Component"
   initial_state: on
   trigger:
     - platform: template
       value_template: '{% if (states.fan.salon.attributes.speed|int) != (states.input_number.dyson_fan_speed.state|int) %}true{%endif%}'
   action:
     - service: input_number.set_value
       entity_id:  input_number.dyson_fan_speed
       data_template:
         value: '{{states.fan.salon.attributes.speed|int}}'

Jer78 it works perfectly fine, you are amazing!!

Thank you very much again for sharing your knowledge, i will learn from this code and post my config for the other users.

Merci beaucoup!

1 Like

@Romquenin You’re quite welcome. Glad to be of assistance!

Hi @AlmostSerious
Thanks for your share!!
But can you help me convert it to RF fan with command boardlink_send??

Hi CloudHoang,

i’m not sure how the Broadlink is working within home assistant, as i do not have this device. However, you should be all set by just changing the “ACTION” part from Harmany to your Broadlink Device command.
So instead of telling Harmony to “press the button” FanSpeedUp 4 times, you just tell it to your Broadlink device. All the others steps should be the same.

Hi @AlmostSerious
Thanks for you reply.
I not sure but I can control via boardlink as the command below:

sequence:
  - service: switch.broadlink_send_packet_192_168_137_84
    data:
      packet: #send a packet
        - "JgBAAGkAA..."

Base on your code… I can change with there line below?

Am I right???
Thanks!

HI @Jer78
Thanks for your modified code…
However, my apologize, I dont know how to user your code.
Can you help me like the 1st topic of @AlmostSerious did…

Thanks :slight_smile:

@CloudHoang I’m not familiar with Broadlink either. What commands would you send? Is this the component?

https://home-assistant.io/components/switch.broadlink/

Hi @Jer78

I just need help about the code only :slight_smile:
Because I new on this so I dont know where to input yr code…
I tried it but most of time I got error :frowning:

@CloudHoang But I can’t help if I don’t know what this component is or does. I’d suggest you first get the commands working in a script and then paste them here. After that we can assemble them. But without knowing how or what this Broadcom Switch does I can’t help.

Hi @Jer78
Thank for your help :slight_smile:

I has tried to add your custom code last night but still not work.
On HA show me that the switch config is wrong. need to check again.

Base on your code, I can change the script as below to control my device via Boardlink

Most of time I can control with this

  - service: switch.broadlink_send_packet_192_168_137_84
    data:
      packet: #send a packet
        - "packet code"