diff --git a/library/sensors/sensors_librehardwaremonitor.py b/library/sensors/sensors_librehardwaremonitor.py index 29436e3d..791cee3d 100644 --- a/library/sensors/sensors_librehardwaremonitor.py +++ b/library/sensors/sensors_librehardwaremonitor.py @@ -176,7 +176,8 @@ class Cpu(sensors.Cpu): def percentage(interval: float) -> float: cpu = get_hw_and_update(Hardware.HardwareType.Cpu) for sensor in cpu.Sensors: - if sensor.SensorType == Hardware.SensorType.Load and str(sensor.Name).startswith("CPU Total"): + if sensor.SensorType == Hardware.SensorType.Load and str(sensor.Name).startswith( + "CPU Total") and sensor.Value is not None: return float(sensor.Value) logger.error("CPU load cannot be read") @@ -186,19 +187,22 @@ def percentage(interval: float) -> float: def frequency() -> float: frequencies = [] cpu = get_hw_and_update(Hardware.HardwareType.Cpu) - for sensor in cpu.Sensors: - if sensor.SensorType == Hardware.SensorType.Clock: - # Keep only real core clocks, ignore effective core clocks - if "Core #" in str(sensor.Name) and "Effective" not in str(sensor.Name): - if sensor.Value: + try: + for sensor in cpu.Sensors: + if sensor.SensorType == Hardware.SensorType.Clock: + # Keep only real core clocks, ignore effective core clocks + if "Core #" in str(sensor.Name) and "Effective" not in str( + sensor.Name) and sensor.Value is not None: frequencies.append(float(sensor.Value)) - if frequencies: - # Take mean of all core clock as "CPU clock" (as it is done in Windows Task Manager Performance tab) - return mean(frequencies) - else: - # Frequencies reading is not supported on this CPU - return math.nan + if frequencies: + # Take mean of all core clock as "CPU clock" (as it is done in Windows Task Manager Performance tab) + return mean(frequencies) + except: + pass + + # Frequencies reading is not supported on this CPU + return math.nan @staticmethod def load() -> Tuple[float, float, float]: # 1 / 5 / 15min avg (%): @@ -208,22 +212,29 @@ def load() -> Tuple[float, float, float]: # 1 / 5 / 15min avg (%): @staticmethod def temperature() -> float: cpu = get_hw_and_update(Hardware.HardwareType.Cpu) - # By default, the average temperature of all CPU cores will be used - for sensor in cpu.Sensors: - if sensor.SensorType == Hardware.SensorType.Temperature and str(sensor.Name).startswith("Core Average"): - return float(sensor.Value) - # If not available, the max core temperature will be used - for sensor in cpu.Sensors: - if sensor.SensorType == Hardware.SensorType.Temperature and str(sensor.Name).startswith("Core Max"): - return float(sensor.Value) - # If not available, the CPU Package temperature (usually same as max core temperature) will be used - for sensor in cpu.Sensors: - if sensor.SensorType == Hardware.SensorType.Temperature and str(sensor.Name).startswith("CPU Package"): - return float(sensor.Value) - # Otherwise any sensor named "Core..." will be used - for sensor in cpu.Sensors: - if sensor.SensorType == Hardware.SensorType.Temperature and str(sensor.Name).startswith("Core"): - return float(sensor.Value) + try: + # By default, the average temperature of all CPU cores will be used + for sensor in cpu.Sensors: + if sensor.SensorType == Hardware.SensorType.Temperature and str(sensor.Name).startswith( + "Core Average") and sensor.Value is not None: + return float(sensor.Value) + # If not available, the max core temperature will be used + for sensor in cpu.Sensors: + if sensor.SensorType == Hardware.SensorType.Temperature and str(sensor.Name).startswith( + "Core Max") and sensor.Value is not None: + return float(sensor.Value) + # If not available, the CPU Package temperature (usually same as max core temperature) will be used + for sensor in cpu.Sensors: + if sensor.SensorType == Hardware.SensorType.Temperature and str(sensor.Name).startswith( + "CPU Package") and sensor.Value is not None: + return float(sensor.Value) + # Otherwise any sensor named "Core..." will be used + for sensor in cpu.Sensors: + if sensor.SensorType == Hardware.SensorType.Temperature and str(sensor.Name).startswith( + "Core") and sensor.Value is not None: + return float(sensor.Value) + except: + pass return math.nan @@ -235,7 +246,7 @@ def fan_percent() -> float: sh.Update() for sensor in sh.Sensors: if sensor.SensorType == Hardware.SensorType.Control and "#2" in str( - sensor.Name): # Is Motherboard #2 Fan always the CPU Fan ? + sensor.Name) and sensor.Value is not None: # Is Motherboard #2 Fan always the CPU Fan ? return float(sensor.Value) except: pass @@ -275,23 +286,28 @@ def stats(cls) -> Tuple[float, float, float, float]: # load (%) / used mem (%) temp = math.nan for sensor in gpu_to_use.Sensors: - if sensor.SensorType == Hardware.SensorType.Load and str(sensor.Name).startswith("GPU Core"): + if sensor.SensorType == Hardware.SensorType.Load and str(sensor.Name).startswith( + "GPU Core") and sensor.Value is not None: load = float(sensor.Value) elif sensor.SensorType == Hardware.SensorType.Load and str(sensor.Name).startswith("D3D 3D") and math.isnan( - load): + load) and sensor.Value is not None: # Only use D3D usage if global "GPU Core" sensor is not available, because it is less # precise and does not cover the entire GPU: https://www.hwinfo.com/forum/threads/what-is-d3d-usage.759/ load = float(sensor.Value) - elif sensor.SensorType == Hardware.SensorType.SmallData and str(sensor.Name).startswith("GPU Memory Used"): + elif sensor.SensorType == Hardware.SensorType.SmallData and str(sensor.Name).startswith( + "GPU Memory Used") and sensor.Value is not None: used_mem = float(sensor.Value) elif sensor.SensorType == Hardware.SensorType.SmallData and str(sensor.Name).startswith( - "D3D") and str(sensor.Name).endswith("Memory Used") and math.isnan(used_mem): + "D3D") and str(sensor.Name).endswith("Memory Used") and math.isnan( + used_mem) and sensor.Value is not None: # Only use D3D memory usage if global "GPU Memory Used" sensor is not available, because it is less # precise and does not cover the entire GPU: https://www.hwinfo.com/forum/threads/what-is-d3d-usage.759/ used_mem = float(sensor.Value) - elif sensor.SensorType == Hardware.SensorType.SmallData and str(sensor.Name).startswith("GPU Memory Total"): + elif sensor.SensorType == Hardware.SensorType.SmallData and str(sensor.Name).startswith( + "GPU Memory Total") and sensor.Value is not None: total_mem = float(sensor.Value) - elif sensor.SensorType == Hardware.SensorType.Temperature and str(sensor.Name).startswith("GPU Core"): + elif sensor.SensorType == Hardware.SensorType.Temperature and str(sensor.Name).startswith( + "GPU Core") and sensor.Value is not None: temp = float(sensor.Value) return load, (used_mem / total_mem * 100.0), used_mem, temp @@ -303,12 +319,16 @@ def fps(cls) -> int: # GPU not supported return -1 - for sensor in gpu_to_use.Sensors: - if sensor.SensorType == Hardware.SensorType.Factor and "FPS" in str(sensor.Name): - # If a reading returns a value <= 0, returns old value instead - if int(sensor.Value) > 0: - cls.prev_fps = int(sensor.Value) - return cls.prev_fps + try: + for sensor in gpu_to_use.Sensors: + if sensor.SensorType == Hardware.SensorType.Factor and "FPS" in str( + sensor.Name) and sensor.Value is not None: + # If a reading returns a value <= 0, returns old value instead + if int(sensor.Value) > 0: + cls.prev_fps = int(sensor.Value) + return cls.prev_fps + except: + pass # No FPS sensor for this GPU model return -1 @@ -322,9 +342,8 @@ def fan_percent(cls) -> float: try: for sensor in gpu_to_use.Sensors: - if sensor.SensorType == Hardware.SensorType.Control: - if sensor.Value: - return float(sensor.Value) + if sensor.SensorType == Hardware.SensorType.Control and sensor.Value is not None: + return float(sensor.Value) except: pass @@ -342,9 +361,8 @@ def frequency(cls) -> float: for sensor in gpu_to_use.Sensors: if sensor.SensorType == Hardware.SensorType.Clock: # Keep only real core clocks, ignore effective core clocks - if "Core" in str(sensor.Name) and "Effective" not in str(sensor.Name): - if sensor.Value: - return float(sensor.Value) + if "Core" in str(sensor.Name) and "Effective" not in str(sensor.Name) and sensor.Value is not None: + return float(sensor.Value) except: pass @@ -369,14 +387,17 @@ def swap_percent() -> float: # Get virtual / physical memory stats for sensor in memory.Sensors: - if sensor.SensorType == Hardware.SensorType.Data and str(sensor.Name).startswith("Virtual Memory Used"): + if sensor.SensorType == Hardware.SensorType.Data and str(sensor.Name).startswith( + "Virtual Memory Used") and sensor.Value is not None: virtual_mem_used = int(sensor.Value) - elif sensor.SensorType == Hardware.SensorType.Data and str(sensor.Name).startswith("Memory Used"): + elif sensor.SensorType == Hardware.SensorType.Data and str(sensor.Name).startswith( + "Memory Used") and sensor.Value is not None: mem_used = int(sensor.Value) elif sensor.SensorType == Hardware.SensorType.Data and str(sensor.Name).startswith( - "Virtual Memory Available"): + "Virtual Memory Available") and sensor.Value is not None: virtual_mem_available = int(sensor.Value) - elif sensor.SensorType == Hardware.SensorType.Data and str(sensor.Name).startswith("Memory Available"): + elif sensor.SensorType == Hardware.SensorType.Data and str(sensor.Name).startswith( + "Memory Available") and sensor.Value is not None: mem_available = int(sensor.Value) # Compute swap stats from virtual / physical memory stats @@ -395,7 +416,8 @@ def swap_percent() -> float: def virtual_percent() -> float: memory = get_hw_and_update(Hardware.HardwareType.Memory) for sensor in memory.Sensors: - if sensor.SensorType == Hardware.SensorType.Load and str(sensor.Name).startswith("Memory"): + if sensor.SensorType == Hardware.SensorType.Load and str(sensor.Name).startswith( + "Memory") and sensor.Value is not None: return float(sensor.Value) return math.nan @@ -404,7 +426,8 @@ def virtual_percent() -> float: def virtual_used() -> int: # In bytes memory = get_hw_and_update(Hardware.HardwareType.Memory) for sensor in memory.Sensors: - if sensor.SensorType == Hardware.SensorType.Data and str(sensor.Name).startswith("Memory Used"): + if sensor.SensorType == Hardware.SensorType.Data and str(sensor.Name).startswith( + "Memory Used") and sensor.Value is not None: return int(sensor.Value * 1000000000.0) return 0 @@ -413,7 +436,8 @@ def virtual_used() -> int: # In bytes def virtual_free() -> int: # In bytes memory = get_hw_and_update(Hardware.HardwareType.Memory) for sensor in memory.Sensors: - if sensor.SensorType == Hardware.SensorType.Data and str(sensor.Name).startswith("Memory Available"): + if sensor.SensorType == Hardware.SensorType.Data and str(sensor.Name).startswith( + "Memory Available") and sensor.Value is not None: return int(sensor.Value * 1000000000.0) return 0 @@ -449,16 +473,17 @@ def stats(if_name, interval) -> Tuple[ net_if = get_net_interface_and_update(if_name) if net_if is not None: for sensor in net_if.Sensors: - if sensor.SensorType == Hardware.SensorType.Data and str(sensor.Name).startswith("Data Uploaded"): + if sensor.SensorType == Hardware.SensorType.Data and str(sensor.Name).startswith( + "Data Uploaded") and sensor.Value is not None: uploaded = int(sensor.Value * 1000000000.0) elif sensor.SensorType == Hardware.SensorType.Data and str(sensor.Name).startswith( - "Data Downloaded"): + "Data Downloaded") and sensor.Value is not None: downloaded = int(sensor.Value * 1000000000.0) elif sensor.SensorType == Hardware.SensorType.Throughput and str(sensor.Name).startswith( - "Upload Speed"): + "Upload Speed") and sensor.Value is not None: upload_rate = int(sensor.Value) elif sensor.SensorType == Hardware.SensorType.Throughput and str(sensor.Name).startswith( - "Download Speed"): + "Download Speed") and sensor.Value is not None: download_rate = int(sensor.Value) return upload_rate, uploaded, download_rate, downloaded diff --git a/library/sensors/sensors_python.py b/library/sensors/sensors_python.py index dbde7292..a312baa3 100644 --- a/library/sensors/sensors_python.py +++ b/library/sensors/sensors_python.py @@ -98,15 +98,24 @@ def sensors_fans_percent(): class Cpu(sensors.Cpu): @staticmethod def percentage(interval: float) -> float: - return psutil.cpu_percent(interval=interval) + try: + return psutil.cpu_percent(interval=interval) + except: + return math.nan @staticmethod def frequency() -> float: - return psutil.cpu_freq().current + try: + return psutil.cpu_freq().current + except: + return math.nan @staticmethod def load() -> Tuple[float, float, float]: # 1 / 5 / 15min avg (%): - return psutil.getloadavg() + try: + return psutil.getloadavg() + except: + return math.nan, math.nan, math.nan @staticmethod def temperature() -> float: @@ -369,37 +378,57 @@ def is_available() -> bool: class Memory(sensors.Memory): @staticmethod def swap_percent() -> float: - return psutil.swap_memory().percent + try: + return psutil.swap_memory().percent + except: + return math.nan @staticmethod def virtual_percent() -> float: - return psutil.virtual_memory().percent + try: + return psutil.virtual_memory().percent + except: + return math.nan @staticmethod def virtual_used() -> int: # In bytes - # Do not use psutil.virtual_memory().used: from https://psutil.readthedocs.io/en/latest/#memory - # "It is calculated differently depending on the platform and designed for informational purposes only" - return psutil.virtual_memory().total - psutil.virtual_memory().available + try: + # Do not use psutil.virtual_memory().used: from https://psutil.readthedocs.io/en/latest/#memory + # "It is calculated differently depending on the platform and designed for informational purposes only" + return psutil.virtual_memory().total - psutil.virtual_memory().available + except: + return -1 @staticmethod def virtual_free() -> int: # In bytes - # Do not use psutil.virtual_memory().free: from https://psutil.readthedocs.io/en/latest/#memory - # "note that this doesn’t reflect the actual memory available (use available instead)." - return psutil.virtual_memory().available - + try: + # Do not use psutil.virtual_memory().free: from https://psutil.readthedocs.io/en/latest/#memory + # "note that this doesn’t reflect the actual memory available (use available instead)." + return psutil.virtual_memory().available + except: + return -1 class Disk(sensors.Disk): @staticmethod def disk_usage_percent() -> float: - return psutil.disk_usage("/").percent + try: + return psutil.disk_usage("/").percent + except: + return math.nan @staticmethod def disk_used() -> int: # In bytes - return psutil.disk_usage("/").used + try: + return psutil.disk_usage("/").used + except: + return -1 @staticmethod def disk_free() -> int: # In bytes - return psutil.disk_usage("/").free + try: + return psutil.disk_usage("/").free + except: + return -1 class Net(sensors.Net): @@ -407,27 +436,30 @@ class Net(sensors.Net): def stats(if_name, interval) -> Tuple[ int, int, int, int]: # up rate (B/s), uploaded (B), dl rate (B/s), downloaded (B) global PNIC_BEFORE - # Get current counters - pnic_after = psutil.net_io_counters(pernic=True) - - upload_rate = 0 - uploaded = 0 - download_rate = 0 - downloaded = 0 - - if if_name != "": - if if_name in pnic_after: - try: - upload_rate = (pnic_after[if_name].bytes_sent - PNIC_BEFORE[if_name].bytes_sent) / interval - uploaded = pnic_after[if_name].bytes_sent - download_rate = (pnic_after[if_name].bytes_recv - PNIC_BEFORE[if_name].bytes_recv) / interval - downloaded = pnic_after[if_name].bytes_recv - except: - # Interface might not be in PNIC_BEFORE for now - pass - - PNIC_BEFORE.update({if_name: pnic_after[if_name]}) - else: - logger.warning("Network interface '%s' not found. Check names in config.yaml." % if_name) - - return upload_rate, uploaded, download_rate, downloaded + try: + # Get current counters + pnic_after = psutil.net_io_counters(pernic=True) + + upload_rate = 0 + uploaded = 0 + download_rate = 0 + downloaded = 0 + + if if_name != "": + if if_name in pnic_after: + try: + upload_rate = (pnic_after[if_name].bytes_sent - PNIC_BEFORE[if_name].bytes_sent) / interval + uploaded = pnic_after[if_name].bytes_sent + download_rate = (pnic_after[if_name].bytes_recv - PNIC_BEFORE[if_name].bytes_recv) / interval + downloaded = pnic_after[if_name].bytes_recv + except: + # Interface might not be in PNIC_BEFORE for now + pass + + PNIC_BEFORE.update({if_name: pnic_after[if_name]}) + else: + logger.warning("Network interface '%s' not found. Check names in config.yaml." % if_name) + + return upload_rate, uploaded, download_rate, downloaded + except: + return -1, -1, -1, -1