Skip to content

Commit 182894c

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.
1 parent 36c01e0 commit 182894c

3 files changed

Lines changed: 21 additions & 1 deletion

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

custom_components/solax_modbus/plugin_solax_ev_charger.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ def value_function_sync_rtc_evc(initval: Any, descr: Any, datadict: dict[str, An
322322
fmt="f",
323323
native_min_value=6,
324324
native_max_value=32,
325+
max_key="max_charge_current_limit",
325326
native_step=0.1,
326327
scale=0.01,
327328
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
@@ -737,10 +738,19 @@ def value_function_sync_rtc_evc(initval: Any, descr: Any, datadict: dict[str, An
737738
},
738739
internal=True,
739740
),
741+
SolaXEVChargerModbusSensorEntityDescription(
742+
name="Max Charge Current Limit",
743+
key="max_charge_current_limit",
744+
register=0x64F,
745+
scale=0.01,
746+
rounding=1,
747+
internal=True,
748+
),
740749
SolaXEVChargerModbusSensorEntityDescription(
741750
name="Max Charge Current",
742751
key="max_charge_current",
743752
register=0x668,
753+
newblock=True,
744754
scale=0.01,
745755
rounding=1,
746756
internal=True,
@@ -1764,7 +1774,7 @@ def getHardwareVersion(self, new_data: dict[str, Any]) -> str | None:
17641774
),
17651775
],
17661776
TIME_TYPES=TIME_TYPES,
1767-
block_size=32,
1777+
block_size=100,
17681778
# order16=Endian.BIG,
17691779
order32="little",
17701780
)

0 commit comments

Comments
 (0)