]> arthur.barton.de Git - netdata.git/blob - python.d/sensors.chart.py
ab-debian 0.20170327.01-0ab1, upstream v1.6.0-42-gaa6b96fc
[netdata.git] / python.d / sensors.chart.py
1 # -*- coding: utf-8 -*-
2 # Description: sensors netdata python.d plugin
3 # Author: Pawel Krupa (paulfantom)
4
5 from base import SimpleService
6 import lm_sensors as sensors
7
8 # default module values (can be overridden per job in `config`)
9 # update_every = 2
10
11 ORDER = ['temperature', 'fan', 'voltage', 'current', 'power', 'energy', 'humidity']
12
13 # This is a prototype of chart definition which is used to dynamically create self.definitions
14 CHARTS = {
15     'temperature': {
16         'options': [None, ' temperature', 'Celsius', 'temperature', 'sensors.temperature', 'line'],
17         'lines': [
18             [None, None, 'absolute', 1, 1000]
19         ]},
20     'voltage': {
21         'options': [None, ' voltage', 'Volts', 'voltage', 'sensors.voltage', 'line'],
22         'lines': [
23             [None, None, 'absolute', 1, 1000]
24         ]},
25     'current': {
26         'options': [None, ' current', 'Ampere', 'current', 'sensors.current', 'line'],
27         'lines': [
28             [None, None, 'absolute', 1, 1000]
29         ]},
30     'power': {
31         'options': [None, ' power', 'Watt', 'power', 'sensors.power', 'line'],
32         'lines': [
33             [None, None, 'absolute', 1, 1000000]
34         ]},
35     'fan': {
36         'options': [None, ' fans speed', 'Rotations/min', 'fans', 'sensors.fan', 'line'],
37         'lines': [
38             [None, None, 'absolute', 1, 1000]
39         ]},
40     'energy': {
41         'options': [None, ' energy', 'Joule', 'energy', 'sensors.energy', 'areastack'],
42         'lines': [
43             [None, None, 'incremental', 1, 1000000]
44         ]},
45     'humidity': {
46         'options': [None, ' humidity', 'Percent', 'humidity', 'sensors.humidity', 'line'],
47         'lines': [
48             [None, None, 'absolute', 1, 1000]
49         ]}
50 }
51
52 LIMITS = {
53     'temperature': [-127, 1000],
54     'voltage': [-127, 127],
55     'current': [-127, 127],
56     'fan': [0, 65535]
57 }
58
59 TYPE_MAP = {
60     0: 'voltage',
61     1: 'fan',
62     2: 'temperature',
63     3: 'power',
64     4: 'energy',
65     5: 'current',
66     6: 'humidity',
67     7: 'max_main',
68     16: 'vid',
69     17: 'intrusion',
70     18: 'max_other',
71     24: 'beep_enable'
72 }
73
74
75 class Service(SimpleService):
76     def __init__(self, configuration=None, name=None):
77         SimpleService.__init__(self, configuration=configuration, name=name)
78         self.order = []
79         self.definitions = {}
80         self.celsius = ('Celsius', lambda x: x)
81         self.fahrenheit = ('Fahrenheit', lambda x: x * 9 / 5 + 32)  if self.configuration.get('fahrenheit') else False
82         self.choice = (choice for choice in [self.fahrenheit, self.celsius] if choice)
83         self.chips = []
84
85     def _get_data(self):
86         data = {}
87         try:
88             for chip in sensors.ChipIterator():
89                 prefix = sensors.chip_snprintf_name(chip)
90                 for feature in sensors.FeatureIterator(chip):
91                     sfi = sensors.SubFeatureIterator(chip, feature)
92                     for sf in sfi:
93                         val = sensors.get_value(chip, sf.number)
94                         break
95                     typeName = TYPE_MAP[feature.type]
96                     if typeName in LIMITS:
97                         limit = LIMITS[typeName];
98                         if val < limit[0] or val > limit[1]:
99                             continue
100                     if 'temp' in str(feature.name.decode()):
101                         data[prefix + "_" + str(feature.name.decode())] = int(self.calc(val) * 1000)
102                     else:
103                         data[prefix + "_" + str(feature.name.decode())] = int(val * 1000)
104         except Exception as e:
105             self.error(e)
106             return None
107
108         if len(data) == 0:
109             return None
110         return data
111
112     def _create_definitions(self):
113         for type in ORDER:
114             for chip in sensors.ChipIterator():
115                 chip_name = sensors.chip_snprintf_name(chip)
116                 if len(self.chips) != 0 and not any([chip_name.startswith(ex) for ex in self.chips]):
117                     continue
118                 for feature in sensors.FeatureIterator(chip):
119                     sfi = sensors.SubFeatureIterator(chip, feature)
120                     vals = [sensors.get_value(chip, sf.number) for sf in sfi]
121                     if vals[0] == 0:
122                         continue
123                     if TYPE_MAP[feature.type] == type:
124                         # create chart
125                         name = chip_name + "_" + TYPE_MAP[feature.type]
126                         if name not in self.order:
127                             self.order.append(name)
128                             chart_def = list(CHARTS[type]['options'])
129                             chart_def[1] = chip_name + chart_def[1]
130                             if chart_def[2] == 'Celsius':
131                                 chart_def[2] = self.choice[0]
132                             self.definitions[name] = {'options': chart_def}
133                             self.definitions[name]['lines'] = []
134                         line = list(CHARTS[type]['lines'][0])
135                         line[0] = chip_name + "_" + str(feature.name.decode())
136                         line[1] = sensors.get_label(chip, feature)
137                         self.definitions[name]['lines'].append(line)
138
139     def check(self):
140         try:
141             sensors.init()
142         except Exception as e:
143             self.error(e)
144             return False
145         
146         try:
147             self.choice = next(self.choice)
148         except StopIteration:
149             # That can not happen but..
150             self.choice = ('Celsius', lambda x: x)
151             self.calc = self.choice[1]
152         else:
153             self.calc = self.choice[1]
154
155         try:
156             self._create_definitions()
157         except Exception as e:
158             self.error(e)
159             return False
160
161         return True