I'd like to start out with saying i am not facing any issues with the ethernet shield/networking. I am just facing a simple programming issue.
So i made a application that will transfer data between a pc and arduino (what it is is not relevant to the question).
Now the pc sends a command that goes like this: "TRACE_IP=[insert IP here]".
When the arduino receives it i need it to remove the "TRACE_IP=" part so i am just left with the IP number.
And after that i need to separate it again like for example i have an ip of "192.168.159.182" i need it to return 4 integers that contain the first part of the ip, then the next one should get the second part of the ip. etc. so i am then left with "192" "168" "159" "182".
Now i am having problems with splitting this. Oh and i cant just go ahead and make each one 3 characters long since ip addresses can vary in size so sometimes it might be "192.168.159.4" or "10.80.0.145"
Does somebody know the solution? Any help would be appreciated
My code (that is relevant to the question):
else if ( currentLine.startsWith("TRACE_IP")) {
// The server send us the IP address we need to traceroute to.
// Let's get the IP address from the message
Serial.print("Starting trace");
currentLine.remove(0, 8);
Serial.print(currentLine);
/* int Parts[4] = {0,0,0,0};
int Part = 0;
for ( int i=0; i<currentLine.length(); i++ )
{
char c = currentLine[i];
if ( c == '.' )
{
Part++;
continue;
}
Parts[Part] *= 10;
Parts[Part] += c - '0';
}
*/ //this code doesn't work correctly, the beginning is correct but the last one it fails at.
IPAddress ip(Parts[0], Parts[1], Parts[2], Parts[3] );
delay(500);
ICMPEchoReply echoReply = ping(ip, 1, 5);
{
sprintf(buffer,
ReplyMessage, // Defined in strings.c
echoReply.data.seq, // sequence is always 0 when BAD_RESPONSE status
echoReply.addr[0],
echoReply.addr[1],
echoReply.addr[2],
echoReply.addr[3],
REQ_DATASIZE,
millis() - echoReply.data.time, // time is working for both PING and TraceRoute (TLL=0) router response
echoReply.ttl, // TTL equals set TTL when TraceRoute(TLL=0) router response
echoReply.status); // Equals 0 for Ping and 3 for TraceRoute(TLL=0) router response
}
client.print("TRACE_RESULTS"); //Command for the server to know that the next data it receives is the traceroute
client.print(buffer);
currentLine = "";
}
}
PS. "currentLine" is the incoming line from the PC, it is reported as a whole
J-M-L: sscanf() would work but that adds a lot of code to your program
True, on an UNO or Leonardo, I'd probably use strtok and atoi. If you have enough resources available, like on a Mega, ARM or ESP board, I think sscanf is easier than having to implement it yourself.
Yep - or if your program is really small then sure why not use more memory that's fine - but it is good to know other technics in case memory becomes a challenge
Sadly i am seriously desperate to save those last few bytes since i am using 95% of the programming storage and 74% RAM (but it is more like 99% since the arduino would just stop working after 75%)
I was so desperate i completely stripped a library so i would get around 2KB of free space again but even that is used now. So i'll probably need some tips on saving RAM and programming space too
and modified it a bit so it would work with the code but sadly another issue occurred. I only have 10 BYTES (Literally) left of programming storage :o .
So i need another piece of code that will split it into 4 pieces.
I only need the splitting part since i already removed the command that goes before the IP address that is send by the pc, the IP address is inside currentLine
Also in reply #4 i won't think that will do what i need it to do, i am probably wrong tho
CrazyVito11:
Sadly i am seriously desperate to save those last few bytes since i am using 95% of the programming storage and 74% RAM (but it is more like 99% since the arduino would just stop working after 75%)
The compiler only tells you about RAM used by global variables etc. Local variables and dynamically allocated memory are not included in that 74%.
I think you need to reconsider your board choice and get something with more memory that's better suited for demanding things like networking.
and modified it a bit so it would work with the code but sadly another issue occurred. I only have 10 BYTES (Literally) left of programming storage :o .
So i need another piece of code that will split it into 4 pieces.
I only need the splitting part since i already removed the command that goes before the IP address that is send by the pc, the IP address is inside currentLine
Also in reply #4 i won't think that will do what i need it to do, i am probably wrong tho
The point was that you should NOT use sscanf when low on memory.
int intval = 0 ; // temporary for building up value on the fly
byte part = 0 ; // index into ip_addr
byte ip_addr [4] ;
int i = 0 ;
while (true)
{
if (buf[i] == '.' || buf[i] == 0) // part separator / end of string
{
ip_addr [part++] = intval ; // store next byte
if (buf[i] == 0 || parts == 4) // done if 4 parts parsed or end of string
break ;
intval = 0 ;
}
else if ('0' <= buf[i] && buf[i] <= '9')
{
intval = intval * 10 + buf[i]-'0' ; // build up value from decimal digits.
if (intval > 255)
break ;
}
else
break ;
i++ ; // step to next char
}
if (parts == 4)
// have a valid result...
else
// bad string
J-M-L: I did but that used too much storage
oqibidipo: That sadly it didn't work, I checked it with the arduino serial monitor, with my server and even with wireshark but it just doesn't do anything. but when i force an ip (hard code it in) it does work so there is something wrong with splitting the IP from the string.
I am now testing this on a MEGA2560 but later i'll still try to put it on a UNO since i already ordered 3 of them from china (not that it is that expensive, but it is just a waste since i am not going to use that many of them) Of course if it just isn't possible to put it on a UNO i'll just order 3 arduino mega's from china (I'm sorry Arduino )
CrazyVito11:
oqibidipo: That sadly it didn't work, I checked it with the arduino serial monitor, with my server and even with wireshark but it just doesn't do anything. but when i force an ip (hard code it in) it does work so there is something wrong with splitting the IP from the string.
Is there something in the string after the IP address, including CR/LF?
IPAddress::fromString() returns false if there is anything but numbers and dots.
oqibidipo:
Is there something in the string after the IP address, including CR/LF?
IPAddress::fromString() returns false if there is anything but numbers and dots.
That is a good one!
I think it probably will since i send a line from my computer so it will probably add a new line to it.
How can i check or better yet remove the NL when the string contains it?
Also i have made up my mind of getting a MEGA, i'm going to do it differently. The UNO's will just be a client, no display at all. This reduced the size immediately down to only 55% of the program memory :o.
oqibidipo:
Is there something in the string after the IP address, including CR/LF?
IPAddress::fromString() returns false if there is anything but numbers and dots.
I don't think it is a CR or LF issue since i had to force the server application to send it and then you would immediately see it on the serial monitor. So something else is going wrong