view weather_server/types.py @ 0:efe7a1eff167

Create initial logger for weather server.
author Paul Fisher <paul@pfish.zone>
date Sat, 28 Sep 2019 23:17:21 -0400
parents
children 52ef21607b31
line wrap: on
line source

"""Basic data types for the weather server."""

import datetime
import math
import typing as t

import attr
import pytz


def c_to_f(c: float) -> float:
    return c * 9 / 5 + 32


# Values from Sontag1990 via Wikipedia:
# https://en.wikipedia.org/wiki/Dew_point
_MAGNUS_B = 17.62
_MAGNUS_C = 243.12


@attr.s(frozen=True, slots=True)
class Reading:
    """A single reading from a weather thingy.

    Field order is important, as it is used in CSV files.
    """

    # The Unix timestamp of the reading.
    sample_time = attr.ib(type=datetime.datetime)

    # The temperature, in degrees Celsius.
    temp_c = attr.ib(type=float)

    # The relative humidity, in percent.
    rh_pct = attr.ib(type=float)

    # The Unix timestamp when the reading was received.
    ingest_time = attr.ib(type=datetime.datetime)

    @property
    def temp_f(self) -> float:
        return c_to_f(self.temp_c)

    @property
    def dew_point_c(self) -> float:
        gamma = self._gamma
        return _MAGNUS_C * gamma / (_MAGNUS_B - gamma)

    @property
    def dew_point_f(self) -> float:
        return c_to_f(self.dew_point_c)

    def as_dict(self) -> t.Dict[str, t.Any]:
        return attr.asdict(self, recurse=False)

    @classmethod
    def from_now(cls, **kwargs) -> 'Reading':
        return cls(ingest_time=_utc_now(), **kwargs)

    @property
    def _gamma(self) -> float:
        return (
            math.log(self.rh_pct / 100) +
            _MAGNUS_B * self.temp_c / (_MAGNUS_C + self.temp_c))


def _utc_now():
    return datetime.datetime.utcnow().replace(tzinfo=pytz.UTC)