Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Xiaomi Air Purifier 4 Compact (xiaomi.airp.cpa4) - No fan speed control #1674

Open
VolunPotest opened this issue May 18, 2024 · 5 comments
Open

Comments

@VolunPotest
Copy link

VolunPotest commented May 18, 2024

Device model / 设备型号

xiaomi.airp.cpa4

Component version / 插件版本

0.7.18

HA core version / HA版本

2024.3.3

Integrated mode / 集成方式

Automatic (自动模式)

The problem / 问题详情

Hi!

I can't control the fan speed on the device.
Is it possible to add support for that?

Entity attributes / 实体属性

N?A

Home Assistant Logs / 系统日志

No response

@VolunPotest VolunPotest changed the title Xiaomi Air Purifier 4 Compact Comp Xiaomi Air Purifier 4 Compact (xiaomi.airp.cpa4) - No fan speed control May 18, 2024
@Samay97
Copy link

Samay97 commented May 25, 2024

Same for me too. Would be nice to have this feature. Support for changing modes would also be very nice.

@bugale
Copy link

bugale commented Jun 14, 2024

It is possible to set the fan speed manually using a service call, e.g.:

service: xiaomi_miot.set_miot_property
data:
  entity_id: fan.xiaomi_cpa4_7865_air_purifier
  siid: 9
  piid: 11
  value: 4

This sets the manual level to 4.

To find the properties, you can install latest python-miio on some computer:
pip install git+https://github.com/rytilahti/python-miio.git
Then find your device IP and token (e.g. using miiocli cloud), and running:

> miiocli genericmiot --ip <ip> --token <token> settings
Running command settings
Switch Status (air-purifier:on)
        Type: <class 'bool'>
        Attribute: air_purifier_on
        Access: rw-
        Extras: {'urn': <URN urn:miot-spec-v2:property:on:00000006:xiaomi-cpa4:1 parent:namespace='miot-spec-v2' type='service' name='air-purifier' internal_id='00007811' model='xiaomi-cpa4' version=1 unexpected=None>, 'siid': 2, 'piid': 1, 'miot_property': MiotProperty(urn=<URN urn:miot-spec-v2:property:on:00000006:xiaomi-cpa4:1 parent:namespace='miot-spec-v2' type='service' name='air-purifier' internal_id='00007811' model='xiaomi-cpa4' version=1 unexpected=None>, description='Switch Status', service=MiotService(siid=2, urn=<URN urn:miot-spec-v2:service:air-purifier:00007811:xiaomi-cpa4:1 parent:None>, description='Air Purifier'), piid=1, format=<class 'bool'>, access=[<MiotAccess.Read: 'read'>, <MiotAccess.Write: 'write'>, <MiotAccess.Notify: 'notify'>], unit=None, range=None, choices=None, gatt_access=None, value=None)}
        Setter: functools.partial(<bound method MiotDevice.set_property_by of <GenericMiot: 192.168.1.116 (token: f6e2cba59591dc9d5b7aed1f7fad417d)>>, 2, 1, name='air-purifier:on')
        Constraint: PropertyConstraint.Unset

Mode (air-purifier:mode)
        Type: <class 'int'>
        Attribute: air_purifier_mode
        Access: rw-
        Extras: {'urn': <URN urn:miot-spec-v2:property:mode:00000008:xiaomi-cpa4:1 parent:namespace='miot-spec-v2' type='service' name='air-purifier' internal_id='00007811' model='xiaomi-cpa4' version=1 unexpected=None>, 'siid': 2, 'piid': 4, 'miot_property': MiotProperty(urn=<URN urn:miot-spec-v2:property:mode:00000008:xiaomi-cpa4:1 parent:namespace='miot-spec-v2' type='service' name='air-purifier' internal_id='00007811' model='xiaomi-cpa4' version=1 unexpected=None>, description='Mode', service=MiotService(siid=2, urn=<URN urn:miot-spec-v2:service:air-purifier:00007811:xiaomi-cpa4:1 parent:None>, description='Air Purifier'), piid=4, format=<class 'int'>, access=[<MiotAccess.Read: 'read'>, <MiotAccess.Write: 'write'>, <MiotAccess.Notify: 'notify'>], unit=None, range=None, choices=[MiotEnumValue(description='Auto', value=0), MiotEnumValue(description='Sleep', value=1), MiotEnumValue(description='Favorite', value=2)], gatt_access=[], value=None)}
        Setter: functools.partial(<bound method MiotDevice.set_property_by of <GenericMiot: 192.168.1.116 (token: f6e2cba59591dc9d5b7aed1f7fad417d)>>, 2, 4, name='air-purifier:mode')
        Constraint: PropertyConstraint.Choice
        Choices: <enum 'Mode'>

