Doc gemaakt voor scripts

This commit is contained in:
Atilla
2024-04-03 14:08:30 +02:00
parent 417dacbe73
commit b8ab58bb53
21 changed files with 629 additions and 300 deletions

View File

@@ -21,9 +21,6 @@ Zorg dat je in de hoofdmap "GoodGarden" zit. Kijk in je path: "../GoodGarden". A
npm install wait-on --save-dev npm install wait-on --save-dev
npm install concurrently --save-dev npm install concurrently --save-dev
pip install mysql-connector-python pip install mysql-connector-python
pip install requests pip install requests
pip install flask-cors pip install flask-cors

95
app.js
View File

@@ -1,50 +1,68 @@
// Importeert de benodigde Electron modules om een desktopapplicatie te creëren.
const { app, BrowserWindow, ipcMain } = require("electron"); const { app, BrowserWindow, ipcMain } = require("electron");
// Express framework om een HTTP-server op te zetten.
const express = require("express"); const express = require("express");
// Body-parser middleware om inkomende request bodies te parsen.
const bodyParser = require("body-parser"); const bodyParser = require("body-parser");
// PythonShell om Python scripts binnen een NodeJS applicatie uit te voeren.
const { PythonShell } = require("python-shell"); const { PythonShell } = require("python-shell");
// Path module voor het werken met bestandspaden.
const path = require("path"); const path = require("path");
// Definieert het pad naar de index.html van de Electron app.
const urlElectron = path.join(__dirname, "src/index.html"); const urlElectron = path.join(__dirname, "src/index.html");
// Initialiseert de Express app.
const server = express(); const server = express();
// Configureert de express server om URL-encoded data te accepteren.
server.use(bodyParser.urlencoded({ extended: true })); server.use(bodyParser.urlencoded({ extended: true }));
// Define a route for form POST requests // Handler voor het "/submit-form" endpoint. Verwerkt formulierinzendingen.
server.post("/submit-form", (req, res) => { server.post("/submit-form", (req, res) =>
{
// Extracts form data from the request body.
const { plant_naam, plantensoort } = req.body; const { plant_naam, plantensoort } = req.body;
const plant_geteelt = req.body.plant_geteelt == "true" ? "true" : "false"; const plant_geteelt = req.body.plant_geteelt == "true" ? "true" : "false";
// Configuratieopties voor het uitvoeren van het Python script.
let options = { let options = {
mode: "text", mode: "text",
args: [plant_naam, plantensoort, plant_geteelt], args: [plant_naam, plantensoort, plant_geteelt],
}; };
// Execute Python script with plant name as an argument // Voert een Python script uit en handelt de response af.
PythonShell.run( PythonShell.run("src/py/script/db_connect_form.py", options, (err, results) =>
"src/py/script/db_connect_form.py", {
options, if (err)
(err, results) => { {
if (err) {
console.error(err); console.error(err);
res.send("Er is een fout opgetreden"); res.send("Er is een fout opgetreden");
} else { }
else
{
console.log("Python script uitvoering resultaten:", results); console.log("Python script uitvoering resultaten:", results);
res.send("Formulier succesvol verwerkt"); res.send("Formulier succesvol verwerkt");
} }
} });
);
}); });
// Start the server // Definieert de poort waarop de server luistert.
const PORT = 3000; const PORT = 3000;
server.listen(PORT, () => { server.listen(PORT, () =>
{
console.log(`Server is listening on port ${PORT}`); console.log(`Server is listening on port ${PORT}`);
}); });
let mainWindow; let mainWindow; // Referentie naar het hoofdvenster van de Electron app.
// Create the Electron application window // Creëert het hoofdvenster van de Electron app.
function createWindow() { function createWindow()
{
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 1280, width: 1280,
height: 800, height: 800,
@@ -58,42 +76,51 @@ function createWindow() {
}, },
}); });
mainWindow.loadFile( mainWindow.loadFile(path.join(__dirname, "src", "py", "templates", "index.html"));
path.join(__dirname, "src", "py", "templates", "index.html")
);
// IPC event listeners for running Python scripts and updating HTML data // Stelt IPC Main Listeners in voor communicatie tussen hoofdproces en renderproces.
setupIpcMainListeners(); setupIpcMainListeners();
} }
// Start the Electron app // Wanneer de app klaar is, wordt het hoofdvenster gecreëerd.
app.whenReady().then(createWindow); app.whenReady().then(createWindow);
// Close the app when all windows are closed, except on macOS // Sluit de app af wanneer alle vensters gesloten zijn (behalve op macOS).
app.on("window-all-closed", () => { app.on("window-all-closed", () =>
if (process.platform !== "darwin") { {
if (process.platform !== "darwin")
{
app.quit(); app.quit();
} }
}); });
// Re-create a window in the app when the dock icon is clicked and there are no other windows open. // Creëert het hoofdvenster opnieuw wanneer het app icoon wordt aangeklikt en er zijn geen vensters open.
app.on("activate", () => { app.on("activate", () =>
if (BrowserWindow.getAllWindows().length === 0) { {
if (BrowserWindow.getAllWindows().length === 0)
{
createWindow(); createWindow();
} }
}); });
function setupIpcMainListeners() { //
ipcMain.on("run-python-script", (event, args) => {
// 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 = { let options = {
mode: "text", mode: "text",
args: args, args: args,
}; };
// Hier zou je PythonShell.run met deze opties aanroepen.
// The actual script path and event replies should be tailored to your application's needs
}); });
ipcMain.on("request-update-data", (event, args) => { // IPC luisteraar voor het aanvragen van data update.
ipcMain.on("request-update-data", (event, args) =>
{
const databaseData = { const databaseData = {
timestamp: "2022-01-01", timestamp: "2022-01-01",
gateway_receive_time: "2022-01-01", gateway_receive_time: "2022-01-01",
@@ -103,7 +130,9 @@ function setupIpcMainListeners() {
event.reply("update-data-result", { databaseData }); event.reply("update-data-result", { databaseData });
}); });
ipcMain.on("update-html-data", (event, data) => { // 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); mainWindow.webContents.send("update-html-data", data);
}); });
} }

8
app.py
View File

