rytilahti / python-miio

Python library & console tool for controlling Xiaomi smart appliances
https://python-miio.readthedocs.io
GNU General Public License v3.0
3.69k stars 553 forks source link

Support for Mi Fresh Air Ventilator dmaker.airfresh.t2017 #502

Closed unixko closed 4 years ago

unixko commented 5 years ago

Product Link: https://www.xiaomiyoupin.com/detail?gid=104643

miiocli airpurifier --ip 192.168.1.xxx --token xxx info

Model: dmaker.airfresh.t2017
Hardware version: esp32
Firmware version: 2.0.3
Network: {'localIp': '192.168.1.xxx', 'mask': '255.255.255.0', 'gw': '192.168.1.1'}
AP: {'rssi': -63, 'ssid': 'APName', 'primary': 1, 'bssid': 'AA:BB:CC:DD:EE:FF'}
miiocli airpurifier --ip 192.168.1.xxx --token xxx status

ValueError: 94 is not a valid OperationMode

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\python3\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "c:\python3\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "C:\Python3\Scripts\miiocli.exe\__main__.py", line 9, in <module>
  File "c:\python3\lib\site-packages\miio\cli.py", line 43, in create_cli
    return cli(auto_envvar_prefix="MIIO")
  File "c:\python3\lib\site-packages\miio\click_common.py", line 54, in __call__

    return self.main(*args, **kwargs)
  File "c:\python3\lib\site-packages\click\core.py", line 717, in main
    rv = self.invoke(ctx)
  File "c:\python3\lib\site-packages\click\core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "c:\python3\lib\site-packages\click\core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "c:\python3\lib\site-packages\click\core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "c:\python3\lib\site-packages\click\core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "c:\python3\lib\site-packages\miio\click_common.py", line 267, in wrap
    result_msg = result_msg_fmt.format(**kwargs)
  File "c:\python3\lib\site-packages\miio\airpurifier.py", line 142, in mode
    return OperationMode(self.data["mode"])
  File "c:\python3\lib\enum.py", line 310, in __call__
    return cls.__new__(cls, value)
  File "c:\python3\lib\enum.py", line 564, in __new__
    raise exc
  File "c:\python3\lib\enum.py", line 548, in __new__
    result = cls._missing_(value)
  File "c:\python3\lib\enum.py", line 577, in _missing_
    raise ValueError("%r is not a valid %s" % (value, cls.__name__))
ValueError: 94 is not a valid OperationMode
miiocli airfresh --ip 192.168.1.xxx --token xxx info

Model: dmaker.airfresh.t2017
Hardware version: esp32
Firmware version: 2.0.3
Network: {'localIp': '192.168.1.xxx', 'mask': '255.255.255.0', 'gw': '192.168.1.1'}
AP: {'rssi': -64, 'ssid': 'APName', 'primary': 1, 'bssid': 'AA:BB:CC:DD:EE:FF'}
miiocli airfresh --ip 192.168.1.xxx --token xxx status

ValueError: 0 is not a valid OperationMode

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\python3\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "c:\python3\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "C:\Python3\Scripts\miiocli.exe\__main__.py", line 9, in <module>
  File "c:\python3\lib\site-packages\miio\cli.py", line 43, in create_cli
    return cli(auto_envvar_prefix="MIIO")
  File "c:\python3\lib\site-packages\miio\click_common.py", line 54, in __call__

    return self.main(*args, **kwargs)
  File "c:\python3\lib\site-packages\click\core.py", line 717, in main
    rv = self.invoke(ctx)
  File "c:\python3\lib\site-packages\click\core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "c:\python3\lib\site-packages\click\core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "c:\python3\lib\site-packages\click\core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "c:\python3\lib\site-packages\click\core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "c:\python3\lib\site-packages\miio\click_common.py", line 267, in wrap
    result_msg = result_msg_fmt.format(**kwargs)
  File "c:\python3\lib\site-packages\miio\airfresh.py", line 81, in mode
    return OperationMode(self.data["mode"])
  File "c:\python3\lib\enum.py", line 310, in __call__
    return cls.__new__(cls, value)
  File "c:\python3\lib\enum.py", line 564, in __new__
    raise exc
  File "c:\python3\lib\enum.py", line 548, in __new__
    result = cls._missing_(value)
  File "c:\python3\lib\enum.py", line 577, in _missing_
    raise ValueError("%r is not a valid %s" % (value, cls.__name__))
