PDA

View Full Version : QT interface with telnet (hyperterminal) connection. Plotting received data



Ethan
7th July 2011, 12:32
Hello everybody,

I am newbie in QT, but this last month I have been dealing with C++ and the SDK environment. What I want to do is to focus properly in how to develop my application, which is explained in the following:

I have a wireless device which can transmit 802.11 data. It creates a point to point network. I could do this (it has nothing to do with QT yet...) by the next steps:

1- I connect to the network created (by using the windows manager).

2- I do a telnet connection by the hyperterminal by using TCP/IP (Winsock) or executing "telnet 164.256.1.1 2000" directly from the console.

3- Once it is done, I can send ASCII commands to retrieve data.

Having said that, what I want to do is the steps 2 and 3 automatically and create a QT graphical interface for:

a) Establish some buttons that send specific commands (in the same way I can do with the hyperterminal)

b) Store data received from the device (they are sent in ASCII commands, which I could see in the hyperterminal) and to graph them in the QT graphical interface in "real time" (e.g. send the command "give the state of your output" each second and graph the reception in the graphical interface)

Can you tell me how could I carry out this, or what could be a good starting point (libraries to use)? My main concern is how to manage the wifi connection (because I understand I am doing a telnet procotol in the application layer with TCP/IP protocol in the transport layer, using a wifi connection of type ad hoc -the device connected to my pc-), the graphical part I think can be easy once the connection with the device is established. Also, I would like to know if there is something already done, because I am almost sure that what I want to do can be done with QT.

Any thought will be very useful, since I am in the starting point.

Thanks a lot,

-E

stampede
7th July 2011, 22:44
I do a telnet connection by the hyperterminal by using TCP/IP (Winsock) or executing "telnet 164.256.1.1 2000" directly from the console.

3- Once it is done, I can send ASCII commands to retrieve data.

Having said that, what I want to do is the steps 2 and 3 automatically and create a QT graphical interface for:

a) Establish some buttons that send specific commands (in the same way I can do with the hyperterminal)

b) Store data received from the device (they are sent in ASCII commands, which I could see in the hyperterminal) and to graph them in the QT graphical interface in "real time"
If I get it right, I think QProcess sounds good for this task. You can start by reading docs here (http://doc.qt.nokia.com/latest/qprocess.html).

Ethan
8th July 2011, 09:15
Hello Stampede,

Thanks a lot for your answer. But maybe I did not explain very well what I want to do. I do not want to create a QT gui that connects with the hyperterminal. My intention is also to manage that connection with QT itself. Since I know it works with hyperterminal or executing "telnet 164.256.1.1 2000", I was wondering if this can be done with QT.
Then what I want to know is how to send ASCII commands once the connection is established, as well as to receive them. Can it be possible?

Regards,

-E

stampede
8th July 2011, 09:35
Since I know it works with hyperterminal or executing "telnet 164.256.1.1 2000", I was wondering if this can be done with QT.
Then what I want to know is to send ASCII commands once the connection is established, as well as to receive them. Can it be possible?
I think you can open the "telnet 164.256.1.1" with QProcess, then you can write and read to / from it - to send commands use write (http://doc.qt.nokia.com/latest/qiodevice.html#write-2) method. You can receive them when waiting for readyRead (http://doc.qt.nokia.com/latest/qiodevice.html#readyRead) signal and then calling one of read methods: read (http://doc.qt.nokia.com/latest/qiodevice.html#read), readLine (http://doc.qt.nokia.com/latest/qiodevice.html#readLine), getChar (http://doc.qt.nokia.com/latest/qiodevice.html#getChar), readAllStandardOutput / readAllStandardError (http://doc.qt.nokia.com/latest/qprocess.html#readAllStandardError).

Ethan
8th July 2011, 10:10
Thanks again.

Yes, I could (i think) do that, but I see that Qtprocess is not compatible with Symbian for example, so I could not migrate my application to another system different from a pc. That's why I want to manage the connection without external applications and only with the QT libraries (i am taking a look now to QtTelnet class and the network examples that come with the SDK). Looking for other possible solutions :).

Thanks a lot,

-E

stampede
8th July 2011, 10:32
Ok, good luck with your project ;)
I'm just curious, what do you mean by this:

I see that Qtprocess is not compatible with Symbian for example
Only limitation I see in documentation is related to some security requirements:

On Symbian, processes which use the functions kill() or terminate() must have the PowerMgmt platform security capability. If the client process lacks this capability, these functions will fail.
I'm not programming mobile devices, but I'm curious, can you post a link ?

Ethan
8th July 2011, 11:17
Hello again!
In the link you sent me I read "Note: On Windows CE and Symbian, reading and writing to a process is not supported." So I can guess I could have some problems when trying to migrate the application to symbian/android (not sure enough). Anyways I will try your solution. However, I am also curious. I seem to understand that with Qtprocess you are interacting with an external application. Don't you think we could establish the connection with the QT libraries themselves (maybe Qtcpsocket)?

Thank you very much for your time,

-E

stampede
8th July 2011, 11:23
Ok thanks, I missed that somehow.

with Qtprocess you are interacting with an external application
Thats correct, I thought about running telnet this way.

Don't you think we could establish the connection with the QT libraries themselves (maybe Qtcpsocket)?
I guess if you can connect by the "hyperterminal by using TCP/IP (Winsock) ", you can use sockets directly as well.

Ethan
8th July 2011, 15:58
Thanks again!. Any other suggestions from the expert community :)? In the meanwhile i'll be trying to solve it by myself. My intention is to publish the code after.

