67 lines
2.5 KiB
Python
67 lines
2.5 KiB
Python
from influxdb_client import Point, WritePrecision
|
|
|
|
DT_H = 5.0 / 60.0
|
|
|
|
|
|
def _f(config, key, default):
|
|
try:
|
|
return float(config.get(key, default) or default)
|
|
except Exception:
|
|
return float(default)
|
|
|
|
|
|
def battery_soc_points(data_obj, forecast_var, pv_dict, load_dict, grid_dict):
|
|
config = data_obj["config"]
|
|
aid = str(config["anlagen_id"])
|
|
cap_kwh = _f(config, "batt_capacity_kwh", 0.0)
|
|
if cap_kwh <= 0 or not grid_dict:
|
|
return []
|
|
|
|
min_soc = _f(config, "batt_min_soc", _f(config, "batt_min_soc_percent", 0.0))
|
|
max_soc = _f(config, "batt_max_soc", _f(config, "batt_max_soc_percent", 100.0))
|
|
charge_eff = max(0.01, min(1.0, _f(config, "batt_charge_efficiency", 0.95)))
|
|
discharge_eff = max(0.01, min(1.0, _f(config, "batt_discharge_efficiency", 0.95)))
|
|
start_soc_value = data_obj.get("current_soc_perc")
|
|
if start_soc_value is None or start_soc_value == "":
|
|
start_soc_value = config.get("batt_soc_percent", 50.0)
|
|
start_soc = float(start_soc_value)
|
|
start_soc = max(min_soc, min(max_soc, start_soc))
|
|
|
|
min_kwh = cap_kwh * min_soc / 100.0
|
|
max_kwh = cap_kwh * max_soc / 100.0
|
|
soc_kwh = max(min_kwh, min(max_kwh, cap_kwh * start_soc / 100.0))
|
|
|
|
planned_battery = (
|
|
data_obj.get("battery_plans", {})
|
|
.get(int(forecast_var), {})
|
|
.get("battery", {})
|
|
)
|
|
points = []
|
|
for t in data_obj["df_fut"].index:
|
|
if t not in grid_dict:
|
|
continue
|
|
if t in planned_battery:
|
|
battery_target_w = float(planned_battery[t]) # positiv = laden
|
|
else:
|
|
residual_w = float(load_dict.get(t, 0.0)) - float(pv_dict.get(t, 0.0))
|
|
grid_w = float(grid_dict.get(t, 0.0))
|
|
battery_target_w = grid_w - residual_w
|
|
|
|
if battery_target_w > 0:
|
|
soc_kwh += battery_target_w * DT_H / 1000.0 * charge_eff
|
|
elif battery_target_w < 0:
|
|
soc_kwh += battery_target_w * DT_H / 1000.0 / discharge_eff
|
|
|
|
soc_kwh = max(min_kwh, min(max_kwh, soc_kwh))
|
|
soc_percent = max(0.0, min(100.0, soc_kwh / cap_kwh * 100.0))
|
|
|
|
points.append(
|
|
Point("forecast_diagnostics")
|
|
.tag("anlagen_id", aid)
|
|
.tag("data_type", "battery_soc_simulation")
|
|
.tag("forecast_var", f"prog_var_{forecast_var}")
|
|
.field("soc_percent", float(soc_percent))
|
|
.time(t.to_pydatetime() if hasattr(t, "to_pydatetime") else t, WritePrecision.S)
|
|
)
|
|
return points
|