269 lines
9.5 KiB
Python
Raw Normal View History

import paho.mqtt.client as mqtt
import json
import threading
import os
2023-05-12 13:56:56 +02:00
import logging
2023-04-30 12:12:11 +02:00
import raspy_sensors as Sensors
2023-05-23 18:08:41 +02:00
from defines import Topics, SENSORDATA, ALLSENSORDATA
2023-05-24 15:27:14 +02:00
import time
def measure_send_data(plantID, actionID, client: mqtt.Client):
"""
2023-05-10 15:58:27 +02:00
Reads all sensors and publishes data via MQTT in form of SENSORDATA
Args:
plantID (_type_): plant to measure
actionID (_type_): current ID of driving action
client (mqtt.Client): current mqtt client for publishing
"""
sensorData = {}
sensorData |= SENSORDATA
2023-05-07 12:32:50 +02:00
try:
Sensors.readSensors(sensorData)
except Exception as e:
2023-05-12 16:51:31 +02:00
logging.error(str(e))
client.publish(Topics["ROBOT_DATA_ERROR"], str(e), qos=1)
sensorData["PlantID"] = plantID
sensorData["ActionID"] = actionID
2023-05-12 16:51:31 +02:00
client.publish(Topics["ROBOT_DATA_SENSORDATA"], json.dumps(sensorData, indent=4), qos=1)
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
"""
# FIXME Change to color code driving
2023-05-10 15:58:27 +02:00
errorCode = os.system(f'sshpass -p maker ssh robot@ev3dev.local python3 /home/robot/Programme/plant_{plantID}.py')
# errorCode = os.system(f'sshpass -p maker ssh robot@ev3dev.local python3 /home/robot/Programme/drive_plant.py {plantID}')
2023-05-10 15:58:27 +02:00
if errorCode != 0:
2023-05-12 13:56:56 +02:00
logging.error(f"Robot Error {errorCode} occurred")
2023-05-12 16:51:31 +02:00
logging.info("Drive Plant aborted, Robot at starting position")
client.publish(Topics["ROBOT_DATA_ERROR"], "Drive Plant aborted, Robot at starting position", qos=1)
client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1)
2023-05-10 15:58:27 +02:00
return
2023-05-12 13:56:56 +02:00
logging.info("Measuring Sensors")
measure_send_data(plantID, actionID, client)
2023-05-17 21:35:58 +02:00
# TODO How to Handle Pictures and PlantID
2023-05-14 10:44:33 +02:00
logging.info("Taking Picture")
sendPicture(client)
2023-05-13 15:19:27 +02:00
2023-05-12 13:56:56 +02:00
logging.info("Robot driving home")
errorCode = os.system(f'sshpass -p maker ssh robot@ev3dev.local python3 /home/robot/Programme/drive_back.py {plantID}')
if errorCode != 0:
2023-05-12 13:56:56 +02:00
logging.error(f"Robot Error {errorCode} occurred")
2023-05-12 16:51:31 +02:00
logging.info(f"Drive Home aborted, Robot at plant {plantID}")
client.publish(Topics["ROBOT_DATA_ERROR"], f"Drive Home aborted, Robot at plant {plantID}", qos=1)
client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1)
return
2023-05-12 13:56:56 +02:00
logging.info("Robot home")
2023-05-15 11:18:48 +02:00
client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1)
2023-05-23 18:08:41 +02:00
def drive_plant_all_thread(plantIDs: list, actionID, client: mqtt.Client):
2023-05-17 21:35:58 +02:00
"""
Function to drive to plants according to numbers from MQTT message in thread
Meassure and publish data for all plants via MQTT
Drive home to starting point
Args:
plantIDs (list): Plants to drive to
actionID (_type_): ActionID from Backend for whole drive action
client (mqtt.Client): current MQTT client
"""
2023-05-24 15:27:14 +02:00
allPlantData = {
"SensorData": [],
"ActionID": ""
}
2023-05-17 21:35:58 +02:00
allPlantData["ActionID"] = actionID
2023-05-15 11:18:48 +02:00
2023-05-17 21:35:58 +02:00
for plant in plantIDs:
2023-05-24 15:27:14 +02:00
# FIXME Only possible with color codes
2023-05-23 18:08:41 +02:00
logging.info(f"Robot Driving to plant {plant}")
2023-05-17 21:35:58 +02:00
errorCode = os.system(f'sshpass -p maker ssh robot@ev3dev.local python3 /home/robot/Programme/drive_plant.py {plant}')
if errorCode != 0:
logging.error(f"Robot Error {errorCode} occurred")
logging.info("Drive Plant aborted, Robot at starting position")
client.publish(Topics["ROBOT_DATA_ERROR"], "Drive Plant aborted, Robot at starting position", qos=1)
client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1)
return
logging.info("Measuring Sensors")
try:
2023-05-24 15:27:14 +02:00
sensordata = {}
sensordata |= SENSORDATA
Sensors.readSensors(sensordata)
2023-05-17 21:35:58 +02:00
except Exception as e:
logging.error(str(e))
client.publish(Topics["ROBOT_DATA_ERROR"], str(e), qos=1)
2023-05-24 15:27:14 +02:00
sensordata["PlantID"] = plant
allPlantData["SensorData"].append(sensordata)
2023-05-17 21:35:58 +02:00
# TODO How to Handle Pictures and PlantID
logging.info("Taking Picture")
sendPicture(client)
errorCode = os.system(f'sshpass -p maker ssh robot@ev3dev.local python3 /home/robot/Programme/drive_arm.py {plant}')
if errorCode != 0:
logging.error(f"Robot Error {errorCode} occurred")
logging.info("Drive Plant aborted, Robot at starting position")
2023-05-23 18:08:41 +02:00
client.publish(Topics["ROBOT_DATA_ERROR"], f"Rotate arm aborted, Robot at plant {plant}", qos=1)
2023-05-17 21:35:58 +02:00
client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1)
return
logging.info("All Plants measured, sending data")
2023-05-23 18:08:41 +02:00
client.publish(Topics["ROBOT_DATA_ALL"], json.dumps(allPlantData, indent=4), qos=1)
2023-05-17 21:35:58 +02:00
2023-05-24 15:27:14 +02:00
2023-05-17 21:35:58 +02:00
logging.info("Robot driving home")
errorCode = os.system(f'sshpass -p maker ssh robot@ev3dev.local python3 /home/robot/Programme/drive_back_straight.py')
if errorCode != 0:
logging.error(f"Robot Error {errorCode} occurred")
logging.info(f"Drive Home aborted, Robot at plant {plant}")
client.publish(Topics["ROBOT_DATA_ERROR"], f"Drive Home aborted, Robot at plant {plant}", qos=1)
client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1)
return
2023-05-15 11:18:48 +02:00
logging.info("Robot home")
2023-05-12 16:51:31 +02:00
client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1)
#region MQTT callbacks
2023-05-12 16:51:31 +02:00
def drive_plant(client: mqtt.Client, userdata, message: mqtt.MQTTMessage):
"""
Function to drive to plant according to request
2023-05-10 15:58:27 +02:00
Starting Drive in Thread to not block main programm
Args:
2023-05-13 15:19:27 +02:00
client (mqtt.Client): current mqtt client
userdata (_type_): _description_
2023-05-10 15:58:27 +02:00
message (mqtt.MQTTMessage): received DRIVE message with PlantID and ActionID
"""
dictMessage = json.loads(str(message.payload.decode("UTF-8")))
2023-05-12 16:51:31 +02:00
plantID = dictMessage["PlantID"]
actionID = dictMessage["ActionID"]
2023-05-12 13:56:56 +02:00
logging.info(f"Received Drive-request to plant {plantID}, ActionID: {actionID}")
2023-05-12 16:51:31 +02:00
client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "False", qos=1)
2023-05-12 16:51:31 +02:00
thread = threading.Thread(target= drive_plant_thread, args=(plantID, actionID, client), daemon=True)
thread.start()
2023-05-17 21:35:58 +02:00
# FIXME Only possible with color codes
2023-05-15 11:18:48 +02:00
def drive_plant_all(client: mqtt.Client, userdata, message: mqtt.MQTTMessage):
2023-05-17 21:35:58 +02:00
"""
Function to drive to plants according to request
Starting Drive in Thread to not block main programm
Args:
client (mqtt.Client): current MQTT client
userdata (_type_): _description_
message (mqtt.MQTTMessage): received DRIVEALL message with PlantIDs and ActionID
"""
2023-05-15 11:18:48 +02:00
dictMessage = json.loads(str(message.payload.decode("UTF-8")))
2023-05-17 21:35:58 +02:00
plantIDs = dictMessage["PlantID"] # List of numbers
2023-05-15 11:18:48 +02:00
actionID = dictMessage["ActionID"]
2023-05-17 21:35:58 +02:00
logging.info(f"Received Drive-request to plants {plantIDs}, ActionID: {actionID}")
2023-05-15 11:18:48 +02:00
client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "False", qos=1)
2023-05-23 18:08:41 +02:00
thread = threading.Thread(target= drive_plant_all_thread, args=(plantIDs, actionID, client), daemon=True)
2023-05-15 11:18:48 +02:00
thread.start()
def get_position(clients: mqtt.Client, userdata, message: mqtt.MQTTMessage):
"""
Callback function for GPS position request
2023-05-10 15:58:27 +02:00
Function to send actual GPS position via MQTT in form of POSITION
Args:
2023-05-13 15:19:27 +02:00
client (mqtt.Client): current mqtt client
userdata (_type_): _description_
message (mqtt.MQTTMessage): received message
"""
2023-05-12 16:51:31 +02:00
logging.info("Received position request")
# TODO Write GPS Sensor Function
position = {
"Position": ""
}
2023-05-12 16:51:31 +02:00
clients.publish(Topics["ROBOT_DATA_POSITION"], json.dumps(position, indent=4), qos=1)
2023-05-31 14:22:17 +02:00
def get_batteryStatus(client: mqtt.Client, userdata, message: mqtt.MQTTMessage):
"""
Callback function for battery status request
2023-05-10 15:58:27 +02:00
Function to read battery status from ev3 and send via MQTT in form of BATTERY
2023-05-05 14:22:12 +02:00
8,5V -> 100%
5V -> 0%
Args:
2023-05-13 15:19:27 +02:00
client (mqtt.Client): current mqtt client
userdata (_type_): _description_
message (mqtt.MQTTMessage): received message
"""
2023-05-12 13:56:56 +02:00
logging.info("Received battery status request")
2023-05-05 14:22:12 +02:00
try:
batteryLevel = int(os.popen('sshpass -p maker ssh robot@ev3dev.local cat /sys/devices/platform/battery/power_supply/lego-ev3-battery/voltage_now').read())
except:
2023-05-12 13:56:56 +02:00
logging.error("Robot not connected")
2023-05-12 16:51:31 +02:00
client.publish(Topics["ROBOT_DATA_ERROR"], "Robot not connected", qos=1)
2023-05-05 14:22:12 +02:00
return
batteryLevel = round(batteryLevel / 1000000, 2) # Voltage
batteryLevel = batteryLevel - 5
2023-05-10 15:58:27 +02:00
batteryLevel = round(batteryLevel / 3.5, 3) *100 # Percentage
battery = {
2023-05-05 14:22:12 +02:00
"Battery": batteryLevel
}
2023-05-12 16:51:31 +02:00
client.publish(Topics["ROBOT_DATA_BATTERY"], json.dumps(battery, indent=4), qos=1)
2023-05-14 10:44:33 +02:00
logging.info(f"Battery done {batteryLevel}")
2023-05-13 15:19:27 +02:00
def sendPicture(client: mqtt.Client):
"""
Takes picture and publish via MQTT
Args:
client (mqtt.Client): current mqtt client
"""
try:
Sensors.takePicture()
except Exception as e:
logging.error(str(e))
client.publish(Topics["ROBOT_DATA_ERROR"], str(e), qos=1)
2023-05-14 10:44:33 +02:00
return
2023-05-13 15:19:27 +02:00
2023-05-14 10:44:33 +02:00
with open("picture.png", "rb") as f:
2023-05-13 15:19:27 +02:00
file = f.read()
byteArr = bytearray(file)
2023-05-14 10:44:33 +02:00
client.publish(Topics["ROBOT_DATA_PICTURE"], byteArr)
logging.info("Picture Published")
2023-05-13 15:19:27 +02:00
#endregion