Skip to content

Commit

Permalink
Data monitor: date, time, temp, humidity, PM10, PM2.5
Browse files Browse the repository at this point in the history
  • Loading branch information
georgialexandrov committed Jan 28, 2020
1 parent 6213e11 commit 5727b80
Show file tree
Hide file tree
Showing 14 changed files with 321 additions and 0 deletions.
21 changes: 21 additions & 0 deletions client/src/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import ApolloClient from 'apollo-boost';
import { ApolloProvider } from 'react-apollo';
import './App.css';
import Dashboard from './pages/Dashboard.tsx'

const client = new ApolloClient({
uri: 'http://localhost:4000/graphql'
});

function App() {
return (
<div className="App">
<ApolloProvider client={client}>
<Dashboard />
</ApolloProvider>
</div>
);
}

export default App;
41 changes: 41 additions & 0 deletions client/src/components/AirQuality.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from "react";
import { useQuery } from "@apollo/react-hooks";
import gql from "graphql-tag";

import Calendar from "./Calendar/index";
import Time from "./Time/index";
import Humidity from "./Data/Humidity"
import Temperature from "./Data/Temperature"
import Particle from "./Data/Particle"

const GET_AIR_QUALITY = gql`
{
latest_air_quality {
pm10
pm25
BME280_temperature
BME280_humidity
}
}
`;

export default function AirQuality() {
const { data, loading } = useQuery(GET_AIR_QUALITY, {});

if (loading) return <div>Loading...</div>
return (
<div className="data">
<div className="left">
<Calendar />
<Time />
</div>

<div className="right">
<Temperature data={data.latest_air_quality.BME280_temperature} />
<Humidity data={data.latest_air_quality.BME280_humidity} />
<Particle data={data.latest_air_quality.pm25} title="PM2.5" />
<Particle data={data.latest_air_quality.pm10} title="PM10" />
</div>
</div>
);
}
21 changes: 21 additions & 0 deletions client/src/components/Calendar/Calendar.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.calendar {
width: 100%;
display: flex;
flex-direction: column;
}

.calendar .date {
font-size: 4em;
}

.calendar .day {
font-size: 2em;
}

.calendar .month {
font-size: 1.5em;
}

.calendar .year {
font-size: 1.2em;
}
29 changes: 29 additions & 0 deletions client/src/components/Calendar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from "react";
import './Calendar.css';

const daysOfWeek = ['Неделя', 'Понеделник', 'Вторник', 'Сряда', 'Четвъртък', 'Петък', 'Събота', 'Неделя']
const monthsOfYear = ['Януари', 'Февруари', 'Март', 'Април', 'Май', 'Юни', 'Юли', 'Август', 'Септември', 'Ноември', 'Октомври', 'Декември']

export default function Calendar() {
const today = () => {
let today = new Date()
return {
date: today.getDate(),
day: daysOfWeek[today.getDay()],
month: monthsOfYear[today.getMonth()],
year: today.getFullYear()
}
}

return (
<div className="calendar">
<span className="day">{today().day}</span>
<span className="date">{today().date}</span>
<span className="month">{today().month}</span>
<span className="year">{today().year}</span>
</div>
);
}



12 changes: 12 additions & 0 deletions client/src/components/Data/Humidity.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from "react";
import './style.css'

export default function Data(props: any) {
return (
<div className="humidity">
<span role="img" aria-label='humidity'>💦</span>{props.data}
</div>
);
}


17 changes: 17 additions & 0 deletions client/src/components/Data/Particle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from "react";

export default function Data(props: any) {
const color = (particle: number) => {
if (particle < 10) return 'great';
if (particle > 10 && particle < 30) return 'not_great';
if (particle > 30 && particle < 50) return 'not_great_not_terrible';
if (particle > 50) return 'terrible';
}

return (
<div className="particle">
<span className={color(props.data)}>{props.data}</span>
<span className="title">{props.title}</span>
</div>
);
}
14 changes: 14 additions & 0 deletions client/src/components/Data/Temperature.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from "react";

