上海問屋で買ったものですが、PCsenserのTEMPerと同じ物のようです。
CentOS 6でpcsensor-1.0.0-multi.tgzを少し弄って使用しています。
MRTG用の出力オプションを使用して利用するつもりでしたが、私の環境では1回起動すると2回目以降正常動作しませんでした。
機器を抜き差しすると1回は正常動作するため、初期化か終了処理がうまくいっていないようなのですが、いろいろ試しても直せませんでした。
取りあえずループモード(-lオプション)では動作するので、次のようにHTTPで情報取得できるようにして使用しています。
$ curl http://localhost:9999/ 30.12 30.12 10:37 pcsensor $
pcsenser-1.0.0-multi との差分は下記になります。
Index: Makefile
===================================================================
--- Makefile (.../vendor/pcsensor/1.0.0-multi)
+++ Makefile (.../pcsensor/trunk)
@@ -3,7 +3,7 @@
CFLAGS = -O2 -Wall
pcsensor: pcsensor.c
- ${CC} -DUNIT_TEST -o $@ $^ -lusb
+ ${CC} -DUNIT_TEST -o $@ $^ -lusb -levent
clean:
rm -f pcsensor *.o
Index: pcsensor.c
===================================================================
--- pcsensor.c (.../vendor/pcsensor/1.0.0-multi)
+++ pcsensor.c (.../pcsensor/trunk)
@@ -34,6 +34,8 @@
#include
#include
#include
+#include
+#include
#define VERSION "1.0.0"
@@ -45,6 +47,8 @@
#define INTERFACE2 0x01
#define MAX_DEV 4
+#define PID_FILE "/var/run/pcsensor.pid"
+#define PORT_NUM 9999
const static int reqIntLen=8;
const static int reqBulkLen=8;
@@ -64,6 +68,7 @@
static int formato=0;
static int mrtg=0;
static int calibration=0;
+static int use_daemon=0;
static usb_dev_handle *handles[MAX_DEV];
@@ -78,24 +83,24 @@
void usb_detach(usb_dev_handle *lvr_winusb, int iInterface) {
int ret;
- ret = usb_detach_kernel_driver_np(lvr_winusb, iInterface);
- if(ret) {
- if(errno == ENODATA) {
- if(debug) {
- printf("Device already detached\n");
- }
- } else {
- if(debug) {
- printf("Detach failed: %s[%d]\n",
- strerror(errno), errno);
- printf("Continuing anyway\n");
- }
- }
- } else {
- if(debug) {
- printf("detach successful\n");
- }
- }
+ ret = usb_detach_kernel_driver_np(lvr_winusb, iInterface);
+ if(ret) {
+ if(errno == ENODATA) {
+ if(debug) {
+ printf("Device already detached\n");
+ }
+ } else {
+ if(debug) {
+ printf("Detach failed: %s[%d]\n",
+ strerror(errno), errno);
+ printf("Continuing anyway\n");
+ }
+ }
+ } else {
+ if(debug) {
+ printf("detach successful\n");
+ }
+ }
}
int setup_libusb_access() {
@@ -152,10 +157,10 @@
struct usb_bus *bus;
struct usb_device *dev;
- int i;
+ int i;
- memset(handles, 0, sizeof(handles));
- i = 0;
+ memset(handles, 0, sizeof(handles));
+ i = 0;
for (bus = usb_busses; bus; bus = bus->next) {
for (dev = bus->devices; dev; dev = dev->next) {
if (dev->descriptor.idVendor == VENDOR_ID &&
@@ -170,8 +175,8 @@
continue;
}
handles[i++] = handle;
- if (i == MAX_DEV)
- break;
+ if (i == MAX_DEV)
+ break;
}
}
}
@@ -314,6 +319,81 @@
(void) signal(SIGINT, SIG_DFL);
}
+
+void daemonize()
+{
+ pid_t pid;
+
+ pid = fork();
+ if (pid < 0) {
+ perror("failed fork()");
+ exit(1);
+ }
+
+ if (pid > 0) {
+ FILE *fp;
+ fp = fopen(PID_FILE, "w");
+ if (fp != NULL) {
+ fprintf(fp, "%d\n", pid);
+ fclose(fp);
+ }
+ exit(0);
+ }
+ seteuid(99);
+ setsid();
+}
+
+void http_handler(struct evhttp_request *req, void *arg)
+{
+ int i;
+ char msg[1024];
+
+ if (req->type != EVHTTP_REQ_GET) {
+ evhttp_send_error(req, HTTP_SERVUNAVAIL, "server unavail");
+ return;
+ }
+
+ struct evbuffer *ebuf;
+ ebuf = evbuffer_new();
+ if (ebuf == NULL) {
+ evhttp_send_error(req, HTTP_SERVUNAVAIL, "Cannot allocate buffer");
+ return;
+ }
+
+ for (i = 0; handles[i] != NULL && i < MAX_DEV; i++) {
+ float tempc;
+ struct tm *local;
+ time_t t;
+
+ memset(msg, 0, sizeof(msg));
+ control_transfer(handles[i], uTemperatura );
+ interrupt_read_temperatura(handles[i], &tempc);
+
+ t = time(NULL);
+ local = localtime(&t);
+
+ if (formato==2) {
+ tempc = (9.0 / 5.0 * tempc + 32.0);
+ }
+ snprintf(msg, sizeof(msg), "%.2f\n%.2f\n%02d:%02d\npcsensor\n", tempc, tempc, local->tm_hour, local->tm_min);
+ }
+ char content_length[8];
+
+ snprintf(content_length, sizeof(content_length)-1, "%d", strlen(msg));
+
+ evhttp_add_header(req->output_headers, "Content-Type", "text/plain");
+ evhttp_add_header(req->output_headers, "Content-Length", content_length);
+ evbuffer_add(ebuf, msg, strlen(msg));
+ evhttp_send_reply(req, HTTP_OK, "", ebuf);
+ evbuffer_free(ebuf);
+}
+
+void signal_cb(int fd, short event, void *arg)
+{
+ struct event *signal = arg;
+ // printf("%s: got signal %d, ev=%0x\n", __func__, EVENT_SIGNAL(signal), event);
+ event_base_loopexit(signal->ev_base, 0);
+}
int main( int argc, char **argv) {
@@ -323,7 +403,7 @@
time_t t;
memset(handles, 0, sizeof(handles));
- while ((c = getopt (argc, argv, "mfcvhl::a:")) != -1)
+ while ((c = getopt (argc, argv, "mfcvhl::a:d")) != -1)
switch (c)
{
case 'v':
@@ -359,19 +439,23 @@
} else {
break;
}
+ case 'd':
+ use_daemon=1;
+ break;
case '?':
case 'h':
printf("pcsensor version %s\n",VERSION);
- printf(" Aviable options:\n");
- printf(" -h help\n");
- printf(" -v verbose\n");
- printf(" -l[n] loop every 'n' seconds, default value is 5s\n");
- printf(" -c output only in Celsius\n");
- printf(" -f output only in Fahrenheit\n");
- printf(" -a[n] increase or decrease temperature in 'n' degrees for device calibration\n");
- printf(" -m output for mrtg integration\n");
+ printf(" Aviable options:\n");
+ printf(" -h help\n");
+ printf(" -v verbose\n");
+ printf(" -l[n] loop every 'n' seconds, default value is 5s\n");
+ printf(" -c output only in Celsius\n");
+ printf(" -f output only in Fahrenheit\n");
+ printf(" -a[n] increase or decrease temperature in 'n' degrees for device calibration\n");
+ printf(" -m output for mrtg integration\n");
+ printf(" -d daemon for mrtg integration\n");
- exit(EXIT_FAILURE);
+ exit(EXIT_FAILURE);
default:
if (isprint (optopt))
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
@@ -394,67 +478,112 @@
(void) signal(SIGINT, ex_program);
for (i = 0; handles[i] != NULL && i < MAX_DEV; i++) {
- ini_control_transfer(handles[i]);
+ ini_control_transfer(handles[i]);
- control_transfer(handles[i], uTemperatura );
- interrupt_read(handles[i]);
+ control_transfer(handles[i], uTemperatura );
+ interrupt_read(handles[i]);
- control_transfer(handles[i], uIni1 );
- interrupt_read(handles[i]);
+ control_transfer(handles[i], uIni1 );
+ interrupt_read(handles[i]);
- control_transfer(handles[i], uIni2 );
- interrupt_read(handles[i]);
- interrupt_read(handles[i]);
- }
+ control_transfer(handles[i], uIni2 );
+ interrupt_read(handles[i]);
+ interrupt_read(handles[i]);
+ }
- do {
- for (i = 0; handles[i] != NULL && i < MAX_DEV; i++) {
- control_transfer(handles[i], uTemperatura );
- interrupt_read_temperatura(handles[i], &tempc);
+ if (use_daemon) {
+ struct event_base *ebase;
+ struct evhttp *http;
+ struct event signal[2];
- t = time(NULL);
- local = localtime(&t);
+ daemonize();
- if (mrtg) {
- if (formato==2) {
- printf("%.2f\n", (9.0 / 5.0 * tempc + 32.0));
- printf("%.2f\n", (9.0 / 5.0 * tempc + 32.0));
- } else {
- printf("%.2f\n", tempc);
- printf("%.2f\n", tempc);
- }
-
- printf("%02d:%02d\n",
- local->tm_hour,
- local->tm_min);
+ ebase = event_base_new();
+ if (ebase == NULL) {
+ perror("failed event_base_new()");
+ goto EXIT;
+ }
+ signal_set(&signal[0], SIGHUP, signal_cb, &signal[0]);
+ event_base_set(ebase, &signal[0]);
+ signal_add(&signal[0], 0);
- printf("pcsensor\n");
- } else {
- printf("%04d/%02d/%02d %02d:%02d:%02d ",
- local->tm_year +1900,
- local->tm_mon + 1,
- local->tm_mday,
- local->tm_hour,
- local->tm_min,
- local->tm_sec);
+ signal_set(&signal[1], SIGTERM, signal_cb, &signal[1]);
+ event_base_set(ebase, &signal[1]);
+ signal_add(&signal[1], 0);
- if (formato==2) {
- printf("Temperature %.2fF\n", (9.0 / 5.0 * tempc + 32.0));
- } else if (formato==1) {
- printf("Temperature %.2fC\n", tempc);
- } else {
- printf("Temperature %.2fF %.2fC\n", (9.0 / 5.0 * tempc + 32.0), tempc);
- }
- }
-
- if (!bsalir)
- sleep(seconds);
- }
- } while (!bsalir);
+ http = evhttp_new(ebase);
+ if (http == NULL) {
+ perror("failed evhttp_new()");
+ event_base_free(ebase);
+ goto EXIT;
+ }
+
+ if (evhttp_bind_socket(http, "127.0.0.1", PORT_NUM) < 0) {
+ perror("failed evhttp_bind_socket()");
+ evhttp_free(http);
+ event_base_free(ebase);
+ goto EXIT;
+ }
+
+ evhttp_set_gencb(http, http_handler, NULL);
+ event_base_dispatch(ebase);
+
+ evhttp_free(http);
+ event_base_free(ebase);
+ unlink(PID_FILE);
+ }
+ else {
+ do {
+ for (i = 0; handles[i] != NULL && i < MAX_DEV; i++) {
+ control_transfer(handles[i], uTemperatura );
+ interrupt_read_temperatura(handles[i], &tempc);
+
+ t = time(NULL);
+ local = localtime(&t);
+
+ if (mrtg) {
+ if (formato==2) {
+ printf("%.2f\n", (9.0 / 5.0 * tempc + 32.0));
+ printf("%.2f\n", (9.0 / 5.0 * tempc + 32.0));
+ } else {
+ printf("%.2f\n", tempc);
+ printf("%.2f\n", tempc);
+ }
+
+ printf("%02d:%02d\n",
+ local->tm_hour,
+ local->tm_min);
+
+ printf("pcsensor\n");
+ } else {
+ printf("%04d/%02d/%02d %02d:%02d:%02d ",
+ local->tm_year +1900,
+ local->tm_mon + 1,
+ local->tm_mday,
+ local->tm_hour,
+ local->tm_min,
+ local->tm_sec);
+
+ if (formato==2) {
+ printf("Temperature %.2fF\n", (9.0 / 5.0 * tempc + 32.0));
+ } else if (formato==1) {
+ printf("Temperature %.2fC\n", tempc);
+ } else {
+ printf("Temperature %.2fF %.2fC\n", (9.0 / 5.0 * tempc + 32.0), tempc);
+ }
+ }
+
+ if (!bsalir)
+ sleep(seconds);
+ }
+ } while (!bsalir);
+ }
+EXIT:
for (i = 0; handles[i] != NULL && i < MAX_DEV; i++) {
usb_release_interface(handles[i], INTERFACE1);
usb_release_interface(handles[i], INTERFACE2);
+ usb_reset(handles[i]);
usb_close(handles[i]);
}
USB温度計を複数持っていないので試していませんが、恐らく複数機器ではうまく動かないかと…。初めてlibeventを使ってみましたが、面白いですね。