Skip to content

feature: Growatt WIT support via solax_modbus — likely already works in VPP mode, needs validation + wiring #632

Description

@johanzander

Overview

Support the Growatt WIT hybrid series (WIT 4-15kW / 8000-HU / 12000-HU / 15K-HU / 100000-HU) through the wills106/homeassistant-solax-modbus integration, reusing the existing solax_modbus_growatt_min (GEN4) platform.

User-visible outcome: a user with a Growatt WIT installs solax_modbus, runs the BESS setup wizard, sees "Growatt MIN/GEN4" light up green with sensors auto-mapped, and gets a working optimized schedule — no manual sensor mapping, no cloud integration.

Reported by @tissson in #627, where a WIT was misdetected as growatt_server_sph via the cloud integration.

Background — what #627 showed

The reporter's WIT has no working control path today:

  • The official growatt_server cloud entry exposes only a plant-level device ("Malax Total"), so BESS's device resolution picks that, and every growatt_server.read_ac_charge_times call returns 500.
  • Detection is elimination-based (ha_api_controller.py:3118-3131): no -tlx_ marker → assume SPH. WIT never enters the logic.
  • His actual WIT entities come from a third-party HACS integration, 0xAHA/Growatt_ModbusTCP (domain growatt_modbus), which BESS knows nothing about. He mapped all sensors by hand.

What is already true today (verified, not assumed)

solax_modbus classifies WIT as GEN4plugin_growatt.py:9703-9707:

    # WIT
    "0PE": HYBRID | GEN4 | X3,  # WIT 8000-HU, 2 MPPT
    "0PC": HYBRID | GEN4 | X3,  # WIT 12000-HU, 2 MPPT
    "0PH": HYBRID | GEN4 | X3 | MPPT10,  # WIT 100000-HU, 10 MPPT
    "0HU": HYBRID | GEN4 | X3,  # WIT 15K-HU, 2 MPPT

Every entity in SOLAX_GROWATT_MIN_SUFFIX_MAP is reachable by a WIT. Each of the 31 mapped keys was resolved to its allowedtypes in plugin_growatt.py. All are gated on GEN4/HYBRID with no X1/X3 constraint, and the only serial blacklist in the plugin is SPF_SINGLE_MPPT_SERIAL_PREFIXES (SPF only). A HYBRID | GEN4 | X3 WIT satisfies all of them:

BESS map group allowedtypes in plugin
battery_soc, battery_charge_power, battery_discharge_power GEN4 | HYBRID
total_forward_power, total_reverse_power, total_load_power, total_yield GEN4
lifetime energy counters GEN4 / GEN4 | HYBRID
ems_charging_rate, ems_discharging_rate, ems_*_stop_soc HYBRID | GEN4
charger_switch HYBRID | AC | GEN4
vpp_status, vpp_remote_control, vpp_power, vpp_time, vpp_allow_ac_charging GEN3 | GEN4
limit_grid_export, grid_export_limit GEN2 | GEN3 | GEN4
time_1..9_{enabled,begin,end,mode,update} HYBRID | GEN4

So detection already fires. _GROWATT_TOU_MARKER_SUFFIX = "time_1_enabled" (ha_api_controller.py:3801) is created for any HYBRID | GEN4 inverter, so a WIT on solax_modbus is detected as solax_modbus_growatt_min with no code change — sensors mapped, wizard pill green.

And BESS already has the control mode WIT most likely needs. SolaxModbusGrowattController supports both tou and vpp, and the Growatt VPP path (registers 30100 / 30407-30410) landed for #118. GEN4 currently defaults to tou (battery_system_manager.py:_resolve_control_mode).

The open question this issue exists to answer

Does WIT honour the GEN4 numbered-TOU registers, or is VPP the only working write path?

Evidence that TOU may be a dead end on WIT — from the other integration's WIT profile (0xAHA/Growatt_ModbusTCP, profiles/wit.py):

- Register 30476 (priority_mode) is READ-ONLY - shows TOU default, cannot be changed via Modbus

That integration drives WIT entirely through work_mode (register 202: 0 Standby / 1 Charge / 2 Discharge) plus a remote charge/discharge power rate, gated by control_authority (register 30100) — a continuous VPP-style command model, and it re-asserts work_mode before every power-rate write.

Register 30100 is the same vpp_status register BESS already writes in VPP mode. So the likely answer is: WIT works today on solax_modbus_growatt_min with control_mode: vpp, and TOU mode silently no-ops.

This cannot be settled from source. It needs one user with a WIT and solax_modbus installed.

Proposed work

Phase 1 — validate (blocking, needs hardware). Ask a WIT owner to install solax_modbus alongside their existing setup and report:

  1. Does the wizard show "Growatt MIN/GEN4" detected, with sensors auto-populated?
  2. In control_mode: tou — does a TOU slot write actually change inverter behaviour, or is it accepted and ignored?
  3. In control_mode: vpp — does a charge and a discharge command take effect?

Phase 2 — wire the outcome. Depending on Phase 1:

  • VPP works, TOU doesn't (expected): make WIT resolve to vpp rather than the GEN4 tou default. WIT is not distinguishable from a MIN by entity shape alone — both are HYBRID | GEN4 — so this needs a positive signal (serial prefix 0PE/0PC/0PH/0HU via the device/serial, or an explicit user choice). Options to weigh: a WIT-specific platform id, or keeping solax_modbus_growatt_min and steering only the control-mode default.
  • Both work: documentation only.
  • Neither works: close this and reopen on the growatt_modbus path (below).

Phase 3 — document. WIT in the supported-hardware table at the correct maturity level (experimental until a real install is confirmed), plus a wizard note that WIT needs solax_modbus rather than the cloud integration.

Explicitly out of scope

Adding a growatt_modbus platform for 0xAHA/Growatt_ModbusTCP. It's a real option — it has a dedicated wit.py profile, per-model register maps, and a VPP control surface close to what BESS already drives (number.growatt_battery_remote_charge_and_discharge_power, select.growatt_battery_mode_vpp, select.growatt_grid_control_authority, number.growatt_tou_active_periods, select.growatt_work_mode) — and #627's bundle already gives the full entity vocabulary. But it is a third integration to support, and solax_modbus is the path already built. File separately if Phase 1 rules solax_modbus out.

Also out of scope: fixing the growatt_server elimination-based detection that misfires on WIT (has_tlx → SPH). That's a bug, tracked from #627.

Acceptance criteria

  • A WIT on solax_modbus is auto-detected by the wizard with sensors mapped, no manual entry.
  • Charge and discharge commands are confirmed to take effect on real WIT hardware (log + inverter state).
  • The platform's control mode is resolved correctly for WIT without the user having to know which register family their inverter honours.
  • Supported-hardware docs list WIT with an accurate maturity level.

Definition of Ready

Fails criterion 4 (approach agreed) and criterion 2 (reproduction) — Awaiting: user/hardware. Phase 1's answer decides Phase 2's design; the fork is stated above so a later attempt doesn't rediscover it. Nobody on the team has WIT hardware.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions