From 27f8550ff5fcbca06481e99ebd59e591dcd16713 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 Dec 2021 01:13:00 +0100 Subject: [PATCH] Implemented cron, daemon and foreground mode; Added interval to args; README update. --- README.md | 37 ++++++++++++++++++++++++++++--------- uplink.py | 55 +++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 69 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 26ab7fb..e3a14e0 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,10 @@ For now, I can say that uplink can monitor the status of you FRITZ!Box uplinks. ## Requirements - - A Linux based operating system (I don't test any other OS's but Raspian is fine and a good target) + - A Linux based operating system (I don't test any other OS's but Raspbian is fine and a good target) - Git (only for installing from Git repository) - - Python3 (running for me using 3.7.3, 3.8.5 and 3.9.7 on Linux) - - fritzconnection = 1.5.0 + - Python3 (running for me using 3.7.3, 3.8.5, 3.9.7 and 3.10.1 on Linux) + - fritzconnection >= 1.5.0 (included as submodule in the Git repository) - pymysql >= 0.10.1 - sqlalchemy = 1.4.27 (not for now) - urwid = 2.1.2 (not for now) @@ -23,6 +23,8 @@ Just install the 3rd party dependencies using `pip install $PACKAGE` or your OS git clone https://git.unixpeople.org/hanez/uplink.git cd uplink + # To get a local copy of fritzconnection you need to get the submodules: + git submodule update --init --recursive cp config.example.json config.json ### Configuration @@ -32,7 +34,6 @@ Edit config.json to your needs. #### Variables - interval: The polling interval - - database: Path to sqlite3 Database - uplinks: List of devices you want to poll - provider: Custom name of the uplink provider - ip: The IP of the router device @@ -42,13 +43,13 @@ Edit config.json to your needs. { "interval": 60, - "database_type": "mysql", + "database_type": "mysql", (NOT USED) "database": "uplink", "database_host": "127.0.0.1", "database_user": "USER", "database_password": "PASSWORD", - "cron": false, - "daemon": false, + "cron": false, (NOT USED) + "daemon": false, (NOT USED) "uplinks": [ { "provider": "Cable Provider", "ip": "192.168.0.1", "password": "1234" }, { "provider": "DSL Provider", "ip": "192.168.1.1", "password": "1234" } @@ -57,16 +58,34 @@ Edit config.json to your needs. ### Create Database - sqlite3 uplink.sqlite3 < uplink.sql + TODO ## Usage - ./uplink ./config.json + ./uplink [-c | -d | -f] ./config.json ### Help ./uplink --help + ``` + usage: uplink [-h] [-c | -d | -f] [-i INTERVAL] [--version] CONFIGFILE + + uplink is a tool to monitor the link status of AVM FRITZ!Box Cable and DSL based routers. + + positional arguments: + CONFIGFILE the configfile to use + + options: + -h, --help show this help message and exit + -c, --cron cron mode executes the script only once without loop (default: false) + -d, --daemon run as native daemon (default: false) + -f, --foreground run looped in foreground (default: false) + -i INTERVAL, --interval INTERVAL + poll interval in seconds. this overrides config file settings. (default: 60) + --version show program's version number and exit + ``` + ## View collected data I actually use "[DBeaver](https://dbeaver.io/)" for taking a look at the data uplink is collecting. diff --git a/uplink.py b/uplink.py index 35b1e81..a835d33 100755 --- a/uplink.py +++ b/uplink.py @@ -22,23 +22,23 @@ import argparse import json -import logging -import logging.handlers +# import logging +# import logging.handlers import sys +import time from uplink.uplink import Uplink # Version format: MAJOR.FEATURE.FIXES -__version__ = "0.3.0-development" +__version__ = "0.4.0-development" +# TODO: CHECK ALL ERROR HANDLING!!! # TODO: Implement logging -# TODO: Implement --no-daemon for a single run e.g. "cron mode" # TODO: Implement CLI output messages # TODO: Add hourly speed-tests' # TODO: IDEA: Implement a small webserver inline to get statistics and graphs over the network? Or maybe better as a # separate daemon -# TODO: Make use of the args passed to the script -# TODO: Cleanup args and reduce to only what makes sense +# TODO: Make use of more args passed to the script def parse_args(): @@ -50,18 +50,19 @@ def parse_args(): parser.add_argument("config", metavar="CONFIGFILE", help="the configfile to use") mode = parser.add_mutually_exclusive_group() - mode.add_argument("--cron", default=False, dest="cron", action="store_true", + mode.add_argument("-c", "--cron", default=False, dest="cron", action="store_true", help="cron mode executes the script only once without loop (default: false)") - mode.add_argument("--daemon", default=False, dest="daemon", action="store_true", + mode.add_argument("-d", "--daemon", default=False, dest="daemon", action="store_true", help="run as native daemon (default: false)") - mode.add_argument("--foreground", default=True, dest="foreground", action="store_true", - help="run in foreground (default: true)") + mode.add_argument("-f", "--foreground", default=False, dest="foreground", action="store_true", + help="run looped in foreground (default: false)") - parser.add_argument("-i", "--interval", default=60, type=int, - help="seconds poll interval (default: 60)") + parser.add_argument("-i", "--interval", type=int, help="poll interval in seconds. this overrides config file " + "settings. (default: 60)") + """ parser.add_argument("-b", "--database", metavar="DATABASE", help="database to use") parser.add_argument("-u", "--user", type=str, help="database username") @@ -91,6 +92,7 @@ def parse_args(): output.add_argument("-d", "--debug", action="store_const", dest="log_level", const=logging.DEBUG, help="output debug messages") output.set_defaults(loglevel=logging.ERROR) + """ parser.add_argument("--version", action="version", version="%(prog)s " + str(__version__)) @@ -108,10 +110,35 @@ if __name__ == "__main__": with open(config_path, 'r') as configfile: config_data = configfile.read() _config = json.loads(config_data) - except Exception as err: + except "OSError, PermissionDenied, RuntimeError, ValueError" as err: # TODO: Replace all lines like this with generic Python logging print(str("Uplink: Configuration Error!")) sys.exit(1) + try: + _config["interval"] + except KeyError: + # interval not configured in configuration; using default value + _config["interval"] = 60 + + if args.interval: + # interval set in args is overriding configuration and default + _config["interval"] = args.interval + uplink = Uplink("/tmp/uplink.pid", _config) - uplink.start() + + if args.cron: + for i in range(len(_config["uplinks"])): + uplink.get_data(_config, i) + elif args.daemon: + uplink.start() + elif args.foreground: + while True: + for i in range(len(_config["uplinks"])): + uplink.get_data(_config, i) + # TODO: print data formatted to STDOUT + time.sleep(_config["interval"]) + else: + + print("uplink: error: no run mode selected; use --cron (-c), --daemon (-d) or --foreground (-f) to run uplink. " + "use --help for more information")