question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Fan Rpm for sensors

See original GitHub issue

Feature Request

I think that a lot of us who use laptop would be happy to know about the rpm speed of the fan (usually there is only one). I got it to work in the sensors module, but I believe it is really dirty and cheap way to do it (I am a novice programmer myself). Nonetheless it works in my case.,.

"""Displays sensor temperature

Parameters:
    * sensors.path: path to temperature file (default /sys/class/thermal/thermal_zone0/temp).
    * sensors.json: if set to "true", interpret sensors.path as JSON "path" in the output
                    of "sensors -j" (i.e. <key1>/<key2>/.../<value>), for example, path could
                    be: "coretemp-isa-00000/Core 0/temp1_input" (defaults to "false")
    * sensors.match: (fallback) Line to match against output of 'sensors -u' (default: temp1_input)
    * sensors.match_pattern: (fallback) Line to match against before temperature is read (no default)
    * sensors.match_number: (fallback) which of the matches you want (default -1: last match).
"""

import re
import json
import logging

import bumblebee.util
import bumblebee.input
import bumblebee.output
import bumblebee.engine

log = logging.getLogger(__name__)

class Module(bumblebee.engine.Module):
    def __init__(self, engine, config):
        super(Module, self).__init__(engine, config,
                                     bumblebee.output.Widget(full_text=self.temperature))
        self._temperature = "unknown"
        self._mhz = "n/a"
        self._rpm = "n/a"
        self._match_number = int(self.parameter("match_number", "-1"))
        self._match_pattern = self.parameter("match_pattern", None)
        self._pattern = re.compile(r"^\s*{}:\s*([\d.]+)$".format(self.parameter("match", "temp1_input")), re.MULTILINE)
        self._match_pattern1 = self.parameter("match_pattern1", None)
        self._pattern1 = re.compile(r"^\s*{}:\s*([\d.]+)$".format(self.parameter("match1", "fan1_input")), re.MULTILINE)
        self._json = bumblebee.util.asbool(self.parameter("json", "false"))
        engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE, cmd="xsensors")
        self.determine_method()

    def determine_method(self):
        if self.parameter("path") != None and self._json == False:
            self.use_sensors = False # use thermal zone
        else:
            # try to use output of sensors -u
            try:
                output = bumblebee.util.execute("sensors -u")
                self.use_sensors = True
                log.debug("Sensors command available")
            except FileNotFoundError as e:
                log.info("Sensors command not available, using /sys/class/thermal/thermal_zone*/")
                self.use_sensors = False

    def _get_temp_from_sensors(self):
        if self._json == True:
            try:
                output = json.loads(bumblebee.util.execute("sensors -j"))
                for key in self.parameter("path").split("/"):
                    output = output[key]
                return int(float(output))
            except Exception as e:
                logging.error("unable to read sensors: {}".format(str(e)))
                return "unknown"
        else:
            output = bumblebee.util.execute("sensors -u")
            if self._match_pattern:
                temp_pattern = self.parameter("match", "temp1_input")
                match = re.search(r"{}.+{}:\s*([\d.]+)$".format(self._match_pattern, temp_pattern), output.replace("\n", ""))
                if match:
                    return int(float(match.group(1)))
                else:
                    return "unknown"
            match = self._pattern.findall(output)
            if match:
                return int(float(match[self._match_number]))
        return "unknown"

    def _get_rpm_from_sensors(self):
        output = bumblebee.util.execute("sensors -u")
        if self._match_pattern1:
            rpm_pattern = self.parameter("match1", "fan1_input")
            match1 = re.search(r"{}.+{}:\s*([\d.]+)$".format(self._match_pattern1, rpm_pattern), output.replace("\n", ""))
            if match1:
                return int(float(match1.group(1)))
            else:
                return "unknown"
        match1 = self._pattern1.findall(output)
        if match1:
            return int(float(match1[self._match_number]))
        return "unknown"

    def get_temp(self):
        if self.use_sensors:
            temperature = self._get_temp_from_sensors()
            log.debug("Retrieve temperature from sensors -u")
        else:
            try:
                temperature = open(self.parameter("path", "/sys/class/thermal/thermal_zone0/temp")).read()[:2]
                log.debug("retrieved temperature from /sys/class/")
                # TODO: Iterate through all thermal zones to determine the correct one and use its value
                # https://unix.stackexchange.com/questions/304845/discrepancy-between-number-of-cores-and-thermal-zones-in-sys-class-thermal

            except IOError:
                temperature = "unknown"
                log.info("Can not determine temperature, please install lm-sensors")

        return temperature

    def get_rpm(self):
        if self.use_sensors:
            rpm = self._get_rpm_from_sensors()
            log.debug("Retrieve RPM from sensors -u")

        return rpm


    def get_mhz(self):
        try:
            output = open("/sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq").read()
            mhz = int(float(output)/1000.0)
        except:
            output = open("/proc/cpuinfo").read()
            m = re.search(r"cpu MHz\s+:\s+(\d+)", output)
            mhz = int(m.group(1))

        if mhz < 1000:
            return "{} MHz".format(mhz)
        else:
            return "{:0.01f} GHz".format(float(mhz)/1000.0)

    def temperature(self, _):
        return u"{}°c @ {}rpm and {}".format(self._temperature, self._rpm ,self._mhz)

    def update(self, widgets):
        self._temperature = self.get_temp()
        self._rpm = self.get_rpm()
        self._mhz = self.get_mhz()

Summary

Fan speed would be a great request.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
martindoublemcommented, Nov 16, 2018

Really sorry, It is my first time submitting a suggestion to github and I can’t get the code insert to work properly

0reactions
tobi-wan-kenobicommented, Nov 17, 2018

Hope this works for you! Please let me know how the new module (sensors2) works for you.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Sensor to measure Fan RPM - TI E2E - Texas Instruments
It provides the capability to measure the RPM of a 12V fan as well as measure temperature from a remote junction or the...
Read more >
Monitoring Fan Speed with a Speed Switch
A Speed Switch can assure positive fan operation and indicate slowdown or stoppage due to belt slippage, clogged air filters, or other mechanical...
Read more >
Easy Guide to Sensor Feedback on Cooling Fan ...
As its name implies, a low-speed sensor's signal will switch when the rotation speed of the fan falls below a preset threshold, e.g.,...
Read more >
Fan RPM With Internal Hall Effect Sensor and Arduino ...
The working is simple in principle. The hall effect sensor generates signal when the magnets connected to its rotor shaft (internally). Depending on...
Read more >
Raven Precision Fan RPM Sensor Kit - SpraySmarter.com
This Raven Fan RPM Sensor Kit is designed to measure the RPM of the desired fan. Sku: 117-0159-575. Qty: Add to Cart.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found