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 from Plugins.Plugin import PluginDescriptor
22 from Screens.Screen import Screen
23 from Components.ActionMap import ActionMap
24 from Components.Sources.StaticText import StaticText
25 from xml.etree.cElementTree import fromstring as cet_fromstring
26 from twisted.internet import defer
27 from twisted.web.client import getPage, downloadPage
28 from urllib import quote
29 from Components.Pixmap import Pixmap
30 from enigma import ePicLoad
31 from os import path as os_path, mkdir as os_mkdir
32 from Components.AVSwitch import AVSwitch
33 from Components.config import ConfigSubsection, ConfigSubList, ConfigInteger, config
34 from setup import initConfig, WeatherPluginEntriesListConfigScreen
36 config.plugins.WeatherPlugin = ConfigSubsection()
37 config.plugins.WeatherPlugin.entriescount = ConfigInteger(0)
38 config.plugins.WeatherPlugin.Entries = ConfigSubList()
41 UserAgent = "Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.0.15) Gecko/2009102815 Ubuntu/9.04 (jaunty) Firefox/3."
43 class WeatherIconItem:
44 def __init__(self, url = "", filename = "", index = -1, error = False):
46 self.filename = filename
51 return getPage(url, agent=UserAgent)
54 return downloadPage(item.url, file(item.filename, 'wb'), agent=UserAgent)
57 def main(session,**kwargs):
58 session.open(WeatherPlugin)
60 def Plugins(**kwargs):
61 list = [PluginDescriptor(name="Weather Plugin", description=_("Weather Plugin"), where = [PluginDescriptor.WHERE_EXTENSIONSMENU], fnc=main)]
65 class WeatherPlugin(Screen):
68 <screen name="WeatherPlugin" position="center,center" size="664,170" title="Weather Plugin">
69 <widget render="Label" source="caption" position="10,20" zPosition="1" size="300,23" font="Regular;22" transparent="1"/>
70 <widget render="Label" source="currentTemp" position="10,45" zPosition="1" size="300,23" font="Regular;22" transparent="1"/>
71 <widget render="Label" source="condition" position="10,80" zPosition="1" size="300,20" font="Regular;18" transparent="1"/>
72 <widget render="Label" source="wind_condition" position="10,105" zPosition="1" size="300,20" font="Regular;18" transparent="1"/>
73 <widget render="Label" source="humidity" position="10,130" zPosition="1" size="300,20" font="Regular;18" valign="bottom" transparent="1"/>
74 <widget render="Label" source="weekday1" position="255,30" zPosition="1" size="72,20" halign="center" valign="center" font="Regular;18" transparent="1"/>
75 <widget name="weekday1_icon" position="255,50" zPosition="1" size="72,72" alphatest="blend"/>
76 <widget render="Label" source="weekday1_temp" position="241,130" zPosition="1" size="100,20" halign="center" valign="bottom" font="Regular;16" transparent="1"/>
77 <widget render="Label" source="weekday2" position="358,30" zPosition="1" size="72,20" halign="center" valign="center" font="Regular;18" transparent="1"/>
78 <widget name="weekday2_icon" position="358,50" zPosition="1" size="72,72" alphatest="blend"/>
79 <widget render="Label" source="weekday2_temp" position="344,130" zPosition="1" size="100,20" halign="center" valign="bottom" font="Regular;16" transparent="1"/>
80 <widget render="Label" source="weekday3" position="461,30" zPosition="1" size="72,20" halign="center" valign="center" font="Regular;18" transparent="1"/>
81 <widget name="weekday3_icon" position="461,50" zPosition="1" size="72,72" alphatest="blend"/>
82 <widget render="Label" source="weekday3_temp" position="448,130" zPosition="1" size="100,20" halign="center" valign="bottom" font="Regular;16" transparent="1"/>
83 <widget render="Label" source="weekday4" position="564,30" zPosition="1" size="72,20" halign="center" valign="center" font="Regular;18" transparent="1"/>
84 <widget name="weekday4_icon" position="564,50" zPosition="1" size="72,72" alphatest="blend"/>
85 <widget render="Label" source="weekday4_temp" position="550,130" zPosition="1" size="100,20" halign="center" valign="bottom" font="Regular;16" transparent="1"/>
86 <widget render="Label" source="statustext" position="0,0" zPosition="1" size="664,170" font="Regular;20" halign="center" valign="center" transparent="1"/>
89 def __init__(self, session):
90 Screen.__init__(self, session)
91 self["actions"] = ActionMap(["WizardActions", "DirectionActions", "ColorActions", "EPGSelectActions"],
94 "input_date_time": self.config,
95 "right": self.nextItem,
96 "left": self.previousItem
99 self["statustext"] = StaticText()
100 self["caption"] = StaticText()
101 self["currentTemp"] = StaticText()
102 self["condition"] = StaticText()
103 self["wind_condition"] = StaticText()
104 self["humidity"] = StaticText()
108 self["weekday%s" % i] = StaticText()
109 self["weekday%s_icon" %i] = WeatherIcon()
110 self["weekday%s_temp" % i] = StaticText()
114 self.appdir = "/usr/lib/enigma2/python/Plugins/Extensions/WeatherPlugin/icons/"
115 if not os_path.exists(self.appdir):
116 os_mkdir(self.appdir)
118 self.weatherPluginEntryIndex = -1
119 self.weatherPluginEntryCount = config.plugins.WeatherPlugin.entriescount.value
120 if self.weatherPluginEntryCount >= 1:
121 self.weatherPluginEntry = config.plugins.WeatherPlugin.Entries[0]
122 self.weatherPluginEntryIndex = 1
124 self.weatherPluginEntry = None
126 self.onLayoutFinish.append(self.startRun)
129 if self.weatherPluginEntry is not None:
130 self["statustext"].text = _("Getting weather information...")
131 url = ("http://www.google.com/ig/api?weather=%s&hl=%s" % (quote(self.weatherPluginEntry.city.value), self.weatherPluginEntry.language.value))
132 getXML(url).addCallback(self.xmlCallback).addErrback(self.error)
134 self["statustext"].text = _("No locations defined...\nPress 'Menu' to do that.")
137 if self.weatherPluginEntryCount != 0:
138 if self.weatherPluginEntryIndex < self.weatherPluginEntryCount:
139 self.weatherPluginEntryIndex = self.weatherPluginEntryIndex + 1
141 self.weatherPluginEntryIndex = 1
144 def previousItem(self):
145 if self.weatherPluginEntryCount != 0:
146 if self.weatherPluginEntryIndex >= 2:
147 self.weatherPluginEntryIndex = self.weatherPluginEntryIndex - 1
149 self.weatherPluginEntryIndex = self.weatherPluginEntryCount
153 self.weatherPluginEntry = config.plugins.WeatherPlugin.Entries[self.weatherPluginEntryIndex-1]
157 def clearFields(self):
158 self["caption"].text = ""
159 self["currentTemp"].text = ""
160 self["condition"].text = ""
161 self["wind_condition"].text = ""
162 self["humidity"].text = ""
165 self["weekday%s" % i].text = ""
166 self["weekday%s_icon" %i].hide()
167 self["weekday%s_temp" % i].text = ""
170 def errorIconDownload(self, error = None, item = None):
173 def finishedIconDownload(self, result, item):
175 self.showIcon(item.index,item.filename)
177 def showIcon(self,index, filename):
178 self["weekday%s_icon" % index].updateIcon(filename)
179 self["weekday%s_icon" % index].show()
181 def xmlCallback(self, xmlstring):
182 self["statustext"].text = ""
186 IconDownloadList = []
187 root = cet_fromstring(xmlstring)
188 for childs in root.findall("weather"):
190 if items.tag == "problem_cause":
191 self["statustext"].text = items.attrib.get("data").encode("utf-8", 'ignore')
192 elif items.tag == "forecast_information":
194 if items2.tag == "city":
195 self["caption"].text = items2.attrib.get("data").encode("utf-8", 'ignore')
196 elif items2.tag == "unit_system":
197 if items2.attrib.get("data").encode("utf-8", 'ignore') == "SI":
200 elif items.tag == "current_conditions":
202 if items2.tag == "condition":
203 self["condition"].text = _("Current: %s") % items2.attrib.get("data").encode("utf-8", 'ignore')
204 elif items2.tag == "temp_f" and metric == 0:
205 self["currentTemp"].text = ("%s °F" % items2.attrib.get("data").encode("utf-8", 'ignore'))
206 elif items2.tag == "temp_c" and metric == 1:
207 self["currentTemp"].text = ("%s °C" % items2.attrib.get("data").encode("utf-8", 'ignore'))
208 elif items2.tag == "humidity":
209 self["humidity"].text = items2.attrib.get("data").encode("utf-8", 'ignore')
210 elif items2.tag == "wind_condition":
211 self["wind_condition"].text = items2.attrib.get("data").encode("utf-8", 'ignore')
212 elif items.tag == "forecast_conditions":
218 if items2.tag == "day_of_week":
219 self["weekday%s" % index].text = items2.attrib.get("data").encode("utf-8", 'ignore')
220 elif items2.tag == "low":
221 lowTemp = items2.attrib.get("data").encode("utf-8", 'ignore')
222 elif items2.tag == "high":
223 highTemp = items2.attrib.get("data").encode("utf-8", 'ignore')
224 self["weekday%s_temp" % index].text = "%s °%s | %s °%s" % (highTemp, UnitSystemText, lowTemp, UnitSystemText)
225 elif items2.tag == "icon":
226 url = "http://www.google.com%s" % items2.attrib.get("data").encode("utf-8", 'ignore')
227 parts = url.split("/")
228 filename = self.appdir + parts[-1]
229 if not os_path.exists(filename):
230 IconDownloadList.append(WeatherIconItem(url = url,filename = filename, index = index))
232 self.showIcon(index,filename)
233 if len(IconDownloadList) != 0:
234 ds = defer.DeferredSemaphore(tokens=len(IconDownloadList))
235 downloads = [ds.run(download,item ).addErrback(self.errorIconDownload, item).addCallback(self.finishedIconDownload,item) for item in IconDownloadList]
236 finished = defer.DeferredList(downloads).addErrback(self.error)
239 self.session.openWithCallback(self.setupFinished, WeatherPluginEntriesListConfigScreen)
241 def setupFinished(self, index, entry = None):
242 self.weatherPluginEntryCount = config.plugins.WeatherPlugin.entriescount.value
243 if self.weatherPluginEntryCount >= 1:
244 if entry is not None:
245 self.weatherPluginEntry = entry
246 self.weatherPluginEntryIndex = index + 1
247 if self.weatherPluginEntry is None:
248 self.weatherPluginEntry = config.plugins.WeatherPlugin.Entries[0]
249 self.weatherPluginEntryIndex = 1
251 self.weatherPluginEntry = None
252 self.weatherPluginEntryIndex = -1
257 def error(self, error = None):
258 if error is not None:
260 self["statustext"].text = str(error.getErrorMessage())
263 class WeatherIcon(Pixmap):
265 Pixmap.__init__(self)
266 self.IconFileName = ""
267 self.picload = ePicLoad()
268 self.picload.PictureData.get().append(self.paintIconPixmapCB)
272 sc = AVSwitch().getFramebufferScale()
273 self.picload.setPara((self.instance.size().width(), self.instance.size().height(), sc[0], sc[1], 0, 0, '#00000000'))
275 def paintIconPixmapCB(self, picInfo=None):
276 ptr = self.picload.getData()
278 self.instance.setPixmap(ptr.__deref__())
280 def updateIcon(self, filename):
281 new_IconFileName = filename
282 if (self.IconFileName != new_IconFileName):
283 self.IconFileName = new_IconFileName
284 self.picload.startDecode(self.IconFileName)