c8e3016fd6
- Implement `sigen_daemon.py` to poll Sigenergy plant metrics and store snapshots. - Create `web_daemon.py` for serving a web interface with various endpoints. - Add debug scripts: - `debug_duplicates.py` to find duplicate target times in forecast data. - `debug_energy_forecast.py` to print baseline energy forecast curves. - `debug_oracle_evaluations.py` to run the oracle evaluator. - `debug_sigen.py` to inspect stored Sigenergy plant snapshots. - `debug_weather.py` to trace resolved truth data. - `modbus_test.py` for exploring Sigenergy plants or inverters over Modbus TCP. - Introduce `oracle_evaluator.py` for evaluating stored oracle predictions against actuals. - Add TCN training scripts in `tcn` directory for training usage sequence models.
68 lines
2.1 KiB
Python
68 lines
2.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Debug baseline energy forecast curves."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
from datetime import timezone
|
|
|
|
from gibil.classes.oracle.builder import EnergyForecastBuilder
|
|
from gibil.classes.env_loader import EnvLoader
|
|
from gibil.classes.models import PowerForecastPoint
|
|
|
|
|
|
def main() -> None:
|
|
EnvLoader().load()
|
|
args = parse_args()
|
|
solar_run, load_run, net_run = EnergyForecastBuilder.from_env().build()
|
|
|
|
print(
|
|
f"issued_at={net_run.issued_at.astimezone(timezone.utc).isoformat(timespec='seconds')}"
|
|
)
|
|
print(
|
|
f"solar_model={solar_run.model_version} "
|
|
f"load_model={load_run.model_version} points={len(net_run.points)}"
|
|
)
|
|
print(
|
|
"target_at solar_p10 solar_p50 solar_p90 "
|
|
"load_p10 load_p50 load_p90 net_p10 net_p50 net_p90"
|
|
)
|
|
solar_by_target = _by_target(solar_run.points)
|
|
load_by_target = _by_target(load_run.points)
|
|
for point in net_run.points[: args.limit]:
|
|
solar_point = solar_by_target[point.target_at]
|
|
load_point = load_by_target[point.target_at]
|
|
print(
|
|
f"{point.target_at.astimezone(timezone.utc).isoformat(timespec='minutes'):25} "
|
|
f"{solar_point.p10_power_w:9.0f} "
|
|
f"{solar_point.p50_power_w:9.0f} "
|
|
f"{solar_point.p90_power_w:9.0f} "
|
|
f"{load_point.p10_power_w:8.0f} "
|
|
f"{load_point.p50_power_w:8.0f} "
|
|
f"{load_point.p90_power_w:8.0f} "
|
|
f"{point.p10_net_power_w:7.0f} "
|
|
f"{point.p50_net_power_w:7.0f} "
|
|
f"{point.p90_net_power_w:7.0f}"
|
|
)
|
|
|
|
|
|
def _by_target(points: list[PowerForecastPoint]) -> dict[object, PowerForecastPoint]:
|
|
return {point.target_at: point for point in points}
|
|
|
|
|
|
def parse_args() -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(
|
|
description="Print baseline solar/load/net forecast curves."
|
|
)
|
|
parser.add_argument(
|
|
"--limit",
|
|
type=int,
|
|
default=24,
|
|
help="Number of forecast points to show. Defaults to 24.",
|
|
)
|
|
return parser.parse_args()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|