Xiaomi mi wifi plug & air purifier

hi raty,
just trying to achieve what you’ve done, however it doesnt seem to work. It doesnt change the fan speed, any idea what I am doing wrong?

I pretty much copied and pasted your settings and just changing the IP address to my purifier.

Thanks

image

Hi kwetiaw,
since 0.60 the AirPurifier component isn’t working anymore in Home-Assistant (at least for me it isn’t).
I’ve read on github, that syssi is working on the solution.

Also, since there is an official component, the miio command has been replaced by the mirobo command.
But luckily it isn’t necessary anymore to do it the way I described.

Now, with the official component you can just use input_number and an automation like this:

Automation:

- id: xiaomi_fav_speed
  alias: Xiaomi Favorite Speed
  trigger:
    platform: state
    entity_id: input_number.xiaomi_fav_speed
  action:
    - service: fan.xiaomi_miio_set_favorite_level
      data_template:
        entity_id: fan.xiaomi_air_purifier_2
        level: '{{ states.input_number.xiaomi_fav_speed.state | int }}'

input_number:

xiaomi_fav_speed:
  name: Xiaomi Air Purifier Favorite Level
  initial: 5
  min: 1
  max: 16
  step: 1

But, as I said earlier, at the moment, it doesn’t work at all.

I have the humidifier and would be more than happy to test for you

It’s fixed and will be part of the next homeassistant release: python-miio version bumped by syssi · Pull Request #11837 · home-assistant/core · GitHub

1 Like

I wrote a custom component as first step:

Please give it a try. If it works fine I will merge the code into fan/xiaomi_miio.

@af950833 Last request for today. :wink: I want to support your Air Purifier Pro properly. You already know the procedere. Could you post the output of:

# I want to know the model name
bin/mirobo --ip 192.168.1.xx --token 3d5fffffffffffffffffffffff37453b info
# First bunch of properties
bin/mirobo --ip 192.168.1.xx --token 3d5fffffffffffffffffffffff37453b get_prop '["power", "aqi", "average_aqi", "humidity", "temp_dec", "mode", "favorite_level", "filter1_life", "f1_hour_used", "use_time", "motor1_speed", "purify_volume", "f1_hour"]'
# Second bunch of properties
bin/mirobo --ip 192.168.1.xx --token 3d5fffffffffffffffffffffff37453b get_prop '["led", "led_b", "bright", "buzzer", "child_lock", "volume" ]'

Thanks! :slight_smile:

