Unsolved Send SMS using Qt and wireless router DWR 730
-
Hello
My system is a Linux laptop running ubuntu 16.04 with Qt 5.8.0 and Qt creator 4.2.1 and it is connected to internet by a DLink - DWR 730 wireless router.
My router can send and receive SMS. This means that I can enter to the router page, (e.g. using firefox browser), set the message I want to send, set the telefone number and send it.My purpose is to send and receive SMS automatically from a Qt application. I tried to develop such application using QNetworkAccessManager and QWebEngineView, but I failed. For me it is hard to understand (from Qt manuals) the way to follow to build the application I would like to.
The only thing I managed to do is to download the main router page!
I wasn't able to log in the router from my test application.Is there somebody that can give me a suggestion about the way I have to follow, or an example?
Thank you very much for your help.
-
Hi and welcome to devnet,
Can you check whether your router provides an API that your can use ?
-
Hi @MauPag,
If your device doesn't have an API (doesn't look like it does from a quick look at the manuals), then you would have to resort to "screen scraping", which it sounds like you're already having a go at.
I tried ... using QNetworkAccessManager and QWebEngineView
In this case, you don't need
QWebEngineView
, butQNetworkAccessManager
is the right starting point.Unfortunately, scraping a device like this is non-trivial. It can be done - I've done similar many times, but using shell scripts, rather than Qt. The process varies a little, based on how the web interface is structured, but the overall process would look something like:
- Fetch the router's landing page (ie whatever webpage it shows you first). Note, usually this will involve one or more redirect responses from the device, so make sure follow-redirects is enabled (see QNetworkAccessManager::setRedirectPolicy()). Also, usually this will result in the device issuing some session data via cookies (indeed, this is the only reason to bother fetching any pages before going straight to submitting the login), so make sure you have a cookie-jar (see QNetworkAccessManager::setCookieJar()). Apart from the session cookies, you probably won't need to programmatically read any of the response itself (other than to check for errors).
- Fetch the router's login page. (Note, often only one of #1 and #2 are required... but just as often both are required, and in sequence. You'll have to test and see for you device).
- Submit the log-in form. To know what fields to include, have a look at the HTML of the login page. This takes a bit of HTML understanding (or, worse, it could be done with Javascript, which will make things much harder, but isn't too likely for this style of device).
- Fetch the SMS inbox page and/or submit the send SMS form.
- Repeat #4 as often as you like.
- Presumably the session will expire at some point, then go back to #1 or #2 (test which is required).
All steps above should be doable with just
QNetworkAccessManager
's request functions (eg QNetworkAccessManager::get() and QNetworkAccessManager::post()). I would not expectQtWebEngine
to help at all (unless there's some really advanced client-side crypto happening in Javascript - but very unlikely).Happy to help further, but this will not be quick and easy if you are not already familiar with web-scraping.
Final huge tip: if this was me, I would first prove the concept using
curl
within a quick and dirty Bash script. It will be much, much quicker to test and figure out the exact scraping requirements for your device that way. Then, when that works, I'd implement it in Qt.Cheers.
-
@Paul-Colby said in Send SMS using Qt and wireless router DWR 730:
curl
Thank you very much for your help.
I have never used before http and/or Java ...
My last try is summarized here below.
My purpose for now is to login the router from my application.
Maybe from the information I reported here below it is easier for you to help me.Thank you very much again for your help.
The first page of my router shows two line-edit to write the username and the password, and a button to login.
The router's IP address is 192.168.0.1, the username is admin and there is no password.In my Qt application I have a class (CC_SmsMngr) which has the constructor and some not working functions!
The constructor is as follow:
CC_SmsMngr::CC_SmsMngr(QWidget *parent)
{
pLogManager = CC_LogManager::bGetInstance();
pRouterWidget = parent;view = new QWebEngineView(pRouterWidget); view->setZoomFactor(0.5); pNetAccessManager = new QNetworkAccessManager(); connect(pNetAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(vManage_finished(QNetworkReply*))); request.setUrl(qUrl); pData = pNetAccessManager->get(request); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "CC: SMS Manager CREATED");
}
In the main window of my application I have a Push button named "Login" and a slot that is executed when I click the push button.
The slot is as I reported here belowvoid CC_SmsMngr::vSlotLogin()
{
QUrlQuery urlQuery;pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "CC: SMS Manager ---> Router login"); qUrl.setUrl("http://192.168.0.1/login.cgi"); //// <--- I changed in many ways this part of the code but always failed. urlQuery.addQueryItem("Account", "admin"); qUrl.setQuery(urlQuery); request.setUrl(qUrl); pData = pNetAccessManager->get(request);
}
I have also a slot connected to the QNetworkAccessManager's "finished" signal named vManage_finished() as can be seen in the CC_SmsMngr constructor
void CC_SmsMngr::vManage_finished(QNetworkReply * qRouterReplay)
{
QString replyText;
int v;qRouterReplay->deleteLater(); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "CC: SMS Manager ---> vManage_finished()"); if(qRouterReplay->error() == QNetworkReply::NoError) { // Get the http status code v = qRouterReplay->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if (v >= 200 && v < 300) // Success { replyText.clear(); replyText = qRouterReplay->readAll(); //view->setContent(replyText.toLocal8Bit(),"XHTML",qUrl);//Shows the text view->setHtml(replyText.toLocal8Bit(), qUrl); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "//------------------------------------------------------------------------------------------"); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "//------------------------------------------------------------------------------------------"); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "//------------------------------------------------------------------------------------------"); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "THE ROUTER HAS ACCEPTED THE REQUEST"); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, qUrl.toString()); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "Request Headers:"); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, request.rawHeader(QByteArray("Host"))); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, request.rawHeader(QByteArray("User-Agent"))); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, request.rawHeader(QByteArray("Accept"))); // pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "Request Body:"); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, request.url().toString()); // pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "Replay:"); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, replyText); } else if (v >= 300 && v < 400) // Redirection { // Get the redirection url QUrl newUrl = qRouterReplay->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); // Because the redirection url can be relative, // we have to use the previous one to resolve it newUrl = qRouterReplay->url().resolved(newUrl); QNetworkAccessManager *manager = qRouterReplay->manager(); QNetworkRequest redirection(newUrl); QNetworkReply *newReply = manager->get(redirection); //view->load(newUrl); replyText = newReply->readAll(); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "//------------------------------------------------------------------------------------------"); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "//------------------------------------------------------------------------------------------"); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "//------------------------------------------------------------------------------------------"); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "THE ROUTER HAS REDIRECTED THE REQUEST"); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, qUrl.toString()); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "TOWARDS"); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, newUrl.toString()); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, newUrl.errorString()); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "Request Headers:"); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, request.rawHeader(QByteArray("Host"))); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, request.rawHeader(QByteArray("User-Agent"))); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, request.rawHeader(QByteArray("Accept"))); // pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "Request Body:"); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, request.url().toString()); // pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, replyText); } } else { // Error pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "Request Headers:"); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, request.rawHeader(QByteArray("Host"))); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, request.rawHeader(QByteArray("User-Agent"))); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, request.rawHeader(QByteArray("Accept"))); // pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, "Request Body:"); pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, request.url().toString()); // pLogManager->vWriteMsgToLogFile(CC_DEF_LOG_MSG_GRAV_SYS_MSG, qRouterReplay->errorString()); } //qRouterReplay->manager()->deleteLater();
}
When I launch my application it creates the CC_SmsMngr object and the router main page is shown.
If I click the login button the slot vSlotLogin() starts but after some redirections the router main page is shown in the main window of my application.
To navigate the router's page from my application is possible using QNetworkAccessManager!! I used mozilla firefox to login my router and I logged
the http messages obtaining the SID value. Then I used the obtained SID value in the qUrl.setUrl("http://192.168.0.1/........"); instruction in the vSlotLogin()
and, this way, in the main window of my application I saw the requested router's page.The problem (for now) is that I can't login from the application.
I tried to attach the log generated during a try but is too long.
I'll try again following your advices and let you know.
Thanks a lot.
-
Thank you for your replay.
My router doesn't have an API. Or at least I didn't find one.
Do you know a router that has an API suitable to be used with Qt?Thank you very much.
-
This post is deleted!