diff --git a/documentation/ER Model Gran Canaria.pdf b/documentation/ER Model Gran Canaria.pdf new file mode 100644 index 0000000..6b30d94 Binary files /dev/null and b/documentation/ER Model Gran Canaria.pdf differ diff --git a/software/backend/backend_database.db b/software/backend/backend_database.db index 406143c..665a62c 100644 Binary files a/software/backend/backend_database.db and b/software/backend/backend_database.db differ diff --git a/software/backend/data_handling_functions.py b/software/backend/data_handling_functions.py index 1bd1ca6..9b3ba23 100644 --- a/software/backend/data_handling_functions.py +++ b/software/backend/data_handling_functions.py @@ -5,73 +5,66 @@ This file contains all functions, which handle the different cases. Every function should return json format with the wanted data from the database """ import paho.mqtt.client as mqtt +from plantdatabase import PlantDataBase -def data_handler(client: mqtt.Client, message) -> dict: +def data_handler(client: mqtt.Client, message: mqtt.MQTTMessage, mydatabase: PlantDataBase) -> None: """ main entrypoint for a message handling method - :param client: - :param message: - :return: + :param mydatabase: database with plant data + :param client: mqtt client + :param message: received message + :return: None """ - if message.topic.startwith('BackEnd'): - - if message.topic == "BackEnd/Action/All": - action_all(client, message) - elif message.topic == "BackEnd/Action/GetPosition": - action_get_position(client, message) - elif message.topic == "BackEnd/Action/GetBattery": - action_get_battery(client, message) - elif message.topic == "BackEnd/Action/GetAllData": - action_get_all_data(client, message) - - elif message.topic.startwith('Robot'): - - if message.topic == "Robot/Data/SensorData": + if message.topic.startswith('Robot'): + if message.topic == 'Robot/Action/SensorData': data_sensordata(client, message) - elif message.topic == "Robot/Data/Position": + elif message.topic == 'Robot/Action/Position': data_position(client, message) - elif message.topic == "Robot/Data/Battery": + elif message.topic == 'Robot/Action/Battery': data_battery(client, message) - elif message.topic == "Robot/Data/Picture": - data_picture(client, message) + elif message.topic.startswith('BackEnd'): + if message.topic == 'BackEnd/Action/Drive': + action_drive(client, message) + elif message.topic == 'BackEnd/Action/GetPosition': + action_getposition(client) + elif message.topic == 'BackEnd/Action/GetBattery': + action_getbattery(client) + elif message.topic == 'BackEnd/Action/GetAllData': + action_getalldata(client) -# START ACTION FUNCTION DEFINITIONS +# Robot Channel Reactions -def action_all(client, message): +def data_sensordata(client: mqtt.Client, message: mqtt.MQTTMessage): + # TODO: Store data in database pass -def action_get_position(client, message): +def data_position(client: mqtt.Client, message: mqtt.MQTTMessage): + # TODO: Publish as json pass -def action_get_battery(client, message): +def data_battery(client: mqtt.Client, message: mqtt.MQTTMessage): + # TODO: Publish as json pass -def action_get_all_data(client, message): +# FrontEnd Channel Reactions + +def action_drive(client: mqtt.Client, message: mqtt.MQTTMessage): + client.publish('Robot/Action/Drive', message.payload).decode("utf-8") + + +def action_getposition(client: mqtt.Client): + client.publish('Robot/Action/GetPosition') + + +def action_getbattery(client: mqtt.Client): + client.publish('Robot/Action/GetBattery') + + +def action_getalldata(client: mqtt.Client): + # TODO: get data from database pass - - -# END ACTION FUNCTION DEFINITIONS - -# START ROBOT FUNCTION DEFINITIONS - -def data_sensordata(client, message): - pass - - -def data_position(client, message): - pass - - -def data_battery(client, message): - pass - - -def data_picture(client, message): - pass - -# END ROBOT FUNCTION DEFINITIONS diff --git a/software/backend/dev_test_examples/mqtt_publisher.py b/software/backend/dev_test_examples/mqtt_publisher.py index e005f0b..4e65bc1 100644 --- a/software/backend/dev_test_examples/mqtt_publisher.py +++ b/software/backend/dev_test_examples/mqtt_publisher.py @@ -10,7 +10,7 @@ client.connect(mqttBroker) while True: randNumber = uniform(20.0, 21.0) - client.publish("planttest", randNumber) + client.publish("Robot/Data/Battery") print("Just published " + str(randNumber) + " to topic TEMPERATURE") time.sleep(0.5) diff --git a/software/backend/main.py b/software/backend/main.py index 872e863..dd8ed26 100644 --- a/software/backend/main.py +++ b/software/backend/main.py @@ -13,38 +13,57 @@ from defines import MQTT_BROKER_LOCAL, MQTT_BROKER_GLOBAL from plantdatabase import PlantDataBase from data_handling_functions import data_handler +# inits +mydatabase = PlantDataBase() +mydatabase.create_table() -def on_message(client, userdata, message): + +def on_message(client: mqtt.Client, userdata, message): + """ + This method gets called, if a subscribed channel gets a new message. + Message gets forwarded to the data handler + :param client: mqtt client object + :param userdata: + :param message: received message object + :return: None + """ + print(type(message)) print(f'message received! {message.topic}') - data_handler(client, message) + data_handler(client, message, mydatabase) -def on_connect(client, userdata, flags, rc): +def on_connect(client: mqtt.Client, userdata, flags, rc): + """ + This method gets called, when it connects to a mqtt broker. + It is used to subscribe to the specific topics + :param client: mqtt client object + :param userdata: + :param flags: + :param rc: connection flag + :return: + """ 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/Action/All") - client.subscribe("BackEnd/Action/GetPosition") - client.subscribe("BackEnd/Action/GetBattery") - client.subscribe("BackEnd/Action/GetAllData") + # From Robot: + client.subscribe('Robot/Data/SensorData') + client.subscribe('Robot/Data/Position') + client.subscribe('Robot/Data/Battery') + # client.subscribe('Robot/Data/Picture') + # From FrontEnd: + client.subscribe('BackEnd/Action/Drive') + client.subscribe('BackEnd/Action/GetPosition') + client.subscribe('BackEnd/Action/GetBattery') + client.subscribe('BackEnd/Action/GetAllData') # 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 diff --git a/software/backend/plantdatabase.py b/software/backend/plantdatabase.py index 3a8b27c..e217faa 100644 --- a/software/backend/plantdatabase.py +++ b/software/backend/plantdatabase.py @@ -19,8 +19,7 @@ class PlantDataBase: def create_table(self): table_config = "CREATE TABLE IF NOT EXISTS plants " \ "(plant_ID INTEGER PRIMARY KEY AUTOINCREMENT," \ - " gps TEXT," \ - " plant_type TEXT)" + " gps TEXT)" self.cur.execute(table_config) table_config = "CREATE TABLE IF NOT EXISTS measurement_values " \ @@ -29,7 +28,7 @@ class PlantDataBase: "plant_ID INTEGER, " \ "sensordata_temp REAL," \ "sensordata_humidity REAL," \ - "sensordata_ground_humidity REAL," \ + "sensordata_soil_moisture REAL," \ "pest_infestation INTEGER," \ "light_intensity REAL," \ "FOREIGN KEY (plant_ID)" \ @@ -47,7 +46,7 @@ class PlantDataBase: 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" sensordata_soil_moisture, pest_infestation, light_intensity) VALUES " f"({plant_id}, {sensordata_temp}, {sensordata_humidity}, {sensordata_ground_humidity}, {pest_infestation}" f", {light_intensity})") self.conn.commit() @@ -66,7 +65,7 @@ class PlantDataBase: "timestamp": data[1], "sensordata_temp": data[3], "sensordata_humidity": data[4], - "sensordata_ground_humidity": data[5], + "sensordata_soil_moisture": data[5], "pest_infestation": data[6], "light_intensity": data[7] }