Dyson Pure Cool TP04 - Custom card?

Hello,

I’m a pretty new user of Home Assistant. What is the right way to add a card that shows the following information:

  • Turn/off
  • Speed
  • Angle
  • Air quality
  • Carbon/Hepa filter

The only way is to add a custom card, right? How do I write the correct code?

I am in the same boat, i have spend a week trying to figure out a custom card, but it is too difficult. As you can see from the image these what i can add to the entities card. can some one help to add some of the attributes to show in the card for example the filter Life instead of clicking on the more info.

Has anyone solved this?

I am also interested in a way to do this. The default card is ok, but, I would like to control the fan & angle easy

I know this is an old post, but I created a card using picture-elements that has a lot of the sensor data and controls included in it.

0017_dyson_card

It’s a bit much to spell out here, but all of the code and assets can be found in my post about it: https://aarongodfrey.dev/home%20automation/dyson-tp04-integration/#custom-card

1 Like

Wow that’s really nice and an angle that I would not have thought about myself!

@fahr this looks great. I’m new to home assistant and I’m having a bit of trouble following your tutorial. First, I had to change µg/m³ to ug/m3 because I was getting an error. Is there a way of adding support for those characters? I’m using home assistant with docker on a synology nas.

Second, where do you put the code for calculating AQI? I tried to add to my configuration.yaml but I was getting this error:

Configuration invalid

