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!