repository to manage all files related to the makeathon farm bot project (Software + Documentation).
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

functions.py 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import paho.mqtt.client as mqtt
  2. import json
  3. import threading
  4. import os
  5. import logging
  6. import raspy_sensors as Sensors
  7. from defines import Topics, SENSORDATA
  8. def measure_send_data(plantID, actionID, client: mqtt.Client):
  9. """
  10. Reads all sensors and publishes data via MQTT in form of SENSORDATA
  11. Args:
  12. plantID (_type_): plant to measure
  13. actionID (_type_): current ID of driving action
  14. client (mqtt.Client): current mqtt client for publishing
  15. """
  16. sensorData = SENSORDATA
  17. try:
  18. sensorData = Sensors.readSensors()
  19. except Exception as e:
  20. logging.error(str(e))
  21. client.publish(Topics["ROBOT_DATA_ERROR"], str(e), qos=1)
  22. sensorData["PlantID"] = plantID
  23. sensorData["ActionID"] = actionID
  24. client.publish(Topics["ROBOT_DATA_SENSORDATA"], json.dumps(sensorData, indent=4), qos=1)
  25. def drive_plant_thread(plantID, actionID, client: mqtt.Client):
  26. """
  27. Function to drive to plant according to number from MQTT message in thread
  28. Meassure and publish data via MQTT
  29. Drive home to starting point
  30. Args:
  31. plantID (_type_): plant to measure
  32. actionID (_type_): current ID of driving action
  33. client (mqtt.Client): current mqtt client for publishing
  34. """
  35. # FIXME Change to color code driving
  36. errorCode = os.system(f'sshpass -p maker ssh robot@ev3dev.local python3 /home/robot/Programme/plant_{plantID}.py')
  37. # errorCode = os.system(f'sshpass -p maker ssh robot@ev3dev.local python3 /home/robot/Programme/drive_plant.py {plantID}')
  38. if errorCode != 0:
  39. logging.error(f"Robot Error {errorCode} occurred")
  40. logging.info("Drive Plant aborted, Robot at starting position")
  41. client.publish(Topics["ROBOT_DATA_ERROR"], "Drive Plant aborted, Robot at starting position", qos=1)
  42. client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1)
  43. return
  44. logging.info("Measuring Sensors")
  45. measure_send_data(plantID, actionID, client)
  46. logging.info("Taking Picture")
  47. sendPicture(client)
  48. logging.info("Robot driving home")
  49. errorCode = os.system(f'sshpass -p maker ssh robot@ev3dev.local python3 /home/robot/Programme/drive_back.py {plantID}')
  50. if errorCode != 0:
  51. logging.error(f"Robot Error {errorCode} occurred")
  52. logging.info(f"Drive Home aborted, Robot at plant {plantID}")
  53. client.publish(Topics["ROBOT_DATA_ERROR"], f"Drive Home aborted, Robot at plant {plantID}", qos=1)
  54. client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1)
  55. return
  56. logging.info("Robot home")
  57. client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1)
  58. # TODO thread all plants
  59. def drive_plant_all(plantID, actionID, client: mqtt.Client):
  60. # TODO loop through plantID array
  61. logging.info("Robot home")
  62. client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "True", qos=1)
  63. #region MQTT callbacks
  64. def drive_plant(client: mqtt.Client, userdata, message: mqtt.MQTTMessage):
  65. """
  66. Function to drive to plant according to request
  67. Starting Drive in Thread to not block main programm
  68. Args:
  69. client (mqtt.Client): current mqtt client
  70. userdata (_type_): _description_
  71. message (mqtt.MQTTMessage): received DRIVE message with PlantID and ActionID
  72. """
  73. dictMessage = json.loads(str(message.payload.decode("UTF-8")))
  74. plantID = dictMessage["PlantID"]
  75. actionID = dictMessage["ActionID"]
  76. logging.info(f"Received Drive-request to plant {plantID}, ActionID: {actionID}")
  77. client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "False", qos=1)
  78. thread = threading.Thread(target= drive_plant_thread, args=(plantID, actionID, client), daemon=True)
  79. thread.start()
  80. # TODO Drive all Plants
  81. # TODO plantID array
  82. # TODO only possible with color codes
  83. def drive_plant_all(client: mqtt.Client, userdata, message: mqtt.MQTTMessage):
  84. dictMessage = json.loads(str(message.payload.decode("UTF-8")))
  85. plantID = dictMessage["PlantID"]
  86. actionID = dictMessage["ActionID"]
  87. logging.info(f"Received Drive-request to plants {plantID}, ActionID: {actionID}")
  88. client.publish(Topics["ROBOT_DATA_ROBOTREADY"], "False", qos=1)
  89. thread = threading.Thread(target= drive_plant_all, args=(plantID, actionID, client), daemon=True)
  90. thread.start()
  91. def get_position(clients: mqtt.Client, userdata, message: mqtt.MQTTMessage):
  92. """
  93. Callback function for GPS position request
  94. Function to send actual GPS position via MQTT in form of POSITION
  95. Args:
  96. client (mqtt.Client): current mqtt client
  97. userdata (_type_): _description_
  98. message (mqtt.MQTTMessage): received message
  99. """
  100. logging.info("Received position request")
  101. # TODO Write GPS Sensor Function
  102. position = {
  103. "Position": ""
  104. }
  105. clients.publish(Topics["ROBOT_DATA_POSITION"], json.dumps(position, indent=4), qos=1)
  106. def get_BatteryStatus(client: mqtt.Client, userdata, message: mqtt.MQTTMessage):
  107. """
  108. Callback function for battery status request
  109. Function to read battery status from ev3 and send via MQTT in form of BATTERY
  110. 8,5V -> 100%
  111. 5V -> 0%
  112. Args:
  113. client (mqtt.Client): current mqtt client
  114. userdata (_type_): _description_
  115. message (mqtt.MQTTMessage): received message
  116. """
  117. logging.info("Received battery status request")
  118. try:
  119. batteryLevel = int(os.popen('sshpass -p maker ssh robot@ev3dev.local cat /sys/devices/platform/battery/power_supply/lego-ev3-battery/voltage_now').read())
  120. except:
  121. logging.error("Robot not connected")
  122. client.publish(Topics["ROBOT_DATA_ERROR"], "Robot not connected", qos=1)
  123. return
  124. batteryLevel = round(batteryLevel / 1000000, 2) # Voltage
  125. batteryLevel = batteryLevel - 5
  126. batteryLevel = round(batteryLevel / 3.5, 3) *100 # Percentage
  127. battery = {
  128. "Battery": batteryLevel
  129. }
  130. client.publish(Topics["ROBOT_DATA_BATTERY"], json.dumps(battery, indent=4), qos=1)
  131. logging.info(f"Battery done {batteryLevel}")
  132. def sendPicture(client: mqtt.Client):
  133. """
  134. Takes picture and publish via MQTT
  135. Args:
  136. client (mqtt.Client): current mqtt client
  137. """
  138. try:
  139. Sensors.takePicture()
  140. except Exception as e:
  141. logging.error(str(e))
  142. client.publish(Topics["ROBOT_DATA_ERROR"], str(e), qos=1)
  143. return
  144. with open("picture.png", "rb") as f:
  145. file = f.read()
  146. byteArr = bytearray(file)
  147. client.publish(Topics["ROBOT_DATA_PICTURE"], byteArr)
  148. logging.info("Picture Published")
  149. #endregion