diff 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 diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/weather_server/types.py	Sat Sep 28 23:17:21 2019 -0400
@@ -0,0 +1,68 @@
+"""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)