IoT for mbed1

Dependencies:   4DGL-uLCD-SE IoTsecuritySys PinDetect mbed-rtos mbed

Fork of IoT by Tal Landes

main.cpp

Committer:
landes
Date:
2015-12-08
Revision:
7:758d4e6fc145
Parent:
6:33185f926189
Child:
8:429fa05b4952

File content as of revision 7:758d4e6fc145:

#include <mbed.h>
#include <string>
#include <iostream>
#include "rtos.h"
#include <mpr121.h>
#include <stdlib.h>
#include "PinDetect.h"
#include "uLCD_4DGL.h"
#include "SongPlayer.h"
#include "Speaker.h"
#include "EthernetInterface.h"
/* CODE_LENGTH needs to be double the amount of numbers you
      want in your authenticator/passcode because of the way interrupt.fall(&fallInterrupt)
      works. It is called twice every time an interrupt is detected.
      The extra numbers in the array will just be filled with zeros and ignored in checking 
      code sequences, so they will not matter either way */
      /* i.e, you want a code with 7 numbers, CODE_LENGTH needs to be 14 */
#define CODE_LENGTH 8

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

DigitalOut doorlock(p21);


//uLCD_4DGL uLCD(p9,p10,p11); // serial tx, serial rx, reset pin;
uLCD_4DGL uLCD(p28, p27, p29); 

// Create the interrupt receiver object on pin 26
InterruptIn interrupt(p30);

// Setup the i2c bus on pins 9 and 10
I2C i2c(p9, p10);

// Setup the Mpr121:
// constructor(i2c object, i2c address of the mpr121)
Mpr121 mpr121(&i2c, Mpr121::ADD_VSS);

// pc serial communication for testing
Serial pc(USBTX, USBRX);

//Set up IR sensor 
AnalogIn IrSensor(p20);

//Shiftbright
DigitalOut latch(p15);
DigitalOut enable(p16);
//AnalogOut DACout(p18);
//Cycles through different colors on RGB LED
SPI spi(p11, p12, p13);


SongPlayer mySpeaker(p26);
Speaker NotePlayer(p26);

// ethernet setup    
EthernetInterface eth;

//Lock timeout 
Timeout flipper;

// ***** GLOBALS ***** //
// Timer is to seed rand
string ID = "1";
volatile int NumTry = 0; 
Timer t1;
Timer t2;
// code counter is the next position in inputCode array
volatile int codeCounter;
// inputCode array is the sequence of numbers the user will enter
volatile int inputCode[CODE_LENGTH];
volatile bool code_enabled;
volatile float IrVoltage = 0.0;
int FindStrLocation(string sntsc, string word, string ptr);
volatile enum Statetype { Armed = 0, IR_sensed = 1, Second_Step = 2, Cleared = 3, Alarm_ON = 4};
Statetype state = Armed;
char charCode[5];

float note[18]= {1568.0,1396.9};
float duration[18]= {0.48,0.24};

Mutex LCD_Access; 
Mutex PC_Access;
Semaphore Consul_Access(5);

