IoT Alarm System with pushbutton for door, webpage for viewing status, and keypad for disabling alarm.
Dependencies: PinDetect mbed wave_player FATFileSystem
Fork of ESP8266-WEB-Mbed-LPC1768-Controller by
main.cpp
- Committer:
- gholden3
- Date:
- 2016-03-17
- Revision:
- 5:28e4c7315a20
- Parent:
- 4:40dd020463ea
File content as of revision 5:28e4c7315a20:
// ECE410 Lab 4 Alarm System Holden&Wasserman /* The following describes an Mbed IoT Alarm system. A push button is pressed to signify an “open door”. The user accesses a web page that displays the statuses of the Mbed Alarm System. The webpage displays the status of the door, as well as the time, and the background indicates the alarm state. Once the door is opened, the user has a time limit to turn off the alarm or it will sound. Once the correct code is keyed in, the alarm will shut off. This status is also displayed on the webpage. */ //Webserver code based off: ESP8266-WEB-Mbed-LPC1768-Controller //Further work: get rtos working to play a sound on the speaker for the alarm. Add more detailed states that //allow the user to key in the code before the alarm sounds. Allow user to turn off alarm from webpage. #include "mbed.h" #include "SDFileSystem.h" #include "wave_player.h" #define twilight_WAVFILE "/sd/wavfiles/twilight_zone_x.wav" #include "PinDetect.h" #include <mbed.h> #include <mpr121.h> #include <string> // Standard Mbed LED definitions DigitalOut led1(LED1); DigitalOut led2(LED2); DigitalOut led3(LED3); DigitalOut led4(LED4); //wifi chip Serial pc(USBTX, USBRX); Serial esp(p28, p27); // tx, rx DigitalOut reset(p25); //timer for alarm countdown Ticker alarmTimer; float numSecondsRemaining = 30; // interrupt pin for keypad InterruptIn interrupt(p26); // Setup the i2c bus on pins 9 and 10 keypad I2C i2c(p9, p10); // Setup the Mpr121: touch sensor // constructor(i2c object, i2c address of the mpr121) Mpr121 mpr121(&i2c, Mpr121::ADD_VSS); //door is triggered by a pushbutton // no external PullUp resistor needed // Pushbutton from P12 to GND. // A pb falling edge (hit) generates an interrupt and activates the interrupt routine PinDetect doorPB(p12); //door status variable enum doorStatus { OPEN, CLOSED }; doorStatus doorStatus = CLOSED; //alarm status variable enum alarmStatus { SOUNDING, OFF }; alarmStatus alarm1Status = OFF; //we need to get rtos working for this :( PwmOut speaker(p21); //timeout timer for getreply() Timer t1; //timeout timer for getcheck() Timer t2; //struct used for RTC struct tm t; int bufflen, DataRX, count, getcount, replycount, servreq, timeout; int bufl, ipdLen, linkID, weberror, webcounter; char pwd[] = "1234"; char enterpwd[100] = ""; char secondsRemaining[10]; char webcount[8]; char lasthit[30]; char timebuf[30]; char type[16]; char type1[16]; char channel[2]; char cmdbuff[32]; char replybuff[1024]; char webdata[1024]; // This may need to be bigger depending on WEB browser used char webbuff[4096]; // Currently using 1986 characters, Increase this if more web page data added void SendCMD(),getreply(),ReadWebData(),startserver(),sendpage(),SendWEB(),sendcheck(); void gettime(),setRTC(); void timerExpired() //called every second once door is opened { numSecondsRemaining--; if (numSecondsRemaining == 0) { //your time to disable the alarm is up. sound alarm! alarmTimer.detach(); alarm1Status = SOUNDING; } sprintf(secondsRemaining, "%2.0f",numSecondsRemaining); } void pb_hit_callback (void) //door { pc.printf("pushbutton hit!\r\n"); pc.printf("door is %s \r\n", doorStatus); if (doorStatus == OPEN) doorStatus = CLOSED; else if (doorStatus == CLOSED) { doorStatus = OPEN; //start counting every second alarmTimer.attach(&timerExpired, 1.0); } wait(.1); } // manual set RTC values int minute =00; // 0-59 int hour =12; // 2-23 int dayofmonth =26; // 1-31 int month =8; // 1-12 int year =15; // last 2 digits int port =80; // set server port int SERVtimeout =5; // set server timeout in seconds in case link breaks. // Serial Interrupt read ESP data void callback() { while (esp.readable()) { webbuff[count] = esp.getc(); count++; } if(strlen(webbuff)>bufflen) { DataRX=1; } } // Key hit/release interrupt routine void fallInterrupt() { int key_code=0; int i=0; int value=mpr121.read(0x00); value +=mpr121.read(0x01)<<8; // puts key number out to LEDs for demo for (i=0; i<12; i++) { if (((value>>i)&0x01)==1) key_code=i+1; } if (key_code == 0) return; else key_code--; led4=key_code & 0x01; led3=(key_code>>1) & 0x01; led2=(key_code>>2) & 0x01; led1=(key_code>>3) & 0x01; char result[10]; //convert float to cstring sprintf(result,"%d",key_code); pc.printf("result: %s\r\n", result); //concatenate to the end strcat(enterpwd,result); pc.printf("enterpwd: %s\r\n",enterpwd); //only compares the first four values entered. future work: make a clear/reset option if((enterpwd[0]==pwd[0]) && (enterpwd[1]==pwd[1]) && (enterpwd[2]==pwd[2]) && (enterpwd[3]==pwd[3])){ alarm1Status=OFF; alarmTimer.detach(); pc.printf("correct!\r\n"); } } int main() { //attach interrupt for keypad interrupt.fall(&fallInterrupt); interrupt.mode(PullUp); doorPB.mode(PullUp); // Delay for initial pullup to take effect wait(.01); // Attach the address of the interrupt handler routine for pushbutton doorPB.attach_deasserted(&pb_hit_callback); doorPB.setSampleFrequency(); reset=0; pc.baud(115200); pc.printf("\f\n\r------------ ESP8266 Hardware Reset --------------\n\r"); wait(0.5); reset=1; timeout=6000; getcount=500; getreply(); // ESP8266 baudrate. Maximum on KLxx' is 115200, 230400 works on K20 and K22F esp.baud(115200); if (time(NULL) < 1420070400) { setRTC(); } startserver(); while(1) { if(DataRX==1) { ReadWebData(); if (servreq == 1 && weberror == 0) { sendpage(); } esp.attach(&callback); pc.printf(" IPD Data:\r\n\n Link ID = %d,\r\n IPD Header Length = %d \r\n IPD Type = %s\r\n", linkID, ipdLen, type); pc.printf("\n\n HTTP Packet: \n\n%s\n", webdata); pc.printf(" Web Characters sent : %d\n\n", bufl); pc.printf(" -------------------------------------\n\n"); strcpy(lasthit, timebuf); servreq=0; } } } // Static WEB page void sendpage() { gettime(); // WEB page data strcpy(webbuff, "<!DOCTYPE html>"); strcat(webbuff, "<html><head><title>ESP8266 Mbed LPC1768</title></head>"); if(alarm1Status == SOUNDING) { strcat(webbuff, "<body style=\"background-color:#FF0000;\" >"); } else if (alarm1Status==OFF) { strcat(webbuff, "<body style=\" background-color:#32CD32;\" >"); } strcat(webbuff, "<div style=\"text-align:center; background-color:#F4F4F4; color:#00AEDB;\"><h1>Mbed Alarm System</h1>"); strcat(webbuff, "Hit Count - "); strcat(webbuff, webcount); strcat(webbuff, "<br>Last Hit - "); strcat(webbuff, lasthit); strcat(webbuff, "</div><br /><hr>"); strcat(webbuff, "<h3>Mbed RTC Time -  "); strcat(webbuff, timebuf); strcat(webbuff, "</h3>\r\n"); strcat(webbuff, "<p><form method=\"POST\"><strong> Door Status:  <input type=\"text\" size=6 value=\""); if(doorStatus == CLOSED) strcat(webbuff, "CLOSED"); else if(doorStatus == OPEN) strcat(webbuff, "OPEN"); strcat(webbuff, "\"> </sup> <form method=\"POST\"> <strong>   Seconds Remaining:  <input type=\"text\" size=4 value=\""); strcat(webbuff, secondsRemaining); strcat(webbuff, "\"> </sup>"); strcat(webbuff, "</strong><p><input type=\"submit\" value=\"send-refresh\" style=\"background: #3498db;"); strcat(webbuff, "background-image:-webkit-linear-gradient(top, #3498db, #2980b9);"); strcat(webbuff, "background-image:linear-gradient(to bottom, #3498db, #2980b9);"); strcat(webbuff, "-webkit-border-radius:12;border-radius: 12px;font-family: Arial;color:#ffffff;font-size:20px;padding:"); strcat(webbuff, "10px 20px 10px 20px; border:solid #103c57 3px;text-decoration: none;"); strcat(webbuff, "background: #3cb0fd;"); strcat(webbuff, "background-image:-webkit-linear-gradient(top,#3cb0fd,#1a5f8a);"); strcat(webbuff, "background-image:linear-gradient(to bottom,#3cb0fd,#1a5f8a);"); strcat(webbuff, "text-decoration:none;\"></form></span>"); strcat(webbuff, "<p/><h2>How to use:</h2><ul>"); strcat(webbuff, "<li>Background color reflects alarm state. Green is good red is bad. </li>"); strcat(webbuff, "<li>You can refresh the page with the browser button or send/refresh.</li>"); strcat(webbuff, "<li>Seconds remaining tells you how much time before alarm sounds</li>"); strcat(webbuff, "</ul>"); strcat(webbuff, "</body></html>"); // end of WEB page data bufl = strlen(webbuff); // get total page buffer length sprintf(cmdbuff,"AT+CIPSEND=%d,%d\r\n", linkID, bufl); // send IPD link channel and buffer character length. timeout=200; getcount=7; SendCMD(); getreply(); SendWEB(); // send web page memset(webbuff, '\0', sizeof(webbuff)); sendcheck(); } // wait for ESP "SEND OK" reply, then close IP to load web page void sendcheck() { weberror=1; timeout=500; getcount=24; t2.reset(); t2.start(); while(weberror==1 && t2.read() <5) { getreply(); if (strstr(replybuff, "SEND OK") != NULL) { weberror=0; // wait for valid SEND OK } } if(weberror==1) { // restart connection strcpy(cmdbuff, "AT+CIPMUX=1\r\n"); timeout=500; getcount=10; SendCMD(); getreply(); pc.printf(replybuff); sprintf(cmdbuff,"AT+CIPSERVER=1,%d\r\n", port); timeout=500; getcount=10; SendCMD(); getreply(); pc.printf(replybuff); } else { sprintf(cmdbuff, "AT+CIPCLOSE=%s\r\n",channel); // close current connection SendCMD(); getreply(); pc.printf(replybuff); } t2.reset(); } // Reads and processes GET and POST web data void ReadWebData() { wait_ms(200); esp.attach(NULL); count=0; DataRX=0; weberror=0; memset(webdata, '\0', sizeof(webdata)); int x = strcspn (webbuff,"+"); if(x) { strcpy(webdata, webbuff + x); weberror=0; int numMatched = sscanf(webdata,"+IPD,%d,%d:%s", &linkID, &ipdLen, type); sprintf(channel, "%d",linkID); if (strstr(webdata, "GET") != NULL) { servreq=1; } if (strstr(webdata, "POST") != NULL) { servreq=1; } webcounter++; sprintf(webcount, "%d",webcounter); } else { memset(webbuff, '\0', sizeof(webbuff)); esp.attach(&callback); weberror=1; } } // Starts and restarts webserver if errors detected. void startserver() { gettime(); pc.printf("\n\n RTC time %s\r\n\n",timebuf); pc.printf("++++++++++ Resetting ESP ++++++++++\r\n"); strcpy(cmdbuff,"AT+RST\r\n"); timeout=8000; getcount=1000; SendCMD(); getreply(); pc.printf(replybuff); pc.printf("%d",count); if (strstr(replybuff, "OK") != NULL) { pc.printf("\n++++++++++ Starting Server ++++++++++\r\n"); strcpy(cmdbuff, "AT+CIPMUX=1\r\n"); // set multiple connections. timeout=500; getcount=20; SendCMD(); getreply(); pc.printf(replybuff); sprintf(cmdbuff,"AT+CIPSERVER=1,%d\r\n", port); timeout=500; getcount=20; SendCMD(); getreply(); pc.printf(replybuff); wait(1); sprintf(cmdbuff,"AT+CIPSTO=%d\r\n",SERVtimeout); timeout=500; getcount=50; SendCMD(); getreply(); pc.printf(replybuff); wait(5); pc.printf("\n Getting Server IP \r\n"); strcpy(cmdbuff, "AT+CIFSR\r\n"); timeout=2500; getcount=200; while(weberror==0) { SendCMD(); getreply(); if (strstr(replybuff, "0.0.0.0") == NULL) { weberror=1; // wait for valid IP } } pc.printf("\n Enter WEB address (IP) found below in your browser \r\n\n"); pc.printf("\n The MAC address is also shown below,if it is needed \r\n\n"); replybuff[strlen(replybuff)-1] = '\0'; //char* IP = replybuff + 5; sprintf(webdata,"%s", replybuff); pc.printf(webdata); // led2=1; bufflen=200; count=0; pc.printf("\n\n++++++++++ Ready ++++++++++\r\n\n"); esp.attach(&callback); } else { pc.printf("\n++++++++++ ESP8266 error, check power/connections ++++++++++\r\n"); while(1) {} } t2.reset(); t2.start(); } // ESP Command data send void SendCMD() { esp.printf("%s", cmdbuff); } // Large WEB buffer data send void SendWEB() { int i=0; if(esp.writeable()) { while(webbuff[i]!='\0') { esp.putc(webbuff[i]); i++; } } } // Get Command and ESP status replies void getreply() { memset(replybuff, '\0', sizeof(replybuff)); t1.reset(); t1.start(); replycount=0; while(t1.read_ms()< timeout && replycount < getcount) { if(esp.readable()) { replybuff[replycount] = esp.getc(); replycount++; } } t1.stop(); } // Get RTC time void gettime() { time_t seconds = time(NULL); strftime(timebuf,50,"%H:%M:%S %a %d %b %y", localtime(&seconds)); } void setRTC() { t.tm_sec = (0); // 0-59 t.tm_min = (minute); // 0-59 t.tm_hour = (hour); // 0-23 t.tm_mday = (dayofmonth); // 1-31 t.tm_mon = (month-1); // 0-11 "0" = Jan, -1 added for Mbed RCT clock format t.tm_year = ((year)+100); // year since 1900, current DCF year + 100 + 1900 = correct year set_time(mktime(&t)); // set RTC clock }