Pilarm - Raspberry Pi Alarm Using Existing Contacts

alarm
dth_security
project_security
raspberrypi

(Ryan) #1

Integrate existing door and window contact sensors with SmartThings using a Raspberry Pi or C.H.I.P.

Built and implemented this in my house about six months ago and has been working pretty good so thought I would share. Other solutions at the time had polling delays and such so ventured to write my own. I’m sure it could use some improvements so would love to see what you might add.


(Amauri Viguera) #2

Do you have any pictures of your setup?

The docs seem fairly straightforward but I haven’t gotten involved with much on the hardware side of the Raspberry pi.

I have a Napco setup currently monitored but I’m wondering if I can extend that into Smartthings by using something like this, since nobody seems to be working on incorporating the Napco zwave stuff.

I have 20+ zones including PIRs and sensors on every portal, so this might be an interesting project to undertake. I’m just worried about not breaking anything dealing with breadboards and resistors. :grinning:


(Ryan) #3

Hi @viguera

Added a few pictures of the breadboard and alarm box, its not very pretty. Wish I would have taken more as I was putting it together… maybe one day I’ll take some wires out and get some better pictures. I ended up with 17 zones hooked up. I put each rooms windows in series and all doors separately.

Images can be found at: https://github.com/rcoodey/Pilarm/tree/master/images and also linked in the readme. Hope that helps a little and thanks for checking out the project.


(Amauri Viguera) #4

Thanks… It’s not the cleanest job, but it does show quite a bit of detail… :slight_smile:

I was researching GPIO breakout kits yesterday and found quite a bit of info. It looks like this should be a (relatively) easy project to connect pretty much any alarm system into SmartThings.

In my case though, it looks like it might be a real pain. I have a bunch of zones on one panel and a bunch in another separate 8 zone expansion module.

I think I might be able to just find the zones that I’m interested in and run a wire from the contact at the panel to the breadboard or something, so that it (hopefully) doesn’t interfere with the system.

The main board:

And the module:


(Amauri Viguera) #5

BTW, I picked this up again and it seems to be working as expected, after a few rounds of fighting with my stupid mistakes… :slight_smile:

A few things worth pointing out…

The code specifically looks for the device name to be “PilarmZone[…]” so you can change the label to have it display something else, but in the IDE it has to be specifically named as PilarmZone followed by the GPIO pin you’re monitoring:

def zonedevice = contactSensors.find { it.deviceNetworkId == "PilarmZone${zone}" }

Speaking of the code, the python script itself also has a hardcoded reference to graph.api.smartthings.com. If you’re on some different shard and your URL is different, this needs to be edited as well.

smartthings_event_url = "https://graph.api.smartthings.com/api/smartapps/installations/" + smartthings_application_id + "/{0}/{1}?access_token=" + smartthings_access_token

Also, if you’re having problems eyeballing the application ID from the JSON return, you can use the old trick of browsing through your “home” in the IDE. Go to My Locations --> Home --> Installed SmartApps. When you hover over the Pilarm URL (or open the description) you can see the application ID right there.

As far as my setup goes, I just got everything up and running and I’m still fiddling with the mounting options, but so far the two zones that I configured are working as expected.

I purchased this USB WiFi antenna and this breakout kit from Amazon. The kit might be overkill, so your mileage may vary. The WiFi setup was relatively simple as well, and not having to worry about running a network cable to the alarm panel is a plus.


(Michael Rogers) #6

Thanks for sharing this! I’ve been looking for a way to tie in the contact sensors from my security system, and this looks perfect! I’ve managed to get a proof-of-concept showing on my SmartThings by triggering the pin manually, now I have the daunting task of wiring it all in.

I noticed you also had a ‘Pirage’ repository on your GitHub. I’m very interested in that, too. Is it functional yet?


(Ryan) #7

Hi Michael,

Glad this code was helpful for you. Good luck with the wiring!

As far as “Pirage”, it is functional, I have been using it reliably since that code was published. I have it running on a C.H.I.P. but should work fine on a Raspberry Pi too. Just need to switch out the GPIO library at the top for a Pi. All it does is tell a relay to open and close to toggle the door opener. Hope it helps.


(Michael Rogers) #8

Oh I see, thanks!

I like the idea of a Pi over the CHIP since I prefer wired ethernet over wifi for things that don’t move. Doubly so since the wifi coverage in my garage is not ideal.

Would you expect the Pilarm and Pirage to conflict if ran on the same Pi? (Assuming they are not configured to the same GPIO.) Doing this would allow me to know if the Pirage were down for some reason since the button looks to work as a blind http get, am I right?


(Michael Rogers) #9

Sorry for the double post, but I’ve made some serious progress since last time.

I’ve adapted Pilarm to read inputs not from GPIO but from an MCP3008 ADC chip. Why would I do this? Because now I can monitor the status of my contacts without disconnecting them from the alarm system!

My alarm system still works (door chime and all), but now SmartThings knows what’s going on, too! Here’s the setup so far:

I made a custom hat for the Pi with Adafruit’s Perma-Proto HAT (No EEPROM). I added the MCP3008 and some screw terminals. I connected the alarm system’s ports to the MCP3008 through a voltage divider to bring the voltage down to below 3.3v. I had to use really high ohms (47k + 18k) to not trip the system to thinking a door was open, but they read very stably. By using an ADC, I can set the thresholds for high or low exactly where I want in software. This is important since the alarm system’s resistors and end-of-line resistors never let the line go fully high or low.

I’m powering the Pi from auxiliary power available from the security system’s board. It was ~14v I think, with a 500mA limit. I used a DC/DC converter to get it down to 5v. The Pi pulled way less than 500mA on the 14v side. I did all that to avoid running a new power adapter from an outlet somewhere.

Lastly the Pi is mounted with a custom 3D printed base to line up with pre-existing mounting holes in the panel.

The only thing I have to take care of is my network connection. There’s no easy way for me to get a CAT5 cable into that box from either the backside of that wall or the attic. I’ve been using a wifi adapter just for now. I’ll either have to figure something out about that network cable, or at the very least extend the wifi card’s antenna to mount externally on the metal box.

Here’s the code I’m using. I’m not a pro, so apologies for the massacre I ran on your work.

#!/usr/bin/env python3
#
# MCP3008 Pilarm Mod by Michael Rogers
#
# Based on Pilarm by rcoodey (https://github.com/rcoodey/Pilarm) and
# the Adafruit_Python_MCP3008 library examples by Tony DiCola
# (https://github.com/adafruit/Adafruit_Python_MCP3008)
#
# See Pilarm documentation for installation instructions.
# Requires Adafruit_Python_MCP3008 library.

import time
import requests

# Import SPI library for hardware SPI only
#import Adafruit_GPIO.SPI as SPI
import Adafruit_MCP3008


############################################################
## BEGIN CONFIGURATION AREA                               ##
## YOU MUST FILL THESE IN                                 ##
############################################################

# SmartThings settings
shard_url = 'XXX'
application_id = 'XXX'
access_token = 'XXX'

# Set individual high/low thresholds here for MCP ports 0-7.
# Should be between 0 and 1023. Ideally in the middle of the expected high and low measurements.
threshold = [512, 512, 512, 512, 512, 512, 512, 512]

# Software SPI configuration:
CLK  = 18
MISO = 23
MOSI = 24
CS   = 25
mcp = Adafruit_MCP3008.MCP3008(clk=CLK, cs=CS, miso=MISO, mosi=MOSI)

# Hardware SPI configuration:
# SPI_PORT   = 0
# SPI_DEVICE = 0
# mcp = Adafruit_MCP3008.MCP3008(spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE))

############################################################
## END CONFIGURATION AREA                                 ##
## YOU SHOULD NOT NEED TO CHANGE ANYTHING BELOW THIS LINE ##
############################################################


# Set initial position list
print('Setting initial positions.')
values = [0]*8
position = [0]*8
prevPosition = [0]*8
differences = 0

json = '{'
for i in range(8):
    values[i] = mcp.read_adc(i)
    if values[i] < threshold[i]:
        prevPosition[i] = 0
    else:
        prevPosition[i] = 1
    json = json + '"' + str(i) + '":"' + str(prevPosition[i]) + '"'
    if i < 7:
        json = json + ','
json = json + '}'

# Send initial json of all positions
requests.put('https://{shard_url}/api/smartapps/installations/{application_id}/pilarm/allZonesEvent?access_token={access_token}'.format(shard_url=shard_url,application_id=application_id,access_token=access_token,status=position[i],zone=i), data=json)

print('{0} {1} {2} {3} {4} {5} {6} {7}'.format(*prevPosition))

print('Starting main loop, press Ctrl-C to quit...')

# Main program loop.
while True:
    # Read all the ADC channel values in a list.
    for i in range(8):
        # The read_adc function will get the value of the specified channel (0-7).
        values[i] = mcp.read_adc(i)
        if values[i] < threshold[i]:
            position[i] = 0
        else:
            position[i] = 1

    # Reset differences count
    differences = 0

    for i in range(8):
        if position[i] != prevPosition[i]:
            print('Firing!')
            differences += 1
            requests.get('https://{shard_url}/api/smartapps/installations/{application_id}/pilarm/zoneEvent/{status}/{zone}?access_token={access_token}'.format(shard_url=shard_url,application_id=application_id,access_token=access_token,status=position[i],zone=i))

    if differences > 0:
        prevPosition = list(position)

    time.sleep(0.1)

It sends the full json for all eight positions on startup and then polls the positions every 0.1 seconds. It only sends updates when something changes. I don’t think it needs to do periodic updates since it polls and compares instead of using an interrupt, but it wouldn’t be hard to add since the full update code is already there.

Thanks again for sharing your code, I couldn’t have accomplished what I wanted without it!


(Ryan) #10

That is great stuff @michaelcasson, thanks a lot of sharing. I didn’t have an existing alarm system so didn’t even think to tie it in with one. Glad you got that all worked out.