void Shiftbright_thread(void const *args);
void IR_thread(void const *args);
void LCD_Code_Enter_Thread(void const *args);
void uLCD_thread(void const *args);
void RGB_LED(int red, int green, int blue);
void Speaker_thread(void const *args);
void Ethernet_thread(void const *args);
bool Ethernet_massage_Send(string args);
void Activate_Lock();
void init_LCD();
// Key hit/release interrupt routine
void fallInterrupt() {
    int key_code=0;
    int i=0;
    int value=mpr121.read(0x00);
    value +=mpr121.read(0x01)<<8;
    // LED demo mod
    i=0;
    // puts key number out to LEDs for demo
    for (i=0; i<12; i++) {
    if (((value>>i)&0x01)==1) key_code=i+1;
    }
    led4=key_code & 0x01;
    led3=(key_code>>1) & 0x01;
    led2=(key_code>>2) & 0x01;
    led1=(key_code>>3) & 0x01;
  
    // save the keypress to inputCode array
    switch (state) {
        case Armed:
        break;
        case IR_sensed:
        case Second_Step:
            if(codeCounter < CODE_LENGTH){
            // ignore odd numbers
            if(codeCounter % 2 != 0){
                inputCode[codeCounter] = 0;
            }
            // only save the even numbers (see lines 6-10)
            else{
                inputCode[codeCounter] = key_code - 1;
                //pc.printf("codeCounter: %d  --  code:  %d\n\r", codeCounter, key_code - 1);
            }      
            codeCounter++;
        }
        break;
        case Alarm_ON:
        break; 
        case Cleared:
            if(key_code == 12 ){
                state = Armed;
                //Ethernet_massage_Send("UpdateStatus");
                }
            else if (key_code == 11 ){
                doorlock = 1;  
                flipper.attach(&Activate_Lock, 5.0);
                }
        break;
        }
    
}

// generate randomized code
void generate_random_code(int (&codeArray)[CODE_LENGTH]){
    //int i = 0;
    // only care about the even numbers (see lines 6-10)
    //////////PC_Access.lock();
    //pc.printf("NEW CODE: ");
    //PC_Access.unlock();
    for(int i = 0; i < CODE_LENGTH; i+=2){
        srand(t1.read_us());
        codeArray[i] = (rand() % 9)+1; //nake code only 1-9
        //////////PC_Access.lock();
        pc.printf("%d,  ", codeArray[i]);
        //PC_Access.unlock();
    }

    snprintf(charCode, sizeof(charCode), "%i%i%i%i ", codeArray[0], codeArray[2], codeArray[4], codeArray[6]);
    //////////PC_Access.lock();
    //pc.printf("\n\r");
    //pc.printf("%s\n\r",charCode,codeArray[6]);
    //PC_Access.unlock();
    //Ethernet_massage_Send("TextCode");
}

// check if the code entered is the correct code
bool check_code_sequence(int (&codeArray)[CODE_LENGTH]){
    //int i = 0;
    int j = 0;
    // only care about the even numbers (see lines 6-10)

    if (NumTry < 3) {
        NumTry++;
    for(int i = 0; i < CODE_LENGTH; i+=2){
        
        if(inputCode[i] == codeArray[i]){
        j++; // count the number of right numbers
        }
         
    }
    if(j == CODE_LENGTH/2){
        for(int i = 0; i < CODE_LENGTH; i+=2){
            inputCode[i] =0;
        }
        return(true);
    }
    else if  (Ethernet_massage_Send("GetTempCode")){
        for(int i = 0; i < CODE_LENGTH; i+=2){
             inputCode[i] =0;
        }
        //pc.printf("return true");
        return(true);
    }
    else {
        for(int i = 0; i < CODE_LENGTH; i+=2){
            inputCode[i] =0;
        }
       return(false);
    }
    }
    else {
        pc.printf("3 times ");
        state = Alarm_ON;
        return(false);
    }
}
 
int main() {
    interrupt.fall(&fallInterrupt);
    interrupt.mode(PullUp);
    pc.baud(921600);
    
    
    // authenticator is the randomly generated sequence of numbers by the machine
    // the user has to match this sequence to gain access, used for phase 2
    int authenticator[CODE_LENGTH];
    // passcode is the user's personal passcode, used for phase 1
    int passcode[CODE_LENGTH] = {1,0,2,0,3,0,4,0};//,4,0,5,0,6,0};
    codeCounter = 0;
    bool pass = false;
    
    // these 2 variables tell the machine when to generate a new random authentication code
    int new_code_timer = 0;
    int new_code_counter = 0;
    // this tells the state machine with phase of authentication we are in
    code_enabled = false;
    
    for(int i = 0; i < CODE_LENGTH; i++){
      authenticator[i] = 0;
      inputCode[i] = 0;
    }
    
    // go ahead and start the timer so that when a random code is generated,
    // the seed will always be random, unlike the predecessor version
    t1.start();
    init_LCD();
    //start threads:
    //////////PC_Access.lock();
    pc.printf("\n\n\nSetting up Ethernet\n\r");
    //PC_Access.unlock();
    Thread Ethernetthread(Ethernet_thread);
    wait(5); //Give the Ethernet connection some time to set up 
    Thread IRthread(IR_thread);
    Thread Shiftbright(Shiftbright_thread);
    Thread LCDthread(uLCD_thread);
    //Thread LCD_CodeEnterThread(LCD_Code_Enter_Thread); 
    //Thread Speakerthread(Speaker_thread);
    
    // while loop constantly checks if the entered code sequence is right or wrong,
    // given that the correct amount of numbers were entered
    ////////////PC_Access.lock();
    pc.printf("Ready\n\r");
    ////PC_Access.unlock();
    doorlock = 0; // make sure locked 
    while (1){
        switch(state){
            case Cleared:
                break;
            case IR_sensed:
                if(codeCounter >= CODE_LENGTH){
                    pass = check_code_sequence(passcode);
                    if(pass == true){
                        ////////////////////////PC_Access.lock();
                        //pc.printf("SENDING AUTHENTICATION CODE...\n\r");
                        ////////PC_Access.unlock();
                        generate_random_code(authenticator);
                        t1.stop(); // reset the time
                        t1.reset(); // so that it is an even
                        t1.start(); // 30 seconds before 1st new code is generated
                        codeCounter = 0;
                        //code_enabled = true;
                        state = Second_Step;
                        Ethernet_massage_Send("UpdateStatus");
                    }
                    else{
                        ////////////////////////PC_Access.lock();
                        //pc.printf("WRONG passcode\n\r");
                        ////PC_Access.unlock();
                        codeCounter = 0;
                    }
                }
                break;
            case Second_Step:
                if(codeCounter >= CODE_LENGTH){
                    NumTry = 0;
                    pass = check_code_sequence(authenticator);
                    if(pass == true){
                        ////////////////////////PC_Access.lock();
                        //pc.printf("ACCESS GRANTED\n\r");
                        ////PC_Access.unlock();
                        doorlock = 1;  
                        flipper.attach(&Activate_Lock, 5.0);
                        //wait(5);
                        //doorlock = 0;*/
                        //pc.printf("Resetting....\n\r");
                        //pc.printf("\n\n\rPlease Enter Your Personal Security Code\n\r");
                        codeCounter = 0;
                        code_enabled = false;
                        state = Cleared;
                        Ethernet_massage_Send("TextCode");
                        Ethernet_massage_Send("UpdateStatus");
                    }
                    else{
                        ////////////////////////PC_Access.lock();
                        //pc.printf("ACCESS DENIED\n\r");
                        ////PC_Access.unlock();
                        codeCounter = 0;
                    }
                }
                // this code generates a new authentication code every 30 seconds (30000 ms)
                new_code_timer = (int)(t1.read_ms()/300000000);
                if(new_code_timer > new_code_counter){
                    new_code_counter++;
                    generate_random_code(authenticator);
                    codeCounter = 0;
                }
                break;
        }
        // reset the timer when the number gets too high, should last about 35 minutes
        //  We do this because int can only hold a number up to 2^32 - 1, preventing errors
        if(t1.read_us() > 2147400000){
            t1.stop();
            t1.reset();
            new_code_timer = 0;
            new_code_counter = 0;
            t1.start();
        }
    }
}