Cheers,

-E

nix
11th July 2011, 14:46
Hi,
I'm responding here according to the PM you sent.

I used QtTelnet from QtSolutions in the past and it works fine for me. I have only used it under linux I can tell how it works in other worlds.
Unfortunately QtSolutions is not managed anymore by Nokia , can be found here http://qt.gitorious.org/qt-solutions. QtTelnet seems to be available only for Qt 4.4 & Qt 4.5. I look quickly in the git where QtSolutions can be found but I found no reference to QtTelnet any more.

If you are interested I should have a tarball somewhere with the source code of QtTelnet (a version which work fine with Qt 4.6.2), maybe you can compile it for your Qt version successfully.

You can have an idea of what QtTelnet do at http://doc.qt.nokia.com/solutions/4/qttelnet/qttelnet.html

In my case I used it to display on a PC remote log file in real time (tail -f /var/log/message on the telnet shell and display the result in a QTextEdit).

Ethan
12th July 2011, 16:20
Hello Nix,

Yes, I would be interested in the source code you used. I have to say that I am a little bit surprised that new versions of QT cannot manage a Telnet connection with an ad-hoc network. I "only" need to do something like "telnet 169.254.1.1 2000". With a terminal emulator it works fine, why should not I do this with QT only?

I think some classes in the Network library can do this, but I am unable to find the way.

Let me know if you can do the tarball you mentioned. I´ll continue looking for a solution.

Thanks a lot,

-E

ChrisW67
13th July 2011, 01:21
You can do a simple stream of commands trivially with a QTcpSocket and state machine. If you want a full implementation of Telnet (RFC 854 (http://www.faqs.org/rfcs/rfc854.html)) with its interupt handling, and virtual terminal requirements then that is a more complicated and specific problem.



#include <QtCore>
#include <QtNetwork>
#include <QDebug>

class Example: public QObject {
Q_OBJECT
public:
Example(QObject *p = 0): QObject(p) {
connect(&sock, SIGNAL(connected()), this, SLOT(connected()));
connect(&sock, SIGNAL(disconnected()), this, SLOT(disconnected()));
connect(&sock, SIGNAL(readyRead()), this, SLOT(readyRead()));
}

void run() {
sock.connectToHost("www.google.com", 80);

}
public slots:
void connected() {
QByteArray ba("GET / HTTP/1.0\r\n\r\n");
sock.write(ba);
qDebug() << "Wrote:" << ba;
}
void disconnected() {
qDebug() << "Disconnected";
qApp->exit();
}
void readyRead() {
QByteArray ba = sock.readAll();
qDebug() << "Read:" << ba;
}

private:
QTcpSocket sock;
};

int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);

Example e;
e.run();

return app.exec();
}
#include "main.moc"

nix
13th July 2011, 08:21
Exactly, I'm not sure we are really agree with what Telnet is.

Telnet run usually on port 23, it is a TCP server communicating using a given protocol (can ask you login and give you a shell, interpret some special sequences characters ....).
If you just want to connect to a port (2000) and send some data of your own you just have to use QTcpSocket that all.

Please give more detail on what you want to do on the port you used and which commands (actions) you want a run. Or maybe, simply post the data you sent in your hyperterminal to be sure there is no misunderstanding here.

Ethan
13th July 2011, 12:46
Hello again Nix,

First of all, thank you for your time. I thought the same as you with regards to the Telnet protocol, it is usually on port 23, but in the case of the device i am trying to communicate the connection is carried out on port 2000.

I am working with a device from roving networks. What I want to do exactly is in this link: http://www.rovingnetworks.com/Docs/WiFly-RN-UM.pdf

