1 # -*- coding: utf-8 -*-
7 # Coded by Dr.Best (c) 2009
8 # Support: www.dreambox-tools.info
10 # This program is free software; you can redistribute it and/or
11 # modify it under the terms of the GNU General Public License
12 # as published by the Free Software Foundation; either version 2
13 # of the License, or (at your option) any later version.
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
21 # for localized messages
24 from Plugins.Plugin import PluginDescriptor
25 from Screens.Screen import Screen
26 from Components.ActionMap import ActionMap
27 from Components.Sources.StaticText import StaticText
28 from xml.etree.cElementTree import fromstring as cet_fromstring
29 from twisted.internet import defer
30 from twisted.web.client import getPage, downloadPage
31 from urllib import quote
32 from Components.Pixmap import Pixmap
33 from enigma import ePicLoad
34 from os import path as os_path, mkdir as os_mkdir
35 from Components.AVSwitch import AVSwitch
36 from Components.config import ConfigSubsection, ConfigSubList, ConfigInteger, config
37 from setup import initConfig, WeatherPluginEntriesListConfigScreen
39 config.plugins.WeatherPlugin = ConfigSubsection()
40 config.plugins.WeatherPlugin.entriescount = ConfigInteger(0)
41 config.plugins.WeatherPlugin.Entries = ConfigSubList()
44 UserAgent = "Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.0.15) Gecko/2009102815 Ubuntu/9.04 (jaunty) Firefox/3."
46 class WeatherIconItem:
47 def __init__(self, url = "", filename = "", index = -1, error = False):
49 self.filename = filename
54 return getPage(url, agent=UserAgent)
57 return downloadPage(item.url, file(item.filename, 'wb'), agent=UserAgent)
60 def main(session,**kwargs):
61 session.open(WeatherPlugin)
63 def Plugins(**kwargs):
64 list = [PluginDescriptor(name=_("Weather Plugin"), description=_("Weather Plugin"), where = [PluginDescriptor.WHERE_EXTENSIONSMENU], fnc=main)]
68 class WeatherPlugin(Screen):
71 <screen name="WeatherPlugin" position="center,center" size="664,190" title="%s">
72 <widget render="Label" source="caption" position="10,20" zPosition="1" size="300,23" font="Regular;22" transparent="1"/>
73 <widget render="Label" source="currentTemp" position="10,45" zPosition="1" size="300,23" font="Regular;22" transparent="1"/>
74 <widget render="Label" source="condition" position="10,100" zPosition="1" size="300,20" font="Regular;18" transparent="1"/>
75 <widget render="Label" source="wind_condition" position="10,125" zPosition="1" size="300,20" font="Regular;18" transparent="1"/>
76 <widget render="Label" source="humidity" position="10,150" zPosition="1" size="300,20" font="Regular;18" valign="bottom" transparent="1"/>
77 <widget render="Label" source="weekday1" position="255,50" zPosition="1" size="72,20" halign="center" valign="center" font="Regular;18" transparent="1"/>
78 <widget name="weekday1_icon" position="255,70" zPosition="1" size="72,72" alphatest="blend"/>
79 <widget render="Label" source="weekday1_temp" position="241,150" zPosition="1" size="100,20" halign="center" valign="bottom" font="Regular;16" transparent="1"/>
80 <widget render="Label" source="weekday2" position="358,50" zPosition="1" size="72,20" halign="center" valign="center" font="Regular;18" transparent="1"/>
81 <widget name="weekday2_icon" position="358,70" zPosition="1" size="72,72" alphatest="blend"/>
82 <widget render="Label" source="weekday2_temp" position="344,150" zPosition="1" size="100,20" halign="center" valign="bottom" font="Regular;16" transparent="1"/>
83 <widget render="Label" source="weekday3" position="461,50" zPosition="1" size="72,20" halign="center" valign="center" font="Regular;18" transparent="1"/>
84 <widget name="weekday3_icon" position="461,70" zPosition="1" size="72,72" alphatest="blend"/>
85 <widget render="Label" source="weekday3_temp" position="448,150" zPosition="1" size="100,20" halign="center" valign="bottom" font="Regular;16" transparent="1"/>
86 <widget render="Label" source="weekday4" position="564,50" zPosition="1" size="72,20" halign="center" valign="center" font="Regular;18" transparent="1"/>
87 <widget name="weekday4_icon" position="564,70" zPosition="1" size="72,72" alphatest="blend"/>
88 <widget render="Label" source="weekday4_temp" position="550,150" zPosition="1" size="100,20" halign="center" valign="bottom" font="Regular;16" transparent="1"/>
89 <widget render="Label" source="statustext" position="0,0" zPosition="1" size="664,190" font="Regular;20" halign="center" valign="center" transparent="1"/>
92 def __init__(self, session):
93 Screen.__init__(self, session)
94 self.title = _("Weather Plugin")
95 self["actions"] = ActionMap(["WizardActions", "DirectionActions", "ColorActions", "EPGSelectActions"],
98 "input_date_time": self.config,
99 "right": self.nextItem,
100 "left": self.previousItem
103 self["statustext"] = StaticText()
104 self["caption"] = StaticText()
105 self["currentTemp"] = StaticText()
106 self["condition"] = StaticText()
107 self["wind_condition"] = StaticText()
108 self["humidity"] = StaticText()
112 self["weekday%s" % i] = StaticText()
113 self["weekday%s_icon" %i] = WeatherIcon()
114 self["weekday%s_temp" % i] = StaticText()
118 self.appdir = "/usr/lib/enigma2/python/Plugins/Extensions/WeatherPlugin/icons/"
119 if not os_path.exists(self.appdir):
120 os_mkdir(self.appdir)
122 self.weatherPluginEntryIndex = -1
123 self.weatherPluginEntryCount = config.plugins.WeatherPlugin.entriescount.value
124 if self.weatherPluginEntryCount >= 1:
125 self.weatherPluginEntry = config.plugins.WeatherPlugin.Entries[0]
126 self.weatherPluginEntryIndex = 1
128 self.weatherPluginEntry = None
130 self.onLayoutFinish.append(self.startRun)
133 if self.weatherPluginEntry is not None:
134 self["statustext"].text = _("Getting weather information...")
135 url = ("http://www.google.com/ig/api?weather=%s&hl=%s" % (quote(self.weatherPluginEntry.city.value), self.weatherPluginEntry.language.value))
136 getXML(url).addCallback(self.xmlCallback).addErrback(self.error)
138 self["statustext"].text = _("No locations defined...\nPress 'Menu' to do that.")
141 if self.weatherPluginEntryCount != 0:
142 if self.weatherPluginEntryIndex < self.weatherPluginEntryCount:
143 self.weatherPluginEntryIndex = self.weatherPluginEntryIndex + 1
145 self.weatherPluginEntryIndex = 1
148 def previousItem(self):
149 if self.weatherPluginEntryCount != 0:
150 if self.weatherPluginEntryIndex >= 2:
151 self.weatherPluginEntryIndex = self.weatherPluginEntryIndex - 1
153 self.weatherPluginEntryIndex = self.weatherPluginEntryCount
157 self.weatherPluginEntry = config.plugins.WeatherPlugin.Entries[self.weatherPluginEntryIndex-1]
161 def clearFields(self):
162 self["caption"].text = ""
163 self["currentTemp"].text = ""
164 self["condition"].text = ""
165 self["wind_condition"].text = ""
166 self["humidity"].text = ""
169 self["weekday%s" % i].text = ""
170 self["weekday%s_icon" %i].hide()
171 self["weekday%s_temp" % i].text = ""
174 def errorIconDownload(self, error = None, item = None):
177 def finishedIconDownload(self, result, item):
179 self.showIcon(item.index,item.filename)
181 def showIcon(self,index, filename):
182 self["weekday%s_icon" % index].updateIcon(filename)
183 self["weekday%s_icon" % index].show()
185 def xmlCallback(self, xmlstring):
186 self["statustext"].text = ""
190 IconDownloadList = []
191 root = cet_fromstring(xmlstring)
192 for childs in root.findall("weather"):
194 if items.tag == "problem_cause":
195 self["statustext"].text = items.attrib.get("data").encode("utf-8", 'ignore')
196 elif items.tag == "forecast_information":
198 if items2.tag == "city":
199 self["caption"].text = items2.attrib.get("data").encode("utf-8", 'ignore')
200 elif items2.tag == "unit_system":
201 if items2.attrib.get("data").encode("utf-8", 'ignore') == "SI":
204 elif items.tag == "current_conditions":
206 if items2.tag == "condition":
207 self["condition"].text = _("Current: %s") % items2.attrib.get("data").encode("utf-8", 'ignore')
208 elif items2.tag == "temp_f" and metric == 0:
209 self["currentTemp"].text = ("%s °F" % items2.attrib.get("data").encode("utf-8", 'ignore'))
210 elif items2.tag == "temp_c" and metric == 1:
211 self["currentTemp"].text = ("%s °C" % items2.attrib.get("data").encode("utf-8", 'ignore'))
212 elif items2.tag == "humidity":
213 self["humidity"].text = items2.attrib.get("data").encode("utf-8", 'ignore')
214 elif items2.tag == "wind_condition":
215 self["wind_condition"].text = items2.attrib.get("data").encode("utf-8", 'ignore')
216 elif items.tag == "forecast_conditions":
222 if items2.tag == "day_of_week":
223 self["weekday%s" % index].text = items2.attrib.get("data").encode("utf-8", 'ignore')
224 elif items2.tag == "low":
225 lowTemp = items2.attrib.get("data").encode("utf-8", 'ignore')
226 elif items2.tag == "high":
227 highTemp = items2.attrib.get("data").encode("utf-8", 'ignore')
228 self["weekday%s_temp" % index].text = "%s °%s | %s °%s" % (highTemp, UnitSystemText, lowTemp, UnitSystemText)
229 elif items2.tag == "icon":
230 url = "http://www.google.com%s" % items2.attrib.get("data").encode("utf-8", 'ignore')
231 parts = url.split("/")
232 filename = self.appdir + parts[-1]
233 if not os_path.exists(filename):
234 IconDownloadList.append(WeatherIconItem(url = url,filename = filename, index = index))
236 self.showIcon(index,filename)
237 if len(IconDownloadList) != 0:
238 ds = defer.DeferredSemaphore(tokens=len(IconDownloadList))
239 downloads = [ds.run(download,item ).addErrback(self.errorIconDownload, item).addCallback(self.finishedIconDownload,item) for item in IconDownloadList]
240 finished = defer.DeferredList(downloads).addErrback(self.error)
243 self.session.openWithCallback(self.setupFinished, WeatherPluginEntriesListConfigScreen)
245 def setupFinished(self, index, entry = None):
246 self.weatherPluginEntryCount = config.plugins.WeatherPlugin.entriescount.value
247 if self.weatherPluginEntryCount >= 1:
248 if entry is not None:
249 self.weatherPluginEntry = entry
250 self.weatherPluginEntryIndex = index + 1
251 if self.weatherPluginEntry is None:
252 self.weatherPluginEntry = config.plugins.WeatherPlugin.Entries[0]
253 self.weatherPluginEntryIndex = 1
255 self.weatherPluginEntry = None
256 self.weatherPluginEntryIndex = -1
261 def error(self, error = None):
262 if error is not None:
264 self["statustext"].text = str(error.getErrorMessage())
267 class WeatherIcon(Pixmap):
269 Pixmap.__init__(self)
270 self.IconFileName = ""
271 self.picload = ePicLoad()
272 self.picload.PictureData.get().append(self.paintIconPixmapCB)
276 sc = AVSwitch().getFramebufferScale()
277 self.picload.setPara((self.instance.size().width(), self.instance.size().height(), sc[0], sc[1], 0, 0, '#00000000'))
279 def paintIconPixmapCB(self, picInfo=None):
280 ptr = self.picload.getData()
282 self.instance.setPixmap(ptr.__deref__())
284 def updateIcon(self, filename):
285 new_IconFileName = filename
286 if (self.IconFileName != new_IconFileName):
287 self.IconFileName = new_IconFileName
288 self.picload.startDecode(self.IconFileName)