+# 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