second version
This commit is contained in:
@@ -12,7 +12,6 @@ import httpx
|
||||
import pandas as pd
|
||||
import pvlib
|
||||
from pvlib import irradiance
|
||||
from pvlib.pvsystem import pvwatts_dc
|
||||
|
||||
from app.config import get_settings
|
||||
|
||||
@@ -64,9 +63,12 @@ async def fetch_pv_forecast(site_id: int, db) -> tuple[int, int]:
|
||||
|
||||
arrays = await db.fetch(
|
||||
"""
|
||||
SELECT *
|
||||
SELECT id, code, nominal_power_wp, azimuth_deg, tilt_deg,
|
||||
shading_factor, controllable
|
||||
FROM ems.asset_pv_array
|
||||
WHERE site_id = $1
|
||||
AND azimuth_deg IS NOT NULL
|
||||
AND tilt_deg IS NOT NULL
|
||||
ORDER BY id
|
||||
""",
|
||||
site_id,
|
||||
@@ -91,7 +93,7 @@ async def fetch_pv_forecast(site_id: int, db) -> tuple[int, int]:
|
||||
"temperature_2m",
|
||||
]
|
||||
),
|
||||
"forecast_days": 2,
|
||||
"forecast_days": max(2, min(int(settings.open_meteo_forecast_days), 16)),
|
||||
"timezone": "auto",
|
||||
}
|
||||
|
||||
@@ -148,6 +150,7 @@ async def fetch_pv_forecast(site_id: int, db) -> tuple[int, int]:
|
||||
|
||||
loc = pvlib.location.Location(lat, lon, tz=api_tz)
|
||||
solar_pos = loc.get_solarposition(times)
|
||||
dni_extra = irradiance.get_extra_radiation(times)
|
||||
|
||||
total_rows = 0
|
||||
horizon_start = times[0].tz_convert(timezone.utc).to_pydatetime()
|
||||
@@ -156,13 +159,13 @@ async def fetch_pv_forecast(site_id: int, db) -> tuple[int, int]:
|
||||
)
|
||||
|
||||
for arr in arrays:
|
||||
tilt = float(arr["tilt_deg"] or 0.0)
|
||||
az_db = float(arr["azimuth_deg"] or 0.0)
|
||||
tilt = float(arr["tilt_deg"])
|
||||
az_db = float(arr["azimuth_deg"])
|
||||
az_pvlib = _db_azimuth_to_pvlib(az_db)
|
||||
pdc0 = float(arr["nominal_power_wp"])
|
||||
nominal_power_wp = float(arr["nominal_power_wp"])
|
||||
shading = float(arr["shading_factor"] or 1.0)
|
||||
|
||||
poa = irradiance.get_total_irradiance(
|
||||
poa_global = irradiance.get_total_irradiance(
|
||||
surface_tilt=tilt,
|
||||
surface_azimuth=az_pvlib,
|
||||
solar_zenith=solar_pos["apparent_zenith"],
|
||||
@@ -170,20 +173,23 @@ async def fetch_pv_forecast(site_id: int, db) -> tuple[int, int]:
|
||||
dni=dni,
|
||||
ghi=ghi,
|
||||
dhi=dhi,
|
||||
dni_extra=dni_extra,
|
||||
model="haydavies",
|
||||
)["poa_global"].fillna(0).clip(lower=0)
|
||||
|
||||
temp_cell = temp_air + 0.04 * poa
|
||||
p_dc = pvwatts_dc(poa, temp_cell, pdc0, -0.004)
|
||||
p_dc = p_dc.fillna(0).clip(lower=0) * shading
|
||||
power_w = p_dc.round().astype(int)
|
||||
area_m2 = nominal_power_wp / (1000.0 * 0.20)
|
||||
power_w = poa_global * area_m2 * 0.20 * shading
|
||||
cap_w = nominal_power_wp * 1.1
|
||||
power_w = power_w.clip(lower=0, upper=cap_w).round().astype(int)
|
||||
|
||||
model_params: dict[str, Any] = {
|
||||
"source": "open_meteo",
|
||||
"endpoint": base,
|
||||
"params": params,
|
||||
"pvlib_model": "haydavies",
|
||||
"pvwatts_gamma_pdc": -0.004,
|
||||
"nominal_power_wp": nominal_power_wp,
|
||||
"shading_factor": shading,
|
||||
"area_m2_ref_20pct": area_m2,
|
||||
}
|
||||
|
||||
run_id = await db.fetchval(
|
||||
|
||||
Reference in New Issue
Block a user