export default function Data(props: any) {
return (
<div className="temperature">
<span>
<svg height="32px" version="1.1" viewBox="0 0 32 32" width="32px"><title /><defs /><g fill="none" fillRule="evenodd" id="Icons new Arranged Names" stroke="none" strokeWidth="1"><g fill="#000000" id="82 Thermometer Half Full"><path d="M16,30 C18.2091391,30 20,28.2091391 20,26 C20,24.5194342 19.1956017,23.2267458 18,22.5351287 L18,4.00494659 C18,2.89764516 17.1122704,2 16,2 C14.8954305,2 14,2.89702623 14,4.00494659 L14,22.5351287 C12.8043983,23.2267458 12,24.5194342 12,26 C12,28.2091391 13.7908609,30 16,30 Z M16,29 C14.3431457,29 13,27.6568543 13,26 C13,24.6885853 13.841462,23.5737048 15.01392,23.1658244 C15.0047629,23.1111049 15,23.0548783 15,22.9975267 L15,13.0024733 C15,12.455761 15.4477153,12 16,12 C16.5561352,12 17,12.4488226 17,13.0024733 L17,22.9975267 C17,23.0547158 16.995101,23.1109097 16.9856957,23.1656908 C18.1583541,23.5734612 19,24.6884421 19,26 C19,27.6568543 17.6568543,29 16,29 Z M16,32 C12.6862913,32 10,29.3137087 10,26 C10,24.2229949 10.7725059,22.6264183 12,21.5277869 L12,4.00552025 C12,1.78708529 13.790861,0 16,0 C18.2046438,0 20,1.7933325 20,4.00552025 L20,21.5277869 C21.2274941,22.6264183 22,24.2229949 22,26 C22,29.3137087 19.3137087,32 16,32 Z M16,32" id="Oval 245" /></g></g></svg>
</span>
{props.data} °C
</div >
);
}


39 changes: 39 additions & 0 deletions client/src/components/Data/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.temperature,
.humidity {
font-size: 3em;
}

.particle {
flex-basis: 1;
font-size: 3em;
flex-direction: column;
}

.particle span {
flex-basis: 1;
width: 100%;
}

.particle .title {
font-size: 0.4em;
}

.great {
color: green;
}

.not_great {
color: rgb(185, 185, 40);
}

.not_great_not_terrible {
color: orange;
}

.terrible {
color: red;
}

.dark path {
fill: white;
}
4 changes: 4 additions & 0 deletions client/src/components/Time/Time.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.time {
font-size: 3em;
width: 100%;
}
21 changes: 21 additions & 0 deletions client/src/components/Time/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React, { useState } from "react";
import './Time.css';

const formatDate = (now: Date = new Date()) => {
let hours = now.getHours() > 9 ? now.getHours() : '0' + now.getHours()
let minutes = now.getMinutes() > 9 ? now.getMinutes() : '0' + now.getMinutes()

return `${hours}:${minutes}`
}

export default function Time() {
let now = new Date()
const [time, updateTime] = useState(formatDate(now))

const timeout = (60 - now.getSeconds()) * 1000
setTimeout(() => updateTime(formatDate()), timeout)

return (
<div className="time">{time}</div>
);
}
17 changes: 17 additions & 0 deletions client/src/pages/Dashboard.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.titleBar {
display: flex;
flex-direction: row;
justify-content: flex-end;
}

.dark {
background: black;
color: white;
width: 100%;
height: 100vh;
}

.light {
background: white;
color: black;
}
19 changes: 19 additions & 0 deletions client/src/pages/Dashboard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React, { useState } from "react";
import AirQuality from "../components/AirQuality";
import './Dashboard.css';

export default function Dashboard(props: any) {
let [theme, setTheme] = useState('light');

const [themeName, themeTitle] = theme === 'dark' ? ['light', 'Light'] : ['dark', 'Dark']
return (
<div className={theme}>
<div className="titleBar">
<button onClick={() => setTheme(themeName)}>{themeTitle}</button>
</div>
<div className="content">
<AirQuality />
</div>
</div>
);
}
43 changes: 43 additions & 0 deletions schema/resolvers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const request = require('request');

module.exports = {
Query: {
latest_air_quality: () => {
const url = 'http://elastic:9200/air-quality/_search?sort=datetime:desc&size=1'

return new Promise((resolve, rej) => {
request.post(url, { json: { "query": { "bool": {} } } }, (error, response, body) => {
if (!error && response.statusCode == 200) {
resolve(body.hits.hits[0]._source)
}
});
})
},
daily_air_quality: () => {
const url = 'http://elastic:9200/air-quality/_search?sort=datetime:desc&size=584'

return new Promise((resolve, rej) => {
request.post(url, {
json: {
"query": {
"range": {
"datetime": {
"gte": "2020-01-19T00:00:00",
"lte": "2020-01-20T00:00:00"
}
}
}
}
}, (error, response, body) => {
if (!error && response.statusCode == 200) {
resolve(body.hits.hits.map(hit => hit._source))
}
});
})
}
},
};




23 changes: 23 additions & 0 deletions schema/schema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const { gql } = require('apollo-server');

module.exports = gql`
scalar Date
type AirQualityRecord {
BME280_humidity: Float
BME280_pressure: Float
BME280_temperature: Float
datetime: Date
esp8266id: Int
max_micro: Int
min_micro: Int
pm10: Float
pm25: Float
signal: Int
software_version: String
}
type Query {
latest_air_quality: AirQualityRecord
daily_air_quality: [AirQualityRecord]
}
`;

0 comments on commit 5727b80

Please sign in to comment.