syssi / xiaomi_airconditioningcompanion

Xiaomi Mi and Aqara Air Conditioning Companion integration for Home Assistant
Apache License 2.0
400 stars 94 forks source link

Understanding the custom_component shenanigans #40

Closed gsotiriou closed 5 years ago

gsotiriou commented 5 years ago

Hi, I have installed your component and I can see the information in my user interface. Previously I had used the companion with MiHome where I had registered my air-condition through a list of registered devices that Xiaomi has pre-selected settings (I assume).

Finging A) What has confused me is that your custom_component initialised already with some settings and it could control my air-condition out of the box (no training occurred).

Finding B) What I realised it "seems" as if the custom_component uses the last settings I used for my registered air-condition through MiHome when I used it through MiHome.

Finding C) Looking in of home assistant I see that my climate component has a value of "ac_model: 010504870000466601" which I suspect is inside the companion's memory now and forces it to use the necessary IR commands for this particular model.

Finding D) It is very unusual that the companion uses these specific settings only and refuses to change anything through the UI (like mode, fan speed, or temperature) - but the ON/OFF functionality works.

Do I need to somehow make it "forget" the ac_model variable and re-train the companion only through your custom_component?

Do I need to just "train" it for the rest commands that it cannot issue besides the ON/OFF that already works?

In terms of training how do slots exactly work? What is the philosophy? Based on the documentation I cannot understand right now, but if you help me understand, I am willing to put all this knowledge into examples and extend the existing documentation.

That is all for now in a nutshell! I will appreciate the effort and time you take to reply. And I already thank you and appreciate your hard work on this!

Regards, George

syssi commented 5 years ago

A) The AC partner (device firmware) is some kind of a middleware. You must use the MiHome app to upload a so called "preset" of infrared commands to the AC partner. Later on you are able to use this custom component to request/send a configuration to the AC partner. The device translates the configuration (power state, temperature, swing mode, ...) into the respective infrared instruction.

Take a look at this method: https://github.com/rytilahti/python-miio/blob/master/miio/airconditioningcompanion.py#L403

If you change the temperature f.e. this send_configuraton method is called. The current state of the custom component (a combination of power, operationMode, targetTemperature, fanSpeed, swingMode and LED state) is transferred to the AC partner. The AC partner translates these configuration/state by the "preset" (applied by MiHome beforehand) to the proper infrared command / configuration of your air condition.

B) The MiHome app is needed once to setup the AC partner. Because of the online "preset" database.

C) The MiHome app sets the ac_model. It's needed later on to select the proper preset.

gsotiriou commented 5 years ago

Ok, so I guess I have two more questions!

A) Why the settings that the custom_component started with (inherited from MiHome) do not change when I change them from the UI? (i.e. temperature is stuck on 22 degrees, mode in heat, fan speed in high and no matter what I select it won't send the command).

B) Can I use the component to separately train the GW for another IR device (i.e. my Logitech speakers)? Or similar to AC I need to train from MiHome app - then use from custom component?

Thanks again! -George

syssi commented 5 years ago

A) The custom component retrieves the current state periodically from the AC partner (middleware). If you change the temperature via the MiHome app the information should propagate to Home Assistant after a while. If you use the custom component to change the temperature and it doesn't work - this is a bug! Which AC partner hardware version (v1, v2, v3) do you own?

Please enable the debug output of the component:

# configuration.yaml

logger:
  default: warn
  logs:
    custom_components.climate.xiaomi_miio: debug
    miio: debug

B) Yes. You can learn/capture additional commands by

https://github.com/syssi/xiaomi_airconditioningcompanion#service-climatexiaomi_miio_learn_command

And replay a previously captured command by

https://github.com/syssi/xiaomi_airconditioningcompanion#service-climatexiaomi_miio_send_command

syssi commented 5 years ago

Please feel free to ask additional questions and point out bad behaviour. My air condition doesn't work with the AC partner. I'm unable to test the custom component properly.

gsotiriou commented 5 years ago

Hi again, I will update this with some back-to-back replies with the output log after several actions have been performed. Kicking things off with a fresh cold start of home assistant. This is the first thing to pop-up:


2018-12-02 11:58:38 DEBUG (MainThread) [miio.protocol] Unable to decrypt, returning raw bytes: b''
2018-12-02 11:58:38 DEBUG (MainThread) [miio.device] Got a response: Container: 
    data = Container: 
        data =  (total 0)
        value =  (total 0)
        offset1 = 32
        offset2 = 32
        length = 0
    header = Container: 
        data = !1\x00 \x00\x00\x00\x00\x045$<\x00\x00\xdf\x0c (total 16)
        value = Container: 
            length = 32
            unknown = 0
            device_id = \x045$< (total 4)
            ts = 1970-01-01 15:51:40
        offset1 = 0
        offset2 = 16
        length = 16
    checksum = \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 (total 16)
