2017-01-20 2 views
0

Я использую BGLib в моем Qt приложение для связи через BLE.Qt - Сигнал эмиссии от обратного вызова

В основном потоке работает GUI (sensornode_gui.cpp). Нажимая кнопку pushButton, другой поток начинает сканировать устройства BLE (ble_connection). Я получаю полученную информацию от функции обратного вызова, например void ble_evt_gap_scan_response(const struct ble_msg_gap_scan_response_evt_t *msg). Как я могу испускать сигналы из этой функции обратного вызова для обновления графического интерфейса с некоторыми атрибутами от msg?

main.cpp

#include "sensornode_gui.h" 
#include <QApplication> 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 
    SensorNode_GUI w; 
    w.show(); 
    return a.exec(); 
} 

sensornode_gui.h

#ifndef SENSORNODE_GUI_H 
#define SENSORNODE_GUI_H 

#include <QMainWindow> 
#include <QThread> 
#include "ble_connection.h" 

namespace Ui { 
class SensorNode_GUI; 
} 

class SensorNode_GUI : public QMainWindow 
{ 
    Q_OBJECT 

public: 
    explicit SensorNode_GUI(QWidget *parent = 0); 
    ~SensorNode_GUI(); 
    void printText(std::string s); 

private slots: 
    void on_pushButtonStartScanning_clicked(); 

private: 
    Ui::SensorNode_GUI *ui; 
    QThread *thread; 
    BLE_Connection *ble_worker; 

}; 

#endif // SENSORNODE_GUI_H 

sensornode_gui.cpp

#include "sensornode_gui.h" 
#include "ui_sensornode_gui.h" 

SensorNode_GUI::SensorNode_GUI(QWidget *parent) : 
    QMainWindow(parent), 
    ui(new Ui::SensorNode_GUI) 
{ 
    ui->setupUi(this); 

    thread = new QThread(); 
    ble_worker = new BLE_Connection(); 
    ble_worker->setGUI(this); 

    ble_worker->moveToThread(thread); 
    connect(ble_worker, SIGNAL(valueChanged(QString)), ui->textEdit, SLOT(append(QString))); 
    connect(ble_worker, SIGNAL(workRequested()), thread, SLOT(start())); 
    connect(thread, SIGNAL(started()), ble_worker, SLOT(doWork())); 
} 

SensorNode_GUI::~SensorNode_GUI() 
{ 
    delete thread; 
    delete ble_worker; 

    delete ui; 
} 

void SensorNode_GUI::printText(std::string s){ 
    ui->textEdit->append(QString::fromStdString(s)); 
} 

void SensorNode_GUI::on_pushButtonStartScanning_clicked() 
{ 
    ble_worker->requestWork(); 
} 

ble_connection.h

#ifndef BLE_CONNECTION_H 
#define BLE_CONNECTION_H 

#include <QObject> 
#include <QMutex> 
#include <QDebug> 
#include <QThread> 
#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <windows.h> 
#include "cmd_def.h" 
#include "apitypes.h" 
#include "sensornode_gui.h" 

class SensorNode_GUI; 

class BLE_Connection : public QObject 
{ 
    Q_OBJECT 

public: 
    explicit BLE_Connection(QObject *parent = 0); 
    static void output(uint8,uint8*,uint16,uint8*); 
    int read_message(); 
    void connect(); 
    void disconnect(); 

    void requestWork(); 

private: 
    bool _abort; 
    bool _working; 
    QMutex mutex; 

signals: 
    void workRequested(); 
    void valueChanged(const QString &value); 

public slots: 
    void doWork(); 
}; 

#endif // BLE_CONNECTION_H 

ble_connection.cpp

#include "ble_connection.h" 

volatile HANDLE serial_handle; 
uint8 connection_handle; 

BLE_Connection::BLE_Connection(QObject *parent) : 
    QObject(parent) 
{ 
    char str[80]; 
    snprintf(str,sizeof(str)-1,"\\\\.\\%s","COM3"); 
    //open I/O device 
    ... 

    bglib_output = output; 

} 


void BLE_Connection::setGUI(SensorNode_GUI *g) 
{ 
    gui = g; 
} 

void BLE_Connection::requestWork() 
{ 
    mutex.lock(); 
    _working = true; 
    _abort = false; 
    qDebug()<<"Request worker start in Thread "<<thread()->currentThreadId(); 
    mutex.unlock(); 

    emit workRequested(); 
} 


void BLE_Connection::doWork() 
{ 
    while(true){ 
     read_message(); 
     qDebug() << "Within doWork"; 
     emit valueChanged(QString::fromStdString("Test")); 
    } 
} 

void BLE_Connection::output(uint8 len1,uint8* data1,uint16 len2,uint8* data2) 
{ 
    ... 
} 

