|
@@ -0,0 +1,103 @@
|
|
|
+# -*- coding: utf-8 -*-
|
|
|
+# Description: 1-wire temperature monitor netdata python.d module
|
|
|
+# Author: Diomidis Spinellis <http://www.spinellis.gr>
|
|
|
+
|
|
|
+import os
|
|
|
+import re
|
|
|
+from bases.FrameworkServices.SimpleService import SimpleService
|
|
|
+
|
|
|
+# default module values (can be overridden per job in `config`)
|
|
|
+update_every = 5
|
|
|
+
|
|
|
+# Location where 1-Wire devices can be found
|
|
|
+W1_DIR = '/sys/bus/w1/devices/'
|
|
|
+
|
|
|
+# Lines matching the following regular expression contain a temperature value
|
|
|
+RE_TEMP = re.compile(r' t=(\d+)')
|
|
|
+
|
|
|
+ORDER = ['temp']
|
|
|
+
|
|
|
+# id: {
|
|
|
+# 'options': [name, title, units, family (heading 2), context, charttype],
|
|
|
+# 'lines': [
|
|
|
+# [unique_dimension_name, name, algorithm, multiplier, divisor]
|
|
|
+# ]}
|
|
|
+CHARTS = {
|
|
|
+ 'temp': {
|
|
|
+ 'options': [
|
|
|
+ None,
|
|
|
+ '1-Wire Temperature Sensor',
|
|
|
+ 'Celsius',
|
|
|
+ 'Temperature',
|
|
|
+ 'w1sensor.temp',
|
|
|
+ 'line'
|
|
|
+ ],
|
|
|
+ # lines are constructed from check
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+# Known and supported family members
|
|
|
+# Based on linux/drivers/w1/w1_family.h and w1/slaves/w1_therm.c
|
|
|
+THERM_FAMILY = {
|
|
|
+ '10': 'W1_THERM_DS18S20',
|
|
|
+ '22': 'W1_THERM_DS1822',
|
|
|
+ '28': 'W1_THERM_DS18B20',
|
|
|
+ '3b': 'W1_THERM_DS1825',
|
|
|
+ '42': 'W1_THERM_DS28EA00',
|
|
|
+}
|
|
|
+
|
|
|
+class Service(SimpleService):
|
|
|
+ """Provide netdata service for 1-Wire sensors"""
|
|
|
+ def __init__(self, configuration=None, name=None):
|
|
|
+ SimpleService.__init__(self, configuration=configuration, name=name)
|
|
|
+ self.order = ORDER
|
|
|
+ self.definitions = CHARTS
|
|
|
+ self.probes = []
|
|
|
+
|
|
|
+ def check(self):
|
|
|
+ """Auto-detect available 1-Wire sensors, setting line definitions
|
|
|
+ and probes to be monitored."""
|
|
|
+ try:
|
|
|
+ file_names = os.listdir(W1_DIR)
|
|
|
+ except OSError as err:
|
|
|
+ self.error(err)
|
|
|
+ return False
|
|
|
+
|
|
|
+ lines = []
|
|
|
+ for file_name in file_names:
|
|
|
+ if file_name[2] != '-':
|
|
|
+ continue
|
|
|
+ if not file_name[0:2] in THERM_FAMILY:
|
|
|
+ continue
|
|
|
+
|
|
|
+ self.probes.append(file_name)
|
|
|
+ identifier = file_name[3:]
|
|
|
+ name = identifier
|
|
|
+ config_name = self.configuration.get('name_' + identifier)
|
|
|
+ if config_name:
|
|
|
+ name = config_name
|
|
|
+ lines.append(['w1sensor_temp_' + identifier, name, 'absolute',
|
|
|
+ 1, 10])
|
|
|
+ self.definitions['temp']['lines'] = lines
|
|
|
+ return len(self.probes) > 0
|
|
|
+
|
|
|
+ def get_data(self):
|
|
|
+ """Return data read from sensors."""
|
|
|
+ data = dict()
|
|
|
+
|
|
|
+ for file_name in self.probes:
|
|
|
+ file_path = W1_DIR + file_name + '/w1_slave'
|
|
|
+ identifier = file_name[3:]
|
|
|
+ try:
|
|
|
+ with open(file_path, 'r') as device_file:
|
|
|
+ for line in device_file:
|
|
|
+ matched = RE_TEMP.search(line)
|
|
|
+ if matched:
|
|
|
+ # Round to one decimal digit to filter-out noise
|
|
|
+ value = round(int(matched.group(1)) / 1000., 1)
|
|
|
+ value = int(value * 10)
|
|
|
+ data['w1sensor_temp_' + identifier] = value
|
|
|
+ except (OSError, IOError) as err:
|
|
|
+ self.error(err)
|
|
|
+ continue
|
|
|
+ return data or None
|