IoT Remote Home Surveillance Security System
Overview
Our project is an integrated remote home surveillance system that is comprised of 3 components:
- A distributed 7-sensor network on 4 separate MBED micro controllers each with its own ESP8266 WiFi chip
- A live server back-end written in NodeJS to receive HTTP requests from the MBED
Team Members
- Varol Burak Aydemir
- Muhammad Doukmak
- Matin Malikyar
- Ahmed Mostafa
How it Works
This is a fully integrated remote home security system with mbed's at four different locations throughout the apartment. There is a server that processes the logic of the system and communicates with the mbeds and the front end. The user can log onto a webpage with a username and password from a desktop or smartphone and see the status of the system. There is a table showing the status of each sensor, and colored dots on the floor plan that show if that mbed is triggered or not. Each mbed has several sensors that could cause an alarm triggering event. Additionally, when the alarm is triggered, an mbed with a camera receives that signal from the server and begins taking pictures at a rate of 1 picture every 3 seconds. The user can arm/disarm the system from the webpage, or they can use the capacitive touch pad to enter in a 4-digit passcode to arm/disarm the system.
Demo Video
Diagram
mbed program
Import program4180_Final_Project
ECE 4180 Spring 2016 Final Project for home surveillance project
mbed bedroom code
#include "mbed.h" #include "rtos.h" #include "LSM9DS1.h" #include "wifi.h" #include "Speaker.h" ////// Global Mbed Pin Objects ////// DigitalOut myled1(LED1); //When ON IMU is detected a move DigitalOut myled2(LED2); //When ON IR sensed an object DigitalOut myled3(LED3); //When ON Mic sensed loud sound DigitalOut myled4(LED4); //When ON Alarm is ON ////// Global Variables ////// volatile bool isSystemArmed=true; volatile bool isSystemArmedChanged=false; volatile bool isIntrusionDetected=false; // Sensor related variables volatile bool isSensorDetect; // IMU related variables volatile bool doorMove; volatile int isDoorClosed = 0; // Wifi related variables volatile char res=0; ////// Mutex Locks ////// Mutex pcSerialMutex; void IRsensor(void const *argument)//thread to read IR { AnalogIn distance_V(p20); float distance[3]; float distance_Vol = 0; float distance_Av; while(true) { if(isSystemArmed) { distance_Vol = distance_V; if (distance_Vol < 0.9) { //sensor never gives value above 0.9 distance[0] = distance[1]; distance[1] = distance[2]; distance[2] = distance_Vol; distance_Av = (distance[0] + distance[1] + distance[2]) / 3; //filtering isSensorDetect = distance_Av < 0.5 && distance_Av > 0.2; //detection range //every one of the samples should be greater than 0.15 isSensorDetect = isSensorDetect && distance[0] > 0.15; isSensorDetect = isSensorDetect && distance[1] > 0.15; isSensorDetect = isSensorDetect && distance[2] > 0.15; if (isSensorDetect) { myled2 = 1; sendRequest('M'); } else { myled2 = 0; } Thread::wait(50); } } else Thread::wait(0); } // while } void mic_thread(void const *argument)//thread to read in mic { AnalogIn mic(p15); float mic_sum = 0; float audiolevel = 0.0; while(true) { if(isSystemArmed){ for(int mic_ctr=0;mic_ctr<5;mic_ctr++){ audiolevel = mic.read(); mic_sum += audiolevel; } mic_sum /= 5; // filtering the mic output if (mic_sum>.8 && mic_sum<.95) { //thresholding the mic output myled3=1; sendRequest('S'); } else { myled3=0; } Thread::wait(1); }else Thread::wait(0); } } void imu_thread(void const *argument) { LSM9DS1 lol(p28, p27, 0xD6, 0x3C); lol.begin(); if (!lol.begin()) { pcSerialMutex.lock(); pc.printf("Failed to communicate with LSM9DS1.\n"); pcSerialMutex.unlock(); } lol.calibrate(); Thread::wait(500); lol.readMag(); lol.readGyro(); float degree = 0; float oldgyro = 0; float oldDegree = 0; oldDegree = lol.calcMag(lol.mx); oldDegree = (oldDegree * oldDegree * 2511.9 - 1759 * oldDegree) + 311; pcSerialMutex.lock(); pc.printf("Old Degree is: %4.2f\r\n", oldDegree); pcSerialMutex.unlock(); bool doorMoveMag; bool doorMoveGyro; int isDoorClosed = 0; //there are 3 states. 0 is closed, 1 is open and 2 is halfway between. if (oldDegree > 85) { isDoorClosed = 1; } else if (oldDegree < 10) { isDoorClosed = 0; } else { isDoorClosed = 2; } while(true) { if(isSystemArmed) { //saves old gyroscope values and sums up all axes. oldgyro = lol.gx + lol.gy + lol.gz; lol.readMag(); lol.readGyro(); if (isSystemArmedChanged) { oldDegree = lol.calcMag(lol.mx); oldDegree = (oldDegree * oldDegree * 2511.9 - 1759 * oldDegree) + 311; pcSerialMutex.lock(); pc.printf("Old Degree is: %4.2f\r\n", oldDegree); pcSerialMutex.unlock(); isSystemArmedChanged = false; } //reads in new gyroscope values degree = lol.calcMag(lol.mx); //convert the raw values to degrees degree = (degree * degree * 2511.9 - 1759 * degree) + 311; if (abs(degree - oldDegree) > 20) { doorMoveMag = 1; pcSerialMutex.lock(); pc.printf("Degree is: %4.2f\r\n", degree); pcSerialMutex.unlock(); } else { doorMoveMag = 0; } if (degree > 85) { isDoorClosed = 1; } else if (degree < 10) { isDoorClosed = 0; } else { isDoorClosed = 2; } if(((lol.gx + lol.gy + lol.gz)-oldgyro)>800) { //compares newly recorded gyroscope values to old one. Sensitivity can be adjusted by changing the number. doorMoveGyro = 1; } else { doorMoveGyro = 0; } doorMove = doorMoveGyro || doorMoveMag; if (doorMove) { myled1=1; sendRequest('O'); } else { myled1 = 0; } Thread::wait(100); } else { Thread::wait(0); } } } void get_thread(void const *argument) { while(true) { res=sendRequest('L'); Thread::wait(5000); } } int main() { myled1=0; myled2=0; myled3=0; myled4=0; /////// Initialization ////// reset = 0; //hardware reset for 8266 pc.baud(9600); // set what you want here depending on your terminal program speed pc.printf("\f\n\r-------------ESP8266 Hardware Reset-------------\n\r"); reset = 1; timeout = 2; getreply(); esp.baud(9600); // change this to the new ESP8266 baudrate if it is changed at any time. //ESPsetbaudrate(); //****************** include this routine to set a different ESP8266 baudrate ****************** ESPconfig(); //****************** include Config to set the ESP8266 configuration *********************** //pc.attach(&pc_recv, Serial::RxIrq); //esp.attach(&dev_recv, Serial::RxIrq); ////// Thread Initialization ////// Thread thread1(IRsensor); Thread thread2(imu_thread); Thread thread3(get_thread); Thread thread4(mic_thread); while (true) { while (isSystemArmed) { if(res=='0') { if (isSystemArmed) { isSystemArmedChanged = true; } else { isSystemArmedChanged = false; } isSystemArmed=false; isIntrusionDetected=false; } if(res=='1') { if (!isSystemArmed) { isSystemArmedChanged = true; } else { isSystemArmedChanged = false; } isSystemArmed=true; isIntrusionDetected=false; } if(res == '2') { if (!isSystemArmed) { isSystemArmedChanged = true; } else { isSystemArmedChanged = false; } isSystemArmed=true; isIntrusionDetected=true; } int k = 0; while(isIntrusionDetected) { myled4=1; //Alarm goes off Speaker mySpeaker(p21); mySpeaker.PlayNote(969.0, 0.5, 0.5); mySpeaker.PlayNote(800.0, 0.5, 0.5); k++; if (k == 10) { if(res=='0') { if (isSystemArmed) { isSystemArmedChanged = true; } else { isSystemArmedChanged = false; } isSystemArmed=false; isIntrusionDetected=false; } if(res=='1') { if (!isSystemArmed) { isSystemArmedChanged = true; } else { isSystemArmedChanged = false; } isSystemArmed=true; isIntrusionDetected=false; } if(res == '2') { if (!isSystemArmed) { isSystemArmedChanged = true; } else { isSystemArmedChanged = false; } isSystemArmed=true; isIntrusionDetected=true; } k = 0; } } } myled4=0; while (!isSystemArmed) { if(res=='0') { if (isSystemArmed) { isSystemArmedChanged = true; } else { isSystemArmedChanged = false; } isSystemArmed=false; isIntrusionDetected=false; } if(res=='1') { if (!isSystemArmed) { isSystemArmedChanged = true; } else { isSystemArmedChanged = false; } isSystemArmed=true; isIntrusionDetected=false; } if(res == '2') { if (!isSystemArmed) { isSystemArmedChanged = true; } else { isSystemArmedChanged = false; } isSystemArmed=true; isIntrusionDetected=true; } } } }
wifi.h
#include "mbed.h" Serial pc(USBTX, USBRX); Serial esp(p13, p14); // tx, rx DigitalOut reset(p26); Timer t; int t1=1,t2=2; int count,ended,timeout; char buf[2024]; char snd[1024]; Mutex espMutex; char ssid[32] = "GT-EE-CS"; // enter WiFi router ssid inside the quotes char pwd [32] = "Georgiatech4642"; // enter WiFi router password inside the quotes void SendCMD(),getreply(),ESPconfig(),ESPsetbaudrate(), sendHTTPRequest(); void dev_recv() { while(esp.readable()) { pc.putc(esp.getc()); } } void pc_recv() { while(pc.readable()) { esp.putc(pc.getc()); } } // Sets new ESP8266 baurate, change the esp.baud(xxxxx) to match your new setting once this has been executed void ESPsetbaudrate() { strcpy(snd, "AT+CIOBAUD=115200\r\n"); // change the numeric value to the required baudrate SendCMD(); } // +++++++++++++++++++++++++++++++++ This is for ESP8266 config only, run this once to set up the ESP8266 +++++++++++++++ void ESPconfig() { wait(5); pc.printf("\f---------- Starting ESP Config ----------\r\n\n"); strcpy(snd,".\r\n.\r\n"); SendCMD(); wait(1); pc.printf("---------- Reset & get Firmware ----------\r\n"); strcpy(snd,"node.restart()\r\n"); SendCMD(); timeout=5; getreply(); pc.printf(buf); wait(2); pc.printf("\n---------- Connecting to AP ----------\r\n"); pc.printf("ssid = %s pwd = %s\r\n",ssid,pwd); strcpy(snd, "wifi.sta.config(\""); strcat(snd, ssid); strcat(snd, "\",\""); strcat(snd, pwd); strcat(snd, "\")\r\n"); SendCMD(); timeout=10; getreply(); pc.printf(buf); wait(5); //pc.printf("\n---------- Get IP's ----------\r\n"); // strcpy(snd, "print(wifi.sta.getip())\r\n"); // SendCMD(); // timeout=3; // getreply(); // pc.printf(buf); // wait(1); pc.printf("\n---------- Get Connection Status ----------\r\n"); strcpy(snd, "print(wifi.sta.status())\r\n"); SendCMD(); timeout=5; getreply(); pc.printf(buf); wait(1); } void sendHTTPMotionRequest() { espMutex.lock(); pc.printf("\n---------- Sending Motion Request ----------\r\n"); strcpy(snd, "conn=net.createConnection(net.TCP, false)\r\n"); SendCMD(); timeout = t1; getreply(); Thread::wait(10); strcpy(snd, "conn:on(\"receive\", function(conn, pl) print(pl) end)\r\n"); SendCMD(); timeout = t1; getreply(); Thread::wait(10); // URL strcpy(snd, "conn:connect(80 ,\"young-hollows-48050.herokuapp.com\")\r\n"); SendCMD(); timeout = t1; getreply(); Thread::wait(10); // BASE URL strcpy(snd, "conn:send(\"POST /alarm HTTP/1.1\\r\\nHost:young-hollows-48050.herokuapp.com\\r\\n"); strcat(snd, "Connection: keep-alive\\r\\nAccept: */*\\r\\n"); strcat(snd, "Content-Type: application/json\\r\\n"); strcat(snd, "Content-Length: 37\\r\\n\\r\\n"); strcat(snd, "{\\\"mbed_id\\\":\\\"1\\\",\\\"alarm_type\\\":\\\"motion\\\"}\\r\\n\")\r\n"); SendCMD(); timeout=t2; getreply(); pc.printf(buf); espMutex.unlock(); } void sendHTTPSoundRequest() { espMutex.lock(); pc.printf("\n---------- Sending Sound Request ----------\r\n"); strcpy(snd, "conn=net.createConnection(net.TCP, false)\r\n"); SendCMD(); timeout = t1; getreply(); Thread::wait(10); strcpy(snd, "conn:on(\"receive\", function(conn, pl) print(pl) end)\r\n"); SendCMD(); timeout = t1; getreply(); Thread::wait(10); // URL strcpy(snd, "conn:connect(80 ,\"young-hollows-48050.herokuapp.com\")\r\n"); SendCMD(); timeout = t1; getreply(); Thread::wait(10); // BASE URL strcpy(snd, "conn:send(\"POST /alarm HTTP/1.1\\r\\nHost:young-hollows-48050.herokuapp.com\\r\\n"); strcat(snd, "Connection: keep-alive\\r\\nAccept: */*\\r\\n"); strcat(snd, "Content-Type: application/json\\r\\n"); strcat(snd, "Content-Length: 36\\r\\n\\r\\n"); strcat(snd, "{\\\"mbed_id\\\":\\\"1\\\",\\\"alarm_type\\\":\\\"sound\\\"}\\r\\n\")\r\n"); SendCMD(); timeout=t2; getreply(); pc.printf(buf); espMutex.unlock(); } void sendHTTPDoorRequest() { espMutex.lock(); pc.printf("\n---------- Sending Door Request ----------\r\n"); strcpy(snd, "conn=net.createConnection(net.TCP, false)\r\n"); SendCMD(); timeout = t1; getreply(); Thread::wait(10); strcpy(snd, "conn:on(\"receive\", function(conn, pl) print(pl) end)\r\n"); SendCMD(); timeout = t1; getreply(); Thread::wait(10); // URL strcpy(snd, "conn:connect(80 ,\"young-hollows-48050.herokuapp.com\")\r\n"); SendCMD(); timeout = t1; getreply(); Thread::wait(10); // BASE URL strcpy(snd, "conn:send(\"POST /alarm HTTP/1.1\\r\\nHost:young-hollows-48050.herokuapp.com\\r\\n"); strcat(snd, "Connection: keep-alive\\r\\nAccept: */*\\r\\n"); strcat(snd, "Content-Type: application/json\\r\\n"); strcat(snd, "Content-Length: 35\\r\\n\\r\\n"); strcat(snd, "{\\\"mbed_id\\\":\\\"1\\\",\\\"alarm_type\\\":\\\"door\\\"}\\r\\n\")\r\n"); SendCMD(); timeout=t2; getreply(); pc.printf(buf); espMutex.unlock(); } char sendHTTPAlarmRequest() { espMutex.lock(); pc.printf("\n---------- Sending Alarm Request ----------\r\n"); strcpy(snd, "conn=net.createConnection(net.TCP, false)\r\n"); SendCMD(); timeout = t1; getreply(); Thread::wait(10); strcpy(snd, "conn:on(\"receive\", function(conn, pl) print(pl) end)\r\n"); SendCMD(); timeout = t1; getreply(); Thread::wait(10); // URL strcpy(snd, "conn:connect(80 ,\"young-hollows-48050.herokuapp.com\")\r\n"); SendCMD(); timeout = t1; getreply(); Thread::wait(10); // BASE URL strcpy(snd, "conn:send(\"GET /alarm HTTP/1.1\\r\\nHost:young-hollows-48050.herokuapp.com\\r\\n"); strcat(snd, "Connection: keep-alive\\r\\nAccept: */*\\r\\n\\r\\n\")\r\n"); SendCMD(); timeout=t2; getreply(); pc.printf(buf); for(int bufCtr=0;bufCtr<sizeof(buf);bufCtr++){ if(buf[bufCtr]=='$'){ espMutex.unlock(); return buf[bufCtr+1]; } } espMutex.unlock(); return NULL; } void sendHTTPArmRequest() { espMutex.lock(); pc.printf("\n---------- Sending Arm Request ----------\r\n"); strcpy(snd, "conn=net.createConnection(net.TCP, false)\r\n"); SendCMD(); timeout = t1; getreply(); Thread::wait(10); strcpy(snd, "conn:on(\"receive\", function(conn, pl) print(pl) end)\r\n"); SendCMD(); timeout = t1; getreply(); Thread::wait(10); // URL strcpy(snd, "conn:connect(80 ,\"young-hollows-48050.herokuapp.com\")\r\n"); SendCMD(); timeout = t1; getreply(); Thread::wait(10); // BASE URL strcpy(snd, "conn:send(\"GET /arm HTTP/1.1\\r\\nHost:young-hollows-48050.herokuapp.com\\r\\n"); strcat(snd, "Connection: keep-alive\\r\\nAccept: */*\\r\\n\\r\\n\")\r\n"); SendCMD(); timeout=t2; getreply(); pc.printf(buf); espMutex.unlock(); } void sendHTTPDisarmRequest() { espMutex.lock(); pc.printf("\n---------- Sending Disarm Request ----------\r\n"); strcpy(snd, "conn=net.createConnection(net.TCP, false)\r\n"); SendCMD(); timeout = t1; getreply(); Thread::wait(10); strcpy(snd, "conn:on(\"receive\", function(conn, pl) print(pl) end)\r\n"); SendCMD(); timeout = t1; getreply(); Thread::wait(10); // URL strcpy(snd, "conn:connect(80 ,\"young-hollows-48050.herokuapp.com\")\r\n"); SendCMD(); timeout = t1; getreply(); Thread::wait(10); // BASE URL strcpy(snd, "conn:send(\"GET /disarm HTTP/1.1\\r\\nHost:young-hollows-48050.herokuapp.com\\r\\n"); strcat(snd, "Connection: keep-alive\\r\\nAccept: */*\\r\\n\\r\\n\")\r\n"); SendCMD(); timeout=t2; getreply(); pc.printf(buf); espMutex.unlock(); } char sendRequest(char arg){ int numNewLines=0;char return_val = NULL; while(numNewLines<2){ if (arg=='L') return_val = sendHTTPAlarmRequest(); if (arg=='D') sendHTTPDisarmRequest(); if (arg=='A') sendHTTPArmRequest(); if (arg=='O') sendHTTPDoorRequest(); if (arg=='S') sendHTTPSoundRequest(); if (arg=='M') sendHTTPMotionRequest(); for(int newLineCtr=0;newLineCtr<sizeof(buf);newLineCtr++){ if(buf[newLineCtr]=='\n')numNewLines++; } } return return_val; } void SendCMD() { esp.printf("%s", snd); } void getreply() { memset(buf, '\0', sizeof(buf)); t.start(); ended=0; count=0; while(!ended) { if(esp.readable()) { buf[count] = esp.getc(); count++; } if(t.read() > timeout) { ended = 1; t.stop(); t.reset(); } } }
Front End
Authentication:
Homepage:
Front End Code
Front End HTML Code
<!DOCTYPE html> <html> <head> <title>Webcam Dashboard</title> <basefont size="2"> <style type="text/css"> body { font-size:25px; } #arm-button { width: 200px; height: 45px; font-size: 35px; text-align: center; } #disarm-button { width: 200px; height: 45px; font-size: 35px; text-align: center; } #floorplan { position: relative; background-image: url("floorplan.jpg"); width: 613px; height: 553px; } #circle1, #circle2, #circle3 { position: absolute; width:20px; height: 20px; border: 2px solid black; background-color: green; border-radius: 50%; } #circle1 { left: 12px; top: 170px; background-color: <%= motion1 == "Yes" || sound1 == "Yes" || door1 == "Yes" ? "red" : "green"; %>; } #circle2 { left: 310px; top: 205px; background-color: <%= motion2 == "Yes" || sound2 == "Yes" || door2 == "Yes" ? "red" : "green"; %>; } #circle3 { left: 344px; top: 278px; background-color: <%= motion3 == "Yes" || sound3 == "Yes" || door3 == "Yes" ? "red" : "green"; %>; } </style> <script src="https://code.jquery.com/jquery-2.2.3.min.js" integrity="sha256-a23g1Nt4dtEYOj7bR+vTu7+T8VP13humZFBJNIYoEJo=" crossorigin="anonymous"></script> <script type="text/javascript"> function initialize() { $('#arm-button').click(function() { $.get('/arm') .then(function() { $('#arm-status').text("armed"); }) }); $('#disarm-button').click(function() { $.get('/disarm') .then(function() { $('#arm-status').text("disarmed"); }) }); setTimeout(function() { location.reload(true); }, 3000); } document.addEventListener('DOMContentLoaded', initialize); </script> </head> <body> <p><%= alarmMessage %></p> <!-- <img id="floorplan" src="/latest.jpg" /> --> <div id="floorplan" src="floorplan.jpg"> <div id="circle1"></div> <div id="circle2"></div> <div id="circle3"></div> </div> <table> <tr> <td><b>Door:</b></td> <td align="center"><b> Front(1) <b></td> <td align="center"><b> Hallway(2) <b></td> <td align="center"><b> Bedroom(3) <b></td> </tr> <tr> <td><b>Motion:</b></td> <td align="center"><%= motion1 %></td> <td align="center"><%= motion2 %></td> <td align="center"><%= motion3 %></td> </tr> <tr> <td><b>Sound:</b></td> <td align="center"><%= sound1 %></td> <td align="center"><%= sound2 %></td> <td align="center"><%= sound3 %></td> </tr> <tr> <td><b>Door Movement:</b></td> <td align="center"><%= door1 %></td> <td align="center"><%= door2 %></td> <td align="center"><%= door3 %></td> </tr> </table> <button id="arm-button">Arm</button> <button id="disarm-button">Disarm</button> <p>System is <span id="arm-status"><%= armed ? "armed" : "disarmed" %></span></p> </body> </html>
Component List
- Mbed – LPC1768
- IR distance sensor
- ESP8266 Huzzah Board
- Sparkfun RGB LED
- 9 Axis IMU - LSM9DS0
- Touch Keypad 12-key - MPR121
- Power Supply - 5V DC 2A Barrel Jack
- MEMS Microphone Breakout
- MicroSD Card
- Small 8Ohm Speaker
- LinkSprite JPEG Color Camera
Hookup Guide
mbed | Device |
---|---|
GND | Breadboard Ground Rail |
VOUT | Breadboard 3.3V Rail |
Vin | 5V DC Supply |
p5 | microSD DI |
p6 | microSD DO |
p7 | microSD SCK |
p8 | microSD CS |
p15 | Audio Amp IN+ |
p20 | IR Sensor Out |
p21 | Green LED (+ 100Ohm resistor) |
p22 | Red LED (+100Ohm resistor) |
p15 | microphone Out |
p28 | IMU MISO |
p27 | IMU MOSI |
p13 | ESP8266 RX |
p14 | ESP8266 TX |
p26 | ESP8266 Reset |
p21 | Speaker + |
p24 | RGB LED Red |
p23 | RGB LED Green |
p21 | RGB LED Blue |
p11 | Red LED + 1kOhm Resistor |
p9 | Capacitive Touch Keypad MOSI |
p10 | Capacitive Touch Keypad MISO |
p28 | JPEG Camera TX |
p27 | JPEG Camera RX |
microSD | |
---|---|
GND | Ground Rail |
VCC | 3.3V Supply Rail |
Class D | Audio Amp Breakout |
---|---|
IN- | Ground Rail |
PWR+ | 3.3V Supply Rail |
PWR- | Ground Rail |
VOL | 10K Trimpot |
OUT- | Speaker- |
OUT+ | Speaker+ |
The microphone needs to be amplified to give a proper range of values. The amplifier circuit is below:
IR Sensor | |
---|---|
Vin | 5V Supply Rail |
GND | Ground Rail |
Photos of Project
Camera Output:
Please log in to post comments.