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

This commit is contained in:
sietse jonker
2024-03-29 15:19:20 +01:00
10 changed files with 180 additions and 53 deletions

BIN
docs/assets/Node.fzz Normal file

Binary file not shown.

BIN
docs/assets/Node.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

View File

@@ -62,3 +62,28 @@ A[Design Sketch] -->|Usertest| B(Fusion360 design)
B -->|Not fitting| C[New fusion360 design]
C -->|assembly| D[Finished product]
```
## The evolved design of the nodes.
During the last sprint we had a lot of feeback about the node and mostly about tis design. hence why we had decided to remake it in several different ways.
We had made a prototype for a wooden version, but that never made it past an first sketch, seeing as almost all fedback came back telling About how the plastic design looked better and was less distreacting.
The user-test document is here:( https://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-3/qaajeeqiinii59/-/blob/main/docs/brainstorm/Feedback.md?ref_type=heads#design-questions-led-by-bram )
After the results came back, we decided to make progress with further designing the cover of the node.
The main body shape was certain, because all of the components needed to fit inside of the node and needed some space.
Aswell as the simple shape to save on printing costs and keep the design simple to look at.
The only thing that was able to change was the cover.
The cover was originally made of solid plastic and was molded to fit the shape of the board and the sensors/ screen inside.
From here we decided to brainstorm on an easyer way of covering the circurty.
That is when it hit us, We could use acrylic as a cover!
Acrylic can come in many different colors, is easyer to cut out ( takes less time) and gives a bit of an isight into the wiring.
This this in mind we made a node with this new design and remade one with the old design, this again could be further used for user-tests.
For the time being we are able to show off both of the designs and are able to read data from both, the only difference being the outer shell.
The images:

View File

@@ -19,20 +19,23 @@ The node is programmed using the Arduino IDE. The code is written in C++ and is
The following libraries are used in the node code:
- <Wire.h>
- <Adafruit_SH110X.h
- <Adafruit_SGP30.h>
- <DHT.h>
- <WiFiMulti.h>
- <WiFi.h>
- <WebSocketsClient.>
- <nodeCodeHeader.h>
- Wire.h
- Adafruit_SH110X.h
- Adafruit_SGP30.h
- DHT.h
- WiFiMulti.h
- WiFi.h
- WebSocketsClient.h
- nodeCodeHeader.h
### Code
The code is divided into the following classes:
uitleg dano
- Node readings
- Websockets
The two classes that are used are split into the 2 becouse the node readings handels everything about reading information from the sensors and displaying them on the screen, all the local stuff is handeled here so to speak. And into Websockets this handels every thing from connecting to the wifi to sending the data that is recorded from the sensors into json format and sending that data to the websockets so that the data can be prossed over there.
### Communication
@@ -63,6 +66,13 @@ The wiring diagram for the node is as follows:
![Wiring diagram of node](docs\assets\imagesSp3\wiringDiagramNode.png)
### Fritsing Diagram
![fritsing diagram of node](docs\assets\Node.fzz)
![fritsing diagram of node](.\assets\Node.png)
## Future Improvements
The node is currently working as intended, but there are some improvements that could be made:

View File

@@ -24,6 +24,7 @@ class GaugeGroup {
</div>
</div>
`).join('')}
<div id="graph${nodeId}></div>
</div>
`;

BIN
web/newWebsite/arrow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -28,8 +28,10 @@
<body>
<script src="main.js"></script>
<script src="GaugGroup.js"></script>
<script src="graph-classes.js"></script>
<script src="main.js"></script>
<script src="liveGraph.js"></script>
</body>
</html>

View File

@@ -0,0 +1,85 @@
class liveGraph {
// Constructor to initialize the graph
constructor(id) {
this.timeArray = [];
this.tempArray = [];
this.humiArray = [];
this.eco2Array = [];
this.tvocArray = [];
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
y: this.tempArray,
mode: "lines",
line: { color: "#FF0000" },
name: "Temperature",
},
]);
// Create a new line for humidity
Plotly.plot(this.nodeId, [
{
x: this.timeArray, // Use timeArray as x values
y: this.humiArray,
mode: "lines",
line: { color: "#80CAF6" },
name: "Humidity",
},
]);
// Create a new line for eCO2
Plotly.plot(this.nodeId, [
{
x: this.timeArray, // Use timeArray as x values
y: this.eco2Array,
mode: "lines",
line: { color: "#FFA500" },
name: "eCO2 / 10",
},
]);
// Create a new line for TVOC
Plotly.plot(this.nodeId, [
{
x: this.timeArray, // Use timeArray as x values
y: this.tvocArray,
mode: "lines",
line: { color: "#000000" },
name: "TVOC / 10",
},
]);
}
// Function to update the graph with new values got from updateData function
updateGraph() {
let time = new Date();
this.timeArray.push(new Date());
let update = {
x: [[this.timeArray]],
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 = {
xaxis: {
type: "date",
range: [olderTime, futureTime],
},
};
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);
this.humiArray.push(humidity);
this.eco2Array.push(eCO2 / 10);
this.tvocArray.push(TVOC / 10);
}
}

View File

@@ -4,7 +4,7 @@ const sensorData = {};
let liveGraphs = [];
let nodeArray = [];
let nodeDict = {};
let graphArray = [];
// letiables
let intervalDelay = 5000;
let amountOfNodes = 3;
@@ -54,18 +54,18 @@ async function handleIncomingData(data) {
await nodeAdressHandler(data.node, Object.keys(data).filter(key => key !== 'node'));
let nodeName = nodeDict[data.node];
let nodeName = nodeDict[data.node].name;
let temperature = data.Temp;
let humidity = data.Humi;
let CO2 = data.eCO2;
let TVOC = data.TVOC;
// Update the gauges with the new data
if (sensorData[nodeName]) {
sensorData[nodeName].updateGauge(1, temperature);
sensorData[nodeName].updateGauge(2, humidity);
sensorData[nodeName].updateGauge(3, CO2);
sensorData[nodeName].updateGauge(4, TVOC);
if (sensorData[data.node]) {
sensorData[data.node].updateGauge(1, temperature);
sensorData[data.node].updateGauge(2, humidity);
sensorData[data.node].updateGauge(3, CO2);
sensorData[data.node].updateGauge(4, TVOC);
} else {
console.error('No sensor data for node:', nodeName);
}
@@ -73,11 +73,18 @@ async function handleIncomingData(data) {
async function nodeAdressHandler(node, dataTypes) {
let nodeInfo = await getNodeInfo(node);
if (!nodeInfo) {
console.error('No node info found for node:', node);
return;
}
let nodeName = nodeInfo.name;
let nodeLocation = nodeInfo.location;
if (!nodeArray.includes(nodeName)) {
nodeArray.push(nodeName);
nodeDict[node] = nodeName;
if (!nodeArray.includes(node)) {
nodeArray.push(node);
nodeDict[node] = {name: nodeName, location: nodeLocation};
let maxGaugeValues = dataTypes.map(dataType => {
switch (dataType) {
@@ -90,40 +97,27 @@ async function nodeAdressHandler(node, dataTypes) {
});
let gaugeGroup = new GaugeGroup(nodeName, nodeLocation, dataTypes.length, maxGaugeValues, dataTypes);
sensorData[nodeName] = gaugeGroup;
sensorData[node] = gaugeGroup;
}
}
function createGauge(node, dataType) {
// Create a new gauge here
let gauge = new GaugeGroup(node, dataType); // Assuming Gauge is the name of the class
sensorData[node][dataType] = gauge; // Store the gauge in the sensorData object for later use
}
//function for making the html elements for the following html code
function nodeData(data) {
let nodeData = document.createElement("div");
nodeData.innerHTML = data;
// nodeData.setAttribute("id", "node" + node);
document.body.appendChild(nodeData);
// console.log("Hello World");
}
function updateGauge(nodeNumber, dataType, value) {
// Update the gauge here
let gauge = sensorData[nodeNumber][dataType]; // Get the gauge from the sensorData object
gauge.update(value); // Assuming the Gauge class has an update method
}
function getNodeInfo(node){
return fetch("http://145.92.8.114/getNodeInfo?macAdress=" + node)
.then(response => response.json())
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
if (data.length == 0) {
throw new Error('No data returned for node: ' + node);
}
return {
name: data[0].Name,
location: data[0].Location // Assuming the server returns a Location property
};
});
})
}

View File

@@ -63,7 +63,7 @@ body {
border-radius: 10px;
text-align: center;
position: relative;
padding-bottom: 6vh; /* Increase bottom padding */
padding-top: 3vh; /* Increase bottom padding */
}
@@ -82,7 +82,7 @@ body {
.gaugeImage {
width: 100%;
height: auto;
max-height: 200%;
max-height: 120%;
object-fit: contain;
position: absolute; /* Make the image position absolute */
top: 0;
@@ -105,10 +105,20 @@ body {
font-size: 1.4vw;
z-index: 2;
position: absolute;
bottom: -3.2vw; /* Adjust this value to move the text further down */
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;
@@ -122,10 +132,10 @@ body {
.needle {
position: absolute;
bottom: -40%; /* Lower the needle to the bottom */
bottom: -10%; /* Lower the needle to the bottom */
left: 50%;
width: 2px;
height: 110%;
height: 100%;
background-color: black;
transform-origin: bottom;
z-index: 3; /* Make the needle display above the image */