Seri bağlantı noktam aracılığıyla bir cihaza (yazma) bayt gönderiyorum. Aygıt IO desteğini başlatmak için QSerialPort (http://qt-project.org/wiki/QtSerialPort) modülünü kullanıyorum. INSTEON modemime (seri) mesaj gönderdiğimde mesajım okunduğunda cihaz + 0x06 (ACK Byte) mesajımın bir kopyasını ve ardından bir durum mesajı gönderir. Qt Seri Bağlantı Noktası - Sürekli olarak veri okumak
Mesajımı DockLight (http://www.docklight.de/) kullanarak test ettim. Ben cihazın durumunu sorgulamak için aşağıdaki iletiyi göndermek:
02 62 1D E9 4B 05 19 00
Docklight kullanarak, yanıt alırsınız:
02 62 1D E9 4B 05 19 00 06 02 50 20 CB CF 1E DA F7 21 00 FF
döndürülen mesajı Cihaz üzerinde olduğunu, ne beklediğiniz tam gösterir . Kapalıysa, modem kapalıysa, son bayt konumuna 0x00 geri gönderir. Şimdi, benim sorunum - Yanıtlama baytlarını göndermek ve almak için doğru şekilde ayarlamam gerekir.
Kur sinyal yuvası bağlantıları: Şu anda aşağıdaki kullanıyorum, pek çok farklı örnekler ve yapılandırmaları çalıştık cihazların QList arasında yineleme için kullanılan
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)));
İşlevini. Cihazın türü ("Işık") isteniyorsa, cihaz kimliğini amaçlanan QByteArray mesaj yapısına göre biçimlendiririz. İleti göndermek için iletiye geçirin. (QSerialPort BlockingMaster
örneğin modifiye parçacığı yerel iplik değişkenleri ve yürütür (çalışır) iplik ayarlamak için kullanılan
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
fonksiyonu
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
Fonksiyonu -.. Gönderme ve
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();
}
alıcı Saplı
handleResponse
işlevi, yanıt sinyali alan SLOT
Burada
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"
İki sorunları:
void Device::handleResponse(const QByteArray &msg){
qDebug() << "Read: " << msg.toHex();
}
aşağıdaki çıktıyı alırsınız.
İkinci aygıtla ilgili hiçbir yanıt almadım (Bedroom Light), ikinci gönderilen mesaj budur. Gönderme engelleniyormuş gibi görünüyor, ilk gönderim için yanıt alındıktan sonra gönderim yapmak için gönderimi biçimlendirmeyi nasıl öneriyorsunuz? Göndermek/göndermek için kullanılabilecek sadece 1 COM bağlantı noktası vardır. Cihaz 1'e mesaj göndermem, Cihaz 1 yanıtı al, Cihaz 2'ye gönder, Cihaz 2'yi almam gerektiğine inanıyorum. Çok fazla cihazla büyük bir trafik sıkışıklığı ve bekletme koşulları kullanarak sonuçlanabilir miyim? Cihaz 1 için işlemi başlatmadan önce cihaz 1 iletişim sürecini bitirmek için bekleyiniz mi?
İlk okuma, almanın uygun 1. yarısını içerir.İkinci almak
Read: "026220cbcf05190006"
ikinci tepkinin 1. yarıda ardından 1 tepkinin 2 yarısını içerir: 2 - Oku
02621DE94B05190006 025020CBCF1EDAF72100FF
olduğunu
Read: "025020cbcf1edaf721000002621de94b05190006"
(tam yanıt örnekte Cihaz 2'nin kimliği
20CBCF
not ise)
Seri bağlantı noktasından veri alma şeklim için hangi düzeltmeler yapılmalıdır? Teşekkür ederiz!
Yorumlarınız için teşekkür ederiz. Kodumu oldukça önemli ölçüde ayarladık. Şimdi daha fazla "tutarlı" yanıt alıyorum, ancak yine de niyetimle uyumlu değil. –
+1 "düşünülemez erişte kodu" ... ve yararlı bir cevap. – cgmb
bytesAvailable() kullanılarak elde edilen sorun, yanıtın belirli sayıda bayt olmamasıdır. Her cevap, cihaza gönderilen mesajın türüne ve formatına bağlı olarak değişken uzunluk olabilir. –