Browse Source

NEW FILES ADDED

master
caliskanbi 1 year ago
parent
commit
35118e8c20

+ 24
- 0
.idea/dataSources.xml View File

<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/software/backend/backend_database.db</jdbc-url> <jdbc-url>jdbc:sqlite:$PROJECT_DIR$/software/backend/backend_database.db</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir> <working-dir>$ProjectFileDir$</working-dir>
</data-source> </data-source>
<data-source source="LOCAL" name="backend_database" uuid="4f1f9bd8-463b-4b3b-b101-cc4b9b84e2e1">
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:C:\Users\bcali\Documents\Uni\BEI6\Projektarbeit\projektarbeit_duelger_waldhauser_caliskan\software\backend\tests\backend_database.db</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
<libraries>
<library>
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.40.1/sqlite-jdbc-3.40.1.jar</url>
</library>
</libraries>
</data-source>
<data-source source="LOCAL" name="test_database" uuid="a72361b0-954e-42bd-8930-b14a0b4c1023">
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:C:\Users\bcali\Documents\Uni\BEI6\Projektarbeit\projektarbeit_duelger_waldhauser_caliskan\software\backend\tests\test_database.db</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
<libraries>
<library>
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.40.1/sqlite-jdbc-3.40.1.jar</url>
</library>
</libraries>
</data-source>
</component> </component>
</project> </project>

+ 1
- 0
requirements.txt View File

Werkzeug==2.2.3 Werkzeug==2.2.3
zipp==3.15.0 zipp==3.15.0
python-ev3dev2==2.1.0.post1 python-ev3dev2==2.1.0.post1
pytest

BIN
software/backend/backend_database.db View File


software/backend/createdatabase_and_test.py → software/backend/createdatabase.py View File



from plantdatabase import PlantDataBase from plantdatabase import PlantDataBase


mydatabase = PlantDataBase()
mydatabase.create_table()
mydatabase = PlantDataBase('backend_database.db')
mydatabase.create_tables()


for i in range(1,6):
mydatabase.insert_plant(_gps='gps', plantname=f"Pflanze{i}")
for i in range(1, 6):
mydatabase.insert_plant(plantname=f"Pflanze{i}")


for i in range(1,7):
for i in range(1, 7):
plant_id = i plant_id = i
temp = random.random() temp = random.random()
humidity = random.random() humidity = random.random()
soil_moisture = random.random() soil_moisture = random.random()
pest_infestation = 0
light_intensity = random.random() light_intensity = random.random()
mydatabase.insert_measurement_data(plant_id=plant_id, mydatabase.insert_measurement_data(plant_id=plant_id,
sensordata_temp=temp, sensordata_temp=temp,
sensordata_humidity=humidity, sensordata_humidity=humidity,
sensordata_soil_moisture=soil_moisture, sensordata_soil_moisture=soil_moisture,
pest_infestation=pest_infestation,
light_intensity=light_intensity)
sensordata_brightness=light_intensity)

+ 34
- 12
software/backend/data_functions.py View File

""" """
import paho.mqtt.client as mqtt import paho.mqtt.client as mqtt
from plantdatabase import PlantDataBase from plantdatabase import PlantDataBase
from software.defines import Topics
from software.defines import Topics, MAX_PLANT_COUNT
import json import json
import uuid import uuid


sensordata_temp=payload['AirTemperature'], sensordata_temp=payload['AirTemperature'],
sensordata_humidity=payload['AirHumidity'], sensordata_humidity=payload['AirHumidity'],
sensordata_soil_moisture=payload['SoilMoisture'], sensordata_soil_moisture=payload['SoilMoisture'],
pest_infestation=0,
light_intensity=payload['Brightness'])
sensordata_brightness=payload['Brightness'])




def data_position(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase): def data_position(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase):




def action_getalldata(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase): def action_getalldata(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase):
# TODO: get data from database
plant_names = json.loads(message.payload.decode("UTF-8"))
print(plant_names)
alldata = [] alldata = []
for i in range(1, 7):
alldata.append(mydatabase.get_latest_data(plant_id=i))
for i in plant_names:
alldata.append(mydatabase.get_latest_data(plant_name=i))
client.publish(Topics['BACKEND_DATA_SENSORDATAALL'], json.dumps(alldata)) client.publish(Topics['BACKEND_DATA_SENSORDATAALL'], json.dumps(alldata))




