planten class V1.1

This commit is contained in:
Renzo
2024-03-20 13:26:00 +01:00
60 changed files with 6458 additions and 3480 deletions

5
.gitignore vendored
View File

@@ -1 +1,4 @@
node_modules/ node_modules/
__pycache__/
venv/
.vscode/

13
.hintrc Normal file
View File

@@ -0,0 +1,13 @@
{
"extends": [
"development"
],
"hints": {
"axe/text-alternatives": [
"default",
{
"image-alt": "off"
}
]
}
}

View File

@@ -1,24 +1,33 @@
# GoodGarden # GoodGarden
Welkom bij ons project genaamd "GoodGarden". Wij hebben besloten om er een monolitische project van te maken. Alles is te vinden binnen deze repository. 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 ### Vereisten
* Python * Python
* Node.Js * Node.Js
* XAMPP (of andere naar keuze) * XAMPP (of andere naar keuze)
* MQTT Geinstalleerd en toegevoegd aan je PATH variable
### Installeren ### 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: 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 electron
- npm install express npm install express
- npm install body-parser npm install body-parser
- npm install python-shell 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
- pip install mysql-connector-python
- pip install requests
## Gebruik ## Gebruik

107
app.js
View File

@@ -1,68 +1,109 @@
const { app, BrowserWindow, ipcMain } = require('electron'); const { app, BrowserWindow, ipcMain } = require("electron");
const express = require('express'); const express = require("express");
const bodyParser = require('body-parser'); const bodyParser = require("body-parser");
const { PythonShell } = require('python-shell'); const { PythonShell } = require("python-shell");
const path = require('path'); const path = require("path");
const urlElectron = path.join(__dirname, "src/index.html"); const urlElectron = path.join(__dirname, "src/index.html");
// Maak een Express-app
const server = express(); const server = express();
server.use(bodyParser.urlencoded({ extended: true })); server.use(bodyParser.urlencoded({ extended: true }));
// Definieer een route voor form POST verzoeken // Define a route for form POST requests
server.post('/submit-form', (req, res) => { server.post("/submit-form", (req, res) => {
const { plant_naam, plantensoort } = req.body; // Verkrijg de plant_naam uit het formulier const { plant_naam, plantensoort } = req.body;
const plant_geteelt = req.body.plant_geteelt == 'true' ? 'true' : 'false'; // Zorgt dat de string "true" herkent wordt const plant_geteelt = req.body.plant_geteelt == "true" ? "true" : "false";
let options = { let options = {
mode: 'text', mode: "text",
args: [plant_naam, plantensoort, plant_geteelt] // Zet hier een variable bij om de data toe te voegen aan de database args: [plant_naam, plantensoort, plant_geteelt],
}; };
// Voer Python script uit met de plant_naam als argument // Execute Python script with plant name as an argument
PythonShell.run('./script/db_connect_form.py', options, (err, results) => { PythonShell.run(
if (err) { "src/py/script/db_connect_form.py",
console.error(err); options,
res.send('Er is een fout opgetreden'); (err, results) => {
} else { if (err) {
console.log('Python script uitvoering resultaten:', results); console.error(err);
res.send('Formulier succesvol verwerkt'); res.send("Er is een fout opgetreden");
} else {
console.log("Python script uitvoering resultaten:", results);
res.send("Formulier succesvol verwerkt");
}
} }
}); );
}); });
// Start de server voor verbinding met de database // Start the server
const PORT = 3000; const PORT = 3000;
server.listen(PORT, () => { server.listen(PORT, () => {
console.log(`Server luistert op port ${PORT}`); console.log(`Server is listening on port ${PORT}`);
}); });
// Maak de Electron applicatie aan met bijbehorende waardes let mainWindow;
// Create the Electron application window
function createWindow() { function createWindow() {
const mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 1280, width: 1280,
height: 800, height: 800,
frame: false, frame: false,
icon: path.join(__dirname, "src/py/static/images/logo.png"),
webPreferences: { webPreferences: {
nodeIntegration: true, nodeIntegration: true,
contextIsolation: false contextIsolation: false,
} enableRemoteModule: true,
webSecurity: true,
},
}); });
mainWindow.loadURL(urlElectron); mainWindow.loadFile(
path.join(__dirname, "src", "py", "templates", "index.html")
);
// IPC event listeners for running Python scripts and updating HTML data
setupIpcMainListeners();
} }
// Start the Electron app
app.whenReady().then(createWindow); app.whenReady().then(createWindow);
// Functionaliteit voor het openen en sluiten van de app // Close the app when all windows are closed, except on macOS
app.on('window-all-closed', () => { app.on("window-all-closed", () => {
if (process.platform !== 'darwin') { if (process.platform !== "darwin") {
app.quit(); app.quit();
} }
}); });
app.on('activate', () => { // Re-create a window in the app when the dock icon is clicked and there are no other windows open.
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) { if (BrowserWindow.getAllWindows().length === 0) {
createWindow(); createWindow();
} }
}); });
function setupIpcMainListeners() {
ipcMain.on("run-python-script", (event, args) => {
let options = {
mode: "text",
args: args,
};
// The actual script path and event replies should be tailored to your application's needs
});
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 });
});
ipcMain.on("update-html-data", (event, data) => {
mainWindow.webContents.send("update-html-data", data);
});
}

50
app.py Normal file
View File

@@ -0,0 +1,50 @@
from flask import Flask, jsonify
import mysql.connector
app = Flask(__name__)
# Function to get data from the MySQL database
def get_database_data():
try:
connection = mysql.connector.connect(
host='localhost',
user='root',
password='',
database='goodgarden'
)
cursor = connection.cursor()
# Query to retrieve the latest battery voltage data
query = "SELECT id, timestamp, gateway_receive_time, device, value FROM battery_voltage_events ORDER BY timestamp DESC LIMIT 1"
cursor.execute(query)
battery_data = cursor.fetchone()
connection.close()
return battery_data
except Exception as e:
print("Error fetching data from database:", e)
return None
@app.route('/', methods=['GET'])
def get_data():
# Get data from the database
battery_data = get_database_data()
if battery_data is None:
return jsonify({"error": "Failed to fetch data from database"})
# Convert the fetched data into a dictionary
data_dict = {
"id": battery_data[0],
"timestamp": str(battery_data[1]), # Convert timestamp to string for JSON serialization
"gateway_receive_time": str(battery_data[2]), # Convert timestamp to string for JSON serialization
"device": battery_data[3],
"value": battery_data[4]
}
# Return the data as JSON
return jsonify(data_dict)
if __name__ == "__main__":
app.run(host='127.0.0.1', port=5000)

View File

@@ -1,190 +1,8 @@
# import requests #** TYPE IN TERMINAL: "pip install requests"
# import time
# import mysql.connector #** TYPE IN TERMINAL: "pip install mysql-connector-python"
# # Import python db_connect.py script
# 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}:")
# print(data)
# insert_data(data)
# except requests.exceptions.RequestException as e:
# print(f"Error fetching data from {url}: {e}")
# print("Waiting for the next create action...")
# time.sleep(10)
# # time.sleep(300)
# # Functie voor het invoegen van gegevens in de database
# def insert_data(data):
# mydb = database_connect()
# if mydb.is_connected():
# mycursor = mydb.cursor()
# insert_query = """
# INSERT INTO goodgarden.battery_voltage_events (timestamp, gateway_receive_time, device, value)
# VALUES (%s, %s, %s, %s)
# """
# for record in data['results']: # 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}")
# # 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()
# # 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}:")
# print(data)
# except requests.exceptions.RequestException as e:
# print(f"Error fetching data from {url}: {e}")
# # Wacht een bepaalde tijd in secondes
# print("Waiting for the next read action...")
# time.sleep(300)
# # Functie voor het bijwerken van gegevens in de database
# def update_data(record_id, new_value):
# 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
# # Hier moet je de juiste kolomnamen aanpassen op basis van de structuur van je database
# update_query = """
# UPDATE goodgarden.battery_voltage_events
# SET 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 value: {new_value}")
# mycursor.execute(update_query, (new_value, record_id)) # Provide the tuple with values here
# # 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.")
# if __name__ == "__main__":
# url = "https://garden.inajar.nl/api/battery_voltage_events/?format=json"
# access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c"
# repeat_count = 10
# operation_choice = input("Choose operation (C for Create, R for Read, U for Update, D for Delete): ").upper()
# # Maak gegevens aan
# if operation_choice == "C":
# create_data(url, access_token, repeat_count)
# # Lees gegevens
# elif operation_choice == "R":
# read_data(url, access_token, repeat_count)
# # Update gegevens
# elif operation_choice == "U":
# record_id = int(input("Enter record ID to update: "))
# new_value = input("Enter new value: ")
# update_data(record_id, new_value)
# # Verwijder gegevens
# elif operation_choice == "D":
# 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.")
import mysql.connector import mysql.connector
import requests import requests
from datetime import datetime, timezone, timedelta from datetime import datetime, timezone, timedelta
import time import time
import os
# import paho.mqtt.client as mqtt
# from dotenv import load_dotenv
# Functie om verbinding te maken met de database # Functie om verbinding te maken met de database
def database_connect(): def database_connect():
return mysql.connector.connect( return mysql.connector.connect(
@@ -193,18 +11,17 @@ def database_connect():
password="", password="",
database="goodgarden" database="goodgarden"
) )
def calculate_timestamp(gateway_receive_time): def calculate_timestamp(gateway_receive_time):
# Converteer de stringrepresentatie naar een datetime-object in UTC # Converteer de stringrepresentatie naar een datetime-object in UTC
datetime_obj_utc = datetime.strptime(gateway_receive_time, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=timezone.utc) datetime_obj_utc = datetime.strptime(gateway_receive_time, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=timezone.utc)
# Voeg het tijdsverschil van 1 uur toe voor de Nederlandse tijdzone (UTC+1) # Voeg het tijdsverschil van 1 uur toe voor de Nederlandse tijdzone (UTC+1)
datetime_obj_nl = datetime_obj_utc + timedelta(hours=0) datetime_obj_nl = datetime_obj_utc + timedelta(hours=1)
# Formateer het datetime-object als een leesbare datumstring # Formateer het datetime-object als een leesbare datumstring
formatted_date = datetime_obj_nl.strftime("%Y-%m-%d %H:%M:%S") formatted_date = datetime_obj_nl.strftime("%Y-%m-%d %H:%M:%S")
return formatted_date return formatted_date
# Functie voor het aanmaken van gegevens in de database # Functie voor het aanmaken van gegevens in de database
def create_data(url, access_token, repeat_count=5): def create_data(url, access_token, repeat_count=5):
for _ in range(repeat_count): for _ in range(repeat_count):
@@ -212,10 +29,10 @@ def create_data(url, access_token, repeat_count=5):
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() response.raise_for_status()
data = response.json() data = response.json()
print(f"Data from {url}:\n") print(f"Data from {url}:\n")
# Check if data is a list (records directly under the root) # Check if data is a list (records directly under the root)
if isinstance(data, list): if isinstance(data, list):
records = data records = data
@@ -224,17 +41,17 @@ def create_data(url, access_token, repeat_count=5):
else: else:
print(f"Unexpected data format received: {data}") print(f"Unexpected data format received: {data}")
continue continue
for record in records: for record in records:
# Now, record is assumed to be a dictionary # Now, record is assumed to be a dictionary
timestamp = record.get('timestamp', '') timestamp = record.get('timestamp', '')
gateway_receive_time = record.get('gateway_receive_time', '') gateway_receive_time = record.get('gateway_receive_time', '')
device = record.get('device', '') device = record.get('device', '')
value = record.get('value', '') value = record.get('value', '')
# Voeg de timestamp-berekening toe # Voeg de timestamp-berekening toe
calculated_timestamp = calculate_timestamp(gateway_receive_time) calculated_timestamp = calculate_timestamp(gateway_receive_time)
print(f"\nInserted data: Timestamp: {calculated_timestamp}, Device: {device}, Battery Voltage: {value}V") print(f"\nInserted data: Timestamp: {calculated_timestamp}, Device: {device}, Battery Voltage: {value}V")
if float(value) < 3.0: if float(value) < 3.0:
print("Waarschuwing: Batterijspanning is lager dan 3.0 volt. Opladen aanbevolen.\n") print("Waarschuwing: Batterijspanning is lager dan 3.0 volt. Opladen aanbevolen.\n")
@@ -243,47 +60,51 @@ def create_data(url, access_token, repeat_count=5):
print("Melding: Batterijspanning is hoger dan 4.2 volt. Batterij is vol.\n") print("Melding: Batterijspanning is hoger dan 4.2 volt. Batterij is vol.\n")
else: else:
print("Melding: Batterijspanning is binnen het gewenste bereik.\n\n") print("Melding: Batterijspanning is binnen het gewenste bereik.\n\n")
# Insert data into the database # Insert data into the database
insert_data(record) insert_data(record)
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}")
print("Waiting for the next create action...\n") print("Waiting for the next create action...\n")
time.sleep(2) time.sleep(2)
# Functie voor het invoegen van gegevens in de database
def insert_data(record): def insert_data(record):
mydb = database_connect() mydb = database_connect()
if mydb.is_connected(): if mydb.is_connected():
mycursor = mydb.cursor() mycursor = mydb.cursor()
# Hier moet je de juiste kolomnamen en gegevensindeling aanpassen op basis van de API-respons # Hier moet je de juiste kolomnamen en gegevensindeling aanpassen op basis van de API-respons
insert_query = """ insert_query = """
INSERT INTO goodgarden.battery_voltage_events (timestamp, gateway_receive_time, device, value) INSERT INTO goodgarden.battery_voltage_events (timestamp, gateway_receive_time, device, value)
VALUES (%s, %s, %s, %s) VALUES (%s, %s, %s, %s)
""" """
# Pas dit aan op basis van de werkelijke structuur van de JSON
timestamp = calculate_timestamp(record.get('gateway_receive_time', '')) try:
gateway_receive_time = record.get('gateway_receive_time', '') # Voer de query uit zonder de timestamp te berekenen
device = record.get('device', '') timestamp = record.get('timestamp', '')
value = record.get('value', '') gateway_receive_time = record.get('gateway_receive_time', '')
device = record.get('device', '')
print(f"Inserting data: timestamp={timestamp}, gateway_receive_time={gateway_receive_time}, device={device}, value={value}\n\n") # Print de ingevoerde gegevens value = record.get('value', '')
# Voer de query uit print(f"Inserting data: timestamp={timestamp}, gateway_receive_time={gateway_receive_time}, device={device}, value={value}\n") # Print de ingevoerde gegevens
mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
# Bevestig de wijzigingen
mydb.commit() # Bevestig de wijzigingen
mydb.commit()
# Sluit cursor en verbinding
mycursor.close() print("Data inserted into the database.")
mydb.close()
except mysql.connector.Error as err:
print("Data inserted into the database.") print(f"Error: {err}")
finally:
# Sluit cursor en verbinding
mycursor.close()
mydb.close()
# Functie voor het lezen van gegevens uit de database # Functie voor het lezen van gegevens uit de database
def read_data(url, access_token, repeat_count=5): def read_data(url, access_token, repeat_count=5):
for _ in range(repeat_count): for _ in range(repeat_count):
@@ -291,16 +112,16 @@ def read_data(url, access_token, repeat_count=5):
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() response.raise_for_status()
data = response.json() data = response.json()
print(f"Data from {url}:\n") print(f"Data from {url}:\n")
for record in data['results']: for record in data['results']:
timestamp = record.get('timestamp', '') timestamp = record.get('timestamp', '')
device = record.get('device', '') device = record.get('device', '')
value = record.get('value', '') value = record.get('value', '')
print(f"Timestamp: {timestamp}, Device: {device}, Battery Voltage: {value}V\n") print(f"Timestamp: {timestamp}, Device: {device}, Battery Voltage: {value}V\n")
if float(value) < 3.0: if float(value) < 3.0:
print("Waarschuwing: Batterijspanning is lager dan 3.0 volt. Opladen aanbevolen.\n") 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 # Controleer of de batterijspanning hoger is dan 4.2 volt en geef een melding
@@ -308,53 +129,53 @@ def read_data(url, access_token, repeat_count=5):
print("Melding: Batterijspanning is hoger dan 4.2 volt. Batterij is vol.\n") print("Melding: Batterijspanning is hoger dan 4.2 volt. Batterij is vol.\n")
else: else:
print("Melding: Batterijspanning is binnen het gewenste bereik.\n\n") print("Melding: Batterijspanning is binnen het gewenste bereik.\n\n")
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}")
print("Waiting for the next read action...\n") print("Waiting for the next read action...\n")
time.sleep(300) time.sleep(300)
# Functie voor het bijwerken van gegevens in de database # Functie voor het bijwerken van gegevens in de database
def update_data(record_id): def update_data(record_id):
try: try:
mydb = database_connect() mydb = database_connect()
if mydb.is_connected(): if mydb.is_connected():
mycursor = mydb.cursor() mycursor = mydb.cursor()
# Controleer of het record bestaat voordat je het bijwerkt # Controleer of het record bestaat voordat je het bijwerkt
mycursor.execute("SELECT * FROM goodgarden.battery_voltage_events WHERE id = %s", (record_id,)) mycursor.execute("SELECT * FROM goodgarden.battery_voltage_events WHERE id = %s", (record_id,))
existing_record = mycursor.fetchone() existing_record = mycursor.fetchone()
if not existing_record: if not existing_record:
print(f"Record with ID {record_id} not found. Update operation aborted.") print(f"Record with ID {record_id} not found. Update operation aborted.")
return return
# Vraag de gebruiker om nieuwe waarden voor de andere velden # Vraag de gebruiker om nieuwe waarden voor de andere velden
new_timestamp = input("Enter new timestamp: ") new_timestamp = input("Enter new timestamp: ")
new_gateway_receive_time = input("Enter new gateway_receive_time: ") new_gateway_receive_time = input("Enter new gateway_receive_time: ")
new_device = input("Enter new device: ") new_device = input("Enter new device: ")
new_value = input("Enter new value: ") new_value = input("Enter new value: ")
# Hier moet je de juiste kolomnamen aanpassen op basis van de structuur van je database # Hier moet je de juiste kolomnamen aanpassen op basis van de structuur van je database
update_query = """ update_query = """
UPDATE goodgarden.battery_voltage_events UPDATE goodgarden.battery_voltage_events
SET timestamp = %s, gateway_receive_time = %s, device = %s, value = %s SET timestamp = %s, gateway_receive_time = %s, device = %s, value = %s
WHERE id = %s WHERE id = %s
""" """
# Voer de query uit # Voer de query uit
print(f"Executing update query: {update_query}") 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}") 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)) mycursor.execute(update_query, (new_timestamp, new_gateway_receive_time, new_device, new_value, record_id))
# Bevestig de wijzigingen # Bevestig de wijzigingen
mydb.commit() mydb.commit()
print(f"Update executed. Rowcount: {mycursor.rowcount}") print(f"Update executed. Rowcount: {mycursor.rowcount}")
except mysql.connector.Error as update_err: except mysql.connector.Error as update_err:
print(f"Error updating data: {update_err}") print(f"Error updating data: {update_err}")
finally: finally:
@@ -363,42 +184,42 @@ def update_data(record_id):
mycursor.close() mycursor.close()
if 'mydb' in locals() and mydb.is_connected(): if 'mydb' in locals() and mydb.is_connected():
mydb.close() mydb.close()
# Functie voor het verwijderen van gegevens uit de database # Functie voor het verwijderen van gegevens uit de database
def delete_data(record_id): def delete_data(record_id):
mydb = database_connect() mydb = database_connect()
if mydb.is_connected(): if mydb.is_connected():
mycursor = mydb.cursor() mycursor = mydb.cursor()
# Hier moet je de juiste kolomnamen aanpassen op basis van de structuur van je database # Hier moet je de juiste kolomnamen aanpassen op basis van de structuur van je database
delete_query = """ delete_query = """
DELETE FROM goodgarden.battery_voltage_events DELETE FROM goodgarden.battery_voltage_events
WHERE id = %s WHERE id = %s
""" """
# Voer de query uit # Voer de query uit
mycursor.execute(delete_query, (record_id,)) mycursor.execute(delete_query, (record_id,))
# Bevestig de wijzigingen # Bevestig de wijzigingen
mydb.commit() mydb.commit()
# Sluit cursor en verbinding # Sluit cursor en verbinding
mycursor.close() mycursor.close()
mydb.close() mydb.close()
print(f"Data with ID {record_id} deleted.") print(f"Data with ID {record_id} deleted.")
# Functie voor het aanmaken van gegevens in de database op basis van batterijspanningsinformatie # Functie voor het aanmaken van gegevens in de database op basis van batterijspanningsinformatie
if __name__ == "__main__": if __name__ == "__main__":
url = "https://garden.inajar.nl/api/battery_voltage_events/?format=json" url = "https://garden.inajar.nl/api/battery_voltage_events/?format=json"
access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c" # Vervang dit door je werkelijke toegangstoken access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c" # Vervang dit door je werkelijke toegangstoken
# Je kunt repeat_count wijzigen om te bepalen hoe vaak je de bewerking wilt herhalen # Je kunt repeat_count wijzigen om te bepalen hoe vaak je de bewerking wilt herhalen
repeat_count = 10 repeat_count = 10
# Keuze voor de bewerking # Keuze voor de bewerking
operation_choice = input("Choose operation (C for Create, R for Read, U for Update, D for Delete): ").upper() operation_choice = input("Choose operation (C for Create, R for Read, U for Update, D for Delete): ").upper()
if operation_choice == "C": if operation_choice == "C":
# Maak gegevens aan # Maak gegevens aan
create_data(url, access_token, repeat_count) create_data(url, access_token, repeat_count)
@@ -415,4 +236,4 @@ if __name__ == "__main__":
record_id = int(input("Enter record ID to delete: ")) record_id = int(input("Enter record ID to delete: "))
delete_data(record_id) delete_data(record_id)
else: else:
print("Invalid operation choice. Please choose C, R, U, or D.") print("Invalid operation choice. Please choose C, R, U, or D.")

316
goodgarden.sql Normal file
View File

@@ -0,0 +1,316 @@
-- phpMyAdmin SQL Dump
-- version 5.2.1
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1
-- Gegenereerd op: 20 mrt 2024 om 10:19
-- Serverversie: 10.4.32-MariaDB
-- PHP-versie: 8.2.12
DROP DATABASE IF EXISTS goodgarden;
CREATE DATABASE goodgarden;
USE goodgarden;
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`
--
-- --------------------------------------------------------
--
-- 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 `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
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- --------------------------------------------------------
--
-- 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(20) UNSIGNED NOT NULL,
`plant_naam` varchar(255) DEFAULT NULL,
`plantensoort` varchar(255) DEFAULT NULL,
`plant_geteelt` tinyint(1) DEFAULT 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
(47, 'Tomaten', 'Groente', 1),
(49, 'Komkommer', 'Groente', 1),
(50, 'Appel', 'Fruit', 1),
(51, 'Sla', 'Groente', 1),
(52, 'Wietplant', 'Onkruid', 0);
-- --------------------------------------------------------
--
-- 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 `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`),
ADD UNIQUE KEY `plant_naam` (`plant_naam`);
--
-- 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=15;
--
-- 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(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=53;
--
-- 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;
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 */;

Binary file not shown.

Binary file not shown.

Binary file not shown.

16
mqtt/db_connect.py Normal file
View File

@@ -0,0 +1,16 @@
import mysql.connector
from mysql.connector import Error
def database_connect():
try:
connection = mysql.connector.connect(
host="localhost",
user="root",
password="",
database="goodgarden"
)
if connection.is_connected():
return connection
except Error as e:
print(f"Connection NIET gelukt! ${e}")
return None

15
mqtt/mqtt_client.py Normal file
View File

@@ -0,0 +1,15 @@
import paho.mqtt.client as mqtt
def create_client(client_id, on_connect, on_message, broker="localhost", port=1883):
client = mqtt.Client(client_id)
client.on_connect = on_connect
client.on_message = on_message
client.connect(broker, port, 60)
return client
def start_loop(client):
try:
client.loop_forever()
except KeyboardInterrupt:
print("Disconnecting from broker")

60
mqtt/publisher.py Normal file
View File

@@ -0,0 +1,60 @@
import requests
import time
import json
from mqtt_client import create_client, start_loop
publish_interval = 30 # Secondes om een aanvraag te doen - MOET ~300 ZIJN!!!!!!!!!
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):
print("Connected with result code "+str(rc))
def on_message(client, userdata, msg):
print(f"Message: {msg.topic} {str(msg.payload)}")
client = create_client("publisher1", on_connect, on_message) # Gebruik een unieke client ID
def publish_to_mqtt(topic, data):
json_data = json.dumps(data) # Serialiseer de data naar een JSON-string
client.publish(topic, json_data)
print(f"\033[92mData published to MQTT topic {topic}.\033[0m")
def fetch_and_publish_data():
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() # Zorgt ervoor dat HTTPError wordt opgeworpen voor slechte responses
data = response.json()
print(f"Data from {url}: {data}")
publish_to_mqtt(mqtt_topic, data)
# load_data(data) # Zorg ervoor dat deze functie elders gedefinieerd is
except requests.exceptions.RequestException as e:
print(f"Error fetching data from {url}: {e}")
if __name__ == "__main__":
client.loop_start() # Start de niet-blokkerende loop
while True:
fetch_and_publish_data()
print(f"\033[91mWachten, wachten en nog eens wachten... {publish_interval} secondes!\033[0m\n")
time.sleep(publish_interval)
client.loop_stop()

