Skip to content

Conversation

@p-monteiro
Copy link

@p-monteiro p-monteiro commented Sep 23, 2025

[DO NOT MERGE]

️ATTENTION

This PR changes the domain of the integration, so current users will lose their device configs!
The config schema also changed, so verify your YAML if you use it to configure the devices.

This PR introduces a rewrite of this integration. The main goal of this was to better align the integration with the Home Assistant (HA) development workflow with two main changes:

  • Completely separate device API code from HA code
  • Align with code style guidelines (mainly Ruff code formatting and full typing)

Other changes that are present in this PR:

  • Async device communication
  • Use a device coordinator to fetch data from the device
  • Device Features are user-selectable since the Gree API does not provide a reliable method of getting them
  • Improvements to entity creation and config flow with better errors and organization
  • Gree API functions are better structured and clearer to understand the logic, which is also reused when possible
  • Gree API is fully declarative, no string guessing
  • Gree API now provides a GreeDevice object to handle device logic
  • Implement Auto Encryption version
  • Expose entity restore behavior as a configuration
  • Properly allow to reconfigure a config entry (including device connection, useful for when a device changes IP)
  • Support for individual device removal
  • RestoreEntity support in ClimateEntity
  • Exposed all device sensors as entities
  • Allow to set the device temperature units (shown on the device display)

I want full feature parity with the current integration and iron out some bugs before this is ready to merge (if you so wish). Currently missing and wishlist:

  • [Bug] Broken VRF Device Status

As you can see, there are a lot of changes, and I understand if this does not go through as is.
I am creating the PR mainly to gather feedback and track progress since most features are now present in this PR.
Don't treat this PR as blocking. I am tracking new changes and integrating them as they are committed.

Also, since this is a big rewrite, I wonder if we should use it to bump the major version (4?) and possibly change the domain to not replace the official integration (as I saw in the bug reports that it might impose some problems).

- Change config flow to: be multi step and allow setting the device features; allow to reconfigure an entry
- Separate HA and Device API logic: device API is now declarative and handles device behaviour. HA entities expose the device
- Implement a coordinator
- Async device communication
- More error handling
- Move consts around
- Proper error report on config_flow
- Proper translations on config_flow
- Configuration of timeout
- Fetch device info during binding
@p-monteiro
Copy link
Author

@RobHofmann I was adding the temperature step back, but I'm not sure of its utility.
Is there any device that accepts non-integer ºC/ºF?

@domialex
Copy link
Contributor

@p-monteiro
The temperature step should not be in the configuration entities anyways, it should be in the climate options. That was a mistake on my part.

@p-monteiro
Copy link
Author

Hi @domialex, that's fine. I'm more interested in the real use case for it. Should it be locked to integers? I don't think any device supports half degrees or even 0.1 steps, as is the lower limit for the current slider...

@p-monteiro
Copy link
Author

@meirlo The thing is, at first glance, the subdevices API does not provide some of the parameters that you want (they came empty in the status pack, but it needs to be further investigated), so maybe the official app sends commands to both the subunit and the main unit when you change the mode on the subunit. If that's the case, it can actually be easier to make the subunits override the main one, or just omit the properties altogether.

I just pushed a commit, please try it, and check if the main device can be discovered, added and it works. Ignore the subunits for a moment hehe

@p-monteiro
Copy link
Author

This might need some architectural changes in the way we communicate with the device (possibly to communicate with the main and sub devices for getting and setting the status)

@p-monteiro
Copy link
Author

@meirlo Another thing, in a VRF system all units are the same as the main one right? So the capabilities of them all are the same.

@meirlo
Copy link
Contributor

meirlo commented Oct 15, 2025

I'm getting an error when trying to add the entity without the sub unit

Logger: custom_components.gree.climate
Source: custom_components/gree/climate.py:846
integration: gree (documentation, issues)
First occurred: 5:37:20 PM (1 occurrence)
Last logged: 5:37:20 PM

