mirror of
https://github.com/KevinMidboe/python-gpiozero.git
synced 2025-12-08 20:39:01 +00:00
More work on the tests...
This commit is contained in:
@@ -19,6 +19,7 @@ from .exc import (
|
||||
BadEventHandler,
|
||||
CompositeDeviceError,
|
||||
CompositeDeviceBadName,
|
||||
CompositeDeviceBadOrder,
|
||||
SPIError,
|
||||
SPIBadArgs,
|
||||
EnergenieSocketMissing,
|
||||
|
||||
@@ -49,5 +49,5 @@ def median(data):
|
||||
return data[n // 2]
|
||||
else:
|
||||
i = n // 2
|
||||
return (data[n - 1] + data[n]) / 2
|
||||
return (data[i - 1] + data[i]) / 2
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ from .mixins import (
|
||||
)
|
||||
from .exc import (
|
||||
DeviceClosed,
|
||||
CompositeDeviceBadName,
|
||||
CompositeDeviceBadOrder,
|
||||
GPIOPinMissing,
|
||||
GPIOPinInUse,
|
||||
GPIODeviceClosed,
|
||||
@@ -191,7 +193,7 @@ class GPIOBase(GPIOMeta(nstr('GPIOBase'), (), {})):
|
||||
method). Once a device is closed you can no longer use any other
|
||||
methods or properties to control or query the device.
|
||||
"""
|
||||
return False
|
||||
raise NotImplementedError
|
||||
|
||||
def _check_open(self):
|
||||
if self.closed:
|
||||
@@ -223,7 +225,7 @@ class Device(ValuesMixin, GPIOBase):
|
||||
ranges (e.g. -1 to +1) and composite devices usually use tuples to
|
||||
return the states of all their subordinate components.
|
||||
"""
|
||||
return 0
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def is_active(self):
|
||||
@@ -261,8 +263,8 @@ class CompositeDevice(Device):
|
||||
if self._order is None:
|
||||
self._order = kwargs.keys()
|
||||
self._order = tuple(self._order)
|
||||
for missing_name in set(self._order) - set(kwargs.keys()):
|
||||
raise ValueError('%s missing from _order' % missing_name)
|
||||
for missing_name in set(kwargs.keys()) - set(self._order):
|
||||
raise CompositeDeviceBadOrder('%s missing from _order' % missing_name)
|
||||
super(CompositeDevice, self).__init__()
|
||||
for name in set(self._order) & set(dir(self)):
|
||||
raise CompositeDeviceBadName('%s is a reserved name' % name)
|
||||
@@ -372,9 +374,6 @@ class GPIODevice(Device):
|
||||
self._check_open()
|
||||
raise
|
||||
|
||||
def _fire_events(self):
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
super(GPIODevice, self).close()
|
||||
with _PINS_LOCK:
|
||||
|
||||
@@ -22,6 +22,9 @@ class CompositeDeviceError(GPIOZeroError):
|
||||
class CompositeDeviceBadName(CompositeDeviceError, ValueError):
|
||||
"Error raised when a composite device is constructed with a reserved name"
|
||||
|
||||
class CompositeDeviceBadOrder(CompositeDeviceError, ValueError):
|
||||
"Error raised when a composite device is constructed with an incomplete order"
|
||||
|
||||
class EnergenieSocketMissing(CompositeDeviceError, ValueError):
|
||||
"Error raised when socket number is not specified"
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import warnings
|
||||
from time import sleep, time
|
||||
from threading import Event
|
||||
|
||||
from .exc import InputDeviceError, GPIODeviceError, GPIODeviceClosed
|
||||
from .exc import InputDeviceError, GPIODeviceError, DeviceClosed
|
||||
from .devices import GPIODevice, CompositeDevice
|
||||
from .mixins import GPIOQueue, EventsMixin
|
||||
|
||||
@@ -161,7 +161,7 @@ class SmoothedInputDevice(EventsMixin, InputDevice):
|
||||
def __repr__(self):
|
||||
try:
|
||||
self._check_open()
|
||||
except GPIODeviceClosed:
|
||||
except DeviceClosed:
|
||||
return super(SmoothedInputDevice, self).__repr__()
|
||||
else:
|
||||
if self.partial or self._queue.full.wait(0):
|
||||
@@ -649,7 +649,9 @@ class DistanceSensor(SmoothedInputDevice):
|
||||
return self.pin
|
||||
|
||||
def _read(self):
|
||||
# Make sure the echo event is clear
|
||||
# Make sure the echo pin is low then ensure the echo event is clear
|
||||
while self.pin.state:
|
||||
sleep(0.00001)
|
||||
self._echo.clear()
|
||||
# Fire the trigger
|
||||
self._trigger.pin.state = True
|
||||
|
||||
@@ -8,7 +8,7 @@ str = type('')
|
||||
|
||||
|
||||
from collections import namedtuple
|
||||
from time import time
|
||||
from time import time, sleep
|
||||
from threading import Thread, Event
|
||||
try:
|
||||
from math import isclose
|
||||
@@ -182,7 +182,7 @@ class MockChargingPin(MockPin):
|
||||
"""
|
||||
def __init__(self, number):
|
||||
super(MockChargingPin, self).__init__()
|
||||
self.charge_time = 0.01
|
||||
self.charge_time = 0.01 # dark charging time
|
||||
self._charge_stop = Event()
|
||||
self._charge_thread = None
|
||||
|
||||
@@ -193,16 +193,51 @@ class MockChargingPin(MockPin):
|
||||
self._charge_stop.set()
|
||||
self._charge_thread.join()
|
||||
self._charge_stop.clear()
|
||||
self._charge_thread = Thread(target=lambda: self._charged)
|
||||
self._charge_thread = Thread(target=self._charge)
|
||||
self._charge_thread.start()
|
||||
elif value == 'output':
|
||||
if self.charge_thread:
|
||||
if self._charge_thread:
|
||||
self._charge_stop.set()
|
||||
self._charge_thread.join()
|
||||
|
||||
def _charged(self):
|
||||
def _charge(self):
|
||||
if not self._charge_stop.wait(self.charge_time):
|
||||
self.drive_high()
|
||||
try:
|
||||
self.drive_high()
|
||||
except AssertionError:
|
||||
# Charging pins are typically flipped between input and output
|
||||
# repeatedly; if another thread has already flipped us to
|
||||
# output ignore the assertion-error resulting from attempting
|
||||
# to drive the pin high
|
||||
pass
|
||||
|
||||
|
||||
class MockTriggerPin(MockPin):
|
||||
"""
|
||||
This derivative of :class:`MockPin` is intended to be used with another
|
||||
:class:`MockPin` to emulate a distance sensor. Set :attr:`echo_pin` to the
|
||||
corresponding pin instance. When this pin is driven high it will trigger
|
||||
the echo pin to drive high for the echo time.
|
||||
"""
|
||||
def __init__(self, number):
|
||||
super(MockTriggerPin, self).__init__()
|
||||
self.echo_pin = None
|
||||
self.echo_time = 0.04 # longest echo time
|
||||
self._echo_thread = None
|
||||
|
||||
def _set_state(self, value):
|
||||
super(MockTriggerPin, self)._set_state(value)
|
||||
if value:
|
||||
if self._echo_thread:
|
||||
self._echo_thread.join()
|
||||
self._echo_thread = Thread(target=self._echo)
|
||||
self._echo_thread.start()
|
||||
|
||||
def _echo(self):
|
||||
sleep(0.001)
|
||||
self.echo_pin.drive_high()
|
||||
sleep(self.echo_time)
|
||||
self.echo_pin.drive_low()
|
||||
|
||||
|
||||
class MockPWMPin(MockPin):
|
||||
|
||||
@@ -16,7 +16,7 @@ try:
|
||||
except ImportError:
|
||||
pass
|
||||
from itertools import count, cycle
|
||||
from math import sin, cos, floor
|
||||
from math import sin, cos, floor, radians
|
||||
try:
|
||||
from statistics import mean
|
||||
except ImportError:
|
||||
@@ -270,7 +270,7 @@ def sin_values():
|
||||
If you require a wider range than 0 to 1, see :func:`scaled`.
|
||||
"""
|
||||
for d in cycle(range(360)):
|
||||
yield sin(d)
|
||||
yield sin(radians(d))
|
||||
|
||||
|
||||
def cos_values():
|
||||
@@ -292,5 +292,5 @@ def cos_values():
|
||||
If you require a wider range than 0 to 1, see :func:`scaled`.
|
||||
"""
|
||||
for d in cycle(range(360)):
|
||||
yield cos(d)
|
||||
yield cos(radians(d))
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@ def _threads_shutdown():
|
||||
|
||||
class GPIOThread(Thread):
|
||||
def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
|
||||
super(GPIOThread, self).__init__(group, target, name, args, kwargs)
|
||||
self.stopping = Event()
|
||||
super(GPIOThread, self).__init__(group, target, name, args, kwargs)
|
||||
self.daemon = True
|
||||
|
||||
def start(self):
|
||||
|
||||
Reference in New Issue
Block a user