Here is my project that sends an HTTP request with a 3G shield.
My problem is not with the shield or the GET method as its returning the correct responses. My problem is passing the returned string into usable variables.
I am relatively new to this so am a little confused by the output.
char data[1024];
char number[1024];
char message[1024];
char waste[1024];
char* variable[] = {};
int data_size;
int led = 13;
int onModulePin = 2; // the pin to switch on the module (without press on button)
boolean dataread = false;
int incomingByte;
String vartostring;
int x = 0;
int n = 0;
int v = 0;
char server[ ]="********.com";
char port[ ]="80";
void switchModule(){
digitalWrite(onModulePin,HIGH);
delay(2000);
digitalWrite(onModulePin,LOW);
}
void setup(){
Serial.begin(115200); // UART baud rate
delay(2000);
pinMode(led, OUTPUT);
pinMode(onModulePin, OUTPUT);
switchModule(); // switches the module ON
Serial.println("SWITCHING ON");
for (int i=0;i< 5;i++){
delay(5000);
Serial.println(5-i);
}
Serial.println("AT+FSLOCA=0");
// store media files to local storage space, put 1 to store media files to storage card
while(Serial.read()!='K');
//FTP CONNECTION *************
Serial.println("AT+CGSOCKCONT=1,\"IP\",\"pp.vodafone.co.uk\"");
Serial.flush();
x=0;
do{
while(Serial.available()==0);
data[x]=Serial.read();
x++;
}while(!(data[x-1]=='K'&&data[x-2]=='O'));
Serial.println("AT+CGAUTH=1,1,\"web\",\"web\""); // Enables handsfree
while(Serial.read()!='K');
Serial.println("SWITCHED ON");
}
void loop()
{
Serial.print("AT+CHTTPACT=\""); //Connects with the HTTP server
Serial.print(server);
Serial.print("\",");
Serial.println(port);
Serial.flush();
x=0;
do{
while(Serial.available()==0);
data[x]=Serial.read();
x++;
}while(!(data[x-1]=='T'&&data[x-2]=='S')); //waits for response "REQUEST"
Serial.println("GET http://********.com/arduino.php HTTP/1.0");
Serial.println("Host: **********.com");
Serial.println("Content-Length: 0");
Serial.write(0x0D);
Serial.write(0x0A);
Serial.write(0x0D);
Serial.write(0x0A);
Serial.write(0x1A); //sends ++
while(Serial.read()!='K');
while(Serial.read()!=' ');
do{
while(Serial.available()==0);
char c = Serial.read();
if (c == '{'){
dataread = true;
}
else if (c == '}'){
dataread = false;
vartoString();
}
else if (dataread == true){
message[n] = c;
n++;
}
data[x] = c;
x++;
}while(!(data[x-1]=='%'&&data[x-2]=='d')); //Program stops at first occurence of "</"
Serial.println("in loop");
Serial.println(variable[0]);
outputVar();
while(1);
}
void vartoString(){
variable[v] = message;
v++;
for(int t=0;t< 1023; t++){
message[t] = '\0';
}
Serial.println(message);
x=0;
n=0;
}
void outputVar(){
Serial.println("OutputVar..");
Serial.println(variable[0]);
Serial.println(variable[1]);
Serial.println(variable[2]);
}
So the problem is that the vartoString() function seems to have the correct info at that point i.e if this is sent back:
number{077123456}message{This is a test message}%end%
Then I thought I was putting 077123456 into variable[0] and "This is a test message" into variable[0]
If I println (variable[v]) within the vartoString() function it prints the correct parameter. But if I println either variable[0] or variable[1] after that function is complete the values are blank (like the outputVar() function for instance). It appears that variable[v] is only available during each iterative loop of the value v.
The problem here is that you are blanking the memory.
You are assigning a pointer (variable[v]) to a memory location where the interesting part of the message is. You are not copying the data. Then you are wiping out that memory (overwriting with '\0'), so when you look at variable[0] it looks at the memory you have just wiped out.
You either need to copy the data from the message[] array into some fresh memory which the variable[] array will point to, or just not wipe out the memory at that point - do it later.
Ah okay - I think I'm completely misunderstanding how this works then!!!
So here's how I thought my logic was working:
Incoming serial - number{077123456}message{This is a test message}%end%
Start writing message[] array at {
Finish writing at }
Write this char array message[] as an entry to a new array variable[]
Clear message[] and start process again.
So how do I actually copy the char array to the new array at point 4? I think maybe I'm misunderstanding how the char array works in this situation? I've also tried converting message[] at the point of writing to the variable array into a string - but found out it doesn't like that logic either?
If I don't clear the memory (or just message[] if that isn't what I'm doing) then I get variables looking like this:
variable0 = 077123456
variable1 = 077123456This is a test message
Also - maybe if I'm completely missing the mark - is there a better way to pass a string with limiting characters? It seems quite hard to find a clear simple example that doesn't refer to ethernet shields or specific libraries.
In C a "string" is just a block of memory with letters in it, with the last character being character 0 to mark the end of the string. The variable you use to access that string is called a "pointer". It is literally just storing the memory address of the start of the string.
If you assign one pointer to another (which is what you are doing) then you are just copying the address of the start of the string in memory from one pointer to the other.
If you know that the variables will have a limited size (number of characters) you can pre-allocate the space to store them in by setting up "variable" to be a 2-dimentional array (at the moment it is only one):
char variable[3][20]; // Space for 3 strings, each containing up to 20 characters.
Then you need to "copy" the string from one place to another:
strcpy(variable[v],message);
That will copy each character from "message" into "variable[v]" up until it reaches the magical character 0. Note that if "message" is longer than "variable[v]" - 20 characters in my example (including the character 0 at the end) then you will end up corrupting your memory and nasty things will happen.
If you cannot predict either the number of variables, or the maximum length of the variables, then it gets a whole lot more complex, and you start heading into the realms of dynamic memory. This is fine on a PC, but on a limited resources microcontroller you can run into difficulties with memory fragmentation. However:
char *variable[10]; // Allocate room to store up to 10 string pointers
...
variable[v] = malloc(strlen(message)+1); // Allocate enough memory to store the message, plus one character for the 0 end of string marker
strcpy(variable[v],message); // Copy the message content
...
free(variable[v]); // Release the memory after use
It is important to call free() on every pointer you allocate with malloc() after you have finished with it, otherwise you will fill your memory up with junk (this is called a memory "leak").
It's very common. I will often use multiple pointers all pointing locations within a string to slice the string up into its component parts without having to allocate any extra memory. Just set a character in the string to '\0' and point a pointer to the next character and voila, you have two strings.
You pass it a string, an array of pointers, and the length of that array, and it chops the string up on spaces (collapsing multiple spaces etc) and sets the pointers to each of the sub-strings. It then returns the number of strings found.
So, for example:
char *mystr="This is my string with stuff in it";
char *myargs[20];
int found;
found = parseLine(mystr,myargs,20);
This is called "destructive parsing" as it modifies the original string "in place". Very efficient on memory, and quite speedy too, but no good if you want to do other things with the original string as well.
A better question is "What makes an Arduino an Arduino". I have a system on my desk with 128K of RAM and 512K of Flash. It uses the Arduino IDE. It uses the Arduino libraries. It uses Arduino shields. It's programmed using avrdude... Is it an Arduino...?
The key question, though, is whether OP has such an Arduino or not.
A better question is "What makes an Arduino an Arduino"
An Arduino has one of a small handful of chips, including the 168, the 328, the 1256 and the 2560.
While that are a number of other chips, of various sizes, that can be programmed using the Arduino IDE and that behave correctly most of the time, it is important, when asking for help, to point out whether you are using one of the standard chips (and which one) or one of the non-standard chips (and which one).
Any other course of actions wastes (some) people's time.