Seite 1 von 1

Daten aus einer Klasse in mehreren Klassen verfügbar halten

Verfasst: 5. März 2015 15:42
von Bohnsopp
Hallo,

ich habe ein kleines Verständigungsproblem.
Ich komme eigentlich aus der Mikrocontroller Ecke und kann diese Dinger auch mit C programmieren.

Aus Interesse arbeite ich mich in C++ inkl. QT und Boos ein.

Ich habe ein Messgerät, welches ich per serieller Schnittstelle per RS232 anspreche. Die Kommunikation sowie das Zurücklesen und verarbeiten der Daten funktioniert dank QT und Boos auch schon sehr gut.
Jetzt würde ich gerne hierfür eine Windows-DLL für Matlab erstellen. Einfache DLLs kann ich auch schon mittels "Extern _C" erstellen.

Ich habe jetzt aber ein kleines C++ Projekt mittels Klassen in denen die
(1). RS232 konfiguriert wird (settings.cpp)
(2). Die RS232 geöffnet wird (serial.cpp)
(3). Eine Abfrage generiert wird und an das Messgerät gesendet wird (console.cpp)
(4). Die empfangenen Daten in einem Ringpuffer mittels Boost gespeichert und sortiert werden (console.cpp)
(5). Die Daten nach seinem Protokoll zerschnitten werden

Über meine Main Funktion (main.c) kann ich auch via Matlab die Kommunikation mit RS232 aufbauen (prüfe ich mit Portmon.exe) und empfange Daten.

Nun meine Frage,
wie kann ich in der main.c auf die Messdaten die in der Klasse "Protocol" gespeichert sind zugreifen?
Ein Rückgabewert bekomme ich nicht, da die RS232 mittels Signal/Slots die empfangenen Daten verarbeitet?

Über die Rückgabe nach Matlab habe ich mir noch nicht wirklich Gedanken gemacht, aber mittels Callib und Pointer habe ich schon ein Array zurücklesen können. Ich denke die Messwerte müsste ich auf ähnliche Weise zurücklesen können.

Gruß

protocol.h

Code: Alles auswählen

class Protocol
{
public:
 ....
    struct Messwerte {
        int status_x;
        int status_y;
        QString d_x;
        QString d_y;
    };
    // Memberfunction
    Messwerte localmw() const;

    Protocol *protocol;

private:
    Messwerte currentMW;
    void updateMesswerte(QString dx, QString dy, int status_x, int status_y);

};

main.cpp

Code: Alles auswählen

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    int i;
    Seriel messgeraet;

    int status_x=0;
    int status_y=0;

    i = messgeraet.AskHardware();
    //i = fb.AskHardware(status_x, status_y);

    a.exec();

    qDebug() << "zurück zu Main";

    // wie komme ich an die Werte aus der Klasse
    // protocol.h??


    return i;
}

Re: Daten aus einer Klasse in mehreren Klassen verfügbar hal

Verfasst: 5. März 2015 15:43
von Bohnsopp
console.h

Code: Alles auswählen

#ifndef CONSOLE_H
#define CONSOLE_H

#include <QString>
#include <QObject>
#include <boost/circular_buffer.hpp>

class Console: public QObject
{
    Q_OBJECT

public:
    explicit Console(QObject *parent = 0);
    ~Console();

signals:
    void getData(const QByteArray &data);

public:
    void putData(const QByteArray &data);
    void setLocalEchoEnabled(bool set);
    int bcc_calc(QString data);

public slots:
    void GMD();

private:
    bool localEchoEnabled;
    int cnt_console = 0;

    boost::circular_buffer<char> buffer;

    QString outputString;
    QString BCC;

    int stx_active = 0;
    int etx_active = 1;
    int read_bcc = 0;

};

#endif // CONSOLE_H
console.cpp

Code: Alles auswählen

#include <QDebug>
#include <boost/circular_buffer.hpp>
#include <QCoreApplication>
#include "console.h"
#include "protocol.h"

typedef boost::circular_buffer<char> CircularBuffer;

Console::Console(QObject *parent) : QObject(parent)
{
    buffer.set_capacity(100);
}

Console::~Console()
{
    buffer.clear();
}


void Console::putData(const QByteArray &data)
{
    //qDebug() << "Antwort: " << QString(data);
    //qDebug() << "Größe von Data: " << data.size();

    // Daten in den Buffer schreiben
    for (QByteArray::const_iterator it=data.begin(); it != data.end(); ++it)
    {
        char aa = *it;
        buffer.push_back(aa);
    }

    QString Input;
    Input.append(buffer[0]);
    QString Test = QString::fromLatin1(Input.toLatin1().toHex());

    // STX = Anfang finden
    if (stx_active == 0){
        while (Test != "02") {
            buffer.pop_front();
            Input = (buffer[0]);
            Test = (QString::fromLatin1(Input.toLatin1().toHex()));
        }
    }
    if (Test == "02") {
        stx_active = 1;
    }

    // cnt sorg dafür, dass der buffer nicht leerläuft
    int cnt = buffer.size();
    while (Test != "03" && cnt > 1) {
        --cnt;
        // 2. inkl ETX
        buffer.pop_front();
        outputString.append(buffer[0]);
        Input = (buffer[0]);
        Test = (QString::fromLatin1(Input.toLatin1().toHex()));
    }

    // ETX finden
    if (Test == "03") {
        stx_active = 0;
        buffer.pop_front();
        Input = (buffer[0]);
        BCC = (QString::fromLatin1(Input.toLatin1().toHex()));
        buffer.pop_front();
        bool ok;

        // BCC berechnen
        if (BCC.toInt(&ok, 16) == bcc_calc(outputString)) {
            Protocol::GMD(outputString);
            // Threads beenden
            QCoreApplication::quit();
        }

    } else {
        BCC.clear();
    }


    if (stx_active == 0) {
        outputString.clear();
    }
}


