Module ButtonLib
[hide private]
[frames] | no frames]

Source Code for Module ButtonLib

  1  # ButtonLib.py 
  2   
  3  import RPi.GPIO as GPIO 
  4  import time 
  5  from threading import Thread 
  6   
  7  DEBUG = False 
  8   
  9  # Button event constants 
 10  BUTTON_PRESSED = 1 
 11  BUTTON_RELEASED = 2 
 12  BUTTON_LONGPRESSED = 3 
 13  BUTTON_CLICKED = 4 
 14  BUTTON_DOUBLECLICKED = 5 
 15  BUTTON_LONGPRESS_DURATION = 2 # default (in s) the button must be pressed to be a long press 
 16  BUTTON_DOUBLECLICK_TIME = 1 # default time (in s) to wait for a double click event 
 17   
18 -def delay(interval):
19 time.sleep(interval / 1000.0)
20
21 -class ClickThread(Thread):
22 - def __init__(self):
23 Thread.__init__(self) 24 self.start()
25
26 - def run(self):
27 if DEBUG: 28 print "===>ClickThread started" 29 global clickThread 30 self.isRunning = True 31 startTime = time.time() 32 while self.isRunning and (time.time() - startTime < BUTTON_DOUBLECLICK_TIME): 33 time.sleep(0.1) 34 if clickCount == 1 and not isLongPressEvent: 35 if xButtonListener != None: 36 xButtonListener(BUTTON_CLICKED) 37 clickThread = None 38 self.isRunning = False 39 if DEBUG: 40 print "===>ClickThread terminated"
41
42 - def stop(self):
43 self.isRunning = False
44
45 -class ButtonThread(Thread):
46 - def __init__(self):
47 Thread.__init__(self) 48 self.isRunning = False
49
50 - def run(self):
51 if DEBUG: 52 print "===>ButtonThread started" 53 self.isRunning = True 54 startTime = time.time() 55 while self.isRunning and (time.time() - startTime < BUTTON_LONGPRESS_DURATION): 56 time.sleep(0.1) 57 if self.isRunning: 58 if buttonListener != None: 59 buttonListener(BUTTON_LONGPRESSED) 60 if DEBUG: 61 print "===>ButtonThread terminated"
62
63 - def stop(self):
64 self.isRunning = False
65
66 -def onXButtonEvent(event):
67 global clickThread, clickCount, isLongPressEvent 68 if event == BUTTON_PRESSED: 69 if xButtonListener != None: 70 xButtonListener(BUTTON_PRESSED) 71 isLongPressEvent = False 72 if clickThread == None: 73 clickCount = 0 74 clickThread = ClickThread() 75 76 elif event == BUTTON_RELEASED: 77 if xButtonListener != None: 78 xButtonListener(BUTTON_RELEASED) 79 if isLongPressEvent and clickThread != None: 80 clickThread.stop() 81 clickThread = None 82 return 83 if clickThread != None and clickThread.isRunning: 84 clickCount += 1 85 if clickCount == 2: 86 clickThread.stop() 87 clickThread = None 88 if xButtonListener != None: 89 xButtonListener(BUTTON_DOUBLECLICKED) 90 else: 91 clickThread = None 92 93 elif event == BUTTON_LONGPRESSED: 94 isLongPressEvent = True 95 if xButtonListener != None: 96 xButtonListener(BUTTON_LONGPRESSED)
97 98 # Hardware callback
99 -def onButtonEvent(channel):
100 global buttonThread, inCallback 101 if inCallback: # inhibit reentrance 102 return 103 inCallback = True 104 # switch may bounce: down-up-up, down-up-down, down-down-up etc. in fast sequence 105 if GPIO.input(buttonPin) == GPIO.LOW: 106 if buttonThread == None: # down-down is suppressed 107 if DEBUG: 108 print "->ButtonDown" 109 buttonThread = ButtonThread() 110 buttonThread.start() 111 if buttonListener != None: 112 buttonListener(BUTTON_PRESSED) 113 else: 114 if buttonThread != None: # up-up is suppressed 115 if DEBUG: 116 print "->ButtonUp" 117 buttonThread.stop() 118 buttonThread.join(200) # wait until finished 119 buttonThread = None 120 if buttonListener != None: 121 buttonListener(BUTTON_RELEASED) 122 inCallback = False
123
124 -def addXButtonListener(listener):
125 global xButtonListener 126 addButtonListener(onXButtonEvent) 127 xButtonListener = listener
128
129 -def addButtonListener(listener):
130 global buttonListener 131 buttonListener = listener
132
133 -def setButtonPin(pin):
134 global buttonPin 135 buttonPin = pin 136 GPIO.setup(buttonPin, GPIO.IN, GPIO.PUD_UP) 137 GPIO.add_event_detect(buttonPin, GPIO.BOTH, onButtonEvent)
138 139 buttonThread = None 140 clickThread = None 141 inCallback = False 142 143 # Use physical pin numbers 144 GPIO.setmode(GPIO.BOARD) 145 GPIO.setwarnings(False) 146