2024-04-01 16:49:47 +02:00
11 changed files with 327 additions and 137 deletions

View File

@@ -49,9 +49,9 @@ def loginDB():
)
return mydb
def getData(node, dataType, MAC, dateStart, dateEnd):
def getData(node, dataTypes, MAC, dateStart, dateEnd):
mydb = loginDB()
query = get_query(node, dataType, MAC, False, False, dateStart, dateEnd)
query = get_query(node, dataTypes, MAC, False, False, dateStart, dateEnd)
cursor = mydb.cursor(dictionary=True) # Enable dictionary output
cursor.execute(query)
result = cursor.fetchall() # Fetch the results
@@ -62,7 +62,7 @@ def getData(node, dataType, MAC, dateStart, dateEnd):
def getNodeInfo(macAdress):
mydb = loginDB()
query = get_query(False, False, macAdress, False, False)
query = get_query(False, False, macAdress, False, False, False, False)
cursor = mydb.cursor(dictionary=True) # Enable dictionary output
cursor.execute(query)
result = cursor.fetchall() # Fetch the results

View File

@@ -1,5 +1,9 @@
def get_query(node, dataType, MAC, questionID, replies, dateStart, dateEnd):
if dateStart and dateEnd and node:
if dateStart and dateEnd and node and dataType:
query = f'''SELECT *
FROM Measurement
WHERE TimeStamp BETWEEN '{dateStart}' AND '{dateEnd}' AND NodeID = {node} AND Type IN ('{dataType}');'''
elif dateStart and dateEnd and node:
query = f'''SELECT *
FROM Measurement
WHERE TimeStamp BETWEEN '{dateStart}' AND '{dateEnd}' AND NodeID = {node};'''
@@ -21,10 +25,7 @@ def get_query(node, dataType, MAC, questionID, replies, dateStart, dateEnd):
query = f"SELECT * FROM Question"
elif replies:
query = f"SELECT * FROM Reply"
elif dateStart and dateEnd and node:
query = f'''SELECT *
FROM Measurement
WHERE TimeStamp BETWEEN '{dateStart}' AND '{dateEnd}';'''
else:
query = "SELECT * FROM `Measurement`"
return query

View File

@@ -42,8 +42,7 @@ class Graph {
}
updateData(type, value, timestamp) {
this.timeArray.push(timestamp);
// this.timeArray.push(timestamp);
switch (type) {
case "Temp":
this.tempArray.push(value);
@@ -67,7 +66,7 @@ class Graph {
x: [this.timeArray],
y: [this.tempArray, this.humiArray, this.eco2Array, this.tvocArray],
};
console.log(update);
Plotly.update(this.id, update);
}
}
@@ -140,10 +139,19 @@ class DataProcessor {
}
updateGraph() {
this.graph.timeArray = [];
this.graph.tempArray = [];
this.graph.humiArray = [];
this.graph.eco2Array = [];
this.graph.tvocArray = [];
for (let i = 0; i < this.data.length; i++) {
if (i % 4 == 0){
this.graph.timeArray.push(this.data[i].TimeStamp);
}
this.graph.updateData(this.data[i].Type, this.data[i].Value, this.data[i].TimeStamp);
console.log(this.data[i].Type, this.data[i].Value, this.data[i].TimeStamp);
this.graph.updateGraph();
}
}
this.graph.updateGraph();
}
}

View File

@@ -24,10 +24,10 @@ container.setAttribute("class", "container");
const dataTypesContainer = document.createElement("div");
dataTypesContainer.setAttribute("class", "data-types");
const temperatureCheckbox = createCheckBox("temperature", "Temperature");
const humidityCheckbox = createCheckBox("humidity", "Humidity");
const eco2Checkbox = createCheckBox("eco2", "eCO2");
const tvocCheckbox = createCheckBox("tvoc", "TVOC");
const temperatureCheckbox = createCheckBox("Temp", "Temperature");
const humidityCheckbox = createCheckBox("Humi", "Humidity");
const eco2Checkbox = createCheckBox("eCO2", "eCO2");
const tvocCheckbox = createCheckBox("TVOC", "TVOC");
dataTypesContainer.appendChild(temperatureCheckbox.checkbox);
dataTypesContainer.appendChild(temperatureCheckbox.checkboxLabel);
@@ -55,24 +55,30 @@ filterButton.addEventListener("click", () => {
temperatureCheckbox,
humidityCheckbox,
eco2Checkbox,
tvocCheckbox,
tvocCheckbox
];
checkboxes.forEach((checkbox) => {
if (checkbox.checkbox.checked) {
selectedFields.push(checkbox.checkbox.id);
selectedFields.push(String(checkbox.checkbox.id));
}
});
let selectedFieldsString = selectedFields.map(String);
let formattedString = '(' + selectedFieldsString.map(item => `'${item}'`).join(', ') + ')';
const filteredData = [
startDate,
endDate,
selectedNodes,
selectedFields
formattedString
];
console.log(filteredData);
console.log(startDate, endDate, selectedNodes);
generateLink(startDate, endDate, selectedNodes);
generateLink(startDate, endDate, selectedNodes, formattedString);
fetchData();
});
@@ -98,7 +104,7 @@ nodeFilter.setAttribute("class", "node-filter");
const nodeInput = document.createElement("input");
nodeInput.setAttribute("type", "text");
nodeInput.setAttribute("placeholder", "Enter node (A, B, etc.)");
nodeInput.setAttribute("placeholder", "Enter Node Name (* for all)");
nodeInput.setAttribute("id", "node-input");
nodeInput.setAttribute("class", "input-field");
@@ -110,12 +116,12 @@ container.appendChild(filterButton);
document.body.appendChild(container);
// Function to get the link for the get request
function generateLink(dateStart, dateEnd, node) {
function generateLink(dateStart, dateEnd, node, dataTypes) {
const baseUrl = 'http://145.92.8.114/getMeasurements';
const formattedDateStart = new Date(dateStart).toISOString().replace('T', '%20');
const formattedDateEnd = new Date(dateEnd).toISOString().replace('T', '%20');
link = `${baseUrl}?dateStart=${formattedDateStart}&dateEnd=${formattedDateEnd}&node=${node}`;
link = `${baseUrl}?dateStart=${formattedDateStart}&dateEnd=${formattedDateEnd}&node=${node}&dataType=${dataTypes}`;
console.log(link);
}

View File

@@ -0,0 +1,27 @@
class ChartConfigClass{
constructor(data, text){
this.data = data
this.text = text
}
get chartConfig() {
return{
type: 'pie',
data: this.data,
options: {
responsive: true,
legend: {
position: 'top',
},
title: {
display: true,
text: this.text
},
animation: {
animateScale: true,
animateRotate: true
}
}
}
}
}

View File

@@ -30,24 +30,30 @@
<body>
<div class="chart-container">
<div class="chart">
<h2>Question 1: How clean are the toilets?</h2>
<canvas id="chart1"></canvas>
</div>
<div class="chart">
<h2>Question 2: How clean is the study area?</h2>
<canvas id="chart2"></canvas>
</div>
<div class="chart">
<h2>Question 3: What do you think of the temperature in the study area?</h2>
<canvas id="chart3"></canvas>
</div>
<div class="chart">
<h2>Question 4: How crowded would you say the study area is?</h2>
<canvas id="chart4"></canvas>
</div>
<div class="chart">
<h2>Question 5: Is there enough help available on the 5th floor?</h2>
<canvas id="chart5"></canvas>
</div>
<!-- Add more questions and canvas elements as needed -->
</div>
<script src="questions-main-class.js"></script>
<script src="questions-chart-class.js"></script>
<script src="questions-creation-class.js"></script>
<script src="questions-main.js"></script>
</body>
</html>

View File

@@ -1,3 +1,4 @@
//For now create dummy data to show on the website.
let dummydata1 = [40, 30, 20];
let questionOptionsDummy1 = ['disgusting','clean', 'fine'];
@@ -13,119 +14,41 @@ let questionOptionsDummy4 = ['really crowded','not at all', 'its fine', ];
let dummydata5 = [30, 20, 20];
let questionOptionsDummy5 = ['no','yes', 'decently'];
const question1Data = new QuestionCreationClass(dummydata1,questionOptionsDummy1)
const question2Data = new QuestionCreationClass(dummydata2,questionOptionsDummy2)
const question3Data = new QuestionCreationClass(dummydata3, questionOptionsDummy3);
const question4Data = new QuestionCreationClass(dummydata4, questionOptionsDummy4);
const question5Data = new QuestionCreationClass(dummydata5, questionOptionsDummy5);
//make arrays to store data.
let chartConfigArray = [];
let textArray = [];
const chartConfig1 = {
type: 'pie',
data: question1Data.questionData,
options: {
responsive: true,
legend: {
position: 'top',
},
title: {
display: true,
text: 'Question 1 Responses'
},
animation: {
animateScale: true,
animateRotate: true
}
}
};
let questionArray = [];
let questionOptionsDummy = [];
let dummydata = [];
const chartConfig2 = {
type: 'pie',
data: question2Data.questionData,
options: {
responsive: true,
legend: {
position: 'top',
},
title: {
display: true,
text: 'Question 2 Responses'
},
animation: {
animateScale: true,
animateRotate: true
}
}
};
//Go along the array's to fetch data, and push this in a class.
for (let i = 0; i < 5; i++) {
dummydata.push(dummydata1, dummydata2, dummydata3, dummydata4, dummydata5);
questionOptionsDummy.push(questionOptionsDummy1, questionOptionsDummy2, questionOptionsDummy3, questionOptionsDummy4, questionOptionsDummy5);
const chartConfig3 = {
type: 'pie',
data: question3Data.questionData,
options: {
responsive: true,
legend: {
position: 'top',
},
title: {
display: true,
text: 'Question 3 Responses'
},
animation: {
animateScale: true,
animateRotate: true
}
}
};
questionArray.push(new QuestionCreationClass(dummydata[i], questionOptionsDummy[i]));
}
const chartConfig4 = {
type: 'pie',
data: question4Data.questionData,
options: {
responsive: true,
legend: {
position: 'top',
},
title: {
display: true,
text: 'Question 4 Responses'
},
animation: {
animateScale: true,
animateRotate: true
}
}
};
//Go allong another array to also give the class that creates the charts the data collected by the previous array.
for (let i = 0; i < 5; i++){
textArray.push('Question 1 Responses', 'Question 2 Responses', 'Question 3 Responses', 'Question 4 Responses', 'Question 5 Responses');
const chartConfig5 = {
type: 'pie',
data: question5Data.questionData,
options: {
responsive: true,
legend: {
position: 'top',
},
title: {
display: true,
text: 'Question 5 Responses'
},
animation: {
animateScale: true,
animateRotate: true
}
}
};
chartConfigArray.push(new ChartConfigClass(questionArray[i].questionData, textArray[i]));
}
// Create the charts
const ctx1 = document.getElementById('chart1').getContext('2d');
const myChart1 = new Chart(ctx1, chartConfig1);
const myChart1 = new Chart(ctx1, chartConfigArray[0].chartConfig);
const ctx2 = document.getElementById('chart2').getContext('2d');
const myChart2 = new Chart(ctx2, chartConfig2);
const myChart2 = new Chart(ctx2, chartConfigArray[1].chartConfig);
const ctx3 = document.getElementById('chart3').getContext('2d');
const myChart3 = new Chart(ctx3, chartConfig3);
const myChart3 = new Chart(ctx3, chartConfigArray[2].chartConfig);
const ctx4 = document.getElementById('chart4').getContext('2d');
const myChart4 = new Chart(ctx4, chartConfig4);
const myChart4 = new Chart(ctx4, chartConfigArray[3].chartConfig);
const ctx5 = document.getElementById('chart5').getContext('2d');
const myChart5 = new Chart(ctx5, chartConfig5);
const myChart5 = new Chart(ctx5, chartConfigArray[4].chartConfig);

View File

@@ -50,7 +50,7 @@ body {
border-radius: 10px;
margin: 20px;
padding: 20px;
width: 100%;
width: 90;
box-sizing: border-box;
}
@@ -98,8 +98,7 @@ body {
}
.filter-button {
flex: 1;
width: 20%;
width: 10%;
background-color: #007bff;
color: white;
padding: 10px;
@@ -108,4 +107,10 @@ body {
cursor: pointer;
}
.js-plotly-plot {
align-self: center;
width: 95%;
height: 100%;
margin: 10px;
}
/* Additional styling as needed */

View File

@@ -4,6 +4,7 @@
}
body {
flex-direction: row;
padding-top: 5vw;
display: flex;
background-color: #dbd7d7;
@@ -42,16 +43,27 @@
}
#data-container {
width: 80%;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
border: 1px solid #ccc;
}
.chart-container {
width: 80%;
margin: 20px auto;
justify-content: center;
align-self: start;
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 100%;
}
.chart {
width: 30%;
margin: 20px;
padding: 20px;
background-color: #dbd7d7;
border: 3px solid #000;
border-radius: 30px;
}
canvas {
margin-bottom: 20px;

View File

@@ -0,0 +1,202 @@
* {
box-sizing: border-box;
font-family: "Roboto", sans-serif;
}
body {
display: flex;
justify-content: center;
margin: 0;
margin-top: 8vh;
background-color: #f0f0f0;
flex-direction: column;
background-color: #afafaf;
align-items: center;
}
.gaugeGroup {
width: 98vw;
height: auto;
display: flex;
flex-direction: column; /* Keep as column */
justify-content: flex-start;
background-color: #333;
color: #fff;
padding: 10px;
border-radius: 50px;
border: 2px solid #333;
clear: both;
margin-bottom: 10px;
position: relative;
}
.groupTitle {
width: 100%;
text-align: center;
font-size: 24px;
}
.Node {
display: flex;
justify-content: space-around;
align-items: center;
width: 100%;
height: 100%;
}
.Sensorvalues {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
flex-wrap: wrap;
width: 15%;
height: 110%;
background-color: #ddd;
color: #333;
padding: 10px;
margin: 10px;
border-radius: 10px;
text-align: center;
position: relative;
padding-top: 3vh; /* Increase bottom padding */
}
.gaugeContainer {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 80%; /* Increase the height from 70% to 80% */
position: relative;
overflow: visible;
height: 5vh;
margin-bottom: 1vh;
}
.gaugeImage {
width: 100%;
height: auto;
max-height: 120%;
object-fit: contain;
position: absolute; /* Make the image position absolute */
top: 0;
left: 0;
z-index: 1; /* Make the image display below the needle */
bottom: 0;
}
.gaugeValue, .gaugeText {
width: 100%;
text-align: center;
font-size: 24px;
z-index: 2;
}
.gaugeText {
width: 100%;
text-align: center;
font-size: 1.4vw;
z-index: 2;
position: absolute;
top: -1.4vw; /* Adjust this value to move the text further down */
}
.arrowimg {
width: 3vh;
height: auto;
max-height: 100%;
object-fit: contain;
position: absolute;
top: 0.5vw;
right: 1.2vw;
z-index: 2;
}
.valueContainer {
display: flex;
justify-content: center;
margin-top: 10px;
}
#valueText {
font-size: 20px;
}
.needle {
position: absolute;
bottom: -10%; /* Lower the needle to the bottom */
left: 50%;
width: 2px;
height: 100%;
background-color: black;
transform-origin: bottom;
z-index: 3; /* Make the needle display above the image */
transition: transform 0.1s ease-out;
}
.contentContainer {
display: flex;
flex-direction: row; /* Layout children side by side */
width: 100%;
height: 100%;
}
.navbar {
background-color: #333;
height: 60px;
display: flex;
align-items: center;
padding: 0 20px;
position: fixed; /* Fix the navbar at the top of the page */
top: 0; /* Position it at the very top */
width: 100%; /* Make it span the full width of the page */
z-index: 1000; /* Make sure it's above all other elements */
}
.navbar-nav {
list-style: none;
display: flex;
align-items: center;
justify-content: center; /* Center the links horizontally */
height: 100%;
width: 100%; /* Make it span the full width of the navbar */
}
.nav-item {
margin-right: 20px;
}
.nav-link {
color: #fff;
text-decoration: none;
font-size: 18px;
}
.plotly-container {
width: 100%;
float: bottom;
padding: 1vw;
align-items: center;
justify-content: center;
display: flex;
}
.js-plotly-plot {
width: 90%;
height: 100%;
}
.disabled {
opacity: 0;
height: 0;
}