v0.9.1 - Multiple fixes
Release Notes
v0.9.1
Issues: #299, #302, #303, #304, #305, #306, #307, #313
⚠️ BREAKING CHANGE — affects all users.Grid Export PowerandGrid Import Powerhave had their values swapped in all previous versions. After upgrading, each will read the opposite direction to before. Swap any automations, dashboard cards, or Energy Dashboard slots that reference either sensor. Users with Invert Grid Power enabled should also disable it (Settings → Devices & Services → Growatt Modbus → Configure) — it was incorrectly enabled by the setup wizard's auto-detection in previous versions.
New profiles:
-
Growatt 3000–15000TL3-S (Issue #299):
Added support for the TL3-S three-phase grid-tied string inverter (3–15 kW, legacy protocol).
Register layout confirmed from a full device scan: PV inputs at regs 3–8, total AC power at reg 12,
per-phase output (R/S/T) at regs 16–25, temperature at reg 32, and energy at regs 53/55 (×0.1 kWh).
Auto-detected via DTC 2049 at holding register 43. No VPP support — holding register 30000 returns
Illegal Function. Note: regs 9–10 contain firmware version bytes (not PV2 power); use the
Total PV Power sensor rather than PV2 Power. -
MIC 2500–5500MTL-S (Issue #304):
Added support for the MIC 2500–5500MTL-S single-phase dual-string grid-tied inverter family
(2.5–5.5 kW, legacy V3.05 protocol). Inherits the MIC 600–3300TL-X register map with a second
PV string confirmed at regs 7–8. Auto-detected via DTC 210. Note: this inverter rejects any
Modbus read of more than one register at a time — themax_block_size: 1mode introduced in
this release handles this automatically for all sensor reads. -
MID Hybrid (11–30kW) (Issue #313 / PR #314):
MID 11–30KTL3-XH and MID 8–15KTL3-XHL/JP share DTC 5400 with MOD 3–10KTL3-XH and use identical
register layouts. A named manual-selection option ("MID Hybrid (11–30kW)") is now available in the
profile dropdown for MID users who prefer the MID label. Auto-detection continues to route DTC 5400
to the MOD Hybrid profile, preserving entity IDs for existing users.
Fixes:
-
Breaking fix:
grid_export_powerandgrid_import_powerswapped on all profiles (Issue #302):
Both always-positive derived power sensors had inverted formulas in all previous versions.
On hybrid profiles (SPH, MOD, WIT) the symptom was visible: during grid import,
grid_export_powershowed the import magnitude whilegrid_import_powerread zero.
On grid-tied string inverters (MIN, MIC, MID),grid_export_powersilently read zero and
grid_import_powercarried the export value under the wrong name.
The signedgrid_powersensor and all daily energy sensors were unaffected.
Also fixes the setup wizard's grid orientation detection, which was enabling Invert Grid Power
for the wrong case — inverting when it should not, and not inverting when it should. -
Fix: MIC 2500–5500MTL-S entities all unavailable (Issue #304):
The inverter rejects any Modbus read of more than one register at a time
(ExceptionResponse FC=132, exception_code=1 — Illegal Function for any block read).
Fixed by adding per-profilemax_block_sizesupport to the coordinator. When a profile
setsmax_block_size: 1, the coordinator switches to sparse read mode: only the specific
register addresses defined in the profile are read, grouped into consecutive runs of at most
1 register, skipping all gaps. This eliminates unnecessary reads for undefined registers.
All other profiles continue to use the original dense 125-register block reads unchanged. -
Fix: Inverter Status shows wrong text on hybrid inverters (Issue #305):
The status sensor was using a single status code table shared across all inverter families.
Hybrid inverters (SPH, SPM, MOD, WIT, MIN TL-XH, SPA, SPE) use the VPP Protocol V2.01
status map where codes have completely different meanings to the grid-tied map — most critically,
code 5 was shown as "Standby" when the correct label is "PV On-Grid", and code 1 was shown as
"Normal" when it means "Self-Test" on hybrid models. SPF off-grid inverters have their own
distinct status set which was also mixed into the same dict.
Fixed by introducing three separate status code tables (STATUS_CODESfor grid-tied,
HYBRID_STATUS_CODESfor hybrid,SPF_STATUS_CODESfor off-grid) and selecting the correct
table at runtime based on the active profile.Code Grid-tied Hybrid SPF Off-Grid 0 Waiting Waiting Standby 1 Normal Self-Test — 2 — Reserved Discharge 3 Fault Fault Fault 4 — Updating Bypass 5 — PV On-Grid PV Charge 6 — Bat On-Grid Combined Charge 7 — PV+Bat Off-Grid — 8 — Bat Off-Grid — 9 — Bypass — -
Fix: SPH/SPM 8000–10000TL-HU auto-detection fails (Issue #303):
DTC code 21303, which identifies the SPH/SPM 8000–10000TL-HU running firmware UL2.21,
was not in the DTC map. Detection fell through to the legacy register-probing path, which could
misidentify the high-PV-voltage SPH HU as a MIC micro inverter. On the MIC profile, all battery
and grid registers are absent, so every power-flow derived sensor was computed from solar
generation alone. Fixed by mapping DTC 21303 →sph_8000_10000_hu. -
Fix:
house_consumptionreturns solar generation on SPH/SPM HU (Issue #303):
Two related issues causedhouse_consumptionto equal solar on HU firmware UL2.21.
First, the HU variant does not populatepower_to_load(register 1021/1022).
Second, the fallback attemptedself_consumption_power(register 1037/1038), which on UL2.21
reports solar-only self-consumption rather than total house load.
Fixed by removing the intermediate step: whenpower_to_loadis absent the integration now
goes directly to the full energy balance
(solar + battery_discharge − battery_charge + grid_import − grid_export)
using the direct grid registers (1015/1016 and 1029/1030), which are correct on UL2.21. -
Fix: Remote Charge/Discharge Power slider rejects negative values (Issue #306):
Register 30409 (remote_charge_and_discharge_power) accepts −100% (full discharge) to +100%
(full charge). Negative values must be sent as unsigned 16-bit two's complement over Modbus
(e.g. −80 → 65456 / 0xFFB0). The code was passing the raw negative Python integer directly to
pymodbus, which expects an unsigned 16-bit value and raises a struct error. Positive values
worked because no conversion was needed.
Fixed by converting signed values to unsigned 16-bit (value & 0xFFFF) inwrite_register
before the pymodbus call. The read-back verification comparison inwrite_register_verified
is also updated to compare against the unsigned representation. -
Fix:
energy_todayrises through the night on SPH hybrid inverters (Issue #307):
The hardware register forenergy_today(reg 53/54) on SPH/WIT hybrid inverters counts total
AC system output, including battery discharge — not solar generation only. The integration
normally avoids this by summing the per-MPPT DC string registers (pv1_energy_today + pv2_energy_today), which track PV input only. However, the guard condition checked
pv*_energy_today > 0. After the inverter's daily counters reset to zero at midnight, all MPPT
values return 0, the guard evaluatedFalse, and the code fell back to register 53/54 — which
then climbed through the night at a rate matching house load (battery powering the house).
Fixed by gating on register address existence rather than value > 0. If the profile defines
per-MPPT energy registers (which all SPH/WIT profiles do), the MPPT sum is always used —
including when it is zero. Zero at night is the correct value. -
Fix: MID 15–25kW PV3 missing from base profile (Issue #313):
The baseMID_15000_25000TL3_Xprofile was missing PV3 registers 11–14. PV3 was previously
only available on the V2.01 variant via VPP registers 31018–31021. Base register availability
confirmed from the Issue #313 scan. MID models with a third MPPT string will now show
pv3_voltage,pv3_current, andpv3_poweron both base and V2.01 profiles. -
Docs: corrected legacy storage register 1000 (uwSysWorkMode) status description:
Previously showed0x05-0x08=Normal. Updated to list each code individually, matching the
VPP Protocol V2.01 register 31000 definition.
v0.9.1b6
Issues: #307
-
Fix:
energy_todayrises through the night on SPH hybrid inverters (Issue #307):
On SPH (and WIT) hybrid inverters the hardware register forenergy_today(reg 53/54)
counts total AC system output, including battery discharge — not solar generation only.
The integration normally avoids this by summing the per-MPPT DC string registers
(pv1_energy_today + pv2_energy_today), which track PV input only.However, the guard condition checked
pv*_energy_today > 0before using the MPPT sum.
After the inverter's daily energy counters reset to zero at midnight, all MPPT values
return 0, the guard evaluatedFalse, and the code fell back to register 53/54 — which
then climbed through the night at a rate matching house load (battery powering the house).Fixed by gating on register address existence rather than value > 0. If the profile
defines per-MPPT energy registers (which all SPH/WIT profiles do), the MPPT sum is always
used — including when it is zero. Zero at night is the correct value.
v0.9.1b5
-
Fix: Remote Charge/Discharge Power cannot be set to negative values (Issue #306):
Register 30409 (remote_charge_and_discharge_power) accepts values from −100% (full discharge)
to +100% (full charge). Writing a negative value requires sending the unsigned 16-bit
two's complement representation over Modbus (e.g. −80 → 65456 / 0xFFB0). The code was
passing the raw negative Python integer directly to pymodbus, which expects an unsigned
16-bit value and raises a struct error. Positive values worked because no conversion was
needed.Fixed by converting signed values to unsigned 16-bit (
value & 0xFFFF) inwrite_register
before the pymodbus call. The read-back verification comparison inwrite_register_verified
is also updated to compare against the unsigned representation, so positive write + verified
confirmation is correctly reported. -
Fix: SPH/SPM 8000-10000TL-HU auto-detection fails (DTC 21303 unmapped, Issue #303):
DTC code 21303, which identifies the SPH/SPM 8000–10000TL-HU running firmware UL2.21,
was not in the DTC map. The detection logic could fall through to the legacy register
probing path, which may identify a high-PV-voltage SPH as a MIC micro inverter. On the
MIC profile, all battery and grid registers are absent, so every power-flow derived sensor
(Grid Export Power,Grid Import Power,House Consumption) was computed from solar
generation alone.Fixed by adding
21303 → sph_8000_10000_huto the DTC map. Detection now resolves at
Step 1 (OffGrid DTC) and reaches the correct profile without reaching the register-probing
fallback. -
Fix:
house_consumptionreturns solar on SPH HU regardless of energy balance (Issue #303):
Register 1037/1038 (self_consumption_power) on HU firmware UL2.21 reports solar-only
self-consumption, not total house load. The previous code used it as a direct house load
proxy whenpower_to_load(register 1021/1022) was zero, causinghouse_consumptionto
equal solar in most operating conditions. The energy balance
(solar + discharge − charge + import − export) was never reached.Fixed by removing the
self_consumption_powerintermediate step. Whenpower_to_load = 0,
the integration now goes directly to the energy balance using the direct grid import/export
registers (1015/1016 and 1029/1030), which are correct on UL2.21.
v0.9.1b4
Issues: #305
-
Fix: Inverter Status shows wrong text on hybrid inverters (Issue #305):
TheInverter Statussensor was using a single status code table shared across all inverter
families. Hybrid inverters (SPH, SPM, MOD, WIT, MIN TL-XH, SPA, SPE) use the V1.39 / VPP
Protocol V2.01 status map where the codes have completely different meanings to the grid-tied
map — most critically, code 5 was shown as "Standby" when the correct label is "PV On-Grid",
and code 1 was shown as "Normal" when it means "Self-Test" on hybrid models. SPF off-grid
inverters have their own distinct status set (0=Standby, 2=Discharge, 5=PV Charge, etc.)
which was previously mixed into the same dict and would now also collide.Fixed by introducing three separate status code tables (
STATUS_CODESfor grid-tied,
HYBRID_STATUS_CODESfor hybrid,SPF_STATUS_CODESfor off-grid) and selecting the correct
table at runtime based on the active profile. Hybrid status codes are now:Code Label 0 Waiting 1 Self-Test 2 Reserved 3 Fault 4 Updating 5 PV On-Grid 6 Bat On-Grid 7 PV+Bat Off-Grid 8 Bat Off-Grid 9 Bypass -
Docs: corrected legacy storage register 1000 (uwSysWorkMode) status description:
The protocol-v139 reference table previously showed0x05-0x08=Normalfor register 1000.
Updated to list each code individually, matching the VPP Protocol V2.01 register 31000
definition which was already correct in the docs.
v0.9.1b3
Issues: #304
- Fix: MIC 2500-5500MTL-S entities all unavailable (Issue #304):
The inverter rejects Modbus reads of more than one register at a time (responds with
ExceptionResponse FC=132, exception_code=1 — Illegal Function for any block read).
Fixed by adding per-profilemax_block_sizesupport to the coordinator. When a profile
setsmax_block_size: 1, the coordinator switches to sparse read mode: it reads only the
specific register addresses defined in the profile, grouped into consecutive runs of at most
max_block_sizeregisters, skipping all gaps. This also eliminates unnecessary register reads
for registers not defined in the profile. All other profiles continue to use the original
dense read mode (contiguous 125-register block reads) unchanged.
v0.9.1b2
-
New profile: Growatt 3000-15000TL3-S (Issue #299):
Added support for the TL3-S three-phase grid-tied string inverter (3–15 kW, legacy protocol).
Register layout confirmed from a full device scan: PV inputs at regs 3–8 (PV1 voltage/current/power
and PV2 voltage/current), total AC power at reg 12, per-phase output (R/S/T) at regs 16–25,
temperature at reg 32, and energy at standalone regs 53/55 (×0.1 kWh). Auto-detected via DTC 2049
at holding register 43. No VPP support — holding register 30000 returns Illegal Function.
Note: regs 9–10 contain firmware version bytes (not PV2 power), so PV2 power stays 0; use the
Total PV Power sensor instead. -
Fix:
house_consumptionmirrors solar on SPM 8000TL-HU (Issue #303):
The HU variant of the SPH family does not populatepower_to_loadorpower_to_userregisters,
causinghouse_consumptionto collapse to solar power when both are zero (the simpleload = solar
fallback). Fixed with a full energy balance fallback: when battery or grid data is present,
house_consumption = solar + battery_discharge − battery_charge + grid_import − grid_export.
With the HU test case (solar 2389 W, import 2801 W, discharge 501 W) this now correctly
computes ≈ 5691 W instead of 2389 W. -
New profile: MIC 2500-5500MTL-S (Issue #304):
Added support for the MIC 2500–5500MTL-S single-phase dual-string grid-tied inverter family
(2.5–5.5 kW, legacy V3.05 protocol). Inherits the MIC 600–3300TL-X register map with PV2
voltage and current confirmed at regs 7–8. PV2 power pair at regs 9–10 is included but
unconfirmed — if the PV2 Power sensor shows an unrealistic value, those registers contain
firmware version bytes and should be reported via the issue tracker.
Auto-detected via DTC 210 at holding register 43. Note: this inverter rejects multi-register
Modbus block reads — useblock_size=1with the Universal Scanner service.
v0.9.1b1
Issues: #302
We apologise for this one. The Grid Export Power and Grid Import Power sensors have had
their values swapped since they were introduced, meaning every user has been seeing export
labelled as import and vice versa. The bug was in the formula that splits the signed grid power
value into its two always-positive halves — the positive and negative parts were extracted into
the wrong sensors. The signed Grid Power sensor and all daily energy sensors were unaffected
because they use a different code path. We only caught it because a user noticed the symptom
on a hybrid inverter where both directions are active (Issue #302). Grid-tied string inverter
users (MIN, MID, MIC) were also affected but the symptom was less obvious — those inverters
only export during the day, so Grid Export Power silently read zero while Grid Import Power
carried the export value. Both are now correct.
⚠️ BREAKING CHANGE — affects all users.
Grid Export PowerandGrid Import Powerwere swapped in all previous versions.
After upgrading, these sensors will read the opposite value to before.
If you have automations, dashboards, or energy dashboard slots referencing either sensor,
you must swap them. The signedGrid Powersensor and all daily energy sensors are unaffected.
Users with Invert Grid Power enabled should also disable it (Settings → Devices &
Services → Growatt Modbus → Configure) — it was incorrectly set by auto-detection in
previous versions and is no longer needed for standard inverters.
-
Breaking fix:
grid_export_powerandgrid_import_powerswapped on all profiles (Issue #302):
The two always-positive derived power sensors had their formulas inverted in all previous
versions.grid_export_powerwas extracting the import portion of the signed grid power
value andgrid_import_powerwas extracting the export portion — the opposite of their names.
On hybrid profiles (SPH, MOD, WIT) the symptom was visible: during grid import,
grid_export_powershowed the import magnitude whilegrid_import_powerread zero. On
grid-tied string inverters (MIN, MIC, MID) the inverter only exports, sogrid_export_power
silently read zero andgrid_import_powershowed the export value under the wrong name.
The signedgrid_powersensor and the daily energy sensors (Energy to Grid Today,
Grid Import Energy Today) were unaffected — they read from separate register addresses. -
Fix:
invert_grid_powerauto-detection was inverting the wrong case:
The setup wizard's grid orientation detection returned the wrong result — it enabled inversion
when it detected positive = export (the correct convention) and disabled it when it detected
negative = export (the case that actually needs correction). This caused some users to have
invert_grid_powerincorrectly set to True, which negated the signedgrid_powersensor
so it showed negative while exporting. Auto-detection is now correct. Existing users with
the flag incorrectly enabled should disable it via Configure.