QML e UDP Socket
-
Buongiorno a tutti,
qualcuno ha mai avuto l'esigenza di ricevere (o inviare) pacchetti UDP all'interno di un'applicazione QML/JavaScript in Android?Da una prima ricerca fatta (https://forum.qt.io/topic/87143/udp-and-tcp-sockets-with-qml) sembrerebbero esserci due strade: integrazione QML/C++ o Libreria esterna.
Ho provato a scaricare la libreria ma non sono riuscito a utilizzarla (non ci sono istruzioni). Nei commenti nella pagina GitHub sembrerebbe però che la libreria non funziona su Android (sarà vero...?)Per la seconda strada, il link presente nel post (http://doc.qt.io/qt-5/qtqml-cppintegration-topic.html) c'è un esempio di integrazione QML/C++ ma si tratta di un'interazione semplice. In questo caso ci dovrebbe essere, dal lato C++, qualcosa in ascolto continuo sulla porta UDP e, in caso di dato ricevuto, dovrebbe trasferirlo dal lato QML.
Qualcuno ha mai avuto un'esigenza simile?
Grazie -
QML/C++, non usare librerie esterne per una cosa così semplice.
Io ad esempio ho un'app che in fase di avvio cerca i dispositivi mandando in broadcast un pacchetto udp e poi mostra a video ciò che trova.
Non pensare sia difficile.Ciao ciao.
grazie @mrdebug !
Ho trovato un esempio che allego. In effetti dal lato c++ si apre una porta UDP in ascolto. Alla ricezione di un dato però invia al "lato QML" un evento di tasto premuto (almeno così mi sembra) che viene riconosciuto dall'evento Keys.OnPressed.
Se invece volessi passare al QML semplicemente i dati ricevuti come dovrebbe essere modificato il codice? oppure chiedo se qualche utente ha un esempio semplice adatto allo scopo.(main.cpp)
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlApplicationEngine> #include <QKeyEvent> #include <QUdpSocket> #include <QTimer> #include <QDebug> #include <QWindow> #include <QObject> #include <QUrl> #include <QString> #include <QVariant> #include <QQmlContext> #include <QByteArray> #include <QHostAddress> QQmlApplicationEngine * engine; class Listener : public QUdpSocket { Q_OBJECT public: Listener(QObject *parent = 0): QUdpSocket(parent) { bind(1129); qDebug() << "Started Listener"; connect(this, SIGNAL(readyRead()), this, SLOT(readDatagram())); } private slots: void readDatagram() { QByteArray datagram; datagram.resize(QUdpSocket::pendingDatagramSize()); QUdpSocket::readDatagram(datagram.data(), datagram.size()); //processTheDatagram(datagram); int key = QString::fromUtf8(datagram.data()).toInt(); qDebug() << "Key: " << QString::number(key); QKeyEvent* keyP = new QKeyEvent(QEvent::KeyPress,key,Qt::NoModifier); QKeyEvent* keyR = new QKeyEvent(QEvent::KeyRelease,key,Qt::NoModifier); QCoreApplication::sendEvent(engine->rootObjects().first(), keyP); QCoreApplication::sendEvent(engine->rootObjects().first(), keyR); } }; int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); engine = new QQmlApplicationEngine; engine->load(QUrl(QStringLiteral("qrc:///main.qml"))); Listener l; return app.exec(); } #include "main.moc"
(main.qml)
import QtQuick 2.9 import QtQuick.Window 2.2 import QtQuick.Controls 1.1 import QtQuick.Layouts 1.1 ApplicationWindow { visible: true width: 1024 height: 768 Rectangle { id:zzMain visible: true width: 1024 height: 768 color: "#56555b" property string source1: "" property string source2 property color bgColor: "#002244" property real volume: 0.25 property string backto: "mainmenu.qml" RowLayout { id: layout anchors.fill: parent spacing: 6 Item { id: header1 width: parent.width height: 135 anchors.top: parent.top Loader { id: headerLoader anchors.fill: parent source: "header.qml" } } Item { anchors.leftMargin: 10 anchors.rightMargin: 10 anchors.topMargin: 10 anchors.left: parent.left anchors.top: header1.bottom width: parent.width height: parent.height - 10 - header1.height Loader { id: sceneLoader focus:true anchors.fill: parent source: "mainmenu.qml" } } Keys.onPressed: { console.log('Key A was pressed'); event.accepted = true } Keys.onReleased: { console.log('Key A was released: ' + event.key); event.accepted = true } function closeScene() { console.log("[qmlvideo] main.closeScene") console.log("[qmlvideo] main.closeScene->Going to:" + zzMain.backto) sceneLoader.source = zzMain.backto } } } }
-
-
Grazie mrdebug,
sono arrivato ad un risultato.
Posto il codice a beneficio di tutti gli utenti, anche se c'è un'ultima cosa che non torna.- MAIN.CPP
#include <QGuiApplication> #include <QQmlApplicationEngine> #include "myudp.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); qmlRegisterType<MyUDP>("MyUDP", 1, 0, "MyUDP"); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }
MYUDP.H
#ifndef MYUDP_H #define MYUDP_H #include <QObject> #include <QUdpSocket> class MyUDP : public QObject { Q_OBJECT Q_PROPERTY(QByteArray type READ type WRITE setType NOTIFY typeChanged) public: explicit MyUDP(QObject *parent = 0); void SayHello(); QByteArray type(); void setType(const QByteArray &t); signals: void typeChanged(); public slots: void readyRead(); private: QUdpSocket *socket; QByteArray _type; }; #endif // MYUDP_H
MYUDP.C
#include "myudp.h" MyUDP::MyUDP(QObject *parent) : QObject(parent) { socket = new QUdpSocket(this); socket->bind(1129, QUdpSocket::ShareAddress); connect(socket,SIGNAL(readyRead()),this, SLOT(readyRead())); } // send message in client mode void MyUDP::SayHello() { QByteArray Data; Data.append("test message"); socket->writeDatagram(Data,QHostAddress::LocalHost,5824); } void MyUDP::readyRead() { QByteArray Buffer; Buffer.resize(socket->pendingDatagramSize());; QHostAddress sender; quint16 senderPort; socket->readDatagram(Buffer.data(),Buffer.size(), &sender, &senderPort); qDebug()<< "Message size:" << Buffer.size(); setType(Buffer); } QByteArray MyUDP::type() { return _type; } void MyUDP::setType(const QByteArray &t) { _type = t; emit typeChanged(); }
MAIN.QML
import QtQuick 2.0 import QtQuick.Controls 2.2 import "main.js" as SpkScript import MyUDP 1.0 ApplicationWindow { id: window visible: true title: qsTr("AESA.Monitor") MyUDP { id:myUdp onTypeChanged: { console.log("[QML]Msg:" + type) } } }
L'esempio funziona in ricezione. Il pacchetto ricevuto è contenuto in "type" (lato QML).
Se si fa una console.log(typeof type) il risultato è "object".Se si ricevono caratteri stampabili va tutto bene. Ho provato il codice seguente che trasforma type in stringa permettendo l'uso di tutte le funzioni relative:
var m=type.toString(); if(m.slice(0,4)==="col=") { ecc.ecc...
il problema (nel mio caso) è che ricevo dati binari, per cui la conversione a stringa non funziona più bene (al primo carattere non stampabile la stringa si interrompe).
Ho provato a ricavare i singoli byte dalla variabile type ma senza successo:
type[0] ritorna "not defined"
type.charCodeAt(0) non funziona (non è una stringa)
ci vorrebbe una conversione ad array ma non so come fare.grazie per tutti i suggerimenti
ciao