Alarm (alarm:alarm)
        Type: <class 'bool'>
        Attribute: alarm_alarm
        Access: rw-
        Extras: {'urn': <URN urn:miot-spec-v2:property:alarm:00000012:xiaomi-cpa4:1 parent:namespace='miot-spec-v2' type='service' name='alarm' internal_id='00007804' model='xiaomi-cpa4' version=1 unexpected=None>, 'siid': 6, 'piid': 1, 'miot_property': MiotProperty(urn=<URN urn:miot-spec-v2:property:alarm:00000012:xiaomi-cpa4:1 parent:namespace='miot-spec-v2' type='service' name='alarm' internal_id='00007804' model='xiaomi-cpa4' version=1 unexpected=None>, description='Alarm', service=MiotService(siid=6, urn=<URN urn:miot-spec-v2:service:alarm:00007804:xiaomi-cpa4:1 parent:None>, description='Alarm'), piid=1, format=<class 'bool'>, access=[<MiotAccess.Read: 'read'>, <MiotAccess.Write: 'write'>, <MiotAccess.Notify: 'notify'>], unit=None, range=None, choices=None, gatt_access=None, value=None)}
        Setter: functools.partial(<bound method MiotDevice.set_property_by of <GenericMiot: 192.168.1.116 (token: f6e2cba59591dc9d5b7aed1f7fad417d)>>, 6, 1, name='alarm:alarm')
        Constraint: PropertyConstraint.Unset

Physical Control Locked (physical-controls-locked:physical-controls-locked)
        Type: <class 'bool'>
        Attribute: physical_controls_locked_physical_controls_locked
        Access: rw-
        Extras: {'urn': <URN urn:miot-spec-v2:property:physical-controls-locked:0000001D:xiaomi-cpa4:1 parent:namespace='miot-spec-v2' type='service' name='physical-controls-locked' internal_id='00007807' model='xiaomi-cpa4' version=1 unexpected=None>, 'siid': 8, 'piid': 1, 'miot_property': MiotProperty(urn=<URN urn:miot-spec-v2:property:physical-controls-locked:0000001D:xiaomi-cpa4:1 parent:namespace='miot-spec-v2' type='service' name='physical-controls-locked' internal_id='00007807' model='xiaomi-cpa4' version=1 unexpected=None>, description='Physical Control Locked', service=MiotService(siid=8, urn=<URN urn:miot-spec-v2:service:physical-controls-locked:00007807:xiaomi-cpa4:1 parent:None>, description='Physical Control Locked'), piid=1, format=<class 'bool'>, access=[<MiotAccess.Read: 'read'>, <MiotAccess.Write: 'write'>, <MiotAccess.Notify: 'notify'>], unit=None, range=None, choices=None, gatt_access=None, value=None)}
        Setter: functools.partial(<bound method MiotDevice.set_property_by of <GenericMiot: 192.168.1.116 (token: f6e2cba59591dc9d5b7aed1f7fad417d)>>, 8, 1, name='physical-controls-locked:physical-controls-locked')
        Constraint: PropertyConstraint.Unset

Brightness (screen:brightness)
        Type: <class 'int'>
        Unit: percentage
        Attribute: screen_brightness
        Access: rw-
        Extras: {'urn': <URN urn:miot-spec-v2:property:brightness:0000000D:xiaomi-cpa4:1 parent:namespace='miot-spec-v2' type='service' name='screen' internal_id='00007806' model='xiaomi-cpa4' version=1 unexpected=None>, 'siid': 13, 'piid': 2, 'miot_property': MiotProperty(urn=<URN urn:miot-spec-v2:property:brightness:0000000D:xiaomi-cpa4:1 parent:namespace='miot-spec-v2' type='service' name='screen' internal_id='00007806' model='xiaomi-cpa4' version=1 unexpected=None>, description='Brightness', service=MiotService(siid=13, urn=<URN urn:miot-spec-v2:service:screen:00007806:xiaomi-cpa4:1 parent:None>, description='Screen'), piid=2, format=<class 'int'>, access=[<MiotAccess.Read: 'read'>, <MiotAccess.Write: 'write'>, <MiotAccess.Notify: 'notify'>], unit='percentage', range=None, choices=[MiotEnumValue(description='Close', value=0), MiotEnumValue(description='Bright', value=1), MiotEnumValue(description='Brightness', value=2)], gatt_access=[], value=None)}
        Setter: functools.partial(<bound method MiotDevice.set_property_by of <GenericMiot: 192.168.1.116 (token: f6e2cba59591dc9d5b7aed1f7fad417d)>>, 13, 2, name='screen:brightness')
        Constraint: PropertyConstraint.Choice
        Choices: <enum 'Brightness'>