def action_newplant(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase): def action_newplant(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase):
# TODO: insert new plant to database
pass
plant_data = json.loads(message.payload.decode("UTF-8"))
mydatabase.insert_plant(plantname=plant_data["PlantName"], plant_id=plant_data["PlantID"])
mydatabase.insert_measurement_data(plant_id=plant_data["PlantID"],
sensordata_temp=plant_data["AirTemperature"],
sensordata_humidity=plant_data["AirHumidity"],
sensordata_soil_moisture=plant_data["SoilMoisture"],
sensordata_brightness=plant_data["Brightness"])
print("BACKEND_ACTION_NEWPLANT RECEIVED DATA: " + str(plant_data))




def action_configureplant(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase): def action_configureplant(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase):
# TODO: configure plant
pass
plant_data = json.loads(message.payload.decode("UTF-8"))
mydatabase.configure_plant(plant_id=plant_data["plant_ID"], plantname=plant_data["PlantName"])
mydatabase.insert_measurement_data(plant_id=plant_data["PlantID"],
sensordata_temp=plant_data["AirTemperature"],
sensordata_humidity=plant_data["AirHumidity"],
sensordata_soil_moisture=plant_data["SoilMoisture"],
sensordata_brightness=plant_data["Brightness"])
print("BACKEND_ACTION_CONFIGUREPLANT RECEIVED DATA: " + str(plant_data))




def action_deleteplant(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase): def action_deleteplant(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase):
# TODO: delete plant from database (from ID)
pass
delete_plant = json.loads(message.payload.decode("UTF-8"))
mydatabase.delete_plant(plant_id=delete_plant["PlantID"])
print("BACKEND_ACTION_DELETEPLANT RECEIVED DATA: " + str(delete_plant))


def action_countplants(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase):
count_payload = {
"CurrentCount": mydatabase.plant_count(),
"MaxCount": MAX_PLANT_COUNT
}
print("BACKEND_DATA_PLANTCOUNT SENDED DATA:" + str(count_payload))
client.publish(Topics["BACKEND_ACTION_PLANTCOUNT"], json.dumps(count_payload, indent=4))

+ 7
- 3
software/backend/main.py View File



# imports # imports
import paho.mqtt.client as mqtt import paho.mqtt.client as mqtt
from software.defines import MQTT_BROKER_LOCAL, MQTT_BROKER_GLOBAL, Topics, BACKEND_CLIENT_ID
from software.defines import MQTT_BROKER_LOCAL, MQTT_BROKER_GLOBAL, Topics, BACKEND_CLIENT_ID, DATABASE_NAME
from plantdatabase import PlantDataBase from plantdatabase import PlantDataBase
import data_functions import data_functions


# inits # inits
mydatabase = PlantDataBase()
mydatabase.create_table()
mydatabase = PlantDataBase(database_name=DATABASE_NAME)
mydatabase.create_tables()
order_handler = [] # will contain UUIDS with Order IDs order_handler = [] # will contain UUIDS with Order IDs




lambda client, userdata, message: data_functions. lambda client, userdata, message: data_functions.
action_deleteplant(client, userdata, message, mydatabase)) action_deleteplant(client, userdata, message, mydatabase))


_client.subscribe(Topics['BACKEND_ACTION_PLANTCOUNT'])
_client.message_callback_add(Topics['BACKEND_ACTION_PLANTCOUNT'], lambda client, userdata, message: data_functions.
action_countplants(client, userdata, message, mydatabase))

# END TOPIC SUBSCRIPTIONS # END TOPIC SUBSCRIPTIONS
else: else:
print("connection failed") print("connection failed")

+ 95
- 49
software/backend/plantdatabase.py View File

# file to create a database via python script # file to create a database via python script
import sqlite3 import sqlite3
from typing import Optional




class PlantDataBase: class PlantDataBase:
""" """
Class to create Makeathon database Class to create Makeathon database
""" """
def __init__(self):
self.db_file = 'backend_database.db'

def __init__(self, database_name: str):
self.db_file = database_name # 'backend_database.db'
self.conn = None self.conn = None
try: try:
self.conn = sqlite3.connect(self.db_file, check_same_thread=False) self.conn = sqlite3.connect(self.db_file, check_same_thread=False)
print(e) print(e)
self.cur = self.conn.cursor() self.cur = self.conn.cursor()


def create_table(self):
table_config = "CREATE TABLE IF NOT EXISTS plants " \
"(plant_ID INTEGER PRIMARY KEY AUTOINCREMENT," \
"plantName TEXT)"
self.cur.execute(table_config)
def create_tables(self):
try:
table_config = "CREATE TABLE IF NOT EXISTS plants " \
"(PlantID INTEGER PRIMARY KEY," \
"PlantName 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_soil_moisture REAL," \
"light_intensity REAL," \
"FOREIGN KEY (plant_ID)" \
"REFERENCES plants (plant_ID) )"
self.cur.execute(table_config)
table_config = "CREATE TABLE IF NOT EXISTS measurement_values " \
"(measurementID INTEGER PRIMARY KEY," \
"Timestamp DATETIME DEFAULT CURRENT_TIMESTAMP," \
"PlantID INTEGER, " \
"AirTemperature REAL," \
"AirHumidity REAL," \
"SoilMoisture REAL," \
"Brightness REAL," \
"FOREIGN KEY (PlantID)" \
"REFERENCES plants (PlantID) )"
self.cur.execute(table_config)
return True
except sqlite3.Warning as e:
return e


