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:
54
arduino/node-code/headerFile.h
Normal file
54
arduino/node-code/headerFile.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef headerFile_h
|
||||
#define headerFile_h
|
||||
|
||||
// include these libraries
|
||||
#include <Wire.h>
|
||||
// #include <Adafruit_SH110X.h>
|
||||
// #include <Adafruit_SGP30.h>
|
||||
// #include "DHT.h"
|
||||
#include <WiFiMulti.h>
|
||||
#include <WiFi.h>
|
||||
// #include <WebSocketsClient.h>
|
||||
// #include <nodeCodeHeader.h>
|
||||
// #include <websockets.h>
|
||||
|
||||
// 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 OLED_RESET -1 // QT-PY / XIAO
|
||||
|
||||
|
||||
#define USE_SERIAL Serial
|
||||
|
||||
// make new objects
|
||||
// Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
|
||||
// Adafruit_SH110X display = Adafruit_SH110X(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
|
||||
// Adafruit_SH110X display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
|
||||
// Adafruit_SH1106G display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
|
||||
// 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;
|
||||
#endif
|
@@ -1,42 +0,0 @@
|
||||
// include these libraries
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_SH110X.h>
|
||||
#include <Adafruit_SGP30.h>
|
||||
#include <DHT.h>
|
||||
#include <WiFiMulti.h>
|
||||
#include <WiFi.h>
|
||||
#include <WebSocketsClient.h>
|
||||
#include <nodeCodeHeader.h>
|
||||
|
||||
// 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 OLED_RESET -1 // QT-PY / XIAO
|
||||
#define USE_SERIAL Serial
|
||||
|
||||
// make new objects
|
||||
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
|
||||
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;
|
@@ -1,17 +0,0 @@
|
||||
#include <nodeCodeHeader.h>
|
||||
|
||||
nodeReadings esp32Node();
|
||||
|
||||
void setup()
|
||||
{
|
||||
// put your setup code here, to run once:
|
||||
esp32Node.setup();
|
||||
esp32Node.websocketSetup();
|
||||
esp32Node.resetValues();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// put your main code here, to run repeatedly:
|
||||
esp32Node.loop();
|
||||
}
|
@@ -1,63 +0,0 @@
|
||||
#include "arduino.h"
|
||||
#include "nodeCodeHeader.h"
|
||||
|
||||
nodeReadings::nodeReadings() {
|
||||
}
|
||||
|
||||
void nodeReadings::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);
|
||||
|
||||
}
|
||||
|
||||
void nodeReadings::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();
|
||||
}
|
||||
|
||||
void nodeReadings::resetValues() {
|
||||
counter = 0;
|
||||
eCO2 = 0;
|
||||
TVOC = 0;
|
||||
temperature = 0;
|
||||
humidity = 0;
|
||||
currentMillis = 0;
|
||||
lastMillis = 0;
|
||||
errorSGP30 = false;
|
||||
errorDHT11 = false;
|
||||
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");
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
#ifndef nodeReading_h
|
||||
#define nodeReading_h
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "headerFile.h"
|
||||
|
||||
|
||||
class nodeReadings {
|
||||
|
||||
public:
|
||||
nodeReadings();
|
||||
void setup();
|
||||
void loop();
|
||||
void resetValues();
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
13
arduino/node-code/nodeCodeFinal/nodeCodeFinal.ino
Normal file
13
arduino/node-code/nodeCodeFinal/nodeCodeFinal.ino
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <nodeCodeHeader.h>
|
||||
#include "websockets.h"
|
||||
nodeReadings esp32Node;
|
||||
|
||||
|
||||
void setup() {
|
||||
esp32Node.setup();
|
||||
esp32Node.resetValues();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
esp32Node.loop();
|
||||
}
|
115
arduino/node-code/nodeCodeFinal/nodeCodeHeader.cpp
Normal file
115
arduino/node-code/nodeCodeFinal/nodeCodeHeader.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
#include "nodeCodeHeader.h"
|
||||
|
||||
nodeReadings::nodeReadings() {
|
||||
|
||||
//Making all the new object as defined in the .h file
|
||||
dht = new DHT(DHTPIN, DHTTYPE);
|
||||
display = new Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
|
||||
webSocket = new websockets();
|
||||
sgp = new Adafruit_SGP30();
|
||||
|
||||
//setting the reding for every 5 sec
|
||||
interval = 5000;
|
||||
resetValues();
|
||||
|
||||
}
|
||||
|
||||
//Script for simpley reseting every value to 0
|
||||
void nodeReadings::resetValues() {
|
||||
counter = 0;
|
||||
eCO2 = 0;
|
||||
TVOC = 0;
|
||||
temperature = 0;
|
||||
humidity = 0;
|
||||
currentMillis = 0;
|
||||
lastMillis = 0;
|
||||
errorSGP30 = false;
|
||||
errorDHT11 = false;
|
||||
noise = false;
|
||||
}
|
||||
|
||||
//Setup for initilising the dht and sgp sensors. Also the display is set up.
|
||||
void nodeReadings::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);
|
||||
|
||||
webSocket->websocketSetup();
|
||||
|
||||
}
|
||||
|
||||
void nodeReadings::loop() {
|
||||
// update when interval is met
|
||||
if (currentMillis - lastMillis >= interval){
|
||||
lastMillis = millis();
|
||||
update();
|
||||
}
|
||||
|
||||
// update the counter
|
||||
currentMillis = millis();
|
||||
|
||||
// loop the websocket connection so it stays alive
|
||||
webSocket->loop();
|
||||
}
|
||||
|
||||
void nodeReadings::update(){
|
||||
|
||||
// display sensordata on oled screen
|
||||
displayData();
|
||||
|
||||
//send the data to the websockets
|
||||
webSocket->sendMyText("{\"node\": \"" + String(WiFi.macAddress()) + "\", \"Temp\":\"" + String(temperature) + "\",\"Humi\":\"" + String(humidity) + "\",\"eCO2\":\"" + String(sgp->eCO2) + "\",\"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();
|
||||
}
|
||||
|
||||
void nodeReadings::displayData() {
|
||||
// clear display for new info
|
||||
display->clearDisplay();
|
||||
|
||||
// display the data on the oled screen
|
||||
display->setTextSize(2);
|
||||
display->setTextColor(SH110X_WHITE);
|
||||
display->setCursor(0,0);
|
||||
display->println("Temp: " + String(int(temperature)) + "C");
|
||||
display->println("Humi: " + String(int(humidity)) + "%");
|
||||
display->println("eCO2: " + String(sgp->eCO2));// + " ppm");
|
||||
display->println("TVOC: " + String(sgp->TVOC));// + " ppb");
|
||||
display->display();
|
||||
}
|
||||
|
||||
//function
|
||||
void nodeReadings::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;
|
||||
}
|
||||
}
|
55
arduino/node-code/nodeCodeFinal/nodeCodeHeader.h
Normal file
55
arduino/node-code/nodeCodeFinal/nodeCodeHeader.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef nodeReading_h
|
||||
#define nodeReading_h
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_SH110X.h>
|
||||
#include <DHT.h>
|
||||
#include <Adafruit_SGP30.h>
|
||||
#include "websockets.h"
|
||||
|
||||
// define pins on esp32
|
||||
#define MICPIN 6
|
||||
#define DHTPIN 7
|
||||
#define SCL 9
|
||||
#define SDA 8
|
||||
#define DHTTYPE DHT22
|
||||
#define SCREEN_WIDTH 128
|
||||
#define SCREEN_HEIGHT 64
|
||||
#define i2c_adress 0x3c
|
||||
#define OLED_RESET -1 // QT-PY / XIAO
|
||||
|
||||
#define USE_SERIAL Serial
|
||||
|
||||
class nodeReadings
|
||||
{
|
||||
|
||||
public:
|
||||
nodeReadings();
|
||||
void setup();
|
||||
void loop();
|
||||
void resetValues();
|
||||
void update();
|
||||
void checkForError();
|
||||
void displayData();
|
||||
|
||||
private:
|
||||
DHT *dht;
|
||||
Adafruit_SH1106G *display;
|
||||
websockets *webSocket;
|
||||
Adafruit_SGP30 *sgp;
|
||||
|
||||
uint16_t TVOC_base, eCO2_base;
|
||||
uint16_t counter;
|
||||
uint16_t eCO2;
|
||||
uint16_t TVOC;
|
||||
uint16_t interval;
|
||||
float temperature;
|
||||
float humidity;
|
||||
unsigned long currentMillis;
|
||||
unsigned long lastMillis;
|
||||
bool errorSGP30;
|
||||
bool errorDHT11;
|
||||
bool noise;
|
||||
};
|
||||
|
||||
#endif
|
81
arduino/node-code/nodeCodeFinal/websockets.cpp
Normal file
81
arduino/node-code/nodeCodeFinal/websockets.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#include "websockets.h"
|
||||
|
||||
websockets::websockets(){
|
||||
webSocket = new WebSocketsClient();
|
||||
_WiFiMulti = new WiFiMulti();
|
||||
}
|
||||
|
||||
// hexdump function for websockets binary handler
|
||||
void websockets::hexdump(const void *mem, uint32_t len, uint8_t cols) {
|
||||
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");
|
||||
}
|
||||
|
||||
// special function to setup websocket
|
||||
void websockets::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");
|
||||
|
||||
// try ever 500 again if connection has failed
|
||||
webSocket->setReconnectInterval(500);
|
||||
}
|
||||
|
||||
void websockets::loop(){
|
||||
webSocket->loop();
|
||||
}
|
||||
|
||||
// handler for websocket events
|
||||
void websockets::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("{\"message\": \"Connected\"}");
|
||||
break;
|
||||
case WStype_TEXT:
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
void websockets::sendMyText(String message) {
|
||||
|
||||
webSocket->sendTXT(message);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
25
arduino/node-code/nodeCodeFinal/websockets.h
Normal file
25
arduino/node-code/nodeCodeFinal/websockets.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef websockets_h
|
||||
#define websockets_h
|
||||
|
||||
#include <WiFiMulti.h>
|
||||
#include <WiFi.h>
|
||||
#include <WebSocketsClient.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
#define USE_SERIAL Serial
|
||||
|
||||
class websockets {
|
||||
public:
|
||||
websockets();
|
||||
void hexdump(const void *mem, uint32_t len, uint8_t cols = 16);
|
||||
void websocketSetup();
|
||||
void loop();
|
||||
void webSocketEvent(WStype_t type, uint8_t * payload, size_t length);
|
||||
void sendMyText(String message);
|
||||
|
||||
private:
|
||||
WebSocketsClient *webSocket;
|
||||
WiFiMulti *_WiFiMulti;
|
||||
};
|
||||
|
||||
#endif
|
@@ -26,7 +26,8 @@ nav:
|
||||
- Database design: brainstorm/Database
|
||||
- Feedback: brainstorm/Feedback
|
||||
- Problem: brainstorm/Problem
|
||||
- Infrastructure: brainstorm/UML-infrastructureV2
|
||||
- InfrastructureUml: brainstorm/UML-infrastructure
|
||||
- Infrascructure: brainstorm/infrasturcture
|
||||
- Taskflow: brainstorm/Taskflow
|
||||
- Design: Sp1SchetsProject/FirstDesign
|
||||
- Interview facility manager: brainstorm/gebouwBeheer
|
||||
|
8
docs/Sprint2/sprint2Review.md
Normal file
8
docs/Sprint2/sprint2Review.md
Normal file
@@ -0,0 +1,8 @@
|
||||
## Wie doet wat:
|
||||
|
||||
dano laat website zien, ik laat het dynamisch toevoegen van nodes zien, en een kleine uitleg waarom dit zo belangrijk is. Bram laat dan zien dat alle data in de database komt door een python script. Sam laat dan het fysieke model zien van het feedback scherm. Sietse laat de userstories zien. Dan laat dano de volgende documentatie zien:
|
||||
|
||||
- OOP - class grafiek
|
||||
- Infrastructuur - UML
|
||||
- Gebruikerstest - feedback scherm vragen
|
||||
- embedded ontwerpen en maken - tft screen van sam
|
BIN
docs/assets/funcionalInfra.png
Normal file
BIN
docs/assets/funcionalInfra.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 63 KiB |
BIN
docs/assets/technicalInfra.png
Normal file
BIN
docs/assets/technicalInfra.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
120
docs/brainstorm/SoftwareDocumentatie/classes-website.md
Normal file
120
docs/brainstorm/SoftwareDocumentatie/classes-website.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# Nodes
|
||||
|
||||
## Introduction
|
||||
|
||||
The nodes are the devices that are placed in the rooms. The nodes are used to collect the data from the sensors. Every node is connected to the websocket, and sends their data with their mac address in json format. The websocket broadcasts the node data back to all clients, and since our website functions as a client it also receives the data. Every node will, depending on what node, be made into a class.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Sensornode
|
||||
|
||||
- Every node has to have a unique nodeID
|
||||
- Every node has to have their corresponding sensorsvalues in form of arrays
|
||||
|
||||
### Feedbacknodes
|
||||
|
||||
- Every node has to have a unique nodeID
|
||||
- Every node has to have their corresponding feedback in form of a 2D array
|
||||
|
||||
## Class diagrams
|
||||
|
||||
### Node
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
|
||||
Node <-- SensorNode : extends
|
||||
Node <-- FeedbackNode : extends
|
||||
|
||||
class Node {
|
||||
+nodeID
|
||||
+processNodeData()
|
||||
+updateNodeData()
|
||||
}
|
||||
|
||||
class SensorNode {
|
||||
+tempArray
|
||||
+humiArray
|
||||
+eco2Array
|
||||
+tvocArray
|
||||
}
|
||||
|
||||
class FeedbackNode {
|
||||
+feedbackArray
|
||||
}
|
||||
```
|
||||
|
||||
# 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
|
||||
|
||||
### Graphs
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
|
||||
liveGraph --> graph: extends
|
||||
class graph {
|
||||
+nodeId
|
||||
makeGraph()
|
||||
}
|
||||
|
||||
class liveGraph {
|
||||
+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
|
||||
|
||||
### Node
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Node
|
||||
participant Raspberry pi
|
||||
participant Website
|
||||
|
||||
Node->>Raspberry pi: node data via websocket every 5 seconds
|
||||
Raspberry pi->>Website: Make a new object depending on what node it is
|
||||
Website->>Website: updateNodeData()
|
||||
Website->>Website: processNodeData()
|
||||
```
|
23
docs/brainstorm/infrasturcture.md
Normal file
23
docs/brainstorm/infrasturcture.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# The infrastructure
|
||||
|
||||
###
|
||||
|
||||
## Three layers
|
||||
|
||||
###
|
||||
|
||||
### functional
|
||||
|
||||
In the top layer of the infrastructure documentation, we are showing the functional flows of the information trafic between the user and the sensor/enquete that are located in the same room. The traffic consists of enviromental sensor values like temperature, humidity etc. Also it is showing the user input at the enquete device to the database that is hosted at the brain of the operation.
|
||||
|
||||

|
||||
|
||||
### Technical
|
||||
|
||||
In the middel layer we are showing the data flow and processing of the data at component level. It consists of 2 area's with 3 parts, namelie the server room and the building as in the common area. Here we send the data in JSON form that is collected at the enquete node (this is the feedback data) and the sensor node (this is the environmental data). This is sent to the database through the websocket that is running on the raspberry pi and than via a rest api sent to the database. If one of the operational manager would log in to the website. They would see the incomming sensor node data that is comming through, but also the data that is already collected and stored in the database.
|
||||
|
||||

|
||||
|
||||
### UML diagram of software
|
||||
|
||||
At the lowest level of our system we are showing how the software is designed. This is shown as a UML diagram. The diagram is made with mermaid. This shows the work flow of the different parts of the software which is running on the main server, for which we are using a Raspberry pi. The pi is located on the 6th floor of the school building in a locked server room.
|
@@ -1,7 +1,47 @@
|
||||
class liveGraph {
|
||||
class node {
|
||||
// Constructor to initialize the node
|
||||
constructor(nodeId) {
|
||||
this.nodeId = nodeId;
|
||||
this.temperature = 0;
|
||||
this.humidity = 0;
|
||||
this.eCO2 = 0;
|
||||
this.TVOC = 0;
|
||||
this.connected = false;
|
||||
}
|
||||
// Function to update the data
|
||||
updateData(temperature, humidity, eCO2, TVOC) {
|
||||
this.temperature = temperature;
|
||||
this.humidity = humidity;
|
||||
this.eCO2 = eCO2;
|
||||
this.TVOC = TVOC;
|
||||
}
|
||||
// Function to update the connection status
|
||||
updateConnection() {
|
||||
if (connectedNodes[this.nodeId]) {
|
||||
this.connected = true;
|
||||
} else {
|
||||
this.connected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class feedbackNode extends node {
|
||||
// Constructor to initialize the feedback node
|
||||
constructor(nodeId) {
|
||||
super(nodeId);
|
||||
this.feedback = {};
|
||||
this.answers = 0;
|
||||
}
|
||||
// Function to update the feedback
|
||||
updateFeedback(feedback) {
|
||||
this.feedback = feedback;
|
||||
}
|
||||
}
|
||||
|
||||
class liveGraph extends graph {
|
||||
// Constructor to initialize the graph
|
||||
constructor(id) {
|
||||
this.timeArray = [];
|
||||
super(id);
|
||||
this.tempArray = [];
|
||||
this.humiArray = [];
|
||||
this.eco2Array = [];
|
||||
@@ -60,7 +100,12 @@ class liveGraph {
|
||||
|
||||
let update = {
|
||||
x: [[this.timeArray]],
|
||||
y: [[this.tempArray], [this.humiArray], [this.eco2Array], [this.tvocArray]]
|
||||
y: [
|
||||
[this.tempArray],
|
||||
[this.humiArray],
|
||||
[this.eco2Array],
|
||||
[this.tvocArray],
|
||||
],
|
||||
};
|
||||
|
||||
let olderTime = time.setMinutes(time.getMinutes() - 1);
|
||||
@@ -82,4 +127,46 @@ class liveGraph {
|
||||
this.eco2Array.push(eCO2 / 10);
|
||||
this.tvocArray.push(TVOC / 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class graph {
|
||||
// Constructor to initialize the graph
|
||||
constructor(id) {
|
||||
this.nodeId = "graph" + id;
|
||||
this.timeArray = [];
|
||||
}
|
||||
// Function to create a graph
|
||||
makeGraph(amountOfGraphs, array1, array2, array3, array4) {
|
||||
for (let i = 0; i < amountOfGraphs; i++) {
|
||||
// Create a new line for temperature
|
||||
Plotly.plot(this.nodeId, [
|
||||
{
|
||||
x: this.timeArray, // Use timeArray as x values
|
||||
y: array + i,
|
||||
mode: "lines",
|
||||
line: { color: "#FF0000" },
|
||||
name: "Temperature",
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
// Function to update the graph with new values got from updateData function
|
||||
updateGraph(array1, array2, array3, array4) {
|
||||
let time = new Date();
|
||||
this.timeArray.push(new Date());
|
||||
|
||||
let update = {
|
||||
x: [[this.timeArray]],
|
||||
y: [array1, array2, array3, array4],
|
||||
};
|
||||
|
||||
let olderTime = time.setMinutes(time.getMinutes() - 1);
|
||||
let futureTime = time.setMinutes(time.getMinutes() + 1);
|
||||
let minuteView = {
|
||||
xaxis: {
|
||||
type: "date",
|
||||
range: [olderTime, futureTime],
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
45
web/main.js
45
web/main.js
@@ -5,10 +5,6 @@ let liveGraphs = [];
|
||||
let nodeArray = [];
|
||||
let nodeDict = {};
|
||||
|
||||
// letiables
|
||||
let intervalDelay = 5000;
|
||||
let amountOfNodes = 3;
|
||||
|
||||
const socket = new WebSocket("ws://145.92.8.114/ws");
|
||||
function openConnection() {
|
||||
// Open connection
|
||||
@@ -29,6 +25,7 @@ function openConnection() {
|
||||
const jsonData = JSON.parse(event.data);
|
||||
// Use the parsed JSON data as needed
|
||||
handleIncomingData(jsonData);
|
||||
console.log(jsonData);
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error parsing JSON:", error);
|
||||
@@ -47,24 +44,36 @@ function openConnection() {
|
||||
openConnection();
|
||||
|
||||
function handleIncomingData(data) {
|
||||
nodeAdressHandler(data.Node);
|
||||
|
||||
nodeNumber = nodeDict[data.Node];
|
||||
if (!data.message) {
|
||||
nodeEventHandler(data.node);
|
||||
nodeNumber = nodeDict[data.node];
|
||||
temperature = data.Temp;
|
||||
humidity = data.Humi;
|
||||
CO2 = data.eCO2;
|
||||
TVOC = data.TVOC;
|
||||
|
||||
updateNodeData(nodeNumber, temperature, humidity, CO2, TVOC);
|
||||
}
|
||||
}
|
||||
|
||||
function nodeAdressHandler(node) {
|
||||
function nodeEventHandler(node) {
|
||||
if (!nodeArray.includes(node)) {
|
||||
nodeArray.push(node);
|
||||
nodeDict[node] = nodeArray.length;
|
||||
|
||||
makeLiveGraph(nodeArray.length);
|
||||
}
|
||||
}
|
||||
|
||||
function makeLiveGraph(node) {
|
||||
createNodeData(node);
|
||||
liveGraphs.push(new liveGraph(node));
|
||||
|
||||
console.log("Node " + node + " added to the liveGraphs array");
|
||||
|
||||
liveGraphs[node - 1].makeGraph();
|
||||
}
|
||||
|
||||
//function for making the html elements for the following html code
|
||||
function nodeData(data, node) {
|
||||
let nodeData = document.createElement("div");
|
||||
@@ -175,20 +184,6 @@ function updateNodeData(node, temperature, humidity, eCO2, TVOC) {
|
||||
document.getElementById("TVOCStatus").textContent = "Connected";
|
||||
|
||||
// Update the graph
|
||||
liveGraphs[0].updateData(temperature, humidity, eCO2, TVOC);
|
||||
liveGraphs[0].updateGraph();
|
||||
|
||||
console.log(nodeDict[node]);
|
||||
console.log(nodeArray);
|
||||
}
|
||||
|
||||
// Call the function to create the HTML structure
|
||||
for (let i = 1; i <= amountOfNodes; i++) {
|
||||
createNodeData(i);
|
||||
liveGraphs.push(new liveGraph(i));
|
||||
}
|
||||
|
||||
// make the graphs
|
||||
liveGraphs.forEach((graph) => {
|
||||
graph.makeGraph();
|
||||
});
|
||||
liveGraphs[node - 1].updateData(temperature, humidity, eCO2, TVOC);
|
||||
liveGraphs[node - 1].updateGraph();
|
||||
}
|
Reference in New Issue
Block a user