diff --git a/arduino/node-code/node-code-final.ino b/arduino/node-code/node-code-final.ino deleted file mode 100644 index 475d905..0000000 --- a/arduino/node-code/node-code-final.ino +++ /dev/null @@ -1,224 +0,0 @@ -// Sietse Jonker & Dano Bosch -// 27/02/2024 - -// include these libraries -#include -#include -#include -#include -#include -#include -#include - -// define pins on esp32 -#define MICPIN 6 -#define DHTPIN 7 -#define SCL 9 -#define SDA 8 -#define DHTTYPE DHT11 -#define SCREEN_WIDTH 128 -#define SCREEN_HEIGHT 64 -#define i2c_adress 0x3c -#define USE_SERIAL Serial - -// make new objects -Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire); -DHT dht(DHTPIN, DHTTYPE); -WiFiMulti WiFiMulti; -Adafruit_SGP30 sgp; -WebSocketsClient webSocket; - -// define variables -uint16_t TVOC_base, eCO2_base; -uint16_t counter = 0; -uint16_t eCO2 = 0; -uint16_t TVOC = 0; -uint16_t interval = 5000; -float temperature = 0; -float humidity = 0; -unsigned long currentMillis; -unsigned long lastMillis; -bool errorSGP30 = false; -bool errorDHT11 = false; -bool noise = false; - -// hexdump function for websockets binary handler -void hexdump(const void *mem, uint32_t len, uint8_t cols = 16) { - const uint8_t* src = (const uint8_t*) mem; - USE_SERIAL.printf("\n[HEXDUMP] Address: 0x%08X len: 0x%X (%d)", (ptrdiff_t)src, len, len); - for(uint32_t i = 0; i < len; i++) { - if(i % cols == 0) { - USE_SERIAL.printf("\n[0x%08X] 0x%08X: ", (ptrdiff_t)src, i); - } - USE_SERIAL.printf("%02X ", *src); - src++; - } - USE_SERIAL.printf("\n"); -} - -// handler for websocket events -void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { - switch(type) { - case WStype_DISCONNECTED: - USE_SERIAL.printf("[WSc] Disconnected!\n"); - break; - case WStype_CONNECTED: - USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload); - - // send message to server when Connected - webSocket.sendTXT("Connected"); - break; - case WStype_TEXT: - USE_SERIAL.printf("[WSc] get text: %s\n", payload); - - // send message to server - // webSocket.sendTXT("message here"); - break; - case WStype_BIN: - USE_SERIAL.printf("[WSc] get binary length: %u\n", length); - hexdump(payload, length); - - // send data to server - // webSocket.sendBIN(payload, length); - break; - case WStype_ERROR: - case WStype_FRAGMENT_TEXT_START: - case WStype_FRAGMENT_BIN_START: - case WStype_FRAGMENT: - case WStype_FRAGMENT_FIN: - break; - } -} - -// special function to setup websocket -void websocketSetup(){ - WiFiMulti.addAP("iotroam", "vbK9gbDBIB"); - WiFiMulti.addAP("LansanKPN-boven", "19sander71vlieland14"); - - while(WiFiMulti.run() != WL_CONNECTED) { - delay(100); - } - - // server address, port and URL - webSocket.begin("145.92.8.114", 80, "/ws"); - - // event handler - webSocket.onEvent(webSocketEvent); - - // try ever 500 again if connection has failed - webSocket.setReconnectInterval(500); -} - -// fucntion to reset the values if needed -void resetValues() { - TVOC_base; - eCO2_base; - counter = 0; - temperature = 0; - humidity = 0; - eCO2 = 0; - TVOC = 0; - noise = false; - lastMillis = 0; - currentMillis = 0; -} - -// function to check for errors in sensors -bool checkForError(){ - if (!sgp.IAQmeasure()) { - Serial.println("SGP30: BAD"); - errorSGP30 = true; - } else { - Serial.println("SGP30: OK"); - errorSGP30 = false; - } - - if (isnan(temperature) || isnan(humidity)){ - Serial.println("DHT11: BAD"); - errorDHT11 = true; - } else { - Serial.println("DHT11: OK"); - errorDHT11 = false; - } - - return false; -} - -// function to update when interval is met (see intervalCounter variable) -void update(){ - // display sensordata on oled screen - displayData(); - - // send data to websocket server - webSocket.sendTXT("Temp: " + String(temperature)); - webSocket.sendTXT("Humi: " + String(humidity)); - webSocket.sendTXT("eCO2: " + String(sgp.eCO2)); - webSocket.sendTXT("TVOC: " + String(sgp.TVOC)); - - sgp.getIAQBaseline(&eCO2_base, &TVOC_base); - - // read dht11 sensor - temperature = float(dht.readTemperature()); - humidity = float(dht.readHumidity()); - - // check if any errors occured when reading sensors - checkForError(); -} - -// function to display data on oled screen -void displayData() { - // clear display for new info - display.clearDisplay(); - - // set custom text properties - display.setTextSize(2); - display.setTextColor(SH110X_WHITE); - display.setCursor(0, 0); - - // display info on oled screen - display.println((String) "Temp: " + int(temperature) + "C" + '\n' - + "Humi: " + int(humidity) + "%" + '\n' - + "eCO2: " + int(sgp.eCO2) + '\n' - + "TVOC: " + int(sgp.TVOC)); - - // display the screen - display.display(); -} - -// setup function -void setup() { - // make serial connection at 115200 baud - Serial.begin(115200); - - // tell display what settings to use - display.begin(i2c_adress, true); - display.clearDisplay(); - - // tell sensors to start reading - dht.begin(); - sgp.begin(); - - pinMode(MICPIN, INPUT); - pinMode(DHTPIN, INPUT); - - // setup websocket connection - websocketSetup(); - - // reset values - resetValues(); -} - -// loop function -void loop() { - // loop the websocket connection so it stays alive - webSocket.loop(); - - // update when interval is met - if (currentMillis - lastMillis >= interval){ - lastMillis = millis(); - update(); - } - - // update the counter - currentMillis = millis(); -} \ No newline at end of file diff --git a/arduino/node-code/node-code-final/node-code-final.ino b/arduino/node-code/node-code-final/node-code-final.ino index 1229b9d..cb78a60 100644 --- a/arduino/node-code/node-code-final/node-code-final.ino +++ b/arduino/node-code/node-code-final/node-code-final.ino @@ -161,6 +161,7 @@ void update(){ temperature = float(dht.readTemperature()); humidity = float(dht.readHumidity()); + // check if any errors occured when reading sensors checkForError(); } @@ -179,12 +180,14 @@ void displayData() { + "Humi: " + int(humidity) + "%" + '\n' + "eCO2: " + int(sgp.eCO2) + '\n' + "TVOC: " + int(sgp.TVOC)); - + + // display the screen display.display(); } // setup function void setup() { + // make serial connection at 115200 baud Serial.begin(115200); // tell display what settings to use diff --git a/docs/.pages b/docs/.pages index 5ab6dc5..3ae2722 100644 --- a/docs/.pages +++ b/docs/.pages @@ -23,4 +23,6 @@ nav: - Infrastructure: brainstorm/UML-infrastructure - Taskflow: brainstorm/Taskflow - Design: Sp1SchetsProject/FirstDesign + - 🖨️ Software: + - Dev page: brainstrom/SotwareDocumentatie/Dev_page \ No newline at end of file diff --git a/docs/brainstorm/SoftwareDocumentatie/Dev_page.md b/docs/brainstorm/SoftwareDocumentatie/Dev_page.md new file mode 100644 index 0000000..138990e --- /dev/null +++ b/docs/brainstorm/SoftwareDocumentatie/Dev_page.md @@ -0,0 +1,151 @@ + + +### parsing JSON + +```js + const jsonData = JSON.parse(event.data); + // Use the parsed JSON data as needed + handleIncomingData(jsonData); +``` + +### Pro + + +function handleIncomingData(data) { + nodeNumber = data.node; + temperature = data.Temp; + humidity = data.Humi; + CO2 = data.eCO2; + TVOC = data.TVOC; + + processNodeData(nodeNumber, temperature, humidity, CO2, TVOC); +} + +function processNodeData(nodeNumber, temperature, humidity, CO2, TVOC) { + // Initialize the array for this node if it doesn't exist yet + if (!sensorData[nodeNumber]) { + sensorData[nodeNumber] = []; + } + + // Push the new data onto the array for this node + sensorData[nodeNumber].push({ + 'node': nodeNumber, + 'temp': temperature, + 'humi': humidity, + '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]); + + // 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"; + + // 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."); + } +} + +function updateNodeData(node, temperature, humidity, eCO2, TVOC) { + // Update the temperature, humidity and light intensity values + document.getElementById("temperature" + node).textContent = temperature; + document.getElementById("humidity" + node).textContent = humidity; + document.getElementById("CO2" + node).textContent = eCO2; + document.getElementById("TVOC" + node).textContent = TVOC; + + // Update the status text + document.getElementById("tempStatus").textContent = "Connected"; + document.getElementById("humidStatus").textContent = "Connected"; + document.getElementById("CO2Status").textContent = "Connected"; + document.getElementById("TVOCStatus").textContent = "Connected"; +} + diff --git a/web/classes.js b/web/classes.js index be77e3f..bea7d93 100644 --- a/web/classes.js +++ b/web/classes.js @@ -1,24 +1,51 @@ -let intervalDelay = 5000; -let newData = true; - class liveGraph { // Constructor to initialize the graph constructor(id) { - this.timeArray = [4, 5, 6, 7, 9]; - this.valueArray = [1, 3, 4, 8, 10]; - this.cnt = 0; - this.nodeId = id; + this.timeArray = []; + this.tempArray = []; + this.humiArray = []; + this.eco2Array = []; + this.tvocArray = []; + this.cnt = 0; + this.nodeId = "liveGraph" + id; } // Fuction to create a graph makeGraph() { - Plotly.plot("liveGraph", [ + Plotly.plot(this.nodeId, [ { x: this.timeArray, // Use timeArray as x values - y: this.valueArray, + y: this.tempArray, + mode: "lines", + line: { color: "#FF0000" }, + name: "Temperature", + }, + ]); + Plotly.plot(this.nodeId, [ + { + x: this.timeArray, // Use timeArray as x values + y: this.humiArray, mode: "lines", line: { color: "#80CAF6" }, - name: "Temperature", + name: "Humidity", + }, + ]); + Plotly.plot(this.nodeId, [ + { + x: this.timeArray, // Use timeArray as x values + y: this.eco2Array, + mode: "lines", + line: { color: "#FFA500" }, + name: "eCO2 / 10", + }, + ]); + Plotly.plot(this.nodeId, [ + { + x: this.timeArray, // Use timeArray as x values + y: this.tvocArray, + mode: "lines", + line: { color: "#000000" }, + name: "TVOC / 10", }, ]); } @@ -27,11 +54,12 @@ class liveGraph { updateGraph() { let time = new Date(); this.timeArray.push(new Date()); - this.valueArray.push(Math.random()); + let update = { x: [[this.timeArray]], - y: [[this.valueArray]], + y: [[this.tempArray], [this.humiArray], [this.eco2Array], [this.tvocArray]] }; + let olderTime = time.setMinutes(time.getMinutes() - 1); let futureTime = time.setMinutes(time.getMinutes() + 1); let minuteView = { @@ -40,17 +68,15 @@ class liveGraph { range: [olderTime, futureTime], }, }; - Plotly.relayout("liveGraph", minuteView); + Plotly.relayout(this.nodeId, minuteView); if (this.cnt === 10) clearInterval(interval); } -} -let graph1 = new liveGraph(1); - -graph1.makeGraph(); - -let interval = setInterval(function () { - if (newData) { - graph1.updateGraph(); + updateData(temperature, humidity, eCO2, TVOC) { + // Update the graph + this.tempArray.push(temperature); + this.humiArray.push(humidity); + this.eco2Array.push(eCO2 / 10); + this.tvocArray.push(TVOC / 10); } -}, intervalDelay); \ No newline at end of file +} \ No newline at end of file diff --git a/web/index.html b/web/index.html index ecf1faf..36d76b3 100644 --- a/web/index.html +++ b/web/index.html @@ -1,12 +1,13 @@ + Node dev page - + @@ -16,63 +17,18 @@ - -
- -
-

