2014年8月12日火曜日

USB温度計

昨年末辺りからUSB接続の温度計でPC付近の室温を計測しています。
上海問屋で買ったものですが、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を使ってみましたが、面白いですね。

2014年4月12日土曜日

Mac mini購入

OS X Server搭載モデルのMac mini MD389J/Aを購入しました。
16GBメモリも買ったのですが、だいぶ高くなっていますね。去年あたりに買っておけばよかったかな。
OS X Serverのメールサーバは、プッシュ通知ができるようなので試してみたいと思います。

また、Windows 8.1も買いました。
どちらかというとWindowsを使う必要があり、ホストサーバ用にMac miniを買った感じです。
Windows 7にしようか迷いましたが、Update1でフットプリントも小さくなるようなので8.1にしました。
折角なので、タッチパネルなしでのイラつき具合を楽しもうと思います。

2014年3月14日金曜日

iPhone 5s購入

今月は、iPhone 4s回線の更新月でした。
4sは気に入っていたのですが更新すると月額費用が上がるようなので、AuからDocomoの5sにMNPしました。

32GBモデルで一括0円でした。割引もあるので月額3000円以下に。
それにしてもMNPと機種変更のサービスの違いは、なんとかならないんでしょうかね。
既存ユーザの満足度を上げる方向になってくれればいいのですが。

で、DocomoのiPhoneのキャリアメールってプッシュ型じゃないんですね。
「新着のお知らせ」設定は出来るのですが、これ微妙に使いにくいというか邪魔なんだけど設定で変えられるんでしょうか?

2014年1月11日土曜日

裸族の集合住宅5Bay SATA6G USB3.0&eSATA with CentOS 6.5

下記構成に、USB3でHDDを追加しようと裸族の集合住宅5Bay[CRSJ535EU3S6G]を購入しました。
  • ASRock H87E-ITX/ac
  • Intel Core i7-4770S
  • CentOS 6.5
