Philips Air Purifier

This was also my finding, and what I did was, I removed all models that I didn’t have from the repository in order to speed up loading.

I guess this made it load a bit faster, and my AC1214 and AC3829 now load (almost) all the time…
(So I still use the original repository, but just shortened the list of supported models)

The devices have now come back (I didn’t change anything), but are as unreliable as before. My interpretation is:

  • When they’re not so responsive during HA startup, the integration just doesn’t set them up so they’re gone from the system for good.
  • When they’re responsive, they’re setup, but that doesn’t mean that they stay live after setup.

As your systems seem to be stabler, I wonder if there is anything different with my devices or with my network setup. One difference could be, that I have two devices in the network. What about you guys?

I noticed that if I shut down and start the purifier via the dedicated app just before restarting HA, integration is successful most of the time

I’ve taken one device off the network for the last twelve hours. It doesn’t help. The remaining device was stable at first, but then started to drop commands. Interestingly, the state continued to be update but I couldn’t control it anymore. I also tried the command line aioairctrl utility, but while this was observing status updates in the beginning, it stopped reporting updates even before HA stopped receiving updates. Weird.

I have one coap device, other 2 are luckily http operated and are much more stable.

I recognize the issue you refer to. If the device is not recognized during ha restart a manual toggle will work and make it appear. No need for me to then also restart HA again.

I also found that service calls typically also revive the device in ha. I use the scheduler custom integration to control my purifiers (on/off, sleep mode, allergen mode etc). Probably, as this relies on the service calls, that helps keep the communication with HA alive on my side.

I do not get rid of the errors in my log though. 1000’s per day. This is the case since the October updates

Logger: coap
Source: /usr/local/lib/python3.9/site-packages/aiocoap/transports/udp6.py:525
First occurred: 09:15:29 (179 occurrences)
Last logged: 11:33:14

Connection loss was not expected.

Since i am using kongo09’s design i wanna share my solution. I changed a few lines to get it running on my 3033/10. I am using your github respository and i have deleted entity.attributes.function. It feels like randomly adding the following code to your configuration.yaml speeds up the start of the purifier. At least for me.

netatmo:
  client_id: dummy
  client_secret: dummy

ac_state:
    variables:
      is_on: '[[[ return entity && entity.state && entity.state == "on" ]]]'
      is_off: '[[[ return entity && entity.state && entity.state == "off" ]]]'
      is_pur: |-
        [[[ return entity && entity.attributes &&
            entity.attributes.function == "Purification"
        ]]]
      is_backlight: |-
        [[[ return entity && entity.attributes &&
            entity.attributes.light_brightness > 0
        ]]]
      is_child_lock: |-
        [[[ return entity && entity.attributes &&
            entity.attributes.child_lock > 0
        ]]]
      is_pm25: >-
        [[[ return entity && entity.attributes &&
        entity.attributes.preferred_index &&
            entity.attributes.preferred_index == "PM2.5"
        ]]]
      has_total_volatile_organic_compounds: |-
        [[[
          return (entity && entity.attributes ) ?
          entity.attributes.total_volatile_organic_compounds : -1
        ]]]
      has_speed: >-
        [[[ return (entity && entity.attributes &&
        entity.attributes.preset_mode) ?
            entity.attributes.preset_mode : null
        ]]]
      has_iai: |-
        [[[
          return (entity && entity.attributes ) ?
          entity.attributes.indoor_allergen_index : -1
        ]]]
      has_pm25: |-
        [[[
          return (entity && entity.attributes ) ?
          entity.attributes.pm25 : -1
        ]]]
      has_days_pre: |-
        [[[
          return (entity && entity.attributes ) ?
          (entity.attributes.filter_pre_remaining).match(/\d+/i) : -1
        ]]]
      has_days_hepa: |-
        [[[
          return (entity && entity.attributes ) ?
          (entity.attributes.filter_hepa_remaining).match(/\d+/i) : -1
        ]]]
      has_days_carbon: |-
        [[[
          return (entity && entity.attributes ) ?
          (entity.attributes.filter_active_carbon_remaining).match(/\d+/i) : -1
        ]]]

Hello everyone

As of a couple of days/week ago the Philips Airpurifier from Kraineff became a READ-ONLY but I intend to try to keep it alive as long as possible.