Pages 6-9 shows what I want to do. It is just to create an ad-hoc connection between the device and my pc, connect to it and sends ASCII commands that provide me some response (for example the value of some digital inputs the device has). By using Teraterm or Hyperterminal emulators I can do this (it is, connect doing a telnet 169.254.1.1 2000 and send ASCII commands) . What I want to do is just the same but through a QT interface that manages this Telnet connection.

For example, one ASCII command I would like to send is "show q", when writing this in the hyperterminal I can see this answer:

<2.21> show q
87377a,
<2.21>

Then, with this value I would try to do something in the QT interface, for example a plot. And that is mainly what I want to do, to receive these sort of data by the QT interface.

As you can read in page 9, what is done is a telnet connection throught wifi, but on port 2000 instead of port 23.

Thanks a lot,

-E

stampede
13th July 2011, 14:02
@up: reported to forum staff, advertisements are forbidden

nix
13th July 2011, 14:05
Ok, it's just a problem of misunderstanding. They use telnet term in the doc but it's only a classic tcp socket you need. So you have to use QTcpSocket and probably add a state machine too, in order to manage the protocol.
A good next move will be : read the documentation of QTcpSocket, QAbstractSocket and take a look to Fortune Client Example (in qt sources).

Ethan
13th July 2011, 14:33
May I ask why do you know it is not a Telnet protocol ? ChrisW67 answered the same as you. Thanks for the info, I am going to take a look to the documentation you mentioned.

-E

nix
13th July 2011, 14:53
Because when you look at the way your device communicate in the documentation it has nothing to do with telnet standard protocol :).

In fact this is a bit confusing because you can use a command like
telnet 169.254.1.1 2000 to communicate with your device but it's just the name of a program and that not mean your are using full Telnet protocol. In your case it's just a socket, telnet programm send the data you give to the other side and display data it received. You can do that easily with QTcpSocket.

ChrisW67
13th July 2011, 23:25
If you never send anything but ASCII characters and expect them in return then the standard telnet client is just a glorified TCP socket giving a transparent pipe. If you send any of the telnet escape codes (bytes with values 240 - 255) then telnet can diverge from being a transparent pipe.

Ethan
19th September 2011, 13:31
The code posted by ChrisW67 works fine for me. In my case, I changed this part:


void connected() {
QByteArray ba("GET / HTTP/1.0\r\n\r\n");
sock.write(ba);
qDebug() << "Wrote:" << ba;


by this one:


public slots:
void connected()
{
QByteArray ba("$$$");
sock.write(ba);
qDebug() << "Wrote:" << ba;
}


And everything seems to work fine, I can see I receive Read: "*Hello*" and Read: "CMD", which means that the device is answering to the command "$$$" I sent. However, what I would like to do is to send another ASCII command and then receive data. I thought about doing this:



public slots:
void connected()
{
QByteArray ba("$$$");
sock.write(ba);
qDebug() << "Wrote:" << ba;
QByteArray bb("show q\r");
sock.write(bb);
qDebug() << "Wrote:" << bb;
}


But this does not work, after sending "show q" in the last variation of the connected method I should receive (appart from Read: "*Hello*" and Read: "CMD") something like "8735b7", however i receive only "Hello", and even I dont receive CMD (which is the response when "$$$" is sent), and that is why i know i am doing something wrong when trying to write two times in the connected method.

My goal is to send different commands and receive data (send command and receive response, send another command and receive response...). Im planning to do it with a widget, but first I would like to do it just by code or by using the console. Any suggestion?

Kind regards,

-E

ChrisW67
19th September 2011, 23:22
Your code assumes that the write() calls are blocking. This is not the case in Qt. The write() calls queue data to be sent, but it will not actually be sent until the program returns to the event loop. Some time later the data will have been sent and a result (possibly) received. The other end will probably receive your two commands immediately after each other: how it handles that depends on their software. This is why I suggested some sort of state machine. The complexity involved depends on how flexible the script of commands must be and how fault tolerant you need to be.

Ethan
24th September 2011, 18:49
I got what you meant ChrisW67 and I could fix my problem, thanks.

I restructured my code and I created a small interface with Designer.
Now I send the "$$$" command and with a QLineEdit widget I can send another commands, the device is answering, but there is yet something strange.

If I use hyperterminal when sending the "show q" command I receive something like:

8735db,
<2.21>

However, with QT I receive:

Received:
" show q
Received:
"
8735db,
<2.21> "

So it seems I am receiving an echo which I do not receive with hyperterminal or another program such as UTF-Teraterm. The main parts which are related with this in my QT code are the followings:



//In the constructor of my class

connect(lineEdit, SIGNAL(clicked()),this, SLOT(sendCommand()));
connect(&sock, SIGNAL(readyRead()), this, SLOT(receiveData()));

//Custom Slots
void FindDialog::sendCommand()
{
QByteArray str = lineEdit->text().toLocal8Bit();
sock.write(str);
sock.write("\r");
qDebug() << " Wrote: " << str;
}

void FindDialog::receiveData()
{
QByteArray ba;
ba = sock.readAll();
display->setText(ba);
qDebug() << " Received: " << ba;
}


Basically, when pressing a QpushButton I send "show q", and it seems receiveData() is executed twice!! ("received" in Qdebug appears two times when pressing the pushbutton). I am thinking it has something to do with the ReadyRead().

I am almost 100 (because it does not happen with hyperterminal and UTF-Teraterm and customer support of the device answered me that it does not echo the remote data packets back to the sender) sure the device does not make echo of what I send, so which can be the reason of this behaviour? Am I missing something with the socket connection?.

Kind regards,

-E

ChrisW67
24th September 2011, 23:07
This is odd. Anything professing to do TELNET should default to no echo over the wire. There is a mechanism to negotiate echo but I think this is probably not where you want to go.

Are you sure that the remote end is expecting a carriage return ('\r') without a line feed ('\n') at line 11 ? Perhaps the echo is an error indication. What is the character before the "show q" is the response? You might need to dump the incoming byte array as hex to see.

Ethan
27th September 2011, 13:15
I tried both, with carriage return ('\r') and line feed ('\n') and with only carriage return ('\r'). I also did a netcat (netcat ip port) and what surprised me is that in that case I received the echo, which does not happen with Teraterm pro or Hyperterminal. The support service of the device told me that the connection is just a socket on a port and the devices does not dont echo the remote data packets back to the sender. So, that's odd but I think it has something to do with the carriage return. For now what i am doing is removing the echo when receiving the data (not the best solution...)

-E

ChrisW67
28th September 2011, 01:16
Firstly I would expect the receiver to take either a lone \n or the \r\n pair (which you haven't tried AFAICT).
If you see the echo with netcat then this is not a Qt issue.

Use the -o option of nc to capture a hex dump of the "show q" outbound message and its inbound response. Post it.

Ethan
29th September 2011, 18:22
Hello ChrisW67,

Thanks. Although I didnt tell in my previous post, I also tried \n and \r\n, in the first case the device does response, and in the second (\r\n) the response is the same one with only \r, i.e., an echo and after the expected data.

I tried "nc -o <ip file> <port> but I am not able of capturing my outbound message.

**Here is what I have so far with netcat:

I first send "$$$" to enter in command mode and the device answer me with "CMD" as expected (NOTE: $$$ is sent without carrier return or line feed)
After that, I send "show q" only, although I tried to send carriage return and line feed (i have read it is possible by pressing ctrl+v or ctrl+m, but I am not sure if it that is true). This is what I record in a txt file.

< 00000000 43 4d 44 0d 0a # CMD..
< 00000005 73 68 6f 77 20 71 0a # show q.
< 0000000c 73 68 6f 77 20 71 2e 0a # show q..
< 00000014 73 73 68 68 6f 6f 77 77 20 71 16 0a # sshhooww q..
< 00000020 73 68 6f 77 20 71 2e 0a # show q..
< 00000028 73 68 6f 77 20 71 0a # show q.
< 0000002f 73 68 6f 77 20 71 0a # show q.
< 00000036 73 68 6f 77 20 71 0a # show q.
< 0000003d 73 68 6f 77 20 71 0a # show q.
< 00000044 73 68 6f 77 20 71 0a # show q.
< 0000004b 73 68 6f 77 20 71 0a # show q.
< 00000052 73 68 6f 77 20 71 0a # show q.
< 00000059 73 68 6f 77 20 71 0a # show q.
< 00000060 0d 0a 38 37 33 35 38 36 2c 0d 0a 3c 32 2e 32 38 # ..873586,..<2.28
< 00000070 3e 20 # >
< 00000072 73 68 6f 77 20 71 0a # show q.


As you can see, in the third last line I receive the data!

However, this is the response with Hyperterminal (which is what i wanted to receive with qt, the expected answer, without echo):
CMD //response to $$$

show q //command i send




<2.28> show q //response and I write in this line "show q"
//response
//response
8735c3, //response

<2.28> show q //i send again show q, <2.28> is also part of the previous response.
//response
//response
873549, //response
//response
<2.28> //response

//response
873530, //response
//response
<2.28> //response



Thanks,

-E

ChrisW67
30th September 2011, 02:32
Your log file indicates only inbound traffic, and clearly that contains (mostly broken) echoed commands. This is not a Qt issue.

To capture a clean run you should put the commands you wish to execute into a file (commands.txt):


$$$
show q

then execute netcat:


nc -o hex.log -i 3 -w 10 host port < commands.txt

The lines will be sent with 3 second delays between to allow any processing time and terminate 10 seconds after the last command. The result should capture everything in and out and give you something to send to the vendor to demonstrate the echo problem. Here is an example from a simple SMTP server connection:


< 00000000 32 32 30 2d 69 70 6d 61 69 6c 30 37 2e 61 64 6c # 220-ipmail07.adl
< 00000010 32 2e 69 6e 74 65 72 6e 6f 64 65 2e 6f 6e 2e 6e # 2.internode.on.n
< 00000020 65 74 20 45 53 4d 54 50 0d 0a 32 32 30 20 45 53 # et ESMTP..220 ES
< 00000030 4d 54 50 3b 20 70 70 70 31 31 38 2d 32 30 38 2d # MTP; ppp118-208-
< 00000040 31 30 31 2d 31 37 30 2e 6c 6e 73 32 30 2e 62 6e # 101-170.lns20.bn
< 00000050 65 34 2e 69 6e 74 65 72 6e 6f 64 65 2e 6f 6e 2e # e4.internode.on.
< 00000060 6e 65 74 20 5b 31 31 38 2e 32 30 38 2e 31 30 31 # net [118.208.101
< 00000070 2e 31 37 30 5d 20 69 6e 20 4d 54 41 27 73 20 49 # .170] in MTA's I
< 00000080 4e 53 49 44 45 69 6e 74 65 72 6e 6f 64 65 3b 20 # NSIDEinternode;
< 00000090 64 72 69 76 69 6e 27 20 69 6e 74 6f 20 74 68 65 # drivin' into the
< 000000a0 20 73 75 6e 73 65 74 0d 0a # sunset..
> 00000000 48 45 4c 4f 20 6e 65 77 74 6f 6e 0a # HELO newton.
< 000000a9 32 35 30 20 69 70 6d 61 69 6c 30 37 2e 61 64 6c # 250 ipmail07.adl
< 000000b9 32 2e 69 6e 74 65 72 6e 6f 64 65 2e 6f 6e 2e 6e # 2.internode.on.n
< 000000c9 65 74 0d 0a # et..
> 0000000c 51 55 49 54 0a # QUIT.
< 000000cd 32 32 31 20 69 70 6d 61 69 6c 30 37 2e 61 64 6c # 221 ipmail07.adl
< 000000dd 32 2e 69 6e 74 65 72 6e 6f 64 65 2e 6f 6e 2e 6e # 2.internode.on.n
< 000000ed 65 74 0d 0a # et..

Ethan
30th September 2011, 11:02
Definitely, there seems to be an echo. After putting the commands "$$$" and "show q" into a file (commands.txt) and running netcat, my hex.log is as follows:


< 00000000 43 4d 44 0d 0a # CMD..
< 00000005 73 68 6f 77 20 71 0d 0a 0d 0a 38 37 33 38 62 38 # show q....8738b8
< 00000015 2c 0d 0a 3c 32 2e 32 38 3e 20 # ,..<2.28>

The only thing that I dont understand is why I dont see such an echo with Teraterm-pro or Hyperterminal. In any case, the information you have provided me through all this thread is very valuable to me to begin to understand how a socket connection works.

Thank you very much for your kind help Chrisw67.

-E

ChrisW67
30th September 2011, 22:26
Your hex log doesn't contain any of your outbound transmissions. They are indicated by ">" rather than "<". Have you removed them?

You can use Wireshark (http://www.wireshark.org/) to watch exactly what goes back and forth between HyperTerminal/TeraTerm and the device.

Ethan
1st October 2011, 17:16
I didnt remove anything, this is exactly the hex.log recorded with the nc sentence. I thought it is odd that netcat did not record in the .log the outbound transmissions ( maybe version ?, dont know). Yes, I am planning to use wireshark.

-E

Nitish157
28th August 2012, 13:27
Hi Ethan ,
Can you please tell how you control telnet through QT GUI. I am getting Hostname not found error while trying to connect using QtTcpSocket..

Can you plese share how you do it.

Nitish

ChrisW67
28th August 2012, 22:55
"Hostname not found" means that the host name you gave whatever program issued that error message could not be resolved into an address. This is either a bad name on your part, or a bad DNS or hosts file. I fail to see what this has to do with Qt.