#!/usr/bin/env python3 """ python3 /var/www/nebuleair_pro_4g/power/get_throttled.py Lit l'état d'alimentation du Raspberry Pi via `vcgencmd get_throttled` et renvoie un JSON décodé. Utilisé par le Self Test (launcher.php?type=throttled) pour détecter une sous-tension (cause fréquente de capteurs USB instables, corruptions SD, reboots). Doit tourner en root (vcgencmd a besoin de /dev/vcio) : appelé via `sudo /usr/bin/python3 ...` depuis launcher.php. Bits de get_throttled (cf. doc Raspberry Pi) : 0 : sous-tension active maintenant 1 : freq ARM bridée maintenant 2 : throttling actif maintenant 3 : limite temperature douce active maintenant 16 : sous-tension survenue depuis le boot 17 : bridage freq ARM survenu depuis le boot 18 : throttling survenu depuis le boot 19 : limite temperature douce survenue depuis le boot """ import json import subprocess def main(): try: raw = subprocess.check_output( ['/usr/bin/vcgencmd', 'get_throttled'], stderr=subprocess.STDOUT, timeout=5, ).decode('utf-8', errors='ignore').strip() except FileNotFoundError: print(json.dumps({"available": False, "error": "vcgencmd introuvable (pas un Raspberry Pi ?)"})) return except Exception as e: print(json.dumps({"available": False, "error": str(e)})) return # Sortie attendue : "throttled=0x50000" if '=' not in raw: print(json.dumps({"available": False, "error": f"sortie inattendue: {raw}"})) return hex_str = raw.split('=', 1)[1].strip() try: value = int(hex_str, 16) except ValueError: print(json.dumps({"available": False, "error": f"valeur illisible: {raw}"})) return flags = { "under_voltage_now": bool(value & 0x1), "arm_freq_capped_now": bool(value & 0x2), "throttled_now": bool(value & 0x4), "soft_temp_limit_now": bool(value & 0x8), "under_voltage_occurred": bool(value & 0x10000), "arm_freq_capped_occurred": bool(value & 0x20000), "throttling_occurred": bool(value & 0x40000), "soft_temp_limit_occurred": bool(value & 0x80000), } # Niveau de gravite pour le Self Test if flags["under_voltage_now"] or flags["throttled_now"]: status = "critical" message = "Sous-tension ACTIVE — alimentation 5V insuffisante (alim/cable a remplacer)" elif flags["under_voltage_occurred"] or flags["throttling_occurred"]: status = "warning" message = "Sous-tension survenue depuis le demarrage — verifier alim 5V / cable USB" else: status = "ok" message = "Alimentation OK" result = {"available": True, "raw": hex_str, "value": value, "status": status, "message": message} result.update(flags) print(json.dumps(result)) if __name__ == "__main__": main()