I am using the BGLib in my Qt application to communicate over BLE.
In the main thread the GUI is running (sensornode_gui.cpp). By clicking on a pushButton a different thread starts to scan for BLE devices (ble_connection). I get the resulting information from a callback function such as void ble_evt_gap_scan_response(const struct ble_msg_gap_scan_response_evt_t *msg)
. How can I emit signals from that callback function to update the GUI with some attributes from msg
for example?
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);
}
Thanks in advance.
You May declare a global variable in "ble_connection.h"
static bool messageCaptured;
static std::string message;
in BLE_Connection class constructer initialization value is false
;
messageCaptured = false;
Now; if your Callback function is called any time you should set
messageCaptured = true;
in your CallbackFunction.
Now you can emit Captured Message in your doWork function
void BLE_Connection::doWork()
{
while(true){
read_message();
qDebug() << "Within doWork";
if( messageCaptured ){
/// do your process
emit valueChanged(QString::fromStdString(message);
messageCaptured = false;
}
}
}
in callback function capture message if capturing proccess is finished before
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);
}