Lovelace: Xiaomi - Mi air purifier 3H card

Also, consider using the official integration until MIoT sensor incorporates Fan and Favorite mode and levels.

@ollli. @dagnelino Any chance you could share the images for clean, polluted, and critical? I tried some from elsewhere in the thread but they were a bit the wrong size.

My config:

type: picture-elements
image: local/mi_air_purifier_3h_4.png
title: Purificatore Aria Salone
elements:
  - type: conditional
    conditions:
      - entity: sensor.mi_air_purifier_pm25_severity_salone
        state: clean
      - entity: binary_sensor.purificatore_aria_salone_mode_off
        state: 'off'
    elements:
      - type: image
        entity: sensor.mi_air_purifier_pm25_severity_salone
        title: PM2.5 severity level
        tap_action:
          action: more-info
        state_image:
          clean: local/mi_air_purifier_3h_clean_4.png
        style:
          top: 50%
          left: 50%
          width: 100%
  - type: conditional
    conditions:
      - entity: sensor.mi_air_purifier_pm25_severity_salone
        state: polluted
      - entity: binary_sensor.purificatore_aria_salone_mode_off
        state: 'off'
    elements:
      - type: image
        entity: sensor.mi_air_purifier_pm25_severity_salone
        title: PM2.5 severity level
        tap_action:
          action: more-info
        state_image:
          polluted: local/mi_air_purifier_3h_polluted_4.png
        style:
          top: 50%
          left: 50%
          width: 100%
  - type: conditional
    conditions:
      - entity: sensor.mi_air_purifier_pm25_severity_salone
        state: critical
      - entity: binary_sensor.purificatore_aria_salone_mode_off
        state: 'off'
    elements:
      - type: image
        entity: sensor.mi_air_purifier_pm25_severity_salone
        title: PM2.5 severity level
        tap_action:
          action: more-info
        state_image:
          critical: local/mi_air_purifier_3h_critical_4.png
        style:
          top: 50%
          left: 50%
          width: 100%
  - type: state-icon
    entity: binary_sensor.purificatore_aria_salone_mode_off
    title: 'Off'
    icon: mdi:power-standby
    tap_action:
      action: call-service
      service: fan.turn_off
      service_data:
        entity_id: fan.purificatore_aria_salone
    style:
      top: 26%
      left: 24%
      '--paper-item-icon-color': rgb(128, 128, 128)
      '--paper-item-icon-active-color': rgb(255, 128, 0)
  - type: state-icon
    entity: fan.purificatore_aria_salone
    title: More Info
    icon: mdi:dots-vertical
    tap_action:
      action: more-info
    style:
      top: 26%
      left: 77%
      '--paper-item-icon-color': rgb(128, 128, 128)
      '--paper-item-icon-active-color': rgb(128, 128, 128)
  - type: conditional
    conditions:
      - entity: binary_sensor.purificatore_aria_salone_mode_off
        state: 'off'
    elements:
      - type: state-label
        entity: sensor.mi_air_purifier_air_quality_pm25_salone
        title: PM2.5
        tap_action:
          action: more-info
        style:
          top: 36%
          left: 50%
          min-width: 40px
          min-height: 40px
          text-align: center
          font-size: 350%
          color: rgb(255,255,255)
      - type: state-label
        entity: sensor.mi_air_purifier_temp_salone
        title: Temperature
        tap_action:
          action: more-info
        style:
          top: 46%
          left: 31%
          min-width: 40px
          min-height: 40px
          text-align: center
          font-size: 75%
          color: rgb(255,255,255)
      - type: state-label
        entity: sensor.mi_air_purifier_humidity_salone
        title: Humidity
        tap_action:
          action: more-info
        style:
          top: 46%
          left: 42%
          min-width: 40px
          min-height: 40px
          text-align: center
          font-size: 75%
          color: rgb(255,255,255)
      - type: state-icon
        entity: switch.mi_air_purifier_led_salone
        title: Display
        tap_action:
          action: toggle
        style:
          top: 45%
          left: 67%
          '--paper-item-icon-color': rgb(128, 128, 128)
          '--paper-item-icon-active-color': rgb(255, 128, 0)
      - type: state-icon
        entity: switch.mi_air_purifier_buzzer_salone
        title: Buzzer
        tap_action:
          action: toggle
        style:
          top: 45%
          left: 54%
          '--paper-item-icon-color': rgb(128, 128, 128)
          '--paper-item-icon-active-color': rgb(255, 128, 0)
      - type: state-icon
        entity: switch.mi_air_purifier_child_lock_salone
        title: Child lock
        tap_action:
          action: toggle
        style:
          top: 36%
          left: 37%
          '--paper-item-icon-color': rgb(128, 128, 128)
          '--paper-item-icon-active-color': rgb(255, 128, 0)
      - type: state-label
        entity: sensor.mi_air_purifier_filter_remaining_salone
        title: Filter remaining
        tap_action:
          action: more-info
        style:
          top: 37%
          left: 63%
          min-width: 40px
          min-height: 40px
          text-align: center
          font-size: 80%
          color: rgb(128,128,128)
  - type: conditional
    conditions:
      - entity: binary_sensor.purificatore_aria_salone_mode_off
        state: 'on'
    elements:
      - type: state-label
        entity: sensor.mi_air_purifier_air_quality_pm25_salone
        title: PM2.5
        tap_action:
          action: more-info
        style:
          top: 36%
          left: 50%
          min-width: 40px
          min-height: 40px
          text-align: center
          font-size: 350%
          color: rgb(128, 128, 128)
      - type: state-label
        entity: sensor.mi_air_purifier_temp_salone
        title: Temperature
        tap_action:
          action: more-info
        style:
          top: 46%
          left: 31%
          min-width: 40px
          min-height: 40px
          text-align: center
          font-size: 75%
          color: rgb(128, 128, 128)
      - type: state-label
        entity: sensor.mi_air_purifier_humidity_salone
        title: Humidity
        tap_action:
          action: more-info
        style:
          top: 46%
          left: 42%
          min-width: 40px
          min-height: 40px
          text-align: center
          font-size: 75%
          color: rgb(128, 128, 128)
  - type: state-icon
    entity: binary_sensor.purificatore_aria_salone_mode_auto
    title: Auto
    icon: mdi:autorenew
    tap_action:
      action: call-service
      service: fan.set_speed
      service_data:
        entity_id: fan.purificatore_aria_salone
        speed: Auto
    style:
      top: 53%
      left: 31%
      '--paper-item-icon-color': rgb(192, 192, 192)
      '--paper-item-icon-active-color': rgb(255, 128, 0)
  - type: state-icon
    entity: binary_sensor.purificatore_aria_salone_mode_silent
    title: Silent
    icon: mdi:power-sleep
    tap_action:
      action: call-service
      service: fan.set_speed
      service_data:
        entity_id: fan.purificatore_aria_salone
        speed: Silent
    style:
      top: 53%
      left: 43%
      '--paper-item-icon-color': rgb(192, 192, 192)
      '--paper-item-icon-active-color': rgb(255, 128, 0)
  - type: state-icon
    entity: binary_sensor.purificatore_aria_salone_mode_fan
    title: Fan
    icon: mdi:fan
    tap_action:
      action: call-service
      service: fan.set_speed
      service_data:
        entity_id: fan.purificatore_aria_salone
        speed: Fan
    style:
      top: 53%
      left: 54%
      '--paper-item-icon-color': rgb(192, 192, 192)
      '--paper-item-icon-active-color': rgb(255, 128, 0)
  - type: state-icon
    entity: binary_sensor.purificatore_aria_salone_mode_favorite
    title: Favorite
    icon: mdi:heart
    tap_action:
      action: call-service
      service: fan.set_speed
      service_data:
        entity_id: fan.purificatore_aria_salone
        speed: Favorite
    style:
      top: 53%
      left: 67%
      '--paper-item-icon-color': rgb(192, 192, 192)
      '--paper-item-icon-active-color': rgb(255, 128, 0)
  - type: conditional
    conditions:
      - entity: binary_sensor.purificatore_aria_salone_mode_fan
        state: 'on'
    elements:
      - type: state-icon
        entity: binary_sensor.purificatore_aria_salone_mode_fan_1
        title: Fan level 1
        icon: mdi:fan-speed-1
        tap_action:
          action: call-service
          service: xiaomi_miio.fan_set_fan_level
          service_data:
            entity_id: fan.purificatore_aria_salone
            level: 1
        style:
          top: 61%
          left: 41%
          '--paper-item-icon-color': rgb(192, 192, 192)
          '--paper-item-icon-active-color': rgb(255, 128, 0)
      - type: state-icon
        entity: binary_sensor.purificatore_aria_salone_mode_fan_2
        title: Fan level 2
        icon: mdi:fan-speed-2
        tap_action:
          action: call-service
          service: xiaomi_miio.fan_set_fan_level
          service_data:
            entity_id: fan.purificatore_aria_salone
            level: 2
        style:
          top: 61%
          left: 50%
          '--paper-item-icon-color': rgb(192, 192, 192)
          '--paper-item-icon-active-color': rgb(255, 128, 0)
      - type: state-icon
        entity: binary_sensor.purificatore_aria_salone_mode_fan_3
        title: Fan level 3
        icon: mdi:fan-speed-3
        tap_action:
          action: call-service
          service: xiaomi_miio.fan_set_fan_level
          service_data:
            entity_id: fan.purificatore_aria_salone
            level: 3
        style:
          top: 61%
          left: 59%
          '--paper-item-icon-color': rgb(192, 192, 192)
          '--paper-item-icon-active-color': rgb(255, 128, 0)
  - type: conditional
    conditions:
      - entity: binary_sensor.purificatore_aria_salone_mode_favorite
        state: 'on'
    elements:
      - type: state-label
        entity: sensor.mi_air_purifier_favorite_level_salone
        title: Favorite level
        tap_action:
          action: none
        style:
          top: 62%
          left: 42%
          min-width: 40px
          min-height: 40px
          text-align: center
          font-size: 200%
          color: rgb(255, 128, 0)
      - type: icon
        icon: mdi:plus
        title: Favorite level +
        tap_action:
          action: call-service
          service: script.favorite_up
          service_data:
            entity_id: fan.purificatore_aria_salone
            step: 2
        style:
          top: 63%
          left: 55.5%
          min-width: 40px
          min-height: 40px
          color: rgb(192, 192, 192)
          color_off: rgb(255, 128, 0)
      - type: icon
        icon: mdi:minus
        title: Favorite level -
        tap_action:
          action: call-service
          service: script.favorite_down
          service_data:
            entity_id: fan.purificatore_aria_salone
            step: 1
        style:
          top: 63%
          left: 33%
          min-width: 40px
          min-height: 40px
          color: rgb(192, 192, 192)
          color_off: rgb(255, 128, 0)
      - type: state-label
        entity: input_select.mi_air_purifier_coverage_salone
        title: Coverage
        tap_action:
          action: none
        style:
          top: 61.7%
          left: 67%
          min-width: 40px
          min-height: 40px
          text-align: center
          font-size: 90%
          color: rgb(255, 128, 0)