4193
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,15 +3,20 @@
"description": "", "description": "",
"main": "app.js", "main": "app.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "start": "npm-run-all --parallel start-flask start-electron",
"start": "electron app.js" "start-electron": "wait-on http://localhost:5000 && electron app.js",
"start-flask": "python app.py"
}, },
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"electron": "^23.3.13" "concurrently": "^8.2.2",
"electron": "^23.3.13",
"npm-run-all": "^4.1.5",
"wait-on": "^7.2.0"
}, },
"dependencies": { "dependencies": {
"axios": "^1.6.7",
"body-parser": "^1.20.2", "body-parser": "^1.20.2",
"elctron": "^0.0.1-security", "elctron": "^0.0.1-security",
"express": "^4.18.3", "express": "^4.18.3",

32
plants.json Normal file
View File

@@ -0,0 +1,32 @@
[
{
"id": 47,
"plant_naam": "Tomaten",
"plantensoort": "Groente",
"plant_geteelt": 1
},
{
"id": 49,
"plant_naam": "Komkommer",
"plantensoort": "Groente",
"plant_geteelt": 1
},
{
"id": 50,
"plant_naam": "Appel",
"plantensoort": "Fruit",
"plant_geteelt": 1
},
{
"id": 51,
"plant_naam": "Sla",
"plantensoort": "Groente",
"plant_geteelt": 1
},
{
"id": 52,
"plant_naam": "Wietplant",
"plantensoort": "Onkruid",
"plant_geteelt": 0
}
]

View File

@@ -1,71 +0,0 @@
import requests
import time
from db_connect import database_connect
def fetch_and_display_all(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}:")
print(data)
load_data(data)
except requests.exceptions.RequestException as e:
print(f"Error fetching data from {url}: {e}")
print("Waiting for the next retrieval action...")
# time.sleep(300) # Time here is in seconds.
time.sleep(1) # Time here is in seconds.
def load_data(data):
mydb = database_connect()
if mydb.is_connected():
mycursor = mydb.cursor()
# Here you need to adjust the correct column names and data formats based on the API response
insert_query = """
INSERT INTO goodgarden.devices (serial_number, name, label, last_seen, last_battery_voltage)
VALUES (%s, %s, %s, %s, %s )
"""
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', '')
print(f"Inserting data: serial_number={serial_number}, name={name}, label={label}, last_seen={last_seen}, last_battery_voltage={last_battery_voltage}")
# Execute the query
mycursor.execute(insert_query, (serial_number, name, label, last_seen, last_battery_voltage))
# Commit the changes
mydb.commit()
# Close cursor and connection
mycursor.close()
mydb.close()
print("Data inserted into the database.")
if __name__ == "__main__":
url = "https://garden.inajar.nl/api/devices/?format=json"
access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c" # Replace this with your actual access token
# access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c"
# You can change the repeat_count to control how many times you want to repeat the process
repeat_count = 10
fetch_and_display_all(url, access_token, repeat_count)

View File

@@ -1,73 +0,0 @@
import requests
import time
from db_connect import database_connect
# Establish a database connection
connection = database_connect()
def fetch_and_display_all(urls, access_token):
for url in urls:
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}:")
print(data)
load_data(data)
except requests.exceptions.RequestException as e:
print(f"Error fetching data from {url}: {e}")
# Wait for a certain time (e.g., 60 seconds) before making the next call
print("Waiting for the next retrieval action...")
time.sleep(10) # Time here is in seconds.
def load_data(data):
mydb = database_connect()
if mydb.is_connected():
mycursor = mydb.cursor()
# Here you need to adjust the correct column names and data formats based on the API response
insert_query = """
INSERT INTO goodgarden.fetch (timestamp, gateway_receive_time, device, value)
VALUES (%s, %s, %s, %s)
"""
for record in data['results']: # Adjust this based on the actual structure of the 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 the data being inserted
# Execute the query
mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
# Commit the changes
mydb.commit()
# Close cursor and connection
mycursor.close()
mydb.close()
print("Data inserted into the database.")
if __name__ == "__main__":
urls = [
"https://garden.inajar.nl/api/battery_voltage_events/?format=json",
"https://garden.inajar.nl/api/devices/?format=json",
"https://garden.inajar.nl/api/par_events/?format=json",
"https://garden.inajar.nl/api/relative_humidity_events/?format=json",
"https://garden.inajar.nl/api/soil_electric_conductivity_events/?format=json",
"https://garden.inajar.nl/api/soil_relative_permittivity_events/?format=json",
"https://garden.inajar.nl/api/soil_temperature_events/?format=json"
]
access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c" # Vervang dit met jouw echte toegangstoken
fetch_and_display_all(urls, access_token)

View File

@@ -1,57 +0,0 @@
import requests
import time
from db_connect import database_connect
def fetch_battery_voltage_events():
url = "https://garden.inajar.nl/api/battery_voltage_events/?format=json"
headers = {
"Authorization": "Token 33bb3b42452306c58ecedc3c86cfae28ba22329c"
}
while True:
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
data = response.json()
load_data(data)
print("Wachten voor de volgende ophaalactie...")
time.sleep(300) # De tijd hier is in seconden.
except requests.exceptions.RequestException as e:
print(f"Error fetching data: {e}")
# Wacht ook hier bij een fout, om niet in een snelle foutloop te komen
time.sleep(300)
def load_data(data):
mydb = database_connect()
if mydb.is_connected():
mycursor = mydb.cursor()
# Hier moet je de juiste kolomnamen en dataformaten 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)
"""
for record in data['results']:
timestamp = record['timestamp']
gateway_receive_time = record['gateway_receive_time']
device = record['device']
value = record['value']
# print(f"Inserting data: timestamp={timestamp}, gateway_receive_time={gateway_receive_time}, device={device}, value={value}")
mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
# Commit de wijzigingen
mydb.commit()
# Sluit cursor en verbinding
mycursor.close()
mydb.close()
print("Data ingevoegd in de database.")
if __name__ == "__main__":
fetch_battery_voltage_events()

View File

@@ -1,64 +0,0 @@
import requests
import time
from db_connect import database_connect
def fetch_and_display_all(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}:")
print(data)
load_data(data)
except requests.exceptions.RequestException as e:
print(f"Error fetching data from {url}: {e}")
print("Waiting for the next retrieval action...")
time.sleep(1) # Time here is in seconds.
def load_data(data):
mydb = database_connect()
if mydb.is_connected():
mycursor = mydb.cursor()
# Here you need to adjust the correct column names and data formats based on the API response
insert_query = """
INSERT INTO goodgarden.par_events (timestamp, gateway_receive_time, device, value)
VALUES (%s, %s, %s, %s)
"""
for record in data['results']:
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}")
# Execute the query
mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
# Commit the changes
mydb.commit()
# Close cursor and connection
mycursor.close()
mydb.close()
print("Data inserted into the database.")
if __name__ == "__main__":
url = "https://garden.inajar.nl/api/par_events/?format=json"
access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c"
# You can change the repeat_count to control how many times you want to repeat the process
repeat_count = 10
fetch_and_display_all(url, access_token, repeat_count)

View File

@@ -1,64 +0,0 @@
import requests
import time
from db_connect import database_connect
def fetch_and_display_all(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}:")
print(data)
load_data(data)
except requests.exceptions.RequestException as e:
print(f"Error fetching data from {url}: {e}")
print("Waiting for the next retrieval action...")
time.sleep(1) # Time here is in seconds.
def load_data(data):
mydb = database_connect()
if mydb.is_connected():
mycursor = mydb.cursor()
# Here you need to adjust the correct column names and data formats based on the API response
insert_query = """
INSERT INTO goodgarden.relative_humidity_events (timestamp, gateway_receive_time, device, value)
VALUES (%s, %s, %s, %s)
"""
for record in data['results']:
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}")
# Execute the query
mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
# Commit the changes
mydb.commit()
# Close cursor and connection
mycursor.close()
mydb.close()
print("Data inserted into the database.")
if __name__ == "__main__":
url = "https://garden.inajar.nl/api/relative_humidity_events/?format=json"
access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c"
# You can change the repeat_count to control how many times you want to repeat the process
repeat_count = 10
fetch_and_display_all(url, access_token, repeat_count)

View File

@@ -1,63 +0,0 @@
import requests
import time
from db_connect import database_connect
def fetch_and_display_all(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}:")
print(data)
load_data(data)
except requests.exceptions.RequestException as e:
print(f"Error fetching data from {url}: {e}")
print("Waiting for the next retrieval action...")
time.sleep(1) # Time here is in seconds.
def load_data(data):
mydb = database_connect()
if mydb.is_connected():
mycursor = mydb.cursor()
# Here you need to adjust the correct column names and data formats based on the API response
insert_query = """
INSERT INTO goodgarden.soil_electric_conductivity_events (timestamp, gateway_receive_time, device, value)
VALUES (%s, %s, %s, %s)
"""
for record in data['results']:
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}")
# Execute the query
mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
# Commit the changes
mydb.commit()
# Close cursor and connection
mycursor.close()
mydb.close()
print("Data inserted into the database.")
if __name__ == "__main__":
url = "https://garden.inajar.nl/api/soil_electric_conductivity_events/?format=json"
access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c" # Replace this with your actual access token
# You can change the repeat_count to control how many times you want to repeat the process
repeat_count = 10
fetch_and_display_all(url, access_token, repeat_count)

View File

@@ -1,66 +0,0 @@
import requests
import time
from db_connect import database_connect
def fetch_and_display_all(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}:")
print(data)
load_data(data)
except requests.exceptions.RequestException as e:
print(f"Error fetching data from {url}: {e}")
print("Waiting for the next retrieval action...")
time.sleep(1) # Time here is in seconds.
def load_data(data):
mydb = database_connect()
if mydb.is_connected():
mycursor = mydb.cursor()
# Here you need to adjust the correct column names and data formats based on the API response
insert_query = """
INSERT INTO goodgarden.soil_temperature_events (timestamp, gateway_receive_time, device, value)
VALUES (%s, %s, %s, %s)
"""
for record in data['results']:
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}")
# Execute the query
mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
# Commit the changes
mydb.commit()
# Close cursor and connection
mycursor.close()
mydb.close()
print("Data inserted into the database.")
if __name__ == "__main__":
url = "https://garden.inajar.nl/api/soil_relative_permittivity_events/?format=json"
access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c"
# You can change the repeat_count to control how many times you want to repeat the process
repeat_count = 10
# fetch_and_display_all(urls, access_token)
fetch_and_display_all(url, access_token, repeat_count)

View File

@@ -1,65 +0,0 @@
import requests
import time
from db_connect import database_connect
def fetch_and_display_all(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}:")
print(data)
load_data(data)
except requests.exceptions.RequestException as e:
print(f"Error fetching data from {url}: {e}")
print("Waiting for the next retrieval action...")
time.sleep(1) # Time here is in seconds.
def load_data(data):
mydb = database_connect()
if mydb.is_connected():
mycursor = mydb.cursor()
# Here you need to adjust the correct column names and data formats based on the API response
insert_query = """
INSERT INTO goodgarden.soil_temperature_events (timestamp, gateway_receive_time, device, value)
VALUES (%s, %s, %s, %s)
"""
for record in data['results']:
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}")
# Execute the query
mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
# Commit the changes
mydb.commit()
# Close cursor and connection
mycursor.close()
mydb.close()
print("Data inserted into the database.")
if __name__ == "__main__":
url = "https://garden.inajar.nl/api/soil_temperature_events/?format=json"
access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c" # Replace this with your actual access token
# You can change the repeat_count to control how many times you want to repeat the process
repeat_count = 10
fetch_and_display_all(url, access_token, repeat_count)

View File

@@ -1,32 +1,26 @@
@import url("https://fonts.googleapis.com/css2?family=Akaya+Kanadaka&display=swap"); @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"); @import url("https://fonts.googleapis.com/css2?family=Afacad:ital,wght@0,400..700;1,400..700&display=swap");
h1, h2, h3, h4, h5 { h1,
h2,
h3,
h4,
h5 {
font-family: "Akaya Kanadaka", system-ui; font-family: "Akaya Kanadaka", system-ui;
margin: 0; margin: 0;
} }
p, td { p,
td {
font-family: "Afacad", sans-serif; font-family: "Afacad", sans-serif;
color: black;
} }
.containers-articles, body .mainContainer .mainBorder .content .kant-rechts #sensor-2, body .mainContainer .mainBorder .content .kant-links #sensor-1, body .mainContainer .mainBorder .content .kant-links #planten td article { a {
height: 7rem; text-decoration: none;
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);
background-color: white;
} }
body { body {
background-image: url("../images/achtergrond.png"); background: linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.5)), url("../images/achtergrond.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: cover;
background-position: center; background-position: center;
@@ -40,7 +34,7 @@ body {
body .mainContainer { body .mainContainer {
width: 85vw; width: 85vw;
height: 38rem; height: 38rem;
background-color: rgba(255, 255, 255, 0.95); background-color: rgba(255, 255, 255, 0.85);
border-radius: 40px; border-radius: 40px;
padding: 2rem; padding: 2rem;
} }
@@ -81,6 +75,7 @@ body .mainContainer .mainBorder #sectie-1 .parent-algemeen-overzicht {
border-radius: 40px; border-radius: 40px;
padding: 1rem; padding: 1rem;
margin-top: 1rem; margin-top: 1rem;
background-color: white;
} }
body .mainContainer .mainBorder #sectie-1 .parent-algemeen-overzicht .algemeen-overzicht { body .mainContainer .mainBorder #sectie-1 .parent-algemeen-overzicht .algemeen-overzicht {
border: solid 2px rgb(171, 211, 174); border: solid 2px rgb(171, 211, 174);
@@ -101,6 +96,7 @@ body .mainContainer .mainBorder #sectie-1 .grafiek {
border-radius: 40px; border-radius: 40px;
padding: 1rem; padding: 1rem;
position: relative; position: relative;
background-color: white;
} }
body .mainContainer .mainBorder #sectie-1 .grafiek .grafiek-innerbox { body .mainContainer .mainBorder #sectie-1 .grafiek .grafiek-innerbox {
border: solid 2px rgb(171, 211, 174); border: solid 2px rgb(171, 211, 174);
@@ -133,6 +129,20 @@ body .mainContainer .mainBorder .content .kant-links #planten {
width: 100%; width: 100%;
border-collapse: collapse; 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 { body .mainContainer .mainBorder .content .kant-links #planten td article #toevoegen {
height: 5rem; height: 5rem;
width: 5rem; width: 5rem;
@@ -143,15 +153,8 @@ body .mainContainer .mainBorder .content .kant-links #planten td article h2 {
body .mainContainer .mainBorder .content .kant-links #planten td article:hover { body .mainContainer .mainBorder .content .kant-links #planten td article:hover {
background-color: lightgray; background-color: lightgray;
} }
body .mainContainer .mainBorder .content .kant-links #sensor-1 {
border: none;
border-radius: 40px 0px 0px 40px;
width: 30vw;
margin-top: 10vh;
}
body .mainContainer .mainBorder .content .kant-rechts { body .mainContainer .mainBorder .content .kant-rechts {
grid-column: 3; grid-column: 3;
margin-right: 2rem;
} }
body .mainContainer .mainBorder .content .kant-rechts #metingen { body .mainContainer .mainBorder .content .kant-rechts #metingen {
border: solid 3px rgb(171, 211, 174); border: solid 3px rgb(171, 211, 174);
@@ -169,16 +172,12 @@ body .mainContainer .mainBorder .content .kant-rechts #metingen #main-waardes ta
justify-content: space-between; justify-content: space-between;
width: 100%; width: 100%;
} }
body .mainContainer .mainBorder .content .kant-rechts #sensor-2 {
border-radius: 0px 40px 40px 0px;
width: 30vw;
margin-top: 10vh;
}
body .mainContainer .mainBorder .grid-column-2 { body .mainContainer .mainBorder .grid-column-2 {
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5); box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
border-radius: 40px; border-radius: 40px;
padding: 1rem; padding: 1rem;
margin: 3.25rem 1rem 1.25rem 1rem; margin: 3.25rem 1rem 1.25rem 1rem;
background-color: white;
} }
body .mainContainer .mainBorder .grid-column-2 .grid-2-child { body .mainContainer .mainBorder .grid-column-2 .grid-2-child {
border: solid 2px rgb(171, 211, 174); border: solid 2px rgb(171, 211, 174);
@@ -189,9 +188,17 @@ body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table {
padding: 1.5rem 2rem; padding: 1.5rem 2rem;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: stretch;
gap: 2.5rem;
justify-content: space-around; justify-content: space-around;
height: 90%; 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 { body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-2 {
position: relative; position: relative;
} }
@@ -211,7 +218,6 @@ body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-
top: -20px; top: -20px;
} }
/* Divider */
.divider { .divider {
display: flex; display: flex;
justify-content: center; justify-content: center;
@@ -221,7 +227,6 @@ body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-
margin: 0 auto; margin: 0 auto;
} }
/* The Modal (background) */
.modal { .modal {
display: none; display: none;
position: fixed; position: fixed;
@@ -234,17 +239,168 @@ body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
width: 30vw; width: 30vw;
height: auto; height: auto;
border: solid 2px black; border: solid 2px #abd3ae;
border-radius: 10px; border-radius: 10px;
} }
.modal .close { .modal .close {
color: #aaa; color: #aaa;
float: right; float: right;
font-size: 1.75rem; font-size: 1.75rem;
font-weight: bold; font-weight: bold;
} }
.modal .close:hover, .modal .close:active {
.modal .close:hover,
.modal .close:active {
color: black; color: black;
text-decoration: none; text-decoration: none;
cursor: pointer; 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-color: white;
}
#myModal button {
background-color: white;
color: black;
}
.toevoeging {
background: linear-gradient(45deg, #abd3ae, #2ecc71);
}
.annulatie-knop {
background: linear-gradient(45deg, #ffcc00, #ff6600);
}
#myModal button:hover {
background: linear-gradient(45deg, #abd3ae, #fff);
color: #000;
}
.modal .close {
color: #aaa;
float: right;
font-size: 1.75rem;
font-weight: bold;
}
.modal .close:hover,
.modal .close:active {
color: black;
text-decoration: none;
cursor: pointer;
}
.switch-container {
display: flex;
align-items: end;
}
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 30px;
}
.switch input {
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: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
border-radius: 50%;
transition: 0.4s;
}
input:checked + .slider {
background-color: #2ecc71;
}
input:checked + .slider:before {
transform: translateX(26px);
}
.rechterkant {
display: flex;
justify-content: end;
}
.plant-container,
#modalButton {
background-color: white;
}/*# sourceMappingURL=style.css.map */ }/*# sourceMappingURL=style.css.map */

View File

@@ -1 +1 @@
{"version":3,"sources":["style.scss","style.css"],"names":[],"mappings":"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","file":"style.css"} {"version":3,"sources":["style.scss","style.css"],"names":[],"mappings":"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","file":"style.css"}

View File

@@ -1,415 +1,535 @@
$primary-color: rgb(171, 211, 174); $primary-color: rgb(171, 211, 174);
$secondary-color: rgb(143, 188, 143); $secondary-color: rgb(143, 188, 143);
@import url('https://fonts.googleapis.com/css2?family=Akaya+Kanadaka&display=swap'); @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'); @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-titels: "Akaya Kanadaka", system-ui;
$font-text: "Afacad", sans-serif; $font-text: "Afacad", sans-serif;
@mixin flexbox @mixin flexbox-center
{ {
display: flex; display: flex;
justify-content: space-around; justify-content: center;
} }
@mixin groene-border @mixin groene-border
{ {
border: solid 2px $primary-color; border: solid 2px $primary-color;
} }
@mixin box-shadow @mixin box-shadow
{ {
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5); box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
} }
@mixin border-radius @mixin border-radius
{ {
border-radius: 40px; border-radius: 40px;
} }
@mixin inner-border-radius @mixin inner-border-radius
{ {
border-radius: 35px; border-radius: 35px;
} }
h1, h2, h3, h4, h5 h1,
h2,
h3,
h4,
h5
{ {
font-family: $font-titels; font-family: $font-titels;
margin: 0; margin: 0;
} }
p, td p,
td
{ {
font-family: $font-text; font-family: $font-text;
color: black;
} }
.containers-articles a
{ {
height: 7rem; text-decoration: none;
width: 10rem;
padding: .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);
background-color: white;
} }
body body
{ {
background-image: url("../images/achtergrond.png"); background: linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.5)), url("../images/achtergrond.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: cover; background-size: cover;
background-position: center; background-position: center;
font-family: $font-text; font-family: $font-text;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
height: 100vh; height: 100vh;
margin: 0; margin: 0;
.mainContainer .mainContainer
{
width: 85vw;
height: 38rem;
background-color: rgb(255, 255, 255, 85%);
border-radius: 40px;
padding: 2rem;
.goodgarden-logo
{ {
width: 85vw; position: absolute;
height: 38rem; width: 10vw;
background-color: rgb(255, 255, 255, 95%); left: 50%;
border-radius: 40px; top: 4.1rem;
padding: 2rem; transform: translateX(-50%);
.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;
}
#sectie-1
{
display: flex;
flex-direction: column;
gap: 1rem;
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;
.algemeen-overzicht
{
@include groene-border;
@include inner-border-radius;
font-size: 1.25rem;
padding: .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;
.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 het 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
{
@extend .containers-articles;
#toevoegen
{
height: 5rem;
width: 5rem;
}
h2
{
color: gray;
}
&:hover
{
background-color: lightgray;
}
}
}
}
#sensor
{
&-1
{
@extend .containers-articles;
border: none;
border-radius: 40px 0px 0px 40px;
width: 30vw;
margin-top: 10vh;
}
}
}
&-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: .5rem;
padding-bottom: 0;
width: 100%;
table
{
display: flex;
justify-content: space-between;
width: 100%;
}
}
}
#sensor
{
&-2
{
@extend .containers-articles;
border-radius: 0px 40px 40px 0px;
width: 30vw;
margin-top: 10vh;
}
}
}
}
}
.grid-column-2
{
@include box-shadow;
@include border-radius;
padding: 1rem;
margin: 3.25rem 1rem 1.25rem 1rem;
.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 */
.divider {
display: flex;
justify-content: center;
border: solid 1px $primary-color;
border-radius: 5px;
width: 80%;
margin: 0 auto;
}
/* The Modal (background) */
.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 black;
border-radius: 10px;
.close
{
color: #aaa;
float: right;
font-size: 1.75rem;
font-weight: bold;
&:hover,
&:active
{
color: black;
text-decoration: none;
cursor: pointer;
}
} }
}
.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;
}
#sectie-1
{
display: flex;
flex-direction: column;
gap: 1rem;
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;
}
}
}
}
}
&-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 .close {
color: #aaa;
float: right;
font-size: 1.75rem;
font-weight: bold;
}
.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-color: white;
}
#myModal button {
background-color: white;
color: black;
}
.toevoeging {
background: linear-gradient(45deg, #abd3ae, #2ecc71);
}
.annulatie-knop {
background: linear-gradient(45deg, #ffcc00, #ff6600);
}
#myModal button:hover {
background: linear-gradient(45deg, #abd3ae, #fff);
color: #000;
}
.modal .close {
color: #aaa;
float: right;
font-size: 1.75rem;
font-weight: bold;
}
.modal .close:hover,
.modal .close:active {
color: black;
text-decoration: none;
cursor: pointer;
}
.switch-container {
display: flex;
align-items: end;
}
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 30px;
}
.switch input {
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: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
border-radius: 50%;
transition: 0.4s;
}
input:checked + .slider {
background-color: #2ecc71;
}
input:checked + .slider:before {
transform: translateX(26px);
}
.rechterkant {
display: flex;
justify-content: end;
}
.plant-container,
#modalButton
{
background-color: white;
}

View File

@@ -95,4 +95,4 @@
</section> </section>
</body> </body>
</html> </html>

View File

@@ -1,115 +0,0 @@
const { ipcRenderer } = require("electron");
document.addEventListener('DOMContentLoaded', () =>
{
ipcRenderer.send('request-update-temp', ['some', 'arguments']);
ipcRenderer.on('update-temp-result', (event, newTemperature) => {
if (newTemperature === 'error') {
console.error('Er is een fout opgetreden bij het ophalen van de nieuwe temperatuur');
} else {
document.getElementById('bodem-temperatuur').textContent = newTemperature;
}
});
});
function openModal()
{
const modal = document.getElementById("myModal");
const button = document.getElementById("modalButton");
const close = document.getElementsByClassName("close")[0];
// Toon de modal wanneer op de knop wordt geklikt
button.onclick = function()
{
modal.style.display = "block";
}
// Sluit de modal wanneer op het 'sluiten' icoon wordt geklikt
close.onclick = function()
{
modal.style.display = "none";
}
// Sluit de modal wanneer buiten de modal wordt geklikt
window.onclick = function(event)
{
if (event.target == modal)
{
modal.style.display = "none";
}
}
}
/**
* --- Functie om de grafiek te tekenen. Enigste belangrijke is de eerste 2 "const" arrays "data" & "xLabels".
*/
function drawLineChart()
{
/*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!!*/
const data = [20, 50, 60, 45, 50, 100, 70, 60, 65, 0, 85, 0];
const xLabels = ["", "", "", "", "", 6, "", "", "", "", "", 12];
const yLabels = ["", 20, "", 40, "", 60, "", 80, "", 100]; /*NIET VERANDEREN!!!*/
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
const padding = 35; // Increased padding for Y labels
const graphWidth = canvas.width - padding * 2;
const graphHeight = canvas.height - padding * 2;
ctx.beginPath();
ctx.moveTo(padding, padding);
ctx.lineTo(padding, canvas.height - padding);
ctx.lineTo(canvas.width - padding, canvas.height - padding);
ctx.stroke();
// Set the color of the line
ctx.strokeStyle = "rgb(143, 188, 143)";
const xIncrement = graphWidth / (xLabels.length - 1);
const yIncrement = graphHeight / (yLabels.length - 1);
// Plot the data
ctx.beginPath();
ctx.moveTo(padding, canvas.height - padding - (data[0] / 100) * graphHeight);
for (let i = 1; i < data.length; i++)
{
const xPos = padding + i * xIncrement;
const yPos = canvas.height - padding - (data[i] / 100) * graphHeight;
ctx.lineTo(xPos, yPos);
}
ctx.stroke();
// Draw Y labels
ctx.fillStyle = "black";
ctx.textAlign = "right"; // Align text to the right
ctx.textBaseline = "middle"; // Center vertically
for (let i = 0; i < yLabels.length; i++)
{
if (yLabels[i] !== "")
{
const yPos = canvas.height - padding - i * yIncrement;
ctx.fillText(yLabels[i], padding - 10, yPos);
}
}
// Draw X labels
ctx.textAlign = "center"; // Center horizontally for X labels
for (let i = 0; i < xLabels.length; i++)
{
if (xLabels[i] !== "")
{
const xPos = padding + i * xIncrement;
ctx.fillText(xLabels[i], xPos, canvas.height - padding + 20);
}
}
}
drawLineChart();

View File

@@ -1,143 +0,0 @@
class Plant {
constructor(dataObject) {
this.id = dataObject.id;
this.plantNaam = dataObject.plantNaam;
this.plantensoort = dataObject.plantensoort;
this.plantGeteelt = dataObject.plantGeteelt;
}
}
class PlantGrid {
constructor() {
this.grid = [];
this.cols = 2; // Number of columns
this.rows = 4; // Number of rows (including the row for the "Add" button)
// Initialize the grid with null values
for (let i = 0; i < this.rows; i++) {
this.grid[i] = new Array(this.cols).fill(null);
}
// Sample data
const dataHardObject = [
{
"id": 1,
"plantNaam": "Tomt",
"plantensoort": "Groente",
"plantGeteelt": 1
},
{
"id": 2,
"plantNaam": "Komkommer",
"plantensoort": "Groente",
"plantGeteelt": 1
},
{
"id": 3,
"plantNaam": "Appel",
"plantensoort": "Groente",
"plantGeteelt": 0
},
{
"id": 4,
"plantNaam": "KwamKwammer",
"plantensoort": "Groente",
"plantGeteelt": 1
},
{
"id": 5,
"plantNaam": ":p",
"plantensoort": "Groente",
"plantGeteelt": 1
},
{
"id": 6,
"plantNaam": ":3",
"plantensoort": "Groente",
"plantGeteelt": 1
},
{
"id": 7,
"plantNaam": "Groene",
"plantensoort": "Groente",
"plantGeteelt": 1
},
{
"id": 8,
"plantNaam": "test",
"plantensoort": "Groente",
"plantGeteelt": 0
},
{
"id": 9,
"plantNaam": "yippie",
"plantensoort": "Groente",
"plantGeteelt": 1
}
];
// Only save objects that have plantGeteelt as 1
const filteredData = dataHardObject.filter(plantObject => plantObject.plantGeteelt === 1);
// Populate the grid with plant objects
filteredData.slice(0, 8).forEach((plantObject, index) => {
const plant = new Plant(plantObject);
const col = index % this.cols;
const row = Math.floor(index / this.cols);
this.grid[row][col] = plant;
});
// Display the grid in the HTML table with id "planten"
this.displayGrid();
}
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 article = document.createElement("article");
const img = article.appendChild(document.createElement("img"));
img.src = "images/Icon awesome-apple-alt.png";
const h2 = article.appendChild(document.createElement("h2"));
h2.classList.add("plant-naam");
h2.textContent = plant.plantNaam;
td.appendChild(article);
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 = "images/Toevoegen.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();
});

View File

@@ -1,109 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="../src/css/style.css" />
<script src="../src/js/main.js" defer></script>
<title>Informatie Kas</title>
</head>
<body>
<section class="mainContainer">
<article>
<img src="../src/images/logo.png" class="goodgarden-logo">
</article>
<section class="mainBorder informatie-kas-main-container">
<article>
<h1 class="pagina-titel">Informatie Kas</h1>
<section id="sectie-1">
<article class="parent-algemeen-overzicht">
<article class="algemeen-overzicht">
<table class="table-informatie-kas">
<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>
<tr class="tr-informatie-kas">
<td>Aandachtspunten</td>
<td>1</td>
</tr>
</table>
</article>
</article>
<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>
<article class="grid-column-2">
<article class="grid-2-child">
<section class="parent-table">
<table class="kas-table-1">
<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">
<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">
<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>

View File

@@ -1,14 +1,10 @@
{ "battery_voltage_events": [
// Deze spanningswaarden zijn relatief hoog, wat suggereert dat de batterijen van de sensoren goed opgeladen zijn. De meeste sensorapparaten gebruiken batterijen die een nominale spanning van ongeveer 3,7 volt hebben (typisch voor lithium-ion batterijen) en kunnen worden beschouwd als "volledig opgeladen" wanneer ze een spanning dicht bij of iets boven 4,1 volt bereiken
"battery_voltage_events": [
{ {
"timestamp": 1707825721, "timestamp": 1707825721,
"gateway_receive_time": "2024-02-13T12:02:01Z", "gateway_receive_time": "2024-02-13T12:02:01Z",
"device": 256, "device": 256,
"value": 4.098901271820068 "value": 4.098901271820068
// Volledig opgeladen: Rond 4.2 volt.
// Nominale spanning: Ongeveer 3.7 volt.
// Kritiek laag: Minder dan 3.0 volt.
}, },
{ {
"timestamp": 1707837460, "timestamp": 1707837460,
@@ -44,7 +40,6 @@
// Fotosyntese??? (zonlicht)
"par_events": [ "par_events": [
{ {
"timestamp": 1707844638, "timestamp": 1707844638,
@@ -63,7 +58,6 @@
// Luchtvochtigheid
"relative_humidity_events": [ "relative_humidity_events": [
{ {
"timestamp": 1707844638, "timestamp": 1707844638,
@@ -83,7 +77,6 @@
// De "soil_electric_conductivity_events" gegevens wijzen op metingen van de elektrische geleidbaarheid (EC) van de bodem, een indicator van de hoeveelheid oplosbare zouten of voedingsstoffen in de bodem. EC wordt gemeten in Siemens per meter (S/m) of, voor bodemmetingen, vaak in milliSiemens per centimeter (mS/cm). Een hogere EC-waarde duidt op een hogere concentratie van opgeloste zouten, wat belangrijk is voor het bepalen van de voedingsstatus van de bodem en het beheren van de bemesting voor optimale plantengroei.
"soil_electric_conductivity_events": [ "soil_electric_conductivity_events": [
{ {
"timestamp": 1707851215, "timestamp": 1707851215,
@@ -97,20 +90,17 @@
// In de context van bodemmetingen, geeft deze waarde inzicht in het vochtgehalte van de bodem, omdat water een relatief hoge diëlektrische constante heeft in vergelijking met droge bodem of lucht.
"soil_relative_permittivity_events": [ "soil_relative_permittivity_events": [
{ {
"timestamp": 1707851215, "timestamp": 1707851215,
"gateway_receive_time": "2024-02-13T19:06:55Z", "gateway_receive_time": "2024-02-13T19:06:55Z",
"device": 322, "device": 322,
"value": 1.52 "value": 1.52
// Een waarde van 1.52 is relatief laag en suggereert dat de bodem droog kan zijn op het moment van meting. Ter referentie, de diëlektrische constante van lucht is ongeveer 1, terwijl water een diëlektrische constante heeft van ongeveer 80 bij kamertemperatuur.
} }
], ],
//De "soil_temperature_events" gegevens bevatten informatie over de temperatuur van de bodem op een specifiek tijdstip. De waarde geeft de temperatuur van de bodem aan in graden Celsius (°C).
"soil_temperature_events": [ "soil_temperature_events": [
{ {
"timestamp": 1707851215, "timestamp": 1707851215,

View File

@@ -0,0 +1,223 @@
import mysql.connector
import requests
from datetime import datetime, timezone, timedelta
import time
# Function to make a connection to the database
def database_connect():
return mysql.connector.connect(
host="localhost",
user="root",
password="",
database="goodgarden"
)
# 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) < 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")
# 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" # Vervang dit door je werkelijke toegangstoken
# 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
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.")

View File

@@ -1,4 +1,4 @@
import mysql.connector #** TYPE IN TERMINAL: "pip install mysql-connector-python" import mysql.connector
from mysql.connector import Error from mysql.connector import Error
def database_connect(): def database_connect():

36
src/py/script/devices.py Normal file
View File

@@ -0,0 +1,36 @@
import json
from paho.mqtt import subscribe
def on_message(client, userdata, message):
payload_str = message.payload.decode("utf-8")
data = json.loads(payload_str)
device_256 = None
last_seen = None
last_battery_voltage = None
device_322 = None
last_seen = None
last_battery_voltage = None
for key in data["results"]:
if int(key["id"]) == 256:
device_256 = int(key["id"])
last_seen = int(key["last_seen"])
last_battery_voltage = float(key["last_battery_voltage"])
# print(f"{device_256}")
print(f"Het device {device_256} is voor het laatst geien op: {last_seen} met de voltage als {last_battery_voltage}")
elif int(key["id"]) == 322:
device_322 = int(key["id"])
last_seen = int(key["last_seen"])
last_battery_voltage = float(key["last_battery_voltage"])
# print(f"{device_256}")
print(f"Het device {device_322} is voor het laatst gezien op: {last_seen} met de voltage als {last_battery_voltage}")
print(f"\033[92mMessage received on topic\033[0m {message.topic}: {data}")
if __name__ == "__main__":
topic = "goodgarden/devices"
subscribe.callback(on_message, topic)

View File

@@ -0,0 +1,346 @@
-- phpMyAdmin SQL Dump
-- version 5.2.1
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1
-- Gegenereerd op: 14 feb 2024 om 14:36
-- Serverversie: 10.4.28-MariaDB
-- PHP-versie: 8.2.4
DROP DATABASE IF EXISTS goodgarden;
CREATE DATABASE goodgarden;
USE goodgarden;
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`
--
-- --------------------------------------------------------
--
-- 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
(1, 1707825721, '2024-02-13T12:02:01Z', 256, 4.09890),
(2, 1707837460, '2024-02-13T15:17:40Z', 322, 4.10501),
(3, 1707825721, '2024-02-13T12:02:01Z', 256, 4.09890),
(4, 1707837460, '2024-02-13T15:17:40Z', 322, 4.10501),
(5, 1707825721, '2024-02-13T12:02:01Z', 256, 4.09890),
(6, 1707837460, '2024-02-13T15:17:40Z', 322, 4.10501),
(7, 1707825721, '2024-02-13T12:02:01Z', 256, 4.09890),
(8, 1707837460, '2024-02-13T15:17:40Z', 322, 4.10501),
(9, 1707825721, '2024-02-13T12:02:01Z', 256, 4.09890),
(10, 1707837460, '2024-02-13T15:17:40Z', 322, 4.10501);
-- --------------------------------------------------------
--
-- 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
) 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`) VALUES
(1, '0033889B1BAB1169', 'firefly2_0051', 'The Field', 1707765066, 4.09768),
(2, '006FE1FC316ED7D8', 'firefly2_0111', 'The Field', 1707764966, 4.10745);
-- --------------------------------------------------------
--
-- 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;
--
-- Gegevens worden geëxporteerd voor tabel `fetch`
--
INSERT INTO `fetch` (`id`, `timestamp`, `gateway_receive_time`, `device`, `value`) VALUES
(70, 1707851215, '2024-02-13T19:06:55Z', 322, 0.00000),
(71, 1707851215, '2024-02-13T19:06:55Z', 322, 1.52000),
(72, 1707851215, '2024-02-13T19:06:55Z', 322, 12.06000),
(73, 1707825721, '2024-02-13T12:02:01Z', 256, 4.09890),
(74, 1707837460, '2024-02-13T15:17:40Z', 322, 4.10501),
(75, 0, '', 0, 0.00000),
(76, 0, '', 0, 0.00000),
(77, 1707844638, '2024-02-13T17:17:18Z', 322, 0.00000),
(78, 1707851099, '2024-02-13T19:04:59Z', 256, 0.00000),
(79, 1707844638, '2024-02-13T17:17:18Z', 322, 71.08984),
(80, 1707851099, '2024-02-13T19:04:59Z', 256, 66.72949),
(81, 1707851215, '2024-02-13T19:06:55Z', 322, 0.00000),
(82, 1707851215, '2024-02-13T19:06:55Z', 322, 1.52000),
(83, 1707851215, '2024-02-13T19:06:55Z', 322, 12.06000),
(84, 0, '', 0, 0.00000),
(85, 0, '', 0, 0.00000),
(86, 1707844638, '2024-02-13T17:17:18Z', 322, 0.00000),
(87, 1707851099, '2024-02-13T19:04:59Z', 256, 0.00000),
(88, 1707844638, '2024-02-13T17:17:18Z', 322, 71.08984),
(89, 1707851099, '2024-02-13T19:04:59Z', 256, 66.72949),
(90, 1707825721, '2024-02-13T12:02:01Z', 256, 4.09890),
(91, 1707837460, '2024-02-13T15:17:40Z', 322, 4.10501),
(92, 0, '', 0, 0.00000),
(93, 0, '', 0, 0.00000),
(94, 1707844638, '2024-02-13T17:17:18Z', 322, 0.00000),
(95, 1707851099, '2024-02-13T19:04:59Z', 256, 0.00000),
(96, 1707844638, '2024-02-13T17:17:18Z', 322, 71.08984),
(97, 1707851099, '2024-02-13T19:04:59Z', 256, 66.72949);
-- --------------------------------------------------------
--
-- 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;
--
-- Gegevens worden geëxporteerd voor tabel `par_events`
--
INSERT INTO `par_events` (`id`, `timestamp`, `gateway_receive_time`, `device`, `value`) VALUES
(1, 1707844638, '2024-02-13T17:17:18Z', 322, 0.00000),
(2, 1707851099, '2024-02-13T19:04:59Z', 256, 0.00000);
-- --------------------------------------------------------
--
-- 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;
--
-- Gegevens worden geëxporteerd voor tabel `relative_humidity_events`
--
INSERT INTO `relative_humidity_events` (`id`, `timestamp`, `gateway_receive_time`, `device`, `value`) VALUES
(3, 1707844638, '2024-02-13T17:17:18Z', 322, 71.08984),
(4, 1707851099, '2024-02-13T19:04:59Z', 256, 66.72949),
(5, 1707844638, '2024-02-13T17:17:18Z', 322, 71.08984),
(6, 1707851099, '2024-02-13T19:04:59Z', 256, 66.72949);
-- --------------------------------------------------------
--
-- 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;
--
-- Gegevens worden geëxporteerd voor tabel `soil_electric_conductivity_events`
--
INSERT INTO `soil_electric_conductivity_events` (`id`, `timestamp`, `gateway_receive_time`, `device`, `value`) VALUES
(3, 1707851215, '2024-02-13T19:06:55Z', 322, 0.00000);
-- --------------------------------------------------------
--
-- 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;
--
-- Gegevens worden geëxporteerd voor tabel `soil_relative_permittivity_events`
--
INSERT INTO `soil_relative_permittivity_events` (`id`, `timestamp`, `gateway_receive_time`, `device`, `value`) VALUES
(3, 1707851215, '2024-02-13T19:06:55Z', 322, 1.52000);
-- --------------------------------------------------------
--
-- 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;
--
-- Gegevens worden geëxporteerd voor tabel `soil_temperature_events`
--
INSERT INTO `soil_temperature_events` (`id`, `timestamp`, `gateway_receive_time`, `device`, `value`) VALUES
(3, 1707851215, '2024-02-13T19:06:55Z', 322, 12.06000);
--
-- Indexen voor geëxporteerde tabellen
--
--
-- Indexen voor tabel `battery_voltage_events`
--
ALTER TABLE `battery_voltage_events`
ADD PRIMARY KEY (`id`);
--
-- Indexen voor tabel `devices`
--
ALTER TABLE `devices`
ADD PRIMARY KEY (`id`);
--
-- Indexen voor tabel `fetch`
--
ALTER TABLE `fetch`
ADD PRIMARY KEY (`id`);
--
-- Indexen voor tabel `par_events`
--
ALTER TABLE `par_events`
ADD PRIMARY KEY (`id`);
--
-- Indexen voor tabel `relative_humidity_events`
--
ALTER TABLE `relative_humidity_events`
ADD PRIMARY KEY (`id`);
--
-- Indexen voor tabel `soil_electric_conductivity_events`
--
ALTER TABLE `soil_electric_conductivity_events`
ADD PRIMARY KEY (`id`);
--
-- Indexen voor tabel `soil_relative_permittivity_events`
--
ALTER TABLE `soil_relative_permittivity_events`
ADD PRIMARY KEY (`id`);
--
-- Indexen voor tabel `soil_temperature_events`
--
ALTER TABLE `soil_temperature_events`
ADD PRIMARY KEY (`id`);
--
-- 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=11;
--
-- AUTO_INCREMENT voor een tabel `devices`
--
ALTER TABLE `devices`
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
--
-- AUTO_INCREMENT voor een tabel `fetch`
--
ALTER TABLE `fetch`
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=98;
--
-- AUTO_INCREMENT voor een tabel `par_events`
--
ALTER TABLE `par_events`
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
--
-- AUTO_INCREMENT voor een tabel `relative_humidity_events`
--
ALTER TABLE `relative_humidity_events`
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
--
-- 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=4;
--
-- 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=4;
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 */;

View File

@@ -0,0 +1,25 @@
import json
from paho.mqtt import subscribe
def on_message(client, userdata, message):
payload_str = message.payload.decode("utf-8")
data = json.loads(payload_str)
device_322_value = None
device_256_value = None
for key in data["results"]:
if key["device"] == 322:
device_322_value = key["value"]
elif key["device"] == 256:
device_256_value = key["value"]
print(f"Device 322 value: {device_322_value}")
print(f"Device 256 value: {device_256_value}")
print(f"Message received on topic {message.topic}: {data}")
if __name__ == "__main__":
topic = "goodgarden/par_events"
subscribe.callback(on_message, topic)

49
src/py/script/planten.py Normal file
View File

@@ -0,0 +1,49 @@
import json
import mysql.connector
import os
# Function to make a connection to the database
def database_connect():
return mysql.connector.connect(
host="localhost",
user="root",
password="",
database="goodgarden"
)
# Function to get the absolute path of the current directory
def get_current_directory():
return os.path.dirname(os.path.abspath(__file__))
def fetch_plant_and_write_to_json():
# Establish a database connection
connection = database_connect()
try:
cursor = connection.cursor(dictionary=True) # To fetch rows as dictionaries
# Execute the query to fetch data
cursor.execute("SELECT id, plant_naam, plantensoort, plant_geteelt FROM planten")
# Fetch all rows
plants = cursor.fetchall()
# Get the absolute path of the current directory
current_directory = get_current_directory()
# Construct the absolute path for the JSON file
json_file_path = os.path.join(current_directory, 'plants.json')
# Write fetched data to JSON file
with open(json_file_path, 'w') as json_file:
json.dump(plants, json_file, indent=4)
except mysql.connector.Error as error:
print("Error fetching data from MySQL table:", error)
finally:
# Close cursor and connection
if 'cursor' in locals():
cursor.close()
if connection.is_connected():
connection.close()
# Call the function to fetch data and write to JSON
fetch_plant_and_write_to_json()

32
src/py/script/plants.json Normal file
View File

@@ -0,0 +1,32 @@
[
{
"id": 47,
"plant_naam": "Tomaten",
"plantensoort": "Groente",
"plant_geteelt": 1
},
{
"id": 49,
"plant_naam": "Komkommer",
"plantensoort": "Groente",
"plant_geteelt": 1
},
{
"id": 50,
"plant_naam": "Appel",
"plantensoort": "Fruit",
"plant_geteelt": 1
},
{
"id": 51,
"plant_naam": "Sla",
"plantensoort": "Groente",
"plant_geteelt": 1
},
{
"id": 52,
"plant_naam": "Wietplant",
"plantensoort": "Onkruid",
"plant_geteelt": 0
}
]

View File

@@ -0,0 +1,13 @@
import json
from paho.mqtt import subscribe
def on_message(client, userdata, message):
payload_str = message.payload.decode("utf-8")
data = json.loads(payload_str)
print(f"Message received on topic {message.topic}: {data}")
if __name__ == "__main__":
topic = "goodgarden/relative_humidity"
subscribe.callback(on_message, topic)

View File

@@ -0,0 +1,218 @@
import requests
import time
from db_connect import database_connect
##########################* DEVICES #######################
def load_data(data):
mydb = database_connect()
if mydb.is_connected():
mycursor = mydb.cursor()
insert_query = """
INSERT INTO goodgarden.devices (serial_number, name, label, last_seen, last_battery_voltage)
VALUES (%s, %s, %s, %s, %s )
"""
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', '')
print(f"Inserting data: serial_number={serial_number}, name={name}, label={label}, last_seen={last_seen}, last_battery_voltage={last_battery_voltage}")
mycursor.execute(insert_query, (serial_number, name, label, last_seen, last_battery_voltage))
mydb.commit()
mycursor.close()
mydb.close()
print("Data inserted into the database.")
############################### EINDE ########################
# #
# #
# #
# #
##########################* PAR_EVENTS #######################
def load_data(data):
mydb = database_connect()
if mydb.is_connected():
mycursor = mydb.cursor()
# Here you need to adjust the correct column names and data formats based on the API response
insert_query = """
INSERT INTO goodgarden.par_events (timestamp, gateway_receive_time, device, value)
VALUES (%s, %s, %s, %s)
"""
for record in data['results']:
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}")
# Execute the query
mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
# Commit the changes
mydb.commit()
# Close cursor and connection
mycursor.close()
mydb.close()
print("Data inserted into the database.")
############################### EINDE ########################
# #
# #
# #
# #
##########################* RELATIVE_HUMIDITY_EVENTS #######################
def load_data(data):
mydb = database_connect()
if mydb.is_connected():
mycursor = mydb.cursor()
# Here you need to adjust the correct column names and data formats based on the API response
insert_query = """
INSERT INTO goodgarden.relative_humidity_events (timestamp, gateway_receive_time, device, value)
VALUES (%s, %s, %s, %s)
"""
for record in data['results']:
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}")
# Execute the query
mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
# Commit the changes
mydb.commit()
# Close cursor and connection
mycursor.close()
mydb.close()
print("Data inserted into the database.")
############################### EINDE ########################
# #
# #
# #
# #
##########################* SOIL_ELECTRIC_CONDUCTIVITY_EVENTS #######################
def load_data(data):
mydb = database_connect()
if mydb.is_connected():
mycursor = mydb.cursor()
# Here you need to adjust the correct column names and data formats based on the API response
insert_query = """
INSERT INTO goodgarden.soil_electric_conductivity_events (timestamp, gateway_receive_time, device, value)
VALUES (%s, %s, %s, %s)
"""
for record in data['results']:
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}")
# Execute the query
mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
# Commit the changes
mydb.commit()
# Close cursor and connection
mycursor.close()
mydb.close()
print("Data inserted into the database.")
############################### EINDE ########################
# #
# #
# #
# #
##########################* SOIL_TEMPERATURE_EVENTS #######################
def load_data(data):
mydb = database_connect()
if mydb.is_connected():
mycursor = mydb.cursor()
# Here you need to adjust the correct column names and data formats based on the API response
insert_query = """
INSERT INTO goodgarden.soil_temperature_events (timestamp, gateway_receive_time, device, value)
VALUES (%s, %s, %s, %s)
"""
for record in data['results']:
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}")
# Execute the query
mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
# Commit the changes
mydb.commit()
# Close cursor and connection
mycursor.close()
mydb.close()
print("Data inserted into the database.")
############################### EINDE ########################
# #
# #
# #
# #
##########################* SOIL_TEMPERATURE_EVENTS #######################
def load_data(data):
mydb = database_connect()
if mydb.is_connected():
mycursor = mydb.cursor()
# Here you need to adjust the correct column names and data formats based on the API response
insert_query = """
INSERT INTO goodgarden.soil_temperature_events (timestamp, gateway_receive_time, device, value)
VALUES (%s, %s, %s, %s)
"""
for record in data['results']:
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}")
# Execute the query
mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
# Commit the changes
mydb.commit()
# Close cursor and connection
mycursor.close()
mydb.close()
print("Data inserted into the database.")

View File

@@ -0,0 +1,74 @@
import os
import time
import requests
import paho.mqtt.client as mqtt
from dotenv import load_dotenv
load_dotenv()
API_URL = os.getenv("API_URL")
MQTT_HOST = os.getenv("MQTT_HOST")
MQTT_PORT = int(os.getenv("MQTT_PORT", 1883))
def get_data_from_api(request):
links = {
'battery': '/battery_voltage_events/',
'devices': '/devices/',
'parEvents': '/par_events/',
'humidity': '/relative_humidity_events/',
'soilConductifity': '/soil_electric_conductivity_events/',
'soilPermittivity' : '/soil_relative_permittivity_events/',
'soilTemperature': '/soil_temperature_events/'
}
headers = {
'accept': 'application/json',
'Authorization': f'Token {os.getenv("API_TOKEN")}'
}
url = API_URL + links[request]
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
except requests.exceptions.HTTPError as errh:
print ("HTTP Error:",errh)
return None
except requests.exceptions.ConnectionError as errc:
print ("Error Connecting:",errc)
return None
except requests.exceptions.Timeout as errt:
print ("Timeout Error:",errt)
return None
except requests.exceptions.RequestException as err:
print ("Something went wrong",err)
return None
data = response.json()
return data['results']
def publish_to_mqtt(topic, message):
client = mqtt.Client()
client.connect(MQTT_HOST, MQTT_PORT, 60)
try:
client.publish(topic, message)
except mqtt.MQTTException as e:
print(f"Failed to publish message: {e}")
finally:
client.disconnect()
def process_results(link, results):
for result in results:
if 'timestamp' in result and 'gateway_receive_time' in result and 'device' in result and 'value' in result:
message = f"Timestamp: {result['timestamp']}, Gateway Receive Time: {result['gateway_receive_time']}, Device: {result['device']}, Value: {result['value']}"
print(message)
publish_to_mqtt(link, message)
def main():
links = ['battery', 'devices', 'parEvents', 'humidity', 'soilConductifity', 'soilPermittivity', 'soilTemperature']
while True:
for link in links:
results = get_data_from_api(link)
if results is not None:
process_results(link, results)
time.sleep(5)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,13 @@
import json
from paho.mqtt import subscribe
def on_message(client, userdata, message):
payload_str = message.payload.decode("utf-8")
data = json.loads(payload_str)
print(f"Message received on topic {message.topic}: {data}")
if __name__ == "__main__":
topic = "goodgarden/soil_electric_conductivity"
subscribe.callback(on_message, topic)

View File

@@ -0,0 +1,13 @@
import json
from paho.mqtt import subscribe
def on_message(client, userdata, message):
payload_str = message.payload.decode("utf-8")
data = json.loads(payload_str)
print(f"Message received on topic {message.topic}: {data}")
if __name__ == "__main__":
topic = "goodgarden/soil_relative_permittivity"
subscribe.callback(on_message, topic)

View File

@@ -0,0 +1,13 @@
import json
from paho.mqtt import subscribe
def on_message(client, userdata, message):
payload_str = message.payload.decode("utf-8")
data = json.loads(payload_str)
print(f"Message received on topic {message.topic}: {data}")
if __name__ == "__main__":
topic = "goodgarden/soil_temperature"
subscribe.callback(on_message, topic)

406
src/py/static/css/style.css Normal file
View File

@@ -0,0 +1,406 @@
@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.png");
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;
}
body .mainContainer .mainBorder #sectie-1 {
display: flex;
flex-direction: column;
gap: 1rem;
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;
margin-top: 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;
}
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 .close {
color: #aaa;
float: right;
font-size: 1.75rem;
font-weight: bold;
}
.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-color: white;
}
#myModal button {
background-color: white;
color: black;
}
.toevoeging {
background: linear-gradient(45deg, #abd3ae, #2ecc71);
}
.annulatie-knop {
background: linear-gradient(45deg, #ffcc00, #ff6600);
}
#myModal button:hover {
background: linear-gradient(45deg, #abd3ae, #fff);
color: #000;
}
.modal .close {
color: #aaa;
float: right;
font-size: 1.75rem;
font-weight: bold;
}
.modal .close:hover,
.modal .close:active {
color: black;
text-decoration: none;
cursor: pointer;
}
.switch-container {
display: flex;
align-items: end;
}
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 30px;
}
.switch input {
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: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
border-radius: 50%;
transition: 0.4s;
}
input:checked + .slider {
background-color: #2ecc71;
}
input:checked + .slider:before {
transform: translateX(26px);
}
.rechterkant {
display: flex;
justify-content: end;
}
.plant-container,
#modalButton {
background-color: white;
}/*# sourceMappingURL=style.css.map */

View 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,iHAAA;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;AC5CR;AD+CM;EAEE,aAAA;EACA,sBAAA;EACA,SAAA;EACA,wBAAA;EACA,kBAAA;AC9CR;ADgDQ;EAEE,uBAAA;AC/CV;ADkDQ;EAlGN,2CAAA;EAKA,mBAAA;EAiGQ,aAAA;EACA,gBAAA;EACA,uBAAA;ACjDV;ADmDU;EA/GR,oCAAA;EAeA,mBAAA;EAoGU,kBAAA;EACA,oBAAA;AClDZ;ADoDY;EAEE,WAAA;ACnDd;ADqDc;EAEE,aAAA;EACA,8BAAA;EACA,gBAAA;ACpDhB;AD0DQ;EA/HN,2CAAA;EAKA,mBAAA;EA8HQ,aAAA;EACA,kBAAA;EACA,uBAAA;ACzDV;AD2DU;EA5IR,oCAAA;EAeA,mBAAA;EAiIU,kBAAA;EACA,sBAAA;EACA,aAAA;EACA,kBAAA;AC1DZ;AD4DY;EAEE,kBAAA;EACA,SAAA;EACA,2BAAA;AC3Dd;AD8DY;EAGE,kBAAA;EACA,QAAA;EACA,SAAA;EACA,gCAAA;AC9Dd;ADoEM;EAEE,aAAA;EACA,kCAAA;EACA,YAAA;ACnER;ADuEU;EAEE,cAAA;ACtEZ;ADwEY;EAEE,WAAA;EACA,yBAAA;ACvEd;AD2EgB;EAEE,YAAA;EACA,YAAA;EACA,eAAA;EACA,cAAA;EACA,iBAAA;EACA,aAAA;EACA,sBAAA;EACA,uBAAA;EACA,mBAAA;EACA,oCAAA;EACA,mBAAA;EACA,wCAAA;AC1ElB;AD4EkB;EAEE,YAAA;EACA,WAAA;AC3EpB;AD8EkB;EAEE,WAAA;AC7EpB;ADgFkB;EAEE,2BAAA;AC/EpB;ADsFU;EAEE,cAAA;ACrFZ;ADwFY;EAEE,oCAAA;EACA,mBAAA;ACvFd;ADyFc;EAEE,aAAA;EACA,8BAAA;EACA,eAAA;EACA,iBAAA;EACA,WAAA;ACxFhB;AD0FgB;EAEE,aAAA;EACA,8BAAA;EACA,WAAA;ACzFlB;ADiGM;EAvPJ,2CAAA;EAKA,mBAAA;EAsPM,aAAA;EACA,iCAAA;EACA,uBAAA;AChGR;ADkGQ;EApQN,oCAAA;EAeA,mBAAA;EAyPQ,YAAA;ACjGV;ADmGU;EAEE,oBAAA;EACA,aAAA;EACA,sBAAA;EACA,oBAAA;EACA,WAAA;EACA,6BAAA;EACA,WAAA;AClGZ;ADwGgB;EAEE,kBAAA;ACvGlB;ADgHgB;EAEE,kBAAA;AC/GlB;ADoHY;EAEE,kBAAA;ACnHd;ADqHc;EAGE,WAAA;EACA,kBAAA;EACA,OAAA;EACA,QAAA;EACA,WAAA;EACA,UAAA;EACA,iBAAA;ACrHhB;ADwHc;EAEE,aAAA;ACvHhB;AD0Hc;EAEE,UAAA;ACzHhB;;ADmIA;EACE,aAAA;EACA,uBAAA;EACA,oCAAA;EACA,kBAAA;EACA,UAAA;EACA,cAAA;AChIF;;ADmIA;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;AChIF;;ADkIA;EACE,WAAA;EACA,YAAA;EACA,kBAAA;EACA,iBAAA;AC/HF;;ADiIA;;EAEE,YAAA;EACA,qBAAA;EACA,eAAA;AC9HF;;ADiIA;;EAEE,wBAAA;EACA,aAAA;EACA,mBAAA;EACA,yBAAA;EACA,kBAAA;EACA,sBAAA;AC9HF;;ADiIA;EACE,aAAA;EACA,8BAAA;AC9HF;;ADiIA;EACE,UAAA;EACA,aAAA;EACA,sBAAA;EACA,YAAA;AC9HF;;ADiIA;EACE,aAAA;EACA,8BAAA;EACA,gBAAA;AC9HF;;ADiIA;;EAEE,OAAA;EACA,aAAA;EACA,aAAA;EACA,sBAAA;AC9HF;;ADiIA;;EAEE,yBAAA;EACA,aAAA;EACA,mBAAA;EACA,sBAAA;AC9HF;;ADiIA;;EAEE,WAAA;EACA,YAAA;EACA,mBAAA;EACA,eAAA;AC9HF;;ADiIA;EACE,uBAAA;AC9HF;;ADiIA;EACE,uBAAA;EACA,YAAA;AC9HF;;ADiIA;EACE,oDAAA;AC9HF;;ADiIA;EACE,oDAAA;AC9HF;;ADiIA;EACE,iDAAA;EACA,WAAA;AC9HF;;ADiIA;EACE,WAAA;EACA,YAAA;EACA,kBAAA;EACA,iBAAA;AC9HF;;ADiIA;;EAEE,YAAA;EACA,qBAAA;EACA,eAAA;AC9HF;;ADiIA;EACE,aAAA;EACA,gBAAA;AC9HF;;ADiIA;EACE,kBAAA;EACA,qBAAA;EACA,WAAA;EACA,YAAA;AC9HF;;ADiIA;EACE,UAAA;EACA,QAAA;EACA,SAAA;AC9HF;;ADiIA;EACE,kBAAA;EACA,eAAA;EACA,MAAA;EACA,OAAA;EACA,QAAA;EACA,SAAA;EACA,sBAAA;EACA,mBAAA;EACA,gBAAA;AC9HF;;ADiIA;EACE,kBAAA;EACA,WAAA;EACA,YAAA;EACA,WAAA;EACA,SAAA;EACA,WAAA;EACA,uBAAA;EACA,kBAAA;EACA,gBAAA;AC9HF;;ADiIA;EACE,yBAAA;AC9HF;;ADiIA;EACE,2BAAA;AC9HF;;ADiIA;EACE,aAAA;EACA,oBAAA;AC9HF;;ADiIE;;EAGE,uBAAA;AC/HJ","file":"style.css"}

View File

@@ -0,0 +1,534 @@
$primary-color: rgb(171, 211, 174);
$secondary-color: rgb(143, 188, 143);
@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.png");
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;
}
#sectie-1
{
display: flex;
flex-direction: column;
gap: 1rem;
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;
}
}
}
}
}
&-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 .close {
color: #aaa;
float: right;
font-size: 1.75rem;
font-weight: bold;
}
.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-color: white;
}
#myModal button {
background-color: white;
color: black;
}
.toevoeging {
background: linear-gradient(45deg, #abd3ae, #2ecc71);
}
.annulatie-knop {
background: linear-gradient(45deg, #ffcc00, #ff6600);
}
#myModal button:hover {
background: linear-gradient(45deg, #abd3ae, #fff);
color: #000;
}
.modal .close {
color: #aaa;
float: right;
font-size: 1.75rem;
font-weight: bold;
}
.modal .close:hover,
.modal .close:active {
color: black;
text-decoration: none;
cursor: pointer;
}
.switch-container {
display: flex;
align-items: end;
}
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 30px;
}
.switch input {
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: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
border-radius: 50%;
transition: 0.4s;
}
input:checked + .slider {
background-color: #2ecc71;
}
input:checked + .slider:before {
transform: translateX(26px);
}
.rechterkant {
display: flex;
justify-content: end;
}
.plant-container,
#modalButton
{
background-color: white;
}

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 107 KiB

View File

Before

Width:  |  Height:  |  Size: 19 MiB

After

Width:  |  Height:  |  Size: 19 MiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

300
src/py/static/js/main.js Normal file
View File

@@ -0,0 +1,300 @@
// const { ipcRenderer } = require("electron");
// document.addEventListener('DOMContentLoaded', () =>
// {
// ipcRenderer.send('request-update-temp', ['some', 'arguments']);
// ipcRenderer.on('update-temp-result', (event, newTemperature) => {
// if (newTemperature === 'error') {
// console.error('Er is een fout opgetreden bij het ophalen van de nieuwe temperatuur');
// } else {
// document.getElementById('bodem-temperatuur').textContent = newTemperature;
// }
// });
// });
// function openModal()
// {
// const modal = document.getElementById("myModal");
// const button = document.getElementById("modalButton");
// const close = document.getElementsByClassName("close")[0];
// // Toon de modal wanneer op de knop wordt geklikt
// button.onclick = function()
// {
// modal.style.display = "block";
// }
// // Sluit de modal wanneer op het 'sluiten' icoon wordt geklikt
// close.onclick = function()
// {
// modal.style.display = "none";
// }
// // Sluit de modal wanneer buiten de modal wordt geklikt
// window.onclick = function(event)
// {
// if (event.target == modal)
// {
// modal.style.display = "none";
// }
// }
// }
// /**
// * --- Functie om de grafiek te tekenen. Enigste belangrijke is de eerste 2 "const" arrays "data" & "xLabels".
// */
// function drawLineChart()
// {
// /*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!!*/
// const data = [20, 50, 60, 45, 50, 100, 70, 60, 65, 0, 85, 0];
// const xLabels = ["", "", "", "", "", 6, "", "", "", "", "", 12];
// const yLabels = ["", 20, "", 40, "", 60, "", 80, "", 100]; /*NIET VERANDEREN!!!*/
// const canvas = document.getElementById("myCanvas");
// const ctx = canvas.getContext("2d");
// ctx.clearRect(0, 0, canvas.width, canvas.height);
// const padding = 35; // Increased padding for Y labels
// const graphWidth = canvas.width - padding * 2;
// const graphHeight = canvas.height - padding * 2;
// ctx.beginPath();
// ctx.moveTo(padding, padding);
// ctx.lineTo(padding, canvas.height - padding);
// ctx.lineTo(canvas.width - padding, canvas.height - padding);
// ctx.stroke();
// // Set the color of the line
// ctx.strokeStyle = "rgb(143, 188, 143)";
// const xIncrement = graphWidth / (xLabels.length - 1);
// const yIncrement = graphHeight / (yLabels.length - 1);
// // Plot the data
// ctx.beginPath();
// ctx.moveTo(padding, canvas.height - padding - (data[0] / 100) * graphHeight);
// for (let i = 1; i < data.length; i++)
// {
// const xPos = padding + i * xIncrement;
// const yPos = canvas.height - padding - (data[i] / 100) * graphHeight;
// ctx.lineTo(xPos, yPos);
// }
// ctx.stroke();
// // Draw Y labels
// ctx.fillStyle = "black";
// ctx.textAlign = "right"; // Align text to the right
// ctx.textBaseline = "middle"; // Center vertically
// for (let i = 0; i < yLabels.length; i++)
// {
// if (yLabels[i] !== "")
// {
// const yPos = canvas.height - padding - i * yIncrement;
// ctx.fillText(yLabels[i], padding - 10, yPos);
// }
// }
// // Draw X labels
// ctx.textAlign = "center"; // Center horizontally for X labels
// for (let i = 0; i < xLabels.length; i++)
// {
// if (xLabels[i] !== "")
// {
// const xPos = padding + i * xIncrement;
// ctx.fillText(xLabels[i], xPos, canvas.height - padding + 20);
// }
// }
// }
// drawLineChart();
// /////////////////////////////////
// // Function to fetch battery data from Flask API
// function fetchBatteryData() {
// axios.get('http://127.0.0.1:5000')
// .then(response => {
// const batteryData = response.data;
// updateBatteryData(batteryData);
// })
// .catch(error => {
// console.error('Error fetching battery data:', error);
// });
// }
// // Function to update HTML content with battery data
// function updateBatteryData(batteryData) {
// document.getElementById('deviceNumber').innerText = batteryData.device;
// document.getElementById('voltage').innerText = batteryData.value;
// document.getElementById('time').innerText = batteryData.gateway_receive_time;
// document.getElementById('tevredenheid').innerText = batteryData.timestamp;
// // Voeg andere eigenschappen toe zoals nodig
// }
// // Fetch battery data when the page loads
// fetchBatteryData();
/////////////////////////////////
const { ipcRenderer } = require("electron");
const axios = require('axios');
// document.addEventListener('DOMContentLoaded', () => {
ipcRenderer.send('request-update-temp', ['some', 'arguments']);
ipcRenderer.on('update-temp-result', (event, newTemperature) => {
if (newTemperature === 'error') {
console.error('Er is een fout opgetreden bij het ophalen van de nieuwe temperatuur');
} else {
document.getElementById('bodem-temperatuur').textContent = newTemperature;
}
});
// 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');
// Function to open the modal
function openModal() {
const modal = document.getElementById("myModal");
const button = document.getElementById("modalButton");
const close = document.getElementsByClassName("close")[0];
// Check if elements are found before attaching events
if (modal && button && close) {
// Show the modal when the button is clicked
button.onclick = function () {
modal.style.display = "block";
}
// Close the modal when the 'close' icon is clicked
close.onclick = function () {
modal.style.display = "none";
}
// Close the modal when clicked outside the modal
window.onclick = function (event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
}
}
// Call the function to open the modal
openModal();
/**
* --- Function to draw the chart. The important arrays are "data" & "xLabels".
*/
function drawLineChart() {
const data = [20, 50, 60, 45, 50, 100, 70, 60, 65, 0, 85, 0];
const xLabels = ["", "", "", "", "", 6, "", "", "", "", "", 12];
const yLabels = ["", 20, "", 40, "", 60, "", 80, "", 100]; /*NIET VERANDEREN!!!*/
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
const padding = 35; // Increased padding for Y labels
const graphWidth = canvas.width - padding * 2;
const graphHeight = canvas.height - padding * 2;
ctx.beginPath();
ctx.moveTo(padding, padding);
ctx.lineTo(padding, canvas.height - padding);
ctx.lineTo(canvas.width - padding, canvas.height - padding);
ctx.stroke();
// Set the color of the line
ctx.strokeStyle = "rgb(143, 188, 143)";
const xIncrement = graphWidth / (xLabels.length - 1);
const yIncrement = graphHeight / (yLabels.length - 1);
// Plot the data
ctx.beginPath();
ctx.moveTo(padding, canvas.height - padding - (data[0] / 100) * graphHeight);
for (let i = 1; i < data.length; i++) {
const xPos = padding + i * xIncrement;
const yPos = canvas.height - padding - (data[i] / 100) * graphHeight;
ctx.lineTo(xPos, yPos);
}
ctx.stroke();
// Draw Y labels
ctx.fillStyle = "black";
ctx.textAlign = "right"; // Align text to the right
ctx.textBaseline = "middle"; // Center vertically
for (let i = 0; i < yLabels.length; i++) {
if (yLabels[i] !== "") {
const yPos = canvas.height - padding - i * yIncrement;
ctx.fillText(yLabels[i], padding - 10, yPos);
}
}
// Draw X labels
ctx.textAlign = "center"; // Center horizontally for X labels
for (let i = 0; i < xLabels.length; i++) {
if (xLabels[i] !== "") {
const xPos = padding + i * xIncrement;
ctx.fillText(xLabels[i], xPos, canvas.height - padding + 20);
}
}
}
// Call the function to draw the line chart
drawLineChart();
// Function to fetch battery data from Flask API
function fetchBatteryData() {
axios.get('http://127.0.0.1:5000')
.then(response => {
const batteryData = response.data;
updateBatteryData(batteryData);
})
.catch(error => {
console.error('Error fetching battery data:', error);
});
}
// Function to update HTML content with battery data
function updateBatteryData(batteryData) {
document.getElementById('deviceNumber').innerText = batteryData.device;
document.getElementById('voltage').innerText = batteryData.value;
document.getElementById('time').innerText = batteryData.gateway_receive_time;
document.getElementById('zulu').innerText = batteryData.timestamp;
// Voeg andere eigenschappen toe zoals nodig
}
// Fetch battery data when the page loads
fetchBatteryData();
// });

View File

@@ -0,0 +1,104 @@
class Plant {
constructor(dataObject) {
this.id = dataObject.id;
this.plantNaam = dataObject.plant_naam; // Note the property name change
this.plantensoort = dataObject.plantensoort;
this.plantGeteelt = dataObject.plant_geteelt;
}
}
class PlantGrid {
constructor() {
this.grid = [];
this.cols = 2; // Number of columns
this.rows = 4; // Number of rows (including the row for the "Add" button)
// Initialize the grid with null values
for (let i = 0; i < this.rows; i++) {
this.grid[i] = new Array(this.cols).fill(null);
}
// Load JSON data from the server
this.loadData();
}
loadData() {
fetch('../script/plants.json') // Assuming your JSON data is stored in 'plants.json'
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
const filteredData = data.filter(plantObject => plantObject.plant_geteelt === 1);
// Populate the grid with plant objects
filteredData.slice(0, 8).forEach((plantObject, index) => {
const plant = new Plant(plantObject);
const col = index % this.cols;
const row = Math.floor(index / this.cols);
this.grid[row][col] = plant;
});
// Display the grid in the HTML table with id "planten"
this.displayGrid();
})
.catch(error => console.error('Error loading data:', error));
}
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/Toevoegen.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();
});

108
src/py/templates/index.html Normal file
View File

@@ -0,0 +1,108 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Dashboard / Planten">
<meta name="author" content="B. Diker, A. Oomen">
<meta name="keywords" content="planten / 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">
<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">
<!-- <tr>
<td>
<article>
<img src="images/Icon awesome-apple-alt.png" alt="">
<h2>Tomaat</h2>
</article>
</td>
</tr> -->
</table>
<div class="formulier">
<div id="myModal" class="modal" style="display: none;">
<h1 id="plant-id">Plant Toevoegen</h1>
<form action="http://localhost:3000/submit-form" method="post">
<label for="plantNaam">Naam van de plant</label><br>
<input type="text" name="plant_naam" id="plantNaam"><br>
<label for="plantensoort">Soort van de plant</label><br>
<input type="text" name="plantensoort" id="plantensoort"><br>
<label for="aanwezig">Aanwezig in de kas</label><br>
<select name="aanwezig_in_kas">
<option value="ja">Ja</option>
<option value="nee">Nee</option>
</select><br>
<label for="ontvangenMeldingen">Meldingen ontvangen</label><br>
<select name="ontvangen_meldingen">
<option value="ja">Ja</option>
<option value="nee">Nee</option>
</select><br>
<section class="knop-container">
<br><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>
<!-- White space -->
<section>
</section>
<section class="kant-rechts">
<section id="sectie-1">
<article class="parent-algemeen-overzicht">
<article class="algemeen-overzicht">
<a href="kas_informatie.html">
<table class="table-informatie-kas">
<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>
<tr class="tr-informatie-kas">
<td>Aandachtspunten</td>
<td>1</td>
</tr>
</table>
<a/>
</article>
</article>
<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>
</section>
</section>
</section>
</section>
</body>
</html>

View File

@@ -0,0 +1,126 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Kas informatie / Planten" />
<meta name="author" content="B. Diker, A. Oomen" />
<meta name="keywords" content="planten / kas" />
<link rel="stylesheet" href="../static/css/style.css" />
<script src="../static/js/main.js" defer></script>
<title>Informatie Kas</title>
</head>
<body>
<section class="mainContainer">
<article>
<a href="index.html">
<img src="../static/images/logo.png" class="goodgarden-logo">
</a>
</article>
<section class="mainBorder informatie-kas-main-container">
<article>
<h1 class="pagina-titel">Informatie Kas</h1>
<section id="sectie-1">
<article class="parent-algemeen-overzicht">
<article class="algemeen-overzicht">
<table class="table-informatie-kas">
<tr class="tr-informatie-kas">
<td>Device</td>
<td id="deviceNumber"></td> <!-- Update this ID -->
</tr>
<tr class="tr-informatie-kas">
<td>Batterij Voltage</td>
<td id="voltage"></td> <!-- Update this ID -->
</tr>
<tr class="tr-informatie-kas">
<td>Tijden</td>
<td id="time"></td> <!-- Update this ID -->
</tr>
<tr class="tr-informatie-kas">
<td>Zulu</td>
<td id="zulu"></td> <!-- Update this ID -->
</tr>
</table>
</article>
</article>
<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>
<article class="grid-column-2">
<article class="grid-2-child">
<section class="parent-table">
<table class="kas-table-1">
<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">
<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">
<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>
<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>
</body>
</html>

View File

@@ -0,0 +1,118 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Planteninfo / Planten" />
<meta name="author" content="B. Diker, A. Oomen" />
<meta name="keywords" content="planten / kas" />
<link rel="stylesheet" href="../static/css/style.css" />
<script src="../static/js/main.js" defer></script>
<title>Informatie Kas</title>
</head>
<body>
<section class="mainContainer">
<article>
<a href="index.html">
<img src="../static/images/logo.png" class="goodgarden-logo">
</a>
</article>
<section class="mainBorder informatie-kas-main-container">
<article>
<h1>Informatie Kas</h1>
<section id="sectie-1">
<article class="parent-algemeen-overzicht">
<article class="algemeen-overzicht">
<table class="table-informatie-kas">
<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>
<tr class="tr-informatie-kas">
<td>Aandachtspunten</td>
<td>1</td>
</tr>
</table>
</article>
</article>
<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>
<article class="grid-column-2">
<article class="grid-2-child">
<section class="parent-table">
<table class="kas-table-1">
<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">
<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">
<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>