Simple KDE4 fan control widget

From juliano.info

Jump to: navigation, search
SimpleFanControl-01.png

My motherboard comes equipped with a W83627EHF sensor chip, which is supported by Linux via the w83627ehf module. It was automatically detected and configured by lm-sensors. The chip has an adjustable PWM output that allows the user to control system fan speeds. The Linux kernel module exports these controls through pwm* files under /sys/class/hwmon/hwmon0/device/. Writing an integer in the 0-255 range to any of these files changes the PWM output of that fan, altering its rotation.

I usually don't bother with system fan speeds, but my current CPU fan produces a particularly annoying noise at ~3300 RPM and above. Sometimes I want to manually adjust it in order to reduce the noise.

I decided to create this widget for two reasons: to have a nice and easy way to adjust the CPU fan speed, without having to manually issue commands every time; and to have a quick look on how it is to develop Plasma widgets (Plasmoids), specially through its Python bindings.

I used the Python Plasmoid Example as a basis. In my case, I wanted a very simple control: a dial or slider to set the output, and a label to display the current value. In less than 30 minutes I had this:

#!/usr/bin/env python
# Simple Fan Control, v0.0.1 (2009-08-09)
 
class SimpleFanControl(plasmascript.Applet):
	pwmfile = "/sys/class/hwmon/hwmon0/device/pwm2"
 
	def __init__(self, parent, args=None):
		plasmascript.Applet.__init__(self, parent)
 
	def init(self):
		self.setHasConfigurationInterface(False)
		self.setAspectRatioMode(Plasma.IgnoreAspectRatio)
		self.setBackgroundHints(Plasma.Applet.DefaultBackground)
 
		self.layout = QGraphicsLinearLayout(Qt.Vertical, self.applet)
		self.layout.setContentsMargins(0, 0, 0, 0)
		self.layout.setSpacing(0)
		self.setLayout(self.layout)
 
		current = self.getCurrent()
 
		self.label = Plasma.Label(self.applet)
		self.label.setText(str(current))
		self.layout.addItem(self.label)
 
		self.slider = Plasma.Slider(self.applet)
		self.slider.setRange(0, 255)
		self.slider.setValue(current)
		self.slider.nativeWidget().setTracking(False)
		QObject.connect(self.slider, SIGNAL("sliderMoved(int)"), self.sliderMoved)
		QObject.connect(self.slider, SIGNAL("valueChanged(int)"), self.valueChanged)
		self.layout.addItem(self.slider)
 
	def sliderMoved(self, value):
		self.label.setText(str(value))
 
	def valueChanged(self, value):
		self.label.setText(str(value))
		pwm = open(self.pwmfile, 'w')
		pwm.write(str(value))
		pwm.close()
 
 	def getCurrent(self):
		pwm = open(self.pwmfile, 'r')
		value = int(pwm.readline().strip())
		pwm.close()
		return value
 
def CreateApplet(parent):
	return SimpleFanControl(parent)

Like I said, it is really simple; the device controlled by the widget is hard-coded in the script, no configuration is provided. It was just a quick personal "proof-of-concept", and it worked!

I liked the simplicity. With about 50 lines of code it is possible to have a functional slider widget that controls some random system variable.

The current widget has many limitations, though:

  • The control file path is hard-coded, no configuration available.
  • It doesn't update itself if the value is changed by other means.
  • The slider orientation is fixed, vertical.
    • It also doesn't detect when it is placed on a panel, so it could reorient itself.

Since I created it just to serve my own needs, I didn't test it with any other configurations and I don't intend to maintain it (my next motherboard may not have the same feature), I won't upload it to KDE. I'm just publishing it here for reference. Fell free to use or modify it, at your own risk.

Download: http://hg.juliano.info/simple-fan-control/ (Mercurial repository)


Icon Crystal Warning.png
Users are advised to be careful when manually controlling system fan speeds. Insufficient fan rotation may cause permanent hardware damage.
Views