2018-12-02 11:58:38 DEBUG (MainThread) [miio.device] Discovered 0435243c with ts: 1970-01-01 15:51:40, token: b'00000000000000000000000000000000'
2018-12-02 11:58:39 DEBUG (MainThread) [miio.device] 192.168.1.168:54321 >>: {'id': 1, 'method': 'miIO.info', 'params': []}
2018-12-02 11:58:39 DEBUG (MainThread) [miio.device] 192.168.1.168:54321 (ts: 1970-01-01 15:51:40, id: 1) << {'result': {'life': 57100, 'cfg_time': 0, 'token': '80dd4b74bb147988b6d2ce11acdb5dbc', 'mac': '78:11:DC:46:E7:16', 'fw_ver': '1.4.1_145', 'hw_ver': 'MW300', 'model': 'lumi.acpartner.v2', 'mcu_fw_ver': '0143', 'wifi_fw_ver': 'SD878x-14.76.36.p84-702.1.0-WM', 'ap': {'rssi': -30, 'ssid': 'Connecto Patronum', 'bssid': '34:CE:00:67:40:7B'}, 'netif': {'localIp': '192.168.1.168', 'mask': '255.255.255.0', 'gw': '192.168.1.2', 'gw_mac': '34:CE:00:67:40:79'}, 'mmfree': 169504, 'ot': 'ott', 'otu_stat': [0, 0, 0, 0, 0, 3], 'ott_stat': [1, 0, 1, 237]}, 'id': 1}
2018-12-02 11:58:39 INFO (MainThread) [custom_components.climate.xiaomi_miio] lumi.acpartner.v2 1.4.1_145 MW300 detected
2018-12-02 11:58:39 DEBUG (SyncWorker_12) [miio.device] 192.168.1.168:54321 >>: {'id': 2, 'method': 'get_model_and_state', 'params': []}
2018-12-02 11:58:39 DEBUG (SyncWorker_12) [miio.device] 192.168.1.168:54321 (ts: 1970-01-01 15:51:40, id: 2) << {'result': ['010504870000466601', '01002117A100004666', '0'], 'id': 2}
2018-12-02 11:58:39 DEBUG (MainThread) [custom_components.climate.xiaomi_miio] Got new state: <AirConditioningCompanionStatus power=off, load_power=0, air_condition_model=010504870000466601, model_format=1, device_type=5, air_condition_brand=487, air_condition_remote=4666, state_format=1, air_condition_configuration=002117A1, led=False, target_temperature=23, swing_mode=SwingMode.Off, fan_speed=FanSpeed.High, mode=OperationMode.Heat>```
gsotiriou commented 5 years ago

Trying to turn the AC ON:

Expected behavior: The air-conditioning unit should turn on. Current behavior: The air-conditioning unit is turning on.

2018-12-02 12:18:55 DEBUG (SyncWorker_11) [miio.device] 192.168.1.168:54321 >>: {'id': 218, 'method': 'set_power', 'params': ['on']}
2018-12-02 12:18:55 DEBUG (SyncWorker_11) [miio.device] 192.168.1.168:54321 (ts: 1970-01-01 00:03:58, id: 218) << {'result': ['ok'], 'id': 218}
2018-12-02 12:18:55 DEBUG (MainThread) [custom_components.climate.xiaomi_miio] Response received: ['ok']
2018-12-02 12:18:55 DEBUG (SyncWorker_14) [miio.device] 192.168.1.168:54321 >>: {'id': 219, 'method': 'get_model_and_state', 'params': []}
2018-12-02 12:18:55 DEBUG (SyncWorker_14) [miio.device] 192.168.1.168:54321 (ts: 1970-01-01 00:03:58, id: 219) << {'result': ['010504870000466601', '011021160100004666', '0'], 'id': 219}
2018-12-02 12:18:55 DEBUG (MainThread) [custom_components.climate.xiaomi_miio] Got new state: <AirConditioningCompanionStatus power=on, load_power=0, air_condition_model=010504870000466601, model_format=1, device_type=5, air_condition_brand=487, air_condition_remote=4666, state_format=1, air_condition_configuration=10211601, led=True, target_temperature=22, swing_mode=SwingMode.Off, fan_speed=FanSpeed.High, mode=OperationMode.Heat>
gsotiriou commented 5 years ago

Unplugging and replugging the air conditioning device from its socket while home assistant running:

2018-12-02 12:15:48 DEBUG (SyncWorker_4) [miio.device] Retrying with incremented id, retries left: 3
2018-12-02 12:15:48 DEBUG (SyncWorker_4) [miio.protocol] Unable to decrypt, returning raw bytes: b''
2018-12-02 12:15:48 DEBUG (SyncWorker_4) [miio.device] Got a response: Container: 
    data = Container: 
        data =  (total 0)
        value =  (total 0)
        offset1 = 32
        offset2 = 32
        length = 0
    header = Container: 
        data = !1\x00 \x00\x00\x00\x00\x045$<\x00\x00\x002 (total 16)
        value = Container: 
            length = 32
            unknown = 0
            device_id = \x045$< (total 4)
            ts = 1970-01-01 00:00:50
        offset1 = 0
        offset2 = 16
        length = 16
    checksum = \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 (total 16)
2018-12-02 12:15:48 DEBUG (SyncWorker_4) [miio.device] Discovered 0435243c with ts: 1970-01-01 00:00:50, token: b'00000000000000000000000000000000'
2018-12-02 12:15:48 DEBUG (SyncWorker_4) [miio.device] 192.168.1.168:54321 >>: {'id': 113, 'method': 'get_model_and_state', 'params': []}
2018-12-02 12:15:48 DEBUG (SyncWorker_4) [miio.device] 192.168.1.168:54321 (ts: 1970-01-01 00:00:51, id: 113) << {'result': ['010504870000466601', '010021160100004666', '0'], 'id': 113}
2018-12-02 12:15:48 DEBUG (MainThread) [custom_components.climate.xiaomi_miio] Got new state: <AirConditioningCompanionStatus power=off, load_power=0, air_condition_model=010504870000466601, model_format=1, device_type=5, air_condition_brand=487, air_condition_remote=4666, state_format=1, air_condition_configuration=00211601, led=True, target_temperature=22, swing_mode=SwingMode.Off, fan_speed=FanSpeed.High, mode=OperationMode.Heat>
gsotiriou commented 5 years ago

Changing the temperature from 22 to 23 degrees (seems to be accepted the air conditioning makes happy noises):

2018-12-02 12:20:12 DEBUG (SyncWorker_10) [miio.device] 192.168.1.168:54321 >>: {'id': 221, 'method': 'send_cmd', 'params': ['0100004666102117A1']}
2018-12-02 12:20:12 DEBUG (SyncWorker_10) [miio.device] 192.168.1.168:54321 (ts: 1970-01-01 00:05:15, id: 221) << {'result': ['ok'], 'id': 221}
2018-12-02 12:20:12 DEBUG (MainThread) [custom_components.climate.xiaomi_miio] Response received: ['ok']
2018-12-02 12:20:12 DEBUG (SyncWorker_9) [miio.device] 192.168.1.168:54321 >>: {'id': 222, 'method': 'get_model_and_state', 'params': []}
2018-12-02 12:20:12 DEBUG (SyncWorker_9) [miio.device] 192.168.1.168:54321 (ts: 1970-01-01 00:05:15, id: 222) << {'result': ['010504870000466601', '01102117A100004666', '0'], 'id': 222}
2018-12-02 12:20:12 DEBUG (MainThread) [custom_components.climate.xiaomi_miio] Got new state: <AirConditioningCompanionStatus power=on, load_power=0, air_condition_model=010504870000466601, model_format=1, device_type=5, air_condition_brand=487, air_condition_remote=4666, state_format=1, air_condition_configuration=102117A1, led=False, target_temperature=23, swing_mode=SwingMode.Off, fan_speed=FanSpeed.High, mode=OperationMode.Heat>
gsotiriou commented 5 years ago

Changing from "heat" to "ventilate" - air condition unit didn't seem to accept it with beepbeep noise but from the behavior I can say it's most likely accepted:

2018-12-02 12:21:12 DEBUG (SyncWorker_3) [miio.device] 192.168.1.168:54321 >>: {'id': 224, 'method': 'send_cmd', 'params': ['0100004666142117A1']}
2018-12-02 12:21:12 DEBUG (SyncWorker_3) [miio.device] 192.168.1.168:54321 (ts: 1970-01-01 00:06:16, id: 224) << {'result': ['ok'], 'id': 224}
2018-12-02 12:21:12 DEBUG (MainThread) [custom_components.climate.xiaomi_miio] Response received: ['ok']
2018-12-02 12:21:12 DEBUG (SyncWorker_2) [miio.device] 192.168.1.168:54321 >>: {'id': 225, 'method': 'get_model_and_state', 'params': []}
2018-12-02 12:21:12 DEBUG (SyncWorker_2) [miio.device] 192.168.1.168:54321 (ts: 1970-01-01 00:06:16, id: 225) << {'result': ['010504870000466601', '01142117A100004666', '0'], 'id': 225}
2018-12-02 12:21:12 DEBUG (MainThread) [custom_components.climate.xiaomi_miio] Got new state: <AirConditioningCompanionStatus power=on, load_power=0, air_condition_model=010504870000466601, model_format=1, device_type=5, air_condition_brand=487, air_condition_remote=4666, state_format=1, air_condition_configuration=142117A1, led=False, target_temperature=23, swing_mode=SwingMode.Off, fan_speed=FanSpeed.High, mode=OperationMode.Ventilate>
gsotiriou commented 5 years ago

Changing fan mode from "high" to "medium" - didn't seem to get accepted neither through a beepbeep sound neither through the unit itself it still blows in high:

2018-12-02 12:22:25 ERROR (MainThread) [homeassistant.core] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/service.py", line 277, in _handle_service_platform_call
    await getattr(entity, func)(**data)
TypeError: async_set_fan_mode() got an unexpected keyword argument 'fan_mode'

EDIT: Went back to "heat" from "ventilate" tried changing fan mode to "medium" from "high" again same log as above.

gsotiriou commented 5 years ago

I don't want to spam you more - the whole log file can be found here and if you want me try a specific use case let me know!

-G