1 Like

They’ve heard our prayers and update interval will be decreased from 60 to 10 seconds!

1 Like

Hello,

hello, the picture card is a bit messy with the phone/tablet. I’ve been looking at a card that is text type but I’m not clear the config. Can anyone give an example of how to do this? I don’t care if the card is very big

Thanks

My binary sensors that displays if the fan is silent mode and others do not work anymore. I guess it’s because the devs changed state attributes?

For instance, for silent mode, I have this configuration:

binary_sensor:
  - platform: template
    sensors:
      mi_air_purifier_mode_silent:
        friendly_name: "Purifier Silent mode"
        value_template: "{{ is_state_attr('fan.bedroom_purifier', 'mode', 1) and is_state('fan.bedroom_purifier', 'on') }}"

But on the developer page, I have the following information:

speed_list:
  - 'off'
  - low
  - medium
  - high
  - Auto
  - Silent
  - Favorite
  - Fan
preset_modes:
  - Auto
  - Silent
  - Favorite
  - Fan
speed: Silent
percentage: 33
percentage_step: 33.333333333333336
preset_mode: Silent
use_time: 36387600
friendly_name: bedroom.air_purifier
supported_features: 9

What I am thinking is that ‘mode’, 1 should be changed to ‘speed’, ‘silent’

