rytilahti / python-miio

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

Add support Xiaomi Mi Air Purifier A1 (MJXFJ-150-A1) dmaker.airfresh.a1 #662

Open aleksandrdobrynin opened 4 years ago

aleksandrdobrynin commented 4 years ago

Please add support.

rytilahti commented 4 years ago

Is this a miio or miot device? Have you tried if miiocli airfresh or miiocli airfresht2017 works for some commands? Do you know what commands does it have?

aleksandrdobrynin commented 4 years ago

image image I get the status, but at the same time I get an error when I try to turn it on. There is also air heating in the device. How to manage it?

aleksandrdobrynin commented 4 years ago

If I change the operating mode to night or manually, I get such errors: image

rytilahti commented 4 years ago

Okay, could you execute the original command but with debug (either --debug or -d) flag to get debug output, and paste it here as text? Looks like it is using different properties (or values), so that would be the first step. To start analyzing it.

Regarding to your follow-up screenshots, could you also try turning it on and off, and set other modes and copy&paste the outputs from the status command when doing that.

aleksandrdobrynin commented 4 years ago

I try to execute a command with the --debug or -d switch and I get an error. Prompt syntax, please.

rytilahti commented 4 years ago

miiocli --debug airfresh --ip <ip> --token <token> status

aleksandrdobrynin commented 4 years ago

When turning on / off the screen backlight and heating mode, there are no changes in the output. Apparently this is not in the library itself.

aleksandrdobrynin commented 4 years ago

--debug image

rytilahti commented 4 years ago

Also, try airfresht2017 instead of airfresh, that is also for dmaker and does have sleep and favorite defined.

aleksandrdobrynin commented 4 years ago

image Is it convenient to take screenshots or is it better to throw text?

rytilahti commented 4 years ago

Copy & paste the text please, it will be easier to use the information in the code then afterwards.

Could you try to modify these two lines to have 1 instead of 15 as a value for how many properties to request: https://github.com/rytilahti/python-miio/blob/master/miio/airfresh_t2017.py#L289 and paste the results as text.

aleksandrdobrynin commented 4 years ago
pi@ihome-2:~ $ miiocli --debug airfresh --ip 192.168.252.64 --token 12ec5081d18a205372f9deab6518f0af status
INFO:miio.cli:Debug mode active
DEBUG:miio.protocol:Unable to decrypt, returning raw bytes: b''
DEBUG:miio.miioprotocol: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\x0e\x04\xd7\x95\x00\x07\xfe\xb3' (total 16)
        value = Container: 
            length = 32
            unknown = 0
            device_id = unhexlify('0e04d795')
            ts = 1970-01-07 01:32:35
        offset1 = 0
        offset2 = 16
        length = 16
    checksum = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' (total 16)
DEBUG:miio.miioprotocol:Discovered 0e04d795 with ts: 1970-01-07 01:32:35, token: b'ffffffffffffffffffffffffffffffff'
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 1, 'method': 'get_prop', 'params': ['power', 'temp_dec', 'aqi', 'average_aqi', 'co2', 'buzzer', 'child_lock', 'humidity', 'led_level', 'mode', 'motor1_speed', 'use_time', 'ntcT', 'app_extra', 'f1_hour_used']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 01:32:35, id: 1) << {'id': 1, 'result': [True], 'exe_time': 120}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 2, 'method': 'get_prop', 'params': ['filter_life', 'f_hour', 'favorite_level', 'led']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 01:32:35, id: 2) << {'id': 2, 'result': [0, 608, 7, 150, 99, 178, 60, True, 'auto', True, True, False, True, True], 'exe_time': 150}
DEBUG:miio.airfresh:Count (19) of requested properties does not match the count (15) of received values.
Power: True
AQI: 608 μg/m³
Average AQI: 7 μg/m³
Temperature: 0.0 °C
Humidity: 60 %
CO2: 150 %
Mode: auto
LED: False
LED brightness: LedBrightness.Dim
Buzzer: False
Child lock: False
Filter life remaining: None %
Filter hours used: True
Use time: True s
Motor speed: True rpm

pi@ihome-2:~ $ miiocli --debug airfresht2017 --ip 192.168.252.64 --token 12ec5081d18a205372f9deab6518f0af status
INFO:miio.cli:Debug mode active
DEBUG:miio.protocol:Unable to decrypt, returning raw bytes: b''
DEBUG:miio.miioprotocol: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\x0e\x04\xd7\x95\x00\x07\xff]' (total 16)
        value = Container: 
            length = 32
            unknown = 0
            device_id = unhexlify('0e04d795')
            ts = 1970-01-07 01:35:25
        offset1 = 0
        offset2 = 16
        length = 16
    checksum = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' (total 16)
