def add_event_detect(channel, trigger, callback=None, bouncetime=None): """ This function is designed to be used in a loop with other things, but unlike polling it is not going to miss the change in state of an input while the CPU is busy working on other things. This could be useful when using something like Pygame or PyQt where there is a main loop listening and responding to GUI events in a timely basis. :param channel: the channel based on the numbering system you have specified (:py:attr:`GPIO.BOARD`, :py:attr:`GPIO.BCM` or :py:attr:`GPIO.SUNXI`). :param trigger: The event to detect, one of: :py:attr:`GPIO.RISING`, :py:attr:`GPIO.FALLING` or :py:attr:`GPIO.BOTH`. :param callback: (optional) TODO :param bouncetime: (optional) TODO .. code: python GPIO.add_event_detect(channel, GPIO.RISING) # add rising edge detection on a channel do_something() if GPIO.event_detected(channel): print('Button pressed') """ _check_configured(channel, direction=IN) if bouncetime is not None: if _gpio_warnings: warnings.warn( "bouncetime is not (yet) fully supported, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.", stacklevel=2) pin = get_gpio_pin(_mode, channel) event.add_edge_detect(pin, trigger, __wrap(callback, channel))
def test_add_edge_detect_called_twice_throws_error(fs): pin = 43 fs.CreateFile("/sys/class/gpio/gpio{0}/edge".format(pin)) fs.CreateFile("/sys/class/gpio/gpio{0}/value".format(pin)) with patch("select.epoll"): try: event.add_edge_detect(pin, RISING) assert pin in event._threads with pytest.raises(RuntimeError) as ex: event.add_edge_detect(pin, RISING) assert str( ex.value ) == "Conflicting edge detection already enabled for this GPIO channel" finally: event.cleanup() assert pin not in event._threads
def test_blocking_wait_raises_error_add_edge_detect_already_active(fs): pin = 66 fs.CreateFile("/sys/class/gpio/gpio{0}/edge".format(pin)) fs.CreateFile("/sys/class/gpio/gpio{0}/value".format(pin)) with patch("select.epoll"): try: assert pin not in event._threads event.add_edge_detect(pin, RISING) with pytest.raises(RuntimeError) as ex: event.blocking_wait_for_edge(pin, RISING) assert str( ex.value ) == "Conflicting edge detection events already exist for this GPIO channel" finally: event.cleanup()
def test_edge_detected(fs): pin = 23 fs.CreateFile("/sys/class/gpio/gpio{0}/edge".format(pin)) fs.CreateFile("/sys/class/gpio/gpio{0}/value".format(pin)) with patch("select.epoll") as mock: try: assert pin not in event._threads event.add_edge_detect(pin, RISING) assert not event.edge_detected(pin) mock.return_value.poll.return_value = [(pin, 4)] time.sleep(2) event._threads[pin].cancel() assert event.edge_detected(pin) assert not event.edge_detected(pin) finally: event.cleanup() assert pin not in event._threads
def test_add_edge_callback(fs): pin = 71 fs.CreateFile("/sys/class/gpio/gpio{0}/edge".format(pin)) fs.CreateFile("/sys/class/gpio/gpio{0}/value".format(pin)) called = {} def cb(p): called[p] = True with patch("select.epoll") as mock: try: assert pin not in event._threads event.add_edge_detect(pin, RISING) event.add_edge_callback(pin, cb) mock.return_value.poll.return_value = [(pin, 4)] time.sleep(2) event.cleanup(pin) assert pin in called finally: event.cleanup()
def test_callback_raises_error(fs): pin = 194 fs.CreateFile("/sys/class/gpio/gpio{0}/edge".format(pin)) fs.CreateFile("/sys/class/gpio/gpio{0}/value".format(pin)) def cb(p): raise RuntimeError("test exception") with patch("select.epoll") as mock: try: assert pin not in event._threads event.add_edge_detect(pin, RISING, cb) mock.return_value.poll.return_value = [(pin, 74)] time.sleep(2) with pytest.raises(RuntimeError) as ex: event.cleanup(pin) assert str(ex.value) == "test exception" finally: event.cleanup()