Using strcat to construct a variable URL/ adaptable url for php request

Hi, all!

I'm working on a system which allows me to send data to my php page which puts the data into mysql, so far so good, I am able to establish a connection with the php page when I use a static char as url path. Though, I would like to have the url adapt to the variables when a RFID tag is read. Thus, i started thinking about how to construct this and came up with a char for each parameter and combine them together by making use of strcat. Unfortunately, until now it doesn't seem to work, when I print my url char it's completely empty and thus I'm unable to get a return char.

The strcat I've constructed:

char* pre_url[]={"/add_db.php?register="};
char* register[]={"StalKennetW", "StalKrawall", "Stapmolen", "Dressuurbak"};
char* mid_url1[]={"&name="};
char* name[]={"KennetW", "Krawall"};
char* mid_url2[]={"&date="};
char* date[]={"lipsum"};
char* mid_url3[]={"&time="};
char* time[]={"dolor"};
char url[300];  // enough room for all strings together


char* concat(char* pre_url, char* register, char* mid_url1, char* name, char* mid_url2, char* date, char* mid_url3, char* time) {
  url[0] = 0;          // start with a null string:
  strcat(url, pre_url);   // add first string
  strcat(url, register); 
  strcat(url, mid_url1);  
  strcat (url, name);
  strcat(url, mid_url2);
  strcat (url, date);
  strcat(url, mid_url3);
  strcat (url, time);

  return url;
}

The following step would be to chose a specific name from the char to put in the url, I guess it would look as following, though I get an error which says my int's aren't declared, which is weird. Because they are. Thus I guess I will probably do something terrible wrong or I'm thinking to difficult.

char* pre_url[]={"/add_db.php?register="};
char* register[]={"StalKennetW", "StalKrawall", "Stapmolen", "Dressuurbak"};
char* mid_url1[]={"&name="};
char* name[]={"KennetW", "Krawall"};
char* mid_url2[]={"&date="};
char* date[]={"lipsum"};
char* mid_url3[]={"&time="};
char* time[]={"dolor"};
char url[300];  


char* concat(char* pre_url, char* register[id], char* mid_url1, char* name[name], char* mid_url2, char* date[date], char* mid_url3, char* time[time]) {
  url[0] = 0;          // start with a null string:
  strcat(url, pre_url);   // add first string
  strcat(url, register[id]); 
  strcat(url, mid_url1);  
  strcat (url, name[name]);
  strcat(url, mid_url2);
  strcat (url, date[date]);
  strcat(url, mid_url3);
  strcat (url, time[time]);

  return url;
}

Thanks in advance,
Niels

Looking at your code I don't even see an int. Are you sure the problem is here?
What line comes up as the problem? Is it one of these?

The thing that makes me confused is this:

char* concat(char* pre_url, char* register[id], char* mid_url1, char* name[name], char* mid_url2, char* date[date], char* mid_url3, char* time[time]) {

//AND THIS

strcat (url, time[time]);

//AND THIS

 strcat (url, date[date]);

//AND THIS

  strcat (url, name[name]);

Chances are that the ints that are not declared are the indexes that should be inside brackets... What were you intending to do here?

Well I did declare the int as following

int id;
int name;
int date;
int time;

Within the loop the int's will get values and based on those values they should select the corresponding char. The squared brackets [ ] contain the actual int and should give me the corresponding char. e.g.

When int id = 2; it should give me the url char which contains /add_db.php?register=stapmolen&name=(char corresponding to the value of int name)... and so on.

Though, I think the first problem will be to solve the strcat that it just outputs a char, which i use as url.
Niels,

This line just isn't valid C:

char* concat(char* pre_url, 
        char* register[id], 
        char* mid_url1, 
        char* name[name], 
        char* mid_url2, 
        char* date[date], 
        char* mid_url3, 
        char* time[time]) {

I'm not sure how to explain it, but you can't have the argument to a function being something like register which is subscripted by id. I'm not sure how the compiler would generate code to handle that.

All those things are global variables anyway, why pass them as arguments?

And what's this doing?

  strcat (url, date[date]);

You are subscripting date by itself? Your intention here eludes me. Ditto for name and time.

All of the subscript evaluation/resolution to pointer happens on the caller's side of the interface, so that what is passed to the function is a pointer (in)to an array. Make all your function parameters either scalar variables or simple pointers and you'll do fine.

That was also a problem I was trying to figure out, the date and time but I already solved that one by using timestamp in mysql, which makes it a lot more easier. This means that I only need the register and the name chars to be put into the url. together with the static chars.

Sorry, I can't follow you in this one, could you give an example?

Kind regards,
Niels

Ok - if, for example, you want to do something (like concatenating it to other stuff in a buffer) with the i-th element of register, you can pass a pointer to the i-th element, but should understand that the subfunction can't know how you coded the call - it can only trust that it received a pointer to some chars.

If it's important for the subfunction to know about both the array and the index, they'll need to be passed as separate parameters.

Still not solved my problem unfortunately, isn't it possible to concatenate pointer char's and form them to a char?

Of course. That's exactly what strcpy() and strcat() are for. Your problem wasn't with that concatenation - but, rather, with the passing of (pointer) parameters to pass to strcat().

And you might want to move those string constants into PROGMEM. I didn't count bytes but if the buffer you're filling with them has to be 300 bytes then you can save significant ram by keeping them in flash.

That may be space you'll need once you're online.

Well, I don't think I need that much, those 300 is probably to much. And i'm unsure if I need to combine multiple chars.

Basically my program needs to read an rfid tag, the id of the tag needs to be linked to a name. The only thing left is to upload the name to my *.php page which stores it in a mysql database. I am able to store data in the mysql database by typing my data manually into the url, thus I only need to tell arduino to do it form, but the url the arduino requests should be adapted to the rfid tag scanned.

If there are any suggestions I would appreciate it. I already am able to connect to my php page but the url used can't adapt to the rfid tags.

Regards,
Niels

You have used this from my example in your other thread.

    sprintf(outBuf,"GET %s HTTP/1.0\r\nHost: www.mydomain.com\r\n\r\n",page);
    client.write(outBuf);

Modify it a bit to suit your needs. Kinda like this:

int rfid = 26;
sprintf(outBuf,"GET /mypage.php?rfid=%u HTTP/1.0\r\nHost: www.mydomain.com\r\n\r\n",rfid);
client.write(outBuf);

This should put the value in rfid in the URL. It will look like this to the server.
http://www.mydomain.com/mypage.php?rfid=26

Insure the character array outBuf is large enough to handle the entire string, and there are no illegal characters in the URL, like spaces.

My simple sprintf tutorial

SurferTim:
This should put the value in rfid in the URL. It will look like this to the server.
http://www.mydomain.com/mypage.php?rfid=26

Insure the character array outBuf is large enough to handle the entire string, and there are no illegal characters in the URL, like spaces.

Thanks, this set me on the right track! But there is one problem to my code, I'm able to read a rfid tag and send this to the database but it works only once right after pushing the reset button. I tried to figure it out, but don't really see the problem. Could someone give me some advise on this one?

Sorry forgot the code here!

#include <SPI.h>
#include <Ethernet.h>


IPAddress ip(*************);
IPAddress gateway(*************);
IPAddress subnet(*************);
byte mac[] = {************* };
IPAddress server(************* ); 


EthernetClient client;

int connectLed=5;
int buttonState=0;

int connectedToServer=6;


/////////////////RFID/////////////////
int RFIDResetPin = 13;
int rfid_val;
//Register your RFID tags here
char tag1[13] = "4500530E9F87";
char tag2[13] = "450052E8E51A";

int led1=2;
int led2=3;

void setup() {
  Serial.begin(9600);

  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  delay(2000);
  Serial.println("Ready");

  /////////////////RFID/////////////////
    
  pinMode(RFIDResetPin, OUTPUT);
  digitalWrite(RFIDResetPin, HIGH);

  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  
  pinMode(connectedToServer, OUTPUT);
}

void loop()
{

  
    if (rfid_val == 1|rfid_val==2){
    digitalWrite(connectLed, HIGH);
   
    if(!getPage(server,"/add_db.php")) Serial.print("Fail ");
    else Serial.print("Pass ");
   
  }
  
   else {
    // turn LED off:
    digitalWrite(connectLed, LOW); 
   
  }
  
  /////////////////RFID/////////////////
  
  char tagString[13];
  int index = 0;
  boolean reading = false;

  while(Serial.available()){

    int readByte = Serial.read(); //read next available byte

    if(readByte == 2) reading = true; //begining of tag
    if(readByte == 3) reading = false; //end of tag

    if(reading && readByte != 2 && readByte != 10 && readByte != 13){
      //store the tag
      tagString[index] = readByte;
      index ++;
    }
  }
  
  Serial.println(rfid_val);
  checkTag(tagString); //Check if it is a match
  clearTag(tagString); //Clear the char of all value
  resetReader(); //eset the RFID reader

}

byte getPage(IPAddress ipBuf,char *page)
{
  int inChar;
  char outBuf[64];

  Serial.print("connecting...");

  if(client.connect(ipBuf,80))
  {
    Serial.println("connected");
    
    

    
 
    sprintf(outBuf,"GET /add_db.php?rfid=%u HTTP/1.0\r\nHost: www.*************.nl\r\n\r\n",rfid_val);
    client.write(outBuf);
    
  } 
    
  
  else
  {
    Serial.println("failed");
    return 0;
  }

  while(client.connected())
  {
    while(client.available())
    {
      inChar = client.read();
      Serial.write(inChar);
    }
    digitalWrite(connectedToServer, HIGH);
    delay(500);
    digitalWrite(connectedToServer, LOW);
  }

  Serial.println();

  Serial.println("disconnecting.");
  client.stop();

  return 1;
}

 /////////////////RFID/////////////////
 void checkTag(char tag[]){
///////////////////////////////////
//Check the read tag against known tags
///////////////////////////////////

  if(strlen(tag) == 0){
   digitalWrite(led1,LOW);
   digitalWrite(led2,LOW);
   rfid_val=0;
    return; //empty, no need to contunue
  }
  if(compareTag(tag, tag1)){ // if matched tag1, do this
     rfid_val=1;
     digitalWrite(led1, HIGH);
     delay(2000); 
  }

    
  if(compareTag(tag, tag2)){ //if matched tag2, do this
     rfid_val=2;
     digitalWrite(led1, HIGH);
     delay(2000);
  }

  
}

//void lightLED(int pin){
/////////////////////////////////////
////Turn on LED on pin "pin" for 250ms
/////////////////////////////////////
//  Serial.println(pin);
//
//  digitalWrite(pin, HIGH);
//
//}

void resetReader(){
///////////////////////////////////
//Reset the RFID reader to read again.
///////////////////////////////////
  digitalWrite(RFIDResetPin, LOW);
  digitalWrite(RFIDResetPin, HIGH);
  delay(200);
}

void clearTag(char one[]){
///////////////////////////////////
//clear the char array by filling with null - ASCII 0
//Will think same tag has been read otherwise
///////////////////////////////////
  for(int i = 0; i < strlen(one); i++){
    one[i] = 0;
  }
}

boolean compareTag(char one[], char two[]){
///////////////////////////////////
//compare two value to see if same,

///////////////////////////////////

  if(strlen(one) == 0) return false; //empty

  for(int i = 0; i < 12; i++){
    if(one[i] != two[i]) return false;
  }

  return true; //no mismatches
}

Regards and thank you very much!
Niels

What is the last message displayed on the serial monitor after the fail?

Instead of loading a buffer with a big string and printing it out, why not just print each piece in turn? If you need to print it to two devices then print each piece to each device before the next.

The concatenation will occur in the serial transmissions. Those could be done 1 byte at a time and still the Arduino would be idle most of the time. You save the ram that may be crashing your sketch for no sacrifice except waste.

Actually, there is no fail, it just keeps printing 0's from the rfid_val to the serial monitor after connecting and uploading. It just doesn't allow me to read a tag and thus doesn't start to connect to the server.

    if (rfid_val == 1|rfid_val==2){

This is probably NOT doing what you think it is. Big difference between | and ||.

If either is true then it evaluates to 1.