@@ -47,6 +47,7 @@ def get_data():
return jsonify(battery_data) # Directly return the list of dictionaries as JSON return jsonify(battery_data) # Directly return the list of dictionaries as JSON
def get_weather_data(): def get_weather_data():
api_key = "05ddd06644" api_key = "05ddd06644"
location = "Leiden" location = "Leiden"
@@ -62,15 +63,16 @@ def get_weather():
return jsonify({"error": "Kon weerdata niet ophalen"}) return jsonify({"error": "Kon weerdata niet ophalen"})
live_weather = weather_response.get('liveweer', []) live_weather = weather_response.get('liveweer', [])
today_forecast = weather_response.get('verwachting_vandaag', []) weather_forecast = weather_response.get('wk_verw', [])
day_forecast = weather_response.get('wk_verw', []) # Dagverwachtingen
weather_data = { weather_data = {
"live_weather": live_weather[0] if live_weather else {}, "live_weather": live_weather[0] if live_weather else {},
"today_forecast": today_forecast[0] if today_forecast else {} "weather_forecast": weather_forecast,
"day_forecast": day_forecast # Voeg de dagverwachtingen toe aan de weerdata
} }
return jsonify(weather_data) return jsonify(weather_data)
if __name__ == "__main__": if __name__ == "__main__":
app.run(host="127.0.0.1", port=5000) app.run(host="127.0.0.1", port=5000)

View File

@@ -1,16 +1,36 @@
# Importeer de benodigde modules voor MySQL connectiviteit.
import mysql.connector import mysql.connector
from mysql.connector import Error from mysql.connector import Error
def database_connect(): def database_connect():
"""
Maakt verbinding met de MySQL database.
Probeert een verbinding met de MySQL-database op te zetten met behulp van
de mysql.connector.connect methode, gebruikmakend van de database
credentials. Bij succes retourneert het de verbinding; bij een mislukking
vangt het de fout op en print een bericht.
Returns:
connection (mysql.connector.connect object): Een connectie object als
de verbinding succesvol is. Anders None.
"""
try: try:
# Probeert een verbinding op te zetten met de MySQL database.
connection = mysql.connector.connect( connection = mysql.connector.connect(
host="localhost", host="localhost", # Database host
user="root", user="root", # Database gebruikersnaam
password="", password="", # Database wachtwoord
database="goodgarden" database="goodgarden" # Database naam
) )
# Controleert of de verbinding succesvol was.
if connection.is_connected(): if connection.is_connected():
return connection return connection # Retourneert het verbinding object.
except Error as e: except Error as e:
# Vangt en print elke fout die optreedt tijdens het verbindingsproces.
print(f"Connection NIET gelukt! ${e}") print(f"Connection NIET gelukt! ${e}")
# Retourneert None als de verbinding mislukt.
return None return None

View File