(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.15 --token 2a4d39a5721f983fdceae9193fc35596 -d info
INFO:miio.vacuum_cli:Debug mode active
DEBUG:miio.vacuum_cli:Read stored sequence ids: {‘manual_seq’: 0, ‘seq’: 12}
DEBUG:miio.vacuum_cli:Connecting to 192.168.0.15 with token 2a4d39a5721f983fdceae9193fc35596
DEBUG:miio.protocol:Unable to decrypt, returning raw bytes: b’’
DEBUG:miio.device:Got a response: Container:
data = Container:
data = (total 0)
offset2 = 32
offset1 = 32
length = 0
value = (total 0)
header = Container:
data = !1\x00 \x00\x00\x00\x00\x036}B\x00\x0b\xdbO (total 16)
offset2 = 16
offset1 = 0
length = 16
value = Container:
length = 32
unknown = 0
device_id = 03367d42 (total 8)
ts = 1970-01-09 23:50:39
checksum = *M9\xa5r\x1f\x98?\xdc\xea\xe9\x19?\xc3U\x96 (total 16)
DEBUG:miio.device:Discovered b’03367d42’ with ts: 1970-01-09 23:50:39, token: b’2a4d39a5721f983fdceae9193fc35596’
DEBUG:miio.device:192.168.0.15:54321 >>: {‘method’: ‘miIO.info’, ‘params’: [], ‘id’: 13}
DEBUG:miio.device:192.168.0.15:54321 (ts: 1970-01-09 23:50:39, id: 13) << {‘result’: {‘token’: ‘2a4d39a5721f983fdceae9193fc35596’, ‘mac’: ‘28:6C:07:B1:FE:B8’, ‘otu_stat’: [74, 74, 21452, 25, 21384, 404], ‘ot’: ‘otu’, ‘hw_ver’: ‘MW300’, ‘life’: 777039, ‘ap’: {‘ssid’: ‘Tommy’, ‘rssi’: -35, ‘bssid’: ‘AC:9E:17:A1:DF:F8’}, ‘model’: ‘zhimi.airpurifier.v6’, ‘wifi_fw_ver’: ‘SD878x-14.76.36.p84-702.1.0-WM’, ‘netif’: {‘localIp’: ‘192.168.0.15’, ‘mask’: ‘255.255.255.0’, ‘gw’: ‘192.168.0.1’}, ‘mmfree’: 185644, ‘ott_stat’: [0, 0, 0, 0], ‘cfg_time’: 0, ‘fw_ver’: ‘1.2.9_9049’}, ‘id’: 13}
zhimi.airpurifier.v6 v1.2.9_9049 (28:6C:07:B1:FE:B8) @ 192.168.0.15 - token: 2a4d39a5721f983fdceae9193fc35596
DEBUG:miio.vacuum_cli:Full response: {‘ap’: {‘bssid’: ‘AC:9E:17:A1:DF:F8’, ‘rssi’: -35, ‘ssid’: ‘Tommy’},
‘cfg_time’: 0,
‘fw_ver’: ‘1.2.9_9049’,
‘hw_ver’: ‘MW300’,
‘life’: 777039,
‘mac’: ‘28:6C:07:B1:FE:B8’,
‘mmfree’: 185644,
‘model’: ‘zhimi.airpurifier.v6’,
‘netif’: {‘gw’: ‘192.168.0.1’,
‘localIp’: ‘192.168.0.15’,
‘mask’: ‘255.255.255.0’},
‘ot’: ‘otu’,
‘ott_stat’: [0, 0, 0, 0],
‘otu_stat’: [74, 74, 21452, 25, 21384, 404],
‘token’: ‘2a4d39a5721f983fdceae9193fc35596’,
‘wifi_fw_ver’: ‘SD878x-14.76.36.p84-702.1.0-WM’}
DEBUG:miio.vacuum_cli:Writing {‘manual_seq’: 0, ‘seq’: 13} to /tmp/python-mirobo.seq
(homeassistant) homeassistant@Tommy:/home/pi $
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.15 --token 2a4d39a5721f983fdceae9193fc35596 raw_command get_prop ‘[“power”, “aqi”, “average_aqi”, “humidity”, “temp_dec”, “mode”, “favorite_level”, “filter1_life”, “f1_hour_used”, “use_time”, “motor1_speed”, “purify_volume”, “f1_hour”]’
Sending cmd get_prop with params [‘power’, ‘aqi’, ‘average_aqi’, ‘humidity’, ‘temp_dec’, ‘mode’, ‘favorite_level’, ‘filter1_life’, ‘f1_hour_used’, ‘use_time’, ‘motor1_speed’, ‘purify_volume’, ‘f1_hour’]
[‘off’, 7, 18, 45, 234, ‘auto’, 17, 52, 1664, 2642700, 0, 62180, 3500]
(homeassistant) homeassistant@Tommy:/home/pi $
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.15 --token 2a4d39a5721f983fdceae9193fc35596 raw_command get_prop ‘[“led”, “led_b”, “bright”, “buzzer”, “child_lock”, “volume” ]’
Sending cmd get_prop with params [‘led’, ‘led_b’, ‘bright’, ‘buzzer’, ‘child_lock’, ‘volume’]
[‘on’, None, 83, None, ‘off’, 50]
(homeassistant) homeassistant@Tommy:/home/pi $

It is my pleasure to help you :slight_smile:
As I mentioned, there is no “led_b” in the Air purifier(and Buzzer is not in it)

Perfect! I will prepare the next interation.

@af950833 Last wish for this device: Could you check/verify the supported operation modes of the Air Purifier Pro? (Command: set_mode, Possible values: auto, silent, favorite, idle)

