Re: Temperature sensor
Scott Mcdermott <[email protected]> Thu, 20 Mar 2003 14:08:19 -0500
| Newsgroups | gmane.network.netsaint.user |
|---|---|
| Message-ID | <[email protected]> |
David Arnold on Thu 20/03 09:54 -0800: > Can you send me the scripts that you wrote to interface to > this device. We are in the process of purchasing a unit > for our server room. I wrote this to Netsaint plugin for the Hot Little Therm.
check_hlt.c
(text/plain, 6.5 KB)
/* * Netsaint "hot little therm" plugin (for remote execution by the ssh plugin) * * author: Scott McDermott <[email protected]> * owner: Questra Consulting * license: GPL >= 2.0 * therm unit: http://www.spyderplant.com/ * * arguments (all required): * -d <device with HLT unit> * -w <fahrenheit temperature warning threshold (too cold)> * -c <fahrenheit temperature critical threshold (way too cold)> * -W <fahrenheit temperature warning threshold (too hot)> * -C <fahrenheit temperature critical threshold (way too hot)> */ #define _GNU_SOURCE #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <termios.h> #include <string.h> #include <sys/time.h> /* plugin return states */ #define STATE_UNKNOWN -1 /* plugin can't run for some reason */ #define STATE_OK 0 /* everything within parameters */ #define STATE_WARNING 1 /* warning threshold exceeded */ #define STATE_CRITICAL 2 /* critical threshold exceeded */ /* program defines */ #define READ_LEN 6 /* chars in string output from therm */ #define READ_TIMEOUT 10 /* number of seconds to wait for input to be available before aborting */ #define CMD_GET_TMP 0x20 /* the address of the probe...in this case, unit 0, probe 2 (endianness) */ #define PORT_SPEED B1200 /* terminal baud rate macro (for both directions) */ int xread (int, void *, size_t); int xopen (char *, int); void *xmalloc (ssize_t); char *xstrdup (char *); void process_options (int, char **); void send_command_byte (int, int); void setup_terminal (int); void wait_for_input (int); char *decode_alert (int); unsigned long warning_low, critical_low, warning_high, critical_high; char *device; int main(int argc, char **argv) { int ret, fd, nr_read, alert_state; char *result, *buf; float celsius, fahrenheit; process_options(argc, argv); buf = xmalloc(READ_LEN + 1); memset(buf, 0, sizeof(buf)); fd = xopen(device, O_RDWR); setup_terminal(fd); send_command_byte(fd, CMD_GET_TMP); /* keep reading bytes as they become available until READ_LEN */ for (nr_read = 0; nr_read < READ_LEN; nr_read += ret) { wait_for_input(fd); ret = xread(fd, buf + nr_read, READ_LEN - nr_read); } if (sscanf(buf, "%f", &celsius) != 1) { fprintf(stderr, "main: sscanf failed\n"); exit(EXIT_FAILURE); } fahrenheit = celsius * 9.0 / 5.0 + 32.0; if (fahrenheit > warning_high || fahrenheit < warning_low) { alert_state = STATE_WARNING; if (fahrenheit > critical_high || fahrenheit < critical_low) alert_state = STATE_CRITICAL; } else alert_state = STATE_OK; printf("HLT: %s: %3.1f (C) %3.1f (F)\n", decode_alert(alert_state), celsius, fahrenheit); exit(alert_state); } void setup_terminal(int fd) { struct termios tio; if (tcgetattr(fd, &tio) == -1) { perror("tcgetattr"); exit(EXIT_FAILURE); } tio.c_iflag = IGNPAR | INPCK; tio.c_cflag = CLOCAL | CREAD | CS8; memset(&tio.c_oflag, 0, sizeof tio.c_oflag); memset(&tio.c_lflag, 0, sizeof tio.c_lflag); if (cfsetispeed(&tio, (speed_t)PORT_SPEED) == -1) { perror("cfsetispeed"); exit(EXIT_FAILURE); } if (cfsetospeed(&tio, (speed_t)PORT_SPEED) == -1) { perror("cfsetospeed"); exit(EXIT_FAILURE); } if (tcsetattr(fd, TCSANOW, &tio) == -1) { perror("tcsetattr"); exit(EXIT_FAILURE); } if (tcflush(fd, TCIOFLUSH) == -1) { perror("tcflush"); exit(EXIT_FAILURE); } } void send_command_byte(int fd, int cmd) { if (write(fd, &cmd, 1) == -1) { perror("write"); exit(EXIT_FAILURE); } } /* * the therm doesn't report back immediately so we select on the input fd and * timeout if we don't hear anything before READ_TIMEOUT seconds. Also * because of the slow line speed, we have to keep looping because a single * read() doesn't return all the bytes we know are coming. */ void wait_for_input(int fd) { fd_set fdset; struct timeval tv; memset(&tv, 0, sizeof tv); tv.tv_sec = READ_TIMEOUT; FD_ZERO(&fdset); FD_SET(fd, &fdset); if (!(select(FD_SETSIZE, &fdset, NULL, NULL, &tv))) { fprintf(stderr, "wait_for_input: input never became available" "before READ_TIMEOUT (%d) seconds\n", READ_TIMEOUT); exit(EXIT_FAILURE); } } void process_options(int count, char **vector) { int ret; opterr = 0; while ((ret = getopt(count, vector, "w:c:d:W:C:")) != -1) switch (ret) { case 'w': if (!(warning_low = strtoul(optarg, NULL, 10))) { fprintf(stderr, "main: strtoul error (w)\n"); exit(EXIT_FAILURE); } continue; case 'c': if (!(critical_low = strtoul(optarg, NULL, 10))) { fprintf(stderr, "main: strtoul error (c)\n"); exit(EXIT_FAILURE); } continue; case 'W': if (!(warning_high = strtoul(optarg, NULL, 10))) { fprintf(stderr, "main: strtoul error (W)\n"); exit(EXIT_FAILURE); } continue; case 'C': if (!(critical_high = strtoul(optarg, NULL, 10))) { fprintf(stderr, "main: strtoul error (C)\n"); exit(EXIT_FAILURE); } continue; case 'd': device = xstrdup(optarg); continue; case '?': fprintf(stderr, "unknown option argument\n"); exit(EXIT_FAILURE); case ':': fprintf(stderr, "required option argument missing\n"); exit(EXIT_FAILURE); default: fprintf(stderr, "invalid option\n"); exit(EXIT_FAILURE); } if (!device || !warning_low || !critical_low || !warning_high || !critical_high) { fprintf(stderr, "required arguments missing\n"); exit(STATE_UNKNOWN); } } char * decode_alert(int i) { switch (i) { case STATE_UNKNOWN: return (xstrdup("ERROR")); case STATE_OK: return (xstrdup("OK")); case STATE_WARNING: return (xstrdup("WARNING")); case STATE_CRITICAL: return (xstrdup("CRITICAL")); default: return (xstrdup("IMPOSSIBLE")); } } int xopen(char *name, int flags) { int fd; if (!(name)) { fprintf(stderr, "xopen: no name given!\n"); exit(EXIT_FAILURE); } if ((fd = open(name, flags)) == -1) { perror("xopen"); exit(EXIT_FAILURE); } return fd; } int xread(int fd, void *address, size_t count) { int ret; if (!(address)) { fprintf(stderr, "xread: address invalid\n"); exit(EXIT_FAILURE); } if ((ret = read(fd, address, count)) == -1) { perror("xread: read"); exit(EXIT_FAILURE); } return ret; } void * xmalloc(ssize_t sz) { void *p; if (!(p = malloc(sz))) { perror("xmalloc: allocation failure"); exit(EXIT_FAILURE); } return p; } char * xstrdup(char *s) { char *p; if (!s) { fprintf(stderr, "xstrdup: null argument!\n"); exit(EXIT_FAILURE); } if (!(p = strdup(s))) { perror("xstrdup"); exit(EXIT_FAILURE); } return p; }