CCNP-PRO

Based on the IT journey of Michael Rickert

Raspberry Pi panic alarm system

Recently I’ve had to set up a way for a receptionist sitting at the front lobby to have access to a panic button that will email out an alert and also call out to a set of phone #s when pressed. With the popularity of the RaspPi and its inexpensive/easy to use linux system I decided that it would be the perfect tool for the job. Below is a brief overview of how I set up a raspberry pi to read from a button (at the lobby desk, using an iStar security panel), email out to a distribution group, and then call a phone number list in python and bash.

You can find the latest script files here: https://github.com/RaceFPV/Panic-Pi

Hardware:

For this project I obtained a raspberry pi:

rasppi

pi case:

rasppicase

and raspberry pi breakout board:

pibreakoutboard

Next, I soldered together the pins in the breakout board:

pisolderboard

and got to work connecting the GPIO pins on the rasp pi to the lobby button. For the button I used pin 4 and the grounding pin, I set the iStar security panel to always feed 1.6v out of an unused relay unless the panic button is pressed, in which case it will ground out and supply 0v out.

NOTE: You can use any old button here, as long as pin 4 sees a voltage change, the istar system is simply what I had to integrate with at the time

istarpi

iStar has some easy to use configuration settings when it comes to the relays so it was as simple as ‘if button pressed -> arm relay 8’ which would then remove the 1.6v, triggering pin 4 on the breakout board connected to the pi GPIO pins and thus causing the button press to be read by the rasp pi.

Software:

The hardware side of this project was pretty simple, find out how many volts are output by the relay on the panel… connect a few wires to the rasp pi breakout board… verify button triggers are read on pin 4… Next up is the software side, where things get a bit more difficult.

Software needed: Python, pjsip, mail

First step was creating a python script on the pi that would listen for the button press on pin 4 and do something about it. I also wanted this script to always run on boot and loop so that if the button was pressed again say, 10 minutes later, it would trigger a second time without having to re-launch the python script.

Here is the full script list used, and afterwards a breakdown of each piece of code:

panicbutton.py

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(4,GPIO.IN)
input = GPIO.input(4)
import time
import os
#initialise a previous input variable
prev_input = 1
while True:
  #take a reading
  input = GPIO.input(4)
  #if the last reading was low and this one high, print
  if ((not prev_input) and input):
    print("Button pressed")
    os.system("su root ./emailout.sh")
    os.system("su root ./callouttest.sh")
    time.sleep(35)
    os.system("su root ./callouttest.sh")
    print("Callout done")
  #update previous input
  prev_input = input
  #slight pause to debounce
  time.sleep(0.05)

emailout.sh

#!/bin/bash
STR="PANIC BUTTON TRIGGERED, CALLING OUT NOW"
echo $STR
echo -e "The Front Desk panic button has been pressed, it is highly recommended that you check the security cameras and call the front desk" | mail -s 'Front Desk Panic Button Activated!' @email
pwd
echo "Email done"

callouttest.sh

#!/bin/bash
pwd
cd /home/pi/
pwd
./killcall.sh & disown
pwd
echo "dial out 1"
pwd
./makesipcall.sh
echo "callout done"

killcall.sh

#!/bin/bash
pwd
rm -f get_it
sleep 25
get_proc=`ps -e -o pid,command | grep pjsua-armv6l-unknown-linux-gnu`
echo $get_proc > get_it
get_pid=`gawk -F" " '{ print pjsua-armv6l-unknown-linux-gnu }' get_it`
kill -kill $get_pid

makesipcall.sh

#!/bin/bash
pwd
cd /home/pi/pjproject-2.1.0/pjsip-apps/bin/
pwd
./pjsua-armv6l-unknown-linux-gnu --null-audio --stereo --play-file '/home/pi/panicon.wav' --auto-play --auto-loop --id sip:ecall@yourdomain.com  --registrar sip:55.55.55.55 --realm '*' --username ecall --password <removed>       sip:1234@55.55.55.55

If your familiar with python you should be able to determine what this script does right off the bat. I also edited /etc/rc.local to have it run the panicbutton.py script on boot. Now, lets break down the python code above:

First, import the software that allows the reading of the breakout board pins that are located on the rasp pi

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)

Next, give the script access to pin 4 on the breakout board

GPIO.setup(4,GPIO.IN)

Label pin 4 as input variable

input = GPIO.input(4)

Import some other python modules so that the code runs properly

import time
import os

Because by default the button/relay is “on” with 1.6v I set prev_input to 1, otherwise it would consider 1.6v a button press and loop constantly

#initialise a previous input variable
prev_input = 1

I created an infinite loop so that the python script is constantly checking for the pin 4 trigger and does not end after the first time it reads a button press

while True:
  #take a reading
  input = GPIO.input(4)
  #if the last reading was low and this one high, print
  if ((not prev_input) and input):

This code prints “button pressed” onto the screen (easier for diagnostics), calls the “emailout.sh” bash script, then when that script completes calls the “callouttest.sh” script, waits 35 seconds, and then re-calls the “callouttest.sh” script a second time. This was done because the callouttest.sh script had a nasty habit of not always phoning out the first time (explained later). Finally it then prints “Callout done” when the panic button script completes

    print("Button pressed")
    os.system("su root ./emailout.sh")
    os.system("su root ./callouttest.sh")
    time.sleep(35)
    os.system("su root ./callouttest.sh")
  #update previous input
  prev_input = input