ValueError: 0 is not a valid OperationMode
rytilahti commented 5 years ago

Please add -dd to your calls to get more output (it'll contain the payloads), but the problem here is that those modes seems to differ from those defined in https://github.com/rytilahti/python-miio/blob/master/miio/airpurifier.py#L19 in https://github.com/rytilahti/python-miio/blob/master/miio/airfresh.py#L18 (being integers instead of strings).

Maybe those mode getters should catch the exceptions are report a new mode called "unknown" (and print out a warning) in case this happens, instead of crashing.

unixko commented 5 years ago

This Air Fresh device has 3 mode ["auto", "sleep", "favourite"]. This payload is from sleep mode. The word "sleep" in payload below will change to "auto", "favourite" following current mode accordingly. Errors from each mode are:

off - ValueError: 0 is not a valid OperationMode auto - ValueError: 97 is not a valid OperationMode sleep - ValueError: 60 is not a valid OperationMode favourite - ValueError: 239 is not a valid OperationMode

C:\Python37\Scripts>miiocli -dd airfresh --ip 192.168.0.2 --token xxx info
INFO:miio.cli:Debug mode active
DEBUG:miio.protocol:Unable to decrypt, returning raw bytes: b''
DEBUG:miio.device:Got a response: Container:
    data = Container:
        data = b'' (total 0)
        value = b'' (total 0)
        offset1 = 32
        offset2 = 32
        length = 0
    header = Container:
        data = b'!1\x00 \x00\x00\x00\x00\x05d5\x9b\x00\x01\\ ' (total 16)
        value = Container:
            length = 32
            unknown = 0
            device_id = b'\x05d5\x9b' (total 4)
            ts = 1970-01-02 00:45:20
        offset1 = 0
        offset2 = 16
        length = 16
    checksum = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf
f' (total 16)
DEBUG:miio.device:Container:
    data = Container:
        data = b'' (total 0)
        value = b'' (total 0)
        offset1 = 32
        offset2 = 32
        length = 0
    header = Container:
        data = b'!1\x00 \x00\x00\x00\x00\x05d5\x9b\x00\x01\\ ' (total 16)
        value = Container:
            length = 32
            unknown = 0
            device_id = b'\x05d5\x9b' (total 4)
            ts = 1970-01-02 00:45:20
        offset1 = 0
        offset2 = 16
        length = 16
    checksum = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf
f' (total 16)
DEBUG:miio.device:Discovered 0564359b with ts: 1970-01-02 00:45:20, token: b'fff
fffffffffffffffffffffffffffff'
DEBUG:miio.device:192.168.0.2:54321 >>: {'id': 1, 'method': 'miIO.info', 'params
': []}
DEBUG:miio.device:send (timeout 5): Container:
    data = Container:
        data = b'\x1a\xfb\xa3U\x1e\xa6!J+\xce\xfca<\xd6\xb3b'... (truncated, tot
al 48)
        value = {'id': 1, 'method': 'miIO.info', 'params': []}
        offset1 = 32
        offset2 = 80
        length = 48
    header = Container:
        data = b'!1\x00P\x00\x00\x00\x00\x05d5\x9b\x00\x01\\!' (total 16)
        value = Container:
            length = 80
            unknown = 0
            device_id = b'\x05d5\x9b' (total 4)
            ts = 1970-01-02 00:45:21
        offset1 = 0
        offset2 = 16
        length = 16
    checksum = b'\xce}\x17\xfcY2,\x08\xb5\x91\xbd.\xa0ntf' (total 16)
DEBUG:miio.device:recv from 192.168.0.2: Container:
    data = Container:
        data = b'\x1b\xcf\x9a\xdb\xb5\xfa\x02\x1a\xfd\x04\xeb\xe8\xbeqFr'... (tr
uncated, total 464)
        value = {'id': 1, 'result': {'life': 89121, 'uid': 1713659356, 'model':
'dmaker.airfresh.t2017', 'token': 'xxx', 'fw_ver':
'2.0.3', 'mcu_fw_ver': '0014', 'miio_ver': '0.0.3', 'hw_ver': 'esp32', 'mmfree':
 69152, 'mac': 'AA:BB:CC:DD:EE:FF', 'wifi_fw_ver': 'v3.1.3-8-gce4d3fe10', 'ap':
{'rssi': -65, 'ssid': 'APName', 'primary': 1, 'bssid': 'FF:EE:DD:CC:BB:AA'}, 'ne
tif': {'localIp': '192.168.0.2', 'mask': '255.255.255.0', 'gw': '192.168.0.1'},
'miio_times': [89120, 7, 213, 88900]}}
        offset1 = 32
        offset2 = 496
        length = 464
    header = Container:
        data = b'!1\x01\xf0\x00\x00\x00\x00\x05d5\x9b\x00\x01\\!' (total 16)
        value = Container:
            length = 496
            unknown = 0
            device_id = b'\x05d5\x9b' (total 4)
            ts = 1970-01-02 00:45:21
        offset1 = 0
        offset2 = 16
        length = 16
    checksum = b'w\x8b|D\xdeMpJ\xb0\xac\x01\xba\xea:\xab\x10' (total 16)
DEBUG:miio.device:192.168.0.2:54321 (ts: 1970-01-02 00:45:21, id: 1) << {'id': 1
, 'result': {'life': 89121, 'uid': 1713659356, 'model': 'dmaker.airfresh.t2017',
 'token': 'xxx', 'fw_ver': '2.0.3', 'mcu_fw_ver': '
0014', 'miio_ver': '0.0.3', 'hw_ver': 'esp32', 'mmfree': 69152, 'mac': 'AA:BB:CC
:DD:EE:FF', 'wifi_fw_ver': 'v3.1.3-8-gce4d3fe10', 'ap': {'rssi': -65, 'ssid': 'A
PName', 'primary': 1, 'bssid': 'FF:EE:DD:CC:BB:AA'}, 'netif': {'localIp': '192.1
68.0.2', 'mask': '255.255.255.0', 'gw': '192.168.0.1'}, 'miio_times': [89120, 7,
 213, 88900]}}
Model: dmaker.airfresh.t2017
Hardware version: esp32
Firmware version: 2.0.3
Network: {'localIp': '192.168.0.2', 'mask': '255.255.255.0', 'gw': '192.168.0.1'
}
AP: {'rssi': -65, 'ssid': 'APName', 'primary': 1, 'bssid': 'FF:EE:DD:CC:BB:AA'}
C:\Python37\Scripts>miiocli -dd airfresh --ip 192.168.0.2 --token xxx status
INFO:miio.cli:Debug mode active
DEBUG:miio.protocol:Unable to decrypt, returning raw bytes: b''
DEBUG:miio.device:Got a response: Container:
    data = Container:
        data = b'' (total 0)
        value = b'' (total 0)
        offset1 = 32
        offset2 = 32
        length = 0
    header = Container:
        data = b'!1\x00 \x00\x00\x00\x00\x05d5\x9b\x00\x01b\x88' (total 16)
        value = Container:
            length = 32
            unknown = 0
            device_id = b'\x05d5\x9b' (total 4)
            ts = 1970-01-02 01:12:40
        offset1 = 0
        offset2 = 16
        length = 16
    checksum = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf
f' (total 16)
DEBUG:miio.device:Container:
    data = Container:
        data = b'' (total 0)
        value = b'' (total 0)
        offset1 = 32
        offset2 = 32
        length = 0
    header = Container:
        data = b'!1\x00 \x00\x00\x00\x00\x05d5\x9b\x00\x01b\x88' (total 16)
        value = Container:
            length = 32
            unknown = 0
            device_id = b'\x05d5\x9b' (total 4)
            ts = 1970-01-02 01:12:40
        offset1 = 0
        offset2 = 16
        length = 16
    checksum = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf
f' (total 16)
DEBUG:miio.device:Discovered 0564359b with ts: 1970-01-02 01:12:40, token: b'fff
fffffffffffffffffffffffffffff'
DEBUG:miio.device:192.168.0.2:54321 >>: {'id': 1, 'method': 'get_prop', 'params'
: ['power', 'temp_dec', 'aqi', 'average_aqi', 'co2', 'buzzer', 'child_lock', 'hu
midity', 'led_level', 'mode', 'motor1_speed', 'use_time', 'ntcT', 'app_extra', '
f1_hour_used']}
DEBUG:miio.device:send (timeout 5): Container:
    data = Container:
        data = b'\x1a\xfb\xa3U\x1e\xa6!J+\xce\xfca<\xd6\xb3b'... (truncated, tot
al 224)
        value = {'id': 1, 'method': 'get_prop', 'params': ['power', 'temp_dec',
'aqi', 'average_aqi', 'co2', 'buzzer', 'child_lock', 'humidity', 'led_level', 'm
ode', 'motor1_speed', 'use_time', 'ntcT', 'app_extra', 'f1_hour_used']}
        offset1 = 32
        offset2 = 256
        length = 224
    header = Container:
        data = b'!1\x01\x00\x00\x00\x00\x00\x05d5\x9b\x00\x01b\x89' (total 16)
        value = Container:
            length = 256
            unknown = 0
            device_id = b'\x05d5\x9b' (total 4)
            ts = 1970-01-02 01:12:41
        offset1 = 0
        offset2 = 16
        length = 16
    checksum = b'\xae_\xab\xb1\x8f\xdd\xdb\xf6\xd0T\xb10\x06\xe6\xd0j' (total 16
)
DEBUG:miio.device:recv from 192.168.0.2: Container:
    data = Container:
        data = b'\x1b\xcf\x9a\xdb\xb5\xfa\x02\x1a\xfd\x04\xeb\xe8\xbeqFr'... (tr
uncated, total 32)
        value = {'id': 1, 'result': [True]}
        offset1 = 32
        offset2 = 64
        length = 32
    header = Container:
        data = b'!1\x00@\x00\x00\x00\x00\x05d5\x9b\x00\x01b\x89' (total 16)
        value = Container:
            length = 64
            unknown = 0
            device_id = b'\x05d5\x9b' (total 4)
            ts = 1970-01-02 01:12:41
        offset1 = 0
        offset2 = 16
        length = 16
    checksum = b'\x03\x9b\x1b\x93o\x0bp\x92\xedP\x95\x93W\xf6(\xfc' (total 16)
DEBUG:miio.device:192.168.0.2:54321 (ts: 1970-01-02 01:12:41, id: 1) << {'id': 1
, 'result': [True]}
DEBUG:miio.device:192.168.0.2:54321 >>: {'id': 2, 'method': 'get_prop', 'params'
: ['filter_life', 'f_hour', 'favorite_level', 'led']}
DEBUG:miio.device:send (timeout 5): Container:
    data = Container:
        data = b'\xcbL\xc4\x05&`\xba\xac\x830F\xae\n{v\x15'... (truncated, total
 96)
        value = {'id': 2, 'method': 'get_prop', 'params': ['filter_life', 'f_hou
r', 'favorite_level', 'led']}
        offset1 = 32
        offset2 = 128
        length = 96
    header = Container:
        data = b'!1\x00\x80\x00\x00\x00\x00\x05d5\x9b\x00\x01b\x8a' (total 16)
        value = Container:
            length = 128
            unknown = 0
            device_id = b'\x05d5\x9b' (total 4)
            ts = 1970-01-02 01:12:42
        offset1 = 0
        offset2 = 16
        length = 16
    checksum = b'qM\x05%\x15\xab{j\xe4>\xe5<\xbf\xa5+\xf9' (total 16)
DEBUG:miio.device:recv from 192.168.0.2: Container:
    data = Container:
        data = b'\xecX\xf9\x17\xce\xf4\x053\xdd\xee\xdc\x05\xe4\x7f6\x8b'... (tr
uncated, total 112)
        value = {'id': 2, 'result': [19, 595, 31, 239, 92, 82, 96, 172, 60, True
, 'sleep', True, 'medium', False, False, True, True, 'forward']}
        offset1 = 32
        offset2 = 144
        length = 112
    header = Container:
        data = b'!1\x00\x90\x00\x00\x00\x00\x05d5\x9b\x00\x01b\x89' (total 16)
        value = Container:
            length = 144
            unknown = 0
            device_id = b'\x05d5\x9b' (total 4)
            ts = 1970-01-02 01:12:41
        offset1 = 0
        offset2 = 16
        length = 16
    checksum = b'\xbd_\xb7[\xb5\xfc\xc4\x9e\x9b\x1db\\\xc1\xdak&' (total 16)
DEBUG:miio.device:192.168.0.2:54321 (ts: 1970-01-02 01:12:41, id: 2) << {'id': 2
, 'result': [19, 595, 31, 239, 92, 82, 96, 172, 60, True, 'sleep', True, 'medium
', False, False, True, True, 'forward']}
ValueError: 60 is not a valid OperationMode

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\python37\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "c:\python37\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "C:\Python37\Scripts\miiocli.exe\__main__.py", line 9, in <module>
  File "c:\python37\lib\site-packages\miio\cli.py", line 43, in create_cli
    return cli(auto_envvar_prefix="MIIO")
  File "c:\python37\lib\site-packages\miio\click_common.py", line 54, in __call_
_
    return self.main(*args, **kwargs)
  File "c:\python37\lib\site-packages\click\core.py", line 717, in main
    rv = self.invoke(ctx)
  File "c:\python37\lib\site-packages\click\core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "c:\python37\lib\site-packages\click\core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "c:\python37\lib\site-packages\click\core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "c:\python37\lib\site-packages\click\core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "c:\python37\lib\site-packages\miio\click_common.py", line 267, in wrap
    result_msg = result_msg_fmt.format(**kwargs)
  File "c:\python37\lib\site-packages\miio\airfresh.py", line 81, in mode
    return OperationMode(self.data["mode"])
  File "c:\python37\lib\enum.py", line 310, in __call__
    return cls.__new__(cls, value)
  File "c:\python37\lib\enum.py", line 564, in __new__
    raise exc
  File "c:\python37\lib\enum.py", line 548, in __new__
    result = cls._missing_(value)
  File "c:\python37\lib\enum.py", line 577, in _missing_
    raise ValueError("%r is not a valid %s" % (value, cls.__name__))
ValueError: 60 is not a valid OperationMode
unixko commented 5 years ago

I found that OperationMode value is fan speed. If I set mode to auto, OperationMode will continuously change following current speed. Range is 60 to 300. 0 - off 60 - sleep mode or lowest setting in favourite mode 300 - highest setting in favourite mode

rezmus commented 5 years ago
    public static final String PROP_CHILD_LOCK = "child_lock";
    public static final String PROP_CO2 = "co2";
    public static final String PROP_CONTROL_SPEED = "control_speed";
    public static final String PROP_DISPLAY = "display";
    public static final String PROP_FILTER_HIGH = "filter_efficient";
    public static final String PROP_FILTER_MEDIUM = "filter_intermediate";
    public static final String PROP_HIGH_DAY = "filter_effi_day";
    public static final String PROP_INCREASE_SPEED = "increase_speed";
    public static final String PROP_MEDIUM_DAY = "filter_inter_day";
    public static final String PROP_MODE = "mode";
    public static final String PROP_PM25 = "pm25";
    public static final String PROP_POWER = "power";
    public static final String PROP_PTC_LEVEL = "ptc_level";
    public static final String PROP_PTC_ON = "ptc_on";
    public static final String PROP_PTC_STATUS = "ptc_status";
    public static final String PROP_SCREEN_DIRECTION = "screen_direction";
    public static final String PROP_SOUND = "sound";
    public static final String PROP_SPEED = "favourite_speed";
    public static final String PROP_TEMP = "temperature_outside";
    public static final String TYPE_ALL = "all";
    public static final String TYPE_CO2 = "co2";
    public static final String TYPE_DEVICE_OFFLINE = "dev_offline";
    public static final String TYPE_EFFICIENT = "efficient";
    public static final String TYPE_INTERMEDIATE = "intermediate";
    public static final String TYPE_PM25 = "pm25";

    static {
        HOME_PROPERTIES = new String[]{TYPE_PM25, TYPE_CO2, PROP_TEMP, PROP_SPEED, PROP_FILTER_MEDIUM, PROP_MEDIUM_DAY, PROP_FILTER_HIGH, PROP_HIGH_DAY, PROP_CONTROL_SPEED, PROP_POWER, PROP_MODE, PROP_PTC_ON, PROP_PTC_LEVEL, PROP_PTC_STATUS, PROP_CHILD_LOCK, PROP_SOUND, PROP_DISPLAY, PROP_SCREEN_DIRECTION, PROP_INCREASE_SPEED};
    }

    public boolean getChildLock() {
        return TypeUtil.getDefaultBoolean(TypeUtil.toBoolean(this.mPropertiesMap.get(PROP_CHILD_LOCK)), false);
    }

    public boolean getSound() {
        return TypeUtil.getDefaultBoolean(TypeUtil.toBoolean(this.mPropertiesMap.get(PROP_SOUND)), false);
    }

    public boolean getDisplay() {
        return TypeUtil.getDefaultBoolean(TypeUtil.toBoolean(this.mPropertiesMap.get(PROP_DISPLAY)), false);
    }

    public String getScreenDirection() {
        return TypeUtil.toString(this.mPropertiesMap.get(PROP_SCREEN_DIRECTION));
    }

    public boolean getIncreaseSpeed() {
        return TypeUtil.getDefaultBoolean(TypeUtil.toBoolean(this.mPropertiesMap.get(PROP_INCREASE_SPEED)), false);
    }

    public Integer getSpeed() {
        return TypeUtil.toInteger(this.mPropertiesMap.get(PROP_SPEED));
    }

    public Integer getHighFilter() {
        return TypeUtil.toInteger(this.mPropertiesMap.get(PROP_FILTER_HIGH));
    }

    public Integer getHighDay() {
        return TypeUtil.toInteger(this.mPropertiesMap.get(PROP_HIGH_DAY));
    }

    public Integer getMediumFilter() {
        return TypeUtil.toInteger(this.mPropertiesMap.get(PROP_FILTER_MEDIUM));
    }

    public Integer getMediumDay() {
        return TypeUtil.toInteger(this.mPropertiesMap.get(PROP_MEDIUM_DAY));
    }

    public String getMode() {
        return TypeUtil.toString(this.mPropertiesMap.get(PROP_MODE));
    }

    public Integer getPm25() {
        return TypeUtil.toInteger(this.mPropertiesMap.get(TYPE_PM25));
    }

    public boolean getPower() {
        return TypeUtil.getDefaultBoolean(TypeUtil.toBoolean(this.mPropertiesMap.get(PROP_POWER)), false);
    }

    public boolean getPtcOn() {
        return TypeUtil.getDefaultBoolean(TypeUtil.toBoolean(this.mPropertiesMap.get(PROP_PTC_ON)), false);
    }

    public String getPtcLevel() {
        return TypeUtil.toString(this.mPropertiesMap.get(PROP_PTC_LEVEL));
    }

    public boolean getPtcStatus() {
        return TypeUtil.getDefaultBoolean(TypeUtil.toBoolean(this.mPropertiesMap.get(PROP_PTC_STATUS)), false);
    }

    public Integer getCo2() {
        return TypeUtil.toInteger(this.mPropertiesMap.get(TYPE_CO2));
    }

    public Float getTemp() {
        return TypeUtil.toFloat(this.mPropertiesMap.get(PROP_TEMP));
    }

 public void getSensor(Callback<JSONArray> callback) {
        callMethod("get_sensor", callback, new Object[0]);
    }

    public void setChildLock(boolean state, Callback<JSONArray> callback) {
        callMethod("set_child_lock", callback, Boolean.valueOf(state));
    }

    public void setSound(boolean sound, Callback<JSONArray> callback) {
        callMethod("set_sound", callback, Boolean.valueOf(sound));
    }

    public void setDisplay(boolean display, Callback<JSONArray> callback) {
        callMethod("set_display", callback, Boolean.valueOf(display));
    }

    public void setScreenDirection(String direction, Callback<JSONArray> callback) {
        callMethod("set_screen_direction", callback, direction);
    }

    public void setIncreaseSpeed(boolean increase, Callback<JSONArray> callback) {
        callMethod("set_increase_speed", callback, Boolean.valueOf(increase));
    }

    public void setSpeed(int speed, Callback<JSONArray> callback) {
        callMethod("set_favourite_speed", callback, Integer.valueOf(speed));
    }

    public void setPtcLevel(String level, Callback<JSONArray> callback) {
        callMethod("set_ptc_level", callback, level);
    }

    public void setRoomArea(int area, Callback<JSONArray> callback) {
        callMethod("set_room_area", callback, Integer.valueOf(area));
    }

    public void setPower(boolean power, Callback<JSONArray> callback) {
        callMethod("set_power", callback, Boolean.valueOf(power));
    }

    public void setPtcOn(boolean ptc, Callback<JSONArray> callback) {
        callMethod("set_ptc_on", callback, Boolean.valueOf(ptc));
    }

    public void setWorkMode(String mode, Callback<JSONArray> callback) {
        callMethod("set_mode", callback, mode);
    }

    public void getTimers(Callback<JSONArray> callback) {
        callMethod("get_timer", callback, new Object[0]);
    }

    public void setTimer(String timer, Callback<JSONArray> callback) {
        callMethod("set_timer", callback, timer);
    }

    public void deleteTimer(int timer, Callback<JSONArray> callback) {
        callMethod("delete_timer", callback, Integer.valueOf(timer));
    }

    public void resetFilter(String type, Callback<JSONArray> callback) {
        callMethod("set_filter_reset", callback, type);
    }

    public void setPtcTimer(String timer, Callback<JSONArray> callback) {
        callMethod("set_ptc_timer", callback, timer);
    }

    public void getPtcTimer(Callback<JSONArray> callback) {
        callMethod("get_ptc_timer", callback, new Object[0]);
    }
ps1x commented 5 years ago

I'm quite far away from python (javascript) but i would love to help integrating that device to Home Assistant, where can i start with help? As of my tries with modification of original plugin, there is no PM25 sensor in original XiaomiAirfresh, so we should add first to python-miio and then create integration in home assistant plugin?

lazzzrus commented 4 years ago

One vote more. Do you need any help?

lazzzrus commented 4 years ago

Got it! https://bbs.hassbian.com/thread-8218-1-1.html This works!

d-litvinov commented 4 years ago

@lazzzrus, could you please create a PR? I have no idea how to use that data

lazzzrus commented 4 years ago

@lazzzrus, could you please create a PR? I have no idea how to use that data

Sorry, i don't know how to create PR. Shortly zxytddd (guy from China) created his own custom component for HA. You need to registrate to download the file so i shared it: https://drive.google.com/file/d/1nHdZjWCIhwYH9FNdKqSAZkrdmg_vvASg/view

The config: fan:

So now i can turn the device on/off.

I'm newbie so don't know how to use parameters for dashboard and automation. So would be glad for any help or link to tutorial.

  1. Properties: ["pm25","co2","temperature_outside","favourite_speed","filter_intermediate","filter_inter_day","filter_efficient","filter_effi_day","control_speed","power","mode","ptc_on","ptc_level","ptc_status","child_lock","sound","display","screen_direction"]
  2. Command: set_mode set_power set_ptc_level set_ptc_on set_ptc_timer set_room_area set_child_lock set_display set_sound set_screen_direction set_favorite set_favorite_area set_favourite_speed set_filter_reset set_increase_speed
unixko commented 4 years ago

Someone already put @zxytddd code on github at https://github.com/mypal/mi-airfresh so we can use it in this mean time. Anyway native support from python-miio and Home Assistant is surely preferred.

lazzzrus commented 4 years ago

Yes. This integration is far too basic. I can't find the way to control speed and heat level. Is it possible?

syssi commented 4 years ago
# Properties
[
"pm25",
 "co2",
 "temperature_outside",
 "favourite_speed",
 "filter_intermediate",
 "filter_inter_day",
 "filter_efficient",
 "filter_effi_day",
 "control_speed",
 "power",
 "mode",
 "ptc_on",
 "ptc_level",
 "ptc_status",
 "child_lock",
 "sound",
 "display",
 "screen_direction"
]

# Methods:

get_prop [propArr]
get_ptc_timer []
get_sensor [propArr]
get_timer null
set_child_lock [value]
set_display [value]
set_favourite_speed [areaNum]
set_filter_reset ['efficient']
set_filter_reset ['intermediate']
set_mode [type]
set_power [status]
set_ptc_level [ptc_leavel]
set_ptc_on [ptc_leavel]
set_ptc_timer, [value]
set_screen_direction [direct]
set_sound [value]
syssi commented 4 years ago

Could somebody provide the output of:

miiocli device --ip IP --token TOKEN raw_command get_prop "['pm25', 'co2', 'temperature_outside', 'favourite_speed', 'filter_intermediate', 'filter_inter_day', 'filter_efficient', 'filter_effi_day', 'control_speed', 'power', 'mode', 'ptc_on', 'ptc_level', 'ptc_status', 'child_lock', 'sound', 'display', 'screen_direction']"
skvalex commented 4 years ago

@syssi here is the output grabbed from Mi Home app via tcpdump:

 ->  request = {"id":4219,"method":"get_prop","params":["pm25","co2","temperature_outside","favourite_speed","filter_intermediate","filter_inter_day","filter_efficient","filter_effi_day","control_speed","power","mode","ptc_on","ptc_level","ptc_status","child_lock","sound","display","screen_direction"]}
 <-  response = {"id":4219,"result":[0,445,3,206,83,74,92,165,60,true,"sleep",false,"high",false,false,false,false,"forward"]}

P.S. I've created pull request for openHAB to add support for this device: https://github.com/openhab/openhab2-addons/pull/6558/files It might be helpful to you.

ps1x commented 3 years ago

Please upvote feature request here https://community.home-assistant.io/t/support-for-xiaomi-miio-support-for-dmaker-airfresh-t2017/235798 if you want it integrated in home assistant.