int BLE_Connection::read_message() 
{ 
    DWORD rread; 
    const struct ble_msg *apimsg; 
    struct ble_header apihdr; 
    unsigned char data[256];//enough for BLE 
    //read header 

    if(!ReadFile(serial_handle, 
       (unsigned char*)&apihdr, 
       4, 
       &rread, 
       NULL)) 
     { 
      return GetLastError(); 
     } 
    if(!rread)return 0; 
    //read rest if needed 
    if(apihdr.lolen) 
    { 
     if(!ReadFile(serial_handle, 
        data, 
        apihdr.lolen, 
        &rread, 
        NULL)) 
      { 
       return GetLastError(); 
      } 
    } 
    apimsg=ble_get_msg_hdr(apihdr); 
    if(!apimsg) 
    { 
     printf("ERROR: Message not found:%d:%d\n",(int)apihdr.cls,(int)apihdr.command); 
     return -1; 
    } 
    apimsg->handler(data); 

    return 0; 
} 


//=============FUNCTIONS FOR HANDELING EVENTS AND RESPONSES==================== 


void ble_evt_gap_scan_response(const struct ble_msg_gap_scan_response_evt_t *msg) 
{ 
    int i; 
    std::string buffAsStdStr; 
    char buff[100]; 
    char *name = NULL; 
    for(i=0;i<6;i++){ 
     snprintf(buff, sizeof(buff), "%02x%s",msg->sender.addr[5-i],i<5?":":""); 
     buffAsStdStr += buff; 
    } 


    snprintf(buff, sizeof(buff), "\t%d",msg->rssi); 
    buffAsStdStr += buff; 
    //HERE I WANT TO EMIT THE SIGNAL VALUECHANGED 
    //emit valueChanged(QString::fromStdString(buffAsStdStr)); 

    free(name); 
} 

Спасибо заранее.

ответ

0

Вы можете объявить глобальную переменные в "ble_connection.h"

static bool messageCaptured; 
static std::string message; 

в BLE_Connection класса значения инициализации Constructer является false;

messageCaptured = false; 

В настоящее время; если ваша функция обратного вызова вызывается в любое время, вы должны установить

messageCaptured = true; 

в вашей функции обратного вызова.

Теперь вы можете излучать Захваченное сообщение в вашем DoWork функцию

