/* * Roomtemp PMDA * * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "pmapi.h" #include "impl.h" #include "pmda.h" #include "domain.h" #include "dsread.h" /* * Roomtemp PMDA * * This PMDA exports the temperature from one or more sensors built using * the DS2480 and DS1280 chipsets and MicroLAN technology from Dallas * Semiconductor Corporation. */ /* * Serial device */ static char *tty; /* * list of instances */ static pmdaInstid *device = NULL; /* * list of instance domains */ static pmdaIndom indomtab[] = { #define DEVICE 0 { DEVICE, 0, NULL }, }; typedef struct { unsigned char sn[8]; } sn_t; sn_t *sntab = NULL; /* * All metrics supported in this PMDA - one table entry for each. * The 4th field specifies the serial number of the instance domain * for the metric, and must be either PM_INDOM_NULL (denoting a * metric that only ever has a single value), or the serial number * of one of the instance domains declared in the instance domain table * (i.e. in indomtab, above). */ static pmdaMetric metrictab[] = { /* roomtemp.celsius */ { NULL, { PMDA_PMID(0,0), PM_TYPE_FLOAT, DEVICE, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, }, /* roomtemp.fahrenheit */ { NULL, { PMDA_PMID(0,1), PM_TYPE_FLOAT, DEVICE, PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, }, }; /* * callback provided to pmdaFetch */ static int roomtemp_fetchCallBack(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom) { __pmID_int *idp = (__pmID_int *)&(mdesc->m_desc.pmid); char return_msg[128]; int numval = 0; if (idp->cluster == 0) { if (inst >= indomtab[DEVICE].it_numinst) return PM_ERR_INST; switch (idp->item) { case 0: /* roomtemp.celsius */ case 1: /* roomtemp.fahrenheit */ if (!Aquire1WireNet(tty, return_msg)) { fputs(return_msg, stderr); exit(1); } if (ReadTemperature(sntab[inst].sn, &atom->f)) numval = 1; Release1WireNet(return_msg); if (idp->item == 1) /* convert to fahrenheit */ atom->f = atom->f * 9 / 5 + 32; break; default: return PM_ERR_PMID; } } else return PM_ERR_PMID; return numval; } /* * Initialise the agent */ void roomtemp_init(pmdaInterface *dp) { int i; char return_msg[128]; unsigned char *p; if (dp->status != 0) return; pmdaSetFetchCallBack(dp, roomtemp_fetchCallBack); if (!Aquire1WireNet(tty, return_msg)) { fputs(return_msg, stderr); exit(1); } for (i = 0; ; i++) { if ((p = nextsensor()) == NULL) break; if ((sntab = (sn_t *)realloc(sntab, (i+1) * sizeof(sn_t))) == NULL) { __pmNoMem("roomtemp_init: realloc sntab", (i+1) * sizeof(sn_t), PM_FATAL_ERR); } if ((device = (pmdaInstid *)realloc(device, (i+1) * sizeof(pmdaInstid))) == NULL) { __pmNoMem("roomtemp_init: realloc device", (i+1) * sizeof(pmdaInstid), PM_FATAL_ERR); } if ((device[i].i_name = (char *)malloc(17)) == NULL) { __pmNoMem("roomtemp_init: malloc name", 17, PM_FATAL_ERR); } memcpy(sntab[i].sn, p, 8); /* SN for later fetch */ device[i].i_inst = i; /* internal name is ordinal number */ /* external name is SN in hex */ sprintf(device[i].i_name, "%02X%02X%02X%02X%02X%02X%02X%02X", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); fprintf(stderr, "Found temp sensor SN %s\n", device[i].i_name); } Release1WireNet(return_msg); indomtab[DEVICE].it_numinst = i; indomtab[DEVICE].it_set = device; pmdaInit(dp, indomtab, sizeof(indomtab)/sizeof(indomtab[0]), metrictab, sizeof(metrictab)/sizeof(metrictab[0])); } static void usage(void) { fprintf(stderr, "Usage: %s [options] tty ...\n\n", pmProgname); fputs("Options:\n" " -d domain use domain (numeric) for metrics domain of PMDA\n" " -l logfile write log into logfile rather than using default log name\n" "\nExactly one of the following options may appear:\n" " -i port expect PMCD to connect on given inet port (number or name)\n" " -p expect PMCD to supply stdin/stdout (pipe)\n" " -u socket expect PMCD to connect on given unix domain socket\n" " -6 port expect PMCD to connect on given ipv6 port (number or name)\n", stderr); exit(1); } int main(int argc, char **argv) { int err = 0; int sep = __pmPathSeparator(); pmdaInterface dispatch; char mypath[MAXPATHLEN]; __pmSetProgname(argv[0]); snprintf(mypath, sizeof(mypath), "%s%c" "roomtemp" "%c" "help", pmGetConfig("PCP_PMDAS_DIR"), sep, sep); pmdaDaemon(&dispatch, PMDA_INTERFACE_3, pmProgname, ROOMTEMP, "roomtemp.log", mypath); if (pmdaGetOpt(argc, argv, "D:d:i:l:pu:6:?", &dispatch, &err) != EOF) err++; if (err) usage(); if (argc != optind+1) usage(); tty = argv[optind]; pmdaOpenLog(&dispatch); roomtemp_init(&dispatch); pmdaConnect(&dispatch); pmdaMain(&dispatch); exit(0); }