mirror of
https://github.com/modelec/ihm.git
synced 2026-01-18 16:47:32 +01:00
TCP and preparation
This commit is contained in:
@@ -7,32 +7,57 @@ set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
|
||||
set(HEADERS
|
||||
MainWindow.h
|
||||
homeButton.h
|
||||
Homologation.h
|
||||
InGame.h
|
||||
TeamChooser.h
|
||||
TestMode.h
|
||||
TestModeBtn.h
|
||||
preparation/TiretteState.h
|
||||
preparation/Lidar.h
|
||||
PreparationMatch.h
|
||||
preparation/OneItemPreparation.h
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
MainWindow.cpp
|
||||
homeButton.cpp
|
||||
Homologation.cpp
|
||||
InGame.cpp
|
||||
TeamChooser.cpp
|
||||
TestMode.cpp
|
||||
TestModeBtn.cpp
|
||||
PreparationMatch.cpp
|
||||
preparation/Lidar.cpp
|
||||
preparation/OneItemPreparation.cpp
|
||||
preparation/TiretteState.cpp
|
||||
)
|
||||
|
||||
set(TCP
|
||||
tcp/TCPServer.hpp
|
||||
tcp/TCPServer.cpp
|
||||
tcp/utils.hpp
|
||||
tcp/QTTCPSocketServer.cpp
|
||||
tcp/QTTCPSocketServer.h
|
||||
)
|
||||
|
||||
|
||||
find_package(Qt6 COMPONENTS
|
||||
Core
|
||||
Gui
|
||||
Widgets
|
||||
Network
|
||||
REQUIRED)
|
||||
|
||||
add_executable(ihm_robot main.cpp resource.qrc
|
||||
MainWindow.cpp
|
||||
MainWindow.h
|
||||
homeButton.cpp
|
||||
homeButton.h
|
||||
Homologation.cpp
|
||||
Homologation.h
|
||||
InGame.cpp
|
||||
InGame.h
|
||||
TeamChooser.cpp
|
||||
TeamChooser.h
|
||||
TestMode.cpp
|
||||
TestMode.h
|
||||
TestModeBtn.cpp
|
||||
TestModeBtn.h
|
||||
)
|
||||
add_executable(ihm_robot resource.qrc ${HEADERS} ${SOURCES} ${TCP})
|
||||
|
||||
target_link_libraries(ihm_robot
|
||||
Qt::Core
|
||||
Qt::Gui
|
||||
Qt::Widgets
|
||||
Qt::Network
|
||||
)
|
||||
|
||||
|
||||
40
MainWindow.h
40
MainWindow.h
@@ -1,12 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QWidget>
|
||||
#include <QStackedWidget>
|
||||
#include <QIcon>
|
||||
#include <QPixmap>
|
||||
|
||||
#include "homeButton.h"
|
||||
#include "Homologation.h"
|
||||
#include "InGame.h"
|
||||
#include "PreparationMatch.h"
|
||||
#include "TeamChooser.h"
|
||||
#include "TestMode.h"
|
||||
|
||||
@@ -58,9 +60,12 @@ public:
|
||||
connect(this->homologation, &Homologation::replierClicked, this, &MainWindow::replierRobot);
|
||||
|
||||
this->teamChooser = new TeamChooser(centralWidget);
|
||||
connect(this->teamChooser, &TeamChooser::blueTeamClicked, this, &MainWindow::onInGamePressed);
|
||||
connect(this->teamChooser, &TeamChooser::spawnPointChoose, this, &MainWindow::onSpawnPointChoose);
|
||||
|
||||
connect(this->teamChooser, &TeamChooser::yellowTeamClicked, this, &MainWindow::onInGamePressed);
|
||||
this->preparationMatch = new PreparationMatch(centralWidget);
|
||||
connect(this->preparationMatch, &PreparationMatch::startGame, this, &MainWindow::onStartGame);
|
||||
// connect(this->preparationMatch, &PreparationMatch::askTCPServer, this, &MainWindow::broadcastTCPMessage);
|
||||
connect(this->preparationMatch, &PreparationMatch::askTCPServer, this, &MainWindow::broadcastTCPMessage);
|
||||
|
||||
this->testMode = new TestMode(centralWidget);
|
||||
connect(this->testMode, &TestMode::goPressed, this, &MainWindow::moveRobot);
|
||||
@@ -71,6 +76,7 @@ public:
|
||||
this->stackedWidget->addWidget(this->home);
|
||||
this->stackedWidget->addWidget(this->homologation);
|
||||
this->stackedWidget->addWidget(this->teamChooser);
|
||||
this->stackedWidget->addWidget(this->preparationMatch);
|
||||
this->stackedWidget->addWidget(this->testMode);
|
||||
this->stackedWidget->addWidget(this->inGame);
|
||||
|
||||
@@ -86,11 +92,15 @@ public:
|
||||
QPalette palette;
|
||||
palette.setBrush(this->backgroundRole(), QBrush(QPixmap(":/img/table.jpg", "JPG").scaled(this->size(), Qt::IgnoreAspectRatio)));
|
||||
this->setPalette(palette);
|
||||
this->homeBtn->hide();
|
||||
this->quit->hide();
|
||||
} else
|
||||
{
|
||||
QPalette palette;
|
||||
palette.setBrush(this->backgroundRole(), QBrush(Qt::white));
|
||||
this->setPalette(palette);
|
||||
this->homeBtn->show();
|
||||
this->quit->show();
|
||||
}
|
||||
this->stackedWidget->setCurrentIndex(index);
|
||||
}
|
||||
@@ -112,13 +122,18 @@ protected slots:
|
||||
}
|
||||
|
||||
void onTestModePressed()
|
||||
{
|
||||
this->setWidgetNb(4);
|
||||
}
|
||||
|
||||
void onSpawnPointChoose(int nb)
|
||||
{
|
||||
this->setWidgetNb(3);
|
||||
}
|
||||
|
||||
void onInGamePressed()
|
||||
void onStartGame()
|
||||
{
|
||||
this->setWidgetNb(4);
|
||||
this->setWidgetNb(5);
|
||||
}
|
||||
|
||||
void onDeplierRobot()
|
||||
@@ -131,10 +146,24 @@ protected slots:
|
||||
emit replierRobot();
|
||||
}
|
||||
|
||||
public slots:
|
||||
void onTCPMesssageReceived(const std::string& message)
|
||||
{
|
||||
QString qMessage = QString::fromStdString(message);
|
||||
|
||||
auto list = qMessage.split(";");
|
||||
|
||||
if (list[2].startsWith("pong"))
|
||||
{
|
||||
preparationMatch->responseFromPing(qMessage);
|
||||
}
|
||||
}
|
||||
|
||||
signals:
|
||||
void deplierRobot();
|
||||
void replierRobot();
|
||||
void moveRobot(int x, int y, int theta);
|
||||
void broadcastTCPMessage(const std::string& message);
|
||||
|
||||
private:
|
||||
QVBoxLayout* mainLayout;
|
||||
@@ -147,6 +176,7 @@ private:
|
||||
homeButton* home;
|
||||
Homologation* homologation;
|
||||
TeamChooser* teamChooser;
|
||||
PreparationMatch* preparationMatch;
|
||||
TestMode* testMode;
|
||||
InGame* inGame;
|
||||
};
|
||||
|
||||
5
PreparationMatch.cpp
Normal file
5
PreparationMatch.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
//
|
||||
// Created by acki on 3/27/24.
|
||||
//
|
||||
|
||||
#include "PreparationMatch.h"
|
||||
115
PreparationMatch.h
Normal file
115
PreparationMatch.h
Normal file
@@ -0,0 +1,115 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
#include "preparation/Lidar.h"
|
||||
#include "preparation/OneItemPreparation.h"
|
||||
#include "preparation/TiretteState.h"
|
||||
|
||||
class PreparationMatch : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
PreparationMatch(QWidget* parent = nullptr) : QWidget(parent)
|
||||
{
|
||||
this->mainLayout = new QVBoxLayout(this);
|
||||
this->gridLayout = new QHBoxLayout();
|
||||
|
||||
this->startButton = new QPushButton("Play", this);
|
||||
|
||||
this->leftLayout = new QVBoxLayout();
|
||||
this->lidar = new Lidar(this);
|
||||
this->leftLayout->addWidget(lidar);
|
||||
|
||||
this->tiretteState = new TiretteState(this);
|
||||
this->leftLayout->addWidget(tiretteState);
|
||||
|
||||
this->rightLayout = new QVBoxLayout();
|
||||
this->ledVerte = new OneItemPreparation("Led verte", "Check", this);
|
||||
connect(this->ledVerte, &OneItemPreparation::buttonClicked, this, [=]() {
|
||||
this->ledVerte->toggleChecked();
|
||||
});
|
||||
|
||||
this->arduino = new OneItemPreparation("Arduino", "Ping", this);
|
||||
connect(this->arduino, &OneItemPreparation::buttonClicked, this, [=]() {
|
||||
// emit askTCPServer("start;tirette;ping;0");
|
||||
|
||||
this->arduino->toggleChecked();
|
||||
});
|
||||
|
||||
this->aruco = new OneItemPreparation("Aruco", "Ping", this);
|
||||
connect(this->aruco, &OneItemPreparation::buttonClicked, this, [=]() {
|
||||
emit askTCPServer("strat;aruco;ping;0");
|
||||
});
|
||||
|
||||
this->lidarPing = new OneItemPreparation("Lidar", "Ping", this);
|
||||
connect(this->lidarPing, &OneItemPreparation::buttonClicked, this, [=]() {
|
||||
emit askTCPServer("strat;lidar;ping;0");
|
||||
});
|
||||
|
||||
this->tirette = new OneItemPreparation("Tirette", "Ping", this);
|
||||
connect(this->tirette, &OneItemPreparation::buttonClicked, this, [=]() {
|
||||
emit askTCPServer("strat;tirette;ping;0");
|
||||
});
|
||||
|
||||
this->rightLayout->addWidget(ledVerte);
|
||||
this->rightLayout->addWidget(arduino);
|
||||
this->rightLayout->addWidget(aruco);
|
||||
this->rightLayout->addWidget(lidarPing);
|
||||
this->rightLayout->addWidget(tirette);
|
||||
|
||||
this->gridLayout->addLayout(leftLayout);
|
||||
this->gridLayout->addLayout(rightLayout);
|
||||
|
||||
this->mainLayout->addLayout(gridLayout);
|
||||
this->mainLayout->addWidget(startButton);
|
||||
|
||||
connect(this->startButton, &QPushButton::pressed, this, &PreparationMatch::onStartButtonClicked);
|
||||
}
|
||||
|
||||
void responseFromPing(const QString& message)
|
||||
{
|
||||
auto list = message.split(";");
|
||||
|
||||
if (list[0] == "tirette") {
|
||||
this->tirette->setChecked(true);
|
||||
} else if (list[0] == "lidar") {
|
||||
this->lidarPing->setChecked(true);
|
||||
} else if (list[0] == "aruco") {
|
||||
this->aruco->setChecked(true);
|
||||
}
|
||||
// TODO check how we ping the arduino
|
||||
/*else if (list[0] == "arduino") {
|
||||
this->arduino->setChecked(true);
|
||||
}*/
|
||||
}
|
||||
|
||||
signals:
|
||||
void startGame();
|
||||
|
||||
void askTCPServer(const std::string& message);
|
||||
|
||||
public slots:
|
||||
void onStartButtonClicked()
|
||||
{
|
||||
emit startGame();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
QVBoxLayout* mainLayout;
|
||||
QHBoxLayout* gridLayout;
|
||||
QVBoxLayout* leftLayout;
|
||||
QVBoxLayout* rightLayout;
|
||||
|
||||
Lidar* lidar;
|
||||
OneItemPreparation* ledVerte;
|
||||
OneItemPreparation* arduino;
|
||||
OneItemPreparation* aruco;
|
||||
OneItemPreparation* lidarPing;
|
||||
OneItemPreparation* tirette;
|
||||
TiretteState* tiretteState;
|
||||
|
||||
QPushButton* startButton;
|
||||
};
|
||||
@@ -8,36 +8,90 @@ class TeamChooser : public QWidget {
|
||||
public:
|
||||
TeamChooser(QWidget* parent = nullptr) : QWidget(parent)
|
||||
{
|
||||
this->mainLayout = new QHBoxLayout(this);
|
||||
this->blueTeam = new QPushButton("Equipe Bleue", this);
|
||||
this->blueTeam->setStyleSheet("background-color: #4D83A1; border-radius: 40px; margin-top: 20px; color: black;");
|
||||
this->yellowTeam = new QPushButton("Equipe Jaune", this);
|
||||
this->yellowTeam->setStyleSheet("background-color: #FFBF00; border-radius: 40px; margin-top: 20px; color: black;");
|
||||
// set a border
|
||||
// this->setStyleSheet("border: 10px solid black;");
|
||||
|
||||
this->mainLayout->addWidget(this->blueTeam);
|
||||
this->mainLayout->addWidget(this->yellowTeam);
|
||||
this->mainLayout = new QVBoxLayout(this);
|
||||
|
||||
connect(this->blueTeam, &QPushButton::pressed, this, &TeamChooser::onBlueTeamClicked);
|
||||
connect(this->yellowTeam, &QPushButton::pressed, this, &TeamChooser::onYellowTeamClicked);
|
||||
this->topLayout = new QHBoxLayout();
|
||||
this->middleLayout = new QHBoxLayout();
|
||||
this->bottomLayout = new QHBoxLayout();
|
||||
|
||||
this->spawnPoint1 = new QPushButton("1", this);
|
||||
this->spawnPoint1->setFixedSize(50, 50);
|
||||
this->spawnPoint1->setStyleSheet("border: 1px solid black; color: white; background-color: rgba(0, 0, 255, 200);");
|
||||
this->spawnPoint2 = new QPushButton("2", this);
|
||||
this->spawnPoint2->setFixedSize(50, 50);
|
||||
this->spawnPoint2->setStyleSheet("border: 1px solid black; color: black; background-color: rgba(255, 255, 0, 200);");
|
||||
this->spawnPoint3 = new QPushButton("3", this);
|
||||
this->spawnPoint3->setFixedSize(50, 50);
|
||||
this->spawnPoint3->setStyleSheet("border: 1px solid black; color: white; background-color: rgba(0, 0, 255, 200);");
|
||||
this->spawnPoint4 = new QPushButton("4", this);
|
||||
this->spawnPoint4->setFixedSize(50, 50);
|
||||
this->spawnPoint4->setStyleSheet("border: 1px solid black; color: black; background-color: rgba(255, 255, 0, 200);");
|
||||
this->spawnPoint5 = new QPushButton("5", this);
|
||||
this->spawnPoint5->setFixedSize(50, 50);
|
||||
this->spawnPoint5->setStyleSheet("border: 1px solid black; color: white; background-color: rgba(0, 0, 255, 200);");
|
||||
this->spawnPoint6 = new QPushButton("6", this);
|
||||
this->spawnPoint6->setFixedSize(50, 50);
|
||||
this->spawnPoint6->setStyleSheet("border: 1px solid black; color: black; background-color: rgba(255, 255, 0, 200);");
|
||||
|
||||
this->mainLayout->addLayout(topLayout);
|
||||
this->mainLayout->addLayout(middleLayout);
|
||||
this->mainLayout->addLayout(bottomLayout);
|
||||
|
||||
this->topLayout->addWidget(spawnPoint1, 0, Qt::AlignTop | Qt::AlignLeft);
|
||||
this->middleLayout->addWidget(spawnPoint2, 0, Qt::AlignCenter | Qt::AlignLeft);
|
||||
this->bottomLayout->addWidget(spawnPoint3, 0, Qt::AlignBottom | Qt::AlignLeft);
|
||||
this->topLayout->addWidget(spawnPoint4, 0, Qt::AlignTop | Qt::AlignRight);
|
||||
this->middleLayout->addWidget(spawnPoint5, 0, Qt::AlignCenter | Qt::AlignRight);
|
||||
this->bottomLayout->addWidget(spawnPoint6, 0, Qt::AlignBottom | Qt::AlignRight);
|
||||
|
||||
connect(this->spawnPoint1, &QPushButton::pressed, this, [=]() {
|
||||
spawnPointClicked(1);
|
||||
});
|
||||
|
||||
connect(this->spawnPoint2, &QPushButton::pressed, this, [=]() {
|
||||
spawnPointClicked(2);
|
||||
});
|
||||
|
||||
connect(this->spawnPoint3, &QPushButton::pressed, this, [=]() {
|
||||
spawnPointClicked(3);
|
||||
});
|
||||
|
||||
connect(this->spawnPoint4, &QPushButton::pressed, this, [=]() {
|
||||
spawnPointClicked(4);
|
||||
});
|
||||
|
||||
connect(this->spawnPoint5, &QPushButton::pressed, this, [=]() {
|
||||
spawnPointClicked(5);
|
||||
});
|
||||
|
||||
connect(this->spawnPoint6, &QPushButton::pressed, this, [=]() {
|
||||
spawnPointClicked(6);
|
||||
});
|
||||
}
|
||||
|
||||
signals:
|
||||
void blueTeamClicked();
|
||||
void yellowTeamClicked();
|
||||
void spawnPointChoose(int nb);
|
||||
|
||||
private slots:
|
||||
void onBlueTeamClicked()
|
||||
void spawnPointClicked(int nb)
|
||||
{
|
||||
emit blueTeamClicked();
|
||||
}
|
||||
|
||||
void onYellowTeamClicked()
|
||||
{
|
||||
emit yellowTeamClicked();
|
||||
emit spawnPointChoose(nb);
|
||||
}
|
||||
|
||||
private:
|
||||
QHBoxLayout* mainLayout;
|
||||
QPushButton* blueTeam;
|
||||
QPushButton* yellowTeam;
|
||||
QVBoxLayout* mainLayout;
|
||||
QHBoxLayout* topLayout;
|
||||
QHBoxLayout* middleLayout;
|
||||
QHBoxLayout* bottomLayout;
|
||||
|
||||
QPushButton* spawnPoint1;
|
||||
QPushButton* spawnPoint2;
|
||||
QPushButton* spawnPoint3;
|
||||
QPushButton* spawnPoint4;
|
||||
QPushButton* spawnPoint5;
|
||||
QPushButton* spawnPoint6;
|
||||
|
||||
};
|
||||
|
||||
48
main.cpp
48
main.cpp
@@ -1,7 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <QApplication>
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include "tcp/TCPServer.hpp"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
QApplication a(argc, argv);
|
||||
@@ -23,9 +26,50 @@ int main(int argc, char* argv[]) {
|
||||
qInfo() << "move" << x << y << theta;
|
||||
});
|
||||
|
||||
//main->show();
|
||||
main->show();
|
||||
// main->showFullScreen();
|
||||
|
||||
main->showFullScreen();
|
||||
auto* server = new TCPServer(8082);
|
||||
server->start();
|
||||
|
||||
QObject::connect(server, &TCPServer::messageReceived, main, &MainWindow::onTCPMesssageReceived);
|
||||
QObject::connect(main, &MainWindow::broadcastTCPMessage, [server](const std::string& message)
|
||||
{
|
||||
server->broadcastMessage(message.c_str());
|
||||
});
|
||||
|
||||
// Create a new thread for the server
|
||||
QThread serverThread;
|
||||
server->moveToThread(&serverThread);
|
||||
serverThread.start();
|
||||
|
||||
// Create a lambda function to run the while loop
|
||||
auto runServerLoop = [&]() {
|
||||
while (true) {
|
||||
std::string message;
|
||||
std::cout << "Enter message ('quit' to exit): ";
|
||||
std::getline(std::cin, message);
|
||||
|
||||
if (message == "quit") {
|
||||
// Stop the server and exit the loop
|
||||
server->stop();
|
||||
break;
|
||||
}
|
||||
|
||||
// Broadcast the message from the server
|
||||
server->broadcastMessage(message.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
// Move the lambda function to the new thread
|
||||
QObject::connect(&serverThread, &QThread::started, runServerLoop);
|
||||
|
||||
// Connect aboutToQuit signal to stop the thread and wait for it to finish
|
||||
QObject::connect(&a, &QCoreApplication::aboutToQuit, [&]() {
|
||||
server->stop(); // Stop the server
|
||||
serverThread.quit(); // Quit the thread event loop
|
||||
serverThread.wait(); // Wait for the thread to finish
|
||||
});
|
||||
|
||||
return QApplication::exec();
|
||||
}
|
||||
|
||||
5
preparation/Lidar.cpp
Normal file
5
preparation/Lidar.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
//
|
||||
// Created by acki on 3/27/24.
|
||||
//
|
||||
|
||||
#include "Lidar.h"
|
||||
48
preparation/Lidar.h
Normal file
48
preparation/Lidar.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
class Lidar : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Lidar(QWidget* parent = nullptr) : QWidget(parent)
|
||||
{
|
||||
this->mainLayout = new QVBoxLayout(this);
|
||||
this->mainLayout->setAlignment(Qt::AlignTop);
|
||||
this->title = new QLabel("Lidar", this);
|
||||
this->title->setStyleSheet("font-size: 24px; color: black;");
|
||||
|
||||
this->position = new QHBoxLayout();
|
||||
this->postionTitle = new QLabel("x: 0, y : 0, r: 0", this);
|
||||
this->positionButton = new QPushButton("Get pos", this);
|
||||
|
||||
this->position->addWidget(postionTitle);
|
||||
this->position->addWidget(positionButton);
|
||||
|
||||
this->health = new QHBoxLayout();
|
||||
this->healthTitle = new QLabel("Health : OK", this);
|
||||
this->healthButton = new QPushButton("Get health", this);
|
||||
|
||||
this->health->addWidget(healthTitle);
|
||||
this->health->addWidget(healthButton);
|
||||
|
||||
this->mainLayout->addWidget(title, 0, Qt::AlignCenter);
|
||||
this->mainLayout->addLayout(position);
|
||||
this->mainLayout->addLayout(health);
|
||||
}
|
||||
|
||||
private:
|
||||
QVBoxLayout* mainLayout;
|
||||
QLabel* title;
|
||||
QHBoxLayout* position;
|
||||
QHBoxLayout* health;
|
||||
|
||||
QLabel* postionTitle;
|
||||
QPushButton* positionButton;
|
||||
|
||||
QLabel* healthTitle;
|
||||
QPushButton* healthButton;
|
||||
};
|
||||
5
preparation/OneItemPreparation.cpp
Normal file
5
preparation/OneItemPreparation.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
//
|
||||
// Created by acki on 3/27/24.
|
||||
//
|
||||
|
||||
#include "OneItemPreparation.h"
|
||||
54
preparation/OneItemPreparation.h
Normal file
54
preparation/OneItemPreparation.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QWidget>
|
||||
#include <QCheckBox>
|
||||
#include <QPushButton>
|
||||
|
||||
class OneItemPreparation : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
OneItemPreparation(const QString& title, const QString& buttonText, QWidget* parent = nullptr) : QWidget(parent)
|
||||
{
|
||||
this->mainLayout = new QHBoxLayout(this);
|
||||
|
||||
this->item = new QLabel(title, this);
|
||||
this->checkBox = new QCheckBox(this);
|
||||
this->button = new QPushButton(buttonText, this);
|
||||
|
||||
this->mainLayout->addWidget(item);
|
||||
this->mainLayout->addWidget(checkBox);
|
||||
this->mainLayout->addWidget(button);
|
||||
|
||||
this->checkBox->setDisabled(true);
|
||||
|
||||
connect(this->button, &QPushButton::pressed, this, &OneItemPreparation::onButtonClicked);
|
||||
}
|
||||
|
||||
void setChecked(const bool checked) const
|
||||
{
|
||||
this->checkBox->setChecked(checked);
|
||||
}
|
||||
|
||||
void toggleChecked() const
|
||||
{
|
||||
this->checkBox->toggle();
|
||||
}
|
||||
|
||||
signals:
|
||||
void buttonClicked();
|
||||
|
||||
public slots:
|
||||
void onButtonClicked()
|
||||
{
|
||||
emit buttonClicked();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
QHBoxLayout* mainLayout;
|
||||
QLabel* item;
|
||||
QCheckBox* checkBox;
|
||||
QPushButton* button;
|
||||
};
|
||||
5
preparation/TiretteState.cpp
Normal file
5
preparation/TiretteState.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
//
|
||||
// Created by acki on 3/27/24.
|
||||
//
|
||||
|
||||
#include "TiretteState.h"
|
||||
33
preparation/TiretteState.h
Normal file
33
preparation/TiretteState.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QWidget>
|
||||
|
||||
class TiretteState : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TiretteState(QWidget* parent = nullptr) : QWidget(parent)
|
||||
{
|
||||
this->mainLayout = new QVBoxLayout(this);
|
||||
this->title = new QLabel("Tirette", this);
|
||||
this->title->setStyleSheet("font-size: 24px; color: black;");
|
||||
|
||||
this->tiretteStateLayout = new QHBoxLayout();
|
||||
this->stateLabel = new QLabel("1 : ", this);
|
||||
this->stateButton = new QPushButton("Get state", this);
|
||||
this->tiretteStateLayout->addWidget(stateLabel);
|
||||
this->tiretteStateLayout->addWidget(stateButton);
|
||||
|
||||
this->mainLayout->addWidget(this->title, 0, Qt::AlignCenter);
|
||||
this->mainLayout->addLayout(this->tiretteStateLayout);
|
||||
}
|
||||
|
||||
private:
|
||||
QVBoxLayout* mainLayout;
|
||||
QLabel* title;
|
||||
QHBoxLayout* tiretteStateLayout;
|
||||
QLabel* stateLabel;
|
||||
QPushButton* stateButton;
|
||||
};
|
||||
9
tcp/CMakeLists.txt
Normal file
9
tcp/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
cmake_minimum_required(VERSION 3.25)
|
||||
project(socketServer)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
add_executable(socketServer main.cpp
|
||||
TCPServer.cpp
|
||||
TCPServer.hpp
|
||||
utils.hpp)
|
||||
149
tcp/TCPServer.cpp
Normal file
149
tcp/TCPServer.cpp
Normal file
@@ -0,0 +1,149 @@
|
||||
#include "TCPServer.hpp"
|
||||
|
||||
#include "utils.hpp"
|
||||
|
||||
ClientHandler::ClientHandler(int clientSocket, TCPServer* server) : clientSocket(clientSocket), server(server) {};
|
||||
|
||||
void ClientHandler::handle() {
|
||||
std::string buffer;
|
||||
buffer.reserve(4096); // Pre-allocate memory to avoid frequent allocations
|
||||
|
||||
while (true) {
|
||||
char tempBuffer[4096] = {0};
|
||||
ssize_t valread = recv(clientSocket, tempBuffer, sizeof(tempBuffer), 0);
|
||||
|
||||
if (valread > 0) {
|
||||
buffer.append(tempBuffer, valread);
|
||||
//std::cout << "Received: " << buffer << std::endl;
|
||||
|
||||
if (buffer == "quit") {
|
||||
std::cout << "Client requested to quit. Closing connection." << std::endl;
|
||||
break;
|
||||
}
|
||||
processMessage(buffer);
|
||||
|
||||
buffer.clear();
|
||||
} else if (valread == 0) {
|
||||
std::cout << "Client disconnected." << std::endl;
|
||||
break; // Client disconnected
|
||||
} else {
|
||||
std::cerr << "Failed to receive data." << std::endl;
|
||||
break; // Error in receiving data
|
||||
}
|
||||
}
|
||||
|
||||
closeConnection();
|
||||
}
|
||||
|
||||
void ClientHandler::processMessage(const std::string& message) {
|
||||
server->handleMessage(message, clientSocket);
|
||||
}
|
||||
|
||||
void ClientHandler::closeConnection() {
|
||||
close(clientSocket);
|
||||
server->clientDisconnected(clientSocket); // Inform the server that the client has disconnected
|
||||
}
|
||||
|
||||
TCPServer::TCPServer(int port, QObject* parent) : QObject(parent)
|
||||
{
|
||||
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (serverSocket == -1) {
|
||||
std::cerr << "Socket creation failed" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
sockaddr_in address{};
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
address.sin_port = htons(port);
|
||||
|
||||
if (bind(serverSocket, reinterpret_cast<struct sockaddr*>(&address), sizeof(address)) == -1) {
|
||||
std::cerr << "Binding failed" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (listen(serverSocket, 5) == -1) {
|
||||
std::cerr << "Listening failed" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
std::cout << "Server started on port " << port << std::endl;
|
||||
}
|
||||
|
||||
void TCPServer::acceptConnections()
|
||||
{
|
||||
while (!shouldStop) {
|
||||
sockaddr_in clientAddress{};
|
||||
int addrlen = sizeof(clientAddress);
|
||||
int clientSocket =
|
||||
accept(serverSocket, reinterpret_cast<struct sockaddr*>(&clientAddress), reinterpret_cast<socklen_t*>(&addrlen));
|
||||
if (clientSocket == -1) {
|
||||
std::cerr << "Accepting connection failed" << std::endl;
|
||||
continue;
|
||||
}
|
||||
std::cout << "Connection accepted" << std::endl;
|
||||
|
||||
// Add the client socket to the list
|
||||
clientSockets.push_back(clientSocket);
|
||||
connectedClients++;
|
||||
|
||||
// Handle client connection in a separate thread
|
||||
clientThreads.emplace_back(&ClientHandler::handle, ClientHandler(clientSocket, this));
|
||||
// Clean up finished threads
|
||||
clientThreads.erase(std::remove_if(clientThreads.begin(), clientThreads.end(), [](std::thread &t) {
|
||||
return !t.joinable();
|
||||
}), clientThreads.end());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void TCPServer::handleMessage(const std::string& message, int clientSocket)
|
||||
{
|
||||
emit messageReceived(message, clientSocket);
|
||||
}
|
||||
|
||||
|
||||
void TCPServer::broadcastMessage(const char* message, int senderSocket)
|
||||
{
|
||||
for (int clientSocket : clientSockets) {
|
||||
if (clientSocket != senderSocket) { // Exclude the sender's socket
|
||||
send(clientSocket, message, strlen(message), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TCPServer::clientDisconnected(const int clientSocket) {
|
||||
// Remove the disconnected client's socket
|
||||
clientSockets.erase(std::remove(clientSockets.begin(), clientSockets.end(), clientSocket), clientSockets.end());
|
||||
// Decrement the count of connected clients
|
||||
connectedClients--;
|
||||
}
|
||||
|
||||
void TCPServer::stop() {
|
||||
shouldStop = true;
|
||||
// Close all client sockets
|
||||
for (int clientSocket : clientSockets) {
|
||||
close(clientSocket);
|
||||
}
|
||||
// Close the server socket
|
||||
close(serverSocket);
|
||||
}
|
||||
|
||||
TCPServer::~TCPServer() {
|
||||
this->stop();
|
||||
// Join all threads before exiting
|
||||
for (auto& thread : clientThreads) {
|
||||
thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
int TCPServer::nbClients()
|
||||
{
|
||||
return connectedClients;
|
||||
}
|
||||
|
||||
void TCPServer::start()
|
||||
{
|
||||
std::thread([this]() { acceptConnections(); }).detach();
|
||||
}
|
||||
61
tcp/TCPServer.hpp
Normal file
61
tcp/TCPServer.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <QObject>
|
||||
|
||||
class TCPServer; // Forward declaration
|
||||
|
||||
class ClientHandler {
|
||||
private:
|
||||
int clientSocket;
|
||||
TCPServer* server; // Reference to the TCPServer instance
|
||||
|
||||
public:
|
||||
explicit ClientHandler(int clientSocket, TCPServer* server);
|
||||
|
||||
void handle();
|
||||
|
||||
void processMessage(const std::string& message);
|
||||
|
||||
void closeConnection();
|
||||
};
|
||||
|
||||
class TCPServer : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
int serverSocket;
|
||||
std::vector<std::thread> clientThreads;
|
||||
std::vector<int> clientSockets; // Store connected client sockets
|
||||
int connectedClients = 0; // Track the number of connected clients
|
||||
bool shouldStop = false; // Flag to indicate if the server should stop
|
||||
|
||||
public:
|
||||
explicit TCPServer(int port, QObject* parent = nullptr);
|
||||
|
||||
void start();
|
||||
|
||||
void acceptConnections();
|
||||
|
||||
// Broadcast message to all connected clients
|
||||
void broadcastMessage(const char* message, int senderSocket = -1); // Modified method signature
|
||||
|
||||
void handleMessage(const std::string& message, int clientSocket = -1);
|
||||
|
||||
void clientDisconnected(int clientSocket); // New method to handle client disconnection
|
||||
|
||||
void stop();
|
||||
|
||||
int nbClients();
|
||||
|
||||
~TCPServer();
|
||||
|
||||
signals:
|
||||
void messageReceived(const std::string& message, int clientSocket);
|
||||
};
|
||||
36
tcp/main.cpp
Normal file
36
tcp/main.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <atomic>
|
||||
#include <csignal>
|
||||
|
||||
#include "TCPServer.hpp"
|
||||
|
||||
std::atomic<bool> keepRunning(true);
|
||||
|
||||
void signalHandler(int signum) {
|
||||
std::cout << "Interrupt signal (" << signum << ") received.\n";
|
||||
keepRunning = false;
|
||||
}
|
||||
|
||||
int main() {
|
||||
signal(SIGTERM, signalHandler);
|
||||
signal(SIGINT, signalHandler);
|
||||
|
||||
TCPServer server(8080);
|
||||
|
||||
try {
|
||||
server.start();
|
||||
|
||||
while (keepRunning) {
|
||||
sleep(1);
|
||||
|
||||
server.broadcastMessage("request aruco");
|
||||
|
||||
std::cout << "Main thread communicating with server..." << std::endl;
|
||||
}
|
||||
|
||||
server.stop();
|
||||
} catch (const std::exception& ex) {
|
||||
std::cerr << "Error: " << ex.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
38
tcp/utils.hpp
Normal file
38
tcp/utils.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
inline bool startWith(const std::string& str, const std::string& start)
|
||||
{
|
||||
return str.rfind(start, 0) == 0;
|
||||
}
|
||||
|
||||
inline bool endsWith(const std::string& str, const std::string& end)
|
||||
{
|
||||
if (str.length() >= end.length())
|
||||
{
|
||||
return (0 == str.compare(str.length() - end.length(), end.length(), end));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool contains(const std::string& str, const std::string& sub)
|
||||
{
|
||||
return str.find(sub) != std::string::npos;
|
||||
}
|
||||
|
||||
inline std::vector<std::string> split(const std::string& str, const std::string& delimiter)
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
size_t prev = 0, pos = 0;
|
||||
do
|
||||
{
|
||||
pos = str.find(delimiter, prev);
|
||||
if (pos == std::string::npos) pos = str.length();
|
||||
std::string token = str.substr(prev, pos - prev);
|
||||
if (!token.empty()) tokens.push_back(token);
|
||||
prev = pos + delimiter.length();
|
||||
} while (pos < str.length() && prev < str.length());
|
||||
return tokens;
|
||||
}
|
||||
Reference in New Issue
Block a user