Source code for gwa.code_AP

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Translation in English by David Dumas

"""
Allow the user to manage Access Points in an independent module.
This file is specifically dedicated to IHM_AP.py, UI file for the module of Access Points management.
"""

import pg
import re
import sys
import time
import string
import logging
import ConfigParser
import threading

from PyQt4 import QtGui, QtCore
from ihm_AP import *
from code.DBA import *
from code.popups import *
from PyQt4.QtGui import *
from WifiScanner import *



[docs]class APController(QtGui.QWizard): """ Create the wizard. Assign functions to the various buttons. """ def __init__(self, main=None, parent=None): """ Called every time this class is instantiated. It’s the equivalent of a class constructor in C/C++. It initializes the UI of the measurement part in four steps: - Creation of the link with the main UI - Creation of the UI - Creation of the event listeners generated by the UI via “connect_signals()” - Variables initializations via “initVariables()” """ QtGui.QWidget.__init__(self, parent=parent) # Keeps link towards high_level application self.main_app = main # Draws UI self.ui = Ui_AP() self.ui.setupUi(self) # Connects signals of UI to self methods self.connect_signals() # Initialization self.initVariables() # Load APs self.loadAP()
[docs] def initVariables(self): """ Initialize the variables necessary to do measures and connect to the database. """ # Init various variables to false self.ui.toolButton_ap_ajouter.setEnabled(False) self.ui.toolButton_ap_supprimer.setEnabled(False) self.ui.toolButton_ap_modifier.setEnabled(False) # Connect to the database with the parameters from the conf file self.db = DBConnect(main=self.main_app) self.ids_environments = {} # Dictionary to store the environement in the UI { key => string displayed : value => environnement ID (in the database) } self.id_environment = None # Environnement ID selected by the user (Window 1) self.ids_places = {} # Dictionary to store the locations displayed in the UI { key => string displayed : value => location ID (in the database) } self.id_place = None # Location ID selected by the user (Window 2) self.ids_aps = {} # Dictionary of the APs { key => string displayed : value => AP ID (in the database) } self.id_ap = None # AP ID selected by the user # Instanciation of class Popup self.popup=Popups() # Instanciation of class WifiScanner self.scanner=WifiScanner() #init treeWidget self.ui.treeWidget.header().setStretchLastSection(False) self.ui.treeWidget.header().setResizeMode(0, QHeaderView.Stretch) #self.ui.treeWidget.header().setResizeMode(1, QHeaderView.Stretch) self.ui.treeWidget.header().setResizeMode(2, QHeaderView.Stretch) self.listItemsAP=[]
[docs] def connect_signals(self): """ Create action listeners for the UI. Example: self.connect(self.ui.toolButton_mesure_campagne_ajouter, QtCore.SIGNAL("clicked()"), self.ajouterCampagne) When the bouton “toolButton_mesure_campagne_ajouter” is clicked, function “ajouterCampagne()” is called. """ # Buttons links with functions self.connect(self, QtCore.SIGNAL("currentIdChanged(int)"), self.switchPage) self.connect(self, QtCore.SIGNAL("rejected()"), self.main_app.switchToMenu) self.connect(self, QtCore.SIGNAL("finished(int)"), self.reinitialize) self.connect(self.ui.listWidget_ap_environnement, QtCore.SIGNAL("itemClicked(QListWidgetItem *)"), self.setCurrentEnvironment) self.connect(self.ui.listWidget_ap_lieu, QtCore.SIGNAL("itemClicked(QListWidgetItem *)"), self.setCurrentLocation) self.connect(self.ui.listWidget_ap_list, QtCore.SIGNAL("itemClicked(QListWidgetItem *)"), self.displayAPInfo) self.connect(self.ui.toolButton_ap_ajouter, QtCore.SIGNAL("clicked()"), self.addAP) self.connect(self.ui.toolButton_ap_supprimer, QtCore.SIGNAL("clicked()"), self.removeAP) self.connect(self.ui.toolButton_ap_modifier, QtCore.SIGNAL("clicked()"), self.editAP) # Grey out the add AP button when the fields are not filled self.connect(self.ui.lineEdit_ap_essid, QtCore.SIGNAL("textChanged (const QString&)"), self.enableAddAP) self.connect(self.ui.lineEdit_ap_MAC, QtCore.SIGNAL("textChanged (const QString&)"), self.enableAddAP) self.connect(self.ui.lineEdit_ap_coor_x, QtCore.SIGNAL("textChanged (const QString&)"), self.enableAddAP) self.connect(self.ui.lineEdit_ap_coor_y, QtCore.SIGNAL("textChanged (const QString&)"), self.enableAddAP) self.connect(self.ui.lineEdit_ap_coor_z, QtCore.SIGNAL("textChanged (const QString&)"), self.enableAddAP) # Grey out the delete AP button when no AP is selected self.connect(self.ui.listWidget_ap_list, QtCore.SIGNAL("itemClicked(QListWidgetItem *)"), self.enableRemoveAP) # Grey out the update AP button when no AP is selected self.connect(self.ui.listWidget_ap_list, QtCore.SIGNAL("itemClicked(QListWidgetItem *)"), self.enableEditAP) #listAP self.connect(self.ui.treeWidget, QtCore.SIGNAL("itemSelectionChanged()"), self.selectAP) self.connect(self.ui.refresh, QtCore.SIGNAL("clicked()"),self.loadAP)
[docs] def switchPage(self): """ Called whenever a UI page change occurs to initialize: - Lists fulfillment (pages 1 to 4) - Measurements (page 5) - Completion of the measures (page 6) """ if self.currentId() == 1: logging.info('Page : Environment (AP)') self.displayEnvironmentList() if self.currentId() == 2: logging.info('Page : Place (AP)') self.displayLocationList() if self.currentId() == 3: logging.info('Page : Add AP (AP)') self.displayAPList() self.clearAPInfo()
[docs] def reinitialize(self, resultCode): """ Switch to the application master menu and reinitializes the QWizard module. """ self.main_app.switchToMenu() self.restart()
[docs] def validateCurrentPage(self): """ Reimplementation of the function “validateCurrentPage” which implements by default “QWizardPage::validatePage()” on “currentPage()”. @return: [ True: page validated + ID changed ==> panel switch / False: page non-compliant + same ID ==> no panel switch ] """ # Check if any environnement is selected if self.currentId() == 1: if not self.ui.listWidget_ap_environnement.currentItem(): return False # Check if any location is selected if self.currentId() == 2: if not self.ui.listWidget_ap_lieu.currentItem(): return False return True #----------Environnement selection page-----
[docs] def displayEnvironmentList(self): """ Display the list of environments in the UI. """ # Empty the list in the UI self.ui.listWidget_ap_environnement.clear() # Select the name, coordinates X,Y,Z and the description of locations in the database result_sql=self.db.select('area',['id_area','name', 'description']) # Update the list in the UI with the info retrieved just before for id_area, name, description in result_sql: str = "%s : %s" % (name, description) self.ids_environments[str] = id_area self.ui.listWidget_ap_environnement.addItem(str)
[docs] def setCurrentEnvironment(self): """ Retrieve the name and database ID of the selected environment. """ # Retrieve the ligne selected in the UI line_select = str(self.ui.listWidget_ap_environnement.currentItem().text()) # Retrieve the ID self.id_environment = self.ids_environments[line_select] #----------Location selection page--------------
[docs] def displayLocationList(self): """ Display the list of locations in the UI. """ # Empty the list in the UI self.ui.listWidget_ap_lieu.clear() # Select the name, coordinates X,Y,Z and the description of locations in the database result_sql=self.db.select('place',['id_place', 'name','description'],{'id_area':self.id_environment}) # Update the list in the UI with the info retrieved just before for id_place, name, description in result_sql: str = "%s : %s" % (name, description) self.ids_places[str] = id_place self.ui.listWidget_ap_lieu.addItem(str)
[docs] def setCurrentLocation(self): """ Retrieve the name and database ID of the selected location. Set a global variable “self.id_place”. """ # Retrieve the ligne selected in the UI line_select = str(self.ui.listWidget_ap_lieu.currentItem().text()) # Retrieve the ID self.id_place = self.ids_places[line_select] #----------Add and edit APs page--------------
[docs] def displayAPList(self): """ Display the list of Access Points in the UI. """ # Empty the list in the UI self.ui.listWidget_ap_list.clear() # Select the name, coordinates X,Y,Z and the description of locations in the database result_sql = self.db.select('ap',['id_ap','essid','mac_address','x_coordinate_place',\ 'y_coordinate_place','z_coordinate_place','description'],{'id_place':self.id_place,'essid !':'\'AP_ignored\''}) # Update the list in the UI with the info retrieved just before for id_ap, essid, mac_address, x_coordinate_place, y_coordinate_place, z_coordinate_place, description in result_sql: str = "%s %s - %s" % (essid, mac_address, description) self.ids_aps[str] = id_ap self.ui.listWidget_ap_list.addItem(str) self.ui.listWidget_ap_list.sortItems() # Grey out the AP delete and update buttons self.ui.toolButton_ap_supprimer.setEnabled(False) self.ui.toolButton_ap_modifier.setEnabled(False)
[docs] def setCurrentAP(self): """ Retrieves the ID depending on the Access Point selected in the UI. """ # Retrieve the ligne selected in the UI line_select=str(self.ui.listWidget_ap_list.currentItem().text()) # Retrieve the ID self.id_ap = self.ids_aps[line_select]
[docs] def clearAPInfo(self): """ Clear the user filled fields. Called whenever the Access Points list is updated. """ # Empty all the fields self.ui.lineEdit_ap_essid.clear() self.ui.lineEdit_ap_MAC.clear() self.ui.textEdit_ap_description.clear() self.ui.lineEdit_ap_coor_x.clear() self.ui.lineEdit_ap_coor_y.clear() self.ui.lineEdit_ap_coor_z.clear()
[docs] def displayAPInfo(self): """ Display the Access Point’s parameters when an element is selected in the list. """ # Retrieve the ID of the selected AP self.setCurrentAP() # Retrieve the info of the ligne selected result_sql = self.db.select('ap',['essid','mac_address','x_coordinate_place',\ 'y_coordinate_place','z_coordinate_place','description'],{'id_ap':self.id_ap}) # Display the parameters in the add / modify fields of the UI for essid, mac_address, x_coordinate_place, y_coordinate_place, z_coordinate_place, description in result_sql: self.ui.lineEdit_ap_essid.setText(QtCore.QLatin1String(str(essid))) self.ui.lineEdit_ap_MAC.setText(QtCore.QLatin1String(str(mac_address))) self.ui.lineEdit_ap_coor_x.setText(QtCore.QLatin1String(str(x_coordinate_place))) self.ui.lineEdit_ap_coor_y.setText(QtCore.QLatin1String(str(y_coordinate_place))) self.ui.lineEdit_ap_coor_z.setText(QtCore.QLatin1String(str(z_coordinate_place))) self.ui.textEdit_ap_description.setText(QtCore.QLatin1String(str(description)))
[docs] def verifyAPInfo(self, mac, ap_x, ap_y, ap_z, essid, appel): """ Integrity check of the user’s input before insertion in the database. Verify the MAC address’ format, the coordinates’ consistency in a location and duplicates of an entry with the same SSID and MAC address. @param appel: by which function this function is call [ True: from addAP() / False: from editAP()] """ # Check the MAC address format match = re.match("[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}$", mac) if not match: self.displayAPList() self.popup.popupOK("MAC adress format error ", "The MAC adress synthaxe is :\n 00:00:00:00:00:00" ) return False # Check the X coordinate x_coor_place = self.db.select('place',['length'], {'id_place':self.id_place})[0][0] if int(ap_x) > x_coor_place: if not self.popup.popupYesNo("Out of local area","Warning, your AP is out of the place (X>%dm). Do you really want to continue ?" % x_coor_place): self.displayAPList() return False # Check the Y coordinate y_coor_place = self.db.select('place',['width'], {'id_place':self.id_place})[0][0] if int(ap_y) > y_coor_place: if not self.popup.popupYesNo("Out of local area","Warning, your AP is out of the place (Y>%dm). Do you really want to continue ?" % y_coor_place): self.displayAPList() return False # Check the Z coordinate z_coor_place = self.db.select('place',['height'], {'id_place':self.id_place})[0][0] if int(ap_z) > z_coor_place: if not self.popup.popupYesNo("Out of local area","Warning, your AP is out of the place (Z>%dm). Do you really want to continue ?" % z_coor_place): self.displayAPList() return False # Check if the MAC-ESSID pair exists already in the database if appel: # Add function if not self.db.select('ap',['id_ap'],{'essid':'\'' + essid + '\'','mac_address':'\'' + mac + '\''})== []: self.displayAPList() self.popup.popupOK("This pair of \"MAC - SSID\" already exist !", "It's not possible to create the AP !\nAn AP already exists in the DB with the SSID \"" + essid + "\" and the MAC adress \"" + mac + "\".") return False else: # Edit function : check if any AP in the database has already the specified SSID-MAC pair, except the currently selected pair if not self.db.select('ap',['id_ap'],{'essid':'\'' + essid + '\'','mac_address':'\'' + mac + '\'','id_ap !':self.id_ap})== []: self.displayAPList() self.popup.popupOK("This pair of \"MAC - SSID\" already exist !", "It's not possible to create the AP \"id " + str(self.id_ap) + "\" !\nAn other AP already exist in the DB with the SSID \"" + essid + "\" and the MAC adress \"" + mac + "\".") return False # Conditions satisfied ==> return True return True
[docs] def addAP(self): """ Add an Access Point into the database. """ # Retrieve the info filled in the UI essid = str(self.ui.lineEdit_ap_essid.text()) mac = str(self.ui.lineEdit_ap_MAC.text()) desc_ap = str(self.ui.textEdit_ap_description.toPlainText()).replace("'", "\\'") ap_x = str(self.ui.lineEdit_ap_coor_x.text()) ap_y = str(self.ui.lineEdit_ap_coor_y.text()) ap_z = str(self.ui.lineEdit_ap_coor_z.text()) # Retrieve the location the user is working with self.setCurrentLocation() # Create a dictionary allowing to define parameters that will be loaded in the database dic = {'essid':essid, 'mac_address':mac, 'x_coordinate_place':ap_x,'y_coordinate_place':ap_y,\ 'z_coordinate_place':ap_z,'description':desc_ap,'id_place':self.id_place} # Insert in the database if the conditions are satisfied if self.verifyAPInfo(mac, ap_x, ap_y, ap_z, essid, True): try: # Insert in the database with the DBA module and the function 'insert', retrieve the added AP's ID. self.id_ap = self.db.insertAndReturn("ap", dic, 'id_ap') # If it suceeds, empty the fields self.clearAPInfo() except pg.DatabaseError, exc: # If there is a value for any coordinate (x,y or z), perform an 'update' instead of an 'insert' print "There ever is this AP in the BDD, use the edit button to modify \n" from traceback import format_exc print format_exc() # Update the list self.displayAPList()
[docs] def removeAP(self): """ Remove an Access Point from the database. """ # Display the AP list self.displayAPList() # Pop up a confirmation dialog to delete the AP validate_remove = self.popup.popupYesNo("AP remove confirmation", "Do you really want to remove the selected AP ?") # Delete the AP from the database after confirmation if validate_remove: self.db.delete("ap", {'id_ap':self.id_ap}) # Update the AP list in the UI self.displayAPList() # Clear the fields self.clearAPInfo()
[docs] def editAP(self): """ Edit an Access Point’s parameters in the database. """ # Retrieve the info filled in the UI essid = str(self.ui.lineEdit_ap_essid.text()) mac = str(self.ui.lineEdit_ap_MAC.text()) desc_ap = str(self.ui.textEdit_ap_description.toPlainText()).replace("'", "\\'") ap_x = str(self.ui.lineEdit_ap_coor_x.text()) ap_y = str(self.ui.lineEdit_ap_coor_y.text()) ap_z = str(self.ui.lineEdit_ap_coor_z.text()) # Integrity check on the modified fields if self.verifyAPInfo(mac, ap_x, ap_y, ap_z, essid, False): # Update the parameters of the AP in the database self.db.update("ap", "essid", '\''+essid+'\'', {'id_ap':self.id_ap}) self.db.update("ap", "mac_address", '\''+mac+'\'', {'id_ap':self.id_ap}) self.db.update("ap", "x_coordinate_place", ap_x, {'id_ap':self.id_ap}) self.db.update("ap", "y_coordinate_place", ap_y, {'id_ap':self.id_ap}) self.db.update("ap", "z_coordinate_place", ap_z, {'id_ap':self.id_ap}) self.db.update("ap", "description", '\''+desc_ap+'\'', {'id_ap':self.id_ap}) # Clear the fields if the edit succeeds self.clearAPInfo() # Update the AP list in the UI self.displayAPList()
[docs] def enableAddAP(self): """ Activates / deactivates the button to add Access Points. The button becomes active only when the user fills the required fields (SSID, MAC address, coordinates). """ # Check if the fields exist, if yes: activate the "Ajouter" button / if no: the "Ajouter" button remains greyed out if self.ui.lineEdit_ap_essid.text() and self.ui.lineEdit_ap_MAC.text() \ and self.ui.lineEdit_ap_coor_x.text() and self.ui.lineEdit_ap_coor_y.text() and self.ui.lineEdit_ap_coor_z.text(): self.ui.toolButton_ap_ajouter.setEnabled(True) else : self.ui.toolButton_ap_ajouter.setEnabled(False)
[docs] def enableRemoveAP(self, itemClicked): """ Activates / deactivates the button “toolButton_ap_supprimer” whenever an Access Point is selected in the list. """ if itemClicked: self.ui.toolButton_ap_supprimer.setEnabled(True) else : self.ui.toolButton_ap_supprimer.setEnabled(False)
[docs] def enableEditAP(self, itemClicked): """ Activates / deactivates the button “toolButton_ap_modifier” whenever an Access Point is selected in the list. """ if itemClicked: self.ui.toolButton_ap_modifier.setEnabled(True) else : self.ui.toolButton_ap_modifier.setEnabled(False)
[docs] def selectAP(self): """ Select an AP from the scanned list """ print "AP select" elements= self.ui.treeWidget.selectedItems() #self.setWindowTitle ( test[0].text(0) + "\t" + test[0].text(2) ) self.SSID = elements[0].text(0) self.mac = elements[0].text(2) self.completionAP(self.SSID,self.mac)
[docs] def completionAP(self,ssid,mac): """ auto completion """ print ssid + ' ' + mac self.ui.lineEdit_ap_essid.setText(ssid) self.ui.lineEdit_ap_MAC.setText(mac)
[docs] def loadAP(self): """ load the AP """ self.ui.treeWidget.clear() self.listItemsAP=[] self.ui.refresh.setEnabled(False) self.ui.refresh.setText('loading') self.ui.refresh.update() threadData = threading.Thread(target=self.getData) threadData.start() #self.getData() threadData.join() for AP in self.listItemsAP: item=QtGui.QTreeWidgetItem([AP[0],' '+str(AP[1])+'%',AP[2]]) if(AP[1]<=20): icon=QtGui.QIcon("images/reception_wifi_1.gif") if(AP[1]>20 and AP[1] <=40): icon=QtGui.QIcon("images/reception_wifi_2.gif") if(AP[1]>40 and AP[1] <=60): icon=QtGui.QIcon("images/reception_wifi_3.gif") if(AP[1]>60 and AP[1] <=80): icon=QtGui.QIcon("images/reception_wifi_4.gif") if(AP[1]>80): icon=QtGui.QIcon("images/reception_wifi_5.gif") self.ui.treeWidget.setIconSize(QtCore.QSize(40,40)) item.setIcon(1,icon) if AP[1]!="": self.ui.treeWidget.addTopLevelItem(item)
[docs] def getData(self): """ scan the AP """ nbAP= 0 self.scanner.scanForWifiNetworks() APs=self.scanner.getWifiNetworksList() print "number of AP :"+str(len(APs)) for AP in APs: #print AP signal=round(float(AP[5]),3)*100 itemAP=[AP[1],signal,AP[0]] self.listItemsAP.append(itemAP) self.ui.refresh.setEnabled(True) self.ui.refresh.setText('refresh')
if __name__ == "__main__": import sys app= QtGui.QApplication(sys.argv) scr = APControlor() scr.show() sys.exit(app.exec_())