Exemple #1
0
class ManageUsers(QWidget):
    #TODO: fix file path stuff
    """
        Summary: This is the widget that will be used to manage the users in the database. There
            are 2 main parts to this view: The add user form and the current user table. The form is
            made with a form layout out and the over all layout is the grid layout. 
        Input: None 
        Output: None
    """
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.path = os.path.dirname(os.path.abspath(__file__))

        manageUsersLayout = QGridLayout(self)
        addUsersLayout = QGridLayout()

        self.db = Database()
        self.db.connectToDatabase()

        # TODO: Change this from relative to absolute
        os.chdir(self.path)
        os.chdir("../Facial_Recognition/dataset")
        #//////////////////////////////////////////////////////////////////////////////// Form layout
        #TODO: add additional options for time frame when guest is selected

        #TODO: Make the combo box only accept certain characters
        # Widget for the access combo box
        self.accessBox = QComboBox()
        self.accessBox.setEditable(False)

        # Gets rooms from the database and adds them to the combo box
        rooms = self.db.getRooms()
        for room_index in range(0, self.db.countRooms()[0]):
            self.accessBox.addItem(rooms[room_index][0])

        self.firstName = QLineEdit()
        self.lastName = QLineEdit()
        self.bluetooth = QLineEdit()
        self.bluetooth.setMaxLength(12)

        # Layout which holds all of the user data input fields
        self.form = QFormLayout()
        self.form.addRow(QLabel("First Name"), self.firstName)
        self.form.addRow(QLabel("Last Name"), self.lastName)
        self.form.addRow(QLabel("BluetoothID"), self.bluetooth)
        self.form.addRow(QLabel("Access"), self.accessBox)

        # Connect fields
        self.firstName.textChanged.connect(self.enableAddUserButton)
        self.lastName.textChanged.connect(self.enableAddUserButton)
        self.bluetooth.textChanged.connect(self.enableAddUserButton)

        # Here is the button section of the grid layout for uploading and submitting
        submitUserButtonLayout = QHBoxLayout()

        self.add = QPushButton("Add User")
        self.clear = QPushButton("Clear Form")
        self.edit = QPushButton("Change")

        self.add.setDisabled(True)
        self.add.clicked.connect(self.createUser)

        self.clear.clicked.connect(self.clearForm)

        self.edit.setDisabled(True)
        self.edit.clicked.connect(self.Modify)

        submitUserButtonLayout.addWidget(self.add)
        submitUserButtonLayout.addWidget(self.edit)
        submitUserButtonLayout.addWidget(self.clear)

        addUsersLayout.addLayout(self.form, 0, 0)
        addUsersLayout.addLayout(submitUserButtonLayout, 1, 0)

        #//////////////////////////////////////////////////////////////////////////////// Progress bar layout
        SubmitLayout = QVBoxLayout()
        buttonLayout = QHBoxLayout()

        self.progress = QProgressBar()
        self.progress.setValue(0)
        self.progress.setTextVisible(True)
        self.progress.setAlignment(Qt.AlignCenter)

        self.upload = QPushButton("Upload")
        self.submit = QPushButton("Submit")

        self.submit.setDisabled(True)
        self.submit.clicked.connect(self.encodeFace)

        self.upload.setDisabled(True)
        self.upload.clicked.connect(self.uploadPicutes)

        buttonLayout.addWidget(self.upload)
        buttonLayout.addWidget(self.submit)

        SubmitLayout.addWidget(self.progress)
        SubmitLayout.addLayout(buttonLayout)

        addUsersLayout.addLayout(SubmitLayout, 0, 1)

        #//////////////////////////////////////////////////////////////////////////////// Table Layout
        # Here are all of Database interface functions needed to get the user information
        #TODO: code unpacking
        userCount = self.db.countUsers()

        # Creates empty table widget with headers
        self.userTable = QTableWidget(userCount[0] + 1, 4, self)
        self.userTable.setHorizontalHeaderLabels(
            ["User Name", "BluetoothID", "Bedroom", "Remove User"])

        self.userTable.horizontalHeader().setSectionResizeMode(
            QHeaderView.ResizeMode(1))
        self.userTable.horizontalHeader().setSectionResizeMode(
            3, QHeaderView.ResizeMode(2))

        self.populateTable()

        #//////////////////////////////////////////////////////////////////////////////// Main Layout Configuration
        widgetTitle = QLabel("Manage Users")
        widgetTitle.setAlignment(Qt.AlignCenter)

        manageUsersLayout.addWidget(widgetTitle, 0, 0)
        manageUsersLayout.addLayout(addUsersLayout, 1, 0)
        manageUsersLayout.addWidget(self.userTable, 2, 0)

    def enableAddUserButton(self):
        """
            Summary: This function is used to activated both the add user and upload button only when the form is filled out.
        """

        # Determines if the form fields are empty or not
        validfirstName = self.firstName.text() != ""
        validLastName = self.lastName.text() != ""
        validBluetooth = self.bluetooth.text() != ""

        # Checks to see if the length for the bluetooth is correct
        if len(self.bluetooth.text()) != 12:
            validBluetooth = False

        # Activates the upload picture and add user button
        self.add.setEnabled(validBluetooth and validfirstName
                            and validLastName)
        self.upload.setEnabled(validBluetooth and validfirstName
                               and validLastName)

    def createUser(self):
        """
            Summary: Here is where the python script will add all of the user info to both the data base
                and a directory for pictures to be stored.
        """
        # Gets the users information from the database
        users = self.db.getUsers()

        # Gets the data from the form.
        name = self.firstName.text() + "_" + self.lastName.text()
        bluetooth = self.bluetooth.text()
        access = self.accessBox.currentText()

        # Formats the bluetooth ID into its proper form
        bluetooth = bluetooth.upper()
        bluetooth = ':'.join(a + b
                             for a, b in zip(bluetooth[::2], bluetooth[1::2]))

        # Checks to see if user already exists in the database
        flag = True
        for userIndex in range(0, len(users)):
            if name in users[userIndex]:
                flag = False

        # If user does exit, the flag is tripped skipping this and erroring out
        if flag:
            os.chdir(self.path)
            os.chdir("../Facial_Recognition/dataset")

            # TODO: add path which is not a relative path
            # Enters data information into the database
            self.db.addUser(name, bluetooth, access)
            self.db.commitChanges()

            # Enters new data into table view
            self.populateTable()

            # Clears the form
            self.clearForm()

            # Added user documented in log
            logging.info("{} added to application".format(name))

            if access != "Guest":
                try:
                    # Creates a directory for the users pictures if they are not a guest
                    os.mkdir("{}".format(name))

                except OSError as error:
                    # An error dialog is brought up telling the user what went wrong
                    logging.warning(
                        "Could not create directory. \n\tError:\n\t{}".format(
                            error))
                    dlg = CustomDialogs("already_Exists", "{}".format(error))
                    dlg.exec_()
                    self.clearForm()
        else:
            logging.warning(
                "Could not create directory. \n\tError:\n\tDuplicate Entry")
            dlg = CustomDialogs("already_Exists", "Duplicate Entry")
            dlg.exec_()
            self.clearForm()

    def clearForm(self):
        self.firstName.setText("")
        self.lastName.setText("")
        self.bluetooth.setText("")
        self.accessBox.setCurrentIndex(0)

        self.bluetooth.setMaxLength(12)

        self.setProgressBar("")
        self.submit.setDisabled(True)

    def removeUser(self):
        #TODO: add function to remove user from face encoding
        # Finds the exact row of the button pressed. Thank you Sam from StackOverFlow
        buttonClicked = self.sender()
        index = self.userTable.indexAt(buttonClicked.pos())
        userRow = index.row()

        # User name is extracted from the table then removed
        item = self.userTable.item(userRow, 0)
        userName = item.text()

        self.userTable.removeRow(userRow)

        # Users name is removed from the database.
        self.db.removeUser(userName)
        self.db.commitChanges()

        # Logs user removal
        logging.info("{} removed from database".format(userName))

        # if user was perminate, their directory is removed
        os.chdir(self.path)
        os.chdir("../Facial_Recognition/dataset")
        path = "./{}".format(userName)

        try:
            # removes the directory of the user being removed
            shutil.rmtree(path, ignore_errors=True)
            self.setProgressBar("")
            self.clearForm()
            self.encodeFace()

            #TODO: add re-encoding process here

        except OSError as error:
            logging.warning(
                "Could not remove directory. \n\tError:\n\t{}".format(error))
            dlg = CustomDialogs("error", "{}".format(error))
            dlg.exec_()

    def populateTable(self):
        """
            Since this table is recreated every time theres an update, this function will delete the table and 
                rebuild it.
        """
        # Removes all of the rows currently in the table
        self.userTable.setRowCount(0)

        #//////////////////////////////////////////////////////////////////////// Table rebuild
        # Gets both the users and the user count from database
        users = self.db.getUsers()
        userCount = self.db.countUsers()

        self.userTable.setRowCount(userCount[0])

        # Gets all of the users in the database and puts the in the table
        for i in range(0, userCount[0]):
            userName = QTableWidgetItem("{}".format(users[i][0]))
            userBluetooth = QTableWidgetItem("{}".format(users[i][1]))
            userRoom = QTableWidgetItem("{}".format(users[i][2]))
            self.removeButton = QPushButton("Kill")

            self.userTable.setItem(i, 0, userName)
            self.userTable.setItem(i, 1, userBluetooth)
            self.userTable.setItem(i, 2, userRoom)
            self.userTable.setCellWidget(i, 3, self.removeButton)

            self.removeButton.clicked.connect(self.removeUser)

        # Allows double clicking on rows for editing
        self.userTable.setEditTriggers(QTableWidget.NoEditTriggers)

        # Connects a double click to an edit menu
        self.userTable.itemDoubleClicked.connect(self.editItem)

    def setProgressBar(self, userName):
        """
            Summary: This is used to set the state of the progess bar for any given user
                NOTE: make userName "" to set the bar to neutral (0/20).
        """
        if userName == "":
            self.progress.setValue(0)
            self.progress.setFormat("0/20")

        else:
            os.chdir(self.path)
            os.chdir("../Facial_Recognition/dataset/{}".format(userName))
            files = len(
                [name for name in os.listdir('.') if os.path.isfile(name)])

            progressValue = 5 * files

            if progressValue >= 100:
                self.submit.setEnabled(True)
                self.progress.setValue(100)
                self.progress.setFormat("{}: {}/20".format(userName, files))

            else:
                self.progress.setValue(progressValue)
                self.progress.setFormat("{}: {}/20".format(userName, files))

    def uploadPicutes(self):
        """
            Summary: This will have python open a camera module and take a picture of the user. Once the picture is
                taken, it will be saved in the users designated directory in the facial recognition site.
        """
        userName = self.firstName.text() + "_" + self.lastName.text()
        os.chdir(self.path)
        os.chdir("../Facial_Recognition/dataset/{}".format(userName))

        # Opens the camera for the user to add pictures of them selves.
        try:
            cam = cv2.VideoCapture(0)
            cv2.namedWindow("")

            img_counter = 0
            while True:
                ret, frame = cam.read()
                cv2.imshow(
                    "User Picture add - Press ESC to Exit - Press Space to take Picture",
                    frame)
                if not ret:
                    break
                k = cv2.waitKey(1)

                if k % 256 == 27:
                    # ESC pressed
                    print("Escape hit, closing...")
                    break

                # Takes photo when space bar is pressed.
                elif k % 256 == 32:
                    # SPACE pressed
                    img_name = "{}{}.png".format(userName, img_counter)
                    cv2.imwrite(img_name, frame)
                    print("{} written!".format(img_name))
                    img_counter += 1

            cam.release()

            cv2.destroyAllWindows()

            self.setProgressBar(userName)

        except Exception as e:
            logging.warning("No Camera Found")
            dlg = CustomDialogs("camera", "{}".format(e))
            dlg.exec_()

    def encodeFace(self):
        #TODO: add progress bar for this
        """
            Summary: Once enough pictures have been uploaded, this will kick off the encode_faces.py script in the
                facial recognition directory
        """
        os.chdir(self.path)
        subprocess.call('./encode.sh')

    def editItem(self, item):
        """
            Summary: Here is where the form is set up for the user to be edited.
                NOTE: this function will no update the user in the database directly, but rather
                by calling another function.
        """
        userRow = item.row()

        # Splits the users name into first and last
        name = self.userTable.item(userRow, 0).text().split("_")

        # Finds the index of the room in the combo box
        index = self.accessBox.findText(self.userTable.item(userRow, 2).text())

        # Allows for the combo box to display the whole modified bluetooth ID
        self.bluetooth.setMaxLength(17)

        # Sets the Add user table to all of the
        self.firstName.setText(name[0])
        self.lastName.setText(name[1])
        self.bluetooth.setText(self.userTable.item(userRow, 1).text())
        self.accessBox.setCurrentIndex(index)

        self.add.setDisabled(True)
        self.edit.setDisabled(False)
        self.upload.setDisabled(False)

        self.ORIGINAL_FIRST_NAME = name[0]
        self.ORIGINAL_LAST_NAME = name[1]

        if self.accessBox.currentText() != "Guest":
            self.setProgressBar(self.userTable.item(userRow, 0).text())
        else:
            self.upload.setDisabled(True)
            self.setProgressBar("")

    def Modify(self):
        """
            Summary: This is the function that will push the changes to the user into the database
        """
        # Gets the current data in the fom
        bluetooth = self.bluetooth.text()
        access = self.accessBox.currentText()

        # gets the name of the user for editing
        combinedOriginalName = self.ORIGINAL_FIRST_NAME + "_" + self.ORIGINAL_LAST_NAME

        # removes the user from the database then readds them with the changes
        self.db.removeUser(combinedOriginalName)
        self.db.addUser(combinedOriginalName, bluetooth, access)
        self.db.commitChanges()

        # the table is re populated
        self.populateTable()
        self.clearForm()
