Dreo Fan Integration?

After on and off being at this for 14 hours and extensive coding :crazy_face:, pretty happy with the final product.

N before anyone asks, Yes there is a dark mode too, automatic switching at night time :smiley:

Last thing which is left, if OP can advise how to get the speed in increments of 1 to 12 rather than percentage that would be the final piece to the puzzle!

FanCard

1 Like

Ok. This is using some custom card? How did you get the icons to be smaller? I am familiar with HTML/CSS/JS, but have yet to find a way to inject my own code style into the HA UI. Awesome work! Feel like posting your YAML or whatever you created the card in?

I’d almost bet money that they used GitHub - custom-cards/button-card: ❇️ Lovelace button-card for home assistant

I need to explore more I guess… custom-cards look pretty awesome! Glad I posted. Thank you for the link! I don’t play with HA as often as I like and with all the new features it gets overwhelming with the time I spend. Another bookmark and weekend project I think?! :stuck_out_tongue:

1 Like

Give me that money :smiley:

I have made this card using picture-elements

2 Likes

Here you go.

It’s a bit of a complex setup.

CARDS
You need to create 4 conditional cards for each fan
1. Light mode Fan Off
2. Light mode Fan On

3.& 4. - N vice versa for Dark mode.

IMAGES:
You need to take 4 screenshots for the fan pic from your Dreo app.
Similar to above, screenshot to be taken when fan is in Off mode in light and dark mode and Fan is On in light and dark mode.

IMAGES SAVE PATH IN HA
Images (.jpg/.png to save under /www in root folder)
I created images folder under www.
So my path was /local/images/smartfanoff.jpg

Light mode Fan in Off State

type: conditional
conditions:
  - condition: state
    entity: fan.smart_fan
    state: 'off'
  - condition: and
    conditions:
      - condition: state
        entity: sun.sun
        state: above_horizon
card:
  type: custom:stack-in-card
  cards:
    - type: picture-elements
      image: /local/images/smartfanoff.jpg
      elements:
        - type: state-label
          entity: sensor.smart_fan_temperature
          style:
            top: 7%
            left: 85%
            font-weight: semibold
            font-size: 190%
            color: '#000000'
            font-family: Helvetica
            tap_action:
              action: none
        - type: state-label
          entity: fan.smart_fan
          style:
            top: 95%
            left: 50%
            font-weight: semibold
            font-size: 170%
            color: '#000000'
            font-family: Helvetica
          tap_action:
            action: call-service
            service: fan.turn_on
            target:
              entity_id: fan.smart_fan
        - type: icon
          entity: fan.smart_fan
          icon: phu:power-panel-logo
          style:
            top: 7%
            left: 51%
            font-weight: semibold
            font-size: 170%
            color: '#000000'
            font-family: Helvetica
          tap_action:
            action: call-service
            service: fan.turn_on
            target:
              entity_id: fan.smart_fan

Light Mode Fan in On State

type: conditional
conditions:
  - condition: state
    entity: fan.smart_fan
    state: 'on'
  - condition: and
    conditions:
      - condition: state
        entity: sun.sun
        state: above_horizon
card:
  type: custom:stack-in-card
  cards:
    - type: picture-elements
      image: /local/images/smartfanon.jpg
      elements:
        - type: state-label
          entity: sensor.smart_fan_temperature
          style:
            top: 7%
            left: 85%
            font-weight: semibold
            font-size: 190%
            color: '#000000'
            font-family: Helvetica
        - type: state-label
          entity: fan.smart_fan
          attribute: percentage
          suffix: '%'
          style:
            top: 95%
            left: 61%
            font-weight: semibold
            font-size: 170%
            color: '#000000'
            font-family: Helvetica
        - type: state-label
          entity: fan.smart_fan
          attribute: preset_mode
          style:
            top: 95%
            left: 41%
            font-weight: semibold
            font-size: 170%
            color: '#000000'
            font-family: Helvetica
          tap_action:
            action: call-service
            service: automation.toggle
            target:
              entity_id: automation.fan_mode
        - type: icon
          icon: mdi:plus
          entity: fan.smart_fan
          style:
            top: 85%
            left: 10%
            color: '#000000'
          tap_action:
            action: call-service
            service: fan.increase_speed
            target:
              entity_id: fan.smart_fan
        - type: icon
          icon: mdi:minus
          entity: fan.smart_fan
          style:
            top: 85%
            left: 90%
            color: '#000000'
          tap_action:
            action: call-service
            service: fan.decrease_speed
            target:
              entity_id: fan.smart_fan
        - type: icon
          entity: fan.smart_fan
          icon: phu:power-panel-logo
          style:
            top: 7%
            left: 51%
            font-weight: semibold
            font-size: 170%
            color: '#00BFFF'
            font-family: Helvetica
          tap_action:
            action: call-service
            service: fan.turn_off
            target:
              entity_id: fan.smart_fan
        - type: icon
          icon: mdi:timer-check-outline
          entity: fan.smart_fan
          style:
            top: 35%
            left: 10%
            color: '#000000'
          tap_action:
            action: call-service
            service: automation.toggle
            target:
              entity_id: automation.smart_fan_turn_off_timer
        - type: icon
          icon: mdi:arrow-oscillating
          style:
            top: 35%
            left: 90%
            color: '#000000'
          tap_action:
            action: call-service
            service: fan.oscillate
            target:
              entity_id: fan.smart_fan
            data:
              oscillating: true
        - type: icon
          icon: mdi:arrow-oscillating-off
          style:
            top: 45%
            left: 90%
            color: '#000000'
          tap_action:
            action: call-service
            service: fan.oscillate
            target:
              entity_id: fan.smart_fan
            data:
              oscillating: false
    - type: conditional
      conditions:
        - condition: state
          entity: fan.smart_fan
          state: 'on'
        - condition: and
          conditions:
            - condition: state
              entity: automation.fan_mode
              state: 'on'
      card:
        type: horizontal-stack
        cards:
          - type: custom:mushroom-template-card
            primary: Natural
            secondary: ''
            icon: mdi:leaf
            icon_color: >-
              {% if states['fan.smart_fan'].attributes.preset_mode == 'natural'
              %}
                  amber
                {% else %}
                  grey
                {% endif %}
            layout: vertical
            tap_action:
              action: call-service
              service: fan.set_preset_mode
              target:
                entity_id: fan.smart_fan
              data:
                preset_mode: natural
            entity: fan.smart_fan
          - type: custom:mushroom-template-card
            primary: Sleep
            secondary: ''
            icon: mdi:moon-waning-crescent
            icon_color: |-
              {% if states['fan.smart_fan'].attributes.preset_mode == 'sleep' %}
                  purple
                {% else %}
                  grey
                {% endif %}
            layout: vertical
            tap_action:
              action: call-service
              service: fan.set_preset_mode
              target:
                entity_id: fan.smart_fan
              data:
                preset_mode: sleep
            entity: fan.smart_fan
          - type: custom:mushroom-template-card
            primary: Normal
            secondary: ''
            icon: mdi:wind-power-outline
            icon_color: >-
              {% if states['fan.smart_fan'].attributes.preset_mode == 'normal'
              %}
                  blue
                {% else %}
                  grey
                {% endif %}
            layout: vertical
            tap_action:
              action: call-service
              service: fan.set_preset_mode
              target:
                entity_id: fan.smart_fan
              data:
                preset_mode: normal
            entity: fan.smart_fan
          - type: custom:mushroom-template-card
            primary: Auto
            secondary: ''
            icon: mdi:autorenew
            icon_color: |-
              {% if states['fan.smart_fan'].attributes.preset_mode == 'auto' %}
                  cyan
                {% else %}
                  grey
                {% endif %}
            layout: vertical
            tap_action:
              action: call-service
              service: fan.set_preset_mode
              target:
                entity_id: fan.smart_fan
              data:
                preset_mode: auto
            entity: fan.smart_fan
    - type: conditional
      conditions:
        - condition: state
          entity: fan.smart_fan
          state: 'on'
        - condition: and
          conditions:
            - condition: state
              entity: automation.smart_fan_turn_off_timer
              state: 'on'
      card:
        type: custom:mushroom-number-card
        entity: input_number.fan_off_timer
        display_mode: slider
        name: Turn Off After
        hold_action:
          action: call-service
          service: automation.toggle
          target:
            entity_id: automation.smart_fan_turn_off_timer
        icon: mdi:clock:timer

For the Dark mode the code is same except
1.Change the condition to below_horizon, so that this card is only displayed in dark mode
2.Change the color to white so that you can see the Text/Icons in Dark mode.

2 Likes

Forgot picture entities let you do that. I used to have an interactive floor plan before i moved using them

Dear Dreo fan owners, is this integration offline or do the Dreo fans require an internet connection to be controlled? I hope not (and if, I’d have to search for a different fan that can be integrated). Thanks!

1 Like

It is cloud dependent but very fast in response.

Same concern here, this still requires the cloud, it would be great if it could be a completely “offline” (cloud independent) integration, so we’re not dependent on what will eventually be unmaintained by Dreo, increased risks of user/data leaks, etc.

Obviously it’s understandable that it was easier to do the API calls to Dreo’s cloud than to break the cert pinning of the app to RE the local calls, so I’m still glad I found this integration and appreciative of the hard work that when into it :clap: .

1 Like

I’m sorry I just saw this. Yes, we use the cloud API that we traced from the app. I don’t know what protocol the fan actually uses to talk to its servers. If anyone knows that, we could consider making it local.

2 Likes

Thanks for the response, really appreciate the hard work that was done so far!

Looking at the traffic between the (AWS EC2) cloud and the fan, it clearly is MQTT based, but all is encapsulated in TLS1.2 rendering RE a bit more complicated (need an mitmproxy setup, and hope that certs can be bypassed…).

2 Likes

I really like this card, great work! Can u share the code for this with the timer? :slight_smile:

What is the support like for the PolyFan 513s? Looking to pick one of these https://a.co/d/0boiLZGb up and wanted to see if it’s fully supported. Thanks!

2 Likes

Hello all, I worked my way through a hacking adventure and built a completely cloudcut integration for my Dreo fan (Pilot Max S), via a local ESPHome device:

For those who are interested in getting rid of the cloud portion of the HA integration…

This only works for the DR-HTF004S and is not expected to work on any other fan model. Other fan models would require their own investigative work.

4 Likes

Got to step 5 and it doesn’t load anything. I may be doing it wrong, or my model may not follow the same steps. Great project though

Feel free to open an issue on Github so we can exchange details/move the discussion there.

1 Like

Thank you for the git instruction update. Bout to try the file upload.

1 Like

I just wanted to say thanks!, I tried it now and it works great!
I’ve been annoyed with that cloud connection since i bought the fan!

2 Likes

Work this integration with the Model PolyFan 513S?