Smart Lock and Doorbell using cayenne


#1

About This Project

A smart lock is arguably the most important part of a truly smart, connected home. Not only will it allow you to come and go as you please, it will also monitor who is entering and leaving your home while you’re away. Some models simply let you use your phone to open and close doors. Some let you assign special privileges to friends, family members, or maintenance staff.

smart locks offer a mobile app that allows you to lock and unlock doors with a simple icon tap. It offers a web app that lets you control things from your desktop or laptop PC. You can add a schedule for specific days and times for the door open/close.

If the lock is Bluetooth-enabled, you’ll have to be within range (around 40 feet) to communicate with it, while with this locks built-in Wi-Fi circuitry, you can control it from almost anywhere as long as they are connected to your home router. You can go back in time to see who has entered or exited your home and when the activity took place.

Another feature is a keyless keypad for those times when you don’t have your phone or your keys. Each user of the house or company can use it unique code for entry and exit. It sends text, and email notifications that let you know who is coming and going in real-time.

A smart lock can be handy when paired with a compatible smart doorbell. If a friend, family member or service worker rings your smart doorbell while you’re away, you can visually confirm who it is via the smart doorbell, then remotely unlock the door to let them in.

What’s Connected

Arduino mega

Esp8266

Raspberry Pi

Raspberry Pi Camera

16x2 LCD

4x4 Keypad

Pushbutton

Led

Triggers & Alerts

There is one main trigger used between Raspberry pi and Arduino mega.

If doorbell (A) is pressed on the 4x4 keypad it makes the Bell two state widget 1 which trigger the image button on raspberry pi to turn ON. This runs the script on raspberry pi to click a pic of the visitor and send it through an email.

When the image button turn ON it sends an alert, notifying that a visitor has arrived and to check the email for visitors pic.

Each user two state widget has an entry alert which sends an SMS, notifying that a user has entered the house.

Dashboard Screenshots

https://cayenne.mydevices.com/shared/5b7c52386d133a24ef9226a1

Video

Connection

Arduino Mega |||||||| ESP8266 |||| LCD ||||||||| Keypad |||||| Button |||||| Led
3.3v ----------------------VCC
GND----------------------GND-----------GND-------------------------------pin2---------- -
19--------------------------Tx
18--------------------------Rx
5v ------------------------------------------VCC
30 ------------------------------------------rs
32 ------------------------------------------en
22 ------------------------------------------d4
24 ------------------------------------------d5
26 ------------------------------------------d6
28 ------------------------------------------d7
2 ---------------------------------------------------------Rowpin1
3 ---------------------------------------------------------Rowpin2
4 ---------------------------------------------------------Rowpin3
5 ---------------------------------------------------------Rowpin4
6 ---------------------------------------------------------Columnpin1
7 ---------------------------------------------------------Columnpin2
9 ---------------------------------------------------------Columnpin3
10---------------------------------------------------------Columnpin4
11-------------------------------------------------------------------------------------pin1
13 -------------------------------------------------------------------------------------------------- + with 470ohm resistor

Raspberry pi ------- pi camera.
https://projects.raspberrypi.org/en/projects/getting-started-with-picamera

Procedure