What do you think?

As far as I know there is no mode anymore.
You should change it to preset_mode and 1 to Silent.
On the other hand you should consider changing the binary_sensor platform template. It is legacy now
and probably will be removed in the future. Template - Home Assistant
Change to modern template integration.

Thank you @uss

I did ponder how I can use the new template integration, but I am a bit at a loss on how to write them.

Would it be like this?

sensor:
  - name: mi_air_purifier_mode_silent
    state: "{{ state_attr('fan.bedroom_purifier, 'preset_mode', 'Silent') }}"

In the template.yaml you should have something like this:

binary_sensor:
  - name: mi_air_purifier_mode_silent
    state: "{{ state_attr('fan.bedroom_purifier', 'preset_mode') ==  'Silent' }}"

Don’t forget to include template.yaml in config.yaml

I use a different approach because it is faster.
Check Lovelace: Xiaomi - Mi air purifier 3H card - #200 by uss
In lovelace

  - type: conditional
    conditions:
      - entity: fan.pi2
        state: 'on'
      - entity: switch.pi2_led
        state: 'on'
      - entity: sensor.pi2_preset_mode_template
        state: Silent
    elements:
      - title: Mode Silent
        type: image
        image: local/pictures/XiaomiAir2S/Air2SSilent.png
        entity: fan.pi2
        tap_action:
          action: more-info
