This implements the proposal discussed in the re-opened #279 to add a
pin_factory argument at the device level and remove the ability to
specify a pin instance to device constructors (they now only accept a
pin specification).
Note: there's still a couple of bits to tidy up (tests on "real" Pis,
and pin_factory.release_all needs refinement) but the test suite is now
at least capable of passing on a PC.
This is a minimal change which re-orders some bits of CompositeDevice's
constructor to ensure that all exceptions get raised *before* we store a
reference to the contained devices. Hopefully this'll be enough to sort
out 2.x but I'm not sure it will be for pypy (might still require an
explicit close there).
Also updated StatusBoard and StatusZero to reject duplicate identifiers
(namedtuple doesn't pick 'em up because they're passed in a dict and
thus the dups are squashed prior to the call). Added tests for all the
relevant stuff.
Permit replacement of pin_factory without closing old factory. However,
continue closing devices associated with extant pin factory at script
termination.
Ensure SourceMixin descendents shut down the source prior to closing.
Furthermore, make sure devices are closed before pin factory shuts down,
and that pins have a strong reference to their owning factory (to
prevent losing the factory before the pins).
Ensure LEDCollection cleans up upon construction failure, rename some
internals to be a bit more obvious, rename PinGPIOUnsupported to
PinUnsupported, and some other stuff I've forgotten!
Sorry! Dave's messing around with the pin implementations again.
Hopefully the last time. The pin_factory is now really a factory object
which can be asked to produce individual pins or pin-based interfaces
like SPI (which can be supported properly via pigpio).
This prevents it being modified post-construction (just like the way
CompositeDevice._all and CompositeDevice._order are already 'frozen' by being
tuples)
While the tests work well on a PC or Travis, the Pi (where I ought to be
running them!) has some issues with the timing tests. Need to relax the
tolerance of the "assert_states_and_times" method to 0.05 seconds
otherwise it periodically fails even on something reasonably quick like
a Pi 2 (less failures on a Pi 3 but still occasionally).
Also reduced default fps to 25; if the default timing occasionally fails
on a Pi 2 it's evidently too fast for a Pi 1 and shouldn't be the
default; 25 also doesn't look any different to me on a pulsing LED.
There's also a bunch of miscellaneous fixes in here; last minute typos
and chart re-gens for the 1.2 release.
Me and my big mouth. No sooner do I declare the base classes "relatively
stable" than I go and mess around with it all again. Anyway, this is the
long promised set of utilities to make source/values more interesting.
It includes a few interesting little utility functions, a whole bunch of
examples and introduces the notion of "pseudo" devices with no (obvious)
hardware representation like a time-of-day device.
This necessitated making the event system a little more generic (it's
not exclusive the GPIO devices after all; no reason we can't use it on
composite devices in future) and by this point the mixins have gotten
large enough to justify their own module.
The pseudo-devices are a bit spartan and basic at the moment but I'm
sure there'll be plenty of future ideas...
This PR implements SnowPi, adds the ability for LEDBoard's to own other
LEDBoards as well as LEDs, and enhances blink so that manually
controlling a LED automatically stops it from blinking (no matter
whether it's blinking itself or a LEDBoard is blinking it).
It also fixes up RGBLED and Motor which I managed to break with the last
PR ...
This PR adds a software SPI implementation. Firstly this removes the
absolute necessity for spidev (#140), which also means when it's not
present things still work (effectively fixes#185), and also enables any
four pins to be used for SPI devices (which don't require the hardware
implementation).
The software implementation is simplistic but still supports clock
polarity and phase, select-high, and variable bits per word. However it
doesn't allow precise speeds to be implemented because it just wibbles
the clock as fast as it can (which being pure Python isn't actually that
fast).
Finally, because this PR involves creating a framework for "shared"
devices (like SPI devices with multiple channels), it made sense to bung
Energenie (#69) in as wells as this is a really simple shared device.
Added source_delay property to SourceMixin which means it'll now appear
everywhere. Default is 0.01 which is just enough to drop CPU usage while
remaining responsive enough for the majority of purposes.
This commit is a fairly major piece of work that abstracts all pin
operations (function, state, edge detection, PWM, etc.) into a base
"Pin" class which is then used by input/output/composite devices to
perform all required configuration.
The idea is to pave the way for I2C based IO extenders which can present
additional GPIO ports with similar capabilities to the Pi's "native"
GPIO ports. As a bonus it also abstracts away the reliance on the
RPi.GPIO library to allow alternative pin implementations (e.g. using
RPIO to take advantage of DMA based PWM), or even pure Python
implementations.
This removes the circular dependency introduced in PR#137. This also
fixes up an issue in the base meta-class which meant it wasn't working
in Python 3 (only Python 2), and adds a bit to the meta-class to allow
docstrings to be inherited (taken from the rest-docs branch).
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 finishes off implementing values and source for all (current)
classes in gpiozero. I'm afraid things get rather complex in this
commit. For starters, we've now got quite a few "aggregate" classes
which necessarily don't descend from GPIODevice. To implement values and
source on these I could either repeat a helluva lot of code or ... turn
to mixin classes. Yeah, it's multiple inheritance time, baby!
Unfortunately multiple inheritance doesn't work with __slots__ but we
really ought to keep functionality that they provide us (raise
AttributeError when an unknown attribute is set). So I've implemented
this with ... erm ... metaclasses. Sorry!
Makes `value` an alias of `is_active` in the base `GPIODevice`, and
`values` an infinite iterable of this value. Then adds `source` property
to `OutputDevice` allowing simple linkage of devices via iterators.
Add more property aliases and do them properly (no more lambdas and
string lookups) which means we can remove `_alias`. This commit also
defines `__slots__` for all classes which should prevent assignation of
invalid attributes with an AttributeError (more friendly than silently
doing the wrong thing). Finally, it cleans up all the property defs to
use Ben's preferred decorator style.
Big push on getting the docs cleaned up before 1.0. Proper wrapping of
everything so it's decently viewable from the command line (or as
decently viewable as markdown can be - the tables will never look great
from the command line).
Only one code change in this PR: rename bouncetime to bounce_time
(everything else is PEP-8, so this probably should be too) and change
its units to seconds from milliseconds (again, all other durations in
the library are in seconds, so it feels inconsistent that this one
isn't; for the sake of those who won't read the docs - which is most
people - I figure consistency helps with guessing!).
Permit devices to be explicitly closed and used as context managers.
Also deal with cleanup properly at script end and ensure objects don't
step on the global cleanup function.