Add a new arduio device to your cayenne dashboard. Edit the arduino code and add your wifi credentials (ssid, password) and MQTT credential. Upload the code into you arduino mega.
Add 5 two states widget to your cayenne dashboard with channel 1 - 5.
A button widget with channel 6 is used to control door lock and unlock.
Install cayenne MQTT python library [https://github.com/myDevicesIoT/Cayenne-MQTT-Python] and follow the procedure to add a new device on cayenne using raspberry pi.
Add the raspberry pi code and run it.
Create a button widget on cayenne dashboard for capturing image on raspberry pi.

Code

Arduino mega

#define CAYENNE_DEBUG
#define CAYENNE_PRINT Serial
#include <CayenneMQTTESP8266Shield.h>
#include <LiquidCrystal.h>
#include <Servo.h>

Servo myservo;

const int rs = 30, en = 32, d4 = 22, d5 = 24, d6 = 26, d7 = 28;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
// WiFi network info.
char ssid[] = "";
char wifiPassword[] = "";

int a;
int time_close;
int door_open;

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

ESP8266 wifi(&EspSerial);

#include <Keypad.h>
#define Password_Lenght 5
char Data[Password_Lenght];
char Master_In[Password_Lenght] = "*123";
char Master_Out[Password_Lenght] = "#123";
char Master1_In[Password_Lenght] = "*346";
char Master1_Out[Password_Lenght] = "#346";
char Master2_In[Password_Lenght] = "*165";
char Master2_Out[Password_Lenght] = "#165";
char Master3_In[Password_Lenght] = "*132";
char Master3_Out[Password_Lenght] = "#132";
char door[] = "A";
char key[1];
byte data_count = 0, master_count = 0;
bool Pass_is_good;
char customKey;
int xx;
int b;
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {2, 3, 4, 5};
byte colPins[COLS] = {6, 7, 9, 10};
//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
void setup()
{
  Serial.begin(9600);// initialize the Serial
  EspSerial.begin(115200);
  pinMode(11, INPUT_PULLUP);
  pinMode(13, OUTPUT);
  delay(10);
  lcd.begin(16, 2);
  Cayenne.begin(username, password, clientID, wifi, ssid, wifiPassword);
  //myservo.attach(12);
  Cayenne.virtualWrite(99, 1, "digital_sensor", "d");
}
void loop()
{
  Cayenne.loop(10);
  lcd.setCursor(0, 0);
  lcd.print(" SMART DOORBELL!");
  if (b == 0)
  {
    lcd.setCursor(0, 1);
    lcd.print(" USING CAYENNE");
  }
  if (!digitalRead(11) && (door_open == 0))
  {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.println("Door Open");
    myservo.write(90);
    digitalWrite(13, HIGH);
    door_open = 1;
    b = 0;
  }
  //lcd.setCursor(0, 1);
  //lcd.print(" WELCOME HOME!");
  //Serial.print("Enter Password");
  customKey = customKeypad.getKey();
  key[0] = customKey;
  if (customKey) // makes sure a key is actually pressed, equal to (customKey != NO_KEY)
  {
    Data[data_count] = customKey; // store char into data array

    data_count++; // increment data array by 1 to store new char, also keep track of the number of chars entered
    a++;
    if (a == 1)
    {
      lcd.clear();
      lcd.setCursor(0, 1);
      lcd.print("*");
      b = 1;

    }
    if (a == 2)
    {
      lcd.setCursor(0, 1);
      lcd.print("**");
    }
    if (a == 3)
    {
      lcd.setCursor(0, 1);
      lcd.print("***");
    }
    if (a == 4)
    {
      lcd.setCursor(0, 1);
      lcd.print("****");
      b = 0;
    }
    if (!strcmp(Data, "A"))
    {
      lcd.clear();
      Cayenne.virtualWrite(5, 1, "digital_sensor", "d");
      scrollInFromRight(0, "Ringing");
      delay(1000);
      Cayenne.virtualWrite(5, 0, "digital_sensor", "d");
      clearData();
      b = 0;
    }
  }

  if (data_count == Password_Lenght - 1) // if the array index is equal to the number of expected chars, compare data to master
  {
    lcd.clear();
    Serial.print("Password is ");


    if (!strcmp(Data, Master_In)) {
      Serial.print("In 1");
      time_close = 0;
      //myservo.write(90);
      digitalWrite(13, HIGH);
      lcd.print( "Welcome ROY");
      lcd.setCursor(0, 1);
      lcd.print("Door Open");
      while ((time_close < 1000) && (digitalRead(11)))
      {
        time_close ++;
        Serial.println(time_close);

      }
      lcd.clear();
      digitalWrite(13, LOW);
      myservo.write(0);
      Cayenne.virtualWrite(1, 1, "digital_sensor", "d");

    }
    else if (!strcmp(Data, Master_Out)) {
      lcd.print( "Goodbye ROY");
      Cayenne.virtualWrite(1, 0, "digital_sensor", "d");
      door_open = 0;
      //myservo.write(90);
      digitalWrite(13, LOW);
    }

    //User 1
    else if (!strcmp(Data, Master1_In)) {
      Serial.print("In 2");
      time_close = 0;
      //myservo.write(90);
      digitalWrite(13, HIGH);
      lcd.print( "Welcome TOM");
      lcd.setCursor(0, 1);
      lcd.print("Door Open");
      while ((time_close < 500) && (digitalRead(11)))
      {
        time_close ++;
        Serial.println(time_close);
      }
      // myservo.write(0);
      digitalWrite(13, LOW);
      Cayenne.virtualWrite(2, 1, "digital_sensor", "d");
    }
    else if (!strcmp(Data, Master1_Out)) {
      lcd.print("Goodbye TOM");
      Cayenne.virtualWrite(2, 0, "digital_sensor", "d");
      door_open = 0;
      //myservo.write(0);
      digitalWrite(13, LOW);
    }

    //User 2
    else if (!strcmp(Data, Master2_In)) {
      time_close = 0;
      //myservo.write(90);
      digitalWrite(13, HIGH);
      lcd.print( "Welcome Jerry");
      lcd.setCursor(0, 1);
      lcd.print("Door Open");
      while ((time_close < 500) && (digitalRead(11)))
      {
        time_close ++;
        Serial.println(time_close);
      }
      //myservo.write(0);
      digitalWrite(13, LOW);
      Cayenne.virtualWrite(3, 1, "digital_sensor", "d");

    }
    else if (!strcmp(Data, Master2_Out)) {
      lcd.print("Goodbye Jerry");
      Cayenne.virtualWrite(3, 0, "digital_sensor", "d");
      door_open = 0;
      //myservo.write(0);
      digitalWrite(13, LOW);

    }

    //User 3
    else if (!strcmp(Data, Master3_In)) {
      time_close = 0;
      //myservo.write(90);
      digitalWrite(13, HIGH);
      lcd.print( "Welcome MIKE");
      lcd.setCursor(0, 1);
      lcd.print("Door Open");
      while ((time_close < 500) && (digitalRead(11)))
      {
        time_close ++;
        Serial.println(time_close);

      }
      //myservo.write(0);
      digitalWrite(13, LOW);
      Cayenne.virtualWrite(4, 1, "digital_sensor", "d");

    }
    else if (!strcmp(Data, Master3_Out)) {
      lcd.print("Goodbye MIKE");
      Cayenne.virtualWrite(4, 0, "digital_sensor", "d");
      door_open = 0;
      //myservo.write(0);
      digitalWrite(13, LOW);
    }

    else {
      delay(1000);
      lcd.print("Access Denied");
    }
    delay(1000);// added 1 second delay to make sure the password is completely shown on screen before it gets cleared.
    clearData();
    delay(1000);
    lcd.clear();

  }

}
void clearData()
{
  a = 0;
  while (data_count != 0)
  { // This can be used for any array size,
    Data[data_count--] = 0; //clear array for new data
  }
  return;
}

int i = 0;

int j = 0;

int k = 0;

int delayTime2 = 150; // Delay between shifts



void scrollInFromRight (int line, char str1[]) {

  // Written by R. Jordan Kreindler June 2016

  i = strlen(str1);

  for (j = 16; j >= 0; j--) {

    lcd.setCursor(0, line);

    for (k = 0; k <= 15; k++) {

      lcd.print(" "); // Clear line

    }

    lcd.setCursor(j, line);

    lcd.print(str1);

    delay(delayTime2);

  }
}
CAYENNE_IN(6)
{
  int value = getValue.asInt();
  digitalWrite(13, value);
}

Raspberry pi
To install cayenne MQTT python https://github.com/myDevicesIoT/Cayenne-MQTT-Python

import smtplib

from email.mime.text import MIMEText

from email.mime.multipart import MIMEMultipart

from email.mime.base import MIMEBase

from email import encoders

from picamera import PiCamera

from time import sleep

#!/usr/bin/env python

import cayenne.client

import time

x = 0

# Cayenne authentication info. This should be obtained from the Cayenne Dashboard.**

MQTT_USERNAME = " "

MQTT_PASSWORD = " "

MQTT_CLIENT_ID = " "

**#email id credential**

email_user = ""

email_password = ""

email_send = ""

subject = 'Smart IoT DoorBell &amp; Lock'

camera = PiCamera()

# The callback for when a message is received from Cayenne.

def on_message (message):

global x

print ( "message received: " + str(message))

# If there is an error processing the message return an error string, otherwise return nothing.

if (message.channel == 4) and (message.value == "1" ):

pic_capture()

x = 1

sleep(2)

# If there is an error processing the message return an error string, other$**

if (message.channel == 5) and (message.value == "1" ):

quit()

def pic_capture ():

sleep(1)

camera.capture( '/home/pi/Cayenne-MQTT-Python/examples/image.jpg')

sleep(1)

msg = MIMEMultipart()

msg[ 'From' ] =email_user

msg[ 'To' ] = email_send

msg[ 'Subject' ] = subject

body = 'You have a new visitor'

msg.attach(MIMEText(body, 'plain' ))

filename = 'image.jpg'

attachment = open(filename, 'rb' )

        part = MIMEBase('application', 'octet-stream')
        part.set_payload((attachment).read())
        encoders.encode_base64(part)
        part.add_header('Content-Disposition',"attachment; filename= "+filename)

        msg.attach(part)
        text = msg.as_string()
        server = smtplib.SMTP('smtp.gmail.com',587)
        server.starttls()
        server.login(email_user,email_password)

        server.sendmail(email_user, email_send, text)
        server.quit()

    
client = cayenne.client.CayenneMQTTClient()
client.on_message = on_message
client.begin(MQTT_USERNAME, MQTT_PASSWORD, MQTT_CLIENT_ID)
# For a secure connection use port 8883 when calling client.begin:
# client.begin(MQTT_USERNAME, MQTT_PASSWORD, MQTT_CLIENT_ID, port=8883)

i=0
timestamp = 0

while True:
    client.loop()
    if (time.time() > timestamp + 10):
        client.virtualWrite(1,i)
        if x == 1:
                client.virtualWrite(4,0)
                x = 0
        timestamp = time.time()
        i = i+1

Photo and Video stream from cayenne dashboard
Stream Pi camera / video on Cayenne
Cayenne with camera