/
weather.js
executable file
·179 lines (148 loc) · 5.37 KB
/
weather.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/* general utility stuff related to weather */
var weatherProviders = {
'owm' : require('./weather_owm'),
// 'forecast' : require('weather_forecast'),
'wunderground' : require('./weather_wunderground')
};
var DEFAULT_WEATHER_PROVIDER = 'owm';
// get new forecasts if 3 hours have elapsed
var FORECAST_MAX_AGE = 3 * 60 * 60 * 1000;
var MAX_FAILURES = 3;
var currentFailures = 0;
// icon codes for sending weather icons to pebble
var WeatherIcons = {
CLEAR_DAY : 0,
CLEAR_NIGHT : 1,
CLOUDY_DAY : 2,
HEAVY_RAIN : 3,
HEAVY_SNOW : 4,
LIGHT_RAIN : 5,
LIGHT_SNOW : 6,
PARTLY_CLOUDY_NIGHT : 7,
PARTLY_CLOUDY : 8,
RAINING_AND_SNOWING : 9,
THUNDERSTORM : 10,
WEATHER_GENERIC : 11
};
function getCurrentWeatherProvider() {
var currentWeatherProvider = window.localStorage.getItem('weather_datasource');
if(weatherProviders[currentWeatherProvider] !== undefined ) {
return weatherProviders[currentWeatherProvider];
} else {
return weatherProviders[DEFAULT_WEATHER_PROVIDER];
}
}
function updateWeather(forceUpdate) {
var weatherDisabled = window.localStorage.getItem('disable_weather');
console.log("Get weather function called! DisableWeather is '" + weatherDisabled + "'");
// if weather is not disabled...
if(weatherDisabled !== "yes") {
// in case "disable_weather" is empty or something weird, set it to "no"
// since we already know it's not "yes"
window.localStorage.setItem('disable_weather', 'no');
var weatherLoc = window.localStorage.getItem('weather_loc');
var storedLat = window.localStorage.getItem('weather_loc_lat');
var storedLng = window.localStorage.getItem('weather_loc_lng');
// console.log("Stored lat: " + storedLat + ", stored lng: " + storedLng);
if(weatherLoc) { // do we have a stored location?
// if so, we should check if we have valid LAT and LNG coords
hasLocationCoords = (storedLat != undefined && storedLng != undefined)
&& (storedLat != '' && storedLng != '');
if(hasLocationCoords) { // do we have valid stored coordinates?
// if we have valid coords, use them
var pos = {
coords : {
latitude : storedLat,
longitude : storedLng
}
};
getCurrentWeatherProvider().getWeatherFromCoords(pos);
if(forceUpdate || isForecastNeeded()) {
getCurrentWeatherProvider().getForecastFromCoords(pos);
}
} else {
// otherwise, use the stored string (legacy, or google was blocked from running)
getCurrentWeatherProvider().getWeather(weatherLoc);
if(forceUpdate || isForecastNeeded()) {
getCurrentWeatherProvider().getForecast(weatherLoc);
}
}
} else {
// if we don't have a stored location, get the GPS location
getLocation();
}
}
}
function getLocation() {
navigator.geolocation.getCurrentPosition(
locationSuccess,
locationError,
{timeout: 15000, maximumAge: 60000}
);
}
function locationError(err) {
console.log('location error on the JS side! Failure #' + currentFailures);
//if we fail, try using the cached location
if(currentFailures <= MAX_FAILURES) {
// reset cache time
window.localStorage.setItem('weather_loc_cache_time', (new Date().getTime() / 1000));
// try again
updateWeather();
currentFailures++;
} else {
// until we get too many failures, at which point give up
currentFailures = 0;
}
}
function locationSuccess(pos) {
getCurrentWeatherProvider().getWeatherFromCoords(pos);
if(isForecastNeeded()) {
setTimeout(function() { getCurrentWeatherProvider().getForecastFromCoords(pos); }, 5000);
}
}
function isForecastNeeded() {
var enableForecast = window.localStorage.getItem('enable_forecast');
var lastForecastTime = window.localStorage.getItem('last_forecast_time');
var forecastAge = Date.now() - lastForecastTime;
console.log("Forecast requested! Age is " + forecastAge);
if(enableForecast === 'yes' && forecastAge > FORECAST_MAX_AGE) {
return true;
} else {
return false;
}
}
function sendWeatherToPebble(dictionary) {
// Send to Pebble
Pebble.sendAppMessage(dictionary,
function(e) {
console.log('Weather info sent to Pebble successfully!');
},
function(e) {
// if we fail, wait a couple seconds, then try again
if(currentFailures < failureRetryAmount) {
// call it again somewhere between 3 and 10 seconds
setTimeout(updateWeather, Math.floor(Math.random() * 10000) + 3000);
currentFailures++;
} else {
currentFailures = 0;
}
console.log('Error sending weather info to Pebble! Count: #' + currentFailures);
}
);
}
var xhrRequest = function (url, type, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function () {
callback(this.responseText);
};
xhr.open(type, url);
xhr.send();
};
// the individual weather providers need access to the weather icons
module.exports.icons = WeatherIcons;
// utility functions common to all weather providers
module.exports.xhrRequest = xhrRequest;
module.exports.sendWeatherToPebble = sendWeatherToPebble;
// called by app.js
// updates the weather if needed, respecting all provider settings in localStorage
module.exports.updateWeather = updateWeather;