Idle isn’t supported and returns an error, right?

@syssi Yes, you are right.

(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.15 --token 2a4d39a5721f983fdceae9193fc35596 raw_command set_mode ‘[“silent”]’
Sending cmd set_mode with params [‘silent’]
[‘ok’]
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.15 --token 2a4d39a5721f983fdceae9193fc35596 raw_command set_mode ‘[“auto”]’
Sending cmd set_mode with params [‘auto’]
[‘ok’]
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.15 --token 2a4d39a5721f983fdceae9193fc35596 raw_command set_mode ‘[“idle”]’
Sending cmd set_mode with params [‘idle’]
{‘id’: 6, ‘error’: {‘code’: -5001, ‘message’: ‘invaild_arg’}}
(homeassistant) homeassistant@Tommy:/home/pi $ mirobo --ip 192.168.0.15 --token 2a4d39a5721f983fdceae9193fc35596 raw_command set_mode ‘[“favorite”]’
Sending cmd set_mode with params [‘favorite’]
[‘ok’]

1 Like

@af950833 I prepared the next iteration of the air purifier component: https://github.com/syssi/xiaomi_airpurifier

Please copy the custom component into .homeassistant/custom_components/fan/xiaomi_miio.py

The custom component overrides the official fan.xiaomi_miio component and provides support for the Xiaomi Air Purifier and Xiaomi Air Humidifier:

fan:
  - platform: xiaomi_miio
    name: Xiaomi Air Purifier
    host: 192.168.130.71
    token: b7c4a758c251955d2c24b1d9e41ce47d

  - platform: xiaomi_miio
    name: Xiaomi Air Humidifier
    host: 192.168.130.72
    token: 2b00042f7481c7b056c4b410d28f33cf

I would be happy about a screenshot of both detail views if the component works out of the box. Because you own the Xiaomi Air Purifier Pro there should be some mor attributes available as in my screenshot:

Thanks in advance!

hi syssi,

The HA frontend is just loading and showed nothing.
1

pi@Tommy:~ $ cat /home/homeassistant/.homeassistant/home-assistant.log
2018-02-22 17:36:33 WARNING (Recorder) [homeassistant.components.recorder] Ended unfinished session (id=76 from 2018-02-22 08:29:04.944067)
2018-02-22 17:36:40 WARNING (Thread-14) [homeassistant.components.emulated_hue] When targeting Google Home, listening port has to be port 80
2018-02-22 17:36:57 WARNING (MainThread) [homeassistant.components.sensor] Setup of platform yr is taking over 10 seconds.
2018-02-22 17:36:57 ERROR (Thread-14) [miio.device] Got error when receiving: timed out
2018-02-22 17:36:57 WARNING (Thread-14) [miio.device] Retrying with incremented id, retries left: 3
2018-02-22 17:36:59 ERROR (Thread-21) [miio.device] Got error when receiving: timed out
2018-02-22 17:36:59 WARNING (Thread-21) [miio.device] Retrying with incremented id, retries left: 3
2018-02-22 17:37:06 ERROR (MainThread) [homeassistant.core] Timer got out of sync. Resetting
2018-02-22 17:37:11 ERROR (MainThread) [homeassistant.core] Timer got out of sync. Resetting
2018-02-22 17:37:30 ERROR (MainThread) [aiohttp.server] Error handling request
Traceback (most recent call last):
File “/srv/homeassistant/lib/python3.5/site-packages/homeassistant/remote.py”, line 126, in default
return json.JSONEncoder.default(self, o)
File “/usr/lib/python3.5/json/encoder.py”, line 179, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <FilterType.Regular: ‘regular’> is not JSON serializable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “/srv/homeassistant/lib/python3.5/site-packages/homeassistant/remote.py”, line 132, in default
for child_obj in o]
TypeError: ‘FilterType’ object is not iterable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “/srv/homeassistant/lib/python3.5/site-packages/aiohttp/web_protocol.py”, line 416, in start
resp = yield from self._request_handler(request)
File “/srv/homeassistant/lib/python3.5/site-packages/aiohttp/web.py”, line 325, in _handle
resp = yield from handler(request)
File “/srv/homeassistant/lib/python3.5/site-packages/aiohttp/web_middlewares.py”, line 93, in impl
return (yield from handler(request))
File “/srv/homeassistant/lib/python3.5/site-packages/homeassistant/components/http/ban.py”, line 58, in ban_middleware
return (yield from handler(request))
File “/srv/homeassistant/lib/python3.5/site-packages/homeassistant/components/http/auth.py”, line 49, in auth_middleware
return (yield from handler(request))
File “/srv/homeassistant/lib/python3.5/site-packages/homeassistant/components/http/static.py”, line 70, in staticresource_middleware
return (yield from handler(request))
File “/srv/homeassistant/lib/python3.5/site-packages/homeassistant/components/http/init.py”, line 430, in handle
result = yield from result
File “/usr/lib/python3.5/asyncio/coroutines.py”, line 213, in coro
res = yield from res
File “/srv/homeassistant/lib/python3.5/site-packages/homeassistant/components/websocket_api.py”, line 397, in handle
yield from self._writer_task
File “/usr/lib/python3.5/asyncio/futures.py”, line 382, in iter
return self.result() # May raise too.
File “/usr/lib/python3.5/asyncio/futures.py”, line 293, in result
raise self._exception
File “/usr/lib/python3.5/asyncio/tasks.py”, line 239, in _step
result = coro.send(None)
File “/srv/homeassistant/lib/python3.5/site-packages/homeassistant/components/websocket_api.py”, line 246, in _writer
yield from self.wsock.send_json(message, dumps=JSON_DUMP)
File “/srv/homeassistant/lib/python3.5/site-packages/aiohttp/web_ws.py”, line 197, in send_json
return self.send_str(dumps(data))
File “/usr/lib/python3.5/json/init.py”, line 237, in dumps
**kw).encode(obj)
File “/usr/lib/python3.5/json/encoder.py”, line 198, in encode
chunks = self.iterencode(o, _one_shot=True)
File “/usr/lib/python3.5/json/encoder.py”, line 256, in iterencode
return _iterencode(o, 0)
File “/srv/homeassistant/lib/python3.5/site-packages/homeassistant/remote.py”, line 135, in default
return json.JSONEncoder.default(self, o)
File “/usr/lib/python3.5/json/encoder.py”, line 179, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <FilterType.Regular: ‘regular’> is not JSON serializable
2018-02-22 17:37:44 ERROR (Recorder) [homeassistant.components.recorder.util] Error executing query: <FilterType.Regular: ‘regular’> is not JSON serializable

