root/lm-sensors/trunk/prog/sensord/sense.c @ 1357

Revision 1357, 8.5 KB (checked in by merlin, 11 years ago)

Added RRD support to sensord; can automatically create
/configure database based on detected/configured sensors,
logs libsensors-processed readings to the database, has a
command-line option for generating a basic rrdcgi script.
Removed sensord from all target because it has an external
dependency on librrd.

This just makes using RRD with sensors easier; you don't
need to figure out what sensors are available and configure
the database with computations that are already in
sensors.conf.

To install:
make install-prog-sensord

To create and start logging to database:
sensord --rrd-file /var/log/sensord.rrd

To create a CGI script:
sensord --rrd-file /var/log/sensord.rrd \

--rrd-cgi /var/www/sensord \
> /usr/lib/cgi-bin/sensord.cgi

man sensord for more details.

Kudos to Mark for doing the hard work ;}

-- merlin

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * sensord
3 *
4 * A daemon that periodically logs sensor information to syslog.
5 *
6 * Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <syslog.h>
27
28#include "sensord.h"
29#include "lib/error.h"
30
31#define DO_READ 0
32#define DO_SCAN 1
33#define DO_SET 2
34#define DO_RRD 3
35
36int
37getValid
38(sensors_chip_name name, int feature, int *valid) {
39  int err;
40  err = sensors_get_ignored (name, feature);
41  if (err >= 0) {
42    *valid = err;
43    err = 0;
44  }
45  return err;
46}
47
48int
49getLabel
50(sensors_chip_name name, int feature, char **label) {
51  int err;
52  err = sensors_get_label (name, feature, label);
53  return err;
54}
55
56int
57getRawLabel
58(sensors_chip_name name, int feature, const char **label) {
59  const sensors_feature_data *rawFeature;
60  int nr1 = 0, nr2 = 0, err = 0;
61  do {
62    rawFeature = sensors_get_all_features (name, &nr1, &nr2);
63  } while (rawFeature && (rawFeature->number != feature));
64  /* TODO: Ensure labels match RRD construct and are not repeated! */
65  if (!rawFeature) {
66    err = -1;
67  } else {
68    *label = rawFeature->name;
69  }
70  return err;
71}
72
73static const char *
74chipName
75(const sensors_chip_name *chip) {
76  static char buffer[256];
77  if (chip->bus == SENSORS_CHIP_NAME_BUS_ISA)
78    sprintf (buffer, "%s-isa-%04x", chip->prefix, chip->addr);
79  else
80    sprintf (buffer, "%s-i2c-%d-%02x", chip->prefix, chip->bus, chip->addr);
81  return buffer;
82}
83
84static int
85idChip
86(const sensors_chip_name *chip) {
87  const char *adapter, *algorithm;
88
89  sensorLog (LOG_INFO, "Chip: %s", chipName (chip));
90  adapter = sensors_get_adapter_name (chip->bus);
91  if (adapter)
92    sensorLog (LOG_INFO, "Adapter: %s", adapter);
93  algorithm = sensors_get_algorithm_name (chip->bus);
94  if (algorithm)
95    sensorLog (LOG_INFO, "Algorithm: %s", algorithm);
96  /* assert adapter || algorithm */
97 
98  return 0;
99}
100
101static int
102readUnknownChip
103(const sensors_chip_name *chip) {
104  const sensors_feature_data *sensor;
105  int index0 = 0, index1 = 0;
106  int ret = 0;
107
108  ret = idChip (chip);
109
110  while ((ret == 0) && ((sensor = sensors_get_all_features (*chip, &index0, &index1)) != NULL)) {
111    char *label = NULL;
112    int valid = 0;
113    double value;
114   
115    if (getValid (*chip, sensor->number, &valid)) {
116      sensorLog (LOG_ERR, "Error getting sensor validity: %s/%s", chip->prefix, sensor->name);
117      ret = 20;
118    } else if (getLabel (*chip, sensor->number, &label)) {
119      sensorLog (LOG_ERR, "Error getting sensor label: %s/%s", chip->prefix, sensor->name);
120      ret = 21;
121    } else if (!valid) {
122      /* skip invalid */
123    } else if (!(sensor->mode & SENSORS_MODE_R)) {
124      sensorLog (LOG_INFO, "%s: %s", sensor->name, label);
125    } else if ((ret = sensors_get_feature (*chip, sensor->number, &value))) {
126      sensorLog (LOG_ERR, "Error getting sensor data: %s/%s: %s", chip->prefix, sensor->name, sensors_strerror (ret));
127      ret = 22;
128    } else {
129      sensorLog (LOG_INFO, "  %s%s: %.2f", (sensor->mapping == SENSORS_NO_MAPPING) ? "" : "-", label, value);
130    }
131    if (label)
132      free (label);
133  }
134 
135  return ret;
136}
137
138static int
139doKnownChip
140(const sensors_chip_name *chip, const ChipDescriptor *descriptor, int action) {
141  const FeatureDescriptor *features = descriptor->features;
142  int alarms = 0, beeps = 0;
143  int index0, subindex;
144  int ret = 0;
145  double tmp;
146
147  if (action == DO_READ)
148    ret = idChip (chip);
149  if (!ret && descriptor->alarmNumber) {
150    if ((ret = sensors_get_feature (*chip, descriptor->alarmNumber, &tmp))) {
151      sensorLog (LOG_ERR, "Error getting sensor data: %s/#%d: %s", chip->prefix, descriptor->alarmNumber, sensors_strerror (ret));
152      ret = 20;
153    } else {
154      alarms = (int) (tmp + 0.5);
155    }
156  }
157  if (!ret && descriptor->beepNumber) {
158    if ((ret = sensors_get_feature (*chip, descriptor->beepNumber, &tmp))) {
159      sensorLog (LOG_ERR, "Error getting sensor data: %s/#%d: %s", chip->prefix, descriptor->beepNumber, sensors_strerror (ret));
160      ret = 21;
161    } else {
162      beeps = (int) (tmp + 0.5);
163    }
164  }
165  for (index0 = 0; (ret == 0) && features[index0].format; ++ index0) {
166    const FeatureDescriptor *feature = features + index0;
167    int labelNumber = feature->dataNumbers[0];
168    int alarm = alarms & feature->alarmMask;
169    int beep = beeps & feature->beepMask;
170    char *label = NULL;
171    int valid = 0;
172
173    if ((action == DO_SCAN) && !alarm) {
174      continue;
175    } else if (getValid (*chip, labelNumber, &valid)) {
176      sensorLog (LOG_ERR, "Error getting sensor validity: %s/#%d", chip->prefix, labelNumber);
177      ret = 22;
178    } else if (getLabel (*chip, labelNumber, &label)) {
179      sensorLog (LOG_ERR, "Error getting sensor label: %s/#%d", chip->prefix, labelNumber);
180      ret = 22;
181    } else if (valid) {
182      double values[MAX_DATA];
183
184      for (subindex = 0; !ret && (feature->dataNumbers[subindex] >= 0); ++ subindex) {
185        if ((ret = sensors_get_feature (*chip, feature->dataNumbers[subindex], values + subindex))) {
186          sensorLog (LOG_ERR, "Error getting sensor data: %s/#%d: %s", chip->prefix, feature->dataNumbers[subindex], sensors_strerror (ret));
187          ret = 23;
188        }
189      }
190      if (ret == 0) {
191        if (action == DO_RRD) { // arse = "N:"
192          if (feature->rrd) {
193            const char *rrded = feature->rrd (values);
194            strcat (strcat (rrdBuff, ":"), rrded ? rrded : "U");
195          }
196        } else {
197          const char *formatted = feature->format (values, alarm, beep);
198          if (formatted) {
199            if (action == DO_READ) {
200              sensorLog (LOG_INFO, "  %s: %s", label, formatted);
201            } else {
202              sensorLog (LOG_ALERT, "Sensor alarm: Chip %s: %s: %s", chipName (chip), label, formatted);
203            }
204          }
205        }
206      }
207    }
208    if (label)
209      free (label);
210  }
211  return ret;
212}
213
214static int
215setChip
216(const sensors_chip_name *chip) {
217  int ret = 0;
218  if ((ret = idChip (chip))) {
219    sensorLog (LOG_ERR, "Error identifying chip: %s", chip->prefix);
220  } else if ((ret = sensors_do_chip_sets (*chip))) {
221    sensorLog (LOG_ERR, "Error performing chip sets: %s: %s", chip->prefix, sensors_strerror (ret));
222    ret = 50;
223  } else {
224    sensorLog (LOG_INFO, "Set.");
225  }
226  return ret;
227}
228
229static int
230doChip
231(const sensors_chip_name *chip, int action) {
232  int ret = 0;
233  if (action == DO_SET) {
234    ret = setChip (chip);
235  } else {
236    int index0, subindex, chipindex = -1;
237    for (index0 = 0; knownChips[index0]; ++ index0)
238      for (subindex = 0; knownChips[index0]->names[subindex]; ++ subindex)
239        if (!strcmp (chip->prefix, knownChips[index0]->names[subindex]))
240          chipindex = index0;
241    if (chipindex >= 0)
242      ret = doKnownChip (chip, knownChips[chipindex], action);
243    else if (action == DO_READ)
244      ret = readUnknownChip (chip);
245  }
246  return ret;
247}
248
249static int
250doChips
251(int action) {
252  const sensors_chip_name *chip;
253  int i = 0, j, ret = 0;
254
255  while ((ret == 0) && ((chip = sensors_get_detected_chips (&i)) != NULL)) {
256    for (j = 0; (ret == 0) && (j < numChipNames); ++ j) {
257      if (sensors_match_chip (*chip, chipNames[j])) {
258        ret = doChip (chip, action);
259      }
260    }
261  }
262
263  return ret;
264}
265
266int
267readChips
268(void) {
269  int ret = 0;
270
271  sensorLog (LOG_DEBUG, "sensor read started");
272  ret = doChips (DO_READ);
273  sensorLog (LOG_DEBUG, "sensor read finished");
274
275  return ret;
276}
277
278int
279scanChips
280(void) {
281  int ret = 0;
282
283  sensorLog (LOG_DEBUG, "sensor sweep started"); /* only logged in debug mode */
284  ret = doChips (DO_SCAN);
285  sensorLog (LOG_DEBUG, "sensor sweep finished");
286
287  return ret;
288}
289
290int
291setChips
292(void) {
293  int ret = 0;
294
295  sensorLog (LOG_DEBUG, "sensor set started");
296  ret = doChips (DO_SET);
297  sensorLog (LOG_DEBUG, "sensor set finished");
298
299  return ret;
300}
301
302/* TODO: loadavg entry */
303
304int
305rrdChips
306(void) {
307  int ret = 0;
308
309  strcpy (rrdBuff, "N");
310
311  sensorLog (LOG_DEBUG, "sensor rrd started"); 
312  ret = doChips (DO_RRD);
313  sensorLog (LOG_DEBUG, "sensor rrd finished");
314
315  return ret;
316}
Note: See TracBrowser for help on using the browser.