Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix button SecondFunc trigger #2367

Merged
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 23 additions & 18 deletions components/gpio_control/GPIODevices/simple_button.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,7 @@ def callbackFunctionHandler(self, *args):
if inval != GPIO.LOW:
return None

if self.hold_mode in ('Repeat', 'Postpone', 'SecondFunc', 'SecondFuncRepeat'):
return self.longPressHandler(*args)
else:
logger.info('{}: execute callback'.format(self.name))
return self.when_pressed(*args)
return self._handleCallbackFunction(*args)

@property
def when_pressed(self):
Expand All @@ -136,36 +132,45 @@ def when_pressed(self, func):
def set_callbackFunction(self, callbackFunction):
self.when_pressed = callbackFunction

def longPressHandler(self, *args):
logger.info('{}: longPressHandler, mode: {}'.format(self.name, self.hold_mode))
# instant action (except Postpone mode)
if self.hold_mode != "Postpone":
self.when_pressed(*args)
def _handleCallbackFunction(self, *args):
logger.info('{}: handleCallbackFunction, mode: {}'.format(self.name, self.hold_mode))

# action(s) after hold_time
if self.hold_mode == "Repeat":
# Repeated call of main action (multiple times if button is held long enough)
# Instantly call primary action
self.when_pressed(*args)
# Repeated call of primary action if button is held long enough
while checkGpioStaysInState(self.hold_time, self.pin, GPIO.LOW):
self.when_pressed(*args)

elif self.hold_mode == "Postpone":
# Postponed call of main action (once)
# Postponed call of primary action (once)
if checkGpioStaysInState(self.hold_time, self.pin, GPIO.LOW):
self.when_pressed(*args)
while checkGpioStaysInState(self.hold_time, self.pin, GPIO.LOW):
pass
while checkGpioStaysInState(self.hold_time, self.pin, GPIO.LOW):
pass

elif self.hold_mode == "SecondFunc":
# Call of secondary action (once)
# execute primary action if not held past hold_time
if checkGpioStaysInState(self.hold_time, self.pin, GPIO.LOW):
self.when_held(*args)
while checkGpioStaysInState(self.hold_time, self.pin, GPIO.LOW):
pass
while checkGpioStaysInState(self.hold_time, self.pin, GPIO.LOW):
pass
else:
self.when_pressed(*args)

elif self.hold_mode == "SecondFuncRepeat":
# Repeated call of secondary action (multiple times if button is held long enough)
while checkGpioStaysInState(self.hold_time, self.pin, GPIO.LOW):
# execute primary action if not held past hold_time
if checkGpioStaysInState(self.hold_time, self.pin, GPIO.LOW):
self.when_held(*args)
while checkGpioStaysInState(self.hold_time, self.pin, GPIO.LOW):
self.when_held(*args)
else:
self.when_pressed(*args)

else:
self.when_pressed(*args)

def __del__(self):
logger.debug('remove event detection')
Expand Down
5 changes: 2 additions & 3 deletions components/gpio_control/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,11 @@ However, a button has more parameters than these. In the following comprehensive
* **functionCallArgs**: Arguments for primary function, defaults to `None`. Arguments are ignored, if `functionCall` does not take any.
* **hold_mode**: Specifies what shall happen if the button is held pressed for longer than `hold_time`:
* `None` (Default): Nothing special will happen.
* `Repeat`: The configured `functionCall` is repeated after each `hold_time` interval.
* `Repeat`: The configured `functionCall` is instantly called and repeatedly after each `hold_time` interval.
* `Postpone`: The function will not be called before `hold_time`, i.e. the button needs to be pressed this long to activate the function
* `SecondFunc`: Holding the button for at least `hold_time` will additionally execute the function `functionCall2` with `functionCall2Args`.
* `SecondFunc`: Pressing the button (shorter than `hold_time`) will execute the function `functionCall` with `functionCallArgs`. Holding the button for at least `hold_time` will execute the function `functionCall2` with `functionCall2Args`.
* `SecondFuncRepeat`: Like SecondFunc, but `functionCall2` is repeated after each `hold_time` interval.

In every `hold_mode` except `Postpone`, the main action `functionCall` gets executed instantly.

Holding the button even longer than `hold_time` will cause no further action unless you are in the `Repeat` or `SecondFuncRepeat` mode.

Expand Down
4 changes: 2 additions & 2 deletions components/gpio_control/test/test_SimpleButton.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def test_hold_SecondFunc_longer_holdtime(self, simple_button):
simple_button.hold_mode = 'SecondFunc'
calls = mockedSecAction.call_count
simple_button.callbackFunctionHandler(simple_button.pin)
mockedAction.assert_called_once()
mockedAction.assert_not_called()
assert mockedSecAction.call_count - calls == 1

def test_hold_SecondFunc_shorter_holdtime(self, simple_button):
Expand All @@ -170,7 +170,7 @@ def test_hold_SecondFuncRepeat_longer_holdtime(self, simple_button):
simple_button.hold_mode = 'SecondFuncRepeat'
calls = mockedSecAction.call_count
simple_button.callbackFunctionHandler(simple_button.pin)
mockedAction.assert_called_once()
mockedAction.assert_not_called()
assert mockedSecAction.call_count - calls == 3

def test_hold_SecondFuncRepeat_shorter_holdtime(self, simple_button):
Expand Down