LoginSignup
1
1

More than 5 years have passed since last update.

ラズパイで取得したセンサー値をGoogleSpreadSheetsでグラフ化する【グラフ化編】(4/4)

Last updated at Posted at 2018-07-04

ラズパイで取得したセンサー値をGoogleSpreadSheetsでグラフ化するのグラフ化編です。

前回まででラズパイのセンサー値はBigQueryに蓄積されています。
今回は蓄積されたセンサー値を抽出してSpreadSheetsでグラフ化します。

次の通り。

image.png

今回は次の順に設定を行います。

下準備する

AppsScriptを書く前に下記を用意します。

また記事内では次の通り設定に名前を付けました。

項目 名前
スプレッドシート名 ラズパイグラフ
グラフ用シート名 graph_sheet
センサー値用シート名 sensor_value_sheet

スプレッドシートを用意する

まず ここから ログインして新しいスプレッドシートを作成して
グラフ用とセンサー値用のシートを作成します。

image.png

新しいシートが出来たら名前を付けます。

image.png

gsファイルを用意する

これはAppsScriptのソースファイルです。

シートのヘッダ部のツール → スクリプトエディタからコード
編集画面を開き、そのままプロジェクト名を指定して保存します。

image.png

エディタが開いたら、プロジェクトに適当な名前を付けて保存します。

image.png

BigQueryへのアクセス許可を取得する

Enabling advanced services を参考にAppsScriptから
BigQueryを利用できるようにします。

image.png


小窓が出てくるので次の通りBigQueryを有効にします。
image.png

以上で下準備が完了です。

AppsScriptでセンサー値を抽出しグラフを描く

AppsScript はJavaScriptベースのスクリプト言語でG Suiteや
GCPのいくつかと連携できます。

今回はBigQueryからセンサー値を抽出してチャートを描画します。
これらの正確なところは次のリファレンスを参照してください。

コードを書く

次の通りです。
mainLogic() がエントリポイントです。
処理内容はソースのコメントの通りです。

コード.gs
PROJECT_ID = "raspi-comfort-sensor";                                  // BigQueryのPROJECT ID

SPREADSHEET_ID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";      // スプレッドシートのID
SENSOR_VALUE_SHEET = "sensor_value_sheet"                             // センサー値 貼付シート
GRAPH_SHEET = "graph_sheet"                                           // グラフ 貼付シート

// センサー値のカラム名
HEADER = ["time(JST)", "temperature(℃)", "pressure(hPa)", "humidity(%)", "illuminance(lx)", "co2(ppm)"];

// エントリポイント
function mainLogic() {

  // シートを取得
  var valueSheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(SENSOR_VALUE_SHEET);
  var graphSheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(GRAPH_SHEET);

  // センサー値を抽出・シート貼付
  getSensorValues(valueSheet);

  // チャートを作成・シート貼付
  createChart(valueSheet.getDataRange(), graphSheet);
}

// 直近12時間のセンサー値を抽出して貼付
function getSensorValues(valueSheet) {

  // 抽出
  var request = {
    useLegacySql: false,
    query:  ' SELECT FORMAT_TIMESTAMP("%F %X", time, "Asia/Tokyo") as jst,       ' +
            '        temperature,                                                ' +
            '        pressure,                                                   ' +
            '        humidity,                                                   ' +
            '        illuminance,                                                ' +
            '        co2                                                         ' +
            ' FROM sensor_dataset.sensor_table                                   ' +
            ' WHERE device = "raspi-is"                                          ' +
            ' AND time >= TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL -12 HOUR)  ' +
            ' ORDER BY jst                                                       '  };

  var queryResults = BigQuery.Jobs.query(request, PROJECT_ID);
  var jobId = queryResults.jobReference.jobId;

  var sleepTimeMs = 500;
  while (!queryResults.jobComplete) {

    Utilities.sleep(sleepTimeMs);
    sleepTimeMs *= 2;
    queryResults = BigQuery.Jobs.getQueryResults(PROJECT_ID, jobId);
  }

  var records = queryResults.rows;
  while (queryResults.pageToken) {
    queryResults = BigQuery.Jobs.getQueryResults(PROJECT_ID, jobId, {
      pageToken: queryResults.pageToken
    });
    records = records.concat(queryResults.rows);
  }

  // シートを初期化
  valueSheet.clear();

  // ヘッダを貼付
  valueSheet.getRange(1, 1, 1, HEADER.length).setValues([HEADER]);

  // センサー値を貼付
  var data = new Array(records.length);
  for (var i = 0; i < records.length; i++) {

    var cols = records[i].f;
    data[i] = new Array(cols.length);
    for (var j = 0; j < cols.length; j++) {
      data[i][j] = cols[j].v;
    }
  }

  valueSheet.getRange(2, 1, records.length, HEADER.length).setValues(data);
}

// チャートを作成してシートに貼付
function createChart(recordRange, graphSheet) {

  // 既存チャートがあれば削除
  var charts = graphSheet.getCharts();
  for (var i in charts) {
    graphSheet.removeChart(charts[i]);
  }

  // チャートを作成
  var chart = graphSheet.newChart()
      .setChartType(Charts.ChartType.LINE)
      .addRange(recordRange)
      .setOption('width', 800)
      .setOption('height', 500)
      .setPosition(1, 1, 0, 0)
      .build()

  graphSheet.insertChart(chart);
}

※ 定数 SPREADSHEET_ID の値は リファレンス を参考に取得します。

コードを実行する

スクリプトエディタで mainLogic() を選択して実行します。
次の通りです。

image.png

上記のような手動実行のほかにタイマーでも実行できます。
※ これはシートを閉じていても発火するので要注意です。

image.png

実行対象と間隔を指定してトリガーを追加します。

image.png

因みに シートを開く操作 もトリガーになるのですが、これは
利用可能なAPIが制限されており、今回は使用できませんでした。

実行結果を見てみる

いよいよ最終的な実行結果を見てみます。

正常に動作すると sensor_value_sheet と graph_sheet に
それぞれセンサー値とグラフが出てきます。
次の通りです。

実行結果:sensor_value_sheet

image.png

実行結果:graph_sheet

image.png





image.png

以上でおしまいです。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1