DEBUG:miio.miioprotocol:Discovered 0e04d795 with ts: 1970-01-07 01:35:25, token: b'ffffffffffffffffffffffffffffffff'
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 1, 'method': 'get_prop', 'params': ['power', 'mode', 'pm25', 'co2', 'temperature_outside', 'favourite_speed', 'control_speed', 'filter_intermediate', 'filter_inter_day', 'filter_efficient', 'filter_effi_day', 'ptc_on', 'ptc_level', 'ptc_status', 'child_lock']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 01:35:25, id: 1) << {'id': 1, 'result': [True, 'auto', 0, 562, 6, 150, 60], 'exe_time': 210}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 2, 'method': 'get_prop', 'params': ['sound', 'display', 'screen_direction']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 01:35:26, id: 2) << {'id': 2, 'result': [True, True], 'exe_time': 150}
DEBUG:miio.airfresh_t2017:Count (18) of requested properties does not match the count (9) of received values.
ValueError: None is not a valid PtcLevel

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/bin/miiocli", line 10, in <module>
    sys.exit(create_cli())
  File "/usr/local/lib/python3.7/dist-packages/miio/cli.py", line 44, in create_cli
    return cli(auto_envvar_prefix="MIIO")
  File "/usr/local/lib/python3.7/dist-packages/miio/click_common.py", line 59, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/lib/python3/dist-packages/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/lib/python3/dist-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python3/dist-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/miio/click_common.py", line 285, in wrap
    result_msg = result_msg_fmt.format(**kwargs)
  File "/usr/local/lib/python3.7/dist-packages/miio/airfresh_t2017.py", line 163, in ptc_level
    return PtcLevel(self.data["ptc_level"])
  File "/usr/lib/python3.7/enum.py", line 310, in __call__
    return cls.__new__(cls, value)
  File "/usr/lib/python3.7/enum.py", line 564, in __new__
    raise exc
  File "/usr/lib/python3.7/enum.py", line 548, in __new__
    result = cls._missing_(value)
  File "/usr/lib/python3.7/enum.py", line 577, in _missing_
    raise ValueError("%r is not a valid %s" % (value, cls.__name__))
ValueError: None is not a valid PtcLevel
aleksandrdobrynin commented 4 years ago

Please tell me where this file is located https://github.com/rytilahti/python-miio/blob/master/miio/airfresh_t2017.py#L289

I have raspberries 4

rytilahti commented 4 years ago

It depends on how you installed it. You could try to do locate airfresh_t2017.py to locate it, which might work.

If you want to do it properly, you will simply checkout this repository, modify it and install the checkout locally inside a virtualenv, that you can remove afterwards.

So something like this:

git clone https://github.com/rytilahti/python-miio.git
virtualenv -p python3 miioenv
source miioenv/bin/activate
pip install -e python-miio/

and then you can modify the files inside the python-miio directory, and execute the modified version without any need to reinstall it (thanks to that -e) as long as the environment is active.

aleksandrdobrynin commented 4 years ago

I hope I did everything right)

(miioenv) pi@ihome-2:~ $ miiocli --debug airfresht2017 --ip 192.168.252.64 --token 12ec5081d18a205372f9deab6518f0af status
INFO:miio.cli:Debug mode active
DEBUG:miio.protocol:Unable to decrypt, returning raw bytes: b''
DEBUG:miio.miioprotocol: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\x0e\x04\xd7\x95\x00\x08\x06\x13' (total 16)
        value = Container: 
            length = 32
            unknown = 0
            device_id = unhexlify('0e04d795')
            ts = 1970-01-07 02:04:03
        offset1 = 0
        offset2 = 16
        length = 16
    checksum = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' (total 16)
DEBUG:miio.miioprotocol:Discovered 0e04d795 with ts: 1970-01-07 02:04:03, token: b'ffffffffffffffffffffffffffffffff'
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 1, 'method': 'get_prop', 'params': ['power']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:04:04, id: 1) << {'id': 1, 'result': [True], 'exe_time': 110}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 2, 'method': 'get_prop', 'params': ['mode']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:04:04, id: 2) << {'id': 2, 'result': ['auto'], 'exe_time': 160}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 3, 'method': 'get_prop', 'params': ['pm25']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:04:04, id: 3) << {'id': 3, 'result': [0], 'exe_time': 160}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 4, 'method': 'get_prop', 'params': ['co2']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:04:04, id: 4) << {'id': 4, 'result': [573], 'exe_time': 160}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 5, 'method': 'get_prop', 'params': ['temperature_outside']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:04:05, id: 5) << {'id': 5, 'result': [7], 'exe_time': 160}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 6, 'method': 'get_prop', 'params': ['favourite_speed']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:04:05, id: 6) << {'id': 6, 'result': [150], 'exe_time': 160}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 7, 'method': 'get_prop', 'params': ['control_speed']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:04:05, id: 7) << {'id': 7, 'result': [60], 'exe_time': 160}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 8, 'method': 'get_prop', 'params': ['filter_intermediate']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:04:05, id: 8) << {'id': 8, 'result': [0, 573, 7, 150, 99, 178, 60, True, 'auto', True, True, False, True, True], 'exe_time': 170}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 9, 'method': 'get_prop', 'params': ['filter_inter_day']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:04:05, id: 9) << {'id': 9, 'result': [0, 573, 7, 150, 99, 178, 60, True, 'auto', True, True, False, True, True], 'exe_time': 160}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 10, 'method': 'get_prop', 'params': ['filter_efficient']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:04:06, id: 10) << {'id': 10, 'result': [0, 573, 7, 150, 99, 178, 60, True, 'auto', True, True, False, True, True], 'exe_time': 160}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 11, 'method': 'get_prop', 'params': ['filter_effi_day']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:04:06, id: 11) << {'id': 11, 'result': [0, 573, 7, 150, 99, 178, 60, True, 'auto', True, True, False, True, True], 'exe_time': 160}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 12, 'method': 'get_prop', 'params': ['ptc_on']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:04:06, id: 12) << {'id': 12, 'result': [True], 'exe_time': 150}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 13, 'method': 'get_prop', 'params': ['ptc_level']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:04:06, id: 13) << {'id': 13, 'result': [0, 573, 7, 150, 99, 178, 60, True, 'auto', True, True, False, True, True], 'exe_time': 170}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 14, 'method': 'get_prop', 'params': ['ptc_status']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:04:06, id: 14) << {'id': 14, 'result': [True], 'exe_time': 150}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 15, 'method': 'get_prop', 'params': ['child_lock']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:04:07, id: 15) << {'id': 15, 'result': [False], 'exe_time': 160}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 16, 'method': 'get_prop', 'params': ['sound']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:04:07, id: 16) << {'id': 16, 'result': [True], 'exe_time': 160}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 17, 'method': 'get_prop', 'params': ['display']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:04:07, id: 17) << {'id': 17, 'result': [True], 'exe_time': 160}
DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 18, 'method': 'get_prop', 'params': ['screen_direction']}
DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:04:07, id: 18) << {'id': 18, 'result': [0, 573, 6, 150, 99, 178, 60, True, 'auto', True, True, False, True, True], 'exe_time': 170}
DEBUG:miio.airfresh_t2017:Count (18) of requested properties does not match the count (96) of received values.
ValueError: 178 is not a valid PtcLevel
rytilahti commented 4 years ago