Error in 'async_set_temperature'
Traceback (most recent call last):
  File "/config/custom_components/gree/gree_api.py", line 372, in fetch_result
    received_json = await udp_request_async(
                    ^^^^^^^^^^^^^^^^^^^^^^^^
        ip_addr, port, json_data, max_connection_attempts, timeout
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/config/custom_components/gree/gree_api.py", line 302, in udp_request_async
    raise ValueError(
        f"Failed to communicate with device '{ip_addr}:{port}' after {max_retries} attempts"
    )
ValueError: Failed to communicate with device '192.168.69.10:7000' after 5 attempts

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/config/custom_components/gree/gree_api.py", line 719, in gree_set_status
    result = await get_result_pack(
             ^^^^^^^^^^^^^^^^^^^^^^
    ...<7 lines>...
    )
    ^
  File "/config/custom_components/gree/gree_api.py", line 428, in get_result_pack
    data = await fetch_result(
           ^^^^^^^^^^^^^^^^^^^
    ...<7 lines>...
    )
    ^
  File "/config/custom_components/gree/gree_api.py", line 376, in fetch_result
    raise ValueError(f"Error communicating with {ip_addr}: {err}") from err
ValueError: Error communicating with 192.168.69.10: Failed to communicate with device '192.168.69.10:7000' after 5 attempts

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/config/custom_components/gree/gree_device.py", line 248, in update_device_status
    await gree_set_status(
    ...<10 lines>...
    )
  File "/config/custom_components/gree/gree_api.py", line 729, in gree_set_status
    raise ValueError("Error getting device status") from err
ValueError: Error getting device status

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/config/custom_components/gree/climate.py", line 846, in async_set_temperature
    await self.device.update_device_status()
  File "/config/custom_components/gree/gree_device.py", line 265, in update_device_status
    raise ValueError("Error setting device status") from err
ValueError: Error setting device status

For the second question, the indoor units are not always identical. For example, my living room ac is a different one than the rest.

Can you please elaborate which parameters are missing?

@p-monteiro
Copy link
Author

@meirlo I'm having a hard time debugging the issue, sorry. Please try the latest version and provide the full debug log, not only the exception.
Your error shows a problem communicating with the device, so either the connection is the problem or the pack sent to the device is invalid, and it does not respond correctly.

@p-monteiro
Copy link
Author

I've been using this for some time now to control my AC without any problem. It would be nice to have more people trying out the latest commit to find bugs or missing features so this can be merged, including people with VRF.

@rudizl
Copy link

rudizl commented Jan 21, 2026

I`ve installed your code, everything works- the 1-st is GEH18AAXF-K6DNA1 and the second is GWH12AVCXD-K6DNA1A. Both with FW 1.31.

@chkr1011
Copy link

I tried your code as well but I am not able to connect the devices any longer. With the "original" version it worked fine. It says that it was not able to obtain the encryption key. The "original" code is capable of doing this (encryption version = 2).

I also picked the encryption keys from the logs from the original version but it did not help. The devices are also no auto discovered anymore. None of the 3 devices is found. The original integration was able to find these but adding still required manual input.

@p-monteiro
Copy link
Author

@chkr1011 Sorry, I didn't have much time lately to continue this code, apart from minor tweaks.

Can you provide more information about your case, if it is the latest code, what kind of setup you have (normal or VRF), and if possible, the logs from the integration (enable debug mode before searching or adding a device).

Hopefully, next month I'll be able to take a deeper look into the issues.

@chkr1011
Copy link

chkr1011 commented Jan 21, 2026

Here is what I get when trying to discover the devices:

2026-01-21 19:38:58.691 ERROR (MainThread) [aiohttp.server] Error handling request from 192.168.1.159
Traceback (most recent call last):
  File "/usr/local/lib/python3.13/site-packages/aiohttp/web_protocol.py", line 510, in _handle_request
    resp = await request_handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/aiohttp/web_app.py", line 569, in _handle
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/aiohttp/web_middlewares.py", line 117, in impl
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 92, in security_filter_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 87, in forwarded_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 26, in request_context_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 86, in ban_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 242, in auth_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/headers.py", line 41, in headers_middleware
    response = await handler(request)
               ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/http.py", line 73, in handle
    result = await handler(request, **request.match_info)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/decorators.py", line 83, in with_admin
    return await func(self, request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/config/config_entries.py", line 234, in post
    return await super().post(request, flow_id)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 74, in wrapper
    return await method(view, request, data, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 121, in post
    result = await self._flow_mgr.async_configure(flow_id, data)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 346, in async_configure
    result = await self._async_configure(flow_id, user_input)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 393, in _async_configure
    result = await self._async_handle_step(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        flow, cur_step["step_id"], user_input
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 493, in _async_handle_step
    result: _FlowResultT = await getattr(flow, method)(user_input)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/gree_custom/config_flow.py", line 579, in async_step_user
    return await self.async_step_manual_discovery()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/gree_custom/config_flow.py", line 622, in async_step_manual_discovery
    self._discovered_devices = await self._discover_devices(self.hass)
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/gree_custom/config_flow.py", line 893, in _discover_devices
    return await discover_gree_devices(broadcast_addresses, 5)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/gree_custom/aiogree/api.py", line 813, in discover_gree_devices
    data = get_gree_response_data(
        response,
        gree_get_default_cipher(EncryptionVersion.V1),
        EncryptionVersion.V1,
    )
  File "/config/custom_components/gree_custom/aiogree/api.py", line 393, in get_gree_response_data
    decryptedPack = cipher.decrypt(pack)
  File "/usr/local/lib/python3.13/site-packages/Crypto/Cipher/_mode_ecb.py", line 196, in decrypt
    raise ValueError("Data must be aligned to block boundary in ECB mode")
ValueError: Data must be aligned to block boundary in ECB mode

To me this looks like that the integration is not trying encryption version 2 when auto discovering devices.

The following log is from the manual config flow:

2026-01-21 19:49:03.145 ERROR (MainThread) [custom_components.gree_custom.config_flow] Cannot connect
Traceback (most recent call last):
  File "/config/custom_components/gree_custom/aiogree/api.py", line 765, in gree_get_device_info
    data: dict = await get_result_pack(
                 ^^^^^^^^^^^^^^^^^^^^^^
    ...<7 lines>...
    )
    ^
  File "/config/custom_components/gree_custom/aiogree/api.py", line 420, in get_result_pack
    data = await fetch_result(
           ^^^^^^^^^^^^^^^^^^^
    ...<7 lines>...
    )
    ^
  File "/config/custom_components/gree_custom/aiogree/api.py", line 375, in fetch_result
    data = get_gree_response_data(received_json, cipher, encryption_version)
  File "/config/custom_components/gree_custom/aiogree/api.py", line 393, in get_gree_response_data
    decryptedPack = cipher.decrypt(pack)
  File "/usr/local/lib/python3.13/site-packages/Crypto/Cipher/_mode_ecb.py", line 196, in decrypt
    raise ValueError("Data must be aligned to block boundary in ECB mode")
ValueError: Data must be aligned to block boundary in ECB mode

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/config/custom_components/gree_custom/aiogree/device.py", line 148, in bind_device
    self._raw_info = await gree_get_device_info(
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<3 lines>...
    )
    ^
  File "/config/custom_components/gree_custom/aiogree/api.py", line 776, in gree_get_device_info
    raise ValueError("Error retrieving basic device info") from err
ValueError: Error retrieving basic device info

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/config/custom_components/gree_custom/config_flow.py", line 686, in async_step_manual_add
    self._discovered_subdevices = await self._devices[
                                  ^^^^^^^^^^^^^^^^^^^^
        _main_device.mac_address_sub
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ].fetch_sub_devices()
    ^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/gree_custom/aiogree/device.py", line 175, in fetch_sub_devices
    await self.bind_device()
  File "/config/custom_components/gree_custom/aiogree/device.py", line 155, in bind_device
    raise CannotConnect(
        f"Not able to connect to the device {self._ip_addr}"
    ) from e
custom_components.gree_custom.aiogree.device.CannotConnect: Not able to connect to the device 192.168.1.74

For the manual config flow I filled IP, MAC, Encryption Version 2 and the Encryption Key as well. These were working properly with the original version.

The device is a Vaillant Vai5. I don't know which regular gree model this is. But no VRF.

@p-monteiro
Copy link
Author

@chkr1011 Thanks for the logs, will take a look when I can. I think the original code did discovery using V1 only and V2 was only used for binding/communicating, will investigate.

@rudizl
Copy link

rudizl commented Jan 21, 2026

Ive added my ACs manually with IP and MAC. The encryption was discovered automatically after thah and for both is V2. Didn`t filled the encryption key, as I saw thaht the field is already with ****** :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants