diff --git a/flexmeasures_weather/cli/commands.py b/flexmeasures_weather/cli/commands.py index a95c435..00cc148 100644 --- a/flexmeasures_weather/cli/commands.py +++ b/flexmeasures_weather/cli/commands.py @@ -98,7 +98,8 @@ def add_weather_sensor(**args): fm_sensor_specs["generic_asset"] = weather_station fm_sensor_specs["timezone"] = args["timezone"] fm_sensor_specs["name"] = fm_sensor_specs.pop("fm_sensor_name") - fm_sensor_specs.pop("weather_sensor_name") + fm_sensor_specs.pop("OWM_sensor_name") + fm_sensor_specs.pop("WAPI_sensor_name") sensor = Sensor(**fm_sensor_specs) sensor.attributes = fm_sensor_specs["attributes"] diff --git a/flexmeasures_weather/cli/tests/utils.py b/flexmeasures_weather/cli/tests/utils.py index 3dab3ab..9c87578 100644 --- a/flexmeasures_weather/cli/tests/utils.py +++ b/flexmeasures_weather/cli/tests/utils.py @@ -1,6 +1,6 @@ from typing import List from datetime import datetime, timedelta - +from flask import current_app from flexmeasures.utils.time_utils import as_server_time, get_timezone @@ -17,11 +17,21 @@ def mock_api_response(api_key, location): mock_date_tz_aware = as_server_time( datetime.fromtimestamp(mock_date.timestamp(), tz=get_timezone()) ).replace(second=0, microsecond=0) + + provider = str(current_app.config.get("WEATHER_PROVIDER", "")) + date_key = "dt" + temp_key = "temp" + wind_speed_key = "wind_speed" + if provider == "WAPI": + date_key = "time_epoch" + temp_key = "temp" + wind_speed_key = "wind_kph" + return mock_date_tz_aware, [ - {"dt": mock_date.timestamp(), "temp": 40, "wind_speed": 100}, + {date_key: mock_date.timestamp(), temp_key: 40, wind_speed_key: 100}, { - "dt": (mock_date + timedelta(hours=1)).timestamp(), - "temp": 42, - "wind_speed": 90, + date_key: (mock_date + timedelta(hours=1)).timestamp(), + temp_key: 42, + wind_speed_key: 90, }, ] diff --git a/flexmeasures_weather/sensor_specs.py b/flexmeasures_weather/sensor_specs.py index 1e06cc6..6a1dcaa 100644 --- a/flexmeasures_weather/sensor_specs.py +++ b/flexmeasures_weather/sensor_specs.py @@ -18,28 +18,32 @@ mapping = [ dict( fm_sensor_name="temperature", - weather_sensor_name="temp", + OWM_sensor_name="temp", + WAPI_sensor_name="temp_c", unit="°C", event_resolution=timedelta(minutes=60), attributes=weather_attributes, ), dict( fm_sensor_name="wind speed", - weather_sensor_name="wind_speed", + OWM_sensor_name="wind_speed", + WAPI_sensor_name="wind_kph", unit="m/s", event_resolution=timedelta(minutes=60), attributes=weather_attributes, ), dict( fm_sensor_name="cloud cover", - weather_sensor_name="clouds", + OWM_sensor_name="clouds", + WAPI_sensor_name="cloud", unit="%", event_resolution=timedelta(minutes=60), attributes=weather_attributes, ), dict( fm_sensor_name="irradiance", # in save_forecasts_to_db, we catch this name and do the actual computation to get to the irradiance - weather_sensor_name="clouds", + OWM_sensor_name="clouds", + WAPI_sensor_name="cloud", unit="W/m²", event_resolution=timedelta(minutes=60), attributes=weather_attributes, diff --git a/flexmeasures_weather/utils/weather.py b/flexmeasures_weather/utils/weather.py index f27f91a..7d500dd 100644 --- a/flexmeasures_weather/utils/weather.py +++ b/flexmeasures_weather/utils/weather.py @@ -68,45 +68,7 @@ def process_weatherapi_data( combined = first_day + second_day + third_day relevant = combined[hour_no : hour_no + 48] - # relevant = combined - - def map_weather_api_to_owm(weather_api_data: Dict[str, Any]) -> Dict[str, Any]: - """ - Converts a single hour of WeatherAPI data to an OpenWeatherMap-style dictionary. - - Args: - weather_api_data (Dict[str, Any]): A dictionary containing an hour's data from WeatherAPI. - - Returns: - Dict[str, Any]: A dictionary with keys and structure similar to OpenWeatherMap's hourly forecast. - """ - game = { - "dt": weather_api_data["time_epoch"], - "temp": weather_api_data["temp_c"], - "feels_like": weather_api_data["feelslike_c"], - "pressure": weather_api_data["pressure_mb"], - "humidity": weather_api_data["humidity"], - "dew_point": weather_api_data["dewpoint_c"], - "uvi": weather_api_data["uv"], - "clouds": weather_api_data["cloud"], - "visibility": weather_api_data["vis_km"] * 1000, - "wind_speed": weather_api_data["wind_kph"] / 3.6, - "wind_deg": weather_api_data["wind_degree"], - "wind_gust": weather_api_data["gust_kph"] / 3.6, - "weather": [ - { - "id": weather_api_data["condition"]["code"], - "main": weather_api_data["condition"]["text"].split()[0], - "description": weather_api_data["condition"]["text"], - "icon": weather_api_data["condition"]["icon"], - } - ], - "pop": weather_api_data["chance_of_rain"] / 100, - } - return game - - converted = [map_weather_api_to_owm(hour) for hour in relevant] - return converted + return relevant def call_openweatherapi( @@ -212,7 +174,7 @@ def call_api( return call_weatherapi(api_key, location) -def save_forecasts_in_db( +def save_forecasts_in_db( # noqa: C901 api_key: str, locations: List[Tuple[float, float]], ): @@ -226,6 +188,7 @@ def save_forecasts_in_db( "WEATHER_MAXIMAL_DEGREE_LOCATION_DISTANCE", DEFAULT_MAXIMAL_DEGREE_LOCATION_DISTANCE, ) + provider = str(current_app.config.get("WEATHER_PROVIDER", "")) for location in locations: click.echo("[FLEXMEASURES] %s, %s" % location) weather_sensors: Dict[str, Sensor] = ( @@ -246,8 +209,9 @@ def save_forecasts_in_db( # loop through forecasts, including the one of current hour (horizon 0) for fc in forecasts: + time_key = fc["dt"] if provider == "OWM" else fc["time_epoch"] fc_datetime = as_server_time( - datetime.fromtimestamp(fc["dt"], get_timezone()) + datetime.fromtimestamp(time_key, get_timezone()) ) click.echo( f"[FLEXMEASURES-WEATHER] Processing forecast for {fc_datetime} ..." @@ -255,8 +219,8 @@ def save_forecasts_in_db( data_source = get_or_create_owm_data_source() for sensor_specs in mapping: sensor_name = str(sensor_specs["fm_sensor_name"]) - owm_response_label = sensor_specs["weather_sensor_name"] - if owm_response_label in fc: + provider_response_label = sensor_specs[f"{provider}_sensor_name"] + if provider_response_label in fc: weather_sensor = get_weather_sensor( sensor_specs, location, @@ -270,7 +234,11 @@ def save_forecasts_in_db( if weather_sensor not in db_forecasts.keys(): db_forecasts[weather_sensor] = [] - fc_value = fc[owm_response_label] + fc_value = fc[provider_response_label] + + if provider_response_label == "wind_kph": + # convert wind speed from kph to m/s + fc_value = fc[provider_response_label] / 3.6 # the irradiance is not available in Provider -> we compute it ourselves if sensor_name == "irradiance": @@ -297,7 +265,7 @@ def save_forecasts_in_db( else: # we will not fail here, but issue a warning msg = "No label '%s' in response data for time %s" % ( - owm_response_label, + provider_response_label, fc_datetime, ) click.echo("[FLEXMEASURES-WEATHER] %s" % msg)