void Console::GMD() {
    QByteArray msg;

    // GMD 02 47 4D 44 03 4D
    msg.append(0x02);
    msg.append(0x47);
    msg.append(0x4D);
    msg.append(0x44);
    msg.append(0x03);
    quint8 bcc = bcc_calc(msg.mid(1,4));
    msg.append(bcc);

    // Feuere anfrage an RS232
    emit getData(msg);
}

int Console::bcc_calc(QString data) {

    int bcc=0;
    bool ok;
    for (QString::iterator it= data.begin(); it != data.end(); ++it)
    {
        QString tmp1, tmp2;
        tmp1.append(*it);
        tmp2 = QString::fromLatin1(tmp1.toLatin1().toHex());
        bcc ^= tmp2.toInt(&ok, 16);
    }
    if (bcc < 0x20) {
        bcc += 0x20;
    }
    return bcc;
}

Re: Daten aus einer Klasse in mehreren Klassen verfügbar hal

Verfasst: 5. März 2015 15:46
von Bohnsopp
protocol.h

Code: Alles auswählen

#ifndef PROTOCOL_H
#define PROTOCOL_H

#include <QPlainTextEdit>
#include <QString>

class Protocol
{
public:
    Protocol();
    ~Protocol();

    static void GMD(QString data);

    struct Messwerte {
        int status_x;
        int status_y;
        QString d_x;
        QString d_y;
    };

    // Memberfunction
    Messwerte localmw() const;

    Protocol *protocol;

private:
    Messwerte currentMW;
    void updateMesswerte(QString dx, QString dy, int status_x, int status_y);

};

#endif // PROTOCOL_H
protcol.cpp

Code: Alles auswählen


#include <QtCore/QDebug>
#include <QtCore/QString>
#include "protocol.h"
#include "main.h"

Protocol::Protocol()
{
    currentMW.status_x = 0;
    currentMW.status_y = 0;
    currentMW.d_x = "+-0";
    currentMW.d_y = "-+0";
}

Protocol::~Protocol() { }

void Protocol::GMD(QString data){
    qDebug() << "Befehl" << data.mid(0,3);

    qDebug() << "Pos X" << data.mid(3,8);
    qDebug() << "Dim X" << data.mid(11,7);
    qDebug() << "Status X" << data.mid(18,3);

    qDebug() << "Pos Y" << data.mid(32,8);
    qDebug() << "Dim Y" << data.mid(40,7);
    qDebug() << "Status Y" << data.mid(47,3);

    qDebug() << "--------------------";

    Protocol *alpha;
    alpha = new Protocol;
    Messwerte p = alpha->localmw();
    alpha->updateMesswerte(data.mid(03,8), data.mid(32,8), data.mid(18,3).toInt(), data.mid(47,3).toInt());
    p = alpha->localmw();

    qDebug() << "/////////////////////////";
    qDebug() << "p.d_x" << p.d_x;
    qDebug() << "p.d_y" << p.d_y;
    qDebug() << "status_x" << p.status_x;
    qDebug() << "status_y" << p.status_y;
    qDebug() << "/////////////////////////";
}

void Protocol::updateMesswerte(QString dx, QString dy, int status_x, int status_y)
{
    currentMW.d_x = dx;
    currentMW.d_y = dy;
    currentMW.status_x = status_x;
    currentMW.status_y = status_y;
}

Protocol::Messwerte Protocol::localmw() const
{
    return currentMW;
}

serial.h

Code: Alles auswählen

#ifndef SERIEL_H
#define SERIEL_H

#include <QtCore/QtGlobal>
#include <QtSerialPort/QSerialPort>

#ifndef MY_API
//#define MY_API extern "C" __declspec(dllexport)
#define MY_API__declspec(dllexport)
#endif

#define MATHFUNCSDLL_EXPORTS

#ifdef MATHFUNCSDLL_EXPORTS
//#define MATHFUNCSDLL_API __declspec(dllexport)
#define MATHFUNCSDLL_API extern "C" __declspec(dllexport)
#else
#define MATHFUNCSDLL_API __declspec(dllimport)
#endif

class Console;
class Settings;
class Protocol;

class Seriel: public QObject
{
    Q_OBJECT

signals:
    void getData(const QByteArray &data);

public:
    explicit Seriel(QObject *parent = 0);
    ~Seriel();

private slots:
    void writeData(const QByteArray &data);

public slots:
    void openSerialPort();
    void closeSerialPort();
    void readData();

    void handleError(QSerialPort::SerialPortError error);
    int AskHardware(void);

private:
    Console *console;
    QSerialPort *serial;
    Settings *setting;
    Protocol *protocol;
};

#endif // SERIEL_H


serial.cpp

Code: Alles auswählen

#include <QtSerialPort/QSerialPort>
#include <QDebug>

#include "console.h"
#include "settings.h"
#include "protocol.h"
#include "serial.h"
#include "protocol.h"

Seriel::Seriel(QObject *parent) : QObject(parent)
{
    console = new Console;
    serial = new QSerialPort(this);

    connect(serial, SIGNAL(error(QSerialPort::SerialPortError)), this,
            SLOT(handleError(QSerialPort::SerialPortError)));
    connect(serial, SIGNAL(readyRead()), this, SLOT(readData()));

    connect(console, SIGNAL(getData(QByteArray)), this, SLOT(writeData(QByteArray)));
}

Seriel::~Seriel(){}

void Seriel::writeData(const QByteArray &data)
{
    serial->write(data);
    qDebug() << "written" << serial->bytesToWrite();
}


void Seriel::openSerialPort()
{

    setting = new Settings;
    Settings::SettingsCom p = setting->localsettings();

    setting->updateSettings();
    p = setting->localsettings();

    //setting->
    p.name = "COM2";
    p = setting->localsettings();
    qDebug() << "p.name" << p.name;

    serial->setPortName(p.name);
    serial->setBaudRate(p.baudRate);
    serial->setDataBits(p.dataBits);
    serial->setParity(p.parity);
    serial->setStopBits(p.stopBits);
    serial->setFlowControl(p.flowControl);



    if (serial->open(QIODevice::ReadWrite)) {
        qDebug() << "serial connected";
    } else {
        qDebug() << "Fehler" << serial->errorString();
    }
}

void Seriel::closeSerialPort()
{
    serial->close();
}


void Seriel::readData()
{
    QByteArray data = serial->readLine();
    console->putData(data);
}

void Seriel::handleError(QSerialPort::SerialPortError error)
{
    if (error == QSerialPort::ResourceError) {
        qDebug() << "handle Error:" << serial->errorString();
        closeSerialPort();
    }
}

int Seriel::AskHardware(void) {

    int i=0;

    openSerialPort();
    console->GMD();

    if ( serial->isOpen()) {
        i++;
    }

    return i;
}



settings.h

Code: Alles auswählen

#ifndef SETTINGS_H
#define SETTINGS_H

#include <QObject>
#include <QtSerialPort/QSerialPortInfo>
#include <QtSerialPort>
#include <QSerialPort>

class Settings
{
public:
    Settings();
    ~Settings();


public:
    struct SettingsCom {
        QString name;
        qint32 baudRate;
        QString stringBaudRate;
        QSerialPort::DataBits dataBits;
        QString stringDataBits;
        QSerialPort::Parity parity;
        QString stringParity;
        QSerialPort::StopBits stopBits;
        QString stringStopBits;
        QSerialPort::FlowControl flowControl;
        QString stringFlowControl;
        bool localEchoEnabled;
    };

    SettingsCom localsettings() const;

//private:
      void updateSettings(void);

private:
    SettingsCom currentSettings;


};

#endif // SETTINGS_H


settings.cpp

Code: Alles auswählen

#include "settings.h"

Settings::Settings()
{
    currentSettings.name = "COM2";
    currentSettings.baudRate = QSerialPort::Baud115200;
    currentSettings.dataBits = QSerialPort::Data8;
    currentSettings.parity   = QSerialPort::NoParity;
    currentSettings.stopBits = QSerialPort::OneStop;
    currentSettings.flowControl = QSerialPort::NoFlowControl;
}

Settings::~Settings()
{

}

void Settings::updateSettings(void) {
    currentSettings.name = "COM4";
}

Settings::SettingsCom Settings::localsettings() const
{
    return currentSettings;
}

main.cpp

Code: Alles auswählen

#ifndef MAIN_H
#define MAIN_H
#define MY_API extern "C" __declspec(dllexport)

#include "protocol.h"

MY_API int main(int argc, char *argv[]);


#endif // MAIN_H



Re: Daten aus einer Klasse in mehreren Klassen verfügbar hal

Verfasst: 13. März 2015 11:37
von Christian81
Ich befürchte, dass es nicht so ohne weiteres möglich ist, ein Qt-Programm, welches dringender Weise eine Eventloop benötigt, in Matlab einzubauen. Zumindest nicht ohne etwas mehr Kenntnisse von Qt.
Zugriff auf Daten bekommt man normalerweise mit get-Funktionen welche die Werte zurückliefern. Aber das sind eher C++ Grundlagen -> C++ Buch wäre hier definitiv erst einmal nötig.