Add a nice __repr__ to the GPIODevice base class.
This isn't much but generally I think `__repr__` implementations should
be deliberately simple: firstly, they're frequently used for debugging
so if they're at all complex you risk making a debugging tool buggy
(very annoying!). Secondly, if you pour too much info into them you risk
making the debugging output cluttered, so I tend to prefer keeping it to
straight-forward simple to retrieve/calculate info without excessive
detail (if the user wants more, they can always query it directly).
There is one refinement here: in SmoothedInputDevice, `__repr__` is
tweaked to ensure that when partial is False (the default), and the
queue isn't filled, `__repr__` doesn't block (because it should *never*
block).
Fairly major tidy up of the hierarchy as well. There's now a trivial
base class: InputDevice which simply permits reading of state.
WaitableInputDevice descends from this and introduces waitable events
and callbacks, and provides a hook for calling them but needs further
machinery to activate that hook.
DigitalInputDevice (crap name?) descends from WaitableInputDevice and
uses the standard RPi.GPIO callback mechanisms to handle events. This is
intended for use with trivial on/off devices with predictably small
bounce times.
Next is SmoothedInputDevice (crap name?) which also descends from
WaitableInputDevice. This includes a background threaded queue which
constantly monitors the state of the device and provides a running mean
of its state. This is compared to a threshold for determining active /
inactive state. This is intended for use with on/off devices that
"jitter" a lot and for which a running average is therefore appropriate
or for devices which provide an effectively analog readout (like
charging capacitor timings).
MonitorSensor and LightSensor now descend from SmoothedInputDevice, and
Button descends from DigitalInputDevice. All "concrete" classes provide
event aliases appropriate to their function (e.g. when_dark,
when_pressed, etc.)
Remove wait_for_input, add_callback and remove_callback from the base
InputDevice class and add specific things for LightSensor:
wait_for_light and wait_for_dark to wait on those events occurring, and
when_light and when_dark which can be set to callbacks to call on those
events occurring.
* Move `is_active` to `GPIODevice`; it's equally applicable to inputs
and outputs so there's no point having it just in inputs
* Flip the pull-up status for `MotionSensor` (it was backwards leading
to reversed readings from the sensor)
* Add a `threshold` to `MotionSensor` (optional), and `value` (similar
to `LightSensor`)
* Also expose `pull_up` as a simple bool property
* Rejig `LightSensor` so it also derives from `InputDevice` (it inherits
enough to make it worthwhile) and so that its API is similar to
`MotionSensor` (a `value` property with a `*_detected` property, and a
background threaded queue which constantly monitors values)
The motion sensor queue doesn't shut down properly at script end at the
moment and prevents the interpreter shutting down. This is because it's
a non-daemon thread so `__del__` never gets run and so on.
This is a bit of a major PR - I can split it up if you want. Firstly it
makes a common base class called `GPIODevice` for both `InputDevice` and
`OutputDevice`. This just takes care of the read-only pin stuff. Next it
makes a `GPIOThread` class that ensures its a daemon thread, and which
also ensures proper cleanup on shutdown.
Finally, it fixes `MotionSensor` to use the new `GPIOThread` class
(tested this time! Works nicely) and adds the `blink` method to the
`LED` class (which also works nicely this time).
Small patch to ensure GPIO.cleanup is always called on interpreter
shutdown. This just means the library will "play nice" with whatever
comes afterward.