Okay, interesting... Looks like it is returning all the variables if the variable name does not match, or that's how I interpret this. Could you try miiocli -d airfresht2017 raw_command get_prop '["testproperty"]' to verify that this is the case?

aleksandrdobrynin commented 4 years ago

(miioenv) pi@ihome-2:~ $ miiocli --debug airfresht2017 --ip 192.168.252.64 --token 12ec5081d18a205372f9deab6518f0af raw_command get_prop ['power'] INFO:miio.cli:Debug mode active Usage: miiocli airfresht2017 raw_command [OPTIONS] COMMAND [PARAMETERS] Try 'miiocli airfresht2017 raw_command --help' for help.

Error: Invalid value for '[PARAMETERS]': [power] is not a valid literal

rytilahti commented 4 years ago

You have to copy the command as it is (including the " and ' characters).

Anyway, I looked at the outputs you gave me, and here is what I found out:

All values: [0, 573, 7, 150, 99, 178, 60, True, 'auto', True, True, False, True, True]

pm25: 0
co2: 573
temperature_outside: 7
favourite_speed: 150
unknown_99: 99
unknown_178: 178
control_speed: 60
unknown_bool: True
mode: 'auto'
unknown_bool: True
unknown_bool: True
child_lock: False
unknown_bool: True
unknown_bool: True

So this leaves quite a few of those unknown. The next step, after verifying that the command returns all values, is to find out what those unknown are for:

aleksandrdobrynin commented 4 years ago

I made a mistake in the syntax. Now it's right:

miioenv) pi@ihome-2:~ $ miiocli --debug airfresht2017 --ip 192.168.252.64 --token 12ec5081d18a205372f9deab6518f0af raw_command get_prop '["power"]' INFO:miio.cli:Debug mode active Running command raw_command DEBUG:miio.protocol:Unable to decrypt, returning raw bytes: b'' DEBUG:miio.miioprotocol: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\x0e\x04\xd7\x95\x00\x08\n$' (total 16) value = Container: length = 32 unknown = 0 device_id = unhexlify('0e04d795') ts = 1970-01-07 02:21:24 offset1 = 0 offset2 = 16 length = 16 checksum = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' (total 16) DEBUG:miio.miioprotocol:Discovered 0e04d795 with ts: 1970-01-07 02:21:24, token: b'ffffffffffffffffffffffffffffffff' DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 1, 'method': 'get_prop', 'params': ['power']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:21:24, id: 1) << {'id': 1, 'result': [True], 'exe_time': 170} [True]

aleksandrdobrynin commented 4 years ago

For integers (99, 178), maybe these are already visible somewhere in the app? Yes, this is the percentage of use of the filter and the number of days before its replacement.

rytilahti commented 4 years ago

Yes, but instead of power use something like testparameter. My assumption is that it returns all variables when encountering an unknown property name, so we can request all of them at once (as soon as we find out which position in the output is is for which property).

rytilahti commented 4 years ago

Ok, great! Maybe they are then filter_intermediate and filter_inter_day, or filter_efficient and filter_effi_day: https://github.com/rytilahti/python-miio/blob/master/miio/airfresh_t2017.py#L135-L153 - can you also check those separately to be sure?

aleksandrdobrynin commented 4 years ago

(miioenv) pi@ihome-2:~ $ miiocli --debug airfresht2017 --ip 192.168.252.64 --token 12ec5081d18a205372f9deab6518f0af raw_command get_prop '["filter_intermediate"]'

DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 1, 'method': 'get_prop', 'params': ['filter_intermediate']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:31:37, id: 1) << {'id': 1, 'result': [0, 766, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 160} [0, 766, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True]

(miioenv) pi@ihome-2:~ $ miiocli --debug airfresht2017 --ip 192.168.252.64 --token 12ec5081d18a205372f9deab6518f0af raw_command get_prop '["filter_inter_day"]'

DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 1, 'method': 'get_prop', 'params': ['filter_inter_day']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:31:52, id: 1) << {'id': 1, 'result': [0, 764, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 80} [0, 764, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True]

(miioenv) pi@ihome-2:~ $ miiocli --debug airfresht2017 --ip 192.168.252.64 --token 12ec5081d18a205372f9deab6518f0af raw_command get_prop '["filter_efficient"]'

DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 1, 'method': 'get_prop', 'params': ['filter_efficient']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:32:06, id: 1) << {'id': 1, 'result': [0, 766, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 170} [0, 766, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True]

(miioenv) pi@ihome-2:~ $ miiocli --debug airfresht2017 --ip 192.168.252.64 --token 12ec5081d18a205372f9deab6518f0af raw_command get_prop '["filter_effi_day"]'

DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 1, 'method': 'get_prop', 'params': ['filter_effi_day']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 02:32:20, id: 1) << {'id': 1, 'result': [0, 770, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 80} [0, 770, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True]

rytilahti commented 4 years ago

Okay, it wasn't either of those then, as you can see it returning more than a single value back..

Here is a small script to test those booleans (just save it to airfresh_tester.py or something, and execute it):

from miio import AirFreshT2017
import logging
logging.basicConfig(level=logging.DEBUG)

dev = AirFreshT2017("192.168.252.64", "12ec5081d18a205372f9deab6518f0af")

for cmd in ['set_child_lock', 'set_display', 'set_sound', 'set_child_lock']:
    for val in ["True", "False"]:
        print("props before: %s" % dev.raw_command("get_prop", ["all"]))
        print("setting %s to %s" % (cmd, val))
        try:
            print("result: %s" % dev.send(cmd, [val]))
            print("props after: %s" % dev.raw_command("get_prop", ["all"]))
        except Exception as ex:
            print("unable to change the setting: %s" % ex)
aleksandrdobrynin commented 4 years ago

(miioenv) pi@ihome-2:~/python-miio/miio $ python3 airfresh_tester.py DEBUG:miio.protocol:Unable to decrypt, returning raw bytes: b'' DEBUG:miio.miioprotocol: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\x0e\x04\xd7\x95\x00\x08\x1b\x8a' (total 16) value = Container: length = 32 unknown = 0 device_id = unhexlify('0e04d795') ts = 1970-01-07 03:35:38 offset1 = 0 offset2 = 16 length = 16 checksum = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' (total 16) DEBUG:miio.miioprotocol:Discovered 0e04d795 with ts: 1970-01-07 03:35:38, token: b'ffffffffffffffffffffffffffffffff' DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 1, 'method': 'get_prop', 'params': ['all']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:35:38, id: 1) << {'id': 1, 'result': [0, 674, 8, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 100} props before: [0, 674, 8, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True] setting set_child_lock to True DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 2, 'method': 'get_prop', 'params': ['all']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:35:39, id: 2) << {'id': 2, 'result': [0, 674, 8, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 160} props after: [0, 674, 8, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True] DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 3, 'method': 'get_prop', 'params': ['all']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:35:39, id: 3) << {'id': 3, 'result': [0, 674, 8, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 160} props before: [0, 674, 8, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True] setting set_child_lock to False DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 4, 'method': 'get_prop', 'params': ['all']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:35:39, id: 4) << {'id': 4, 'result': [0, 674, 8, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 160} props after: [0, 674, 8, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True] DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 5, 'method': 'get_prop', 'params': ['all']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:35:39, id: 5) << {'id': 5, 'result': [0, 674, 8, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 160} props before: [0, 674, 8, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True] setting set_display to True DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 6, 'method': 'get_prop', 'params': ['all']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:35:39, id: 6) << {'id': 6, 'result': [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 160} props after: [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True] DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 7, 'method': 'get_prop', 'params': ['all']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:35:40, id: 7) << {'id': 7, 'result': [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 160} props before: [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True] setting set_display to False DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 8, 'method': 'get_prop', 'params': ['all']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:35:40, id: 8) << {'id': 8, 'result': [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 160} props after: [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True] DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 9, 'method': 'get_prop', 'params': ['all']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:35:40, id: 9) << {'id': 9, 'result': [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 150} props before: [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True] setting set_buzzer to True DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 10, 'method': 'get_prop', 'params': ['all']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:35:40, id: 10) << {'id': 10, 'result': [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 150} props after: [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True] DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 11, 'method': 'get_prop', 'params': ['all']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:35:40, id: 11) << {'id': 11, 'result': [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 140} props before: [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True] setting set_buzzer to False DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 12, 'method': 'get_prop', 'params': ['all']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:35:41, id: 12) << {'id': 12, 'result': [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 160} props after: [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True] DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 13, 'method': 'get_prop', 'params': ['all']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:35:41, id: 13) << {'id': 13, 'result': [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 160} props before: [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True] setting set_child_lock to True DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 14, 'method': 'get_prop', 'params': ['all']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:35:41, id: 14) << {'id': 14, 'result': [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 150} props after: [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True] DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 15, 'method': 'get_prop', 'params': ['all']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:35:41, id: 15) << {'id': 15, 'result': [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 140} props before: [0, 674, 7, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True] setting set_child_lock to False DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 16, 'method': 'get_prop', 'params': ['all']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:35:41, id: 16) << {'id': 16, 'result': [0, 674, 8, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 150} props after: [0, 674, 8, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True] DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 17, 'method': 'set_power', 'params': ['on']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:35:46, id: 17) << {'id': 17, 'error': {'code': -9999, 'message': 'user ack timeout'}, 'exe_time': 4020} Traceback (most recent call last): File "airfresh_tester.py", line 17, in dev.on() File "/home/pi/python-miio/miio/airfresh_t2017.py", line 307, in on return self.send("set_power", ["on"]) File "/home/pi/python-miio/miio/device.py", line 124, in send return self._protocol.send(command, parameters, retry_count) File "/home/pi/python-miio/miio/miioprotocol.py", line 196, in send raise DeviceError(error) miio.exceptions.DeviceError: {'code': -9999, 'message': 'user ack timeout'}

