PDA

View Full Version : How to write bytes read from serial port to a QFile



shamik
15th June 2007, 07:52
hiii friends,

i am using Qt3.3.6 on Fedora Core-6 OS.
i have written a code to read data from the serial port. It reads the data and prints on the terminal and also writes to a QFile.
The code is as follows


#include<termios.h>
#include<fcntl.h>
#include<errno.h>
#include<sys/ioctl.h>
#include<stdio.h>
#include<sys/time.h>
#include<iostream.h>
#include<sys/types.h>
#include<unistd.h>
#include<string.h>
#include <qfile.h>
#include <qdatastream.h>
#include <qstring.h>
#include <qmessagebox.h>
#include <qapplication.h>
#include <qtextstream.h>


main ()
{

struct termios t;
char *devicedest = "/dev/ttyr00";

unsigned char recvbuf[2];
int rbyte, status, sPortdest,r,i,c=0;
long count=0;

int inp_check=0;
int ifirst=0;
QFile ff("/root/ss.txt");
ff.open( IO_WriteOnly );
QTextStream stream(&ff);
QString buff = "";

struct timeval timeout;
fd_set testfds,readfds;


t.c_cc[VMIN] = 1;
t.c_cc[VTIME]=0;
// t.c_cc[VEOF]='\n';
/* t.c_iflag &= ~(BRKINT|IGNPAR|PARMRK|INPCK|INLCR|IGNCR|ICRNL|IXO N);
t.c_iflag |= (IGNBRK|ISTRIP|IXOFF);
t.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON|ISIG|NOFLSH|TOSTO P);
t.c_cflag &= (CSIZE|CSTOPB|HUPCL|PARENB);
t.c_cflag |= (CLOCAL|CREAD|CS8);*/
// t.c_iflag |= (ISIG);
// t.c_iflag &= ~(IUCLC);

// t.c_iflag &= ~BRKINT;

t.c_iflag = (ISIG | IUCLC) ;
t.c_cflag = B9600 | CS8 | CREAD | CLOCAL| HUPCL;


sPortdest= open(devicedest,O_RDONLY|O_NOCTTY|O_NDELAY);
if(tcsetattr(sPortdest,TCSANOW,&t) != 0 )
{
cout<<"\n attribute not set";
}
FD_ZERO(&readfds);
FD_SET(sPortdest,&readfds);


if(sPortdest!=-1)
{
cout<<"Open successfully\n";
do
{
testfds = readfds;

timeout.tv_sec=0;
timeout.tv_usec=1000;

r=select(FD_SETSIZE,&testfds,(fd_set *)0,(fd_set *)0,&timeout);

if(r == -1)
cout<<"Error in select";


//Activity happen on some ports
if(r > 0)
{
//check all

for(i=0;i<FD_SETSIZE;i++)
{

if(FD_ISSET(i,&testfds))
{
//Activity on serial port
if(i == sPortdest)
{

if(ifirst == 0) //Set all attribute when first start
{
status = ioctl(sPortdest,TCSETS,t);
ifirst = 1;
}
rbyte= read(sPortdest,recvbuf,1);

if(rbyte > 0)
{
recvbuf[1]='\0';
cout<<recvbuf;
stream<<recvbuf;
count++;
if((count%11)==0)
{
// cout<<"";

}
usleep(1000);
}
}
}
}
}

//Activity not happen on SP
if(r == 0)
{
//cout<<"\nwaiting\n";
usleep(1000);
ff.close();

}

}while(1);
}
else
{
cout<<"Device could not be oepn successfully";
}


}



when i run this code on the terminal, it shows the file correctly on the terminal but it data written to the file is in some other format ( may b in hex). only integer numbers are getting stored in the file and not the actual characters.
also when i run the program for the first time after tranmitting the file from other end, it says error : QFile::writeBlock() file not open.
then i have to terminate the program and again run it. Then it does not give that error. But anyways the data written to the file is not the one getting printed to the terminal. On terminal the exact characters/numbers are printed while on the file some ascii or integer numbers get stored.

please tell me how to solve this problem

high_flyer
15th June 2007, 10:26
try:


stream<<(const char*)recvbuf;
//or
stream<<(char*)recvbuf;

shamik
15th June 2007, 12:16
thanks for the reply

the mistake was actually somewhere else

if u see the code deeply, then i have closed the file and then for writing the data i was not opening it.

now the file is being written correctly
i just want to ask one thing now
and that is i m currently transferring text files and writing the same to another text file. is it possible to transfer any kind of binary files like pdf, zip, jpg etc. and recieve it in the same format using the same code listed above? may be the slightest modification i guess would be to use QDataStream rather than QTextStream

wat Say??

high_flyer
15th June 2007, 12:43
if u see the code deeply, then i have closed the file and then for writing the data i was not opening it.
But you said you are getting data in the file, just not the same as you get in the console.
How is it possible you got data in the file if it was closed? (not that I am saying that what you said is not the problem, since obviously you had it corrected, but I still don't understand how this is possible).


is it possible to transfer any kind of binary files like pdf, zip, jpg etc. and recieve it in the same format using the same code listed above? may be the slightest modification i guess would be to use QDataStream rather than QTextStream
Yes, for this you need to use QDataStream if you want to use a tream.
Ah just a second, you are not using QextSerailPort - so you can't use QDataStream.
So you will have to read the input data in binary form and transmit it the same similar to what you have done above.
Nothing speciall actually.

shamik
15th June 2007, 13:16
So you will have to read the input data in binary form and transmit it the same similar to what you have done above.
Nothing speciall actually.

i dint get u
do you mean i dont need to change my code ??

high_flyer
15th June 2007, 13:23
Yes you will need to change a bit.
I was not sure if you want to read the data from the serial port or from a file and send through serial port.
If you are getting the data through the serial port, then you can use QDataStream and QFile to save that binary data in its origianl binary form (not text).

EDIT:
by using QextSerialPort this is really easy, just few lines of code since both QextSerial and QFile are QIODevices, that you can use with QDataStream.

shamik
15th June 2007, 13:30
so u mean 2 say just by using QDataStream in place of QTextStream in the above code will do !!! rite

i have already got QExtSerial package with me. But i am afraid of using it since i m finding it difficult. if this code will work fine with other file formats also by using QDataStream then i think i wont b using QExtSerial for that. In my current code i m just reading the data from the serial port. but the application involves sending file through serial port also.

if anybody has some code in which there is use of QExtSerial then please post it over here. it will b of gr8 help.

best regards,

high_flyer
15th June 2007, 13:41
for goodness sake,please don't use sms lingo.
You have a kyeboard, use it.

Well, basically yes, it would be enough if you change to QDataStream, and write access to the file should be binary raw.

But your whole approach is not very nice.
You are reading one char at a time, and write one char at a time.
Why not read everything at once (or large chunks) and write is so as well.

I think QextSerialPort is much easier then what you used here, and it plays nicely with Qt.

But do what you think is the best for you.

shamik
21st June 2007, 13:14
in my above code i have changed from QTextStream to QDataStream.

but i not able to write the file properly.
if the file is simple text file then it is written correctly but if it something else like .doc, .pdf etc. then i m not able to write to the file. the data written to the file is also not readable on the terminal as u might c from the code that i m also printing the data on the terminal and writing the same to the file simultaneously.

please tell me wat 2 do in that case. is it that this problem cant be solved without using QExtSerial ??

high_flyer
21st June 2007, 13:37
how do you expect us to answer that with out seeing the code you are talking about?

PLEASE don't use sms short typing!

shamik
21st June 2007, 14:07
the code is already posted above

the only difference is instead of QTextStream i have used QDataStream

high_flyer
21st June 2007, 14:36
you might want to try writeRawBytes() (http://doc.trolltech.com/3.3/qdatastream.html#writeRawBytes)
And you also should open the file in raw mode (IO_Raw)(as I told you before) .

shamik
21st June 2007, 15:40
i have done following modifications in the above code :


ff.open( IO_Raw | IO_WriteOnly | IO_Append);
stream.writeRawBytes((const char *)recbuf, 1);

but still the problem is that the file size is the same i.e. exact number of bytes are getting written but i m not able to read that file.
i.e. if i transfer a pdf file then the pdf reader is not able to read the file
if i transfer a .doc file then openoffice is not able to read the file
if i transfer a .jpg file then picture viewer is not able to read the file

can u please tell now what to do ??

high_flyer
21st June 2007, 16:03
hmm...
Try openning both files (the original and the one you wrote through the serial port) with an hex editor/viewer, this might show you what in fact is being written from your code.

shamik
22nd June 2007, 07:05
hmm...
Try openning both files (the original and the one you wrote through the serial port) with an hex editor/viewer, this might show you what in fact is being written from your code.

what is hex editor/viewer and how can i open it?
can you please tell how to open both the files original and the one i wrote through serial port.
it would be quite helpful if you can explain in detail or can provide some code

high_flyer
22nd June 2007, 09:52
Hex editor (http://en.wikipedia.org/wiki/Hex_editor)
Ask if you have further questions.

shamik
25th June 2007, 12:40
i have now tried to use QExtSerialPort and have written a small application using is which is as follows :


#include </sfiles/Serial Communication/qextserialport-0.9.0/posix_qextserialport.h>
#include </sfiles/Serial Communication/qextserialport-0.9.0/qextserialbase.h>
#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#include <qfile.h>
#include <qapplication.h>
#include <qstring.h>
#include <qmessagebox.h>
#include <qdatastream.h>
#include <qtextstream.h>



void Form1::send_clicked()
{
QFile ff("/root/ss.txt");
QDataStream stream(&ff);
ff.open( IO_ReadOnly );

if(ff.exists())
{
qWarning("file exists");
}
else
{
qWarning("file does not exists");
}

Posix_QextSerialPort sp("/dev/ttyS0");
sp.open();
sp.flush();
char *data = new char();
ff.readBlock(data, 15);
if ( !sp.isOpen())
{
qWarning("port not opened");
}
else
{
qWarning("port opened successfully");
}
qWarning("Writing data ... ");
qWarning(data);
sp.writeBlock(data , 15);
sp.close();
ff.close();
if(sp.open())
{
qWarning("port still open after closing");
}
else
{
qWarning("port closed successfully");
}
qWarning("Data written successfully..........now exiting");
close();


}


void Form1::recieve_clicked()
{
QFile ff("/root/sss.txt");
Posix_QextSerialPort sp("/dev/ttyS0");
sp.open();
if(!sp.isOpen())
{
qWarning("port not opened");
}
else
{
qWarning("port opened successfully");
}
char *data = new char();
while(1)
{
//sleep(1000);
//cout<<"No bytes currently waiting on the port "<<endl;

if(sp.bytesWaiting()>0)
{
ff.open( IO_Raw | IO_WriteOnly | IO_Append );
cout<<"Bytes waiting ---"<<sp.bytesWaiting()<<endl;
sp.readBlock(data,15);
ff.writeBlock(data,15);
ff.close();
}

}
sp.close();

}


i m quite sure that the libraries have compiled well.
i have added two pushbuttons in the applications through which you can send and recieve the data

by clicking on send button the output is as follows :


[root@localhost ftransfer]# ./ftransfer
file exists
port opened successfully
Writing data ...
God is Great

*** glibc detected *** ./ftransfer: malloc(): memory corruption (fast): 0x08332fe8 ***
======= Backtrace: =========
/lib/libc.so.6[0x29fe55]
/lib/libc.so.6(__libc_malloc+0x7e)[0x2a0d2e]
/usr/lib/libstdc++.so.6(_Znwj+0x27)[0x6875d27]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZN7QGArray7newDataEv+0x1e)[0x10f2a0e]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZN7QGArrayC2Ei+0x3b)[0x10f2c5b]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZN8QCStringC1Ei+0x2c)[0x10e2fac]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZNK10QUtf8Codec11fromUnicodeERK7QStringRi +0x4c)[0x114656c]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZNK10QTextCodec11fromUnicodeERK7QString+0 x39)[0x1140489]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZNK7QString9local8BitEv+0x39)[0x1114169]
/usr/lib/qt-3.3/lib/libqt-mt.so.3[0x10f0159]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZN5QFile10encodeNameERK7QString+0x2a)[0x10effba]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZN5QFile4openEi+0x101)[0x10d9161]
/usr/lib/libqextserialport.so.1(_ZN20Posix_QextSerialPort4o penEi+0x93)[0x9ac88b]
./ftransfer(_ZN7QWidget6createEmbb+0xe69)[0x804c285]
./ftransfer(_ZN7QWidget6createEmbb+0x16e9)[0x804cb05]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZN7QObject15activate_signalEP15QConnectio nListP8QUObject+0x16a)[0xdf8e2a]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZN7QObject15activate_signalEi+0xbd)[0xdf995d]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZN7QButton7clickedEv+0x2c)[0x118c8ac]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZN7QButton13keyPressEventEP9QKeyEvent+0x6 1)[0xe9c7b1]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZN7QWidget5eventEP6QEvent+0x36b)[0xe3627b]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZN12QApplication14internalNotifyEP7QObjec tP6QEvent+0x9b)[0xd900fb]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZN12QApplication6notifyEP7QObjectP6QEvent +0x54d)[0xd91a1d]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZN9QETWidget17translateKeyEventEPK7_XEven tb+0x36a)[0xd25b0a]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZN12QApplication15x11ProcessEventEP7_XEve nt+0x635)[0xd26a75]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZN10QEventLoop13processEventsEj+0x4eb)[0xd386ab]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZN10QEventLoop9enterLoopEv+0x42)[0xda9672]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZN10QEventLoop4execEv+0x26)[0xda9536]
/usr/lib/qt-3.3/lib/libqt-mt.so.3(_ZN12QApplication4execEv+0x1f)[0xd8fc0f]
./ftransfer(_ZNK7QDialog8sizeHintEv+0x173)[0x804be2f]
/lib/libc.so.6(__libc_start_main+0xdc)[0x24ef2c]
./ftransfer(_ZNK7QDialog8sizeHintEv+0x55)[0x804bd11]
======= Memory map: ========
00110000-0020e000 r-xp 00000000 03:07 483679 /usr/lib/libX11.so.6.2.0
0020e000-00212000 rwxp 000fe000 03:07 483679 /usr/lib/libX11.so.6.2.0
00212000-00237000 r-xp 00000000 03:07 1329150 /lib/libm-2.5.so
00237000-00238000 r-xp 00024000 03:07 1329150 /lib/libm-2.5.so
00238000-00239000 rwxp 00025000 03:07 1329150 /lib/libm-2.5.so
00239000-00370000 r-xp 00000000 03:07 1329143 /lib/libc-2.5.so
00370000-00372000 r-xp 00137000 03:07 1329143 /lib/libc-2.5.so
00372000-00373000 rwxp 00139000 03:07 1329143 /lib/libc-2.5.so
00373000-00376000 rwxp 00373000 00:00 0
00376000-00389000 r-xp 00000000 03:07 1329145 /lib/libpthread-2.5.so
00389000-0038a000 r-xp 00012000 03:07 1329145 /lib/libpthread-2.5.so
0038a000-0038b000 rwxp 00013000 03:07 1329145 /lib/libpthread-2.5.so
0038b000-0038d000 rwxp 0038b000 00:00 0
0038d000-003f5000 r-xp 00000000 03:07 483703 /usr/lib/libmng.so.1.0.0
003f5000-003f8000 rwxp 00067000 03:07 483703 /usr/lib/libmng.so.1.0.0
003f8000-0040a000 r-xp 00000000 03:07 483673 /usr/lib/libz.so.1.2.3
0040a000-0040b000 rwxp 00011000 03:07 483673 /usr/lib/libz.so.1.2.3
0040b000-0040e000 r-xp 00000000 03:07 483687 /usr/lib/libXrandr.so.2.0.0
0040e000-0040f000 rwxp 00002000 03:07 483687 /usr/lib/libXrandr.so.2.0.0
0040f000-00421000 r-xp 00000000 03:07 483704 /usr/lib/libXft.so.2.1.2
00421000-00422000 rwxp 00012000 03:07 483704 /usr/lib/libXft.so.2.1.2
00422000-00424000 r-xp 00000000 03:07 1329144 /lib/libdl-2.5.so
00424000-00425000 r-xp 00001000 03:07 1329144 /lib/libdl-2.5.so
00425000-00426000 rwxp 00002000 03:07 1329144 /lib/libdl-2.5.so
00426000-00428000 r-xp 00000000 03:07 483677 /usr/lib/libXau.so.6.0.0
00428000-00429000 rwxp 00001000 03:07 483677 /usr/lib/libXau.so.6.0.0
00429000-0042e000 r-xp 00000000 03:07 483678 /usr/lib/libXdmcp.so.6.0.0
0042e000-0042f000 rwxp 00004000 03:07 483678 /usr/lib/libXdmcp.so.6.0.0
0042f000-00460000 r-xp 00000000 03:07 483702 /usr/lib/liblcms.so.1.0.15
00460000-00461000 rwxp 00030000 03:07 483702 /usr/lib/liblcms.so.1.0.15
00461000-00464000 rwxp 00461000 00:00 0
00464000-00479000 r-xp 00000000 03:07 686877 /usr/lib/qt-3.3/plugins/styles/bluecurve.so
00479000-0047a000 rwxp 00015000 03:07 686877 /usr/lib/qt-3.3/plugins/styles/bluecurve.so
005c4000-005cd000 r-xp 00000000 03:07 487954 /lib/libnss_files-2.5.so
005cd000-005ce000 r-xp 00008000 03:07 487954 /lib/libnss_files-2.5.so
005ce000-005cf000 rwxp 00009000 03:07 487954 /lib/libnss_files-2.5.so
007e8000-007e9000 r-xp 007e8000 00:00 0 [vdso]
009a8000-009af000 r-xp 00000000 03:07 484535 /usr/lib/libqextserialport.so.1
009af000-009b0000 rwxp 00006000 03:07 484535 /usr/lib/libqextserialport.so.1
00ab3000-00ac2000 r-xp 00000000 03:07 483684 /usr/lib/libXext.so.6.4.0
00ac2000-00ac3000 rwxp 0000e000 03:07 483684 /usr/lib/libXext.so.6.4.0
00ac5000-00ae4000 r-xp 00000000 03:07 1329151 /lib/libexpat.so.0.5.0
00ae4000-00ae6000 rwxp 0001e000 03:07 1329151 /lib/libexpat.so.0.5.0
00ae8000-00b0f000 r-xp 00000000 03:07 483675 /usr/lib/libfontconfig.so.1.1.0
00b0f000-00b17000 rwxp 00027000 03:07 483675 /usr/lib/libfontconfig.so.1.1.0
00b19000-00b21000 r-xp 00000000 03:07 483680 /usr/lib/libXrender.so.1.3.0
00b21000-00b22000 rwxp 00007000 03:07 483680 /usr/lib/libXrender.so.1.3.0
00b24000-00b28000 r-xp 00000000 03:07 483688 /usr/lib/libXfixes.so.3.1.0
00b28000-00b29000 rwxp 00003000 03:07 483688 /usr/lib/libXfixes.so.3.1.0
00b2c000-00b45000 r-xp 00000000 03:07 1329142 /lib/ld-2.5.so
00b45000-00b46000 r-xp 00018000 03:07 1329142 /lib/ld-2.5.so
00b46000-00b47000 rwxp 00019000 03:07 1329142 /lib/ld-2.5.so
00b47000-01378000 r-xp 00000000 03:07 196091 /usr/lib/qt-3.3/lib/libqt-mt.so.3.3.6
01378000-013b9000 rwxp 00830000 03:07 196091 Aborted
[root@localhost ftransfer]#


after printing God is Great on the terminal it waits for about 1 min. and then immediately prints the above memory map and backtrace.

also when i clicke recieve the program hangs( i know i runs in infinite while loop) and nothing is recieved.

can anyone please tell me where is the fault ??

high_flyer
25th June 2007, 12:57
some comments:
1. why do you allocate the serial port on the stack?
make it a member, this way you don't need to allocate it in every method, and better on the heap.
It is dengeraus to do it the way you do.
2. why don't you use QDataStream on the serial port?
3. you want to use isOpen() not open() :


if(sp.isOpen()) //here
{
qWarning("port still open after closing");
}

It could well be that once you fix these points, the problem will go away, if not, posts again.

Another point:
You don't need to use Posix_QexSerial port, it is not portable.
Use QextSerialPort, and give the _TTY_POSIX_ flag in the make file.
This way your code will compile on windows as well.

shamik
25th June 2007, 14:13
why do you allocate the serial port on the stack?
make it a member, this way you don't need to allocate it in every method, and better on the heap.

how to allocate it on heap??
all i have done is made it a global member like this --->


Posix_QextSerialPort *sp = new Posix_QextSerialPort("/dev/ttyS0");

but its still not working. the error is the same.

high_flyer
25th June 2007, 15:12
why global? why not make it a member?
And yes, use 'new' to allocate on the heap, and don't forget to use 'delete' when you don't need the object anymore (or just give it Qt object parent).