From d88229dddf5890e73c37aec4a0cd56043116b03a Mon Sep 17 00:00:00 2001 From: localhorst Date: Thu, 11 Sep 2025 21:23:10 +0200 Subject: [PATCH] only run convertion on solar power or sufficient battery --- convert/convert.py | 134 +++++++++++++++++++++++++++++++++------------ 1 file changed, 98 insertions(+), 36 deletions(-) diff --git a/convert/convert.py b/convert/convert.py index b9f6689..afd3235 100644 --- a/convert/convert.py +++ b/convert/convert.py @@ -8,34 +8,81 @@ import sys from pathlib import Path PROM_URL = "http://127.0.0.1:9104/metrics" +MIN_SOC = 0.5 # 50% +MIN_SOLAR_POWER = 500 # 500W def load_config(path): """Load JSON configuration file.""" with open(path, "r", encoding="utf-8") as f: return json.load(f) -def wait_for_solar_power(): +import requests +import time + +def wait_for_solar_power(prom_url, check_interval=300, max_retries=None): """ - Wait until the Prometheus metric `fronius_site_autonomy_ratio` equals 1.0. - Check every 5 minutes if not available. + Wait until: + - fronius_site_power_photovoltaic > 500 + - fronius_inverter_soc{inverter="1"} > 0.5 + + Args: + prom_url (str): Prometheus metrics endpoint. + check_interval (int): Seconds between checks (default: 300). + max_retries (int or None): Optional limit on checks. If None, loop indefinitely. + + Returns: + bool: True if conditions met, False if retries exhausted. """ + attempts = 0 while True: try: - r = requests.get(PROM_URL, timeout=5) - if r.status_code == 200: - for line in r.text.splitlines(): - if line.startswith("fronius_site_autonomy_ratio"): - try: - value = float(line.split()[-1]) - if value == 1.0: - print("[INFO] Solar power available – starting conversion.") - return - except ValueError: - pass - print("[INFO] No solar power – waiting 5 minutes...") + r = requests.get(prom_url, timeout=5) + r.raise_for_status() + + pv_power = None + inverter_soc = None + + for line in r.text.splitlines(): + if line.startswith("#"): # Skip comments and HELP/TYPE lines + continue + parts = line.split() + if len(parts) != 2: + continue + + metric, value_str = parts + try: + value = float(value_str) + except ValueError: + continue + + if metric == "fronius_site_power_photovoltaic": + pv_power = value + elif ( + metric.startswith("fronius_inverter_soc") + and '{inverter="1"}' in metric + ): + inverter_soc = value + + if pv_power is not None and inverter_soc is not None: + if pv_power > MIN_SOLAR_POWER and inverter_soc > MIN_SOC: + print( + f"[INFO] Solar power available: PV={pv_power:.2f} W, SOC={inverter_soc:.2f} – starting conversion." + ) + return True + + print( + f"[INFO] Conditions not met (PV={pv_power}, SOC={inverter_soc}). Waiting {check_interval} seconds..." + ) + except requests.RequestException as e: print(f"[WARN] Could not reach Prometheus: {e}") - time.sleep(300) # Wait 5 minutes + + attempts += 1 + if max_retries is not None and attempts >= max_retries: + print("[ERROR] Max retries reached. Exiting without solar power.") + return False + + time.sleep(check_interval) def analyze_codecs(oldfile, newfile, dst_folder): """ @@ -59,7 +106,7 @@ def main(): if len(sys.argv) != 2: print("Give path to config file as argument.") sys.exit(1) - + cfg = load_config(sys.argv[1]) dst_folder = Path(cfg["dst_folder"]) src_folder = Path(cfg["src_folder"]) @@ -76,36 +123,52 @@ def main(): print(f"Source: {src_file}") print(f"Temp name: {tmp_movie_name}") print(f"Final name: {movie_name}") - + # Remove leftover temporary file if tmp_dst_file.exists(): print(f"[INFO] File {tmp_dst_file} already exists. --> Delete!") tmp_dst_file.unlink() - + # Skip if final file already exists if dst_file.exists(): print(f"[INFO] Skip {dst_file}, already exists. --> Convert already done!") continue - wait_for_solar_power() + wait_for_solar_power(PROM_URL) try: cmd = [ - "taskset", "-c", "0,1,2,3", # limit to first 4 CPU cores - "ffmpeg", "-i", str(src_file), - "-c:v", "libaom-av1", - "-c:a", "libopus", - "-mapping_family", "1", - "-af", "aformat=channel_layouts=5.1", - "-c:s", "copy", - "-map", "0", - "-crf", "24", - "-b:v", "0", - "-b:a", "128k", - "-cpu-used", "4", - "-row-mt", "1", - "-tiles", "2x2", - str(tmp_dst_file) + "taskset", + "-c", + "0,1,2,3", # limit to first 4 CPU cores + "ffmpeg", + "-i", + str(src_file), + "-c:v", + "libaom-av1", + "-c:a", + "libopus", + "-mapping_family", + "1", + "-af", + "aformat=channel_layouts=5.1", + "-c:s", + "copy", + "-map", + "0", + "-crf", + "24", + "-b:v", + "0", + "-b:a", + "128k", + "-cpu-used", + "4", + "-row-mt", + "1", + "-tiles", + "2x2", + str(tmp_dst_file), ] print(f"[CMD] {' '.join(cmd)}") subprocess.run(cmd, check=True) @@ -118,7 +181,6 @@ def main(): except subprocess.CalledProcessError as e: print(f"[ERROR] Processing failed for {job}: {e}") - if __name__ == "__main__": main()