rytilahti commented 4 years ago

Sorry, I forgot to call the function to change the values, so I cut off that part of the output from your comment. I modified the script in my previous comment, could you please re-try it?

aleksandrdobrynin commented 4 years ago

(miioenv) pi@ihome-2:~/python-miio/miio $ python3 airfresh_tester.py DEBUG:miio.protocol:Unable to decrypt, returning raw bytes: b'' DEBUG:miio.miioprotocol: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\x0e\x04\xd7\x95\x00\x08\x1b\xea' (total 16) value = Container: length = 32 unknown = 0 device_id = unhexlify('0e04d795') ts = 1970-01-07 03:37:14 offset1 = 0 offset2 = 16 length = 16 checksum = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' (total 16) DEBUG:miio.miioprotocol:Discovered 0e04d795 with ts: 1970-01-07 03:37:14, token: b'ffffffffffffffffffffffffffffffff' DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 1, 'method': 'get_prop', 'params': ['all']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:37:14, id: 1) << {'id': 1, 'result': [0, 671, 8, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True], 'exe_time': 90} props before: [0, 671, 8, 150, 99, 178, 150, True, 'favourite', True, True, False, True, True] setting set_child_lock to True DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 2, 'method': 'set_child_lock', 'params': ['on']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:37:18, id: 2) << {'id': 2, 'error': {'code': -9999, 'message': 'user ack timeout'}, 'exe_time': 4020} Traceback (most recent call last): File "airfresh_tester.py", line 15, in print("result: %s" % func(val)) File "/home/pi/python-miio/miio/airfresh_t2017.py", line 373, in set_child_lock return self.send("set_child_lock", ["on"]) File "/home/pi/python-miio/miio/device.py", line 124, in send return self._protocol.send(command, parameters, retry_count) File "/home/pi/python-miio/miio/miioprotocol.py", line 196, in send raise DeviceError(error) miio.exceptions.DeviceError: {'code': -9999, 'message': 'user ack timeout'}

rytilahti commented 4 years ago

Okay, that very same error ("user ack timeout") as when trying to turn it on/off.. Unfortunately I have no idea what could cause it, and short googling didn't reveal much ideas either..

Maybe there is some sort of pairing process for these? Is it taking 4 seconds (as shown in exe_time) before it errors out? If yes, maybe you could try to push a button on the device to see if that helps.

Another idea worth testing could be checking if the parameter has to be an integer instead of a string:

miiocli --debug airfresht2017 --ip 192.168.252.64 --token 12ec5081d18a205372f9deab6518f0af raw_command set_power '1'

or

miiocli --debug airfresht2017 --ip 192.168.252.64 --token 12ec5081d18a205372f9deab6518f0af raw_command set_power '[1]'

Other than that, I'm out of ideas..

aleksandrdobrynin commented 4 years ago

I did the pairing process and added the device to Mi Home. 4 seconds elapse before an error appears. And what does it mean to press a button on a device? Which button on / off?

