Project tutorial
Connected Security System

Connected Security System © GPL3+

Reinventing the home security system with the IoT method using sensors connected to a Node.JS server.

  • 7,570 views
  • 2 comments
  • 21 respects

Components and supplies

About this project

The Idea

Modern security systems have several disadvantages, some of which are:

  • As a user to you can't customize the system the way you want
  • The panel is in a centralized location, if you can't get to it and you don't have a keyfob handy, there is no way to trigger the alarm or arm it
  • There may be vulnerabilities that robbers are aware of with that specific system that haven't been patched, I know that the panel we used to have for years never got any kind of updates
  • Most of the existing companies that do advanced modern systems usually need to put holes in the wall for wires or mounting, which might not be allowed if your in a rental, and that means you can't move it with you if you go to a new place

Thinking through those things, I came up with an idea for a wireless connected alarm system, that is modular in such a way that it can be installed in any location, and be easily moved to a new place.

How the sensors would work

Like a typical system, all the sensors would be in their own self-contained packages that are either magnetized to the door/window, or stuck on the surface with double-sided mounting tape that's easy to remove.

All the sensors would connect to a central NodeJS server on the local network that would save their status', handle sensor events, and provide a point of access either internally or remotely for an admin panel.

But if the network wasn't available, instead one of the sensors would switch to hosting an Ad-Hoc network that all the sensor would connect to, and it would manage basic alarm functionality until the main server comes online again.

This effectively creates a system where there is no simple single point of entry, eliminating the potential issues that come with having a central panel that could potentially be knocked out to disable the system. Having the sensors also connect to each other means that even if one is knocked-out of the system, all the others are still active.

Points of Access

To access the system, you have several options:

  • Create a panel that you mount somewhere that connects to the server and allows you to control the system
  • Connect to the server via your laptop of phone and view a webpage with settings and controls
  • Use other devices such as a raspberry pie or an Hexiwear to create a remote from the system. The Hexiwear is especially suited for it because of it's low costs, and the sensors it has which could also be used for events in the system.

Also because the system would be running on a NodeJS server, you could port-forward to the server and connect from anywhere in the world, not just from in your house.

Making it Happen

At this point I don't have the money to buy all the components the build a full system, but I'm going to make use of what I have and at least make a small scale one for now.

For this project I'll be using my:

  • Beta Arduino MKR1000
  • Particle Photon
  • Intel Edison
  • Hexiwear
  • And maybe my TI Launchpad

For sensors I'll be using:

  • Some pieces of tin-foil for door/windows. Ideally I'd use reed-switches but I don't have any on hand right now
  • A cheap $5 360p webcam from the Dollar store along with my Intel Edison for a camera
  • Some photo-diodes and a laser for a laser trip wire
  • A basic Microphone for detecting sound, probably one salvaged from some old ear-buds

Out of this whole program the NodeJS server is the simplest part. Connecting all the sensors and microcontrollers will probably be the hard part, along with having them communicate with the NodeJS server.

Also I don;t have the time right now to put into making the sensors a connected cloud type setups for when the server goes down, so for this project it will just be a single server.

Hexiwear - Getting Started

Since I already know how to use and program all the other microcontrollers I'll be using, and how to program the NodeJS server, I'm starting with figuring out how to get the Hexiwear to work.

Hexiwear - IDE Options

There are the two options I mentioned before, the Kinetis IDE (KDE), or the mBed online IDE.

mBed

Yesterday the Hexiwear team started posting more examples for using the mBed platform for programming the Hexiwear, and answering some questions on the forum for how to use the OLED through the mBed platform.

Ideally I would like to go with using the mBed platform, as it's simpler to use, but I need to figure out how to fully use the OLED before I can consider it.

KDE

The usual/pro way to program it would be using KDE. Unfortunately though I tried to for 3 days and couldn't get very far due to the lack of any kind of libraries or basic project templates for Hexiwear projects. The factory demo project could access all the sensors and the OLED, but it also depended on a lot of other files (some unnecessary for what I was doing) that created quite a bloated project.

I'm going to wait a could days and see if I can figure out how to use the OLED in mBed before deciding the use KDE, as mbed would speed us the process a ton.

Using mbed

