added hwmon alias map

linux kernel does not guarantee order of hwmon devices, so use alias instead that gets replaced with teh correct hwmonX, based on hwmonX/name
This commit is contained in:
2019-09-11 14:43:49 +02:00
parent 0bd909d157
commit 67ba3d8fca
3 changed files with 81 additions and 65 deletions

2
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,2 @@
# Default ignored files
/workspace.xml

View File

@@ -1,26 +1,26 @@
loglevel: DEBUG loglevel: DEBUG
thermalzones: thermalzones:
- - name: GPU+SYSTEM
name: GPU+SYSTEM hwmon: amdgpu
source: hwmon3/temp1_input source: temp1_input
factor: 1000 factor: 1000
fan: fan:
- hwmon2/pwm2 - it8686/pwm2
- hwmon3/pwm1: 170 - amdgpu/pwm1: 170
target: 60 target: 60
pid: pid:
p: 1 p: 1
i: 1.5 i: 1
d: 2 d: 1.5
- - name: CPU
name: CPU hwmon: it8686
source: hwmon1/temp1_input source: coretemp/temp1_input
factor: 1000 factor: 1000
fan: fan:
- hwmon2/pwm1 - it8686/pwm1
target: 50 target: 50
pid: pid:
p: 1 p: 1
i: 1.5 i: 1
d: 2 d: 1.5

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
import glob
import logging import logging
import re
import sys import sys
from time import sleep from time import sleep
@@ -10,42 +11,28 @@ from simple_pid import PID
SYSFS_HWMON_BASE = "/sys/class/hwmon/" SYSFS_HWMON_BASE = "/sys/class/hwmon/"
def build_pwm_path(specific):
return SYSFS_HWMON_BASE + specific
def write_sysfs(path, value):
with open(build_pwm_path(path), 'w') as sysfs_f:
sysfs_f.write(str(value))
def read_sysfs(path):
with open(build_pwm_path(path)) as sysfs_f:
return sysfs_f.readline()
def set_pwm_mode(path, value=1):
write_sysfs(path + "_enable", value)
class ThermalZone: class ThermalZone:
def __init__(self, temp_source, fans, p, i, d, target, factor, name) -> None: def __init__(self, config, hwmon_map) -> None:
self.fans = fans self.fans = config["fan"]
self.temp_source = temp_source self.temp_source = config["source"]
self.pid = PID(p, i, d, setpoint=0) self.pid = PID(config["pid"]["p"], config["pid"]["i"], config["pid"]["d"], setpoint=0)
self.pid.output_limits = (0, 255) self.pid.output_limits = (0, 255)
self.factor = 1 / factor self.factor = 1 / config["factor"]
self.name = name self.name = config["name"]
self.target = target self.target = config["target"]
self.hwname = config["hwmon"]
self.hwmap = hwmon_map
self.alias_replace = re.compile(r'\b(' + '|'.join(re.escape(key) for key in self.hwmap.keys()) + r')\b')
self.setup_pwm() self.setup_pwm()
logging.getLogger("pyfan").info( logging.getLogger("pyfan").info(
"[{zone}] Source={source} Fans={fans} Factor={factor} PID={pid}".format(zone=name, "[{zone}] Source={source} Fans={fans} Factor={factor} PID={pid}".format(zone=self.name,
source=temp_source, source=self.temp_source,
fans=fans, fans=self.fans,
factor=factor, factor=self.factor,
pid=( pid=(
p, i, d))) self.pid.Kp, self.pid.Ki,
self.pid.Kd)))
def eval(self): def eval(self):
diff = self.target - self.get_temp() diff = self.target - self.get_temp()
@@ -54,9 +41,9 @@ class ThermalZone:
try: try:
for target_fan in self.fans: for target_fan in self.fans:
if type(target_fan) is dict: if type(target_fan) is dict:
write_sysfs(list(target_fan.keys())[0], min(int(val), list(target_fan.values())[0])) self.write_sysfs(list(target_fan.keys())[0], min(int(val), list(target_fan.values())[0]))
else: else:
write_sysfs(target_fan, int(val)) self.write_sysfs(target_fan, int(val))
except OSError as err: except OSError as err:
logging.getLogger("pyfan").warning( logging.getLogger("pyfan").warning(
"[%s] Failed to set pwm, trying to reset it. (%s)" % (self.name, err.strerror)) "[%s] Failed to set pwm, trying to reset it. (%s)" % (self.name, err.strerror))
@@ -71,7 +58,7 @@ class ThermalZone:
d=int(d))) d=int(d)))
def get_temp(self): def get_temp(self):
return float(read_sysfs(self.temp_source)) * self.factor return float(self.read_sysfs(self.temp_source)) * self.factor
def restore(self): def restore(self):
self.setup_pwm(2) self.setup_pwm(2)
@@ -80,12 +67,31 @@ class ThermalZone:
for target_fan in self.fans: for target_fan in self.fans:
try: try:
if type(target_fan) is dict: if type(target_fan) is dict:
set_pwm_mode(list(target_fan.keys())[0], value) self.set_pwm_mode(list(target_fan.keys())[0], value)
else: else:
set_pwm_mode(target_fan, value) self.set_pwm_mode(target_fan, value)
except FileNotFoundError as err: except FileNotFoundError as err:
logging.getLogger("pyfan").warning("[%s] pwm not found. Not ready yet or wrong path? (%s)" % self.name, logging.getLogger("pyfan").warning("[%s] pwm not found. Not ready yet or wrong path? (%s)" % (self.name,
err.strerror) err.strerror))
def replace_alias(self, path):
replaced = self.alias_replace.sub(lambda x: self.hwmap[x.group()], path)
logging.getLogger("pyfan").debug("[ALIAS] %s -> %s" % (path, replaced))
return replaced
def build_pwm_path(self, specific):
return self.replace_alias(SYSFS_HWMON_BASE + specific)
def write_sysfs(self, path, value):
with open(self.build_pwm_path(path), 'w') as sysfs_f:
sysfs_f.write(str(value))
def read_sysfs(self, path):
with open(self.build_pwm_path(path)) as sysfs_f:
return sysfs_f.readline()
def set_pwm_mode(self, path, value=1):
self.write_sysfs(path + "_enable", value)
class PyFan: class PyFan:
@@ -93,12 +99,11 @@ class PyFan:
self.config = self.__load_config(config) self.config = self.__load_config(config)
logging.basicConfig(level=logging.getLevelName(self.config["loglevel"])) logging.basicConfig(level=logging.getLevelName(self.config["loglevel"]))
self.zones = [] self.zones = []
self.hwmon_map = {}
self.gen_hwmon_map()
for zone in self.config["thermalzones"]: for zone in self.config["thermalzones"]:
self.zones.append( self.zones.append(ThermalZone(zone, self.hwmon_map))
ThermalZone(zone["source"], zone["fan"], zone["pid"]["p"], zone["pid"]["i"], zone["pid"]["d"],
zone["target"],
zone["factor"], zone["name"]))
logging.getLogger("pyfan").info("Finished creating %d thermal zones." % len(self.zones)) logging.getLogger("pyfan").info("Finished creating %d thermal zones." % len(self.zones))
@@ -118,6 +123,15 @@ class PyFan:
with open(path) as cfg_file: with open(path) as cfg_file:
return yaml.safe_load(cfg_file) return yaml.safe_load(cfg_file)
def gen_hwmon_map(self):
names = glob.glob(SYSFS_HWMON_BASE + "hwmon*/name")
for name in names:
hwmon = name.split("/")[-2]
with open(name) as file:
hwname = file.read()
self.hwmon_map[hwname] = hwmon
if __name__ == "__main__": if __name__ == "__main__":
with PyFan() as pyfan: with PyFan() as pyfan: