@@ -0,0 +1,12 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project version="4"> | |||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true"> | |||
<data-source source="LOCAL" name="backend_database.db" uuid="a5aefbe2-75a1-4a5e-ae27-5f87ff08045a"> | |||
<driver-ref>sqlite.xerial</driver-ref> | |||
<synchronize>true</synchronize> | |||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver> | |||
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/software/backend/backend_database.db</jdbc-url> | |||
<working-dir>$ProjectFileDir$</working-dir> | |||
</data-source> | |||
</component> | |||
</project> |
@@ -0,0 +1,7 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project version="4"> | |||
<component name="SqlDialectMappings"> | |||
<file url="file://$PROJECT_DIR$/software/backend/plantdatabase.py" dialect="GenericSQL" /> | |||
<file url="PROJECT" dialect="SQLite" /> | |||
</component> | |||
</project> |
@@ -0,0 +1,6 @@ | |||
""" | |||
created by caliskan at 19.04.2023 | |||
This file contains all functions, which handle the different cases. | |||
Every function should return json format with the wanted data from the database | |||
""" |
@@ -0,0 +1,8 @@ | |||
""" | |||
created by caliskan at 19.04.2023 | |||
contains all constants for the backend architecture of the smart garden project | |||
""" | |||
MQTT_BROKER_LOCAL = "" | |||
MQTT_BROKER_GLOBAL = "mqtt.eclipseprojects.io" |
@@ -0,0 +1,16 @@ | |||
import paho.mqtt.client as mqtt | |||
from random import randrange, uniform | |||
import time | |||
mqttBroker ="mqtt.eclipseprojects.io" | |||
client = mqtt.Client("Temperature_Inside") | |||
client.connect(mqttBroker) | |||
while True: | |||
randNumber = uniform(20.0, 21.0) | |||
client.publish("planttest", randNumber) | |||
print("Just published " + str(randNumber) + " to topic TEMPERATURE") | |||
time.sleep(0.5) | |||
@@ -0,0 +1,18 @@ | |||
import paho.mqtt.client as mqtt | |||
import time | |||
def on_message(client, userdata, message): | |||
print("received message: " ,str(message.payload.decode("utf-8"))) | |||
mqttBroker ="mqtt.eclipseprojects.io" | |||
client = mqtt.Client("Smartphone") | |||
client.connect(mqttBroker) | |||
client.loop_start() | |||
client.subscribe("TEMPERATURE") | |||
client.on_message=on_message | |||
time.sleep(30) | |||
client.loop_stop() |
@@ -0,0 +1,54 @@ | |||
""" | |||
created by caliskan at 19.04.2023 | |||
This file contains the main script for the backend server of smart garden project | |||
It has the task to be a bridge between the frontend and robot. | |||
It also contains a database with the current plant data | |||
Used protocol for interaction: mqtt (paho-mqtt module) | |||
""" | |||
# imports | |||
import paho.mqtt.client as mqtt | |||
from defines import MQTT_BROKER_LOCAL, MQTT_BROKER_GLOBAL | |||
from plantdatabase import PlantDataBase | |||
def on_message(client, userdata, message): | |||
print(f'message received! {message.topic}') | |||
def on_connect(client, userdata, flags, rc): | |||
if rc == 0: | |||
print("connected") | |||
# TOPIC SUBSCRIPTIONS | |||
client.subscribe("planttest") | |||
# Robot topics | |||
client.subscribe("Robot/Data/SensorData") | |||
client.subscribe("Robot/Data/Position") | |||
client.subscribe("Robot/Data/Battery") | |||
client.subscribe("Robot/Data/Picture") | |||
# FrontEnd topics | |||
client.subscribe("BackEnd/Data/SensorData") | |||
client.subscribe("BackEnd/Data/SensorDataAll") | |||
client.subscribe("BackEnd/Data/Position") | |||
client.subscribe("BackEnd/Data/Battery") | |||
client.subscribe("BackEnd/Data/Picture") | |||
# END TOPIC SUBSCRIPTIONS | |||
else: | |||
print("connection failed") | |||
def main(): | |||
mydatabase = PlantDataBase() | |||
mydatabase.create_table() | |||
client = mqtt.Client() | |||
client.on_connect = on_connect | |||
client.on_message = on_message | |||
client.connect(MQTT_BROKER_GLOBAL) | |||
client.loop_forever() | |||
if __name__ == "__main__": | |||
main() |
@@ -1,29 +0,0 @@ | |||
import paho.mqtt.client as mqtt | |||
def on_connect(_client, userdata, flags, rc): | |||
print("Connected with result code " + str(rc)) | |||
client.subscribe("test/topic") | |||
def on_message(_client, userdata, msg): | |||
print(msg.topic + " " + str(msg.payload)) | |||
client = mqtt.Client() | |||
client.on_connect = on_connect | |||
client.on_message = on_message | |||
client.connect("localhost", 1883, 60) | |||
client.loop_forever() | |||
"""In this example, we create a new instance of the mqtt.Client class and set up the on_connect and on_message | |||
callback functions. The on_connect function is called when the client successfully connects to the broker, | |||
and the on_message function is called when a message is received on a subscribed topic. | |||
Then, we call the connect method to connect to the MQTT broker running on the local machine on port 1883, and set the | |||
keepalive value to 60 seconds. | |||
Finally, we call the loop_forever method to start the client and begin processing incoming messages. This method | |||
blocks the program execution and runs the client loop in a loop until the client is disconnected. (ChatGPT)""" |
@@ -0,0 +1,77 @@ | |||
# file to create a database via python script | |||
import sqlite3 | |||
class PlantDataBase: | |||
""" | |||
Class to create Makeathon database | |||
""" | |||
def __init__(self): | |||
self.db_file = 'backend_database.db' | |||
self.conn = None | |||
try: | |||
self.conn = sqlite3.connect(self.db_file, check_same_thread=False) | |||
print(sqlite3.version) | |||
except sqlite3.Error as e: | |||
print(e) | |||
self.cur = self.conn.cursor() | |||
def create_table(self): | |||
table_config = "CREATE TABLE IF NOT EXISTS plants " \ | |||
"(plant_ID INTEGER PRIMARY KEY AUTOINCREMENT," \ | |||
" gps TEXT," \ | |||
" plant_type TEXT)" | |||
self.cur.execute(table_config) | |||
table_config = "CREATE TABLE IF NOT EXISTS measurement_values " \ | |||
"(measurement_id INTEGER PRIMARY KEY AUTOINCREMENT," \ | |||
"Timestamp DATETIME DEFAULT CURRENT_TIMESTAMP," \ | |||
"plant_ID INTEGER, " \ | |||
"sensordata_temp REAL," \ | |||
"sensordata_humidity REAL," \ | |||
"sensordata_ground_humidity REAL," \ | |||
"pest_infestation INTEGER," \ | |||
"light_intensity REAL," \ | |||
"FOREIGN KEY (plant_ID)" \ | |||
" REFERENCES plants (plant_ID) )" | |||
self.cur.execute(table_config) | |||
def insert_plant(self, gps: str, plant_type: str): | |||
self.cur.execute(f"INSERT INTO plants (gps, plant_type) VALUES ({gps}, {plant_type})") | |||
self.conn.commit() | |||
def insert_measurement_data(self, plant_id, | |||
sensordata_temp, | |||
sensordata_humidity, | |||
sensordata_ground_humidity, | |||
pest_infestation, | |||
light_intensity): | |||
self.cur.execute(f"INSERT INTO measurement_values (plant_ID, sensordata_temp, sensordata_humidity," | |||
f" sensordata_ground_humidity, pest_infestation, light_intensity) VALUES " | |||
f"({plant_id}, {sensordata_temp}, {sensordata_humidity}, {sensordata_ground_humidity}, {pest_infestation}" | |||
f", {light_intensity})") | |||
self.conn.commit() | |||
def get_latest_data(self, plant_id) -> dict: | |||
""" | |||
Gets the newest parameter of specific plant and returns all parameters in json format | |||
:param plant_id: | |||
:return: | |||
""" | |||
self.cur.execute(f"SELECT * FROM measurement_values where plant_ID = {plant_id} ORDER BY Timestamp DESC LIMIT 1") | |||
data = self.cur.fetchone() | |||
json_file = { | |||
"measurement_id": data[0], | |||
"plant_id": data[2], | |||
"timestamp": data[1], | |||
"sensordata_temp": data[3], | |||
"sensordata_humidity": data[4], | |||
"sensordata_ground_humidity": data[5], | |||
"pest_infestation": data[6], | |||
"light_intensity": data[7] | |||
} | |||
return json_file | |||
def delete_data(self, table_name): | |||
self.cur.execute(f"DELETE FROM {table_name}") | |||
self.conn.commit() |