QUdpSocket multicast receiver timeout detection?
-
I am using multicast receiver example. How can I add a timer where if I loose the multicast signal and don't get any multicast signal in a specific time, then it will set a gpio to high?
This is what I tried but it does not work the way its supposed to.if (udpSocket->hasPendingDatagrams() != 1) { QTimer::singleShot(5000, this, SLOT(nomsg())); } void MainWindow::nomsg() { ::gpio_set_value(this->GREEN_LED_PIN, HIGH); }
I receive 1 udp signal every second, so this program just keeps toggling the gpio to high and low.
I just want to turn my gpio high if I don't get any multicast message in 5 seconds.Any help will be greatly appreciated.
-
I am using multicast receiver example. How can I add a timer where if I loose the multicast signal and don't get any multicast signal in a specific time, then it will set a gpio to high?
This is what I tried but it does not work the way its supposed to.if (udpSocket->hasPendingDatagrams() != 1) { QTimer::singleShot(5000, this, SLOT(nomsg())); } void MainWindow::nomsg() { ::gpio_set_value(this->GREEN_LED_PIN, HIGH); }
I receive 1 udp signal every second, so this program just keeps toggling the gpio to high and low.
I just want to turn my gpio high if I don't get any multicast message in 5 seconds.Any help will be greatly appreciated.
@samy03
You need to be reading the datagrams that do arrive, e.g. viaQUdpSocket::receiveDatagram()
.How about:
- Create function to set GREEN (
nomsg()
). - Create function to set off
QTimer::singleShot(5000, this, SLOT(nomsg()));
. - Set off that function initially.
- In
readyRead
slot whenever a datagram received, read it (receiveDatagram()
) and then cancel existing 5 second timer and call function to restart a new one.
?
Alternatively, if http://doc.qt.io/qt-5/qabstractsocket.html#waitForReadyRead works for your UDP (and note it's not reliable if you are Windows anyway), you might architect using http://doc.qt.io/qt-5/qabstractsocket.html#waitForReadyRead specifying your 5,000ms, but you'll probably end up with using earlier methof.
- Create function to set GREEN (
-
@samy03 said in QUdpSocket multicast receiver timeout detection?:
@JonB I tried both methods but none of them are working.
With the first method, as soon as I start receiving multicast message, my program shutdown.With waitForReadyRead, nothing was happening, even though its on Linux.
-
@samy03 said in QUdpSocket multicast receiver timeout detection?:
@JonB I tried both methods but none of them are working.
With the first method, as soon as I start receiving multicast message, my program shutdown.With waitForReadyRead, nothing was happening, even though its on Linux.
@samy03
Since the docs state thatwaitForReadyRead()
may be flaky (although it says only under Windows), let's not use that. In any case it doesn't do anything we cannot do ourselves.As for:
With the first method, as soon as I start receiving multicast message, my program shutdown.
Well, you know your program should not "shutdown" in such a situation! So either examine your own code, or show us a minimal example of what does not work for you?
-
@JonB
Here is my code:#include "mainwindow.h" #include "ui_mainwindow.h" #include <QtWidgets> #include <QtNetwork> #include <QXmlStreamReader> #include "SimpleGPIO.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); setWindowFlags(Qt::Window | Qt::FramelessWindowHint); setWindowState(Qt::WindowFullScreen); gpio_omap_mux_setup("eCAP0_in_PWM0", "128"); //gpio1_28 P9 header pin# 12 this->GREEN_LED_PIN = 60; gpio_export(this->GREEN_LED_PIN); gpio_set_dir(this->GREEN_LED_PIN, OUTPUT_PIN); ::gpio_set_value(this->GREEN_LED_PIN, HIGH); xmltimer(); //starting timer groupAddress = QHostAddress("224.224.24.23"); udpSocket = new QUdpSocket(this); udpSocket->bind(QHostAddress::AnyIPv4, 11007, QUdpSocket::ShareAddress); udpSocket->joinMulticastGroup(groupAddress); connect(udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams())); } void MainWindow::processPendingDatagrams() { while (udpSocket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(udpSocket->pendingDatagramSize()); udpSocket->readDatagram(datagram.data(), datagram.size()); str=datagram; QXmlStreamReader xml(str); timer->stop(); //stopping the timer xmltimer(); //calling the timer again //Parse the XML until we reach end of it while(!xml.atEnd() && !xml.hasError()) { // Read next element QXmlStreamReader::TokenType token = xml.readNext(); //If token is just StartDocument - go to next if(token == QXmlStreamReader::StartDocument) { continue; } } } } void MainWindow::nomsg() { ::gpio_set_value(this->GREEN_LED_PIN, HIGH); } void MainWindow::xmltimer() { QTimer::singleShot(5000, this, SLOT(nomsg())); }
This is just a minimal example of what I am trying to achieve here.
-
@JonB
Here is my code:#include "mainwindow.h" #include "ui_mainwindow.h" #include <QtWidgets> #include <QtNetwork> #include <QXmlStreamReader> #include "SimpleGPIO.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); setWindowFlags(Qt::Window | Qt::FramelessWindowHint); setWindowState(Qt::WindowFullScreen); gpio_omap_mux_setup("eCAP0_in_PWM0", "128"); //gpio1_28 P9 header pin# 12 this->GREEN_LED_PIN = 60; gpio_export(this->GREEN_LED_PIN); gpio_set_dir(this->GREEN_LED_PIN, OUTPUT_PIN); ::gpio_set_value(this->GREEN_LED_PIN, HIGH); xmltimer(); //starting timer groupAddress = QHostAddress("224.224.24.23"); udpSocket = new QUdpSocket(this); udpSocket->bind(QHostAddress::AnyIPv4, 11007, QUdpSocket::ShareAddress); udpSocket->joinMulticastGroup(groupAddress); connect(udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams())); } void MainWindow::processPendingDatagrams() { while (udpSocket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(udpSocket->pendingDatagramSize()); udpSocket->readDatagram(datagram.data(), datagram.size()); str=datagram; QXmlStreamReader xml(str); timer->stop(); //stopping the timer xmltimer(); //calling the timer again //Parse the XML until we reach end of it while(!xml.atEnd() && !xml.hasError()) { // Read next element QXmlStreamReader::TokenType token = xml.readNext(); //If token is just StartDocument - go to next if(token == QXmlStreamReader::StartDocument) { continue; } } } } void MainWindow::nomsg() { ::gpio_set_value(this->GREEN_LED_PIN, HIGH); } void MainWindow::xmltimer() { QTimer::singleShot(5000, this, SLOT(nomsg())); }
This is just a minimal example of what I am trying to achieve here.
@samy03
And? I don't know how it performs. You can put someqDebug()
s in, or use the debugger, to see what is actually doing, surely?After your code has exited
MainWindow::MainWindow()
, I assume your caller does go into the normal Qt event loop, it doesn't just exit? -
I am using multicast receiver example. How can I add a timer where if I loose the multicast signal and don't get any multicast signal in a specific time, then it will set a gpio to high?
This is what I tried but it does not work the way its supposed to.if (udpSocket->hasPendingDatagrams() != 1) { QTimer::singleShot(5000, this, SLOT(nomsg())); } void MainWindow::nomsg() { ::gpio_set_value(this->GREEN_LED_PIN, HIGH); }
I receive 1 udp signal every second, so this program just keeps toggling the gpio to high and low.
I just want to turn my gpio high if I don't get any multicast message in 5 seconds.Any help will be greatly appreciated.
@samy03 said in QUdpSocket multicast receiver timeout detection?:
I am using multicast receiver example
I'd just modify the existing processPendingDatagrams() method (receiver.cpp) to handle the timer start/stop actions... pseudo-code (not tested):
... QTimer timerLostSignal = QTimer(5000); QObject::connect(timerLostSignal, &QTimer::timeout, this, &MainWindow::noMsg); // start checking if no datagrams are received timerLostSignal.start(); ... ... void Receiver::processPendingDatagrams() { // since we're going to read datagrams // stop timer (signal is not lost yet...) timerLostSignal.stop(); QByteArray datagram; while (udpSocket->hasPendingDatagrams()) { datagram.resize(int(udpSocket->pendingDatagramSize())); udpSocket->readDatagram(datagram.data(), datagram.size()); statusLabel->setText(tr("Received datagram: \"%1\"") .arg(datagram.constData())); } // loop finished, no more datagrams to read so far // start timer just in case no other datagram arrives ever timerLostSignal.start(); } ... ... void MainWindow::noMsg() { ::gpio_set_value(this->GREEN_LED_PIN, HIGH); }
-
I got it working just by changing the format of my timer like this:
newtimer = new QTimer(this); newtimer->setInterval(3000); newtimer->setSingleShot(true); connect(newtimer, SIGNAL(timeout()), SLOT(nomsg())); newtimer->start();
and then calling newtimer to start or stop.
I had to do this since you cannot start or stop SingleShot timer in this "QTimer::singleShot(200, this, SLOT(updateCaption()));" format.