comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:efe7a1eff167
1 """Basic data types for the weather server."""
2
3 import datetime
4 import math
5 import typing as t
6
7 import attr
8 import pytz
9
10
11 def c_to_f(c: float) -> float:
12 return c * 9 / 5 + 32
13
14
15 # Values from Sontag1990 via Wikipedia:
16 # https://en.wikipedia.org/wiki/Dew_point
17 _MAGNUS_B = 17.62
18 _MAGNUS_C = 243.12
19
20
21 @attr.s(frozen=True, slots=True)
22 class Reading:
23 """A single reading from a weather thingy.
24
25 Field order is important, as it is used in CSV files.
26 """
27
28 # The Unix timestamp of the reading.
29 sample_time = attr.ib(type=datetime.datetime)
30
31 # The temperature, in degrees Celsius.
32 temp_c = attr.ib(type=float)
33
34 # The relative humidity, in percent.
35 rh_pct = attr.ib(type=float)
36
37 # The Unix timestamp when the reading was received.
38 ingest_time = attr.ib(type=datetime.datetime)
39
40 @property
41 def temp_f(self) -> float:
42 return c_to_f(self.temp_c)
43
44 @property
45 def dew_point_c(self) -> float:
46 gamma = self._gamma
47 return _MAGNUS_C * gamma / (_MAGNUS_B - gamma)
48
49 @property
50 def dew_point_f(self) -> float:
51 return c_to_f(self.dew_point_c)
52
53 def as_dict(self) -> t.Dict[str, t.Any]:
54 return attr.asdict(self, recurse=False)
55
56 @classmethod
57 def from_now(cls, **kwargs) -> 'Reading':
58 return cls(ingest_time=_utc_now(), **kwargs)
59
60 @property
61 def _gamma(self) -> float:
62 return (
63 math.log(self.rh_pct / 100) +
64 _MAGNUS_B * self.temp_c / (_MAGNUS_C + self.temp_c))
65
66
67 def _utc_now():
68 return datetime.datetime.utcnow().replace(tzinfo=pytz.UTC)