UNPKG

js-gpiozero

Version:

A simple interface to GPIO devices with Raspberry Pi using nodejs

187 lines (166 loc) 5.51 kB
function EventsMixin () { this._active_event = false; this._inactive_event = false; this.when_activated = null; this.when_deactivated = null; this._last_state = null; this._last_changed = (new Date()).getTime(); } exports.EventsMixin = EventsMixin; EventsMixin.prototype._fire_events = function() { const old_state = this._last_state; const new_state = this._last_state = this.is_active(); if (old_state === null) { // Initial "indeterminate" state; set events but don't fire // callbacks as there's not necessarily an edge if (new_state !== false) { this._active_event = true; } else { this._inactive_event = true; } } else if (old_state !== new_state) { this._last_changed = (new Date()).getTime(); if (new_state !== false) { this._inactive_event = false; this._active_event = true; this._fire_activated(); } else { this._active_event = false; this._inactive_event = true; this._fire_deactivated(); } } }; /** * These methods are largely here to be overridden by descendents. * * @private */ EventsMixin.prototype._fire_activated = function () { if (this.when_activated !== null) { this.when_activated(); } }; /** * These methods are largely here to be overridden by descendents. * * @private */ EventsMixin.prototype._fire_deactivated = function () { if (this.when_deactivated !== null) { this.when_deactivated(); } }; /* def wait_for_active(self, timeout=None): """ Pause the script until the device is activated, or the timeout is reached. :param float timeout: Number of seconds to wait before proceeding. If this is ``None`` (the default), then wait indefinitely until the device is active. """ return self._active_event.wait(timeout) def wait_for_inactive(self, timeout=None): """ Pause the script until the device is deactivated, or the timeout is reached. :param float timeout: Number of seconds to wait before proceeding. If this is ``None`` (the default), then wait indefinitely until the device is inactive. """ return self._inactive_event.wait(timeout) @property def when_activated(self): """ The function to run when the device changes state from inactive to active. This can be set to a function which accepts no (mandatory) parameters, or a Python function which accepts a single mandatory parameter (with as many optional parameters as you like). If the function accepts a single mandatory parameter, the device that activated will be passed as that parameter. Set this property to ``None`` (the default) to disable the event. """ return self._when_activated @when_activated.setter def when_activated(self, value): self._when_activated = self._wrap_callback(value) @property def when_deactivated(self): """ The function to run when the device changes state from active to inactive. This can be set to a function which accepts no (mandatory) parameters, or a Python function which accepts a single mandatory parameter (with as many optional parameters as you like). If the function accepts a single mandatory parameter, the device that deactivated will be passed as that parameter. Set this property to ``None`` (the default) to disable the event. """ return self._when_deactivated @when_deactivated.setter def when_deactivated(self, value): self._when_deactivated = self._wrap_callback(value) @property def active_time(self): """ The length of time (in seconds) that the device has been active for. When the device is inactive, this is ``None``. """ if self._active_event.is_set(): return time() - self._last_changed else: return None @property def inactive_time(self): """ The length of time (in seconds) that the device has been inactive for. When the device is active, this is ``None``. """ if self._inactive_event.is_set(): return time() - self._last_changed else: return None def _wrap_callback(self, fn): if fn is None: return None elif not callable(fn): raise BadEventHandler('value must be None or a callable') # If fn is wrapped with partial (i.e. partial, partialmethod, or wraps # has been used to produce it) we need to dig out the "real" function # that's been wrapped along with all the mandatory positional args # used in the wrapper so we can test the binding args = () wrapped_fn = fn while isinstance(wrapped_fn, partial): args = wrapped_fn.args + args wrapped_fn = wrapped_fn.func if inspect.isbuiltin(wrapped_fn): # We can't introspect the prototype of builtins. In this case we # assume that the builtin has no (mandatory) parameters; this is # the most reasonable assumption on the basis that pre-existing # builtins have no knowledge of gpiozero, and the sole parameter # we would pass is a gpiozero object return fn else: # Try binding ourselves to the argspec of the provided callable. # If this works, assume the function is capable of accepting no # parameters try: inspect.getcallargs(wrapped_fn, *args) return fn except TypeError: try: # If the above fails, try binding with a single parameter # (ourselves). If this works, wrap the specified callback inspect.getcallargs(wrapped_fn, *(args + (self,))) @wraps(fn) def wrapper(): return fn(self) return wrapper except TypeError: raise BadEventHandler( 'value must be a callable which accepts up to one ' 'mandatory parameter') */