集合住宅に4台のHDDを設定、USB接続すると次のようなSense Key : No Sense [current] [descriptor]メッセージを出し続けます。
Jan  5 21:50:06 abc kernel: usb 4-6: new SuperSpeed USB device number 4 using xhci_hcd
Jan  5 21:50:06 abc kernel: usb 4-6: New USB device found, idVendor=152d, idProduct=0567
Jan  5 21:50:06 abc kernel: usb 4-6: New USB device strings: Mfr=10, Product=11, SerialNumber=5
Jan  5 21:50:06 abc kernel: usb 4-6: Product: USB to ATA/ATAPI Bridge
Jan  5 21:50:06 abc kernel: usb 4-6: Manufacturer: JMicron
Jan  5 21:50:06 abc kernel: usb 4-6: SerialNumber: 152Dxxxxxxxx
Jan  5 21:50:06 abc kernel: usb 4-6: configuration #1 chosen from 1 choice
Jan  5 21:50:06 abc kernel: Initializing USB Mass Storage driver...
Jan  5 21:50:06 abc kernel: scsi6 : SCSI emulation for USB Mass Storage devices
Jan  5 21:50:06 abc kernel: usbcore: registered new interface driver usb-storage
Jan  5 21:50:06 abc kernel: USB Mass Storage support registered.
Jan  5 21:50:07 abc kernel: scsi 6:0:0:0: Direct-Access     ST3000DM 001-1CH166       1520 PQ: 0 ANSI: 6
Jan  5 21:50:07 abc kernel: scsi 6:0:0:1: Direct-Access     ST3000DM 001-1CH166       1520 PQ: 0 ANSI: 6 
Jan  5 21:50:07 abc kernel: scsi 6:0:0:2: Direct-Access     ST3000DM 001-1CH166       1520 PQ: 0 ANSI: 6 
Jan  5 21:50:07 abc kernel: scsi 6:0:0:3: Direct-Access     ST3000DM 001-1CH166       1520 PQ: 0 ANSI: 6 
Jan  5 21:50:07 abc kernel: sd 6:0:0:0: Attached scsi generic sg6 type 0 
Jan  5 21:50:07 abc kernel: sd 6:0:0:0: [sdg] Very big device. Trying to use READ CAPACITY(16).
Jan  5 21:50:07 abc kernel: sd 6:0:0:1: Attached scsi generic sg7 type 0 
Jan  5 21:50:07 abc kernel: sd 6:0:0:0: [sdg] 5860533168 512-byte logical blocks: (3.00 TB/2.72 TiB)
Jan  5 21:50:07 abc kernel: sd 6:0:0:0: [sdg] 4096-byte physical blocks
Jan  5 21:50:07 abc kernel: sd 6:0:0:2: Attached scsi generic sg8 type 0 
Jan  5 21:50:07 abc kernel: sd 6:0:0:2: [sdi] Very big device. Trying to use READ CAPACITY(16).
Jan  5 21:50:07 abc kernel: sd 6:0:0:3: Attached scsi generic sg9 type 0 
Jan  5 21:50:07 abc kernel: sd 6:0:0:2: [sdi] 5860533168 512-byte logical blocks: (3.00 TB/2.72 TiB)
Jan  5 21:50:07 abc kernel: sd 6:0:0:2: [sdi] 4096-byte physical blocks
Jan  5 21:50:07 abc kernel: sd 6:0:0:2: [sdi] Write Protect is off
Jan  5 21:50:07 abc kernel: sd 6:0:0:2: [sdi] Assuming drive cache: write through
Jan  5 21:50:07 abc kernel: sd 6:0:0:2: [sdi] Very big device. Trying to use READ CAPACITY(16).
Jan  5 21:50:07 abc kernel: sd 6:0:0:0: [sdg] Write Protect is off
Jan  5 21:50:07 abc kernel: sd 6:0:0:0: [sdg] Assuming drive cache: write through
Jan  5 21:50:07 abc kernel: sd 6:0:0:2: [sdi] Assuming drive cache: write through
Jan  5 21:50:07 abc kernel: sdi:
Jan  5 21:50:07 abc kernel: sd 6:0:0:2: [sdi] Sense Key : No Sense [current] [descriptor]
Jan  5 21:50:07 abc kernel: Descriptor sense data with sense descriptors (in hex):
Jan  5 21:50:07 abc kernel:        72 00 05 00 00 00 00 0a 00 00 00 00 24 00 00 00 
Jan  5 21:50:07 abc kernel:        00 00 
Jan  5 21:50:07 abc kernel: sd 6:0:0:2: [sdi] Add. Sense: Logical unit does not respond to selection
Jan  5 21:50:07 abc kernel: sd 6:0:0:2: [sdi] Sense Key : No Sense [current] [descriptor]
Jan  5 21:50:07 abc kernel: Descriptor sense data with sense descriptors (in hex):
Jan  5 21:50:07 abc kernel:        72 00 05 00 00 00 00 0a 00 00 00 00 24 00 00 00
Jan  5 21:50:07 abc kernel:        00 00
Jan  5 21:50:07 abc kernel: sd 6:0:0:2: [sdi] Add. Sense: Logical unit does not respond to selection
Jan  5 21:50:07 abc kernel: sd 6:0:0:2: [sdi] Sense Key : No Sense [current] [descriptor]
Jan  5 21:50:07 abc kernel: Descriptor sense data with sense descriptors (in hex):
Jan  5 21:50:07 abc kernel:        72 00 05 00 00 00 00 0a 00 00 00 00 24 00 00 00
Jan  5 21:50:07 abc kernel:        00 00
Jan  5 21:50:07 abc kernel: sd 6:0:0:2: [sdi] Add. Sense: Logical unit does not respond to selection
Jan  5 21:50:07 abc kernel: sd 6:0:0:2: [sdi] Sense Key : No Sense [current] [descriptor]
Jan  5 21:50:07 abc kernel: Descriptor sense data with sense descriptors (in hex):
Jan  5 21:50:07 abc kernel:        72 00 05 00 00 00 00 0a 00 00 00 00 24 00 00 00
Jan  5 21:50:07 abc kernel:        00 00
マザーボードのSATAに6台のHDDを接続しているので、集合住宅のHDDはsdg〜sdjと認識されるのですが、1台目のsdg以外は、Sense Key : No Sense [current] [descriptor]を出力し続けます。

集合住宅にHDD1台設定だと問題なし、2台以上のHDDを設定すると台数によらず同じ現象になるようです。
USB2, USB3のどちらのポートに接続しても変化なしで、同じOSですが、他のHWに接続してみても同じ現象が発生します。

既にPCI-Eスロットに空きがないのでSATA増設ともいかず、さて困りました。