EVC: fix segmented-register reads (vendor-confirmed); firmware-version gating; doc-aligned entities - #2275
Draft
Bl00d-B0b wants to merge 2 commits into
Draft
Conversation
Bl00d-B0b
force-pushed
the
fix/evc-max-current-documented-register
branch
3 times, most recently
from
August 11, 2026 07:26
e2f9c3b to
182894c
Compare
Bl00d-B0b
force-pushed
the
fix/evc-max-current-documented-register
branch
25 times, most recently
from
August 11, 2026 13:28
9252618 to
7ad6795
Compare
Bl00d-B0b
force-pushed
the
fix/evc-max-current-documented-register
branch
2 times, most recently
from
August 12, 2026 11:49
017344a to
8b4a6fa
Compare
Bl00d-B0b
marked this pull request as ready for review
August 12, 2026 14:23
Bl00d-B0b
force-pushed
the
fix/evc-max-current-documented-register
branch
from
August 13, 2026 10:05
8b4a6fa to
5c697da
Compare
Bl00d-B0b
marked this pull request as draft
August 13, 2026 10:12
Bl00d-B0b
force-pushed
the
fix/evc-max-current-documented-register
branch
7 times, most recently
from
August 13, 2026 11:16
ebdcf9f to
a9d72f3
Compare
Bl00d-B0b
force-pushed
the
fix/evc-max-current-documented-register
branch
15 times, most recently
from
August 13, 2026 14:19
83107eb to
6ff3b77
Compare
…ptions dialog
Energy Dashboard: the refresh only marked sensors inactive when a feature
switch was turned off - the entity stayed alive and its registry entry was
never removed, so the device accumulated sensors stuck at unavailable
(grid-to-battery, home-consumption and PV-variant sensors). They are now
removed and their registry entries purged.
Generic sub-device infrastructure, used by follow-up PRs that move the
EPS, Parallel, External Generator and Dry Contact families into their own
devices: entity descriptions gain device_group (assigns the entity to a
named sub-device linked to the inverter with via_device, the same pattern
as the battery pack devices) and active_when ({sensor_key: allowed values}
evaluated against polled hub.data; keys not polled on a model never block
availability). The hub tracks gated entities and adds or removes them as
conditions change, with a two-poll hysteresis so a stale readback right
after a write cannot make entities flicker. A sub-device whose option is
switched off is removed from the registry instead of lingering. Switch and
number writes publish the written value immediately, as selects and times
already did. Numbers gain max_key, letting a sensor value override
native_max_value. The number, select, switch, time and sensor platforms
honour all of it. No entities move in this PR.
The options dialog no longer shows feature switches the selected plugin
does not implement, and all feature options now default to off for new
entries, including the Energy Dashboard virtual device.
…entities SolaX support (ticket 703158) confirmed the EVC holding registers are internally segmented: 0x600-0x650 is one segment, 0x660-0x66F another (used for master-slave parallel operation). A function 0x03 read that spans the boundary silently returns 0 for second-segment registers. Reproduced on an X3-EVC-11kW Gen1 (ARM V1.18). Fixed by starting a new read block at 0x668 and restoring the default block_size 100 (the block_size=32 workaround predating this knowledge is no longer needed). The plugin now publishes its firmware version (input 0x25, e.g. V1.18 -> 118) as hub.modbus_protocol_version, enabling modbus_min/ modbus_max gating for EV chargers. Entities on registers dated by the protocol document's revision history are gated accordingly, and every register pair that changed location across firmware versions is exposed as a single entity identity whose backing register follows the firmware: Charge Power 0x08-0x0A -> 0x100-0x102, Run Mode 0x1D -> 0x106, Charge Phase 0x625 -> 0x63B, Charge Mode (0x104 sensor on V1.12-13, 0x641 select from V1.14, 0x669 select on GEN2). The Alt-suffixed duplicate entities are gone. Support suggested using the documented 0x64F (limit_current_allmode) for the maximum current. Live testing shows it is the persistent device limit rather than the setpoint (SolaXCloud itself writes 0x668; external writes to 0x64F are acknowledged but ignored), so Max Charge Current stays on 0x668 and a new optional max_key field on number descriptions caps the Max/Min Charge Current sliders dynamically from the 0x64F readback. New doc-based entities (disabled by default unless noted): Unbalanced Power 0x63C and Unbalanced Switch 0x63D (X3), Mode Button 0x63E, Min Charge Current 0x63F, Datahub Charge Power 0x643, Green 30s Delay 0x644 (switch), Parallel Support 0x107, WiFi S/N 0x607, Customized S/N 0x629. Alignments: Overload Limit renamed Overvoltage Limit (doc OverVoltSet), Charger Type name unified across GEN1/GEN2, RSSI renamed WiFi RSSI, per-phase Charge Current sensors consistently disabled by default, Datahub Charge Current disabled by default, charge_added_cum GEN2 scope narrowed from GEN2|GEN3|GEN4. Input 0x2D/0x2E are marked in code as conflicting between the Gen1 V3.5 and GEN2 documents (clarification requested from SolaX). Register 0x642 Parallel_enable is deliberately not exposed: the device returns values outside the documented 0/1 range and SolaXCloud's parallel toggle does not use it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
SolaX support (ticket 703158, replying to my bug report about
MaxChargeCurrentreading 0) disclosed that the EVC holding registers are internally segmented:0x600-0x650is one segment and0x660-0x66Fanother (used for internal master-slave parallel operation). A function 0x03 read spanning the boundary silently returns 0 for second-segment registers.Reproduced on an X3-EVC-11kW Gen1 (serial C31103I9612443, ARM V1.18):
Everything below was verified on that charger over Modbus TCP, and the register semantics were confirmed with SolaX support.
Segmentation fix
newblock=Trueon the Max Charge Current readback pins the read-block boundary at0x668, so no read can cross the segment boundary.block_sizereturns from 32 to the default 100 - the 32 was a blind workaround for this same symptom (fix(solax): unify firmware version display and key naming across all inverter types #2064), added before the segmentation was known. Both resulting holding blocks and the input blocks were verified against single-register reads.Firmware-version gating
The plugin now reads its firmware version once at startup (input
0x25, e.g. V1.18 -> 118) and publishes it ashub.modbus_protocol_version, activating the existingmodbus_min/modbus_maxmachinery for EV chargers. Thresholds come from the protocol document's revision history and its protocol-to-firmware matching table.Every register that moved across firmware versions is now one entity identity whose backing register follows the firmware - the Alt-suffixed duplicates are gone:
0x08-0x0A(<= V1.11)0x100-0x102(>= V1.12)0x1D(<= V1.11)0x106(>= V1.12)0x625(<= V1.10)0x63B(>= V1.11)0x104sensor (V1.12-V1.13)0x641select (>= V1.14);0x669select on GEN2Other dated entities (
control_command,charge_current, the boost family,modbus_address, the0x100input block) carry matchingmodbus_mingates. Unknown firmware falls back to the legacy definitions.Max charge current
Support suggested using the documented
0x64F(limit_current_allmode) for the maximum current, and clarified its behaviour: 0x64F is the Modbus-dedicated current setting - writes only take effect while a vehicle is connected, and it reverts to the charger's rated maximum when the gun is unplugged, whereas the value written from SolaXCloud is the persistent setpoint in0x668. (Our earlier write tests to 0x64F appeared to be ignored because they were all performed with no vehicle connected.) Support also confirmed that the charger caps the actual charging current at its rated value regardless of what is written to0x668.Accordingly:
0x668, the persistent setpoint SolaXCloud itself writes;max_keyfield on number descriptions dynamically overridesnative_max_valuefrom a sensor value. It is fed by the charger's rated current, derived fromTypePower(0x21) andTypePhase(0x22) - 11 kW three-phase gives 16 A - so the slider ceiling matches the hardware and never follows a dynamic setpoint. It falls back to the static maximum if those registers cannot be read.Parallel entities
SolaX support provided the Gen1 meaning of
0x0642, which the document still describes as an on/off enable: 0 = Master, 1 = Slave, 2 = Parallel operation with Gen2 chargers. It is exposed as a **Parallel Role is a read-only diagnostic sensor: live testing showed writes are accepted but an internal sync re-asserts the stored value after 10–15 seconds, so a writable control would silently revert.Both appear only on chargers that actually support parallel operation: the type detection probes
0x0107at startup and sets aPARALLEL_TYPEfeature flag, the same pattern the plugin already uses for OCPP detection via0x0023.Other doc-based entities and alignments
New (disabled by default unless noted): Unbalanced Power
0x63C+ Unbalanced Switch0x63D(X3, >= V1.11), Mode Button0x63Eand Min Charge Current0x63F(>= V1.12), Datahub Charge Power0x643and Green 30s Delay switch0x644(>= V1.14), and the string diagnostics Serial Number0x600, WiFi S/N0x607, Customized S/N0x629(standardREGISTER_STRsensors; the startup serial read used for model detection is unchanged).Alignments: Overload Limit renamed Overvoltage Limit (doc:
OverVoltSet, 1 V); Charger Type name unified across GEN1/GEN2 (options stay per-generation); RSSI renamed WiFi RSSI; per-phase Charge Current sensors and Datahub Charge Current consistently disabled by default;charge_added_cumsecond definition narrowed fromGEN2 | GEN3 | GEN4toGEN2(no GEN3/GEN4 EVC exists or is detected); the X1 measured-current diagnostic (input0x4) renamed keycharge_current->charge_current_measured, which previously collided with the setpoint readback and made the Charge Current number flicker between setpoint and measurement.Input
0x2D–0x30(Lock State, Main Breaker Limit State, Random Delay State, Ban State) are gated to second-generation chargers: SolaX support confirmed these registers do not exist on Gen1 and will be removed from the Gen1 protocol document.Platform fixes
Modbus switches and numbers now publish the accepted value locally after a successful write, instead of waiting for the next readback poll. Without this the entity keeps reporting the previous value until the register is polled again, which shows up as a switch flipping back or a slider snapping back for one cycle.