#!/usr/bin/python3 import time, socket, atexit import queue, threading, select from libtuer import log, ThreadFunction import RPi.GPIO as GPIO GPIO.setmode(GPIO.BOARD) atexit.register(GPIO.cleanup) tuerSock = "/run/tuer.sock" ringPin = 18 # Main classes class PinWatcher(): def __init__(self, pin, histlen): GPIO.setup(pin, GPIO.IN) assert histlen > 1 # otherwise our logic goes nuts... self._pin = pin self._histlen = histlen # state change detection self._state = None self._newstate = None # != None iff we are currently seeing a state change self._newstatelen = 0 # only valid if newstate != None # start state change handler thread self._callback = ThreadFunction(self.callback) self.stop = self._callback.stop def read(self): curstate = GPIO.input(self._pin) assert curstate in (0, 1) if curstate != self._state: # the state is about to change if curstate == self._newstate: # we already saw this new state self._newstatelen += 1 if self._newstatelen >= self._histlen: self._callback(self._state, curstate) # send stuff to the other thread self._state = curstate self._newstate = None else: # now check for how long we see this new state self._newstate = curstate self._newstatelen = 1 else: # old state is preserved self._newstate = None class RingWatcher(PinWatcher): def __init__(self): super().__init__(ringPin, 2) self.last1Event = None def callback(self, oldstate, newstate): if oldstate is None: return # ignore the very first state change # now (oldstate, newstate) is either (0, 1) or (1, 0) if newstate: self.last1Event = time.time() elif self.last1Event is not None: # how long was this pressed? timePressed = time.time() - self.last1Event log("Ring button pressed for",timePressed) if timePressed >= 1.5 and timePressed <= 3: self.buzz() def buzz(self): log("Opening door") # talk with tuerd s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) s.connect(tuerSock) s.send(b'buzz') s.close() # MAIN PROGRAM pins = [ RingWatcher(), ] try: log("entering loop") while True: for pin in pins: pin.read() time.sleep(0.02) except KeyboardInterrupt: for pin in pins: pin.stop()