diff --git a/README.md b/README.md index 2d67641..e60f1a1 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,21 @@ The easiest way to track your Raspberry Pi or Ubuntu computer system health and * 2024-01-27: Updated the sensors names not to include the device name as per home assistant guidelines * 2024-01-10: Added support for Raspberry Pi 5 fan speed monitoring (only works on Raspberry Pi 5 with stock fan) +## CLI arguments + +``` +usage: rpi-cpu2mqtt.py [-h] [--display] [--service] [--version] [--update] + +options: + -h, --help show this help message and exit + --display, -d display values on screen + --service, -s run script as a service + --version, -v display version + --update, -u update script and config +``` + + + ## Installation ### Automated diff --git a/src/config.py.example b/src/config.py.example index f2d411c..1cae288 100644 --- a/src/config.py.example +++ b/src/config.py.example @@ -53,4 +53,4 @@ wifi_signal = False wifi_signal_dbm = False # this works only on raspbery pi version 5 with stock fan -rpi5_fan_speed = False \ No newline at end of file +rpi5_fan_speed = False diff --git a/src/rpi-cpu2mqtt.py b/src/rpi-cpu2mqtt.py index 7835240..cfb018f 100644 --- a/src/rpi-cpu2mqtt.py +++ b/src/rpi-cpu2mqtt.py @@ -13,6 +13,7 @@ import json import config import os import argparse +import update # get device host name - used in mqtt topic hostname = socket.gethostname() @@ -142,8 +143,7 @@ def get_manufacturer(): return(pretty_name) -def check_git_update(): - script_dir = os.path.dirname(os.path.realpath(__file__)) +def check_git_update(script_dir): full_cmd = "git -C {} remote update && git -C {} status -uno".format(script_dir, script_dir) try: git_update = subprocess.Popen(full_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0].decode("utf-8") @@ -157,16 +157,14 @@ def check_git_update(): return(git_update) -def check_git_version(): - script_dir = os.path.dirname(os.path.realpath(__file__)) +def check_git_version(script_dir): full_cmd = "git -C {} describe --tags `git -C {} rev-list --tags --max-count=1`".format(script_dir, script_dir) git_version = subprocess.Popen(full_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0].decode("utf-8") return(git_version) -def check_git_version_remote(): - script_dir = os.path.dirname(os.path.realpath(__file__)) +def check_git_version_remote(script_dir): full_cmd = "git -C {} ls-remote --tags origin | awk -F'/' '{{print $3}}' | sort -V | tail -n 1".format(script_dir) result = subprocess.Popen(full_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0].decode("utf-8") latest_tag = result.strip() @@ -184,7 +182,7 @@ def get_network_ip(): s.close() return IP -def print_values(): +def print_measured_values(): print(":: rpi-mqtt-monitor") print(" Version: " + config.version) print("") @@ -417,20 +415,44 @@ def bulk_publish_to_mqtt(cpu_load=0, cpu_temp=0, used_space=0, voltage=0, sys_cl client.disconnect() - -if __name__ == '__main__': - # parse arguments +def parse_arguments(): parser = argparse.ArgumentParser() - parser.add_argument('--display', '-d', action='store_true', help='Display values on screen', default=False) - parser.add_argument('--service', '-s', action='store_true', help='Run script as a service', default=False) - parser.add_argument('--version', '-v', action='store_true', help='Display version', default=False) + parser.add_argument('--display', '-d', action='store_true', help='display values on screen', default=False) + parser.add_argument('--service', '-s', action='store_true', help='run script as a service, sleep interval is configurable in config.py', default=False) + parser.add_argument('--version', '-v', action='store_true', help='display installed version and exit', default=False) + parser.add_argument('--update', '-u', action='store_true', help='update script and config then exit', default=False) args = parser.parse_args() - if args.version: - print("rpi-mqtt-monitor version: " + check_git_version().strip()) - print("rpi-mqtt-monitor remote version: " + check_git_version_remote().strip()) + if args.update: + version = check_git_version_remote(script_dir).strip() + git_update = check_git_update(script_dir) + + if git_update == 'on': + git_update = True + else: + git_update = False + + update.do_update(version, git_update) + exit() + if args.version: + installed_version = check_git_version(script_dir).strip() + latest_versino = check_git_version_remote(script_dir).strip() + print("Installed version: " + installed_version) + print("Latest version: " + latest_versino) + if installed_version != latest_versino: + print("Update available") + else: + print("No update available") + exit() + return args + + +if __name__ == '__main__': + script_dir = os.path.dirname(os.path.realpath(__file__)) + args = parse_arguments(); + while True: # set all monitored values to False in case they are turned off in the config cpu_load = cpu_temp = used_space = voltage = sys_clock_speed = swap = memory = uptime_days = wifi_signal = wifi_signal_dbm = rpi5_fan_speed = git_update = False @@ -465,11 +487,11 @@ if __name__ == '__main__': if config.rpi5_fan_speed: rpi5_fan_speed = check_rpi5_fan_speed() if config.git_update: - git_update = check_git_update() + git_update = check_git_update(script_dir) # Display collected values on screen if --display option is used if args.display: - print_values() + print_measured_values() # Publish messages to MQTT if hasattr(config, 'group_messages') and config.group_messages: diff --git a/src/update.py b/src/update.py index 904ecdf..0d5318c 100644 --- a/src/update.py +++ b/src/update.py @@ -1,6 +1,7 @@ import ast import os import subprocess +import config def get_assignments(filename): @@ -10,6 +11,7 @@ def get_assignments(filename): assignments = {node.targets[0].id: ast.literal_eval(node.value) for node in ast.walk(tree) if isinstance(node, ast.Assign)} return assignments + def update_config(current_config, example_config): current_assignments = get_assignments(current_config) example_assignments = get_assignments(example_config) @@ -21,30 +23,51 @@ def update_config(current_config, example_config): for var, value in missing_assignments.items(): f.write('\n{} = {!r}'.format(var, value)) -def display_config_differences(current_config, example_config): + +def display_config_differences(current_config, example_config, display=True): current_assignments = get_assignments(current_config) example_assignments = get_assignments(example_config) missing_assignments = {var: value for var, value in example_assignments.items() if var not in current_assignments} if missing_assignments: - print("Missing variables:") - for var, value in missing_assignments.items(): - print('\n{} = {!r}'.format(var, value)) + if display: + print("Missing variables:") + for var, value in missing_assignments.items(): + print('\n{} = {!r}'.format(var, value)) return True else: return False +def update_config_version(version): + with open('config.py', 'r') as f: + lines = f.readlines() -script_dir = os.path.dirname(os.path.realpath(__file__)) -os.chdir(script_dir) + with open('config.py', 'w') as f: + print(":: Updating config version to {}".format(version)) + for line in lines: + if 'version = ' in line: + f.write('version = "{}"\n'.format(version)) + else: + f.write(line) -print(":: Updating git repository") -result = subprocess.run(['git', '-C', script_dir, 'pull'], check=True, universal_newlines=True, stdout=subprocess.PIPE) -print(result.stdout) -if display_config_differences('config.py', 'config.py.example'): - print(":: Updating config.py") - update_config('config.py', 'config.py.example') -else: - print(":: No config.py updates needed") \ No newline at end of file +def do_update(version=config.version, git_update=True, config_update=True): + script_dir = os.path.dirname(os.path.realpath(__file__)) + os.chdir(script_dir) + print("Current version: {}".format(config.version)) + if git_update: + print(":: Updating git repository") + result = subprocess.run(['git', '-C', script_dir, 'pull'], check=True, universal_newlines=True, stdout=subprocess.PIPE) + print(result.stdout) + + if display_config_differences('config.py', 'config.py.example') and config_update: + print(":: Updating config.py") + update_config('config.py', 'config.py.example') + + if version != config.version: + update_config_version(version) + + +if __name__ == '__main__': + do_update() \ No newline at end of file