Skip to content

feat: gateway sub-device discovery (VRF / multi-split support) - #148

Open
meirlo wants to merge 1 commit into
cmroche:masterfrom
meirlo:master
Open

feat: gateway sub-device discovery (VRF / multi-split support)#148
meirlo wants to merge 1 commit into
cmroche:masterfrom
meirlo:master

Conversation

@meirlo

@meirlo meirlo commented Apr 16, 2026

Copy link
Copy Markdown

Summary

Adds support for Gree gateway modules that front multiple indoor units (VRF / multi-split systems). A single Wi-Fi gateway exposes several indoor units, each addressed by its own internal MAC inside the encrypted pack while all traffic is routed to the gateway MAC.

With this change, each indoor unit is discovered and surfaced as an ordinary DeviceInfo, so it flows through the existing Discovery -> Device pipeline and can be controlled independently — no API changes are required for existing consumers, and downstream integrations (e.g. Home Assistant) get one device per indoor unit without any integration-side changes.

Closes the "multiple units behind a single Wi-Fi controller" request.

How it works

  1. During scan(), a gateway is identified by subCnt > 0 in its discovery response.
  2. The library binds to the gateway and sends a subList query, which returns the list of indoor units (each with its own internal MAC).
  3. Each indoor unit is emitted as a DeviceInfo carrying the gateway's key/cipher, so it binds by reusing the gateway session (no separate handshake).
  4. All status/command messages target the indoor unit by placing its MAC in the pack, while the packet is routed to the gateway MAC.

Changes

Protocol (network.py)

  • Add subList command/response and create_sublist_message.
  • Add handle_sublist_response; resolve the response type from a top-level t field (subList replies place it outside the pack).
  • Make the packet handler registry per-instance. A gateway, its sub-devices and any standalone units coexist as separate DeviceProtocol2 instances; the previous shared class-level dict cross-dispatched callbacks between them and broke bind/state handling once more than one device existed.

Device (device.py)

  • Add get_sub_devices() to enumerate a gateway's indoor units via subList.
  • bind() auto-inherits the gateway's key and cipher from DeviceInfo.
  • target_temperature: tolerate a missing / None / "" TemRec. Sub-devices and command acknowledgements omit the 0.5° rounding bit; default it to 0 instead of dropping the whole setpoint.
  • Harden temperature/version parsing against non-numeric values reported by some gateways.

Discovery (discovery.py)

  • Parse subCnt; auto-query gateways for their sub-devices during scan().
  • Add an include_gateways flag (default False) so the gateway "shell" isn't surfaced as a device.

Device info (deviceinfo.py)

  • Add sub_count, plus gateway_key and gateway_cipher (the parent gateway's bound key and live cipher instance) so a sub-device reuses the session.

All new parameters are optional and keyword-only; existing callers are unaffected.

Tests

  • subList request/response at the protocol level.
  • Per-instance handler isolation (regression test for the shared-dict bug).
  • get_sub_devices() success and timeout paths.
  • Sub-device binding via explicit key and via gateway-inherited key/cipher.
  • Sub-device state updates.
  • target_temperature surviving a missing/None TemRec.
  • Discovery with subCnt parsing, gateway querying, and the include_gateways flag.

Notes

  • Verified end-to-end against real hardware: a 4-unit VRF gateway enumerates and controls each indoor unit independently, alongside a standalone AC on the network.
  • Home Assistant needs no code changes to benefit — only a greeclimate version bump in the integration's manifest.json once released.

@meirlo

meirlo commented Apr 16, 2026

Copy link
Copy Markdown
Author

@codecov

codecov Bot commented Apr 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.97959% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 96.57%. Comparing base (47b9850) to head (45b6fd5).
⚠️ Report is 22 commits behind head on master.

Files with missing lines Patch % Lines
greeclimate/device.py 97.77% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #148      +/-   ##
==========================================
+ Coverage   95.71%   96.57%   +0.85%     
==========================================
  Files           8        8              
  Lines         770      846      +76     
==========================================
+ Hits          737      817      +80     
+ Misses         33       29       -4     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@meirlo meirlo changed the title feat: Implement sub-device management and discovery features feat: gateway sub-device discovery (VRF / multi-split support) Jul 28, 2026
@meirlo

meirlo commented Jul 28, 2026

Copy link
Copy Markdown
Author

@cmroche when you have a moment, could you take a look at this PR? 🙏

This adds VRF / multi-split support (multiple indoor units behind a single Wi-Fi gateway), which a lot of people have been waiting for — it comes up regularly in issues and in the Home Assistant community.

A few things that should make review easier:

  • Additive and backward-compatible — all new parameters are optional and keyword-only, existing callers are unaffected.
  • Library-only — the Home Assistant integration needs no code changes; sub-devices flow through the existing Discovery -> Device pipeline as regular DeviceInfo objects. Once released, HA only needs a greeclimate version bump in its manifest.json.
  • Verified on real hardware — a 4-unit VRF gateway enumerates and controls each indoor unit independently, alongside a standalone AC on the same network.
  • Cleaned up — rebased on current master, squashed to a single focused commit, with tests covering the protocol, discovery, binding, and state handling.

Happy to make any changes you'd like. Thanks for maintaining this library!

Adds support for Gree gateway modules that front multiple indoor units
(VRF / multi-split systems). Each indoor unit is surfaced as a regular
DeviceInfo and flows through the existing Discovery -> Device pipeline, so
consumers get one device per indoor unit with no API changes required.

Protocol (network.py)
- Add subList command/response and create_sublist_message
- Add handle_sublist_response and resolve response type from a top-level
  't' field (subList replies place it outside the pack)
- Make the packet handler registry per-instance. A gateway, its sub-devices
  and any standalone units coexist as separate DeviceProtocol2 instances;
  a shared class-level dict cross-dispatched callbacks between them and
  broke bind/state handling.

Device (device.py)
- Add get_sub_devices() to enumerate a gateway's indoor units via subList
- bind() auto-inherits the gateway's key and cipher from DeviceInfo, so a
  sub-device binds without a separate handshake
- target_temperature: tolerate a missing/None/'' TemRec (sub-devices and
  command acknowledgements omit the 0.5-degree bit); default it to 0 instead
  of dropping the whole setpoint
- Harden temperature/version parsing against non-numeric values

Discovery (discovery.py)
- Parse subCnt; auto-query gateways for sub-devices during scan()
- Add include_gateways flag (default False) to hide the gateway shell

DeviceInfo (deviceinfo.py)
- Add sub_count, plus gateway_key and gateway_cipher (the parent gateway's
  bound key and live cipher instance) so a sub-device reuses the session

All new parameters are optional and keyword-only; existing callers are
unaffected.
@meirlo

meirlo commented Jul 28, 2026

Copy link
Copy Markdown
Author

Closes #101 (which contains the maintainer's own protocol notes for subCnt / subList and links the Home Assistant request home-assistant/core#122200).

Also relevant: #172 addresses mixed-case bindOk responses — this PR resolves the response type case-insensitively in _resolve_response_type, so it handles that casing too.

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.

1 participant