Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
d295c41
active bat control includes all chargemodes
ndrsnhs Jul 14, 2025
2eba749
Merge branch 'openWB:master' into active-bat-control
ndrsnhs Jul 28, 2025
78e9c12
check for cp power
ndrsnhs Aug 12, 2025
5a7c442
adjust test
ndrsnhs Aug 12, 2025
dc2829a
Merge branch 'active-bat-control' of https://github.com/ndrsnhs/core …
ndrsnhs Oct 15, 2025
6c71001
more options for active bat control + test
ndrsnhs Nov 24, 2025
0171c96
remove whitespaces
ndrsnhs Nov 24, 2025
797b14c
add valid topics
ndrsnhs Nov 24, 2025
1ad049d
build UI
ndrsnhs Nov 25, 2025
06a012d
Revert "build UI"
ndrsnhs Nov 25, 2025
429161a
update setdata
ndrsnhs Nov 25, 2025
affe45b
build UI
ndrsnhs Nov 25, 2025
6c931ea
Revert "build UI"
ndrsnhs Nov 25, 2025
d635cc9
Merge branch 'openWB:master' into active-bat-control
ndrsnhs Nov 25, 2025
b4cfb14
fix indentation
ndrsnhs Nov 25, 2025
7a265aa
build UI
ndrsnhs Nov 25, 2025
cfcec4f
Revert "build UI"
ndrsnhs Nov 26, 2025
f9bbd2d
build UI
ndrsnhs Nov 26, 2025
76cf992
Revert "build UI"
ndrsnhs Dec 3, 2025
e75c1e9
Merge branch 'openWB:master' into active-bat-control
ndrsnhs Dec 3, 2025
cc4e906
support multiple batteries
ndrsnhs Dec 3, 2025
e432917
add valid topics
ndrsnhs Dec 4, 2025
5b5fec6
simple price limit
ndrsnhs Dec 5, 2025
84f6aca
Merge branch 'openWB:master' into active-bat-control
ndrsnhs Dec 5, 2025
e7dff6f
build UI
ndrsnhs Dec 5, 2025
1957f4a
Revert "build UI"
ndrsnhs Dec 8, 2025
e4ee29d
change variable name
ndrsnhs Dec 8, 2025
0cfaa20
add charging plans
ndrsnhs Dec 17, 2025
489b805
Merge branch 'openWB:master' into active-bat-control
ndrsnhs Dec 17, 2025
cf42dc8
Revert "add charging plans"
ndrsnhs Dec 17, 2025
478ee43
Merge branch 'active-bat-control' of https://github.com/ndrsnhs/core …
ndrsnhs Dec 17, 2025
7f4be59
add tests, improve price charging
ndrsnhs Dec 17, 2025
ffbd286
add tests for price charging
ndrsnhs Dec 17, 2025
908f3b7
Merge branch 'openWB:master' into active-bat-control
ndrsnhs Feb 3, 2026
1a6c277
no active bat control on startup
ndrsnhs Feb 3, 2026
795de02
add comments
ndrsnhs Feb 3, 2026
aa7a6e5
Merge branch 'openWB:master' into bat-control-remove-last_mode
ndrsnhs Feb 3, 2026
4aa0638
Merge branch 'openWB:master' into bat-control-remove-last_mode
ndrsnhs Feb 9, 2026
dff8d7e
Merge branch 'bat-control-remove-last_mode' of https://github.com/ndr…
ndrsnhs Apr 8, 2026
91d67ef
invert sign of max_discharge_power
ndrsnhs Apr 8, 2026
dff071f
fix
ndrsnhs Apr 8, 2026
fdfa407
correct factor calculation
ndrsnhs Apr 8, 2026
2e351ce
fix update_config
ndrsnhs Apr 8, 2026
338915b
fix hysteresis
ndrsnhs Apr 9, 2026
16b644e
correct access of set_limit
ndrsnhs Apr 9, 2026
d48b399
move set_limit/current_state out of synced dataclass
ndrsnhs Apr 9, 2026
1c7f1a3
move current_state/set_limit
ndrsnhs Apr 9, 2026
4cd9358
Merge branch 'bat-control-remove-last_mode' of https://github.com/ndr…
ndrsnhs Apr 9, 2026
d3c7fd5
Prevent merge conflict in update_config.py
benderl Apr 9, 2026
e69001f
Merge branch 'master' into bat-control-remove-last_mode
benderl Apr 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions packages/control/bat_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ class ManualMode(Enum):
MANUAL_DISCHARGE = "manual_discharge" # in DE nicht erlaubt


class CurrentState(Enum):
STARTUP = "startup"
ACTIVE = "active"
IDLE = "idle"


@dataclass
class Config:
configured: bool = field(default=False, metadata={"topic": "config/configured"})
Expand All @@ -76,8 +82,8 @@ class Config:
metadata={"topic": "config/bat_control_condition"})
manual_mode: str = field(default=ManualMode.MANUAL_DISABLE.value,
metadata={"topic": "config/manual_mode"})
bat_control_min_soc: str = field(default=5, metadata={"topic": "config/bat_control_min_soc"})
bat_control_max_soc: str = field(default=90, metadata={"topic": "config/bat_control_max_soc"})
bat_control_min_soc: int = field(default=10, metadata={"topic": "config/bat_control_min_soc"})
bat_control_max_soc: int = field(default=90, metadata={"topic": "config/bat_control_max_soc"})
price_limit_activated: bool = field(default=False, metadata={"topic": "config/price_limit_activated"})
price_charge_activated: bool = field(default=False, metadata={"topic": "config/price_charge_activated"})
price_limit: float = field(default=0.30, metadata={"topic": "config/price_limit"})
Expand Down Expand Up @@ -111,6 +117,8 @@ class Set:
power_limit: Optional[float] = field(default=None, metadata={"topic": "set/power_limit"})
regulate_up: bool = field(default=False, metadata={"topic": "set/regulate_up"})
hysteresis_discharge: bool = field(default=False, metadata={"topic": "set/hysteresis_discharge"})
current_state: str = field(default=CurrentState.STARTUP.value, metadata={"topic": "set/current_state"})
set_limit: bool = field(default=False, metadata={"topic": "set/set_limit"})


