Skip to content

Commit

Permalink
Merge branch 'develop' into flake8-config-file
Browse files Browse the repository at this point in the history
  • Loading branch information
s-martin authored May 11, 2024
2 parents 9ae8d8c + f3b4b20 commit 9707cf6
Show file tree
Hide file tree
Showing 29 changed files with 421 additions and 398 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test_docker_debian_codename_sub.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ jobs:
uses: docker/[email protected]

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.2.0
uses: docker/setup-buildx-action@v3.3.0
with:
# network=host driver-opt needed to push to local registry
driver-opts: network=host
Expand Down Expand Up @@ -155,7 +155,7 @@ jobs:
uses: docker/[email protected]

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.2.0
uses: docker/setup-buildx-action@v3.3.0

- name: Artifact Download Docker Image
uses: actions/download-artifact@v4
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Check out the following references.
* [PN532](components/rfid-reader/PN532/README.md)
* PC/SC
* also [multiple readers](https://github.com/MiczFlor/RPi-Jukebox-RFID/pull/1012#issue-434052529) simultaneously
* [**GPIO** control](components/gpio_control/README.md) for [buttons](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Using-GPIO-hardware-buttons), [knobs / dials](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Audio-RotaryKnobVolume) and much more to control your Phoniebox via GPIO.
* [**GPIO** control](components/gpio_control/README.md) for [buttons](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Using-GPIO-hardware-buttons) and much more to control your Phoniebox via GPIO.
* Control via smooth [**Web App**](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#webapp) running on ajax from your phone, tablet or PC. You can play, upload, move files, assign new RFID cards, control playout, settings, etc.
* Support for files with embedded chapters metadata (like m4a)
* Customizable poweroff command
Expand Down
7 changes: 3 additions & 4 deletions components/audio/PirateAudioHAT/setup_pirateAudioHAT.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ source "${JUKEBOX_HOME_DIR}"/scripts/helperscripts/inc.systemHelper.sh

question() {
local question=$1
read -p "${question} (y/n)? " choice
read -p "${question} (Y/n)? " choice
case "$choice" in
y|Y ) ;;
n|N ) exit 0;;
* ) echo "Error: invalid" ; question ${question};;
[nN][oO]|[nN]) exit 0;;
* ) ;;
esac
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ BUTTONS_USB_ENCODER_DIR="${JUKEBOX_HOME_DIR}/components/controls/buttons_usb_enc

question() {
local question=$1
read -p "${question} (y/n)? " choice
read -p "${question} (Y/n)? " choice
case "$choice" in
y|Y ) ;;
n|N ) exit 0;;
* ) echo "Error: invalid" ; question ${question};;
[nN][oO]|[nN]) exit 0;;
* ) ;;
esac
}

