diff --git a/.github/workflows/test_docker_debian_codename_sub.yml b/.github/workflows/test_docker_debian_codename_sub.yml index 00ef4efd7..7aa1cd41e 100644 --- a/.github/workflows/test_docker_debian_codename_sub.yml +++ b/.github/workflows/test_docker_debian_codename_sub.yml @@ -58,7 +58,7 @@ jobs: uses: docker/setup-qemu-action@v3.0.0 - 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 @@ -155,7 +155,7 @@ jobs: uses: docker/setup-qemu-action@v3.0.0 - 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 diff --git a/README.md b/README.md index 3b2266d84..ebaada654 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/components/audio/PirateAudioHAT/setup_pirateAudioHAT.sh b/components/audio/PirateAudioHAT/setup_pirateAudioHAT.sh index 97c91194b..2fc977443 100755 --- a/components/audio/PirateAudioHAT/setup_pirateAudioHAT.sh +++ b/components/audio/PirateAudioHAT/setup_pirateAudioHAT.sh @@ -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 } diff --git a/components/controls/buttons_usb_encoder/setup-buttons-usb-encoder.sh b/components/controls/buttons_usb_encoder/setup-buttons-usb-encoder.sh index 95db0199c..0fa5fadc0 100755 --- a/components/controls/buttons_usb_encoder/setup-buttons-usb-encoder.sh +++ b/components/controls/buttons_usb_encoder/setup-buttons-usb-encoder.sh @@ -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 } diff --git a/components/gpio_control/GPIODevices/simple_button.py b/components/gpio_control/GPIODevices/simple_button.py index a022a812f..920358acf 100644 --- a/components/gpio_control/GPIODevices/simple_button.py +++ b/components/gpio_control/GPIODevices/simple_button.py @@ -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): @@ -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') diff --git a/components/gpio_control/README.md b/components/gpio_control/README.md index 8661e8d27..3b53d26d0 100644 --- a/components/gpio_control/README.md +++ b/components/gpio_control/README.md @@ -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`. @@ -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` @@ -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. @@ -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: diff --git a/components/gpio_control/example_configs/gpio_setting_rotary_vol_prevnext.ini b/components/gpio_control/example_configs/gpio_setting_rotary_vol_prevnext.ini deleted file mode 100755 index 3e829d55e..000000000 --- a/components/gpio_control/example_configs/gpio_setting_rotary_vol_prevnext.ini +++ /dev/null @@ -1,36 +0,0 @@ -[DEFAULT] -enabled: True - -[VolumeControl] -enabled: True -Type: RotaryEncoder -PinUp: 7 -PinDown: 8 -timeBase: 0.02 -functionCallDown: functionCallVolD -functionCallUp: functionCallVolU - -[PrevNextControl] -enabled: True -Type: RotaryEncoder -PinUp: 16 -PinDown: 20 -timeBase: 0.02 -functionCallDown: functionCallPlayerPrev -functionCallUp: functionCallPlayerNext - -[Shutdown] -enabled: True -Type: Button -Pin: 17 -pull_up_down: pull_down -edge: raising -functionCall: functionCallShutdown - -[PlayPause] -enabled: True -Type: Button -Pin: 25 -pull_up_down: pull_up -edge: falling -functionCall: functionCallPlayerPause diff --git a/components/gpio_control/example_configs/gpio_settings.ini b/components/gpio_control/example_configs/gpio_settings.ini index 4f84ba01b..a386d6ec6 100755 --- a/components/gpio_control/example_configs/gpio_settings.ini +++ b/components/gpio_control/example_configs/gpio_settings.ini @@ -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 @@ -143,3 +151,7 @@ pull_up_down: pull_up functionCall: functionCallTriggerPlayFolder functionCallArgs: someRelativeFolderName +[StatusLED] +enabled: False +Type: StatusLED +Pin: 14 diff --git a/components/gpio_control/example_configs/gpio_settings_rotary_and_led.ini b/components/gpio_control/example_configs/gpio_settings_rotary_and_led.ini deleted file mode 100644 index f636adbcf..000000000 --- a/components/gpio_control/example_configs/gpio_settings_rotary_and_led.ini +++ /dev/null @@ -1,49 +0,0 @@ -[DEFAULT] -enabled: True - -[VolumeControl] -enabled: True -Type: RotaryEncoder -PinUp: 17 -PinDown: 22 -pull_up_down: pull_up -timeBase: 0.2 -; only for rotary encoder -functionCallDown: functionCallVolD -functionCallUp: functionCallVolU -functionCallTwoButtons: functionCallStop -; only for TwoButtonControl -functionCallButton: functionCallPlayerPause -; only for RotaryEncoderClickable - -[PrevNextControl] -enabled: True -Type: TwoButtonControl -Pin1: 6 -Pin2: 12 -functionCall1: functionCallPlayerPrev -functionCall2: functionCallPlayerNext -functionCallTwoButtons: functionCallPlayerStop -pull_up_down: pull_up -hold_time: 0.3 -hold_mode: None - - -[Shutdown] -enabled: False -Type: Button -Pin: 3 -functionCall: functionCallShutdown - - -[PlayPause] -enabled: True -Type: Button -Pin: 27 -pull_up_down: pull_up -functionCall: functionCallPlayerPause - -[StatusLED] -enabled: True -Type: MPDStatusLED -Pin: 16 diff --git a/components/gpio_control/example_configs/gpio_settings_status_led.ini b/components/gpio_control/example_configs/gpio_settings_status_led.ini deleted file mode 100644 index 68e6461b2..000000000 --- a/components/gpio_control/example_configs/gpio_settings_status_led.ini +++ /dev/null @@ -1,7 +0,0 @@ -[DEFAULT] -enabled: True - -[StatusLED] -enabled: True -Type: StatusLED -Pin: 14 diff --git a/components/gpio_control/function_calls.py b/components/gpio_control/function_calls.py index 4151f9581..9978a7695 100644 --- a/components/gpio_control/function_calls.py +++ b/components/gpio_control/function_calls.py @@ -18,7 +18,7 @@ def __init__(self): def functionCallShutdown(self, *args): function_call("{command} -c=shutdown".format(command=self.playout_control), shell=True) - def functionCallVolU(self, steps=None): + def functionCallVolU(self, steps=None, *args): if steps is None: function_call("{command} -c=volumeup".format(command=self.playout_control), shell=True) else: @@ -26,7 +26,7 @@ def functionCallVolU(self, steps=None): command=self.playout_control), shell=True) - def functionCallVolD(self, steps=None): + def functionCallVolD(self, steps=None, *args): if steps is None: function_call("{command} -c=volumedown".format(command=self.playout_control), shell=True) else: @@ -65,22 +65,22 @@ def functionCallPlayerStop(self, *args): function_call("{command} -c=playerstop".format(command=self.playout_control), shell=True) - def functionCallPlayerSeekFwd(self, seconds=None): + def functionCallPlayerSeekFwd(self, seconds=None, *args): if seconds is None: seconds = 10 function_call("{command} -c=playerseek -v=+{value}".format(command=self.playout_control, value=seconds), shell=True) - def functionCallPlayerSeekBack(self, seconds=None): + def functionCallPlayerSeekBack(self, seconds=None, *args): if seconds is None: seconds = 10 function_call("{command} -c=playerseek -v=-{value}".format(command=self.playout_control, value=seconds), shell=True) - def functionCallPlayerSeekFarFwd(self, seconds=None): + def functionCallPlayerSeekFarFwd(self, seconds=None, *args): if seconds is None: seconds = 60 function_call("{command} -c=playerseek -v=+{value}".format(command=self.playout_control, value=seconds), shell=True) - def functionCallPlayerSeekFarBack(self, seconds=None): + def functionCallPlayerSeekFarBack(self, seconds=None, *args): if seconds is None: seconds = 60 function_call("{command} -c=playerseek -v=-{value}".format(command=self.playout_control, value=seconds), shell=True) @@ -94,15 +94,15 @@ def functionCallPlayerRandomCard(self, *args): def functionCallPlayerRandomFolder(self, *args): function_call("{command} -c=randomfolder".format(command=self.playout_control), shell=True) - def functionCallBluetoothToggle(self, mode=None): + def functionCallBluetoothToggle(self, mode=None, *args): if mode is None: mode = 'toggle' function_call("{command} -c=bluetoothtoggle -v={value}".format(command=self.playout_control, value=mode), shell=True) - def functionCallTriggerPlayCardId(self, cardid): + def functionCallTriggerPlayCardId(self, cardid, *args): function_call("{command} --cardid={value}".format(command=self.rfid_trigger, value=cardid), shell=True) - def functionCallTriggerPlayFolder(self, folder): + def functionCallTriggerPlayFolder(self, folder, *args): function_call("{command} --dir={value}".format(command=self.rfid_trigger, value=folder), shell=True) def getFunctionCall(self, functionName): diff --git a/components/gpio_control/gpio_control.py b/components/gpio_control/gpio_control.py index 45977b89b..3e91df31b 100755 --- a/components/gpio_control/gpio_control.py +++ b/components/gpio_control/gpio_control.py @@ -32,7 +32,10 @@ def getFunctionCall(self, function_name, function_args): try: if function_name is not None and function_name != 'None': functionCall = getattr(self.function_calls, function_name) - return (lambda *args: functionCall(*args, function_args)) + if function_args is not None and function_args != 'None': + return (lambda *args: functionCall(function_args, *args)) + else: + return (lambda *args: functionCall(*args)) except AttributeError: self.logger.error('Could not find FunctionCall {function_name}'.format(function_name=function_name)) return lambda *args: None @@ -77,8 +80,8 @@ def generate_device(self, config, deviceName): elif device_type == 'RotaryEncoder': return RotaryEncoder(config.getint('Pin1'), config.getint('Pin2'), - self.getFunctionCall(config.get('functionCall1'), None), - self.getFunctionCall(config.get('functionCall2'), None), + self.getFunctionCall(config.get('functionCall1'), config.get('functionCall1Args', fallback=None)), + self.getFunctionCall(config.get('functionCall2'), config.get('functionCall2Args', fallback=None)), config.getfloat('timeBase', fallback=0.1), name=deviceName) elif device_type == 'ShutdownButton': diff --git a/components/gpio_control/test/test_SimpleButton.py b/components/gpio_control/test/test_SimpleButton.py index d6f03acd3..b0b933e09 100644 --- a/components/gpio_control/test/test_SimpleButton.py +++ b/components/gpio_control/test/test_SimpleButton.py @@ -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): @@ -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): diff --git a/components/gpio_control/test/test_gpio_control.py b/components/gpio_control/test/test_gpio_control.py index 4c139b67e..26d6885fa 100644 --- a/components/gpio_control/test/test_gpio_control.py +++ b/components/gpio_control/test/test_gpio_control.py @@ -16,11 +16,11 @@ def gpio_control_class(): class MockFunctionCalls: - def funcTestWithoutParameter(self, *args): - return "funcTestWithoutParameter" + def funcTestWithoutParameter(*args): + return "funcTestWithoutParameter()" - def funcTestWithParameter(self, param1): - return f"funcTestWithParameter({param1})" + def funcTestWithParameter(param1, *args): + return f"funcTestWithParameter({str(param1)})" _gpio_control_class = GPIOControl(MockFunctionCalls) # function_calls will be mocked return _gpio_control_class @@ -226,19 +226,44 @@ def test_generateDevice_TwoButtonControl(self, gpio_control_class): def test_getFunctionCall_None_None(self, gpio_control_class): result = gpio_control_class.getFunctionCall(None, None) - assert result(()) is None + assert result() is None result = gpio_control_class.getFunctionCall('None', None) - assert result(()) is None + assert result() is None result = gpio_control_class.getFunctionCall("nonExisting", None) - assert result(()) is None + assert result() is None - def test_getFunctionCall_withoutParam(self, gpio_control_class): + def test_getFunctionCall_funcWithoutArgs(self, gpio_control_class): result = gpio_control_class.getFunctionCall("funcTestWithoutParameter", None) - assert result(()) == "funcTestWithoutParameter" + assert result() == "funcTestWithoutParameter()" - def test_getFunctionCall_withParam(self, gpio_control_class): - result = gpio_control_class.getFunctionCall("funcTestWithParameter", "param1") - assert result(()) == "funcTestWithParameter(param1)" + def test_getFunctionCall_funcWithoutArgs_withParam(self, gpio_control_class): + result = gpio_control_class.getFunctionCall("funcTestWithoutParameter", None) + assert result("param") == "funcTestWithoutParameter()" + + def test_getFunctionCall_funcWithoutArgs_withFuncArgs(self, gpio_control_class): + result = gpio_control_class.getFunctionCall("funcTestWithoutParameter", "funcArgs") + assert result() == "funcTestWithoutParameter()" + + def test_getFunctionCallfuncWithoutArgs_withFuncArgsAndParam(self, gpio_control_class): + result = gpio_control_class.getFunctionCall("funcTestWithoutParameter", "funcArgs") + assert result("param") == "funcTestWithoutParameter()" + + def test_getFunctionCall_funcWithArgs_withoutFuncArgsAndParam(self, gpio_control_class): + result = gpio_control_class.getFunctionCall("funcTestWithParameter", None) + with pytest.raises(TypeError): + result() + + def test_getFunctionCall_funcWithArgs_withParam(self, gpio_control_class): + result = gpio_control_class.getFunctionCall("funcTestWithParameter", None) + assert result("param") == "funcTestWithParameter(param)" + + def test_getFunctionCall_funcWithArgs_withFuncArgs(self, gpio_control_class): + result = gpio_control_class.getFunctionCall("funcTestWithParameter", "funcArgs") + assert result() == "funcTestWithParameter(funcArgs)" + + def test_getFunctionCall_funcWithArgs_withFuncArgsAndParam(self, gpio_control_class): + result = gpio_control_class.getFunctionCall("funcTestWithParameter", "funcArgs") + assert result("param") == "funcTestWithParameter(funcArgs)" # --------------- diff --git a/components/rfid-reader/PN532/setup_pn532.sh b/components/rfid-reader/PN532/setup_pn532.sh index 3b9ab1252..8f2e97bbb 100755 --- a/components/rfid-reader/PN532/setup_pn532.sh +++ b/components/rfid-reader/PN532/setup_pn532.sh @@ -5,11 +5,10 @@ JUKEBOX_HOME_DIR="${HOME_DIR}/RPi-Jukebox-RFID" 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 } diff --git a/components/rfid-reader/RC522/setup_rc522.sh b/components/rfid-reader/RC522/setup_rc522.sh index 43ab60fa6..b6333767b 100644 --- a/components/rfid-reader/RC522/setup_rc522.sh +++ b/components/rfid-reader/RC522/setup_rc522.sh @@ -5,11 +5,10 @@ JUKEBOX_HOME_DIR="${HOME_DIR}/RPi-Jukebox-RFID" 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 } diff --git a/misc/sampleconfigs/gpio_settings.ini.sample b/misc/sampleconfigs/gpio_settings.ini.sample index 4f84ba01b..a386d6ec6 100644 --- a/misc/sampleconfigs/gpio_settings.ini.sample +++ b/misc/sampleconfigs/gpio_settings.ini.sample @@ -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 @@ -143,3 +151,7 @@ pull_up_down: pull_up functionCall: functionCallTriggerPlayFolder functionCallArgs: someRelativeFolderName +[StatusLED] +enabled: False +Type: StatusLED +Pin: 14 diff --git a/scripts/RegisterDevice.py.Multi b/scripts/RegisterDevice.py.Multi index 66dc16898..008121496 100644 --- a/scripts/RegisterDevice.py.Multi +++ b/scripts/RegisterDevice.py.Multi @@ -17,7 +17,7 @@ def runCmd(cmd, wait=True): def setupPN532(): answer = input('Please make sure that the PN532 reader is wired up correctly ' 'to the GPIO ports before continuing...\n Continue?: [Y/n]') - if not answer or answer[0] != 'Y': + if answer and answer[0].lower() == 'n': return False print("Activating I2C interface...\n") runCmd("sudo raspi-config nonint do_i2c 0") @@ -41,7 +41,7 @@ def setupPN532(): def setupMFRC522(): answer = input('Please make sure that the RC522 reader is wired up correctly ' 'to the GPIO ports before continuing...\n Continue?: [Y/n]') - if not answer or answer[0] != 'Y': + if answer and answer[0].lower() == 'n': return False print("Installing Python requirements for RC522...\n") runCmd("sudo python3 -m pip install --upgrade --force-reinstall " @@ -78,7 +78,7 @@ def configureDevices(): addDevice() while True: answer = input('Do you want to add another device: [Y/n]') - if not answer or answer[0] != 'Y': + if answer and answer[0].lower() == 'n': break addDevice() diff --git a/scripts/helperscripts/inc.helper.sh b/scripts/helperscripts/inc.helper.sh new file mode 100644 index 000000000..04cac78c8 --- /dev/null +++ b/scripts/helperscripts/inc.helper.sh @@ -0,0 +1,17 @@ +# Reads a textfile and pipes all lines as args to the given command. +# Does filter out comments. +# Arguments: +# 1 : textfile to read +# 2... : command to receive args (e.g. 'echo', 'apt-get -y install', ...) +call_with_args_from_file () { + local package_file="$1" + shift + + sed 's|#.*||g' ${package_file} | xargs "$@" +} + +# escape relevant chars for strings used in 'sed' commands. implies delimiter char '|' +escape_for_sed() { + local escaped=$(echo "$1" | sed -e 's/[\&'\''|]/\\&/g') + echo "$escaped" +} diff --git a/scripts/helperscripts/inc.networkHelper.sh b/scripts/helperscripts/inc.networkHelper.sh index ff0df181e..f96a9138d 100644 --- a/scripts/helperscripts/inc.networkHelper.sh +++ b/scripts/helperscripts/inc.networkHelper.sh @@ -74,7 +74,7 @@ add_wireless_network() { local wpa_network_with_dummy_psk=$(wpa_passphrase "$ssid" "dummypsk") if echo "$wpa_network_with_dummy_psk" | grep -qF 'network='; then local wpa_network=$(echo "$wpa_network_with_dummy_psk" | sed -e '/#psk/d' -e "s/psk=.*$/psk=${pass}/" -e "/^}/i\\\tpriority=${prio}" ) - sudo bash -c "echo '${wpa_network}' >> $WPA_CONF" + echo "${wpa_network}" | sudo tee -a "$WPA_CONF" > /dev/null fi fi fi diff --git a/scripts/helperscripts/setup_autohotspot.sh b/scripts/helperscripts/setup_autohotspot.sh index 2ae9cd361..61d0e2297 100644 --- a/scripts/helperscripts/setup_autohotspot.sh +++ b/scripts/helperscripts/setup_autohotspot.sh @@ -14,18 +14,6 @@ if [[ "$#" -lt 2 || ( "${AUTOHOTSPOTconfig}" != "NO" && "${AUTOHOTSPOTconfig}" ! exit 1 fi -# Reads a textfile and pipes all lines as args to the given command. -# Does filter out comments. -# Arguments: -# 1 : textfile to read -# 2... : command to receive args (e.g. 'echo', 'apt-get -y install', ...) -call_with_args_from_file () { - local package_file="$1" - shift - - sed 's/#.*//g' ${package_file} | xargs "$@" -} - _get_last_ip_segment() { local ip="$1" echo $ip | cut -d'.' -f1-3 @@ -80,6 +68,7 @@ wifi_interface=wlan0 ip_without_last_segment=$(_get_last_ip_segment $AUTOHOTSPOTip) autohotspot_profile="Phoniebox_Hotspot" +source "${JUKEBOX_HOME_DIR}"/scripts/helperscripts/inc.helper.sh source "${JUKEBOX_HOME_DIR}"/scripts/helperscripts/inc.networkHelper.sh _install_autohotspot_dhcpcd() { @@ -103,8 +92,8 @@ _install_autohotspot_dhcpcd() { config_file_backup "${dnsmasq_conf}" sudo cp "${JUKEBOX_HOME_DIR}"/misc/sampleconfigs/autohotspot/dhcpcd/dnsmasq.conf "${dnsmasq_conf}" - sudo sed -i "s|%WIFI_INTERFACE%|${wifi_interface}|g" "${dnsmasq_conf}" - sudo sed -i "s|%IP_WITHOUT_LAST_SEGMENT%|${ip_without_last_segment}|g" "${dnsmasq_conf}" + sudo sed -i "s|%WIFI_INTERFACE%|$(escape_for_sed "${wifi_interface}")|g" "${dnsmasq_conf}" + sudo sed -i "s|%IP_WITHOUT_LAST_SEGMENT%|$(escape_for_sed "${ip_without_last_segment}")|g" "${dnsmasq_conf}" sudo chown root:root "${dnsmasq_conf}" sudo chmod 644 "${dnsmasq_conf}" @@ -112,10 +101,10 @@ _install_autohotspot_dhcpcd() { config_file_backup "${hostapd_conf}" sudo cp "${JUKEBOX_HOME_DIR}"/misc/sampleconfigs/autohotspot/dhcpcd/hostapd.conf "${hostapd_conf}" - sudo sed -i "s|%WIFI_INTERFACE%|${wifi_interface}|g" "${hostapd_conf}" - sudo sed -i "s|%AUTOHOTSPOTssid%|${AUTOHOTSPOTssid}|g" "${hostapd_conf}" - sudo sed -i "s|%AUTOHOTSPOTpass%|${AUTOHOTSPOTpass}|g" "${hostapd_conf}" - sudo sed -i "s|%AUTOHOTSPOTcountryCode%|${AUTOHOTSPOTcountryCode}|g" "${hostapd_conf}" + sudo sed -i "s|%WIFI_INTERFACE%|$(escape_for_sed "${wifi_interface}")|g" "${hostapd_conf}" + sudo sed -i "s|%AUTOHOTSPOTssid%|$(escape_for_sed "${AUTOHOTSPOTssid}")|g" "${hostapd_conf}" + sudo sed -i "s|%AUTOHOTSPOTpass%|$(escape_for_sed "${AUTOHOTSPOTpass}")|g" "${hostapd_conf}" + sudo sed -i "s|%AUTOHOTSPOTcountryCode%|$(escape_for_sed "${AUTOHOTSPOTcountryCode}")|g" "${hostapd_conf}" sudo chown root:root "${hostapd_conf}" sudo chmod 644 "${hostapd_conf}" @@ -123,7 +112,7 @@ _install_autohotspot_dhcpcd() { config_file_backup "${hostapd_deamon}" sudo cp "${JUKEBOX_HOME_DIR}"/misc/sampleconfigs/autohotspot/dhcpcd/hostapd "${hostapd_deamon}" - sudo sed -i "s|%HOSTAPD_CONF%|${hostapd_conf}|g" "${hostapd_deamon}" + sudo sed -i "s|%HOSTAPD_CONF%|$(escape_for_sed "${hostapd_conf}")|g" "${hostapd_deamon}" sudo chown root:root "${hostapd_deamon}" sudo chmod 644 "${hostapd_deamon}" @@ -136,28 +125,28 @@ _install_autohotspot_dhcpcd() { fi if [[ ! $(grep -w "${dhcpcd_conf_nohook_wpa_supplicant}" ${dhcpcd_conf}) ]]; then - sudo bash -c "echo ${dhcpcd_conf_nohook_wpa_supplicant} >> ${dhcpcd_conf}" + echo "${dhcpcd_conf_nohook_wpa_supplicant}" | sudo tee -a "${dhcpcd_conf}" > /dev/null fi # create service to trigger hotspot sudo cp "${JUKEBOX_HOME_DIR}"/misc/sampleconfigs/autohotspot/dhcpcd/autohotspot "${autohotspot_script}" - sudo sed -i "s|%WIFI_INTERFACE%|${wifi_interface}|g" "${autohotspot_script}" - sudo sed -i "s|%AUTOHOTSPOT_IP%|${AUTOHOTSPOTip}|g" "${autohotspot_script}" - sudo sed -i "s|%AUTOHOTSPOT_SERVICE_DAEMON%|${autohotspot_service_daemon}|g" "${autohotspot_script}" + sudo sed -i "s|%WIFI_INTERFACE%|$(escape_for_sed "${wifi_interface}")|g" "${autohotspot_script}" + sudo sed -i "s|%AUTOHOTSPOT_IP%|$(escape_for_sed "${AUTOHOTSPOTip}")|g" "${autohotspot_script}" + sudo sed -i "s|%AUTOHOTSPOT_SERVICE_DAEMON%|$(escape_for_sed "${autohotspot_service_daemon}")|g" "${autohotspot_script}" sudo chmod +x "${autohotspot_script}" sudo cp "${JUKEBOX_HOME_DIR}"/misc/sampleconfigs/autohotspot/dhcpcd/autohotspot-daemon.service "${autohotspot_service_daemon_path}" - sudo sed -i "s|%WIFI_INTERFACE%|${wifi_interface}|g" "${autohotspot_service_daemon_path}" + sudo sed -i "s|%WIFI_INTERFACE%|$(escape_for_sed "${wifi_interface}")|g" "${autohotspot_service_daemon_path}" sudo chown root:root "${autohotspot_service_daemon_path}" sudo chmod 644 "${autohotspot_service_daemon_path}" sudo cp "${JUKEBOX_HOME_DIR}"/misc/sampleconfigs/autohotspot/dhcpcd/autohotspot.service "${autohotspot_service_path}" - sudo sed -i "s|%AUTOHOTSPOT_SCRIPT%|${autohotspot_script}|g" "${autohotspot_service_path}" + sudo sed -i "s|%AUTOHOTSPOT_SCRIPT%|$(escape_for_sed "${autohotspot_script}")|g" "${autohotspot_service_path}" sudo chown root:root "${autohotspot_service_path}" sudo chmod 644 "${autohotspot_service_path}" sudo cp "${JUKEBOX_HOME_DIR}"/misc/sampleconfigs/autohotspot/dhcpcd/autohotspot.timer "${autohotspot_timer_path}" - sudo sed -i "s|%AUTOHOTSPOT_SERVICE%|${autohotspot_service}|g" "${autohotspot_timer_path}" + sudo sed -i "s|%AUTOHOTSPOT_SERVICE%|$(escape_for_sed "${autohotspot_service}")|g" "${autohotspot_timer_path}" sudo chown root:root "${autohotspot_timer_path}" sudo chmod 644 "${autohotspot_timer_path}" @@ -212,22 +201,22 @@ _install_autohotspot_NetworkManager() { # create service to trigger hotspot sudo cp "${JUKEBOX_HOME_DIR}"/misc/sampleconfigs/autohotspot/NetworkManager/autohotspot "${autohotspot_script}" - sudo sed -i "s|%WIFI_INTERFACE%|${wifi_interface}|g" "${autohotspot_script}" - sudo sed -i "s|%AUTOHOTSPOT_PROFILE%|${autohotspot_profile}|g" "${autohotspot_script}" - sudo sed -i "s|%AUTOHOTSPOT_SSID%|${AUTOHOTSPOTssid}|g" "${autohotspot_script}" - sudo sed -i "s|%AUTOHOTSPOT_PASSWORD%|${AUTOHOTSPOTpass}|g" "${autohotspot_script}" - sudo sed -i "s|%AUTOHOTSPOT_IP%|${AUTOHOTSPOTip}|g" "${autohotspot_script}" - sudo sed -i "s|%IP_WITHOUT_LAST_SEGMENT%|${ip_without_last_segment}|g" "${autohotspot_script}" - sudo sed -i "s|%AUTOHOTSPOT_TIMER_NAME%|${autohotspot_timer}|g" "${autohotspot_script}" + sudo sed -i "s|%WIFI_INTERFACE%|$(escape_for_sed "${wifi_interface}")|g" "${autohotspot_script}" + sudo sed -i "s|%AUTOHOTSPOT_PROFILE%|$(escape_for_sed "${autohotspot_profile}")|g" "${autohotspot_script}" + sudo sed -i "s|%AUTOHOTSPOT_SSID%|$(escape_for_sed "${AUTOHOTSPOTssid}")|g" "${autohotspot_script}" + sudo sed -i "s|%AUTOHOTSPOT_PASSWORD%|$(escape_for_sed "${AUTOHOTSPOTpass}")|g" "${autohotspot_script}" + sudo sed -i "s|%AUTOHOTSPOT_IP%|$(escape_for_sed "${AUTOHOTSPOTip}")|g" "${autohotspot_script}" + sudo sed -i "s|%IP_WITHOUT_LAST_SEGMENT%|$(escape_for_sed "${ip_without_last_segment}")|g" "${autohotspot_script}" + sudo sed -i "s|%AUTOHOTSPOT_TIMER_NAME%|$(escape_for_sed "${autohotspot_timer}")|g" "${autohotspot_script}" sudo chmod +x "${autohotspot_script}" sudo cp "${JUKEBOX_HOME_DIR}"/misc/sampleconfigs/autohotspot/NetworkManager/autohotspot.service "${autohotspot_service_path}" - sudo sed -i "s|%AUTOHOTSPOT_SCRIPT%|${autohotspot_script}|g" "${autohotspot_service_path}" + sudo sed -i "s|%AUTOHOTSPOT_SCRIPT%|$(escape_for_sed "${autohotspot_script}")|g" "${autohotspot_service_path}" sudo chown root:root "${autohotspot_service_path}" sudo chmod 644 "${autohotspot_service_path}" sudo cp "${JUKEBOX_HOME_DIR}"/misc/sampleconfigs/autohotspot/NetworkManager/autohotspot.timer "${autohotspot_timer_path}" - sudo sed -i "s|%AUTOHOTSPOT_SERVICE%|${autohotspot_service}|g" "${autohotspot_timer_path}" + sudo sed -i "s|%AUTOHOTSPOT_SERVICE%|$(escape_for_sed "${autohotspot_service}")|g" "${autohotspot_timer_path}" sudo chown root:root "${autohotspot_timer_path}" sudo chmod 644 "${autohotspot_timer_path}" diff --git a/scripts/installscripts/install-jukebox.sh b/scripts/installscripts/install-jukebox.sh index 6faf90cfd..9025afeba 100644 --- a/scripts/installscripts/install-jukebox.sh +++ b/scripts/installscripts/install-jukebox.sh @@ -19,8 +19,6 @@ PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" GIT_BRANCH=${GIT_BRANCH:-master} GIT_URL=${GIT_URL:-https://github.com/MiczFlor/RPi-Jukebox-RFID.git} -echo GIT_BRANCH $GIT_BRANCH -echo GIT_URL $GIT_URL DATETIME=$(date +"%Y%m%d_%H%M%S") @@ -29,8 +27,7 @@ JOB="${SCRIPTNAME}" CURRENT_USER="${SUDO_USER:-$(whoami)}" HOME_DIR=$(getent passwd "$CURRENT_USER" | cut -d: -f6) -echo "Current User: $CURRENT_USER" -echo "User home dir: $HOME_DIR" + JUKEBOX_HOME_DIR="${HOME_DIR}/RPi-Jukebox-RFID" LOGDIR="${HOME_DIR}"/phoniebox_logs @@ -38,7 +35,6 @@ JUKEBOX_BACKUP_DIR="${HOME_DIR}/BACKUP" # Get the Raspberry Pi OS codename (e.g. buster, bullseye, ...) OS_CODENAME="$( . /etc/os-release; printf '%s\n' "$VERSION_CODENAME"; )" -printf "Used Raspberry Pi OS: ${OS_CODENAME}\n" WIFI_INTERFACE="wlan0" @@ -94,18 +90,14 @@ log_close() { fi } -escape_for_shell() { +# local function as it is needed before the repo is checked out! +_escape_for_shell() { local escaped="${1//\"/\\\"}" escaped="${escaped//\`/\\\`}" escaped="${escaped//\$/\\\$}" echo "$escaped" } -escape_for_sed() { - local escaped=$(echo "$1" | sed -e 's/[\/&'\'']/\\&/g') - echo "$escaped" -} - checkPrerequisite() { #currently the user 'pi' is mandatory #https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/1785 @@ -227,12 +219,12 @@ case "$response" in *) # append variables to config file { - echo "WIFIconfig=\"$WIFIconfig\""; - echo "WIFIcountryCode=\"$WIFIcountryCode\""; - echo "WIFIssid=\"$WIFIssid\""; - echo "WIFIpass=\"$WIFIpass\""; - echo "WIFIip=\"$WIFIip\""; - echo "WIFIipRouter=\"$WIFIipRouter\""; + echo "WIFIconfig=\"$(_escape_for_shell "$WIFIconfig")\""; + echo "WIFIcountryCode=\"$(_escape_for_shell "$WIFIcountryCode")\""; + echo "WIFIssid=\"$(_escape_for_shell "$WIFIssid")\""; + echo "WIFIpass=\"$(_escape_for_shell "$WIFIpass")\""; + echo "WIFIip=\"$(_escape_for_shell "$WIFIip")\""; + echo "WIFIipRouter=\"$(_escape_for_shell "$WIFIipRouter")\""; } >> "${HOME_DIR}/PhonieboxInstall.conf" ;; esac @@ -241,9 +233,9 @@ case "$response" in WIFIconfig=NO echo "You want to configure WiFi later." # append variables to config file - echo "WIFIconfig=$WIFIconfig" >> "${HOME_DIR}/PhonieboxInstall.conf" + echo "WIFIconfig=\"$(_escape_for_shell "$WIFIconfig")\"" >> "${HOME_DIR}/PhonieboxInstall.conf" # make a fallback for WiFi Country Code, because we need that even without WiFi config - echo "WIFIcountryCode=DE" >> "${HOME_DIR}/PhonieboxInstall.conf" + echo "WIFIcountryCode=\"$(_escape_for_shell "DE")\"" >> "${HOME_DIR}/PhonieboxInstall.conf" ;; esac read -rp "Hit ENTER to proceed to the next step." INPUT @@ -315,18 +307,18 @@ case "$response" in esac # append variables to config file { - echo "AUTOHOTSPOTconfig=\"$AUTOHOTSPOTconfig\""; - echo "AUTOHOTSPOTssid=\"$AUTOHOTSPOTssid\""; - echo "AUTOHOTSPOTcountryCode=\"$AUTOHOTSPOTcountryCode\""; - echo "AUTOHOTSPOTpass=\"$AUTOHOTSPOTpass\""; - echo "AUTOHOTSPOTip=\"$AUTOHOTSPOTip\""; + echo "AUTOHOTSPOTconfig=\"$(_escape_for_shell "$AUTOHOTSPOTconfig")\""; + echo "AUTOHOTSPOTssid=\"$(_escape_for_shell "$AUTOHOTSPOTssid")\""; + echo "AUTOHOTSPOTcountryCode=\"$(_escape_for_shell "$AUTOHOTSPOTcountryCode")\""; + echo "AUTOHOTSPOTpass=\"$(_escape_for_shell "$AUTOHOTSPOTpass")\""; + echo "AUTOHOTSPOTip=\"$(_escape_for_shell "$AUTOHOTSPOTip")\""; } >> "${HOME_DIR}/PhonieboxInstall.conf" ;; *) AUTOHOTSPOTconfig=NO echo "You don't want to configure Autohotspot." # append variables to config file - echo "AUTOHOTSPOTconfig=$AUTOHOTSPOTconfig" >> "${HOME_DIR}/PhonieboxInstall.conf" + echo "AUTOHOTSPOTconfig=\"$(_escape_for_shell "$AUTOHOTSPOTconfig")\"" >> "${HOME_DIR}/PhonieboxInstall.conf" ;; esac @@ -442,7 +434,7 @@ check_existing() { ;; esac # append variables to config file - echo "EXISTINGuseRfidConf=$EXISTINGuseRfidConf" >> "${local_home_dir}/PhonieboxInstall.conf" + echo "EXISTINGuseRfidConf=\"$(_escape_for_shell "$EXISTINGuseRfidConf")\"" >> "${local_home_dir}/PhonieboxInstall.conf" read -rp "RFID shortcuts to play audio folders? [Y/n] " response case "$response" in @@ -454,7 +446,7 @@ check_existing() { ;; esac # append variables to config file - echo "EXISTINGuseRfidLinks=$EXISTINGuseRfidLinks" >> "${local_home_dir}/PhonieboxInstall.conf" + echo "EXISTINGuseRfidLinks=\"$(_escape_for_shell "$EXISTINGuseRfidLinks")\"" >> "${local_home_dir}/PhonieboxInstall.conf" read -rp "Audio folders: use existing? [Y/n] " response case "$response" in @@ -466,7 +458,7 @@ check_existing() { ;; esac # append variables to config file - echo "EXISTINGuseAudio=$EXISTINGuseAudio" >> "${local_home_dir}/PhonieboxInstall.conf" + echo "EXISTINGuseAudio=\"$(_escape_for_shell "$EXISTINGuseAudio")\"" >> "${local_home_dir}/PhonieboxInstall.conf" read -rp "Sound effects: use existing startup / shutdown sounds? [Y/n] " response case "$response" in @@ -478,7 +470,7 @@ check_existing() { ;; esac # append variables to config file - echo "EXISTINGuseSounds=$EXISTINGuseSounds" >> "${local_home_dir}/PhonieboxInstall.conf" + echo "EXISTINGuseSounds=\"$(_escape_for_shell "$EXISTINGuseSounds")\"" >> "${local_home_dir}/PhonieboxInstall.conf" if [ "$(printf '%s\n' "2.1" "$(cat ${local_home_dir}/BACKUP/settings/version-number)" | sort -V | head -n1)" = "2.1" ]; then read -rp "GPIO: use existing file? [Y/n] " response @@ -500,7 +492,7 @@ https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Using-GPIO-hardware-buttons" config_gpio fi # append variables to config file - echo "EXISTINGuseGpio=$EXISTINGuseGpio" >> "${local_home_dir}/PhonieboxInstall.conf" + echo "EXISTINGuseGpio=\"$(_escape_for_shell "$EXISTINGuseGpio")\"" >> "${local_home_dir}/PhonieboxInstall.conf" read -rp "Button USB Encoder: use existing device and button mapping? [Y/n] " response case "$response" in @@ -512,7 +504,7 @@ https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Using-GPIO-hardware-buttons" ;; esac # append variables to config file - echo "EXISTINGuseButtonUSBEncoder=$EXISTINGuseButtonUSBEncoder" >> "${local_home_dir}/PhonieboxInstall.conf" + echo "EXISTINGuseButtonUSBEncoder=\"$(_escape_for_shell "$EXISTINGuseButtonUSBEncoder")\"" >> "${local_home_dir}/PhonieboxInstall.conf" echo "Thanks. Got it." echo "The existing install can be found in the BACKUP directory." @@ -521,7 +513,7 @@ https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Using-GPIO-hardware-buttons" esac fi # append variables to config file - echo "EXISTINGuse=$EXISTINGuse" >> "${local_home_dir}/PhonieboxInstall.conf" + echo "EXISTINGuse=\"$(_escape_for_shell "$EXISTINGuse")\"" >> "${local_home_dir}/PhonieboxInstall.conf" # Check if we found a Phoniebox install configuration earlier and ask if to run this now if [ "${EXISTINGusePhonieboxInstall}" == "YES" ]; then @@ -576,7 +568,7 @@ ${audio_interfaces} ;; esac # append variables to config file - echo "AUDIOiFace=\"$AUDIOiFace\"" >> "${HOME_DIR}/PhonieboxInstall.conf" + echo "AUDIOiFace=\"$(_escape_for_shell "$AUDIOiFace")\"" >> "${HOME_DIR}/PhonieboxInstall.conf" echo "Your iFace is called '$AUDIOiFace'" read -rp "Hit ENTER to proceed to the next step." INPUT } @@ -638,11 +630,11 @@ config_spotify() { esac # append variables to config file { - echo "SPOTinstall=\"$SPOTinstall\""; - echo "SPOTIuser=\"$(escape_for_shell "$SPOTIuser")\""; - echo "SPOTIpass=\"$(escape_for_shell "$SPOTIpass")\""; - echo "SPOTIclientid=\"$(escape_for_shell "$SPOTIclientid")\""; - echo "SPOTIclientsecret=\"$(escape_for_shell "$SPOTIclientsecret")\"" + echo "SPOTinstall=\"$(_escape_for_shell "$SPOTinstall")\""; + echo "SPOTIuser=\"$(_escape_for_shell "$SPOTIuser")\""; + echo "SPOTIpass=\"$(_escape_for_shell "$SPOTIpass")\""; + echo "SPOTIclientid=\"$(_escape_for_shell "$SPOTIclientid")\""; + echo "SPOTIclientsecret=\"$(_escape_for_shell "$SPOTIclientsecret")\"" } >> "${HOME_DIR}/PhonieboxInstall.conf" read -rp "Hit ENTER to proceed to the next step." INPUT } @@ -682,7 +674,7 @@ config_audio_folder() { ;; esac # append variables to config file - echo "DIRaudioFolders=\"$DIRaudioFolders\"" >> "${HOME_DIR}/PhonieboxInstall.conf" + echo "DIRaudioFolders=\"$(_escape_for_shell "$DIRaudioFolders")\"" >> "${HOME_DIR}/PhonieboxInstall.conf" echo "Your audio folders live in this dir:" echo "${DIRaudioFolders}" read -rp "Hit ENTER to proceed to the next step." INPUT @@ -723,7 +715,7 @@ config_gpio() { ;; esac # append variables to config file - echo "GPIOconfig=\"$GPIOconfig\"" >> "${HOME_DIR}/PhonieboxInstall.conf" + echo "GPIOconfig=\"$(_escape_for_shell "$GPIOconfig")\"" >> "${HOME_DIR}/PhonieboxInstall.conf" echo "" read -rp "Hit ENTER to proceed to the next step." INPUT } @@ -801,9 +793,7 @@ samba_config() { sudo chown root:root "${smb_conf}" sudo chmod 644 "${smb_conf}" # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash - sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' "${smb_conf}" - # Replace homedir; double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${smb_conf}" + sudo sed -i 's|%DIRaudioFolders%|'"$(escape_for_sed "$DIRaudioFolders")"'|' "${smb_conf}" # Samba: create user 'pi' with password 'raspberry' # ToDo: use current user with a default password (echo "raspberry"; echo "raspberry") | sudo smbpasswd -s -a pi @@ -822,8 +812,6 @@ web_server_config() { sudo cp "${jukebox_dir}"/misc/sampleconfigs/lighttpd.conf-default.sample "${lighthttpd_conf}" sudo chown root:root "${lighthttpd_conf}" sudo chmod 644 "${lighthttpd_conf}" - # double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${lighthttpd_conf}" # Web server PHP7 fastcgi conf # -rw-r--r-- 1 root root 398 Apr 30 09:35 /etc/lighttpd/conf-available/15-fastcgi-php.conf @@ -844,18 +832,6 @@ web_server_config() { sudo chmod 440 "${sudoers_wwwdata}" } -# Reads a textfile and pipes all lines as args to the given command. -# Does filter out comments. -# Arguments: -# 1 : textfile to read -# 2... : command to receive args (e.g. 'echo', 'apt-get -y install', ...) -call_with_args_from_file () { - local package_file="$1" - shift - - sed 's/#.*//g' ${package_file} | xargs "$@" -} - install_main() { local jukebox_dir="$1" local apt_get="sudo apt-get -qq --yes" @@ -894,6 +870,14 @@ install_main() { # Start logging here log_open + echo "################################################" + echo "Interactive mode: ${INTERACTIVE}" + echo "GIT_BRANCH ${GIT_BRANCH}" + echo "GIT_URL ${GIT_URL}" + echo "Current User: ${CURRENT_USER}" + echo "User home dir: ${HOME_DIR}" + echo "Used Raspberry Pi OS: ${OS_CODENAME}" + # Add conffile into logfile for better debugging echo "################################################" grep -v -e "SPOTI" -e "WIFIpass" "${HOME_DIR}/PhonieboxInstall.conf" @@ -928,6 +912,10 @@ install_main() { cd "${HOME_DIR}" git clone ${GIT_URL} --branch "${GIT_BRANCH}" + source "${jukebox_dir}"/scripts/helperscripts/inc.helper.sh + source "${jukebox_dir}"/scripts/helperscripts/inc.networkHelper.sh + + # some packages are only available on raspberry pi's but not on test docker containers running on x86_64 machines if [[ $(uname -m) =~ ^armv.+$ ]]; then call_with_args_from_file "${jukebox_dir}"/packages-raspberrypi.txt ${apt_get} ${allow_downgrades} install @@ -1022,8 +1010,6 @@ install_main() { # create config file for web app from sample sudo cp "${jukebox_dir}"/htdocs/config.php.sample "${jukebox_dir}"/htdocs/config.php - # double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${jukebox_dir}"/htdocs/config.php # Starting web server and php7 sudo lighttpd-enable-mod fastcgi @@ -1058,24 +1044,16 @@ install_main() { # 2. install new ones - this is version > 1.1.8-beta RFID_READER_SERVICE="${systemd_dir}/phoniebox-rfid-reader.service" sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-rfid-reader.service-default.sample "${RFID_READER_SERVICE}" - # Replace homedir; double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${RFID_READER_SERVICE}" STARTUP_SCRIPT_SERVICE="${systemd_dir}/phoniebox-startup-scripts.service" sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-startup-scripts.service-default.sample "${STARTUP_SCRIPT_SERVICE}" - # Replace homedir; double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${STARTUP_SCRIPT_SERVICE}" IDLE_WATCHDOG_SERVICE="${systemd_dir}/phoniebox-idle-watchdog.service" sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-idle-watchdog.service.sample "${IDLE_WATCHDOG_SERVICE}" - # Replace homedir; double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${IDLE_WATCHDOG_SERVICE}" if [[ "${GPIOconfig}" == "YES" ]]; then GPIO_CONTROL_SERVICE="${systemd_dir}/phoniebox-gpio-control.service" sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-gpio-control.service.sample "${GPIO_CONTROL_SERVICE}" - # Replace homedir; double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${GPIO_CONTROL_SERVICE}" fi sudo chown root:root "${systemd_dir}"/phoniebox-*.service @@ -1097,11 +1075,9 @@ install_main() { # -rw-r----- 1 mpd audio 14043 Jul 17 20:16 /etc/mpd.conf sudo cp "${jukebox_dir}"/misc/sampleconfigs/mpd.conf.sample ${mpd_conf} # Change vars to match install config - sudo sed -i 's/%AUDIOiFace%/'"$AUDIOiFace"'/' "${mpd_conf}" + sudo sed -i 's|%AUDIOiFace%|'"$(escape_for_sed "$AUDIOiFace")"'|' "${mpd_conf}" # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash - sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' "${mpd_conf}" - # Replace homedir; double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${mpd_conf}" + sudo sed -i 's|%DIRaudioFolders%|'"$(escape_for_sed "$DIRaudioFolders")"'|' "${mpd_conf}" sudo chown mpd:audio "${mpd_conf}" sudo chmod 640 "${mpd_conf}" @@ -1120,14 +1096,12 @@ install_main() { sudo locale-gen sudo cp "${jukebox_dir}"/misc/sampleconfigs/mopidy.conf.sample "${mopidy_conf}" # Change vars to match install config - sudo sed -i 's/%spotify_username%/'"$(escape_for_sed "$SPOTIuser")"'/' "${mopidy_conf}" - sudo sed -i 's/%spotify_password%/'"$(escape_for_sed "$SPOTIpass")"'/' "${mopidy_conf}" - sudo sed -i 's/%spotify_client_id%/'"$(escape_for_sed "$SPOTIclientid")"'/' "${mopidy_conf}" - sudo sed -i 's/%spotify_client_secret%/'"$(escape_for_sed "$SPOTIclientsecret")"'/' "${mopidy_conf}" + sudo sed -i 's|%spotify_username%|'"$(escape_for_sed "$SPOTIuser")"'|' "${mopidy_conf}" + sudo sed -i 's|%spotify_password%|'"$(escape_for_sed "$SPOTIpass")"'|' "${mopidy_conf}" + sudo sed -i 's|%spotify_client_id%|'"$(escape_for_sed "$SPOTIclientid")"'|' "${mopidy_conf}" + sudo sed -i 's|%spotify_client_secret%|'"$(escape_for_sed "$SPOTIclientsecret")"'|' "${mopidy_conf}" # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash - sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' "${mopidy_conf}" - # Replace homedir; double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${mopidy_conf}" + sudo sed -i 's|%DIRaudioFolders%|'"$(escape_for_sed "$DIRaudioFolders")"'|' "${mopidy_conf}" fi # GPIO-Control @@ -1146,6 +1120,9 @@ install_main() { echo "classic" > "${jukebox_dir}"/settings/edition fi + wifi_settings "${jukebox_dir}" + autohotspot "${jukebox_dir}" + # / INSTALLATION ##################################################### } @@ -1172,7 +1149,7 @@ wifi_settings() { local wpa_supplicant_conf="/etc/wpa_supplicant/wpa_supplicant.conf" # -rw-rw-r-- 1 root netdev 137 Jul 16 08:53 /etc/wpa_supplicant/wpa_supplicant.conf sudo cp "${jukebox_dir}"/misc/sampleconfigs/wpa_supplicant.conf.sample "${wpa_supplicant_conf}" - sudo sed -i 's/%WIFIcountryCode%/'"$WIFIcountryCode"'/' "${wpa_supplicant_conf}" + sudo sed -i 's|%WIFIcountryCode%|'"$(escape_for_sed "$WIFIcountryCode")"'|' "${wpa_supplicant_conf}" sudo chown root:netdev "${wpa_supplicant_conf}" sudo chmod 664 "${wpa_supplicant_conf}" @@ -1184,11 +1161,11 @@ wifi_settings() { #-rw-rw-r-- 1 root netdev 0 Apr 17 11:25 /etc/dhcpcd.conf sudo cp "${jukebox_dir}"/misc/sampleconfigs/dhcpcd.conf-default-noHotspot.sample "${dhcpcd_conf}" # Change IP for router and Phoniebox - sudo sed -i 's/%WIFIinterface%/'"$WIFI_INTERFACE"'/' "${dhcpcd_conf}" - sudo sed -i 's/%WIFIip%/'"$WIFIip"'/' "${dhcpcd_conf}" - sudo sed -i 's/%WIFIipRouter%/'"$WIFIipRouter"'/' "${dhcpcd_conf}" - sudo sed -i 's/%WIFIipExtDNS%/'"$wifiExtDNS"'/' "${dhcpcd_conf}" - sudo sed -i 's/%WIFIcountryCode%/'"$WIFIcountryCode"'/' "${dhcpcd_conf}" + sudo sed -i 's|%WIFIinterface%|'"$(escape_for_sed "$WIFI_INTERFACE")"'|' "${dhcpcd_conf}" + sudo sed -i 's|%WIFIip%|'"$(escape_for_sed "$WIFIip")"'|' "${dhcpcd_conf}" + sudo sed -i 's|%WIFIipRouter%|'"$(escape_for_sed "$WIFIipRouter")"'|' "${dhcpcd_conf}" + sudo sed -i 's|%WIFIipExtDNS%|'"$(escape_for_sed "$wifiExtDNS")"'|' "${dhcpcd_conf}" + sudo sed -i 's|%WIFIcountryCode%|'"$(escape_for_sed "$WIFIcountryCode")"'|' "${dhcpcd_conf}" # Change user:group and access mod sudo chown root:netdev "${dhcpcd_conf}" sudo chmod 664 "${dhcpcd_conf}" @@ -1229,7 +1206,7 @@ existing_assets() { # Additional error check: key should not start with a hash and not be empty. if [ ! "${key:0:1}" == '#' ] && [ -n "$key" ]; then # Replace the matching value in the newly created conf file - sed -i 's/%'"$key"'%/'"$val"'/' "${jukebox_dir}"/settings/rfid_trigger_play.conf + sed -i 's|%'"$key"'%|'"$val"'|' "${jukebox_dir}"/settings/rfid_trigger_play.conf fi done <"${backup_dir}"/settings/rfid_trigger_play.conf fi @@ -1262,8 +1239,6 @@ existing_assets() { # make sure service is still enabled by registering again USB_BUTTONS_SERVICE="/etc/systemd/system/phoniebox-buttons-usb-encoder.service" sudo cp -v "${jukebox_dir}"/components/controls/buttons_usb_encoder/phoniebox-buttons-usb-encoder.service.sample "${USB_BUTTONS_SERVICE}" - # Replace homedir; double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${USB_BUTTONS_SERVICE}" sudo systemctl start phoniebox-buttons-usb-encoder.service sudo systemctl enable phoniebox-buttons-usb-encoder.service fi @@ -1350,80 +1325,101 @@ autohotspot() { fi } -finish_installation() { - local jukebox_dir="$1" +finished() { echo " # # INSTALLATION FINISHED # ##################################################### + +Let the sounds begin. +Find more information and documentation on the github account: +https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/ + " +} - ##################################################### - # Register external device(s) +register_rfid_reader() { + local jukebox_dir="$1" - echo "If you are using an RFID reader, connect it to your RPi." - echo "(In case your RFID reader required soldering, consult the manual.)" - # Use -e to display response of user in the logfile - read -e -r -p "Have you connected your RFID reader? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - ;; - *) - echo 'Please select the RFID reader you want to use' - options=("USB-Reader (e.g. Neuftech)" "RC522" "PN532" "Manual configuration" "Multiple RFID reader") - select opt in "${options[@]}"; do - case $opt in - "USB-Reader (e.g. Neuftech)") - cd "${jukebox_dir}"/scripts/ || exit - python3 RegisterDevice.py - sudo chown pi:www-data "${jukebox_dir}"/scripts/deviceName.txt - sudo chmod 644 "${jukebox_dir}"/scripts/deviceName.txt - break - ;; - "RC522") - bash "${jukebox_dir}"/components/rfid-reader/RC522/setup_rc522.sh - break - ;; - "PN532") - bash "${jukebox_dir}"/components/rfid-reader/PN532/setup_pn532.sh - break - ;; - "Manual configuration") - echo "Please configure your reader manually." - break - ;; - "Multiple RFID reader") - cd "${jukebox_dir}"/scripts/ || exit - sudo python3 RegisterDevice.py.Multi - break - ;; - *) - echo "This is not a number" - ;; - esac - done - esac + echo "" + echo "-----------------------------------------------------" + echo "Register RFID reader" + echo "-----------------------------------------------------" + + if [[ ${INTERACTIVE} == "true" ]]; then + echo "If you are using an RFID reader, connect it to your RPi." + echo "(In case your RFID reader required soldering, consult the manual.)" + # Use -e to display response of user in the logfile + read -e -r -p "Have you connected your RFID reader? [Y/n] " response + case "$response" in + [nN][oO]|[nN]) + ;; + *) + echo 'Please select the RFID reader you want to use' + options=("USB-Reader (e.g. Neuftech)" "RC522" "PN532" "Manual configuration" "Multiple RFID reader") + select opt in "${options[@]}"; do + case $opt in + "USB-Reader (e.g. Neuftech)") + cd "${jukebox_dir}"/scripts/ || exit + python3 RegisterDevice.py + sudo chown pi:www-data "${jukebox_dir}"/scripts/deviceName.txt + sudo chmod 644 "${jukebox_dir}"/scripts/deviceName.txt + break + ;; + "RC522") + bash "${jukebox_dir}"/components/rfid-reader/RC522/setup_rc522.sh + break + ;; + "PN532") + bash "${jukebox_dir}"/components/rfid-reader/PN532/setup_pn532.sh + break + ;; + "Manual configuration") + echo "Please configure your reader manually." + break + ;; + "Multiple RFID reader") + cd "${jukebox_dir}"/scripts/ || exit + sudo python3 RegisterDevice.py.Multi + break + ;; + *) + echo "This is not a number" + ;; + esac + done + esac + else + echo "Skipping RFID reader setup..." + echo "For manual registration of an RFID reader type:" + echo "python3 ${JUKEBOX_HOME_DIR}/scripts/RegisterDevice.py" + fi +} - echo - echo "DONE. Let the sounds begin." - echo "Find more information and documentation on the github account:" - echo "https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/" +cleanup_and_reboot() { - echo "Reboot is needed to activate all settings" - # Use -e to display response of user in the logfile - read -e -r -p "Would you like to reboot now? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - # Close logging - log_close - ;; - *) - # Close logging - log_close - sudo shutdown -r now - ;; - esac + echo "" + echo "-----------------------------------------------------" + echo "A reboot is required to activate all settings!" + local do_shutdown=false + if [[ ${INTERACTIVE} == "true" ]]; then + # Use -e to display response of user in the logfile + read -e -r -p "Would you like to reboot now? [Y/n] " response + case "$response" in + [nN][oO]|[nN]) + ;; + *) + do_shutdown=true + ;; + esac + fi + + # Close logging + log_close + if [[ ${do_shutdown} == "true" ]]; then + sudo shutdown -r now + fi } ######## @@ -1451,10 +1447,6 @@ main() { fi install_main "${JUKEBOX_HOME_DIR}" - source "${JUKEBOX_HOME_DIR}"/scripts/helperscripts/inc.networkHelper.sh - - wifi_settings "${JUKEBOX_HOME_DIR}" - autohotspot "${JUKEBOX_HOME_DIR}" existing_assets "${JUKEBOX_HOME_DIR}" "${JUKEBOX_BACKUP_DIR}" folder_access "${JUKEBOX_HOME_DIR}" "pi:www-data" 775 @@ -1463,15 +1455,10 @@ main() { sudo chown pi:www-data "${JUKEBOX_HOME_DIR}/settings/PhonieboxInstall.conf" sudo chmod 775 "${JUKEBOX_HOME_DIR}/settings/PhonieboxInstall.conf" - if [[ ${INTERACTIVE} == "true" ]]; then - finish_installation "${JUKEBOX_HOME_DIR}" - else - echo "Skipping USB device setup..." - echo "For manual registration of a USB card reader type:" - echo "python3 ${JUKEBOX_HOME_DIR}/scripts/RegisterDevice.py" - echo " " - echo "Reboot is required to activate all settings!" - fi + finished + + register_rfid_reader "${JUKEBOX_HOME_DIR}" + cleanup_and_reboot } start=$(date +%s) diff --git a/scripts/installscripts/tests/run_installation_autohotspot_NetworkManager.sh b/scripts/installscripts/tests/run_installation_autohotspot_NetworkManager.sh index 0979e7c72..cb935bec8 100644 --- a/scripts/installscripts/tests/run_installation_autohotspot_NetworkManager.sh +++ b/scripts/installscripts/tests/run_installation_autohotspot_NetworkManager.sh @@ -17,7 +17,8 @@ echo 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selecti # y confirm interactive mode # n configure wifi (extra ENTER) # y configure autohotspot -# y use autohotspot default config (extra ENTER) +# n use autohotspot default config +# y use custom data (extra ENTER) # y use default audio iface (extra ENTER) # n spotify (extra ENTER) # y audio default location (extra ENTER) @@ -27,10 +28,15 @@ echo 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selecti # n reboot export CI_TEST_DHCPCD="false" export CI_TEST_NETWORKMANAGER="true" -./../install-jukebox.sh <<< "y +./../install-jukebox.sh <<< 'y n y +n +a!b"c§d$e%f&g/h(i)j=k?l´m`n²o³p{q[r]s}t\u+v*w~x#y'\''z01234 +DE +ß,ä;ö.ü:Ä-Ö_Ü 1@2€3^4°5|6$7&8/9\0 +192.168.100.2 y y @@ -44,7 +50,7 @@ y y n n -" +' INSTALLATION_EXITCODE=$? # Test installation diff --git a/scripts/installscripts/tests/run_installation_autohotspot_dhcpcd.sh b/scripts/installscripts/tests/run_installation_autohotspot_dhcpcd.sh index 7091399bb..4e69e0866 100644 --- a/scripts/installscripts/tests/run_installation_autohotspot_dhcpcd.sh +++ b/scripts/installscripts/tests/run_installation_autohotspot_dhcpcd.sh @@ -17,7 +17,8 @@ echo 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selecti # y confirm interactive mode # n configure wifi (extra ENTER) # y configure autohotspot -# y use autohotspot default config (extra ENTER) +# n use autohotspot default config +# y use custom data (extra ENTER) # y use default audio iface (extra ENTER) # n spotify (extra ENTER) # y audio default location (extra ENTER) @@ -27,10 +28,15 @@ echo 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selecti # n reboot export CI_TEST_DHCPCD="true" export CI_TEST_NETWORKMANAGER="false" -./../install-jukebox.sh <<< "y +./../install-jukebox.sh <<< 'y n y +n +a!b"c§d$e%f&g/h(i)j=k?l´m`n²o³p{q[r]s}t\u+v*w~x#y'\''z01234 +DE +ß,ä;ö.ü:Ä-Ö_Ü 1@2€3^4°5|6$7&8/9\0 +10.0.0.1 y y @@ -44,7 +50,7 @@ y y n n -" +' INSTALLATION_EXITCODE=$? # Test installation diff --git a/scripts/installscripts/tests/run_installation_classic.sh b/scripts/installscripts/tests/run_installation_classic.sh index 434efc360..f52567f19 100644 --- a/scripts/installscripts/tests/run_installation_classic.sh +++ b/scripts/installscripts/tests/run_installation_classic.sh @@ -26,7 +26,7 @@ echo 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selecti # n RFID registration # n reboot -./../install-jukebox.sh <<< "y +./../install-jukebox.sh <<< 'y n n @@ -42,7 +42,7 @@ y y n n -" +' INSTALLATION_EXITCODE=$? # Test installation diff --git a/scripts/installscripts/tests/run_installation_rfid.sh b/scripts/installscripts/tests/run_installation_rfid.sh index d9f150ad8..e3cfa08c2 100644 --- a/scripts/installscripts/tests/run_installation_rfid.sh +++ b/scripts/installscripts/tests/run_installation_rfid.sh @@ -28,7 +28,7 @@ echo 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selecti # y, use legacy readermode # n reboot -./../install-jukebox.sh <<< "y +./../install-jukebox.sh <<< 'y n n @@ -47,7 +47,7 @@ y y y n -" +' INSTALLATION_EXITCODE=$? # Test installation diff --git a/scripts/installscripts/tests/run_installation_spotify.sh b/scripts/installscripts/tests/run_installation_spotify.sh index e65552b5d..d99ce30b3 100644 --- a/scripts/installscripts/tests/run_installation_spotify.sh +++ b/scripts/installscripts/tests/run_installation_spotify.sh @@ -33,8 +33,8 @@ n y y -abc$defghijkl&mnopqrstuvwxyzßäöüÄÖÜ$1234567890 -!"§$%&/()=?´`²³{[]}\+*~#'\'',;.:-_ @€^° +a!b"c§d$e%f&g/h(i)j=k?l´m`n²o³p{q[r]s}t\u+v*w~x#y'\''zß,ä;ö.ü:Ä-Ö_Ü 1@2€3^4°5|67890 +a!b"c§d$e%f&g/h(i)j=k?l´m`n²o³p{q[r]s}t\u+v*w~x#y'\''zß,ä;ö.ü:Ä-Ö_Ü 1@2€3^4°5|67890 myclient_id myclient+SECRET/0123456789= diff --git a/scripts/installscripts/tests/run_installation_staticip_dhcpcd.sh b/scripts/installscripts/tests/run_installation_staticip_dhcpcd.sh index a01610170..b143e8c70 100644 --- a/scripts/installscripts/tests/run_installation_staticip_dhcpcd.sh +++ b/scripts/installscripts/tests/run_installation_staticip_dhcpcd.sh @@ -28,11 +28,11 @@ echo 'debconf debconf/frontend select Noninteractive' | sudo debconf-set-selecti # n reboot export CI_TEST_DHCPCD="true" export CI_TEST_NETWORKMANAGER="false" -./../install-jukebox.sh <<< "y +./../install-jukebox.sh <<< 'y y -TestWifi +a!b"c§d$e%f&g/h(i)j=k?l´m`n²o³p{q[r]s}t\u+v*w~x#y'\''z01234 DE -TestWifiPW +ß,ä;ö.ü:Ä-Ö_Ü 1@2€3^4°5|6$7&8/9\0 192.168.100.2 192.168.100.1 y @@ -50,7 +50,7 @@ y y n n -" +' INSTALLATION_EXITCODE=$? # Test installation diff --git a/settings/version-number b/settings/version-number index 1dba92d5c..c338ba7ef 100644 --- a/settings/version-number +++ b/settings/version-number @@ -1 +1 @@ -2.7.0-alpha +2.8.0-alpha