How to add variable to #define

Hello,

To send data to a PHP file on a remote webserver I use this code:

#define PACHUBEAPIURL "/ethershield_log/save.php?pwd=secret&client=1&status=this-is-a-test-string"


es.ES_client_http_post(PSTR(PACHUBEAPIURL),PSTR(PACHUBE_VHOST),PSTR(PACHUBEAPIKEY), PSTR("PUT "),statusstr, &browserresult_callback);

This works. The "save.php" file on the server accepts the input and uses "this-is-a-test-string" on a website.

But now I want to add variables (like a string or byte) to send to the save.php file.

I tried everything like:

es.ES_client_http_post(PSTR(PACHUBEAPIURL+mystring),PSTR(PACHUBE_VHOST),PSTR(PACHUBEAPIKEY), PSTR("PUT "),statusstr, &browserresult_callback);

or

#define PACHUBEAPIURL "/ethershield_log/save.php?pwd=secret&client=1&status=this-is-a-test-string"+MYSTRING


es.ES_client_http_post(PSTR(PACHUBEAPIURL),PSTR(PACHUBE_VHOST),PSTR(PACHUBEAPIKEY), PSTR("PUT "),statusstr, &browserresult_callback);

But nothing works.

How do I get this working?

Thanks in advance,

Atmoz

#define pragmas are evaluated at compile-time, not run-time. So if you want to send a string whose value changes at various times while the sketch is running, you'll need to generate that string in your code.

You can use the C library function sprintf to generate a string from the value of variables and constants, then pass the result of that to the routine that sends the string to the server.

Thanks for the reply Andy!!

Can you give me an short example how to use it in my code?
What do I have to do with PSTR(PACHUBEAPIURL) ??

Thank you very much.

Regards,

Atmoz

You can find many examples of how to use sprintf by just googling "sprintf example c." Here is one.

The idea is that you declare a string buffer variable to receive the result of the formatting operation (sprintf). You give sprintf some variables and a string that contains formatting instructions. It substitutes the values of the variable you give it in the corresponding slots in the formatting string, and puts the result in the buffer you give it. The formatting string has all kinds of options to convert numbers to text.

I don't know what your PSTR call does, since you didn't post your whole sketch, but this should get you going.

Thanks for the help!!

I've uploaded the code: 404 De pagina is niet gevonden

I keep trying to get this working, but it doesn't want to!!

char      mystring[] = "/ethershield_log/save.php?pwd=secret&client=1&status=123456789" ;
  byte hoi = 23; 
          
//#define PACHUBEAPIURL "/ethershield_log/save.php?pwd=secret&client=1&status=56565688888888851"
  
  
 //es.ES_client_http_post(PSTR(PACHUBEAPIURL),PSTR(PACHUBE_VHOST),PSTR(PACHUBEAPIKEY), PSTR("PUT "), statusstr ,&browserresult_callback); 
        // es.ES_client_http_post(PSTR("hoi"), PSTR(PACHUBEAPIURL),PSTR(PACHUBE_VHOST), PSTR("PUT "),statusstr, &browserresult_callback);

      // es.ES_client_http_post(PSTR(PACHUBEAPIURL + sprintf(mystring)),PSTR(PACHUBE_VHOST), PSTR(PACHUBEAPIKEY),PSTR("PUT "),statusstr, &browserresult_callback);

        es.ES_client_http_post(sprintf(mystring),PSTR(PACHUBE_VHOST),PSTR(PACHUBEAPIKEY),NULL,statusstr,&browserresult_callback);

The only thing that works is the code beneath, but it isn't variable, because I can't insert a string or char or so instead of "test"

es.ES_client_http_post(PSTR(PACHUBEAPIURL"test"),PSTR(PACHUBE_VHOST),PSTR(PACHUBEAPIKEY), PSTR("PUT "), statusstr ,&browserresult_callback);

You haven't used sprintf correctly.

Here's a small example of using it to format a number:

char str[4];
int rpm;

sprintf (str, "%3d", rpm);
lcd.print (str);

Make sure your buffer is one char longer than the string you want to represent so that it has a trailing null, required to represent strings in c.

Okay, but what do I have to do with PACHUBEAPIURL then?
How do I "connect" that with a variable?

char str[4];

int rpm;
rpm = 55;
sprintf (str, "%3d", rpm);
  
        es.ES_client_http_post(PSTR(PACHUBEAPIURL +sprintf(str)),PSTR(PACHUBE_VHOST),PSTR(PACHUBEAPIKEY), PSTR("PUT "), statusstr ,&browserresult_callback);

Gives a error: at this point in file

Yes, you still aren't formulating the string correctly with sprintf.

I need to see more of your sketch code to advise you more. The link above at hetnet.nl is not valid.

You can't add a variable string to a constant string within a #define.
You have to build your string at runtime with a construct like:

#define PACHUBEAPIURL "/ethershield_log/save.php?pwd=secret&client=1&status=this-is-a-test-string"
char urlstring[BIGENOUGH];

  strncpy(urlstring, PACHUBEAPIURL, sizeof(urlstring));
  srtncat(urlstring, mystring, sizeof(urlstring));

  es.ES_client_http_post(urlstring, PSTR(PACHUBE_VHOST), PSTR(PACHUBEAPIKEY), ...

There may be problems with urlstring not being a PSTR.
There may be problems with having enough RAM for a BIGENOUGH array.
You could use sprintf() instead of strcpy/strcat, but it tends to be a large function with a lot more features than you need for just putting two strings together.
You know all those "buffer overflow attacks" you hear about that cause security failures in software? Those are from not guessing right about BIGENOUGH, and/or not using the "n" forms of strncpy/strncat/sprintf.

Yes, you still aren't formulating the string correctly with sprintf.

I need to see more of your sketch code to advise you more. The link above at hetnet.nl is not valid.

Sorry, I've fixed the link to my webspace.
My internet provider changed from name, and therefore the webspace URL changed also. At the moment of posting it was working, at the same day they changed everything ::slight_smile: Arggh :stuck_out_tongue:

You can't add a variable string to a constant string within a #define.
You have to build your string at runtime with a construct like:

..Code..

There may be problems with urlstring not being a PSTR.
There may be problems with having enough RAM for a BIGENOUGH array.
You could use sprintf() instead of strcpy/strcat, but it tends to be a large function with a lot more features than you need for just putting two strings together.
You know all those "buffer overflow attacks" you hear about that cause security failures in software? Those are from not guessing right about BIGENOUGH, and/or not using the "n" forms of strncpy/strncat/sprintf.

Thanks!! But this isn't working because of what you say: it isn't a PSTR!!

Is there a way to make a PSTR from a string?

Again: thanks for the help!!
If it's working some day I will be VERY glad :smiley: :smiley:

Regards,

Atmoz

Where is PSTR defined? etherShieldNEW.h?

Let's see that also, please...

PSTR is something from Arduino itself.
It's in the standard library's.

They use it for printing to the serial port also.
(that's what I get when I search to "PSTR" on the forum)

Maybe this helps:

Well that helped a lot! I moved all of the strings to inline progmem with PSTR. Very neat, albeit it seems a little unreliable... stuff like this happen:

I found it on the forum somewhere. Maybe it helps to find out what PSTR is?! ::slight_smile:

Is there a way to make a PSTR from a string?

No. PSTR are constant strings stored in flash program memory so that they won't consume RAM space that is used for "real" variables, but there is no way for a running program to write the program memory.

Is etherShieldNEW.h and es.ES_client_http_post()/etc your code, or from some standard library that I can't find anywhere? What you need is a version of es.ES_client_http_post() that accepts the URL part as a normal string rather than a PSTR. It MIGHT already exist. If not, you might want to consider a compromise solution where you have both a PSTR (constant) part of the URL string AND a variable part of the string:es.ES_client_http_post_w_avrurl(const PROGMEM char *urlfixed, char *urlvar, ...)
At some point the data is all getting copied into a packet buffer to send, so you don't necessarily have to put the whole url into a single sting before then...

PSTR are constant strings stored in flash program memory

Where is this defined or documented, do you know, westfw? I could not uncover it anywhere on the arduino site.

Where is PSTR defined or documented, do you know, westfw? I could not uncover it anywhere on the arduino site.

Hmm. It's part of the underlying gnu C compiler support (defined in <avr/pgmspace.h>) rather than part of the Arduino environment.
There's a nice tutorial here:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=38003

All it really does is allow you to put quoted strings in function arguments into program memory, so you could have in your program: print_pstring(PSTR("this is a long string that will get stuck into progmem\n");Instead of having to do the multiple steps:

static char mystring[] PROGMEM = "this is a long string that will get stuck into progmem\n";
//later:
 print_pstring(mystring);

I would have thought PSTR would be at least mentioned in the Arduino reference on PROGMEM (http://www.arduino.cc/en/Reference/PROGMEM), but you're correct that there doesn't seem to be anything there. Note that none of the Arduino core functions (like Serial.print()) support PSTR, and it doesn't seem to be possible for C++ to tell the difference between a progmem string and a RAM string (so that the right thing can happen automagically), so perhaps the omission is designed to prevent inadvertent bugs like:Serial.print(PSTR("Look, I'm saving RAM space"));

Is etherShieldNEW.h and es.ES_client_http_post()/etc your code, or from some standard library that I can't find anywhere?

It's the library I got from Andy (also on this forum) his website: http://blog.thiseldo.co.uk/?p=344

file:
http://blog.thiseldo.co.uk/wp-files/etherShield_pachubeclient.zip

He uses it for sending data to Twitter and Pachube.
I thought that I can use it to send data to my "save.php" file because the other code that I use from "Nuelectronics" doens't work for more then 1 hour: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1219733115/15#15

What you need is a version of es.ES_client_http_post() that accepts the URL part as a normal string rather than a PSTR. It MIGHT already exist. If not, you might want to consider a compromise solution where you have both a PSTR (constant) part of the URL string AND a variable part of the string

Yep, that's exactly what I need. But how to make it...
Like I said, I tried tons of options, the most didn't even compile, while some of it does, and the sketch started, but no update on the php file from the server.

Besides that, I am not that good in all this things.

Therefore I absolutely appreciate the help of you pro guys :smiley:

With kind regards from the Netherlands,

Atmoz

OK, thanks for that explanation, westfw.

Now, Atmoz...

This means that you need a different approach to fabricating the strings you pass to the EtherShield routine that will change. You have to replace PSTR with the standard C functions for string manipulation (in string.h), which put the result in RAM (so that it can be modified during the run of your program).

So you're back to the approach that westfw and I described earlier in this thread. Is it clear?

Thanks.

It is clear that I have to make my "own" procedure to get this working, but the problem is that I don't know where to start. And second my program skills from the Arduino environment aren't that good.

I prefer Borland Delphi to progam in ;D

In the meanwhile I send another Andy (the maker of the website and library that I mentioned before) a message if he can looks at this.

If he can make a whole working network library, then he probably also can make a procedure to send variable data to a php file :sunglasses:

With kind regards,

Atmoz

The reason no one has just written the code for you here in the forum, Atmoz, can be related in an old expression. It goes something like:

"If you give someone a fish you have caught, he eats for a day; if you show him how to fish for himself, he eats for a lifetime."

If you want to do more than simple things in software (your issue is completely independent of Arduino and is a standard C programming language task), it will be good to learn how to do these things, beyond cutting and pasting code fragments together.

We are trying to lead you towards a solution, rather than just writing the code for you. You will have more power if you figure out how to solve this kind of problem, how to approach a solution process, rather than just using other's code.

The code you have there is reasonably complex and it is written in a fairly obtuse style, so it's not easy to unravel what is going on. I don't know Delphi, but it appears to be a visual programming language. So if this is your first C experience, I'm not surprised you are struggling.

If this Arduino stuff interests you, you might want to invest some time in a C language tutorial. Also, Massimo Banzi's book, "Getting Started with Arduino," is a very readable and accessible introduction to Arduino programming.

In the interest of fishing, I will try to spend a little time later working up a simple example that might help you understand the string problem you need to solve.

Apologies if I have underestimated your experience; no offense intended.

.andy

Thanks for your post Andy.
Don't worry, you haven't underestimated my experience.
Like I said, I don't know much about all this things. Thereby, my English isn't that good either. I constantly have to pick a dictionary to find the explanation of some things...

Some therms are so technically, that this is very difficult to understand.

And there are no friends or so that can help me with the electronic stuff because all of them plat football or something instead of it :stuck_out_tongue:

You're right that I better can invest some time in all this things, but the problem is that this is REALLY nice stuff, and I can't wait to get it working. I spent maybe 10 hours on it, without get it working. Yes, I got something working with fixed text, that was very cool!! But when it's still not working after you tried so many times, it's time to ask for help.

But anyway, I took a look at the procedure again and found:

      // ----- http get
      void ES_client_browse_url(prog_char *urlbuf, char *urlbuf_varpart, prog_char *hoststr,void (*callback)(uint8_t,uint16_t));
      // The callback is a reference to a function which must look like this:
      // void browserresult_callback(uint8_t statuscode,uint16_t datapos)
      // statuscode=0 means a good webpage was received, with http code 200 OK
      // statuscode=1 an http error was received
      // statuscode=2 means the other side in not a web server and in this case datapos is also zero
      // ----- http post 
      // client web browser using http POST operation:
      // additionalheaderline must be set to NULL if not used.
      // method should be used if default POST to be overridden set NULL for dfault
      // postval is a string buffer which can only be de-allocated by the caller 
      // when the post operation was really done (e.g when callback was executed).
      // postval must be urlencoded.
      void ES_client_http_post(prog_char *urlbuf, prog_char *hoststr, prog_char *additionalheaderline, prog_char *method, char *postval,void (*callback)

(uint8_t,uint16_t));
      // The callback is a reference to a function which must look like this:
      // void browserresult_callback(uint8_t statuscode,uint16_t datapos)
      // statuscode=0 means a good webpage was received, with http code 200 OK
      // statuscode=1 an http error was received
      // statuscode=2 means the other side in not a web server and in this case datapos is also zero

All the parameters are prog_char (not possible to insert variables during run time) except postval, that one is a (normal?) char. Maybe I can fix something with that...

Regards,

Atmoz