maratk1n
11th May 2017, 17:42
Hi all!
Small fragment of the project:
mainwindow.cpp
//constructor
QThread *thread = new QThread;
//thread = new QThread(this);
valve = new Valve(7);
pressureSensors = new PressureSensors;
valve->moveToThread(thread);
pressureSensors->moveToThread(thread);
connect(pressureSensors, SIGNAL(remoteSignal(bool)), this, SLOT(readPressureSensors(bool)));
connect(valve, SIGNAL(remoteSignal(bool)), this, SLOT(updateStates(bool)));
connect(this, SIGNAL(valveOpen(int)), valve, SLOT(open(int)));
connect(this, SIGNAL(valveClose(int)), valve, SLOT(close(int)));
connect(valve, SIGNAL(valveStatus(int,bool,bool)), this, SLOT(valveIndicate(int,bool,bool)));
QTimer *sensorsReadTimer = new QTimer(this);
sensorsReadTimer->moveToThread(thread);
connect(sensorsReadTimer, SIGNAL(timeout()), pressureSensors, SLOT(readSensors()));
sensorsReadTimer->start(100);
QTimer *valvesReadTimer = new QTimer(this);
valvesReadTimer->moveToThread(thread);
connect(valvesReadTimer, SIGNAL(timeout()), valve, SLOT(getAllStates()));
valvesReadTimer->start(100);
thread->start();
//***//
void MainWindow::openValve(int id)
{
valveButton[id]->setEnabled(false);
//valve->open(id);
emit valveOpen(id);
}
protocol.cpp
bool Valve::open(int id)
{
QByteArray arr;
arr.resize(7);
arr[0] = 0xAB;
arr[1] = 0x01;
arr[2] = 0x02;
arr[3] = 0x02;
arr[4] = id + 1;
arr[5] = 0xFF;
arr[6] = 0x00 - arr[1] - arr[2] - arr[3] - arr[4] - arr[5];
QByteArray response = ComPort::get().requestResponse(arr);
if(response[0] == arr[0])
{
qDebug() << "клапан №: " << id << " открыт!";
valveState[id] = true;
emit valveStatus(id, 1, 1);
return 1;
}
emit valveStatus(id, 1, 0);
return 0;
}
bool Valve::getAllStates()
{
QByteArray arr;
arr.resize(5);
arr[0] = 0xAB;
arr[1] = 0x01;
arr[2] = 0x00;
arr[3] = 0x00;
arr[4] = 0x00 - arr[1] - arr[2] - arr[3];
QByteArray response = ComPort::get().requestResponse(arr);
if(response[0] == arr[0])
{
QBitArray bitStates(16);
for (int i = 4; i<6; i++)
for (int b = 0; b<8; b++)
bitStates.setBit((i-4)*8+b, response.at(i)&(1<<b));
for (int i = 0; i < valveState.size(); i++)
valveState[i] = bitStates[i];
for (uint i = 0; i < sizeof(fittingState); i++)
fittingState[i] = bitStates[i+8];
emit remoteSignal(1);
return 1;
}
emit remoteSignal(0);
return 0;
}
//***//
QByteArray ComPort::requestResponse(const QByteArray &data)
{
mutex->lock();
QByteArray readBuf;
qDebug() << "-------------------------";
if(!serial->isOpen())
open();
int attempts = 1;
while (attempts <= REQATTEMPTS) { //3 попытки
if (serial->isWritable())
{
serial->write(data);
qDebug() << "Попытка № " << attempts;
qDebug() << "ЗапроÑ: " << data.toHex();
while (serial->waitForReadyRead(WAITFORREADY)) {
readBuf += serial->readAll();
if (crcCheck(readBuf) && data[2] == readBuf[2] ){ //еÑли CRC и команда ÑошлиÑÑŒ -- уÑпех!
qDebug() << "Ответ: " << readBuf.toHex();
responseCount++;
qDebug() << "Кол-во запроÑов: " << responseCount;
qDebug() << "Кол-во таймаутов: " << timeoutCount;
float percent = timeoutCount * 100;
percent = percent / responseCount;
qDebug() << "Процент коÑÑков: " << QString::number(percent, 'f', 3) << "%";
close();
mutex->unlock();
return readBuf;
}
}
//qDebug() << readBuf.toHex();
readBuf.clear();
qDebug() << "Таймаут...";
timeoutCount++;
close();
open();
attempts++;
}
else
{
qDebug() << "Порт " << portName << " не пишетÑÑ!";
close();
mutex->unlock();
return 0;
}
}
close();
mutex->unlock();
return 0;
}
If I do not put valve and pressureSensors in a separate thread, then everything works more or less normally.
But if I put them in a separate thread, the valve opening slot works very late (~ 10 seconds, as lucky). As I understand it, this is because the signal is emitted from the main thread, and the slot is in the other thread. Is it possible to build a queue?
Slot open from Valve class must have the highest priority.
Thankful in advance for the help!
Small fragment of the project:
mainwindow.cpp
//constructor
QThread *thread = new QThread;
//thread = new QThread(this);
valve = new Valve(7);
pressureSensors = new PressureSensors;
valve->moveToThread(thread);
pressureSensors->moveToThread(thread);
connect(pressureSensors, SIGNAL(remoteSignal(bool)), this, SLOT(readPressureSensors(bool)));
connect(valve, SIGNAL(remoteSignal(bool)), this, SLOT(updateStates(bool)));
connect(this, SIGNAL(valveOpen(int)), valve, SLOT(open(int)));
connect(this, SIGNAL(valveClose(int)), valve, SLOT(close(int)));
connect(valve, SIGNAL(valveStatus(int,bool,bool)), this, SLOT(valveIndicate(int,bool,bool)));
QTimer *sensorsReadTimer = new QTimer(this);
sensorsReadTimer->moveToThread(thread);
connect(sensorsReadTimer, SIGNAL(timeout()), pressureSensors, SLOT(readSensors()));
sensorsReadTimer->start(100);
QTimer *valvesReadTimer = new QTimer(this);
valvesReadTimer->moveToThread(thread);
connect(valvesReadTimer, SIGNAL(timeout()), valve, SLOT(getAllStates()));
valvesReadTimer->start(100);
thread->start();
//***//
void MainWindow::openValve(int id)
{
valveButton[id]->setEnabled(false);
//valve->open(id);
emit valveOpen(id);
}
protocol.cpp
bool Valve::open(int id)
{
QByteArray arr;
arr.resize(7);
arr[0] = 0xAB;
arr[1] = 0x01;
arr[2] = 0x02;
arr[3] = 0x02;
arr[4] = id + 1;
arr[5] = 0xFF;
arr[6] = 0x00 - arr[1] - arr[2] - arr[3] - arr[4] - arr[5];
QByteArray response = ComPort::get().requestResponse(arr);
if(response[0] == arr[0])
{
qDebug() << "клапан №: " << id << " открыт!";
valveState[id] = true;
emit valveStatus(id, 1, 1);
return 1;
}
emit valveStatus(id, 1, 0);
return 0;
}
bool Valve::getAllStates()
{
QByteArray arr;
arr.resize(5);
arr[0] = 0xAB;
arr[1] = 0x01;
arr[2] = 0x00;
arr[3] = 0x00;
arr[4] = 0x00 - arr[1] - arr[2] - arr[3];
QByteArray response = ComPort::get().requestResponse(arr);
if(response[0] == arr[0])
{
QBitArray bitStates(16);
for (int i = 4; i<6; i++)
for (int b = 0; b<8; b++)
bitStates.setBit((i-4)*8+b, response.at(i)&(1<<b));
for (int i = 0; i < valveState.size(); i++)
valveState[i] = bitStates[i];
for (uint i = 0; i < sizeof(fittingState); i++)
fittingState[i] = bitStates[i+8];
emit remoteSignal(1);
return 1;
}
emit remoteSignal(0);
return 0;
}
//***//
QByteArray ComPort::requestResponse(const QByteArray &data)
{
mutex->lock();
QByteArray readBuf;
qDebug() << "-------------------------";
if(!serial->isOpen())
open();
int attempts = 1;
while (attempts <= REQATTEMPTS) { //3 попытки
if (serial->isWritable())
{
serial->write(data);
qDebug() << "Попытка № " << attempts;
qDebug() << "ЗапроÑ: " << data.toHex();
while (serial->waitForReadyRead(WAITFORREADY)) {
readBuf += serial->readAll();
if (crcCheck(readBuf) && data[2] == readBuf[2] ){ //еÑли CRC и команда ÑошлиÑÑŒ -- уÑпех!
qDebug() << "Ответ: " << readBuf.toHex();
responseCount++;
qDebug() << "Кол-во запроÑов: " << responseCount;
qDebug() << "Кол-во таймаутов: " << timeoutCount;
float percent = timeoutCount * 100;
percent = percent / responseCount;
qDebug() << "Процент коÑÑков: " << QString::number(percent, 'f', 3) << "%";
close();
mutex->unlock();
return readBuf;
}
}
//qDebug() << readBuf.toHex();
readBuf.clear();
qDebug() << "Таймаут...";
timeoutCount++;
close();
open();
attempts++;
}
else
{
qDebug() << "Порт " << portName << " не пишетÑÑ!";
close();
mutex->unlock();
return 0;
}
}
close();
mutex->unlock();
return 0;
}
If I do not put valve and pressureSensors in a separate thread, then everything works more or less normally.
But if I put them in a separate thread, the valve opening slot works very late (~ 10 seconds, as lucky). As I understand it, this is because the signal is emitted from the main thread, and the slot is in the other thread. Is it possible to build a queue?
Slot open from Valve class must have the highest priority.
Thankful in advance for the help!