@@ -1,15 +1,59 @@
# Importeer de paho.mqtt.client module die MQTT-client functionaliteiten biedt.
import paho.mqtt.client as mqtt import paho.mqtt.client as mqtt
def create_client(client_id, on_connect, on_message, broker="localhost", port=1883): 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) client = mqtt.Client(client_id)
# Stelt de callback functies in voor connect- en message-events.
client.on_connect = on_connect client.on_connect = on_connect
client.on_message = on_message client.on_message = on_message
client.connect(broker, port, 60) # 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 return client
def start_loop(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: try:
# Start de oneindige loop die berichten verwerkt.
client.loop_forever() client.loop_forever()
except KeyboardInterrupt: except KeyboardInterrupt:
# Print een bericht en maakt de verbinding met de broker los
# als de gebruiker de loop onderbreekt.
print("Disconnecting from broker") print("Disconnecting from broker")

View File

@@ -1,60 +1,82 @@
# Importeer benodigde modules voor het uitvoeren van HTTP-verzoeken, tijdbeheer, en JSON-operaties.
import requests import requests
import time import time
import json import json
# Importeer MQTT-client functies van een aangepaste module.
from mqtt_client import create_client, start_loop from mqtt_client import create_client, start_loop
publish_interval = 30 # Secondes om een aanvraag te doen - MOET ~300 ZIJN!!!!!!!!! # Stel het interval in seconden in voor het periodiek ophalen en publiceren van data.
publish_interval = 30 # MOET ~300 ZIJN voor productiegebruik.
# Definieer API-eindpunten en de corresponderende MQTT topics.
api_endpoints = [ api_endpoints = [
{"url": "https://garden.inajar.nl/api/devices/", "topic": "goodgarden/devices"}, {"url": "https://garden.inajar.nl/api/devices/", "topic": "goodgarden/devices"},
{"url": "https://garden.inajar.nl/api/relative_humidity_events/", "topic": "goodgarden/relative_humidity"}, # Voeg meer API-eindpunten en topics toe zoals vereist.
{"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): 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("Connected with result code "+str(rc)) print("Connected with result code "+str(rc))
def on_message(client, userdata, msg): 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)}") print(f"Message: {msg.topic} {str(msg.payload)}")
client = create_client("publisher1", on_connect, on_message) # Gebruik een unieke client ID # 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): def publish_to_mqtt(topic, data):
"""
Publiceert data naar een MQTT topic.
json_data = json.dumps(data) # Serialiseer de data naar een JSON-string 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) client.publish(topic, json_data)
print(f"\033[92mData published to MQTT topic {topic}.\033[0m") print(f"\033[92mData published to MQTT topic {topic}.\033[0m")
def fetch_and_publish_data(): def fetch_and_publish_data():
"""
Haalt data op van API-eindpunten en publiceert deze naar MQTT.
"""
for endpoint in api_endpoints: for endpoint in api_endpoints:
url = endpoint["url"] url = endpoint["url"]
mqtt_topic = endpoint["topic"] mqtt_topic = endpoint["topic"]
access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c" access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c" # Voorbeeld token.
try: try:
headers = {"Authorization": f"Token {access_token}"} headers = {"Authorization": f"Token {access_token}"}
response = requests.get(url, headers=headers) response = requests.get(url, headers=headers)
response.raise_for_status() # Zorgt ervoor dat HTTPError wordt opgeworpen voor slechte responses response.raise_for_status() # Verifieert respons status.
data = response.json() data = response.json()
print(f"Data from {url}: {data}") print(f"Data from {url}: {data}")
publish_to_mqtt(mqtt_topic, data) publish_to_mqtt(mqtt_topic, data)
# load_data(data) # Zorg ervoor dat deze functie elders gedefinieerd is
except requests.exceptions.RequestException as e: except requests.exceptions.RequestException as e:
print(f"Error fetching data from {url}: {e}") print(f"Error fetching data from {url}: {e}")
if __name__ == "__main__": if __name__ == "__main__":
client.loop_start() # Start de niet-blokkerende loop client.loop_start() # Start de niet-blokkerende MQTT-client loop.
while True: while True:
fetch_and_publish_data() fetch_and_publish_data() # Haal data op en publiceer.
print(f"\033[91mWachten, wachten en nog eens wachten... {publish_interval} secondes!\033[0m\n") print(f"\033[91mWachten, wachten en nog eens wachten... {publish_interval} secondes!\033[0m\n")
time.sleep(publish_interval) # Wacht voor het ingestelde interval.
time.sleep(publish_interval)
client.loop_stop() client.loop_stop()

View File

@@ -214,6 +214,7 @@ if __name__ == "__main__":
# Update gegevens # Update gegevens
record_id = int(input("Enter record ID to update: ")) record_id = int(input("Enter record ID to update: "))
# Call the update_data function without additional arguments # Call the update_data function without additional arguments
# Roep de update_data function aan zonder arguments
update_data(record_id) update_data(record_id)
elif operation_choice == "D": elif operation_choice == "D":
# Verwijder gegevens # Verwijder gegevens

View File

@@ -1,19 +1,26 @@
# Importeer de mysql.connector module en Error klasse uit deze module.
import mysql.connector import mysql.connector
from mysql.connector import Error from mysql.connector import Error
# Definieer een functie genaamd `database_connect` om verbinding te maken met de database.
def database_connect(): def database_connect():
try: try:
# Maak een verbinding met de MySQL database.
# Specificeer de database credentials en de database naam.
connection = mysql.connector.connect( connection = mysql.connector.connect(
host="localhost", host="localhost", # De hostnaam waar de database draait, in dit geval lokaal.
user="root", user="root", # De gebruikersnaam voor de database.
password="", password="", # Het wachtwoord voor de gebruiker, leeg in dit geval.
database="goodgarden" database="goodgarden" # De naam van de database waarmee je wilt verbinden.
) )
# Controleer of de verbinding succesvol is opgezet.
if connection.is_connected(): 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!") # print("Connection gelukt!")
return connection return connection
except Error as e: 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}") print(f"Connection NIET gelukt! ${e}")
# Als de verbinding niet succesvol was, retourneer None.
return None return None
# database_connect()

View File

@@ -49,9 +49,6 @@ def on_message(client, userdata, message):
print(f"\033[92mMessage received on topic\033[0m {message.topic}: {data}") print(f"\033[92mMessage received on topic\033[0m {message.topic}: {data}")
# def berekenAlgo(data):
if __name__ == "__main__": if __name__ == "__main__":
topic = "goodgarden/devices" topic = "goodgarden/devices"
subscribe.callback(on_message, topic) subscribe.callback(on_message, topic)

View File

@@ -1,25 +1,38 @@
# Importeer de json module om met JSON data te werken.
import json import json
# Importeer de subscribe module van paho.mqtt om te abonneren op MQTT topics.
from paho.mqtt import subscribe from paho.mqtt import subscribe
# Definieer een callback functie die wordt aangeroepen wanneer een bericht wordt ontvangen.
def on_message(client, userdata, message): 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") payload_str = message.payload.decode("utf-8")
# Laad de JSON string in een Python dictionary.
data = json.loads(payload_str) data = json.loads(payload_str)
# Initialiseer variabelen om de waarden van de apparaten op te slaan.
device_322_value = None device_322_value = None
device_256_value = None device_256_value = None
# Doorloop de "results" key in de data dictionary.
for key in data["results"]: for key in data["results"]:
# Controleer of de "device" key overeenkomt met device 322 of 256 en sla de waarde op.
if key["device"] == 322: if key["device"] == 322:
device_322_value = key["value"] device_322_value = key["value"]
elif key["device"] == 256: elif key["device"] == 256:
device_256_value = key["value"] device_256_value = key["value"]
# Print de waarden van beide apparaten.
print(f"Device 322 value: {device_322_value}") print(f"Device 322 value: {device_322_value}")
print(f"Device 256 value: {device_256_value}") print(f"Device 256 value: {device_256_value}")
# Print het volledige bericht dat ontvangen is op het abonnementstopic.
print(f"Message received on topic {message.topic}: {data}") 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__": if __name__ == "__main__":
# Definieer het topic waarop geabonneerd wordt.
topic = "goodgarden/par_events" 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) subscribe.callback(on_message, topic)

View File

@@ -1,51 +1,54 @@
# Importeer de json en mysql.connector modules voor het werken met JSON data en MySQL databases.
# Importeer ook os voor bestandssysteem operaties.
import json import json
import mysql.connector import mysql.connector
import os import os
# Function to make a connection to the database # Functie om een verbinding met de database te maken.
def database_connect(): def database_connect():
return mysql.connector.connect( return mysql.connector.connect(
host="localhost", host="localhost", # De server waar de database draait.
user="root", user="root", # De gebruikersnaam om in te loggen op de database.
password="", password="", # Het wachtwoord voor de gebruiker.
database="goodgarden" database="goodgarden" # De naam van de database waarmee verbinding moet worden gemaakt.
) )
# Function to get the absolute path of the current directory # Functie om het absolute pad van de huidige directory te krijgen.
def get_current_directory(): def get_current_directory():
return os.path.dirname(os.path.abspath(__file__)) 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(): def fetch_plant_and_write_to_json():
# Establish a database connection # Maak verbinding met de database.
connection = database_connect() connection = database_connect()
try: try:
cursor = connection.cursor(dictionary=True) # To fetch rows as dictionaries # Maak een cursorobject aan met dictionary=True om rijen als woordenboeken op te halen.
# Execute the query to fetch data 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") cursor.execute("SELECT id, plant_naam, plantensoort, plant_geteelt FROM planten")
# Fetch all rows # Haal alle rijen op.
plants = cursor.fetchall() plants = cursor.fetchall()
# Get the absolute path of the current directory # Verkrijg het absolute pad van de huidige directory.
current_directory = get_current_directory() current_directory = get_current_directory()
# Construct the absolute path for the JSON file # Construeer het absolute pad voor het JSON-bestand.
json_file_path = os.path.join(current_directory, 'plants.json') json_file_path = os.path.join(current_directory, 'plants.json')
# Write fetched data to JSON file # Schrijf de opgehaalde gegevens naar een JSON-bestand.
with open(json_file_path, 'w') as json_file: with open(json_file_path, 'w') as json_file:
json.dump(plants, json_file, indent=4) json.dump(plants, json_file, indent=4)
except mysql.connector.Error as error: except mysql.connector.Error as error:
# Print de fout als er iets misgaat bij het ophalen van de gegevens.
print("Error fetching data from MySQL table:", error) print("Error fetching data from MySQL table:", error)
finally: finally:
# Close cursor and connection # Sluit de cursor en de verbinding, indien ze bestaan.
if 'cursor' in locals(): if 'cursor' in locals():
cursor.close() cursor.close()
if connection.is_connected(): if connection.is_connected():
connection.close() connection.close()
# Call the function to fetch data and write to JSON # Roept de functie aan om gegevens op te halen en naar JSON te schrijven.
fetch_plant_and_write_to_json() fetch_plant_and_write_to_json()
# if __name__ == "__main__":
# fetch_plant_and_write_to_json()

View File

@@ -1,13 +1,22 @@
# Importeer de json module voor het werken met JSON data.
import json import json
# Importeer de subscribe functie uit de paho.mqtt module voor MQTT-communicatie.
from paho.mqtt import subscribe from paho.mqtt import subscribe
# Definieer een callback functie die wordt aangeroepen wanneer een bericht wordt ontvangen.
def on_message(client, userdata, message): def on_message(client, userdata, message):
# Decodeer de berichtpayload van bytes naar een UTF-8 gecodeerde string.
payload_str = message.payload.decode("utf-8") payload_str = message.payload.decode("utf-8")
# Converteer de JSON string naar een Python dictionary.
data = json.loads(payload_str) 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}") 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__": if __name__ == "__main__":
# Specificeer het MQTT-topic waarop geabonneerd moet worden.
topic = "goodgarden/relative_humidity" 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) subscribe.callback(on_message, topic)

View File

@@ -1,13 +1,24 @@
# De json module wordt geïmporteerd om te werken met JSON-geformatteerde data.
import json 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 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): 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") 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) 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}") 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__": if __name__ == "__main__":
# Het MQTT-topic waarop het script zich abonneert, gerelateerd aan de elektrische geleidbaarheid van de bodem.
topic = "goodgarden/soil_electric_conductivity" 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) subscribe.callback(on_message, topic)

View File

@@ -1,13 +1,22 @@
# Importeer de json module om te werken met JSON data.
import json import json
# Importeer de subscribe functie van paho.mqtt om te abonneren op MQTT berichten.
from paho.mqtt import subscribe 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): def on_message(client, userdata, message):
# Decodeer de berichtpayload van bytes naar een UTF-8 string.
payload_str = message.payload.decode("utf-8") 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) 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}") print(f"Message received on topic {message.topic}: {data}")
# Het hoofdscript dat wordt uitgevoerd wanneer dit bestand direct wordt gerund.
if __name__ == "__main__": 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" 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) subscribe.callback(on_message, topic)

View File

@@ -1,13 +1,22 @@
# Importeer de json module om te werken met JSON-geformatteerde data.
import json import json
# Importeer de subscribe functie van de paho.mqtt bibliotheek voor MQTT communicatie.
from paho.mqtt import subscribe from paho.mqtt import subscribe
# Definieer de on_message functie die wordt uitgevoerd wanneer een bericht wordt ontvangen.
def on_message(client, userdata, message): 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") 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) 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}") 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__": if __name__ == "__main__":
# Definieer het MQTT-topic waarop we willen abonneren, in dit geval bodemtemperatuur.
topic = "goodgarden/soil_temperature" topic = "goodgarden/soil_temperature"
# Start het abonneren op het opgegeven topic met de on_message functie als de callback.
subscribe.callback(on_message, topic) subscribe.callback(on_message, topic)

View File

@@ -1,94 +1,113 @@
// 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"); const { ipcRenderer } = require("electron");
// Importeer Axios voor het maken van HTTP-verzoeken
const axios = require('axios'); const axios = require('axios');
// Function to open the modal /**
function openModal() { * 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 modal = document.getElementById("myModal");
const button = document.getElementById("modalButton"); const button = document.getElementById("modalButton");
const close = document.getElementsByClassName("close")[0]; const close = document.getElementsByClassName("close")[0];
if (modal && button) { // Check if elements are found // Controleer of de elementen bestaan om fouten te voorkomen.
// Toon de modal wanneer op de knop wordt geklikt if (modal && button)
button.onclick = function () { {
// Toon de modaal wanneer op de knop wordt geklikt.
button.onclick = function ()
{
modal.style.display = "block"; modal.style.display = "block";
} }
// Sluit de modal wanneer op het 'sluiten' icoon wordt geklikt // Sluit de modaal wanneer op het 'sluiten' icoon wordt geklikt.
close.onclick = function () { close.onclick = function ()
{
modal.style.display = "none"; modal.style.display = "none";
} }
// Sluit de modal wanneer buiten de modal wordt geklikt // Sluit de modaal wanneer buiten de modaal wordt geklikt.
window.onclick = function (event) { window.onclick = function (event)
if (event.target == modal) { {
if (event.target == modal)
{
modal.style.display = "none"; modal.style.display = "none";
} }
} }
} else { }
console.error("Modal elements not found"); else
{
console.error("Modaal elementen niet gevonden");
} }
} }
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () =>
// Call openModal when DOM content is loaded {
openModal(); openModal();
// Send a message to the main process to execute the Python script // Roep andere functies hier aan zoals vereist, bijvoorbeeld:
// fetchWeatherDataAndDrawChart();
// Stuur een bericht naar het hoofdproces om het Python-script uit te voeren.
ipcRenderer.send('run-python-script', ['some', 'arguments']); ipcRenderer.send('run-python-script', ['some', 'arguments']);
ipcRenderer.on('python-script-response', (event, pythonData) => { // Luister naar updates van HTML-data vanuit het hoofdproces.
if (pythonData === 'error') { ipcRenderer.on('update-html-data', (event, data) =>
console.error('An error occurred while retrieving data from Python'); {
} else { // Werk de HTML bij met de ontvangen data.
// 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; document.getElementById('batteryVoltage').innerText = data.batteryVoltage;
// Add similar lines for other data fields // Voeg vergelijkbare regels toe voor andere data velden.
}); });
// Trigger an event to request data update // Trigger een event om data update aan te vragen.
ipcRenderer.send('request-update-data'); ipcRenderer.send('request-update-data');
// Fetch battery data when the page loads // Haal batterij data op wanneer de pagina laadt.
fetchBatteryData(); fetchBatteryData();
}); });
function drawLineChart() /**
* Functie om een lijngrafiek te tekenen.
* @param {Array} xLabels Labels voor de x-as.
* @param {Array} data De data punten voor de grafiek.
*/
function drawLineChart(xLabels, data)
{ {
/*Dit is de data die getoond wordt als "punt" op de grafiek. 20 = y20 / x20, 50 = y50 / x50 enzovoort... De array "data" & "xLabels" moeten beide evenveel array items hebben!!*/ // Definieer Y labels (niet veranderen volgens commentaar).
const data = [20, 50, 60, 45, 50, 100, 70, 60, 65, 0, 85, 0]; const yLabels = ["", 10, 15, 20, 25, 30, 35, 40];
const xLabels = ["", "", "", "", "", 6, "", "", "", "", "", 12];
const yLabels = ["", 20, "", 40, "", 60, "", 80, "", 100]; /*NIET VERANDEREN!!!*/
// Verkrijg het canvas element en de context voor tekenen.
const canvas = document.getElementById("myCanvas"); const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d"); const ctx = canvas.getContext("2d");
// Maak het canvas schoon voor nieuwe tekening.
ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.clearRect(0, 0, canvas.width, canvas.height);
const padding = 35; // Increased padding for Y labels // Definieer padding en bereken grafiekafmetingen.
const padding = 35; // Vergrote padding voor Y labels.
const graphWidth = canvas.width - padding * 2; const graphWidth = canvas.width - padding * 2;
const graphHeight = canvas.height - padding * 2; const graphHeight = canvas.height - padding * 2;
// Teken de as van de grafiek.
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(padding, padding); ctx.moveTo(padding, padding);
ctx.lineTo(padding, canvas.height - padding); ctx.lineTo(padding, canvas.height - padding);
ctx.lineTo(canvas.width - padding, canvas.height - padding); ctx.lineTo(canvas.width - padding, canvas.height - padding);
ctx.stroke(); ctx.stroke();
// Set the color of the line // Stel de kleur van de lijn in.
ctx.strokeStyle = "rgb(143, 188, 143)"; ctx.strokeStyle = "rgb(143, 188, 143)";
// Bereken incrementen voor het plotten.
const xIncrement = graphWidth / (xLabels.length - 1); const xIncrement = graphWidth / (xLabels.length - 1);
const yIncrement = graphHeight / (yLabels.length - 1); const yIncrement = graphHeight / (yLabels.length - 1);
// Plot the data // Plot de data.
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(padding, canvas.height - padding - (data[0] / 100) * graphHeight); ctx.moveTo(padding, canvas.height - padding - (data[0] / 100) * graphHeight);
@@ -100,10 +119,10 @@ function drawLineChart()
} }
ctx.stroke(); ctx.stroke();
// Draw Y labels // Teken Y labels.
ctx.fillStyle = "black"; ctx.fillStyle = "black";
ctx.textAlign = "right"; // Align text to the right ctx.textAlign = "right"; // Tekst naar rechts uitlijnen.
ctx.textBaseline = "middle"; // Center vertically ctx.textBaseline = "middle"; // Verticaal centreren.
for (let i = 0; i < yLabels.length; i++) for (let i = 0; i < yLabels.length; i++)
{ {
@@ -114,8 +133,8 @@ function drawLineChart()
} }
} }
// Draw X labels // Teken X labels.
ctx.textAlign = "center"; // Center horizontally for X labels ctx.textAlign = "center"; // Horizontaal centreren voor X labels.
for (let i = 0; i < xLabels.length; i++) for (let i = 0; i < xLabels.length; i++)
{ {
if (xLabels[i] !== "") if (xLabels[i] !== "")
@@ -125,59 +144,146 @@ function drawLineChart()
} }
} }
} }
drawLineChart();
// Function to fetch battery data from Flask API /**
function fetchBatteryData() { * Functie om weergegevens op te halen en een grafiek te tekenen.
* Deze functie haalt weergegevens op van een lokale server en tekent een lijngrafiek
* op basis van de verkregen data.
*/
function fetchWeatherDataAndDrawChart()
{
// URL van de API waar de weergegevens opgehaald kunnen worden.
const apiUrl = `http://127.0.0.1:5000/weather`;
// Voer een GET-verzoek uit naar de API.
fetch(apiUrl)
.then(response =>
{
// Controleer of het verzoek succesvol was.
if (response.ok)
{
return response.json();
}
// Gooi een fout als het verzoek niet succesvol was.
throw new Error('Network response was not ok.');
})
.then(data =>
{
// Verkrijg de weersvoorspelling voor de eerste 5 dagen.
const weatherForecast = data.weather_forecast.slice(0, 5);
// Converteer datums naar dagen van de week.
const dates = weatherForecast.map(day => convertDateToDayOfWeek(day.dag));
// Verkrijg de maximale temperaturen.
const temperatures = weatherForecast.map(day => day.max_temp);
// Teken de lijngrafiek met de verkregen data.
drawLineChart(dates, temperatures);
})
.catch(error =>
{
// Log eventuele fouten tijdens het ophalen.
console.error('There was a problem with the fetch operation:', error);
});
}
/**
* Functie om een datum (bijv. "07-02") om te zetten naar de dag van de week (bijv. "zo", "ma", etc.).
* @param {string} dateString - De datum als string in het formaat "dd-mm".
* @returns {string} De afkorting van de dag van de week.
*/
function convertDateToDayOfWeek(dateString)
{
// Split de datum in dag en maand, en zet deze om naar nummers.
const [day, month] = dateString.split('-').map(Number);
// Maak een nieuwe datumobject (jaar is willekeurig omdat we alleen maand en dag nodig hebben).
const date = new Date(2024, month - 1, day);
// Verkrijg de dag van de week en zet deze om naar een afkorting.
const dayOfWeek = ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'][date.getDay()];
return dayOfWeek;
}
/**
* 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') axios.get('http://127.0.0.1:5000')
.then(response => { .then(response =>
{
// Verwerk de ontvangen data.
const batteryData = response.data; const batteryData = response.data;
updateBatteryData(batteryData); updateBatteryData(batteryData);
}) })
.catch(error => { .catch(error =>
{
// Log eventuele fouten tijdens het ophalen.
console.error('Error fetching battery data:', error); 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) function updateBatteryData(batteryData)
{ {
// Update de data voor specifieke apparaten op basis van hun ID.
if (batteryData[1].device_id == 322) if (batteryData[1].device_id == 322)
{ {
document.getElementById('deviceNumber-322').innerHTML = batteryData[1].device_id; document.getElementById('deviceNumber-322').innerHTML = batteryData[1].device_id;
document.getElementById('voltage-322').innerHTML = batteryData[1].label; document.getElementById('voltage-322').innerHTML = batteryData[1].label;
document.getElementById('time-322').innerHTML = batteryData[1].last_seen; document.getElementById('time-322').innerHTML = new Date(batteryData[0].last_seen).toLocaleTimeString();
document.getElementById('tevredenheid-322').innerHTML = batteryData[1].last_battery_voltage; document.getElementById('tevredenheid-322').innerHTML = batteryData[1].last_battery_voltage;
} }
if (batteryData[0].device_id == 256) if (batteryData[0].device_id == 256)
{ {
document.getElementById('deviceNumber-256').innerHTML = batteryData[0].device_id; document.getElementById('deviceNumber-256').innerHTML = batteryData[0].device_id;
document.getElementById('voltage-256').innerHTML = batteryData[0].label; document.getElementById('voltage-256').innerHTML = batteryData[0].label;
document.getElementById('time-256').innerHTML = batteryData[0].last_seen; document.getElementById('time-256').innerHTML = new Date(batteryData[0].last_seen).toLocaleTimeString();
document.getElementById('tevredenheid-256').innerHTML = batteryData[0].last_battery_voltage; document.getElementById('tevredenheid-256').innerHTML = batteryData[0].last_battery_voltage;
} }
console.log(batteryData);
} }
// Definieer de API-sleutel en de stad waarvoor we de weergegevens willen ophalen.
const apiKey = "9516081f15727d063c9e2f08454a2fe9"; const apiKey = "9516081f15727d063c9e2f08454a2fe9";
const city = "Leiden"; const city = "Leiden";
// Maak de URL voor de API-aanroep // Construeer de URL voor de API-aanroep. In dit geval is het een lokale server.
const apiUrl = `https://weerlive.nl/api/weerlive_api_v2.php?key=${apiKey}&locatie=${city}`; const apiUrl = `http://127.0.0.1:5000/weather`;
// Doe een GET-verzoek naar de API // Voer een GET-verzoek uit naar de API om de weergegevens op te halen.
fetch(apiUrl) fetch(apiUrl)
.then(response => { .then(response =>
if (response.ok) { {
// Controleer of de respons van de server in orde is (status code 200).
if (response.ok)
{
// Zo ja, parse de JSON uit de respons.
return response.json(); return response.json();
} }
// Zo niet, gooi een fout.
throw new Error('Network response was not ok.'); throw new Error('Network response was not ok.');
}) })
.then(data => { .then(data =>
// Verwerk de ontvangen weerdata {
// Log de ontvangen data naar de console voor debugging.
console.log(data); console.log(data);
const weatherIcon = data.live_weather.image;
const weatherImageUrl = `https://www.weerlive.nl/delen.php?size=klein&weer=${weatherIcon}`; // Extraheren van de weersvoorspelling voor de eerste vijf dagen.
document.getElementById('weatherImage').src = weatherImageUrl; const weatherForecast = data.weather_forecast.slice(0, 5);
// Haal de dagen op waarvoor de voorspelling geldt.
const dates = weatherForecast.map(day => day.dag);
// Haal de maximale temperaturen op voor deze dagen.
const temperatures = weatherForecast.map(day => day.max_temp);
// Update de grafiek met de nieuwe data.
drawLineChart(dates, temperatures);
}) })
.catch(error => { .catch(error =>
{
// Log eventuele fouten tijdens het ophalen van de data.
console.error('There was a problem with the fetch operation:', error); console.error('There was a problem with the fetch operation:', error);
}); });

View File

@@ -1,52 +1,60 @@
// Definitie van de Plant klasse.
class Plant { class Plant {
// Constructor om een Plant object te initialiseren met data van een dataObject.
constructor(dataObject) { constructor(dataObject) {
// Initialiseren van de eigenschappen van de plant.
this.id = dataObject.id; this.id = dataObject.id;
this.plantNaam = dataObject.plant_naam; // Note the property name change this.plantNaam = dataObject.plant_naam; // Naam van de plant.
this.plantensoort = dataObject.plantensoort; this.plantensoort = dataObject.plantensoort; // Soort van de plant.
this.plantGeteelt = dataObject.plant_geteelt; this.plantGeteelt = dataObject.plant_geteelt; // Geteelt status van de plant.
} }
} }
class PlantGrid { class PlantGrid {
// Constructor om een PlantGrid object te initialiseren.
constructor() { constructor() {
this.grid = []; this.grid = []; // De datastructuur die het raster van planten bevat.
this.cols = 2; // Number of columns this.cols = 2; // Aantal kolommen in het raster.
this.rows = 4; // Number of rows (including the row for the "Add" button) this.rows = 4; // Aantal rijen in het raster (inclusief de rij voor de "Toevoegen" knop).
// Initialize the grid with null values // Initialiseren van het raster met null waarden.
for (let i = 0; i < this.rows; i++) { for (let i = 0; i < this.rows; i++) {
this.grid[i] = new Array(this.cols).fill(null); this.grid[i] = new Array(this.cols).fill(null);
} }
// Load JSON data from the server // Laadt JSON data van de server.
this.loadData(); this.loadData();
} }
// Methode om data te laden.
loadData() { loadData() {
fetch('../script/plants.json') // Assuming your JSON data is stored in 'plants.json' fetch('../script/plants.json') // Veronderstelt dat de JSON data is opgeslagen in 'plants.json'.
.then(response => { .then(response => {
// Controleer of de netwerkrespons ok is.
if (!response.ok) { if (!response.ok) {
throw new Error('Network response was not ok'); throw new Error('Network response was not ok');
} }
return response.json(); return response.json(); // Parse de JSON uit de respons.
}) })
.then(data => { .then(data => {
// Filter de data op planten die geteeld zijn.
const filteredData = data.filter(plantObject => plantObject.plant_geteelt === 1); const filteredData = data.filter(plantObject => plantObject.plant_geteelt === 1);
// Populate the grid with plant objects // Vul het raster met plantobjecten.
filteredData.slice(0, 8).forEach((plantObject, index) => { filteredData.slice(0, 8).forEach((plantObject, index) => {
const plant = new Plant(plantObject); const plant = new Plant(plantObject); // Maak een nieuw Plant object.
const col = index % this.cols; const col = index % this.cols; // Bereken de kolomindex.
const row = Math.floor(index / this.cols); const row = Math.floor(index / this.cols); // Bereken de rijindex.
this.grid[row][col] = plant; this.grid[row][col] = plant; // Voeg de plant toe aan het raster.
}); });
// Display the grid in the HTML table with id "planten" // Toon het raster in de HTML tabel met id "planten".
this.displayGrid(); this.displayGrid();
}) })
.catch(error => console.error('Error loading data:', error)); .catch(error => console.error('Error loading data:', error)); // Log eventuele fouten.
} }
displayGrid() { displayGrid() {
const plantenTable = document.getElementById("planten"); const plantenTable = document.getElementById("planten");
@@ -98,6 +106,61 @@ class PlantGrid {
}); });
} }
displayGrid() {
const plantenTable = document.getElementById("planten"); // Verkrijg de tabel waarin het raster getoond moet worden.
let itemCount = 0; // Teller voor het aantal items in het raster.
this.grid.forEach((row, rowIndex) => {
const tr = document.createElement("tr"); // Maak een tabelrij element.
row.forEach((plant, colIndex) => {
const td = document.createElement("td"); // Maak een tabeldata element.
// Logica om plantitems of de "Toevoegen" knop te verwerken.
if (itemCount < 8) {
if (plant) {
// Verwerk normale plantitems.
// Creëer een link element naar de planteninformatiepagina met plant ID als query parameter.
// Voeg vervolgens een artikel, afbeelding en titel toe met de plantinformatie.
// Handle regular plant items
const link = document.createElement("a");
link.href = `planteninfo.html?id=${plant.id}`;
const article = document.createElement("article");
article.classList.add("plant-container");
link.appendChild(article);
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);
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/Toevoegen.png";
img.id = "toevoegen";
img.alt = "Add";
article.id = "modalButton";
article.onclick = openModal;
td.appendChild(article);
itemCount++;
}
}
tr.appendChild(td); // Voeg de td toe aan de tr.
});
plantenTable.appendChild(tr); // Voeg de tr toe aan de tabel.
});
}
} }
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {

View File

@@ -22,19 +22,14 @@
<section class="content"> <section class="content">
<section class="kant-links"> <section class="kant-links">
<table id="planten"> <table id="planten">
<!-- <tr>
<td>
<article>
<img src="images/Icon awesome-apple-alt.png" alt="">
<h2>Tomaat</h2>
</article>
</td>
</tr> -->
</table> </table>
<!-- Modal voor het toevoegen van nieuwe planten -->
<div id="myModal" class="modal"> <div id="myModal" class="modal">
<!-- Sluitknop voor de modal -->
<span class="close">&times;</span> <span class="close">&times;</span>
<!-- Formulier voor het toevoegen van nieuwe planten -->
<form action="http://localhost:3000/submit-form" method="post" onsubmit="return addplant()"> <form action="http://localhost:3000/submit-form" method="post" onsubmit="return addplant()">
<!-- Velden voor het invullen van plantinformatie -->
<input type="text" name="plant_naam" id="plantNaam"> <input type="text" name="plant_naam" id="plantNaam">
<label for="plantNaam">Naam van de plant</label> <label for="plantNaam">Naam van de plant</label>
@@ -49,40 +44,18 @@
<input type="submit" value="Submit"> <input type="submit" value="Submit">
</form> </form>
</div> </div>
<div id="overlay" onclick="closeOverlay"></div> <div id="overlay" onclick="closeOverlay"></div>
</section> </section>
<section class="kant-rechts"> <section class="kant-rechts">
<!-- Sectie voor sensorinformatie -->
<section id="sectie-1"> <section id="sectie-1">
<!-- <article class="parent-algemeen-overzicht"> <!-- Container voor algemene overzichtinformatie -->
<article class="algemeen-overzicht">
<a href="kas_informatie.html">
<table class="table-informatie-kas">
<tr class="tr-informatie-kas">
<td>Planten aanwezig in kas:</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>
<tr class="tr-informatie-kas">
<td>Aandachtspunten</td>
<td>1</td>
</tr>
</table>
<a/>
</article>
</article> -->
<!-- SENSOR 1 -->
<article class="parent-algemeen-overzicht"> <article class="parent-algemeen-overzicht">
<article class="algemeen-overzicht"> <article class="algemeen-overzicht">
<!-- Link naar pagina met meer details over de sensoren -->
<a href="sensoren.html"> <a href="sensoren.html">
<!-- Tabel met sensorinformatie -->
<table class="table-informatie-kas"> <table class="table-informatie-kas">
<tr class="tr-informatie-kas"> <tr class="tr-informatie-kas">
<td>Sensor:</td> <td>Sensor:</td>
@@ -104,7 +77,6 @@
<a/> <a/>
</article> </article>
</article> </article>
<!-- SENSOR 2 -->
<article class="parent-algemeen-overzicht"> <article class="parent-algemeen-overzicht">
<article class="algemeen-overzicht"> <article class="algemeen-overzicht">
<a href="sensoren.html"> <a href="sensoren.html">

View File

@@ -17,32 +17,37 @@
<img src="../static/images/logo.png" class="goodgarden-logo"> <img src="../static/images/logo.png" class="goodgarden-logo">
</a> </a>
</article> </article>
<!-- De container die de inhoud van de informatiepagina bevat -->
<section class="mainBorder informatie-kas-main-container"> <section class="mainBorder informatie-kas-main-container">
<article> <article>
<h1 class="pagina-titel">Informatie Kas</h1> <h1 class="pagina-titel">Informatie Kas</h1>
<!-- Sectie met overzicht van de kas gegevens -->
<section id="sectie-1"> <section id="sectie-1">
<!-- Weergave van sensor data en kascondities -->
<article class="parent-algemeen-overzicht"> <article class="parent-algemeen-overzicht">
<article class="algemeen-overzicht"> <article class="algemeen-overzicht">
<!-- Tabel voor het weergeven van sensorgegevens -->
<table class="table-informatie-kas"> <table class="table-informatie-kas">
<tr class="tr-informatie-kas"> <tr class="tr-informatie-kas">
<td>Device</td> <td>Device</td>
<td id="deviceNumber"></td> <!-- Update this ID --> <td id="deviceNumber"></td>
</tr> </tr>
<tr class="tr-informatie-kas"> <tr class="tr-informatie-kas">
<td>Batterij Voltage</td> <td>Batterij Voltage</td>
<td id="voltage"></td> <!-- Update this ID --> <td id="voltage"></td>
</tr> </tr>
<tr class="tr-informatie-kas"> <tr class="tr-informatie-kas">
<td>Tijden</td> <td>Tijden</td>
<td id="time"></td> <!-- Update this ID --> <td id="time"></td>
</tr> </tr>
<tr class="tr-informatie-kas"> <tr class="tr-informatie-kas">
<td>Zulu</td> <td>Zulu</td>
<td id="zulu"></td> <!-- Update this ID --> <td id="zulu"></td>
</tr> </tr>
</table> </table>
</article> </article>
</article> </article>
<!-- Weergave van zonlichtdata in een grafiek -->
<article class="grafiek"> <article class="grafiek">
<article class="grafiek-innerbox"> <article class="grafiek-innerbox">
<h2>Zonlicht</h2> <h2>Zonlicht</h2>
@@ -56,10 +61,13 @@
</article> </article>
</section> </section>
</article> </article>
<!-- Sectie met aanvullende informatie over de kas in tabelvorm -->
<article class="grid-column-2"> <article class="grid-column-2">
<article class="grid-2-child"> <article class="grid-2-child">
<section class="parent-table"> <section class="parent-table">
<!-- Verschillende tabellen voor gedetailleerde informatie -->
<table class="kas-table-1"> <table class="kas-table-1">
<!-- Rijen met specifieke kas informatie, zoals aantal geplante en geoogste planten -->
<tr> <tr>
<td>Aantal geplant:</td> <td>Aantal geplant:</td>
<td id="totale_planten">Loading...</td> <td id="totale_planten">Loading...</td>
@@ -74,6 +82,7 @@
</tr> </tr>
</table> </table>
<table class="kas-table-2"> <table class="kas-table-2">
<!-- Rijen met klimaat- en bodemcondities -->
<tr> <tr>
<td>Warmste Maand:</td> <td>Warmste Maand:</td>
<td>n.v.t.</td> <td>n.v.t.</td>
@@ -92,6 +101,7 @@
</tr> </tr>
</table> </table>
<table class="kas-table-3"> <table class="kas-table-3">
<!-- Rijen met irrigatie- en bemestingschema's -->
<tr> <tr>
<td>Laatste Irrigatie:</td> <td>Laatste Irrigatie:</td>
<td>2u</td> <td>2u</td>
@@ -115,12 +125,6 @@
</section> </section>
</section> </section>
<script> <script>
// fetch('get_data.php')
// .then(response => response.json())
// .then(data => {
// document.getElementById('totale_planten').innerHTML = data.totale_planten;
// })
// .catch(error => console.error('Error:', error));
</script> </script>
</body> </body>
</html> </html>

View File

@@ -17,13 +17,18 @@
<img src="../static/images/logo.png" class="goodgarden-logo"> <img src="../static/images/logo.png" class="goodgarden-logo">
</a> </a>
</article> </article>
<!-- Bevat de primaire inhoud van de pagina -->
<section class="mainBorder informatie-kas-main-container"> <section class="mainBorder informatie-kas-main-container">
<article> <article>
<h1>Informatie Kas</h1> <h1>Informatie Kas</h1>
<!-- Bevat een overzicht van algemene informatie en grafieken -->
<section id="sectie-1"> <section id="sectie-1">
<!-- Weergave van belangrijke kasstatistieken -->
<article class="parent-algemeen-overzicht"> <article class="parent-algemeen-overzicht">
<article class="algemeen-overzicht"> <article class="algemeen-overzicht">
<!-- Tabel met statische data over de kas -->
<table class="table-informatie-kas"> <table class="table-informatie-kas">
<!-- Rijen met specifieke informatie zoals dagen tot oogst en tevredenheid -->
<tr class="tr-informatie-kas"> <tr class="tr-informatie-kas">
<td>Dagen tot Oogst</td> <td>Dagen tot Oogst</td>
<td>12</td> <td>12</td>
@@ -43,6 +48,7 @@
</table> </table>
</article> </article>
</article> </article>
<!-- Sectie voor het weergeven van een grafiek over zonlicht -->
<article class="grafiek"> <article class="grafiek">
<article class="grafiek-innerbox"> <article class="grafiek-innerbox">
<h2>Zonlicht</h2> <h2>Zonlicht</h2>
@@ -56,10 +62,13 @@
</article> </article>
</section> </section>
</article> </article>
<!-- Presenteert aanvullende informatie in tabelvorm -->
<article class="grid-column-2"> <article class="grid-column-2">
<article class="grid-2-child"> <article class="grid-2-child">
<section class="parent-table"> <section class="parent-table">
<!-- Meerdere tabellen met informatie over geplante aantallen, oogstresultaten en klimaatcondities -->
<table class="kas-table-1"> <table class="kas-table-1">
<!-- Details over geplant aantal, succesvolle en gefaalde oogst -->
<tr> <tr>
<td>Aantal geplant:</td> <td>Aantal geplant:</td>
<td>2</td> <td>2</td>
@@ -74,6 +83,7 @@
</tr> </tr>
</table> </table>
<table class="kas-table-2"> <table class="kas-table-2">
<!-- Informatie over de klimaatcondities zoals de warmste en koudste maand, gemiddelde bodemtemperatuur en zonlichturen -->
<tr> <tr>
<td>Warmste Maand:</td> <td>Warmste Maand:</td>
<td>n.v.t.</td> <td>n.v.t.</td>
@@ -92,6 +102,7 @@
</tr> </tr>
</table> </table>
<table class="kas-table-3"> <table class="kas-table-3">
<!-- Schema voor irrigatie en bemesting -->
<tr> <tr>
<td>Laatste Irrigatie:</td> <td>Laatste Irrigatie:</td>
<td>2u</td> <td>2u</td>