Node 1

-
-
-
Temperatuur:

Not connected

-
-
-

Not connected

-
+
-
-
Luchtvochtigheid:

Not connected

-
-
-

Not connected

-
-
-
-
Lichtintensiteit:

Not connected

-
-
-

Not connected

-
-
-
- - - -
-
-

Live graph:

-
-
-
-
-
- -
-
-

Live graph:

-
-
-
-
- - - + + + - + \ No newline at end of file diff --git a/web/main.js b/web/main.js index e69de29..db1c2e3 100644 --- a/web/main.js +++ b/web/main.js @@ -0,0 +1,220 @@ +const sensorData = {}; +let intervalDelay = 1000; +// Create WebSocket connection. +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 + socket.addEventListener('error', (event) => { + console.error('WebSocket error:', event); + // Attempt to reconnect + setTimeout(openConnection, 1000); // Retry after 1 second + }); + + // Message handling + socket.addEventListener("message", (event) => { + try { + const jsonData = JSON.parse(event.data); + // Use the parsed JSON data as needed + handleIncomingData(jsonData); + + } catch (error) { + console.error("Error parsing JSON:", error); + } + }); + + // Close handling + socket.addEventListener('close', (event) => { + console.log('Connection closed'); + // Attempt to reconnect + setTimeout(openConnection, 1000); // Retry after 1 second + }); + console.log("Connected to the WebSocket server!!!!!!!!"); +} + +// Open the connection +openConnection(); + + + +function handleIncomingData(data) { + nodeNumber = data.node; + temperature = data.Temp; + humidity = data.Humi; + CO2 = data.eCO2; + TVOC = data.TVOC; + + processNodeData(nodeNumber, temperature, humidity, CO2, TVOC); +} + +function processNodeData(nodeNumber, temperature, humidity, CO2, TVOC) { + // Initialize the array for this node if it doesn't exist yet + if (!sensorData[nodeNumber]) { + sensorData[nodeNumber] = []; + } + + // Push the new data onto the array for this node + sensorData[nodeNumber].push({ + 'node': nodeNumber, + 'temp': temperature, + 'humi': humidity, + '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]); + + // If the array for this node has more than 10 elements, remove the oldest one + if (sensorData[nodeNumber].length >= 10) { + sensorData[nodeNumber].shift(); + } +} + + + +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; + // nodeData.setAttribute("id", "node" + node); + document.body.appendChild(nodeData); + // console.log("Hello World"); +} + +function createNodeData(node) { + // Create main div + var nodeData = document.createElement("div"); + nodeData.className = "nodeData"; + + // Create flex-NodeData div + var flexNodeData = document.createElement("div"); + flexNodeData.className = "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" + node; + + 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."); + } +} + +function updateNodeData(node, temperature, humidity, eCO2, TVOC) { + // Update the temperature, humidity and light intensity values + document.getElementById("temperature" + node).textContent = temperature; + document.getElementById("humidity" + node).textContent = humidity; + document.getElementById("CO2" + node).textContent = eCO2; + document.getElementById("TVOC" + node).textContent = TVOC; + + // Update the status text + document.getElementById("tempStatus").textContent = "Connected"; + document.getElementById("humidStatus").textContent = "Connected"; + document.getElementById("CO2Status").textContent = "Connected"; + document.getElementById("TVOCStatus").textContent = "Connected"; + + // Update the graph` + graphNode1.updateData(temperature, humidity, eCO2, TVOC); + graphNode1.updateGraph(); +} + +// Call the function to create the HTML structure +createNodeData(1); +createNodeData(2); +createNodeData(3); +createNodeData(4); + +// Create a new liveGraph object +let graphNode1 = new liveGraph(1); + +graphNode1.makeGraph(); + +let graphNode2 = new liveGraph(2); + +graphNode2.makeGraph(); +// openConnection(); diff --git a/web/styles.css b/web/styles.css index 9adefe6..42e9256 100644 --- a/web/styles.css +++ b/web/styles.css @@ -43,21 +43,56 @@ p1 { border: solid #1f82d3 2px; border-radius: 10px; width: 90%; + } .statusText{ 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%; margin-right: 1%; - width: 100%; - height: 40%; + justify-content: space-evenly; + /* height: 40%; */ flex-direction: column; border: 3px solid #1f82d3; - border-radius: 20px; + /* border-radius: 20px; */ + /* border: 2px solid red; */ + /* margin-right: 90%; */ + /* width: 150vh; */ + /* padding-right: 40%; */ + /* padding-left: 40%; */ } .nodeData { @@ -78,6 +113,8 @@ justify-content: left; justify-content: space-evenly; gap: 5px; padding: 10px; + + } @@ -89,6 +126,8 @@ justify-content: left; border-radius: 10px; height: fit-content; width: 30%; + + } .flex-graph {