シリアル ポート経由でデバイスにバイトを送信 (書き込み) しています。QSerialPort ( http://qt-project.org/wiki/QtSerialPort ) モジュールを使用して、デバイス IO サポートをインスタンス化しています。メッセージを INSTEON モデム (シリアル) に送信すると、メッセージを読み取ると、デバイスはメッセージのコピー + 0x06 (ACK バイト) とそれに続くステータス メッセージを返信します。
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 を返します。さて、私の問題-応答バイトを送信してから受信するために、関数を適切にセットアップしてはいけません。私は多くの異なる例と構成を試しましたが、現在は以下を使用しています:
シグナルスロット接続をセットアップします。
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)));
デバイスの QList を反復処理するために使用される関数。デバイスが目的のタイプ (「ライト」) の場合、デバイス 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"
ここで2つの問題。
2 番目のデバイス (Bedroom Light) に関する応答がありません。これが 2 番目に送信されたメッセージです。送信がブロックされているようです。最初の送信で応答が受信された後に送信するように、送信をどのようにフォーマットすることをお勧めしますか? 送受信に使用できる COM ポートは 1 つだけです。デバイス 1 にメッセージを送信し、デバイス 1 の応答を受信し、デバイス 2 に送信し、デバイス 2 を受信する必要があると思います。デバイス 2 の通信プロセスを実行する前に、デバイス 1 の通信プロセスが終了するのを待ちますか?
最初の読み取りには、受信の適切な前半が含まれます。
Read: "026220cbcf05190006"
2 番目の受信には、最初の応答の後半と 2 番目の応答の前半が含まれます。 Read 2 -Read: "025020cbcf1edaf721000002621de94b05190006"
適切な完全な応答は次のとおりです (完全な応答の例では、デバイス 2 の ID に02621DE94B05190006 025020CBCF1EDAF72100FF
注意してください)。20CBCF
シリアルポートからデータを受信する方法を修正する必要がありますか? ありがとうございました!