Compare commits
98 Commits
5193580d13
...
2504d4fbcc
| Author | SHA1 | Date | |
|---|---|---|---|
| 2504d4fbcc | |||
| 77c8039af6 | |||
|
|
7013b69e03 | ||
|
|
7d0a2bf2f8 | ||
|
|
ff93fa9af2 | ||
|
|
49b0a66cb4 | ||
|
|
5d58ac6cf0 | ||
|
|
7aea48ad67 | ||
|
|
6df64fd3a0 | ||
|
|
70e5633ce6 | ||
|
|
02ca9e7f58 | ||
|
|
f1562764f1 | ||
|
|
b45fca728f | ||
|
|
f599cb95d8 | ||
|
|
59ffdbbc22 | ||
|
|
bc383b28ad | ||
|
|
b97f611acd | ||
|
|
ed55bbd673 | ||
|
|
13cf7198ea | ||
|
|
f36dae570b | ||
|
|
a60f14853f | ||
|
|
be5250c413 | ||
|
|
d0337a74d4 | ||
|
|
c2dd64c6e9 | ||
|
|
cd77bceec1 | ||
|
|
4957c1d300 | ||
|
|
a3b1566ef4 | ||
|
|
e3c737ef1d | ||
|
|
f10739a927 | ||
|
|
3d66669d49 | ||
|
|
49f8316e04 | ||
|
|
3ba1aa864d | ||
|
|
275d64585e | ||
|
|
534d0daeff | ||
|
|
7ffe1bed6c | ||
|
|
281d201b52 | ||
|
|
4b3d6ea7cc | ||
|
|
380764d1a6 | ||
|
|
925f73469b | ||
|
|
af6c0ba971 | ||
|
|
e75c4ad40c | ||
|
|
8e31537b57 | ||
|
|
23a235931d | ||
|
|
0a8db9a840 | ||
|
|
44750a12a2 | ||
|
|
6b8c3846c1 | ||
|
|
a73fa98a5c | ||
|
|
1606296400 | ||
|
|
12b1bba6a3 | ||
|
|
78bf985a29 | ||
|
|
a7d1ed2df7 | ||
|
|
152ccd551a | ||
|
|
0031bbe808 | ||
|
|
1470010fbc | ||
|
|
e596a6c60d | ||
|
|
2d24fa154c | ||
|
|
14b7a1a48b | ||
|
|
0e2aab49d7 | ||
|
|
9dd2c37627 | ||
|
|
78bc64cc59 | ||
|
|
4074647094 | ||
|
|
6c81ff08f9 | ||
|
|
2ab2ca4769 | ||
|
|
e077fc61c2 | ||
|
|
928429b75d | ||
|
|
04af341917 | ||
|
|
5f9c61dbca | ||
|
|
0e7305c739 | ||
|
|
fc76dc14a3 | ||
|
|
f28973f46c | ||
|
|
58bb6d6ef6 | ||
|
|
d9f740df36 | ||
|
|
ef18410631 | ||
|
|
e1e79af4e2 | ||
|
|
cc0e375767 | ||
|
|
5bf1b7ad28 | ||
|
|
6ecabb9e6d | ||
|
|
aa42a03508 | ||
|
|
96bf2cda69 | ||
|
|
c824379d90 | ||
|
|
15f8849480 | ||
|
|
74e01fcd66 | ||
|
|
0b83802ce8 | ||
|
|
dd89be3c2f | ||
|
|
f9d18f21b3 | ||
|
|
f345726e0c | ||
|
|
a8028b0483 | ||
|
|
37748727c7 | ||
|
|
81302d8587 | ||
|
|
471413a6c9 | ||
|
|
5e64d16661 | ||
|
|
1eeb156191 | ||
|
|
27d97e1586 | ||
|
|
e264d3a1c2 | ||
|
|
5bb5543157 | ||
|
|
5f6c95d017 | ||
|
|
3fb7a42587 | ||
|
|
079a27ad2c |
19
.gitignore
vendored
Normal file
19
.gitignore
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
node_modules/
|
||||
__pycache__/
|
||||
venv/
|
||||
.vscode/
|
||||
|
||||
*.pyc
|
||||
*.pyo
|
||||
.cache/
|
||||
.pytest_cache/
|
||||
.mypy_cache/
|
||||
.ruff_cache/
|
||||
.parcel-cache/
|
||||
.next/
|
||||
.nuxt/
|
||||
.turbo/
|
||||
coverage/
|
||||
dist-cache/
|
||||
.sass-cache/
|
||||
.pnpm-store/
|
||||
13
.hintrc
Normal file
13
.hintrc
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": [
|
||||
"development"
|
||||
],
|
||||
"hints": {
|
||||
"axe/text-alternatives": [
|
||||
"default",
|
||||
{
|
||||
"image-alt": "off"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
56
ReadMe.md
Normal file
56
ReadMe.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# GoodGarden
|
||||
|
||||
Welkom bij ons project genaamd "GoodGarden". Wij hebben besloten om er een semi-monolithic project van te maken. Alles is te vinden binnen deze repository, inclusief de "mqtt" publisher.
|
||||
|
||||
### Vereisten
|
||||
|
||||
* Python
|
||||
* Node.Js
|
||||
* XAMPP (of andere naar keuze)
|
||||
* MQTT Geinstalleerd en toegevoegd aan je PATH variable
|
||||
|
||||
### Installeren
|
||||
|
||||
Zorg dat je in de hoofdmap "GoodGarden" zit. Kijk in je path: "../GoodGarden". Als je in de correcte map zit moet je de volgende items installeren:
|
||||
|
||||
npm install electron
|
||||
npm install express
|
||||
npm install body-parser
|
||||
npm install python-shell
|
||||
|
||||
npm install --save-dev npm-run-all
|
||||
npm install wait-on --save-dev
|
||||
npm install concurrently --save-dev
|
||||
|
||||
|
||||
pip install mysql-connector-python
|
||||
pip install requests
|
||||
pip install flask-cors
|
||||
|
||||
## Gebruik
|
||||
|
||||
- De data wordt gefetched via MQTT, waarnaar het in topics wordt verdeeld en dan kan je met een script op he gewenste onderwerp "subscriben".
|
||||
|
||||
- Op het Dashboard worden de planten getoond die aanwezig zijn in de database. Je kan doormiddel een modal de planten invullen die je getoond wilt hebben op het Dashboard. Voor nu moet je dan even het "planten.py" script handmatig uitvoeren. Ook worden de 2 sensoren getoond op het Dashboard en hebben we voor nu een "placeholder" neergezet voor de pomp.
|
||||
|
||||
- Als je op een plant klikt ga je naar de pagina van de plant toe. Die is dynamisch gemaakt, alleen nog niet helemaal ingevuld met data. Er zit een switch-knop in waarmee je kan aangeven of de plant aanwezig is in de kas of niet, ook die werkt helaas niet helemaal naar behoren.
|
||||
|
||||
- Je kan ook op de sensoren klikken die op de homepage staan. Dan ga je door naar de pagina van die desbetreffende sensor. De bedoeling was om hier alle errors en waardes te tonen de we doorkrijgen van de sensoren.
|
||||
|
||||
- Als laatste hebben we een grafiek toegevoegd aan het project die laat zien wat de temperatuur is voor de aankomende 5 dagen. De bedoeling was om voor elke plant een unieke grafiek te maken waar dan data in getoond zou worden.
|
||||
|
||||
## Versiebeheer
|
||||
|
||||
We gebruiken [Github](https://github.com) voor versiebeheer. Voor de beschikbare versies, zie de [GoodGarden](https://github.com/Znooptokkie/GoodGarden).
|
||||
|
||||
## Auteurs
|
||||
|
||||
* **Atilla Oomen** - *Projectleider | Back end Programmeur* - [Znooptokkie](https://github.com/Znooptokkie)
|
||||
|
||||
* **Mohammed Çifçi** - *Back end Programmeur* - [6028570](https://github.com/6028570)
|
||||
|
||||
* **Burak Diker** - *Back end Programmeur* - [6028083](https://github.com/6028083)
|
||||
|
||||
* **Justin Doekhi** - *Front end Programmeur* - [6027529](https://github.com/6027529)
|
||||
|
||||
* **Renzo van Putten** - *Front end Programmeur* - [6025850](https://github.com/6025850)
|
||||
177
app.js
Normal file
177
app.js
Normal file
@@ -0,0 +1,177 @@
|
||||
// Importeert de benodigde Electron modules om een desktopapplicatie te creëren.
|
||||
const { app, BrowserWindow, ipcMain } = require("electron");
|
||||
|
||||
// Express framework om een HTTP-server op te zetten.
|
||||
const express = require("express");
|
||||
|
||||
// Body-parser middleware om inkomende request bodies te parsen.
|
||||
const bodyParser = require("body-parser");
|
||||
|
||||
// PythonShell om Python scripts binnen een NodeJS applicatie uit te voeren.
|
||||
const { PythonShell } = require("python-shell");
|
||||
|
||||
// Path module voor het werken met bestandspaden.
|
||||
const path = require("path");
|
||||
|
||||
// Definieert het pad naar de index.html van de Electron app.
|
||||
// const urlElectron = path.join(__dirname, "src/index.html");
|
||||
/*⠀⠀⠀⢸⣦⡀⠀⠀⠀⠀⢀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⢸⣏⠻⣶⣤⡶⢾⡿⠁⠀⢠⣄⡀⢀⣴⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⣀⣼⠷⠀⠀⠁⢀⣿⠃⠀⠀⢀⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠴⣾⣯⣅⣀⠀⠀⠀⠈⢻⣦⡀⠒⠻⠿⣿⡿⠿⠓⠂⠀⠀⢀⡇⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠉⢻⡇⣤⣾⣿⣷⣿⣿⣤⠀⠀⣿⠁⠀⠀⠀⢀⣴⣿⣿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠸⣿⡿⠏⠀⢀⠀⠀⠿⣶⣤⣤⣤⣄⣀⣴⣿⡿⢻⣿⡆⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠟⠁⠀⢀⣼⠀⠀⠀⠹⣿⣟⠿⠿⠿⡿⠋⠀⠘⣿⣇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⢳⣶⣶⣿⣿⣇⣀⠀⠀⠙⣿⣆⠀⠀⠀⠀⠀⠀⠛⠿⣿⣦⣤⣀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⣹⣿⣿⣿⣿⠿⠋⠁⠀⣹⣿⠳⠀⠀⠀⠀⠀⠀⢀⣠⣽⣿⡿⠟⠃
|
||||
⠀⠀⠀⠀⠀⢰⠿⠛⠻⢿⡇⠀⠀⠀⣰⣿⠏⠀⠀⢀⠀⠀⠀⣾⣿⠟⠋⠁⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠀⠀⣰⣿⣿⣾⣿⠿⢿⣷⣀⢀⣿⡇⠁⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠉⠁⠀⠀⠀⠀⠙⢿⣿⣿⠇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀*/
|
||||
// Initialiseert de Express app.
|
||||
const server = express();
|
||||
|
||||
// Configureert de express server om URL-encoded data te accepteren.
|
||||
server.use(bodyParser.urlencoded({ extended: true }));
|
||||
|
||||
// Handler voor het "/submit-form" endpoint. Verwerkt formulierinzendingen.
|
||||
server.post("/submit-form", (req, res) =>
|
||||
{
|
||||
// Extracts form data from the request body.
|
||||
const { plant_naam, plantensoort } = req.body;
|
||||
const plant_geteelt = req.body.plant_geteelt == "true" ? "true" : "false";
|
||||
|
||||
// Configuratieopties voor het uitvoeren van het Python script.
|
||||
let options = {
|
||||
mode: "text",
|
||||
args: [plant_naam, plantensoort, plant_geteelt],
|
||||
};
|
||||
|
||||
// Voert een Python script uit en handelt de response af.
|
||||
PythonShell.run("src/py/script/db_connect_form.py", options, (err, results) =>
|
||||
{
|
||||
if (err)
|
||||
{
|
||||
console.error(err);
|
||||
res.send("Er is een fout opgetreden");
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log("Python script uitvoering resultaten:", results);
|
||||
res.send("Formulier succesvol verwerkt");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Definieert de poort waarop de server luistert.
|
||||
// const PORT = 5000;
|
||||
const PORT = 3000;
|
||||
server.listen(PORT, () =>
|
||||
{
|
||||
console.log(`Server is listening on port ${PORT}`);
|
||||
});
|
||||
/*⠀⠀⠀⢸⣦⡀⠀⠀⠀⠀⢀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⢸⣏⠻⣶⣤⡶⢾⡿⠁⠀⢠⣄⡀⢀⣴⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⣀⣼⠷⠀⠀⠁⢀⣿⠃⠀⠀⢀⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠴⣾⣯⣅⣀⠀⠀⠀⠈⢻⣦⡀⠒⠻⠿⣿⡿⠿⠓⠂⠀⠀⢀⡇⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠉⢻⡇⣤⣾⣿⣷⣿⣿⣤⠀⠀⣿⠁⠀⠀⠀⢀⣴⣿⣿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠸⣿⡿⠏⠀⢀⠀⠀⠿⣶⣤⣤⣤⣄⣀⣴⣿⡿⢻⣿⡆⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠟⠁⠀⢀⣼⠀⠀⠀⠹⣿⣟⠿⠿⠿⡿⠋⠀⠘⣿⣇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⢳⣶⣶⣿⣿⣇⣀⠀⠀⠙⣿⣆⠀⠀⠀⠀⠀⠀⠛⠿⣿⣦⣤⣀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⣹⣿⣿⣿⣿⠿⠋⠁⠀⣹⣿⠳⠀⠀⠀⠀⠀⠀⢀⣠⣽⣿⡿⠟⠃
|
||||
⠀⠀⠀⠀⠀⢰⠿⠛⠻⢿⡇⠀⠀⠀⣰⣿⠏⠀⠀⢀⠀⠀⠀⣾⣿⠟⠋⠁⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠀⠀⣰⣿⣿⣾⣿⠿⢿⣷⣀⢀⣿⡇⠁⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠉⠁⠀⠀⠀⠀⠙⢿⣿⣿⠇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀*/
|
||||
let mainWindow; // Referentie naar het hoofdvenster van de Electron app.
|
||||
|
||||
// Creëert het hoofdvenster van de Electron app.
|
||||
function createWindow()
|
||||
{
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 1280,
|
||||
height: 800,
|
||||
frame: false,
|
||||
icon: path.join(__dirname, "src/py/static/images/logo.png"),
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false,
|
||||
enableRemoteModule: true,
|
||||
webSecurity: true,
|
||||
},
|
||||
});
|
||||
|
||||
mainWindow.loadFile(path.join(__dirname, "src", "py", "templates", "index.html"));
|
||||
|
||||
// Stelt IPC Main Listeners in voor communicatie tussen hoofdproces en renderproces.
|
||||
setupIpcMainListeners();
|
||||
}
|
||||
|
||||
// Wanneer de app klaar is, wordt het hoofdvenster gecreëerd.
|
||||
app.whenReady().then(createWindow);
|
||||
|
||||
// Sluit de app af wanneer alle vensters gesloten zijn (behalve op macOS).
|
||||
app.on("window-all-closed", () =>
|
||||
{
|
||||
if (process.platform !== "darwin")
|
||||
{
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
// Creëert het hoofdvenster opnieuw wanneer het app icoon wordt aangeklikt en er zijn geen vensters open.
|
||||
app.on("activate", () =>
|
||||
{
|
||||
|
||||
if (BrowserWindow.getAllWindows().length === 0)
|
||||
{
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
/*⠀⠀⠀⢸⣦⡀⠀⠀⠀⠀⢀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⢸⣏⠻⣶⣤⡶⢾⡿⠁⠀⢠⣄⡀⢀⣴⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⣀⣼⠷⠀⠀⠁⢀⣿⠃⠀⠀⢀⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠴⣾⣯⣅⣀⠀⠀⠀⠈⢻⣦⡀⠒⠻⠿⣿⡿⠿⠓⠂⠀⠀⢀⡇⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠉⢻⡇⣤⣾⣿⣷⣿⣿⣤⠀⠀⣿⠁⠀⠀⠀⢀⣴⣿⣿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠸⣿⡿⠏⠀⢀⠀⠀⠿⣶⣤⣤⣤⣄⣀⣴⣿⡿⢻⣿⡆⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠟⠁⠀⢀⣼⠀⠀⠀⠹⣿⣟⠿⠿⠿⡿⠋⠀⠘⣿⣇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⢳⣶⣶⣿⣿⣇⣀⠀⠀⠙⣿⣆⠀⠀⠀⠀⠀⠀⠛⠿⣿⣦⣤⣀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⣹⣿⣿⣿⣿⠿⠋⠁⠀⣹⣿⠳⠀⠀⠀⠀⠀⠀⢀⣠⣽⣿⡿⠟⠃
|
||||
⠀⠀⠀⠀⠀⢰⠿⠛⠻⢿⡇⠀⠀⠀⣰⣿⠏⠀⠀⢀⠀⠀⠀⣾⣿⠟⠋⠁⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠀⠀⣰⣿⣿⣾⣿⠿⢿⣷⣀⢀⣿⡇⠁⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠉⠁⠀⠀⠀⠀⠙⢿⣿⣿⠇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀*/
|
||||
// Configureert IPC (Inter-Process Communication) luisteraars.
|
||||
function setupIpcMainListeners()
|
||||
{
|
||||
// IPC luisteraar voor het uitvoeren van een Python script.
|
||||
ipcMain.on("run-python-script", (event, args) =>
|
||||
{
|
||||
let options = {
|
||||
mode: "text",
|
||||
args: args,
|
||||
};
|
||||
// Hier zou je PythonShell.run met deze opties aanroepen.
|
||||
});
|
||||
|
||||
// IPC luisteraar voor het aanvragen van data update.
|
||||
ipcMain.on("request-update-data", (event, args) =>
|
||||
{
|
||||
const databaseData = {
|
||||
timestamp: "2022-01-01",
|
||||
gateway_receive_time: "2022-01-01",
|
||||
device: "Device1",
|
||||
value: 50,
|
||||
};
|
||||
event.reply("update-data-result", { databaseData });
|
||||
});
|
||||
|
||||
// IPC luisteraar voor het bijwerken van HTML data via het renderproces.
|
||||
ipcMain.on("update-html-data", (event, data) =>
|
||||
{
|
||||
mainWindow.webContents.send("update-html-data", data);
|
||||
});
|
||||
}
|
||||
102
app.py
Normal file
102
app.py
Normal file
@@ -0,0 +1,102 @@
|
||||
from flask import Flask, jsonify
|
||||
import mysql.connector
|
||||
import requests
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
def database_connect():
|
||||
try:
|
||||
|
||||
connection = mysql.connector.connect(
|
||||
host="localhost",
|
||||
user="root",
|
||||
password="root",
|
||||
database="goodgarden"
|
||||
)
|
||||
return connection
|
||||
|
||||
except Exception as e:
|
||||
|
||||
print("Database connection failed:", e)
|
||||
#Throw error
|
||||
return None
|
||||
|
||||
# Function to get data from the MySQL database
|
||||
def get_database_data():
|
||||
#Throw error
|
||||
mydb = database_connect()
|
||||
if mydb and mydb.is_connected():
|
||||
|
||||
cursor = mydb.cursor(dictionary=True) # Enable dictionary result
|
||||
|
||||
# Query to retrieve the latest battery voltage data
|
||||
query = "SELECT label, last_seen, last_battery_voltage, device_id FROM devices"
|
||||
cursor.execute(query)
|
||||
battery_data = cursor.fetchall() # Fetch all rows
|
||||
mydb.close()
|
||||
return battery_data
|
||||
|
||||
@app.route('/', methods=['GET'])
|
||||
def get_data():
|
||||
battery_data = get_database_data()
|
||||
|
||||
if battery_data is None or len(battery_data) == 0:
|
||||
|
||||
return jsonify({"error": "Failed to fetch data from database"})
|
||||
|
||||
return jsonify(battery_data) # Directly return the list of dictionaries as JSON
|
||||
|
||||
def get_weather_data():
|
||||
# Api key in a file
|
||||
api_key = "05ddd06644"
|
||||
location = "Leiden"
|
||||
url = f"https://weerlive.nl/api/weerlive_api_v2.php?key={api_key}&locatie={location}"
|
||||
response = requests.get(url).json()
|
||||
return response
|
||||
|
||||
@app.route('/weather', methods=['GET'])
|
||||
def get_weather():
|
||||
weather_response = get_weather_data()
|
||||
|
||||
if 'error' in weather_response:
|
||||
return jsonify({"error": "Kon weerdata niet ophalen"})
|
||||
|
||||
live_weather = weather_response.get('liveweer', [])
|
||||
weather_forecast = weather_response.get('wk_verw', [])
|
||||
day_forecast = weather_response.get('wk_verw', []) # Dagverwachtingen
|
||||
|
||||
weather_data = {
|
||||
"live_weather": live_weather[0] if live_weather else {},
|
||||
"weather_forecast": weather_forecast,
|
||||
"day_forecast": day_forecast # Voeg de dagverwachtingen toe aan de weerdata
|
||||
}
|
||||
|
||||
return jsonify(weather_data)
|
||||
|
||||
def get_planten_data():
|
||||
mydb = database_connect()
|
||||
if mydb and mydb.is_connected():
|
||||
try:
|
||||
cursor = mydb.cursor(dictionary=True)
|
||||
query = "SELECT id, plant_naam, plantensoort, plant_geteelt FROM planten"
|
||||
cursor.execute(query)
|
||||
planten_data = cursor.fetchall()
|
||||
mydb.close()
|
||||
return planten_data
|
||||
except Exception as e:
|
||||
print("Failed to fetch planten data:", e)
|
||||
return {"error": "Kon plantendata niet ophalen"}
|
||||
else:
|
||||
return {"error": "Database connection failed"}
|
||||
|
||||
@app.route("/planten", methods=["GET"])
|
||||
def get_planten():
|
||||
planten_response = get_planten_data()
|
||||
|
||||
if "error" in planten_response:
|
||||
return jsonify(planten_response)
|
||||
|
||||
return jsonify(planten_response)
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(host="127.0.0.1", port=5000)
|
||||
BIN
documentatie/Goodgarden.pptx
Normal file
BIN
documentatie/Goodgarden.pptx
Normal file
Binary file not shown.
BIN
documentatie/Projectdossier_goodgarden.docx
Normal file
BIN
documentatie/Projectdossier_goodgarden.docx
Normal file
Binary file not shown.
@@ -1,16 +0,0 @@
|
||||
DROP DATABASE IF EXISTS goodgarden;
|
||||
CREATE DATABASE goodgarden;
|
||||
|
||||
CREATE TABLE goodgarden.sensor_data (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
timestamp INT,
|
||||
gateway_receive_time VARCHAR(50),
|
||||
device INT,
|
||||
value DECIMAL(10, 5),
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
-- Invoegen van gegevens in de 'sensor_data'-tabel
|
||||
INSERT INTO goodgarden.sensor_data (timestamp, gateway_receive_time, device, value)
|
||||
VALUES (1707295162, '2024-02-07T08:39:22Z', 256, 4.107448101043701),
|
||||
(1707261284, '2024-02-06T23:14:44Z', 322, 4.111111164093018);
|
||||
417
goodgarden.sql
Normal file
417
goodgarden.sql
Normal file
@@ -0,0 +1,417 @@
|
||||
-- phpMyAdmin SQL Dump
|
||||
-- version 5.2.1
|
||||
-- https://www.phpmyadmin.net/
|
||||
--
|
||||
-- Host: 127.0.0.1
|
||||
-- Gegenereerd op: 09 apr 2024 om 21:22
|
||||
-- Serverversie: 10.4.32-MariaDB
|
||||
-- PHP-versie: 8.2.12
|
||||
|
||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||
START TRANSACTION;
|
||||
SET time_zone = "+00:00";
|
||||
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8mb4 */;
|
||||
|
||||
--
|
||||
-- Database: `goodgarden`
|
||||
--
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
DROP DATABASE IF EXISTS goodgarden;
|
||||
CREATE DATABASE goodgarden;
|
||||
|
||||
USE goodgarden;
|
||||
|
||||
--
|
||||
-- Tabelstructuur voor tabel `battery_voltage_events`
|
||||
--
|
||||
|
||||
CREATE TABLE `battery_voltage_events` (
|
||||
`id` int(10) UNSIGNED NOT NULL,
|
||||
`timestamp` int(11) DEFAULT NULL,
|
||||
`gateway_receive_time` varchar(50) DEFAULT NULL,
|
||||
`device` int(11) DEFAULT NULL,
|
||||
`value` decimal(10,5) DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Gegevens worden geëxporteerd voor tabel `battery_voltage_events`
|
||||
--
|
||||
|
||||
INSERT INTO `battery_voltage_events` (`id`, `timestamp`, `gateway_receive_time`, `device`, `value`) VALUES
|
||||
(2185, 1710839863, '2024-03-19T09:17:43Z', 256, 4.03663),
|
||||
(2186, 1710842346, '2024-03-19T09:59:06Z', 322, 4.08547);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabelstructuur voor tabel `care_schedules`
|
||||
--
|
||||
|
||||
CREATE TABLE `care_schedules` (
|
||||
`plant_id` int(10) UNSIGNED NOT NULL,
|
||||
`water` int(11) DEFAULT NULL,
|
||||
`bemesting` int(11) DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Gegevens worden geëxporteerd voor tabel `care_schedules`
|
||||
--
|
||||
|
||||
INSERT INTO `care_schedules` (`plant_id`, `water`, `bemesting`) VALUES
|
||||
(1, 2, 15),
|
||||
(2, 3, 10),
|
||||
(3, 2, 10),
|
||||
(4, 2, 15),
|
||||
(5, 2, 15),
|
||||
(6, 3, 15),
|
||||
(7, 3, 10),
|
||||
(8, 2, 15),
|
||||
(9, 2, 10),
|
||||
(10, 2, 10),
|
||||
(11, 2, 15),
|
||||
(12, 3, 15),
|
||||
(13, 2, 10),
|
||||
(14, 3, 15),
|
||||
(15, 2, 10);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabelstructuur voor tabel `devices`
|
||||
--
|
||||
|
||||
CREATE TABLE `devices` (
|
||||
`id` int(10) UNSIGNED NOT NULL,
|
||||
`serial_number` varchar(255) DEFAULT NULL,
|
||||
`name` varchar(255) DEFAULT NULL,
|
||||
`label` varchar(255) DEFAULT NULL,
|
||||
`last_seen` int(11) DEFAULT NULL,
|
||||
`last_battery_voltage` float DEFAULT NULL,
|
||||
`device_id` int(10) DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Gegevens worden geëxporteerd voor tabel `devices`
|
||||
--
|
||||
|
||||
INSERT INTO `devices` (`id`, `serial_number`, `name`, `label`, `last_seen`, `last_battery_voltage`, `device_id`) VALUES
|
||||
(15, '0033889B1BAB1169', 'firefly2_0051', 'The Field', 1712297000, 3.92796, 256),
|
||||
(16, '006FE1FC316ED7D8', 'firefly2_0111', 'The Field', 1712297257, 4.07448, 322);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabelstructuur voor tabel `fetch`
|
||||
--
|
||||
|
||||
CREATE TABLE `fetch` (
|
||||
`id` int(10) UNSIGNED NOT NULL,
|
||||
`timestamp` int(11) DEFAULT NULL,
|
||||
`gateway_receive_time` varchar(50) DEFAULT NULL,
|
||||
`device` int(11) DEFAULT NULL,
|
||||
`value` decimal(10,5) DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabelstructuur voor tabel `par_events`
|
||||
--
|
||||
|
||||
CREATE TABLE `par_events` (
|
||||
`id` int(10) UNSIGNED NOT NULL,
|
||||
`timestamp` int(11) DEFAULT NULL,
|
||||
`gateway_receive_time` varchar(50) DEFAULT NULL,
|
||||
`device` int(11) DEFAULT NULL,
|
||||
`value` decimal(10,5) DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabelstructuur voor tabel `planten`
|
||||
--
|
||||
|
||||
CREATE TABLE `planten` (
|
||||
`id` int(11) NOT NULL,
|
||||
`plant_naam` varchar(50) DEFAULT NULL,
|
||||
`plantensoort` varchar(50) NOT NULL,
|
||||
`plant_geteelt` tinyint(1) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Gegevens worden geëxporteerd voor tabel `planten`
|
||||
--
|
||||
|
||||
INSERT INTO `planten` (`id`, `plant_naam`, `plantensoort`, `plant_geteelt`) VALUES
|
||||
(1, 'Tomatenplant', 'Groente', 1),
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabelstructuur voor tabel `plants`
|
||||
--
|
||||
|
||||
CREATE TABLE `plants` (
|
||||
`id` int(10) UNSIGNED NOT NULL,
|
||||
`name` varchar(255) DEFAULT NULL,
|
||||
`type` varchar(255) DEFAULT NULL,
|
||||
`beschrijving` text DEFAULT NULL,
|
||||
`licht` varchar(50) DEFAULT NULL,
|
||||
`vochtigheid` varchar(50) DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Gegevens worden geëxporteerd voor tabel `plants`
|
||||
--
|
||||
|
||||
INSERT INTO `plants` (`id`, `name`, `type`, `beschrijving`, `licht`, `vochtigheid`) VALUES
|
||||
(1, 'Tomaat', 'Groente', 'Tomaat (Solanum lycopersicum) is een veelgeteelde groenteplant in de nachtschadefamilie.', 'Volle Zon', '70'),
|
||||
(2, 'Sla', 'Groente', 'Sla (Lactuca sativa) is een bladgroente die vaak wordt gebruikt in salades.', 'Gedeeltelijke Schaduw', '80'),
|
||||
(3, 'Wortel', 'Groente', 'Wortel (Daucus carota) is een wortelgroente meestal oranje van kleur.', 'Volle Zon', '60'),
|
||||
(4, 'Komkommer', 'Groente', 'Komkommer (Cucumis sativus) is een veel gekweekte kruipende wijnplant in de familie Cucurbitaceae.', 'Volle Zon', '65'),
|
||||
(5, 'Aardappel', 'Groente', 'Aardappel (Solanum tuberosum) is een zetmeelhoudend knolgewas van de vaste plant Solanum tuberosum.', 'Gedeeltelijke Schaduw', '75'),
|
||||
(6, 'Courgette', 'Groente', 'Courgette (Cucurbita pepo) is een zomerpompoen die bijna een meter lang kan worden, maar meestal onrijp wordt geoogst op 15 tot 25 cm.', 'Volle Zon', '70'),
|
||||
(7, 'Spinazie', 'Groente', 'Spinazie (Spinacia oleracea) is een bladgroente afkomstig uit Centraal- en West-Azië.', 'Gedeeltelijke Schaduw', '70'),
|
||||
(8, 'Paprika', 'Groente', 'Paprika (Capsicum annuum) is een fruit- en groenteplant gekweekt om zijn vruchten.', 'Volle Zon', '80'),
|
||||
(9, 'Ui', 'Groente', 'Ui (Allium cepa) is een groente die de meest geteelde soort is van het geslacht Allium.', 'Volle Zon', '50'),
|
||||
(10, 'Radijs', 'Groente', 'Radijs (Raphanus raphanistrum subsp. sativus) is een eetbare wortelgroente.', 'Volle Zon', '70'),
|
||||
(11, 'Groene Boon', 'Groente', 'Groene bonen zijn de onrijpe, jonge vruchten en beschermende peulen van verschillende cultivars van de gewone boon.', 'Volle Zon', '75'),
|
||||
(12, 'Broccoli', 'Groente', 'Broccoli (Brassica oleracea var. italica) is een koelgewas dat in het voorjaar of de herfst kan worden gekweekt.', 'Volle Zon', '75'),
|
||||
(13, 'Kool', 'Groente', 'Kool (Brassica oleracea of varianten) is een bladgroente, rood of wit, een tweejarige plant die wordt geteeld als eenjarige groente.', 'Gedeeltelijke Schaduw', '80'),
|
||||
(14, 'Aubergine', 'Groente', 'Aubergine (Solanum melongena) is een soort in de nachtschadefamilie die wordt gekweekt om zijn eetbare vruchten.', 'Volle Zon', '85'),
|
||||
(15, 'Boerenkool', 'Groente', 'Boerenkool of bladkool (Brassica oleracea var. acephala) is een groenteplant met groene of paarse bladeren.', 'Gedeeltelijke Schaduw', '70');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabelstructuur voor tabel `relative_humidity_events`
|
||||
--
|
||||
|
||||
CREATE TABLE `relative_humidity_events` (
|
||||
`id` int(10) UNSIGNED NOT NULL,
|
||||
`timestamp` int(11) DEFAULT NULL,
|
||||
`gateway_receive_time` varchar(50) DEFAULT NULL,
|
||||
`device` int(11) DEFAULT NULL,
|
||||
`value` decimal(10,5) DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabelstructuur voor tabel `soil_electric_conductivity_events`
|
||||
--
|
||||
|
||||
CREATE TABLE `soil_electric_conductivity_events` (
|
||||
`id` int(10) UNSIGNED NOT NULL,
|
||||
`timestamp` int(11) DEFAULT NULL,
|
||||
`gateway_receive_time` varchar(50) DEFAULT NULL,
|
||||
`device` int(11) DEFAULT NULL,
|
||||
`value` decimal(10,5) DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabelstructuur voor tabel `soil_relative_permittivity_events`
|
||||
--
|
||||
|
||||
CREATE TABLE `soil_relative_permittivity_events` (
|
||||
`id` int(10) UNSIGNED NOT NULL,
|
||||
`timestamp` int(11) DEFAULT NULL,
|
||||
`gateway_receive_time` varchar(50) DEFAULT NULL,
|
||||
`device` int(11) DEFAULT NULL,
|
||||
`value` decimal(10,5) DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabelstructuur voor tabel `soil_temperature_events`
|
||||
--
|
||||
|
||||
CREATE TABLE `soil_temperature_events` (
|
||||
`id` int(10) NOT NULL,
|
||||
`timestamp` int(11) DEFAULT NULL,
|
||||
`gateway_receive_time` varchar(50) DEFAULT NULL,
|
||||
`device` int(11) DEFAULT NULL,
|
||||
`value` decimal(10,5) DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Indexen voor geëxporteerde tabellen
|
||||
--
|
||||
|
||||
--
|
||||
-- Indexen voor tabel `battery_voltage_events`
|
||||
--
|
||||
ALTER TABLE `battery_voltage_events`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `timestamp` (`timestamp`),
|
||||
ADD UNIQUE KEY `gateway_receive_time` (`gateway_receive_time`);
|
||||
|
||||
--
|
||||
-- Indexen voor tabel `care_schedules`
|
||||
--
|
||||
ALTER TABLE `care_schedules`
|
||||
ADD PRIMARY KEY (`plant_id`);
|
||||
|
||||
--
|
||||
-- Indexen voor tabel `devices`
|
||||
--
|
||||
ALTER TABLE `devices`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `last_seen` (`last_seen`),
|
||||
ADD UNIQUE KEY `last_battery_voltage` (`last_battery_voltage`);
|
||||
|
||||
--
|
||||
-- Indexen voor tabel `fetch`
|
||||
--
|
||||
ALTER TABLE `fetch`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `timestamp` (`timestamp`),
|
||||
ADD UNIQUE KEY `gateway_receive_time` (`gateway_receive_time`),
|
||||
ADD UNIQUE KEY `value` (`value`);
|
||||
|
||||
--
|
||||
-- Indexen voor tabel `par_events`
|
||||
--
|
||||
ALTER TABLE `par_events`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `timestamp` (`timestamp`),
|
||||
ADD UNIQUE KEY `gateway_receive_time` (`gateway_receive_time`),
|
||||
ADD UNIQUE KEY `value` (`value`);
|
||||
|
||||
--
|
||||
-- Indexen voor tabel `planten`
|
||||
--
|
||||
ALTER TABLE `planten`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- Indexen voor tabel `plants`
|
||||
--
|
||||
ALTER TABLE `plants`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- Indexen voor tabel `relative_humidity_events`
|
||||
--
|
||||
ALTER TABLE `relative_humidity_events`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `timestamp` (`timestamp`),
|
||||
ADD UNIQUE KEY `gateway_receive_time` (`gateway_receive_time`),
|
||||
ADD UNIQUE KEY `value` (`value`);
|
||||
|
||||
--
|
||||
-- Indexen voor tabel `soil_electric_conductivity_events`
|
||||
--
|
||||
ALTER TABLE `soil_electric_conductivity_events`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `timestamp` (`timestamp`),
|
||||
ADD UNIQUE KEY `gateway_receive_time` (`gateway_receive_time`),
|
||||
ADD UNIQUE KEY `value` (`value`);
|
||||
|
||||
--
|
||||
-- Indexen voor tabel `soil_relative_permittivity_events`
|
||||
--
|
||||
ALTER TABLE `soil_relative_permittivity_events`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `timestamp` (`timestamp`),
|
||||
ADD UNIQUE KEY `gateway_receive_time` (`gateway_receive_time`),
|
||||
ADD UNIQUE KEY `value` (`value`);
|
||||
|
||||
--
|
||||
-- Indexen voor tabel `soil_temperature_events`
|
||||
--
|
||||
ALTER TABLE `soil_temperature_events`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `timestamp` (`timestamp`),
|
||||
ADD UNIQUE KEY `gateway_receive_time` (`gateway_receive_time`),
|
||||
ADD UNIQUE KEY `value` (`value`);
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT voor geëxporteerde tabellen
|
||||
--
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT voor een tabel `battery_voltage_events`
|
||||
--
|
||||
ALTER TABLE `battery_voltage_events`
|
||||
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2189;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT voor een tabel `devices`
|
||||
--
|
||||
ALTER TABLE `devices`
|
||||
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=21;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT voor een tabel `fetch`
|
||||
--
|
||||
ALTER TABLE `fetch`
|
||||
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=100;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT voor een tabel `par_events`
|
||||
--
|
||||
ALTER TABLE `par_events`
|
||||
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT voor een tabel `planten`
|
||||
--
|
||||
ALTER TABLE `planten`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=15;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT voor een tabel `plants`
|
||||
--
|
||||
ALTER TABLE `plants`
|
||||
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=16;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT voor een tabel `relative_humidity_events`
|
||||
--
|
||||
ALTER TABLE `relative_humidity_events`
|
||||
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=9;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT voor een tabel `soil_electric_conductivity_events`
|
||||
--
|
||||
ALTER TABLE `soil_electric_conductivity_events`
|
||||
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT voor een tabel `soil_relative_permittivity_events`
|
||||
--
|
||||
ALTER TABLE `soil_relative_permittivity_events`
|
||||
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT voor een tabel `soil_temperature_events`
|
||||
--
|
||||
ALTER TABLE `soil_temperature_events`
|
||||
MODIFY `id` int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8;
|
||||
|
||||
--
|
||||
-- Beperkingen voor geëxporteerde tabellen
|
||||
--
|
||||
|
||||
--
|
||||
-- Beperkingen voor tabel `care_schedules`
|
||||
--
|
||||
ALTER TABLE `care_schedules`
|
||||
ADD CONSTRAINT `fk_plant_id` FOREIGN KEY (`plant_id`) REFERENCES `plants` (`id`);
|
||||
COMMIT;
|
||||
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
62
index.py
62
index.py
@@ -1,62 +0,0 @@
|
||||
import mysql.connector
|
||||
import requests
|
||||
|
||||
# Verbinding maken met de database
|
||||
mydb = mysql.connector.connect(
|
||||
host="localhost",
|
||||
user="root",
|
||||
password="",
|
||||
database="goodgarden"
|
||||
)
|
||||
|
||||
# Controleren of de verbinding succesvol is
|
||||
if mydb.is_connected():
|
||||
print("Connected to the database")
|
||||
else:
|
||||
print("Failed to connect to the database")
|
||||
|
||||
try:
|
||||
# Maak een cursor aan
|
||||
mycursor = mydb.cursor()
|
||||
|
||||
# Voer de query uit om gegevens op te halen
|
||||
mycursor.execute("SELECT * FROM goodgarden.sensor_data")
|
||||
|
||||
# Haal de resultaten op
|
||||
myresult = mycursor.fetchall()
|
||||
|
||||
# Print de resultaten
|
||||
for x in myresult:
|
||||
print(x)
|
||||
|
||||
except mysql.connector.Error as err:
|
||||
print(f"Error: {err}")
|
||||
|
||||
finally:
|
||||
# Sluit de cursor en de databaseverbinding
|
||||
mycursor.close()
|
||||
mydb.close(
|
||||
|
||||
)
|
||||
|
||||
def fetch_data():
|
||||
url = "https://garden.inajar.nl/api/battery_voltage_events/?format=json"
|
||||
headers = {
|
||||
"Authorization": "Token 33bb3b42452306c58ecedc3c86cfae28ba22329c"
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.get(url, headers=headers)
|
||||
response.raise_for_status() # Raise an exception for 4xx and 5xx status codes
|
||||
|
||||
data = response.json()
|
||||
load_data(data)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Error fetching data: {e}")
|
||||
|
||||
def load_data(data):
|
||||
api_data = data
|
||||
print("Data loaded:", api_data)
|
||||
|
||||
if __name__ == "__main__":
|
||||
fetch_data()
|
||||
59
mqtt/mqtt_client.py
Normal file
59
mqtt/mqtt_client.py
Normal file
@@ -0,0 +1,59 @@
|
||||
# Importeer de paho.mqtt.client module die MQTT-client functionaliteiten biedt.
|
||||
import paho.mqtt.client as mqtt
|
||||
|
||||
def create_client(client_id, on_connect, on_message, broker="localhost", port=1883):
|
||||
"""
|
||||
Creëert en configureert een MQTT-client.
|
||||
|
||||
Deze functie initialiseert een MQTT-client met een unieke client_id,
|
||||
definieert callback functies voor connect- en message-events, en
|
||||
maakt vervolgens verbinding met de MQTT-broker.
|
||||
|
||||
Parameters:
|
||||
client_id (str): Een unieke identifier voor de MQTT-client.
|
||||
on_connect (function): Callback functie die wordt aangeroepen
|
||||
wanneer de client verbinding maakt met de broker.
|
||||
on_message (function): Callback functie die wordt aangeroepen
|
||||
wanneer een bericht wordt ontvangen.
|
||||
broker (str, optional): Het adres van de MQTT-broker.
|
||||
Standaard is dit "localhost".
|
||||
port (int, optional): De poort waarop de MQTT-broker luistert.
|
||||
Standaard is dit 1883.
|
||||
|
||||
Returns:
|
||||
mqtt.Client: Een geconfigureerde MQTT-clientobject.
|
||||
"""
|
||||
# Initialiseert een MQTT-client met de opgegeven client_id.
|
||||
client = mqtt.Client(client_id)
|
||||
|
||||
# Stelt de callback functies in voor connect- en message-events.
|
||||
client.on_connect = on_connect
|
||||
client.on_message = on_message
|
||||
|
||||
# Maakt verbinding met de opgegeven MQTT-broker en poort.
|
||||
client.connect(broker, port, 60) # De keepalive is ingesteld op 60 seconden.
|
||||
|
||||
# Retourneert het geïnitialiseerde en geconfigureerde client-object.
|
||||
return client
|
||||
|
||||
def start_loop(client):
|
||||
"""
|
||||
Start de netwerkloop van de MQTT-client.
|
||||
|
||||
Deze functie start de oneindige loop van de client, waardoor deze
|
||||
continu luistert naar berichten van de broker. De loop wordt onderbroken
|
||||
bij het ontvangen van een KeyboardInterrupt (Ctrl+C).
|
||||
|
||||
Parameters:
|
||||
client (mqtt.Client): De MQTT-client die de loop zal uitvoeren.
|
||||
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
try:
|
||||
# Start de oneindige loop die berichten verwerkt.
|
||||
client.loop_forever()
|
||||
except KeyboardInterrupt:
|
||||
# Print een bericht en maakt de verbinding met de broker los
|
||||
# als de gebruiker de loop onderbreekt.
|
||||
print("Disconnecting from broker")
|
||||
87
mqtt/publisher.py
Normal file
87
mqtt/publisher.py
Normal file
@@ -0,0 +1,87 @@
|
||||
# Importeer benodigde modules voor het uitvoeren van HTTP-verzoeken, tijdbeheer, en JSON-operaties.
|
||||
import requests
|
||||
import time
|
||||
import json
|
||||
|
||||
# Importeer MQTT-client functies van een aangepaste module.
|
||||
from mqtt_client import create_client, start_loop
|
||||
|
||||
# Stel het interval in seconden in voor het periodiek ophalen en publiceren van data.
|
||||
publish_interval = 900 # MOET ~900 ZIJN. -- 15min
|
||||
|
||||
# Definieer API-eindpunten en de corresponderende MQTT topics.
|
||||
api_endpoints = [
|
||||
{"url": "https://garden.inajar.nl/api/devices/", "topic": "goodgarden/devices"},
|
||||
{"url": "https://garden.inajar.nl/api/relative_humidity_events/", "topic": "goodgarden/relative_humidity"},
|
||||
{"url": "https://garden.inajar.nl/api/battery_voltage_events/", "topic": "goodgarden/battery_voltage"},
|
||||
{"url": "https://garden.inajar.nl/api/soil_electric_conductivity_events/", "topic": "goodgarden/soil_electric_conductivity"},
|
||||
{"url": "https://garden.inajar.nl/api/soil_relative_permittivity_events/", "topic": "goodgarden/soil_relative_permittivity"},
|
||||
{"url": "https://garden.inajar.nl/api/soil_temperature_events/", "topic": "goodgarden/soil_temperature"},
|
||||
{"url": "https://garden.inajar.nl/api/par_events/", "topic": "goodgarden/par_events"}
|
||||
]
|
||||
|
||||
def on_connect(client, userdata, flags, rc):
|
||||
"""
|
||||
Callback functie voor het afhandelen van de connectie-event met de MQTT broker.
|
||||
|
||||
Parameters:
|
||||
client: De MQTT-client instantie.
|
||||
userdata: De private user-specifieke data zoals ingesteld in Client() of user_data_set().
|
||||
flags: Reactie vlaggen van de broker.
|
||||
rc: De connectie resultaat code.
|
||||
"""
|
||||
print("Geconnect met code "+str(rc))
|
||||
|
||||
def on_message(client, userdata, msg):
|
||||
"""
|
||||
Callback functie voor het afhandelen van inkomende berichten voor geabonneerde topics.
|
||||
|
||||
Parameters:
|
||||
client: De MQTT-client instantie.
|
||||
userdata: De private user-specifieke data.
|
||||
msg: Het bericht instantie.
|
||||
"""
|
||||
print(f"Message: {msg.topic} {str(msg.payload)}")
|
||||
|
||||
# Initialiseer de MQTT-client met een unieke client ID en callback functies.
|
||||
client = create_client("publisher1", on_connect, on_message)
|
||||
|
||||
def publish_to_mqtt(topic, data):
|
||||
"""
|
||||
Publiceert data naar een MQTT topic.
|
||||
|
||||
Parameters:
|
||||
topic (str): Het MQTT topic waarop de data wordt gepubliceerd.
|
||||
data (dict): De data die gepubliceerd moet worden, geconverteerd naar JSON formaat.
|
||||
"""
|
||||
json_data = json.dumps(data) # Serialiseer de data naar een JSON-string.
|
||||
client.publish(topic, json_data)
|
||||
print(f"\033[92mData gepubliceerd naar MQTT topic {topic}.\033[0m")
|
||||
|
||||
def fetch_and_publish_data():
|
||||
"""
|
||||
Haalt data op van API-eindpunten en publiceert deze naar MQTT.
|
||||
"""
|
||||
for endpoint in api_endpoints:
|
||||
url = endpoint["url"]
|
||||
mqtt_topic = endpoint["topic"]
|
||||
access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c"
|
||||
|
||||
try:
|
||||
headers = {"Authorization": f"Token {access_token}"}
|
||||
response = requests.get(url, headers=headers)
|
||||
response.raise_for_status() # Verifieert respons status.
|
||||
data = response.json()
|
||||
print(f"Data van {url}: {data}")
|
||||
publish_to_mqtt(mqtt_topic, data)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Error met data ophalen {url}: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
client.loop_start() # Start de niet-blokkerende MQTT-client loop.
|
||||
while True:
|
||||
fetch_and_publish_data() # Haal data op en publiceer.
|
||||
print(f"\033[91mWachten, wachten en nog eens wachten... {publish_interval} secondes!\033[0m\n")
|
||||
time.sleep(publish_interval) # Wacht voor het ingestelde interval.
|
||||
|
||||
client.loop_stop()
|
||||
3307
package-lock.json
generated
Normal file
3307
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
26
package.json
Normal file
26
package.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "goodgarden",
|
||||
"description": "",
|
||||
"main": "app.js",
|
||||
"scripts": {
|
||||
"start": "npm-run-all --parallel start-flask start-electron",
|
||||
"start-electron": "wait-on http://localhost:5000 && electron app.js",
|
||||
"start-flask": "py app.py"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"concurrently": "^8.2.2",
|
||||
"electron": "^23.3.13",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"wait-on": "^7.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.6.7",
|
||||
"body-parser": "^1.20.2",
|
||||
"elctron": "^0.0.1-security",
|
||||
"express": "^4.19.2",
|
||||
"mysql2": "^3.9.1",
|
||||
"python-shell": "^5.0.0"
|
||||
}
|
||||
}
|
||||
0
src/py/__init__.py
Normal file
0
src/py/__init__.py
Normal file
216
src/py/script/battery_voltage_events.py
Normal file
216
src/py/script/battery_voltage_events.py
Normal file
@@ -0,0 +1,216 @@
|
||||
import mysql.connector
|
||||
import requests
|
||||
import time
|
||||
|
||||
from db_connect import database_connect
|
||||
|
||||
# Functie voor het aanmaken van gegevens in de database
|
||||
def create_data(url, access_token, repeat_count=5):
|
||||
for _ in range(repeat_count):
|
||||
try:
|
||||
headers = {"Authorization": f"Token {access_token}"}
|
||||
response = requests.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
data = response.json()
|
||||
print(f"Data from {url}:\n")
|
||||
|
||||
# Check if data is a list (records directly under the root)
|
||||
if isinstance(data, list):
|
||||
records = data
|
||||
elif isinstance(data, dict) and 'results' in data:
|
||||
records = data['results']
|
||||
else:
|
||||
print(f"Unexpected data format received: {data}")
|
||||
continue
|
||||
|
||||
for record in records:
|
||||
# Now, record is assumed to be a dictionary
|
||||
timestamp = record.get('timestamp', '')
|
||||
gateway_receive_time = record.get('gateway_receive_time', '')
|
||||
device = record.get('device', '')
|
||||
value = record.get('value', '')
|
||||
|
||||
print(f"\nInserted data: Timestamp: {timestamp}, Device: {device}, Battery Voltage: {value}V\n")
|
||||
if float(value) < 5.0:
|
||||
print("Waarschuwing: Batterijspanning is lager dan 3.0 volt. Opladen aanbevolen.\n")
|
||||
# Controleer of de batterijspanning hoger is dan 4.2 volt en geef een melding
|
||||
elif float(value) > 6.2:
|
||||
print("Melding: Batterijspanning is hoger dan 4.2 volt. Batterij is vol.\n")
|
||||
else:
|
||||
print("Melding: Batterijspanning is binnen het gewenste bereik.\n\n")
|
||||
|
||||
# Insert data into the database
|
||||
insert_data(record)
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Error fetching data from {url}: {e}")
|
||||
|
||||
print("Waiting for the next create action...\n")
|
||||
time.sleep(1)
|
||||
|
||||
# Functie voor het invoegen van gegevens in de database
|
||||
def insert_data(record):
|
||||
mydb = database_connect()
|
||||
if mydb.is_connected():
|
||||
mycursor = mydb.cursor()
|
||||
|
||||
# Hier moet je de juiste kolomnamen en gegevensindeling aanpassen op basis van de API-respons
|
||||
insert_query = """
|
||||
INSERT INTO goodgarden.battery_voltage_events (timestamp, gateway_receive_time, device, value)
|
||||
VALUES (%s, %s, %s, %s)
|
||||
"""
|
||||
# Pas dit aan op basis van de werkelijke structuur van de JSON
|
||||
timestamp = record.get('timestamp', '')
|
||||
gateway_receive_time = record.get('gateway_receive_time', '')
|
||||
device = record.get('device', '')
|
||||
value = record.get('value', '')
|
||||
|
||||
print(f"Inserting data: timestamp={timestamp}, gateway_receive_time={gateway_receive_time}, device={device}, value={value}") # Print de ingevoerde gegevens
|
||||
|
||||
# Voer de query uit
|
||||
mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
|
||||
|
||||
# Bevestig de wijzigingen
|
||||
mydb.commit()
|
||||
|
||||
# Sluit cursor en verbinding
|
||||
mycursor.close()
|
||||
mydb.close()
|
||||
|
||||
print("Data inserted into the database.")
|
||||
|
||||
# Functie voor het lezen van gegevens uit de database
|
||||
def read_data(url, access_token, repeat_count=5):
|
||||
for _ in range(repeat_count):
|
||||
try:
|
||||
headers = {"Authorization": f"Token {access_token}"}
|
||||
response = requests.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
data = response.json()
|
||||
print(f"Data from {url}:\n")
|
||||
|
||||
for record in data['results']:
|
||||
timestamp = record.get('timestamp', '')
|
||||
device = record.get('device', '')
|
||||
value = record.get('value', '')
|
||||
print(f"Timestamp: {timestamp}, Device: {device}, Battery Voltage: {value}V\n")
|
||||
|
||||
if float(value) < 3.0:
|
||||
print("Waarschuwing: Batterijspanning is lager dan 3.0 volt. Opladen aanbevolen.\n")
|
||||
# Controleer of de batterijspanning hoger is dan 4.2 volt en geef een melding
|
||||
elif float(value) > 4.2:
|
||||
print("Melding: Batterijspanning is hoger dan 4.2 volt. Batterij is vol.\n")
|
||||
else:
|
||||
print("Melding: Batterijspanning is binnen het gewenste bereik.\n\n")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Error fetching data from {url}: {e}")
|
||||
|
||||
print("Waiting for the next read action...\n")
|
||||
time.sleep(300)
|
||||
|
||||
# Functie voor het bijwerken van gegevens in de database
|
||||
def update_data(record_id):
|
||||
try:
|
||||
mydb = database_connect()
|
||||
|
||||
if mydb.is_connected():
|
||||
mycursor = mydb.cursor()
|
||||
|
||||
# Controleer of het record bestaat voordat je het bijwerkt
|
||||
mycursor.execute("SELECT * FROM goodgarden.battery_voltage_events WHERE id = %s", (record_id,))
|
||||
existing_record = mycursor.fetchone()
|
||||
|
||||
if not existing_record:
|
||||
print(f"Record with ID {record_id} not found. Update operation aborted.")
|
||||
return
|
||||
|
||||
# Vraag de gebruiker om nieuwe waarden voor de andere velden
|
||||
new_timestamp = input("Enter new timestamp: ")
|
||||
new_gateway_receive_time = input("Enter new gateway_receive_time: ")
|
||||
new_device = input("Enter new device: ")
|
||||
new_value = input("Enter new value: ")
|
||||
|
||||
# Hier moet je de juiste kolomnamen aanpassen op basis van de structuur van je database
|
||||
update_query = """
|
||||
UPDATE goodgarden.battery_voltage_events
|
||||
SET timestamp = %s, gateway_receive_time = %s, device = %s, value = %s
|
||||
WHERE id = %s
|
||||
"""
|
||||
|
||||
# Voer de query uit
|
||||
print(f"Executing update query: {update_query}")
|
||||
print(f"Updating record with ID {record_id} to new values - timestamp: {new_timestamp}, gateway_receive_time: {new_gateway_receive_time}, device: {new_device}, value: {new_value}")
|
||||
|
||||
mycursor.execute(update_query, (new_timestamp, new_gateway_receive_time, new_device, new_value, record_id))
|
||||
|
||||
# Bevestig de wijzigingen
|
||||
mydb.commit()
|
||||
|
||||
print(f"Update executed. Rowcount: {mycursor.rowcount}")
|
||||
|
||||
except mysql.connector.Error as update_err:
|
||||
print(f"Error updating data: {update_err}")
|
||||
finally:
|
||||
# Zorg ervoor dat je altijd de cursor en de databaseverbinding sluit
|
||||
if 'mycursor' in locals() and mycursor is not None:
|
||||
mycursor.close()
|
||||
if 'mydb' in locals() and mydb.is_connected():
|
||||
mydb.close()
|
||||
|
||||
# Functie voor het verwijderen van gegevens uit de database
|
||||
def delete_data(record_id):
|
||||
mydb = database_connect()
|
||||
if mydb.is_connected():
|
||||
mycursor = mydb.cursor()
|
||||
|
||||
# Hier moet je de juiste kolomnamen aanpassen op basis van de structuur van je database
|
||||
delete_query = """
|
||||
DELETE FROM goodgarden.battery_voltage_events
|
||||
WHERE id = %s
|
||||
"""
|
||||
|
||||
# Voer de query uit
|
||||
mycursor.execute(delete_query, (record_id,))
|
||||
|
||||
# Bevestig de wijzigingen
|
||||
mydb.commit()
|
||||
|
||||
# Sluit cursor en verbinding
|
||||
mycursor.close()
|
||||
mydb.close()
|
||||
|
||||
print(f"Data with ID {record_id} deleted.")
|
||||
|
||||
# Functie voor het aanmaken van gegevens in de database op basis van batterijspanningsinformatie
|
||||
|
||||
if __name__ == "__main__":
|
||||
url = "https://garden.inajar.nl/api/battery_voltage_events/?format=json"
|
||||
access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c"
|
||||
|
||||
# Je kunt repeat_count wijzigen om te bepalen hoe vaak je de bewerking wilt herhalen
|
||||
repeat_count = 10
|
||||
|
||||
# Keuze voor de bewerking
|
||||
operation_choice = input("Choose operation (C for Create, R for Read, U for Update, D for Delete): ").upper()
|
||||
|
||||
if operation_choice == "C":
|
||||
# Maak gegevens aan
|
||||
create_data(url, access_token, repeat_count)
|
||||
elif operation_choice == "R":
|
||||
# Lees gegevens
|
||||
read_data(url, access_token, repeat_count)
|
||||
elif operation_choice == "U":
|
||||
# Update gegevens
|
||||
record_id = int(input("Enter record ID to update: "))
|
||||
# Call the update_data function without additional arguments
|
||||
# Roep de update_data function aan zonder arguments
|
||||
update_data(record_id)
|
||||
elif operation_choice == "D":
|
||||
# Verwijder gegevens
|
||||
record_id = int(input("Enter record ID to delete: "))
|
||||
delete_data(record_id)
|
||||
else:
|
||||
print("Invalid operation choice. Please choose C, R, U, or D.")
|
||||
26
src/py/script/db_connect.py
Normal file
26
src/py/script/db_connect.py
Normal file
@@ -0,0 +1,26 @@
|
||||
import mysql.connector
|
||||
|
||||
from mysql.connector import Error
|
||||
|
||||
# Definieer een functie genaamd `database_connect` om verbinding te maken met de database.
|
||||
def database_connect():
|
||||
try:
|
||||
# Maak een verbinding met de MySQL database.
|
||||
# Specificeer de database credentials en de database naam.
|
||||
connection = mysql.connector.connect(
|
||||
host="localhost", # De hostnaam waar de database draait, in dit geval lokaal.
|
||||
user="root", # De gebruikersnaam voor de database.
|
||||
password="root", # Het wachtwoord voor de gebruiker, leeg in dit geval.
|
||||
database="goodgarden" # De naam van de database waarmee je wilt verbinden.
|
||||
)
|
||||
# Controleer of de verbinding succesvol is opgezet.
|
||||
if connection.is_connected():
|
||||
# Als de verbinding succesvol is, retourneer het verbinding object.
|
||||
# De print statement is uitgecommentarieerd, maar kan worden gebruikt voor debuggen.
|
||||
# print("Connection gelukt!")
|
||||
return connection
|
||||
except Error as e:
|
||||
# Als er een fout optreedt bij het maken van de verbinding, vang deze dan op en print een foutbericht.
|
||||
print(f"Connection NIET gelukt! ${e}")
|
||||
# Als de verbinding niet succesvol was, retourneer None.
|
||||
return None
|
||||
41
src/py/script/db_connect_form.py
Normal file
41
src/py/script/db_connect_form.py
Normal file
@@ -0,0 +1,41 @@
|
||||
import sys
|
||||
import json
|
||||
|
||||
from db_connect import database_connect
|
||||
from mysql.connector import Error
|
||||
|
||||
# Voeg de data uit het formulier toe aan de database
|
||||
def insert_plant_name(plant_naam, plantensoort, plant_geteelt):
|
||||
|
||||
# Als er "true" is meegegeven als waarde dan komt in de database 1 anders 0 (false)
|
||||
plant_geteelt_value = 1 if plant_geteelt.lower() == "true" else 0
|
||||
|
||||
try:
|
||||
# Gebruik de verbinding die teruggegeven wordt door de database_connect functie uit de db_connect module
|
||||
connection = database_connect()
|
||||
|
||||
# Je kunt de controle of de verbinding succesvol is rechtstreeks in de database_connect functie uitvoeren
|
||||
# De cursor() zorgt ervoor dat er een verbinding met de database gelegd kan worden en de data gemanipuleerd
|
||||
cursor = connection.cursor()
|
||||
query = "INSERT INTO goodgarden.planten (plant_naam, plantensoort, plant_geteelt) VALUES (%s, %s, %s)"
|
||||
cursor.execute(query, (plant_naam, plantensoort, plant_geteelt_value)) # "%s" wordt hier ingevuld doormiddel van de variable (parameter)
|
||||
connection.commit()
|
||||
print(json.dumps({"success": True}))
|
||||
|
||||
except Error as e:
|
||||
print(json.dumps({"success": False, "error": str(e)}))
|
||||
|
||||
finally:
|
||||
if connection and connection.is_connected():
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
# Wordt alleen uitgevoerd als het een standalone script is (geen import!!!)
|
||||
if __name__ == "__main__":
|
||||
# Dit zijn de variables die door het JavaScript bestand (app.js) worden meegegeven --- NOTE: sys.argv[0] is altijd de naam van het script!
|
||||
plant_naam = sys.argv[1]
|
||||
plantensoort = sys.argv[2]
|
||||
plant_geteelt = sys.argv[3]
|
||||
|
||||
# Call de function met de variables
|
||||
insert_plant_name(plant_naam, plantensoort, plant_geteelt)
|
||||
55
src/py/script/devices.py
Normal file
55
src/py/script/devices.py
Normal file
@@ -0,0 +1,55 @@
|
||||
import json
|
||||
|
||||
from db_connect import database_connect
|
||||
from paho.mqtt import subscribe
|
||||
|
||||
def on_message(client, userdata, message):
|
||||
payload_str = message.payload.decode("utf-8")
|
||||
data = json.loads(payload_str)
|
||||
|
||||
# Verbinding maken met de database
|
||||
mydb = database_connect()
|
||||
|
||||
if mydb.is_connected():
|
||||
|
||||
# Creëren van een cursor object
|
||||
mycursor = mydb.cursor()
|
||||
|
||||
# SQL query voor het invoegen van de gegevens
|
||||
insert_query = """
|
||||
INSERT INTO goodgarden.devices
|
||||
(serial_number, name, label, last_seen, last_battery_voltage, device_id)
|
||||
VALUES (%s, %s, %s, %s, %s, %s)
|
||||
"""
|
||||
|
||||
# Verwerken van de gegevens uit het bericht
|
||||
for record in data['results']:
|
||||
serial_number = record.get('serial_number', '')
|
||||
name = record.get('name', '')
|
||||
label = record.get('label', '')
|
||||
last_seen = record.get('last_seen', '')
|
||||
last_battery_voltage = record.get('last_battery_voltage', '')
|
||||
device_id = record.get("id", "")
|
||||
|
||||
print(f"Inserting data: serial_number={serial_number}, name={name}, label={label}, last_seen={last_seen}, last_battery_voltage={last_battery_voltage}, device_id={device_id}")
|
||||
|
||||
# Uitvoeren van de SQL query
|
||||
mycursor.execute(insert_query, (serial_number, name, label, last_seen, last_battery_voltage, device_id))
|
||||
|
||||
# Commit de transacties naar de database
|
||||
mydb.commit()
|
||||
|
||||
# Sluiten van de cursor en de databaseconnectie
|
||||
mycursor.close()
|
||||
mydb.close()
|
||||
|
||||
print("Data inserted into the database.")
|
||||
|
||||
else:
|
||||
print("Failed to connect to the database.")
|
||||
|
||||
print(f"\033[92mMessage received on topic\033[0m {message.topic}: {data}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
topic = "goodgarden/devices"
|
||||
subscribe.callback(on_message, topic)
|
||||
8
src/py/script/json/plants.json
Normal file
8
src/py/script/json/plants.json
Normal file
@@ -0,0 +1,8 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"plant_naam": "Tomatenplant",
|
||||
"plantensoort": "Groente",
|
||||
"plant_geteelt": 1
|
||||
}
|
||||
]
|
||||
20
src/py/script/par_events.py
Normal file
20
src/py/script/par_events.py
Normal file
@@ -0,0 +1,20 @@
|
||||
import json
|
||||
|
||||
# Importeer de subscribe module van paho.mqtt om te abonneren op MQTT topics.
|
||||
from paho.mqtt import subscribe
|
||||
|
||||
# Definieer een callback functie die wordt aangeroepen wanneer een bericht wordt ontvangen.
|
||||
def on_message(client, userdata, message):
|
||||
# Decodeer het bericht payload van bytes naar een string met UTF-8 encoding.
|
||||
payload_str = message.payload.decode("utf-8")
|
||||
# Laad de JSON string in een Python dictionary.
|
||||
data = json.loads(payload_str)
|
||||
|
||||
print(f"Message received on topic {message.topic}: {data}")
|
||||
|
||||
# Dit blok zorgt ervoor dat de code alleen wordt uitgevoerd als dit script rechtstreeks wordt uitgevoerd.
|
||||
if __name__ == "__main__":
|
||||
# Definieer het topic waarop geabonneerd wordt.
|
||||
topic = "goodgarden/par_events"
|
||||
# Roep de subscribe.callback functie aan met de on_message functie als callback om te luisteren naar berichten op het gespecificeerde topic.
|
||||
subscribe.callback(on_message, topic)
|
||||
45
src/py/script/planten.py
Normal file
45
src/py/script/planten.py
Normal file
@@ -0,0 +1,45 @@
|
||||
import json
|
||||
import mysql.connector
|
||||
import os
|
||||
|
||||
from db_connect import database_connect # Gebruik deze geïmporteerde functie
|
||||
|
||||
# Functie om het absolute pad van de huidige directory te krijgen.
|
||||
def get_current_directory():
|
||||
return os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
# Functie om plantgegevens uit de database te halen en naar een JSON-bestand te schrijven.
|
||||
def fetch_plant_and_write_to_json():
|
||||
# Maak verbinding met de database.
|
||||
connection = database_connect()
|
||||
|
||||
try:
|
||||
# Maak een cursorobject aan met dictionary=True om rijen als woordenboeken op te halen.
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
# Voer de SQL-query uit om gegevens op te halen.
|
||||
cursor.execute("SELECT id, plant_naam, plantensoort, plant_geteelt FROM planten")
|
||||
# Haal alle rijen op.
|
||||
plants = cursor.fetchall()
|
||||
|
||||
# Verkrijg het absolute pad van de huidige directory.
|
||||
current_directory = get_current_directory()
|
||||
# Construeer het absolute pad voor het JSON-bestand.
|
||||
json_file_path = os.path.join(current_directory, './json/plants.json')
|
||||
|
||||
# Schrijf de opgehaalde gegevens naar een JSON-bestand.
|
||||
with open(json_file_path, 'w') as json_file:
|
||||
json.dump(plants, json_file, indent=4)
|
||||
|
||||
except mysql.connector.Error as error:
|
||||
# Print de fout als er iets misgaat bij het ophalen van de gegevens.
|
||||
print(f"Error fetching data from MySQL table: {error}")
|
||||
|
||||
finally:
|
||||
# Sluit de cursor en de verbinding, indien ze bestaan.
|
||||
if 'cursor' in locals():
|
||||
cursor.close()
|
||||
if connection and connection.is_connected():
|
||||
connection.close()
|
||||
|
||||
# Roept de functie aan om gegevens op te halen en naar JSON te schrijven.
|
||||
fetch_plant_and_write_to_json()
|
||||
21
src/py/script/relative_humidity_events.py
Normal file
21
src/py/script/relative_humidity_events.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import json
|
||||
|
||||
# Importeer de subscribe functie uit de paho.mqtt module voor MQTT-communicatie.
|
||||
from paho.mqtt import subscribe
|
||||
|
||||
# Definieer een callback functie die wordt aangeroepen wanneer een bericht wordt ontvangen.
|
||||
def on_message(client, userdata, message):
|
||||
# Decodeer de berichtpayload van bytes naar een UTF-8 gecodeerde string.
|
||||
payload_str = message.payload.decode("utf-8")
|
||||
# Converteer de JSON string naar een Python dictionary.
|
||||
data = json.loads(payload_str)
|
||||
|
||||
# Print een bericht uit met de ontvangen data en het topic waarop het bericht is ontvangen.
|
||||
print(f"Message received on topic {message.topic}: {data}")
|
||||
|
||||
# Het hoofdgedeelte van het script wordt alleen uitgevoerd als dit script als hoofdscript wordt gedraaid.
|
||||
if __name__ == "__main__":
|
||||
# Specificeer het MQTT-topic waarop geabonneerd moet worden.
|
||||
topic = "goodgarden/relative_humidity"
|
||||
# Abonneer op het opgegeven topic en roep de on_message functie aan als callback voor ontvangen berichten.
|
||||
subscribe.callback(on_message, topic)
|
||||
23
src/py/script/soil_electric_conductivity_events.py
Normal file
23
src/py/script/soil_electric_conductivity_events.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import json
|
||||
|
||||
# Van de paho.mqtt bibliotheek wordt de subscribe module geïmporteerd.
|
||||
# Deze module stelt ons in staat om ons te abonneren op MQTT-topics en berichten te ontvangen.
|
||||
from paho.mqtt import subscribe
|
||||
|
||||
# Definitie van de functie on_message die wordt aangeroepen wanneer een bericht wordt ontvangen.
|
||||
def on_message(client, userdata, message):
|
||||
# De payload van het bericht, dat in bytes is, wordt gedecodeerd naar een UTF-8 string.
|
||||
payload_str = message.payload.decode("utf-8")
|
||||
# De gedecodeerde string, die in JSON-formaat is, wordt omgezet naar een Python dictionary.
|
||||
data = json.loads(payload_str)
|
||||
|
||||
# Een bericht wordt geprint naar de console met de informatie over het ontvangen bericht.
|
||||
print(f"Message received on topic {message.topic}: {data}")
|
||||
|
||||
# Dit blok zorgt ervoor dat de volgende code alleen uitgevoerd wordt als dit script direct wordt uitgevoerd.
|
||||
if __name__ == "__main__":
|
||||
# Het MQTT-topic waarop het script zich abonneert, gerelateerd aan de elektrische geleidbaarheid van de bodem.
|
||||
topic = "goodgarden/soil_electric_conductivity"
|
||||
# De subscribe.callback functie wordt aangeroepen met de on_message functie als callback.
|
||||
# Dit start het proces van luisteren naar berichten op het gespecificeerde topic.
|
||||
subscribe.callback(on_message, topic)
|
||||
21
src/py/script/soil_relative_permittivity_events.py
Normal file
21
src/py/script/soil_relative_permittivity_events.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import json
|
||||
|
||||
# Importeer de subscribe functie van paho.mqtt om te abonneren op MQTT berichten.
|
||||
from paho.mqtt import subscribe
|
||||
|
||||
# Definieer een functie die wordt aangeroepen wanneer een bericht wordt ontvangen op het gespecificeerde MQTT topic.
|
||||
def on_message(client, userdata, message):
|
||||
# Decodeer de berichtpayload van bytes naar een UTF-8 string.
|
||||
payload_str = message.payload.decode("utf-8")
|
||||
# Laad de JSON string in een Python dictionary om gemakkelijk met de data te kunnen werken.
|
||||
data = json.loads(payload_str)
|
||||
|
||||
# Print een bericht uit met de topicnaam en de ontvangen data.
|
||||
print(f"Message received on topic {message.topic}: {data}")
|
||||
|
||||
# Het hoofdscript dat wordt uitgevoerd wanneer dit bestand direct wordt gerund.
|
||||
if __name__ == "__main__":
|
||||
# Specificeer het MQTT-topic waarop we willen abonneren. In dit geval luisteren we naar data over de relatieve permittiviteit van de bodem.
|
||||
topic = "goodgarden/soil_relative_permittivity"
|
||||
# Roep de subscribe.callback functie aan met de on_message functie als argument. Dit zorgt ervoor dat we voortdurend luisteren naar berichten op het gegeven topic.
|
||||
subscribe.callback(on_message, topic)
|
||||
21
src/py/script/soil_temperature_events.py
Normal file
21
src/py/script/soil_temperature_events.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import json
|
||||
|
||||
# Importeer de subscribe functie van de paho.mqtt bibliotheek voor MQTT communicatie.
|
||||
from paho.mqtt import subscribe
|
||||
|
||||
# Definieer de on_message functie die wordt uitgevoerd wanneer een bericht wordt ontvangen.
|
||||
def on_message(client, userdata, message):
|
||||
# Decodeer de payload van het bericht van bytes naar een UTF-8 gecodeerde string.
|
||||
payload_str = message.payload.decode("utf-8")
|
||||
# Converteer de JSON string naar een Python dictionary om het gemakkelijker te verwerken.
|
||||
data = json.loads(payload_str)
|
||||
|
||||
# Print de ontvangen data samen met het topic waarop het bericht is ontvangen.
|
||||
print(f"Message received on topic {message.topic}: {data}")
|
||||
|
||||
# Het hoofdgedeelte van het script dat wordt uitgevoerd als het script direct wordt aangeroepen.
|
||||
if __name__ == "__main__":
|
||||
# Definieer het MQTT-topic waarop we willen abonneren, in dit geval bodemtemperatuur.
|
||||
topic = "goodgarden/soil_temperature"
|
||||
# Start het abonneren op het opgegeven topic met de on_message functie als de callback.
|
||||
subscribe.callback(on_message, topic)
|
||||
460
src/py/static/css/style.css
Normal file
460
src/py/static/css/style.css
Normal file
@@ -0,0 +1,460 @@
|
||||
@import url("https://fonts.googleapis.com/css2?family=Akaya+Kanadaka&display=swap");
|
||||
@import url("https://fonts.googleapis.com/css2?family=Afacad:ital,wght@0,400..700;1,400..700&display=swap");
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5 {
|
||||
font-family: "Akaya Kanadaka", system-ui;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
p,
|
||||
td {
|
||||
font-family: "Afacad", sans-serif;
|
||||
color: black;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
body {
|
||||
background: linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.5)), url("../images/achtergrond.webp");
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
font-family: "Afacad", sans-serif;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
margin: 0;
|
||||
}
|
||||
body .mainContainer {
|
||||
width: 85vw;
|
||||
height: 38rem;
|
||||
background-color: rgba(255, 255, 255, 0.85);
|
||||
border-radius: 40px;
|
||||
padding: 2rem;
|
||||
}
|
||||
body .mainContainer .goodgarden-logo {
|
||||
position: absolute;
|
||||
width: 10vw;
|
||||
left: 50%;
|
||||
top: 4.1rem;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
body .mainContainer .informatie-kas-main-container {
|
||||
display: grid;
|
||||
grid-template-columns: 5fr 7fr;
|
||||
}
|
||||
body .mainContainer .mainBorder {
|
||||
padding: 1.25rem 1.5rem;
|
||||
padding: 1rem 0;
|
||||
height: 35rem;
|
||||
border: solid 5px rgb(171, 211, 174);
|
||||
border-radius: 40px;
|
||||
}
|
||||
body .mainContainer .mainBorder .pagina-titel {
|
||||
font-size: 2rem;
|
||||
margin-left: 1.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
body .mainContainer .mainBorder #sectie-1 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
padding: 0 2.5rem 0 1rem;
|
||||
position: relative;
|
||||
}
|
||||
body .mainContainer .mainBorder #sectie-1 h1 {
|
||||
background-color: green;
|
||||
}
|
||||
body .mainContainer .mainBorder #sectie-1 .parent-algemeen-overzicht {
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
|
||||
border-radius: 40px;
|
||||
padding: 1rem;
|
||||
background-color: white;
|
||||
}
|
||||
body .mainContainer .mainBorder #sectie-1 .parent-algemeen-overzicht .algemeen-overzicht {
|
||||
border: solid 2px rgb(171, 211, 174);
|
||||
border-radius: 35px;
|
||||
font-size: 1.25rem;
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
body .mainContainer .mainBorder #sectie-1 .parent-algemeen-overzicht .algemeen-overzicht .table-informatie-kas {
|
||||
width: 100%;
|
||||
}
|
||||
body .mainContainer .mainBorder #sectie-1 .parent-algemeen-overzicht .algemeen-overzicht .table-informatie-kas .tr-informatie-kas {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
text-align: left;
|
||||
}
|
||||
body .mainContainer .mainBorder #sectie-1 .grafiek {
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
|
||||
border-radius: 40px;
|
||||
padding: 1rem;
|
||||
position: relative;
|
||||
background-color: white;
|
||||
}
|
||||
body .mainContainer .mainBorder #sectie-1 .grafiek .grafiek-innerbox {
|
||||
border: solid 2px rgb(171, 211, 174);
|
||||
border-radius: 35px;
|
||||
font-size: 1.25rem;
|
||||
padding: 0 1rem 2.5rem;
|
||||
height: 225px;
|
||||
position: relative;
|
||||
}
|
||||
body .mainContainer .mainBorder #sectie-1 .grafiek .grafiek-innerbox h2 {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
body .mainContainer .mainBorder #sectie-1 .grafiek .grafiek-innerbox canvas {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
body .mainContainer .mainBorder .content {
|
||||
display: grid;
|
||||
grid-template-columns: 3fr 1fr 3fr;
|
||||
height: 100%;
|
||||
}
|
||||
body .mainContainer .mainBorder .content .kant-links {
|
||||
grid-column: 1;
|
||||
}
|
||||
body .mainContainer .mainBorder .content .kant-links #planten {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
body .mainContainer .mainBorder .content .kant-links #planten td article {
|
||||
height: 7rem;
|
||||
width: 10rem;
|
||||
padding: 0.6rem;
|
||||
margin: 0.1rem;
|
||||
margin-left: 2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: solid 3px rgb(171, 211, 174);
|
||||
border-radius: 40px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
body .mainContainer .mainBorder .content .kant-links #planten td article #toevoegen {
|
||||
height: 5rem;
|
||||
width: 5rem;
|
||||
}
|
||||
body .mainContainer .mainBorder .content .kant-links #planten td article h2 {
|
||||
color: gray;
|
||||
}
|
||||
body .mainContainer .mainBorder .content .kant-links #planten td article:hover {
|
||||
background-color: lightgray;
|
||||
cursor: pointer;
|
||||
}
|
||||
body .mainContainer .mainBorder .content .kant-rechts {
|
||||
grid-column: 3;
|
||||
}
|
||||
body .mainContainer .mainBorder .content .kant-rechts #metingen {
|
||||
border: solid 3px rgb(171, 211, 174);
|
||||
border-radius: 40px;
|
||||
}
|
||||
body .mainContainer .mainBorder .content .kant-rechts #metingen #main-waardes {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0.5rem;
|
||||
padding-bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
body .mainContainer .mainBorder .content .kant-rechts #metingen #main-waardes table {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
body .mainContainer .mainBorder .grid-column-2 {
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
|
||||
border-radius: 40px;
|
||||
padding: 1rem;
|
||||
margin: 3.25rem 1rem 1.25rem 1rem;
|
||||
background-color: white;
|
||||
}
|
||||
body .mainContainer .mainBorder .grid-column-2 .grid-2-child {
|
||||
border: solid 2px rgb(171, 211, 174);
|
||||
border-radius: 35px;
|
||||
height: 100%;
|
||||
}
|
||||
body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table {
|
||||
padding: 1.5rem 2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 2.5rem;
|
||||
justify-content: space-around;
|
||||
height: 90%;
|
||||
}
|
||||
body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table table tr td {
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-1 tr td {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-2 {
|
||||
position: relative;
|
||||
}
|
||||
body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-2::after, body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-2::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 1px;
|
||||
width: 90%;
|
||||
background: black;
|
||||
}
|
||||
body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-2::after {
|
||||
bottom: -20px;
|
||||
}
|
||||
body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-2::before {
|
||||
top: -20px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
border: solid 1px rgb(171, 211, 174);
|
||||
border-radius: 5px;
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: white;
|
||||
padding: 1.25rem;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
width: 30vw;
|
||||
height: auto;
|
||||
border: solid 2px #abd3ae;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.modal #plant-id {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.modal .close {
|
||||
color: #aaa;
|
||||
float: right;
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
margin-top: -35px;
|
||||
}
|
||||
|
||||
.modal .close:hover,
|
||||
.modal .close:active {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#myModal select,
|
||||
#myModal input {
|
||||
width: calc(100% - 20px);
|
||||
padding: 10px;
|
||||
margin-bottom: 15px;
|
||||
border: 2px solid #abd3ae;
|
||||
border-radius: 5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#myModal .knop {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#myModal button {
|
||||
width: 48%;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
#myModal .knop-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
#myModal .knop-container input,
|
||||
#myModal .knop-container button {
|
||||
flex: 1;
|
||||
margin: 0 5px;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#myModal input[type=text],
|
||||
#myModal select {
|
||||
border: 2px solid #abd3ae;
|
||||
padding: 10px;
|
||||
border-radius: 17px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#myModal input[type=submit],
|
||||
#myModal button {
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#myModal input[type=submit] {
|
||||
background: linear-gradient(45deg, #abd3ae, #6ebf7d);
|
||||
}
|
||||
|
||||
#myModal button {
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.toevoeging {
|
||||
background: linear-gradient(45deg, #abd3ae, #2ecc71);
|
||||
}
|
||||
|
||||
.annulatie-knop {
|
||||
background: linear-gradient(45deg, #ffcc00, #ff6600);
|
||||
}
|
||||
|
||||
.switch-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.switch-wrapper {
|
||||
margin-left: 20vw;
|
||||
}
|
||||
|
||||
.switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
height: 25px;
|
||||
}
|
||||
|
||||
.switch input[type=checkbox] {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
border-radius: 34px;
|
||||
transition: 0.4s;
|
||||
}
|
||||
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
left: 3px;
|
||||
bottom: 2px;
|
||||
background-color: white;
|
||||
border-radius: 50%;
|
||||
transition: 0.4s;
|
||||
}
|
||||
|
||||
input:checked + .slider {
|
||||
background-color: rgb(171, 211, 174);
|
||||
}
|
||||
|
||||
input:checked + .slider:before {
|
||||
transform: translateX(23px);
|
||||
}
|
||||
|
||||
.rechterkant {
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
}
|
||||
|
||||
.plant-container,
|
||||
#modalButton {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.switch-container {
|
||||
position: absolute;
|
||||
right: 75px;
|
||||
}
|
||||
|
||||
.pagina-container {
|
||||
position: relative;
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.close-button:hover {
|
||||
background-color: rgb(171, 211, 174); /* Aangepaste hover kleur */
|
||||
color: white; /* Tekstkleur wit op hover voor betere zichtbaarheid */
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.close-button {
|
||||
position: absolute;
|
||||
top: -90px;
|
||||
right: -35px;
|
||||
transform: translate(100%, 0%);
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background-color: white;
|
||||
color: rgb(171, 211, 174);
|
||||
border-radius: 50%; /* Aangepast voor perfecte cirkel */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
font-size: 50px;
|
||||
border: solid rgb(171, 211, 174) 2px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
position: absolute;
|
||||
top: -90px;
|
||||
right: -25px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background-color: white;
|
||||
color: rgb(171, 211, 174);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
font-size: 35px;
|
||||
border: solid rgb(171, 211, 174) 2px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.back-button:hover {
|
||||
background-color: rgb(171, 211, 174);
|
||||
color: white;
|
||||
}/*# sourceMappingURL=style.css.map */
|
||||
1
src/py/static/css/style.css.map
Normal file
1
src/py/static/css/style.css.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["style.scss","style.css"],"names":[],"mappings":"AAGQ,mFAAA;AACA,2GAAA;AAgCR;;;;;EAME,wCApCY;EAqCZ,SAAA;AClCF;;ADqCA;;EAGE,iCAzCU;EA0CV,YAAA;ACnCF;;ADsCA;EAEE,qBAAA;ACpCF;;ADuCA;EAEE,kHAAA;EACA,4BAAA;EACA,sBAAA;EACA,2BAAA;EACA,iCAxDU;EAyDV,aAAA;EACA,uBAAA;EACA,mBAAA;EACA,aAAA;EACA,SAAA;ACrCF;ADuCE;EAEE,WAAA;EACA,aAAA;EACA,2CAAA;EACA,mBAAA;EACA,aAAA;ACtCJ;ADwCI;EAEE,kBAAA;EACA,WAAA;EACA,SAAA;EACA,WAAA;EACA,2BAAA;ACvCN;AD0CI;EAEE,aAAA;EACA,8BAAA;ACzCN;AD4CI;EAEE,uBAAA;EACA,eAAA;EACA,aAAA;EACA,oCAAA;EACA,mBAAA;AC3CN;AD6CM;EAEE,eAAA;EACA,mBAAA;EACA,mBAAA;AC5CR;AD+CM;EAEE,aAAA;EACA,sBAAA;EACA,YAAA;EACA,wBAAA;EACA,kBAAA;AC9CR;ADgDQ;EAEE,uBAAA;AC/CV;ADkDQ;EAnGN,2CAAA;EAKA,mBAAA;EAkGQ,aAAA;EAEA,uBAAA;AClDV;ADoDU;EAhHR,oCAAA;EAeA,mBAAA;EAqGU,kBAAA;EACA,oBAAA;ACnDZ;ADqDY;EAEE,WAAA;ACpDd;ADsDc;EAEE,aAAA;EACA,8BAAA;EACA,gBAAA;ACrDhB;AD2DQ;EAhIN,2CAAA;EAKA,mBAAA;EA+HQ,aAAA;EACA,kBAAA;EACA,uBAAA;AC1DV;AD4DU;EA7IR,oCAAA;EAeA,mBAAA;EAkIU,kBAAA;EACA,sBAAA;EACA,aAAA;EACA,kBAAA;AC3DZ;AD6DY;EAEE,kBAAA;EACA,SAAA;EACA,2BAAA;AC5Dd;AD+DY;EAGE,kBAAA;EACA,QAAA;EACA,SAAA;EACA,gCAAA;AC/Dd;ADqEM;EAEE,aAAA;EACA,kCAAA;EACA,YAAA;ACpER;ADwEU;EAEE,cAAA;ACvEZ;ADyEY;EAEE,WAAA;EACA,yBAAA;ACxEd;AD4EgB;EAEE,YAAA;EACA,YAAA;EACA,eAAA;EACA,cAAA;EACA,iBAAA;EACA,aAAA;EACA,sBAAA;EACA,uBAAA;EACA,mBAAA;EACA,oCAAA;EACA,mBAAA;EACA,wCAAA;AC3ElB;AD6EkB;EAEE,YAAA;EACA,WAAA;AC5EpB;AD+EkB;EAEE,WAAA;AC9EpB;ADiFkB;EAEE,2BAAA;EACA,eAAA;AChFpB;ADuFU;EAEE,cAAA;ACtFZ;ADyFY;EAEE,oCAAA;EACA,mBAAA;ACxFd;AD0Fc;EAEE,aAAA;EACA,8BAAA;EACA,eAAA;EACA,iBAAA;EACA,WAAA;ACzFhB;AD2FgB;EAEE,aAAA;EACA,8BAAA;EACA,WAAA;AC1FlB;ADkGM;EAzPJ,2CAAA;EAKA,mBAAA;EAwPM,aAAA;EACA,iCAAA;EACA,uBAAA;ACjGR;ADmGQ;EAtQN,oCAAA;EAeA,mBAAA;EA2PQ,YAAA;AClGV;ADoGU;EAEE,oBAAA;EACA,aAAA;EACA,sBAAA;EACA,oBAAA;EACA,WAAA;EACA,6BAAA;EACA,WAAA;ACnGZ;ADyGgB;EAEE,kBAAA;ACxGlB;ADiHgB;EAEE,kBAAA;AChHlB;ADqHY;EAEE,kBAAA;ACpHd;ADsHc;EAGE,WAAA;EACA,kBAAA;EACA,OAAA;EACA,QAAA;EACA,WAAA;EACA,UAAA;EACA,iBAAA;ACtHhB;ADyHc;EAEE,aAAA;ACxHhB;AD2Hc;EAEE,UAAA;AC1HhB;;ADoIA;EACE,aAAA;EACA,uBAAA;EACA,oCAAA;EACA,kBAAA;EACA,UAAA;EACA,cAAA;ACjIF;;ADoIA;EACE,aAAA;EACA,eAAA;EACA,YAAA;EACA,SAAA;EACA,QAAA;EACA,gCAAA;EACA,iBAAA;EACA,gBAAA;EACA,wCAAA;EACA,WAAA;EACA,YAAA;EACA,yBAAA;EACA,mBAAA;ACjIF;;ADoIA;EAEE,iBAAA;AClIF;;ADqIA;EACE,WAAA;EACA,YAAA;EACA,eAAA;EACA,iBAAA;EACA,iBAAA;AClIF;;ADoIA;;EAEE,YAAA;EACA,qBAAA;EACA,eAAA;ACjIF;;ADoIA;;EAEE,wBAAA;EACA,aAAA;EACA,mBAAA;EACA,yBAAA;EACA,kBAAA;EACA,sBAAA;ACjIF;;ADoIA;EACE,aAAA;EACA,8BAAA;ACjIF;;ADoIA;EACE,UAAA;EACA,aAAA;EACA,sBAAA;EACA,YAAA;ACjIF;;ADoIA;EACE,aAAA;EACA,8BAAA;EACA,gBAAA;ACjIF;;ADoIA;;EAEE,OAAA;EACA,aAAA;EACA,aAAA;EACA,sBAAA;ACjIF;;ADoIA;;EAEE,yBAAA;EACA,aAAA;EACA,mBAAA;EACA,sBAAA;ACjIF;;ADoIA;;EAEE,WAAA;EACA,YAAA;EACA,mBAAA;EACA,eAAA;ACjIF;;ADoIA;EACE,oDAAA;ACjIF;;ADoIA;EACE,uBAAA;EACA,YAAA;ACjIF;;ADoIA;EACE,oDAAA;ACjIF;;ADoIA;EACE,oDAAA;ACjIF;;ADoIA;EACE,aAAA;EACA,mBAAA;EACA,yBAAA;ACjIF;;ADoIA;EACE,iBAAA;ACjIF;;ADoIA;EACE,kBAAA;EACA,qBAAA;EACA,WAAA;EACA,YAAA;ACjIF;;ADoIA;EACE,UAAA;EACA,QAAA;EACA,SAAA;ACjIF;;ADoIA;EACE,kBAAA;EACA,eAAA;EACA,MAAA;EACA,OAAA;EACA,QAAA;EACA,SAAA;EACA,sBAAA;EACA,mBAAA;EACA,gBAAA;ACjIF;;ADoIA;EACE,kBAAA;EACA,WAAA;EACA,YAAA;EACA,WAAA;EACA,SAAA;EACA,WAAA;EACA,uBAAA;EACA,kBAAA;EACA,gBAAA;ACjIF;;ADoIA;EACE,oCAhgBc;AC+XhB;;ADoIA;EACE,2BAAA;ACjIF;;ADmIA;EACE,aAAA;EACA,oBAAA;AChIF;;ADmIE;;EAGE,uBAAA;ACjIJ;;ADoIE;EACE,kBAAA;EACA,WAAA;ACjIJ;;ADmIA;EACE,kBAAA;EACA,gBAAA;AChIF;;ADmIA;EACE,oCA3hBc,EA2hBoB,2BAAA;EAClC,YAAA,EAAA,sDAAA;AChIF;;ADmIA;EACE,kBAAA;EACA,gBAAA;AChIF;;ADmIA;EAEE,kBAAA;EACA,UAAA;EACA,YAAA;EACA,8BAAA;EACA,WAAA;EACA,YAAA;EACA,uBAAA;EACA,yBA7iBc;EA8iBd,kBAAA,EAAA,mCAAA;EACA,aAAA;EACA,uBAAA;EACA,mBAAA;EACA,eAAA;EACA,eAAA;EACA,oCAAA;EACA,iBAAA;ACjIF;;ADoIA;EACE,kBAAA;EACA,UAAA;EACA,YAAA;EACA,WAAA;EACA,YAAA;EACA,uBAAA;EACA,yBA/jBc;EAgkBd,kBAAA;EACA,aAAA;EACA,uBAAA;EACA,mBAAA;EACA,eAAA;EACA,eAAA;EACA,oCAAA;EACA,iBAAA;ACjIF;;ADoIA;EACE,oCA3kBc;EA4kBd,YAAA;ACjIF","file":"style.css"}
|
||||
592
src/py/static/css/style.scss
Normal file
592
src/py/static/css/style.scss
Normal file
@@ -0,0 +1,592 @@
|
||||
$primary-color: rgb(171, 211, 174);
|
||||
$secondary-color: rgb(143, 188, 143);
|
||||
|
||||
$titel-color: rgb(46, 86, 81);
|
||||
|
||||
@import url("https://fonts.googleapis.com/css2?family=Akaya+Kanadaka&display=swap");
|
||||
@import url("https://fonts.googleapis.com/css2?family=Afacad:ital,wght@0,400..700;1,400..700&display=swap");
|
||||
|
||||
$font-titels: "Akaya Kanadaka", system-ui;
|
||||
|
||||
$font-text: "Afacad", sans-serif;
|
||||
|
||||
@mixin flexbox-center
|
||||
{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@mixin groene-border
|
||||
{
|
||||
border: solid 2px $primary-color;
|
||||
}
|
||||
|
||||
@mixin box-shadow
|
||||
{
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
@mixin border-radius
|
||||
{
|
||||
border-radius: 40px;
|
||||
}
|
||||
|
||||
@mixin inner-border-radius
|
||||
{
|
||||
border-radius: 35px;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5
|
||||
{
|
||||
font-family: $font-titels;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
p,
|
||||
td
|
||||
{
|
||||
font-family: $font-text;
|
||||
color: black;
|
||||
}
|
||||
|
||||
a
|
||||
{
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
background: linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.5)), url("../images/achtergrond.webp");
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
font-family: $font-text;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
margin: 0;
|
||||
|
||||
.mainContainer
|
||||
{
|
||||
width: 85vw;
|
||||
height: 38rem;
|
||||
background-color: rgb(255, 255, 255, 85%);
|
||||
border-radius: 40px;
|
||||
padding: 2rem;
|
||||
|
||||
.goodgarden-logo
|
||||
{
|
||||
position: absolute;
|
||||
width: 10vw;
|
||||
left: 50%;
|
||||
top: 4.1rem;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.informatie-kas-main-container
|
||||
{
|
||||
display: grid;
|
||||
grid-template-columns: 5fr 7fr;
|
||||
}
|
||||
|
||||
.mainBorder
|
||||
{
|
||||
padding: 1.25rem 1.5rem;
|
||||
padding: 1rem 0;
|
||||
height: 35rem;
|
||||
border: solid 5px $primary-color;
|
||||
border-radius: 40px;
|
||||
|
||||
.pagina-titel
|
||||
{
|
||||
font-size: 2rem;
|
||||
margin-left: 1.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
#sectie-1
|
||||
{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
padding: 0 2.5rem 0 1rem;
|
||||
position: relative;
|
||||
|
||||
h1
|
||||
{
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
.parent-algemeen-overzicht
|
||||
{
|
||||
@include box-shadow;
|
||||
@include border-radius;
|
||||
padding: 1rem;
|
||||
// margin-top: 1rem;
|
||||
background-color: white;
|
||||
|
||||
.algemeen-overzicht
|
||||
{
|
||||
@include groene-border;
|
||||
@include inner-border-radius;
|
||||
font-size: 1.25rem;
|
||||
padding: 0.5rem 1rem;
|
||||
|
||||
.table-informatie-kas
|
||||
{
|
||||
width: 100%;
|
||||
|
||||
.tr-informatie-kas
|
||||
{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.grafiek
|
||||
{
|
||||
@include box-shadow;
|
||||
@include border-radius;
|
||||
padding: 1rem;
|
||||
position: relative;
|
||||
background-color: white;
|
||||
|
||||
.grafiek-innerbox
|
||||
{
|
||||
@include groene-border;
|
||||
@include inner-border-radius;
|
||||
font-size: 1.25rem;
|
||||
padding: 0 1rem 2.5rem;
|
||||
height: 225px;
|
||||
position: relative;
|
||||
|
||||
h2
|
||||
{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
canvas
|
||||
{
|
||||
// Zorgt ervoor dat de grafiek precies in eht midden komt
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content
|
||||
{
|
||||
display: grid;
|
||||
grid-template-columns: 3fr 1fr 3fr;
|
||||
height: 100%;
|
||||
|
||||
.kant
|
||||
{
|
||||
&-links
|
||||
{
|
||||
grid-column: 1;
|
||||
|
||||
#planten
|
||||
{
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
|
||||
td
|
||||
{
|
||||
article
|
||||
{
|
||||
height: 7rem;
|
||||
width: 10rem;
|
||||
padding: 0.6rem;
|
||||
margin: 0.1rem;
|
||||
margin-left: 2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: solid 3px $primary-color;
|
||||
border-radius: 40px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
|
||||
#toevoegen
|
||||
{
|
||||
height: 5rem;
|
||||
width: 5rem;
|
||||
}
|
||||
|
||||
h2
|
||||
{
|
||||
color: gray;
|
||||
}
|
||||
|
||||
&:hover
|
||||
{
|
||||
background-color: lightgray;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-rechts
|
||||
{
|
||||
grid-column: 3;
|
||||
// margin-right: 2rem;
|
||||
|
||||
#metingen
|
||||
{
|
||||
border: solid 3px $primary-color;
|
||||
border-radius: 40px;
|
||||
|
||||
#main-waardes
|
||||
{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0.5rem;
|
||||
padding-bottom: 0;
|
||||
width: 100%;
|
||||
|
||||
table
|
||||
{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.grid-column-2
|
||||
{
|
||||
@include box-shadow;
|
||||
@include border-radius;
|
||||
padding: 1rem;
|
||||
margin: 3.25rem 1rem 1.25rem 1rem;
|
||||
background-color: white;
|
||||
|
||||
.grid-2-child
|
||||
{
|
||||
@include groene-border;
|
||||
@include inner-border-radius;
|
||||
height: 100%;
|
||||
|
||||
.parent-table
|
||||
{
|
||||
padding: 1.5rem 2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 2.5rem;
|
||||
justify-content: space-around;
|
||||
height: 90%;
|
||||
|
||||
table
|
||||
{
|
||||
tr
|
||||
{
|
||||
td
|
||||
{
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.kas-table-1
|
||||
{
|
||||
tr
|
||||
{
|
||||
td
|
||||
{
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.kas-table-2
|
||||
{
|
||||
position: relative;
|
||||
|
||||
&::after,
|
||||
&::before
|
||||
{
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 1px;
|
||||
width: 90%;
|
||||
background: black;
|
||||
}
|
||||
|
||||
&::after
|
||||
{
|
||||
bottom: -20px;
|
||||
}
|
||||
|
||||
&::before
|
||||
{
|
||||
top: -20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.divider {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
border: solid 1px $primary-color;
|
||||
border-radius: 5px;
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: white;
|
||||
padding: 1.25rem;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
width: 30vw;
|
||||
height: auto;
|
||||
border: solid 2px #abd3ae;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.modal #plant-id
|
||||
{
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.modal .close {
|
||||
color: #aaa;
|
||||
float: right;
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
margin-top: -35px;
|
||||
}
|
||||
.modal .close:hover,
|
||||
.modal .close:active {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#myModal select,
|
||||
#myModal input {
|
||||
width: calc(100% - 20px);
|
||||
padding: 10px;
|
||||
margin-bottom: 15px;
|
||||
border: 2px solid #abd3ae;
|
||||
border-radius: 5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#myModal .knop {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#myModal button {
|
||||
width: 48%;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
#myModal .knop-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
#myModal .knop-container input,
|
||||
#myModal .knop-container button {
|
||||
flex: 1;
|
||||
margin: 0 5px;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#myModal input[type="text"],
|
||||
#myModal select {
|
||||
border: 2px solid #abd3ae;
|
||||
padding: 10px;
|
||||
border-radius: 17px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#myModal input[type="submit"],
|
||||
#myModal button {
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#myModal input[type="submit"] {
|
||||
background: linear-gradient(45deg, #abd3ae, #6ebf7d);
|
||||
}
|
||||
|
||||
#myModal button {
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.toevoeging {
|
||||
background: linear-gradient(45deg, #abd3ae, #2ecc71);
|
||||
}
|
||||
|
||||
.annulatie-knop {
|
||||
background: linear-gradient(45deg, #ffcc00, #ff6600);
|
||||
}
|
||||
|
||||
.switch-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.switch-wrapper {
|
||||
margin-left: 20vw; // slider aan rechterkant
|
||||
}
|
||||
|
||||
.switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
height: 25px;
|
||||
}
|
||||
|
||||
.switch input[type="checkbox"] {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
border-radius: 34px;
|
||||
transition: 0.4s;
|
||||
}
|
||||
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
left: 3px;
|
||||
bottom: 2px;
|
||||
background-color: white;
|
||||
border-radius: 50%;
|
||||
transition: 0.4s;
|
||||
}
|
||||
|
||||
input:checked + .slider {
|
||||
background-color: $primary-color;
|
||||
}
|
||||
|
||||
input:checked + .slider:before {
|
||||
transform: translateX(23px);
|
||||
}
|
||||
.rechterkant {
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
}
|
||||
|
||||
.plant-container,
|
||||
#modalButton
|
||||
{
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.switch-container {
|
||||
position: absolute;
|
||||
right: 75px;
|
||||
}
|
||||
.pagina-container {
|
||||
position: relative;
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.close-button:hover {
|
||||
background-color: $primary-color; /* Aangepaste hover kleur */
|
||||
color: white; /* Tekstkleur wit op hover voor betere zichtbaarheid */
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.close-button
|
||||
{
|
||||
position: absolute;
|
||||
top: -90px;
|
||||
right: -35px;
|
||||
transform: translate(100%, 0%);
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background-color: white;
|
||||
color: $primary-color;
|
||||
border-radius: 50%; /* Aangepast voor perfecte cirkel */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
font-size: 50px;
|
||||
border: solid $primary-color 2px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
position: absolute;
|
||||
top: -90px;
|
||||
right: -25px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background-color: white;
|
||||
color: $primary-color;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
font-size: 35px;
|
||||
border: solid $primary-color 2px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.back-button:hover {
|
||||
background-color: $primary-color;
|
||||
color: white
|
||||
}
|
||||
BIN
src/py/static/images/Icon_awesome-apple-alt.png
Normal file
BIN
src/py/static/images/Icon_awesome-apple-alt.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/py/static/images/achtergrond.webp
Normal file
BIN
src/py/static/images/achtergrond.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
2
src/py/static/images/desktop.ini
Normal file
2
src/py/static/images/desktop.ini
Normal file
@@ -0,0 +1,2 @@
|
||||
[LocalizedFileNames]
|
||||
achtergrond.webp=@achtergrond.webp,0
|
||||
BIN
src/py/static/images/logo.png
Normal file
BIN
src/py/static/images/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
BIN
src/py/static/images/plus.png
Normal file
BIN
src/py/static/images/plus.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src/py/static/images/warning-logo.png
Normal file
BIN
src/py/static/images/warning-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
160
src/py/static/js/grafiek.js
Normal file
160
src/py/static/js/grafiek.js
Normal file
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
* Class to handle the creation and manipulation of line charts on a canvas.
|
||||
*/
|
||||
class LineChart
|
||||
{
|
||||
/**
|
||||
* Creates an instance of LineChart.
|
||||
* @param {string} canvasId - The ID of the canvas element where the chart will be drawn.
|
||||
*/
|
||||
constructor(canvasId)
|
||||
{
|
||||
this.canvas = document.getElementById(canvasId);
|
||||
if (this.canvas)
|
||||
{
|
||||
this.ctx = this.canvas.getContext("2d");
|
||||
}
|
||||
this.padding = 35; // Default padding around the graph
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the entire canvas, preparing it for a new drawing.
|
||||
*/
|
||||
clearCanvas()
|
||||
{
|
||||
if (this.canvas)
|
||||
{
|
||||
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a line chart on the canvas using the provided data.
|
||||
* @param {Array<string>} xLabels - Labels for the x-axis.
|
||||
* @param {Array<number>} data - Data points for the chart, one per x-label.
|
||||
* @param {Array<number|string>} [yLabels=["", 10, 15, 20, 25, 30, 35, 40]] - Labels for the y-axis.
|
||||
*/
|
||||
drawChart(xLabels, data, yLabels = [0, 5, 10, 15, 20, 25, 30, 35, 40])
|
||||
{
|
||||
if (!this.canvas)
|
||||
{
|
||||
return; // Exit if canvas is not initialized
|
||||
}
|
||||
|
||||
this.clearCanvas();
|
||||
const graphWidth = this.canvas.width - this.padding * 2;
|
||||
const graphHeight = this.canvas.height - this.padding * 2;
|
||||
const maxValue = Math.max(...yLabels);
|
||||
const graphScale = graphHeight / maxValue;
|
||||
|
||||
// Draw the axes
|
||||
this.ctx.strokeStyle = "rgb(46, 86, 81)";
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(this.padding, this.padding);
|
||||
this.ctx.lineTo(this.padding, this.canvas.height - this.padding);
|
||||
this.ctx.lineTo(this.canvas.width - this.padding, this.canvas.height - this.padding);
|
||||
this.ctx.stroke();
|
||||
|
||||
// Calculate increments for plotting points
|
||||
const xIncrement = graphWidth / (xLabels.length - 1);
|
||||
|
||||
// Plot the data points and draw the line
|
||||
this.ctx.strokeStyle = "rgb(191, 215, 182)";
|
||||
this.ctx.beginPath();
|
||||
let xPos = this.padding;
|
||||
let yPos = this.canvas.height - this.padding - (data[0] * graphScale);
|
||||
this.ctx.moveTo(xPos, yPos);
|
||||
|
||||
for (let i = 1; i < data.length; i++)
|
||||
{
|
||||
xPos = this.padding + i * xIncrement;
|
||||
yPos = this.canvas.height - this.padding - (data[i] * graphScale);
|
||||
this.ctx.lineTo(xPos, yPos);
|
||||
}
|
||||
this.ctx.stroke();
|
||||
|
||||
// Draw points on the line and temperature labels
|
||||
this.ctx.fillStyle = "rgb(46, 86, 81)";
|
||||
for (let i = 0; i < data.length; i++)
|
||||
{
|
||||
xPos = this.padding + i * xIncrement;
|
||||
yPos = this.canvas.height - this.padding - (data[i] * graphScale);
|
||||
|
||||
// Draw point for each data entry
|
||||
this.ctx.beginPath();
|
||||
this.ctx.arc(xPos, yPos, 3, 0, Math.PI * 2);
|
||||
this.ctx.fill();
|
||||
|
||||
// Draw temperature values beside each point
|
||||
this.ctx.fillStyle = "rgb(46, 86, 81)";
|
||||
this.ctx.fillText(data[i] + "°C", xPos + 10, yPos - 10);
|
||||
}
|
||||
|
||||
// Draw y-axis labels
|
||||
this.ctx.textAlign = "right";
|
||||
this.ctx.textBaseline = "middle"; // Center the text vertically
|
||||
for (let i = 0; i < yLabels.length; i++)
|
||||
{
|
||||
const label = yLabels[i];
|
||||
// Calculate the y position for the label
|
||||
yPos = this.canvas.height - this.padding - (label * graphScale);
|
||||
this.ctx.fillText(label, this.padding - 10, yPos);
|
||||
}
|
||||
|
||||
// Draw x-axis labels
|
||||
this.ctx.textAlign = "center";
|
||||
this.ctx.textBaseline = "alphabetic"; // Default vertical alignment for text
|
||||
for (let i = 0; i < xLabels.length; i++)
|
||||
{
|
||||
xPos = this.padding + i * xIncrement;
|
||||
if (xLabels[i] !== "")
|
||||
{
|
||||
this.ctx.fillText(xLabels[i], xPos, this.canvas.height - this.padding + 20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Fetches weather data from an API and draws a line chart with the fetched data.
|
||||
* @param {LineChart} chart - The LineChart instance to draw on.
|
||||
* @param {string} apiUrl - The URL to fetch the weather data from.
|
||||
*/
|
||||
function fetchWeatherDataAndDrawChart(chart, apiUrl) {
|
||||
fetch(apiUrl)
|
||||
.then(response => response.ok ? response.json() : Promise.reject('Network response was not ok.'))
|
||||
.then(data => {
|
||||
const dates = data.weather_forecast.map(item => {
|
||||
// Split the date string
|
||||
const [day, month, year] = item.dag.split('-').map(Number);
|
||||
|
||||
// Create a new Date object (Month is 0-based in JavaScript)
|
||||
const date = new Date(year, month - 1, day);
|
||||
|
||||
// Map days to Dutch weekdays
|
||||
const weekdays = ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'];
|
||||
const weekday = weekdays[date.getDay()];
|
||||
|
||||
// Format the date string
|
||||
// return `${weekday} ${String(day).padStart(2, '0')}-${String(month).padStart(2, '0')}`;
|
||||
return `${weekday}`;
|
||||
});
|
||||
|
||||
const temperatures = data.weather_forecast.map(item => item.max_temp);
|
||||
|
||||
// Draw the chart with the transformed dates and temperatures
|
||||
chart.drawChart(dates, temperatures);
|
||||
})
|
||||
.catch(error => console.error('There was a problem with the fetch operation:', error));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Utility function to return the weekday in Dutch
|
||||
function getWeekday(date) {
|
||||
const options = { weekday: 'short' };
|
||||
return date.toLocaleDateString('nl-NL', options);
|
||||
}
|
||||
|
||||
const myChart = new LineChart("myCanvas");
|
||||
fetchWeatherDataAndDrawChart(myChart, "http://127.0.0.1:5000/weather");
|
||||
324
src/py/static/js/main.js
Normal file
324
src/py/static/js/main.js
Normal file
@@ -0,0 +1,324 @@
|
||||
// Importeer de ipcRenderer-module van Electron voor communicatie tussen processen.
|
||||
// Dit maakt het mogelijk voor renderer-processen (webpagina's) om berichten te verzenden naar het hoofdproces.
|
||||
const { ipcRenderer } = require("electron");
|
||||
|
||||
// Importeer Axios voor het maken van HTTP-verzoeken
|
||||
const axios = require('axios');
|
||||
/*⠀⠀⠀⢸⣦⡀⠀⠀⠀⠀⢀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⢸⣏⠻⣶⣤⡶⢾⡿⠁⠀⢠⣄⡀⢀⣴⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⣀⣼⠷⠀⠀⠁⢀⣿⠃⠀⠀⢀⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠴⣾⣯⣅⣀⠀⠀⠀⠈⢻⣦⡀⠒⠻⠿⣿⡿⠿⠓⠂⠀⠀⢀⡇⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠉⢻⡇⣤⣾⣿⣷⣿⣿⣤⠀⠀⣿⠁⠀⠀⠀⢀⣴⣿⣿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠸⣿⡿⠏⠀⢀⠀⠀⠿⣶⣤⣤⣤⣄⣀⣴⣿⡿⢻⣿⡆⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠟⠁⠀⢀⣼⠀⠀⠀⠹⣿⣟⠿⠿⠿⡿⠋⠀⠘⣿⣇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⢳⣶⣶⣿⣿⣇⣀⠀⠀⠙⣿⣆⠀⠀⠀⠀⠀⠀⠛⠿⣿⣦⣤⣀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⣹⣿⣿⣿⣿⠿⠋⠁⠀⣹⣿⠳⠀⠀⠀⠀⠀⠀⢀⣠⣽⣿⡿⠟⠃
|
||||
⠀⠀⠀⠀⠀⢰⠿⠛⠻⢿⡇⠀⠀⠀⣰⣿⠏⠀⠀⢀⠀⠀⠀⣾⣿⠟⠋⠁⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠀⠀⣰⣿⣿⣾⣿⠿⢿⣷⣀⢀⣿⡇⠁⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠉⠁⠀⠀⠀⠀⠙⢿⣿⣿⠇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀*/
|
||||
function closeApplication()
|
||||
{
|
||||
if (confirm("Weet je zeker dat je de applicatie wilt sluiten?"))
|
||||
{
|
||||
window.close();
|
||||
}
|
||||
}
|
||||
/*⠀⠀⠀⢸⣦⡀⠀⠀⠀⠀⢀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⢸⣏⠻⣶⣤⡶⢾⡿⠁⠀⢠⣄⡀⢀⣴⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⣀⣼⠷⠀⠀⠁⢀⣿⠃⠀⠀⢀⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠴⣾⣯⣅⣀⠀⠀⠀⠈⢻⣦⡀⠒⠻⠿⣿⡿⠿⠓⠂⠀⠀⢀⡇⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠉⢻⡇⣤⣾⣿⣷⣿⣿⣤⠀⠀⣿⠁⠀⠀⠀⢀⣴⣿⣿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠸⣿⡿⠏⠀⢀⠀⠀⠿⣶⣤⣤⣤⣄⣀⣴⣿⡿⢻⣿⡆⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠟⠁⠀⢀⣼⠀⠀⠀⠹⣿⣟⠿⠿⠿⡿⠋⠀⠘⣿⣇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⢳⣶⣶⣿⣿⣇⣀⠀⠀⠙⣿⣆⠀⠀⠀⠀⠀⠀⠛⠿⣿⣦⣤⣀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⣹⣿⣿⣿⣿⠿⠋⠁⠀⣹⣿⠳⠀⠀⠀⠀⠀⠀⢀⣠⣽⣿⡿⠟⠃
|
||||
⠀⠀⠀⠀⠀⢰⠿⠛⠻⢿⡇⠀⠀⠀⣰⣿⠏⠀⠀⢀⠀⠀⠀⣾⣿⠟⠋⠁⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠀⠀⣰⣿⣿⣾⣿⠿⢿⣷⣀⢀⣿⡇⠁⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠉⠁⠀⠀⠀⠀⠙⢿⣿⣿⠇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀*/
|
||||
/**
|
||||
* Functie om een modaal venster te openen.
|
||||
* Deze functie stelt event listeners in voor het openen en sluiten van de modaal.
|
||||
*/
|
||||
function openModal()
|
||||
{
|
||||
// Verkrijg de elementen voor de modaal, de open-knop en de sluit-knop op basis van hun ID of klasse.
|
||||
const modal = document.getElementById("myModal");
|
||||
const button = document.getElementById("modalButton");
|
||||
const close = document.getElementsByClassName("close")[0];
|
||||
|
||||
// Controleer of de elementen bestaan om fouten te voorkomen.
|
||||
if (modal && button)
|
||||
{
|
||||
// Toon de modaal wanneer op de knop wordt geklikt.
|
||||
button.onclick = function ()
|
||||
{
|
||||
modal.style.display = "block";
|
||||
}
|
||||
|
||||
// Sluit de modaal wanneer op het 'sluiten' icoon wordt geklikt.
|
||||
close.onclick = function ()
|
||||
{
|
||||
modal.style.display = "none";
|
||||
}
|
||||
|
||||
// Sluit de modaal wanneer buiten de modaal wordt geklikt.
|
||||
window.onclick = function (event)
|
||||
{
|
||||
if (event.target == modal)
|
||||
{
|
||||
modal.style.display = "none";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Call openModal when DOM content is loaded
|
||||
openModal();
|
||||
/*⠀⠀⠀⢸⣦⡀⠀⠀⠀⠀⢀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⢸⣏⠻⣶⣤⡶⢾⡿⠁⠀⢠⣄⡀⢀⣴⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⣀⣼⠷⠀⠀⠁⢀⣿⠃⠀⠀⢀⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠴⣾⣯⣅⣀⠀⠀⠀⠈⢻⣦⡀⠒⠻⠿⣿⡿⠿⠓⠂⠀⠀⢀⡇⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠉⢻⡇⣤⣾⣿⣷⣿⣿⣤⠀⠀⣿⠁⠀⠀⠀⢀⣴⣿⣿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠸⣿⡿⠏⠀⢀⠀⠀⠿⣶⣤⣤⣤⣄⣀⣴⣿⡿⢻⣿⡆⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠟⠁⠀⢀⣼⠀⠀⠀⠹⣿⣟⠿⠿⠿⡿⠋⠀⠘⣿⣇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⢳⣶⣶⣿⣿⣇⣀⠀⠀⠙⣿⣆⠀⠀⠀⠀⠀⠀⠛⠿⣿⣦⣤⣀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⣹⣿⣿⣿⣿⠿⠋⠁⠀⣹⣿⠳⠀⠀⠀⠀⠀⠀⢀⣠⣽⣿⡿⠟⠃
|
||||
⠀⠀⠀⠀⠀⢰⠿⠛⠻⢿⡇⠀⠀⠀⣰⣿⠏⠀⠀⢀⠀⠀⠀⣾⣿⠟⠋⠁⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠀⠀⣰⣿⣿⣾⣿⠿⢿⣷⣀⢀⣿⡇⠁⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠉⠁⠀⠀⠀⠀⠙⢿⣿⣿⠇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀*/
|
||||
/**
|
||||
* *WAT IS DIT, WERKT HET? */
|
||||
|
||||
|
||||
// Send a message to the main process to execute the Python script
|
||||
ipcRenderer.send('run-python-script', ['some', 'arguments']);
|
||||
|
||||
ipcRenderer.on('python-script-response', (event, pythonData) =>
|
||||
{
|
||||
if (pythonData === 'error')
|
||||
{
|
||||
console.error('An error occurred while retrieving data from Python');
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update HTML elements with data received from Python
|
||||
document.getElementById('bodem-temperatuur').textContent = pythonData.bodemTemperatuur; // Adjust the property based on your actual Python response
|
||||
}
|
||||
});
|
||||
|
||||
// Listen for updates to HTML data from the main process
|
||||
ipcRenderer.on('update-html-data', (event, data) =>
|
||||
{
|
||||
// Update the HTML with the received data
|
||||
document.getElementById('batteryVoltage').innerText = data.batteryVoltage;
|
||||
// Add similar lines for other data fields
|
||||
});
|
||||
|
||||
// Trigger an event to request data update
|
||||
ipcRenderer.send('request-update-data');
|
||||
/*⠀⠀⠀⢸⣦⡀⠀⠀⠀⠀⢀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⢸⣏⠻⣶⣤⡶⢾⡿⠁⠀⢠⣄⡀⢀⣴⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⣀⣼⠷⠀⠀⠁⢀⣿⠃⠀⠀⢀⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠴⣾⣯⣅⣀⠀⠀⠀⠈⢻⣦⡀⠒⠻⠿⣿⡿⠿⠓⠂⠀⠀⢀⡇⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠉⢻⡇⣤⣾⣿⣷⣿⣿⣤⠀⠀⣿⠁⠀⠀⠀⢀⣴⣿⣿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠸⣿⡿⠏⠀⢀⠀⠀⠿⣶⣤⣤⣤⣄⣀⣴⣿⡿⢻⣿⡆⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠟⠁⠀⢀⣼⠀⠀⠀⠹⣿⣟⠿⠿⠿⡿⠋⠀⠘⣿⣇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⢳⣶⣶⣿⣿⣇⣀⠀⠀⠙⣿⣆⠀⠀⠀⠀⠀⠀⠛⠿⣿⣦⣤⣀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⣹⣿⣿⣿⣿⠿⠋⠁⠀⣹⣿⠳⠀⠀⠀⠀⠀⠀⢀⣠⣽⣿⡿⠟⠃
|
||||
⠀⠀⠀⠀⠀⢰⠿⠛⠻⢿⡇⠀⠀⠀⣰⣿⠏⠀⠀⢀⠀⠀⠀⣾⣿⠟⠋⠁⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠀⠀⣰⣿⣿⣾⣿⠿⢿⣷⣀⢀⣿⡇⠁⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠉⠁⠀⠀⠀⠀⠙⢿⣿⣿⠇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀*/
|
||||
/**
|
||||
* Functie om batterijdata op te halen wanneer de pagina laadt.
|
||||
* Deze functie haalt data op met Axios en verwerkt deze vervolgens.
|
||||
*/
|
||||
function fetchBatteryData()
|
||||
{
|
||||
// Voer een GET-verzoek uit naar de server om batterijdata op te halen.
|
||||
axios.get('http://127.0.0.1:5000')
|
||||
.then(response =>
|
||||
{
|
||||
// Verwerk de ontvangen data.
|
||||
const batteryData = response.data;
|
||||
updateBatteryData(batteryData);
|
||||
})
|
||||
.catch(error =>
|
||||
{
|
||||
// Log eventuele fouten tijdens het ophalen.
|
||||
console.error('Error fetching battery data:', error);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Functie om batterijdata op de pagina bij te werken.
|
||||
* Deze functie update de HTML met de ontvangen batterijdata.
|
||||
* @param {Array} batteryData - De ontvangen batterijdata.
|
||||
*/
|
||||
function updateBatteryData(batteryData)
|
||||
{
|
||||
// Check if on the specific page where the battery data should be updated
|
||||
if (window.location.pathname.endsWith('index.html'))
|
||||
{
|
||||
// Update de data voor specifieke apparaten op basis van hun ID.
|
||||
const sensor322Element = document.getElementById('deviceNumber-322');
|
||||
const sensor256Element = document.getElementById('deviceNumber-256');
|
||||
|
||||
if (batteryData[1].device_id === 322 && sensor322Element)
|
||||
{
|
||||
sensor322Element.innerHTML = batteryData[1].device_id;
|
||||
document.getElementById('voltage-322').innerHTML = batteryData[1].label;
|
||||
document.getElementById('time-322').innerHTML = new Date(batteryData[1].last_seen * 1000).toLocaleTimeString();
|
||||
document.getElementById('tevredenheid-322').innerHTML = batteryData[1].last_battery_voltage.toFixed(2);
|
||||
}
|
||||
if (batteryData[0].device_id === 256 && sensor256Element)
|
||||
{
|
||||
sensor256Element.innerHTML = batteryData[0].device_id;
|
||||
document.getElementById('voltage-256').innerHTML = batteryData[0].label;
|
||||
document.getElementById('time-256').innerHTML = new Date(batteryData[0].last_seen * 1000).toLocaleTimeString();
|
||||
document.getElementById('tevredenheid-256').innerHTML = batteryData[0].last_battery_voltage.toFixed(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fetch battery data when the page loads
|
||||
fetchBatteryData();
|
||||
/*⠀⠀⠀⢸⣦⡀⠀⠀⠀⠀⢀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⢸⣏⠻⣶⣤⡶⢾⡿⠁⠀⢠⣄⡀⢀⣴⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⣀⣼⠷⠀⠀⠁⢀⣿⠃⠀⠀⢀⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠴⣾⣯⣅⣀⠀⠀⠀⠈⢻⣦⡀⠒⠻⠿⣿⡿⠿⠓⠂⠀⠀⢀⡇⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠉⢻⡇⣤⣾⣿⣷⣿⣿⣤⠀⠀⣿⠁⠀⠀⠀⢀⣴⣿⣿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠸⣿⡿⠏⠀⢀⠀⠀⠿⣶⣤⣤⣤⣄⣀⣴⣿⡿⢻⣿⡆⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠟⠁⠀⢀⣼⠀⠀⠀⠹⣿⣟⠿⠿⠿⡿⠋⠀⠘⣿⣇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⢳⣶⣶⣿⣿⣇⣀⠀⠀⠙⣿⣆⠀⠀⠀⠀⠀⠀⠛⠿⣿⣦⣤⣀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⣹⣿⣿⣿⣿⠿⠋⠁⠀⣹⣿⠳⠀⠀⠀⠀⠀⠀⢀⣠⣽⣿⡿⠟⠃
|
||||
⠀⠀⠀⠀⠀⢰⠿⠛⠻⢿⡇⠀⠀⠀⣰⣿⠏⠀⠀⢀⠀⠀⠀⣾⣿⠟⠋⠁⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠀⠀⣰⣿⣿⣾⣿⠿⢿⣷⣀⢀⣿⡇⠁⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠉⠁⠀⠀⠀⠀⠙⢿⣿⣿⠇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀ ⠀⠈⠀⠀⠀*/
|
||||
|
||||
|
||||
function dynamischSensor()
|
||||
{
|
||||
if (window.location.pathname.endsWith('index.html') || window.location.pathname === '/')
|
||||
{
|
||||
const sensor1 = document.getElementById("sensor-1");
|
||||
const sensor2 = document.getElementById("sensor-2");
|
||||
|
||||
if (sensor1 && sensor2)
|
||||
{
|
||||
sensor1.href = `sensor.html?id=${322}`;
|
||||
sensor2.href = `sensor.html?id=${256}`;
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log("Elementen 'sensor-1' of 'sensor-2' bestaan niet in de DOM.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Aanroepen van de functie
|
||||
dynamischSensor();
|
||||
|
||||
/*⠀⠀⠀⢸⣦⡀⠀⠀⠀⠀⢀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⢸⣏⠻⣶⣤⡶⢾⡿⠁⠀⢠⣄⡀⢀⣴⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⣀⣼⠷⠀⠀⠁⢀⣿⠃⠀⠀⢀⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠴⣾⣯⣅⣀⠀⠀⠀⠈⢻⣦⡀⠒⠻⠿⣿⡿⠿⠓⠂⠀⠀⢀⡇⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠉⢻⡇⣤⣾⣿⣷⣿⣿⣤⠀⠀⣿⠁⠀⠀⠀⢀⣴⣿⣿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠸⣿⡿⠏⠀⢀⠀⠀⠿⣶⣤⣤⣤⣄⣀⣴⣿⡿⢻⣿⡆⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠟⠁⠀⢀⣼⠀⠀⠀⠹⣿⣟⠿⠿⠿⡿⠋⠀⠘⣿⣇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⢳⣶⣶⣿⣿⣇⣀⠀⠀⠙⣿⣆⠀⠀⠀⠀⠀⠀⠛⠿⣿⣦⣤⣀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⣹⣿⣿⣿⣿⠿⠋⠁⠀⣹⣿⠳⠀⠀⠀⠀⠀⠀⢀⣠⣽⣿⡿⠟⠃
|
||||
⠀⠀⠀⠀⠀⢰⠿⠛⠻⢿⡇⠀⠀⠀⣰⣿⠏⠀⠀⢀⠀⠀⠀⣾⣿⠟⠋⠁⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠀⠀⣰⣿⣿⣾⣿⠿⢿⣷⣀⢀⣿⡇⠁⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠉⠁⠀⠀⠀⠀⠙⢿⣿⣿⠇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀PLANTEN⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠈⠀⠀⠀*/
|
||||
|
||||
function fetchPlantenData()
|
||||
{
|
||||
// Gebruik Axios om een GET-verzoek te versturen naar de planten endpoint.
|
||||
axios.get('http://127.0.0.1:5000/planten')
|
||||
.then(response =>
|
||||
{
|
||||
// Verwerk de ontvangen data.
|
||||
const plantenData = response.data;
|
||||
updatePlantenData(plantenData);
|
||||
})
|
||||
.catch(error =>
|
||||
{
|
||||
// Log eventuele fouten tijdens het ophalen.
|
||||
console.error('Error fetching planten data:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function getPlantIdFromUrl()
|
||||
{
|
||||
// Maak een URL-object van de huidige locatie.
|
||||
const currentUrl = new URL(window.location.href);
|
||||
// Gebruik de URLSearchParams API om de query parameters te verwerken.
|
||||
const searchParams = currentUrl.searchParams;
|
||||
// Haal de 'id' query parameter op.
|
||||
return searchParams.get('id'); // Dit zal een string retourneren of null als het niet bestaat.
|
||||
}
|
||||
|
||||
function updatePlantenData(plantenData)
|
||||
{
|
||||
// Verkrijg de plant ID uit de URL.
|
||||
const plantId = parseInt(getPlantIdFromUrl(), 10);
|
||||
|
||||
// Vind de plant met die ID in de ontvangen JSON-data.
|
||||
const gevondenPlant = plantenData.find(plant => plant.id === plantId);
|
||||
|
||||
// Update de titel van de pagina met de naam van de gevonden plant.
|
||||
if (gevondenPlant)
|
||||
{
|
||||
document.title = gevondenPlant.plant_naam;
|
||||
document.querySelector(".plant-titel").textContent = gevondenPlant.plant_naam;
|
||||
// console.log("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log(`Geen plant gevonden met ID ${plantId}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Roep fetchPlantenData aan ergens waar het logisch is binnen je applicatielogica, bijvoorbeeld na het laden van de pagina of na een gebruikersactie.
|
||||
fetchPlantenData();
|
||||
/*⠀⠀⠀⢸⣦⡀⠀⠀⠀⠀⢀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⢸⣏⠻⣶⣤⡶⢾⡿⠁⠀⢠⣄⡀⢀⣴⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⣀⣼⠷⠀⠀⠁⢀⣿⠃⠀⠀⢀⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠴⣾⣯⣅⣀⠀⠀⠀⠈⢻⣦⡀⠒⠻⠿⣿⡿⠿⠓⠂⠀⠀⢀⡇⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠉⢻⡇⣤⣾⣿⣷⣿⣿⣤⠀⠀⣿⠁⠀⠀⠀⢀⣴⣿⣿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠸⣿⡿⠏⠀⢀⠀⠀⠿⣶⣤⣤⣤⣄⣀⣴⣿⡿⢻⣿⡆⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠟⠁⠀⢀⣼⠀⠀⠀⠹⣿⣟⠿⠿⠿⡿⠋⠀⠘⣿⣇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⢳⣶⣶⣿⣿⣇⣀⠀⠀⠙⣿⣆⠀⠀⠀⠀⠀⠀⠛⠿⣿⣦⣤⣀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⣹⣿⣿⣿⣿⠿⠋⠁⠀⣹⣿⠳⠀⠀⠀⠀⠀⠀⢀⣠⣽⣿⡿⠟⠃
|
||||
⠀⠀⠀⠀⠀⢰⠿⠛⠻⢿⡇⠀⠀⠀⣰⣿⠏⠀⠀⢀⠀⠀⠀⣾⣿⠟⠋⠁⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠀⠀⣰⣿⣿⣾⣿⠿⢿⣷⣀⢀⣿⡇⠁⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⠉⠁⠀⠀⠀⠀⠙⢿⣿⣿⠇⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀*/
|
||||
// Get the battery voltage
|
||||
// const batteryVoltage = parseFloat(document.getElementById('battery-voltage'));
|
||||
|
||||
// // Select the img element
|
||||
// const batteryImage = document.getElementById('battery-image');
|
||||
|
||||
// // Check the battery voltage and decide whether to show the image
|
||||
// if (batteryVoltage < 3.0) {
|
||||
// // Battery is lower than 3.0 volts, show the empty battery image
|
||||
// batteryImage.src = '../static/img/warning-logo.png';
|
||||
// } else if (batteryVoltage > 4.2) {
|
||||
// // Battery is higher than 4.2 volts, do not show the image
|
||||
// batteryImage.style.display = 'none';
|
||||
// } else {
|
||||
// // Battery voltage is within the desired range, hide the image
|
||||
// batteryImage.style.display = 'none';
|
||||
// }
|
||||
115
src/py/static/js/planten.class.js
Normal file
115
src/py/static/js/planten.class.js
Normal file
@@ -0,0 +1,115 @@
|
||||
// Definitie van de Plant klasse.
|
||||
class Plant {
|
||||
// Constructor om een Plant object te initialiseren met data van een dataObject.
|
||||
constructor(dataObject) {
|
||||
// Initialiseren van de eigenschappen van de plant.
|
||||
this.id = dataObject.id;
|
||||
this.plantNaam = dataObject.plant_naam; // Naam van de plant.
|
||||
this.plantensoort = dataObject.plantensoort; // Soort van de plant.
|
||||
this.plantGeteelt = dataObject.plant_geteelt; // Geteelt status van de plant.
|
||||
}
|
||||
}
|
||||
|
||||
class PlantGrid {
|
||||
// Constructor om een PlantGrid object te initialiseren.
|
||||
constructor() {
|
||||
this.grid = []; // De datastructuur die het raster van planten bevat.
|
||||
this.cols = 2; // Aantal kolommen in het raster.
|
||||
this.rows = 4; // Aantal rijen in het raster (inclusief de rij voor de "Toevoegen" knop).
|
||||
|
||||
// Initialiseren van het raster met null waarden.
|
||||
for (let i = 0; i < this.rows; i++) {
|
||||
this.grid[i] = new Array(this.cols).fill(null);
|
||||
}
|
||||
|
||||
// Laadt JSON data van de server.
|
||||
this.loadData();
|
||||
}
|
||||
|
||||
// Methode om data te laden.
|
||||
loadData() {
|
||||
fetch('../script/json/plants.json')
|
||||
.then(response => {
|
||||
// Controleer of de netwerkrespons ok is.
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
return response.json(); // Parse de JSON uit de respons.
|
||||
})
|
||||
.then(data => {
|
||||
// Filter de data op planten die geteeld zijn.
|
||||
const filteredData = data.filter(plantObject => plantObject.plant_geteelt === 1);
|
||||
|
||||
// Vul het raster met plantobjecten.
|
||||
filteredData.slice(0, 8).forEach((plantObject, index) => {
|
||||
const plant = new Plant(plantObject); // Maak een nieuw Plant object.
|
||||
const col = index % this.cols; // Bereken de kolomindex.
|
||||
const row = Math.floor(index / this.cols); // Bereken de rijindex.
|
||||
this.grid[row][col] = plant; // Voeg de plant toe aan het raster.
|
||||
});
|
||||
|
||||
// Toon het raster in de HTML tabel met id "planten".
|
||||
this.displayGrid();
|
||||
})
|
||||
.catch(error => console.error('Error loading data:', error)); // Log eventuele fouten.
|
||||
}
|
||||
|
||||
|
||||
displayGrid() {
|
||||
const plantenTable = document.getElementById("planten");
|
||||
|
||||
let itemCount = 0; // Counter for the number of items in the grid
|
||||
|
||||
this.grid.forEach((row, rowIndex) => {
|
||||
const tr = document.createElement("tr");
|
||||
|
||||
row.forEach((plant, colIndex) => {
|
||||
const td = document.createElement("td");
|
||||
|
||||
if (itemCount < 8) {
|
||||
if (plant) {
|
||||
// Handle regular plant items
|
||||
const link = document.createElement("a");
|
||||
link.href = `planteninfo.html?id=${plant.id}`; // Link naar de planteninfo pagina met plant id als query parameter
|
||||
|
||||
const article = document.createElement("article");
|
||||
article.classList.add("plant-container");
|
||||
link.appendChild(article); // Voeg het artikel toe aan de link
|
||||
|
||||
const img = article.appendChild(document.createElement("img"));
|
||||
img.src = "../static/images/icon_awesome-apple-alt.png";
|
||||
const h2 = article.appendChild(document.createElement("h2"));
|
||||
h2.classList.add("plant-naam");
|
||||
h2.textContent = plant.plantNaam;
|
||||
|
||||
td.appendChild(link); // Voeg de link toe aan de td
|
||||
itemCount++;
|
||||
} else if (rowIndex === this.rows - 1 && colIndex === this.cols - 1 && itemCount <= 7) {
|
||||
// Handle the "Add" button
|
||||
const article = document.createElement("article");
|
||||
const img = article.appendChild(document.createElement("img"));
|
||||
img.src = "../static/images/plus.png";
|
||||
img.id = "toevoegen";
|
||||
img.alt = "Add";
|
||||
article.id = "modalButton";
|
||||
article.onclick = openModal;
|
||||
|
||||
td.appendChild(article);
|
||||
itemCount++;
|
||||
}
|
||||
}
|
||||
|
||||
tr.appendChild(td);
|
||||
});
|
||||
|
||||
plantenTable.appendChild(tr);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const plantGrid = new PlantGrid();
|
||||
});
|
||||
1
src/py/static/js/planten_pagina.js
Normal file
1
src/py/static/js/planten_pagina.js
Normal file
@@ -0,0 +1 @@
|
||||
/*Hier komt alle code die te maken heeft met de "dynamische" planten pagina's*/
|
||||
151
src/py/templates/index.html
Normal file
151
src/py/templates/index.html
Normal file
@@ -0,0 +1,151 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="nl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="De pagina voor de verschillende sensoren" />
|
||||
<meta name="author" content="B. Diker, A. Oomen, J. Doekhi, R. van Putten, M. Çifçi" />
|
||||
<meta name="keywords" content="Homepage / Dashboard / Algoritme / Voeding / Planten / Data / Kas" />
|
||||
<title>Dashboard</title>
|
||||
<link rel="stylesheet" href="../static/css/style.css">
|
||||
<script src="../static/js/main.js" defer></script>
|
||||
<script src="../static/js/planten.class.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<section class="mainContainer">
|
||||
<div class="pagina-container">
|
||||
<div class="close-button" onclick="closeApplication()">×</div>
|
||||
</div>
|
||||
<article>
|
||||
<a href="index.html">
|
||||
<img src="../static/images/logo.png" class="goodgarden-logo">
|
||||
</a>
|
||||
</article>
|
||||
<section class="mainBorder">
|
||||
<section class="content">
|
||||
<section class="kant-links">
|
||||
<table id="planten">
|
||||
</table>
|
||||
<div class="formulier">
|
||||
<div id="myModal" class="modal" style="display: none;">
|
||||
<h1 id="plant-id">Plant Toevoegen</h1>
|
||||
<span class="close">×</span>
|
||||
<form action="http://localhost:3000/submit-form" method="post" onsubmit="return addplant()">
|
||||
<label for="plantNaam">Naam van de plant</label>
|
||||
|
||||
<input type="text" name="plant_naam" id="plantNaam">
|
||||
|
||||
<label for="plantensoort">Soort van de plant</label>
|
||||
|
||||
<input type="text" name="plantensoort" id="plantensoort">
|
||||
|
||||
<label for="aanwezig">Aanwezig
|
||||
<input type="radio" name="plant_geteelt" id="aanwezig" value="true">
|
||||
</label>
|
||||
|
||||
<label for="afwezig">Afwezig
|
||||
<input type="radio" name="plant_geteelt" id="afwezig" value="false">
|
||||
</label>
|
||||
|
||||
<label for="ontvangenMeldingen">Meldingen ontvangen</label>
|
||||
|
||||
<select name="ontvangen_meldingen">
|
||||
<option value="true">Ja</option>
|
||||
<option value="false">Nee</option>
|
||||
</select>
|
||||
|
||||
<section class="knop-container">
|
||||
<button class="annulatie-knop" type="button" onclick="closeOverlay()">Annuleren</button>
|
||||
<input type="submit" value="Submit">
|
||||
</section>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div id="overlay" onclick="closeOverlay"></div>
|
||||
</section>
|
||||
<section class="kant-rechts">
|
||||
<!-- Sectie voor sensorinformatie -->
|
||||
<section id="sectie-1">
|
||||
<article class="parent-algemeen-overzicht">
|
||||
<article class="algemeen-overzicht">
|
||||
<a href="./pomp_informatie.html" id="kas-informatie">
|
||||
<table class="table-informatie-kas">
|
||||
<tr class="tr-informatie-pomp">
|
||||
<td>Pomp Status:</td>
|
||||
<td id="">Uitstekend!</td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-pomp">
|
||||
<td>Volgende Irrigatie:</td>
|
||||
<td id="">24:00</td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-pomp">
|
||||
<td>Laatste Irrigatie:</td>
|
||||
<td id="">18:00</td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-pomp">
|
||||
<td>Waterverbruik:</td>
|
||||
<td id="">0.5 L/u</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a/>
|
||||
</article>
|
||||
</article>
|
||||
<!-- Container voor algemene overzichtinformatie -->
|
||||
<article class="parent-algemeen-overzicht">
|
||||
<article class="algemeen-overzicht">
|
||||
<!-- Link naar pagina met meer details over de sensoren -->
|
||||
<a href="./sensor.html" id="sensor-1">
|
||||
<!-- Tabel met sensorinformatie -->
|
||||
<table class="table-informatie-kas">
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Sensor:</td>
|
||||
<td id="deviceNumber-322"></td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Locatie:</td>
|
||||
<td id="voltage-322"></td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Batterijvoltage:</td>
|
||||
<td id="tevredenheid-322"></td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Dagen resterend:</td>
|
||||
<td id="time-322"></td>
|
||||
</tr>
|
||||
</table>
|
||||
<a/>
|
||||
</article>
|
||||
</article>
|
||||
<article class="parent-algemeen-overzicht">
|
||||
<article class="algemeen-overzicht">
|
||||
<a href="sensoren.html" id="sensor-2">
|
||||
<table class="table-informatie-kas">
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Sensor:</td>
|
||||
<td id="deviceNumber-256"></td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Locatie:</td>
|
||||
<td id="voltage-256"></td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Batterijvoltage:</td>
|
||||
<td id="tevredenheid-256"></td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Dagen resterend:</td>
|
||||
<td id="time-256"></td>
|
||||
</tr>
|
||||
</table>
|
||||
<a/>
|
||||
</article>
|
||||
</article>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
135
src/py/templates/kas_informatie.html
Normal file
135
src/py/templates/kas_informatie.html
Normal file
@@ -0,0 +1,135 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="nl">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="De pagina voor de verschillende sensoren" />
|
||||
<meta name="author" content="B. Diker, A. Oomen, J. Doekhi, R. van Putten, M. Çifçi" />
|
||||
<meta name="keywords" content="Kas informatie / Algoritme / Voeding / Planten / Data / Kas" />
|
||||
<link rel="stylesheet" href="../static/css/style.css" />
|
||||
<script src="../static/js/main.js" defer></script>
|
||||
<script src="../static/js/grafiek.js" defer></script>
|
||||
<title>Informatie Kas</title>
|
||||
</head>
|
||||
<body>
|
||||
<section class="mainContainer">
|
||||
<article>
|
||||
<div class="pagina-container">
|
||||
<div class="close-button" onclick="closeApplication()">×</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<a href="index.html" class="back-button">←</a>
|
||||
</div>
|
||||
<a href="index.html">
|
||||
<img src="../static/images/logo.png" class="goodgarden-logo">
|
||||
</a>
|
||||
</article>
|
||||
<!-- De container die de inhoud van de informatiepagina bevat -->
|
||||
<section class="mainBorder informatie-kas-main-container">
|
||||
<article>
|
||||
<h1 class="pagina-titel-kas">Informatie Kas</h1>
|
||||
<!-- Sectie met overzicht van de kas gegevens -->
|
||||
<section id="sectie-1">
|
||||
<!-- Weergave van sensor data en kascondities -->
|
||||
<article class="parent-algemeen-overzicht">
|
||||
<article class="algemeen-overzicht">
|
||||
<!-- Tabel voor het weergeven van sensorgegevens -->
|
||||
<table class="table-informatie-kas">
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Device</td>
|
||||
<td id="deviceNumber"></td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Batterij Voltage</td>
|
||||
<td id="voltage"></td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Tijden</td>
|
||||
<td id="time"></td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Zulu</td>
|
||||
<td id="zulu"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</article>
|
||||
</article>
|
||||
<!-- Weergave van zonlichtdata in een grafiek -->
|
||||
<article class="grafiek">
|
||||
<article class="grafiek-innerbox">
|
||||
<h2>Zonlicht</h2>
|
||||
<canvas
|
||||
id="myCanvas"
|
||||
class="canvas-informatie-kas"
|
||||
width="275"
|
||||
height="275"
|
||||
></canvas>
|
||||
</article>
|
||||
</article>
|
||||
</section>
|
||||
</article>
|
||||
<!-- Sectie met aanvullende informatie over de kas in tabelvorm -->
|
||||
<article class="grid-column-2">
|
||||
<article class="grid-2-child">
|
||||
<section class="parent-table">
|
||||
<!-- Verschillende tabellen voor gedetailleerde informatie -->
|
||||
<table class="kas-table-1">
|
||||
<!-- Rijen met specifieke kas informatie, zoals aantal geplante en geoogste planten -->
|
||||
<tr>
|
||||
<td>Aantal geplant:</td>
|
||||
<td id="totale_planten">Loading...</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Succesvolle Oogst:</td>
|
||||
<td>2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gefaalde Oogst:</td>
|
||||
<td>2</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="kas-table-2">
|
||||
<!-- Rijen met klimaat- en bodemcondities -->
|
||||
<tr>
|
||||
<td>Warmste Maand:</td>
|
||||
<td>n.v.t.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>koudste Maand:</td>
|
||||
<td>December</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gemiddelde Bodemtemp.:</td>
|
||||
<td id="bodem-temperatuur">2˚C</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gemiddelde Uren Zonlicht:</td>
|
||||
<td id="battery_voltage">2u</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="kas-table-3">
|
||||
<!-- Rijen met irrigatie- en bemestingschema's -->
|
||||
<tr>
|
||||
<td>Laatste Irrigatie:</td>
|
||||
<td>2u</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Aankomende Irrigatie:</td>
|
||||
<td>2u</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Laatste Bemesting</td>
|
||||
<td>2d</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Aankomende Bemesting:</td>
|
||||
<td>2w</td>
|
||||
</tr>
|
||||
</table>
|
||||
</section>
|
||||
</article>
|
||||
</article>
|
||||
</section>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
143
src/py/templates/planteninfo.html
Normal file
143
src/py/templates/planteninfo.html
Normal file
@@ -0,0 +1,143 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="nl">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="De pagina voor de verschillende sensoren" />
|
||||
<meta name="author" content="B. Diker, A. Oomen, J. Doekhi, R. van Putten, M. Çifçi" />
|
||||
<meta name="keywords" content="Planten informatie / Algoritme / Voeding / Planten / Data / Kas" />
|
||||
<link rel="stylesheet" href="../static/css/style.css" />
|
||||
<script src="../static/js/main.js" defer></script>
|
||||
<script src="../static/js/grafiek.js" defer></script>
|
||||
<title>Planten</title>
|
||||
</head>
|
||||
<body>
|
||||
<section class="mainContainer">
|
||||
<article>
|
||||
<div class="pagina-container">
|
||||
<div class="close-button" onclick="closeApplication()">×</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<a href="index.html" class="back-button">←</a>
|
||||
</div>
|
||||
<a href="index.html">
|
||||
<img src="../static/images/logo.png" class="goodgarden-logo">
|
||||
</a>
|
||||
</article>
|
||||
<!-- Bevat de primaire inhoud van de pagina -->
|
||||
<section class="mainBorder informatie-kas-main-container">
|
||||
<article>
|
||||
<h1 class="pagina-titel plant-titel"> </h1>
|
||||
<!-- Bevat een overzicht van algemene informatie en grafieken -->
|
||||
<section id="sectie-1">
|
||||
<!-- Weergave van belangrijke kasstatistieken -->
|
||||
<article class="parent-algemeen-overzicht">
|
||||
<article class="algemeen-overzicht">
|
||||
<!-- Tabel met statische data over de kas -->
|
||||
<table class="table-informatie-kas">
|
||||
<!-- Rijen met specifieke informatie zoals dagen tot oogst en tevredenheid -->
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Aanwezig in kas</td>
|
||||
<div class="switch-container">
|
||||
<form action="{{ url_for('toggle') }}" method="POST">
|
||||
<label class="switch">
|
||||
<input type="checkbox" name="schakelaar" {% if schakelaar.status %}checked{% endif %}>
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</form>
|
||||
</div>
|
||||
</tr>
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Dagen tot Oogst</td>
|
||||
<td>12</td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Dagen in Kas</td>
|
||||
<td>2</td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Tevredenheid</td>
|
||||
<td>80%</td>
|
||||
</tr>
|
||||
</table>
|
||||
</article>
|
||||
</article>
|
||||
<!-- Sectie voor het weergeven van een grafiek over zonlicht -->
|
||||
<article class="grafiek">
|
||||
<article class="grafiek-innerbox">
|
||||
<h2>Zonlicht</h2>
|
||||
<canvas
|
||||
id="myCanvas"
|
||||
class="canvas-informatie-kas"
|
||||
width="275"
|
||||
height="275"
|
||||
></canvas>
|
||||
</article>
|
||||
</article>
|
||||
</section>
|
||||
</article>
|
||||
<!-- Presenteert aanvullende informatie in tabelvorm -->
|
||||
<article class="grid-column-2">
|
||||
<article class="grid-2-child">
|
||||
<section class="parent-table">
|
||||
<!-- Meerdere tabellen met informatie over geplante aantallen, oogstresultaten en klimaatcondities -->
|
||||
<table class="kas-table-1">
|
||||
<!-- Details over geplant aantal, succesvolle en gefaalde oogst -->
|
||||
<tr>
|
||||
<td>Aantal geplant:</td>
|
||||
<td>2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Succesvolle Oogst:</td>
|
||||
<td>2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gefaalde Oogst:</td>
|
||||
<td>2</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="kas-table-2">
|
||||
<!-- Informatie over de klimaatcondities zoals de warmste en koudste maand, gemiddelde bodemtemperatuur en zonlichturen -->
|
||||
<tr>
|
||||
<td>Warmste Maand:</td>
|
||||
<td>n.v.t.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>koudste Maand:</td>
|
||||
<td>December</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gemiddelde Bodemtemp.:</td>
|
||||
<td id="bodem-temperatuur">2˚C</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gemiddelde Uren Zonlicht:</td>
|
||||
<td id="battery_voltage">2u</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="kas-table-3">
|
||||
<!-- Schema voor irrigatie en bemesting -->
|
||||
<tr>
|
||||
<td>Laatste Irrigatie:</td>
|
||||
<td>2u</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Aankomende Irrigatie:</td>
|
||||
<td>2u</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Laatste Bemesting</td>
|
||||
<td>2d</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Aankomende Bemesting:</td>
|
||||
<td>2w</td>
|
||||
</tr>
|
||||
</table>
|
||||
</section>
|
||||
</article>
|
||||
</article>
|
||||
</section>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
135
src/py/templates/pomp_informatie.html
Normal file
135
src/py/templates/pomp_informatie.html
Normal file
@@ -0,0 +1,135 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="nl">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="Een pagina speciaal voor de pomp!" />
|
||||
<meta name="author" content="B. Diker, A. Oomen, J. Doekhi, R. van Putten, M. Çifçi" />
|
||||
<meta name="keywords" content="Pomp / Algoritme / Voeding / Planten / Data / Kas" />
|
||||
<link rel="stylesheet" href="../static/css/style.css" />
|
||||
<script src="../static/js/main.js" defer></script>
|
||||
<script src="../static/js/grafiek.js" defer></script>
|
||||
<title>Informatie Pomp</title>
|
||||
</head>
|
||||
<body>
|
||||
<section class="mainContainer">
|
||||
<article>
|
||||
<div class="pagina-container">
|
||||
<div class="close-button" onclick="closeApplication()">×</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<a href="index.html" class="back-button">←</a>
|
||||
</div>
|
||||
<a href="index.html">
|
||||
<img src="../static/images/logo.png" class="goodgarden-logo">
|
||||
</a>
|
||||
</article>
|
||||
<!-- De container die de inhoud van de informatiepagina bevat -->
|
||||
<section class="mainBorder informatie-kas-main-container">
|
||||
<article>
|
||||
<h1 class="pagina-titel">Informatie Pomp</h1>
|
||||
<!-- Sectie met overzicht van de kas gegevens -->
|
||||
<section id="sectie-1">
|
||||
<!-- Weergave van sensor data en kascondities -->
|
||||
<article class="parent-algemeen-overzicht">
|
||||
<article class="algemeen-overzicht">
|
||||
<!-- Tabel voor het weergeven van sensorgegevens -->
|
||||
<table class="table-informatie-kas">
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Pomp Status:</td>
|
||||
<td id="deviceNumber">Uitstekend!</td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Waterverbruik:</td>
|
||||
<td id="voltage">0.5 L/u</td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Volgende Irrigatie</td>
|
||||
<td id="time">24:00</td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Laatste Irrigatie:</td>
|
||||
<td id="zulu">18:00</td>
|
||||
</tr>
|
||||
</table>
|
||||
</article>
|
||||
</article>
|
||||
<!-- Weergave van zonlichtdata in een grafiek -->
|
||||
<article class="grafiek">
|
||||
<article class="grafiek-innerbox">
|
||||
<h2>Temperatuur</h2>
|
||||
<canvas
|
||||
id="myCanvas"
|
||||
class="canvas-informatie-kas"
|
||||
width="275"
|
||||
height="275"
|
||||
></canvas>
|
||||
</article>
|
||||
</article>
|
||||
</section>
|
||||
</article>
|
||||
<!-- Sectie met aanvullende informatie over de kas in tabelvorm -->
|
||||
<article class="grid-column-2">
|
||||
<article class="grid-2-child">
|
||||
<section class="parent-table">
|
||||
<!-- Verschillende tabellen voor gedetailleerde informatie -->
|
||||
<table class="kas-table-1">
|
||||
<!-- Rijen met specifieke kas informatie, zoals aantal geplante en geoogste planten -->
|
||||
<tr>
|
||||
<td>Aantal geplant:</td>
|
||||
<td id="totale_planten">Loading...</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Succesvolle Oogst:</td>
|
||||
<td>2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gefaalde Oogst:</td>
|
||||
<td>2</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="kas-table-2">
|
||||
<!-- Rijen met klimaat- en bodemcondities -->
|
||||
<tr>
|
||||
<td>Warmste Maand:</td>
|
||||
<td>n.v.t.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>koudste Maand:</td>
|
||||
<td>December</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gemiddelde Bodemtemp.:</td>
|
||||
<td id="bodem-temperatuur">2˚C</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gemiddelde Uren Zonlicht:</td>
|
||||
<td id="battery_voltage">2u</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="kas-table-3">
|
||||
<!-- Rijen met irrigatie- en bemestingschema's -->
|
||||
<tr>
|
||||
<td>Laatste Irrigatie:</td>
|
||||
<td>2u</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Aankomende Irrigatie:</td>
|
||||
<td>2u</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Laatste Bemesting</td>
|
||||
<td>2d</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Aankomende Bemesting:</td>
|
||||
<td>2w</td>
|
||||
</tr>
|
||||
</table>
|
||||
</section>
|
||||
</article>
|
||||
</article>
|
||||
</section>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
135
src/py/templates/sensor.html
Normal file
135
src/py/templates/sensor.html
Normal file
@@ -0,0 +1,135 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="nl">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="De pagina voor de verschillende sensoren" />
|
||||
<meta name="author" content="B. Diker, A. Oomen, J. Doekhi, R. van Putten, M. Çifçi" />
|
||||
<meta name="keywords" content="Sensor / Algoritme / Voeding / Planten / Data / Kas" />
|
||||
<link rel="stylesheet" href="../static/css/style.css" />
|
||||
<script src="../static/js/main.js" defer></script>
|
||||
<script src="../static/js/grafiek.js" defer></script>
|
||||
<title>Informatie Sensor</title>
|
||||
</head>
|
||||
<body>
|
||||
<section class="mainContainer">
|
||||
<article>
|
||||
<div class="pagina-container">
|
||||
<div class="close-button" onclick="closeApplication()">×</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<a href="index.html" class="back-button">←</a>
|
||||
</div>
|
||||
<a href="index.html">
|
||||
<img src="../static/images/logo.png" class="goodgarden-logo">
|
||||
</a>
|
||||
</article>
|
||||
<!-- De container die de inhoud van de informatiepagina bevat -->
|
||||
<section class="mainBorder informatie-kas-main-container">
|
||||
<article>
|
||||
<h1 class="pagina-titel sensor-titel">Informatie Kas</h1>
|
||||
<!-- Sectie met overzicht van de kas gegevens -->
|
||||
<section id="sectie-1">
|
||||
<!-- Weergave van sensor data en kascondities -->
|
||||
<article class="parent-algemeen-overzicht">
|
||||
<article class="algemeen-overzicht">
|
||||
<!-- Tabel voor het weergeven van sensorgegevens -->
|
||||
<table class="table-informatie-kas">
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Device</td>
|
||||
<td id="deviceNumber"></td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Batterij Voltage</td>
|
||||
<td id="voltage"></td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Tijden</td>
|
||||
<td id="time"></td>
|
||||
</tr>
|
||||
<tr class="tr-informatie-kas">
|
||||
<td>Zulu</td>
|
||||
<td id="zulu"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</article>
|
||||
</article>
|
||||
<!-- Weergave van zonlichtdata in een grafiek -->
|
||||
<article class="grafiek">
|
||||
<article class="grafiek-innerbox">
|
||||
<h2>Zonlicht</h2>
|
||||
<canvas
|
||||
id="sensorCanvas"
|
||||
class="canvas-informatie-kas"
|
||||
width="275"
|
||||
height="275"
|
||||
></canvas>
|
||||
</article>
|
||||
</article>
|
||||
</section>
|
||||
</article>
|
||||
<!-- Sectie met aanvullende informatie over de kas in tabelvorm -->
|
||||
<article class="grid-column-2">
|
||||
<article class="grid-2-child">
|
||||
<section class="parent-table">
|
||||
<!-- Verschillende tabellen voor gedetailleerde informatie -->
|
||||
<table class="kas-table-1">
|
||||
<!-- Rijen met specifieke kas informatie, zoals aantal geplante en geoogste planten -->
|
||||
<tr>
|
||||
<td>Aantal geplant:</td>
|
||||
<td id="totale_planten">Loading...</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Succesvolle Oogst:</td>
|
||||
<td>2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gefaalde Oogst:</td>
|
||||
<td>2</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="kas-table-2">
|
||||
<!-- Rijen met klimaat- en bodemcondities -->
|
||||
<tr>
|
||||
<td>Warmste Maand:</td>
|
||||
<td>n.v.t.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>koudste Maand:</td>
|
||||
<td>December</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gemiddelde Bodemtemp.:</td>
|
||||
<td id="bodem-temperatuur">2˚C</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gemiddelde Uren Zonlicht:</td>
|
||||
<td id="battery_voltage">2u</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="kas-table-3">
|
||||
<!-- Rijen met irrigatie- en bemestingschema's -->
|
||||
<tr>
|
||||
<td>Laatste Irrigatie:</td>
|
||||
<td>2u</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Aankomende Irrigatie:</td>
|
||||
<td>2u</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Laatste Bemesting</td>
|
||||
<td>2d</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Aankomende Bemesting:</td>
|
||||
<td>2w</td>
|
||||
</tr>
|
||||
</table>
|
||||
</section>
|
||||
</article>
|
||||
</article>
|
||||
</section>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user