smart_garden_server/imports/ui/Overview.jsx

185 lines
8.5 KiB
JavaScript

import React from 'react'
import {CartesianGrid, Legend, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis} from 'recharts';
import SensorCardDeck from './SensorCardDeck'
import {SensorDataCollection, ActiveDeviceCollection, ConfiguredDevicesCollection} from "../../client/main";
import {useTracker} from 'meteor/react-meteor-data';
import { Col, Form, Row, Card, CardDeck } from "react-bootstrap";
import moment from 'moment'
export default function Overview() {
// Return the document of the currently active device in the activeDevice collection.
const activeDevice = useTracker(() => {
return ActiveDeviceCollection.find().fetch()[0];
});
// Return all documents of the configuredDevices collection.
const configuredDevices = useTracker(() => {
return ConfiguredDevicesCollection.find().fetch();
});
// If the activeDevice is not null or undefined, return and filter the documents of the last two days (48 Hrs) of the currently active device in the sensorData collection
// and reverse the array so that the oldest documents come first.
const sensorData = useTracker(() => {
if (activeDevice === null || activeDevice === undefined) {
return [];
} else {
return SensorDataCollection.find(
{
device_id: activeDevice.deviceId,
timestamp: { $gt: moment(Date.now()).subtract(2, 'days').toDate() }
},
{
sort: { timestamp: -1 }
}
).fetch().reverse();
}
});
// Set the selected device from the configured devices dropdown-menu, to the new currently active device.
const handleChange = (e) => {
if (e.target.value === "") {
console.log("No device selected!");
} else {
var doc = ActiveDeviceCollection.findOne({deviceId: activeDevice.deviceId});
ActiveDeviceCollection.update({_id: doc._id}, {$set: {deviceId: e.target.value}});
}
}
// Get the current date as string.
const getLabelFromStamp = (x) => {
return moment(x.timestamp).format("LLLL");
}
// Workaround for log(0).
const brightnessMapper = (x) => {
if (x.brightness < 1) {
x.brightness = 0.1
}
return x;
}
//If the data that is loaded from the database has not been fetched yet, show a loading screen. Else load the application.
if ((sensorData.length <= 0)) {
return (
<>
<br></br>
<Row>
<Col xs lg="2">
<h4>Devices:</h4>
</Col>
</Row>
<Row>
<Col xs lg="2">
<Form>
<Form.Group>
<Form.Control as="select" type="text" onChange={handleChange}>
<option></option>
{configuredDevices.map((devices, index) => {
return <option key={index} value={devices.deviceId}>{devices.alias}</option>
})}
</Form.Control>
</Form.Group>
</Form>
</Col>
<Col>
<h6>active device: {!activeDevice === undefined && !ConfiguredDevicesCollection.findOne({ deviceId: activeDevice.deviceId }) === undefined ?
ConfiguredDevicesCollection.findOne({ deviceId: activeDevice.deviceId }).alias : "No device selected"}</h6>
</Col>
</Row>
<CardDeck>
<Card>
<Card.Body>
<Card.Title>Loading!</Card.Title>
<Card.Text>Please wait...</Card.Text>
</Card.Body>
</Card>
</CardDeck>
</>
)
} else {
return (
<>
<br></br>
<Row>
<Col xs lg="2">
<h4>Devices:</h4>
</Col>
</Row>
<Row>
<Col xs lg="2">
<Form>
<Form.Group>
<Form.Control as="select" type="text" onChange={handleChange}>
<option></option>
{configuredDevices.map((devices, index) => {
return <option key={index} value={devices.deviceId}>{devices.alias}</option>
})}
</Form.Control>
</Form.Group>
</Form>
</Col>
<Col>
<h6>active device: {ConfiguredDevicesCollection.findOne({deviceId: activeDevice.deviceId}) === undefined ?
"No device selected" : ConfiguredDevicesCollection.findOne({deviceId: activeDevice.deviceId}).alias}</h6>
</Col>
</Row>
<SensorCardDeck/>
<Row>
<Col>
<ResponsiveContainer width='100%' height={325}>
<LineChart data={sensorData.filter(el => el.temperature !== null)} margin={{top: 50, right: 50, bottom: 20, left: 5}}>
<Line type="monotone" dataKey="temperature" stroke="#10b5de" dot={false}/>
<CartesianGrid stroke="#ccc" strokeDasharray="5 5"/>
<XAxis dataKey={getLabelFromStamp} tick={false} />
<YAxis/>
<Tooltip/>
<Legend/>
</LineChart>
</ResponsiveContainer>
</Col>
<Col>
<ResponsiveContainer width='100%' height={325}>
<LineChart data={sensorData.filter(el => el.humidity !== null)} margin={{top: 50, right: 50, bottom: 20, left: 5}}>
<Line type="monotone" dataKey="humidity" stroke="#ff6f00" dot={false}/>
<CartesianGrid stroke="#ccc" strokeDasharray="5 5"/>
<XAxis dataKey={getLabelFromStamp} tick={false}/>
<YAxis/>
<Tooltip/>
<Legend/>
</LineChart>
</ResponsiveContainer>
</Col>
</Row>
<Row>
<Col>
<ResponsiveContainer width='100%' height={325}>
<LineChart data={sensorData.filter(el => el.brightness !== null).map(brightnessMapper)} margin={{top: 50, right: 50, bottom: 20, left: 5}}>
<Line type="monotone" dataKey="brightness" stroke="#ffd500" dot={false}/>
<CartesianGrid stroke="#ccc" strokeDasharray="5 5"/>
<XAxis dataKey={getLabelFromStamp} tick={false}/>
<YAxis scale="log" domain={[0.1, 'dataMax']} tickFormatter={val => Math.round(val)} />
<Tooltip formatter={val => Math.round(val)}/>
<Legend/>
</LineChart>
</ResponsiveContainer>
</Col>
<Col>
<ResponsiveContainer width='100%' height={325}>
<LineChart data={sensorData.filter(el => el.moisture !== null)} margin={{top: 50, right: 50, bottom: 20, left: 5}}>
<Line type="monotone" dataKey="moisture" stroke="#1c4399" dot={false}/>
<CartesianGrid stroke="#ccc" strokeDasharray="5 5"/>
<XAxis dataKey={getLabelFromStamp} tick={false}/>
<YAxis/>
<Tooltip/>
<Legend/>
</LineChart>
</ResponsiveContainer>
</Col>
</Row>
</>
)
}
}