Browse Source

Merge pull request #3822 from dspinellis/w1sensor

Add 1-Wire sensor monitoring
Costa Tsaousis 6 years ago
parent
commit
9598db24ca

+ 1 - 0
conf.d/Makefile.am

@@ -79,6 +79,7 @@ dist_pythonconfig_DATA = \
     python.d/traefik.conf \
     python.d/unbound.conf \
     python.d/varnish.conf \
+    python.d/w1sensor.conf \
     python.d/web_log.conf \
     $(NULL)
 

+ 1 - 0
conf.d/python.d.conf

@@ -82,3 +82,4 @@ nginx_log: no
 unbound: no
 # varnish: yes
 # web_log: yes
+# w1sensor: yes

+ 74 - 0
conf.d/python.d/w1sensor.conf

@@ -0,0 +1,74 @@
+# netdata python.d.plugin configuration for w1sensor
+#
+# This file is in YaML format. Generally the format is:
+#
+# name: value
+#
+# There are 2 sections:
+#  - global variables
+#  - one or more JOBS
+#
+# JOBS allow you to collect values from multiple sources.
+# Each source will have its own set of charts.
+#
+# JOB parameters have to be indented (using spaces only, example below).
+
+# ----------------------------------------------------------------------
+# Global Variables
+# These variables set the defaults for all JOBs, however each JOB
+# may define its own, overriding the defaults.
+
+# update_every sets the default data collection frequency.
+# If unset, the python.d.plugin default is used.
+# update_every: 5
+
+# priority controls the order of charts at the netdata dashboard.
+# Lower numbers move the charts towards the top of the page.
+# If unset, the default for python.d.plugin is used.
+# priority: 60000
+
+# retries sets the number of retries to be made in case of failures.
+# If unset, the default for python.d.plugin is used.
+# Attempts to restore the service are made once every update_every
+# and only if the module has collected values in the past.
+# retries: 60
+
+# autodetection_retry sets the job re-check interval in seconds.
+# The job is not deleted if check fails.
+# Attempts to start the job are made once every autodetection_retry.
+# This feature is disabled by default.
+# autodetection_retry: 0
+
+# ----------------------------------------------------------------------
+# JOBS (data collection sources)
+#
+# The default JOBS share the same *name*. JOBS with the same name
+# are mutually exclusive. Only one of them will be allowed running at
+# any time. This allows autodetection to try several alternatives and
+# pick the one that works.
+#
+# Any number of jobs is supported.
+#
+# All python.d.plugin JOBS (for all its modules) support a set of
+# predefined parameters. These are:
+#
+# job_name:
+#     name: myname            # the JOB's name as it will appear at the
+#                             # dashboard (by default is the job_name)
+#                             # JOBs sharing a name are mutually exclusive
+#     update_every: 5         # the JOB's data collection frequency
+#     priority: 60000         # the JOB's order on the dashboard
+#     retries: 60             # the JOB's number of restoration attempts
+#     autodetection_retry: 0  # the JOB's re-check interval in seconds
+#
+# Additionally to the above, example also supports the following:
+#
+# name_<1-Wire id>: '<human readable name>'
+# This allows associating a human readable name with a sensor's 1-Wire
+# identifier. Example:
+# name_00000022276e: 'Machine room'
+# name_00000022298f: 'Rack 12'
+#
+# ----------------------------------------------------------------------
+# AUTO-DETECTION JOBS
+# only one of them will run (they have the same name)

+ 1 - 0
python.d/Makefile.am

@@ -67,6 +67,7 @@ dist_python_DATA = \
     traefik.chart.py \
     unbound.chart.py \
     varnish.chart.py \
+    w1sensor.chart.py \
     web_log.chart.py \
     $(NULL)
 

+ 14 - 0
python.d/README.md

@@ -2522,6 +2522,20 @@ No configuration is needed.
 
 ---
 
+# w1sensor
+
+Data from 1-Wire sensors.
+On Linux these are supported by the wire, w1_gpio, and w1_therm modules.
+Currently temperature sensors are supported and automatically detected.
+
+Charts are created dynamically based on the number of detected sensors.
+
+### configuration
+
+For detailed configuration information please read [`w1sensor.conf`](https://github.com/firehol/netdata/blob/master/conf.d/python.d/w1sensor.conf) file.
+
+---
+
 # web_log
 
 Tails the apache/nginx/lighttpd/gunicorn log files to collect real-time web-server statistics.

+ 103 - 0
python.d/w1sensor.chart.py

@@ -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

+ 10 - 0
web/dashboard_info.js

@@ -384,6 +384,12 @@ netdataDashboard.menu = {
         title: 'BOINC',
         icon: '<i class="fas fa-microchip"></i>',
         info: 'Provides task counts for <b><a href="http://boinc.berkeley.edu/">BOINC</a></b> distributed computing clients.'
+    },
+
+    'w1sensor': {
+        title: '1-Wire Sensors',
+        icon: '<i class="fas fa-thermometer-half"></i>',
+        info: 'Data derived from <a href="https://en.wikipedia.org/wiki/1-Wire">1-Wire</a> sensors.  Currently temperature sensors are automatically detected.'
     }
 };
 
@@ -2142,6 +2148,10 @@ netdataDashboard.context = {
 
     'boinc.process': {
         info: 'Counts of active tasks in each process state.  <code>Executing</code> tasks are running right now.  <code>Suspended</code> tasks have an associated process, but are not currently running (either because the system isn\'t processing any tasks right now, or because they have been preempted by higher priority tasks).  <code>Quit</code> tasks are exiting gracefully.  <code>Aborted</code> tasks exceeded some resource limit, and are being shut down.  code>Copy Pending</code> tasks are waiting on a background file transfer to finish.  <code>Uninitialized</code> tasks do not have an associated process yet.'
+    },
+
+    'w1sensor.temp': {
+        info: 'Temperature derived from 1-Wire temperature sensors.'
     }
 
     // ------------------------------------------------------------------------