1
votes

I am trying to implement custom QIODevice.

I have detector which will be using 2 tcp sockets, one for sending commands and receiving responses, the other one just for reading data.

How should I do it? I tried to create my class, derive it from QIODevice and implement pure virtual methods, but I faced some dificulties.

I have the following piece of code:

class Detector : public QIODevice {
    Q_OBJECT
    Q_DISABLE_COPY(MasterDevice)

public:
    enum CHANNEL_TYPE {
        DataChannel,
        ControlChannel
    };

private:
    QTcpSocket *controlDevice;
    QTcpSocket *dataDevice;

    QHostAddress hostAddress;

    quint16 dataPort;
    quint16 controlPort;

public:
    explicit Detector(QObject *parent, QHostAddress hostAddress, quint16 dataPort, quint16 controlPort)
        : QIODevice(parent)
        , hostAddress(hostAddress)
        , dataPort(dataPort)
        , controlPort(controlPort)
    {
        controlDevice = new QTcpSocket(this);
        connect(controlDevice, SIGNAL(readyRead()),this, SLOT(controlChannelReadReady()));

        dataDevice = new QTcpSocket(this);
        connect(dataDevice, SIGNAL(readyRead()),this, SLOT(dataChannelReadReady()));
    }

    virtual ~Detector() {}

    bool open(OpenMode mode) override {
        QIODevice::open(mode);

        controlDevice->connectToHost(hostAddress, controlPort, QTcpSocket::ReadWrite);
        dataDevice->connectToHost(hostAddress, dataPort, QTcpSocket::ReadOnly);
    }

    qint64 readData(char *data, qint64 maxSize) override {
        QTcpSocket *socket;

        switch ( currentReadChannel() ) {
        case DataChannel:
            socket = dataDevice;
            break;
        case ControlChannel:
            socket = controlDevice;
            break;
        default:
            return -1;
            break;
        }

        return socket->read(data, maxSize);
    }

    qint64 writeData(const char * data, qint64 maxSize) override {
        QTcpSocket *socket;

        switch ( currentWriteChannel() ) {
        case DataChannel:
            socket = dataDevice;
            break;
        case ControlChannel:
            socket = controlDevice;
            break;
        default:
            return -1;
            break;
        }

        return socket->write(data, maxSize);
    }

private slots:
    void controlChannelReadReady() {
        emit channelReadyRead(ControlChannel);
    }

    void dataChannelReadReady() {
        emit channelReadyRead(DataChannel);
    }
};

So basically my question is, how do I handle those channels, because for example from qt documentation I have this

bool QIODevice::open(OpenMode mode)

Opens the device and sets its OpenMode to mode. Returns true if successful; otherwise returns false. This function should be called from any reimplementations of open() or other functions that open the device.

So I have to invoke it from my overrided Open() method, but I looked at the implementation of this method and I saw that it is setting the number of channels to 1. How can I change this number?

What for are those buffers that I am inheriting from QIODevice, how should I use them?

Am I missing the point of creating custom QIODevice? If so, please explain it to me.

1
You might get inspiration from QProcess, which provides interface for stdin, stdout and stderr... and is a QIODevice subclass too.hyde
Thank you for your comment, I will take a look at this.notfound404

1 Answers

0
votes

Unlikely you need to subclass QIODevice here, just design and implement interface with semantic you need, e.g.:

sendCommand();
responseReceived();
dataReady();
...
etc

QIODevice is a common interface for reading/writing byte streams from/to different sources like files, sockets, serial ports, etc