[WeatherPlugin] Because msn weather-api is dead, I switched from msn to yahoo. Saved...
[enigma2-plugins.git] / weatherplugin / src / plugin.py
1 # -*- coding: utf-8 -*-
2 #
3 # WeatherPlugin E2
4 #
5 # Coded by Dr.Best (c) 2012
6 # Support: www.dreambox-tools.info
7 # E-Mail: dr.best@dreambox-tools.info
8 #
9 # This plugin is open source but it is NOT free software.
10 #
11 # This plugin may only be distributed to and executed on hardware which
12 # is licensed by Dream Multimedia GmbH.
13 # In other words:
14 # It's NOT allowed to distribute any parts of this plugin or its source code in ANY way
15 # to hardware which is NOT licensed by Dream Multimedia GmbH.
16 # It's NOT allowed to execute this plugin and its source code or even parts of it in ANY way
17 # on hardware which is NOT licensed by Dream Multimedia GmbH.
18 #
19 # If you want to use or modify the code or parts of it,
20 # you have to keep MY license and inform me about the modifications by mail.
21 #
22 from Plugins.Plugin import PluginDescriptor
23 from Screens.Screen import Screen
24 from Components.ActionMap import ActionMap
25 from Components.Sources.StaticText import StaticText
26 from Components.Pixmap import Pixmap
27 from enigma import ePicLoad, eRect, eSize, gPixmapPtr
28 from Components.AVSwitch import AVSwitch
29 from Components.config import ConfigSubsection, ConfigSubList, ConfigInteger, config
30 from setup import initConfig, MSNWeatherPluginEntriesListConfigScreen
31 from MSNWeather import MSNWeather
32 import time
33
34 try:
35         from Components.WeatherMSN import weathermsn
36         WeatherMSNComp = weathermsn
37 except:
38         WeatherMSNComp = None
39
40 config.plugins.WeatherPlugin = ConfigSubsection()
41 config.plugins.WeatherPlugin.entrycount =  ConfigInteger(0)
42 config.plugins.WeatherPlugin.Entry = ConfigSubList()
43 initConfig()
44
45
46 def main(session,**kwargs):
47         session.open(MSNWeatherPlugin)
48
49 def Plugins(**kwargs):
50         list = [PluginDescriptor(name=_("Weather Plugin"), description=_("Show Weather Forecast"), where = [PluginDescriptor.WHERE_PLUGINMENU, PluginDescriptor.WHERE_EXTENSIONSMENU], icon = "weather.png", fnc=main)]
51         return list
52
53 class MSNWeatherPlugin(Screen):
54
55         skin = """
56                 <screen name="MSNWeatherPlugin" position="center,center" size="720,400" title="Weather Plugin">
57                         <widget render="Label" source="caption" position="10,10" size="700,30" font="Regular;24"/>
58                         <widget render="Label" source="observationtime" position="430,45" size="280,25" font="Regular;16" halign="right" />
59                         <widget render="Label" source="observationpoint" position="110,70" size="600,25" font="Regular;16" halign="right" />
60                         <widget name="currenticon" position="10,115" size="55,45" alphatest="on"/>
61                         <widget render="Label" source="currentTemp" position="90,115" size="100,23" font="Regular;22"/>
62                         <widget render="Label" source="feelsliketemp" position="90,150" size="140,20" font="Regular;14"/>
63                         <widget render="Label" source="condition" position="320,115" size="380,20" font="Regular;18"/>
64                         <widget render="Label" source="wind_condition" position="320,145" size="380,20" font="Regular;18"/>
65                         <widget render="Label" source="humidity" position="320,165" size="380,20" font="Regular;18" valign="bottom"/>
66                         <widget render="Label" source="weekday1" position="35,210" size="105,40" halign="center" valign="center" font="Regular;18"/>
67                         <widget name="weekday1_icon" position="60,265" size="55,45" alphatest="on"/>
68                         <widget render="Label" source="weekday1_temp" position="35,320" size="105,60" halign="center" valign="top" font="Regular;16"/>
69                         <widget render="Label" source="weekday2" position="175,210" size="105,40" halign="center" valign="top" font="Regular;18"/>
70                         <widget name="weekday2_icon" position="200,265" size="55,45" alphatest="on"/>
71                         <widget render="Label" source="weekday2_temp" position="175,320" size="105,60" halign="center" valign="top" font="Regular;16"/>
72                         <widget render="Label" source="weekday3" position="315,210" size="105,40" halign="center" valign="top" font="Regular;18"/>
73                         <widget name="weekday3_icon" position="340,265" size="55,45" alphatest="on"/>
74                         <widget render="Label" source="weekday3_temp" position="315,320" size="105,60" halign="center" valign="top" font="Regular;16"/>
75                         <widget render="Label" source="weekday4" position="455,210" size="105,40" halign="center" valign="top" font="Regular;18"/>
76                         <widget name="weekday4_icon" position="480,265" size="55,45" alphatest="on"/>
77                         <widget render="Label" source="weekday4_temp" position="455,320" size="105,60" halign="center" valign="top" font="Regular;16"/>
78                         <widget render="Label" source="weekday5" position="595,210" size="105,40" halign="center" valign="top" font="Regular;18"/>
79                         <widget name="weekday5_icon" position="620,265" size="55,45" alphatest="on"/>
80                         <widget render="Label" source="weekday5_temp" position="595,320" size="105,60" halign="center" valign="top" font="Regular;16"/>
81                         <widget render="Label" source="statustext" position="0,0" size="720,400" font="Regular;20" halign="center" valign="center" transparent="1"/>
82                 </screen>"""
83         
84         def __init__(self, session):
85                 Screen.__init__(self, session)
86                 self.title = _("Weather Plugin")
87                 self["actions"] = ActionMap(["WizardActions", "DirectionActions", "ColorActions", "EPGSelectActions"],
88                 {
89                         "back": self.close,
90                         "input_date_time": self.config,
91                         "right": self.nextItem,
92                         "left": self.previousItem,
93                         "info": self.showWebsite
94                 }, -1)
95
96                 self["statustext"] = StaticText()
97                 self["currenticon"] = WeatherIcon()
98                 self["caption"] = StaticText()
99                 self["currentTemp"] = StaticText()
100                 self["condition"] = StaticText()
101                 self["wind_condition"] = StaticText()
102                 self["humidity"] = StaticText()
103                 self["observationtime"] = StaticText()
104                 self["observationpoint"] = StaticText()
105                 self["feelsliketemp"] = StaticText()
106                 
107                 i = 1
108                 while i <= 5:
109                         self["weekday%s" % i] = StaticText()
110                         self["weekday%s_icon" %i] = WeatherIcon()
111                         self["weekday%s_temp" % i] = StaticText()
112                         i += 1
113                 del i
114                 
115
116                 self.weatherPluginEntryIndex = -1
117                 self.weatherPluginEntryCount = config.plugins.WeatherPlugin.entrycount.value
118                 if self.weatherPluginEntryCount >= 1:
119                         self.weatherPluginEntry = config.plugins.WeatherPlugin.Entry[0]
120                         self.weatherPluginEntryIndex = 1
121                 else:
122                         self.weatherPluginEntry = None
123
124
125                 self.webSite = ""
126                 
127                 self.weatherData = None
128                 self.onLayoutFinish.append(self.startRun)
129                 self.onClose.append(self.__onClose)
130                 
131         def __onClose(self):
132                 if self.weatherData is not None:
133                         self.weatherData.cancel()
134
135         def startRun(self):
136                 if self.weatherPluginEntry is not None:
137                         self["statustext"].text = _("Getting weather information...")
138                         if self.weatherData is not None:
139                                 self.weatherData.cancel()
140                                 self.weatherData = None
141                         self.weatherData = MSNWeather()
142                         self.weatherData.getWeatherData(self.weatherPluginEntry.degreetype.value, self.weatherPluginEntry.weatherlocationcode.value, self.weatherPluginEntry.city.value, self.getWeatherDataCallback, self.showIcon)
143                 else:
144                         self["statustext"].text = _("No locations defined...\nPress 'Menu' to do that.")
145
146         def nextItem(self):
147                 if self.weatherPluginEntryCount != 0:
148                         if self.weatherPluginEntryIndex < self.weatherPluginEntryCount:
149                                 self.weatherPluginEntryIndex = self.weatherPluginEntryIndex + 1
150                         else:
151                                 self.weatherPluginEntryIndex = 1
152                         self.setItem()
153
154         def previousItem(self):
155                 if self.weatherPluginEntryCount != 0:
156                         if self.weatherPluginEntryIndex >= 2:
157                                 self.weatherPluginEntryIndex = self.weatherPluginEntryIndex - 1
158                         else:
159                                 self.weatherPluginEntryIndex = self.weatherPluginEntryCount
160                         self.setItem()
161
162         def setItem(self):
163                 self.weatherPluginEntry = config.plugins.WeatherPlugin.Entry[self.weatherPluginEntryIndex-1]
164                 self.clearFields()
165                 self.startRun()
166
167         def clearFields(self):
168                 self["caption"].text = ""
169                 self["currentTemp"].text = ""
170                 self["condition"].text = ""
171                 self["wind_condition"].text = ""
172                 self["humidity"].text = ""
173                 self["observationtime"].text = ""
174                 self["observationpoint"].text = ""
175                 self["feelsliketemp"].text = ""
176                 self["currenticon"].hide()
177                 self.webSite = ""
178                 i = 1
179                 while i <= 5:
180                         self["weekday%s" % i].text = ""
181                         self["weekday%s_icon" %i].hide()
182                         self["weekday%s_temp" % i].text = ""
183                         i += 1
184
185         def showIcon(self,index, filename):
186                 if index <> -1:
187                         self["weekday%s_icon" % index].updateIcon(filename)
188                         self["weekday%s_icon" % index].show()
189                 else:
190                         self["currenticon"].updateIcon(filename)
191                         self["currenticon"].show()
192
193         def getWeatherDataCallback(self, result, errortext):
194                 self["statustext"].text = ""
195                 if result == MSNWeather.ERROR:
196                         self.error(errortext)
197                 else:
198                         self["caption"].text = self.weatherData.city
199                         self.webSite = self.weatherData.url
200                         for weatherData in self.weatherData.weatherItems.items():
201                                 item = weatherData[1]
202                                 if weatherData[0] == "-1": # current
203                                         self["currentTemp"].text = "%s%s" % (item.temperature, self.weatherData.degreetype)
204                                         self["condition"].text = item.skytext
205                                         self["humidity"].text = _("Humidity: %s %%") % item.humidity
206                                         self["wind_condition"].text = item.winddisplay
207                                         self["observationtime"].text = _("Observation time: %s") %  item.observationtime
208                                         self["observationpoint"].text = "" #_("Observation point: %s") % item.observationpoint
209                                         if item.feelslike != "":
210                                                 self["feelsliketemp"].text = _("Feels like %s") % item.feelslike + "" +  self.weatherData.degreetype
211                                         else:
212                                                 self["feelsliketemp"].text = ""
213                                 else:
214                                         index = weatherData[0]
215                                         c = time.strptime(item.date,"%d %m %Y")
216                                         self["weekday%s" % index].text = "%s\n%s" % (item.day, time.strftime("%d.%m",c))
217                                         lowTemp = item.low
218                                         highTemp = item.high
219                                         self["weekday%s_temp" % index].text = "%s%s|%s%s\n%s" % (highTemp, self.weatherData.degreetype, lowTemp, self.weatherData.degreetype, item.skytextday)
220                 
221                 if self.weatherPluginEntryIndex == 1 and WeatherMSNComp is not None:
222                         WeatherMSNComp.updateWeather(self.weatherData, result, errortext)
223
224         def config(self):
225                 self.session.openWithCallback(self.setupFinished, MSNWeatherPluginEntriesListConfigScreen)
226
227         def setupFinished(self, index, entry = None):
228                 self.weatherPluginEntryCount = config.plugins.WeatherPlugin.entrycount.value
229                 if self.weatherPluginEntryCount >= 1:
230                         if entry is not None:
231                                 self.weatherPluginEntry = entry
232                                 self.weatherPluginEntryIndex = index + 1
233                         if self.weatherPluginEntry is None:
234                                 self.weatherPluginEntry = config.plugins.WeatherPlugin.Entry[0]
235                                 self.weatherPluginEntryIndex = 1
236                 else:
237                         self.weatherPluginEntry = None
238                         self.weatherPluginEntryIndex = -1
239
240                 self.clearFields()
241                 self.startRun()
242
243         def error(self, errortext):
244                 self.clearFields()
245                 self["statustext"].text = errortext
246
247         def showWebsite(self):
248                 try:
249                         from Plugins.Extensions.Browser.Browser import Browser
250                         if self.webSite:
251                                 self.session.open(Browser, config.plugins.WebBrowser.fullscreen.value, self.webSite, False)
252                 except: pass # I dont care if browser is installed or not...
253
254 class WeatherIcon(Pixmap):
255         def __init__(self):
256                 Pixmap.__init__(self)
257                 self.IconFileName = ""
258                 self.picload = ePicLoad()
259                 self.picload_conn = self.picload.PictureData.connect(self.paintIconPixmapCB)
260
261         def onShow(self):
262                 Pixmap.onShow(self)
263                 sc = AVSwitch().getFramebufferScale()
264                 self._aspectRatio = eSize(sc[0], sc[1])
265                 self._scaleSize = self.instance.size()
266                 self.picload.setPara((self._scaleSize.width(), self._scaleSize.height(), sc[0], sc[1], True, 2, '#ff000000'))
267
268         def paintIconPixmapCB(self, picInfo=None):
269                 ptr = self.picload.getData()
270                 if ptr is not None:
271                         pic_scale_size = eSize()
272                         # To be added in the future:
273                         if 'scale' in eSize.__dict__ and self._scaleSize.isValid() and self._aspectRatio.isValid():
274                                 pic_scale_size = ptr.size().scale(self._scaleSize, self._aspectRatio)
275                         # To be removed in the future:
276                         elif 'scaleSize' in gPixmapPtr.__dict__:
277                                 pic_scale_size = ptr.scaleSize()
278
279                         if pic_scale_size.isValid():
280                                 pic_scale_width = pic_scale_size.width()
281                                 pic_scale_height = pic_scale_size.height()
282                                 dest_rect = eRect(0, 0, pic_scale_width, pic_scale_height)
283                                 self.instance.setScale(1)
284                                 self.instance.setScaleDest(dest_rect)
285                         else:
286                                 self.instance.setScale(0)
287                         self.instance.setPixmap(ptr)
288                 else:
289                         self.instance.setPixmap(None)
290                 
291         def updateIcon(self, filename):
292                 new_IconFileName = filename
293                 if (self.IconFileName != new_IconFileName):
294                         self.IconFileName = new_IconFileName
295                         self.picload.startDecode(self.IconFileName)
296