diff --git a/.hintrc b/.hintrc index 058c88a..ae62a1a 100644 --- a/.hintrc +++ b/.hintrc @@ -3,6 +3,11 @@ "development" ], "hints": { - "axe/text-alternatives": "off" + "axe/text-alternatives": [ + "default", + { + "image-alt": "off" + } + ] } } \ No newline at end of file diff --git a/ReadMe.md b/ReadMe.md index bcdedca..71b8b79 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -1,16 +1,17 @@ # 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 * Python * Node.Js * XAMPP (of andere naar keuze) + * MQTT Geinstalleerd en toegevoegd aan je PATH variable ### Installeren -Zorg dat je in de hoofdmap "GoodGarden" zit. Kijk in je path: "/GoodGarden". Als je in de correcte map zit moet je de volgende items installeren: +Zorg dat je in de hoofdmap "GoodGarden" zit. Kijk in je path: "../GoodGarden". Als je in de correcte map zit moet je de volgende items installeren: npm install electron npm install express diff --git a/app.js b/app.js index 372f23a..0c11547 100644 --- a/app.js +++ b/app.js @@ -18,11 +18,19 @@ server.post('/submit-form', (req, res) => { let options = { mode: 'text', - args: [plant_naam, plantensoort, plant_geteelt], + args: [plant_naam, plantensoort, plant_geteelt] // Zet hier een variable bij om de data toe te voegen aan de database }; - // The following line was causing issues and has been commented out - // ipcRenderer.send('request-update-temp', [/* arguments for Python script */]); + // Voer Python script uit met de plant_naam als argument + PythonShell.run('./script/db_connect_form.py', options, (err, results) => { + if (err) { + console.error(err); + res.send('Er is een fout opgetreden'); + } else { + console.log('Python script uitvoering resultaten:', results); + res.send('Formulier succesvol verwerkt'); + } + }); }); // Start the server for connecting to the database diff --git a/battery_voltage_events.py b/battery_voltage_events.py new file mode 100644 index 0000000..b0faac6 --- /dev/null +++ b/battery_voltage_events.py @@ -0,0 +1,239 @@ +import mysql.connector +import requests +from datetime import datetime, timezone, timedelta +import time + +# Functie om verbinding te maken met de database +def database_connect(): + return mysql.connector.connect( + host="localhost", + user="root", + password="", + database="goodgarden" + ) + +def calculate_timestamp(gateway_receive_time): + # 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) + + # Voeg het tijdsverschil van 1 uur toe voor de Nederlandse tijdzone (UTC+1) + datetime_obj_nl = datetime_obj_utc + timedelta(hours=1) + + # Formateer het datetime-object als een leesbare datumstring + formatted_date = datetime_obj_nl.strftime("%Y-%m-%d %H:%M:%S") + return formatted_date +# 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', '') + + # Voeg de timestamp-berekening toe + calculated_timestamp = calculate_timestamp(gateway_receive_time) + + print(f"\nInserted data: Timestamp: {calculated_timestamp}, Device: {device}, Battery Voltage: {value}V") + 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(2) + +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) + """ + + try: + # Voer de query uit zonder de timestamp te berekenen + 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}\n") # Print de ingevoerde gegevens + + mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value)) + + # Bevestig de wijzigingen + mydb.commit() + + print("Data inserted into the database.") + + except mysql.connector.Error as err: + print(f"Error: {err}") + + finally: + # 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}:\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.") diff --git a/goodgarden.sql b/goodgarden.sql new file mode 100644 index 0000000..c77be7f --- /dev/null +++ b/goodgarden.sql @@ -0,0 +1,421 @@ +-- 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 + +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 */ +; diff --git a/mqtt/db_connect.py b/mqtt/db_connect.py new file mode 100644 index 0000000..bc4922c --- /dev/null +++ b/mqtt/db_connect.py @@ -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 \ No newline at end of file diff --git a/mqtt/mqtt_client.py b/mqtt/mqtt_client.py new file mode 100644 index 0000000..35f8402 --- /dev/null +++ b/mqtt/mqtt_client.py @@ -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") diff --git a/mqtt/publisher.py b/mqtt/publisher.py new file mode 100644 index 0000000..b6ff42a --- /dev/null +++ b/mqtt/publisher.py @@ -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() diff --git a/package-lock.json b/package-lock.json index 65119af..e37043a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,16 +9,66 @@ "dependencies": { "axios": "^1.6.7", "body-parser": "^1.20.2", + "elctron": "^0.0.1-security", "express": "^4.18.3", "mysql2": "^3.9.1", "python-shell": "^5.0.0" }, "devDependencies": { + "concurrently": "^8.2.2", "electron": "^23.3.13", "npm-run-all": "^4.1.5", "wait-on": "^7.2.0" } }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "extraneous": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "extraneous": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "extraneous": true + }, + "express": { + "version": "4.18.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.3.tgz", + "integrity": "sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw==", + "extraneous": true + }, + "extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "extraneous": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/@babel/runtime": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz", + "integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@electron/get": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", @@ -190,6 +240,15 @@ "node": ">= 0.6" } }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -417,6 +476,20 @@ "node": ">=0.8.0" } }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/clone-response": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", @@ -461,6 +534,118 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/concurrently": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz", + "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.2", + "date-fns": "^2.30.0", + "lodash": "^4.17.21", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "spawn-command": "0.0.2", + "supports-color": "^8.1.1", + "tree-kill": "^1.2.2", + "yargs": "^17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": "^14.13.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/concurrently/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/concurrently/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concurrently/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/concurrently/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -518,6 +703,22 @@ "semver": "bin/semver" } }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -640,6 +841,11 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, + "node_modules/elctron": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/elctron/-/elctron-0.0.1-security.tgz", + "integrity": "sha512-7Wuk6B1NYD7yhzVsPAnXtVdw3LpZFiAteoVsNthzu8cfht+tts6aM3IenqpAbEIomABBFNDkUfCaZYR9z4PyEg==" + }, "node_modules/electron": { "version": "23.3.13", "resolved": "https://registry.npmjs.org/electron/-/electron-23.3.13.tgz", @@ -664,6 +870,12 @@ "integrity": "sha512-Za3eRO5y0UWShynpsbNq/Dtqjc+g3GM9/PnrebiWiU4pYa5dOQbpCGuZ7ICqbiZ0JvLaZZ4eq7t5cSts2IEgkg==", "dev": true }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -811,6 +1023,15 @@ "dev": true, "optional": true }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -1061,6 +1282,15 @@ "is-property": "^1.0.2" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -1459,6 +1689,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-negative-zero": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", @@ -2171,6 +2410,12 @@ "node": ">=4" } }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", @@ -2189,6 +2434,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -2472,6 +2726,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/spawn-command": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", + "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", + "dev": true + }, "node_modules/spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", @@ -2527,6 +2787,20 @@ "node": ">= 0.8" } }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/string.prototype.padend": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.5.tgz", @@ -2589,6 +2863,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -2665,6 +2951,15 @@ "node": ">=0.6" } }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", @@ -2899,12 +3194,71 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -2912,6 +3266,33 @@ "dev": true, "optional": true }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", diff --git a/package.json b/package.json index f3e7116..78a1d37 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "author": "", "license": "ISC", "devDependencies": { + "concurrently": "^8.2.2", "electron": "^23.3.13", "npm-run-all": "^4.1.5", "wait-on": "^7.2.0" @@ -17,6 +18,7 @@ "dependencies": { "axios": "^1.6.7", "body-parser": "^1.20.2", + "elctron": "^0.0.1-security", "express": "^4.18.3", "mysql2": "^3.9.1", "python-shell": "^5.0.0" diff --git a/src/css/style.css.map b/src/css/style.css.map new file mode 100644 index 0000000..43ebafd --- /dev/null +++ b/src/css/style.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["style.scss","style.css"],"names":[],"mappings":"AAGQ,mFAAA;AACA,2GAAA;AAgCR;EAEI,wCAhCU;EAiCV,SAAA;AClCJ;;ADqCA;EAEI,iCApCQ;ACCZ;;ADsCA;EAEI,kDAAA;EACA,4BAAA;EACA,sBAAA;EACA,2BAAA;EACA,iCA7CQ;EA8CR,aAAA;EACA,uBAAA;EACA,mBAAA;EACA,aAAA;EACA,SAAA;ACpCJ;ADsCI;EAEI,WAAA;EACA,aAAA;EACA,2CAAA;EACA,mBAAA;EACA,aAAA;ACrCR;ADuCQ;EAEI,kBAAA;EACA,WAAA;EACA,SAAA;EACA,WAAA;EACA,2BAAA;ACtCZ;ADyCQ;EAEI,aAAA;EACA,8BAAA;ACxCZ;AD2CQ;EAEI,uBAAA;EACA,eAAA;EACA,aAAA;EACA,oCAAA;EACA,mBAAA;AC1CZ;AD4CY;EAEI,eAAA;EACA,mBAAA;AC3ChB;AD8CY;EAEI,aAAA;EACA,sBAAA;EACA,SAAA;EACA,wBAAA;EACA,kBAAA;AC7ChB;AD+CgB;EAEI,uBAAA;AC9CpB;ADiDgB;EAvFZ,2CAAA;EAKA,mBAAA;EAsFgB,aAAA;EACA,gBAAA;AChDpB;ADmDoB;EApGhB,oCAAA;EAeA,mBAAA;EAyFoB,kBAAA;EACA,oBAAA;AClDxB;ADoDwB;EAEI,WAAA;ACnD5B;ADqD4B;EAEI,aAAA;EACA,8BAAA;EACA,gBAAA;ACpDhC;AD0DgB;EApHZ,2CAAA;EAKA,mBAAA;EAmHgB,aAAA;EACA,kBAAA;ACzDpB;AD2DoB;EAhIhB,oCAAA;EAeA,mBAAA;EAqHoB,kBAAA;EACA,sBAAA;EACA,aAAA;EACA,kBAAA;AC1DxB;AD4DwB;EAEI,kBAAA;EACA,SAAA;EACA,2BAAA;AC3D5B;AD8DwB;EAGI,kBAAA;EACA,QAAA;EACA,SAAA;EACA,gCAAA;AC9D5B;ADoEY;EAEI,aAAA;EACA,kCAAA;EACA,YAAA;ACnEhB;ADuEoB;EAEI,cAAA;ACtExB;ADwEwB;EAEI,WAAA;EACA,yBAAA;ACvE5B;AD2EgC;EAEI,YAAA;EACA,YAAA;EACA,eAAA;EACA,cAAA;EACA,iBAAA;EACA,aAAA;EACA,sBAAA;EACA,uBAAA;EACA,mBAAA;EACA,oCAAA;EACA,mBAAA;EACA,wCAAA;AC1EpC;AD4EoC;EAEI,YAAA;EACA,WAAA;AC3ExC;AD8EoC;EAEI,WAAA;AC7ExC;ADgFoC;EAEI,2BAAA;AC/ExC;ADwFoB;EAEI,cAAA;EACA,kBAAA;ACvFxB;ADyFwB;EAGI,oCAAA;EACA,mBAAA;ACzF5B;AD2F4B;EAEA,aAAA;EACA,8BAAA;EACA,eAAA;EACA,iBAAA;EACA,WAAA;AC1F5B;AD4FgC;EAEI,aAAA;EACA,8BAAA;EACA,WAAA;AC3FpC;ADmGY;EA9OR,2CAAA;EAKA,mBAAA;EA6OY,aAAA;EACA,iCAAA;AClGhB;ADoGgB;EA1PZ,oCAAA;EAeA,mBAAA;EA+OgB,YAAA;ACnGpB;ADsGoB;EAEI,oBAAA;EACA,aAAA;EACA,sBAAA;EACA,oBAAA;EACA,WAAA;EACA,6BAAA;EACA,WAAA;ACrGxB;AD2GgC;EAEI,kBAAA;AC1GpC;ADmHgC;EAEI,kBAAA;AClHpC;ADuHwB;EAEI,kBAAA;ACtH5B;ADwH4B;EAGI,WAAA;EACA,kBAAA;EACA,OAAA;EACA,QAAA;EACA,WAAA;EACA,UAAA;EACA,iBAAA;ACxHhC;AD2H4B;EAEI,aAAA;AC1HhC;AD6H4B;EAEI,UAAA;AC5HhC;;ADwII,YAAA;AACJ;EACI,aAAA;EACA,uBAAA;EACA,oCAAA;EACA,kBAAA;EACA,UAAA;EACA,cAAA;ACrIJ;;ADwIA,2BAAA;AAEA;EAEI,aAAA;EACA,eAAA;EACA,YAAA;EACA,SAAA;EACA,QAAA;EACA,gCAAA;EACA,iBAAA;EACA,gBAAA;EACA,wCAAA;EACA,WAAA;EACA,YAAA;EACA,uBAAA;EACA,mBAAA;ACvIJ;ADyII;EAEI,WAAA;EACA,YAAA;EACA,kBAAA;EACA,iBAAA;ACxIR;AD0IQ;EAGI,YAAA;EACA,qBAAA;EACA,eAAA;AC1IZ","file":"style.css"} \ No newline at end of file diff --git a/src/get_data.php b/src/get_data.php new file mode 100644 index 0000000..77ba071 --- /dev/null +++ b/src/get_data.php @@ -0,0 +1,50 @@ +connect_error) { + die("Connection failed: " . $conn->connect_error); +} + +// Query om gegevens op te halen uit de tabel devices +$query_devices = "SELECT * FROM devices"; +$result_devices = $conn->query($query_devices); + +// Query om gegevens op te halen uit de tabel battery_voltage_events +$query_battery_voltage = "SELECT * FROM battery_voltage_events"; +$result_battery_voltage = $conn->query($query_battery_voltage); + +// Query om gegevens op te halen uit de tabel fetch +$query_fetch = "SELECT * FROM fetch"; +$result_fetch = $conn->query($query_fetch); + +// Array om resultaten op te slaan +$data = array(); + +// Controleren of er resultaten zijn van de tabel devices +if ($result_devices->num_rows > 0) { + $data['devices'] = $result_devices->fetch_all(MYSQLI_ASSOC); +} + +// Controleren of er resultaten zijn van de tabel battery_voltage_events +if ($result_battery_voltage->num_rows > 0) { + $data['battery_voltage_events'] = $result_battery_voltage->fetch_all(MYSQLI_ASSOC); +} + +// Controleren of er resultaten zijn van de tabel fetch +if ($result_fetch->num_rows > 0) { + $data['fetch'] = $result_fetch->fetch_all(MYSQLI_ASSOC); +} + +// Gegevens als JSON-uitvoer +echo json_encode($data); + +// Verbinding sluiten +$conn->close(); diff --git a/src/js/main.js b/src/js/main.js new file mode 100644 index 0000000..5d770b7 --- /dev/null +++ b/src/js/main.js @@ -0,0 +1,113 @@ +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); + } + } +} diff --git a/src/js/planten.class.js b/src/js/planten.class.js new file mode 100644 index 0000000..db55ccc --- /dev/null +++ b/src/js/planten.class.js @@ -0,0 +1,32 @@ +dataHardObject = { + "id": 1, + "plantnaam": "Tomaat", + "plantensoort": "Groente", + "plantGeteelt": 1 +} + +// Nieuwe planten aanmaken in de table +// function hardcodeData(dataHardObject) +// { +// dataHardObject => "id" +// } + +class Plant { + constructor(dataHardObject) { + this.id = dataHardObject.id; + this.plantNaam = dataHardObject.plantNaam; + this.plantensoort = dataHardObject.plantensoort; + this.plantGeteelt = dataHardObject.plantGeteelt; + } + + htmlData(plantNaam) { + if (this.plantGeteelt) + { + const titel = document.querySelector(".plant-naam"); + titel.textContent = this.plantNaam; + } + } +} + +const tomaatPlant = new Plant(dataHardObject); +tomaatPlant.htmlData(); \ No newline at end of file diff --git a/src/kas_informatie.html b/src/kas_informatie.html new file mode 100644 index 0000000..c3d34b4 --- /dev/null +++ b/src/kas_informatie.html @@ -0,0 +1,119 @@ + + + + + + + + Informatie Kas + + +
+
+ +
+
+
+

Informatie Kas

+
+
+
+ + + + + + + + + + + + + + + + + +
Dagen tot Oogst12
Dagen in Kas2
Tevredenheid80%
Aandachtspunten1
+
+
+
+
+

Zonlicht

+ +
+
+
+
+
+
+
+ + + + + + + + + + + + + +
Aantal geplant:Loading...
Succesvolle Oogst:2
Gefaalde Oogst:2
+ + + + + + + + + + + + + + + + + +
Warmste Maand:n.v.t.
koudste Maand:December
Gemiddelde Bodemtemp.:2˚C
Gemiddelde Uren Zonlicht:2u
+ + + + + + + + + + + + + + + + + +
Laatste Irrigatie:2u
Aankomende Irrigatie:2u
Laatste Bemesting2d
Aankomende Bemesting:2w
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/py/script/calculate.py b/src/py/script/calculate.py index 5a4f5f5..9175a51 100644 --- a/src/py/script/calculate.py +++ b/src/py/script/calculate.py @@ -1,5 +1,6 @@ # In calculate.py + # Doe je berekeningen hier, vervang 42 door je berekende waarde calculated_value = 42 diff --git a/src/py/script/db_connect.py b/src/py/script/db_connect.py index fbed212..8d61b95 100644 --- a/src/py/script/db_connect.py +++ b/src/py/script/db_connect.py @@ -1,4 +1,4 @@ -import mysql.connector #** TYPE IN TERMINAL: "pip install mysql-connector-python" +import mysql.connector from mysql.connector import Error def database_connect(): diff --git a/src/py/script/devices.py b/src/py/script/devices.py index 3825589..eb63fca 100644 --- a/src/py/script/devices.py +++ b/src/py/script/devices.py @@ -1,71 +1,36 @@ -import requests -import time +import json -from db_connect import database_connect +from paho.mqtt import subscribe -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() +def on_message(client, userdata, message): + payload_str = message.payload.decode("utf-8") + data = json.loads(payload_str) - data = response.json() - print(f"Data from {url}:") - print(data) - load_data(data) + device_256 = None + last_seen = None + last_battery_voltage = None - except requests.exceptions.RequestException as e: - print(f"Error fetching data from {url}: {e}") + device_322 = None + last_seen = None + last_battery_voltage = None - print("Waiting for the next retrieval action...") + 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}") - # time.sleep(300) # Time here is in seconds. + 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}") - 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.") + print(f"\033[92mMessage received on topic\033[0m {message.topic}: {data}") 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) + topic = "goodgarden/devices" + subscribe.callback(on_message, topic) \ No newline at end of file diff --git a/src/py/script/par_events.py b/src/py/script/par_events.py index 8246737..a5cda5e 100644 --- a/src/py/script/par_events.py +++ b/src/py/script/par_events.py @@ -1,64 +1,25 @@ -import requests -import time +import json -from db_connect import database_connect +from paho.mqtt import subscribe -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() +def on_message(client, userdata, message): + payload_str = message.payload.decode("utf-8") + data = json.loads(payload_str) - data = response.json() - print(f"Data from {url}:") - print(data) - load_data(data) + device_322_value = None + device_256_value = None - except requests.exceptions.RequestException as e: - print(f"Error fetching data from {url}: {e}") + for key in data["results"]: + if key["device"] == 322: + device_322_value = key["value"] + elif key["device"] == 256: + device_256_value = key["value"] - print("Waiting for the next retrieval action...") + print(f"Device 322 value: {device_322_value}") + print(f"Device 256 value: {device_256_value}") - 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.") + print(f"Message received on topic {message.topic}: {data}") 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) \ No newline at end of file + topic = "goodgarden/par_events" + subscribe.callback(on_message, topic) \ No newline at end of file diff --git a/src/py/script/relative_humidity_events.py b/src/py/script/relative_humidity_events.py index 6961094..4b71813 100644 --- a/src/py/script/relative_humidity_events.py +++ b/src/py/script/relative_humidity_events.py @@ -1,64 +1,13 @@ -import requests -import time +import json -from db_connect import database_connect +from paho.mqtt import subscribe -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() +def on_message(client, userdata, message): + payload_str = message.payload.decode("utf-8") + data = json.loads(payload_str) - 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.") + print(f"Message received on topic {message.topic}: {data}") 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) \ No newline at end of file + topic = "goodgarden/relative_humidity" + subscribe.callback(on_message, topic) \ No newline at end of file diff --git a/src/py/script/samenvoegen_databases.py b/src/py/script/samenvoegen_databases.py new file mode 100644 index 0000000..b604664 --- /dev/null +++ b/src/py/script/samenvoegen_databases.py @@ -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.") \ No newline at end of file diff --git a/src/py/script/soil_electric_conductivity_events.py b/src/py/script/soil_electric_conductivity_events.py index d9a598a..69f0960 100644 --- a/src/py/script/soil_electric_conductivity_events.py +++ b/src/py/script/soil_electric_conductivity_events.py @@ -1,63 +1,13 @@ -import requests -import time +import json -from db_connect import database_connect +from paho.mqtt import subscribe -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() +def on_message(client, userdata, message): + payload_str = message.payload.decode("utf-8") + data = json.loads(payload_str) - data = response.json() - print(f"Data from {url}:") - print(data) - load_data(data) + print(f"Message received on topic {message.topic}: {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) \ No newline at end of file + topic = "goodgarden/soil_electric_conductivity" + subscribe.callback(on_message, topic) \ No newline at end of file diff --git a/src/py/script/soil_relative_permittivity_events.py b/src/py/script/soil_relative_permittivity_events.py index 62b3483..ce0cb25 100644 --- a/src/py/script/soil_relative_permittivity_events.py +++ b/src/py/script/soil_relative_permittivity_events.py @@ -1,66 +1,13 @@ -import requests -import time +import json -from db_connect import database_connect +from paho.mqtt import subscribe -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() +def on_message(client, userdata, message): + payload_str = message.payload.decode("utf-8") + data = json.loads(payload_str) - 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.") + print(f"Message received on topic {message.topic}: {data}") 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) \ No newline at end of file + topic = "goodgarden/soil_relative_permittivity" + subscribe.callback(on_message, topic) \ No newline at end of file diff --git a/src/py/script/soil_temperature_events.py b/src/py/script/soil_temperature_events.py index 2cd9750..89b7116 100644 --- a/src/py/script/soil_temperature_events.py +++ b/src/py/script/soil_temperature_events.py @@ -1,65 +1,13 @@ -import requests -import time +import json +from paho.mqtt import subscribe -from db_connect import database_connect +def on_message(client, userdata, message): + payload_str = message.payload.decode("utf-8") + data = json.loads(payload_str) -def fetch_and_display_all(url, access_token, repeat_count=5): - for _ in range(repeat_count): + print(f"Message received on topic {message.topic}: {data}") - 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) \ No newline at end of file + topic = "goodgarden/soil_temperature" + subscribe.callback(on_message, topic) \ No newline at end of file diff --git a/src/py/static/css/style.css b/src/py/static/css/style.css index df72a6f..a418aa3 100644 --- a/src/py/static/css/style.css +++ b/src/py/static/css/style.css @@ -1,4 +1,3 @@ -/*default colors*/ @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 { @@ -15,6 +14,7 @@ body { background-repeat: no-repeat; background-size: cover; background-position: center; + font-family: "Afacad", sans-serif; display: flex; justify-content: center; align-items: center; @@ -32,7 +32,7 @@ body .mainContainer .goodgarden-logo { position: absolute; width: 10vw; left: 50%; - top: 2.5rem; + top: 4.1rem; transform: translateX(-50%); } body .mainContainer .informatie-kas-main-container { @@ -41,6 +41,7 @@ body .mainContainer .informatie-kas-main-container { } body .mainContainer .mainBorder { padding: 1.25rem 1.5rem; + padding: 1rem 0; height: 35rem; border: solid 5px rgb(171, 211, 174); border-radius: 40px; @@ -56,6 +57,9 @@ body .mainContainer .mainBorder #sectie-1 { 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; @@ -88,6 +92,7 @@ body .mainContainer .mainBorder #sectie-1 .grafiek .grafiek-innerbox { font-size: 1.25rem; padding: 0 1rem 2.5rem; height: 225px; + position: relative; } body .mainContainer .mainBorder #sectie-1 .grafiek .grafiek-innerbox h2 { position: absolute; @@ -138,6 +143,7 @@ body .mainContainer .mainBorder .content .kant-links #planten td article:hover { } body .mainContainer .mainBorder .content .kant-rechts { grid-column: 3; + margin-right: 2rem; } body .mainContainer .mainBorder .content .kant-rechts #metingen { border: solid 3px rgb(171, 211, 174); @@ -145,14 +151,15 @@ body .mainContainer .mainBorder .content .kant-rechts #metingen { } body .mainContainer .mainBorder .content .kant-rechts #metingen #main-waardes { display: flex; - justify-content: space-evenly; + 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-around; + justify-content: space-between; + width: 100%; } body .mainContainer .mainBorder .grid-column-2 { box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5); @@ -169,6 +176,8 @@ 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%; } diff --git a/src/py/static/css/style.scss b/src/py/static/css/style.scss index 4949508..adc4ce4 100644 --- a/src/py/static/css/style.scss +++ b/src/py/static/css/style.scss @@ -1,5 +1,3 @@ -/*default colors*/ - $primary-color: rgb(171, 211, 174); $secondary-color: rgb(143, 188, 143); @@ -10,10 +8,10 @@ $font-titels: "Akaya Kanadaka", system-ui; $font-text: "Afacad", sans-serif; -@mixin flexbox +@mixin flexbox-center { display: flex; - justify-content: space-around; + justify-content: center; } @mixin groene-border @@ -53,7 +51,7 @@ body background-repeat: no-repeat; background-size: cover; background-position: center; - // font-family: $font-text; + font-family: $font-text; display: flex; justify-content: center; align-items: center; @@ -70,11 +68,10 @@ body .goodgarden-logo { - // z-index: inherit; position: absolute; width: 10vw; left: 50%; - top: 2.5rem; + top: 4.1rem; transform: translateX(-50%); } @@ -87,6 +84,7 @@ body .mainBorder { padding: 1.25rem 1.5rem; + padding: 1rem 0; height: 35rem; border: solid 5px $primary-color; border-radius: 40px; @@ -105,6 +103,11 @@ body padding: 0 2.5rem 0 1rem; position: relative; + h1 + { + background-color: green; + } + .parent-algemeen-overzicht { @include box-shadow; @@ -119,7 +122,6 @@ body @include inner-border-radius; font-size: 1.25rem; padding: .5rem 1rem; - // background-color: red; .table-informatie-kas { @@ -131,8 +133,6 @@ body justify-content: space-between; text-align: left; } - - } } } @@ -151,7 +151,7 @@ body font-size: 1.25rem; padding: 0 1rem 2.5rem; height: 225px; - // position: relative; + position: relative; h2 { @@ -170,8 +170,13 @@ body } } } +<<<<<<< HEAD:src/py/static/css/style.scss } +======= + + } +>>>>>>> main:src/css/style.scss .content { display: grid; @@ -191,7 +196,11 @@ body td { +<<<<<<< HEAD:src/py/static/css/style.scss article +======= + article +>>>>>>> main:src/css/style.scss { height: 7rem; width: 10rem; @@ -227,12 +236,21 @@ body } } } +<<<<<<< HEAD:src/py/static/css/style.scss &-rechts { grid-column: 3; // margin-right: 2rem; +======= + + &-rechts + { + grid-column: 3; + margin-right: 2rem; + +>>>>>>> main:src/css/style.scss #metingen { @@ -242,7 +260,11 @@ body #main-waardes { display: flex; +<<<<<<< HEAD:src/py/static/css/style.scss justify-content: space-evenly; +======= + justify-content: space-between; +>>>>>>> main:src/css/style.scss padding: .5rem; padding-bottom: 0; width: 100%; @@ -250,15 +272,20 @@ body table { display: flex; +<<<<<<< HEAD:src/py/static/css/style.scss justify-content: space-around; // width: 100%; +======= + justify-content: space-between; + width: 100%; +>>>>>>> main:src/css/style.scss } } } } } } - + .grid-column-2 { @include box-shadow; @@ -278,8 +305,8 @@ body padding: 1.5rem 2rem; display: flex; flex-direction: column; - // align-items: stretch; - // gap: 2.5rem; + align-items: stretch; + gap: 2.5rem; justify-content: space-around; height: 90%;