Http.get Help Please

Hey spark ninjas help me out. I have a variable setup in ubidots ( an awesome service from @aguspg ) and am having trouble reading its status. It will either be 0 or 1 depending on whether my actuator is on or off.

When I try to retrieve the switch status the response.body is always empty making me think I am missing the boat on how to do this right. Tks !

request.path = "/api/v1.6/variables/XXXXXXXXX/values";
request.body = "{\"key\":\"value\"}";
http.get(request,response,headers);
   
String theresponse = response.body;

For reference all my post data works great and I am using #include “HttpClient/HttpClient.h”

Just a quick guess to give you something to try… I haven’t looked into this unidots service but since you are putting stuff in the body of your request, you probably need to perform a POST request, not a GET.

Edit: anyone reading through this, my initial advise was wrong :slight_smile: Keep on reading below

2 Likes

Thanks Bdub I am actually not trying to post I am trying to GET a variable value with XXX being my variable id. I think I must be way off in left field on how to do this based off your comment :smile:

Help?! lol

Ok I’ve reviewed the ubidot’s Spark Core tutorial and I see what you’re up to now :slight_smile: Basically if you want to access a variable in your Ubidot’s dashboard from your Spark Core, you need to perform a GET request. It’s just like a POST request, but you don’t send the request.body. So just comment out this line request.body = "{\"key\":\"value\"}"; and it might not even matter when performing a GET request as you are using http.get() and it probably doesn’t even read the values from request.body.

Make sure you include some code to access the response.body like this:

// Get request
http.get(request, response, headers);
Serial.print("Application>\tResponse status: ");
Serial.println(response.status);

Serial.print("Application>\tHTTP Response Body: ");
Serial.println(response.body);

Without seeing your entire firmware for the Spark Core, it’s kind of hard to tell if you are doing all of this correctly but I get the idea you’re just about there. I’m going to fire up something on my own Core here and see if I can get it working. Ubidots looks pretty cool… they should do a GET example like they did for the POST example which is really well done.

1 Like

Ok I got a working demo here for you… most of the trouble is in parsing the response from Ubidots. I just implemented a simple Switch controller that’s either on or off, but the issue is that the response is in JSON format for one so you have to parse the values out… and two they send a list of all of the past values of that variable. So depending on how you are parsing, you will always find the data you want. I had to effectively write code to determine what was the first valid value and act upon that. Let me know if this helps:

HttpClient http;
#define VARIABLE_ID_LIGHT "544dc00372345234523b19e3c"
#define VARIABLE_ID_SWITCH "54423452345234523521b109d"
#define TOKEN "ninp98f08394j0ifmj0w9ealksdviunwvnsdklsijnvlkjnsidunjnkdjnii34"
int lightLevel = 0;

// Headers currently need to be set at init, useful for API keys etc.
http_header_t headers[] = {
      { "Content-Type", "application/json" },
      { "X-Auth-Token" , TOKEN },
    { NULL, NULL } // NOTE: Always terminate headers will NULL
};

http_request_t request;
http_response_t response;

void setup() {
    pinMode(D7, OUTPUT);
    pinMode(A0, INPUT);
    request.hostname = "things.ubidots.com";
    request.port = 80;
    Serial.begin(9600);
}

void loop() {

    // Read light level from hardware
    lightLevel = analogRead(A0);

    //===============================
    // Send light level to Ubidots
    //===============================
    Serial.println("\n\n\n\n>>> [ SEND DATA TO UBIDOTS ]");
    request.path = "/api/v1.6/variables/"VARIABLE_ID_LIGHT"/values";
    request.body = "{\"value\":" + String(lightLevel) + "}";
    http.post(request, response, headers);
    //Serial.println(response.status);
    //Serial.println(response.body);
    delay(1000);
    
    // Clear the response, in case next request to communicate fails.
    // That way we won't process the previous response for the current request.
    response.body = "";
    response.status = 0;

    //===============================
    // Get switch value from Ubidots
    //===============================
    Serial.println("\n\n\n>>> [ GET DATA FROM UBIDOTS ]");
    request.path = "/api/v1.6/variables/"VARIABLE_ID_SWITCH"/values";
    http.get(request, response, headers);
    //Serial.println(response.status);
    
    // Update D7 LED based on Ubidots Switch value
    // index_on = -1 if not found
    // index_off = -1 if not found
    // index_on < index_off if last command was turning on
    // index_off < index_on if last command was turning off
    //Serial.println(response.body);
    String search_on = String("\"value\": 1.0");
    String search_off = String("\"value\": 0.0");
    int index_on = response.body.indexOf(search_on);
    int index_off = response.body.indexOf(search_off);
    Serial.print("INDEX ON: ");
    Serial.println(index_on);
    Serial.print("INDEX OFF: ");
    Serial.println(index_off);
    if (index_on == -1 && index_off == -1) {
        return;
    }
    else if (index_on != -1 && index_off == -1) {
        digitalWrite(D7, HIGH);
    }
    else if (index_off != 1 && index_on == -1) {
        digitalWrite(D7, LOW);
    }
    else if (index_on < index_off) {
        digitalWrite(D7, HIGH);
    }
    else if (index_off < index_on) {
        digitalWrite(D7, LOW);
    }
    delay(1000);
}

The Ubidot’s switch turns the D7 led on and off on the Spark Core

3 Likes

You sir are my hero.

I am using a SPARK to calculates on demand BTU output of my HVAC system so I know how to do all the fancy math / calculations but some of my code skills are rusty.

I will try to implement tonight and let you know how I make out ! Seriously, thank you!

1 Like

Hi @Herner, I’m glad you worked this out, and @BDub thanks for the awesome support.

It might be worth noting that Ubidots can also return the last value of a variable. To do this, just make your GET request to this URL (same as before but omitting the “/values” at the end):

request.path = "/api/v1.6/variables/"VARIABLE_ID_SWITCH"/";

It will return general information about the Variable, like name, units, etc., as well as the last value.

Another alternative is to use the pagination feature of the Ubidots API, setting a page size of just 1 value:

request.path = "/api/v1.6/variables/"VARIABLE_ID_SWITCH"/values?page_size=1";

Good luck!

1 Like

Ahh, thank you! It was getting late and I had thought there should be a way to do this through the API, but didn't go looking for the answer... just worked with what I had, MacGyver style.

This definitely makes it easier to get the latest value!

1 Like