You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

360 lines
12 KiB
JavaScript

'use strict';
import React from 'react';
import { connect } from 'react-redux';
import _ from 'lodash';
import SensorWidget from '../components/sensor-widget';
import { fetchSensorData } from '../actions/action-creators';
import { round } from '../utils/format';
const getTime = function (str) {
let date = new Date(str);
return Math.floor(date.getTime() / 1000);
};
const sensorProps = React.PropTypes.shape({
fetched: React.PropTypes.bool,
fetching: React.PropTypes.bool,
data: React.PropTypes.array
});
var Home = React.createClass({
displayName: 'Home',
propTypes: {
_requestSensorData: React.PropTypes.func,
sensorUv: sensorProps,
sensorLuminosity: sensorProps,
sensorPressure: sensorProps,
sensorHumidity: sensorProps,
sensorTemperature: sensorProps,
sensorPm10: sensorProps,
sensorPm25: sensorProps,
sensorWindDir: sensorProps,
sensorWindSpeed: sensorProps,
sensorRain: sensorProps,
},
// Having measurements every minute is too much. Group them.
// Max seconds between reading for them to be considered part
// of the same group.
_mTimeThreshold: 120,
_mGroupSize: 6, // Equal to 10 measurements per hour.
_fetchInterval: null,
// In seconds.
_fetchRate: 300, // 5 min
prepareData: function (rawData) {
var data = null;
if (rawData && rawData.length) {
data = [];
rawData[0].value = +rawData[0].value;
let bucket = [rawData[0]];
for (var i = 1; i < rawData.length; i++) {
rawData[i].value = +rawData[i].value;
let prevTime = getTime(rawData[i - 1].createdAt);
let currTime = getTime(rawData[i].createdAt);
// Having measurements every minute is too much. Group them.
// To make sure that the grouped measurements are all around the same
// time there can't be more than X seconds difference between them.
if (currTime - prevTime > this._mTimeThreshold || bucket.length === this._mGroupSize) {
let f = {
createdAt: _.last(bucket).createdAt,
value: +round(_.meanBy(bucket, 'value'))
};
data.push(f);
bucket = [];
}
bucket.push(rawData[i]);
}
// After the loop finished there may still be data to process.
// if bucket.length < this._mGroupSize for example.
let f = {
createdAt: _.last(bucket).createdAt,
value: +round(_.meanBy(bucket, 'value'))
};
data.push(f);
}
let startToday = new Date();
startToday.setHours(0);
startToday.setMinutes(0);
startToday.setSeconds(0);
startToday = Math.floor(startToday.getTime() / 1000);
let startYesterday = startToday - (60 * 60 * 24);
let dataAll = [];
let dataToday = [];
let dataYesterday = [];
_.forEach(data, o => {
let date = new Date(o.createdAt);
let time = Math.floor(date.getTime() / 1000);
dataAll.push({
timestep: date,
value: +o.value
});
if (time >= startToday) {
dataToday.push({
timestep: date,
value: +o.value
});
}
if (time < startToday && time >= startYesterday) {
dataYesterday.push({
timestep: date,
value: +o.value
});
}
});
let avgs = {
today: _.meanBy(dataToday, 'value'),
yesterday: _.meanBy(dataYesterday, 'value')
};
let sums = {
today: _.sumBy(dataToday, 'value'),
yesterday: _.sumBy(dataYesterday, 'value')
};
let last = _.last(dataAll) || null;
return {
data: dataAll,
last,
avgs,
sums,
};
},
fetchData: function () {
let daysAgo3 = (new Date()).getTime() - (60 * 60 * 24 * 3 * 1000);
daysAgo3 = new Date(daysAgo3).toISOString();
this.props._requestSensorData('temperature', daysAgo3);
this.props._requestSensorData('humidity', daysAgo3);
this.props._requestSensorData('uv', daysAgo3);
this.props._requestSensorData('luminosity', daysAgo3);
this.props._requestSensorData('pressure', daysAgo3);
this.props._requestSensorData('pm10', daysAgo3);
this.props._requestSensorData('pm25', daysAgo3);
this.props._requestSensorData('windDir', daysAgo3);
this.props._requestSensorData('windSpeed', daysAgo3);
this.props._requestSensorData('rain', daysAgo3);
},
componentDidMount: function () {
this.fetchData();
this._fetchInterval = setInterval(() => {
this.fetchData();
}, this._fetchRate * 1000);
},
componentWillUnmount: function () {
if (this._fetchInterval) {
clearInterval(this._fetchInterval);
}
},
render: function () {
let sensorTemperatureData = this.prepareData(this.props.sensorTemperature.data);
let sensorHumidityData = this.prepareData(this.props.sensorHumidity.data);
let sensorUvData = this.prepareData(this.props.sensorUv.data);
let sensorLuminosityData = this.prepareData(this.props.sensorLuminosity.data);
let sensorPressureData = this.prepareData(this.props.sensorPressure.data);
let sensorPm10Data = this.prepareData(this.props.sensorPm10.data);
let sensorPm25Data = this.prepareData(this.props.sensorPm25.data);
let sensorWindDirData = this.prepareData(this.props.sensorWindDir.data);
let sensorWindSpeedData = this.prepareData(this.props.sensorWindSpeed.data);
let sensorRainData = this.prepareData(this.props.sensorRain.data);
return (
<section className='page'>
<header className='page__header'>
<div className='inner'>
<div className='page__headline'>
<h1 className='page__title'>Sense Dashboard</h1>
</div>
</div>
</header>
<div className='page__body'>
<section className='page__content'>
<div className='inner'>
<SensorWidget
className='card--temp'
fetching={this.props.sensorTemperature.fetching}
fetched={this.props.sensorTemperature.fetched}
title='Temperatur'
lastReading={sensorTemperatureData.last}
avgs={sensorTemperatureData.avgs}
plotData={sensorTemperatureData.data}
axisLineMax={40}
axisLineVal={20}
axisLineMin={0}
unit=' ºC'
/>
<SensorWidget
className='card--hum'
fetching={this.props.sensorPressure.fetching}
fetched={this.props.sensorPressure.fetched}
title='Luftdruck'
lastReading={sensorPressureData.last}
avgs={sensorPressureData.avgs}
plotData={sensorPressureData.data}
axisLineMax={1030}
axisLineVal={1000}
axisLineMin={970}
unit=' hPa'
/>
<SensorWidget
className='card--press'
fetching={this.props.sensorHumidity.fetching}
fetched={this.props.sensorHumidity.fetched}
title='rel. Luftfeuchte'
lastReading={sensorHumidityData.last}
avgs={sensorHumidityData.avgs}
plotData={sensorHumidityData.data}
axisLineMax={100}
axisLineVal={50}
axisLineMin={10}
unit=' %'
/>
<SensorWidget
className='card--press'
fetching={this.props.sensorRain.fetching}
fetched={this.props.sensorRain.fetched}
title='Niederschlag'
lastReading={sensorRainData.last}
sums={sensorRainData.sums}
plotData={sensorRainData.data}
axisLineMax={1}
axisLineVal={0.28}
axisLineMin={0}
unit=' L / m²'
/>
<SensorWidget
className='card--uv'
fetching={this.props.sensorWindDir.fetching}
fetched={this.props.sensorWindDir.fetched}
title='Windrichtung'
lastReading={sensorWindDirData.last}
avgs={sensorWindDirData.avgs}
plotData={sensorWindDirData.data}
axisLineMax={360}
axisLineVal={180}
axisLineMin={0}
unit=' °'
/>
<SensorWidget
className='card--uv'
fetching={this.props.sensorWindSpeed.fetching}
fetched={this.props.sensorWindSpeed.fetched}
title='Windgeschwindigkeit'
lastReading={sensorWindSpeedData.last}
avgs={sensorWindSpeedData.avgs}
plotData={sensorWindSpeedData.data}
axisLineMax={20}
axisLineVal={10}
axisLineMin={0}
unit=' km/h'
/>
<SensorWidget
className='card--lux'
fetching={this.props.sensorUv.fetching}
fetched={this.props.sensorUv.fetched}
title='Uv Licht'
lastReading={sensorUvData.last}
avgs={sensorUvData.avgs}
plotData={sensorUvData.data}
axisLineMax={5000}
axisLineVal={250}
axisLineMin={0}
unit=' μW/cm²'
/>
<SensorWidget
className='card--lux'
fetching={this.props.sensorLuminosity.fetching}
fetched={this.props.sensorLuminosity.fetched}
title='Helligkeit'
lastReading={sensorLuminosityData.last}
avgs={sensorLuminosityData.avgs}
plotData={sensorLuminosityData.data}
axisLineMax={135000}
axisLineVal={50000}
axisLineMin={0}
unit=' lx'
/>
<SensorWidget
className='card--pm'
fetching={this.props.sensorPm10.fetching}
fetched={this.props.sensorPm10.fetched}
title='Feinstaub 10 μm'
lastReading={sensorPm10Data.last}
avgs={sensorPm10Data.avgs}
plotData={sensorPm10Data.data}
axisLineMax={25}
axisLineVal={10}
axisLineMin={0}
unit=' μg/m³'
/>
<SensorWidget
className='card--pm'
fetching={this.props.sensorPm25.fetching}
fetched={this.props.sensorPm25.fetched}
title='Feinstaub 2.5 μm'
lastReading={sensorPm25Data.last}
avgs={sensorPm25Data.avgs}
plotData={sensorPm25Data.data}
axisLineMax={25}
axisLineVal={10}
axisLineMin={0}
unit=' μg/m³'
/>
</div>
</section>
</div>
</section>
);
}
});
// /////////////////////////////////////////////////////////////////// //
// Connect functions
function selector (state) {
return {
sensorUv: state.sensorUv,
sensorLuminosity: state.sensorLuminosity,
sensorPressure: state.sensorPressure,
sensorHumidity: state.sensorHumidity,
sensorTemperature: state.sensorTemperature,
sensorPm10: state.sensorPm10,
sensorPm25: state.sensorPm25,
sensorWindDir: state.sensorWindDir,
sensorWindSpeed: state.sensorWindSpeed,
sensorRain: state.sensorRain,
};
}
function dispatcher (dispatch) {
return {
_requestSensorData: (sensor, toDate) => dispatch(fetchSensorData(sensor, toDate))
};
}
module.exports = connect(selector, dispatcher)(Home);