Making REST calls with Arduino

I recently did a small hello world project on arduino, the basic use case was to read a students RFID tag and cross-check it with our own server to check if the student was registered or not. Pretty simple right? Not when it’s your first project!

Anyway, there are enough of tutorials about scanning RFID tags using arduino so I won’t talk about that much here. Instead I’m gonna talk about a potentially big problem for anyone using this for the first time.

My basic configuration:

  • Arduino Mega 2560 board
  • CC3000 Wifi Shield
  • RFID Scanner module

The first problem,

You have to use a external library to interface with the CC3000 shield. We used the Adafruit_CC3000_Library. Now why do I say this is a problem?

The documentation is very limited and hard to find, I had to finally go through the code to find the problem.

The basic structure of making the rest call is this:

#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
#include "utility/debug.h"

#define ADAFRUIT_CC3000_IRQ   3
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10
#define WLAN_SSID       "myWIFI"
#define WLAN_PASS       "myPassword"
#define WLAN_SECURITY   WLAN_SEC_WPA2
#define IDLE_TIMEOUT_MS  3000
#define WEBSITE      "www.example.com"
#define WEB_HOST_IP      cc3000.IP2U32(192, 168, 253, 71)
#define WEBPAGE      "/users/student/rfidvalidate/"
#define WEBPAGE2      "/users/student/rfidvalidate/24853484854666952526567483"
#define WEBPORT      3000

Adafruit_CC3000_Client www;
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
	SPI_CLOCK_DIVIDER);
uint32_t ip;
void setup(){
	resolveHostDetails();
	sendRequest();
	processResponse();

}
void loop(){}
void resolveHostDetails() {
	ip = WEB_HOST_IP;
  //This happens only if there is no ip specified
	while (ip == 0) {
		if (! cc3000.getHostByName(WEBSITE, &ip)) {
			Serial.println(F("Couldn't resolve!"));
		}
		delay(500);
	}

}
void sendRequest() {
	www = cc3000.connectTCP(ip, WEBPORT);
	if (www.connected()) {
		www.fastrprint(F("GET "));
		www.fastrprint(WEBPAGE2);
		www.fastrprint(F(" HTTP/1.1\r\n"));
		www.fastrprint(F("Host: ")); www.fastrprint(WEBSITE); www.fastrprint(F("\r\n"));
		www.fastrprint(F("\r\n"));
		www.println();
	} else {
		Serial.println(F("Connection failed"));
		return ;
	}
}

void processResponse() {
  /* Read data until either the connection is closed, or the idle timeout is reached. */
	unsigned long lastRead = millis();
	while (www.connected() && (millis() - lastRead < IDLE_TIMEOUT_MS)) {
		while (www.available()) {
			char c = www.read();
			Serial.print(c);
			lastRead = millis();
		}
	}
	www.close();
}

 

So the problem here is this. The WEBPAGE is a constant and you cannot concatenate to a constant neither can you pass a string there since fastprint does not accept it. So how do I add the RFID tag to the URL request dynamically? I was stuck on that myself for awhile before I finally went through the code for the CC3000 library. I checked the overloads for the fastprint method and found out that it accepts a array of chars. So then what i did was made my own string, concatenated the WEBPAGE and the tag scanned and converted it to a char array and passes that instead. Worked like a charm. Just remember to clear the char array after you’re done otherwise it might lead to some errors.

Here’s the improved code, just replace the old sendRequest() method with this,

void sendRequest(String tagID) {
	String url = WEBPAGE + tagID;
	int x = url.length() + 1;
	char test[x];
	url.toCharArray(test, x);
  //Incase you want to check your url
	Serial.println("XXXXXXXXXXXXXX");
	for (int i = 0; i < x; i++) {
		Serial.print(test[i]);
	}
	Serial.println("");
	Serial.println("XXXXXXXXXXXXXX");

	www = cc3000.connectTCP(ip, WEBPORT);
	if (www.connected()) {
		www.fastrprint(F("GET "));
		www.fastrprint(test);
		www.fastrprint(F(" HTTP/1.1\r\n"));
		www.fastrprint(F("Host: "));
    //www.fastrprint(WEBSITE);
		www.fastrprint(F("\r\n"));
		www.fastrprint(F("\r\n"));
		www.println();
	} else {
		Serial.println(F("Connection failed"));
		return ;
	}
}

Some notes,

I did not include the code to connect to the wifi, that’s pretty boilerplate stuff.

When connecting to wifi it’s normal for the code to hang at the dhcp request for awhile.(You might even have to reset your board a few times.)

The CC3000 library is prone to give a Connection failed sometimes after a few requests, if anyone finds out why please do comment below 🙂

 

That’s about it. If there are any questions feel free to ask as always. 🙂

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s