1

I built a minimal source/replica direct connection QtRo system: https://codeshare.io/29xj4V
What I would like to achieve is uniquely identify the message coming from the source to be a reply to the one sent from each of the replicas. If rep1 sends "hello source, I'm rep1", I'd like the source to reply back "hello rep1 this is source". I would like to achieve the same with 3 replicas running at a very high and different rate. The issue is on every signal to the source the source replies back to all 3 replicas; the way i'm filtering this is by sending the "id" of the replica in text format then append that id back with the message to check for it inside the replica itself, if it's a match then it accepts the message, otherwise it discards it. Although this seems to be working, there's a big overhead here. My question would be: is there a better way to handle that instead of sending an identifier back and forth? thanks

bardao
  • 914
  • 12
  • 23
  • Why do you point out that there is an overhead? – eyllanesc Feb 14 '19 at 00:38
  • because if one replica is asking for a handshake once every second and another is asking for it 100 times a second, the first replica will get a 100 callback to filter – bardao Feb 14 '19 at 00:56
  • that you can not change it because the idea of the replicas is that they are identical, that is, they will receive the same signals from the source, **that is why they are called replicas**. also compare does not consume any time, for example instead of sending the id as string inside the message could do it as another parameter in the signal, remember that a signal can send several data. – eyllanesc Feb 14 '19 at 01:08

1 Answers1

1

The replicas receive the same signals, there is no way to filter that data from the source side. So the filtering must be done on the client's side, for this you can use an attribute that is the identifier and send that data as a new parameter in the signal instead of sending it within the message. So although there is a lot of calls the cost will be minimal since the if statement does not consume much time.

remoteminimal.rep

class RemoteMinimal
{
    SIGNAL(sendData(const QString &, const QString &));
    SLOT(void printData(const QString &));
    SLOT(void process(const QString &, const QString &));
    SLOT(void triggerSendData());
};

minimalsource.h

#ifndef MINIMALSOURCE_H
#define MINIMALSOURCE_H

#include "rep_remoteminimal_source.h"
#include <QObject>

class MinimalSource : public RemoteMinimalSource
{
    Q_OBJECT
public:
    MinimalSource(QObject *parent = nullptr);
    ~MinimalSource() override;

public slots:
    void printData(const QString& data) override;
    void process(const QString& data, const QString & id) override;
    void triggerSendData() override;

private:
    int m_global_server;
};

#endif // MINIMALSOURCE_H

minimalsource.cpp

#include "minimalsource.h"

MinimalSource::MinimalSource(QObject* parent):
    RemoteMinimalSource (parent), m_global_server(0)
{
}

MinimalSource::~MinimalSource(){}

void MinimalSource::printData(const QString& data)
{
    Q_UNUSED(data);
}

void MinimalSource::process(const QString& data, const QString &id)
{
    m_global_server++;
    emit sendData(data+":"+QString::number(m_global_server), id);
}

void MinimalSource::triggerSendData()
{

}

objects.h

#ifndef OBJECTS_H
#define OBJECTS_H

#include <QObject>
#include "rep_remoteminimal_replica.h"

class QTimer;

class Objects: public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString id READ id WRITE setId)
    Q_PROPERTY(double rate READ rate WRITE setRate)
public:
    explicit Objects(QSharedPointer<RemoteMinimalReplica> ptr);
    ~Objects();
    double rate() const;
    void setRate(double rate);

    QString id() const;
    void setId(const QString &id);

signals:
    void sendData(const QString&, const QString &);

public slots:
    void printData(const QString&, const QString &);
    void process(const QString&);
    void triggerSendData();
    void run();
private:
    int m_global_server;
    QTimer *m_loop;
    double m_rate;
    QString m_id;
    QSharedPointer<RemoteMinimalReplica> reptr;
};

#endif // OBJECTS_H

objects.cpp

#include "objects.h"

#include <QTimer>
#include <QDebug>

Objects::Objects(QSharedPointer<RemoteMinimalReplica> ptr): QObject (Q_NULLPTR),
    m_global_server(0), reptr(ptr)
{
    m_loop = new QTimer(this);
}
Objects::~Objects(){}

void Objects::printData(const QString& data, const QString& id)
{
    if(id == m_id)
        qDebug() << "[" << m_id << "]:" << data;
}

void Objects::process(const QString& data)
{
    emit sendData(data+":processed", m_id);
}

void Objects::run()
{
    connect(m_loop, &QTimer::timeout, this, &Objects::triggerSendData);
    m_loop->setInterval(static_cast<int>(1000/m_rate));
    m_loop->start();
}

QString Objects::id() const
{
    return m_id;
}

void Objects::setId(const QString &id)
{
    m_id = id;
}

double Objects::rate() const
{
    return m_rate;
}

void Objects::setRate(double rate)
{
    m_rate = rate;
}

void Objects::triggerSendData()
{
    m_global_server++;
    emit sendData(QString("test:%1:%2").arg(m_id).arg(m_global_server), m_id);
}

The complete example you find here

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • I was under the assumption that multiple params in signals/slots aren't encouraged / bad practice. Apparently it's not according to https://doc.qt.io/qt-5/signalsandslots.html .thanks for the cleaner solution – bardao Feb 14 '19 at 19:09
  • 1
    @bardao have multiple parameters is not a bad practice, it is actually a good practice because it allows you to differentiate the parameters easily without any processing and Qt uses it a lot (there are a lot of signals that use it) where did you get that is a bad practice? It would be good to indicate is that part of the docs indicates that to be able to discuss better. – eyllanesc Feb 14 '19 at 19:12
  • I read it once somewhere, but as I mentioned in my comment above "apparently it's not" and referenced the doc that says that it's useful :) maybe i needed to rephrase that – bardao Feb 14 '19 at 19:19