...

where sensor.pi2_preset_mode_template is:

sensor:
  - name: pi2_preset_mode_template
    state: "{{ state_attr('fan.pi2', 'preset_mode') }}"

As you may see, I create an sensor that gets the preset_mode and I do the check for Silent (and for Auto etc.) in conditions.

1 Like

I prefer to keep it in my configuration file for now, sadly this:

template:
  - binary_sensor:
      - name: mi_air_purifier_mode_silent_test
        state: "{{ state_attr('fan.bedroom_purifier, 'preset_mode') ==  'Silent' }}"

Throws this error:

2021-10-19 13:59:42 ERROR (MainThread) [homeassistant.config] Invalid config for [template]: invalid template (TemplateSyntaxError: expected token ',', got 'preset_mode') for dictionary value @ data['binary_sensor'][0]['state']. Got "{{ state_attr('fan.bedroom_purifier, 'preset_mode') == 'Silent' }}". (See /config/configuration.yaml, line 128).

I reckon you’re missing a quote:
'fan.bedroom_purifier, ‘preset_mode’
should be
‘fan.bedroom_purifier’, ‘preset_mode’

(Actually I was missing a quote)

1 Like

You are a godsend. I think I owe you a coffee or a beer by now.

For reference, this is my translated list:

template:
  - binary_sensor:
      - name: bedroom_purifier_mode_silent
        state: "{{ state_attr('fan.bedroom_purifier', 'speed') ==  'Silent' }}"
  - binary_sensor:
      - name: bedroom_purifier_mode_favorite
        state: "{{ state_attr('fan.bedroom_purifier', 'speed') ==  'Favorite' }}"
  - binary_sensor:
      - name: bedroom_purifier_mode_fan
        state: "{{ state_attr('fan.bedroom_purifier', 'speed') ==  'Fan' }}"
  - binary_sensor:
      - name: bedroom_purifier_mode_fan_1'
        state: "{{ state_attr('fan.bedroom_purifier', 'speed') ==  'Fan' and is_state('number.bedroomair_purifier_fan_level', '1') }}"
  - binary_sensor:
      - name: bedroom_purifier_mode_fan_2
        state: "{{ state_attr('fan.bedroom_purifier', 'speed') ==  'Fan' and is_state('number.bedroomair_purifier_fan_level', '2') }}"
  - binary_sensor:
      - name: bedroom_purifier_mode_fan_3
        state: "{{ state_attr('fan.bedroom_purifier', 'speed') ==  'Fan' and is_state('number.bedroomair_purifier_fan_level', '3') }}"
  - binary_sensor:
      - name: bedroom_purifier_mode_off
        state: "{{ is_state('fan.bedroom_purifier', 'off') }}"

