Added new sensors.py and dropped borrowed sensors
This commit is contained in:
parent
5dd8fa8416
commit
cb67f7e3c3
4 changed files with 117 additions and 276 deletions
|
|
@ -1,35 +0,0 @@
|
||||||
sensors.py
|
|
||||||
==========
|
|
||||||
python bindings using ctypes for libsensors3 of the [lm-sensors project](https://github.com/groeck/lm-sensors). The code was written against libsensors 3.3.4.
|
|
||||||
|
|
||||||
For documentation of the low level API see [sensors.h](https://github.com/groeck/lm-sensors/blob/master/lib/sensors.h). For an example of the high level API see [example.py](example.py).
|
|
||||||
|
|
||||||
For a GUI application that displays the sensor readings and is based on this library, take a look at [sensors-unity](https://launchpad.net/sensors-unity).
|
|
||||||
|
|
||||||
Features
|
|
||||||
--------
|
|
||||||
* Full access to low level libsensors3 API
|
|
||||||
* High level iterator API
|
|
||||||
* unicode handling
|
|
||||||
* Python2 and Python3 compatible
|
|
||||||
|
|
||||||
Licensing
|
|
||||||
---------
|
|
||||||
LGPLv2 (same as libsensors3)
|
|
||||||
|
|
||||||
Usage Notes
|
|
||||||
-----------
|
|
||||||
As Python does not support call by reference for primitive types some of the libsensors API had to be adapted:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# nr is changed by refrence in the C API
|
|
||||||
chip_name, nr = sensors.get_detected_chips(None, nr)
|
|
||||||
|
|
||||||
# returns the value. throws on error
|
|
||||||
val = sensors.get_value(chip, subfeature_nr)
|
|
||||||
```
|
|
||||||
|
|
||||||
Missing Features (pull requests are welcome):
|
|
||||||
* `sensors_subfeature_type` enum
|
|
||||||
* `sensors_get_subfeature`
|
|
||||||
* Error handlers
|
|
||||||
|
|
@ -1,236 +0,0 @@
|
||||||
"""
|
|
||||||
@package sensors.py
|
|
||||||
Python Bindings for libsensors3
|
|
||||||
|
|
||||||
use the documentation of libsensors for the low level API.
|
|
||||||
see example.py for high level API usage.
|
|
||||||
|
|
||||||
@author: Pavel Rojtberg (http://www.rojtberg.net)
|
|
||||||
@see: https://github.com/paroj/sensors.py
|
|
||||||
@copyright: LGPLv2 (same as libsensors) <http://opensource.org/licenses/LGPL-2.1>
|
|
||||||
"""
|
|
||||||
|
|
||||||
from ctypes import *
|
|
||||||
import ctypes.util
|
|
||||||
|
|
||||||
_libc = cdll.LoadLibrary(ctypes.util.find_library("c"))
|
|
||||||
# see https://github.com/paroj/sensors.py/issues/1
|
|
||||||
_libc.free.argtypes = [c_void_p]
|
|
||||||
|
|
||||||
_hdl = cdll.LoadLibrary(ctypes.util.find_library("sensors"))
|
|
||||||
|
|
||||||
version = c_char_p.in_dll(_hdl, "libsensors_version").value.decode("ascii")
|
|
||||||
|
|
||||||
class bus_id(Structure):
|
|
||||||
_fields_ = [("type", c_short),
|
|
||||||
("nr", c_short)]
|
|
||||||
|
|
||||||
class chip_name(Structure):
|
|
||||||
_fields_ = [("prefix", c_char_p),
|
|
||||||
("bus", bus_id),
|
|
||||||
("addr", c_int),
|
|
||||||
("path", c_char_p)]
|
|
||||||
|
|
||||||
class feature(Structure):
|
|
||||||
_fields_ = [("name", c_char_p),
|
|
||||||
("number", c_int),
|
|
||||||
("type", c_int)]
|
|
||||||
|
|
||||||
# sensors_feature_type
|
|
||||||
IN = 0x00
|
|
||||||
FAN = 0x01
|
|
||||||
TEMP = 0x02
|
|
||||||
POWER = 0x03
|
|
||||||
ENERGY = 0x04
|
|
||||||
CURR = 0x05
|
|
||||||
HUMIDITY = 0x06
|
|
||||||
MAX_MAIN = 0x7
|
|
||||||
VID = 0x10
|
|
||||||
INTRUSION = 0x11
|
|
||||||
MAX_OTHER = 0x12
|
|
||||||
BEEP_ENABLE = 0x18
|
|
||||||
|
|
||||||
class subfeature(Structure):
|
|
||||||
_fields_ = [("name", c_char_p),
|
|
||||||
("number", c_int),
|
|
||||||
("type", c_int),
|
|
||||||
("mapping", c_int),
|
|
||||||
("flags", c_uint)]
|
|
||||||
|
|
||||||
_hdl.sensors_get_detected_chips.restype = POINTER(chip_name)
|
|
||||||
_hdl.sensors_get_features.restype = POINTER(feature)
|
|
||||||
_hdl.sensors_get_all_subfeatures.restype = POINTER(subfeature)
|
|
||||||
_hdl.sensors_get_label.restype = c_void_p # return pointer instead of str so we can free it
|
|
||||||
_hdl.sensors_get_adapter_name.restype = c_char_p # docs do not say whether to free this or not
|
|
||||||
_hdl.sensors_strerror.restype = c_char_p
|
|
||||||
|
|
||||||
### RAW API ###
|
|
||||||
MODE_R = 1
|
|
||||||
MODE_W = 2
|
|
||||||
COMPUTE_MAPPING = 4
|
|
||||||
|
|
||||||
def init(cfg_file = None):
|
|
||||||
file = _libc.fopen(cfg_file.encode("utf-8"), "r") if cfg_file is not None else None
|
|
||||||
|
|
||||||
if _hdl.sensors_init(file) != 0:
|
|
||||||
raise Exception("sensors_init failed")
|
|
||||||
|
|
||||||
if file is not None:
|
|
||||||
_libc.fclose(file)
|
|
||||||
|
|
||||||
def cleanup():
|
|
||||||
_hdl.sensors_cleanup()
|
|
||||||
|
|
||||||
def parse_chip_name(orig_name):
|
|
||||||
ret = chip_name()
|
|
||||||
err= _hdl.sensors_parse_chip_name(orig_name.encode("utf-8"), byref(ret))
|
|
||||||
|
|
||||||
if err < 0:
|
|
||||||
raise Exception(strerror(err))
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def strerror(errnum):
|
|
||||||
return _hdl.sensors_strerror(errnum).decode("utf-8")
|
|
||||||
|
|
||||||
def free_chip_name(chip):
|
|
||||||
_hdl.sensors_free_chip_name(byref(chip))
|
|
||||||
|
|
||||||
def get_detected_chips(match, nr):
|
|
||||||
"""
|
|
||||||
@return: (chip, next nr to query)
|
|
||||||
"""
|
|
||||||
_nr = c_int(nr)
|
|
||||||
|
|
||||||
if match is not None:
|
|
||||||
match = byref(match)
|
|
||||||
|
|
||||||
chip = _hdl.sensors_get_detected_chips(match, byref(_nr))
|
|
||||||
chip = chip.contents if bool(chip) else None
|
|
||||||
return chip, _nr.value
|
|
||||||
|
|
||||||
def chip_snprintf_name(chip, buffer_size=200):
|
|
||||||
"""
|
|
||||||
@param buffer_size defaults to the size used in the sensors utility
|
|
||||||
"""
|
|
||||||
ret = create_string_buffer(buffer_size)
|
|
||||||
err = _hdl.sensors_snprintf_chip_name(ret, buffer_size, byref(chip))
|
|
||||||
|
|
||||||
if err < 0:
|
|
||||||
raise Exception(strerror(err))
|
|
||||||
|
|
||||||
return ret.value.decode("utf-8")
|
|
||||||
|
|
||||||
def do_chip_sets(chip):
|
|
||||||
"""
|
|
||||||
@attention this function was not tested
|
|
||||||
"""
|
|
||||||
err = _hdl.sensors_do_chip_sets(byref(chip))
|
|
||||||
if err < 0:
|
|
||||||
raise Exception(strerror(err))
|
|
||||||
|
|
||||||
def get_adapter_name(bus):
|
|
||||||
return _hdl.sensors_get_adapter_name(byref(bus)).decode("utf-8")
|
|
||||||
|
|
||||||
def get_features(chip, nr):
|
|
||||||
"""
|
|
||||||
@return: (feature, next nr to query)
|
|
||||||
"""
|
|
||||||
_nr = c_int(nr)
|
|
||||||
feature = _hdl.sensors_get_features(byref(chip), byref(_nr))
|
|
||||||
feature = feature.contents if bool(feature) else None
|
|
||||||
return feature, _nr.value
|
|
||||||
|
|
||||||
def get_label(chip, feature):
|
|
||||||
ptr = _hdl.sensors_get_label(byref(chip), byref(feature))
|
|
||||||
val = cast(ptr, c_char_p).value.decode("utf-8")
|
|
||||||
_libc.free(ptr)
|
|
||||||
return val
|
|
||||||
|
|
||||||
def get_all_subfeatures(chip, feature, nr):
|
|
||||||
"""
|
|
||||||
@return: (subfeature, next nr to query)
|
|
||||||
"""
|
|
||||||
_nr = c_int(nr)
|
|
||||||
subfeature = _hdl.sensors_get_all_subfeatures(byref(chip), byref(feature), byref(_nr))
|
|
||||||
subfeature = subfeature.contents if bool(subfeature) else None
|
|
||||||
return subfeature, _nr.value
|
|
||||||
|
|
||||||
def get_value(chip, subfeature_nr):
|
|
||||||
val = c_double()
|
|
||||||
err = _hdl.sensors_get_value(byref(chip), subfeature_nr, byref(val))
|
|
||||||
if err < 0:
|
|
||||||
raise Exception(strerror(err))
|
|
||||||
return val.value
|
|
||||||
|
|
||||||
def set_value(chip, subfeature_nr, value):
|
|
||||||
"""
|
|
||||||
@attention this function was not tested
|
|
||||||
"""
|
|
||||||
val = c_double(value)
|
|
||||||
err = _hdl.sensors_set_value(byref(chip), subfeature_nr, byref(val))
|
|
||||||
if err < 0:
|
|
||||||
raise Exception(strerror(err))
|
|
||||||
|
|
||||||
### Convenience API ###
|
|
||||||
class ChipIterator:
|
|
||||||
def __init__(self, match = None):
|
|
||||||
self.match = parse_chip_name(match) if match is not None else None
|
|
||||||
self.nr = 0
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __next__(self):
|
|
||||||
chip, self.nr = get_detected_chips(self.match, self.nr)
|
|
||||||
|
|
||||||
if chip is None:
|
|
||||||
raise StopIteration
|
|
||||||
|
|
||||||
return chip
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
if self.match is not None:
|
|
||||||
free_chip_name(self.match)
|
|
||||||
|
|
||||||
def next(self): # python2 compability
|
|
||||||
return self.__next__()
|
|
||||||
|
|
||||||
class FeatureIterator:
|
|
||||||
def __init__(self, chip):
|
|
||||||
self.chip = chip
|
|
||||||
self.nr = 0
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __next__(self):
|
|
||||||
feature, self.nr = get_features(self.chip, self.nr)
|
|
||||||
|
|
||||||
if feature is None:
|
|
||||||
raise StopIteration
|
|
||||||
|
|
||||||
return feature
|
|
||||||
|
|
||||||
def next(self): # python2 compability
|
|
||||||
return self.__next__()
|
|
||||||
|
|
||||||
class SubFeatureIterator:
|
|
||||||
def __init__(self, chip, feature):
|
|
||||||
self.chip = chip
|
|
||||||
self.feature = feature
|
|
||||||
self.nr = 0
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __next__(self):
|
|
||||||
subfeature, self.nr = get_all_subfeatures(self.chip, self.feature, self.nr)
|
|
||||||
|
|
||||||
if subfeature is None:
|
|
||||||
raise StopIteration
|
|
||||||
|
|
||||||
return subfeature
|
|
||||||
|
|
||||||
def next(self): # python2 compability
|
|
||||||
return self.__next__()
|
|
||||||
|
|
@ -29,8 +29,9 @@ COLORS = {
|
||||||
'RED': '\033[31m',
|
'RED': '\033[31m',
|
||||||
'GREEN': '\033[32m',
|
'GREEN': '\033[32m',
|
||||||
'YELLOW': '\033[33m',
|
'YELLOW': '\033[33m',
|
||||||
|
'ORANGE': '\033[31;1m',
|
||||||
'BLUE': '\033[34m'
|
'BLUE': '\033[34m'
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
HKU = winreg.HKEY_USERS
|
HKU = winreg.HKEY_USERS
|
||||||
HKCR = winreg.HKEY_CLASSES_ROOT
|
HKCR = winreg.HKEY_CLASSES_ROOT
|
||||||
|
|
|
||||||
111
.bin/Scripts/functions/sensors.py
Normal file
111
.bin/Scripts/functions/sensors.py
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
# Wizard Kit: Functions - Sensors
|
||||||
|
|
||||||
|
import itertools
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
|
||||||
|
from functions.common import *
|
||||||
|
|
||||||
|
# STATIC VARIABLES
|
||||||
|
TEMP_LIMITS = {
|
||||||
|
'GREEN': 60,
|
||||||
|
'YELLOW': 70,
|
||||||
|
'ORANGE': 80,
|
||||||
|
'RED': 90,
|
||||||
|
}
|
||||||
|
|
||||||
|
# REGEX
|
||||||
|
REGEX_COLORS = re.compile(r'\033\[\d+;?1?m')
|
||||||
|
|
||||||
|
def fix_sensor_str(s):
|
||||||
|
"""Cleanup string and return str."""
|
||||||
|
s = re.sub(r'^(\w+)-(\w+)-(\w+)', r'\1 (\2 \3)', s, re.IGNORECASE)
|
||||||
|
s = s.title()
|
||||||
|
s = s.replace('Coretemp', 'CoreTemp')
|
||||||
|
s = s.replace('Acpi', 'ACPI')
|
||||||
|
s = s.replace('Isa ', 'ISA ')
|
||||||
|
s = s.replace('Id ', 'ID ')
|
||||||
|
s = re.sub(r'(\D+)(\d+)', r'\1 \2', s, re.IGNORECASE)
|
||||||
|
s = s.replace(' ', ' ')
|
||||||
|
return s
|
||||||
|
|
||||||
|
def get_color_temp(temp):
|
||||||
|
"""Get colored temp string, returns str."""
|
||||||
|
try:
|
||||||
|
temp = float(temp)
|
||||||
|
except ValueError:
|
||||||
|
return '{YELLOW}{temp}{CLEAR}'.format(temp=temp, **COLORS)
|
||||||
|
if temp > TEMP_LIMITS['RED']:
|
||||||
|
color = COLORS['RED']
|
||||||
|
elif temp > TEMP_LIMITS['ORANGE']:
|
||||||
|
color = COLORS['ORANGE']
|
||||||
|
elif temp > TEMP_LIMITS['YELLOW']:
|
||||||
|
color = COLORS['YELLOW']
|
||||||
|
elif temp > TEMP_LIMITS['GREEN']:
|
||||||
|
color = COLORS['GREEN']
|
||||||
|
elif temp > 0:
|
||||||
|
color = COLORS['BLUE']
|
||||||
|
else:
|
||||||
|
color = COLORS['CLEAR']
|
||||||
|
return '{color}{prefix}{temp:2.0f}°C{CLEAR}'.format(
|
||||||
|
color = color,
|
||||||
|
prefix = '-' if temp < 0 else '',
|
||||||
|
temp = temp,
|
||||||
|
**COLORS)
|
||||||
|
|
||||||
|
def get_raw_sensor_data():
|
||||||
|
"""Read sensor data and return dict."""
|
||||||
|
cmd = ['sensors', '-j']
|
||||||
|
result = run_program(cmd)
|
||||||
|
return json.loads(result.stdout.decode())
|
||||||
|
|
||||||
|
def get_sensor_data():
|
||||||
|
"""Parse raw sensor data and return new dict."""
|
||||||
|
json_data = get_raw_sensor_data()
|
||||||
|
sensor_data = {'CoreTemps': {}, 'Other': {}}
|
||||||
|
for _adapter, _sources in json_data.items():
|
||||||
|
if 'coretemp' in _adapter:
|
||||||
|
_section = 'CoreTemps'
|
||||||
|
else:
|
||||||
|
_section = 'Other'
|
||||||
|
sensor_data[_section][_adapter] = {}
|
||||||
|
_sources.pop('Adapter', None)
|
||||||
|
|
||||||
|
# Find current temp and add to dict
|
||||||
|
## current temp is labeled xxxx_input
|
||||||
|
for _source, _labels in _sources.items():
|
||||||
|
for _label, _temp in _labels.items():
|
||||||
|
if 'input' in _label:
|
||||||
|
sensor_data[_section][_adapter][_source] = {
|
||||||
|
'Temps': [_temp],
|
||||||
|
'Label': _label,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Remove empty sections
|
||||||
|
for k, v in sensor_data.items():
|
||||||
|
v = {k2: v2 for k2, v2 in v.items() if v2}
|
||||||
|
|
||||||
|
# Done
|
||||||
|
return sensor_data
|
||||||
|
|
||||||
|
def update_sensor_data(sensor_data):
|
||||||
|
"""Read sensors and update existing sensor_data, returns dict."""
|
||||||
|
json_data = get_raw_sensor_data()
|
||||||
|
for _section, _adapters in sensor_data.items():
|
||||||
|
for _adapter, _sources in _adapters.items():
|
||||||
|
for _source, _data in _sources.items():
|
||||||
|
_label = _ddata['Label']
|
||||||
|
_temp = json_data[_adapter][_source][_label]
|
||||||
|
_data['Temps'].append(_temp)
|
||||||
|
return sensor_data
|
||||||
|
|
||||||
|
def join_columns(column1, column2, width=55):
|
||||||
|
return '{:<{}}{}'.format(
|
||||||
|
column1,
|
||||||
|
55+len(column1)-len(REGEX_COLORS.sub('', column1)),
|
||||||
|
column2)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print("This file is not meant to be called directly.")
|
||||||
|
|
||||||
|
# vim: sts=2 sw=2 ts=2
|
||||||
Loading…
Reference in a new issue