Xiaomi Humidifier support

I miscommented for LED level.
2 is off, 1 is Dim light and 0 is Bright light.(These are corrent)

What test do I have to do for extend component?
Please let me know it and I will follow it up~

Please provide the feedback of:

# target humidity?
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop '["limit_hum"]'
# parental controls?
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop '["child_lock"]'
# sounds?
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop '["volume"]'

pi@Tommy:~ $ sudo su -s /bin/bash homeassistant
homeassistant@Tommy:/home/pi $ source /srv/homeassistant/bin/activate
(homeassistant) homeassistant@Tommy:/home/pi $ # target humidity?
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop ‘[“limit_hum”]’

parental controls?

mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop ‘[“child_lock”]’

sounds?

(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop ‘[“limit_hum”]’
Sending cmd get_prop with params [‘limit_hum’]
[40]
(homeassistant) homeassistant@Tommy:/home/pi $ # parental controls?
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop ‘[“child_lock”]’
Sending cmd get_prop with params [‘child_lock’]
[‘off’]
(homeassistant) homeassistant@Tommy:/home/pi $ # sounds?
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop ‘[“volume”]’
Sending cmd get_prop with params [‘volume’]
[None]
(homeassistant) homeassistant@Tommy:/home/pi $

if you need more, pls let me konw it.

Okay. We are able to retrieve the child_lock and target humidity. Could you try to change the values by:


# error
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_limit_hum '[30]'
# ok
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_limit_hum '[40]'
# ok
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_limit_hum '[50]'
# ok
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_limit_hum '[60]'
# ok
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_limit_hum '[70]'
# ok
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_limit_hum '[80]'
# error
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_limit_hum '[90]'

# ok
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_child_lock '["on"]'
# ok
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_child_lock '["off"]'

What’s the response? I found another property I’m interested in:

mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop '["trans_level"]'

Do you know the meaning of trans_level? Does this value show up at the MiHome app?

(homeassistant) homeassistant@Tommy:/home/pi $ # error
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_limit_hum ‘[30]’
ERROR:miio.vacuum_cli:Unable to read the stored msgid: [Errno 2] No such file or directory: ‘/tmp/python-mirobo.seq’
Sending cmd set_limit_hum with params [30]
[‘ok’]
(homeassistant) homeassistant@Tommy:/home/pi $ # ok
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_limit_hum ‘[40]’
Sending cmd set_limit_hum with params [40]
[‘ok’]
(homeassistant) homeassistant@Tommy:/home/pi $ # ok
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_limit_hum ‘[50]’
Sending cmd set_limit_hum with params [50]
[‘ok’]
(homeassistant) homeassistant@Tommy:/home/pi $ # ok
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_limit_hum ‘[60]’
Sending cmd set_limit_hum with params [60]
[‘ok’]
(homeassistant) homeassistant@Tommy:/home/pi $ # ok
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_limit_hum ‘[70]’
Sending cmd set_limit_hum with params [70]
[‘ok’]
(homeassistant) homeassistant@Tommy:/home/pi $ # ok
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_limit_hum ‘[80]’
Sending cmd set_limit_hum with params [80]
[‘ok’]
(homeassistant) homeassistant@Tommy:/home/pi $ # error
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_limit_hum ‘[90]’
Sending cmd set_limit_hum with params [90]
{‘id’: 7, ‘error’: {‘message’: ‘invaild_arg’, ‘code’: -5001}}
(homeassistant) homeassistant@Tommy:/home/pi $ # ok
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_child_lock ‘[“on”]’
Sending cmd set_child_lock with params [‘on’]
[‘ok’]
(homeassistant) homeassistant@Tommy:/home/pi $ # ok
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_child_lock ‘[“off”]’
Sending cmd set_child_lock with params [‘off’]
[‘ok’]
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop ‘[“trans_level”]’
Sending cmd get_prop with params [‘trans_level’]
[30]
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop ‘[“trans_level”]’
Sending cmd get_prop with params [‘trans_level’]
[55]
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop ‘[“trans_level”]’
Sending cmd get_prop with params [‘trans_level’]
[85]

Although limit_hum 30 is OK, there is no change in Mi Home app because there is no 30% for target.
And child lock’s name in the Mi Home is “parental controls”
The trans_level is the speed.(right side of power button in Mi Home)
Speed 1 - trans_level 30
Speed 2 - trans_level 55
Speed 3 - trans_level 85

Can we control the trans_level?

# error
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_trans_level '[10]'
# what's the new value?
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop '["trans_level"]'

# ok
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_trans_level '[30]'
# 30
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop '["trans_level"]'

# error
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_trans_level '[45]'
# 45? vs. no change
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop '["trans_level"]'

# ok
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_trans_level '[55]'
# 55
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop '["trans_level"]'

# ok
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_trans_level '[85]'
# 85
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop '["trans_level"]'

# ok
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_trans_level '[95]'
# 95 vs. no change
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop '["trans_level"]'

And can you explain the correlation between “Speed” and “Operation Mode” (Auto, Silent, Favorite)? Speed it’s something like the favorite level of the Air Purifier, right? It affects the Operation Mode “Favorite” only.

Another question: If you set the target humidity to 30 by

mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_limit_hum '[30]'

Does the property “limit_hum” return the correct value (30) afterwards?

# should return 30
mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop '["limit_hum"]'

@af950833 Ping? :wink:

No, we can’t control the trans level.

(homeassistant) homeassistant@Tommy:/home/pi $ # error
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_trans_level ‘[10]’
Sending cmd set_trans_level with params [10]
{‘error’: {‘code’: -32601, ‘message’: ‘Method not found.’}, ‘id’: 5}
(homeassistant) homeassistant@Tommy:/home/pi $ # what’s the new value?
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop ‘[“trans_level”]’
Sending cmd get_prop with params [‘trans_level’]
[85]
(homeassistant) homeassistant@Tommy:/home/pi $ # ok
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_trans_level ‘[30]’
Sending cmd set_trans_level with params [30]
{‘error’: {‘code’: -32601, ‘message’: ‘Method not found.’}, ‘id’: 7}
(homeassistant) homeassistant@Tommy:/home/pi $ # 30
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop ‘[“trans_level”]’
Sending cmd get_prop with params [‘trans_level’]
[85]
(homeassistant) homeassistant@Tommy:/home/pi $

The below is the trans level of Speed 1, 2 and 3.
Speed 2 is 50 or 55 & Speed 3 is 80 or 85(I don’t know the deference)

(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop ‘[“trans_level”]’
Sending cmd get_prop with params [‘trans_level’]
[30]
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop ‘[“trans_level”]’
Sending cmd get_prop with params [‘trans_level’]
[50]
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop ‘[“trans_level”]’
Sending cmd get_prop with params [‘trans_level’]
[80]

The mode is same with the speed. The speed of Humidifier is diferent with Air Purifier. There is no favorite level in Humidifier.

Mi Home : Speed 1 - Speed 2 - Speed 3
Python-miio : Silent - Medium - High (Operation Mode)
(Speed is same with the mode)

(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command set_limit_hum ‘[30]’
Sending cmd set_limit_hum with params [30]
[‘ok’]
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.25 --token 689c4056fe28ebb3a2e8c2fe350e51ba raw_command get_prop ‘[“limit_hum”]’
Sending cmd get_prop with params [‘limit_hum’]
[30]
(homeassistant) homeassistant@Tommy:/home/pi $

The limit_hum 30 returned correct value but It was not reflected in the MI Home (bcz there is no 30% icon)
The current humidity of my home is 36% and the Humidifier is on state.
When I sent raw_command set_limit_hum ‘[30]’, the Humidifier was turned off.
I think that limit_hum 30 is working properly but it just doesn’t have own icon in the Mi Home App.

Did I understand it correctly: The trans_level changes if you change the operation mode?

Yes, right.
When I change the mode(Speed) in Mi Home, the trans_level also changed,
Upper trans_levels(30, 50, 80) are checked right after I changed the mode in Mi Home App

1 Like

@af950833 Many thanks for your work! I’ve released the first version of the custom component right now:

Please give it a try!

Thank you, syssi
I will try it now.
BTW there is no services.yaml file?

No. There is no services.yaml as long as it’s no official component. The home assistant api has changed and the services.yaml is shared over all platforms of a domain (“fan”). Home assistant doesn’t retrieve the services.yaml from the custom_components/fan folder without copying all fan/*.py files beforehand. In other words: There is no service description for custom components at the moment.

Everything is OK.
It works well.

@af950833 Do you own a rooted android device and are you familiar with the android debug bridge (adb)? If yes, I would like to request some plugin files (apks) of your xiaomi mihome app. :slight_smile:

Just a side note, a backup can be extracted also without rooting the device, usually at least :slight_smile:

Sorry.
I don’t have a rooted device.
Because my phone is connected to company, I can’t root it.
If you want a just apk files to install, I can extract it without rooting.

I found a old old old Samsung Galaxy S3 :slight_smile:
I installed Mi Home and rooted the phone.
Android OS version is 4.3 now.
Please let me know what you want~

Please install the mihome app and login into your account. With each registered device (f.e. the air humidifier) the app does install a plugin (apk) I’m interested in. The APKs of the plugins are located here normally:

/data/data/com.xiaomi.smarthome/files/plugin/install/mpk

Could you provide a complete copy of the folder?

adb root
adb connect 192.168.132.24
adb pull /data/data/com.xiaomi.smarthome/files/plugin/install/mpk
zip -r plugins.zip mpk

This is the content in my case:

hammerhead:/data # find ./data/com.xiaomi.smarthome/files/plugin/install/mpk
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/com.xiaomi.catalog
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/com.xiaomi.catalog/7
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/com.xiaomi.catalog/7/7.apk
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/com.mijiashop.main
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/com.mijiashop.main/19
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/com.mijiashop.main/19/19.apk
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/com.xiaomi.pinwei
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/com.xiaomi.pinwei/2
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/com.xiaomi.pinwei/2/2.apk
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/108
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/108/10707.apk
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/108/10585.apk
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/229
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/229/7956.apk
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/229/10301.apk
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/107
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/107/8653.apk
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/473
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/473/7490.apk
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/503
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/503/10146.apk
/data/data/com.xiaomi.smarthome/files/plugin/install/mpk/503/10536.apk

I sent a message to you.
You can download my mpk.zip from my dropbox.

Thanks a lot! I just downloaded the archive and decompiled the air humidifier plugin. A few new findings:

  • The MiHome app uses the same properties like us: “humidity”, “temp_dec”, “power”, “mode”, “led_b”, “buzzer”, “child_lock”, “limit_hum”, “trans_level”
  • There is an additional mode called “strong” may be.
  • The temperature range is limited to -40 - +125°C (and round up)
  • There is second version (for canada?) called zhimi.humidifier.ca1
    • Requested properties: “humidity”, “temp_dec”, “power”, “mode”, “buzzer”, “led_b”, “child_lock”, “depth”, “speed”, “limit_hum”, “dry”
    • Modes: auto, high, medium, silent
    • Additional properties: hw_version, use_time, button_pressed
    • Setter: set_buzzer, set_child_lock, set_dry(on/off), set_led_b, set_limit_hum, set_mode, set_power
# The strong mode seems to be support of a new firmware only
isStrongMode() {
  if(fw_version == 25 && trans_level == 90) {
    return true;
  } else if(fw_version > 25) {
    return (operation_mode == "strong")
  }
  return false;
}