Hello @schilea thanks for Your beautiful config. I’m new to Home Assistant so forgive me for my questions. I add my Xiaomi Air purifier 3/3H to HA and now have that default view. As I understand I have to copy Your config to my /homeassistant/configuration.yaml file but don’t know what to do next.

  1. Where I can get host: !secret mi_air_host, token: !secret mi_air_token
  2. Do I have to use Your automation?
  3. Do I have to remove my Air purifier card from dashboard first?
  4. Do I have to something else to make it work?

Regards,
Przemek

@PrzemekSkw

  1. you need a file secrets.yaml where to add ip, passwords and tokens

#======================#

Mi Air Purifier 3H

#======================#
mi_air_host: 192.168.x.xx
mi_air_token: “abcdefghijklmnopqrstuvwxyz0123456789”

  1. only if you want. if not you can create your own or go without any automation

  2. no, you don’t have to remove. Sometimes I am having multiple cards for the same entity.

  3. try this first

BR, Silviu

Quick question, why don’t you use the graphical setup, where the details are not on the config file?
I keep a written copy of the token, in case that the easy way of fetching it today disappears. But it’s far away from my HA setup.

you mean when adding the device via the MIIO integration? indeed if you use it the is no need for the secret info

@schilea Do I have to make secrets.yaml file or I have to find it in my homeassistant folder?

You have to create it. It is needed if you’d like to hide some sensitive info from your configuration.yaml.

But if you add the purifier via Integration - Xiaomi Miio there is no need for token to be specified, neither IP address. They are provided at the integration.

Screenshot 2021-10-21 114101

Now in my config I have commented the purifier:

#======================#
#  Mi Air Purifier 3H  #
#======================#
#fan:
#  - platform: xiaomi_miio
#    name: "Mi Air Purifier 3H"
#    host: !secret mi_air_host
#    token: !secret mi_air_token
#    model: zhimi.airpurifier.mb3
input_select:
    mi_air_purifier_3h_coverage:
      name: Coverage
      options:
        - 2-4 m²
        - 5-9 m²
        - 7-12 m²
        - 12-22 m²
        - 14-24 m²
        - 14-25 m²
        - 16-27 m²
        - 17-30 m²
        - 18-32 m²
        - 19-33 m²
        - 20-34 m²
        - 22-38 m²
        - 23-40 m²
        - 26-45 m²
        - 28-49 m²
      icon: mdi:texture-box

OK, @schilea I do everything from Your post from 14 sep.
I have already xiaomi mioo integration and my Air Purifier works. I don’t have any card in my dashboard yet.

  1. I copy your config to my configuration.yaml file.
  2. I open dashboard>edit dashboard>add card in yaml editor

I copy picture to my /www/images/ folder and now it looks that:
Zrzut ekranu z 2021-10-21 11-25-49

Firstly - some entities are missing. You have to replace the updated template to your config yaml (sensors and binary sensors).