Exemple #2
0
class ManageRooms(QWidget):
    """
        Summary: This class will display the manage rooms window
    """
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # TODO: Fix table so that it only has entries for how many devices are in each room
        # TODO: Make add and remove device functions.
        # TODO: Add function to count devices based on room in db_interface

        self.path = os.path.dirname(os.path.abspath(__file__))
        os.chdir(self.path)

        # Connects the application to the database
        self.db = Database()
        self.db.connectToDatabase()

        # Initiates a layout and a tree widget
        self.layout = QVBoxLayout(self)
        self.roomTree = QTreeWidget()
        self.roomTree.setHeaderLabels(["Bedrooms"])

        self.populateTable()

        self.buttonLayout = QHBoxLayout()
        self.addDevice = QPushButton("Add Device")
        self.removeButton = QPushButton("Remove Device")

        self.buttonLayout.addWidget(self.addDevice)
        self.buttonLayout.addWidget(self.removeButton)

        self.addDevice.clicked.connect(self.deviceAdd)
        self.removeButton.clicked.connect(self.deviceRemove)

        # Adds the dock widget to the main layout for the manage room plane
        self.layout.addWidget(self.roomTree)
        self.layout.addLayout(self.buttonLayout)

    def populateTable(self):
        """
            Summary: Since this table will be updated regularly via adding and removing
                devices, it is given its own function which first destroys the table then
                rebuilds it from the top
        """
        rooms = self.db.getRooms()

        self.roomTree.clear()

        for room in range(0, len(rooms)):
            roomName = rooms[room][0]
            root = QTreeWidgetItem(self.roomTree, [roomName])

            devices = self.db.getDevices(roomName)

            # Adds all of the devices to the room specific tree
            for dev in range(0, len(devices)):
                deviceName = devices[dev][0]
                child = QTreeWidgetItem(root, [deviceName])

        self.roomTree.expandAll()

