mirror of
https://gitlab.fdmci.hva.nl/technische-informatica-sm3/ti-projectten/rooziinuubii79.git
synced 2025-08-05 12:54:57 +00:00
Compare commits
42 Commits
d0bfef2296
...
06dd2d9f48
Author | SHA1 | Date | |
---|---|---|---|
|
06dd2d9f48 | ||
|
7d3a5fa9a3 | ||
|
3bca04053a | ||
|
82363d393c | ||
|
1964589abc | ||
|
8d339851dd | ||
|
79c2073d29 | ||
|
ffbf3347f4 | ||
|
64452b78b4 | ||
|
c87ebc565c | ||
|
39659fffab | ||
|
a4ae0170a0 | ||
|
ed475cd19f | ||
|
a9c37ec470 | ||
|
369120b16b | ||
|
ec71028270 | ||
|
7560b0f67a | ||
|
331de940cc | ||
|
ec0b32a221 | ||
|
3aa77f5314 | ||
|
e59f235b91 | ||
|
2e4f048ed9 | ||
|
9a3829cdb2 | ||
|
015b2db819 | ||
|
6ef739f794 | ||
|
ec2a08c656 | ||
|
89421ccf34 | ||
|
1c081451aa | ||
|
2396d61eae | ||
|
fa17893b1b | ||
|
07d88eef7d | ||
|
d066f68ad2 | ||
|
d90ac72591 | ||
|
a2aa80804e | ||
|
612af45f59 | ||
|
3ff1b22346 | ||
|
1a4056ff77 | ||
|
8517a0d558 | ||
|
092e4f5aeb | ||
|
9eb9822cff | ||
|
fe64267307 | ||
|
72a0fadef8 |
51
docs/Infrastructure/uml.md
Normal file
51
docs/Infrastructure/uml.md
Normal file
@@ -0,0 +1,51 @@
|
||||
```mermaid
|
||||
classDiagram
|
||||
class CKobuki {
|
||||
+enableCommands(bool commands)
|
||||
+loop(void *user_data, TKobukiData &Kobuki_data)
|
||||
+startCommunication(char *portname, bool CommandsEnabled, void *userDataL)
|
||||
+measure()
|
||||
+setLed(int led1, int led2)
|
||||
+setTranslationSpeed(int mmpersec)
|
||||
+setRotationSpeed(double radpersec)
|
||||
+setArcSpeed(int mmpersec, int radius)
|
||||
+setSound(int noteinHz, int duration)
|
||||
+setPower(int value)
|
||||
+goStraight(long double distance)
|
||||
+forward(int speedvalue)
|
||||
+doRotation(long double th)
|
||||
}
|
||||
|
||||
class FlaskApp {
|
||||
+on_message(client, message)
|
||||
+get_db()
|
||||
+close_db(error)
|
||||
+index()
|
||||
+control()
|
||||
+move()
|
||||
}
|
||||
|
||||
class MQTTClient {
|
||||
+connect()
|
||||
+subscribe(topic)
|
||||
+getLastMessage()
|
||||
+isConnected()
|
||||
}
|
||||
|
||||
FlaskApp --> MQTTClient : uses
|
||||
FlaskApp --> CKobuki : controls
|
||||
|
||||
class RPI {
|
||||
+KobukiCommunication()
|
||||
+ESP32Communication()
|
||||
+Camera()
|
||||
}
|
||||
|
||||
class ESP32 {
|
||||
+TVOC()
|
||||
+DHT11()
|
||||
}
|
||||
|
||||
RPI --> MQTTClient : communicates
|
||||
MQTTClient --> CKobuki : communicates
|
||||
RPI --> ESP32 : communicates
|
@@ -68,28 +68,14 @@ int CKobuki::connect(char *comportT) {
|
||||
HCom = open(comportT, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||
|
||||
if (HCom == -1) {
|
||||
printf("Kobuki connected\n");
|
||||
std::cerr <<"unable to connect. retry in 1 second" << std::endl;
|
||||
return HCom;
|
||||
} else {
|
||||
set_interface_attribs2(HCom, B115200,
|
||||
0); // set speed to 115,200 bps, 8n1 (no parity)
|
||||
set_interface_attribs2(HCom, B115200,0); // set speed to 115,200 bps, 8n1 (no parity)
|
||||
set_blocking2(HCom, 0); // set no blocking
|
||||
/* struct termios settings;
|
||||
tcgetattr(HCom, &settings);
|
||||
|
||||
cfsetospeed(&settings, B115200); // baud rate
|
||||
settings.c_cflag &= ~PARENB; // no parity
|
||||
settings.c_cflag &= ~CSTOPB; // 1 stop bit
|
||||
settings.c_cflag &= ~CSIZE;
|
||||
settings.c_cflag |= CS8 | CLOCAL; // 8 bits
|
||||
settings.c_lflag &= ~ICANON; // canonical mode
|
||||
settings.c_cc[VTIME]=1;
|
||||
settings.c_oflag &= ~OPOST; // raw output
|
||||
|
||||
tcsetattr(HCom, TCSANOW, &settings); // apply the settings*/
|
||||
tcflush(HCom, TCOFLUSH);
|
||||
|
||||
printf("Kobuki connected\n");
|
||||
std::cout<<"Kobuki connected" << std::endl;
|
||||
return HCom;
|
||||
}
|
||||
}
|
||||
@@ -252,7 +238,7 @@ void CKobuki::setSound(int noteinHz, int duration) {
|
||||
pocet = write(HCom, &message, 9);
|
||||
}
|
||||
|
||||
bool CKobuki::startCommunication(char *portname, bool CommandsEnabled,
|
||||
void CKobuki::startCommunication(char *portname, bool CommandsEnabled,
|
||||
void *userDataL) {
|
||||
if(connect(portname) != -1){
|
||||
enableCommands(CommandsEnabled);
|
||||
|
@@ -60,7 +60,7 @@ public:
|
||||
|
||||
long loop(void *user_data, TKobukiData &Kobuki_data);
|
||||
|
||||
bool startCommunication(char *portname,bool CommandsEnabled,void *userDataL);
|
||||
void startCommunication(char *portname,bool CommandsEnabled,void *userDataL);
|
||||
int measure(); //thread function, contains an infinite loop and reads data
|
||||
void setLed(int led1 = 0, int led2 = 0); //led1 green/red 2/1, //led2 green/red 2/1
|
||||
void setTranslationSpeed(int mmpersec);
|
||||
|
@@ -1,13 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <thread>
|
||||
#include "MQTT/MqttClient.h"
|
||||
#include "KobukiDriver/CKobuki.h"
|
||||
#include <opencv4/opencv2/opencv.hpp>
|
||||
#include <opencv4/opencv2/core.hpp>
|
||||
|
||||
#include <thread>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
CKobuki robot;
|
||||
@@ -15,21 +12,24 @@ CKobuki robot;
|
||||
std::string readMQTT();
|
||||
void parseMQTT(std::string message);
|
||||
void CapnSend();
|
||||
// ip, clientID, username, password
|
||||
MqttClient client("ws://145.92.224.21/ws/", "KobukiRPI", "rpi",
|
||||
"rpiwachtwoordofzo"); // create a client object
|
||||
MqttClient client("ws://145.92.224.21/ws/", "KobukiRPI", "rpi","rpiwachtwoordofzo"); // create a client object
|
||||
std::string message = "stop";
|
||||
std::string serializeKobukiData(const TKobukiData &data);
|
||||
void sendKobukiData(TKobukiData &data);
|
||||
|
||||
void setup() {
|
||||
unsigned char *null_ptr(0);
|
||||
std::cout << "Attempting to start communication with Kobuki..." << std::endl;
|
||||
robot.startCommunication("/dev/ttyUSB0", true, null_ptr);
|
||||
if (!robot.isConnected()) {
|
||||
std::cerr << "Failed to start communication with Kobuki." << std::endl;
|
||||
} else {
|
||||
std::cout << "Successfully started communication with Kobuki." << std::endl;
|
||||
}
|
||||
// connect mqtt server and sub to commands
|
||||
|
||||
client.connect();
|
||||
client.subscribe("home/commands");
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
@@ -40,6 +40,16 @@ int main() {
|
||||
std::thread sendMqtt([&]() { sendKobukiData(robot.parser.data); });
|
||||
|
||||
while (true) {
|
||||
if (!robot.isConnected()) {
|
||||
std::cout << "Kobuki is not connected anymore. Reconnecting..." << std::endl;
|
||||
robot.startCommunication("/dev/ttyUSB0", true, nullptr);
|
||||
while (!robot.isConnected()) {
|
||||
std::cout << "Attempting to reconnect..." << std::endl;
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
std::cout << "Reconnected to Kobuki." << std::endl;
|
||||
}
|
||||
|
||||
std::string message = readMQTT();
|
||||
if (!message.empty()) {
|
||||
parseMQTT(message);
|
||||
@@ -62,7 +72,7 @@ std::string readMQTT() {
|
||||
|
||||
// Add a small delay to avoid busy-waiting
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
return message;
|
||||
return lastMessage;
|
||||
}
|
||||
|
||||
void parseMQTT(std::string message) {
|
||||
@@ -326,6 +336,13 @@ std::string serializeKobukiData(const TKobukiData &data) {
|
||||
// needed it so it can be threaded
|
||||
void sendKobukiData(TKobukiData &data) {
|
||||
while (true) {
|
||||
// if(!robot.isConnected()){
|
||||
// std::cout << "Kobuki is not connected anymore" << std::endl;
|
||||
// robot.startCommunication("/dev/ttyUSB0", true, nullptr);
|
||||
// while(!robot.isConnected()){
|
||||
// std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
// }
|
||||
// }
|
||||
client.publishMessage("kobuki/data", serializeKobukiData(data));
|
||||
std::cout << "Sent data" << std::endl;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
|
@@ -1,6 +1,7 @@
|
||||
from flask import Flask, request, render_template, jsonify, g
|
||||
import paho.mqtt.client as mqtt
|
||||
import mysql.connector
|
||||
import json
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@@ -9,10 +10,12 @@ kobuki_message = ""
|
||||
latest_image = None
|
||||
|
||||
# Globale MQTT setup
|
||||
def on_message(client, message):
|
||||
def on_message(client,userdata, message):
|
||||
global kobuki_message, latest_image
|
||||
if message.topic == "kobuki/data":
|
||||
kobuki_message = str(message.payload.decode("utf-8"))
|
||||
with app.app_context():
|
||||
sensor_data(kobuki_message) # Sla de data op in de database
|
||||
elif message.topic == "kobuki/cam":
|
||||
latest_image = message.payload
|
||||
|
||||
@@ -24,6 +27,9 @@ mqtt_client.connect("localhost", 1884, 60)
|
||||
mqtt_client.loop_start()
|
||||
mqtt_client.subscribe("kobuki/data")
|
||||
|
||||
mqtt_client.on_message = on_message # this line needs to be under the function definition otherwise it can't find which function it needs to use
|
||||
|
||||
|
||||
# Database connectie-functie
|
||||
def get_db():
|
||||
if 'db' not in g: # 'g' is specifiek voor een request en leeft zolang een request duurt
|
||||
@@ -54,6 +60,11 @@ def control():
|
||||
else:
|
||||
return ('Unauthorized', 401, {'WWW-Authenticate': 'Basic realm="Login Required"'})
|
||||
|
||||
@app.route('/data', methods=['GET'])
|
||||
def data():
|
||||
return kobuki_message
|
||||
|
||||
|
||||
@app.route('/move', methods=['POST'])
|
||||
def move():
|
||||
data = request.get_json()
|
||||
@@ -65,19 +76,14 @@ def move():
|
||||
|
||||
db_connection = get_db()
|
||||
cursor = db_connection.cursor()
|
||||
sql = "INSERT INTO command (command) VALUES (%s)"
|
||||
value = direction
|
||||
cursor.execute(sql, (value,))
|
||||
sql_command = "INSERT INTO command (command) VALUES (%s)"
|
||||
cursor.execute(sql_command, (direction,))
|
||||
|
||||
db_connection.commit()
|
||||
cursor.close()
|
||||
db_connection.close()
|
||||
|
||||
return jsonify({"status": "success", "direction": direction})
|
||||
|
||||
@app.route('/data', methods=['GET'])
|
||||
def data():
|
||||
return jsonify(kobuki_message)
|
||||
|
||||
@app.route("/database")
|
||||
def database():
|
||||
db = get_db()
|
||||
@@ -87,5 +93,39 @@ def database():
|
||||
cursor.close()
|
||||
return str(rows)
|
||||
|
||||
def sensor_data(kobuki_message):
|
||||
try:
|
||||
# Parse de JSON-string naar een Python-dictionary
|
||||
data = json.loads(kobuki_message)
|
||||
|
||||
# Maak een lijst van tuples met de naam en waarde van elk veld
|
||||
sensor_data_tuples = [(name, float(value)) for name, value in data.items() if isinstance(value, (int, float))]
|
||||
|
||||
# Extra informatie of nested data (zoals "extraInfo" of "gyroData") kun je apart verwerken
|
||||
if "extraInfo" in data:
|
||||
for key, value in data["extraInfo"].items():
|
||||
sensor_data_tuples.append((f"extraInfo_{key}", float(value)))
|
||||
|
||||
if "gyroData" in data:
|
||||
for i, gyro in enumerate(data["gyroData"]):
|
||||
for axis, value in gyro.items():
|
||||
sensor_data_tuples.append((f"gyroData_{i}_{axis}", float(value)))
|
||||
|
||||
# Database-insert
|
||||
db = get_db()
|
||||
cursor = db.cursor()
|
||||
|
||||
# Zorg dat je tabel `kobuki_data` kolommen heeft: `name` en `value`
|
||||
sql_sensor = "INSERT INTO kobuki_data (name, value) VALUES (%s, %s)"
|
||||
cursor.executemany(sql_sensor, sensor_data_tuples)
|
||||
|
||||
# Commit en sluit de cursor
|
||||
db.commit()
|
||||
cursor.close()
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"JSON decode error: {e}")
|
||||
except mysql.connector.Error as err:
|
||||
print(f"Database error: {err}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True, port=5000)
|
||||
|
@@ -1,6 +1,8 @@
|
||||
{% extends 'base.html' %} {% block head %}
|
||||
{% extends 'base.html' %}
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="../static/style.css" />
|
||||
{% endblock %} {% block content %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
@@ -11,8 +13,8 @@
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="image-section">
|
||||
<!-- <img src="kobuki.jpg" alt="Kobuki Robot" id="robot-image" /> -->
|
||||
<div class="robot-image">
|
||||
<img src="/image" alt="Kobuki Camera Feed" id="robot-image" />
|
||||
</div>
|
||||
<div class="button-section">
|
||||
<form id="form" action="/move" method="post">
|
||||
@@ -42,6 +44,7 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="../static/script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
Reference in New Issue
Block a user