void Shiftbright_thread(void const *args){
    spi.format(16,0);
    spi.frequency(500000);
    enable=0;
    latch=0;
    
    while(1) {
    switch (state) {
        case Armed:
            for (int i = 0; i <= 50; i++) {
                RGB_LED( i, 0, 0);
                Thread::wait(10);
            }
            for (int i = 50; i >= 0; i--) {
                RGB_LED( i, 0, 0);
                Thread::wait(10);
            }
        break;
        case IR_sensed:
            RGB_LED( 100, 0, 0);
            Thread::wait(500);
            RGB_LED( 0, 0, 0);
        break;
        case Alarm_ON:
            for (int i = 0; i <= 100; i++) {
                RGB_LED( i, i/2, 0);
                Thread::wait(10);
            }
            for (int i = 100; i >= 0; i--) {
                RGB_LED( i, i/3, 0);
                Thread::wait(10);
            }
        break; 
        case Cleared:
            RGB_LED( 0, 100, 0);
            break;
        }
        Thread::wait(1000);
   }
}


void IR_thread(void const *args) {
    
    Timer t;
    t.start(); 
    
    while(1) {
        
        if (state == Armed) {
            IrVoltage=IrSensor.read();
            if (IrVoltage <= 0.1) { //if value just nois reset timer
                t.reset();
                state = Armed;
                Ethernet_massage_Send("UpdateStatus");
                }
            if (t.read() >= 5) { //wait 5 seconds to make sure that sense someone 
                state = IR_sensed; 
                Ethernet_massage_Send("UpdateStatus");
                }
            Thread::wait(1000);
        }
        else {
            //nothing to do for this thread make space for others
            Thread::wait(1000);
        }
    }
}

void RGB_LED(int red, int green, int blue) {
    
    unsigned int low_color=0;
    unsigned int high_color=0;
    high_color=(blue<<4)|((red&0x3C0)>>6);
    low_color=(((red&0x3F)<<10)|(green));
    spi.write(high_color);
    spi.write(low_color);
    latch=1;
    latch=0;
}

void init_LCD() {
    uLCD.baudrate(3000000);
    uLCD.background_color(BLACK);
    
}
    

void uLCD_thread(void const *args) {
    int Change = 99; 
    string temp;
    temp = "abc";
    while(1) {
        
        if (Change != state) {
            Change = state;
            switch (state) {
                case Armed:
                    LCD_Access.lock();
                    uLCD.cls();
                    uLCD.color(WHITE);
                    uLCD.text_width(2);
                    uLCD.text_height(2);
                    uLCD.printf("  ARMED\r\n");
                    uLCD.text_width(1); 
                    uLCD.text_height(1);
                   
                    if (eth.getIPAddress() == "\0") {
                        uLCD.printf("\n\n No Internet connection");
                        }
                    else {
                        uLCD.printf("\n\nConnected to the  Internet\n");
                        uLCD.printf("IP Address: \n%s ", eth.getIPAddress());
                        }
                    LCD_Access.unlock();
                break;
                case IR_sensed:
                    LCD_Access.lock();
                    uLCD.cls();
                    uLCD.printf("\nSensor triggred \n"); 
                    uLCD.printf("\n  Enter the code ...");
                    LCD_Access.unlock();
                    for (int i=30; i>=0; --i) {
                        if (state == IR_sensed) {
                            LCD_Access.lock();
                            uLCD.text_width(4);
                            uLCD.text_height(4);
                            uLCD.color(RED);
                            uLCD.locate(1,2);
                            uLCD.printf("%2D",i);                    
                            LCD_Access.unlock();                    
                            Thread::wait(1000);
                            }
                        }
                        if (state == IR_sensed) {
                            state = Alarm_ON;
                            Ethernet_massage_Send("UpdateStatus");
                            Ethernet_massage_Send("TextAlarm");
                            }

                break;
                case Second_Step: 
                    LCD_Access.lock();
                    uLCD.cls();
                    uLCD.color(BLUE);
                    uLCD.printf("\nPleas enter code from text massage \n");
                    LCD_Access.unlock();
                    break;
                case Alarm_ON:
                    LCD_Access.lock();
                    uLCD.cls();
                    uLCD.color(RED);
                    uLCD.text_width(1.5); //4X size text
                    uLCD.text_height(1.5);
                    uLCD.printf("\nALARM IS ON \nText message sent \n"); 
                    LCD_Access.unlock();
                    break;
                case Cleared: 
                    LCD_Access.lock();
                    uLCD.cls();
                    uLCD.color(GREEN);
                    uLCD.printf("\n\nAccess Granted. \n\n"); 
                    LCD_Access.unlock();  
                break; 
                }
            }
            Thread::wait(500);
        }
}

void LCD_Code_Enter_Thread(void const *args) {
    int LineHight = 120;
    int LineWidth = 10; 
    int SpaceWidth = 5;
    int MidPoint = 127/2;
    while(1) {
        switch (state) {
                case Armed:
                break;
                case IR_sensed:
                case Cleared:
                case Second_Step:
                  
                    Thread::wait(500);
                    while((state == IR_sensed)||(state == Cleared)||(state == Second_Step)) {
                        LCD_Access.lock();
                        //dusplay four lines 
                        uLCD.line(MidPoint-2*(LineWidth+SpaceWidth), LineHight, MidPoint- 2*SpaceWidth-LineWidth, LineHight, WHITE); //line( int x1, int y1, int x2, int y2, int color)
                        uLCD.line(MidPoint-LineWidth-SpaceWidth, LineHight, MidPoint-SpaceWidth, LineHight, WHITE); //line( int x1, int y1, int x2, int y2, int color)
                        uLCD.line(MidPoint+SpaceWidth, LineHight, MidPoint+SpaceWidth+LineWidth, LineHight, WHITE); //line( int x1, int y1, int x2, int y2, int color)
                        uLCD.line(MidPoint+2*SpaceWidth+LineWidth, LineHight, MidPoint+2*(SpaceWidth+LineWidth), LineHight, WHITE); //line( int x1, int y1, int x2, int y2, int color)
                        uLCD.locate(5,14);
                        uLCD.text_width(1); //4X size text
                        uLCD.text_height(1);
                        
                        // add black numbers
                        /*if (inputCode[0] == inputCode[2] ==inputCode[4] ==inputCode[6] == 0) {                        
                            uLCD.color(BLACK);                        
                        }
                        else {*/
                        //uLCD.color(WHITE);
                        uLCD.printf("%d %d  %d %d",inputCode[0],inputCode[2],inputCode[4],inputCode[6]);
                        //}
                        LCD_Access.unlock();
                    }
                
                case Alarm_ON:
                break;
                }
        }
}

void Speaker_thread(void const *args) {
    while (1) {
    if (state == Alarm_ON) {
        mySpeaker.PlaySong(note,duration);
        Thread::wait(1000); 
        }
    }
}

void Ethernet_thread(void const *args) { 
 
    char buffer[300];
   
    int ret,found;
    eth.init(); //Use DHCP
    eth.connect();
//pc.printf("IP Address is: %s\n\r", eth.getIPAddress());
    while (1) {
                        Thread::wait(3000);
        int timeout;

        //t2.start();                 
        TCPSocketConnection sock;
        sock.connect("dreamphysix.com", 80);
        char http_cmd[100] = "GET http://www.dreamphysix.com/alarm/readstatus.php?mbedID=0 HTTP/1.0\n\n";
    ////////////PC_Access.lock();
    //pc.printf("%s",http_cmd);
    ////PC_Access.unlock();
    sock.send_all(http_cmd, sizeof(http_cmd)-1);
    
                        while (true) {
                        ret = sock.receive(buffer, sizeof(buffer)-1);
                        if (ret <= 0)
                            break;
                        buffer[ret] = '\0';
                        Consul_Access.wait();
                        ////////////////////////PC_Access.lock();
                        //pc.printf("Received %d chars from server:\n%s\n", ret, buffer);
                        ////PC_Access.unlock();
                        Consul_Access.release();
                        }
                    sock.close();
                    //t2.stop();
    string str(buffer);
    found = str.find("Status=");
    //pc.printf("location: %d string: %s" , found, str);              
    //pc.printf("\n\rhttp_cmd: %c\n\r",buffer[found+7]);
    //pc.printf("\n\state: %i\n\r",state);
    int dummy = (buffer[found+7])-48;
    //int dummy = ((int)buffer[found+7]);
    //dummy = atoi(dummy);
    state = (Statetype)dummy;
    //state = (Statetype)buffer[found+7];
    pc.printf("\n\state: %i\n\r",dummy);
    //Thread::wait(3000); 
    

    }
}

