Merge branch 'main' of gitlab.fdmci.hva.nl:propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-3/qaajeeqiinii59

This commit is contained in:
Bram Barbieri
2024-03-10 15:50:58 +01:00
13 changed files with 405 additions and 232 deletions

View File

@@ -1,8 +1,5 @@
#include <SPI.h>
#include "Adafruit_GFX.h"
#include "Adafruit_ST7796S_kbv.h"
#include "headerFile.h"
#include "displayText.h"
int i = 0;
char* Question[] = {
@@ -29,7 +26,6 @@ DisplayText displayText(tft);
void setup() {
tft.begin(); // Initialize the display
tft.setRotation(3); // Set the rotation to horizontal
tft.fillScreen(ST7796S_BLACK);
}
void loop() {
@@ -43,27 +39,5 @@ void loop() {
// writeText(Answer[0], 2, 50, 300, 4000);
displayText.writeText(Question[i], 3, 0, 0, 0, true, false);
displayText.writeText(Answer[i], 3, 0, 200, 0, true, true);
delay(10000);
delay(20000);
}
// void writeText(char* text, int size, int posX, int posY, int screenTime, bool center){
// //if true overwrites x
// if (center){
// posX = centerText(text);
// }
// tft.setCursor(posX, posY); // Set the cursor to the top left corner
// tft.setTextSize(size); // Set textsize
// tft.println(text);
// delay(screenTime);
// }
// int centerText(char* text) {
// int16_t x1, y1;
// uint16_t w, h;
// tft.getTextBounds(text, 0, 0, &x1, &y1, &w, &h); // Calculate the width of the text
// int x = (tft.width() - w) / 2; // Calculate the x-coordinate for the centered text
// return x;
// }

View File

@@ -4,8 +4,9 @@
//constructor
DisplayText::DisplayText(Adafruit_ST7796S_kbv& tftDisplay) : tft(tftDisplay) {
tft.setCursor(0,0);
tft.fillScreen(ST7796S_BLACK);
}
//display text public function
void DisplayText::writeText(char* text, int size, int posX, int posY, int screenTime, bool center, bool bottom) {
if (center) {
posX = centerText(text);
@@ -15,22 +16,60 @@ void DisplayText::writeText(char* text, int size, int posX, int posY, int screen
}
tft.setCursor(posX, posY);
tft.setTextSize(size);
tft.println(text);
printWordsFull(text);
delay(screenTime);
}
//to center the text when enabled in the public function
int DisplayText::centerText(char* text) {
int16_t x1, y1;
int16_t x1, y1;
uint16_t w, h;
tft.getTextBounds(text, 0, 0, &x1, &y1, &w, &h);
int x = (tft.width() - w) / 2;
return x;
}
//to dijsplay the text at the bottom when enabled in the public function
int DisplayText::bottomText(char* text) {
int16_t x1, y1;
uint16_t w, h;
tft.getTextBounds(text, 0, 0, &x1, &y1, &w, &h);
int y = (tft.height() - h);
return y;
}
//attempt to write the text out in full (wip)
void DisplayText::printWordsFull(char* text) {
char* textArray[100];
int i = 0;
//copy the text into a variable so the string can be re-used later
char* textCopy = strdup(text);
//split the text into words and put them into a array
char* word = strtok(text, " ");
while (word != NULL) {
textArray[i] = word;
word = strtok(NULL, " ");
i++;
}
int lineWidth = 0;
int maxLineWidth = 320; // replace with the width of your TFT display
int charWidth = 11; // replace with the width of your characters
for (int j = 0; j < i; j++) {
//count the amount of letters in the word
int wordLength = strlen(textArray[j]);
// If the word won't fit on the current line, move to the next line
if (lineWidth + wordLength * charWidth > maxLineWidth) {
tft.println();
//reset lineWidth
lineWidth = 0;
}
//print the text
tft.print(textArray[j]);
tft.print(" ");
lineWidth += (wordLength + 1) * charWidth; // +1 for the space
}
//removes textCopy out of the memory
free(textCopy);
}

View File

@@ -9,6 +9,7 @@ class DisplayText {
Adafruit_ST7796S_kbv& tft;
int centerText(char* text);
int bottomText(char* text);
void printWordsFull(char* text);
public:
DisplayText(Adafruit_ST7796S_kbv& tftDisplay);

View File

@@ -1,3 +1,8 @@
#include <SPI.h>
#include "Adafruit_GFX.h"
#include "Adafruit_ST7796S_kbv.h"
#include "displayText.h"
#define TFT_CS 14
#define TFT_DC 13
#define TFT_RST 12

View File

@@ -9,6 +9,7 @@ nav:
- 🎮 Arduino documentation:
- I2C: arduino-documentation/i2c-ESP32
- TFT screen : node-documentation/TFT-screen
- Classes : arduino-documentation/classes
- 🍓 RPi Documentation:
- Raspberry pi: Sp1SchetsProject/InfrastructuurDocumentatie/raspberryPi
- MariaDB: rpi-documentation/mariadb-installation
@@ -24,5 +25,5 @@ nav:
- Taskflow: brainstorm/Taskflow
- Design: Sp1SchetsProject/FirstDesign
- 🖨️ Software:
- Dev page: brainstrom/SotwareDocumentatie/Dev_page
- Dev page: brainstorm/SoftwareDocumentatie/Dev_page

View File

@@ -0,0 +1,73 @@
# Arduino classes
## How do I make a class?
First you need to start out with a header file. This file will contain the class definition. And which functions of the class are public and which are private.
```cpp
#ifndef DISPLAYTEXT_H
#define DISPLAYTEXT_H
#include "Adafruit_GFX.h"
#include "Adafruit_ST7796S_kbv.h"
class DisplayText {
private:
Adafruit_ST7796S_kbv& tft;
int centerText(char* text);
int bottomText(char* text);
void printWordsFull(char* text);
public:
DisplayText(Adafruit_ST7796S_kbv& tftDisplay);
void writeText(char* text, int size, int posX, int posY, int screenTime, bool center, bool bottom);
};
#endif
```
```#ifndef``` DISPLAYTEXT_H is a preprocessor directive that checks if DISPLAYTEXT_H is defined. If it is not defined, the code between #ifndef and #endif will be included in the compilation. If it is defined, the code will be excluded from the compilation. This is to prevent the same code from being included multiple times in the same file.
To start out with a class you need a constructor. This is a function that is called when the class is created. This function is used to initialize the class.
```cpp
DisplayText::DisplayText(Adafruit_ST7796S_kbv& tftDisplay) : tft(tftDisplay) {
tft.fillScreen(0x0000);
}
```
The library gets passed to tftdisplay. And the tft gets initialized with the tftdisplay.
## How do I create a function in a class?
```cpp
void DisplayText::centerText() {
//insert code here
}
```
This is a example of a function in a class. The function is called centerText and it is a private function. This means that it can only be called from within the class.
When creating a class you also need to reference it in the header file like this
```cpp
#include "DisplayText.h"
class DisplayText {
private:
int centerText();
//other functions
public:
//other functions
};
```
# Sources
* https://www.circuitbasics.com/programming-with-classes-and-objects-on-the-arduino/

View File

@@ -2,15 +2,17 @@
### parsing JSON
The data that is send by the nodes is send in json data. We chose this becouse we can easily use the data within javascript, this is called parsing. We use the parced data and send that in to the next function to make the data more acceseble to use in further instences.
```js
const jsonData = JSON.parse(event.data);
// Use the parsed JSON data as needed
handleIncomingData(jsonData);
```
### Pro
Here is the function that receves the parced JSON data and set it into variables. So that it can be more easlily used in the next function with is the processNodeData, witch is setting the data in to the right array.
```js
function handleIncomingData(data) {
nodeNumber = data.node;
temperature = data.Temp;
@@ -20,13 +22,20 @@ function handleIncomingData(data) {
processNodeData(nodeNumber, temperature, humidity, CO2, TVOC);
}
```
function processNodeData(nodeNumber, temperature, humidity, CO2, TVOC) {
In the function processNodeData we first check if there is a array for the node that is sending the data, this is done becouse if we want to seperate the data in to show witch node is sending what data. So if the nodeNumber plus sensorData (the name of the array) not already there the array is made.
```js
// Initialize the array for this node if it doesn't exist yet
if (!sensorData[nodeNumber]) {
sensorData[nodeNumber] = [];
}
```
For the actual data put in to array function is there a simple array.push for the data that is send allong from when the function is called.
```js
// Push the new data onto the array for this node
sensorData[nodeNumber].push({
'node': nodeNumber,
@@ -35,106 +44,22 @@ function processNodeData(nodeNumber, temperature, humidity, CO2, TVOC) {
'CO2': CO2,
'TVOC': TVOC,
});
```
// updateNodeData(node, temperature, humidity, lightIntensity)
updateNodeData(nodeNumber, temperature, humidity, CO2, TVOC);
// Log the array for this node
console.log(sensorData[nodeNumber]);
We want only use the last 10 readings from the nodes so there is a check for if the array is longer than 10 the first (or the oldest reading), if that is so there is a .shift executed. This is done to be later used in the graph function. Than there is a call for the next function, that is the updateNodeData and that will acctually find the right html id coresponding with the right reading to update that.
```js
// If the array for this node has more than 10 elements, remove the oldest one
if (sensorData[nodeNumber].length >= 10) {
sensorData[nodeNumber].shift();
}
}
function createNodeData(node) {
// Create main div
var nodeData = document.createElement("div");
nodeData.className = "nodeData";
updateNodeData(nodeNumber, temperature, humidity, CO2, TVOC);
```
// Create flex-NodeData div
var flexNodeData = document.createElement("div");
flexNodeData.clsName = "flex-NodeData";
// Create p element
var pNode = document.createElement("p");
pNode.textContent = "Node " + node;
// Append p to flex-NodeData
flexNodeData.appendChild(pNode);
// Create flex-LiveData div
var flexLiveData = document.createElement("div");
flexLiveData.className = "flex-LiveData";
// Create data divs (Temperature, Humidity, Light Intensity)
var dataTypes = ["Temperatuur", "Luchtvochtigheid", "CO2", "TVOC"];
var ids = ["temperature", "humidity", "CO2", "TVOC"];
var statusIds = ["tempStatus", "humidStatus", "CO2Status", "TVOCStatus"];
for (var i = 0; i < dataTypes.length; i++) {
var dataDiv = document.createElement("div");
var dataTypeDiv = document.createElement("div");
dataTypeDiv.textContent = dataTypes[i] + ": ";
var pElement = document.createElement("p");
pElement.id = ids[i] + node;
pElement.textContent = "Not connected";
dataTypeDiv.appendChild(pElement);
dataDiv.appendChild(dataTypeDiv);
var statusElement = document.createElement("div");
statusElement.className = "statusElement";
var statusText = document.createElement("p");
statusText.className = "statusText";
statusText.id = statusIds[i];
statusText.textContent = "Not connected";
statusElement.appendChild(statusText);
dataDiv.appendChild(statusElement);
flexLiveData.appendChild(dataDiv);
}
// Append flex-LiveData to flex-NodeData
flexNodeData.appendChild(flexLiveData);
// Create flex-graph div
var flexGraph = document.createElement("div");
flexGraph.className = "flex-graph";
var graphDiv = document.createElement("div");
var graphP = document.createElement("p");
graphP.textContent = "Live graph:";
var liveGraph = document.createElement("div");
liveGraph.id = "liveGraph";
graphDiv.appendChild(graphP);
graphDiv.appendChild(liveGraph);
flexGraph.appendChild(graphDiv);
// Append flex-graph to flex-NodeData
flexNodeData.appendChild(flexGraph);
// Append flex-NodeData to main div
nodeData.appendChild(flexNodeData);
// Check if nodeDataLocation element exists
var nodeDataLocation = document.getElementById("nodeDataLocation");
if (nodeDataLocation) {
// Append main div to nodeDataLocation
nodeDataLocation.appendChild(nodeData);
} else {
console.error("Element with ID 'nodeDataLocation' does not exist.");
}
}
In the last function there are 2 updates the first is to actually update the text to the right value that we are getting from the node, and the connection checker.
```js
function updateNodeData(node, temperature, humidity, eCO2, TVOC) {
// Update the temperature, humidity and light intensity values
document.getElementById("temperature" + node).textContent = temperature;
@@ -148,4 +73,4 @@ function updateNodeData(node, temperature, humidity, eCO2, TVOC) {
document.getElementById("CO2Status").textContent = "Connected";
document.getElementById("TVOCStatus").textContent = "Connected";
}
```

View File

@@ -0,0 +1,56 @@
# Graphs
## Introduction
The graphs are used to display the data from the sensors. The data is collected by the raspberry pi and then displayed on the graphs. The graphs are made using the [plotly library](https://plotly.com/javascript/) .
## Requirements
### Live graphs
- Every node has to have a live graph
- The graphs has to be updated every 5 seconds
- All the data from one node has to fit in one graph
## Class diagrams
### Live graphs
```mermaid
classDiagram
class liveGraph {
+nodeId
+cnt
+timeArray
+tempArray
+humiArray
+eco2Array
+tvocArray
makeGraph()
updateGraph()
updateData()
}
```
## Order of operations
### Live graphs
```mermaid
sequenceDiagram
participant Node
participant Raspberry pi
participant Website
Node->>Raspberry pi: sensordata via websocket every 5 seconds
Raspberry pi->>Website: Node data via websocket if new data is received from the node
Website->>Website: updateGraph()
Website->>Website: updateData()
```
1. Every node sends its data to the raspberry pi via websocket every 5 seconds
2. The raspberry pi sends the data to the website via websocket if new data is received from the node
3. The website updates the data coming from the raspberry pi on its own variables and arrays
4. The website updates the live graphs every time new data is received from the websocket

120
server/DatabasewithMAC.sql Normal file
View File

@@ -0,0 +1,120 @@
-- MySQL Script generated by MySQL Workbench
-- Fri Mar 8 12:25:17 2024
-- Model: New Model Version: 1.0
-- MySQL Workbench Forward Engineering
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
-- -----------------------------------------------------
-- Schema NodeData
-- -----------------------------------------------------
-- -----------------------------------------------------
-- Schema NodeData
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `NodeData` DEFAULT CHARACTER SET utf8 ;
USE `NodeData` ;
-- -----------------------------------------------------
-- Table `NodeData`.`Question`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `NodeData`.`Question` (
`QuestionID` INT NOT NULL,
`Question` VARCHAR(45) NULL,
PRIMARY KEY (`QuestionID`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `NodeData`.`Node`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `NodeData`.`Node` (
`NodeID` INT NOT NULL,
`Name` VARCHAR(45) NULL,
`Location` VARCHAR(45) NULL,
`MAC` VARCHAR(45) NULL,
PRIMARY KEY (`NodeID`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `NodeData`.`Measurement`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `NodeData`.`Measurement` (
`NodeID` INT NOT NULL,
`Type` VARCHAR(45) NULL,
`Value` FLOAT NULL,
`TimeStamp` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`Node_NodeID` INT NOT NULL,
PRIMARY KEY (`NodeID`, `Node_NodeID`),
INDEX `fk_Measurement_Node1_idx` (`Node_NodeID` ASC) VISIBLE,
CONSTRAINT `fk_Measurement_Node1`
FOREIGN KEY (`Node_NodeID`)
REFERENCES `NodeData`.`Node` (`NodeID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `NodeData`.`Enquete`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `NodeData`.`Enquete` (
`EnqueteID` INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`EnqueteID`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `NodeData`.`enqueteQuestion`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `NodeData`.`enqueteQuestion` (
`Enquete_EnqueteID` INT NOT NULL,
`Question_QuestionID` INT NOT NULL,
PRIMARY KEY (`Enquete_EnqueteID`, `Question_QuestionID`),
INDEX `fk_Enquete_has_Question_Question1_idx` (`Question_QuestionID` ASC) VISIBLE,
INDEX `fk_Enquete_has_Question_Enquete1_idx` (`Enquete_EnqueteID` ASC) VISIBLE,
CONSTRAINT `fk_Enquete_has_Question_Enquete1`
FOREIGN KEY (`Enquete_EnqueteID`)
REFERENCES `NodeData`.`Enquete` (`EnqueteID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_Enquete_has_Question_Question1`
FOREIGN KEY (`Question_QuestionID`)
REFERENCES `NodeData`.`Question` (`QuestionID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `NodeData`.`Reply`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `NodeData`.`Reply` (
`Node_NodeID` INT NOT NULL,
`enqueteQuestion_Enquete_EnqueteID` INT NOT NULL,
`enqueteQuestion_Question_QuestionID` INT NOT NULL,
`Result` INT NULL,
`Time` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
`AnswerID` INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`AnswerID`, `Node_NodeID`, `enqueteQuestion_Enquete_EnqueteID`, `enqueteQuestion_Question_QuestionID`),
INDEX `fk_Node_has_enqueteQuestion_enqueteQuestion1_idx` (`enqueteQuestion_Enquete_EnqueteID` ASC, `enqueteQuestion_Question_QuestionID` ASC) VISIBLE,
INDEX `fk_Node_has_enqueteQuestion_Node1_idx` (`Node_NodeID` ASC) VISIBLE,
CONSTRAINT `fk_Node_has_enqueteQuestion_Node1`
FOREIGN KEY (`Node_NodeID`)
REFERENCES `NodeData`.`Node` (`NodeID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_Node_has_enqueteQuestion_enqueteQuestion1`
FOREIGN KEY (`enqueteQuestion_Enquete_EnqueteID` , `enqueteQuestion_Question_QuestionID`)
REFERENCES `NodeData`.`enqueteQuestion` (`Enquete_EnqueteID` , `Question_QuestionID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;

View File

@@ -1,21 +1,34 @@
import websockets;
import asyncio;
import websockets
import asyncio
connected = set()
async def handler(websocket):
while True:
#Save the incoming message in variable message.
message = await websocket.recv()
print(message)
# Register.
connected.add(websocket)
try:
while True:
message = await websocket.recv()
print(message)
await broadcast(message)
except websockets.ConnectionClosedOK:
print("Client disconnected")
finally:
connected.remove(websocket)
async def broadcast(message):
if connected: # asyncio.wait doesn't accept an empty list
await asyncio.wait([ws.send(message) for ws in connected])
async def sendClientId():
if connected: # asyncio.wait doesn't accept an empty list
await asyncio.wait([ws.send(message) for ws in connected])
async def main():
async with websockets.serve(handler, "145.92.8.114" , 8001):
async with websockets.serve(handler, "0.0.0.0", 8001):
await asyncio.Future() # run forever
if __name__ == "__main__":
asyncio.run(main())
asyncio.run(main())
#https://websockets.readthedocs.io/en/stable/reference/sync/server.html#websockets.sync.server.serve

View File

@@ -9,9 +9,9 @@ class liveGraph {
this.cnt = 0;
this.nodeId = "liveGraph" + id;
}
// Fuction to create a graph
makeGraph() {
// Create a new line for temperature
Plotly.plot(this.nodeId, [
{
x: this.timeArray, // Use timeArray as x values
@@ -21,6 +21,7 @@ class liveGraph {
name: "Temperature",
},
]);
// Create a new line for humidity
Plotly.plot(this.nodeId, [
{
x: this.timeArray, // Use timeArray as x values
@@ -30,6 +31,7 @@ class liveGraph {
name: "Humidity",
},
]);
// Create a new line for eCO2
Plotly.plot(this.nodeId, [
{
x: this.timeArray, // Use timeArray as x values
@@ -39,6 +41,7 @@ class liveGraph {
name: "eCO2 / 10",
},
]);
// Create a new line for TVOC
Plotly.plot(this.nodeId, [
{
x: this.timeArray, // Use timeArray as x values
@@ -50,7 +53,7 @@ class liveGraph {
]);
}
// Function to update the graph with new values
// Function to update the graph with new values got from updateData function
updateGraph() {
let time = new Date();
this.timeArray.push(new Date());
@@ -71,7 +74,7 @@ class liveGraph {
Plotly.relayout(this.nodeId, minuteView);
if (this.cnt === 10) clearInterval(interval);
}
// function to get the new data for graph
updateData(temperature, humidity, eCO2, TVOC) {
// Update the graph
this.tempArray.push(temperature);

View File

@@ -1,13 +1,17 @@
// Description: Main JavaScript file for the web application.
// arrays and stuff
const sensorData = {};
let intervalDelay = 1000;
// Create WebSocket connection.
const socket = new WebSocket("ws://145.92.8.114/ws");
let liveGraphs = [];
// letiables
let intervalDelay = 5000;
let amountOfNodes = 3;
const socket = new WebSocket("ws://145.92.8.114/ws");
function openConnection() {
// Open connection
socket.addEventListener("open", (event) => {
console.log("Connected to the WebSocket server");
socket.send("Hello Server!");
});
// Error handling
@@ -35,14 +39,11 @@ function openConnection() {
// Attempt to reconnect
setTimeout(openConnection, 1000); // Retry after 1 second
});
console.log("Connected to the WebSocket server!!!!!!!!");
console.log("Connected to the WebSocket server");
}
// Open the connection
openConnection();
function handleIncomingData(data) {
nodeNumber = data.node;
temperature = data.Temp;
@@ -80,16 +81,7 @@ function processNodeData(nodeNumber, temperature, humidity, CO2, TVOC) {
}
}
function pushArray(array) {
for (let i = 0; i < 10; i++) {
array.push(Math.random() * 10);
}
}
//function for making the html elements for the following html code
function nodeData(data, node) {
let nodeData = document.createElement("div");
nodeData.innerHTML = data;
@@ -100,46 +92,46 @@ function nodeData(data, node) {
function createNodeData(node) {
// Create main div
var nodeData = document.createElement("div");
let nodeData = document.createElement("div");
nodeData.className = "nodeData";
// Create flex-NodeData div
var flexNodeData = document.createElement("div");
let flexNodeData = document.createElement("div");
flexNodeData.className = "flex-NodeData";
// Create p element
var pNode = document.createElement("p");
let pNode = document.createElement("p");
pNode.textContent = "Node " + node;
// Append p to flex-NodeData
flexNodeData.appendChild(pNode);
// Create flex-LiveData div
var flexLiveData = document.createElement("div");
let flexLiveData = document.createElement("div");
flexLiveData.className = "flex-LiveData";
// Create data divs (Temperature, Humidity, Light Intensity)
var dataTypes = ["Temperatuur", "Luchtvochtigheid", "CO2", "TVOC"];
var ids = ["temperature", "humidity", "CO2", "TVOC"];
var statusIds = ["tempStatus", "humidStatus", "CO2Status", "TVOCStatus"];
let dataTypes = ["Temperatuur", "Luchtvochtigheid", "CO2", "TVOC"];
let ids = ["temperature", "humidity", "CO2", "TVOC"];
let statusIds = ["tempStatus", "humidStatus", "CO2Status", "TVOCStatus"];
for (var i = 0; i < dataTypes.length; i++) {
var dataDiv = document.createElement("div");
for (let i = 0; i < dataTypes.length; i++) {
let dataDiv = document.createElement("div");
var dataTypeDiv = document.createElement("div");
let dataTypeDiv = document.createElement("div");
dataTypeDiv.textContent = dataTypes[i] + ": ";
var pElement = document.createElement("p");
let pElement = document.createElement("p");
pElement.id = ids[i] + node;
pElement.textContent = "Not connected";
dataTypeDiv.appendChild(pElement);
dataDiv.appendChild(dataTypeDiv);
var statusElement = document.createElement("div");
let statusElement = document.createElement("div");
statusElement.className = "statusElement";
var statusText = document.createElement("p");
let statusText = document.createElement("p");
statusText.className = "statusText";
statusText.id = statusIds[i];
statusText.textContent = "Not connected";
@@ -154,15 +146,15 @@ function createNodeData(node) {
flexNodeData.appendChild(flexLiveData);
// Create flex-graph div
var flexGraph = document.createElement("div");
let flexGraph = document.createElement("div");
flexGraph.className = "flex-graph";
var graphDiv = document.createElement("div");
let graphDiv = document.createElement("div");
var graphP = document.createElement("p");
let graphP = document.createElement("p");
graphP.textContent = "Live graph:";
var liveGraph = document.createElement("div");
let liveGraph = document.createElement("div");
liveGraph.id = "liveGraph" + node;
graphDiv.appendChild(graphP);
@@ -176,7 +168,7 @@ function createNodeData(node) {
nodeData.appendChild(flexNodeData);
// Check if nodeDataLocation element exists
var nodeDataLocation = document.getElementById("nodeDataLocation");
let nodeDataLocation = document.getElementById("nodeDataLocation");
if (nodeDataLocation) {
// Append main div to nodeDataLocation
nodeDataLocation.appendChild(nodeData);
@@ -198,23 +190,18 @@ function updateNodeData(node, temperature, humidity, eCO2, TVOC) {
document.getElementById("CO2Status").textContent = "Connected";
document.getElementById("TVOCStatus").textContent = "Connected";
// Update the graph`
graphNode1.updateData(temperature, humidity, eCO2, TVOC);
graphNode1.updateGraph();
// Update the graph
liveGraphs[node - 1].updateData(temperature, humidity, eCO2, TVOC);
liveGraphs[node - 1].updateGraph();
}
// Call the function to create the HTML structure
createNodeData(1);
createNodeData(2);
createNodeData(3);
createNodeData(4);
for (let i = 1; i <= amountOfNodes; i++) {
createNodeData(i);
liveGraphs.push(new liveGraph(i));
}
// Create a new liveGraph object
let graphNode1 = new liveGraph(1);
graphNode1.makeGraph();
let graphNode2 = new liveGraph(2);
graphNode2.makeGraph();
// openConnection();
// make the graphs
liveGraphs.forEach((graph) => {
graph.makeGraph();
});

View File

@@ -33,11 +33,6 @@ p1 {
text-align: begin;
}
.apiGraph{
height: 100%;
width: 90%;
}
.statusElement{
display:inline-block;
border: solid #1f82d3 2px;
@@ -50,35 +45,6 @@ p1 {
font-size: 20px;
}
/* body{
display: flex;
flex-direction: row;
justify-content: space-evenly;
align-content: center;
} */
#randomShit{
display: flex;
flex-direction: row;
justify-content: space-evenly;
align-content: center;
border: 2px solid purple;
}
#nodeDataLocation{
display: flex;
flex-direction: column;
align-items: center;
/* justify-content: center; */
/* align-content: center; */
border: 4px solid blue;
/* padding-bottom: 50%; */
}
.flex-NodeData {
display: flex;
margin-left: 1%;
@@ -87,21 +53,33 @@ p1 {
/* height: 40%; */
flex-direction: column;
border: 3px solid #1f82d3;
/* border-radius: 20px; */
border-radius: 20px;
/* width: 90%; */
/* border: 2px solid red; */
/* margin-right: 90%; */
/* width: 150vh; */
/* padding-right: 40%; */
/* padding-left: 40%; */
}
#nodeDataLocation{
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
align-content: center;
border: 4px solid rgb(0, 0, 255);
/* padding-bottom: 50%; */
}
.nodeData {
display: flex;
justify-content: left;
flex-direction: row;
margin-bottom: 2%;
margin-top: 1%;
/* border: 2px solid red; */
}
@@ -113,8 +91,6 @@ justify-content: left;
justify-content: space-evenly;
gap: 5px;
padding: 10px;
}