Also just realized I didn’t respond to your last question about running multiple apps on the same Pi… you sure can do this. I just configured each to listen on a different port. Started with 80, then 81 and 82. Right now I have Pilarm and Piputer on one Pi and Pirage on its own C.H.I.P.

Thanks again for sharing!


#11

@michaelcasson, Your solution is exactly what I’ve been trying to do on my system! I’m so glad I stumbled across this forum post. I purchased an MCP3008 ADC back in February and have been messing around with it and the Rpi ever sense. I’ve tried hooking up to my security system using resistor dividers, as you did, but I’m doing something wrong in my circuitry.

Would you mind posting your schematic of your circuit (from zone terminals, resistor divider, mcp3008, and RPI)? Just one zone would be sufficient. I think where my circuit is wrong is the connections to the various COMS, grounds, Rpi ground, etc.

I even tried using an op amp buffer prior to resistive divider, but that didn’t work either.

Thanks!


#12

Thank you @michaelcasson and @rcoodey for the inspiration on this project. I have successfully managed to monitor my pre-wired security system via an MCP3008 chip, also using a LM324 op-amp buffer to isolate the main system. I had to study very closely the photograph from @michaelcasson to get the wiring correct. Monitoring all done via code written in Java on Raspberry Pi (Pi4J). I also was able to create an Android app to monitor and subscribe to all events. Works perfectly. I couldn’t have done it without you guys. I plan (and hope) to post my entire project on the internet for others benefit. Thank you so much everyone for the inspiration.


(Michael Rogers) #13

Sorry @przano for not responding sooner! Yes, since I used the adafruit board in the picture, it’s all labelled pretty well. I think there’s only four jumper wires that you can’t see, which are on the first four zones. They work the same as the white ones on the last four, which are visible.

As far as grounds go, I connected one from the security panel to the gnd on the Pi, and one comes in from the 5v power connector on the micro usb. The one on the panel was labeled either gnd or (-). It was zero ohm to the neg battery terminal if I remember correctly.

The wires for each zone in my panel are labelled one high and one low. Some of the lows are shared but none of the highs are. The ‘lows’ aren’t exactly grounds and I didn’t connect to them at all. The high sides went from 12 point something volts down to … something else. Not completely high (~14v) and not completely low either. I measured these against the ground to see what values I needed for my divider.

I used a script that just constantly spit out the values from the MCP so I could see what highs and lows measured at before I bothered with the smartthings part. One step at a time. The LM324 will probably protect your pi better, though, anyway. Case in point, the first zone in my picture above is disconnected because I didn’t realize that the motion detector feeds back a higher voltage than the door/window sensors. It wasn’t until I saw the MCP feeding back 1023 (1024?) that I realized I was going above the 3.3v on that pin. Luckily I didn’t blow that pin, or worse.

Again, sorry for the delay but it looks like you got it figured out anyway. Meanwhile I finally ran a CAT5 cable (PITA) and got rid of that wifi adapter.


(Jay) #14

Hey Guys,

This is a really interesting project. I have an old alarm system with 30 sensors. I’d like to be able to read each sensor individually. I also have a Pi 3 B laying around waiting for a job, but the number of sensors is higher than the number of GPIO pins. Has anyone tried connecting the sensors through some kind of multiplexer?

Or do you foresee any problems doing so?

Thanks!


(Ryan) #15

Sorry, don’t know how to answer your question about if or how a multiplexer would work. My workaround for not having enough GPIO pins was to wire each door separate but then combine each individual rooms windows in series. So will know what room triggered the alarm but have to find the actual window.

Thinking you probably knew that already, sorry for not really helping…


(Jay) #16

Hi Ryan, didn’t realize you had replied already, didn’t see a notification. I am working on a setup with a couple of MCP23017 chips (16 bit digital IO with internal pull-ups and i2c interface). I have the sensor side of things working, but am still working on interfacing with Smartthings. Got an OAuth error.


(Kenneth Collins) #17

@rcoodey Hi Ryan,

Many thanks for sharing this, I’m looking to get a pi zero to notify me when the doorbell has been pressed (returned the Ring doorbell I bought, it was useless).

I’m at point 12 in the readme on your github…I just get an error…

Oh No! Something Went Wrong!

Error
500: Internal Server Error
URI
/oauth/token
Reference Id
xxxxb453-b966-4cf8-93ef-9a18d17799be
Date
Sat Aug 18 21:12:26 UTC 2018

I’m not sure I’ve got the formatting correct…

https://graph.api.smartthings.com/oauth/token?grant_type=authorization_code&client_id=xxxxxxxx-70a8-41a7-bc5b-02b78cfdxxxx&client_secret=xxxxb5f2-ad1e-478e-a43c-12c39367xxxx&redirect_uri=http://localhost&code=xxxxxx&scope=app

Any help greatly appreciated.

Kenny.


(Ryan) #18

@kencol78 Your URL seems ok. Haven’t done that piece in a long time now. Maybe double check the shard you are on: FAQ: How to find out what “shard” (cloud slice IDE URL) your Account / Location is on?