Ralph Yamamoto
Published © GPL3+

Smart Home Security Camera System

Cost-effective camera system using a single PTZ IP camera to monitor 3 separate zones using PIR sensors to pan camera.

IntermediateFull instructions provided12 hours8,740

Things used in this project

Hardware components

SparkFun ESP8266 Thing - Dev Board
SparkFun ESP8266 Thing - Dev Board
×1
SparkFun - SparkFun ESP8266 Thing - Board
×1
SparkFun FTDI Basic Breakout - 3.3V
SparkFun FTDI Basic Breakout - 3.3V
×1
HC-SR501 PIR Motion Sensor Module
×2
Raspberry Pi 3 Model B
Raspberry Pi 3 Model B
×1
Red Laser 5mW 3-5V
×1
CDS Photocell
×2
FDT FD7903 Outdoor PTZ IP Camera
×1
2n3904 NPN Transistor
×1
Resistor 1K Ohm
×1
Resistor 10 Ohm
×2

Software apps and online services

Arduino IDE
Arduino IDE
Cayenne
myDevices Cayenne
Omxplayer
Linux Screen manager

Story

Read more

Schematics

Front Door Module Breadboard

Front Door Module Schematic

Driveway Module Breadboard

Driveway Module Schematic

Code

PIR-ESP8266ThingCayenne.ino

Arduino
Code for Front Door Module
// This example shows how to connect to Cayenne using an ESP8266 and send/receive sample data.
// Make sure you install the ESP8266 Board Package via the Arduino IDE Board Manager and select the correct ESP8266 board before compiling. 

//#define CAYENNE_DEBUG
#define CAM_ENABLE
//#define PAN_RESET
#define CAYENNE_PRINT Serial
#include <CayenneMQTTESP8266.h>

// WiFi network info.
const char ssid[] = "xxxxx";
const char wifiPassword[] = "xxxxx";
const char* host = "x.x.x.x";

int ledPin = 5;       //onboard blue LED connected to digital pin 5
int pirPin = 4;       //PIR output connected to digital pin 4
int laserPin = 13;    //laser on connected to digital pin 13
int uptimeCh = 0;     //channel for uptime
int pirCh = 2;        //channel for PIR detect
int tripCh = 3;       //channel for trip detect photocell
int laserCh = 4;      //channel for laser
int presetpanCh = 5;  //channel for pan to preset
int resetpanCh = 6;   //channel for reset pan
int valPIR = 0;
float valTrip = 0;
bool trigPIR = false;
bool firstTrig = false;

// Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
char username[] = "xxxxx";
char password[] = "xxxxx";
char clientID[] = "xxxxx";

unsigned long lastMillis = 0;
unsigned long trigTime = 0;

void setup() {
  pinMode(ledPin, OUTPUT);  //LED indication of Pan signal
  pinMode(laserPin, OUTPUT);  //Laser
  pinMode(pirPin, INPUT);  //PIR signal
  Serial.begin(9600);
  Cayenne.begin(username, password, clientID, ssid, wifiPassword);
}

void loop() {
  Cayenne.loop();
  lastMillis = millis();
  valPIR = digitalRead(pirPin);
  valTrip = analogRead(A0);

  //Write data to Cayenne here
  if(valPIR && !firstTrig) {
    trigPIR = true;
    firstTrig = true;
    trigTime = millis();
  }
  else {
    trigPIR = false;
  }
  if(!trigPIR && firstTrig && ((millis() - trigTime)/1000) > 20) {
    trigTime = 0;
    firstTrig = false;
    Cayenne.virtualWrite(resetpanCh, 1, "digital_sensor", "d"); //reset Pan after 20 seconds if no motion
  }
  else {
    Cayenne.virtualWrite(resetpanCh, 0, "digital_sensor", "d"); //do not reset Pan
  }
  Cayenne.virtualWrite(uptimeCh, lastMillis/1000);   //uptime in seconds
  Cayenne.virtualWrite(pirCh, valPIR, "digital_sensor", "d");
  Cayenne.virtualWrite(tripCh, valTrip, "analog_sensor", "null");  //trip photocell value
}

//Default function for processing actuator commands from the Cayenne Dashboard.
CAYENNE_IN(presetpanCh) {
  //CAYENNE_LOG("CAYENNE_IN_DEFAULT(%u) - %s, %s", request.channel, getValue.getId(), getValue.asString());

  int i = getValue.asInt();
  digitalWrite(ledPin, !i);

#ifdef CAM_ENABLE
  WiFiClient client;
  Serial.printf("\n[Connecting to %s ... ", host);
  if (client.connect(host, 80))
  {
    Serial.println("connected]");
    Serial.println("[Sending a request]");
    
    if (i)
    {
      client.print(String ("GET /") + "/cgi-bin/param.cgi?cmd=preset&-act=goto&-number=1 HTTP/1.1\r\n" +
                   "Host: " + host + "\r\n" +
                   "Connection: close\r\n" +
                   "Authorization: Basic XXXXX\r\n" +
                   "\r\n"
                  );
      Serial.println("[Response:]");
    }
    else
    {
      client.print(String ("GET /") + "/cgi-bin/param.cgi?cmd=preset&-act=goto&-number=0 HTTP/1.1\r\n" +
                   "Host: " + host + "\r\n" +
                   "Connection: close\r\n" +
                   "Authorization: Basic XXXXX\r\n" +
                   "\r\n"
                  );
      Serial.println("[Response:]"); 
    }
    while (client.connected())
    {
      if (client.available())
      {
        String line = client.readStringUntil('\n');
        Serial.println(line);
      }
    }
    client.stop();
    Serial.println("\n[Disconnected]");
  }
  else
  {
    Serial.println("connection failed!]");
    client.stop();
  }
  delay(5000);
#endif
}

