Source code for lories.components.weather.weather

# -*- coding: utf-8 -*-
"""
lories.weather
~~~~~~~~~~~~~~


"""

from __future__ import annotations

from collections.abc import Callable
from typing import Optional, Type, TypeVar

from lories.components import Component, ComponentError, register_component_type
from lories.core import Constant, ResourceError
from lories.core.activator import ActivatorMeta
from lories.core.register import Registry
from lories.location import Location, LocationUnavailableException
from lories.typing import Configurations, ContextArgument


# noinspection PyShadowingBuiltins
def register_weather_type(
    type: str,
    *alias: str,
    factory: Callable[[ContextArgument, Optional[Configurations]], WeatherType] = None,
    replace: bool = False,
) -> Callable[[Type[WeatherType]], Type[WeatherType]]:
    # noinspection PyShadowingNames
    def _register(cls: Type[WeatherType]) -> Type[WeatherType]:
        registry.register(cls, type, *alias, factory=factory, replace=replace)
        return cls

    return _register


[docs] class WeatherMeta(ActivatorMeta): def __call__(cls, context: ContextArgument, configs: Configurations, **kwargs) -> WeatherType: _type = configs.get("type", default="default").lower() _cls = cls._get_class(_type) if cls != _cls: return _cls(context, configs, **kwargs) return super().__call__(context, configs, **kwargs) # noinspection PyMethodMayBeStatic, PyShadowingBuiltins def _get_class(cls: Type[WeatherType], type: str) -> Type[WeatherType]: if type in ["default", "virtual"]: return cls elif registry.has_type(type): registration = registry.from_type(type) return registration.type raise ResourceError(f"Unknown weather type '{type}'")
# noinspection SpellCheckingInspection
[docs] @register_component_type("weather") class Weather(Component, metaclass=WeatherMeta): GHI = Constant(float, "ghi", "Global Horizontal Irradiance", "W/m2") DNI = Constant(float, "dni", "Direct Normal Irradiance", "W/m2") DHI = Constant(float, "dhi", "Diffuse Horizontal Irradiance", "W/m2") TEMP_AIR = Constant(float, "temp_air", "Air Temperature", "°C") TEMP_FELT = Constant(float, "temp_felt", "Felt Temperature", "°C") TEMP_DEW_POINT = Constant(float, "dew_point", "Dewpoint Temperature", "°C") HUMIDITY_REL = Constant(float, "humidity_relative", "Relative Humidity", "%") PRESSURE_SEA = Constant(float, "pressure_sea", "Atmospheric Pressure", "hPa") WIND_SPEED = Constant(float, "wind_speed", "Wind Speed", "km/h") WIND_SPEED_GUST = Constant(float, "wind_speed_gust", "Wind Gust Speed", "km/h") WIND_DIRECTION = Constant(float, "wind_direction", "Wind Direction", "°") WIND_DIRECTION_GUST = Constant(float, "wind_direction_gust", "Wind Gust Direction", "°") CLOUD_COVER = Constant(float, "cloud_cover", "Total Cloud Cover", "%") CLOUDS_LOW = Constant(float, "clouds_low", "Low Cloud Cover", "%") CLOUDS_MID = Constant(float, "clouds_mid", "Medium Cloud Cover", "%") CLOUDS_HIGH = Constant(float, "clouds_high", "High Cloud Cover", "%") SUNSHINE = Constant(int, "sunshine", "Sunshine Duration", "min") VISIBILITY = Constant(int, "visibility", "Visibility", "m") PRECIPITATION = Constant(float, "precipitation", "Precipitation", "mm") PRECIPITATION_CONV = Constant(float, "precipitation_convective", "Precipitation Convective", "mm") PRECIPITATION_PROB = Constant(float, "precipitation_probability", "Precipitation Probability", "%") PRECIPITABLE_WATER = Constant(float, "precipitable_water", "Precipitable Water", "cm") SNOW_FRACTION = Constant(float, "snow_fraction", "Snow Fraction", "1/0") location: Location # noinspection PyProtectedMember def configure(self, configs: Configurations) -> None: super().configure(configs) self.localize(configs.get_member(Location.TYPE, defaults={})) # noinspection PyUnresolvedReferences def localize(self, configs: Configurations) -> None: if configs.enabled and all(k in configs for k in ["latitude", "longitude"]): self.location = Location( configs.get_float("latitude"), configs.get_float("longitude"), timezone=configs.get("timezone", default="UTC"), altitude=configs.get_float("altitude", default=None), country=configs.get("country", default=None), state=configs.get("state", default=None), ) else: try: self.location = self.context.location if not isinstance(self.location, Location): raise ComponentError(self, f"Invalid location type '{type(self.location)}'") except (LocationUnavailableException, AttributeError): raise ComponentError(self, "Missing location")
WeatherType = TypeVar("WeatherType", bound=Weather) registry = Registry[Weather]()