# HG changeset patch # User Paul Fisher # Date 1571365692 14400 # Node ID 39c0686e67658cf3baf08ab32b92cd12a1d68fa2 # Parent 770215590d8095600f8c3bf18203f576e79136ec daemon: Change to executing from a config file. This updates daemon.py to execute based on a config file, rather than needing manual configuration. It also instructs setup.py to create an entry point for the new daemon.py main function. Configuration is specified in a TOML file whose format is documented, kind of, in the parse_config function. diff -r 770215590d80 -r 39c0686e6765 setup.py --- a/setup.py Thu Oct 17 22:19:33 2019 -0400 +++ b/setup.py Thu Oct 17 22:28:12 2019 -0400 @@ -2,7 +2,7 @@ setuptools.setup( name='weatherlog', - version='0.1.0', + version='0.2.0', packages=setuptools.find_packages(), python_requires='>=3.7', install_requires=[ @@ -14,6 +14,12 @@ 'requests', 'RPi.bme280', 'smbus2', + 'toml', ], setup_requires=['wheel'], + entry_points={ + 'console_scripts': [ + 'weatherlogd = weatherlog.daemon:main', + ] + } ) diff -r 770215590d80 -r 39c0686e6765 weatherlog/daemon.py --- a/weatherlog/daemon.py Thu Oct 17 22:19:33 2019 -0400 +++ b/weatherlog/daemon.py Thu Oct 17 22:28:12 2019 -0400 @@ -1,8 +1,13 @@ """Entry point to set up a temperature logging daemon.""" +import argparse +import enum import time import typing as t +import attr +import toml + from . import http_writer from . import logger from . import reader @@ -12,25 +17,69 @@ def run( - directory: str, - url: str, - preamble: t.Dict[str, t.Any], + rd: reader.Reader, + log: logger.BufferedLogger, + writer: logger.RemoteWriter, interval: int = DEFAULT_INTERVAL_SECS, ): """Sets up and runs a logger daemon.""" - writer = http_writer.HTTPWriter(url, preamble) - log = logger.BufferedLogger(directory, writer) log.start() - - r = reader.DHT22Reader() cycle = 0 start = time.time() try: while True: - log.write(r.read().as_dict()) + log.write(rd.read().as_dict()) cycle += 1 target = start + interval * cycle now = time.time() time.sleep(max(target - now, MIN_INTERVAL_SECS)) finally: log.close() + + +class SensorType(enum.Enum): + DHT22 = 'DHT22' + BME280 = 'BME280' + + +@attr.s(auto_attribs=True, frozen=True, slots=True) +class _Config: + # The directory to store reading data in. + directory: str + # The URL to submit readings to. + url: str + # The type of sensor to read from. + sensor: SensorType + # The authentication preamble for the URL. + auth: t.Dict[str, object] + + +def parse_config(config_file: str): + with open(config_file, 'r') as infile: + config = toml.load(infile) + return _Config( + directory=config['directory'], + url=config['url'], + sensor=SensorType(config['sensor']['type']), + auth=config['auth']) + + +def main(args: t.Optional[t.Sequence[str]] = None) -> None: + parser = argparse.ArgumentParser() + parser.add_argument('config_file', help='TOML file to load config from.') + parsed = parser.parse_args(args) + config = parse_config(parsed.config_file) + writer = http_writer.HTTPWriter(config.url, config.auth) + log = logger.BufferedLogger(config.directory, writer) + + if config.sensor is SensorType.DHT22: + rdr = reader.DHT22Reader() + elif config.sensor is SensorType.BME280: + rdr = reader.BME280Reader() + else: + raise AssertionError('Unknown sensor type') + run(rdr, log, writer) + + +if __name__ == '__main__': + main()