<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>2014/05/23 on Yano&#39;s digital garage</title>
    <link>https://www.bravotouring.com/~yano/archives/2014/05/23/</link>
    <description>Recent content in 2014/05/23 on Yano&#39;s digital garage</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Fri, 23 May 2014 00:37:57 +0900</lastBuildDate>
    <atom:link href="https://www.bravotouring.com/~yano/archives/2014/05/23/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>fplug_for_linux</title>
      <link>https://www.bravotouring.com/~yano/diary/it/20140523fplug4linux.htm</link>
      <pubDate>Fri, 23 May 2014 00:37:57 +0900</pubDate>
      <guid>https://www.bravotouring.com/~yano/diary/it/20140523fplug4linux.htm</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://www.bravotouring.com/~yano/diary/it/20140521fplug.htm&#34;&gt;先日調達&lt;/a&gt;した&lt;a href=&#34;http://www.bsc.fujitsu.com/&#34;&gt;富士通ビー・エス・シー&lt;/a&gt;の&lt;a href=&#34;http://www.bsc.fujitsu.com/services/f-plug/&#34;&gt;F-PLUG（エフプラグ）&lt;/a&gt;。&lt;/p&gt;&#xA;&lt;table align=&#34;right&#34; class=&#34;Landscape&#34;&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;&lt;img alt=&#34;F-PLUG&#34; src=&#34;https://www.bravotouring.com/~yano/images/2014/20140521fplug.jpg&#34;/&gt;&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td class=&#34;PhotoMemo&#34;&gt;F-PLUG&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;データの取得は一般公開されている&lt;a href=&#34;http://www.bsc.fujitsu.com/services/f-plug/downloads/message.html&#34;&gt;F-PLUG メッセージ一覧&lt;/a&gt;に従って一般的なRFCOMMの接続手順をベースに実装すれば良いのだが、まずは動作確認を含めて&lt;a href=&#34;http://obdnmagazine.blogspot.jp/&#34;&gt;OBDNマガジン&lt;/a&gt;の&lt;a href=&#34;https://github.com/goto2048/fplug_for_linux&#34;&gt;goto2048/fplug_for_linux&lt;/a&gt;を利用してみた。&lt;/p&gt;&#xA;&lt;p&gt;電力は期待通り採れたので動作確認はOKとしたのだが、&lt;span class=&#34;Software&#34;&gt;fptest&lt;/span&gt;で&lt;span class=&#34;Warning&#34;&gt;温度(Temperature)が採れない事&lt;/span&gt;がある事に気付いて調べてみたところ、応答メッセージが&lt;a href=&#34;http://www.bsc.fujitsu.com/services/f-plug/downloads/message.html&#34;&gt;F-PLUG メッセージ一覧&lt;/a&gt;の仕様と違って1バイト短い事がわかった。湿度、照度は大丈夫そうなのだが、ひとまずデータの最後から2バイトに注目するように改修した。&#xA;&lt;blockquote class=&#34;Log&#34;&gt;&#xA;yano@ML110G7:~/software/fplug_for_linux$ sudo &lt;span class=&#34;Software&#34;&gt;fptest&lt;/span&gt;&lt;br/&gt;&#xA;1.Get Temperature&lt;br/&gt;&#xA;2.Get Humidity&lt;br/&gt;&#xA;3.Illumination&lt;br/&gt;&#xA;4.Watt(Realtime)&lt;br/&gt;&#xA;5.Exit&lt;br/&gt;&#xA;Input command no -&gt;1&lt;br/&gt;&#xA;Temp Command:10,81,00,00,0E,F0,00,00,11,00,62,01,E0,00,&lt;br/&gt;&#xA;ret size=&lt;span class=&#34;Warning&#34;&gt;15&lt;/span&gt;&lt;br/&gt;&#xA;&lt;span class=&#34;Warning&#34;&gt;Temp Status:10,81,00,00,00,00,0E,F0,00,72,01,E0,02,0E,01,&lt;/span&gt;&lt;br/&gt;&#xA;Temperature=27.0&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;1.Get Temperature&lt;br/&gt;&#xA;2.Get Humidity&lt;br/&gt;&#xA;3.Illumination&lt;br/&gt;&#xA;4.Watt(Realtime)&lt;br/&gt;&#xA;5.Exit&lt;br/&gt;&#xA;Input command no -&gt;4&lt;br/&gt;&#xA;ret size=16&lt;br/&gt;&#xA;Realtime Wattmeter:10,81,00,00,00,22,00,0E,F0,00,72,01,E2,02,73,02,&lt;br/&gt;&#xA;Watt(Realtime)=62.7W&lt;br/&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;&lt;span class=&#34;Software&#34;&gt;fpstatus&lt;/span&gt;もsensors.cronからデータを取得できるよう同様に改修してみたのだが、応答メッセージの受信以前に要求メッセージの送信がうまくいかない事が多い事がわかった。調べてみると&lt;span class=&#34;Error&#34;&gt;&#34;Transport endpoint is not connected&#34;&lt;/span&gt;が発生しているので、ENOTCONNの場合はwriteをリトライするように対処。&lt;/p&gt;&#xA;&lt;p&gt;ついでに一度の接続で電力、温度、湿度、照度を立て続けに取得できるように改造。&#xA;&lt;blockquote class=&#34;Log&#34;&gt;&#xA;#include &lt;stdint.h&gt;&lt;br/&gt;&#xA;#include &lt;errno.h&gt;&lt;br/&gt;&#xA;#include &lt;stdio.h&gt;&lt;br/&gt;&#xA;#include &lt;sys/types.h&gt;&lt;br/&gt;&#xA;#include &lt;sys/stat.h&gt;&lt;br/&gt;&#xA;#include &lt;sys/ioctl.h&gt;&lt;br/&gt;&#xA;#include &lt;fcntl.h&gt;&lt;br/&gt;&#xA;#include &lt;termios.h&gt;&lt;br/&gt;&#xA;#include &lt;unistd.h&gt;&lt;br/&gt;&#xA;#include &lt;time.h&gt;&lt;br/&gt;&#xA;#include &lt;string.h&gt;&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;#include &#34;fplug.h&#34;&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;#define DEOJ_TOKEN &#34;\x0E\xF0\x00\x72&#34;&lt;br/&gt;&#xA;#define DEOJ_TOKEN_LEN 4&lt;br/&gt;&#xA;static unsigned char *&lt;br/&gt;&#xA;memmem(unsigned char *a, size_t a_len, unsigned char *b, size_t b_len)&lt;br/&gt;&#xA;{&lt;br/&gt;&#xA;    int i;&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    for (i = 0; i &lt; (a_len - b_len); i++ ){&lt;br/&gt;&#xA;        if ( a[i] != *b )&lt;br/&gt;&#xA;            continue;&lt;br/&gt;&#xA;        if ( !memcmp(&amp;a[i], b, b_len) )&lt;br/&gt;&#xA;            return &amp;a[i];&lt;br/&gt;&#xA;    }&lt;br/&gt;&#xA;    return NULL;&lt;br/&gt;&#xA;}&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;static void dump_message( char *mes, unsigned char *buf, int size  )&lt;br/&gt;&#xA;{&lt;br/&gt;&#xA;/*&lt;br/&gt;&#xA;    int cnt;&lt;br/&gt;&#xA;    printf( &#34;%s&#34;, mes );&lt;br/&gt;&#xA;    for ( cnt=0; cnt&lt;size; cnt++ ) {&lt;br/&gt;&#xA;        printf( &#34;%02X,&#34;, buf[cnt] );&lt;br/&gt;&#xA;    }&lt;br/&gt;&#xA;    printf( &#34;\n&#34; );&lt;br/&gt;&#xA;*/&lt;br/&gt;&#xA;    return;&lt;br/&gt;&#xA;}&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;int fp_main( int, int );&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;int main(int argc, char *argv[])&lt;br/&gt;&#xA;{&lt;br/&gt;&#xA;    int fd;&lt;br/&gt;&#xA;    struct termios oldtio, newtio;&lt;br/&gt;&#xA;    char *cmd;&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    if ( argc == 1 ) {&lt;br/&gt;&#xA;        printf(&#34;Usage: fpstatus &lt;option&gt;\n&#34;);&lt;br/&gt;&#xA;        return(0);&lt;br/&gt;&#xA;    }&lt;br/&gt;&#xA;    if ( *argv[1] == &#39;-&#39; ) argv[1]++;&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    fd = open(SERIAL_PORT, O_RDWR);&lt;br/&gt;&#xA;    if ( fd &lt; 0 ){&lt;br/&gt;&#xA;        perror(&#34;open(/dev/rfcomm0)&#34;);&lt;br/&gt;&#xA;        return 0;&lt;br/&gt;&#xA;    }&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    tcgetattr( fd, &amp;oldtio );&lt;br/&gt;&#xA;    newtio = oldtio;&lt;br/&gt;&#xA;    newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD;&lt;br/&gt;&#xA;    tcsetattr(fd, TCSANOW, &amp;newtio);&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    for ( cmd = argv[1]; cmd &amp;&amp; *cmd; cmd++ )&lt;br/&gt;&#xA;        fp_main(fd, *cmd);&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    printf( &#34;\n&#34;);&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    tcsetattr(fd, TCSANOW, &amp;oldtio);&lt;br/&gt;&#xA;    close(fd);&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    return 0;&lt;br/&gt;&#xA;}&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;typedef unsigned char uchar;&lt;br/&gt;&#xA;size_t fplug_request(int fd, uchar *req_buf,size_t req_len,uchar *res_buf, size_t bufsiz)&lt;br/&gt;&#xA;{&lt;br/&gt;&#xA;    struct timespec tmspec = { 0, 1000 * 1000 };&lt;br/&gt;&#xA;    int ret, i;&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    dump_message( &#34;Command:&#34;, req_buf, req_len);&lt;br/&gt;&#xA;    for (ret = i = 0;i &lt; 10; i++ ) {&lt;br/&gt;&#xA;        tmspec.tv_nsec = i * 100 * 1000 * 1000;&lt;br/&gt;&#xA;        ret = write(fd, req_buf, req_len);&lt;br/&gt;&#xA;        if ( ret == req_len )&lt;br/&gt;&#xA;                break;&lt;br/&gt;&#xA;// printf(&#34;write()=%d,errno=%d\n&#34;, ret, errno);&lt;br/&gt;&#xA;        switch ( errno ){&lt;br/&gt;&#xA;        case &lt;span class=&#34;Error&#34;&gt;ENOTCONN&lt;/span&gt; :&lt;br/&gt;&#xA;                nanosleep(&amp;tmspec, NULL);&lt;br/&gt;&#xA;                break;&lt;br/&gt;&#xA;        }&lt;br/&gt;&#xA;    }&lt;br/&gt;&#xA;    ret = read(fd, res_buf, bufsiz);&lt;br/&gt;&#xA;    dump_message( &#34;read:&#34;, res_buf, ret );&lt;br/&gt;&#xA;    return ret;&lt;br/&gt;&#xA;}&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;int fp_main( int fd, int mode )&lt;br/&gt;&#xA;{&lt;br/&gt;&#xA;    int cmd;&lt;br/&gt;&#xA;    int cnt;&lt;br/&gt;&#xA;    int a=0;&lt;br/&gt;&#xA;    double f;&lt;br/&gt;&#xA;    int ret;&lt;br/&gt;&#xA;    int i=0;&lt;br/&gt;&#xA;    unsigned char buf[BUFSIZ];&lt;br/&gt;&#xA;    time_t timer;&lt;br/&gt;&#xA;    struct tm *t;&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    switch(mode) {&lt;br/&gt;&#xA;        case &#39;t&#39;:&lt;br/&gt;&#xA;            while (1) {&lt;br/&gt;&#xA;                ret = fplug_request(fd, Temp, sizeof(Temp), buf, BUFSIZ);&lt;br/&gt;&#xA;                if (memmem(buf, ret, DEOJ_TOKEN, DEOJ_TOKEN_LEN)) break;&lt;br/&gt;&#xA;                if ( i++ &gt;10 ) return(0);&lt;br/&gt;&#xA;            }&lt;br/&gt;&#xA;            a = *(int16_t *)&amp;buf[ret-2];&lt;br/&gt;&#xA;            printf( &#34;FP_TEMP=%.1f;&#34;, (float)a / 10);&lt;br/&gt;&#xA;            break;&lt;br/&gt;&#xA;        case &#39;h&#39;:&lt;br/&gt;&#xA;            while (1) {&lt;br/&gt;&#xA;                ret = fplug_request(fd, Humid, sizeof(Humid), buf, BUFSIZ);&lt;br/&gt;&#xA;                if (memmem(buf, ret, DEOJ_TOKEN, DEOJ_TOKEN_LEN)) break;&lt;br/&gt;&#xA;                if ( i++ &gt;10 ) return(0);&lt;br/&gt;&#xA;            }&lt;br/&gt;&#xA;            a = *(uint16_t *)&amp;buf[ret-2];&lt;br/&gt;&#xA;            printf( &#34;FP_HUMID=%d;&#34;, a );&lt;br/&gt;&#xA;            break;&lt;br/&gt;&#xA;        case &#39;i&#39;:&lt;br/&gt;&#xA;            while (1) {&lt;br/&gt;&#xA;                ret = fplug_request(fd, Illum, sizeof(Illum), buf, BUFSIZ);&lt;br/&gt;&#xA;                if (memmem(buf, ret, DEOJ_TOKEN, DEOJ_TOKEN_LEN)) break;&lt;br/&gt;&#xA;                if ( i++ &gt;10 ) return(0);&lt;br/&gt;&#xA;            }&lt;br/&gt;&#xA;            a = *(uint16_t *)&amp;buf[ret-2];&lt;br/&gt;&#xA;            printf( &#34;FP_ILLUM=%d;&#34;, a );&lt;br/&gt;&#xA;            break;&lt;br/&gt;&#xA;        case &#39;w&#39;:&lt;br/&gt;&#xA;            while (1) {&lt;br/&gt;&#xA;                ret = fplug_request(fd, RWatt, sizeof(RWatt), buf, BUFSIZ);&lt;br/&gt;&#xA;                if (memmem(buf, ret, DEOJ_TOKEN, DEOJ_TOKEN_LEN)) break;&lt;br/&gt;&#xA;                if ( i++ &gt;10 ) return(0);&lt;br/&gt;&#xA;            }&lt;br/&gt;&#xA;            a = *(uint16_t *)&amp;buf[ret-2];&lt;br/&gt;&#xA;            printf( &#34;FP_WATT=%.1f;&#34;, (float)a / 10);&lt;br/&gt;&#xA;            break;&lt;br/&gt;&#xA;        default:&lt;br/&gt;&#xA;            break;&lt;br/&gt;&#xA;    }&lt;br/&gt;&#xA;}&#xA;&lt;/blockquote&gt;&#xA;&lt;iframe align=&#34;right&#34; frameborder=&#34;0&#34; marginheight=&#34;0&#34; marginwidth=&#34;0&#34; scrolling=&#34;no&#34; src=&#34;https://rcm-jp.amazon.co.jp/e/cm?lt1=_blank&amp;bc1=000000&amp;IS2=1&amp;bg1=FFFFFF&amp;fc1=000000&amp;lc1=0000FF&amp;t=yanosdigitalg-22&amp;o=9&amp;p=8&amp;l=as4&amp;m=amazon&amp;f=ifr&amp;ref=ss_til&amp;asins=B00AFQZRZM&#34; style=&#34;width:120px;height:240px;&#34;/&gt;&#xA;更にread待ちにならないようにpselect監視を挟んでみたのだが、期待通りに受信してもpselectでキャッチできないので、素直にwriteできたらreadするよう着地。あとrootでないと/dev/rfcomm0が&lt;span class=&#34;Warning&#34;&gt;&#34;Permission denied&#34;&lt;/span&gt;になるのでseteuidするようにしてみたのだが、うまくいかないという問題が残っているものの、取り敢えず期待通りに温度、湿度、照度を含めてデータは採れるようになった。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
