ubuntu-touch-coreapps-reviewers team mailing list archive
-
ubuntu-touch-coreapps-reviewers team
-
Mailing list archive
-
Message #09493
[Merge] lp:~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api into lp:ubuntu-weather-app
Victor Thompson has proposed merging lp:~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api into lp:ubuntu-weather-app.
Commit message:
* Update to use new weather API
* Change the trimAPIKey function so it only trims the API Key
Requested reviews:
Ubuntu Weather Developers (ubuntu-weather-dev)
Related bugs:
Bug #1511070 in Ubuntu Weather App: "TWC API change"
https://bugs.launchpad.net/ubuntu-weather-app/+bug/1511070
For more details, see:
https://code.launchpad.net/~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api/+merge/289584
Move to the new weather api.
For reference, here is the commit to use the new API in the scope: http://bazaar.launchpad.net/~ubuntuone-hackers/ubuntu-rest-scopes/trunk/revision/505
--
Your team Ubuntu Weather Developers is requested to review the proposed merge of lp:~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api into lp:ubuntu-weather-app.
=== modified file 'app/data/WeatherApi.js'
--- app/data/WeatherApi.js 2015-10-21 02:16:50 +0000
+++ app/data/WeatherApi.js 2016-05-28 00:41:30 +0000
@@ -100,15 +100,20 @@
}
-// Remove anything including and after APPID in the given term
+// Remove just the API key
function trimAPIKey(data) {
- var owm = data.indexOf("&APPID=");
- var twc = data.indexOf("&key=");
+ var owm = data.indexOf("APPID=");
+ var twc = data.indexOf("apiKey=");
+
+ // Key length is 32 char for both APIs
+ var keySize = 32;
if (owm > -1) {
- data = data.substr(0, owm);
+ var replace = data.substr(owm+6, keySize);
+ data = data.replace(replace,"")
} else if (twc > -1) {
- data = data.substr(0, twc);
+ var replace = data.substr(twc+7, keySize);
+ data = data.replace(replace,"")
}
return data;
@@ -400,7 +405,7 @@
/**
provides neccessary methods for requesting and preparing data from OpenWeatherMap.org
*/
- var _baseUrl = "http://wxdata.weather.com/wxdata/";
+ var _baseUrl = "https://api.weather.com/";
//
var _serviceName = "weatherchannel";
//
@@ -457,65 +462,70 @@
};
//
function _buildDataPoint(date, dataObj) {
- var data = dataObj["Observation"] || dataObj,
+ var partData = dataObj["metric"] || dataObj["imperial"] || dataObj; // TODO: be more intelligent?
+ var data = dataObj["observation"] || dataObj,
result = {
- timestamp: data.date || data.dateTime,
+ timestamp: data.fcst_valid,
date: date,
metric: {
- temp: data.temp,
- tempFeels: data.feelsLike,
- windSpeed: data.wSpeed
+ temp: partData.temp,
+ tempFeels: partData.feels_like,
+ windSpeed: partData.wspd
},
imperial: {
- temp: calcFahrenheit(data.temp),
- tempFeels: calcFahrenheit(data.feelsLike),
- windSpeed: convertKphToMph(data.wSpeed)
+ temp: calcFahrenheit(partData.temp),
+ tempFeels: calcFahrenheit(partData.feels_like),
+ windSpeed: convertKphToMph(partData.wspd)
},
precipType: (data.precip_type !== undefined) ? data.precip_type : null,
propPrecip: (data.pop !== undefined) ? data.pop : null,
- humidity: data.humid,
- pressure: data.pressure,
- windDeg: data.wDir,
- windDir: data.wDirText,
- icon: _iconMap[(data.wxIcon||data.icon)],
- condition: data.text || data.wDesc,
- uv: data.uv
+ humidity: partData.rh,
+ pressure: partData.mslp,
+ windDeg: data.wdir,
+ windDir: data.wdir_cardinal,
+ icon: _iconMap[data.icon_code],
+ condition: data.phrase_32char,
+ uv: data.uv_index
};
- if(_iconMap[data.wxIcon||data.icon] === undefined) {
- print("ICON MISSING POINT: "+(data.wxIcon||data.icon)+" "+result.condition)
+
+ if (_iconMap[data.icon_code] === undefined) {
+ print("ICON MISSING POINT: " + data.icon_code + " " + result.condition)
}
+
return result;
}
//
function _buildDayFormat(date, data, now) {
- var partData = (now > data.validDate || data.day === undefined) ? data.night : data.day,
+ var partData = (now > data.fcst_valid || data.day === undefined) ? data.night : data.day,
result = {
date: date,
- timestamp: data.validDate,
+ timestamp: data.fcst_valid,
metric: {
- tempMin: data.minTemp,
- tempMax: data.maxTemp,
- windSpeed: partData.wSpeed
+ tempMin: data.min_temp,
+ tempMax: data.max_temp,
+ windSpeed: partData.wspd
},
imperial: {
- tempMin: calcFahrenheit(data.minTemp),
- tempMax: calcFahrenheit(data.maxTemp !== undefined ? data.maxTemp : data.minTemp),
- windSpeed: convertKphToMph(partData.wSpeed)
+ tempMin: calcFahrenheit(data.min_temp),
+ tempMax: calcFahrenheit(data.max_temp !== undefined ? data.max_temp : data.min_temp),
+ windSpeed: convertKphToMph(partData.wspd)
},
precipType: partData.precip_type,
propPrecip: partData.pop,
pressure: null,
- humidity: partData.humid,
- icon: _iconMap[partData.icon],
- condition: partData.phrase,
- windDeg: partData.wDir,
- windDir: partData.wDirText,
- uv: partData.uv,
+ humidity: partData.rh,
+ icon: _iconMap[partData.icon_code],
+ condition: partData.phrase_32char,
+ windDeg: partData.wdir,
+ windDir: partData.wdir_cardinal,
+ uv: partData.uv_index,
hourly: []
}
- if(_iconMap[partData.icon] === undefined) {
- print("ICON MISSING DAY: "+partData.icon+" "+result.condition)
+
+ if (_iconMap[partData.icon_code] === undefined) {
+ print("ICON MISSING DAY: " + partData.icon_code + " " + result.condition)
}
+
return result;
}
//
@@ -527,35 +537,43 @@
nowMs = parseInt(now/1000),
localNow = getLocationTime(now+offset),
data = {
- "location": combinedData[0]["Location"],
- "daily": combinedData[0]["DailyForecasts"],
- "forecast": combinedData[0]["HourlyForecasts"],
- "current": combinedData[0]["StandardObservation"],
- "sunRiseSet": combinedData[0]["SunRiseSet"],
+ "location": combinedData["current"]["metadata"],
+ "daily": combinedData["daily"]["forecasts"],
+ "forecast": combinedData["forecast"]["forecasts"],
+ "current": combinedData["current"]["observation"],
};
print("["+location.name+"] "+JSON.stringify(localNow));
// add openweathermap id for faster responses
if(location.services && !location.services[_serviceName] && data["location"].key) {
location.services[_serviceName] = data["location"].key
- }
+ }
// only 5 days of forecast for TWC
- for(var x=0;x<5;x++) {
+ for(var x=0; x<5; x++) {
var dayData = data["daily"][x],
- date = getLocationTime(((dayData.validDate*1000)-1000)+offset); // minus 1 sec to handle +/-12 TZ
- var sunRiseSet = data["sunRiseSet"][x];
+ date = getLocationTime(((dayData.fcst_valid * 1000) - 1000) + offset); // minus 1 sec to handle +/-12 TZ
+
+ // Sun{rise,set} is in ISOString format so use getTime() to convert
+ var sunrise = new Date(dayData.sunrise).getTime(),
+ sunset = new Date(dayData.sunset).getTime();
day = date.year+"-"+date.month+"-"+date.date;
- if(!todayDate) {
- if(localNow.year+"-"+localNow.month+"-"+localNow.date > day) {
+
+ if (!todayDate) {
+ if (localNow.year + "-" + localNow.month + "-" + localNow.date > day) {
// skip "yesterday"
continue;
}
+
todayDate = date;
}
+
tmpResult[day] = _buildDayFormat(date, dayData, nowMs);
+
var timezoneOffset = new Date().getTimezoneOffset();
var timesOffset = (location.timezone && location.timezone.dstOffset !== undefined) ? (location.timezone.dstOffset*60 + timezoneOffset)*60*1000: 0
- var sunrise = new Date(sunRiseSet.rise*1000 + timesOffset);
- var sunset = new Date(sunRiseSet.set*1000 + timesOffset);
+
+ sunrise = new Date(sunrise + timesOffset);
+ sunset = new Date(sunset + timesOffset);
+
var options = { timeZone: location.timezone.timeZoneId, timeZoneName: 'long' };
tmpResult[day].sunrise = sunrise.toLocaleTimeString(Qt.locale().name, options);
tmpResult[day].sunset = sunset.toLocaleTimeString(Qt.locale().name, options);
@@ -563,8 +581,9 @@
//
if(data["forecast"] !== undefined) {
data["forecast"].forEach(function(hourData) {
- var dateData = getLocationTime((hourData.dateTime*1000)+offset),
+ var dateData = getLocationTime((hourData.fcst_valid * 1000) + offset),
day = dateData.year+"-"+dateData.month+"-"+dateData.date;
+
if(tmpResult[day]) {
tmpResult[day]["hourly"].push(_buildDataPoint(dateData, hourData));
}
@@ -591,48 +610,101 @@
return result;
}
//
- function _getUrl(params) {
- var url, serviceId,
- baseParams = {
- key: params.twc_api_key,
- units: (params.units === "metric") ? "m" : "e",
- locale: Qt.locale().name,
- hours: "48",
- },
- commands = {
- "mobileaggregation": "mobile/mobagg/",
+ function _getUrls(params) {
+ var baseParams = {
+ units: (params.units === "metric") ? "m" : "e",
+ language: Qt.locale().name.replace("_","-"),
+ apiKey: params.twc_api_key,
+ };
+ var commands = {
+ "geocode": "v1/geocode/",
+ };
+ var urls = {
+ current: "",
+ daily: "",
+ hourly: "",
+ };
+
+ if(1==2 && params.location.services && params.location.services[_serviceName]) { // FIXME: disable for now (UKXX0085)
+ var serviceId = encodeURIComponent(params.location.services[_serviceName]);
+
+ urls.current = _baseUrl + commands["geocode"] +
+ serviceId + ".js?" + parameterize(baseParams);
+ urls.daily = _baseUrl + commands["geocode"] +
+ serviceId + ".js?" + parameterize(baseParams);
+ urls.hourly = _baseUrl + commands["geocode"] +
+ serviceId + ".js?" + parameterize(baseParams);
+ } else if (params.location.coord) {
+ var coord = {
+ lat: params.location.coord.lat,
+ lng: params.location.coord.lon
};
- if(params.location.services && params.location.services[_serviceName]) {
- serviceId = encodeURIComponent(params.location.services[_serviceName]);
- url = _baseUrl+commands["mobileaggregation"]+serviceId+".js?"+parameterize(baseParams);
- } else if (params.location.coord) {
- var coord = {lat: params.location.coord.lat, lng: params.location.coord.lon};
- url = _baseUrl+commands["mobileaggregation"]+"get.js?"+parameterize(baseParams)+"&"+
- parameterize(coord);
+
+ urls.current = _baseUrl + commands["geocode"] +
+ coord.lat + "/" + coord.lng +
+ "/observations/current.json?" +
+ parameterize(baseParams);
+ urls.daily = _baseUrl + commands["geocode"] +
+ coord.lat + "/" + coord.lng +
+ "/forecast/daily/5day.json?" +
+ parameterize(baseParams);
+ urls.hourly = _baseUrl + commands["geocode"] +
+ coord.lat + "/" + coord.lng +
+ "/forecast/hourly/48hour.json?" +
+ parameterize(baseParams);
}
- return url;
+
+ return urls;
}
//
return {
getData: function(params, apiCaller, onSuccess, onError) {
- var url = _getUrl(params),
+ var urls = _getUrls(params),
handlerMap = {
- all: { type: "all", url: url}
- },
- response = {
- location: params.location,
- db: (params.db) ? params.db : null,
- format: RESPONSE_DATA_VERSION
- },
- addDataToResponse = (function(request, data) {
- var formattedResult;
- response["data"] = formatResult(data, params.location);
+ current: {
+ type: "current",
+ url: urls.current
+ },
+ daily: {
+ type: "daily",
+ url: urls.daily
+ },
+ forecast: {
+ type: "forecast",
+ url: urls.hourly
+ }
+ },
+ response = {
+ location: params.location,
+ db: (params.db) ? params.db : null,
+ format: RESPONSE_DATA_VERSION
+ },
+ respData = {},
+ addDataToResponse = (function(request, data) {
+ var formattedResult;
+ respData[request.type] = data;
+
+ if (respData["current"] !== undefined &&
+ respData["forecast"] !== undefined &&
+ respData["daily"] !== undefined) {
+
+ response["data"] = formatResult(respData, params.location);
onSuccess(response);
- }),
- onErrorHandler = (function(err) {
- onError(err);
- });
- apiCaller(handlerMap.all, addDataToResponse, onErrorHandler);
+ }
+ }),
+ onErrorHandler = (function(err) {
+ onError(err);
+ }),
+ retryHandler = (function(err) {
+ console.log("retry of " + trimAPIKey(err.request.url));
+ var retryFunc = handlerMap[err.request.type];
+
+ apiCaller(retryFunc, addDataToResponse, onErrorHandler);
+ });
+
+ apiCaller(handlerMap.current, addDataToResponse, retryHandler);
+ apiCaller(handlerMap.forecast, addDataToResponse, retryHandler);
+ apiCaller(handlerMap.daily, addDataToResponse, retryHandler);
}
}
})();
Follow ups
-
Re: [Merge] lp:~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api into lp:ubuntu-weather-app
From: Jenkins Bot, 2016-06-08
-
[Merge] lp:~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api into lp:ubuntu-weather-app
From: noreply, 2016-06-05
-
[Merge] lp:~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api into lp:ubuntu-weather-app
From: Victor Thompson, 2016-06-05
-
Re: [Merge] lp:~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api into lp:ubuntu-weather-app
From: Victor Thompson, 2016-06-05
-
Re: [Merge] lp:~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api into lp:ubuntu-weather-app
From: Jenkins Bot, 2016-06-04
-
Re: [Merge] lp:~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api into lp:ubuntu-weather-app
From: Jenkins Bot, 2016-06-04
-
Re: [Merge] lp:~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api into lp:ubuntu-weather-app
From: Victor Thompson, 2016-06-04
-
Re: [Merge] lp:~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api into lp:ubuntu-weather-app
From: Victor Thompson, 2016-06-04
-
Re: [Merge] lp:~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api into lp:ubuntu-weather-app
From: Jenkins Bot, 2016-06-04
-
Re: [Merge] lp:~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api into lp:ubuntu-weather-app
From: Andrew Hayzen, 2016-06-04
-
Re: [Merge] lp:~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api into lp:ubuntu-weather-app
From: Jenkins Bot, 2016-06-04
-
[Merge] lp:~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api into lp:ubuntu-weather-app
From: Andrew Hayzen, 2016-06-04
-
Re: [Merge] lp:~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api into lp:ubuntu-weather-app
From: Victor Thompson, 2016-05-30
-
Re: [Merge] lp:~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api into lp:ubuntu-weather-app
From: Jenkins Bot, 2016-05-28
-
Re: [Merge] lp:~ubuntu-weather-dev/ubuntu-weather-app/new-weather-api into lp:ubuntu-weather-app
From: Andrew Hayzen, 2016-05-28