I decided to go with using mbed, over the last few days the Hexiwear team have been adding a ton of example code that helped me get started and figure out how to use the different sensors via mbed.

For drawing on the OLED, I'll be using the Hexiwear team's official SSD1351 library.

Hexiwear - Creating a New Project

I went ahead and created a new mbed project called "security-console" which I will make public when I'm finished. Then I imported the SSD1351 library via it's url.

Hexiwear - Displaying the Time

Here is some basic code for displaying the time on the screen using the Real Time Clock and the SSD1351 library. You'll need to use your phone with the Hexiwear app to set the time on the Hexiwear.

#include "mbed.h" 
#include "Hexi_OLED_SSD1351.h" 
#include "string.h" 
DigitalOut led_green(LED_GREEN); 
// Connect to the oled 
SSD1351 oled(PTB22,PTB21,PTC13,PTB20,PTE6, PTD15); /* (MOSI,SCLK,POWER,CS,RST,DC) */ 
int main() { 
// Buffer to store label text 
char text[20]; 
// Use default properties 
oled_text_properties_t textProperties = {0}; 
oled.GetTextProperties(&textProperties);     
// Fill the screen     
oled.FillScreen(COLOR_BLACK); 
// Set text color to white and left aligned 
textProperties.fontColor = COLOR_WHITE; 
textProperties.alignParam = OLED_TEXT_ALIGN_CENTER; 
oled.SetTextProperties(&textProperties);     
while (true) { 
time_t seconds = time(NULL); // Get the time in unix format 
const tm *t = localtime (&seconds); // Convert the unix time to actual time 
char* s = "AM"; // The suffix to use for the time of day 
int h = t->tm_hour; // The hours 
if (h > 12){ // If it's entering 24/h time, change it to 12/h and add PM 
    s = "PM"; 
    h = h - 12;     
} 
// Format the time 
sprintf(text,"%d:%d %s",h, t->tm_min, s); 
// Display the time on screen - we're using a full width textbox so it is centered
oled.TextBox((uint8_t *)text,2,2, 91, 15);  
// Flash the green led 
led_green = !led_green; 
Thread::wait(1000); 
} 
} 

Hexiwear - Creating the Images

Next thing we need are some images to draw on the screen. I'm creating the images with GIMP, and exporting them to Hexiwear code using my tutorial on exporting from GIMP for the Hexiwear.

Once we have the exported image code, we can create the files images.h and images.c to store the image data arrays. (code in the project repository at the end of the project)

Now we just need to include the images header file, and then add this to out main:

...
const uint8_t *borderImage; 
borderImage = border_bmp; 
oled.DrawImage(borderImage,0,20); 
...

And now we get a nice white outline on the screen!

Hexiwear - Drawing Alarm Status

New we need to show is the alarm is on or not. We'll add a new variable for storing the alarm status:

bool armed = false; 

As well as a couple for storing the images:

const uint8_t *armedImage;  
armedImage = lock_bmp; 
const uint8_t *disarmedImage;  
disarmedImage = unlock_bmp;  

And then in the main loop we'll check if the alarm is armed or not and display the respective image:

if(armed){ 
oled.DrawImage(armedImage,0,20); 
}else{ 
oled.DrawImage(disarmedImage,0,20); 
}  

Hexiwear - Getting the Alarm Status

Now since there currently isn't an mbed library for interacting with the Bluetooth on the Hexiwear, we can't use that to change the alarm status.

So what I've decided to do instead is to using the Hexiwear and the base like a control panel, and use the expansion headers to connect the Hexiwear to the Intel Edison running the alarm server via UART and have the Edison send the alarm status to the Hexiwear.

Intel Edison - NodeJS - Creating the Server

To connect everything together we'll be using a Node.JS server running on the Intel Edison.

I'll be creating the server on my laptop, and then uploading it to the Edison - this makes it easier to write and test. The server will use Express for handling get and post calls.

Ideally we would send JSON, but unfortunately it's not easy to parse on the microcontrollers like the Photon and Arduino MKR1000. So instead we'll have to make separate query's to the server to get the alarm and armed status instead of just one.

var express = require('express'); 
var app = express(); 
var armed = false; // true if armed 
var alarm = false; // true is alarm is triggered 
app.get('/armed', function (req, res) { 
res.send(armed); 
}); 
app.get('/alarm', function (req, res) { 
res.send(alarm); 
}); 
app.listen(3000, function () { 
console.log('Server listening on 3000!'); 
}) 

Now we need to make a way to sent the statuses. To keep is simple we'll use get requests instead of posts, as posts are harder to do on some platforms so there's no reason for not using get requests instead.

...
app.get('/armed/:armed', function (req, res) { 
var on = req.params.armed; 
armed = on; 
res.send('ok').status(200).end();
}); 
app.get('/alarm/:alarm', function (req, res) { 
var on = req.params.alarm; 
alarm = on; 
res.send('ok').status(200).end();
});
...  

Now we get just do a get request to "/armed/true" to set it to true, and "/armed" if we want to check if it's armed.

I used SFTP to upload the code to my Edison, and then put it in a special folder that runs all the scripts in it when the Edison boots.

Photon - Photon Code

I'll be using my Particle Photon as one of the sensors for the alarm. I'm using the HttpClient library for get requests which you can add via the libraries tab in the Particle IDE.

The code for the Photon is pretty basic, we just need to send a get request to the server to trigger the alarm when the door sensor is triggered.

// This #include statement was automatically added by the Particle IDE. 
#include "HttpClient/HttpClient.h" 
#define ADDRESS "192.168.0.27" 
#define PORT 3000 
int pin = D0; 
int led = D7; 
HttpClient http; 
http_request_t request; 
http_response_t response; 
void setup() { 
pinMode(pin, INPUT_PULLDOWN); 
pinMode(led, OUTPUT); 
Serial.begin(9600); 
} 
bool sentOn = false; 
bool sentOff = true; 
void loop() { 
if(digitalRead(pin) == HIGH){ 
  if(!sentOn){ 
      digitalWrite(led, HIGH); 
      Serial.println("HIGH"); 
      send("true"); 
      sentOn = true; 
      sentOff = false; 
  } 
} 
if(digitalRead(pin) == LOW){ 
  digitalWrite(led, LOW); 
  sentOn = false; 
/*   Optionally reset the alarm status when sensor isn't triggered  
  if(!sentOff){ 
      Serial.println("LOW"); 
      send("false"); 
      digitalWrite(led, HIGH); 
      sentOff = true; 
  } */ 
}
} 
void send(String on){ 
Serial.println("sending..."); 
request.hostname = ADDRESS; 
request.port = PORT; 
request.path = "/alarm/"+on; 
Serial.println(request.path); 
http.get(request, response, NULL); 
Serial.println(response.status); 
Serial.println(response.body); 
Serial.println("sent!"); 
} 

Now all we need to do it attach something to the +3.3v pin and to the D0 pin, and set it up so that they touch when you want the alarm to be triggered. You might also want to reverse it so that it triggers when the contacts are separated, in the case of a window or door.

MKR1000 - Programming

I all also use my MKR1000 as another sensor. It will do the same thing as the Photon and just update the alarm status if a sensor is triggered.

#include <SPI.h> 
#include <WiFi101.h> 
char ssid[] = "RCMP14"; 
char pass[] = "spatialguru"; 
int status = WL_IDLE_STATUS; 
char server[] = "192.168.0.27"; 
int sensorPin = 6; 
WiFiClient client; 
bool sentHigh = false; 
void setup() { 
Serial.begin(9600); 
pinMode(sensorPin, INPUT); 
while (status != WL_CONNECTED) { 
 Serial.print("Attempting to connect to SSID: "); 
 Serial.println(ssid); 
 status = WiFi.begin(ssid, pass); 
 // wait 10 seconds for connection: 
 delay(10000); 
} 
Serial.println("Connected to wifi"); 
} 
void loop() { 
if(digitalRead(sensorPin) == HIGH){ 
 if(!sentHigh){ 
   sentHigh = true; 
   sendStatus("true"); 
 } 
}else{ 
 sentHigh = false; 
}  
} 
void sendStatus (char* status){ 
Serial.println("\nStarting connection to server..."); 
if (client.connect(server, 3000)) { 
 Serial.println("connected to server"); 
 // Make a HTTP request: 
 client.println(String("GET /alarm/") +status+" HTTP/1.1"); 
 client.println(String("Host: ") + server); 
 client.println("Connection: close"); 
 client.println(); 
 client.stop(); 
 Serial.println(String("sent alarm status! ") + status); 
} 
} 