The last bit of the script just pauses for a moment in case the panic button goes from 1.6v to 0v and back really fast for some reason, say line jitter…

  #slight pause to debounce
  time.sleep(0.05)

Now lets look at the scripts the button press calls.The first script, “emailout.sh”, uses the linux ‘mail’ command to email out to a distribution group alerting them of the button press.

#!/bin/bash
STR="PANIC BUTTON TRIGGERED, CALLING OUT NOW"
echo $STR
echo -e "The Front Desk panic button has been pressed, it is highly recommended that you check the security cameras and  call the front desk *****" | mail -s 'Front Desk Panic Button Activated!'  email@email.com
pwd

Pretty simple huh? This script simply uses the mail command to create an email with a subject of ‘Front Desk Panic Button Activated’ and then emails that out to the email address specified.

mail -s 'Front Desk Panic Button Activated!'  email@email.com

The second script: “callouttest.sh”, Calls the sip calling script as well as a kill script to kill the sip calling script if it hangs (which it loves to do):

#!/bin/bash
cd /home/pi/
pwd
./killcall.sh & disown
pwd
echo "dial out 1"
./makesipcall.sh
echo "callout done"

The script does the following: first, change to the /home/pi directory that contains the main scripts

cd /home/pi/

Set “killcall.sh” script to run in the background so that it doesn’t hang up anything else I want to run in the script by using the disown command

./killcall.sh & disown

Let us know that the dial out is starting and then run the sip call script

echo "dial out 1"
pwd
./makesipcall.sh

The makesipcall.sh script, which is run to make the sip call out, has only a few lines starting with one to change to the pjsip application folder:

 cd /home/pi/pjproject-2.1.0/pjsip-apps/bin/

pwd is needed next because the pjsip program really bugs out when run from any kind of script and needs to be a special line

pwd

command run via pjsip to call out to shoretel via SIP phone, it will loop and play the audio file specified over the voip call and use a specific user/phone# that is easy to spot as the panic button call number.

./pjsua-armv6l-unknown-linux-gnu --null-audio --stereo --play-file '/home/pi/panicon.wav' --auto-play --auto-loop --id sip:ecall@yourdomain.com  --registrar sip:55.55.55.55 --realm '*' --username ecall --password <removed>       sip:1234@55.55.55.55

You’ll notice that callouttest.sh calls another script, killcall.sh. Killcall.sh waits 30 seconds, and then runs a kill command on the pjsip command as the command itself has no time limit. Without the killcall script the phone call would continue to occur until all users receiving the call either hung up, or ran out of voicemail space, which is not good! You can see the killcall.sh script here:

#!/bin/bash
rm -f get_it
sleep 30
get_proc=`ps -e -o pid,command | grep pjsua-armv6l-unknown-linux-gnu`
echo $get_proc > get_it
get_pid=`gawk -F" " '{ print pjsua-armv6l-unknown-linux-gnu }' get_it`
kill -kill $get_pid
echo "callout done"

A quick breakdown of the killcall.sh script:

remove get_it to clean up any previous trigger files if killcall.sh was run previously

#!/bin/bash
rm -f get_it

wait for 30 seconds while the pjsip program has a chance to call out to people

sleep 30

Find the pjsua-armv6l-unknown-linux-gnu commmand if it is running

get_proc=`ps -e -o pid,command | grep pjsua-armv6l-unknown-linux-gnu`
echo $get_proc > get_it
get_pid=`gawk -F" " '{ print pjsua-armv6l-unknown-linux-gnu }' get_it`

Stop the pjsua-armv6l-unknown-linux-gnu command so that the calls are no longer going out

kill -kill $get_pid

print “callout done” to the screen so I know the script completed

echo "callout done"

Wrap up:

Be sure to add the following line to your /etc/rc.local file so that the script runs on boot:

(sleep 10;python /home/pi/panicbutton.py)&

And that’s it! A few small linux programs, basic soldering, and and understanding of python and bash scripting can get you a sub $100 panic alarm button that emails, voip calls, and anything else you could ever need simply by scripting it in.

3 comments for “Raspberry Pi panic alarm system

  1. McD
    April 5, 2016 at 15:35

    Hi!

    Would it be possible to mod your solution to power a LED (like this for example https://www.adafruit.com/products/481) via gpio or something, while the pjsip call is active?

    Also, what happens if the dialed extension is busy? I was thinking about using a queue (asterisk) to receive the call, and hold it until an agent can receive it. To do this, I would have to remove the killcall script part, because the call might be in the queue for longer than 30 sec. The second call for the callout script would have to removed too, I think. Would this work?

    • Michael Rickert
      April 6, 2016 at 08:40

      I don’t see why you couldn’t add an LED on/off to the panicbutton.py script. It should only be an extra two to three lines in the calling loop.

      The dial out script runs twice, it calls once, then waits for 35 seconds, then calls a second time. Unfortunately i don’t think pjsip is smart enough to try to call back if the number is busy. The best answer I can think of if that’s the case is have it call again if the previous call was shorter than the specified length.

  2. Harold
    October 27, 2016 at 11:40

    Michael, This project is very interesting to me. I have been looking at “panic button” options for our small school. Do you think this would work with the RaspPi Zero?

Leave a Reply

Your email address will not be published.

Time limit is exhausted. Please reload CAPTCHA.

%d bloggers like this: