Tôi đang gửi (ghi) byte vào thiết bị qua cổng nối tiếp của mình. Tôi đang sử dụng mô-đun QSerialPort (http://qt-project.org/wiki/QtSerialPort) để nhanh chóng hỗ trợ IO thiết bị. Khi tôi gửi tin nhắn đến modem INSTEON của tôi (nối tiếp), khi đọc tin nhắn của tôi, thiết bị sẽ gửi lại một bản sao của tin nhắn của tôi + 0x06 (ACK Byte), sau đó là thông báo trạng thái.Cổng nối tiếp Qt - Đọc dữ liệu một cách nhất quán
Tôi đã kiểm tra thư của mình bằng DockLight (http://www.docklight.de/). Tôi gửi thông điệp sau đây để truy vấn trạng thái của thiết bị:
02 62 1D E9 4B 05 19 00
Sử dụng Docklight, tôi nhận được phản hồi:
02 62 1D E9 4B 05 19 00 06 02 50 20 CB CF 1E DA F7 21 00 FF
Thông điệp trở chỉ ra chính xác những gì tôi mong đợi, rằng thiết bị trên . Nếu tắt, modem sẽ gửi lại 0x00 ở vị trí byte cuối cùng nếu thiết bị tắt. Bây giờ, vấn đề của tôi - Tôi không phải thiết lập chức năng của tôi đúng cách để gửi và sau đó nhận các byte phản hồi. Tôi đã cố gắng rất nhiều ví dụ và cấu hình khác nhau, hiện nay tôi đang sử dụng như sau: kết nối tín hiệu-khe
Setup:
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)));
Chức năng sử dụng để lặp qua QList của thiết bị. Nếu thiết bị là kiểu mong muốn ("Light"), thì chúng ta định dạng ID thiết bị thành cấu trúc tin nhắn QByteArray dự định. Chuyển tin nhắn tới chủ đề để gửi. (Chủ đề được sửa đổi từ QSerialPort BlockingMaster
dụ
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
chức năng sử dụng để thiết lập các biến chủ đề địa phương và thực thi (chạy) chủ đề
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
Chức năng -.. Cầm gửi và nhận
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
chức năng, SLOT nhận tín hiệu phản hồi
void Device::handleResponse(const QByteArray &msg){
qDebug() << "Read: " << msg.toHex();
}
tôi nhận được kết quả như sau:
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"
Hai vấn đề ở đây.
Tôi chưa bao giờ nhận được bất kỳ phản hồi nào về thiết bị thứ hai (Đèn ngủ), đây là tin nhắn được gửi thứ hai. Dường như việc gửi đang bị chặn, bạn sẽ đề xuất định dạng gửi của tôi như thế nào để tôi gửi sau khi nhận được phản hồi cho lần gửi đầu tiên? Chỉ có 1 cổng COM có thể được sử dụng để gửi/nhận. Tôi tin rằng tôi nên gửi tin nhắn đến thiết bị 1, nhận được thiết bị 1 phản ứng, gửi đến thiết bị 2, nhận thiết bị 2. Tôi có thể kết thúc nhìn thấy một mứt giao thông rất lớn với rất nhiều thiết bị và sử dụng điều kiện chờ đợi, tức là. chờ cho quá trình liên lạc thiết bị 1 kết thúc trước khi thực hiện quá trình kết nối cho thiết bị 2?
Lần đọc đầu tiên chứa nửa đầu thích hợp của lần nhận.
Read: "026220cbcf05190006"
Thứ hai nhận chứa nửa thứ 2 của phản ứng 1 tiếp theo là nửa ngày 1 câu trả lời thứ hai: Đọc 2 -Read: "025020cbcf1edaf721000002621de94b05190006"
Câu trả lời đầy đủ thích hợp là02621DE94B05190006 025020CBCF1EDAF72100FF
(lưu ý20CBCF
là ID thiết bị 2 trong ví dụ phản ứng đầy đủ)
Điều chỉnh nào được thực hiện theo cách tôi nhận dữ liệu từ cổng nối tiếp? Cảm ơn bạn!
Cảm ơn bạn đã nhận xét. Tôi đã điều chỉnh mã của tôi khá đáng kể. Tôi hiện đang nhận được phản hồi "nhất quán" hơn, tuy nhiên nó vẫn không phù hợp với ý định của tôi. –
+1 cho "mì không thể tưởng tượng được mã" ... và một câu trả lời hữu ích. – cgmb
Sự cố với việc sử dụng byteTiện ích() là phản hồi không phải là số byte được đặt. Mỗi câu trả lời có thể có độ dài thay đổi tùy thuộc vào loại và định dạng của tin nhắn được gửi đến thiết bị. –