#///////////////////////////////////////////////////////////////////// Device add functions

    def deviceAdd(self):
        """
        """
        # Add to Custom Dialog class
        newAddition = QDialog()
        dialogLayout = QVBoxLayout(newAddition)

        # Widget for the access combo box
        self.accessBox = QComboBox()
        self.accessBox.setEditable(False)

        # Gets rooms from the database and adds them to the combo box
        rooms = self.db.getRooms()
        for room_index in range(0, self.db.countRooms()[0]):
            self.accessBox.addItem(rooms[room_index][0])

        self.deviceName = QLineEdit()
        self.deviceImportance = QLineEdit()
        self.devicePurpose = QLineEdit()

        # Form for the user to enter in new device information
        formLayout = QFormLayout()
        formLayout.addRow(QLabel("Device Name"), self.deviceName)
        formLayout.addRow(QLabel("Device Importance"), self.deviceImportance)
        formLayout.addRow(QLabel("Device Purpose"), self.devicePurpose)
        formLayout.addRow(QLabel("Device Location"), self.accessBox)

        # Adds the okay and cancel button at the bottom
        QBtn = QDialogButtonBox.Ok

        buttonBox = QDialogButtonBox(QBtn)
        buttonBox.accepted.connect(self.accept)

        dialogLayout.addLayout(formLayout)
        dialogLayout.addWidget(buttonBox)

        newAddition.setWindowTitle("Add Device")
        newAddition.exec_()

    def accept(self):
        """
            Summary: Loads new device information into the database
        """
        # adds the device to the database
        self.db.addDevice(self.deviceName.text(), self.devicePurpose.text(),
                          self.deviceImportance.text(),
                          self.accessBox.currentText())
        self.db.commitChanges()
        self.populateTable()

        # Logs the new addition
        logging.info("Added new device: {}".format(self.deviceName.text()))

        # Clears the from on the add button dialog
        self.deviceName.setText("")
        self.deviceImportance.setText("")
        self.devicePurpose.setText("")
        self.accessBox.setCurrentIndex(0)

