Merge commit 'origin/bug_202_networkconfig_cleanup' into experimental
[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 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                 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
266                 encryption = encrypted and _("Yes") or _("No")
267                 if bssid == 'hidden...':
268                         return((essid, bssid, None, None, None, None, divpng))
269                 else:                                   
270                         return((essid, bssid, _("Signal: ") + str(signal), _("Max. Bitrate: ") + str(maxrate), _("Encrypted: ") + encryption, _("Interface: ") + str(iface), divpng))
271
272         def updateAPList(self):
273                 self.oldlist = []
274                 self.oldlist = self.cleanList
275                 self.newAPList = []
276                 newList = []
277                 tmpList = []
278                 newListIndex = None
279                 currentListEntry = None
280                 currentListIndex = None
281                 newList = self.getAccessPoints(refresh = True)
282                 
283                 for oldentry in self.oldlist:
284                         if oldentry not in newList:
285                                 newList.append(oldentry)
286
287                 for newentry in newList:
288                         if newentry[1] == "hidden...":
289                                 continue
290                         tmpList.append(newentry)
291
292                 if len(tmpList):
293                         if "hidden..." not in tmpList:
294                                 tmpList.append( ( _("enter hidden network SSID"), "hidden...", True, self.iface, _("unavailable"), "" ) )
295         
296                         for entry in tmpList:
297                                 self.newAPList.append(self.buildEntryComponent( entry[0], entry[1], entry[2], entry[3], entry[4], entry[5] ))
298         
299                         currentListEntry = self["list"].getCurrent()
300                         idx = 0
301                         for entry in self.newAPList:
302                                 if entry == currentListEntry:
303                                         newListIndex = idx
304                                 idx +=1
305                         self['list'].setList(self.newAPList)
306                         self["list"].setIndex(newListIndex)
307                         self["list"].updateList(self.newAPList)
308                         self.listLenght = len(self.newAPList)
309                         self.buildWlanList()
310                         self.setInfo()
311
312         def getAccessPoints(self, refresh = False):
313                 self.APList = []
314                 self.cleanList = []
315                 self.w = Wlan(self.iface)
316                 aps = self.w.getNetworkList()
317                 if aps is not None:
318                         print "[NetworkWizard.py] got Accespoints!"
319                         tmpList = []
320                         compList = []
321                         for ap in aps:
322                                 a = aps[ap]
323                                 if a['active']:
324                                         tmpList.append( (a['essid'], a['bssid']) )
325                                         compList.append( (a['essid'], a['bssid'], a['encrypted'], a['iface'], a['maxrate'], a['signal']) )
326
327                         for entry in tmpList:
328                                 if entry[0] == "":
329                                         for compentry in compList:
330                                                 if compentry[1] == entry[1]:
331                                                         compList.remove(compentry)
332                         for entry in compList:
333                                 self.cleanList.append( ( entry[0], entry[1], entry[2], entry[3], entry[4], entry[5] ) )
334                 
335                 if "hidden..." not in self.cleanList:
336                         self.cleanList.append( ( _("enter hidden network SSID"), "hidden...", True, self.iface, _("unavailable"), "" ) )
337
338                 for entry in self.cleanList:
339                         self.APList.append(self.buildEntryComponent( entry[0], entry[1], entry[2], entry[3], entry[4], entry[5] ))
340                 
341                 if refresh is False:
342                         self['list'].setList(self.APList)
343                 self.listLenght = len(self.APList)
344                 self.setInfo()
345                 self.rescanTimer.start(5000)
346                 return self.cleanList
347
348         def setInfo(self):
349                 length = self.getLength()
350                 if length == 0:
351                         self["info"].setText(_("No wireless networks found! Please refresh."))
352                 elif length == 1:
353                         self["info"].setText(_("1 wireless network found!"))
354                 else:
355                         self["info"].setText(str(length)+_(" wireless networks found!"))
356
357         def buildWlanList(self):
358                 self.WlanList = []
359                 currList = []
360                 currList = self['list'].list
361                 for entry in currList:
362                         self.WlanList.append( (entry[1], entry[0]) )            
363
364         def getLength(self):
365                 return self.listLenght          
366
367         def getWlanList(self):
368                 return self.WlanList
369
370
371 def WlanStatusScreenMain(session, iface):
372         session.open(WlanStatus, iface)
373
374
375 def callFunction(iface):
376         w = Wlan(iface)
377         i = w.getWirelessInterfaces()
378         if i:
379                 if iface in i:
380                         return WlanStatusScreenMain
381         return None
382
383
384 def configStrings(iface):
385         driver = iNetwork.detectWlanModule()
386         print "Found WLAN-Driver:",driver
387         if driver  in ('ralink', 'zydas'):
388                 return "        pre-up /usr/sbin/wpa_supplicant -i"+iface+" -c/etc/wpa_supplicant.conf -B -D"+driver+"\n        post-down wpa_cli terminate"
389         else:
390                 if config.plugins.wlan.essid.value == "hidden...":
391                         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'
392                 else:
393                         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'
394
395 def Plugins(**kwargs):
396         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..."})