void BLE_Connection::doWork() 
{ 
    while(true){ 
     read_message(); 
     qDebug() << "Within doWork"; 
     if(messageCaptured){ 
      /// do your process 
      emit valueChanged(QString::fromStdString(message); 
     messageCaptured = false; 
     }    
    } 
} 

в обратном вызове сообщении захвата функции, если захват proccess закончен до того

void ble_evt_gap_scan_response(const struct 
ble_msg_gap_scan_response_evt_t *msg) 
    { 
     int i; 
     std::string buffAsStdStr; 
     char buff[100]; 
     char *name = NULL; 
     for(i=0;i<6;i++){ 
      snprintf(buff, sizeof(buff), "%02x%s",msg->sender.addr[5-i],i<5?":":""); 
      buffAsStdStr += buff; 
     } 


     snprintf(buff, sizeof(buff), "\t%d",msg->rssi); 
     buffAsStdStr += buff; 

     // if message captured before you can take it 
     if(!messageCaptured){ 
      message = buffAsStdStr; 
      messageCaptured = true; 
     } 

     free(name); 
    } 
1

я столкнулся с той же проблемой при использовании другая библиотека. Я решил эту проблему, обернув класс библиотеки моим (CameraWrapper) и поместив объект этого класса в свой класс (MeasurementSystem), унаследованный от QObject. Поэтому, когда этот родительский класс создает оболочку для класса, который отправляет обратный вызов, он передает указатель на себя QObject *. Child chass (CameraWrapper) хранит этот указатель и отправляет его в обратном вызове.

выглядит так:

MeasurementSystem.ч

#ifndef MEASUREMENTSYSTEM_H 
#define MEASUREMENTSYSTEM_H 
#include <vector> 
#include "camerawrapper.h" 
#include "qobject.h" 

class MeasurementSystem : public QObject 
{ 
    Q_OBJECT 
public: 
    MeasurementSystem(); 
    enum CamAlign {caTopInner = 0,caTopOuter,caBottomInner,caBottomOuter,caSide}; //cameras alignment in optical sysem 


    void Connect(); 
    void Disconnect(); 
signals: 
    void sigDataReceived(int,std::vector<int>); 

private: 
    std::vector<CameraWrapper*> _cams; 
    friend void DataReceived(QObject * Sender, int &, std::vector<int>&);  //callback function for receiving data from any camera 
}; 

#endif // MEASUREMENTSYSTEM_H 

MeasurementSystem.cpp

#include "measurementsystem.h" 
#include <QApplication> 
MeasurementSystem::MeasurementSystem() 
{ 
    QString path = QApplication::applicationDirPath(); 
    _cams.push_back(new CameraWrapper(this,*DataReceived,(path+"/CameraSettings/Ranger D50 TopInner.icx").toStdString(),"192.168.1.11","CamTopInner",caTopInner)); 
    _cams.push_back(new CameraWrapper(this,*DataReceived,(path+"/CameraSettings/Ranger D50 TopInner.icx").toStdString(),"192.168.1.12","CamTopOuter",caTopOuter)); 
    _cams.push_back(new CameraWrapper(this,*DataReceived,(path+"/CameraSettings/Ranger D50 TopInner.icx").toStdString(),"192.168.1.13","CamBottomInner",caBottomInner)); 
    _cams.push_back(new CameraWrapper(this,*DataReceived,(path+"/CameraSettings/Ranger D50 TopInner.icx").toStdString(),"192.168.1.14","CamBottomOuter",caBottomOuter)); 
    _cams.push_back(new CameraWrapper(this,*DataReceived,(path+"/CameraSettings/Ranger D50 TopInner.icx").toStdString(),"192.168.1.15","CamSide",caSide)); 
} 

void MeasurementSystem::Connect() 
{ 
    foreach (CameraWrapper* cam, _cams) 
    { 
     cam->Connect(); 
    } 
} 

void MeasurementSystem::Disconnect() 
{ 
    foreach (CameraWrapper* cam, _cams) 
    { 
     cam->Disconnect(); 
    } 
} 

void DataReceived(QObject * Sender, int & CamId, std::vector<int> & Profile) 
{ 
    MeasurementSystem * CamSys = reinterpret_cast<MeasurementSystem*>(Sender); 
    emit CamSys->sigDataReceived(CamId,Profile); 
} 

CameraWrapper.h

#ifndef CAMERAWRAPPER_H 
#define CAMERAWRAPPER_H 

#include <QObject> 
#include <icamerasystem.h> 
#include <icamerasystemsubscriber.h> 
#include <icon_error.h> 
#include <windows.h> 
typedef void CallbackDataT(QObject*,int&,std::vector<int>&); 

class CameraWrapper : public icon::ICameraSystemSubscriber, public icon::ErrorHandler 
{ 
public: 
    CameraWrapper(QObject * Parent, CallbackDataT callback, std::string ConfigFileIcx, std::string IpAddr, std::string Name, int Id = -1); 
    void Connect(); 
    void Disconnect(); 
    int AccessData(const icon::IconBuffer *buffer, std::string& resultString); 
    virtual void onData(const icon::IconBuffer * buffer, const icon::IGrabStatus * status); 
    virtual void onError(const icon::IError &error){}; 
    virtual void onStateChanged(const icon::IState * state){}; 

private: 
    //IconAPI objects 
    icon::ErrorCode _res;           //result of some camera operations 
    icon::ICameraSystem * _camSystem;        //the camera itself 

    //callbacks 
    void (*_callbackData)(QObject*,int&, std::vector<int>&);  //called when buffer is parsed 

    //proprieties 
    int _id;              //camera identifier 
    std::string _name;            //camera name 

    //parent 
    QObject * _parent; 
}; 
#endif // CAMERAWRAPPER_H 

CameraWrapper.cpp

#include "camerawrapper.h" 
#include <qdebug.h>    //qdebug() 


CameraWrapper::CameraWrapper(QObject * Parent, CallbackDataT Callback, std::string ConfigFileIcx, std::string IpAddr, std::string Name, int Id): 
    _parent(Parent), _callbackData(Callback), _id(Id), _name(Name) 
{ 
    //Create the camera system object 
    _camSystem = icon::createCameraSystem(icon::ICameraSystem::ETHERNET_CAMERA, Name.c_str()); 
    //smth else 
} 

void CameraWrapper::Connect() 
{ 
    _res = _camSystem->subscribe(*this); 
    _res = _camSystem->connect(); 
    _res = _camSystem->start(); 
} 

void CameraWrapper::Disconnect() 
{ 
    _res = _camSystem->stop(); 
    _res = _camSystem->disconnect(); 
} 

int CameraWrapper::AccessData(const icon::IconBuffer * buffer, std::string& resultString) 
{ 
    std::vector<int> vProfile; 
    // Loop through all components in the buffer 
    const icon::DataFormat *dataFormat = buffer->getDataFormat(); 
    for (unsigned int compIndex = 0; compIndex < dataFormat->numComponents(); compIndex++) 
    { 
     // Get handle to component. 
     const icon::Component *component = dataFormat->getComponent(compIndex); 

     // Loop through all subcomponents of the component. 
     for (unsigned int subCompIndex = 0; subCompIndex < component->numSubComponents(); subCompIndex++) 
     { 
      const icon::SubComponent *subComponent = component->getSubComponent(subCompIndex); 
      unsigned int subCompWidth = subComponent->getWidth(); 

      const unsigned short *wordData; 
      unsigned short wordValue; 
      buffer->getReadPointer(component->getName().c_str(), subComponent->getName().c_str(), 0, wordData); 
      //rsv:push current scan into vector(profile view) 
      for (size_t i = 0; i < subCompWidth; i++) 
      { 
       wordValue = *(wordData + i); 
       vProfile.push_back(static_cast<int>(wordValue)); 
      } 
     } 
    } 
    //callback is here 
    _callbackData(_parent,_id,vProfile); 
    return 0; 
} 

void CameraWrapper::onData(const icon::IconBuffer * buffer, const icon::IGrabStatus * status) 
{ 
    if (!(status->allOK())) 
    { 
     return; 
    } 
    AccessData(buffer, outString); 
} 
Смежные вопросы