Merge commit 'origin/bug_478_Listbox_ScrollbarMode'
[enigma2.git] / lib / python / Plugins / SystemPlugins / WirelessLan / plugin.py
1 from enigma import eTimer
2 from Screens.Screen import Screen
3 from Components.ActionMap import ActionMap, NumberActionMap
4 from Components.Pixmap import Pixmap,MultiPixmap
5 from Components.Label import Label
6 from Components.Sources.StaticText import StaticText
7 from Components.Sources.List import List
8 from Components.MenuList import MenuList
9 from Components.config import config, getConfigListEntry, ConfigYesNo, NoSave, ConfigSubsection, ConfigText, ConfigSelection, ConfigPassword
10 from Components.ConfigList import ConfigListScreen
11 from Components.Network import Network, iNetwork
12 from Components.Console import Console
13 from Plugins.Plugin import PluginDescriptor
14 from os import system, path as os_path, listdir
15 from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE
16 from Tools.LoadPixmap import LoadPixmap
17 from Wlan import Wlan, wpaSupplicant, iStatus
18
19 plugin_path = "/usr/lib/enigma2/python/Plugins/SystemPlugins/WirelessLan"
20
21 list = []
22 list.append("WEP")
23 list.append("WPA")
24 list.append("WPA2")
25 list.append("WPA/WPA2")
26
27 weplist = []
28 weplist.append("ASCII")
29 weplist.append("HEX")
30
31 config.plugins.wlan = ConfigSubsection()
32 config.plugins.wlan.essid = NoSave(ConfigText(default = "home", fixed_size = False))
33 config.plugins.wlan.hiddenessid = NoSave(ConfigText(default = "home", fixed_size = False))
34
35 config.plugins.wlan.encryption = ConfigSubsection()
36 config.plugins.wlan.encryption.enabled = NoSave(ConfigYesNo(default = False))
37 config.plugins.wlan.encryption.type = NoSave(ConfigSelection(list, default = "WPA/WPA2" ))
38 config.plugins.wlan.encryption.wepkeytype = NoSave(ConfigSelection(weplist, default = "ASCII"))
39 config.plugins.wlan.encryption.psk = NoSave(ConfigPassword(default = "mysecurewlan", fixed_size = False))
40
41
42 class WlanStatus(Screen):
43         skin = """
44                 <screen name="WlanStatus" position="center,center" size="560,400" title="Wireless Network State" >
45                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
46                         <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
47         
48                         <widget source="LabelBSSID" render="Label" position="10,60" size="250,25" valign="left" font="Regular;20" transparent="1" foregroundColor="#FFFFFF" />
49                         <widget source="LabelESSID" render="Label" position="10,100" size="250,25" valign="center" font="Regular;20" transparent="1" foregroundColor="#FFFFFF" />
50                         <widget source="LabelQuality" render="Label" position="10,140" size="250,25" valign="center" font="Regular;20" transparent="1" foregroundColor="#FFFFFF" />
51                         <widget source="LabelSignal" render="Label" position="10,180" size="250,25" valign="center" font="Regular;20" transparent="1" foregroundColor="#FFFFFF" />
52                         <widget source="LabelBitrate" render="Label" position="10,220" size="250,25" valign="center" font="Regular;20" transparent="1" foregroundColor="#FFFFFF" />
53                         <widget source="LabelEnc" render="Label" position="10,260" size="250,25" valign="center" font="Regular;20" transparent="1" foregroundColor="#FFFFFF" />
54                         
55                         <widget source="BSSID" render="Label" position="320,60" size="180,25" valign="center" font="Regular;20" transparent="1" foregroundColor="#FFFFFF" />
56                         <widget source="ESSID" render="Label" position="320,100" size="180,25" valign="center" font="Regular;20" transparent="1" foregroundColor="#FFFFFF" />
57                         <widget source="quality" render="Label" position="320,140" size="180,25" valign="center" font="Regular;20" transparent="1" foregroundColor="#FFFFFF" />
58                         <widget source="signal" render="Label" position="320,180" size="180,25" valign="center" font="Regular;20" transparent="1" foregroundColor="#FFFFFF" />
59                         <widget source="bitrate" render="Label" position="320,220" size="180,25" valign="center" font="Regular;20" transparent="1" foregroundColor="#FFFFFF" />
60                         <widget source="enc" render="Label" position="320,260" size="180,25" valign="center" font="Regular;20" transparent="1" foregroundColor="#FFFFFF" />
61         
62                         <ePixmap pixmap="skin_default/div-h.png" position="0,350" zPosition="1" size="560,2" />         
63                         <widget source="IFtext" render="Label" position="10,355" size="120,21" zPosition="10" font="Regular;20" halign="left" backgroundColor="#25062748" transparent="1" />
64                         <widget source="IF" render="Label" position="120,355" size="400,21" zPosition="10" font="Regular;20" halign="left" backgroundColor="#25062748" transparent="1" />
65                         <widget source="Statustext" render="Label" position="10,375" size="115,21" zPosition="10" font="Regular;20" halign="left" backgroundColor="#25062748" transparent="1"/>
66                         <widget name="statuspic" pixmaps="skin_default/buttons/button_green.png,skin_default/buttons/button_green_off.png" position="130,380" zPosition="10" size="15,16" transparent="1" alphatest="on"/>
67                 </screen>"""
68         
69         def __init__(self, session, iface):
70                 Screen.__init__(self, session)
71                 self.session = session
72                 self.iface = iface
73                                     
74                 self["LabelBSSID"] = StaticText(_('Accesspoint:'))
75                 self["LabelESSID"] = StaticText(_('SSID:'))
76                 self["LabelQuality"] = StaticText(_('Link Quality:'))
77                 self["LabelSignal"] = StaticText(_('Signal Strength:'))
78                 self["LabelBitrate"] = StaticText(_('Bitrate:'))
79                 self["LabelEnc"] = StaticText(_('Encryption:'))
80                         
81                 self["BSSID"] = StaticText()
82                 self["ESSID"] = StaticText()
83                 self["quality"] = StaticText()
84                 self["signal"] = StaticText()
85                 self["bitrate"] = StaticText()
86                 self["enc"] = StaticText()
87
88                 self["IFtext"] = StaticText()
89                 self["IF"] = StaticText()
90                 self["Statustext"] = StaticText()
91                 self["statuspic"] = MultiPixmap()
92                 self["statuspic"].hide()
93                 self["key_red"] = StaticText(_("Close"))
94
95                 self.resetList()
96                 self.updateStatusbar()
97                 
98                 self["actions"] = NumberActionMap(["WizardActions", "InputActions", "EPGSelectActions", "ShortcutActions"],
99                 {
100                         "ok": self.exit,
101                         "back": self.exit,
102                         "red": self.exit,
103                 }, -1)
104                 self.timer = eTimer()
105                 self.timer.timeout.get().append(self.resetList) 
106                 self.onShown.append(lambda: self.timer.start(5000))
107                 self.onLayoutFinish.append(self.layoutFinished)
108                 self.onClose.append(self.cleanup)
109
110         def cleanup(self):
111                 iStatus.stopWlanConsole()
112                 
113         def layoutFinished(self):
114                 self.setTitle(_("Wireless Network State"))
115                 
116         def resetList(self):
117                 iStatus.getDataForInterface(self.iface,self.getInfoCB)
118                 
119         def getInfoCB(self,data,status):
120                 if data is not None:
121                         if data is True:
122                                 if status is not None:
123                                         self["BSSID"].setText(status[self.iface]["acesspoint"])
124                                         self["ESSID"].setText(status[self.iface]["essid"])
125                                         self["quality"].setText(status[self.iface]["quality"]+"%")
126                                         self["signal"].setText(status[self.iface]["signal"])
127                                         self["bitrate"].setText(status[self.iface]["bitrate"])
128                                         self["enc"].setText(status[self.iface]["encryption"])
129                                         self.updateStatusLink(status)
130
131         def exit(self):
132                 self.timer.stop()
133                 self.close(True)        
134
135         def updateStatusbar(self):
136                 self["BSSID"].setText(_("Please wait..."))
137                 self["ESSID"].setText(_("Please wait..."))
138                 self["quality"].setText(_("Please wait..."))
139                 self["signal"].setText(_("Please wait..."))
140                 self["bitrate"].setText(_("Please wait..."))
141                 self["enc"].setText(_("Please wait..."))
142                 self["IFtext"].setText(_("Network:"))
143                 self["IF"].setText(iNetwork.getFriendlyAdapterName(self.iface))
144                 self["Statustext"].setText(_("Link:"))
145
146         def updateStatusLink(self,status):
147                 if status is not None:
148                         if status[self.iface]["acesspoint"] == "No Connection" or status[self.iface]["acesspoint"] == "Not-Associated" or status[self.iface]["acesspoint"] == False:
149                                 self["statuspic"].setPixmapNum(1)
150                         else:
151                                 self["statuspic"].setPixmapNum(0)
152                         self["statuspic"].show()                
153
154
155 class WlanScan(Screen):
156         skin = """
157                 <screen name="WlanScan" position="center,center" size="560,400" title="Choose a Wireless Network" >
158                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
159                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
160                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
161                         <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
162                         <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
163                         <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
164                         <widget source="list" render="Listbox" position="5,40" size="550,300" scrollbarMode="showOnDemand">
165                                 <convert type="TemplatedMultiContent">
166                                         {"template": [
167                                                         MultiContentEntryText(pos = (0, 0), size = (550, 30), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the essid
168                                                         MultiContentEntryText(pos = (0, 30), size = (175, 20), font=1, flags = RT_HALIGN_LEFT, text = 5), # index 5 is the interface
169                                                         MultiContentEntryText(pos = (175, 30), size = (175, 20), font=1, flags = RT_HALIGN_LEFT, text = 4), # index 0 is the encryption
170                                                         MultiContentEntryText(pos = (350, 0), size = (200, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 0 is the signal
171                                                         MultiContentEntryText(pos = (350, 30), size = (200, 20), font=1, flags = RT_HALIGN_LEFT, text = 3), # index 0 is the maxrate
172                                                         MultiContentEntryPixmapAlphaTest(pos = (0, 52), size = (550, 2), png = 6), # index 6 is the div pixmap
173                                                 ],
174                                         "fonts": [gFont("Regular", 28),gFont("Regular", 18)],
175                                         "itemHeight": 54
176                                         }
177                                 </convert>
178                         </widget>
179                         <ePixmap pixmap="skin_default/div-h.png" position="0,340" zPosition="1" size="560,2" />         
180                         <widget source="info" render="Label" position="0,350" size="560,50" font="Regular;24" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
181                 </screen>"""
182
183         def __init__(self, session, iface):
184                 Screen.__init__(self, session)
185                 self.session = session
186                 self.iface = iface
187                 self.skin_path = plugin_path
188                 self.oldInterfaceState = iNetwork.getAdapterAttribute(self.iface, "up")
189                 self.APList = None
190                 self.newAPList = None
191                 self.WlanList = None
192                 self.cleanList = None
193                 self.oldlist = {}
194                 self.listLength = None
195                 self.rescanTimer = eTimer()
196                 self.rescanTimer.callback.append(self.rescanTimerFired)
197                 
198                 self["info"] = StaticText()
199                 
200                 self.list = []
201                 self["list"] = List(self.list)
202                 
203                 self["key_red"] = StaticText(_("Close"))
204                 self["key_green"] = StaticText(_("Connect"))
205                 self["key_yellow"] = StaticText()
206                         
207                 self["actions"] = NumberActionMap(["WizardActions", "InputActions", "EPGSelectActions"],
208                 {
209                         "ok": self.select,
210                         "back": self.cancel,
211                 }, -1)
212                 
213                 self["shortcuts"] = ActionMap(["ShortcutActions"],
214                 {
215                         "red": self.cancel,
216                         "green": self.select,
217                 })
218                 self.onLayoutFinish.append(self.layoutFinished)
219                 self.getAccessPoints(refresh = False)
220                 
221         def layoutFinished(self):
222                 self.setTitle(_("Choose a wireless network"))
223         
224         def select(self):
225                 cur = self["list"].getCurrent()
226                 if cur is not None:
227                         self.rescanTimer.stop()
228                         del self.rescanTimer
229                         if cur[1] is not None:
230                                 if cur[1] == 'hidden...':
231                                         essid = cur[1]
232                                 else:
233                                         essid = cur[0]
234                                 self.close(essid,self.getWlanList())
235                         else:
236                                 self.close(None,None)
237                 else:
238                         self.rescanTimer.stop()
239                         del self.rescanTimer
240                         self.close(None,None)
241         
242         def WlanSetupClosed(self, *ret):
243                 if ret[0] == 2:
244                         self.rescanTimer.stop()
245                         del self.rescanTimer
246                         self.close(None)
247         
248         def cancel(self):
249                 if self.oldInterfaceState is False:
250                         iNetwork.setAdapterAttribute(self.iface, "up", False)
251                         iNetwork.deactivateInterface(self.iface,self.deactivateInterfaceCB)
252                 else:
253                         self.rescanTimer.stop()
254                         del self.rescanTimer
255                         self.close(None)
256
257         def deactivateInterfaceCB(self,data):
258                 if data is not None:
259                         if data is True:
260                                 self.rescanTimer.stop()
261                                 del self.rescanTimer
262                                 self.close(None)
263
264         def rescanTimerFired(self):
265                 self.rescanTimer.stop()
266                 self.updateAPList()
267
268         def buildEntryComponent(self, essid, bssid, encrypted, iface, maxrate, signal):
269                 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
270                 encryption = encrypted and _("Yes") or _("No")
271                 if bssid == 'hidden...':
272                         return((essid, bssid, None, None, None, None, divpng))
273                 else:                                   
274                         return((essid, bssid, _("Signal: ") + str(signal), _("Max. Bitrate: ") + str(maxrate), _("Encrypted: ") + encryption, _("Interface: ") + str(iface), divpng))
275
276         def updateAPList(self):
277                 newList = []
278                 newList = self.getAccessPoints(refresh = True)  
279                 self.newAPList = []
280                 tmpList = []
281                 newListIndex = None
282                 currentListEntry = None
283                 currentListIndex = None
284
285                 for ap in self.oldlist.keys():
286                         data = self.oldlist[ap]['data']
287                         if data is not None:
288                                 tmpList.append(data)
289
290                 if len(tmpList):
291                         if "hidden..." not in tmpList:
292                                 tmpList.append( ( _("enter hidden network SSID"), "hidden...", True, self.iface, _("unavailable"), "" ) )
293         
294                         for entry in tmpList:
295                                 self.newAPList.append(self.buildEntryComponent( entry[0], entry[1], entry[2], entry[3], entry[4], entry[5] ))
296         
297                         currentListEntry = self["list"].getCurrent()
298                         idx = 0
299                         for entry in self.newAPList:
300                                 if entry[0] == currentListEntry[0]:
301                                         newListIndex = idx
302                                 idx +=1
303                         self['list'].setList(self.newAPList)
304                         self["list"].setIndex(newListIndex)
305                         self["list"].updateList(self.newAPList)
306                         self.listLength = len(self.newAPList)
307                         self.buildWlanList()
308                         self.setInfo()
309
310         def getAccessPoints(self, refresh = False):
311                 self.APList = []
312                 self.cleanList = []
313                 self.w = Wlan(self.iface)
314                 aps = self.w.getNetworkList()
315                 if aps is not None:
316                         print "[WirelessLan.py] got Accespoints!"
317                         tmpList = []
318                         compList = []
319                         for ap in aps:
320                                 a = aps[ap]
321                                 if a['active']:
322                                         tmpList.append( (a['essid'], a['bssid']) )
323                                         compList.append( (a['essid'], a['bssid'], a['encrypted'], a['iface'], a['maxrate'], a['signal']) )
324
325                         for entry in tmpList:
326                                 if entry[0] == "":
327                                         for compentry in compList:
328                                                 if compentry[1] == entry[1]:
329                                                         compList.remove(compentry)
330                         for entry in compList:
331                                 self.cleanList.append( ( entry[0], entry[1], entry[2], entry[3], entry[4], entry[5] ) )
332                                 if not self.oldlist.has_key(entry[0]):
333                                         self.oldlist[entry[0]] = { 'data': entry }
334                                 else:
335                                         self.oldlist[entry[0]]['data'] = entry
336                 
337                 if "hidden..." not in self.cleanList:
338                         self.cleanList.append( ( _("enter hidden network SSID"), "hidden...", True, self.iface, _("unavailable"), "" ) )
339
340                 for entry in self.cleanList:
341                         self.APList.append(self.buildEntryComponent( entry[0], entry[1], entry[2], entry[3], entry[4], entry[5] ))
342                 
343                 if refresh is False:
344                         self['list'].setList(self.APList)
345                 self.listLength = len(self.APList)
346                 self.setInfo()
347                 self.rescanTimer.start(5000)
348                 return self.cleanList
349
350         def setInfo(self):
351                 length = self.getLength()
352                 if length <= 1:
353                         self["info"].setText(_("No wireless networks found! Please refresh."))
354                 elif length == 2:
355                         self["info"].setText(_("1 wireless network found!"))
356                 else:
357                         self["info"].setText(str(length-1)+_(" wireless networks found!"))
358
359         def buildWlanList(self):
360                 self.WlanList = []
361                 for entry in self['list'].list:
362                         if entry[1] == "hidden...":
363                                 self.WlanList.append(( "hidden...",_("enter hidden network SSID") ))#continue
364                         else:
365                                 self.WlanList.append( (entry[0], entry[0]) )
366
367         def getLength(self):
368                 return self.listLength          
369
370         def getWlanList(self):
371                 if self.WlanList is None:
372                         self.buildWlanList()
373                 return self.WlanList
374
375
376 def WlanStatusScreenMain(session, iface):
377         session.open(WlanStatus, iface)
378
379
380 def callFunction(iface):
381         w = Wlan(iface)
382         i = w.getWirelessInterfaces()
383         if i:
384                 if iface in i:
385                         return WlanStatusScreenMain
386         return None
387
388
389 def configStrings(iface):
390         driver = iNetwork.detectWlanModule()
391         print "Found WLAN-Driver:",driver
392         if driver  in ('ralink', 'zydas'):
393                 return "        pre-up /usr/sbin/wpa_supplicant -i"+iface+" -c/etc/wpa_supplicant.conf -B -D"+driver+"\n        post-down wpa_cli terminate"
394         else:
395                 if config.plugins.wlan.essid.value == "hidden...":
396                         return '        pre-up iwconfig '+iface+' essid "'+config.plugins.wlan.hiddenessid.value+'"\n   pre-up /usr/sbin/wpa_supplicant -i'+iface+' -c/etc/wpa_supplicant.conf -B -dd -D'+driver+'\n    post-down wpa_cli terminate'
397                 else:
398                         return '        pre-up iwconfig '+iface+' essid "'+config.plugins.wlan.essid.value+'"\n pre-up /usr/sbin/wpa_supplicant -i'+iface+' -c/etc/wpa_supplicant.conf -B -dd -D'+driver+'\n    post-down wpa_cli terminate'
399
400 def Plugins(**kwargs):
401         return PluginDescriptor(name=_("Wireless LAN"), description=_("Connect to a Wireless Network"), where = PluginDescriptor.WHERE_NETWORKSETUP, fnc={"ifaceSupported": callFunction, "configStrings": configStrings, "WlanPluginEntry": lambda x: "Wireless Network Configuartion..."})
402