Last active
February 9, 2018 23:01
-
-
Save gcch/46c99cacc5f161a72acdd0d322583635 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* | |
* monitor.js --- Show the graph about room status (temp. / hum. / pres.) acquired from json data | |
* | |
* Copyright (c) 2018 tag. | |
* | |
*/ | |
var express = require('express'); | |
var router = express.Router(); | |
/**************************************************/ | |
var jsdom = require('jsdom'); | |
var d3 = require('d3'); | |
function generateSvg() { | |
const { JSDOM } = jsdom; | |
const { document } = (new JSDOM(``)).window; | |
global.document = document; | |
const datafile = '/home/pi/bme280.json' | |
// Load data | |
var fs = require('fs'); | |
var file = fs.readFileSync(datafile, {encoding:'utf8'}, function(err, data){ | |
if (err) { | |
throw err; | |
} | |
}); | |
var dataset = JSON.parse(file); | |
//console.log(dataset); | |
var parseDate = d3.timeParse('%Y-%m-%dT%H:%M:%S'); | |
// Generate SVG area | |
var margin = { | |
top: 64, | |
right: 128, | |
bottom: 64, | |
left: 128 | |
}; | |
var size = { | |
width: 1200, | |
height: 800 | |
} | |
var datetimeOldest = dataset[0]['datetime']; | |
var datetimeLatest = dataset[dataset.length - 1]['datetime']; | |
var svg = d3.select('body') | |
.append('svg') | |
.attr('width', margin.left + size.width + margin.right) | |
.attr('height', margin.top + size.height + margin.bottom) | |
.append('g') | |
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')'); | |
// Scale | |
var xScale = d3.scaleTime() | |
.domain( [new Date(datetimeOldest), new Date(datetimeLatest)] ) | |
.range([0, size.width]); | |
var yScale1 = d3.scaleLinear() | |
.domain([45, -5]) | |
.range([0, size.height]); | |
var yScale2 = d3.scaleLinear() | |
.domain([100, 0]) | |
.range([0, size.height]); | |
var yScale3 = d3.scaleLinear() | |
.domain([1100, 900]) | |
.range([0, size.height]); | |
// Title | |
var title = svg.append('text') | |
.text('Temp. / Hum. / Pres. (Last Update: ' + datetimeLatest + ')') | |
.attr('transform', 'translate(0, ' + -margin.top / 4 + ')'); | |
// X axis | |
var xAxis = svg.append('g') | |
.attr('class', 'axis x') | |
.attr('transform', 'translate(0, ' + size.height + ')') | |
.call( | |
d3.axisBottom(xScale) | |
.tickFormat( d3.timeFormat('%Y-%m-%d %H:%M:%S') ) | |
.tickSize(-size.height) | |
) | |
.append('text') | |
.text('datetime') | |
.attr('stroke', '#000') | |
.attr('x', size.width / 2) | |
.attr('y', margin.bottom * 7 / 8); | |
svg.select('.x') | |
.selectAll('.tick') | |
.selectAll('text') | |
.style('text-anchor', 'end') | |
.attr('transform', 'rotate(-15)'); | |
// Y axis | |
var yAxis1 = svg.append('g') | |
.attr('class', 'axis y1') | |
.call( | |
d3.axisLeft(yScale1) | |
.ticks(50) | |
.tickSize(-size.width) | |
) | |
.append('text') | |
.text('temperature [℃]') | |
.attr('text-anchor', 'start') | |
.attr('stroke', '#F00') | |
.attr('transform', 'translate(' + -margin.left / 4 + ', ' + size.height / 2 + ')rotate(90)'); | |
var yAxis2 = svg.append('g') | |
.attr('class', 'axis y2') | |
.attr('transform', 'translate(' + size.width + ', 0)') | |
.call( | |
d3.axisRight(yScale2) | |
.ticks(10) | |
.tickSize(-size.width) | |
) | |
.append('text') | |
.text('humidity [%]') | |
.attr('stroke', '#0F0') | |
.attr('transform', 'translate(' + margin.right / 4 + ', ' + size.height / 2 + ')rotate(90)'); | |
var yAxis3 = svg.append('g') | |
.attr('class', 'axis y3') | |
.attr('transform', 'translate(' + size.width + ', 0)') | |
.call( | |
d3.axisRight(yScale3) | |
.ticks(10) | |
.tickSize(-size.width) | |
) | |
.append('text') | |
.text('pressure [hPa]') | |
.attr('stroke', '#00F') | |
.attr('transform', 'translate(' + margin.right * 7 / 8 + ', ' + size.height / 2 + ')rotate(90)'); | |
svg.select('.y3') | |
.selectAll('.tick') | |
.selectAll('text') | |
.attr('transform', 'translate(' + margin.right / 2 + ', 0)'); | |
// Grid | |
svg.selectAll('line') | |
.attr('stroke', '#ddd'); | |
// Graph | |
var line1 = d3.line() | |
.x(function(d, i) { return xScale( new Date(d.datetime) ); }) | |
.y(function(d, i) { return yScale1( d.temperature ); }); | |
var line2 = d3.line() | |
.x(function(d, i) { return xScale( new Date(d.datetime) ); }) | |
.y(function(d, i) { return yScale2( d.humidity ); }); | |
var line3 = d3.line() | |
.x(function(d, i) { return xScale( new Date(d.datetime) ); }) | |
.y(function(d, i) { return yScale3( d.pressure ); }); | |
svg.append('path') | |
.datum(dataset) | |
.attr('d', line1) | |
.attr('fill', 'none') | |
.attr('stroke', '#F00') | |
.attr('stroke-width', 2); | |
svg.append('path') | |
.datum(dataset) | |
.attr('d', line2) | |
.attr('fill', 'none') | |
.attr('stroke', '#0F0') | |
.attr('stroke-width', 2); | |
svg.append('path') | |
.datum(dataset) | |
.attr('d', line3) | |
.attr('fill', 'none') | |
.attr('stroke', '#00F') | |
.attr('stroke-width', 2); | |
} | |
/**************************************************/ | |
router.get('/', function(req, res, next) { | |
generateSvg(); | |
res.send(d3.select('body').node().innerHTML); | |
}); | |
module.exports = router; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment