diff --git a/README.md b/README.md index 3ce7a87..a516bde 100644 --- a/README.md +++ b/README.md @@ -214,12 +214,16 @@ Create a cron entry like this (you might need to update the path in the cron ent ``` ## How to update -Navigate to the folder where Rapsberry Pi MQTT Monitor is installed and pull the git repository: +Remote updates via Home Assistant are now available. + +To use these you need to have the script running as a service. (the installer now supports this) + +Manual update: ```bash -git pull +cd rpi-mqtt-monitor +python3 src/update.py ``` -* Note that sometimes you might need to add new variables to our src/config.py file, so make sure you check the example file and update your config.py file accordingly. ## Home Assistant Integration diff --git a/src/config.py.example b/src/config.py.example index cf51670..9fd280e 100644 --- a/src/config.py.example +++ b/src/config.py.example @@ -50,6 +50,7 @@ sys_clock_speed = False swap = False memory = True uptime = True +uptime_seconds = False # Enable wifi_signal for unit of measuring % or wifi_signal_dbm for unit of meaning dBm wifi_signal = False diff --git a/src/rpi-cpu2mqtt.py b/src/rpi-cpu2mqtt.py index 839c38c..1629de7 100644 --- a/src/rpi-cpu2mqtt.py +++ b/src/rpi-cpu2mqtt.py @@ -102,8 +102,8 @@ def check_sys_clock_speed(): return subprocess.Popen(full_cmd, shell=True, stdout=subprocess.PIPE).communicate()[0] -def check_uptime(): - full_cmd = "awk '{print int($1/3600/24)}' /proc/uptime" +def check_uptime(format): + full_cmd = "awk '{print int($1"+format+")}' /proc/uptime" return int(subprocess.Popen(full_cmd, shell=True, stdout=subprocess.PIPE).communicate()[0]) @@ -146,22 +146,15 @@ def get_manufacturer(): 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") - except subprocess.CalledProcessError as e: - print("Error updating git repository:", e.output) - - if any(s in git_update for s in ('Your branch is up to date', 'Your branch is up-to-date', 'Votre branche est à jour')): + if config.version == update.check_git_version_remote(script_dir): git_update = { "installed_ver": config.version, "new_ver": config.version, } - else: git_update = { "installed_ver": config.version, - "new_ver": check_git_version_remote(script_dir), + "new_ver": update.check_git_version_remote(script_dir), } return(json.dumps(git_update)) @@ -173,11 +166,7 @@ def check_git_version(script_dir): return(git_version) -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() - return latest_tag if latest_tag else None + def get_network_ip(): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) @@ -197,9 +186,9 @@ def print_measured_values( cpu_load=0, cpu_temp=0, used_space=0, voltage=0, sys_ print(" Version: " + config.version) print("") print(":: Device Information") - print(" Model Name: " + check_model_name().strip()) - print(" Manufacturer: " + get_manufacturer().strip()) - print(" OS: " + get_os().strip()) + print(" Model Name: " + check_model_name()) + print(" Manufacturer: " + get_manufacturer()) + print(" OS: " + get_os()) print(" Hostname: " + hostname) print(" IP Address: " + get_network_ip()) if args.service: @@ -214,6 +203,7 @@ def print_measured_values( cpu_load=0, cpu_temp=0, used_space=0, voltage=0, sys_ print(" Swap: " + str(swap) + " %") print(" Memory: " + str(memory) + " %") print(" Uptime: " + str(uptime_days) + " days") + print(" Uptime: " + str(uptime_seconds) + " seconds") print(" Wifi Signal: " + str(wifi_signal) + " %") print(" Wifi Signal dBm: " + str(wifi_signal_dbm) + " dBm") print(" RPI5 Fan Speed: " + str(rpi5_fan_speed) + " RPM") @@ -232,10 +222,11 @@ def config_json(what_config): "unit_of_measurement": "", "device": { "identifiers": [hostname], - "manufacturer": manufacturer, - "model": model_name, + "manufacturer": 'github.com/hjelev', + "model": 'RPi MQTT Monitor ' + config.version, "name": hostname, - "sw_version": config.version, + "sw_version": os, + "hw_version": model_name + " by " + manufacturer, "configuration_url": "https://github.com/hjelev/rpi-mqtt-monitor" } } @@ -282,6 +273,12 @@ def config_json(what_config): data["name"] = "Uptime" data["unit_of_measurement"] = "days" data["state_class"] = "measurement" + elif what_config == "uptime_seconds": + data["icon"] = "mdi:timer-outline" + data["name"] = "Uptime" + data["unit_of_measurement"] = "s" + data["device_class"] = "duration" + data["state_class"] = "total_increasing" elif what_config == "wifi_signal": data["icon"] = "mdi:wifi" data["name"] = "Wifi Signal" @@ -310,7 +307,7 @@ def config_json(what_config): version = check_git_version(script_dir).strip() data["icon"] = "mdi:update" data["name"] = "RPi MQTT Monitor" - data["title"] = "RPi MQTT Monitor v" + version + data["title"] = "Version" data["state_topic"] = config.mqtt_topic_prefix + "/" + hostname + "/" + "git_update" data["value_template"] = "{{ {'installed_version': value_json.installed_ver, 'latest_version': value_json.new_ver } | to_json }}" data["device_class"] = "firmware" @@ -333,7 +330,7 @@ def on_connect(client, userdata, flags, rc): def publish_to_mqtt(cpu_load=0, cpu_temp=0, used_space=0, voltage=0, sys_clock_speed=0, swap=0, memory=0, - uptime_days=0, wifi_signal=0, wifi_signal_dbm=0, rpi5_fan_speed=0, git_update=False, update=False): + uptime_days=0, uptime_seconds=0, wifi_signal=0, wifi_signal_dbm=0, rpi5_fan_speed=0, git_update=False, update=False): # connect to mqtt server client = paho.Client(client_id="rpi-mqtt-monitor-" + hostname) client.username_pw_set(config.mqtt_user, config.mqtt_password) @@ -404,6 +401,13 @@ def publish_to_mqtt(cpu_load=0, cpu_temp=0, used_space=0, voltage=0, sys_clock_s time.sleep(config.sleep_time) client.publish(config.mqtt_topic_prefix + "/" + hostname + "/uptime_days", uptime_days, qos=config.qos, retain=config.retain) time.sleep(config.sleep_time) + if config.uptime_seconds: + if config.discovery_messages: + client.publish("homeassistant/sensor/" + config.mqtt_topic_prefix + "/" + hostname + "_uptime/config", + config_json('uptime'), qos=config.qos) + time.sleep(config.sleep_time) + client.publish(config.mqtt_topic_prefix + "/" + hostname + "/uptime_seconds", uptime_seconds, qos=config.qos, retain=config.retain) + time.sleep(config.sleep_time) if config.wifi_signal: if config.discovery_messages: client.publish("homeassistant/sensor/" + config.mqtt_topic_prefix + "/" + hostname + "_wifi_signal/config", @@ -444,10 +448,10 @@ def publish_to_mqtt(cpu_load=0, cpu_temp=0, used_space=0, voltage=0, sys_clock_s def bulk_publish_to_mqtt(cpu_load=0, cpu_temp=0, used_space=0, voltage=0, sys_clock_speed=0, swap=0, memory=0, - uptime_days=0, wifi_signal=0, wifi_signal_dbm=0, rpi5_fan_speed=0, git_update=0): + uptime_days=0, uptime_seconds=0, wifi_signal=0, wifi_signal_dbm=0, rpi5_fan_speed=0, git_update=0): # compose the CSV message containing the measured values - values = cpu_load, cpu_temp, used_space, voltage, int(sys_clock_speed), swap, memory, uptime_days, wifi_signal, wifi_signal_dbm, rpi5_fan_speed, git_update + values = cpu_load, cpu_temp, used_space, voltage, int(sys_clock_speed), swap, memory, uptime_days, uptime_seconds, wifi_signal, wifi_signal_dbm, rpi5_fan_speed, git_update values = str(values)[1:-1] client = paho.Client(client_id="rpi-mqtt-monitor-" + hostname) @@ -477,7 +481,7 @@ def parse_arguments(): args = parser.parse_args() if args.update: - version = check_git_version_remote(script_dir).strip() + version = update.check_git_version_remote(script_dir).strip() git_update = check_git_update(script_dir) if git_update == 'on': @@ -485,13 +489,13 @@ def parse_arguments(): else: git_update = False - update.do_update(version, git_update) + update.do_update(script_dir, version, git_update) exit() if args.version: - installed_version = check_git_version(script_dir).strip() - latest_versino = check_git_version_remote(script_dir).strip() + installed_version = config.version + latest_versino = update.check_git_version_remote(script_dir).strip() print("Installed version: " + installed_version) print("Latest version: " + latest_versino) if installed_version != latest_versino: @@ -504,7 +508,7 @@ def parse_arguments(): def gather_and_send_info(): 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 = update = False + cpu_load = cpu_temp = used_space = voltage = sys_clock_speed = swap = memory = uptime_seconds = uptime_days = wifi_signal = wifi_signal_dbm = rpi5_fan_speed = git_update = update = False # delay the execution of the script if hasattr(config, 'random_delay'): time.sleep(config.random_delay) @@ -528,7 +532,9 @@ def gather_and_send_info(): if config.memory: memory = check_memory() if config.uptime: - uptime_days = check_uptime() + uptime_days = check_uptime('/3600/24') + if config.uptime_seconds: + uptime_seconds = check_uptime('') if config.wifi_signal: wifi_signal = check_wifi_signal('') if config.wifi_signal_dbm: @@ -546,9 +552,9 @@ def gather_and_send_info(): # Publish messages to MQTT if hasattr(config, 'group_messages') and config.group_messages: - bulk_publish_to_mqtt(cpu_load, cpu_temp, used_space, voltage, sys_clock_speed, swap, memory, uptime_days, wifi_signal, wifi_signal_dbm, rpi5_fan_speed, git_update) + bulk_publish_to_mqtt(cpu_load, cpu_temp, used_space, voltage, sys_clock_speed, swap, memory, uptime_days, uptime_seconds, wifi_signal, wifi_signal_dbm, rpi5_fan_speed, git_update) else: - publish_to_mqtt(cpu_load, cpu_temp, used_space, voltage, sys_clock_speed, swap, memory, uptime_days, wifi_signal, wifi_signal_dbm, rpi5_fan_speed, git_update, update) + publish_to_mqtt(cpu_load, cpu_temp, used_space, voltage, sys_clock_speed, swap, memory, uptime_days, uptime_seconds, wifi_signal, wifi_signal_dbm, rpi5_fan_speed, git_update, update) # if not running as a service, break the loop after one iteration if not args.service: @@ -560,8 +566,8 @@ def on_message(client, userdata, msg): global exit_flag print("Received message: ", msg.payload.decode()) if msg.payload.decode() == "install": - version = check_git_version_remote(script_dir).strip() - update.do_update(version, git_update=True, config_update=True) + version = update.check_git_version_remote(script_dir).strip() + update.do_update(script_dir, version, git_update=True, config_update=True) print("Update completed. Setting exit flag...") exit_flag = True diff --git a/src/update.py b/src/update.py index e5296df..a47e23a 100644 --- a/src/update.py +++ b/src/update.py @@ -3,7 +3,6 @@ import os import subprocess import config - def get_assignments(filename): with open(filename) as f: tree = ast.parse(f.read(), filename) @@ -19,9 +18,19 @@ def update_config(current_config, example_config): missing_assignments = {var: value for var, value in example_assignments.items() if var not in current_assignments} if missing_assignments: + with open(current_config, 'ab+') as f: # Open the file in binary mode + f.seek(-1, os.SEEK_END) # Move the cursor to the last character + last_char = f.read(1) # Read the last character + + # If the last character is not a newline, write a newline + if last_char != b'\n': + with open(current_config, 'a') as f: # Open the file in text mode + f.write('\n') + + # Write the missing assignments with open(current_config, 'a') as f: for var, value in missing_assignments.items(): - f.write('\n{} = {!r}'.format(var, value)) + f.write('{} = {!r}\n'.format(var, value)) def display_config_differences(current_config, example_config, display=True): @@ -39,6 +48,13 @@ def display_config_differences(current_config, example_config, display=True): else: return False +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() + return latest_tag if latest_tag else None + + def update_config_version(version, script_dir): with open(script_dir + '/config.py', 'r') as f: lines = f.readlines() @@ -52,11 +68,10 @@ def update_config_version(version, script_dir): f.write(line) -def do_update(version=config.version, git_update=True, config_update=True): - script_dir = os.path.dirname(os.path.realpath(__file__)) +def do_update(script_dir, version=config.version, git_update=True, config_update=True): print("Current version: {}".format(config.version)) if git_update: - print(":: Updating git repository") + print(":: Updating git repository", script_dir) result = subprocess.run(['git', '-C', script_dir, 'pull'], check=True, universal_newlines=True, stdout=subprocess.PIPE) print(result.stdout) @@ -68,5 +83,6 @@ def do_update(version=config.version, git_update=True, config_update=True): update_config_version(version, script_dir) -if __name__ == '__main__': - do_update() \ No newline at end of file +if __name__ == '__main__': + script_dir = os.path.dirname(os.path.realpath(__file__)) + do_update(script_dir,check_git_version_remote(script_dir)) \ No newline at end of file