Smart Doorbell using Raspberry Pi

About a year ago, I had to do a project titled Smart Home Automation using a Raspberry Pi and Arduino, part of the project  incorporated a doorbell but not just any doorbell but a Smart doorbell.

Why do I call it a Smart Doorbell?

A classic doorbell can be defined as a signalling device typically placed near an entry door to a building. When a visitor presses a button the bell rings inside the building, alerting the occupant to the presence of the visitor.

The smart doorbell, works in that manner however when a visitor presses the doorbell button it notifies the occupant with an images of the visitor and also sends an email, sms and push notification (to an smart device) to the occupant in case they are not able to hear the bell ringing.

If the button is pressed a pre-recorded voice notification is played for the occupant to check the door as there might be someone, this happens concurrently with an sms notification while a picture of the visitor is captured and sent to both email and push notification. Initially there was a feature to enable 2-way real-time video communication but due to network latency and high resource usage the feature was deprecated.

Click For A Demo

Comment if you need the code

See code snippets(Initial Revision): https://mmphego.wordpress.com/2015/01/11/smart-doorbell-using-rpi-with-voice-and-email-notification/

Advertisements

Node-Red Dashboard running on Nginx port 80

After finishing my Node-Red dashboard app, and boy, it’s awesome. Everything works great, but I wanted to bind it to port 80 on my nginx server.

Nginx

A more popular approach is to set up Nginx as a reverse proxy by having it bind to the desired port, forwarding all incoming traffic to my node red dashboard.

Nginx is a high performance, open source web server (similar to Apache) that is widely-used.

The main benefit of Nginx is the fact that it takes care of transport optimization.

Installing Nginx

sudo apt-get install nginx
 

Configuring Nginx

Next, we’ll need to configure Nginx so that it forwards traffic to my dashboard. Let’s start off by removing the default configuration file:

sudo rm /etc/nginx/sites-enabled/default
 

Next, create a new file in /etc/nginx/sites-available/ called node and open it with nano:

sudo nano /etc/nginx/sites-available/node
 

Paste the following code in the file and make sure to change example.com to your domain (or IP), and 1880 to your Node-Red Dashboard port:

server {
    listen 80;
    server_name example.com;

    location /ui {
        proxy_set_header   X-Forwarded-For $remote_addr;
        proxy_set_header   Host $http_host;
        proxy_pass         "http://127.0.0.1:1880";
    }
}

The proxy_pass declaration configures Nginx to act as a reverse proxy by forwarding all incoming requests on port 80 to Node-Red dashboard on port 1880, on behalf of the client.

Next, we need to symlink our configuration to sites-enabled for it to be used by Nginx, since it’s currently in sites-available:

sudo ln -s /etc/nginx/sites-available/node /etc/nginx/sites-enabled/node

Applying the Configuration

Let’s restart Nginx so that it loads our configuration:

sudo service nginx restart

run

sudo service nginx status

and you should see something like:

* nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled)
   Active: active (running) since Sat 2017-02-11 14:14:14 UTC; 306ms ago
  Process: 3103 ExecStop=/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid (code=exited, status=0/SUCCESS)
  Process: 3111 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
  Process: 3108 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
 Main PID: 3113 (nginx)
   CGroup: /system.slice/nginx.service
           |-3113 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
           |-3114 nginx: worker process
           |-3115 nginx: worker process
           |-3116 nginx: worker process
           `-3119 nginx: worker process

Feb 11 14:14:14 alexapi nginx[3108]: nginx: [warn] server name "127.0.0.1:1880/ui" has suspicious symbols in /etc/nginx/sites-enabled/node:3
Feb 11 14:14:14 alexapi nginx[3111]: nginx: [warn] server name "127.0.0.1:1880/ui" has suspicious symbols in /etc/nginx/sites-enabled/node:3
Feb 11 14:14:14 alexapi systemd[1]: Started A high performance web server and a reverse proxy server.

All set! Nginx will now forward all incoming requests to your app and even survive a server crash, since it automatically starts up with your machine.

Screenshot_2017-02-11_16-18-49.png

also see: https://www.digitalocean.com/community/tutorials/how-to-connect-your-internet-of-things-with-node-red-on-ubuntu-16-04

 

If you found this helpful, donate some coins

BTC: 1GLwaJiYo7NT71DFHj7KzcDjcczJUWVCbz

ETH: 0x5218b473b25Bff87f6820f3A84400cbdf3Ab85AB

Raspberry Pi – Stuck in boot after installing upstart

I  installed upstart so I could run a script at startup [native /etc/init/*.conf]  with sudo apt-get install upstart and I then rebooted my RPi.

Afterwards my RPi running Debian-Jessie was pretty much unresponsive via the network. Right after connecting it to my monitor I then realised that it was stuck on boot.

CODE:

[   17.777252] init: samba-ad-dc main process (513) terminated with status 1
[  133.770712] init: failsafe main process (364_ killed by TERM signal
[info] Using makefile-style concurrent boot in runlevel S
...
[info] Loading kernel module fuse.

Only at that moment, I started realising that I should have probably backed up my SD Card before, but then it was already too late. It then struck me – So I will have to redo it all over again with a new and fresh raspbian installation. That was not something I was looking forward to do ,especially not after I have invested my time to this project I have undertaken myself on[apts, pips and nodes].

And then it hit me, A while ago – I had more or less the same issue on my Xubuntu 12.04 install and managed to get away with it via chroot which then worked, then started researching as to if it is possible to chroot my ARM Raspbian install from an Wbuntu system. To my revelation it was…And below is how I managed to rollback to Systemd-sysv without having to burn a new raspbian image to my sd card.

First, install two packages on your Ubuntu system: qemu-user, and proot.

sudo apt-get install -y qemu-user proot

After you mount the Raspbian SD card, you can do the equivalent of a ‘chroot‘ with:

 sudo proot -q qemu-arm  -r /mnt/raspbian_sd_card

I was then able to chroot/proot to my raspbian install and removed upstart:

sudo apt-get -y purge --auto-remove upstart

This command will also automatically re-install systemd-sysv

System V init script(start-stop-daemon)

I’ve been looking for efficient ways to start at boot my NodeJS dependent applications, with inspiration from https://gist.github.com/alobato/1968852, I modified it to my own needs.

Link might interest you as well:
http://big-elephants.com/2013-01/writing-your-own-init-scripts/
https://www.cyberciti.biz/tips/linux-write-sys-v-init-script-to-start-stop-service.html

Copy template to /etc/init.d and rename it to something meaningful. Then edit the script and enter that name after Provides:(between ### BEGIN INIT INFO and ### END INIT INFO).

#!/bin/bash
# Inspired by https://gist.github.com/alobato/1968852
# Needs Provides, Descriptions

### BEGIN INIT INFO
# Provides:
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description:
# Description:
### END INIT INFO

set -e
NAME=""
PIDFILE="/run/$NAME/$NAME.pid"
# Application one wants to upstart
DAEMON=""
DAEMON_OPTS=""
# Run as user
RUN_USER=""
RUN_GROUP=""
function daemon_run {
	mkdir -p /run/$NAME
	chown $RUN_USER:$RUN_GROUP /run/$NAME
	start-stop-daemon --start --background --quiet --chuid $RUN_USER:$RUN_GROUP --chdir /run/$NAME --pidfile $PIDFILE --make-pidfile --exec $DAEMON $DAEMON_OPTS
}
exec > /var/log/$NAME.log 2>&1

case "$1" in
start)
	echo -n "Starting $NAME ... "
	daemon_run
	echo "done."
;;

silent)
	echo -n "Starting $NAME in silent mode ... "
	daemon_run
	echo "done."
;;

stop)
	echo -n "Stopping $NAME ... "
	start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE --remove-pidfile
	echo "done."
;;
restart|force-reload)
	echo -n "Restarting $NAME ... "
	start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile $PIDFILE --remove-pidfile
	alexa_run
	echo "done."
;;
*)
	echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit 0

When done,

sudo systemctl enable 'name_of_filename'
reboot

Mpho

Installing latest Node.js on Raspberry Pi B+

So, I’ve been battling with updating my node.js via apt-get, for some apparent reason seems like they’ve discontinued updates or maybe I’ve been doing it wrong all along – who knows.

But I found a way to bypass apt-get and go back to the basics.
Note: This assumes that the latest release is node-v7.4.0, else you can go to https://nodejs.org/dist/latest and get the required build.

This assumes the Raspberry Pi is running Rasbian – Jessie

# Download Node.js source Raspberry Pi Model A, B, B+ and Compute Module

wget -qO- https://nodejs.org/dist/latest/node-v7.4.0-linux-armv6l.tar.gz | tar xvz
cd node-v7.4.0*

# Raspberry Pi 2 Model B

wget https://nodejs.org/dist/latest/node-v7.4.0-linux-armv7l.tar.gz | tar xzv
cd node-v7.4.0-linux-armv7l

# and lastly
sudo cp -Rv * /usr/local/

# That's it! To check Node.js is properly installed and you have the right version, run the command:

node -v

Mpho

Android WebView App (to Apache server)

Yippyyyy!!!

Just successfully created my first Android App.

So I have been playing around recently with modifications, improvements and configurations on my current project – “Smart Home using Raspberry Pi & Android with Voice Recognition.”

I have been thinking of implementing a simple Android application which directly opens up URL, rather than going to my browser each and every time I need to access the web control server(Apache2).

So one might be wondering what is exactly this WebView ‘nonsense’ a simple Google search gave me this definition, A “webview” is a browser bundled inside of a mobile application producing what is called a hybrid app. Using a webview allows mobile apps to be built using Web technologies (HTML, JavaScript, CSS, etc.) but still package it as a native app and put it in the app store.

Now coming back to the App, i’m using the latest Android Studio, source code below.

mpho

Main_Activity.java

//__author__ = "Mpho Mphego"
//__description__ = "Android WebView App controlling Raspberry Pi running Apache2"
//__version__ = "Revision: 1.0 "
//__date__ = "Date: 2015/01/17 22:23 "
//__url__ = "mmphego.wordpress.com"
//__copyright__ = "Copyright (c) 2015 Mpho Mphego"
//__license__ = "Java"

package com.wordpress.mpho112.mobilehomectrl;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebSettings;
import android.webkit.WebView;


public class MainActivity extends ActionBarActivity {
    private WebView mWebView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mWebView = (WebView) findViewById(R.id.activity_main_webview);
        // Enable Javascript
        WebSettings webSettings = mWebView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        mWebView.loadUrl("http://172.18.20.41/");
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

Activity_main.xml


<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    tools:ignore="MergeRootFrame">

    <WebView
        android:id="@+id/activity_main_webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>   

Smart Doorbell using RPi with voice and email notification.

Part of my project involves having a doorbell, I figured a simple doorbell whereby a visitor just presses a button and then it rings/ notify whoever is it the house, That’s not really creative in my point of view.

So I then decided why not have a doorbell that not only rings when the button is pressed but also tell you someone is at the door and then sends you an email notification just in case you might be away(Not able to hear the bell.) as well as log the time that the button was pressed.

IDEA: It would be really cool if I had a USB Webcam that would take a picture of the person visiting and emails it.

first things first, we’ll need to create the wav file ie TextToSpeech. Using this simple tool below.

pico2wave -w DoorNotify.wav "Someone is ringing the doorbell. Please Go Check"

Next, create a python script that will watch the state of GPIO pin 18 on the RPi and take some action when the doorbell brings it to ‘HIGH’.

#!/usr/bin/env python2.7
__author__ = "Mpho Mphego"
__version__ = "$Revision: 1.1 $"
__description__ = "Smart Doorbell Notifier with voice and email notification : Interrupt driven"
__date__ = "$Date: 2015/01/11 02:23 $"
__copyright__ = "Copyright (c) 2015 Mpho Mphego"
__url__ = "mmphego.wordpress.com"
__license__ = "Python"

import RPi.GPIO as GPIO
import time
import os

# Connect to Relay which will control the 12V Buzzer.
led = 17 #GPIO0
button = 18 #GPIO1

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(led, GPIO.OUT)
time.sleep(0.1)
GPIO.output(led, False)

# GPIO 1 set up as inputs, pulled up to avoid false detection.
# Both ports are wired to connect to GND on button press.
# So we'll be setting up falling edge detection for both
GPIO.setup(button, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# define callback functions
# this will run when an event are detected
def buttonHandler(channel):
    print "falling edge detected on 18"
    GPIO.output(led, True)
    time.sleep(1)
    GPIO.output(led, False)
    os.system("aplay /home/pi/Scripts/Smart_DoorBell/DoorNotify.wav")			
    os.system("python /home/pi/Scripts/Smart_DoorBell/DoorBellLogger.py")
    time.sleep(1)
    GPIO.output(led, True)
    time.sleep(1)
    GPIO.output(led, False)

# when a falling edge is detected on port 1, regardless of whatever 
# else is happening in the program, the function buttonHandler will be run
GPIO.add_event_detect(button, GPIO.FALLING, callback=buttonHandler, bouncetime=5000)

try:
    print "Waiting for button to be pressed"
    while True:
        # To ease the CPU Usage have a 10s delay on while loop.
        time.sleep(10)
        continue
except:
    GPIO.cleanup()       # clean up GPIO on CTRL+C exit
GPIO.cleanup()           # clean up GPIO on normal exit
print "Clean up by resetting all GPIO"

Now for the fun part, the email notification and data log.


#!/usr/bin/env python
__author__ = "Mpho Mphego"
__description__ = "Doorbell notifier time logger and email notifier."
__version__ = "$Revision: 1.0 $"
__date__ = "$Date: 2015/01/10 02:09 $"
__copyright__ = "Copyright (c) 2015 Mpho Mphego"
__license__ = "Python"

import time
import datetime
import os
import smtplib
from email.mime.text import MIMEText

#-----------------------Data Logger-----------------
f=open('/home/pi/Logs/DoorBell_Data_Log.txt','a')
now = datetime.datetime.now()
timestamp = now.strftime("%H:%M on %Y/%m/%d")
outstring1 = " Someone was at the door at " + str(timestamp) 
outstring2 = "\n********************************************* \n "
outstring = outstring1 + outstring2
f.write(outstring)
f.close()

# -----------------------Email Notifier----------------------
# Replace with your details.
USERNAME = "*******@gmail.com"
PASSWORD = "*********"
MAILTO  = "******@gmail.com"

if os.system("ping -c 1 www.google.com >> /dev/null 2&>1") == 0 :
	print "Sending Email Notification"
	msg = MIMEText('Someone is ringing the doorbell! \nGo Check!')
	msg['Subject'] = 'Doorbell notification!'
	msg['From'] = USERNAME
	msg['To'] = MAILTO

	server = smtplib.SMTP('smtp.gmail.com:587')
	server.ehlo_or_helo_if_needed()
	server.starttls()
	server.ehlo_or_helo_if_needed()
	server.login(USERNAME,PASSWORD)
	server.sendmail(USERNAME, MAILTO, msg.as_string())
	server.quit()
else:
	print "Unable to connect to Internet."

To have this run upon booting, we need to edit /etc/rc.local (as root since this is the owner).

sudo nano /etc/rc.local

At the bottom, just above exit 0 we’ll add a call to our script.

python /home/pi/Scripts/Smart_DoorBell/WaitDoorbell.py