39
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Xivelyでセンサデータなどのリアルタイムなチャートを作る

Last updated at Posted at 2014-08-23

概要

センサデータと天気APIのデータを集積してリアルタイムチャートを作る。

Xively

Xivelyはデバイスデータなどを集約管理するためのプラットフォーム。

  1. ユーザー登録する。
  2. DevelopからAdd Deviceする。
  3. API KeyFeed IDをメモる。

無料だとデバイス数などに制約があった気がするが、今回は1デバイスにまとめてデータ送信しているのでとりあえず足りている。

センサ

回路はそれぞれ簡単なので割愛(気になる人は聞いてください)。

無線

XBee Wi-Fiを使う場合は以下の設定を行う。

  • destination : nslookup api.xively.comして64.94.18.120
  • port : 0x50(=80)

センサデータの送信

Arduinoのスケッチを書く。C++苦手…
温湿度センサーは以前使ったがややデータの読み取りが難しい。DHTのライブラリを使う。

sensors.ino

#include <DHT.h>

#define DHTTYPE DHT22
#define DHT22_PIN 7
DHT dht(DHT22_PIN, DHTTYPE);


int napionAnalogPin = A0;
int illuminancePin  = A1;
int microphonePin   = A2;
int napion10mPin    = 6;
int interval        = 3; //sec
int loopCount       = 100;

String moduleId = "0001";

String feedId = "YOUR_XIVELY_FEED_ID";
String apiKey = "YOUR_XIVELY_API_KEY";
String reqHeader;

void setup() {
  Serial.begin(9600);
  pinMode(napionAnalogPin,    INPUT);
  pinMode(illuminancePin, INPUT);
  pinMode(microphonePin,  INPUT);  
  pinMode(DHT22_PIN,      INPUT);      
  pinMode(napion10mPin,      INPUT);      

  reqHeader = "PUT /v2/feeds/" + feedId +" HTTP/1.1\r\n" + "X-ApiKey: " + apiKey + "\r\n"+"host: api.xively.com\r\n";

}

int illuminanceValue = 0;
int microphoneValue = 0;

void loop() {
  int illuminanceValueMax = 0;
  int microphoneValueMax = 0;

  long napionAnalogValue = 0;
  long napion10mValue = 0;

  for (int sec=0; sec<interval; sec++) {
    for (int j=0; j<loopCount ; j++) {
      delay(10);
      illuminanceValue = analogRead(illuminancePin);
      if (illuminanceValueMax < illuminanceValue) {
        illuminanceValueMax = illuminanceValue;
      }
      microphoneValue = analogRead(microphonePin);
      if (microphoneValueMax  < microphoneValue) {
        microphoneValueMax  = microphoneValue;
      }
      
      napion10mValue += digitalRead(napion10mPin);
      napionAnalogValue += analogRead(napionAnalogPin);
    }
  }
  float napion10mValueAvg    = 1.0*napion10mValue   /interval/loopCount;
  float napionAnalogValueAvg = 1.0*napionAnalogValue/interval/loopCount;
  char napion10mValueAvgChar[10];
  char napionAnalogValueAvgChar[10];
  dtostrf(napion10mValueAvg,    6, 2, napion10mValueAvgChar);
  dtostrf(napionAnalogValueAvg, 6, 2, napionAnalogValueAvgChar);


  float h  = dht.readHumidity() ;
  float t  = 5.0/9.0*(dht.readTemperature(true)-32.0); // fahrenheit -> celsius
  char ch[10];
  char ct[10];
  dtostrf(h, 6, 2, ch);
  dtostrf(t, 6, 2, ct);

  // HTTP request
  Serial.print(reqHeader);

  String httpBody =  "{\"version\":\"1.0.0\",\"datastreams\" : [  \r\n";
  httpBody.concat(  tuple("napion10m",       String(napion10mValueAvgChar))        + ","        );
  httpBody.concat(  tuple("napionAnalog",    String(napionAnalogValueAvgChar))     + ","        );
  httpBody.concat(  tuple("microphone",      String(microphoneValueMax))    + ","        );
  httpBody.concat(  tuple("humidity",        String(ch))                    + ","        );
  httpBody.concat(  tuple("temperature",     String(ct))                    + ","        );
  httpBody.concat(  tuple("illuminance",     String(illuminanceValueMax))   + " ] }" );
  
  Serial.print("Content-Length: " + String(httpBody.length()) + "\r\n\r\n");
  Serial.print(httpBody);  
  
}

String tuple(String channel, String value) {
  return "{\"id\":\"" + channel + moduleId + "\",  \"current_value\" : \"" + value + "\"}";
}

APIデータの送信

センサを室内に設置したが、公開されている外気温もpostしてみる。
World Weather OnlineのAPIを使う。API keyを取得したら以下のようなコマンドをサーバーのcronにでも登録する。データの更新間隔は30分程度なので実行間隔もそれくらいでよいだろう。
ちょっとダサいがpost内容を1回ファイルに吐いている。
JSONの整形はjqを使っている。

curl "api.worldweatheronline.com/free/v1/weather.ashx?q=Tokyo&format=json&num_of_days=1&key=YOUR_WEATHER_API_KEY" | ~/bin/jq  ' { "datastreams": [ { "id": "temp_tokyo", "current_value": ( .data.current_condition[0].temp_C ) } ] }' > /tmp/temp_tokyo; curl https://api.xively.com/v2/feeds/YOUR_XIVELY_FEED_ID -X PUT -H "X-ApiKey: YOUR_XIVELY_API_KEY" --data @/tmp/temp_tokyo

結果

XivelyでFeedをクリックすると送られているJSONを確認することができる。

{
  "version": "1.0.0",
  "datastreams": [
    {
      "id": "napion10m0001",
      "current_value": "  0.37"
    },
    {
      "id": "napionAnalog0001",
      "current_value": "497.49"
    },
    {
      "id": "microphone0001",
      "current_value": "396"
    },
    {
      "id": "humidity0001",
      "current_value": " 52.60"
    },
    {
      "id": "temperature0001",
      "current_value": " 27.60"
    },
    {
      "id": "illuminance0001",
      "current_value": "225"
    }
  ]
}

idごとに以下のようなグラフが勝手にできてリアルタイムに更新されていく。とりあえずのトレンド確認としては便利。

外気温

更新間隔が粗いが人のデータなので仕方ない。

室温

人の出入りがある間は動きが激しい。あと空調のon/offも現れている。

室内湿度

冷房を切った時に湿度も上がっている気がするが、換気が切れたからか発汗によるものか。

明るさ

暗いほうが値が高い(後々回路を直したい)。夜に段階的に照明が落ちるのと、朝日の日照が徐々に増えていくのが現れている。

人の出入りや会話に反応。

赤外線(アナログ)

人の動きに反応。

赤外線(デジタル)

3秒間の平均をとっている。デジタルのデータでもアナログっぽく使える気がする。高価なアナログ型を使う理由は減る。

感想

データ送信頻度

Xivelyのrequest間隔をどの程度にしようか迷ったが、1デバイスでかつ3秒程度なら全く問題ない。デバイスが増えた場合は分からない。

時刻

センサ取得したデータをすぐに送っているが、タイムスタンプをつけて後でまとめて送るとなるとNTPからの現在時刻の取得が必要。エラー処理や再送など総合的に考えるとRaspberry Piなどのほうが有利かも?

展望

いったん蓄積したデータのAPIによる取得もできそうなので別のフロントエンドや分析プラットフォームにつなぐなどやってみたら面白そう。

参考

39
39
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
39
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?