def insert_plant(self, _gps: str, plantname):
self.cur.execute("INSERT INTO plants (gps, plantName) VALUES (?,?)", (_gps, plantname))
self.conn.commit()
def insert_plant(self, plantname: str, plant_id: int):
try:
self.cur.execute("INSERT INTO plants (PlantName, PlantID) VALUES (?,?)", (plantname, plant_id))
self.conn.commit()
return True
except (sqlite3.NotSupportedError, sqlite3.Warning) as e:
return e

def configure_plant(self, plant_id: int, plantname: str):
try:
self.cur.execute("UPDATE plants SET PlantID = ?, PlantName = ? WHERE PlantID= ?",
(plant_id, plantname, plant_id))
self.conn.commit()
return True
except (sqlite3.NotSupportedError, sqlite3.Warning) as e:
return e

def delete_plant(self, plant_id):
try:
self.cur.execute('DELETE FROM plants WHERE PlantID = ?', (plant_id,))
self.conn.commit()
return True
except (sqlite3.NotSupportedError, sqlite3.Warning) as e:
return e


def insert_measurement_data(self, plant_id, def insert_measurement_data(self, plant_id,
sensordata_temp, sensordata_temp,
sensordata_humidity, sensordata_humidity,
sensordata_soil_moisture, sensordata_soil_moisture,
light_intensity):
self.cur.execute(f"INSERT INTO measurement_values (plant_ID, sensordata_temp, sensordata_humidity,"
f" sensordata_soil_moisture, light_intensity) VALUES "
f"({plant_id}, {sensordata_temp}, {sensordata_humidity}, {sensordata_soil_moisture}"
f", {light_intensity})")
self.conn.commit()
sensordata_brightness) -> bool:
try:
self.cur.execute(f"INSERT INTO measurement_values (PlantID, AirTemperature, AirHumidity,"
f"SoilMoisture, Brightness) VALUES "
f"({plant_id}, {sensordata_temp}, {sensordata_humidity}, {sensordata_soil_moisture}"
f", {sensordata_brightness})")
self.conn.commit()
return True
except (sqlite3.NotSupportedError, sqlite3.Warning) as e:
return e


def get_latest_data(self, plant_id) -> dict:
def get_latest_data(self, plant_name: Optional[str] = None, plant_id: Optional[int] = None):
""" """
Gets the newest parameter of specific plant and returns all parameters in json format Gets the newest parameter of specific plant and returns all parameters in json format
:param plant_id: :param plant_id:
:param plant_name:
:return: :return:
""" """
self.cur.execute(f"SELECT * FROM measurement_values where plant_ID = {plant_id} ORDER BY Timestamp DESC LIMIT 1")
data = self.cur.fetchone()
self.cur.execute(f"SELECT plantName FROM plants where plant_ID = {plant_id}")
name = self.cur.fetchone()
print(data)
print(name[0])
json_file = {
"MeasurementID": data[0],
"PlantID": data[2],
"Timestamp": data[1],
"AirTemperature": data[3],
"AirHumidity": data[4],
"SoilMoisture": data[5],
"Brightness": data[6],
"PlantName": name
}
return json_file
try:
if plant_name is not None and plant_id is None:
self.cur.execute("SELECT PlantID FROM plants where PlantName = ?", (plant_name,))
plant_id = self.cur.fetchone()[0]
elif (plant_id is not None and plant_name is not None) or (plant_id is None and plant_name is None):
raise TypeError("Can't pass plant_id and plant_name to the function. Just one allowed !")

self.cur.execute("SELECT * FROM measurement_values where PlantID = ? ORDER BY Timestamp DESC LIMIT 1",
(plant_id,))
data = self.cur.fetchone()
json_file = {
"MeasurementID": data[0],
"PlantID": data[2],
"Timestamp": data[1],
"AirTemperature": data[3],
"AirHumidity": data[4],
"SoilMoisture": data[5],
"Brightness": data[6],
"PlantName": plant_name
}
return json_file
except (sqlite3.Warning, TypeError) as e:
return e


def delete_data(self, table_name): def delete_data(self, table_name):
self.cur.execute(f"DELETE FROM {table_name}")
self.cur.execute(f'DELETE FROM {table_name}')
self.conn.commit() self.conn.commit()
return True


