SystemPlugins/WirelessLan: - replace manual wlan scan in favour of an automatic wlan...
[vuplus_dvbapp] / 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()    
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 class WlanScan(Screen):
155         skin = """
156                 <screen name="WlanScan" position="center,center" size="560,400" title="Choose a Wireless Network" >
157                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
158                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
159                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
160                         <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" />
161                         <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" />
162                         <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" />
163                         <widget source="list" render="Listbox" position="5,40" size="550,300" scrollbarMode="showOnDemand">
164                                 <convert type="TemplatedMultiContent">
165                                         {"template": [
166                                                         MultiContentEntryText(pos = (0, 0), size = (550, 30), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the essid
167                                                         MultiContentEntryText(pos = (0, 30), size = (175, 20), font=1, flags = RT_HALIGN_LEFT, text = 5), # index 5 is the interface
168                                                         MultiContentEntryText(pos = (175, 30), size = (175, 20), font=1, flags = RT_HALIGN_LEFT, text = 4), # index 0 is the encryption
169                                                         MultiContentEntryText(pos = (350, 0), size = (200, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 0 is the signal
170                                                         MultiContentEntryText(pos = (350, 30), size = (200, 20), font=1, flags = RT_HALIGN_LEFT, text = 3), # index 0 is the maxrate
171                                                         MultiContentEntryPixmapAlphaTest(pos = (0, 52), size = (550, 2), png = 6), # index 6 is the div pixmap
172                                                 ],
173                                         "fonts": [gFont("Regular", 28),gFont("Regular", 18)],
174                                         "itemHeight": 54
175                                         }
176                                 </convert>
177                         </widget>
178                         <ePixmap pixmap="skin_default/div-h.png" position="0,340" zPosition="1" size="560,2" />         
179                         <widget source="info" render="Label" position="0,350" size="560,50" font="Regular;24" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
180                 </screen>"""
181
182         def __init__(self, session, iface):
183                 Screen.__init__(self, session)
184                 self.session = session
185                 self.iface = iface
186                 self.skin_path = plugin_path
187                 self.oldInterfaceState = iNetwork.getAdapterAttribute(self.iface, "up")
188                 self.APList = None
189                 self.newAPList = None
190                 self.WlanList = None
191                 self.cleanList = None
192                 self.oldlist = None
193                 self.listLenght = None
194                 self.rescanTimer = eTimer()
195                 self.rescanTimer.callback.append(self.rescanTimerFired)
196                 
197                 self["info"] = StaticText()
198                 
199                 self.list = []
200                 self["list"] = List(self.list)
201                 
202                 self["key_red"] = StaticText(_("Close"))
203                 self["key_green"] = StaticText(_("Connect"))
204                 self["key_yellow"] = StaticText()
205                         
206                 self["actions"] = NumberActionMap(["WizardActions", "InputActions", "EPGSelectActions"],
207                 {
208                         "ok": self.select,
209                         "back": self.cancel,
210                 }, -1)
211                 
212                 self["shortcuts"] = ActionMap(["ShortcutActions"],
213                 {
214                         "red": self.cancel,
215                         "green": self.select,
216                 })
217                 self.onLayoutFinish.append(self.layoutFinished)
218                 self.getAccessPoints(refresh = False)
219                 
220         def layoutFinished(self):
221                 self.setTitle(_("Choose a wireless network"))
222         
223         def select(self):
224                 cur = self["list"].getCurrent()
225                 if cur is not None:
226                         self.rescanTimer.stop()
227                         del self.rescanTimer
228                         if cur[1] is not None:
229                                 essid = cur[1]
230                                 self.close(essid,self.getWlanList())
231                         else:
232                                 self.close(None,None)
233                 else:
234                         self.rescanTimer.stop()
235                         del self.rescanTimer
236                         self.close(None,None)
237         
238         def WlanSetupClosed(self, *ret):
239                 if ret[0] == 2:
240                         self.rescanTimer.stop()
241                         del self.rescanTimer
242                         self.close(None)
243         
244         def cancel(self):
245                 if self.oldInterfaceState is False:
246                         iNetwork.setAdapterAttribute(self.iface, "up", False)
247                         iNetwork.deactivateInterface(self.iface,self.deactivateInterfaceCB)
248                 else:
249                         self.rescanTimer.stop()
250                         del self.rescanTimer
251                         self.close(None)
252
253         def deactivateInterfaceCB(self,data):
254                 if data is not None:
255                         if data is True:
256                                 self.rescanTimer.stop()
257                                 del self.rescanTimer
258                                 self.close(None)
259
260         def rescanTimerFired(self):
261                 self.rescanTimer.stop()
262                 self.updateAPList()
263
264         def buildEntryComponent(self, essid, bssid, encrypted, iface, maxrate, signal):
265                 print "buildEntryComponent",essid
266                 print "buildEntryComponent",bssid
267                 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
268                 encryption = encrypted and _("Yes") or _("No")
269                 if bssid == 'hidden...':
270                         return((essid, bssid, None, None, None, None, divpng))
271                 else:                                   
272                         return((essid, bssid, _("Signal: ") + str(signal), _("Max. Bitrate: ") + str(maxrate), _("Encrypted: ") + encryption, _("Interface: ") + str(iface), divpng))
273
274         def updateAPList(self):
275                 self.oldlist = []
276                 self.oldlist = self.cleanList
277                 self.newAPList = []
278                 newList = []
279                 tmpList = []
280                 newListIndex = None
281                 currentListEntry = None
282                 currentListIndex = None
283                 newList = self.getAccessPoints(refresh = True)
284                 
285                 for oldentry in self.oldlist:
286                         if oldentry not in newList:
287                                 newList.append(oldentry)
288
289                 for newentry in newList:
290                         if newentry[1] == "hidden...":
291                                 continue
292                         tmpList.append(newentry)
293
294                 if len(tmpList):
295                         if "hidden..." not in tmpList:
296                                 tmpList.append( ( _("enter hidden network SSID"), "hidden...", True, self.iface, _("unavailable"), "" ) )
297         
298                         for entry in tmpList:
299                                 self.newAPList.append(self.buildEntryComponent( entry[0], entry[1], entry[2], entry[3], entry[4], entry[5] ))
300         
301                         currentListEntry = self["list"].getCurrent()
302                         idx = 0
303                         for entry in self.newAPList:
304                                 if entry == currentListEntry:
305                                         newListIndex = idx
306                                 idx +=1
307                         self['list'].setList(self.newAPList)
308                         self["list"].setIndex(newListIndex)
309                         self["list"].updateList(self.newAPList)
310                         self.listLenght = len(self.newAPList)
311                         self.buildWlanList()
312                         self.setInfo()
313
314         def getAccessPoints(self, refresh = False):
315                 self.APList = []
316                 self.cleanList = []
317                 self.w = Wlan(self.iface)
318                 aps = self.w.getNetworkList()
319                 if aps is not None:
320                         print "[NetworkWizard.py] got Accespoints!"
321                         tmpList = []
322                         compList = []
323                         for ap in aps:
324                                 a = aps[ap]
325                                 if a['active']:
326                                         tmpList.append( (a['essid'], a['bssid']) )
327                                         compList.append( (a['essid'], a['bssid'], a['encrypted'], a['iface'], a['maxrate'], a['signal']) )
328
329                         for entry in tmpList:
330                                 if entry[0] == "":
331                                         for compentry in compList:
332                                                 if compentry[1] == entry[1]:
333                                                         compList.remove(compentry)
334                         for entry in compList:
335                                 self.cleanList.append( ( entry[0], entry[1], entry[2], entry[3], entry[4], entry[5] ) )
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.listLenght = 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 == 0:
353                         self["info"].setText(_("No wireless networks found! Please refresh."))
354                 elif length == 1:
355                         self["info"].setText(_("1 wireless network found!"))
356                 else:
357                         self["info"].setText(str(length)+_(" wireless networks found!"))
358
359         def buildWlanList(self):
360                 self.WlanList = []
361                 currList = []
362                 currList = self['list'].list
363                 for entry in currList:
364                         self.WlanList.append( (entry[1], entry[0]) )            
365
366         def getLength(self):
367                 return self.listLenght          
368
369         def getWlanList(self):
370                 return self.WlanList
371
372
373 def WlanStatusScreenMain(session, iface):
374         session.open(WlanStatus, iface)
375
376
377 def callFunction(iface):
378         w = Wlan(iface)
379         i = w.getWirelessInterfaces()
380         if i:
381                 if iface in i:
382                         return WlanStatusScreenMain
383         return None
384
385
386 def configStrings(iface):
387         driver = iNetwork.detectWlanModule()
388         print "Found WLAN-Driver:",driver
389         if driver  in ('ralink', 'zydas'):
390                 return "        pre-up /usr/sbin/wpa_supplicant -i"+iface+" -c/etc/wpa_supplicant.conf -B -D"+driver+"\n        post-down wpa_cli terminate"
391         else:
392                 if config.plugins.wlan.essid.value == "hidden...":
393                         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'
394                 else:
395                         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'
396
397 def Plugins(**kwargs):
398         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..."})
399