Skip to content

Varta Modbus - active bat control#3516

Open
ndrsnhs wants to merge 11 commits into
openWB:masterfrom
ndrsnhs:varta-active-bat-control
Open

Varta Modbus - active bat control#3516
ndrsnhs wants to merge 11 commits into
openWB:masterfrom
ndrsnhs:varta-active-bat-control

Conversation

@ndrsnhs

@ndrsnhs ndrsnhs commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Aktive Batteriesteuerung für Varta über Modbus

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds active battery control support for Varta batteries via Modbus by extending the Varta Modbus battery component with a set_power_limit() implementation and related state/logging changes.

Changes:

  • Add set_power_limit() / power_limit_controllable() to enable active control via Modbus register writes.
  • Adjust battery state update to include imported/exported energy counters via SimCounter.
  • Introduce module-level logging for debugging control mode transitions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +54 to +55
log.debug(f'last_mode: {self.last_mode}')

Comment on lines +52 to +56
def set_power_limit(self, power_limit: Optional[int]) -> None:
unit=self.__modbus_id
log.debug(f'last_mode: {self.last_mode}')

if power_limit is None:
self.store.set(bat_state)

def set_power_limit(self, power_limit: Optional[int]) -> None:
unit=self.__modbus_id
Comment on lines +39 to +43
def update(self) -> None:
self.set_state(self.get_state())

def get_state(self) -> BatState:
soc = self.client.read_holding_registers(1068, ModbusDataType.INT_16, unit=self.__modbus_id)
power = self.client.read_holding_registers(1066, ModbusDataType.INT_16, unit=self.__modbus_id)
self.peak_filter.check_values(power)
return BatState(
imported, exported = self.sim_counter.sim_count(power)
Comment on lines +62 to +68
self.__tcp_client.write_register(1074, -4000, data_type=ModbusDataType.INT_16, unit=unit)
self.last_mode = None
else:
log.debug("Aktive Batteriesteuerung. Batterie wird auf Stop gesetzt und nicht entladen. "
"Leistungsübergabe und aktive Ladung nicht möglich.")
self.__tcp_client.write_register(1074, 0, data_type=ModbusDataType.INT_16, unit=unit)
self.last_mode = 'stop'

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.

Comment on lines +63 to +67
# hier muss die maximale Entladeleistung des Systems gesetzt werden
# Wir nehmen default -4000W an. Nach 120s setzt sich das Register
# automatisch zurück
self.client.write_register(1074, -4000, data_type=ModbusDataType.INT_16, unit=unit)
self.last_mode = None
Comment on lines +56 to +73
def set_power_limit(self, power_limit: Optional[int]) -> None:
unit = self.__modbus_id
log.debug(f'last_mode: {self.last_mode}')

if power_limit is None:
log.debug("Keine Batteriesteuerung, Selbstregelung durch Wechselrichter")
if self.last_mode is not None:
# hier muss die maximale Entladeleistung des Systems gesetzt werden
# Wir nehmen default -4000W an. Nach 120s setzt sich das Register
# automatisch zurück
self.client.write_register(1074, -4000, data_type=ModbusDataType.INT_16, unit=unit)
self.last_mode = None
else:
log.debug("Aktive Batteriesteuerung. Batterie wird auf Stop gesetzt und nicht entladen. "
"Leistungsübergabe und aktive Ladung nicht möglich.")
self.client.write_register(1074, 0, data_type=ModbusDataType.INT_16, unit=unit)
self.last_mode = 'stop'

@ndrsnhs ndrsnhs marked this pull request as draft June 10, 2026 14:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

Comment thread packages/modules/common/modbus.py Outdated
Comment on lines 196 to 200
if data_type == ModbusDataType.INT_16:
packed = struct.pack(">h", int(value))
uint16_value = struct.unpack(">H", packed)[0]
builder.add_16bit_uint(uint16_value)
if data_type == ModbusDataType.FLOAT_16:
Comment on lines +68 to +72
else:
log.debug("Aktive Batteriesteuerung. Batterie wird auf Stop gesetzt und nicht entladen. "
"Leistungsübergabe und aktive Ladung nicht möglich.")
self.client.write_register(1074, 0, data_type=ModbusDataType.INT_16, unit=unit)
self.last_mode = 'stop'

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Varta hat einen Watchdog der das Register zurücksetzt wenn nicht geschrieben wird. Damit die Entladesperre dauerhaft greift muss kontinuierlich geschrieben werden

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

Comment thread packages/modules/common/modbus.py Outdated
Comment on lines +211 to +215
def write_register(self, address: int, value: Union[int, float], data_type: Optional[ModbusDataType] = None,
byteorder: Endian = Endian.Big, wordorder: Endian = Endian.Big, **kwargs):
if data_type is not None:
if data_type.bits > 16 or data_type in [ModbusDataType.FLOAT_16,
if data_type.bits > 16 or data_type in [ModbusDataType.INT_16,
ModbusDataType.FLOAT_16,
Comment on lines 33 to 38
self.client: ModbusTcpClient_ = self.kwargs['client']
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher")
self.store = get_bat_value_store(self.component_config.id)
self.last_mode = 'Undefined'
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
self.peak_filter = PeakFilter(ComponentType.BAT, self.component_config.id, self.fault_state)
Comment on lines +56 to +60
def set_power_limit(self, power_limit: Optional[int]) -> None:
unit = self.__modbus_id
log.debug(f'last_mode: {self.last_mode}')

if power_limit is None:

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

Comment on lines +58 to +78
unit = self.__modbus_id
log.debug(f'last_mode: {self.last_mode}')

if power_limit is None:
log.debug("Keine Batteriesteuerung, Selbstregelung durch Wechselrichter")
if self.last_mode is not None:
# hier muss die maximale Entladeleistung des Systems einmalig gesetzt werden
# Wir nehmen default -4000W an. Nach 120s setzt sich das Register
# automatisch zurück
packed = struct.pack(">h", int(-4000))
uint16_value = struct.unpack(">H", packed)[0]
self.client.write_register(1074, uint16_value, data_type=ModbusDataType.UINT_16, unit=unit)
self.last_mode = None
else:
# Das Register muss kontinuierlich geschrieben werden, da der Speicher
# sonst nach 120s die Steuerung aufhebt.
log.debug(f"Aktive Batteriesteuerung, übergebene Leistung: {power_limit}W. "
"Leistungsübergabe an Speicher und aktive Ladung nicht möglich. "
"Speicher wird auf Stop gesetzt.")
self.client.write_register(1074, 0, data_type=ModbusDataType.INT_16, unit=unit)
self.last_mode = 'stop'
@ndrsnhs ndrsnhs marked this pull request as ready for review June 11, 2026 07:00
@ndrsnhs ndrsnhs requested a review from LKuemmel June 11, 2026 07:01

@LKuemmel LKuemmel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

man kann die max Entladeleistung vorgeben, aber nicht die Ladeleistung.

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.

3 participants