- Use urllib.parse.quote instead of requests.utils.quote in the pvnode and
Solcast providers: the runtime re-export exists, but the requests type stubs
do not declare it, so the pre-commit mypy hook failed with
'Module has no attribute "quote"'.
- Mark the force_update keyword in the new provider tests with `# type: ignore`
— it is consumed by the cache_in_file decorator at runtime; same call
convention and ignore style as pvforecastakkudoktor.py.
- Add PVForecastPVNode, PVForecastForecastSolar and PVForecastSolcast to the
expected provider sequence in tests/test_prediction.py (fixture + index
assertions) — the two sequence tests failed because the new providers were
registered in prediction.py but missing from the hardcoded expectations.
Add PVForecastForecastSolar, a PV forecast provider for the free Forecast.Solar
API (https://forecast.solar), giving operators a no-account forecast source in
addition to Akkudoktor, VRM, Import and pvnode. An optional API key raises the
rate limit.
result.watts is the instantaneous AC power per timestamp, fed directly as
pvforecast_ac_power. Plants with several roof planes issue one request per plane
(Forecast.Solar is single-plane) and the powers are summed per timestamp.
Forecast.Solar azimuth (-180=N..0=S..90=W) is converted from EOS surface_azimuth
(north=0..south=180); local wall-clock timestamps are resolved via the response
timezone before resampling.
Registered in pvforecast.py and prediction.py. Adds tests for timezone
resolution, azimuth conversion, multi-plane summation and HTTP-error handling.