I have created a repository on Github for you. This repository is updated, 2021-12-23, to work with 2021.12 without errors for my Philips AC3259/10.
My fan dont have a humidifier so I cant guarantee this will work for you.

https://github.com/AcidSleeper/Philips-Airpurifier

Could you please show the YAML cards? I try to do it, but it works out like this ;/

Przechwytywanie

This looks strange. Are you using my YAML unchanged or did you tweak it? There was a tiny bug that I fixed some time ago and updated my code, so maybe copy-paste will help?

I copy yours YAML and only change name of entity. This is My YAML:

type: vertical-stack
layout: horizontal
cards:
  - type: custom:button-card
    icon: custom:circle
    entity: fan.philips_airpurifier
    show_name: false
    template: ac_state
    size: 100%
    state:
      - operator: template
        value: '[[[ return variables.has_iai <= 3 ]]]'
        color: blue
      - operator: template
        value: '[[[ return variables.has_iai <= 6 ]]]'
        color: '#6666ff'
      - operator: template
        value: '[[[ return variables.has_iai <= 9 ]]]'
        color: '#ff00ff'
      - operator: template
        value: '[[[ return variables.has_iai > 9 ]]]'
        color: red
    styles:
      icon:
        - filter: drop-shadow(0 0 0.7rem)
      card:
        - pointer-events: none
      grid:
        - position: relative
      custom_fields:
        primary_reading:
          - position: absolute
          - top: 50%
          - left: 50%
          - transform: translate(-50%, -60%)
          - pointer-events: none
        secondary_reading:
          - position: absolute
          - top: 57%
          - left: 50%
          - transform: translate(-50%, 0%)
          - pointer-events: none
        notifications:
          - position: absolute
          - top: 25%
          - left: 50%
          - transform: translate(-50%, 0%)
          - pointer-events: none
    custom_fields:
      notifications:
        card:
          type: horizontal-stack
          cards:
            - type: custom:button-card
              template: ac_notifications
              icon: mdi:air-filter
              color: darkgreen
              state:
                - operator: template
                  value: '[[[ return variables.has_days_pre <=1 ]]]'
                  styles:
                    icon:
                      - color: darkred
                      - animation: blink 3s ease infinite
                - operator: template
                  value: '[[[ return variables.has_days_pre <=3 ]]]'
                  styles:
                    icon:
                      - color: darkorange
            - type: custom:button-card
              template: ac_notifications
              icon: philips:filter_replacement
              color: darkgreen
              state:
                - operator: template
                  value: '[[[ return variables.has_days_hepa <=1 ]]]'
                  styles:
                    icon:
                      - color: darkred
                      - animation: blink 3s ease infinite
                - operator: template
                  value: '[[[ return variables.has_days_hepa <=3 ]]]'
                  styles:
                    icon:
                      - color: darkorange
            - type: custom:button-card
              template: ac_notifications
              icon: mdi:image-filter-none
              color: darkgreen
              state:
                - operator: template
                  value: '[[[ return variables.has_days_carbon <=1 ]]]'
                  styles:
                    icon:
                      - color: darkred
                      - animation: blink 3s ease infinite
                - operator: template
                  value: '[[[ return variables.has_days_carbon <=3 ]]]'
                  styles:
                    icon:
                      - color: darkorange
            - type: custom:state-switch
              entity: template
              template: '[[[ return variables.has_water >= 0 && !variables.is_pur ]]]'
              states:
                'true':
                  type: custom:button-card
                  template: ac_notifications
                  icon: philips:water_refill
                  color: darkgreen
                  state:
                    - operator: template
                      value: '[[[ return variables.has_water <=10 ]]]'
                      styles:
                        icon:
                          - color: darkred
                          - animation: blink 3s ease infinite
                    - operator: template
                      value: '[[[ return variables.has_water <=30 ]]]'
                      styles:
                        icon:
                          - color: darkorange
            - type: custom:state-switch
              entity: template
              template: '[[[ return variables.has_days_wick >= 0 && !variables.is_pur ]]]'
              states:
                'true':
                  type: custom:button-card
                  template: ac_notifications
                  icon: philips:prefilter_wick_cleaning
                  color: darkgreen
                  state:
                    - operator: template
                      value: '[[[ return variables.has_days_wick <=1 ]]]'
                      styles:
                        icon:
                          - color: darkred
                          - animation: blink 3s ease infinite
                    - operator: template
                      value: '[[[ return variables.has_days_wick <=3 ]]]'
                      styles:
                        icon:
                          - color: darkorange
      secondary_reading:
        card:
          type: vertical-stack
          cards:
            - type: custom:button-card
              template: ac_readings
              icon: |
                [[[
                  if (variables.is_pm25)
                    return 'philips:iai' 
                  else
                    return 'philips:pm25'
                ]]]              
              variables:
                var_reading_text: |
                  [[[
                    if (variables.is_pm25)
                      return variables.has_iai
                    else
                      return variables.has_pm25
                  ]]] 
            - type: custom:state-switch
              entity: template
              template: '[[[ return variables.has_temp >= 0 ]]]'
              states:
                'true':
                  type: custom:button-card
                  template:
                    - ac_readings
                    - ac_state
                  icon: hass:thermometer
                  variables:
                    var_reading_text: '[[[ return variables.has_temp + " °C" ]]]'
            - type: custom:state-switch
              entity: template
              template: '[[[ return variables.has_humidity >= 0 ]]]'
              states:
                'true':
                  type: custom:button-card
                  template: ac_readings
                  icon: philips:humidity_button
                  variables:
                    var_reading_text: '[[[ return variables.has_humidity + " %" ]]]'
      primary_reading:
        card:
          type: custom:button-card
          icon: |
            [[[
              if (variables.is_pm25)
                return 'philips:pm25' 
              else
                return 'philips:iai'
            ]]] 
          size: 50%
          label: |
            [[[
              if (variables.is_pm25)
                return variables.has_pm25
              else
                return variables.has_iai
            ]]] 
          layout: icon_label
          show_label: true
          styles:
            label:
              - font-size: 400%
          style: |
            ha-card {
              box-shadow: none;
              background: none;
            }
  - type: horizontal-stack
    cards:
      - type: custom:button-card
        template: buttons
        icon: philips:power_button
        entity: fan.air_ac2729
        name: Power
        tap_action:
          action: call-service
          service: script.toggle_ac_power
          service_data:
            entity_id: entity
      - type: custom:button-card
        template:
          - buttons
          - ac_state
        entity: fan.air_ac2729
        name: Lüfter
        tap_action:
          action: call-service
          service: script.toggle_ac_fan_speed
          service_data:
            entity_id: entity
        state:
          - operator: template
            value: '[[[ return variables.is_off ]]]'
            styles:
              card:
                - pointer-events: none
          - operator: template
            value: '[[[ return variables.is_on ]]]'
            id: activated_state
            icon: |-
              [[[
                switch (variables.has_speed) {
                  case "1":
                    return "philips:fan_speed_button"
                  case "2":
                    return "philips:fan_speed_button"
                  case "3":
                    return "philips:fan_speed_button"
                  case "auto":
                    return "philips:auto_mode"
                  case "allergen":
                    return "philips:allergen_mode"
                  case "night":
                    return "philips:sleep_mode"
                  case "turbo":
                    return "philips:fan_speed_button"
                }
              ]]]
        styles:
          icon:
            - animation: |-
                [[[
                  var speed = 'linear 0s infinite normal none running rotating';
                  switch (variables.has_speed) {
                    case '1':
                      return '12s ' + speed;
                    case '2':
                      return '6s ' + speed;
                    case '3':
                      return '2s ' + speed;
                    case 'turbo':
                      return '0.5s ' + speed;
                    default:
                      return 'none'; 
                  }
                ]]]
          grid:
            - position: relative
          custom_fields:
            fan_speed:
              - position: absolute
              - top: 47%
              - left: 42%
              - transform: translate(-50%, -60%)
              - pointer-events: none
        custom_fields:
          fan_speed:
            card:
              type: custom:button-card
              template: activated_state
              color_type: icon
              show_icon: false
              show_label: true
              label: |-
                [[[
                  switch (variables.has_speed) {
                    case '1':
                      return '1';
                    case '2':
                      return '2';
                    case '3':
                      return '3';
                    case 'turbo':
                      return 't';
                  }
                ]]]
              state:
                - operator: template
                  value: '[[[ return variables.is_on ]]]'
                  id: activated_state
              styles:
                label:
                  - padding: 2px 6px 0px 6px
                  - font-weight: bold
                  - color: |
                      [[[
                        if (variables.is_off)
                          return 'var(--paper-item-icon-color)';
                        else
                          return 'var(--mmp-accent-color, var(--accent-color))';
                      ]]]
              style: |
                ha-card {
                  box-shadow: none;
                }
      - type: custom:button-card
        template:
          - buttons
          - ac_state
        icon: philips:light_dimming_button
        entity: fan.air_ac2729
        name: Anzeige
        tap_action:
          action: call-service
          service: script.toggle_ac_light
          service_data:
            entity_id: entity
        state:
          - operator: template
            value: '[[[ return variables.is_off ]]]'
            styles:
              card:
                - pointer-events: none
          - operator: template
            value: '[[[ return variables.is_backlight ]]]'
            id: activated_state
      - type: custom:button-card
        template:
          - buttons
          - ac_state
        entity: fan.air_ac2729
        name: Modus
        tap_action:
          action: call-service
          service: script.toggle_ac_two_in_one_mode
          service_data:
            entity_id: entity
        state:
          - operator: template
            value: '[[[ return variables.is_on && variables.has_humidity > 0 ]]]'
            icon: >-
              [[[ return variables.is_pur ? "philips:purification_only_mode" :
              "philips:two_in_one_mode" ]]]
            id: activated_state
          - operator: template
            value: '[[[ return variables.is_off || variables.has_humidity < 0 ]]]'
            icon: >-
              [[[ return variables.is_pur ? "philips:purification_only_mode" :
              "philips:two_in_one_mode" ]]]
            styles:
              card:
                - pointer-events: none

