Kodi Community Forum

Full Version: Yahoo! Weather
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 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
I'm using a windows and android kodis
Location of the Yahoo! Weather Addon default.py file per OS. Adapted from the Kodi Wiki.

Android: /sdcard/Android/data/org.xbmc.kodi/files/.kodi/addons/weather.yahoo/
iOS: /private/var/mobile/Library/Preferences/Kodi/addons/weather.yahoo/
Linux: ~/.kodi/addons/weather.yahoo/
Mac: /Users/<your_user_name>/Library/Application Support/Kodi/addons/weather.yahoo/
OpenELEC: /storage/.kodi/addons/weather.yahoo/
Windows: Type %APPDATA%\kodi\addons\weather.yahoo\ at the Start menu
(2016-03-28, 00:23)Sittich Wrote: [ -> ]Well, so happy I'm not with two solutions. I have now made more than two hours test run. The result is as follows:
...
How can that be, when both solutions are from the one and the same data source, namely yahoo HuhHuhHuh
...
Why use yahoo even different data sources for the same place?!?! And what data source is correct and also current? I thought yahoo is yahoo !!!!!
...

This is unfortunately a problem with Yahoo! and not with the addon. It is pretty evident that lag in the YQL solution means that it is probably doing a database query while the RSS feed is not. This means that they are probably unsynchronized data sources. I am not too concerned about a few hours difference with my usage pattern as I am normally checking the night before what the general forecast is for the next day/next few days. This doesn't help us, or excuse Yahoo!

If you search the web there are other similar issues with the Yahoo weather APIs that have caused users problems. Actually, when I first changed my default.py to use the new URL the weather started from 3 days in the future and I needed to refresh.
The test run continues...

It looks like yahoo is in both cases not directly connected meteorological institutes. It buys apparently weather informations from weather.com
But why weather.com makes different weather forecasts, even after many hours (#153,#165), I do not know.

Who doesn't know what i mean, he can read my Post #171. And who still does not know what I mean, which can run Kodi on two device simultaneously (Rasperry Pi, PC, Android, whatever).
The one Kodi with the solution of default.py Post #153, and the other Kodi with the solution of Post #165. You will see that different weather forecasts for the one and the same place (woeid) be made.

Briefly, yahoo-weather is not the same yahoo-weather. There are differences depending on what you include API / Data Source
And who do we believe now? Let's do this again our weatherfrog from ?!

Why do I write all this? I want to draw attention to how you want to sell us again for stupid!!! One Yahoo, one weather forecast. hahahaha (ironic)
I hope the maintainer of this addon can be found out for next reposity upgrade a data source with more weighting.



(Due to mechanised translation grammar may be faulty, sorry)
(2016-03-28, 12:07)Sittich Wrote: [ -> ]I hope the maintainer of this addon can be found out for next reposity upgrade a data source with more weighting.

You are free to switch to the Weather Underground add-on at any time, feel free to not use the Yahoo! Weather add-on.
diedrich, I think you're right. I should be completely switsh. Have now all devices being updated on the solution #165 ..... I'm just so fun updates from frequent .... and what happens? Occasionally I get 2 different weather updates. Yahoo can not even keep the database moment during the query separately. Incredible!!!!!!!!
Probably I have get weather information from another "woeid"

The left image corresponds to the current weather situation. Sometimes (very rarely) I get also as the right picture
watch gallery





(Due to mechanised translation grammar may be faulty, sorry)
1000% Work
Code:
import os, sys, socket, urllib2
from xml.dom import minidom
import xbmc, xbmcgui, xbmcaddon
if sys.version_info < (2, 7):
    import simplejson
else:
    import json as simplejson

__addon__      = xbmcaddon.Addon()
__addonname__  = __addon__.getAddonInfo('name')
__addonid__    = __addon__.getAddonInfo('id')
__version__    = __addon__.getAddonInfo('version')
__cwd__        = __addon__.getAddonInfo('path').decode("utf-8")
__resource__   = xbmc.translatePath( os.path.join( __cwd__, 'resources', 'lib' ).encode("utf-8") ).decode("utf-8")

sys.path.append(__resource__)

from utilities import *

LOC_URL          = 'http://query.yahooapis.com/v1/public/yql?q=%s&format=json'
LOC_QUERY        = 'select * from geo.places where text="%s"'
API_URL          = 'http://xml.weather.yahoo.com/forecastrss?w=%s&u=c'
WEATHER_ICON     = xbmc.translatePath('special://temp/weather/%s.png').decode("utf-8")
WEATHER_WINDOW   = xbmcgui.Window(12600)

socket.setdefaulttimeout(10)

def log(txt):
    if isinstance (txt,str):
        txt = txt.decode("utf-8")
    message = u'%s: %s' % (__addonid__, txt)
    xbmc.log(msg=message.encode("utf-8"), level=xbmc.LOGDEBUG)

def set_property(name, value):
    WEATHER_WINDOW.setProperty(name, value)

def refresh_locations():
    locations = 0
    for count in range(1, 4):
        loc_name = __addon__.getSetting('Location%s' % count)
        if loc_name != '':
            locations += 1
        set_property('Location%s' % count, loc_name)
    set_property('Locations', str(locations))
    log('available locations: %s' % str(locations))

def location(loc):
    items  = []
    locs   = []
    locids = []
    log('searching for location: %s' % loc)
    query = find_location(loc)
    log('location data: %s' % query)
    data = parse_data(query)
    if data != '' and data.has_key('query') and data['query'].has_key('results') and data['query']['results'].has_key('place'):
        if isinstance (data['query']['results']['place'],list):
            for item in data['query']['results']['place']:
                listitem   = item['name'] + ' (' + item['admin1']['content'] + ' - ' + item['country']['code'] + ')'
                location   = item['name'] + ' (' + item['country']['code'] + ')'
                locationid = item['woeid']
                items.append(listitem)
                locs.append(location)
                locids.append(locationid)
        else:
            listitem   = data['query']['results']['place']['name'] + ' (' + data['query']['results']['place']['admin1']['content'] + ' - ' + data['query']['results']['place']['country']['code'] + ')'
            location   = data['query']['results']['place']['name'] + ' (' + data['query']['results']['place']['country']['code'] + ')'
            locationid = data['query']['results']['place']['woeid']
            items.append(listitem)
            locs.append(location)
            locids.append(locationid)
    return items, locs, locids

def find_location(loc):
    query = urllib2.quote(LOC_QUERY % loc)
    url = LOC_URL % query
    try:
        req = urllib2.urlopen(url)
        response = req.read()
        req.close()
    except:
        response = ''
    return response

def parse_data(reply):
    try:
        data = simplejson.loads(reply)
    except:
        log('failed to parse weather data')
        data = ''
    return data

def forecast(loc,locid):
    log('weather location: %s' % locid)
    retry = 0
    while (retry < 6) and (not MONITOR.abortRequested()):
        query = get_weather(locid)
        if query != '':
            retry = 6
        else:
            retry += 1
            xbmc.sleep(10000)
            log('weather download failed')
    log('forecast data: %s' % query)
    if query != '':
        properties(query,loc)
    else:
        clear()

def get_weather(locid):
    url = API_URL % locid
    try:
        req = urllib2.urlopen(url)
        response = req.read()
        req.close()
    except:
        response = ''
    return response

def clear():
    set_property('Current.Condition'     , 'N/A')
    set_property('Current.Temperature'   , '0')
    set_property('Current.Wind'          , '0')
    set_property('Current.WindDirection' , 'N/A')
    set_property('Current.Humidity'      , '0')
    set_property('Current.FeelsLike'     , '0')
    set_property('Current.UVIndex'       , '0')
    set_property('Current.DewPoint'      , '0')
    set_property('Current.OutlookIcon'   , 'na.png')
    set_property('Current.FanartCode'    , 'na')
    for count in range (0, 5):
        set_property('Day%i.Title'       % count, 'N/A')
        set_property('Day%i.HighTemp'    % count, '0')
        set_property('Day%i.LowTemp'     % count, '0')
        set_property('Day%i.Outlook'     % count, 'N/A')
        set_property('Day%i.OutlookIcon' % count, 'na.png')
        set_property('Day%i.FanartCode'  % count, 'na')

def properties(data,loc):
    xml = minidom.parseString(data)
    wind = xml.getElementsByTagName('yweather:wind')
    atmosphere = xml.getElementsByTagName('yweather:atmosphere')
    astronomy = xml.getElementsByTagName('yweather:astronomy')
    condition = xml.getElementsByTagName('yweather:condition')
    forecast = xml.getElementsByTagName('yweather:forecast')
    set_property('Current.Location'      , loc)
    set_property('Current.Condition'     , condition[0].attributes['text'].value.replace('/', ' / '))
    set_property('Current.Temperature'   , condition[0].attributes['temp'].value)
    set_property('Current.Wind'          , wind[0].attributes['speed'].value)
    if (wind[0].attributes['direction'].value != ''):
        set_property('Current.WindDirection' , winddir(int(wind[0].attributes['direction'].value)))
    else:
        set_property('Current.WindDirection' , '')
    set_property('Current.WindChill'     , wind[0].attributes['chill'].value)
    set_property('Current.Humidity'      , atmosphere[0].attributes['humidity'].value)
    set_property('Current.Visibility'    , atmosphere[0].attributes['visibility'].value)
    set_property('Current.Pressure'      , atmosphere[0].attributes['pressure'].value)
    if (wind[0].attributes['speed'].value != ''):
        set_property('Current.FeelsLike'     , feelslike(int(condition[0].attributes['temp'].value), int(round(float(wind[0].attributes['speed'].value) + 0.5))))
    else:
        set_property('Current.FeelsLike' , '')
    set_property('Current.DewPoint'      , dewpoint(int(condition[0].attributes['temp'].value), int(atmosphere[0].attributes['humidity'].value)))
    set_property('Current.UVIndex'       , '')
    set_property('Current.OutlookIcon'   , '%s.png' % condition[0].attributes['code'].value) # Kodi translates it to Current.ConditionIcon
    set_property('Current.FanartCode'    , condition[0].attributes['code'].value)
    set_property('Today.Sunrise'         , astronomy[0].attributes['sunrise'].value)
    set_property('Today.Sunset'          , astronomy[0].attributes['sunset'].value)
    for count, item in enumerate(forecast):
        set_property('Day%i.Title'       % count, DAYS[item.attributes['day'].value])
        set_property('Day%i.HighTemp'    % count, item.attributes['high'].value)
        set_property('Day%i.LowTemp'     % count, item.attributes['low'].value)
        set_property('Day%i.Outlook'     % count, item.attributes['text'].value.replace('/', ' / '))
        set_property('Day%i.OutlookIcon' % count, '%s.png' % item.attributes['code'].value)
        set_property('Day%i.FanartCode'  % count, item.attributes['code'].value)

class MyMonitor(xbmc.Monitor):
    def __init__(self, *args, **kwargs):
        xbmc.Monitor.__init__(self)

log('version %s started: %s' % (__version__, sys.argv))

MONITOR = MyMonitor()
set_property('Forecast.IsFetched' , '')
set_property('Current.IsFetched'  , '')
set_property('Today.IsFetched'    , '')
set_property('Daily.IsFetched'    , '')
set_property('Weekend.IsFetched'  , '')
set_property('36Hour.IsFetched'   , '')
set_property('Hourly.IsFetched'   , '')
set_property('Alerts.IsFetched'   , '')
set_property('Map.IsFetched'      , '')
set_property('WeatherProvider'    , __addonname__)
set_property('WeatherProviderLogo', xbmc.translatePath(os.path.join(__cwd__, 'resources', 'banner.png')))

if sys.argv[1].startswith('Location'):
    keyboard = xbmc.Keyboard('', xbmc.getLocalizedString(14024), False)
    keyboard.doModal()
    if (keyboard.isConfirmed() and keyboard.getText() != ''):
        text = keyboard.getText()
        items, locs, locids = location(text)
        dialog = xbmcgui.Dialog()
        if locs != []:
            selected = dialog.select(xbmc.getLocalizedString(396), items)
            if selected != -1:
                __addon__.setSetting(sys.argv[1], locs[selected])
                __addon__.setSetting(sys.argv[1] + 'id', locids[selected])
                log('selected location: %s' % locs[selected])
        else:
            log('no locations found')
            dialog.ok(__addonname__, xbmc.getLocalizedString(284))
else:
    location = __addon__.getSetting('Location%s' % sys.argv[1])
    locationid = __addon__.getSetting('Location%sid' % sys.argv[1])
    if (locationid == '') and (sys.argv[1] != '1'):
        location = __addon__.getSetting('Location1')
        locationid = __addon__.getSetting('Location1id')
        log('trying location 1 instead')
    if not locationid == '':
        forecast(location, locationid)
    else:
        log('empty location id')
        clear()
    refresh_locations()

log('finished')
(2016-03-27, 00:12)haxobel Wrote: [ -> ]Yahoo! made a change to their weather API authentication rules on 15/03/2016 (See https://developer.yahoo.com/weather/) which broke many applications using their weather service including my Kodi installations. I have changed the KODI Yahoo! Weather add-on (default.py) to use YQL over SSL to fetch the weather instead of the RSS feed API which is used in version 3.0.9. The code is actually much neater using JSON instead of XML. This fixed my issue.

Here is the working default.py code. It would be nice if ronie could update the addon in the KODI repository if the code is deemed to work. In the meantime, you can backup your current default.py and replace it with this code (be careful with Python indenting). Hope it's nice weather where you live Smile

Code:
import os, sys, socket, urllib2
from xml.dom import minidom
import xbmc, xbmcgui, xbmcaddon
if sys.version_info < (2, 7):
    import simplejson
else:
    import json as simplejson

ADDON        = xbmcaddon.Addon()
ADDONNAME    = ADDON.getAddonInfo('name')
ADDONID      = ADDON.getAddonInfo('id')
ADDONVERSION = ADDON.getAddonInfo('version')
CWD          = ADDON.getAddonInfo('path').decode("utf-8")
RESOURCE     = xbmc.translatePath( os.path.join( CWD, 'resources', 'lib' ).encode("utf-8") ).decode("utf-8")

sys.path.append(RESOURCE)

from utilities import *

YQL_URL          = 'https://query.yahooapis.com/v1/public/yql?q=%s&format=json'
LOC_QUERY        = 'select * from geo.places where text="%s"'
FORECAST_QUERY   = 'select * from weather.forecast where woeid=%s and u="c"'
WEATHER_ICON     = xbmc.translatePath('special://temp/weather/%s.png').decode("utf-8")
WEATHER_WINDOW   = xbmcgui.Window(12600)

socket.setdefaulttimeout(10)

def log(txt):
    if isinstance (txt,str):
        txt = txt.decode("utf-8")
    message = u'%s: %s' % (ADDONID, txt)
    xbmc.log(msg=message.encode("utf-8"), level=xbmc.LOGDEBUG)

def set_property(name, value):
    WEATHER_WINDOW.setProperty(name, value)

def refresh_locations():
    locations = 0
    for count in range(1, 6):
        loc_name = ADDON.getSetting('Location%s' % count)
        if loc_name != '':
            locations += 1
        set_property('Location%s' % count, loc_name)
    set_property('Locations', str(locations))
    log('available locations: %s' % str(locations))

def location(loc):
    items  = []
    locs   = []
    locids = []
    log('searching for location: %s' % loc)
    query = find_location(loc)
    log('location data: %s' % query)
    data = parse_data(query)
    if data != '' and data.has_key('query') and data['query'].has_key('results') and data['query']['results'].has_key('place'):
        if isinstance (data['query']['results']['place'],list):
            for item in data['query']['results']['place']:
                listitem = item['name'] + ' (' + (item['admin1']['content'] + ' - ' if item['admin1'] is not None else '') + item['country']['code'] + ')'
                location   = item['name'] + ' (' + item['country']['code'] + ')'
                locationid = item['woeid']
                items.append(listitem)
                locs.append(location)
                locids.append(locationid)
        else:
            listitem   = data['query']['results']['place']['name'] + ' (' + data['query']['results']['place']['admin1']['content'] + ' - ' + data['query']['results']['place']['country']['code'] + ')'
            location   = data['query']['results']['place']['name'] + ' (' + data['query']['results']['place']['country']['code'] + ')'
            locationid = data['query']['results']['place']['woeid']
            items.append(listitem)
            locs.append(location)
            locids.append(locationid)
    return items, locs, locids

def find_location(loc):
    query = urllib2.quote(LOC_QUERY % loc)
    url = YQL_URL % query
    try:
        req = urllib2.urlopen(url)
        response = req.read()
        req.close()
    except:
        response = ''
    return response

def parse_data(reply):
    try:
        data = simplejson.loads(reply)
    except:
        log('failed to parse weather data')
        data = ''
    return data

def forecast(loc,locid):
    log('weather location: %s' % locid)
    retry = 0
    while (retry < 6) and (not MONITOR.abortRequested()):
        query = get_weather(locid)
        if query != '':
            retry = 6
        else:
            retry += 1
            xbmc.sleep(10000)
            log('weather download failed')
    log('forecast data: %s' % query)
    if query != '':
        properties(query,loc)
    else:
        clear()

def get_weather(locid):
    query = urllib2.quote(FORECAST_QUERY % locid)
    url = YQL_URL % query
    try:
        req = urllib2.urlopen(url)
        response = req.read()
        req.close()
    except:
        response = ''
    return response
    
def clear():
    set_property('Current.Condition'     , 'N/A')
    set_property('Current.Temperature'   , '0')
    set_property('Current.Wind'          , '0')
    set_property('Current.WindDirection' , 'N/A')
    set_property('Current.Humidity'      , '0')
    set_property('Current.FeelsLike'     , '0')
    set_property('Current.UVIndex'       , '0')
    set_property('Current.DewPoint'      , '0')
    set_property('Current.OutlookIcon'   , 'na.png')
    set_property('Current.FanartCode'    , 'na')
    for count in range (0, 5):
        set_property('Day%i.Title'       % count, 'N/A')
        set_property('Day%i.HighTemp'    % count, '0')
        set_property('Day%i.LowTemp'     % count, '0')
        set_property('Day%i.Outlook'     % count, 'N/A')
        set_property('Day%i.OutlookIcon' % count, 'na.png')
        set_property('Day%i.FanartCode'  % count, 'na')

def properties(data,loc):
    json = parse_data(data)
    wind = json['query']['results']['channel']['wind']
    atmosphere = json['query']['results']['channel']['atmosphere']
    astronomy = json['query']['results']['channel']['astronomy']
    condition = json['query']['results']['channel']['item']['condition']
    forecast = json['query']['results']['channel']['item']['forecast']
    set_property('Current.Location'      , loc)
    set_property('Current.Condition'     , condition['text'].replace('/', ' / '))
    set_property('Current.Temperature'   , condition['temp'])
    set_property('Current.Wind'          , wind['speed'])
    if (wind['direction'] != ''):
        set_property('Current.WindDirection' , winddir(int(wind['direction'])))
    else:
        set_property('Current.WindDirection' , '')
    set_property('Current.WindChill'     , wind['chill'])
    set_property('Current.Humidity'      , atmosphere['humidity'])
    set_property('Current.Visibility'    , atmosphere['visibility'])
    set_property('Current.Pressure'      , atmosphere['pressure'])
    if (wind['speed'] != ''):
        set_property('Current.FeelsLike'     , feelslike(int(condition['temp']), int(round(float(wind['speed']) + 0.5))))
    else:
        set_property('Current.FeelsLike' , '')
    if (condition['temp'] != '') and (atmosphere['humidity'] != ''):
        set_property('Current.DewPoint'      , dewpoint(int(condition['temp']), int(atmosphere['humidity'])))
    else:
        set_property('Current.DewPoint' , '')
    set_property('Current.UVIndex'       , '')
    set_property('Current.OutlookIcon'   , '%s.png' % condition['code']) # Kodi translates it to Current.ConditionIcon
    set_property('Current.FanartCode'    , condition['code'])
    set_property('Today.Sunrise'         , astronomy['sunrise'])
    set_property('Today.Sunset'          , astronomy['sunset'])
    for count, item in enumerate(forecast):
        set_property('Day%i.Title'       % count, DAYS[item['day']])
        set_property('Day%i.HighTemp'    % count, item['high'])
        set_property('Day%i.LowTemp'     % count, item['low'])
        set_property('Day%i.Outlook'     % count, item['text'].replace('/', ' / '))
        set_property('Day%i.OutlookIcon' % count, '%s.png' % item['code'])
        set_property('Day%i.FanartCode'  % count, item['code'])

class MyMonitor(xbmc.Monitor):
    def __init__(self, *args, **kwargs):
        xbmc.Monitor.__init__(self)

log('version %s started: %s' % (ADDONVERSION, sys.argv))

MONITOR = MyMonitor()
set_property('Forecast.IsFetched' , '')
set_property('Current.IsFetched'  , '')
set_property('Today.IsFetched'    , '')
set_property('Daily.IsFetched'    , '')
set_property('Weekend.IsFetched'  , '')
set_property('36Hour.IsFetched'   , '')
set_property('Hourly.IsFetched'   , '')
set_property('Alerts.IsFetched'   , '')
set_property('Map.IsFetched'      , '')
set_property('WeatherProvider'    , ADDONNAME)
set_property('WeatherProviderLogo', xbmc.translatePath(os.path.join(CWD, 'resources', 'banner.png')))

if sys.argv[1].startswith('Location'):
    keyboard = xbmc.Keyboard('', xbmc.getLocalizedString(14024), False)
    keyboard.doModal()
    if (keyboard.isConfirmed() and keyboard.getText() != ''):
        text = keyboard.getText()
        items, locs, locids = location(text)
        dialog = xbmcgui.Dialog()
        if locs != []:
            selected = dialog.select(xbmc.getLocalizedString(396), items)
            if selected != -1:
                ADDON.setSetting(sys.argv[1], locs[selected])
                ADDON.setSetting(sys.argv[1] + 'id', locids[selected])
                log('selected location: %s' % locs[selected])
        else:
            log('no locations found')
            dialog.ok(ADDONNAME, xbmc.getLocalizedString(284))
else:
    location = ADDON.getSetting('Location%s' % sys.argv[1])
    locationid = ADDON.getSetting('Location%sid' % sys.argv[1])
    if (locationid == '') and (sys.argv[1] != '1'):
        location = ADDON.getSetting('Location1')
        locationid = ADDON.getSetting('Location1id')
        log('trying location 1 instead')
    if not locationid == '':
        forecast(location, locationid)
    else:
        log('empty location id')
        clear()
    refresh_locations()

log('finished')

Thank you haxobel, I was wondering why my Yahoo weather quit working, this works great for me!
Noob question, how do I open the .py file with Windows 10? I know what folder it's in I just can't open it.
I use Sublime Text editor https://www.sublimetext.com/
(2016-03-28, 15:56)Trillium Wrote: [ -> ]
(2016-03-27, 00:12)haxobel Wrote: [ -> ]Yahoo! made a change to their weather API authentication rules on 15/03/2016 (See https://developer.yahoo.com/weather/) which broke many applications using their weather service including my Kodi installations. I have changed the KODI Yahoo! Weather add-on (default.py) to use YQL over SSL to fetch the weather instead of the RSS feed API which is used in version 3.0.9. The code is actually much neater using JSON instead of XML. This fixed my issue.

Here is the working default.py code. It would be nice if ronie could update the addon in the KODI repository if the code is deemed to work. In the meantime, you can backup your current default.py and replace it with this code (be careful with Python indenting). Hope it's nice weather where you live Smile

Code:
import os, sys, socket, urllib2
from xml.dom import minidom
import xbmc, xbmcgui, xbmcaddon
if sys.version_info < (2, 7):
    import simplejson
else:
    import json as simplejson

ADDON        = xbmcaddon.Addon()
ADDONNAME    = ADDON.getAddonInfo('name')
ADDONID      = ADDON.getAddonInfo('id')
ADDONVERSION = ADDON.getAddonInfo('version')
CWD          = ADDON.getAddonInfo('path').decode("utf-8")
RESOURCE     = xbmc.translatePath( os.path.join( CWD, 'resources', 'lib' ).encode("utf-8") ).decode("utf-8")

sys.path.append(RESOURCE)

from utilities import *

YQL_URL          = 'https://query.yahooapis.com/v1/public/yql?q=%s&format=json'
LOC_QUERY        = 'select * from geo.places where text="%s"'
FORECAST_QUERY   = 'select * from weather.forecast where woeid=%s and u="c"'
WEATHER_ICON     = xbmc.translatePath('special://temp/weather/%s.png').decode("utf-8")
WEATHER_WINDOW   = xbmcgui.Window(12600)

socket.setdefaulttimeout(10)

def log(txt):
    if isinstance (txt,str):
        txt = txt.decode("utf-8")
    message = u'%s: %s' % (ADDONID, txt)
    xbmc.log(msg=message.encode("utf-8"), level=xbmc.LOGDEBUG)

def set_property(name, value):
    WEATHER_WINDOW.setProperty(name, value)

def refresh_locations():
    locations = 0
    for count in range(1, 6):
        loc_name = ADDON.getSetting('Location%s' % count)
        if loc_name != '':
            locations += 1
        set_property('Location%s' % count, loc_name)
    set_property('Locations', str(locations))
    log('available locations: %s' % str(locations))

def location(loc):
    items  = []
    locs   = []
    locids = []
    log('searching for location: %s' % loc)
    query = find_location(loc)
    log('location data: %s' % query)
    data = parse_data(query)
    if data != '' and data.has_key('query') and data['query'].has_key('results') and data['query']['results'].has_key('place'):
        if isinstance (data['query']['results']['place'],list):
            for item in data['query']['results']['place']:
                listitem = item['name'] + ' (' + (item['admin1']['content'] + ' - ' if item['admin1'] is not None else '') + item['country']['code'] + ')'
                location   = item['name'] + ' (' + item['country']['code'] + ')'
                locationid = item['woeid']
                items.append(listitem)
                locs.append(location)
                locids.append(locationid)
        else:
            listitem   = data['query']['results']['place']['name'] + ' (' + data['query']['results']['place']['admin1']['content'] + ' - ' + data['query']['results']['place']['country']['code'] + ')'
            location   = data['query']['results']['place']['name'] + ' (' + data['query']['results']['place']['country']['code'] + ')'
            locationid = data['query']['results']['place']['woeid']
            items.append(listitem)
            locs.append(location)
            locids.append(locationid)
    return items, locs, locids

def find_location(loc):
    query = urllib2.quote(LOC_QUERY % loc)
    url = YQL_URL % query
    try:
        req = urllib2.urlopen(url)
        response = req.read()
        req.close()
    except:
        response = ''
    return response

def parse_data(reply):
    try:
        data = simplejson.loads(reply)
    except:
        log('failed to parse weather data')
        data = ''
    return data

def forecast(loc,locid):
    log('weather location: %s' % locid)
    retry = 0
    while (retry < 6) and (not MONITOR.abortRequested()):
        query = get_weather(locid)
        if query != '':
            retry = 6
        else:
            retry += 1
            xbmc.sleep(10000)
            log('weather download failed')
    log('forecast data: %s' % query)
    if query != '':
        properties(query,loc)
    else:
        clear()

def get_weather(locid):
    query = urllib2.quote(FORECAST_QUERY % locid)
    url = YQL_URL % query
    try:
        req = urllib2.urlopen(url)
        response = req.read()
        req.close()
    except:
        response = ''
    return response
    
def clear():
    set_property('Current.Condition'     , 'N/A')
    set_property('Current.Temperature'   , '0')
    set_property('Current.Wind'          , '0')
    set_property('Current.WindDirection' , 'N/A')
    set_property('Current.Humidity'      , '0')
    set_property('Current.FeelsLike'     , '0')
    set_property('Current.UVIndex'       , '0')
    set_property('Current.DewPoint'      , '0')
    set_property('Current.OutlookIcon'   , 'na.png')
    set_property('Current.FanartCode'    , 'na')
    for count in range (0, 5):
        set_property('Day%i.Title'       % count, 'N/A')
        set_property('Day%i.HighTemp'    % count, '0')
        set_property('Day%i.LowTemp'     % count, '0')
        set_property('Day%i.Outlook'     % count, 'N/A')
        set_property('Day%i.OutlookIcon' % count, 'na.png')
        set_property('Day%i.FanartCode'  % count, 'na')

def properties(data,loc):
    json = parse_data(data)
    wind = json['query']['results']['channel']['wind']
    atmosphere = json['query']['results']['channel']['atmosphere']
    astronomy = json['query']['results']['channel']['astronomy']
    condition = json['query']['results']['channel']['item']['condition']
    forecast = json['query']['results']['channel']['item']['forecast']
    set_property('Current.Location'      , loc)
    set_property('Current.Condition'     , condition['text'].replace('/', ' / '))
    set_property('Current.Temperature'   , condition['temp'])
    set_property('Current.Wind'          , wind['speed'])
    if (wind['direction'] != ''):
        set_property('Current.WindDirection' , winddir(int(wind['direction'])))
    else:
        set_property('Current.WindDirection' , '')
    set_property('Current.WindChill'     , wind['chill'])
    set_property('Current.Humidity'      , atmosphere['humidity'])
    set_property('Current.Visibility'    , atmosphere['visibility'])
    set_property('Current.Pressure'      , atmosphere['pressure'])
    if (wind['speed'] != ''):
        set_property('Current.FeelsLike'     , feelslike(int(condition['temp']), int(round(float(wind['speed']) + 0.5))))
    else:
        set_property('Current.FeelsLike' , '')
    if (condition['temp'] != '') and (atmosphere['humidity'] != ''):
        set_property('Current.DewPoint'      , dewpoint(int(condition['temp']), int(atmosphere['humidity'])))
    else:
        set_property('Current.DewPoint' , '')
    set_property('Current.UVIndex'       , '')
    set_property('Current.OutlookIcon'   , '%s.png' % condition['code']) # Kodi translates it to Current.ConditionIcon
    set_property('Current.FanartCode'    , condition['code'])
    set_property('Today.Sunrise'         , astronomy['sunrise'])
    set_property('Today.Sunset'          , astronomy['sunset'])
    for count, item in enumerate(forecast):
        set_property('Day%i.Title'       % count, DAYS[item['day']])
        set_property('Day%i.HighTemp'    % count, item['high'])
        set_property('Day%i.LowTemp'     % count, item['low'])
        set_property('Day%i.Outlook'     % count, item['text'].replace('/', ' / '))
        set_property('Day%i.OutlookIcon' % count, '%s.png' % item['code'])
        set_property('Day%i.FanartCode'  % count, item['code'])

class MyMonitor(xbmc.Monitor):
    def __init__(self, *args, **kwargs):
        xbmc.Monitor.__init__(self)

log('version %s started: %s' % (ADDONVERSION, sys.argv))

MONITOR = MyMonitor()
set_property('Forecast.IsFetched' , '')
set_property('Current.IsFetched'  , '')
set_property('Today.IsFetched'    , '')
set_property('Daily.IsFetched'    , '')
set_property('Weekend.IsFetched'  , '')
set_property('36Hour.IsFetched'   , '')
set_property('Hourly.IsFetched'   , '')
set_property('Alerts.IsFetched'   , '')
set_property('Map.IsFetched'      , '')
set_property('WeatherProvider'    , ADDONNAME)
set_property('WeatherProviderLogo', xbmc.translatePath(os.path.join(CWD, 'resources', 'banner.png')))

if sys.argv[1].startswith('Location'):
    keyboard = xbmc.Keyboard('', xbmc.getLocalizedString(14024), False)
    keyboard.doModal()
    if (keyboard.isConfirmed() and keyboard.getText() != ''):
        text = keyboard.getText()
        items, locs, locids = location(text)
        dialog = xbmcgui.Dialog()
        if locs != []:
            selected = dialog.select(xbmc.getLocalizedString(396), items)
            if selected != -1:
                ADDON.setSetting(sys.argv[1], locs[selected])
                ADDON.setSetting(sys.argv[1] + 'id', locids[selected])
                log('selected location: %s' % locs[selected])
        else:
            log('no locations found')
            dialog.ok(ADDONNAME, xbmc.getLocalizedString(284))
else:
    location = ADDON.getSetting('Location%s' % sys.argv[1])
    locationid = ADDON.getSetting('Location%sid' % sys.argv[1])
    if (locationid == '') and (sys.argv[1] != '1'):
        location = ADDON.getSetting('Location1')
        locationid = ADDON.getSetting('Location1id')
        log('trying location 1 instead')
    if not locationid == '':
        forecast(location, locationid)
    else:
        log('empty location id')
        clear()
    refresh_locations()

log('finished')

Thank you haxobel, I was wondering why my Yahoo weather quit working, this works great for me!

Thanks, this is working for me also ( FYI: I used "Notepad++" for Python file edit )
My Yahoo Weather add-on recently broke as well.

I'm running Win10 w/ Kodi 14.2 and the Confluence Customizable Mod skin and am in the USA.

I found the default.py file at users.../addons/weather.yahoo

I copied and pasted the above code into Notepad++ and saved it as default.py.

I then replaced the existing default.py with this new one and restarted everything. Yahoo weather now gives a script error where before it simply had no data.

I could sure use more guidance.
Hey rbmcgee ,

I have tried both ways offered to fix the problem, both ways work but I think that post # 165 is the easiest.
But to save you trouble, I am including the edited file here (.zip)
http://www.filedropper.com/yahooedited , just click on download and enter the catcha.
Just drop it in Start/Run %appdata%\Kodi\addons\weather.yahoo
Thanks OTinley,

While waiting I started backtracking through this thread and found post 165. I tried that answer and that one seems to have worked.

So my vote is 165 works, but the entirely new default.py code does not.
(2016-03-28, 22:01)rbmcgee Wrote: [ -> ]So my vote is 165 works, but the entirely new default.py code does not.
It does. I am using both for testing purposes.
If you are getting the script error, an illegal character was probably introduced during the cut/paste process.(especially an extra blank space)
If you want it, I can also upload that one.
Pages: 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