so im working with CAN utils using this CANopenNode im making candump through a .c program file.
my code for the receiver looks like this
char raw_message[47], message_id[4], message_data[17];
fp = popen("candump vcan0 -L", "r");
if( fp == NULL )
{
printf("Failed to run CANDUMP for VCAN0");
exit(1);
}
while ( fgets(raw_message, sizeof(raw_message), fp) )
{
if( isspace(raw_message[0]) )
{
}
else
{
//GETTING THE ACTUAL MESSAGE = ID+DATA
cid = 0;
cdata = 0;
for(i=26; i<46; i++)
{
if( i<29 )
{
message_id[cid] = raw_message[i];
cid++;
}
else if ( i==29 )
message_id[cid] = '\0';
else if ( i>29 )
{
message_data[cdata] = raw_message[i];
cdata++;
}
}
message_data[16] = '\0';
//END OF GETTING MESSAGE
fprintf(stdout,"%s\n",raw_message);
fflush(stdout);
}
}
pclose(fp);
and im running a shell script for sending
echo "Start"
i=0;
while [ $i -le 5 ] ;
do
#echo "sent"
cansend vcan0 123#0801010101010101
let i=$i+1
done
exit 0
what im trying to do is to split the id from the actual data of message. The thing is that as you can see I do that only if the first slot of the raw_message isnt space cause I receive a message i get it with fgets and then I get ' ' then message, then ' ' and so go on. Only when I use if (isspace) seems to work and if I put on comments the command "fprintf(stdout,"%s\n",raw_message);" stops working. I tried multiple solutions but nothing seems to work. Is there any particular reason why is doing that? Am I doing something wrong or it maybe something of CANUtils ?
Output when I use issspace() (output is the same as when I run candump on bash){}
(1585149182.549347) vcan0 123#0801010101010101
(1585149182.550713) vcan0 123#0801010101010101
(1585149182.555930) vcan0 123#0801010101010101
(1585149182.559413) vcan0 123#0801010101010101
(1585149182.560687) vcan0 123#0801010101010101
(1585149182.561604) vcan0 123#0801010101010101
Output when I dont use it
while ( fgets(raw_message, sizeof(raw_message), fpdump) )
{
// if( isspace(raw_message[0]) )
// {
// }
// else
{
//GETTING THE ACTUAL MESSAGE = ID+DATA
cid = 0;
cdata = 0;
for(i=26; i<46; i++)
{
if( i<29 )
{
message_id[cid] = raw_message[i];
cid++;
}
else if ( i==29 )
message_id[cid] = '\0';
else if ( i>29 )
{
message_data[cdata] = raw_message[i];
cdata++;
}
}
message_data[16] = '\0';
//END OF GETTING MESSAGE
fprintf(stdout,"%s\n",raw_message);
fflush(stdout);
}
}
Output:
(1585149305.257591) vcan0 123#0801010101010101
(1585149305.258339) vcan0 123#0801010101010101
(1585149305.259055) vcan0 123#0801010101010101
(1585149305.259651) vcan0 123#0801010101010101
(1585149305.260280) vcan0 123#0801010101010101
(1585149305.260860) vcan0 123#0801010101010101
The example data as shown in the question
(1585149182.549347) vcan0 123#0801010101010101
(1585149182.550713) vcan0 123#0801010101010101
...
has a line length of 46 characters without the newline character ('\n'
) or 47 including the newline.
fgets
needs to append a trailing NUL
character ('\0'
) to terminate the string. That's why the first call will read the line without the newline because the buffer is full. The buffer will contain the string
"(1585149182.549347) vcan0 123#0801010101010101"
The next call will read the newline character only because this is the end of the line. The buffer will contain
"\n"
You have to increase the size of raw_message
to at least 48.
Then you would get
"(1585149182.549347) vcan0 123#0801010101010101\n"
in one fgets
call.
Note that it might be better to read the binary CAN messages using the socketcan interface instead of parsing the text output of candump
.