> #=============#
> #  Templates  #
> #=============#   
> template:
> 
>   #======================#
>   #  Mi Air Purifier 3H  #
>   #======================#
>   - sensor:
>       - name: mi_air_purifier_3h_pm2_5_value
>         state: "{{ states('sensor.mi_air_purifier_3h_pm2_5')|float|round|int }}"
>         icon: "mdi-blur"
>         unit_of_measurement: " "
>       - name: mi_air_purifier_3h_temperature_value
>         state: "{{ states('sensor.mi_air_purifier_3h_temperature')|float|round(1) }}"
>         device_class: "temperature"
>       - name: mi_air_purifier_3h_humidity_value
>         state: "{{ states('sensor.mi_air_purifier_3h_humidity')|float|round|int }}"
>         device_class: "humidity"
>       - name: mi_air_purifier_3h_pm2_5_severity
>         state: >-
>           {% if states('sensor.mi_air_purifier_3h_pm2_5') | int > 30 %}
>             {{ 'critical' }}              
>           {% elif states('sensor.mi_air_purifier_3h_pm2_5') | int > 15 %}
>             {{ 'polluted' }}              
>           {% else %}
>             {{ 'clean' }}              
>           {% endif %}
>         icon: "mdi:air-filter"
>       - name: mi_air_purifier_3h_use_time
> #        state: "{{ state_attr('fan.mi_air_purifier_3h', 'use_time') }}"
>         state: >
>             {% macro phrase(value, name) %}
>             {%- set value = value | int %}
>             {%- set end = 's' if value > 1 else '' %}
>             {{- '{} {}{}'.format(value, name, end) if value | int > 0 else '' }}
>             {%- endmacro %}
>             
>             {% set weeks = (state_attr('fan.mi_air_purifier_3h', 'use_time') | int / 604800) | int %}
>             {% set days = ((state_attr('fan.mi_air_purifier_3h', 'use_time') | int - (weeks * 604800)) / 86400) | int %}
>             {% set hours = ((state_attr('fan.mi_air_purifier_3h', 'use_time') | int - (weeks * 604800) - (days * 86400)) / 3600) | int %}
>             {% set minutes = ((state_attr('fan.mi_air_purifier_3h', 'use_time') | int - (weeks * 604800) - (days * 86400) - (hours * 3600)) / 60) | int %}
>             {% set seconds = (state_attr('fan.mi_air_purifier_3h', 'use_time') | int - (weeks * 604800) - (days * 86400) - (hours * 3600) - (minutes*60)) | int %}
>             {{ [ phrase(weeks, 'week'), phrase(days, 'day'), phrase(hours, 'hr'), phrase(minutes, 'min'), phrase(seconds, 'sec') ] | select('!=','') | list | join(', ') }}
> #        unit_of_measurement: "sec"
>         icon: "mdi:heart-pulse"
> 
>   - binary_sensor:
>       - name: mi_air_purifier_3h_mode_auto
>         state: "{{ is_state_attr('fan.mi_air_purifier_3h', 'preset_mode', 'Auto') and is_state('fan.mi_air_purifier_3h', 'on') }}"
>       - name: mi_air_purifier_3h_mode_silent
>         state: "{{ is_state_attr('fan.mi_air_purifier_3h', 'preset_mode', 'Silent') and is_state('fan.mi_air_purifier_3h', 'on') }}"
>       - name: mi_air_purifier_3h_mode_favorite
>         state: "{{ is_state_attr('fan.mi_air_purifier_3h', 'preset_mode', 'Favorite') and is_state('fan.mi_air_purifier_3h', 'on') }}"
>       - name: mi_air_purifier_3h_mode_fan
>         state: "{{ is_state_attr('fan.mi_air_purifier_3h', 'preset_mode', 'Fan') and is_state('fan.mi_air_purifier_3h', 'on') }}"
>       - name: mi_air_purifier_3h_mode_fan_1
>         state: "{{ is_state_attr('fan.mi_air_purifier_3h', 'preset_mode', 'Fan') and is_state('number.mi_air_purifier_3h_fan_level', '1') and is_state('fan.mi_air_purifier_3h', 'on') }}"
>       - name: mi_air_purifier_3h_mode_fan_2
>         state: "{{ is_state_attr('fan.mi_air_purifier_3h', 'preset_mode', 'Fan') and is_state('number.mi_air_purifier_3h_fan_level', '2') and is_state('fan.mi_air_purifier_3h', 'on') }}"
>       - name: mi_air_purifier_3h_mode_fan_3
>         state: "{{ is_state_attr('fan.mi_air_purifier_3h', 'preset_mode', 'Fan') and is_state('number.mi_air_purifier_3h_fan_level', '3') and is_state('fan.mi_air_purifier_3h', 'on') }}"

Secondly - you have to add pictures in your \config\www folder