Skip to content

Instantly share code, notes, and snippets.

@kylemsguy
Created January 11, 2024 06:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kylemsguy/5875f3d37eab25739db835b319c3030c to your computer and use it in GitHub Desktop.
Save kylemsguy/5875f3d37eab25739db835b319c3030c to your computer and use it in GitHub Desktop.
Modern Pebble Watch Face OpenWeather API fix
var weathersleep = false;
var ready = false;
var settings;
var manuallongitude;
var manuallatitude;
var manuallocation;
var fetchtime = 60;
var apikey = "{API_KEY_HERE}";
function iconFromWeatherId(weatherId) {
if (weatherId < 300) {
return 7;
} else if (weatherId < 400) {
return 6;
} else if (weatherId == 511) {
return 8;
} else if (weatherId < 600) {
return 6;
} else if (weatherId < 700) {
return 8;
} else if (weatherId < 800) {
return 10;
} else if (weatherId == 800) {
return 1;
} else if (weatherId == 801) {
return 2;
} else if (weatherId < 900) {
return 5;
} else {
return 0;
}
}
function translateYWeather(code){
if ( code < 5){
return 7;
} else if ( code < 13){
return 6;
} else if ( code < 19){
return 8;
} else if ( code < 23){
return 10;
} else if ( code < 25){
return 2;
} else if ( code < 26){
return 9;
} else if ( code < 27){
return 5;
} else if ( code < 28){
return 4;
} else if ( code < 29){
return 2;
} else if ( code < 30){
return 4;
} else if ( code < 31){
return 2;
} else if ( code < 32){
return 3;
} else if ( code < 33){
return 1;
} else if ( code < 34){
return 3;
} else if ( code < 35){
return 1;
} else if ( code < 36){
return 6;
} else if ( code < 37){
return 1;
} else if ( code < 40){
return 7;
} else if ( code < 41){
return 6;
} else if ( code < 44){
return 8;
} else if ( code < 45){
return 5;
} else if ( code < 46){
return 7;
} else if ( code < 47){
return 8;
} else if ( code < 48){
return 7;
} else {
return 0;
}
}
function fetchWeather(latitude, longitude) {
fetchOWeather(latitude, longitude);
}
function fetchOWeather(latitude, longitude) {
if(!latitude||!longitude||latitude=="undefined"||longitude=="undefined"){
console.log("Pebble JS: Location not set");
Pebble.sendAppMessage({
"icon":11,
"temperature":" SET LOC."});
return;
}
var response;
var req = new XMLHttpRequest();
var imperial = "";
var degrees = "C";
var kelvins = 273.15;
if(settings.substring(10,11)=='1'){
imperial = "&units=imperial";
degrees = "F";
kelvins = 0.0;
}
req.open('GET', "http://api.openweathermap.org/data/2.5/weather?" +
"lat=" + latitude + "&lon=" + longitude + imperial + "&APPID=" + apikey, true);
req.onload = function(e) {
if (req.readyState == 4) {
if(req.status == 200) {
//console.log("Pebble JS: open weather api response: " + req.responseText);
console.log("Pebble JS: Got weather from openweather.");
response = JSON.parse(req.responseText);
var temperature, icon, city, description, icon_n;
temperature = Math.round(response.main.temp - kelvins);
icon = iconFromWeatherId(response.weather[0].id);
icon_n = response.weather[0].icon;
if(icon_n == "01n")icon = 3;
if(icon_n == "02n")icon = 4;
console.log("Pebble JS: temp = " + temperature + ", icon_n = " + icon_n + ", icon = " + icon);
Pebble.sendAppMessage({
"icon":icon,
"temperature":" " + temperature + degrees});
} else {
console.log("Pebble JS: Error processing weather:" + req.readyState + ", HTTP code: " + req.status);
Pebble.sendAppMessage({
"icon":11,
"temperature":" WEB " + req.status});
}
}
}
req.onerror = function(e) {
console.log("Pebble JS: Error downloading weather: " + req.status);
Pebble.sendAppMessage({
"icon":11,
"temperature":" DATA "+req.status}); //0 means timeout
}
req.send(null);
}
function fetchYWeather() {
var response;
var req = new XMLHttpRequest();
var degrees = "C";
if(settings.substring(10,11)=='1'){
degrees = "F";
}
if(!manuallocation||manuallocation==""){
console.log("Pebble JS: Location not set");
Pebble.sendAppMessage({
"icon":11,
"temperature":" SET LOC."});
return;
}
var locationQuery = escape("select item from weather.forecast where woeid in (select woeid from geo.places where text='" + manuallocation + "') and u='" + degrees.toLowerCase() + "'"),
locationUrl = "http://query.yahooapis.com/v1/public/yql?q=" + locationQuery + "&format=json";
req.open('GET', locationUrl, true);
req.onload = function(e) {
if(req.readyState == 4){
if(req.status == 200){
//console.log("Pebble JS: req.responseText=" + req.responseText);
console.log("Pebble JS: Got weather from yahoo.");
response = JSON.parse(req.responseText);
var temperature, code, icon;
try{
temperature = Math.round(response.query.results.channel[0].item.condition.temp);
code = response.query.results.channel[0].item.condition.code;
}catch(err){
try{
temperature = Math.round(response.query.results.channel.item.condition.temp);
code = response.query.results.channel.item.condition.code;
}catch(err){
console.log("Pebble JS: Can't fetch weather for location: " + manuallocation);
Pebble.sendAppMessage({
"icon":11,
"temperature":" 404"});
return;
}
}
icon = translateYWeather(code);
console.log("Pebble JS: temp = " + temperature + ", code = " + code + ", icon = " + icon);
Pebble.sendAppMessage({
"icon":icon,
"temperature":" " + temperature + degrees});
}else{
console.log("Pebble JS: req.status=" + req.status);
console.log("Pebble JS: req.responseText=" + req.responseText);
Pebble.sendAppMessage({
"icon":11,
"temperature":" WEB " + req.status});
}
}else{
console.log("Pebble JS: req.readystate=" + req.readystate);
console.log("Pebble JS: locationUrl=" + locationUrl);
Pebble.sendAppMessage({
"icon":11,
"temperature":" WEB " + req.status});
}
}
req.onerror = function(e) {
console.log("Pebble JS: Error downloading weather: " + req.status);
Pebble.sendAppMessage({
"icon":11,
"temperature":" DATA "+req.status}); //0 means timeout
}
req.send(null);
}
function locationSuccess(pos) {
var coordinates = pos.coords;
console.log('Pebble JS: location success!');
fetchWeather(coordinates.latitude, coordinates.longitude);
}
function locationError(err) {
console.warn('location error (' + err.code + '): ' + err.message);
Pebble.sendAppMessage({
"icon":11,
"temperature":" GPS"
});
}
var locationOptions = { "timeout": 15000, "maximumAge": 60000 };
function getLocationForWeather(){
if(settings.substring(13,14)=='0')return;//weather off
if(settings.substring(14,15)=='1'){
//yahoo
fetchYWeather();
}else if(settings.substring(11,12)=='1'){
//location automatic
console.log("Pebble JS: fetching weather for automatic location...");
window.navigator.geolocation.getCurrentPosition(locationSuccess, locationError, locationOptions);
}else{
//location manual
console.log("Pebble JS: fetching weather for manual location: lat " + manuallatitude + ", lng " + manuallongitude);
fetchWeather(manuallatitude, manuallongitude);
}
}
Pebble.addEventListener("ready",
function(e) {
console.log("Pebble JS reading settings...");
settings = localStorage.getItem("modernsettings");
if (!settings||settings==""||settings.length<19) {
settings = "0100008220010100001";
}
console.log("Pebble JS: settings are: " + settings + ", sending settings.");
manuallongitude = localStorage.getItem("modernlongitude");
manuallatitude = localStorage.getItem("modernlatitude");
manuallocation = localStorage.getItem("modernlocation");
fetchtime = localStorage.getItem("modernfetchtime");
if (!manuallocation||manuallocation=="") {
manuallocation = "";
}
Pebble.sendAppMessage({"settings":translateForPebble()},
function(e) {
console.log("Pebble JS: settings delivered.");
getLocationForWeather();
},
function(e) {
console.log("Peble JS: unable to deliver settings, " +e.error.message);
getLocationForWeather(); //because, why not?
}
);
console.log("Pebble JS: ready and up.");
ready = true;
if (!fetchtime||fetchtime=="undefined"||fetchtime<=0||fetchtime>180) {
//undefined from settings website will crash pebble
fetchtime = 60; //minutes
}
console.log("Pebble JS: Fetch time: " + fetchtime);
window.setInterval(function(){
if(settings.substring(13,14)=='0')return;
if(isActiveHour()){
console.log("Pebble JS: Active hour, refreshing weather");
weathersleep = false;
getLocationForWeather();
}else if(weathersleep==false){
console.log("Pebble JS: Inactive hour, putting watch to sleep");
weathersleep = true;
Pebble.sendAppMessage({
"icon":12,
"temperature":" --"});
}else{
console.log("Pebble JS: Inactive hour, watch sleeping");
}
}, 60000*fetchtime);
//getLocationForWeather();
});
Pebble.addEventListener("appmessage",
function(e) {
console.log("Pebble JS: got message!");
});
Pebble.addEventListener("showConfiguration", function() {
console.log("Pebble JS: showing configuration");
Pebble.openURL(encodeURI("http://zalew.net.pl/pebble/modern311.php?&settings=" + settings + "&longitude=" + manuallongitude + "&latitude=" + manuallatitude + "&location=" + manuallocation + "&fetchtime=" + fetchtime));
});
Pebble.addEventListener("webviewclosed", function(e) {
console.log("Pebble JS: configuration closed");
var configuration = JSON.parse(e.response);
//Pebble.sendAppMessage(configuration);
settings = configuration["settings"];
Pebble.sendAppMessage({"settings":translateForPebble()});
manuallongitude = configuration["longitude"];
manuallatitude = configuration["latitude"];
manuallocation = configuration["location"];
fetchtime = configuration["fetchtime"];
localStorage.setItem("modernsettings", settings);
localStorage.setItem("modernlongitude", manuallongitude);
localStorage.setItem("modernlatitude", manuallatitude);
localStorage.setItem("modernlocation", manuallocation);
localStorage.setItem("modernfetchtime", fetchtime);
console.log("Pebble JS: new configuration is: " + settings);
console.log("Pebble JS: new location is: " + manuallongitude + "," + manuallatitude + ", " + manuallocation);
});
function translateForPebble(){
var result = 0;
if(settings.substring(0,1)=='1'){
result += Math.pow(2,31);
}
if(settings.substring(1,2)=='1'){
result += Math.pow(2,30);
}
var tmp = parseInt(settings.substring(2,4), 10).toString(2);
//console.log("Pebble JS: " + parseInt(settings.substring(2,4), 10) + " tobits: " + tmp);
for(var i = tmp.length-1; i>=0; i--){
if(tmp[i]==1){
result += Math.pow(2,25+(5-tmp.length)+i);
}
}
if(settings.substring(4,5)=='1'){
result += Math.pow(2,24);
}
tmp = parseInt(settings.substring(5,7), 10).toString(2);
//console.log("Pebble JS: " + parseInt(settings.substring(5,7), 10) + " tobits: " + tmp);
for(var i = tmp.length-1; i>=0; i--){
if(tmp[i]==1){
result += Math.pow(2,19+(5-tmp.length)+i);
}
}
tmp = parseInt(settings.substring(7,9), 10).toString(2);
//console.log("Pebble JS: " + parseInt(settings.substring(7,9), 10) + " tobits: " + tmp);
for(var i = tmp.length-1; i>=0; i--){
if(tmp[i]==1){
result += Math.pow(2,14+(5-tmp.length)+i);
}
}
tmp = parseInt(settings.substring(9,10), 10).toString(2);
//console.log("Pebble JS: " + parseInt(settings.substring(9,10), 10) + " tobits: " + tmp);
for(var i = tmp.length-1; i>=0; i--){
if(tmp[i]==1){
result += Math.pow(2,11+(3-tmp.length)+i);
}
}
if(settings.substring(10,11)=='1'){
result += Math.pow(2,10);
}
if(settings.substring(11,12)=='1'){
result += Math.pow(2,9);
}
tmp = parseInt(settings.substring(12,13), 10).toString(2);
//console.log("Pebble JS: " + parseInt(settings.substring(12,13), 10) + " tobits: " + tmp);
for(var i = tmp.length-1; i>=0; i--){
if(tmp[i]==1){
result += Math.pow(2,6+(3-tmp.length)+i);
}
}
if(settings.substring(13,14)=='1'){
result += Math.pow(2,5);
}
if(settings.substring(14,15)=='1'){
result += Math.pow(2,4);
}
if(settings.substring(15,16)=='1'){
result += Math.pow(2,3);
}
if(settings.substring(16,17)=='1'){
result += Math.pow(2,2);
}
if(settings.substring(17,18)=='1'){
result += Math.pow(2,1);
}
if(settings.substring(18,19)=='1'){
result += Math.pow(2,0);
}
console.log("Pebble JS: translated settings(" + settings + "): " + result);
return result;
}
function isActiveHour() {
var currentdate = new Date();
var hour = currentdate.getHours();
var activestart = parseInt(settings.substring(5,7), 10);
var activeend = parseInt(settings.substring(7,9), 10);
if(activestart==activeend){
//console.log(activestart + "=="+ activeend);
//24h active
return true;
}
if(activestart>activeend){
if(hour>=activestart-1||hour<=activeend-1){
//console.log(hour + ">=" + activestart+ "-1||" + hour + "<=" + activeend + "-1");
return true;
}
}else if(hour>=activestart-1&&hour<=activeend-1){
//console.log(hour + ">=" + activestart+ "-1&&" + hour + "<=" + activeend + "-1");
return true;
}
return false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment