Coverage for linuxpy/thermal.py: 71%
58 statements
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-13 08:09 +0200
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-13 08:09 +0200
1#
2# This file is part of the linuxpy project
3#
4# Copyright (c) 2023 Tiago Coutinho
5# Distributed under the GPLv3 license. See LICENSE for more info.
7"""
8Human friendly interface to linux thermal subsystem.
10The heart of linuxpy thermal library are the [`ThermalZone`][linuxpy.thermal.ThermalZone]
11and [`CoolingDevice`][linuxpy.thermal.CoolingDevice] classes.
13Probably the most common way to create a thermal device is through
14the [`find`][linuxpy.thermal.find] helper:
16```python
17with find(type="x86_pkg_temp") as tz:
18 print(f"X86 temperature: {tz.temperature/1000:6.2f} C")
19```
20"""
22import pathlib
24from linuxpy.device import device_number
25from linuxpy.sysfs import THERMAL_PATH, Attr, Device, Int, Mode, Str
26from linuxpy.types import Callable, Iterable, Optional, Union
27from linuxpy.util import make_find
30class ThermalZone(Device):
31 """
32 Thermal sensor
34 Attributes:
35 type (str): thermal zone type
36 policy (str): the policy
37 available_policies list[str]: list of available policies
38 temperature (int): current temperature in milli-celsius
39 offset (int): offet in milli-celsius
40 mode (Mode): current mode (enabled/disabled)
41 device_number (int): thermal device number
42 trip_points (list[TripPoint]): list of trip points (new list every time)
43 """
45 type = Str("type")
46 policy = Str("policy")
47 available_policies = Attr("available_policies", str.split)
48 temperature = Int("temp")
49 offset = Int("offset")
50 mode = Attr("mode", Mode)
52 @classmethod
53 def from_id(cls, n):
54 return cls.from_syspath(THERMAL_PATH / f"thermal_zone{n}")
56 @property
57 def trip_points(self):
58 result = []
59 for temp_path in self.syspath.glob("trip_point_*_temp"):
60 type_path = temp_path.with_name(temp_path.name.replace("_temp", "_type"))
61 result.append(TripPoint(temp_path, type_path))
62 return result
64 @property
65 def device_number(self) -> Optional[int]:
66 return device_number(self.syspath)
69class TripPoint:
70 """
71 Trip point associated with the thermal zone
73 Attributes:
74 temperature (int): trip point temperature in milli-celsius
75 type (str): trip point type
76 """
78 def __init__(self, temperature_path, type_path):
79 self.temperature_path = temperature_path
80 self.type_path = type_path
82 @property
83 def temperature(self) -> int:
84 with self.temperature_path.open() as f:
85 return int(f.read())
87 @property
88 def type(self) -> str:
89 with self.type_path.open() as f:
90 return f.read().strip()
93class CoolingDevice(Device):
94 """
95 Cooling device (fan, processor, ...)
97 Attributes:
98 type (str): thermal zone type
99 """
101 type = Str("type")
102 state = Int("cur_state")
103 max_state = Int("max_state")
105 @property
106 def device_number(self) -> Optional[int]:
107 return device_number(self.syspath)
110def iter_thermal_zone_paths() -> Iterable[pathlib.Path]:
111 """Returns an iterator over all thermal zone paths"""
112 yield from THERMAL_PATH.glob("thermal_zone*")
115def iter_thermal_zone_devices() -> Iterable[ThermalZone]:
116 """Returns an iterator over all thermal zone devices"""
117 return (ThermalZone.from_syspath(path) for path in iter_thermal_zone_paths())
120def iter_cooling_device_paths() -> Iterable[pathlib.Path]:
121 """Returns an iterator over all cooling device paths"""
122 yield from THERMAL_PATH.glob("cooling_device*")
125def iter_cooling_devices() -> Iterable[CoolingDevice]:
126 """Returns an iterator over all cooling devices"""
127 return (CoolingDevice.from_syspath(path) for path in iter_cooling_device_paths())
130def iter_devices() -> Iterable[Union[ThermalZone, CoolingDevice]]:
131 """Returns an iterator over all thermal and cooling devices"""
132 yield from iter_thermal_zone_devices()
133 yield from iter_cooling_devices()
136_find = make_find(iter_devices)
139def find(
140 find_all: bool = False, custom_match: Optional[Callable] = None, **kwargs
141) -> Union[Device, Iterable[Device], None]:
142 """
143 If find_all is False:
145 Find a device follwing the criteria matched by custom_match and kwargs.
146 If no device is found matching the criteria it returns None.
147 Default is to return a random first device.
149 If find_all is True:
151 The result is an iterator.
152 Find all devices that match the criteria custom_match and kwargs.
153 If no device is found matching the criteria it returns an empty iterator.
154 Default is to return an iterator over all input devices found on the system.
155 """
156 return _find(find_all, custom_match, **kwargs)