diff --git a/gspconsumer/app.py b/gspconsumer/app.py index 0f9da64..5fbffc2 100644 --- a/gspconsumer/app.py +++ b/gspconsumer/app.py @@ -24,6 +24,7 @@ from gspconsumer.backup import make_gsp_yields_from_national from gspconsumer.gsps import filter_gsps_which_have_new_data, get_gsps from gspconsumer.time import check_uk_london_hour +from gspconsumer.nitghtime import make_night_time_zeros logging.basicConfig( level=getattr(logging, os.getenv("LOGLEVEL", "DEBUG")), @@ -181,6 +182,12 @@ def pull_data_and_save( logger.debug(f"Got {len(gsp_yield_df)} gsp yield for gsp id {gsp.gsp_id} before filtering") + if len(gsp_yield_df) == 0: + logger.warning(f"Did not find any data for {gsp.gsp_id} for {start} to {end}. " + f"Will try adding some nighttime zeros") + + gsp_yield_df = make_night_time_zeros(start, end, gsp, gsp_yield_df, regime) + if len(gsp_yield_df) == 0: logger.warning(f"Did not find any data for {gsp.gsp_id} for {start} to {end}") else: diff --git a/gspconsumer/nitghtime.py b/gspconsumer/nitghtime.py new file mode 100644 index 0000000..6affc70 --- /dev/null +++ b/gspconsumer/nitghtime.py @@ -0,0 +1,74 @@ +import pandas as pd +import pvlib +import os +import logging +from datetime import datetime + +from nowcasting_datamodel.models.gsp import LocationSQL + +logger = logging.getLogger(__name__) + +elevation_limit = os.getenv("ELEVATION_LIMIT", 5) + +# get lat and longs of the gsps +dir = os.path.dirname(__file__) +gsp_locations_file = os.path.join(dir, "data/uk_gsp_locations.csv") +gsp_locations = pd.read_csv(gsp_locations_file) +gsp_locations = gsp_locations.set_index("gsp_id") + + + +def make_night_time_zeros( + start: datetime, + end: datetime, + gsp: LocationSQL, + gsp_yield_df: pd.DataFrame, + regime: str, +): + """ + Set generation to zero if it is night time + + :param start: The start datetimes we are looking for + :param end: The end datetimes we are looking for + :param gsp: + :param gsp_yield_df: + :param regime: + :return: + """ + + if regime != "in-day": + return gsp_yield_df + + gsp_location = gsp_locations.loc[gsp.gsp_id] + longitude = gsp_location["longitude"] + latitude = gsp_location["latitude"] + + times = pd.date_range(start=start, end=end, freq="30min") + # check if it is nighttime, and if so, set generation values to zero + solpos = pvlib.solarposition.get_solarposition( + time=times, longitude=longitude, latitude=latitude, method="nrel_numpy" + ) + elevation = solpos["elevation"] + + # only keep nighttime values + elevation = elevation[elevation < elevation_limit] + + # last capacity is + if gsp.last_gsp_yield is not None: + last_capacity = gsp.last_gsp_yield.capacity_mwp + last_pvlive_updated_utc = gsp.last_gsp_yield.pvlive_updated_utc + else: + last_capacity = 0 + last_pvlive_updated_utc = start + + gsp_yield_df = pd.DataFrame( + { + "generation_mw": 0, + "datetime_gmt": elevation.index, + "installedcapacity_mwp": last_capacity, + "capacity_mwp": last_capacity, + "updated_gmt": last_pvlive_updated_utc, + } + ) + + return gsp_yield_df diff --git a/requirements.txt b/requirements.txt index b7cae9a..c1e282d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,3 +8,4 @@ nowcasting_datamodel==1.5.46 sentry-sdk==2.13.0 #git+https://github.com/SheffieldSolar/PV_Live-API#pvlive_api click +pvlib diff --git a/tests/test_app.py b/tests/test_app.py index b949672..429e680 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -33,6 +33,25 @@ def test_pull_data(db_session, input_data_last_updated_sql): assert gsps[0].installed_capacity_mw != 10 +# need to make this tomorrows date +@freeze_time("2024-12-07 02:00:00") +def test_pull_data_night_time(db_session): + gsps = [ + Location(gsp_id=1, label="GSP_1", installed_capacity_mw=10).to_orm(), + ] + gsps[0].last_gsp_yield = None + + pull_data_and_save(gsps=gsps, session=db_session) + + pv_yields = db_session.query(GSPYieldSQL).all() + assert len(pv_yields) > 0 + assert pv_yields[0].pvlive_updated_utc != None + assert pv_yields[0].capacity_mwp != None + assert pv_yields[0].solar_generation_kw == 0 + + + + def test_app(db_connection, input_data_last_updated_sql): make_national(db_connection)