<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>2014/06/16 on Yano&#39;s digital garage</title>
    <link>https://www.bravotouring.com/~yano/archives/2014/06/16/</link>
    <description>Recent content in 2014/06/16 on Yano&#39;s digital garage</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Mon, 16 Jun 2014 23:08:36 +0900</lastBuildDate>
    <atom:link href="https://www.bravotouring.com/~yano/archives/2014/06/16/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>fplug_for_linux</title>
      <link>https://www.bravotouring.com/~yano/diary/it/20140616fplug4linux.htm</link>
      <pubDate>Mon, 16 Jun 2014 23:08:36 +0900</pubDate>
      <guid>https://www.bravotouring.com/~yano/diary/it/20140616fplug4linux.htm</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://www.bravotouring.com/~yano/diary/it/20140523fplug4linux.htm&#34;&gt;先日導入&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;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;https://www.bravotouring.com/~yano/diary/it/20140526sensors.htm&#34;&gt;ゴミデータっぽい&lt;/a&gt;値が採れたりしたので&lt;a href=&#34;https://www.bravotouring.com/~yano/diary/it/20140528fplug4linux.htm&#34;&gt;改修にトライ&lt;/a&gt;していたが、シリアル通信のパラメータやリトライ手順など地道にプロトコル実装を固める事で、&lt;span class=&#34;Topics&#34;&gt;1週間以上連続&lt;/span&gt;で安定して（ペアリングも解除されずに）計測できる事を確認した。&lt;/p&gt;&#xA;&lt;p&gt;ポイントとしては&#xA;&lt;ul&gt;&#xA;&lt;li&gt;RTS/CTSによるフロー制御&lt;/li&gt;&#xA;&lt;li&gt;Rawモード送信&lt;/li&gt;&#xA;&lt;li&gt;非カノニカル受信&lt;/li&gt;&#xA;&lt;li&gt;応答が無い場合は要求を再送信&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;で、最終版の&lt;span class=&#34;Software&#34;&gt;fpstatus&lt;/span&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;stdlib.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;#undef  DEBUG&lt;br/&gt;&#xA;#define ENOTCONN_RETRY_MAX      10&lt;br/&gt;&#xA;#define MSG_RETRY_MAX           5&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;#define FPLUG_EXEC(fd,msg,buf)  fplug_exec((fd),(msg),sizeof((msg)),(buf),sizeof((buf)))&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;typedef unsigned char uchar;&lt;br/&gt;&#xA;static uint16_t tid = 0x0001;&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;void hunt_tid(uchar *buf)&lt;br/&gt;&#xA;{&lt;br/&gt;&#xA;    *(uint16_t *)&amp;buf[2] = tid++;&lt;br/&gt;&#xA;}&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;typedef uchar uchar;&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;static void dump_message( char *mes, uchar *buf, int size  )&lt;br/&gt;&#xA;{&lt;br/&gt;&#xA;#ifdef DEBUG&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;#endif&lt;br/&gt;&#xA;    return;&lt;br/&gt;&#xA;}&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;int fplug_exec(int fd, uchar *req_msg, 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, j;&lt;br/&gt;&#xA;    uchar req_buf[BUFSIZ];&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    memcpy(req_buf, req_msg, req_len);&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    for (i = 0;i &lt; MSG_RETRY_MAX; i++ ) {&lt;br/&gt;&#xA;        hunt_tid(req_buf);&lt;br/&gt;&#xA;        dump_message( &#34;Command:&#34;, req_buf, req_len);&lt;br/&gt;&#xA;        for (ret = j = 0;j &lt; ENOTCONN_RETRY_MAX; j++ ) {&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;#ifdef DEBUG&lt;br/&gt;&#xA;printf(&#34;%s:%d; write()=%d,errno=%d\n&#34;, __FILE__, __LINE__, ret, errno);&lt;br/&gt;&#xA;#endif&lt;br/&gt;&#xA;            switch ( errno ){&lt;br/&gt;&#xA;            case ENOTCONN :&lt;br/&gt;&#xA;                tmspec.tv_nsec = 500 * 1000 * 1000;&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;        if ( ret &lt;= 0 )&lt;br/&gt;&#xA;            break;&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;        for (j = 0;j &lt; MSG_RETRY_MAX &amp;&amp; !(ret = read(fd, res_buf, bufsiz)); j++ ) {&lt;br/&gt;&#xA;            tmspec.tv_sec = 0;&lt;br/&gt;&#xA;            tmspec.tv_nsec = (j+1) * 100 * 1000 * 1000;&lt;br/&gt;&#xA;            nanosleep(&amp;tmspec, NULL);&lt;br/&gt;&#xA;        }&lt;br/&gt;&#xA;        if ( ret &lt;= 0 ){&lt;br/&gt;&#xA;#ifdef DEBUG&lt;br/&gt;&#xA;printf(&#34;%s:%d; read()=%d,errno=%d\n&#34;, __FILE__, __LINE__, ret, errno);&lt;br/&gt;&#xA;#endif&lt;br/&gt;&#xA;            continue;&lt;br/&gt;&#xA;        }&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;        dump_message( &#34;read:&#34;, res_buf, ret );&lt;br/&gt;&#xA;        if (4 &lt; ret &amp;&amp; !memcmp(req_buf, res_buf, 4)){   // TID match&lt;br/&gt;&#xA;#ifdef DEBUG&lt;br/&gt;&#xA;printf(&#34;%s:%d; read()=%d\n&#34;, __FILE__, __LINE__, ret);&lt;br/&gt;&#xA;#endif&lt;br/&gt;&#xA;            return ret;&lt;br/&gt;&#xA;        }&lt;br/&gt;&#xA;    }&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    return -1;&lt;br/&gt;&#xA;}&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;int fplug_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 ret;&lt;br/&gt;&#xA;    int i=0;&lt;br/&gt;&#xA;    uchar buf[BUFSIZ];&lt;br/&gt;&#xA;    uchar *szMode, szResult[BUFSIZ];&lt;br/&gt;&#xA;    time_t timer;&lt;br/&gt;&#xA;    struct tm *t;&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    strcpy(szResult, &#34;x&#34;);&lt;br/&gt;&#xA;    szMode = szResult;&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    switch(mode) {&lt;br/&gt;&#xA;    case &#39;h&#39;:&lt;br/&gt;&#xA;        szMode = &#34;FP_HUMID&#34;;&lt;br/&gt;&#xA;        for ( i = 0; i &lt; MSG_RETRY_MAX &amp;&amp; 0 &lt; (ret = FPLUG_EXEC(fd, Humid, buf)); i++ ){&lt;br/&gt;&#xA;            uint16_t a = *(uint16_t *)&amp;buf[ret-2];&lt;br/&gt;&#xA;            if ( 100 &lt; a )&lt;br/&gt;&#xA;                continue;&lt;br/&gt;&#xA;            sprintf(szResult, &#34;%d&#34;, a );&lt;br/&gt;&#xA;            break;&lt;br/&gt;&#xA;        }&lt;br/&gt;&#xA;        break;&lt;br/&gt;&#xA;    case &#39;i&#39;:&lt;br/&gt;&#xA;        szMode = &#34;FP_ILLUM&#34;;&lt;br/&gt;&#xA;        for ( i = 0; i &lt; MSG_RETRY_MAX &amp;&amp; 0 &lt; (ret = FPLUG_EXEC(fd, Illum, buf)); i++ ){&lt;br/&gt;&#xA;            uint16_t a = *(uint16_t *)&amp;buf[ret-2];&lt;br/&gt;&#xA;            if ( 0xFFFD &lt; a )&lt;br/&gt;&#xA;                continue;&lt;br/&gt;&#xA;            sprintf(szResult, &#34;%d&#34;, a );&lt;br/&gt;&#xA;            break;&lt;br/&gt;&#xA;        }&lt;br/&gt;&#xA;        break;&lt;br/&gt;&#xA;    case &#39;t&#39;:&lt;br/&gt;&#xA;        szMode = &#34;FP_TEMP&#34;;&lt;br/&gt;&#xA;        for ( i = 0; i &lt; MSG_RETRY_MAX &amp;&amp; 0 &lt; (ret = FPLUG_EXEC(fd, Temp, buf)); i++ ){&lt;br/&gt;&#xA;            int16_t a = *(int16_t *)&amp;buf[ret-2];&lt;br/&gt;&#xA;            if ( a &lt; -100 || 500 &lt; a )&lt;br/&gt;&#xA;                continue;&lt;br/&gt;&#xA;            sprintf(szResult, &#34;%.1f&#34;, (float)a / 10);&lt;br/&gt;&#xA;            break;&lt;br/&gt;&#xA;        }&lt;br/&gt;&#xA;        break;&lt;br/&gt;&#xA;    case &#39;w&#39;:&lt;br/&gt;&#xA;        szMode = &#34;FP_WATT&#34;;&lt;br/&gt;&#xA;        for ( i = 0; i &lt; MSG_RETRY_MAX &amp;&amp; 0 &lt; (ret = FPLUG_EXEC(fd, RWatt, buf)); i++ ){&lt;br/&gt;&#xA;            int16_t a = *(int16_t *)&amp;buf[ret-2];&lt;br/&gt;&#xA;            if ( 2000 &lt; a )&lt;br/&gt;&#xA;                continue;&lt;br/&gt;&#xA;            sprintf(szResult, &#34;%.1f&#34;, (float)a / 10);&lt;br/&gt;&#xA;            break;&lt;br/&gt;&#xA;        }&lt;br/&gt;&#xA;        break;&lt;br/&gt;&#xA;    default:&lt;br/&gt;&#xA;        szMode = &#34;FP_unknown&#34;;&lt;br/&gt;&#xA;        break;&lt;br/&gt;&#xA;    }&lt;br/&gt;&#xA;    printf( &#34;%s=%s;&#34;, szMode, szResult);&lt;br/&gt;&#xA;}&lt;br/&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;&lt;br/&gt;&#xA;int main(int argc, char *argv[])&lt;br/&gt;&#xA;{&lt;br/&gt;&#xA;    int fd, opt;&lt;br/&gt;&#xA;    struct termios oldtio, newtio;&lt;br/&gt;&#xA;    char cmdbuf[16];&lt;br/&gt;&#xA;    char *cmd = cmdbuf, *cmd_all = &#34;with&#34;;&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    memset(cmdbuf, 0x00, sizeof(cmdbuf));&lt;br/&gt;&#xA;    while ((opt = getopt(argc, argv, cmd_all)) != -1) {&lt;br/&gt;&#xA;        switch (opt) {&lt;br/&gt;&#xA;        case &#39;w&#39;:&lt;br/&gt;&#xA;        case &#39;i&#39;:&lt;br/&gt;&#xA;        case &#39;t&#39;:&lt;br/&gt;&#xA;        case &#39;h&#39;:&lt;br/&gt;&#xA;            *cmd++ = tolower(opt);&lt;br/&gt;&#xA;            break;&lt;br/&gt;&#xA;        default: /* &#39;?&#39; */&lt;br/&gt;&#xA;            fprintf(stderr, &#34;Usage: %s [Options] device\nOptions\t-w\tPower consumption(W)\n\t-i\tIlluminance\n\t-t\tTemperature\n\t-h\tHumidity\n&#34;, argv[0]);&lt;br/&gt;&#xA;            exit(EXIT_FAILURE);&lt;br/&gt;&#xA;        }&lt;br/&gt;&#xA;    }&lt;br/&gt;&#xA;    if ( argc &lt;= optind ){&lt;br/&gt;&#xA;        fprintf(stderr, &#34;Usage: %s [Options] device\nOptions\t-w\tPower consumption(W)\n\t-i\tIlluminance\n\t-t\tTemperature\n\t-h\tHumidity\n&#34;, argv[0]);&lt;br/&gt;&#xA;        exit(EXIT_FAILURE);&lt;br/&gt;&#xA;    }&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    fd = open(argv[optind], O_RDWR);&lt;br/&gt;&#xA;    if ( fd &lt; 0 ){&lt;br/&gt;&#xA;        perror(argv[optind]);&lt;br/&gt;&#xA;        return 0;&lt;br/&gt;&#xA;    }&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    if ( !cmdbuf[0] )&lt;br/&gt;&#xA;        strcpy(cmdbuf, cmd_all);&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;    newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD | &lt;span class=&#34;Topics&#34;&gt;CRTSCTS&lt;/span&gt;;&lt;br/&gt;&#xA;    newtio.c_oflag = 0;         &lt;span class=&#34;Topics&#34;&gt;/* Rawモード出力 */&lt;/span&gt;&lt;br/&gt;&#xA;    newtio.c_lflag = 0;         &lt;span class=&#34;Topics&#34;&gt;/* 非カノニカル入力 */&lt;/span&gt;&lt;br/&gt;&#xA;    newtio.c_cc[VTIME]=0;       /* キャラクタ間タイマは未使用 */&lt;br/&gt;&#xA;    newtio.c_cc[VMIN]=0x00;     &lt;span class=&#34;Topics&#34;&gt;/* ブロック受信しない */&lt;/span&gt;&lt;br/&gt;&#xA;    tcflush(fd, TCIFLUSH);&lt;br/&gt;&#xA;    tcsetattr(fd, TCSANOW, &amp;newtio);&lt;br/&gt;&#xA;&lt;br/&gt;&#xA;    for ( cmd = cmdbuf; cmd &amp;&amp; *cmd; cmd++ )&lt;br/&gt;&#xA;        fplug_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;/blockquote&gt;&#xA;これで期待通りにデータが採れるようになった。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