#///////////////////////////////////////////////////////////////////// Device Remove Functions

    def deviceRemove(self):
        """
            Summary: Displays a table of ever device for users to remove
        """
        removeDeviceDialog = QDialog()

        dialogLayout = QVBoxLayout(removeDeviceDialog)

        devices = self.db.getDevices()
        deviceCount = len(devices)

        self.removeDeviceTable = QTableWidget(self.db.countDevices()[0], 5,
                                              self)
        self.removeDeviceTable.setHorizontalHeaderLabels(
            ["Name", "Purpose", "Importance", "Location", "Remove"])

        # Formats the table to fill up all avaliable space
        self.removeDeviceTable.horizontalHeader().setSectionResizeMode(
            QHeaderView.ResizeMode(1))
        self.removeDeviceTable.horizontalHeader().setSectionResizeMode(
            4, QHeaderView.ResizeMode(2))

        # Here is where all of the information is unpacked and inserted into the table
        for deviceIndex in range(0, deviceCount):
            deviceName = QTableWidgetItem("{}".format(devices[deviceIndex][0]))
            devicePurpose = QTableWidgetItem("{}".format(
                devices[deviceIndex][1]))
            deviceImportance = QTableWidgetItem("{}".format(
                devices[deviceIndex][2]))
            deviceLocation = QTableWidgetItem("{}".format(
                devices[deviceIndex][3]))
            deviceRemove = QPushButton("Kill")

            self.removeDeviceTable.setItem(deviceIndex, 0, deviceName)
            self.removeDeviceTable.setItem(deviceIndex, 1, devicePurpose)
            self.removeDeviceTable.setItem(deviceIndex, 2, deviceImportance)
            self.removeDeviceTable.setItem(deviceIndex, 3, deviceLocation)
            self.removeDeviceTable.setCellWidget(deviceIndex, 4, deviceRemove)

            deviceRemove.clicked.connect(self.killDevice)

        dialogLayout.addWidget(self.removeDeviceTable)

        removeDeviceDialog.exec_()

    def killDevice(self):
        buttonClicked = self.sender()
        index = self.removeDeviceTable.indexAt(buttonClicked.pos())
        deviceRow = index.row()

        # User name is extracted from the table then removed
        item = self.removeDeviceTable.item(deviceRow, 0)
        deviceName = item.text()

        self.removeDeviceTable.removeRow(deviceRow)

        self.db.removeDevice(deviceName)
        self.db.commitChanges()

        self.populateTable()
Exemple #3
0
				counts[name] = counts.get(name, 0) + 1
				
				# determine the recognized face with the largest number
				# of votes (note: in the event of an unlikely tie Python
				# will select first entry in the dictionary)
				name = max(counts, key=counts.get)

			#################################### PLACE REACTION CODE HERE ###################################################
			#TODO: Added scripts to activate locks

			if name != "Unknown":
				print("success {} from {}".format(name, rpiName))
				
				logging.info("{} Entering from {} at {}".format(name, rpiName, datetime.now()))
				db.addEntry(datetime.now(), rpiName, "Accepted", name)
				db.commitChanges()
				
				imageHub.send_reply(b'Open Door')

				time.sleep(2)

		else:
			print("Unknown User!")

			logging.warning("Unknown user approaching at {}: Time - {}".format(rpiName, datetime.now()))
			db.addEntry(datetime.now(), rpiName, "Rejected", "Unknown")
			db.commitChanges()

			imageHub.send_reply(b"test")

			time.sleep(5)