diff --git a/.idea/deployment.xml b/.idea/deployment.xml
new file mode 100644
index 0000000..efacd62
--- /dev/null
+++ b/.idea/deployment.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/sshConfigs.xml b/.idea/sshConfigs.xml
new file mode 100644
index 0000000..4a6426e
--- /dev/null
+++ b/.idea/sshConfigs.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/webServers.xml b/.idea/webServers.xml
new file mode 100644
index 0000000..51d8c58
--- /dev/null
+++ b/.idea/webServers.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index c983847..04e64e1 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -29,4 +29,4 @@ urllib3==1.26.14
Werkzeug==2.2.3
zipp==3.15.0
python-ev3dev2==2.1.0.post1
-pytest
\ No newline at end of file
+pytest==7.3.1
\ No newline at end of file
diff --git a/software/backend/backend_database.db b/software/backend/backend_database.db
index f8ce5be..ac54c93 100644
Binary files a/software/backend/backend_database.db and b/software/backend/backend_database.db differ
diff --git a/software/backend/data_functions.py b/software/backend/data_functions.py
index d7d28f1..69bc018 100644
--- a/software/backend/data_functions.py
+++ b/software/backend/data_functions.py
@@ -10,73 +10,103 @@ from software.defines import Topics, MAX_PLANT_COUNT
import json
import uuid
from typing import Union
+from datetime import datetime
+import logging
+from robot import Robot
# Robot Channel Reactions
def data_sensordata(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase,
- order_handler: list):
- print("message received")
- # TODO: Store data in database
+ robot: Robot):
str_in = str(message.payload.decode("UTF-8"))
payload = json.loads(str_in)
- print("Received data: ", json.dumps(payload))
+ logging.info("ROBOT_DATA_SENSORDATA Received data: " + json.dumps(payload))
+ drive_data = {
+ "PlantID": payload['PlantID'],
+ "ActionID": payload['ActionID']
+ }
- order_handler.remove(payload['ActionID'])
+ try:
+ robot.delete_order(drive_data)
+ except Exception as e:
+ logging.error("Could not delete order: " + str(e))
mydatabase.insert_measurement_data(plant_id=payload['PlantID'],
sensordata_temp=payload['AirTemperature'],
sensordata_humidity=payload['AirHumidity'],
sensordata_soil_moisture=payload['SoilMoisture'],
sensordata_brightness=payload['Brightness'])
+ logging.debug("Inserted to data base: " + json.dumps(payload))
-def data_position(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase):
- # TODO: Forward to frontend in json format
- client.publish(Topics['BACKEND_DATA_POSITION'], message.payload.decode("utf-8"))
+def data_position(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, robot: Robot):
+ logging.info("ROBOT_DATA_POSITION Received data: " + json.dumps(message.payload.decode("UTF-8")))
+ robot.store_position(json.loads(message.payload.decode("UTF-8"))["Position"])
+ position_data = {
+ "Position": robot.get_position(),
+ "Timestamp": str(datetime.now())
+ }
+ client.publish(Topics['BACKEND_DATA_POSITION'], json.dumps(position_data))
-def data_battery(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase):
- # TODO: Forward to frontend in json format
- client.publish(Topics['BACKEND_DATA_BATTERY'], message.payload.decode("utf-8"))
+def data_battery(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, robot: Robot):
+ logging.info("ROBOT_DATA_BATTERY Received data: " + json.dumps(message.payload.decode("UTF-8")))
+ robot.store_battery(json.loads(message.payload.decode("UTF-8"))["Battery"])
+ battery_data = {
+ "Battery": robot.get_battery(),
+ "Timestamp": str(datetime.now())
+ }
+ client.publish(Topics['BACKEND_DATA_BATTERY'], json.dumps(battery_data))
# FrontEnd Channel Reactions
def action_drive(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase,
- order_handler: list):
- # TODO: ROBOT READY CHECK
- if len(order_handler) < 5:
- order_handler.append(uuid.uuid4())
+ robot: Robot):
+ plant_id = mydatabase.get_plant_id(plant_name=json.loads(message.payload.decode("UTF-8"))["PlantName"])
+ action_id = str(uuid.uuid4())
+ drive_data = {
+ "PlantID": plant_id,
+ "ActionID": action_id
+ }
+
+ if robot.get_order_number() < 5 and robot.get_robot_status() is True:
+ robot.add_order(drive_data)
+ client.publish(Topics['ROBOT_ACTION_DRIVE'], json.dumps(drive_data))
+ logging.info("BACKEND_ACTION_DRIVE Drive Command published: " + json.dumps(drive_data))
else:
- # TODO: What to do when no place in order_list left
- pass
- client.publish(Topics['ROBOT_ACTION_DRIVE'], message.payload.decode("utf-8"))
+ if robot.get_order_number() < 5:
+ robot.add_order(drive_data)
+ logging.info("BACKEND_ACTION_DRIVE New data added to order list: " + str(drive_data))
+ elif robot.get_order_number() >= 5:
+ logging.error("Could not add Order to list. Order discarded")
+ client.publish(Topics['BACKEND_DATA_ERROR'], "Could not add Order to list. Order discarded")
-def action_driveall(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase):
+def action_driveall(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase,
+ robot: Robot):
# TODO: Implement here
- pass
+ print("HELLO")
def action_getposition(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase):
client.publish(Topics['ROBOT_ACTION_GETPOSITION'])
+ logging.info("BACKEND_ACTION_GETPOSITION message forwarded to Robot")
-def action_getbattery(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase):
+def action_getbattery(client: mqtt.Client, userdata, message: mqtt.MQTTMessage):
client.publish(Topics['ROBOT_ACTION_GETBATTERY'])
+ logging.info("BACKEND_ACTION_GETBATTERY message forwarded to Robot")
def action_getalldata(client: mqtt.Client, userdata, message: Union[mqtt.MQTTMessage, list], mydatabase: PlantDataBase):
plant_names = mydatabase.get_plant_names()
- print(type(plant_names))
alldata = []
for i in plant_names:
- print("I Type: " + str(type(i)))
- print("I: " + i[0])
alldata.append(mydatabase.get_latest_data(plant_name=i[0]))
client.publish(Topics['BACKEND_DATA_SENSORDATAALL'], json.dumps(alldata))
- print("BACKEND_DATA_SENSORDATAALL SEND DATA:" + str(alldata))
+ logging.info("BACKEND_DATA_SENSORDATAALL got data from database:" + str(alldata))
def action_newplant(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase):
@@ -87,8 +117,7 @@ def action_newplant(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, my
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))
- print(mydatabase.get_plant_names())
+ logging.info("BACKEND_ACTION_NEWPLANT new plant data received and inserted: " + str(plant_data))
action_getalldata(client, userdata, message, mydatabase)
@@ -100,14 +129,14 @@ def action_configureplant(client: mqtt.Client, userdata, message: mqtt.MQTTMessa
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))
+ logging.info("BACKEND_ACTION_CONFIGUREPLANT configure plant data received and inserted: " + str(plant_data))
action_getalldata(client, userdata, message, mydatabase)
def action_deleteplant(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, mydatabase: PlantDataBase):
delete_plant = json.loads(message.payload.decode("UTF-8"))
mydatabase.delete_plant(plant_id=delete_plant)
- print("BACKEND_ACTION_DELETEPLANT RECEIVED DATA: " + str(delete_plant))
+ logging.info("BACKEND_ACTION_DELETEPLANT delete plant data received and deleted: " + str(delete_plant))
action_getalldata(client, userdata, message, mydatabase)
@@ -118,4 +147,20 @@ def action_countplants(client: mqtt.Client, userdata, message: mqtt.MQTTMessage,
"MaxCount": MAX_PLANT_COUNT
}
client.publish(Topics["BACKEND_DATA_PLANTCOUNT"], json.dumps(count_payload))
- print("BACKEND_DATA_PLANTCOUNT SEND DATA: " + str(count_payload))
+ logging.info("BACKEND_DATA_PLANTCOUNT forwarded plant count to FrontEnd: " + str(count_payload))
+
+
+def data_error(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, robot: Robot):
+ robot.store_last_error(message.payload.decode("UTF-8"))
+ logging.error("ROBOT_DATA_ERROR new error received from Robot: " + robot.get_last_error())
+ client.publish(Topics['BACKEND_DATA_ERROR'], message.payload.decode("UTF-8"))
+
+
+def data_robotready(client: mqtt.Client, userdata, message: mqtt.MQTTMessage, robot: Robot):
+ robot.change_robot_status(message.payload.decode("UTF-8") == 'True')
+ if robot.get_robot_status() is True and robot.get_order_number() >= 1:
+ client.publish(Topics['ROBOT_ACTION_DRIVE'], json.dumps(robot.get_next_order()))
+ logging.info("Waiting Order send to Robot")
+
+ logging.info("ROBOT_DATA_ROBOTREADY status updated: " + str(robot.get_robot_status()))
+ client.publish(Topics['BACKEND_DATA_ROBOTREADY'], message.payload.decode("UTF-8"))
diff --git a/software/backend/dev_test_examples/mqtt_publisher.py b/software/backend/dev_test_examples/mqtt_publisher.py
index 2e3d51c..c2d1091 100644
--- a/software/backend/dev_test_examples/mqtt_publisher.py
+++ b/software/backend/dev_test_examples/mqtt_publisher.py
@@ -1,10 +1,12 @@
import paho.mqtt.client as mqtt
+
+import software.defines
from software.defines import MQTT_BROKER_LOCAL
from random import randrange, uniform
import time
import json
from software.defines import Topics, PLANTDATA
-mqttBroker = "192.168.178.182"
+mqttBroker = software.defines.MQTT_BROKER_GLOBAL
def on_connect(client, userdata, flags, rc):
@@ -20,17 +22,10 @@ client.on_connect = on_connect
client.connect(mqttBroker)
plantdata = {
- "AirTemperature": 20.4,
- "AirHumidity": 7.0,
- "SoilMoisture": 5.0,
- "Brightness": 39,
- "PlantID": 2,
- "Timestamp": "hallo",
- "MeasurementID": 187
+ "PlantName": "Kemal"
}
print(type(PLANTDATA))
-while True:
- client.publish("TEST", json.dumps(plantdata))
- print(json.dumps(plantdata))
- time.sleep(2)
+client.publish("BACKEND/ACTION/GETBATTERY", json.dumps(plantdata))
+print(json.dumps(plantdata))
+time.sleep(2)
diff --git a/software/backend/main.py b/software/backend/main.py
index 8aae264..6a89c44 100644
--- a/software/backend/main.py
+++ b/software/backend/main.py
@@ -12,17 +12,17 @@ import paho.mqtt.client as mqtt
from software.defines import MQTT_BROKER_LOCAL, MQTT_BROKER_GLOBAL, Topics, BACKEND_CLIENT_ID, DATABASE_NAME
from plantdatabase import PlantDataBase
import data_functions
-
-# inits
-mydatabase = PlantDataBase(database_name=DATABASE_NAME)
-mydatabase.create_tables()
-order_handler = [] # will contain UUIDS with Order IDs
+import logging
+import sys
+from robot import Robot
-def on_connect(_client: mqtt.Client, _userdata, _flags, _rc):
+def on_connect(_client: mqtt.Client, _userdata, _flags, _rc, _mydatabase, _robot):
"""
This method gets called, when it connects to a mqtt broker.
It is used to subscribe to the specific topics
+ :param _robot:
+ :param _mydatabase:
:param _client: mqtt client object
:param _userdata:
:param _flags:
@@ -37,25 +37,25 @@ def on_connect(_client: mqtt.Client, _userdata, _flags, _rc):
# From Robot:
_client.subscribe(Topics['ROBOT_DATA_SENSORDATA'])
_client.message_callback_add(Topics['ROBOT_DATA_SENSORDATA'], lambda client, userdata, message: data_functions.
- data_sensordata(client, userdata, message, mydatabase, order_handler))
+ data_sensordata(client, userdata, message, _mydatabase, _robot))
_client.subscribe(Topics['ROBOT_DATA_POSITION'])
_client.message_callback_add(Topics['ROBOT_DATA_POSITION'], data_functions.data_position)
_client.subscribe(Topics['ROBOT_DATA_BATTERY'])
_client.message_callback_add(Topics['ROBOT_DATA_BATTERY'], lambda client, userdata, message: data_functions.
- data_battery(client, userdata, message, mydatabase))
+ data_battery(client, userdata, message))
# client.subscribe('Robot/Data/Picture')
# From FrontEnd:
_client.subscribe(Topics['BACKEND_ACTION_DRIVE'])
_client.message_callback_add(Topics['BACKEND_ACTION_DRIVE'], lambda client, userdata, message: data_functions.
- action_drive(client, userdata, message, mydatabase, order_handler))
+ action_drive(client, userdata, message, _mydatabase, _robot))
_client.subscribe(Topics['BACKEND_ACTION_DRIVEALL'])
- _client.message_callback_add(Topics['BACKEND_ACTION_DRIVE'], lambda client, userdata, message: data_functions.
- action_driveall(client, userdata, message, mydatabase))
+ _client.message_callback_add(Topics['BACKEND_ACTION_DRIVEALL'], lambda client, userdata, message: data_functions.
+ action_driveall(client, userdata, message, _mydatabase, _robot))
_client.subscribe(Topics['BACKEND_ACTION_GETPOSITION'])
_client.message_callback_add(Topics['BACKEND_ACTION_GETPOSITION'], data_functions.action_getposition)
@@ -66,35 +66,54 @@ def on_connect(_client: mqtt.Client, _userdata, _flags, _rc):
_client.subscribe(Topics['BACKEND_ACTION_GETALLDATA'])
_client.message_callback_add(Topics['BACKEND_ACTION_GETALLDATA'],
lambda client, userdata, message: data_functions.
- action_getalldata(client, userdata, message, mydatabase))
+ action_getalldata(client, userdata, message, _mydatabase))
_client.subscribe(Topics['BACKEND_ACTION_NEWPLANT'])
_client.message_callback_add(Topics['BACKEND_ACTION_NEWPLANT'], lambda client, userdata, message: data_functions.
- action_newplant(client, userdata, message, mydatabase))
+ action_newplant(client, userdata, message, _mydatabase))
_client.subscribe(Topics['BACKEND_ACTION_CONFIGUREPLANT'])
_client.message_callback_add(Topics['BACKEND_ACTION_CONFIGUREPLANT'], lambda client, userdata, message: data_functions.
- action_configureplant(client, userdata, message, mydatabase))
+ action_configureplant(client, userdata, message, _mydatabase))
_client.subscribe(Topics['BACKEND_ACTION_DELETEPLANT'])
_client.message_callback_add(Topics['BACKEND_ACTION_DELETEPLANT'],
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))
+ action_countplants(client, userdata, message, _mydatabase))
+ _client.subscribe(Topics['ROBOT_DATA_ERROR'])
+ _client.message_callback_add(Topics['ROBOT_DATA_ERROR'], lambda client, userdata, message: data_functions.
+ data_error(client, userdata, message, _robot))
+
+ _client.subscribe(Topics['ROBOT_DATA_ROBOTREADY'])
+ _client.message_callback_add(Topics['ROBOT_DATA_ROBOTREADY'], lambda client, userdata, message: data_functions.
+ data_robotready(client, userdata, message, _robot))
# END TOPIC SUBSCRIPTIONS
else:
print("connection failed")
def main():
- client = mqtt.Client(BACKEND_CLIENT_ID)
- client.on_connect = on_connect
- client.connect(MQTT_BROKER_GLOBAL)
- client.loop_forever()
+ robot = Robot()
+ my_database = PlantDataBase(database_name=DATABASE_NAME)
+ my_database.create_tables()
+ mqttclient = mqtt.Client(BACKEND_CLIENT_ID)
+ mqttclient.on_connect = lambda client, userdata, flags, rc: on_connect(_client=client,
+ _userdata=userdata,
+ _flags=flags,
+ _rc=rc,
+ _mydatabase=my_database,
+ _robot=robot)
+ mqttclient.connect(MQTT_BROKER_GLOBAL)
+ logging.basicConfig(filename="server.log", filemode="a", encoding="utf-8", level=logging.DEBUG,
+ format='%(asctime)s %(name)s %(levelname)s %(message)s',
+ datefmt="%d-%m-%Y %H:%M:%S")
+ logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))
+ mqttclient.loop_forever()
if __name__ == "__main__":
diff --git a/software/backend/plantdatabase.py b/software/backend/plantdatabase.py
index a2de15d..fb89f77 100644
--- a/software/backend/plantdatabase.py
+++ b/software/backend/plantdatabase.py
@@ -1,6 +1,7 @@
# file to create a database via python script
import sqlite3
from typing import Optional
+import logging
class PlantDataBase:
@@ -13,9 +14,8 @@ class PlantDataBase:
self.conn = None
try:
self.conn = sqlite3.connect(self.db_file, check_same_thread=False)
- print(sqlite3.version)
except sqlite3.Error as e:
- print(e)
+ logging.error("Database init error: " + str(e))
self.cur = self.conn.cursor()
def create_tables(self):
@@ -38,32 +38,36 @@ class PlantDataBase:
self.cur.execute(table_config)
return True
except sqlite3.Warning as e:
- return e
+ logging.error("Could not create tables: " + str(e))
+ return False
- def insert_plant(self, plantname: str, plant_id: int):
+ def insert_plant(self, plantname: str, plant_id: int) -> bool:
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
+ except Exception as e:
+ logging.error("Could not insert plant: " + str(e))
+ return False
- def configure_plant(self, plant_id: int, plantname: str):
+ def configure_plant(self, plant_id: int, plantname: str) -> bool:
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
+ except Exception as e:
+ logging.error("Could not configure plant: " + str(e))
+ return False
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
+ except Exception as e:
+ logging.error("Could not delete plant: " + str(e))
+ return False
def insert_measurement_data(self, plant_id,
sensordata_temp,
@@ -72,13 +76,14 @@ class PlantDataBase:
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})")
+ 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
+ except Exception as e:
+ logging.error("Could not insert measurement data: " + str(e))
+ return False
def get_latest_data(self, plant_name: Optional[str] = None, plant_id: Optional[int] = None):
"""
@@ -108,27 +113,42 @@ class PlantDataBase:
"PlantName": plant_name
}
return json_file
- except (sqlite3.Warning, TypeError) as e:
- return e
+
+ except Exception as e:
+ logging.error("Could not get measurement values: " + str(e))
def delete_data(self, table_name):
- self.cur.execute(f'DELETE FROM {table_name}')
- self.conn.commit()
- return True
-
- # TODO: Kemals Scheiß implementieren
+ try:
+ self.cur.execute(f'DELETE FROM {table_name}')
+ self.conn.commit()
+ return True
+ except Exception as e:
+ logging.error("Could not delete data: " + str(e))
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]
+ try:
+ self.cur.execute("SELECT COUNT(*) FROM plants")
+ return self.cur.fetchone()[0]
+ except Exception as e:
+ logging.error("Could not count plants: " + str(e))
def get_plant_names(self) -> list:
- self.cur.execute("SELECT PlantName FROM plants")
- return self.cur.fetchall()
+ try:
+ self.cur.execute("SELECT PlantName FROM plants")
+ return self.cur.fetchall()
+ except Exception as e:
+ logging.error("Could not get plant names: " + str(e))
+
+ def get_plant_id(self, plant_name: str) -> int:
+ try:
+ self.cur.execute("SELECT PlantID FROM plants WHERE PlantName=?", (plant_name,))
+ return self.cur.fetchone()[0]
+ except Exception as e:
+ logging.error("Could not get plant id: " + str(e))
def __del__(self):
self.conn.close()
diff --git a/software/backend/robot.py b/software/backend/robot.py
new file mode 100644
index 0000000..96cb5e1
--- /dev/null
+++ b/software/backend/robot.py
@@ -0,0 +1,47 @@
+class Robot:
+ """
+ This class contains the features of the robot. It is used as an interface for the main to avoid global variables and
+ store them instead in an instance of this robot object
+ """
+ def __init__(self):
+ self.robot_ready = True
+ self.order_handler = []
+ self.battery = 0
+ self.position = ""
+ self.last_error = ""
+
+ def change_robot_status(self, status: bool):
+ self.robot_ready = status
+
+ def add_order(self, drivedata):
+ self.order_handler.append(drivedata)
+
+ def delete_order(self, drivedata):
+ self.order_handler.remove(drivedata)
+
+ def get_next_order(self):
+ return self.order_handler[0]
+
+ def get_order_number(self):
+ return len(self.order_handler)
+
+ def store_battery(self, battery):
+ self.battery = battery
+
+ def store_position(self, position):
+ self.position = position
+
+ def store_last_error(self, error):
+ self.last_error = error
+
+ def get_battery(self):
+ return self.battery
+
+ def get_position(self):
+ return self.position
+
+ def get_last_error(self):
+ return self.last_error
+
+ def get_robot_status(self):
+ return self.robot_ready
diff --git a/software/backend/tests/test_database.db b/software/backend/tests/test_database.db
index d38a441..a6d863c 100644
Binary files a/software/backend/tests/test_database.db and b/software/backend/tests/test_database.db differ
diff --git a/software/defines.py b/software/defines.py
index 9bc3e77..2f3786c 100644
--- a/software/defines.py
+++ b/software/defines.py
@@ -21,6 +21,8 @@ Topics = {
"ROBOT_DATA_BATTERY": "ROBOT/DATA/BATTERY",
"ROBOT_DATA_POSITION": "ROBOT/DATA/POSITION",
"ROBOT_DATA_PICTURE": "ROBOT/DATA/PICTURE",
+ "ROBOT_DATA_ERROR": "ROBOT/DATA/ERROR",
+ "ROBOT_DATA_ROBOTREADY": "ROBOT/DATA/ROBOTREADY",
"BACKEND_ACTION_DRIVE": "BACKEND/ACTION/DRIVE",
"BACKEND_ACTION_DRIVEALL": "BACKEND/ACTION/DRIVEALL",
@@ -38,7 +40,8 @@ Topics = {
"BACKEND_DATA_BATTERY": "BACKEND/DATA/BATTERY",
"BACKEND_DATA_PICTURE": "BACKEND/DATA/PICTURE",
"BACKEND_DATA_PLANTCOUNT": "BACKEND/DATA/PLANTCOUNT",
-
+ "BACKEND_DATA_ERROR": "BACKEND/DATA/ERROR",
+ "BACKEND_DATA_ROBOTREADY": "BACKEND/DATA/ROBOTREADY"
}