mirror of
				https://github.com/KevinMidboe/python-gpiozero.git
				synced 2025-10-29 17:50:37 +00:00 
			
		
		
		
	Fix #107
Add forward_device and backward_device to Motor, left_motor and right_motor to Robot, and ensure all CompositeDevice descendents have a proper close() method and closed property. Also, add a few more _check_open calls around the place to make sure GPIODeviceClosed is properly raised in response to read and writing values.
This commit is contained in:
		@@ -31,6 +31,10 @@ class LEDBoard(SourceMixin, CompositeDevice):
 | 
				
			|||||||
        for led in self.leds:
 | 
					        for led in self.leds:
 | 
				
			||||||
            led.close()
 | 
					            led.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def closed(self):
 | 
				
			||||||
 | 
					        return all(led.closed for led in self.leds)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def leds(self):
 | 
					    def leds(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@@ -188,6 +192,10 @@ class TrafficLightsBuzzer(SourceMixin, CompositeDevice):
 | 
				
			|||||||
        self.buzzer.close()
 | 
					        self.buzzer.close()
 | 
				
			||||||
        self.button.close()
 | 
					        self.button.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def closed(self):
 | 
				
			||||||
 | 
					        return all(o.closed for o in self.all)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def all(self):
 | 
					    def all(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@@ -305,6 +313,24 @@ class Robot(SourceMixin, CompositeDevice):
 | 
				
			|||||||
        self._left.close()
 | 
					        self._left.close()
 | 
				
			||||||
        self._right.close()
 | 
					        self._right.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def closed(self):
 | 
				
			||||||
 | 
					        return self._left.closed and self._right.closed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def left_motor(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Returns the `Motor` device representing the robot's left motor.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return self._left
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def right_motor(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Returns the `Motor` device representing the robot's right motor.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return self._right
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def value(self):
 | 
					    def value(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,8 +82,20 @@ class GPIOBase(object):
 | 
				
			|||||||
        # safely called from subclasses without worrying whether super-class'
 | 
					        # safely called from subclasses without worrying whether super-class'
 | 
				
			||||||
        # have it (which in turn is useful in conjunction with the SourceMixin
 | 
					        # have it (which in turn is useful in conjunction with the SourceMixin
 | 
				
			||||||
        # class).
 | 
					        # class).
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Shut down the device and release all associated resources.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def closed(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Returns `True` if the device is closed (see the `close` method). Once a
 | 
				
			||||||
 | 
					        device is closed you can no longer use any other methods or properties
 | 
				
			||||||
 | 
					        to control or query the device.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __enter__(self):
 | 
					    def __enter__(self):
 | 
				
			||||||
        return self
 | 
					        return self
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -150,7 +162,8 @@ class CompositeDevice(ValuesMixin, GPIOBase):
 | 
				
			|||||||
    Represents a device composed of multiple GPIO devices like simple HATs,
 | 
					    Represents a device composed of multiple GPIO devices like simple HATs,
 | 
				
			||||||
    H-bridge motor controllers, robots composed of multiple motors, etc.
 | 
					    H-bridge motor controllers, robots composed of multiple motors, etc.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    pass
 | 
					    def __repr__(self):
 | 
				
			||||||
 | 
					        return "<gpiozero.%s object>" % (self.__class__.__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GPIODevice(ValuesMixin, GPIOBase):
 | 
					class GPIODevice(ValuesMixin, GPIOBase):
 | 
				
			||||||
@@ -199,15 +212,6 @@ class GPIODevice(ValuesMixin, GPIOBase):
 | 
				
			|||||||
            raise GPIODeviceClosed(
 | 
					            raise GPIODeviceClosed(
 | 
				
			||||||
                '%s is closed or uninitialized' % self.__class__.__name__)
 | 
					                '%s is closed or uninitialized' % self.__class__.__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					 | 
				
			||||||
    def closed(self):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Returns `True` if the device is closed (see the `close` method). Once a
 | 
					 | 
				
			||||||
        device is closed you can no longer use any other methods or properties
 | 
					 | 
				
			||||||
        to control or query the device.
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        return self._pin is None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def close(self):
 | 
					    def close(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Shut down the device and release all associated resources.
 | 
					        Shut down the device and release all associated resources.
 | 
				
			||||||
@@ -254,6 +258,10 @@ class GPIODevice(ValuesMixin, GPIOBase):
 | 
				
			|||||||
                GPIO.remove_event_detect(pin)
 | 
					                GPIO.remove_event_detect(pin)
 | 
				
			||||||
                GPIO.cleanup(pin)
 | 
					                GPIO.cleanup(pin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def closed(self):
 | 
				
			||||||
 | 
					        return self._pin is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def pin(self):
 | 
					    def pin(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,7 +62,11 @@ class OutputDevice(SourceMixin, GPIODevice):
 | 
				
			|||||||
            raise
 | 
					            raise
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _write(self, value):
 | 
					    def _write(self, value):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
            GPIO.output(self.pin, bool(value))
 | 
					            GPIO.output(self.pin, bool(value))
 | 
				
			||||||
 | 
					        except ValueError:
 | 
				
			||||||
 | 
					            self._check_open()
 | 
				
			||||||
 | 
					            raise
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def on(self):
 | 
					    def on(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@@ -236,12 +240,17 @@ class PWMOutputDevice(DigitalOutputDevice):
 | 
				
			|||||||
        super(PWMOutputDevice, self).close()
 | 
					        super(PWMOutputDevice, self).close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _read(self):
 | 
					    def _read(self):
 | 
				
			||||||
 | 
					        self._check_open()
 | 
				
			||||||
        return self._value
 | 
					        return self._value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _write(self, value):
 | 
					    def _write(self, value):
 | 
				
			||||||
        if not 0 <= value <= 1:
 | 
					        if not 0 <= value <= 1:
 | 
				
			||||||
            raise OutputDeviceError("PWM value must be between 0 and 1")
 | 
					            raise OutputDeviceError("PWM value must be between 0 and 1")
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
            self._pwm.ChangeDutyCycle(value * 100)
 | 
					            self._pwm.ChangeDutyCycle(value * 100)
 | 
				
			||||||
 | 
					        except AttributeError:
 | 
				
			||||||
 | 
					            self._check_open()
 | 
				
			||||||
 | 
					            raise
 | 
				
			||||||
        self._value = value
 | 
					        self._value = value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
@@ -385,6 +394,30 @@ class Motor(SourceMixin, CompositeDevice):
 | 
				
			|||||||
        self._forward = PWMOutputDevice(forward)
 | 
					        self._forward = PWMOutputDevice(forward)
 | 
				
			||||||
        self._backward = PWMOutputDevice(backward)
 | 
					        self._backward = PWMOutputDevice(backward)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def close(self):
 | 
				
			||||||
 | 
					        self._forward.close()
 | 
				
			||||||
 | 
					        self._backward.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def closed(self):
 | 
				
			||||||
 | 
					        return self._forward.closed and self._backward.closed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def forward_device(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Returns the `PWMOutputDevice` representing the forward pin of the motor
 | 
				
			||||||
 | 
					        controller.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return self._forward
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def backward_device(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Returns the `PWMOutputDevice` representing the backward pin of the
 | 
				
			||||||
 | 
					        motor controller.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        return self._backward
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def value(self):
 | 
					    def value(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user