Mercurial > personal > weatherlog
annotate weatherlog/daemon.py @ 19:7117db65715e
Make weatherlog shutdown properly by handling SIGTERM.
| author | Paul Fisher <paul@pfish.zone> |
|---|---|
| date | Mon, 20 Jan 2020 23:36:23 -0500 |
| parents | 39c0686e6765 |
| children | 92367b644e29 |
| rev | line source |
|---|---|
|
12
91e22a09b82f
Create 'daemon.py', a runner to tie it all together.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
1 """Entry point to set up a temperature logging daemon.""" |
|
91e22a09b82f
Create 'daemon.py', a runner to tie it all together.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
2 |
|
17
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
3 import argparse |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
4 import enum |
|
19
7117db65715e
Make weatherlog shutdown properly by handling SIGTERM.
Paul Fisher <paul@pfish.zone>
parents:
17
diff
changeset
|
5 import signal |
|
7117db65715e
Make weatherlog shutdown properly by handling SIGTERM.
Paul Fisher <paul@pfish.zone>
parents:
17
diff
changeset
|
6 import threading |
|
12
91e22a09b82f
Create 'daemon.py', a runner to tie it all together.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
7 import time |
|
91e22a09b82f
Create 'daemon.py', a runner to tie it all together.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
8 import typing as t |
|
91e22a09b82f
Create 'daemon.py', a runner to tie it all together.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
9 |
|
17
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
10 import attr |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
11 import toml |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
12 |
|
12
91e22a09b82f
Create 'daemon.py', a runner to tie it all together.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
13 from . import http_writer |
|
91e22a09b82f
Create 'daemon.py', a runner to tie it all together.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
14 from . import logger |
|
91e22a09b82f
Create 'daemon.py', a runner to tie it all together.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
15 from . import reader |
|
91e22a09b82f
Create 'daemon.py', a runner to tie it all together.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
16 |
|
91e22a09b82f
Create 'daemon.py', a runner to tie it all together.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
17 DEFAULT_INTERVAL_SECS = 60 |
|
91e22a09b82f
Create 'daemon.py', a runner to tie it all together.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
18 MIN_INTERVAL_SECS = 5 |
|
91e22a09b82f
Create 'daemon.py', a runner to tie it all together.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
19 |
|
91e22a09b82f
Create 'daemon.py', a runner to tie it all together.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
20 |
|
91e22a09b82f
Create 'daemon.py', a runner to tie it all together.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
21 def run( |
|
17
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
22 rd: reader.Reader, |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
23 log: logger.BufferedLogger, |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
24 writer: logger.RemoteWriter, |
|
12
91e22a09b82f
Create 'daemon.py', a runner to tie it all together.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
25 interval: int = DEFAULT_INTERVAL_SECS, |
|
19
7117db65715e
Make weatherlog shutdown properly by handling SIGTERM.
Paul Fisher <paul@pfish.zone>
parents:
17
diff
changeset
|
26 ) -> None: |
|
12
91e22a09b82f
Create 'daemon.py', a runner to tie it all together.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
27 """Sets up and runs a logger daemon.""" |
|
19
7117db65715e
Make weatherlog shutdown properly by handling SIGTERM.
Paul Fisher <paul@pfish.zone>
parents:
17
diff
changeset
|
28 evt = threading.Event() |
|
7117db65715e
Make weatherlog shutdown properly by handling SIGTERM.
Paul Fisher <paul@pfish.zone>
parents:
17
diff
changeset
|
29 signal.signal(signal.SIGTERM, lambda *args: evt.set()) |
|
12
91e22a09b82f
Create 'daemon.py', a runner to tie it all together.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
30 cycle = 0 |
|
91e22a09b82f
Create 'daemon.py', a runner to tie it all together.
Paul Fisher <paul@pfish.zone>
parents:
diff
changeset
|
31 start = time.time() |
|
19
7117db65715e
Make weatherlog shutdown properly by handling SIGTERM.
Paul Fisher <paul@pfish.zone>
parents:
17
diff
changeset
|
32 running = True |
|
7117db65715e
Make weatherlog shutdown properly by handling SIGTERM.
Paul Fisher <paul@pfish.zone>
parents:
17
diff
changeset
|
33 log.start() |
|
13
4c81182eaa6b
daemon: Fail less ungracefully, bump to v0.1.0.
Paul Fisher <paul@pfish.zone>
parents:
12
diff
changeset
|
34 try: |
|
19
7117db65715e
Make weatherlog shutdown properly by handling SIGTERM.
Paul Fisher <paul@pfish.zone>
parents:
17
diff
changeset
|
35 while running: |
|
17
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
36 log.write(rd.read().as_dict()) |
|
13
4c81182eaa6b
daemon: Fail less ungracefully, bump to v0.1.0.
Paul Fisher <paul@pfish.zone>
parents:
12
diff
changeset
|
37 cycle += 1 |
|
4c81182eaa6b
daemon: Fail less ungracefully, bump to v0.1.0.
Paul Fisher <paul@pfish.zone>
parents:
12
diff
changeset
|
38 target = start + interval * cycle |
|
4c81182eaa6b
daemon: Fail less ungracefully, bump to v0.1.0.
Paul Fisher <paul@pfish.zone>
parents:
12
diff
changeset
|
39 now = time.time() |
|
19
7117db65715e
Make weatherlog shutdown properly by handling SIGTERM.
Paul Fisher <paul@pfish.zone>
parents:
17
diff
changeset
|
40 running = not evt.wait(max(target - now, MIN_INTERVAL_SECS)) |
|
13
4c81182eaa6b
daemon: Fail less ungracefully, bump to v0.1.0.
Paul Fisher <paul@pfish.zone>
parents:
12
diff
changeset
|
41 finally: |
|
4c81182eaa6b
daemon: Fail less ungracefully, bump to v0.1.0.
Paul Fisher <paul@pfish.zone>
parents:
12
diff
changeset
|
42 log.close() |
|
17
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
43 |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
44 |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
45 class SensorType(enum.Enum): |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
46 DHT22 = 'DHT22' |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
47 BME280 = 'BME280' |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
48 |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
49 |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
50 @attr.s(auto_attribs=True, frozen=True, slots=True) |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
51 class _Config: |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
52 # The directory to store reading data in. |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
53 directory: str |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
54 # The URL to submit readings to. |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
55 url: str |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
56 # The type of sensor to read from. |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
57 sensor: SensorType |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
58 # The authentication preamble for the URL. |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
59 auth: t.Dict[str, object] |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
60 |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
61 |
|
19
7117db65715e
Make weatherlog shutdown properly by handling SIGTERM.
Paul Fisher <paul@pfish.zone>
parents:
17
diff
changeset
|
62 def parse_config(config_file: str) -> _Config: |
|
17
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
63 with open(config_file, 'r') as infile: |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
64 config = toml.load(infile) |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
65 return _Config( |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
66 directory=config['directory'], |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
67 url=config['url'], |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
68 sensor=SensorType(config['sensor']['type']), |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
69 auth=config['auth']) |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
70 |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
71 |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
72 def main(args: t.Optional[t.Sequence[str]] = None) -> None: |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
73 parser = argparse.ArgumentParser() |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
74 parser.add_argument('config_file', help='TOML file to load config from.') |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
75 parsed = parser.parse_args(args) |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
76 config = parse_config(parsed.config_file) |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
77 writer = http_writer.HTTPWriter(config.url, config.auth) |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
78 log = logger.BufferedLogger(config.directory, writer) |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
79 |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
80 if config.sensor is SensorType.DHT22: |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
81 rdr = reader.DHT22Reader() |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
82 elif config.sensor is SensorType.BME280: |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
83 rdr = reader.BME280Reader() |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
84 else: |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
85 raise AssertionError('Unknown sensor type') |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
86 run(rdr, log, writer) |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
87 |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
88 |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
89 if __name__ == '__main__': |
|
39c0686e6765
daemon: Change to executing from a config file.
Paul Fisher <paul@pfish.zone>
parents:
14
diff
changeset
|
90 main() |