Invalid config for [sensor.template]: expected dictionary for dictionary value @ data['sensors']. Got None
extra keys not allowed @ data['dyson_calc_aqi']. Got OrderedDict([('friendly_name', 'Dyson Calculated PM2.5 AQI'), ('unit_of_measurement', 'AQI'), ('unique_id', 'dypson_tp_04_calc_aqi'), ('value_template', '{% macro calcAQI(Cp, Ih, Il, BPh, BPl) -%}\n {{ (((Ih - Il)/(BPh - BPl)) * (Cp - BPl) + Il)|round }}\n{%- endmacro %} {% if (states("sensor.dyson_particulate_matter_2_5")|float) > 1000 %}\n invalid\n{% elif (states("sensor.dyson_particulate_matter_2_5")|float) > 350.5 %} {{ calcAQI((states("sensor.dyson_particulate_matter_2_5")|float), 500.... (See ?, line ?).

Thanks for the help!

Is there a way of adding support for those characters?

I’m not entirely sure about that, since it’s unicode it should just work out of the box in python 3.x.

Second, where do you put the code for calculating AQI?

Sorry about that, it should go with the other template sensors above that code. So in your configuration.yaml it would be nested under sensor.

sensor:
  - platform: template
    sensors:
      dyson_aqi:
        friendly_name: "Dyson TP-04 Air Quality Index"
        value_template: ""
        unit_of_measurement: AQI
        unique_id: dyson_tp_04_aqi

      dyson_particulate_matter_2_5:
        friendly_name: "Dyson TP-04 PM2.5"
        value_template: ""
        unit_of_measurement: "µg/m³"
        unique_id: dyson_tp_04_pm2_5

      dyson_particulate_matter_10:
        friendly_name: "Dyson TP-04 PM10"
        value_template: ""
        unit_of_measurement: "µg/m³"
        unique_id: dyson_tp_04_pm_10

      dyson_volatile_organic_compounds:
        friendly_name: "Dyson TP-04 Volatile Organic Compounds"
        value_template: ""
        unit_of_measurement: "VOC Scale"
        unique_id: dyson_tp_04_voc

      dyson_nitrogen_dioxide:
        friendly_name: "Dyson TP-04 Nitrogen Dioxide"
        value_template: ""
        unit_of_measurement: NO2 Scale
        unique_id: dyson_tp_04_no2
 
     dyson_calc_aqi:
       # ...rest of the config

Thanks! This works and looks great! If you take feature requests. I would love if the card had a slider or something like that for manually setting the speed.

Awesome, glad you got it working! I had originally intended to add a button for angle and speed, but those require a bit more thought since you need some other control to pop-up and I haven’t ever used those functions before.

It’s just a picture-elements card so you could easily add your own when you get more familiar with Home Assistant and lovelace.

Hi Aaron,

Do you think you can update the syntax for the latest version of HA as it is not working any more?
I am not experienced enough to do that myself. I will appreciate if you can help.

Or this config won’t work with the new HA-Dyson integration?

I am getting this error:

Thanks

There are a few changes required, most of the template sensors are no longer needed. I’ll update the blog post with the updated yaml later today.

1 Like
diff --git a/lovelace/danielle.yaml b/lovelace/dyson.yaml
index 751025f..68fb9d8 100644
--- a/lovelace/dyson.yaml
+++ b/lovelace/dyson.yaml
@@ -256,15 +256,13 @@ cards:
         - type: state-icon
           state_color: false
           icon: mdi:sleep
-          title_template: 'Night mode {% if state_attr("fan.master_bedroom", "night_mode") %}(click to disable){% else %}(click to enable){% endif %}'
+          title_template: 'Night mode {% if states("switch.master_bedroom_night_mode") == "on" %}(click to disable){% else %}(click to enable){% endif %}'
           entity: fan.master_bedroom
           tap_action:
             action: call-service
-            service: dyson.set_night_mode
+            service: switch.toggle
             service_data:
-              entity_id: fan.master_bedroom
-              night_mode_template: >-
-                {% if state_attr("fan.master_bedroom", "night_mode") %}false{% else %}true{% endif %}
+              entity_id: switch.master_bedroom_night_mode
           style:
             right: 0
             bottom: 0
@@ -272,20 +270,18 @@ cards:
             transform: translate(0%,0%)
             font-size: 16px
             line-height: 16px
-            --paper-item-icon-color_template: '{% if state_attr("fan.master_bedroom", "night_mode") %}green{% else %}rgb(68, 115, 158){% endif %}'
+            --paper-item-icon-color_template: '{% if states("switch.master_bedroom_night_mode") == "on" %}green{% else %}rgb(68, 115, 158){% endif %}'
 
         - type: state-icon
           state_color: false
           icon: mdi:alpha-a-circle
-          title_template: 'Auto mode {% if state_attr("fan.master_bedroom", "auto_mode") %}(click to disable){% else %}(click to enable){% endif %}'
+          title_template: 'Auto mode {% if states("switch.master_bedroom_auto_mode") == "on" %}(click to disable){% else %}(click to enable){% endif %}'
           entity: fan.master_bedroom
           tap_action:
             action: call-service
-            service: dyson.set_auto_mode
+            service: switch.toggle
             service_data:
-              entity_id: fan.master_bedroom
-              auto_mode_template: >-
-                {% if state_attr("fan.master_bedroom", "auto_mode") %}false{% else %}true{% endif %}
+              entity_id: switch.master_bedroom_auto_mode
           style:
             right: 61px
             bottom: 0
@@ -293,7 +289,7 @@ cards:
             transform: translate(0%,0%)
             font-size: 16px
             line-height: 16px
-            --paper-item-icon-color_template: '{% if state_attr("fan.master_bedroom", "auto_mode") %}green{% else %}rgb(68, 115, 158){% endif %}'
+            --paper-item-icon-color_template: '{% if states("switch.master_bedroom_auto_mode") == "on" %}green{% else %}rgb(68, 115, 158){% endif %}'
 
         - type: state-icon
           state_color: false
@@ -370,19 +366,20 @@ cards:
             transform: translate(0%,0%)
 
         - type: state-label
-          entity:  sensor.dyson_particulate_matter_2_5
+          entity:  air_quality.master_bedroom
+          attribute: particulate_matter_2_5
           suffix: ' PM2.5'
           style:
             background-color_template: >-
-              {% if states("sensor.dyson_particulate_matter_2_5")|float > 250 %}
+              {% if state_attr("air_quality.master_bedroom", "particulate_matter_2_5")|float > 250 %}
               #B71C1C
-              {% elif states("sensor.dyson_particulate_matter_2_5")|float > 150 %}
+              {% elif state_attr("air_quality.master_bedroom", "particulate_matter_2_5")|float > 150 %}
               #9C27B0
-              {% elif states("sensor.dyson_particulate_matter_2_5")|float > 70 %}
+              {% elif state_attr("air_quality.master_bedroom", "particulate_matter_2_5")|float > 70 %}
               #E53935
-              {% elif states("sensor.dyson_particulate_matter_2_5")|float > 53 %}
+              {% elif state_attr("air_quality.master_bedroom", "particulate_matter_2_5")|float > 53 %}
               #FB8C00
-              {% elif states("sensor.dyson_particulate_matter_2_5")|float > 35 %}
+              {% elif state_attr("air_quality.master_bedroom", "particulate_matter_2_5")|float > 35 %}
               #FFC107
               {% else %}
               #4CAF50
@@ -400,19 +397,20 @@ cards:
             transform: translate(0%,0%)
 
         - type: state-label
-          entity:  sensor.dyson_particulate_matter_10
+          entity: air_quality.master_bedroom
+          attribute: particulate_matter_10
           suffix: ' PM10'
           style:
             background-color_template: >-
-              {% if states("sensor.dyson_particulate_matter_10")|float > 420 %}
+              {% if state_attr("air_quality.master_bedroom", "particulate_matter_10")|float > 420 %}
               #B71C1C
-              {% elif states("sensor.dyson_particulate_matter_10")|float > 350 %}
+              {% elif state_attr("air_quality.master_bedroom", "particulate_matter_10")|float > 350 %}
               #9C27B0
-              {% elif states("sensor.dyson_particulate_matter_10")|float > 100 %}
+              {% elif state_attr("air_quality.master_bedroom", "particulate_matter_10")|float > 100 %}
               #E53935
-              {% elif states("sensor.dyson_particulate_matter_10")|float > 75 %}
+              {% elif state_attr("air_quality.master_bedroom", "particulate_matter_10")|float > 75 %}
               #FB8C00
-              {% elif states("sensor.dyson_particulate_matter_10")|float > 50 %}
+              {% elif state_attr("air_quality.master_bedroom", "particulate_matter_10")|float > 50 %}
               #FFC107
               {% else %}
               #4CAF50
@@ -430,14 +428,16 @@ cards:
             transform: translate(0%,0%)
 
         - type: state-label
-          entity: sensor.dyson_nitrogen_dioxide
+          entity: air_quality.master_bedroom
+          attribute: nitrogen_dioxide
+          suffix: ' NO2'
           style:
             background-color_template: >-
-              {% if states("sensor.dyson_nitrogen_dioxide")|float > 8 %}
+              {% if state_attr("air_quality.master_bedroom", "nitrogen_dioxide")|float > 8 %}
               #E53935
-              {% elif states("sensor.dyson_nitrogen_dioxide")|float > 6 %}
+              {% elif state_attr("air_quality.master_bedroom", "nitrogen_dioxide")|float > 6 %}
               #FB8C00
-              {% elif states("sensor.dyson_nitrogen_dioxide")|float > 3 %}
+              {% elif state_attr("air_quality.master_bedroom", "nitrogen_dioxide")|float > 3 %}
               #FFC107
               {% else %}
               #4CAF50
@@ -455,14 +455,16 @@ cards:
             transform: translate(0%,0%)
 
         - type: state-label
-          entity: sensor.dyson_volatile_organic_compounds
+          entity: air_quality.master_bedroom
+          attribute: volatile_organic_compounds
+          suffix: ' VOC'
           style:
             background-color_template: >-
-              {% if states("sensor.dyson_volatile_organic_compounds")|float > 8 %}
+              {% if state_attr("air_quality.master_bedroom", "volatile_organic_compounds")|float > 8 %}
               #E53935
-              {% elif states("sensor.dyson_volatile_organic_compounds")|float > 6 %}
+              {% elif state_attr("air_quality.master_bedroom", "volatile_organic_compounds")|float > 6 %}
               #FB8C00
-              {% elif states("sensor.dyson_volatile_organic_compounds")|float > 3 %}
+              {% elif state_attr("air_quality.master_bedroom", "volatile_organic_compounds")|float > 3 %}
               #FFC107
               {% else %}
               #4CAF50
@@ -524,7 +526,7 @@ cards:
         # Filters
 
         - type: custom:circle-sensor-card
-          entity: sensor.dyson_carbon_filter
+          entity: sensor.master_bedroom_carbon_filter_life
           name: Carbon Filter
           fill: rgba(0, 0, 0, 0.7)
           style:

Working on updating the blog post, but in the interim this diff might make it easier for you to see what lines need to be updated.

1 Like

Ok blog post is up to date now with the new custom integration: Integrating the Dyson TP04 Air Purifier in Home Assistant - Automate The Things

1 Like

Hi @fahr,

I am having a bit of an issue with some of the bits:

For some reason the 3 attribute of the entity: air_quality.dyson are not available this is the error message I get.
However when I use an entity card it works

Also the text is a bit off … when I expand the browser window the text it goes back in place though…

I wonder if you would be able to help with this issue :slight_smile:

Thanks for all your help.

For some reason the 3 attribute of the entity: air_quality.dyson are not available this is the error message I get.

This is a bug in the current version of home-assistant front-end. When specifying an attribute to show in a picture-element it will erroneously show a warning if the value is falsey (0, false, or ''). I submitted a fix for that bug that should be in the next release of home assistant.

Also the text is a bit off … when I expand the browser window the text it goes back in place though…

I don’t have a good idea how to address that particular issue, you could always try to adjust the styling to get it to center. Although that wouldn’t explain why it re-centers when you maximize the window.

1 Like

Aaron thank you very much for your time you have been super helpful :slight_smile:

I have one last question do you know how to add speed control for the Dyson Fan?

The custom integration supports the fan.set_percentage service: Fan - Home Assistant

I didn’t bother with this as I haven’t used the fan and didn’t want to think about how to display something more complex (selecting a value) in the UI. You could do this in a simpler fashion by adding your own buttons for low/medium/high and call that service with percentages like 25% for low, 50% for medium and 100% for high.

For example a button that would set the fan to 100% speed:

- type: state-icon
  icon: mdi:power
  entity: fan.master_bedroom
  tap_action:
    action: call-service
    service: fan.set_percentage
    service_data:
      entity_id: fan.master_bedroom
      percentage: 100
  style:
     # ... position it somewhere on the card

I was thinking more like a slider or some kind of way to set it from 1 to 10… or buttons for up and down to increase and decrease the speed.