Skip to content

Commit 7ad6795

Browse files
committed
fix: isolate EVC second register segment; dynamic max from 0x64F
SolaX support (ticket 703158) confirmed the EVC holding registers are internally segmented: 0x600-0x650 is one segment, 0x660-0x66F another (mainly internal 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): reading 0x640 count 48 returns 0 for 0x668 (Max Charge Current), while an in-segment or single read returns the true value. Starting a new read block at 0x668 pins the segment boundary, so the 0x668/0x669 block never crosses it. That makes the block_size=32 workaround (introduced blind against this same symptom before the segmentation was known) unnecessary, so the plugin returns to the default 100. Both resulting holding blocks verified on the charger above against single-register reads. Support pointed to the documented register 0x64F (limit_current_allmode). Live testing shows it is the persistent maximum limit, not the setpoint: SolaXCloud writes the active setpoint through 0x668 (0x64F stays fixed at the device rating, and external writes to 0x64F are acknowledged but ignored), and the cloud UI caps its picker at the 0x64F value. The Max Charge Current entity therefore stays on 0x668 and now reads 0x64F as a readback sensor to cap its own slider the same way, via a new optional max_key field on number descriptions that dynamically overrides native_max_value from a sensor value, falling back to the static native_max_value when absent. The EVC plugin now publishes its firmware version (input 0x25, e.g. V1.18 -> 118) as hub.modbus_protocol_version, enabling the existing modbus_min/modbus_max gating for EV chargers. The per-phase charge power sensors use it: protocol V2.8 (SolaX EV Charger firmware V1.12 per the document's version matching table) added input registers 0x100-0x102 (ChargePowerA/B/C), so on firmware >= V1.12 the Charge Power (X1) and Charge Power L1/L2/L3 (X3) sensors read the new block under their existing names and keys, while older firmware keeps the legacy 0x8-0xA registers; the separate Alt entities are gone. If the firmware version cannot be read, only the legacy definitions load. Also adds a disabled-by-default diagnostic sensor for input register 0x107 Is_support_parallel (0xAA55 = parallel operation supported).
1 parent 36c01e0 commit 7ad6795

3 files changed

Lines changed: 287 additions & 32 deletions

File tree

custom_components/solax_modbus/const.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ class BaseModbusNumberEntityDescription(NumberEntityDescription):
390390
prevent_update: bool = False # if set to True, value will not be re-read/updated with each polling cycle;
391391
# update only when read value changes
392392
sensor_key: str | None = None # only specify this if corresponding sensor has a different key name
393+
max_key: str | None = None # key of a sensor whose value dynamically overrides native_max_value
393394
depends_on: list[str] | None = None # list of modbus register keys that must be read
394395
display_as_box: bool = True # display numbers as an input box (default); set False for a slider.
395396
suggested_display_precision: int | None = None

custom_components/solax_modbus/number.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,15 @@ def name(self) -> str:
184184
def unique_id(self) -> str | None:
185185
return f"{self._platform_name}_{self._key}"
186186

187+
@property
188+
def native_max_value(self) -> float:
189+
max_key = self.entity_description.max_key
190+
if max_key:
191+
value = self._hub.data.get(max_key)
192+
if value:
193+
return float(value)
194+
return self._attr_native_max_value
195+
187196
@property
188197
def native_value(self) -> float | None:
189198
descr = self.entity_description

0 commit comments

Comments
 (0)