[modules/sensors] Add support for JSON-formatted sensors output

sensors -j give JSON output, which is much easier to parse than
raw output.

Use this, together with the "path" parameter, to allow robust reading of
sensor values.

fixes #308
This commit is contained in:
Tobias Witek 2018-11-07 16:46:49 +01:00
parent 7b12f678d6
commit c39e2077e3

View file

@ -5,12 +5,16 @@
Parameters: Parameters:
* sensors.path: path to temperature file (default /sys/class/thermal/thermal_zone0/temp). * 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: (fallback) Line to match against output of 'sensors -u' (default: temp1_input)
* sensors.match_number: (fallback) which of the matches you want (default -1: last match). * sensors.match_number: (fallback) which of the matches you want (default -1: last match).
""" """
import re import re
import json
import logging import logging
import bumblebee.util import bumblebee.util
@ -28,11 +32,12 @@ class Module(bumblebee.engine.Module):
self._mhz = "n/a" self._mhz = "n/a"
self._match_number = int(self.parameter("match_number", "-1")) self._match_number = int(self.parameter("match_number", "-1"))
self._pattern = re.compile(r"^\s*{}:\s*([\d.]+)$".format(self.parameter("match", "temp1_input")), re.MULTILINE) self._pattern = re.compile(r"^\s*{}:\s*([\d.]+)$".format(self.parameter("match", "temp1_input")), re.MULTILINE)
self._json = bumblebee.util.asbool(self.parameter("json", "false"))
engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE, cmd="xsensors") engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE, cmd="xsensors")
self.determine_method() self.determine_method()
def determine_method(self): def determine_method(self):
if self.parameter("path") != None: if self.parameter("path") != None and self._json == False:
self.use_sensors = False # use thermal zone self.use_sensors = False # use thermal zone
else: else:
# try to use output of sensors -u # try to use output of sensors -u
@ -45,10 +50,20 @@ class Module(bumblebee.engine.Module):
self.use_sensors = False self.use_sensors = False
def _get_temp_from_sensors(self): def _get_temp_from_sensors(self):
output = bumblebee.util.execute("sensors -u") if self._json == True:
match = self._pattern.findall(output) try:
if match: output = json.loads(bumblebee.util.execute("sensors -j"))
return int(float(match[self._match_number])) 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")
match = self._pattern.findall(output)
if match:
return int(float(match[self._match_number]))
return "unknown" return "unknown"
def get_temp(self): def get_temp(self):