Ups! This is my fault. Fixed! Please update the custom component.

You have to correct the line# 510 :slight_smile:
3

After that, I got the below result.(make the picture to enlarge)

2

For reference, at the HA starting, there are some time out errors but everything is OK.
2018-02-22 18:54:41 WARNING (Thread-17) [homeassistant.components.emulated_hue] When targeting Google Home, listening port has to be port 80
2018-02-22 18:54:50 ERROR (Thread-9) [miio.device] Got error when receiving: timed out
2018-02-22 18:54:50 WARNING (Thread-9) [miio.device] Retrying with incremented id, retries left: 3
2018-02-22 18:54:50 ERROR (Thread-19) [miio.device] Got error when receiving: timed out
2018-02-22 18:54:50 WARNING (Thread-19) [miio.device] Retrying with incremented id, retries left: 3
2018-02-22 18:55:17 ERROR (MainThread) [homeassistant.core] Timer got out of sync. Resetting
2018-02-22 19:01:38 ERROR (Thread-4) [miio.device] Got error when receiving: timed out
2018-02-22 19:01:38 WARNING (Thread-4) [miio.device] Retrying with incremented id, retries left: 3
2018-02-22 19:02:37 ERROR (MainThread) [homeassistant.core] Timer got out of sync. Resetting

Hi,

first of all, thanks for the great work with this module!

Now, onto my problem, I cannot figure out how to set the mode on my purifier v2…
I can change the mode from the Home Assistant UI, but whenever I try sending the command manually I get an error message.

Here’s my setup:

Versions
python-miio==0.3.6
Home Assistant 0.63.3
Custom Component from https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/fan/xiaomi_miio.py

Config

  • platform: xiaomi_miio
    name: Air Purifier
    host: 192.168.1.61
    token: d4c02da2dexxxx158xxxx9a4413316df

The fan is visible as:
fan.air_purifier on speed: Silent
speed_list: Auto,Silent,Favorite,Idle
sleep_time: 75486
child_lock: false
buzzer: false
filter_life_remaining: 74
temperature: 22.3
favorite_level: 16
mode: silent
turbo_mode_supported: true
sleep_mode: silent
motor_speed: 348
sleep_mode_learn_count: 30
extra_features: 1
led_brightness: 1
filter_hours_used: 909
learn_mode: true
friendly_name: Air Purifier
humidity: 56
average_aqi: 8
aqi: 10
model: zhimi.airpurifier.m1
led: true
supported_features: 6905
purify_volume: 241409

The problem:
Calling service: fan.turn_on
with JSON:
{
“entity_id”: “fan.air_purifier”,
“speed”:“auto”
}

I get the error:
2018-02-22 21:10:29 ERROR (MainThread) [homeassistant.core] Error executing service <ServiceCall fan.turn_on: entity_id=[‘fan.air_purifier’], speed=auto>
Traceback (most recent call last):
File “/usr/local/lib/python3.5/dist-packages/homeassistant/core.py”, line 1010, in _event_to_service_call
yield from service_handler.func(service_call)
File “/usr/local/lib/python3.5/dist-packages/homeassistant/components/fan/init.py”, line 218, in async_handle_fan_service
yield from getattr(fan, method[‘method’])(**params)
File “/home/pi/.homeassistant/custom_components/fan/xiaomi_miio.py”, line 327, in async_turn_on
result = yield from self.async_set_speed(speed)
File “/home/pi/.homeassistant/custom_components/fan/xiaomi_miio.py”, line 552, in async_set_speed
self._device.set_mode, OperationMode[speed])
File “/usr/lib/python3.5/enum.py”, line 277, in getitem
return cls.member_map[name]
KeyError: ‘auto’

It doesn’t matter what I try, auto, high,low, a number, always the same error.

Any tips?

thanks again!

There is no service to change the mode in the current air purifier component.
You can do it with a shell command like the below.
With them, you can make a automation what you want.

shell_command:
mi_air_mode_auto: /srv/homeassistant/bin/mirobo --ip 192.168.0.15 --token 2a4d39a5721f983fdceae9193fc35555 raw_command set_mode ‘[“auto”]’
mi_air_mode_silent: /srv/homeassistant/bin/mirobo --ip 192.168.0.15 --token 2a4d39a5721f983fdceae9193fc35555 raw_command set_mode ‘[“silent”]’
mi_air_mode_favorite: /srv/homeassistant/bin/mirobo --ip 192.168.0.15 --token 2a4d39a5721f983fdceae9193fc35555 raw_command set_mode ‘[“favorite”]’

@hkrob You found a bug! I just fixed the set_speed service. This is the code change:

https://github.com/syssi/xiaomi_airpurifier/commit/8bc091f03cfaaea6ffff2b823bb52b6103f6508b

You could use the custom component in the meantime. I will provide an official fix for home assistant soon!

@syssi you’re awesome, working fine now!

@af950833 thanks for the work-around, but you might want to correct your statement “There is no service to change the mode in the current air purifier component”

cheers guys

As I mentioned, there is no service to change a mode in current air purifier.
The fan.turn_on (you tried) is not a service of air purifier.
Syssi is making a new code and he will add it but not available now.

I rethink my fix. This wasn’t a bug. The change broke the dropdown of the UI. Please revert the fix. The payload of the service was wrong. This will work:

{“entity_id”: “fan.air_purifier”, “speed”:“Auto”}
{“entity_id”: “fan.air_purifier”, “speed”:“Favorite”}

etc.