def set_factory() -> Set:
Expand Down Expand Up @@ -585,6 +593,21 @@ def get_power_limit(self):
self.data.set.power_limit = None
log.debug("Speicher-Leistung nicht begrenzen")

if ((self.data.config.bat_control_permitted is False or
self.data.config.bat_control_activated is False)
and self.data.set.current_state == CurrentState.STARTUP.value):
self.data.set.set_limit = False
elif (self.data.set.current_state == CurrentState.IDLE.value and
charge_mode == BatChargeMode.BAT_SELF_REGULATION):
self.data.set.set_limit = False
else:
self.data.set.set_limit = True

if charge_mode == BatChargeMode.BAT_SELF_REGULATION:
self.data.set.current_state = CurrentState.IDLE.value
else:
self.data.set.current_state = CurrentState.ACTIVE.value


def get_controllable_bat_components() -> List:
bat_components = []
Expand Down
3 changes: 2 additions & 1 deletion packages/control/bat_all_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

@pytest.fixture(autouse=True)
def data_fixture() -> None:
data.data_init(Mock())
data.data.general_data = General()
data.data.cp_all_data = Mock(spec=AllChargepoints, data=Mock(
spec=AllChargepointData, get=Mock(spec=AllGet, power=0)))
Expand Down Expand Up @@ -194,7 +195,7 @@ class BatControlParams:
bat_control_permitted: bool = True
bat_control_activated: bool = True
max_charge_power: float = 5000
max_discharge_power: float = 5000
max_discharge_power: float = -5000
bat_control_min_soc: float = 10.0
bat_control_max_soc: float = 90.0
price_limit_activated: bool = False
Expand Down
15 changes: 8 additions & 7 deletions packages/control/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,14 @@ def process_algorithm_results(self) -> None:
cp.remember_previous_values()
except Exception:
log.exception("Fehler im Process-Modul für Ladepunkt "+str(cp))
for bat_component in get_controllable_bat_components():
modules_threads.append(
Thread(
target=set_power_limit_wrapper,
args=(bat_component,
data.data.bat_data[f"bat{bat_component.component_config.id}"].data.set.power_limit),
name=f"set power limit {bat_component.component_config.id}"))
if data.data.bat_all_data.data.set.set_limit:
for bat_component in get_controllable_bat_components():
modules_threads.append(
Thread(
target=set_power_limit_wrapper,
args=(bat_component,
data.data.bat_data[f"bat{bat_component.component_config.id}"].data.set.power_limit),
name=f"set power limit {bat_component.component_config.id}"))
for action in data.data.io_actions.actions.values():
if isinstance(action, DimmingDirectControl):
for d in action.config.configuration.devices:
Expand Down
5 changes: 3 additions & 2 deletions packages/helpermodules/setdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -673,9 +673,10 @@ def process_bat_topic(self, msg: mqtt.MQTTMessage):
"openWB/set/bat/set/regulate_up" in msg.topic or
"openWB/set/bat/set/hysteresis_discharge" in msg.topic):
self._validate_value(msg, bool)
elif (re.search("openWB/set/bat/[0-9]+/get/max_charge_power$", msg.topic) is not None or
re.search("openWB/set/bat/[0-9]+/get/max_discharge_power$", msg.topic) is not None):
elif re.search("^openWB/set/bat/[0-9]+/get/max_charge_power$", msg.topic) is not None:
self._validate_value(msg, float, [(0, float("inf"))])
elif re.search("^openWB/set/bat/[0-9]+/get/max_discharge_power$", msg.topic) is not None:
self._validate_value(msg, float, [(None, 0)])
elif (re.search("openWB/set/bat/[0-9]+/get/state_str$", msg.topic) is not None):
self._validate_value(msg, str)
elif ("openWB/set/bat/config/price_limit" in msg.topic or
Expand Down
12 changes: 11 additions & 1 deletion packages/helpermodules/update_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@

class UpdateConfig:

DATASTORE_VERSION = 120
DATASTORE_VERSION = 121

valid_topic = [
"^openWB/bat/config/bat_control_permitted$",
Expand Down Expand Up @@ -3058,3 +3058,13 @@ def upgrade(topic: str, payload) -> Optional[dict]:
return {topic: mode}
self._loop_all_received_topics(upgrade)
self._append_datastore_version(120)

def upgrade_datastore_121(self) -> None:
def upgrade(topic: str, payload) -> Optional[dict]:
if re.search(r"^openWB/bat/[0-9]+/get/max_discharge_power$", topic) is not None:
payload = decode_payload(payload)
if isinstance(payload, (int, float)):
payload = -abs(payload)
return {topic: payload}
self._loop_all_received_topics(upgrade)
self._append_datastore_version(121)
Loading