# TODO: Kemals Scheiß implementieren # TODO: Kemals Scheiß implementieren


def delete_plant(self, plant_id):
self.cur.execute('DELETE FROM plants WHERE plant_ID = ?', (plant_id,))
self.conn.commit()
def plant_count(self) -> int:
"""
returns the number of plants registered in the database
:return:
"""
self.cur.execute("SELECT COUNT(*) FROM plants")
return self.cur.fetchone()[0]

def __del__(self):
self.conn.close()

BIN
software/backend/tests/test_database.db View File


+ 50
- 0
software/backend/tests/test_plantdatabase.py View File

#
# created by caliskan
# use this file to test your plantdatabase changes

from software.backend.plantdatabase import PlantDataBase
import pytest


def test_create_table():
testdatabase = PlantDataBase(database_name='test_database.db')
assert testdatabase.create_tables() is True


def test_insert_and_delete_plant():
testdatabase = PlantDataBase(database_name='test_database.db')

assert testdatabase.create_tables() is True
assert testdatabase.delete_data("plants") is True
assert testdatabase.insert_plant(plantname="Bertha", plant_id=1) is True
assert testdatabase.plant_count() == 1
assert testdatabase.delete_plant(plant_id=1) is True
assert testdatabase.plant_count() == 0


def test_insert_and_get_measurement_values():
test_plant_id = 2
test_temp = 22.4
test_humidity = 93.4
test_soil_moisture = 12.5
test_brightness = 66
test_plant_name = "Bertha"

testdatabase = PlantDataBase(database_name='test_database.db')
assert testdatabase.create_tables() is True
assert testdatabase.delete_data("plants") is True
assert testdatabase.insert_plant(plantname=test_plant_name, plant_id=test_plant_id) is True

assert testdatabase.insert_measurement_data(plant_id=test_plant_id,
sensordata_temp=test_temp,
sensordata_humidity=test_humidity,
sensordata_soil_moisture=test_soil_moisture,
sensordata_brightness=test_brightness) is True
test_plant_data = testdatabase.get_latest_data(plant_name=test_plant_name)
print(test_plant_data)
assert test_plant_data["PlantID"] == test_plant_id
assert test_plant_data["AirTemperature"] == test_temp
assert test_plant_data["AirHumidity"] == test_humidity
assert test_plant_data["SoilMoisture"] == test_soil_moisture
assert test_plant_data["Brightness"] == test_brightness
assert test_plant_data["PlantName"] == test_plant_name

+ 7
- 3
software/defines.py View File

MQTT_BROKER_GLOBAL = "mqtt.eclipseprojects.io" MQTT_BROKER_GLOBAL = "mqtt.eclipseprojects.io"
RASPI_CLIENT_ID = "smart_farming_raspi" RASPI_CLIENT_ID = "smart_farming_raspi"
BACKEND_CLIENT_ID = "smart_farming_server" BACKEND_CLIENT_ID = "smart_farming_server"
MAX_PLANT_COUNT = 6
DATABASE_NAME = 'backend_database.db'


# Topics: # Topics:
Topics = { Topics = {
"ROBOT_DATA_PICTURE": "ROBOT/DATA/PICTURE", "ROBOT_DATA_PICTURE": "ROBOT/DATA/PICTURE",


"BACKEND_ACTION_DRIVE": "BACKEND/ACTION/DRIVE", "BACKEND_ACTION_DRIVE": "BACKEND/ACTION/DRIVE",
"BACKEND_ACTION_DRIVEPALL": "BACKEND/ACTION/DRIVEALL",
"BACKEND_ACTION_DRIVEALL": "BACKEND/ACTION/DRIVEALL",
"BACKEND_ACTION_GETPOSITION": "BACKEND/ACTION/GETPOSITION", "BACKEND_ACTION_GETPOSITION": "BACKEND/ACTION/GETPOSITION",
"BACKEND_ACTION_GETBATTERY": "BACKEND/ACTION/GETBATTERY", "BACKEND_ACTION_GETBATTERY": "BACKEND/ACTION/GETBATTERY",
"BACKEND_ACTION_GETALLDATA": "BACKEND/ACTION/GETALLDATA", "BACKEND_ACTION_GETALLDATA": "BACKEND/ACTION/GETALLDATA",


PLANTCOUNT = { PLANTCOUNT = {
"CurrenCount": 0, "CurrenCount": 0,
"maxCount": 0
"MaxCount": 0
} }


# endregion # endregion


# GETBATTERY -> no message needed # GETBATTERY -> no message needed


# GETALLDATA -> no message needed
GETALLDATA = {
"PlantNames": []
}


# endregion # endregion

Loading…
Cancel
Save