Hexiwear - Connecting Hexiwear to the Server

Now since there are no libraries yet for using the Bluetooth chip in the Hexiwear via mbed, the best way I can figure out to connect the Hexiwear to the server is to use one of the pairs of UART pins on the Hexiwear dock, and attach it to the uart pins on the Edison.

Then we can just send serial messages back and fourth to update the status.

Once the Bluetooth chip is made available through mbed, along with the capacitive touch sensors, then we'll be able to use it without the dock, but for now this is all we can do.

If the mbed code, we'll open a serial connection and listen for the serial messages. At the top of the mbed main.cpp, we'll define a serial connection on the tx and rx pins on the first click sockets on the dock.

Serial eddy(PTD3, PTD2); // tx rx 

Then in the main loop we'll listen for available data, and change the bool as needed:

if(eddy.readable()) { 
  char read = eddy.getc(); 
  if(read == '0'){ 
      armed = false; 
  }else{ 
      armed = true; 
  } 
} 

Edison - Connecting Hexiwear to the Server

Now to do serial communications from NodeJS, we need to install the serialport Node package.

npm install serialport --save

Then at the top of the NodeJS main file, we'll define the port:

var SerialPort = require("serialport"); 
var port = "/dev/ttyMFD1"; 
var serialPort = new SerialPort(port, { autoOpen:false}); 

And then we open the port and make sure there aren't any errors:

serialPort.open(function (error) {     
if (error) {     
   console.log('Failed to open serial port: '+error);     
} else {     
   console.log('opened serial port!');     
} 
});   

I'm creating a separate function for sending the serial status to keep things clean:

function sendStatus(status){ 
 serialPort.write(status, function(err) {     
 if(err) {     
     console.log('err writing serial data' + err);     
 }else{     
     console.log('wrote serial data ' + status + '!');     
 }     
} 

Now we just update it when the alarm status is changed!

app.get('/armed/:armed', function (req, res) { 
 var on = req.params.armed; 
 armed = on; 
 res.send("ok").status(200).end(); 
 console.log('armed: ' + on); 
 sendStatus(on == 'true' ? '1' : '0'); 
}); 

Hexiwear - Showing alarm on the Hexiwear

Now I want to make the vibration motor in the Hexiwear buzz when the alarm is triggered.

I also added a new image into the program for when the alarm is triggered.

First register the pin for the vibration motor:

DigitalOut vib(PTB9);

Now for the code to draw it. I'm using nested if statements so that the alarm status takes priority over drawing the armed image:

if(alarm){ 
   vib = !vib; 
   oled.DrawImage(alarmImage,0,20); 
   }else{         
   if(armed){ 
       oled.DrawImage(armedImage,0,20); 
   }else{ 
       oled.DrawImage(disarmedImage,0,20); 
   } 
} 

Now we'll just modify the code so that when the Node script sends a 2 the alarm is on, and a 0 resets it.

if(eddy.readable()) { 
  char read = eddy.getc(); 
  if(read == '0'){ 
       armed = false; 
  }else if (read == '1'){ 
      alarm = false; 
      armed = true; 
  }else if (read == '2'){ 
      alarm = true; 
  } 
} 

Edison - Showing Alarm on the Hexiwear

Now we just need to send the status via UART to the Hexiwear when the alarm is triggered:

if(on == 'true'){ 
   sendStatus('2'); 
}else{ 
   sendStatus(armed == 'true' ? '1' : '0'); 
} 

Fusion360 Cases (Downloads in Resources Section...)

I also designed a case for the Hexiwear base + attached Intel Edison, one that mounts on the wall for a single Hexiwear.

The dimensions are rough because I don't have a 3D printer to test the design with (I was suppose to have one in August, but there where some complications..) , so this is all I was able to do with the resources I had available ;)

Hexiwear docking station case

Hexiwear Wall Mount hexagonal case that screws to a wall and lets a Hexiwear slide in the top.

Conclusion

For now this completes my project! I want to expand it later to include more communications to help keep the device in sync. Also when the Bluetooth and capacitive touch buttons are available for the Hexiwear via mbed, I want to change to using Bluetooth for communications with the connected phone to contact the server, and add arm/disarm/alarm buttons on the Hexiwear.

The current setup still has a long way to go to reach the scope of my ideas outlined at the beginning of the project, but for now this is all I can do with the resources I have available.

Code

Particle Photon CodeC/C++
Code for turning the Photon into a sensor. Use at build.particle.io. Requires you to import the HttpClient library via the Particle Online IDE.
// This #include statement was automatically added by the Particle IDE.
#include "HttpClient/HttpClient.h"

#define ADDRESS "192.168.0.27" /* Change this to the IP of the device running the server! */
#define PORT 3000

int pin = D0;

int led = D7;

HttpClient http;

http_request_t request;
http_response_t response;

void setup() {
    pinMode(pin, INPUT_PULLDOWN);
    pinMode(led, OUTPUT);
    
    Serial.begin(9600);
    
}

bool sentOn = false;
bool sentOff = true;

void loop() {
    if(digitalRead(pin) == HIGH){
        if(!sentOn){
            digitalWrite(led, HIGH);
            Serial.println("HIGH");
            send("true");
            sentOn = true;
            sentOff = false;
        }
    }
    
    if(digitalRead(pin) == LOW){
        digitalWrite(led, LOW);
        sentOn = false;
        if(!sentOff){
            Serial.println("LOW");
            send("false");
            digitalWrite(led, HIGH);
            sentOff = true;
        }
    }
}

void send(String on){
    Serial.println("sending...");
    request.hostname = ADDRESS;
    request.port = PORT;
    request.path = "/alarm/"+on;
    Serial.println(request.path);
    
    http.get(request, response, NULL);
    
    Serial.println(response.status);
    Serial.println(response.body);
    Serial.println("sent!");
}
Arduino Sensor CodeC/C++
The code for the MKR1000 to turn it into a sensor
#include <SPI.h>
#include <WiFi101.h>

char ssid[] = "ssid";
char pass[] = "password";

int status = WL_IDLE_STATUS;

char server[] = "192.168.0.27"; /* ip of the device running the nodejs server  */

int sensorPin = 6;

WiFiClient client;

bool sentHigh = false;

void setup() {
  Serial.begin(9600);

  pinMode(sensorPin, INPUT);
  
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);

    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }
  Serial.println("Connected to wifi");
}

