From a4cd746fed484cc3651e1f046433d1f111db580f Mon Sep 17 00:00:00 2001 From: Miisa Ekholm <73100292+Miisa@users.noreply.github.com> Date: Thu, 27 Oct 2022 22:49:37 +0300 Subject: [PATCH] Final changes Changed login to both modes and layout, modified period selection in chart --- WebUI/index.html | 240 ++++++++++++++++++------------------ WebUI/index.js | 65 +++++----- WebUI/main.js | 292 ++++++++++++++++++++++++++------------------ WebUI/style.css | 83 ++++++++++--- WebUI/user_log.json | 68 ++++++++++- 5 files changed, 449 insertions(+), 299 deletions(-) diff --git a/WebUI/index.html b/WebUI/index.html index 2b71598..1c0799c 100644 --- a/WebUI/index.html +++ b/WebUI/index.html @@ -9,135 +9,128 @@ - - +
-

ESP-Ventilation

-
-

-
- -
-
+

ABB Ventilation Controller

-
-
-
-
- - - -
-
-
- - - -

-
-
-
-
-
-

Wrong username or password

-

All fields must be filled!

-

You must log in to access manual mode
Please give your credentials:

- -

- -

- -
-

If you don't have account, please contact the site administrator

-
-
-
-
-

Fan is not settled in required time!

-
-
-
-
-

Set pressure value

- 10 Pa - -
-
+
+

+
+ +
+
+
+
+ -
-
-
-

Set fan speed

- 0 % - +
+
+ +
+
+
+ +

+
+
+
+
+
+
+
+

Set pressure value

+ 0 Pa + +
+
+
+
+
+
+

Set fan speed

+ 0 % + +
-
-
-
-

-
-
- Monitor -
-
-

Pressure

- 0 -

Pa

-
-
-
-
-

Fan speed

- 0 -

%

-
-
-
-
-

CO2

- 0 -

ppm

-
-
-
-
-

Temperature

- 0 -

-
-
-
-
-

Relative Humidity

- 0 -

%

-
-
-
-
-
- - -
+ + +
+
+
+

Data History

+ No data found for selected period. +
+
+ + + + + +
-
-

-
+
+

User Log History

@@ -151,7 +144,6 @@
-

- +
\ No newline at end of file diff --git a/WebUI/index.js b/WebUI/index.js index 8cb9992..d15e1dc 100644 --- a/WebUI/index.js +++ b/WebUI/index.js @@ -12,7 +12,15 @@ const mqtt = require('mqtt'); const session = require('express-session'); const bcrypt = require('bcrypt') -const client = mqtt.connect('mqtt://127.0.0.1:1883', {clientId: 'node_server', clean: true}) +const client = mqtt.connect('mqtt://192.168.1.254:1883', + {username: 'SmartIotMQTT', + password: 'SmartIot', + clientId: 'node_server', + clean: true, + connectTimeout: 8000, + reconnectPeriod: 1000, + }) +//const client = mqtt.connect('mqtt://127.0.0.1:1883', {clientId: 'node_server', clean: true}) let newData; let user; let msg; @@ -46,14 +54,10 @@ function write(data, filePath) { } function getTime(){ - let today = new Date(); - let day = ("0" + today.getDate()).slice(-2); - let month = ("0" + (today.getMonth() + 1)).slice(-2); - let hours = ("0" + today.getHours()).slice(-2); - let mins = ("0" + today.getMinutes()).slice(-2); - let secs = ("0" + today.getSeconds()).slice(-2); - let timestamp = (day + '.' + month + '.' + today.getFullYear() + ' ' + hours + '.' + mins + '.' + secs).toString(); - return timestamp; + let day = new Date(); + day = new Date(day.getTime() - day.getTimezoneOffset()*60000); + let today = day.toISOString().replace('T', ' ').slice(0,19); + return today; } client.on('connect', ()=>{ @@ -62,14 +66,13 @@ client.on('connect', ()=>{ client.subscribe('controller/status', (err)=>{ if(err){ - console.log('Subscription failed') + console.log('Subscription failed ' + err); } }); io.on('connection', (socket)=>{ console.log("User " + socket.id + " connected"); - socket.on('setting', (arg)=> { - let data = JSON.stringify(arg); + socket.on('setting', (arg)=> { client.publish("controller/settings", JSON.stringify(arg), { qos: 2, retain: false }, (error)=>{ if(error){ console.log(error); @@ -80,9 +83,6 @@ io.on('connection', (socket)=>{ client.on('message', async (topic, message) =>{ newData = JSON.parse(message); - console.log(newData); - io.emit('data', newData); - let info = []; try { info = await read('data.json'); @@ -90,7 +90,8 @@ client.on('message', async (topic, message) =>{ let now = getTime(); newData['ts'] = now; info.push(newData); - write(info, 'data.json'); + write(info, 'data.json'); + io.emit('data', newData); }); @@ -98,15 +99,6 @@ app.get('/', (req, res)=>{ res.sendFile(path.join(__dirname + '/index.html')); }) -app.get('/data', async (req, res) => { - try { - const data = await read('data.json'); - res.json(data); - } catch (e) { - res.status(404).send(e); - } -}); - app.get('/register', (req,res)=>{ res.send(`

Register

@@ -132,14 +124,20 @@ app.post('/', async (req,res)=>{ if(bcrypt.compareSync(password, pwd)){ let now = getTime(); + let d = now.slice(8,10); + let m = now.slice(5,7); + let y = now.slice(0,4); + let t = now.slice(11, 19); + let stamp = d + '.' + m + '.' + y + ' ' + t; + //console.log(stamp); req.session.userId = username; - req.session.startTime = now; + req.session.startTime = stamp; console.log('Password is correct'); user = req.session.userId; io.emit('user', user); sesUser = user; sesStart = req.session.startTime; - res.status(205); + res.redirect('/'); } else{ msg = 'wrong'; @@ -183,7 +181,12 @@ app.post('/register', async (req,res) =>{ app.post('/logout',async (req, res) =>{ let now = getTime(); - req.session.endTime = now; + let d = now.slice(8,10); + let m = now.slice(5,7); + let y = now.slice(0,4); + let t = now.slice(11, 19); + let stamp = d + '.' + m + '.' + y + ' ' + t; + req.session.endTime = stamp; let sesEnd = req.session.endTime; let log = []; try { @@ -196,6 +199,7 @@ app.post('/logout',async (req, res) =>{ "Login": sesStart, "Logout": sesEnd } + console.log(newLog); log.unshift(newLog); write(log, 'user_log.json'); @@ -208,7 +212,7 @@ app.post('/logout',async (req, res) =>{ }); }); - +/* app.get('/data', async (req, res) => { try { const data = await read('data.json'); @@ -217,6 +221,5 @@ app.get('/data', async (req, res) => { res.status(404).send(e); } }); - - +*/ server.listen(3000, () => console.log('Server listening on port 3000')); \ No newline at end of file diff --git a/WebUI/main.js b/WebUI/main.js index cb14330..c52753e 100644 --- a/WebUI/main.js +++ b/WebUI/main.js @@ -1,3 +1,4 @@ + const automode = document.getElementById('m_auto'); const manmode = document.getElementById('m_man'); const s_pressure = document.getElementById('pressure'); //slider @@ -12,7 +13,10 @@ const canvas = document.getElementById('dataChart'); const filter = document.getElementById('data'); const submit = document.getElementById('btn_login'); const log_out = document.getElementById('btn_log_out'); -let data_miss = false; +const start = document.getElementById('start-time'); +const end = document.getElementById('end-time'); +const reset = document.getElementById('btn_reset'); + let user; let pointerX = -1; let pointerY = -1; @@ -21,18 +25,23 @@ let lastY = 0; let counter = 0; let lastSpeed = 0; let notSettled = 0; +let day = new Date(); +day = new Date(day.getTime() - day.getTimezoneOffset()*60000); +let today = day.toISOString().slice(0,16); +start.value = today.replace('T', ' ') + ':00'; +end.value = today.replace('T', ' ') + ':00'; +let start_time = new Date(start.value).getTime(); +let end_time = new Date(end.value).getTime(); const socket = io(); socket.on('connection'); socket.on('data', (data) =>{ - if(data.auto === true){ - s_pressure.value = data.setpoint; - document.getElementById('set_press').value = s_pressure.value + ' Pa'; + if(data.error === true){ + document.getElementById('mon-warn').style.display = 'block'; } - if(data.auto === false){ - s_speed.value = data.setpoint; - document.getElementById('set_speed').value = s_speed.value + ' %'; + else{ + document.getElementById('mon-warn').style.display = 'none'; } g_pressure.value = data.pressure; g_co.value = data.co2; @@ -40,16 +49,14 @@ socket.on('data', (data) =>{ g_speed.value = data.speed; g_temp.value = data.temp; updateChart(); - checkData(); - checkFan(); circleColor(); }); socket.on('pwd', (data) =>{ if(data){ - automode.checked = true; - document.getElementById('login-form').style.display = "block"; - document.getElementById('pwd-warn').style.display = "block"; + sessionStorage.setItem('reload', true); + document.location.reload(); + } }); @@ -59,6 +66,32 @@ socket.on('user', (data) =>{ sessionStorage.setItem('loggedIn', 'true'); }); +reset.addEventListener('click', e =>{ + e.preventDefault(); + start.value = today.replace('T', ' ') + ':00'; + end.value = today.replace('T', ' ') + ':00'; + start_time = new Date(start.value).getTime(); + end_time = new Date(end.value).getTime(); + + //start.value = today.replace('T', ' ') + ':00'; + //end.value = today.replace('T', ' ') + ':00'; + updateChart(); +}) + +start.addEventListener('change', e =>{ + e.preventDefault(); + start_time = start.value + ':00'; + start_time = new Date(start_time).getTime(); + updateChart(); +}); + +end.addEventListener('change', e =>{ + e.preventDefault(); + end_time = end.value + ':00'; + end_time = new Date(end_time).getTime(); + updateChart(); +}); + s_pressure.addEventListener('input', e =>{ e.preventDefault(); sendPressure(); @@ -70,20 +103,34 @@ s_speed.addEventListener('input', e =>{ }); automode.addEventListener('click', () =>{ - document.getElementById('login-form').style.display = "none"; + if(!sessionStorage.getItem('loggedIn')){ + document.getElementById('login-form').style.display = "block"; + document.getElementsByClassName('modes').style.display = "none"; + document.getElementsByClassName('set_values').style.display = "none"; + } + else{ + document.getElementById('login-form').style.display = "none"; + s_pressure.disabled = false; + document.getElementById('pr_div').style.opacity = 1; - s_pressure.disabled = false; - document.getElementById('pr_div').style.opacity = 1; - - s_speed.disabled = true; - document.getElementById('sp_div').style.opacity = 0.4; + s_speed.disabled = true; + document.getElementById('sp_div').style.opacity = 0.4; + } + }) manmode.addEventListener('click', () =>{ if(!sessionStorage.getItem('loggedIn')){ - document.getElementById('login-form').style.display = "block"; + document.getElementById('login-form').style.display = "block"; + document.getElementById('sp_div').style.display = "none"; + document.getElementById('pr_div').style.display = "none"; + document.getElementById('m_auto').style.display = "none"; + document.getElementById('m_man').style.display = "none"; + document.getElementById('auto_label').style.display = "none"; + document.getElementById('man_label').style.display = "none"; } - else{ + else{ + document.getElementById('login-form').style.display = "none"; document.getElementById('sp_div').style.opacity = 1; s_speed.disabled = false; @@ -92,11 +139,6 @@ manmode.addEventListener('click', () =>{ } }) -filter.addEventListener('change', e =>{ - e.preventDefault(); - updateChart(); -}) - submit.addEventListener('click', e =>{ if(document.getElementById('username').value && document.getElementById('password').value){ document.getElementById('login-form').style.display = "none"; @@ -111,7 +153,8 @@ document.getElementById('password').addEventListener('click', ()=>{ document.getElementById('form-warn').style.display = "none"; }); -log_out.addEventListener('click', ()=>{ +log_out.addEventListener('click', () =>{ + console.log('log out clicked'); localStorage.clear(); sessionStorage.clear(); }) @@ -155,20 +198,6 @@ function circleColor(){ } } -function checkFan(){ - if(lastSpeed !== g_speed.value){ - notSettled += 1; - lastSpeed = g_speed.value; - } - else{ - notSettled = 0; - document.getElementById('mon-warn').style.display = 'none'; - } - if(notSettled > 12){ - document.getElementById('mon-warn').style.display = 'block'; - } -} - function logOutUser(){ if(document.cookie){ log_out.click(); @@ -182,7 +211,7 @@ document.onmousemove = function(event) { setInterval(activityCheck, 1000); function activityCheck() { - if(document.cookie){ + if(sessionStorage.getItem('loggedIn')){ if(pointerX - lastX === 0 && pointerY - lastY === 0){ counter = counter + 1; } @@ -197,34 +226,65 @@ function activityCheck() { } } -function checkMode(){ +function checkUser(){ + if(sessionStorage.getItem('reload')){ + document.getElementById('login-form').style.display = "block"; + document.getElementById('pwd-warn').style.display = "block"; + sessionStorage.removeItem('reload'); + } if(document.cookie && sessionStorage.getItem('loggedIn')){ + document.getElementById('login-form').style.display = "none"; document.getElementById('user').style.display = "block"; document.getElementById('user').innerHTML = 'Signed in user: ' + localStorage.getItem('user'); document.getElementById('btn_log_out').style.display = "block"; + document.getElementById('user').style.display = "block"; + document.getElementById('user').innerHTML = 'Signed in user: ' + localStorage.getItem('user'); + document.getElementById('btn_log_out').style.display = "block"; + document.getElementById('user-table').style.width = "45%"; + document.getElementById('chart-cont').style.width = "50%"; - manmode.checked = true; - s_pressure.disabled = true; - document.getElementById('pr_div').style.opacity = 0.4; - s_speed.disabled = false; + if(manmode.checked = true){ + s_pressure.disabled = true; + document.getElementById('pr_div').style.opacity = 0.4; + s_speed.disabled = false; + } + if(automode.checked = true){ + s_speed.disabled = true; + document.getElementById('sp_div').style.opacity = 0.4; + s_pressure.disabled = false; + } } else{ - automode.checked = true; - s_speed.disabled = true; - document.getElementById('sp_div').style.opacity = 0.4; - s_pressure.disabled = false; - document.getElementById('user').style.display = "none"; - document.getElementById('btn_log_out').style.display = "none"; + document.getElementById('login-form').style.display = "block"; + document.getElementById('sp_div').style.display = "none"; + document.getElementById('pr_div').style.display = "none"; + document.getElementById('m_auto').style.display = "none"; + document.getElementById('m_man').style.display = "none"; + document.getElementById('auto_label').style.display = "none"; + document.getElementById('man_label').style.display = "none"; + document.getElementById('user-table').style.display = "none"; + document.getElementById('chart-cont').style.width = "95%"; } } -function checkData(){ - if(data_miss){ - document.getElementById('chart_warning').style.display = "block"; +function checkMode(){ + if(document.cookie && sessionStorage.getItem('loggedIn')){ + automode.checked = true; + s_speed.disabled = true; + document.getElementById('sp_div').style.opacity = 0.4; + document.getElementById('pr_div').style.opacity = 1; + s_pressure.disabled = false; + } + else{ + document.getElementById('login-form').style.display = "block"; + document.getElementById('sp_div').style.display = "none"; + document.getElementById('pr_div').style.display = "none"; + document.getElementById('m_auto').style.display = "none"; + document.getElementById('m_man').style.display = "none"; + document.getElementById('auto_label').style.display = "none"; + document.getElementById('man_label').style.display = "none"; + document.getElementById('user-table').style.display = "none"; } - if(!data_miss){ - document.getElementById('chart_warning').style.display = "none"; - } } function sendPressure(){ @@ -237,6 +297,54 @@ function sendSpeed(){ socket.emit('setting', speed); } +function updateChart(){ + async function fetchData(){ + const response = await fetch('data.json'); + const data = await response.json(); + if(data.length !== 0){ + let min = data[0].ts; + let max = data[data.length-1].ts; + start.min = min.slice(0, 16); + start.max = max.slice(0, 16); + end.min = min.slice(0, 16); + end.max = max.slice(0, 16); + } + const datapoints = data.filter(d => { + if((end_time-start_time) !== 0){ + return (new Date(d.ts).getTime() >= start_time && new Date(d.ts).getTime() <= end_time) + } + else{ + return data; + } + }) + return datapoints; + }; + + fetchData().then(datapoints => { + if(datapoints.length === 0) + { + document.getElementById('chart_warn').style.display = "block"; + } + const time = datapoints.map((index) => { + return index.ts; + }); + const co = datapoints.map((index) => { + return index.co2; + }); + const pressure = datapoints.map((index) => { + return index.pressure; + }); + const rh = datapoints.map((index) => { + return index.rh; + }); + myChart.config.data.labels = time; + myChart.config.data.datasets[0].data = co; + myChart.config.data.datasets[1].data = pressure; + myChart.config.data.datasets[2].data = rh; + myChart.update(); + }); +}; + const data = { datasets: [{ label: 'CO2', @@ -318,73 +426,13 @@ const config = { } - }//, - //aspectRatio: 1 + }, + aspectRatio: 2 } }; const myChart = new Chart(canvas, config); -function updateChart(){ - async function fetchData(){ - let datasize = 0; - let data_per_min = 12; - let datapoints; - await fetch('/data') - .then(res => res.json()) - .then(data =>{ - console.log(data.length); - datapoints = data.filter((elem, index)=>{ - switch(parseInt(filter.value)) - { - case 0: //all - datasize = data.length; - break; - case 1: //10min - datasize = 10*data_per_min; - break; - case 2: //30min - datasize = 30*data_per_min; - break; - case 3: //1 hour - datasize = 60*data_per_min; - break; - } - if(datasize > data.length){ - data_miss = true; - } - else{ - data_miss = false; - } - return index >= data.length -datasize; - }); - }); - - return datapoints; - }; - - fetchData().then(datapoints => { - const time = datapoints.map((time) => { - return time.ts; - }); - const co = datapoints.map((time) => { - return time.co2; - }); - const pressure = datapoints.map((time) => { - return time.pressure; - }); - const rh = datapoints.map((time) => { - return time.rh; - }); - myChart.config.data.labels = time; - myChart.config.data.datasets[0].data = co; - myChart.config.data.datasets[1].data = pressure; - myChart.config.data.datasets[2].data = rh; - myChart.update(); - checkData(); - }); -}; - fetch('user_log.json') .then((res)=>{ return res.json(); @@ -404,8 +452,8 @@ fetch('user_log.json') placeholder.innerHTML = out; }); -function getStartValues(){ - fetch('data.json') +async function getStartValues(){ + await fetch('data.json') .then((res) =>{ return res.json(); }) diff --git a/WebUI/style.css b/WebUI/style.css index 8831f61..1011cfe 100644 --- a/WebUI/style.css +++ b/WebUI/style.css @@ -11,7 +11,7 @@ body { padding-bottom: 5px; } main { - margin-top: 100px; + margin-top: 50px; padding-bottom: 20px; display: block; position: relative; @@ -21,11 +21,27 @@ main { aside { width: 100%; background-color: #F6FFF8; + margin-bottom: 50px; +} + +.upper{ + display: flex; + flex-wrap: wrap; + width: 100%; +} + +.lower{ + display: flex; + flex-wrap: wrap; + flex-direction: column; + width: 100%; + margin-bottom: 50px; } header { width: 100%; - height: 150px; + height: 100px; + color: black; } h1 { padding-top: 40px; @@ -51,12 +67,13 @@ h4{ text-align: center; } -.dropdown{ - position: relative; - float: right; +.filter{ + font-weight: bolder; } + .logout{ margin-left: 20px; + margin-top: 35px; } #btn_log_out{ margin-bottom: 10px; @@ -68,6 +85,14 @@ h4{ display: none; } +#btn_reset{ + position: relative; + float: right; + border-radius: 5px; + background-color: #CCE3DE; + border: 0.5px solid; +} + #user{ display: none; font-weight: bolder; @@ -77,6 +102,11 @@ h4{ background-color: red; } +.login{ + margin-top: 50px; + padding-top: 50px; +} + #login-form:valid #btn_login{ background-color: mediumseagreen; } @@ -89,6 +119,7 @@ h4{ font-weight: bolder; border-radius: 10px; display: none; + } #acc{ @@ -96,6 +127,12 @@ h4{ margin: auto; } +#chart_warn{ + display: none; + text-align: center; + color: red; +} + #mon-warn{ height: 20px; text-align: center; @@ -120,9 +157,8 @@ h4{ flex-direction: row; flex-wrap: wrap; justify-content: space-evenly; - margin: 20px; - padding: 20px; - width: 80%; + margin: auto; + width: 85%; } fieldset { @@ -176,7 +212,8 @@ fieldset { background-color: gray; } -.buttons{ +#buttons{ + display: block; font-size: 25px; font-weight: bolder; width: 12ch; @@ -186,6 +223,7 @@ fieldset { display: flex; flex-direction: column; align-items: center; + padding-top: 30px; } .set_values{ @@ -195,6 +233,10 @@ fieldset { justify-content: space-evenly; } +.sp_div{ + display: block; +} + .get_values{ display: flex; flex-direction: row; @@ -226,30 +268,32 @@ fieldset { display: flex; flex-direction: column; align-items: center; - width: 150px; + width: 200px; } -.chart-container{ - position: relative; - width: 700px; - height: 350px; +#chart-cont{ + display: block; + width: 90%; margin: auto; + margin-bottom: 30px; } canvas{ border-radius: 10px; border: 1px solid black; background-color: white; - } -.user-table{ +#user-table{ + display: block; margin-bottom: 50px; + width: 50%; + margin: auto; } table{ background-color: #CCE3DE; - width: 700px; + width: 90%; margin: auto; border-collapse: collapse; } @@ -274,10 +318,13 @@ output { width: 50%; } aside { - margin-top: 100px; + margin-top: 50px; background: #F6FFF8; width: 50%; } + .lower{ + flex-direction: row; + } } input[type="radio"] { diff --git a/WebUI/user_log.json b/WebUI/user_log.json index 9104869..fefcb64 100644 --- a/WebUI/user_log.json +++ b/WebUI/user_log.json @@ -1,15 +1,75 @@ [ + { + "id": 15, + "UserId": "Miisa", + "Login": "27.10.2022 18:51:43", + "Logout": "27.10.2022 18:54:01" + }, + { + "id": 14, + "UserId": "Jaakko", + "Login": "27.10.2022 16:59:26", + "Logout": "27.10.2022 17:00:54" + }, + { + "id": 13, + "UserId": "Miisa", + "Login": "27.10.2022 16:56:19", + "Logout": "27.10.2022 16:59:03" + }, + { + "id": 12, + "UserId": "Miisa", + "Login": "27.10.2022 16:54:23", + "Logout": "27.10.2022 16:54:33" + }, + { + "id": 11, + "UserId": "Miisa", + "Login": "27.10.2022 14:18:53", + "Logout": "27.10.2022 14:19:30" + }, + { + "id": 10, + "UserId": "Miisa", + "Login": "27.10.2022 14:17:45", + "Logout": "27.10.2022 14:18:42" + }, + { + "id": 9, + "UserId": "Miisa", + "Login": "27.10.2022 14:15:43", + "Logout": "27.10.2022 14:16:01" + }, + { + "id": 8, + "UserId": "Miisa", + "Login": "27.10.2022 14:14:49", + "Logout": "27.10.2022 14:15:06" + }, + { + "id": 7, + "UserId": "Miisa", + "Login": "27.10.2022 14:12:33", + "Logout": "27.10.2022 14:14:10" + }, + { + "id": 6, + "UserId": "Miisa", + "Login": "27.10.2022 13:29:52", + "Logout": "27.10.2022 13:30:54" + }, { "id": 5, "UserId": "Miisa", - "Login": "25.10.2022 20.19.50", - "Logout": "25.10.2022 20.19.55" + "Login": "27.10.2022 08:10:40", + "Logout": "27.10.2022 08:11:42" }, { "id": 4, "UserId": "Miisa", - "Login": "25.10.2022 20.18.27", - "Logout": "25.10.2022 20.18.43" + "Login": "27.10.2022 07:55:06", + "Logout": "27.10.2022 07:56:01" }, { "id": 3,