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