Please Read - simpleWeather is currently not working. #221

Open
ahmedhammad opened this Issue Mar 23, 2016 · 100 comments

Projects

None yet
@ahmedhammad

Simple Weather Gives me the following error: THERE WAS A PROBLEM RETRIEVING THE LATEST WEATHER INFORMATION.
Also, I tried the plugin in the website http://simpleweatherjs.com/ and the same result is happen.
Please help me to find a solution for it

@fleeting
Member

Yahoo has made some changes to their API including requiring oAuth. As simpleWeather is pure JavaScript using oAuth isn't an easy option as I don't want people publishing their consumer and secret keys. I'm looking into other API options but honestly not sure when I'll have a replacement.

It has also been up and down a few times today so it's possible it could start working again.

@canomi
canomi commented Mar 24, 2016

I need use it like temporary module, please show me how to fix it with secret keys!

@X-Ryl669

You can still use the rss feed, like this: http://weather.yahooapis.com/forecastrss?w=WOEID_HERE.
Since it's XML, you can parse it as well with jQuery automatically (or use Yahoo to digest their own dog food)

Example code:

var woeid = "26355493";

var $url = "http://query.yahooapis.com/v1/public/yql?callback=?";

$.getJSON($url, {
    q: "select * from xml where url=" +
       "\"http://weather.yahooapis.com/forecastrss?w=" + woeid + "\"",
    format: "json"
  }, function (data) {
    console.log(data.query.results.rss.channel);
  }
);
@X-Ryl669

Just a side node, it's possible to do something better so it'll be futureproof, using OAuth. This requires modifying a bit the code so it first fetch the access token from Yahoo's server, but it'll also imply having to modify simpleWeather instantiation so it includes the Yahoo's developer API as a mandatory parameter. For example about how to do it, see this: https://gist.github.com/hannestyden/563893

I'm not 100% sure Yahoo allow OAuth2 for its api. In all case, it's not very sexy to give the secret keys & token in the JS code from the final user, and Yahoo as some tricks that allows you to avoid this (see this post):
http://derek.io/blog/2010/how-to-secure-oauth-in-javascript/

@fleeting
Member

It's unlikely I'll update simpleWeather to work with OAuth. It is not recommended to have secret keys or tokens in client side code as it's not really secret anymore. The initial option would be to provide a PHP proxy but that complicates simpleWeather more than I would like at the moment.

The XML feed is also limited by woeid only so location names and geolocation wouldn't work which I believe is the majority of the simpleWeather use cases.

I have been looking at other options for the data. One might be to use weather.gov but it will be a complete change in data returned and how location works; http://forecast.weather.gov/MapClick.php?lat=38.4247341&lon=-86.9624086&FcstType=json is an option but uses coordinates vs location name. forecast.io API would also require a proxy due to OAuth but it also only gives 1,000 free API calls a day before charging. I'm not sure when I'll have the time to really work on it or whether the weather.gov data will be the best option.

If anybody has recommendations for those wanting an alternate solution to simpleWeather please share. Thanks!

@fleeting fleeting changed the title from Simple Weather didn't retrieve data to Please Read - simpleWeather is currently not working. Mar 24, 2016
@quartsZzz

fleeting, can use http://openweathermap.org/ ?

@webdevbrian

Broke 13 of my apps. Dammit!

@rwebler
rwebler commented Mar 24, 2016

The XML RSS looks promising. We can still make it work with geolocation by retrieving woeid from geo.places in a separate call.

@githubthom

The XML solution is working in my case. Thanks for that.

@fleeting
Member

I'm glad the XML feed is a workable solution for some. The geo.places call will continue to work for getting the woeid until Yahoo rolls out OAuth to it as well.

@X-Ryl669

@fleeting Please read my second comment and the derek's blog, as it's a method to avoid distributing your Yahoo's API key. Basically you'll store the keys/token on Yahoo's servers directly, only referencing them in your request.

@trex888
trex888 commented Mar 24, 2016

Sorry guys, I've tried the XML feed option but can't quite make it work. Can anyone advise as to where exactly the above XML code should go? This is what I'm currently using in my header.php file of my Wordpress install and up until yesterday it worked perfectly:

` $(function() {

        $.simpleWeather({
             location: '43.623432, -79.386583',
            unit: 'c',
            success: function(weather) {
                html = '<div align="center">' + weather.temp + '&deg;' + weather.units.temp + '<br />' + weather.wind.direction + ' ' + Math.round(weather.wind.speed * 0.540) + 'kts</div>';

                $("#weather2").html(html);
            },
            error: function(error) {
                $("#weather2").html('<p>'+error+'</p>');
            }
        });
    });`

Thanks for any help with this,

T

@aric87
aric87 commented Mar 24, 2016

This broke ~150 sites. I really hate that Yahoo isn't more proactive with warnings.

@githubthom

If somebody is interested, this is how I my code looks like now after change to XML/RSS. I'm not using geo.places, so it was a quick fix.

`function getWeatherData() {

var woeid = '2375129';
var weatherURL = 'http://weather.yahooapis.com/forecastrss?w=' + woeid;
$.ajax({
    url: "http://query.yahooapis.com/v1/public/yql",
    async: true,
    data: {
        q: "select * from xml where url='" + weatherURL + "'",
        format: "json"
    },
    success: function (data) {

        var weather = data.query.results.rss.channel.item;

        // Today
        $('#condition').find('.weather').addClass('icon-' + weather.condition.code);
        $('#conditionText').text(weather.condition.text);
        $('#todayHighText').find('span').html(weather.forecast[0].high + '<i class="degree">&deg;</i>');
        $('#todayLowText').find('span').html(weather.forecast[0].low + '<i class="degree">&deg;</i>');
        $('#todayCurrentText').find('.value').html(weather.condition.temp + '<i class="degree">&deg;</i>');
        $('#todayCurrentText').find('.unit').text('F');

        // Forecast
        $('#day1 .weather').addClass('icon-' + weather.forecast[1].code);
        $('#day1 .weekdayHigh').html(weather.forecast[1].high + '<i class="degree">&deg;</i>');
        $('#day1 .weekdayLow').html(weather.forecast[1].low + '<i class="degree">&deg;</i>');
        $('#day2 .weather').addClass('icon-' + weather.forecast[2].code);
        $('#day2 .weekdayHigh').html(weather.forecast[2].high + '<i class="degree">&deg;</i>');
        $('#day2 .weekdayLow').html(weather.forecast[2].low + '<i class="degree">&deg;</i>');
        $('#day3 .weather').addClass('icon-' + weather.forecast[3].code);
        $('#day3 .weekdayHigh').html(weather.forecast[3].high + '<i class="degree">&deg;</i>');
        $('#day3 .weekdayLow').html(weather.forecast[3].low + '<i class="degree">&deg;</i>');

        $('#weatherContainer').addClass('fadeInDown');

    },
    error: function () {
        $('#weatherContainer').html('No weather data available').addClass('fadeInDown');
    }
});

}`

@webdevbrian

For my needs I'm switching to the weather underground API

@mattferderer

Using the XML method proposed by @X-Ryl669 this is a simplified version of the code I used just in case it helps anyone: http://plnkr.co/edit/dClPDtnToMhHqvKpfCzj?p=preview

var zipCode = 90210;

$.ajax({
    dataType: "json",
    headers:  { "Accept": "application/json; odata=verbose" },
    url: "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20geo.places%20where%20text%3D"+zipCode+"%20limit%201&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys",
    beforeSend: function(xhr){xhr.setRequestHeader('Accept', 'application/json; odata=verbose');},
    success: function(data){
        $.getJSON("https://query.yahooapis.com/v1/public/yql?callback=?", {
            q: "select * from xml where url=\"https://weather.yahooapis.com/forecastrss?w="+data.query.results.place.locality1.woeid+"\"",
            format: "json"
        },function (data) {
          var weather = data.query.results.rss.channel;
          var html = '<div><span class="temperature">'+weather.item.condition.temp+'<span class="degree">&deg;</span><sup>'+weather.units.temperature+'</sup></span><br><span class="wind-chill">Feels like: '+weather.wind.chill+'<span class="degree">&deg;</span></span></div></a>';
          $("#weather").html(html);
        });
    },
});
@alexranc

Was also able to work with XML using code below (thanks X-Ryl669). You will now have a weather object with all the data you need.

My only concern is how often these XML/RSS get updated. Anyone know this?

var woeid = "12772140";
var $url = "http://query.yahooapis.com/v1/public/yql?callback=?";

$.getJSON($url, {
    q: "select * from xml where url=" +
       "\"http://weather.yahooapis.com/forecastrss?w=" + woeid + "\"",
    format: "json"
  }, function (data) {

    var weather = {
      code: data.query.results.rss.channel.item.condition.code, 
      temp: data.query.results.rss.channel.item.condition.temp,
      phrase: data.query.results.rss.channel.item.condition.text
    };

    weather.temp_alt = Math.round( (weather.temp - 32) * 5 / 9 );

  }
);
@rhyshalsey

I have modified Simple Weather to use the new rss and xml solution provided by @X-Ryl669 and @mattferderer. It should work as before, just swap the old script for this one.

EDIT : This no longer works!

(function($) {
  "use strict";

  function getAltTemp(unit, temp) {
    if(unit === 'f') {
      return Math.round((5.0/9.0)*(temp-32.0));
    } else {
      return Math.round((9.0/5.0)*temp+32.0);
    }
  }

  $.extend({
    simpleWeather: function(options){
      options = $.extend({
        location: '',
        woeid: '',
        unit: 'f',
        success: function(weather){},
        error: function(message){}
      }, options);

      if(options.location !== '') {
        $.ajax({
          dataType: "json",
          headers: {"Accept": "application/json; odata=verbose"},
          url: "https://query.yahooapis.com/v1/public/yql?format=json&q=select%20woeid%20from%20geo.places(1)%20where%20text%3D%22" + options.location + "%22&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=",
          beforeSend: function (xhr) {
            xhr.setRequestHeader('Accept', 'application/json; odata=verbose');
          },
          success: function (data) {
            if (data !== null && data.query !== null && data.query.results !== null && data.query.results.place !== null && data.query.results.place.woeid !== null) {
              var woeid = data.query.results.place.woeid;
              getWeatherData(woeid);
            } else {
              options.error({message: "There was an error retrieving the latest weather information. Please try again.", error: null});
            }
          }
        });
      } else if(options.woeid !== '') {
        getWeatherData(options.woeid);
      } else {
        options.error({message: "Could not retrieve weather due to an invalid location."});
        return false;
      }


      function getWeatherData (woeid) {
        var now = new Date();
        $.getJSON('https://query.yahooapis.com/v1/public/yql?callback=?&rnd='+now.getFullYear()+now.getMonth()+now.getDay()+now.getHours(), {
          q: 'select * from xml where url="https://weather.yahooapis.com/forecastrss?w='+woeid+'&u='+options.unit+'"',
          format: "json"
        },function (data) {
          if(data !== null && data.query !== null && data.query.results !== null && data.query.results.rss !== null && data.query.results.rss.channel.description !== 'Yahoo! Weather Error') {
            var result = data.query.results.rss.channel,
                weather = {},
                forecast,
                compass = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW', 'N'],
                image404 = "https://s.yimg.com/os/mit/media/m/weather/images/icons/l/44d-100567.png";

            weather.title = result.item.title;
            weather.temp = result.item.condition.temp;
            weather.code = result.item.condition.code;
            weather.todayCode = result.item.forecast[0].code;
            weather.currently = result.item.condition.text;
            weather.high = result.item.forecast[0].high;
            weather.low = result.item.forecast[0].low;
            weather.text = result.item.forecast[0].text;
            weather.humidity = result.atmosphere.humidity;
            weather.pressure = result.atmosphere.pressure;
            weather.rising = result.atmosphere.rising;
            weather.visibility = result.atmosphere.visibility;
            weather.sunrise = result.astronomy.sunrise;
            weather.sunset = result.astronomy.sunset;
            weather.description = result.item.description;
            weather.city = result.location.city;
            weather.country = result.location.country;
            weather.region = result.location.region;
            weather.updated = result.item.pubDate;
            weather.link = result.item.link;
            weather.units = {temp: result.units.temperature, distance: result.units.distance, pressure: result.units.pressure, speed: result.units.speed};
            weather.wind = {chill: result.wind.chill, direction: compass[Math.round(result.wind.direction / 22.5)], speed: result.wind.speed};

            if(result.item.condition.temp < 80 && result.atmosphere.humidity < 40) {
              weather.heatindex = -42.379+2.04901523*result.item.condition.temp+10.14333127*result.atmosphere.humidity-0.22475541*result.item.condition.temp*result.atmosphere.humidity-6.83783*(Math.pow(10, -3))*(Math.pow(result.item.condition.temp, 2))-5.481717*(Math.pow(10, -2))*(Math.pow(result.atmosphere.humidity, 2))+1.22874*(Math.pow(10, -3))*(Math.pow(result.item.condition.temp, 2))*result.atmosphere.humidity+8.5282*(Math.pow(10, -4))*result.item.condition.temp*(Math.pow(result.atmosphere.humidity, 2))-1.99*(Math.pow(10, -6))*(Math.pow(result.item.condition.temp, 2))*(Math.pow(result.atmosphere.humidity,2));
            } else {
              weather.heatindex = result.item.condition.temp;
            }

            if(result.item.condition.code == "3200") {
              weather.thumbnail = image404;
              weather.image = image404;
            } else {
              weather.thumbnail = "https://s.yimg.com/zz/combo?a/i/us/nws/weather/gr/"+result.item.condition.code+"ds.png";
              weather.image = "https://s.yimg.com/zz/combo?a/i/us/nws/weather/gr/"+result.item.condition.code+"d.png";
            }

            weather.alt = {temp: getAltTemp(options.unit, result.item.condition.temp), high: getAltTemp(options.unit, result.item.forecast[0].high), low: getAltTemp(options.unit, result.item.forecast[0].low)};
            if(options.unit === 'f') {
              weather.alt.unit = 'c';
            } else {
              weather.alt.unit = 'f';
            }

            weather.forecast = [];
            for(var i=0;i<result.item.forecast.length;i++) {
              forecast = result.item.forecast[i];
              forecast.alt = {high: getAltTemp(options.unit, result.item.forecast[i].high), low: getAltTemp(options.unit, result.item.forecast[i].low)};

              if(result.item.forecast[i].code == "3200") {
                forecast.thumbnail = image404;
                forecast.image = image404;
              } else {
                forecast.thumbnail = "https://s.yimg.com/zz/combo?a/i/us/nws/weather/gr/"+result.item.forecast[i].code+"ds.png";
                forecast.image = "https://s.yimg.com/zz/combo?a/i/us/nws/weather/gr/"+result.item.forecast[i].code+"d.png";
              }

              weather.forecast.push(forecast);
            }

            options.success(weather);
          } else {
            options.error({message: "There was an error retrieving the latest weather information. Please try again.", error: data.query.results.rss.channel.item.title});
          }
        });
      }
      return this;
    }
  });
})(jQuery);


@kgiszewski

@rhyshalsey +1, worked immediately for me

@kgiszewski

One note, it appears to be reporting the wrong weather status. It's 54 degrees and raining here, but shows snowing. Could be an issue with the icons I'm using.

screen shot 2016-03-24 at 1 36 53 pm

@equatebrand

@rhyshalsey, thank you!

@whistletutor

@rhyshalsey Thanks from me as well, I was neck deep in other options for my applications. Glad you got this figured out!

@nfishertbc

@rhyshalsey thanks!! This worked for me as well. I just made the code change and its now working.

@X-Ryl669

@rhyshalsey, you should move the line var now = new Date(); into the function just below, else it's undefined in the function itself where you're using it.

@X-Ryl669

Just a comment, guys: This is only a temporary workaround. As soon as more people will use this, Yahoo is going to protect with oAuth either their RSS feed, either their XML to JSON converter.
I still think we need to figure out how to use their weather api with oAuth in pure JS without having to give our reader our own dev API tokens.

@rhyshalsey

Good catch @X-Ryl669, updated the code. I also agree that this should not be considered a long term solution.

I have been trying to get a consumer key for the YDN all day, but I'm being been hit with a "An internal error occurred" when trying to access the YDN apps section. Anyone else getting this error?

@kgiszewski

@X-Ryl669 Send me a link and I'll try.

@mattferderer

I've been getting a "Server Connection Closed" error all day when trying to go to https://developer.yahoo.com/apps/

Trying to create an app gives me some server connection error on submit.

@kgiszewski

Same error here.

@X-Ryl669

Same for me. I guess their weather API change is currently overloading their "processing" buffers.

@mattferderer

With talks of Yahoo trying to sell the majority of their internet business & staff, plus large shareholders trying to remove their entire board, the best path forward may be to find a different weather api. Unfortunately I can't find any that are free, utilize zip codes or city/state/country, and have a high request per hour/day limit.

@webdevbrian

@mattferderer I'm probably going to fork this and hook this up with weatherunderground's API. 500 calls a day @ 10 a minute max suits my needs. edited, I said "an hour" previously, not by minute.

@mattferderer

@webdevbrian Are you going to cache the response from Weather Underground or do you get less than 10 visitors per hour on your site or am I mistaken in how I read that?

@X-Ryl669

@webdevbrian Where I live, there's only 24 hours a day. So the best I could expect with only 10 call per hour would be 240 calls per day. Did I miss something ?

@webdevbrian

@X-Ryl669 Whoops, meant to say minute. Here are their limits for their free account. Feel free to dig into it if it'll work for you (and their other packages if you need more and what you'll be paying) See here

screen shot 2016-03-24 at 3 41 00 pm

Just started my fork, I'm out on vacation next week but I need this working again so probably expect it to be done in a few weeks. I'll ping @fleeting to see what he wants to do? Holler at me buddy. Also, I might be in Boston soon, we should meet up for some 🍻 .

@mattferderer I'll probably set a rate limit. I'll need more than 500 a day for my needs, but at least people will be able to throttle it so it doesn't get canned. I'll have to think it over a few margaritas on the beach next week :)

⛵️ 🌅 ☀️ 😎

@kgiszewski

I think the difference is the application. I only use it for a digital signage (updates every 5 mins) whereas someone else may use it on a website and may load it 1000's of times a day.

@webdevbrian

@kgiszewski Correct -- I'll probably just rate limit it which people can define whatever they'd like in the options depending how crazy they want to get, haven't thought to that point yet. Currently mapping the response from wunderground to what @fleeting has, there are a bunch of things to change.

@dmcrock
dmcrock commented Mar 24, 2016

@rhyshalsey Looks like we are starting to get an error on your work around. Was working great until 2 minutes ago. "Unhandled exception at line 53, column 21, 0x800a138f - JavaScript runtime error: Unable to get property 'channel' of undefined or null reference" anyone else seeing this?
Doug

@romssilva

@dmcrock, same here

@mattferderer

Looks like they're requiring OAuth on the XML feed now. Glad to see Yahoo took the time to implement that fix but still haven't fixed their Developer App section so you can login & create an app to connect through OAuth.

@odunsair

So what? When hundreds of people enter my website, I can not show the weather? This is so absurd. Is there another weather app I can use?

@lostcook

Long time SimpleWeather user, first time commentor. Not sure if others are experiencing this, but it seems like it is only displaying Fahrenheit. Sorry to be a pain, but in Canada we use Celsius.

Otherwise, thanks for all the updating you have been doing to this plugin.

@grandoompa

@dmcrock, same here. The workaround provided by @rhyshalsey (by the way, thanks for trying) worked for a few hours until around 5pm'ish EST today (3/24/16).

I am now getting the following console error:
Uncaught TypeError: Cannot read property 'channel' of undefined

@mattferderer

Yahoo claims the site to create an app works now. I can't verify though. 

@whistletutor

Yes, it is working now - but their example code doesn't reference the API keys so I'm not sure where we're supposed to pass them.

@biapar
biapar commented Mar 25, 2016

@rhyshalsey don't work

@chimit
chimit commented Mar 25, 2016

I think openweathermap.org is only one replacement for the Yahoo API, because it has the best limits (Calls per minute 60). I don't see any other way to make this plugin work again, because as I know there are no public weather APIs without limitations. Even in this way we have to expose keys.

@X-Ryl669

Ok, for those interested, I've started my port with weatherunderground and it's working for my need.
You'll need to register an api key from the Weatherunderground website, and add a apiKey member to the options of simpleWeather. The woeid does not exist in weather underground, but I've used the "id" they are using. Either you use the location member of options to specify the location (but it'll make 2 request to WU, one to figure out the id, and the second for the forecast), either you capture the output of the former request on the console, and use that as woeid. If location is set to auto then it takes the IP address of the client for the weather query.

Not everything is ported (feel free to adjust to your need), but for those using metrics system, it works quite well.

(function($) {
  "use strict";

  function getAltTemp(unit, temp) {
    if(unit === 'f') {
      return Math.round((5.0/9.0)*(temp-32.0));
    } else {
      return Math.round((9.0/5.0)*temp+32.0);
    }
  }

  $.extend({
    simpleWeather: function(options){
      options = $.extend({
        location: '',
        woeid: '',
        unit: 'f',
        apiKey: '',
        success: function(weather){},
        error: function(message){}
      }, options);

      if(options.location !== '') {
        if (options.location == 'auto')
        {
            $.ajax({
              dataType: "json",
              headers: {"Accept": "application/json; odata=verbose"},
              url: "http://api.wunderground.com/api/"+options.apiKey+"/geolookup/q/autoip.json",
              beforeSend: function (xhr) {
                xhr.setRequestHeader('Accept', 'application/json; odata=verbose');
              },
              success: function (data) {
                 if (data !== null && data.location !== null && data.location.l !== null) {
                    var query = data.location.l;
                    console.log("Fetching weather forecast for :" + query);
                    getWeatherData(query);
                 } else {
                    options.error({message: "There was an error retrieving the latest weather information. Please try again.", error: null});
                 }
              }
            });
        }
        else
        {
            $.ajax({
              dataType: "json",
              headers: {"Accept": "application/json; odata=verbose"},
              url: "http://api.wunderground.com/api/"+options.apiKey+"/geolookup/q/" + options.location + ".json",
              beforeSend: function (xhr) {
                xhr.setRequestHeader('Accept', 'application/json; odata=verbose');
              },
              success: function (data) {
                 if (data !== null && data.location !== null && data.location.l !== null) {
                    var query = data.location.l;
                    console.log("Fetching weather forecast for :" + query);
                    getWeatherData(query);
                 } else {
                    options.error({message: "There was an error retrieving the latest weather information. Please try again.", error: null});
                 }
              }
            });
        }
      } else if(options.woeid !== '') {
        getWeatherData(options.woeid);
      } else {
        options.error({message: "Could not retrieve weather due to an invalid location."});
        return false;
      }

      function iconToCode(icon) {
         var night = /^nt_/.test(icon);
         var i = icon.replace("nt_", "");
         switch(i) {
            case "chanceflurries": // Chance of Flurries
                return 13;
            case "chancerain": // Chance of Rain
                return 40;
            case "chancesleet": // Chance of Freezing Rain
                return 10;
            case "chancesnow": // Chance of Snow
                return 42;
            case "chancetstorms": // Chance of Thunderstorms
                return 38;
            case "clear": // Clear
                 return night ? 31 : 32;
            case "flurries": // Flurries
                 return 13;
            case "fog": // Fog
                 return 20;
            case "hazy": // Haze
                 return 21;
            case "mostlycloudy": // Mostly Cloudy
                 return night ? 27 : 28;
            case "mostlysunny": // Mostly Sunny
                 return night ? 33 : 34;
            case "partlycloudy": // Partly Cloudy
                 return night ? 29 : 30;
            case "partlysunny": // Partly Sunny
                 return night ? 33 : 34;
            case "rain": // Rain
                 return 11;
            case "sleet": // Sleet
                 return 18;
            case "snow": // Snow
                 return 16;
            case "sunny": // Sunny
                 return 32;
            case "tstorms": // Thunderstorms
                 return 4;
            case "cloudy": // Overcast
                 return 26;
            default:
            case "unknown": // Unknown
                 return 3200;
         }
      }

      function padToTwo(number) {
         if (number<=99) { number = ("0"+number).slice(-2); }
         return number;
      }

      function getWeatherData (woeid) {
        $.getJSON('http://api.wunderground.com/api/' + options.apiKey + '/conditions/astronomy/forecast10day' + woeid + '.json', { format: 'json' }, function(data) {
          if(data !== null && data.current_observation !== null && data.sun_phase !== null && data.forecast !== null && data.forecast.simpleforecast !== null && data.forecast.simpleforecast.forecastday !== null) {
            var current = data.current_observation,
                weather = {},
                forecast,
                compass = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW', 'N'],
                image404 = "https://s.yimg.com/os/mit/media/m/weather/images/icons/l/44d-100567.png";
                weather.title = 'Conditions for ' + current.display_location.city;
                weather.city = current.display_location.city;
                weather.temp = options.unit == 'f' ? current.temp_f : current.temp_c;
                weather.humidity = current.relative_humidity.replace("%", "");
                weather.pressure = current.pressure_mb;
                weather.currently = current.weather;
                weather.code = iconToCode(current.icon);

                weather.sunrise = data.sun_phase.sunrise.hour + ':' + padToTwo(data.sun_phase.sunrise.minute);
                weather.sunset = data.sun_phase.sunset.hour + ':' + padToTwo(data.sun_phase.sunset.minute);

           var result = data.forecast.simpleforecast.forecastday;
                weather.forecast = [];

                     for(var i=0;i<Math.min(result.length, 5);i++) {
                        var forecast = {};
                        forecast.day = result[i].date.weekday;
                        forecast.low = result[i].low[options.unit == 'c' ? "celsius" : "fahrenheit"];
                        forecast.high = result[i].high[options.unit == 'c' ? "celsius" : "fahrenheit"];
                        forecast.code = iconToCode(result[i].icon);
                        forecast.text = result[i].conditions;
                        weather.forecast.push(forecast);
                     }

                     weather.todayCode = weather.code;
                     weather.high = weather.forecast[0].high;
                     weather.low = weather.forecast[0].low;
                     weather.text = weather.forecast[0].text;

/* Everything below should be adapted to WU format, but I'm not interested into them.
   Refer to https://www.wunderground.com/weather/api/d/docs?d=data/forecast10day for documentation
            weather.rising = result.atmosphere.rising;
            weather.visibility = result.atmosphere.visibility;
            weather.description = result.item.description;
            weather.country = result.location.country;
            weather.region = result.location.region;
            weather.updated = result.item.pubDate;
            weather.link = result.item.link;
            weather.units = {temp: result.units.temperature, distance: result.units.distance, pressure: result.units.pressure, speed: result.units.speed};
            weather.wind = {chill: result.wind.chill, direction: compass[Math.round(result.wind.direction / 22.5)], speed: result.wind.speed};

            if(result.item.condition.temp < 80 && result.atmosphere.humidity < 40) {
              weather.heatindex = -42.379+2.04901523*result.item.condition.temp+10.14333127*result.atmosphere.humidity-0.22475541*result.item.condition.temp*result.atmosphere.humidity-6.83783*(Math.pow(10, -3))*(Math.pow(result.item.condition.temp, 2))-5.481717*(Math.pow(10, -2))*(Math.pow(result.atmosphere.humidity, 2))+1.22874*(Math.pow(10, -3))*(Math.pow(result.item.condition.temp, 2))*result.atmosphere.humidity+8.5282*(Math.pow(10, -4))*result.item.condition.temp*(Math.pow(result.atmosphere.humidity, 2))-1.99*(Math.pow(10, -6))*(Math.pow(result.item.condition.temp, 2))*(Math.pow(result.atmosphere.humidity,2));
            } else {
              weather.heatindex = result.item.condition.temp;
            }

            if(result.item.condition.code == "3200") {
              weather.thumbnail = image404;
              weather.image = image404;
            } else {
              weather.thumbnail = "https://s.yimg.com/zz/combo?a/i/us/nws/weather/gr/"+result.item.condition.code+"ds.png";
              weather.image = "https://s.yimg.com/zz/combo?a/i/us/nws/weather/gr/"+result.item.condition.code+"d.png";
            }

            weather.alt = {temp: getAltTemp(options.unit, result.item.condition.temp), high: getAltTemp(options.unit, result.item.forecast[0].high), low: getAltTemp(options.unit, result.item.forecast[0].low)};
            if(options.unit === 'f') {
              weather.alt.unit = 'c';
            } else {
              weather.alt.unit = 'f';
            }
*/

                       options.success(weather);
            } else {
               options.error({message: "There was an error retrieving the latest weather information. Please try again.", error: data.query.results.rss.channel.item.title});
            }
        });
      }
      return this;
    }
  });
})(jQuery);
@larsinsd

X-Ryl669 Thank you for posting this! I went to WeatherUnderground and got an API key, but I'm getting this in the console:

XMLHttpRequest cannot load http://api.wunderground.com/api//geolookup/q/Solana%20Beach,%20CA,%20United%20States.json. The 'Access-Control-Allow-Origin' header has a value 'http://www.wunderground.com' that is not equal to the supplied origin. Origin 'http://mydomain.com' is therefore not allowed access.

Am I missing something obvious here?

@larsinsd

Ah - never mind - I forgot to camel case apiKey. It works.

@takemuraori

@larsinsd can you help me understand what is camel case? i am getting the same error you used to :(

@X-Ryl669

It's apiKey not apikey or APIKey.

Kind regards, CR

Le 27 mars 2016 9:11 AM, takemuraori notifications@github.com a écrit :

@larsinsd can you help me understand what is camel case? i am getting the same error you used to :(


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

@takemuraori

@X-Ryl669 but in your example it is already apiKey.... and it still gives this errot to me, it also gives me Uncaught TypeError: Cannot read property 'l' of undefined in line 54, and if i remove all instances of that it starts to give me Access-Control-Allow-Origin :(

@larsinsd

It's probably because you aren't properly formatting the location. Look at Weather Underground's API documentation. In the US, it's State/City and internationally it's Country/City.

@takemuraori

I feel stupid but after adding response.countryCode from my ip location API to the Location, the original plugin works perfectly for me... where I used to have say 'Singapore' it is now 'Singapore, SG' and it all works.

@kgiszewski

@X-Ryl669 Thanks for the code. I'm integrating it now and discovering some of the things missing from Weather Underground. This isn't an implication of your code or WU, just pointing out some bumps:

  • Units (Celsius /Fahrenheit) not given as a parameter
  • Temperature is a decimaled number, just have to parse it
  • Wind direction/speed not provided

screen shot 2016-03-28 at 8 10 42 am

Also, be aware that WU requires an attribution to be displayed regardless of use: https://www.wunderground.com/weather/api/d/terms.html

Not calling this out as a show-stopper, but be aware.

Thanks again for the code.

@kgiszewski

The WU API does return more information, but it does need to be mapped as @X-Ryl669 pointed out.

I'm also trying to debug why IE11 is not playing nice with this code as well.

screen shot 2016-03-28 at 8 49 28 am

@X-Ryl669

WU provides both units in their answer, so selection is done client-side. I haven't extracted wind speed and direction but it's it's there too. You are right, you need to attribute them.

@kgiszewski

Is anyone else having CORS issues with IE 11 and the Weather Underground solution? I'm half tempted to just pull it with server side code. Just curious.

@X-Ryl669

Not tested, but did you try with .jsonp + &callback=test at the url of the URL instead of .json to avoid CORS ?

@githubthom

The Javascript example from wunderground API docs works fine for me (with jsonp):

$.ajax({ url: 'http://api.wunderground.com/api/---yourapikey---/conditions/forecast/q/'+state+'/'+city+'.json', dataType: "jsonp", success: function (data) {}})

@soRailicious

Any news?

@odunsair
odunsair commented Apr 1, 2016

My yahoo api is working now. But sometimes show this error:
THERE WAS A PROBLEM RETRIEVING THE LATEST WEATHER INFORMATION.

I use old simpleweather

@soRailicious

Same on my sites... +1

@takemuraori

@odunsair @soRailicious it works absolutely fine change the way you format location, instead of just a city try city + country. that is all it took for me.

@soRailicious

@takemuraori location: 'Bremen, DE', thats what i've wrote in my request

@takemuraori

@soRailicious in my webapp your location gives me: "Bremen, DE
Forecast: sun chilly day".
In here http://codepen.io/fleeting/pen/xwpar it gives 45F for Bremen, DE. it all works.

@infosion
infosion commented Apr 1, 2016

In here http://codepen.io/fleeting/pen/xwpar it gives 45F for Bremen, DE. it all works.
Unfortunately it does not work: "There was a problem retrieving the latest weather information."

@soRailicious

@takemuraori and @infosion yes... but from time to time it is 50% chance to get the weather ... in maybe every 2nd-3rd click / reload it says "THERE WAS A PROBLEM RETRIEVING THE LATEST WEATHER INFORMATION."

@infosion
infosion commented Apr 1, 2016

@soRailicious - I have realized that and my clients, too ;-)

@takemuraori

@soRailicious - that is strange coz it never gives me an error. could it be that you are using it for a mobile app or something? because my use is in a website and it works very well.

@soRailicious

@infosion sorry for that :D
@takemuraori yes sometimes it works for a few hours perfectly...

@Mik75
Mik75 commented Apr 1, 2016

when will be released a version that works please? soon? i use the plugin on 10 website and i am not able to fix it...or provide more details/instructionts to get it works. i don't understand the fixes above. many thanks

@fleeting
Member
fleeting commented Apr 1, 2016

@Mik75 I'm honestly not sure when a new version will be released. The fixes above are mostly temporary so until I can really get some time to look into other options that don't have API keys or just adding a PHP proxy, I'm not sure. I hope soon but it could be a few weeks.

@uliworm
uliworm commented Apr 3, 2016

i've seen another question on stackoverflow which was using:
https://github.com/isaacs/authentipede as a answer

see here: http://stackoverflow.com/questions/36186538/making-yahoo-weather-api-request-with-oauth-1/36207117#36207117

Maybe this is an option?

@fleeting
Member
fleeting commented Apr 3, 2016

@uliworm That project hasn't been active for seven years and the main site isn't up anymore. However, that uses PHP to handle the consumer and secret key which using a PHP proxy is an option for those who are able to use PHP and want to go that route.

@uliworm
uliworm commented Apr 4, 2016

@fleeting I see, and i would like to stick to this plugin.
Just tried it with an php-call including key and secret and it took longer than your plugin (and because i didnt ajaxed the page stopped loading until the api came back) and the main problem is, that i also got null-values as response very often!!

But why not offering your plugin with key and secet in the meantime as input-parameters? I just created a new app on their site and wouldn't mind putting the key in my js-source because you insert a callback-domain when creating and it says:

Please specify the domain to which your application will be returning after successfully authenticating. Yahoo OAuth flow will redirect users to a URL only on this domain (or its sub-domain) after they authorize access to their private data.

So do i understand this correct, that key, secret and domain must fit? If so, then noone else can use the api-key, right?

@Freelancealot

Hi,
Oh, I love this plugin. I'm using it in a Wordpress site. Is there anyway I can use the following with SimpleWeather?

`<?php
include_once("yosdk/lib/Yahoo.inc");

define("API_KEY","your-api-key-here");
define("SHARED_SECRET","your-secret-here");
YahooLogger::setDebug(true);

$twoleg = new YahooApplication (API_KEY, SHARED_SECRET);
$query = 'select * from weather.forecast where woeid in (select woeid from geo.places(1) where text="84054") and u="f"';
$results = $twoleg->query ($query);
print_r ($results);`

(from: http://stackoverflow.com/questions/36186538/making-yahoo-weather-api-request-with-oauth-1/36207117#36207117)

I am only a PHP and JS fiddler, so I have no idea how to marry the above code to SimpleWeather.js

I've literally just built the site, almost ready for launch when Yahoo made it's changes. I'm currently using 'location: 'Point Salines, GND','

Any help appreciated.

Cheers,
Tracy

@whistletutor

I tried that myself, and despite creating a valid $twoleg object, I get no results with the query.

@jayharland

I'm currently migrating to a different weather API. While SimpleWeather has been great, these current changes by Yahoo render it basically useless; no offense. There should be a notice on the plugin homepage or something - just a suggestion. Thanks for the work on this either way.

@aconanlai

this API seems promising.
https://developer.forecast.io/

@Freelancealot

Ah yes, I've looked at that before. But am not expert enough to 'plug' that
into SimpleWeather. I also think they have some type of login you have to
do.

@anketwokings

Edit: The below was indeed working for a short while, fallen back to error status again. Looks like it's indeed flakey somewhere else and sometimes 'just' works.
Notice the demosite is not working as well, at the moment. :/

Working with v3.1.0.


Working with simpleweather as well, kept getting the error status.
What solved it for me: I used the woeid, AND made sure it was the first attribute on the js. So I just deleted everything that was above ( zipcode / location etc).

$.simpleWeather({ woeid: '733252', location: '', unit: 'c', success: function(weather) {
etc etc..

Hope this helps!!

@X-Ryl669
X-Ryl669 commented Apr 6, 2016

Maybe it's time to close this issue, and report on the main page that simpleWeather is no more working with new Yahoo API change, else we'll get tons of report like the one above where in the exceptional rare time where Yahoo does not require OAuth, it seems to work. Currently, they don't seem to require OAuth anymore (maybe many people started to flee from their services after the change), but in their term and conditions, it's still specified they require it.

So, there is only 2 possible scenario for the close future:

  1. They decide to restore access without OAuth and the plugin will work as it was working before the storm.
  2. They keep requiring OAuth for getting the forecast and then, either you'll have to use a server side proxy to hide your key (PHP, NodeJS, whatever) and this plugin will not work either (but it won't be hard to get the same information through your server), either you switch the plugin to any other that's not using Yahoo data feed (if you want minimal changes to your code, you can use the example one I've written above to use WeatherUnderground data feed).

In all cases, to my knowledge, there is no other weather feed provider that does not require some sort of authentication, which, in turns, prevent any javascript only solution to fetch the feed.

@infosion
infosion commented Apr 6, 2016

I would also recommend to inform the users on the project home page due to the particular problems with yahoo.

@kevandju
kevandju commented Apr 6, 2016

Just want to say thanks to @X-Ryl669 for modifying the script to work with Wunderground. Works perfectly.

@Freelancealot

@X-Ryl669 Thanks for posting the WU code. I'm trying to implement it but without much success. I'm not getting any errors but neither is any weather displaying.

I copied your code to a new document named jquery.weather.js and call that at the bottom of the WP page INSTEAD of jquery.simpleWeather.min.js and then in a separate js file I have:

`jQuery(document).ready(function() {
jQuery.simpleWeather({
apiKey: 'myapikeyhere',
location: 'Grenada, Point Salines',
woeid: '',
unit: 'c',
success: function(weather) {
html = '

'+weather.temp+'°'+weather.units.temp+''+weather.currently+'

';
html += '
  • Wind Speed: '+weather.wind.speed+' '+weather.units.speed+' '+weather.wind.direction+'
  • ';
    html += '
  • Humidity: '+weather.humidity+' %
  • ';
    html += '
  • Pressure: '+weather.pressure+' mb
  • ';
    html += '
  • Visibility: '+weather.visibility+' '+weather.units.distance+'
  • ';
    html += '
  • '+weather.sunrise+' '+weather.sunset+'
';
html += '

Tomorrow: '+weather.forecast[1].text+'

';
html += '

Weather from '+weather.city+'

';

  jQuery("#weather").html(html);
},
 error: function(error) {
  jQuery("#weather").html('<p>'+error+'</p>');
}

});
});`
What am I doing wrong?

I'm trying to rebuild this which at the moment is SimpleWeather: www.gotoalmanac.com

Thanks very much for your help.

Tracy

@X-Ryl669
X-Ryl669 commented Apr 7, 2016

The location format is different from Yahoo and Wunderground. If I remember correctly, it's "/state/city" (please refer to WUnderground documentation). Anyway, since you're doing fixed location, you can run the request once on WUnderground developer console to find out the /q/whatever code for this location and put that information in the woeid field of your options.

For example, if I want the weather from San Francisco, CA, I would have to put "CA/San_Francisco" in the location member for the option, which would lead to a first request emitted:

http://api.wunderground.com/api/yourKeyHere/conditions/q/CA/San_Francisco.json

Notice that if you have your javascript console opened, it'll print you something about the woeid to use (which would be something like /q/zmw:94101.1.99999)

Put that in the woeid and leave the location empty, it'll avoid a geolookup request each time you load the page.

@alotufo
alotufo commented Apr 7, 2016

FWIW, this plugin seems to be working reliably again as of yesterday, so maybe Yahoo changed something back. I'd like to get more feedback from others if this is true.

@infosion
infosion commented Apr 7, 2016

It seems to be working! Hopefully reliably ;-)

@WarGravy
WarGravy commented Apr 8, 2016

This hasn't been working for me since March. I am using ZipCodes to get weather data and I get the error message: "could not retrieve weather due to an invalid location" - is this the part of the same issue people have been running into, or is this something new?

EDIT: It looks like the woeid lookup is the only piece that is causing issues. Using the woeid directly seems to work just fine.

Code:

//removed my code because the example is also not working for me:
$.simpleWeather({
    zipcode: '76309',
    unit: 'f',
    success: function(weather) {
        html = '<h2>'+weather.city+', '+weather.region+'</h2>';
        html += '<img style="float:left;" width="125px" src="images/weather/'+weather.code+'.png">';
        html += '<p>'+weather.temp+'&deg; '+weather.units.temp+'<br /><span>'+weather.currently+'</span></p>';
        html += '<a href="'+weather.link+'">View Forecast &raquo;</a>';

        $("#weather").html(html);
    },
    error: function(error) {
        $("#weather").html("<p>"+error+"</p>");
    }
});
@biapar
biapar commented Apr 9, 2016

Where Do I found woeid?

@XavierFlo

On yahoo weather website.
It's the number at the end of Web address.
When you look for weather of your city of course.

@danielpradilla

In case anyone needs it, I made an ugly hack to plug the forecast.io API into simpleWeather.

https://github.com/danielpradilla/jquery-simpleWeather-forecastio

@interglobalmedia
interglobalmedia commented Jul 16, 2016 edited

The API is working for me, however I can't figure out how to use both F and C. I want to be able to use a button to toggle between the two. Anyone know how to implement both Fahrenheit and Celsius in Simple Weather? The developer says you can do it, but I haven't yet been successful. This is the link to my repo: (https://github.com/interglobalmedia/simpleweather) Thanks!

@geoaetos
geoaetos commented Aug 23, 2016 edited

please how select from choose city from dropdown??? this code is work

$(document).on('click', 'a.weather-link', function (e) {
var city = $(this).data('city');
loadWeather(city);
e.preventDefault();
});
this code how work from this list and not click link
select id="list"
option value="london"londonoption
option value="tokyo"tokyo/option
option value="paris"paris/option
/select

@dennym
dennym commented Jan 10, 2017

Whats the status about this topic?

@HybridSolutions

It's working again but sometimes on the first call, it will fail. After a refresh, it will loadthe data, so what do I have to change to retry the call at least one more time if it fails? Also, is the data being stored on local cache? If no, how could this be done with SimpleWeather?

@fleeting
Member

With the state of Yahoo as a company, it's unlikely their weather API will ever become stable again. Most stable and feature rich weather APIs like https://openweathermap.org/api and https://darksky.net/dev/ require API keys and have pricing options which is outside the scope of this project for now. I'll update the readme and website to note how unstable the Yahoo API is. If I get some time moving forward I'll look at the other API options.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment