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() |