diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..0d516933b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +*/temp* +*/*/temp* +*.md +.git +.github diff --git a/.editorconfig b/.editorconfig index ad7373099..1c436d1ea 100644 --- a/.editorconfig +++ b/.editorconfig @@ -14,3 +14,6 @@ indent_size = 4 [*.md] trim_trailing_whitespace = false + +[*.{js,yaml,yml}] +indent_size = 2 diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0c8ea40c2..e58e25d4b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,4 @@ /components/controls/buttons_usb_encoder/ @jeripeierSBB -/scripts/installscripts/buster-install-default.sh @jeripeierSBB -/scripts/installscripts/buster-install-default-with-autohotspot.sh @jeripeierSBB +/components/synchronisation/sync-shared @AlvinSchiller +/scripts/installscripts/install-jukebox.sh @jeripeierSBB +/scripts/helperscripts/setup_autohotspot.sh @Groovylein diff --git a/.github/ISSUE_TEMPLATE/bug_template.md b/.github/ISSUE_TEMPLATE/bug_template.md index 1be942778..222325940 100644 --- a/.github/ISSUE_TEMPLATE/bug_template.md +++ b/.github/ISSUE_TEMPLATE/bug_template.md @@ -10,7 +10,7 @@ labels: bug, needs triage ### What I did ### What happened @@ -56,7 +56,7 @@ the following command will help with that ### Installscript diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..e8ce1a65d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: 🤔 Questions and Help + url: https://github.com/MiczFlor/RPi-Jukebox-RFID/discussions/new?category=q-a + about: This issue tracker is not for support questions. Please refer to our Discussions. + - name: 💬 Chat + url: https://matrix.to/#/#phoniebox_community:gitter.im + about: Want to discuss with others? Check out our chat. diff --git a/.github/dependabot.yml b/.github/dependabot.yml index de5e8ce51..80a061f32 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -19,3 +19,8 @@ updates: directory: "/" schedule: interval: "monthly" + + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "monthly" diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 1a365a93c..f895114ef 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -35,7 +35,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/dockerimage.yml b/.github/workflows/dockerimage.yml deleted file mode 100644 index 6cdce896a..000000000 --- a/.github/workflows/dockerimage.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Test Install Scripts on Docker - -on: - push: - branches-ignore: - - 'future3/**' - pull_request: - # The branches below must be a subset of the branches above - branches: [ develop ] - -jobs: - - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - name: Build Docker image and run tests - run: | - docker build . --file ./ci/Dockerfile.buster.test_install.amd64 --tag rpi-jukebox-rfid-buster:latest - docker run --rm -i rpi-jukebox-rfid-buster:latest /code/scripts/installscripts/tests/run_installation_tests.sh - docker run --rm -i rpi-jukebox-rfid-buster:latest /code/scripts/installscripts/tests/run_installation_tests2.sh - docker run --rm -i rpi-jukebox-rfid-buster:latest /code/scripts/installscripts/tests/run_installation_tests3.sh - - name: Build Docker image and run tests for alternate user hans - run: | - docker build . --file ./ci/Dockerfile.buster.test_install_altuser.amd64 --tag rpi-jukebox-rfid-buster-altuser:latest - docker run --rm -i rpi-jukebox-rfid-buster-altuser:latest /code/scripts/installscripts/tests/run_installation_tests_altuser.sh - docker run --rm -i rpi-jukebox-rfid-buster-altuser:latest /code/scripts/installscripts/tests/run_installation_tests2_altuser.sh - docker run --rm -i rpi-jukebox-rfid-buster-altuser:latest /code/scripts/installscripts/tests/run_installation_tests3_altuser.sh diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml new file mode 100644 index 000000000..128334e9c --- /dev/null +++ b/.github/workflows/php.yml @@ -0,0 +1,46 @@ +name: PHP Composer + +on: + push: + branches: [ develop ] + pull_request: + branches: [ develop ] + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP with XDebug + uses: shivammathur/setup-php@v2 + with: + php-version: 7.3 + coverage: xdebug + tools: composer + + - name: Validate composer.json and composer.lock + run: composer validate --strict + + - name: Cache Composer packages + id: composer-cache + uses: actions/cache@v3 + with: + path: vendor + key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-php- + + - name: Install dependencies + run: composer install --prefer-dist --no-progress + + # Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit" + # Docs: https://getcomposer.org/doc/articles/scripts.md + + - name: Run test suite + run: composer run-script test # run not all tests, see composer.json diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index b61b46aff..6b9a3722c 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -15,10 +15,10 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: [3.6, 3.7, 3.8] + python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: @@ -40,4 +40,21 @@ jobs: working-directory: ./components/gpio_control run: | pip install -r requirements.txt - pytest + pytest --cov --cov-report xml + - name: Report to Coveralls (parallel) + uses: coverallsapp/github-action@v2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + file: ./components/gpio_control/coverage.xml + format: cobertura + parallel: true + + finish: + needs: build + runs-on: ubuntu-latest + steps: + - name: Close parallel build + uses: coverallsapp/github-action@v2 + with: + parallel-finished: true + #carryforward: "run-1,run-2" diff --git a/.github/workflows/pythonpackage_future3.yml b/.github/workflows/pythonpackage_future3.yml deleted file mode 100644 index cf5005fd2..000000000 --- a/.github/workflows/pythonpackage_future3.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: Python + Docs Checks and Tests - -on: - push: - branches: - - 'future3/**' - paths: - - '**.py' - - '**.py.*' - - 'docs/sphinx/**' - pull_request: - branches: - - 'future3/**' - paths: - - '**.py' - - '**.py.*' - - 'docs/sphinx/**' - -jobs: - build: - - runs-on: ubuntu-latest - strategy: - max-parallel: 4 - matrix: - python-version: [3.7, 3.8] - - steps: - - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y libasound2-dev - python -m pip install --upgrade pip - pip install wheel - pip install spidev - pip 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 - pip install -r docs/sphinx/requirements_pyzmq.txt - pip install -r docs/sphinx/requirements.txt - # Also install all optional dependencies - pip install -r src/jukebox/components/rfid/fake_reader_gui/requirements.txt - - name: Lint with flake8 - run: | - pip 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/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..7b1e4da01 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,97 @@ +name: Release + +on: + push: + branches: + - 'master' + +jobs: + + check: + # TODO remove test code + if: ${{ github.repository_owner == 'MiczFlor' || github.repository_owner == 'AlvinSchiller' }} + runs-on: ubuntu-latest + + outputs: + tag_name: ${{ steps.vars.outputs.tag_name }} + release_type: ${{ steps.vars.outputs.release_type }} + check_abort: ${{ steps.vars.outputs.check_abort }} + + steps: + - uses: actions/checkout@v3 + + - name: Set Output vars + id: vars + env: + BRANCH_NAME: ${{ github.ref_name }} + run: | + # Official SemVer Regex definition + # https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string + # Needed changes to the regex: + # - '?:' capture command needed to be removed as it wasn't working in shell + # - '\d' had to be replaced with [0-9] + # + # Release versions like 1.0.0, 3.5.0, 100.4.50000+metadata + REGEX_VERSION_RELEASE="^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(\+([0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*))?$" + # + # Prerelease versions like 1.0.0-alpha, 3.5.0-whatsoever.12, 100.4.50000-identifier.12+metadata + REGEX_VERSION_PRERELEASE="^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-((0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*))?(\+([0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*))?$" + + + # Get the version and calculate release type + VERSION=$(cat ./settings/version-number) + if echo "$VERSION" | grep -qoE "$REGEX_VERSION_RELEASE" ; then + RELEASE_TYPE=release + elif echo "$VERSION" | grep -qoE "$REGEX_VERSION_PRERELEASE" ; then + RELEASE_TYPE=prerelease + else + RELEASE_TYPE=none + fi + + if [ "$BRANCH_NAME" == 'master' -a "$RELEASE_TYPE" == 'release' ] ; then + CHECK_ABORT=false + else + echo "::notice title=Abort due to not matching ${RELEASE_TYPE} version for branch!::'${VERSION}' on '${BRANCH_NAME}'" + CHECK_ABORT=true + fi + + echo "::group::Output values" + echo "Version: ${VERSION}" + echo "RELEASE_TYPE: ${RELEASE_TYPE}" + echo "BRANCH_NAME: ${BRANCH_NAME}" + echo "CHECK_ABORT: ${CHECK_ABORT}" + + echo "tag_name=v${VERSION}" >> $GITHUB_OUTPUT + echo "release_type=${RELEASE_TYPE}" >> $GITHUB_OUTPUT + echo "branch_name=${BRANCH_NAME}" >> $GITHUB_OUTPUT + echo "check_abort=${CHECK_ABORT}" >> $GITHUB_OUTPUT + echo "::endgroup::" + + release: + needs: [check] + if: ${{ needs.check.outputs.check_abort == 'false' }} + runs-on: ubuntu-latest + + concurrency: + group: ${{ needs.check.outputs.tag_name }} + + permissions: + contents: write + + steps: + - name: Create Release + uses: ncipollo/release-action@v1 + with: + commit: ${{ github.sha }} + tag: ${{ needs.check.outputs.tag_name }} + body: "Automated Release for ${{ needs.check.outputs.tag_name }}" + makeLatest: ${{ needs.check.outputs.release_type == 'release' }} + prerelease: ${{ needs.check.outputs.release_type == 'prerelease' }} + generateReleaseNotes: ${{ needs.check.outputs.release_type == 'release' }} + skipIfReleaseExists: false + allowUpdates: true + removeArtifacts: false + replacesArtifacts: false + omitBodyDuringUpdate: true + omitNameDuringUpdate: true + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test_docker_debian.yml b/.github/workflows/test_docker_debian.yml new file mode 100644 index 000000000..8b3778606 --- /dev/null +++ b/.github/workflows/test_docker_debian.yml @@ -0,0 +1,37 @@ +name: Test Install Scripts Debian + +on: + schedule: + # run at 5:00 every sunday + - cron: '0 5 * * 0' + push: + branches-ignore: + - 'future3/**' + pull_request: + # The branches below must be a subset of the branches above + branches: [ develop ] + +# let only one instance run the test so cache is not corrupted. +# cancel already running instances as only the last run will be relevant +concurrency: + group: ${{ github.ref }}-test-debian + cancel-in-progress: true + +jobs: + + # Build container and run tests + run: + name: ${{ matrix.debian_codename }} + strategy: + fail-fast: false + matrix: + debian_codename: ['bookworm', 'bullseye', 'buster'] + uses: ./.github/workflows/test_docker_debian_codename_sub.yml + with: + runs_on: ubuntu-latest + platform: linux/arm/v7 + docker_image_name: rpi-jukebox-rfid + cache_scope: ${{ github.ref }}-test-debian + matrix_usernames: "['pi', 'hans']" + matrix_test_scripts: "['run_installation_tests.sh', 'run_installation_tests2.sh', 'run_installation_tests3.sh']" + debian_codename: ${{ matrix.debian_codename }} diff --git a/.github/workflows/test_docker_debian_codename_sub.yml b/.github/workflows/test_docker_debian_codename_sub.yml new file mode 100644 index 000000000..b018afaf5 --- /dev/null +++ b/.github/workflows/test_docker_debian_codename_sub.yml @@ -0,0 +1,182 @@ +name: Subworkflow Test Install Scripts Debian + +on: + workflow_call: + inputs: + runs_on: + required: true + type: string + platform: + required: true + type: string + debian_codename: + required: true + type: string + cache_scope: + required: true + type: string + docker_image_name: + required: true + type: string + matrix_usernames: + required: true + type: string + matrix_test_scripts: + required: true + type: string + local_registry_port: + required: false + type: number + default: 5000 + +# let only one instance run the test so cache is not corrupted. +# cancel already running instances as only the last run will be relevant +concurrency: + group: ${{ inputs.cache_scope }}-${{ inputs.debian_codename }} + cancel-in-progress: true + +jobs: + + # Build container for test execution + build: + runs-on: ${{ inputs.runs_on }} + + outputs: + cache_key: ${{ steps.vars.outputs.cache_key }} + image_file_name: ${{ steps.vars.outputs.image_file_name }} + image_tag_name: ${{ steps.vars.outputs.image_tag_name }} + + # create local docker registry to use locally build images + services: + registry: + image: registry:2 + ports: + - ${{ inputs.local_registry_port }}:5000 + + steps: + - uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3.0.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3.0.0 + with: + # network=host driver-opt needed to push to local registry + driver-opts: network=host + + - name: Set Output pre-vars + id: pre-vars + env: + DEBIAN_CODENAME: ${{ inputs.debian_codename }} + DOCKER_IMAGE_NAME: ${{ inputs.docker_image_name }} + CACHE_SCOPE: ${{ inputs.cache_scope }} + run: | + echo "image_tag_name=${{ env.DOCKER_IMAGE_NAME }}:${{ env.DEBIAN_CODENAME }}-test" >> $GITHUB_OUTPUT + echo "image_file_name=${{ env.DOCKER_IMAGE_NAME }}-${{ env.DEBIAN_CODENAME }}.tar" >> $GITHUB_OUTPUT + echo "cache_scope=${{ env.CACHE_SCOPE }}-${{ env.DEBIAN_CODENAME }}" >> $GITHUB_OUTPUT + + - name: Set Output vars + id: vars + env: + LOCAL_REGISTRY_PORT: ${{ inputs.local_registry_port }} + run: | + echo "image_tag_name=${{ steps.pre-vars.outputs.image_tag_name }}" >> $GITHUB_OUTPUT + echo "image_tag_name_local_base=localhost:${{ env.LOCAL_REGISTRY_PORT }}/${{ steps.pre-vars.outputs.image_tag_name }}-base" >> $GITHUB_OUTPUT + echo "image_file_name=${{ steps.pre-vars.outputs.image_file_name }}" >> $GITHUB_OUTPUT + echo "image_file_path=./${{ steps.pre-vars.outputs.image_file_name }}" >> $GITHUB_OUTPUT + echo "cache_scope=${{ steps.pre-vars.outputs.cache_scope }}" >> $GITHUB_OUTPUT + echo "cache_key=${{ steps.pre-vars.outputs.cache_scope }}-${{ github.sha }}#${{ github.run_attempt }}" >> $GITHUB_OUTPUT + + # Build base image for debian version name. Layers will be cached and image pushes to local registry + - name: Build Image - Base + uses: docker/build-push-action@v5 + with: + context: . + load: false + push: true + file: ./ci/Dockerfile.debian + target: test-code + platforms: ${{ inputs.platform }} + tags: ${{ steps.vars.outputs.image_tag_name_local_base }} + cache-from: type=gha,scope=${{ steps.vars.outputs.cache_scope }} + cache-to: type=gha,mode=max,scope=${{ steps.vars.outputs.cache_scope }} + build-args: | + DEBIAN_CODENAME=${{ inputs.debian_codename }} + GIT_BRANCH=${{ github.head_ref || github.ref_name }} + GIT_URL=${{ github.server_url }}/${{ github.event.pull_request.head.repo.full_name || github.repository }} + + # Build new image with updates packages based on base image. Layers will NOT be chached. Result is written to file. + - name: Build Image - Update + uses: docker/build-push-action@v5 + with: + context: . + load: false + push: false + file: ./ci/Dockerfile.debian + target: test-update + platforms: ${{ inputs.platform }} + tags: ${{ steps.vars.outputs.image_tag_name }} + cache-from: type=gha,scope=${{ steps.vars.outputs.cache_scope }} + # DON'T use 'cache-to' here as the layer is then cached and this build would be useless + outputs: type=docker,dest=${{ steps.vars.outputs.image_file_path }} + build-args: | + BASE_TEST_IMAGE=${{ steps.vars.outputs.image_tag_name_local_base }} + + - name: Artifact Upload Docker Image + uses: actions/upload-artifact@v3 + with: + name: ${{ steps.vars.outputs.image_file_name }} + path: ${{ steps.vars.outputs.image_file_path }} + retention-days: 2 + + + # Run tests with build image + test: + needs: [build] + runs-on: ${{ inputs.runs_on }} + + strategy: + fail-fast: false + matrix: + username: ${{ fromJSON(inputs.matrix_usernames) }} + test_script: ${{ fromJSON(inputs.matrix_test_scripts) }} + + steps: + - name: Set up QEMU + uses: docker/setup-qemu-action@v3.0.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3.0.0 + + - name: Artifact Download Docker Image + uses: actions/download-artifact@v3 + with: + name: ${{ needs.build.outputs.image_file_name }} + + - name: Load Docker Image + run: | + docker load --input ${{ needs.build.outputs.image_file_name }} + + # Run test + - name: Run Test ${{ inputs.debian_codename }}-${{ matrix.username }}-${{ matrix.test_script }} + uses: tj-actions/docker-run@v2 + with: + image: ${{ needs.build.outputs.image_tag_name }} + options: --platform ${{inputs.platform }} --user ${{ matrix.username }} + name: ${{ matrix.test_script }} + args: | + ./${{ matrix.test_script }} + + # cleanup after test execution + cleanup: + # run only if tests didn't fail: keep the artifact to make job reruns possible + if: ${{ !failure() }} + needs: [build, test] + runs-on: ${{ inputs.runs_on }} + + steps: + - name: Artifact Delete Docker Image + uses: geekyeggo/delete-artifact@v2 + with: + name: ${{ needs.build.outputs.image_file_name }} diff --git a/.gitignore b/.gitignore index 04d9c5d32..593e3b75b 100755 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,8 @@ settings/Playlists_Folders_Path settings/rfid_trigger_play.conf settings/Second_Swipe settings/ShowCover +settings/sync-shared.conf +settings/sync-shared-enabled settings/version htdocs/config.php scripts/deviceName.txt diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 5e8fc7288..dfd857be8 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,14 +1,7 @@ - -Dear Phonieboxians, - -As the Phoniebox community is growing, somebody suggested a pull request with the below document. I was hesitant to include it right away, but at the same time I thought: it might be good to have some kind of document to formulate the foundation this project is built on. To tell you the truth, this document is not it. However, it is a start and I thought: why not open this in the spirit of open source, sharing and pull requests and see if and how you or you or you want to change or add parts of this very *standard and corporate* document. Like most of you, I also have a small kid and my time is scarce, I might find some time though to add a bit. - -All the best, Micz - -2018-08-21 - # Contributor Covenant Code of Conduct +> 📝**NOTE:** Dear Phonieboxians, as the Phoniebox community is growing, somebody suggested a pull request with the below document. I was hesitant to include it right away, but at the same time I thought: it might be good to have some kind of document to formulate the foundation this project is built on. To tell you the truth, this document is not it. However, it is a start and I thought: why not open this in the spirit of open source, sharing and pull requests and see if and how you or you or you want to change or add parts of this very *standard and corporate* document. Like most of you, I also have a small kid and my time is scarce, I might find some time though to add a bit. **All the best, Micz**, 2018-08-21 + This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] ## Our Pledge @@ -45,7 +38,7 @@ This Code of Conduct applies both within project spaces and in public spaces whe ## Enforcement -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at micz.flor@web.de. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at . The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eb1212ad1..889233f70 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,41 +1,8 @@ +# Contributing -# Table of contents +> 📝**NOTE:** This describes contributing for **version 2.x**. For Version 3 please see -* Naming conventions -* Structure of files and folders -* How to contribute - -# Naming conventions - -* **Files & folder names** - * all **lower case** - * separate words with **dashes** `-` (less keystrokes, better autocomplete recognition, in HTML links dashes can not be confused) not camel/PascalCaps or underscores - * be **descriptive** in your wording (e.g. `raspberry`, not `juicy-red-thing`) - * move **from general to specific** (e.g. `food-fruit-raspberry`, not `raspberry-food-fruit`) - * unique and clear product IDs (e.g. MAX7219) - * the product ID should be written as is (no lowercase) - * the product ID should come last in a descriptive name (e.g. dot-matrix-module-MAX7219) - * be consistent and look at existing examples before you invent something new - -* **`README.md`** - * written in capital letters, so it's easier to spot - * every new folder of a component deserves a `README.md` file - -# Structure of files and folders - -Inside the root folder or the repo, these folders are important: - -* `scripts` - * this folder should contain **only actively used scripts** (controlling playout, rfid tiggers, etc.) - * some possible services and features might live in the *components* directory (see below) - * if one or more scripts are needed for the activation of a component (like daemons), they should be copied to the `scripts` directory during installation / activation - * WHY? By copying, changes will NOT affect the github repo and make it easier for users to modify their components -* `components` - * contains sub- und subsubfolders for additional features, services, hardware - * **subfolders** are for categories (e.g. displays, soundcards) and are plural, even if there is only one - * **subsubfolders** are specific hardware, services, features, protocols, etc. - -# How to contribute +## How to contribute Contributors have played a bigger role over time to keep Phoniebox on the edge of innovation :) @@ -43,7 +10,7 @@ We want to keep it as easy as possible to contribute changes that get things wor Development is done on the git branch `develop`. How to move to that branch, see below. -## Getting Started +### Getting Started * Make sure you have a [GitHub account](https://github.com/signup/free). * Open an issue if one does not already exist. @@ -62,11 +29,13 @@ git pull The preferred way of code contributions are [pull requests (follow this link for a small howto)](https://www.digitalocean.com/community/tutorials/how-to-create-a-pull-request-on-github). And ideally pull requests using the "running code" on the `develop` branch of your Phoniebox. Alternatively, feel free to post tweaks, suggestions and snippets in the ["issues" section](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues). -## Making Changes +Please check also our [Code of Conduct](CODE_OF_CONDUCT.md). + +### Making Changes * Create a topic branch from where you want to base your work. - * This is usually the master branch. - * Only target release branches if you are certain your fix must be on that + * This is usually the `develop` branch. + * Only target release branches (i.e. `master`) if you are certain your fix must be on that branch. * To quickly create a topic branch based on master, run `git checkout -b fix/master/my_contribution master`. Please avoid working directly on the @@ -74,7 +43,7 @@ The preferred way of code contributions are [pull requests (follow this link for * Make commits of logical and atomic units. * Check for unnecessary whitespace with `git diff --check` before committing. -~~~ +~~~bash Added shuffle mode and RFID controls for it (issue #130) #140 Adds a shuffle mode for MPD to be triggered by RFID card. @@ -91,7 +60,7 @@ The preferred way of code contributions are [pull requests (follow this link for master branch. ~~~ -## Making Trivial Changes +### Making Trivial Changes For changes of a trivial nature, it is not always necessary to create a new issue. In this case, it is appropriate to start the first line of a @@ -102,39 +71,58 @@ For commits that address trivial repository maintenance tasks or packaging issues, start the first line of the commit with `(maint)` or `(packaging)`, respectively. -## Submitting Changes +### Submitting Changes * Push your changes to a topic branch in your fork of the repository. * Submit a pull request to the repository. * The core team looks at Pull Requests on a regular basis. -* After feedback has been given we expect responses within two weeks. After two - weeks we may close the pull request if it isn't showing any activity. +* After feedback has been given we expect responses within two weeks. After two weeks we may close the pull request if it isn't showing any activity. -## Revert Policy +### Revert Policy -By running tests in advance and by engaging with peer review for prospective -changes, your contributions have a high probability of becoming long lived -parts of the the project. After being merged, the code will run through a -series of testings. These Tests can reveal incompatibilities that are difficult -to detect in advance. +By running tests in advance and by engaging with peer review for prospective changes, your contributions have a high probability of becoming long lived parts of the the project. After being merged, the code will run through a series of testings. These Tests can reveal incompatibilities that are difficult to detect in advance. -If the code change results in a test failure, we will make our best effort to -correct the error. If a fix cannot be determined and committed within 24 hours -of its discovery, the commit(s) responsible *may* be reverted, at the -discretion of the committer and Phonie maintainers. -The original contributor will be notified of the revert. +If the code change results in a test failure, we will make our best effort to correct the error. If a fix cannot be determined and committed within 24 hours of its discovery, the commit(s) responsible *may* be reverted, at the discretion of the committer and Phonie maintainers. The original contributor will be notified of the revert. -### Summary +#### Summary -* Changes resulting in test failures will be reverted if they cannot - be resolved within one business day. +* Changes resulting in test failures will be reverted if they cannot be resolved within one business day. -## Guidelines +### Guidelines -* Currently Phoniebox runs on Raspian **Buster** . Therefore all Python code should work with **Python 3.7**. +* The oldest supported Raspberry Pi OS version is currently **Buster**. Therefore all Python code should work with **Python 3.7**. * For GPIO all code should work with **RPi.GPIO**. gpiozero is currently not intended to use. -## Additional Resources +### Additional Resources * [General GitHub documentation](https://help.github.com/) * [GitHub pull request documentation](https://help.github.com/articles/creating-a-pull-request/) + +## Naming conventions + +* **Files & folder names** + * all **lower case** + * separate words with **dashes** `-` (less keystrokes, better autocomplete recognition, in HTML links dashes can not be confused) not camel/PascalCaps or underscores + * be **descriptive** in your wording (e.g. `raspberry`, not `juicy-red-thing`) + * move **from general to specific** (e.g. `food-fruit-raspberry`, not `raspberry-food-fruit`) + * unique and clear product IDs (e.g. MAX7219) + * the product ID should be written as is (no lowercase) + * the product ID should come last in a descriptive name (e.g. dot-matrix-module-MAX7219) + * be consistent and look at existing examples before you invent something new +* **`README.md`** + * written in capital letters, so it's easier to spot + * every new folder of a component deserves a `README.md` file + +## Structure of files and folders + +Inside the root folder or the repo, these folders are important: + +* `scripts` + * this folder should contain **only actively used scripts** (controlling playout, rfid tiggers, etc.) + * some possible services and features might live in the *components* directory (see below) + * if one or more scripts are needed for the activation of a component (like daemons), they should be copied to the `scripts` directory during installation / activation + * WHY? By copying, changes will NOT affect the github repo and make it easier for users to modify their components +* `components` + * contains sub- und subsubfolders for additional features, services, hardware + * **subfolders** are for categories (e.g. displays, soundcards) and are plural, even if there is only one + * **subsubfolders** are specific hardware, services, features, protocols, etc. diff --git a/INSTALL b/INSTALL deleted file mode 100644 index 68021e111..000000000 --- a/INSTALL +++ /dev/null @@ -1,51 +0,0 @@ -Installing Phoniebox -==================== - -You can download the code or use git to keep up to date with the -latest changes. As a third option there are install scripts -available - which require a better understanding of what you are -doing. - -Step by step manual -------------------- -The best way to walk through the install process would be to follow -the manuals inside the 'docs' folder. - -Download --------- -You can either download the latest version as a zip / tarball at: -https://github.com/MiczFlor/RPi-Jukebox-RFID/releases -The advantages of using the download option: your installation -will be running when it's running and changes in the code on -github will not change your installation. - -1. Download the code as .zip or .tar.gz into your home directory - /home/pi/ -2. Unzip / untar the code. The code should now live inside a folder - named 'RPi-Jukebox-RFID' -3. Consult the manual in the 'docs' folder to configure the system - and set the correct folder access rights. - -Git ---- -The advantage of using git and the github repo means: you can always -update to the latest code changes. This can be a problem - for the -same reason - when changes in the code repository might require -additional changes in your installation. If you run into such -problems, check the file 'docs/UPGRADE.md' - -The manuals are written with the 'git' installation process in mind, -please go to the 'docs' folder and read the manuals. - -Install Scripts ---------------- -Inside the folder 'scripts/installscripts' you can find bash files -which install the system in one go. However, you might need to change -some sample config files (e.g. static IP address). -If you want to use the install scripts, you seem to know what you are -doing, so roll up your sleeves, open them and read :) - -All the best and don't forget to share your results with the community -in this thread: -https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/5 - diff --git a/README.md b/README.md index b1b0ab5f3..41f106e99 100644 --- a/README.md +++ b/README.md @@ -2,146 +2,225 @@ ![GitHub last commit (branch)](https://img.shields.io/github/last-commit/MiczFlor/RPi-Jukebox-RFID/develop) -[![Python Checks and Tests](https://github.com/MiczFlor/RPi-Jukebox-RFID/actions/workflows/pythonpackage.yml/badge.svg)](https://github.com/MiczFlor/RPi-Jukebox-RFID/actions/workflows/pythonpackage.yml) [![Test Install Scripts on Docker](https://github.com/MiczFlor/RPi-Jukebox-RFID/actions/workflows/dockerimage.yml/badge.svg)](https://github.com/MiczFlor/RPi-Jukebox-RFID/actions/workflows/dockerimage.yml) [![CodeQL](https://github.com/MiczFlor/RPi-Jukebox-RFID/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/MiczFlor/RPi-Jukebox-RFID/actions/workflows/codeql-analysis.yml) +[![Python Checks and Tests](https://github.com/MiczFlor/RPi-Jukebox-RFID/actions/workflows/pythonpackage.yml/badge.svg)](https://github.com/MiczFlor/RPi-Jukebox-RFID/actions/workflows/pythonpackage.yml) +[![Test Install Scripts Debian](https://github.com/MiczFlor/RPi-Jukebox-RFID/actions/workflows/test_docker_debian.yml/badge.svg)](https://github.com/MiczFlor/RPi-Jukebox-RFID/actions/workflows/test_docker_debian.yml) +[![CodeQL](https://github.com/MiczFlor/RPi-Jukebox-RFID/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/MiczFlor/RPi-Jukebox-RFID/actions/workflows/codeql-analysis.yml) +[![PHP Tests](https://github.com/MiczFlor/RPi-Jukebox-RFID/actions/workflows/php.yml/badge.svg)](https://github.com/MiczFlor/RPi-Jukebox-RFID/actions/workflows/php.yml) -[![Gitter chat](https://badges.gitter.im/phoniebox/gitter.png)](https://gitter.im/phoniebox) +[![Coverage Status](https://coveralls.io/repos/github/MiczFlor/RPi-Jukebox-RFID/badge.svg?branch=develop)](https://coveralls.io/github/MiczFlor/RPi-Jukebox-RFID?branch=develop) -A contactless jukebox for the Raspberry Pi, playing audio files, playlists, podcasts, web streams and spotify triggered by RFID cards. All plug and play via USB, no soldering iron needed. Update: if you must, it now also features a howto for adding GPIO buttons controls. +[![Gitter chat](https://badges.gitter.im/join_chat.svg)](https://matrix.to/#/#phoniebox_community:gitter.im) +[![Matrix chat](https://matrix.to/img/matrix-badge.svg)](https://matrix.to/#/#phoniebox_community:gitter.im) -**IMPORTANT NOTICE REGARDING SPOTIFY INTEGRATION** ->Spotify has [disabled access to libspotify on May 16, 2022](https://developer.spotify.com/community/news/2022/04/12/libspotify-sunset/). -This means Phoniebox can not communicate with Spotify via libspotify (and mopidy-spotify) anymore. -The problem is not our code but the cut off by Spotify. +## Introduction ->We want Phoniebox users to be able to connect their box to their Spotify accounts and play their content. -The possibilities Spotify offers are -- at first glance -- not supporting an integration with Phoniebox. -Third party projects like [librespot-java](https://github.com/librespot-org/librespot-java) enter a grey zone regarding violation of Spotify's *Terms of Services* (ToS). For a potential Spotify re-integration, we are committed to a Spotify ToS compliant way of doing so (both in Version 2 and Version 3). This means looking into the (relatively new) Spotify Playback API, which is going to take an unknown amount of time. +Phoniebox is a contactless jukebox for the Raspberry Pi, playing audio files, playlists, podcasts, web streams and spotify triggered by RFID cards. All plug and play via USB, no soldering iron needed. It also features GPIO buttons control support. ->This leaves us in a pickle and we are happy to hear from developer talent in the Phoniebox community on how to move forward regarding Phoniebox. -We are also curious to learn about alternative services we can connect with and which you would like to see supported -- or have developed support for already: - +## Important Notice regarding Spotify Integration -## The Phoniebox Calendar 2022 is here!!! +**Spotify has [disabled access to libspotify on May 16, 2022](https://developer.spotify.com/community/news/2022/04/12/libspotify-sunset/).** -Another bunch of wonderful designs! 2022 is the fourth Phoniebox calendar. If you are interested, you can see the [2019, 2020 and 2021 calendars in the docs folder](https://github.com/MiczFlor/RPi-Jukebox-RFID/tree/develop/docs). Download [the printable PDF of 2022 here](https://mi.cz/static/2022-Phoniebox-Calendar.pdf). +This means **Spotify in Phoniebox doesn't work at the moment**, as Phoniebox can not communicate with Spotify via libspotify (and mopidy-spotify) anymore. -![The 2022 Phoniebox Calendar](docs/2022-Phoniebox-Calendar.jpg "The 2022 Phoniebox Calendar") +The problem is not our code but the cut off by Spotify. We want Phoniebox users to be able to connect their box to their Spotify accounts and play their content. The possibilities Spotify offers are -- at first glance -- not supporting an integration with Phoniebox. -If you want to be featured on next years calendar, please make sure to add your Phoniebox pics to the [design thread here on github](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/639). +Third party projects like [librespot-java](https://github.com/librespot-org/librespot-java) enter a grey zone regarding violation of Spotify's *Terms of Services* (ToS). For a potential Spotify re-integration, we are committed to a Spotify ToS compliant way of doing so (both in Version 2 and Version 3). This means looking into the (relatively new) Spotify Playback API, which is going to take an unknown amount of time. ---- +This leaves us in a pickle and **we are happy to hear from developer talent in the Phoniebox community on how to move forward regarding Spotify integration**. -## Install latest Phoniebox version +We are also curious to learn about alternative services we can connect with and which you would like to see supported -- or have developed support for already: -If you are looking for **the latest stable version**, use the [install script for Raspberry Pi OS](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/INSTALL-stretch). -If you dare to go where only few have gone before, **become an alpha-tester, bug reporter, contributor** for the exciting, totally re-written, up and coming, yet feature incomplete and unstable version 3 of the Phoniebox code base: +## The Phoniebox Calendar 2023 is here -## 🔥 Version 3 is coming ... +Another bunch of wonderful designs! 2023 is the fifth Phoniebox calendar. If you are interested, you can see the [2019, 2020, 2021 and 2022 calendars in the docs folder](docs). Download [the printable PDF of 2023 here](https://mi.cz/static/2023-Phoniebox-Calendar.pdf). + +![The 2023 Phoniebox Calendar](docs/2023-Phoniebox-Calendar.jpg "The 2023 Phoniebox Calendar") + +If you want to be featured on next years calendar, please make sure to add your Phoniebox pics to the [design thread here on github](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/639). -### Newest release: V3.2.0 Beta -> 7. Feb 2022 +## Install Phoniebox -* New GPIO backend based on GPIOZero including more sophisticated controls for inputs and outputs -* Bluetooth Headset support with device buttons -* Equalizer + Mono down mixer -* Localization support for Webapp, current languages supported are English and German (help us translate!) -* Timer support in Webapp and via RFID cards -* Additional system information in Webapp like Battery status, CPU temperature or IP address -* Preperation for Text-to-Speech + Read My IP as a first example -* Bugfixes for Install Script +If you are looking for the latest **stable version 2.x**, use the [install script for Raspberry Pi](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/INSTALL). -Over the last few months, a few Phoniebox fans started to think about a potential future of the Jukebox code. Version 2 is mature -and works well but doesn't scale enough for future development. It's the mix of Shell, Python and PHP. The goal was to tidy up the codebase, focus on a single programming language for the core (Python), establish a solid plugin system and build a responsive web client. [Read on here if you want to learn about more reasons](https://rpi-jukebox-rfid.readthedocs.io/en/latest/). +### 🔥 Version 3 is coming -### 👋 Looking for adopters, testers and contributors +The goal for Version 3 was to tidy up the codebase, focus on a single programming language for the core (Python), establish a solid plugin system and build a responsive web client. [Read on here if you want to learn about more reasons](https://github.com/MiczFlor/RPi-Jukebox-RFID/blob/future3/develop/documentation/README.md). + +#### 👋 Looking for adopters, testers and contributors If you want to test or help develop this new version called `future3`, let us know what you think about the new architecture, the new web application and help us find bugs (or fix them proactively). -While Version 3 is still under development, it is becoming a lot more stable! Although only some of the features from version 2.x have been ported to version 3 so far. +While Version 3 is still under development, it is becoming a lot more stable! Although not all of the features from version 2.x have been ported to version 3 so far. If you seek the adventure, your support will be more then welcome. Before contributing, check out the following references. -* 🚀 **[Install Jukebox Version 3 Beta](https://rpi-jukebox-rfid.readthedocs.io/en/latest/install.html)** +* ⭐ **[Releases](https://github.com/MiczFlor/RPi-Jukebox-RFID/releases?q=v3&expanded=true)** +* 🚀 **[Install Jukebox Version 3 Beta](https://github.com/MiczFlor/RPi-Jukebox-RFID/blob/future3/develop/documentation/builders/installation.md)** * 🐛 [Report a bug](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/new?assignees=&labels=future3%2C+bug%2C+needs+triage&template=future3.md&title=ISSUE+SUMMARY+on+future3) -* ☑️ [Feature Status](https://rpi-jukebox-rfid.readthedocs.io/en/latest/featurelist.html) -* 📖 [Documentation](https://rpi-jukebox-rfid.readthedocs.io/en/latest/) -* 👩‍💻 [Development](https://rpi-jukebox-rfid.readthedocs.io/en/latest/development_environment.html) +* ☑️ [Feature Status](https://github.com/MiczFlor/RPi-Jukebox-RFID/blob/future3/develop/documentation/developers/status.md) +* 📖 [Documentation](https://github.com/MiczFlor/RPi-Jukebox-RFID/blob/future3/develop/documentation/README.md) +* 👩‍💻 [Development](https://github.com/MiczFlor/RPi-Jukebox-RFID/blob/future3/develop/documentation/developers/README.md) * 🦄 Code: [Release Branch](https://github.com/MiczFlor/RPi-Jukebox-RFID/tree/future3/main), [Development Branch](https://github.com/MiczFlor/RPi-Jukebox-RFID/tree/future3/develop) ---- +### Version 2 (stable) -## Important updates / news + ⭐ **[Releases](https://github.com/MiczFlor/RPi-Jukebox-RFID/releases?q=v2&expanded=true)** -* **Discussions forums** we use Github's Discussions feature for a more forum style. Please ask general questions in [Discussions](https://github.com/MiczFlor/RPi-Jukebox-RFID/discussions), bugs and enhancements should still be in [Issues](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues). +#### Features Version 2 -* **Phoniebox [future3 Beta](https://rpi-jukebox-rfid.readthedocs.io/en/latest/) released (2022-02)** -* **Gitter Community** we got ourselves a gitter community; chat us up at +* The **one-line install script** handles both **Classic** and **+Spotify** when [setting up your Phoniebox](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/INSTALL#one-line-install-command) + * integrated selection of RFID readers + * features *non-interactive* installs based on a config file +* [**RFID** control](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#cardcontrol) for playout and controlling your Phoniebox (e.g. set [maximum volume with RFID](https://github.com/MiczFlor/RPi-Jukebox-RFID/pull/633) cards). +* Support for various RFID readers, e.g. + * USB + * [RC422](components/rfid-reader/RC522/README.md) + * [PN532](components/rfid-reader/PN532/README.md) + * PC/SC + * also [multiple readers](https://github.com/MiczFlor/RPi-Jukebox-RFID/pull/1012#issue-434052529) simultaneously +* [**GPIO** control](components/gpio_control/README.md) for [buttons](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Using-GPIO-hardware-buttons), [knobs / dials](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Audio-RotaryKnobVolume) and much more to control your Phoniebox via GPIO. +* Control via smooth [**Web App**](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#webapp) running on ajax from your phone, tablet or PC. You can play, upload, move files, assign new RFID cards, control playout, settings, etc. +* Support for files with embedded chapters metadata (like m4a) +* Customizable poweroff command +* **[WiFi management](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#wifi-settings)** + * RFID cards to toggle WiFi (or switch it on/off) + * Read out the WiFi IP address (if you are connecting to a new network and don't know where to point your browser) + * **Hotspot** Phoniebox: [ad-hoc hotspot](https://github.com/MiczFlor/RPi-Jukebox-RFID/pull/967) if no known network found (IP: 10.0.0.5 SSID: phoniebox Password: PlayItLoud) +* **Touchscreen** LCD display Player (file: `index-lcd.php` in web app) +* Integrate your [Phoniebox in your Smart Home with MQTT](components/smart-home-automation/MQTT-protocol/README.md). +* Player control + * [Playout **Resume**](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#manage-playout-behaviour) switch for audio books, allowing you to jump straight back to where you were (unless you fell asleep...). + * Playout **Shuffle** switch to mix up your playlists. +* Audio sources + * Local audio files + * Download from **YouTube** directly to your Phoniebox. + * Support for **[Spotify](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Spotify-FAQ)** integration. + * [**Podcast feature** for Phoniebox](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#podcasts) + +#### Quick install Version 2 + +* [One line install script](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/INSTALL#one-line-install-command) for Raspberry Pi OS. +* Two editions: + * *Phoniebox Classic* supports local audio, web radio, podcasts, YouTube (download and convert), GPIO and/or RFID + * **MUST READ** for users of *[Phoniebox +Spotify Edition](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Spotify-FAQ)* +* Check [Installation instructions](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/INSTALL) or [Complete Install Guide](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/INSTALL-COMPLETE-GUIDE) +* Once everything has been installed and configured, [read the manual](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL) to change settings, register RFID cards, add audio. +* Adding push buttons to control volume, skipping tracks, pause, play: read the [GPIO Control Readme](components/gpio_control/README.md). -* **Phoniebox [2.4](https://github.com/MiczFlor/RPi-Jukebox-RFID/milestone/7?closed=1) released (2022-12-18)** +## Contact and Support -The [2.4](https://github.com/MiczFlor/RPi-Jukebox-RFID/milestone/7?closed=1) release was pushed through the doors with many contributors: [List of all contributors](https://github.com/MiczFlor/RPi-Jukebox-RFID/graphs/contributors) +* Please ask **general questions** in [Discussions](https://github.com/MiczFlor/RPi-Jukebox-RFID/discussions) +* **Bugs and enhancements** should still be in [Issues](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues). +* We got ourselves a gitter community; **chat us up** at [Gitter/Matrix](https://matrix.to/#/#phoniebox_community:gitter.im) -## What's new in version 2.4? +## Documentation -* 🔥 Finally fixed the annoying `evdev` bug during installation (fixes e.g. #1721, #1653, #1618, #1501 and MANY more) -* Flexible PHP version in install script (makes sure Raspian Bullseye can be used) #1849 -* Publish "card swiped" event via MQTT #1496 -* Right now Spotify integration **still doesn't work** - please follow the discussion at +Documentation can be found in the [GitHub wiki for Phoniebox](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki). Please try to add content in the wiki regarding special hardware, software tweaks and the like. -* Lots of fixed bugs and minor improvements... +### Manual -**What's still hot?** +In the [Manual](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL) you will learn: -* [GPIO control](components/gpio_control/README.md) -* Added support for files with embedded chapters metada (like m4a) enhancement -* Added customizable poweroff command bash enhancement -* Support for PC/SC-readers -* The constantly improved **one-line install script** handles both **Classic** and **+Spotify** when [setting up your Phoniebox](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/INSTALL-stretch#one-line-install-command) - * integrated improved [GPIO control](components/gpio_control/README.md) - * integrated selection of RFID readers and uses [multiple readers](https://github.com/MiczFlor/RPi-Jukebox-RFID/pull/1012#issue-434052529) simultaneously - * features *non-interactive* installs based on a config file -* **[WiFi management](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#wifi-settings)** - * RFID cards to **toggle Wifi** (or switch it on/off) - * Read out the Wifi IP address (if you are connecting to a new network and don't know where to point your browser) - * **Hotspot** Phoniebox: [ad-hoc hotspot](https://github.com/MiczFlor/RPi-Jukebox-RFID/pull/967) if no known network found (IP: 10.0.0.5 SSID: phoniebox Password: PlayItLoud) -* **Touchscreen** LCD display Player (file: `index-lcd.php` in web app) -* Integrate your [Phoniebox in your Smart Home](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Smart-Home-remote-control-with-MQTT). -* Smoother [Web App running on ajax](https://github.com/MiczFlor/RPi-Jukebox-RFID/pull/623). -* New [search form for local files](https://github.com/MiczFlor/RPi-Jukebox-RFID/pull/710) -* Control the debug logs in the web app (individual scripts switched on/off, empty log file). -* Set [maximum volume with RFID](https://github.com/MiczFlor/RPi-Jukebox-RFID/pull/633) cards. -* Control via [**wifi web app**](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#webapp) from your phone, tablet or PC. You can play, upload, move files, assign new RFID cards, control playout, settings, etc. -* [**RFID** control](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#phoniebox-controls-using-rfid-cards) for playout and controlling your Phoniebox. -* [Playout **Resume**](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#manage-playout-behaviour) switch for audio books, allowing you to jump straight back to where you were (unless you fell asleep...). -* Playout **Shuffle** switch to mix up your playlists. -* Download from **YouTube** directly to your Phoniebox. -* Support for **[Spotify](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Spotify-FAQ)** and **[Google Play Music](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Enable-Google-Play-Music-GMusic)** integration. -* **Podcasts!** More for myself than anybody else, I guess, I added the [podcast feature for Phoniebox](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#podcasts) (2018-05-09) -* [Buttons](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Using-GPIO-hardware-buttons) and [knobs / dials](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Audio-RotaryKnobVolume) to control your **Phoniebox via GPIO**. - -### Quick install - -[One line install script](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/INSTALL-stretch#one-line-install-command) for Raspbian `buster` available. - -* **MUST READ for users of [Phoniebox +Spotify Edition](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Spotify-FAQ)** -* This install script combines the two versions *Classic* and *+ Spotify*. -* *Phoniebox Classic* supports local audio, web radio, podcasts, YouTube (download and convert), GPIO and/or RFID +* [How to connect to the Phoniebox from any computer to add and edit audio files.](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#connect) +* [How to register new RFID cards, assign them a *human readable* shortcut and add audio files for each card.](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#registercardswebapp) +* [How to add webradio stations and other streams to the playout files](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#webstreams) - [and even mix web based and local files.](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#mixwebstreams) +* [Adding Podcasts the your Phoniebox](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#podcasts) +* [How to control the Phoniebox through the web app.](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#webapp) +* [How to assign cards specific tasks such as changing the volume level or shutting down the Phoniebox.](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#cardcontrol) -Documentation can be found in the [GitHub wiki for Phoniebox](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki). Please try to add content in the wiki regarding special hardware, software tweaks and the like. +### Troubleshooting + +There is a growing section of [troubleshooting](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Troubleshooting-FAQ) including: + +* I want to improve the onboard audio quality +* I am moving, how do I get the Phoniebox into my new WiFi network? +* The RFID Reader doesn't seem to work. +* Changing the volume does not work, but the playout works. +* Script `daemon_rfid_reader.py` only works via SSH not by RFID cards. +* Script daemon is closing down unexpectedly. +* Everything seems to work, but I hear nothing when swiping a card. +* I would like to use two cards / IDs to do the same thing. + +### Reporting Bugs + +To make maintenance easier for everyone, please run the following script and post the results when reporting a bug. +(Note: the results contain some personal information like IP or SSID. +You might want to erase some of it before sharing with the bug report.) + +~~~bash +/home/pi/RPi-Jukebox-RFID/scripts/helperscripts/Analytics_AfterInstallScript.sh +~~~ + +Just copy this line and paste it into your terminal on the pi. + +If you find something that doesn't work. And you tried and tried again, but it still doesn't work, please report your issue in the ["issues" section](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues). + +## Hardware aka Shopping List + +Here is a list of equipment needed. You can find a lot second hand online (save money and the planet). The links below lead to Amazon, not at all because I want to support them, but because their PartnerNet program helps to support the Phoniebox maintenance (a little bit...). + +Note: depending on individual projects, the hardware requirements vary. + +### Raspberry Pi + +* [Raspberry Pi 4 Modell B](https://amzn.to/2Yuei04) +* [Raspberry Pi 3 Model B](https://amzn.to/3fqp8ef) +* [Raspberry Pi Zero WH](https://amzn.to/3fkfKc5) + +You might be surprised how easy and affordable you can get an RPi second hand. Think about the planet before you buy a new one. + +### RFID Reader and cards / fobs + +* RFID Card Reader (USB): [Neuftech USB RFID Reader ID](https://amzn.to/2RrqScm) using 125 kHz - make sure to buy compatible cards, RFID stickers or key fobs working with the same frequency as the reader. + * RFID cards: [125 KHz EM4100](https://amzn.to/37pjy9q) make sure the frequency matches the RFID card reader! + * RFID fobs / key rings: [EM4100 RFID-Transponder-Schlüsselring, 125 KHz](https://amzn.to/3hsuvLO) make sure the frequency matches the RFID card reader! +* RFID Kit RC522: [RC522 Reader, Chip, Card for Raspberry Pi 13.56MHz](https://amzn.to/2C7YZCZ) + * RFID sticker / tags: [MIFARE RFID NFC Tags](https://amzn.to/30GfLDg) untested by me personally, but reported to work with work with RC522 and PN532 card readers. + +### Speakers / amps + +* [USB Stereo Speaker Set (6 Watt, 3,5mm jack, USB-powered) black](http://amzn.to/2kXrard) | This USB powered speaker set sounds good for its size, is good value for money and keeps this RPi project clean and without the need of a soldering iron :) +* [USB A Male to Female Extenstion Cable with Switch On/Off](http://amzn.to/2hHrvkG) | I placed this USB extension between the USB power adapter and the Phoniebox. This will allow you to switch the Phoniebox on and off easily. +* [USB 2.0 Hub 4-port bus powered USB Adapter](http://amzn.to/2kXeErv) | Depending on your setup, you will need none, one or two of these. If you are using the external USB powered speakers, you need one to make sure the speakers get enough power. If you want to use the additional USB soundcard and have an older RPi, you might need a second one to make sure you can connect enough devices with the RPi. + +### Arcade Buttons + +* [USB Interface for Arcade buttons](https://amzn.to/3nRAtIS) if you insist on not soldering hardware. +* Arcade Buttons / Sensors (one of these might suit you) + * [Arcade Buttons / Schalter in various colours](https://amzn.to/2QMxe9r) if you want buttons for the GPIO control. + * [Arcade Buttons wit LED and custom icons](https://amzn.to/2MWQ6hq) as used by [@splitti](https://splittscheid.de/selfmade-phoniebox/#3C). + * [Set: Arcade Buttons / Tasten / Schalter](https://amzn.to/2T81JTZ) GPIO Extension Board Starter Kit including cables and breadboard. + * [Touch Sensor / Kapazitive Touch Tasten](https://amzn.to/2Vc4ntx) these are not buttons to press but to touch as GPIO controls. + +### Special hardware + +These are links to additional items, which will add an individual flavour to your Phoniebox setup. Consult the issue threads to see if your idea has been realised already. + +* [Ground Loop Isolator / Entstörfilter Audio](https://amzn.to/2Kseo0L) this seems to [get rid off crackles in the audio out (a typical RPi problem)](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/341) +* [Mechanical audio switch](https://amzn.to/35oOSCS) if you want to connect differen audio devices, this is the easiest way (in connection with the *Ground Loop Isolator* you will get good results) +* [Rotary Encoder / Drehregler / Dial](https://amzn.to/2J34guF) for volume control. Read here for more information on how to [integrate the rotary dial](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/267) +* [HiFiBerry DAC+ Soundcard](https://amzn.to/2J36cU9) Read here for more information on how to [HifiBerry Soundcard integration](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/HiFiBerry-Soundcard-Details) +* [HDMI zu HDMI + Optisches SPDIF mit 3,5-mm-Stereo-HDMI Audio-Extractor | HDMI zu SPDIF Konverter](https://amzn.to/2N8KP8C) If you plan to use video, this might be the better solution than a USB soundcard or the hifiberry. If takes up some space, but will work with the HDMI audio out and split the signal to deliver audio through 3.5mm jack. + +### Components + +Special hardware is now organised in the folder [`components`](components/). If you have new hardware attached to your Phoniebox, please add to this library! It currently contains soundcards, displays, GPIO controls, RFID reader, smarthome integration. ---- +## Support Phoniebox - If you like your Phoniebox, consider to [buy me a coffee](https://www.buymeacoffee.com/MiczFlor) -or donate via [PayPal](https://www.paypal.com) to micz.flor@web.de using the *friends* option. +or donate via [PayPal](https://www.paypal.com) to using the *friends* option. ---- +## Media + +### Videos and Screenshots Prototype of the RFID jukebox -*See the Phoniebox code in action, watch this video and read the blog post from [iphone-ticker.de](https://www.iphone-ticker.de/wochenend-projekt-kontaktlose-musikbox-fuer-kinder-123063/)* +See the Phoniebox code in action, watch this video and read the blog post from [iphone-ticker.de](https://www.iphone-ticker.de/wochenend-projekt-kontaktlose-musikbox-fuer-kinder-123063/) **We love Tech** published a video screencast on *how to build your Phoniebox* (in German), you can find all the steps and see the final product here: @@ -153,7 +232,7 @@ A new video screencast about **What makes this Phoniebox easy to install and use:** -* Runs on all Raspberry Pi models (1, 2 and 3) and [Raspberry Zero](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/15). (jump to the [install instructions](#install)) +* Runs on all Raspberry Pi models (1, 2, 3 and 4) and [Raspberry Zero](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/15). * Just plug and play using USB, no soldering iron needed. * Once the Phoniebox is up and running, add music from any computer on your home network. * Register new RFID cards easily without having to connect to the RPi. @@ -172,13 +251,13 @@ The **web app** runs on any device and is mobile optimised. It provides: * Register new RFID cards, manage Phoniebox settings, display system info and edit the wifi connection. * Covers displayed in the web app (files called `cover.jpg`). -## Phoniebox Gallery +### Phoniebox Gallery | | | | | | | | --- | --- | --- | --- | --- | --- | | ![Caption](docs/img/gallery/Steph-20171215_h90-01.jpg "Caption") | ![Caption](docs/img/gallery/Elsa-20171210_h90-01.jpg "Caption") | ![Caption](docs/img/gallery/Geliras-20171228-Jukebox-01-h90.jpg "Caption") | ![Caption](docs/img/gallery/UlliH-20171210_h90-01.jpg "Caption") | ![Caption](docs/img/gallery/KingKahn-20180101-Jukebox-01-h90.jpg "Caption") | ![Caption](docs/img/gallery/hailogugo-20171222-h90-01.jpg "Caption") | -**See more innovation, upcycling and creativity in the [Phoniebox Gallery](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/GALLERY) or visit and share the project's homepage at [phoniebox.de](http://phoniebox.de/). There is also an [english Phoniebox page](http://phoniebox.de/index.php?l=en).** +**See more innovation, upcycling and creativity in the [Phoniebox Gallery](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/GALLERY) or visit and share the project's homepage at [phoniebox.de](https://phoniebox.de/). There is also an [english Phoniebox page](https://phoniebox.de/index-en.html).** ## Sustainability @@ -191,64 +270,10 @@ Creating a Phoniebox may be sustainable for the following reasons: * **RFID cards or tags can be reused - no need to buy new plastic elements** for changing the music or story linked to a card * **Build it together with your kids** to show them that building things on their own is possible and in cooperation with others makes life easier and fun at the same time -## Installation - -* Installation instructions for Raspbian (). -* You can also use the [headless installation over ssh](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/INSTALL-stretch#ssh-install) straight from a fresh SD card. -* For a quick install procedure, take a look at the [bash one line install script for stretch and buster](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/INSTALL-stretch#one-line-install-command). This should get you started quickly. -* If you choose the step by step installation, you need to walk through the configuration steps for [Stretch](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/CONFIGURE-stretch). -* Once everything has been installed and configured, [read the manual](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL) to change settings, register RFID cards, add audio. - -Adding push buttons to control volume, skipping tracks, pause, play: read the [GPIO buttons installation guide](docs/GPIO-BUTTONS.md). - -### Components - -Special hardware is now organised in the folder [`components`](https://github.com/MiczFlor/RPi-Jukebox-RFID/tree/master/components). If you have new hardware attached to your Phoniebox, please add to this library! It currently contains soundcards, displays, GPIO controls, RFID reader, smarthome integration. - -## Manual - -In the [Manual](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL) you will learn: - -* [How to connect to the Phoniebox from any computer to add and edit audio files.](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#connect) -* [How to register new RFID cards, assign them a *human readable* shortcut and add audio files for each card.](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#registercards) -* [How to add webradio stations and other streams to the playout files](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#webstreams) - [and even mix web based and local files.](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#mixwebstreams) -* [Adding Podcasts the your Phoniebox](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#podcasts) -* [How to control the Phoniebox through the web app.](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#webapp) -* [How to assign cards specific tasks such as changing the volume level or shutting down the Phoniebox.](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#cardcontrol) - ## Contributing improvements Read the [CONTRIBUTING.md](CONTRIBUTING.md) file for [more infos on how to contribute code](CONTRIBUTING.md). -## Reporting bugs - -To make maintenance easier for everyone, please run the following script and post the results when reporting a bug. -(Note: the results contain some personal information like IP or SSID. -You might want to erase some of it before sharing with the bug report.) - -~~~bash -/home/pi/RPi-Jukebox-RFID/scripts/helperscripts/Analytics_AfterInstallScript.sh -~~~ - -Just copy this line and paste it into your terminal on the pi. - -If you find something that doesn't work. And you tried and tried again, but it still doesn't work, please report your issue in the ["issues" section](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues). Make sure to include information about the system and hardware you are using, like: - -*Raspberry ZERO, OS Jessie, Card reader lists as (insert here) when running scripts/RegisterDevice.py, installed Phoniebox version 0.9.3 (or: using latest master branch).* - -## Troubleshooting - -There is a growing section of [troubleshooting](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#faq) including: - -* I want to improve the onboard audio quality -* I am moving, how do I get the Phoniebox into my new WiFi network? -* The RFID Reader doesn't seem to work. -* Changing the volume does not work, but the playout works. -* Script `daemon_rfid_reader.py` only works via SSH not by RFID cards. -* Script daemon is closing down unexpectedly. -* Everything seems to work, but I hear nothing when swiping a card. -* I would like to use two cards / IDs to do the same thing. - ## Acknowledgments There are many, many, many inspiring suggestions and solutions on the web to bring together the idea of a jukebox with RFID cards. I want to mention a few of these that have inspired me. @@ -266,56 +291,3 @@ I also want to link to two proprietary and commercial projects, because they wer * [tonies® - das neue Audiosystem für mehr Hör-Spiel-Spaß im Kinderzimmer. (German)](https://tonies.de/) You buy a plastic figure which then triggers the audiofile - which is served over the web. * [Hörbert - a MP3 player controlled by buttons](https://hoerbert.com) In Germany this has already become a *classic*. They also started selling a DIY kit. - ---- - - - -If you like your Phoniebox, consider to [buy me a coffee](https://www.buymeacoffee.com/MiczFlor) - ---- - -## Shopping list - -Here is a list of equipment needed. You can find a lot second hand online (save money and the planet). The links below lead to amazon, not at all because I want to support them, but because their PartnerNet program helps to support the Phoniebox maintenance (a little bit...). **Note: depending on individual projects, the hardware requirements vary.** - -### Raspberry Pi - -* [Raspberry Pi 4 Modell B](https://amzn.to/2Yuei04) -* [Raspberry Pi 3 Model B](https://amzn.to/3fqp8ef) -* [Raspberry Pi Zero WH](https://amzn.to/3fkfKc5) -* Note: You might be surprised how easy and affordable you can get an RPi second hand. Think about the planet before you buy a new one. - -### RFID Reader and cards / fobs - -* RFID Card Reader (USB): [Neuftech USB RFID Reader ID](https://amzn.to/2RrqScm) using 125 kHz - make sure to buy compatible cards, RFID stickers or key fobs working with the same frequency as the reader. **Important notice:** the hardware of the reader that I had linked here for a long times seems to have changed and suddenly created problems with the Phoniebox installation. The reader listed now has worked and was recommended by two Phoniebox makers (2018 Oct 4). I can not guarantee that this will not change and invite you to give [RFID Reader feedback in this thread](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/231). - * RFID cards: [125 KHz EM4100](https://amzn.to/37pjy9q) make sure the frequency matches the RFID card reader !!! - * RFID fobs / key rings: [EM4100 RFID-Transponder-Schlüsselring, 125 KHz](https://amzn.to/3hsuvLO) make sure the frequency matches the RFID card reader !!! - -* RFID Kit RC522: [RC522 Reader, Chip, Card for Raspberry Pi 13.56MHz] () - * RFID sticker / tags: [MIFARE RFID NFC Tags](https://amzn.to/30GfLDg) untested by me personally, but reported to work with work with RC522 and PN532 card readers. - -### Speakers / amps - -* [USB Stereo Speaker Set (6 Watt, 3,5mm jack, USB-powered) black](http://amzn.to/2kXrard) | This USB powered speaker set sounds good for its size, is good value for money and keeps this RPi project clean and without the need of a soldering iron :) -* [USB A Male to Female Extenstion Cable with Switch On/Off](http://amzn.to/2hHrvkG) | I placed this USB extension between the USB power adapter and the Phoniebox. This will allow you to switch the Phoniebox on and off easily. -* [USB 2.0 Hub 4-port bus powered USB Adapter](http://amzn.to/2kXeErv) | Depending on your setup, you will need none, one or two of these. If you are using the external USB powered speakers, you need one to make sure the speakers get enough power. If you want to use the additional USB soundcard and have an older RPi, you might need a second one to make sure you can connect enough devices with the RPi. - -### Arcade Buttons - -* [USB Interface for Arcade buttons](https://amzn.to/3nRAtIS) if you insist on not soldering hardware. (23rd Nov 2020: GPIO control script not yet part of the repo) -* Arcade Buttons / Sensors (one of these might suit you) - * [Arcade Buttons / Schalter in various colours](https://amzn.to/2QMxe9r) if you want buttons for the GPIO control. - * [Arcade Buttons wit LED and custom icons](https://amzn.to/2MWQ6hq) as used by [@splitti](https://splittscheid.de/selfmade-phoniebox/#3C). - * [Set: Arcade Buttons / Tasten / Schalter](https://amzn.to/2T81JTZ) GPIO Extension Board Starter Kit including cables and breadboard. - * [Touch Sensor / Kapazitive Touch Tasten](https://amzn.to/2Vc4ntx) these are not buttons to press but to touch as GPIO controls. - -### Special hardware - -These are links to additional items, which will add an individual flavour to your Phoniebox setup. Consult the issue threads to see if your idea has been realised already. - -* [Ground Loop Isolator / Entstörfilter Audio](https://amzn.to/2Kseo0L) this seems to [get rid off crackles in the audio out (a typical RPi problem)](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/341) -* [Mechanical audio switch](https://amzn.to/35oOSCS) if you want to connect differen audio devices, this is the easiest way (in connection with the *Ground Loop Isolator* you will get good results) -* [Rotary Encoder / Drehregler / Dial](https://amzn.to/2J34guF) for volume control. Read here for more information on how to [integrate the rotary dial](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/267) -* [HiFiBerry DAC+ Soundcard](https://amzn.to/2J36cU9) Read here for more information on how to [HifiBerry Soundcard integration](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#hifiberry-dac-soundcard-details) -* [HDMI zu HDMI + Optisches SPDIF mit 3,5-mm-Stereo-HDMI Audio-Extractor | HDMI zu SPDIF Konverter](https://amzn.to/2N8KP8C) If you plan to use video, this might be the better solution than a USB soundcard or the hifiberry. If takes up some space, but will work with the HDMI audio out and split the signal to deliver audio through 3.5mm jack. diff --git a/ci/Dockerfile.buster.amd64 b/ci/Dockerfile.buster.amd64 deleted file mode 100644 index 7aafa047e..000000000 --- a/ci/Dockerfile.buster.amd64 +++ /dev/null @@ -1,30 +0,0 @@ -FROM debian:buster - -COPY . /code -WORKDIR /code - -RUN groupadd --gid 1000 pi ;\ - useradd -u 1000 -g 1000 -G sudo -d /home/pi -m -s /bin/bash -p '$1$iV7TOwOe$6ojkJQXyEA9bHd/SqNLNj0' pi ;\ - chown -R 1000:1000 /code /home/pi ;\ - chmod +x /code/scripts/installscripts/buster-install-default.sh - -RUN export DEBIAN_FRONTEND=noninteractive ;\ - apt-get update ;\ - apt-get -y install curl gnupg sudo nano;\ - echo 'deb http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi' > /etc/apt/sources.list.d/raspi.list ;\ - echo 'deb http://archive.raspberrypi.org/debian/ buster main' >> /etc/apt/sources.list.d/raspi.list ;\ - curl http://raspbian.raspberrypi.org/raspbian.public.key | apt-key add - ;\ - curl http://archive.raspberrypi.org/debian/raspberrypi.gpg.key | apt-key add - ;\ - echo 'pi ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/pi ;\ - apt-get clean ;\ - rm -rf /var/cache/apt/* /var/lib/apt/lists/* - -RUN export DEBIAN_FRONTEND=noninteractive ;\ - apt-get update ;\ - apt-get -y dist-upgrade --auto-remove --purge ;\ - apt-get -y install wget build-essential git iw locales wpasupplicant;\ - apt-get clean ;\ - touch /boot/cmdline.txt /etc/sysctl.conf ;\ - rm -rf /var/cache/apt/* /var/lib/apt/lists/* - -USER pi diff --git a/ci/Dockerfile.buster.armv7 b/ci/Dockerfile.buster.armv7 deleted file mode 100644 index 2041697be..000000000 --- a/ci/Dockerfile.buster.armv7 +++ /dev/null @@ -1,30 +0,0 @@ -FROM arm32v7/debian:buster-slim - -COPY . /code -WORKDIR /code - -RUN groupadd --gid 1000 pi ;\ - useradd -u 1000 -g 1000 -G sudo -d /home/pi -m -s /bin/bash -p '$1$iV7TOwOe$6ojkJQXyEA9bHd/SqNLNj0' pi ;\ - chown -R 1000:1000 /code /home/pi ;\ - chmod +x /code/scripts/installscripts/buster-install-default.sh - -RUN export DEBIAN_FRONTEND=noninteractive ;\ - apt-get update ;\ - apt-get -y install curl gnupg sudo nano;\ - echo 'deb http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi' >> /etc/apt/sources.list.d/raspi.list ;\ - echo 'deb http://archive.raspberrypi.org/debian/ buster main' > /etc/apt/sources.list.d/raspi.list ;\ - curl http://raspbian.raspberrypi.org/raspbian.public.key | apt-key add - ;\ - curl http://archive.raspberrypi.org/debian/raspberrypi.gpg.key | apt-key add - ;\ - echo 'pi ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/pi ;\ - apt-get clean ;\ - rm -rf /var/cache/apt/* /var/lib/apt/lists/* - -RUN export DEBIAN_FRONTEND=noninteractive ;\ - apt-get update ;\ - apt-get -y dist-upgrade --auto-remove --purge ;\ - apt-get -y install wget build-essential git iw locales wpasupplicant ;\ - apt-get clean ;\ - touch /boot/cmdline.txt /etc/sysctl.conf ;\ - rm -rf /var/cache/apt/* /var/lib/apt/lists/* - -USER pi diff --git a/ci/Dockerfile.buster.test_install.amd64 b/ci/Dockerfile.buster.test_install.amd64 deleted file mode 100644 index 54b78b78c..000000000 --- a/ci/Dockerfile.buster.test_install.amd64 +++ /dev/null @@ -1,33 +0,0 @@ -FROM debian:buster - -COPY . /code -WORKDIR /code - -RUN groupadd --gid 1000 pi ;\ - useradd -u 1000 -g 1000 -G sudo -d /home/pi -m -s /bin/bash -p '$1$iV7TOwOe$6ojkJQXyEA9bHd/SqNLNj0' pi ;\ - chown -R 1000:1000 /code /home/pi ;\ - chmod +x /code/scripts/installscripts/buster-install-default.sh ;\ - chmod +x /code/scripts/installscripts/tests/run_installation_tests.sh ;\ - chmod +x /code/scripts/installscripts/tests/run_installation_tests2.sh ;\ - chmod +x /code/scripts/installscripts/tests/run_installation_tests3.sh - -RUN export DEBIAN_FRONTEND=noninteractive ;\ - apt-get update ;\ - apt-get -y install curl gnupg sudo nano systemd apt-utils;\ - echo 'deb http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi' > /etc/apt/sources.list.d/raspi.list ;\ - echo 'deb http://archive.raspberrypi.org/debian/ buster main' >> /etc/apt/sources.list.d/raspi.list ;\ - curl http://raspbian.raspberrypi.org/raspbian.public.key | apt-key add - ;\ - curl http://archive.raspberrypi.org/debian/raspberrypi.gpg.key | apt-key add - ;\ - echo 'pi ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/pi ;\ - apt-get clean ;\ - rm -rf /var/cache/apt/* /var/lib/apt/lists/* - -RUN export DEBIAN_FRONTEND=noninteractive ;\ - apt-get update ;\ - apt-get -y dist-upgrade --auto-remove --purge ;\ - apt-get -y install wget build-essential git iw locales wpasupplicant;\ - apt-get clean ;\ - touch /boot/cmdlinetxt ;\ - rm -rf /var/cache/apt/* /var/lib/apt/lists/* - -USER pi diff --git a/ci/Dockerfile.buster.test_install_altuser.amd64 b/ci/Dockerfile.buster.test_install_altuser.amd64 deleted file mode 100644 index 9def1fcbf..000000000 --- a/ci/Dockerfile.buster.test_install_altuser.amd64 +++ /dev/null @@ -1,33 +0,0 @@ -FROM debian:buster - -COPY . /code -WORKDIR /code - -RUN groupadd --gid 1000 wurst ;\ - useradd -u 1000 -g 1000 -G sudo -d /home/hans -m -s /bin/bash -p '$1$iV7TOwOe$6ojkJQXyEA9bHd/SqNLNj0' hans ;\ - chown -R 1000:1000 /code /home/hans ;\ - chmod +x /code/scripts/installscripts/buster-install-default.sh ;\ - chmod +x /code/scripts/installscripts/tests/run_installation_tests_altuser.sh ;\ - chmod +x /code/scripts/installscripts/tests/run_installation_tests2_altuser.sh ;\ - chmod +x /code/scripts/installscripts/tests/run_installation_tests3_altuser.sh - -RUN export DEBIAN_FRONTEND=noninteractive ;\ - apt-get update ;\ - apt-get -y install curl gnupg sudo nano systemd apt-utils;\ - echo 'deb http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi' > /etc/apt/sources.list.d/raspi.list ;\ - echo 'deb http://archive.raspberrypi.org/debian/ buster main' >> /etc/apt/sources.list.d/raspi.list ;\ - curl http://raspbian.raspberrypi.org/raspbian.public.key | apt-key add - ;\ - curl http://archive.raspberrypi.org/debian/raspberrypi.gpg.key | apt-key add - ;\ - echo 'hans ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/hans ;\ - apt-get clean ;\ - rm -rf /var/cache/apt/* /var/lib/apt/lists/* - -RUN export DEBIAN_FRONTEND=noninteractive ;\ - apt-get update ;\ - apt-get -y dist-upgrade --auto-remove --purge ;\ - apt-get -y install wget build-essential git iw locales wpasupplicant;\ - apt-get clean ;\ - touch /boot/cmdlinetxt ;\ - rm -rf /var/cache/apt/* /var/lib/apt/lists/* - -USER hans diff --git a/ci/Dockerfile.debian b/ci/Dockerfile.debian new file mode 100644 index 000000000..eb545e6b3 --- /dev/null +++ b/ci/Dockerfile.debian @@ -0,0 +1,112 @@ +# Base Target to build and install all needed base configuration and packages. Specifie the needed platform with the docker '--platform XXX' option +ARG DEBIAN_CODENAME=bullseye +ARG BASE_TEST_IMAGE=test-code +FROM debian:${DEBIAN_CODENAME}-slim as base +ARG DEBIAN_CODENAME + +ENV DOCKER_RUNNING=true +RUN touch /boot/cmdlinetxt + +RUN export DEBIAN_FRONTEND=noninteractive \ + && echo "--- install packages (1) ---" \ + && apt-get update \ + && apt-get -y install \ + apt-utils \ + curl \ + gnupg \ + && echo "--- add sources ---" \ + && curl -fsSL http://raspbian.raspberrypi.org/raspbian.public.key | gpg --dearmor > /usr/share/keyrings/raspberrypi-raspbian-keyring.gpg \ + && curl -fsSL http://archive.raspberrypi.org/debian/raspberrypi.gpg.key | gpg --dearmor > /usr/share/keyrings/raspberrypi-archive-debian-keyring.gpg \ + && echo "deb [signed-by=/usr/share/keyrings/raspberrypi-raspbian-keyring.gpg] http://raspbian.raspberrypi.org/raspbian/ ${DEBIAN_CODENAME} main contrib non-free rpi" > /etc/apt/sources.list.d/raspi.list \ + && echo "deb [signed-by=/usr/share/keyrings/raspberrypi-archive-debian-keyring.gpg] http://archive.raspberrypi.org/debian/ ${DEBIAN_CODENAME} main" >> /etc/apt/sources.list.d/raspi.list \ + && echo "--- install packages (2) ---" \ + && apt-get update \ + && apt-get -y upgrade \ + && apt-get -y install \ + alsa-utils \ + build-essential \ + locales \ + sudo \ + systemd \ + wireless-tools \ + wget \ + wpasupplicant \ + && rm -rf /var/lib/apt/lists/* +# ------ + +# Base Target for setting up the default user. user can be selected with the docker '--user YYY' option +FROM base as user +ARG USER=pi +ARG USER_GROUP=$USER + +ENV USER=$USER USER_GROUP=$USER_GROUP + +RUN groupadd --gid 1000 $USER_GROUP \ + && useradd -u 1000 -g $USER_GROUP -G sudo -d /home/$USER -m -s /bin/bash -p '$1$iV7TOwOe$6ojkJQXyEA9bHd/SqNLNj0' $USER \ + && echo "$USER ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$USER +# ------ + + + +####### Code Targets ####### + +# Target for adding code from the repo. Set Default User +FROM user as code + +COPY --chown=$USER:$USER_GROUP --chmod=770 . /code +WORKDIR /code + +USER $USER +# ------ + + + +####### Test Targets ####### + +# Target for setting up an alternativ user 'hans:wurst'. user can be selected with the docker '--user YYY' option +FROM user as test-user + +ENV TEST_USER_GROUP=test + +RUN groupadd --gid 1002 $TEST_USER_GROUP \ + && usermod -a -G $TEST_USER_GROUP $USER + +RUN export USER_ALT=hans \ + && export USER_ALT_GROUP=wurst \ + && groupadd --gid 1001 $USER_ALT_GROUP \ + && useradd -u 1001 -g $USER_ALT_GROUP -G sudo,$TEST_USER_GROUP -d /home/$USER_ALT -m -s /bin/bash -p '$1$iV7TOwOe$6ojkJQXyEA9bHd/SqNLNj0' $USER_ALT \ + && echo "$USER_ALT ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$USER_ALT +# ------ + + +# Target for adding envs and scripts from the repo to test installation +FROM test-user as test-code +ARG GIT_BRANCH +ARG GIT_URL + +ENV GIT_BRANCH=$GIT_BRANCH GIT_URL=$GIT_URL + +COPY --chown=root:$TEST_USER_GROUP --chmod=770 packages.txt packages-raspberrypi.txt ./ + +RUN export DEBIAN_FRONTEND=noninteractive \ + && echo "--- install internal packages ---" \ + && apt-get update \ + # remove resolvconf as installation will fail in container + && sed 's/#.*//g' packages.txt | sed 's/resolvconf//' | xargs apt-get -y install \ + && sed 's/#.*//g' packages-raspberrypi.txt | xargs apt-get -y install \ + && rm -rf /var/lib/apt/lists/* + +COPY --chown=root:$TEST_USER_GROUP --chmod=770 scripts/installscripts/install-jukebox.sh ./ +WORKDIR /tests +COPY --chown=root:$TEST_USER_GROUP --chmod=770 scripts/installscripts/tests/*.sh ./ + +# ------ + + +# Target for applying latest updates (should not be cached!) +FROM $BASE_TEST_IMAGE as test-update +RUN export DEBIAN_FRONTEND=noninteractive \ + && apt-get update \ + && apt-get -y upgrade \ + && rm -rf /var/lib/apt/lists/* +# ------ diff --git a/ci/Dockerfile.stretch.amd64 b/ci/Dockerfile.stretch.amd64 deleted file mode 100644 index 86fc73858..000000000 --- a/ci/Dockerfile.stretch.amd64 +++ /dev/null @@ -1,30 +0,0 @@ -FROM debian:stretch - -COPY . /code -WORKDIR /code - -RUN groupadd --gid 1000 pi ;\ - useradd -u 1000 -g 1000 -G sudo -d /home/pi -m -s /bin/bash -p '$1$iV7TOwOe$6ojkJQXyEA9bHd/SqNLNj0' pi ;\ - chown -R 1000:1000 /code /home/pi ;\ - chmod +x /code/scripts/installscripts/stretch-install-default.sh - -RUN export DEBIAN_FRONTEND=noninteractive ;\ - apt-get update ;\ - apt-get -y install curl gnupg sudo nano;\ - echo 'deb http://raspbian.raspberrypi.org/raspbian/ stretch main contrib non-free rpi' > /etc/apt/sources.list.d/raspi.list ;\ - echo 'deb http://archive.raspberrypi.org/debian/ stretch main' >> /etc/apt/sources.list.d/raspi.list ;\ - curl http://raspbian.raspberrypi.org/raspbian.public.key | apt-key add - ;\ - curl http://archive.raspberrypi.org/debian/raspberrypi.gpg.key | apt-key add - ;\ - echo 'pi ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/pi ;\ - apt-get clean ;\ - rm -rf /var/cache/apt/* /var/lib/apt/lists/* - -RUN export DEBIAN_FRONTEND=noninteractive ;\ - apt-get update ;\ - apt-get -y dist-upgrade --auto-remove --purge ;\ - apt-get -y install wget build-essential git iw locales wpasupplicant;\ - apt-get clean ;\ - touch /boot/cmdline.txt /etc/sysctl.conf ;\ - rm -rf /var/cache/apt/* /var/lib/apt/lists/* - -USER pi diff --git a/ci/Dockerfile.stretch.armv7 b/ci/Dockerfile.stretch.armv7 deleted file mode 100644 index e37eeae02..000000000 --- a/ci/Dockerfile.stretch.armv7 +++ /dev/null @@ -1,30 +0,0 @@ -FROM arm32v7/debian:stretch-slim - -COPY . /code -WORKDIR /code - -RUN groupadd --gid 1000 pi ;\ - useradd -u 1000 -g 1000 -G sudo -d /home/pi -m -s /bin/bash -p '$1$iV7TOwOe$6ojkJQXyEA9bHd/SqNLNj0' pi ;\ - chown -R 1000:1000 /code /home/pi ;\ - chmod +x /code/scripts/installscripts/stretch-install-default.sh - -RUN export DEBIAN_FRONTEND=noninteractive ;\ - apt-get update ;\ - apt-get -y install curl gnupg sudo nano;\ - echo 'deb http://raspbian.raspberrypi.org/raspbian/ stretch main contrib non-free rpi' >> /etc/apt/sources.list.d/raspi.list ;\ - echo 'deb http://archive.raspberrypi.org/debian/ stretch main' > /etc/apt/sources.list.d/raspi.list ;\ - curl http://raspbian.raspberrypi.org/raspbian.public.key | apt-key add - ;\ - curl http://archive.raspberrypi.org/debian/raspberrypi.gpg.key | apt-key add - ;\ - echo 'pi ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/pi ;\ - apt-get clean ;\ - rm -rf /var/cache/apt/* /var/lib/apt/lists/* - -RUN export DEBIAN_FRONTEND=noninteractive ;\ - apt-get update ;\ - apt-get -y dist-upgrade --auto-remove --purge ;\ - apt-get -y install wget build-essential git iw locales wpasupplicant ;\ - apt-get clean ;\ - touch /boot/cmdline.txt /etc/sysctl.conf ;\ - rm -rf /var/cache/apt/* /var/lib/apt/lists/* - -USER pi diff --git a/ci/README.md b/ci/README.md index 9bb4e874f..674dedd64 100644 --- a/ci/README.md +++ b/ci/README.md @@ -8,7 +8,7 @@ This is a work in progress so expect things to fail or being flaky. ## Howto * First you need a raspberry pi with some decent performance (RPi 3 or 4 would be recommended) -* Flash its sd card with **raspbian buster lite** +* Flash its sd card with **Raspberry Pi OS lite** * use raspi-config to resize the filesystem to the whole sd card (menu: 7 -> A1) * install some tools and reboot: ```bash @@ -19,30 +19,33 @@ This is a work in progress so expect things to fail or being flaky. sudo reboot ``` * login to your RPi -* clone this repo and cd into its local clone: +* clone the repo and cd into its local clone: ```bash + cd /home/pi/ + # optional: change to your fork appropriately git clone https://github.com/MiczFlor/RPi-Jukebox-RFID.git - cd /home/pi/RPi-Jukebox-RFID/ + cd RPi-Jukebox-RFID/ + # optional: switch to another branch + git checkout ``` * build the docker image: - * **on normal PCs:** - ```bash - docker build -t rpi-jukebox-rfid-stretch:latest -f ci/Dockerfile.stretch.amd64 . - docker build -t rpi-jukebox-rfid-buster:latest -f ci/Dockerfile.buster.amd64 . - ``` + ```bash + docker build -t rpi-jukebox-rfid:debian-latest -f ci/Dockerfile.debian --platform=linux/arm/v7 --target=code . + ``` + * additional arguments + * for builds + - on normal PCs use `--platform=linux/amd64` + - on a raspberry pi use `--platform=linux/arm/v7` + * to use a different debian version as base add parameter `--build-arg="DEBIAN_CODENAME="` ( = e.g. buster, bullseye, ...). - * **on a raspberry pi:** - ```bash - docker build -t rpi-jukebox-rfid-stretch:latest -f ci/Dockerfile.stretch.armv7 . - docker build -t rpi-jukebox-rfid-buster:latest -f ci/Dockerfile.buster.armv7 . - ``` * get something to drink or eat * run the freshly built docker image and start testing. For example: ```bash - docker run --rm -ti rpi-jukebox-rfid-buster:latest /bin/bash + docker run --rm -ti rpi-jukebox-rfid:debian-latest /bin/bash cd /home/pi/ - cp /code/scripts/installscripts/buster-install-default.sh /home/pi/ - bash buster-install-default.sh + cp /code/scripts/installscripts/install-jukebox.sh /home/pi/ + # set GIT_URL and GIT_BRANCH appropriately to your checkout + bash GIT_URL=https://github.com/MiczFlor/RPi-Jukebox-RFID.git GIT_BRANCH=main install-jukebox.sh ``` NOTE: Get familiar with docker and its flags - `--rm` for example will remove the @@ -50,19 +53,7 @@ This is a work in progress so expect things to fail or being flaky. ### mount hosts code as volume -The created image now contains all the code in the directory `/code` - if you do not want to -rebuild the image after each code-change you can 'mount' the RPi's code version into the -container: - -```bash - git clone https://github.com/MiczFlor/RPi-Jukebox-RFID.git - cd /home/pi/RPi-Jukebox-RFID/ - docker build -t rpi-jukebox-rfid-buster:latest -f ci/Dockerfile . - docker run --rm -ti -w /code -v $PWD:/code rpi-jukebox-rfid-buster:latest /bin/bash - - cd /home/pi/ - cp /code/scripts/installscripts/buster-install-default.sh /home/pi/ - bash buster-install-default.sh -``` +The created image now contains all the code in the directory `/code` - if you do not want to rebuild the image after each code-change you can 'mount' the RPi's code version into the container. +Add `-w /code -v $PWD:/code` to the `docker run` parameter. In that way every change to the code in the container will be available on the RPi as well as vice versa. diff --git a/components/audio/PirateAudioHAT/README.md b/components/audio/PirateAudioHAT/README.md index adebac7ef..82a02396b 100644 --- a/components/audio/PirateAudioHAT/README.md +++ b/components/audio/PirateAudioHAT/README.md @@ -74,12 +74,15 @@ NOTE: changes to the installation should find their way into the script `setup_p bcm6 = volume_down,active_low,150 bcm16 = next,active_low,150 bcm20 = volume_up,active_low,150 + bcm24 = volume_up,active_low,150 [pidi] enabled = true display = st7789 ``` + **Attention:** Early revisions of PirateAudio HAT used bcm20 for Volume up, later revisions use bcm24. see also + 12. Enable access for modipy user `sudo usermod -a -G spi,i2c,gpio,video mopidy` 13. Reboot Raspberry Pi diff --git a/components/audio/PirateAudioHAT/setup_pirateAudioHAT.sh b/components/audio/PirateAudioHAT/setup_pirateAudioHAT.sh index add059670..a6152a0ca 100755 --- a/components/audio/PirateAudioHAT/setup_pirateAudioHAT.sh +++ b/components/audio/PirateAudioHAT/setup_pirateAudioHAT.sh @@ -106,6 +106,7 @@ bcm5 = play_pause,active_low,150 bcm6 = volume_down,active_low,150 bcm16 = next,active_low,150 bcm20 = volume_up,active_low,150 +bcm24 = volume_up,active_low,150 [pidi] enabled = true diff --git a/components/bluetooth-sink-switch/README.md b/components/bluetooth-sink-switch/README.md index 16fabde10..8e5c9cec3 100644 --- a/components/bluetooth-sink-switch/README.md +++ b/components/bluetooth-sink-switch/README.md @@ -4,7 +4,7 @@ This component provides a mechanism to toggle between both audio sinks through all the usual user interfaces (i.e. GPIO, RFID Card Swipe, Web Interface). The current status is reflected in the Web Interface and through an optional LED. -**Convinced? So, what is the vision?** +## Convinced? So, what is the vision? When a user powers on their Bluetooth headphones, they connect automatically to the Phoniebox. At the switch of the button (or card swipe, etc) the (already running) audio playback is transferred from the speakers to the headphones. This happens almost seamlessly. Parents feel an instant wave of relief at not having to listen to the 500th iteration of this month favourite song. The small user feels instantly proud at having working headphones much like the mom/dad always uses while doing home-office online meetings. If no Bluetooth headphones are connected, the audio sink toggle request defaults to speakers. An LED indicates the currently active audio sink. @@ -14,21 +14,21 @@ If no bluetooth device is connected, the output defaults back to speakers. After ![Web Interface Add-on in settings.php](webif.png "Web Interface Add-on in settings.php") -**Limitations** +### Limitations This feature only works for the *Classic* Edition. Why? It relies on the mpd multiple output channels feature to switch between outputs. This is no available in mopidy, which is used in the Spotify Edition. -### Installation +## Installation This looks lengthy, but I the major deal is setting up your audio output devices. I have been rather explicit to avoid confusion. -#### Step 1) Setting up asound.conf +### Step 1) Setting up asound.conf You need to set up both audio sinks and make sure they work. This is pretty much a prerequisite for everything that follows. Follow the instructions for your soundcard. Configure `/etc/asound.conf`correctly. And make sure it works! -Then follow the instructions on the [Wiki on how to connect the bluetooth device](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Bluetooth). We diverge where we set up two audio sinks instead of one: Just **add** the `pcm.btspeaker` section described in the wiki to `/etc/asound.conf` (choose a name to your liking). Do **not** touch the mpd.conf yet! +Then follow the instructions on the [Wiki on how to connect the bluetooth device](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Connecting_Bluetooth_device_to_Phoniebox). We diverge where we set up two audio sinks instead of one: Just **add** the `pcm.btspeaker` section described in the wiki to `/etc/asound.conf` (choose a name to your liking). Do **not** touch the mpd.conf yet! The new entry should end up looking like this: @@ -58,7 +58,7 @@ $ aplay -D btheadphone /usr/share/sounds/alsa/Front_Center.wav $ aplay -D hifiberry /usr/share/sounds/alsa/Front_Center.wav ~~~ -#### Step 2) Setting up mpd.conf +### Step 2) Setting up mpd.conf You need to set up two audio_output sections. **The order is important**: the first entry must relate to the soundcard setup, the second entry must relate to the bluetooth setup. Give meaningful names, as they will show up in the Web Interface. @@ -98,7 +98,7 @@ Output 2 (Gesas Headphones) is enabled You may switch with `$ mpc enable only 1` and `$ mpc enable only 2`. Play some music and use these commands to check you mpd configuration. You should be able to switch the audio output between the two devices. -#### Step 3) Run the installer +### Step 3) Run the installer This sets up the appropriate user rights and registers the component with global settings etc. @@ -107,9 +107,9 @@ $ cd components/bluetooth-sink-switch $ ./install-bt-sink-switch.sh ~~~ -#### Step 4) Fine-tuning +### Step 4) Fine-tuning -**Status LED** +#### Status LED An optional status LED will be turned on if the audio sink is set to bluetooth. If a toggle command is issued, but no bluetooth device is connected, the LED will blink three times. Looks very neat, if you have a button with integrated LED. Add these lines to your `RPi-Jukebox-RFID/settings/gpio_settings.ini`, to use GPIO 13 as LED signal. It is `led_pin` the BCM number of the GPIO pin (i.e. 'led_pin = 13' means GPIO13) and defaults to None. Create the file, if it does not exist. @@ -121,7 +121,7 @@ enabled: True led_pin: 13 ~~~ -**GPIO control** +#### GPIO control If you want to toggle from a GPIO button (e.g. on GPIO5), add these lines to your `RPi-Jukebox-RFID/settings/gpio_settings.ini`. Create it, if it does not exist. @@ -135,7 +135,7 @@ hold_time: 0.3 functionCall: functionCallBluetoothToggle ~~~ -**RFID Card** +#### RFID Card If you want to toggle by RFID card swipe, set the card id in `rfid_trigger_play.conf`, e.g.: @@ -144,7 +144,7 @@ If you want to toggle by RFID card swipe, set the card id in `rfid_trigger_play. CMDBLUETOOTHTOGGLE="1364237231134" ~~~ -**Volume attenuation** +#### Volume attenuation Speakers and Headphones can have very different maximum volume levels. This sometimes leads to very strong volume level changes when switching between speakers and headphones. Restricting the maximum volume with the Phoniebox-integrated max-volume setting does no yield the desired effect, as this is a single setting and does not differentiate between different audio sinks. diff --git a/components/controls/buttons-bluetooth-headphone/README.md b/components/controls/buttons-bluetooth-headphone/README.md index 8d9397df0..6cedd1207 100644 --- a/components/controls/buttons-bluetooth-headphone/README.md +++ b/components/controls/buttons-bluetooth-headphone/README.md @@ -5,7 +5,7 @@ This component provides support for controlling your Phoniebox through these but ### Installation -1. Make sure your bluetooth headset is connected to the Phoniebox. Follow the instructions in the [Wiki](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Bluetooth). +1. Make sure your bluetooth headset is connected to the Phoniebox. Follow the instructions in the [Wiki](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Connecting_Bluetooth_device_to_Phoniebox). 2. Execute `$ ./install-bt-buttons.sh. It will ask you to identify your headset and set up appropriate user rights, and registers the script as a service. It should work immediatly. In case of doubt, reboot. - If later changing the headset, re-run `$ ./register-device.py`. Reboot or restart the service with `sudo systemctl restart phoniebox-bt-buttons.service` diff --git a/components/controls/buttons_usb_encoder/README.md b/components/controls/buttons_usb_encoder/README.md index e66ef97e0..586850e8a 100644 --- a/components/controls/buttons_usb_encoder/README.md +++ b/components/controls/buttons_usb_encoder/README.md @@ -1,7 +1,5 @@ # Buttons USB Encoder -Taken from [issue 1156](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/1156). - Supports functionality of buttons which are connected via USB Encoder. The USB Encoder is the easy solution for anyone who doesn't want to solder, but also wants arcade buttons. @@ -9,11 +7,53 @@ Tested Devices: * [IGames Zero Verzögerung USB Encoder](https://www.amazon.de/gp/product/B01N0GZQZI) * [EG STARTS Nullverzögerung USB Encoder](https://www.amazon.de/gp/product/B075DFNK24) +* [Dragonrise inc. generic usb joystick](https://de.aliexpress.com/item/1005001700497245.html) -## Usage +## Installation 1. Plug in your USB Encoder. You don't need to install any drivers. After plugging in, the USB encoder acts like an input device. -2. Navigate to your RPi-Jukebox home directory and run the script `setup-buttons-usb-encoder.sh` to set up your USB Encoder (choose the device and map the buttons). +2. Navigate to your RPi-Jukebox home directory and run the script `setup-buttons-usb-encoder.sh` to set up your USB Encoder. Then choose the device and map the buttons. + + `cd ~/RPi-Jukebox-RFID` + + `./components/controls/buttons_usb_encoder/setup-buttons-usb-encoder.sh` + +If you make a mistake at the first install you can "remap" the buttons: + +* Stop the service: `sudo systemctl stop phoniebox-buttons-usb-encoder.service` +* Run the installation script again: `./components/controls/buttons_usb_encoder/setup-buttons-usb-encoder.sh` +* Restart the service: `sudo systemctl start phoniebox-buttons-usb-encoder.service` + +### Possible Button Mappings + +* 'BluetoothToggle': Turn bluetooth on or off +* 'PlayerNext': Play Next +* 'PlayerPause': Pause +* 'PlayerPauseForce': Force Pause? +* 'PlayerPrev': Previous track +* 'PlayerRandomCard': Activate (play?) random card? +* 'PlayerRandomFolder': Play random folder +* 'PlayerRandomTrack': Play random track +* 'PlayerSeekBack': Seek backwards on playing track (x seconds) +* 'PlayerSeekFarBack': Seek backwards on playing track (x seconds) +* 'PlayerSeekFarFwd': Seek forwards on playing track (x seconds) +* 'PlayerSeekFwd': Seek forwards on playing track (x seconds) +* 'PlayerStop': Stop playing +* 'RecordPlayLatest': Play latest recording +* 'RecordStart': Start recording +* 'RecordStop': Stop recording +* 'Shutdown': Shut down the Phoniebox +* 'ToggleWifi': Turn Wifi on or off +* 'Vol0': Volume mute? +* 'VolD': Volume down +* 'VolU': Volume up + +## Schematics ![USB Encoder schematics](buttons-usb-encoder.jpg) + +## Issues & Discussions + +* +* diff --git a/components/controls/buttons_usb_encoder/buttons_usb_encoder.py b/components/controls/buttons_usb_encoder/buttons_usb_encoder.py index e5b56acfb..33d13657c 100644 --- a/components/controls/buttons_usb_encoder/buttons_usb_encoder.py +++ b/components/controls/buttons_usb_encoder/buttons_usb_encoder.py @@ -2,7 +2,7 @@ import sys -sys.path.append(".") # This command should be before imports of components +sys.path.append(".") # This command should be before imports of components import logging from evdev import categorize, ecodes, KeyEvent diff --git a/components/controls/buttons_usb_encoder/map_buttons_usb_encoder.py b/components/controls/buttons_usb_encoder/map_buttons_usb_encoder.py index 40b094135..6cf0bcb28 100644 --- a/components/controls/buttons_usb_encoder/map_buttons_usb_encoder.py +++ b/components/controls/buttons_usb_encoder/map_buttons_usb_encoder.py @@ -2,7 +2,7 @@ import sys -sys.path.append(".") # This command should be before imports of components +sys.path.append(".") # This command should be before imports of components from evdev import categorize, ecodes, KeyEvent from io_buttons_usb_encoder import current_device, write_button_map diff --git a/components/displays/HD44780-i2c/README.md b/components/displays/HD44780-i2c/README.md index 17b6a719a..fce87d0c4 100755 --- a/components/displays/HD44780-i2c/README.md +++ b/components/displays/HD44780-i2c/README.md @@ -5,17 +5,17 @@ The following files allow using LCD displays based on HD44780 connected via i2c bus for this project. The following displays have been used for testing: -- 2x16 display -- 4x20 display (recommended as more information can be displayed) +* 2x16 display +* 4x20 display (recommended as more information can be displayed) Various informations such as artist, album, track_number, track_title, track_time and many more can be displayed see main script for more display options. The required files are: -- components/displays/HD44780-i2c/i2c_lcd.py -- components/displays/HD44780-i2c/i2c_lcd_driver.py -- components/displays/HD44780-i2c/i2c-lcd.service.default.sample -- components/displays/HD44780-i2c/README.md +* components/displays/HD44780-i2c/i2c_lcd.py +* components/displays/HD44780-i2c/i2c_lcd_driver.py +* components/displays/HD44780-i2c/i2c-lcd.service.default.sample +* components/displays/HD44780-i2c/README.md The first file is the main LCD script that makes use of I2C_LCD_driver.py. @@ -25,7 +25,7 @@ The third is used as sample service file that runs the i2c_lcd.py main script at The fourth file is this file which describes the features, usage and installation of the code. -### Installation +## Installation * You need to install additional python libraries. Run the following two command in the command line: diff --git a/components/displays/HD44780-i2c/i2c_lcd_driver.py b/components/displays/HD44780-i2c/i2c_lcd_driver.py index bbf5b5090..d9c244e79 100755 --- a/components/displays/HD44780-i2c/i2c_lcd_driver.py +++ b/components/displays/HD44780-i2c/i2c_lcd_driver.py @@ -25,6 +25,7 @@ import smbus from time import sleep + class i2c_device: def __init__(self, addr, port=I2CBUS): self.addr = addr @@ -100,12 +101,13 @@ def read_block_data(self, cmd): LCD_BACKLIGHT = 0x08 LCD_NOBACKLIGHT = 0x00 -En = 0b00000100 # Enable bit -Rw = 0b00000010 # Read/Write bit -Rs = 0b00000001 # Register select bit +En = 0b00000100 # Enable bit +Rw = 0b00000010 # Read/Write bit +Rs = 0b00000001 # Register select bit + class lcd: - #initializes objects and lcd + # initializes objects and lcd def __init__(self): self.lcd_device = i2c_device(ADDRESS) @@ -120,7 +122,6 @@ def __init__(self): self.lcd_write(LCD_ENTRYMODESET | LCD_ENTRYLEFT) sleep(0.2) - # clocks EN to latch command def lcd_strobe(self, data): self.lcd_device.write_cmd(data | En | LCD_BACKLIGHT) @@ -165,7 +166,7 @@ def lcd_clear(self): self.lcd_write(LCD_RETURNHOME) # define backlight on/off (lcd.backlight(1); off= lcd.backlight(0) - def backlight(self, state): # for state, 1 = on, 0 = off + def backlight(self, state): # for state, 1 = on, 0 = off if state == 1: self.lcd_device.write_cmd(LCD_BACKLIGHT) elif state == 0: @@ -173,8 +174,7 @@ def backlight(self, state): # for state, 1 = on, 0 = off # add custom characters (0 - 7) def lcd_load_custom_chars(self, fontdata): - self.lcd_write(0x40); + self.lcd_write(0x40) for char in fontdata: for line in char: self.lcd_write_char(line) - diff --git a/components/gpio_control/GPIODevices/led.py b/components/gpio_control/GPIODevices/led.py index aff6dbc45..01d2d34ef 100644 --- a/components/gpio_control/GPIODevices/led.py +++ b/components/gpio_control/GPIODevices/led.py @@ -41,4 +41,3 @@ def __init__(self, pin, name='StatusLED'): time.sleep(1) self.logger.info('phoniebox-startup-scripts service active') self.on() - diff --git a/components/gpio_control/GPIODevices/rotary_encoder.py b/components/gpio_control/GPIODevices/rotary_encoder.py index 1528b625f..d3455622f 100755 --- a/components/gpio_control/GPIODevices/rotary_encoder.py +++ b/components/gpio_control/GPIODevices/rotary_encoder.py @@ -1,10 +1,5 @@ #!/usr/bin/env python3 # rotary volume knob -# these files belong all together: -# RPi-Jukebox-RFID/scripts/rotary-encoder.py -# RPi-Jukebox-RFID/scripts/rotary_encoder.py -# RPi-Jukebox-RFID/misc/sampleconfigs/phoniebox-rotary-encoder.service.stretch-default.sample -# See wiki for more info: https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki import RPi.GPIO as GPIO from timeit import default_timer as timer diff --git a/components/gpio_control/GPIODevices/shutdown_button.py b/components/gpio_control/GPIODevices/shutdown_button.py index 30ba26b6f..3f9eec341 100644 --- a/components/gpio_control/GPIODevices/shutdown_button.py +++ b/components/gpio_control/GPIODevices/shutdown_button.py @@ -34,29 +34,30 @@ def set_led(self, status): logger.debug('cannot set LED to {}: no LED pin defined'.format(status)) def callbackFunctionHandler(self, *args): - logger.debug('ShutdownButton pressed, ensuring long press for {} seconds, checking each {}s'.format( - self.hold_time, self.iteration_time - )) - t_passed = 0 - led_state = True - while t_passed < self.hold_time: - self.set_led(led_state) - time.sleep(self.iteration_time) - t_passed += self.iteration_time - led_state = not led_state - if not self.is_pressed: - break - if t_passed >= self.hold_time: - # trippel off period to indicate command accepted - self.set_led(GPIO.HIGH) - time.sleep(.6) - # leave it on for the moment, it will be off when the system is down - self.when_pressed(*args) - else: - # switch off LED if pressing was cancelled early (during flashing) - self.set_led(GPIO.LOW) + if self.is_pressed: # Should not be necessary, but handler gets called on rising edge too + logger.debug('ShutdownButton pressed, ensuring long press for {} seconds, checking each {}s'.format( + self.hold_time, self.iteration_time + )) + t_passed = 0 + led_state = True + while t_passed < self.hold_time: + self.set_led(led_state) + time.sleep(self.iteration_time) + t_passed += self.iteration_time + led_state = not led_state + if not self.is_pressed: + break + if t_passed >= self.hold_time: + # trippel off period to indicate command accepted + self.set_led(GPIO.HIGH) + time.sleep(.6) + # leave it on for the moment, it will be off when the system is down + self.when_pressed(*args) + else: + # switch off LED if pressing was cancelled early (during flashing) + self.set_led(GPIO.LOW) def __repr__(self): return ''.format( - self.name, self.pin, self.hold_time, self.iteration_time, self.led_pin, print_edge_key(self.edge), self.bouncetime,self.antibouncehack, print_pull_up_down(self.pull_up_down) + self.name, self.pin, self.hold_time, self.iteration_time, self.led_pin, print_edge_key(self.edge), self.bouncetime, self.antibouncehack, print_pull_up_down(self.pull_up_down) ) diff --git a/components/gpio_control/GPIODevices/simple_button.py b/components/gpio_control/GPIODevices/simple_button.py index 69b6e3407..4b7149e7e 100644 --- a/components/gpio_control/GPIODevices/simple_button.py +++ b/components/gpio_control/GPIODevices/simple_button.py @@ -6,10 +6,11 @@ logger = logging.getLogger(__name__) -map_edge_parse = {'falling':GPIO.FALLING, 'rising':GPIO.RISING, 'both':GPIO.BOTH} -map_pull_parse = {'pull_up':GPIO.PUD_UP, 'pull_down':GPIO.PUD_DOWN, 'pull_off':GPIO.PUD_OFF} +map_edge_parse = {'falling': GPIO.FALLING, 'rising': GPIO.RISING, 'both': GPIO.BOTH} +map_pull_parse = {'pull_up': GPIO.PUD_UP, 'pull_down': GPIO.PUD_DOWN, 'pull_off': GPIO.PUD_OFF} map_edge_print = {GPIO.FALLING: 'falling', GPIO.RISING: 'rising', GPIO.BOTH: 'both'} -map_pull_print = {GPIO.PUD_UP:'pull_up', GPIO.PUD_DOWN: 'pull_down', GPIO.PUD_OFF: 'pull_off'} +map_pull_print = {GPIO.PUD_UP: 'pull_up', GPIO.PUD_DOWN: 'pull_down', GPIO.PUD_OFF: 'pull_off'} + def parse_edge_key(edge): if edge in [GPIO.FALLING, GPIO.RISING, GPIO.BOTH]: @@ -21,6 +22,7 @@ def parse_edge_key(edge): raise KeyError('Unknown Edge type {edge}'.format(edge=edge)) return result + def parse_pull_up_down(pull_up_down): if pull_up_down in [GPIO.PUD_UP, GPIO.PUD_DOWN, GPIO.PUD_OFF]: return pull_up_down @@ -31,6 +33,7 @@ def parse_pull_up_down(pull_up_down): raise KeyError('Unknown Pull Up/Down type {pull_up_down}'.format(pull_up_down=pull_up_down)) return result + def print_edge_key(edge): try: result = map_edge_print[edge] @@ -38,6 +41,7 @@ def print_edge_key(edge): result = edge return result + def print_pull_up_down(pull_up_down): try: result = map_pull_print[pull_up_down] @@ -45,6 +49,7 @@ def print_pull_up_down(pull_up_down): result = pull_up_down return result + # This function takes a holding time (fractional seconds), a channel, a GPIO state and an action reference (function). # It checks if the GPIO is in the state since the function was called. If the state # changes it return False. If the time is over the function returns True. @@ -93,7 +98,7 @@ def callbackFunctionHandler(self, *args): args = args[1:] logger.debug('args after: {}'.format(args)) - if self.antibouncehack: + if self.antibouncehack: time.sleep(0.1) inval = GPIO.input(self.pin) if inval != GPIO.LOW: @@ -132,32 +137,32 @@ def longPressHandler(self, *args): # instant action (except Postpone mode) if self.hold_mode != "Postpone": self.when_pressed(*args) - + # action(s) after hold_time if self.hold_mode == "Repeat": # Repeated call of main action (multiple times if button is held long enough) while checkGpioStaysInState(self.hold_time, self.pin, GPIO.LOW): self.when_pressed(*args) - + elif self.hold_mode == "Postpone": # Postponed call of main action (once) if checkGpioStaysInState(self.hold_time, self.pin, GPIO.LOW): self.when_pressed(*args) while checkGpioStaysInState(self.hold_time, self.pin, GPIO.LOW): pass - + elif self.hold_mode == "SecondFunc": # Call of secondary action (once) if checkGpioStaysInState(self.hold_time, self.pin, GPIO.LOW): self.when_held(*args) while checkGpioStaysInState(self.hold_time, self.pin, GPIO.LOW): pass - + elif self.hold_mode == "SecondFuncRepeat": # Repeated call of secondary action (multiple times if button is held long enough) while checkGpioStaysInState(self.hold_time, self.pin, GPIO.LOW): self.when_held(*args) - + def __del__(self): logger.debug('remove event detection') GPIO.remove_event_detect(self.pin) @@ -170,7 +175,7 @@ def is_pressed(self): def __repr__(self): return ''.format( - self.name, self.pin, print_edge_key(self.edge), self.hold_mode, self.hold_time, self.bouncetime,self.antibouncehack,print_pull_up_down(self.pull_up_down) + self.name, self.pin, print_edge_key(self.edge), self.hold_mode, self.hold_time, self.bouncetime, self.antibouncehack, print_pull_up_down(self.pull_up_down) ) diff --git a/components/gpio_control/GPIODevices/two_button_control.py b/components/gpio_control/GPIODevices/two_button_control.py index d4ceb0a11..e93584cd1 100644 --- a/components/gpio_control/GPIODevices/two_button_control.py +++ b/components/gpio_control/GPIODevices/two_button_control.py @@ -63,20 +63,20 @@ def __init__(self, hold_mode=None, hold_time=0.3, bouncetime=500, - antibouncehack=False, - edge='falling', + antibouncehack=False, + edge='falling', name='TwoButtonControl'): self.bcmPin1 = bcmPin1 self.bcmPin2 = bcmPin2 self.functionCallBtn1 = functionCallBtn1 self.functionCallBtn2 = functionCallBtn2 self.functionCallTwoBtns = functionCallTwoBtns - self.pull_up_down=pull_up_down - self.hold_mode=hold_mode - self.hold_time=hold_time - self.bouncetime=bouncetime - self.antibouncehack=antibouncehack - self.edge=edge + self.pull_up_down = pull_up_down + self.hold_mode = hold_mode + self.hold_time = hold_time + self.bouncetime = bouncetime + self.antibouncehack = antibouncehack + self.edge = edge self.btn1 = SimpleButton( pin=bcmPin1, name=name + 'Btn1', diff --git a/components/gpio_control/README.md b/components/gpio_control/README.md index 0c92ca6f5..229d120a8 100644 --- a/components/gpio_control/README.md +++ b/components/gpio_control/README.md @@ -38,11 +38,11 @@ Each section needs to be activated by setting `enabled: True`. Many example files are located in `~/RPi-Jukebox-RFID/components/gpio_control/example_configs/`. -# Extended documentation +## Extended documentation This section provides some extended documentation and guideline. Especially some exemplary configurations are introduced showing how these controls can be set up in the configuration file `~/RPi-Jukebox-RFID/settings/gpio_settings.ini`. -## Button +### Button At the most basic level, a button can be created using an `ini` entry like this: @@ -86,7 +86,7 @@ However, a button has more parameters than these. In the following comprehensive Note: If you prefer, you may also use `Type: SimpleButton` instead of `Type: Button` - this makes no difference. -## ShutdownButton +### ShutdownButton An extended ShutdownButton can be created using an `ini` entry like these: @@ -127,9 +127,9 @@ hold_time: 3.0 functionCall: functionCallShutdown ``` -## TwoButtonControl +### TwoButtonControl -A TwoButtonControl can be created using an `ini` entry like this: +A TwoButtonControl can be created using an `ini` entry like this: ```bash [PrevNextStop] @@ -163,9 +163,9 @@ In this example, the volume will be in-/decreased step-wise using intervals of 0 Furthermore, the following settings can be used as described for the [regular buttons](#doc_button): **pull_up_down**, **edge**, **bouncetime**, **antibouncehack** -## RotaryEncoder +### RotaryEncoder -A RotaryEncoder can be created using an `ini` entry like this: +A RotaryEncoder can be created using an `ini` entry like this: ```bash [VolumeControl] @@ -181,9 +181,9 @@ functionCall2: functionCallVolD Pin1 and FunctionCall1 correspond to rotary direction "up", while Pin2 and FunctionCall2 correspond to "down". Note that the old configuration entries PinUp/PinDown and functionCallUp/functionCallDown are deprecated and might stop working in future. -## StatusLED +### StatusLED -A StatusLED can be created using an `ini` entry like this: +A StatusLED can be created using an `ini` entry like this: ```bash [StatusLED] @@ -196,11 +196,11 @@ Pin: 14 Note: If you prefer, you may also use `Type: MPDStatusLED` instead of `Type: StatusLED` - this makes no difference. -## Further examples +### Further examples By tapping the potential of the features presented above, you can create buttons like this: -### Play random tracks or folders +#### Play random tracks or folders If you have buttons to navigate to the next/previous track it might be a good idea to define that holding these buttons for a certain time (e.g. 2 seconds) will activate a random (surpise!) track or even folder/card. This might look like this @@ -226,7 +226,7 @@ functionCall: functionCallPlayerPrev functionCall2: functionCallPlayerRandomFolder ``` -### Short and long jumps +#### Short and long jumps If you are using two buttons to jump backwards or forwards within the current track, you can use the repeated hold action to allow larger jumps: @@ -245,7 +245,7 @@ functionCall2: functionCallPlayerSeekFarFwd In this example, a short press initiates a short jump forward by 10 seconds (functionCallPlayerSeekFwd) while holding the button will cause further, longer jumps. In this case it will cause a jump of 1 minute forward (functionCallPlayerSeekFarFwd) every 5 seconds. If you wish, you can adjust these values in `components/gpio_control/function_calls.py`. For jumping backwards, this can be done equivalently (see [function list below](#doc_funcs)). -## Functions +### Functions The available functions are defined/implemented in `components/gpio_control/function_calls.py`: @@ -270,7 +270,7 @@ The available functions are defined/implemented in `components/gpio_control/func * **functionCallPlayerRandomCard**: Activate a random card * **functionCallPlayerRandomFolder**: Play a random folder -## Troubleshooting +### Troubleshooting If you encounter bouncing effects with your buttons like unrequested/double actions after releasing a button, you can try to set `antibouncehack` to True: diff --git a/components/gpio_control/config_compatibility.py b/components/gpio_control/config_compatibility.py index 62922c299..9c2e92f5d 100644 --- a/components/gpio_control/config_compatibility.py +++ b/components/gpio_control/config_compatibility.py @@ -3,6 +3,7 @@ import os from shutil import copyfile + def Ini_CheckAndUpgrade(config): has_changed = False for section in config.sections(): @@ -37,8 +38,8 @@ def Ini_CheckAndUpgrade(config): has_changed = True if not config.has_option(section, 'hold_time'): config.set(section, 'hold_time', str(v)) - #PinUp: --> Pin1 - #PinDown: --> Pin2 + # PinUp: --> Pin1 + # PinDown: --> Pin2 if config.has_option(section, 'PinUp'): v = config.getint(section, 'PinUp') config.remove_option(section, 'PinUp') @@ -67,17 +68,17 @@ def Ini_CheckAndUpgrade(config): config.set(section, 'functionCall2', v) return has_changed - - + + def ConfigCompatibilityChecks(config, config_path): # Check for deprecated settings in gpio_settings.ini if not Ini_CheckAndUpgrade(config): return - + # If we reach here, gpio_settings.ini needed some patching... # Try creating a backup of the previous ini file - backup_path = config_path+'.bak' + backup_path = config_path + '.bak' if os.path.isfile(backup_path): return copyfile(config_path, backup_path) diff --git a/components/gpio_control/gpio_control.py b/components/gpio_control/gpio_control.py index 44ad68df1..113850431 100755 --- a/components/gpio_control/gpio_control.py +++ b/components/gpio_control/gpio_control.py @@ -118,7 +118,7 @@ def gpio_loop(self): config = configparser.ConfigParser(inline_comment_prefixes=";", delimiters=(':', '=')) config_path = os.path.expanduser('/home/pi/RPi-Jukebox-RFID/settings/gpio_settings.ini') config.read(config_path) - + ConfigCompatibilityChecks(config, config_path) phoniebox_function_calls = function_calls.phoniebox_function_calls() diff --git a/components/gpio_control/test/gpio_settings_test.ini b/components/gpio_control/test/gpio_settings_test.ini index a0e318244..d1bb8ed93 100644 --- a/components/gpio_control/test/gpio_settings_test.ini +++ b/components/gpio_control/test/gpio_settings_test.ini @@ -13,8 +13,8 @@ PinUp: 16 PinDown: 19 timeBase: 0.1 ; timeBase only for rotary encoder -functionCallDown: functionCallVolD -functionCallUp: functionCallVolU +functionCall1: functionCallVolU +functionCall2: functionCallVolD functionCallTwoButtons: functionCallVol0 ; functionCallTwoButtons only for TwoButtonControl ; functionCallButton: functionCallPlayerPause ; only for RotaryEncoderClickable diff --git a/components/gpio_control/test/test_gpio_control.py b/components/gpio_control/test/test_gpio_control.py index aca6e8b3a..5d5a1c107 100644 --- a/components/gpio_control/test/test_gpio_control.py +++ b/components/gpio_control/test/test_gpio_control.py @@ -2,7 +2,8 @@ import logging from mock import patch, MagicMock -from gpio_control import gpio_control +with patch('os.system', return_value=0): + from gpio_control import gpio_control import function_calls # def test_functionCallTwoButtonsOnlyBtn2Pressed(btn1Mock, btn2Mock, functionCall1Mock, functionCall2Mock, @@ -29,7 +30,7 @@ def testMain(): config = configparser.ConfigParser() - config.read('./gpio_settings_test.ini') + config.read('./test/gpio_settings_test.ini') phoniebox_function_calls = function_calls.phoniebox_function_calls() gpio_controler = gpio_control(phoniebox_function_calls) diff --git a/components/rfid-reader/RC522/requirements.txt b/components/rfid-reader/RC522/requirements.txt index 6643d6123..312014b2c 100644 --- a/components/rfid-reader/RC522/requirements.txt +++ b/components/rfid-reader/RC522/requirements.txt @@ -1,5 +1,4 @@ # RC522 related requirements # You need to install these with `sudo python3 -m pip install --upgrade --force-reinstall -q -r requirements.txt` -# pi-rc522 use latest version from Github -git+https://github.com/ondryaso/pi-rc522.git#egg=pi-rc522 +pi-rc522==2.3.0 diff --git a/components/smart-home-automation/MQTT-protocol/README.md b/components/smart-home-automation/MQTT-protocol/README.md index da00394b7..69267656b 100644 --- a/components/smart-home-automation/MQTT-protocol/README.md +++ b/components/smart-home-automation/MQTT-protocol/README.md @@ -153,6 +153,8 @@ First step: copy files to destination locations: # First copy the daemon script and service config file to the correct directory: sudo cp /home/pi/RPi-Jukebox-RFID/components/smart-home-automation/MQTT-protocol/daemon_mqtt_client.py /home/pi/RPi-Jukebox-RFID/scripts/ sudo cp /home/pi/RPi-Jukebox-RFID/components/smart-home-automation/MQTT-protocol/phoniebox-mqtt-client.service.stretch-default.sample /etc/systemd/system/phoniebox-mqtt-client.service +# make sure the file exists +touch /home/pi/RPi-Jukebox-RFID/settings/Latest_RFID ~~~ Now edit the `SETTINGS` section in `/home/pi/RPi-Jukebox-RFID/scripts/daemon_mqtt_client.py` to match your environment (MQTT connection details etc.). Now continue and activate the service. diff --git a/components/smart-home-automation/MQTT-protocol/daemon_mqtt_client.py b/components/smart-home-automation/MQTT-protocol/daemon_mqtt_client.py index b99b89eab..6ffe2e1ad 100644 --- a/components/smart-home-automation/MQTT-protocol/daemon_mqtt_client.py +++ b/components/smart-home-automation/MQTT-protocol/daemon_mqtt_client.py @@ -452,6 +452,7 @@ def regex(needle, hay, exception="-"): else: return exception + def getDuration(status): """ Find the duration of the track in the output from mpd status""" @@ -463,9 +464,10 @@ def getDuration(status): # this attribute value is split into two parts by ":" # first is the elapsed time and the second part is the duration duration = regex("\ntime: .*:(.*)\n", status, "0") - + return int(float(duration)) + REPEAT_MODE_OFF = "off" REPEAT_MODE_SINGLE = "single" REPEAT_MODE_PLAYLIST = "playlist" diff --git a/components/synchronisation/sync-shared/README.md b/components/synchronisation/sync-shared/README.md new file mode 100644 index 000000000..5bf9818aa --- /dev/null +++ b/components/synchronisation/sync-shared/README.md @@ -0,0 +1,60 @@ +# Synchronize shared files from a server + +This component activates a synchronisation from a server to the Phoniebox for the shared folders 'shortcuts' and 'audiofolders'. +It allows to manage the shortcuts and audiofiles of one to many Phonieboxes in a central place (e.g. NAS, one main Phoniebox, ...) in the network, but keeps the possibility to play audio offline once the data where synced. + +The synchronisation can be initiated as a "full-sync" command and optionally on every RFID scan for the particular CardID (and corresponding audiofolder). +For the "full-sync" bind a CardId to the command "SYNCSHAREDFULL". +For the "RFID scan sync" feature, activate the option in the configuration. There is also a command to toggle the activation of the "RFID scan sync" feature via CardId (bind to command "SYNCSHAREDONRFIDSCANTOGGLE"). + +## Synchronisation + +The synchronisation will be FROM a server TO the Phoniebox, overriding existing files. So configuration of audiofiles / -folders made locally will be lost after sync. +If you want to make the initial setup e.g. via WebUi copy the files and use it as a base for the server. +The "folder.conf" files will be synced if present on the server, but not delete if not (they are automatically generated on playback). + +To access the files on the server two modes are supported: SSH or MOUNT. +Please make sure you have the correct access rights for 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 shortcut and audiofolder is found and the changes will be transfered. +The playback will be delayed for the time the data are transfered (see "SYNCSHAREDFULL" to use a full-sync if a lot of new files have been added). +If the server is not reachable the check will be aborted after the timeout. So an unreachable server will cause a delay (see command "SYNCSHAREDONRFIDSCANTOGGLE" to toggle activation state). +Deleted shortcuts / audiofolders (not the contained items) will not be purged locally if deleted on remote. This is also true for changed shortcuts (the old audiofolder / -files will remain). To also delete not existing items us a "full-sync". + +## Installation + +Run the 'install-sync-shared.sh' script. This will install all required packages and rights. +Please configure all settings according to your setup. + +## Configuration + +If your configuration has changed, run the script 'change_configuration.sh' to update the settings. This lets you also deactivate this feature. +You may also change the settings in the according files directly. + +### Settings + +**{INSTALLATION_ROOT}/settings/sync-shared-enabled** + +Holds the activation state of this feature. Values are "TRUE" or "FALSE" + +**{INSTALLATION_ROOT}/settings/sync-shared.conf** + +SYNCSHAREDMODE: The mode to access the server files. SSH or MOUNT + +SYNCSHAREDREMOTESSHUSER: The username if SSH mode is used. + +SYNCSHAREDREMOTESERVER: The IP or hostname of the server (used to check connectivity and SSH mode). e.g. "192.168.0.2" or "myhomeserver.local" + +SYNCSHAREDREMOTEPORT: The port of the server (used to check connectivity and SSH mode). e.g. "80" or "22" + +SYNCSHAREDREMOTETIMOUT: The timeout to reach the server (in seconds) (used to check connectivity). e.g. 1 + +SYNCSHAREDREMOTEPATH: The 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" + +SYNCSHAREDONRFIDSCAN: Holds the activation state of the optional feature "RFID scan sync". Values are "TRUE" or "FALSE" + +## Special Thanks + +Inspired by [splitti - phoniebox_rsync](https://github.com/splitti/phoniebox_rsync) diff --git a/components/synchronisation/sync-shared/change-configuration.sh b/components/synchronisation/sync-shared/change-configuration.sh new file mode 100755 index 000000000..078c531dd --- /dev/null +++ b/components/synchronisation/sync-shared/change-configuration.sh @@ -0,0 +1,139 @@ +#!/bin/bash + +PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +PROJROOTPATH="${PATHDATA}/../../.." +STATEFILE="${PROJROOTPATH}/settings/sync-shared-enabled" +CONFFILE="${PROJROOTPATH}/settings/sync-shared.conf" +SKIP_INITIAL_CHECK="$1" + + +############################################################# +# Functions + +set_activation() { + local SETTINGVALUE="$1" + + local SETTINGSTATE="activated" + if [ "$SETTINGVALUE" != "TRUE" ]; then + SETTINGSTATE="deactivated" + fi + + # Let global controls know this feature is enabled + echo -e "\nLet global controls know this feature is ${SETTINGSTATE}. (sync-shared-enabled -> ${SETTINGVALUE})" + + echo "$SETTINGVALUE" > "$STATEFILE" + sudo chgrp www-data "$STATEFILE" + sudo chmod 775 "$STATEFILE" +} + +init_settings() { + # Init config from sample if not present + if [ ! -f "$CONFFILE" ]; then + cp "${PATHDATA}/settings/sync-shared.conf.sample" "$CONFFILE" + # change the read/write so that later this might also be editable through the web app + sudo chgrp www-data "$CONFFILE" + sudo chmod 775 "$CONFFILE" + fi + . "$CONFFILE" +} + +set_setting() { + local SETTINGNAME="$1" + local SETTINGVALUE="$2" + + # check if value is set and not equal to the current settings value + if [ ! -z "$SETTINGVALUE" -a "${!SETTINGNAME}" != "$SETTINGVALUE" ]; then + sed -i "s|^${SETTINGNAME}=.*|${SETTINGNAME}=\"${SETTINGVALUE}\"|g" "$CONFFILE" + echo "New value: \"${SETTINGVALUE}\"" + fi +} + +read_setting() { + local SETTINGNAME="$1" + local TEXT="$2" + + local READ_PROMPT=$'\n'"${TEXT} Leave blank for no change." + READ_PROMPT="${READ_PROMPT}"$'\n'"Current value = \"${SETTINGNAME}\""$'\n' + + read -rp "$READ_PROMPT" response +} + +read_all_settings() { + + read_setting "$SYNCSHAREDMODE" "Choose synchronisation mode to access the server (m[ount]/s[sh])." + case "$response" in + [mM][oO][uU][nN][tT]|[mM][nN][tT]|[mM]) + response="MOUNT" + ;; + [sS][sS][hH]|[sS]) + response="SSH" + ;; + *) + # no change + ;; + esac + set_setting "SYNCSHAREDMODE" "$response" + + if [ "$response" == "SSH" ]; then + read_setting "$SYNCSHAREDREMOTESSHUSER" "Please enter SSH user." + set_setting "SYNCSHAREDREMOTESSHUSER" "$response" + fi + + read_setting "$SYNCSHAREDREMOTESERVER" "Please enter your servers adresse (IP/Hostname)." + set_setting "SYNCSHAREDREMOTESERVER" "$response" + + read_setting "$SYNCSHAREDREMOTEPORT" "Please enter your servers port." + set_setting "SYNCSHAREDREMOTEPORT" "$response" + + read_setting "$SYNCSHAREDREMOTETIMOUT" "Please enter the timeout to try to reach the server (in seconds)." + set_setting "SYNCSHAREDREMOTETIMOUT" "$response" + + read_setting "$SYNCSHAREDREMOTEPATH" "Please enter the path to the shared files to sync (without trailing slash)." + # Make sure paths dont have a trailing slash ({VAR%/}) + set_setting "SYNCSHAREDREMOTEPATH" "${response%/}" + + read_setting "$SYNCSHAREDONRFIDSCAN" "Do you want to activate the syncronisation on RFID scan (y[es]/n[o])." + case "$response" in + [yY][eE][sS]|[yY]) + response="TRUE" + ;; + [nN][oO]|[nN]) + response="FALSE" + ;; + *) + ;; + esac + set_setting "SYNCSHAREDONRFIDSCAN" "$response" +} + +############################################################# + +# If intial check is skipped, asume the component shall be activated +if [ -z "$SKIP_INITIAL_CHECK" ]; then + read -rp "Do you want to activate the sync-shared component? [Y/n] " response +else + response="yes" +fi + +case "$response" in + [nN][oO]|[nN]) + set_activation "FALSE" + ;; + *) + set_activation "TRUE" + + # Ensure start was intended + read -rp "Do you want to change the configuration? [Y/n] " response + case "$response" in + [nN][oO]|[nN]) + exit + ;; + *) + ;; + esac + init_settings + read_all_settings + ;; +esac + +echo -e "\nConfiguration finished" diff --git a/components/synchronisation/sync-shared/install-sync-shared.sh b/components/synchronisation/sync-shared/install-sync-shared.sh new file mode 100755 index 000000000..aa2f96e05 --- /dev/null +++ b/components/synchronisation/sync-shared/install-sync-shared.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Ensure start was intended +read -rp "Start installation? [Y/n] " response +case "$response" in + [nN][oO]|[nN]) + echo "Installation aborted..." + exit + ;; + *) + ;; +esac + +PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +PROJROOTPATH="${PATHDATA}/../../.." + +# Ensure script is executable for everyone +sudo chmod ugo+rx "${PATHDATA}/sync-shared.sh" + +# Make sure required packages are installed +echo -e "\nChecking rsync package" +sudo apt install rsync -y +echo -e "\nChecking ssh package" +sudo apt install openssh-client -y + +"${PATHDATA}"/change-configuration.sh "SkipInitialCheck" + +echo -e "\n\nFINAL NOTE:\nPlease check README.md for further configuration" diff --git a/components/synchronisation/sync-shared/settings/sync-shared.conf.sample b/components/synchronisation/sync-shared/settings/sync-shared.conf.sample new file mode 100755 index 000000000..f77ad8289 --- /dev/null +++ b/components/synchronisation/sync-shared/settings/sync-shared.conf.sample @@ -0,0 +1,14 @@ +# The mode to access the server files. SSH or MOUNT +SYNCSHAREDMODE="MOUNT" +# The username if SSH mode is used +SYNCSHAREDREMOTESSHUSER="" +# The IP or hostname of the server (used to check connectivity and SSH mode) +SYNCSHAREDREMOTESERVER="" +# The port of the server (used to check connectivity and SSH mode) +SYNCSHAREDREMOTEPORT="" +# The timeout to reach the server (in seconds) (used to check connectivity) +SYNCSHAREDREMOTETIMOUT="1" +# The path to the shared files to sync (without trailing slash) (remote path for SSH mode or local path for MOUNT mode) +SYNCSHAREDREMOTEPATH="" +# Holds the activation state of the optional feature "RFID scan sync" +SYNCSHAREDONRFIDSCAN="FALSE" diff --git a/components/synchronisation/sync-shared/sync-shared.sh b/components/synchronisation/sync-shared/sync-shared.sh new file mode 100755 index 000000000..dca8f07bf --- /dev/null +++ b/components/synchronisation/sync-shared/sync-shared.sh @@ -0,0 +1,324 @@ +#!/bin/bash + +# This script synchronises shortcuts and/or audiofolders from a server to the local storage. + +# VALID COMMANDS: +# shortcuts (with -i) +# audiofolders (with -d) +# full +# changeOnRfidScan(with -v=on | off | toogle) + +# USAGE EXAMPLES: +# +# sync shortcuts: +# ./sync_shared.sh -c=shortcuts -i=xxx +# +# sync audiofolders: +# ./sync_shared.sh -c=audiofolders -d=xxx +# +# sync full: +# ./sync_shared.sh -c=full +# +# toggle sync OnRfidScan: +# ./sync_shared.sh -c=changeOnRfidScan -v=toggle + +# Set the date and time of now +NOW=`date +%Y-%m-%d.%H:%M:%S` + +# The absolute path to the folder which contains all the scripts. +# Unless you are working with symlinks, leave the following line untouched. +PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +PROJROOTPATH="${PATHDATA}/../../.." + +############################################################# +# $DEBUG TRUE|FALSE +# Read debug logging configuration file +. "${PROJROOTPATH}"/settings/debugLogging.conf + +if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "########### SCRIPT sync_shared.sh (${NOW}) ##" >> "${PROJROOTPATH}"/logs/debug.log; fi + +####################### +# Activation status of component sync-shared +SYNCSHAREDENABLED="FALSE" +if [ -f "${PROJROOTPATH}/settings/sync-shared-enabled" ]; then + SYNCSHAREDENABLED=`cat "${PROJROOTPATH}/settings/sync-shared-enabled"` +fi + + +if [ "$SYNCSHAREDENABLED" != "TRUE" ]; then + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: disabled" >> "${PROJROOTPATH}"/logs/debug.log; fi + +else + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: enabled" >> "${PROJROOTPATH}"/logs/debug.log; fi + + ############################################################# + # Read global configuration file + if [ ! -f "${PROJROOTPATH}/settings/global.conf" ]; then + echo "Global settingsfile does not exist. Please call the script from a defined entrypoint" + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: Global settingsfile does not exist. Please call the script from a defined entrypoint" >> "${PROJROOTPATH}"/logs/debug.log; fi + exit + fi + . "${PROJROOTPATH}"/settings/global.conf + + ############################################################# + # Read configuration file + CONFFILE="${PROJROOTPATH}/settings/sync-shared.conf" + if [ ! -f "$CONFFILE" ]; then + echo "Settingsfile does not exist. Please read ${PATHDATA}/README.md to set configuration" + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: Settingsfile does not exist. Please read ${PATHDATA}/README.md to set configuration" >> "${PROJROOTPATH}"/logs/debug.log; fi + exit + fi + . "$CONFFILE" + + ############################################################# + # Get args from command line (see Usage above) + # Read the args passed on by the command line + # see following file for details: + . "${PROJROOTPATH}"/scripts/inc.readArgsFromCommandLine.sh + + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "VAR COMMAND: ${COMMAND}" >> "${PROJROOTPATH}"/logs/debug.log; fi + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "VAR CARDID: ${CARDID}" >> "${PROJROOTPATH}"/logs/debug.log; fi + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "VAR FOLDER: ${FOLDER}" >> "${PROJROOTPATH}"/logs/debug.log; fi + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "VAR VALUE: ${VALUE}" >> "${PROJROOTPATH}"/logs/debug.log; fi + + ############################################################# + # Set local vars after confs are read + # Make sure paths dont have a trailing slash ({VAR%/}) + SYNCSHAREDREMOTEPATH="${SYNCSHAREDREMOTEPATH%/}" + SYNCSHORTCUTSPATH="${SYNCSHAREDREMOTEPATH}/shortcuts" + SYNCAUDIOFOLDERSPATH="${SYNCSHAREDREMOTEPATH}/audiofolders" + + LOCAL_SHORTCUTSPATH="${PROJROOTPATH}/shared/shortcuts" + LOCAL_AUDIOFOLDERSPATH="${AUDIOFOLDERSPATH%/}" + + ############################################################# + # Functions + + # Check if the sync mode is SSH + is_mode_ssh() { + [ "$SYNCSHAREDMODE" == "SSH" ] + } + + # Executes the command for the current mode + exec_for_mode() { + if is_mode_ssh ; then + # Quote every param to deal with whitespaces in paths + local quotedparams + for var in "$@" + do + quotedparams="${quotedparams} '${var}'" + done + + # Execute remote via SSH + ssh "$SYNCSHAREDREMOTESSHUSER"@"$SYNCSHAREDREMOTESERVER" -p "$SYNCSHAREDREMOTEPORT" "$quotedparams" + else + # Execute local on mount + "$@" + fi + } + + # Check if server is reachable on port + is_server_reachable() { + return `nc -z "$SYNCSHAREDREMOTESERVER" -w "$SYNCSHAREDREMOTETIMOUT" "$SYNCSHAREDREMOTEPORT"` + } + + # Check if first parameter ends with the character second parameter + endswith() { + case "$1" in *"$2") true;; *) false;; esac; + } + + # Sync all files from source to destination + # Some special options are needed as the 'folder.conf' file will be generated on playback. + # Explanation for rsync options: + # "--itemize-changes" print a summary of copied files. Used for determination if files where changed (empty if no syncing performed). Useful for debug.log + # "--safe-links" ignore symlinks that point outside the tree + # "--times" preserve modification times from source. Recommended option to efficiently identify unchanged files + # "--omit-dir-times" ignore modification time on dirs (see --times). Needed to ignore the creation of 'folder.conf' which alters the modification time of dirs + # "--delete" delete files that no longer exist in source + # "--prune-empty-dirs" delete empty dirs (incl. subdirs) + # "--filter='-rp folder.conf' exclude (option '-') 'folder.conf' file from deletion on receiving side (option 'r'). Delete anyway if folder will be deleted (option 'p' (perishable)). + # "--exclude='placeholder' exclude 'placeholder' file from syncing, especially deletion + # "--exclude='.*/' exclude special 'hidden' folders from syncing + # "--exclude='@*/' exclude special folders from syncing + sync_from_server() { + local src_path="$1" + local dst_path="$2" + local update_db="$3" + + if is_mode_ssh ; then + # Quote source path to deal with whitespaces in paths + src_path="'${src_path}'" + + local ssh_port=(-e "ssh -p ${SYNCSHAREDREMOTEPORT}") + local ssh_conn="${SYNCSHAREDREMOTESSHUSER}@${SYNCSHAREDREMOTESERVER}:" + fi + + if endswith "$dst_path" "/" ; then + mkdir -p "$dst_path" + fi + rsync_changes=$(rsync --compress --recursive --itemize-changes --safe-links --times --omit-dir-times --delete --prune-empty-dirs --filter='-rp folder.conf' --exclude='placeholder' --exclude='.*/' --exclude='@*/' "${ssh_port[@]}" "${ssh_conn}""${src_path}" "${dst_path}") + + if [ $? -eq 0 -a -n "$rsync_changes" ]; then + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo -e "Sync: executed rsync \n${rsync_changes}" >> "${PROJROOTPATH}"/logs/debug.log; fi + + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: files copied. change access of files" >> "${PROJROOTPATH}"/logs/debug.log; fi + change_access "$dst_path" "www-data" "775" + + if [ ! -z "$update_db" ]; then + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: update database" >> "${PROJROOTPATH}"/logs/debug.log; fi + # if spotify edition is installed, update via mopidy as mpc update doesnt work + if [ "$EDITION" == "plusSpotify" ]; then + # don't stop / start service (like in payout_controls scan) as all mpd calls after will fail + # (or an artifical sleep time would be needed to make sure mpd is started) + sudo mopidyctl local scan > /dev/null 2>&1 + else + mpc update --wait > /dev/null 2>&1 + fi + fi + + else + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: nothing changed" >> "${PROJROOTPATH}"/logs/debug.log; fi + fi + } + + # Sync shortcut for CARDID + handle_shortcuts() { + if [ "$SYNCSHAREDONRFIDSCAN" == "TRUE" ]; then + if is_server_reachable ; then + + if exec_for_mode [ ! -d "$SYNCSHORTCUTSPATH" ] ; then + exec_for_mode mkdir "$SYNCSHORTCUTSPATH" + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: Folder ${SYNCSHORTCUTSPATH} does not exist. created" >> "${PROJROOTPATH}"/logs/debug.log; fi + + elif exec_for_mode [ -f "${SYNCSHORTCUTSPATH}/${CARDID}" ] ; then + sync_from_server "${SYNCSHORTCUTSPATH}/${CARDID}" "${LOCAL_SHORTCUTSPATH}/${CARDID}" + + else + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: Shortcut for $CARDID not found in REMOTE $SYNCSHORTCUTSPATH" >> "${PROJROOTPATH}"/logs/debug.log; fi + fi + + else + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: Server is NOT reachable" >> "${PROJROOTPATH}"/logs/debug.log; fi + fi + + else + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: Sync on RFID scan deactivated" >> "${PROJROOTPATH}"/logs/debug.log; fi + fi + } + + # Sync audiofolder FOLDER + handle_audiofolders() { + if [ "$SYNCSHAREDONRFIDSCAN" == "TRUE" ]; then + if is_server_reachable ; then + + if exec_for_mode [ ! -d "$SYNCAUDIOFOLDERSPATH" ] ; then + exec_for_mode mkdir "$SYNCAUDIOFOLDERSPATH" + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: Folder ${SYNCAUDIOFOLDERSPATH} does not exist. created" >> "${PROJROOTPATH}"/logs/debug.log; fi + + elif exec_for_mode [ -d "${SYNCAUDIOFOLDERSPATH}/${FOLDER}" ] ; then + sync_from_server "${SYNCAUDIOFOLDERSPATH}/${FOLDER}/" "${LOCAL_AUDIOFOLDERSPATH}/${FOLDER}/" "UpdateDB" + + else + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: Folder $FOLDER not found in REMOTE $SYNCAUDIOFOLDERSPATH" >> "${PROJROOTPATH}"/logs/debug.log; fi + fi + + else + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: Server is NOT reachable" >> "${PROJROOTPATH}"/logs/debug.log; fi + fi + + else + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: Sync on RFID scan deactivated" >> "${PROJROOTPATH}"/logs/debug.log; fi + fi + } + + # Sync full (shortcuts and audiofolders) + handle_full() { + if is_server_reachable ; then + + if exec_for_mode [ ! -d "$SYNCSHORTCUTSPATH" ] ; then + exec_for_mode mkdir "$SYNCSHORTCUTSPATH" + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: Folder ${SYNCSHORTCUTSPATH} does not exist. created" >> "${PROJROOTPATH}"/logs/debug.log; fi + else + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: Folder ${SYNCSHORTCUTSPATH}" >> "${PROJROOTPATH}"/logs/debug.log; fi + sync_from_server "${SYNCSHORTCUTSPATH}/" "${LOCAL_SHORTCUTSPATH}/" + + fi + + if exec_for_mode [ ! -d "$SYNCAUDIOFOLDERSPATH" ] ; then + exec_for_mode mkdir "$SYNCAUDIOFOLDERSPATH" + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: Folder ${SYNCAUDIOFOLDERSPATH} does not exist. created" >> "${PROJROOTPATH}"/logs/debug.log; fi + else + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: Folder ${SYNCAUDIOFOLDERSPATH}" >> "${PROJROOTPATH}"/logs/debug.log; fi + sync_from_server "${SYNCAUDIOFOLDERSPATH}/" "${LOCAL_AUDIOFOLDERSPATH}/" "UpdateDB" + + fi + + else + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: Server is NOT reachable" >> "${PROJROOTPATH}"/logs/debug.log; fi + fi + } + + # Change setting for Sync on RFID scan + handle_changeOnRfidScan() { + case "$VALUE" in + on) + SYNCSHAREDONRFIDSCAN_NEW="TRUE" + ;; + off) + SYNCSHAREDONRFIDSCAN_NEW="FALSE" + ;; + toggle) + if [ "$SYNCSHAREDONRFIDSCAN" == "TRUE" ]; then + SYNCSHAREDONRFIDSCAN_NEW="FALSE" + else + SYNCSHAREDONRFIDSCAN_NEW="TRUE" + fi + ;; + *) + echo "Unknown VALUE ${VALUE} for COMMAND ${COMMAND}" + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Unknown VALUE ${VALUE} for COMMAND ${COMMAND}" >> "${PROJROOTPATH}"/logs/debug.log; fi + ;; + esac + + if [ ! -z "${SYNCSHAREDONRFIDSCAN_NEW}" ]; then + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Sync: Set SYNCSHAREDONRFIDSCAN to ${SYNCSHAREDONRFIDSCAN_NEW}" >> "${PROJROOTPATH}"/logs/debug.log; fi + sed -i "s|^SYNCSHAREDONRFIDSCAN=.*|SYNCSHAREDONRFIDSCAN=\"${SYNCSHAREDONRFIDSCAN_NEW}\"|g" "$CONFFILE" + fi + } + + # Change access of file or dir + # only changes group as the user should be correctly taken from caller context (logged in user or service) + change_access() { + local file_or_dir="$1" + local group="$2" + local mod="$3" + + sudo chgrp -R "$group" "$file_or_dir" + sudo chmod -R "$mod" "$file_or_dir" + } + + ############################################################# + + ############################################################# + # Main switch + case "$COMMAND" in + shortcuts) + handle_shortcuts + ;; + audiofolders) + handle_audiofolders + ;; + full) + handle_full + ;; + changeOnRfidScan) + handle_changeOnRfidScan + ;; + *) + echo "Unknown COMMAND {$COMMAND}" + if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "Unknown COMMAND ${COMMAND} CARDID ${CARDID} FOLDER ${FOLDER} VALUE ${VALUE}" >> "${PROJROOTPATH}"/logs/debug.log; fi + ;; + esac + +fi +if [ "${DEBUG_sync_shared_sh}" == "TRUE" ]; then echo "########### SCRIPT sync_shared.sh ##" >> "${PROJROOTPATH}"/logs/debug.log; fi diff --git a/composer.json b/composer.json index 1fe5789bf..b0661a42f 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,21 @@ { + "name": "miczflor/rpi-jukebox-rfid", + "description": "A Raspberry Pi jukebox, playing local music, podcasts, web radio and streams triggered by RFID cards, web app or home automation. All plug and play via USB. GPIO scripts available.", + "type": "project", "require-dev": { "phpunit/phpunit": "^9", - "php-mock/php-mock-phpunit": "^2.5" + "php-mock/php-mock-phpunit": "^2.6", + "mpyw/phpunit-patch-serializable-comparison": "^0.0.2" + }, + "license": "MIT", + "authors": [ + { + "name": "MiczFlor" + } + ], + "minimum-stability": "stable", + "scripts": { + "test": "vendor/bin/phpunit ./tests/htdocs --exclude real-env", + "test-all": "vendor/bin/phpunit ./tests/htdocs" } } diff --git a/composer.lock b/composer.lock index fbcfe6e49..41ff99f13 100644 --- a/composer.lock +++ b/composer.lock @@ -4,35 +4,35 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6d659550344086ef6e414765a7a1a227", + "content-hash": "890e6b393f255fb50b55d3866c724feb", "packages": [], "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.4.1", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", - "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^9", + "doctrine/coding-standard": "^9 || ^11", "ext-pdo": "*", "ext-phar": "*", "phpbench/phpbench": "^0.16 || ^1", "phpstan/phpstan": "^1.4", "phpstan/phpstan-phpunit": "^1", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.22" + "vimeo/psalm": "^4.30 || ^5.4" }, "type": "library", "autoload": { @@ -59,7 +59,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.1" + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" }, "funding": [ { @@ -75,20 +75,72 @@ "type": "tidelift" } ], - "time": "2022-03-03T08:28:38+00:00" + "time": "2022-12-30T00:15:36+00:00" + }, + { + "name": "mpyw/phpunit-patch-serializable-comparison", + "version": "v0.0.2", + "source": { + "type": "git", + "url": "https://github.com/mpyw/phpunit-patch-serializable-comparison.git", + "reference": "262180fb1fc529b3735f147f754d5ba1f05e541b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mpyw/phpunit-patch-serializable-comparison/zipball/262180fb1fc529b3735f147f754d5ba1f05e541b", + "reference": "262180fb1fc529b3735f147f754d5ba1f05e541b", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/comparator": "^1.0 || ^2.0 || ^3.0 || ^4.0" + }, + "type": "library", + "autoload": { + "files": [ + "./files/ComparisonFailure.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "mpyw", + "email": "ryosuke_i_628@yahoo.co.jp" + } + ], + "description": "Fixes assertSame/assertEquals serialization errors running in separate processes.", + "keywords": [ + "bug", + "fix", + "isolation", + "patch", + "phpunit", + "process", + "processes", + "separate", + "serialization" + ], + "support": { + "issues": "https://github.com/mpyw/phpunit-patch-serializable-comparison/issues", + "source": "https://github.com/mpyw/phpunit-patch-serializable-comparison/tree/v0.0.2" + }, + "time": "2021-07-04T05:15:38+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.11.0", + "version": "1.11.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", "shasum": "" }, "require": { @@ -126,7 +178,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" }, "funding": [ { @@ -134,20 +186,20 @@ "type": "tidelift" } ], - "time": "2022-03-03T13:19:32+00:00" + "time": "2023-03-08T13:26:56+00:00" }, { "name": "nikic/php-parser", - "version": "v4.15.1", + "version": "v4.17.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900" + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900", - "reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", "shasum": "" }, "require": { @@ -188,9 +240,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" }, - "time": "2022-09-04T07:30:47+00:00" + "time": "2023-08-13T19:53:39+00:00" }, { "name": "phar-io/manifest", @@ -305,27 +357,27 @@ }, { "name": "php-mock/php-mock", - "version": "2.3.1", + "version": "2.4.1", "source": { "type": "git", "url": "https://github.com/php-mock/php-mock.git", - "reference": "9a55bd8ba40e6da2e97a866121d2c69dedd4952b" + "reference": "6240b6f0a76d7b9d1ee4d70e686a7cc711619a9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-mock/php-mock/zipball/9a55bd8ba40e6da2e97a866121d2c69dedd4952b", - "reference": "9a55bd8ba40e6da2e97a866121d2c69dedd4952b", + "url": "https://api.github.com/repos/php-mock/php-mock/zipball/6240b6f0a76d7b9d1ee4d70e686a7cc711619a9d", + "reference": "6240b6f0a76d7b9d1ee4d70e686a7cc711619a9d", "shasum": "" }, "require": { "php": "^5.6 || ^7.0 || ^8.0", - "phpunit/php-text-template": "^1 || ^2" + "phpunit/php-text-template": "^1 || ^2 || ^3" }, "replace": { "malkusch/php-mock": "*" }, "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.0 || ^9.0", + "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.0 || ^9.0 || ^10.0", "squizlabs/php_codesniffer": "^3.5" }, "suggest": { @@ -364,11 +416,12 @@ "mock", "stub", "test", - "test double" + "test double", + "testing" ], "support": { "issues": "https://github.com/php-mock/php-mock/issues", - "source": "https://github.com/php-mock/php-mock/tree/2.3.1" + "source": "https://github.com/php-mock/php-mock/tree/2.4.1" }, "funding": [ { @@ -376,29 +429,29 @@ "type": "github" } ], - "time": "2022-02-07T18:57:52+00:00" + "time": "2023-06-12T20:48:52+00:00" }, { "name": "php-mock/php-mock-integration", - "version": "2.1.0", + "version": "2.2.1", "source": { "type": "git", "url": "https://github.com/php-mock/php-mock-integration.git", - "reference": "003d585841e435958a02e9b986953907b8b7609b" + "reference": "04f4a8d5442ca457b102b5204673f77323e3edb5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-mock/php-mock-integration/zipball/003d585841e435958a02e9b986953907b8b7609b", - "reference": "003d585841e435958a02e9b986953907b8b7609b", + "url": "https://api.github.com/repos/php-mock/php-mock-integration/zipball/04f4a8d5442ca457b102b5204673f77323e3edb5", + "reference": "04f4a8d5442ca457b102b5204673f77323e3edb5", "shasum": "" }, "require": { "php": ">=5.6", - "php-mock/php-mock": "^2.2", - "phpunit/php-text-template": "^1 || ^2" + "php-mock/php-mock": "^2.4", + "phpunit/php-text-template": "^1 || ^2 || ^3" }, "require-dev": { - "phpunit/phpunit": "^5.7.27 || ^6 || ^7 || ^8 || ^9" + "phpunit/phpunit": "^5.7.27 || ^6 || ^7 || ^8 || ^9 || ^10" }, "type": "library", "autoload": { @@ -431,31 +484,37 @@ ], "support": { "issues": "https://github.com/php-mock/php-mock-integration/issues", - "source": "https://github.com/php-mock/php-mock-integration/tree/2.1.0" + "source": "https://github.com/php-mock/php-mock-integration/tree/2.2.1" }, - "time": "2020-02-08T14:40:25+00:00" + "funding": [ + { + "url": "https://github.com/michalbundyra", + "type": "github" + } + ], + "time": "2023-02-13T09:51:29+00:00" }, { "name": "php-mock/php-mock-phpunit", - "version": "2.6.1", + "version": "2.9.0", "source": { "type": "git", "url": "https://github.com/php-mock/php-mock-phpunit.git", - "reference": "b9ba2db21e7e1c7deba98bc86dcfc6425fb4647d" + "reference": "3dabfd474d43da4d1d2fee5260c634457c5da344" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-mock/php-mock-phpunit/zipball/b9ba2db21e7e1c7deba98bc86dcfc6425fb4647d", - "reference": "b9ba2db21e7e1c7deba98bc86dcfc6425fb4647d", + "url": "https://api.github.com/repos/php-mock/php-mock-phpunit/zipball/3dabfd474d43da4d1d2fee5260c634457c5da344", + "reference": "3dabfd474d43da4d1d2fee5260c634457c5da344", "shasum": "" }, "require": { "php": ">=7", - "php-mock/php-mock-integration": "^2.1", - "phpunit/phpunit": "^6 || ^7 || ^8 || ^9" + "php-mock/php-mock-integration": "^2.2.1", + "phpunit/phpunit": "^6 || ^7 || ^8 || ^9 || ^10.0.17" }, "require-dev": { - "phpspec/prophecy": "^1.10.3" + "mockery/mockery": "^1.3.6" }, "type": "library", "autoload": { @@ -488,11 +547,12 @@ "phpunit", "stub", "test", - "test double" + "test double", + "testing" ], "support": { "issues": "https://github.com/php-mock/php-mock-phpunit/issues", - "source": "https://github.com/php-mock/php-mock-phpunit/tree/2.6.1" + "source": "https://github.com/php-mock/php-mock-phpunit/tree/2.9.0" }, "funding": [ { @@ -500,27 +560,27 @@ "type": "github" } ], - "time": "2022-09-07T20:40:07+00:00" + "time": "2023-12-01T21:50:22+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.18", + "version": "9.2.29", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "12fddc491826940cf9b7e88ad9664cf51f0f6d0a" + "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/12fddc491826940cf9b7e88ad9664cf51f0f6d0a", - "reference": "12fddc491826940cf9b7e88ad9664cf51f0f6d0a", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76", + "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.14", + "nikic/php-parser": "^4.15", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -535,8 +595,8 @@ "phpunit/phpunit": "^9.3" }, "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { @@ -569,7 +629,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.18" + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.29" }, "funding": [ { @@ -577,7 +638,7 @@ "type": "github" } ], - "time": "2022-10-27T13:35:33+00:00" + "time": "2023-09-19T04:57:46+00:00" }, { "name": "phpunit/php-file-iterator", @@ -822,20 +883,20 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.26", + "version": "9.6.15", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2" + "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/851867efcbb6a1b992ec515c71cdcf20d895e9d2", - "reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/05017b80304e0eb3f31d90194a563fd53a6021f1", + "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1", + "doctrine/instantiator": "^1.3.1 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", @@ -846,7 +907,7 @@ "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.13", + "phpunit/php-code-coverage": "^9.2.28", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", "phpunit/php-text-template": "^2.0.3", @@ -864,8 +925,8 @@ "sebastian/version": "^3.0.2" }, "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "bin": [ "phpunit" @@ -873,7 +934,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.5-dev" + "dev-master": "9.6-dev" } }, "autoload": { @@ -904,7 +965,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.26" + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.15" }, "funding": [ { @@ -920,7 +982,7 @@ "type": "tidelift" } ], - "time": "2022-10-28T06:00:21+00:00" + "time": "2023-12-01T16:55:19+00:00" }, { "name": "sebastian/cli-parser", @@ -1222,16 +1284,16 @@ }, { "name": "sebastian/diff", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", "shasum": "" }, "require": { @@ -1276,7 +1338,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" }, "funding": [ { @@ -1284,20 +1346,20 @@ "type": "github" } ], - "time": "2020-10-26T13:10:38+00:00" + "time": "2023-05-07T05:35:17+00:00" }, { "name": "sebastian/environment", - "version": "5.1.4", + "version": "5.1.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", "shasum": "" }, "require": { @@ -1339,7 +1401,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" }, "funding": [ { @@ -1347,7 +1409,7 @@ "type": "github" } ], - "time": "2022-04-03T09:37:03+00:00" + "time": "2023-02-03T06:03:51+00:00" }, { "name": "sebastian/exporter", @@ -1428,16 +1490,16 @@ }, { "name": "sebastian/global-state", - "version": "5.0.5", + "version": "5.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + "reference": "bde739e7565280bda77be70044ac1047bc007e34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", + "reference": "bde739e7565280bda77be70044ac1047bc007e34", "shasum": "" }, "require": { @@ -1480,7 +1542,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" }, "funding": [ { @@ -1488,7 +1550,7 @@ "type": "github" } ], - "time": "2022-02-14T08:28:10+00:00" + "time": "2023-08-02T09:26:13+00:00" }, { "name": "sebastian/lines-of-code", @@ -1661,16 +1723,16 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { @@ -1709,10 +1771,10 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" }, "funding": [ { @@ -1720,7 +1782,7 @@ "type": "github" } ], - "time": "2020-10-26T13:17:30+00:00" + "time": "2023-02-03T06:07:39+00:00" }, { "name": "sebastian/resource-operations", @@ -1779,16 +1841,16 @@ }, { "name": "sebastian/type", - "version": "3.2.0", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e" + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", - "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { @@ -1823,7 +1885,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.0" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" }, "funding": [ { @@ -1831,7 +1893,7 @@ "type": "github" } ], - "time": "2022-09-12T14:47:03+00:00" + "time": "2023-02-03T06:13:03+00:00" }, { "name": "sebastian/version", @@ -1888,16 +1950,16 @@ }, { "name": "theseer/tokenizer", - "version": "1.2.1", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", "shasum": "" }, "require": { @@ -1926,7 +1988,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + "source": "https://github.com/theseer/tokenizer/tree/1.2.2" }, "funding": [ { @@ -1934,7 +1996,7 @@ "type": "github" } ], - "time": "2021-07-28T10:34:58+00:00" + "time": "2023-11-20T00:12:19+00:00" } ], "aliases": [], @@ -1944,5 +2006,5 @@ "prefer-lowest": false, "platform": [], "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/docs/2023-Phoniebox-Calendar.jpg b/docs/2023-Phoniebox-Calendar.jpg new file mode 100644 index 000000000..cd42a55b1 Binary files /dev/null and b/docs/2023-Phoniebox-Calendar.jpg differ diff --git a/docs/FIRMWARE_UPDATE.md b/docs/FIRMWARE_UPDATE.md deleted file mode 100644 index d3ad0f879..000000000 --- a/docs/FIRMWARE_UPDATE.md +++ /dev/null @@ -1,39 +0,0 @@ -# Firmware update improves audio out? - -**This has not been tested yet**: The analogue audio out quality of the RPi3 is horrible. Learn more about the [impact of the firmware update in the raspberry forum](https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=167934). In the same forum you can find information on the [firmaware update effect on the analogue audio out](https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=136445). If you were to try to update the firmware, now would be the right moment. I tried the firmware update successfully, but haven't yet built a Phoniebox on top of it. So if you are new to the RPi, skip the following lines and go to the next chapter, configuring your keyboard. - -Open a terminal window and update the firmware typing: - -~~~~bash -sudo rpi-update -~~~~ - -Then reboot the machine: - -~~~~bash -sudo reboot -~~~~ - -Now open the terminal window again. The howto suggests to switch off the HDMI audio out: - -~~~~bash -amixer cset numid=3 1 -~~~~ - -Open the config file with: - -~~~~bash -sudo nano /boot/config.txt -~~~~ - -and add the following line: - -~~~~bash -audio_pwm_mode=2 -~~~~ - -Better safe than sorry, reboot the machine once more: - -~~~~bash -sudo reboot -~~~~ diff --git a/docs/GPIO-BUTTONS.md b/docs/GPIO-BUTTONS.md deleted file mode 100644 index 134cb8df2..000000000 --- a/docs/GPIO-BUTTONS.md +++ /dev/null @@ -1,98 +0,0 @@ -Deprecated, please see [wiki](/wiki) for the latest version - ---------------------------------------------- - -# Control Jukebox with buttons / GPIO - -(Other docs: [Installation](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/INSTALL-stretch) | -[Configuration](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/CONFIGURE-stretch) | -[Phoniebox manual](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL)) - -**Add buttons to your jukebox to control volume, skip tracks and more.** - -Before we start: -One of the plus points about this projects, at least in my mind, -was the fact that you don't need a soldering iron to build it. -Everything is USB, plug and play, thank you, boot and go. - -Many, many fellow jukebox tweakers have contacted me to push -the envelope a bit further and add buttons to the jukebox. -Buttons to change the volume and skip between tracks in a playlist. - -So this documentation is entirely community driven, I am only editing and asking for -confirmation that this works :) - -Enough said, here we go. - ---------------------------------------------- - -## Pin numbering on the RPi - -On your RPi there are pin numbers printed on the board. In the following we are not referring to the board numbers, but the Broadcom (BCM) pin numbering for the GPIO pins. You can find more information on this issue on the [pin numbering](https://gpiozero.readthedocs.io/en/stable/recipes.html#pin-numbering) section of the GPIO Zero documentation site. - -![Any pin marked “GPIO” in the diagram below can be used as a pin number. For example, if an LED was attached to “GPIO17” you would specify the pin number as 17 rather than 11.](img/GPIO-pin-numbering.png - "Any pin marked “GPIO” in the diagram below can be used as a pin number. For example, if an LED was attached to “GPIO17” you would specify the pin number as 17 rather than 11.") - -Any pin marked “GPIO” in the diagram above can be used as a pin number. A button attached to “GPIO17” would be specified in the script as pin number 17 rather than 11 (which would be the count on the board). - -## Fire up the soldering iron - -Ok, you asked for it, roll up your sleeves and read these before you start: - -* [Getting started with soldering on raspberrypi.org](https://www.raspberrypi.org/blog/getting-started-soldering/) -* [Switch and buttons basics on sparkfun.com](https://learn.sparkfun.com/tutorials/switch-basics) - -You will be running wires from the RPi board to another board where the buttons will be connected. The following image is what this looks like in a successful project. - -![The extra board to connect the RPi with the buttons using resistors on the extra board.](img/buttons-board.jpg - "The extra board to connect the RPi with the buttons using resistors on the extra board.") - -On the above image you can also see the pin numbering, in this case containing both: the RPi board numbering on the RPi3 and the Broadcom (BCM) pin numbering used for the code. - -The [script for the GPIO buttons](../misc/sampleconfigs/gpio-buttons.py.sample) we are using originally been provided by Andreas aka [hailogugo](https://github.com/hailogugo). It's been modified since then and now provides `pull_up=True` for all pins (not incl. shutdown). Read more in this thread [why we added `pull_up`](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/259). - -Here is how to connect the buttons: - -* **Volume Down** GPIO19 (PIN35) and GND (PIN39) -* **Volume Up** GPIO16 (PIN36) and GND (PIN34) -* **Play/Pause/Halt (or how you call it)** GPIO21 (PIN40) and GND (PIN25) -* **Next** GPIO26 (PIN37) and GND (PIN30) -* **Previous** GPIO20 (PIN38) and GND (PIN20) -* **Shutdown (you need to hold button for 2 secs for shutdown)** GPIO3 (PIN5) and GND (PIN6) - -**!!! IMPORTANT Only when using the above listed pins for wiring you will be able to power-up the Raspberry PI from firmware halt. !!!** - -### Circuit example(s) for the button wiring - -You will be using push buttons, which are essentially the same as arcade buttons, meaning: when you press them down, they are ON, when you let go, the are OFF. So skipping a track is tapping a button once, changing the volume, each tap changes it a bit. - -There are a number of different ways to connect a button. The easiest one is well explained on O'Reilly's RPi site: - -* [Connecting a Push Switch, O'Reilly](http://razzpisampler.oreilly.com/ch07.html) -* Watch the [Connecting a Push Switch with Raspberry Pi video on YouTube](https://youtu.be/3TDJ4FmtGgk) - -## Install GPIO software - -We need to run [GPIO Zero](https://gpiozero.readthedocs.io/en/stable/), a simple interface to GPIO devices with Raspberry Pi. GPIO Zero is installed by default in Raspbian Jessie. To install see the [installing](https://gpiozero.readthedocs.io/en/stable/installing.html) chapter on their site. Better safe than sorry, so lets install the packages on our machine: - -~~~bash -sudo apt-get install python3-gpiozero python-gpiozero -~~~ - -**Note**: No harm done to install both, python3 and python2. This needs trimming later on. - -Make a copy of the [python script for the GPIO buttons](../misc/sampleconfigs/gpio-buttons.py.sample) into the scripts folder. This way you are free to make changes to the script without changing your github repo. - -~~~bash -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/gpio-buttons.py.sample /home/pi/RPi-Jukebox-RFID/scripts/gpio-buttons.py -~~~ - -And change the copy to be executable - -~~~bash -sudo chmod +x /home/pi/RPi-Jukebox-RFID/scripts/gpio-buttons.py -~~~ - -**Note**: work in progress: the [python script for the GPIO buttons](../misc/sampleconfigs/gpio-buttons.py.sample) will be explained when I get to it. - -To have this started automatically at boot. Please read the section on [autostarting the scripts](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/CONFIGURE-stretch#systemdautostart) in the [configuration documentation](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/CONFIGURE-stretch#systemdautostart). diff --git a/docs/INSTALL-COMPLETE-GUIDE.md b/docs/INSTALL-COMPLETE-GUIDE.md deleted file mode 100644 index 696d2d813..000000000 --- a/docs/INSTALL-COMPLETE-GUIDE.md +++ /dev/null @@ -1,230 +0,0 @@ -# How to set up a Phoniebox from scratch - -- [How to set up a Phoniebox from scratch](#how-to-set-up-a-phoniebox-from-scratch) - - [1. What you need](#1-what-you-need) - - [2. Install Raspberry Pi OS](#2-install-raspberry-pi-os) - - [3. Initial Boot](#3-initial-boot) - - [4. Prepare hardware](#4-prepare-hardware) - - [5. Audio](#5-audio) - - [5a. On-board headphone](#5a-on-board-headphone) - - [5b. USB sound card](#5b-usb-sound-card) - - [6. Install Phoniebox software](#6-install-phoniebox-software) - - [7. Verify Phoniebox setup](#7-verify-phoniebox-setup) - ---- - -## 1. What you need - -All parts marked with a star (*) are optional but improve the overall experience. All linked components are examples but have proven to work together. You are free to choose different equipment. - -1. [Micro SD Card](https://amzn.to/3do7KJr) (e.g. 32 GB) -1. Raspberry Pi - - [Model 3 B+](https://amzn.to/2NGL7Fa) - recommended - - [Model 4 B](https://amzn.to/2M0xtfJ) - could be a little overhead - - (Model 1, 2, 3 and Zero are possible, but they are slower...) -1. [USB RFID Reader](https://amzn.to/3s47Iun) -1. [RFID Chips](https://amzn.to/3k78F2j) or [RFID Cards](https://amzn.to/3dplljG) -1. [Speakers with 3.5mm jack](https://amzn.to/3dnhmnV) - -To improve the sound, we recommend: - -- [Ground Loop Isolator](https://amzn.to/37nyZjK) * - -Alternatively you can use an external sound card, but sometimes that doesn't seem to improve much: - -- [USB Sound Card](https://amzn.to/3djaKqC) * - [Alternative](https://amzn.to/3u8guth) - ---- - -## 2. Install Raspberry Pi OS - -Before you can install the Phoniebox software, you need to prepare your Raspberry Pi and install - -1. Connect your Micro SD card (through a card reader) to your computer -1. [Download](https://www.raspberrypi.org/software/) the [Raspberry Pi Imager](https://www.raspberrypi.org/blog/raspberry-pi-imager-imaging-utility/) and open it -1. Select **Raspberry Pi OS** as the operating system -1. Select your Micro SD card (your card will be formatted) -1. Click `Write` -1. Wait for the imaging process to be finished (it'll take a few minutes) - ---- - -## 3. Initial Boot - -You will need a terminal, like PuTTY for Windows or the Terminal for Mac to proceed with the next steps. - -1. Open a terminal of your choice -1. Insert your card again if it has been ejected automatically -1. Navigate to your SC card e.g., `cd /Volumes/boot` for Mac or `D:` for Windows -1. Enable SSH by adding a simple file - - ```bash - $ touch ssh - ``` - -1. Set up your Wifi connection - - Mac - - ```bash - $ nano wpa_supplicant.conf - ``` - - - Windows - - ```bash - D:\> notepad wpa_supplicant.conf - ``` - -1. Insert the following content, update your country, Wifi credentials and save the file. - - ```bash - country=DE - ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev - update_config=1 - - network={ - ssid="network-name" - psk="network-password" - } - ``` - -1. Eject your SD card and insert it into your Raspberry Pi -1. Start your Raspberry Pi by attaching a power supply -1. 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. - - ```bash - $ ssh pi@raspberrypi.local - ``` - -1. Update the Pi's software. This may take a bit - - ```bash - $ sudo apt update && sudo apt full-upgrade - ``` - -1. Reboot with `sudo reboot` -1. Login again with SSH and open the Raspberry Pi config - - ```bash - $ sudo raspi-config - ``` - -1. Update the following settings - - ```bash - 1 System Options - S5 Boot / Auto Login -> B2 Console Autologin - S6 Network at Boot -> Yes - ``` - -1. Close the settings panel with `` -1. Shutdown your Raspberry Pi with `sudo shutdown` - ---- - -## 4. Prepare hardware - -1. Connect the RFID Reader -1. Conntect USB Sound Card if available -1. Plug in the 3.5" speakers with the Ground Loop Isolator in between. If you have chosen the example speakers from above, you can power them either through the Raspberry Pi or through an external power source. -1. Boot your Raspberry Pi -1. Open a terminal in your second computer and login via SSH using the `pi` user and default password `raspberry`. If you see a question about authentication and fingerprint, type `yes` and hit `enter` - - ```bash - ssh pi@raspberrypi.local - ``` - ---- - -## 5. Audio - -### 5a. On-board headphone - -Installing with an external monitor (HDMI) can create a problem if you use the mini-jack audio out. The problem is that if you plug in a HDMI monitor an additional sound output is added and the index changes. This bothering behavior was introduced, when Raspberry Pi separated headphones jack and HDMI into two different devices in May 2020. -Also see [Troubleshooting: headphone audio unavailable after unplugging HDMI](https://github.com/MiczFlor/RPi-Jukebox-RFID/discussions/1300) - -### 5b. USB sound card - -1. Open the Raspberry Pi config - - ```bash - $ sudo raspi-config - ``` - -1. Update the following settings - - ```bash - 1 System Options - S2 Audio -> 1 USB Audio - ``` - -1. Close the settings panel with `` -1. Make your soundcard the primary sound device. To update the sound card priority order, edit the following file: - - ```bash - $ sudo nano /usr/share/alsa/alsa.conf - ``` - -1. Find the following variables and change their value from `0` to `1` - - ```bash - defaults.ctl.card 0 - defaults.pcm.card 0 - - // to - - defaults.ctl.card 1 - defaults.pcm.card 1 - ``` - -1. Reboot -1. Test your audio! Check if you hear white noise in stereo when running the following command from your connected speakers. If not, refer to this [resource](https://learn.adafruit.com/usb-audio-cards-with-a-raspberry-pi/instructions) to troubleshoot. - - ```bash - speaker-test -c2 - ``` - ---- - -## 6. Install Phoniebox software - -If you want to install the **Spotify+ version**, [read this first](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Spotify-FAQ). - -Run the following command in your SSH terminal and follow the instructions - -```bash -cd; rm buster-install-*; wget https://raw.githubusercontent.com/MiczFlor/RPi-Jukebox-RFID/master/scripts/installscripts/buster-install-default.sh; chmod +x buster-install-default.sh; ./buster-install-default.sh -``` - -1. `Yes` to `Continue interactive installation` -1. `No` to the `Wifi Setting step` - it's already set! -1. `Speaker` to `CONFIGURE AUDIO INTERFACE (iFace)` -1. Setup Spotify (optional) - 1. You need to generate your personal Spotify client ID and secret - 1. Visit the [Mopidy Spotify Authentication Page](https://mopidy.com/ext/spotify/#authentication) - 1. Click the button `Authenticate Mopidy with Spotify` - 1. Login to Spotify with your credentials - 1. Once logged in, the code snippet on the website is updated with your `client_id` and `client_secret` - 1. Provide your Spotify `username`, `password` and paste your `client_id` and `client_secret` into your terminal -1. `Yes` to `CONFIGURE MPD` -1. `Yes` to `FOLDER CONTAINING AUDIO FILES` -1. Optional: In this scenario, we do not install GPIO buttons, so feel free to choose `No` -1. `Yes` to `Do you want to start the installation?` -1. ... Wait a bit for the installation to happen ... -1. `Yes` to `Have you connected your RFID reader?` -1. `1` to select `1. USB-Reader` -1. Choose the `#` that resonates with your RFID reader, in our case `HXGCoLtd Keyboard` -1. `Yes` to `Would you like to reboot now?` - ---- - -## 7. Verify Phoniebox setup - -1. Open a browser in your computer and navigate to your Raspberry Pi: `http://raspberrypi.local` -1. You should see the Phoniebox UI -1. In your navigation, choose `Card ID` -1. Swipe one card near your RFID reader. If `Last used Chip ID` is automatically updated (you might hear a beep) and shows a number, your reader works -1. Verify Spotify (optional) - 1. Click `Spotify+` in the menu - 1. Mopidy opens, a second web player which was also installed - 1. You should be able to search and play Spotify content here diff --git a/docs/PHONIEBOX_ReadOnly.md b/docs/PHONIEBOX_ReadOnly.md deleted file mode 100644 index b2dc4c13f..000000000 --- a/docs/PHONIEBOX_ReadOnly.md +++ /dev/null @@ -1,127 +0,0 @@ -# Phoniebox with read-only Filesystem - -In order to make the Phoniebox more resilient against sudden power loss a mostly read-only filesystem helps against filesystem corruption. - -First we need to mount a read-write Partition to /home/pi/RPi-Jukebox-RFID/shared/. This can bei either a further partition on the SD -card or an USB drive connected to the Pi. If you want to store the shared partition on the sd card you need to first resize the main -partition. In a normal raspbian install there is one small partition and one that fills the rest of the card. There is a good HOWTO on how -to resize the partition here: https://www.howtoforge.com/partitioning_with_gparted - -Please resize the partition AFTER the first boot of teh systtem since Raspbian tries to resize the partition on the sd card to fill the -whole card this process seems to fail if there is a partition in the way. - -Before the new partition can be mounted the original shared directory with its contents needs to be moved out of the way: - -``` -cd ~/RPi-Jukebox-RFID/ -mv shared shared.old -mkdir shared -``` - -Then we need to find out the PARTUUID of the newly created partition with the command blkid. It should produce the following output: - -``` -pi@JukeboxJan:~/RPi-Jukebox-RFID $ blkid -/dev/mmcblk0p1: LABEL="boot" UUID="9304-D9FD" TYPE="vfat" PARTUUID="9282f822-01" -/dev/mmcblk0p2: LABEL="rootfs" UUID="29075e46-f0d4-44e2-a9e7-55ac02d6e6cc" TYPE="ext4" PARTUUID="9282f822-02" -/dev/mmcblk0p3: LABEL="shared" UUID="821fcedf-b705-4515-a5e8-2e99beefc1bf" TYPE="ext4" PARTUUID="9282f822-03" -``` - -In order to mount the rw partition to ~/RPi-Jukebox-RFID/shared/ on bootup you need to add the following line to /etc/fstab Replace the PARTUUID with teh one from your output. (Don't forget you need to ```sudo vi /etc/fstab``` to edit the file) - -``` -PARTUUID="9282f822-03" /home/pi/RPi-Jukebox-RFID/shared ext4 defaults,noatime 0 2 -``` - -```sudo mount -a``` will mount the new partition to its mountpoint. - -Now adjust the ownership and permissions of the new shared directory: - -``` -sudo chown pi:www-data shared -sudo chmod 775 shared -``` - -Rsync the contents of shared.old into share: - -```` -rsync -av shared.old/* shared/ -```` - -Some settings need to persist between boots, others are not necessarily persistend. Those that need to be persistent are symlinked to -a new directory shared/settings, the others are symlinked to files in /var/tmp that will reside on a ramdisk. - -``` -ln -sf /var/tmp/Latest_RFID ~/RPi-Jukebox-RFID/settings -ln -sf /var/tmp/Latest_Folder_Played ~/RPi-Jukebox-RFID/settings -ln -sf /var/tmp/Latest_Playlist_Played ~/RPi-Jukebox-RFID/settings -ln -sf /var/tmp/latestID.txt ~/RPi-Jukebox-RFID/shared/ - -mkdir ~/RPi-Jukebox-RFID/shared/settings -mv Audio_Folders_Path Audio_Volume_Change_Step Idle_Time_Before_Shutdown Max_Volume_Limit Playlists_Folders_Path Second_Swipe ShowCover ../shared/settings/ -ln -sf ~/RPi-Jukebox-RFID/shared/settings/* ~/RPi-Jukebox-RFID/settings/ -``` - - -Add the following lines to the fstab: - -```sudo vi /etc/fstab``` - -``` -tmpfs /var/log tmpfs nodev,nosuid 0 0 -tmpfs /var/lib/samba tmpfs nodev,nosuid 0 0 -tmpfs /var/lib/mpd tmpfs nodev,nosuid 0 0 -tmpfs /var/cache/samba tmpfs nodev,nosuid 0 0 -tmpfs /var/tmp tmpfs nodev,nosuid 0 0 -tmpfs /tmp tmpfs nodev,nosuid 0 0 -``` - -If you have not yet created a password for the Samba User pi, do it now, before moving the files away: - -```sudo smbpasswd pi``` - -Move Samba files away and create mount point for a tmpfs: -``` -sudo mv /var/lib/samba /var/lib/samba.save -sudo mkdir /var/lib/samba -``` - -```sudo vi /etc/tmpfiles.d/smb.conf``` - -paste -``` -#Type Path Mode UID GID Age Argument -C /var/lib/samba/private - - - - /var/lib/samba.save/private -C /var/lib/samba/account_policy.tdb - - - - /var/lib/samba.save/account_policy.tdb -C /var/lib/samba/group_mapping.tdb - - - - /var/lib/samba.save/group_mapping.tdb -C /var/lib/samba/printers - - - - /var/lib/samba.save/printers -C /var/lib/samba/registry.tdb - - - - /var/lib/samba.save/registry.tdb -C /var/lib/samba/share_info.tdb - - - - /var/lib/samba.save/share_info.tdb -C /var/lib/samba/usershares - - - - /var/lib/samba.save/usershares -C /var/lib/samba/wins.dat - - - - /var/lib/samba.save/wins.dat -C /var/lib/samba/wins.tdb - - - - /var/lib/samba.save/wins.tdb -d /var/log/samba 0750 root adm - - -``` - - -```sudo vi /etc/tmpfiles.d/lighttpd.conf``` - -paste - -``` -#Type Path Mode UID GID Age Argument -d /var/log/lighttpd 0755 www-data www-data - - -``` - -Change settings/Playlist_Folders_Path to shared/playlists - -Edit /etc/mpd.conf and change log_file from /var/log/mpd/mpd.log to /var/log/mpd.log - -If you need to make changes to your root filesystem in the future you need to remount it in read-write mode. - -This can be done with the command ```mount -o remount,rw /``` and reversed by ```mount -oremount,to /``` - -Sources: -* https://kofler.info/raspbian-lite-fuer-den-read-only-betrieb/ and -* https://petr.io/en/blog/2015/11/09/read-only-raspberry-pi-with-jessie/ - diff --git a/docs/UPGRADE.md b/docs/UPGRADE.md deleted file mode 100755 index f7e173255..000000000 --- a/docs/UPGRADE.md +++ /dev/null @@ -1,259 +0,0 @@ - -# How to upgrade the Phoniebox code - -Assuming that you use `git pull` to update the code base of your Phoniebox, -every now and then you need to run some update scripts, like patches. -To make this somewhat consistent, I started this page to document things that need to be done. - -If you still encounter problems after running the below upgrade snippets, check inside the folder `scripts/installscripts/` for scripts which contain the entire install process. - -## Which version am I on? - -There is a file `settings/version` containing the version number. - -**Note:*** This is work in progress, please share experience, improvements and insights in the [issue section](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues). - -# Upgrade from Version 1.1.7 to 1.1.8 - -**NOTE**: version `1.1.8` is the `master` branch. If you run into issues, please ask them on the "issues" board on GitHub. [2018-12-10]. - -And in capital letters: **YOUR BEST CHOICE IS TO GET A NEW SD CARD AND DO A FRESH INSTALL FOR THE NEW 1.1.8 VERSION, BECAUSE A LOT HAS CHANGED AS YOU CAN SEE IN THE UPGRADE SCRIPT BELOW** (now you can't say you didn't know...) - -We introduce Phoniebox Editions. To distinguish them, we call them "Phoniebox Classic" (out of the box, no Spotify) and "Phoniebox +Spotify" (Phoniebox with Spotify integration). - -**This is a bugfix-version.** After release of "Phoniebox +Spotify" there were reported some problems, which are bugfixed now, hopefully. e.g. Improved loading time of local music **(please go to "Folders & Files" and scan your library ONCE after update and everytime you upload new files to your box!)**. To reduce the boot up time of Phoniebox, be sure you are using the newest version of mopidy-spotify. The upgrade is integrated into the following steps. - -**Please use our [spotify thread](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/18) to post improvements regarding this feature.** - -~~~bash -cd /home/pi/RPi-Jukebox-RFID -git checkout master -git fetch origin -git reset --hard origin/master -git pull -sudo systemctl stop mpd -sudo systemctl stop mopidy - -USERNAME=$(sudo grep 'username' /etc/mopidy/mopidy.conf|sed 's/username = //g'|sed 's/"//g'|tr -d "\n") -PASSWORD=$(sudo grep 'password' /etc/mopidy/mopidy.conf|sed 's/password = //g'|sed 's/"//g'|tr -d "\n") -CLIENT_ID=$(sudo grep 'client_id' /etc/mopidy/mopidy.conf|sed 's/client_id = //g'|sed 's/"//g'|tr -d "\n") -CLIENT_SECRET=$(sudo grep 'client_secret' /etc/mopidy/mopidy.conf|sed 's/client_secret = //g'|sed 's/"//g'|tr -d "\n") - -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/mpd.conf.sample /etc/mpd.conf -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/mopidy-etc.sample /etc/mopidy/mopidy.conf -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/mopidy.sample /home/pi/.config/mopidy/mopidy.conf - -sudo sed -i 's/%spotify_username%/'"$USERNAME"'/' /etc/mopidy/mopidy.conf -sudo sed -i 's/%spotify_password%/'"$PASSWORD"'/' /etc/mopidy/mopidy.conf -sudo sed -i 's/%spotify_client_id%/'"$CLIENT_ID"'/' /etc/mopidy/mopidy.conf -sudo sed -i 's/%spotify_client_secret%/'"$CLIENT_SECRET"'/' /etc/mopidy/mopidy.conf -sudo sed -i 's/%spotify_username%/'"$USERNAME"'/' ~/.config/mopidy/mopidy.conf -sudo sed -i 's/%spotify_password%/'"$PASSWORD"'/' ~/.config/mopidy/mopidy.conf -sudo sed -i 's/%spotify_client_id%/'"$CLIENT_ID"'/' ~/.config/mopidy/mopidy.conf -sudo sed -i 's/%spotify_client_secret%/'"$CLIENT_SECRET"'/' ~/.config/mopidy/mopidy.conf - -# services to launch after boot using systemd -# -rw-r--r-- 1 root root 304 Apr 30 10:07 phoniebox-rfid-reader.service -# 1. delete old services (this is legacy, might throw errors but is necessary. Valid for versions < 1.1.8-beta) -echo "### Deleting older versions of service daemons. This might throw errors, ignore them" -sudo systemctl disable idle-watchdog -sudo systemctl disable rfid-reader -sudo systemctl disable startup-sound -sudo systemctl disable gpio-buttons -sudo rm /etc/systemd/system/rfid-reader.service -sudo rm /etc/systemd/system/startup-sound.service -sudo rm /etc/systemd/system/gpio-buttons.service -sudo rm /etc/systemd/system/idle-watchdog.service -echo "### Done with erasing old daemons. Stop ignoring errors!" -# 2. install new ones - this is version > 1.1.8-beta -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/phoniebox-rfid-reader.service.stretch-default.sample /etc/systemd/system/phoniebox-rfid-reader.service -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/phoniebox-startup-sound.service.stretch-default.sample /etc/systemd/system/phoniebox-startup-sound.service -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/phoniebox-gpio-buttons.service.stretch-default.sample /etc/systemd/system/phoniebox-gpio-buttons.service -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/phoniebox-idle-watchdog.service.sample /etc/systemd/system/phoniebox-idle-watchdog.service -sudo chown root:root /etc/systemd/system/phoniebox-rfid-reader.service -sudo chown root:root /etc/systemd/system/phoniebox-startup-sound.service -sudo chown root:root /etc/systemd/system/phoniebox-gpio-buttons.service -sudo chown root:root /etc/systemd/system/phoniebox-idle-watchdog.service -sudo chmod 644 /etc/systemd/system/phoniebox-rfid-reader.service -sudo chmod 644 /etc/systemd/system/phoniebox-startup-sound.service -sudo chmod 644 /etc/systemd/system/phoniebox-gpio-buttons.service -sudo chmod 644 /etc/systemd/system/phoniebox-idle-watchdog.service -# enable the services needed -sudo systemctl enable phoniebox-idle-watchdog -sudo systemctl enable phoniebox-rfid-reader -sudo systemctl enable phoniebox-startup-sound -sudo systemctl enable phoniebox-gpio-buttons - -echo "classic" > /home/pi/RPi-Jukebox-RFID/settings/edition -EDITION=$(grep 'SPOTinstall' /home/pi/PhonieboxInstall.conf|sed 's/SPOTinstall="//g'|sed 's/"//g'); if [ $EDITION == "YES" ]; then echo "plusSpotify"; else echo "classic"; fi > /home/pi/RPi-Jukebox-RFID/settings/edition - -sudo apt-get install libspotify12 python-cffi python-ply python-pycparser python-spotify -sudo rm -rf /usr/lib/python2.7/dist-packages/mopidy_spotify* -sudo rm -rf /usr/lib/python2.7/dist-packages/Mopidy_Spotify-* -sudo rm -rf /usr/local/lib/python2.7/dist-packages/mopidy_spotify* -sudo rm -rf /usr/local/lib/python2.7/dist-packages/Mopidy_Spotify-* -cd -sudo rm -rf mopidy-spotify -git clone -b fix/web_api_playlists --single-branch https://github.com/princemaxwell/mopidy-spotify.git -cd mopidy-spotify -sudo python setup.py install - -sudo sed -i '/level/s/\bINFO\b/WARNING/g' /etc/mopidy/logging.conf -sudo rm /var/log/mopidy/mopidy.log - -sudo reboot -~~~ - -# Upgrade from Version 1.1.1 to 1.1.7 - -Not much has changed in the core of this version. There is the new feature: Integrating **Spotify** to your Phoniebox. Currently this is *only* a [HOWTO document](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Spotify-FAQ) which needs improvement and your input. I invite everybody to use our [spotify thread](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/18) to post improvements regarding this feature. You might also want to [improve the documentation on *Spotify integration*](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Spotify-FAQ) and create pull requests so I can merge this with the core. - -Upgrading is therefore fairly simple. The following will overwrite any local changes to your code but NOT to your configruation files and systemd services, GPIO and the like. Only core code: - -~~~bash -cd /home/pi/RPi-Jukebox-RFID -git checkout master -git fetch origin -git reset --hard origin/master -git pull -~~~ - -# Upgrade from Version 1.1.1 to 1.1.6 - -A few important bug fixes. And a new design. -And the option to decide what the 'second swipe' of a card does (see settings in the web app). -The following should get you all you need, without running the install script if you -only want to upgrade. - -~~~bash -cd /home/pi/RPi-Jukebox-RFID -git checkout master -git fetch origin -git reset --hard origin/master -git pull -sudo chown -R pi:www-data /home/pi/RPi-Jukebox-RFID/shared -sudo chmod -R 775 /home/pi/RPi-Jukebox-RFID/shared -sudo chown -R pi:www-data /home/pi/RPi-Jukebox-RFID/htdocs -sudo chmod -R 775 /home/pi/RPi-Jukebox-RFID/htdocs -sudo chown -R pi:www-data /home/pi/RPi-Jukebox-RFID/settings -sudo chmod -R 777 /home/pi/RPi-Jukebox-RFID/settings -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/phoniebox-rfid-reader.service.stretch-default.sample /etc/systemd/system/phoniebox-rfid-reader.service -sudo chown root:root /etc/systemd/system/phoniebox-rfid-reader.service -sudo chmod 644 /etc/systemd/system/phoniebox-rfid-reader.service -sudo systemctl enable rfid-reader -~~~ - -# Upgrade from Version 1.0.0 to 1.1.1 - -This upgrade brings the web app UI for file management, recursive folder management, wifi switch off and more. The latest [one-line Phoniebox install script](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/CONFIGURE-stretch#oneLineInstall) contains all the necessary steps, but will treat your upgrade like a new install. Manual upgrade: - -~~~bash -cd -cd /home/pi/RPi-Jukebox-RFID -git fetch -git checkout master -git pull -# settings for php.ini to support upload -# make backup -sudo cp /etc/php/7.0/fpm/php.ini /etc/php/7.0/fpm/php.ini.backup -# replace file -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/php.ini.stretch-default.sample /etc/php/7.0/fpm/php.ini -sudo chown root:root /etc/php/7.0/fpm/php.ini -sudo chmod 644 /etc/php/7.0/fpm/php.ini -sudo service lighttpd force-reload -sudo service php7.0-fpm restart -~~~ - -# Upgrade to Version 1.0 - -As of version 1.0 there is a much simpler install procedure: copy and paste one line into your terminal and hit *enter*. Find out more about the [one-line Phoniebox install script](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/CONFIGURE-stretch#oneLineInstall). - -# Upgrade from 0.9.5 to 0.9.7 - -* Adding a *Settings* page in the web app to control features like 'idle shutdown' and 'max volume' and toggle systemd services -* Documentation / troubleshooting / tricks: how to install via ssh, improve on board audio quality and the like -* Adding auto shutdown when idle for longer than x minutes (see [manual](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#settings) for details) -* Adding maximum volume percent to settings (see [manual](https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/MANUAL#settings) for details) -* Fixing bug: settings volume for stereo audio iFace -* Fixing bug: bash code compatible with all shells -* Web app enhancements (audio level, display 'playing now') - -~~~bash -# services to launch after boot using systmed -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/phoniebox-idle-watchdog.service.sample /etc/systemd/system/phoniebox-idle-watchdog.service -sudo chown root:root /etc/systemd/system/phoniebox-idle-watchdog.service -sudo chmod 644 /etc/systemd/system/phoniebox-idle-watchdog.service -# the config file where you can add the minutes after which Phoniebox shuts down -echo "0" > /home/pi/RPi-Jukebox-RFID/settings/Idle_Time_Before_Shutdown -# enable and start the service -sudo systemctl enable phoniebox-idle-watchdog.service -sudo systemctl start phoniebox-idle-watchdog.service -~~~ - -# Upgrade from 0.9.4 to 0.9.5 - -* Configuration of RFID card control in extra file `settings/rfid_trigger_play.conf` -* Playout control config now uses `settings` folder to store iFace value (e.g. PCM) and percentage of relative volume change -* both bash scripts `scripts/rfid_trigger_play.sh` and `scripts/playout_controls.sh` are not created from `.sample` versions anymore, because the config has been moved to external files. - -~~~bash -# make backups of the current scripts -mv /home/pi/RPi-Jukebox-RFID/scripts/rfid_trigger_play.sh /home/pi/RPi-Jukebox-RFID/scripts/rfid_trigger_play.sh.backup.0.9.4 -mv /home/pi/RPi-Jukebox-RFID/scripts/playout_controls.sh /home/pi/RPi-Jukebox-RFID/scripts/playout_controls.sh.backup.0.9.4 -rm /home/pi/RPi-Jukebox-RFID/scripts/rfid_trigger_play.sh.sample -rm /home/pi/RPi-Jukebox-RFID/scripts/playout_controls.sh.sample -cp /home/pi/RPi-Jukebox-RFID/htdocs/config.php /home/pi/RPi-Jukebox-RFID/htdocs/config.php.backup.0.9.4 -# update with git -git checkout master -git pull -# copy config file for RFID chips from sample to "live" -# you need to manually edit the created files and add the values from the backup version of `scripts/rfid_trigger_play.sh` -cp /home/pi/RPi-Jukebox-RFID/settings/rfid_trigger_play.conf.sample /home/pi/RPi-Jukebox-RFID/settings/rfid_trigger_play.conf -sudo chown pi:pi /home/pi/RPi-Jukebox-RFID/settings/rfid_trigger_play.conf -sudo chmod 775 /home/pi/RPi-Jukebox-RFID/settings/rfid_trigger_play.conf -~~~ - -# Upgrade to 0.9.4 - -* The following script refers to the OS version 'Stretch' in some places but this should also work for 'Jessie'. -* OS 'Stretch' and 'Jessie' require different `lighttpd.conf` parameters. Samples can be found in `misc/sampleconfigs` - -~~~bash -# make backups of the current scripts -cp /home/pi/RPi-Jukebox-RFID/scripts/rfid_trigger_play.sh /home/pi/RPi-Jukebox-RFID/scripts/rfid_trigger_play.sh.backup.0.9.3 -cp /home/pi/RPi-Jukebox-RFID/scripts/playout_controls.sh /home/pi/RPi-Jukebox-RFID/scripts/playout_controls.sh.backup.0.9.3 -cp /home/pi/RPi-Jukebox-RFID/htdocs/config.php /home/pi/RPi-Jukebox-RFID/htdocs/config.php.backup.0.9.3 -# update with git -git checkout master -git pull -# copy shell script for player -cp /home/pi/RPi-Jukebox-RFID/scripts/rfid_trigger_play.sh.sample /home/pi/RPi-Jukebox-RFID/scripts/rfid_trigger_play.sh -sudo chown pi:pi /home/pi/RPi-Jukebox-RFID/scripts/rfid_trigger_play.sh -sudo chmod 775 /home/pi/RPi-Jukebox-RFID/scripts/rfid_trigger_play.sh -# copy bash script for player controls -cp /home/pi/RPi-Jukebox-RFID/scripts/playout_controls.sh.sample /home/pi/RPi-Jukebox-RFID/scripts/playout_controls.sh -sudo chown pi:pi /home/pi/RPi-Jukebox-RFID/scripts/playout_controls.sh -sudo chmod 775 /home/pi/RPi-Jukebox-RFID/scripts/playout_controls.sh -# create config file for web app from sample -sudo cp /home/pi/RPi-Jukebox-RFID/htdocs/config.php.sample /home/pi/RPi-Jukebox-RFID/htdocs/config.php -# make sure the shared folder is accessible by the web server -sudo chown -R pi:www-data /home/pi/RPi-Jukebox-RFID/shared -sudo chmod -R 775 /home/pi/RPi-Jukebox-RFID/shared -# make sure the htdocs folder can be changed by the web server -sudo chown -R pi:www-data /home/pi/RPi-Jukebox-RFID/htdocs -sudo chmod -R 775 /home/pi/RPi-Jukebox-RFID/htdocs -# services to launch after boot using systmed -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/phoniebox-rfid-reader.service.stretch-default.sample /etc/systemd/system/phoniebox-rfid-reader.service -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/phoniebox-startup-sound.service.stretch-default.sample /etc/systemd/system/phoniebox-startup-sound.service -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/phoniebox-gpio-buttons.service.stretch-default.sample /etc/systemd/system/phoniebox-gpio-buttons.service -sudo chown root:root /etc/systemd/system/phoniebox-rfid-reader.service -sudo chown root:root /etc/systemd/system/phoniebox-startup-sound.service -sudo chown root:root /etc/systemd/system/phoniebox-gpio-buttons.service -sudo chmod 644 /etc/systemd/system/phoniebox-rfid-reader.service -sudo chmod 644 /etc/systemd/system/phoniebox-startup-sound.service -sudo chmod 644 /etc/systemd/system/phoniebox-gpio-buttons.service -# In case the older version of Phoniebox still uses crontab to start daemon script, UNDO the crontab changes -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/crontab-pi.UNDO-default.sample /var/spool/cron/crontabs/pi -sudo chown pi:crontab /var/spool/cron/crontabs/pi -sudo chmod 600 /var/spool/cron/crontabs/pi -~~~ diff --git a/docs/WLAN-ACCESS-POINT.md b/docs/WLAN-ACCESS-POINT.md deleted file mode 100644 index 8558f6f42..000000000 --- a/docs/WLAN-ACCESS-POINT.md +++ /dev/null @@ -1,231 +0,0 @@ - -# Access Phoniebox without Router - -It is possible to connect to the Phoniebox directly, without having your -laptop and the Phoniebox connect to the same WiFi network. Configuring the -Raspberry Pi to be a WiFi access point. - -I tested this only with the Raspberry Pi 3, which has a WiFi card onboard. -If you successfully did the same with another Raspberry Pi version, please -share your knowledge, I will weave it into the documenation. The reason I -say this is because creating a WiFi access point requires a WiFi card that -supports this mode. RPi3 does. - -Install two packages we need later. Later meaning: when we might not have Internet anymore. Because the wlan0 -interface will be set to a static IP -to create the access point. - -```bash -sudo apt-get update -sudo apt-get install dnsmasq hostapd -``` - -## Configure the network - -Using jessie, dhcpd is activated by default. This dhcp daemon is assigning -IP addresses to devices which want to connect to the Phoniebox. - -Set the IP address for the wlan card by opening: - -```bash -sudo nano /etc/network/interfaces -``` - -Replace the existing content with the following lines: - -```bash -# Localhost -auto lo -iface lo inet loopback - -# Ethernet -auto eth0 -iface eth0 inet manual - -# WLAN-Interface -allow-hotplug wlan0 -iface wlan0 inet static -address 192.168.1.1 -netmask 255.255.255.0 -``` - -Now, the wlan is set to the IP address `192.168.1.1`. - -We add one line to the dhcpd config file: - -```bash -sudo nano /etc/dhcpcd.conf -``` - -Append the line: - -```bash -denyinterfaces wlan0 -``` - -Now we reboot and afterwards you should be connected to your RPi directly, not via ssh. -Because if your RPi relied on a WiFi connection to the Internet, this will be cut off. -Remember: we need the wlan0 interface to hook up other devices to a WiFi network the -RPi is creating. - -Let's check if all interfaces are up and running. We only really need the wlan0 -but if eth0 is also up and is connected to the Internet, your Phoniebox will be online -and all devices connected to it. Type in the command line: - -```bash -ip a -``` - -This should list both interfaces (eth0 and wlan0). If it does, you can connect the RPi -to the Internet via an ethernet cable. But you still won't be able to connect to the -RPi via ssh quite yet. So make sure you have the RPi hooked up to a keyboard and a -monitor. - -Reboot. - -```bash -sudo reboot -``` - -## dhcp server configuration - -```bash -sudo nano /etc/dnsmasq.conf -``` - -The following lines are the minimal configuration required. - -```bash -# interface which is active -interface=wlan0 - -# interface to ignore -no-dhcp-interface=eth0 - -# IPv4 addresses and lease time -dhcp-range=192.168.1.100,192.168.1.200,24h - -# DNS -dhcp-option=option:dns-server,192.168.1.1 -``` - -Check the configuration before you start the dhcp server and -cache. - -```bash -dnsmasq --test -C /etc/dnsmasq.conf -``` - -This should return 'OK'. Now start `dnsmasq`: - -```bash -sudo systemctl restart dnsmasq -``` - -Check if it is up and running: - -```bash -sudo systemctl status dnsmasq -``` - -Now install dnsmasq to start after boot: - -```bash -sudo systemctl enable dnsmasq -``` - -## configure hostapd - -To assign ssid and password, we need to configure -`hostapd`. - -```bash -sudo nano /etc/hostapd/hostapd.conf -``` - -Replace the content of this file (if it already exists) with -the following content. - -```bash -# interface and driver -interface=wlan0 -#driver=nl80211 - -# WLAN-config -ssid=Phoniebox -channel=1 -hw_mode=g -ieee80211n=1 -ieee80211d=1 -country_code=DE -wmm_enabled=1 - -# WLAN-encryption -auth_algs=1 -wpa=2 -wpa_key_mgmt=WPA-PSK -rsn_pairwise=CCMP -wpa_passphrase=Pl4yM3N0w -``` - -The network will be listed as `Phoniebox` and the password -to connect to the network is `Pl4yM3N0w` (as in 'play me now' with a number four and a number three and a zero). If you want a different ssid and/or password, edit the lines above. - -This file contains a password in raw text, so make -sure only root can read it. - -```bash -sudo chmod 600 /etc/hostapd/hostapd.conf -``` - -Check if this setup is correct. Open -the wlan host in debug mode and read through the results. - -```bash -sudo hostapd -dd /etc/hostapd/hostapd.conf -``` - -Scroll up to see if you can find these two lines anywhere: - -```bash -wlan0: interface state COUNTRY_UPDATE->ENABLED -wlan0: AP-ENABLED -``` - -If yes, you can also try to hook -up a device with the network already. -See if you can find `Phoniebox` as a WiFi network. - -If that works, all is well. Stop the `hostapd` daemon with `Ctrl&C`. - -Before we can start `hostapd` on boot, we have to add a few lines -in the config file to specify -the location of the config file. - -```bash -sudo nano /etc/default/hostapd -``` - -Add these lines: - -```bash -RUN_DAEMON=yes -DAEMON_CONF="/etc/hostapd/hostapd.conf" -``` - -And start `hostapd` with the following commands: - -```bash -sudo systemctl start hostapd -sudo systemctl enable hostapd -``` - -Check if the daemon is up and running: - -```bash -sudo systemctl status hostapd -``` - -This concludes what we need to connect to the Phoniebox directly via WiFi. - -If you plan to connect the `eth0` via a cable with the Internet, you need to learn about firewall configurations. Google how to do this (I hope to replace this last paragraph with a nicer explanation and a link later, when I find the time. Apologies.) diff --git a/docs/img/GPIO-pin-numbering.png b/docs/img/GPIO-pin-numbering.png deleted file mode 100644 index 64270faa3..000000000 Binary files a/docs/img/GPIO-pin-numbering.png and /dev/null differ diff --git a/docs/img/Phoniebox-Manual-AddNewCardID.png b/docs/img/Phoniebox-Manual-AddNewCardID.png deleted file mode 100644 index 314798992..000000000 Binary files a/docs/img/Phoniebox-Manual-AddNewCardID.png and /dev/null differ diff --git a/docs/img/Phoniebox-RegisterNew_Button.png b/docs/img/Phoniebox-RegisterNew_Button.png deleted file mode 100644 index f9dd098aa..000000000 Binary files a/docs/img/Phoniebox-RegisterNew_Button.png and /dev/null differ diff --git a/docs/img/Phoniebox_Manual_HomeEditCardLink.png b/docs/img/Phoniebox_Manual_HomeEditCardLink.png deleted file mode 100644 index dc1208377..000000000 Binary files a/docs/img/Phoniebox_Manual_HomeEditCardLink.png and /dev/null differ diff --git a/docs/img/buttons-board.jpg b/docs/img/buttons-board.jpg deleted file mode 100644 index 97ba2753e..000000000 Binary files a/docs/img/buttons-board.jpg and /dev/null differ diff --git a/htdocs/cardEdit.php b/htdocs/cardEdit.php index 3872aea03..867d026f5 100755 --- a/htdocs/cardEdit.php +++ b/htdocs/cardEdit.php @@ -5,7 +5,7 @@ /************************************************** * VARIABLES * No changes required if you stuck to the -* INSTALL-stretch.md instructions. +* INSTALL.md instructions. * If you want to change the paths, edit config.php ***************************************************/ diff --git a/htdocs/cardRegisterNew.php b/htdocs/cardRegisterNew.php index 56aefd626..8c777e03f 100755 --- a/htdocs/cardRegisterNew.php +++ b/htdocs/cardRegisterNew.php @@ -4,7 +4,7 @@ /************************************************** * VARIABLES * No changes required if you stuck to the -* INSTALL-stretch.md instructions. +* INSTALL.md instructions. * If you want to change the paths, edit config.php * If you want to change the paths, edit config.php ***************************************************/ diff --git a/htdocs/inc.header.php b/htdocs/inc.header.php index 2b101cf69..65bc61ce5 100755 --- a/htdocs/inc.header.php +++ b/htdocs/inc.header.php @@ -4,7 +4,7 @@ /************************************************** * VARIABLES * No changes required if you stuck to the -* INSTALL-stretch.md instructions. +* INSTALL.md instructions. * If you want to change the paths, edit config.php ***************************************************/ @@ -75,6 +75,7 @@ "DEBUG_rfid_trigger_play_sh", "DEBUG_shuffle_play_sh", "DEBUG_single_play_sh", +"DEBUG_sync_shared_sh", ); $debugOptions = array("TRUE", "FALSE"); diff --git a/htdocs/lang/lang-de-DE.php b/htdocs/lang/lang-de-DE.php index 7487c4db7..95d50d02d 100644 --- a/htdocs/lang/lang-de-DE.php +++ b/htdocs/lang/lang-de-DE.php @@ -131,7 +131,7 @@ $lang['cardRegisterFolder2Card'] = "Audio-Ordner ist nun mit der Karten-ID verknüpft."; $lang['cardRegisterDownloadingYT'] = "

YouTube Audio wird heruntergeladen. Dies kann einige Minuten dauern. Du kannst die Logdatei \"youtube-dl.log\" im Ordner \"shared\" ansehen.

"; $lang['cardRegisterSwipeUpdates'] = "Dies wird automatisch aktualisiert, wenn du eine RFID-Karte ausliest."; -$lang['cardRegisterManualLinks'] = "

Du kannst Karten auch manuell mit Ordnern verbinden. Das Handbuch erklärt, wie man sich mit der Phoniebox verbindet und Karten registriert.

"; +$lang['cardRegisterManualLinks'] = "

Du kannst Karten auch manuell mit Ordnern verbinden. Das Handbuch erklärt, wie man sich mit der Phoniebox verbindet und Karten registriert.

"; $lang['cardRegisterTriggerSuccess'] = "Die Karte ist jetzt verknüpft um die Funktion auszuführen:"; /* diff --git a/htdocs/lang/lang-en-UK.php b/htdocs/lang/lang-en-UK.php index 9610adaa2..5b68fc9e3 100755 --- a/htdocs/lang/lang-en-UK.php +++ b/htdocs/lang/lang-en-UK.php @@ -132,7 +132,7 @@ $lang['cardRegisterFolder2Card'] = "Audio folder is now linked to Card."; $lang['cardRegisterDownloadingYT'] = "

YouTube audio is downloading. This may take a couple of minutes. You may check the logfile \"youtube-dl.log\" in the shared folder.

"; $lang['cardRegisterSwipeUpdates'] = "This will automatically update as you swipe a RFID card."; -$lang['cardRegisterManualLinks'] = "

You can also connect cards to folders manually. The manual explains how to connect to the phoniebox and register cards.

"; +$lang['cardRegisterManualLinks'] = "

You can also connect cards to folders manually. The manual explains how to connect to the phoniebox and register cards.

"; $lang['cardRegisterTriggerSuccess'] = "The card is now linked to trigger the command:"; /* diff --git a/htdocs/lang/lang-fr-FR.php b/htdocs/lang/lang-fr-FR.php index 73780f2d2..352846b37 100755 --- a/htdocs/lang/lang-fr-FR.php +++ b/htdocs/lang/lang-fr-FR.php @@ -132,7 +132,7 @@ $lang['cardRegisterFolder2Card'] = "Le dossier audio est désormais lié à une carte."; $lang['cardRegisterDownloadingYT'] = "

Piste YouTube en cours de téléchargement. Cela peut prendre plusieurs minutes. Log dans le fichier \"youtube-dl.log\".

"; $lang['cardRegisterSwipeUpdates'] = "Mise à jour automatique lors du passage d'une carte."; -$lang['cardRegisterManualLinks'] = "

Vous pouvez lier manuellement une carte à un dossier. Explication dans la documentation connection à phoniebox et enregistrer une carte.

"; +$lang['cardRegisterManualLinks'] = "

Vous pouvez lier manuellement une carte à un dossier. Explication dans la documentation connection à phoniebox et enregistrer une carte.

"; $lang['cardRegisterTriggerSuccess'] = "La carte est désormais lié à une commande :"; /* diff --git a/htdocs/lang/lang-nl-NL.php b/htdocs/lang/lang-nl-NL.php index 83b480cf6..38c6c451b 100755 --- a/htdocs/lang/lang-nl-NL.php +++ b/htdocs/lang/lang-nl-NL.php @@ -115,7 +115,7 @@ $lang['cardRegisterFolder2Card'] = "De audiomap is nu gekoppeld aan kaart-ID"; $lang['cardRegisterDownloadingYT'] = "

YouTube-audio wordt gedownload. Dit kan een paar minuten duren. U kunt het logbestand 'youtube-dl.log' in de gedeelde map controleren.

"; $lang['cardRegisterSwipeUpdates'] = "Dit wordt automatisch bijgewerkt terwijl je een RFID-kaart veegt."; -$lang['cardRegisterManualLinks'] = "

U kunt kaarten ook handmatig met mappen verbinden. In de handleiding wordt uitgelegd hoe u verbinding maakt met de phoniebox en kaarten registreert.

"; +$lang['cardRegisterManualLinks'] = "

U kunt kaarten ook handmatig met mappen verbinden. In de handleiding wordt uitgelegd hoe u verbinding maakt met de phoniebox en kaarten registreert.

"; /* * Card edit form diff --git a/htdocs/manageFilesFolders.php b/htdocs/manageFilesFolders.php index 0664704fa..4f8d6c59f 100755 --- a/htdocs/manageFilesFolders.php +++ b/htdocs/manageFilesFolders.php @@ -5,7 +5,7 @@ /************************************************** * VARIABLES * No changes required if you stuck to the - * INSTALL-stretch.md instructions. + * INSTALL.md instructions. * If you want to change the paths, edit config.php ***************************************************/ @@ -63,14 +63,14 @@ */ if ($_POST['ACTION'] == "fileUpload") { /* - * I spent 3 hours trying to find out why when I upload multiples file $_FILES return empty, - * I did noticed it was only when I select files that exceed 3m so I thought it was something - * related to the MAX_UPLOAD_SIZE that for my surprice came as default as 20m which was very - * confusing. Later I discovery the problem was in the POST_MAX_SIZE been 3m, so it happen - * that not only MAX_UPLOAD_SIZE is responsible and that is why I'd like to know there is no + * I spent 3 hours trying to find out why when I upload multiples file $_FILES return empty, + * I did noticed it was only when I select files that exceed 3m so I thought it was something + * related to the MAX_UPLOAD_SIZE that for my surprice came as default as 20m which was very + * confusing. Later I discovery the problem was in the POST_MAX_SIZE been 3m, so it happen + * that not only MAX_UPLOAD_SIZE is responsible and that is why I'd like to know there is no * error message that shows the cause. - */ - + */ + $uFiles = getFiles(); //print "
"; print_r($uFiles); print "
"; //??? // are there any files? @@ -82,7 +82,7 @@ if (count($uFiles['ufile']) == 0) { // if 0 there are no files $messageWarning .= "

No files were uploaded.

"; - } + } /* * let's start building the path to move the files to * as a relative path. @@ -112,7 +112,7 @@ if(!file_exists($Audio_Folders_Path . "/" . $moveFolder)) { // no, so create the folder $exec = 'mkdir "' . $moveFolder . '"; chown -R pi:www-data "' . $moveFolder . '"; sudo chmod -R 777 "' . $moveFolder . '"'; - exec($exec); + exec($exec); $messageAction .= "Will create new folder and move files to: '" . $moveFolder . "'"; } else { // folder exists already :( @@ -126,7 +126,7 @@ if(realpath($moveFolder) == realpath($Audio_Folders_Path)) { $messageWarning .= $lang['manageFilesFoldersErrorNoNewFolder']; } - + // if no error message if ($messageWarning == "") { // move files to folder @@ -161,12 +161,12 @@ if($messageWarning == "") { /* * create folder - */ + */ $exec = 'mkdir "'.$Audio_Folders_Path.'/'.$newDirPathRel.'"; sudo chmod -R 777 "'.$Audio_Folders_Path.'/'.$newDirPathRel.'"; chown -R pi:www-data "' . $Audio_Folders_Path.'/'.$newDirPathRel . '"'; exec($exec); $messageSuccess = "

".$lang['manageFilesFoldersSuccessNewFolder']." '".$newDirPathRel."'

"; - - + + } } @@ -278,13 +278,6 @@ } } - // check if we can preselect an audiofolder if NOT a foldername was posted - if (!isset($fpost['folder'])) { - if (array_key_exists($fpost['cardID'], $shortcuts)) { - $fpost['folder'] = $shortcuts[$fpost['cardID']]; - } - } - // go through all folders foreach ($audiofolders as $keyfolder => $audiofolder) { @@ -340,19 +333,19 @@ class="form-control input-md" type="text"> -
+
- +
- +
- +
- +
@@ -368,16 +361,16 @@ class="form-control input-md" type="text"> print " selected=selected"; } print ">".$audiofolder."\n"; - + } ?> - +
- +
- +
diff --git a/htdocs/trackEdit.php b/htdocs/trackEdit.php index 19be521cd..14ced2757 100755 --- a/htdocs/trackEdit.php +++ b/htdocs/trackEdit.php @@ -11,7 +11,7 @@ /************************************************** * VARIABLES * No changes required if you stuck to the -* INSTALL-stretch.md instructions. +* INSTALL.md instructions. * If you want to change the paths, edit config.php ***************************************************/ diff --git a/htdocs/userScripts.php b/htdocs/userScripts.php index f1897224f..536c06743 100755 --- a/htdocs/userScripts.php +++ b/htdocs/userScripts.php @@ -5,7 +5,7 @@ /************************************************** * VARIABLES * No changes required if you stuck to the -* INSTALL-stretch.md instructions. +* INSTALL.md instructions. * If you want to change the paths, edit config.php ***************************************************/ diff --git a/misc/sampleconfigs/15-fastcgi-php.conf.stretch-default.sample b/misc/sampleconfigs/15-fastcgi-php.conf.stretch-default.sample deleted file mode 100755 index 77c4f5475..000000000 --- a/misc/sampleconfigs/15-fastcgi-php.conf.stretch-default.sample +++ /dev/null @@ -1,11 +0,0 @@ -# -*- depends: fastcgi -*- -# /usr/share/doc/lighttpd/fastcgi.txt.gz -# http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:ConfigurationOptions#mod_fastcgi-fastcgi - -## Start an FastCGI server for php (needs the php5-cgi package) -fastcgi.server += ( ".php" => - (( - "socket" => "/var/run/php/php7.0-fpm.sock", - "broken-scriptfilename" => "enable" - )) -) diff --git a/misc/sampleconfigs/autohotspot.service.stretch-default2-Hotspot.sample b/misc/sampleconfigs/autohotspot.service.stretch-default2-Hotspot.sample index 743fba2d4..1e6ccc5fd 100755 --- a/misc/sampleconfigs/autohotspot.service.stretch-default2-Hotspot.sample +++ b/misc/sampleconfigs/autohotspot.service.stretch-default2-Hotspot.sample @@ -4,6 +4,6 @@ After=multi-user.target [Service] Type=oneshot RemainAfterExit=yes -ExecStart=/usr/bin/autohotspot +ExecStart=%AUTOHOTSPOT_SCRIPT% [Install] -WantedBy=multi-user.target \ No newline at end of file +WantedBy=multi-user.target diff --git a/misc/sampleconfigs/autohotspot.sh.stretch-default2-Hotspot.sample b/misc/sampleconfigs/autohotspot.sh.stretch-default2-Hotspot.sample new file mode 100644 index 000000000..cdb56bad6 --- /dev/null +++ b/misc/sampleconfigs/autohotspot.sh.stretch-default2-Hotspot.sample @@ -0,0 +1,219 @@ +#!/bin/bash +#version 0.962-N/HS + +#You may share this script on the condition all references to RaspberryConnect.com +#must be included in copies or derivatives of this script. + +#A script to switch between a wifi network and a non internet routed Hotspot +#Works at startup or with a seperate timer or manually without a reboot +#Other setup required find out more at +#http://www.raspberryconnect.com + +#Additions where made for the Phoniebox project +#https://github.com/MiczFlor/RPi-Jukebox-RFID + +if [ $# -gt 0 ] ; then + if [ $# -eq 1 ] && [ "$1" == "--force-hotspot" ]; then + FORCE_HOTSPOT=1 + else + echo "ignoring unrecognized parameter: $*" + fi +fi + +NO_SSID='NoSSid' +ssidChk="$NO_SSID" + +wifidev="wlan0" #device name to use. Default is wlan0. +#use the command: iw dev ,to see wifi interface name + +IFSdef=$IFS +cnt=0 +#These four lines capture the wifi networks the RPi is setup to use +wpassid=$(awk '/ssid="/{ print $0 }' /etc/wpa_supplicant/wpa_supplicant.conf | awk -F'ssid=' '{ print $2 }' | sed 's/\r//g'| awk 'BEGIN{ORS=","} {print}' | sed 's/\"/''/g' | sed 's/,$//') +IFS="," +ssids=($wpassid) +IFS=$IFSdef #reset back to defaults + + +#Note:If you only want to check for certain SSIDs +#Remove the # in in front of ssids=('mySSID1'.... below and put a # infront of all four lines above +# separated by a space, eg ('mySSID1' 'mySSID2') +#ssids=('mySSID1' 'mySSID2' 'mySSID3') + +#Enter the Routers Mac Addresses for hidden SSIDs, seperated by spaces ie +#( '11:22:33:44:55:66' 'aa:bb:cc:dd:ee:ff' ) +mac=() + +ssidsmac=("${ssids[@]}" "${mac[@]}") #combines ssid and MAC for checking + +CreateAdHocNetwork() +{ + echo "Creating Hotspot" + ip link set dev "$wifidev" down + ip a add %AUTOHOTSPOT_IP%/24 brd + dev "$wifidev" + ip link set dev "$wifidev" up + dhcpcd -k "$wifidev" >/dev/null 2>&1 + systemctl start dnsmasq + systemctl start hostapd +} + +KillHotspot() +{ + echo "Shutting Down Hotspot" + ip link set dev "$wifidev" down + systemctl stop hostapd + systemctl stop dnsmasq + ip addr flush dev "$wifidev" + ip link set dev "$wifidev" up + dhcpcd -n "$wifidev" >/dev/null 2>&1 +} + +CheckWifiUp() +{ + echo "Checking WiFi connection ok" + sleep 20 #give time for connection to be completed to router + if ! wpa_cli -i "$wifidev" status | grep 'ip_address' >/dev/null 2>&1 + then #Failed to connect to wifi (check your wifi settings, password etc) + echo 'Wifi failed to connect, falling back to Hotspot.' + wpa_cli terminate "$wifidev" >/dev/null 2>&1 + CreateAdHocNetwork + fi +} + +InitWPA() { + wpa_supplicant -B -i "$wifidev" -c /etc/wpa_supplicant/wpa_supplicant.conf >/dev/null 2>&1 +} + +CheckServices() +{ + #After some system updates hostapd gets masked using Raspbian Buster, and above. This checks and fixes + #the issue and also checks dnsmasq is ok so the hotspot can be generated. + #Check Hostapd is unmasked and disabled + if (systemctl -all list-unit-files hostapd.service | grep "hostapd.service masked") >/dev/null 2>&1 ;then + systemctl unmask hostapd.service >/dev/null 2>&1 + fi + if (systemctl -all list-unit-files hostapd.service | grep "hostapd.service enabled") >/dev/null 2>&1 ;then + systemctl disable hostapd.service >/dev/null 2>&1 + systemctl stop hostapd >/dev/null 2>&1 + fi + #Check dnsmasq is disabled + if (systemctl -all list-unit-files dnsmasq.service | grep "dnsmasq.service masked") >/dev/null 2>&1 ;then + systemctl unmask dnsmasq >/dev/null 2>&1 + fi + if (systemctl -all list-unit-files dnsmasq.service | grep "dnsmasq.service enabled") >/dev/null 2>&1 ;then + systemctl disable dnsmasq >/dev/null 2>&1 + systemctl stop dnsmasq >/dev/null 2>&1 + fi +} + +CheckDevice() +{ + local j=0 + while [ true ] #wait for wifi if busy, usb wifi is slower. + do + echo "Device availability check: try $j" + if [ $j -ge 5 ]; then + #if no wifi device,ie usb wifi removed, activate wifi so when it is + #reconnected wifi to a router will be available + echo "No wifi device connected" + InitWPA + exit 1 + elif (iw dev "$wifidev" info 2>&1 >/dev/null) ; then + echo "wifi device available" + if (rfkill list wifi -rno HARD,SOFT | grep -i "unblocked.*unblocked") >/dev/null 2>&1 ; then + local wifidev_up=$(ip link show "$wifidev" up) + if [ -z "$wifidev_up" ]; then + echo "wifi is down. setting up" + ip link set dev "$wifidev" up + sleep 2 + fi + return + else + echo "wifi is deactivated" + exit 0 + fi + else + j=$((j + 1)) + sleep 2 + fi + done +} + +FindSSID() +{ + if [ -n "$FORCE_HOTSPOT" ]; then return; fi + + #Check to see what SSID's and MAC addresses are in range + local i=0; j=0 + while [ $i -eq 0 ] + do + scanreply=$(iw dev "$wifidev" scan ap-force 2>&1) + ssidreply=$(echo "$scanreply" | egrep "^BSS|SSID:") + echo "SSID availability check: try $j" + if [ $j -ge 5 ]; then + ssidreply="" + i=1 + elif [ -z "$ssidreply" ] ; then + echo "Error scan SSID's: $scanreply" + j=$((j + 1)) + sleep 2 + else + echo "SSID's in range:" + echo "$ssidreply" + i=1 + fi + done + + for ssid in "${ssidsmac[@]}" + do + if (echo "$ssidreply" | grep "$ssid") >/dev/null 2>&1 + then + #Valid SSid found, passing to script + echo "Valid SSID Detected, assesing Wifi status" + ssidChk=$ssid + return 0 + fi + done +} + +CheckSSID() +{ + #Create Hotspot or connect to valid wifi networks + if [ "$ssidChk" != "$NO_SSID" ] + then + if systemctl status hostapd | grep "(running)" >/dev/null 2>&1 + then #hotspot running and ssid in range + KillHotspot + echo "Hotspot Deactivated, Bringing Wifi Up" + InitWPA + CheckWifiUp + elif { wpa_cli -i "$wifidev" status | grep 'ip_address'; } >/dev/null 2>&1 + then #Already connected + echo "Wifi already connected to a network" + else #ssid exists and no hotspot running connect to wifi network + echo "Connecting to the WiFi Network" + InitWPA + CheckWifiUp + fi + else #ssid or MAC address not in range + if systemctl status hostapd | grep "(running)" >/dev/null 2>&1 + then + echo "Hostspot already active" + elif { wpa_cli status | grep "$wifidev"; } >/dev/null 2>&1 + then + echo "Cleaning wifi files and Activating Hotspot" + wpa_cli terminate >/dev/null 2>&1 + ip addr flush "$wifidev" + ip link set dev "$wifidev" down + rm -r /var/run/wpa_supplicant >/dev/null 2>&1 + CreateAdHocNetwork + else #"No SSID, activating Hotspot" + CreateAdHocNetwork + fi + fi +} + +CheckServices +CheckDevice +FindSSID +CheckSSID diff --git a/misc/sampleconfigs/autohotspot.stretch-default2-Hotspot.sample b/misc/sampleconfigs/autohotspot.stretch-default2-Hotspot.sample deleted file mode 100755 index ad63e4665..000000000 --- a/misc/sampleconfigs/autohotspot.stretch-default2-Hotspot.sample +++ /dev/null @@ -1,164 +0,0 @@ -#!/bin/bash -#version 0.95-4-N/HS - -#You may share this script on the condition a reference to RaspberryConnect.com -#must be included in copies or derivatives of this script. - -#A script to switch between a wifi network and a non internet routed Hotspot -#Works at startup or with a seperate timer or manually without a reboot -#Other setup required find out more at -#http://www.raspberryconnect.com - -wifidev="wlan0" #device name to use. Default is wlan0. -#use the command: iw dev ,to see wifi interface name - -IFSdef=$IFS -cnt=0 -#These four lines capture the wifi networks the RPi is setup to use -wpassid=$(awk '/ssid="/{ print $0 }' /etc/wpa_supplicant/wpa_supplicant.conf | awk -F'ssid=' '{ print $2 }' ORS=',' | sed 's/\"/''/g' | sed 's/,$//') -IFS="," -ssids=($wpassid) -IFS=$IFSdef #reset back to defaults - - -#Note:If you only want to check for certain SSIDs -#Remove the # in in front of ssids=('mySSID1'.... below and put a # infront of all four lines above -# separated by a space, eg ('mySSID1' 'mySSID2') -#ssids=('mySSID1' 'mySSID2' 'mySSID3') - -#Enter the Routers Mac Addresses for hidden SSIDs, seperated by spaces ie -#( '11:22:33:44:55:66' 'aa:bb:cc:dd:ee:ff' ) -mac=() - -ssidsmac=("${ssids[@]}" "${mac[@]}") #combines ssid and MAC for checking - -createAdHocNetwork() -{ - echo "Creating Hotspot" - ip link set dev "$wifidev" down - ip a add 10.0.0.10/24 brd + dev "$wifidev" - ip link set dev "$wifidev" up - dhcpcd -k "$wifidev" >/dev/null 2>&1 - systemctl start dnsmasq - systemctl start hostapd -} - -KillHotspot() -{ - echo "Shutting Down Hotspot" - ip link set dev "$wifidev" down - systemctl stop hostapd - systemctl stop dnsmasq - ip addr flush dev "$wifidev" - ip link set dev "$wifidev" up - dhcpcd -n "$wifidev" >/dev/null 2>&1 -} - -ChkWifiUp() -{ - echo "Checking WiFi connection ok" - sleep 20 #give time for connection to be completed to router - if ! wpa_cli -i "$wifidev" status | grep 'ip_address' >/dev/null 2>&1 - then #Failed to connect to wifi (check your wifi settings, password etc) - echo 'Wifi failed to connect, falling back to Hotspot.' - wpa_cli terminate "$wifidev" >/dev/null 2>&1 - createAdHocNetwork - fi -} - - -FindSSID() -{ -#Check to see what SSID's and MAC addresses are in range -ssidChk=('NoSSid') -i=0; j=0 -until [ $i -eq 1 ] #wait for wifi if busy, usb wifi is slower. -do - ssidreply=$((iw dev "$wifidev" scan ap-force | egrep "^BSS|SSID:") 2>&1) >/dev/null 2>&1 - echo "SSid's in range: " $ssidreply - echo "Device Available Check try " $j - if (($j >= 10)); then #if busy 10 times goto hotspot - echo "Device busy or unavailable 10 times, going to Hotspot" - ssidreply="" - i=1 - elif echo "$ssidreply" | grep "No such device (-19)" >/dev/null 2>&1; then - echo "No Device Reported, try " $j - NoDevice - elif echo "$ssidreply" | grep "Network is down (-100)" >/dev/null 2>&1 ; then - echo "Network Not available, trying again" $j - j=$((j + 1)) - sleep 2 - elif echo "$ssidreplay" | grep "Read-only file system (-30)" >/dev/null 2>&1 ; then - echo "Temporary Read only file system, trying again" - j=$((j + 1)) - sleep 2 - elif ! echo "$ssidreply" | grep "resource busy (-16)" >/dev/null 2>&1 ; then - echo "Device Available, checking SSid Results" - i=1 - else #see if device not busy in 2 seconds - echo "Device unavailable checking again, try " $j - j=$((j + 1)) - sleep 2 - fi -done - -for ssid in "${ssidsmac[@]}" -do - if (echo "$ssidreply" | grep "$ssid") >/dev/null 2>&1 - then - #Valid SSid found, passing to script - echo "Valid SSID Detected, assesing Wifi status" - ssidChk=$ssid - return 0 - else - #No Network found, NoSSid issued" - echo "No SSid found, assessing WiFi status" - ssidChk='NoSSid' - fi -done -} - -NoDevice() -{ - #if no wifi device,ie usb wifi removed, activate wifi so when it is - #reconnected wifi to a router will be available - echo "No wifi device connected" - wpa_supplicant -B -i "$wifidev" -c /etc/wpa_supplicant/wpa_supplicant.conf >/dev/null 2>&1 - exit 1 -} - -FindSSID - -#Create Hotspot or connect to valid wifi networks -if [ "$ssidChk" != "NoSSid" ] -then - if systemctl status hostapd | grep "(running)" >/dev/null 2>&1 - then #hotspot running and ssid in range - KillHotspot - echo "Hotspot Deactivated, Bringing Wifi Up" - wpa_supplicant -B -i "$wifidev" -c /etc/wpa_supplicant/wpa_supplicant.conf >/dev/null 2>&1 - ChkWifiUp - elif { wpa_cli -i "$wifidev" status | grep 'ip_address'; } >/dev/null 2>&1 - then #Already connected - echo "Wifi already connected to a network" - else #ssid exists and no hotspot running connect to wifi network - echo "Connecting to the WiFi Network" - wpa_supplicant -B -i "$wifidev" -c /etc/wpa_supplicant/wpa_supplicant.conf >/dev/null 2>&1 - ChkWifiUp - fi -else #ssid or MAC address not in range - if systemctl status hostapd | grep "(running)" >/dev/null 2>&1 - then - echo "Hostspot already active" - elif { wpa_cli status | grep "$wifidev"; } >/dev/null 2>&1 - then - echo "Cleaning wifi files and Activating Hotspot" - wpa_cli terminate >/dev/null 2>&1 - ip addr flush "$wifidev" - ip link set dev "$wifidev" down - rm -r /var/run/wpa_supplicant >/dev/null 2>&1 - createAdHocNetwork - else #"No SSID, activating Hotspot" - createAdHocNetwork - fi -fi \ No newline at end of file diff --git a/misc/sampleconfigs/dhcpcd.conf.jessie-WlanAP.sample b/misc/sampleconfigs/dhcpcd.conf.jessie-WlanAP.sample deleted file mode 100755 index 8e47989b3..000000000 --- a/misc/sampleconfigs/dhcpcd.conf.jessie-WlanAP.sample +++ /dev/null @@ -1,48 +0,0 @@ -# A sample configuration for dhcpcd. -# See dhcpcd.conf(5) for details. - -# Allow users of this group to interact with dhcpcd via the control socket. -#controlgroup wheel - -# Inform the DHCP server of our hostname for DDNS. -hostname - -# Use the hardware address of the interface for the Client ID. -clientid -# or -# Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361. -#duid - -# Persist interface configuration when dhcpcd exits. -persistent - -# Rapid commit support. -# Safe to enable by default because it requires the equivalent option set -# on the server to actually work. -option rapid_commit - -# A list of options to request from the DHCP server. -option domain_name_servers, domain_name, domain_search, host_name -option classless_static_routes -# Most distributions have NTP support. -option ntp_servers -# Respect the network MTU. -# Some interface drivers reset when changing the MTU so disabled by default. -#option interface_mtu - -# A ServerID is required by RFC2131. -require dhcp_server_identifier - -# Generate Stable Private IPv6 Addresses instead of hardware based ones -slaac private - -# A hook script is provided to lookup the hostname if not set by the DHCP -# server, but it should not be run by default. -nohook lookup-hostname - -interface wlan0 -static ip_address=192.168.178.198/24 -static routers=192.168.178.1 -static domain_name_servers=192.168.178.1 - -denyinterfaces wlan0 diff --git a/misc/sampleconfigs/dhcpcd.conf.jessie-default.sample b/misc/sampleconfigs/dhcpcd.conf.jessie-default.sample deleted file mode 100755 index 94eaca6b5..000000000 --- a/misc/sampleconfigs/dhcpcd.conf.jessie-default.sample +++ /dev/null @@ -1,46 +0,0 @@ -# A sample configuration for dhcpcd. -# See dhcpcd.conf(5) for details. - -# Allow users of this group to interact with dhcpcd via the control socket. -#controlgroup wheel - -# Inform the DHCP server of our hostname for DDNS. -hostname - -# Use the hardware address of the interface for the Client ID. -clientid -# or -# Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361. -#duid - -# Persist interface configuration when dhcpcd exits. -persistent - -# Rapid commit support. -# Safe to enable by default because it requires the equivalent option set -# on the server to actually work. -option rapid_commit - -# A list of options to request from the DHCP server. -option domain_name_servers, domain_name, domain_search, host_name -option classless_static_routes -# Most distributions have NTP support. -option ntp_servers -# Respect the network MTU. -# Some interface drivers reset when changing the MTU so disabled by default. -#option interface_mtu - -# A ServerID is required by RFC2131. -require dhcp_server_identifier - -# Generate Stable Private IPv6 Addresses instead of hardware based ones -slaac private - -# A hook script is provided to lookup the hostname if not set by the DHCP -# server, but it should not be run by default. -nohook lookup-hostname - -interface wlan0 -static ip_address=192.168.178.199/24 -static routers=192.168.178.1 -static domain_name_servers=192.168.178.1 diff --git a/misc/sampleconfigs/dhcpcd.conf.stretch-default.sample b/misc/sampleconfigs/dhcpcd.conf.stretch-default.sample deleted file mode 100755 index ee79f1a50..000000000 --- a/misc/sampleconfigs/dhcpcd.conf.stretch-default.sample +++ /dev/null @@ -1,4 +0,0 @@ -interface wlan0 -static ip_address=192.168.178.201/24 -static routers=192.168.178.1 -static domain_name_servers=192.168.178.1 diff --git a/misc/sampleconfigs/dhcpcd.conf.stretch-default2-Hotspot.sample b/misc/sampleconfigs/dhcpcd.conf.stretch-default2-Hotspot.sample deleted file mode 100755 index 5f4f95569..000000000 --- a/misc/sampleconfigs/dhcpcd.conf.stretch-default2-Hotspot.sample +++ /dev/null @@ -1,5 +0,0 @@ -interface wlan0 -static ip_address=%WIFIip%/24 -static routers=%WIFIipRouter% -static domain_name_servers=8.8.8.8 %WIFIipRouter% -nohook wpa_supplicant \ No newline at end of file diff --git a/misc/sampleconfigs/dhcpcd.conf.stretch-default2-noHotspot.sample b/misc/sampleconfigs/dhcpcd.conf.stretch-default2-noHotspot.sample deleted file mode 100755 index f00ed04f4..000000000 --- a/misc/sampleconfigs/dhcpcd.conf.stretch-default2-noHotspot.sample +++ /dev/null @@ -1,4 +0,0 @@ -interface wlan0 -static ip_address=%WIFIip%/24 -static routers=%WIFIipRouter% -static domain_name_servers=8.8.8.8 %WIFIipRouter% diff --git a/misc/sampleconfigs/dnsmasq.conf.jessie-WlanAP.sample b/misc/sampleconfigs/dnsmasq.conf.jessie-WlanAP.sample deleted file mode 100755 index d12324f0b..000000000 --- a/misc/sampleconfigs/dnsmasq.conf.jessie-WlanAP.sample +++ /dev/null @@ -1,655 +0,0 @@ -# Configuration file for dnsmasq. -# -# Format is one option per line, legal options are the same -# as the long options legal on the command line. See -# "/usr/sbin/dnsmasq --help" or "man 8 dnsmasq" for details. - -# Listen on this specific port instead of the standard DNS port -# (53). Setting this to zero completely disables DNS function, -# leaving only DHCP and/or TFTP. -#port=5353 - -# The following two options make you a better netizen, since they -# tell dnsmasq to filter out queries which the public DNS cannot -# answer, and which load the servers (especially the root servers) -# unnecessarily. If you have a dial-on-demand link they also stop -# these requests from bringing up the link unnecessarily. - -# Never forward plain names (without a dot or domain part) -#domain-needed -# Never forward addresses in the non-routed address spaces. -#bogus-priv - -# Uncomment these to enable DNSSEC validation and caching: -# (Requires dnsmasq to be built with DNSSEC option.) -#conf-file=%%PREFIX%%/share/dnsmasq/trust-anchors.conf -#dnssec - -# Replies which are not DNSSEC signed may be legitimate, because the domain -# is unsigned, or may be forgeries. Setting this option tells dnsmasq to -# check that an unsigned reply is OK, by finding a secure proof that a DS -# record somewhere between the root and the domain does not exist. -# The cost of setting this is that even queries in unsigned domains will need -# one or more extra DNS queries to verify. -#dnssec-check-unsigned - -# Uncomment this to filter useless windows-originated DNS requests -# which can trigger dial-on-demand links needlessly. -# Note that (amongst other things) this blocks all SRV requests, -# so don't use it if you use eg Kerberos, SIP, XMMP or Google-talk. -# This option only affects forwarding, SRV records originating for -# dnsmasq (via srv-host= lines) are not suppressed by it. -#filterwin2k - -# Change this line if you want dns to get its upstream servers from -# somewhere other that /etc/resolv.conf -#resolv-file= - -# By default, dnsmasq will send queries to any of the upstream -# servers it knows about and tries to favour servers to are known -# to be up. Uncommenting this forces dnsmasq to try each query -# with each server strictly in the order they appear in -# /etc/resolv.conf -#strict-order - -# If you don't want dnsmasq to read /etc/resolv.conf or any other -# file, getting its servers from this file instead (see below), then -# uncomment this. -#no-resolv - -# If you don't want dnsmasq to poll /etc/resolv.conf or other resolv -# files for changes and re-read them then uncomment this. -#no-poll - -# Add other name servers here, with domain specs if they are for -# non-public domains. -#server=/localnet/192.168.0.1 - -# Example of routing PTR queries to nameservers: this will send all -# address->name queries for 192.168.3/24 to nameserver 10.1.2.3 -#server=/3.168.192.in-addr.arpa/10.1.2.3 - -# Add local-only domains here, queries in these domains are answered -# from /etc/hosts or DHCP only. -#local=/localnet/ - -# Add domains which you want to force to an IP address here. -# The example below send any host in double-click.net to a local -# web-server. -#address=/double-click.net/127.0.0.1 - -# --address (and --server) work with IPv6 addresses too. -#address=/www.thekelleys.org.uk/fe80::20d:60ff:fe36:f83 - -# Add the IPs of all queries to yahoo.com, google.com, and their -# subdomains to the vpn and search ipsets: -#ipset=/yahoo.com/google.com/vpn,search - -# You can control how dnsmasq talks to a server: this forces -# queries to 10.1.2.3 to be routed via eth1 -# server=10.1.2.3@eth1 - -# and this sets the source (ie local) address used to talk to -# 10.1.2.3 to 192.168.1.1 port 55 (there must be a interface with that -# IP on the machine, obviously). -# server=10.1.2.3@192.168.1.1#55 - -# If you want dnsmasq to change uid and gid to something other -# than the default, edit the following lines. -#user= -#group= - -# If you want dnsmasq to listen for DHCP and DNS requests only on -# specified interfaces (and the loopback) give the name of the -# interface (eg eth0) here. -# Repeat the line for more than one interface. -#interface= -# Or you can specify which interface _not_ to listen on -#except-interface= -# Or which to listen on by address (remember to include 127.0.0.1 if -# you use this.) -#listen-address= -# If you want dnsmasq to provide only DNS service on an interface, -# configure it as shown above, and then use the following line to -# disable DHCP and TFTP on it. -#no-dhcp-interface= - -# On systems which support it, dnsmasq binds the wildcard address, -# even when it is listening on only some interfaces. It then discards -# requests that it shouldn't reply to. This has the advantage of -# working even when interfaces come and go and change address. If you -# want dnsmasq to really bind only the interfaces it is listening on, -# uncomment this option. About the only time you may need this is when -# running another nameserver on the same machine. -#bind-interfaces - -# If you don't want dnsmasq to read /etc/hosts, uncomment the -# following line. -#no-hosts -# or if you want it to read another file, as well as /etc/hosts, use -# this. -#addn-hosts=/etc/banner_add_hosts - -# Set this (and domain: see below) if you want to have a domain -# automatically added to simple names in a hosts-file. -#expand-hosts - -# Set the domain for dnsmasq. this is optional, but if it is set, it -# does the following things. -# 1) Allows DHCP hosts to have fully qualified domain names, as long -# as the domain part matches this setting. -# 2) Sets the "domain" DHCP option thereby potentially setting the -# domain of all systems configured by DHCP -# 3) Provides the domain part for "expand-hosts" -#domain=thekelleys.org.uk - -# Set a different domain for a particular subnet -#domain=wireless.thekelleys.org.uk,192.168.2.0/24 - -# Same idea, but range rather then subnet -#domain=reserved.thekelleys.org.uk,192.68.3.100,192.168.3.200 - -# Uncomment this to enable the integrated DHCP server, you need -# to supply the range of addresses available for lease and optionally -# a lease time. If you have more than one network, you will need to -# repeat this for each network on which you want to supply DHCP -# service. -#dhcp-range=192.168.0.50,192.168.0.150,12h - -# This is an example of a DHCP range where the netmask is given. This -# is needed for networks we reach the dnsmasq DHCP server via a relay -# agent. If you don't know what a DHCP relay agent is, you probably -# don't need to worry about this. -#dhcp-range=192.168.0.50,192.168.0.150,255.255.255.0,12h - -# This is an example of a DHCP range which sets a tag, so that -# some DHCP options may be set only for this network. -#dhcp-range=set:red,192.168.0.50,192.168.0.150 - -# Use this DHCP range only when the tag "green" is set. -#dhcp-range=tag:green,192.168.0.50,192.168.0.150,12h - -# Specify a subnet which can't be used for dynamic address allocation, -# is available for hosts with matching --dhcp-host lines. Note that -# dhcp-host declarations will be ignored unless there is a dhcp-range -# of some type for the subnet in question. -# In this case the netmask is implied (it comes from the network -# configuration on the machine running dnsmasq) it is possible to give -# an explicit netmask instead. -#dhcp-range=192.168.0.0,static - -# Enable DHCPv6. Note that the prefix-length does not need to be specified -# and defaults to 64 if missing/ -#dhcp-range=1234::2, 1234::500, 64, 12h - -# Do Router Advertisements, BUT NOT DHCP for this subnet. -#dhcp-range=1234::, ra-only - -# Do Router Advertisements, BUT NOT DHCP for this subnet, also try and -# add names to the DNS for the IPv6 address of SLAAC-configured dual-stack -# hosts. Use the DHCPv4 lease to derive the name, network segment and -# MAC address and assume that the host will also have an -# IPv6 address calculated using the SLAAC alogrithm. -#dhcp-range=1234::, ra-names - -# Do Router Advertisements, BUT NOT DHCP for this subnet. -# Set the lifetime to 46 hours. (Note: minimum lifetime is 2 hours.) -#dhcp-range=1234::, ra-only, 48h - -# Do DHCP and Router Advertisements for this subnet. Set the A bit in the RA -# so that clients can use SLAAC addresses as well as DHCP ones. -#dhcp-range=1234::2, 1234::500, slaac - -# Do Router Advertisements and stateless DHCP for this subnet. Clients will -# not get addresses from DHCP, but they will get other configuration information. -# They will use SLAAC for addresses. -#dhcp-range=1234::, ra-stateless - -# Do stateless DHCP, SLAAC, and generate DNS names for SLAAC addresses -# from DHCPv4 leases. -#dhcp-range=1234::, ra-stateless, ra-names - -# Do router advertisements for all subnets where we're doing DHCPv6 -# Unless overriden by ra-stateless, ra-names, et al, the router -# advertisements will have the M and O bits set, so that the clients -# get addresses and configuration from DHCPv6, and the A bit reset, so the -# clients don't use SLAAC addresses. -#enable-ra - -# Supply parameters for specified hosts using DHCP. There are lots -# of valid alternatives, so we will give examples of each. Note that -# IP addresses DO NOT have to be in the range given above, they just -# need to be on the same network. The order of the parameters in these -# do not matter, it's permissible to give name, address and MAC in any -# order. - -# Always allocate the host with Ethernet address 11:22:33:44:55:66 -# The IP address 192.168.0.60 -#dhcp-host=11:22:33:44:55:66,192.168.0.60 - -# Always set the name of the host with hardware address -# 11:22:33:44:55:66 to be "fred" -#dhcp-host=11:22:33:44:55:66,fred - -# Always give the host with Ethernet address 11:22:33:44:55:66 -# the name fred and IP address 192.168.0.60 and lease time 45 minutes -#dhcp-host=11:22:33:44:55:66,fred,192.168.0.60,45m - -# Give a host with Ethernet address 11:22:33:44:55:66 or -# 12:34:56:78:90:12 the IP address 192.168.0.60. Dnsmasq will assume -# that these two Ethernet interfaces will never be in use at the same -# time, and give the IP address to the second, even if it is already -# in use by the first. Useful for laptops with wired and wireless -# addresses. -#dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.60 - -# Give the machine which says its name is "bert" IP address -# 192.168.0.70 and an infinite lease -#dhcp-host=bert,192.168.0.70,infinite - -# Always give the host with client identifier 01:02:02:04 -# the IP address 192.168.0.60 -#dhcp-host=id:01:02:02:04,192.168.0.60 - -# Always give the host with client identifier "marjorie" -# the IP address 192.168.0.60 -#dhcp-host=id:marjorie,192.168.0.60 - -# Enable the address given for "judge" in /etc/hosts -# to be given to a machine presenting the name "judge" when -# it asks for a DHCP lease. -#dhcp-host=judge - -# Never offer DHCP service to a machine whose Ethernet -# address is 11:22:33:44:55:66 -#dhcp-host=11:22:33:44:55:66,ignore - -# Ignore any client-id presented by the machine with Ethernet -# address 11:22:33:44:55:66. This is useful to prevent a machine -# being treated differently when running under different OS's or -# between PXE boot and OS boot. -#dhcp-host=11:22:33:44:55:66,id:* - -# Send extra options which are tagged as "red" to -# the machine with Ethernet address 11:22:33:44:55:66 -#dhcp-host=11:22:33:44:55:66,set:red - -# Send extra options which are tagged as "red" to -# any machine with Ethernet address starting 11:22:33: -#dhcp-host=11:22:33:*:*:*,set:red - -# Give a fixed IPv6 address and name to client with -# DUID 00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2 -# Note the MAC addresses CANNOT be used to identify DHCPv6 clients. -# Note also the they [] around the IPv6 address are obilgatory. -#dhcp-host=id:00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2, fred, [1234::5] - -# Ignore any clients which are not specified in dhcp-host lines -# or /etc/ethers. Equivalent to ISC "deny unknown-clients". -# This relies on the special "known" tag which is set when -# a host is matched. -#dhcp-ignore=tag:!known - -# Send extra options which are tagged as "red" to any machine whose -# DHCP vendorclass string includes the substring "Linux" -#dhcp-vendorclass=set:red,Linux - -# Send extra options which are tagged as "red" to any machine one -# of whose DHCP userclass strings includes the substring "accounts" -#dhcp-userclass=set:red,accounts - -# Send extra options which are tagged as "red" to any machine whose -# MAC address matches the pattern. -#dhcp-mac=set:red,00:60:8C:*:*:* - -# If this line is uncommented, dnsmasq will read /etc/ethers and act -# on the ethernet-address/IP pairs found there just as if they had -# been given as --dhcp-host options. Useful if you keep -# MAC-address/host mappings there for other purposes. -#read-ethers - -# Send options to hosts which ask for a DHCP lease. -# See RFC 2132 for details of available options. -# Common options can be given to dnsmasq by name: -# run "dnsmasq --help dhcp" to get a list. -# Note that all the common settings, such as netmask and -# broadcast address, DNS server and default route, are given -# sane defaults by dnsmasq. You very likely will not need -# any dhcp-options. If you use Windows clients and Samba, there -# are some options which are recommended, they are detailed at the -# end of this section. - -# Override the default route supplied by dnsmasq, which assumes the -# router is the same machine as the one running dnsmasq. -#dhcp-option=3,1.2.3.4 - -# Do the same thing, but using the option name -#dhcp-option=option:router,1.2.3.4 - -# Override the default route supplied by dnsmasq and send no default -# route at all. Note that this only works for the options sent by -# default (1, 3, 6, 12, 28) the same line will send a zero-length option -# for all other option numbers. -#dhcp-option=3 - -# Set the NTP time server addresses to 192.168.0.4 and 10.10.0.5 -#dhcp-option=option:ntp-server,192.168.0.4,10.10.0.5 - -# Send DHCPv6 option. Note [] around IPv6 addresses. -#dhcp-option=option6:dns-server,[1234::77],[1234::88] - -# Send DHCPv6 option for namservers as the machine running -# dnsmasq and another. -#dhcp-option=option6:dns-server,[::],[1234::88] - -# Ask client to poll for option changes every six hours. (RFC4242) -#dhcp-option=option6:information-refresh-time,6h - -# Set the NTP time server address to be the same machine as -# is running dnsmasq -#dhcp-option=42,0.0.0.0 - -# Set the NIS domain name to "welly" -#dhcp-option=40,welly - -# Set the default time-to-live to 50 -#dhcp-option=23,50 - -# Set the "all subnets are local" flag -#dhcp-option=27,1 - -# Send the etherboot magic flag and then etherboot options (a string). -#dhcp-option=128,e4:45:74:68:00:00 -#dhcp-option=129,NIC=eepro100 - -# Specify an option which will only be sent to the "red" network -# (see dhcp-range for the declaration of the "red" network) -# Note that the tag: part must precede the option: part. -#dhcp-option = tag:red, option:ntp-server, 192.168.1.1 - -# The following DHCP options set up dnsmasq in the same way as is specified -# for the ISC dhcpcd in -# http://www.samba.org/samba/ftp/docs/textdocs/DHCP-Server-Configuration.txt -# adapted for a typical dnsmasq installation where the host running -# dnsmasq is also the host running samba. -# you may want to uncomment some or all of them if you use -# Windows clients and Samba. -#dhcp-option=19,0 # option ip-forwarding off -#dhcp-option=44,0.0.0.0 # set netbios-over-TCP/IP nameserver(s) aka WINS server(s) -#dhcp-option=45,0.0.0.0 # netbios datagram distribution server -#dhcp-option=46,8 # netbios node type - -# Send an empty WPAD option. This may be REQUIRED to get windows 7 to behave. -#dhcp-option=252,"\n" - -# Send RFC-3397 DNS domain search DHCP option. WARNING: Your DHCP client -# probably doesn't support this...... -#dhcp-option=option:domain-search,eng.apple.com,marketing.apple.com - -# Send RFC-3442 classless static routes (note the netmask encoding) -#dhcp-option=121,192.168.1.0/24,1.2.3.4,10.0.0.0/8,5.6.7.8 - -# Send vendor-class specific options encapsulated in DHCP option 43. -# The meaning of the options is defined by the vendor-class so -# options are sent only when the client supplied vendor class -# matches the class given here. (A substring match is OK, so "MSFT" -# matches "MSFT" and "MSFT 5.0"). This example sets the -# mtftp address to 0.0.0.0 for PXEClients. -#dhcp-option=vendor:PXEClient,1,0.0.0.0 - -# Send microsoft-specific option to tell windows to release the DHCP lease -# when it shuts down. Note the "i" flag, to tell dnsmasq to send the -# value as a four-byte integer - that's what microsoft wants. See -# http://technet2.microsoft.com/WindowsServer/en/library/a70f1bb7-d2d4-49f0-96d6-4b7414ecfaae1033.mspx?mfr=true -#dhcp-option=vendor:MSFT,2,1i - -# Send the Encapsulated-vendor-class ID needed by some configurations of -# Etherboot to allow is to recognise the DHCP server. -#dhcp-option=vendor:Etherboot,60,"Etherboot" - -# Send options to PXELinux. Note that we need to send the options even -# though they don't appear in the parameter request list, so we need -# to use dhcp-option-force here. -# See http://syslinux.zytor.com/pxe.php#special for details. -# Magic number - needed before anything else is recognised -#dhcp-option-force=208,f1:00:74:7e -# Configuration file name -#dhcp-option-force=209,configs/common -# Path prefix -#dhcp-option-force=210,/tftpboot/pxelinux/files/ -# Reboot time. (Note 'i' to send 32-bit value) -#dhcp-option-force=211,30i - -# Set the boot filename for netboot/PXE. You will only need -# this is you want to boot machines over the network and you will need -# a TFTP server; either dnsmasq's built in TFTP server or an -# external one. (See below for how to enable the TFTP server.) -#dhcp-boot=pxelinux.0 - -# The same as above, but use custom tftp-server instead machine running dnsmasq -#dhcp-boot=pxelinux,server.name,192.168.1.100 - -# Boot for Etherboot gPXE. The idea is to send two different -# filenames, the first loads gPXE, and the second tells gPXE what to -# load. The dhcp-match sets the gpxe tag for requests from gPXE. -#dhcp-match=set:gpxe,175 # gPXE sends a 175 option. -#dhcp-boot=tag:!gpxe,undionly.kpxe -#dhcp-boot=mybootimage - -# Encapsulated options for Etherboot gPXE. All the options are -# encapsulated within option 175 -#dhcp-option=encap:175, 1, 5b # priority code -#dhcp-option=encap:175, 176, 1b # no-proxydhcp -#dhcp-option=encap:175, 177, string # bus-id -#dhcp-option=encap:175, 189, 1b # BIOS drive code -#dhcp-option=encap:175, 190, user # iSCSI username -#dhcp-option=encap:175, 191, pass # iSCSI password - -# Test for the architecture of a netboot client. PXE clients are -# supposed to send their architecture as option 93. (See RFC 4578) -#dhcp-match=peecees, option:client-arch, 0 #x86-32 -#dhcp-match=itanics, option:client-arch, 2 #IA64 -#dhcp-match=hammers, option:client-arch, 6 #x86-64 -#dhcp-match=mactels, option:client-arch, 7 #EFI x86-64 - -# Do real PXE, rather than just booting a single file, this is an -# alternative to dhcp-boot. -#pxe-prompt="What system shall I netboot?" -# or with timeout before first available action is taken: -#pxe-prompt="Press F8 for menu.", 60 - -# Available boot services. for PXE. -#pxe-service=x86PC, "Boot from local disk" - -# Loads /pxelinux.0 from dnsmasq TFTP server. -#pxe-service=x86PC, "Install Linux", pxelinux - -# Loads /pxelinux.0 from TFTP server at 1.2.3.4. -# Beware this fails on old PXE ROMS. -#pxe-service=x86PC, "Install Linux", pxelinux, 1.2.3.4 - -# Use bootserver on network, found my multicast or broadcast. -#pxe-service=x86PC, "Install windows from RIS server", 1 - -# Use bootserver at a known IP address. -#pxe-service=x86PC, "Install windows from RIS server", 1, 1.2.3.4 - -# If you have multicast-FTP available, -# information for that can be passed in a similar way using options 1 -# to 5. See page 19 of -# http://download.intel.com/design/archives/wfm/downloads/pxespec.pdf - - -# Enable dnsmasq's built-in TFTP server -#enable-tftp - -# Set the root directory for files available via FTP. -#tftp-root=/var/ftpd - -# Make the TFTP server more secure: with this set, only files owned by -# the user dnsmasq is running as will be send over the net. -#tftp-secure - -# This option stops dnsmasq from negotiating a larger blocksize for TFTP -# transfers. It will slow things down, but may rescue some broken TFTP -# clients. -#tftp-no-blocksize - -# Set the boot file name only when the "red" tag is set. -#dhcp-boot=tag:red,pxelinux.red-net - -# An example of dhcp-boot with an external TFTP server: the name and IP -# address of the server are given after the filename. -# Can fail with old PXE ROMS. Overridden by --pxe-service. -#dhcp-boot=/var/ftpd/pxelinux.0,boothost,192.168.0.3 - -# If there are multiple external tftp servers having a same name -# (using /etc/hosts) then that name can be specified as the -# tftp_servername (the third option to dhcp-boot) and in that -# case dnsmasq resolves this name and returns the resultant IP -# addresses in round robin fasion. This facility can be used to -# load balance the tftp load among a set of servers. -#dhcp-boot=/var/ftpd/pxelinux.0,boothost,tftp_server_name - -# Set the limit on DHCP leases, the default is 150 -#dhcp-lease-max=150 - -# The DHCP server needs somewhere on disk to keep its lease database. -# This defaults to a sane location, but if you want to change it, use -# the line below. -#dhcp-leasefile=/var/lib/misc/dnsmasq.leases - -# Set the DHCP server to authoritative mode. In this mode it will barge in -# and take over the lease for any client which broadcasts on the network, -# whether it has a record of the lease or not. This avoids long timeouts -# when a machine wakes up on a new network. DO NOT enable this if there's -# the slightest chance that you might end up accidentally configuring a DHCP -# server for your campus/company accidentally. The ISC server uses -# the same option, and this URL provides more information: -# http://www.isc.org/files/auth.html -#dhcp-authoritative - -# Run an executable when a DHCP lease is created or destroyed. -# The arguments sent to the script are "add" or "del", -# then the MAC address, the IP address and finally the hostname -# if there is one. -#dhcp-script=/bin/echo - -# Set the cachesize here. -#cache-size=150 - -# If you want to disable negative caching, uncomment this. -#no-negcache - -# Normally responses which come from /etc/hosts and the DHCP lease -# file have Time-To-Live set as zero, which conventionally means -# do not cache further. If you are happy to trade lower load on the -# server for potentially stale date, you can set a time-to-live (in -# seconds) here. -#local-ttl= - -# If you want dnsmasq to detect attempts by Verisign to send queries -# to unregistered .com and .net hosts to its sitefinder service and -# have dnsmasq instead return the correct NXDOMAIN response, uncomment -# this line. You can add similar lines to do the same for other -# registries which have implemented wildcard A records. -#bogus-nxdomain=64.94.110.11 - -# If you want to fix up DNS results from upstream servers, use the -# alias option. This only works for IPv4. -# This alias makes a result of 1.2.3.4 appear as 5.6.7.8 -#alias=1.2.3.4,5.6.7.8 -# and this maps 1.2.3.x to 5.6.7.x -#alias=1.2.3.0,5.6.7.0,255.255.255.0 -# and this maps 192.168.0.10->192.168.0.40 to 10.0.0.10->10.0.0.40 -#alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0 - -# Change these lines if you want dnsmasq to serve MX records. - -# Return an MX record named "maildomain.com" with target -# servermachine.com and preference 50 -#mx-host=maildomain.com,servermachine.com,50 - -# Set the default target for MX records created using the localmx option. -#mx-target=servermachine.com - -# Return an MX record pointing to the mx-target for all local -# machines. -#localmx - -# Return an MX record pointing to itself for all local machines. -#selfmx - -# Change the following lines if you want dnsmasq to serve SRV -# records. These are useful if you want to serve ldap requests for -# Active Directory and other windows-originated DNS requests. -# See RFC 2782. -# You may add multiple srv-host lines. -# The fields are ,,,, -# If the domain part if missing from the name (so that is just has the -# service and protocol sections) then the domain given by the domain= -# config option is used. (Note that expand-hosts does not need to be -# set for this to work.) - -# A SRV record sending LDAP for the example.com domain to -# ldapserver.example.com port 389 -#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389 - -# A SRV record sending LDAP for the example.com domain to -# ldapserver.example.com port 389 (using domain=) -#domain=example.com -#srv-host=_ldap._tcp,ldapserver.example.com,389 - -# Two SRV records for LDAP, each with different priorities -#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389,1 -#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389,2 - -# A SRV record indicating that there is no LDAP server for the domain -# example.com -#srv-host=_ldap._tcp.example.com - -# The following line shows how to make dnsmasq serve an arbitrary PTR -# record. This is useful for DNS-SD. (Note that the -# domain-name expansion done for SRV records _does_not -# occur for PTR records.) -#ptr-record=_http._tcp.dns-sd-services,"New Employee Page._http._tcp.dns-sd-services" - -# Change the following lines to enable dnsmasq to serve TXT records. -# These are used for things like SPF and zeroconf. (Note that the -# domain-name expansion done for SRV records _does_not -# occur for TXT records.) - -#Example SPF. -#txt-record=example.com,"v=spf1 a -all" - -#Example zeroconf -#txt-record=_http._tcp.example.com,name=value,paper=A4 - -# Provide an alias for a "local" DNS name. Note that this _only_ works -# for targets which are names from DHCP or /etc/hosts. Give host -# "bert" another name, bertrand -#cname=bertand,bert - -# For debugging purposes, log each DNS query as it passes through -# dnsmasq. -#log-queries - -# Log lots of extra information about DHCP transactions. -#log-dhcp - -# Include another lot of configuration options. -#conf-file=/etc/dnsmasq.more.conf -#conf-dir=/etc/dnsmasq.d - -# interface which is active -interface=wlan0 - -# interface to ignore -no-dhcp-interface=eth0 - -# IPv4 addresses and lease time -dhcp-range=192.168.1.100,192.168.1.200,24h - -# DNS -dhcp-option=option:dns-server,192.168.1.1 - diff --git a/misc/sampleconfigs/dnsmasq.conf.stretch-default2-Hotspot.sample b/misc/sampleconfigs/dnsmasq.conf.stretch-default2-Hotspot.sample new file mode 100644 index 000000000..96674a303 --- /dev/null +++ b/misc/sampleconfigs/dnsmasq.conf.stretch-default2-Hotspot.sample @@ -0,0 +1,7 @@ +#AutoHotspot Config +#stop DNSmasq from using resolv.conf +no-resolv +#Interface to use +interface=wlan0 +bind-interfaces +dhcp-range=%IP_WITHOUT_LAST_SEGMENT%.100,%IP_WITHOUT_LAST_SEGMENT%.200,12h diff --git a/misc/sampleconfigs/hostapd.conf.jessie-WlanAP.sample b/misc/sampleconfigs/hostapd.conf.jessie-WlanAP.sample deleted file mode 100755 index 123287f10..000000000 --- a/misc/sampleconfigs/hostapd.conf.jessie-WlanAP.sample +++ /dev/null @@ -1,20 +0,0 @@ -# interface and driver -interface=wlan0 -#driver=nl80211 - -# WLAN-config -ssid=jukebox -channel=1 -hw_mode=g -ieee80211n=1 -ieee80211d=1 -country_code=DE -wmm_enabled=1 - -# WLAN-encryption -auth_algs=1 -wpa=2 -wpa_key_mgmt=WPA-PSK -rsn_pairwise=CCMP -wpa_passphrase=Pl4yM3N0w - diff --git a/misc/sampleconfigs/hostapd.conf.stretch-default2-Hotspot.sample b/misc/sampleconfigs/hostapd.conf.stretch-default2-Hotspot.sample index 3b2fadbbf..6b2195dc6 100755 --- a/misc/sampleconfigs/hostapd.conf.stretch-default2-Hotspot.sample +++ b/misc/sampleconfigs/hostapd.conf.stretch-default2-Hotspot.sample @@ -1,7 +1,7 @@ #2.4GHz setup wifi 80211 b,g,n interface=wlan0 driver=nl80211 -ssid=Phoniebox +ssid=%AUTOHOTSPOTssid% hw_mode=g channel=8 wmm_enabled=0 @@ -9,12 +9,12 @@ macaddr_acl=0 auth_algs=1 ignore_broadcast_ssid=0 wpa=2 -wpa_passphrase=PlayItLoud +wpa_passphrase=%AUTOHOTSPOTpass% wpa_key_mgmt=WPA-PSK wpa_pairwise=CCMP TKIP rsn_pairwise=CCMP -#80211n - Change GB to your WiFi country code -country_code=%WIFIcountryCode% +#80211n - Change DE to your WiFi country code +country_code=%AUTOHOTSPOTcountryCode% ieee80211n=1 ieee80211d=1 diff --git a/misc/sampleconfigs/hostapd.jessie-WlanAP.sample b/misc/sampleconfigs/hostapd.jessie-WlanAP.sample deleted file mode 100755 index 28a254107..000000000 --- a/misc/sampleconfigs/hostapd.jessie-WlanAP.sample +++ /dev/null @@ -1,22 +0,0 @@ -# Defaults for hostapd initscript -# -# See /usr/share/doc/hostapd/README.Debian for information about alternative -# methods of managing hostapd. -# -# Uncomment and set DAEMON_CONF to the absolute path of a hostapd configuration -# file and hostapd will be started during system boot. An example configuration -# file can be found at /usr/share/doc/hostapd/examples/hostapd.conf.gz -# -#DAEMON_CONF="" - -# Additional daemon options to be appended to hostapd command:- -# -d show more debug messages (-dd for even more) -# -K include key data in debug messages -# -t include timestamps in some debug messages -# -# Note that -B (daemon mode) and -P (pidfile) options are automatically -# configured by the init.d script and must not be added to DAEMON_OPTS. -# -#DAEMON_OPTS="" -RUN_DAEMON=yes -DAEMON_CONF="/etc/hostapd/hostapd.conf" diff --git a/misc/sampleconfigs/hostapd.stretch-default2-Hotspot.sample b/misc/sampleconfigs/hostapd.stretch-default2-Hotspot.sample index 5783c15eb..3dcd47857 100755 --- a/misc/sampleconfigs/hostapd.stretch-default2-Hotspot.sample +++ b/misc/sampleconfigs/hostapd.stretch-default2-Hotspot.sample @@ -7,7 +7,7 @@ # file and hostapd will be started during system boot. An example configuration # file can be found at /usr/share/doc/hostapd/examples/hostapd.conf.gz # -DAEMON_CONF="/etc/hostapd/hostapd.conf" +DAEMON_CONF="%HOSTAPD_CONF%" # Additional daemon options to be appended to hostapd command:- # -d show more debug messages (-dd for even more) diff --git a/misc/sampleconfigs/interfaces.jessie-WlanAP.sample b/misc/sampleconfigs/interfaces.jessie-WlanAP.sample deleted file mode 100755 index d24f0022c..000000000 --- a/misc/sampleconfigs/interfaces.jessie-WlanAP.sample +++ /dev/null @@ -1,13 +0,0 @@ -# Localhost -auto lo -iface lo inet loopback - -# Ethernet -auto eth0 -iface eth0 inet manual - -# WLAN-Interface -allow-hotplug wlan0 -iface wlan0 inet static -address 192.168.1.1 -netmask 255.255.255.0 diff --git a/misc/sampleconfigs/interfaces.stretch-default2-Hotspot.sample b/misc/sampleconfigs/interfaces.stretch-default2-Hotspot.sample deleted file mode 100755 index eb9ccfcb2..000000000 --- a/misc/sampleconfigs/interfaces.stretch-default2-Hotspot.sample +++ /dev/null @@ -1,5 +0,0 @@ -# interfaces(5) file used by ifup(8) and ifdown(8) -# Please note that this file is written to be used with dhcpcd -# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf' -# Include files from /etc/network/interfaces.d: -source-directory /etc/network/interfaces.d \ No newline at end of file diff --git a/misc/sampleconfigs/lighttpd.conf.buster-default.sample b/misc/sampleconfigs/lighttpd.conf.buster-default.sample index a5a0f8c9a..534fba3fb 100755 --- a/misc/sampleconfigs/lighttpd.conf.buster-default.sample +++ b/misc/sampleconfigs/lighttpd.conf.buster-default.sample @@ -35,8 +35,8 @@ index-file.names = ( "index.php", "index.html" ) url.access-deny = ( "~", ".inc" ) static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" ) -compress.cache-dir = "/var/cache/lighttpd/compress/" -compress.filetype = ( "application/javascript", "text/css", "text/html", "text/plain" ) +deflate.cache-dir = "/var/cache/lighttpd/compress/" +deflate.mimetypes = ( "application/javascript", "text/css", "text/html", "text/plain" ) # default listening port for IPv6 falls back to the IPv4 port include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port @@ -45,7 +45,7 @@ include "/etc/lighttpd/conf-enabled/*.conf" #server.compat-module-load = "disable" server.modules += ( - "mod_compress", + "mod_deflate", "mod_dirlisting", "mod_staticfile", ) diff --git a/misc/sampleconfigs/lighttpd.conf.jessie-default.sample b/misc/sampleconfigs/lighttpd.conf.jessie-default.sample deleted file mode 100755 index 3cdaebd2b..000000000 --- a/misc/sampleconfigs/lighttpd.conf.jessie-default.sample +++ /dev/null @@ -1,28 +0,0 @@ -server.modules = ( - "mod_access", - "mod_alias", - "mod_compress", - "mod_redirect", -# "mod_rewrite", -) - -server.document-root = "/home/pi/RPi-Jukebox-RFID/htdocs" -server.upload-dirs = ( "/var/cache/lighttpd/uploads" ) -server.errorlog = "/var/log/lighttpd/error.log" -server.pid-file = "/var/run/lighttpd.pid" -server.username = "www-data" -server.groupname = "www-data" -server.port = 80 - - -index-file.names = ( "index.php", "index.html", "index.lighttpd.html" ) -url.access-deny = ( "~", ".inc" ) -static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" ) - -compress.cache-dir = "/var/cache/lighttpd/compress/" -compress.filetype = ( "application/javascript", "text/css", "text/html", "text/plain" ) - -# default listening port for IPv6 falls back to the IPv4 port -include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port -include_shell "/usr/share/lighttpd/create-mime.assign.pl" -include_shell "/usr/share/lighttpd/include-conf-enabled.pl" diff --git a/misc/sampleconfigs/lighttpd.conf.stretch-default.sample b/misc/sampleconfigs/lighttpd.conf.stretch-default.sample deleted file mode 100755 index 31ac5f8ce..000000000 --- a/misc/sampleconfigs/lighttpd.conf.stretch-default.sample +++ /dev/null @@ -1,27 +0,0 @@ -server.modules = ( - "mod_access", - "mod_alias", - "mod_compress", - "mod_redirect", -) - -server.document-root = "/home/pi/RPi-Jukebox-RFID/htdocs" -server.upload-dirs = ( "/var/cache/lighttpd/uploads" ) -server.errorlog = "/var/log/lighttpd/error.log" -server.pid-file = "/var/run/lighttpd.pid" -server.username = "www-data" -server.groupname = "www-data" -server.port = 80 - - -index-file.names = ( "index.php", "index.html", "index.lighttpd.html" ) -url.access-deny = ( "~", ".inc" ) -static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" ) - -compress.cache-dir = "/var/cache/lighttpd/compress/" -compress.filetype = ( "application/javascript", "text/css", "text/html", "text/plain" ) - -# default listening port for IPv6 falls back to the IPv4 port -include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port -include_shell "/usr/share/lighttpd/create-mime.assign.pl" -include_shell "/usr/share/lighttpd/include-conf-enabled.pl" diff --git a/misc/sampleconfigs/php.ini.stretch-default.sample b/misc/sampleconfigs/php.ini.stretch-default.sample deleted file mode 100755 index 6206f62c9..000000000 --- a/misc/sampleconfigs/php.ini.stretch-default.sample +++ /dev/null @@ -1,1918 +0,0 @@ -[PHP] - -;;;;;;;;;;;;;;;;;;; -; About php.ini ; -;;;;;;;;;;;;;;;;;;; -; PHP's initialization file, generally called php.ini, is responsible for -; configuring many of the aspects of PHP's behavior. - -; PHP attempts to find and load this configuration from a number of locations. -; The following is a summary of its search order: -; 1. SAPI module specific location. -; 2. The PHPRC environment variable. (As of PHP 5.2.0) -; 3. A number of predefined registry keys on Windows (As of PHP 5.2.0) -; 4. Current working directory (except CLI) -; 5. The web server's directory (for SAPI modules), or directory of PHP -; (otherwise in Windows) -; 6. The directory from the --with-config-file-path compile time option, or the -; Windows directory (C:\windows or C:\winnt) -; See the PHP docs for more specific information. -; http://php.net/configuration.file - -; The syntax of the file is extremely simple. Whitespace and lines -; beginning with a semicolon are silently ignored (as you probably guessed). -; Section headers (e.g. [Foo]) are also silently ignored, even though -; they might mean something in the future. - -; Directives following the section heading [PATH=/www/mysite] only -; apply to PHP files in the /www/mysite directory. Directives -; following the section heading [HOST=www.example.com] only apply to -; PHP files served from www.example.com. Directives set in these -; special sections cannot be overridden by user-defined INI files or -; at runtime. Currently, [PATH=] and [HOST=] sections only work under -; CGI/FastCGI. -; http://php.net/ini.sections - -; Directives are specified using the following syntax: -; directive = value -; Directive names are *case sensitive* - foo=bar is different from FOO=bar. -; Directives are variables used to configure PHP or PHP extensions. -; There is no name validation. If PHP can't find an expected -; directive because it is not set or is mistyped, a default value will be used. - -; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one -; of the INI constants (On, Off, True, False, Yes, No and None) or an expression -; (e.g. E_ALL & ~E_NOTICE), a quoted string ("bar"), or a reference to a -; previously set variable or directive (e.g. ${foo}) - -; Expressions in the INI file are limited to bitwise operators and parentheses: -; | bitwise OR -; ^ bitwise XOR -; & bitwise AND -; ~ bitwise NOT -; ! boolean NOT - -; Boolean flags can be turned on using the values 1, On, True or Yes. -; They can be turned off using the values 0, Off, False or No. - -; An empty string can be denoted by simply not writing anything after the equal -; sign, or by using the None keyword: - -; foo = ; sets foo to an empty string -; foo = None ; sets foo to an empty string -; foo = "None" ; sets foo to the string 'None' - -; If you use constants in your value, and these constants belong to a -; dynamically loaded extension (either a PHP extension or a Zend extension), -; you may only use these constants *after* the line that loads the extension. - -;;;;;;;;;;;;;;;;;;; -; About this file ; -;;;;;;;;;;;;;;;;;;; -; PHP comes packaged with two INI files. One that is recommended to be used -; in production environments and one that is recommended to be used in -; development environments. - -; php.ini-production contains settings which hold security, performance and -; best practices at its core. But please be aware, these settings may break -; compatibility with older or less security conscience applications. We -; recommending using the production ini in production and testing environments. - -; php.ini-development is very similar to its production variant, except it is -; much more verbose when it comes to errors. We recommend using the -; development version only in development environments, as errors shown to -; application users can inadvertently leak otherwise secure information. - -; This is php.ini-production INI file. - -;;;;;;;;;;;;;;;;;;; -; Quick Reference ; -;;;;;;;;;;;;;;;;;;; -; The following are all the settings which are different in either the production -; or development versions of the INIs with respect to PHP's default behavior. -; Please see the actual settings later in the document for more details as to why -; we recommend these changes in PHP's behavior. - -; display_errors -; Default Value: On -; Development Value: On -; Production Value: Off - -; display_startup_errors -; Default Value: Off -; Development Value: On -; Production Value: Off - -; error_reporting -; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED -; Development Value: E_ALL -; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT - -; html_errors -; Default Value: On -; Development Value: On -; Production value: On - -; log_errors -; Default Value: Off -; Development Value: On -; Production Value: On - -; max_input_time -; Default Value: -1 (Unlimited) -; Development Value: 60 (60 seconds) -; Production Value: 60 (60 seconds) - -; output_buffering -; Default Value: Off -; Development Value: 4096 -; Production Value: 4096 - -; register_argc_argv -; Default Value: On -; Development Value: Off -; Production Value: Off - -; request_order -; Default Value: None -; Development Value: "GP" -; Production Value: "GP" - -; session.gc_divisor -; Default Value: 100 -; Development Value: 1000 -; Production Value: 1000 - -; session.hash_bits_per_character -; Default Value: 4 -; Development Value: 5 -; Production Value: 5 - -; short_open_tag -; Default Value: On -; Development Value: Off -; Production Value: Off - -; track_errors -; Default Value: Off -; Development Value: On -; Production Value: Off - -; url_rewriter.tags -; Default Value: "a=href,area=href,frame=src,form=,fieldset=" -; Development Value: "a=href,area=href,frame=src,input=src,form=fakeentry" -; Production Value: "a=href,area=href,frame=src,input=src,form=fakeentry" - -; variables_order -; Default Value: "EGPCS" -; Development Value: "GPCS" -; Production Value: "GPCS" - -;;;;;;;;;;;;;;;;;;;; -; php.ini Options ; -;;;;;;;;;;;;;;;;;;;; -; Name for user-defined php.ini (.htaccess) files. Default is ".user.ini" -;user_ini.filename = ".user.ini" - -; To disable this feature set this option to empty value -;user_ini.filename = - -; TTL for user-defined php.ini files (time-to-live) in seconds. Default is 300 seconds (5 minutes) -;user_ini.cache_ttl = 300 - -;;;;;;;;;;;;;;;;;;;; -; Language Options ; -;;;;;;;;;;;;;;;;;;;; - -; Enable the PHP scripting language engine under Apache. -; http://php.net/engine -engine = On - -; This directive determines whether or not PHP will recognize code between -; tags as PHP source which should be processed as such. It is -; generally recommended that should be used and that this feature -; should be disabled, as enabling it may result in issues when generating XML -; documents, however this remains supported for backward compatibility reasons. -; Note that this directive does not control the would work. -; http://php.net/syntax-highlighting -;highlight.string = #DD0000 -;highlight.comment = #FF9900 -;highlight.keyword = #007700 -;highlight.default = #0000BB -;highlight.html = #000000 - -; If enabled, the request will be allowed to complete even if the user aborts -; the request. Consider enabling it if executing long requests, which may end up -; being interrupted by the user or a browser timing out. PHP's default behavior -; is to disable this feature. -; http://php.net/ignore-user-abort -;ignore_user_abort = On - -; Determines the size of the realpath cache to be used by PHP. This value should -; be increased on systems where PHP opens many files to reflect the quantity of -; the file operations performed. -; http://php.net/realpath-cache-size -;realpath_cache_size = 4096k - -; Duration of time, in seconds for which to cache realpath information for a given -; file or directory. For systems with rarely changing files, consider increasing this -; value. -; http://php.net/realpath-cache-ttl -;realpath_cache_ttl = 120 - -; Enables or disables the circular reference collector. -; http://php.net/zend.enable-gc -zend.enable_gc = On - -; If enabled, scripts may be written in encodings that are incompatible with -; the scanner. CP936, Big5, CP949 and Shift_JIS are the examples of such -; encodings. To use this feature, mbstring extension must be enabled. -; Default: Off -;zend.multibyte = Off - -; Allows to set the default encoding for the scripts. This value will be used -; unless "declare(encoding=...)" directive appears at the top of the script. -; Only affects if zend.multibyte is set. -; Default: "" -;zend.script_encoding = - -;;;;;;;;;;;;;;;;; -; Miscellaneous ; -;;;;;;;;;;;;;;;;; - -; Decides whether PHP may expose the fact that it is installed on the server -; (e.g. by adding its signature to the Web server header). It is no security -; threat in any way, but it makes it possible to determine whether you use PHP -; on your server or not. -; http://php.net/expose-php -expose_php = Off - -;;;;;;;;;;;;;;;;;;; -; Resource Limits ; -;;;;;;;;;;;;;;;;;;; - -; Maximum execution time of each script, in seconds -; http://php.net/max-execution-time -; Note: This directive is hardcoded to 0 for the CLI SAPI -max_execution_time = 30 - -; Maximum amount of time each script may spend parsing request data. It's a good -; idea to limit this time on productions servers in order to eliminate unexpectedly -; long running scripts. -; Note: This directive is hardcoded to -1 for the CLI SAPI -; Default Value: -1 (Unlimited) -; Development Value: 60 (60 seconds) -; Production Value: 60 (60 seconds) -; http://php.net/max-input-time -max_input_time = 60 - -; Maximum input variable nesting level -; http://php.net/max-input-nesting-level -;max_input_nesting_level = 64 - -; How many GET/POST/COOKIE input variables may be accepted -; max_input_vars = 1000 - -; Maximum amount of memory a script may consume (128MB) -; http://php.net/memory-limit -memory_limit = 128M - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Error handling and logging ; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; This directive informs PHP of which errors, warnings and notices you would like -; it to take action for. The recommended way of setting values for this -; directive is through the use of the error level constants and bitwise -; operators. The error level constants are below here for convenience as well as -; some common settings and their meanings. -; By default, PHP is set to take action on all errors, notices and warnings EXCEPT -; those related to E_NOTICE and E_STRICT, which together cover best practices and -; recommended coding standards in PHP. For performance reasons, this is the -; recommend error reporting setting. Your production server shouldn't be wasting -; resources complaining about best practices and coding standards. That's what -; development servers and development settings are for. -; Note: The php.ini-development file has this setting as E_ALL. This -; means it pretty much reports everything which is exactly what you want during -; development and early testing. -; -; Error Level Constants: -; E_ALL - All errors and warnings (includes E_STRICT as of PHP 5.4.0) -; E_ERROR - fatal run-time errors -; E_RECOVERABLE_ERROR - almost fatal run-time errors -; E_WARNING - run-time warnings (non-fatal errors) -; E_PARSE - compile-time parse errors -; E_NOTICE - run-time notices (these are warnings which often result -; from a bug in your code, but it's possible that it was -; intentional (e.g., using an uninitialized variable and -; relying on the fact it is automatically initialized to an -; empty string) -; E_STRICT - run-time notices, enable to have PHP suggest changes -; to your code which will ensure the best interoperability -; and forward compatibility of your code -; E_CORE_ERROR - fatal errors that occur during PHP's initial startup -; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's -; initial startup -; E_COMPILE_ERROR - fatal compile-time errors -; E_COMPILE_WARNING - compile-time warnings (non-fatal errors) -; E_USER_ERROR - user-generated error message -; E_USER_WARNING - user-generated warning message -; E_USER_NOTICE - user-generated notice message -; E_DEPRECATED - warn about code that will not work in future versions -; of PHP -; E_USER_DEPRECATED - user-generated deprecation warnings -; -; Common Values: -; E_ALL (Show all errors, warnings and notices including coding standards.) -; E_ALL & ~E_NOTICE (Show all errors, except for notices) -; E_ALL & ~E_NOTICE & ~E_STRICT (Show all errors, except for notices and coding standards warnings.) -; E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR (Show only errors) -; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED -; Development Value: E_ALL -; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT -; http://php.net/error-reporting -error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT - -; This directive controls whether or not and where PHP will output errors, -; notices and warnings too. Error output is very useful during development, but -; it could be very dangerous in production environments. Depending on the code -; which is triggering the error, sensitive information could potentially leak -; out of your application such as database usernames and passwords or worse. -; For production environments, we recommend logging errors rather than -; sending them to STDOUT. -; Possible Values: -; Off = Do not display any errors -; stderr = Display errors to STDERR (affects only CGI/CLI binaries!) -; On or stdout = Display errors to STDOUT -; Default Value: On -; Development Value: On -; Production Value: Off -; http://php.net/display-errors -display_errors = Off - -; The display of errors which occur during PHP's startup sequence are handled -; separately from display_errors. PHP's default behavior is to suppress those -; errors from clients. Turning the display of startup errors on can be useful in -; debugging configuration problems. We strongly recommend you -; set this to 'off' for production servers. -; Default Value: Off -; Development Value: On -; Production Value: Off -; http://php.net/display-startup-errors -display_startup_errors = Off - -; Besides displaying errors, PHP can also log errors to locations such as a -; server-specific log, STDERR, or a location specified by the error_log -; directive found below. While errors should not be displayed on productions -; servers they should still be monitored and logging is a great way to do that. -; Default Value: Off -; Development Value: On -; Production Value: On -; http://php.net/log-errors -log_errors = On - -; Set maximum length of log_errors. In error_log information about the source is -; added. The default is 1024 and 0 allows to not apply any maximum length at all. -; http://php.net/log-errors-max-len -log_errors_max_len = 1024 - -; Do not log repeated messages. Repeated errors must occur in same file on same -; line unless ignore_repeated_source is set true. -; http://php.net/ignore-repeated-errors -ignore_repeated_errors = Off - -; Ignore source of message when ignoring repeated messages. When this setting -; is On you will not log errors with repeated messages from different files or -; source lines. -; http://php.net/ignore-repeated-source -ignore_repeated_source = Off - -; If this parameter is set to Off, then memory leaks will not be shown (on -; stdout or in the log). This has only effect in a debug compile, and if -; error reporting includes E_WARNING in the allowed list -; http://php.net/report-memleaks -report_memleaks = On - -; This setting is on by default. -;report_zend_debug = 0 - -; Store the last error/warning message in $php_errormsg (boolean). Setting this value -; to On can assist in debugging and is appropriate for development servers. It should -; however be disabled on production servers. -; Default Value: Off -; Development Value: On -; Production Value: Off -; http://php.net/track-errors -track_errors = Off - -; Turn off normal error reporting and emit XML-RPC error XML -; http://php.net/xmlrpc-errors -;xmlrpc_errors = 0 - -; An XML-RPC faultCode -;xmlrpc_error_number = 0 - -; When PHP displays or logs an error, it has the capability of formatting the -; error message as HTML for easier reading. This directive controls whether -; the error message is formatted as HTML or not. -; Note: This directive is hardcoded to Off for the CLI SAPI -; Default Value: On -; Development Value: On -; Production value: On -; http://php.net/html-errors -html_errors = On - -; If html_errors is set to On *and* docref_root is not empty, then PHP -; produces clickable error messages that direct to a page describing the error -; or function causing the error in detail. -; You can download a copy of the PHP manual from http://php.net/docs -; and change docref_root to the base URL of your local copy including the -; leading '/'. You must also specify the file extension being used including -; the dot. PHP's default behavior is to leave these settings empty, in which -; case no links to documentation are generated. -; Note: Never use this feature for production boxes. -; http://php.net/docref-root -; Examples -;docref_root = "/phpmanual/" - -; http://php.net/docref-ext -;docref_ext = .html - -; String to output before an error message. PHP's default behavior is to leave -; this setting blank. -; http://php.net/error-prepend-string -; Example: -;error_prepend_string = "" - -; String to output after an error message. PHP's default behavior is to leave -; this setting blank. -; http://php.net/error-append-string -; Example: -;error_append_string = "" - -; Log errors to specified file. PHP's default behavior is to leave this value -; empty. -; http://php.net/error-log -; Example: -;error_log = php_errors.log -; Log errors to syslog (Event Log on Windows). -;error_log = syslog - -;windows.show_crt_warning -; Default value: 0 -; Development value: 0 -; Production value: 0 - -;;;;;;;;;;;;;;;;; -; Data Handling ; -;;;;;;;;;;;;;;;;; - -; The separator used in PHP generated URLs to separate arguments. -; PHP's default setting is "&". -; http://php.net/arg-separator.output -; Example: -;arg_separator.output = "&" - -; List of separator(s) used by PHP to parse input URLs into variables. -; PHP's default setting is "&". -; NOTE: Every character in this directive is considered as separator! -; http://php.net/arg-separator.input -; Example: -;arg_separator.input = ";&" - -; This directive determines which super global arrays are registered when PHP -; starts up. G,P,C,E & S are abbreviations for the following respective super -; globals: GET, POST, COOKIE, ENV and SERVER. There is a performance penalty -; paid for the registration of these arrays and because ENV is not as commonly -; used as the others, ENV is not recommended on productions servers. You -; can still get access to the environment variables through getenv() should you -; need to. -; Default Value: "EGPCS" -; Development Value: "GPCS" -; Production Value: "GPCS"; -; http://php.net/variables-order -variables_order = "GPCS" - -; This directive determines which super global data (G,P & C) should be -; registered into the super global array REQUEST. If so, it also determines -; the order in which that data is registered. The values for this directive -; are specified in the same manner as the variables_order directive, -; EXCEPT one. Leaving this value empty will cause PHP to use the value set -; in the variables_order directive. It does not mean it will leave the super -; globals array REQUEST empty. -; Default Value: None -; Development Value: "GP" -; Production Value: "GP" -; http://php.net/request-order -request_order = "GP" - -; This directive determines whether PHP registers $argv & $argc each time it -; runs. $argv contains an array of all the arguments passed to PHP when a script -; is invoked. $argc contains an integer representing the number of arguments -; that were passed when the script was invoked. These arrays are extremely -; useful when running scripts from the command line. When this directive is -; enabled, registering these variables consumes CPU cycles and memory each time -; a script is executed. For performance reasons, this feature should be disabled -; on production servers. -; Note: This directive is hardcoded to On for the CLI SAPI -; Default Value: On -; Development Value: Off -; Production Value: Off -; http://php.net/register-argc-argv -register_argc_argv = Off - -; When enabled, the ENV, REQUEST and SERVER variables are created when they're -; first used (Just In Time) instead of when the script starts. If these -; variables are not used within a script, having this directive on will result -; in a performance gain. The PHP directive register_argc_argv must be disabled -; for this directive to have any affect. -; http://php.net/auto-globals-jit -auto_globals_jit = On - -; Whether PHP will read the POST data. -; This option is enabled by default. -; Most likely, you won't want to disable this option globally. It causes $_POST -; and $_FILES to always be empty; the only way you will be able to read the -; POST data will be through the php://input stream wrapper. This can be useful -; to proxy requests or to process the POST data in a memory efficient fashion. -; http://php.net/enable-post-data-reading -;enable_post_data_reading = Off - -; Maximum size of POST data that PHP will accept. -; Its value may be 0 to disable the limit. It is ignored if POST data reading -; is disabled through enable_post_data_reading. -; http://php.net/post-max-size -post_max_size = 0 - -; Automatically add files before PHP document. -; http://php.net/auto-prepend-file -auto_prepend_file = - -; Automatically add files after PHP document. -; http://php.net/auto-append-file -auto_append_file = - -; By default, PHP will output a media type using the Content-Type header. To -; disable this, simply set it to be empty. -; -; PHP's built-in default media type is set to text/html. -; http://php.net/default-mimetype -default_mimetype = "text/html" - -; PHP's default character set is set to UTF-8. -; http://php.net/default-charset -default_charset = "UTF-8" - -; PHP internal character encoding is set to empty. -; If empty, default_charset is used. -; http://php.net/internal-encoding -;internal_encoding = - -; PHP input character encoding is set to empty. -; If empty, default_charset is used. -; http://php.net/input-encoding -;input_encoding = - -; PHP output character encoding is set to empty. -; If empty, default_charset is used. -; See also output_buffer. -; http://php.net/output-encoding -;output_encoding = - -;;;;;;;;;;;;;;;;;;;;;;;;; -; Paths and Directories ; -;;;;;;;;;;;;;;;;;;;;;;;;; - -; UNIX: "/path1:/path2" -;include_path = ".:/usr/share/php" -; -; Windows: "\path1;\path2" -;include_path = ".;c:\php\includes" -; -; PHP's default setting for include_path is ".;/path/to/php/pear" -; http://php.net/include-path - -; The root of the PHP pages, used only if nonempty. -; if PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root -; if you are running php as a CGI under any web server (other than IIS) -; see documentation for security issues. The alternate is to use the -; cgi.force_redirect configuration below -; http://php.net/doc-root -doc_root = - -; The directory under which PHP opens the script using /~username used only -; if nonempty. -; http://php.net/user-dir -user_dir = - -; Directory in which the loadable extensions (modules) reside. -; http://php.net/extension-dir -; extension_dir = "./" -; On windows: -; extension_dir = "ext" - -; Directory where the temporary files should be placed. -; Defaults to the system default (see sys_get_temp_dir) -; sys_temp_dir = "/tmp" - -; Whether or not to enable the dl() function. The dl() function does NOT work -; properly in multithreaded servers, such as IIS or Zeus, and is automatically -; disabled on them. -; http://php.net/enable-dl -enable_dl = Off - -; cgi.force_redirect is necessary to provide security running PHP as a CGI under -; most web servers. Left undefined, PHP turns this on by default. You can -; turn it off here AT YOUR OWN RISK -; **You CAN safely turn this off for IIS, in fact, you MUST.** -; http://php.net/cgi.force-redirect -;cgi.force_redirect = 1 - -; if cgi.nph is enabled it will force cgi to always sent Status: 200 with -; every request. PHP's default behavior is to disable this feature. -;cgi.nph = 1 - -; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape -; (iPlanet) web servers, you MAY need to set an environment variable name that PHP -; will look for to know it is OK to continue execution. Setting this variable MAY -; cause security issues, KNOW WHAT YOU ARE DOING FIRST. -; http://php.net/cgi.redirect-status-env -;cgi.redirect_status_env = - -; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's -; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok -; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting -; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting -; of zero causes PHP to behave as before. Default is 1. You should fix your scripts -; to use SCRIPT_FILENAME rather than PATH_TRANSLATED. -; http://php.net/cgi.fix-pathinfo -;cgi.fix_pathinfo=1 - -; if cgi.discard_path is enabled, the PHP CGI binary can safely be placed outside -; of the web tree and people will not be able to circumvent .htaccess security. -; http://php.net/cgi.dicard-path -;cgi.discard_path=1 - -; FastCGI under IIS (on WINNT based OS) supports the ability to impersonate -; security tokens of the calling client. This allows IIS to define the -; security context that the request runs under. mod_fastcgi under Apache -; does not currently support this feature (03/17/2002) -; Set to 1 if running under IIS. Default is zero. -; http://php.net/fastcgi.impersonate -;fastcgi.impersonate = 1 - -; Disable logging through FastCGI connection. PHP's default behavior is to enable -; this feature. -;fastcgi.logging = 0 - -; cgi.rfc2616_headers configuration option tells PHP what type of headers to -; use when sending HTTP response code. If set to 0, PHP sends Status: header that -; is supported by Apache. When this option is set to 1, PHP will send -; RFC2616 compliant header. -; Default is zero. -; http://php.net/cgi.rfc2616-headers -;cgi.rfc2616_headers = 0 - -; cgi.check_shebang_line controls whether CGI PHP checks for line starting with #! -; (shebang) at the top of the running script. This line might be needed if the -; script support running both as stand-alone script and via PHP CGI<. PHP in CGI -; mode skips this line and ignores its content if this directive is turned on. -; http://php.net/cgi.check-shebang-line -;cgi.check_shebang_line=1 - -;;;;;;;;;;;;;;;; -; File Uploads ; -;;;;;;;;;;;;;;;; - -; Whether to allow HTTP file uploads. -; http://php.net/file-uploads -file_uploads = On - -; Temporary directory for HTTP uploaded files (will use system default if not -; specified). -; http://php.net/upload-tmp-dir -;upload_tmp_dir = - -; Maximum allowed size for uploaded files. -; http://php.net/upload-max-filesize -upload_max_filesize = 0 - -; Maximum number of files that can be uploaded via a single request -max_file_uploads = 20 - -;;;;;;;;;;;;;;;;;; -; Fopen wrappers ; -;;;;;;;;;;;;;;;;;; - -; Whether to allow the treatment of URLs (like http:// or ftp://) as files. -; http://php.net/allow-url-fopen -allow_url_fopen = On - -; Whether to allow include/require to open URLs (like http:// or ftp://) as files. -; http://php.net/allow-url-include -allow_url_include = Off - -; Define the anonymous ftp password (your email address). PHP's default setting -; for this is empty. -; http://php.net/from -;from="john@doe.com" - -; Define the User-Agent string. PHP's default setting for this is empty. -; http://php.net/user-agent -;user_agent="PHP" - -; Default timeout for socket based streams (seconds) -; http://php.net/default-socket-timeout -default_socket_timeout = 60 - -; If your scripts have to deal with files from Macintosh systems, -; or you are running on a Mac and need to deal with files from -; unix or win32 systems, setting this flag will cause PHP to -; automatically detect the EOL character in those files so that -; fgets() and file() will work regardless of the source of the file. -; http://php.net/auto-detect-line-endings -;auto_detect_line_endings = Off - -;;;;;;;;;;;;;;;;;;;;;; -; Dynamic Extensions ; -;;;;;;;;;;;;;;;;;;;;;; - -; If you wish to have an extension loaded automatically, use the following -; syntax: -; -; extension=modulename.extension -; -; For example, on Windows: -; -; extension=msql.dll -; -; ... or under UNIX: -; -; extension=msql.so -; -; ... or with a path: -; -; extension=/path/to/extension/msql.so -; -; If you only provide the name of the extension, PHP will look for it in its -; default extension directory. -; -; Windows Extensions -; Note that ODBC support is built in, so no dll is needed for it. -; Note that many DLL files are located in the extensions/ (PHP 4) ext/ (PHP 5+) -; extension folders as well as the separate PECL DLL download (PHP 5+). -; Be sure to appropriately set the extension_dir directive. -; -;extension=php_bz2.dll -;extension=php_curl.dll -;extension=php_fileinfo.dll -;extension=php_ftp.dll -;extension=php_gd2.dll -;extension=php_gettext.dll -;extension=php_gmp.dll -;extension=php_intl.dll -;extension=php_imap.dll -;extension=php_interbase.dll -;extension=php_ldap.dll -;extension=php_mbstring.dll -;extension=php_exif.dll ; Must be after mbstring as it depends on it -;extension=php_mysqli.dll -;extension=php_oci8_12c.dll ; Use with Oracle Database 12c Instant Client -;extension=php_openssl.dll -;extension=php_pdo_firebird.dll -;extension=php_pdo_mysql.dll -;extension=php_pdo_oci.dll -;extension=php_pdo_odbc.dll -;extension=php_pdo_pgsql.dll -;extension=php_pdo_sqlite.dll -;extension=php_pgsql.dll -;extension=php_shmop.dll - -; The MIBS data available in the PHP distribution must be installed. -; See http://www.php.net/manual/en/snmp.installation.php -;extension=php_snmp.dll - -;extension=php_soap.dll -;extension=php_sockets.dll -;extension=php_sqlite3.dll -;extension=php_tidy.dll -;extension=php_xmlrpc.dll -;extension=php_xsl.dll - -;;;;;;;;;;;;;;;;;;; -; Module Settings ; -;;;;;;;;;;;;;;;;;;; - -[CLI Server] -; Whether the CLI web server uses ANSI color coding in its terminal output. -cli_server.color = On - -[Date] -; Defines the default timezone used by the date functions -; http://php.net/date.timezone -;date.timezone = - -; http://php.net/date.default-latitude -;date.default_latitude = 31.7667 - -; http://php.net/date.default-longitude -;date.default_longitude = 35.2333 - -; http://php.net/date.sunrise-zenith -;date.sunrise_zenith = 90.583333 - -; http://php.net/date.sunset-zenith -;date.sunset_zenith = 90.583333 - -[filter] -; http://php.net/filter.default -;filter.default = unsafe_raw - -; http://php.net/filter.default-flags -;filter.default_flags = - -[iconv] -; Use of this INI entry is deprecated, use global input_encoding instead. -; If empty, default_charset or input_encoding or iconv.input_encoding is used. -; The precedence is: default_charset < intput_encoding < iconv.input_encoding -;iconv.input_encoding = - -; Use of this INI entry is deprecated, use global internal_encoding instead. -; If empty, default_charset or internal_encoding or iconv.internal_encoding is used. -; The precedence is: default_charset < internal_encoding < iconv.internal_encoding -;iconv.internal_encoding = - -; Use of this INI entry is deprecated, use global output_encoding instead. -; If empty, default_charset or output_encoding or iconv.output_encoding is used. -; The precedence is: default_charset < output_encoding < iconv.output_encoding -; To use an output encoding conversion, iconv's output handler must be set -; otherwise output encoding conversion cannot be performed. -;iconv.output_encoding = - -[intl] -;intl.default_locale = -; This directive allows you to produce PHP errors when some error -; happens within intl functions. The value is the level of the error produced. -; Default is 0, which does not produce any errors. -;intl.error_level = E_WARNING -;intl.use_exceptions = 0 - -[sqlite3] -;sqlite3.extension_dir = - -[Pcre] -;PCRE library backtracking limit. -; http://php.net/pcre.backtrack-limit -;pcre.backtrack_limit=100000 - -;PCRE library recursion limit. -;Please note that if you set this value to a high number you may consume all -;the available process stack and eventually crash PHP (due to reaching the -;stack size limit imposed by the Operating System). -; http://php.net/pcre.recursion-limit -;pcre.recursion_limit=100000 - -;Enables or disables JIT compilation of patterns. This requires the PCRE -;library to be compiled with JIT support. -;pcre.jit=1 - -[Pdo] -; Whether to pool ODBC connections. Can be one of "strict", "relaxed" or "off" -; http://php.net/pdo-odbc.connection-pooling -;pdo_odbc.connection_pooling=strict - -;pdo_odbc.db2_instance_name - -[Pdo_mysql] -; If mysqlnd is used: Number of cache slots for the internal result set cache -; http://php.net/pdo_mysql.cache_size -pdo_mysql.cache_size = 2000 - -; Default socket name for local MySQL connects. If empty, uses the built-in -; MySQL defaults. -; http://php.net/pdo_mysql.default-socket -pdo_mysql.default_socket= - -[Phar] -; http://php.net/phar.readonly -;phar.readonly = On - -; http://php.net/phar.require-hash -;phar.require_hash = On - -;phar.cache_list = - -[mail function] -; For Win32 only. -; http://php.net/smtp -SMTP = localhost -; http://php.net/smtp-port -smtp_port = 25 - -; For Win32 only. -; http://php.net/sendmail-from -;sendmail_from = me@example.com - -; For Unix only. You may supply arguments as well (default: "sendmail -t -i"). -; http://php.net/sendmail-path -;sendmail_path = - -; Force the addition of the specified parameters to be passed as extra parameters -; to the sendmail binary. These parameters will always replace the value of -; the 5th parameter to mail(). -;mail.force_extra_parameters = - -; Add X-PHP-Originating-Script: that will include uid of the script followed by the filename -mail.add_x_header = On - -; The path to a log file that will log all mail() calls. Log entries include -; the full path of the script, line number, To address and headers. -;mail.log = -; Log mail to syslog (Event Log on Windows). -;mail.log = syslog - -[SQL] -; http://php.net/sql.safe-mode -sql.safe_mode = Off - -[ODBC] -; http://php.net/odbc.default-db -;odbc.default_db = Not yet implemented - -; http://php.net/odbc.default-user -;odbc.default_user = Not yet implemented - -; http://php.net/odbc.default-pw -;odbc.default_pw = Not yet implemented - -; Controls the ODBC cursor model. -; Default: SQL_CURSOR_STATIC (default). -;odbc.default_cursortype - -; Allow or prevent persistent links. -; http://php.net/odbc.allow-persistent -odbc.allow_persistent = On - -; Check that a connection is still valid before reuse. -; http://php.net/odbc.check-persistent -odbc.check_persistent = On - -; Maximum number of persistent links. -1 means no limit. -; http://php.net/odbc.max-persistent -odbc.max_persistent = -1 - -; Maximum number of links (persistent + non-persistent). -1 means no limit. -; http://php.net/odbc.max-links -odbc.max_links = -1 - -; Handling of LONG fields. Returns number of bytes to variables. 0 means -; passthru. -; http://php.net/odbc.defaultlrl -odbc.defaultlrl = 4096 - -; Handling of binary data. 0 means passthru, 1 return as is, 2 convert to char. -; See the documentation on odbc_binmode and odbc_longreadlen for an explanation -; of odbc.defaultlrl and odbc.defaultbinmode -; http://php.net/odbc.defaultbinmode -odbc.defaultbinmode = 1 - -;birdstep.max_links = -1 - -[Interbase] -; Allow or prevent persistent links. -ibase.allow_persistent = 1 - -; Maximum number of persistent links. -1 means no limit. -ibase.max_persistent = -1 - -; Maximum number of links (persistent + non-persistent). -1 means no limit. -ibase.max_links = -1 - -; Default database name for ibase_connect(). -;ibase.default_db = - -; Default username for ibase_connect(). -;ibase.default_user = - -; Default password for ibase_connect(). -;ibase.default_password = - -; Default charset for ibase_connect(). -;ibase.default_charset = - -; Default timestamp format. -ibase.timestampformat = "%Y-%m-%d %H:%M:%S" - -; Default date format. -ibase.dateformat = "%Y-%m-%d" - -; Default time format. -ibase.timeformat = "%H:%M:%S" - -[MySQLi] - -; Maximum number of persistent links. -1 means no limit. -; http://php.net/mysqli.max-persistent -mysqli.max_persistent = -1 - -; Allow accessing, from PHP's perspective, local files with LOAD DATA statements -; http://php.net/mysqli.allow_local_infile -;mysqli.allow_local_infile = On - -; Allow or prevent persistent links. -; http://php.net/mysqli.allow-persistent -mysqli.allow_persistent = On - -; Maximum number of links. -1 means no limit. -; http://php.net/mysqli.max-links -mysqli.max_links = -1 - -; If mysqlnd is used: Number of cache slots for the internal result set cache -; http://php.net/mysqli.cache_size -mysqli.cache_size = 2000 - -; Default port number for mysqli_connect(). If unset, mysqli_connect() will use -; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the -; compile-time value defined MYSQL_PORT (in that order). Win32 will only look -; at MYSQL_PORT. -; http://php.net/mysqli.default-port -mysqli.default_port = 3306 - -; Default socket name for local MySQL connects. If empty, uses the built-in -; MySQL defaults. -; http://php.net/mysqli.default-socket -mysqli.default_socket = - -; Default host for mysql_connect() (doesn't apply in safe mode). -; http://php.net/mysqli.default-host -mysqli.default_host = - -; Default user for mysql_connect() (doesn't apply in safe mode). -; http://php.net/mysqli.default-user -mysqli.default_user = - -; Default password for mysqli_connect() (doesn't apply in safe mode). -; Note that this is generally a *bad* idea to store passwords in this file. -; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_pw") -; and reveal this password! And of course, any users with read access to this -; file will be able to reveal the password as well. -; http://php.net/mysqli.default-pw -mysqli.default_pw = - -; Allow or prevent reconnect -mysqli.reconnect = Off - -[mysqlnd] -; Enable / Disable collection of general statistics by mysqlnd which can be -; used to tune and monitor MySQL operations. -; http://php.net/mysqlnd.collect_statistics -mysqlnd.collect_statistics = On - -; Enable / Disable collection of memory usage statistics by mysqlnd which can be -; used to tune and monitor MySQL operations. -; http://php.net/mysqlnd.collect_memory_statistics -mysqlnd.collect_memory_statistics = Off - -; Records communication from all extensions using mysqlnd to the specified log -; file. -; http://php.net/mysqlnd.debug -;mysqlnd.debug = - -; Defines which queries will be logged. -; http://php.net/mysqlnd.log_mask -;mysqlnd.log_mask = 0 - -; Default size of the mysqlnd memory pool, which is used by result sets. -; http://php.net/mysqlnd.mempool_default_size -;mysqlnd.mempool_default_size = 16000 - -; Size of a pre-allocated buffer used when sending commands to MySQL in bytes. -; http://php.net/mysqlnd.net_cmd_buffer_size -;mysqlnd.net_cmd_buffer_size = 2048 - -; Size of a pre-allocated buffer used for reading data sent by the server in -; bytes. -; http://php.net/mysqlnd.net_read_buffer_size -;mysqlnd.net_read_buffer_size = 32768 - -; Timeout for network requests in seconds. -; http://php.net/mysqlnd.net_read_timeout -;mysqlnd.net_read_timeout = 31536000 - -; SHA-256 Authentication Plugin related. File with the MySQL server public RSA -; key. -; http://php.net/mysqlnd.sha256_server_public_key -;mysqlnd.sha256_server_public_key = - -[OCI8] - -; Connection: Enables privileged connections using external -; credentials (OCI_SYSOPER, OCI_SYSDBA) -; http://php.net/oci8.privileged-connect -;oci8.privileged_connect = Off - -; Connection: The maximum number of persistent OCI8 connections per -; process. Using -1 means no limit. -; http://php.net/oci8.max-persistent -;oci8.max_persistent = -1 - -; Connection: The maximum number of seconds a process is allowed to -; maintain an idle persistent connection. Using -1 means idle -; persistent connections will be maintained forever. -; http://php.net/oci8.persistent-timeout -;oci8.persistent_timeout = -1 - -; Connection: The number of seconds that must pass before issuing a -; ping during oci_pconnect() to check the connection validity. When -; set to 0, each oci_pconnect() will cause a ping. Using -1 disables -; pings completely. -; http://php.net/oci8.ping-interval -;oci8.ping_interval = 60 - -; Connection: Set this to a user chosen connection class to be used -; for all pooled server requests with Oracle 11g Database Resident -; Connection Pooling (DRCP). To use DRCP, this value should be set to -; the same string for all web servers running the same application, -; the database pool must be configured, and the connection string must -; specify to use a pooled server. -;oci8.connection_class = - -; High Availability: Using On lets PHP receive Fast Application -; Notification (FAN) events generated when a database node fails. The -; database must also be configured to post FAN events. -;oci8.events = Off - -; Tuning: This option enables statement caching, and specifies how -; many statements to cache. Using 0 disables statement caching. -; http://php.net/oci8.statement-cache-size -;oci8.statement_cache_size = 20 - -; Tuning: Enables statement prefetching and sets the default number of -; rows that will be fetched automatically after statement execution. -; http://php.net/oci8.default-prefetch -;oci8.default_prefetch = 100 - -; Compatibility. Using On means oci_close() will not close -; oci_connect() and oci_new_connect() connections. -; http://php.net/oci8.old-oci-close-semantics -;oci8.old_oci_close_semantics = Off - -[PostgreSQL] -; Allow or prevent persistent links. -; http://php.net/pgsql.allow-persistent -pgsql.allow_persistent = On - -; Detect broken persistent links always with pg_pconnect(). -; Auto reset feature requires a little overheads. -; http://php.net/pgsql.auto-reset-persistent -pgsql.auto_reset_persistent = Off - -; Maximum number of persistent links. -1 means no limit. -; http://php.net/pgsql.max-persistent -pgsql.max_persistent = -1 - -; Maximum number of links (persistent+non persistent). -1 means no limit. -; http://php.net/pgsql.max-links -pgsql.max_links = -1 - -; Ignore PostgreSQL backends Notice message or not. -; Notice message logging require a little overheads. -; http://php.net/pgsql.ignore-notice -pgsql.ignore_notice = 0 - -; Log PostgreSQL backends Notice message or not. -; Unless pgsql.ignore_notice=0, module cannot log notice message. -; http://php.net/pgsql.log-notice -pgsql.log_notice = 0 - -[bcmath] -; Number of decimal digits for all bcmath functions. -; http://php.net/bcmath.scale -bcmath.scale = 0 - -[browscap] -; http://php.net/browscap -;browscap = extra/browscap.ini - -[Session] -; Handler used to store/retrieve data. -; http://php.net/session.save-handler -session.save_handler = files - -; Argument passed to save_handler. In the case of files, this is the path -; where data files are stored. Note: Windows users have to change this -; variable in order to use PHP's session functions. -; -; The path can be defined as: -; -; session.save_path = "N;/path" -; -; where N is an integer. Instead of storing all the session files in -; /path, what this will do is use subdirectories N-levels deep, and -; store the session data in those directories. This is useful if -; your OS has problems with many files in one directory, and is -; a more efficient layout for servers that handle many sessions. -; -; NOTE 1: PHP will not create this directory structure automatically. -; You can use the script in the ext/session dir for that purpose. -; NOTE 2: See the section on garbage collection below if you choose to -; use subdirectories for session storage -; -; The file storage module creates files using mode 600 by default. -; You can change that by using -; -; session.save_path = "N;MODE;/path" -; -; where MODE is the octal representation of the mode. Note that this -; does not overwrite the process's umask. -; http://php.net/session.save-path -;session.save_path = "/var/lib/php/sessions" - -; Whether to use strict session mode. -; Strict session mode does not accept uninitialized session ID and regenerate -; session ID if browser sends uninitialized session ID. Strict mode protects -; applications from session fixation via session adoption vulnerability. It is -; disabled by default for maximum compatibility, but enabling it is encouraged. -; https://wiki.php.net/rfc/strict_sessions -session.use_strict_mode = 0 - -; Whether to use cookies. -; http://php.net/session.use-cookies -session.use_cookies = 1 - -; http://php.net/session.cookie-secure -;session.cookie_secure = - -; This option forces PHP to fetch and use a cookie for storing and maintaining -; the session id. We encourage this operation as it's very helpful in combating -; session hijacking when not specifying and managing your own session id. It is -; not the be-all and end-all of session hijacking defense, but it's a good start. -; http://php.net/session.use-only-cookies -session.use_only_cookies = 1 - -; Name of the session (used as cookie name). -; http://php.net/session.name -session.name = PHPSESSID - -; Initialize session on request startup. -; http://php.net/session.auto-start -session.auto_start = 0 - -; Lifetime in seconds of cookie or, if 0, until browser is restarted. -; http://php.net/session.cookie-lifetime -session.cookie_lifetime = 0 - -; The path for which the cookie is valid. -; http://php.net/session.cookie-path -session.cookie_path = / - -; The domain for which the cookie is valid. -; http://php.net/session.cookie-domain -session.cookie_domain = - -; Whether or not to add the httpOnly flag to the cookie, which makes it inaccessible to browser scripting languages such as JavaScript. -; http://php.net/session.cookie-httponly -session.cookie_httponly = - -; Handler used to serialize data. php is the standard serializer of PHP. -; http://php.net/session.serialize-handler -session.serialize_handler = php - -; Defines the probability that the 'garbage collection' process is started -; on every session initialization. The probability is calculated by using -; gc_probability/gc_divisor. Where session.gc_probability is the numerator -; and gc_divisor is the denominator in the equation. Setting this value to 1 -; when the session.gc_divisor value is 100 will give you approximately a 1% chance -; the gc will run on any give request. -; Default Value: 1 -; Development Value: 1 -; Production Value: 1 -; http://php.net/session.gc-probability -session.gc_probability = 0 - -; Defines the probability that the 'garbage collection' process is started on every -; session initialization. The probability is calculated by using the following equation: -; gc_probability/gc_divisor. Where session.gc_probability is the numerator and -; session.gc_divisor is the denominator in the equation. Setting this value to 1 -; when the session.gc_divisor value is 100 will give you approximately a 1% chance -; the gc will run on any give request. Increasing this value to 1000 will give you -; a 0.1% chance the gc will run on any give request. For high volume production servers, -; this is a more efficient approach. -; Default Value: 100 -; Development Value: 1000 -; Production Value: 1000 -; http://php.net/session.gc-divisor -session.gc_divisor = 1000 - -; After this number of seconds, stored data will be seen as 'garbage' and -; cleaned up by the garbage collection process. -; http://php.net/session.gc-maxlifetime -session.gc_maxlifetime = 1440 - -; NOTE: If you are using the subdirectory option for storing session files -; (see session.save_path above), then garbage collection does *not* -; happen automatically. You will need to do your own garbage -; collection through a shell script, cron entry, or some other method. -; For example, the following script would is the equivalent of -; setting session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes): -; find /path/to/sessions -cmin +24 -type f | xargs rm - -; Check HTTP Referer to invalidate externally stored URLs containing ids. -; HTTP_REFERER has to contain this substring for the session to be -; considered as valid. -; http://php.net/session.referer-check -session.referer_check = - -; How many bytes to read from the file. -; http://php.net/session.entropy-length -;session.entropy_length = 32 - -; Specified here to create the session id. -; http://php.net/session.entropy-file -; Defaults to /dev/urandom -; On systems that don't have /dev/urandom but do have /dev/arandom, this will default to /dev/arandom -; If neither are found at compile time, the default is no entropy file. -; On windows, setting the entropy_length setting will activate the -; Windows random source (using the CryptoAPI) -;session.entropy_file = /dev/urandom - -; Set to {nocache,private,public,} to determine HTTP caching aspects -; or leave this empty to avoid sending anti-caching headers. -; http://php.net/session.cache-limiter -session.cache_limiter = nocache - -; Document expires after n minutes. -; http://php.net/session.cache-expire -session.cache_expire = 180 - -; trans sid support is disabled by default. -; Use of trans sid may risk your users' security. -; Use this option with caution. -; - User may send URL contains active session ID -; to other person via. email/irc/etc. -; - URL that contains active session ID may be stored -; in publicly accessible computer. -; - User may access your site with the same session ID -; always using URL stored in browser's history or bookmarks. -; http://php.net/session.use-trans-sid -session.use_trans_sid = 0 - -; Select a hash function for use in generating session ids. -; Possible Values -; 0 (MD5 128 bits) -; 1 (SHA-1 160 bits) -; This option may also be set to the name of any hash function supported by -; the hash extension. A list of available hashes is returned by the hash_algos() -; function. -; http://php.net/session.hash-function -session.hash_function = 0 - -; Define how many bits are stored in each character when converting -; the binary hash data to something readable. -; Possible values: -; 4 (4 bits: 0-9, a-f) -; 5 (5 bits: 0-9, a-v) -; 6 (6 bits: 0-9, a-z, A-Z, "-", ",") -; Default Value: 4 -; Development Value: 5 -; Production Value: 5 -; http://php.net/session.hash-bits-per-character -session.hash_bits_per_character = 5 - -; The URL rewriter will look for URLs in a defined set of HTML tags. -; form/fieldset are special; if you include them here, the rewriter will -; add a hidden field with the info which is otherwise appended -; to URLs. If you want XHTML conformity, remove the form entry. -; Note that all valid entries require a "=", even if no value follows. -; Default Value: "a=href,area=href,frame=src,form=,fieldset=" -; Development Value: "a=href,area=href,frame=src,input=src,form=fakeentry" -; Production Value: "a=href,area=href,frame=src,input=src,form=fakeentry" -; http://php.net/url-rewriter.tags -url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry" - -; Enable upload progress tracking in $_SESSION -; Default Value: On -; Development Value: On -; Production Value: On -; http://php.net/session.upload-progress.enabled -;session.upload_progress.enabled = On - -; Cleanup the progress information as soon as all POST data has been read -; (i.e. upload completed). -; Default Value: On -; Development Value: On -; Production Value: On -; http://php.net/session.upload-progress.cleanup -;session.upload_progress.cleanup = On - -; A prefix used for the upload progress key in $_SESSION -; Default Value: "upload_progress_" -; Development Value: "upload_progress_" -; Production Value: "upload_progress_" -; http://php.net/session.upload-progress.prefix -;session.upload_progress.prefix = "upload_progress_" - -; The index name (concatenated with the prefix) in $_SESSION -; containing the upload progress information -; Default Value: "PHP_SESSION_UPLOAD_PROGRESS" -; Development Value: "PHP_SESSION_UPLOAD_PROGRESS" -; Production Value: "PHP_SESSION_UPLOAD_PROGRESS" -; http://php.net/session.upload-progress.name -;session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS" - -; How frequently the upload progress should be updated. -; Given either in percentages (per-file), or in bytes -; Default Value: "1%" -; Development Value: "1%" -; Production Value: "1%" -; http://php.net/session.upload-progress.freq -;session.upload_progress.freq = "1%" - -; The minimum delay between updates, in seconds -; Default Value: 1 -; Development Value: 1 -; Production Value: 1 -; http://php.net/session.upload-progress.min-freq -;session.upload_progress.min_freq = "1" - -; Only write session data when session data is changed. Enabled by default. -; http://php.net/session.lazy-write -;session.lazy_write = On - -[Assertion] -; Switch whether to compile assertions at all (to have no overhead at run-time) -; -1: Do not compile at all -; 0: Jump over assertion at run-time -; 1: Execute assertions -; Changing from or to a negative value is only possible in php.ini! (For turning assertions on and off at run-time, see assert.active, when zend.assertions = 1) -; Default Value: 1 -; Development Value: 1 -; Production Value: -1 -; http://php.net/zend.assertions -zend.assertions = -1 - -; Assert(expr); active by default. -; http://php.net/assert.active -;assert.active = On - -; Throw an AssertationException on failed assertions -; http://php.net/assert.exception -;assert.exception = On - -; Issue a PHP warning for each failed assertion. (Overridden by assert.exception if active) -; http://php.net/assert.warning -;assert.warning = On - -; Don't bail out by default. -; http://php.net/assert.bail -;assert.bail = Off - -; User-function to be called if an assertion fails. -; http://php.net/assert.callback -;assert.callback = 0 - -; Eval the expression with current error_reporting(). Set to true if you want -; error_reporting(0) around the eval(). -; http://php.net/assert.quiet-eval -;assert.quiet_eval = 0 - -[COM] -; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs -; http://php.net/com.typelib-file -;com.typelib_file = - -; allow Distributed-COM calls -; http://php.net/com.allow-dcom -;com.allow_dcom = true - -; autoregister constants of a components typlib on com_load() -; http://php.net/com.autoregister-typelib -;com.autoregister_typelib = true - -; register constants casesensitive -; http://php.net/com.autoregister-casesensitive -;com.autoregister_casesensitive = false - -; show warnings on duplicate constant registrations -; http://php.net/com.autoregister-verbose -;com.autoregister_verbose = true - -; The default character set code-page to use when passing strings to and from COM objects. -; Default: system ANSI code page -;com.code_page= - -[mbstring] -; language for internal character representation. -; This affects mb_send_mail() and mbstring.detect_order. -; http://php.net/mbstring.language -;mbstring.language = Japanese - -; Use of this INI entry is deprecated, use global internal_encoding instead. -; internal/script encoding. -; Some encoding cannot work as internal encoding. (e.g. SJIS, BIG5, ISO-2022-*) -; If empty, default_charset or internal_encoding or iconv.internal_encoding is used. -; The precedence is: default_charset < internal_encoding < iconv.internal_encoding -;mbstring.internal_encoding = - -; Use of this INI entry is deprecated, use global input_encoding instead. -; http input encoding. -; mbstring.encoding_traslation = On is needed to use this setting. -; If empty, default_charset or input_encoding or mbstring.input is used. -; The precedence is: default_charset < intput_encoding < mbsting.http_input -; http://php.net/mbstring.http-input -;mbstring.http_input = - -; Use of this INI entry is deprecated, use global output_encoding instead. -; http output encoding. -; mb_output_handler must be registered as output buffer to function. -; If empty, default_charset or output_encoding or mbstring.http_output is used. -; The precedence is: default_charset < output_encoding < mbstring.http_output -; To use an output encoding conversion, mbstring's output handler must be set -; otherwise output encoding conversion cannot be performed. -; http://php.net/mbstring.http-output -;mbstring.http_output = - -; enable automatic encoding translation according to -; mbstring.internal_encoding setting. Input chars are -; converted to internal encoding by setting this to On. -; Note: Do _not_ use automatic encoding translation for -; portable libs/applications. -; http://php.net/mbstring.encoding-translation -;mbstring.encoding_translation = Off - -; automatic encoding detection order. -; "auto" detect order is changed according to mbstring.language -; http://php.net/mbstring.detect-order -;mbstring.detect_order = auto - -; substitute_character used when character cannot be converted -; one from another -; http://php.net/mbstring.substitute-character -;mbstring.substitute_character = none - -; overload(replace) single byte functions by mbstring functions. -; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(), -; etc. Possible values are 0,1,2,4 or combination of them. -; For example, 7 for overload everything. -; 0: No overload -; 1: Overload mail() function -; 2: Overload str*() functions -; 4: Overload ereg*() functions -; http://php.net/mbstring.func-overload -;mbstring.func_overload = 0 - -; enable strict encoding detection. -; Default: Off -;mbstring.strict_detection = On - -; This directive specifies the regex pattern of content types for which mb_output_handler() -; is activated. -; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml) -;mbstring.http_output_conv_mimetype= - -[gd] -; Tell the jpeg decode to ignore warnings and try to create -; a gd image. The warning will then be displayed as notices -; disabled by default -; http://php.net/gd.jpeg-ignore-warning -;gd.jpeg_ignore_warning = 0 - -[exif] -; Exif UNICODE user comments are handled as UCS-2BE/UCS-2LE and JIS as JIS. -; With mbstring support this will automatically be converted into the encoding -; given by corresponding encode setting. When empty mbstring.internal_encoding -; is used. For the decode settings you can distinguish between motorola and -; intel byte order. A decode setting cannot be empty. -; http://php.net/exif.encode-unicode -;exif.encode_unicode = ISO-8859-15 - -; http://php.net/exif.decode-unicode-motorola -;exif.decode_unicode_motorola = UCS-2BE - -; http://php.net/exif.decode-unicode-intel -;exif.decode_unicode_intel = UCS-2LE - -; http://php.net/exif.encode-jis -;exif.encode_jis = - -; http://php.net/exif.decode-jis-motorola -;exif.decode_jis_motorola = JIS - -; http://php.net/exif.decode-jis-intel -;exif.decode_jis_intel = JIS - -[Tidy] -; The path to a default tidy configuration file to use when using tidy -; http://php.net/tidy.default-config -;tidy.default_config = /usr/local/lib/php/default.tcfg - -; Should tidy clean and repair output automatically? -; WARNING: Do not use this option if you are generating non-html content -; such as dynamic images -; http://php.net/tidy.clean-output -tidy.clean_output = Off - -[soap] -; Enables or disables WSDL caching feature. -; http://php.net/soap.wsdl-cache-enabled -soap.wsdl_cache_enabled=1 - -; Sets the directory name where SOAP extension will put cache files. -; http://php.net/soap.wsdl-cache-dir -soap.wsdl_cache_dir="/tmp" - -; (time to live) Sets the number of second while cached file will be used -; instead of original one. -; http://php.net/soap.wsdl-cache-ttl -soap.wsdl_cache_ttl=86400 - -; Sets the size of the cache limit. (Max. number of WSDL files to cache) -soap.wsdl_cache_limit = 5 - -[sysvshm] -; A default size of the shared memory segment -;sysvshm.init_mem = 10000 - -[ldap] -; Sets the maximum number of open links or -1 for unlimited. -ldap.max_links = -1 - -[mcrypt] -; For more information about mcrypt settings see http://php.net/mcrypt-module-open - -; Directory where to load mcrypt algorithms -; Default: Compiled in into libmcrypt (usually /usr/local/lib/libmcrypt) -;mcrypt.algorithms_dir= - -; Directory where to load mcrypt modes -; Default: Compiled in into libmcrypt (usually /usr/local/lib/libmcrypt) -;mcrypt.modes_dir= - -[dba] -;dba.default_handler= - -[opcache] -; Determines if Zend OPCache is enabled -;opcache.enable=0 - -; Determines if Zend OPCache is enabled for the CLI version of PHP -;opcache.enable_cli=0 - -; The OPcache shared memory storage size. -;opcache.memory_consumption=64 - -; The amount of memory for interned strings in Mbytes. -;opcache.interned_strings_buffer=4 - -; The maximum number of keys (scripts) in the OPcache hash table. -; Only numbers between 200 and 1000000 are allowed. -;opcache.max_accelerated_files=2000 - -; The maximum percentage of "wasted" memory until a restart is scheduled. -;opcache.max_wasted_percentage=5 - -; When this directive is enabled, the OPcache appends the current working -; directory to the script key, thus eliminating possible collisions between -; files with the same name (basename). Disabling the directive improves -; performance, but may break existing applications. -;opcache.use_cwd=1 - -; When disabled, you must reset the OPcache manually or restart the -; webserver for changes to the filesystem to take effect. -;opcache.validate_timestamps=1 - -; How often (in seconds) to check file timestamps for changes to the shared -; memory storage allocation. ("1" means validate once per second, but only -; once per request. "0" means always validate) -;opcache.revalidate_freq=2 - -; Enables or disables file search in include_path optimization -;opcache.revalidate_path=0 - -; If disabled, all PHPDoc comments are dropped from the code to reduce the -; size of the optimized code. -;opcache.save_comments=1 - -; If enabled, a fast shutdown sequence is used for the accelerated code -; Depending on the used Memory Manager this may cause some incompatibilities. -;opcache.fast_shutdown=0 - -; Allow file existence override (file_exists, etc.) performance feature. -;opcache.enable_file_override=0 - -; A bitmask, where each bit enables or disables the appropriate OPcache -; passes -;opcache.optimization_level=0xffffffff - -;opcache.inherited_hack=1 -;opcache.dups_fix=0 - -; The location of the OPcache blacklist file (wildcards allowed). -; Each OPcache blacklist file is a text file that holds the names of files -; that should not be accelerated. The file format is to add each filename -; to a new line. The filename may be a full path or just a file prefix -; (i.e., /var/www/x blacklists all the files and directories in /var/www -; that start with 'x'). Line starting with a ; are ignored (comments). -;opcache.blacklist_filename= - -; Allows exclusion of large files from being cached. By default all files -; are cached. -;opcache.max_file_size=0 - -; Check the cache checksum each N requests. -; The default value of "0" means that the checks are disabled. -;opcache.consistency_checks=0 - -; How long to wait (in seconds) for a scheduled restart to begin if the cache -; is not being accessed. -;opcache.force_restart_timeout=180 - -; OPcache error_log file name. Empty string assumes "stderr". -;opcache.error_log= - -; All OPcache errors go to the Web server log. -; By default, only fatal errors (level 0) or errors (level 1) are logged. -; You can also enable warnings (level 2), info messages (level 3) or -; debug messages (level 4). -;opcache.log_verbosity_level=1 - -; Preferred Shared Memory back-end. Leave empty and let the system decide. -;opcache.preferred_memory_model= - -; Protect the shared memory from unexpected writing during script execution. -; Useful for internal debugging only. -;opcache.protect_memory=0 - -; Allows calling OPcache API functions only from PHP scripts which path is -; started from specified string. The default "" means no restriction -;opcache.restrict_api= - -; Mapping base of shared memory segments (for Windows only). All the PHP -; processes have to map shared memory into the same address space. This -; directive allows to manually fix the "Unable to reattach to base address" -; errors. -;opcache.mmap_base= - -; Enables and sets the second level cache directory. -; It should improve performance when SHM memory is full, at server restart or -; SHM reset. The default "" disables file based caching. -;opcache.file_cache= - -; Enables or disables opcode caching in shared memory. -;opcache.file_cache_only=0 - -; Enables or disables checksum validation when script loaded from file cache. -;opcache.file_cache_consistency_checks=1 - -; Implies opcache.file_cache_only=1 for a certain process that failed to -; reattach to the shared memory (for Windows only). Explicitly enabled file -; cache is required. -;opcache.file_cache_fallback=1 - -; Enables or disables copying of PHP code (text segment) into HUGE PAGES. -; This should improve performance, but requires appropriate OS configuration. -;opcache.huge_code_pages=1 - -; Validate cached file permissions. -; opcache.validate_permission=0 - -; Prevent name collisions in chroot'ed environment. -; opcache.validate_root=0 - -[curl] -; A default value for the CURLOPT_CAINFO option. This is required to be an -; absolute path. -;curl.cainfo = - -[openssl] -; The location of a Certificate Authority (CA) file on the local filesystem -; to use when verifying the identity of SSL/TLS peers. Most users should -; not specify a value for this directive as PHP will attempt to use the -; OS-managed cert stores in its absence. If specified, this value may still -; be overridden on a per-stream basis via the "cafile" SSL stream context -; option. -;openssl.cafile= - -; If openssl.cafile is not specified or if the CA file is not found, the -; directory pointed to by openssl.capath is searched for a suitable -; certificate. This value must be a correctly hashed certificate directory. -; Most users should not specify a value for this directive as PHP will -; attempt to use the OS-managed cert stores in its absence. If specified, -; this value may still be overridden on a per-stream basis via the "capath" -; SSL stream context option. -;openssl.capath= - -; Local Variables: -; tab-width: 4 -; End: diff --git a/misc/sampleconfigs/smb.conf.jessie-default.sample b/misc/sampleconfigs/smb.conf.jessie-default.sample deleted file mode 100755 index 09e2ee061..000000000 --- a/misc/sampleconfigs/smb.conf.jessie-default.sample +++ /dev/null @@ -1,264 +0,0 @@ -# -# Sample configuration file for the Samba suite for Debian GNU/Linux. -# -# -# This is the main Samba configuration file. You should read the -# smb.conf(5) manual page in order to understand the options listed -# here. Samba has a huge number of configurable options most of which -# are not shown in this example -# -# Some options that are often worth tuning have been included as -# commented-out examples in this file. -# - When such options are commented with ";", the proposed setting -# differs from the default Samba behaviour -# - When commented with "#", the proposed setting is the default -# behaviour of Samba but the option is considered important -# enough to be mentioned here -# -# NOTE: Whenever you modify this file you should run the command -# "testparm" to check that you have not made any basic syntactic -# errors. - -#======================= Global Settings ======================= - -[global] - -## Browsing/Identification ### - -# Change this to the workgroup/NT-domain name your Samba server will part of - workgroup = WORKGROUP - -# Windows Internet Name Serving Support Section: -# WINS Support - Tells the NMBD component of Samba to enable its WINS Server - wins support = yes - -# WINS Server - Tells the NMBD components of Samba to be a WINS Client -# Note: Samba can be either a WINS Server, or a WINS Client, but NOT both -; wins server = w.x.y.z - -# This will prevent nmbd to search for NetBIOS names through DNS. - dns proxy = no - -#### Networking #### - -# The specific set of interfaces / networks to bind to -# This can be either the interface name or an IP address/netmask; -# interface names are normally preferred -; interfaces = 127.0.0.0/8 eth0 - -# Only bind to the named interfaces and/or networks; you must use the -# 'interfaces' option above to use this. -# It is recommended that you enable this feature if your Samba machine is -# not protected by a firewall or is a firewall itself. However, this -# option cannot handle dynamic or non-broadcast interfaces correctly. -; bind interfaces only = yes - - - -#### Debugging/Accounting #### - -# This tells Samba to use a separate log file for each machine -# that connects - log file = /var/log/samba/log.%m - -# Cap the size of the individual log files (in KiB). - max log size = 1000 - -# If you want Samba to only log through syslog then set the following -# parameter to 'yes'. -# syslog only = no - -# We want Samba to log a minimum amount of information to syslog. Everything -# should go to /var/log/samba/log.{smbd,nmbd} instead. If you want to log -# through syslog you should set the following parameter to something higher. - syslog = 0 - -# Do something sensible when Samba crashes: mail the admin a backtrace - panic action = /usr/share/samba/panic-action %d - - -####### Authentication ####### - -# Server role. Defines in which mode Samba will operate. Possible -# values are "standalone server", "member server", "classic primary -# domain controller", "classic backup domain controller", "active -# directory domain controller". -# -# Most people will want "standalone sever" or "member server". -# Running as "active directory domain controller" will require first -# running "samba-tool domain provision" to wipe databases and create a -# new domain. - server role = standalone server - -# If you are using encrypted passwords, Samba will need to know what -# password database type you are using. - passdb backend = tdbsam - - obey pam restrictions = yes - -# This boolean parameter controls whether Samba attempts to sync the Unix -# password with the SMB password when the encrypted SMB password in the -# passdb is changed. - unix password sync = yes - -# For Unix password sync to work on a Debian GNU/Linux system, the following -# parameters must be set (thanks to Ian Kahan < for -# sending the correct chat script for the passwd program in Debian Sarge). - passwd program = /usr/bin/passwd %u - passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* . - -# This boolean controls whether PAM will be used for password changes -# when requested by an SMB client instead of the program listed in -# 'passwd program'. The default is 'no'. - pam password change = yes - -# This option controls how unsuccessful authentication attempts are mapped -# to anonymous connections - map to guest = bad user - -########## Domains ########### - -# -# The following settings only takes effect if 'server role = primary -# classic domain controller', 'server role = backup domain controller' -# or 'domain logons' is set -# - -# It specifies the location of the user's -# profile directory from the client point of view) The following -# required a [profiles] share to be setup on the samba server (see -# below) -; logon path = \\%N\profiles\%U -# Another common choice is storing the profile in the user's home directory -# (this is Samba's default) -# logon path = \\%N\%U\profile - -# The following setting only takes effect if 'domain logons' is set -# It specifies the location of a user's home directory (from the client -# point of view) -; logon drive = H: -# logon home = \\%N\%U - -# The following setting only takes effect if 'domain logons' is set -# It specifies the script to run during logon. The script must be stored -# in the [netlogon] share -# NOTE: Must be store in 'DOS' file format convention -; logon script = logon.cmd - -# This allows Unix users to be created on the domain controller via the SAMR -# RPC pipe. The example command creates a user account with a disabled Unix -# password; please adapt to your needs -; add user script = /usr/sbin/adduser --quiet --disabled-password --gecos "" %u - -# This allows machine accounts to be created on the domain controller via the -# SAMR RPC pipe. -# The following assumes a "machines" group exists on the system -; add machine script = /usr/sbin/useradd -g machines -c "%u machine account" -d /var/lib/samba -s /bin/false %u - -# This allows Unix groups to be created on the domain controller via the SAMR -# RPC pipe. -; add group script = /usr/sbin/addgroup --force-badname %g - -############ Misc ############ - -# Using the following line enables you to customise your configuration -# on a per machine basis. The %m gets replaced with the netbios name -# of the machine that is connecting -; include = /home/samba/etc/smb.conf.%m - -# Some defaults for winbind (make sure you're not using the ranges -# for something else.) -; idmap uid = 10000-20000 -; idmap gid = 10000-20000 -; template shell = /bin/bash - -# Setup usershare options to enable non-root users to share folders -# with the net usershare command. - -# Maximum number of usershare. 0 (default) means that usershare is disabled. -; usershare max shares = 100 - -# Allow users who've been granted usershare privileges to create -# public shares, not just authenticated ones - usershare allow guests = yes - -#======================= Share Definitions ======================= - -[homes] - comment = Home Directories - browseable = no - -# By default, the home directories are exported read-only. Change the -# next parameter to 'no' if you want to be able to write to them. - read only = yes - -# File creation mask is set to 0700 for security reasons. If you want to -# create files with group=rw permissions, set next parameter to 0775. - create mask = 0700 - -# Directory creation mask is set to 0700 for security reasons. If you want to -# create dirs. with group=rw permissions, set next parameter to 0775. - directory mask = 0700 - -# By default, \\server\username shares can be connected to by anyone -# with access to the samba server. -# The following parameter makes sure that only "username" can connect -# to \\server\username -# This might need tweaking when using external authentication schemes - valid users = %S - -# Un-comment the following and create the netlogon directory for Domain Logons -# (you need to configure Samba to act as a domain controller too.) -;[netlogon] -; comment = Network Logon Service -; path = /home/samba/netlogon -; guest ok = yes -; read only = yes - -# Un-comment the following and create the profiles directory to store -# users profiles (see the "logon path" option above) -# (you need to configure Samba to act as a domain controller too.) -# The path below should be writable by all users so that their -# profile directory may be created the first time they log on -;[profiles] -; comment = Users profiles -; path = /home/samba/profiles -; guest ok = no -; browseable = no -; create mask = 0600 -; directory mask = 0700 - -[printers] - comment = All Printers - browseable = no - path = /var/spool/samba - printable = yes - guest ok = no - read only = yes - create mask = 0700 - -# Windows clients look for this share name as a source of downloadable -# printer drivers -[print$] - comment = Printer Drivers - path = /var/lib/samba/printers - browseable = yes - read only = yes - guest ok = no -# Uncomment to allow remote administration of Windows print drivers. -# You may need to replace 'lpadmin' with the name of the group your -# admin users are members of. -# Please note that you also need to set appropriate Unix permissions -# to the drivers directory for these users to have write rights in it -; write list = root, @lpadmin - -[pi_jukebox] - comment= Pi Jukebox - path=/home/pi/RPi-Jukebox-RFID/shared - browseable=Yes - writeable=Yes - only guest=no - create mask=0777 - directory mask=0777 - public=no - diff --git a/misc/sampleconfigs/smb.conf.stretch-default.sample b/misc/sampleconfigs/smb.conf.stretch-default.sample deleted file mode 100755 index b8b938b53..000000000 --- a/misc/sampleconfigs/smb.conf.stretch-default.sample +++ /dev/null @@ -1,263 +0,0 @@ -# -# Sample configuration file for the Samba suite for Debian GNU/Linux. -# -# -# This is the main Samba configuration file. You should read the -# smb.conf(5) manual page in order to understand the options listed -# here. Samba has a huge number of configurable options most of which -# are not shown in this example -# -# Some options that are often worth tuning have been included as -# commented-out examples in this file. -# - When such options are commented with ";", the proposed setting -# differs from the default Samba behaviour -# - When commented with "#", the proposed setting is the default -# behaviour of Samba but the option is considered important -# enough to be mentioned here -# -# NOTE: Whenever you modify this file you should run the command -# "testparm" to check that you have not made any basic syntactic -# errors. - -#======================= Global Settings ======================= - -[global] - -## Browsing/Identification ### - -# Change this to the workgroup/NT-domain name your Samba server will part of - workgroup = WORKGROUP - -# Windows Internet Name Serving Support Section: -# WINS Support - Tells the NMBD component of Samba to enable its WINS Server -# wins support = no - -# WINS Server - Tells the NMBD components of Samba to be a WINS Client -# Note: Samba can be either a WINS Server, or a WINS Client, but NOT both -; wins server = w.x.y.z - -# This will prevent nmbd to search for NetBIOS names through DNS. - dns proxy = no - -#### Networking #### - -# The specific set of interfaces / networks to bind to -# This can be either the interface name or an IP address/netmask; -# interface names are normally preferred -; interfaces = 127.0.0.0/8 eth0 - -# Only bind to the named interfaces and/or networks; you must use the -# 'interfaces' option above to use this. -# It is recommended that you enable this feature if your Samba machine is -# not protected by a firewall or is a firewall itself. However, this -# option cannot handle dynamic or non-broadcast interfaces correctly. -; bind interfaces only = yes - - - -#### Debugging/Accounting #### - -# This tells Samba to use a separate log file for each machine -# that connects - log file = /var/log/samba/log.%m - -# Cap the size of the individual log files (in KiB). - max log size = 1000 - -# If you want Samba to only log through syslog then set the following -# parameter to 'yes'. -# syslog only = no - -# We want Samba to log a minimum amount of information to syslog. Everything -# should go to /var/log/samba/log.{smbd,nmbd} instead. If you want to log -# through syslog you should set the following parameter to something higher. - syslog = 0 - -# Do something sensible when Samba crashes: mail the admin a backtrace - panic action = /usr/share/samba/panic-action %d - - -####### Authentication ####### - -# Server role. Defines in which mode Samba will operate. Possible -# values are "standalone server", "member server", "classic primary -# domain controller", "classic backup domain controller", "active -# directory domain controller". -# -# Most people will want "standalone sever" or "member server". -# Running as "active directory domain controller" will require first -# running "samba-tool domain provision" to wipe databases and create a -# new domain. - server role = standalone server - -# If you are using encrypted passwords, Samba will need to know what -# password database type you are using. - passdb backend = tdbsam - - obey pam restrictions = yes - -# This boolean parameter controls whether Samba attempts to sync the Unix -# password with the SMB password when the encrypted SMB password in the -# passdb is changed. - unix password sync = yes - -# For Unix password sync to work on a Debian GNU/Linux system, the following -# parameters must be set (thanks to Ian Kahan < for -# sending the correct chat script for the passwd program in Debian Sarge). - passwd program = /usr/bin/passwd %u - passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* . - -# This boolean controls whether PAM will be used for password changes -# when requested by an SMB client instead of the program listed in -# 'passwd program'. The default is 'no'. - pam password change = yes - -# This option controls how unsuccessful authentication attempts are mapped -# to anonymous connections - map to guest = bad user - -########## Domains ########### - -# -# The following settings only takes effect if 'server role = primary -# classic domain controller', 'server role = backup domain controller' -# or 'domain logons' is set -# - -# It specifies the location of the user's -# profile directory from the client point of view) The following -# required a [profiles] share to be setup on the samba server (see -# below) -; logon path = \\%N\profiles\%U -# Another common choice is storing the profile in the user's home directory -# (this is Samba's default) -# logon path = \\%N\%U\profile - -# The following setting only takes effect if 'domain logons' is set -# It specifies the location of a user's home directory (from the client -# point of view) -; logon drive = H: -# logon home = \\%N\%U - -# The following setting only takes effect if 'domain logons' is set -# It specifies the script to run during logon. The script must be stored -# in the [netlogon] share -# NOTE: Must be store in 'DOS' file format convention -; logon script = logon.cmd - -# This allows Unix users to be created on the domain controller via the SAMR -# RPC pipe. The example command creates a user account with a disabled Unix -# password; please adapt to your needs -; add user script = /usr/sbin/adduser --quiet --disabled-password --gecos "" %u - -# This allows machine accounts to be created on the domain controller via the -# SAMR RPC pipe. -# The following assumes a "machines" group exists on the system -; add machine script = /usr/sbin/useradd -g machines -c "%u machine account" -d /var/lib/samba -s /bin/false %u - -# This allows Unix groups to be created on the domain controller via the SAMR -# RPC pipe. -; add group script = /usr/sbin/addgroup --force-badname %g - -############ Misc ############ - -# Using the following line enables you to customise your configuration -# on a per machine basis. The %m gets replaced with the netbios name -# of the machine that is connecting -; include = /home/samba/etc/smb.conf.%m - -# Some defaults for winbind (make sure you're not using the ranges -# for something else.) -; idmap uid = 10000-20000 -; idmap gid = 10000-20000 -; template shell = /bin/bash - -# Setup usershare options to enable non-root users to share folders -# with the net usershare command. - -# Maximum number of usershare. 0 (default) means that usershare is disabled. -; usershare max shares = 100 - -# Allow users who've been granted usershare privileges to create -# public shares, not just authenticated ones - usershare allow guests = yes - -#======================= Share Definitions ======================= - -[homes] - comment = Home Directories - browseable = no - -# By default, the home directories are exported read-only. Change the -# next parameter to 'no' if you want to be able to write to them. - read only = yes - -# File creation mask is set to 0700 for security reasons. If you want to -# create files with group=rw permissions, set next parameter to 0775. - create mask = 0700 - -# Directory creation mask is set to 0700 for security reasons. If you want to -# create dirs. with group=rw permissions, set next parameter to 0775. - directory mask = 0700 - -# By default, \\server\username shares can be connected to by anyone -# with access to the samba server. -# The following parameter makes sure that only "username" can connect -# to \\server\username -# This might need tweaking when using external authentication schemes - valid users = %S - -# Un-comment the following and create the netlogon directory for Domain Logons -# (you need to configure Samba to act as a domain controller too.) -;[netlogon] -; comment = Network Logon Service -; path = /home/samba/netlogon -; guest ok = yes -; read only = yes - -# Un-comment the following and create the profiles directory to store -# users profiles (see the "logon path" option above) -# (you need to configure Samba to act as a domain controller too.) -# The path below should be writable by all users so that their -# profile directory may be created the first time they log on -;[profiles] -; comment = Users profiles -; path = /home/samba/profiles -; guest ok = no -; browseable = no -; create mask = 0600 -; directory mask = 0700 - -[printers] - comment = All Printers - browseable = no - path = /var/spool/samba - printable = yes - guest ok = no - read only = yes - create mask = 0700 - -# Windows clients look for this share name as a source of downloadable -# printer drivers -[print$] - comment = Printer Drivers - path = /var/lib/samba/printers - browseable = yes - read only = yes - guest ok = no -# Uncomment to allow remote administration of Windows print drivers. -# You may need to replace 'lpadmin' with the name of the group your -# admin users are members of. -# Please note that you also need to set appropriate Unix permissions -# to the drivers directory for these users to have write rights in it -; write list = root, @lpadmin - -[pi_jukebox] - comment= Pi Jukebox - path=/home/pi/RPi-Jukebox-RFID/shared - browseable=Yes - writeable=Yes - only guest=no - create mask=0777 - directory mask=0777 - public=no diff --git a/misc/sampleconfigs/smb.conf.stretch-default2.sample b/misc/sampleconfigs/smb.conf.stretch-default2.sample deleted file mode 100755 index 7266bc809..000000000 --- a/misc/sampleconfigs/smb.conf.stretch-default2.sample +++ /dev/null @@ -1,274 +0,0 @@ -# -# Sample configuration file for the Samba suite for Debian GNU/Linux. -# -# -# This is the main Samba configuration file. You should read the -# smb.conf(5) manual page in order to understand the options listed -# here. Samba has a huge number of configurable options most of which -# are not shown in this example -# -# Some options that are often worth tuning have been included as -# commented-out examples in this file. -# - When such options are commented with ";", the proposed setting -# differs from the default Samba behaviour -# - When commented with "#", the proposed setting is the default -# behaviour of Samba but the option is considered important -# enough to be mentioned here -# -# NOTE: Whenever you modify this file you should run the command -# "testparm" to check that you have not made any basic syntactic -# errors. - -#======================= Global Settings ======================= - -[global] - -## Browsing/Identification ### - -# Change this to the workgroup/NT-domain name your Samba server will part of - workgroup = WORKGROUP - -# Windows Internet Name Serving Support Section: -# WINS Support - Tells the NMBD component of Samba to enable its WINS Server -# wins support = no - -# WINS Server - Tells the NMBD components of Samba to be a WINS Client -# Note: Samba can be either a WINS Server, or a WINS Client, but NOT both -; wins server = w.x.y.z - -# This will prevent nmbd to search for NetBIOS names through DNS. - dns proxy = no - -#### Networking #### - -# The specific set of interfaces / networks to bind to -# This can be either the interface name or an IP address/netmask; -# interface names are normally preferred -; interfaces = 127.0.0.0/8 eth0 - -# Only bind to the named interfaces and/or networks; you must use the -# 'interfaces' option above to use this. -# It is recommended that you enable this feature if your Samba machine is -# not protected by a firewall or is a firewall itself. However, this -# option cannot handle dynamic or non-broadcast interfaces correctly. -; bind interfaces only = yes - - - -#### Debugging/Accounting #### - -# This tells Samba to use a separate log file for each machine -# that connects - log file = /var/log/samba/log.%m - -# Cap the size of the individual log files (in KiB). - max log size = 1000 - -# If you want Samba to only log through syslog then set the following -# parameter to 'yes'. -# syslog only = no - -# We want Samba to log a minimum amount of information to syslog. Everything -# should go to /var/log/samba/log.{smbd,nmbd} instead. If you want to log -# through syslog you should set the following parameter to something higher. - syslog = 0 - -# Do something sensible when Samba crashes: mail the admin a backtrace - panic action = /usr/share/samba/panic-action %d - - -####### Authentication ####### - -# Server role. Defines in which mode Samba will operate. Possible -# values are "standalone server", "member server", "classic primary -# domain controller", "classic backup domain controller", "active -# directory domain controller". -# -# Most people will want "standalone sever" or "member server". -# Running as "active directory domain controller" will require first -# running "samba-tool domain provision" to wipe databases and create a -# new domain. - server role = standalone server - -# If you are using encrypted passwords, Samba will need to know what -# password database type you are using. - passdb backend = tdbsam - - obey pam restrictions = yes - -# This boolean parameter controls whether Samba attempts to sync the Unix -# password with the SMB password when the encrypted SMB password in the -# passdb is changed. - unix password sync = yes - -# For Unix password sync to work on a Debian GNU/Linux system, the following -# parameters must be set (thanks to Ian Kahan < for -# sending the correct chat script for the passwd program in Debian Sarge). - passwd program = /usr/bin/passwd %u - passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* . - -# This boolean controls whether PAM will be used for password changes -# when requested by an SMB client instead of the program listed in -# 'passwd program'. The default is 'no'. - pam password change = yes - -# This option controls how unsuccessful authentication attempts are mapped -# to anonymous connections - map to guest = bad user - -########## Domains ########### - -# -# The following settings only takes effect if 'server role = primary -# classic domain controller', 'server role = backup domain controller' -# or 'domain logons' is set -# - -# It specifies the location of the user's -# profile directory from the client point of view) The following -# required a [profiles] share to be setup on the samba server (see -# below) -; logon path = \\%N\profiles\%U -# Another common choice is storing the profile in the user's home directory -# (this is Samba's default) -# logon path = \\%N\%U\profile - -# The following setting only takes effect if 'domain logons' is set -# It specifies the location of a user's home directory (from the client -# point of view) -; logon drive = H: -# logon home = \\%N\%U - -# The following setting only takes effect if 'domain logons' is set -# It specifies the script to run during logon. The script must be stored -# in the [netlogon] share -# NOTE: Must be store in 'DOS' file format convention -; logon script = logon.cmd - -# This allows Unix users to be created on the domain controller via the SAMR -# RPC pipe. The example command creates a user account with a disabled Unix -# password; please adapt to your needs -; add user script = /usr/sbin/adduser --quiet --disabled-password --gecos "" %u - -# This allows machine accounts to be created on the domain controller via the -# SAMR RPC pipe. -# The following assumes a "machines" group exists on the system -; add machine script = /usr/sbin/useradd -g machines -c "%u machine account" -d /var/lib/samba -s /bin/false %u - -# This allows Unix groups to be created on the domain controller via the SAMR -# RPC pipe. -; add group script = /usr/sbin/addgroup --force-badname %g - -############ Misc ############ - -# Using the following line enables you to customise your configuration -# on a per machine basis. The %m gets replaced with the netbios name -# of the machine that is connecting -; include = /home/samba/etc/smb.conf.%m - -# Some defaults for winbind (make sure you're not using the ranges -# for something else.) -; idmap uid = 10000-20000 -; idmap gid = 10000-20000 -; template shell = /bin/bash - -# Setup usershare options to enable non-root users to share folders -# with the net usershare command. - -# Maximum number of usershare. 0 (default) means that usershare is disabled. -; usershare max shares = 100 - -# Allow users who've been granted usershare privileges to create -# public shares, not just authenticated ones - usershare allow guests = yes - -#======================= Share Definitions ======================= - -[homes] - comment = Home Directories - browseable = no - -# By default, the home directories are exported read-only. Change the -# next parameter to 'no' if you want to be able to write to them. - read only = yes - -# File creation mask is set to 0700 for security reasons. If you want to -# create files with group=rw permissions, set next parameter to 0775. - create mask = 0700 - -# Directory creation mask is set to 0700 for security reasons. If you want to -# create dirs. with group=rw permissions, set next parameter to 0775. - directory mask = 0700 - -# By default, \\server\username shares can be connected to by anyone -# with access to the samba server. -# The following parameter makes sure that only "username" can connect -# to \\server\username -# This might need tweaking when using external authentication schemes - valid users = %S - -# Un-comment the following and create the netlogon directory for Domain Logons -# (you need to configure Samba to act as a domain controller too.) -;[netlogon] -; comment = Network Logon Service -; path = /home/samba/netlogon -; guest ok = yes -; read only = yes - -# Un-comment the following and create the profiles directory to store -# users profiles (see the "logon path" option above) -# (you need to configure Samba to act as a domain controller too.) -# The path below should be writable by all users so that their -# profile directory may be created the first time they log on -;[profiles] -; comment = Users profiles -; path = /home/samba/profiles -; guest ok = no -; browseable = no -; create mask = 0600 -; directory mask = 0700 - -#[printers] -# comment = All Printers -# browseable = no -# path = /var/spool/samba -# printable = yes -# guest ok = no -# read only = yes -# create mask = 0700 - -# Windows clients look for this share name as a source of downloadable -# printer drivers -# [print$] -# comment = Printer Drivers -# path = /var/lib/samba/printers -# browseable = yes -# read only = yes -# guest ok = no -# Uncomment to allow remote administration of Windows print drivers. -# You may need to replace 'lpadmin' with the name of the group your -# admin users are members of. -# Please note that you also need to set appropriate Unix permissions -# to the drivers directory for these users to have write rights in it -; write list = root, @lpadmin - -[phoniebox] - comment= Pi Jukebox - path=/home/pi/RPi-Jukebox-RFID/shared - browseable=Yes - writeable=Yes - only guest=no - create mask=0777 - directory mask=0777 - public=no - -# if the audiofiles are not in 'shared', we need this -[phoniebox_audiofile] - comment= Pi Jukebox - path=%DIRaudioFolders% - browseable=Yes - writeable=Yes - only guest=no - create mask=0777 - directory mask=0777 - public=no diff --git a/misc/sampleconfigs/sudoers.jessie-default.sample b/misc/sampleconfigs/sudoers.jessie-default.sample deleted file mode 100755 index 78111dc9f..000000000 --- a/misc/sampleconfigs/sudoers.jessie-default.sample +++ /dev/null @@ -1,30 +0,0 @@ -# -# This file MUST be edited with the 'visudo' command as root. -# -# Please consider adding local content in /etc/sudoers.d/ instead of -# directly modifying this file. -# -# See the man page for details on how to write a sudoers file. -# -Defaults env_reset -Defaults mail_badpass -Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - -# Host alias specification - -# User alias specification - -# Cmnd alias specification - -# User privilege specification -root ALL=(ALL:ALL) ALL - -# Allow members of group sudo to execute any command -%sudo ALL=(ALL:ALL) ALL - -# See sudoers(5) for more information on "#include" directives: - -#includedir /etc/sudoers.d - -www-data ALL=(ALL) NOPASSWD: ALL -mopidy ALL=NOPASSWD: /usr/local/lib/python2.7/dist-packages/mopidy_iris/system.sh diff --git a/misc/sampleconfigs/sudoers.stretch-default.sample b/misc/sampleconfigs/sudoers.stretch-default.sample deleted file mode 100755 index c98e7e85c..000000000 --- a/misc/sampleconfigs/sudoers.stretch-default.sample +++ /dev/null @@ -1,29 +0,0 @@ -# -# This file MUST be edited with the 'visudo' command as root. -# -# Please consider adding local content in /etc/sudoers.d/ instead of -# directly modifying this file. -# -# See the man page for details on how to write a sudoers file. -# -Defaults env_reset -Defaults mail_badpass -Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - -# Host alias specification - -# User alias specification - -# Cmnd alias specification - -# User privilege specification -root ALL=(ALL:ALL) ALL - -# Allow members of group sudo to execute any command -%sudo ALL=(ALL:ALL) ALL - -# See sudoers(5) for more information on "#include" directives: - -#includedir /etc/sudoers.d -www-data ALL=(ALL) NOPASSWD: ALL -mopidy ALL=NOPASSWD: /usr/local/lib/python2.7/dist-packages/mopidy_iris/system.sh diff --git a/misc/sampleconfigs/wpa_supplicant.conf.stretch.sample b/misc/sampleconfigs/wpa_supplicant.conf.stretch.sample deleted file mode 100644 index 37c75113f..000000000 --- a/misc/sampleconfigs/wpa_supplicant.conf.stretch.sample +++ /dev/null @@ -1,9 +0,0 @@ -ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev -update_config=1 -country=%WIFIcountryCode% - -network={ - ssid="%WIFIssid%" - psk="%WIFIpass%" - key_mgmt=WPA-PSK -} \ No newline at end of file diff --git a/packages-autohotspot.txt b/packages-autohotspot.txt new file mode 100644 index 000000000..833eeb020 --- /dev/null +++ b/packages-autohotspot.txt @@ -0,0 +1,6 @@ +# Define packages for apt-get. These can be installed with +# 'sed 's/#.*//g' packages.txt | xargs sudo apt-get install' + +dnsmasq +hostapd +iw diff --git a/packages-raspberrypi.txt b/packages-raspberrypi.txt new file mode 100644 index 000000000..abff17ec9 --- /dev/null +++ b/packages-raspberrypi.txt @@ -0,0 +1,4 @@ +# Define packages for apt-get. These can be installed with +# 'sed 's/#.*//g' packages.txt | xargs sudo apt-get install' + +raspberrypi-kernel-headers diff --git a/packages-spotify.txt b/packages-spotify.txt new file mode 100644 index 000000000..862f2c2a3 --- /dev/null +++ b/packages-spotify.txt @@ -0,0 +1,13 @@ +# Define packages for apt-get. These can be installed with +# 'sed 's/#.*//g' packages.txt | xargs sudo apt-get install' + +libspotify-dev +libspotify12 +python3-cffi +python3-ply +python3-pycparser +python3-spotify +mopidy +mopidy-mpd +mopidy-local +mopidy-spotify diff --git a/packages.txt b/packages.txt new file mode 100644 index 000000000..68e201c29 --- /dev/null +++ b/packages.txt @@ -0,0 +1,30 @@ +# Define packages for apt-get. These can be installed with +# 'sed 's/#.*//g' packages.txt | xargs sudo apt-get install' + +samba +samba-common-bin +gcc +lighttpd +php-common +php-cgi +php +at +mpd +mpc +mpg123 +git +ffmpeg +resolvconf +spi-tools +netcat-traditional +alsa-utils +lsof +procps +python3 +python3-dev +python3-pip +python3-setuptools +python3-wheel +python3-mutagen +python3-gpiozero +python3-spidev diff --git a/requirements-gmusic.txt b/requirements-gmusic.txt deleted file mode 100644 index 39e13ce36..000000000 --- a/requirements-gmusic.txt +++ /dev/null @@ -1,3 +0,0 @@ -# Google Music related requirements (in addition to requirements-spotify.txt) -# You need to install these with `sudo pip install --upgrade --force-reinstall -r requirements-gmusic.txt` -Mopidy-Gmusic diff --git a/requirements-spotify.txt b/requirements-spotify.txt index 83fa3206f..b521b6ac6 100644 --- a/requirements-spotify.txt +++ b/requirements-spotify.txt @@ -1,3 +1,3 @@ # Spotify related requirements # You need to install these with `sudo pip install --upgrade --force-reinstall -r requirements-spotify.txt` - Mopidy-Iris==3.54.2 + Mopidy-Iris==3.69.2 diff --git a/requirements.txt b/requirements.txt index 21e820309..e15872843 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +# Test trigger # Library dependencies for the python code. You need to install these with # `sudo python3 -m pip install --upgrade --force-reinstall -r requirements.txt` before you can run this. @@ -6,7 +7,7 @@ # related libraries. evdev git+https://github.com/lthiery/SPI-Py.git#egg=spi-py -youtube_dl +youtube-dl pyserial RPi.GPIO diff --git a/scripts/Reader.py.pcsc b/scripts/Reader.py.pcsc index dac10de7c..e0d2cc374 100644 --- a/scripts/Reader.py.pcsc +++ b/scripts/Reader.py.pcsc @@ -63,7 +63,7 @@ class Reader: 'Failed to release context: ' + \ SCardGetErrorMessage(hresult)) - return(toHexString(response, PACK)) + return (toHexString(response, PACK)) except error as e: print(e) diff --git a/scripts/RegisterDevice.py b/scripts/RegisterDevice.py index 026a4ecb3..1198bb708 100755 --- a/scripts/RegisterDevice.py +++ b/scripts/RegisterDevice.py @@ -16,3 +16,6 @@ with open(path + '/deviceName.txt', 'w') as f: f.write(devices[dev_id].name) f.close() + +for dev in devices: + dev.close() diff --git a/scripts/activate_amplifier.py b/scripts/activate_amplifier.py index c51ecf59b..3d0150c74 100755 --- a/scripts/activate_amplifier.py +++ b/scripts/activate_amplifier.py @@ -9,7 +9,7 @@ # see for an example implementation with a PAM8403 digital amplifier # (PAM pin 12 connected to GPIO 26) -# https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Hardware-Hack-PAM8403-Poweroff +# https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Hardware-Hack-PAM8403-Amplifier-Power-Off # change this value based on which GPIO port the amplifier or other devices are connected to # Flexible Pinout diff --git a/scripts/helperscripts/DeleteAllConfig.sh b/scripts/helperscripts/DeleteAllConfig.sh index dc73e08e2..38081a051 100755 --- a/scripts/helperscripts/DeleteAllConfig.sh +++ b/scripts/helperscripts/DeleteAllConfig.sh @@ -1,7 +1,7 @@ #!/bin/bash -echo "This script will delete all config files" -echo "including mpd.conf and the like." +echo "This script will delete all config files" +echo "including mpd.conf and the like." read -r -p "Do you want to proceed? [y/N] " response case "$response" in [Yy][Ee][Ss]|[Yy]) @@ -34,14 +34,15 @@ sudo rm /home/pi/RPi-Jukebox-RFID/settings/Second_Swipe sudo rm /home/pi/RPi-Jukebox-RFID/settings/Playlists_Folders_Path sudo rm /home/pi/RPi-Jukebox-RFID/settings/ShowCover sudo rm /home/pi/RPi-Jukebox-RFID/scripts/gpio-buttons.py -sudo rm /etc/systemd/system/phoniebox-rfid-reader.service +sudo rm /etc/systemd/system/phoniebox-rfid-reader.service sudo rm /etc/systemd/system/phoniebox-startup-sound.service sudo rm /etc/systemd/system/phoniebox-gpio-buttons.service sudo rm /etc/systemd/system/phoniebox-idle-watchdog.service -sudo rm /etc/systemd/system/rfid-reader.service +sudo rm /etc/systemd/system/rfid-reader.service sudo rm /etc/systemd/system/startup-sound.service sudo rm /etc/systemd/system/gpio-buttons.service sudo rm /etc/systemd/system/idle-watchdog.service +sudo rm /etc/systemd/system/autohotspot.service sudo rm /etc/mpd.conf sudo rm /etc/locale.gen sudo rm /etc/default/locale diff --git a/scripts/helperscripts/README.md b/scripts/helperscripts/README.md index be4914a6e..7b22ab890 100644 --- a/scripts/helperscripts/README.md +++ b/scripts/helperscripts/README.md @@ -42,10 +42,6 @@ including mpd.conf and the like. Deletes sample folders with files and streams inside the $AUDIOFOLDERSPATH directory -## autohotspot - -Changed to autohotspot service - ## cli-player.py Command line player to play folders on the Phoniebox. @@ -66,5 +62,22 @@ not bound to any RFID card, and fixing broken links. A command line replacement some functionality of the phoniebox-web-ui, which challenges the raspberry pi zero. Using this small script significantly reduces resource usage on the system. +## setup_autohotspot.sh + +Script to setup the autohotspot feature. It automatically sets up a wifi hotspot if no known network is found. +This is already included in the main install script, but can also be run manually. Please perform a reboot after you changed the configuration. + +usage: +setup_autohotspot.sh \ \ \ \ \ \ +### activate +``` +chmod +x ./scripts/helperscripts/setup_autohotspot.sh +./scripts/helperscripts/setup_autohotspot.sh . YES phoniebox DE PlayItLoud 10.0.0.5 +``` +### deactivate +``` +chmod +x ./scripts/helperscripts/setup_autohotspot.sh +./scripts/helperscripts/setup_autohotspot.sh . NO +``` diff --git a/scripts/helperscripts/autohotspot b/scripts/helperscripts/autohotspot deleted file mode 100755 index af64f1dbf..000000000 --- a/scripts/helperscripts/autohotspot +++ /dev/null @@ -1,169 +0,0 @@ -#!/bin/bash -#version 0.95-41-N/HS - -#You may share this script on the condition a reference to RaspberryConnect.com -#must be included in copies or derivatives of this script. - -#A script to switch between a wifi network and a non internet routed Hotspot -#Works at startup or with a seperate timer or manually without a reboot -#Other setup required find out more at -#http://www.raspberryconnect.com - -wifidev="wlan0" #device name to use. Default is wlan0. -#use the command: iw dev ,to see wifi interface name - -IFSdef=$IFS -cnt=0 -#These four lines capture the wifi networks the RPi is setup to use -wpassid=$(awk '/ssid="/{ print $0 }' /etc/wpa_supplicant/wpa_supplicant.conf | awk -F'ssid=' '{ print $2 }' ORS=',' | sed 's/\"/''/g' | sed 's/,$//') -wpassid=$(echo "${wpassid//[$'\r\n']}") -IFS="," -ssids=($wpassid) -IFS=$IFSdef #reset back to defaults - - -#Note:If you only want to check for certain SSIDs -#Remove the # in in front of ssids=('mySSID1'.... below and put a # infront of all four lines above -# separated by a space, eg ('mySSID1' 'mySSID2') -#ssids=('mySSID1' 'mySSID2' 'mySSID3') - -#Enter the Routers Mac Addresses for hidden SSIDs, seperated by spaces ie -#( '11:22:33:44:55:66' 'aa:bb:cc:dd:ee:ff' ) -mac=() - -ssidsmac=("${ssids[@]}" "${mac[@]}") #combines ssid and MAC for checking - -createAdHocNetwork() -{ - echo "Creating Hotspot" - ip link set dev "$wifidev" down - ip a add 10.0.0.5/24 brd + dev "$wifidev" - ip link set dev "$wifidev" up - dhcpcd -k "$wifidev" >/dev/null 2>&1 - systemctl start dnsmasq - systemctl start hostapd -} - -KillHotspot() -{ - echo "Shutting Down Hotspot" - ip link set dev "$wifidev" down - systemctl stop hostapd - systemctl stop dnsmasq - ip addr flush dev "$wifidev" - ip link set dev "$wifidev" up - dhcpcd -n "$wifidev" >/dev/null 2>&1 -} - -ChkWifiUp() -{ - echo "Checking WiFi connection ok" - sleep 20 #give time for connection to be completed to router - if ! wpa_cli -i "$wifidev" status | grep 'ip_address' >/dev/null 2>&1 - then #Failed to connect to wifi (check your wifi settings, password etc) - echo 'Wifi failed to connect, falling back to Hotspot.' - wpa_cli terminate "$wifidev" >/dev/null 2>&1 - createAdHocNetwork - fi -} - - -FindSSID() -{ -#Check to see what SSID's and MAC addresses are in range -ssidChk=('NoSSid') -i=0; j=0 -until [ $i -eq 1 ] #wait for wifi if busy, usb wifi is slower. -do - ssidreply=$((iw dev "$wifidev" scan ap-force | egrep "^BSS|SSID:") 2>&1) >/dev/null 2>&1 - echo "SSid's in range: " $ssidreply - echo "Device Available Check try " $j - if (($j >= 10)); then #if busy 10 times goto hotspot - echo "Device busy or unavailable 10 times, going to Hotspot" - ssidreply="" - i=1 - elif echo "$ssidreply" | grep "No such device (-19)" >/dev/null 2>&1; then - echo "No Device Reported, try " $j - NoDevice - elif echo "$ssidreply" | grep "Network is down (-100)" >/dev/null 2>&1 ; then - echo "Network Not available, trying again" $j - j=$((j + 1)) - sleep 2 - elif echo "$ssidreply" | grep "Read-only file system (-30)" >/dev/null 2>&1 ; then - echo "Temporary Read only file system, trying again" - j=$((j + 1)) - sleep 2 - elif echo "$ssidreply" | grep "Invalid exchange (-52)" >/dev/null 2>&1 ; then - echo "Temporary unavailable, trying again" - j=$((j + 1)) - sleep 2 - elif ! echo "$ssidreply" | grep "resource busy (-16)" >/dev/null 2>&1 ; then - echo "Device Available, checking SSid Results" - i=1 - else #see if device not busy in 2 seconds - echo "Device unavailable checking again, try " $j - j=$((j + 1)) - sleep 2 - fi -done - -for ssid in "${ssidsmac[@]}" -do - if (echo "$ssidreply" | grep "$ssid") >/dev/null 2>&1 - then - #Valid SSid found, passing to script - echo "Valid SSID Detected, assesing Wifi status" - ssidChk=$ssid - return 0 - else - #No Network found, NoSSid issued" - echo "No SSid found, assessing WiFi status" - ssidChk='NoSSid' - fi -done -} - -NoDevice() -{ - #if no wifi device,ie usb wifi removed, activate wifi so when it is - #reconnected wifi to a router will be available - echo "No wifi device connected" - wpa_supplicant -B -i "$wifidev" -c /etc/wpa_supplicant/wpa_supplicant.conf >/dev/null 2>&1 - exit 1 -} - -FindSSID - -#Create Hotspot or connect to valid wifi networks -if [ "$ssidChk" != "NoSSid" ] -then - if systemctl status hostapd | grep "(running)" >/dev/null 2>&1 - then #hotspot running and ssid in range - KillHotspot - echo "Hotspot Deactivated, Bringing Wifi Up" - wpa_supplicant -B -i "$wifidev" -c /etc/wpa_supplicant/wpa_supplicant.conf >/dev/null 2>&1 - ChkWifiUp - elif { wpa_cli -i "$wifidev" status | grep 'ip_address'; } >/dev/null 2>&1 - then #Already connected - echo "Wifi already connected to a network" - else #ssid exists and no hotspot running connect to wifi network - echo "Connecting to the WiFi Network" - wpa_supplicant -B -i "$wifidev" -c /etc/wpa_supplicant/wpa_supplicant.conf >/dev/null 2>&1 - ChkWifiUp - fi -else #ssid or MAC address not in range - if systemctl status hostapd | grep "(running)" >/dev/null 2>&1 - then - echo "Hostspot already active" - elif { wpa_cli status | grep "$wifidev"; } >/dev/null 2>&1 - then - echo "Cleaning wifi files and Activating Hotspot" - wpa_cli terminate >/dev/null 2>&1 - ip addr flush "$wifidev" - ip link set dev "$wifidev" down - rm -r /var/run/wpa_supplicant >/dev/null 2>&1 - createAdHocNetwork - else #"No SSID, activating Hotspot" - createAdHocNetwork - fi -fi diff --git a/scripts/helperscripts/organizeFiles.py b/scripts/helperscripts/organizeFiles.py index 596ee4839..06c372633 100644 --- a/scripts/helperscripts/organizeFiles.py +++ b/scripts/helperscripts/organizeFiles.py @@ -52,7 +52,7 @@ def readFolders(audioDir, relpath=None, isFirst=True): elif os.path.isdir(absf): childResult = readFolders(audioDir=absf, relpath=os.path.join(relpath, f), isFirst=False) for k, v in childResult.items(): - assert(k not in result) + assert (k not in result) result[k] = v if hasAudioFiles: result[relpath] = os.path.exists(os.path.join(audioDir, "folder.conf")) diff --git a/scripts/helperscripts/setup_autohotspot.sh b/scripts/helperscripts/setup_autohotspot.sh new file mode 100644 index 000000000..5f9067894 --- /dev/null +++ b/scripts/helperscripts/setup_autohotspot.sh @@ -0,0 +1,181 @@ +#!/usr/bin/env bash + +JUKEBOX_HOME_DIR="$1" +AUTOHOTSPOTconfig="$2" +AUTOHOTSPOTssid="$3" +AUTOHOTSPOTcountryCode="$4" +AUTOHOTSPOTpass="$5" +AUTOHOTSPOTip="$6" +if [[ "$#" -lt 2 || ( "${AUTOHOTSPOTconfig}" != "NO" && "${AUTOHOTSPOTconfig}" != "YES") || ( "${AUTOHOTSPOTconfig}" == "YES" && "$#" -ne 6 ) ]] ; then + echo "error: missing paramter" + echo "usage: ./setup_autohotspot.sh " + echo "or" + echo "usage: ./setup_autohotspot.sh " + exit 1 +fi + +# Reads a textfile and pipes all lines as args to the given command. +# Does filter out comments. +# Arguments: +# 1 : textfile to read +# 2... : command to receive args (e.g. 'echo', 'apt-get -y install', ...) +call_with_args_from_file () { + local package_file="$1" + shift + + sed 's/#.*//g' ${package_file} | xargs "$@" +} + +apt_get="sudo apt-get -qq --yes" + +systemd_dir="/etc/systemd/system" + +autohotspot_service="autohotspot.service" +autohotspot_service_path="${systemd_dir}/${autohotspot_service}" +autohotspot_script="/usr/bin/autohotspot" + +dnsmasq_conf=/etc/dnsmasq.conf +hostapd_conf=/etc/hostapd/hostapd.conf +hostapd_deamon=/etc/default/hostapd +dhcpcd_conf=/etc/dhcpcd.conf +dhcpcd_conf_nohook_wpa_supplicant="nohook wpa_supplicant" + +if [ "${AUTOHOTSPOTconfig}" == "YES" ]; then + + # adapted from https://www.raspberryconnect.com/projects/65-raspberrypi-hotspot-accesspoints/158-raspberry-pi-auto-wifi-hotspot-switch-direct-connection + + # power management of wifi: switch off to avoid disconnecting + sudo iwconfig wlan0 power off + + # required packages + call_with_args_from_file "${JUKEBOX_HOME_DIR}"/packages-autohotspot.txt ${apt_get} install + sudo systemctl unmask hostapd + sudo systemctl disable hostapd + sudo systemctl stop hostapd + sudo systemctl unmask dnsmasq + sudo systemctl disable dnsmasq + sudo systemctl stop dnsmasq + + # configure DNS + # create flag file or copy present conf to orig file + # to correctly handling future deactivation of autohotspot + if [ ! -f "${dnsmasq_conf}" ]; then + sudo touch "${dnsmasq_conf}.remove" + elif [ ! -f "${dnsmasq_conf}.orig" ] && [ ! -f "${dnsmasq_conf}.remove" ]; then + sudo cp "${dnsmasq_conf}" "${dnsmasq_conf}.orig" + fi + + ip_without_last_segment=$(echo $AUTOHOTSPOTip | cut -d'.' -f1-3) + sudo cp "${JUKEBOX_HOME_DIR}"/misc/sampleconfigs/dnsmasq.conf.stretch-default2-Hotspot.sample "${dnsmasq_conf}" + sudo sed -i "s|%IP_WITHOUT_LAST_SEGMENT%|${ip_without_last_segment}|g" "${dnsmasq_conf}" + sudo chown root:root "${dnsmasq_conf}" + sudo chmod 644 "${dnsmasq_conf}" + + # configure hostapd conf + # create flag file or copy present conf to orig file + # to correctly handling future deactivation of autohotspot + if [ ! -f "${hostapd_conf}" ]; then + sudo touch "${hostapd_conf}.remove" + elif [ ! -f "${hostapd_conf}.orig" ] && [ ! -f "${hostapd_conf}.remove" ]; then + sudo cp "${hostapd_conf}" "${hostapd_conf}.orig" + fi + + sudo cp "${JUKEBOX_HOME_DIR}"/misc/sampleconfigs/hostapd.conf.stretch-default2-Hotspot.sample "${hostapd_conf}" + sudo sed -i "s|%AUTOHOTSPOTssid%|${AUTOHOTSPOTssid}|g" "${hostapd_conf}" + sudo sed -i "s|%AUTOHOTSPOTpass%|${AUTOHOTSPOTpass}|g" "${hostapd_conf}" + sudo sed -i "s|%AUTOHOTSPOTcountryCode%|${AUTOHOTSPOTcountryCode}|g" "${hostapd_conf}" + sudo chown root:root "${hostapd_conf}" + sudo chmod 644 "${hostapd_conf}" + + # configure hostapd daemon + # create flag file or copy present conf to orig file + # to correctly handling future deactivation of autohotspot + if [ ! -f "${hostapd_deamon}" ]; then + sudo touch "${hostapd_deamon}.remove" + elif [ ! -f "${hostapd_deamon}.orig" ] && [ ! -f "${hostapd_deamon}.remove" ]; then + sudo cp "${hostapd_deamon}" "${hostapd_deamon}.orig" + fi + + sudo cp "${JUKEBOX_HOME_DIR}"/misc/sampleconfigs/hostapd.stretch-default2-Hotspot.sample "${hostapd_deamon}" + sudo sed -i "s|%HOSTAPD_CONF%|${hostapd_conf}|g" "${hostapd_deamon}" + sudo chown root:root "${hostapd_deamon}" + sudo chmod 644 "${hostapd_deamon}" + + # configure dhcpcd conf + # create flag file or copy present conf to orig file + # to correctly handling future deactivation of autohotspot + if [ ! -f "${dhcpcd_conf}" ]; then + sudo touch "${dhcpcd_conf}.remove" + sudo touch "${dhcpcd_conf}" + sudo chown root:netdev "${dhcpcd_conf}" + sudo chmod 664 "${dhcpcd_conf}" + elif [ ! -f "${dhcpcd_conf}.orig" ] && [ ! -f "${dhcpcd_conf}.remove" ]; then + sudo cp "${dhcpcd_conf}" "${dhcpcd_conf}.orig" + fi + + if [[ ! $(grep -w "${dhcpcd_conf_nohook_wpa_supplicant}" ${dhcpcd_conf}) ]]; then + sudo bash -c "echo ${dhcpcd_conf_nohook_wpa_supplicant} >> ${dhcpcd_conf}" + fi + + # create service to trigger hotspot + sudo cp "${JUKEBOX_HOME_DIR}"/misc/sampleconfigs/autohotspot.sh.stretch-default2-Hotspot.sample "${autohotspot_script}" + sudo sed -i "s|%AUTOHOTSPOT_IP%|${AUTOHOTSPOTip}|g" "${autohotspot_script}" + sudo chmod +x "${autohotspot_script}" + + sudo cp "${JUKEBOX_HOME_DIR}"/misc/sampleconfigs/autohotspot.service.stretch-default2-Hotspot.sample "${autohotspot_service_path}" + sudo sed -i "s|%AUTOHOTSPOT_SCRIPT%|${autohotspot_script}|g" "${autohotspot_service_path}" + sudo chown root:root "${autohotspot_service_path}" + sudo chmod 644 "${autohotspot_service_path}" + + sudo systemctl enable "${autohotspot_service}" + + # create crontab entry + crontab_user=$(crontab -l 2>/dev/null) + if [[ -z "${crontab_user}" || ! $(echo "${crontab_user}" | grep -w "${autohotspot_script}") ]]; then + (echo "${crontab_user}"; echo "*/5 * * * * sudo ${autohotspot_script} >/dev/null 2>&1") | crontab - + fi + +else + # clear autohotspot configurations made from past installation + + # stop services and clear services + if systemctl list-unit-files "${autohotspot_service}" >/dev/null 2>&1 ; then + sudo systemctl stop hostapd + sudo systemctl stop dnsmasq + sudo systemctl stop "${autohotspot_service}" + sudo systemctl disable "${autohotspot_service}" + sudo rm "${autohotspot_service_path}" + fi + + # remove crontab entry and script + crontab_user=$(crontab -l 2>/dev/null) + if [[ ! -z "${crontab_user}" && $(echo "${crontab_user}" | grep -w "${autohotspot_script}") ]]; then + echo "${crontab_user}" | sed "s|^.*\s${autohotspot_script}\s.*$||g" | crontab - + fi + + if [ -f "${autohotspot_script}" ]; then + sudo rm "${autohotspot_script}" + fi + + # remove config files + if [ -f "${dnsmasq_conf}.remove" ]; then + sudo rm "${dnsmasq_conf}.remove" "${dnsmasq_conf}" + elif [ -f "${dnsmasq_conf}.orig" ]; then + sudo mv "${dnsmasq_conf}.orig" "${dnsmasq_conf}" + fi + if [ -f "${hostapd_conf}.remove" ]; then + sudo rm "${hostapd_conf}.remove" "${hostapd_conf}" + elif [ -f "${hostapd_conf}.orig" ]; then + sudo mv "${hostapd_conf}.orig" "${hostapd_conf}" + fi + if [ -f "${hostapd_deamon}.remove" ]; then + sudo rm "${hostapd_deamon}.remove" "${hostapd_deamon}" + elif [ -f "${hostapd_deamon}.orig" ]; then + sudo mv "${hostapd_deamon}.orig" "${hostapd_deamon}" + fi + if [ -f "${dhcpcd_conf}.remove" ]; then + sudo rm "${dhcpcd_conf}.remove" "${dhcpcd_conf}" + elif [ -f "${dhcpcd_conf}.orig" ]; then + sudo mv "${dhcpcd_conf}.orig" "${dhcpcd_conf}" + fi +fi diff --git a/scripts/installscripts/buster-install-default-with-autohotspot.sh b/scripts/installscripts/buster-install-default-with-autohotspot.sh deleted file mode 100644 index 2517681fe..000000000 --- a/scripts/installscripts/buster-install-default-with-autohotspot.sh +++ /dev/null @@ -1,1445 +0,0 @@ -#!/usr/bin/env bash -# -# see https://github.com/MiczFlor/RPi-Jukebox-RFID for details -# -# NOTE: Running automated install (without interaction): -# Each install creates a file called PhonieboxInstall.conf -# in you $HOME directory -# You can install the Phoniebox using such a config file -# which means you don't need to run the interactive install: -# -# 1. download the install file from github -# https://github.com/MiczFlor/RPi-Jukebox-RFID/tree/develop/scripts/installscripts -# (note: currently only works for buster and newer OS) -# 2. make the file executable: chmod +x -# 3. place the PhonieboxInstall.conf in the folder $HOME -# 4. run the installscript with option -a like this: -# buster-install-default.sh -a - -# The absolute path to the folder which contains this script -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -GIT_BRANCH=${GIT_BRANCH:-master} -GIT_URL=${GIT_URL:-https://github.com/MiczFlor/RPi-Jukebox-RFID.git} -echo GIT_BRANCH $GIT_BRANCH -echo GIT_URL $GIT_URL - -DATETIME=$(date +"%Y%m%d_%H%M%S") - -SCRIPTNAME="$(basename $0)" -JOB="${SCRIPTNAME}" - -HOME_DIR=$(echo $HOME) - -JUKEBOX_HOME_DIR="${HOME_DIR}/RPi-Jukebox-RFID" -LOGDIR="${HOME_DIR}"/phoniebox_logs -JUKEBOX_BACKUP_DIR="${HOME_DIR}/BACKUP" - -INTERACTIVE=true - -usage() { - printf "Usage: ${SCRIPTNAME} [-a] [-h]\n" - printf " -a\tautomatic/non-interactive mode\n" - printf " -h\thelp\n" - exit 0 -} - -while getopts ":ah" opt; -do - case ${opt} in - a ) INTERACTIVE=false - ;; - h ) usage - ;; - \? ) usage - ;; - esac -done - - -# Setup logger functions -# Input from http://www.ludovicocaldara.net/dba/bash-tips-5-output-logfile/ -log_open() { - [[ -d "${LOGDIR}" ]] || mkdir -p "${LOGDIR}" - PIPE="${LOGDIR}"/"${JOB}"_"${DATETIME}".pipe - mkfifo -m 700 "${PIPE}" - LOGFILE="${LOGDIR}"/"${JOB}"_"${DATETIME}".log - exec 3>&1 - tee "${LOGFILE}" <"${PIPE}" >&3 & - TEEPID=$! - exec 1>"${PIPE}" 2>&1 - PIPE_OPENED=1 -} - -log_close() { - if [ "${PIPE_OPENED}" ]; then - exec 1<&3 - sleep 0.2 - ps --pid "${TEEPID}" >/dev/null - if [ $? -eq 0 ] ; then - # a wait ${TEEPID} whould be better but some - # commands leave file descriptors open - sleep 1 - kill "${TEEPID}" - fi - rm "${PIPE}" - unset PIPE_OPENED - fi -} - - -welcome() { - clear - echo "##################################################### -# ___ __ ______ _ __________ ____ __ _ _ # -# / _ \/ // / __ \/ |/ / _/ __/( _ \ / \( \/ ) # -# / ___/ _ / /_/ / // // _/ ) _ (( O )) ( # -# /_/ /_//_/\____/_/|_/___/____/ (____/ \__/(_/\_) # -# # -##################################################### - -You are turning your Raspberry Pi into a Phoniebox. Good choice. -This INTERACTIVE INSTALL script requires you to be online and -will guide you through the configuration. - -If you want to run the AUTOMATED INSTALL (non-interactive) from -an existing configuration file, do the following: -1. exit this install script (press n) -2. place your PhonieboxInstall.conf in the folder ${HOME_DIR} -3. run the installscript with option -a. For example like this: - .${HOME_DIR}/buster-install-default.sh -a - " - read -rp "Continue interactive installation? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - exit - ;; - *) - echo "Installation continues..." - ;; - esac -} - -reset_install_config_file() { - ##################################################### - # CONFIG FILE - # This file will contain all the data given in the - # following dialogue - # At a later stage, the install should also be done - # from such a config file with no user input. - - # Remove existing config file - #rm "${HOME_DIR}/PhonieboxInstall.conf" - # Create empty config file - #touch "${HOME_DIR}/PhonieboxInstall.conf" - #echo "# Phoniebox config" > "${HOME_DIR}/PhonieboxInstall.conf" - echo "# Phoniebox config" -} - -config_wifi() { - ##################################################### - # Ask if wifi config - - clear - - echo "##################################################### -# -# CONFIGURE WIFI -# -# Requires SSID, WiFi password and the static IP you want -# to assign to your Phoniebox. -# (Note: can be done manually later, if you are unsure.) -" -read -rp "Do you want to configure your WiFi? [Y/n] " response -echo "" -case "$response" in - [nN][oO]|[nN]) - WIFIconfig=NO - echo "You want to configure WiFi later." - # append variables to config file - echo "WIFIconfig=$WIFIconfig" >> "${HOME_DIR}/PhonieboxInstall.conf" - # make a fallback for WiFi Country Code, because we need that even without WiFi config - echo "WIFIcountryCode=DE" >> "${HOME_DIR}/PhonieboxInstall.conf" - ;; - *) - WIFIconfig=YES - #Ask for SSID - read -rp "* Type SSID name: " WIFIssid - #Ask for wifi country code - read -rp "* WiFi Country Code (e.g. DE, GB, CZ or US): " WIFIcountryCode - #Ask for password - read -rp "* Type password: " WIFIpass - #Ask for IP - read -rp "* Static IP (e.g. 192.168.1.199): " WIFIip - #Ask for Router IP - read -rp "* Router IP (e.g. 192.168.1.1): " WIFIipRouter - echo "" - echo "Your WiFi config:" - echo "SSID : $WIFIssid" - echo "WiFi Country Code : $WIFIcountryCode" - echo "Password : $WIFIpass" - echo "Static IP : $WIFIip" - echo "Router IP : $WIFIipRouter" - read -rp "Are these values correct? [Y/n] " response - echo "" - case "$response" in - [nN][oO]|[nN]) - echo "The values are incorrect." - read -rp "Hit ENTER to exit and start over." INPUT; exit - ;; - *) - # append variables to config file - { - echo "WIFIconfig=\"$WIFIconfig\""; - echo "WIFIcountryCode=\"$WIFIcountryCode\""; - echo "WIFIssid=\"$WIFIssid\""; - echo "WIFIpass=\"$WIFIpass\""; - echo "WIFIip=\"$WIFIip\""; - echo "WIFIipRouter=\"$WIFIipRouter\""; - } >> "${HOME_DIR}/PhonieboxInstall.conf" - ;; - esac - ;; -esac -read -rp "Hit ENTER to proceed to the next step." INPUT -} - -check_existing() { - local jukebox_dir="$1" - local backup_dir="$2" - local home_dir="$3" - - ##################################################### - # Check for existing Phoniebox - # - # In case there is no existing install, - # set the var now for later use: - EXISTINGuse=NO - - # The install will be in the home dir of user pi - # Move to home directory now to check - cd ~ || exit - if [ -d "${jukebox_dir}" ]; then - # Houston, we found something! - clear - echo "##################################################### -# -# . . . * alert * alert * alert * alert * . . . -# -# WARNING: an existing Phoniebox installation was found. -# -" - # check if we find the version number - if [ -f "${jukebox_dir}"/settings/version ]; then - #echo "The version of your installation is: $(cat ${jukebox_dir}/settings/version)" - - # get the current short commit hash of the repo - CURRENT_REMOTE_COMMIT="$(git ls-remote ${GIT_URL} ${GIT_BRANCH} | cut -c1-7)" - fi - echo "IMPORTANT: you can use the existing content and configuration" - echo "files for your new install." - echo "Whatever you chose to keep will be moved to the new install." - echo "Everything else will remain in a folder called 'BACKUP'. - " - - ### - # See if we find the PhonieboxInstall.conf file - # We need to do this first, because if we re-use the .conf file, we need to append - # the variables regarding the found content to the also found configuration file. - # That way, reading the configuration file for the (potentially) non-interactive - # install procedure will: - # a) overwrite whatever variables regarding re-cycling existing content which might - # be stored in the config file - # b) if there are no variables for dealing with re-cycled context, we will append - # them - to have them for this install - if [ -f "${jukebox_dir}"/settings/PhonieboxInstall.conf ]; then - # ask for re-using the found configuration file - echo "The configuration of your last Phoniebox install was found." - read -rp "Use existing configuration for this installation? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGusePhonieboxInstall=NO - ;; - *) - EXISTINGusePhonieboxInstall=YES - # Copy PhonieboxInstall.conf configuration file to settings folder - sudo cp "${jukebox_dir}"/settings/PhonieboxInstall.conf "${home_dir}"/PhonieboxInstall.conf - sudo chown pi:www-data "${home_dir}"/PhonieboxInstall.conf - sudo chmod 775 "${home_dir}"/PhonieboxInstall.conf - echo "The existing configuration will be used." - echo "Just a few more questions to answer." - read -rp "Hit ENTER to proceed to the next step." INPUT - clear - ;; - esac - fi - - # Delete or use existing installation? - read -rp "Re-use config, audio and RFID codes for the new install? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuse=NO - echo "Phoniebox will be a fresh install. The existing version will be dropped." - sudo rm -rf "${jukebox_dir}" - read -rp "Hit ENTER to proceed to the next step." INPUT - ;; - *) - EXISTINGuse=YES - # CREATE BACKUP - # delete existing BACKUP dir if exists - if [ -d "${backup_dir}" ]; then - sudo rm -r "${backup_dir}" - fi - # move install to BACKUP dir - mv "${jukebox_dir}" "${backup_dir}" - # delete .git dir - if [ -d "${backup_dir}"/.git ]; then - sudo rm -r "${backup_dir}"/.git - fi - # delete placeholder files so moving the folder content back later will not create git pull conflicts - rm "${backup_dir}"/shared/audiofolders/placeholder - rm "${backup_dir}"/shared/shortcuts/placeholder - - # ask for things to use - echo "Ok. You want to use stuff from the existing installation." - echo "What would you want to keep? Answer now." - read -rp "RFID config for system control (e.g. 'volume up' etc.)? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseRfidConf=NO - ;; - *) - EXISTINGuseRfidConf=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseRfidConf=$EXISTINGuseRfidConf" >> "${HOME_DIR}/PhonieboxInstall.conf" - - read -rp "RFID shortcuts to play audio folders? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseRfidLinks=NO - ;; - *) - EXISTINGuseRfidLinks=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseRfidLinks=$EXISTINGuseRfidLinks" >> "${HOME_DIR}/PhonieboxInstall.conf" - - read -rp "Audio folders: use existing? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseAudio=NO - ;; - *) - EXISTINGuseAudio=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseAudio=$EXISTINGuseAudio" >> "${HOME_DIR}/PhonieboxInstall.conf" - - read -rp "Sound effects: use existing startup / shutdown sounds? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseSounds=NO - ;; - *) - EXISTINGuseSounds=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseSounds=$EXISTINGuseSounds" >> "${HOME_DIR}/PhonieboxInstall.conf" - - if [ "$(printf '%s\n' "2.1" "$(cat ~/BACKUP/settings/version-number)" | sort -V | head -n1)" = "2.1" ]; then - read -rp "GPIO: use existing file? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseGpio=NO - ;; - *) - EXISTINGuseGpio=YES - ;; - esac - else - echo "" - echo "Warning! -The configuration of GPIO-Devices has changed in the new version -and needs to be reconfigured. For further info check out the wiki: -https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Using-GPIO-hardware-buttons" - read -rp "Hit ENTER to proceed to the next step." INPUT - config_gpio - fi - # append variables to config file - echo "EXISTINGuseGpio=$EXISTINGuseGpio" >> "${HOME_DIR}/PhonieboxInstall.conf" - - read -rp "Button USB Encoder: use existing device and button mapping? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseButtonUSBEncoder=NO - ;; - *) - EXISTINGuseButtonUSBEncoder=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseButtonUSBEncoder=$EXISTINGuseButtonUSBEncoder" >> "${HOME_DIR}/PhonieboxInstall.conf" - - echo "Thanks. Got it." - echo "The existing install can be found in the BACKUP directory." - read -rp "Hit ENTER to proceed to the next step." INPUT - ;; - esac - fi - # append variables to config file - echo "EXISTINGuse=$EXISTINGuse" >> "${HOME_DIR}/PhonieboxInstall.conf" - - # Check if we found a Phoniebox install configuration earlier and ask if to run this now - if [ "${EXISTINGusePhonieboxInstall}" == "YES" ]; then - clear - echo "Using the existing configuration, you can run a non-interactive install." - echo "This will re-cycle found content (specified just now) as well as the" - echo "system information from last time (wifi, audio interface, spotify, etc.)." - read -rp "Do you want to run a non-interactive installation? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - ;; - *) - cd "${home_dir}" - clear - ./buster-install-default.sh -a - exit - ;; - esac - fi -} - -config_audio_interface() { - ##################################################### - # Audio iFace - - clear - - echo "##################################################### -# -# CONFIGURE AUDIO INTERFACE (iFace) -# -# The default RPi audio interface is 'Headphone'. -# But this does not work for every setup. Here a list of -# available iFace names: -" - amixer scontrols - echo " " - read -rp "Use Headphone as iFace? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - read -rp "Type the iFace name you want to use:" AUDIOiFace - ;; - *) - AUDIOiFace="Headphone" - ;; - esac - # append variables to config file - echo "AUDIOiFace=\"$AUDIOiFace\"" >> "${HOME_DIR}/PhonieboxInstall.conf" - echo "Your iFace is called '$AUDIOiFace'" - read -rp "Hit ENTER to proceed to the next step." INPUT -} - -config_spotify() { - ##################################################### - # Configure spotify - - clear - - echo "##################################################### -# -# OPTIONAL: INCLUDE SPOTIFY -# -# Note: if this is your first time installing a phoniebox -# it might be best to do a test install without Spotify -# to make sure all your hardware works. -# -# If you want to include Spotify, MUST have your -# credentials ready: -# -# * username -# * password -# * client_id -# * client_secret - -" - read -rp "Do you want to enable Spotify? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - SPOTinstall=NO - echo "You don't want spotify support." - ;; - *) - SPOTinstall=YES - clear - echo "##################################################### -# -# CREDENTIALS for Spotify -# -# Requires Spotify username, password, client_id and client_secret -# to get connection to Spotify. -# -# (Note: You need a device with browser to generate ID and SECRET) -# -# Please go to this website: -# https://www.mopidy.com/authenticate/ -# and follow the instructions. -# -# Your credential will appear on the site below the login button. -# Please note your client_id and client_secret! -# -" - read -rp "Type your Spotify username: " SPOTIuser - read -rp "Type your Spotify password: " SPOTIpass - read -rp "Type your client_id: " SPOTIclientid - read -rp "Type your client_secret: " SPOTIclientsecret - ;; - esac - # append variables to config file - { - echo "SPOTinstall=\"$SPOTinstall\""; - echo "SPOTIuser=\"$SPOTIuser\""; - echo "SPOTIpass=\"$SPOTIpass\""; - echo "SPOTIclientid=\"$SPOTIclientid\""; - echo "SPOTIclientsecret=\"$SPOTIclientsecret\"" - } >> "${HOME_DIR}/PhonieboxInstall.conf" - read -rp "Hit ENTER to proceed to the next step." INPUT -} - -config_mpd() { - ##################################################### - # Configure MPD - - clear - - echo "##################################################### -# -# CONFIGURE MPD -# -# MPD (Music Player Daemon) runs the audio output and must -# be configured. Do it now, if you are unsure. -# (Note: can be done manually later.) -" - read -rp "Do you want to configure MPD? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - MPDconfig=NO - echo "You want to configure MPD later." - ;; - *) - MPDconfig=YES - echo "MPD will be set up with default values." - ;; - esac - # append variables to config file - echo "MPDconfig=\"$MPDconfig\"" >> "${HOME_DIR}/PhonieboxInstall.conf" - read -rp "Hit ENTER to proceed to the next step." INPUT -} - -config_audio_folder() { - local jukebox_dir="$1" - - ##################################################### - # Folder path for audio files - # default: $HOME/RPi-Jukebox-RFID/shared/audiofolders - - clear - - echo "##################################################### -# -# FOLDER CONTAINING AUDIO FILES -# -# The default location for folders containing audio files: -# ${jukebox_dir}/shared/audiofolders -# -# If unsure, keep it like this. If your files are somewhere -# else, you can specify the folder in the next step. -# IMPORTANT: the folder will not be created, only the path -# will be remembered. If you use a custom folder, you must -# create it. -" - - read -rp "Do you want to use the default location? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - echo "Please type the absolute path here (no trailing slash)." - echo "Default would be for example: ${jukebox_dir}/shared/audiofolders" - read -r DIRaudioFolders - ;; - *) - DIRaudioFolders="${jukebox_dir}/shared/audiofolders" - ;; - esac - # append variables to config file - echo "DIRaudioFolders=\"$DIRaudioFolders\"" >> "${HOME_DIR}/PhonieboxInstall.conf" - echo "Your audio folders live in this dir:" - echo "${DIRaudioFolders}" - read -rp "Hit ENTER to proceed to the next step." INPUT -} - -check_variable() { - local variable=${1} - # check if variable exist and if it's empty - test -z "${!variable+x}" && echo "ERROR: \$${variable} is missing!" && fail=true && return - test "${!variable}" == "" && echo "ERROR: \$${variable} is empty!" && fail=true -} - -config_gpio() { - ##################################################### - # Configure GPIO - - clear - - echo "##################################################### -# -# ACTIVATE GPIO-Control -# -# Activation of the GPIO-Control-Service, which mangages Buttons -# or a Rotary Encoder for Volume and/or Track control. -# To configure the controls please consult the wiki: -# https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Using-GPIO-hardware-buttons -# It's also possible to activate the service later (see wiki). -" - read -rp "Do you want to activate the GPIO-Control-Service? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - GPIOconfig=NO - echo "You don't want to activate GPIO-Controls now." - ;; - *) - GPIOconfig=YES - echo "GPIO-Control-Service will be activated and set to default values." - ;; - esac - # append variables to config file - echo "GPIOconfig=\"$GPIOconfig\"" >> "${HOME_DIR}/PhonieboxInstall.conf" - echo "" - read -rp "Hit ENTER to proceed to the next step." INPUT -} - -check_config_file() { - local install_conf="${HOME_DIR}/PhonieboxInstall.conf" - echo "Checking PhonieboxInstall.conf..." - # check that PhonieboxInstall.conf exists and is not empty - - # check if config file exists - if [[ -f "${install_conf}" ]]; then - # Source config file - source "${install_conf}" - cat "${install_conf}" - echo "" - else - echo "ERROR: ${install_conf} does not exist!" - exit 1 - fi - - fail=false - if [[ -z "${WIFIconfig+x}" ]]; then - echo "ERROR: \$WIFIconfig is missing or not set!" && fail=true - else - if [[ "$WIFIconfig" == "YES" ]]; then - check_variable "WIFIcountryCode" - check_variable "WIFIssid" - check_variable "WIFIpass" - check_variable "WIFIip" - check_variable "WIFIipRouter" - fi - fi - check_variable "EXISTINGuse" - check_variable "AUDIOiFace" - - if [[ -z "${SPOTinstall+x}" ]]; then - echo "ERROR: \$SPOTinstall is missing or not set!" && fail=true - else - if [ "$SPOTinstall" == "YES" ]; then - check_variable "SPOTIuser" - check_variable "SPOTIpass" - check_variable "SPOTIclientid" - check_variable "SPOTIclientsecret" - fi - fi - check_variable "MPDconfig" - check_variable "DIRaudioFolders" - check_variable "GPIOconfig" - - if [ "${fail}" == "true" ]; then - exit 1 - fi - - echo "" -} - -samba_config() { - local smb_conf="/etc/samba/smb.conf" - echo "Configuring Samba..." - # Samba configuration settings - # -rw-r--r-- 1 root root 9416 Apr 30 09:02 /etc/samba/smb.conf - sudo cp "${jukebox_dir}"/misc/sampleconfigs/smb.conf.buster-default.sample ${smb_conf} - sudo chown root:root "${smb_conf}" - sudo chmod 644 "${smb_conf}" - # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash - sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' "${smb_conf}" - # Replace homedir; double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${smb_conf}" - # Samba: create user 'pi' with password 'raspberry' - # ToDo: use current user with a default password - (echo "raspberry"; echo "raspberry") | sudo smbpasswd -s -a pi -} - -web_server_config() { - local lighthttpd_conf="/etc/lighttpd/lighttpd.conf" - local fastcgi_php_conf="/etc/lighttpd/conf-available/15-fastcgi-php.conf" - local php_ini="/etc/php/$(ls -1 /etc/php)/cgi/php.ini" - local sudoers="/etc/sudoers" - - echo "Configuring web server..." - # Web server configuration settings - # -rw-r--r-- 1 root root 1040 Apr 30 09:19 /etc/lighttpd/lighttpd.conf - sudo cp "${jukebox_dir}"/misc/sampleconfigs/lighttpd.conf.buster-default.sample "${lighthttpd_conf}" - sudo chown root:root "${lighthttpd_conf}" - sudo chmod 644 "${lighthttpd_conf}" - # double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${lighthttpd_conf}" - - # Web server PHP7 fastcgi conf - # -rw-r--r-- 1 root root 398 Apr 30 09:35 /etc/lighttpd/conf-available/15-fastcgi-php.conf - sudo cp "${jukebox_dir}"/misc/sampleconfigs/15-fastcgi-php.conf.buster-default.sample ${fastcgi_php_conf} - sudo chown root:root "${fastcgi_php_conf}" - sudo chmod 644 "${fastcgi_php_conf}" - - # settings for php.ini to support upload - # -rw-r--r-- 1 root root 70999 Jun 14 13:50 /etc/php/7.3/cgi/php.ini - sudo cp "${jukebox_dir}"/misc/sampleconfigs/php.ini.buster-default.sample ${php_ini} - sudo chown root:root "${php_ini}" - sudo chmod 644 "${php_ini}" - - # SUDO users (adding web server here) - # -r--r----- 1 root root 703 Nov 17 21:08 /etc/sudoers - sudo cp "${jukebox_dir}"/misc/sampleconfigs/sudoers.buster-default.sample ${sudoers} - sudo chown root:root "${sudoers}" - sudo chmod 440 "${sudoers}" -} - -install_main() { - local jukebox_dir="$1" - local apt_get="sudo apt-get -qq --yes" - local allow_downgrades="--allow-downgrades --allow-remove-essential --allow-change-held-packages" - - clear - - echo "##################################################### -# -# START INSTALLATION -# -# Good news: you completed the input. -# Let the install begin. -# -# Get yourself a cup of something. The install takes -# between 15 minutes to half an hour, depending on -# your Raspberry Pi and Internet connectivity. -# -# You will be prompted later to complete the installation. -" - - if [[ ${INTERACTIVE} == "true" ]]; then - read -rp "Do you want to start the installation? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - echo "Exiting the installation." - echo "Your configuration data was saved in this file:" - echo "${HOME_DIR}/PhonieboxInstall.conf" - echo - exit - ;; - esac - fi - - # Start logging here - log_open - - # Add conffile into logfile for better debugging - echo "################################################" - grep -v -e "SPOTI" -e "WIFIpass" "${HOME_DIR}/PhonieboxInstall.conf" - echo "################################################" - - ##################################################### - # INSTALLATION - - # Read install config as written so far - # (this might look stupid so far, but makes sense once - # the option to install from config file is introduced.) - # shellcheck source=scripts/installscripts/tests/ShellCheck/PhonieboxInstall.conf - . "${HOME_DIR}/PhonieboxInstall.conf" - - # power management of wifi: switch off to avoid disconnecting - sudo iwconfig wlan0 power off - - # create backup of /etc/resolv.conf - sudo cp /etc/resolv.conf /etc/resolv.conf.orig - - # Generate locales - sudo locale-gen "${LANG}" - - # Install required packages - ${apt_get} ${allow_downgrades} install apt-transport-https - wget -q -O - https://apt.mopidy.com/mopidy.gpg | sudo apt-key add - - sudo wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/buster.list - - ${apt_get} update - ${apt_get} upgrade - ${apt_get} install libspotify-dev - - # some packages are only available on raspberry pi's but not on test docker containers running on x86_64 machines - if [[ $(uname -m) =~ ^armv.+$ ]]; then - ${apt_get} ${allow_downgrades} install raspberrypi-kernel-headers - fi - - ${apt_get} ${allow_downgrades} install samba samba-common-bin gcc lighttpd php-common php-cgi php at mpd mpc mpg123 git ffmpeg resolvconf spi-tools netcat alsa-utils lsof procps - - # restore backup of /etc/resolv.conf in case installation of resolvconf cleared it - sudo cp /etc/resolv.conf.orig /etc/resolv.conf - - # prepare python3 - ${apt_get} ${allow_downgrades} install python3 python3-dev python3-pip python3-mutagen python3-gpiozero python3-spidev - - # use python3.7 as default - sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.7 1 - - # Get github code - cd "${HOME_DIR}" || exit - git clone ${GIT_URL} --branch "${GIT_BRANCH}" - - # VERSION of installation - - # Get version number - VERSION_NO=`cat ${jukebox_dir}/settings/version-number` - - # add used git branch and commit hash to version file - USED_BRANCH="$(git --git-dir=${jukebox_dir}/.git rev-parse --abbrev-ref HEAD)" - - # add git commit hash to version file - COMMIT_NO="$(git --git-dir=${jukebox_dir}/.git describe --always)" - - echo "${VERSION_NO} - ${COMMIT_NO} - ${USED_BRANCH}" > ${jukebox_dir}/settings/version - chmod 777 ${jukebox_dir}/settings/version - - # Install required spotify packages - if [ "${SPOTinstall}" == "YES" ]; then - echo "Installing dependencies for Spotify support..." - # keep major verson 3 of mopidy - echo -e "Package: mopidy\nPin: version 3.*\nPin-Priority: 1001" | sudo tee /etc/apt/preferences.d/mopidy - - sudo wget -q -O /usr/local/share/keyrings/mopidy-archive-keyring.gpg https://apt.mopidy.com/mopidy.gpg - sudo wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/buster.list - ${apt_get} update - ${apt_get} upgrade - ${apt_get} ${allow_downgrades} install mopidy mopidy-mpd mopidy-local mopidy-spotify - ${apt_get} ${allow_downgrades} install libspotify12 python3-cffi python3-ply python3-pycparser python3-spotify - - # Install necessary Python packages - sudo python3 -m pip install --upgrade --force-reinstall -q -r "${jukebox_dir}"/requirements-spotify.txt - fi - - # Install more required packages - echo "Installing additional Python packages..." - sudo python3 -m pip install --upgrade --force-reinstall -q -r "${jukebox_dir}"/requirements.txt - - samba_config - - web_server_config - - # copy shell script for player - cp "${jukebox_dir}"/settings/rfid_trigger_play.conf.sample "${jukebox_dir}"/settings/rfid_trigger_play.conf - - # creating files containing editable values for configuration - echo "$AUDIOiFace" > "${jukebox_dir}"/settings/Audio_iFace_Name - echo "$DIRaudioFolders" > "${jukebox_dir}"/settings/Audio_Folders_Path - echo "3" > "${jukebox_dir}"/settings/Audio_Volume_Change_Step - echo "100" > "${jukebox_dir}"/settings/Max_Volume_Limit - echo "0" > "${jukebox_dir}"/settings/Idle_Time_Before_Shutdown - echo "RESTART" > "${jukebox_dir}"/settings/Second_Swipe - echo "${jukebox_dir}/playlists" > "${jukebox_dir}"/settings/Playlists_Folders_Path - echo "ON" > "${jukebox_dir}"/settings/ShowCover - - # sample file for debugging with all options set to FALSE - sudo cp "${jukebox_dir}"/settings/debugLogging.conf.sample "${jukebox_dir}"/settings/debugLogging.conf - sudo chmod 777 "${jukebox_dir}"/settings/debugLogging.conf - - # The new way of making the bash daemon is using the helperscripts - # creating the shortcuts and script from a CSV file. - # see scripts/helperscripts/AssignIDs4Shortcuts.php - - # create config file for web app from sample - sudo cp "${jukebox_dir}"/htdocs/config.php.sample "${jukebox_dir}"/htdocs/config.php - # double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${jukebox_dir}"/htdocs/config.php - - # Starting web server and php7 - sudo lighttpd-enable-mod fastcgi - sudo lighttpd-enable-mod fastcgi-php - sudo service lighttpd force-reload - - # make sure bash scripts have the right settings - sudo chown pi:www-data "${jukebox_dir}"/scripts/*.sh - sudo chmod +x "${jukebox_dir}"/scripts/*.sh - sudo chown pi:www-data "${jukebox_dir}"/scripts/*.py - sudo chmod +x "${jukebox_dir}"/scripts/*.py - - # services to launch after boot using systemd - # -rw-r--r-- 1 root root 304 Apr 30 10:07 phoniebox-rfid-reader.service - # 1. delete old services (this is legacy, might throw errors but is necessary. Valid for versions < 1.1.8-beta) - local systemd_dir="/etc/systemd/system" - echo "### Deleting older versions of service daemons. This might throw errors, ignore them" - sudo systemctl disable idle-watchdog - sudo systemctl disable rfid-reader - sudo systemctl disable phoniebox-startup-sound - sudo systemctl disable gpio-buttons - sudo systemctl disable phoniebox-rotary-encoder - sudo systemctl disable phoniebox-gpio-buttons.service - sudo rm "${systemd_dir}"/rfid-reader.service - sudo rm "${systemd_dir}"/startup-sound.service - sudo rm "${systemd_dir}"/gpio-buttons.service - sudo rm "${systemd_dir}"/idle-watchdog.service - sudo rm "${systemd_dir}"/phoniebox-rotary-encoder.service - sudo rm "${systemd_dir}"/phoniebox-gpio-buttons.service - echo "### Done with erasing old daemons. Stop ignoring errors!" - # 2. install new ones - this is version > 1.1.8-beta - RFID_READER_SERVICE="${systemd_dir}/phoniebox-rfid-reader.service" - sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-rfid-reader.service.stretch-default.sample "${RFID_READER_SERVICE}" - # Replace homedir; double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${RFID_READER_SERVICE}" - - #startup sound now part of phoniebox-startup-scripts - #sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-startup-sound.service.stretch-default.sample "${systemd_dir}"/phoniebox-startup-sound.service - STARTUP_SCRIPT_SERVICE="${systemd_dir}/phoniebox-startup-scripts.service" - sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-startup-scripts.service.stretch-default.sample "${STARTUP_SCRIPT_SERVICE}" - # Replace homedir; double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${STARTUP_SCRIPT_SERVICE}" - - IDLE_WATCHDOG_SERVICE="${systemd_dir}/phoniebox-idle-watchdog.service" - sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-idle-watchdog.service.sample "${IDLE_WATCHDOG_SERVICE}" - # Replace homedir; double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${IDLE_WATCHDOG_SERVICE}" - - if [[ "${GPIOconfig}" == "YES" ]]; then - GPIO_CONTROL_SERVICE="${systemd_dir}/phoniebox-gpio-control.service" - sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-gpio-control.service.sample "${GPIO_CONTROL_SERVICE}" - # Replace homedir; double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${GPIO_CONTROL_SERVICE}" - fi - - sudo chown root:root "${systemd_dir}"/phoniebox-*.service - sudo chmod 644 "${systemd_dir}"/phoniebox-*.service - # enable the services needed - sudo systemctl enable phoniebox-idle-watchdog - sudo systemctl enable phoniebox-rfid-reader - #startup sound is part of phoniebox-startup-scripts now - #sudo systemctl enable phoniebox-startup-sound - sudo systemctl enable phoniebox-startup-scripts - # copy mp3s for startup and shutdown sound to the right folder - cp "${jukebox_dir}"/misc/sampleconfigs/startupsound.mp3.sample "${jukebox_dir}"/shared/startupsound.mp3 - cp "${jukebox_dir}"/misc/sampleconfigs/shutdownsound.mp3.sample "${jukebox_dir}"/shared/shutdownsound.mp3 - - # Spotify config - if [ "${SPOTinstall}" == "YES" ]; then - local etc_mopidy_conf="/etc/mopidy/mopidy.conf" - local mopidy_conf="${HOME_DIR}/.config/mopidy/mopidy.conf" - echo "Configuring Spotify support..." - sudo systemctl disable mpd - sudo systemctl enable mopidy - # Install Config Files - sudo cp "${jukebox_dir}"/misc/sampleconfigs/locale.gen.sample /etc/locale.gen - sudo cp "${jukebox_dir}"/misc/sampleconfigs/locale.sample /etc/default/locale - sudo locale-gen - mkdir -p "${HOME_DIR}"/.config/mopidy - sudo cp "${jukebox_dir}"/misc/sampleconfigs/mopidy-etc.sample "${etc_mopidy_conf}" - cp "${jukebox_dir}"/misc/sampleconfigs/mopidy.sample "${mopidy_conf}" - # Change vars to match install config - sudo sed -i 's/%spotify_username%/'"$SPOTIuser"'/' "${etc_mopidy_conf}" - sudo sed -i 's/%spotify_password%/'"$SPOTIpass"'/' "${etc_mopidy_conf}" - sudo sed -i 's/%spotify_client_id%/'"$SPOTIclientid"'/' "${etc_mopidy_conf}" - sudo sed -i 's/%spotify_client_secret%/'"$SPOTIclientsecret"'/' "${etc_mopidy_conf}" - # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash - sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' "${etc_mopidy_conf}" - # Replace homedir; double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${etc_mopidy_conf}" - - sed -i 's/%spotify_username%/'"$SPOTIuser"'/' "${mopidy_conf}" - sed -i 's/%spotify_password%/'"$SPOTIpass"'/' "${mopidy_conf}" - sed -i 's/%spotify_client_id%/'"$SPOTIclientid"'/' "${mopidy_conf}" - sed -i 's/%spotify_client_secret%/'"$SPOTIclientsecret"'/' "${mopidy_conf}" - # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash - sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' "${mopidy_conf}" - # Replace homedir; double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${mopidy_conf}" - fi - - # GPIO-Control - if [[ "${GPIOconfig}" == "YES" ]]; then - sudo python3 -m pip install --upgrade --force-reinstall -q -r "${jukebox_dir}"/requirements-GPIO.txt - sudo systemctl enable phoniebox-gpio-control.service - if [[ ! -f "${jukebox_dir}"/settings/gpio_settings.ini ]]; then - cp "${jukebox_dir}"/misc/sampleconfigs/gpio_settings.ini.sample "${jukebox_dir}"/settings/gpio_settings.ini - fi - fi - - if [ "${MPDconfig}" == "YES" ]; then - local mpd_conf="/etc/mpd.conf" - - echo "Configuring MPD..." - # MPD configuration - # -rw-r----- 1 mpd audio 14043 Jul 17 20:16 /etc/mpd.conf - sudo cp "${jukebox_dir}"/misc/sampleconfigs/mpd.conf.buster-default.sample ${mpd_conf} - # Change vars to match install config - sudo sed -i 's/%AUDIOiFace%/'"$AUDIOiFace"'/' "${mpd_conf}" - # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash - sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' "${mpd_conf}" - # Replace homedir; double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${mpd_conf}" - sudo chown mpd:audio "${mpd_conf}" - sudo chmod 640 "${mpd_conf}" - fi - - # set which version has been installed - if [ "${SPOTinstall}" == "YES" ]; then - echo "plusSpotify" > "${jukebox_dir}"/settings/edition - else - echo "classic" > "${jukebox_dir}"/settings/edition - fi - - # update mpc / mpd DB - mpc update - - # / INSTALLATION - ##################################################### -} - -wifi_settings() { - local sample_configs_dir="$1" - local dhcpcd_conf="$2" - local wpa_supplicant_conf="$3" - - ############################### - # WiFi settings (SSID password) - # - # https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md - # - # $WIFIssid - # $WIFIpass - # $WIFIip - # $WIFIipRouter - if [ "${WIFIconfig}" == "YES" ]; then - # DHCP configuration settings - echo "Setting ${dhcpcd_conf}..." - #-rw-rw-r-- 1 root netdev 0 Apr 17 11:25 /etc/dhcpcd.conf - sudo cp "${sample_configs_dir}"/dhcpcd.conf.buster-default-noHotspot.sample "${dhcpcd_conf}" - # Change IP for router and Phoniebox - sudo sed -i 's/%WIFIip%/'"$WIFIip"'/' "${dhcpcd_conf}" - sudo sed -i 's/%WIFIipRouter%/'"$WIFIipRouter"'/' "${dhcpcd_conf}" - sudo sed -i 's/%WIFIcountryCode%/'"$WIFIcountryCode"'/' "${dhcpcd_conf}" - # Change user:group and access mod - sudo chown root:netdev "${dhcpcd_conf}" - sudo chmod 664 "${dhcpcd_conf}" - - # WiFi SSID & Password - echo "Setting ${wpa_supplicant_conf}..." - # -rw-rw-r-- 1 root netdev 137 Jul 16 08:53 /etc/wpa_supplicant/wpa_supplicant.conf - sudo cp "${sample_configs_dir}"/wpa_supplicant.conf.buster-default.sample "${wpa_supplicant_conf}" - sudo sed -i 's/%WIFIssid%/'"$WIFIssid"'/' "${wpa_supplicant_conf}" - sudo sed -i 's/%WIFIpass%/'"$WIFIpass"'/' "${wpa_supplicant_conf}" - sudo sed -i 's/%WIFIcountryCode%/'"$WIFIcountryCode"'/' "${wpa_supplicant_conf}" - sudo chown root:netdev "${wpa_supplicant_conf}" - sudo chmod 664 "${wpa_supplicant_conf}" - fi - - # start DHCP - echo "Starting dhcpcd service..." - sudo service dhcpcd start - sudo systemctl enable dhcpcd - -# / WiFi settings (SSID password) -############################### -} - -existing_assets() { - local jukebox_dir="$1" - local backup_dir="$2" - - ##################################################### - # EXISTING ASSETS TO USE FROM EXISTING INSTALL - - if [ "${EXISTINGuse}" == "YES" ]; then - # RFID config for system control - if [ "${EXISTINGuseRfidConf}" == "YES" ]; then - # read old values and write them into new file (copied above already) - # do not overwrite but use 'sed' in case there are new vars in new version installed - - # Read the existing RFID config file line by line and use - # only lines which are separated (IFS) by '='. - while IFS='=' read -r key val ; do - # $var should be stripped of possible leading or trailing " - val=${val%\"} - val=${val#\"} - key=${key} - # Additional error check: key should not start with a hash and not be empty. - if [ ! "${key:0:1}" == '#' ] && [ -n "$key" ]; then - # Replace the matching value in the newly created conf file - sed -i 's/%'"$key"'%/'"$val"'/' "${jukebox_dir}"/settings/rfid_trigger_play.conf - fi - done <"${backup_dir}"/settings/rfid_trigger_play.conf - fi - - # RFID shortcuts for audio folders - if [ "${EXISTINGuseRfidLinks}" == "YES" ]; then - # copy from backup to new install - cp -R "${backup_dir}"/shared/shortcuts/* "${jukebox_dir}"/shared/shortcuts/ - fi - - # Audio folders: use existing - if [ "${EXISTINGuseAudio}" == "YES" ]; then - # copy from backup to new install - cp -R "${backup_dir}"/shared/audiofolders/* "$DIRaudioFolders/" - fi - - # GPIO: use existing file - if [ "${EXISTINGuseGpio}" == "YES" ]; then - # copy from backup to new install - cp "${backup_dir}"/settings/gpio_settings.ini "${jukebox_dir}"/settings/gpio_settings.ini - fi - - # Button USB Encoder: use existing file - if [ "${EXISTINGuseButtonUSBEncoder}" == "YES" ]; then - # copy from backup to new install - cp "${backup_dir}"/components/controls/buttons_usb_encoder/deviceName.txt "${jukebox_dir}"/components/controls/buttons_usb_encoder/deviceName.txt - cp "${backup_dir}"/components/controls/buttons_usb_encoder/buttonMap.json "${jukebox_dir}"/components/controls/buttons_usb_encoder/buttonMap.json - # make buttons_usb_encoder.py ready to be use from phoniebox-buttons-usb-encoder service - sudo chmod +x "${jukebox_dir}"/components/controls/buttons_usb_encoder/buttons_usb_encoder.py - # make sure service is still enabled by registering again - USB_BUTTONS_SERVICE="/etc/systemd/system/phoniebox-buttons-usb-encoder.service" - sudo cp -v "${jukebox_dir}"/components/controls/buttons_usb_encoder/phoniebox-buttons-usb-encoder.service.sample "${USB_BUTTONS_SERVICE}" - # Replace homedir; double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${USB_BUTTONS_SERVICE}" - sudo systemctl start phoniebox-buttons-usb-encoder.service - sudo systemctl enable phoniebox-buttons-usb-encoder.service - fi - - # Sound effects: use existing startup / shutdown sounds - if [ "${EXISTINGuseSounds}" == "YES" ]; then - # copy from backup to new install - cp "${backup_dir}"/shared/startupsound.mp3 "${jukebox_dir}"/shared/startupsound.mp3 - cp "${backup_dir}"/shared/shutdownsound.mp3 "${jukebox_dir}"/shared/shutdownsound.mp3 - fi - - fi - - # / EXISTING ASSETS TO USE FROM EXISTING INSTALL - ################################################ -} - - -folder_access() { - local jukebox_dir="$1" - local user_group="$2" - local mod="$3" - - ##################################################### - # Folders and Access Settings - - echo "Setting owner and permissions for directories..." - - # create playlists folder - mkdir -p "${jukebox_dir}"/playlists - sudo chown -R "${user_group}" "${jukebox_dir}"/playlists - sudo chmod -R "${mod}" "${jukebox_dir}"/playlists - - # make sure the shared folder is accessible by the web server - sudo chown -R "${user_group}" "${jukebox_dir}"/shared - sudo chmod -R "${mod}" "${jukebox_dir}"/shared - - # make sure the htdocs folder can be changed by the web server - sudo chown -R "${user_group}" "${jukebox_dir}"/htdocs - sudo chmod -R "${mod}" "${jukebox_dir}"/htdocs - - sudo chown -R "${user_group}" "${jukebox_dir}"/settings - sudo chmod -R "${mod}" "${jukebox_dir}"/settings - - # logs dir accessible by pi and www-data - sudo chown "${user_group}" "${jukebox_dir}"/logs - sudo chmod "${mod}" "${jukebox_dir}"/logs - - # audio folders might be somewhere else, so treat them separately - sudo chown "${user_group}" "${DIRaudioFolders}" - sudo chmod "${mod}" "${DIRaudioFolders}" - - # make sure bash scripts have the right settings - sudo chown "${user_group}" "${jukebox_dir}"/scripts/*.sh - sudo chmod +x "${jukebox_dir}"/scripts/*.sh - sudo chown "${user_group}" "${jukebox_dir}"/scripts/*.py - sudo chmod +x "${jukebox_dir}"/scripts/*.py - - # set audio volume to 100% - # see: https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/54 - sudo amixer cset numid=1 100% - - # delete the global.conf file, in case somebody manually copied stuff back and forth - # this will be created the first time the Phoniebox is put to use by web app or RFID - GLOBAL_CONF="${jukebox_dir}"/settings/global.conf - if [ -f "${GLOBAL_CONF}" ]; then - echo "global.conf needs to be deleted." - rm "${GLOBAL_CONF}" - fi - - # / Access settings - ##################################################### -} - -autohotspot() { - local jukebox_dir="$1" - local apt_get="sudo apt-get -qq --yes" - - # adapted from https://www.raspberryconnect.com/projects/65-raspberrypi-hotspot-accesspoints/158-raspberry-pi-auto-wifi-hotspot-switch-direct-connection - - # required packages - ${apt_get} install dnsmasq hostapd - sudo systemctl unmask hostapd - sudo systemctl disable hostapd - sudo systemctl disable dnsmasq - - # configure DNS - if [ -f /etc/dnsmasq.conf ]; then - sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig - sudo touch /etc/dnsmasq.conf - else - sudo touch /etc/dnsmasq.conf - fi - sudo bash -c 'cat << EOF > /etc/dnsmasq.conf -#AutoHotspot Config -#stop DNSmasq from using resolv.conf -no-resolv -#Interface to use -interface=wlan0 -bind-interfaces -dhcp-range=10.0.0.50,10.0.0.150,12h -EOF' - - # configure hotspot - if [ -f /etc/hostapd/hostapd.conf ]; then - sudo mv /etc/hostapd/hostapd.conf /etc/hostapd/hostapd.conf.orig - sudo touch /etc/hostapd/hostapd.conf - else - sudo touch /etc/hostapd/hostapd.conf - fi - sudo bash -c 'cat << EOF > /etc/hostapd/hostapd.conf -#2.4GHz setup wifi 80211 b,g,n -interface=wlan0 -driver=nl80211 -ssid=phoniebox -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 DE to your WiFi country code -country_code=DE -ieee80211n=1 -ieee80211d=1 -EOF' - - # configure Hotspot daemon - if [ -f /etc/default/hostapd ]; then - sudo mv /etc/default/hostapd /etc/default/hostapd.orig - sudo touch /etc/default/hostapd - else - sudo touch /etc/default/hostapd - fi - sudo bash -c 'cat << EOF > /etc/default/hostapd -DAEMON_CONF="/etc/hostapd/hostapd.conf" -EOF' - - if [ $(grep -v '^$' /etc/network/interfaces |wc -l) -gt 5 ]; then - sudo cp /etc/network/interfaces /etc/network/interfaces-backup - fi - - # disable powermanagement of wlan0 device - sudo iw wlan0 set power_save off - - if [[ ! $(grep "nohook wpa_supplicant" /etc/dhcpcd.conf) ]]; then - sudo echo -e "nohook wpa_supplicant" >> /etc/dhcpcd.conf - fi - - # create service to trigger hotspot - sudo bash -c 'cat << EOF > /etc/systemd/system/autohotspot.service -[Unit] -Description=Automatically generates an internet Hotspot when a valid ssid is not in range -After=multi-user.target -[Service] -Type=oneshot -RemainAfterExit=yes -ExecStart=/usr/bin/autohotspot -[Install] -WantedBy=multi-user.target -EOF' - - sudo systemctl enable autohotspot.service - - sudo cp "${jukebox_dir}"/scripts/helperscripts/autohotspot /usr/bin/autohotspot - sudo chmod +x /usr/bin/autohotspot - - # create crontab entry - if [[ ! $(grep "autohotspot" /var/spool/cron/crontabs/pi) ]]; then - sudo bash -c 'cat << EOF >> /var/spool/cron/crontabs/pi -*/5 * * * * sudo /usr/bin/autohotspot >/dev/null 2>&1 -EOF' - fi - sudo chown pi:crontab /var/spool/cron/crontabs/pi - sudo chmod 600 /var/spool/cron/crontabs/pi - sudo /usr/bin/crontab /var/spool/cron/crontabs/pi - -} - -finish_installation() { - local jukebox_dir="$1" - echo " -# -# INSTALLATION FINISHED -# -##################################################### -" - - ##################################################### - # Register external device(s) - - echo "If you are using an RFID reader, connect it to your RPi." - echo "(In case your RFID reader required soldering, consult the manual.)" - # Use -e to display response of user in the logfile - read -e -r -p "Have you connected your RFID reader? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - ;; - *) - echo 'Please select the RFID reader you want to use' - options=("USB-Reader (e.g. Neuftech)" "RC522" "PN532" "Manual configuration" "Multiple RFID reader") - select opt in "${options[@]}"; do - case $opt in - "USB-Reader (e.g. Neuftech)") - cd "${jukebox_dir}"/scripts/ || exit - python3 RegisterDevice.py - sudo chown pi:www-data "${jukebox_dir}"/scripts/deviceName.txt - sudo chmod 644 "${jukebox_dir}"/scripts/deviceName.txt - break - ;; - "RC522") - bash "${jukebox_dir}"/components/rfid-reader/RC522/setup_rc522.sh - break - ;; - "PN532") - bash "${jukebox_dir}"/components/rfid-reader/PN532/setup_pn532.sh - break - ;; - "Manual configuration") - echo "Please configure your reader manually." - break - ;; - "Multiple RFID reader") - cd "${jukebox_dir}"/scripts/ || exit - sudo python3 RegisterDevice.py.Multi - break - ;; - *) - echo "This is not a number" - ;; - esac - done - esac - - echo - echo "DONE. Let the sounds begin." - echo "Find more information and documentation on the github account:" - echo "https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/" - - echo "Reboot is needed to activate all settings" - # Use -e to display response of user in the logfile - read -e -r -p "Would you like to reboot now? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - # Close logging - log_close - ;; - *) - # Close logging - log_close - sudo shutdown -r now - ;; - esac -} - -######## -# Main # -######## -main() { - if [[ ${INTERACTIVE} == "true" ]]; then - welcome - #reset_install_config_file - config_wifi - check_existing "${JUKEBOX_HOME_DIR}" "${JUKEBOX_BACKUP_DIR}" "${HOME_DIR}" - config_audio_interface - config_spotify - config_mpd - config_audio_folder "${JUKEBOX_HOME_DIR}" - config_gpio - else - echo "Non-interactive installation!" - check_config_file - # Skip interactive Samba WINS config dialog - echo "samba-common samba-common/dhcp boolean false" | sudo debconf-set-selections - fi - install_main "${JUKEBOX_HOME_DIR}" - wifi_settings "${JUKEBOX_HOME_DIR}/misc/sampleconfigs" "/etc/dhcpcd.conf" "/etc/wpa_supplicant/wpa_supplicant.conf" - existing_assets "${JUKEBOX_HOME_DIR}" "${JUKEBOX_BACKUP_DIR}" - folder_access "${JUKEBOX_HOME_DIR}" "pi:www-data" 775 - autohotspot "${JUKEBOX_HOME_DIR}" - - # Copy PhonieboxInstall.conf configuration file to settings folder - sudo cp "${HOME_DIR}/PhonieboxInstall.conf" "${JUKEBOX_HOME_DIR}/settings/" - sudo chown pi:www-data "${JUKEBOX_HOME_DIR}/settings/PhonieboxInstall.conf" - sudo chmod 775 "${JUKEBOX_HOME_DIR}/settings/PhonieboxInstall.conf" - - if [[ ${INTERACTIVE} == "true" ]]; then - finish_installation "${JUKEBOX_HOME_DIR}" - else - echo "Skipping USB device setup..." - echo "For manual registration of a USB card reader type:" - echo "python3 ${HOME_DIR}/RPi-Jukebox-RFID/scripts/RegisterDevice.py" - echo " " - echo "Reboot is required to activate all settings!" - fi -} - -start=$(date +%s) - -main - -end=$(date +%s) -runtime=$((end-start)) -((h=${runtime}/3600)) -((m=(${runtime}%3600)/60)) -((s=${runtime}%60)) -echo "Done (in ${h}h ${m}m ${s}s)." - -##################################################### -# notes for things to do - -# CLEANUP -## remove dir BACKUP (possibly not, because we do this at the beginning after user confirms for latest config) -##################################################### diff --git a/scripts/installscripts/buster-install-default.sh b/scripts/installscripts/install-jukebox.sh similarity index 84% rename from scripts/installscripts/buster-install-default.sh rename to scripts/installscripts/install-jukebox.sh index f010c8b17..54da685e3 100644 --- a/scripts/installscripts/buster-install-default.sh +++ b/scripts/installscripts/install-jukebox.sh @@ -9,12 +9,11 @@ # which means you don't need to run the interactive install: # # 1. download the install file from github -# https://github.com/MiczFlor/RPi-Jukebox-RFID/tree/develop/scripts/installscripts -# (note: currently only works for buster and newer OS) +# https://github.com/MiczFlor/RPi-Jukebox-RFID/tree/master/scripts/installscripts # 2. make the file executable: chmod +x # 3. place the PhonieboxInstall.conf in the folder $HOME # 4. run the installscript with option -a like this: -# buster-install-default.sh -a +# install-jukebox.sh -a # The absolute path to the folder which contains this script PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" @@ -28,12 +27,19 @@ DATETIME=$(date +"%Y%m%d_%H%M%S") SCRIPTNAME="$(basename $0)" JOB="${SCRIPTNAME}" -HOME_DIR=$(echo $HOME) +CURRENT_USER="${SUDO_USER:-$(whoami)}" +HOME_DIR=$(getent passwd "$CURRENT_USER" | cut -d: -f6) +echo "Current User: $CURRENT_USER" +echo "User home dir: $HOME_DIR" JUKEBOX_HOME_DIR="${HOME_DIR}/RPi-Jukebox-RFID" LOGDIR="${HOME_DIR}"/phoniebox_logs JUKEBOX_BACKUP_DIR="${HOME_DIR}/BACKUP" +# Get the Raspberry Pi OS codename (e.g. buster, bullseye, ...) +OS_CODENAME="$( . /etc/os-release; printf '%s\n' "$VERSION_CODENAME"; )" +printf "Used Raspberry Pi OS: ${OS_CODENAME}\n" + INTERACTIVE=true usage() { @@ -86,6 +92,32 @@ log_close() { fi } +checkPrerequisite() { + #currently the user 'pi' is mandatory + #https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/1785 + if [ "${CURRENT_USER}" != "pi" ]; then + echo + echo "ERROR: User must be 'pi'!" + echo " Other usernames are currently not supported." + echo " Please check the wiki for further information" + exit 2 + fi + + if [ "${HOME_DIR}" != "/home/pi" ]; then + echo + echo "ERROR: HomeDir must be '/home/pi'!" + echo " Other usernames are currently not supported." + echo " Please check the wiki for further information" + exit 2 + fi + + if [ ! -d "${HOME_DIR}" ]; then + echo + echo "Warning: HomeDir ${HOME_DIR} does not exist." + echo " Please create it and start again." + exit 2 + fi +} welcome() { clear @@ -106,7 +138,7 @@ an existing configuration file, do the following: 1. exit this install script (press n) 2. place your PhonieboxInstall.conf in the folder ${HOME_DIR} 3. run the installscript with option -a. For example like this: - .${HOME_DIR}/buster-install-default.sh -a + ${HOME_DIR}/install-jukebox.sh -a " read -rp "Continue interactive installation? [Y/n] " response case "$response" in @@ -203,10 +235,94 @@ esac read -rp "Hit ENTER to proceed to the next step." INPUT } +config_autohotspot() { + ##################################################### + # Ask if an autohotspot should be created if no known network is found. + + clear + + echo "##################################################### +# +# CONFIGURE AUTOHOTSPOT +# +# Automatically sets up a wifi hotspot if no known network is found. +# This enables you to directly connect to your phoniebox +# and change configuration (e.g. while you travel). +# (Note: can be done manually later, if you are unsure.) +" +read -rp "Do you want to configure autohotspot? [y/N] " response +echo "" +case "$response" in + [yY][eE][sS]|[yY]) + AUTOHOTSPOTconfig=YES + AUTOHOTSPOTssid="phoniebox" + AUTOHOTSPOTcountryCode="DE" + AUTOHOTSPOTpass="PlayItLoud" + AUTOHOTSPOTip="10.0.0.5" + echo "" + echo "The autohotspot configuration uses this default values:" + echo "SSID : $AUTOHOTSPOTssid" + echo "WiFi Country Code : $AUTOHOTSPOTcountryCode" + echo "Password : $AUTOHOTSPOTpass" + echo "Static IP : $AUTOHOTSPOTip" + read -rp "Do you want to use this default values? [Y/n] " response + echo "" + case "$response" in + [nN][oO]|[nN]) + #Ask for SSID + read -rp "* Type SSID name: " AUTOHOTSPOTssid + #Ask for wifi country code + read -rp "* Type WiFi Country Code (e.g. DE, GB, CZ or US): " AUTOHOTSPOTcountryCode + #Ask for password + read -rp "* Type password (8 characters at least. max 63 characters): " AUTOHOTSPOTpass + #Ask for IP + read -rp "* Type Static IP (e.g. 10.0.0.5, 192.168.1.199): " AUTOHOTSPOTip + echo "" + echo "Your Autohotspot config:" + echo "SSID : $AUTOHOTSPOTssid" + echo "WiFi Country Code : $AUTOHOTSPOTcountryCode" + echo "Password : $AUTOHOTSPOTpass" + echo "Static IP : $AUTOHOTSPOTip" + read -rp "Are these values correct? [Y/n] " response + echo "" + case "$response" in + [nN][oO]|[nN]) + echo "The values are incorrect." + read -rp "Hit ENTER to exit and start over." INPUT; exit + ;; + *) + # step out and continue + ;; + esac + ;; + *) + # step out and continue + ;; + esac + # append variables to config file + { + echo "AUTOHOTSPOTconfig=\"$AUTOHOTSPOTconfig\""; + echo "AUTOHOTSPOTssid=\"$AUTOHOTSPOTssid\""; + echo "AUTOHOTSPOTcountryCode=\"$AUTOHOTSPOTcountryCode\""; + echo "AUTOHOTSPOTpass=\"$AUTOHOTSPOTpass\""; + echo "AUTOHOTSPOTip=\"$AUTOHOTSPOTip\""; + } >> "${HOME_DIR}/PhonieboxInstall.conf" + ;; + *) + AUTOHOTSPOTconfig=NO + echo "You don't want to configure Autohotspot." + # append variables to config file + echo "AUTOHOTSPOTconfig=$AUTOHOTSPOTconfig" >> "${HOME_DIR}/PhonieboxInstall.conf" + ;; + +esac +read -rp "Hit ENTER to proceed to the next step." INPUT +} + check_existing() { local jukebox_dir="$1" local backup_dir="$2" - local home_dir="$3" + local local_home_dir="$3" ##################################################### # Check for existing Phoniebox @@ -217,7 +333,7 @@ check_existing() { # The install will be in the home dir of user pi # Move to home directory now to check - cd ~ || exit + cd "${local_home_dir}" if [ -d "${jukebox_dir}" ]; then # Houston, we found something! clear @@ -262,9 +378,9 @@ check_existing() { *) EXISTINGusePhonieboxInstall=YES # Copy PhonieboxInstall.conf configuration file to settings folder - sudo cp "${jukebox_dir}"/settings/PhonieboxInstall.conf "${home_dir}"/PhonieboxInstall.conf - sudo chown pi:www-data "${home_dir}"/PhonieboxInstall.conf - sudo chmod 775 "${home_dir}"/PhonieboxInstall.conf + sudo cp "${jukebox_dir}"/settings/PhonieboxInstall.conf "${local_home_dir}"/PhonieboxInstall.conf + sudo chown pi:www-data "${local_home_dir}"/PhonieboxInstall.conf + sudo chmod 775 "${local_home_dir}"/PhonieboxInstall.conf echo "The existing configuration will be used." echo "Just a few more questions to answer." read -rp "Hit ENTER to proceed to the next step." INPUT @@ -312,7 +428,7 @@ check_existing() { ;; esac # append variables to config file - echo "EXISTINGuseRfidConf=$EXISTINGuseRfidConf" >> "${HOME_DIR}/PhonieboxInstall.conf" + echo "EXISTINGuseRfidConf=$EXISTINGuseRfidConf" >> "${local_home_dir}/PhonieboxInstall.conf" read -rp "RFID shortcuts to play audio folders? [Y/n] " response case "$response" in @@ -324,7 +440,7 @@ check_existing() { ;; esac # append variables to config file - echo "EXISTINGuseRfidLinks=$EXISTINGuseRfidLinks" >> "${HOME_DIR}/PhonieboxInstall.conf" + echo "EXISTINGuseRfidLinks=$EXISTINGuseRfidLinks" >> "${local_home_dir}/PhonieboxInstall.conf" read -rp "Audio folders: use existing? [Y/n] " response case "$response" in @@ -336,7 +452,7 @@ check_existing() { ;; esac # append variables to config file - echo "EXISTINGuseAudio=$EXISTINGuseAudio" >> "${HOME_DIR}/PhonieboxInstall.conf" + echo "EXISTINGuseAudio=$EXISTINGuseAudio" >> "${local_home_dir}/PhonieboxInstall.conf" read -rp "Sound effects: use existing startup / shutdown sounds? [Y/n] " response case "$response" in @@ -348,9 +464,9 @@ check_existing() { ;; esac # append variables to config file - echo "EXISTINGuseSounds=$EXISTINGuseSounds" >> "${HOME_DIR}/PhonieboxInstall.conf" + echo "EXISTINGuseSounds=$EXISTINGuseSounds" >> "${local_home_dir}/PhonieboxInstall.conf" - if [ "$(printf '%s\n' "2.1" "$(cat ~/BACKUP/settings/version-number)" | sort -V | head -n1)" = "2.1" ]; then + if [ "$(printf '%s\n' "2.1" "$(cat ${local_home_dir}/BACKUP/settings/version-number)" | sort -V | head -n1)" = "2.1" ]; then read -rp "GPIO: use existing file? [Y/n] " response case "$response" in [nN][oO]|[nN]) @@ -370,7 +486,7 @@ https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Using-GPIO-hardware-buttons" config_gpio fi # append variables to config file - echo "EXISTINGuseGpio=$EXISTINGuseGpio" >> "${HOME_DIR}/PhonieboxInstall.conf" + echo "EXISTINGuseGpio=$EXISTINGuseGpio" >> "${local_home_dir}/PhonieboxInstall.conf" read -rp "Button USB Encoder: use existing device and button mapping? [Y/n] " response case "$response" in @@ -382,7 +498,7 @@ https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Using-GPIO-hardware-buttons" ;; esac # append variables to config file - echo "EXISTINGuseButtonUSBEncoder=$EXISTINGuseButtonUSBEncoder" >> "${HOME_DIR}/PhonieboxInstall.conf" + echo "EXISTINGuseButtonUSBEncoder=$EXISTINGuseButtonUSBEncoder" >> "${local_home_dir}/PhonieboxInstall.conf" echo "Thanks. Got it." echo "The existing install can be found in the BACKUP directory." @@ -391,7 +507,7 @@ https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Using-GPIO-hardware-buttons" esac fi # append variables to config file - echo "EXISTINGuse=$EXISTINGuse" >> "${HOME_DIR}/PhonieboxInstall.conf" + echo "EXISTINGuse=$EXISTINGuse" >> "${local_home_dir}/PhonieboxInstall.conf" # Check if we found a Phoniebox install configuration earlier and ask if to run this now if [ "${EXISTINGusePhonieboxInstall}" == "YES" ]; then @@ -404,9 +520,9 @@ https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Using-GPIO-hardware-buttons" [nN][oO]|[nN]) ;; *) - cd "${home_dir}" + cd "${local_home_dir}" clear - ./buster-install-default.sh -a + ./install-jukebox.sh -a exit ;; esac @@ -649,6 +765,7 @@ check_config_file() { check_variable "WIFIipRouter" fi fi + check_variable "EXISTINGuse" check_variable "AUDIOiFace" @@ -666,6 +783,18 @@ check_config_file() { check_variable "DIRaudioFolders" check_variable "GPIOconfig" + # Feature optional. if config not present, defaults to NO + if [[ -z "${AUTOHOTSPOTconfig}" ]]; then + echo "INFO: \$AUTOHOTSPOTconfig is missing or not set" + else + if [[ "$AUTOHOTSPOTconfig" == "YES" ]]; then + check_variable "AUTOHOTSPOTssid" + check_variable "AUTOHOTSPOTcountryCode" + check_variable "AUTOHOTSPOTpass" + check_variable "AUTOHOTSPOTip" + fi + fi + if [ "${fail}" == "true" ]; then exit 1 fi @@ -697,6 +826,8 @@ web_server_config() { local sudoers="/etc/sudoers" echo "Configuring web server..." + # make sure lighttp can access the home directory of the user + sudo chmod o+x ${HOME_DIR} # Web server configuration settings # -rw-r--r-- 1 root root 1040 Apr 30 09:19 /etc/lighttpd/lighttpd.conf sudo cp "${jukebox_dir}"/misc/sampleconfigs/lighttpd.conf.buster-default.sample "${lighthttpd_conf}" @@ -724,10 +855,23 @@ web_server_config() { sudo chmod 440 "${sudoers}" } +# Reads a textfile and pipes all lines as args to the given command. +# Does filter out comments. +# Arguments: +# 1 : textfile to read +# 2... : command to receive args (e.g. 'echo', 'apt-get -y install', ...) +call_with_args_from_file () { + local package_file="$1" + shift + + sed 's/#.*//g' ${package_file} | xargs "$@" +} + install_main() { local jukebox_dir="$1" local apt_get="sudo apt-get -qq --yes" local allow_downgrades="--allow-downgrades --allow-remove-essential --allow-change-held-packages" + local pip_install="sudo python3 -m pip install --upgrade --force-reinstall -q" clear @@ -770,49 +914,48 @@ install_main() { # INSTALLATION # Read install config as written so far - # (this might look stupid so far, but makes sense once - # the option to install from config file is introduced.) - # shellcheck source=scripts/installscripts/tests/ShellCheck/PhonieboxInstall.conf . "${HOME_DIR}/PhonieboxInstall.conf" # power management of wifi: switch off to avoid disconnecting sudo iwconfig wlan0 power off - # create backup of /etc/resolv.conf - sudo cp /etc/resolv.conf /etc/resolv.conf.orig + # in the docker test env fiddling with resolv.conf causes issues, see https://stackoverflow.com/a/60576223 + if [ "$DOCKER_RUNNING" != "true" ]; then + # create backup of /etc/resolv.conf + sudo cp /etc/resolv.conf /etc/resolv.conf.orig + fi # Generate locales sudo locale-gen "${LANG}" # Install required packages - ${apt_get} ${allow_downgrades} install apt-transport-https - sudo mkdir -p /usr/local/share/keyrings - sudo wget -q -O /usr/local/share/keyrings/mopidy-archive-keyring.gpg https://apt.mopidy.com/mopidy.gpg - sudo wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/buster.list + sudo mkdir -p /etc/apt/keyrings ${apt_get} update ${apt_get} upgrade - ${apt_get} install libspotify-dev + + # Get github code. git must be installed before, even if defined in packages.txt! + ${apt_get} install git + cd "${HOME_DIR}" + git clone ${GIT_URL} --branch "${GIT_BRANCH}" # some packages are only available on raspberry pi's but not on test docker containers running on x86_64 machines if [[ $(uname -m) =~ ^armv.+$ ]]; then - ${apt_get} ${allow_downgrades} install raspberrypi-kernel-headers + call_with_args_from_file "${jukebox_dir}"/packages-raspberrypi.txt ${apt_get} ${allow_downgrades} install fi - ${apt_get} ${allow_downgrades} install samba samba-common-bin gcc lighttpd php-common php-cgi php at mpd mpc mpg123 git ffmpeg resolvconf spi-tools netcat alsa-utils lsof procps + call_with_args_from_file "${jukebox_dir}"/packages.txt ${apt_get} ${allow_downgrades} install - # restore backup of /etc/resolv.conf in case installation of resolvconf cleared it - sudo cp /etc/resolv.conf.orig /etc/resolv.conf - - # prepare python3 - ${apt_get} ${allow_downgrades} install python3 python3-dev python3-pip python3-mutagen python3-gpiozero python3-spidev + # in the docker test env fiddling with resolv.conf causes issues, see https://stackoverflow.com/a/60576223 + if [ "$DOCKER_RUNNING" != "true" ]; then + # restore backup of /etc/resolv.conf in case installation of resolvconf cleared it + sudo cp /etc/resolv.conf.orig /etc/resolv.conf + fi # use python3 as default sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 1 - - # Get github code - cd "${HOME_DIR}" || exit - git clone ${GIT_URL} --branch "${GIT_BRANCH}" + # make compatible for Bookworm, which implements PEP 668 + sudo python3 -m pip config set global.break-system-packages true # VERSION of installation @@ -834,20 +977,20 @@ install_main() { # keep major verson 3 of mopidy echo -e "Package: mopidy\nPin: version 3.*\nPin-Priority: 1001" | sudo tee /etc/apt/preferences.d/mopidy - sudo wget -q -O /usr/local/share/keyrings/mopidy-archive-keyring.gpg https://apt.mopidy.com/mopidy.gpg - sudo wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/buster.list + sudo wget -q -O /etc/apt/keyrings/mopidy-archive-keyring.gpg https://apt.mopidy.com/mopidy.gpg + sudo wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/${OS_CODENAME}.list + ${apt_get} update ${apt_get} upgrade - ${apt_get} ${allow_downgrades} install mopidy mopidy-mpd mopidy-local mopidy-spotify - ${apt_get} ${allow_downgrades} install libspotify12 python3-cffi python3-ply python3-pycparser python3-spotify + call_with_args_from_file "${jukebox_dir}"/packages-spotify.txt ${apt_get} ${allow_downgrades} install # Install necessary Python packages - sudo python3 -m pip install --upgrade --force-reinstall -q -r "${jukebox_dir}"/requirements-spotify.txt + ${pip_install} -r "${jukebox_dir}"/requirements-spotify.txt fi # Install more required packages echo "Installing additional Python packages..." - sudo python3 -m pip install --upgrade --force-reinstall -q -r "${jukebox_dir}"/requirements.txt + ${pip_install} -r "${jukebox_dir}"/requirements.txt samba_config @@ -945,12 +1088,35 @@ install_main() { cp "${jukebox_dir}"/misc/sampleconfigs/startupsound.mp3.sample "${jukebox_dir}"/shared/startupsound.mp3 cp "${jukebox_dir}"/misc/sampleconfigs/shutdownsound.mp3.sample "${jukebox_dir}"/shared/shutdownsound.mp3 + if [ "${MPDconfig}" == "YES" ]; then + local mpd_conf="/etc/mpd.conf" + + echo "Configuring MPD..." + # MPD configuration + # -rw-r----- 1 mpd audio 14043 Jul 17 20:16 /etc/mpd.conf + sudo cp "${jukebox_dir}"/misc/sampleconfigs/mpd.conf.buster-default.sample ${mpd_conf} + # Change vars to match install config + sudo sed -i 's/%AUDIOiFace%/'"$AUDIOiFace"'/' "${mpd_conf}" + # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash + sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' "${mpd_conf}" + # Replace homedir; double quotes for variable expansion + sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${mpd_conf}" + sudo chown mpd:audio "${mpd_conf}" + sudo chmod 640 "${mpd_conf}" + + # start mpd + echo "Starting mpd service..." + sudo service mpd restart + sudo systemctl enable mpd + fi + # Spotify config if [ "${SPOTinstall}" == "YES" ]; then local etc_mopidy_conf="/etc/mopidy/mopidy.conf" local mopidy_conf="${HOME_DIR}/.config/mopidy/mopidy.conf" echo "Configuring Spotify support..." sudo systemctl disable mpd + sudo service mpd stop sudo systemctl enable mopidy # Install Config Files sudo cp "${jukebox_dir}"/misc/sampleconfigs/locale.gen.sample /etc/locale.gen @@ -981,30 +1147,13 @@ install_main() { # GPIO-Control if [[ "${GPIOconfig}" == "YES" ]]; then - sudo python3 -m pip install --upgrade --force-reinstall -q -r "${jukebox_dir}"/requirements-GPIO.txt + ${pip_install} -r "${jukebox_dir}"/requirements-GPIO.txt sudo systemctl enable phoniebox-gpio-control.service if [[ ! -f "${jukebox_dir}"/settings/gpio_settings.ini ]]; then cp "${jukebox_dir}"/misc/sampleconfigs/gpio_settings.ini.sample "${jukebox_dir}"/settings/gpio_settings.ini fi fi - if [ "${MPDconfig}" == "YES" ]; then - local mpd_conf="/etc/mpd.conf" - - echo "Configuring MPD..." - # MPD configuration - # -rw-r----- 1 mpd audio 14043 Jul 17 20:16 /etc/mpd.conf - sudo cp "${jukebox_dir}"/misc/sampleconfigs/mpd.conf.buster-default.sample ${mpd_conf} - # Change vars to match install config - sudo sed -i 's/%AUDIOiFace%/'"$AUDIOiFace"'/' "${mpd_conf}" - # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash - sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' "${mpd_conf}" - # Replace homedir; double quotes for variable expansion - sudo sed -i "s%/home/pi%${HOME_DIR}%g" "${mpd_conf}" - sudo chown mpd:audio "${mpd_conf}" - sudo chmod 640 "${mpd_conf}" - fi - # set which version has been installed if [ "${SPOTinstall}" == "YES" ]; then echo "plusSpotify" > "${jukebox_dir}"/settings/edition @@ -1020,9 +1169,7 @@ install_main() { } wifi_settings() { - local sample_configs_dir="$1" - local dhcpcd_conf="$2" - local wpa_supplicant_conf="$3" + local jukebox_dir="$1" ############################### # WiFi settings (SSID password) @@ -1034,10 +1181,12 @@ wifi_settings() { # $WIFIip # $WIFIipRouter if [ "${WIFIconfig}" == "YES" ]; then + # DHCP configuration settings + local dhcpcd_conf="/etc/dhcpcd.conf" echo "Setting ${dhcpcd_conf}..." #-rw-rw-r-- 1 root netdev 0 Apr 17 11:25 /etc/dhcpcd.conf - sudo cp "${sample_configs_dir}"/dhcpcd.conf.buster-default-noHotspot.sample "${dhcpcd_conf}" + sudo cp "${jukebox_dir}"/misc/sampleconfigs/dhcpcd.conf.buster-default-noHotspot.sample "${dhcpcd_conf}" # Change IP for router and Phoniebox sudo sed -i 's/%WIFIip%/'"$WIFIip"'/' "${dhcpcd_conf}" sudo sed -i 's/%WIFIipRouter%/'"$WIFIipRouter"'/' "${dhcpcd_conf}" @@ -1047,9 +1196,10 @@ wifi_settings() { sudo chmod 664 "${dhcpcd_conf}" # WiFi SSID & Password + local wpa_supplicant_conf="/etc/wpa_supplicant/wpa_supplicant.conf" echo "Setting ${wpa_supplicant_conf}..." # -rw-rw-r-- 1 root netdev 137 Jul 16 08:53 /etc/wpa_supplicant/wpa_supplicant.conf - sudo cp "${sample_configs_dir}"/wpa_supplicant.conf.buster-default.sample "${wpa_supplicant_conf}" + sudo cp "${jukebox_dir}"/misc/sampleconfigs/wpa_supplicant.conf.buster-default.sample "${wpa_supplicant_conf}" sudo sed -i 's/%WIFIssid%/'"$WIFIssid"'/' "${wpa_supplicant_conf}" sudo sed -i 's/%WIFIpass%/'"$WIFIpass"'/' "${wpa_supplicant_conf}" sudo sed -i 's/%WIFIcountryCode%/'"$WIFIcountryCode"'/' "${wpa_supplicant_conf}" @@ -1198,6 +1348,17 @@ folder_access() { ##################################################### } +autohotspot() { + local jukebox_dir="$1" + + # Behave the same as other steps and only add configuration if selected and dont remove + if [ "${AUTOHOTSPOTconfig}" == "YES" ]; then + local setup_script="${jukebox_dir}/scripts/helperscripts/setup_autohotspot.sh" + sudo chmod +x "${setup_script}" + "${setup_script}" "${jukebox_dir}" "${AUTOHOTSPOTconfig}" "${AUTOHOTSPOTssid}" "${AUTOHOTSPOTcountryCode}" "${AUTOHOTSPOTpass}" "${AUTOHOTSPOTip}" + fi +} + finish_installation() { local jukebox_dir="$1" echo " @@ -1278,6 +1439,8 @@ finish_installation() { # Main # ######## main() { + checkPrerequisite + # Skip interactive Samba WINS config dialog echo "samba-common samba-common/dhcp boolean false" | sudo debconf-set-selections @@ -1286,6 +1449,7 @@ main() { #reset_install_config_file config_wifi check_existing "${JUKEBOX_HOME_DIR}" "${JUKEBOX_BACKUP_DIR}" "${HOME_DIR}" + config_autohotspot config_audio_interface config_spotify config_mpd @@ -1296,7 +1460,8 @@ main() { check_config_file fi install_main "${JUKEBOX_HOME_DIR}" - wifi_settings "${JUKEBOX_HOME_DIR}/misc/sampleconfigs" "/etc/dhcpcd.conf" "/etc/wpa_supplicant/wpa_supplicant.conf" + wifi_settings "${JUKEBOX_HOME_DIR}" + autohotspot "${JUKEBOX_HOME_DIR}" existing_assets "${JUKEBOX_HOME_DIR}" "${JUKEBOX_BACKUP_DIR}" folder_access "${JUKEBOX_HOME_DIR}" "pi:www-data" 775 @@ -1310,7 +1475,7 @@ main() { else echo "Skipping USB device setup..." echo "For manual registration of a USB card reader type:" - echo "python3 ${HOME_DIR}/RPi-Jukebox-RFID/scripts/RegisterDevice.py" + echo "python3 ${JUKEBOX_HOME_DIR}/scripts/RegisterDevice.py" echo " " echo "Reboot is required to activate all settings!" fi diff --git a/scripts/installscripts/stretch-install-default-HotspotAddOn.sh b/scripts/installscripts/stretch-install-default-HotspotAddOn.sh deleted file mode 100644 index a7f9aa276..000000000 --- a/scripts/installscripts/stretch-install-default-HotspotAddOn.sh +++ /dev/null @@ -1,124 +0,0 @@ -#!/bin/bash -# DO NOT USE UNTIL THIS LINE HAS DISAPPEARED -# -# This script turns the Phoniebox into a Hotspot -# IF there is no other WiFi network to connect to. -# Needs to run on top of a finished install. And might -# not work if you are not using a Pi3 or ZERO with Wifi. -# See for more information: -# http://www.raspberryconnect.com/network/item/331-raspberry-pi-auto-wifi-hotspot-switch-no-internet-routing -# -# Belongs to: https://github.com/MiczFlor/RPi-Jukebox-RFID - -##################################################### -# Ask if access point - -clear - -echo "##################################################### -# -# CONFIGURE ACCESS POINT / HOTSPOT -# -# If you take your Phoniebox on the road and it is not -# connected to a WiFi network, it can automatically turn -# into an access point and show up as SSID 'phoniebox'. -# This will work for RPi3 out of the box. It might not -# work for other models and WiFi cards. -# (Note: can be done manually later, if you are unsure.) -" -read -r -p "Do you want to configure as Access Point? [Y/n] " response -case "$response" in - [nN][oO]|[nN]) - ACCESSconfig=NO - echo "You don't want to configure as an Access Point." - echo "Hit ENTER to proceed to the next step." - read -r - ;; - *) - ACCESSconfig=YES - ;; -esac -# append variables to config file -echo "ACCESSconfig=\"$ACCESSconfig\"" >> "${PATHDATA}/PhonieboxInstall.conf" - - -######################## -# Access Point / Hotspot -# http://www.raspberryconnect.com/network/item/331-raspberry-pi-auto-wifi-hotspot-switch-no-internet-routing -if [ $ACCESSconfig == "IGNOREFORNOWYES" ] -then - -# -# NOT IMPLEMENTED YET -# - # Work in progress, so keep in mind: BACKUP conf files for ACCESS POINT - # cp /etc/hostapd/hostapd.conf hostapd.conf.stretch.sample - # cp /etc/default/hostapd hostapd.stretch.sample - # cp /etc/dnsmasq.conf dnsmasq.conf.stretch.sample - # cp /etc/network/interfaces interfaces.stretch.sample - # WIFIcountryCode - # https://www.cisco.com/en/US/products/ps6305/products_configuration_guide_chapter09186a00804ddd8a.html - - # Remove dns-root-data - sudo apt-get purge dns-root-data - # Install packages - sudo apt-get install hostapd dnsmasq iw - # enter Y when prompted - - # The installers will have set up the programme so they run when the pi is started. - # For this setup they only need to be started if the home router is not found. - # So automatic startup needs to be disabled. This is done with the following commands: - sudo systemctl disable hostapd - sudo systemctl disable dnsmasq - - # -rw-r--r-- 1 root root 345 Aug 13 17:55 /etc/hostapd/hostapd.conf - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/hostapd.conf.stretch-default2-Hotspot.sample /etc/hostapd/hostapd.conf - sudo sed -i 's/%WIFIcountryCode%/'"$WIFIcountryCode"'/' /etc/hostapd/hostapd.conf - sudo chmod 644 /etc/hostapd/hostapd.conf - sudo chown root:root /etc/hostapd/hostapd.conf - - # -rw-r--r-- 1 root root 794 Aug 13 18:40 /etc/default/hostapd - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/hostapd.stretch-default2-Hotspot.sample /etc/default/hostapd - sudo chmod 644 /etc/default/hostapd - sudo chown root:root /etc/default/hostapd - - # -rw-r--r-- 1 root root 82 Jul 17 15:13 /etc/network/interfaces - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/interfaces.stretch-default2-Hotspot.sample /etc/network/interfaces - sudo chmod 644 /etc/network/interfaces - sudo chown root:root /etc/network/interfaces - - # DHCP configuration settings - #-rw-rw-r-- 1 root netdev 0 Apr 17 11:25 /etc/dhcpcd.conf - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/dhcpcd.conf.stretch-default2-Hotspot.sample /etc/dhcpcd.conf - # Change IP for router and Phoniebox - sudo sed -i 's/%WIFIip%/'"$WIFIip"'/' /etc/dhcpcd.conf - sudo sed -i 's/%WIFIipRouter%/'"$WIFIipRouter"'/' /etc/dhcpcd.conf - sudo sed -i 's/%WIFIcountryCode%/'"$WIFIcountryCode"'/' /etc/dhcpcd.conf - # Change user:group and access mod - sudo chown root:netdev /etc/dhcpcd.conf - sudo chmod 664 /etc/dhcpcd.conf - - # /usr/bin/autohotspot - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/autohotspot.stretch-default2-Hotspot.sample /usr/bin/autohotspot - sudo chown root:root /usr/bin/autohotspot - sudo chmod 644 /usr/bin/autohotspot - sudo chmod +x /usr/bin/autohotspot - - # /etc/systemd/system/autohotspot.service - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/autohotspot.service.stretch-default2-Hotspot.sample /etc/systemd/system/autohotspot.service - sudo chown root:root /etc/systemd/system/autohotspot.service - sudo chmod 644 /etc/systemd/system/autohotspot.service - sudo systemctl enable autohotspot.service - - echo " - ######################## - # Hotspot (Access Point) - NOTE: - The network 'phoniebox' appears only when away from your usual WiFi. - You can connect from any device with the password 'PlayItLoud'. - In your browser, open the IP '10.0.0.10' to access the web app. - " -fi - -# / Access Point -################ \ No newline at end of file diff --git a/scripts/installscripts/stretch-install-default.sh b/scripts/installscripts/stretch-install-default.sh deleted file mode 100755 index 49843d7cf..000000000 --- a/scripts/installscripts/stretch-install-default.sh +++ /dev/null @@ -1,894 +0,0 @@ -#!/bin/bash -# -# see https://github.com/MiczFlor/RPi-Jukebox-RFID for details -# Especially the docs folder for documentation - -# The absolute path to the folder which contains this script -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -GIT_BRANCH=${GIT_BRANCH:-master} - -clear -echo "##################################################### -# ___ __ ______ _ __________ ____ __ _ _ # -# / _ \/ // / __ \/ |/ / _/ __/( _ \ / \( \/ ) # -# / ___/ _ / /_/ / // // _/ ) _ (( O )) ( # -# /_/ /_//_/\____/_/|_/___/____/ (____/ \__/(_/\_) # -# # -##################################################### - -Welcome to the installation script. - -This script will install Phoniebox on your Raspberry Pi. -To do so, you must be online. The install script can -automatically configure: - -* WiFi settings (SSID, password and static IP) - -All these are optional and can also be done later -manually. - -If you are ready, hit ENTER" -read -r INPUT - -##################################################### -# CONFIG FILE -# This file will contain all the data given in the -# following dialogue -# At a later stage, the install should also be done -# from such a config file with no user input. - -# Remove existing config file -rm PhonieboxInstall.conf -# Create empty config file -touch PhonieboxInstall.conf -echo "# Phoniebox config" > "${PATHDATA}/PhonieboxInstall.conf" - -##################################################### -# Ask if wifi config - -clear - -echo "##################################################### -# -# CONFIGURE WIFI -# -# Requires SSID, WiFi password and the static IP you want -# to assign to your Phoniebox. -# (Note: can be done manually later, if you are unsure.) -" -read -r -p "Do you want to configure your WiFi? [Y/n] " response -case "$response" in - [nN][oO]|[nN]) - WIFIconfig=NO - echo "You want to configure WiFi later." - echo "Hit ENTER to proceed to the next step." - read -r INPUT - # append variables to config file - echo "WIFIconfig=$WIFIconfig" >> "${PATHDATA}/PhonieboxInstall.conf" - # make a fallback for WiFi Country Code, because we need that even without WiFi config - echo "WIFIcountryCode=DE" >> "${PATHDATA}/PhonieboxInstall.conf" - ;; - *) - WIFIconfig=YES - #Ask for ssid - echo "* Type SSID name" - read -r INPUT - WIFIssid="$INPUT" - #Ask for wifi country code - echo "* WiFi Country Code (e.g. DE, GB, CZ or US)" - read -r INPUT - WIFIcountryCode="$INPUT" - #Ask for password - echo "* Type password" - read -r INPUT - WIFIpass="$INPUT" - #Ask for IP - echo "* Static IP (e.g. 192.168.1.199)" - read -r INPUT - WIFIip="$INPUT" - #Ask for Router IP - echo "* Router IP (e.g. 192.168.1.1)" - read -r INPUT - WIFIipRouter="$INPUT" - echo "Your WiFi config:" - echo "SSID : $WIFIssid" - echo "WiFi Country Code : $WIFIcountryCode" - echo "Password : $WIFIpass" - echo "Static IP : $WIFIip" - echo "Router IP : $WIFIipRouter" - read -r -p "Are these values correct? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - echo "The values are incorrect." - echo "Hit ENTER to exit and start over." - read -r INPUT; exit - ;; - *) - # append variables to config file - echo "WIFIconfig=\"$WIFIconfig\"" >> "${PATHDATA}/PhonieboxInstall.conf" - echo "WIFIcountryCode=\"$WIFIcountryCode\"" >> "${PATHDATA}/PhonieboxInstall.conf" - echo "WIFIssid=\"$WIFIssid\"" >> "${PATHDATA}/PhonieboxInstall.conf" - echo "WIFIpass=\"$WIFIpass\"" >> "${PATHDATA}/PhonieboxInstall.conf" - echo "WIFIip=\"$WIFIip\"" >> "${PATHDATA}/PhonieboxInstall.conf" - echo "WIFIipRouter=\"$WIFIipRouter\"" >> "${PATHDATA}/PhonieboxInstall.conf" - ;; - esac - ;; -esac - -##################################################### -# Check for existing Phoniebox -# -# In case there is no existing install, -# set the var now for later use: -EXISTINGuse=NO - -# The install will be in the home dir of user pi -# Move to home directory now to check -cd || exit -if [ -d /home/pi/RPi-Jukebox-RFID ]; then - # Houston, we found something! - clear -echo "##################################################### -# -# . . . * alert * alert * alert * alert * . . . -# -# WARNING: an existing Phoniebox installation was found. -# -" - # check if we find the version number - if [ -f /home/pi/RPi-Jukebox-RFID/settings/version ]; then - echo "The version of your installation is: $(cat RPi-Jukebox-RFID/settings/version)" - fi - echo "IMPORTANT: you can use the existing content and configuration files for your new install." - echo "Whatever you chose to keep will be moved to the new install." - echo "Everything else will remain in a folder called 'BACKUP'. - " - # Delete or use existing installation? - read -r -p "Re-use config, audio and RFID codes for the new install? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuse=NO - echo "Phoniebox will be a fresh install. The existing version will be dropped." - echo "Hit ENTER to proceed to the next step." - sudo rm -rf RPi-Jukebox-RFID - read -r INPUT - ;; - *) - EXISTINGuse=YES - # CREATE BACKUP - # delete existing BACKUP dir if exists - if [ -d BACKUP ]; then - sudo rm -r BACKUP - fi - # move install to BACKUP dir - mv RPi-Jukebox-RFID BACKUP - # delete .git dir - if [ -d BACKUP/.git ]; then - sudo rm -r BACKUP/.git - fi - # delete placeholder files so moving the folder content back later will not create git pull conflicts - rm BACKUP/shared/audiofolders/placeholder - rm BACKUP/shared/shortcuts/placeholder - - # ask for things to use - echo "Ok. You want to use stuff from the existing installation." - echo "What would you want to keep? Answer now." - read -r -p "RFID config for system control (e.g. 'volume up' etc.)? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseRfidConf=NO - ;; - *) - EXISTINGuseRfidConf=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseRfidConf=$EXISTINGuseRfidConf" >> "${PATHDATA}/PhonieboxInstall.conf" - - read -r -p "RFID shortcuts to play audio folders? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseRfidLinks=NO - ;; - *) - EXISTINGuseRfidLinks=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseRfidLinks=$EXISTINGuseRfidLinks" >> "${PATHDATA}/PhonieboxInstall.conf" - - read -r -p "Audio folders: use existing? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseAudio=NO - ;; - *) - EXISTINGuseAudio=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseAudio=$EXISTINGuseAudio" >> "${PATHDATA}/PhonieboxInstall.conf" - - read -r -p "GPIO: use existing file? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseGpio=NO - ;; - *) - EXISTINGuseGpio=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseGpio=$EXISTINGuseGpio" >> "${PATHDATA}/PhonieboxInstall.conf" - - read -r -p "Sound effects: use existing startup / shutdown sounds? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseSounds=NO - ;; - *) - EXISTINGuseSounds=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseSounds=$EXISTINGuseSounds" >> "${PATHDATA}/PhonieboxInstall.conf" - - read -r -p "Button USB Encoder: use existing device and button mapping? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseButtonUSBEncoder=NO - ;; - *) - EXISTINGuseButtonUSBEncoder=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseButtonUSBEncoder=$EXISTINGuseButtonUSBEncoder" >> "${PATHDATA}/PhonieboxInstall.conf" - - echo "Thanks. Got it." - echo "The existing install can be found in the BACKUP directory." - echo "Hit ENTER to proceed to the next step." - read -r INPUT - ;; - esac -fi -# append variables to config file -echo "EXISTINGuse=$EXISTINGuse" >> "${PATHDATA}/PhonieboxInstall.conf" - -##################################################### -# Audio iFace - -clear - -echo "##################################################### -# -# CONFIGURE AUDIO INTERFACE (iFace) -# -# By default for the RPi the audio interface would be 'PCM'. -# But this does not work for every setup, alternatives are -# 'Master' or 'Speaker'. Other external sound cards might -# use different interface names. -# To list all available iFace names, type 'amixer scontrols' -# in the terminal. -" -read -r -p "Use PCM as iFace? [Y/n] " response -case "$response" in - [nN][oO]|[nN]) - echo "Type the iFace name you want to use:" - read -r INPUT - AUDIOiFace="$INPUT" - ;; - *) - AUDIOiFace="PCM" - ;; -esac -# append variables to config file -echo "AUDIOiFace=\"$AUDIOiFace\"" >> "${PATHDATA}/PhonieboxInstall.conf" -echo "Your iFace is called'$AUDIOiFace'" -echo "Hit ENTER to proceed to the next step." -read -r INPUT - -##################################################### -# Configure spotify - -clear - -echo "##################################################### -# -# OPTIONAL: INCLUDE SPOTIFY SUPPORT -# -# Spotify uses Mopidy for audio output and must -# be configured. Do it now, or never. -# (Note: To add this later, you must re-install phoniebox) -" -read -r -p "Do you want to install Mopidy? [Y/n] " response -case "$response" in - [nN][oO]|[nN]) - SPOTinstall=NO - echo "You don't want spotify support." - echo "Hit ENTER to proceed to the next step." - read -r INPUT - ;; - *) - SPOTinstall=YES - clear - echo "This was a great decision! Mopidy will be set up." - echo "##################################################### -# -# CONFIGURE MOPIDY -# -# Requires spotify username, password, client_id and client_secret -# to get connection to Spotify. -# -# (Note: You need a device with browser to generate ID and SECRET) -# -# Please go to this website: -# https://www.mopidy.com/authenticate/ -# and follow the instructions. -# -# Your credential will appear on the site below the login button. -# Please note your client_id and client_secret! -# -" - echo "" - echo "Type your Spotify username:" - read -r INPUT - SPOTIuser="$INPUT" - echo "" - echo "Type your Spotify password:" - read -r INPUT - SPOTIpass="$INPUT" - echo "" - echo "Type your client_id:" - read -r INPUT - SPOTIclientid="$INPUT" - echo "" - echo "Type your client_secret:" - read -r INPUT - SPOTIclientsecret="$INPUT" - echo "" - echo "Hit ENTER to proceed to the next step." - read -r INPUT - ;; -esac -# append variables to config file -{ - echo "SPOTinstall=\"$SPOTinstall\""; - echo "SPOTIuser=\"$SPOTIuser\""; - echo "SPOTIpass=\"$SPOTIpass\""; - echo "SPOTIclientid=\"$SPOTIclientid\""; - echo "SPOTIclientsecret=\"$SPOTIclientsecret\"" -} >> "${PATHDATA}/PhonieboxInstall.conf" - -if [ $SPOTinstall == "NO" ]; then -##################################################### -# Configure MPD - -clear - -echo "##################################################### -# -# CONFIGURE MPD -# -# MPD (Music Player Daemon) runs the audio output and must -# be configured. Do it now, if you are unsure. -# (Note: can be done manually later.) -" -read -r -p "Do you want to configure MPD? [Y/n] " response -case "$response" in - [nN][oO]|[nN]) - MPDconfig=NO - echo "You want to configure MPD later." - echo "Hit ENTER to proceed to the next step." - read -r INPUT - ;; - *) - MPDconfig=YES - echo "MPD will be set up with default values." - echo "Hit ENTER to proceed to the next step." - read -r INPUT - ;; -esac -# append variables to config file -echo "MPDconfig=\"$MPDconfig\"" >> "${PATHDATA}/PhonieboxInstall.conf" -fi - -##################################################### -# Folder path for audio files -# default: /home/pi/RPi-Jukebox-RFID/shared/audiofolders - -clear - -echo "##################################################### -# -# FOLDER CONTAINING AUDIO FILES -# -# The default location for folders containing audio files: -# /home/pi/RPi-Jukebox-RFID/shared/audiofolders -# -# If unsure, keep it like this. If your files are somewhere -# else, you can specify the folder in the next step. -# IMPORTANT: the folder will not be created, only the path -# will be remembered. If you use a custom folder, you must -# create it. -" - -read -r -p "Do you want to use the default location? [Y/n] " response -case "$response" in - [nN][oO]|[nN]) - echo "Please type the absolute path here (no trailing slash)." - echo "Default would be for example:" - echo "/home/pi/RPi-Jukebox-RFID/shared/audiofolders" - read -r INPUT - DIRaudioFolders="$INPUT" - ;; - *) - DIRaudioFolders="/home/pi/RPi-Jukebox-RFID/shared/audiofolders" - ;; -esac -# append variables to config file -echo "DIRaudioFolders=\"$DIRaudioFolders\"" >> "${PATHDATA}/PhonieboxInstall.conf" -echo "Your audio folders live in this dir:" -echo $DIRaudioFolders -echo "Hit ENTER to proceed to the next step." -read -r INPUT - -clear - -echo "##################################################### -# -# START INSTALLATION -# -# Good news: you completed the input. -# Let the install begin. -# -# Get yourself a cup of something. The install takes -# between 15 minutes to half an hour, depending on -# your Raspberry Pi and Internet connectivity. -# -# You will be prompted later to complete the installation. -" - -read -r -p "Do you want to start the installation? [Y/n] " response -case "$response" in - [nN][oO]|[nN]) - echo "Exiting the installation." - echo "Your configuration data was saved in this file:" - echo "${PATHDATA}/PhonieboxInstall.conf" - echo - exit - ;; -esac - -##################################################### -# INSTALLATION - -# Read install config as written so far -# (this might look stupid so far, but makes sense once -# the option to install from config file is introduced.) -# shellcheck source=scripts/installscripts/tests/ShellCheck/PhonieboxInstall.conf -. "${PATHDATA}/PhonieboxInstall.conf" - -# power management of wifi: switch off to avoid disconnecting -sudo iwconfig wlan0 power off - -# Install required packages -sudo apt-get update -sudo apt-get --yes --force-yes install apt-transport-https samba samba-common-bin gcc linux-headers-4.9 lighttpd php7.0-common php7.0-cgi php7.0 at mpd mpc mpg123 git ffmpeg - -# prepare for python2 and python3 -sudo apt-get --yes --force-yes install python-dev python-pip python-mutagen python-gpiozero python-spidev -sudo apt-get --yes --force-yes install python3-dev python3-pip python3-mutagen python3-gpiozero python3-spidev - -# use python3.5 as default -sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.5 1 -# Install required spotify packages -if [ $SPOTinstall == "YES" ] -then - wget -q -O - https://apt.mopidy.com/mopidy.gpg | sudo apt-key add - - sudo wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/stretch.list - sudo apt-get update - sudo apt-get --yes --force-yes install mopidy - sudo apt-get --yes --force-yes install libspotify12 python-cffi python-ply python-pycparser python-spotify - sudo apt-get --yes --force-yes install libspotify12 python3-cffi python3-ply python3-pycparser - sudo python3 -m pip install spotify - sudo rm -rf /usr/lib/python2.7/dist-packages/mopidy_spotify* - sudo rm -rf /usr/lib/python2.7/dist-packages/Mopidy_Spotify-* - cd || exit - sudo rm -rf mopidy-spotify - git clone -b fix/web_api_playlists --single-branch https://github.com/princemaxwell/mopidy-spotify.git - cd mopidy-spotify || exit - sudo python setup.py install - cd || exit - # should be removed, if Mopidy-Iris can be installed normally - # pylast >= 3.0.0 removed the python2 support - sudo pip install pylast==2.4.0 - sudo pip install Mopidy-Iris -fi - -# Get github code -cd /home/pi/ || exit -git clone https://github.com/MiczFlor/RPi-Jukebox-RFID.git --branch "${GIT_BRANCH}" - -# check, which branch was cloned -git status - -# the following three lines are needed as long as this is not the master branch: -cd /home/pi/RPi-Jukebox-RFID || exit -git fetch - -# Install more required packages -sudo pip install -r requirements.txt -sudo pip3 install -r /home/pi/RPi-Jukebox-RFID/components/rfid-reader/PN532/requirements.txt - -# actually, for the time being most of the requirements are run here (again). -# the requirements.txt version seems to throw errors. Help if you can to fix this: - -sudo pip install "evdev == 0.7.0" -sudo pip install --upgrade youtube_dl -sudo pip install spidev -sudo pip install git+git://github.com/lthiery/SPI-Py.git#egg=spi-py -sudo pip install pyserial -sudo pip install RPi.GPIO -sudo pip install pi-rc522 - -sudo python3 -m pip install "evdev == 0.7.0" - -# Switch of WiFi power management -sudo iwconfig wlan0 power off - -# Samba configuration settings -# -rw-r--r-- 1 root root 9416 Apr 30 09:02 /etc/samba/smb.conf -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/smb.conf.stretch-default2.sample /etc/samba/smb.conf -sudo chown root:root /etc/samba/smb.conf -sudo chmod 644 /etc/samba/smb.conf -# for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash -sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' /etc/samba/smb.conf -# Samba: create user 'pi' with password 'raspberry' -(echo "raspberry"; echo "raspberry") | sudo smbpasswd -s -a pi - -# Web server configuration settings -# -rw-r--r-- 1 root root 1040 Apr 30 09:19 /etc/lighttpd/lighttpd.conf -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/lighttpd.conf.stretch-default.sample /etc/lighttpd/lighttpd.conf -sudo chown root:root /etc/lighttpd/lighttpd.conf -sudo chmod 644 /etc/lighttpd/lighttpd.conf - -# Web server PHP7 fastcgi conf -# -rw-r--r-- 1 root root 398 Apr 30 09:35 /etc/lighttpd/conf-available/15-fastcgi-php.conf -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/15-fastcgi-php.conf.stretch-default.sample /etc/lighttpd/conf-available/15-fastcgi-php.conf -sudo chown root:root /etc/lighttpd/conf-available/15-fastcgi-php.conf -sudo chmod 644 /etc/lighttpd/conf-available/15-fastcgi-php.conf -# settings for php.ini to support upload -# -rw-r--r-- 1 root root 70999 Jun 14 13:50 /etc/php/7.0/fpm/php.ini -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/php.ini.stretch-default.sample /etc/php/7.0/fpm/php.ini -sudo chown root:root /etc/php/7.0/fpm/php.ini -sudo chmod 644 /etc/php/7.0/fpm/php.ini - -# SUDO users (adding web server here) -# -r--r----- 1 root root 703 Nov 17 21:08 /etc/sudoers -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/sudoers.stretch-default.sample /etc/sudoers -sudo chown root:root /etc/sudoers -sudo chmod 440 /etc/sudoers - -# copy shell script for player -cp /home/pi/RPi-Jukebox-RFID/settings/rfid_trigger_play.conf.sample /home/pi/RPi-Jukebox-RFID/settings/rfid_trigger_play.conf - -# creating files containing editable values for configuration -# DISCONTINUED: now done by MPD? echo "PCM" > /home/pi/RPi-Jukebox-RFID/settings/Audio_iFace_Name -echo "$AUDIOiFace" > /home/pi/RPi-Jukebox-RFID/settings/Audio_iFace_Name -echo "$DIRaudioFolders" > /home/pi/RPi-Jukebox-RFID/settings/Audio_Folders_Path -echo "3" > /home/pi/RPi-Jukebox-RFID/settings/Audio_Volume_Change_Step -echo "100" > /home/pi/RPi-Jukebox-RFID/settings/Max_Volume_Limit -echo "0" > /home/pi/RPi-Jukebox-RFID/settings/Idle_Time_Before_Shutdown -echo "RESTART" > /home/pi/RPi-Jukebox-RFID/settings/Second_Swipe -echo "/home/pi/RPi-Jukebox-RFID/playlists" > /home/pi/RPi-Jukebox-RFID/settings/Playlists_Folders_Path -echo "ON" > /home/pi/RPi-Jukebox-RFID/settings/ShowCover - -# The new way of making the bash daemon is using the helperscripts -# creating the shortcuts and script from a CSV file. -# see scripts/helperscripts/AssignIDs4Shortcuts.php - -# create config file for web app from sample -sudo cp /home/pi/RPi-Jukebox-RFID/htdocs/config.php.sample /home/pi/RPi-Jukebox-RFID/htdocs/config.php - -# Starting web server and php7 -sudo lighttpd-enable-mod fastcgi -sudo lighttpd-enable-mod fastcgi-php -sudo service lighttpd force-reload -sudo service php7.0-fpm restart - -# create copy of GPIO script -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/gpio-buttons.py.sample /home/pi/RPi-Jukebox-RFID/scripts/gpio-buttons.py -sudo chmod +x /home/pi/RPi-Jukebox-RFID/scripts/gpio-buttons.py - -# make sure bash scripts have the right settings -sudo chown pi:www-data /home/pi/RPi-Jukebox-RFID/scripts/*.sh -sudo chmod +x /home/pi/RPi-Jukebox-RFID/scripts/*.sh -sudo chown pi:www-data /home/pi/RPi-Jukebox-RFID/scripts/*.py -sudo chmod +x /home/pi/RPi-Jukebox-RFID/scripts/*.py - -# services to launch after boot using systemd -# -rw-r--r-- 1 root root 304 Apr 30 10:07 phoniebox-rfid-reader.service -# 1. delete old services (this is legacy, might throw errors but is necessary. Valid for versions < 1.1.8-beta) -echo "### Deleting older versions of service daemons. This might throw errors, ignore them" -sudo systemctl disable idle-watchdog -sudo systemctl disable rfid-reader -sudo systemctl disable startup-sound -sudo systemctl disable gpio-buttons -sudo rm /etc/systemd/system/rfid-reader.service -sudo rm /etc/systemd/system/startup-sound.service -sudo rm /etc/systemd/system/gpio-buttons.service -sudo rm /etc/systemd/system/idle-watchdog.service -echo "### Done with erasing old daemons. Stop ignoring errors!" -# 2. install new ones - this is version > 1.1.8-beta -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/phoniebox-rfid-reader.service.stretch-default.sample /etc/systemd/system/phoniebox-rfid-reader.service -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/phoniebox-startup-sound.service.stretch-default.sample /etc/systemd/system/phoniebox-startup-sound.service -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/phoniebox-gpio-buttons.service.stretch-default.sample /etc/systemd/system/phoniebox-gpio-buttons.service -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/phoniebox-idle-watchdog.service.sample /etc/systemd/system/phoniebox-idle-watchdog.service -sudo chown root:root /etc/systemd/system/phoniebox-rfid-reader.service -sudo chown root:root /etc/systemd/system/phoniebox-startup-sound.service -sudo chown root:root /etc/systemd/system/phoniebox-gpio-buttons.service -sudo chown root:root /etc/systemd/system/phoniebox-idle-watchdog.service -sudo chmod 644 /etc/systemd/system/phoniebox-rfid-reader.service -sudo chmod 644 /etc/systemd/system/phoniebox-startup-sound.service -sudo chmod 644 /etc/systemd/system/phoniebox-gpio-buttons.service -sudo chmod 644 /etc/systemd/system/phoniebox-idle-watchdog.service -# enable the services needed -sudo systemctl enable phoniebox-idle-watchdog -sudo systemctl enable phoniebox-rfid-reader -sudo systemctl enable phoniebox-startup-sound -sudo systemctl enable phoniebox-gpio-buttons - -# copy mp3s for startup and shutdown sound to the right folder -cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/startupsound.mp3.sample /home/pi/RPi-Jukebox-RFID/shared/startupsound.mp3 -cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/shutdownsound.mp3.sample /home/pi/RPi-Jukebox-RFID/shared/shutdownsound.mp3 - -if [ $SPOTinstall == "NO" ] -then - # MPD configuration - # -rw-r----- 1 mpd audio 14043 Jul 17 20:16 /etc/mpd.conf - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/mpd.conf.sample /etc/mpd.conf - # Change vars to match install config - sudo sed -i 's/%AUDIOiFace%/'"$AUDIOiFace"'/' /etc/mpd.conf - # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash - sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' /etc/mpd.conf - echo "classic" > /home/pi/RPi-Jukebox-RFID/settings/edition - sudo chown mpd:audio /etc/mpd.conf - sudo chmod 640 /etc/mpd.conf - # update mpc / mpd DB - mpc update -fi - -if [ $SPOTinstall == "YES" ] -then - sudo systemctl disable mpd - sudo systemctl enable mopidy - # Install Config Files - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/locale.gen.sample /etc/locale.gen - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/locale.sample /etc/default/locale - sudo locale-gen - sudo mkdir /home/pi/.config - sudo mkdir /home/pi/.config/mopidy - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/mopidy-etc.sample /etc/mopidy/mopidy.conf - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/mopidy.sample ~/.config/mopidy/mopidy.conf - echo "plusSpotify" > /home/pi/RPi-Jukebox-RFID/settings/edition - # Change vars to match install config - sudo sed -i 's/%spotify_username%/'"$SPOTIuser"'/' /etc/mopidy/mopidy.conf - sudo sed -i 's/%spotify_password%/'"$SPOTIpass"'/' /etc/mopidy/mopidy.conf - sudo sed -i 's/%spotify_client_id%/'"$SPOTIclientid"'/' /etc/mopidy/mopidy.conf - sudo sed -i 's/%spotify_client_secret%/'"$SPOTIclientsecret"'/' /etc/mopidy/mopidy.conf - sudo sed -i 's/%spotify_username%/'"$SPOTIuser"'/' ~/.config/mopidy/mopidy.conf - sudo sed -i 's/%spotify_password%/'"$SPOTIpass"'/' ~/.config/mopidy/mopidy.conf - sudo sed -i 's/%spotify_client_id%/'"$SPOTIclientid"'/' ~/.config/mopidy/mopidy.conf - sudo sed -i 's/%spotify_client_secret%/'"$SPOTIclientsecret"'/' ~/.config/mopidy/mopidy.conf -fi - -############################### -# WiFi settings (SSID password) -# -# https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md -# -# $WIFIssid -# $WIFIpass -# $WIFIip -# $WIFIipRouter -if [ $WIFIconfig == "YES" ] -then - # DHCP configuration settings - #-rw-rw-r-- 1 root netdev 0 Apr 17 11:25 /etc/dhcpcd.conf - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/dhcpcd.conf.stretch-default2-noHotspot.sample /etc/dhcpcd.conf - # Change IP for router and Phoniebox - sudo sed -i 's/%WIFIip%/'"$WIFIip"'/' /etc/dhcpcd.conf - sudo sed -i 's/%WIFIipRouter%/'"$WIFIipRouter"'/' /etc/dhcpcd.conf - sudo sed -i 's/%WIFIcountryCode%/'"$WIFIcountryCode"'/' /etc/dhcpcd.conf - # Change user:group and access mod - sudo chown root:netdev /etc/dhcpcd.conf - sudo chmod 664 /etc/dhcpcd.conf - - # WiFi SSID & Password - # -rw-rw-r-- 1 root netdev 137 Jul 16 08:53 /etc/wpa_supplicant/wpa_supplicant.conf - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/wpa_supplicant.conf.stretch.sample /etc/wpa_supplicant/wpa_supplicant.conf - sudo sed -i 's/%WIFIssid%/'"$WIFIssid"'/' /etc/wpa_supplicant/wpa_supplicant.conf - sudo sed -i 's/%WIFIpass%/'"$WIFIpass"'/' /etc/wpa_supplicant/wpa_supplicant.conf - sudo sed -i 's/%WIFIcountryCode%/'"$WIFIcountryCode"'/' /etc/wpa_supplicant/wpa_supplicant.conf - sudo chown root:netdev /etc/wpa_supplicant/wpa_supplicant.conf - sudo chmod 664 /etc/wpa_supplicant/wpa_supplicant.conf -fi - -# start DHCP -sudo service dhcpcd start -sudo systemctl enable dhcpcd - -# / WiFi settings (SSID password) -############################### - -# / INSTALLATION -##################################################### - -##################################################### -# EXISTING ASSETS TO USE FROM EXISTING INSTALL - -if [ $EXISTINGuse == "YES" ] -then - - # RFID config for system control - if [ $EXISTINGuseRfidConf == "YES" ] - then - # read old values and write them into new file (copied above already) - # do not overwrite but use 'sed' in case there are new vars in new version installed - - # Read the existing RFID config file line by line and use - # only lines which are separated (IFS) by '='. - while IFS='=' read -r key val ; do - # $var should be stripped of possible leading or trailing " - val=${val%\"} - val=${val#\"} - key=${key} - # Additional error check: key should not start with a hash and not be empty. - if [ ! "${key:0:1}" == '#' ] && [ -n "$key" ] - then - # Replace the matching value in the newly created conf file - sed -i 's/%'"$key"'%/'"$val"'/' /home/pi/RPi-Jukebox-RFID/settings/rfid_trigger_play.conf - fi - done /dev/null) + if [[ ! $(echo "${crontab_user}" | grep -w "${autohotspot_script}") ]]; then + echo " ERROR: crontab for user not installed" + ((failed_tests++)) + fi + ((tests++)) + + # check owner and permissions + check_chmod_chown 644 root root "/etc" "dnsmasq.conf hostapd/hostapd.conf default/hostapd" + check_chmod_chown 664 root netdev "/etc" "dhcpcd.conf" + check_chmod_chown 644 root root "/etc/systemd/system" "${autohotspot_service}" + + # check that the services are activ + check_service_enablement "${autohotspot_service}" enabled + check_service_enablement hostapd disabled + check_service_enablement dnsmasq disabled + fi +} + +# Reads a textfile and pipes all lines as args to the given command. +# Does filter out comments, egg-prefixes and version suffixes +# Arguments: +# 1 : textfile to read +# 2... : command to receive args (e.g. 'echo', 'apt-get -y install', ...) +call_with_args_from_file() { + local package_file="$1" + shift + + sed 's/.*#egg=//g' ${package_file} | sed -E 's/(#|=|>|<).*//g' | xargs "$@" +} + +verify_apt_packages() { + local jukebox_dir="$1" + local packages=$(call_with_args_from_file "${jukebox_dir}"/packages.txt echo) + local packages_raspberrypi=$(call_with_args_from_file "${jukebox_dir}"/packages-raspberrypi.txt echo) + local packages_spotify=$(call_with_args_from_file "${jukebox_dir}"/packages-spotify.txt echo) + local packages_autohotspot=$(call_with_args_from_file "${jukebox_dir}"/packages-autohotspot.txt echo) printf "\nTESTING installed packages...\n\n" @@ -168,14 +248,19 @@ python3-cffi python3-ply python3-pycparser python3-spotify" packages="${packages} ${packages_spotify}" fi + if [[ "$AUTOHOTSPOTconfig" == "YES" ]]; then + packages="${packages} ${packages_autohotspot}" + fi + # check for raspberry pi packages only on raspberry pi's but not on test docker containers running on x86_64 machines if [[ $(uname -m) =~ ^armv.+$ ]]; then packages="${packages} ${packages_raspberrypi}" fi + local apt_list_installed=$(apt -qq list --installed 2>/dev/null) for package in ${packages} do - if [[ $(apt -qq list "${package}" 2>/dev/null | grep 'installed') ]]; then + if [[ $(echo "${apt_list_installed}" | grep -i "${package}.*installed") ]]; then echo " ${package} is installed" else echo " ERROR: ${package} is not installed" @@ -186,11 +271,12 @@ python3-cffi python3-ply python3-pycparser python3-spotify" } verify_pip_packages() { - local modules="evdev spi-py youtube_dl pyserial RPi.GPIO" - local modules_spotify="Mopidy-Iris" - local modules_pn532="py532lib" - local modules_rc522="pi-rc522" - local deviceName="${JUKEBOX_HOME_DIR}"/scripts/deviceName.txt + local jukebox_dir="$1" + local modules=$(call_with_args_from_file "${jukebox_dir}"/requirements.txt echo) + local modules_spotify=$(call_with_args_from_file "${jukebox_dir}"/requirements-spotify.txt echo) + local modules_pn532=$(call_with_args_from_file "${jukebox_dir}"/components/rfid-reader/PN532/requirements.txt echo) + local modules_rc522=$(call_with_args_from_file "${jukebox_dir}"/components/rfid-reader/RC522/requirements.txt echo) + local deviceName="${jukebox_dir}"/scripts/deviceName.txt printf "\nTESTING installed pip modules...\n\n" @@ -201,21 +287,22 @@ verify_pip_packages() { if [[ -f "${deviceName}" ]]; then # RC522 reader is used - if grep -Fxq "${deviceName}" MFRC522 + if grep -Fxq "MFRC522" "${deviceName}" then modules="${modules} ${modules_rc522}" fi # PN532 reader is used - if grep -Fxq "${deviceName}" PN532 + if grep -Fxq "PN532" "${deviceName}" then modules="${modules} ${modules_pn532}" fi fi + local pip_list_installed=$(pip3 list) for module in ${modules} do - if [[ $(pip3 show "${module}") ]]; then + if [[ $(echo "${pip_list_installed}" | grep -i "${module}") ]]; then echo " ${module} is installed" else echo " ERROR: pip module ${module} is not installed" @@ -233,10 +320,11 @@ verify_samba_config() { } verify_webserver_config() { + local phpver="$(ls -1 /etc/php)" printf "\nTESTING webserver config...\n\n" check_chmod_chown 644 root root "/etc/lighttpd" "lighttpd.conf" check_chmod_chown 644 root root "/etc/lighttpd/conf-available" "15-fastcgi-php.conf" - check_chmod_chown 644 root root "/etc/php/7.3/cgi" "php.ini" + check_chmod_chown 644 root root "/etc/php/${phpver}/cgi" "php.ini" check_chmod_chown 440 root root "/etc" "sudoers" # Bonus TODO: check that fastcgi and fastcgi-php mods are enabled @@ -295,13 +383,13 @@ verify_mpd_config() { } verify_folder_access() { - local jukebox_dir="${HOME_DIR}/RPi-Jukebox-RFID" + local jukebox_dir="$1" printf "\nTESTING folder access...\n\n" # check owner and permissions - check_chmod_chown 775 pi www-data "${jukebox_dir}" "playlists shared htdocs settings" + check_chmod_chown 775 "$USER_NAME" www-data "${jukebox_dir}" "playlists shared htdocs settings" # ${DIRaudioFolders} => "testing" "audiofolders" - check_chmod_chown 775 pi www-data "${DIRaudioFolders}/.." "audiofolders" + check_chmod_chown 775 "$USER_NAME" www-data "${DIRaudioFolders}/.." "audiofolders" #find .sh and .py scripts that are NOT executable local count=$(find . -maxdepth 1 -type f \( -name "*.sh" -o -name "*.py" \) ! -executable | wc -l) @@ -315,12 +403,13 @@ verify_folder_access() { main() { printf "\nTesting installation:\n" + verify_installation_exitcode verify_conf_file if [[ "$WIFIconfig" == "YES" ]]; then verify_wifi_settings fi - verify_apt_packages - verify_pip_packages + verify_apt_packages "${JUKEBOX_HOME_DIR}" + verify_pip_packages "${JUKEBOX_HOME_DIR}" verify_samba_config verify_webserver_config verify_systemd_services @@ -328,7 +417,8 @@ main() { verify_spotify_config fi verify_mpd_config - verify_folder_access + verify_autohotspot_settings + verify_folder_access "${JUKEBOX_HOME_DIR}" } start=$(date +%s) diff --git a/scripts/installscripts/tests/test_installation_altuser.sh b/scripts/installscripts/tests/test_installation_altuser.sh deleted file mode 100755 index de61a2f0b..000000000 --- a/scripts/installscripts/tests/test_installation_altuser.sh +++ /dev/null @@ -1,349 +0,0 @@ -#!/usr/bin/env bash - -# Test to verify that the installation script works as expected. -# This script needs to be adapted, if new packages, etc are added to the install script - -# The absolute path to the folder which contains this script -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -HOME_DIR="/home/hans" - -tests=0 -failed_tests=0 - -# Tool functions - -check_chmod_chown() { - local mod_expected=$1 - local user_expected=$2 - local group_expected=$3 - local dir=$4 - local files=$5 - - for file in ${files}; - do - mod_actual=$(stat --format '%a' "${dir}/${file}") - user_actual=$(stat -c '%U' "${dir}/${file}") - group_actual=$(stat -c '%G' "${dir}/${file}") - test ! "${mod_expected}" -eq "${mod_actual}" && echo " ERROR: ${file} actual mod (${mod_actual}) differs from expected (${mod_expected})!" - test ! "${user_expected}" == "${user_actual}" && echo " ERROR: ${file} actual owner (${user_actual}) differs from expected (${user_expected})!" - test ! "${group_expected}" == "${group_actual}" && echo " ERROR: ${file} actual group (${group_actual}) differs from expected (${group_expected})!" - done -} - -check_file_contains_string() { - local string="$1" - local file="$2" - - # sudo is required for checking /etc/mopidy/mopidy.conf - if [[ ! $(sudo grep -iw "${string}" "${file}") ]]; then - echo " ERROR: '${string}' not found in ${file}" - ((failed_tests++)) - fi - ((tests++)) -} - -check_service_state() { - local service="$1" - local desired_state="$2" - - local actual_state=$(systemctl show -p ActiveState --value "${service}") - if [[ ! "${actual_state}" == "${desired_state}" ]]; then - echo " ERROR: service ${service} is not ${desired_state} (state: ${actual_state})." - ((failed_tests++)) - fi - ((tests++)) -} - -check_service_enablement() { - local service="$1" - local desired_enablement="$2" - - local actual_enablement=$(systemctl is-enabled "${service}") - if [[ ! "${actual_enablement}" == "${desired_enablement}" ]]; then - echo " ERROR: service ${service} is not ${desired_enablement} (state: ${actual_enablement})." - ((failed_tests++)) - fi - ((tests++)) -} - -check_variable() { - local variable=${1} - # check if variable exist and if it's empty - test -z "${!variable+x}" && echo "ERROR: \$${variable} is missing!" && fail=true && return - test "${!variable}" == "" && echo "ERROR: \$${variable} is empty!" && fail=true -} - -# Verify functions - -verify_conf_file() { - local install_conf="${HOME_DIR}/PhonieboxInstall.conf" - printf "\nTESTING PhonieboxInstall.conf file...\n\n" - # check that PhonieboxInstall.conf exists and is not empty - - # check if config file exists - if [[ -f "${install_conf}" ]]; then - # Source config file - source "${install_conf}" - cat "${install_conf}" - echo "" - else - echo "ERROR: ${install_conf} does not exist!" - exit 1 - fi - - fail=false - if [[ -z "${WIFIconfig+x}" ]]; then - echo " ERROR: \$WIFIconfig is missing or not set!" && fail=true - else - echo "\$WIFIconfig is set to '$WIFIconfig'" - if [[ "$WIFIconfig" == "YES" ]]; then - check_variable "WIFIcountryCode" - check_variable "WIFIssid" - check_variable "WIFIpass" - check_variable "WIFIip" - check_variable "WIFIipRouter" - fi - fi - check_variable "EXISTINGuse" - check_variable "AUDIOiFace" - - if [[ -z "${SPOTinstall+x}" ]]; then - echo " ERROR: \$SPOTinstall is missing or not set!" && fail=true - else - echo "\$SPOTinstall is set to '$SPOTinstall'" - if [ "$SPOTinstall" == "YES" ]; then - check_variable "SPOTIuser" - check_variable "SPOTIpass" - check_variable "SPOTIclientid" - check_variable "SPOTIclientsecret" - fi - fi - check_variable "MPDconfig" - check_variable "DIRaudioFolders" - - if [ "${fail}" == "true" ]; then - exit 1 - fi - - echo "" -} - -verify_wifi_settings() { - local dhcpcd_conf="/etc/dhcpcd.conf" - local wpa_supplicant_conf="/etc/wpa_supplicant/wpa_supplicant.conf" - printf "\nTESTING WiFi settings...\n" - - # check conf files - check_file_contains_string "static ip_address=${WIFIip}/24" "${dhcpcd_conf}" - check_file_contains_string "static routers=${WIFIipRouter}" "${dhcpcd_conf}" - check_file_contains_string "static domain_name_servers=8.8.8.8 ${WIFIipRouter}" "${dhcpcd_conf}" - - check_file_contains_string "country=${WIFIcountryCode}" "${wpa_supplicant_conf}" - check_file_contains_string "ssid=\"${WIFIssid}\"" "${wpa_supplicant_conf}" - check_file_contains_string "psk=\"${WIFIpass}\"" "${wpa_supplicant_conf}" - - # check owner and permissions - check_chmod_chown 664 root netdev "/etc" "dhcpcd.conf" - check_chmod_chown 664 root netdev "/etc/wpa_supplicant" "wpa_supplicant.conf" - - # check that dhcpcd service is enabled and started - check_service_state dhcpcd active - check_service_enablement dhcpcd enabled -} - -verify_apt_packages(){ - local packages="libspotify-dev samba -samba-common-bin gcc lighttpd php7.3-common php7.3-cgi php7.3 at mpd mpc mpg123 git ffmpeg -resolvconf spi-tools python3 python3-dev python3-pip python3-mutagen python3-gpiozero -python3-spidev netcat alsa-utils" - # TODO apt-transport-https checking only on RPi is currently a workaround - local packages_raspberrypi="apt-transport-https raspberrypi-kernel-headers" - local packages_spotify="mopidy mopidy-mpd mopidy-local mopidy-spotify libspotify12 -python3-cffi python3-ply python3-pycparser python3-spotify" - - printf "\nTESTING installed packages...\n\n" - - # also check for spotify packages if it has been installed - if [[ "${SPOTinstall}" == "YES" ]]; then - packages="${packages} ${packages_spotify}" - fi - - # check for raspberry pi packages only on raspberry pi's but not on test docker containers running on x86_64 machines - if [[ $(uname -m) =~ ^armv.+$ ]]; then - packages="${packages} ${packages_raspberrypi}" - fi - - for package in ${packages} - do - if [[ $(apt -qq list "${package}" 2>/dev/null | grep 'installed') ]]; then - echo " ${package} is installed" - else - echo " ERROR: ${package} is not installed" - ((failed_tests++)) - fi - ((tests++)) - done -} - -verify_pip_packages() { - local modules="evdev spi-py youtube_dl pyserial RPi.GPIO" - local modules_spotify="Mopidy-Iris" - local modules_pn532="py532lib" - local modules_rc522="pi-rc522" - local deviceName="${JUKEBOX_HOME_DIR}"/scripts/deviceName.txt - - printf "\nTESTING installed pip modules...\n\n" - - # also check for spotify pip modules if it has been installed - if [[ "${SPOTinstall}" == "YES" ]]; then - modules="${modules} ${modules_spotify}" - fi - - if [[ -f "${deviceName}" ]]; then - # RC522 reader is used - if grep -Fxq "${deviceName}" MFRC522 - then - modules="${modules} ${modules_rc522}" - fi - - # PN532 reader is used - if grep -Fxq "${deviceName}" PN532 - then - modules="${modules} ${modules_pn532}" - fi - fi - - for module in ${modules} - do - if [[ $(pip3 show "${module}") ]]; then - echo " ${module} is installed" - else - echo " ERROR: pip module ${module} is not installed" - ((failed_tests++)) - fi - ((tests++)) - done -} - -verify_samba_config() { - printf "\nTESTING samba config...\n\n" - check_chmod_chown 644 root root "/etc/samba" "smb.conf" - - check_file_contains_string "path=${DIRaudioFolders}" "/etc/samba/smb.conf" -} - -verify_webserver_config() { - printf "\nTESTING webserver config...\n\n" - check_chmod_chown 644 root root "/etc/lighttpd" "lighttpd.conf" - check_chmod_chown 644 root root "/etc/lighttpd/conf-available" "15-fastcgi-php.conf" - check_chmod_chown 644 root root "/etc/php/7.3/cgi" "php.ini" - check_chmod_chown 440 root root "/etc" "sudoers" - - # Bonus TODO: check that fastcgi and fastcgi-php mods are enabled -} - -verify_systemd_services() { - printf "\nTESTING systemd services...\n\n" - # check that services exist - check_chmod_chown 644 root root "/etc/systemd/system" "phoniebox-rfid-reader.service phoniebox-startup-scripts.service phoniebox-gpio-control.service phoniebox-idle-watchdog.service" - - # check that phoniebox services are enabled - check_service_enablement phoniebox-idle-watchdog enabled - check_service_enablement phoniebox-rfid-reader enabled - check_service_enablement phoniebox-startup-scripts enabled - check_service_enablement phoniebox-gpio-control enabled -} - -verify_spotify_config() { - local etc_mopidy_conf="/etc/mopidy/mopidy.conf" - local mopidy_conf="${HOME_DIR}/.config/mopidy/mopidy.conf" - - printf "\nTESTING spotify config...\n\n" - - check_file_contains_string "username = ${SPOTIuser}" "${etc_mopidy_conf}" - check_file_contains_string "password = ${SPOTIpass}" "${etc_mopidy_conf}" - check_file_contains_string "client_id = ${SPOTIclientid}" "${etc_mopidy_conf}" - check_file_contains_string "client_secret = ${SPOTIclientsecret}" "${etc_mopidy_conf}" - check_file_contains_string "media_dir = ${DIRaudioFolders}" "${etc_mopidy_conf}" - - check_file_contains_string "username = ${SPOTIuser}" "${mopidy_conf}" - check_file_contains_string "password = ${SPOTIpass}" "${mopidy_conf}" - check_file_contains_string "client_id = ${SPOTIclientid}" "${mopidy_conf}" - check_file_contains_string "client_secret = ${SPOTIclientsecret}" "${mopidy_conf}" - check_file_contains_string "media_dir = ${DIRaudioFolders}" "${mopidy_conf}" - - # check that mopidy service is enabled - check_service_enablement mopidy enabled - # check that mpd service is disabled - check_service_enablement mpd disabled -} - -verify_mpd_config() { - local mpd_conf="/etc/mpd.conf" - - printf "\nTESTING mpd config...\n\n" - - check_file_contains_string "^[[:blank:]]\+mixer_control[[:blank:]]\+\"${AUDIOiFace}\"" "${mpd_conf}" - check_file_contains_string "^music_directory[[:blank:]]\+\"${DIRaudioFolders}\"" "${mpd_conf}" - - check_chmod_chown 640 mpd audio "/etc" "mpd.conf" - - # check that mpd service is enabled, when Spotify support is not installed - if [[ "${SPOTinstall}" == "NO" ]]; then - check_service_enablement mpd enabled - fi -} - -verify_folder_access() { - local jukebox_dir="${HOME_DIR}/RPi-Jukebox-RFID" - printf "\nTESTING folder access...\n\n" - - # check owner and permissions - check_chmod_chown 775 hans www-data "${jukebox_dir}" "playlists shared htdocs settings" - # ${DIRaudioFolders} => "testing" "audiofolders" - check_chmod_chown 775 hans www-data "${DIRaudioFolders}/.." "audiofolders" - - #find .sh and .py scripts that are NOT executable - local count=$(find . -maxdepth 1 -type f \( -name "*.sh" -o -name "*.py" \) ! -executable | wc -l) - if [[ "${count}" -gt 0 ]]; then - echo " ERROR: found ${count} '*.sh' and/or '*.py' files that are NOT executable:" - find . -maxdepth 1 -type f \( -name "*.sh" -o -name "*.py" \) ! -executable - ((failed_tests++)) - fi - ((tests++)) -} - -main() { - printf "\nTesting installation:\n" - verify_conf_file - if [[ "$WIFIconfig" == "YES" ]]; then - verify_wifi_settings - fi - verify_apt_packages - verify_pip_packages - verify_samba_config - verify_webserver_config - verify_systemd_services - if [[ "${SPOTinstall}" == "YES" ]]; then - verify_spotify_config - fi - verify_mpd_config - verify_folder_access -} - -start=$(date +%s) -main -end=$(date +%s) - -runtime=$((end-start)) -((h=${runtime}/3600)) -((m=($runtime%3600)/60)) -((s=$runtime%60)) - -if [[ "${failed_tests}" -gt 0 ]]; then - echo "${failed_tests} Test(s) failed (of ${tests} tests) (in ${h}h ${m}m ${s}s)." - exit 1 -else - echo "${tests} tests done in ${h}h ${m}m ${s}s." -fi - diff --git a/scripts/playout_controls.sh b/scripts/playout_controls.sh index 0bc6a3a67..908655ff8 100755 --- a/scripts/playout_controls.sh +++ b/scripts/playout_controls.sh @@ -73,6 +73,8 @@ NOW=`date +%Y-%m-%d.%H:%M:%S` # readwifiipoverspeaker # bluetoothtoggle # switchaudioiface +# sharedsyncfull +# sharedsyncchangeonrfidscan # The absolute path to the folder which contains all the scripts. # Unless you are working with symlinks, leave the following line untouched. @@ -118,6 +120,8 @@ if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo "VAR VALUE: ${VALUE}" # speed of these commands. shortcutCommands="^(setvolume|volumedown|volumeup|mute)$" +autohotspot_script="/usr/bin/autohotspot" + # Run the code from this block only, if the current command is not in "shortcutCommands" if [[ ! "$COMMAND" =~ $shortcutCommands ]] then @@ -285,7 +289,7 @@ case $COMMAND in # schedule shutdown after VALUE minutes echo "${PATHDATA}/playout_controls.sh -c=shutdownsilent" | at -q q now + ${VALUE} minute fi - ;; + ;; reboot) if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi ${PATHDATA}/resume_play.sh -c=savepos && mpc clear @@ -1003,6 +1007,7 @@ case $COMMAND in enablewifi) if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi rfkill unblock wifi + if [ -f "$autohotspot_script" ]; then sudo "$autohotspot_script"; fi ;; disablewifi) if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi @@ -1028,6 +1033,7 @@ case $COMMAND in if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " Wifi will now be activated" >> ${PATHDATA}/../logs/debug.log; fi echo "Wifi will now be activated" rfkill unblock wifi + if [ -f "$autohotspot_script" ]; then sudo "$autohotspot_script"; fi fi ;; randomcard) @@ -1136,6 +1142,12 @@ case $COMMAND in dbg "Command requires \"amixer\" as volume manager." fi ;; + sharedsyncfull) + $PATHDATA/../components/synchronisation/sync-shared/sync-shared.sh -c=full + ;; + sharedsyncchangeonrfidscan) + $PATHDATA/../components/synchronisation/sync-shared/sync-shared.sh -c=changeOnRfidScan -v="$VALUE" + ;; *) echo Unknown COMMAND $COMMAND VALUE $VALUE if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo "Unknown COMMAND ${COMMAND} VALUE ${VALUE}" >> ${PATHDATA}/../logs/debug.log; fi diff --git a/scripts/python-phoniebox/ConfigParserExtended.py b/scripts/python-phoniebox/ConfigParserExtended.py deleted file mode 100644 index 3227210e5..000000000 --- a/scripts/python-phoniebox/ConfigParserExtended.py +++ /dev/null @@ -1,31 +0,0 @@ -# from configparser import RawConfigParser -import configparser - - -class ConfigParserExtended(configparser.ConfigParser): - - def as_dict(self, section="all"): - if section == "all": - d = self.__dict__['_sections'] - else: - d = self.__dict__['_sections'][section] - return d - - def as_json(self, section="all"): - import json - if section == "all": - d = self.__dict__['_sections'] - else: - d = self.__dict__['_sections'][section] - return json.dumps(d, separators=(',', ':'), indent=4, sort_keys=True, - ensure_ascii=False).encode('utf8') - - def print_ini(self, section="all"): - if section == "all": - sections = self.sections() - else: - sections = [section] - for section_name in sections: - print("[{}]".format(section_name)) - for key, value in self.items(section_name): - print('{} = {}'.format(key, value)) diff --git a/scripts/python-phoniebox/LICENSE b/scripts/python-phoniebox/LICENSE deleted file mode 100644 index e27d99892..000000000 --- a/scripts/python-phoniebox/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 laclaro - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/scripts/python-phoniebox/Phoniebox.py b/scripts/python-phoniebox/Phoniebox.py deleted file mode 100755 index b4f2e2b1a..000000000 --- a/scripts/python-phoniebox/Phoniebox.py +++ /dev/null @@ -1,412 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -__name__ = "Phoniebox" - -import configparser # needed only for the exception types ?! -from ConfigParserExtended import ConfigParserExtended -import codecs -import subprocess # needed for aplay call -import os, sys -from time import sleep -from mpd import MPDClient - -# get absolute path of this script -dir_path = os.path.dirname(os.path.realpath(__file__)) -defaultconfigFilePath = os.path.join(dir_path, './phoniebox.conf') - - -# TODO: externalize helper functions for the package. How? -def is_int(s): - """ return True if string is an int """ - try: - int(s) - return True - except ValueError: - return False - - -def str2bool(s): - """ convert string to a python boolean """ - return s.lower() in ("yes", "true", "t", "1") - - -def str2num(s): - """ convert string to an int or a float """ - try: - return int(s) - except ValueError: - return float(s) - - -def find_modified_files(path, since): - modified_files = [] - for root, dirs, files in os.walk(path): - for basename in files: - filename = os.path.join(path, basename) - status = os.stat(filename) - if status.st_mtime > since: - modified_files.append(filename) - return modified_files - - -def file_modified(filename, since): - if os.stat(filename).st_mtime > since: - return True - else: - return False - - -class Phoniebox(object): - - def __init__(self, configFilePath=defaultconfigFilePath): - print("Using configuration file {}".format(configFilePath)) - self.read_config(configFilePath) - # read cardAssignments from given card assignments file - card_assignments_file = self.get_setting("phoniebox", "card_assignments_file") - self.cardAssignments = self.read_cardAssignments() - if self.get_setting("phoniebox", "translate_legacy_cardassignments", "bool") is True: - self.log("Translating legacy cardAssignment config from folder.conf files.", 3) - legacy_cardAssignments = self.translate_legacy_cardAssignments() - self.update_cardAssignments(legacy_cardAssignments) - - def log(self, msg, level=3): - """ level based logging to stdout """ - log_level_map = {0: None, 1: "error", 2: "warning", 3: "info", 4: "extended", 5: "debug"} - log_level = int(self.get_setting("phoniebox", "log_level")) - if log_level >= level and log_level != -1: - print("{}: {}".format(log_level_map[level].upper(), msg)) - - def mpd_init_connection(self): - """ connect to mpd """ - host = self.get_setting("mpd", "host") - if host == -1: - host = "localhost" - port = self.get_setting("mpd", "port") - if port == -1: - port = 6600 - timeout = self.get_setting("mpd", "timeout") - if timeout == -1: - timeout = 3 - - self.client = MPDClient() - self.client.host = host - self.client.port = port - self.client.timeout = timeout - - # ret = self.mpd_connect_timeout() - if self.mpd_connect_timeout() != 0: - sys.exit() - else: - self.log("connected to MPD with settings host = {}, port = {}, timeout = {}".format(host, port, timeout), 3) - - def mpd_connect_timeout(self): - """ establishes the connection to MPD when disconnected """ - success = False - runtime = 0 - try: - self.client.disconnect() - except: - pass - while success is not True and runtime <= self.client.timeout: - try: - self.client.connect(self.client.host, self.client.port) - success = True - self.log("Connected to MPD at {} on port {}.".format(self.client.host, self.client.port), 5) - return 0 - except: - self.log("Could not connect to MPD, retrying.", 5) - sleep(0.2) - runtime += 0.2 - if runtime >= self.client.timeout: - self.log("Could not connect to MPD for {}s, giving up.".format(self.client.timeout), 2) - return 1 - - def do_second_swipe(self): - """ react to the second swipe of the same card according to settings""" - second_swipe_map = {'default': self.do_restart_playlist, - 'restart': self.do_restart_playlist, - 'restart_track': self.do_restart_track, - 'stop': self.do_stop, - 'pause': self.do_toggle, - 'noaudioplay': self.do_pass, - 'skipnext': self.do_next, - } - setting_key = "second_swipe" - map_key = self.config.get("phoniebox", setting_key) - try: - second_swipe_map[map_key]() - except KeyError as e: - self.log("Unknown setting \"{} = {}\", using \"{} = default\".".format(setting_key, map_key, setting_key), 5) - second_swipe_map['default']() - - def do_restart_playlist(self): - """ restart the same playlist from the beginning """ - # TODO: Any reason not to just start the first item in the current playlist? - self.mpd_connect_timeout() - self.set_mpd_playmode(self.lastplayedID) - self.play_mpd(self.get_cardsetting(self.lastplayedID, "uri")) - - def do_restart_track(self): - """ restart currently playing track """ - self.mpd_connect_timeout() - mpd_status = self.client.status() - self.set_mpd_playmode(self.lastplayedID) - # restart current track - self.client.play(mpd_status['song']) - - def do_start_playlist(self, cardid): - """ restart the same playlist, eventually resume """ - if self.get_cardsetting(self.lastplayedID, "resume"): - self.resume(self.lastplayedID, "save") - self.mpd_connect_timeout() - self.set_mpd_playmode(cardid) - self.play_mpd(self.get_cardsetting(cardid, "uri")) - if self.get_cardsetting(cardid, "resume"): - self.resume(cardid, "resume") - self.lastplayedID = cardid - - def do_toggle(self): - """ toggle play/pause """ - self.mpd_connect_timeout() - status = self.client.status() - if status['state'] == "play": - self.client.pause() - else: - self.client.play() - - def do_pass(self): - """ do nothing (on second swipe with noaudioplay) """ - pass - - def do_next(self): - """ skip to next track or restart playlist if stopped (on second swipe with noaudioplay) """ - self.mpd_connect_timeout() - status = self.client.status() - # start playlist if in stop state or there is only one song in the playlist (virtually loop) - if (status["state"] == "stop") or (status["playlistlength"] == "1"): - self.do_restart_playlist() - else: - self.client.next() - - def do_stop(self): - """ do nothing (on second swipe with noaudioplay) """ - self.mpd_connect_timeout() - self.client.stop() - - def play_alsa(self, audiofile): - """ pause mpd and play file on alsa player """ - self.mpd_connect_timeout() - self.client.pause() - # TODO: use the standard audio device or set them via phoniebox.conf - subprocess.call(["aplay -q -Dsysdefault:CARD=sndrpijustboomd " + audiofile], shell=True) - subprocess.call(["aplay -q -Dsysdefault " + audiofile], shell=True) - - def play_mpd(self, uri): - """ play uri in mpd """ - self.mpd_connect_timeout() - self.client.clear() - self.client.add(uri) - self.client.play() - self.log("phoniebox: playing {}".format(uri.encode('utf-8')), 3) - - # TODO: is there a better way to check for "value not present" than to return -1? - def get_setting(self, section, key, opt_type="string"): - """ get a setting from configFile file or cardAssignmentsFile - if not present, return -1 - """ - try: - num = str2num(section) - parser = self.cardAssignments - except ValueError: - parser = self.config - - try: - opt = parser.get(section, key) - except configparser.NoOptionError: - print("No option {} in section {}".format(key, section)) - return -1 - except configparser.NoSectionError: - print("No section {}".format(section)) - return -1 - if "bool" in opt_type.lower(): - return str2bool(opt) - else: - try: - return str2num(opt) - except ValueError: - return opt - - def get_cardsetting(self, cardid, key, opt_type="string"): - """ catches Errors """ - return self.get_setting(cardid, key, opt_type) - - def mpd_init_settings(self): - """ set initial mpd state: - max_volume - initial_volume """ - mpd_status = self.client.status() - max_volume = self.get_setting("phoniebox", "max_volume") - init_volume = self.get_setting("phoniebox", "init_volume") - if max_volume == -1: - max_volume = 100 # the absolute max_volume is 100% - if init_volume == -1: - init_volume = 0 # to be able to compare - if max_volume < init_volume: - self.log("init_volume cannot exceed max_volume.", 2) - init_volume = max_volume # do not exceed max_volume - if mpd_status["volume"] > max_volume: - self.client.setvol(init_volume) - - def set_mpd_playmode(self, cardid): - """ set playmode in mpd according to card settings """ - playmode_defaults_map = {"repeat": 0, "random": 0, "single": 0, "consume": 0} - set_playmode_map = {"repeat": self.client.repeat, - "random": self.client.random, - "single": self.client.single, - "consume": self.client.consume} - for key in set_playmode_map.keys(): - # option is set if config file contains "option = 1" or just "option" without value. - playmode_setting = self.get_cardsetting(cardid, key) - if playmode_setting == -1 or playmode_setting == 1: - playmode_setting = 1 - else: - playmode_setting = playmode_defaults_map[key] - # set value - set_playmode_map[key](playmode_setting) - self.log("setting mpd {} = {}".format(key, playmode_setting), 5) - - def resume(self, cardid, action="resume"): - """ seek to saved position if resume is activated """ - self.mpd_connect_timeout() - mpd_status = self.client.status() - print(mpd_status) - if action in ["resume", "restore"]: - opt_resume = self.get_cardsetting(cardid, "resume") - if opt_resume == -1 or opt_resume == 1: - resume_elapsed = self.get_cardsetting(cardid, "resume_elapsed") - resume_song = self.get_cardsetting(cardid, "resume_song") - if resume_song == -1: - resume_song = 0 - if resume_elapsed != -1 and resume_elapsed != 0: - self.log("{}: resume song {} at time {}s".format(cardid, - self.get_cardsetting(cardid, "resume_song"), - self.get_cardsetting(cardid, "resume_elapsed")), 5) - self.client.seek(resume_song, resume_elapsed) - elif action in ["save", "store"]: - try: - self.log("{}: save state, song {} at time {}s".format(cardid, - mpd_status["song"], mpd_status["elapsed"]), 5) - self.cardAssignments.set(cardid, "resume_elapsed", - mpd_status["elapsed"]) - self.cardAssignments.set(cardid, "resume_song", - mpd_status["song"]) - except KeyError as e: - print("KeyError: {}".format(e)) - except ValueError as e: - print("ValueError: {}".format(e)) - - def read_cardAssignments(self): - card_assignments_file = self.config.get("phoniebox", "card_assignments_file") - parser = ConfigParserExtended(allow_no_value=True) - dataset = parser.read(card_assignments_file) - if len(dataset) != 1: - raise ValueError("Config file {} not found!".format(card_assignments_file)) - return parser - - def update_cardAssignments(self, static_cardAssignments): - """card_assignments_file = self.config.get("phoniebox","card_assignments_file") - parser = ConfigParserExtended(allow_no_value=True) - dataset = parser.read(card_assignments_file) - if len(dataset) != 1: - raise ValueError("Config file {} not found!".format(card_assignments_file)) - # if cardAssignments is still empty, store new cardAssignments directly - # otherwise compare new values with old values and update only certain values - if hasattr(self, 'cardAssignments'): - self.debug("cardAssignments already set, updating data in memory with new data from file {}".format(card_assignments_file)) - static_cardAssignments = parser""" - self.log("Updating changes in cardAssignments from disk.", 3) - keep_cardsettings = ["resume_song", "resume_elapsed"] - common_sections = list(set(static_cardAssignments.sections()).intersection(self.cardAssignments.sections())) - for section in common_sections: - for option in keep_cardsettings: - if self.cardAssignments.has_option(section, option): - value = self.cardAssignments.get(section, option) - static_cardAssignments.set(section, option, value) - self.log("Updating cardid {} with \"{} = {}\".".format(section, option, value), 5) - # finally assign new values - self.cardAssignments = static_cardAssignments - - def read_config(self, configFilePath=defaultconfigFilePath): - """ read config variables from file """ - configParser = ConfigParserExtended(allow_no_value=True, interpolation=configparser.BasicInterpolation()) - dataset = configParser.read(configFilePath) - if len(dataset) != 1: - raise ValueError("Config file {} not found!".format(configFilePath)) - self.config = configParser - - def translate_legacy_cardAssignments(self, last_translate_legacy_cardAssignments=0): - """ reads the card settings data from the old scheme an translates them """ - shortcuts_path = self.get_setting("phoniebox", "shortcuts_path") - audiofolders_path = self.get_setting("phoniebox", "audiofolders_path") - if shortcuts_path != -1: - configParser = ConfigParserExtended() - shortcut_files = [f for f in os.listdir(shortcuts_path) if os.path.isfile(os.path.join(shortcuts_path, f)) and is_int(f)] - - # filename is the cardid - for filename in shortcut_files: - with open(os.path.join(shortcuts_path, filename)) as f: - uri = f.readline().strip().decode('utf-8') - - # add default settings - if filename not in configParser.sections(): - self.log("Adding section {} to cardAssignments".format(filename), 5) - configParser.add_section(filename) - configParser[filename] = self.config["default_cardsettings"] - configParser.set(filename, "cardid", filename) - configParser.set(filename, "uri", uri) - # translate and add folder.conf settings if they contradict default_cardsettings - cardsettings_map = {"CURRENTFILENAME": None, - "ELAPSED": "resume_elapsed", - "PLAYSTATUS": None, - "RESUME": "resume", - "SHUFFLE": "random", - "LOOP": "repeat"} - folderconf = os.path.join(audiofolders_path, uri, "folder.conf") - if os.path.isfile(folderconf) and file_modified(folderconf, last_translate_legacy_cardAssignments): - with open(folderconf) as f: - lines = f.readlines() - cardsettings_old = dict([l.strip().replace('"', '').split("=") for l in lines]) - for key in cardsettings_old.keys(): - if cardsettings_map[key] is not None: - # ignore 0 and OFF values, drop settings that have None in cardsettings_map - if key != "ELAPSED": - if cardsettings_old[key] != "0" and cardsettings_old[key] != "OFF": - configParser.set(filename, cardsettings_map[key], "1") - else: - configParser.set(filename, cardsettings_map[key], "0") - else: - try: - elapsed_val = float(cardsettings_old[key]) - except ValueError: - elaped_val = 0 - configParser.set(filename, cardsettings_map[key], str(elapsed_val)) - return configParser - - def write_new_cardAssignments(self): - """ updates the cardsettings with according to playstate """ - card_assignments_file = self.config.get("phoniebox", "card_assignments_file") - self.log("Write new card assignments to file {}.".format(card_assignments_file), 3) - with codecs.open(card_assignments_file, 'w', 'utf-8') as f: - self.cardAssignments.write(f) - - def print_to_file(self, filename, string): - """ simple function to write a string to a file """ - with codecs.open(filename, 'w', 'utf-8') as f: - f.write(string) - - -if __name__ == "__main__": - print("This module is not to be run! Use \"from Phoniebox import Phoniebox\" instead!") -else: - print("Phoniebox imported. Use \"box = Phoniebox(configFile)\" to get it working.") diff --git a/scripts/python-phoniebox/PhonieboxConfigChanger.py b/scripts/python-phoniebox/PhonieboxConfigChanger.py deleted file mode 100755 index 4c3c9bd46..000000000 --- a/scripts/python-phoniebox/PhonieboxConfigChanger.py +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -# import json -import os, sys, signal -# from mpd import MPDClient -import configparser -# from RawConfigParserExtended import RawConfigParserExtended -from Phoniebox import Phoniebox - -# get absolute path of this script -dir_path = os.path.dirname(os.path.realpath(__file__)) -defaultconfigFilePath = os.path.join(dir_path, './phoniebox.conf') - - -def is_int(s): - """ return True if string is an int """ - try: - int(s) - return True - except ValueError: - return False - - -def str2bool(s): - """ convert string to a python boolean """ - return s.lower() in ("yes", "true", "t", "1") - - -def str2num(s): - """ convert string to an int or a float """ - try: - return int(s) - except ValueError: - return float(s) - - -class PhonieboxConfigChanger(Phoniebox): - - def __init__(self, configFilePath=defaultconfigFilePath): - Phoniebox.__init__(self, configFilePath) - - def assigncard(self, cardid, uri): - section = cardid - # set uri and cardid for card (section = cardid) - if not section in self.cardAssignments.sections(): - self.cardAssignments.add_section(section) - self.cardAssignments.set(section, "cardid", cardid) - self.cardAssignments.set(section, "uri", uri) - # write updated assignments to file - with open(self.config['card_assignments_file'], 'w') as cardAssignmentsFile: - self.cardAssignments.write(cardAssignmentsFile) - - def removecard(self, cardid): - section = cardid - if section in self.cardAssignments.sections(): - self.cardAssignments.remove_section(section) - # write updated assignments to file - with open(self.config['card_assignments_file'], 'w') as f: - self.cardAssignments.write(f) - - def set(self, section, key, value): - try: - num = int(section) - parser = self.cardAssignments - config_file = self.config.get("phoniebox", "card_assignments_file") - except ValueError: - parser = self.config - # update value - try: - parser.set(section, key, value) - self.debug("Set {} = {} in section {}".format(key, value, section)) - except configparser.NoSectionError as e: - raise e - - def get(self, section, t="ini"): - try: - num = int(section) - parser = self.cardAssignments - except ValueError: - parser = self.config - - if t == "json": - print(parser.as_json(section)) - elif t == "dict": - print(parser.as_dict(section)) - else: - print(parser.print_ini(section)) - - def print_usage(self): - print("Usage: {} set ".format(sys.argv[0])) - - -def main(self): - - cmdlist = ["assigncard", "removecard", "set", "get"] - - if len(sys.argv) < 1: - sys.exit() - else: - if sys.argv[1] in cmdlist: - configFilePath = defaultconfigFilePath - cmd = sys.argv[1] - shift = 0 - else: - configFilePath = sys.argv[1] - cmd = sys.argv[2] - shift = 1 - - ConfigChanger = PhonieboxConfigChanger(configFilePath) - try: - if cmd == "assigncard": - cardid = sys.argv[2+shift] - uri = sys.argv[3+shift] - ConfigChanger.assigncard(cardid, uri) - elif cmd == "removecard": - cardid = sys.argv[2+shift] - ConfigChanger.removecard(cardid) - elif cmd == "set": - section = sys.argv[2+shift] - key = sys.argv[3+shift] - value = sys.argv[4+shift] - ConfigChanger.set(section, key, value) - elif cmd == "get": - section = sys.argv[2+shift] - try: - t = sys.argv[3+shift] - except: - t = "ini" - ConfigChanger.get(section, t) - else: - # will never be reached - print("supported commands are {} and {}".format(", ".join(cmdlist[:-1]), cmdlist[-1])) - except: - self.print_usage() - - -if __name__ == "__main__": - main() diff --git a/scripts/python-phoniebox/PhonieboxDaemon.py b/scripts/python-phoniebox/PhonieboxDaemon.py deleted file mode 100755 index a5739bbe0..000000000 --- a/scripts/python-phoniebox/PhonieboxDaemon.py +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -# import threading -import sys, os.path -import signal -from Phoniebox import Phoniebox -from time import sleep, time - -# get absolute path of this script -dir_path = os.path.dirname(os.path.realpath(__file__)) -defaultconfigFilePath = os.path.join(dir_path, 'phoniebox.conf') - -# watchdog blocks the script, so it cannot be used in the same file as the PhonieboxDaemon -# from watchdog.observers import Observer -# from watchdog.events import FileSystemEventHandler -# from os.path import dirname - -# class FileModifiedHandler(FileSystemEventHandler): - -# """ watch the given file for changes and execute callback function on modification """ -# def __init__(self, file_path, callback): -# self.file_path = file_path -# self.callback = callback - -# # set observer to watch for changes in the directory -# self.observer = Observer() -# self.observer.schedule(self, dirname(file_path), recursive=False) -# self.observer.start() -# try: -# while True: -# sleep(1) -# except KeyboardInterrupt: -# self.observer.stop() -# self.observer.join() -# -# def on_modified(self, event): -# # only act on the change that we're looking for -# if not event.is_directory and event.src_path.endswith(self.file_path): -# daemon.log("cardAssignmentsFile modified!",3) -# self.callback() # call callback - - -class PhonieboxDaemon(Phoniebox): - """ This subclass of Phoniebox is to be called directly, running as RFID reader daemon """ - - def __init__(self, configFilePath=defaultconfigFilePath): - Phoniebox.__init__(self, configFilePath) - self.lastplayedID = 0 - - def run(self): - # do things if killed - signal.signal(signal.SIGINT, self.signal_handler) - signal.signal(signal.SIGTERM, self.signal_handler) - - # establish mpd connection - self.mpd_init_connection() - self.mpd_init_settings() - state = self.client.status()["state"] - - daemon.play_alsa(daemon.get_setting("phoniebox", 'startup_sound')) - if state == "play": - self.client.play() - - # launch watcher for config files, blocks the script - # TODO: it would be better to watch the changes with a second process that - # tells the PhonieboxDaemon to reload the config whenever needed. - - # card_assignments_file = daemon.get_setting("phoniebox","card_assignments_file") - # cardAssignmentsWatchdog = FileModifiedHandler(card_assignments_file, self.update_cardAssignments) - # ConfigWatchdog = FileModifiedHandler(configFilePath, self.read_config) - -# # start_reader runs an endless loop, nothing will be executed afterwards - daemon.start_reader() - - def start_reader(self): - from Reader import Reader - reader = Reader() - - card_detection_sound = self.get_setting("phoniebox", "card_detection_sound") - debounce_time = self.get_setting("phoniebox", "debounce_time") - if debounce_time == -1: - debounce_time = 0.5 - second_swipe_delay = self.get_setting("phoniebox", "second_swipe_delay") - if second_swipe_delay == -1: - second_swipe_delay = 0 - store_card_assignments = self.get_setting("phoniebox", "store_card_assignments") - if store_card_assignments == -1: - store_card_assignments = 30 - last_swipe = 0 - last_write_card_assignments = 0 - - while True: - # reading the card id - cardid = reader.reader.readCard() -# cardid = None -# sleep(debounce_time) - try: - # start the player script and pass on the cardid - if cardid is not None: - print("Card ID: {}".format(int(cardid))) - filename = self.get_setting("phoniebox", "Latest_RFID_file") - if filename != -1: - self.print_to_file(filename, "\'{}\' was used at {}".format(cardid, time())) - if card_detection_sound != -1: - self.play_alsa(card_detection_sound) - if cardid in self.cardAssignments.sections(): - # second swipe detection - if int(cardid) == int(self.lastplayedID) and time()-last_swipe > second_swipe_delay: - self.log("Second swipe for {}".format(cardid), 3) - self.do_second_swipe() - # if first swipe, just play - else: - last_swipe = time() - self.do_start_playlist(cardid) - # do not react for debounce_time - sleep(debounce_time) - else: - self.log("Card with ID {} not mapped yet.".format(cardid), 1) - - except OSError as e: - print("Execution failed:", e) - - # check if it is time for the next update of the cardAssignments and do it - # Note: this is purely time-based and not clever at all. Find a - # TODO: find a better way to check for changes in the files on disk to trigger the update - if time()-last_write_card_assignments > store_card_assignments and store_card_assignments != False: - # store card assignments - if self.get_setting("phoniebox", "translate_legacy_cardassignments", "bool") == True: - legacy_cardAssignments = self.translate_legacy_cardAssignments(last_write_card_assignments) - self.update_cardAssignments(legacy_cardAssignments) - else: - self.update_cardAssignments(self.read_cardAssignments) - - self.write_new_cardAssignments() - last_write_card_assignments = time() - - def signal_handler(self, signal, frame): - """ catches signal and triggers the graceful exit """ - print("Caught signal {}, exiting...".format(signal)) - self.exit_gracefully() - - def exit_gracefully(self): - """ stop mpd and write cardAssignments to disk if daemon is stopped """ - self.mpd_connect_timeout() - self.client.stop() - self.client.disconnect() - # write config to update playstate - self.write_new_cardAssignments() - - # exit script - sys.exit(0) - - -if __name__ == "__main__": - - # if called directly, launch Phoniebox.py as rfid-reader daemon - # treat the first argument as defaultconfigFilePath if given - if len(sys.argv) <= 1: - configFilePath = defaultconfigFilePath - else: - configFilePath = sys.argv[1] - - daemon = PhonieboxDaemon(configFilePath) - - # setup the signal listeners - signal.signal(signal.SIGINT, daemon.exit_gracefully) - signal.signal(signal.SIGTERM, daemon.exit_gracefully) - - # start the daemon (blocking) - daemon.run() diff --git a/scripts/python-phoniebox/README.md b/scripts/python-phoniebox/README.md deleted file mode 100644 index 35d1242d2..000000000 --- a/scripts/python-phoniebox/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# python-phoniebox -python daemon to be used with the RPi-Jukebox-RFID by MiczFlor - -https://github.com/MiczFlor/RPi-Jukebox-RFID - - Make sure to edit the defaultconfigFilePath in the file Phoniebox.py to match the path of the phoniebox.conf file. diff --git a/scripts/python-phoniebox/RawConfigParserExtended.py b/scripts/python-phoniebox/RawConfigParserExtended.py deleted file mode 100755 index 49cd28ff9..000000000 --- a/scripts/python-phoniebox/RawConfigParserExtended.py +++ /dev/null @@ -1,31 +0,0 @@ -# from configparser import RawConfigParser -import configparser - - -class RawConfigParserExtended(configparser.RawConfigParser): - - def as_dict(self, section="all"): - if section == "all": - d = self.__dict__['_sections'] - else: - d = self.__dict__['_sections'][section] - return d - - def as_json(self, section="all"): - import json - if section == "all": - d = self.__dict__['_sections'] - else: - d = self.__dict__['_sections'][section] - return json.dumps(d, separators=(',', ':'), indent=4, sort_keys=True, - ensure_ascii=False).encode('utf8') - - def print_ini(self, section="all"): - if section == "all": - sections = self.sections() - else: - sections = [section] - for section_name in sections: - print("[{}]".format(section_name)) - for key, value in self.items(section_name): - print('{} = {}'.format(key, value)) diff --git a/scripts/python-phoniebox/Reader.py b/scripts/python-phoniebox/Reader.py deleted file mode 100755 index 927912f8f..000000000 --- a/scripts/python-phoniebox/Reader.py +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env python3 -# This alternative Reader.py script was meant to cover not only USB readers but more. -# It can be used to replace Reader.py if you have readers such as -# MFRC522 or RDM6300. -# Please use the github issue threads to share bugs and improvements -# or create pull requests. - -import os.path -import sys -import serial -import string -import RPi.GPIO as GPIO - -from evdev import InputDevice, categorize, ecodes, list_devices -import pirc522 - - -def get_devices(): - devices = [InputDevice(fn) for fn in list_devices()] - devices.append(NonUsbDevice('MFRC522')) - devices.append(NonUsbDevice('RDM6300')) - return devices - - -class NonUsbDevice(object): - name = None - - def __init__(self, name): - self.name = name - - -class UsbReader(object): - def __init__(self, device): - self.keys = "X^1234567890XXXXqwertzuiopXXXXasdfghjklXXXXXyxcvbnmXXXXXXXXXXXXXXXXXXXXXXX" - self.dev = device - - def readCard(self): - from select import select - stri = '' - key = '' - while key != 'KEY_ENTER': - select([self.dev], [], []) - for event in self.dev.read(): - if event.type == 1 and event.value == 1: - stri += self.keys[event.code] - key = ecodes.KEY[event.code] - return stri[:-1] - - -class Mfrc522Reader(object): - def __init__(self): - self.device = pirc522.RFID() - - def readCard(self): - # Scan for cards - self.device.wait_for_tag() - (error, tag_type) = self.device.request() - - if not error: - print("Card detected.") - # Perform anti-collision detection to find card uid - (error, uid) = self.device.anticoll() - if not error: - return ''.join((str(x) for x in uid)) - - print("No Device ID found.") - return None - - @staticmethod - def cleanup(): - GPIO.cleanup() - - -class Rdm6300Reader: - def __init__(self): - device = '/dev/ttyS0' - baudrate = 9600 - ser_timeout = 0.1 - self.last_card_id = '' - try: - self.rfid_serial = serial.Serial(device, baudrate, timeout=ser_timeout) - except serial.SerialException as e: - print(e) - exit(1) - - def readCard(self): - byte_card_id = b'' - - try: - while True: - try: - read_byte = self.rfid_serial.read() - - if read_byte == b'\x02': # start byte - while read_byte != b'\x03': # end bye - read_byte = self.rfid_serial.read() - byte_card_id += read_byte - - card_id = byte_card_id.decode('utf-8') - byte_card_id = '' - card_id = ''.join(x for x in card_id if x in string.printable) - - # Only return UUIDs with correct length - if len(card_id) == 12 and card_id != self.last_card_id: - self.last_card_id = card_id - self.rfid_serial.reset_input_buffer() - return self.last_card_id - - else: # wrong UUID length or already send that UUID last time - self.rfid_serial.reset_input_buffer() - - except ValueError as ve: - print(ve) - - except serial.SerialException as se: - print(se) - - def cleanup(self): - self.rfid_serial.close() - - -class Reader(object): - def __init__(self): - path = os.path.dirname(os.path.realpath(__file__)) - if not os.path.isfile(path + '/deviceName.txt'): - sys.exit('Please run RegisterDevice.py first') - else: - with open(path + '/deviceName.txt', 'r') as f: - device_name = f.read() - - if device_name == 'MFRC522': - self.reader = Mfrc522Reader() - elif device_name == 'RDM6300': - self.reader = Rdm6300Reader() - else: - try: - device = [device for device in get_devices() if device.name == device_name][0] - self.reader = UsbReader(device) - except IndexError: - sys.exit('Could not find the device %s.\n Make sure it is connected' % device_name) diff --git a/scripts/python-phoniebox/__init__.py b/scripts/python-phoniebox/__init__.py deleted file mode 100755 index e69de29bb..000000000 diff --git a/scripts/python-phoniebox/deviceName.txt b/scripts/python-phoniebox/deviceName.txt deleted file mode 100755 index a404db7da..000000000 --- a/scripts/python-phoniebox/deviceName.txt +++ /dev/null @@ -1 +0,0 @@ -MFRC522 \ No newline at end of file diff --git a/scripts/python-phoniebox/helpers_unused_atm/__init__.py b/scripts/python-phoniebox/helpers_unused_atm/__init__.py deleted file mode 100755 index e69de29bb..000000000 diff --git a/scripts/python-phoniebox/helpers_unused_atm/helpers.py b/scripts/python-phoniebox/helpers_unused_atm/helpers.py deleted file mode 100755 index 68aef4b68..000000000 --- a/scripts/python-phoniebox/helpers_unused_atm/helpers.py +++ /dev/null @@ -1,23 +0,0 @@ -__name__ = "helpers" - - -def is_int(s): - """ return True if string is an int """ - try: - int(s) - return True - except ValueError: - return False - - -def str2bool(s): - """ convert string to a python boolean """ - return s.lower() in ("yes", "true", "t", "1") - - -def str2num(s): - """ convert string to an int or a float """ - try: - return int(s) - except ValueError: - return float(s) diff --git a/scripts/python-phoniebox/phoniebox.conf b/scripts/python-phoniebox/phoniebox.conf deleted file mode 100755 index d52c9fdbf..000000000 --- a/scripts/python-phoniebox/phoniebox.conf +++ /dev/null @@ -1,62 +0,0 @@ -[phoniebox] -# log level -# 0: no output -# 1: error -# 2: warning -# 3: info (default) -# 4: not used -# 5: debug -log_level = 3 - -# time in seconds to pause detection after swipe (default: 0.5) -debounce_time = 0.5 - -# setup directories -base_path = /home/pi/RPi-Jukebox-RFID/ -audiofolders_path = %(base_path)s/shared/audiofolders -card_assignments_file = %(base_path)s/settings/Card_Assignments.txt -# card detection sound will be played on swipe by aplay (default: none) -card_detection_sound = %(base_path)s/shared/card_detection_sound.wav -# PhonieboxDaemon startup sound will be played by aplay (default: none) -startup_sound = %(base_path)s/shared/startupsound.wav - -# file to log detected card IDs. Required for web interface -Latest_RFID_file = %(base_path)s/shared/latestID.txt - -# use the old-style folder.conf files as card-assignments -# which enables sticking to the legacy-web interface -# resume-settings are not imported, but kept up-to-date by PhonieboxDaemon -translate_legacy_cardassignments = 1 -# the legacy shortcut files are only used to find the legacy cardassignments -shortcuts_path = %(base_path)s/shared/shortcuts/ - -# store card assignments and resume data regularly on disk (default: 30) -store_card_assignments = 30 - -# action for second swipe of the same RFID card. Possible values: -# restart (default), restart_track, stop, pause, skipnext or next, noaudioplay -# note that the combination of "second_swipe = restart" for an RFID card -# with random in the cardsettings behaves similar to "skipnext" with random enabled. -second_swipe = skipnext -# seconds to wait until second swipe is possible (default: 0) -second_swipe_delay = 0 - -# volume settings -init_volume = 65 -max_volume = 80 -# only used by rotary_volume.py -volume_step = 2 - -[mpd] -# mpd connection settings (default: localhost:6600) -host = localhost -port = 6600 -timeout = 5 - -[default_cardsettings] -# default settings for newly registered or translated RFID cards -repeat = 0 -resume = 1 -random = 1 -single = 0 -consume = 0 diff --git a/scripts/rfid_trigger_play.sh b/scripts/rfid_trigger_play.sh index b1bc08ede..5c443d83d 100755 --- a/scripts/rfid_trigger_play.sh +++ b/scripts/rfid_trigger_play.sh @@ -63,6 +63,14 @@ fi # see following file for details: . $PATHDATA/inc.readArgsFromCommandLine.sh +####################### +# Activation status of component sync-shared-from-server +SYNCSHAREDENABLED="FALSE" +if [ -f $PATHDATA/../settings/sync-shared-enabled ]; then + SYNCSHAREDENABLED=`cat $PATHDATA/../settings/sync-shared-enabled` +fi +if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "Sync: SYNCSHAREDENABLED=$SYNCSHAREDENABLED" >> $PATHDATA/../logs/debug.log; fi + ################################################################## # Check if we got the card ID or the audio folder from the prompt. # Sloppy error check, because we assume the best. @@ -238,6 +246,18 @@ if [ "$CARDID" ]; then # stop player after -v minutes $PATHDATA/playout_controls.sh -c=playerstopafter -v=60 ;; + $STOPAFTER120) + # stop player after -v minutes + $PATHDATA/playout_controls.sh -c=playerstopafter -v=120 + ;; + $STOPAFTER180) + # stop player after -v minutes + $PATHDATA/playout_controls.sh -c=playerstopafter -v=180 + ;; + $STOPAFTER240) + # stop player after -v minutes + $PATHDATA/playout_controls.sh -c=playerstopafter -v=240 + ;; $SHUTDOWNAFTER5) # shutdown after -v minutes $PATHDATA/playout_controls.sh -c=shutdownafter -v=5 @@ -253,6 +273,18 @@ if [ "$CARDID" ]; then $SHUTDOWNAFTER60) # shutdown after -v minutes $PATHDATA/playout_controls.sh -c=shutdownafter -v=60 + ;; + $SHUTDOWNAFTER120) + # shutdown after -v minutes + $PATHDATA/playout_controls.sh -c=shutdownafter -v=120 + ;; + $SHUTDOWNAFTER180) + # shutdown after -v minutes + $PATHDATA/playout_controls.sh -c=shutdownafter -v=180 + ;; + $SHUTDOWNAFTER240) + # shutdown after -v minutes + $PATHDATA/playout_controls.sh -c=shutdownafter -v=240 ;; $SHUTDOWNVOLUMEREDUCTION10) # reduce volume until shutdown in -v minutes @@ -270,6 +302,18 @@ if [ "$CARDID" ]; then # reduce volume until shutdown in -v minutes $PATHDATA/playout_controls.sh -c=shutdownvolumereduction -v=60 ;; + $SHUTDOWNVOLUMEREDUCTION120) + # reduce volume until shutdown in -v minutes + $PATHDATA/playout_controls.sh -c=shutdownvolumereduction -v=120 + ;; + $SHUTDOWNVOLUMEREDUCTION180) + # reduce volume until shutdown in -v minutes + $PATHDATA/playout_controls.sh -c=shutdownvolumereduction -v=180 + ;; + $SHUTDOWNVOLUMEREDUCTION240) + # reduce volume until shutdown in -v minutes + $PATHDATA/playout_controls.sh -c=shutdownvolumereduction -v=240 + ;; $ENABLEWIFI) $PATHDATA/playout_controls.sh -c=enablewifi ;; @@ -306,12 +350,23 @@ if [ "$CARDID" ]; then $CMDBLUETOOTHTOGGLE) $PATHDATA/playout_controls.sh -c=bluetoothtoggle -v=toggle ;; + $SYNCSHAREDFULL) + $PATHDATA/playout_controls.sh -c=sharedsyncfull + ;; + $SYNCSHAREDONRFIDSCANTOGGLE) + $PATHDATA/playout_controls.sh -c=sharedsyncchangeonrfidscan -v=toggle + ;; *) # We checked if the card was a special command, seems it wasn't. # Now we expect it to be a trigger for one or more audio file(s). # Let's look at the ID, write a bit of log information and then try to play audio. + # If enabled sync shortcut $CARDID + if [ "${SYNCSHAREDENABLED}" == "TRUE" ]; then + $PATHDATA/../components/synchronisation/sync-shared/sync-shared.sh -c=shortcuts -i="$CARDID" + fi + # Look for human readable shortcut in folder 'shortcuts' # check if CARDID has a text file by the same name - which would contain the human readable folder name if [ -f $PATHDATA/../shared/shortcuts/$CARDID ] @@ -345,174 +400,179 @@ fi if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "# Attempting to play: $AUDIOFOLDERSPATH/$FOLDER" >> $PATHDATA/../logs/debug.log; fi if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "# Type of play \$VALUE: $VALUE" >> $PATHDATA/../logs/debug.log; fi -# check if -# - $FOLDER is not empty (! -z "$FOLDER") -# - AND (-a) -# - $FOLDER is set (! -z ${FOLDER+x}) -# - AND (-a) -# - and points to existing directory (-d "${AUDIOFOLDERSPATH}/${FOLDER}") -if [ ! -z "$FOLDER" -a ! -z ${FOLDER+x} -a -d "${AUDIOFOLDERSPATH}/${FOLDER}" ]; then - - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "\$FOLDER set, not empty and dir exists: ${AUDIOFOLDERSPATH}/${FOLDER}" >> $PATHDATA/../logs/debug.log; fi - - # if we play a folder the first time, add some sensible information to the folder.conf - if [ ! -f "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" ]; then - # now we create a default folder.conf file by calling this script - # with the command param createDefaultFolderConf - # (see script for details) - # the $FOLDER would not need to be passed on, because it is already set in this script - # see inc.writeFolderConfig.sh for details - . $PATHDATA/inc.writeFolderConfig.sh -c=createDefaultFolderConf -d="${FOLDER}" - fi +# check if $FOLDER is not empty +if [ ! -z "$FOLDER" ]; then - # get the name of the last folder played. As mpd doesn't store the name of the last - # playlist, we have to keep track of it via the Latest_Folder_Played file - LASTFOLDER=$(cat $PATHDATA/../settings/Latest_Folder_Played) - LASTPLAYLIST=$(cat $PATHDATA/../settings/Latest_Playlist_Played) - # this might need to go? resume not working... echo ${FOLDER} > $PATHDATA/../settings/Latest_Folder_Played - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Var \$LASTFOLDER: $LASTFOLDER" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Var \$LASTPLAYLIST: $LASTPLAYLIST" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "Checking 'recursive' list? VAR \$VALUE: $VALUE" >> $PATHDATA/../logs/debug.log; fi - - if [ "$VALUE" == "recursive" ]; then - # set path to playlist - # replace subfolder slashes with " % " - PLAYLISTPATH="${PLAYLISTSFOLDERPATH}/${FOLDER//\//\ %\ }-%RCRSV%.m3u" - PLAYLISTNAME="${FOLDER//\//\ %\ }-%RCRSV%" - $PATHDATA/playlist_recursive_by_folder.php --folder "${FOLDER}" --list 'recursive' > "${PLAYLISTPATH}" - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "recursive? YES" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "$PATHDATA/playlist_recursive_by_folder.php --folder \"${FOLDER}\" --list 'recursive' > \"${PLAYLISTPATH}\"" >> $PATHDATA/../logs/debug.log; fi - else - # set path to playlist - # replace subfolder slashes with " % " - PLAYLISTPATH="${PLAYLISTSFOLDERPATH}/${FOLDER//\//\ %\ }.m3u" - PLAYLISTNAME="${FOLDER//\//\ %\ }" - $PATHDATA/playlist_recursive_by_folder.php --folder "${FOLDER}" > "${PLAYLISTPATH}" - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "recursive? NO" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "$PATHDATA/playlist_recursive_by_folder.php --folder \"${FOLDER}\" > \"${PLAYLISTPATH}\"" >> $PATHDATA/../logs/debug.log; fi + # If enabled sync audio folder $FOLDER + if [ "${SYNCSHAREDENABLED}" == "TRUE" ]; then + $PATHDATA/../components/synchronisation/sync-shared/sync-shared.sh -c=audiofolders -d="$FOLDER" fi - # Second Swipe value - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Var \$SECONDSWIPE: ${SECONDSWIPE}" >> $PATHDATA/../logs/debug.log; fi - # Playlist name - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Var \$PLAYLISTNAME: ${PLAYLISTNAME}" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Var \$LASTPLAYLIST: ${LASTPLAYLIST}" >> $PATHDATA/../logs/debug.log; fi - - # Setting a VAR to start "play playlist from start" - # This will be changed in the following checks "if this is the second swipe" - PLAYPLAYLIST=yes - - # Check if the second swipe happened - # - The same playlist is cued up ("$LASTPLAYLIST" == "$PLAYLISTNAME") - if [ "$LASTPLAYLIST" == "$PLAYLISTNAME" ] - then - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Second Swipe DID happen: \$LASTPLAYLIST == \$PLAYLISTNAME" >> $PATHDATA/../logs/debug.log; fi - - # check if - # - $SECONDSWIPE is set to toggle pause/play ("$SECONDSWIPE" == "PAUSE") - # - AND (-a) - # - check the length of the playlist, if =0 then it was cleared before, a state, which should only - # be possible after a reboot ($PLLENGTH -gt 0) - PLLENGTH=$(echo -e "status\nclose" | nc -w 1 localhost 6600 | grep -o -P '(?<=playlistlength: ).*') - if [ $PLLENGTH -eq 0 ] - then - # after a reboot we want to play the playlist once no matter what the setting is - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Take second wipe as first after fresh boot" >> $PATHDATA/../logs/debug.log; fi - elif [ "$SECONDSWIPE" == "PAUSE" -a $PLLENGTH -gt 0 ] - then - # The following involves NOT playing the playlist, so we set: - PLAYPLAYLIST=no + # check if $FOLDER points to existing directory + if [ -d "${AUDIOFOLDERSPATH}/${FOLDER}" ]; then + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "\$FOLDER not empty and dir exists: ${AUDIOFOLDERSPATH}/${FOLDER}" >> $PATHDATA/../logs/debug.log; fi + + # if we play a folder the first time, add some sensible information to the folder.conf + if [ ! -f "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" ]; then + # now we create a default folder.conf file by calling this script + # with the command param createDefaultFolderConf + # (see script for details) + # the $FOLDER would not need to be passed on, because it is already set in this script + # see inc.writeFolderConfig.sh for details + . $PATHDATA/inc.writeFolderConfig.sh -c=createDefaultFolderConf -d="${FOLDER}" + fi + + # get the name of the last folder played. As mpd doesn't store the name of the last + # playlist, we have to keep track of it via the Latest_Folder_Played file + LASTFOLDER=$(cat $PATHDATA/../settings/Latest_Folder_Played) + LASTPLAYLIST=$(cat $PATHDATA/../settings/Latest_Playlist_Played) + # this might need to go? resume not working... echo ${FOLDER} > $PATHDATA/../settings/Latest_Folder_Played + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Var \$LASTFOLDER: $LASTFOLDER" >> $PATHDATA/../logs/debug.log; fi + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Var \$LASTPLAYLIST: $LASTPLAYLIST" >> $PATHDATA/../logs/debug.log; fi + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "Checking 'recursive' list? VAR \$VALUE: $VALUE" >> $PATHDATA/../logs/debug.log; fi + + if [ "$VALUE" == "recursive" ]; then + # set path to playlist + # replace subfolder slashes with " % " + PLAYLISTPATH="${PLAYLISTSFOLDERPATH}/${FOLDER//\//\ %\ }-%RCRSV%.m3u" + PLAYLISTNAME="${FOLDER//\//\ %\ }-%RCRSV%" + $PATHDATA/playlist_recursive_by_folder.php --folder "${FOLDER}" --list 'recursive' > "${PLAYLISTPATH}" + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "recursive? YES" >> $PATHDATA/../logs/debug.log; fi + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "$PATHDATA/playlist_recursive_by_folder.php --folder \"${FOLDER}\" --list 'recursive' > \"${PLAYLISTPATH}\"" >> $PATHDATA/../logs/debug.log; fi + else + # set path to playlist + # replace subfolder slashes with " % " + PLAYLISTPATH="${PLAYLISTSFOLDERPATH}/${FOLDER//\//\ %\ }.m3u" + PLAYLISTNAME="${FOLDER//\//\ %\ }" + $PATHDATA/playlist_recursive_by_folder.php --folder "${FOLDER}" > "${PLAYLISTPATH}" + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "recursive? NO" >> $PATHDATA/../logs/debug.log; fi + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "$PATHDATA/playlist_recursive_by_folder.php --folder \"${FOLDER}\" > \"${PLAYLISTPATH}\"" >> $PATHDATA/../logs/debug.log; fi + fi + + # Second Swipe value + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Var \$SECONDSWIPE: ${SECONDSWIPE}" >> $PATHDATA/../logs/debug.log; fi + # Playlist name + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Var \$PLAYLISTNAME: ${PLAYLISTNAME}" >> $PATHDATA/../logs/debug.log; fi + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Var \$LASTPLAYLIST: ${LASTPLAYLIST}" >> $PATHDATA/../logs/debug.log; fi + + # Setting a VAR to start "play playlist from start" + # This will be changed in the following checks "if this is the second swipe" + PLAYPLAYLIST=yes - STATE=$(echo -e "status\nclose" | nc -w 1 localhost 6600 | grep -o -P '(?<=state: ).*') - if [ $STATE == "play" ] + # Check if the second swipe happened + # - The same playlist is cued up ("$LASTPLAYLIST" == "$PLAYLISTNAME") + if [ "$LASTPLAYLIST" == "$PLAYLISTNAME" ] + then + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Second Swipe DID happen: \$LASTPLAYLIST == \$PLAYLISTNAME" >> $PATHDATA/../logs/debug.log; fi + + # check if + # - $SECONDSWIPE is set to toggle pause/play ("$SECONDSWIPE" == "PAUSE") + # - AND (-a) + # - check the length of the playlist, if =0 then it was cleared before, a state, which should only + # be possible after a reboot ($PLLENGTH -gt 0) + PLLENGTH=$(echo -e "status\nclose" | nc -w 1 localhost 6600 | grep -o -P '(?<=playlistlength: ).*') + if [ $PLLENGTH -eq 0 ] then - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " MPD playing, pausing the player" >> $PATHDATA/../logs/debug.log; fi - sudo $PATHDATA/playout_controls.sh -c=playerpause &>/dev/null - else - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "MPD not playing, start playing" >> $PATHDATA/../logs/debug.log; fi + # after a reboot we want to play the playlist once no matter what the setting is + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Take second wipe as first after fresh boot" >> $PATHDATA/../logs/debug.log; fi + elif [ "$SECONDSWIPE" == "PAUSE" -a $PLLENGTH -gt 0 ] + then + # The following involves NOT playing the playlist, so we set: + PLAYPLAYLIST=no + + STATE=$(echo -e "status\nclose" | nc -w 1 localhost 6600 | grep -o -P '(?<=state: ).*') + if [ $STATE == "play" ] + then + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " MPD playing, pausing the player" >> $PATHDATA/../logs/debug.log; fi + sudo $PATHDATA/playout_controls.sh -c=playerpause &>/dev/null + else + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "MPD not playing, start playing" >> $PATHDATA/../logs/debug.log; fi + sudo $PATHDATA/playout_controls.sh -c=playerplay &>/dev/null + fi + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Completed: toggle pause/play" >> $PATHDATA/../logs/debug.log; fi + elif [ "$SECONDSWIPE" == "PLAY" -a $PLLENGTH -gt 0 ] + then + # The following involves NOT playing the playlist, so we set: + PLAYPLAYLIST=no sudo $PATHDATA/playout_controls.sh -c=playerplay &>/dev/null + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Completed: Resume playback" >> $PATHDATA/../logs/debug.log; fi + elif [ "$SECONDSWIPE" == "NOAUDIOPLAY" ] + then + # The following involves NOT playing the playlist, so we set: + PLAYPLAYLIST=no + # following needs testing (see https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/914) + # Special case for NOAUDIOPLAY because once the playlist has finished, + # it needs to be noted by the system that the second swipe is like a *first* swipe. + currentSong=`mpc current` + if [[ -z "$currentSong" ]]; then + #end of playlist (EOPL) reached. Ignore last played playlist + PLAYPLAYLIST=yes + fi + + # "$SECONDSWIPE" == "NOAUDIOPLAY" + # "$LASTPLAYLIST" == "$PLAYLISTNAME" => same playlist triggered again + # => do nothing + # echo "do nothing" > /dev/null 2>&1 + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Completed: do nothing" >> $PATHDATA/../logs/debug.log; fi + elif [ "$SECONDSWIPE" == "SKIPNEXT" ] + then + # We will not play the playlist but skip to the next track: + PLAYPLAYLIST=skipnext + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Completed: skip next track" >> $PATHDATA/../logs/debug.log; fi fi - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Completed: toggle pause/play" >> $PATHDATA/../logs/debug.log; fi - elif [ "$SECONDSWIPE" == "PLAY" -a $PLLENGTH -gt 0 ] + fi + # now we check if we are still on for playing what we got passed on: + if [ "$PLAYPLAYLIST" == "yes" ] then - # The following involves NOT playing the playlist, so we set: - PLAYPLAYLIST=no - sudo $PATHDATA/playout_controls.sh -c=playerplay &>/dev/null - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Completed: Resume playback" >> $PATHDATA/../logs/debug.log; fi - elif [ "$SECONDSWIPE" == "NOAUDIOPLAY" ] + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "We must play the playlist no matter what: \$PLAYPLAYLIST == yes" >> $PATHDATA/../logs/debug.log; fi + + # Above we already checked if the folder exists -d "$AUDIOFOLDERSPATH/$FOLDER" + # + # the process is as such - because of the recursive play option: + # - each folder can be played. + # - a single folder will create a playlist with the same name as the folder + # - because folders can live inside other folders, the relative path might contain + # slashes (e.g. audiobooks/Moby Dick/) + # - because slashes can not be in the playlist name, slashes are replaced with " % " + # - the "recursive" option means that the content of the folder AND all subfolders + # is being played + # - in this case, the playlist is related to the same folder name, which means we need + # to make a different name for "recursive" playout + # - a recursive playlist has the suffix " %RCRSV%" - keeping it cryptic to avoid clashes + # with a possible "real" name for a folder + # - with this new logic, there are no more SPECIALFORMAT playlists. Live streams and podcasts + # are now all unfolded into the playlist + # - creating the playlist is now done in the php script with parameters: + # $PATHDATA/playlist_recursive_by_folder.php --folder "${FOLDER}" --list 'recursive' + + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " VAR FOLDER: $FOLDER" >> $PATHDATA/../logs/debug.log; fi + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " VAR PLAYLISTPATH: $PLAYLISTPATH" >> $PATHDATA/../logs/debug.log; fi + + # save position of current playing list "stop" + $PATHDATA/playout_controls.sh -c=playerstop + # play playlist + # the variable passed on to play is the playlist name -v (NOT the folder name) + # because (see above) a folder can be played recursively (including subfolders) or flat (only containing files) + # load new playlist and play + $PATHDATA/playout_controls.sh -c=playlistaddplay -v="${PLAYLISTNAME}" -d="${FOLDER}" + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Command: $PATHDATA/playout_controls.sh -c=playlistaddplay -v=\"${PLAYLISTNAME}\" -d=\"${FOLDER}\"" >> $PATHDATA/../logs/debug.log; fi + # save latest playlist not to file + sudo echo ${PLAYLISTNAME} > $PATHDATA/../settings/Latest_Playlist_Played + sudo chown pi:www-data $PATHDATA/../settings/Latest_Playlist_Played + sudo chmod 777 $PATHDATA/../settings/Latest_Playlist_Played + fi + if [ "$PLAYPLAYLIST" == "skipnext" ] then - # The following involves NOT playing the playlist, so we set: - PLAYPLAYLIST=no - # following needs testing (see https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/914) - # Special case for NOAUDIOPLAY because once the playlist has finished, - # it needs to be noted by the system that the second swipe is like a *first* swipe. - currentSong=`mpc current` - if [[ -z "$currentSong" ]]; then - #end of playlist (EOPL) reached. Ignore last played playlist - PLAYPLAYLIST=yes - fi + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "Skip to the next track in the playlist: \$PLAYPLAYLIST == skipnext" >> $PATHDATA/../logs/debug.log; fi + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " VAR FOLDER: $FOLDER" >> $PATHDATA/../logs/debug.log; fi + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " VAR PLAYLISTPATH: $PLAYLISTPATH" >> $PATHDATA/../logs/debug.log; fi - # "$SECONDSWIPE" == "NOAUDIOPLAY" - # "$LASTPLAYLIST" == "$PLAYLISTNAME" => same playlist triggered again - # => do nothing - # echo "do nothing" > /dev/null 2>&1 - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Completed: do nothing" >> $PATHDATA/../logs/debug.log; fi - elif [ "$SECONDSWIPE" == "SKIPNEXT" ] - then - # We will not play the playlist but skip to the next track: - PLAYPLAYLIST=skipnext - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Completed: skip next track" >> $PATHDATA/../logs/debug.log; fi + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Command: $PATHDATA/playout_controls.sh -c=playernext" >> $PATHDATA/../logs/debug.log; fi + $PATHDATA/playout_controls.sh -c=playernext fi - fi - # now we check if we are still on for playing what we got passed on: - if [ "$PLAYPLAYLIST" == "yes" ] - then - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "We must play the playlist no matter what: \$PLAYPLAYLIST == yes" >> $PATHDATA/../logs/debug.log; fi - - # Above we already checked if the folder exists -d "$AUDIOFOLDERSPATH/$FOLDER" - # - # the process is as such - because of the recursive play option: - # - each folder can be played. - # - a single folder will create a playlist with the same name as the folder - # - because folders can live inside other folders, the relative path might contain - # slashes (e.g. audiobooks/Moby Dick/) - # - because slashes can not be in the playlist name, slashes are replaced with " % " - # - the "recursive" option means that the content of the folder AND all subfolders - # is being played - # - in this case, the playlist is related to the same folder name, which means we need - # to make a different name for "recursive" playout - # - a recursive playlist has the suffix " %RCRSV%" - keeping it cryptic to avoid clashes - # with a possible "real" name for a folder - # - with this new logic, there are no more SPECIALFORMAT playlists. Live streams and podcasts - # are now all unfolded into the playlist - # - creating the playlist is now done in the php script with parameters: - # $PATHDATA/playlist_recursive_by_folder.php --folder "${FOLDER}" --list 'recursive' - - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " VAR FOLDER: $FOLDER" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " VAR PLAYLISTPATH: $PLAYLISTPATH" >> $PATHDATA/../logs/debug.log; fi - - # save position of current playing list "stop" - $PATHDATA/playout_controls.sh -c=playerstop - # play playlist - # the variable passed on to play is the playlist name -v (NOT the folder name) - # because (see above) a folder can be played recursively (including subfolders) or flat (only containing files) - # load new playlist and play - $PATHDATA/playout_controls.sh -c=playlistaddplay -v="${PLAYLISTNAME}" -d="${FOLDER}" - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Command: $PATHDATA/playout_controls.sh -c=playlistaddplay -v=\"${PLAYLISTNAME}\" -d=\"${FOLDER}\"" >> $PATHDATA/../logs/debug.log; fi - # save latest playlist not to file - sudo echo ${PLAYLISTNAME} > $PATHDATA/../settings/Latest_Playlist_Played - sudo chown pi:www-data $PATHDATA/../settings/Latest_Playlist_Played - sudo chmod 777 $PATHDATA/../settings/Latest_Playlist_Played - fi - if [ "$PLAYPLAYLIST" == "skipnext" ] - then - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "Skip to the next track in the playlist: \$PLAYPLAYLIST == skipnext" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " VAR FOLDER: $FOLDER" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " VAR PLAYLISTPATH: $PLAYLISTPATH" >> $PATHDATA/../logs/debug.log; fi - - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Command: $PATHDATA/playout_controls.sh -c=playernext" >> $PATHDATA/../logs/debug.log; fi - $PATHDATA/playout_controls.sh -c=playernext + else + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "Path not found $AUDIOFOLDERSPATH/$FOLDER" >> $PATHDATA/../logs/debug.log; fi fi else - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "Path not found $AUDIOFOLDERSPATH/$FOLDER" >> $PATHDATA/../logs/debug.log; fi + if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "var FOLDER empty" >> $PATHDATA/../logs/debug.log; fi fi diff --git a/scripts/test/mockedGPIO.py b/scripts/test/mockedGPIO.py deleted file mode 100644 index e4ff6a153..000000000 --- a/scripts/test/mockedGPIO.py +++ /dev/null @@ -1,17 +0,0 @@ -from mock import MagicMock, patch - -MockRPi = MagicMock() -modules = { - "RPi": MockRPi, - "RPi.GPIO": MockRPi.GPIO, -} - -MockRPi.GPIO.RISING = 31 -MockRPi.GPIO.FALLING = 32 -MockRPi.GPIO.BOTH = 33 -MockRPi.GPIO.HIGH = 1 -MockRPi.GPIO.LOW = 0 -patcher = patch.dict("sys.modules", modules) -patcher.start() -import RPi.GPIO -GPIO = RPi.GPIO diff --git a/scripts/test/test_TwoButtonControl.py b/scripts/test/test_TwoButtonControl.py deleted file mode 100644 index d59125cc6..000000000 --- a/scripts/test/test_TwoButtonControl.py +++ /dev/null @@ -1,157 +0,0 @@ -import mock -import pytest -from mock import MagicMock -from test.mockedGPIO import GPIO - - -import TwoButtonControl - - -@pytest.fixture -def btn1Mock(): - return mock.MagicMock() - - -@pytest.fixture -def btn2Mock(): - return mock.MagicMock() - - -@pytest.fixture -def functionCall1Mock(): - return mock.MagicMock() - - -@pytest.fixture -def functionCall2Mock(): - return mock.MagicMock() - - -@pytest.fixture -def functionCallBothPressedMock(): - return mock.MagicMock() - - -def test_functionCallTwoButtonsOnlyBtn1Pressed(btn1Mock, - btn2Mock, - functionCall1Mock, - functionCall2Mock, - functionCallBothPressedMock): - btn1Mock.is_pressed = True - btn2Mock.is_pressed = False - func = TwoButtonControl.functionCallTwoButtons(btn1Mock, - btn2Mock, - functionCall1Mock, - functionCall2Mock, - functionCallBothPressed=functionCallBothPressedMock) - func() - functionCall1Mock.assert_called_once_with() - functionCall2Mock.assert_not_called() - functionCallBothPressedMock.assert_not_called() - - -def test_functionCallTwoButtonsBothBtnsPressedFunctionCallBothPressedExists(btn1Mock, - btn2Mock, - functionCall1Mock, - functionCall2Mock, - functionCallBothPressedMock): - btn1Mock.is_pressed = True - btn2Mock.is_pressed = True - func = TwoButtonControl.functionCallTwoButtons(btn1Mock, btn2Mock, functionCall1Mock, functionCall2Mock, - functionCallBothPressed=functionCallBothPressedMock) - func() - functionCall1Mock.assert_not_called() - functionCall2Mock.assert_not_called() - functionCallBothPressedMock.assert_called_once_with() - - -def test_functionCallTwoButtonsBothBtnsPressedFunctionCallBothPressedIsNone(btn1Mock, - btn2Mock, - functionCall1Mock, - functionCall2Mock): - btn1Mock.is_pressed = True - btn2Mock.is_pressed = True - func = TwoButtonControl.functionCallTwoButtons(btn1Mock, btn2Mock, functionCall1Mock, functionCall2Mock, - functionCallBothPressed=None) - func() - functionCall1Mock.assert_not_called() - functionCall2Mock.assert_not_called() - - -mockedFunction1 = MagicMock() -mockedFunction2 = MagicMock() -mockedFunction3 = MagicMock() - - -@pytest.fixture -def two_button_control(): - mockedFunction1.reset_mock() - mockedFunction2.reset_mock() - mockedFunction3.reset_mock() - return TwoButtonControl.TwoButtonControl(bcmPin1=1, - bcmPin2=2, - functionCallBtn1=mockedFunction1, - functionCallBtn2=mockedFunction2, - functionCallTwoBtns=mockedFunction3, - pull_up=True, - hold_repeat=False, - hold_time=0.3, - name='TwoButtonControl') - - -class TestTwoButtonControl: - def test_init(self): - TwoButtonControl.TwoButtonControl(bcmPin1=1, - bcmPin2=2, - functionCallBtn1=mockedFunction1, - functionCallBtn2=mockedFunction2, - functionCallTwoBtns=mockedFunction3, - pull_up=True, - hold_repeat=False, - hold_time=0.3, - name='TwoButtonControl') - - def test_btn1_pressed(self, two_button_control): - pinA = two_button_control.bcmPin1 - pinB = two_button_control.bcmPin2 - - def func(pin): - values = {pinA: False, pinB: True} - if pin in values: - return values[pin] - else: - print('Cannot find pin {} in values: {}'.format(pin, values)) - return None - TwoButtonControl.GPIO.input.side_effect = func - two_button_control.action() - mockedFunction1.assert_called_once() - mockedFunction2.assert_not_called() - mockedFunction3.assert_not_called() - two_button_control.action() - assert mockedFunction1.call_count == 2 - - def test_btn2_pressed(self, two_button_control): - pinA = two_button_control.bcmPin1 - pinB = two_button_control.bcmPin2 - TwoButtonControl.GPIO.input.side_effect = lambda pin: {pinA: True, pinB: False}[pin] - two_button_control.action() - mockedFunction1.assert_not_called() - mockedFunction2.assert_called_once() - mockedFunction3.assert_not_called() - two_button_control.action() - assert mockedFunction2.call_count == 2 - - def test_btn1_and_btn2_pressed(self, two_button_control): - pinA = two_button_control.bcmPin1 - pinB = two_button_control.bcmPin2 - TwoButtonControl.GPIO.input.side_effect = lambda pin: {pinA: False, pinB: False}[pin] - two_button_control.action() - mockedFunction1.assert_not_called() - mockedFunction2.assert_not_called() - mockedFunction3.assert_called_once() - two_button_control.action() - assert mockedFunction3.call_count == 2 - - def test_repr(self, two_button_control): - expected = "" - assert repr(two_button_control) == expected diff --git a/scripts/userscripts/addhotspot.sh b/scripts/userscripts/addhotspot.sh index 038fd6957..6e8e63a4e 100644 --- a/scripts/userscripts/addhotspot.sh +++ b/scripts/userscripts/addhotspot.sh @@ -1,10 +1,14 @@ -#!/bin/bash +#!/usr/bin/env bash + +if [[ -z "$1" || -z "$2" ]]; then + echo "usage: addhotspot.sh " + exit 1 +fi # addhotspot.sh newssid newpassword wpa_passphrase "$1" $2 >> /etc/wpa_supplicant/wpa_supplicant.conf # /etc/dhcpcd.conf -echo ssid $1 >> /etc/dhcpcd.conf - - - +if [[ ! $(grep -w "ssid $1" /etc/dhcpcd.conf) ]]; then + echo "ssid $1" >> /etc/dhcpcd.conf +fi diff --git a/settings/debugLogging.conf.sample b/settings/debugLogging.conf.sample index 9494224e3..1cece8131 100755 --- a/settings/debugLogging.conf.sample +++ b/settings/debugLogging.conf.sample @@ -10,3 +10,4 @@ DEBUG_resume_play_sh="FALSE" DEBUG_rfid_trigger_play_sh="FALSE" DEBUG_shuffle_play_sh="FALSE" DEBUG_single_play_sh="FALSE" +DEBUG_sync_shared_sh="FALSE" diff --git a/settings/rfid_trigger_play.conf.sample b/settings/rfid_trigger_play.conf.sample index 9b99fa7a2..aa1c57df6 100755 --- a/settings/rfid_trigger_play.conf.sample +++ b/settings/rfid_trigger_play.conf.sample @@ -16,7 +16,7 @@ # A section starts with ## # Example: ## Audio player # A command's description is *above* the command and starts with ### -# Example: +# Example: # ### Stop player # CMDSTOP="%CMDSTOP%" # This structuring was introduced to have a human readable display in the Web UI @@ -115,6 +115,12 @@ STOPAFTER15="%STOPAFTER15%" STOPAFTER30="%STOPAFTER30%" ### Stop player after 60 min. STOPAFTER60="%STOPAFTER60%" +### Stop player after 120 min. +STOPAFTER120="%STOPAFTER120%" +### Stop player after 180 min. +STOPAFTER180="%STOPAFTER180%" +### Stop player after 240 min. +STOPAFTER240="%STOPAFTER240%" ## Timer: shutdown after x minutes ### Shutdown after 5 min. @@ -125,6 +131,12 @@ SHUTDOWNAFTER15="%SHUTDOWNAFTER15%" SHUTDOWNAFTER30="%SHUTDOWNAFTER30%" ### Shutdown after 60 min. SHUTDOWNAFTER60="%SHUTDOWNAFTER60%" +### Shutdown after 120 min. +SHUTDOWNAFTER120="%SHUTDOWNAFTER120%" +### Shutdown after 180 min. +SHUTDOWNAFTER180="%SHUTDOWNAFTER180%" +### Shutdown after 240 min. +SHUTDOWNAFTER240="%SHUTDOWNAFTER240%" ## Shutdown Timer Volume Reduction : reduce volume until shutdown in x minutes ### Reduce volume and Shutdown after 10 min. @@ -135,6 +147,12 @@ SHUTDOWNVOLUMEREDUCTION15="%SHUTDOWNVOLUMEREDUCTION15%" SHUTDOWNVOLUMEREDUCTION30="%SHUTDOWNVOLUMEREDUCTION30%" ### Reduce volume and Shutdown after 60 min. SHUTDOWNVOLUMEREDUCTION60="%SHUTDOWNVOLUMEREDUCTION60%" +### Reduce volume and Shutdown after 120 min. +SHUTDOWNVOLUMEREDUCTION120="%SHUTDOWNVOLUMEREDUCTION120%" +### Reduce volume and Shutdown after 180 min. +SHUTDOWNVOLUMEREDUCTION180="%SHUTDOWNVOLUMEREDUCTION180%" +### Reduce volume and Shutdown after 240 min. +SHUTDOWNVOLUMEREDUCTION240="%SHUTDOWNVOLUMEREDUCTION240%" ## Wifi: switch on/off and other ### Enable Wifi @@ -146,7 +164,7 @@ TOGGLEWIFI="%TOGGLEWIFI%" ### Read out the Wifi IP over the Phoniebox speakers CMDREADWIFIIP="%CMDREADWIFIIP%" -## Recording audio commands +## Recording audio commands ### Start recording for 10 sec. duration RECORDSTART10="%RECORDSTART10%" ### Start recording for 60 sec. duration @@ -157,3 +175,9 @@ RECORDSTART600="%RECORDSTART600%" RECORDSTOP="%RECORDSTOP%" ### Replay latest recording RECORDPLAYBACKLATEST="%RECORDPLAYBACKLATEST%" + +## Synchronisation +### Synchronise all shared files +SYNCSHAREDFULL="%SYNCSHAREDFULL%" +### Toggle activation of 'sync on RFID scan' +SYNCSHAREDONRFIDSCANTOGGLE="%SYNCSHAREDONRFIDSCANTOGGLE%" diff --git a/settings/version-number b/settings/version-number index 6b4950e3d..71d37081c 100644 --- a/settings/version-number +++ b/settings/version-number @@ -1 +1 @@ -2.4 +2.5.0-alpha diff --git a/tests/htdocs/trackEditTest.php b/tests/htdocs/TrackEditTest.php similarity index 88% rename from tests/htdocs/trackEditTest.php rename to tests/htdocs/TrackEditTest.php index 03e99314f..be83a4188 100644 --- a/tests/htdocs/trackEditTest.php +++ b/tests/htdocs/TrackEditTest.php @@ -58,7 +58,19 @@ public function setUp(): void { "EDITION" => "FALSE", "AUDIOVOLMAXLIMIT" => "FALSE", "LANG" => "FALSE", - "AUDIOFOLDERSPATH" => sys_get_temp_dir() + "AUDIOFOLDERSPATH" => sys_get_temp_dir(), + "PLAYLISTSFOLDERPATH" => sys_get_temp_dir(), + "SECONDSWIPEPAUSE" => "FALSE", + "SWIPEORPLACE" => "FALSE", + "SECONDSWIPEPAUSECONTROLS" => "FALSE", + "VOLUMEMANAGER" => "FALSE", + "READWLANIPYN" => "FALSE", + "MAILWLANIPYN" => "FALSE", + "MAILWLANIPADDR" => "FALSE", + "AUDIOVOLSTARTUP" => "FALSE", + "AUDIOVOLBOOT" => "FALSE", + "AUDIOVOLCHANGESTEP" => "FALSE", + "IDLETIMESHUTDOWN" => "FALSE" )); } diff --git a/tests/htdocs/api/playListTest.php b/tests/htdocs/api/PlayListTest.php similarity index 100% rename from tests/htdocs/api/playListTest.php rename to tests/htdocs/api/PlayListTest.php diff --git a/tests/htdocs/api/playerTest.php b/tests/htdocs/api/PlayerTest.php similarity index 97% rename from tests/htdocs/api/playerTest.php rename to tests/htdocs/api/PlayerTest.php index 0699c9829..37ed7f2f5 100644 --- a/tests/htdocs/api/playerTest.php +++ b/tests/htdocs/api/PlayerTest.php @@ -19,6 +19,9 @@ public function setUp(): void { require_once 'htdocs/api/player.php'; } + /** + * @group real-env + */ public function testReturnHandleGet() { $exec = $this->getFunctionMock(__NAMESPACE__, 'exec'); $exec->expects($this->once())->willReturnCallback(