Mashery Weather Application

Introduction

This article is a brief explanation of how to create a simple application that demonstrates the usage of the Mashery API on the Intel® Galileo board. The application fetches the current weather of a particular location, is written in C, and uses libcurl, the Mashery Web API and a light-weight parson for parsing the JSON data.

To fetch the weather data, the application uses Free Weather API and needs an API key. You can get the API key by registering here.

Compilation

Import the source files into a project created by selecting File -> Other Project -> Yocto C Project. As mentioned earlier, the application uses libcurl and parson, hence they have to be added in the Makefile.am located under the src folder. parson.c must be added to PROJXX_SOURCES and -lcurl to XX_LDFLAGS.

PROJXX_SOURCES = weather.c parser.c
XX_LDFLAGS = -lcurl

Mashery API

The application uses the Free Weather API provided by World Weather Online APIs to fetch the weather information. For example, the API below fetches the weather data for Barcelona, Spain and specifies a JSON response format.

http://api.worldweatheronline.com/free/v1/weather.ashx?q=Barcelona&format=json&num_of_days=5&key=*****

libcurl

The libcurl library is used to request weather data using the above URL. The curl_easy_init() function starts a libcurl session and returns a CURL easy handle used in future operations.

The curl_easy_setopt() function can be used to set the URL using the CURLOPT_URL option.

CURL *curl_handle;
FILE * fptr; 
/* URL for the API call */
char *url="http://api.worldweatheronline.com/free/v1/weather.ashx?q=Barcelona&format=json&num_of_days=1&key=***";
CURLcode res;

curl_handle = curl_easy_init();
if(curl_handle) {
	curl_easy_setopt(curl_handle, CURLOPT_URL, url);	

	curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);

	fptr = fopen(output_filename,"w+");
	if(!fptr) {
		printf("Exiting, error opening file");
		/* always cleanup */
		curl_easy_cleanup(curl_handle);
		return 1;
	}
	/* write content to the file handle */ 
	curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, fptr); 

	res = curl_easy_perform(curl_handle);
	printf("\nWeather Report Query Status:: %d\n", res);

	fclose (fptr); 
	curl_easy_cleanup(curl_handle);	
}
return 0;

The response can be read using the same function call with the CURLOPT_WRITEFUNCTION option. A pointer to the function with prototype size_t function(char *ptr, size_t size, size_t nmemb, void *userdata); is passed as an argument, which will be called when data is received. This data is stored as a file stream. The received data is stored in a file using option CURLOPT_WRITEDATA by passing a file pointer as argument. The file transfer is performed while making a call to curl_easy_perform(curl_handle). Make sure to clean up the handle once the data is saved in a file by making a call to curl_easy_cleanup(curl_handle).

Parson

Parson, a light weight JSON parser was used to parse the received JSON data. The json_parse_file() function takes file name as arguments, parses the JSON and returns NULL on error. A call to json_value_get_object returns the root object from the data. The required information, specifically the weather code, can be retrieved from the object using json_object_dotget_array, which returns an array with the target objects.

JSON_Value *root_value;
JSON_Array *array;
JSON_Object *root_object, *CCobject;
const char *weatherValue;
int ret_val = -1; 
char cleanup_file[256];
sprintf(cleanup_file, "rm -f %s", output_filename);

/* now parse the json file */
root_value = json_parse_file(output_filename);
if (json_value_get_type(root_value) != JSONObject) {
	return;
}    
/* get the root object */
root_object = json_value_get_object(root_value); 

/* Now get the required array from the root object*/
array = json_object_dotget_array(root_object, "data.current_condition");
if (array != NULL) {
	/* The array has target objects, so get the object of first array element*/
	CCobject = json_array_get_object(array,0);

	/* Now with the target object retrieve the values */
	weatherValue = json_object_get_string(CCobject, "weatherCode");

	ret_val = updateWeatherData(atoi(weatherValue));
	printf("Return Value = %d\n", ret_val);
} else {
	printf("Empty array\n");
}

/* cleanup code */
json_value_free(root_value);
system(cleanup_file);
return 0;

The object in the first array contains the target data. Using json_array_get_object, the object can be retrieved and the needed value is associated with the object. json_object_get_string will return the value (weather code) while taking the object and the key “weatherCode” as arguments.

updateWeatherData

This function determines the weather condition based on the given weather code. Based on the condition, it calls the writeToGPIOPort function to turn ON the appropriate LED.

writeToGPIOPort

This function takes the port as input and makes a call to openGPIOFile to open the port in write mode. The openGIOFile function sets the direction to "OUT" and returns the fileHandle in O_WRONLY mode. This handle is used to either turn ON or OFF the LED.

For more complete information about compiler optimizations, see our Optimization Notice.

2 comments

Top
Naga Venkata Raghu Kiran K. (Intel)'s picture

This code sample demonstrates the use of IoT wherein which it gets the weather data using mashery API provided by http://developer.worldweatheronline.com/io-docs. If your query is more like where exactly the Galileo's pins are accessed, it is not added in the document. In writeToGPIOPort, openGPIOFile function is called. This is where the actual GPIO ports are made high or low based on the input received. The source code looks something like


 

int writeToGPIOPort(int gpioPort, int val)
{
int gpioFileHandle;
/* open the GPIO file */
gpioFileHandle = openGPIOFile(gpioPort, val);
if(ERROR == gpioFileHandle)
{
return(-1);
}
if(val == 0)
{
/* Set LOW on GPIO port */
write(gpioFileHandle, "0", 1);
}
else
{
/* Set HIGH on GPIO port */
write(gpioFileHandle, "1", 1);
}
close(gpioFileHandle);
return(0);
}
 
int openGPIOFile(int gpio, int direction )
{
char buffer[256];
int fileHandle;
int fileMode;
 
  /* Export GPIO */
fileHandle = open("/sys/class/gpio/export", O_WRONLY);
if(ERROR == fileHandle)
{
puts("Error: Unable to opening /sys/class/gpio/export");
return(-1);
}
sprintf(buffer, "%d", gpio);
write(fileHandle, buffer, strlen(buffer));
close(fileHandle);
 
   /* Direction GPIO */
sprintf(buffer, "/sys/class/gpio/gpio%d/direction", gpio);
fileHandle = open(buffer, O_WRONLY);
 
/* Set out direction */
write(fileHandle, "out", 3);
fileMode = O_WRONLY;
close(fileHandle);
 
   /* Open GPIO for Read / Write */
sprintf(buffer, "/sys/class/gpio/gpio%d/value", gpio);
fileHandle = open(buffer, fileMode);
if(ERROR == fileHandle)
{
puts("Unable to open file:");
puts(buffer);
return(-1);
}
 
return(fileHandle); /* This file handle will be used in read/write and close operations. */
}

Regards,

Raghu Kona

P W.'s picture

Is WeatherOnLine API a Mashery API?

It is not clear to me which part of this is IoT related. I could use curl on any Linux machine to get to WeatherOnLine.

 

Add a Comment

Have a technical question? Visit our forums. Have site or software product issues? Contact support.