(miioenv) pi@ihome-2:~/python-miio/miio $ miiocli --debug airfresht2017 --ip 192.168.252.64 --token 12ec5081d18a205372f9deab6518f0af raw_command set_power '1' INFO:miio.cli:Debug mode active Running command raw_command DEBUG:miio.protocol:Unable to decrypt, returning raw bytes: b'' DEBUG:miio.miioprotocol: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\x0e\x04\xd7\x95\x00\x08\x1f\xc7' (total 16) value = Container: length = 32 unknown = 0 device_id = unhexlify('0e04d795') ts = 1970-01-07 03:53:43 offset1 = 0 offset2 = 16 length = 16 checksum = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' (total 16) DEBUG:miio.miioprotocol:Discovered 0e04d795 with ts: 1970-01-07 03:53:43, token: b'ffffffffffffffffffffffffffffffff' DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 1, 'method': 'set_power', 'params': 1} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:53:47, id: 1) << {'id': 1, 'error': {'code': -9999, 'message': 'user ack timeout'}, 'exe_time': 4010} DEBUG:miio.click_common:Exception: {'code': -9999, 'message': 'user ack timeout'} Traceback (most recent call last): File "/home/pi/python-miio/miio/click_common.py", line 59, in call return self.main(args, kwargs) File "/home/pi/miioenv/lib/python3.7/site-packages/click/core.py", line 782, in main rv = self.invoke(ctx) File "/home/pi/miioenv/lib/python3.7/site-packages/click/core.py", line 1259, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) File "/home/pi/miioenv/lib/python3.7/site-packages/click/core.py", line 1259, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) File "/home/pi/miioenv/lib/python3.7/site-packages/click/core.py", line 1066, in invoke return ctx.invoke(self.callback, ctx.params) File "/home/pi/miioenv/lib/python3.7/site-packages/click/core.py", line 610, in invoke return callback(args, kwargs) File "/home/pi/python-miio/miio/click_common.py", line 280, in wrap kwargs["result"] = func(*args, *kwargs) File "/home/pi/miioenv/lib/python3.7/site-packages/click/decorators.py", line 73, in new_func return ctx.invoke(f, obj, args, kwargs) File "/home/pi/miioenv/lib/python3.7/site-packages/click/core.py", line 610, in invoke return callback(*args, kwargs) File "/home/pi/python-miio/miio/click_common.py", line 245, in command_callback return miio_command.call(miio_device, *args, *kwargs) File "/home/pi/python-miio/miio/click_common.py", line 193, in call return method(args, kwargs) File "/home/pi/python-miio/miio/device.py", line 140, in raw_command return self._protocol.send(command, parameters) File "/home/pi/python-miio/miio/miioprotocol.py", line 196, in send raise DeviceError(error) miio.exceptions.DeviceError: {'code': -9999, 'message': 'user ack timeout'} Error: {'code': -9999, 'message': 'user ack timeout'} (miioenv) pi@ihome-2:~/python-miio/miio $ miiocli --debug airfresht2017 --ip 192.168.252.64 --token 12ec5081d18a205372f9deab6518f0af raw_command set_power '[1]' INFO:miio.cli:Debug mode active Running command raw_command DEBUG:miio.protocol:Unable to decrypt, returning raw bytes: b'' DEBUG:miio.miioprotocol: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\x0e\x04\xd7\x95\x00\x08\x1f\xce' (total 16) value = Container: length = 32 unknown = 0 device_id = unhexlify('0e04d795') ts = 1970-01-07 03:53:50 offset1 = 0 offset2 = 16 length = 16 checksum = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' (total 16) DEBUG:miio.miioprotocol:Discovered 0e04d795 with ts: 1970-01-07 03:53:50, token: b'ffffffffffffffffffffffffffffffff' DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 1, 'method': 'set_power', 'params': [1]} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-07 03:53:54, id: 1) << {'id': 1, 'error': {'code': -9999, 'message': 'user ack timeout'}, 'exe_time': 4010} DEBUG:miio.click_common:Exception: {'code': -9999, 'message': 'user ack timeout'} Traceback (most recent call last): File "/home/pi/python-miio/miio/click_common.py", line 59, in call return self.main(args, kwargs) File "/home/pi/miioenv/lib/python3.7/site-packages/click/core.py", line 782, in main rv = self.invoke(ctx) File "/home/pi/miioenv/lib/python3.7/site-packages/click/core.py", line 1259, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) File "/home/pi/miioenv/lib/python3.7/site-packages/click/core.py", line 1259, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) File "/home/pi/miioenv/lib/python3.7/site-packages/click/core.py", line 1066, in invoke return ctx.invoke(self.callback, ctx.params) File "/home/pi/miioenv/lib/python3.7/site-packages/click/core.py", line 610, in invoke return callback(args, kwargs) File "/home/pi/python-miio/miio/click_common.py", line 280, in wrap kwargs["result"] = func(*args, *kwargs) File "/home/pi/miioenv/lib/python3.7/site-packages/click/decorators.py", line 73, in new_func return ctx.invoke(f, obj, args, kwargs) File "/home/pi/miioenv/lib/python3.7/site-packages/click/core.py", line 610, in invoke return callback(*args, kwargs) File "/home/pi/python-miio/miio/click_common.py", line 245, in command_callback return miio_command.call(miio_device, *args, *kwargs) File "/home/pi/python-miio/miio/click_common.py", line 193, in call return method(args, kwargs) File "/home/pi/python-miio/miio/device.py", line 140, in raw_command return self._protocol.send(command, parameters) File "/home/pi/python-miio/miio/miioprotocol.py", line 196, in send raise DeviceError(error) miio.exceptions.DeviceError: {'code': -9999, 'message': 'user ack timeout'} Error: {'code': -9999, 'message': 'user ack timeout'}

rytilahti commented 4 years ago

How did you do the pairing with the mi home app? I'd assume it's similar process (if it involves pressing something on the physical device).

aleksandrdobrynin commented 4 years ago

To pair, I pressed and held the two buttons as written instructions. Then he clicked on, chose a wifi network and connected the device to 2.4 networks.

