diff --git a/software/roboter/raspy/defines.py b/software/roboter/raspy/defines.py new file mode 100644 index 0000000..face226 --- /dev/null +++ b/software/roboter/raspy/defines.py @@ -0,0 +1,119 @@ +""" +created by caliskan at 19.04.2023 + +contains all constants for the backend architecture of the smart garden project +""" + +MQTT_BROKER_LOCAL = "lorem ipsum" +MQTT_BROKER_GLOBAL = "mqtt.eclipseprojects.io" +RASPI_CLIENT_ID = "smart_farming_raspi" +BACKEND_CLIENT_ID = "smart_farming_server" + +# Topics: +Topics = { + "ROBOT_ACTION_DRIVE": "ROBOT/ACTION/DRIVE", + "ROBOT_ACTION_GETPOSITION": "ROBOT/ACTION/GETPOSITION", + "ROBOT_ACTION_GETBATTERY": "ROBOT/ACTION/GETBATTERY", + + "ROBOT_DATA_SENSORDATA": "ROBOT/DATA/SENSORDATA", + "ROBOT_DATA_BATTERY": "ROBOT/DATA/BATTERY", + "ROBOT_DATA_POSITION": "ROBOT/DATA/POSITION", + "ROBOT_DATA_PICTURE": "ROBOT/DATA/PICTURE", + + "BACKEND_ACTION_DRIVE": "BACKEND/ACTION/DRIVE", + "BACKEND_ACTION_GETPOSITION": "BACKEND/ACTION/GETPOSITION", + "BACKEND_ACTION_GETBATTERY": "BACKEND/ACTION/GETBATTERY", + "BACKEND_ACTION_GETALLDATA": "BACKEND/ACTION/GETALLDATA", + + "BACKEND_DATA_SENSORDATA": "BACKEND/DATA/SENSORDATA", + "BACKEND_DATA_SENSORDATAALL": "BACKEND/DATA/SENSORDATA_ALL", + "BACKEND_DATA_POSITION": "BACKEND/DATA/POSITION", + "BACKEND_DATA_BATTERY": "BACKEND/DATA/BATTERY", + "BACKEND_DATA_PICTURE": "BACKEND/DATA/PICTURE" + +} + + +# MQTT Messages: + +# region Robot -> Backend +SENSORDATA = { + "AirTemperature": 0.0, + "AirHumidity" : 0.0, + "SoilMoisture" : 0.0, + "Brightness" : 0, + "PlantID": 0, + "ActionID": 0 +} + +# TODO When sensor is available +POSITION = { + "Position": "" +} + +BATTERY = { + "Battery": 0.0 +} + +# endregion + +# region Backend -> Robot + +DRIVE = { + "PlantID": 0, + "ActionID": 0 +} + +# GETPOSITION -> no message needed + +# GETBATTERY -> no message needed + +# endregion + +# region Backend -> Frontend + +PLANTDATA = { + "AirTemperature": 0.0, + "AirHumidity" : 0.0, + "SoilMoisture" : 0.0, + "Brightness" : 0, + "PlantID": 0, + "Timestamp": "", + "MeasurementID": 0 +} + +ALLPLANTDATA = [ + PLANTDATA, + PLANTDATA, + PLANTDATA, + PLANTDATA, + PLANTDATA, + PLANTDATA +] + +# TODO When sensor is available +POSITION = { + "Position": "", + "Timestamp": "" +} + +BATTERY = { + "Battery": 0.0, + "Timestamp": "" +} + +# endregion + +# region Frontend -> Backend + +DRIVE = { + "PlantID": 0 +} + +# GETPOSITION -> no message needed + +# GETBATTERY -> no message needed + +# GETALLDATA -> no message needed + +# endregion \ No newline at end of file diff --git a/software/roboter/raspy/functions.py b/software/roboter/raspy/functions.py new file mode 100644 index 0000000..ce8275d --- /dev/null +++ b/software/roboter/raspy/functions.py @@ -0,0 +1,120 @@ +import paho.mqtt.client as mqtt +import json +import threading +import os +import raspy_sensors as RaspySensors +from defines import Topics + +def measure_send_data(plantID, actionID, client: mqtt.Client): + """ + Reads all sensors and publishes data via MQTT + + Args: + plantID (_type_): plant to measure + actionID (_type_): current ID of driving action + client (mqtt.Client): current mqtt client for publishing + """ + sensor = RaspySensors() + sensorData = sensor.readSensors() + sensorData["PlantID"] = plantID + sensorData["ActionID"] = actionID + client.publish(Topics["ROBOT_DATA_SENSORDATA"], json.dumps(sensorData, indent=4)) + + +def drive_plant_thread(plantID, actionID, client: mqtt.Client): + """ + Function to drive to plant according to number from MQTT message in thread + Meassure and publish data via MQTT + Drive home to starting point + + Args: + plantID (_type_): plant to measure + actionID (_type_): current ID of driving action + client (mqtt.Client): current mqtt client for publishing + """ + os.system(f'sshpass -p maker ssh robot@ev3dev.local python3 /home/robot/Programme/plant_{plantID}.py') + + print("Measuring Sensors") + + #FIXME Sensor not working + # measure_send_data(plantID, actionID, client) + + print("Robot driving home") + if plantID % 2 == 0: + leftRight = -50 #rotating left + else: + leftRight = 50 #rotating right + os.system(f'sshpass -p maker ssh robot@ev3dev.local python3 /home/robot/Programme/drive_back.py {leftRight}') + print("Robot home") + + #TODO decide about robot occupied message + #client.publish("ROBOT/DATA/OCCUPIED", "false") + + +#region MQTT callbacks + +#Testing +def send_data_json(clients: mqtt.Client, userdata, message: mqtt.MQTTMessage): + strIn = str(message.payload.decode("UTF-8")) + dataDict = json.loads(strIn) + print("Received data: ", json.dumps(dataDict)) + + +def drive_plant(clients: mqtt.Client, userdata, message: mqtt.MQTTMessage): + """ + Function to drive to plant according to request + Starting Drive in Thread + + Args: + clients (mqtt.Client): current mqtt client + userdata (_type_): _description_ + message (mqtt.MQTTMessage): received message + """ + dictMessage = json.loads(str(message.payload.decode("UTF-8"))) + plantID = dictMessage["PlantID"] + actionID = dictMessage["ActionID"] + + print(f"received drive to plant {plantID}") + + thread = threading.Thread(target= drive_plant_thread, args=(plantID, actionID, clients), daemon=True) + thread.start() + + +def get_position(clients: mqtt.Client, userdata, message: mqtt.MQTTMessage): + """ + Callback function for GPS position request + Function to send actual GPS position via MQTT + + Args: + clients (mqtt.Client): current mqtt client + userdata (_type_): _description_ + message (mqtt.MQTTMessage): received message + """ + # TODO Write GPS Sensor Function + position = { + "Position": "" + } + + clients.publish(Topics["ROBOT_DATA_POSITION"], json.dumps(position, indent=4)) + + +def get_BatteryStatus(clients: mqtt.Client, userdata, message: mqtt.MQTTMessage): + """ + Callback function for battery status request + Function to read battery status from ev3 and send via MQTT + + Args: + clients (mqtt.Client): current mqtt client + userdata (_type_): _description_ + message (mqtt.MQTTMessage): received message + """ + + battery = { + "Battery": 0.0 + } + + #TODO read Battery + clients.publish(Topics["ROBOT_DATA_BATTERY"], json.dumps(battery, indent=4)) + + +#endregion \ No newline at end of file diff --git a/software/roboter/raspy/mainProg.py b/software/roboter/raspy/mainProg.py index 321f295..1bdbf75 100644 --- a/software/roboter/raspy/mainProg.py +++ b/software/roboter/raspy/mainProg.py @@ -9,71 +9,10 @@ Interaction with the EV3 via SSH """ import paho.mqtt.client as mqtt -import json -import threading -import os -import time +import functions from raspy_sensors import RaspySensors +from defines import Topics, RASPI_CLIENT_ID, MQTT_BROKER_GLOBAL -from software.defines import Topics, RASPI_CLIENT_ID, MQTT_BROKER_GLOBAL - - - -#region global Varaibles - -# FIXME Sensor not working -#sensors: RaspySensors - - -#endregion - -#region global functions - -# TODO auslagern -def measure_send_data(plantID, actionID, client: mqtt.Client): - """ - Reads all sensors and publishes data via MQTT - - Args: - plantID (_type_): plant to measure - actionID (_type_): current ID of driving action - client (mqtt.Client): current mqtt client for publishing - """ - sensorData = sensors.readSensors() - sensorData["PlantID"] = plantID - sensorData["ActionID"] = actionID - client.publish(Topics["ROBOT_DATA_SENSORDATA"], json.dumps(sensorData, indent=4)) - -# TODO auslagern -def drive_plant_thread(plantID, actionID, client: mqtt.Client): - """ - Function to drive to plant according to number from MQTT message in thread - Meassure and publish data via MQTT - Drive home to starting point - - Args: - plantID (_type_): plant to measure - actionID (_type_): current ID of driving action - client (mqtt.Client): current mqtt client for publishing - """ - os.system(f'sshpass -p maker ssh robot@ev3dev.local python3 /home/robot/Programme/plant_{plantID}.py') - #CHECK if working properly - - print("Measuring Sensors") - - #FIXME Sensor not working - # measure_send_data(plantID, actionID, client) - - print("Robot driving home") - if plantID % 2 == 0: - leftRight = -50 #rotating left - else: - leftRight = 50 #rotating right - os.system(f'sshpass -p maker ssh robot@ev3dev.local python3 /home/robot/Programme/drive_back.py {leftRight}') - print("Robot home") - - #TODO decide about robot occupied message - #client.publish("ROBOT/DATA/OCCUPIED", "false") def on_connect(client: mqtt.Client, userdata, flags, rc): """ @@ -88,10 +27,10 @@ def on_connect(client: mqtt.Client, userdata, flags, rc): """ if rc == 0: #Add callbacks - client.message_callback_add("ROBOT/DATA", send_data_json) #Testing - client.message_callback_add(Topics["ROBOT_ACTION_DRIVE"], drive_plant) - client.message_callback_add(Topics["ROBOT_ACTION_GETPOSITION"], get_position) - client.message_callback_add(Topics["ROBOT_ACTION_GETBATTERY"], get_BatteryStatus) + client.message_callback_add("ROBOT/DATA", functions.send_data_json) #Testing + client.message_callback_add(Topics["ROBOT_ACTION_DRIVE"], functions.drive_plant) + client.message_callback_add(Topics["ROBOT_ACTION_GETPOSITION"], functions.get_position) + client.message_callback_add(Topics["ROBOT_ACTION_GETBATTERY"], functions.get_BatteryStatus) #Subscribe to topics client.subscribe("ROBOT/DATA") #Testing @@ -102,89 +41,12 @@ def on_connect(client: mqtt.Client, userdata, flags, rc): print("MQTT initialized") -#endregion - -# TODO auslagern -#region MQTT callbacks - -#Testing -def send_data_json(clients: mqtt.Client, userdata, message: mqtt.MQTTMessage): - strIn = str(message.payload.decode("UTF-8")) - dataDict = json.loads(strIn) - print("Received data: ", json.dumps(dataDict)) - - -# CHECK if working properly -def drive_plant(clients: mqtt.Client, userdata, message: mqtt.MQTTMessage): - """ - Function to drive to plant according to request - Starting Drive in Thread - - Args: - clients (mqtt.Client): current mqtt client - userdata (_type_): _description_ - message (mqtt.MQTTMessage): received message - """ - dictMessage = json.loads(str(message.payload.decode("UTF-8"))) - plantID = dictMessage["PlantID"] - actionID = dictMessage["ActionID"] - - print(f"received drive to plant {plantID}") - - thread = threading.Thread(target= drive_plant_thread, args=(plantID, actionID, clients), daemon=True) - thread.start() - - -def get_position(clients: mqtt.Client, userdata, message: mqtt.MQTTMessage): - """ - Callback function for GPS position request - Function to send actual GPS position via MQTT - - Args: - clients (mqtt.Client): current mqtt client - userdata (_type_): _description_ - message (mqtt.MQTTMessage): received message - """ - # TODO Write Sensor Function - position = { - "Position": "" - } - - clients.publish(Topics["ROBOT_DATA_POSITION"], json.dumps(position, indent=4)) - - -def get_BatteryStatus(clients: mqtt.Client, userdata, message: mqtt.MQTTMessage): - """ - Callback function for battery status request - Function to read battery status from ev3 and send via MQTT - - Args: - clients (mqtt.Client): current mqtt client - userdata (_type_): _description_ - message (mqtt.MQTTMessage): received message - """ - - battery = { - "Battery": 0.0 - } - - #TODO read Battery - clients.publish(Topics["ROBOT_DATA_BATTERY"], json.dumps(battery, indent=4)) - - -#endregion - - def main(): """ Initialises MQTT and Sensors Runs forever and controlls all robot functions """ - # CHECK if global - # FIXME Sensor not working - # global sensors - # sensors = RaspySensors() client = mqtt.Client(RASPI_CLIENT_ID) client.on_connect = on_connect client.connect(MQTT_BROKER_GLOBAL) diff --git a/software/roboter/raspy/raspy_sensors.py b/software/roboter/raspy/raspy_sensors.py index 04ef62b..76103e7 100644 --- a/software/roboter/raspy/raspy_sensors.py +++ b/software/roboter/raspy/raspy_sensors.py @@ -57,6 +57,8 @@ class RaspySensors: #read TSL2561 self.sensorData["Brightness"] = round(self.tsl2561.lux, 2) + #TODO SoilMoisture Sensor + return self.sensorData #TODO - take picture function