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
readyReadslot 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.