From 1ca5a81afcb08cdf6f4c3afb7b21b791b2e53ea9 Mon Sep 17 00:00:00 2001 From: pabera <1260686+pabera@users.noreply.github.com> Date: Sat, 11 Nov 2023 21:26:19 +0100 Subject: [PATCH] future3 - Move docs back to Github & markdown (#2085) * Start moving docs to markdown * update userguide * add more pages * Rename index.md * Undo last commit * Add autohotspot * Finish userguide without references * Rename bt audio btns * Adding developers and rfid * docker: optimizations (#2074) - linux host: use pulse unix socket - mpd: run as user (pi / root) - mpd: remove port exposure to host, connections to mpd only come from other docker containers - less config adjustments for docker environment Co-authored-by: Christoph Lauer * Start moving docs to markdown * update userguide * add more pages * Rename index.md * Undo last commit * Add autohotspot * Finish userguide without references * Rename bt audio btns * Adding developers and rfid * Rename docs to documentation * Update document structure * Move rfid to developers * Remove sphinx * Remove even more sphinx * Test pydoc * Revert "Test pydoc" This reverts commit e1c6aeb25c690e180b6c2c17c3e055e86af9ad1d. Revert "Remove even more sphinx" This reverts commit 6f5559717740760919d67c245cba359d8fd49ae6. Revert "Remove sphinx" This reverts commit 23abee327db39dc77141a0e2c19677cc05097319. * Moving sphinx for api and command reference * Remove Sphinx for good * update paths to developers --------- Co-authored-by: notapirate Co-authored-by: Christoph Lauer --- .flake8 | 2 - .githooks/pre-commit | 13 +- .github/workflows/pythonpackage_future3.yml | 11 - .gitignore | 3 - .readthedocs.yaml | 28 - CONTRIBUTING.md | 15 - README.md | 19 +- docker/docker-compose.yml | 4 + docker/jukebox.Dockerfile | 3 - docker/webapp.Dockerfile | 2 +- docs/sphinx/_templates/footer.html | 17 - docs/sphinx/api/api.rst | 20 - docs/sphinx/api/callingback.rst | 9 - docs/sphinx/api/cfghandler.rst | 5 - docs/sphinx/api/controls.rst | 19 - docs/sphinx/api/gpioz/connector.rst | 45 - docs/sphinx/api/gpioz/converter.rst | 13 - docs/sphinx/api/gpioz/gpioz.rst | 17 - docs/sphinx/api/gpioz/input_devices.rst | 42 - docs/sphinx/api/gpioz/output_devices.rst | 44 - docs/sphinx/api/playlist.rst | 11 - docs/sphinx/api/plugs.rst | 6 - docs/sphinx/api/publishing.rst | 12 - docs/sphinx/api/rpc_server.rst | 7 - docs/sphinx/api/utils.rst | 6 - docs/sphinx/api/volume.rst | 17 - docs/sphinx/conf.py | 67 -- docs/sphinx/developer/coreapps.rst | 61 -- docs/sphinx/developer/developer_issues.rst | 80 -- .../developer/development_environment.rst | 73 -- docs/sphinx/developer/docker.rst | 250 ----- docs/sphinx/featurelist.rst | 313 ------ docs/sphinx/index.rst | 57 - docs/sphinx/install.rst | 98 -- docs/sphinx/issues.rst | 15 - docs/sphinx/migration.rst | 55 - docs/sphinx/requirements.txt | 8 - docs/sphinx/requirements_pyzmq.txt | 5 - docs/sphinx/rfid/basics.rst | 91 -- docs/sphinx/rfid/genericusb.rst | 1 - docs/sphinx/rfid/mfrc522_spi.rst | 1 - docs/sphinx/rfid/mock_reader.rst | 1 - docs/sphinx/rfid/pn532_i2c.rst | 1 - docs/sphinx/rfid/rdm6300.rst | 1 - docs/sphinx/rfid/rfid.rst | 14 - docs/sphinx/rfid/template.rst | 1 - docs/sphinx/userguide/audio.rst | 152 --- docs/sphinx/userguide/autohotspot.rst | 112 -- .../userguide/bluetooth_audio_buttons.rst | 4 - docs/sphinx/userguide/carddatabase.rst | 94 -- docs/sphinx/userguide/concepts.rst | 46 - docs/sphinx/userguide/configuration.rst | 43 - docs/sphinx/userguide/gpioz.rst | 1 - .../userguide/rpc_command_alias_reference.rst | 188 ---- .../userguide/rpc_command_reference.rst | 994 ------------------ docs/sphinx/userguide/rpc_commands.rst | 116 -- docs/sphinx/userguide/sync_rfidcards.rst | 71 -- docs/sphinx/userguide/system.rst | 121 --- docs/sphinx/userguide/troubleshooting.rst | 107 -- .../primer.rst => documentation/README.md | 32 +- .../calendars/2019-Phoniebox-Calendar.jpg | Bin .../calendars/2020-Phoniebox-Calendar.jpg | Bin .../calendars/2021-Phoniebox-Calendar.jpg | Bin documentation/content/developers/coreapps.md | 56 + .../content/developers/developer-issues.md | 73 ++ .../developers/development-environment.md | 74 ++ documentation/content/developers/docker.md | 265 +++++ .../content/developers/known-issues.md | 13 + .../content/developers/rfid/README.md | 12 + .../content/developers/rfid/basics.md | 93 ++ .../content/developers/rfid/genericusb.md | 14 + .../content/developers/rfid/mfrc522_spi.md | 81 ++ .../content/developers/rfid/mock_reader.md | 26 + .../content/developers}/rfid/mock_reader.png | Bin .../content/developers/rfid/pn532_i2c.md | 53 + .../content/developers/rfid/rdm6300.md | 19 + .../developers/rfid/template_reader.md | 41 + .../developers/to-be-deleted-status.md | 244 +++++ documentation/content/userguide/audio.md | 141 +++ .../content/userguide/autohotspot.md | 107 ++ .../userguide/bluetooth-audio-buttons.md | 63 ++ .../content/userguide/card-database.md | 101 ++ documentation/content/userguide/concepts.md | 27 + .../content/userguide/configuration.md | 40 + .../content/userguide/installation.md | 93 ++ .../content}/userguide/mock_gpio.png | Bin documentation/content/userguide/rfid.md | 80 ++ documentation/content/userguide/system.md | 112 ++ .../content/userguide/troubleshooting.md | 97 ++ documentation/content/userguide/update.md | 39 + installation/routines/customize_options.sh | 24 - installation/routines/setup_jukebox_webapp.sh | 9 - requirements.txt | 3 - resources/default-settings/nginx.default | 37 +- resources/html/runsphinx.html | 24 - run_sphinx.sh | 45 - .../bluetooth_audio_buttons/README.rst | 2 +- src/jukebox/components/gpio/gpioz/README.rst | 2 - .../hardware/template_new_reader/README.rst | 3 +- src/jukebox/jukebox/daemon.py | 11 - 100 files changed, 1998 insertions(+), 3790 deletions(-) delete mode 100644 .readthedocs.yaml delete mode 100644 docs/sphinx/_templates/footer.html delete mode 100644 docs/sphinx/api/api.rst delete mode 100644 docs/sphinx/api/callingback.rst delete mode 100644 docs/sphinx/api/cfghandler.rst delete mode 100644 docs/sphinx/api/controls.rst delete mode 100644 docs/sphinx/api/gpioz/connector.rst delete mode 100644 docs/sphinx/api/gpioz/converter.rst delete mode 100644 docs/sphinx/api/gpioz/gpioz.rst delete mode 100644 docs/sphinx/api/gpioz/input_devices.rst delete mode 100644 docs/sphinx/api/gpioz/output_devices.rst delete mode 100644 docs/sphinx/api/playlist.rst delete mode 100644 docs/sphinx/api/plugs.rst delete mode 100644 docs/sphinx/api/publishing.rst delete mode 100644 docs/sphinx/api/rpc_server.rst delete mode 100644 docs/sphinx/api/utils.rst delete mode 100644 docs/sphinx/api/volume.rst delete mode 100644 docs/sphinx/conf.py delete mode 100644 docs/sphinx/developer/coreapps.rst delete mode 100644 docs/sphinx/developer/developer_issues.rst delete mode 100644 docs/sphinx/developer/development_environment.rst delete mode 100644 docs/sphinx/developer/docker.rst delete mode 100644 docs/sphinx/featurelist.rst delete mode 100644 docs/sphinx/index.rst delete mode 100644 docs/sphinx/install.rst delete mode 100644 docs/sphinx/issues.rst delete mode 100644 docs/sphinx/migration.rst delete mode 100644 docs/sphinx/requirements.txt delete mode 100644 docs/sphinx/requirements_pyzmq.txt delete mode 100644 docs/sphinx/rfid/basics.rst delete mode 100644 docs/sphinx/rfid/genericusb.rst delete mode 100644 docs/sphinx/rfid/mfrc522_spi.rst delete mode 100644 docs/sphinx/rfid/mock_reader.rst delete mode 100644 docs/sphinx/rfid/pn532_i2c.rst delete mode 100644 docs/sphinx/rfid/rdm6300.rst delete mode 100644 docs/sphinx/rfid/rfid.rst delete mode 100644 docs/sphinx/rfid/template.rst delete mode 100644 docs/sphinx/userguide/audio.rst delete mode 100644 docs/sphinx/userguide/autohotspot.rst delete mode 100644 docs/sphinx/userguide/bluetooth_audio_buttons.rst delete mode 100644 docs/sphinx/userguide/carddatabase.rst delete mode 100644 docs/sphinx/userguide/concepts.rst delete mode 100644 docs/sphinx/userguide/configuration.rst delete mode 100644 docs/sphinx/userguide/gpioz.rst delete mode 100644 docs/sphinx/userguide/rpc_command_alias_reference.rst delete mode 100644 docs/sphinx/userguide/rpc_command_reference.rst delete mode 100644 docs/sphinx/userguide/rpc_commands.rst delete mode 100644 docs/sphinx/userguide/sync_rfidcards.rst delete mode 100644 docs/sphinx/userguide/system.rst delete mode 100644 docs/sphinx/userguide/troubleshooting.rst rename docs/sphinx/primer.rst => documentation/README.md (62%) rename {docs => documentation/content}/calendars/2019-Phoniebox-Calendar.jpg (100%) rename {docs => documentation/content}/calendars/2020-Phoniebox-Calendar.jpg (100%) rename {docs => documentation/content}/calendars/2021-Phoniebox-Calendar.jpg (100%) create mode 100644 documentation/content/developers/coreapps.md create mode 100644 documentation/content/developers/developer-issues.md create mode 100644 documentation/content/developers/development-environment.md create mode 100644 documentation/content/developers/docker.md create mode 100644 documentation/content/developers/known-issues.md create mode 100644 documentation/content/developers/rfid/README.md create mode 100644 documentation/content/developers/rfid/basics.md create mode 100644 documentation/content/developers/rfid/genericusb.md create mode 100644 documentation/content/developers/rfid/mfrc522_spi.md create mode 100644 documentation/content/developers/rfid/mock_reader.md rename {docs/sphinx => documentation/content/developers}/rfid/mock_reader.png (100%) create mode 100644 documentation/content/developers/rfid/pn532_i2c.md create mode 100644 documentation/content/developers/rfid/rdm6300.md create mode 100644 documentation/content/developers/rfid/template_reader.md create mode 100644 documentation/content/developers/to-be-deleted-status.md create mode 100644 documentation/content/userguide/audio.md create mode 100644 documentation/content/userguide/autohotspot.md create mode 100644 documentation/content/userguide/bluetooth-audio-buttons.md create mode 100644 documentation/content/userguide/card-database.md create mode 100644 documentation/content/userguide/concepts.md create mode 100644 documentation/content/userguide/configuration.md create mode 100644 documentation/content/userguide/installation.md rename {docs/sphinx => documentation/content}/userguide/mock_gpio.png (100%) create mode 100644 documentation/content/userguide/rfid.md create mode 100644 documentation/content/userguide/system.md create mode 100644 documentation/content/userguide/troubleshooting.md create mode 100644 documentation/content/userguide/update.md delete mode 100755 resources/html/runsphinx.html delete mode 100755 run_sphinx.sh diff --git a/.flake8 b/.flake8 index 42dddd56d..d11edbe8a 100644 --- a/.flake8 +++ b/.flake8 @@ -19,8 +19,6 @@ filename = *.py,*.py.* extend-exclude = # Ignore all scratch development directories scratch*, - # The conf file is mostly autogenerated, ignore it - docs/sphinx/conf.py, # Ignore dirs and files that have not been ported yet */jukebox/NvManager.py # ignore GitHub Codespaces diff --git a/.githooks/pre-commit b/.githooks/pre-commit index 026740b23..95901bcda 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -26,18 +26,7 @@ if [[ -n $PY_FILES ]]; then echo "Flake8 return code: $flake8_code" fi -DOC_FILES="$(git diff --diff-filter=d --staged --name-only -- docs/sphinx/*)" -sphinx_code=0 -if [[ -n $DOC_FILES || -n $PY_FILES ]]; then - echo -e "\n**************************************************************" - echo -e "Files for documentation modified. Testing re-build of docs ... \n" - echo -e "**************************************************************\n" - ./run_sphinx.sh -c - sphinx_code=$? - echo "Sphinx return code: $sphinx_code" -fi - -code=$(( flake8_code + sphinx_code )) +code=$(( flake8_code )) if [[ code -gt 0 ]]; then echo -e "\n**************************************************************" diff --git a/.github/workflows/pythonpackage_future3.yml b/.github/workflows/pythonpackage_future3.yml index 670f373da..757edb6f8 100644 --- a/.github/workflows/pythonpackage_future3.yml +++ b/.github/workflows/pythonpackage_future3.yml @@ -7,14 +7,12 @@ on: paths: - '**.py' - '**.py.*' - - 'docs/sphinx/**' pull_request: branches: - 'future3/**' paths: - '**.py' - '**.py.*' - - 'docs/sphinx/**' jobs: build: @@ -40,9 +38,6 @@ jobs: pip3 install spidev pip3 install -r requirements.txt # For operation of the Jukebox, ZMQ must be compiled from sources due to Websocket support - # When just building the docs, the regular ZMQ package is sufficient - pip3 install -r docs/sphinx/requirements_pyzmq.txt - pip3 install -r docs/sphinx/requirements.txt # Also install all optional dependencies pip3 install -r src/jukebox/components/rfid/hardware/fake_reader_gui/requirements.txt pip3 install -r src/jukebox/components/rfid/hardware/pn532_i2c_py532/requirements.txt @@ -53,9 +48,3 @@ jobs: pip3 install flake8 # Stop the build if linting fails ./run_flake8.sh - - name: Build the docs - working-directory: ./docs/sphinx - run: | - # Stop the build if documentation cannot be built - # Treat all warnings as errors - sphinx-build -W --keep-going -T -a -E -b html . _build diff --git a/.gitignore b/.gitignore index 48270aedb..9d38e1b8c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,9 +7,6 @@ /shared/*.* /shared/* -# Documentation builder -/docs/sphinx/_build/ - # Application /src/cli_client/pbc diff --git a/.readthedocs.yaml b/.readthedocs.yaml deleted file mode 100644 index f53f8c41c..000000000 --- a/.readthedocs.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# .readthedocs.yaml -# Read the Docs configuration file -# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details - -# Required -version: 2 - -build: - os: ubuntu-20.04 - tools: - python: "3.9" - apt_packages: - - libasound2-dev - - libpulse0 - -# Build documentation in the docs/ directory with Sphinx -sphinx: - configuration: docs/sphinx/conf.py - builder: html - fail_on_warning: true - -# Optionally set the version of Python and requirements required to build your docs -# autodoc imports (!) modules. This means it needs ALL the dependencies, even the optional ones -python: - install: - - requirements: requirements.txt - - requirements: docs/sphinx/requirements_pyzmq.txt - - requirements: docs/sphinx/requirements.txt diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a3089b6d8..c3bc03705 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,7 +26,6 @@ The Jukebox core app is written entirely in Python. Therefore, we follow the [Py * **Documentation** * You are expected to write some Documentation. It's easy. **Very** easy actually with [Python Docstrings](https://www.geeksforgeeks.org/python-docstrings/) - * If you dare, you may add the python documentation reference to the Sphinx documentation build. But we are also ok with doing that for you # Structure of files and folders @@ -38,8 +37,6 @@ Inside the root folder or the repo, these folders are important: * contains the Python packages that are loaded using the plugin interface * `src/webapp` * contains the Web Interface -* `src/docs/sphinx` - * contains the documentation sources and build flow using Sphinx All folders on all hierarchy levels starting with `scratch*` are ignored by git and flake8. These are intended as local, temporary scratch areas. @@ -132,18 +129,6 @@ cd /home/pi/RPi-Jukebox-RFID If you are convinced some issue should not apply to your case or would require extensive re-coding, that could be OK. Let us know in the pull request - we will look at it. -### Documentation - -When adding or improving documentation, build the documentation and look at it locally. -If you are contributing to existing Python modules, be aware that these are already included in the documentation flow. -Also run through this step in this case! Fix all warnings! - -~~~bash -$ cd /home/pi/RPi-Jukebox-RFID/ -$ ./run_sphinx.sh -# open and check the result: 'file:///path/to/RPi-Jukebox-RFID/docs/sphinx/_build/html/index.html' -~~~ - ### Tests Tests are very few at the moment, but it cannot hurt to run them. If you have tests for your new modules, please add diff --git a/README.md b/README.md index 619534ec3..e45ddaa26 100644 --- a/README.md +++ b/README.md @@ -11,24 +11,7 @@ project check out the [documentation of Version 2]( -

- -

-

- Local copy of documentation for {{ project }} Version {{ release }}. - View online documentation - -

- -{% endif %} -{% endblock %} diff --git a/docs/sphinx/api/api.rst b/docs/sphinx/api/api.rst deleted file mode 100644 index 117fe92f6..000000000 --- a/docs/sphinx/api/api.rst +++ /dev/null @@ -1,20 +0,0 @@ ----------------------- -Developers API ----------------------- - -Developers API Introduction - -.. toctree:: - :maxdepth: 2 - :caption: The Python packages: - - plugs - publishing - rpc_server - cfghandler - playlist - utils - volume - controls - callingback - gpioz/gpioz diff --git a/docs/sphinx/api/callingback.rst b/docs/sphinx/api/callingback.rst deleted file mode 100644 index f913b41fd..000000000 --- a/docs/sphinx/api/callingback.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. RPI Jukebox RFID Version 3 -.. Copyright (c) See file LICENSE in project root folder - -------------------------------- -Generic Callback Handler -------------------------------- - -.. automodule:: jukebox.callingback - :members: diff --git a/docs/sphinx/api/cfghandler.rst b/docs/sphinx/api/cfghandler.rst deleted file mode 100644 index cfdcd078d..000000000 --- a/docs/sphinx/api/cfghandler.rst +++ /dev/null @@ -1,5 +0,0 @@ -Config Handler -***************** - -.. automodule:: jukebox.cfghandler - :members: diff --git a/docs/sphinx/api/controls.rst b/docs/sphinx/api/controls.rst deleted file mode 100644 index 1ad0a2956..000000000 --- a/docs/sphinx/api/controls.rst +++ /dev/null @@ -1,19 +0,0 @@ - -Controls based on EvDev input devices -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - -Common -************************* - -.. automodule:: components.controls.common.evdev_listener - :members: - :private-members: _filter_by_device_name, _filter_by_mandatory_keys - -Bluetooth audio buttons -************************* - -See also the corresponding user guide :ref:`userguide/bluetooth_audio_buttons:Bluetooth audio buttons` - -.. automodule:: components.controls.bluetooth_audio_buttons - :members: diff --git a/docs/sphinx/api/gpioz/connector.rst b/docs/sphinx/api/gpioz/connector.rst deleted file mode 100644 index eb547de55..000000000 --- a/docs/sphinx/api/gpioz/connector.rst +++ /dev/null @@ -1,45 +0,0 @@ -.. RPI Jukebox RFID Version 3 -.. Copyright (c) See file LICENSE in project root folder - -------------------------------- -GPIOZ Connector Functions -------------------------------- - -.. automodule:: components.gpio.gpioz.plugin.connectivity - -.. currentmodule:: components.gpio.gpioz.plugin.connectivity - -Common -^^^^^^^^ - -.. autoattribute:: components.gpio.gpioz.plugin.connectivity.BUZZ_TONE - -RFID -^^^^^ - -.. autofunction:: register_rfid_callback - - -Volume -^^^^^^^^ - -.. autofunction:: register_volume_led_callback - -.. autofunction:: register_volume_rgbled_callback - -.. autofunction:: register_volume_buzzer_callback - -Audio output sink -^^^^^^^^^^^^^^^^^^ - -.. autofunction:: register_audio_sink_change_callback - -Status -^^^^^^^^ -.. autofunction:: register_status_led_callback - -.. autofunction:: register_status_buzzer_callback - -.. autofunction:: register_status_tonalbuzzer_callback - - diff --git a/docs/sphinx/api/gpioz/converter.rst b/docs/sphinx/api/gpioz/converter.rst deleted file mode 100644 index d65e4b595..000000000 --- a/docs/sphinx/api/gpioz/converter.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. RPI Jukebox RFID Version 3 -.. Copyright (c) See file LICENSE in project root folder - -------------------------------- -GPIOZ Converters -------------------------------- - -.. automodule:: components.gpio.gpioz.core.converter - :members: - :special-members: +__call__ - - - diff --git a/docs/sphinx/api/gpioz/gpioz.rst b/docs/sphinx/api/gpioz/gpioz.rst deleted file mode 100644 index 024fd90ee..000000000 --- a/docs/sphinx/api/gpioz/gpioz.rst +++ /dev/null @@ -1,17 +0,0 @@ -.. RPI Jukebox RFID Version 3 -.. Copyright (c) See file LICENSE in project root folder - ----------------------- -GPIOZ ----------------------- - -The GPIOZ plugin connects to GPIO devices such as Buttons, LEDs, Buzzers. It utilizes GPIOZero to do so. - -.. toctree:: - :maxdepth: 2 - :caption: The GPIOZ packages: - - input_devices - output_devices - connector - converter diff --git a/docs/sphinx/api/gpioz/input_devices.rst b/docs/sphinx/api/gpioz/input_devices.rst deleted file mode 100644 index ba29d70f5..000000000 --- a/docs/sphinx/api/gpioz/input_devices.rst +++ /dev/null @@ -1,42 +0,0 @@ -.. RPI Jukebox RFID Version 3 -.. Copyright (c) See file LICENSE in project root folder - -------------------------------- -GPIOZ Input Devices -------------------------------- - -.. automodule:: components.gpio.gpioz.core.input_devices - -.. currentmodule:: components.gpio.gpioz.core.input_devices - -Button -^^^^^^^^ - -.. autoclass:: Button - :members: on_press, set_rpc_actions, close, value, pull_up, pin, hold_time, hold_repeat - -Long press Button -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. autoclass:: LongPressButton - :members: on_press, set_rpc_actions, close, value, pull_up, pin, hold_time, hold_repeat - -Short + Long press Button -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. autoclass:: ShortLongPressButton - :members: on_short_press, on_long_press, set_rpc_actions, close, value, pull_up, pin, hold_time, hold_repeat - -Twin Button -^^^^^^^^^^^^^^^^^^^ - -.. autoclass:: TwinButton - :members: on_short_press_a, on_short_press_b, on_short_press_ab, on_long_press_a, on_long_press_b, on_long_press_ab, value, is_active, hold_repeat, hold_time, close - -Rotary Encoder -^^^^^^^^^^^^^^^^^^ - -.. autoclass:: RotaryEncoder - :members: on_rotate_clockwise, on_rotate_counter_clockwise, set_rpc_actions, close, pin_a, pin_b - - diff --git a/docs/sphinx/api/gpioz/output_devices.rst b/docs/sphinx/api/gpioz/output_devices.rst deleted file mode 100644 index a30986f03..000000000 --- a/docs/sphinx/api/gpioz/output_devices.rst +++ /dev/null @@ -1,44 +0,0 @@ -.. RPI Jukebox RFID Version 3 -.. Copyright (c) See file LICENSE in project root folder - -------------------------------- -GPIOZ Output Devices -------------------------------- - -.. automodule:: components.gpio.gpioz.core.output_devices - -.. py:currentmodule:: components.gpio.gpioz.core.output_devices - - -LED -^^^ - -.. autoclass:: LED(pin, *, active_high=True, initial_value=False, pin_factory=None, name=None) - :members: flash, on, off, toggle, blink, pin, is_lit, value - -PWMLED -^^^^^^^ - -.. autoclass:: PWMLED(pin, *, active_high=True, initial_value=0, frequency=100, pin_factory=None, name=None) - :members: flash, on, off, toggle, blink, pulse, pin, is_lit, value - - -RGBLED -^^^^^^^ - -.. autoclass:: RGBLED(red, green, blue, *, active_high=True, initial_value=(0, 0, 0), pwm=True, pin_factory=None, name=None) - :members: flash, on, off, toggle, blink, pulse, red, green, blue, is_lit, color, value - - -Buzzer -^^^^^^^ - -.. autoclass:: Buzzer(pin, *, active_high=True, initial_value=False, pin_factory=None, name=None) - :members: flash, on, off, toggle, beep, pin, is_active, value - - -TonalBuzzer -^^^^^^^^^^^^^^ - -.. autoclass:: TonalBuzzer(pin, *, initial_value=None, mid_tone=Tone('A5'), octaves=2, pin_factory=None, name=None) - :members: melody, flash, play, stop, octaves, min_tone, mid_tone, max_tone, tone, is_active, value diff --git a/docs/sphinx/api/playlist.rst b/docs/sphinx/api/playlist.rst deleted file mode 100644 index febeb4c0f..000000000 --- a/docs/sphinx/api/playlist.rst +++ /dev/null @@ -1,11 +0,0 @@ -Playlist Generator -********************** - -.. automodule:: jukebox.playlistgenerator - -.. autoclass:: jukebox.playlistgenerator.PlaylistCollector - :members: - :private-members: _exclude_endings - - - diff --git a/docs/sphinx/api/plugs.rst b/docs/sphinx/api/plugs.rst deleted file mode 100644 index 73f2e1043..000000000 --- a/docs/sphinx/api/plugs.rst +++ /dev/null @@ -1,6 +0,0 @@ ----------------------------- -Plugs: The Plugin Package ----------------------------- - -.. automodule:: jukebox.plugs - :members: diff --git a/docs/sphinx/api/publishing.rst b/docs/sphinx/api/publishing.rst deleted file mode 100644 index 607d9e8d3..000000000 --- a/docs/sphinx/api/publishing.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. automodule:: jukebox.publishing.server - - jukebox.publishing - ------------------- - - .. autofunction:: jukebox.publishing.get_publisher - - jukebox.publishing.server - ------------------------- - - .. autoclass:: jukebox.publishing.server.Publisher - :members: diff --git a/docs/sphinx/api/rpc_server.rst b/docs/sphinx/api/rpc_server.rst deleted file mode 100644 index 634adf763..000000000 --- a/docs/sphinx/api/rpc_server.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. automodule:: jukebox.rpc.server - - jukebox.rpc.server - ------------------------- - - .. autoclass:: jukebox.rpc.server.RpcServer - :members: diff --git a/docs/sphinx/api/utils.rst b/docs/sphinx/api/utils.rst deleted file mode 100644 index 17ba7500c..000000000 --- a/docs/sphinx/api/utils.rst +++ /dev/null @@ -1,6 +0,0 @@ ----------------------------- -Jukebox utility functions ----------------------------- - -.. automodule:: jukebox.utils - :members: diff --git a/docs/sphinx/api/volume.rst b/docs/sphinx/api/volume.rst deleted file mode 100644 index 4bf700832..000000000 --- a/docs/sphinx/api/volume.rst +++ /dev/null @@ -1,17 +0,0 @@ -.. RPI Jukebox RFID -.. RPI Jukebox RFID -.. Copyright (c) See file LICENSE in project root folder - -------------------------------- -Volume and Audio Sink Control -------------------------------- - -.. automodule:: components.volume - -.. autoclass:: components.volume.PulseMonitor - :members: - :inherited-members: Thread - -.. autoclass:: components.volume.PulseVolumeControl - :members: - :inherited-members: Thread diff --git a/docs/sphinx/conf.py b/docs/sphinx/conf.py deleted file mode 100644 index 79b9476bd..000000000 --- a/docs/sphinx/conf.py +++ /dev/null @@ -1,67 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -import os -import sys -import sphinx_rtd_theme -sys.path.insert(0, os.path.abspath('../../src/jukebox')) -# This is needed for autodoc to load components.plugins with regular import - i.e. w/o going through plugs.load(...) -import jukebox.plugs # noqa: E402 -jukebox.plugs.ALLOW_DIRECT_IMPORTS = True -import jukebox.utils # noqa: E402 - - -# -- Project information ----------------------------------------------------- - -project = 'RPi Jukebox RFID' -copyright = '2021-2022, The RPi Jukebox RFID Community' -author = 'The RPi Jukebox RFID Community' - -# The full version, including alpha/beta/rc tags -release = jukebox.version() -version = release - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = ['sphinx.ext.autodoc', 'sphinx.ext.autosectionlabel'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# html_theme = 'alabaster' -html_theme = 'sphinx_rtd_theme' -html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -# There are none yet: Comment out to suppress warning -# html_static_path = ['_static'] - -# --------------------------------------------------- - -# Prefix document path to section labels, to use: -# `path/to/file:heading` instead of just `heading` -autosectionlabel_prefix_document = True diff --git a/docs/sphinx/developer/coreapps.rst b/docs/sphinx/developer/coreapps.rst deleted file mode 100644 index 887b8d143..000000000 --- a/docs/sphinx/developer/coreapps.rst +++ /dev/null @@ -1,61 +0,0 @@ -Jukebox Apps -=============== - -The Jukebox's core apps are located in ``src/jukebox``. Run the following command to learn more about each app and its parameters: - -.. code-block:: bash - - $ ./run_app_name.py -h - -Jukebox Core -***************** - -run_jukebox.py ---------------- - -.. automodule:: run_jukebox - -Configuration Tools -******************** - -Before running the configuration tools, stop the Jukebox Core service. -See :ref:`userguide/configuration:Best practice procedure`. - -run_configure_audio.py ------------------------------ - -.. automodule:: run_configure_audio - -run_register_rfid_reader.py ------------------------------ - -.. automodule:: run_register_rfid_reader - -Developer Tools -***************** - -run_rpc_tool.py ---------------- - -.. automodule:: run_rpc_tool - -run_publicity_sniffer.py -------------------------- - -.. automodule:: run_publicity_sniffer - -run_sphinx.sh -------------------------- - -This command rebuilds the documentation using a Sphinx flow, located in the main directory. - -The documentation is built partially from auto-generated RST-files. -Thee files contain the :ref:`userguide/rpc_command_reference:RPC Command Reference` -and :ref:`userguide/rpc_command_alias_reference:RPC Command Alias Reference`. - -.. code-block:: bash - - run_jukebox.py -a - -The above command regenerate these RST files. This only needs to be done when -the RPC call references need to be updated within the documentation flow. diff --git a/docs/sphinx/developer/developer_issues.rst b/docs/sphinx/developer/developer_issues.rst deleted file mode 100644 index dd3a511fd..000000000 --- a/docs/sphinx/developer/developer_issues.rst +++ /dev/null @@ -1,80 +0,0 @@ -Developer Issues -****************** - -.. contents:: - -Building the Webapp on the PI -================================== - -JavaScript heap out of memory --------------------------------- - -While (re-) building the Web App, you get the following output: - -.. code-block:: bash - :emphasize-lines: 12 - - pi@MusicPi:~/RPi-Jukebox-RFID/src/webapp $ npm run build - - > webapp@0.1.0 build - > react-scripts build - - Creating an optimized production build... - - [...] - - <--- JS stacktrace ---> - - FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory - - -**Reason** - -Not enough memory for Node - -**Solution** - -Prior to building set the node memory environment variable. - - #. Make sure the value is less than the total available space on the system, or you may run into the next issue. (Not always though!) - Check memory availability with ``free -mt``. - #. We also experience trouble, when the space is set too small a value. 512 always works, 256 sometimes does, sometimes does not. - If your free memory is small, consider increasing the swap size of your system! - -.. code-block:: bash - - export NODE_OPTIONS=--max-old-space-size=512 - npm run build - -Alternatively, use the provided script, which sets the variable for you (provided your swap size is large enough): - -.. code-block:: bash - - $ ./run_rebuild.sh - - -Process exited too early // kill -9 ---------------------------------------- - -.. code-block:: bash - :emphasize-lines: 8,9 - - pi@MusicPi:~/RPi-Jukebox-RFID/src/webapp $ npm run build - - > webapp@0.1.0 build - > react-scripts build - - ... - - The build failed because the process exited too early. - This probably means the system ran out of memory or someone called 'kill -9' on the process. - -**Reason** - -Node tried to allocate more memory than available on the system. - -**Solution** - -Adjust the node memory variable as described in :ref:`developer/developer_issues:JavaScript heap out of memory`. -But make sure to allocate less memory than the available memory. -If that is not sufficient, increase the swap file size of your system and try again. diff --git a/docs/sphinx/developer/development_environment.rst b/docs/sphinx/developer/development_environment.rst deleted file mode 100644 index 243584eb7..000000000 --- a/docs/sphinx/developer/development_environment.rst +++ /dev/null @@ -1,73 +0,0 @@ -Development Environment -************************ - -You have 3 development options: - -.. contents:: - -Directly on Raspberry Pi ------------------------- - -The full setup is running on the RPi and you access files via SSH. Pretty easy to set up as -you simply do a normal install and switch to the ``future3/develop`` branch. - -Steps to install -```````````````` - -We recommend to use at least a Pi 3 or Pi Zero 2 for development. This hardware won't be needed -in production, but it can be slow while developing. - -1. Install the latest Pi OS on a SD card. -2. Boot up your Raspberry Pi. -3. :ref:`Install ` the Jukebox software as if you were building a Phoniebox. You can install from your own fork and feature branch if you wish which can be changed later as well. The original repository will be set as ``upstream``. -4. Once the installation has successfully ran, reboot your Pi. -5. Due to some resource constraints, the Webapp does not build the latest changes and instead consumes the latest official release. To change that, you need to install NodeJS and build the Webapp locally. -6. Install NodeJS using the existing installer - -.. code-block:: bash - - cd ~/RPi-Jukebox-RFID/installation/routines; \ - source setup_jukebox_webapp.sh; \ - _jukebox_webapp_install_node - -7. To free up RAM, reboot your Pi. -8. Build the Webapp using the existing build command. If the build fails, you might have forgotten to reboot. - -.. code-block:: bash - - cd ~/RPi-Jukebox-RFID/src/webapp; \ - ./run_rebuild.sh -u - -9. The Webapp should now be updated. -10. To continuously update Webapp, pull the latest changes from your repository and rerun the command above. - - -Locally on any Linux machine ------------------------------- - -The jukebox also runs on any Linux machine. The Raspberry Pi specific stuff will not work of course. That is no issue depending -our your development area. USB RFID Readers, however, will work. -You may setup a Python virtual environment or a conda virtual environment. -You will have to install and configure `MPD (Music Player Daemon) `_. - -In addition to the `requirements.txt`, you will this dependency. On the Raspberry PI, the latest stable -release of ZMQ does not support WebSockets. We need to compile the latest -version from Github, which is taken care of by the installation script. -For regular machines, the normal package can be installed: - -.. code-block:: bash - - pip3 install pyzmq - - -You will have to start Jukebox core application and the WebUI separately. The MPD usually runs as a service. - -Using Docker container ------------------------------- - -There is a complete setup :ref:`docker workflow `. - -.. toctree:: - :hidden: - - docker diff --git a/docs/sphinx/developer/docker.rst b/docs/sphinx/developer/docker.rst deleted file mode 100644 index f3de61902..000000000 --- a/docs/sphinx/developer/docker.rst +++ /dev/null @@ -1,250 +0,0 @@ -Phoniebox Development Runbook for Docker environments -******************************************************** - -.. contents:: - -This document describes how to set up a local development environment with Docker. -It is useful to develop certain parts of the Phoniebox application that do not directly require the Raspberry Pi -hardware such as GPIO. *Raspberry Pi OS* is based on Debian but comes with a lot of special packages and a unique -graphical interface. It is difficult to mock a Raspberry Pi whithin a Docker container but we try to keep both -environments as close as possible. The Docker environment is not meant to be deployed on the Raspberry Pi directly for -performance reasons. - -Depending on your host environment (Mac, Linux or Windows), you might need to adapt some of those commands to your needs. - -Prerequisites --------------------------- - -1. Install required software - - * Linux - - * `Docker `_ - * `Compose `_ - - * Mac: - - * `Docker & Compose (Mac) `_ - * `pulseaudio (Doc) `_ - - * Windows: - - * `Docker & Compose (Win) `_ - * `pulseaudio (Win) `_ - -2. Pull the Jukebox repository: ``git clone https://github.com/MiczFlor/RPi-Jukebox-RFID.git`` - - -3. Create a jukebox.yaml file - - * Copy the ``./resources/default-settings/jukebox.default.yaml`` to ``./shared/settings`` and - rename the file to ``jukebox.yaml``. - - ``$ cp ./resources/default-settings/jukebox.default.yaml ./shared/settings/jukebox.yaml`` - - - * Override/Merge the values from the following - `Override file - `_ - in your ``jukebox.yaml``. - -4. Change directory into the ``./RPi-Jukebox-RFID/shared/audiofolders`` and copy a set of MP3 files into this folder (for more fun when testing). - -Run development environment ------------------------------- - -In contrary to how everything is set up on the Raspberry Pi, it's good practice to isolate different components in -different Docker images. They can be run individually or in combination. -To do that, we use ``docker compose``. - -Linux -^^^^^^^ - -Make sure you don't use ``sudo`` to run your ``docker compose``. Check out Docker's `post-installation guide ` -for more information. - -.. code-block:: bash - - // Build Images - $ docker compose -f docker/docker-compose.yml -f docker/docker-compose.linux.yml build - - // Run Docker Environment - $ docker compose -f docker/docker-compose.yml -f docker/docker-compose.linux.yml up - - // Shuts down Docker containers and Docker network - $ docker compose -f docker/docker-compose.yml -f docker/docker-compose.linux.yml down - - -The docker linux setup tries to mirror the current users pulseaudio socket from ``$XDG_RUNTIME_DIR/pulse/native`` to the containers ``mpd`` and ``jukebox``. -If your pulseaudio socket is in another place, adjust path in docker/docker-compose.linux.yml. You can find out the socket path with the command ``pactl info``. -To access the socket, the user inside the docker containers also must have the same UID as the user running docker. You can find out your UID by running ``id -u``. If your UID deviates from the default UID 1000, please run ``export UID=$(id -u)`` prior to any docker commands. - -Mac -^^^^^ - -Remember, pulseaudio is a prerequisite. `Follow these instructions `_ -for Mac hosts. - -.. code-block:: bash - - // Build Images - $ docker compose -f docker/docker-compose.yml -f docker/docker-compose.mac.yml build - - // Run Docker Environment - $ docker compose -f docker/docker-compose.yml -f docker/docker-compose.mac.yml up - - // Shuts down Docker containers and Docker network - $ docker compose -f docker/docker-compose.yml -f docker/docker-compose.mac.yml down - -Windows -^^^^^^^^^^^ - -#. Download `pulseaudio `_ -#. Uncompress somewhere in your user folder -#. Edit ``$INSTALL_DIR/etc/pulse/default.pa`` -#. Add the following line - - .. code-block:: bash - - load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1 - -1. Edit ``$INSTALL_DIR/etc/pulse//etc/pulse/daemon.conf``, find the following line and change it to: - - .. code-block:: bash - - exit-idle-time = -1 - -1. Execute ``$INSTALL_DIR/bin/pulseaudio.exe`` -1. Run ``cocker-compose`` - -.. code-block:: bash - - // Build Images - $ docker compose -f docker/docker-compose.yml build - - // Run Docker Environment - $ docker compose -f docker/docker-compose.yml up - - // Shuts down Docker containers and Docker network - $ docker compose -f docker/docker-compose.yml down - -Test & Develop ---------------------- - -The Dockerfile is defined to start all Phoniebox related services. - -Windows: Open `host.docker.internal:3000 `_ in your browser to see the web application. -Linux / Mac: Open `http://localhost:3000 `_ in your browser to see the web application. - - -While the ``webapp`` container does not require a reload while working on it (hot-reload is enabled), -you will have to restart your ``jukebox`` container whenever you make a change (in the Python code). -Instead of stopping and starting the ``docker compose`` command, you can individually restart your -``jukebox`` container. Update the below path with your specific host environment. - -.. code-block:: bash - - $ docker compose -f docker/docker-compose.yml -f docker/docker-compose.[ENVIRONMENT].yml restart jukebox - -Known issues ----------------- - -The docker environment only exists to make development easier and possible without a physical device. It won't -replace it though. Therefore, we currently accept certain issues related to the individual Docker containers. -Here is a list of known errors or weird behaviour which you can easily ignore unless they prevent you from progressing. -If would be of course useful to get rid of them, but currently we make a trade-off between a development environment and -solving the specific details. - -``mpd`` container -^^^^^^^^^^^^^^^^^^ - -When starting the ``mpd`` container, you will see the following errors. You can ignore them, MPD will run. - -.. code-block:: bash - - mpd | exception: bind to '0.0.0.0:6600' failed (continuing anyway, because binding to '[::]:6600' succeeded): Failed to bind socket: Address already in use - mpd | exception: Failed to open '/root/.config/mpd/database': No such file or directory - mpd | exception: RTIOThread could not get realtime scheduling, continuing anyway: sched_setscheduler failed: Operation not permitted - mpd | avahi: Failed to create client: Daemon not running - - -You might also notice the following errors after the ``mpd`` Docker ran for a while. Specifically the first error -could fill up your console, sometimes it stops with the second error message. It's not a problem, sound continues to -work. As a side effect, your CPU usage increases. Just kill the process and restart. - -.. code-block:: bash - - mpd | alsa_mixer: snd_mixer_handle_events() failed: Input/output error - mpd | exception: Failed to read mixer for 'My ALSA Device': snd_mixer_handle_events() failed: Input/output error - - -``jukebox`` container -^^^^^^^^^^^^^^^^^^^^^^ - -Many features of the Phoniebox are based on the Raspberry Pi hardware. This hardware can't be mocked in a virtual Docker -environment. As a result, a few plugins like RFID, GPIO or CPU temperature will throw errors because they can't start -successfully. Unless you want to develop such plugins, you will be able to ignore these errors. The plugin system is built in a way -that the Jukebox daemon will come up. If you want to develop plugins that require hardware support, you will have to -work on the hardware directly. - -Typical errors and following exceptions to be ignored in the Docker ``jukebox`` container are: - -.. code-block:: bash - - jukebox | 277:utils.py - jb.utils - MainThread - ERROR - CalledProcessError: Command 'git log --pretty='%h [%cs] %s %d' -n 1 --no-color' returned non-zero exit status 128. - jukebox | 287:utils.py - jb.utils - MainThread - ERROR - CalledProcessError: Command 'git describe --tag --dirty='-dirty'' returned non-zero exit status 128. - jukebox | 634:plugs.py - jb.plugin - MainThread - ERROR - Ignoring failed package load finalizer: 'rfid.finalize()' - jukebox | 635:plugs.py - jb.plugin - MainThread - ERROR - Reason: FileNotFoundError: [Errno 2] No such file or directory: '/home/pi/RPi-Jukebox-RFID/shared/settings/rfid.yaml' - ... - jukebox | 171:__init__.py - jb.host.lnx - MainThread - ERROR - Error reading temperature. Canceling temperature publisher. FileNotFoundError: [Errno 2] No such file or directory: '/sys/class/thermal/thermal_zone0/temp' - ... - jukebox | 319:server.py - jb.pub.server - host.timer.cputemp - ERROR - Publish command from different thread 'host.timer.cputemp' than publisher was created from 'MainThread'! - - - -Appendix -------------- - -Individual Docker Image -^^^^^^^^^^^^^^^^^^^^^^^^ - -Run an individual Docker container, e.g. ``jukebox``. Similarly you could run ``mpd`` or ``webapp``. - -The following command can be run on a Mac. - -.. code-block:: bash - - $ docker compose -f docker/docker-compose.yml -f docker/docker-compose.mac.yml build jukebox - $ docker compose -f docker/docker-compose.yml -f docker/docker-compose.mac.yml run --rm --name jukebox jukebox - -Resources -^^^^^^^^^^^ - -**Mac** - -* https://stackoverflow.com/questions/54702179/how-to-access-mac-os-x-microphone-inside-docker-container -* https://stackoverflow.com/questions/40136606/how-to-expose-audio-from-docker-container-to-a-mac -* https://github.com/jessfraz/dockerfiles/blob/master/pulseaudio/Dockerfile - -**Windows** - -* https://stackoverflow.com/questions/52890474/how-to-get-docker-audio-and-input-with-windows-or-mac-host# -* https://arnav.jain.se/2020/enable-audio--video-in-docker-container/ -* https://x410.dev/cookbook/wsl/enabling-sound-in-wsl-ubuntu-let-it-sing/ -* https://research.wmz.ninja/articles/2017/11/setting-up-wsl-with-graphics-and-audio.html - -**Audio** - -* https://github.com/mviereck/x11docker/wiki/Container-sound:-ALSA-or-Pulseaudio -* https://mpd.fandom.com/wiki/PulseAudio -* https://stmllr.net/blog/streaming-audio-with-mpd-and-icecast2-on-raspberry-pi/ - -**MPD** - -* https://stmllr.net/blog/streaming-audio-with-mpd-and-icecast2-on-raspberry-pi/ -* https://github.com/Tob1asDocker/rpi-mpd -* https://github.com/vimagick/dockerfiles/tree/master/mpd - -**ZMQ** - -* https://codeblog.dotsandbrackets.com/using-zeromq-with-docker/ diff --git a/docs/sphinx/featurelist.rst b/docs/sphinx/featurelist.rst deleted file mode 100644 index bc3769e43..000000000 --- a/docs/sphinx/featurelist.rst +++ /dev/null @@ -1,313 +0,0 @@ -.. |[X]| unicode:: 0x2611 -.. |[ ]| unicode:: 0x2610 - -Feature Status -**************** - -**This is where we are in a nutshell:** Playing music from local folders via RFID trigger. -We also built a new WebUI to control the Jukebox from a browser. - -The are a few things that are specifically not integrated yet: playing streams, podcasts or Spotify. - -In the following is the currently implemented feature list in more detail. It also shows some of the shortcomings. -However the list is *not complete in terms of planned features*, -but probably **reflects more of where work is currently being put into**. - -**For new contributors:** If you want to port a feature from version 2.X or implement a new feature, contact us. Open an issue -or join us on in the chat room. You may pick topic marked as open below, but also any other topic missing in below list. -As mentioned, that list is not complete in terms of open features. Check the -`Contribution guide `_. -Topics marked *in progress* are already in the process of implementation by community members. - -.. contents:: - -Jukebox Core App -------------------- - -Base -^^^^^^^^ - -* |[X]| Clean up of surplus files -* |[X]| Host interface (shutdown, reboot) -* |[X]| Temperature getter - - * |[X]| Timer + Publisher - -* |[X]| RPi is_throttled getter - - * |[X]| Decode hex value to readable string (check version 2.x mqtt as reference?) - * |[X]| Timer + Publisher - -* |[X]| Git hash log information - - * |[X]| Log and publish this! - -* |[X]| Version number getter (Version number should be stored in a python file) - - * |[X]| Log and publish this - -* |[X]| Exit via RPC -* |[X]| Service restart via RPC - - * |[X]| Check if really running as a service - -* |[X]| Storage space getter / publisher (shutil.disk_usage) -* |[X]| Getter for error logs to show in WebUI - - * Get file location from FileHandlers (files may be stale!) - * Logger might be disabled or not connected - -* |[ ]| Enable/Disable debug logging from RPC -* |[X]| Publisher of errors (specialized logger handler) - - * This is a configurable logger handler in logger.yaml - -* |[X]| Basic Logging Config should enable Publisher stream handler -* |[ ]| Disable Console Stream Handler (or set to warning) when running as a service -* |[X]| Log & publish start time -* |[ ]| Method to change configuration through WebUI - - * The difficulty lies bringing the running Jukebox to accept the changes. There probably won't be a catch all solution - but rather a custom implementation for a select few features - -* |[X]| Strategy to post config changes via PubSub: Must be taken care of by the setter function modifying the property - - -Via RPC -^^^^^^^^ - -* |[X]| List of loaded / failed plugins -* |[X]| card action reference -* |[X]| Help command (available commands) - - * which basically is a plugin reference - -* |[X]| Simplified alias definitions for often used RPC commands (for RFID, GPIO, etc) - - * |[ ]| Port all previous commands - * |[X]| Reference file write-out: now also included in Sphinx documentation - * |[ ]| Export available alias definitions to RPC - * |[ ]| Base quick select on yaml file (*in progress*) - - * or write a yaml file as artifact which contains all the meta information about the functions as well? - * or include a ``get_signature`` function that returns the meta information for a given alias - -Config handler -^^^^^^^^^^^^^^^^^^^ - -* |[X]| While saving config to disk: local file change detection -* |[X]| cfghandler creates setndefault() at arbitrary depth - -ZMQ Publisher -^^^^^^^^^^^^^^^^^ - -* |[X]| Last Value Cache -* |[X]| Subscriber detection and initial status update -* |[X]| Port configuration option (WS and/or TCP) -* |[ ]| Callback registration option for plugin on topic send - - * How to interact with threads? - -Playback -^^^^^^^^^^^^^^^^^ - -* |[X]| Playlist generator - - * |[X]| Local folders - - * |[X]| Non-recursive folder play - * |[X]| Recursive folder play - - * |[X]| Podcast - * |[X]| Livestreams - * |[X]| NEW: Playback of m3u playlists (e.g. folder.m3u) ? - -* |[ ]| Folder configuration (*in progress*) - - * |[ ]| `Reference `_ - * |[ ]| Resume: Save and restore position (how interact with shuffle?) - * |[ ]| Single: Enable mpc single - * |[ ]| Shuffle: Enable mpc random (not shuffle) - - * Rename to random, as this is mpc random - - * |[ ]| Loop: Loop playlist - -MPD Player -^^^^^^^^^^^^^^^^^ - -* |[ ]| Thread safety for status information / configuration (*in progress*) -* |[ ]| Differential status post (*in progress*) -* |[ ]| Second swipe option setter via RPC (*in progress*) -* |[ ]| Before every music lib update, player should check user rights (not only after start-up) - -RFID -^^^^^^^^^^^^^^^^^ - -* |[X]| Test with Reader disabled -* |[X]| Start-up behaviour with un-configured Reader -* |[X]| Command card -> is now parameter ignore_same_id_delay -* |[X]| Revised RFID reader user-query setup script - - * |[ ]| Ask for place option - -* |[ ]| Enable config flag ? -* |[X]| Place not swipe / Timer thread - - * |[X]| Configurable card removal action - -* |[X]| Readers support - - * |[X]| USB (e.g. Neuftech) - * |[X]| RDM6300 - * |[X]| MFRC522 - * |[X]| RC532 - * |[X]| Multi-reader support - * |[X]| GUI Fake Reader for Development - * |[ ]| PC/SC Cards (what actually is this?) - -* |[X]| Publish RFID Card ID via PubSub - - * Needs to be thread safe - -* |[X]| Card reference IF via RPC - -* |[X]| Second Swipe Options -> must be part of player control (partially broken at the moment) - - * Freely configurable with an RPC call - * Ignore (nothing) - * Toggle Pause/Play - * Skip to next track - * Re-start playlist - -Cards -^^^^^^^^^^^^^^^^^ - -* |[ ]| Write a simplified card summary to - - * |[ ]| file - * |[X]| RPC - -* |[ ]| Card assignment function for WebUI - - * |[X]| Via RPC command alias definitions - * |[ ]| Full custom RPC call - -* |[X]| Remove card - -Timer -^^^^^^^^^^^^^^^ - -* |[X]| Shutdown timer -* |[X]| Play stop timer -* |[X]| Shutdown timer volume reduction - - * Decreases volume every x min until zero, then shuts down - * Needs to be cancelable - -* |[X]| Publish mechanism of timer status -* |[X]| Change multitimer function call interface such that endless timer etc wont pass the `iteration` kwarg -* |[ ]| Make timer settings persistent -* |[ ]| Idle timer - - * This needs clearer specification: Idle is when no music is playing and no user interaction is taking place - * i.e. needs information from RPC AND from player status. Let's do this when we see a little clearer about Spotify - - - -Volume -^^^^^^^^^^^^^^^^^ - -* |[X]| Jingle playback volume as fixed value in config -* |[X]| Default volume setting after boot-up -* |[X]| Max Volume -* |[X]| PulseAudio integration with event handler -* |[X]| Bluetooth support -* |[X]| Automatic audio sink toggle - - * |[ ]| Callbacks for audio sink change - -GPIO -^^^^^^^^^^^^^^^^^ - -* |[X]| All done! Read the docs at :ref:`userguide/gpioz:GPIO Recipes`! -* |[ ]| USB Buttons: It's a different category as it works similar to the RFID cards (in progress) - -WLAN -^^^^^^^^^^^^^^^^^ - -* |[X]| Ad-hoc WLAN Hot spot -* |[X]| IP address read-out - -Spotify -^^^^^^^^^^^^^^^^^ - -* |[ ]| Everything - -Others -^^^^^^^^^^^^^^^^^ - -* |[ ]| MQTT -* |[ ]| Record and Playback using a Mic -* |[ ]| Dot Matrix Displays - -Start-up stuff -^^^^^^^^^^^^^^^^^ - -* |[X]| check music folder permissions -* |[X]| mpc update / (mpc rescan) -* |[X]| sudo iwconfig wlan0 power off (need to be done after every restart) -* |[X]| Optional power down HDMI circuits: /usr/bin/tvservice -o - - -Debug Tools --------------- - -* |[X]| Publishing Sniffer - - * |[ ]| Update mode vs linear mode ? - -* |[X]| RPC command line client - - * |[X]| with tab-completion and history - - -WebUI --------------- - -* |[X]| Playback Control -* |[X]| Cover Art -* |[X]| Register cards / Delete cards -* |[X]| Shutdown button -* |[ ]| Settings configuration page -* |[ ]| System information page - - * |[ ]| Configure (one or multiple) WLANs - * |[X]| Enable/Disable Auto-Hotspot - -* |[X]| ``run_npm_build`` script - - * |[X]| Must consider ``export NODE_OPTIONS=--max-old-space-size=512`` - - -Installation Procedure ------------------------ - -* |[X]| Single call installation script -* |[X]| Query for settings vs. automatic version -* |[X]| IPQoS in SSH config -* |[X]| Separate static IP and IPv6 disable -* |[ ]| For all system config file changes, check prior to modification, if modification already exists - - -Documentation --------------- - -* |[X]| Sphinx / Restructured Text tool flow -* |[ ]| What is the Phoniebox -* |[X]| Artifacts: Generate artifacts (on command line switch only) for - - * |[X]| loaded plugins and rpc command aliases (to sphinx and shared/artifcats) - * |[X]| rpc command aliases (to sphinx and shared/artifcats) - -* |[ ]| How to: Write a plugin diff --git a/docs/sphinx/index.rst b/docs/sphinx/index.rst deleted file mode 100644 index a83777673..000000000 --- a/docs/sphinx/index.rst +++ /dev/null @@ -1,57 +0,0 @@ -.. RPi Jukebox for Kids documentation master file, created by - sphinx-quickstart on Sun Sep 26 15:26:31 2021. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to RPi Jukebox RFID's documentation! -================================================ - -.. include:: primer.rst - -.. toctree:: - :maxdepth: 2 - :caption: Getting Started: - - featurelist - install - migration - issues - -.. toctree:: - :maxdepth: 2 - :caption: User Guide: - - userguide/concepts - userguide/system - userguide/configuration - userguide/audio - userguide/troubleshooting - rfid/rfid - userguide/gpioz - userguide/bluetooth_audio_buttons - userguide/rpc_commands - userguide/rpc_command_reference - userguide/rpc_command_alias_reference - userguide/carddatabase - userguide/autohotspot - userguide/sync_rfidcards - - -.. toctree:: - :maxdepth: 2 - :caption: Developer Reference: - - developer/developer_issues.rst - developer/coreapps - developer/development_environment - api/api.rst - - - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/docs/sphinx/install.rst b/docs/sphinx/install.rst deleted file mode 100644 index 948c79c42..000000000 --- a/docs/sphinx/install.rst +++ /dev/null @@ -1,98 +0,0 @@ -Installing Phoniebox future3 -============================ - -Install Raspberry Pi OS Lite -------------------------------------------- - -.. important:: Currently, the installation does only work on Raspberry Pi's with ARMv7 and ARMv8 architecture, so 2, 3 and 4! - Pi 1 and Zero's are currently unstable and will require a bit more work! - -Before you can install the Phoniebox software, you need to prepare your Raspberry Pi. - -1. Connect a Micro SD card to your computer (preferable an SD card with high read throughput) -2. `Download `_ - the `Raspberry Pi Imager `_ and open it -3. Select **Raspberry Pi OS Lite (32-bit)** (without desktop environment) as the operating system. future3 does not support 64bit kernels (``aarch64``). You can use the settings menu of the Raspberry Pi Imager to configure SSH and WiFi in a more userfriendly way, or do it manually as described in the next step. In case you already have a 64bit system installed, `you can fix the issue like this `_. -4. Select your Micro SD card (your card will be formatted) -5. Click *Write* -6. Wait for the imaging process to be finished (it'll take a few minutes) - - -Pre-boot preparation -------------------------------------------- - -You will need a terminal, like PuTTY for Windows or the Terminal app for Mac to proceed with the next steps. - -1. Open a terminal of your choice. -2. Insert your card again if it has been ejected automatically. -3. Navigate to your SD card e.g., ``cd /Volumes/boot`` for Mac or ``D:`` for Windows. -4. Enable SSH by adding a simple file. - - .. code-block:: bash - - $ touch ssh - -5. Set up your Wifi connection. - - *Mac* - - .. code-block:: bash - - $ nano wpa_supplicant.conf - - *Windows* - - .. code-block:: bash - - D:\> notepad wpa_supplicant.conf - -6. Insert the following content, update your country, Wifi credentials and save the file. - - .. code-block:: bash - - country=DE - ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev - update_config=1 - - network={ - ssid="network-name" - psk="network-password" - } - -7. Eject your SD card and insert it into your Raspberry Pi. -8. Start your Raspberry Pi by attaching a power supply. -9. Login into your Raspberry Pi, username is ``pi`` and password is ``raspberry``. - If ``raspberrypi.local`` does not work, find out your Raspberry Pi's IP address from your router. - -Install Phoniebox software -------------------------------------------- - -Run the following command in your SSH terminal and follow the instructions - -.. code-block:: bash - - cd; bash <(wget -qO- https://raw.githubusercontent.com/MiczFlor/RPi-Jukebox-RFID/future3/main/installation/install-jukebox.sh) - -This will get the latest stable release from the branch future3/main. -To install directly from a specific branch and/or a different repository -specify the variables like this: - -.. code-block:: bash - - cd; GIT_USER='MiczFlor' GIT_BRANCH='future3/develop' bash <(wget -qO- https://raw.githubusercontent.com/MiczFlor/RPi-Jukebox-RFID/future3/develop/installation/install-jukebox.sh) - - -This will switch directly to the specified feature branch during installation. - -.. attention:: For all branches *except* the current Release, you will need to build the Web App locally on the Pi. - This is not part of the installation process due to memory limitation issues. - See :ref:`developer/development_environment:Steps to install`. - - - -If you suspect an error you can monitor the installation-process with - -.. code-block:: bash - - cd; tail -f INSTALL-.log - diff --git a/docs/sphinx/issues.rst b/docs/sphinx/issues.rst deleted file mode 100644 index d38d3ce5c..000000000 --- a/docs/sphinx/issues.rst +++ /dev/null @@ -1,15 +0,0 @@ -Known Issues -****************** - -Browsers ----------- - -The Web UI will **not** work with Firefox, due to an issue with websockets and pyzmq. Please use a different -browser for now. - -Configuration --------------- -In ``jukebox.yaml`` (and all other config files): do not use relative paths with ``~/some/dir``. -Always use entire explicit path, e.g. ``/home/pi/some/dir``. - -**Sole** exception is in playermpd.mpd_conf. diff --git a/docs/sphinx/migration.rst b/docs/sphinx/migration.rst deleted file mode 100644 index 8d3599953..000000000 --- a/docs/sphinx/migration.rst +++ /dev/null @@ -1,55 +0,0 @@ -Updating -************** - -Updating from Version 3.0 to 3.1 ---------------------------------------- - -There are a number of significant changes to the overall system setup, which require a fresh install. Notable changes in this respect include: - - #. Shift system setup to PulseAudio - #. Run MPD as user-local service - #. Run Jukebox Daemon as user local service - -.. important:: You need re-install on a fresh SD card! - A git pull procedure as described below will not work! - - -Updating your Jukebox Version 3 -------------------------------------- - -Things on Version 3 are moving fast and you may want to keep up with recent changes. Since we are in Alpha Release stage, -a fair number of fixes are expected to be committed in the near future. - -You will need to do three things to update your version from develop (or the next release candidate version) - -#. Pull the newest code base from Github -#. Check for new entries in the configuration -#. Re-build the WebUI - -.. code-block:: bash - - # Switch to develop (if desired) - $ git checkout future3/develop - - # Get latest code - $ git pull - - # Check if new (mandatory) options appeared in jukebox.yaml - # with your favourite diff tool and merge them - $ diff shared/settings/jukebox.yaml resources/default-settings/jukebox.default.yaml - - $ cd src/webapp - $ ./run_rebuild.sh - - -Migration Path from Version 2 -------------------------------------- - -There is no update path coming from Version 2.x of the Jukebox. -You need to do a fresh install of Version 3 on a fresh Raspian Bullseye image. - -.. important:: Do start with a fresh SD card image! - -Do not just pull the future3 branch into you existing Version 2.x directory. -Do not run the installer on an system that had Version 2.x running before on it. -Stuff has changed too much to make this feasible. diff --git a/docs/sphinx/requirements.txt b/docs/sphinx/requirements.txt deleted file mode 100644 index e169c2c69..000000000 --- a/docs/sphinx/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -# These are just the additional RTD-specific requirements -readthedocs-sphinx-search - -# Install packages for documentation build from package repository -# that are installed on the PI via APT -RPi.GPIO -gpiozero<2.0.0;python_version<'3.8' -gpiozero;python_version>='3.8' diff --git a/docs/sphinx/requirements_pyzmq.txt b/docs/sphinx/requirements_pyzmq.txt deleted file mode 100644 index e2a37a6e1..000000000 --- a/docs/sphinx/requirements_pyzmq.txt +++ /dev/null @@ -1,5 +0,0 @@ -# For operation of the Jukebox, -# ZMQ must be compiled from sources due to Websocket support -# When just building the docs, the regular ZMQ package is sufficient - -pyzmq diff --git a/docs/sphinx/rfid/basics.rst b/docs/sphinx/rfid/basics.rst deleted file mode 100644 index 7bc49ddeb..000000000 --- a/docs/sphinx/rfid/basics.rst +++ /dev/null @@ -1,91 +0,0 @@ -Basics ---------- - -Cards placed on the reader trigger an action. An action may be any callable plugin function through the RPC with any arguments. -Typically, this would be "play some folder", but can also be "activate shutdown timer", or "increase volume". -This is configured in the :ref:`userguide/carddatabase:Card Database`. - -You may configure a single or even multiple parallel readers (of different or identical types). - -Successive card swipes are suppressed to avoid bouncing effects. This behavior can be deactivated for individual cards. - -Reader Types ------------- - -place-capable: - Some readers give a single event signal when the card is placed on the reader. This is sufficient - to build a fully-featured Jukebox. Other readers give a continuous signal. They allow both card placements - and card removals. This can be used to play the Jukebox when a card is placed and to pause it when it's removed. - - Generally, **not** all :ref:`USB-based RFID readers ` are place-capable. - - The known place-capable readers are :ref:`RDM6300 `, - :ref:`MFRC522 ` or - :ref:`PN532 `. - -Frequency: - Readers operate on one of two different frequencies: 125kHz or 13.56 MHz. - Make sure to buy compatible cards, RFID stickers or key fobs working with the same frequency as the reader. - -Reader Configuration ------------------------ - -During the installation process, you can already configure a RFID reader. To manually configure RFID reader(s), -:ref:`please run the tool ` ``src/jukebox/run_register_rfid_reader.py``. - -It will generate a reader configuration file at ``shared/settings/rfid.yaml``. -You can re-run the tool to change the settings any time. - -Some options are not covered by the tool. You may change the file manually. - -.. code-block:: yaml - - rfid: - readers: - read_00: - module: fake_reader_gui - config: .... - same_id_delay: float|integer - log_ignored_cards: true|false - place_not_swipe: - enabled: true|false - card_removal_action: - alias: pause - -For each reader, there is an entry ``read_XX``. - -module: - Indicates the Python package used for this reader. Filled by the RFID configuration tool. - -config: - Filled by the - :ref:`RFID configuration tool ` ``src/jukebox/run_register_rfid_reader.py`` - based on default values and user input. - After running the tool, you may manually change some settings here, as not everything can - be configured through the tool. Note that re-running the tool will completely rewrite the - configuration file. - -same_id_delay: float | integer - Minimum delay in seconds between 2 card detections before triggering a new action. This - is to prevent double triggering or bouncing. - -place_not_swipe: true | false - For place-capable RFID readers enable dual action mode: - a start action (e.g. playing) on card placement and card removal action (e.g. pause). - -card_removal_action: Dictionary - Executes the given function on card removal. Only relevant if place_not_swipe is true. The action is identical for all cards read on - that reader. The removal-action can be set to ignored on a card-by-card basis. - More on card action configurations in :ref:`userguide/rpc_commands:RPC Commands`. - - Developer's note: The reason for a unique removal action for all cards is that card triggering and card removal are happening - in two separate threads. Removal needs to be in a time-out thread. Thus, we would need to transport information from - one thread to another. This can be done of course but is not implemented (yet). Ignoring card removal is much easier and works for now. - -log_ignored_cards: true | false - Log all cards that are ignored due to same_id_delay. This is a option for developers. Don't use it unless you need it for debugging as it has - the potential to spam your log files. - -Second Swipe - Looking for 'Second Swipe' option? That is part of the Player configuration and not part of the RFID configuration, as - the 'Second Swipe' action needs to take into account the player state, which can also be altered through the WebUI. diff --git a/docs/sphinx/rfid/genericusb.rst b/docs/sphinx/rfid/genericusb.rst deleted file mode 100644 index 03ef2c4ef..000000000 --- a/docs/sphinx/rfid/genericusb.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../../src/jukebox/components/rfid/hardware/generic_usb/README.rst \ No newline at end of file diff --git a/docs/sphinx/rfid/mfrc522_spi.rst b/docs/sphinx/rfid/mfrc522_spi.rst deleted file mode 100644 index ac57bda26..000000000 --- a/docs/sphinx/rfid/mfrc522_spi.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../../src/jukebox/components/rfid/hardware/rc522_spi/README.rst diff --git a/docs/sphinx/rfid/mock_reader.rst b/docs/sphinx/rfid/mock_reader.rst deleted file mode 100644 index 8acb618ec..000000000 --- a/docs/sphinx/rfid/mock_reader.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../../src/jukebox/components/rfid/hardware/fake_reader_gui/README.rst diff --git a/docs/sphinx/rfid/pn532_i2c.rst b/docs/sphinx/rfid/pn532_i2c.rst deleted file mode 100644 index 849fc6e05..000000000 --- a/docs/sphinx/rfid/pn532_i2c.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../../src/jukebox/components/rfid/hardware/pn532_i2c_py532/README.rst \ No newline at end of file diff --git a/docs/sphinx/rfid/rdm6300.rst b/docs/sphinx/rfid/rdm6300.rst deleted file mode 100644 index e84643e77..000000000 --- a/docs/sphinx/rfid/rdm6300.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../../src/jukebox/components/rfid/hardware/rdm6300_serial/README.rst \ No newline at end of file diff --git a/docs/sphinx/rfid/rfid.rst b/docs/sphinx/rfid/rfid.rst deleted file mode 100644 index ad7c00d24..000000000 --- a/docs/sphinx/rfid/rfid.rst +++ /dev/null @@ -1,14 +0,0 @@ ----------------------- -RFID Readers ----------------------- - -.. toctree:: - :maxdepth: 2 - - basics - genericusb - rdm6300 - mfrc522_spi - pn532_i2c - mock_reader - template diff --git a/docs/sphinx/rfid/template.rst b/docs/sphinx/rfid/template.rst deleted file mode 100644 index 70d01622b..000000000 --- a/docs/sphinx/rfid/template.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../../src/jukebox/components/rfid/hardware/template_new_reader/README.rst \ No newline at end of file diff --git a/docs/sphinx/userguide/audio.rst b/docs/sphinx/userguide/audio.rst deleted file mode 100644 index 51b7b9a40..000000000 --- a/docs/sphinx/userguide/audio.rst +++ /dev/null @@ -1,152 +0,0 @@ -Audio Configuration -==================== - -The Jukebox supports 2 audio outputs, primary and secondary. The **primary output** is the default output and must -be available after system boot. This will typically be your sound card or the Pi's built-in headphone output. - -The **secondary output** is an optional alternative output where the audio stream can be routed to. -Stream transfer happens on user input or automatically on the connection of an audio device. -This is mainly targeted at Bluetooth Headsets/Speakers. - -Audio outputs run via PulseAudio and the basic configuration should be easy. -There is a :ref:`configuration tool`, -to setup the configuration for the Jukebox Core App. - -To set up the audio - - #. Follow the setup steps according to your sound card - #. Check that the sound output works :ref:`as described below` - #. Run the the tool :ref:`developer/coreapps:run_configure_audio.py` - #. :ref:`Fine-tune audio parameters` - -Checking system sound output -------------------------------- - -Run the following steps in a console: - -.. code-block:: bash - - # Check available PulseAudio sinks - $ pactl list sinks short - 0 alsa_output.platform-soc_sound.stereo-fallback module-alsa-card.c s16le 2ch 48000Hz - 1 bluez_sink.C4_FB_20_63_CO_FE.a2dp_sink module-bluez5-device.c s16le 2ch 44100Hz - - # Set the default sink (this will be reset at reboot) - $ pactl set-default-sink sink_name - - # Check default sink is correctly set - $ pactl info - .... - # Check volume level (exit with ESC) - $ alsamixer - - # Play a sound - $ paplay /usr/share/sounds/alsa/Front_Center.wav - - # This must also work when using an ALSA device - $ aplay /usr/share/sounds/alsa/Front_Center.wav - -You can also try different PulseAudio sinks without setting the default sink. In this case the volume is the last used -volume level for this sink: - -.. code-block:: bash - - $ paplay -d sink_name /usr/share/sounds/alsa/Front_Center.wav - - -Bluetooth ------------ - -Bluetooth setup consists of three steps - - #. Pair and connect your Bluetooth device - #. Check the output works - #. Re-run the config tool - -To pair and connect, follow these steps. This will be a one-time setup. - -.. code-block:: bash - - $ bluetoothctl - Agent registered - [CHG] Controller B8:27:EB:44:C4:33 Pairable: yes - #### Put your headset into pairing mode - [bluetooth]# scan on - Discovery started - #### Wait a few seconds for your device to appear - .... - [NEW] Device C4:FB:20:63:CO:FE PowerLocus Buddy - .... - [bluetooth]# scan off - .... - [bluetooth]# pair C4:FB:20:63:CO:FE - .... - Pairing successful - .... - [bluetooth]# trust C4:FB:20:63:CO:FE - .... - [bluetooth]# connect C4:FB:20:63:CO:FE - .... - [PowerLocus Buddy]# exit - - -Wait for a few seconds and then with ``$ pactl list sinks short``, check wether the Bluetooth device shows up as an output. -Its name usually looks like this: ``bluez_sink.C4_FB_20_63_CO_FE.a2dp_sink``. - -Run through steps in `Checking system sound output` to check wether the output is working or not. -If it does not work immediately, turn your headset off and on to force a reconnect. - -Rerun the config tool to register the Bluetooth device with the Jukebox core app as its secondary audio output. - -Additional options -------------------- - -For other audio configuration options, please look at the ``jukebox.yaml`` for now. - -Directly edit ``jukebox.yaml`` following the steps: :ref:`userguide/configuration:Best practice procedure`. - - -Developer Information ------------------------ - -The optional processing stages *Equalizer* and *Mono down mix* are realized by PulseAudio plugins. -The processing chain is - -.. code-block:: text - - player --> mono mix --> equalizer --> hardware sink - -Both plugins (if enabled) appear in the PulseAudio sinks - -.. code-block:: bash - - $ pactl list sinks short - ... - -Which means we can put any of these as sink into the jukebox configuration file (if there is any need). - -Mono down mix is enabled by the module ``module-remap-sink`` -for which `documentation and an example can be found here -`_. - -The equalizer is the PulseAudio module ``module-ladspa-sink`` with the `corresponding documentation -`_. - -This in turn loads a `LADSPA plugin `_. -The LADSPA plugin in the ``Eq10X2`` plugin of the `CAPS Library `_ -The CAPS library is available as linux package ``caps``. - -This is the same plugin which is used in the -`equalizer for pure ALSA `_ -configurations which is part of the linux package ``libasound2-plugin-equal``. - -You are, of course, free to modify the PulseAudio configuration to your needs. References - - #. `PulseAudio Documentation `_ - #. `PulseAudio Examples `_ - -In this case, run the configuration tool with below parameter to avoid touching the PulseAudio configuration file. - -.. code-block:: bash - - $ ./run_configure_audio.py --ro_pulse diff --git a/docs/sphinx/userguide/autohotspot.rst b/docs/sphinx/userguide/autohotspot.rst deleted file mode 100644 index 9156412b1..000000000 --- a/docs/sphinx/userguide/autohotspot.rst +++ /dev/null @@ -1,112 +0,0 @@ -Auto-Hotspot -************ - -The Auto-Hotspot function allows the Jukebox to switch between its connection between a known WiFi and an automatically -generated hotspot so that you can still access via SSH or Webapp. - -.. important:: Please configure the WiFi connection to your home access point before enabling these feature! - -To create a hotspot and allow clients to connect `hostapd` [1]_ and `dnsmasq` [2]_ - -How to connect --------------- - -When the Jukebox is not able to connect to a known WiFi it will create a hotspot named ``Phoniebox_Hotspot``. You will be -able to connect to this hotspot using the given password in the installation or the default password: ``PlayItLoud!`` - -Webapp -^^^^^^ - -After connecting to the ``Phoniebox_Hotspot`` you are able to connect to the webapp accessing the website `10.0.0.5 `_ - -ssh -^^^ - -After connecting to the ``Phoniebox_Hotspot`` you are able to connect via ssh to your Jukebox - -.. code-block:: bash - - ssh pi@10.0.0.5 - - -Changing basic configuration of the hotspot -------------------------------------------- - -The whole hotspot configuration can be found at ``/etc/hostapd/hostapd.conf``. - -The following parameters are relevant: - -* ``ssid`` for the displayed hotspot name -* ``wpa_passphrase`` for the password of the hotspot -* ``country_code`` the country you are currently in - -.. code-block:: bash - - $ cat /etc/hostapd/hostapd.conf - - #2.4GHz setup wifi 80211 b,g,n - interface=wlan0 - driver=nl80211 - ssid=Phoniebox_Hotspot - hw_mode=g - channel=8 - wmm_enabled=0 - macaddr_acl=0 - auth_algs=1 - ignore_broadcast_ssid=0 - wpa=2 - wpa_passphrase==PlayItLoud! - wpa_key_mgmt=WPA-PSK - wpa_pairwise=CCMP TKIP - rsn_pairwise=CCMP - - #80211n - Change GB to your WiFi country code - country_code=DE - ieee80211n=1 - ieee80211d=1 - -Disabling automatism --------------------- - -Auto-Hotspot can be enabled or disabled using the Webapp. - -.. important:: Disabling or enabling will keep the last state. - -Troubleshooting --------------------- - -Phoniebox is not connecting to the known WiFi -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The script will fall back to the hotspot so you still have some type of connection. - -Check your password in ``/etc/wpa_supplicant/wpa_supplicant.conf``. - -AutoHotspot functionality is not working -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -You can check the output of the script by running the following script: - -.. code-block:: bash - - $ sudo /usr/bin/autohotspot - -You need to add a new wifi network to the Raspberry Pi -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Because it is in Auto-Hotspot mode, you won't be able to scan for new wifi signals. - -You will need to add a new network to ``/etc/wpa_supplicant/wpa_supplicant.conf`` manually. Enter the following details -replacing mySSID and myPassword with your details. If your WiFi has a hidden SSID then include the line ``scan_ssid=1``. - -Resources ---------- - -`Raspberry Pi - Auto WiFi Hotspot Switch - Direct Connection `__ - ------------- - -References: - -.. [1] http://w1.fi/hostapd/ -.. [2] https://thekelleys.org.uk/dnsmasq/doc.html diff --git a/docs/sphinx/userguide/bluetooth_audio_buttons.rst b/docs/sphinx/userguide/bluetooth_audio_buttons.rst deleted file mode 100644 index b935edb36..000000000 --- a/docs/sphinx/userguide/bluetooth_audio_buttons.rst +++ /dev/null @@ -1,4 +0,0 @@ -Bluetooth audio buttons -************************* - -.. include:: ../../../src/jukebox/components/controls/bluetooth_audio_buttons/README.rst \ No newline at end of file diff --git a/docs/sphinx/userguide/carddatabase.rst b/docs/sphinx/userguide/carddatabase.rst deleted file mode 100644 index d0b40a903..000000000 --- a/docs/sphinx/userguide/carddatabase.rst +++ /dev/null @@ -1,94 +0,0 @@ -Card Database -***************** - -In the card database, an RPC command is assigned to every card. - -This RPC command is called every time when the card is swiped (or placed) on the reader. Every -RPC callable function can be called. See :ref:`userguide/rpc_commands:RPC Commands` for an introduction. - -The card database is stored in ``shared\settings\cards.yaml``. -Here are some examples for RPC command assignments to cards '0001' to '0003' using the alias option: - -.. important:: Card IDs **must** be strings! So, be sure to quote numbers! - -.. code-block:: yaml - - '0001': - # A RPC command using the alias definition without any arguments - # Here: pause playback - alias: pause - '0002': - # A RPC command using the alias definition with one arguments - # Here: Trigger music playback through the card interface - alias: play_card - args: [path/to/folder] - '0003': - # A RPC command using keyword arguments. Args and kwargs can also be mixed. - # Args and Kwargs translate directly into the function python call - # Some as in '0002' but using kwargs - alias: play_card - kwargs: - folder: path/to/folder - -.. note:: - * Remember card ids must be strings! So, quote them! - * *args* must be a **list** of arguments to be passed! Even if ony a single argument is passed. So, use *args: [value]*. - We try catch mis-uses but that might not always work. - -Additional options -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In addition to the RPC commands, these options may be specified for every card - -ignore_card_removal_action: true | false (default: false) - Only applies when using a place-capable reader and *place_not_swipe* is *true*. This option is ignored otherwise, - so it does not hurt. - - Do not execute card removal action, when this card is removed from the reader. Useful for command card, - that e.g. enable the shutdown timer - - .. code-block:: yaml - - '0004': - alias: timer_shutdown - ignore_card_removal_action: true - - -ignore_same_id_delay: true | false (default: false) - Override the ``same_id_delay`` parameter from the reader configuration for this card. - If true, the ``same_id_delay`` for this card is treated as 0. - This makes sense e.g., for an "increase volume" card in combination with a place-capable RFID reader. - As long as the card is placed on the reader, the volume is increased. - - .. note:: This parameter causes *ignore_card_removal_action* to be treated as true - - .. code-block:: yaml - - '0005': - alias: incr_volume - ignore_same_id_delay: true - ignore_card_removal_action: true - -Full RPC action specification -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -You have seen some examples card actions using the *alias* configuration. A full RPC action can also be specified -using the following syntax: - -.. code-block:: yaml - - '0006': - # Option 1: Omit the keyword 'alias' - # Here: Set the volume to level 12 - package: volume - plugin: ctrl - method: set_volume - args: [12] - '0007': - # Option 2: Set 'alias' to custom - # Here: Set the volume to level 12 - alias: custom - package: volume - plugin: ctrl - method: set_volume - args: [12] diff --git a/docs/sphinx/userguide/concepts.rst b/docs/sphinx/userguide/concepts.rst deleted file mode 100644 index 19d5d37e5..000000000 --- a/docs/sphinx/userguide/concepts.rst +++ /dev/null @@ -1,46 +0,0 @@ -Concepts -================================================ - -The Jukebox is based on three concepts. Don't worry we won't dive into all the juicy developer details (just yet). -But a rough understanding is important as an foundation to understand the configuration files. - -Plugin Interface ----------------- - -The core app is centered around a plugin concept. This serves three purposes: - - #. Dynamically load packages with additional functionality based on configuration files. - #. Initialize and close these packages at app start / close. This happens automatically in the background. Failing - packages (for any reason) are ignored during start-up. So when some functionality is not available, always - check the logs to ensure all packages have loaded successfully! See :ref:`userguide/troubleshooting:Troubleshooting`. - #. Register and present functions which can be called via the :ref:`userguide/concepts:Remote Procedure Call Server (RPC)` - -That's about what you need to know for the plugin concept. Developer detailed information -can be found here (TBD). - -Remote Procedure Call Server (RPC) --------------------------------------- - -The Remote Procedure Call (RPC) server allows to remotely trigger actions (e.g., from the Webapp) within the Jukebox core application. -Only Python functions registered by the plugin interface can be called. This -simplifies external APIs and let's us focus on the relevant user functions. - -Why should you care? Because we use the same protocol when triggering actions from other inputs like a card swipe, a -GPIO button press, etc. How that works is described in :ref:`userguide/rpc_commands:RPC Commands`. - -You will find a full list of RPC callable functions in :ref:`userguide/rpc_command_reference:RPC Command Reference` -and aliases for convinience in :ref:`userguide/rpc_command_alias_reference:RPC Command Alias Reference` - -For developers the details can be found here (TBD). We also have a tool to send RPC commands to the running Jukebox application: -:ref:`developer/coreapps:run_rpc_tool.py` - -Publishing Message Queue --------------------------- - -The Publishing Message Queue is the complimentary part to the RPC where the core application publishes its status and status updates. -As a user, you need not worry about it. - -If you want to interact with the Jukebox from your own application, this is where you get the current -state from. Details about the protocol can be found here (TBD). A sniffer tool exists which listens and prints the incoming -status messages: :ref:`developer/coreapps:run_publicity_sniffer.py`. - diff --git a/docs/sphinx/userguide/configuration.rst b/docs/sphinx/userguide/configuration.rst deleted file mode 100644 index ac40b16d7..000000000 --- a/docs/sphinx/userguide/configuration.rst +++ /dev/null @@ -1,43 +0,0 @@ -Jukebox Configuration -======================= - -The Jukebox configuration is managed by set of files located in ``../shared/settings``. -Some configuration changes can be made through the WebUI and take immediate effect. - -The majority of configuration options is only available by editing the config files - -*when the service is not running!* -Don't fear (overly), they contain commentaries. - -For several aspects we have :ref:`developer/coreapps:Configuration Tools` and detailed guides: - - * :ref:`userguide/audio:Audio Configuration` - * :ref:`RFID Reader Configuration` - -Even after running the tools certain aspects can only be changed by modifying the configuration files directly. - -Best practice procedure -------------------------- - -.. code-block:: bash - - # Make sure the Jukebox service is stopped - $ systemctl --user stop jukebox-daemon - - # Edit the file(s) - $ nano ./shared/settings/jukebox.yaml - - # Start Jukebox in console and check the log output (optional) - $ ./src/jukebox/run_jukebox.py - # and if OK, press Ctrl-C and restart the service - - # Restart the service - $ systemctl --user start jukebox-daemon - - -To try different configurations, you can start the Jukebox with a custom config file. -This could be useful if you want your Jukebox to only allow a lower volume when started -at night time when there is time to go to bed :-) - -.. code-block:: bash - - $./run_jukebox.py --conf ../path/to/custom/config.yaml diff --git a/docs/sphinx/userguide/gpioz.rst b/docs/sphinx/userguide/gpioz.rst deleted file mode 100644 index 5ba83d97a..000000000 --- a/docs/sphinx/userguide/gpioz.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../../src/jukebox/components/gpio/gpioz/README.rst \ No newline at end of file diff --git a/docs/sphinx/userguide/rpc_command_alias_reference.rst b/docs/sphinx/userguide/rpc_command_alias_reference.rst deleted file mode 100644 index e5dfc2cb5..000000000 --- a/docs/sphinx/userguide/rpc_command_alias_reference.rst +++ /dev/null @@ -1,188 +0,0 @@ -RPC Command Alias Reference -*************************** - - -.. |--| unicode:: U+2014 -.. |->| unicode:: U+21d2 - -.. py:function:: play_card(...) -> player.ctrl.play_card(folder: str, recursive: bool = False) - :noindex: - - **Play music folder triggered by card swipe** - - Main entry point for trigger music playing from RFID reader. Decodes second swipe options before playing folder content - - Checks for second (or multiple) trigger of the same folder and calls first swipe / second swipe action - accordingly. - - :param folder: Folder path relative to music library path - :param recursive: Add folder recursively - - .. note:: This function you'll want to use most often - -.. py:function:: play_album(...) -> player.ctrl.play_album(albumartist: str, album: str) - :noindex: - - **Play Album triggered by card swipe** - - Playback a album found in MPD database. - - All album songs are added to the playlist - The playlist is cleared first. - - :param albumartist: Artist of the Album provided by MPD database - :param album: Album name provided by MPD database - - .. note:: This function plays the content of a given album - -.. py:function:: play_single(...) -> player.ctrl.play_single(song_url) - :noindex: - - **Play a single song triggered by card swipe** - - - - .. note:: This function plays the content of a given song URL - -.. py:function:: play_folder(...) -> player.ctrl.play_folder(folder: str, recursive: bool = False) -> None - :noindex: - - **Play a folder URL triggered by card swipe** - - Playback a music folder. - - Folder content is added to the playlist as described by :mod:`jukebox.playlistgenerator`. - The playlist is cleared first. - - :param folder: Folder path relative to music library path - :param recursive: Add folder recursively - - .. note:: This function plays the content of a given folder URL - -.. py:function:: pause(...) -> player.ctrl.pause(state: int = 1) - :noindex: - - Enforce pause to state (1: pause, 0: resume) - - This is what you want as card removal action: pause the playback, so it can be resumed when card is placed - on the reader again. What happens on re-placement depends on configured second swipe option - - .. note:: This is what you want as card removal action for place capable readers - - Default actions modifiers - **ignore_card_removal_action** |--| True - -.. py:function:: next_song(...) -> player.ctrl.next() - :noindex: - - Play next track in current playlist - - Default actions modifiers - **ignore_card_removal_action** |--| True - -.. py:function:: prev_song(...) -> player.ctrl.prev() - :noindex: - - - - Default actions modifiers - **ignore_card_removal_action** |--| True - -.. py:function:: toggle(...) -> player.ctrl.toggle() - :noindex: - - Toggle pause state, i.e. do a pause / resume depending on current state - - Default actions modifiers - **ignore_card_removal_action** |--| True - -.. py:function:: set_volume(...) -> volume.ctrl.set_volume(volume: int) - :noindex: - - Set the volume (0-100) for the currently active output - - Default actions modifiers - **ignore_card_removal_action** |--| True - -.. py:function:: change_volume(...) -> volume.ctrl.change_volume(step: int) - :noindex: - - Increase/decrease the volume by step for the currently active output - - .. note:: For place-capable readers increment volume as long as card is on reader - - Default actions modifiers - **ignore_card_removal_action** |--| True - - **ignore_same_id_delay** |--| True - -.. py:function:: set_soft_max_volume(...) -> volume.ctrl.set_soft_max_volume(max_volume: int) - :noindex: - - Limit the maximum volume to max_volume for the currently active output - - Default actions modifiers - **ignore_card_removal_action** |--| True - -.. py:function:: toggle_output(...) -> volume.ctrl.toggle_output() - :noindex: - - Toggle the audio output sink - - Default actions modifiers - **ignore_card_removal_action** |--| True - -.. py:function:: shutdown(...) -> host.shutdown() - :noindex: - - Shutdown the host machine - - Default actions modifiers - **ignore_card_removal_action** |--| True - -.. py:function:: reboot(...) -> host.reboot() - :noindex: - - Reboot the host machine - - Default actions modifiers - **ignore_card_removal_action** |--| True - -.. py:function:: say_my_ip(...) -> host.say_my_ip(option='full') - :noindex: - - - - Default actions modifiers - **ignore_card_removal_action** |--| True - -.. py:function:: timer_shutdown(...) -> timers.timer_shutdown.start(wait_seconds=None) - :noindex: - - **Start the shutdown timer** - - Start the timer (with default or new parameters) - - Default actions modifiers - **ignore_card_removal_action** |--| True - -.. py:function:: timer_fade_volume(...) -> timers.timer_fade_volume.start(iterations=None, wait_seconds_per_iteration=None) - :noindex: - - **Start the volume fade out timer and shutdown** - - Start the timer (with default or new parameters) - - Default actions modifiers - **ignore_card_removal_action** |--| True - -.. py:function:: timer_stop_player(...) -> timers.timer_stop_player.start(wait_seconds=None) - :noindex: - - **Start the stop music timer** - - Start the timer (with default or new parameters) - - Default actions modifiers - **ignore_card_removal_action** |--| True - diff --git a/docs/sphinx/userguide/rpc_command_reference.rst b/docs/sphinx/userguide/rpc_command_reference.rst deleted file mode 100644 index e600ea336..000000000 --- a/docs/sphinx/userguide/rpc_command_reference.rst +++ /dev/null @@ -1,994 +0,0 @@ -RPC Command Reference -*********************** - - -This file provides a summary of all the callable functions through the RPC. It depends on the loaded modules - -.. contents:: - -Module: publishing -------------------------------------------- - - -**loaded_from**: components.publishing - -Plugin interface for Jukebox Publisher - - -.. py:function:: publishing.republish(topic=None) - :noindex: - - Re-publish the topic tree 'topic' to all subscribers - - :param topic: Topic tree to republish. None = resend all - - -Module: volume -------------------------------------------- - - -**loaded_from**: components.volume - -PulseAudio Volume Control Plugin Package - - -.. py:function:: volume.ctrl.change_volume(step: int) - :noindex: - - Increase/decrease the volume by step for the currently active output - - -.. py:function:: volume.ctrl.get_mute() - :noindex: - - Return mute status for the currently active output - - -.. py:function:: volume.ctrl.get_outputs() - :noindex: - - Get current output and list of outputs - - -.. py:function:: volume.ctrl.get_soft_max_volume() - :noindex: - - Return the maximum volume limit for the currently active output - - -.. py:function:: volume.ctrl.get_volume() - :noindex: - - Get the volume - - -.. py:function:: volume.ctrl.mute(mute=True) - :noindex: - - Set mute status for the currently active output - - -.. py:function:: volume.ctrl.publish_outputs() - :noindex: - - Publish current output and list of outputs - - -.. py:function:: volume.ctrl.publish_volume() - :noindex: - - Publish (volume, mute) - - -.. py:function:: volume.ctrl.set_output(sink_index: int) - :noindex: - - Set the active output (sink_index = 0: primary, 1: secondary) - - -.. py:function:: volume.ctrl.set_soft_max_volume(max_volume: int) - :noindex: - - Limit the maximum volume to max_volume for the currently active output - - -.. py:function:: volume.ctrl.set_volume(volume: int) - :noindex: - - Set the volume (0-100) for the currently active output - - -.. py:function:: volume.ctrl.toggle_output() - :noindex: - - Toggle the audio output sink - - -Module: jingle -------------------------------------------- - - -**loaded_from**: components.jingle - -Jingle Playback Factory for extensible run-time support of various file types - - -.. py:function:: jingle.play(filename) - :noindex: - - Play the jingle using the configured jingle service - - Note: This runs in a separate thread. And this may cause troubles - when changing the volume level before - and after the sound playback: There is nothing to prevent another - thread from changing the volume and sink while playback happens - and afterwards we change the volume back to where it was before! - - There is no way around this dilemma except for not running the jingle as a - separate thread. Currently (as thread) even the RPC is started before the sound - is finished and the volume is reset to normal... - - However: Volume plugin is loaded before jingle and sets the default - volume. No interference here. It can now only happen - if (a) through the RPC or (b) some other plugin the volume is changed. Okay, now - (a) let's hope that there is enough delay in the user requesting a volume change - (b) let's hope no other plugin wants to do that - (c) no bluetooth device connects during this time (and pulseaudio control is set to toggle_on_connect) - and take our changes with the threaded approach. - - -.. py:function:: jingle.play_startup() - :noindex: - - Play the startup sound (using jingle.play) - - -.. py:function:: jingle.play_shutdown() - :noindex: - - Play the shutdown sound (using jingle.play) - - -Module: jingle.alsawave -------------------------------------------- - - -**loaded_from**: components.jingle.alsawave - -ALSA wave jingle Service for jingle.JingleFactory - - -.. py:function:: jingle.alsawave.alsawave.play(filename) - :noindex: - - Play the wave file - - -Module: jingle.jinglemp3 -------------------------------------------- - - -**loaded_from**: components.jingle.jinglemp3 - -Generic MP3 jingle Service for jingle.JingleFactory - - -.. py:function:: jingle.jinglemp3.jinglemp3.play(filename) - :noindex: - - Play the MP3 file - - -Module: player -------------------------------------------- - - -**loaded_from**: components.playermpd - -Package for interfacing with the MPD Music Player Daemon - - -.. py:function:: player.ctrl.get_current_song(param) - :noindex: - - - - -.. py:function:: player.ctrl.get_folder_content(folder: str) - :noindex: - - Get the folder content as content list with meta-information. Depth is always 1. - - Call repeatedly to descend in hierarchy - - :param folder: Folder path relative to music library path - - -.. py:function:: player.ctrl.get_player_type_and_version() - :noindex: - - - - -.. py:function:: player.ctrl.get_song_by_url(song_url) - :noindex: - - - - -.. py:function:: player.ctrl.list_albums() - :noindex: - - - - -.. py:function:: player.ctrl.list_all_dirs() - :noindex: - - - - -.. py:function:: player.ctrl.list_song_by_artist_and_album(albumartist, album) - :noindex: - - - - -.. py:function:: player.ctrl.map_filename_to_playlist_pos(filename) - :noindex: - - - - -.. py:function:: player.ctrl.move() - :noindex: - - - - -.. py:function:: player.ctrl.next() - :noindex: - - Play next track in current playlist - - -.. py:function:: player.ctrl.pause(state: int = 1) - :noindex: - - Enforce pause to state (1: pause, 0: resume) - - This is what you want as card removal action: pause the playback, so it can be resumed when card is placed - on the reader again. What happens on re-placement depends on configured second swipe option - - -.. py:function:: player.ctrl.play() - :noindex: - - - - -.. py:function:: player.ctrl.play_album(albumartist: str, album: str) - :noindex: - - Playback a album found in MPD database. - - All album songs are added to the playlist - The playlist is cleared first. - - :param albumartist: Artist of the Album provided by MPD database - :param album: Album name provided by MPD database - - -.. py:function:: player.ctrl.play_card(folder: str, recursive: bool = False) - :noindex: - - Main entry point for trigger music playing from RFID reader. Decodes second swipe options before playing folder content - - Checks for second (or multiple) trigger of the same folder and calls first swipe / second swipe action - accordingly. - - :param folder: Folder path relative to music library path - :param recursive: Add folder recursively - - -.. py:function:: player.ctrl.play_folder(folder: str, recursive: bool = False) -> None - :noindex: - - Playback a music folder. - - Folder content is added to the playlist as described by :mod:`jukebox.playlistgenerator`. - The playlist is cleared first. - - :param folder: Folder path relative to music library path - :param recursive: Add folder recursively - - -.. py:function:: player.ctrl.play_single(song_url) - :noindex: - - - - -.. py:function:: player.ctrl.playerstatus() - :noindex: - - - - -.. py:function:: player.ctrl.playlistinfo() - :noindex: - - - - -.. py:function:: player.ctrl.prev() - :noindex: - - - - -.. py:function:: player.ctrl.queue_load(folder) - :noindex: - - - - -.. py:function:: player.ctrl.remove() - :noindex: - - - - -.. py:function:: player.ctrl.repeatmode(mode) - :noindex: - - - - -.. py:function:: player.ctrl.replay() - :noindex: - - Re-start playing the last-played folder - - Will reset settings to folder config - - -.. py:function:: player.ctrl.replay_if_stopped() - :noindex: - - Re-start playing the last-played folder unless playlist is still playing - - .. note:: To me this seems much like the behaviour of play, - but we keep it as it is specifically implemented in box 2.X - - -.. py:function:: player.ctrl.resume() - :noindex: - - - - -.. py:function:: player.ctrl.rewind() - :noindex: - - Re-start current playlist from first track - - Note: Will not re-read folder config, but leave settings untouched - - -.. py:function:: player.ctrl.second_swipe_action() - :noindex: - - Toggle pause state, i.e. do a pause / resume depending on current state - - -.. py:function:: player.ctrl.seek(new_time) - :noindex: - - - - -.. py:function:: player.ctrl.shuffle(random) - :noindex: - - - - -.. py:function:: player.ctrl.stop() - :noindex: - - - - -.. py:function:: player.ctrl.toggle() - :noindex: - - Toggle pause state, i.e. do a pause / resume depending on current state - - -.. py:function:: player.ctrl.update() - :noindex: - - - - -Module: cards -------------------------------------------- - - -**loaded_from**: components.rfid.cards - -Handling the RFID card database - - -.. py:function:: cards.list_cards() - :noindex: - - Provide a summarized, decoded list of all card actions - - This is intended as basis for a formatter function - - Format: 'id': {decoded_function_call, ignore_same_id_delay, ignore_card_removal_action, description, from_alias} - - -.. py:function:: cards.delete_card(card_id: str, auto_save: bool = True) - :noindex: - - :param auto_save: - :param card_id: - - -.. py:function:: cards.register_card(card_id: str, cmd_alias: str, args: Union[List, NoneType] = None, kwargs: Union[Dict, NoneType] = None, ignore_card_removal_action: Union[bool, NoneType] = None, ignore_same_id_delay: Union[bool, NoneType] = None, overwrite: bool = False, auto_save: bool = True) - :noindex: - - Register a new card based on quick-selection - - If you are going to call this through the RPC it will get a little verbose - - **Example:** Registering a new card with ID *0009* for increment volume with a custom argument to inc_volume - (*here: 15*) and custom *ignore_same_id_delay value*:: - - plugin.call_ignore_errors('cards', 'register_card', - args=['0009', 'inc_volume'], - kwargs={'args': [15], 'ignore_same_id_delay': True, 'overwrite': True}) - - -.. py:function:: cards.register_card_custom() - :noindex: - - Register a new card with full RPC call specification (Not implemented yet) - - -.. py:function:: cards.load_card_database(filename) - :noindex: - - - - -.. py:function:: cards.save_card_database(filename=None, *, only_if_changed=True) - :noindex: - - Store the current card database. If filename is None, it is saved back to the file it was loaded from - - -Module: rfid -------------------------------------------- - - -**loaded_from**: components.rfid.reader - - - - -Module: timers -------------------------------------------- - - -**loaded_from**: components.timers - - - - -.. py:function:: timers.timer_shutdown.cancel() - :noindex: - - Cancel the timer - - -.. py:function:: timers.timer_shutdown.get_state() - :noindex: - - Get the current state and config as dictionary - - -.. py:function:: timers.timer_shutdown.get_timeout() - :noindex: - - Get the configured time-out - - :return: The total wait time. (Not the remaining wait time!) - - -.. py:function:: timers.timer_shutdown.is_alive() - :noindex: - - Check if timer is active - - -.. py:function:: timers.timer_shutdown.publish() - :noindex: - - Publish the current state and config - - -.. py:function:: timers.timer_shutdown.set_timeout(wait_seconds: float) - :noindex: - - Set a new time-out in seconds. Re-starts the timer if already running! - - -.. py:function:: timers.timer_shutdown.start(wait_seconds=None) - :noindex: - - Start the timer (with default or new parameters) - - -.. py:function:: timers.timer_shutdown.toggle() - :noindex: - - Toggle the activation of the timer - - -.. py:function:: timers.timer_shutdown.trigger() - :noindex: - - Trigger the next target execution before the time is up - - -.. py:function:: timers.timer_stop_player.cancel() - :noindex: - - Cancel the timer - - -.. py:function:: timers.timer_stop_player.get_state() - :noindex: - - Get the current state and config as dictionary - - -.. py:function:: timers.timer_stop_player.get_timeout() - :noindex: - - Get the configured time-out - - :return: The total wait time. (Not the remaining wait time!) - - -.. py:function:: timers.timer_stop_player.is_alive() - :noindex: - - Check if timer is active - - -.. py:function:: timers.timer_stop_player.publish() - :noindex: - - Publish the current state and config - - -.. py:function:: timers.timer_stop_player.set_timeout(wait_seconds: float) - :noindex: - - Set a new time-out in seconds. Re-starts the timer if already running! - - -.. py:function:: timers.timer_stop_player.start(wait_seconds=None) - :noindex: - - Start the timer (with default or new parameters) - - -.. py:function:: timers.timer_stop_player.toggle() - :noindex: - - Toggle the activation of the timer - - -.. py:function:: timers.timer_stop_player.trigger() - :noindex: - - Trigger the next target execution before the time is up - - -.. py:function:: timers.timer_fade_volume.cancel() - :noindex: - - Cancel the timer - - -.. py:function:: timers.timer_fade_volume.get_timeout() - :noindex: - - Get the configured time-out - - :return: The total wait time. (Not the remaining wait time!) - - -.. py:function:: timers.timer_fade_volume.is_alive() - :noindex: - - Check if timer is active - - -.. py:function:: timers.timer_fade_volume.publish() - :noindex: - - Publish the current state and config - - -.. py:function:: timers.timer_fade_volume.set_timeout(wait_seconds: float) - :noindex: - - Set a new time-out in seconds. Re-starts the timer if already running! - - -.. py:function:: timers.timer_fade_volume.start(iterations=None, wait_seconds_per_iteration=None) - :noindex: - - Start the timer (with default or new parameters) - - -.. py:function:: timers.timer_fade_volume.toggle() - :noindex: - - Toggle the activation of the timer - - -.. py:function:: timers.timer_fade_volume.trigger() - :noindex: - - Trigger the next target execution before the time is up - - -Module: host -------------------------------------------- - - -**loaded_from**: components.hostif.linux - - - - -.. py:function:: host.shutdown() - :noindex: - - Shutdown the host machine - - -.. py:function:: host.reboot() - :noindex: - - Reboot the host machine - - -.. py:function:: host.jukebox_is_service() - :noindex: - - Check if current Jukebox process is running as a service - - -.. py:function:: host.is_any_jukebox_service_active() - :noindex: - - Check if a Jukebox service is running - - .. note:: Does not have the be the current app, that is running as a service! - - -.. py:function:: host.restart_service() - :noindex: - - Restart Jukebox App if running as a service - - -.. py:function:: host.get_disk_usage(path='/') - :noindex: - - Return the disk usage in Megabytes as dictionary for RPC export - - -.. py:function:: host.get_cpu_temperature() - :noindex: - - Get the CPU temperature with single decimal point - - No error handling: this is expected to take place up-level! - - -.. py:function:: host.publish_cpu_temperature() - :noindex: - - - - -.. py:function:: host.get_ip_address() - :noindex: - - Get the IP address - - -.. py:function:: host.say_my_ip(option='full') - :noindex: - - - - -.. py:function:: host.wlan_disable_power_down(card=None) - :noindex: - - Turn off power management of wlan. Keep RPi reachable via WLAN - - This must be done after every reboot - card=None takes card from configuration file - - -.. py:function:: host.get_autohotspot_status() - :noindex: - - Get the status of the auto hotspot feature - - -.. py:function:: host.stop_autohotspot() - :noindex: - - Stop auto hotspot functionality - - Basically disabling the cronjob and running the script one last time manually - - -.. py:function:: host.start_autohotspot() - :noindex: - - start auto hotspot functionality - - Basically enabling the cronjob and running the script one time manually - - -.. py:function:: host.timer_temperature.cancel() - :noindex: - - Cancel the timer - - -.. py:function:: host.timer_temperature.get_timeout() - :noindex: - - Get the configured time-out - - :return: The total wait time. (Not the remaining wait time!) - - -.. py:function:: host.timer_temperature.is_alive() - :noindex: - - Check if timer is active - - -.. py:function:: host.timer_temperature.publish() - :noindex: - - Publish the current state and config - - -.. py:function:: host.timer_temperature.set_timeout(wait_seconds: float) - :noindex: - - Set a new time-out in seconds. Re-starts the timer if already running! - - -.. py:function:: host.timer_temperature.start(wait_seconds=None) - :noindex: - - Start the timer (with default or new parameters) - - -.. py:function:: host.timer_temperature.toggle() - :noindex: - - Toggle the activation of the timer - - -.. py:function:: host.timer_temperature.trigger() - :noindex: - - Trigger the next target execution before the time is up - - -Module: bluetooth_audio_buttons -------------------------------------------- - - -**loaded_from**: components.controls.bluetooth_audio_buttons - -Plugin to attempt to automatically listen to it's buttons (play, next, ...) -when a bluetooth sound device (headphone, speakers) connects - - -.. py:function:: bluetooth_audio_buttons.activate(device_name: str, exact: bool = True, open_initial_delay: float = 0.25) - :noindex: - - - - -Module: gpio -------------------------------------------- - - -**loaded_from**: components.gpio.gpioz.plugin - -The GPIOZ plugin interface build all input and output devices from the configuration file and connects -the actions and callbacks. It also provides a very restricted, but common API for the output devices to the RPC. -That API is mainly used for testing. All the relevant output state changes are usually made through callbacks directly -using the output device's API. - - -.. py:function:: gpio.on(name: str) - :noindex: - - Turn an output device on - - :param name: The alias name output device instance - - -.. py:function:: gpio.off(name: str) - :noindex: - - Turn an output device off - - :param name: The alias name output device instance - - -.. py:function:: gpio.set_value(name: str, value: Any) - :noindex: - - Set the output device to :attr:`value` - - :param name: The alias name output device instance - - :param value: Value to set the device to - - -.. py:function:: gpio.flash(name, on_time=1, off_time=1, n=1, *, fade_in_time=0, fade_out_time=0, tone=None, color=(1, 1, 1)) - :noindex: - - Flash (blink or beep) an output device - - This is a generic function for all types of output devices. Parameters not applicable to an - specific output device are silently ignored - - :param name: The alias name output device instance - - :param on_time: Time in seconds in state ``ON`` - - :param off_time: Time in seconds in state ``OFF`` - - :param n: Number of flash cycles - - :param tone: The tone in to play, e.g. 'A4'. *Only for TonalBuzzer*. - - :param color: The RGB color *only for PWMLED*. - - :param fade_in_time: Time in seconds for transitioning to on. *Only for PWMLED and RGBLED* - - :param fade_out_time: Time in seconds for transitioning to off. *Only for PWMLED and RGBLED* - - -Module: music_cover_art -------------------------------------------- - - -**loaded_from**: components.music_cover_art - -Read all cover art from music save it to a cache for the UI to load - - -.. py:function:: music_cover_art.ctrl.get_by_filename_as_base64(audio_src: str) - :noindex: - - - - -Module: misc -------------------------------------------- - - -**loaded_from**: components.misc - -Miscellaneous function package - - -.. py:function:: misc.rpc_cmd_help() - :noindex: - - Return all commands for RPC - - -.. py:function:: misc.get_all_loaded_packages() - :noindex: - - Get all successfully loaded plugins - - -.. py:function:: misc.get_all_failed_packages() - :noindex: - - Get all plugins with error during load or initialization - - -.. py:function:: misc.get_start_time() - :noindex: - - Time when JukeBox has been started - - -.. py:function:: misc.get_log_debug() - :noindex: - - Get the log file (from the debug_file_handler) - - -.. py:function:: misc.get_log_error() - :noindex: - - Get the log file (from the error_file_handler) - - -.. py:function:: misc.get_version() - :noindex: - - - - -.. py:function:: misc.get_git_state() - :noindex: - - Return git state information for the current branch - - -.. py:function:: misc.empty_rpc_call(msg: str = '') - :noindex: - - This function does nothing. - - The RPC command alias 'none' is mapped to this function. - - This is also used when configuration errors lead to non existing RPC command alias definitions. - When the alias definition is void, we still want to return a valid function to simplify error handling - up the module call stack. - - :param msg: If present, this message is send to the logger with severity warning - - - - -Generation notes -------------------------------------------- - - -This is an automatically generated file from the loaded plugins: - -* *publishing*: components.publishing -* *volume*: components.volume -* *jingle*: components.jingle -* *jingle.alsawave*: components.jingle.alsawave -* *jingle.jinglemp3*: components.jingle.jinglemp3 -* *player*: components.playermpd -* *cards*: components.rfid.cards -* *rfid*: components.rfid.reader -* *timers*: components.timers -* *host*: components.hostif.linux -* *bluetooth_audio_buttons*: components.controls.bluetooth_audio_buttons -* *gpio*: components.gpio.gpioz.plugin -* *music_cover_art*: components.music_cover_art -* *misc*: components.misc diff --git a/docs/sphinx/userguide/rpc_commands.rst b/docs/sphinx/userguide/rpc_commands.rst deleted file mode 100644 index 5b2a58515..000000000 --- a/docs/sphinx/userguide/rpc_commands.rst +++ /dev/null @@ -1,116 +0,0 @@ -RPC Commands -***************** - -We use the RPC commands when triggering actions from different inputs like a card swipe, -a GPIO button press, etc. Triggering an action is equal to sending an RPC function call. -In many places the command to send when an input is triggered is configurable in a YAML-file. - -Basics ---------- - -Consequently, you need to know how to specify the RPC command in the YAML file. -Here is the essence of what you need to know: - -An RPC command consists of up to three parts - - #. the function to execute (e.g. play_folder, change_volume) - #. the positional arguments (optional) - #. the keyword arguments (optional) - -The function specification consists of two (e.g., ``host.shutdown``) or three terms (e.g., ``volume.ctrl.change_volume``). -In configuration files, this will look like this: - -.. code-block:: yaml - - package: host - plugin: shutdown - -Or like this for a three part function with the argument set to ``5``: - -.. code-block:: yaml - - package: volume - plugin: ctrl - method: change_volume - args: [5] - -The keyword ``method`` is optional. If needs to be used depends on the function you want to call. -You will find a full list of RPC callable functions in :ref:`userguide/rpc_command_reference:RPC Command Reference`, - -Aliases --------- - -Not so complicated, right? It will get even easier. For common commands we have defined aliases. An alias simply maps -to a pre-defined RPC command, e.g. ``play_card`` maps to ``player.ctrl.play_card``. - -Instead of - -.. code-block:: yaml - - package: player - plugin: ctrl - method: play_card - args: [path/to/folder] - -you can simply specify instead : - -.. code-block:: yaml - - alias: play_card - args: [path/to/folder] - -Using in alias is optional. But if the keyword is present in the configuration it takes precedence over an explicit -specified RPC command. All alias definitions may be found -in the :ref:`userguide/rpc_command_alias_reference:RPC Command Alias Reference`. - -Arguments --------------- - -Arguments can be specified in similar fashion to Python function arguments: as positional arguments and / or -keyword arguments. Let's check out play_card, which is defined as: - -.. py:function:: play_card(...) -> player.ctrl.play_card(folder: str, recursive: bool = False) - :noindex: - - :param folder: Folder path relative to music library path - :param recursive: Add folder recursively - -This means it takes two arguments: - - * folder of type string - * recursive of type bool - -In the following examples, we will always use the alias for smaller configuration text. All three examples -do exactly the same, but use different ways of specifying the command. - -.. code-block:: yaml - - alias: play_card - args: [path/to/folder, True] - -.. code-block:: yaml - - alias: play_card - args: [path/to/folder] - kwargs: - recursive: True - -.. code-block:: yaml - - alias: play_card - kwargs: - folder: path/to/folder - recursive: True - - -.. important:: *args* must be a **list** of arguments to be passed! Even if only a single argument is passed. - So, use *args: [value]*. We try catch mis-uses but that might not always work. - - -You will find some more examples the configuration of the :ref:`userguide/carddatabase:Card Database` - -For developers ----------------- - -There is a ready-to-use decoding functions which decodes an RPC command (with or without alias) -from a YAML entry:func:`jukebox.utils.decode_rpc_command`. diff --git a/docs/sphinx/userguide/sync_rfidcards.rst b/docs/sphinx/userguide/sync_rfidcards.rst deleted file mode 100644 index 5cb554acb..000000000 --- a/docs/sphinx/userguide/sync_rfidcards.rst +++ /dev/null @@ -1,71 +0,0 @@ -Syncronisation RFID Cards -************************* - -This component handles the synchronisation of RFID cards (audiofolder and card database entries). - -It allows to manage card database entries and audiofiles of one to many Phonieboxes -in a central place (e.g. NAS, primary Phoniebox etc.) in the network, -but allows to play the audio offline once the data has synced. -The synchronisation can be initiated with the command ``sync-all`` -and optionally on every RFID scan for a particular CardID and its corresponding audiofolder. -To execute the ``sync-all`` command, bind a RFID card to the command. -For the "RFID scan sync" feature, activate the option in the configuration -or bind a RFID card to the command for dynamic activation or deactivation. - -Synchronisation ---------------- - -The synchronisation will be FROM a server TO the Phoniebox, overriding existing files. -A local configuration will be lost after the synchronization. -If you want to make the initial setup e.g. via WebUi copy the files and use it as a base for the server. - -To access the files on the server, 2 modes are supported: SSH or MOUNT. -Please make sure you have the correct access rights to the source and use key-based authentication for SSH. - -RFID scan sync -^^^^^^^^^^^^^^ -If the feature "RFID scan sync" is activated, there will be a check on every RFID scan against the server -if a matching card entry and audiofolder is available. If so, changes will be synced. -The playback will be delayed for the time the data is transfered (see "sync-all" to use a full synchronization if a lot of new files have been added). -If the server is not reachable, the check will be aborted after the timeout. -Therfore, an unreachable server will cause a delay (see commands to toggle activation state). -Deleted card entries / audiofolders (not the contained items) will not be purged locally if deleted on remote. -This is also true for changed card entries (the old audiofolder / -files will remain). To remove not existing items us a "sync-all". - -Configuration -------------- - -Set the corresponding setting in ``shared\settings\jukebox.yaml`` to activate this feature. - -.. code-block:: yaml - - modules: - named: - ... - sync_rfidcards: synchronisation.rfidcards - - ... - sync_rfidcards: - enable: false - config_file: ../../shared/settings/sync_rfidcards.yaml - -The settings file (``shared\settings\sync_rfidcards.yaml``) contains the following configuration - -.. code-block:: yaml - - sync_rfidcards: - # Holds the activation state of the optional feature "RFID scan sync". Values are "TRUE" or "FALSE" - on_rfid_scan_enabled: true # bool - # Server Access mode. MOUNT or SSH - mode: mount # 'mount' or 'ssh' - credentials: - # IP or hostname of the server (used to check connectivity and for SSH mode). e.g. "192.168.0.2" or "myhomeserver.local" - server: '' - # Port (used to check connectivity and for SSH mode). e.g. "80" or "22" - port: # int - # Timeout to reach the server (in seconds) (used to check connectivity). e.g. 1 - timeout: 1 # int - # Path to the shared files to sync (without trailing slash) (remote path for SSH mode or local path for MOUNT mode). e.g. "/mnt/Phoniebox" - path: '' - # Username if SSH mode is used. - username: '' diff --git a/docs/sphinx/userguide/system.rst b/docs/sphinx/userguide/system.rst deleted file mode 100644 index 3740663ab..000000000 --- a/docs/sphinx/userguide/system.rst +++ /dev/null @@ -1,121 +0,0 @@ -System Setup -===================== - -A few words on how the system is setup and interacts. - -The system consists of - - #. the :ref:`userguide/system:Music Player Daemon (MPD)` which we use for all music playback (local, stream, podcast, ...) - #. the :ref:`userguide/system:PulseAudio` for flexible audio output support - #. the :ref:`userguide/system:Jukebox Core Service` for controlling MPD and PulseAudio and providing all the features - #. the :ref:`userguide/system:Web UI` which is served through an Nginx web server - #. a set of :ref:`developer/coreapps:Configuration Tools` and - a set of :ref:`developer/coreapps:Developer Tools` - -.. note:: The default install puts everything into the folder ``/home/pi/RPi-Jukebox-RFID``. - Another folder might work, but is certainly not tested. Things are installed for the default user ``pi``. Again, - another user might work, but is not tested. - -Music Player Daemon (MPD) --------------------------- - -The Music Player Daemon runs as *user-local* service (not as system-wide service which is usually the default). -This is important for the interaction with PulseAudio. - -You will find the MPD configuration file under - -.. code-block:: text - - $HOME/.config/mpd/mpd.conf - -All MPD *var*-files are also located in ``$HOME/.config/mpd``. - -The service can be controlled with the *systemctl*-command when adding the parameter ``--user``: - -.. code-block:: bash - - $ systemctl --user status mpd - $ systemctl --user start mpd - $ systemctl --user stop mpd - -.. important:: Never start or enable the system-wide MPD service with `sudo systemctl start mpd`! - -To check if MPD is running or has issues, use - -.. code-block:: bash - - $ systemctl --user status mpd - # or, if you need to get the full logs - $ journalctl --user -b -u mpd - -The ``systemd`` service file is located at the default location for user services: - -.. code-block:: text - - /usr/lib/systemd/user/mpd.service - -PulseAudio ---------------------- - -We use PulseAudio for the audio output configuration. Check out the Audio Configuration page for details. - -There is a number of reasons for that: - - * It is easier to support and setup different audio hardware. Over the years, many builders have - tried many different ways to set up audio on their Jukebox so this become the most reliable and compatible - solution - * We can cleanly control and switch between different audio outputs independent of the playback software - * The current Pi OS based on Bullseye does not allow another way to control Bluetooth based speakers, - as Bluealsa is currently not working with Bluez 5 - -The PulseAudio configuration file is located at - -.. code-block:: text - - ~/.config/pulse/default.pa - -Service control and service configuration file location is identical to MPD. - -Jukebox Core Service ---------------------- - -The :ref:`developer/coreapps:Jukebox Core` runs as a *user-local* service with the name ``jukebox-daemon``. -Similar to MPD, it's important that it does run as system-wide service to be able to interact with PulseAudio. - -The service can be controlled with the ``systemctl``-command by adding the parameter ``--user`` - -.. code-block:: bash - - $ systemctl --user start jukebox-daemon - $ systemctl --user stop jukebox-daemon - -Check out the service with - -.. code-block:: bash - - $ systemctl --user status jukebox-daemon - # and if you need to get the full log output - $ journalctl --user -b -u jukebox-daemon - -The ``systemd`` service file is located at the default location for user services: - -.. code-block:: text - - /usr/lib/systemd/user/jukebox-daemon.service - -Starting and stopping the service can be useful for debugging or configuration checks. - -Web UI ------------------------ - -The Web UI is served using nginx. Nginx runs as a system service. The home directory is localed at - -.. code-block:: text - - /home/pi/RPi-Jukebox-RFID/src/webapp/build - -The Nginx configuration is located at - -.. code-block:: text - - /etc/nginx/sites-available/default diff --git a/docs/sphinx/userguide/troubleshooting.rst b/docs/sphinx/userguide/troubleshooting.rst deleted file mode 100644 index 24d1fec9c..000000000 --- a/docs/sphinx/userguide/troubleshooting.rst +++ /dev/null @@ -1,107 +0,0 @@ -Troubleshooting -***************** - -We have made a point of providing extensive log messages. -In full debug mode, this may become very verbose. In fact, better observability -has been one of the design goals for version 3. - -There are various options to get access to debug information. - -Debugging your setup runs in several steps - - #. Check that :ref:`audio output works` - #. Check that :ref:`MPD works` - #. Checking log messages from the Jukebox Core App as described below - -The short answer ----------------- - -**We are still in the Pre-Release phase, so by default two log files should be written out:** - -.. code-block:: bash - - ../shared/logs/app.log : Complete Debug Messages - ../shared/logs/errors.log: Only Errors and Warnings - -These files always contain the messages of the current run only. -The logs of previous runs are post-fixed with ``.1``, e.g. ``app.log.1``. This is useful for debugging issues during -shutdown of the service. - -The logs are also available via the Web Server: - -.. code-block:: - - http://ip.of.your.box/logs - -.. important:: Always check the time modification date or the beginning of the log - file to ensure you are not looking at an old log file! - -The long answer: A few more details ------------------------------------- - -If started without parameters, the Jukebox checks for the existence of ``../shared/settings/logger.yaml`` -and if present, uses that configuration for logging. This file is created by the installation process. -The default configuration file is also provided in ``../resources/default-settings/logger.default.yaml``. -We use Python's logging module to provide the debug messages which is configured through this file. - -**We are still in the Pre-Release phase which means full debug logging is enabled by default.** - -Default logging configuration -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The default logging config does 2 things: - -1. It writes 2 log files: - -.. code-block:: bash - - ../shared/logs/app.log : Complete Debug Messages - ../shared/logs/errors.log : Only Errors and Warnings - -2. Prints logging messages to the console. If run as a service, only error messages are emitted to console to avoid spamming the system log files. - -Debug logging in console -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -For debugging, it is usually very helpful to observe the apps output directly -on the console log. - -.. code-block:: bash - - # Make sure the Jukebox service is stopped: - $ systemctl --user stop jukebox-daemon - - # Start the Jukebox in debug mode: - # with default logger: - $ ./run_jukebox.py - - # or with custom logger configuration: - $ ./run_jukebox.py --logger ../path/to/logger.yaml - -Fallback configuration -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -It is possible to start the Jukebox with a catch-all debug enabler with a logger.yaml. -Attention: This only emits messages to the console and does not write to the log files! -This is more a fallback features: - -.. code-block:: bash - - $./run_jukebox.py -vv - -Extreme cases -^^^^^^^^^^^^^ - -Sometimes, the Jukebox app might crash with an exception and stack trace which is -neither logged, nor caught and handled. - -If run locally from your console, you will see it immediately. No worries! - -If running as a service, you will probably not even notice immediately that something has -gone pear-shaped. Services are restarted automatically when they fail. - -Things are just not behaving as expected? Time to check the system logs: - -.. code-block:: bash - - $journalctl --user -b -u jukebox-daemon diff --git a/docs/sphinx/primer.rst b/documentation/README.md similarity index 62% rename from docs/sphinx/primer.rst rename to documentation/README.md index 90de9f916..d71a57e0b 100644 --- a/docs/sphinx/primer.rst +++ b/documentation/README.md @@ -1,24 +1,32 @@ -What is this? -================================================ +# Welcome to RPi Jukebox RFID’s documentation! -The exciting, new **Version 3** of the RPi Jukebox RFID. A complete rewrite of the Jukebox code base. +The exciting, new Version 3 of the RPi Jukebox RFID. A complete rewrite of the Jukebox code base. -.. important:: This documentation applies to the Version 3 which is developed in the branches *future3/main* and *future3/develop*. - Currently the default Version is 2.X +> [!NOTE] +> This documentation applies to the Version 3 which is developed in the branches `future3/main` and `future3/develop`. Currently the default Version is 2.x To find out more about the RPi Jukebox RFID -project check out the `documentation of Version 2 `_ or `www.phoniebox.de `_. +project check out the [documentation of Version 2](https://github.com/MiczFlor/RPi-Jukebox-RFID) or [www.phoniebox.de](https://www.phoniebox.de/). -Why? ------ +## Quickstart + +* [Installing Phoniebox future3](./content/userguide/installation.md) +* [Update](./content/userguide/update.md) +* [Feature Status](status.md) +* [Known Issues](./content/developers/known-issues.md) +* [User Guide](./content/userguide/) +* [Developer Reference](developers) + +## future3 + +### Why? * Better extensibility, clear architecture allowing for easier integration of new features * Higher performance especially on lower end hardware (it's a stretch at the moment) * Better maintainability * Better observability for debugging -How? ------- +### How? * Jukebox core is a holistic Python3-only application * Avoid shell script invocation during runtime wherever possible @@ -27,8 +35,7 @@ How? * Implemented a plugin concept to dynamically load Python modules configurable through the configuration file * In conjunction with the RPC, this is a neat way of allowing additional features without having to touch the core all the time -Where are we? Help wanted! --------------------------- +### Where are we? Help wanted! The initial proof-of-concept phase has been left behind and there is quite some functionality available already. This is still an ongoing process but the WebUI and RFID-triggered playback of local files work. @@ -36,4 +43,3 @@ This is still an ongoing process but the WebUI and RFID-triggered playback of lo Features/files from version 2.X will only be copied/merged once they can be integrated and tested. If you don't find your v2.X contributions, it doesn't mean they are obsolete. Things will be integrated step by step. And, of course, you are welcome to adapt your previous contributions to this new exiting structure. - diff --git a/docs/calendars/2019-Phoniebox-Calendar.jpg b/documentation/content/calendars/2019-Phoniebox-Calendar.jpg similarity index 100% rename from docs/calendars/2019-Phoniebox-Calendar.jpg rename to documentation/content/calendars/2019-Phoniebox-Calendar.jpg diff --git a/docs/calendars/2020-Phoniebox-Calendar.jpg b/documentation/content/calendars/2020-Phoniebox-Calendar.jpg similarity index 100% rename from docs/calendars/2020-Phoniebox-Calendar.jpg rename to documentation/content/calendars/2020-Phoniebox-Calendar.jpg diff --git a/docs/calendars/2021-Phoniebox-Calendar.jpg b/documentation/content/calendars/2021-Phoniebox-Calendar.jpg similarity index 100% rename from docs/calendars/2021-Phoniebox-Calendar.jpg rename to documentation/content/calendars/2021-Phoniebox-Calendar.jpg diff --git a/documentation/content/developers/coreapps.md b/documentation/content/developers/coreapps.md new file mode 100644 index 000000000..fa6e7c99c --- /dev/null +++ b/documentation/content/developers/coreapps.md @@ -0,0 +1,56 @@ +# Jukebox Apps + +The Jukebox\'s core apps are located in `src/jukebox`. Run the following +command to learn more about each app and its parameters: + +``` bash +$ ./run_app_name.py -h +``` + +## Jukebox Core + +### `run_jukebox.py` + +This is the main app and starts the Jukebox Core. + +Usually this runs as a service, which is started automatically after boot-up. At times, it may be necessary to restart the service. For example after a configuration change. Not all configuration changes can be applied on-the-fly. See [Jukebox Configuration](../userguide/configuration.md#jukebox-configuration). + +For debugging, it is usually desirable to run the Jukebox directly from the console rather than as service. This gives direct logging info in the console and allows changing command line parameters. See [Troubleshooting](../userguide/troubleshooting.md). + +## Configuration Tools + +Before running the configuration tools, stop the Jukebox Core service. +See [Best practice procedure](../userguide/configuration.md#best-practice-procedure). + +### `run_configure_audio.py` + +Setup tool to register the PulseAudio sinks as primary and secondary audio outputs. + +Will also setup equalizer and mono down mixer in the pulseaudio config file. + +Run this once after installation. Can be re-run at any time to change the settings. For more information see [Audio Configuration](../userguide/audio.md). + +### `run_register_rfid_reader.py` + +Setup tool to configure the RFID Readers. + +Run this once to register and configure the RFID readers with the Jukebox. Can be re-run at any time to change the settings. For more information see [RFID Readers](../rfid/README.md). + +> [!NOTE] +> This tool will always write a new configurations file. Thus, overwrite the old one (after checking with the user). Any manual modifications to the settings will have to be re-applied + +## Developer Tools + +### `run_rpc_tool.py` + +Command Line Interface to the Jukebox RPC Server + +A command line tool for sending RPC commands to the running jukebox app. This uses the same interface as the WebUI. Can be used for additional control or for debugging. + +The tool features auto-completion and command history. + +The list of available commands is fetched from the running Jukebox service. + +### `run_publicity_sniffer.py` + +A command line tool that monitors all messages being sent out from the Jukebox via the publishing interface. Received messages are printed in the console. Mainly used for debugging. diff --git a/documentation/content/developers/developer-issues.md b/documentation/content/developers/developer-issues.md new file mode 100644 index 000000000..c20cff5ec --- /dev/null +++ b/documentation/content/developers/developer-issues.md @@ -0,0 +1,73 @@ +# Developer Issues + +## Building the Webapp on the PI + +### JavaScript heap out of memory + +While (re-) building the Web App, you get the following output: + +``` {.bash emphasize-lines="12"} +pi@MusicPi:~/RPi-Jukebox-RFID/src/webapp $ npm run build + +> webapp@0.1.0 build +> react-scripts build + +Creating an optimized production build... + +[...] + +<--- JS stacktrace ---> + +FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory +``` + +**Reason** + +Not enough memory for Node + +**Solution** + +Prior to building set the node memory environment variable. + +1. Make sure the value is less than the total available space on the + system, or you may run into the next issue. (Not always though!) + Check memory availability with `free -mt`. +2. We also experience trouble, when the space is set too small a + value. 512 always works, 256 sometimes does, sometimes does not. + If your free memory is small, consider increasing the swap size of + your system! + +``` bash +export NODE_OPTIONS=--max-old-space-size=512 +npm run build +``` + +Alternatively, use the provided script, which sets the variable for you +(provided your swap size is large enough): + +``` bash +$ ./run_rebuild.sh +``` + +### Process exited too early // kill -9 + +``` {.bash emphasize-lines="8,9"} +pi@MusicPi:~/RPi-Jukebox-RFID/src/webapp $ npm run build + +> webapp@0.1.0 build +> react-scripts build + +... + +The build failed because the process exited too early. +This probably means the system ran out of memory or someone called 'kill -9' on the process. +``` + +**Reason** + +Node tried to allocate more memory than available on the system. + +**Solution** + +Adjust the node memory variable as described in [JavaScript heap out of memory](#javascript-heap-out-of-memory). But make sure to allocate less memory than the available memory. If that is not sufficient, increase the swap file size of your +system and try again. diff --git a/documentation/content/developers/development-environment.md b/documentation/content/developers/development-environment.md new file mode 100644 index 000000000..0b271ce38 --- /dev/null +++ b/documentation/content/developers/development-environment.md @@ -0,0 +1,74 @@ +# Development Environment + +You have 3 development options: + +## Directly on Raspberry Pi + +The full setup is running on the RPi and you access files via SSH. +Pretty easy to set up as you simply do a normal install and switch to +the `future3/develop` branch. + +### Steps to install + +We recommend to use at least a Pi 3 or Pi Zero 2 for development. This +hardware won\'t be needed in production, but it can be slow while +developing. + +1. Install the latest Pi OS on a SD card. +2. Boot up your Raspberry Pi. +3. [Install](../installation.md) the Jukebox software as if you were building a + Phoniebox. You can install from your own fork and feature branch if + you wish which can be changed later as well. The original repository + will be set as `upstream`. +4. Once the installation has successfully ran, reboot your Pi. +5. Due to some resource constraints, the Webapp does not build the + latest changes and instead consumes the latest official release. To + change that, you need to install NodeJS and build the Webapp + locally. +6. Install NodeJS using the existing installer + + ``` bash + cd ~/RPi-Jukebox-RFID/installation/routines; \ + source setup_jukebox_webapp.sh; \ + _jukebox_webapp_install_node + ``` + +7. To free up RAM, reboot your Pi. +8. Build the Webapp using the existing build command. If the build + fails, you might have forgotten to reboot. + + ``` bash + cd ~/RPi-Jukebox-RFID/src/webapp; \ + ./run_rebuild.sh -u + ``` + +9. The Webapp should now be updated. +10. To continuously update Webapp, pull the latest changes from your + repository and rerun the command above. + +## Locally on any Linux machine + +The jukebox also runs on any Linux machine. The Raspberry Pi specific +stuff will not work of course. That is no issue depending our your +development area. USB RFID Readers, however, will work. You may setup a +Python virtual environment or a conda virtual environment. You will have +to install and configure [MPD (Music Player +Daemon)](https://www.musicpd.org/). + +In addition to the `requirements.txt`, you will this +dependency. On the Raspberry PI, the latest stable release of ZMQ does +not support WebSockets. We need to compile the latest version from +Github, which is taken care of by the installation script. For regular +machines, the normal package can be installed: + +``` bash +pip3 install pyzmq +``` + +You will have to start Jukebox core application and the WebUI +separately. The MPD usually runs as a service. + +## Using Docker container + +There is a complete setup +`docker workflow `. diff --git a/documentation/content/developers/docker.md b/documentation/content/developers/docker.md new file mode 100644 index 000000000..f3b9c825f --- /dev/null +++ b/documentation/content/developers/docker.md @@ -0,0 +1,265 @@ +# Phoniebox Development Runbook for Docker environments + +This document describes how to set up a local development environment +with Docker. It is useful to develop certain parts of the Phoniebox +application that do not directly require the Raspberry Pi hardware such +as GPIO. *Raspberry Pi OS* is based on Debian but comes with a lot of +special packages and a unique graphical interface. It is difficult to +mock a Raspberry Pi whithin a Docker container but we try to keep both +environments as close as possible. The Docker environment is not meant +to be deployed on the Raspberry Pi directly for performance reasons. + +Depending on your host environment (Mac, Linux or Windows), you might +need to adapt some of those commands to your needs. + +## Prerequisites + +1. Install required software + * Linux + * [Docker](https://docs.docker.com/engine/install/debian/) + * [Compose](https://docs.docker.com/compose/install/) + * Mac + * [Docker & Compose (Mac)](https://docs.docker.com/docker-for-mac/install/) + * [pulseaudio (Docker)](https://devops.datenkollektiv.de/running-a-docker-soundbox-on-mac.html) + * Windows + * [Docker & Compose (Windows)](https://docs.docker.com/docker-for-windows/install/) + * [pulseaudio (Windows)](https://www.freedesktop.org/wiki/Software/PulseAudio/Ports/Windows/Support/) + +2. Pull the Jukebox repository: + ``` + $ git clone https://github.com/MiczFlor/RPi-Jukebox-RFID.git + `````` + +3. Create a jukebox.yaml file + * Copy the `./resources/default-settings/jukebox.default.yaml` to `./shared/settings` and rename the file to `jukebox.yaml`. + ``` + $ cp ./resources/default-settings/jukebox.default.yaml ./shared/settings/jukebox.yaml + ``` + * Override/Merge the values from the following [Override file](https://github.com/MiczFlor/RPi-Jukebox-RFID/blob/future3/develop/docker/config/jukebox.overrides.yaml) in your `jukebox.yaml`. + * **\[Currently required\]** Update all relative paths (`../..`) in to `/home/pi/RPi-Jukebox-RFID`. + +4. Change directory into the `./RPi-Jukebox-RFID/shared/audiofolders` + and copy a set of MP3 files into this folder (for more fun when + testing). + +## Run development environment + +In contrary to how everything is set up on the Raspberry Pi, it\'s good +practice to isolate different components in different Docker images. +They can be run individually or in combination. To do that, we use +`docker-compose`. + +### Linux + +Make sure you don\'t use `sudo` to run your `docker-compose`. Check out +Docker\'s [post-installation guide](https://docs.docker.com/engine/install/linux-postinstall/] for more information. + +``` bash +// Build Images +$ docker-compose -f docker/docker-compose.yml -f docker/docker-compose.linux.yml build + +// Run Docker Environment +$ docker-compose -f docker/docker-compose.yml -f docker/docker-compose.linux.yml up + +// Shuts down Docker containers and Docker network +$ docker-compose -f docker/docker-compose.yml -f docker/docker-compose.linux.yml down +``` + +Note: if you have `mpd` running on your system, you need to stop it +using: + +``` bash +$ sudo systemctl stop mpd.socket +$ sudo mpd --kill +``` + +Otherwise you might get the error message: + +``` bash +$ docker-compose -f docker-compose.yml -f docker-compose.linux.yml up +Starting mpd ... +Starting mpd ... error +(...) +Error starting userland proxy: listen tcp4 0.0.0.0:6600: bind: address already in use +``` + +Read these threads for details: [thread 1](https://unix.stackexchange.com/questions/456909/socket-already-in-use-but-is-not-listed-mpd) and [thread 2](https://stackoverflow.com/questions/5106674/error-address-already-in-use-while-binding-socket-with-address-but-the-port-num/5106755#5106755) + +### Mac + +Remember, pulseaudio is a prerequisite. [Follow these +instructions](https://stackoverflow.com/a/50939994/1062438) for Mac +hosts. + +``` bash +// Build Images +$ docker-compose -f docker/docker-compose.yml -f docker/docker-compose.mac.yml build + +// Run Docker Environment +$ docker-compose -f docker/docker-compose.yml -f docker/docker-compose.mac.yml up + +// Shuts down Docker containers and Docker network +$ docker-compose -f docker/docker-compose.yml -f docker/docker-compose.mac.yml down +``` + +### Windows + +1. Download + [pulseaudio](https://www.freedesktop.org/wiki/Software/PulseAudio/Ports/Windows/Support/) + +2. Uncompress somewhere in your user folder + +3. Edit `$INSTALL_DIR/etc/pulse/default.pa` + +4. Add the following line + + ``` bash + load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1 + ``` + +5. Edit `$INSTALL_DIR/etc/pulse//etc/pulse/daemon.conf`, find the + following line and change it to: + + ``` bash + exit-idle-time = -1 + ``` + +6. Execute `$INSTALL_DIR/bin/pulseaudio.exe` + +7. Run `cocker-compose` + + ``` bash + // Build Images + $ docker-compose -f docker/docker-compose.yml -f docker/docker-compose.windows.yml build + + // Run Docker Environment + $ docker-compose -f docker/docker-compose.yml -f docker/docker-compose.windows.yml up + + // Shuts down Docker containers and Docker network + $ docker-compose -f docker/docker-compose.yml -f docker/docker-compose.windows.yml down + ``` + +## Test & Develop + +The Dockerfile is defined to start all Phoniebox related services. + +Open in your browser to see the web application. + +While the `webapp` container does not require a reload while working on +it (hot-reload is enabled), you will have to restart your `jukebox` +container whenever you make a change (in the Python code). Instead of +stopping and starting the `docker-compose` command, you can individually +restart your `jukebox` container. Update the below path with your +specific host environment. + +``` bash +$ docker-compose -f docker/docker-compose.yml -f docker/docker-compose.[ENVIRONMENT].yml restart jukebox +``` + +## Known issues + +The docker environment only exists to make development easier and +possible without a physical device. It won\'t replace it though. +Therefore, we currently accept certain issues related to the individual +Docker containers. Here is a list of known errors or weird behaviour +which you can easily ignore unless they prevent you from progressing. If +would be of course useful to get rid of them, but currently we make a +trade-off between a development environment and solving the specific +details. + +### `mpd` container + +When starting the `mpd` container, you will see the following errors. +You can ignore them, MPD will run. + +``` bash +mpd | exception: bind to '0.0.0.0:6600' failed (continuing anyway, because binding to '[::]:6600' succeeded): Failed to bind socket: Address already in use +mpd | exception: Failed to open '/root/.config/mpd/database': No such file or directory +mpd | exception: RTIOThread could not get realtime scheduling, continuing anyway: sched_setscheduler failed: Operation not permitted +mpd | avahi: Failed to create client: Daemon not running +``` + +You might also notice the following errors after the `mpd` Docker ran +for a while. Specifically the first error could fill up your console, +sometimes it stops with the second error message. It\'s not a problem, +sound continues to work. As a side effect, your CPU usage increases. +Just kill the process and restart. + +``` bash +mpd | alsa_mixer: snd_mixer_handle_events() failed: Input/output error +mpd | exception: Failed to read mixer for 'My ALSA Device': snd_mixer_handle_events() failed: Input/output error +``` + +### `jukebox` container + +Many features of the Phoniebox are based on the Raspberry Pi hardware. +This hardware can\'t be mocked in a virtual Docker environment. As a +result, a few plugins like RFID, GPIO or CPU temperature will throw +errors because they can\'t start successfully. Unless you want to +develop such plugins, you will be able to ignore these errors. The +plugin system is built in a way that the Jukebox daemon will come up. If +you want to develop plugins that require hardware support, you will have +to work on the hardware directly. + +Typical errors and following exceptions to be ignored in the Docker +`jukebox` container are: + +``` bash +jukebox | 634:plugs.py - jb.plugin - MainThread - ERROR - Ignoring failed package load finalizer: 'rfid.finalize()' +jukebox | 635:plugs.py - jb.plugin - MainThread - ERROR - Reason: FileNotFoundError: [Errno 2] No such file or directory: '/home/pi/RPi-Jukebox-RFID/shared/settings/rfid.yaml' +... +jukebox | 171:__init__.py - jb.host.lnx - MainThread - ERROR - Error reading temperature. Canceling temperature publisher. FileNotFoundError: [Errno 2] No such file or directory: '/sys/class/thermal/thermal_zone0/temp' +... +jukebox | 319:server.py - jb.pub.server - host.timer.cputemp - ERROR - Publish command from different thread 'host.timer.cputemp' than publisher was created from 'MainThread'! +``` + +## Appendix + +### Individual Docker Image + +Run an individual Docker container, e.g. `jukebox`. Similarly you could +run `mpd` or `webapp`. + +The following command can be run on a Mac. + +``` bash +$ docker build -f docker/jukebox.Dockerfile -t jukebox . +$ docker run -it --rm \ + -v $(PWD)/src/jukebox:/home/pi/RPi-Jukebox-RFID/src/jukebox \ + -v $(PWD)/shared/audiofolders:/home/pi/RPi-Jukebox-RFID/shared/audiofolders \ + -v ~/.config/pulse:/root/.config/pulse \ + -v /usr/local/Cellar/pulseaudio/14.2/etc/pulse/:/etc/pulse \ + -e PULSE_SERVER=tcp:host.docker.internal:4713 \ + --name jukebox jukebox +``` + +### Resources + +**Mac** + +- +- +- + +**Windows** + +- +- +- +- + +**Audio** + +- +- +- + +**MPD** + +- +- +- + +**ZMQ** + +- diff --git a/documentation/content/developers/known-issues.md b/documentation/content/developers/known-issues.md new file mode 100644 index 000000000..598ecd791 --- /dev/null +++ b/documentation/content/developers/known-issues.md @@ -0,0 +1,13 @@ +# Known Issues + +## Browsers + +The Web UI will **not** work with Firefox, due to an issue with websockets and pyzmq. Please use a different +browser for now. + +## Configuration + +In `jukebox.yaml` (and all other config files): do not use relative paths with `~/some/dir`. +Always use entire explicit path, e.g. `/home/pi/some/dir`. + +**Sole** exception is in `playermpd.mpd_conf`. diff --git a/documentation/content/developers/rfid/README.md b/documentation/content/developers/rfid/README.md new file mode 100644 index 000000000..0717ef661 --- /dev/null +++ b/documentation/content/developers/rfid/README.md @@ -0,0 +1,12 @@ +# RFID Readers + +* [Basics](basics.md) +* [Reader Types](basics.md#reader-types) +* [Reader Configuration](basics.md#reader-configuration) +* Readers + * [Generic USB Reader](genericusb.md) + * [RDM6300 Reader](rdm63000.md) + * [MFRC522 SPI Reader](mfrc522_spi.md) + * [PN532 I2C Reader](pn532_i2c.md) + * [Mock Reader](mock_reader.md) + * [Template Reader](template_reader.md) \ No newline at end of file diff --git a/documentation/content/developers/rfid/basics.md b/documentation/content/developers/rfid/basics.md new file mode 100644 index 000000000..f1e1bc499 --- /dev/null +++ b/documentation/content/developers/rfid/basics.md @@ -0,0 +1,93 @@ +# RFID + +## Basics + +Cards placed on the reader trigger an action. An action may be any +callable plugin function through the RPC with any arguments. Typically, +this would be "play some folder", but can also be "activate shutdown +timer", or "increase volume". This is configured in the +[Card Database](../userguide/card-database.md). + +You may configure a single or even multiple parallel readers (of +different or identical types). + +Successive card swipes are suppressed to avoid bouncing effects. This +behavior can be deactivated for individual cards. + +## Reader Types + +#### place-capable: + +Some readers give a single event signal when the card is placed on +the reader. This is sufficient to build a fully-featured Jukebox. +Other readers give a continuous signal. They allow both card +placements and card removals. This can be used to play the Jukebox +when a card is placed and to pause it when it's removed. + +Generally, **not** all [USB-based RFID readers](genericusb.md) are place-capable. + +The known place-capable readers are [RDM6300 Reader](rdm6300:RDM6300), [MFRC522 SPI Reader](mfrc522_spi:MFRC522) or [PN532 I2C Reader](pn532_i2c:PN532). + +#### Frequency: + +Readers operate on one of two different frequencies: 125kHz or 13.56 MHz. Make sure to buy compatible cards, RFID stickers or key fobs working with the same frequency as the reader. + +## Reader Configuration + +During the installation process, you can already configure a RFID +reader. To manually configure RFID reader(s), +[please run the tool](../developer/coreapps.md#run_register_rfid_reader.py), (`src/jukebox/run_register_rfid_reader.py`). + +It will generate a reader configuration file at +`shared/settings/rfid.yaml`. You can re-run the tool to change the +settings any time. + +Some options are not covered by the tool. You may change the file +manually. + +``` yaml +rfid: + readers: + read_00: + module: fake_reader_gui + config: .... + same_id_delay: float|integer + log_ignored_cards: true|false + place_not_swipe: + enabled: true|false + card_removal_action: + alias: pause +``` + +For each reader, there is an entry `read_XX`. + +#### module: + +Indicates the Python package used for this reader. Filled by the RFID configuration tool. + +#### config: + +Filled by the [RFID configuration tool](../developer/coreapps.md#run_register_rfid_reader.py) (`src/jukebox/run_register_rfid_reader.py`) based on default values and user input. After running the tool, you may manually change some settings here, as not everything can be configured through the tool. Note that re-running the tool will completely rewrite the configuration file. + +#### same_id_delay: float \| integer + +Minimum delay in seconds between 2 card detections before triggering a new action. This is to prevent double triggering or bouncing. + +#### place_not_swipe: true \| false + +For place-capable RFID readers enable dual action mode: a start action (e.g. playing) on card placement and card removal action (e.g. pause). + +#### card_removal_action: Dictionary + +Executes the given function on card removal. Only relevant if place_not_swipe is true. The action is identical for all cards read on that reader. The removal-action can be set to ignored on a card-by-card basis. More on card action configurations in [RPC Commands](../userguide/rpc-commands.md). + +> [!NOTE] +> Developer's note: The reason for a unique removal action for all cards is that card triggering and card removal are happening in two separate threads. Removal needs to be in a time-out thread. Thus, we would need to transport information from one thread to another. This can be done of course but is not implemented (yet). Ignoring card removal is much easier and works for now. + +#### log_ignored_cards: true \| false + +Log all cards that are ignored due to same_id_delay. This is a option for developers. Don't use it unless you need it for debugging as it has the potential to spam your log files. + +#### Second Swipe + +Looking for 'Second Swipe' option? That is part of the Player configuration and not part of the RFID configuration, as the 'Second Swipe' action needs to take into account the player state, which can also be altered through the WebUI. diff --git a/documentation/content/developers/rfid/genericusb.md b/documentation/content/developers/rfid/genericusb.md new file mode 100644 index 000000000..2f049291d --- /dev/null +++ b/documentation/content/developers/rfid/genericusb.md @@ -0,0 +1,14 @@ +# Generic USB Reader + +**place-capable**: typically no + +This module covers all types of USB-based RFID input readers. If you +plan to connect multiple USB-based RFID readers to the Jukebox, make +sure to connect all of them before running the registration tool [run_register_rfid_reader.py](../developers/coreapps.md). + +> [!NOTE] +> The user needs to be part of the group \'input\' for evdev to work. This should usually be the case. However, a user can be added with: +> +>``` bash +>sudo usermod -a -G input USER +>``` diff --git a/documentation/content/developers/rfid/mfrc522_spi.md b/documentation/content/developers/rfid/mfrc522_spi.md new file mode 100644 index 000000000..726136d61 --- /dev/null +++ b/documentation/content/developers/rfid/mfrc522_spi.md @@ -0,0 +1,81 @@ +# MFRC522 SPI Reader + +RC522 RFID reader via SPI connection. + +**place-capable**: yes + +## Installation + +Run the ref:[run_rfid_configuration]{.title-ref} tool for guided +installation. + +## Options + +In principle Raspberry PIs support multiple SPI interfaces. The reader +class is based on pi-rc522 which uses spidev. This allows to use +different SPI bus configurations. The below parameters regarding pin-out +are just routed through to spidev. Have a look at the spidev +documentation for details if you really want to use a different SPI bus. +The default setup makes most sense for almost everyone. + +#### spi_bus *(default=0)* + +The SPI Bus ID. The default bus is 0. For other bus IDs, the RPi also needs to re-configured. For that reason we set this to zero. + +#### spi_ce *(default=0)* + +SPI chip enable pin. On default SPI bus 0, this can be + +- 0 = GPIO8 (Pin 24) +- 1 = GPIO7 (Pin 26) + +For other SPI buses refer to RPi documentation. + +#### pin_irq + +Mandatory IRQ pin. This can be any GPIO pin. + +#### pin_rst *(default=0)* + +Reset pin for hardware reset. This is an optional pin. If not used, + +- hardware reset will only be performed by power-on-reset. This has been tested on works fine. +- you **must** tie the reset pin of the MFRC522 board **high**! + +#### mode_legacy *(default=false)* + +4-byte-only legacy mode: previously the pirc522 library could only read the lower 4 bytes of a card UID. It can now read 4-byte and full 7-byte UIDs. Legacy mode turns back to the old behaviour. This only makes sense, if you already have an large RFID collection and do not want to re-assign every card. + +#### antenna_gain *(default=4)* + +Antenna gain factor of the RFID reader chip on the MFRC522 board. + +#### log_all_cards *(default=false)* + +If true all card read-outs will be logged, even when card is permanently on reader. Only for debugging. + +## Board Connections + +The following pin-out is for the default SPI Bus 0 on Raspberry Pins. + +*MFRC522 default wiring (spi_bus=0, spi_ce=0)* +|Pin Board Name |Function |RPI GPIO |RPI Pin | +|----------------|----------|----------|---------| +|SDA |CE |GPIO8 |24 | +|SCK |SCLK |GPIO11 |23 | +|MOSI |MOSI |GPIO10 |19 | +|MISO |MISO |GPIO9 |21 | +|IRQ GND |IRQ |GPIO24 |18 | +|RST 3.3V |RST |GPIO25 |22 | + + +Some RC522 boards use reversed labeling for MOSI and MISO pins. The good +thing is, no harm is done to the card reader when incorrectly connected. +In case no cards are read, try swapping the connections for MOSI and +MISO. + +## Hardware + +MFRC522 boards can be picked up from many places for little money. + +Good quality ones can be found e.g. here diff --git a/documentation/content/developers/rfid/mock_reader.md b/documentation/content/developers/rfid/mock_reader.md new file mode 100644 index 000000000..da90d5405 --- /dev/null +++ b/documentation/content/developers/rfid/mock_reader.md @@ -0,0 +1,26 @@ +# Mock Reader + +A fake reader using a TK GUI for development purposes. This target +software development which does not happen on the RPi but on another +machine - probably in a Python virtual environment. + +**place-capable**: yes + +If you [mock the GPIO pins](../userguide/gpio.md), this GUI will show the GPIO devices. + +![image](mock_reader.png) + +> [!NOTE] +> When using Anaconda, the GUI will look horrible! That's because Anaconda's TK is compiled without FreeType support. +> +> There is a very quick and very dirty [fix](https://stackoverflow.com/questions/47769187/make-anacondas-tkinter-aware-of-system-fonts-or-install-new-fonts-for-anaconda). +> Replacing the TK lib in Anaconda's environment with the system `libtk`. +> However, this depends on an exact version match of the `libtk`. +> +>``` bash +>cd /path/to/anaconda3/envs/rpi/lib +>mv ./libtk8.6.so ./libtk8.6.so.bak +>ln -s /usr/lib/x86_64-linux-gnu/libtk8.6.so libtk8.6.so +>``` +> +>An alternative is to simply use Python's `venv` module to create a virtual environment. This uses your systems Python version and thus will work with your system `libtk`. It might not be the RPi's Python version - but that should not matter in most cases. diff --git a/docs/sphinx/rfid/mock_reader.png b/documentation/content/developers/rfid/mock_reader.png similarity index 100% rename from docs/sphinx/rfid/mock_reader.png rename to documentation/content/developers/rfid/mock_reader.png diff --git a/documentation/content/developers/rfid/pn532_i2c.md b/documentation/content/developers/rfid/pn532_i2c.md new file mode 100644 index 000000000..819f051f3 --- /dev/null +++ b/documentation/content/developers/rfid/pn532_i2c.md @@ -0,0 +1,53 @@ +# PN532 I2C Reader + +The PN532-based readers connected via I2C + +This reader module is based on the [py532lib +library](https://github.com/HubCityLabs/py532lib) and uses the I2C bus. +It utilizes a polling mechanism. It only needs 2 pins, but has a certain +performance overhead due to polling. + +## Options + +There are no configurable options for this module. + +## Hardware + +This reader module has been tested with the excellent and highly +recommendable [Adafruit PN532 breakout +board](https://www.adafruit.com/product/364). It also comes with [heaps +of documentation and even +schematics](https://learn.adafruit.com/adafruit-pn532-rfid-nfc/downloads). + +I have used various RFID boards and this one has an excellent reading +range and no problem with various types of cards and stickers. + +You can usually pick up a board at + +> - +> - + +## Board Connections + +*Default wiring* + +| PN532 | RPI GPIO | RPI Pin | +|-------|--------------|---------| +| 5V | 5V | > 4 | +| GND | GND | > 6 | +| SDA | GPIO 2 (SDA) | > 3 | +| SCL | GPIO 3 (SCL) | > 5 | + +Other pins from the Adafruit board need not be connected. Especially do +**not** connect the 3.3V pin, if connecting the 5.0V pin. It is +recommended to use the 5.0V because that does not draw power from the +PI's own voltage regulator. + +## Jumpers + +*Jumper settings for I2C protocol* + +Jumper | Position +-------|---------- +SEL0 | ON +SEL1 | OFF diff --git a/documentation/content/developers/rfid/rdm6300.md b/documentation/content/developers/rfid/rdm6300.md new file mode 100644 index 000000000..6cc47e563 --- /dev/null +++ b/documentation/content/developers/rfid/rdm6300.md @@ -0,0 +1,19 @@ +# RDM6300 Reader + +The RDM6300 / RDM630 connected via serial UART port + +**place-capable**: yes + +## Options + +Number Format + +## Board Connections + +The voltage level of the RX/TX is 3.3V despite the wide-spread belief +that it is 5V. (At least on the boards I have). I did check with an +oscilloscope. And one can easily identify the AMS1117 LDO voltage +regulator on the backside of the board. + +No warranties: If you meddle with GPIOs you are old enough to know the +risks of wrong voltage levels. diff --git a/documentation/content/developers/rfid/template_reader.md b/documentation/content/developers/rfid/template_reader.md new file mode 100644 index 000000000..77f3008c2 --- /dev/null +++ b/documentation/content/developers/rfid/template_reader.md @@ -0,0 +1,41 @@ +# Template Reader + +*Template for creating and integrating a new RFID Reader* + +> [!NOTE] +> For developers only + +This template provides the skeleton API for a new Reader. If you follow +the conventions outlined below, your new reader will be picked up +automatically There is no extra need to register the reader module with +the Phoniebox. Just re-run `the reader config tool `. + +Follow the instructions in [template_new_reader.py] + +Also have a look at the other reader subpackages to see how stuff works +with an example + +## File structure + +Your new reader is a python subpackage with these three mandatory files + +``` bash +components/rfid/hardware/awesome_reader/ + +- awesome_reader.py <-- The actual reader module + +- description.py <-- A description module w/o dependencies. Do not change the filename! + +- README.rst <-- The Readme +``` + +The module documentation must go into a separate file, called README.ME. + +## Conventions + +- Single reader per directory / subpackage +- reader module directory name and reader module file name must be + identical +- Obviously awesome_reader will be replaced with something more + descriptive. The naming scheme for the subpackage is + - \\_\\_\ + - e.g. generic_usb/generic_usb.py + - e.g. pn532_spi/pn532_spi.py + - ... diff --git a/documentation/content/developers/to-be-deleted-status.md b/documentation/content/developers/to-be-deleted-status.md new file mode 100644 index 000000000..68bbe6864 --- /dev/null +++ b/documentation/content/developers/to-be-deleted-status.md @@ -0,0 +1,244 @@ +## Feature Status + +**This is where we are in a nutshell:** Playing music from local folders via RFID trigger. We also built a new WebUI to control the Jukebox from a browser. + +There are a few things that are specifically not integrated yet: playing streams, podcasts, or Spotify. + +In the following is the currently implemented feature list in more detail. It also shows some of the shortcomings. However, the list is _not complete in terms of planned features_, but probably _reflects more of where work is currently being put into_. + +**For new contributors:** If you want to port a feature from version 2.X or implement a new feature, contact us. Open an issue or join us in the chat room. You may pick topics marked as open below, but also any other topic missing in the list below. As mentioned, that list is not complete in terms of open features. Check the [Contribution guide](https://github.com/MiczFlor/RPi-Jukebox-RFID/blob/future3/main/CONTRIBUTING.md). + +Topics marked _in progress_ are already in the process of implementation by community members. + +## Table of Contents + +- [Jukebox Core App](#jukebox-core-app) + - [Base](#base) + - [Via RPC](#via-rpc) + - [Config handler](#config-handler) + - [ZMQ Publisher](#zmq-publisher) + - [Playback](#playback) + - [MPD Player](#mpd-player) + - [RFID](#rfid) + - [Cards](#cards) + - [Timer](#timer) + - [Volume](#volume) + - [GPIO](#gpio) + - [WLAN](#wlan) + - [Spotify](#spotify) + - [Others](#others) + - [Start-up stuff](#start-up-stuff) +- [Debug Tools](#debug-tools) +- [WebUI](#webui) +- [Installation Procedure](#installation-procedure) +- [Documentation](#documentation) + +## Jukebox Core App + +### Base + +- [x] Clean up surplus files +- [x] Host interface (shutdown, reboot) +- [x] Temperature getter + - [x] Timer + Publisher +- [x] RPi is_throttled getter + - [x] Decode hex value to readable string (check version 2.x mqtt as reference?) + - [x] Timer + Publisher +- [x] Git hash log information + - [x] Log and publish this! +- [x] Version number getter (Version number should be stored in a python file) + - [x] Log and publish this +- [x] Exit via RPC +- [x] Service restart via RPC + - [x] Check if really running as a service +- [x] Storage space getter / publisher (shutil.disk_usage) +- [x] Getter for error logs to show in WebUI + - Get file location from FileHandlers (files may be stale!) + - Logger might be disabled or not connected +- [ ] Enable/Disable debug logging from RPC +- [x] Publisher of errors (specialized logger handler) + - This is a configurable logger handler in logger.yaml +- [x] Basic Logging Config should enable Publisher stream handler +- [ ] Disable Console Stream Handler (or set to warning) when running as a service +- [x] Log & publish start time +- [ ] Method to change configuration through WebUI + - The difficulty lies in bringing the running Jukebox to accept the changes. There probably won't be a catch-all solution but rather a custom implementation for a select few features +- [x] Strategy to post config changes via PubSub: Must be taken care of by the setter function modifying the property + +### Via RPC + +- [x] List of loaded / failed plugins +- [x] card action reference +- [x] Help command (available commands) + - which basically is a plugin reference +- [x] Simplified alias definitions for often used RPC commands (for RFID, GPIO, etc) + - [ ] Port all previous commands + - [x] Reference file write-out: now also included in Sphinx documentation + - [ ] Export available alias definitions to RPC + - [ ] Base quick select on yaml file (_in progress_) + - or write a yaml file as an artifact that contains all the meta information about the functions as well? + - or include a `get_signature` function that returns the meta information for a given alias + +### Config handler + +- [x] While saving config to disk: local file change detection +- [x] cfghandler creates setndefault() at an arbitrary depth + +### ZMQ Publisher + +- [x] Last Value Cache +- [x] Subscriber detection and initial status update +- [x] Port configuration option (WS and/or TCP) +- [ ] Callback registration option for plugin on topic send + - How to interact with threads? + +### Playback + +- [x] Playlist generator + - [x] Local folders + - [x] Non-recursive folder play + - [x] Recursive folder play + - [x] Podcast + - [x] Livestreams + - [x] NEW: Playback of m3u playlists (e.g., folder.m3u) ? + +- [ ] Folder configuration (_in progress_) + - [ ] [Reference](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#manage-playout-behaviour) + - [ ] Resume: Save and restore position (how interact with shuffle?) + - [ ] Single: Enable mpc single + - [ ] Shuffle: Enable mpc random (not shuffle) + - Rename to random, as this is mpc random + - [ ] Loop: Loop playlist + +### MPD Player + +- [ ] Thread safety for status information / configuration (_in progress_) +- [ ] Differential status post (_in progress_) +- [ ] Second swipe option setter via RPC (_in progress_) +- [ ] Before every music lib update, player should check user rights (not only after start-up) + +### RFID + +- [x] Test with Reader disabled +- [x] Start-up behavior with un-configured Reader +- [x] Command card -> is now parameter ignore_same_id_delay +- [x] Revised RFID reader user-query setup script + - [ ] Ask for place option +- [ ] Enable config flag ? +- [x] Place not swipe / Timer thread + - [x] Configurable card removal action +- [x] Readers support + - [x] USB (e.g., Neuftech) + - [x] RDM6300 + - [x] MFRC522 + - [x] RC532 + - [x] Multi-reader support + - [x] GUI Fake Reader for Development + - [ ] PC/SC Cards (what actually is this?) +- [x] Publish RFID Card ID via PubSub + - Needs to be thread safe +- [x] Card reference IF via RPC +- [x] Second Swipe Options -> must be part of player control (partially broken at the moment) + - Freely configurable with an RPC call + - Ignore (nothing) + - Toggle Pause/Play + - Skip to the next track + - Re-start playlist + +### Cards + +- [ ] Write a simplified card summary to + - [ ] file + - [x] RPC +- [ ] Card assignment function for WebUI + - [x] Via RPC command alias definitions + - [ ] Full custom RPC call +- [x] Remove card + +### Timer + +- [x] Shutdown timer +- [x] Play stop timer +- [x] Shutdown timer volume reduction + - Decreases volume every x min until zero, then shuts down + - Needs to be cancelable +- [x] Publish mechanism of timer status +- [x] Change multitimer function call interface such that endless timer etc. won't pass the `iteration` kwarg +- [ ] Make timer settings persistent +- [ ] Idle timer + - This needs clearer specification: Idle is when no music is playing and no user interaction is taking place + - i.e., needs information from RPC AND from player status. Let's do this when we see a little clearer about Spotify + +### Volume + +- [x] Jingle playback volume as a fixed value in config +- [x] Default volume setting after boot-up +- [x] Max Volume +- [x] PulseAudio integration with event handler +- [x] Bluetooth support +- [x] Automatic audio sink toggle + - [ ] Callbacks for audio sink change + +### GPIO + +- [x] All done! Read the docs at [GPIO Recipes](#userguide/gpioz:GPIO Recipes)! +- [ ] USB Buttons: It's a different category as it works similar to the RFID cards (in progress) + +### WLAN + +- [x] Ad-hoc WLAN Hotspot +- [x] IP address read-out + +### Spotify + +- [ ] Everything + +### Others + +- [ ] MQTT +- [ ] Record and Playback using a Mic +- [ ] Dot Matrix Displays + +### Start-up stuff + +- [x] check music folder permissions +- [x] mpc update / (mpc rescan) +- [x] sudo iwconfig wlan0 power off (need to be done after every restart) +- [x] Optional power down HDMI circuits: /usr/bin/tvservice -o + +## Debug Tools + +- [x] Publishing Sniffer + - [ ] Update mode vs. linear mode? +- [x] RPC command line client + - [x] with tab-completion and history + +## WebUI + +- [x] Playback Control +- [x] Cover Art +- [x] Register cards / Delete cards +- [x] Shutdown button +- [ ] Settings configuration page +- [ ] System information page + - [ ] Configure (one or multiple) WLANs + - [x] Enable/Disable Auto-Hotspot +- [x] `run_npm_build` script + - [x] Must consider `export NODE_OPTIONS=--max-old-space-size=512` + +## Installation Procedure + +- [x] Single call installation script +- [x] Query for settings vs. automatic version +- [x] IPQoS in SSH config +- [x] Separate static IP and IPv6 disable +- [ ] For all system config file changes, check prior to modification if modification already exists + +## Documentation + +- [x] Sphinx / Restructured Text tool flow +- [ ] What is the Phoniebox +- [x] Artifacts: Generate artifacts (on command line switch only) for + - [x] loaded plugins and rpc command aliases (to sphinx and shared/artifacts) + - [x] rpc command aliases (to sphinx and shared/artifacts) +- [ ] How to: Write a plugin diff --git a/documentation/content/userguide/audio.md b/documentation/content/userguide/audio.md new file mode 100644 index 000000000..fb3271197 --- /dev/null +++ b/documentation/content/userguide/audio.md @@ -0,0 +1,141 @@ +# Audio + +## Configuration + +The Jukebox supports 2 audio outputs, primary and secondary. The **primary output** is the default output and must +be available after system boot. This will typically be your sound card or the Pi's built-in headphone output. + +The **secondary output** is an optional alternative output where the audio stream can be routed to. +Stream transfer happens on user input or automatically on the connection of an audio device. +This is mainly targeted at Bluetooth Headsets/Speakers. + +Audio outputs run via PulseAudio and the basic configuration should be easy. +There is a [configuration tool](..developers/coreapps#run_configure_audio.py), +to setup the configuration for the Jukebox Core App. + +To set up the audio + +1. Follow the setup steps according to your sound card +2. Check that the sound output works [as described below](audio.md#checking-system-sound-output) +3. Run the the tool [run_configure_audio](developers/coreapps.md#run_configure_audio.py) +4. [Fine-tune audio parameters](audio.md#additional-options) + +## Checking system sound output + +Run the following steps in a console: + +```bash +# Check available PulseAudio sinks +$ pactl list sinks short +0 alsa_output.platform-soc_sound.stereo-fallback module-alsa-card.c s16le 2ch 48000Hz +1 bluez_sink.C4_FB_20_63_CO_FE.a2dp_sink module-bluez5-device.c s16le 2ch 44100Hz + +# Set the default sink (this will be reset at reboot) +$ pactl set-default-sink sink_name + +# Check default sink is correctly set +$ pactl info +.... +# Check volume level (exit with ESC) +$ alsamixer + +# Play a sound +$ paplay /usr/share/sounds/alsa/Front_Center.wav + +# This must also work when using an ALSA device +$ aplay /usr/share/sounds/alsa/Front_Center.wav +``` + +You can also try different PulseAudio sinks without setting the default sink. In this case the volume is the last used +volume level for this sink: + +```bash +$ paplay -d sink_name /usr/share/sounds/alsa/Front_Center.wav +``` + +# Bluetooth + +Bluetooth setup consists of three steps + +1. Pair and connect your Bluetooth device +2. Check the output works +3. Re-run the config tool + +To pair and connect, follow these steps. This will be a one-time setup. + +```bash +$ bluetoothctl +Agent registered +[CHG] Controller B8:27:EB:44:C4:33 Pairable: yes +#### Put your headset into pairing mode +[bluetooth]# scan on +Discovery started +#### Wait a few seconds for your device to appear +.... +[NEW] Device C4:FB:20:63:CO:FE PowerLocus Buddy +.... +[bluetooth]# scan off +.... +[bluetooth]# pair C4:FB:20:63:CO:FE +.... +Pairing successful +.... +[bluetooth]# trust C4:FB:20:63:CO:FE +.... +[bluetooth]# connect C4:FB:20:63:CO:FE +.... +[PowerLocus Buddy]# exit +``` + +Wait for a few seconds and then with `$ pactl list sinks short`, check wether the Bluetooth device shows up as an output. +Its name usually looks like this: `bluez_sink.C4_FB_20_63_CO_FE.a2dp_sink`. + +Run through steps above to check wether the output is working or not. +If it does not work immediately, turn your headset off and on to force a reconnect. + +Rerun the config tool to register the Bluetooth device with the Jukebox core app as its secondary audio output. + +## Additional options + +For other audio configuration options, please look at the `jukebox.yaml` for now. + +Directly edit `jukebox.yaml` following the steps: [Best practice procedure](.md#best-practice-procedure). + + +## Developer Information + +The optional processing stages *Equalizer* and *Mono down mix* are realized by PulseAudio plugins. The processing chain is +``` +player --> mono mix --> equalizer --> hardware sink +``` + +Both plugins (if enabled) appear in the PulseAudio sinks + +```bash +$ pactl list sinks short +``` + +Which means we can put any of these as sink into the jukebox configuration file (if there is any need). + +Mono down mix is enabled by the module `module-remap-sink` +for which documentation and an example can be found [here](https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/Modules/#module-remap-sink>). + +The equalizer is the PulseAudio module `module-ladspa-sink` with the [corresponding documentation](https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/Modules/#module-ladspa-sink>). + +This in turn loads a [LADSPA plugin](https://www.ladspa.org/). +The LADSPA plugin in the `Eq10X2` plugin of the [CAPS Library](http://quitte.de/dsp/caps.html#Eq10>). The CAPS library is available as linux package `caps`. + +This is the same plugin which is used in the +[equalizer for pure ALSA](https://github.com/raedwulf/alsaequal>) +configurations which is part of the linux package `libasound2-plugin-equal`. + +You are, of course, free to modify the PulseAudio configuration to your needs. References + +1. [PulseAudio Documentation](https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User>) +2. [PulseAudio Examples](https://wiki.archlinux.org/title/PulseAudio/Examples>) + +In this case, run the configuration tool with below parameter to avoid touching the PulseAudio configuration file. + +```bash +$ ./run_configure_audio.py --ro_pulse +``` diff --git a/documentation/content/userguide/autohotspot.md b/documentation/content/userguide/autohotspot.md new file mode 100644 index 000000000..a283a94f2 --- /dev/null +++ b/documentation/content/userguide/autohotspot.md @@ -0,0 +1,107 @@ +# Auto-Hotspot + +The Auto-Hotspot function allows the Jukebox to switch between its +connection between a known WiFi and an automatically generated hotspot +so that you can still access via SSH or Webapp. + +> [!IMPORTANT] +> Please configure the WiFi connection to your home access point before enabling these feature! + +To create a hotspot and allow clients to connect +[hostapd](http://w1.fi/hostapd/) and [dnsmasq](https://thekelleys.org.uk/dnsmasq/doc.html). + +## How to connect + +When the Jukebox is not able to connect to a known WiFi it will create a +hotspot named `Phoniebox_Hotspot`. You will be able to connect to this +hotspot using the given password in the installation or the default +password: `PlayItLoud!` + +### Webapp + +After connecting to the `Phoniebox_Hotspot` you are able to connect to +the webapp accessing the website [10.0.0.5](http://10.0.0.5/). + +### ssh + +After connecting to the `Phoniebox_Hotspot` you are able to connect via +ssh to your Jukebox + +``` bash +ssh pi@10.0.0.5 +``` + +## Changing basic configuration of the hotspot + +The whole hotspot configuration can be found at +`/etc/hostapd/hostapd.conf`. + +The following parameters are relevant: + +- `ssid` for the displayed hotspot name +- `wpa_passphrase` for the password of the hotspot +- `country_code` the country you are currently in + +``` bash +$ cat /etc/hostapd/hostapd.conf + +#2.4GHz setup wifi 80211 b,g,n +interface=wlan0 +driver=nl80211 +ssid=Phoniebox_Hotspot +hw_mode=g +channel=8 +wmm_enabled=0 +macaddr_acl=0 +auth_algs=1 +ignore_broadcast_ssid=0 +wpa=2 +wpa_passphrase==PlayItLoud! +wpa_key_mgmt=WPA-PSK +wpa_pairwise=CCMP TKIP +rsn_pairwise=CCMP + +#80211n - Change GB to your WiFi country code +country_code=DE +ieee80211n=1 +ieee80211d=1 +``` + +## Disabling automatism + +Auto-Hotspot can be enabled or disabled using the Webapp. + +> [!IMPORTANT] +> Disabling or enabling will keep the last state. + +## Troubleshooting + +### Phoniebox is not connecting to the known WiFi + +The script will fall back to the hotspot so you still have some type of +connection. + +Check your password in `/etc/wpa_supplicant/wpa_supplicant.conf`. + +### AutoHotspot functionality is not working + +You can check the output of the script by running the following script: + +``` bash +$ sudo /usr/bin/autohotspot +``` + +### You need to add a new wifi network to the Raspberry Pi + +Because it is in Auto-Hotspot mode, you won\'t be able to scan for new +wifi signals. + +You will need to add a new network to +`/etc/wpa_supplicant/wpa_supplicant.conf` manually. Enter the following +details replacing mySSID and myPassword with your details. If your WiFi +has a hidden SSID then include the line `scan_ssid=1`. + +## Resources + +[Raspberry Pi - Auto WiFi Hotspot Switch - Direct +Connection](https://www.raspberryconnect.com/projects/65-raspberrypi-hotspot-accesspoints/158-raspberry-pi-auto-wifi-hotspot-switch-direct-connection) diff --git a/documentation/content/userguide/bluetooth-audio-buttons.md b/documentation/content/userguide/bluetooth-audio-buttons.md new file mode 100644 index 000000000..ff419ccc4 --- /dev/null +++ b/documentation/content/userguide/bluetooth-audio-buttons.md @@ -0,0 +1,63 @@ +# Bluetooth + +## Bluetooth Audio Buttons + +When a bluetooth sound device (headphone, speakers) connects attempt to +automatically listen to it's buttons (play, next, etc.) + +The bluetooth input device name is matched automatically from the +bluetooth sound card device name. During boot up, it is uncertain if the +bluetooth device connects first, or the Jukebox service is ready first. +Therefore, after service initialization, already connected bluetooth +sound devices are scanned and an attempt is made to find their input +buttons. + +> [!NOTE] +> If the automatic matching fails, there currently is no manual configuration option. Open an issue ticket if you have problems with the automatic matching. + +Button key codes are standardized and by default the buttons play, +pause, next song, previous song are recognized. Volume up/down is +handled independently from this module by PulseAudio and the bluetooth +audio transmission protocol. + +The module needs to be enabled in the main configuration file with: + +``` yaml +bluetooth_audio_buttons: + enable: true +``` + +### Custom key bindings + +You may change or extend the actions assigned to a button in the +configuration. If the configuration contains a block 'mapping', the +default button-action mapping is *completely* replaced with the new +mapping. The definitions for each key looks like +`key-code: {rpc_command_definition}`. The RPC command follows the +regular RPC command rules as defined in +[RPC Commands](rpc-commands.md). + +``` yaml +bluetooth_audio_buttons: + enable: true + mapping: + # Play & pause both map to toggle which is also the usual behaviour of headsets + 200: + alias: toggle + 201: + alias: toggle + # Re-map next song button, to set defined output volume (for some fun) + 163: + package: volume + plugin: ctrl + method: set_volume + args: [18] + # Re-map prev song button to shutdown + 165: + alias: shutdown +``` + +Key codes can be found in the log files. Press the various buttons on +your headset, while watching the logs with e.g. +`tail -f shared/logs/app.log`. Look for entries like +`No callback registered for button ...`. diff --git a/documentation/content/userguide/card-database.md b/documentation/content/userguide/card-database.md new file mode 100644 index 000000000..66d4e3925 --- /dev/null +++ b/documentation/content/userguide/card-database.md @@ -0,0 +1,101 @@ +# Card Database + +In the card database, an RPC command is assigned to every card. + +This RPC command is called every time when the card is swiped (or +placed) on the reader. Every RPC callable function can be called. See +[RPC Commands](userguide/rpc_commands.md) for an introduction. + +The card database is stored in `shared\settings\cards.yaml`. Here are +some examples for RPC command assignments to cards \'0001\' to \'0003\' +using the alias option: + +> [!IMPORTANT] +> Card IDs **must** be strings! So, be sure to quote numbers! + +``` yaml +'0001': + # A RPC command using the alias definition without any arguments + # Here: pause playback + alias: pause +'0002': + # A RPC command using the alias definition with one arguments + # Here: Trigger music playback through the card interface + alias: play_card + args: [path/to/folder] +'0003': + # A RPC command using keyword arguments. Args and kwargs can also be mixed. + # Args and Kwargs translate directly into the function python call + # Some as in '0002' but using kwargs + alias: play_card + kwargs: + folder: path/to/folder +``` + +> [!NOTE] +> * Remember card ids must be strings! So, quote them! +> * *args* must be +a **list** of arguments to be passed! Even if ony a single argument is +passed. So, use *args: \[value\]*. We try catch mis-uses but that might +not always work. + +## Additional options + +In addition to the RPC commands, these options may be specified for +every card + +#### ignore_card_removal_action: true \| false (default: false) + +Only applies when using a place-capable reader and *place_not_swipe* is *true*. This option is ignored otherwise, so it does not hurt. + +Do not execute card removal action, when this card is removed from +the reader. Useful for command card, that e.g. enable the shutdown +timer + +``` yaml +'0004': + alias: timer_shutdown + ignore_card_removal_action: true +``` + +#### ignore_same_id_delay: true \| false (default: false) + +Override the `same_id_delay` parameter from the reader configuration +for this card. If true, the `same_id_delay` for this card is treated +as 0. This makes sense e.g., for an \"increase volume\" card in +combination with a place-capable RFID reader. As long as the card is +placed on the reader, the volume is increased. + +> [!NOTE] +> This parameter causes *ignore_card_removal_action* to be treated as true + +``` yaml +'0005': + alias: incr_volume + ignore_same_id_delay: true + ignore_card_removal_action: true +``` + +## Full RPC action specification + +You have seen some examples card actions using the *alias* +configuration. A full RPC action can also be specified using the +following syntax: + +``` yaml +'0006': + # Option 1: Omit the keyword 'alias' + # Here: Set the volume to level 12 + package: volume + plugin: ctrl + method: set_volume + args: [12] +'0007': + # Option 2: Set 'alias' to custom + # Here: Set the volume to level 12 + alias: custom + package: volume + plugin: ctrl + method: set_volume + args: [12] +``` diff --git a/documentation/content/userguide/concepts.md b/documentation/content/userguide/concepts.md new file mode 100644 index 000000000..509f474fc --- /dev/null +++ b/documentation/content/userguide/concepts.md @@ -0,0 +1,27 @@ +# Concepts + +The Jukebox is based on three concepts. Don't worry, we won't dive into all the juicy developer details (just yet). But a rough understanding is important as a foundation to understand the configuration files. + +## Plugin Interface + +The core app is centered around a plugin concept. This serves three purposes: + +1. Dynamically load packages with additional functionality based on configuration files. +2. Initialize and close these packages at app start/close. This happens automatically in the background. Failing packages (for any reason) are ignored during start-up. So when some functionality is not available, always check the logs to ensure all packages have loaded successfully! See [Troubleshooting](troubleshooting.md). +3. Register and present functions that can be called via the [Remote Procedure Call Server (RPC)](#remote-procedure-call-server-rpc). + +## Remote Procedure Call Server (RPC) + +The Remote Procedure Call (RPC) server allows remotely triggering actions (e.g., from the Webapp) within the Jukebox core application. Only Python functions registered by the plugin interface can be called. This simplifies external APIs and lets us focus on the relevant user functions. + +Why should you care? Because we use the same protocol when triggering actions from other inputs like a card swipe, a GPIO button press, etc. How that works is described in [RPC Commands](rpc-commands.md). + +You will find a full list of RPC callable functions in [RPC Command Reference](rpc-command-reference.md) and aliases for convenience in [RPC Command Alias Reference](rpc-command-alias-reference.md). + +We also have a tool to send RPC commands to the running Jukebox application: [run_rpc_tool.py](src/jukebox/run_rpc_tool.py). + +## Publishing Message Queue + +The Publishing Message Queue is the complementary part to the RPC where the core application publishes its status and status updates. As a user, you need not worry about it. + +If you want to interact with the Jukebox from your own application, this is where you get the current state from. Details about the protocol can be found here (TBD). A sniffer tool exists which listens and prints the incoming status messages: [run_publicity_sniffer.py](src/jukebox/run_rpc_tool.py). diff --git a/documentation/content/userguide/configuration.md b/documentation/content/userguide/configuration.md new file mode 100644 index 000000000..d23cce01f --- /dev/null +++ b/documentation/content/userguide/configuration.md @@ -0,0 +1,40 @@ +# Jukebox Configuration + +The Jukebox configuration is managed by set of files located in `../shared/settings`. +Some configuration changes can be made through the WebUI and take immediate effect. + +The majority of configuration options is only available by editing the config files - +*when the service is not running!* +Don't fear (overly), they contain commentaries. + +For several aspects we have :ref:`developer/coreapps:Configuration Tools` and detailed guides: + +* [Audio Configuration](userguide/audio.md#audio-configuration) +* [RFID Reader Configuration](rfid/basics.md#reader-configuration) + +Even after running the tools, certain aspects can only be changed by modifying the configuration files directly. + +## Best practice procedure + +```bash +# Make sure the Jukebox service is stopped +$ systemctl --user stop jukebox-daemon + +# Edit the file(s) +$ nano ./shared/settings/jukebox.yaml + +# Start Jukebox in console and check the log output (optional) +$ ./src/jukebox/run_jukebox.py +# and if OK, press Ctrl-C and restart the service + +# Restart the service +$ systemctl --user start jukebox-daemon +``` + +To try different configurations, you can start the Jukebox with a custom config file. +This could be useful if you want your Jukebox to only allow a lower volume when started +at night time when there is time to go to bed :-) + +```bash +$./run_jukebox.py --conf ../path/to/custom/config.yaml +``` diff --git a/documentation/content/userguide/installation.md b/documentation/content/userguide/installation.md new file mode 100644 index 000000000..e84b5de05 --- /dev/null +++ b/documentation/content/userguide/installation.md @@ -0,0 +1,93 @@ +# Installing Phoniebox future3 + +## Install Raspberry Pi OS Lite + +> [!IMPORTANT] +> Currently, the installation does only work on Raspberry Pi's with ARMv7 and ARMv8 architecture, so 2, 3 and 4! Pi 1 and Zero's are currently unstable and will require a bit more work! + +Before you can install the Phoniebox software, you need to prepare your Raspberry Pi. + +1. Connect a Micro SD card to your computer (preferable an SD card with high read throughput) +2. [Download](https://www.raspberrypi.org/software/) + the [Raspberry Pi Imager](https://www.raspberrypi.org/blog/raspberry-pi-imager-imaging-utility/>) and open it +3. Select **Raspberry Pi OS Lite (32-bit)** (without desktop environment) as the operating system. future3 does not support 64bit kernels (`aarch64`). You can use the settings menu of the Raspberry Pi Imager to configure SSH and WiFi in a more userfriendly way, or do it manually as described in the next step. In case you already have a 64bit system installed, [you can fix the issue like this](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/2041>). +4. Select your Micro SD card (your card will be formatted) +5. Click *Write* +6. Wait for the imaging process to be finished (it'll take a few minutes) + + +## Pre-boot preparation + +You will need a terminal, like PuTTY for Windows or the Terminal app for Mac to proceed with the next steps. + +1. Open a terminal of your choice. +2. Insert your card again if it has been ejected automatically. +3. Navigate to your SD card e.g., `cd /Volumes/boot` for Mac or `D:` for Windows. +4. Enable SSH by adding a simple file. + + ```bash + $ touch ssh + ``` + + +5. Set up your Wifi connection. + + *Mac* + + ```bash + $ nano wpa_supplicant.conf + ``` + + *Windows* + + ```bash + D:\> notepad wpa_supplicant.conf + ``` + +6. Insert the following content, update your country, Wifi credentials and save the file. + + ``` + country=DE + ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev + update_config=1 + + network={ + ssid="network-name" + psk="network-password" + } + ``` + +7. Eject your SD card and insert it into your Raspberry Pi. +8. Start your Raspberry Pi by attaching a power supply. +9. Login into your Raspberry Pi, username is `pi` and password is `raspberry`. + If `raspberrypi.local` does not work, find out your Raspberry Pi's IP address from your router. + +## Install Phoniebox software + +Run the following command in your SSH terminal and follow the instructions + +```bash +cd; bash <(wget -qO- https://raw.githubusercontent.com/MiczFlor/RPi-Jukebox-RFID/future3/main/installation/install-jukebox.sh) +``` + +This will get the latest stable release from the branch future3/main. +To install directly from a specific branch and/or a different repository +specify the variables like this: + +```bash + +cd; GIT_USER='MiczFlor' GIT_BRANCH='future3/develop' bash <(wget -qO- https://raw.githubusercontent.com/MiczFlor/RPi-Jukebox-RFID/future3/develop/installation/install-jukebox.sh) +``` + +This will switch directly to the specified feature branch during installation. + +> [!NOTE] +> For all branches *except* the current Release, you will need to build the Web App locally on the Pi. This is not part of the installation process due to memory limitation issues. See [Steps to install](developers/development-environment#steps-to-install) + + +If you suspect an error you can monitor the installation-process with + +```bash +cd; tail -f INSTALL-.log +``` + diff --git a/docs/sphinx/userguide/mock_gpio.png b/documentation/content/userguide/mock_gpio.png similarity index 100% rename from docs/sphinx/userguide/mock_gpio.png rename to documentation/content/userguide/mock_gpio.png diff --git a/documentation/content/userguide/rfid.md b/documentation/content/userguide/rfid.md new file mode 100644 index 000000000..f8826f68f --- /dev/null +++ b/documentation/content/userguide/rfid.md @@ -0,0 +1,80 @@ +# RFID + +## Syncronisation RFID Cards + +This component handles the synchronisation of RFID cards (audiofolder +and card database entries). + +It allows to manage card database entries and audiofiles of one to many +Phonieboxes in a central place (e.g. NAS, primary Phoniebox etc.) in the +network, but allows to play the audio offline once the data has synced. +The synchronisation can be initiated with the command `sync-all` and +optionally on every RFID scan for a particular CardID and its +corresponding audiofolder. To execute the `sync-all` command, bind a +RFID card to the command. For the \"RFID scan sync\" feature, activate +the option in the configuration or bind a RFID card to the command for +dynamic activation or deactivation. + +### Synchronisation + +The synchronisation will be FROM a server TO the Phoniebox, overriding +existing files. A local configuration will be lost after the +synchronization. If you want to make the initial setup e.g. via WebUi +copy the files and use it as a base for the server. + +To access the files on the server, 2 modes are supported: SSH or MOUNT. +Please make sure you have the correct access rights to the source and +use key-based authentication for SSH. + +#### RFID scan sync + +If the feature \"RFID scan sync\" is activated, there will be a check on +every RFID scan against the server if a matching card entry and audiofolder is available. If so, changes will be synced. The playback +will be delayed for the time the data is transfered (see \"sync-all\" to +use a full synchronization if a lot of new files have been added). If +the server is not reachable, the check will be aborted after the +timeout. Therfore, an unreachable server will cause a delay (see +commands to toggle activation state). Deleted card entries / +audiofolders (not the contained items) will not be purged locally if +deleted on remote. This is also true for changed card entries (the old +audiofolder / -files will remain). To remove not existing items us a +\"sync-all\". + +### Configuration + +Set the corresponding setting in `shared\settings\jukebox.yaml` to +activate this feature. + +``` yaml +modules: + named: + ... + sync_rfidcards: synchronisation.rfidcards + +... +sync_rfidcards: + enable: false + config_file: ../../shared/settings/sync_rfidcards.yaml +``` + +The settings file (`shared\settings\sync_rfidcards.yaml`) contains the +following configuration + +``` yaml +sync_rfidcards: + # Holds the activation state of the optional feature "RFID scan sync". Values are "TRUE" or "FALSE" + on_rfid_scan_enabled: true # bool + # Server Access mode. MOUNT or SSH + mode: mount # 'mount' or 'ssh' + credentials: + # IP or hostname of the server (used to check connectivity and for SSH mode). e.g. "192.168.0.2" or "myhomeserver.local" + server: '' + # Port (used to check connectivity and for SSH mode). e.g. "80" or "22" + port: # int + # Timeout to reach the server (in seconds) (used to check connectivity). e.g. 1 + timeout: 1 # int + # Path to the shared files to sync (without trailing slash) (remote path for SSH mode or local path for MOUNT mode). e.g. "/mnt/Phoniebox" + path: '' + # Username if SSH mode is used. + username: '' +``` diff --git a/documentation/content/userguide/system.md b/documentation/content/userguide/system.md new file mode 100644 index 000000000..a9e4a162e --- /dev/null +++ b/documentation/content/userguide/system.md @@ -0,0 +1,112 @@ +# System Setup + +A few words on how the system is setup and interacts. + +The system consists of + +1. [Music Player Daemon (MPD)](system.md#music-player-daemon-mpd) which we use for all music playback (local, stream, podcast, ...) +2. [PulseAudio](system.md#pulseaudio) for flexible audio output support +3. [Jukebox Core Service](system.md#jukebox-core-service) for controlling MPD and PulseAudio and providing all the features +4. [Web UI](system.md#web-ui) which is served through an Nginx web server +5. A set of [Configuration Tools](../developer/coreapps.md#configuration-tools) and a set of [Developer Tools](../developer/coreapps.md#developer-tools) + +.. note:: The default install puts everything into the folder `/home/pi/RPi-Jukebox-RFID`. + Another folder might work, but is certainly not tested. Things are installed for the default user `pi`. Again, + another user might work, but is not tested. + +## Music Player Daemon (MPD) + +The Music Player Daemon runs as *user-local* service (not as system-wide service which is usually the default). +This is important for the interaction with PulseAudio. + +You will find the MPD configuration file under + +```text +$HOME/.config/mpd/mpd.conf +``` + +All MPD *var*-files are also located in `$HOME/.config/mpd`. + +The service can be controlled with the *systemctl*-command when adding the parameter `--user`: + +```bash +$ systemctl --user status mpd +$ systemctl --user start mpd +$ systemctl --user stop mpd +``` + +.. important:: Never start or enable the system-wide MPD service with `sudo systemctl start mpd`! + +To check if MPD is running or has issues, use + +```bash +$ systemctl --user status mpd +# or, if you need to get the full logs +$ journalctl --user -b -u mpd +``` + +The `systemd` service file is located at the default location for user services: + +``` +/usr/lib/systemd/user/mpd.service +``` + +## PulseAudio + +We use PulseAudio for the audio output configuration. Check out the Audio Configuration page for details. + +There is a number of reasons for that: + +* It is easier to support and setup different audio hardware. Over the years, many builders have tried many different ways to set up audio on their Jukebox so this become the most reliable and compatible solution +* We can cleanly control and switch between different audio outputs independent of the playback software +* The current Pi OS based on Bullseye does not allow another way to control Bluetooth based speakers, as Bluealsa is currently not working with Bluez 5 + +The PulseAudio configuration file is located at + +``` +~/.config/pulse/default.pa +``` + +Service control and service configuration file location is identical to MPD. + +## Jukebox Core Service + +The :ref:`developer/coreapps:Jukebox Core` runs as a *user-local* service with the name `jukebox-daemon`. +Similar to MPD, it's important that it does run as system-wide service to be able to interact with PulseAudio. + +The service can be controlled with the `systemctl`-command by adding the parameter `--user` + +```bash +$ systemctl --user start jukebox-daemon +$ systemctl --user stop jukebox-daemon +``` + +Check out the service with + +```bash +$ systemctl --user status jukebox-daemon +# and if you need to get the full log output +$ journalctl --user -b -u jukebox-daemon +``` + +The `systemd` service file is located at the default location for user services: + +``` +/usr/lib/systemd/user/jukebox-daemon.service +``` + +Starting and stopping the service can be useful for debugging or configuration checks. + +## Web UI + +The Web UI is served using nginx. Nginx runs as a system service. The home directory is localed at + +``` +/home/pi/RPi-Jukebox-RFID/src/webapp/build +``` + +The Nginx configuration is located at + +``` +/etc/nginx/sites-available/default +``` diff --git a/documentation/content/userguide/troubleshooting.md b/documentation/content/userguide/troubleshooting.md new file mode 100644 index 000000000..a0618ab5d --- /dev/null +++ b/documentation/content/userguide/troubleshooting.md @@ -0,0 +1,97 @@ +# Troubleshooting + +We have made a point of providing extensive log messages. +In full debug mode, this may become very verbose. In fact, better observability +has been one of the design goals for version 3. + +There are various options to get access to debug information. + +Debugging your setup runs in several steps + +1. Check that [audio output works](audio.md#checking-system-sound-output) +2. Check that [MPD works](system.md#music-player-daemon-mpd) +3. Checking log messages from the Jukebox Core App as described below + +## The short answer + +```bash +../shared/logs/app.log : Complete Debug Messages +../shared/logs/errors.log: Only Errors and Warnings +``` + +These files always contain the messages of the current run only. +The logs of previous runs are post-fixed with `.1`, e.g. `app.log.1`. This is useful for debugging issues during +shutdown of the service. + +The logs are also available via the Web Server: + +``` +http://ip.of.your.box/logs +``` + +> [!IMPORTANT] Always check the time modification date or the beginning of the log file to ensure you are not looking at an old log file! + +## The long answer: A few more details + +If started without parameters, the Jukebox checks for the existence of `../shared/settings/logger.yaml` +and if present, uses that configuration for logging. This file is created by the installation process. +The default configuration file is also provided in `../resources/default-settings/logger.default.yaml`. +We use Python's logging module to provide the debug messages which is configured through this file. + +**We are still in the Pre-Release phase which means full debug logging is enabled by default.** + +### Default logging configuration + +The default logging config does 2 things: + +1. It writes 2 log files: + +```bash +../shared/logs/app.log : Complete Debug Messages +../shared/logs/errors.log : Only Errors and Warnings +``` + +2. Prints logging messages to the console. If run as a service, only error messages are emitted to console to avoid spamming the system log files. + +### Debug logging in console + +For debugging, it is usually very helpful to observe the apps output directly +on the console log. + +``` bash +# Make sure the Jukebox service is stopped: +$ systemctl --user stop jukebox-daemon + +# Start the Jukebox in debug mode: +# with default logger: +$ ./run_jukebox.py + +# or with custom logger configuration: +$ ./run_jukebox.py --logger ../path/to/logger.yaml +``` + +### Fallback configuration + +It is possible to start the Jukebox with a catch-all debug enabler with a logger.yaml. +Attention: This only emits messages to the console and does not write to the log files! +This is more a fallback features: + +``` bash +$ ./run_jukebox.py -vv +``` + +### Extreme cases + +Sometimes, the Jukebox app might crash with an exception and stack trace which is +neither logged, nor caught and handled. + +If run locally from your console, you will see it immediately. No worries! + +If running as a service, you will probably not even notice immediately that something has +gone pear-shaped. Services are restarted automatically when they fail. + +Things are just not behaving as expected? Time to check the system logs: + +``` bash +$ journalctl --user -b -u jukebox-daemon +``` diff --git a/documentation/content/userguide/update.md b/documentation/content/userguide/update.md new file mode 100644 index 000000000..e09137ca3 --- /dev/null +++ b/documentation/content/userguide/update.md @@ -0,0 +1,39 @@ +# Update + +## Updating your Jukebox Version 3 + +Things on Version 3 are moving fast and you may want to keep up with recent changes. Since we are in Alpha Release stage, +a fair number of fixes are expected to be committed in the near future. + +You will need to do three things to update your version from develop (or the next release candidate version) + +1. Pull the newest code base from Github +2. Check for new entries in the configuration +3. Re-build the WebUI + +```bash +# Switch to develop (if desired) +$ git checkout future3/develop + +# Get latest code +$ git pull + +# Check if new (mandatory) options appeared in jukebox.yaml +# with your favourite diff tool and merge them +$ diff shared/settings/jukebox.yaml resources/default-settings/jukebox.default.yaml + +$ cd src/webapp +$ ./run_rebuild.sh +``` + +## Migration Path from Version 2 + +There is no update path coming from Version 2.x of the Jukebox. +You need to do a fresh install of Version 3 on a fresh Raspian Bullseye image. + +> [!IMPORTANT] +> Do start with a fresh SD card image! + +Do not just pull the future3 branch into you existing Version 2.x directory. +Do not run the installer on an system that had Version 2.x running before on it. +Stuff has changed too much to make this feasible. diff --git a/installation/routines/customize_options.sh b/installation/routines/customize_options.sh index 3af9274d5..5fe93c1b8 100644 --- a/installation/routines/customize_options.sh +++ b/installation/routines/customize_options.sh @@ -188,29 +188,6 @@ ${DISABLE_ONBOARD_AUDIO_BACKUP} if things go pear-shaped.) } -_option_build_local_docs() { - echo -e "Do you want to build the documentation locally and -make it available under http://ip.of.your.box/docs ? - -Note: - - This will force enable=true for the WebApp - - Up to date documentation is also always available online -Build and serve docs locally? [y/N] " 1>&3 - read -r response - case "$response" in - [yY]) - ENABLE_LOCAL_DOCS=true - ENABLE_WEBAPP=true - ;; - *) - ;; - esac - - echo "ENABLE_LOCAL_DOCS=${ENABLE_LOCAL_DOCS}" - echo "ENABLE_WEBAPP=${ENABLE_WEBAPP}" - -} - _option_webapp_devel_build() { # Let's detect if we are on the official release branch if [[ "$GIT_BRANCH" != "${GIT_BRANCH_RELEASE}" || "$GIT_USER" != "$GIT_UPSTREAM_USER" ]]; then @@ -250,7 +227,6 @@ customize_options() { _option_disable_onboard_audio _option_samba _option_webapp - _option_build_local_docs if [[ $ENABLE_WEBAPP == true ]] ; then _option_kiosk_mode _option_webapp_devel_build diff --git a/installation/routines/setup_jukebox_webapp.sh b/installation/routines/setup_jukebox_webapp.sh index 2014214fc..df8b64c69 100644 --- a/installation/routines/setup_jukebox_webapp.sh +++ b/installation/routines/setup_jukebox_webapp.sh @@ -70,12 +70,6 @@ _jukebox_webapp_register_as_system_service_with_nginx() { sudo service nginx restart } -_jukebox_build_local_docs() { - echo " Build docs locally" | tee /dev/fd/3 - "${INSTALLATION_PATH}/run_sphinx.sh" -c -} - - setup_jukebox_webapp() { echo "Install web application" | tee /dev/fd/3 @@ -88,9 +82,6 @@ setup_jukebox_webapp() { # Needs to be done after reboot! There will be a message at the end of the installation process # _jukebox_webapp_build fi - if [[ $ENABLE_LOCAL_DOCS == true ]]; then - _jukebox_build_local_docs - fi _jukebox_webapp_register_as_system_service_with_nginx echo "DONE: setup_jukebox_webapp" diff --git a/requirements.txt b/requirements.txt index 25fd7f4d3..1d9e9ae83 100644 --- a/requirements.txt +++ b/requirements.txt @@ -23,9 +23,6 @@ tornado # On regular Linux PCs, Websocket is enabled in the Python package # pyzmq -# Documentation build flow -sphinx -sphinx_rtd_theme # Code quality flake8>=4.0.0 diff --git a/resources/default-settings/nginx.default b/resources/default-settings/nginx.default index 284819257..b949beb26 100644 --- a/resources/default-settings/nginx.default +++ b/resources/default-settings/nginx.default @@ -20,41 +20,16 @@ server { try_files $uri $uri/ =404; } + location /logs { + root /home/pi/RPi-Jukebox-RFID/shared; - location /docs { - root /home/pi/RPi-Jukebox-RFID/docs/sphinx/_build/html; - try_files $uri $uri/ =404; - location = /docs/index.html { - error_page 404 = @runsphinx; - log_not_found off; - } - location = /docs { - error_page 404 = @runsphinx; - log_not_found off; - } - location = /docs/ { - error_page 404 = @runsphinx; - log_not_found off; - } + autoindex on; + autoindex_exact_size off; + autoindex_localtime on; + default_type text/plain; } - location /logs { - root /home/pi/RPi-Jukebox-RFID/shared; - - autoindex on; - autoindex_exact_size off; - autoindex_localtime on; - - default_type text/plain; - } - - location @runsphinx { - root /home/pi/RPi-Jukebox-RFID/resources/html; - try_files /runsphinx.html =404; - internal; - } - location @buildwebui { root /home/pi/RPi-Jukebox-RFID/resources/html; try_files /runbuildui.html =404; diff --git a/resources/html/runsphinx.html b/resources/html/runsphinx.html deleted file mode 100755 index 10feb79f0..000000000 --- a/resources/html/runsphinx.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -Phoniebox documentation not found: please build documentation - - - -
-

Ups! Looks like your documentation has not been build!

-

No reason to panic. Please run through the following steps: -

    -
  • cd /home/pi/RPi-Jukebox-RFID
  • -
  • ./run_sphinx.sh -c
  • -
  • Reload this page
  • -
-

Or check out the online documentation at Read The Docs. -

- - diff --git a/run_sphinx.sh b/run_sphinx.sh deleted file mode 100755 index 972860cbe..000000000 --- a/run_sphinx.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env bash - -usage() { - echo "Runner script for sphinx documentation build" - echo -e "\nWarnings are treated as errors as preparation for documentation releases.\n" - echo "Usage:" - echo " ./run_sphinx.sh : incremental build" - echo " ./run_sphinx.sh -c : clean re-build" - echo " ./run_sphinx.sh -n : Don't escalate warning to errors (for debug only!)" - exit 1 -} - -# Change working directory to location of script -SOURCE=${BASH_SOURCE[0]} -SCRIPT_DIR="$(dirname "$SOURCE")" -cd "$SCRIPT_DIR/docs/sphinx" || (echo "Could not change to docs directory" && exit 1) - -BUILD_DIR=_build - -CLEAN_BUILD=false -SPHINX_OPTS="-W --keep-going -T" -while getopts ":chn" opt; -do - case ${opt} in - c ) CLEAN_BUILD=true - ;; - h ) usage - ;; - n ) SPHINX_OPTS="-T" - ;; - \? ) usage - ;; - esac -done - - -if [[ $CLEAN_BUILD = true ]]; then - echo "Cleaning $BUILD_DIR" - rm -rf $BUILD_DIR - SPHINX_OPTS="$SPHINX_OPTS -a -E" -fi - -echo "Building docs [ sphinx-build $SPHINX_OPTS -b html . ${BUILD_DIR}/html/docs ]" -sphinx-build $SPHINX_OPTS -b html . ${BUILD_DIR}/html/docs - diff --git a/src/jukebox/components/controls/bluetooth_audio_buttons/README.rst b/src/jukebox/components/controls/bluetooth_audio_buttons/README.rst index 290b0c6b1..87a7eab2b 100644 --- a/src/jukebox/components/controls/bluetooth_audio_buttons/README.rst +++ b/src/jukebox/components/controls/bluetooth_audio_buttons/README.rst @@ -52,4 +52,4 @@ The RPC command follows the regular RPC command rules as defined in :ref:`usergu Key codes can be found in the log files. Press the various buttons on your headset, while watching the -logs with e.g. ``tail -f shared/logs/app.log``. Look for entries like ``No callback registered for button ...``. \ No newline at end of file +logs with e.g. ``tail -f shared/logs/app.log``. Look for entries like ``No callback registered for button ...``. diff --git a/src/jukebox/components/gpio/gpioz/README.rst b/src/jukebox/components/gpio/gpioz/README.rst index 9d6d7020b..46ab0250a 100644 --- a/src/jukebox/components/gpio/gpioz/README.rst +++ b/src/jukebox/components/gpio/gpioz/README.rst @@ -462,5 +462,3 @@ Simply change the header in the configuration file to enable it. Host is the IP pigpio.PiGPIOFactory: kwargs: host: 192.168.178.32 - - diff --git a/src/jukebox/components/rfid/hardware/template_new_reader/README.rst b/src/jukebox/components/rfid/hardware/template_new_reader/README.rst index 228f3039a..e20e4452b 100644 --- a/src/jukebox/components/rfid/hardware/template_new_reader/README.rst +++ b/src/jukebox/components/rfid/hardware/template_new_reader/README.rst @@ -27,8 +27,7 @@ Your new reader is a python subpackage with these three mandatory files +- description.py <-- A description module w/o dependencies. Do not change the filename! +- README.rst <-- The Readme -The module documentation must go into a separate file so we can import it into the Sphinx document generation flow -without loading the Python module. +The module documentation must go into a separate file, named README.MD. Conventions ^^^^^^^^^^^^^^^^^^ diff --git a/src/jukebox/jukebox/daemon.py b/src/jukebox/jukebox/daemon.py index 0c3805eeb..e847428e2 100755 --- a/src/jukebox/jukebox/daemon.py +++ b/src/jukebox/jukebox/daemon.py @@ -230,13 +230,10 @@ def run(self): if self.write_artifacts: # This writes out - # rpc_command_reference.rst # rpc_command_reference.txt - # rpc_command_alias_reference.rst # rpc_command_alias_reference.txt artifacts_dir = '../../shared/artifacts/' - sphinx_dir = '../../docs/sphinx/userguide' try: os.mkdir(artifacts_dir) @@ -250,14 +247,6 @@ def run(self): with open(os.path.join(artifacts_dir, 'rpc_command_alias_reference.txt'), 'w') as stream: jukebox.utils.generate_cmd_alias_reference(stream) - # Write RST files directly into Sphinx directory - - with open(os.path.join(sphinx_dir, 'rpc_command_reference.rst'), 'w') as stream: - plugin.generate_help_rst(stream) - - with open(os.path.join(sphinx_dir, 'rpc_command_alias_reference.rst'), 'w') as stream: - jukebox.utils.generate_cmd_alias_rst(stream) - # Start the RPC Server self.rpc_server.run()