pyledriver/sensors.py

56 lines
1.5 KiB
Python

import RPi.GPIO as GPIO
import logging, time
from functools import partial
from threading import Timer
logger = logging.getLogger(__name__)
# this importantly controls which sensor events get logged. DEBUG logs
# everything, INFO logs only events that occur when state machine in
# "sensitive states" (armed, trippedCountdown, tripped)
logger.setLevel(logging.INFO)
# delay GPIO init to avoid false positive during powerup
INIT_DELAY = 60
def _lowPassFilter(pin, targetVal, period=0.001):
divisions = 10
sleepTime = period/divisions
for i in range(0, divisions):
time.sleep(sleepTime)
if GPIO.input(pin) != targetVal:
return False
return GPIO.input(pin) == targetVal
def _initGPIO(name, pin, GPIOEvent, callback):
logger.debug('starting \"%s\" on pin %s', name, pin)
GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(pin, GPIOEvent, callback=callback, bouncetime=500)
def startMotionSensor(pin, location, action):
name = 'MotionSensor@' + location
def trip(channel):
if _lowPassFilter(pin, 1):
action(location, logger)
logger.debug('waiting %s for %s to power on', INIT_DELAY, name)
t = Timer(INIT_DELAY, partial(_initGPIO, name, pin, GPIO.RISING, trip))
t.daemon = True
t.start()
def startDoorSensor(pin, action):
def trip(channel):
nonlocal closed
val = GPIO.input(pin)
if val != closed:
if _lowPassFilter(pin, val):
closed = val
action(closed, logger)
_initGPIO('DoorSensor', pin, GPIO.BOTH, trip)
closed = GPIO.input(pin)