#!/usr/bin/python3
-import time, socket
+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
-GPIO.setmode(GPIO.BOARD)
-GPIO.setup(ringPin, GPIO.IN)
-lastEvent = 0
+# 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
-
-while True:
- GPIO.wait_for_edge(ringPin, GPIO.BOTH)
- # measure time since event
- now = time.time()
- timePassed = now-lastEvent
- print("Time between events %f" % timePassed)
- # remember, remember
- lastEvent = now
- # action to be taken?
- if timePassed >= 1.5 and timePassed <= 3:
- print("Opening door")
+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')
- data = s.recv(4)
s.close()
- print("...done")
- if data != b'1':
- print("Received unexpected answer %s" % str(data))
-GPIO.cleanup()
+# 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()