Skip to content

Commit f025930

Browse files
Merge pull request #59 from trikset/mailbox
Mailbox
2 parents 97b5a11 + c783bb6 commit f025930

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2260
-198
lines changed

trikCommunicator/include/trikCommunicator/trikCommunicator.h

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2013 Yurii Litvinov
1+
/* Copyright 2013 - 2014 Yurii Litvinov, Cybertech Labs Ltd.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -21,6 +21,8 @@
2121
#include <QtNetwork/QTcpServer>
2222
#include <QtNetwork/QTcpSocket>
2323

24+
#include <trikKernel/trikServer.h>
25+
2426
namespace trikScriptRunner {
2527
class TrikScriptRunner;
2628
}
@@ -37,26 +39,20 @@ class Connection;
3739
/// Communication subsystem consists of TrikCommunicator object which runs in main thread and listens for incoming
3840
/// connections, Connection objects --- one for every connected client, they run in separate threads each, and
3941
/// ScriptRunnerWrapper object in main thread which processes signals from Connections.
40-
class TrikCommunicator : public QTcpServer
42+
class TrikCommunicator : public trikKernel::TrikServer
4143
{
4244
Q_OBJECT
4345

4446
public:
4547
/// Constructor that creates its own instance of a script runner.
4648
/// @param configPath - path to config file for trikControl, for example, /home/root/trik/.
4749
/// @param startDirPath - path to the directory from which the application was executed.
48-
explicit TrikCommunicator(trikControl::Brick &brick, QString const &startDirPath);
50+
TrikCommunicator(trikControl::Brick &brick, QString const &startDirPath);
4951

5052
/// Constructor that accepts external script runner and issues commands to it.
5153
explicit TrikCommunicator(trikScriptRunner::TrikScriptRunner &runner);
5254

53-
~TrikCommunicator();
54-
55-
/// Starts listening given port on all network interfaces.
56-
void startServer(int const &port);
57-
58-
/// Sends message to server if socket is opened; otherwise does nothing.
59-
void sendMessage(QString const &message);
55+
~TrikCommunicator() override;
6056

6157
signals:
6258
/// Emitted when command to run a script from a file is received.
@@ -68,16 +64,10 @@ class TrikCommunicator : public QTcpServer
6864
/// Emitted when script finishes execution.
6965
void finishedScript();
7066

71-
protected:
72-
void incomingConnection(int socketDescriptor); // Override.
73-
74-
private slots:
75-
/// Called when connection thread finishes.
76-
void onConnectionClosed();
77-
7867
private:
79-
/// Common initialization from constructors.
80-
void init();
68+
TrikCommunicator(trikScriptRunner::TrikScriptRunner * const runner, bool hasScriptRunnerOwnership);
69+
70+
Connection *connectionFactory();
8171

8272
/// Script runner object common to all connections.
8373
/// Ownership depends on mHasScriptRunnerOwnership flag, if we received runner belonging to other object or created
@@ -86,9 +76,6 @@ private slots:
8676

8777
/// True, if we created our own script runner, false if we got it from someone.
8878
bool const mHasScriptRunnerOwnership;
89-
90-
/// Maps thread object to corresponding connection worker object, to be able to correctly stop and delete them all.
91-
QHash<QThread *, Connection *> mConnections; // Has ownership over threads and connections.
9279
};
9380

9481
}

trikCommunicator/src/connection.cpp

Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -24,38 +24,15 @@
2424

2525
using namespace trikCommunicator;
2626

27-
Connection::Connection()
28-
: mTrikScriptRunner(nullptr)
27+
Connection::Connection(trikScriptRunner::TrikScriptRunner &trikScriptRunner)
28+
: trikKernel::Connection(trikKernel::Protocol::messageLength)
29+
, mTrikScriptRunner(trikScriptRunner)
2930
{
3031
}
3132

32-
void Connection::sendMessage(QString const &message)
33+
void Connection::processData(QByteArray const &data)
3334
{
34-
mSocket->write(message.toLocal8Bit());
35-
}
36-
37-
void Connection::init(int socketDescriptor, trikScriptRunner::TrikScriptRunner *trikScriptRunner)
38-
{
39-
mTrikScriptRunner = trikScriptRunner;
40-
mSocket.reset(new QTcpSocket());
41-
42-
if (!mSocket->setSocketDescriptor(socketDescriptor)) {
43-
qDebug() << "Failed to set socket descriptor" << socketDescriptor;
44-
return;
45-
}
46-
47-
connect(mSocket.data(), SIGNAL(readyRead()), this, SLOT(onReadyRead()));
48-
connect(mSocket.data(), SIGNAL(disconnected()), this, SLOT(disconnected()));
49-
}
50-
51-
void Connection::onReadyRead()
52-
{
53-
if (!mSocket || !mSocket->isValid()) {
54-
return;
55-
}
56-
57-
QByteArray const &data = mSocket->readAll();
58-
QString command = QString::fromUtf8(data.constData());
35+
QString command(data);
5936

6037
if (!command.startsWith("keepalive")) {
6138
// Discard "keepalive" output.
@@ -78,19 +55,13 @@ void Connection::onReadyRead()
7855
} else if (command.startsWith("run")) {
7956
command.remove(0, QString("run:").length());
8057
QString const fileContents = trikKernel::FileUtils::readFromFile(command);
81-
QMetaObject::invokeMethod(mTrikScriptRunner, "run", Q_ARG(QString, fileContents));
58+
QMetaObject::invokeMethod(&mTrikScriptRunner, "run", Q_ARG(QString, fileContents));
8259
emit startedScript(command);
8360
} else if (command == "stop") {
84-
QMetaObject::invokeMethod(mTrikScriptRunner, "abort");
61+
QMetaObject::invokeMethod(&mTrikScriptRunner, "abort");
8562
} else if (command.startsWith("direct")) {
8663
command.remove(0, QString("direct:").length());
87-
QMetaObject::invokeMethod(mTrikScriptRunner, "run", Q_ARG(QString, command));
64+
QMetaObject::invokeMethod(&mTrikScriptRunner, "run", Q_ARG(QString, command));
8865
emit startedDirectScript();
8966
}
9067
}
91-
92-
void Connection::disconnected()
93-
{
94-
qDebug() << "Disconnected.";
95-
thread()->quit();
96-
}

trikCommunicator/src/connection.h

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <QtCore/QObject>
1818
#include <QtCore/QScopedPointer>
1919
#include <QtNetwork/QTcpSocket>
20+
#include <trikKernel/connection.h>
2021

2122
namespace trikScriptRunner {
2223
class TrikScriptRunner;
@@ -33,11 +34,13 @@ namespace trikCommunicator {
3334
/// - stop --- stop current script execution and a robot.
3435
/// - direct:<command> --- execute given script without saving it to a file.
3536
/// - keepalive --- do nothing, used to check the availability of connection.
36-
class Connection : public QObject {
37+
class Connection : public trikKernel::Connection {
3738
Q_OBJECT
3839

3940
public:
40-
Connection();
41+
/// Constructor.
42+
/// @param trikScriptRunner - instance of script runner object.
43+
explicit Connection(trikScriptRunner::TrikScriptRunner &trikScriptRunner);
4144

4245
/// Writes a given message to inner socket.
4346
void sendMessage(QString const &message);
@@ -49,26 +52,11 @@ class Connection : public QObject {
4952
/// Emitted when command to run script directly is received.
5053
void startedDirectScript();
5154

52-
public slots:
53-
/// Creates socket and initializes connection, shall be called when Connection is already in its own thread.
54-
/// @param socketDescriptor - native socket descriptor.
55-
/// @param scriptRunnerWrapper - instance of script runner object.
56-
void init(int socketDescriptor, trikScriptRunner::TrikScriptRunner *trikScriptRunner);
57-
58-
private slots:
59-
/// New data is ready on a socket.
60-
void onReadyRead();
61-
62-
/// Socket is closed for some reason.
63-
void disconnected();
64-
6555
private:
66-
/// Socket for this connection.
67-
QScopedPointer<QTcpSocket> mSocket;
56+
void processData(QByteArray const &data) override;
6857

6958
/// Common script runner object, located in another thread.
70-
/// Does not have ownership.
71-
trikScriptRunner::TrikScriptRunner *mTrikScriptRunner;
59+
trikScriptRunner::TrikScriptRunner &mTrikScriptRunner;
7260
};
7361

7462
}
Lines changed: 17 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2013 Yurii Litvinov
1+
/* Copyright 2013 - 2014 Yurii Litvinov, CyberTech Labs Ltd.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -25,89 +25,38 @@
2525
using namespace trikCommunicator;
2626

2727
TrikCommunicator::TrikCommunicator(trikControl::Brick &brick, QString const &startDirPath)
28-
: mTrikScriptRunner(new trikScriptRunner::TrikScriptRunner(brick, startDirPath))
29-
, mHasScriptRunnerOwnership(true)
28+
: TrikCommunicator(new trikScriptRunner::TrikScriptRunner(brick, startDirPath), true)
3029
{
31-
init();
3230
}
3331

3432
TrikCommunicator::TrikCommunicator(trikScriptRunner::TrikScriptRunner &runner)
35-
: mTrikScriptRunner(&runner)
36-
, mHasScriptRunnerOwnership(false)
33+
: TrikCommunicator(&runner, false)
3734
{
38-
init();
3935
}
4036

41-
TrikCommunicator::~TrikCommunicator()
37+
TrikCommunicator::TrikCommunicator(trikScriptRunner::TrikScriptRunner * const runner, bool hasScriptRunnerOwnership)
38+
: trikKernel::TrikServer([this] () { return connectionFactory(); })
39+
, mTrikScriptRunner(runner)
40+
, mHasScriptRunnerOwnership(hasScriptRunnerOwnership)
4241
{
43-
foreach (QThread *thread, mConnections.keys()) {
44-
thread->quit();
45-
if (!thread->wait(1000)) {
46-
qDebug() << "Unable to stop thread" << thread;
47-
}
48-
}
49-
50-
qDeleteAll(mConnections);
51-
qDeleteAll(mConnections.keys());
52-
53-
if (mHasScriptRunnerOwnership) {
54-
delete mTrikScriptRunner;
55-
}
56-
}
42+
qRegisterMetaType<trikScriptRunner::TrikScriptRunner *>("trikScriptRunner::TrikScriptRunner *");
5743

58-
void TrikCommunicator::startServer(int const &port)
59-
{
60-
if (!listen(QHostAddress::Any, port)) {
61-
qDebug() << "Can not start TrikCommunicator server";
62-
} else {
63-
qDebug() << "TrikCommunicator started";
64-
}
44+
connect(mTrikScriptRunner, SIGNAL(completed(QString)), this, SIGNAL(finishedScript()));
6545
}
6646

67-
void TrikCommunicator::sendMessage(QString const &message)
47+
TrikCommunicator::~TrikCommunicator()
6848
{
69-
for (Connection * const connection : mConnections.values()) {
70-
connection->sendMessage(message);
49+
if (mHasScriptRunnerOwnership) {
50+
delete mTrikScriptRunner;
7151
}
7252
}
7353

74-
void TrikCommunicator::incomingConnection(int socketDescriptor)
75-
{
76-
qDebug() << "New connection, socket descriptor: " << socketDescriptor;
77-
78-
QThread * const connectionThread = new QThread();
79-
80-
connect(connectionThread, SIGNAL(finished()), connectionThread, SLOT(deleteLater()));
81-
connect(connectionThread, SIGNAL(finished()), this, SLOT(onConnectionClosed()));
82-
83-
Connection * const connectionWorker = new Connection();
84-
85-
connect(connectionWorker, SIGNAL(startedDirectScript()), this, SIGNAL(startedDirectScript()));
86-
connect(connectionWorker, SIGNAL(startedScript(QString)), this, SIGNAL(startedScript(QString)));
87-
88-
connectionWorker->moveToThread(connectionThread);
89-
90-
mConnections.insert(connectionThread, connectionWorker);
91-
92-
connectionThread->start();
93-
94-
QMetaObject::invokeMethod(connectionWorker, "init", Q_ARG(int, socketDescriptor)
95-
, Q_ARG(trikScriptRunner::TrikScriptRunner *, mTrikScriptRunner));
96-
}
97-
98-
void TrikCommunicator::onConnectionClosed()
54+
Connection *TrikCommunicator::connectionFactory()
9955
{
100-
QThread * const thread = static_cast<QThread *>(sender());
101-
102-
// Thread shall already be finished here.
103-
delete mConnections.value(thread);
104-
105-
mConnections.remove(thread);
106-
}
56+
auto connection = new Connection(*mTrikScriptRunner);
10757

108-
void TrikCommunicator::init()
109-
{
110-
qRegisterMetaType<trikScriptRunner::TrikScriptRunner *>("trikScriptRunner::TrikScriptRunner *");
58+
connect(connection, SIGNAL(startedDirectScript()), this, SIGNAL(startedDirectScript()));
59+
connect(connection, SIGNAL(startedScript(QString)), this, SIGNAL(startedScript(QString)));
11160

112-
connect(mTrikScriptRunner, SIGNAL(completed(QString)), this, SIGNAL(finishedScript()));
61+
return connection;
11362
}

trikCommunicator/trikCommunicator.pro

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@ DEFINES += TRIKCOMMUNICATOR_LIBRARY
3131
uses(trikScriptRunner trikControl trikKernel)
3232

3333
INCLUDEPATH += \
34-
../trikScriptRunner/include/ \
35-
../trikControl/include/ \
36-
../trikKernel/include/ \
34+
$PWD/../trikScriptRunner/include/ \
35+
$PWD/../trikControl/include/ \
36+
$PWD/../trikKernel/include/ \

trikControl/config.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,4 +215,8 @@ Use it if JCx ports are configured to work as PWM signal generators.
215215

216216
<!-- Settings for gamepad TCP server to communicate with Android "TRIK Gamepad" application -->
217217
<gamepad port="4444" disabled="false" />
218+
219+
<!-- Settings for mailbox server (which enables communication between robots) -->
220+
<mailbox port="8889" disabled="false" />
221+
218222
</config>

trikControl/config_capture.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,4 +214,8 @@ Use it if JCx ports are configured to work as PWM signal capture devices.
214214

215215
<!-- Settings for gamepad TCP server to communicate with Android "TRIK Gamepad" application -->
216216
<gamepad port="4444" disabled="false" />
217+
218+
<!-- Settings for mailbox server (which enables communication between robots) -->
219+
<mailbox port="8889" disabled="false" />
220+
217221
</config>

trikControl/include/trikControl/brick.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <QtCore/QThread>
2020
#include <QtCore/QHash>
2121
#include <QtCore/QStringList>
22+
#include <QtCore/QScopedPointer>
2223

2324
#include "declSpec.h"
2425

@@ -32,6 +33,7 @@
3233
#include "keys.h"
3334
#include "led.h"
3435
#include "lineSensor.h"
36+
#include "mailbox.h"
3537
#include "motor.h"
3638
#include "objectSensor.h"
3739
#include "pwmCapture.h"
@@ -139,6 +141,9 @@ public slots:
139141
/// Returns reference to LED control class.
140142
Led *led();
141143

144+
/// Returns reference to mailbox used to send and receive messages to/from other robots.
145+
Mailbox *mailbox();
146+
142147
/// Starts event loop for script.
143148
void run();
144149

@@ -182,6 +187,7 @@ public slots:
182187
I2cCommunicator *mI2cCommunicator = nullptr; // Has ownership.
183188
Display mDisplay;
184189
Led *mLed = nullptr; // Has ownership.
190+
QScopedPointer<Mailbox> mMailbox;
185191

186192
/// True, if a system is in event-driven running mode, so it shall wait for events when script is executed.
187193
/// If it is false, script will exit immediately.

0 commit comments

Comments
 (0)