bool Ethernet_massage_Send(string buff) { 

    char buffer[300];
    int ret;
    //pc.printf("IP Address is: %s\n\r", eth.getIPAddress());

                    TCPSocketConnection sock;
                    sock.connect("dreamphysix.com", 80);
                    
                    if (buff == "TextCode") { 
                            char http_cmd[100] = "GET http://www.dreamphysix.com/alarm/sendcode.php?authcode=0e9cae34a0&randomcode=";
                            strcat(http_cmd, charCode);
                            strcat(http_cmd, " HTTP/1.0\n\n");
                            //////////////////////////PC_Access.lock();
                            //pc.printf("%s",http_cmd);
                            ////PC_Access.unlock();
                            sock.send_all(http_cmd, sizeof(http_cmd)-1);
                    }
                    else if (buff == "TextAlarm") {
                            char http_cmd[] = "GET http://dreamphysix.com/alarm/sendalert.php?authcode=0e9cae34a0 HTTP/1.0\n\n";
                            sock.send_all(http_cmd, sizeof(http_cmd)-1);
                   }
                    else if (buff == "GetTempCode") {
                            snprintf(charCode, sizeof(charCode), "%i%i%i%i ", inputCode[0], inputCode[2], inputCode[4], inputCode[6]);
                            char http_cmd[100] = "GET http://www.dreamphysix.com/alarm/validatecode.php?code=";
                            strcat(http_cmd, charCode);
                            strcat(http_cmd, " HTTP/1.0\n\n");
                            //////////////////////////PC_Access.lock();
                            //pc.printf("%s",http_cmd);
                            ////PC_Access.unlock();
                            sock.send_all(http_cmd, sizeof(http_cmd)-1);
                    }
                    else if (buff == "UpdateStatus") {
                            char tempStatus[2];
                            snprintf(tempStatus, sizeof(tempStatus), "%i", state);
                            char http_cmd[100] = "GET http://www.dreamphysix.com/alarm/updatestatus.php?mbedID=1";
                            //strcat(http_cmd, ID);
                            strcat(http_cmd, "&status=");
                            strcat(http_cmd, tempStatus);
                            strcat(http_cmd, " HTTP/1.0\n\n");
                            //////////////////////////PC_Access.lock();
                            //pc.printf("%s",http_cmd);
                            ////PC_Access.unlock();
                            sock.send_all(http_cmd, sizeof(http_cmd)-1);
                    }
                    else {
                        
                    }


                    while (true) {
                        ret = sock.receive(buffer, sizeof(buffer)-1);
                        if (ret <= 0)
                            break;
                        buffer[ret] = '\0';
                        Consul_Access.wait();
                        ////////////////////////PC_Access.lock();
                       //pc.printf("Received %d chars from server:\n%s\n", ret, buffer);
                        ////PC_Access.unlock();
                        Consul_Access.release();
                        }
                    sock.close();
                    
                    snprintf(buffer, ret, "%c",buffer);
                    //pc.printf("buffer: %s", buffer);
                    if (strstr(buffer,"True") != NULL) {
                         //pc.printf("true fron eth check");
                         return true;
                    }
                    else if (strstr(buffer,"False") != NULL) {
                         //pc.printf("false fron eth check");
                         return false;
                    }
                    else {
                        //pc.printf("default ");
                        return false;
                    }
}

void Activate_Lock(){
    doorlock =! doorlock;
}