はじめに
前回は温度・湿度を継続的に取得するプラグラムを作成しました
[SensorTag] Texas Instruments の CC2650 SensorTag を試す(2)
本記事では、前回の記事で宣言したとおり
WebSocketを使った温度・湿度のリアルタイム描画にチャレンジしました。
使ったパッケージとか
package.json
{
"name": "sensor",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"watch": "gulp watch",
"start": "gulp && node ./dist/sample.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.13.3",
"redis": "^2.4.2",
"sensortag": "^1.2.0",
"ws": "^0.8.1"
},
"devDependencies": {
"babel-polyfill": "^6.3.14",
"babel-preset-es2015": "^6.1.18",
"babel-preset-stage-0": "^6.1.18",
"gulp": "^3.9.0",
"gulp-babel": "^6.1.1"
}
}
- express は Node.js 向けのWeb アプリケーション・フレームワークです。
- redis は名前から分かる通り、 redis を扱うためのパッケージです。
- ws は WebSocket を扱うためのパッケージです。
- グラフの描画には d3.js を利用しました。
async/await を使おうと思って babel-polyfill 入れたけど、結局使わなかった。
今回はいわゆるコールバック地獄で書きました。
完成品
こんな感じでCC2650から取得した温度と湿度の情報をもとに、
グラフを1分毎にリアルタイムに更新しています。
解説
WebSocket に接続があったタイミング(つまり、初期表示)で1日前からのセンサーデータを redis から取得しています。
// 1日前のデータまで取得
let ago = Date.now() - (1000 * 60 * 60 * 24);
redis.zrevrangebyscore('sensor', '+inf', ago, function(err, result){
if (err) throw err;
sensordataset = result.map((element, index, array) => {
return JSON.parse(element)
})
ws.send(JSON.stringify({type: 'init', sensordataset}), () => {});
});
その後は、1分毎に最新のセンサーデータをサーバからクライアントに WebSocket を通じて送信しています。また、 redis にもセンサーデータを保存しています。
// 1分毎に
setInterval(() => {
// センサーデータを取得
tag.readHumidity((error, temperature, humidity) => {
let humidityData = {
date: Date.now(),
temperature: temperature,
humidity: humidity
};
let sensordata = humidityData;
// センサーデータを redis に保存
redis.zadd('sensor', Date.now(), JSON.stringify(sensordata));
// 接続クライアントがあれば...
connects.forEach(ws => {
// センサーデータを送信
ws.send(JSON.stringify({type: 'update', sensordata}), () => {});
});
});
}, PERIOD);
クライアントサイドは受け取ったセンサーデータをもとにグラフを描画しています。
詳しくは一番下に貼ってあるリンクを参照してみてください
ソース
参考
激しく参考にさせていただきました