view weather_server/types.py @ 31:9bc3687e1e5e

logfile: Add an index, and don't keep everything in RAM. - Adds index BSON file, updated upon writing. - Limits amount of data in RAM. - Gracefully handles writes that don't update index.
author Paul Fisher <paul@pfish.zone>
date Tue, 07 Jul 2020 19:51:30 -0400
parents beb42c835c52
children
line wrap: on
line source

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

import datetime
import math
import typing as t

import attr


T = t.TypeVar('T')


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)

    @classmethod
    def from_dict(cls: t.Type[T], d: t.Dict[str, t.Any]) -> T:
        return cls(**{f.name: d[f.name] for f in attr.fields(cls)})

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