rytilahti commented 4 years ago

Ok, maybe try this during that 4s delay when running the command? Or was holding those buttons to reset the wifi settings? In that case, simply try to push those buttons to see what happens.

aleksandrdobrynin commented 4 years ago

I tried, it turned out only to reset the device settings. Now he re-added his Mi Homes while Token has changed.

aleksandrdobrynin commented 4 years ago

Dead end? No more ideas? (( I myself definitely will not be able to implement management, maybe I can somehow help?

rytilahti commented 4 years ago

Okay, that makes sense... How about just simply pressing (without holding) either of those buttons?

I'm out of ideas now though, but at least we know that this error comes up when some sort of user acknowledgement is needed.. I'll update the documentation on this regard later on, hopefully someone figures out how to make it work.

aleksandrdobrynin commented 4 years ago

I did!!! ))))))))

(miioenv) pi@ihome-2:~/python-miio/miio $ miiocli airfresht2017 --ip 192.168.252.64 --token 3beca659e0a80706666a6db9f1809e78 raw_command "set_power" ["False"] Running command raw_command ['ok']

(miioenv) pi@ihome-2:~/python-miio/miio $ miiocli airfresht2017 --ip 192.168.252.64 --token 3beca659e0a80706666a6db9f1809e78 raw_command "set_power" ["True"] Running command raw_command ['ok']

It's works.

rytilahti commented 4 years ago

Could you please explain what exactly you did? :-)

Anyway, could you now please run the test script above to find out those booleans, so that we can proceed to add support for this device!

aleksandrdobrynin commented 4 years ago

I just picked up the correct parameter and it turned out to turn the device on and off. The output of the command is higher.

The script fails with a timeout error.

(miioenv) pi@ihome-2:~/python-miio/miio $ python3 airfresh_tester.py DEBUG:miio.protocol:Unable to decrypt, returning raw bytes: b'' DEBUG:miio.miioprotocol: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\x0e\x04\xd7\x95\x00\x00\x12k' (total 16) value = Container: length = 32 unknown = 0 device_id = unhexlify('0e04d795') ts = 1970-01-01 01:18:35 offset1 = 0 offset2 = 16 length = 16 checksum = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' (total 16) DEBUG:miio.miioprotocol:Discovered 0e04d795 with ts: 1970-01-01 01:18:35, token: b'ffffffffffffffffffffffffffffffff' DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 1, 'method': 'get_prop', 'params': ['all']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-01 01:18:35, id: 1) << {'id': 1, 'result': [0, 693, 6, 150, 98, 176, 0, False, 'auto', True, True, False, True, False], 'exe_time': 80} props before: [0, 693, 6, 150, 98, 176, 0, False, 'auto', True, True, False, True, False] setting set_child_lock to True DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 2, 'method': 'set_child_lock', 'params': ['on']} DEBUG:miio.miioprotocol:192.168.252.64:54321 (ts: 1970-01-01 01:18:39, id: 2) << {'id': 2, 'error': {'code': -9999, 'message': 'user ack timeout'}, 'exe_time': 4010} Traceback (most recent call last): File "airfresh_tester.py", line 15, in print("result: %s" % func(val)) File "/home/pi/python-miio/miio/airfresh_t2017.py", line 373, in set_child_lock return self.send("set_child_lock", ["on"]) File "/home/pi/python-miio/miio/device.py", line 124, in send return self._protocol.send(command, parameters, retry_count) File "/home/pi/python-miio/miio/miioprotocol.py", line 196, in send raise DeviceError(error) miio.exceptions.DeviceError: {'code': -9999, 'message': 'user ack timeout'}

rytilahti commented 4 years ago

Hmm, oh. So no need to physically do anything with the device? Looking at your command, looks like it wanted to have that boolean as a string..

So you could try to see if this works:

miiocli airfresht2017 --ip 192.168.252.64 --token 3beca659e0a80706666a6db9f1809e78 raw_command "set_child_lock" '["True"]'
aleksandrdobrynin commented 4 years ago

(miioenv) pi@ihome-2:~/python-miio/miio $ miiocli airfresht2017 --ip 192.168.252.64 --token 3beca659e0a80706666a6db9f1809e78 raw_command "set_child_lock" ["True"] Running command raw_command ['ok']

It's works.

rytilahti commented 4 years ago

Ok, great! I updated the airfresh_tester.py above, could you give it a new try now.

aleksandrdobrynin commented 4 years ago

The device has three operating modes: Auto Night Manual (depends on the area of the room displayed in Mi Home).

There are also modes for turning on the heating of the supplied air.

I’d like to understand how to add it and manage them.

Also, if you switch the operating mode of the device in Mi Home to night or manual mode, then the status output is received with an error:

(miioenv) pi@ihome-2:~/python-miio/miio $ miiocli airfresht2017 --ip 192.168.252.64 --token 3beca659e0a80706666a6db9f1809e78 status ValueError: 176 is not a valid PtcLevel

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "/home/pi/miioenv/bin/miiocli", line 11, in load_entry_point('python-miio', 'console_scripts', 'miiocli')() File "/home/pi/python-miio/miio/cli.py", line 44, in create_cli return cli(auto_envvar_prefix="MIIO") File "/home/pi/python-miio/miio/click_common.py", line 59, in call return self.main(args, kwargs) File "/home/pi/miioenv/lib/python3.7/site-packages/click/core.py", line 782, in main rv = self.invoke(ctx) File "/home/pi/miioenv/lib/python3.7/site-packages/click/core.py", line 1259, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) File "/home/pi/miioenv/lib/python3.7/site-packages/click/core.py", line 1259, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) File "/home/pi/miioenv/lib/python3.7/site-packages/click/core.py", line 1066, in invoke return ctx.invoke(self.callback, ctx.params) File "/home/pi/miioenv/lib/python3.7/site-packages/click/core.py", line 610, in invoke return callback(args, kwargs) File "/home/pi/python-miio/miio/click_common.py", line 285, in wrap result_msg = result_msg_fmt.format(kwargs) File "/home/pi/python-miio/miio/airfresh_t2017.py", line 163, in ptc_level return PtcLevel(self.data["ptc_level"]) File "/usr/lib/python3.7/enum.py", line 310, in call return cls.new(cls, value) File "/usr/lib/python3.7/enum.py", line 564, in new raise exc File "/usr/lib/python3.7/enum.py", line 548, in new result = cls.missing(value) File "/usr/lib/python3.7/enum.py", line 577, in missing raise ValueError("%r is not a valid %s" % (value, cls.name)) ValueError: 176 is not a valid PtcLevel

Normally, the status is displayed only in auto mode. (miioenv) pi@ihome-2:~/python-miio/miio $ miiocli airfresh --ip 192.168.252.64 --token 3beca659e0a80706666a6db9f1809e78 status Power: True AQI: 725 μg/m³ Average AQI: 7 μg/m³ Temperature: 0.0 °C Humidity: 100 % CO2: 150 % Mode: auto LED: False LED brightness: LedBrightness.Dim Buzzer: False Child lock: False Filter life remaining: None % Filter hours used: True Use time: True s Motor speed: True rpm

aleksandrdobrynin commented 4 years ago

Output of updated airfresh_tester.py

(miioenv) pi@ihome-2:~/python-miio/miio $ python3 airfresh_tester.py props before: [0, 667, 6, 150, 98, 176, 60, True, 'auto', True, True, False, True, True] setting set_child_lock to True Traceback (most recent call last): File "airfresh_tester.py", line 11, in print("result: %s" % dev.send(cmd, [val])) File "/home/pi/python-miio/miio/device.py", line 124, in send return self._protocol.send(command, parameters, retry_count) File "/home/pi/python-miio/miio/miioprotocol.py", line 196, in send raise DeviceError(error) miio.exceptions.DeviceError: {'code': -9999, 'message': 'user ack timeout'}

rytilahti commented 4 years ago

One step at a time, let us first figure out the properties, then we can fix the status issue / setting modes. These do differ from the t2017 model, so some adaptations need to be done.

I updated the script, please try again.

aleksandrdobrynin commented 4 years ago

(miioenv) pi@ihome-2:~/python-miio/miio $ python3 airfresh_tester.py props before: [0, 623, 7, 150, 98, 176, 60, True, 'auto', True, True, False, True, True] setting set_child_lock to "True" Traceback (most recent call last): File "airfresh_tester.py", line 11, in print("result: %s" % dev.send(cmd, [val])) File "/home/pi/python-miio/miio/device.py", line 124, in send return self._protocol.send(command, parameters, retry_count) File "/home/pi/python-miio/miio/miioprotocol.py", line 196, in send raise DeviceError(error) miio.exceptions.DeviceError: {'code': -9999, 'message': 'user ack timeout'}

rytilahti commented 4 years ago

Hm, but set_child_lock ["True"] was working using the raw_command? Could you turn logging.INFO to logging.DEBUG in the tester script, and compare the request contents for "set_child_lock" to the one when using debug mode with the raw_command?

The line containing "set_child_lock" in the outputs (something like >>: {'id': 1, 'method': 'set_child_lock', 'params': '..'), what does it show for "params"?

aleksandrdobrynin commented 4 years ago

"Hm, but set_child_lock ["True"] was working using the raw_command?" Yes, it worked.

logging.DEBUG

DEBUG:miio.miioprotocol:192.168.252.64:54321 >>: {'id': 2, 'method': 'set_child_lock', 'params': ['"True"']}

rytilahti commented 4 years ago

Well, I suppose there must be something different in those parameters for both requests?

Anycase, I updated the script once more to remove one pair of quotation marks, and now if it fails to do a request, it will try the other commands, too.

You could try to play around with the script to figure out the required formatting, I think it's simpler that way than me trying to keep changing the script.

aleksandrdobrynin commented 4 years ago

And what should happen as a result of the script?

rytilahti commented 4 years ago

So, the script simply tries to change those four settings ('set_child_lock', 'set_display', 'set_sound', 'set_child_lock') back and forth while printing out all the available properties (to complete the listing in https://github.com/rytilahti/python-miio/issues/662#issuecomment-607863160).

I made it in hopes that it will simplify understanding what those boolean values in the output stand for, but adding support for those commands will also need us to figure out the correct commands (and inputs), so.. :-)