Пытаюсь вынести запрос по сом порту в отдельный поток. Использую для этого код из примера к библиотеке QSerialPort "master". Связь сигнал-слот и таймер в стартовом методе обрабатывает, когда доходить до инициализации порта ругается
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QSerialPort(0x23fe30), parent's thread is QThread(0x35b48), current thread is QThread(0x23fe60)
В поток выношу следующим способом:
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
....
QThread thread1;
ComThread2 ct; // класс с сом портом
QObject::connect(&thread1,SIGNAL(started()),&ct,SLOT(run()));
// QObject::connect(&text1,SIGNAL(finished()),&thread1,SLOT(terminate()));
ct.moveToThread(&thread1);
thread1.start();
return a.exec();
}
Вначале проверяла сам механизм переноса в другой поток, он работает. Проверяла на счетчике и таймере.
Подскажите, пожалуйста, почему он не переносит в дочерние методы в поток.
Вот код класса для другого потока:
header
#ifndef COMTHREAD2_H
#define COMTHREAD2_H
#include <QObject>
#include <QCoreApplication>
#include <QTimer>
#include <QSerialPort>
#include <QVector>
#include "crc16cs.h"
class ComThread2 : public QObject
{
Q_OBJECT
public:
explicit ComThread2(QObject *parent = 0);
signals:
void parse();
public slots:
void sendRequest();
void readResponse();
void processTimeout();
void run();
QString formRequest();
QString parseResponse(QString resp1);
QVector <quint16> strToVector(QString string);
void parseRes();
void Init();
private:
QSerialPort serial;
QByteArray response;
QTimer timer;
//QTimer timerCOM;
Crc16CS *crc16;
QString fromRoc;
void setControlsEnabled(bool enable);
void processError(const QString &error);
};
#endif // COMTHREAD2_H
cpp
#include "comthread2.h"
#include <QtSerialPort/QSerialPortInfo>
#include <QtSql>
#include <qmath.h>
#include <QDateTime>
#include "qdatabase.h"
ComThread2::ComThread2(QObject *parent) :
QObject(parent)
{
}
void ComThread2::sendRequest()
{
if (serial.portName() != "COM2") {
serial.close();
serial.setPortName("COM2");
if (!serial.open(QIODevice::ReadWrite)) {
processError(tr("Can't open %1, error code %2")
.arg(serial.portName()).arg(serial.error()));
return;
}
if (!serial.setBaudRate(QSerialPort::Baud9600)) {
processError(tr("Can't set rate 9600 baud to port %1, error code %2")
.arg(serial.portName()).arg(serial.error()));
return;
}
if (!serial.setDataBits(QSerialPort::Data8)) {
processError(tr("Can't set 8 data bits to port %1, error code %2")
.arg(serial.portName()).arg(serial.error()));
return;
}
if (!serial.setParity(QSerialPort::NoParity)) {
processError(tr("Can't set no parity to port %1, error code %2")
.arg(serial.portName()).arg(serial.error()));
return;
}
if (!serial.setStopBits(QSerialPort::OneStop)) {
processError(tr("Can't set 1 stop bit to port %1, error code %2")
.arg(serial.portName()).arg(serial.error()));
return;
}
if (!serial.setFlowControl(QSerialPort::NoFlowControl)) {
processError(tr("Can't set no flow control to port %1, error code %2")
.arg(serial.portName()).arg(serial.error()));
return;
}
}
setControlsEnabled(false);
// statusLabel->setText(tr("Status: Running, connected to port %1.")
// .arg(serialPortComboBox->currentText()));
// requestLineEdit->setText(formRequest());
// QTimer *timer = new QTimer(this);
// timer->setSingleShot(true);
// connect(timer, SIGNAL(timeout()),
// this, SLOT(processTimeout()));
QString req ("fofo");
serial.write(req.toLocal8Bit());
timer.start(100);
}
void ComThread2::readResponse()
{
response.append(serial.readAll());
emit parse();
}
void ComThread2::processTimeout()
{
setControlsEnabled(true);
// trafficLabel->setText(tr("Traffic, transaction #%1:"
// "\n\r-request: %2"
// "\n\r-response: %3")
// .arg(++transactionCount).arg(requestLineEdit->text()).arg(QString(response)));
response.clear();
}
void ComThread2::processError(const QString &error)
{
setControlsEnabled(true);
// statusLabel->setText(tr("Status: Not running, %1.").arg(error));
// trafficLabel->setText(tr("No traffic."));
}
void ComThread2::setControlsEnabled(bool enable)
{
// runButton->setEnabled(enable);
// serialPortComboBox->setEnabled(enable);
// waitResponseSpinBox->setEnabled(enable);
// requestLineEdit->setEnabled(enable);
}
QString ComThread2::formRequest()
{
crc16 = new Crc16CS();
QString req1 ("");
QString roc2 ("0201");
QString roc1 ("0101");
QString comp ("0301");
QString opcode ("0A");
QString rdata ("00000B");
if ((rdata.size()/2%2 != 0) )
{
req1 = roc1 + comp + opcode + "0" + QString::number(rdata.size()/2,16) + rdata;
}
if (rdata.size()/2%2 == 0)
{
req1 = roc1 + comp + opcode + QString::number(rdata.size()/2,16) + rdata;
}
req1 = req1 + crc16->ComputeChecksumBytes(strToVector(req1));
return req1;
}
QString ComThread2::parseResponse(QString resp1)
{
QVector <quint16> rqVector;
resp1 = resp1.left(76);
rqVector = strToVector(resp1); // str to vector
QString cr6 = crc16->ComputeChecksumBytes(rqVector); // check ctc, if "0" it's ok
QString ansStr ("");
if ((cr6 == "00")&& resp1.size()>0 )
{
QString respFormat; // format of response
/*
float 4
uint8 8
uint16 16
uint32 32
*/
respFormat = "4 16 16 16 16 8 8 8 8 8 16 32"; // из базы данных
QStringList respList = respFormat.split(" ", QString::SkipEmptyParts);
int count(0);
int pos (26);
QStringList anwList;
for (quint8 i=0; i< respList.size(); i++)
{
if (respList[i].toInt()!=4)
{
count = respList[i].toInt()/4;
anwList.append(resp1.mid(pos,count));
pos = pos+count;
}
if (respList[i].toInt()==4)
{
anwList.append(resp1.mid(pos,8));
pos=pos+8;
}
}
bool ok;
for( quint8 i=0; i <anwList.size(); i++)
{
if (respList[i].toInt()==4) // for parse float
{
QString resp (anwList[i]);
QByteArray flarray;
flarray.append(resp.at(6));
flarray.append(resp.at(7));
flarray.append(resp.at(4));
flarray.append(resp.at(5));
flarray.append(resp.at(2));
flarray.append(resp.at(3));
flarray.append(resp.at(0));
flarray.append(resp.at(1));
QString P ("");
bool ok;
int sign = 1;
flarray.toLongLong(&ok,16);
flarray = QByteArray::number(flarray.toLongLong(&ok,16),2);
if(flarray.length()==32) {
if(flarray.at(0)=='1') {sign =-1;} // if bit 0 is 1 number is negative
flarray.remove(0,1); // remove sign bit
}
QByteArray fraction =flarray.right(23); //get the fractional part
double mantissa = 0;
for(int i=0;i<fraction.length();i++) // iterate through the array to claculate the fraction as a decimal.
{ if(fraction.at(i)=='1') { mantissa += 1.0/(pow(2,i+1));}}
int exponent = flarray.left(flarray.length()-23).toLongLong(&ok,2)-127; //claculate the exponent
P = QString::number( sign*pow(2,exponent)*(mantissa+1.0),'f', 7 );
ansStr = ansStr + P + " ";
}
if (respList[i].toInt()==8) // for parse uint8
{
ansStr = ansStr + QString::number(anwList[i].toInt(&ok,16))
+ " ";
}
if (respList[i].toInt()==16) // for parse uint16
{
QString s =anwList[i].right(2)+anwList[i].left(2);
ansStr = ansStr + QString::number(s.toInt(&ok,16))
+ " ";
}
if (respList[i].toInt()==32) // for parse uint32
{
QString s = anwList[i].mid(6,2)+anwList[i].mid(4,2)+
anwList[i].mid(2,2)+anwList[i].mid(0,2);
ansStr = ansStr + QString::number(s.toInt(&ok,16))
+ " ";
}
}
}
return ansStr;
}
QVector<quint16> ComThread2::strToVector(QString string)
{
bool ok;
QVector<quint16> rqVector;
for(int i=0; i < string.size(); i++)
{
QString resp2 = string.mid(i,2);
rqVector.append(resp2.toInt(&ok,16)); // zanosim v vektor
i++;
}
return rqVector;
}
void ComThread2::parseRes()
{
QString res ("");
res = response;
if (res.size()!=0)
{
QStringList dataList = parseResponse(res).split(" ", QString::SkipEmptyParts);
float P1 = (dataList[1].toFloat())/1000;
float Q1 = (dataList[2].toFloat())/1000;
float Ro1 =(dataList[3].toFloat())/10;
float T1 = (dataList[4].toFloat())/1000;
QDateTime dt;
dt = QDateTime::fromMSecsSinceEpoch(dataList[11].toLongLong()*1000);
QDataBase bb1;
bb1.UpdateDb(dt.date(), dt.time().addSecs(2), 1, Q1, Ro1, P1, T1);
bb1.UpdateDb(dt.date(), dt.time().addSecs(2), 2, Q1, Ro1, P1, T1);
}
}
void ComThread2::Init()
{
QTimer *timerCOM = new QTimer(this);
connect(timerCOM, SIGNAL(timeout()),
this, SLOT(sendRequest()));
timerCOM->start(300);
timer.setSingleShot(true);
connect(&serial, SIGNAL(readyRead()),
this, SLOT(readResponse()));
connect(&timer, SIGNAL(timeout()),
this, SLOT(processTimeout()));
connect(this , SIGNAL(parse()),
this, SLOT(parseRes()));
}
void ComThread2::run()
{
Init();
}
Падает на строках
if (!serial.open(QIODevice::ReadWrite)) {
processError(tr("Can't open %1, error code %2")
.arg(serial.portName()).arg(serial.error()));
return;