CAYENNE_IN(laserCh) {
  //CAYENNE_LOG("CAYENNE_IN_DEFAULT(%u) - %s, %s", request.channel, getValue.getId(), getValue.asString());
  
  int i = getValue.asInt();
  digitalWrite(13, i);
  
  Serial.print("Laser ");
  if(i)
  {
    Serial.println("On"); 
  }
  else
  {
    Serial.println("Off"); 
  }
}

PIR-ESP8266ThingDevCayenne.ino

Arduino
Code for Driveway Module
// This example shows how to connect to Cayenne using an ESP8266 and send/receive sample data.
// Make sure you install the ESP8266 Board Package via the Arduino IDE Board Manager and select the correct ESP8266 board before compiling. 

//#define CAYENNE_DEBUG
#define CAM_ENABLE
//#define PAN_RESET
#define CAYENNE_PRINT Serial
#include <CayenneMQTTESP8266.h>

// WiFi network info.
char ssid[] = "xxxxx";
char wifiPassword[] = "xxxxx";
const char* host = "x.x.x.x";

int ledPin = 5;       //onboard blue LED connected to digital pin 5
int pirPin = 4;       //PIR output connected to digital pin 4
int uptimeCh = 0;     //channel for uptime
int pirCh = 2;        //channel for PIR detect
int ambCh = 3;        //channel for ambient light
int presetpanCh = 5;  //channel for pan to preset
int resetpanCh = 6;   //channel for reset pan
int valPIR = 0;
float valAtoD = 0;
bool trigPIR = false;
bool firstTrig = false;

// Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
char username[] = "xxxxx";
char password[] = "xxxxx";
char clientID[] = "xxxxx";

unsigned long lastMillis = 0;
unsigned long trigTime = 0;

void setup() {
  pinMode(ledPin, OUTPUT);  //LED
  pinMode(pirPin, INPUT);   //PIR signal
  pinMode(A0, INPUT);       //Ambient light photocell connected to AtoD
	Serial.begin(9600);
	Cayenne.begin(username, password, clientID, ssid, wifiPassword);
}

void loop() {
	Cayenne.loop();
	lastMillis = millis();
  valPIR = digitalRead(pirPin);
  valAtoD = analogRead(A0);

#ifdef CAYENNE_DEBUG    //output values to serial monitor if debug
    Serial.print("valPIR: ");
    Serial.println(valPIR);
    Serial.print("valAtoD: ");
    Serial.println(valAtoD);
#endif
  
	//Write data to Cayenne here
  if(valPIR && !firstTrig) {
    trigPIR = true;
    firstTrig = true;
    trigTime = millis();
  }
  else {
    trigPIR = false;
  }
  if(!trigPIR && firstTrig && ((millis() - trigTime)/1000) > 20) {
    trigTime = 0;
    firstTrig = false;
    Cayenne.virtualWrite(resetpanCh, 1, "digital_sensor", "d"); //reset Pan after 20 seconds if no motion
  }
  else {
    Cayenne.virtualWrite(resetpanCh, 0, "digital_sensor", "d"); //do not reset Pan
  }  
	Cayenne.virtualWrite(uptimeCh, lastMillis/1000);   //uptime in seconds
  Cayenne.virtualWrite(pirCh, valPIR, "digital_sensor", "d");   //PIR detect signal
	Cayenne.virtualWrite(ambCh, valAtoD, "analog_sensor", "null");  //Ambient light

}

//Default function for processing actuator commands from the Cayenne Dashboard.
//You can also use functions for specific channels, e.g CAYENNE_IN(1) for channel 1 commands.
CAYENNE_IN(presetpanCh)
{ //turn on blue LED in response to trigger
	CAYENNE_LOG("CAYENNE_IN_DEFAULT(%u) - %s, %s", request.channel, getValue.getId(), getValue.asString());
	//Process message here. If there is an error set an error message using getValue.setError(), e.g getValue.setError("Error message");

  int i = getValue.asInt();
  digitalWrite(ledPin, !i);

#ifdef CAM_ENABLE
  WiFiClient client;
  Serial.printf("\n[Connecting to %s ... ", host);
  if (client.connect(host, 80))
  {
    Serial.println("connected]");
    Serial.println("[Sending a request]");
    
    if (i)
    {
      client.print(String ("GET /") + "/cgi-bin/param.cgi?cmd=preset&-act=goto&-number=0 HTTP/1.1\r\n" +
                   "Host: " + host + "\r\n" +
                   "Connection: close\r\n" +
                   "Authorization: Basic XXXXX\r\n" +
                   "\r\n"
                  );
      Serial.println("[Response:]");
    }
    else
    {
      client.print(String ("GET /") + "/cgi-bin/param.cgi?cmd=preset&-act=goto&-number=1 HTTP/1.1\r\n" +
                   "Host: " + host + "\r\n" +
                   "Connection: close\r\n" +
                   "Authorization: Basic XXXXX\r\n" +
                   "\r\n"
                  );
      Serial.println("[Response:]"); 
    }
    while (client.connected())
    {
      if (client.available())
      {
        String line = client.readStringUntil('\n');
        Serial.println(line);
      }
    }
    client.stop();
    Serial.println("\n[Disconnected]");
  }
  else
  {
    Serial.println("connection failed!]");
    client.stop();
  }
  delay(5000);
#endif  
}

driveway

ActionScript
bash script to display camera rtsp stream on Raspberry Pi display
#!/bin/bash

if !(screen -list | grep -q "driveway")
then
screen -dmS driveway sh -c 'omxplayer --win "0 32 1280 992" rtsp://admin:xxxx@x.x.x.x:554/12 --live'
fi

Credits

Ralph Yamamoto

Ralph Yamamoto

10 projects • 20 followers

Comments