Demo of Bluetooth Notification (with Fingerprint Approval)

Dependencies:   mbed Menu DRV2605 RPG RGBLED TextLCD GT511C3

main.cpp

Committer:
austinterrell
Date:
2019-12-03
Revision:
0:5fa2d54bedb4

File content as of revision 0:5fa2d54bedb4:

#include "mbed.h"
#include "GT511C3.hpp"
#include "TextLCD.h"
#include "DRV2605.h"
#include "RGBLED.h"
#include "Menu.h"
#include "Selection.h"
#include "Navigator.h"
using namespace std;

// Devices
GT511C3     scanner(p9,p10);
TextLCD     lcd(p15, p16, p17, p18, p19, p20, TextLCD::LCD16x2);
RPG         rpg(p21,p22,p23);
RGBLed      rgb(p24,p25,p26);
DRV2605     haptics(p28, p27);
Serial      blue(p13, p14);

// Globals
Navigator   *navPtr;
Menu        mainMenu("1");
Menu        notificationsMenu("2");
Menu        settingsMenu("2");
Menu        notification("3");
char        text[16];
char        *textPtr = text;
int         userID = 1;
bool        notificationPresent = false;
bool        led = false;
Ticker      t;

// Prototypes
void    receive();
void    print(char *msg);
int     progress(int status, char *msg);
void    refreshMenu();
void    gotoMainMenu();
bool    verifyUser();
void    approve();
void    decline();
void    enroll();
void    deleteUsers();
void    blinker();

int main()
{       
    // Locals
    unsigned char data[498]; // Fingerprint template
    
    /* DEVICE SETUP */
    
    // Setup haptic feedback
    haptics.init(3.3);
    haptics.load_waveform_sequence(45,65);
    haptics.play();
    while(haptics.i2cReadByte(GO));
    
    // Configure Bluetooth
    blue.baud(9600);
    blue.attach(&receive);
    
    // Start blinker
    t.attach(&blinker, 0.4);
    
    /* MENU SETUP */
    
    // Make menus
    notificationsMenu.add(Selection(NULL, &mainMenu, " None..."));
    
    // Build settings menu
    settingsMenu.add(Selection(&enroll, NULL, " Enroll User"));
    settingsMenu.add(Selection(&deleteUsers, NULL, " Delete Users"));
    settingsMenu.add(Selection(NULL, &mainMenu, " Main Menu"));
    
    // Build main Menu
    mainMenu.add(Selection(NULL, &notificationsMenu, " Notification"));
    mainMenu.add(Selection(NULL, &settingsMenu, " Settings"));
    
    // Add notification options
    notification.add(Selection(&approve, NULL, " Approve"));
    notification.add(Selection(&decline, NULL, " Decline"));
    notification.add(Selection(NULL, &mainMenu, " Cancel"));
    
    // Build navigator to browse menus
    Navigator navigator(&mainMenu, rpg, &lcd);
    navPtr = &navigator;
    
    /* FINGERPRINT SCANNER SETUP */
    
    // Start fingerprint scanner
    if(scanner.Open() != 0) {
        lcd.cls();
        lcd.printf("Fingerprint Scanner FAILED.\n\r");
        exit(0);
    }

    // Deletes All Fingerprints enrolled in the database
    scanner.DeleteAllIDs();
    
    // Turn on scanner
    scanner.CmosLed(1);
    
    // Add inital user
    print("Scan New\nUser's Finger...");
    scanner.WaitPress(1);
    scanner.Enroll(-1, progress);
    scanner.RecvData(data, 498);
    scanner.SetTemplate(userID, data, 498);
    
    // Turn off scanner
    scanner.CmosLed(0);
    
    // Show menu
    refreshMenu();
    
    // Poll navigator for menu
    while(1) {    
        navigator.poll();
    }
}

// Reads bluetooth and posts notification
void receive()
{
    // Locals
    int i = 1;
    
    // Make first char a space
    memset(text, 0, sizeof(text));
    text[0] = ' ';
    
    // Read serial from bluetooth
    while(blue.readable() && (i < 15)) {
        text[i] += blue.getc();
        i++;
        wait(0.1);
    }
    text[i] = '\0'; // Null terminate
    
    // Post notification
    notificationsMenu.selections[0].childMenu = &notification;
    notificationsMenu.selections[0].selText = text;
    
    // Show notificaiton for a couple seconds
    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("%s\n", text);
    rgb.write(0.5, 0.0, 0.5);
    haptics.play();
    wait(2);
    refreshMenu();
    notificationPresent = true;
}

// Print message to LCD
void print(char *msg)
{
    lcd.cls();
    lcd.printf("%s\n", msg);
}

