• 概要
  • RaspberryPi Zero W を各部屋に設置して気温をモニタするシステムを作ってみました。
    当初はRaspberryPi4を親機にしていましたがもったいないので、ファイルサーバにしているRockPi4Aを使っています。
    RaspberryPi Zero Wは3台リビング、寝室、PC室に設置しています。
    色々な言語を使っています。

    C言語:センサ読み取り
    sh:データ移動
    Perl:データ変換
    SQL:CSVの処理 (Perl内)
    HTML:表示 (Perl内)
    SVG:グラフ (Perl内)

  • グラフ
  • 1日の気温変化

    1週間の気温変化
  • RaspberryPiZeroW
  • I2Cの読み取りが肝です。
    加速度と角速度は読み捨てています。
    今回の用途ではキー読み取りは不要です。
    ここでは WiribgPi を使っていますが、これからはPiGPIOを使うのがよいでしょう。
    mpu_6050_3.c
    //gcc -o mpu_6050_3 mpu_6050_3.c -lwiringPi -pthread
    #include <stdio.h>
    #include <wiringPi.h>
    #include <wiringPiI2C.h>
    #include <unistd.h>
    #include <pthread.h>
    
    #define SLAVE_ADDR 0x68    // I2C
    
    #define GYRO_CONFIG  0x1b
    #define ACCEL_CONFIG 0x1c
    #define ACCEL_XOUT   0x3b
    #define ACCEL_XOUT_H 0x3b
    #define ACCEL_XOUT_L 0x3c
    #define ACCEL_YOUT   0x3d
    #define ACCEL_YOUT_H 0x3d
    #define ACCEL_YOUT_L 0x3e
    #define ACCEL_ZOUT   0x3f
    #define ACCEL_ZOUT_H 0x3f
    #define ACCEL_ZOUT_L 0x40
    #define TEMP_OUT     0x41
    #define TEMP_OUT_H   0x41
    #define TEMP_OUT_L   0x42
    #define GYRO_XOUT    0x43
    #define GYRO_XOUT_H  0x43
    #define GYRO_XOUT_L  0x44
    #define GYRO_YOUT    0x45
    #define GYRO_YOUT_H  0x45
    #define GYRO_YOUT_L  0x46
    #define GYRO_ZOUT    0x47
    #define GYRO_ZOUT_H  0x47
    #define GYRO_ZOUT_L  0x48
    #define PWR_MGMT_1   0x6B  //PWR_MGMT_1
    #define PWR_MGMT_2   0x6c  //PWR_MGMT_2
    
    #define FS_SEL       0x18
    #define AFS_SEL      0x18
    #define SAMPLES       10
    
    int exit_req = 0;       //終了要求
    float Accel_Sensitivity[]={16384, 8192, 4096, 2048};
    float Gyro_Sensitivity[] ={  131, 65.5, 32.8, 14.4};
    
    float read16(int fd, int reg){
      short val = (wiringPiI2CReadReg8(fd, reg) << 8) // High
                | wiringPiI2CReadReg8(fd, reg +1);    // Low
      return (float)val;
    }
    
    void *key_check(){
      getchar();
      exit_req = 1;
    }
    
    int main(int ac, char *av[]){
      pthread_t ptid;
      int fd = wiringPiI2CSetup(SLAVE_ADDR);
    
      if (fd == -1){
        printf("cannot setup i2c.");
        return 1;
      }
    
      pthread_create( &ptid, NULL, key_check, NULL);
    
      wiringPiI2CWriteReg16(fd, PWR_MGMT_1, 0);
      float as = Accel_Sensitivity[(wiringPiI2CReadReg8(fd, ACCEL_CONFIG) & AFS_SEL) >> 3]; //加速度感度設定確認
      float gs = Gyro_Sensitivity[(wiringPiI2CReadReg8(fd, GYRO_CONFIG ) & FS_SEL) >> 3];  //角速度感度設定確認
      float temp=0;
    
      for(int i=0; i<SAMPLES; i++){
        temp+=(read16(fd, TEMP_OUT) / 340 + 36.53);
        usleep(1000);
      }
        temp /= SAMPLES;
        printf("%4.2f",temp);
        printf("\n");
    }
    
  • RockPi4
  • 1日分のCSVファイルからグラフのページを生成します。
    csv2chart.pl
    #!/usr/bin/perl
    use DBI;
    use Time::Local 'timelocal';
    
    my $xmag = 0.01;
    my $ymag = 10;
    my $yoff = 400;
    my $xmin = 0;
    my $xmax = sec2pos(3600*24);
    my $width = $xmax - $xmin;
    my $height = $yoff;
    my $ymin = 0;
    my $ymax = $ymin + $yoff;
    my $ytit = $ymin + 10;
    my $xtet = $xmax;
    my $offset = -2;  # 他の機器との誤差を修正
    
    # 日付関連
    my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime;
    $mon++;
    $year+=1900;
    my $today = sprintf "%04d%02d%02d", $year, $mon, $mday;
    my $table = "temp".$today;
    my $data_dir = $ARGV[0];
    
    if($ARGV[1] ne ""){
      $table = $ARGV[1];
      $table =~ m/(\d{4})(\d{2})(\d{2})/;
      ($year, $mon, $mday) = ($1, $2, $3);
    }
    
    my $tm = get_tm($year, $mon, $mday);
    my $prevday = get_date($tm - 24 * 3600);
    my $nextday = get_date($tm + 24 * 3600);
    my $link;
    
    if($ARGV[1] ne ""){
        $link = "<a href=\"Cur.html\">《</a>";
        if($nextday ne $today){
            $link .= "<a href=\"".$nextday.".html\">《</a>";
        }
    }
    $link .= "<a href=\"".$prevday.".html\">》</a>";
    
    # 最新データ
    my $NowTemp = join("", `tail temp/$table.csv -n 1`);
    #my $NowTemp = join("", `tail $table.csv -n 1`);
    $NowTemp =~ m/(\d\d:\d\d:\d\d),(\d\d\.\d\d),(\d\d\.\d\d),(\d\d\.\d\d)/;
    my ($time, $temp1, $temp2, $temp3) = ($1, $2 + $offset, $3 + $offset, $4 + $offset);
    
    my $title = sprintf "%04d%02d%02d", $year, $mon, $mday;
    output_head();
    
    my $dbh = DBI->connect("DBI:CSV:f_dir=$data_dir;f_ext=.csv")
        or die "Cannot connect: " . $DBI::errstr;
    
    my $sth = $dbh->prepare("SELECT * FROM ".$table)
        or die "Cannot prepare: " . $dbh->errstr();
    $sth->execute() or die "Cannot execute: " . $sth->errstr();
    
    while(my $t = $sth->fetchrow_arrayref){
        my ($time, $room1, $room2, $room3) = @$t;
    #    print "$time, $room1, $room2, $room3\n";
        point($time, $room1 + $offset, $room2 + $offset, $room3 + $offset);
    }
    $sth->finish();
    $dbh->disconnect();
    output_foot();
    
    
    #
    # 時間日付変換
    #
    sub get_date {
      my $tm = shift;
      my ($day, $month, $year) = (localtime($tm))[3..5];
      return sprintf "%04d%02d%02d", $year + 1900, $month + 1, $day;
    }
    
    
    #
    # 日付時間変換
    #
    sub get_tm {
      my $year = shift;
      my $month = shift;
      my $day = shift;
      return timelocal(0, 0, 0, $day, $month - 1, $year - 1900);
    }
    
    
    #
    # 時刻に相当するX座標に3つの温度データを指定するSVGを出力
    #
    sub point(){
      my ($x, $y1, $y2, $y3) = @_;
      $x =~ m/(\d\d):(\d\d):(\d\d)/;
      $x = sec2pos($1*3600 + $2*60 + $3);
    #  $x = time2pos($1, $2, $3);
      $y1 = temp2pos($y1);
      $y2 = temp2pos($y2);
      $y3 = temp2pos($y3);
      print("  <use href=\"#cr\" x=\"$x\" y=\"$y1\" />\n");
      print("  <use href=\"#cg\" x=\"$x\" y=\"$y2\" />\n");
      print("  <use href=\"#cb\" x=\"$x\" y=\"$y3\" />\n");
    }
    
    
    #
    # HTMLヘッダからグラフの点以外を生成
    #
    sub output_head(){
    my ($te05, $te10, $te15, $te20, $te25, $te28, $te30, $te32, $te35)
        = (temp2pos(5), temp2pos(10), temp2pos(15), temp2pos(20), temp2pos(25), temp2pos(28), temp2pos(30), temp2pos(32), temp2pos(35));
    my ($ti03, $ti06, $ti09, $ti12, $ti15, $ti18, $ti21)
        = (sec2pos(3*3600), sec2pos(6*3600), sec2pos(9*3600), sec2pos(12*3600), sec2pos(15*3600), sec2pos(18*3600), sec2pos(21*3600));
    
    print <<EOD;
    <html>
    <head>
      <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
      <style type="text/css">
      <!--
      a{
        color:#008800;
        text-decoration:none;
      }
      a:hover{
        color:#ff0000;
      }
      div.right {
        text-align: right;
      }
      div.float {
        float: left;
      }
      -->
      </style>
    <script language="javascript">
    <!--
    const timer = 30000    // ミリ秒で間隔の時間を指定
    window.addEventListener('load',function(){
      setInterval('location.reload()',timer);
    });
    //-->
    </script>
      <title>$title</title>
    </head>
    <body style="background:#f0f0f0">
    <div>
      <div class="float">各部屋の温度</div>
      <div class="right">$link</div>
    赤:リビング:$temp1℃、緑:寝室:$temp2℃、青:PC室:$temp3℃<br>
    更新時刻:$time<br>
    <svg width="$width.px" height="$height.px" viewBox="$xmin $ymin $width $height">
      <defs>
        <g id="cr"><circle cx="0" cy="0" r="1" fill="red"/></g>
        <g id="cg"><circle cx="0" cy="0" r="1" fill="green"/></g>
        <g id="cb"><circle cx="0" cy="0" r="1" fill="blue"/></g>
      </defs>
      <rect x="$xmin" y="$ymin" width="$width" height="$height" stroke="black" stroke-eidth="1" fill="white" />
      <line x1="$ti03" y1="$ymin" x2="$ti03" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$ti06" y1="$ymin" x2="$ti06" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$ti09" y1="$ymin" x2="$ti09" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$ti12" y1="$ymin" x2="$ti12" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$ti15" y1="$ymin" x2="$ti15" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$ti18" y1="$ymin" x2="$ti18" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$ti21" y1="$ymin" x2="$ti21" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$xmin" y1="$te05" x2="$xmax" y2="$te05" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$xmin" y1="$te10" x2="$xmax" y2="$te10" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$xmin" y1="$te15" x2="$xmax" y2="$te15" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$xmin" y1="$te20" x2="$xmax" y2="$te20" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$xmin" y1="$te25" x2="$xmax" y2="$te25" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$xmin" y1="$te28" x2="$xmax" y2="$te28" stroke="blue"      stroke-dasharray="2 2" />
      <line x1="$xmin" y1="$te30" x2="$xmax" y2="$te30" stroke="green"     stroke-dasharray="2 2" />
      <line x1="$xmin" y1="$te32" x2="$xmax" y2="$te32" stroke="red"       stroke-dasharray="2 2" />
      <line x1="$xmin" y1="$te35" x2="$xmax" y2="$te35" stroke="lightgray" stroke-dasharray="2 2" />
      <text x="$xtet" y="$te05" font-size="10" text-anchor="end">5</text>
      <text x="$xtet" y="$te10" font-size="10" text-anchor="end">10</text>
      <text x="$xtet" y="$te15" font-size="10" text-anchor="end">15</text>
      <text x="$xtet" y="$te20" font-size="10" text-anchor="end">20</text>
      <text x="$xtet" y="$te25" font-size="10" text-anchor="end">25</text>
      <text x="$xtet" y="$te28" font-size="10" text-anchor="end" stroke="blue">28</text>
      <text x="$xtet" y="$te30" font-size="10" text-anchor="end" stroke="green">30</text>
      <text x="$xtet" y="$te32" font-size="10" text-anchor="end" stroke="red">32</text>
      <text x="$xtet" y="$te35" font-size="10" text-anchor="end">35</text>
      <text x="$ti03" y="10" font-size="10" text-anchor="middle">3</text>
      <text x="$ti06" y="10" font-size="10" text-anchor="middle">6</text>
      <text x="$ti09" y="10" font-size="10" text-anchor="middle">9</text>
      <text x="$ti12" y="10" font-size="10" text-anchor="middle">12</text>
      <text x="$ti15" y="10" font-size="10" text-anchor="middle">15</text>
      <text x="$ti18" y="10" font-size="10" text-anchor="middle">18</text>
      <text x="$ti21" y="10" font-size="10" text-anchor="middle">21</text>
    EOD
    }
    
    #
    # 後ろの定型部分を出力
    #
    sub output_foot(){
    print <<EOD;
    </svg>
    </body>
    </html>
    EOD
    }
    
    
    #
    # 時刻をX座標に変換
    #
    sub sec2pos(){
      return $_[0] * $xmag;
    }
    
    
    #
    # 温度をY座標に変換
    #
    sub temp2pos(){
      return $yoff - $_[0] * $ymag;
    }
    
    1週間分のCSVファイルからグラフのページを生成します。
    csv2chart_w.pl
    #!/usr/bin/perl
    use DBI;
    use Time::Local 'timelocal';
    
    my $xmag = 0.01;
    my $ymag = 10;
    my $yoff = 400;
    my $xmin = 0;
    my $xmax = sec2pos(3600*24);
    my $width = $xmax - $xmin;
    my $height = $yoff;
    my $ymin = 0;
    my $ymax = $ymin + $yoff;
    my $ytit = $ymin + 10;
    my $xtet = $xmax;
    my $t_offset = -2;  # 他の機器との誤差を修正
    my $plot;
    
    # 日付関連
    my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime;
    $mon++;
    $year+=1900;
    my $today = sprintf "%04d%02d%02d", $year, $mon, $mday;
    my $table = "temp".$today;
    my $data_dir = $ARGV[0];
    
    if($ARGV[1] ne ""){
      $table = $ARGV[1];
      $table =~ m/(\d{4})(\d{2})(\d{2})/;
      ($year, $mon, $mday) = ($1, $2, $3);
    }
    
    my $tm = get_tm($year, $mon, $mday);
    my $prevday = get_date($tm - 24 * 3600);
    my $nextday = get_date($tm + 24 * 3600);
    my $wday      = get_date($tm - 24 * 3600 * 6);
    my $link;
    
    if($ARGV[1] ne ""){
        $link = "<a href=\"Cur.w.html\">《</a>";
        if($nextday ne $today){
            $link .= "<a href=\"".$nextday.".w.html\">《</a>";
        }
    }
    $link .= "<a href=\"".$prevday.".w.html\">》</a>";
    
    my $title = sprintf "%s - %04d%02d%02d",$wday, $year, $mon, $mday;
    
    for ($i = 0; $i < 7; $i++){
        my $prevday = get_date($tm - (24 * 3600)*$i);
        my $table = "temp".$prevday;
        $plot .= get_data($table, 6 - $i);
    }
    
    output_head();
    print $plot;
    output_foot();
    
    
    #
    # CSV1ファイル分の処理
    #
    sub get_data {
        my $plot;
        my $table = $_[0];
        my $d_offset = $_[1];
    
        my $dbh = DBI->connect("DBI:CSV:f_dir=$data_dir;f_ext=.csv")
            or return $plot;
    
        my $sth = $dbh->prepare("SELECT * FROM ".$table)
            or return $plot;
        $sth->execute() or die "Cannot execute: " . $sth->errstr();
    
        while(my $t = $sth->fetchrow_arrayref){
            my ($time, $room1, $room2, $room3) = @$t;
            $plot .= point($d_offset, $time, $room1 + $t_offset, $room2 + $t_offset, $room3 + $t_offset);
        }
        $sth->finish();
        $dbh->disconnect();
        return $plot;
    }
    
    
    #
    # 時間日付変換
    #
    sub get_date {
      my $tm = shift;
      my ($day, $month, $year) = (localtime($tm))[3..5];
      return sprintf "%04d%02d%02d", $year + 1900, $month + 1, $day;
    }
    
    
    #
    # 日付時間変換
    #
    sub get_tm {
      my $year = shift;
      my $month = shift;
      my $day = shift;
      return timelocal(0, 0, 0, $day, $month - 1, $year - 1900);
    }
    
    
    #
    # 時刻に相当するX座標に3つの温度データを指定するSVGを出力
    #
    sub point(){
      my ($offset, $x, $y1, $y2, $y3) = @_;
      $x =~ m/(\d\d):(\d\d):(\d\d)/;
      $x = sec2pos(($1*3600 + $2*60 + $3 + $offset * 24 * 3600)/7);
    #  $x = time2pos($1, $2, $3);
      $y1 = temp2pos($y1);
      $y2 = temp2pos($y2);
      $y3 = temp2pos($y3);
      return "  <use href=\"#cr\" x=\"$x\" y=\"$y1\" />\n  <use href=\"#cg\" x=\"$x\" y=\"$y2\" />\n  <use href=\"#cb\" x=\"$x\" y=\"$y3\" />\n";
    }
    
    
    #
    # HTMLヘッダからグラフの点以外を生成
    #
    sub output_head(){
    my ($te05, $te10, $te15, $te20, $te25, $te28, $te30, $te32, $te35)
        = (temp2pos(5), temp2pos(10), temp2pos(15), temp2pos(20), temp2pos(25), temp2pos(28), temp2pos(30), temp2pos(32), temp2pos(35));
    my ($ti03, $ti06, $ti09, $ti12, $ti15, $ti18, $ti21)
        = (sec2pos(3*3600/7), sec2pos(6*3600/7), sec2pos(9*3600/7), sec2pos(12*3600/7), sec2pos(15*3600/7), sec2pos(18*3600/7), sec2pos(21*3600/7));
    
    print <<EOD;
    <html>
    <head>
      <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
      <style type="text/css">
      <!--
      a{
        color:#008800;
        text-decoration:none;
      }
      a:hover{
        color:#ff0000;
      }
      div.right {
        text-align: right;
      }
      div.float {
        float: left;
      }
      -->
      </style>
      <title>$title</title>
    </head>
    <body style="background:#f0f0f0">
    <div>
      <div class="float">各部屋の温度</div>
      <div class="right">$link</div>
    赤:リビング、緑:寝室、青:PC室<br>
    <svg width="$width.px" height="$height.px" viewBox="$xmin $ymin $width $height">
      <defs>
        <g id="cr"><circle cx="0" cy="0" r="1" fill="red"/></g>
        <g id="cg"><circle cx="0" cy="0" r="1" fill="green"/></g>
        <g id="cb"><circle cx="0" cy="0" r="1" fill="blue"/></g>
        <g id="time">
          <line x1="0"     y1="$ymin" x2="0"     y2="$ymax" stroke="lightgray" stroke-dasharray="2 0" />
          <line x1="$ti03" y1="$ymin" x2="$ti03" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
          <line x1="$ti06" y1="$ymin" x2="$ti06" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
          <line x1="$ti09" y1="$ymin" x2="$ti09" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
          <line x1="$ti12" y1="$ymin" x2="$ti12" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
          <line x1="$ti15" y1="$ymin" x2="$ti15" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
          <line x1="$ti18" y1="$ymin" x2="$ti18" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
          <line x1="$ti21" y1="$ymin" x2="$ti21" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
          <text x="$ti03" y="10" font-size="10" text-anchor="middle">3</text>
          <text x="$ti06" y="10" font-size="10" text-anchor="middle">6</text>
          <text x="$ti09" y="10" font-size="10" text-anchor="middle">9</text>
          <text x="$ti12" y="10" font-size="10" text-anchor="middle">12</text>
          <text x="$ti15" y="10" font-size="10" text-anchor="middle">15</text>
          <text x="$ti18" y="10" font-size="10" text-anchor="middle">18</text>
          <text x="$ti21" y="10" font-size="10" text-anchor="middle">21</text>
        </g>
      </defs>
      <rect x="$xmin" y="$ymin" width="$width" height="$height" stroke="black" stroke-eidth="1" fill="white" />
      <line x1="$ti03" y1="$ymin" x2="$ti03" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$ti06" y1="$ymin" x2="$ti06" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$ti09" y1="$ymin" x2="$ti09" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$ti12" y1="$ymin" x2="$ti12" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$ti15" y1="$ymin" x2="$ti15" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$ti18" y1="$ymin" x2="$ti18" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$ti21" y1="$ymin" x2="$ti21" y2="$ymax" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$xmin" y1="$te05" x2="$xmax" y2="$te05" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$xmin" y1="$te10" x2="$xmax" y2="$te10" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$xmin" y1="$te15" x2="$xmax" y2="$te15" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$xmin" y1="$te20" x2="$xmax" y2="$te20" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$xmin" y1="$te25" x2="$xmax" y2="$te25" stroke="lightgray" stroke-dasharray="2 2" />
      <line x1="$xmin" y1="$te28" x2="$xmax" y2="$te28" stroke="blue"      stroke-dasharray="2 2" />
      <line x1="$xmin" y1="$te30" x2="$xmax" y2="$te30" stroke="green"     stroke-dasharray="2 2" />
      <line x1="$xmin" y1="$te32" x2="$xmax" y2="$te32" stroke="red"       stroke-dasharray="2 2" />
      <line x1="$xmin" y1="$te35" x2="$xmax" y2="$te35" stroke="lightgray" stroke-dasharray="2 2" />
      <text x="$xtet" y="$te05" font-size="10" text-anchor="end">5</text>
      <text x="$xtet" y="$te10" font-size="10" text-anchor="end">10</text>
      <text x="$xtet" y="$te15" font-size="10" text-anchor="end">15</text>
      <text x="$xtet" y="$te20" font-size="10" text-anchor="end">20</text>
      <text x="$xtet" y="$te25" font-size="10" text-anchor="end">25</text>
      <text x="$xtet" y="$te28" font-size="10" text-anchor="end" stroke="blue">28</text>
      <text x="$xtet" y="$te30" font-size="10" text-anchor="end" stroke="green">30</text>
      <text x="$xtet" y="$te32" font-size="10" text-anchor="end" stroke="red">32</text>
      <text x="$xtet" y="$te35" font-size="10" text-anchor="end">35</text>
      <use href="#time" x="0" y="0" />
      <use href="#time" x="123.4" y="0" />
      <use href="#time" x="246.8" y="0" />
      <use href="#time" x="370.2" y="0" />
      <use href="#time" x="493.7" y="0" />
      <use href="#time" x="617.1" y="0" />
      <use href="#time" x="740.5" y="0" />
    EOD
    }
    
    #
    # 後ろの定型部分を出力
    #
    sub output_foot(){
    print <<EOD;
    </svg>
    </body>
    </html>
    EOD
    }
    
    
    #
    # 時刻をX座標に変換
    #
    sub sec2pos(){
      return $_[0] * $xmag;
    }
    
    
    #
    # 温度をY座標に変換
    #
    sub temp2pos(){
      return $yoff - $_[0] * $ymag;
    }
    
    1分おきにデータを取得してHTMLファイルを生成します。
    SSDの書込み回数を抑えるためにRAMディスクを使っています。
    あらかじめ sshpass をインストールしておいてください。
    gettemp4.sh
    #!/bin/bash
    #clear
    PastDay=`date +%Y%m%d --date '1 day ago'`
    PastDay2=`date +%Y%m%d --date '2 day ago'`
    PastTime="11:59:59"
    while true
    do
      PresentTime=`date +%H:%M:%S`
      if [ $PastTime != $PresentTime ]; then
        if expr "$PresentTime" : '..:..:00' > /dev/null; then
          PresentDay=`date +%Y%m%d`
          if [ $PastDay != $PresentDay ]; then
            if [ ! -e temp/temp$PresentDay.csv ]; then
              if [ ! -e temp$PresentDay.csv ]; then
                echo "Time,Living,Bed,PC" > 'temp/temp'$PresentDay'.csv'
                cp temp/temp$PastDay.csv .
                ./csv2chart.pl . 'temp'$PastDay > $PastDay'.html'
                ./csv2chart.pl . 'temp'$PastDay2 > $PastDay2'.html'
              else
                cp temp$PresentDay.csv temp
              fi
            fi
            PastDay2=$PastDay
            PastDay=$PresentDay
            cp *.html /var/www/html/temp
          fi
    
          echo $PresentTime > temp/temp.csv
          echo "," >> temp/temp.csv
          sshpass -p raspberry ssh pi@192.168.1.201 'RaspberryPi/I2C/mpu_6050_3' >> temp/temp.csv
          echo "," >> temp/temp.csv
          sshpass -p raspberry ssh pi@192.168.1.202 'RaspberryPi/I2C/mpu_6050_3' >> temp/temp.csv
          echo "," >> temp/temp.csv
          sshpass -p raspberry ssh pi@192.168.1.203 'RaspberryPi/I2C/mpu_6050_3' >> temp/temp.csv
          ./gettemp.pl temp/temp.csv >> 'temp/temp'$PresentDay'.csv'
    
          PastTime=$PresentTime
    
          ./csv2chart.pl ./temp > /var/www/html/temp/Cur.html
          ./csv2chart_w.pl ./temp 'temp'$PresentDay > '/var/www/html/temp/'$PresentDay'.w.html'
        fi
      fi
      sleep 1s
    done
    
  • RAM Disk
  • 取得したファイル置き場と公開用ファイル置き場をRAMディスクにしています。
    dataはファイルサーバ用のM.2 SSDです。

    /etc/fstab
    # UNCONFIGURED FSTAB FOR BASE SYSTEM
    # /etc/fstab: static file system information.
    #
    # <file system> <mount point>   <type>  <options>       <dump>  <pass>
    
    # /etc/fstab: static file system information.
    #
    # <file system> <mount point>   <type>  <options>       <dump>  <pass>
    
    /dev/mmcblk1p4  /boot   vfat    defaults        0       2
    LABEL=data      /mnt/data       ext4    defaults  0       2
    tmpfs           /var/www/html/temp  tmpfs  defaults,size=256m 0       0
    temp            /home/rock/temp     tmpfs  defaults,size=32m 0       0
    
  • 振り返り
  • 上の例ではお遊びでスクリプトをグルグル回してタイミングを取っていますが、
    cronやatコマンドで実行させるのが楽です。真似はしないでください。