Expand Down
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
91 changes: 74 additions & 17 deletions components/gpio_control/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,18 @@ Up to now the following input devices are implemented:
* **ShutdownButton**:
A specialized implementation for a shutdown button with integrated (but optional) LED support. It initializes a shutdown if the button is pressed more than `time_pressed` seconds and a (optional) LED on GPIO `led_pin` is flashing until that time is reached. For additional information, see [extended documentation below](#shutdownbutton).

* **RotaryEncoder**:
Control of a rotary encoder, for example KY040, see also in [Wiki](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Audio-RotaryKnobVolume).
It can be configured using `pinUp` and `PiNDown` (use GPIO numbers here), `functionCallUp`, `functionCallDown`, and `timeBase` see [extended documentation below](#rotaryencoder).

* **TwoButtonControl**:
This Device uses two Buttons and implements a third action if both buttons are pressed together. See [extended documentation below](#twobuttoncontrol).

* **RotaryEncoder**:
Control of a rotary encoder, for example KY040.
It can be configured using `Pin1` and `Pin2` (use GPIO numbers here), `functionCall1`, `functionCall2` see [extended documentation below](#rotaryencoder).

* **StatusLED**:
A LED which will light up once the Phoniebox has fully booted up and is ready to be used. For additional information, see [extended documentation below](#statusled).

Each section needs to be activated by setting `enabled: True`.

Many example files are located in `~/RPi-Jukebox-RFID/components/gpio_control/example_configs/`.

## Extended documentation

This section provides some extended documentation and guideline. Especially some exemplary configurations are introduced showing how these controls can be set up in the configuration file `~/RPi-Jukebox-RFID/settings/gpio_settings.ini`.
Expand All @@ -61,15 +59,18 @@ functionCall: functionCallPlayerPause
However, a button has more parameters than these. In the following comprehensive list you can also find the default values which are used automatically if you leave out these settings:

* **functionCallArgs**: Arguments for primary function, defaults to `None`. Arguments are ignored, if `functionCall` does not take any.

> [!IMPORTANT]
> Since v2.8.0 the behavior of `hold_mode` `SecondFunc` and `SecondFuncRepeat` has changed. The secondary function is no longer triggered additionally to the primary function.
> Now its called exclusively if `hold_time` is reached. The primary function will only be triggered if the button is pressed shorter then `hold_time`!
> Existing configurations may need to adapt to this.
* **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.

* **hold_time**: Reference time for this buttons `hold_mode` feature in seconds. Default is `0.3`. This setting is ignored if `hold_mode` is unset or `None`
Expand All @@ -81,10 +82,10 @@ However, a button has more parameters than these. In the following comprehensive
* `pull_off`. Use this to deactivate internal pull-up/pulldown resistors. This is useful if your wiring includes your own (external) pull up / down resistors.
* **edge**: Configures the events in which the GPIO library shall trigger the callback function. Valid settings:
* `falling` (Default). Triggers if the GPIO voltage goes down.
* `rising`. Trigegrs only if the GPIO voltage goes up.
* `rising`. Triggers only if the GPIO voltage goes up.
* `both`. Triggers in both cases.
* **bouncetime**: This is a setting of the GPIO library to limit bouncing effects during button usage. Default is `500` ms.
* **antibouncehack**: Despite the integrated bounce reduction of the GPIO library some users may notice false triggers of their buttons (e.g. unrequested / double actions when releasing the button). If you encounter such problems, try setting this setting to `True` to activate an additional countermeasure.
* **antibouncehack**: Despite the integrated bounce reduction of the GPIO library some users may notice false triggers of their buttons (e.g. unrequested / double actions when releasing the button). If you encounter such problems, try setting this to `True` to activate an additional countermeasure.

Note: If you prefer, you may also use `Type: SimpleButton` instead of `Type: Button` - this makes no difference.

Expand Down Expand Up @@ -172,19 +173,75 @@ Furthermore, the following settings can be used as described for the [regular bu
A RotaryEncoder can be created using an `ini` entry like this:

```bash
[VolumeControl]
[RotaryVolumeControl]
enabled: True
Type: RotaryEncoder
Pin1: 7
Pin2: 8
timeBase: 0.02
Pin1: 22
Pin2: 23
timeBase: 0.1
functionCall1: functionCallVolU
functionCall2: functionCallVolD
```

Pin1 and FunctionCall1 correspond to rotary direction "up", while Pin2 and FunctionCall2 correspond to "down".
* **enabled**: This needs to be `True` for the rotary encoder to work.
* **Pin1**: GPIO number corresponding to rotary direction "clockwise" ('CLK')
* **Pin2**: GPIO number corresponding to rotary direction "counter clockwise" ('DT')
* **functionCall1**: function called for every rotation step corresponding to rotary direction "clockwise". See below for passed arguments. See [function documentation below](#functions).
* **functionCall2**: function called for every rotation step corresponding to rotary direction "counter clockwise". See below for passed arguments. See [function documentation below](#functions).
* **timeBase**: Factor used for calculating the rotation value base on rotation speed, defaults to `0.1`. Use `0` for deactivating rotation speed influence.
Example:
* a single rotation step leads to the value 1 passed to the function.
* steady rotation of two to or more steps, leads to the value 1 for the first call and the value 2 for all further calls.
* speeding up rotation of two to or more steps, leads to the value 1 for the first call, the value 2 for the second, the value 3 for the third and so on.
* **functionCall1Args**: Arguments for `functionCall1`, defaults to `None`. If defined takes precedence over rotation value. Arguments are ignored, if `functionCall1` does not take any.
* **functionCall2Args**: Arguments for `functionCall2`, defaults to `None`. If defined takes precedence over rotation value. Arguments are ignored, if `functionCall1` does not take any.

To also use the push button of the encoder just a button definition:
```bash
[Mute]
enabled: True
Type: Button
Pin: 27
functionCall: functionCallVol0
```

Note that the old configuration entries PinUp/PinDown and functionCallUp/functionCallDown are deprecated and might stop working in future.


```bash
[RotarySeekingControl]
enabled: True
Type: RotaryEncoder
Pin1: 22
Pin2: 23
timeBase: 0.1
functionCall1: functionCallPlayerSeekFwd
functionCall1Args: 5
functionCall2: functionCallPlayerSeekBack
functionCall2Args: 5
```

In this example, the encoder will be used to seek for- and backwards by 5 seconds on every rotation step. The rotation value will **NOT** be used in this case as the function args are defined!


#### Circuit diagram
```text
.---------------. .---------------.
| | | |
| CLK |----------------------| GPIO 22 |
| | | |
| DT |----------------------| GPIO 23 |
| | | |
| SW |----------------------| GPIO 27 |
| | | |
| + |----------------------| 3.3V |
| | | |
| GND |----------------------| GND |
| | | |
'---------------' '---------------'
KY-040 Raspberry
```

### StatusLED

A StatusLED can be created using an `ini` entry like this:
Expand Down

This file was deleted.

18 changes: 15 additions & 3 deletions components/gpio_control/example_configs/gpio_settings.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,28 @@ antibouncehack: False

[VolumeControl]
enabled: False
Type: TwoButtonControl ;or RotaryEncoder
Type: TwoButtonControl
Pin1: 5
Pin2: 6
pull_up_down: pull_up
hold_time: 0.3
hold_mode: Repeat
timeBase: 0.1 ;only for RotaryEncoder
functionCall1: functionCallVolU
functionCall2: functionCallVolD
functionCallTwoButtons: functionCallVol0 ;only for TwoButtonControl
functionCallTwoButtons: functionCallVol0
;functionCall1Args: 1
;functionCall2Args: 1
;functionCallTwoButtonsArgs: x

[RotaryVolumeControl]
enabled: False
Type: RotaryEncoder
Pin1: 22
Pin2: 23
timeBase: 0.1
functionCall1: functionCallVolU
functionCall2: functionCallVolD

[PrevNextControl]
enabled: False
Type: TwoButtonControl
Expand Down Expand Up @@ -143,3 +151,7 @@ pull_up_down: pull_up
functionCall: functionCallTriggerPlayFolder
functionCallArgs: someRelativeFolderName

[StatusLED]
enabled: False
Type: StatusLED
Pin: 14

This file was deleted.

Loading

0 comments on commit 9707cf6

Please sign in to comment.