Did you install my Phillips icons as well? Is the custom:button-card up to date?

Thank you! it worked for me, I have a 3033.

In log I get this warning when component starts:

2021-12-28 17:04:08 WARNING (MainThread) [homeassistant.helpers.entity] Entity fan.philips_airpurifier (<class 'custom_components.philips_airpurifier_coap.fan.PhilipsAC3033'>) implements device_state_attributes. Please report it to the custom component author.

EDIT:
device_version: 3.3.1
software_version: Ms3331
wifi_version: [email protected]

I did a diff with my yaml and noticed quite a few differences appart from the renamed entity.

  • You’re using your own icons? I’m not sure if that makes a difference, but it could explain why the icons are not shown on your buttons
  • The templates have been changed for the humidity_button. Might not make a difference? Or maybe it does?
  • The whole icon part for the toggle_ac_fan_speed was moved
  • and some other stuff is modified, moved or changed

Overall, that makes it difficult to judge if the changes introduced a problem. I suggest, you try with the original script first and then step by step adapt it to what you want.

Could you give the actual script here? I copied from your post from January.

Hello, do you know the scale for the pm25, voc and air quality?

Because I am want to do some automation but I don’t know the max values and the ranges of the “good” values…

I created a custom card for this air purifier. this is the link https://community.home-assistant.io/t/fan-control-with-set-preset-mode/372741

These are the values from the Philips Clean Home+ App for iOS. I hope this helps.

1 Like

Are there other components or steps necessary to add the purifier to HA?
I followed the “Installation” instructions but the air purifier stays unavailable.
Its an AC2889/10, device firmware version 1.0.7, WiFi Firmware version 68.3.

Are you really using “my” repository of Philips AirPurifier? Just asking… =)
There are other repositorys of Philips Airpurifier that uses “coap”

This problem with “device_state_attributes” I have fixed, but I dont have the “COAP” fan

Hey

Have you changed the ip-adress to your fans ip?

Yes I did. To be sure I removed the component and configuration and added it once more. Unfortunately the problem persists.
Interestingly Studio Code Server gives me this warning:
Screenshot 2022-01-06 at 21.15.02
But checking the configuration and restarting HA does not result in an error or warning.
After fixing the apparent error to:

fan:
  - platform: philips_airpurifier
    host: 192.168.182.25

and a successful restart without errors or warnings the state is still unavailable. Any ideas?