// Prints enrollment progress
int progress(int status, char *msg)
{
    lcd.cls();
    lcd.printf("%s\n", msg);
    return 0;
}

// Re-display menu
void refreshMenu()
{
    navPtr->printMenu();
    navPtr->printCursor();
}

// Go to main menu
void gotoMainMenu()
{
    navPtr->activeMenu = &notificationsMenu;
    navPtr->bottom = navPtr->activeMenu->selections.size();
    navPtr->cursorPos = 0;
    navPtr->cursorLine = 1;
    navPtr->printMenu();
    navPtr->printCursor();
}

// Read finger and verify identity
bool verifyUser()
{
    // Locals
    int attempts = 0;
    
    // Turn on scanner
    scanner.CmosLed(1);
    
    // Allow 3 attempts
    while (attempts < 3) {
        print("Please Verify\nIdentity...");
        scanner.WaitPress(1);
        scanner.Capture(1);
        
        // If finger in database
        if (scanner.Identify() != -1) 
        {
            print("Thank You.\nRemove Finger...");
            if (scanner.IsPress()) scanner.WaitPress(0);
            
            // Turn off
            scanner.CmosLed(0);
            return true;
        } 
        else 
        {
            print("User Unknown.\nRemove Finger...");
            if (scanner.IsPress()) scanner.WaitPress(0);
            attempts++;
        }
    }
    
    // Turn off
    scanner.CmosLed(0);
    return false;
    
}

// Approve notification
void approve()
{
    // Turn off blinker
    notificationPresent = false;
    
    // If identity checks-out
    if (verifyUser()) 
    {
        // Send approval
        blue.puts("Approved.\n");
        
        // Feedback
        print("Approved.\nThank You.");
        rgb.write(0.0, 1.0, 0.0);
        wait(2);
        rgb.write(0.0, 0.0, 0.0);
    }
    else
    {
        // Send error
        blue.puts("User Identity Unknown.\n");
        
        // Feedback
        print("Error.\nUser Unknown.");
        rgb.write(1.0, 0.0, 0.0);
        wait(2);
        rgb.write(0.0, 0.0, 0.0);
    }
    
    // Clear notification
    notificationsMenu.selections[0].childMenu = &mainMenu;
    notificationsMenu.selections[0].selText = " None...";
    gotoMainMenu();
}

// Decline notification
void decline()
{
    // Turn off blinker
    notificationPresent = false;
    
    // If identity checks-out
    if (verifyUser()) 
    {
        // Send declination
        blue.puts("Declined.\n");
        
        // Feedback
        print("Declined.\nThank You.");
        rgb.write(0.0, 1.0, 0.0);
        wait(2);
        rgb.write(0.0, 0.0, 0.0);
    }
    else
    {
        // Send error
        blue.puts("User Identity Unknown.\n");
        
        // Feedback
        print("Error.\nUser Unknown.");
        rgb.write(1.0, 0.0, 0.0);
        wait(2);
        rgb.write(0.0, 0.0, 0.0);
    }
    
    // Clear notification
    notificationsMenu.selections[0].childMenu = &mainMenu;
    notificationsMenu.selections[0].selText = " None...";
    gotoMainMenu();
}

// Add a new user to the scanner
void enroll()
{
    unsigned char data[498]; // Fingerprint template

    if (verifyUser()) {
        
        // New user
        userID++;
        
        // Turn on scanner
        scanner.CmosLed(1);
        
        // Add user
        print("Scan New\nUser's Finger...");
        scanner.WaitPress(1);
        scanner.Enroll(-1, progress);
        scanner.RecvData(data, 498);
        scanner.SetTemplate(userID, data, 498);
        
        // Turn off scanner
        scanner.CmosLed(0);
    }

    refreshMenu();
}

// Remove all users from scanner
void deleteUsers()
{
    unsigned char data[498]; // Fingerprint template

    if (verifyUser()) {
        
        // Reset user IDs
        userID = 1;
        
        // Deletes All Fingerprints enrolled in the database
        scanner.DeleteAllIDs();
        
        // Turn on scanner
        scanner.CmosLed(1);
        
        // Add inital user
        print("Scan New\nUser's Finger...");
        scanner.WaitPress(1);
        scanner.Enroll(-1, progress);
        scanner.RecvData(data, 498);
        scanner.SetTemplate(userID, data, 498);
        
        // Turn off scanner
        scanner.CmosLed(0);
    }

    refreshMenu();
}

// Persistent notification led
void blinker()
{
    // If there is a notification
    if (notificationPresent) {
        
        // If led is not on
        if (!led) {
            rgb.write(0.5, 0.0, 0.5);
        }
        else {
            rgb.write(0.0, 0.0, 0.0);
        }   
        led = !led;     
    }
}