Operating system: Debian Linux 10 (Buster)
Python version: 3.8
No Pi
GPIO Zero version: 1.5.1
Pin factory used: e.g. MockFactory
Hi,
I am trying to trigger a callback function with the following simple code, but nothing happens. And while looking at the test coverage, I only found imperative test code for MotionSensor.
Is it possible to "trigger" the callback somehow?
from gpiozero.pins.mock import MockFactory
from gpiozero import Device, MotionSensor, LED
from signal import pause
from time import sleep
Device.pin_factory = MockFactory()
pir = MotionSensor(7)
led = LED(26)
def test_cb(channel):
print("Motion detected")
print(channel)
pir.when_motion = test_cb
# Mocking the device
pir_pin = Device.pin_factory.pin(7)
pir_pin.drive_high()
sleep(5)
pir_pin.drive_low()
That's weird. I tried it using slightly different code and it worked fine. But your version doesn't.
This example is working fine for me (Python 3.8 on Ubuntu) in IPython:
In [1]: from gpiozero.pins.mock import MockFactory
...: from gpiozero import Device, MotionSensor
...:
...: Device.pin_factory = MockFactory()
...:
...: pir = MotionSensor(7)
In [2]: def test_cb(channel):
...: print("Motion detected")
...: print(channel)
...:
In [3]: pir.when_motion = test_cb
In [4]: pir.value
Out[4]: 0
In [5]: pir.pin.drive_high()
Motion detected
<gpiozero.MotionSensor object on pin GPIO7, pull_up=False, is_active=True>
In [6]: pir.value
Out[6]: 1
In [7]: pir.pin.drive_low()
In [8]: pir.value
Out[8]: 0
The callback fires as soon as I run pin.drive_high().
The only difference really is me using pir.pin and you're using Device.pin_factory.pin(7).
Oddly:
In [3]: pir_pin == pir.pin
Out[3]: True
That's a head scratcher. @lurch any ideas? I'll ask @waveform80 if I get chance.
For me, even simpler code only works, if executed in the context of the REPL, but not as a standalone script.
from gpiozero.pins.mock import MockFactory
from gpiozero import Device, MotionSensor, LED
from signal import pause
Device.pin_factory = MockFactory()
pir = MotionSensor(7)
def test_cb(channel):
print(pir.motion_detected)
print("Motion detected")
print(channel)
pir.when_motion = test_cb
# Mocking the device
pir.pin.drive_high()
pause()
Hi,
I had the same problem this evening.
After some debugging I found out that my function might not getting triggered because of the sample_wait configuration (1/10[sec]) in MotionSensor constructor.
After putting a sleep with > sample_wait in my Test when configuring the callback or setting pin states it's working.
from time import sleep
from gpiozero import Device, MotionSensor
from gpiozero.pins.mock import MockFactory, MockPin
Device.pin_factory = MockFactory()
pin: MockPin = Device.pin_factory.pin(7)
pir = MotionSensor(7)
def test_cb(channel):
print(pir.motion_detected)
print("Motion detected")
print(channel)
"""
sleep calls in this test are necessary that motion sensor gets activated
this is due to gpiozero.input_devices.SmoothedInputDevice.__init__ and
the default sample wait time (1/10) configured in gpiozero/input_devices.py:612 (__init__)
"""
# default is 1/10, so to make sure wait twice as long
sample_wait_time_sec = (2/10)
pir.when_activated = test_cb
sleep(sample_wait_time_sec)
# Mocking the device
pin.drive_high()
sleep(sample_wait_time_sec)
print(pir.is_active)
print(pir.motion_detected)
Hi,
I had the same problem this evening.
After some debugging I found out that my function might not getting triggered because of thesample_waitconfiguration (1/10[sec]) inMotionSensorconstructor.After putting a
sleepwith >sample_waitin my Test when configuring the callback or setting pin states it's working.from time import sleep from gpiozero import Device, MotionSensor from gpiozero.pins.mock import MockFactory, MockPin Device.pin_factory = MockFactory() pin: MockPin = Device.pin_factory.pin(7) pir = MotionSensor(7) def test_cb(channel): print(pir.motion_detected) print("Motion detected") print(channel) """ sleep calls in this test are necessary that motion sensor gets activated this is due to gpiozero.input_devices.SmoothedInputDevice.__init__ and the default sample wait time (1/10) configured in gpiozero/input_devices.py:612 (__init__) """ # default is 1/10, so to make sure wait twice as long sample_wait_time_sec = (2/10) pir.when_activated = test_cb sleep(sample_wait_time_sec) # Mocking the device pin.drive_high() sleep(sample_wait_time_sec) print(pir.is_active) print(pir.motion_detected)
Hi @matt-hires, thx for the reply. I just tested your proposal and I can confirm your findings . 馃
Most helpful comment
Hi @matt-hires, thx for the reply. I just tested your proposal and I can confirm your findings . 馃