w1sensor.chart.py 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. # -*- coding: utf-8 -*-
  2. # Description: 1-wire temperature monitor netdata python.d module
  3. # Author: Diomidis Spinellis <http://www.spinellis.gr>
  4. # SPDX-License-Identifier: GPL-3.0-or-later
  5. import os
  6. import re
  7. from bases.FrameworkServices.SimpleService import SimpleService
  8. # default module values (can be overridden per job in `config`)
  9. update_every = 5
  10. # Location where 1-Wire devices can be found
  11. W1_DIR = '/sys/bus/w1/devices/'
  12. # Lines matching the following regular expression contain a temperature value
  13. RE_TEMP = re.compile(r' t=(-?\d+)')
  14. ORDER = [
  15. 'temp',
  16. ]
  17. CHARTS = {
  18. 'temp': {
  19. 'options': [None, '1-Wire Temperature Sensor', 'Celsius', 'Temperature', 'w1sensor.temp', 'line'],
  20. 'lines': []
  21. }
  22. }
  23. # Known and supported family members
  24. # Based on linux/drivers/w1/w1_family.h and w1/slaves/w1_therm.c
  25. THERM_FAMILY = {
  26. '10': 'W1_THERM_DS18S20',
  27. '22': 'W1_THERM_DS1822',
  28. '28': 'W1_THERM_DS18B20',
  29. '3b': 'W1_THERM_DS1825',
  30. '42': 'W1_THERM_DS28EA00',
  31. }
  32. class Service(SimpleService):
  33. """Provide netdata service for 1-Wire sensors"""
  34. def __init__(self, configuration=None, name=None):
  35. SimpleService.__init__(self, configuration=configuration, name=name)
  36. self.order = ORDER
  37. self.definitions = CHARTS
  38. self.probes = []
  39. def check(self):
  40. """Auto-detect available 1-Wire sensors, setting line definitions
  41. and probes to be monitored."""
  42. try:
  43. file_names = os.listdir(W1_DIR)
  44. except OSError as err:
  45. self.error(err)
  46. return False
  47. lines = []
  48. for file_name in file_names:
  49. if file_name[2] != '-':
  50. continue
  51. if not file_name[0:2] in THERM_FAMILY:
  52. continue
  53. self.probes.append(file_name)
  54. identifier = file_name[3:]
  55. name = identifier
  56. config_name = self.configuration.get('name_' + identifier)
  57. if config_name:
  58. name = config_name
  59. lines.append(['w1sensor_temp_' + identifier, name, 'absolute',
  60. 1, 10])
  61. self.definitions['temp']['lines'] = lines
  62. return len(self.probes) > 0
  63. def get_data(self):
  64. """Return data read from sensors."""
  65. data = dict()
  66. for file_name in self.probes:
  67. file_path = W1_DIR + file_name + '/w1_slave'
  68. identifier = file_name[3:]
  69. try:
  70. with open(file_path, 'r') as device_file:
  71. for line in device_file:
  72. matched = RE_TEMP.search(line)
  73. if matched:
  74. # Round to one decimal digit to filter-out noise
  75. value = round(int(matched.group(1)) / 1000., 1)
  76. value = int(value * 10)
  77. data['w1sensor_temp_' + identifier] = value
  78. except (OSError, IOError) as err:
  79. self.error(err)
  80. continue
  81. return data or None