Skip to content

X1 Hybrid Gen4: fix battery current sign, add Load power and Run Mode - #216

Open
bjorn-ioronksen wants to merge 1 commit into
squishykid:masterfrom
bjorn-ioronksen:x1-hybrid-gen4-battery-current-and-sensors
Open

X1 Hybrid Gen4: fix battery current sign, add Load power and Run Mode#216
bjorn-ioronksen wants to merge 1 commit into
squishykid:masterfrom
bjorn-ioronksen:x1-hybrid-gen4-battery-current-and-sensors

Conversation

@bjorn-ioronksen

Copy link
Copy Markdown
Contributor

What

For the X1HybridGen4 inverter (API type: 15):

  1. Fix battery current sign. Register 15 is signed, but it was decoded with div100 alone. On a discharging battery that produces a large positive number (I saw ~652 A). twoway_div100 gives the correct signed value.
  2. Add Load power (register 38, to_signed).
  3. Add Inverter Run Mode (register 10, raw enum, same table as X3HybridG4).

Why

My inverter (type: 15, ver: 3.019.01) reports battery current as 65316 while discharging ~250 W at ~115 V. div100653.16 A. twoway_div100to_signed(65316)/100-2.2 A, which matches battery power / battery voltage (-252 W / 114.9 V).

The two extra registers are useful and already validated by the fixtures.

Tests

  • Adds X1_HYBRID_GEN4_V_3_019_RESPONSE / _VALUES: a real ReadRealTimeData capture from a discharging type: 15 inverter (the case the sign bug affected). Serial fields sanitised.
  • Updates the two existing X1HybridGen4 expected-value dicts (X1_HYBRID_G4_VALUES, X1_HYBRID_G4_V_3_018_VALUES) with Load power and Inverter Run Mode. Battery current is unchanged for both (their raw values are small positives, so twoway_div100 == div100 there).
  • pytest: 191 passed, 135 skipped. flake8 clean.

Note

Inverter Run Mode reads 2 ("Normal") across all three fixtures; a maintainer with another type: 15 unit confirming register 10 would be welcome. A decoded text variant (like X3HybridG4's "Run mode text") could be added later.

Battery current (register 15) is a signed value. Decoding it with div100
alone reports a large positive number (~652 A) whenever the battery is
discharging; twoway_div100 gives the correct signed reading. Verified on a
type 15 inverter (ver 3.019.01) against battery power / battery voltage.

Also expose two registers this class was not decoding:
- Load power (register 38, to_signed)
- Inverter Run Mode (register 10), raw enum matching the X3 Hybrid G4
  run-mode table; reads 2 (Normal) across both existing X1 Hybrid Gen4
  fixtures and the new one.

Adds a ReadRealTimeData fixture from a discharging type 15 inverter (the
case the sign bug affected) and updates the two existing X1 Hybrid Gen4
expected-value dicts for the new sensors.
@bjorn-ioronksen
bjorn-ioronksen force-pushed the x1-hybrid-gen4-battery-current-and-sensors branch from 1b6d920 to 6016ffc Compare September 6, 2026 18:02
@bjorn-ioronksen

Copy link
Copy Markdown
Contributor Author

Heads up on CI: the black --check step also flags solax/inverter.py and solax/response_parser.py, which this PR doesn't touch. That's pre-existing: the workflow does pip install --upgrade black (unpinned), so it now pulls black 26.x whose 2026 stable style reformats those two files. It fails the same way on a clean master. My additions are formatted with current black. Happy to either pin black in the workflow or run black . as a separate commit here, whichever you prefer.

@bjorn-ioronksen
bjorn-ioronksen force-pushed the x1-hybrid-gen4-battery-current-and-sensors branch from f5584b1 to 6016ffc Compare September 6, 2026 18:05
@bjorn-ioronksen

Copy link
Copy Markdown
Contributor Author

Updated: reverted the black-reformat commit, this PR is now just the X1 Hybrid Gen4 change.

The CI failures on this branch are pre-existing, not from this PR. The workflow does pip install --upgrade for both black and pylint (unpinned), and the current versions flag existing code:

  • black --check wants to reformat solax/inverter.py and solax/response_parser.py (fails the same on a clean master)
  • pylint flags solax/response_parser.py:49 C0103 on GenericResponseSchema

My additions pass black, isort, flake8, mypy and pylint locally. Pinning the linters in the workflow would make CI meaningful again; happy to do that as a separate PR if useful.

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