我正在通過串行端口向設備發送(寫入)字節。我正在使用QSerialPort(http://qt-project.org/wiki/QtSerialPort)模塊實例化設備IO支持。當我發送消息到我的INSTEON調制解調器(串行)時,在閱讀我的消息時,設備發送一條消息+ 0x06(ACK字節),然後發送一條狀態消息。Qt串行端口 - 始終讀取數據
我已經使用DockLight測試了我的消息(http://www.docklight.de/)。我將下列消息發送到查詢設備的狀態:
02 62 1D E9 4B 05 19 00
使用Docklight,我收到了迴應:
02 62 1D E9 4B 05 19 00 06 02 50 20 CB CF 1E DA F7 21 00 FF
返回的消息表明正是我所期望的,該設備是上。如果關閉,如果設備關閉,則調制解調器將在最後一個字節位置返回0x00。現在,我的問題 - 我不能正確地發送並接收響應字節。我已經嘗試了許多不同的實施例和配置,目前我使用以下:
設置信號槽連接:用於通過設備的QList迭代
QObject::connect(&thread, SIGNAL(sendResponse(QByteArray)),
this, SLOT(handleResponse(QByteArray)));
QObject::connect(&thread, SIGNAL(error(QString)),
this, SLOT(processError(QString)));
QObject::connect(&thread, SIGNAL(timeout(QString)),
this, SLOT(processTimeout(QString)));
功能。如果設備是所需類型(「Light」),那麼我們將設備ID格式化爲預期的QByteArray消息結構。將消息傳遞給線程以進行發送。 (線程從QSerialPort BlockingMaster
例如改性用於設置局部線程變量和執行(運行)螺紋
void Device::currentStatus(QList<Device *> * deviceList){
QString devID, updateQry;
int devStatus, updateStatus;
updateStatus=0;
QSqlQuery query;
for(int i=0; i<deviceList->size(); i++){
if(deviceList->at(i)->type == "Light"){
devStatus = deviceList->at(i)->status;
devID = deviceList->at(i)->deviceID;
QByteArray msg;
bool msgStatus;
msg.resize(8);
msg[0] = 0x02;
msg[1] = 0x62;
msg[2] = 0x00;
msg[3] = 0x00;
msg[4] = 0x00;
msg[5] = 0x05;
msg[6] = 0x19;
msg[7] = 0x00;
msg.replace(2, 3, QByteArray::fromHex(devID.toLocal8Bit()));
qDebug() << "Has device " << deviceList->at(i)->name << "Changed?";
//send(msg,&msgStatus, &updateStatus);
//msg.clear();
thread.setupPort("COM3",500,msg);
if(devStatus!=updateStatus){
qDebug() << deviceList->at(i)->name << " is now: " << updateStatus;
updateStatus = !updateStatus;
}
}
}
}
SetupThread
功能
void serialThread::setupPort(const QString &portName, int waitTimeout, const QByteArray &msg){
qDebug() << "Send Message " << msg.toHex();
QMutexLocker locker(&mutex);
this->portName = portName;
this->waitTimeout = waitTimeout;
this->msg = msg;
if(!isRunning())
start();
else
cond.wakeOne();
}
Run
功能。 - 已處理髮送和接收
void serialThread::run(){
bool currentPortNameChanged = false;
qDebug() << "Thread executed";
mutex.lock();
QString currentPortName;
if(currentPortName != portName){
currentPortName = portName;
currentPortNameChanged = true;
}
int currentWaitTimeout = waitTimeout;
QByteArray sendMsg = msg;
mutex.unlock();
QSerialPort serial;
while(!quit){
if(currentPortNameChanged){
serial.close();
serial.setPortName("COM3");
if (!serial.open(QIODevice::ReadWrite)) {
emit error(tr("Can't open %1, error code %2")
.arg(portName).arg(serial.error()));
return;
}
if (!serial.setBaudRate(QSerialPort::Baud19200)) {
emit error(tr("Can't set baud rate 9600 baud to port %1, error code %2")
.arg(portName).arg(serial.error()));
return;
}
if (!serial.setDataBits(QSerialPort::Data8)) {
emit error(tr("Can't set 8 data bits to port %1, error code %2")
.arg(portName).arg(serial.error()));
return;
}
if (!serial.setParity(QSerialPort::NoParity)) {
emit error(tr("Can't set no patity to port %1, error code %2")
.arg(portName).arg(serial.error()));
return;
}
if (!serial.setStopBits(QSerialPort::OneStop)) {
emit error(tr("Can't set 1 stop bit to port %1, error code %2")
.arg(portName).arg(serial.error()));
return;
}
if (!serial.setFlowControl(QSerialPort::NoFlowControl)) {
emit error(tr("Can't set no flow control to port %1, error code %2")
.arg(portName).arg(serial.error()));
return;
}
}
//write request
serial.write(msg);
if (serial.waitForBytesWritten(waitTimeout)) {
//! [8] //! [10]
// read response
if (serial.waitForReadyRead(currentWaitTimeout)) {
QByteArray responseData = serial.readAll();
while (serial.waitForReadyRead(10)){
responseData += serial.readAll();
}
QByteArray response = responseData;
//! [12]
emit this->sendResponse(response);
//! [10] //! [11] //! [12]
} else {
emit this->timeout(tr("Wait read response timeout %1")
.arg(QTime::currentTime().toString()));
}
//! [9] //! [11]
} else {
emit timeout(tr("Wait write request timeout %1")
.arg(QTime::currentTime().toString()));
}
mutex.lock();
cond.wait(&mutex);
if (currentPortName != portName) {
currentPortName = portName;
currentPortNameChanged = true;
} else {
currentPortNameChanged = false;
}
currentWaitTimeout = waitTimeout;
sendMsg = msg;
mutex.unlock();
}
serial.close();
}
handleResponse
功能,接收響應信號的SLOT
void Device::handleResponse(const QByteArray &msg){
qDebug() << "Read: " << msg.toHex();
}
我收到以下輸出:這裏
Has device "Living Room Light" Changed?
Send Message "02621de94b051900"
Has device "Bedroom Light" Changed?
Send Message "026220cbcf051900"
Thread executed
Read: "026220cbcf05190006"
Polling for changes...
Has device "Living Room Light" Changed?
Send Message "02621de94b051900"
Has device "Bedroom Light" Changed?
Send Message "026220cbcf051900"
Read: "025020cbcf1edaf721000002621de94b05190006"
Polling for changes...
Has device "Living Room Light" Changed?
Send Message "02621de94b051900"
Has device "Bedroom Light" Changed?
Send Message "026220cbcf051900"
Read: "02501de94b1edaf72100ff02621de94b05190006"
兩個問題。
我從來沒有收到關於第二個設備(臥室燈)的任何迴應,這是發送第二個消息。似乎發送被阻止,你會如何建議我格式化我的發送,以便在收到第一次發送的響應後發送?只有1個COM端口可用於發送/接收。我相信我應該發送消息到設備1,接收設備1響應,發送到設備2,接收設備2.我可能會看到大量設備和使用等待條件的巨大交通堵塞,即。在執行設備2的通信過程之前,請等待設備1通信過程完成?
第一次閱讀包含適當的前半部分接收。
Read: "026220cbcf05190006"
第二接收包含第一響應接着所述第二響應的第一半部分的第二半:讀取2 -Read: "025020cbcf1edaf721000002621de94b05190006"
適當全響應是02621DE94B05190006 025020CBCF1EDAF72100FF
(注意20CBCF
是設備2的在充分響應的示例ID)
對串口接收數據的方式應該做些什麼改正? 謝謝!
謝謝您的意見。我相當大地調整了我的代碼。我現在收到了更多的「一致」迴應,但它仍然不符合我的意圖。 – 2013-03-04 05:12:17
+1爲「難以想象的麪條代碼」...和一個有用的答案。 – cgmb 2013-03-08 03:05:36
使用bytesAvailable()的問題是響應不是設定的字節數。根據發送到設備的消息的類型和格式,每個響應可以是可變的長度。 – 2013-10-18 08:07:39