1313from collections import deque
1414from types import FunctionType
1515
16- from RPi import GPIO
17-
1816from .exc import GPIODeviceError , GPIODeviceClosed , InputDeviceError
1917
20- _GPIO_THREADS = set ()
21- _GPIO_PINS = set ()
18+ # Get a pin implementation to use as the default; we prefer RPi.GPIO's here
19+ # as it supports PWM, and all Pi revisions. If no third-party libraries are
20+ # available, however, we fall back to a pure Python implementation which
21+ # supports platforms like PyPy
22+ from .pins import PINS_CLEANUP
23+ try :
24+ from .pins .rpigpio import RPiGPIOPin
25+ DefaultPin = RPiGPIOPin
26+ except ImportError :
27+ try :
28+ from .pins .rpio import RPIOPin
29+ DefaultPin = RPIOPin
30+ except ImportError :
31+ from .pins .native import NativePin
32+ DefaultPin = NativePin
33+
34+
35+ _THREADS = set ()
36+ _PINS = set ()
2237# Due to interactions between RPi.GPIO cleanup and the GPIODevice.close()
2338# method the same thread may attempt to acquire this lock, leading to deadlock
2439# unless the lock is re-entrant
25- _GPIO_PINS_LOCK = RLock ()
40+ _PINS_LOCK = RLock ()
2641
27- def _gpio_threads_shutdown ():
28- while _GPIO_THREADS :
29- for t in _GPIO_THREADS .copy ():
42+ def _shutdown ():
43+ while _THREADS :
44+ for t in _THREADS .copy ():
3045 t .stop ()
31- with _GPIO_PINS_LOCK :
32- while _GPIO_PINS :
33- GPIO .remove_event_detect (_GPIO_PINS .pop ())
34- GPIO .cleanup ()
46+ with _PINS_LOCK :
47+ while _PINS :
48+ _PINS .pop ().close ()
49+ # Any cleanup routines registered by pins libraries must be called *after*
50+ # cleanup of pin objects used by devices
51+ for routine in PINS_CLEANUP :
52+ routine ()
3553
36- atexit .register (_gpio_threads_shutdown )
37- GPIO .setmode (GPIO .BCM )
38- GPIO .setwarnings (False )
54+ atexit .register (_shutdown )
3955
4056
4157class GPIOMeta (type ):
@@ -196,20 +212,22 @@ def __init__(self, pin=None):
196212 # value of pin until we've verified that it isn't already allocated
197213 self ._pin = None
198214 if pin is None :
199- raise GPIODeviceError ('No GPIO pin number given' )
200- with _GPIO_PINS_LOCK :
201- if pin in _GPIO_PINS :
215+ raise GPIODeviceError ('No pin given' )
216+ if isinstance (pin , int ):
217+ pin = DefaultPin (pin )
218+ with _PINS_LOCK :
219+ if pin in _PINS :
202220 raise GPIODeviceError (
203- 'pin %d is already in use by another gpiozero object' % pin
221+ 'pin %r is already in use by another gpiozero object' % pin
204222 )
205- _GPIO_PINS .add (pin )
223+ _PINS .add (pin )
206224 self ._pin = pin
207- self ._active_state = GPIO . HIGH
208- self ._inactive_state = GPIO . LOW
225+ self ._active_state = True
226+ self ._inactive_state = False
209227
210228 def _read (self ):
211229 try :
212- return GPIO . input ( self .pin ) == self ._active_state
230+ return self .pin . state == self ._active_state
213231 except TypeError :
214232 self ._check_open ()
215233 raise
@@ -260,13 +278,12 @@ def close(self):
260278 ...
261279 """
262280 super (GPIODevice , self ).close ()
263- with _GPIO_PINS_LOCK :
281+ with _PINS_LOCK :
264282 pin = self ._pin
265283 self ._pin = None
266- if pin in _GPIO_PINS :
267- _GPIO_PINS .remove (pin )
268- GPIO .remove_event_detect (pin )
269- GPIO .cleanup (pin )
284+ if pin in _PINS :
285+ _PINS .remove (pin )
286+ pin .close ()
270287
271288 @property
272289 def closed (self ):
@@ -275,9 +292,10 @@ def closed(self):
275292 @property
276293 def pin (self ):
277294 """
278- The pin (in BCM numbering) that the device is connected to. This will
279- be ``None`` if the device has been closed (see the :meth:`close`
280- method).
295+ The :class:`Pin` that the device is connected to. This will be ``None``
296+ if the device has been closed (see the :meth:`close` method). When
297+ dealing with GPIO pins, query ``pin.number`` to discover the GPIO
298+ pin (in BCM numbering) that the device is connected to.
281299 """
282300 return self ._pin
283301
@@ -293,7 +311,7 @@ def value(self):
293311
294312 def __repr__ (self ):
295313 try :
296- return "<gpiozero.%s object on pin=%d , is_active=%s>" % (
314+ return "<gpiozero.%s object on pin %r , is_active=%s>" % (
297315 self .__class__ .__name__ , self .pin , self .is_active )
298316 except GPIODeviceClosed :
299317 return "<gpiozero.%s object closed>" % self .__class__ .__name__
@@ -307,7 +325,7 @@ def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
307325
308326 def start (self ):
309327 self .stopping .clear ()
310- _GPIO_THREADS .add (self )
328+ _THREADS .add (self )
311329 super (GPIOThread , self ).start ()
312330
313331 def stop (self ):
@@ -316,7 +334,7 @@ def stop(self):
316334
317335 def join (self ):
318336 super (GPIOThread , self ).join ()
319- _GPIO_THREADS .discard (self )
337+ _THREADS .discard (self )
320338
321339
322340class GPIOQueue (GPIOThread ):
0 commit comments