country-code (custom-service:country-code)
        Type: <class 'int'>
        Attribute: custom_service_country_code
        Access: rw-
        Extras: {'urn': <URN urn:xiaomi-spec:property:country-code:0000000a:xiaomi-cpa4:1 parent:namespace='xiaomi-spec' type='service' name='custom-service' internal_id='00007801' model='xiaomi-cpa4' version=1 unexpected=None>, 'siid': 9, 'piid': 10, 'miot_property': MiotProperty(urn=<URN urn:xiaomi-spec:property:country-code:0000000a:xiaomi-cpa4:1 parent:namespace='xiaomi-spec' type='service' name='custom-service' internal_id='00007801' model='xiaomi-cpa4' version=1 unexpected=None>, description='country-code', service=MiotService(siid=9, urn=<URN urn:xiaomi-spec:service:custom-service:00007801:xiaomi-cpa4:1 parent:None>, description='custom-service'), piid=10, format=<class 'int'>, access=[<MiotAccess.Read: 'read'>, <MiotAccess.Notify: 'notify'>, <MiotAccess.Write: 'write'>], unit=None, range=None, choices=[MiotEnumValue(description='CN', value=17230), MiotEnumValue(description='EU', value=17749), MiotEnumValue(description='TH', value=21576)], gatt_access=[], value=None)}
        Setter: functools.partial(<bound method MiotDevice.set_property_by of <GenericMiot: 192.168.1.116 (token: f6e2cba59591dc9d5b7aed1f7fad417d)>>, 9, 10, name='custom-service:country-code')
        Constraint: PropertyConstraint.Choice
        Choices: <enum 'country-code'>

 (custom-service:favorite-level)
        Type: <class 'int'>
        Attribute: custom_service_favorite_level
        Access: rw-
        Extras: {'urn': <URN urn:xiaomi-spec:property:favorite-level:00000002:xiaomi-cpa4:1 parent:namespace='xiaomi-spec' type='service' name='custom-service' internal_id='00007801' model='xiaomi-cpa4' version=1 unexpected=None>, 'siid': 9, 'piid': 11, 'miot_property': MiotProperty(urn=<URN urn:xiaomi-spec:property:favorite-level:00000002:xiaomi-cpa4:1 parent:namespace='xiaomi-spec' type='service' name='custom-service' internal_id='00007801' model='xiaomi-cpa4' version=1 unexpected=None>, description='', service=MiotService(siid=9, urn=<URN urn:xiaomi-spec:service:custom-service:00007801:xiaomi-cpa4:1 parent:None>, description='custom-service'), piid=11, format=<class 'int'>, access=[<MiotAccess.Read: 'read'>, <MiotAccess.Notify: 'notify'>, <MiotAccess.Write: 'write'>], unit=None, range=[0, 14, 1], choices=None, gatt_access=None, value=None)}
        Setter: functools.partial(<bound method MiotDevice.set_property_by of <GenericMiot: 192.168.1.116 (token: f6e2cba59591dc9d5b7aed1f7fad417d)>>, 9, 11, name='custom-service:favorite-level')
        Constraint: PropertyConstraint.Range
        Range: 0 - 14 (step 1)

 (custom-service:filter-used-time-dbg)
        Type: <class 'int'>
        Unit: hours
        Attribute: custom_service_filter_used_time_dbg
        Access: -w-
        Extras: {'urn': <URN urn:xiaomi-spec:property:filter-used-time-dbg:00000003:xiaomi-cpa4:1 parent:namespace='xiaomi-spec' type='service' name='custom-service' internal_id='00007801' model='xiaomi-cpa4' version=1 unexpected=None>, 'siid': 9, 'piid': 12, 'miot_property': MiotProperty(urn=<URN urn:xiaomi-spec:property:filter-used-time-dbg:00000003:xiaomi-cpa4:1 parent:namespace='xiaomi-spec' type='service' name='custom-service' internal_id='00007801' model='xiaomi-cpa4' version=1 unexpected=None>, description='', service=MiotService(siid=9, urn=<URN urn:xiaomi-spec:service:custom-service:00007801:xiaomi-cpa4:1 parent:None>, description='custom-service'), piid=12, format=<class 'int'>, access=[<MiotAccess.Write: 'write'>], unit='hours', range=[0, 7000, 1], choices=None, gatt_access=None, value=None)}
        Setter: functools.partial(<bound method MiotDevice.set_property_by of <GenericMiot: 192.168.1.116 (token: f6e2cba59591dc9d5b7aed1f7fad417d)>>, 9, 12, name='custom-service:filter-used-time-dbg')
        Constraint: PropertyConstraint.Range
        Range: 0 - 7000 (step 1)

 (aqi:aqi-updata-heartbeat)
        Type: <class 'int'>
        Attribute: aqi_aqi_updata_heartbeat
        Access: rw-
        Extras: {'urn': <URN urn:xiaomi-spec:property:aqi-updata-heartbeat:00000004:xiaomi-cpa4:1 parent:namespace='xiaomi-spec' type='service' name='aqi' internal_id='00007803' model='xiaomi-cpa4' version=1 unexpected=None>, 'siid': 11, 'piid': 4, 'miot_property': MiotProperty(urn=<URN urn:xiaomi-spec:property:aqi-updata-heartbeat:00000004:xiaomi-cpa4:1 parent:namespace='xiaomi-spec' type='service' name='aqi' internal_id='00007803' model='xiaomi-cpa4' version=1 unexpected=None>, description='', service=MiotService(siid=11, urn=<URN urn:xiaomi-spec:service:aqi:00007803:xiaomi-cpa4:1 parent:None>, description='aqi'), piid=4, format=<class 'int'>, access=[<MiotAccess.Read: 'read'>, <MiotAccess.Notify: 'notify'>, <MiotAccess.Write: 'write'>], unit=None, range=[0, 65535, 1], choices=None, gatt_access=None, value=None)}
        Setter: functools.partial(<bound method MiotDevice.set_property_by of <GenericMiot: 192.168.1.116 (token: f6e2cba59591dc9d5b7aed1f7fad417d)>>, 11, 4, name='aqi:aqi-updata-heartbeat')
        Constraint: PropertyConstraint.Range
        Range: 0 - 65535 (step 1)

@VolunPotest
Copy link
Author

VolunPotest commented Jun 15, 2024

I have an update on this!

Yes, @bugale, I was able to set the priority. Thank you!
I also added a custom button to control the speed.

Here how I did this.
DON't forget to change your entity_id!

  1. Add a custom script to HA
alias: Set Fan Speed
sequence:
  - service: xiaomi_miot.set_miot_property
    data:
      entity_id: fan.xiaomi_cpa4_7xxx_air_purifier
      siid: 9
      piid: 11
      value: >
            {% set percentage = states('input_number.fan_speed_percentage') | int(0) %}
            {% set speed = (percentage * 14 / 100) | round(0) %}
            {{ speed }}
mode: single
description: ""
icon: mdi:fan
  1. Add A input_number to configuration.yaml file
input_number:
  fan_speed_percentage:
    name: Fan Speed Percentage
    min: 0
    max: 100
    step: 1
    unit_of_measurement: "%"

  1. Create a new automation!
alias: Adjust Fan Speed
trigger:
  - platform: state
    entity_id: input_number.fan_speed_percentage
action:
  - service: script.set_fan_speed

  1. Create a custom card
type: entities
entities:
  - entity: fan.xiaomi_cpa4_7xxx_air_purifier
  - entity: input_number.fan_speed_percentage
    name: Set Fan Speed
    icon: mdi:fan
    type: custom:slider-entity-row

After that you should see something like this
image

@JurekAndrzejewski
Copy link

@VolunPotest Sadly, your solution does not work for my air purifier (compact 4). Do I have to restart purifier for it to work or do any additional stuff?

@al-one
Copy link
Owner

al-one commented Oct 28, 2024

Try master branch.

wget -O - https://get.hacs.vip | DOMAIN=xiaomi_miot ARCHIVE_TAG=master bash -

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants