The weather information on the watch is retrieved from openweathermap.org in the JSON format. I make 2 calls for weather, one for the current conditions and one for forecast.
The URL for current conditions:
var url = "http://api.openweathermap.org/data/2.5/weather?lat=" +
pos.coords.latitude + "&lon=" + pos.coords.longitude;
The URL for forecast conditions:
var forecasturl = "http://api.openweathermap.org/data/2.5/forecast/daily?lat=" +
pos.coords.latitude + "&lon=" + pos.coords.longitude;
Open Weather Map returns the weather data in JSON format.
For an example, we'll pull the weather from Traverse City, Michigan (N44.7681 W86.6222). Winter time in Michigan should have quite interesting weather.
Current Conditions URL:
http://api.openweathermap.org/data/2.5/weather?lat=44.7681&lon=-85.6222
(You can type this URL in your web browser to see the output.)
Current Conditions Raw Output:
{"coord":{"lon":-85.62,"lat":44.77},"sys":{"type":1,"id":1459,"message":0.0399,"country":"US","sunrise":1417265884,"sunset":1417298637},"weather":[{"id":600,"main":"Snow","description":"light snow","icon":"13n"}],"base":"cmc stations","main":{"temp":268.55,"pressure":1017,"humidity":79,"temp_min":267.15,"temp_max":269.15},"wind":{"speed":1.5,"deg":0},"clouds":{"all":90},"dt":1417225020,"id":5012495,"name":"Traverse City","cod":200}
Forecast Conditions URL:
http://api.openweathermap.org/data/2.5/forecast/daily?lat=44.7681&lon=-85.6222
(You can type this URL in your web browser to see the output.)
Forecast Conditions Raw Output:
{"cod":"200","message":0.0066,"city":{"id":5012495,"name":"Traverse City","coord":{"lon":-85.620628,"lat":44.763062},"country":"US","population":0},"cnt":7,"list":[{"dt":1417194000,"temp":{"day":269.15,"min":268.92,"max":270.14,"night":270.14,"eve":269.15,"morn":269.15},"pressure":1004.17,"humidity":100,"weather":[{"id":601,"main":"Snow","description":"snow","icon":"13d"}],"speed":7.88,"deg":170,"clouds":92,"snow":2},{"dt":1417280400,"temp":{"day":278.83,"min":275.01,"max":279.23,"night":278.33,"eve":278.59,"morn":275.01},"pressure":992.92,"humidity":90,"weather":[{"id":600,"main":"Snow","description":"light snow","icon":"13d"}],"speed":7.13,"deg":195,"clouds":48,"snow":0.5},{"dt":1417366800,"temp":{"day":279.25,"min":272.88,"max":279.25,"night":272.88,"eve":275.6,"morn":276.1},"pressure":993.15,"humidity":94,"weather":[{"id":800,"main":"Clear","description":"sky is clear","icon":"02d"}],"speed":7.06,"deg":232,"clouds":8},{"dt":1417453200,"temp":{"day":269.83,"min":267.55,"max":270.65,"night":267.55,"eve":269,"morn":270.65},"pressure":1020.68,"humidity":0,"weather":[{"id":600,"main":"Snow","description":"light snow","icon":"13d"}],"speed":11.08,"deg":308,"clouds":69,"snow":0.82},{"dt":1417539600,"temp":{"day":271.5,"min":268.24,"max":273.72,"night":273.72,"eve":272.95,"morn":268.24},"pressure":1020.55,"humidity":0,"weather":[{"id":600,"main":"Snow","description":"light snow","icon":"13d"}],"speed":8.29,"deg":178,"clouds":0,"snow":0.26},{"dt":1417626000,"temp":{"day":279.39,"min":271.41,"max":279.39,"night":271.41,"eve":276.42,"morn":276.33},"pressure":986.23,"humidity":0,"weather":[{"id":600,"main":"Snow","description":"light snow","icon":"13d"}],"speed":12.83,"deg":208,"clouds":93,"rain":3.44,"snow":0.22},{"dt":1417712400,"temp":{"day":272.6,"min":271.5,"max":272.6,"night":272.49,"eve":272.56,"morn":271.5},"pressure":1003.13,"humidity":0,"weather":[{"id":601,"main":"Snow","description":"snow","icon":"13d"}],"speed":13.59,"deg":285,"clouds":47,"snow":4.52}]}
Paste the raw output above into that parser to see the results.
Parsed Current Conditions:
{
- "coord":{
- "lon":-85.62,
- "lat":44.77
- "sys":{
- "type":1,
- "id":1459,
- "message":0.0399,
- "country":"US",
- "sunrise":1417265884,
- "sunset":1417298637
- "weather":[
- {
- "id":600,
- "main":"Snow",
- "description":"light snow",
- "icon":"13n"
- {
- "base":"cmc stations",
- "main":{
- "temp":268.55,
- "pressure":1017,
- "humidity":79,
- "temp_min":267.15,
- "temp_max":269.15
- "wind":{
- "speed":1.5,
- "deg":0
- "clouds":{
- "all":90
- "dt":1417225020,
- "id":5012495,
- "name":"Traverse City",
- "cod":200
Parsed Forecast Conditions:
{
- "cod":"200",
- "message":0.0066,
- "city":{
- "id":5012495,
- "name":"Traverse City",
- "coord":{
- "lon":-85.620628,
- "lat":44.763062
- "country":"US",
- "population":0
- "cnt":7,
- "list":[
- {
- "dt":1417194000,
- "temp":{
- "day":269.15,
- "min":268.92,
- "max":270.14,
- "night":270.14,
- "eve":269.15,
- "morn":269.15
- "pressure":1004.17,
- "humidity":100,
- "weather":[
- {
- "id":601,
- "main":"Snow",
- "description":"snow",
- "icon":"13d"
- {
- "speed":7.88,
- "deg":170,
- "clouds":92,
- "snow":2
- {
- "dt":1417280400,
- "temp":{
- "day":278.83,
- "min":275.01,
- "max":279.23,
- "night":278.33,
- "eve":278.59,
- "morn":275.01
- "pressure":992.92,
- "humidity":90,
- "weather":[
- {
- "id":600,
- "main":"Snow",
- "description":"light snow",
- "icon":"13d"
- {
- "speed":7.13,
- "deg":195,
- "clouds":48,
- "snow":0.5
- {
- "dt":1417366800,
- "temp":{
- "day":279.25,
- "min":272.88,
- "max":279.25,
- "night":272.88,
- "eve":275.6,
- "morn":276.1
- "pressure":993.15,
- "humidity":94,
- "weather":[
- {
- "id":800,
- "main":"Clear",
- "description":"sky is clear",
- "icon":"02d"
- {
- "speed":7.06,
- "deg":232,
- "clouds":8
- {
- "dt":1417453200,
- "temp":{
- "day":269.83,
- "min":267.55,
- "max":270.65,
- "night":267.55,
- "eve":269,
- "morn":270.65
- "pressure":1020.68,
- "humidity":0,
- "weather":[
- {
- "id":600,
- "main":"Snow",
- "description":"light snow",
- "icon":"13d"
- {
- "speed":11.08,
- "deg":308,
- "clouds":69,
- "snow":0.82
- {
- "dt":1417539600,
- "temp":{
- "day":271.5,
- "min":268.24,
- "max":273.72,
- "night":273.72,
- "eve":272.95,
- "morn":268.24
- "pressure":1020.55,
- "humidity":0,
- "weather":[
- {
- "id":600,
- "main":"Snow",
- "description":"light snow",
- "icon":"13d"
- {
- "speed":8.29,
- "deg":178,
- "clouds":0,
- "snow":0.26
- {
- "dt":1417626000,
- "temp":{
- "day":279.39,
- "min":271.41,
- "max":279.39,
- "night":271.41,
- "eve":276.42,
- "morn":276.33
- "pressure":986.23,
- "humidity":0,
- "weather":[
- {
- "id":600,
- "main":"Snow",
- "description":"light snow",
- "icon":"13d"
- {
- "speed":12.83,
- "deg":208,
- "clouds":93,
- "rain":3.44,
- "snow":0.22
- {
- "dt":1417712400,
- "temp":{
- "day":272.6,
- "min":271.5,
- "max":272.6,
- "night":272.49,
- "eve":272.56,
- "morn":271.5
- "pressure":1003.13,
- "humidity":0,
- "weather":[
- {
- "id":601,
- "main":"Snow",
- "description":"snow",
- "icon":"13d"
- {
- "speed":13.59,
- "deg":285,
- "clouds":47,
- "snow":4.52
- {
With the data parsed using the handy online tool, it is very easy to visualize how it is structured and how we can read the data inside.
For example on the forecast:
"list":[
- {
- "dt":1417194000,
- "temp":{
- "min":268.92,
- "max":270.14,
- },
- "weather":[
- {
- "id":601,
- "main":"Snow",
- "description":"snow",
- "icon":"13d"
- {
To retrieve the dt value for the first day, our JavaScript code will be: json.list[0].dt
To retrieve it for the second day: json.list[1].dt
Min/max temperature is in a group within the primary list.
To retrieve the minimum temperature for the first day: json.list[0].temp.min
To retrieve it for the second day: json.list[1].temp.min
Finally the weather grouping is also an array (note the []s); it's just an array of 1 entry. To get a value from there, we give an index.
To retrieve the "main" weather description for the first day: json.list[0].weather[0].main
To retrieve it for the second day: json.list[1].weather[0].main
Current Weather Conditions
Let's look at the simpler case first, the Current Weather conditions.The JavaScript code for the query: (Some data has been commented out because I'm not using it in the watch face; however, it may be of value to you.)
// Construct URL
var url = "http://api.openweathermap.org/data/2.5/weather?lat=" +
pos.coords.latitude + "&lon=" + pos.coords.longitude;
// Send request to OpenWeatherMap
xhrRequest(url, 'GET',
function(responseText) {
// responseText contains a JSON object with weather info
var json = JSON.parse(responseText);
// Temperature in Kelvin requires adjustment
var temperature = Math.round(json.main.temp - 273.15);
// Conditions
//var conditions = json.weather[0].main;
// Temperature Min
//var temperatureMin = Math.round(json.main.temp_min - 273.15);
// Temperature Min
//var temperatureMax = Math.round(json.main.temp_max - 273.15);
// Wind Speed
var windSpeed = Math.round(json.wind.speed);
// Wind Direction
var windDirection = Math.round(json.wind.deg);
// Humidity
//var humidity = Math.round(json.main.humidity);
// Description
var description = json.weather[0].description;
// Assemble dictionary using our keys
var dictionary = {
"KEY_TEMPERATURE": temperature,
"KEY_WIND_SPEED": windSpeed,
"KEY_WIND_DIRECTION": windDirection,
"KEY_DESCRIPTION": description
};
// "KEY_TEMP_MIN": temperatureMin,
// "KEY_TEMP_MAX": temperatureMax,
// "KEY_CONDITIONS": conditions,
// "KEY_HUMIDITY": humidity,
// Send to Pebble
Pebble.sendAppMessage(dictionary,
function(e) {
//console.log("Weather info sent to Pebble successfully WX!");
},
function(e) {
//console.log("Error sending weather info to Pebble WX!");
}
);
}
);
What happens is the JavaScript code is sending out a query for the weather conditions and getting the response in the JSON format. The JavaScript code then pulls out the values it cares about, associates them with keys I have defined, and builds a dictionary array that is sent to the Pebble C code.
As you can see, JSON returns a wealth of data, but I'm only using the current temperature, wind speed, wind direction, and description.
After some research, I found out the current low and high temperatures returned from the current conditions query aren't actually from forecast data; they're formulated by other conditions throughout the day. The values are not reliable and give poor results. To get good values for the min and max temperature of the day, you must make a separate query for the forecast conditions.
The "description" from JSON is far more descriptive than "main". In this example, the "main" is "Snow" but the description is "light snow". I have room on my text layer so I want to be as descriptive as I can so I went with the "description".
KEY_TEMPERATURE = 0
KEY_CONDITIONS = 1
KEY_TEMP_MIN = 2
KEY_TEMP_MAX = 3
KEY_WIND_SPEED = 4
KEY_WIND_DIRECTION = 5
KEY_HUMIDITY = 6
KEY_DESCRIPTION = 7
The corresponding keys are also #defined in the C code:
#define KEY_TEMPERATURE 0
#define KEY_CONDITIONS 1
#define KEY_TEMP_MIN 2
#define KEY_TEMP_MAX 3
#define KEY_WIND_SPEED 4
#define KEY_WIND_DIRECTION 5
#define KEY_HUMIDITY 6
#define KEY_DESCRIPTION 7
There are existing tutorials on how to setup inbox callbacks with the JavaScript code, so I'll mostly gloss over those details.
In the init(), the inbox_received_callback has been setup to receive the call from the JavaScript code:
app_message_register_inbox_received(inbox_received_callback);
The inbox_received_callback itself:
static void inbox_received_callback(DictionaryIterator *iterator, void *context)
{
...
// Read first item Tuple *t = dict_read_first(iterator);
// For all items
while(t != NULL)
{
// Which key was received?
switch(t->key)
{
case KEY_TEMPERATURE:
currentTemperature_c = t->value->int32;
break;
// case KEY_CONDITIONS:
// // Current conditions (abbreviated).
// break;
// case KEY_TEMP_MIN:
// // Not reliably low temperature.
// break;
// case KEY_TEMP_MAX:
// // Not reliably high temperature.
// break;
case KEY_WIND_SPEED:
// Reported in meters per second, convert to knots.
currentWindSpeed_metersPerSecond = t->value->int32;
break;
case KEY_WIND_DIRECTION:
currentWindDirection_deg = t->value->int32;
break;
// case KEY_HUMIDITY:
// break;
case KEY_DESCRIPTION:
// Similar to conditions, but far more descriptive.
strncpy(currentConditions, t->value->cstring, 32);
break;
...
default:
APP_LOG(APP_LOG_LEVEL_ERROR, "Key %d not recognized!", (int)t->key);
break;
}
// Look for next item
t = dict_read_next(iterator);
}
...
update_weather();
}
In the above code, you can see how the keys that were in the JavaScript code, included in the CloudPebble Settings, and #defined at the top of the C code, are now fully retrieved.
currentTemperature_c, currentWindSpeed_metersPerSecond,currentWindDirection_deg, and currentConditions are defined as global variables at the top of the C code:
static int currentTemperature_c;
static char currentConditions[32];
static int currentWindDirection_deg;
static int currentWindSpeed_metersPerSecond;
The update_weather() function takes those values and updates the text layers on the watch face.
Forecast Weather Conditions
Now for the trickier one, the forecast conditions. The forecast includes 7 days worth of weather data. You can't assume the first weather condition is today, the second weather condition is tomorrow, etc. You must read the date to determine which day the forecast belongs to. Sometimes the first entry of the retrieved data is not in fact today's forecast, it is yesterday's! To be able to get today's and tomorrow's forecast, I have to pull 3 values from the forecast JSON.
Each day's conditions includes a "dt" value which is the date/time of that forecast in UNIX format. We'll be reading that "dt" value to determine what day it belongs to.
For reference, I found a handy UNIX time calculator here: http://www.onlineconversion.com/unix_time.htm Just give it in the "dt" value and it will reply with a more human-friendly date and time.
The JavaScript code:
// Construct URL
var forecasturl = "http://api.openweathermap.org/data/2.5/forecast/daily?lat=" +
pos.coords.latitude + "&lon=" + pos.coords.longitude;
// Send request to OpenWeatherMap
xhrRequest(forecasturl, 'GET',
function(responseForecastText) {
// responseText contains a JSON object with weather info
var json = JSON.parse(responseForecastText);
var day1Time = json.list[0].dt;
// Conditions
var day1Conditions = json.list[0].weather[0].main;
// Temperature in Kelvin requires adjustment
var day1TemperatureMin = Math.round(json.list[0].temp.min - 273.15);
// Temperature in Kelvin requires adjustment
var day1TemperatureMax = Math.round(json.list[0].temp.max - 273.15);
var day2Time = json.list[1].dt;
// Conditions
var day2Conditions = json.list[1].weather[0].main;
// Temperature in Kelvin requires adjustment
var day2TemperatureMin = Math.round(json.list[1].temp.min - 273.15);
// Temperature in Kelvin requires adjustment
var day2TemperatureMax = Math.round(json.list[1].temp.max - 273.15);
var day3Time = json.list[2].dt;
// Conditions
var day3Conditions = json.list[2].weather[0].main;
// Temperature in Kelvin requires adjustment
var day3TemperatureMin = Math.round(json.list[2].temp.min - 273.15);
// Temperature in Kelvin requires adjustment
var day3TemperatureMax = Math.round(json.list[2].temp.max - 273.15);
// Assemble dictionary using our keys
var dictionary = {
"KEY_DAY1_TIME": day1Time,
"KEY_DAY1_CONDITIONS": day1Conditions,
"KEY_DAY1_TEMP_MIN": day1TemperatureMin,
"KEY_DAY1_TEMP_MAX": day1TemperatureMax,
"KEY_DAY2_TIME": day2Time,
"KEY_DAY2_CONDITIONS": day2Conditions,
"KEY_DAY2_TEMP_MIN": day2TemperatureMin,
"KEY_DAY2_TEMP_MAX": day2TemperatureMax,
"KEY_DAY3_TIME": day3Time,
"KEY_DAY3_CONDITIONS": day3Conditions,
"KEY_DAY3_TEMP_MIN": day3TemperatureMin,
"KEY_DAY3_TEMP_MAX": day3TemperatureMax
};
// Send to Pebble
Pebble.sendAppMessage(dictionary,
function(e) {
//console.log("Weather info sent to Pebble successfully WX!");
},
function(e) {
//console.log("Error sending weather info to Pebble WX!");
}
);
}
);
The keys for CloudPebble:
KEY_DAY1_CONDITIONS = 8
KEY_DAY1_TEMP_MIN = 9
KEY_DAY1_TEMP_MAX = 10
KEY_DAY1_TIME = 11
KEY_DAY2_CONDITIONS = 12
KEY_DAY2_TEMP_MIN = 13
KEY_DAY2_TEMP_MAX = 14
KEY_DAY2_TIME = 15
KEY_DAY3_CONDITIONS = 16
KEY_DAY3_TEMP_MIN = 17
KEY_DAY3_TEMP_MAX = 18
KEY_DAY3_TIME = 19
The corresponding keys #defined in the C code:
#define KEY_DAY1_CONDITIONS 8
#define KEY_DAY1_TEMP_MIN 9
#define KEY_DAY1_TEMP_MAX 10
#define KEY_DAY1_TIME 11
#define KEY_DAY2_CONDITIONS 12
#define KEY_DAY2_TEMP_MIN 13
#define KEY_DAY2_TEMP_MAX 14
#define KEY_DAY2_TIME 15
#define KEY_DAY3_CONDITIONS 16
#define KEY_DAY3_TEMP_MIN 17
#define KEY_DAY3_TEMP_MAX 18
#define KEY_DAY3_TIME 19
And now the C code:
static void inbox_received_callback(DictionaryIterator *iterator, void *context)
{
...
// Read first item
Tuple *t = dict_read_first(iterator);
int day1Date = 0;
int day2Date = 0;
//int day3Date = 0;
int day1LowTemperature_c = 0;
int day2LowTemperature_c = 0;
int day3LowTemperature_c = 0;
int day1HighTemperature_c = 0;
int day2HighTemperature_c = 0;
int day3HighTemperature_c = 0;
char day1Conditions[32];
char day2Conditions[32];
char day3Conditions[32];
// For all items
while(t != NULL)
{
// Which key was received?
switch(t->key)
{
...
case KEY_DAY1_TIME:
// Usually today's date, but in the morning it's yesterday's!
day1Date = t->value->int32;
break;
case KEY_DAY1_CONDITIONS:
// Today's condition (abbreviated).
//snprintf(day1_conditions_buffer, sizeof(day1_conditions_buffer), "%s", t->value->cstring);
strncpy(day1Conditions, t->value->cstring, 32);
break;
case KEY_DAY1_TEMP_MIN:
//currentLowTemperature_c = t->value->int32;
day1LowTemperature_c = t->value->int32;
break;
case KEY_DAY1_TEMP_MAX:
//currentHighTemperature_c = t->value->int32;
day1HighTemperature_c = t->value->int32;
break;
case KEY_DAY2_TIME:
// Usually it's tomorrow's date, but in the morning it's today's!.
//forecastDate = t->value->int32;
day2Date = t->value->int32;
break;
case KEY_DAY2_CONDITIONS:
// Forecast condition (abbreviated).
//strncpy(forecastConditions, t->value->cstring, 32);
strncpy(day2Conditions, t->value->cstring, 32);
break;
case KEY_DAY2_TEMP_MIN:
//forecastLowTemperature_c = t->value->int32;
day2LowTemperature_c = t->value->int32;
break;
case KEY_DAY2_TEMP_MAX:
//forecastHighTemperature_c = t->value->int32;
day2HighTemperature_c = t->value->int32;
break;
case KEY_DAY3_TIME:
// Usually it's in two days, but in the morning it's tomorrow's!
//day3Date = t->value->int32;
break;
case KEY_DAY3_CONDITIONS:
// Forecast condition (abbreviated).
strncpy(day3Conditions, t->value->cstring, 32);
break;
case KEY_DAY3_TEMP_MIN:
//day3LowTemperature_c = t->value->int32;
day3LowTemperature_c = t->value->int32;
break;
case KEY_DAY3_TEMP_MAX:
day3HighTemperature_c = t->value->int32;
break;
...
default:
APP_LOG(APP_LOG_LEVEL_ERROR, "Key %d not recognized!", (int)t->key);
break;
}
// Look for next item
t = dict_read_next(iterator);
}
if (day1Date > 0)
{
// Forecast Response
time_t currentTime = time(NULL);
struct tm *currentCalendarTime = localtime(¤tTime);
int dayOfMonthCurrent = currentCalendarTime->tm_mday;
time_t day1Date_t = day1Date;
struct tm *day1CalendarTime = localtime(&day1Date_t);
int dayOfMonth1 = day1CalendarTime->tm_mday;
time_t day2Date_t = day2Date;
struct tm *day2CalendarTime = localtime(&day2Date_t);
int dayOfMonth2 = day2CalendarTime->tm_mday;
if (dayOfMonthCurrent == dayOfMonth1)
{
// Day 1 is Today's Date
currentDate = day1Date;
strncpy(currentDayForecastConditions, day1Conditions, 32);
currentLowTemperature_c = day1LowTemperature_c;
currentHighTemperature_c = day1HighTemperature_c;
// So Day 2 will be the forecast.
strncpy(forecastConditions, day2Conditions, 32);
forecastLowTemperature_c = day2LowTemperature_c;
forecastHighTemperature_c = day2HighTemperature_c;
}
else if (dayOfMonthCurrent == dayOfMonth2)
{
// Day 2 is Today's Date
currentDate = day2Date;
strncpy(currentDayForecastConditions, day2Conditions, 32);
currentLowTemperature_c = day2LowTemperature_c;
currentHighTemperature_c = day2HighTemperature_c;
// So Day 3 will be the forecast.
strncpy(forecastConditions, day3Conditions, 32);
forecastLowTemperature_c = day3LowTemperature_c;
forecastHighTemperature_c = day3HighTemperature_c;
}
} // (day1Date > 0)
...
update_weather();
}
The key piece above is determining if the first forecast condition is today's date or yesterday's.
I get the current day of the month:
time_t currentTime = time(NULL);
struct tm *currentCalendarTime = localtime(¤tTime);
int dayOfMonthCurrent = currentCalendarTime->tm_mday;
the first forecast day of the month:
time_t day1Date_t = day1Date;
struct tm *day1CalendarTime = localtime(&day1Date_t);
int dayOfMonth1 = day1CalendarTime->tm_mday;
and the second forecast day of the month:
time_t day2Date_t = day2Date;
struct tm *day2CalendarTime = localtime(&day2Date_t);
int dayOfMonth2 = day2CalendarTime->tm_mday;
If my current day of the month equals the first forecast day:
if (dayOfMonthCurrent == dayOfMonth1)
{
Then I know the first value from the JSON data is today's forecast (and the second value is tomorrow's):
// Day 1 is Today's Date
currentDate = day1Date;
strncpy(currentDayForecastConditions, day1Conditions, 32);
currentLowTemperature_c = day1LowTemperature_c;
currentHighTemperature_c = day1HighTemperature_c;
// So Day 2 will be the forecast.
strncpy(forecastConditions, day2Conditions, 32);
forecastLowTemperature_c = day2LowTemperature_c;
forecastHighTemperature_c = day2HighTemperature_c;
Else if my current day of the month equals the second forecast day:
else if (dayOfMonthCurrent == dayOfMonth2)
{
Then I know the second value from the JSON data is today's forecast (and the third value is tomorrow's):
// Day 2 is Today's Date
currentDate = day2Date;
strncpy(currentDayForecastConditions, day2Conditions, 32);
currentLowTemperature_c = day2LowTemperature_c;
currentHighTemperature_c = day2HighTemperature_c;
// So Day 3 will be the forecast.
strncpy(forecastConditions, day3Conditions, 32);
forecastLowTemperature_c = day3LowTemperature_c;
forecastHighTemperature_c = day3HighTemperature_c;
Please refer to the first Pebble Watchface post for the full source code. Hopefully this has aided you in parsing JSON / weather data!