void loop() {
  if(digitalRead(sensorPin) == HIGH){
    if(!sentHigh){
        sentHigh = true;
        sendStatus("true");
      }
  }else{
    sentHigh = false;
  }
}

void sendStatus (char* status){
  Serial.println("\nStarting connection to server...");
  if (client.connect(server, 3000)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    client.println(String("GET /alarm/") +status+" HTTP/1.1");
    client.println(String("Host: ") + server);
    client.println("Connection: close");
    client.println();
    client.stop();
    Serial.println(String("sent alarm status! ") + status);
  }
}
mbed repository with the Hexiwear code
The mbed repository with all the code for programming the Hexiwear via the online mbed IDE/Compiler - Link to the mbed repo is in the Gist
Intel Edison Node.JS Server
Upload to the Edsion. npm install && node.

Custom parts and enclosures

F360 Hexiwear + Edison dock case
Hexiwear%20Case.f3z
F360 - Hexiwear Wall Mount
A sleek hexagonal holder that screws to the walls and allows a Hexiwear to slide into the top
Hexiwear%20Wall%20Mount.f3z

Comments

Similar projects you might like

Alarm System Security Put to the Test

Project tutorial by danionescu

  • 15,246 views
  • 5 comments
  • 26 respects

Ultrasonic Security System

Project tutorial by Ivan

  • 38,813 views
  • 27 comments
  • 86 respects

Security System And Access Control With Arduino And RFID

Project tutorial by Sarath P

  • 10,669 views
  • 1 comment
  • 23 respects

Bluetooth Security System

Project tutorial by Victor Carreño

  • 14,320 views
  • 2 comments
  • 37 respects

Security System | SW-420 | Arduino | GSM

by AbuTaj

  • 6,704 views
  • 3 comments
  • 9 respects

Security System With 1Sheeld

Project showcase by nada abdelnaby mady

  • 2,122 views
  • 0 comments
  • 2 respects
Add projectSign up / Login