I have device on my local network and am trying to get a status page as well as issue basic commands via GET. I understand the headers I need, the URL to call but would like to dynamically create the request path based on logic in my app. I broke the full uri down to its pieces and know where I would insert numbers 0-4 depending on the need but don’t know how to combine it all into a single line. I think SPRINTF might be the right answer I am not entirely sure.
Here are the baseline components of the URI path I need to call, 0-4 would be added behind each =. Thoughts?
#define ThingProgBase "thing.cgi?"
#define ThingNumURI "num="
#define ThingProgURI "&val="
Yup, my first thought would be sprintf()
too (or snprintf()
if you can’t be sure of resulting length).
Alternatively you could use String::format()
(
personal opinion)
Or strcpy()
+ strcat()
+ itoa()
(
)
const char ThingProgURI[] = "thing.cgi?num=%d&val=%d";
char uri[32];
void loop()
{
int n = 9999;
int v = 8888;
sprintf(uri, ThingProgURI, n, v);
}
1 Like
I am keeping it simple with hard coded stuff for now but was hoping you could help me with this. I am using the HTTPClient lib from within my own lib. Here is what I have and the compile error message I am getting, any ideas?
The HTTPClient lib is there as a Public object which is how I have seen other libs do this but I have also seen some use the new keyword like this ds = new OneWire(pin). What is the difference?
class Thing
{
private:
//Private functions
//bool parse();
//Private variables
uint8_t thingNum;
http_request_t request;
http_response_t response;
// Headers currently need to be set at init, useful for API keys etc.
http_header_t headers[] = {
{ "Accept" , "*/*" },
{ "Authorization" , "Basic Base64EncodedUser:Pass" },
{ NULL, NULL }
};
public:
HttpClient thingWeb;
Function that uses thingWeb HTTPClient.
void Thing::update()
{
request.ip = SERVER_IP;
request.port = SERVER_PORT;
request.path = THINGXML;
thingWeb.get(request, response, headers);
Serial.println(response.status);
Serial.println(response.body);
}
![](https://global.discourse-cdn.com/business7/uploads/particle/original/2X/0/0d3e4a2a9f083b6de00994cf56c9c727251de0b2.png)
Pinging @peekay123 too…
new is used to allocate a class or array and return a pointer (so you’ll need -> to access members), similar to alloc() but for a class it calls the constructor. Always remember to delete it as well after use, which calls the destructor and frees the memory, which won’t occur on exit of a routine like when instantiated without the new (on the stack).
You could also use a String object to build a URI, like…
String uri = "http://";
uri += "www.mysite.com/";
uri += "?val1=";
uri += number1;
uri += "&val2=";
uri += number2;
1 Like
@LukeUSMC, since the objects will be instantiated dynamically, you might want to write http_header_t headers[3] = { ... }
instead, otherwise you’ll get a zero length array.
Or you declare it static
class Thing
{
private:
//Private functions
//bool parse();
//Private variables
uint8_t thingNum;
http_request_t request;
http_response_t response;
// Headers currently need to be set at init, useful for API keys etc.
static http_header_t headers[];
public:
Thing();
void update();
HttpClient thingWeb;
};
and initialize in the .cpp
http_header_t Thing::headers[] = {
{ "Accept" , "*/*" },
{ "Authorization" , "Basic Base64EncodedUser:Pass" },
{ NULL, NULL }
};
Thank you sir! Went with [3] for now but they are static so may use the other approach long term. Where can I read about dynamic inits so I understand this a bit better? Or even better if you have a fav C++ book I’m all ears.