diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index c5907d6f101..00000000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,46 +0,0 @@ -FROM mcr.microsoft.com/vscode/devcontainers/base:debian - -WORKDIR /workspaces - -SHELL ["/bin/bash", "-o", "pipefail", "-c"] - -# Set Docker daemon config -RUN \ - mkdir -p /etc/docker \ - && echo '{"storage-driver": "vfs"}' > /etc/docker/daemon.json - -# Installa aditional tools -RUN \ - apt-get update \ - && apt-get install -y --no-install-recommends \ - dbus \ - network-manager \ - libpulse0 \ - xz-utils - -# Install docker -RUN apt-get update && apt-get install -y --no-install-recommends \ - apt-transport-https \ - ca-certificates \ - curl \ - software-properties-common \ - gpg-agent \ - && curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - \ - && add-apt-repository "deb https://download.docker.com/linux/debian $(lsb_release -cs) stable" \ - && apt-get update && apt-get install -y --no-install-recommends \ - docker-ce \ - docker-ce-cli \ - containerd.io \ - && rm -rf /var/lib/apt/lists/* - -# Install shellcheck -RUN \ - curl -fLs \ - "https://github.com/koalaman/shellcheck/releases/download/stable/shellcheck-stable.linux.x86_64.tar.xz" \ - | tar -xJ \ - \ - && mv -f "./shellcheck-stable/shellcheck" "/usr/bin/shellcheck" \ - && rm -rf "./shellcheck-stable" - -# Generate a machine-id for this container -RUN rm /etc/machine-id && dbus-uuidgen --ensure=/etc/machine-id diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 30e7edebab0..b75098ee007 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,18 +1,25 @@ { - "name": "Home Assistant Add-Ons", - "context": "..", - "dockerFile": "Dockerfile", - "appPort": ["7123:8123", "7357:4357"], - "postStartCommand": "service docker start", - "runArgs": ["-e", "GIT_EDITOR=code --wait", "--privileged"], - "containerEnv": { - "WORKSPACE_DIRECTORY": "${containerWorkspaceFolder}" - }, - "extensions": [ - "timonwong.shellcheck", - "esbenp.prettier-vscode" - ], - "settings": { - "terminal.integrated.shell.linux": "/bin/bash" - } -} + "name": "Home Assistant Add-ons", + "image": "ghcr.io/home-assistant/devcontainer:addons", + "appPort": ["7123:8123", "7357:4357"], + "postStartCommand": "bash devcontainer_bootstrap", + "runArgs": ["-e", "GIT_EDITOR=code --wait", "--privileged"], + "remoteUser":"root", + "containerEnv": { + "WORKSPACE_DIRECTORY": "${containerWorkspaceFolder}" + }, + "extensions": ["timonwong.shellcheck", "esbenp.prettier-vscode"], + "mounts": [ "type=volume,target=/var/lib/docker" ], + "settings": { + "terminal.integrated.profiles.linux": { + "zsh": { + "path": "/usr/bin/zsh" + } + }, + "terminal.integrated.defaultProfile.linux": "zsh", + "editor.formatOnPaste": false, + "editor.formatOnSave": true, + "editor.formatOnType": true, + "files.trimTrailingWhitespace": true + } + } diff --git a/.devcontainer/supervisor.sh b/.devcontainer/supervisor.sh index 9891b8bbcfd..2634985c2f6 100755 --- a/.devcontainer/supervisor.sh +++ b/.devcontainer/supervisor.sh @@ -81,7 +81,7 @@ function run_supervisor() { --name hassio_supervisor \ --privileged \ --security-opt seccomp=unconfined \ - --security-opt apparmor:unconfined \ + --security-opt apparmor=unconfined \ -v /run/docker.sock:/run/docker.sock:rw \ -v /run/dbus:/run/dbus:ro \ -v /run/udev:/run/udev:ro \ @@ -142,4 +142,4 @@ cleanup_docker init_dbus init_udev run_supervisor -stop_docker \ No newline at end of file +stop_docker diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.md b/.github/ISSUE_TEMPLATE/BUG_REPORT.md deleted file mode 100644 index 1accd59c648..00000000000 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -name: Report a bug with one of the add-ons -about: Report an issue with one of the add-ons in this repository ---- - -## The problem - - - -## Environment - - -- Add-on with the issue: -- Add-on release with the issue: -- Last working add-on release (if known): -- Operating environment (OS/Supervised): - -## Problem-relevant configuration - - -```yaml - -``` - -## Traceback/Error logs - - -```txt - -``` - -## Additional information diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000000..6a331190b3a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,143 @@ +--- +# yamllint disable rule:line-length +name: Bug Report Form +description: Report an issue related to one of the official add-ons. +body: + - type: markdown + attributes: + value: | + This issue form is for reporting bugs with **supported** setups only! + + If you have a feature or enhancement request, please use the [feature request][fr] section of our [Community Forum][fr]. + + [fr]: https://community.home-assistant.io/c/feature-requests + + - type: textarea + validations: + required: true + attributes: + label: Describe the issue you are experiencing + description: Provide a clear and concise description of what the bug is. + + - type: markdown + attributes: + value: | + ## Environment + + - type: dropdown + validations: + required: true + attributes: + label: What type of installation are you running? + description: > + If you don't know, can be found in [Settings -> System -> Repairs -> System Information](https://my.home-assistant.io/redirect/system_health/). + It is listed as the `Installation Type` value. + options: + - Home Assistant OS + - Home Assistant Supervised + + - type: dropdown + validations: + required: true + attributes: + label: Which operating system are you running on? + options: + - Home Assistant Operating System + - Debian + - Other (e.g., Raspbian/Raspberry Pi OS/Fedora) + + - type: dropdown + validations: + required: true + attributes: + label: Which add-on are you reporting an issue with? + options: + - CEC Scanner + - File editor + - deCONZ + - DHCP Server + - Dnsmasq + - Duck DNS + - Git pull + - Google Assistant SDK + - Let's Encrypt + - MariaDB + - Matter Server + - Mosquitto broker + - NGINX Home Assistant SSL proxy + - OpenThread Border Router + - Piper + - RPC Shutdown + - Samba share + - Silicon Labs Flasher + - Silicon Labs Multiprotocol + - Terminal & SSH + - TellStick + - VLC + - Whisper + - Z-Wave JS + + - type: input + validations: + required: true + attributes: + label: What is the version of the add-on? + description: Can be found in [Settings -> Add-ons](https://my.home-assistant.io/redirect/supervisor/) -> the add-on + + - type: markdown + attributes: + value: | + # Details + + - type: textarea + validations: + required: true + attributes: + label: Steps to reproduce the issue + description: | + Please tell us exactly how to reproduce your issue. + Provide clear and concise step by step instructions and add code snippets if needed. + value: | + 1. + 2. + 3. + ... + + - type: textarea + validations: + required: true + attributes: + label: System Health information + description: > + System Health information can be found in the top right menu in [Settings -> System -> Repairs](https://my.home-assistant.io/redirect/repairs/). + Click the copy button at the bottom of the pop-up and paste it here. + + [![Open your Home Assistant instance and show health information about your system.](https://my.home-assistant.io/badges/system_health.svg)](https://my.home-assistant.io/redirect/system_health/) + + - type: textarea + attributes: + label: Anything in the Supervisor logs that might be useful for us? + description: > + Supervisor Logs can be found in [Settings -> System -> Logs](https://my.home-assistant.io/redirect/logs/) + then choose `Supervisor` in the top right. + + [![Open your Home Assistant instance and show your Supervisor system logs.](https://my.home-assistant.io/badges/supervisor_logs.svg)](https://my.home-assistant.io/redirect/supervisor_logs/) + render: txt + + - type: textarea + attributes: + label: Anything in the add-on logs that might be useful for us? + description: > + Addon Logs can be found in [Settings -> System -> Logs](https://my.home-assistant.io/redirect/logs/) + then choose the add-on in the top right. + + [![Open your Home Assistant instance and show your Home Assistant logs.](https://my.home-assistant.io/badges/logs.svg)](https://my.home-assistant.io/redirect/logs/) + render: txt + + - type: textarea + attributes: + label: Additional information + description: > + If you have any additional information for us, use the field below. + Please note, you can attach screenshots or screen recordings here, by + dragging and dropping files in the field below. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 3fb99d9aebd..9063623ce8c 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,6 +1,8 @@ +--- +# yamllint disable rule:line-length blank_issues_enabled: false contact_links: - - name: Report a bug with the UI, Frontend or Lovelace + - name: Report a bug with the UI, Frontend or Dashboards url: https://github.com/home-assistant/frontend/issues about: This is the issue tracker for our backend. Please report issues with the UI in the frontend repository. - name: Report a bug with Home Assistant @@ -17,4 +19,4 @@ contact_links: about: Please use our Community Forum for making feature requests. - name: I'm unsure where to go url: https://www.home-assistant.io/join-chat - about: If you are unsure where to go, then joining our chat is recommended; Just ask! \ No newline at end of file + about: If you are unsure where to go, then joining our chat is recommended; Just ask! diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 10f096219ea..8f266a9b528 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,8 +1,9 @@ +--- version: 2 updates: -- package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: daily - time: "06:00" - open-pull-requests-limit: 10 \ No newline at end of file + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: weekly + time: "06:00" + open-pull-requests-limit: 10 diff --git a/.github/move.yml b/.github/move.yml deleted file mode 100644 index e041083c9ae..00000000000 --- a/.github/move.yml +++ /dev/null @@ -1,13 +0,0 @@ -# Configuration for move-issues - https://github.com/dessant/move-issues - -# Delete the command comment. Ignored when the comment also contains other content -deleteCommand: true -# Close the source issue after moving -closeSourceIssue: true -# Lock the source issue after moving -lockSourceIssue: false -# Set custom aliases for targets -# aliases: -# r: repo -# or: owner/repo - diff --git a/.github/stale.yml b/.github/stale.yml deleted file mode 100644 index 4e71c1984e6..00000000000 --- a/.github/stale.yml +++ /dev/null @@ -1,18 +0,0 @@ -# Number of days of inactivity before an issue becomes stale -daysUntilStale: 30 -# Number of days of inactivity before a stale issue is closed -daysUntilClose: 7 -# Issues with these labels will never be considered stale -exemptLabels: - - pinned - - security - - Help wanted -# Label to use when marking an issue as stale -staleLabel: stale -# Comment to post when marking an issue as stale. Set to `false` to disable -markComment: > - This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. Thank you - for your contributions. -# Comment to post when closing a stale issue. Set to `false` to disable -closeComment: false diff --git a/.github/workflows/builder.yml b/.github/workflows/builder.yml index 1d4c3a0911a..d6d51de6efc 100644 --- a/.github/workflows/builder.yml +++ b/.github/workflows/builder.yml @@ -1,8 +1,10 @@ +--- +# yamllint disable rule:line-length rule:truthy name: Build add-on env: BUILD_ARGS: "--test" - MONITORED_FILES: "apparmor.txt build.json config.json Dockerfile data rootfs" + MONITORED_FILES: "apparmor.txt build.yaml config.yaml Dockerfile data rootfs" on: pull_request: @@ -12,7 +14,7 @@ on: jobs: init: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 name: Initialize builds outputs: changed_files: ${{ steps.changed_files.outputs.all }} @@ -20,20 +22,20 @@ jobs: changed: ${{ steps.changed_addons.outputs.changed }} steps: - name: Check out the repository - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v4.2.2 - name: Get changed files id: changed_files - uses: jitterbit/get-changed-files@v1 + uses: masesgroup/retrieve-changed-files@v3.0.0 - name: Get add-ons id: addons run: | declare -a addons - for addon in $(find ./ -name config.json | cut -d "/" -f2 | sort -u); do + for addon in $(find ./ -name config.yaml | cut -d "/" -f2 | sort -u); do addons+=("$addon"); done - echo "::set-output name=addons::${addons[@]}" + echo "addons=${addons[@]}" >> "$GITHUB_OUTPUT" - name: Get changed add-ons id: changed_addons @@ -54,25 +56,25 @@ jobs: changed=$(echo ${changed_addons[@]} | rev | cut -c 2- | rev) if [[ -n ${changed} ]]; then echo "Changed add-ons: $changed"; - echo "::set-output name=changed::true"; - echo "::set-output name=addons::[$changed]"; + echo "changed=true" >> "$GITHUB_OUTPUT"; + echo "addons=[$changed]" >> "$GITHUB_OUTPUT"; else echo "No add-on had any monitored files changed (${{ env.MONITORED_FILES }})"; fi build: needs: init - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 if: needs.init.outputs.changed == 'true' name: Build ${{ matrix.arch }} ${{ matrix.addon }} add-on strategy: - matrix: + matrix: addon: ${{ fromJson(needs.init.outputs.changed_addons) }} arch: ["aarch64", "amd64", "armhf", "armv7", "i386"] steps: - name: Check out repository - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v4.2.2 - name: Get information id: info @@ -83,14 +85,11 @@ jobs: - name: Check add-on id: check run: | - if [[ "${{ steps.info.outputs.architectures }}" =~ ${{ matrix.arch }} ]]; then - echo "::set-output name=build_arch::true"; - else - echo "${{ matrix.arch }} is not a valid arch for ${{ matrix.addon }}, skipping build"; - fi - - version=$(jq -r '.version' "./${{ matrix.addon }}/config.json") - echo "::set-output name=version::${version}"; + if [[ "${{ steps.info.outputs.architectures }}" =~ ${{ matrix.arch }} ]]; then + echo "build_arch=true" >> "$GITHUB_OUTPUT"; + else + echo "${{ matrix.arch }} is not a valid arch for ${{ matrix.addon }}, skipping build"; + fi - name: Set build arguments if: steps.check.outputs.build_arch == 'true' @@ -101,27 +100,17 @@ jobs: - name: Login to DockerHub if: env.BUILD_ARGS == '--docker-hub-check' - uses: docker/login-action@v1.10.0 + uses: docker/login-action@v3.3.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Login to GitHub Container Registry - if: env.BUILD_ARGS == '--docker-hub-check' - uses: docker/login-action@v1.10.0 - with: - registry: ghcr.io - username: ${{ secrets.GIT_USER }} - password: ${{ secrets.GIT_TOKEN }} - - name: Build ${{ matrix.addon }} add-on if: steps.check.outputs.build_arch == 'true' - uses: home-assistant/builder@2021.06.2 + uses: home-assistant/builder@2025.02.0 with: args: | ${{ env.BUILD_ARGS }} \ --${{ matrix.arch }} \ --target /data/${{ matrix.addon }} \ - --with-codenotary "${{ secrets.VCN_USER }}" "${{ secrets.VCN_PASSWORD }}" "${{ secrets.VCN_ORG }}" \ - --validate-from "${{ secrets.VCN_ORG }}" \ --addon diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 437e38fa647..9c758d0f580 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,3 +1,5 @@ +--- +# yamllint disable rule:truthy name: Lint env: @@ -16,7 +18,7 @@ jobs: name: hadolint steps: - name: Check out the repository - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v4.2.2 - name: Run linter id: changed_files @@ -29,24 +31,40 @@ jobs: hadolint/hadolint:${{ env.HADOLINT_VERSION }} < "$dockerfile" done - jq: + yamllint: runs-on: ubuntu-latest - name: JQ + name: YAMLLint steps: - name: Check out the repository - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v4.2.2 - - name: Run linter - run: | - shopt -s globstar - cat **/*.json | jq '.' + - name: Run YAMLLint + uses: frenck/action-yamllint@v1.5 shellcheck: runs-on: ubuntu-latest name: ShellCheck steps: - name: Check out the repository - uses: actions/checkout@v2.3.4 + uses: actions/checkout@v4.2.2 - name: Run linter - uses: ludeeus/action-shellcheck@1.1.0 \ No newline at end of file + uses: ludeeus/action-shellcheck@2.0.0 + with: + # Names of scripts with custom shebangs that the action would not + # discover on its own: + additional_files: >- + check_certificate_renewal + cpcd-config-up + discovery + finish + lock-tables-for-backup + matter-server-discovery + reboot + run + shutdown + universal-silabs-flasher-up + unlock-tables-for-backup + vlc-discovery + ignore_paths: >- + google_assistant diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000000..fa517401513 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,27 @@ +--- +# yamllint disable rule:truthy +name: Stale + +on: + schedule: + - cron: "0 * * * *" + workflow_dispatch: + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - name: 30 days stale issues + uses: actions/stale@v9.1.0 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + days-before-issue-stale: 30 + days-before-issue-close: 7 + operations-per-run: 150 + remove-stale-when-updated: true + stale-issue-label: "stale" + exempt-issue-labels: "pinned,security,Help wanted" + stale-issue-message: > + This issue has been automatically marked as stale because it has + not had recent activity. It will be closed if no further activity + occurs. Thank you for your contributions. diff --git a/.hadolint.yaml b/.hadolint.yaml index d29b725401b..99819b5cf54 100644 --- a/.hadolint.yaml +++ b/.hadolint.yaml @@ -1,3 +1,4 @@ +--- ignored: - DL3003 - DL3006 @@ -5,5 +6,7 @@ ignored: - DL3008 - DL3013 - DL3018 + - DL3042 - DL4006 - SC2046 + - SC2086 diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 81384a17b07..cb4e05c51f4 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,31 +1,19 @@ { - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "2.0.0", - "tasks": [ - { - "label": "Start Home Assistant", - "type": "shell", - "command": "./.devcontainer/supervisor.sh", - "group": { - "kind": "test", - "isDefault": true, - }, - "presentation": { - "reveal": "always", - "panel": "new" - }, - "problemMatcher": [] - },{ - "label": "Run Home Assistant CLI", - "type": "shell", - "command": "docker exec -ti hassio_cli /usr/bin/cli.sh", - "group": "test", - "presentation": { - "reveal": "always", - "panel": "new" - }, - "problemMatcher": [] - } - ] -} \ No newline at end of file + "version": "2.0.0", + "tasks": [ + { + "label": "Start Home Assistant", + "type": "shell", + "command": "supervisor_run", + "group": { + "kind": "test", + "isDefault": true + }, + "presentation": { + "reveal": "always", + "panel": "new" + }, + "problemMatcher": [] + } + ] +} diff --git a/README.md b/README.md index 4262ecc05db..3329492739e 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,22 @@ # Home Assistant Add-ons: The official repository -Add-ons for Home Assistant, allow you to extend the functionality +Add-ons for Home Assistant allow you to extend the functionality around your Home Assistant setup. These add-ons can consist of an application -that Home Assistant can integrate with (e.g., a MQTT broker or database server) -or allow access to your Home Assistant configuration (e.g., via Samba or using -the Configurator). +that Home Assistant can integrate with (e.g., a [MQTT broker](/mosquitto/README.md) or [database server](/mariadb/README.md)) +or allow access to your Home Assistant configuration (e.g., via [Samba](/samba/README.md) or using +the [File Editor](/configurator/README.md)). Add-ons can be installed and configured via the Home Assistant frontend on systems that have installed Home Assistant. -## Add-ons provided by this repository - -- **[Almond](/almond/README.md)** +[![Home Assistant - A project from the Open Home Foundation](https://www.openhomefoundation.org/badges/home-assistant.png)](https://www.openhomefoundation.org/) - Almond For Home Servers. +## Add-ons provided by this repository - **[CEC Scanner](/cec_scan/README.md)** Scan & discover HDMI CEC devices and their addresses. -- **[Check Home Assistant configuration](/check_config/README.md)** - - Check your current configuration against any Home Assistant version. - - **[deCONZ](/deconz/README.md)** Control a Zigbee network using ConBee or RaspBee hardware by Dresden Elektronik. @@ -51,14 +45,6 @@ systems that have installed Home Assistant. A virtual personal assistant developed by Google. -- **[Hey Ada!](/ada/README.md)** - - Voice assistant powered by Home Assistant. - -- **[HomeMatic](/homematic/README.md)** - - HomeMatic central based on OCCU. - - **[Let's Encrypt](/letsencrypt/README.md)** Manage an create certificates from Let's Encrypt. @@ -81,17 +67,17 @@ systems that have installed Home Assistant. - **[Samba share](/samba/README.md)** - Expose Home Assistant folders with SMB/CIFS. + Share your configuration over the network using Windows file sharing. - **[SSH server](/ssh/README.md)** - Allow logging in remotely to Home Assistant using SSH. + Allow logging in remotely to Home Assistant using SSH or just the web terminal with Ingress. - **[TellStick](/tellstick/README.md)** TellStick and TellStick Duo service. -- **[OpenZWave](/zwave/README.md)** +- **[Z-Wave JS](/zwave_js/README.md)** Allow Home Assistant to talk to a Z-Wave Network via a USB Controller. @@ -103,7 +89,7 @@ You have several options to get them answered: - The [Home Assistant Discord Chat Server][discord]. - The Home Assistant [Community Forum][forum]. -- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit] +- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit]. In case you've found a bug, please [open an issue on our GitHub][issue]. @@ -117,6 +103,6 @@ about developing an add-on, please see our [discord]: https://discord.gg/c5DvZ4e [forum]: https://community.home-assistant.io [i386-shield]: https://img.shields.io/badge/i386-no-red.svg -[issue]: https://github.com/home-assistant/hassio-addons/issues +[issue]: https://github.com/home-assistant/addons/issues [reddit]: https://reddit.com/r/homeassistant -[dev-docs]: https://developers.home-assistant.io/docs/add-ons +[dev-docs]: https://developers.home-assistant.io/docs/add-ons/ diff --git a/ada/CHANGELOG.md b/ada/CHANGELOG.md deleted file mode 100644 index cb24d61932c..00000000000 --- a/ada/CHANGELOG.md +++ /dev/null @@ -1,55 +0,0 @@ -# Changelog - -## 1.1.1 - -- Fix aarch64 support - -## 1.1.0 - -- Renaming Home Assistant -- Convert to s6-overlay -- Support new audio backend - -## 1.0.0 - -- Support aarch64 in armv7 combat mode - -## 0.9.0 - -- Corrected link to documentation inside the add-on -- Adjust source links in Dockerfile -- Update add-on documentation to match current state - -## 0.8.0 - -- Fix API url for access to Home Assistant - -## 0.7.0 - -- Add missing options - -## 0.6.0 - -- Update Ada to 0.7 -- Add options to change TTS / STT Home Assistant provider - -## 0.5.0 - -- Update Ada to 0.6 - -## 0.4.0 - -- Update Ada to 0.5 - -## 0.3.0 - -- Update Ada to 0.4 - -## 0.2.0 - -- Update Ada to 0.3 -- Add armhf support - -## 0.1.0 - -- Initial support diff --git a/ada/DOCS.md b/ada/DOCS.md deleted file mode 100644 index 0991f5d6269..00000000000 --- a/ada/DOCS.md +++ /dev/null @@ -1,59 +0,0 @@ -# Home Assistant Add-on: Ada - -## Installation - -Follow these steps to get the add-on installed on your system: - -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. -2. Find the "Hey Ada!" add-on and click it. -3. Click on the "INSTALL" button. - -## How to use - -The basic thing to get the add-on running would be: - -1. Select input and output audio device to use in the "Audio" configuration section of the add-on configuration. -2. Start the add-on. - -## Configuration - -Example add-on configuration: - -```yaml -stt: cloud -tts: cloud -``` - -### Option: `stt` (required) - -The Home Assistant STT (Speech-to-Text) integration to use when converting -detected audio to text for Almond to process. - -Please note, this STT integration has to be configured and active in -Home Assistant before using it with this add-on! - -### Option: `tts` (required) - -The Home Assistant TTS (Text-to-Speech) integration to use when converting -the response from Almond back to audio. - -Please note, this TTS integration has to be configured and active in -Home Assistant before using it with this add-on! - -## Support - -Got questions? - -You have several options to get them answered: - -- The [Home Assistant Discord Chat Server][discord]. -- The Home Assistant [Community Forum][forum]. -- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit] - -In case you've found an bug, please [open an issue on our GitHub][issue]. - -[discord]: https://discord.gg/c5DvZ4e -[forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues -[reddit]: https://reddit.com/r/homeassistant -[repository]: https://github.com/hassio-addons/repository diff --git a/ada/Dockerfile b/ada/Dockerfile deleted file mode 100644 index 3ba5af0c832..00000000000 --- a/ada/Dockerfile +++ /dev/null @@ -1,36 +0,0 @@ -ARG BUILD_FROM -FROM ${BUILD_FROM} - -# Install Ada -WORKDIR /usr/src/ada -ARG ADA_VERSION - -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - portaudio19-dev \ - libasound2-plugins \ - libsndfile1 \ - mplayer \ - libffi-dev \ - python3 \ - python3-pip \ - python3-dev \ - git \ - build-essential \ - \ - && git clone --depth 1 -b ${ADA_VERSION} \ - "https://github.com/home-assistant/ada" . \ - && rm -rf .git \ - && pip3 install --no-cache-dir -U setuptools wheel \ - && pip3 install --no-cache-dir -r requirements.txt \ - && pip3 install --no-cache-dir -e . \ - && python3 -m compileall ada \ - \ - && apt-get purge -y --auto-remove \ - git \ - build-essential \ - python3-dev \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR / -COPY rootfs / diff --git a/ada/README.md b/ada/README.md deleted file mode 100644 index 4d3041a9635..00000000000 --- a/ada/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Home Assistant Add-on: Ada - -![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield] - -Voice assistant powered by Home Assistant. - -Voice assistants are a great way to interact with your house, ask a quick -question, set a timer or control your devices. The more an assistant knows about -you, your home and it’s other inhabitants, the better it is able to help you. - -Ada is powered by Almond which is an open, privacy-preserving virtual assistant -that is open source. - -For more information about Ada & Almond, read our blog post: - - - -[aarch64-shield]: https://img.shields.io/badge/aarch64-no-red.svg -[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg -[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg -[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg -[i386-shield]: https://img.shields.io/badge/i386-no-red.svg diff --git a/ada/build.json b/ada/build.json deleted file mode 100644 index 5c7c6119475..00000000000 --- a/ada/build.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "build_from": { - "amd64": "homeassistant/amd64-base-debian:buster", - "armhf": "homeassistant/armhf-base-debian:buster", - "armv7": "homeassistant/armv7-base-debian:buster" - }, - "args": { - "ADA_VERSION": "0.8.1" - } -} diff --git a/ada/config.json b/ada/config.json deleted file mode 100644 index 5c3bb9b3e57..00000000000 --- a/ada/config.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "Hey Ada!", - "version": "1.1.1", - "slug": "ada", - "description": "Voice assistant powered by Home Assistant", - "url": "https://github.com/home-assistant/hassio-addons/blob/master/ada", - "arch": ["armhf", "armv7", "amd64"], - "init": false, - "audio": true, - "homeassistant": "0.102.0", - "homeassistant_api": true, - "options": { - "stt": "cloud", - "tts": "cloud" - }, - "schema": { - "stt": "str", - "tts": "str" - }, - "image": "homeassistant/{arch}-addon-ada" -} diff --git a/ada/icon.png b/ada/icon.png deleted file mode 100644 index d6d6450568d..00000000000 Binary files a/ada/icon.png and /dev/null differ diff --git a/ada/logo.png b/ada/logo.png deleted file mode 100644 index 2e3ea85e46e..00000000000 Binary files a/ada/logo.png and /dev/null differ diff --git a/ada/rootfs/etc/services.d/ada/finish b/ada/rootfs/etc/services.d/ada/finish deleted file mode 100644 index 48df08c2e73..00000000000 --- a/ada/rootfs/etc/services.d/ada/finish +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/execlineb -S0 -# ============================================================================== -# Take down the S6 supervision tree when Ada fails -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } - -s6-svscanctl -t /var/run/s6/services \ No newline at end of file diff --git a/ada/rootfs/etc/services.d/ada/run b/ada/rootfs/etc/services.d/ada/run deleted file mode 100644 index 9e5bf83ee12..00000000000 --- a/ada/rootfs/etc/services.d/ada/run +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Start Ada service -# ============================================================================== -STT=$(bashio::config 'stt') -TTS=$(bashio::config 'tts') - -exec python3 -m ada --url "http://supervisor/core/api" --key "$SUPERVISOR_TOKEN" --stt "$STT" --tts "$TTS" \ No newline at end of file diff --git a/almond/CHANGELOG.md b/almond/CHANGELOG.md deleted file mode 100644 index a23b0a35902..00000000000 --- a/almond/CHANGELOG.md +++ /dev/null @@ -1,78 +0,0 @@ -# Changelog - -## 2.0.1 - -- Fix url for API requests - -## 2.0.0 - -- Almond was updated to 2.0.0: this is a major release that - brings significant changes to the supported skills. Additional - details are in the release notes: https://wiki.almond.stanford.edu/en/release-planning/two-point-oh - All users are encouraged to upgrade as soon as possible, because - the previous release line is unmaintained and unsupported. Cloud - services that Almond relies on might drop compatibility with - Almond 1.* at some point in the future. -- Voice support is now included in this addon, and the Ada add-on - is not required (in fact, it should not be enabled at the same time). - -## 1.1.2 - -- Revert restart nginx service on error - -## 1.1.1 - -- Fix issue with some Almond packages - -## 1.1.0 - -- Restart nginx service on error -- Use Alpine 3.13 - -## 1.0.1 - -- Keep unzip dependency installed - -## 1.0.0 - -- Update Almond to 1.8.0 -- Rewrite onto S6 overlay -- Reduce add-on image size -- Updates Supervisor API token and endpoint - -## 0.9 - -- Update Almond to 1.7.3 - -## 0.8 - -- Update Almond to 1.7.2 - -## 0.7 - -- Change startup type to Application - -## 0.6 - -- Fix issue with restart / Hass.io token handling - -## 0.5 - -- Update Almond to 1.7.1 - -## 0.4 - -- Update Almond to 1.7.0 - -## 0.3 - -- Add automatic Almond setup - -## 0.2 - -- Add Ingress -- Update almond to 1.6.0 - -## 0.1 - -- Initial version diff --git a/almond/DOCS.md b/almond/DOCS.md deleted file mode 100644 index 20caab3b2fe..00000000000 --- a/almond/DOCS.md +++ /dev/null @@ -1,43 +0,0 @@ -# Home Assistant Add-on: Almond - -## Installation - -Follow these steps to get the add-on installed on your system: - -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. -2. Find the "Almond" add-on and click it. -3. Click on the "INSTALL" button. - -## How to use - -The basic thing to get the add-on running would be: - -1. Start the add-on. -2. Go to Home Assistant frontend -> **Configuration** -> **Integrations** - to configure Home Assistant to use this add-on. After starting, - it will be automatically discovered by Home Assistant. - -## Configuration - -This add-on has no additional configuration options. - -## Support - -Got questions? - -You have several options to get them answered: - -- The [Home Assistant Discord Chat Server][discord]. -- The Home Assistant [Community Forum][forum]. -- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit]. -- The [Almond Discord Chat Server][discordalmond]. -- The Almond [Community Forum][forumalmond]. - -In case you've found a bug, please [open an issue on our GitHub][issue]. - -[discord]: https://discord.gg/c5DvZ4e -[forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues -[reddit]: https://reddit.com/r/homeassistant -[discordalmond]: https://discord.gg/anthtR4 -[forumalmond]: https://community.almond.stanford.edu diff --git a/almond/Dockerfile b/almond/Dockerfile deleted file mode 100644 index 69679f70dd1..00000000000 --- a/almond/Dockerfile +++ /dev/null @@ -1,88 +0,0 @@ -ARG BUILD_FROM -FROM ${BUILD_FROM} - -# Base env settings -ENV \ - LANG="en_US.utf8" \ - THINGENGINE_HOME="/data/almond-server" \ - THINGENGINE_HAS_REVERSE_PROXY=true \ - THINGENGINE_HOST_BASED_AUTHENTICATION=insecure \ - THINGENGINE_IN_HOME_ASSISTANT_ADDON=true - -WORKDIR /opt/almond -ARG ALMOND_VERSION - -RUN \ - set -x \ - && apt-get update \ - && apt-get install -y --no-install-recommends \ - build-essential \ - libcanberra-dev \ - libcanberra0 \ - libpulse-dev \ - libatlas-base-dev \ - libatlas3-base \ - pkg-config \ - ca-certificates \ - git \ - gnupg \ - nginx \ - python-dev \ - software-properties-common \ - unzip \ - sqlite \ - coreutils \ - pulseaudio \ - pulseaudio-utils \ - gettext \ - zip \ - wget \ - gstreamer1.0-plugins-base-apps \ - gstreamer1.0-plugins-good \ - gstreamer1.0-pulseaudio \ - \ - && curl -sS https://deb.nodesource.com/gpgkey/nodesource.gpg.key \ - | apt-key add - \ - && echo "deb https://deb.nodesource.com/node_12.x buster main" \ - > /etc/apt/sources.list.d/nodesource.list \ - \ - && apt-get update \ - && apt-get install -y --no-install-recommends \ - nodejs \ - \ - && npm config set unsafe-perm \ - \ - && git clone -b "${ALMOND_VERSION}" --depth 1 https://github.com/stanford-oval/almond-server . \ - && npm ci \ - && npm install --no-package-lock --ignore-scripts snowboy@1.3.1 \ - && cd node_modules/snowboy/ \ - && PYTHON=python2 npx node-pre-gyp clean configure \ - && make -C build/ \ - && rm -fr /root/.cache \ - && rm -fr /root/.npm \ - && mkdir /root/.cache \ - \ - && apt-get purge -y --auto-remove \ - build-essential \ - libcanberra-dev \ - libpulse-dev \ - libatlas-base-dev \ - pkg-config \ - git \ - gnupg \ - python-dev \ - software-properties-common \ - \ - && rm -rf \ - /opt/almond/.[!.]* \ - /root/.cache \ - /root/.config \ - /tmp/.[!.]* \ - /tmp/* \ - /usr/local/share/.cache \ - /usr/local/share/.config \ - /usr/lib/nginx \ - /var/lib/apt/lists/* \ - /var/www - -COPY rootfs / diff --git a/almond/README.md b/almond/README.md deleted file mode 100644 index 729c9ec366f..00000000000 --- a/almond/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Home Assistant Add-on: Almond - -The Open-source, Privacy-Preserving Voice Assistant. - -![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield] - -[Almond] provides a complete solution to turn your Home Assistant -into a smart speaker. It supports playing music, controlling your -IoT, checking the weather, and other simple questions. - -To use Almond as a voice assistant, you should connect a microphone and speaker to the -device where Home Assistant is installed. - -**Note**: since version 2.0.0 of the add-on, the use of the separate -Ada add-on is not required. Almond includes built-in voice capabilities, -using the wake-word "computer". It is recommended to avoid using Ada -with Almond >= 2.0.0. - -[Almond]: https://almond.stanford.edu/ -[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg -[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg -[armhf-shield]: https://img.shields.io/badge/armhf-no-red.svg -[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg -[i386-shield]: https://img.shields.io/badge/i386-no-red.svg diff --git a/almond/build.json b/almond/build.json deleted file mode 100644 index b8280df7bc5..00000000000 --- a/almond/build.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "build_from": { - "aarch64": "homeassistant/aarch64-base-debian:buster", - "amd64": "homeassistant/amd64-base-debian:buster", - "armv7": "homeassistant/armv7-base-debian:buster" - }, - "args": { - "ALMOND_VERSION": "v2.0.1" - } -} diff --git a/almond/config.json b/almond/config.json deleted file mode 100644 index df666628dc1..00000000000 --- a/almond/config.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "Almond", - "version": "2.0.1", - "slug": "almond", - "description": "The open-source, privacy-preserving voice assistant", - "url": "https://github.com/home-assistant/hassio-addons/blob/master/almond", - "arch": ["armv7", "aarch64", "amd64"], - "init": false, - "discovery": ["almond"], - "ingress": true, - "audio": true, - "panel_icon": "mdi:comment-eye-outline", - "homeassistant": "0.102.0", - "homeassistant_api": true, - "image": "homeassistant/{arch}-addon-almond" -} diff --git a/almond/icon.png b/almond/icon.png deleted file mode 100644 index 9172330fd62..00000000000 Binary files a/almond/icon.png and /dev/null differ diff --git a/almond/logo.png b/almond/logo.png deleted file mode 100644 index 9172330fd62..00000000000 Binary files a/almond/logo.png and /dev/null differ diff --git a/almond/rootfs/etc/almond/default-prefs.db b/almond/rootfs/etc/almond/default-prefs.db deleted file mode 100644 index ba94f517928..00000000000 --- a/almond/rootfs/etc/almond/default-prefs.db +++ /dev/null @@ -1,7 +0,0 @@ -{ - "server-login": { - "password":"x", - "salt":"x", - "sqliteKeySalt":"x" - } -} diff --git a/almond/rootfs/etc/nginx/nginx.conf b/almond/rootfs/etc/nginx/nginx.conf deleted file mode 100644 index fc2709cb137..00000000000 --- a/almond/rootfs/etc/nginx/nginx.conf +++ /dev/null @@ -1,57 +0,0 @@ -worker_processes 1; -pid /var/run/nginx.pid; -error_log /dev/stdout info; -daemon off; - -events { - worker_connections 1024; -} - -http { - include mime.types; - default_type application/octet-stream; - sendfile on; - keepalive_timeout 65; - proxy_read_timeout 1200; - gzip on; - gzip_disable "msie6"; - - upstream backend { - ip_hash; - server 127.0.0.1:3000; - } - - map $http_upgrade $connection_upgrade { - default upgrade; - '' close; - } - - # API & Ingress - server { - listen 3001 default_server; - listen 8099 default_server; - listen [::]:3001 default_server; - listen [::]:8099 default_server; - - allow 172.30.32.1; - allow 172.30.32.2; - deny all; - - server_name _; - access_log /dev/stdout combined; - - client_max_body_size 4G; - keepalive_timeout 5; - - root /dev/null; - - location / { - proxy_redirect off; - proxy_pass http://backend; - - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - } - } -} diff --git a/almond/rootfs/etc/services.d/almond/finish b/almond/rootfs/etc/services.d/almond/finish deleted file mode 100644 index a29ced9a496..00000000000 --- a/almond/rootfs/etc/services.d/almond/finish +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/execlineb -S1 -# ============================================================================== -# Take down the S6 supervision tree based on service exit code -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } - -s6-svscanctl -t /var/run/s6/services diff --git a/almond/rootfs/etc/services.d/almond/register b/almond/rootfs/etc/services.d/almond/register deleted file mode 100755 index d03215d4bd5..00000000000 --- a/almond/rootfs/etc/services.d/almond/register +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Register Home Assistant skill with Almond -# ============================================================================== -declare access_token_expires -declare almond_config - -# Wait for Almond service to be available -bashio::net.wait_for 3000 - -# Calulcate token expire time value -access_token_expires="$(( - $(( - $(date +%s) + 60 * 60 * 24 * 365 * 5 - )) * 1000 -)).$(date +%N)" - -# Prepare Almond configuration payload -almond_config=$(\ - bashio::var.json \ - kind "io.home-assistant" \ - hassUrl "http://supervisor/core" \ - accessToken "${SUPERVISOR_TOKEN}" \ - refreshToken "" \ - accessTokenExpires "^${access_token_expires}" \ - isHassio "^true" \ -) - -# Create Home Assistant entry in Almond service -if curl \ - -f -s -X POST -H "Content-Type: application/json" \ - -d "${almond_config}" \ - "http://127.0.0.1:3000/api/devices/create" -then - bashio::log.info "Successfully register local Home Assistant on Almond" -else - bashio::log.error "Almond registration of local Home Assistant failed!" -fi diff --git a/almond/rootfs/etc/services.d/almond/run b/almond/rootfs/etc/services.d/almond/run deleted file mode 100644 index 0888d11d087..00000000000 --- a/almond/rootfs/etc/services.d/almond/run +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Start Almond service -# ============================================================================== -export THINGENGINE_BASE_URL - -# Set the Ingress URL as Almond base URL for correct handling -THINGENGINE_BASE_URL=$(bashio::addon.ingress_entry) - -mkdir -p /data/almond-server -if [ ! -f /data/almond-server/prefs.db ]; then - cp /etc/almond/default-prefs.db /data/almond-server/prefs.db -fi - -# Send out discovery information to Home Assistant -./discovery & - -# Register Home Assistant with Almond -./register & - -# Start Almond -cd /opt/almond || bashio::exit.nok "Failed to change directory to Almond" -exec node main.js diff --git a/almond/rootfs/etc/services.d/nginx/finish b/almond/rootfs/etc/services.d/nginx/finish deleted file mode 100644 index 5bb07a651c9..00000000000 --- a/almond/rootfs/etc/services.d/nginx/finish +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/execlineb -S1 -# ============================================================================== -# Take down the S6 supervision tree based on service exit code -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } - -s6-svscanctl -t /var/run/s6/services diff --git a/assist_microphone/CHANGELOG.md b/assist_microphone/CHANGELOG.md new file mode 100644 index 00000000000..927a0a5867c --- /dev/null +++ b/assist_microphone/CHANGELOG.md @@ -0,0 +1,15 @@ +# Changelog + +## 1.3.0 + +- Update to wyoming-satellite 1.3.0 to get support for timers +- Added configuration options for setting timer sound, repetitions and delay + +## 1.2.0 + +- Update to wyoming-satellite 1.2.0 + +## 1.0.0 + +- Initial release + diff --git a/assist_microphone/DOCS.md b/assist_microphone/DOCS.md new file mode 100644 index 00000000000..a1fe3bc61e4 --- /dev/null +++ b/assist_microphone/DOCS.md @@ -0,0 +1,79 @@ +# Assist Microphone + +Use [Assist](https://www.home-assistant.io/voice_control/) voice assistant with a USB microphone. For example, a USB webcam. + +## How to use + +After this add-on is installed and running, it will be automatically discovered +by the Wyoming integration in Home Assistant. To finish the setup, +click the following my button: + +[![Open your Home Assistant instance and start setting up a new integration.](https://my.home-assistant.io/badges/config_flow_start.svg)](https://my.home-assistant.io/redirect/config_flow_start/?domain=wyoming) + +Alternatively, you can install the Wyoming integration manually, see the +[Wyoming integration documentation](https://www.home-assistant.io/integrations/wyoming/) +for more information. + +## Configuration + +### Option: `awake_wav` + +Path to WAV file to play when wake word is detected (empty to disable, default is `/usr/src/sounds/awake.wav`). + +### Option: `done_wav` + +Path to WAV file to play when voice command is finished (empty to disable, default is `/usr/src/sounds/done.wav`). + +### Option: `timer_finished_wav` + +Path to WAV file to play when timer is finished (empty to disable, default is `/usr/src/sounds/timer_finished.wav`). + +### Option: `timer_repeat_count` + +Number of times to repeat `timer_finished_wav` (default is 3). + +### Option: `timer_repeat_delay` + +Delay before repeating `timer_finished_wav`, in seconds (default is 0.75). + +### Option: `noise_suppression` + +Noise suppression level (0 is disabled, 4 is max). Disabled by default. + +### Option: `auto_gain` + +Automatic volume boost for microphone (0 is disabled, 31 dbfs is max). Disabled by default. + +### Option: `mic_volume_multiplier` + +Multiply microphone volume by fixed value (1.0 = no change, 2.0 = twice as loud). 1.0 is the default. + +### Option: `sound_enabled` + +Enables or disables output audio. + +### Option: `sound_volume_multiplier` + +Multiply sound output volume by fixed value (1.0 = no change, 2.0 = twice as loud). 1.0 is the default. + +### Option: `debug_logging` + +Enable debug logging. + +## Support + +Got questions? + +You have several options to get them answered: + +- The [Home Assistant Discord Chat Server][discord]. +- The Home Assistant [Community Forum][forum]. +- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit] + +In case you've found an bug, please [open an issue on our GitHub][issue]. + +[discord]: https://discord.gg/c5DvZ4e +[forum]: https://community.home-assistant.io +[issue]: https://github.com/home-assistant/addons/issues +[reddit]: https://reddit.com/r/homeassistant +[repository]: https://github.com/hassio-addons/repository diff --git a/assist_microphone/Dockerfile b/assist_microphone/Dockerfile new file mode 100644 index 00000000000..9c6dab26370 --- /dev/null +++ b/assist_microphone/Dockerfile @@ -0,0 +1,38 @@ +ARG BUILD_FROM +FROM ${BUILD_FROM} + +# Set shell +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +WORKDIR /usr/src +ARG WYOMING_SATELLITE_VERSION +ENV PIP_BREAK_SYSTEM_PACKAGES=1 + +RUN \ + apt-get update \ + && apt-get install -y --no-install-recommends \ + netcat-traditional \ + libasound2-plugins \ + alsa-utils \ + python3 \ + python3-pip \ + \ + && pip3 install --no-cache-dir -U \ + setuptools \ + wheel \ + && pip3 install --no-cache-dir \ + "wyoming-satellite[webrtc] @ https://github.com/rhasspy/wyoming-satellite/archive/refs/tags/v${WYOMING_SATELLITE_VERSION}.tar.gz" \ + \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +COPY sounds/ ./sounds/ + +WORKDIR / +COPY rootfs / + +HEALTHCHECK --start-period=10m \ + CMD echo '{ "type": "describe" }' \ + | nc -w 1 localhost 10700 \ + | grep -q "assist" \ + || exit 1 diff --git a/assist_microphone/README.md b/assist_microphone/README.md new file mode 100644 index 00000000000..49c8f5de30d --- /dev/null +++ b/assist_microphone/README.md @@ -0,0 +1,13 @@ +# Home Assistant Add-on: Assist Microphone + +![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] + +Home Assistant add-on that uses a local USB microphone to control [Assist](https://www.home-assistant.io/voice_control/). + +Part of the [Year of Voice](https://www.home-assistant.io/blog/2022/12/20/year-of-voice/). + +[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg +[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg +[armhf-shield]: https://img.shields.io/badge/armhf-no-red.svg +[armv7-shield]: https://img.shields.io/badge/armv7-no-red.svg +[i386-shield]: https://img.shields.io/badge/i386-no-red.svg diff --git a/assist_microphone/build.yaml b/assist_microphone/build.yaml new file mode 100644 index 00000000000..0457e61b23d --- /dev/null +++ b/assist_microphone/build.yaml @@ -0,0 +1,9 @@ +--- +build_from: + amd64: ghcr.io/home-assistant/amd64-base-debian:bookworm + aarch64: ghcr.io/home-assistant/aarch64-base-debian:bookworm +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io +args: + WYOMING_SATELLITE_VERSION: 1.3.0 diff --git a/assist_microphone/config.yaml b/assist_microphone/config.yaml new file mode 100644 index 00000000000..62dabbbd770 --- /dev/null +++ b/assist_microphone/config.yaml @@ -0,0 +1,42 @@ +--- +version: 1.3.0 +slug: assist_microphone +name: Assist Microphone +description: Use Assist with local microphone +url: https://github.com/home-assistant/addons/blob/master/assist_microphone +hassio_api: true +arch: + - amd64 + - aarch64 +init: false +discovery: + - wyoming +map: + - share:ro +options: + awake_wav: "/usr/src/sounds/awake.wav" + done_wav: "/usr/src/sounds/done.wav" + timer_finished_wav: "/usr/src/sounds/timer_finished.wav" + timer_repeat_count: 3 + timer_repeat_delay: 0.75 + sound_enabled: true + noise_suppression: 0 + auto_gain: 0 + mic_volume_multiplier: 1.0 + sound_volume_multiplier: 1.0 + debug_logging: false +schema: + awake_wav: str + done_wav: str + timer_finished_wav: str + timer_repeat_count: int + timer_repeat_delay: float + sound_enabled: bool + noise_suppression: int + auto_gain: int + mic_volume_multiplier: float + sound_volume_multiplier: float + debug_logging: bool +audio: true +homeassistant: 2023.12.1 +image: homeassistant/{arch}-addon-assist_microphone diff --git a/mariadb/rootfs/etc/services.d/mariadb-lock/down b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/dependencies.d/base similarity index 100% rename from mariadb/rootfs/etc/services.d/mariadb-lock/down rename to assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/dependencies.d/base diff --git a/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/finish b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/finish new file mode 100755 index 00000000000..8558b9a95ea --- /dev/null +++ b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/finish @@ -0,0 +1,27 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Take down the S6 supervision tree when service fails +# s6-overlay docs: https://github.com/just-containers/s6-overlay +# ============================================================================== +# shellcheck disable=SC2155 +readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode + fi + [[ "${exit_code_signal}" -eq 15 ]] && exec /run/s6/basedir/bin/halt +elif [[ "${exit_code_service}" -ne 0 ]]; then + if [[ "${exit_code_container}" -eq 0 ]]; then + echo "${exit_code_service}" > /run/s6-linux-init-container-results/exitcode + fi + exec /run/s6/basedir/bin/halt +fi diff --git a/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/run b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/run new file mode 100755 index 00000000000..01aaedb7b5b --- /dev/null +++ b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/run @@ -0,0 +1,29 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start service +# ============================================================================== +extra_args=() +if bashio::config.true 'debug_logging'; then + extra_args+=('--debug') +fi + +if bashio::config.true 'sound_enabled'; then + extra_args+=('--snd-command' 'aplay -r 16000 -c 1 -f S16_LE -t raw') +fi + +exec python3 -m wyoming_satellite \ + --name 'assist microphone' \ + --uri 'tcp://0.0.0.0:10700' \ + --mic-command 'arecord -r 16000 -c 1 -f S16_LE -t raw' \ + --snd-command-rate 16000 \ + --awake-wav "$(bashio::config 'awake_wav')" \ + --done-wav "$(bashio::config 'done_wav')" \ + --timer-finished-wav "$(bashio::config 'timer_finished_wav')" \ + --timer-finished-wav-repeat "$(bashio::config 'timer_repeat_count')" "$(bashio::config 'timer_repeat_delay')" \ + --mic-volume-multiplier "$(bashio::config 'mic_volume_multiplier')" \ + --snd-volume-multiplier "$(bashio::config 'sound_volume_multiplier')" \ + --mic-auto-gain "$(bashio::config 'auto_gain')" \ + --mic-noise-suppression "$(bashio::config 'noise_suppression')" \ + --no-zeroconf "${extra_args[@]}" diff --git a/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/type b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/type new file mode 100644 index 00000000000..1780f9f44ef --- /dev/null +++ b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/assist_microphone/type @@ -0,0 +1 @@ +longrun \ No newline at end of file diff --git a/mariadb/rootfs/etc/services.d/mariadb-lock/finish b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/discovery/dependencies.d/assist_microphone similarity index 100% rename from mariadb/rootfs/etc/services.d/mariadb-lock/finish rename to assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/discovery/dependencies.d/assist_microphone diff --git a/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/discovery/run b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/discovery/run new file mode 100755 index 00000000000..fa40eecd987 --- /dev/null +++ b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/discovery/run @@ -0,0 +1,25 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Sends discovery information to Home Assistant. +# ============================================================================== +declare config + +# Wait for satellite to become available +bash -c \ + "until + echo '{ \"type\": \"describe\" }' + > /dev/tcp/localhost/10700; do sleep 0.5; + done" > /dev/null 2>&1 || true; + +config=$(\ + bashio::var.json \ + uri "tcp://$(hostname):10700" \ +) + +if bashio::discovery "wyoming" "${config}" > /dev/null; then + bashio::log.info "Successfully sent discovery information to Home Assistant." +else + bashio::log.error "Discovery message to Home Assistant failed!" +fi diff --git a/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/discovery/type b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/discovery/type new file mode 100644 index 00000000000..3d92b15f2d5 --- /dev/null +++ b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/discovery/type @@ -0,0 +1 @@ +oneshot \ No newline at end of file diff --git a/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/discovery/up b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/discovery/up new file mode 100755 index 00000000000..31b0a0205b5 --- /dev/null +++ b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/discovery/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/discovery/run \ No newline at end of file diff --git a/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/assist_microphone b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/assist_microphone new file mode 100644 index 00000000000..e69de29bb2d diff --git a/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/discovery b/assist_microphone/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/discovery new file mode 100644 index 00000000000..e69de29bb2d diff --git a/assist_microphone/sounds/awake.wav b/assist_microphone/sounds/awake.wav new file mode 100644 index 00000000000..c0ef2d5de41 Binary files /dev/null and b/assist_microphone/sounds/awake.wav differ diff --git a/assist_microphone/sounds/done.wav b/assist_microphone/sounds/done.wav new file mode 100644 index 00000000000..43ad9b640d8 Binary files /dev/null and b/assist_microphone/sounds/done.wav differ diff --git a/assist_microphone/sounds/timer_finished.wav b/assist_microphone/sounds/timer_finished.wav new file mode 100644 index 00000000000..40a97bca6c5 Binary files /dev/null and b/assist_microphone/sounds/timer_finished.wav differ diff --git a/assist_microphone/translations/en.yaml b/assist_microphone/translations/en.yaml new file mode 100644 index 00000000000..411674d7861 --- /dev/null +++ b/assist_microphone/translations/en.yaml @@ -0,0 +1,50 @@ +--- +configuration: + awake_wav: + name: Awake WAV + description: >- + Path to WAV file to play when wake word is detected (empty to disable). + done_wav: + name: Done WAV + description: >- + Path to WAV file to play when voice command is finished (empty to + disable). + timer_finished_wav: + name: Timer Finished WAV + description: >- + Path to WAV file to play when timer is finished (empty to disable, + default is /usr/src/sounds/timer_finished.wav). + timer_repeat_count: + name: Timer Finished WAV Repetition Count + description: >- + Number of times to repeat timer_finished_wav (default is 3). + timer_repeat_delay: + name: Timer Repetition Delay + description: >- + Delay before repeating timer_finished_wav, in seconds (default is 0.75). + noise_suppression: + name: Noise suppression + description: >- + Noise suppression level (0 is disabled, 4 is max). + auto_gain: + name: Auto gain + description: >- + Automatic volume boost for microphone (0 is disabled, 31 is max). + mic_volume_multiplier: + name: Microphone volume multiplier + description: >- + Multiply microphone volume by fixed value (1.0 = no change, 2.0 = twice as + loud). + sound_enabled: + name: Sound enabled + description: >- + Enables or disables output audio. + sound_volume_multiplier: + name: Sound volume multiplier + description: >- + Multiply sound output volume by fixed value (1.0 = no change, 2.0 = twice + as loud). 1.0 is the default. + debug_logging: + name: Debug logging + description: >- + Enable debug logging. diff --git a/cec_scan/CHANGELOG.md b/cec_scan/CHANGELOG.md index 7f4dfe2d82d..c20a47d9b32 100644 --- a/cec_scan/CHANGELOG.md +++ b/cec_scan/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 3.0 + +- Using the Upstream Linux support only +- Using s6-overlay style +- Update to Alpine 3.14 + ## 2.4 - Use new `video` feature of Supervisor 199 diff --git a/cec_scan/DOCS.md b/cec_scan/DOCS.md index eacadf65cd0..805b41b0e40 100644 --- a/cec_scan/DOCS.md +++ b/cec_scan/DOCS.md @@ -4,7 +4,7 @@ Follow these steps to get the add-on installed on your system: -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. 2. Find the "CEC Scanner" add-on and click it. 3. Click on the "INSTALL" button. @@ -31,4 +31,4 @@ In case you've found a bug, please [open an issue on our GitHub][issue]. [forum]: https://community.home-assistant.io [issue]: https://github.com/home-assistant/hassio-addons/issues [reddit]: https://reddit.com/r/homeassistant -[repository]: https://github.com/hassio-addons/repository +[repository]: https://github.com/addons/repository diff --git a/cec_scan/Dockerfile b/cec_scan/Dockerfile index f9c07ff71fb..c4c6f9a2fd9 100644 --- a/cec_scan/Dockerfile +++ b/cec_scan/Dockerfile @@ -1,21 +1,11 @@ ARG BUILD_FROM FROM $BUILD_FROM -# Set shell -SHELL ["/bin/bash", "-o", "pipefail", "-c"] - -# Meta -WORKDIR /usr/src -ARG BUILD_ARCH -ARG LIBCEC_VERSION - # Build libcec for HDMI-CEC -COPY data/libcec.patch /usr/src/ +ARG LIBCEC_VERSION +WORKDIR /usr/src RUN \ - if [[ "armhf armv7 aarch64" = *"$BUILD_ARCH"* ]]; then \ - apk add --no-cache raspberrypi-dev raspberrypi-libs; \ - fi \ - && apk add --no-cache \ + apk add --no-cache \ eudev-libs\ p8-platform \ && apk add --no-cache --virtual .build-dependencies \ @@ -27,38 +17,18 @@ RUN \ swig \ linux-headers \ && git clone --depth 1 -b libcec-${LIBCEC_VERSION} \ - "https://github.com/Pulse-Eight/libcec" /usr/src/libcec \ - && cd /usr/src/libcec \ - && git apply /usr/src/libcec.patch \ - && mkdir -p /usr/src/libcec/build \ - && cd /usr/src/libcec/build \ - && if [[ "armhf armv7 aarch64" = *"$BUILD_ARCH"* ]]; then \ - cmake \ - -DCMAKE_INSTALL_PREFIX:PATH=/usr/local \ - -DRPI_INCLUDE_DIR=/opt/vc/include \ - -DRPI_LIB_DIR=/opt/vc/lib \ - -DHAVE_EXYNOS_API=1 \ - -DHAVE_AOCEC_API=1 \ - -DHAVE_LINUX_API=1 \ - ..; \ - else \ - cmake \ - -DCMAKE_INSTALL_PREFIX:PATH=/usr/local \ - -DHAVE_LINUX_API=1 \ - ..; \ - fi \ + "https://github.com/Pulse-Eight/libcec" libcec \ + && mkdir -p libcec/build \ + && cd libcec/build \ + && cmake \ + -DCMAKE_INSTALL_PREFIX:PATH=/usr/local \ + -DHAVE_LINUX_API=1 \ + .. \ && make -j$(nproc) \ && make install \ && apk del --no-cache .build-dependencies \ - && if [[ "armhf armv7 aarch64" = *"$BUILD_ARCH"* ]]; then \ - apk del --no-cache raspberrypi-dev; \ - fi \ && rm -rf /usr/src/* -ENV LD_LIBRARY_PATH=/opt/vc/lib:${LD_LIBRARY_PATH} - # Copy data -COPY data/run.sh / - WORKDIR / -CMD [ "/run.sh" ] +COPY rootfs / diff --git a/cec_scan/build.json b/cec_scan/build.json deleted file mode 100644 index 46c2a5bfa0a..00000000000 --- a/cec_scan/build.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "build_from": { - "aarch64": "homeassistant/aarch64-base:3.11", - "amd64": "homeassistant/amd64-base:3.11", - "armhf": "homeassistant/armhf-base:3.11", - "armv7": "homeassistant/armv7-base:3.11", - "i386": "homeassistant/i386-base:3.11" - }, - "args": { - "LIBCEC_VERSION": "4.0.3" - } -} diff --git a/cec_scan/build.yaml b/cec_scan/build.yaml new file mode 100644 index 00000000000..f7aeba897e4 --- /dev/null +++ b/cec_scan/build.yaml @@ -0,0 +1,12 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base:3.14 + amd64: ghcr.io/home-assistant/amd64-base:3.14 + armhf: ghcr.io/home-assistant/armhf-base:3.14 + armv7: ghcr.io/home-assistant/armv7-base:3.14 + i386: ghcr.io/home-assistant/i386-base:3.14 +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io +args: + LIBCEC_VERSION: 6.0.2 diff --git a/cec_scan/config.json b/cec_scan/config.json deleted file mode 100644 index f9d31811130..00000000000 --- a/cec_scan/config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "CEC Scanner", - "version": "2.4", - "slug": "cec_scan", - "description": "Scan for HDMI CEC devices", - "url": "https://github.com/home-assistant/hassio-addons/tree/master/cec_scan", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "startup": "once", - "boot": "manual", - "video": true, - "options": {}, - "schema": {}, - "image": "homeassistant/{arch}-addon-cec_scan" -} diff --git a/cec_scan/config.yaml b/cec_scan/config.yaml new file mode 100644 index 00000000000..fb91aed4c29 --- /dev/null +++ b/cec_scan/config.yaml @@ -0,0 +1,19 @@ +--- +version: "3.0" +slug: cec_scan +name: CEC Scanner +url: https://github.com/home-assistant/addons/tree/master/cec_scan +arch: + - armhf + - armv7 + - aarch64 + - amd64 + - i386 +boot: manual +description: Scan for HDMI CEC devices +image: homeassistant/{arch}-addon-cec_scan +options: {} +schema: {} +startup: once +video: true +init: false diff --git a/cec_scan/data/libcec.patch b/cec_scan/data/libcec.patch deleted file mode 100644 index 49af7eadf31..00000000000 --- a/cec_scan/data/libcec.patch +++ /dev/null @@ -1,887 +0,0 @@ -From 467cc79fd289403e7d4f6e4e817b906c0c0027dd Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Wed, 6 Sep 2017 17:37:05 +0200 -Subject: [PATCH] Add Linux CEC Adapter - ---- - docs/README.linux.md | 6 + - include/cectypes.h | 11 + - src/libcec/CECTypeUtils.h | 2 + - src/libcec/CMakeLists.txt | 2 + - src/libcec/adapter/AdapterFactory.cpp | 26 +- - .../Linux/LinuxCECAdapterCommunication.cpp | 438 ++++++++++++++++++ - .../Linux/LinuxCECAdapterCommunication.h | 95 ++++ - .../Linux/LinuxCECAdapterDetection.cpp | 50 ++ - .../adapter/Linux/LinuxCECAdapterDetection.h | 51 ++ - src/libcec/cmake/CheckPlatformSupport.cmake | 12 + - src/libcec/cmake/DisplayPlatformSupport.cmake | 6 + - src/libcec/env.h.in | 3 + - 12 files changed, 700 insertions(+), 2 deletions(-) - create mode 100644 src/libcec/adapter/Linux/LinuxCECAdapterCommunication.cpp - create mode 100644 src/libcec/adapter/Linux/LinuxCECAdapterCommunication.h - create mode 100644 src/libcec/adapter/Linux/LinuxCECAdapterDetection.cpp - create mode 100644 src/libcec/adapter/Linux/LinuxCECAdapterDetection.h - -diff --git a/docs/README.linux.md b/docs/README.linux.md -index c59fb80..e8053cc 100644 ---- a/docs/README.linux.md -+++ b/docs/README.linux.md -@@ -51,5 +51,11 @@ Pass the argument `-DHAVE_TDA995X_API=1` to the cmake command in the compilation - cmake -DHAVE_TDA995X_API=1 .. - ``` - -+### Linux CEC Framework (v4.10+) -+Pass the argument `-DHAVE_LINUX_API=1` to the cmake command in the compilation instructions: -+``` -+cmake -DHAVE_LINUX_API=1 .. -+``` -+ - ### Debian / Ubuntu .deb packaging - See [docs/README.debian.md](README.debian.md). -\ No newline at end of file -diff --git a/include/cectypes.h b/include/cectypes.h -index 9c91842..2c32e4d 100644 ---- a/include/cectypes.h -+++ b/include/cectypes.h -@@ -281,6 +281,16 @@ namespace CEC { - */ - #define CEC_MAX_DATA_PACKET_SIZE (16 * 4) - -+/*! -+ * the path to use for the Linux CEC device -+ */ -+#define CEC_LINUX_PATH "/dev/cec0" -+ -+/*! -+ * the name of the virtual COM port to use for the Linux' CEC wire -+ */ -+#define CEC_LINUX_VIRTUAL_COM "Linux" -+ - /*! - * the path to use for the AOCEC HDMI CEC device - */ -@@ -861,6 +871,7 @@ typedef enum cec_adapter_type - ADAPTERTYPE_RPI = 0x100, - ADAPTERTYPE_TDA995x = 0x200, - ADAPTERTYPE_EXYNOS = 0x300, -+ ADAPTERTYPE_LINUX = 0x400, - ADAPTERTYPE_AOCEC = 0x500 - } cec_adapter_type; - -diff --git a/src/libcec/CECTypeUtils.h b/src/libcec/CECTypeUtils.h -index 25c1c6e..15f9543 100644 ---- a/src/libcec/CECTypeUtils.h -+++ b/src/libcec/CECTypeUtils.h -@@ -766,6 +766,8 @@ namespace CEC - return "Raspberry Pi"; - case ADAPTERTYPE_TDA995x: - return "TDA995x"; -+ case ADAPTERTYPE_LINUX: -+ return "Linux"; - default: - return "unknown"; - } -diff --git a/src/libcec/CMakeLists.txt b/src/libcec/CMakeLists.txt -index 6baee69..74fe5f3 100644 ---- a/src/libcec/CMakeLists.txt -+++ b/src/libcec/CMakeLists.txt -@@ -89,6 +89,8 @@ set(CEC_HEADERS devices/CECRecordingDevice.h - adapter/Exynos/ExynosCEC.h - adapter/Exynos/ExynosCECAdapterDetection.h - adapter/Exynos/ExynosCECAdapterCommunication.h -+ adapter/Linux/LinuxCECAdapterDetection.h -+ adapter/Linux/LinuxCECAdapterCommunication.h - adapter/AOCEC/AOCEC.h - adapter/AOCEC/AOCECAdapterDetection.h - adapter/AOCEC/AOCECAdapterCommunication.h -diff --git a/src/libcec/adapter/AdapterFactory.cpp b/src/libcec/adapter/AdapterFactory.cpp -index 91195ea..323c272 100644 ---- a/src/libcec/adapter/AdapterFactory.cpp -+++ b/src/libcec/adapter/AdapterFactory.cpp -@@ -58,6 +58,11 @@ - #include "Exynos/ExynosCECAdapterCommunication.h" - #endif - -+#if defined(HAVE_LINUX_API) -+#include "Linux/LinuxCECAdapterDetection.h" -+#include "Linux/LinuxCECAdapterCommunication.h" -+#endif -+ - #if defined(HAVE_AOCEC_API) - #include "AOCEC/AOCECAdapterDetection.h" - #include "AOCEC/AOCECAdapterCommunication.h" -@@ -131,6 +136,18 @@ int8_t CAdapterFactory::DetectAdapters(cec_adapter_descriptor *deviceList, uint8 - } - #endif - -+#if defined(HAVE_LINUX_API) -+ if (iAdaptersFound < iBufSize && CLinuxCECAdapterDetection::FindAdapter()) -+ { -+ snprintf(deviceList[iAdaptersFound].strComPath, sizeof(deviceList[iAdaptersFound].strComPath), CEC_LINUX_PATH); -+ snprintf(deviceList[iAdaptersFound].strComName, sizeof(deviceList[iAdaptersFound].strComName), CEC_LINUX_VIRTUAL_COM); -+ deviceList[iAdaptersFound].iVendorId = 0; -+ deviceList[iAdaptersFound].iProductId = 0; -+ deviceList[iAdaptersFound].adapterType = ADAPTERTYPE_LINUX; -+ iAdaptersFound++; -+ } -+#endif -+ - #if defined(HAVE_AOCEC_API) - if (iAdaptersFound < iBufSize && CAOCECAdapterDetection::FindAdapter()) - { -@@ -144,7 +161,7 @@ int8_t CAdapterFactory::DetectAdapters(cec_adapter_descriptor *deviceList, uint8 - #endif - - --#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_AOCEC_API) -+#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_LINUX_API) && !defined(HAVE_AOCEC_API) - #error "libCEC doesn't have support for any type of adapter. please check your build system or configuration" - #endif - -@@ -163,6 +180,11 @@ IAdapterCommunication *CAdapterFactory::GetInstance(const char *strPort, uint16_ - return new CExynosCECAdapterCommunication(m_lib->m_cec); - #endif - -+#if defined(HAVE_LINUX_API) -+ if (!strcmp(strPort, CEC_LINUX_VIRTUAL_COM)) -+ return new CLinuxCECAdapterCommunication(m_lib->m_cec); -+#endif -+ - #if defined(HAVE_AOCEC_API) - if (!strcmp(strPort, CEC_AOCEC_VIRTUAL_COM)) - return new CAOCECAdapterCommunication(m_lib->m_cec); -@@ -177,7 +199,7 @@ IAdapterCommunication *CAdapterFactory::GetInstance(const char *strPort, uint16_ - return new CUSBCECAdapterCommunication(m_lib->m_cec, strPort, iBaudRate); - #endif - --#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) && !defined(HAVE_AOCEC_API) -+#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) && !defined(HAVE_LINUX_API) && !defined(HAVE_AOCEC_API) - return NULL; - #endif - } -diff --git a/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.cpp b/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.cpp -new file mode 100644 -index 0000000..6a28835 ---- /dev/null -+++ b/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.cpp -@@ -0,0 +1,438 @@ -+/* -+ * This file is part of the libCEC(R) library. -+ * -+ * libCEC Linux CEC Adapter is Copyright (C) 2017-2019 Jonas Karlman -+ * based heavily on: -+ * libCEC AOCEC Code is Copyright (C) 2016 Gerald Dachs -+ * libCEC Exynos Code is Copyright (C) 2014 Valentin Manea -+ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved. -+ * libCEC(R) is an original work, containing original code. -+ * -+ * libCEC(R) is a trademark of Pulse-Eight Limited. -+ * -+ * This program is dual-licensed; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * -+ * Alternatively, you can license this library under a commercial license, -+ * please contact Pulse-Eight Licensing for more information. -+ * -+ * For more information contact: -+ * Pulse-Eight Licensing -+ * http://www.pulse-eight.com/ -+ * http://www.pulse-eight.net/ -+ */ -+ -+#include "env.h" -+#include -+#include -+ -+#if defined(HAVE_LINUX_API) -+#include "LinuxCECAdapterCommunication.h" -+#include "CECTypeUtils.h" -+#include "LibCEC.h" -+#include "p8-platform/util/buffer.h" -+#include -+ -+using namespace CEC; -+using namespace P8PLATFORM; -+ -+#define LIB_CEC m_callback->GetLib() -+ -+// Required capabilities -+#define CEC_LINUX_CAPABILITIES (CEC_CAP_LOG_ADDRS | CEC_CAP_TRANSMIT | CEC_CAP_PASSTHROUGH) -+ -+CLinuxCECAdapterCommunication::CLinuxCECAdapterCommunication(IAdapterCommunicationCallback *callback) -+ : IAdapterCommunication(callback) -+{ -+ m_fd = INVALID_SOCKET_VALUE; -+} -+ -+CLinuxCECAdapterCommunication::~CLinuxCECAdapterCommunication(void) -+{ -+ Close(); -+} -+ -+bool CLinuxCECAdapterCommunication::Open(uint32_t UNUSED(iTimeoutMs), bool UNUSED(bSkipChecks), bool bStartListening) -+{ -+ if (IsOpen()) -+ Close(); -+ -+ if ((m_fd = open(CEC_LINUX_PATH, O_RDWR)) >= 0) -+ { -+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Open - m_fd=%d bStartListening=%d", m_fd, bStartListening); -+ -+ // Ensure the CEC device supports required capabilities -+ struct cec_caps caps = {}; -+ if (ioctl(m_fd, CEC_ADAP_G_CAPS, &caps) || (caps.capabilities & CEC_LINUX_CAPABILITIES) != CEC_LINUX_CAPABILITIES) -+ { -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_G_CAPS failed - capabilities=%02x errno=%d", caps.capabilities, errno); -+ Close(); -+ return false; -+ } -+ -+ if (!bStartListening) -+ { -+ Close(); -+ return true; -+ } -+ -+ // This is an exclusive follower, in addition put the CEC device into passthrough mode -+ uint32_t mode = CEC_MODE_INITIATOR | CEC_MODE_EXCL_FOLLOWER_PASSTHRU; -+ if (ioctl(m_fd, CEC_S_MODE, &mode)) -+ { -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Open - ioctl CEC_S_MODE failed - errno=%d", errno); -+ Close(); -+ return false; -+ } -+ -+ uint16_t addr; -+ if (ioctl(m_fd, CEC_ADAP_G_PHYS_ADDR, &addr)) -+ { -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_G_PHYS_ADDR failed - errno=%d", errno); -+ Close(); -+ return false; -+ } -+ -+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_G_PHYS_ADDR - addr=%04x", addr); -+ -+ if (addr == CEC_PHYS_ADDR_INVALID) -+ LIB_CEC->AddLog(CEC_LOG_WARNING, "CLinuxCECAdapterCommunication::Open - physical address is invalid"); -+ -+ // Clear existing logical addresses and set the CEC device to the unconfigured state -+ struct cec_log_addrs log_addrs = {}; -+ if (ioctl(m_fd, CEC_ADAP_S_LOG_ADDRS, &log_addrs)) -+ { -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_S_LOG_ADDRS failed - errno=%d", errno); -+ Close(); -+ return false; -+ } -+ -+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_S_LOG_ADDRS - log_addr_mask=%04x num_log_addrs=%u", log_addrs.log_addr_mask, log_addrs.num_log_addrs); -+ -+ // Set logical address to unregistered, without any logical address configured no messages is transmitted or received -+ log_addrs = {}; -+ log_addrs.cec_version = CEC_OP_CEC_VERSION_1_4; -+ log_addrs.vendor_id = CEC_VENDOR_PULSE_EIGHT; -+ log_addrs.num_log_addrs = 1; -+ log_addrs.flags = CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK; -+ log_addrs.log_addr[0] = CEC_LOG_ADDR_UNREGISTERED; -+ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_SWITCH; -+ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED; -+ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH; -+ if (ioctl(m_fd, CEC_ADAP_S_LOG_ADDRS, &log_addrs)) -+ { -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_S_LOG_ADDRS failed - errno=%d", errno); -+ Close(); -+ return false; -+ } -+ -+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Open - ioctl CEC_ADAP_S_LOG_ADDRS - log_addr_mask=%04x num_log_addrs=%u", log_addrs.log_addr_mask, log_addrs.num_log_addrs); -+ -+ if (CreateThread()) -+ return true; -+ -+ Close(); -+ } -+ -+ return false; -+} -+ -+void CLinuxCECAdapterCommunication::Close(void) -+{ -+ StopThread(0); -+ -+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Close - m_fd=%d", m_fd); -+ -+ close(m_fd); -+ m_fd = INVALID_SOCKET_VALUE; -+} -+ -+bool CLinuxCECAdapterCommunication::IsOpen(void) -+{ -+ return m_fd != INVALID_SOCKET_VALUE; -+} -+ -+cec_adapter_message_state CLinuxCECAdapterCommunication::Write(const cec_command &data, bool &bRetry, uint8_t UNUSED(iLineTimeout), bool UNUSED(bIsReply)) -+{ -+ if (IsOpen()) -+ { -+ struct cec_msg msg; -+ cec_msg_init(&msg, data.initiator, data.destination); -+ -+ if (data.opcode_set) -+ { -+ msg.msg[msg.len++] = data.opcode; -+ -+ if (data.parameters.size) -+ { -+ memcpy(&msg.msg[msg.len], data.parameters.data, data.parameters.size); -+ msg.len += data.parameters.size; -+ } -+ } -+ -+ if (ioctl(m_fd, CEC_TRANSMIT, &msg)) -+ { -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Write - ioctl CEC_TRANSMIT failed - tx_status=%02x errno=%d", msg.tx_status, errno); -+ return ADAPTER_MESSAGE_STATE_ERROR; -+ } -+ -+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Write - ioctl CEC_TRANSMIT - tx_status=%02x len=%d addr=%02x opcode=%02x", msg.tx_status, msg.len, msg.msg[0], cec_msg_opcode(&msg)); -+ -+ // The CEC driver will make re-transmission attempts -+ bRetry = false; -+ -+ if (msg.tx_status & CEC_TX_STATUS_OK) -+ return ADAPTER_MESSAGE_STATE_SENT_ACKED; -+ -+ if (msg.tx_status & CEC_TX_STATUS_NACK) -+ return ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED; -+ -+ return ADAPTER_MESSAGE_STATE_ERROR; -+ } -+ -+ return ADAPTER_MESSAGE_STATE_UNKNOWN; -+} -+ -+bool CLinuxCECAdapterCommunication::SetLogicalAddresses(const cec_logical_addresses &addresses) -+{ -+ if (IsOpen()) -+ { -+ struct cec_log_addrs log_addrs = {}; -+ if (ioctl(m_fd, CEC_ADAP_G_LOG_ADDRS, &log_addrs)) -+ { -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::SetLogicalAddresses - ioctl CEC_ADAP_G_LOG_ADDRS failed - errno=%d", errno); -+ return false; -+ } -+ -+ // TODO: Claiming a logical address will only work when CEC device has a valid physical address -+ -+ // Clear existing logical addresses and set the CEC device to the unconfigured state -+ if (log_addrs.num_log_addrs) -+ { -+ log_addrs = {}; -+ if (ioctl(m_fd, CEC_ADAP_S_LOG_ADDRS, &log_addrs)) -+ { -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::SetLogicalAddresses - ioctl CEC_ADAP_S_LOG_ADDRS failed - errno=%d", errno); -+ return false; -+ } -+ -+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::SetLogicalAddresses - ioctl CEC_ADAP_S_LOG_ADDRS - log_addr_mask=%04x num_log_addrs=%u", log_addrs.log_addr_mask, log_addrs.num_log_addrs); -+ } -+ -+ if (!addresses.IsEmpty()) -+ { -+ // NOTE: This can only be configured when num_log_addrs > 0 -+ // and gets reset when num_log_addrs = 0 -+ log_addrs.cec_version = CEC_OP_CEC_VERSION_1_4; -+ log_addrs.vendor_id = CEC_VENDOR_PULSE_EIGHT; -+ -+ // TODO: Support more then the primary logical address -+ log_addrs.num_log_addrs = 1; -+ log_addrs.log_addr[0] = addresses.primary; -+ -+ switch (addresses.primary) -+ { -+ case CECDEVICE_AUDIOSYSTEM: -+ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM; -+ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_AUDIOSYSTEM; -+ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM; -+ break; -+ case CECDEVICE_PLAYBACKDEVICE1: -+ case CECDEVICE_PLAYBACKDEVICE2: -+ case CECDEVICE_PLAYBACKDEVICE3: -+ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_PLAYBACK; -+ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_PLAYBACK; -+ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_PLAYBACK; -+ break; -+ case CECDEVICE_RECORDINGDEVICE1: -+ case CECDEVICE_RECORDINGDEVICE2: -+ case CECDEVICE_RECORDINGDEVICE3: -+ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_RECORD; -+ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_RECORD; -+ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_RECORD; -+ break; -+ case CECDEVICE_TUNER1: -+ case CECDEVICE_TUNER2: -+ case CECDEVICE_TUNER3: -+ case CECDEVICE_TUNER4: -+ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_TUNER; -+ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_TUNER; -+ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_TUNER; -+ break; -+ case CECDEVICE_TV: -+ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_TV; -+ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_TV; -+ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_TV; -+ break; -+ default: -+ log_addrs.primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_SWITCH; -+ log_addrs.log_addr_type[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED; -+ log_addrs.all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH; -+ break; -+ } -+ } -+ else -+ log_addrs.num_log_addrs = 0; -+ -+ if (ioctl(m_fd, CEC_ADAP_S_LOG_ADDRS, &log_addrs)) -+ { -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::SetLogicalAddresses - ioctl CEC_ADAP_S_LOG_ADDRS failed - errno=%d", errno); -+ return false; -+ } -+ -+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::SetLogicalAddresses - ioctl CEC_ADAP_S_LOG_ADDRS - log_addr_mask=%04x num_log_addrs=%u", log_addrs.log_addr_mask, log_addrs.num_log_addrs); -+ -+ if (log_addrs.num_log_addrs && !log_addrs.log_addr_mask) -+ return false; -+ -+ return true; -+ } -+ -+ return false; -+} -+ -+cec_logical_addresses CLinuxCECAdapterCommunication::GetLogicalAddresses(void) const -+{ -+ cec_logical_addresses addresses; -+ addresses.Clear(); -+ -+ if (m_fd != INVALID_SOCKET_VALUE) -+ { -+ struct cec_log_addrs log_addrs = {}; -+ if (ioctl(m_fd, CEC_ADAP_G_LOG_ADDRS, &log_addrs)) -+ { -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::GetLogicalAddresses - ioctl CEC_ADAP_G_LOG_ADDRS failed - errno=%d", errno); -+ return addresses; -+ } -+ -+ for (int i = 0; i < log_addrs.num_log_addrs; i++) -+ addresses.Set(cec_logical_address(log_addrs.log_addr[i])); -+ } -+ -+ return addresses; -+} -+ -+uint16_t CLinuxCECAdapterCommunication::GetPhysicalAddress(void) -+{ -+ if (IsOpen()) -+ { -+ uint16_t addr; -+ if (!ioctl(m_fd, CEC_ADAP_G_PHYS_ADDR, &addr)) -+ return addr; -+ -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::GetPhysicalAddress - ioctl CEC_ADAP_G_PHYS_ADDR failed - errno=%d", errno); -+ } -+ -+ return CEC_INVALID_PHYSICAL_ADDRESS; -+} -+ -+cec_vendor_id CLinuxCECAdapterCommunication::GetVendorId(void) -+{ -+ if (IsOpen()) -+ { -+ struct cec_log_addrs log_addrs = {}; -+ if (!ioctl(m_fd, CEC_ADAP_G_LOG_ADDRS, &log_addrs)) -+ return cec_vendor_id(log_addrs.vendor_id); -+ -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::GetVendorId - ioctl CEC_ADAP_G_LOG_ADDRS failed - errno=%d", errno); -+ } -+ -+ return CEC_VENDOR_UNKNOWN; -+} -+ -+void *CLinuxCECAdapterCommunication::Process(void) -+{ -+ CTimeout phys_addr_timeout; -+ bool phys_addr_changed = false; -+ uint16_t phys_addr = CEC_INVALID_PHYSICAL_ADDRESS; -+ fd_set rd_fds; -+ fd_set ex_fds; -+ -+ while (!IsStopped()) -+ { -+ struct timeval timeval = {}; -+ timeval.tv_sec = 1; -+ -+ FD_ZERO(&rd_fds); -+ FD_ZERO(&ex_fds); -+ FD_SET(m_fd, &rd_fds); -+ FD_SET(m_fd, &ex_fds); -+ -+ if (select(m_fd + 1, &rd_fds, NULL, &ex_fds, &timeval) < 0) -+ { -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Process - select failed - errno=%d", errno); -+ break; -+ } -+ -+ if (FD_ISSET(m_fd, &ex_fds)) -+ { -+ struct cec_event ev = {}; -+ if (ioctl(m_fd, CEC_DQEVENT, &ev)) -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Process - ioctl CEC_DQEVENT failed - errno=%d", errno); -+ else if (ev.event == CEC_EVENT_STATE_CHANGE) -+ { -+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Process - CEC_DQEVENT - CEC_EVENT_STATE_CHANGE - log_addr_mask=%04x phys_addr=%04x", ev.state_change.log_addr_mask, ev.state_change.phys_addr); -+ -+ // TODO: handle ev.state_change.log_addr_mask change -+ -+ phys_addr = ev.state_change.phys_addr; -+ phys_addr_changed = true; -+ -+ if (ev.state_change.phys_addr == CEC_PHYS_ADDR_INVALID) -+ { -+ // Debounce change to invalid physical address with 2 seconds because -+ // EDID refresh and other events may cause short periods of invalid physical address -+ phys_addr_timeout.Init(2000); -+ } -+ else -+ { -+ // Debounce change to valid physical address with 500 ms when no logical address have been claimed -+ phys_addr_timeout.Init(ev.state_change.log_addr_mask ? 0 : 500); -+ } -+ } -+ } -+ -+ if (phys_addr_changed && !phys_addr_timeout.TimeLeft() && !IsStopped()) -+ { -+ phys_addr_changed = false; -+ m_callback->HandlePhysicalAddressChanged(phys_addr); -+ } -+ -+ if (FD_ISSET(m_fd, &rd_fds)) -+ { -+ struct cec_msg msg = {}; -+ if (ioctl(m_fd, CEC_RECEIVE, &msg)) -+ LIB_CEC->AddLog(CEC_LOG_ERROR, "CLinuxCECAdapterCommunication::Process - ioctl CEC_RECEIVE failed - rx_status=%02x errno=%d", msg.rx_status, errno); -+ else if (msg.len > 0) -+ { -+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Process - ioctl CEC_RECEIVE - rx_status=%02x len=%d addr=%02x opcode=%02x", msg.rx_status, msg.len, msg.msg[0], cec_msg_opcode(&msg)); -+ -+ cec_command cmd; -+ cmd.PushArray(msg.len, msg.msg); -+ -+ if (!IsStopped()) -+ m_callback->OnCommandReceived(cmd); -+ } -+ } -+ -+ if (!IsStopped()) -+ Sleep(5); -+ } -+ -+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "CLinuxCECAdapterCommunication::Process - stopped - m_fd=%d", m_fd); -+ return 0; -+} -+ -+#endif -diff --git a/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.h b/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.h -new file mode 100644 -index 0000000..f4fac87 ---- /dev/null -+++ b/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.h -@@ -0,0 +1,95 @@ -+#pragma once -+/* -+ * This file is part of the libCEC(R) library. -+ * -+ * libCEC Linux CEC Adapter is Copyright (C) 2017-2018 Jonas Karlman -+ * based heavily on: -+ * libCEC AOCEC Code is Copyright (C) 2016 Gerald Dachs -+ * libCEC Exynos Code is Copyright (C) 2014 Valentin Manea -+ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved. -+ * libCEC(R) is an original work, containing original code. -+ * -+ * libCEC(R) is a trademark of Pulse-Eight Limited. -+ * -+ * This program is dual-licensed; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * -+ * Alternatively, you can license this library under a commercial license, -+ * please contact Pulse-Eight Licensing for more information. -+ * -+ * For more information contact: -+ * Pulse-Eight Licensing -+ * http://www.pulse-eight.com/ -+ * http://www.pulse-eight.net/ -+ */ -+ -+#include "env.h" -+ -+#if defined(HAVE_LINUX_API) -+#include "p8-platform/threads/threads.h" -+#include "../AdapterCommunication.h" -+ -+namespace CEC -+{ -+ class CLinuxCECAdapterCommunication : public IAdapterCommunication, public P8PLATFORM::CThread -+ { -+ public: -+ /*! -+ * @brief Create a new Linux CEC communication handler. -+ * @param callback The callback to use for incoming CEC commands. -+ */ -+ CLinuxCECAdapterCommunication(IAdapterCommunicationCallback *callback); -+ virtual ~CLinuxCECAdapterCommunication(void); -+ -+ /** @name IAdapterCommunication implementation */ -+ ///{ -+ bool Open(uint32_t iTimeoutMs = CEC_DEFAULT_CONNECT_TIMEOUT, bool bSkipChecks = false, bool bStartListening = true) override; -+ void Close(void) override; -+ bool IsOpen(void) override; -+ cec_adapter_message_state Write(const cec_command &data, bool &bRetry, uint8_t iLineTimeout, bool bIsReply) override; -+ -+ bool SetLineTimeout(uint8_t UNUSED(iTimeout)) override { return true; } -+ bool StartBootloader(void) override { return false; } -+ bool SetLogicalAddresses(const cec_logical_addresses &addresses) override; -+ cec_logical_addresses GetLogicalAddresses(void) const override; -+ bool PingAdapter(void) override { return true; } -+ uint16_t GetFirmwareVersion(void) override { return 0; } -+ uint32_t GetFirmwareBuildDate(void) override { return 0; } -+ bool IsRunningLatestFirmware(void) override { return true; } -+ bool SetControlledMode(bool UNUSED(controlled)) override { return true; } -+ bool PersistConfiguration(const libcec_configuration & UNUSED(configuration)) override { return false; } -+ bool SetAutoMode(bool UNUSED(automode)) override { return false; } -+ bool GetConfiguration(libcec_configuration & UNUSED(configuration)) override { return false; } -+ std::string GetPortName(void) override { return std::string("LINUX"); } -+ uint16_t GetPhysicalAddress(void) override; -+ cec_vendor_id GetVendorId(void) override; -+ bool SupportsSourceLogicalAddress(const cec_logical_address address) override { return address > CECDEVICE_TV && address <= CECDEVICE_BROADCAST; } -+ cec_adapter_type GetAdapterType(void) override { return ADAPTERTYPE_LINUX; } -+ uint16_t GetAdapterVendorId(void) const override { return 1; } -+ uint16_t GetAdapterProductId(void) const override { return 1; } -+ void SetActiveSource(bool UNUSED(bSetTo), bool UNUSED(bClientUnregistered)) override {} -+ ///} -+ -+ /** @name P8PLATFORM::CThread implementation */ -+ ///{ -+ void *Process(void) override; -+ ///} -+ -+ private: -+ int m_fd; -+ }; -+}; -+ -+#endif -diff --git a/src/libcec/adapter/Linux/LinuxCECAdapterDetection.cpp b/src/libcec/adapter/Linux/LinuxCECAdapterDetection.cpp -new file mode 100644 -index 0000000..7b72238 ---- /dev/null -+++ b/src/libcec/adapter/Linux/LinuxCECAdapterDetection.cpp -@@ -0,0 +1,50 @@ -+/* -+ * This file is part of the libCEC(R) library. -+ * -+ * libCEC Linux CEC Adapter is Copyright (C) 2017 Jonas Karlman -+ * based heavily on: -+ * libCEC AOCEC Code is Copyright (C) 2016 Gerald Dachs -+ * libCEC Exynos Code is Copyright (C) 2014 Valentin Manea -+ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved. -+ * libCEC(R) is an original work, containing original code. -+ * -+ * libCEC(R) is a trademark of Pulse-Eight Limited. -+ * -+ * This program is dual-licensed; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * -+ * Alternatively, you can license this library under a commercial license, -+ * please contact Pulse-Eight Licensing for more information. -+ * -+ * For more information contact: -+ * Pulse-Eight Licensing -+ * http://www.pulse-eight.com/ -+ * http://www.pulse-eight.net/ -+ */ -+ -+#include "env.h" -+#include -+ -+#if defined(HAVE_LINUX_API) -+#include "LinuxCECAdapterDetection.h" -+ -+using namespace CEC; -+ -+bool CLinuxCECAdapterDetection::FindAdapter(void) -+{ -+ return access(CEC_LINUX_PATH, 0) == 0; -+} -+ -+#endif -diff --git a/src/libcec/adapter/Linux/LinuxCECAdapterDetection.h b/src/libcec/adapter/Linux/LinuxCECAdapterDetection.h -new file mode 100644 -index 0000000..f5ea2c4 ---- /dev/null -+++ b/src/libcec/adapter/Linux/LinuxCECAdapterDetection.h -@@ -0,0 +1,51 @@ -+#pragma once -+/* -+ * This file is part of the libCEC(R) library. -+ * -+ * libCEC Linux CEC Adapter is Copyright (C) 2017 Jonas Karlman -+ * based heavily on: -+ * libCEC AOCEC Code is Copyright (C) 2016 Gerald Dachs -+ * libCEC Exynos Code is Copyright (C) 2014 Valentin Manea -+ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved. -+ * libCEC(R) is an original work, containing original code. -+ * -+ * libCEC(R) is a trademark of Pulse-Eight Limited. -+ * -+ * This program is dual-licensed; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * -+ * Alternatively, you can license this library under a commercial license, -+ * please contact Pulse-Eight Licensing for more information. -+ * -+ * For more information contact: -+ * Pulse-Eight Licensing -+ * http://www.pulse-eight.com/ -+ * http://www.pulse-eight.net/ -+ */ -+ -+#include "env.h" -+ -+#if defined(HAVE_LINUX_API) -+ -+namespace CEC -+{ -+ class CLinuxCECAdapterDetection -+ { -+ public: -+ static bool FindAdapter(void); -+ }; -+}; -+ -+#endif -diff --git a/src/libcec/cmake/CheckPlatformSupport.cmake b/src/libcec/cmake/CheckPlatformSupport.cmake -index 2d7102f..dacca0f 100644 ---- a/src/libcec/cmake/CheckPlatformSupport.cmake -+++ b/src/libcec/cmake/CheckPlatformSupport.cmake -@@ -9,6 +9,7 @@ - # HAVE_RPI_API ON if Raspberry Pi is supported - # HAVE_TDA995X_API ON if TDA995X is supported - # HAVE_EXYNOS_API ON if Exynos is supported -+# HAVE_LINUX_API ON if Linux is supported - # HAVE_AOCEC_API ON if AOCEC is supported - # HAVE_P8_USB ON if Pulse-Eight devices are supported - # HAVE_P8_USB_DETECT ON if Pulse-Eight devices can be auto-detected -@@ -30,6 +31,7 @@ SET(HAVE_LIBUDEV OFF CACHE BOOL "udev not supported") - SET(HAVE_RPI_API OFF CACHE BOOL "raspberry pi not supported") - SET(HAVE_TDA995X_API OFF CACHE BOOL "tda995x not supported") - SET(HAVE_EXYNOS_API OFF CACHE BOOL "exynos not supported") -+SET(HAVE_LINUX_API OFF CACHE BOOL "linux not supported") - SET(HAVE_AOCEC_API OFF CACHE BOOL "aocec not supported") - # Pulse-Eight devices are always supported - set(HAVE_P8_USB ON CACHE BOOL "p8 usb-cec supported" FORCE) -@@ -139,6 +141,16 @@ else() - list(APPEND CEC_SOURCES ${CEC_SOURCES_ADAPTER_EXYNOS}) - endif() - -+ # Linux -+ if (${HAVE_LINUX_API}) -+ set(LIB_INFO "${LIB_INFO}, Linux") -+ SET(HAVE_LINUX_API ON CACHE BOOL "linux supported" FORCE) -+ set(CEC_SOURCES_ADAPTER_LINUX adapter/Linux/LinuxCECAdapterDetection.cpp -+ adapter/Linux/LinuxCECAdapterCommunication.cpp) -+ source_group("Source Files\\adapter\\Linux" FILES ${CEC_SOURCES_ADAPTER_LINUX}) -+ list(APPEND CEC_SOURCES ${CEC_SOURCES_ADAPTER_LINUX}) -+ endif() -+ - # AOCEC - if (${HAVE_AOCEC_API}) - set(LIB_INFO "${LIB_INFO}, AOCEC") -diff --git a/src/libcec/cmake/DisplayPlatformSupport.cmake b/src/libcec/cmake/DisplayPlatformSupport.cmake -index 83a778a..f47b1f7 100644 ---- a/src/libcec/cmake/DisplayPlatformSupport.cmake -+++ b/src/libcec/cmake/DisplayPlatformSupport.cmake -@@ -44,6 +44,12 @@ else() - message(STATUS "DRM support: no") - endif() - -+if (HAVE_LINUX_API) -+ message(STATUS "Linux support: yes") -+else() -+ message(STATUS "Linux support: no") -+endif() -+ - if (HAVE_AOCEC_API) - message(STATUS "AOCEC support: yes") - else() -diff --git a/src/libcec/env.h.in b/src/libcec/env.h.in -index 456a2e7..71895a8 100644 ---- a/src/libcec/env.h.in -+++ b/src/libcec/env.h.in -@@ -76,6 +76,9 @@ - /* Define to 1 for Exynos support */ - #cmakedefine HAVE_EXYNOS_API @HAVE_EXYNOS_API@ - -+/* Define to 1 for Linux support */ -+#cmakedefine HAVE_LINUX_API @HAVE_LINUX_API@ -+ - /* Define to 1 for AOCEC support */ - #cmakedefine HAVE_AOCEC_API @HAVE_AOCEC_API@ - diff --git a/cec_scan/data/run.sh b/cec_scan/data/run.sh deleted file mode 100755 index 4b898e7f358..00000000000 --- a/cec_scan/data/run.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bashio -set -e - -bashio::log.info "Starting CEC client scan..." -echo scan | cec-client -s -d 1 diff --git a/almond/rootfs/etc/services.d/nginx/run b/cec_scan/rootfs/etc/services.d/cec-scan/finish old mode 100644 new mode 100755 similarity index 65% rename from almond/rootfs/etc/services.d/nginx/run rename to cec_scan/rootfs/etc/services.d/cec-scan/finish index bd6f1e811a8..2e68f50bc41 --- a/almond/rootfs/etc/services.d/nginx/run +++ b/cec_scan/rootfs/etc/services.d/cec-scan/finish @@ -1,5 +1,6 @@ #!/usr/bin/env bashio +# vim: ft=bash # ============================================================================== -# Start NGINX service +# Take down the S6 supervision tree when service is done # ============================================================================== -exec nginx +/run/s6/basedir/bin/halt diff --git a/homematic/rootfs/etc/services.d/nginx/run b/cec_scan/rootfs/etc/services.d/cec-scan/run old mode 100644 new mode 100755 similarity index 57% rename from homematic/rootfs/etc/services.d/nginx/run rename to cec_scan/rootfs/etc/services.d/cec-scan/run index 964bc41847e..4d27f510d9b --- a/homematic/rootfs/etc/services.d/nginx/run +++ b/cec_scan/rootfs/etc/services.d/cec-scan/run @@ -1,9 +1,9 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== -# Start NGINX service +# Start CEC scan service # ============================================================================== -# Wait for HomeMatic httpd -bashio::net.wait_for 80 -bashio::log.info "Starting Nginx..." -exec nginx +bashio::log.info "Starting CEC client scan..." +echo scan | cec-client -s -d 1 diff --git a/check_config/CHANGELOG.md b/check_config/CHANGELOG.md deleted file mode 100644 index 5f733f7d149..00000000000 --- a/check_config/CHANGELOG.md +++ /dev/null @@ -1,71 +0,0 @@ -# Changelog - -## 3.8.0 - -- Update base image to 2021.07.0 -- Allow using `stable`, `beta` and `dev` as target versions -- Add translation file for English - -## 3.7.1 - -- Update base image to 2021.04.3 - -## 3.7.0 - -- Update base image to 2021.04.2 -- Suppress PIP install output, unless an error occurs -- Remove udev usage, replaced by uart & usb flag -- Fix S6 supervisor not listening message - -## 3.6.0 - -- Change to rsync for copy -- Ignore HA db files - -## 3.5.0 - -- Update base image to version 8.4.0 -- Add media folder - -## 3.4.0 - -- Update base image to version 8.1.0 - -## 3.3.0 - -- Update base image to version 7.2.0 -- Add access to `share` folder for when using `whitelist_external_dirs` -- Fixes `fatal: unable to control: supervisor not listening` -- Show only top of the error log in add-on output -- Write full check config output to `/share/check_config.txt` -- Ensure service script does not crash when check config fails -- Hide pip version warning to avoid confusion - -## 3.2.0 - -- Update base image to version 7.1.0 -- Migrate to S6-overlay - -## 3.1.0 - -- Moved the 'reassurance' log message "Don't worry, this temporary installation is not overwriting your current one." to earlier in the process. - -## 3.0.0 - -- Use Home Assistant base image as base for this Add-on -- Disable external UDEV - -## 2.2.0 - -- Update python/alpine to HA 0.96 - -## 2.1.0 - -- Adds additional information in log output to avoid confusion - -## 2.0.0 - -- Migrated add-on onto Bashio -- Improved add-on log output -- Added documentation to add-on itself -- Added support for Home Assistant wheels repository diff --git a/check_config/DOCS.md b/check_config/DOCS.md deleted file mode 100644 index 326a562c649..00000000000 --- a/check_config/DOCS.md +++ /dev/null @@ -1,65 +0,0 @@ -# Home Assistant Add-on: Check Home Assistant configuration - -## Installation - -Follow these steps to get the add-on installed on your system: - -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. -2. Find the "Check Home Assistant configuration" add-on and click it. -3. Click on the "INSTALL" button. - -## How to use - -In the configuration section, set the version you want to check your configuration -against. In case you'd like to check your configuration against the latest version of -Home Assistant, leave it set to `latest`, which is already there as the default. - -1. Start the add-on. -2. Have some patience and wait a couple of minutes. -3. Check the add-on log output to see the result. - -If the log ends with `Configuration check finished - no error found! :)`, -it means the check against your configuration passes on the specified -Home Assistant version. - -## Configuration - -Add-on configuration: - -```yaml -version: latest -``` - -### Option: `version` (required) - -The version of Home Assistant that want to check your configuration against. - -- Setting this option to `latest` or `stable` will result in checking your configuration -against the latest stable release of Home Assistant. -- Setting this option to `beta` will result in checking your configuration -against the latest beta release of Home Assistant. -- Setting this option to `dev` will result in checking your configuration -against the current dev branch of Home Assistant. - -## Known issues and limitations - -- Currently, this add-on only supports checking against Home Assistant >= 0.94 - or less 0.91. - -## Support - -Got questions? - -You have several options to get them answered: - -- The [Home Assistant Discord Chat Server][discord]. -- The Home Assistant [Community Forum][forum]. -- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit] - -In case you've found a bug, please [open an issue on our GitHub][issue]. - -[discord]: https://discord.gg/c5DvZ4e -[forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues -[reddit]: https://reddit.com/r/homeassistant -[repository]: https://github.com/hassio-addons/repository diff --git a/check_config/Dockerfile b/check_config/Dockerfile deleted file mode 100644 index cabaf29a9fa..00000000000 --- a/check_config/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -ARG BUILD_FROM -FROM $BUILD_FROM - -RUN apk add --no-cache \ - rsync - -# Copy data -COPY rootfs / diff --git a/check_config/README.md b/check_config/README.md deleted file mode 100644 index e707eacc8a8..00000000000 --- a/check_config/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Home Assistant Add-on: Check Home Assistant configuration - -Check your current configuration against any Home Assistant version. - -![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield] - -You can use this add-on to check whether your configuration files are valid against the -new version of Home Assistant before you actually update your Home Assistant -installation. This add-on will help you avoid errors due to breaking changes, -resulting in a smooth update. - -[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg -[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg -[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg -[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg -[i386-shield]: https://img.shields.io/badge/i386-yes-green.svg diff --git a/check_config/build.json b/check_config/build.json deleted file mode 100644 index e8674e7ae42..00000000000 --- a/check_config/build.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "build_from": { - "aarch64": "ghcr.io/home-assistant/aarch64-homeassistant-base:2021.07.0", - "amd64": "ghcr.io/home-assistant/amd64-homeassistant-base:2021.07.0", - "armhf": "ghcr.io/home-assistant/armhf-homeassistant-base:2021.07.0", - "armv7": "ghcr.io/home-assistant/armv7-homeassistant-base:2021.07.0", - "i386": "ghcr.io/home-assistant/i386-homeassistant-base:2021.07.0" - } -} diff --git a/check_config/config.json b/check_config/config.json deleted file mode 100644 index c0006820b4a..00000000000 --- a/check_config/config.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "Check Home Assistant configuration", - "version": "3.8.0", - "slug": "check_config", - "description": "Check current Home Assistant configuration against a new version", - "url": "https://github.com/home-assistant/hassio-addons/tree/master/check_config", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "uart": true, - "usb": true, - "startup": "once", - "boot": "manual", - "init": false, - "map": ["config", "ssl", "media:rw", "share:rw"], - "options": { - "version": "latest" - }, - "schema": { - "version": "str" - }, - "image": "homeassistant/{arch}-addon-check_config" -} diff --git a/check_config/icon.png b/check_config/icon.png deleted file mode 100644 index 11f2f67f996..00000000000 Binary files a/check_config/icon.png and /dev/null differ diff --git a/check_config/logo.png b/check_config/logo.png deleted file mode 100644 index 027848b1caf..00000000000 Binary files a/check_config/logo.png and /dev/null differ diff --git a/check_config/rootfs/etc/services.d/check-config/finish b/check_config/rootfs/etc/services.d/check-config/finish deleted file mode 100644 index a1ecd5f99a4..00000000000 --- a/check_config/rootfs/etc/services.d/check-config/finish +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/execlineb -S1 -# ============================================================================== -# Take down the S6 supervision tree when config check is done -# ============================================================================== -s6-svscanctl -t /var/run/s6/services diff --git a/check_config/rootfs/etc/services.d/check-config/run b/check_config/rootfs/etc/services.d/check-config/run deleted file mode 100644 index 5d545f5d035..00000000000 --- a/check_config/rootfs/etc/services.d/check-config/run +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Start config checker service -# ============================================================================== -VERSION=$(bashio::config 'version') - -CMD_OPTIONS=("--disable-pip-version-check" "--find-links" "${WHEELS_LINKS}") - -# Generate install string -if [[ "${VERSION}" =~ latest|stable ]]; then - CMD_OPTIONS+=("homeassistant") -elif [ "${VERSION}" == "beta" ]; then - CMD_OPTIONS+=("--pre") - CMD_OPTIONS+=("homeassistant") -elif [ "${VERSION}" == "dev" ]; then - CMD_OPTIONS+=("git+git://github.com/home-assistant/core.git@dev") -else - CMD_OPTIONS+=("homeassistant==${VERSION}") -fi - -bashio::log.info "Don't worry, this temporary installation is not overwriting your current one." -bashio::log.info "Installing Home Assistant: ${VERSION}..." -bashio::log.info "Please be patient, this might take a few minutes..." - -# Install Home Assistant with the requested version -if ! PIP_OUTPUT=$(pip3 install "${CMD_OPTIONS[@]}" 2>&1); then - bashio::log.error "An error occurred while installing Home Assistant:" - bashio::log "${PIP_OUTPUT}" - bashio::exit.nok -fi -INSTALLED_VERSION="$(pip freeze | grep homeassistant)" -bashio::log.info "Installed Home Assistant ${INSTALLED_VERSION##*=}" - -# Making a temporary copy of your configuration -bashio::log.info "Making a copy of your configuration for checking..." -rsync -avr --exclude='*home-assistant_v2*' /config/ /tmp/config --quiet - -# Start configuration check -bashio::log.info "Checking your configuration against this version..." - -if ! hass -c /tmp/config --script check_config > /share/check_config.txt; then - # The configuration check exited with an error - bashio::log.error "The configuration check did not pass!" - bashio::log.error "See the output below for more details." - - grep -v homeassistant.util.package /share/check_config.txt | head -n 15 - - bashio::log.info "The full output has been written to /share/check_config.txt" - bashio::exit.nok -fi - -# Scan configuration check output for occurrences of "ERROR" -if grep -i ERROR /share/check_config.txt > /dev/null; then - # An "ERROR" occurrence has been found, exit with an error - bashio::log.error "Found an error in the log output of the check!" - bashio::log.error "See the output below for more details." - - grep -i ERROR /share/check_config.txt - - bashio::log.info "The full output has been written to /share/check_config.txt" - bashio::exit.nok -fi - -# You rock! <(*_*)> -bashio::log.info "Configuration check finished - no error found! :)" diff --git a/check_config/translations/en.yaml b/check_config/translations/en.yaml deleted file mode 100644 index de1c55e3e5d..00000000000 --- a/check_config/translations/en.yaml +++ /dev/null @@ -1,4 +0,0 @@ -configuration: - version: - name: Version - description: The version of Home Assistant to check against, you can use `stable` , `latest`, `dev` and a version \ No newline at end of file diff --git a/configurator/CHANGELOG.md b/configurator/CHANGELOG.md index a08c52f36c1..b5ae6a99fc4 100644 --- a/configurator/CHANGELOG.md +++ b/configurator/CHANGELOG.md @@ -1,5 +1,53 @@ # Changelog +## 5.8.0 + +- Update base image to Alpine 3.19 + +## 5.7.0 + +- Use new location for accessing the Home Assistant configuration folder using `/homeassistant` +- Add access to the new public configuration folders of add-ons +- Upgrade to Alpine 3.18 +- Remove unneeded pip configuration when building add-on +- Remove unused variable in finish script + +## 5.6.0 + +- Update base image to Alpine 3.17 +- Migrate old style S6 Overlay service scripts to new `s6-rc.d` style +- Add Docker healthchecks + +## 5.5.1 + +- Fix Home Assistant wheels path + +## 5.5.0 + +- Update base image to Alpine 3.16 + - Bumps `git` to 2.36.3 + - Bumps `ssh` to OpenSSH_9.0p1 + - Bumps `python3` to 3.10.9 + +## 5.4.2 + +- Bugfix: Fix page load with special characters in states + +## 5.4.1 + +- Bugfix: Disable Ace-internal yaml-linting +- Disable internal check for new releases + +## 5.4.0 + +- Add Generate UUID menu item +- Harmonize Home Assistant term +- Rename Components to integrations +- Remove images for libraries +- Update jQuery to 3.6.0 +- Update js-yaml to 4.1.0 +- Update Ace Editor to 1.9.6 + ## 5.3.3 - Fix Home Assistant API endpoint diff --git a/configurator/DOCS.md b/configurator/DOCS.md index 2fea440fae8..0c840df2a60 100644 --- a/configurator/DOCS.md +++ b/configurator/DOCS.md @@ -4,7 +4,7 @@ Follow these steps to get the add-on installed on your system: -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. 2. Find the "File editor" add-on and click it. 3. Click on the "INSTALL" button. @@ -38,7 +38,8 @@ Set it to `true` to list directories first, `false` otherwise. ### Option: `enforce_basepath` (required) -If set to `true`, access is limited to files within the `/config` directory. +If set to `true`, access is limited to files within the `/homeassistant` directory +(also known as the `/config` folder inside Home Assisant itself). ### Option: `git` (required) @@ -71,6 +72,5 @@ In case you've found a bug, please [open an issue on our GitHub][issue]. [discord]: https://discord.gg/c5DvZ4e [forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues +[issue]: https://github.com/home-assistant/addons/issues [reddit]: https://reddit.com/r/homeassistant -[repository]: https://github.com/hassio-addons/repository diff --git a/configurator/Dockerfile b/configurator/Dockerfile index 69b09f5e413..13a3d10b9d8 100644 --- a/configurator/Dockerfile +++ b/configurator/Dockerfile @@ -1,6 +1,8 @@ ARG BUILD_FROM FROM $BUILD_FROM +ENV PIP_BREAK_SYSTEM_PACKAGES=1 + # Setup base ARG BUILD_ARCH ARG CONFIGURATOR_VERSION @@ -11,9 +13,6 @@ RUN \ py3-pip \ python3 \ && pip3 install \ - --no-cache-dir \ - --prefer-binary \ - --find-links "https://wheels.home-assistant.io/alpine-3.14/${BUILD_ARCH}/" \ hass-configurator=="${CONFIGURATOR_VERSION}" \ \ && find /usr/local \ @@ -23,3 +22,6 @@ RUN \ # Copy data COPY rootfs / + +# Health check +HEALTHCHECK CMD curl --fail http://127.0.0.1:8099 || exit 1 diff --git a/configurator/build.json b/configurator/build.json deleted file mode 100644 index 42015ee8b80..00000000000 --- a/configurator/build.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "build_from": { - "aarch64": "ghcr.io/home-assistant/aarch64-base:3.14", - "amd64": "ghcr.io/home-assistant/amd64-base:3.14", - "armhf": "ghcr.io/home-assistant/armhf-base:3.14", - "armv7": "ghcr.io/home-assistant/armv7-base:3.14", - "i386": "ghcr.io/home-assistant/i386-base:3.14" - }, - "args": { - "CONFIGURATOR_VERSION": "0.4.1" - } -} diff --git a/configurator/build.yaml b/configurator/build.yaml new file mode 100644 index 00000000000..9366f81e814 --- /dev/null +++ b/configurator/build.yaml @@ -0,0 +1,12 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base:3.19 + amd64: ghcr.io/home-assistant/amd64-base:3.19 + armhf: ghcr.io/home-assistant/armhf-base:3.19 + armv7: ghcr.io/home-assistant/armv7-base:3.19 + i386: ghcr.io/home-assistant/i386-base:3.19 +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io +args: + CONFIGURATOR_VERSION: 0.5.2 diff --git a/configurator/config.json b/configurator/config.json deleted file mode 100644 index 3747026309b..00000000000 --- a/configurator/config.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "File editor", - "version": "5.3.3", - "slug": "configurator", - "description": "Simple browser-based file editor for Home Assistant", - "url": "https://github.com/home-assistant/hassio-addons/tree/master/configurator", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "homeassistant": "0.91.1", - "init": false, - "ingress": true, - "panel_icon": "mdi:wrench", - "homeassistant_api": true, - "map": ["backup:rw", "config:rw", "media:rw", "share:rw", "ssl:rw"], - "options": { - "dirsfirst": false, - "enforce_basepath": true, - "git": true, - "ignore_pattern": ["__pycache__", ".cloud", ".storage", "deps"], - "ssh_keys": [] - }, - "schema": { - "dirsfirst": "bool", - "enforce_basepath": "bool", - "git": "bool", - "ignore_pattern": ["str"], - "ssh_keys": ["str"] - }, - "image": "homeassistant/{arch}-addon-configurator" -} diff --git a/configurator/config.yaml b/configurator/config.yaml new file mode 100644 index 00000000000..b345c7efe27 --- /dev/null +++ b/configurator/config.yaml @@ -0,0 +1,44 @@ +--- +version: 5.8.0 +slug: configurator +name: File editor +description: Simple browser-based file editor for Home Assistant +url: https://github.com/home-assistant/addons/tree/master/configurator +codenotary: notary@home-assistant.io +arch: + - armhf + - armv7 + - aarch64 + - amd64 + - i386 +homeassistant: 0.91.1 +homeassistant_api: true +image: homeassistant/{arch}-addon-configurator +ingress: true +init: false +map: + - all_addon_configs:rw + - backup:rw + - homeassistant_config:rw + - media:rw + - share:rw + - ssl:rw +options: + dirsfirst: false + enforce_basepath: true + git: true + ignore_pattern: + - __pycache__ + - .cloud + - .storage + - deps + ssh_keys: [] +panel_icon: mdi:wrench +schema: + dirsfirst: bool + enforce_basepath: bool + git: bool + ignore_pattern: + - str + ssh_keys: + - str diff --git a/configurator/rootfs/etc/configurator.conf b/configurator/rootfs/etc/configurator.conf index baf83ed49e6..4148ae21a9d 100644 --- a/configurator/rootfs/etc/configurator.conf +++ b/configurator/rootfs/etc/configurator.conf @@ -2,7 +2,7 @@ "LISTENIP": "0.0.0.0", "PORT": 8099, "GIT": true, - "BASEPATH": "/config", + "BASEPATH": "/homeassistant", "ENFORCE_BASEPATH": true, "SSL_CERTIFICATE": null, "SSL_KEY": null, @@ -12,7 +12,7 @@ "HASS_API_PASSWORD": null, "USERNAME": null, "PASSWORD": null, - "ALLOWED_NETWORKS": ["172.30.32.2"], + "ALLOWED_NETWORKS": ["127.0.0.1", "172.30.32.2"], "ALLOWED_DOMAINS": [], "BANNED_IPS": [], "BANLIMIT": 0, diff --git a/configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/dependencies.d/base b/configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/dependencies.d/base new file mode 100644 index 00000000000..e69de29bb2d diff --git a/configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/finish b/configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/finish new file mode 100755 index 00000000000..8558b9a95ea --- /dev/null +++ b/configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/finish @@ -0,0 +1,27 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Take down the S6 supervision tree when service fails +# s6-overlay docs: https://github.com/just-containers/s6-overlay +# ============================================================================== +# shellcheck disable=SC2155 +readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode + fi + [[ "${exit_code_signal}" -eq 15 ]] && exec /run/s6/basedir/bin/halt +elif [[ "${exit_code_service}" -ne 0 ]]; then + if [[ "${exit_code_container}" -eq 0 ]]; then + echo "${exit_code_service}" > /run/s6-linux-init-container-results/exitcode + fi + exec /run/s6/basedir/bin/halt +fi diff --git a/configurator/rootfs/etc/services.d/configurator/run b/configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/run old mode 100644 new mode 100755 similarity index 94% rename from configurator/rootfs/etc/services.d/configurator/run rename to configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/run index 7cd5107e47a..37ab1afa586 --- a/configurator/rootfs/etc/services.d/configurator/run +++ b/configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/run @@ -1,4 +1,6 @@ -#!/usr/bin/with-contenv bashio +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Start Configurator service # ============================================================================== diff --git a/configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/type b/configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/type new file mode 100644 index 00000000000..1780f9f44ef --- /dev/null +++ b/configurator/rootfs/etc/s6-overlay/s6-rc.d/configurator/type @@ -0,0 +1 @@ +longrun \ No newline at end of file diff --git a/configurator/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/configurator b/configurator/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/configurator new file mode 100644 index 00000000000..e69de29bb2d diff --git a/configurator/rootfs/etc/services.d/configurator/finish b/configurator/rootfs/etc/services.d/configurator/finish deleted file mode 100644 index a29ced9a496..00000000000 --- a/configurator/rootfs/etc/services.d/configurator/finish +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/execlineb -S1 -# ============================================================================== -# Take down the S6 supervision tree based on service exit code -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } - -s6-svscanctl -t /var/run/s6/services diff --git a/configurator/translations/en.yaml b/configurator/translations/en.yaml new file mode 100644 index 00000000000..8beed56b080 --- /dev/null +++ b/configurator/translations/en.yaml @@ -0,0 +1,27 @@ +--- +configuration: + dirsfirst: + name: Directories First + description: >- + This option allows you to list directories before files in the file + browser tree. + enforce_basepath: + name: Enforce Basepath + description: >- + If set to `true`, access is limited to files within the `/config` + directory. + git: + name: Git + description: >- + If set to `true`, add-on will initialize git for directories which support + it. + ignore_pattern: + name: Ignore Pattern + description: >- + This option allows you to hide files and folders from the file browser + tree. + ssh_keys: + name: SSH Keys + description: >- + A list of filenames containing SSH private keys. These can be used to + allow for access to remote git repositories. diff --git a/deconz/CHANGELOG.md b/deconz/CHANGELOG.md index 63befc79ddd..41026268f66 100644 --- a/deconz/CHANGELOG.md +++ b/deconz/CHANGELOG.md @@ -1,5 +1,89 @@ # Changelog +## 7.0.0 + +- Bump deCONZ to 2.28.1 +- Use debian bookworm for all arch types +- Use dwm instead of wmii as window manager + +## 6.23.0 + +- Bump deCONZ to 2.25.3 + +## 6.22.0 + +- Revert deCONZ to 2.22.2 due to a Phoscon bug: https://forum.phoscon.de/t/phoscon-de-pwa-login-html-does-not-work-anymore/3967 + +## 6.21.0 + +- Bump deCONZ to 2.23.1 + +## 6.20.0 + +- Bump deCONZ to 2.22.2 + +## 6.19.0 + +- Bump deCONZ to 2.21.2 + +## 6.18.0 + +- Bump deCONZ to 2.20.1 + +## 6.17.1 + +- Bump deCONZ to 2.19.3 + +## 6.17.0 + +- Bump deCONZ to 2.19.1 + +## 6.16.0 + +- Bump deCONZ to 2.18.2 + +## 6.15.0 + +- Bump deCONZ to 2.17.1 + +## 6.14.2 + +- Fix finish script for S6 V3 + +## 6.14.1 + +- Version bump to fix S6 service permissions + +## 6.14.0 + +- Bump deCONZ to 2.16.1 + +## 6.13.0 + +- Bump deCONZ to 2.15.3 + +## 6.12.1 + +- Fix Phoscon App gateway discovery with FQDN over Ingress +- Improve Phoscon App subnet probing block when using Ingress + +## 6.12.0 + +- Bump deCONZ to 2.14.1 + +## 6.11.1 + +- Add missing libqt5qml5 dependency +- Do not force install of deCONZ packages + +## 6.11.0 + +- Bump deCONZ to 2.13.4 + +## 6.10.0 + +- Bump deCONZ to 2.12.6 + ## 6.9.0 - Bump deCONZ to 2.11.5 diff --git a/deconz/DOCS.md b/deconz/DOCS.md index 4e22a03cfe8..f0ba649824c 100644 --- a/deconz/DOCS.md +++ b/deconz/DOCS.md @@ -4,7 +4,7 @@ Follow these steps to get the add-on installed on your system: -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. 2. Find the "deCONZ" add-on and click it. 3. Click on the "INSTALL" button. @@ -28,7 +28,7 @@ The add-on needs to know where your ConBee/RaspBee can be found, and therefore, you'll need to configure the add-on to point to the right device. If you're using Home Assistant you may find the correct value for this on the -`Supervisor -> System -> Host system -> Hardware` page. It is recommended +`Settings -> System -> Hardware` page. It is recommended to use a "by-id" path to the device if one exists, as it is not subject to change if other devices are added to the system. @@ -48,7 +48,7 @@ with "WEB UI" button. By default, Home Assistant has the `discovery` integration enabled, which automatically discovers this add-on. -Navigate to **Configuration** -> **Integrations** page after starting this +Navigate to **Settings** -> **Devices & Services** -> **Integrations** page after starting this add-on to configure the deCONZ integration. In case you don't have `discovery` enabled on your Home Assistant instance, @@ -232,7 +232,7 @@ In case you've found a bug, please [open an issue on our GitHub][issue]. [discord]: https://discord.gg/c5DvZ4e [forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues +[issue]: https://github.com/home-assistant/addons/issues [manual-upgrade]: https://github.com/dresden-elektronik/deconz-rest-plugin/wiki/Update-deCONZ-manually [reddit]: https://reddit.com/r/homeassistant [vnc-viewer]: https://bintray.com/tigervnc/stable/tigervnc/ diff --git a/deconz/Dockerfile b/deconz/Dockerfile index 4fc686721d1..3734a30ed36 100644 --- a/deconz/Dockerfile +++ b/deconz/Dockerfile @@ -11,6 +11,7 @@ RUN \ && apt-get update \ && apt-get install -y --no-install-recommends \ curl \ + dwm \ iproute2 \ iputils-ping \ kmod \ @@ -22,8 +23,9 @@ RUN \ libqt5sql5 \ libqt5websockets5 \ libqt5widgets5 \ + libqt5qml5 \ lsof \ - netcat \ + netcat-traditional \ nginx \ novnc \ sqlite3 \ @@ -31,33 +33,9 @@ RUN \ tigervnc-standalone-server \ udev \ wget \ - wmii \ xfonts-base \ xfonts-scalable \ - && rm -rf /var/lib/apt/lists/* \ - && if [[ "armhf aarch64" = *"$BUILD_ARCH"* ]]; \ - then \ - apt-get update \ - && apt-get install -y --no-install-recommends \ - build-essential \ - git \ - && git clone --depth 1 https://github.com/WiringPi/WiringPi /usr/src/wiringpi \ - && cd /usr/src/wiringpi/wiringPi \ - && make \ - && make install \ - && cd ../devLib \ - && make \ - && make install \ - && cd ../gpio \ - && make \ - && make install \ - && apt-get purge -y --auto-remove \ - build-essential \ - git \ - && rm -rf \ - /var/lib/apt/lists/* \ - /usr/src/wiringpi; \ - fi + && rm -rf /var/lib/apt/lists/* # Install deCONZ ARG DECONZ_VERSION @@ -68,11 +46,11 @@ RUN \ curl -q -L -o /deconz.deb http://deconz.dresden-elektronik.de/raspbian/stable/deconz-${DECONZ_VERSION}-qt5.deb; \ elif [ "${BUILD_ARCH}" = "aarch64" ]; \ then \ - curl -q -L -o /deconz.deb http://deconz.dresden-elektronik.de/debian/stable/deconz_${DECONZ_VERSION}-debian-stretch-stable_arm64.deb; \ + curl -q -L -o /deconz.deb http://deconz.dresden-elektronik.de/debian/stable/deconz_${DECONZ_VERSION}-debian-buster-stable_arm64.deb; \ else \ curl -q -L -o /deconz.deb http://deconz.dresden-elektronik.de/ubuntu/stable/deconz-${DECONZ_VERSION}-qt5.deb; \ fi \ - && dpkg --force-all -i /deconz.deb \ + && dpkg -i /deconz.deb \ && rm -f /deconz.deb \ && chown root:root /usr/bin/deCONZ* \ && sed -i 's/\/root/\/data/' /etc/passwd diff --git a/deconz/build.json b/deconz/build.json deleted file mode 100644 index e4a3cd35fbb..00000000000 --- a/deconz/build.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "build_from": { - "aarch64": "homeassistant/aarch64-base-debian:buster", - "amd64": "homeassistant/amd64-base-debian:buster", - "armhf": "homeassistant/armhf-base-raspbian:buster" - }, - "args": { - "DECONZ_VERSION": "2.11.05" - } -} diff --git a/deconz/build.yaml b/deconz/build.yaml new file mode 100644 index 00000000000..9fb3332a1cb --- /dev/null +++ b/deconz/build.yaml @@ -0,0 +1,10 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base-debian:bookworm + amd64: ghcr.io/home-assistant/amd64-base-debian:bookworm + armhf: ghcr.io/home-assistant/armhf-base-raspbian:bookworm +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io +args: + DECONZ_VERSION: 2.28.1 diff --git a/deconz/config.json b/deconz/config.json deleted file mode 100644 index 8f8698d870a..00000000000 --- a/deconz/config.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "deCONZ", - "version": "6.9.0", - "slug": "deconz", - "description": "Control a Zigbee network with ConBee or RaspBee by Dresden Elektronik", - "arch": ["amd64", "armhf", "aarch64"], - "url": "https://github.com/home-assistant/hassio-addons/tree/master/deconz", - "startup": "services", - "init": false, - "ingress": true, - "ingress_entry": "ingress.html", - "panel_icon": "mdi:zigbee", - "homeassistant": "0.91.2", - "discovery": ["deconz"], - "ports": { - "5900/tcp": null, - "8081/tcp": null, - "40850/tcp": null - }, - "ports_description": { - "5900/tcp": "deCONZ via VNC (Not required for Ingress. Not secure!)", - "8081/tcp": "deCONZ WebSocket (Not required for Ingress)", - "40850/tcp": "deCONZ API backend (Not required for Ingress)" - }, - "kernel_modules": true, - "usb": true, - "udev": true, - "gpio": true, - "apparmor": false, - "privileged": ["SYS_RAWIO"], - "devices": ["/dev/mem"], - "snapshot_exclude": ["*/otau"], - "options": { - "device": null - }, - "schema": { - "device": "device(subsystem=tty)", - "dbg_aps": "int?", - "dbg_info": "int?", - "dbg_otau": "int?", - "dbg_zcl": "int?", - "dbg_zdp": "int?" - }, - "image": "homeassistant/{arch}-addon-deconz" -} diff --git a/deconz/config.yaml b/deconz/config.yaml new file mode 100644 index 00000000000..5224c0ab4da --- /dev/null +++ b/deconz/config.yaml @@ -0,0 +1,45 @@ +--- +version: 7.0.0 +slug: deconz +name: deCONZ +description: >- + Control a Zigbee network with ConBee or RaspBee by Dresden Elektronik. +url: https://github.com/home-assistant/addons/tree/master/deconz +apparmor: false +arch: + - amd64 + - armhf + - aarch64 +backup_exclude: + - "*/otau" +codenotary: notary@home-assistant.io +devices: + - /dev/mem +discovery: + - deconz +gpio: true +homeassistant: 0.91.2 +image: homeassistant/{arch}-addon-deconz +ingress: true +ingress_entry: ingress.html +init: false +kernel_modules: true +options: + device: null +panel_icon: mdi:zigbee +ports: + 40850/tcp: null + 5900/tcp: null + 8081/tcp: null +privileged: + - SYS_RAWIO +schema: + device: device(subsystem=tty) + dbg_aps: int? + dbg_info: int? + dbg_otau: int? + dbg_zcl: int? + dbg_zdp: int? +startup: services +udev: true +usb: true diff --git a/deconz/rootfs/etc/cont-init.d/firmware.sh b/deconz/rootfs/etc/cont-init.d/firmware.sh old mode 100644 new mode 100755 index 8e0c23d524a..1254c356aa0 --- a/deconz/rootfs/etc/cont-init.d/firmware.sh +++ b/deconz/rootfs/etc/cont-init.d/firmware.sh @@ -1,4 +1,5 @@ #!/usr/bin/with-contenv bashio +# shellcheck shell=bash # ============================================================================== # Manage deCONZ firmware # ============================================================================== diff --git a/deconz/rootfs/etc/cont-init.d/nginx.sh b/deconz/rootfs/etc/cont-init.d/nginx.sh old mode 100644 new mode 100755 index 2f70a4c5011..66d8ca0b2e9 --- a/deconz/rootfs/etc/cont-init.d/nginx.sh +++ b/deconz/rootfs/etc/cont-init.d/nginx.sh @@ -1,4 +1,5 @@ #!/usr/bin/with-contenv bashio +# shellcheck shell=bash # ============================================================================== # Configure NGINX for use with deCONZ # ============================================================================== diff --git a/deconz/rootfs/etc/cont-init.d/novnc.sh b/deconz/rootfs/etc/cont-init.d/novnc.sh old mode 100644 new mode 100755 index c133526527a..6be4bc781f5 --- a/deconz/rootfs/etc/cont-init.d/novnc.sh +++ b/deconz/rootfs/etc/cont-init.d/novnc.sh @@ -1,4 +1,5 @@ #!/usr/bin/with-contenv bashio +# shellcheck shell=bash # ============================================================================== # Setup noVNC # ============================================================================== diff --git a/deconz/rootfs/etc/nginx/nginx.conf b/deconz/rootfs/etc/nginx/nginx.conf index e5702193e6a..b00bdf2b4bf 100644 --- a/deconz/rootfs/etc/nginx/nginx.conf +++ b/deconz/rootfs/etc/nginx/nginx.conf @@ -73,19 +73,17 @@ http { sub_filter_once off; sub_filter_types *; + # Tell Phoscon app where the gateway is and stop scan of other hosts. + sub_filter ',-1!==document.location.hash.indexOf("nocache")' ',app.probeWorker.postMessage({add:[document.location.host+\'%%ingress_entry%%\']}),app.probeWorker.postMessage({scan:!0}),true'; + # Disable Discovery from Dresden - sub_filter 'phoscon.de/discover' 'phoscon.de/discover_disable'; - sub_filter 'dresden-light.appspot.com/discover' 'dresden-light.appspot.com/discover_disable'; sub_filter 'queryDresdenDiscovery(url){' 'queryDresdenDiscovery(url){ return Promise.resolve([]);'; - # Do not probe our subnets from Ingress - sub_filter 'probeSubnet(ip) {' 'probeSubnet(ip) { throw new Error(\'avail\');'; - - # Prevent unauthenticated requests to go to Home Assistant, triggering IP bans - sub_filter '/api/config?_=\' + Date.now()' '%%ingress_entry%%/api/config?_=\' + Date.now()'; + # Block attempt to probe subnets + sub_filter '} else if (state === STATE_CHECKSUBNETS) {\n if' '} else if (state === STATE_CHECKSUBNETS) { if (true) {needCheckSubnets = false;state = STATE_IDLE;queueStateAction(E_TIMEOUT, 1000);} else if'; - # Stop guessing URL's - sub_filter 'if (err === \'avail\')' 'if (err === \'avail\' && false)'; + # Block attempt at loading gateway api by adding port + sub_filter 'if (ip.indexOf(\':\') === -1) // no port was specified' 'if (false)'; # Correctly handle redirect to login sub_filter 'window.location.href = \'/pwa/login.html\';' 'window.location.href = \'%%ingress_entry%%/pwa/login.html\';'; @@ -97,4 +95,4 @@ http { sub_filter '' ''; } } -} \ No newline at end of file +} diff --git a/deconz/rootfs/etc/services.d/deconz/discovery b/deconz/rootfs/etc/services.d/deconz/discovery index 96cd7690a92..7d3355412cd 100755 --- a/deconz/rootfs/etc/services.d/deconz/discovery +++ b/deconz/rootfs/etc/services.d/deconz/discovery @@ -1,4 +1,6 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Send deCONZ discovery information to Home Assistant # ============================================================================== diff --git a/deconz/rootfs/etc/services.d/deconz/finish b/deconz/rootfs/etc/services.d/deconz/finish old mode 100644 new mode 100755 index a29ced9a496..f4c53b282d0 --- a/deconz/rootfs/etc/services.d/deconz/finish +++ b/deconz/rootfs/etc/services.d/deconz/finish @@ -1,8 +1,13 @@ -#!/usr/bin/execlineb -S1 +#!/usr/bin/env bashio +# vim: ft=bash # ============================================================================== -# Take down the S6 supervision tree based on service exit code +# Take down the S6 supervision tree when service fails +# s6-overlay docs: https://github.com/just-containers/s6-overlay # ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } -s6-svscanctl -t /var/run/s6/services +if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then + bashio::log.warning "Halt add-on" + exec /run/s6/basedir/bin/halt +fi + +bashio::log.info "Service restart after closing" diff --git a/deconz/rootfs/etc/services.d/deconz/run b/deconz/rootfs/etc/services.d/deconz/run old mode 100644 new mode 100755 index 1e8685e11e4..010299d028b --- a/deconz/rootfs/etc/services.d/deconz/run +++ b/deconz/rootfs/etc/services.d/deconz/run @@ -1,4 +1,6 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Start deCONZ service # ============================================================================== diff --git a/deconz/rootfs/etc/services.d/nginx/finish b/deconz/rootfs/etc/services.d/nginx/finish old mode 100644 new mode 100755 index 5bb07a651c9..f4c53b282d0 --- a/deconz/rootfs/etc/services.d/nginx/finish +++ b/deconz/rootfs/etc/services.d/nginx/finish @@ -1,8 +1,13 @@ -#!/usr/bin/execlineb -S1 -# ============================================================================== -# Take down the S6 supervision tree based on service exit code -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } +#!/usr/bin/env bashio +# vim: ft=bash +# ============================================================================== +# Take down the S6 supervision tree when service fails +# s6-overlay docs: https://github.com/just-containers/s6-overlay +# ============================================================================== -s6-svscanctl -t /var/run/s6/services +if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then + bashio::log.warning "Halt add-on" + exec /run/s6/basedir/bin/halt +fi + +bashio::log.info "Service restart after closing" diff --git a/deconz/rootfs/etc/services.d/nginx/run b/deconz/rootfs/etc/services.d/nginx/run old mode 100644 new mode 100755 index 38ef478552e..e98c4571ac5 --- a/deconz/rootfs/etc/services.d/nginx/run +++ b/deconz/rootfs/etc/services.d/nginx/run @@ -1,4 +1,6 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Start NGINX service # ============================================================================== diff --git a/deconz/rootfs/etc/services.d/otau-ikea/run b/deconz/rootfs/etc/services.d/otau-ikea/run old mode 100644 new mode 100755 index 922a063440e..1f7053d54a0 --- a/deconz/rootfs/etc/services.d/otau-ikea/run +++ b/deconz/rootfs/etc/services.d/otau-ikea/run @@ -1,4 +1,6 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Download available firmware update for IKEA # ============================================================================== diff --git a/deconz/rootfs/etc/services.d/otau-ledvance/run b/deconz/rootfs/etc/services.d/otau-ledvance/run old mode 100644 new mode 100755 index 1697f39aa48..7a69b94c045 --- a/deconz/rootfs/etc/services.d/otau-ledvance/run +++ b/deconz/rootfs/etc/services.d/otau-ledvance/run @@ -1,4 +1,6 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Download available firmware update for OSRAM Ledvance # ============================================================================== diff --git a/deconz/rootfs/etc/services.d/websockify/run b/deconz/rootfs/etc/services.d/websockify/run old mode 100644 new mode 100755 index d75921d60b9..db2eb43503b --- a/deconz/rootfs/etc/services.d/websockify/run +++ b/deconz/rootfs/etc/services.d/websockify/run @@ -1,4 +1,6 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Start ozw-admin # ============================================================================== diff --git a/deconz/translations/en.yaml b/deconz/translations/en.yaml new file mode 100644 index 00000000000..8672c154c49 --- /dev/null +++ b/deconz/translations/en.yaml @@ -0,0 +1,19 @@ +--- +configuration: + device: + name: Device + description: The device address of your ConBee/RaspBee. + dbg_aps: + name: Debug aps + dbg_info: + name: Debug info + dbg_otau: + name: Debug otau + dbg_zcl: + name: Debug zcl + dbg_zdp: + name: Debug zdp +network: + 40850/tcp: deCONZ API backend (Not required for Ingress) + 5900/tcp: deCONZ via VNC (Not required for Ingress. Not secure!) + 8081/tcp: deCONZ WebSocket (Not required for Ingress) diff --git a/dhcp_server/CHANGELOG.md b/dhcp_server/CHANGELOG.md index c9341a77828..7f2b0aa3d7e 100644 --- a/dhcp_server/CHANGELOG.md +++ b/dhcp_server/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## 1.4.0 + +- Update base image to alpine 3.19 + +## 1.3.1 + +- Don't fail if no DNS is provided + +## 1.3.0 + +- Add NTP server configuration option. + ## 1.2 - Fixes crash when using FQDN as domain diff --git a/dhcp_server/DOCS.md b/dhcp_server/DOCS.md index 688bc180ae0..30bdd4d4853 100644 --- a/dhcp_server/DOCS.md +++ b/dhcp_server/DOCS.md @@ -4,9 +4,10 @@ Follow these steps to get the add-on installed on your system: -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. 2. Find the "DHCP server" add-on and click it. 3. Click on the "INSTALL" button. +4. Modify configuration as needed ## How to use @@ -26,6 +27,8 @@ domain: mynetwork.local dns: - 8.8.8.8 - 8.8.4.4 +ntp: + - 192.168.1.0 default_lease: 86400 max_lease: 172800 networks: @@ -35,7 +38,7 @@ networks: range_end: 192.168.1.200 broadcast: 192.168.1.255 gateway: 192.168.1.1 - interface: eth0 + interface: end0 hosts: - name: webcam_xy mac: aa:bb:ee:cc @@ -52,6 +55,11 @@ The DNS servers your DHCP server gives to your clients. This option can contain a list of servers. By default, it is configured to have Google's public DNS servers: `"8.8.8.8", "8.8.4.4". +### Option `ntp` (required) + +The NTP servers your DHCP server gives to your clients. This option can +contain a list of server. By default, none are configured ([]) + ### Option: `default_lease` (required) The default time in seconds that the IP is leased to your client. @@ -102,7 +110,7 @@ This is usually the IP address of your router. #### Option: `networks.interface` -The network interface to listen to for this network, e.g., `eth0`. +The network interface to listen to for this network, e.g., `end0`. ### Option: `hosts` (optional) @@ -138,6 +146,6 @@ In case you've found a bug, please [open an issue on our GitHub][issue]. [discord]: https://discord.gg/c5DvZ4e [forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues +[issue]: https://github.com/home-assistant/addons/issues [reddit]: https://reddit.com/r/homeassistant [repository]: https://github.com/hassio-addons/repository diff --git a/dhcp_server/build.json b/dhcp_server/build.json deleted file mode 100644 index bbf7adee049..00000000000 --- a/dhcp_server/build.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "build_from": { - "aarch64": "homeassistant/aarch64-base:3.10", - "amd64": "homeassistant/amd64-base:3.10", - "armhf": "homeassistant/armhf-base:3.10", - "armv7": "homeassistant/armv7-base:3.10", - "i386": "homeassistant/i386-base:3.10" - } -} diff --git a/dhcp_server/build.yaml b/dhcp_server/build.yaml new file mode 100644 index 00000000000..039821f92e6 --- /dev/null +++ b/dhcp_server/build.yaml @@ -0,0 +1,10 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base:3.19 + amd64: ghcr.io/home-assistant/amd64-base:3.19 + armhf: ghcr.io/home-assistant/armhf-base:3.19 + armv7: ghcr.io/home-assistant/armv7-base:3.19 + i386: ghcr.io/home-assistant/i386-base:3.19 +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io diff --git a/dhcp_server/config.json b/dhcp_server/config.json deleted file mode 100644 index d63f75affb4..00000000000 --- a/dhcp_server/config.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "DHCP server", - "version": "1.2", - "slug": "dhcp_server", - "description": "A simple DHCP server", - "url": "https://home-assistant.io/addons/dhcp_server/", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "advanced": true, - "startup": "system", - "host_network": true, - "options": { - "default_lease": 86400, - "max_lease": 172800, - "domain": null, - "dns": ["8.8.8.8", "8.8.4.4"], - "networks": [ - { - "subnet": "192.168.1.0", - "netmask": "255.255.255.0", - "range_start": "192.168.1.100", - "range_end": "192.168.1.200", - "broadcast": "192.168.1.255", - "gateway": "192.168.1.1", - "interface": "eth0" - } - ], - "hosts": [] - }, - "schema": { - "default_lease": "int", - "max_lease": "int", - "domain": "str", - "dns": ["str"], - "networks": [ - { - "subnet": "str", - "netmask": "str", - "range_start": "str", - "range_end": "str", - "broadcast": "str", - "gateway": "str", - "interface": "str" - } - ], - "hosts": [ - { - "mac": "str", - "name": "str", - "ip": "str" - } - ] - }, - "image": "homeassistant/{arch}-addon-dhcp_server" -} diff --git a/dhcp_server/config.yaml b/dhcp_server/config.yaml new file mode 100644 index 00000000000..62b0dadd56e --- /dev/null +++ b/dhcp_server/config.yaml @@ -0,0 +1,55 @@ +--- +version: 1.4.0 +slug: dhcp_server +name: DHCP server +description: A simple DHCP server +url: https://home-assistant.io/addons/dhcp_server/ +codenotary: notary@home-assistant.io +advanced: true +arch: + - armhf + - armv7 + - aarch64 + - amd64 + - i386 +host_network: true +image: homeassistant/{arch}-addon-dhcp_server +options: + default_lease: 86400 + dns: + - 8.8.8.8 + - 8.8.4.4 + ntp: [] + domain: null + hosts: [] + max_lease: 172800 + networks: + - broadcast: 192.168.1.255 + gateway: 192.168.1.1 + interface: eth0 + netmask: 255.255.255.0 + range_end: 192.168.1.200 + range_start: 192.168.1.100 + subnet: 192.168.1.0 +schema: + default_lease: int + dns: + - str + ntp: + - str + domain: str + hosts: + - ip: str + mac: str + name: str + max_lease: int + networks: + - broadcast: str + gateway: str + interface: str + netmask: str + range_end: str + range_start: str + subnet: str +startup: system +init: false diff --git a/dhcp_server/data/run.sh b/dhcp_server/data/run.sh index 3070d8d60a7..11b673abc7a 100755 --- a/dhcp_server/data/run.sh +++ b/dhcp_server/data/run.sh @@ -1,4 +1,5 @@ -#!/usr/bin/env bashio +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash set -e CONFIG="/etc/dhcpd.conf" @@ -8,18 +9,35 @@ bashio::log.info "Creating DHCP configuration..." # Create main config DEFAULT_LEASE=$(bashio::config 'default_lease') -DNS=$(bashio::config 'dns|join(", ")') DOMAIN=$(bashio::config 'domain') MAX_LEASE=$(bashio::config 'max_lease') { echo "option domain-name \"${DOMAIN}\";" - echo "option domain-name-servers ${DNS};"; echo "default-lease-time ${DEFAULT_LEASE};" echo "max-lease-time ${MAX_LEASE};" echo "authoritative;" } > "${CONFIG}" +# Create DNS Server List +if [ "$(bashio::config 'dns')" ] +then + DNS=$(bashio::config 'dns|join(", ")') + { + echo "option domain-name-servers ${DNS};"; + } >> "${CONFIG}" +fi + + +# Create NTP Server List +if [ "$(bashio::config 'ntp')" ] +then + NTP=$(bashio::config 'ntp|join(", ")') + { + echo "option ntp-servers ${NTP};"; + } >> "${CONFIG}" +fi + # Create networks for network in $(bashio::config 'networks|keys'); do BROADCAST=$(bashio::config "networks[${network}].broadcast") diff --git a/dhcp_server/translations/en.yaml b/dhcp_server/translations/en.yaml new file mode 100644 index 00000000000..fa29373b8e3 --- /dev/null +++ b/dhcp_server/translations/en.yaml @@ -0,0 +1,26 @@ +--- +configuration: + default_lease: + name: Default Lease Time + description: >- + The default time in seconds that the IP is leased to your client. + dns: + name: DNS Servers + description: The DNS servers your DHCP server gives to your clients. + domain: + name: Domain + description: >- + Your network domain name, e.g., `mynetwork.local` or `home.local` + hosts: + name: Hosts + description: >- + This option defines settings for one or host definitions for the DHCP + server. + max_lease: + name: Max Lease Time + description: The max time in seconds that the IP is leased to your client. + networks: + name: Networks + description: >- + This option defines settings for one or multiple networks for the DHCP + server to hand out IP addresses for. diff --git a/dnsmasq/CHANGELOG.md b/dnsmasq/CHANGELOG.md index 5a68babd41d..61ddd24a7ba 100644 --- a/dnsmasq/CHANGELOG.md +++ b/dnsmasq/CHANGELOG.md @@ -1,5 +1,34 @@ # Changelog +## 1.8.1 + +- Fix config bug of cache_size option + +## 1.8.0 + +- Add cache_size option + +## 1.7.0 + +- Update to Alpine 3.19 + +## 1.6.0 + +- Update to Alpine 3.17 +- Limit open file descriptors to 1024 to minimize + +## 1.5.2 + +- Disable DNS request logging by default + +## 1.5.1 + +- Default cnames to empty array + +## 1.5.0 + +- Adds support for CNAME records + ## 1.4.4 - Make it align to our base profile diff --git a/dnsmasq/DOCS.md b/dnsmasq/DOCS.md index fb604bb5da4..f3e26881228 100644 --- a/dnsmasq/DOCS.md +++ b/dnsmasq/DOCS.md @@ -4,7 +4,7 @@ Follow these steps to get the add-on installed on your system: -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. 2. Find the "Dnsmasq" add-on and click it. 3. Click on the "INSTALL" button. @@ -38,6 +38,7 @@ services: port: 389 priority: 0 weight: 100 +log_queries: false ``` ### Option: `defaults` (required) @@ -106,6 +107,26 @@ The priority for the service. The weight for the service. +### Option: `cnames` (optional) + +This option allows you to provide cname records. + +#### Option: `cnames.name` + +The name to resolve. + +#### Option: `cnames.target` + +The target 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 + +### Option: `log_queries` (required) + +Log all DNS requests. Defaults to `false`. + +### Option: `cache_size` + +Sets the size of the Dnsmasq cache. The default setting is 150. If this is set to 0 this disables caching. Note that huge cache sizes can create performance problems. + ## Support Got questions? @@ -120,6 +141,6 @@ In case you've found a bug, please [open an issue on our GitHub][issue]. [discord]: https://discord.gg/c5DvZ4e [forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues +[issue]: https://github.com/home-assistant/addons/issues [reddit]: https://reddit.com/r/homeassistant [repository]: https://github.com/hassio-addons/repository diff --git a/dnsmasq/build.json b/dnsmasq/build.json deleted file mode 100644 index 9ff70b4eb75..00000000000 --- a/dnsmasq/build.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "build_from": { - "aarch64": "homeassistant/aarch64-base:3.13", - "amd64": "homeassistant/amd64-base:3.13", - "armhf": "homeassistant/armhf-base:3.13", - "armv7": "homeassistant/armv7-base:3.13", - "i386": "homeassistant/i386-base:3.13" - } -} diff --git a/dnsmasq/build.yaml b/dnsmasq/build.yaml new file mode 100644 index 00000000000..039821f92e6 --- /dev/null +++ b/dnsmasq/build.yaml @@ -0,0 +1,10 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base:3.19 + amd64: ghcr.io/home-assistant/amd64-base:3.19 + armhf: ghcr.io/home-assistant/armhf-base:3.19 + armv7: ghcr.io/home-assistant/armv7-base:3.19 + i386: ghcr.io/home-assistant/i386-base:3.19 +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io diff --git a/dnsmasq/config.json b/dnsmasq/config.json deleted file mode 100644 index 5f42344b9ba..00000000000 --- a/dnsmasq/config.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "Dnsmasq", - "version": "1.4.4", - "slug": "dnsmasq", - "description": "A simple DNS server", - "url": "https://github.com/home-assistant/hassio-addons/tree/master/dnsmasq", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "advanced": true, - "startup": "system", - "init": false, - "ports": { - "53/tcp": 53, - "53/udp": 53 - }, - "options": { - "defaults": ["8.8.8.8", "8.8.4.4"], - "forwards": [], - "hosts": [], - "services": [] - }, - "schema": { - "defaults": ["str"], - "forwards": [ - { - "domain": "str", - "server": "str" - } - ], - "hosts": [ - { - "host": "str", - "ip": "str" - } - ], - "services": [ - { - "srv": "str", - "host": "str", - "port": "str", - "priority": "int", - "weight": "int" - } - ] - }, - "image": "homeassistant/{arch}-addon-dnsmasq" -} diff --git a/dnsmasq/config.yaml b/dnsmasq/config.yaml new file mode 100644 index 00000000000..45591570b7a --- /dev/null +++ b/dnsmasq/config.yaml @@ -0,0 +1,49 @@ +--- +version: 1.8.1 +slug: dnsmasq +name: Dnsmasq +description: A simple DNS server +url: https://github.com/home-assistant/addons/tree/master/dnsmasq +advanced: true +arch: + - armhf + - armv7 + - aarch64 + - amd64 + - i386 +image: homeassistant/{arch}-addon-dnsmasq +init: false +options: + defaults: + - 8.8.8.8 + - 8.8.4.4 + forwards: [] + hosts: [] + services: [] + cnames: [] + log_queries: false + cache_size: 150 +ports: + 53/tcp: 53 + 53/udp: 53 +schema: + defaults: + - str + forwards: + - domain: str + server: str + hosts: + - host: str + ip: str + services: + - host: str + port: str + priority: int + srv: str + weight: int + cnames: + - name: str + target: str + log_queries: bool + cache_size: int +startup: system diff --git a/dnsmasq/rootfs/etc/cont-init.d/config.sh b/dnsmasq/rootfs/etc/cont-init.d/config.sh old mode 100644 new mode 100755 index 24d3e00d2d6..e1b35e15b5a --- a/dnsmasq/rootfs/etc/cont-init.d/config.sh +++ b/dnsmasq/rootfs/etc/cont-init.d/config.sh @@ -1,4 +1,5 @@ #!/usr/bin/with-contenv bashio +# shellcheck shell=bash # ============================================================================== # DNSMASQ config # ============================================================================== diff --git a/dnsmasq/rootfs/etc/services.d/dnsmasq/finish b/dnsmasq/rootfs/etc/services.d/dnsmasq/finish old mode 100644 new mode 100755 index 2d2d9e526cc..f4c53b282d0 --- a/dnsmasq/rootfs/etc/services.d/dnsmasq/finish +++ b/dnsmasq/rootfs/etc/services.d/dnsmasq/finish @@ -1,8 +1,13 @@ -#!/usr/bin/execlineb -S0 +#!/usr/bin/env bashio +# vim: ft=bash # ============================================================================== -# Take down the S6 supervision tree when dnsmasq fails +# Take down the S6 supervision tree when service fails +# s6-overlay docs: https://github.com/just-containers/s6-overlay # ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } -s6-svscanctl -t /var/run/s6/services +if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then + bashio::log.warning "Halt add-on" + exec /run/s6/basedir/bin/halt +fi + +bashio::log.info "Service restart after closing" diff --git a/dnsmasq/rootfs/etc/services.d/dnsmasq/run b/dnsmasq/rootfs/etc/services.d/dnsmasq/run old mode 100644 new mode 100755 index 028a42945e3..62771823a80 --- a/dnsmasq/rootfs/etc/services.d/dnsmasq/run +++ b/dnsmasq/rootfs/etc/services.d/dnsmasq/run @@ -1,7 +1,13 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash CONFIG="/etc/dnsmasq.conf" # Run dnsmasq bashio::log.info "Starting dnsmasq..." + +# Set max open file limit to speed up startup +ulimit -n 1024 + exec dnsmasq -C "${CONFIG}" -z < /dev/null diff --git a/dnsmasq/rootfs/usr/share/tempio/dnsmasq.config b/dnsmasq/rootfs/usr/share/tempio/dnsmasq.config index 36d416accd9..6068b47d066 100644 --- a/dnsmasq/rootfs/usr/share/tempio/dnsmasq.config +++ b/dnsmasq/rootfs/usr/share/tempio/dnsmasq.config @@ -3,10 +3,13 @@ no-resolv no-hosts keep-in-foreground +{{ if .log_queries }} log-queries +{{ end }} log-facility=- no-poll user=root +cache-size={{ .cache_size}} # Default forward servers {{ range .defaults }} @@ -28,3 +31,7 @@ address=/{{ .host }}/{{ .ip }} srv-host={{ .srv }},{{ .host }},{{ .port }},{{ .priority }},{{ .weight }} {{ end }} +# Static cname +{{ range .cnames }} +cname={{ .name }},{{ .target }} +{{ end }} diff --git a/dnsmasq/translations/en.yaml b/dnsmasq/translations/en.yaml new file mode 100644 index 00000000000..4dd80c5e2c3 --- /dev/null +++ b/dnsmasq/translations/en.yaml @@ -0,0 +1,26 @@ +--- +configuration: + defaults: + name: Upstream Servers + description: The defaults are upstream DNS servers. + forwards: + name: Forwards + description: >- + This option allows you to list domain that are forwarded to a different + (not the default) upstream DNS server. + hosts: + name: Hosts + description: >- + This option allows you to provide local static answer for your DNS server. + services: + name: Services + description: This option allows you to provide srv-host records. + cnames: + name: Cnames + description: Provide cname records for DNSMasq to resolve. + log_queries: + name: Log Queries + description: Log all DNS requests. +network: + 53/tcp: TCP port for DNS requests. + 53/udp: UDP port for DNS requests. diff --git a/duckdns/CHANGELOG.md b/duckdns/CHANGELOG.md index d0d2b26f801..ba3b31c3e1e 100644 --- a/duckdns/CHANGELOG.md +++ b/duckdns/CHANGELOG.md @@ -1,5 +1,30 @@ # Changelog +## 1.18.0 + +- Update to use s6-overlay to manage service +- Update base image to Alpine 3.20 + +## 1.17.0 + +- Reduce log spam when updating IP address + +## 1.16.0 + +- Update base image to Alpine 3.19 +- Update dehydrated to 0.7.1 + +## 1.15.0 + +- Use Supervisor API to detect IPv6 host addresses, selectable by interface +- Split IPv4 and IPv6 updates as duckdns skips v4 detection with v6 present +- Fix misleading help text regarding IPv6 address autodetection +- Disable Docker default system init for S6 update + +## 1.14.0 + +- Add option to specify algorithm used for SSL certificates + ## 1.13.0 - Update base to 3.14 diff --git a/duckdns/DOCS.md b/duckdns/DOCS.md index 3f22e38d3fb..029f013e728 100644 --- a/duckdns/DOCS.md +++ b/duckdns/DOCS.md @@ -4,7 +4,7 @@ Follow these steps to get the add-on installed on your system: -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. 2. Find the "DuckDNS" add-on and click it. 3. Click on the "INSTALL" button. @@ -48,7 +48,7 @@ only apply to Let's Encrypt SSL certificates. #### Option `lets_encrypt.accept_terms` -Once you have read and accepted the Let's Encrypt[Subscriber Agreement](https://letsencrypt.org/repository/), change value to `true` in order to use Let's Encrypt services. +Once you have read and accepted the Let's Encrypt [Subscriber Agreement](https://letsencrypt.org/repository/), change value to `true` in order to use Let's Encrypt services. #### Option `lets_encrypt.certfile` @@ -62,6 +62,15 @@ The name of the private key file generated by Let's Encrypt. The private key fil **Note**: _The file is stored in `/ssl/`, which is the default for Home Assistant_ +#### Option `lets_encrypt.algo` + +Public key algorithm that will be used. + +Supported values: `rsa`, `prime256v1` and `secp384r1`. + +The default is `secp384r1` + + ### Option: `ipv4` (optional) By default, Duck DNS will auto detect your IPv4 address and use that. @@ -121,7 +130,7 @@ The number of seconds to wait before updating DuckDNS subdomains and renewing Le ## Known issues and limitations -- To log in, DuckDNS requires a free account from any of the following services: Google, Github, Twitter, Persona or Reddit. +- To log in, DuckDNS requires a free account from any of the following services: Google, Github, Twitter or Persona. - A free DuckDNS account is limited to five subdomains. - At time of writing, Duck DNS' own IPv6 autodetection [does not actually work][duckdns-faq], but you can use the URL option @@ -141,7 +150,7 @@ In case you've found a bug, please [open an issue on our GitHub][issue]. [discord]: https://discord.gg/c5DvZ4e [forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues +[issue]: https://github.com/home-assistant/addons/issues [reddit]: https://reddit.com/r/homeassistant [duckdns]: https://www.duckdns.org [duckdns-faq]: https://www.duckdns.org/faqs.jsp diff --git a/duckdns/Dockerfile b/duckdns/Dockerfile index a639c87d0e8..5d229bc0d0b 100644 --- a/duckdns/Dockerfile +++ b/duckdns/Dockerfile @@ -8,7 +8,5 @@ RUN apk add --no-cache openssl \ "https://raw.githubusercontent.com/lukas2511/dehydrated/v${DEHYDRATED_VERSION}/dehydrated" \ && chmod a+x /usr/bin/dehydrated -# Copy data -COPY data/*.sh / - -CMD [ "/run.sh" ] +# Copy root filesystem +COPY rootfs / diff --git a/duckdns/build.json b/duckdns/build.json deleted file mode 100644 index 83334ed40b6..00000000000 --- a/duckdns/build.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "build_from": { - "aarch64": "ghcr.io/home-assistant/aarch64-base:3.14", - "amd64": "ghcr.io/home-assistant/amd64-base:3.14", - "armhf": "ghcr.io/home-assistant/armhf-base:3.14", - "armv7": "ghcr.io/home-assistant/armv7-base:3.14", - "i386": "ghcr.io/home-assistant/i386-base:3.14" - }, - "args": { - "DEHYDRATED_VERSION": "0.7.0" - } -} diff --git a/duckdns/build.yaml b/duckdns/build.yaml new file mode 100644 index 00000000000..f0a265a8a4f --- /dev/null +++ b/duckdns/build.yaml @@ -0,0 +1,12 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base:3.20 + amd64: ghcr.io/home-assistant/amd64-base:3.20 + armhf: ghcr.io/home-assistant/armhf-base:3.20 + armv7: ghcr.io/home-assistant/armv7-base:3.20 + i386: ghcr.io/home-assistant/i386-base:3.20 +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io +args: + DEHYDRATED_VERSION: 0.7.1 diff --git a/duckdns/config.json b/duckdns/config.json deleted file mode 100644 index d96bb48e2f8..00000000000 --- a/duckdns/config.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "Duck DNS", - "version": "1.13.0", - "slug": "duckdns", - "description": "Free Dynamic DNS (DynDNS or DDNS) service with Let's Encrypt support", - "url": "https://github.com/home-assistant/hassio-addons/tree/master/duckdns", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "startup": "services", - "map": ["ssl:rw"], - "options": { - "lets_encrypt": { - "accept_terms": false, - "certfile": "fullchain.pem", - "keyfile": "privkey.pem" - }, - "token": null, - "domains": [null], - "aliases": [], - "seconds": 300 - }, - "schema": { - "lets_encrypt": { - "accept_terms": "bool", - "certfile": "str", - "keyfile": "str" - }, - "ipv4": "str?", - "ipv6": "str?", - "token": "str", - "domains": ["match(.+\\.duckdns\\.org)"], - "aliases": [ - {"domain": "str", "alias": "str"} - ], - "seconds": "int" - }, - "image": "homeassistant/{arch}-addon-duckdns" -} diff --git a/duckdns/config.yaml b/duckdns/config.yaml new file mode 100644 index 00000000000..cbd96df24bf --- /dev/null +++ b/duckdns/config.yaml @@ -0,0 +1,45 @@ +--- +version: 1.18.0 +slug: duckdns +name: Duck DNS +description: >- + Free Dynamic DNS (DynDNS or DDNS) service with Let's Encrypt support +url: https://github.com/home-assistant/addons/tree/master/duckdns +arch: + - armhf + - armv7 + - aarch64 + - amd64 + - i386 +hassio_api: true +init: false +image: homeassistant/{arch}-addon-duckdns +map: + - ssl:rw +options: + domains: + - null + token: null + aliases: [] + lets_encrypt: + accept_terms: false + algo: secp384r1 + certfile: fullchain.pem + keyfile: privkey.pem + seconds: 300 +schema: + domains: + - match(.+\.duckdns\.org) + token: str + aliases: + - alias: str + domain: str + lets_encrypt: + accept_terms: bool + algo: list(rsa|prime256v1|secp384r1) + certfile: str + keyfile: str + seconds: int + ipv4: str? + ipv6: str? +startup: services diff --git a/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/dependencies.d/base b/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/dependencies.d/base new file mode 100644 index 00000000000..e69de29bb2d diff --git a/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/finish b/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/finish new file mode 100755 index 00000000000..57efe3f4f85 --- /dev/null +++ b/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/finish @@ -0,0 +1,28 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Home Assistant Community Add-on: chrony +# Take down the S6 supervision tree when chrony fails +# ============================================================================== +# shellcheck disable=SC2155 +readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode + fi + [[ "${exit_code_signal}" -eq 15 ]] && exec /run/s6/basedir/bin/halt +elif [[ "${exit_code_service}" -ne 0 ]]; then + if [[ "${exit_code_container}" -eq 0 ]]; then + echo "${exit_code_service}" > /run/s6-linux-init-container-results/exitcode + fi + exec /run/s6/basedir/bin/halt +fi \ No newline at end of file diff --git a/duckdns/data/run.sh b/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/run similarity index 58% rename from duckdns/data/run.sh rename to duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/run index 969a1b7f9ec..78e01737e02 100755 --- a/duckdns/data/run.sh +++ b/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/run @@ -1,4 +1,6 @@ -#!/usr/bin/env bashio +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash CERT_DIR=/data/letsencrypt WORK_DIR=/data/workdir @@ -12,8 +14,9 @@ if bashio::config.has_value "ipv6"; then IPV6=$(bashio::config 'ipv6'); else IPV TOKEN=$(bashio::config 'token') DOMAINS=$(bashio::config 'domains | join(",")') WAIT_TIME=$(bashio::config 'seconds') +ALGO=$(bashio::config 'lets_encrypt.algo') -# Function that performe a renew +# Function that performs a renew function le_renew() { local domain_args=() local domains='' @@ -36,7 +39,7 @@ function le_renew() { domain_args+=("--domain" "${domain}") done - dehydrated --cron --hook ./hooks.sh --challenge dns-01 "${domain_args[@]}" --out "${CERT_DIR}" --config "${WORK_DIR}/config" || true + dehydrated --cron --algo "${ALGO}" --hook /root/hooks.sh --challenge dns-01 "${domain_args[@]}" --out "${CERT_DIR}" --config "${WORK_DIR}/config" || true LE_UPDATE="$(date +%s)" } @@ -62,21 +65,53 @@ if bashio::config.true 'lets_encrypt.accept_terms'; then fi # Run duckdns +bashio::log.info "Starting DuckDNS..." while true; do [[ ${IPV4} != *:/* ]] && ipv4=${IPV4} || ipv4=$(curl -s -m 10 "${IPV4}") [[ ${IPV6} != *:/* ]] && ipv6=${IPV6} || ipv6=$(curl -s -m 10 "${IPV6}") - if answer="$(curl -s "https://www.duckdns.org/update?domains=${DOMAINS}&token=${TOKEN}&ip=${ipv4}&ipv6=${ipv6}&verbose=true")" && [ "${answer}" != 'KO' ]; then - bashio::log.info "${answer}" - else - bashio::log.warning "${answer}" + # Get IPv6-address from host interface + if [[ -n "$IPV6" && ${ipv6} != *:* ]]; then + ipv6= + bashio::cache.flush_all + for addr in $(bashio::network.ipv6_address "$IPV6"); do + # Skip non-global addresses + if [[ ${addr} != fe80:* && ${addr} != fc* && ${addr} != fd* ]]; then + ipv6=${addr%/*} + break + fi + done + fi + + if [[ ${ipv6} == *:* ]]; then + if answer="$(curl -s "https://www.duckdns.org/update?domains=${DOMAINS}&token=${TOKEN}&ipv6=${ipv6}&verbose=true")" && [ "${answer}" != 'KO' ]; then + if [[ "${answer}" == *NOCHANGE* ]]; then + bashio::log.debug "${answer}" + else + bashio::log.info "${answer}" + fi + else + bashio::log.warning "${answer}" + fi fi - + + if [[ -z ${ipv4} || ${ipv4} == *.* ]]; then + if answer="$(curl -s "https://www.duckdns.org/update?domains=${DOMAINS}&token=${TOKEN}&ip=${ipv4}&verbose=true")" && [ "${answer}" != 'KO' ]; then + if [[ "${answer}" == *NOCHANGE* ]]; then + bashio::log.debug "${answer}" + else + bashio::log.info "${answer}" + fi + else + bashio::log.warning "${answer}" + fi + fi + now="$(date +%s)" if bashio::config.true 'lets_encrypt.accept_terms' && [ $((now - LE_UPDATE)) -ge 43200 ]; then le_renew fi - + sleep "${WAIT_TIME}" done diff --git a/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/type b/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/type new file mode 100644 index 00000000000..1780f9f44ef --- /dev/null +++ b/duckdns/rootfs/etc/s6-overlay/s6-rc.d/duckdns/type @@ -0,0 +1 @@ +longrun \ No newline at end of file diff --git a/duckdns/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/duckdns b/duckdns/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/duckdns new file mode 100644 index 00000000000..e69de29bb2d diff --git a/duckdns/data/hooks.sh b/duckdns/rootfs/root/hooks.sh similarity index 100% rename from duckdns/data/hooks.sh rename to duckdns/rootfs/root/hooks.sh diff --git a/duckdns/translations/en.yaml b/duckdns/translations/en.yaml new file mode 100644 index 00000000000..e6f78fb1d8e --- /dev/null +++ b/duckdns/translations/en.yaml @@ -0,0 +1,36 @@ +--- +configuration: + domains: + name: Domains + description: >- + A list of DuckDNS subdomains registered under your account. An acceptable + naming convention is `my-domain.duckdns.org`. + token: + name: Token + description: >- + The DuckDNS authentication token found at the top of the DuckDNS account + landing page. The token is required to make any changes to the subdomains + registered to your account. + aliases: + name: Alias + description: A list aliases of domains configured on the `domains` option. + lets_encrypt: + name: Let's Encrypt + description: Configure Let's Encrypt options + seconds: + name: Seconds + description: >- + The number of seconds to wait before updating DuckDNS subdomains and + renewing Let's Encrypt certificates. + ipv4: + name: IPv4 + description: >- + By default, DuckDNS will auto detect your IPv4 address and use that. + This option allows you to override the auto-detection and specify an + IPv4 address manually. The value 'none' disables IPv4 updates. + ipv6: + name: IPv6 + description: >- + DuckDNS currently cannot auto-detect your IPv6 address. This option + allows to specify either 'default' or an interface name to use an IPv6 + address of the host, alternatively you can input an address manually. diff --git a/git_pull/CHANGELOG.md b/git_pull/CHANGELOG.md index 0ef82bc087c..7a6034c8734 100644 --- a/git_pull/CHANGELOG.md +++ b/git_pull/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## 8.0.1 +- Fix bashio warn(ing) logger usage breaking deployment keys + +## 8.0.0 +- Refactor git_pull to use HA Api with bashio +- Update base image to Alpine 3.21 +- Remove ha cli dependency + + +## 7.14.1 +- Fix error where $HOME is not defined + +## 7.14.0 + +- Update base image to Alpine 3.19 +- Update Home Assistant CLI to 4.31.0 + ## 7.13.1 - Update Home Assistant CLI to 4.12.2 diff --git a/git_pull/DOCS.md b/git_pull/DOCS.md index 95790a34c9e..4e11e6c3a66 100644 --- a/git_pull/DOCS.md +++ b/git_pull/DOCS.md @@ -4,7 +4,7 @@ Follow these steps to get the add-on installed on your system: -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. 2. Find the "Git pull" add-on and click it. 3. Click on the "INSTALL" button. @@ -150,6 +150,6 @@ In case you've found a bug, please [open an issue on our GitHub][issue]. [discord]: https://discord.gg/c5DvZ4e [forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues +[issue]: https://github.com/home-assistant/addons/issues [reddit]: https://reddit.com/r/homeassistant [repository]: https://github.com/hassio-addons/repository diff --git a/git_pull/Dockerfile b/git_pull/Dockerfile index 732139a5d11..f4d9a5c70b3 100644 --- a/git_pull/Dockerfile +++ b/git_pull/Dockerfile @@ -4,13 +4,6 @@ FROM $BUILD_FROM # Setup base RUN apk add --no-cache jq curl git openssh-client -# Home Assistant CLI -ARG BUILD_ARCH -ARG CLI_VERSION -RUN curl -Lso /usr/bin/ha \ - "https://github.com/home-assistant/cli/releases/download/${CLI_VERSION}/ha_${BUILD_ARCH}" \ - && chmod a+x /usr/bin/ha - # Copy data COPY data/run.sh / diff --git a/git_pull/build.json b/git_pull/build.json deleted file mode 100644 index 410226e9479..00000000000 --- a/git_pull/build.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "build_from": { - "aarch64": "ghcr.io/home-assistant/aarch64-base:3.13", - "amd64": "ghcr.io/home-assistant/amd64-base:3.13", - "armhf": "ghcr.io/home-assistant/armhf-base:3.13", - "armv7": "ghcr.io/home-assistant/armv7-base:3.13", - "i386": "ghcr.io/home-assistant/i386-base:3.13" - }, - "args": { - "CLI_VERSION": "4.12.2" - } -} diff --git a/git_pull/build.yaml b/git_pull/build.yaml new file mode 100644 index 00000000000..1e6de937829 --- /dev/null +++ b/git_pull/build.yaml @@ -0,0 +1,10 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base:3.21 + amd64: ghcr.io/home-assistant/amd64-base:3.21 + armhf: ghcr.io/home-assistant/armhf-base:3.21 + armv7: ghcr.io/home-assistant/armv7-base:3.21 + i386: ghcr.io/home-assistant/i386-base:3.21 +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io diff --git a/git_pull/config.json b/git_pull/config.json deleted file mode 100644 index 17af2d1fe8f..00000000000 --- a/git_pull/config.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "name": "Git pull", - "version": "7.13.1", - "slug": "git_pull", - "description": "Simple git pull to update the local configuration", - "url": "https://github.com/home-assistant/hassio-addons/tree/master/git_pull", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "advanced": true, - "init": false, - "startup": "services", - "boot": "manual", - "hassio_api": true, - "hassio_role": "homeassistant", - "map": ["config:rw"], - "options": { - "deployment_key": [], - "deployment_key_protocol": "rsa", - "deployment_user": "", - "deployment_password": "", - "git_branch": "master", - "git_command": "pull", - "git_remote": "origin", - "git_prune": false, - "repository": null, - "auto_restart": false, - "restart_ignore": ["ui-lovelace.yaml", ".gitignore"], - "repeat": { - "active": false, - "interval": 300 - } - }, - "schema": { - "deployment_key": ["str"], - "deployment_key_protocol": "match(rsa|dsa|ecdsa|ed25519|rsa)", - "deployment_user": "str", - "deployment_password": "password", - "git_branch": "str", - "git_command": "list(pull|reset)", - "git_remote": "str", - "git_prune": "bool", - "repository": "str", - "auto_restart": "bool", - "restart_ignore": ["str"], - "repeat": { - "active": "bool", - "interval": "int" - } - }, - "image": "homeassistant/{arch}-addon-git_pull" -} diff --git a/git_pull/config.yaml b/git_pull/config.yaml new file mode 100644 index 00000000000..1fd689f2161 --- /dev/null +++ b/git_pull/config.yaml @@ -0,0 +1,55 @@ +--- +version: 8.0.1 +slug: git_pull +name: Git pull +description: Simple git pull to update the local configuration +url: https://github.com/home-assistant/addons/tree/master/git_pull +advanced: true +arch: + - armhf + - armv7 + - aarch64 + - amd64 + - i386 +boot: manual +hassio_api: true +hassio_role: homeassistant +image: homeassistant/{arch}-addon-git_pull +init: false +map: + - config:rw +options: + repository: null + git_branch: master + git_remote: origin + auto_restart: false + restart_ignore: + - ui-lovelace.yaml + - .gitignore + git_command: pull + git_prune: false + deployment_key: [] + deployment_user: "" + deployment_password: "" + deployment_key_protocol: rsa + repeat: + active: false + interval: 300 +schema: + repository: str + git_branch: str + git_remote: str + auto_restart: bool + restart_ignore: + - str + git_command: list(pull|reset) + git_prune: bool + deployment_key: + - str + deployment_user: str + deployment_password: password + deployment_key_protocol: match(rsa|dsa|ecdsa|ed25519|rsa) + repeat: + active: bool + interval: int +startup: services diff --git a/git_pull/data/run.sh b/git_pull/data/run.sh index d08cae89c7c..0f5cae42abb 100755 --- a/git_pull/data/run.sh +++ b/git_pull/data/run.sh @@ -1,27 +1,29 @@ -#!/bin/bash - -#### config #### +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# shellcheck disable=SC2034 CONFIG_PATH=/data/options.json - -DEPLOYMENT_KEY=$(jq --raw-output ".deployment_key[]" $CONFIG_PATH) -DEPLOYMENT_KEY_PROTOCOL=$(jq --raw-output ".deployment_key_protocol" $CONFIG_PATH) -DEPLOYMENT_USER=$(jq --raw-output ".deployment_user" $CONFIG_PATH) -DEPLOYMENT_PASSWORD=$(jq --raw-output ".deployment_password" $CONFIG_PATH) -GIT_BRANCH=$(jq --raw-output '.git_branch' $CONFIG_PATH) -GIT_COMMAND=$(jq --raw-output '.git_command' $CONFIG_PATH) -GIT_REMOTE=$(jq --raw-output '.git_remote' $CONFIG_PATH) -GIT_PRUNE=$(jq --raw-output '.git_prune' $CONFIG_PATH) -REPOSITORY=$(jq --raw-output '.repository' $CONFIG_PATH) -AUTO_RESTART=$(jq --raw-output '.auto_restart' $CONFIG_PATH) -RESTART_IGNORED_FILES=$(jq --raw-output '.restart_ignore | join(" ")' $CONFIG_PATH) -REPEAT_ACTIVE=$(jq --raw-output '.repeat.active' $CONFIG_PATH) -REPEAT_INTERVAL=$(jq --raw-output '.repeat.interval' $CONFIG_PATH) +HOME=~ + +DEPLOYMENT_KEY=$(bashio::config 'deployment_key') +DEPLOYMENT_KEY_PROTOCOL=$(bashio::config 'deployment_key_protocol') +DEPLOYMENT_USER=$(bashio::config 'deployment_user') +DEPLOYMENT_PASSWORD=$(bashio::config 'deployment_password') +GIT_BRANCH=$(bashio::config 'git_branch') +GIT_COMMAND=$(bashio::config 'git_command') +GIT_REMOTE=$(bashio::config 'git_remote') +GIT_PRUNE=$(bashio::config 'git_prune') +REPOSITORY=$(bashio::config 'repository') +AUTO_RESTART=$(bashio::config 'auto_restart') +RESTART_IGNORED_FILES=$(bashio::config 'restart_ignore | join(" ")') +REPEAT_ACTIVE=$(bashio::config 'repeat.active') +REPEAT_INTERVAL=$(bashio::config 'repeat.interval') ################ #### functions #### function add-ssh-key { - echo "[Info] Start adding SSH key" + bashio::log.info "[Info] Start adding SSH key" mkdir -p ~/.ssh ( @@ -29,7 +31,7 @@ function add-ssh-key { echo " StrictHostKeyChecking no" ) > ~/.ssh/config - echo "[Info] Setup deployment_key on id_${DEPLOYMENT_KEY_PROTOCOL}" + bashio::log.info "[Info] Setup deployment_key on id_${DEPLOYMENT_KEY_PROTOCOL}" rm -f "${HOME}/.ssh/id_${DEPLOYMENT_KEY_PROTOCOL}" while read -r line; do echo "$line" >> "${HOME}/.ssh/id_${DEPLOYMENT_KEY_PROTOCOL}" @@ -42,17 +44,17 @@ function add-ssh-key { function git-clone { # create backup BACKUP_LOCATION="/tmp/config-$(date +%Y-%m-%d_%H-%M-%S)" - echo "[Info] Backup configuration to $BACKUP_LOCATION" + bashio::log.info "[Info] Backup configuration to $BACKUP_LOCATION" - mkdir "${BACKUP_LOCATION}" || { echo "[Error] Creation of backup directory failed"; exit 1; } - cp -rf /config/* "${BACKUP_LOCATION}" || { echo "[Error] Copy files to backup directory failed"; exit 1; } + mkdir "${BACKUP_LOCATION}" || bashio::exit.nok "[Error] Creation of backup directory failed" + cp -rf /config/* "${BACKUP_LOCATION}" || bashio::exit.nok "[Error] Copy files to backup directory failed" # remove config folder content - rm -rf /config/{,.[!.],..?}* || { echo "[Error] Clearing /config failed"; exit 1; } + rm -rf /config/{,.[!.],..?}* || bashio::exit.nok "[Error] Clearing /config failed" # git clone - echo "[Info] Start git clone" - git clone "$REPOSITORY" /config || { echo "[Error] Git clone failed"; exit 1; } + bashio::log.info "[Info] Start git clone" + git clone "$REPOSITORY" /config || bashio::exit.nok "[Error] Git clone failed" # try to copy non yml files back cp "${BACKUP_LOCATION}" "!(*.yaml)" /config 2>/dev/null @@ -63,14 +65,14 @@ function git-clone { function check-ssh-key { if [ -n "$DEPLOYMENT_KEY" ]; then - echo "Check SSH connection" + bashio::log.info "Check SSH connection" IFS=':' read -ra GIT_URL_PARTS <<< "$REPOSITORY" # shellcheck disable=SC2029 DOMAIN="${GIT_URL_PARTS[0]}" if OUTPUT_CHECK=$(ssh -T -o "StrictHostKeyChecking=no" -o "BatchMode=yes" "$DOMAIN" 2>&1) || { [[ $DOMAIN = *"@github.com"* ]] && [[ $OUTPUT_CHECK = *"You've successfully authenticated"* ]]; }; then - echo "[Info] Valid SSH connection for $DOMAIN" + bashio::log.info "[Info] Valid SSH connection for $DOMAIN" else - echo "[Warn] No valid SSH connection for $DOMAIN" + bashio::log.warning "[Warn] No valid SSH connection for $DOMAIN" add-ssh-key fi fi @@ -79,7 +81,7 @@ fi function setup-user-password { if [ -n "$DEPLOYMENT_USER" ]; then cd /config || return - echo "[Info] setting up credential.helper for user: ${DEPLOYMENT_USER}" + bashio::log.info "[Info] setting up credential.helper for user: ${DEPLOYMENT_USER}" git config --system credential.helper 'store --file=/tmp/git-credentials' # Extract the hostname from repository @@ -107,7 +109,7 @@ password=${DEPLOYMENT_PASSWORD} " # Use git commands to write the credentials to ~/.git-credentials - echo "[Info] Saving git credentials to /tmp/git-credentials" + bashio::log.info "[Info] Saving git credentials to /tmp/git-credentials" # shellcheck disable=SC2259 git credential fill | git credential approve <<< "$cred_data" fi @@ -115,116 +117,121 @@ fi function git-synchronize { # is /config a local git repo? - if git rev-parse --is-inside-work-tree &>/dev/null - then - echo "[Info] Local git repository exists" - - # Is the local repo set to the correct origin? - CURRENTGITREMOTEURL=$(git remote get-url --all "$GIT_REMOTE" | head -n 1) - if [ "$CURRENTGITREMOTEURL" = "$REPOSITORY" ] - then - echo "[Info] Git origin is correctly set to $REPOSITORY" - OLD_COMMIT=$(git rev-parse HEAD) - - # Always do a fetch to update repos - echo "[Info] Start git fetch..." - git fetch "$GIT_REMOTE" || { echo "[Error] Git fetch failed"; return 1; } - - # Prune if configured - if [ "$GIT_PRUNE" == "true" ] - then - echo "[Info] Start git prune..." - git prune || { echo "[Error] Git prune failed"; return 1; } - fi + if ! git rev-parse --is-inside-work-tree &>/dev/null; then + bashio::log.warning "[Warn] Git repository doesn't exist" + git-clone + return + fi - # Do we switch branches? - GIT_CURRENT_BRANCH=$(git rev-parse --symbolic-full-name --abbrev-ref HEAD) - if [ -z "$GIT_BRANCH" ] || [ "$GIT_BRANCH" == "$GIT_CURRENT_BRANCH" ]; then - echo "[Info] Staying on currently checked out branch: $GIT_CURRENT_BRANCH..." - else - echo "[Info] Switching branches - start git checkout of branch $GIT_BRANCH..." - git checkout "$GIT_BRANCH" || { echo "[Error] Git checkout failed"; exit 1; } - GIT_CURRENT_BRANCH=$(git rev-parse --symbolic-full-name --abbrev-ref HEAD) - fi + bashio::log.info "[Info] Local git repository exists" + # Is the local repo set to the correct origin? + CURRENTGITREMOTEURL=$(git remote get-url --all "$GIT_REMOTE" | head -n 1) + if [ "$CURRENTGITREMOTEURL" != "$REPOSITORY" ]; then + bashio::exit.nok "[Error] git origin does not match $REPOSITORY!"; + return + fi - # Pull or reset depending on user preference - case "$GIT_COMMAND" in - pull) - echo "[Info] Start git pull..." - git pull || { echo "[Error] Git pull failed"; return 1; } - ;; - reset) - echo "[Info] Start git reset..." - git reset --hard "$GIT_REMOTE"/"$GIT_CURRENT_BRANCH" || { echo "[Error] Git reset failed"; return 1; } - ;; - *) - echo "[Error] Git command is not set correctly. Should be either 'reset' or 'pull'" - exit 1 - ;; - esac - else - echo "[Error] git origin does not match $REPOSITORY!"; exit 1; - fi + bashio::log.info "[Info] Git origin is correctly set to $REPOSITORY" + OLD_COMMIT=$(git rev-parse HEAD) + # Always do a fetch to update repos + bashio::log.info "[Info] Start git fetch..." + git fetch "$GIT_REMOTE" "$GIT_BRANCH" || bashio::exit.nok "[Error] Git fetch failed"; + + # Prune if configured + if [ "$GIT_PRUNE" == "true" ] + then + bashio::log.info "[Info] Start git prune..." + git prune || bashio::exit.nok "[Error] Git prune failed"; + fi + + # Do we switch branches? + GIT_CURRENT_BRANCH=$(git rev-parse --symbolic-full-name --abbrev-ref HEAD) + if [ -z "$GIT_BRANCH" ] || [ "$GIT_BRANCH" == "$GIT_CURRENT_BRANCH" ]; then + bashio::log.info "[Info] Staying on currently checked out branch: $GIT_CURRENT_BRANCH..." else - echo "[Warn] Git repostory doesn't exist" - git-clone + bashio::log.info "[Info] Switching branches - start git checkout of branch $GIT_BRANCH..." + git checkout "$GIT_BRANCH" || bashio::exit.nok "[Error] Git checkout failed" + GIT_CURRENT_BRANCH=$(git rev-parse --symbolic-full-name --abbrev-ref HEAD) fi + + # Pull or reset depending on user preference + case "$GIT_COMMAND" in + pull) + bashio::log.info "[Info] Start git pull..." + git pull || bashio::exit.nok "[Error] Git pull failed"; + ;; + reset) + bashio::log.info "[Info] Start git reset..." + git reset --hard "$GIT_REMOTE"/"$GIT_CURRENT_BRANCH" || bashio::exit.nok "[Error] Git reset failed"; + ;; + *) + bashio::exit.nok "[Error] Git command is not set correctly. Should be either 'reset' or 'pull'" + ;; + esac } function validate-config { - echo "[Info] Checking if something has changed..." + bashio::log.info "[Info] Checking if something has changed..." # Compare commit ids & check config NEW_COMMIT=$(git rev-parse HEAD) - if [ "$NEW_COMMIT" != "$OLD_COMMIT" ]; then - echo "[Info] Something has changed, checking Home-Assistant config..." - if ha --no-progress core check; then - if [ "$AUTO_RESTART" == "true" ]; then - DO_RESTART="false" - CHANGED_FILES=$(git diff "$OLD_COMMIT" "$NEW_COMMIT" --name-only) - echo "Changed Files: $CHANGED_FILES" - if [ -n "$RESTART_IGNORED_FILES" ]; then - for changed_file in $CHANGED_FILES; do - restart_required_file="" - for restart_ignored_file in $RESTART_IGNORED_FILES; do - if [ -d "$restart_ignored_file" ]; then - # file to be ignored is a whole dir - restart_required_file=$(echo "${changed_file}" | grep "^${restart_ignored_file}") - else - restart_required_file=$(echo "${changed_file}" | grep "^${restart_ignored_file}$") - fi - # break on first match - if [ -n "$restart_required_file" ]; then break; fi - done - if [ -z "$restart_required_file" ]; then - DO_RESTART="true" - echo "[Info] Detected restart-required file: $changed_file" - fi - done - else - DO_RESTART="true" - fi - if [ "$DO_RESTART" == "true" ]; then - echo "[Info] Restart Home-Assistant" - ha --no-progress core restart 2&> /dev/null + if [ "$NEW_COMMIT" == "$OLD_COMMIT" ]; then + bashio::log.info "[Info] Nothing has changed." + return + fi + bashio::log.info "[Info] Something has changed, checking Home-Assistant config..." + if ! bashio::core.check; then + bashio::log.error "[Error] Configuration updated but it does not pass the config check. Do not restart until this is fixed!" + return + fi + if [ "$AUTO_RESTART" != "true" ]; then + bashio::log.info "[Info] Local configuration has changed. Restart required." + return + fi + DO_RESTART="false" + CHANGED_FILES=$(git diff "$OLD_COMMIT" "$NEW_COMMIT" --name-only) + bashio::log.info "Changed Files: $CHANGED_FILES" + if [ -n "$RESTART_IGNORED_FILES" ]; then + for changed_file in $CHANGED_FILES; do + restart_required_file="" + for restart_ignored_file in $RESTART_IGNORED_FILES; do + bashio::log.info "[Info] Checking: $changed_file for $restart_ignored_file" + if [ -d "$restart_ignored_file" ]; then + # file to be ignored is a whole dir + set +e + restart_required_file=$(echo "${changed_file}" | grep "^${restart_ignored_file}") + set -e else - echo "[Info] No Restart Required, only ignored changes detected" + set +e + restart_required_file=$(echo "${changed_file}" | grep "^${restart_ignored_file}$") + set -e fi + # break on first match + if [ -n "$restart_required_file" ]; then break; fi + done + if [ -z "$restart_required_file" ]; then + DO_RESTART="true" + bashio::log.info "[Info] Detected restart-required file: $changed_file" else - echo "[Info] Local configuration has changed. Restart required." + bashio::log.info "[Info] Detected ignored file: $changed_file" fi - else - echo "[Error] Configuration updated but it does not pass the config check. Do not restart until this is fixed!" - fi + done + else + DO_RESTART="true" + fi + + if [ "$DO_RESTART" == "true" ]; then + bashio::log.info "[Info] Restart Home-Assistant" + bashio::core.restart else - echo "[Info] Nothing has changed." + bashio::log.info "[Info] No Restart Required, only ignored changes detected" fi } ################### #### Main program #### -cd /config || { echo "[Error] Failed to cd into /config"; exit 1; } +cd /config || bashio::exit.nok "[Error] Failed to cd into /config"; while true; do check-ssh-key diff --git a/git_pull/translations/en.yaml b/git_pull/translations/en.yaml new file mode 100644 index 00000000000..f7e687cc2c2 --- /dev/null +++ b/git_pull/translations/en.yaml @@ -0,0 +1,55 @@ +--- +configuration: + repository: + name: Repository + description: Git URL to your repository. + git_branch: + name: Git Branch + description: >- + Branch name of the Git repo. If left empty, the currently checked out + branch will be updated. Leave this as 'master' if you are unsure. + git_remote: + name: Git Remote + description: >- + Name of the tracked repository. Leave this as `origin` if you are unsure. + auto_restart: + name: Auto restart + description: >- + Restart Home Assistant when the configuration has changed (and is valid). + restart_ignore: + name: Restart Ignore + description: >- + When `auto_restart` is enabled, changes to these files will not make HA + restart. Full directories to ignore can be specified. + git_command: + name: Git Command + description: Command to run. Leave this as `pull` if you are unsure. + git_prune: + name: Git Prune + description: >- + If enabled, the add-on will clean-up branches that are deleted on the + remote repository, but still have cached entries on the local machine. + Leave this as `false` if you are unsure. + deployment_key: + name: Deployment Key + description: >- + A private SSH key that will be used for communication during Git + operations. + deployment_user: + name: Deployment User + description: >- + Username to use when authenticating to a repository with a username and + password. + deployment_password: + name: Deployment Password + description: >- + Password to use when authenticating to a repository. Ignored if + `deployment_user` is not set. + deployment_key_protocol: + name: Deployment Key Protocol + description: The key protocol + repeat: + name: Polling + description: >- + Configure the Git pull add-on to poll the repository for updates + periodically automatically. diff --git a/google_assistant/DOCS.md b/google_assistant/DOCS.md index a052144ee10..858da0777ef 100644 --- a/google_assistant/DOCS.md +++ b/google_assistant/DOCS.md @@ -4,7 +4,7 @@ Follow these steps to get the add-on installed on your system: -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. 2. Find the "Google Assistant SDK" add-on and click it. 3. Click on the "INSTALL" button. @@ -101,14 +101,14 @@ You have several options to get them answered: In case you've found a bug, please [open an issue on our GitHub][issue]. [discord]: https://discord.gg/c5DvZ4e -[documentation]: https://github.com/home-assistant/hassio-addons/blob/master/google_assistant/DOCS.md +[documentation]: https://github.com/home-assistant/addons/blob/master/google_assistant/DOCS.md [forum]: https://community.home-assistant.io [google-actions-console]: https://console.actions.google.com/ [google-assistant-api]: https://console.developers.google.com/apis/api/embeddedassistant.googleapis.com/overview [google-oauth-client]: https://console.developers.google.com/apis/credentials/oauthclient [google-oauth-concent]: https://console.developers.google.com/apis/credentials/consent [google-platform-project]: https://console.cloud.google.com/project -[issue]: https://github.com/home-assistant/hassio-addons/issues +[issue]: https://github.com/home-assistant/addons/issues [reddit]: https://reddit.com/r/homeassistant [repository]: https://github.com/hassio-addons/repository -[samba-addon]: https://github.com/home-assistant/hassio-addons/tree/master/samba +[samba-addon]: https://github.com/home-assistant/addons/tree/master/samba diff --git a/google_assistant/README.md b/google_assistant/README.md index 3ced66bc896..a4e051c5265 100644 --- a/google_assistant/README.md +++ b/google_assistant/README.md @@ -1,5 +1,12 @@ # Home Assistant Add-on: Google Assistant SDK +> [!CAUTION] +> **Deprecation notice** +> The [Google Assistant SDK for device][google-assistant-sdk] Python library +> this add-on depends on is no longer developed and has been archived. The +> OAuth out-of-band (OOB) flow used by the add-on has been deprecated as well. +> Hence a new setup is currently no longer possible. + A virtual personal assistant developed by Google. ![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield] @@ -21,5 +28,6 @@ If you want to use Google Assistant (for example, from your phone or Google Home [google-actions]: https://actions.google.com/ [google-assistant-integration]: https://www.home-assistant.io/integrations/google_assistant/ [google-assistant]: https://assistant.google.com/ +[google-assistant-sdk]: https://github.com/googlesamples/assistant-sdk-python [i386-shield]: https://img.shields.io/badge/i386-no-red.svg [aarch64-shield]: https://img.shields.io/badge/aarch64-no-red.svg diff --git a/google_assistant/build.json b/google_assistant/build.json deleted file mode 100644 index f39a42b0ac6..00000000000 --- a/google_assistant/build.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "build_from": { - "armhf": "homeassistant/armhf-base-debian:buster", - "armv7": "homeassistant/armv7-base-debian:buster", - "amd64": "homeassistant/amd64-base-debian:buster" - }, - "args": { - "GOOGLE_GRPC_VERSION": "0.2.0", - "GOOGLE_LIBRARY_VERSION": "1.0.0", - "GOOGLE_SDK_VERSION": "0.5.0", - "GOOGLE_AUTH_VERSION": "1.6.3", - "REQUESTS_OAUTHLIB_VERSION": "1.2.0", - "CHERRYPY_VERSION": "18.1.1" - } -} diff --git a/google_assistant/build.yaml b/google_assistant/build.yaml new file mode 100644 index 00000000000..543b6f7ace1 --- /dev/null +++ b/google_assistant/build.yaml @@ -0,0 +1,15 @@ +--- +build_from: + amd64: ghcr.io/home-assistant/amd64-base-debian:buster + armhf: ghcr.io/home-assistant/armhf-base-debian:buster + armv7: ghcr.io/home-assistant/armv7-base-debian:buster +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io +args: + CHERRYPY_VERSION: 18.1.1 + GOOGLE_AUTH_VERSION: 1.6.3 + GOOGLE_GRPC_VERSION: 0.2.0 + GOOGLE_LIBRARY_VERSION: 1.0.0 + GOOGLE_SDK_VERSION: 0.5.0 + REQUESTS_OAUTHLIB_VERSION: 1.2.0 diff --git a/google_assistant/config.json b/google_assistant/config.json deleted file mode 100644 index 8da4390f2c9..00000000000 --- a/google_assistant/config.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "Google Assistant SDK", - "version": "2.5.0", - "slug": "google_assistant", - "description": "A virtual personal assistant developed by Google", - "url": "https://github.com/home-assistant/hassio-addons/tree/master/google_assistant", - "arch": ["armhf", "armv7", "amd64"], - "init": false, - "advanced": true, - "stage": "experimental", - "map": ["share"], - "audio": true, - "ports": { - "9324/tcp": 9324 - }, - "webui": "http://[HOST]:[PORT:9324]", - "options": { - "client_secrets": "google_assistant.json", - "project_id": null, - "model_id": null, - "feedback": { - "enable": false, - "volume": 80 - } - }, - "schema": { - "client_secrets": "str", - "project_id": "str", - "model_id": "str", - "feedback": { - "enable": "bool", - "volume": "int(0,100)" - } - }, - "image": "homeassistant/{arch}-addon-google_assistant" -} diff --git a/google_assistant/config.yaml b/google_assistant/config.yaml new file mode 100644 index 00000000000..37fb29ab41a --- /dev/null +++ b/google_assistant/config.yaml @@ -0,0 +1,35 @@ +--- +version: 2.5.0 +slug: google_assistant +name: Google Assistant SDK +description: A virtual personal assistant developed by Google +url: >- + https://github.com/home-assistant/addons/tree/master/google_assistant +advanced: true +arch: + - armhf + - armv7 + - amd64 +audio: true +image: homeassistant/{arch}-addon-google_assistant +init: false +map: + - share +options: + project_id: null + client_secrets: google_assistant.json + model_id: null + feedback: + enable: false + volume: 80 +ports: + 9324/tcp: 9324 +schema: + project_id: str + client_secrets: str + model_id: str + feedback: + enable: bool + volume: int(0,100) +stage: deprecated +webui: http://[HOST]:[PORT:9324] diff --git a/google_assistant/rootfs/etc/services.d/google-assistant/finish b/google_assistant/rootfs/etc/services.d/google-assistant/finish old mode 100644 new mode 100755 index 046043b2eb9..5a23d05348c --- a/google_assistant/rootfs/etc/services.d/google-assistant/finish +++ b/google_assistant/rootfs/etc/services.d/google-assistant/finish @@ -1,8 +1,12 @@ -#!/usr/bin/execlineb -S0 +#!/usr/bin/env bashio # ============================================================================== -# Take down the S6 supervision tree when Google Assistant fails +# Take down the S6 supervision tree when service fails +# s6-overlay docs: https://github.com/just-containers/s6-overlay # ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } -s6-svscanctl -t /var/run/s6/services \ No newline at end of file +if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then + bashio::log.warning "Halt add-on" + exec /run/s6/basedir/bin/halt +fi + +bashio::log.info "Service restart after closing" diff --git a/google_assistant/rootfs/etc/services.d/google-assistant/run b/google_assistant/rootfs/etc/services.d/google-assistant/run old mode 100644 new mode 100755 diff --git a/google_assistant/translations/en.yaml b/google_assistant/translations/en.yaml new file mode 100644 index 00000000000..8383294621c --- /dev/null +++ b/google_assistant/translations/en.yaml @@ -0,0 +1,20 @@ +--- +configuration: + project_id: + name: Project ID + description: >- + Project ID of the project you've created at Google for this add-on. + client_secrets: + name: Client Secrets + description: >- + The name of the client secrets file to you've downloaded from Google and + placed in your `/share` folder. + model_id: + name: Model ID + description: >- + The ID of the model you've registered at Google for this add-on. + feedback: + name: Feedback + description: Control feedback options +network: + 9324/tcp: The port for the Webserver diff --git a/homematic/CHANGELOG.md b/homematic/CHANGELOG.md deleted file mode 100644 index a68d6b1b267..00000000000 --- a/homematic/CHANGELOG.md +++ /dev/null @@ -1,75 +0,0 @@ -# Changelog - -## 11.3.0 - -- Update OCCU to 3.59.6 - -## 11.2.2 - -- Revert restart nginx service on error - -## 11.2.1 - -- Restart nginx service on error - -## 11.2.0 - -- Update OCCU to 3.55.10 - -## 11.1.0 - -- Migrate OCCU back to EQ3 -- Use Home helper again -- Update hardware configuration for Supervisor 2021.02.5 - -## 11.0.6 - -- Persist groups - -## 11.0.5 - -- Skip HmIP firmware update for udev path -- Persist certificate - -## 11.0.4 - -- Fix template for hmip - -## 11.0.3 - -- Fix Ingress path - -## 11.0.2 - -- Fix issue with library -- Take container down on ReGaHss error - -## 11.0.1 - -- Small cleanup with s6-overlay - -## 11.0.0 - -- Migrate to s6-overlay & tempio -- Update OCCU to 3.55.5-1 - -## 10.3.0 - -- Flush ReGaHss config on shutdown -- Add ReGaHss reset option - -## 10.2.0 - -- Update Bashio to fix the wait function -- Extend the log output - -## 10.1.0 - -- Fix issue with SSL - -## 10.0.0 - -- Add Ingress support -- Disable external ports per default -- Fix wrong version number -- Speedup start without sleeps diff --git a/homematic/DOCS.md b/homematic/DOCS.md deleted file mode 100644 index 51c183fdf80..00000000000 --- a/homematic/DOCS.md +++ /dev/null @@ -1,158 +0,0 @@ -# Home Assistant Add-on: HomeMatic - -## Installation - -Follow these steps to get the add-on installed on your system: - -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. -2. Find the "HomeMatic CCU" add-on and click it. -3. Click on the "INSTALL" button. - -## How to use - -1. Properly configure the add-on config (see below). -2. Start the add-on. -3. Check the add-on log output to see if it started successfully. -4. Add homematic to your Home Assistant configuration (also see below). -5. Restart Home Assistant. - -## Configuration - -Add-on configuration: - -```yaml -rf_enable: true -rf: - - type: CCU2 - device: "/dev/ttyAMA0" -wired_enable: false -wired: - - serial: xy - key: abc - ip: 192.168.0.0 -hmip_enable: false -hmip: - - type: HMIP_CCU2 - device: "/dev/ttyUSB0" -regahss_reset: false -``` - -### Option: `rf_enable` (required) - -Enable or disable BidCoS-RF. - -### Option: `rf` - -List of RF devices. - -#### Option: `rf.type` (required) - -Device type for RFD service. Check your device manual. - -- HM-MOD-RPI-PCB: `CCU2` - -#### Option: `rf.device` (required) - -Device on the host. - -### Option: `wired_enable` (required) - -Enable or disable BidCoS-Wired. - -### Option: `wired` - -List of wired devices. - -#### Option: `wired.serial` (required) - -Serial number of the device. - -#### Option: `wired.key` (required) - -Encryption key for the device. - -#### Option: `wired.ip` (required) - -IP address of LAN gateway. - -### Option: `hmip_enable` (required) - -Enable or disable hmip. - -### Option: `hmip` - -List of HMIP devices. - -#### Option: `hmip.type` (required) - -Device type for HMIP service. Check your device manual. - -- HmIP-RFUSB: `HMIP_CCU2` - -#### Option: `hmip.device` (required) - -Device on the host. - -#### Option: `regahss_reset` - -If this is set and enabled, the ReGaHss setting will be removed before it will be started. - -## Home Assistant configuration - -Add the following to your Home Assistant configuration to enable -the integration: - -```yaml -homematic: - interfaces: - rf: - host: core-homematic - port: 2001 - wired: - host: core-homematic - port: 2000 - hmip: - host: core-homematic - port: 2010 - group: - host: core-homematic - port: 9292 - path: /groups -``` - -## Raspberry Pi3 - -If you use the HM-MOD-RPI-PCB on a Raspberry Pi 3, you need to add -the following to the `config.txt` file on the boot partition: - -```text -dtoverlay=pi3-miniuart-bt -``` - -## HmIP-RFUSB - -HassOS versions 1.11 and later support the HmIP-RFUSB by default and don't need any -configuration. If you installed Hassio on another distribution of Linux, you need to -follow the installation guide for the UART USB to setup the UART USB interface on -your computer. - -## Support - -Got questions? - -You have several options to get them answered: - -- The [Home Assistant Discord Chat Server][discord]. -- The Home Assistant [Community Forum][forum]. -- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit] - -In case you've found a bug, please [open an issue on our GitHub][issue]. - -[discord]: https://discord.gg/c5DvZ4e -[forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues -[reddit]: https://reddit.com/r/homeassistant -[repository]: https://github.com/hassio-addons/repository -[occu]: https://github.com/jens-maus/occu/ -[hm-mod-rpi-pcb]: https://www.elv.ch/homematic-funkmodul-fuer-raspberry-pi-bausatz.html -[hmip-rufsb]: https://www.elv.ch/elv-homematic-ip-rf-usb-stick-hmip-rfusb-fuer-alternative-steuerungsplattformen-arr-bausatz.html diff --git a/homematic/Dockerfile b/homematic/Dockerfile deleted file mode 100644 index fdc263dc1d2..00000000000 --- a/homematic/Dockerfile +++ /dev/null @@ -1,88 +0,0 @@ -ARG BUILD_FROM -FROM $BUILD_FROM - -# Set shell -SHELL ["/bin/bash", "-o", "pipefail", "-c"] - -# Install packages -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - libusb-1.0 \ - lighttpd \ - lighttpd-mod-openssl \ - nginx \ - openjdk-11-jre-headless \ - && rm -rf /var/lib/apt/lists/* - -ARG OCCU_VERSION -ARG BUILD_ARCH - -# Install OCCU -WORKDIR /usr/src -RUN \ - set -x \ - && curl -SL https://github.com/eq-3/occu/archive/${OCCU_VERSION}.tar.gz | tar xzf - \ - && cd occu-${OCCU_VERSION} \ - && mkdir -p \ - /boot \ - /opt/hm \ - /opt/hm/etc/config \ - /opt/HmIP \ - /opt/HMServer \ - /var/status \ - \ - && echo "VERSION=${OCCU_VERSION}" > /boot/VERSION \ - && cp /boot/VERSION /VERSION \ - && ln -s /opt/hm/etc/config /etc/config \ - \ - && if [ "${BUILD_ARCH}" = "armv7" ]; \ - then \ - cd arm-gnueabihf-gcc8; \ - else \ - cd X86_32_GCC8; \ - fi \ - \ - && cp -R packages-eQ-3/RFD/bin /opt/hm/ \ - && cp -R packages-eQ-3/RFD/lib /opt/hm/ \ - && cp -R packages-eQ-3/LinuxBasis/bin /opt/hm/ \ - && cp -R packages-eQ-3/LinuxBasis/lib /opt/hm/ \ - && cp -R packages-eQ-3/HS485D/bin /opt/hm/ \ - && cp -R packages-eQ-3/HS485D/lib /opt/hm/ \ - \ - && cp -R packages-eQ-3/WebUI/bin /opt/hm/ \ - && cp -R packages-eQ-3/WebUI/lib /opt/hm/ \ - && rm -rf packages-eQ-3/WebUI/etc/config* packages-eQ-3/WebUI/etc/rega.conf \ - && mv /opt/hm/bin/ReGaHss.normal /opt/hm/bin/ReGaHss \ - && rm -f /opt/hm/bin/ReGaHss.* \ - && cp -R packages-eQ-3/WebUI/etc/* /opt/hm/etc/ \ - && cp -R packages/lighttpd/etc/lighttpd /opt/hm/etc/ \ - && sed -i "s|/etc/lighttpd/||" /opt/hm/etc/lighttpd/conf.d/proxy.conf \ - \ - && cd ../ \ - \ - && cp -r firmware / \ - && mv /firmware/HmIP-RFUSB/hmip_coprocessor_update.eq3 /firmware/HmIP-RFUSB/hmip_coprocessor_update-2.8.6.eq3 \ - && sed -i "s/hmip_coprocessor_update.eq3/hmip_coprocessor_update-2.8.6.eq3/" /firmware/HmIP-RFUSB/fwmap \ - && sed -i "s/2.8.4/2.8.6/" /firmware/HmIP-RFUSB/fwmap \ - \ - && cp -R HMserver/opt/HmIP/* /opt/HmIP/ \ - && cp -a HMserver/opt/HMServer/*.jar /opt/HMServer/ \ - && cp -R HMserver/opt/HMServer/groups /opt/HMServer/ \ - && cp -R HMserver/opt/HMServer/measurement /opt/HMServer/ \ - && cp -R HMserver/opt/HMServer/pages /opt/HMServer/ \ - \ - && sed -i "s/WEBUI_VERSION = \".*\"/WEBUI_VERSION = \"${OCCU_VERSION}\"/" WebUI/www/rega/pages/index.htm \ - && cp -R WebUI/* / \ - && ln -s /www /opt/hm/www \ - \ - && touch /opt/hm/etc/config/userAckSecurityHint \ - && touch /opt/hm/etc/config/firewallConfigured \ - && touch /opt/hm/etc/config/legacyAPIMigrationAccepted \ - \ - && rm -rf /usr/src/occu-${OCCU_VERSION} - -ENV \ - HM_HOME=/opt/hm \ - LD_LIBRARY_PATH=/opt/hm/lib:${LD_LIBRARY_PATH} - -COPY rootfs / diff --git a/homematic/README.md b/homematic/README.md deleted file mode 100644 index 7a2a49185fd..00000000000 --- a/homematic/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# Home Assistant Add-on: HomeMatic - -HomeMatic central based on OCCU. - -![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield] - -## About - -This add-on allows you to control your HomeMatic devices so they can be -integrated into Home Assistant. It is based on the -[HomeMatic Open Central Control Unit (OCCU) SDK][occu]. - -Note: Requires a [HM-MOD-RPI-PCB][hm-mod-rpi-pcb] or [HmIP-RFUSB][hmip-rufsb] -to interface with your devices. - -## Features - -- Your Raspberry Pi is your HomeMatic control center! -- WebUI ReGaHss with ingress support -- Firmware updates - - -[aarch64-shield]: https://img.shields.io/badge/aarch64-no-red.svg -[amd64-shield]: https://img.shields.io/badge/amd64-no-red.svg -[armhf-shield]: https://img.shields.io/badge/armhf-no-red.svg -[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg -[i386-shield]: https://img.shields.io/badge/i386-yes-green.svg -[occu]: https://github.com/jens-maus/occu/ -[hm-mod-rpi-pcb]: https://www.elv.ch/homematic-funkmodul-fuer-raspberry-pi-bausatz.html -[hmip-rufsb]: https://www.elv.ch/elv-homematic-ip-rf-usb-stick-hmip-rfusb-fuer-alternative-steuerungsplattformen-arr-bausatz.html diff --git a/homematic/build.json b/homematic/build.json deleted file mode 100644 index c6cb672b38b..00000000000 --- a/homematic/build.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "build_from": { - "armv7": "homeassistant/armv7-base-debian:bullseye", - "i386": "homeassistant/i386-base-debian:bullseye" - }, - "args": { - "OCCU_VERSION": "3.59.6" - } -} diff --git a/homematic/config.json b/homematic/config.json deleted file mode 100644 index 12701c06d60..00000000000 --- a/homematic/config.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "name": "HomeMatic CCU", - "version": "11.3.0", - "slug": "homematic", - "description": "HomeMatic central based on OCCU", - "url": "https://github.com/home-assistant/hassio-addons/tree/master/homematic", - "arch": ["armv7", "i386"], - "map": ["share:rw"], - "startup": "system", - "timeout": 15, - "gpio": true, - "apparmor": false, - "ingress": true, - "panel_title": "HomeMatic", - "panel_icon": "mdi:router-wireless", - "ports": { - "80/tcp": null, - "2001/tcp": null, - "2000/tcp": null, - "2010/tcp": null - }, - "ports_description": { - "80/tcp": "ReGaHss Webinterface (Not required for Ingress)", - "2001/tcp": "Homematic xmlrpc (Extern)", - "2000/tcp": "HomematicWire xmlrpc (Extern)", - "2010/tcp": "HomematicIP xmlrpc (Extern)" - }, - "options": { - "rf_enable": false, - "wired_enable": false, - "hmip_enable": false, - "rf": [], - "wired": [], - "hmip": [] - }, - "schema": { - "rf_enable": "bool", - "rf": [ - { - "type": "match(CCU2)", - "device": "device(subsystem=tty)", - "reset": "bool?" - } - ], - "wired_enable": "bool", - "wired": [ - { - "serial": "str", - "key": "str", - "ip": "str" - } - ], - "hmip_enable": "bool", - "hmip": [ - { - "type": "match(HMIP_CCU2)", - "device": "device(subsystem=tty)" - } - ], - "regahss_reset": "bool?" - }, - "image": "homeassistant/{arch}-addon-homematic" -} diff --git a/homematic/icon.png b/homematic/icon.png deleted file mode 100644 index 9969b1c66c3..00000000000 Binary files a/homematic/icon.png and /dev/null differ diff --git a/homematic/logo.png b/homematic/logo.png deleted file mode 100644 index 7c4723b6f76..00000000000 Binary files a/homematic/logo.png and /dev/null differ diff --git a/homematic/rootfs/etc/cont-finish.d/hmip.sh b/homematic/rootfs/etc/cont-finish.d/hmip.sh deleted file mode 100755 index ebc1f2f12c4..00000000000 --- a/homematic/rootfs/etc/cont-finish.d/hmip.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Backup hmip_address -# ============================================================================== -if bashio::config.true 'hmip_enable' && [ -f /data/hmip_address.conf ]; then - cp -f /etc/config/hmip_address.conf /data/ || bashio::log.warning "Failed to backup hmip address" -fi diff --git a/homematic/rootfs/etc/cont-finish.d/regahss.sh b/homematic/rootfs/etc/cont-finish.d/regahss.sh deleted file mode 100755 index d834502884b..00000000000 --- a/homematic/rootfs/etc/cont-finish.d/regahss.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Store RegaHss data -# ============================================================================== - -echo "load tclrega.so; rega system.Save()" | "${HM_HOME}/bin/tclsh" 2> /dev/null || true diff --git a/homematic/rootfs/etc/cont-init.d/certs.sh b/homematic/rootfs/etc/cont-init.d/certs.sh deleted file mode 100644 index a3ef2d5d7a6..00000000000 --- a/homematic/rootfs/etc/cont-init.d/certs.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Configure NGINX for use with ReGaHss -# ============================================================================== - -if [ -f /data/server.pem ]; then - cp -f /data/server.pem /etc/config/server.pem -else - openssl req -new -x509 -nodes -keyout /etc/config/server.pem -out /etc/config/server.pem -days 3650 -subj "/C=DE/O=HomeMatic/OU=HomeAssistant/CN=$(hostname)" - cp -f /etc/config/server.pem /data/server.pem -fi diff --git a/homematic/rootfs/etc/cont-init.d/env.sh b/homematic/rootfs/etc/cont-init.d/env.sh deleted file mode 100644 index 7624395f28a..00000000000 --- a/homematic/rootfs/etc/cont-init.d/env.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Initialize file system layout /data -# ============================================================================== - -mkdir -p /share/hm-firmware -mkdir -p /share/hmip-firmware -mkdir -p /data/crRFD -mkdir -p /data/rfd -mkdir -p /data/hs485d -mkdir -p /data/userprofiles - -# Init files -touch /data/groups.json -touch /data/hmip_user.conf -touch /data/rega_user.conf -touch /data/homematic.regadom -touch /data/userprofiles/userAckInstallWizard_Admin - -# Persist -ln -s /data/userprofiles /etc/config/userprofiles -ln -s /data/groups.gson /etc/config/groups.gson diff --git a/homematic/rootfs/etc/cont-init.d/hm_ip.sh b/homematic/rootfs/etc/cont-init.d/hm_ip.sh deleted file mode 100755 index 8d5ac14fae0..00000000000 --- a/homematic/rootfs/etc/cont-init.d/hm_ip.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Update HomeMatic firmware -# ============================================================================== -# shellcheck disable=SC2012 -declare hmip_index -declare hmip_device -declare version_to -declare version_from - -# HMIP support -if bashio::config.false 'hmip_enable'; then - bashio::exit.ok -fi -bashio::log.info "Setup HmIP-RF" - -# Generate config -tempio \ - -conf /data/options.json \ - -template /usr/share/tempio/crRFD.conf \ - -out /etc/config/crRFD.conf - -# Restore data -if [ -f /data/hmip_address.conf ]; then - cp -f /data/hmip_address.conf /etc/config/ -fi - -# Update Firmware -for hmip_index in $(bashio::config 'hmip|keys'); do - hmip_device=$(bashio::config "hmip[${hmip_index}].device") - - # Skeep device path with id - if echo "${hmip_device}" | grep "by-id"; then - bashio::log.warning "Skip firmware for ${hmip_device}" - continue - fi - - version_from="$(java -Xmx64m -jar /opt/HmIP/hmip-copro-update.jar -p "${hmip_device}" -v | grep "Application version =" | cut -d' ' -f5)" - version_to="$(ls /firmware/HmIP-RFUSB/hmip_coprocessor_update-*.eq3 | sed 's/.*hmip_coprocessor_update-\(.*\)\.eq3/\1/' | tail -n1)" - if [ "${version_from}" != "${version_to}" ]; then - if java -Xmx64m -jar /opt/HmIP/hmip-copro-update.jar -p "${hmip_device}" -f "/firmware/HmIP-RFUSB/hmip_coprocessor_update-${version_to}.eq3"; then - bashio::log.info "HmIP update to ${version_to} was successful" - else - bashio::log.error "HmIP update ${version_to} fails!" - fi - fi -done diff --git a/homematic/rootfs/etc/cont-init.d/hm_rfd.sh b/homematic/rootfs/etc/cont-init.d/hm_rfd.sh deleted file mode 100755 index f5e3f6a4756..00000000000 --- a/homematic/rootfs/etc/cont-init.d/hm_rfd.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Update HomeMatic firmware -# ============================================================================== - -# RF support -if bashio::config.false 'rf_enable'; then - bashio::exit.ok -fi -bashio::log.info "Setup BidCos-RF" - -# Generate config -tempio \ - -conf /data/options.json \ - -template /usr/share/tempio/rfd.conf \ - -out /etc/config/rfd.conf - -# Init GPIO -if [ ! -d /sys/class/gpio/gpio18 ]; then - echo 18 > /sys/class/gpio/export - sleep 2 -fi -if [ "$(cat /sys/class/gpio/gpio18/direction)" != "out" ]; then - echo out > /sys/class/gpio/gpio18/direction - sleep 2 -fi - -echo 0 > /sys/class/gpio/gpio18/value || echo "Can't set default value!" -sleep 0.5 - -# Update Firmware -if "${HM_HOME}/bin/eq3configcmd" update-coprocessor -lgw -u -rfdconf /etc/config/rfd.conf -l 1; then - bashio::log.info "RFd update was successful" -else - bashio::log.error "RFd update fails!" -fi diff --git a/homematic/rootfs/etc/cont-init.d/hm_wired.sh b/homematic/rootfs/etc/cont-init.d/hm_wired.sh deleted file mode 100755 index 762e090effb..00000000000 --- a/homematic/rootfs/etc/cont-init.d/hm_wired.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Update HomeMatic firmware -# ============================================================================== - -# Wired support -if bashio::config.false 'wired_enable'; then - bashio::exit.ok -fi -bashio::log.info "Setup Hm-Wired" - -# Generate config -tempio \ - -conf /data/options.json \ - -template /usr/share/tempio/hs485d.conf \ - -out /etc/config/hs485d.conf - -# Update Firmware -if "${HM_HOME}/bin/eq3configcmd" update-lgw-firmware -m /firmware/fwmap -c /etc/config/hs485d.conf -l 1; then - bashio::log.info "Wired update was successful" -else - bashio::log.error "Wired update fails!" -fi diff --git a/homematic/rootfs/etc/cont-init.d/interface.sh b/homematic/rootfs/etc/cont-init.d/interface.sh deleted file mode 100755 index d6ec9173860..00000000000 --- a/homematic/rootfs/etc/cont-init.d/interface.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Generate InterfacesList.xml -# ============================================================================== -tempio \ - -conf /data/options.json \ - -template /usr/share/tempio/InterfacesList.xml \ - -out /etc/config/InterfacesList.xml diff --git a/homematic/rootfs/etc/cont-init.d/nginx.sh b/homematic/rootfs/etc/cont-init.d/nginx.sh deleted file mode 100644 index e98e5d8ac82..00000000000 --- a/homematic/rootfs/etc/cont-init.d/nginx.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Configure NGINX for use with ReGaHss -# ============================================================================== -ingress_entry=$(bashio::addon.ingress_entry) -sed -i "s#%%ingress_entry%%#${ingress_entry}#g" /etc/nginx/nginx.conf diff --git a/homematic/rootfs/etc/nginx/nginx.conf b/homematic/rootfs/etc/nginx/nginx.conf deleted file mode 100644 index 5a4c646a798..00000000000 --- a/homematic/rootfs/etc/nginx/nginx.conf +++ /dev/null @@ -1,79 +0,0 @@ -worker_processes 1; -pid /var/run/nginx.pid; -error_log /dev/stdout info; -daemon off; - -events { - worker_connections 1024; -} - -http { - include mime.types; - default_type application/octet-stream; - sendfile on; - keepalive_timeout 65; - proxy_read_timeout 1200; - gzip on; - gzip_disable "msie6"; - - map $http_upgrade $connection_upgrade { - default upgrade; - '' close; - } - - # https://stackoverflow.com/questions/21230918/nginx-scheme-variable-behind-load-balancer/21911864#21911864 - map $http_x_forwarded_proto $real_scheme { - default $http_x_forwarded_proto; - '' $scheme; - } - - # Ingress - server { - listen 8099 default_server; - - allow 172.30.32.2; - deny all; - - server_name _; - access_log /dev/stdout combined; - - client_max_body_size 4G; - keepalive_timeout 5; - - root /dev/null; - - location / { - proxy_pass http://127.0.0.1:80; - proxy_redirect ~^/(.+)$ $real_scheme://$http_host%%ingress_entry%%/$1; - - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Host $http_host; - proxy_set_header X-NginX-Proxy true; - - sub_filter_once off; - sub_filter_types *; - - # Hack for reset paths back - sub_filter '/etc/config/' '/etc/config/'; - - # Make URLs relative - sub_filter '/webui/' '%%ingress_entry%%/webui/'; - sub_filter '/ise/' '%%ingress_entry%%/ise/'; - sub_filter '/pda/' '%%ingress_entry%%/pda/'; - sub_filter '/config/' '%%ingress_entry%%/config/'; - sub_filter '/api/' '%%ingress_entry%%/api/'; - sub_filter '/pages/' '%%ingress_entry%%/pages/'; - sub_filter '/jpages/' '%%ingress_entry%%/jpages/'; - sub_filter '/esp/' '%%ingress_entry%%/esp/'; - - # Protect iframe breakouts - sub_filter 'top.window.location.href' 'location.href'; - } - } -} \ No newline at end of file diff --git a/homematic/rootfs/etc/services.d/hmserver/finish b/homematic/rootfs/etc/services.d/hmserver/finish deleted file mode 100644 index a29ced9a496..00000000000 --- a/homematic/rootfs/etc/services.d/hmserver/finish +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/execlineb -S1 -# ============================================================================== -# Take down the S6 supervision tree based on service exit code -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } - -s6-svscanctl -t /var/run/s6/services diff --git a/homematic/rootfs/etc/services.d/hmserver/run b/homematic/rootfs/etc/services.d/hmserver/run deleted file mode 100644 index 9b4b5f74d45..00000000000 --- a/homematic/rootfs/etc/services.d/hmserver/run +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Start HomeMatic HMServer service -# ============================================================================== -# shellcheck disable=SC2086 -if bashio::config.true 'hmip_enable'; then - bashio::log.info "Starting HMIPServer..." - exec java -Xmx64m -Dlog4j.configuration=file:///etc/config/log4j.xml -Dfile.encoding=ISO-8859-1 -jar /opt/HMServer/HMIPServer.jar /etc/config/crRFD.conf /etc/config/HMServer.conf -else - bashio::log.info "Starting HMServer..." - exec java -Xmx64m -Dlog4j.configuration=file:///etc/config/log4j.xml -Dfile.encoding=ISO-8859-1 -jar /opt/HMServer/HMServer.jar /etc/config/HMServer.conf -fi diff --git a/homematic/rootfs/etc/services.d/lighttpd/run b/homematic/rootfs/etc/services.d/lighttpd/run deleted file mode 100644 index ebaa1557620..00000000000 --- a/homematic/rootfs/etc/services.d/lighttpd/run +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Start light httpd service -# ============================================================================== -bashio::log.info "Initialize webinterface routing..." -exec lighttpd-angel -D -f "${HM_HOME}/etc/lighttpd/lighttpd.conf" diff --git a/homematic/rootfs/etc/services.d/nginx/finish b/homematic/rootfs/etc/services.d/nginx/finish deleted file mode 100644 index 5bb07a651c9..00000000000 --- a/homematic/rootfs/etc/services.d/nginx/finish +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/execlineb -S1 -# ============================================================================== -# Take down the S6 supervision tree based on service exit code -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } - -s6-svscanctl -t /var/run/s6/services diff --git a/homematic/rootfs/etc/services.d/regahss/finish b/homematic/rootfs/etc/services.d/regahss/finish deleted file mode 100644 index a29ced9a496..00000000000 --- a/homematic/rootfs/etc/services.d/regahss/finish +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/execlineb -S1 -# ============================================================================== -# Take down the S6 supervision tree based on service exit code -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } - -s6-svscanctl -t /var/run/s6/services diff --git a/homematic/rootfs/etc/services.d/regahss/run b/homematic/rootfs/etc/services.d/regahss/run deleted file mode 100644 index 7a9d5922f63..00000000000 --- a/homematic/rootfs/etc/services.d/regahss/run +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Start ReGaHss service -# ============================================================================== -# Wait until interfaces are initialized -bashio::log.info "Wait until HMServer is setup" -bashio::net.wait_for 9292 - -# Reset Regahss -if bashio::config.true "regahss_reset"; then - bashio::log.warning "Reset ReGaHss" - rm -f /data/homematic.regadom - touch /data/homematic.regadom -fi - -# Start Regahss -bashio::log.info "Starting ReGaHss..." -exec "${HM_HOME}/bin/ReGaHss" -c -f /etc/config/rega.conf diff --git a/homematic/rootfs/etc/services.d/rfd/finish b/homematic/rootfs/etc/services.d/rfd/finish deleted file mode 100644 index a29ced9a496..00000000000 --- a/homematic/rootfs/etc/services.d/rfd/finish +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/execlineb -S1 -# ============================================================================== -# Take down the S6 supervision tree based on service exit code -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } - -s6-svscanctl -t /var/run/s6/services diff --git a/homematic/rootfs/etc/services.d/rfd/run b/homematic/rootfs/etc/services.d/rfd/run deleted file mode 100644 index e6d66006927..00000000000 --- a/homematic/rootfs/etc/services.d/rfd/run +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Start HomeMatic RFD service -# ============================================================================== -if bashio::config.false 'rf_enable'; then - exec sleep infinity -fi - -bashio::log.info "Starting rfd..." -exec "${HM_HOME}/bin/rfd" -c -l 0 -f /etc/config/rfd.conf diff --git a/homematic/rootfs/etc/services.d/timesync/run b/homematic/rootfs/etc/services.d/timesync/run deleted file mode 100644 index fa762ea2894..00000000000 --- a/homematic/rootfs/etc/services.d/timesync/run +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Start HomeMatic RF timesync service -# ============================================================================== -if bashio::config.false 'rf_enable'; then - exec sleep infinity -fi - -while true -do - sleep 30m - bashio::log.info "$(date '+%Y-%m-%d %H:%M:%S.%3N') Run SetInterfaceClock now." - "${HM_HOME}/bin/SetInterfaceClock" 127.0.0.1:2001 -done diff --git a/homematic/rootfs/etc/services.d/wired/finish b/homematic/rootfs/etc/services.d/wired/finish deleted file mode 100644 index a29ced9a496..00000000000 --- a/homematic/rootfs/etc/services.d/wired/finish +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/execlineb -S1 -# ============================================================================== -# Take down the S6 supervision tree based on service exit code -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } - -s6-svscanctl -t /var/run/s6/services diff --git a/homematic/rootfs/etc/services.d/wired/run b/homematic/rootfs/etc/services.d/wired/run deleted file mode 100644 index 16821c5834a..00000000000 --- a/homematic/rootfs/etc/services.d/wired/run +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Start HomeMatic wired service -# ============================================================================== -if bashio::config.false 'wired_enable'; then - exec sleep infinity -fi - -bashio::log.info "Starting wired..." -exec "${HM_HOME}/bin/hs485d" -g -i 0 -f /etc/config/hs485d.conf diff --git a/homematic/rootfs/opt/hm/etc/config/HMServer.conf b/homematic/rootfs/opt/hm/etc/config/HMServer.conf deleted file mode 100644 index 7b17760959f..00000000000 --- a/homematic/rootfs/opt/hm/etc/config/HMServer.conf +++ /dev/null @@ -1,2 +0,0 @@ -hmServerPort=9292 -regaPort=8183 diff --git a/homematic/rootfs/opt/hm/etc/config/log4j.xml b/homematic/rootfs/opt/hm/etc/config/log4j.xml deleted file mode 100644 index 2a49e9b6a14..00000000000 --- a/homematic/rootfs/opt/hm/etc/config/log4j.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/homematic/rootfs/opt/hm/etc/config/rega.conf b/homematic/rootfs/opt/hm/etc/config/rega.conf deleted file mode 100644 index 7ef574fe0b2..00000000000 --- a/homematic/rootfs/opt/hm/etc/config/rega.conf +++ /dev/null @@ -1,72 +0,0 @@ -################################################################################ -# rega.conf -# Standard-Einstellungen für die logikschicht -################################################################################ - -#******************************************************************************* -# Pfade für Konfiguration-Dateien -#******************************************************************************* - -# UserConfigFileName -# Benuterdefinierte Konfigurationdatei. -# Diese Datei kann die hier festgelegten Werte überschreiben, z.B. das -# Session-Timeout -# Standard: /etc/config/rega.conf -UserConfigFileName=/data/rega_user.conf - -# DomFileName -# DOM-Datei. Enthält das Objekt Modell (Programme, Systemvariablen, ...) -# Standard: /etc/config/homematic.regadom -DomFileName=/data/homematic.regadom - -# TimeConfigFileName -# Enthält Zeit- und Positionseinstellungen. -# Standard: /etc/config/time.conf -TimeConfigFileName=/etc/config/time.conf - -# XmlRpcFileName -# Enthält die Liste der unterstützen Schnittstellen zur -# Anbindung von HomeMatic Geräten -# Standard: /etc/config/InterfacesList.xml -XmlRpcFileName=/etc/config/InterfacesList.xml - -#******************************************************************************* -# HTTP-Einstellungen -#******************************************************************************* - -# HttpDocPath -# Pfad des HTTP-Root-Verzeichnisses -# Standard: /www/rega -HttpDocPath=/www/rega - -# HttpListenerPort -# Portnummer des WebServers -# Standardwert: 8181 -HttpListenerPort=8183 - -# VirtualPathInternalConfig -# Standard: /config/ -VirtualPathInternalConfig=/config/ - -# VirtualPathInternalConfigDest -# Standard: 80:/config/ -VirtualPathInternalConfigDest=80:/config/ - -# SessionTimout -# Zeit in Sekunden, nach der eine Session abläuft. -# Standard: 300 -SessionTimeout=300 - -#******************************************************************************* -# Ereignisse -#******************************************************************************* - -# OnStartup -# Wird nach dem Laden des DOM ausgelöst -# Standard: /bin/hm_startup -OnStartup=/bin/hm_startup - -# OnAddDevice -# Wird beim Hinzufügen eines Geräts ausgeführt -# Standard: /bin/hm_autoconf -OnAddDevice=/bin/hm_autoconf diff --git a/homematic/rootfs/usr/share/tempio/InterfacesList.xml b/homematic/rootfs/usr/share/tempio/InterfacesList.xml deleted file mode 100644 index f0445b8b487..00000000000 --- a/homematic/rootfs/usr/share/tempio/InterfacesList.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - {{ if .rf_enable }} - - BidCos-RF - xmlrpc_bin://127.0.0.1:2001 - BidCos-RF - - {{ end }} - - VirtualDevices - xmlrpc://127.0.0.1:9292/groups - Virtual Devices - - {{ if .hmip_enable }} - - HmIP-RF - xmlrpc://127.0.0.1:2010 - HmIP-RF - - {{ end }} - {{ if .wired_enable }} - - Hm-Wired - xmlrpc://127.0.0.1:2000 - Hm-Wired - - {{ end }} - \ No newline at end of file diff --git a/homematic/rootfs/usr/share/tempio/crRFD.conf b/homematic/rootfs/usr/share/tempio/crRFD.conf deleted file mode 100644 index 85de798c934..00000000000 --- a/homematic/rootfs/usr/share/tempio/crRFD.conf +++ /dev/null @@ -1,48 +0,0 @@ - -Config.Dir=/data/crRFD -Config.Include=/data/hmip_user.conf - -# Directory Configuration -Persistence.Home=/data/crRFD -FirmwareUpdate.BG.OTAU.Home=/share/hmip-firmware -FirmwareUpdate.BG.OTAU.divergent.device.type.definition.file=/opt/HmIP/crrfd.fwfix - -# Legacy API Configuration -API.1.Type=XML-RPC -Legacy.Encoding=ISO-8859-1 -Legacy.ResponseTimeout=20 -Legacy.ReplacementURL=127.0.0.1 -Legacy.Parameter.Definition.File=/opt/HmIP/legacy-parameter-definition.config -# Legacy.RemoveUnreachableClients=false -Legacy.AddressPrefix=3014F711A0 -Legacy.SwitchTypeAndSubtype=true -Legacy.HandlersFilename=/var/LegacyService.handlers -Legacy.DiscardDutyCycleEvents=true -Legacy.SendUDPServiceMessages=true -Legacy.Port=2010 -Legacy.VirtualRemoteControl.Enabled=true -Legacy.CallDeleteDevicesForChangedDevices=false -Legacy.Client.Connection.Timeout=600000 -Legacy.Client.Socket.Timeout=600000 - -# HmIP-Routing -Adapter.Remote.Enabled=true -AccessPoint.WebSocket.Port=9293 -IPServices.Firmware.Update.URL=http://drap-update.homematic.com:80/firmware/hap/ - -# Miscellaneous Configuration -CyclicTimeout.TimerStartMaxDelay=90 -CyclicTimeout.TimerCycleTime=600 -Legacy.Parameter.ReplaceEnumValueWithOrdinal=true -AED.Enabled=true - -### Configuration for Inclusion with key server (internet) or local key (offline) -KeyServer.Mode=KEYSERVER_LOCAL -KeyServer.Gateway.URL=secgtw.homematic.com -Vertx.WorkerPoolSize=5 - -# USB HM/IP TRX Adapter Configuration -{{ range $index, $device := .hmip }} -Adapter.{{ if eq $index 0 }}1{{ else }}2{{ end }}.Type={{ $device.type }} -Adapter.{{ if eq $index 0 }}1{{ else }}2{{ end }}.Port={{ $device.device }} -{{ end }} \ No newline at end of file diff --git a/homematic/rootfs/usr/share/tempio/hs485d.conf b/homematic/rootfs/usr/share/tempio/hs485d.conf deleted file mode 100644 index 436244a9b6d..00000000000 --- a/homematic/rootfs/usr/share/tempio/hs485d.conf +++ /dev/null @@ -1,19 +0,0 @@ -# TCP Port for XmlRpc connections -Listen Port = 2000 - -Log Destination = None - -Persist Keys = 1 - -Device Description Dir = /firmware/hs485types -Device Files Dir = /data/hs485d -Firmware Dir = /firmware -User Firmware Dir = /share/hm-firmware - -{{ range $index, $device := .wired }} -[Interface {{ $index }}] -Type = HMWLGW -Serial Number = {{ $device.serial }} -Encryption Key = {{ $device.key }} -IP Address = {{ $device.ip }} -{{ end }} \ No newline at end of file diff --git a/homematic/rootfs/usr/share/tempio/rfd.conf b/homematic/rootfs/usr/share/tempio/rfd.conf deleted file mode 100644 index d386fb3586e..00000000000 --- a/homematic/rootfs/usr/share/tempio/rfd.conf +++ /dev/null @@ -1,22 +0,0 @@ -# TCP Port for XmlRpc connections -Listen Port = 2001 - -Log Destination = None - -Persist Keys = 1 - -Device Description Dir = /firmware/rftypes -Device Files Dir = /data/rfd -Key File = /data/keys -Address File = /data/ids -Firmware Dir = /firmware -User Firmware Dir = /share/hm-firmware -Replacemap File = /firmware/rftypes/replaceMap/rfReplaceMap.xml - -{{ range $index, $device := .rf }} -[Interface {{ $index }}] -Type = CCU2 -ComPortFile = {{ $device.device }} -AccessFile = /dev/null -ResetFile = /sys/class/gpio/gpio18/value -{{ end }} \ No newline at end of file diff --git a/letsencrypt/CHANGELOG.md b/letsencrypt/CHANGELOG.md index 86d7d09aede..b41d08d639d 100644 --- a/letsencrypt/CHANGELOG.md +++ b/letsencrypt/CHANGELOG.md @@ -1,5 +1,301 @@ # Changelog +## 5.4.3 + +- Update certbot-dns-websupport to 3.0.0 +- Re-enable certbot-dns-websupport + +## 5.4.2 + +- Update certbot-dns-dynu to 0.0.8 +- Update certbot-dns-gandi to 1.6.1 + (incl. switch back to a renamed updated original version) + +## 5.4.1 + +- Fix TransIP global_key handling + +## 5.4.0 + +- Add additional arguments to certbot (dry-run, test-cert, verbose) +- Switch gandi-dns to a maintained version (certbot-plugin-gandi-modern) +- Refactor scripts +- Improve documentation +- Refactor configuration and align with documentation + +## 5.3.3 + +- Re-enabled certbot-dns-mijn-host + +## 5.3.2 + +- Update certbot to 3.2.0 +- Update acme to 3.2.0 +- Update certbot-dns-inwx to 3.0.2 + +## 5.3.1 + +- Add Eurodns DNS support + +## 5.3.0 + +- Disabled certbot-dns-mijn-host (Breaking change) + - issue: [mijnhost/certbot-dns-mijn-host#8](https://github.com/mijnhost/certbot-dns-mijn-host/issues/8) +- Disabled certbot-dns-websupport (Breaking change) + - issue: [johnybx/certbot-dns-websupport#1](https://github.com/johnybx/certbot-dns-websupport/issues/1) +- Update to Python 3.13 +- Update to Alpine 3.21 +- Update certbot to 3.1.0 +- Update acme to 3.1.0 +- Update cryptography to 44.0.1 +- Update certbot-dns-azure to 2.6.1 +- Update certbot-dns-directadmin to 10.0.13 +- Update certbot-dns-duckdns to 1.5 +- Update certbot-dns-dynu to 0.0.6 +- Update certbot-dns-inwx to 3.0.1 +- Update certbot-dns-ionos to 2024.11.9 +- Update certbot-dns-norisnetwork to 0.3.0 +- Update certbot-dns-porkbun to 0.9.1 +- Update certbot-dns-netcup to 1.4.4 +- Update certbot-dns-njalla to 2.0.2 +- Update the remaining dns challenges with DNS_PROVIDER placeholder + +## 5.2.12 + +- Add rfc2136_sign_query parameter to config.yaml + +## 5.2.11 + +- Use a newer, maintained Hurricane Electric plugin. + +## 5.2.10 + +- Add transip global_key parameter to config.yaml + +## 5.2.9 + +- Update certbot-dns-infomaniak to 0.2.3 + +## 5.2.8 + +- Add transip global_key parameter to support authentication without IP whitelist requirements + +## 5.2.7 + +- Add mijn.host DNS support + +## 5.2.6 + +- Fix dns-loopia username error + +## 5.2.5 + +- Update certbot-dns-directadmin to 1.0.12 + +## 5.2.4 + +- Add Loopia DNS support + +## 5.2.3 + +- Fix syntax error in run script + +## 5.2.2 + +- Add IONOS DNS support + +## 5.2.1 + +- Revert Cryptography to 42.0.8 to avoid deprecation warnings + +## 5.2.0 + +- Update Certbot/ACME to 2.11.0 & update all plugins to their latest version +- Update to Python 3.12 +- Update to Alpine 3.20 + +## 5.1.4 + +- Drop Google Domains support (the new operator Squarespace has no ACME support) + +## 5.1.3 + +- Add godaddy.com DNS support + +## 5.1.2 + +- Fixes subdomain DNS challenge not working for Simply.com + +## 5.1.1 + +- Add Simply.com DNS support + +## 5.1.0 + +- Add external account binding support + +## 5.0.27 + +- Add Plesk DNS challenge support + +## 5.0.26 + +- Add noris network DNS challenge support + +## 5.0.25 + +- Add DigitalOcean propagation-seconds support + +## 5.0.24 + +- Fix Gandi DNS support using API key + +## 5.0.23 + +- Fix missing domain configuration for joker.com DNS challenge + +## 5.0.22 + +- Add joker.com DNS challenge support + +## 5.0.21 + +- Fix configuration to make list of provider parsable again + +## 5.0.20 + +- Fix file-structure.sh script +- Fix domainoffensive plug-in installation + +## 5.0.19 + +- Add domainoffensive challenge support + +## 5.0.18 + +- Fix Gandi DNS support using API key +- Add Gandi DNS support using token authentication + +## 5.0.17 + +- Add WebSupport challenge support + +## 5.0.16 + +- Add Dynu challenge support + +## 5.0.15 + +- Add easyDNS challenge support + +## 5.0.14 + +- Update docs for key_type setting + +## 5.0.13 + +- By default, choose key type based on existing certificates at startup. +- Allow ECDSA curve selection. + +## 5.0.12 + +- Fix ClouDNS challenge support + +## 5.0.11 + +- Add HE DNS challenge support + +## 5.0.10 + +- Add ClouDNS DNS challenge support + +## 5.0.9 + +- Add option to specify Private Key type + +## 5.0.8 + +- Add Dreamhost DNS challenge support + +## 5.0.7 + +- Add Porkbun DNS challenge support + +## 5.0.6 + +- Add Infomaniak DNS challenge support + +## 5.0.5 + +- Fix DirectAdmin DNS challenge support + +## 5.0.4 + +- Add Namecheap DNS challenge support + +## 5.0.3 + +- Add deSEC DNS challenge support + +## 5.0.2 + +- Fix DirectAdmin DNS challenge support + +## 5.0.1 + +- Add DuckDNS DNS challenge support + +## 5.0.0 + +- Upgrade to Certbot 2.7.4 & all DNS authenticator plug-ins +- Drop CloudXNS (removed in Certbot upstream) +- Update to Python 3.11 +- Update to Alpine 3.18 +- Add GANDI DNS propagation delay setting + +## 4.12.9 + +- Add Google Domains DNS challenge support + +## 4.12.8 + +- Add INWX DNS challenge support + +## 4.12.7 + +- Add Hetzner DNS challenge support + +## 4.12.6 + +- Add Azure DNS challenge support + +## 4.12.5 + +- Fix another syntax error in runs script for rfc2136 + +## 4.12.4 + +- Fix syntax error in runs script for rfc2136 +- Fix finish script for S6 V3 + +## 4.12.3 + +- Fix the DNS propagation delay setting for the rfc2136 provider + +## 4.12.2 + +- Use HA wheels when possible during build + +## 4.12.1 + +- Set preferred chain to "ISRG Root X1" + +## 4.12.0 + +- Update Certbot 1.21.0 & Plugins +- Update to Python 3.9 +- Update to Alpine 3.14 + ## 4.11.0 - Add support for Njalla DNS diff --git a/letsencrypt/DOCS.md b/letsencrypt/DOCS.md index 53da89d5776..56103d8025a 100644 --- a/letsencrypt/DOCS.md +++ b/letsencrypt/DOCS.md @@ -4,103 +4,245 @@ Follow these steps to get the add-on installed on your system: -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. 2. Find the "letsencrypt" add-on and click it. 3. Click on the "INSTALL" button. ## How to use -To use this add-on, you have two options on how to get your certificate: +The Letsencrypt add-on can be configured via the add-on interface. +The configuration via YAML is also possible, see the examples below. + +Navigate in your Home Assistant frontend to the add-ons overview page at +**Settings** -> **Add-ons**, and pick the **Let's Encrypt** add-on. On the top, +pick the **Configuration** page. + +Provide the domain names to issue certificates for. Additionally, provide the +e-mail address used for the registration, and path values for **Priv Key File** +and **Certificate File**. + +There are two options to obtain certificates. ### 1. HTTP challenge - Requires Port 80 to be available from the internet and your domain assigned to the externally assigned IP address -- Doesn’t allow wildcard certificates (*.yourdomain.com). +- Doesn’t allow wildcard certificates (*.domain.tld). ### 2. DNS challenge - Requires you to use one of the supported DNS providers (See "Supported DNS providers" below) -- Allows to request wildcard certificates (*.yourdomain.com) +- Allows to request wildcard certificates (*.domain.tld) - Doesn’t need you to open a port to your Home Assistant host on your router. -### You always need to provide the following entries within the configuration +### DNS providers -```yaml -email: your@email.com -domains: - # use "*.yourdomain.com" for wildcard certificates. - - yourdomain.com -challenge: http OR dns -``` + -IF you choose `dns` as `challenge`, you will also need to fill: +
+ Supported DNS providers -```yaml -# Add the dnsprovider of your choice from the list of "Supported DNS providers" below -dns: - provider: "" +```txt +dns-azure +dns-cloudflare +dns-cloudns +dns-desec +dns-digitalocean +dns-directadmin +dns-dnsimple +dns-dnsmadeeasy +dns-domainoffensive +dns-dreamhost +dns-duckdns +dns-dynu +dns-easydns +dns-eurodns +dns-gandi +dns-gehirn +dns-godaddy +dns-google +dns-he +dns-hetzner +dns-infomaniak +dns-inwx +dns-ionos +dns-joker +dns-linode +dns-loopia +dns-luadns +dns-mijn-host +dns-namecheap +dns-netcup +dns-njalla +dns-noris +dns-nsone +dns-ovh +dns-plesk +dns-porkbun +dns-rfc2136 +dns-route53 +dns-sakuracloud +dns-simply +dns-transip +dns-websupport ``` -In addition add the fields according to the credentials required by your DNS provider: +
+
+ In addition add the fields according to the credentials required by your DNS provider: ```yaml propagation_seconds: 60 -cloudflare_email: '' +aws_access_key_id: '' +aws_secret_access_key: '' +azure_config: '' cloudflare_api_key: '' cloudflare_api_token: '' -cloudxns_api_key: '' -cloudxns_secret_key: '' +cloudflare_email: '' +cloudns_auth_id: '' +cloudns_auth_password: '' +cloudns_sub_auth_id: '' +cloudns_sub_auth_user: '' +desec_token: '' digitalocean_token: '' +directadmin_password: '' directadmin_url: '' directadmin_username: '' -directadmin_password: '' dnsimple_token: '' dnsmadeeasy_api_key: '' dnsmadeeasy_secret_key: '' -google_creds: '' -gehirn_api_token: '' +domainoffensive_token: '' +dreamhost_api_baseurl: '' +dreamhost_api_key: '' +duckdns_token: '' +dynu_auth_token: '' +easydns_endpoint: '' +easydns_key: '' +easydns_token: '' +eurodns_apiKey: '' +eurodns_applicationId: '' +gandi_api_key: '' +gandi_sharing_id: '' +gandi_token: '' gehirn_api_secret: '' +gehirn_api_token: '' +godaddy_key: '' +godaddy_secret: '' +google_creds: '' +he_pass: '' +he_user: '' +hetzner_api_token: '' +infomaniak_api_token: '' +inwx_password: '' +inwx_shared_secret: '' +inwx_username: '' +ionos_endpoint: '' +ionos_prefix: '' +ionos_secret: '' +joker_domain: '' +joker_password: '' +joker_username: '' linode_key: '' linode_version: '' +loopia_password: '' +loopia_user: '' luadns_email: '' luadns_token: '' +mijn_host_api_key: '' +namecheap_api_key: '' +namecheap_username: '' +netcup_api_key: '' +netcup_api_password: '' +netcup_customer_id: '' njalla_token: '' +noris_token: '' nsone_api_key: '' -ovh_endpoint: '' ovh_application_key: '' ovh_application_secret: '' ovh_consumer_key: '' -rfc2136_server: '' -rfc2136_port: '' +ovh_endpoint: '' +plesk_api_url: '' +plesk_password: '' +plesk_username: '' +porkbun_key: '' +porkbun_secret: '' +rfc2136_algorithm: '' rfc2136_name: '' +rfc2136_port: '' rfc2136_secret: '' -rfc2136_algorithm: '' -aws_access_key_id: '' -aws_secret_access_key: '' -sakuracloud_api_token: '' +rfc2136_server: '' +rfc2136_sign_query: false sakuracloud_api_secret: '' -netcup_customer_id: '' -netcup_api_key: '' -netcup_api_password: '' -gandi_api_key: '' -gandi_sharing_id: '' -transip_username: '' +sakuracloud_api_token: '' +simply_account_name: '' +simply_api_key: '' transip_api_key: '' +transip_global_key: '' +transip_username: '' +websupport_identifier: '' +websupport_secret_key: '' ``` +
+ +### Configure certificate files + +The certificate files will be available within the "ssl" share after successful +request of the certificates. + +By default other addons are referring to the correct path of the certificates. +You can in addition find the files via the "samba" addon within the "ssl" share. + +For example, to use the certificates provided by this add-on to enable TLS on +Home Assistant in the default paths, add the following lines to Home +Assistant's main configuration file, `configuration.yaml`: + +```yaml +# TLS with letsencrypt add-on +http: + server_port: 443 + ssl_certificate: /ssl/fullchain.pem + ssl_key: /ssl/privkey.pem +``` + +### Create & renew certificates + +The letsencrypt add-on creates the certificates once it is started: navigate +to **Settings** -> **Add-ons**, pick the **Let's Encrypt** add-on, click the +**START** button on the bottom. The add-on stops once the certificates are +created. + +Certificates are not renewed automatically by the plugin. The add-on has to be +started again to renew certificates. If the add-on is started again, it checks +if the certificates are due for renewal. This is usually the case 30 days +before the certificates' due date. If the certificates are not due for renewal, +the add-on terminates without changes. If the certificates are due for renewal, +new certificates will be created. + +There are multiple ways how the add-on can be started to check/renew the +certificates. One way to automate the certificate renewal it to configure a +renewal via [Home Assistant automation][haauto], and then restarting this +automation every night via the [Supervisor Addon restart action][supervisorrestart]. + +[haauto]: https://www.home-assistant.io/docs/automation/editor/ +[supervisorrestart]: https://www.home-assistant.io/integrations/hassio/#service-hassioaddon_restart + +In this example, the automation will run every day at the chosen time, checking +if a renewal is due, and will request it if needed. + ## Advanced
Changing the ACME Server - By default, The addon uses Let’s Encrypt’s default server at https://acme-v02.api.letsencrypt.org/. You can instruct the addon to use a different ACME server by providing the field `acme_server` with the URL of the server’s ACME directory: +By default, The addon uses Let’s Encrypt’s default server at . You can instruct the addon to use a different ACME server by providing the field `acme_server` with the URL of the server’s ACME directory: ```yaml acme_server: 'https://my.custom-acme-server.com' ``` - If your custom ACME server uses a certificate signed by an untrusted certificate authority (CA), you can add the root certificate to the trust store by setting its content as an option: +If your custom ACME server uses a certificate signed by an untrusted certificate authority (CA), you can add the root certificate to the trust store by setting its content as an option: + ```yaml acme_server: 'https://my.custom-acme-server.com' acme_root_ca_cert: | @@ -111,16 +253,58 @@ transip_api_key: ''
+
+ Selecting the Key Type + + By default the ECDSA key type is used. You can choose to use an RSA key for compatibility with systems where ECDSA keys are not supported. ECDSA is widely supported in modern software with security and performance benefits. + + ```yaml + key_type: 'rsa' + ``` + + When the `key_type` parameter is not set, the add-on will attempt to auto-detect an existing certificate's key type or use `ecdsa` by default. + +
+ +
+ Selecting the ECDSA Elliptic Curve + + You can choose from the following ECDSA elliptic curves: `secp256r1`, `secp384r1` + + ```yaml + key_type: 'ecdsa' + elliptic_curve: 'secp384r1' + ``` + + When the `elliptic_curve` parameter is not set, ECDSA keys will be generated using the Certbot default. This option must be used with `key_type` set to `'ecdsa'`. + +
+ +
+ Set up external account binding + + The ACME protocol (RFC 8555) defines an external account binding (EAB) field that ACME clients can use to access a specific account on the certificate authority (CA). Some CAs may require the client to utilize the EAB protocol to operate. You can add your EAB key ID and HMAC key through the config options `eab_kid` and `eab_hmac_key`. + + ```yaml + eab_kid: 'key_id' + eab_hmac_key: 'AABBCCDD' #Base64url encoded key + ``` + +
## Example Configurations +Note: These configuration examples are raw YAML configs. When you use UI edit +mode (default), and configure DNS, simply copy the attributes underneath *dns* +into the *DNS Provider configuration* field. +
HTTP challenge ```yaml email: your.email@example.com domains: - - home-assistant.io + - your.domain.tld certfile: fullchain.pem keyfile: privkey.pem challenge: http @@ -135,7 +319,7 @@ transip_api_key: '' ```yaml email: your.email@example.com domains: - - home-assistant.io + - your.domain.tld certfile: fullchain.pem keyfile: privkey.pem challenge: dns @@ -148,136 +332,192 @@ transip_api_key: ''
- Google DNS challenge + RSA key ```yaml email: your.email@example.com domains: - - home-assistant.io + - your.domain.tld certfile: fullchain.pem keyfile: privkey.pem + key_type: rsa challenge: dns dns: - provider: dns-google - google_creds: google.json + provider: dns-cloudflare + cloudflare_email: your.email@example.com + cloudflare_api_key: 31242lk3j4ljlfdwsjf0 ``` - Please copy your credentials file "google.json" into the "share" shared folder on the Home Assistant host before starting the service. +
+ +
+ Azure + +```yaml +email: your.email@example.com +domains: + - your.domain.tld +certfile: fullchain.pem +keyfile: privkey.pem +challenge: dns +dns: + provider: dns-azure + azure_config: azure.txt +``` - One way is to use the "Samba" add on to make the folder available via network or SSH Add-on. +Please copy your credentials file "azure.txt" into the "share" shared folder +on the Home Assistant host before starting the service. One way is to use the +"Samba" add on to make the folder available via network or SSH Add-on. You +can find information on the required file format in the [documentation][certbot-dns-azure-conf] +for the Certbot Azure plugin. - The credential file can be created and downloaded when creating the service user within the Google cloud. - You can find additional information regarding the required permissions in the "credentials" section here: +To use this plugin, [create an Azure Active Directory app registration][aad-appreg] +and service principal; add a client secret; and create a credentials file +using the above directions. Grant the app registration DNS Zone Contributor +on the DNS zone to be used for authentication. - +[aad-appreg]: https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal#register-an-application-with-azure-ad-and-create-a-service-principal +[certbot-dns-azure-conf]: https://certbot-dns-azure.readthedocs.io/en/latest/#configuration
- route53 DNS challenge + Cloudflare + +To use this plugin a Cloudflare API Token, restricted to the specific domain and operations are the recommended authentication option. +The API Token used for Certbot requires only the `Zone:DNS:Edit` permission for the zone in which you want a certificate. + +Example credentials file using restricted API Token (recommended): ```yaml - email: your.email@example.com - domains: - - home-assistant.io - certfile: fullchain.pem - keyfile: privkey.pem - challenge: dns dns: - provider: dns-route53 - aws_access_key_id: 0123456789ABCDEF0123 - aws_secret_access_key: 0123456789abcdef0123456789/abcdef0123456 + provider: dns-cloudflare + cloudflare_api_token: 0123456789abcdef0123456789abcdef01234 ``` - For security reasons, don't use your main account's credentials. Instead, add a new [AWS user](https://console.aws.amazon.com/iam/home?#/users) with _Access Type: Programmatic access_ and use that user's access key. Assign a minimum [policy](https://console.aws.amazon.com/iam/home?#/policies$new?step=edit) like the following example. Make sure to replace the Resource ARN in the first statement to your domain's hosted zone ARN or use _*_ for all. +Previously, Cloudflare’s “Global API Key” was used for authentication. However this key can access the entire Cloudflare API for all domains in your account, meaning it could cause a lot of damage if leaked. - ```json - { - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "ChangeSpecificDomainsRecordSet", - "Effect": "Allow", - "Action": "route53:ChangeResourceRecordSets", - "Resource": "arn:aws:route53:::hostedzone/01234567890ABC" - }, - { - "Sid": "ListAllHostedZones", - "Effect": "Allow", - "Action": "route53:ListHostedZones", - "Resource": "*" - }, - { - "Sid": "ReadChanges", - "Effect": "Allow", - "Action": "route53:GetChange", - "Resource": "arn:aws:route53:::change/*" - } - ] - } +Example credentials file using Global API Key (NOT RECOMMENDED: + + ```yaml + dns: + provider: dns-cloudflare + cloudflare_email: cloudflare@example.com + cloudflare_api_key: 0123456789abcdef0123456789abcdef01234 ```
- CloudFlare + ClouDNS - Previously, Cloudflare’s “Global API Key” was used for authentication, however this key can access the entire Cloudflare API for all domains in your account, meaning it could cause a lot of damage if leaked. +In order to use a domain with this challenge, you first need to log into your control panel and +create a new HTTP API user from the `API & Resellers` page on top of your control panel. + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-cloudns + cloudns_auth_id: 12345 + cloudns_auth_password: ****** + ``` - Cloudflare’s newer API Tokens can be restricted to specific domains and operations, and are therefore now the recommended authentication option. - The API Token used for Certbot requires only the `Zone:DNS:Edit` permission for the zone in which you want a certificate. +API Users have full account access. It is recommended to create an API Sub-user, which can be limited in scope. You can use either the `sub-auth-id` or the `sub-auth-user` as follows: - Example credentials file using restricted API Token (recommended): ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns dns: - provider: dns-cloudflare - cloudflare_api_token: 0123456789abcdef0123456789abcdef01234 + provider: dns-cloudns + cloudns_sub_auth_id: 12345 + cloudns_auth_password: ****** ``` - Example credentials file using Global API Key (not recommended): ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns dns: - provider: dns-cloudflare - cloudflare_email: cloudflare@example.com - cloudflare_api_key: 0123456789abcdef0123456789abcdef01234 + provider: dns-cloudns + cloudns_sub_auth_user: alice + cloudns_auth_password: ****** ```
- Linode - - To use this addon with Linode DNS, first [create a new API/access key](https://www.linode.com/docs/platform/api/getting-started-with-the-linode-api#get-an-access-token), with read/write permissions to DNS; no other permissions are needed. Newly keys will likely use API version '4.' **Important**: single quotes are required around the `linode_version` number; failure to do this will cause a type error (as the addon expects a string, not an integer). + deSEC.io + You need a deSEC API token with sufficient permission for performing the required DNS changes on your domain. + If you don't have a token yet, an easy way to obtain one is by logging into your account at deSEC.io. + Navigate to "Token Management" and create a new one. + It's good practice to restrict the token permissions as much as possible, e.g. by setting the maximum unused period to four months. + This way, the token will expire if it is not continuously used to renew your certificate. + ```yaml - email: you@mailprovider.com + email: your.email@example.com domains: - - ha.yourdomain.com + - your.domain.tld certfile: fullchain.pem keyfile: privkey.pem challenge: dns dns: - provider: dns-linode - linode_key: 865c9f462c7d54abc1ad2dbf79c938bc5c55575fdaa097ead2178ee68365ab3e - linode_version: '4' + provider: dns-desec + desec_token: your-desec-access-token ```
+
+ DigitalOcean + +Use of this plugin requires a configuration file containing DigitalOcean API credentials, obtained from your DigitalOcean account’s [Applications & API Tokens page](https://cloud.digitalocean.com/settings/api/tokens). + +```yaml + email: mail@domain.tld + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-digitalocean + digitalocean_token: digitalocean-token +``` + +[Full Documentation](https://certbot-dns-digitalocean.readthedocs.io/en/stable/) + +
+
DirectAdmin - It is recommended to create a login key in the DirectAdmin control panel to be used as value for directadmin_password. - Instructions on how to create such key can be found at https://help.directadmin.com/item.php?id=523. +It is recommended to create a login key in the DirectAdmin control panel to be used as value for directadmin_password. +Instructions on how to create such key can be found at . + +Make sure to grant the following permissions: - Make sure to grant the following permissions: - - `CMD_API_LOGIN_TEST` - - `CMD_API_DNS_CONTROL` - - `CMD_API_SHOW_DOMAINS` +- `CMD_API_LOGIN_TEST` +- `CMD_API_DNS_CONTROL` +- `CMD_API_SHOW_DOMAINS` +- `CMD_API_DOMAIN_POINTER` - Username and password can also be used in case your DirectAdmin instance has no support for login keys. +Username and password can also be used in case your DirectAdmin instance has no support for login keys. + +Example configuration: - Example configuration: ```yaml email: mail@domain.tld domains: @@ -296,35 +536,32 @@ transip_api_key: ''
- Njalla + dnsimple - You need to generate an API token inside Settings > API Access or directly at https://njal.la/settings/api/. If you have a static IP-address restrict the access to your IP. I you are not sure, you probably don't have a static IP-address. +Use of this plugin requires a configuration file containing DNSimple API credentials, obtained from your DNSimple [account page](https://dnsimple.com/user). - Example configuration: - - ```yaml - email: your.email@example.com +```yaml + email: mail@domain.tld domains: - - home-assistant.io + - your.domain.tld certfile: fullchain.pem keyfile: privkey.pem challenge: dns dns: - provider: dns-njalla - njalla_token: 0123456789abcdef0123456789abcdef01234567 - ``` + provider: dns-simple + dnsimple_token: dnssimple-token +``` + +[Full Documentation](https://certbot-dns-dnsimple.readthedocs.io/en/stable/)
- TransIP + dnsmadeeasy - You will need to generate an API key from the TransIP Control Panel at https://www.transip.nl/cp/account/api/. +Use of this plugin requires a configuration file containing DNS Made Easy API credentials, obtained from your DNS Made Easy [account page](https://cp.dnsmadeeasy.com/account/info). - The propagation limit will be automatically raised to 240 seconds. - - Example configuration: - ```yaml +```yaml email: your.email@example.com domains: - your.domain.tld @@ -332,89 +569,700 @@ transip_api_key: '' keyfile: privkey.pem challenge: dns dns: - provider: dns-transip - transip_username: transip-user - transip_api_key: | - -----BEGIN PRIVATE KEY----- - MII..ABCDEFGHIJKLMNOPQRSTUVWXYZ - AAAAAABCDEFGHIJKLMNOPQRSTUVWXYZ - -----END PRIVATE KEY----- - ``` + provider: dns-dnsmadeeasy + dnsmadeeasy_api_key: dnsmadeeasy-api-key + dnsmadeeasy_secret_key: dnsmadeeasy-secret-key +``` + +[Full Documentation](https://certbot-dns-dnsmadeeasy.readthedocs.io/en/stable/)
- OVH + domainoffensive - You will need to generate an OVH API Key first at https://eu.api.ovh.com/createToken/ (for Europe) or https://ca.api.ovh.com/createToken/ (for north America). +Use of this plugin requires an API token, obtained from domainoffensive account page in the menu under `Domains` -> `Settings` -> *Let's Encrypt API token`. - When creating the API Key, you must ensure that the following rights are granted: - * ``GET /domain/zone/*`` - * ``PUT /domain/zone/*`` - * ``POST /domain/zone/*`` - * ``DELETE /domain/zone/*`` - - Example configuration ```yaml email: your.email@example.com domains: - - home-assistant.io + - your.domain.tld certfile: fullchain.pem keyfile: privkey.pem challenge: dns dns: - provider: dns-ovh - ovh_endpoint: ovh-eu - ovh_application_key: 0123456789abcdef0123456789abcdef01234 - ovh_application_secret: 0123456789abcdef0123456789abcdef01234 - ovh_consumer_key: 0123456789abcdef0123456789abcdef01234 + provider: dns-domainoffensive + domainoffensive_token: domainoffensive-token ``` - Use `ovh_endpoint: ovh-ca` for north America region. + +[Full Documentation DE](https://www.do.de/wiki/freie-ssl-tls-zertifikate-ueber-acme/)
- RFC2136 + DreamHost - You will need to set up a server with RFC2136 (Dynamic Update) support with a TKEY (to authenticate the updates). How to do this will vary depending on the DNS server software in use. For Bind9, you first need to first generate an authentication key by running - +Use of this plugin an API key from DreamHost with `dns-*` permissions. You can get it [here](https://panel.dreamhost.com/?tree=home.api) + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-dreamhost + dreamhost_baseurl: https://api.dreamhost.com/ + dreamhost_api_key: dreamhost-api-key + ``` + +
+ +
+ DuckDNS + +Use of this plugin requires an API token, obtained from the DuckDNS account page. + +```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-duckdns + duckdns_token: duckdns-token + +``` + +[Full documentation](https://github.com/infinityofspace/certbot_dns_duckdns?tab=readme-ov-file#usage) + +
+ +
+ Dynu + +You can get the API key in the API Credentials area of the Dynu control panel: + +```yaml +email: your.email@example.com +domains: + - your.domain.tld +certfile: fullchain.pem +keyfile: privkey.pem +challenge: dns +dns: + provider: dns-dynu + dynu_auth_token: 0123456789abcdef +``` + +
+ +
+ easyDNS + +easyDNS REST API access must be requested and granted in order to use this module: after logging into your account. + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-easydns + easydns_token: 0123456789abcdef + easydns_key: **** + easydns_endpoint: https://rest.easydns.net + ``` + +
+ +
+ EuroDNS + + You can configure the APP id and the API key in the API Users area of the Eurodns control panel: + +```yaml +domains: + - your.domain.tld +certfile: fullchain.pem +keyfile: privkey.pem +challenge: dns +dns: + provider: dns-eurodns + eurodns_applicationId: X-APP-ID + eurodns_apiKey: X-API-KEY + propagation_seconds: 60 +``` + +
+ +
+ Gandi + +Use of this plugin requires an [PersonalAccessToken](https://helpdesk.gandi.net/hc/en-us/articles/14051397687324-Personal-Access-Tokens) for the [Gandi LiveDNS API](https://api.gandi.net/docs/livedns/) with `Domains` scope for the `domain.tld` you are going to request a certificate for. +If you only have an Gandi LiveDNS `API key`, please refer to the [FAQ](https://github.com/obynio/certbot-plugin-gandi?tab=readme-ov-file#faq) on how to use this. +Due to the wide scope of this `API key`, this is not the recommended setup. + +```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-gandi + gandi_token: gandi-personalaccesstoken +``` + +[Full Documentation](https://github.com/obynio/certbot-plugin-gandi?tab=readme-ov-file) + +
+ +
+ gehirn + +Use of this plugin requires Gehirn Infrastructure Service DNS API credentials, obtained from your Gehirn Infrastructure Service [dashboard](https://gis.gehirn.jp/). + +```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-gehirn + gehirn_api_secret: gehirn-api-secret + gehirn_api_token: gehirn-api-token +``` + +[Full Documentation](https://certbot-dns-gehirn.readthedocs.io/en/stable/) + +
+ +
+ GoDaddy + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-godaddy + godaddy_secret: YOUR_GODADDY_SECRET + godaddy_key: YOUR_GODADDY_KEY + ``` + +To obtain the ACME DNS API Key and Secret, follow the instructions here: + + +**IMPORTANT**: GoDaddy limits DNS API access to customers with 10 or more domains and/or an active "Discount Domain Club – Premier Membership" plan; the API will respond with a HTTP401 otherwise. See the [Terms of Use](https://developer.godaddy.com/getstarted) for more information. + +
+ +
+ Google Cloud + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-google + google_creds: google.json + ``` + +Please copy your credentials file "google.json" into the "share" shared folder on the Home Assistant host before starting the service. + +One way is to use the "Samba" add on to make the folder available via network or SSH Add-on. + +The credential file can be created and downloaded when creating the service user within the Google cloud. +You can find additional information regarding the required permissions in the "credentials" section here: + + + +
+ +
+ Hurricane Electric (HE) + +Use of this plugin requires your Hurricane Electric username and password. +You will need to create the dynamic TXT record from within the dns.he.net interface before you will be able to make updates. You will not be able to dynamically create and delete these TXT records as doing so would subsequently remove your ddns key associated with the record. + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + propagation_seconds: 310 + provider: dns-he + he_user: me + he_pass: ****** + ``` + +[Full Documentation](https://dns.he.net/) + +
+ +
+ Hetzner + +Use of this plugin requires a Hetzner DNS API personal access token. You can create one on the Hetzner [DNS website](https://dns.hetzner.com/settings/api-token). + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-hetzner + hetzner_api_token: hetzner-personal-access-token + ``` + +[Full Documentation](https://github.com/ctrlaltcoop/certbot-dns-hetzner) + +
+ +
+ Infomaniak + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-infomaniak + infomaniak_api_token: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + ``` + +To obtain the DNS API token follow the instructions here: + + + +Choose "Domain" as the scope. + +
+ +
+ INWX + +Use the user for the dyndns service, not the normal user. +The shared secret is the 2FA code, it must be the same length as the example. +To get this code, you must activate the 2FA or deactivate and reactivate 2FA. +Without 2FA leave the example key. + +Example configuration: + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-inwx + inwx_username: user + inwx_password: password + inwx_shared_secret: ABCDEFGHIJKLMNOPQRSTUVWXYZ012345 + ``` + +
+ +
+ IONOS + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-ionos + ionos_prefix: YOUR_IONOS_API_KEY_PREFIX + ionos_secret: YOUR_IONOS_API_KEY_SECRET + ionos_endpoint: https://api.hosting.ionos.com + ``` + +To obtain the DNS API Key Information, follow the instructions here: + + +
+ +
+ Joker + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-joker + joker_username: username + joker_password: password + joker_domain: example.com + ``` + +You can find further detailed information here: + + + + +
+ +
+ Linode + +To use this addon with Linode DNS, first [create a new API/access key](https://www.linode.com/docs/platform/api/getting-started-with-the-linode-api#get-an-access-token), with read/write permissions to DNS; no other permissions are needed. Newly keys will likely use API version '4.' **Important**: single quotes are required around the `linode_version` number; failure to do this will cause a type error (as the addon expects a string, not an integer). + + ```yaml + email: you@mailprovider.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-linode + linode_key: 865c9f462c7d54abc1ad2dbf79c938bc5c55575fdaa097ead2178ee68365ab3e + linode_version: '4' + ``` + +
+ +
+ Loopia + +To use this addon with Loopia DNS, first [create a new API user](https://customerzone.loopia.com/api/), with the following minimum required permissions: + +- `addZoneRecord` - Required to create DNS records +- `getZoneRecords` - Required to verify DNS records +- `removeZoneRecord` - Required to clean up DNS records +- `removeSubdomain` - Required for complete cleanup + +Example configuration in YAML edit mode: + +```yaml +email: you@mailprovider.com +domains: + - your.domain.tld +certfile: fullchain.pem +keyfile: privkey.pem +challenge: dns +dns: + provider: dns-loopia + loopia_user: example@loopiaapi + loopia_password: supersecretpasswordhere +``` + +
+ +
+ LuaDNS + +Use of this plugin requires LuaDNS API credentials, obtained from your [account settings page](https://api.luadns.com/settings). + +```yaml +email: your.email@example.com +domains: + - your.domain.tld +certfile: fullchain.pem +keyfile: privkey.pem +challenge: dns +dns: + provider: dns-luadns + luadns_email: your.email@example.com + luadns_token: luadns-token +``` + +[Full Documentation](https://certbot-dns-luadns.readthedocs.io/en/stable/) + +
+ +
+ mijn.host + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-mijn-host + mijn_host_api_key: XXXXXX + propagation_seconds: 60 + ``` + +The `mijn_host_api_key` is the account's API key. +The API key assigned to your mijn.host account can be found in your mijn.host Control panel. + +
+ +
+ Namecheap + +To use this addon with Namecheap, you must first enable API access on your account. See "Enabling API Access" and "Whitelisting IP" [here](https://www.namecheap.com/support/api/intro/) for details and requirements. + +Example configuration: + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-namecheap + namecheap_username: your-namecheap-username + namecheap_api_key: 0123456789abcdef0123456789abcdef01234567 ``` - $ dnssec-keygen -a HMAC-SHA512 -b 512 -n HOST letsencrypt - Kletsencrypt.+165+20675 + +
+ +
+ Netcup + +Both the API password and key can be obtained via the following page: +It is important to set the `propagation_seconds` to >= 630 seconds due to the slow DNS update of Netcup. + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-netcup + netcup_customer_id: "userid" + netcup_api_key: **** + netcup_api_password: **** + propagation_seconds: "900" ``` - - The key file (Kletsencrypt.+165+20675.key in this example) looks like the following: - + +References: + +- +- + +
+ +
+ Njalla + +You need to generate an API token inside Settings > API Access or directly at . If you have a static IP-address restrict the access to your IP. I you are not sure, you probably don't have a static IP-address. + +Example configuration: + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-njalla + njalla_token: 0123456789abcdef0123456789abcdef01234567 ``` - $ cat Kletsencrypt.+165+20675.key - letsencrypt. IN KEY 512 3 165 Cj2SJThIYZqZO39HIOA8dYryzsLT3CI+m43m3yfGfTMvpyYw5DXjn5da hokrwyLe3MTboGkloKIsT6DUcTSdEA== - + +
+ +
+ noris network + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-noris + noris_token: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + propagation_seconds: 240 + ``` + +To obtain the `noris_token` follow the instructions as described in our [GitHub repository][GitHub repo]. + +You can define the `propagation_seconds` explicitly. Otherwise, it will use the default value (currently set to `60` seconds). + +[GitHub repo]: + +
+ +
+ nsone + +Use of this plugin requires NS1 API credentials, obtained from your NS1 [account page](https://my.nsone.net/#/account/settings). + +```yaml +email: your.email@example.com +domains: + - your.domain.tld +certfile: fullchain.pem +keyfile: privkey.pem +challenge: dns +dns: + provider: dns-nsone + nsone_api_key: nsone-api-key +``` + +[Full Documentation](https://certbot-dns-nsone.readthedocs.io/en/stable/) + +
+ +
+ OVH + +You will need to generate an OVH API Key first at (for Europe) or (for North America). +Further documentation is [here](https://certbot-dns-ovh.readthedocs.io/en/stable/). + +When creating the API Key, you must ensure that the following rights are granted: + +- ``GET /domain/zone/*`` +- ``PUT /domain/zone/*`` +- ``POST /domain/zone/*`` +- ``DELETE /domain/zone/*`` + +Example configuration + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-ovh + ovh_endpoint: ovh-eu + ovh_application_key: 0123456789abcdef0123456789abcdef01234 + ovh_application_secret: 0123456789abcdef0123456789abcdef01234 + ovh_consumer_key: 0123456789abcdef0123456789abcdef01234 ``` - You don't need to publish this; just copy the key data into your named.conf file: + +Use `ovh_endpoint: ovh-ca` for North America region. + +
+ +
+ Plesk Hosting + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-plesk + plesk_username: your-username + plesk_password: your-password + plesk_api_url: https://plesk.example.com + propagation_seconds: 120 ``` - + +The `plesk_username` and `plesk_password` are the same as those you use on the login page of your admin panel. + +The `plesk_api_url` is the base URL of your Plesk admin panel. + +You can define the `propagation_seconds` explicitly. Otherwise, it will use a custom default value (currently set to `120` seconds). +If the provided value is less than `120`, then the value is forced to a minimum of `120` seconds. + +
+ +
+ Porkbun + +In order to use a domain with this challenge, API access will need enabling on the domain. In order to +do this go to domain management -> select the domain -> details and click the API access toggle. +Then go to the menu in the top right select API access and then create a new api key. +The title does not matter and is not used by certbot, make note of the key and the secret as both are required. + +```yaml +email: your.email@example.com +domains: + - your.domain.tld +certfile: fullchain.pem +keyfile: privkey.pem +challenge: dns +dns: + provider: dns-porkbun + porkbun_key: 0123456789abcdef0123456789abcdef01234 + porkbun_secret: 0123456789abcdef0123456789abcdef01234 +``` + +
+ +
+ RFC2136 + +You will need to set up a server with RFC2136 (Dynamic Update) support with a TKEY (to authenticate the updates). How to do this will vary depending on the DNS server software in use. For Bind9, you first need to first generate an authentication key by running + + ```shell + $ tsig-keygen -a hmac-sha512 letsencrypt key "letsencrypt" { algorithm hmac-sha512; - secret "Cj2SJThIYZqZO39HIOA8dYryzsLT3CI+m43m3yfGfTMvpyYw5DXjn5da hokrwyLe3MTboGkloKIsT6DUcTSdEA=="; + secret "xxxxxxxxxxxxxxxxxx=="; }; - ``` - And ensure you have an update policy in place in the zone that uses this key to enable update of the correct domain (which must match the domain in your yaml configuration): + +You don't need to publish this; just copy the key data into your named.conf file: + + ```shell + key "letsencrypt" { + algorithm hmac-sha512; + secret "xxxxxxxxxxxxxxxxxx=="; + }; ``` + +And ensure you have an update policy in place in the zone that uses this key to enable update of the correct domain (which must match the domain in your yaml configuration): + ```shell update-policy { - grant letsencrypt name _acme-challenge.home-assistant.io. txt; + grant letsencrypt name _acme-challenge.your.domain.tld. txt; }; ``` - For this provider, you will need to supply all the `rfc2136_*` options. Note that the `rfc2136_port` item is required (there is no default port in the add-on) and, most importantly, the port number must be quoted. Also, be sure to copy in the key so certbot can authenticate to the DNS server. Finally, the algorithm should be in all caps. +For this provider, you will need to supply all the `rfc2136_*` options. Note that the `rfc2136_port` item is required (there is no default port in the add-on) and, most importantly, the port number must be quoted. Also, be sure to copy in the key so certbot can authenticate to the DNS server. Finally, the algorithm should be in all caps. - An example configuration: +An example configuration: ```yaml email: your.email@example.com domains: - - home-assistant.io + - your.domain.tld certfile: fullchain.pem keyfile: privkey.pem challenge: dns @@ -425,10 +1273,151 @@ transip_api_key: '' rfc2136_name: letsencrypt rfc2136_secret: "secret-key" rfc2136_algorithm: HMAC-SHA512 + # Optional: Enable TSIG key signing for DNS queries (useful for BIND multiple views) + rfc2136_sign_query: true ``` - + +
+ +
+ route53 + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-route53 + aws_access_key_id: 0123456789ABCDEF0123 + aws_secret_access_key: 0123456789abcdef0123456789/abcdef0123456 + ``` + +For security reasons, don't use your main account's credentials. Instead, add a new [AWS user](https://console.aws.amazon.com/iam/home?#/users) with _Access Type: Programmatic access_ and use that user's access key. Assign a minimum [policy](https://console.aws.amazon.com/iam/home?#/policies$new?step=edit) like the following example. Make sure to replace the Resource ARN in the first statement to your domain's hosted zone ARN or use _*_ for all. + + ```json + { + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "ChangeSpecificDomainsRecordSet", + "Effect": "Allow", + "Action": "route53:ChangeResourceRecordSets", + "Resource": "arn:aws:route53:::hostedzone/01234567890ABC" + }, + { + "Sid": "ListAllHostedZones", + "Effect": "Allow", + "Action": "route53:ListHostedZones", + "Resource": "*" + }, + { + "Sid": "ReadChanges", + "Effect": "Allow", + "Action": "route53:GetChange", + "Resource": "arn:aws:route53:::change/*" + } + ] + } + ``` + +
+ +
+ SakuraCloud + +Use of this plugin requires Sakura Cloud DNS API credentials, obtained from your Sakura Cloud DNS [apikey page](https://secure.sakura.ad.jp/cloud/#!/apikey/top/). + +```yaml +email: your.email@example.com +domains: + - your.domain.tld +certfile: fullchain.pem +keyfile: privkey.pem +challenge: dns +dns: + provider: dns-sakuracloud + sakuracloud_api_secret: '' + sakuracloud_api_token: '' +``` + +[Full Documentation](https://certbot-dns-sakuracloud.readthedocs.io/en/stable/) + +
+ +
+ Simply.com + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-simply + simply_account_name: Sxxxxxx + simply_api_key: YOUR_API_KEY # Replace 'YOUR_API_KEY' with your actual Simply.com API key. + ``` + +The `simply_account_name` refers to the Simply.com account number (Sxxxxxx), and the `simply_api_key` is the account's API key. +The API key assigned to your Simply.com account can be found in your Simply.com Control panel. + +
+ +
+ TransIP + +You will need to generate an API key from the TransIP Control Panel at . + +If you can't use IP whitelisting, set the `transip_global_key` parameter to `'yes'`. See [Certbot TransIP DNS plugin documentation](https://github.com/hsmade/certbot-dns-transip/blob/master/USAGE.rst#ip-whitelistsing) for more details. + +The propagation limit will be automatically raised to 240 seconds. + +Example configuration: + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-transip + transip_username: transip-user + transip_global_key: 'no' + transip_api_key: | + -----BEGIN PRIVATE KEY----- + MII..ABCDEFGHIJKLMNOPQRSTUVWXYZ + AAAAAABCDEFGHIJKLMNOPQRSTUVWXYZ + -----END PRIVATE KEY----- + ``` +
+
+ WebSupport + +An identifier and secret key have to be obtained to use this module (see ). + + ```yaml + email: your.email@example.com + domains: + - your.domain.tld + certfile: fullchain.pem + keyfile: privkey.pem + challenge: dns + dns: + provider: dns-websupport + websupport_identifier: + websupport_secret_key: + ``` + +
## Certificate files @@ -440,25 +1429,48 @@ You can in addition find the files via the "samba" addon within the "ssl" share. ## Supported DNS providers ```txt +dns-azure dns-cloudflare -dns-cloudxns +dns-cloudns +dns-desec dns-digitalocean dns-directadmin dns-dnsimple dns-dnsmadeeasy +dns-domainoffensive +dns-dreamhost +dns-duckdns +dns-dynu +dns-easydns +dns-eurodns +dns-gandi dns-gehirn +dns-godaddy dns-google +dns-he +dns-hetzner +dns-infomaniak +dns-inwx +dns-ionos +dns-joker dns-linode +dns-loopia dns-luadns +dns-mijn-host +dns-namecheap +dns-netcup dns-njalla +dns-noris dns-nsone dns-ovh +dns-plesk +dns-porkbun dns-rfc2136 dns-route53 dns-sakuracloud -dns-netcup -dns-gandi +dns-simply dns-transip +dns-websupport ``` ## Support @@ -476,6 +1488,6 @@ In case you've found a bug, please [open an issue on our GitHub][issue]. [discord]: https://discord.gg/c5DvZ4e [forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues +[issue]: https://github.com/home-assistant/addons/issues [certbot]: https://certbot.eff.org [reddit]: https://reddit.com/r/homeassistant diff --git a/letsencrypt/Dockerfile b/letsencrypt/Dockerfile index e66f80c314e..256848b52ce 100644 --- a/letsencrypt/Dockerfile +++ b/letsencrypt/Dockerfile @@ -2,44 +2,103 @@ ARG BUILD_FROM FROM $BUILD_FROM # setup base -ARG CERTBOT_VERSION -ARG CERTBOT_DNS_DIRECTADMIN_VERSION -ARG CERTBOT_NETCUP_VERSION -ARG CERTBOT_NJALLA_VERSION -ARG CERTBOT_GANDI_VERSION -ARG CERTBOT_DNS_TRANSIP_VERSION +# Developer note: please add a new plugin alphabetically into all lists +ARG \ + BUILD_ARCH \ + ACME_VERSION \ + CERTBOT_DNS_AZURE_VERSION \ + CERTBOT_DNS_CLOUDNS_VERSION \ + CERTBOT_DNS_DESEC_VERSION \ + CERTBOT_DNS_DIRECTADMIN_VERSION \ + CERTBOT_DNS_DOMAINOFFENSIVE_VERSION \ + CERTBOT_DNS_DREAMHOST_VERSION \ + CERTBOT_DNS_DUCKDNS_VERSION \ + CERTBOT_DNS_DYNU_VERSION \ + CERTBOT_DNS_EASYDNS_VERSION \ + CERTBOT_DNS_EURODNS_VERSION \ + CERTBOT_DNS_GANDI_VERSION \ + CERTBOT_DNS_GODADDY_VERSION \ + CERTBOT_DNS_HETZNER_VERSION \ + CERTBOT_DNS_HURRICANE_ELECTRIC_VERSION \ + CERTBOT_DNS_INFOMANIAK_VERSION \ + CERTBOT_DNS_INWX_VERSION \ + CERTBOT_DNS_IONOS_VERSION \ + CERTBOT_DNS_JOKER_VERSION \ + CERTBOT_DNS_LOOPIA_VERSION \ + CERTBOT_DNS_MIJN_HOST_VERSION \ + CERTBOT_DNS_NAMECHEAP_VERSION \ + CERTBOT_DNS_NETCUP_VERSION \ + CERTBOT_DNS_NJALLA_VERSION \ + CERTBOT_DNS_NORISNETWORK_VERSION \ + CERTBOT_DNS_PLESK_VERSION \ + CERTBOT_DNS_PORKBUN_VERSION \ + CERTBOT_DNS_SIMPLY_VERSION \ + CERTBOT_DNS_TRANSIP_VERSION \ + CERTBOT_DNS_WEBSUPPORT_VERSION \ + CERTBOT_VERSION \ + CLOUDFLARE_VERSION \ + CRYPTOGRAPHY_VERSION -RUN apk add --no-cache --update \ +RUN \ + set -x \ + && apk add --no-cache --update \ libffi \ musl \ openssl \ && apk add --no-cache --virtual .build-dependencies \ - g++ \ + build-base \ libffi-dev \ musl-dev \ openssl-dev \ + cargo \ && pip3 install --no-cache-dir --find-links \ "https://wheels.home-assistant.io/alpine-$(cut -d '.' -f 1-2 < /etc/alpine-release)/${BUILD_ARCH}/" \ - certbot==${CERTBOT_VERSION} \ + acme==${ACME_VERSION} \ + certbot-dns-azure==${CERTBOT_DNS_AZURE_VERSION} \ certbot-dns-cloudflare==${CERTBOT_VERSION} \ - certbot-dns-cloudxns==${CERTBOT_VERSION} \ + certbot-dns-cloudns==${CERTBOT_DNS_CLOUDNS_VERSION} \ + certbot-dns-desec==${CERTBOT_DNS_DESEC_VERSION} \ certbot-dns-digitalocean==${CERTBOT_VERSION} \ certbot-dns-directadmin==${CERTBOT_DNS_DIRECTADMIN_VERSION} \ certbot-dns-dnsimple==${CERTBOT_VERSION} \ certbot-dns-dnsmadeeasy==${CERTBOT_VERSION} \ + certbot-dns-domainoffensive==${CERTBOT_DNS_DOMAINOFFENSIVE_VERSION} \ + certbot-dns-dreamhost==${CERTBOT_DNS_DREAMHOST_VERSION} \ + certbot-dns-duckdns==${CERTBOT_DNS_DUCKDNS_VERSION} \ + certbot-dns-dynu-dev==${CERTBOT_DNS_DYNU_VERSION} \ + certbot-dns-easydns==${CERTBOT_DNS_EASYDNS_VERSION} \ + certbot-dns-eurodns==${CERTBOT_DNS_EURODNS_VERSION} \ + certbot-dns-gandi==${CERTBOT_DNS_GANDI_VERSION} \ certbot-dns-gehirn==${CERTBOT_VERSION} \ + certbot-dns-godaddy==${CERTBOT_DNS_GODADDY_VERSION} \ certbot-dns-google==${CERTBOT_VERSION} \ + certbot-dns-hetzner==${CERTBOT_DNS_HETZNER_VERSION} \ + certbot-dns-hurricane-electric==${CERTBOT_DNS_HURRICANE_ELECTRIC_VERSION} \ + certbot-dns-infomaniak==${CERTBOT_DNS_INFOMANIAK_VERSION} \ + certbot-dns-inwx==${CERTBOT_DNS_INWX_VERSION} \ + certbot-dns-ionos==${CERTBOT_DNS_IONOS_VERSION} \ + certbot-dns-joker==${CERTBOT_DNS_JOKER_VERSION} \ certbot-dns-linode==${CERTBOT_VERSION} \ + certbot-dns-loopia==${CERTBOT_DNS_LOOPIA_VERSION} \ certbot-dns-luadns==${CERTBOT_VERSION} \ - certbot-dns-njalla==${CERTBOT_NJALLA_VERSION} \ + certbot-dns-mijn-host==${CERTBOT_DNS_MIJN_HOST_VERSION} \ + certbot-dns-namecheap==${CERTBOT_DNS_NAMECHEAP_VERSION} \ + certbot-dns-netcup==${CERTBOT_DNS_NETCUP_VERSION} \ + certbot-dns-njalla==${CERTBOT_DNS_NJALLA_VERSION} \ + certbot-dns-norisnetwork==${CERTBOT_DNS_NORISNETWORK_VERSION} \ certbot-dns-nsone==${CERTBOT_VERSION} \ certbot-dns-ovh==${CERTBOT_VERSION} \ + certbot-dns-plesk==${CERTBOT_DNS_PLESK_VERSION} \ + certbot-dns-porkbun==${CERTBOT_DNS_PORKBUN_VERSION} \ certbot-dns-rfc2136==${CERTBOT_VERSION} \ certbot-dns-route53==${CERTBOT_VERSION} \ certbot-dns-sakuracloud==${CERTBOT_VERSION} \ - certbot-dns-netcup==${CERTBOT_NETCUP_VERSION} \ - certbot-plugin-gandi==${CERTBOT_GANDI_VERSION} \ + certbot-dns-simply==${CERTBOT_DNS_SIMPLY_VERSION} \ certbot-dns-transip==${CERTBOT_DNS_TRANSIP_VERSION} \ + certbot-dns-websupport==${CERTBOT_DNS_WEBSUPPORT_VERSION} \ + certbot==${CERTBOT_VERSION} \ + cloudflare==${CLOUDFLARE_VERSION} \ + cryptography==${CRYPTOGRAPHY_VERSION} \ && apk del .build-dependencies # Copy data diff --git a/letsencrypt/README.md b/letsencrypt/README.md index 66dfc36fcfe..0b7addf3755 100644 --- a/letsencrypt/README.md +++ b/letsencrypt/README.md @@ -9,12 +9,6 @@ It requires you to own the domain you are requesting the certificate for. The generated certificate can be used within others addons. By default the path and file for the certificates within other addons will refer to the files generated within this addon. -[discord]: https://discord.gg/c5DvZ4e -[forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues -[certbot]: https://certbot.eff.org -[reddit]: https://reddit.com/r/homeassistant - [aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg [amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg [armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg diff --git a/letsencrypt/build.json b/letsencrypt/build.json deleted file mode 100644 index 3c6bad13a55..00000000000 --- a/letsencrypt/build.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "build_from": { - "aarch64": "homeassistant/aarch64-base-python:3.7-alpine3.11", - "amd64": "homeassistant/amd64-base-python:3.7-alpine3.11", - "armhf": "homeassistant/armhf-base-python:3.7-alpine3.11", - "armv7": "homeassistant/armv7-base-python:3.7-alpine3.11", - "i386": "homeassistant/i386-base-python:3.7-alpine3.11" - }, - "args": { - "CERTBOT_VERSION": "1.2.0", - "CERTBOT_DNS_DIRECTADMIN_VERSION": "0.0.13", - "CERTBOT_NETCUP_VERSION": "0.31.0.1", - "CERTBOT_NJALLA_VERSION": "0.0.4", - "CERTBOT_GANDI_VERSION": "1.2.5", - "CERTBOT_DNS_TRANSIP_VERSION": "0.3.0" - } -} diff --git a/letsencrypt/build.yaml b/letsencrypt/build.yaml new file mode 100644 index 00000000000..86798fc3fc8 --- /dev/null +++ b/letsencrypt/build.yaml @@ -0,0 +1,45 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base-python:3.13-alpine3.21 + amd64: ghcr.io/home-assistant/amd64-base-python:3.13-alpine3.21 + armhf: ghcr.io/home-assistant/armhf-base-python:3.13-alpine3.21 + armv7: ghcr.io/home-assistant/armv7-base-python:3.13-alpine3.21 + i386: ghcr.io/home-assistant/i386-base-python:3.13-alpine3.21 +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io +args: + # Developer note: please add a new plugin alphabetically into all lists + ACME_VERSION: 3.2.0 + CERTBOT_DNS_AZURE_VERSION: 2.6.1 + CERTBOT_DNS_CLOUDNS_VERSION: 0.7.0 + CERTBOT_DNS_DESEC_VERSION: 1.2.1 + CERTBOT_DNS_DIRECTADMIN_VERSION: 1.0.13 + CERTBOT_DNS_DOMAINOFFENSIVE_VERSION: 2.0.0 + CERTBOT_DNS_DREAMHOST_VERSION: 1.0 + CERTBOT_DNS_DUCKDNS_VERSION: 1.5 + CERTBOT_DNS_DYNU_VERSION: 0.0.8 + CERTBOT_DNS_EASYDNS_VERSION: 0.1.4 + CERTBOT_DNS_EURODNS_VERSION: 1.8.1 + CERTBOT_DNS_GANDI_VERSION: 1.6.1 + CERTBOT_DNS_GODADDY_VERSION: 2.8.0 + CERTBOT_DNS_HETZNER_VERSION: 2.0.1 + CERTBOT_DNS_HURRICANE_ELECTRIC_VERSION: 0.1.0 + CERTBOT_DNS_INFOMANIAK_VERSION: 0.2.3 + CERTBOT_DNS_INWX_VERSION: 3.0.2 + CERTBOT_DNS_IONOS_VERSION: 2024.11.9 + CERTBOT_DNS_JOKER_VERSION: 1.1.0 + CERTBOT_DNS_LOOPIA_VERSION: 1.0.1 + CERTBOT_DNS_MIJN_HOST_VERSION: 0.0.8 + CERTBOT_DNS_NAMECHEAP_VERSION: 1.0.0 + CERTBOT_DNS_NETCUP_VERSION: 1.4.4 + CERTBOT_DNS_NJALLA_VERSION: 2.0.2 + CERTBOT_DNS_NORISNETWORK_VERSION: 0.3.0 + CERTBOT_DNS_PLESK_VERSION: 0.3.0 + CERTBOT_DNS_PORKBUN_VERSION: 0.9.1 + CERTBOT_DNS_SIMPLY_VERSION: 0.1.2 + CERTBOT_DNS_TRANSIP_VERSION: 0.5.2 + CERTBOT_DNS_WEBSUPPORT_VERSION: 3.0.0 + CERTBOT_VERSION: 3.2.0 + CLOUDFLARE_VERSION: 2.19.4 + CRYPTOGRAPHY_VERSION: 44.0.1 diff --git a/letsencrypt/config.json b/letsencrypt/config.json deleted file mode 100644 index ac0ec939c3f..00000000000 --- a/letsencrypt/config.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "name": "Let's Encrypt", - "version": "4.11.0", - "slug": "letsencrypt", - "description": "Manage certificate from Let's Encrypt", - "url": "https://github.com/home-assistant/hassio-addons/tree/master/letsencrypt", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "startup": "once", - "init": false, - "boot": "manual", - "ports": { - "80/tcp": 80 - }, - "ports_description": { - "80/tcp": "Only needed for http challenge" - }, - "map": ["ssl:rw", "share"], - "options": { - "email": null, - "domains": [null], - "certfile": "fullchain.pem", - "keyfile": "privkey.pem", - "challenge": "http", - "dns": {} - }, - "schema": { - "email": "email", - "domains": ["str"], - "certfile": "str", - "keyfile": "str", - "challenge": "list(dns|http)", - "acme_server": "url?", - "acme_root_ca_cert": "str?", - "dns": { - "provider": "list(dns-cloudflare|dns-cloudxns|dns-digitalocean|dns-directadmin|dns-dnsimple|dns-dnsmadeeasy|dns-gehirn|dns-google|dns-linode|dns-luadns|dns-njalla|dns-nsone|dns-ovh|dns-rfc2136|dns-route53|dns-sakuracloud|dns-netcup|dns-gandi|dns-transip)?", - "propagation_seconds": "int(60,3600)?", - "cloudflare_email": "email?", - "cloudflare_api_key": "str?", - "cloudflare_api_token": "str?", - "cloudxns_api_key": "str?", - "cloudxns_secret_key": "str?", - "digitalocean_token": "str?", - "directadmin_url": "str?", - "directadmin_username": "str?", - "directadmin_password": "str?", - "dnsimple_token": "str?", - "dnsmadeeasy_api_key": "str?", - "dnsmadeeasy_secret_key": "str?", - "gehirn_api_token": "str?", - "gehirn_api_secret": "str?", - "google_creds": "str?", - "linode_key": "str?", - "linode_version": "str?", - "luadns_email": "email?", - "luadns_token": "str?", - "njalla_token": "str?", - "nsone_api_key": "str?", - "ovh_endpoint": "str?", - "ovh_application_key": "str?", - "ovh_application_secret": "str?", - "ovh_consumer_key": "str?", - "rfc2136_server": "str?", - "rfc2136_port": "str?", - "rfc2136_name": "str?", - "rfc2136_secret": "str?", - "rfc2136_algorithm": "str?", - "aws_access_key_id": "str?", - "aws_secret_access_key": "str?", - "sakuracloud_api_token": "str?", - "sakuracloud_api_secret": "str?", - "netcup_customer_id": "str?", - "netcup_api_key": "str?", - "netcup_api_password": "str?", - "gandi_api_key": "str?", - "gandi_sharing_id": "str?", - "transip_username": "str?", - "transip_api_key": "str?" - } - }, - "image": "homeassistant/{arch}-addon-letsencrypt" -} diff --git a/letsencrypt/config.yaml b/letsencrypt/config.yaml new file mode 100644 index 00000000000..e94056a33c4 --- /dev/null +++ b/letsencrypt/config.yaml @@ -0,0 +1,180 @@ +--- +version: 5.4.3 +breaking_versions: [5.3.0] +slug: letsencrypt +name: Let's Encrypt +description: Manage certificate from Let's Encrypt +url: https://github.com/home-assistant/addons/tree/master/letsencrypt +arch: + - armhf + - armv7 + - aarch64 + - amd64 + - i386 +boot: manual +image: homeassistant/{arch}-addon-letsencrypt +init: false +map: + - ssl:rw + - share +options: + domains: + - null + email: null + keyfile: privkey.pem + certfile: fullchain.pem + challenge: http + dns: {} +ports: + 80/tcp: 80 +schema: + domains: + - str + email: email + keyfile: str + certfile: str + challenge: list(dns|http) + acme_root_ca_cert: str? + acme_server: url? + eab_kid: str? + eab_hmac_key: str? + key_type: list(ecdsa|rsa)? + elliptic_curve: list(secp256r1|secp384r1)? + dry_run: bool? + test_cert: bool? + verbose: bool? + dns: + # Developer note: please add a new plugin alphabetically into all lists + aws_access_key_id: str? + aws_secret_access_key: str? + azure_config: str? + cloudflare_api_key: str? + cloudflare_api_token: str? + cloudflare_email: email? + cloudns_auth_id: int? + cloudns_auth_password: str? + cloudns_sub_auth_id: int? + cloudns_sub_auth_user: str? + desec_token: str? + digitalocean_token: str? + directadmin_password: str? + directadmin_url: str? + directadmin_username: str? + dnsimple_token: str? + dnsmadeeasy_api_key: str? + dnsmadeeasy_secret_key: str? + domainoffensive_token: str? + dreamhost_api_key: str? + dreamhost_baseurl: str? + duckdns_token: str? + dynu_auth_token: str? + easydns_endpoint: str? + easydns_key: str? + easydns_token: str? + eurodns_apiKey: str? + eurodns_applicationId: str? + gandi_api_key: str? + gandi_sharing_id: str? + gandi_token: str? + gehirn_api_secret: str? + gehirn_api_token: str? + godaddy_key: str? + godaddy_secret: str? + google_creds: str? + he_pass: str? + he_user: str? + hetzner_api_token: str? + infomaniak_api_token: str? + inwx_password: str? + inwx_shared_secret: str? + inwx_username: str? + ionos_endpoint: str? + ionos_prefix: str? + ionos_secret: str? + joker_domain: str? + joker_password: str? + joker_username: str? + linode_key: str? + linode_version: str? + loopia_password: str? + loopia_user: str? + luadns_email: email? + luadns_token: str? + mijn_host_api_key: str? + namecheap_api_key: str? + namecheap_username: str? + netcup_api_key: str? + netcup_api_password: str? + netcup_customer_id: str? + njalla_token: str? + noris_token: str? + nsone_api_key: str? + ovh_application_key: str? + ovh_application_secret: str? + ovh_consumer_key: str? + ovh_endpoint: str? + plesk_api_url: str? + plesk_password: str? + plesk_username: str? + porkbun_key: str? + porkbun_secret: str? + propagation_seconds: int(60,3600)? + provider: "list(\ + dns-azure|\ + dns-cloudflare|\ + dns-cloudns|\ + dns-desec|\ + dns-digitalocean|\ + dns-directadmin|\ + dns-dnsimple|\ + dns-dnsmadeeasy|\ + dns-domainoffensive|\ + dns-dreamhost|\ + dns-duckdns|\ + dns-dynu|\ + dns-easydns|\ + dns-eurodns|\ + dns-gandi|\ + dns-gehirn|\ + dns-godaddy|\ + dns-google|\ + dns-he|\ + dns-hetzner|\ + dns-infomaniak|\ + dns-inwx|\ + dns-ionos|\ + dns-joker|\ + dns-linode|\ + dns-loopia|\ + dns-luadns|\ + dns-mijn-host|\ + dns-namecheap|\ + dns-netcup|\ + dns-njalla|\ + dns-noris|\ + dns-nsone|\ + dns-ovh|\ + dns-plesk|\ + dns-porkbun|\ + dns-rfc2136|\ + dns-route53|\ + dns-sakuracloud|\ + dns-simply|\ + dns-transip|\ + dns-websupport)?" + rfc2136_algorithm: str? + rfc2136_name: str? + rfc2136_port: str? + rfc2136_secret: str? + rfc2136_server: str? + rfc2136_sign_query: bool? + sakuracloud_api_secret: str? + sakuracloud_api_token: str? + simply_account_name: str? + simply_api_key: str? + transip_api_key: str? + transip_global_key: list(yes|no)? + transip_username: str? + websupport_identifier: str? + websupport_secret_key: str? +startup: once diff --git a/letsencrypt/rootfs/etc/cont-init.d/file-structure.sh b/letsencrypt/rootfs/etc/cont-init.d/file-structure.sh old mode 100644 new mode 100755 index 31b8d9d7e2b..6fd91aeef38 --- a/letsencrypt/rootfs/etc/cont-init.d/file-structure.sh +++ b/letsencrypt/rootfs/etc/cont-init.d/file-structure.sh @@ -1,4 +1,5 @@ #!/usr/bin/with-contenv bashio +# shellcheck shell=bash # ============================================================================== # Init folder & structures # ============================================================================== @@ -6,42 +7,97 @@ mkdir -p /data/workdir mkdir -p /data/letsencrypt # Setup Let's encrypt config -echo -e "dns_cloudxns_api_key = $(bashio::config 'dns.cloudxns_api_key')\n" \ - "dns_cloudxns_secret_key = $(bashio::config 'dns.cloudxns_secret_key')\n" \ +echo -e "aws_access_key_id = $(bashio::config 'dns.aws_access_key_id')\n" \ + "aws_secret_access_key = $(bashio::config 'dns.aws_secret_access_key')\n" \ + "dns_cloudns_auth_password = $(bashio::config 'dns.cloudns_auth_password')\n" \ + "dns_desec_token = $(bashio::config 'dns.desec_token')\n" \ "dns_digitalocean_token = $(bashio::config 'dns.digitalocean_token')\n" \ - "certbot_dns_directadmin:directadmin_url = $(bashio::config 'dns.directadmin_url')\n" \ - "certbot_dns_directadmin:directadmin_username = $(bashio::config 'dns.directadmin_username')\n" \ - "certbot_dns_directadmin:directadmin_password = $(bashio::config 'dns.directadmin_password')\n" \ + "dns_directadmin_password = $(bashio::config 'dns.directadmin_password')\n" \ + "dns_directadmin_url = $(bashio::config 'dns.directadmin_url')\n" \ + "dns_directadmin_username = $(bashio::config 'dns.directadmin_username')\n" \ "dns_dnsimple_token = $(bashio::config 'dns.dnsimple_token')\n" \ "dns_dnsmadeeasy_api_key = $(bashio::config 'dns.dnsmadeeasy_api_key')\n" \ "dns_dnsmadeeasy_secret_key = $(bashio::config 'dns.dnsmadeeasy_secret_key')\n" \ - "dns_gehirn_api_token = $(bashio::config 'dns.gehirn_api_token')\n" \ + "dns_domainoffensive_api_token = $(bashio::config 'dns.domainoffensive_token')\n" \ + "dns_dreamhost_api_key = $(bashio::config 'dns.dreamhost_api_key')\n" \ + "dns_dreamhost_baseurl = $(bashio::config 'dns.dreamhost_baseurl')\n" \ + "dns_duckdns_token = $(bashio::config 'dns.duckdns_token')\n" \ + "dns_dynu_auth_token = $(bashio::config 'dns.dynu_auth_token')\n" \ + "dns_easydns_endpoint = $(bashio::config 'dns.easydns_endpoint')\n" \ + "dns_easydns_userkey = $(bashio::config 'dns.easydns_key')\n" \ + "dns_easydns_usertoken = $(bashio::config 'dns.easydns_token')\n" \ + "dns_eurodns_apiKey = $(bashio::config 'dns.eurodns_apiKey')\n" \ + "dns_eurodns_applicationId = $(bashio::config 'dns.eurodns_applicationId')\n" \ "dns_gehirn_api_secret = $(bashio::config 'dns.gehirn_api_secret')\n" \ + "dns_gehirn_api_token = $(bashio::config 'dns.gehirn_api_token')\n" \ + "dns_godaddy_key = $(bashio::config 'dns.godaddy_key')\n" \ + "dns_godaddy_secret = $(bashio::config 'dns.godaddy_secret')\n" \ + "dns_hetzner_api_token = $(bashio::config 'dns.hetzner_api_token')\n" \ + "dns_hurricane_electric_pass = $(bashio::config 'dns.he_pass')\n" \ + "dns_hurricane_electric_user = $(bashio::config 'dns.he_user')\n" \ + "dns_infomaniak_token = $(bashio::config 'dns.infomaniak_api_token')\n" \ + "dns_inwx_password = $(bashio::config 'dns.inwx_password')\n" \ + "dns_inwx_shared_secret = $(bashio::config 'dns.inwx_shared_secret')\n" \ + "dns_inwx_url = https://api.domrobot.com\n" \ + "dns_inwx_username = $(bashio::config 'dns.inwx_username')\n" \ + "dns_ionos_endpoint = $(bashio::config 'dns.ionos_endpoint')\n" \ + "dns_ionos_prefix = $(bashio::config 'dns.ionos_prefix')\n" \ + "dns_ionos_secret = $(bashio::config 'dns.ionos_secret')\n" \ + "dns_joker_domain = $(bashio::config 'dns.joker_domain')\n" \ + "dns_joker_password = $(bashio::config 'dns.joker_password')\n" \ + "dns_joker_username = $(bashio::config 'dns.joker_username')\n" \ "dns_linode_key = $(bashio::config 'dns.linode_key')\n" \ "dns_linode_version = $(bashio::config 'dns.linode_version')\n" \ + "dns_loopia_password = $(bashio::config 'dns.loopia_password')\n" \ + "dns_loopia_user = $(bashio::config 'dns.loopia_user')\n" \ "dns_luadns_email = $(bashio::config 'dns.luadns_email')\n" \ "dns_luadns_token = $(bashio::config 'dns.luadns_token')\n" \ - "certbot_dns_netcup:dns_netcup_customer_id = $(bashio::config 'dns.netcup_customer_id')\n" \ - "certbot_dns_netcup:dns_netcup_api_key = $(bashio::config 'dns.netcup_api_key')\n" \ - "certbot_dns_netcup:dns_netcup_api_password = $(bashio::config 'dns.netcup_api_password')\n" \ - "certbot_dns_njalla:dns_njalla_token = $(bashio::config 'dns.njalla_token')\n" \ + "dns_mijn_host_api_key = $(bashio::config 'dns.mijn_host_api_key')\n" \ + "dns_namecheap_api_key = $(bashio::config 'dns.namecheap_api_key')\n" \ + "dns_namecheap_username = $(bashio::config 'dns.namecheap_username')\n" \ + "dns_netcup_api_key = $(bashio::config 'dns.netcup_api_key')\n" \ + "dns_netcup_api_password = $(bashio::config 'dns.netcup_api_password')\n" \ + "dns_netcup_customer_id = $(bashio::config 'dns.netcup_customer_id')\n" \ + "dns_njalla_token = $(bashio::config 'dns.njalla_token')\n" \ + "dns_noris_token = $(bashio::config 'dns.noris_token')\n" \ "dns_nsone_api_key = $(bashio::config 'dns.nsone_api_key')\n" \ - "dns_ovh_endpoint = $(bashio::config 'dns.ovh_endpoint')\n" \ "dns_ovh_application_key = $(bashio::config 'dns.ovh_application_key')\n" \ "dns_ovh_application_secret = $(bashio::config 'dns.ovh_application_secret')\n" \ "dns_ovh_consumer_key = $(bashio::config 'dns.ovh_consumer_key')\n" \ - "dns_rfc2136_server = $(bashio::config 'dns.rfc2136_server')\n" \ - "dns_rfc2136_port = $(bashio::config 'dns.rfc2136_port')\n" \ + "dns_ovh_endpoint = $(bashio::config 'dns.ovh_endpoint')\n" \ + "dns_plesk_api_url = $(bashio::config 'dns.plesk_api_url')\n" \ + "dns_plesk_password = $(bashio::config 'dns.plesk_password')\n" \ + "dns_plesk_username = $(bashio::config 'dns.plesk_username')\n" \ + "dns_porkbun_key = $(bashio::config 'dns.porkbun_key')\n" \ + "dns_porkbun_secret = $(bashio::config 'dns.porkbun_secret')\n" \ + "dns_rfc2136_algorithm = $(bashio::config 'dns.rfc2136_algorithm')\n" \ "dns_rfc2136_name = $(bashio::config 'dns.rfc2136_name')\n" \ + "dns_rfc2136_port = $(bashio::config 'dns.rfc2136_port')\n" \ "dns_rfc2136_secret = $(bashio::config 'dns.rfc2136_secret')\n" \ - "dns_rfc2136_algorithm = $(bashio::config 'dns.rfc2136_algorithm')\n" \ - "aws_access_key_id = $(bashio::config 'dns.aws_access_key_id')\n" \ - "aws_secret_access_key = $(bashio::config 'dns.aws_secret_access_key')\n" \ - "dns_sakuracloud_api_token = $(bashio::config 'dns.sakuracloud_api_token')\n" \ + "dns_rfc2136_server = $(bashio::config 'dns.rfc2136_server')\n" \ + "dns_rfc2136_sign_query = $(bashio::config 'dns.rfc2136_sign_query')\n" \ "dns_sakuracloud_api_secret = $(bashio::config 'dns.sakuracloud_api_secret')\n" \ - "certbot_plugin_gandi:dns_api_key = $(bashio::config 'dns.gandi_api_key')\n" \ - "certbot_dns_transip:dns_transip_username = $(bashio::config 'dns.transip_username')\n" \ - "certbot_dns_transip:dns_transip_key_file = /data/transip-rsa.key" > /data/dnsapikey + "dns_sakuracloud_api_token = $(bashio::config 'dns.sakuracloud_api_token')\n" \ + "dns_simply_account_name = $(bashio::config 'dns.simply_account_name')\n" \ + "dns_simply_api_key = $(bashio::config 'dns.simply_api_key')\n" \ + "dns_transip_key_file = /data/transip-rsa.key\n" \ + "dns_transip_username = $(bashio::config 'dns.transip_username')\n" \ + "dns_websupport_identifier = $(bashio::config 'dns.websupport_identifier')\n" \ + "dns_websupport_secret_key = $(bashio::config 'dns.websupport_secret_key')\n" > /data/dnsapikey + +# ClouDNS +# Only a single non-empty auth option must be in /data/dnsapikey when using ClouDNS to avoid a certbot error +if bashio::config.exists 'dns.cloudns_auth_id'; then + echo -e "dns_cloudns_auth_id = $(bashio::config 'dns.cloudns_auth_id')\n" >> /data/dnsapikey +fi + +if bashio::config.exists 'dns.cloudns_sub_auth_id'; then + echo -e "dns_cloudns_sub_auth_id = $(bashio::config 'dns.cloudns_sub_auth_id')\n" >> /data/dnsapikey +fi + +if bashio::config.exists 'dns.cloudns_sub_auth_user'; then + echo -e "dns_cloudns_sub_auth_user = $(bashio::config 'dns.cloudns_sub_auth_user')\n" >> /data/dnsapikey +fi chmod 600 /data/dnsapikey @@ -51,3 +107,25 @@ if bashio::config.exists 'dns.transip_api_key'; then echo "${TRANSIP_API_KEY}" | openssl rsa -out /data/transip-rsa.key chmod 600 /data/transip-rsa.key fi + +# TransIP global_key conditional write out to config +if bashio::config.exists 'dns.transip_global_key'; then + echo -e "dns_transip_global_key = $(bashio::config 'dns.transip_global_key')\n" >> "/data/dnsapikey" +fi + +# Cleanup removed add-on options +if bashio::config.exists 'dns.cloudxns_api_key'; then + bashio::addon.option 'dns.cloudxns_api_key' +fi +if bashio::config.exists 'dns.cloudxns_secret_key'; then + bashio::addon.option 'dns.cloudxns_secret_key' +fi +if bashio::config.exists 'keytype'; then + bashio::addon.option 'keytype' +fi +if bashio::config.exists 'dns.google_domains_access_token'; then + bashio::addon.option 'dns.google_domains_access_token' +fi +if bashio::config.exists 'dns.google_domains_zone'; then + bashio::addon.option 'dns.google_domains_zone' +fi diff --git a/letsencrypt/rootfs/etc/services.d/lets-encrypt/finish b/letsencrypt/rootfs/etc/services.d/lets-encrypt/finish old mode 100644 new mode 100755 index 249d086695c..a5edea72dfa --- a/letsencrypt/rootfs/etc/services.d/lets-encrypt/finish +++ b/letsencrypt/rootfs/etc/services.d/lets-encrypt/finish @@ -1,5 +1,7 @@ -#!/usr/bin/execlineb -S0 +#!/usr/bin/env bashio +# vim: ft=bash # ============================================================================== -# Take down the S6 supervision tree +# Take down the S6 supervision tree when service is done # ============================================================================== -s6-svscanctl -t /var/run/s6/services \ No newline at end of file +/run/s6/basedir/bin/halt + diff --git a/letsencrypt/rootfs/etc/services.d/lets-encrypt/run b/letsencrypt/rootfs/etc/services.d/lets-encrypt/run old mode 100644 new mode 100755 index 5154c808648..7a318425b36 --- a/letsencrypt/rootfs/etc/services.d/lets-encrypt/run +++ b/letsencrypt/rootfs/etc/services.d/lets-encrypt/run @@ -1,4 +1,6 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Start sshd service if enabled # ============================================================================== @@ -6,6 +8,8 @@ CERT_DIR=/data/letsencrypt WORK_DIR=/data/workdir PROVIDER_ARGUMENTS=() ACME_CUSTOM_SERVER_ARGUMENTS=() +KEY_ARGUMENTS=() +EAB_ARGUMENTS=() EMAIL=$(bashio::config 'email') DOMAINS=$(bashio::config 'domains') @@ -15,90 +19,277 @@ CHALLENGE=$(bashio::config 'challenge') DNS_PROVIDER=$(bashio::config 'dns.provider') ACME_SERVER=$(bashio::config 'acme_server') ACME_ROOT_CA=$(bashio::config 'acme_root_ca_cert') +EAB_KID=$(bashio::config 'eab_kid') +EAB_HMAC_KEY=$(bashio::config 'eab_hmac_key') +DRY_RUN=$(bashio::config 'dry_run') +TEST_CERT=$(bashio::config 'test_cert') +VERBOSE=$(bashio::config 'verbose') if [ "${CHALLENGE}" == "dns" ]; then bashio::log.info "Selected DNS Provider: ${DNS_PROVIDER}" PROPAGATION_SECONDS=60 if bashio::config.exists 'dns.propagation_seconds'; then - PROPAGATION_SECONDS="$(bashio::config 'dns.propagation_seconds')" + PROPAGATION_SECONDS="$(bashio::config 'dns.propagation_seconds')" fi bashio::log.info "Use propagation seconds: ${PROPAGATION_SECONDS}" else bashio::log.info "Selected http verification" fi -# AWS -if bashio::config.exists 'dns.aws_access_key_id' && bashio::config.exists 'dns.aws_secret_access_key'; then - AWS_ACCESS_KEY_ID="$(bashio::config 'dns.aws_access_key_id')" - AWS_SECRET_ACCESS_KEY="$(bashio::config 'dns.aws_secret_access_key')" +# Azure +if [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-azure" ]; then + bashio::config.require 'dns.azure_config' + AZURE_CREDS="$(bashio::config 'dns.azure_config')" - export AWS_ACCESS_KEY_ID - export AWS_SECRET_ACCESS_KEY - PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}") -#Google -elif bashio::config.exists 'dns.google_creds'; then - GOOGLE_CREDS="$(bashio::config 'dns.google_creds')" - - export GOOGLE_CREDS - if [ -f "/share/${GOOGLE_CREDS}" ]; then - cp -f "/share/${GOOGLE_CREDS}" "/data/${GOOGLE_CREDS}" - chmod 600 "/data/${GOOGLE_CREDS}" + export AZURE_CREDS + if [ -f "/share/${AZURE_CREDS}" ]; then + cp -f "/share/${AZURE_CREDS}" "/data/azure_creds" + chmod 600 "/data/azure_creds" else - bashio::log.info "Google Credentials File doesnt exists in folder share." + bashio::log.error "Azure credentials file '${AZURE_CREDS}' not found in /share directory" + exit 1 fi - PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/${GOOGLE_CREDS}") - -#Netcup -elif bashio::config.exists 'dns.netcup_customer_id' && bashio::config.exists 'dns.netcup_api_key' && bashio::config.exists 'dns.netcup_api_password'; then - PROVIDER_ARGUMENTS+=("--authenticator" "certbot-dns-netcup:dns-netcup" "--certbot-dns-netcup:dns-netcup-credentials" /data/dnsapikey "--certbot-dns-netcup:dns-netcup-propagation-seconds" "${PROPAGATION_SECONDS}") - -#TransIP -elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-transip" ]; then - bashio::config.require.username 'dns.transip_username' - bashio::config.require 'dns.transip_api_key' - if (( PROPAGATION_SECONDS < 240 )); then - bashio::log.info "Increasing DNS propagation limit for TransIP to at least 240 seconds." - PROPAGATION_SECONDS=240 - fi - PROVIDER_ARGUMENTS+=("--authenticator" "certbot-${DNS_PROVIDER}:${DNS_PROVIDER}" "--certbot-${DNS_PROVIDER}:${DNS_PROVIDER}-credentials" /data/dnsapikey "--certbot-${DNS_PROVIDER}:${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-config" "/data/azure_creds") # CloudFlare elif [ "${DNS_PROVIDER}" == "dns-cloudflare" ]; then if bashio::config.exists 'dns.cloudflare_api_token'; then bashio::log.info "Use CloudFlare token" - echo "dns_cloudflare_api_token = $(bashio::config 'dns.cloudflare_api_token')" >> /data/dnsapikey + echo "dns_cloudflare_api_token = $(bashio::config 'dns.cloudflare_api_token')" >> "/data/dnsapikey" else bashio::log.warning "Use CloudFlare global key (not recommended!)" echo -e "dns_cloudflare_email = $(bashio::config 'dns.cloudflare_email')\n" \ - "dns_cloudflare_api_key = $(bashio::config 'dns.cloudflare_api_key')\n" >> /data/dnsapikey + "dns_cloudflare_api_key = $(bashio::config 'dns.cloudflare_api_key')\n" >> "/data/dnsapikey" fi - PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" /data/dnsapikey "--dns-cloudflare-propagation-seconds" "${PROPAGATION_SECONDS}") + PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# ClouDNS +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-cloudns" ]; then + bashio::config.require 'dns.cloudns_auth_password' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# desec +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-desec" ]; then + bashio::config.require 'dns.desec_token' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# DigitalOcean +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-digitalocean" ]; then + bashio::config.require 'dns.digitalocean_token' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") # DirectAdmin elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-directadmin" ]; then bashio::config.require 'dns.directadmin_url' bashio::config.require 'dns.directadmin_username' bashio::config.require 'dns.directadmin_password' - PROVIDER_ARGUMENTS+=("--authenticator" "certbot-dns-directadmin:directadmin" "--certbot-dns-directadmin:directadmin-credentials" /data/dnsapikey "--certbot-dns-directadmin:directadmin-propagation-seconds" "${PROPAGATION_SECONDS}") + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# domainoffensive +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-domainoffensive" ]; then + bashio::config.require 'dns.domainoffensive_token' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey") + +# Dreamhost +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-dreamhost" ]; then + bashio::config.require 'dns.dreamhost_baseurl' + bashio::config.require 'dns.dreamhost_api_key' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey") + +# DuckDNS +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-duckdns" ]; then + bashio::config.require 'dns.duckdns_token' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# Dynu +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-dynu" ]; then + bashio::config.require 'dns.dynu_auth_token' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# easyDNS +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-easydns" ]; then + bashio::config.require 'dns.easydns_key' + bashio::config.require 'dns.easydns_token' + bashio::config.require 'dns.easydns_endpoint' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# Eurodns +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-eurodns" ]; then + bashio::config.require 'dns.eurodns_applicationId' + bashio::config.require 'dns.eurodns_apiKey' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") # Gandi elif [ "${DNS_PROVIDER}" == "dns-gandi" ]; then if bashio::config.exists 'dns.gandi_sharing_id'; then bashio::log.info "Use Gandi sharing ID" - echo "certbot_plugin_gandi:dns_sharing_id = $(bashio::config 'dns.gandi_sharing_id')" >> /data/dnsapikey + echo "dns_gandi_sharing_id = $(bashio::config 'dns.gandi_sharing_id')" >> "/data/dnsapikey" + fi + if bashio::config.exists 'dns.gandi_token'; then + bashio::log.info "Use Gandi gandi_token" + echo "dns_gandi_token = $(bashio::config 'dns.gandi_token')" >> "/data/dnsapikey" + fi + if bashio::config.exists 'dns.gandi_api_key'; then + bashio::log.info "Use Gandi gandi_api_key" + echo "dns_gandi_api_key = $(bashio::config 'dns.gandi_api_key')" >> "/data/dnsapikey" fi - PROVIDER_ARGUMENTS+=("--authenticator" "certbot-plugin-gandi:dns" "--certbot-plugin-gandi:dns-credentials" /data/dnsapikey) + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}" ) + +# GoDaddy +elif [ "${DNS_PROVIDER}" == "dns-godaddy" ]; then + bashio::config.require 'dns.godaddy_secret' + bashio::config.require 'dns.godaddy_key' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# Google +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-google" ]; then + bashio::config.require 'dns.google_creds' + GOOGLE_CREDS="$(bashio::config 'dns.google_creds')" + + export GOOGLE_CREDS + if [ -f "/share/${GOOGLE_CREDS}" ]; then + cp -f "/share/${GOOGLE_CREDS}" "/data/${GOOGLE_CREDS}" + chmod 600 "/data/${GOOGLE_CREDS}" + else + bashio::log.error "Google credentials file '${GOOGLE_CREDS}' not found in /share directory" + exit 1 + fi + PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/${GOOGLE_CREDS}") + +# Hurricane Electric +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-he" ]; then + bashio::config.require 'dns.he_user' + bashio::config.require 'dns.he_pass' + PROVIDER_ARGUMENTS+=("--authenticator" "dns-hurricane_electric" "--dns-hurricane_electric-credentials" "/data/dnsapikey" "--dns-hurricane_electric-propagation-seconds" "${PROPAGATION_SECONDS}") + +# Hetzner +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-hetzner" ]; then + bashio::config.require 'dns.hetzner_api_token' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# Infomaniak +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-infomaniak" ]; then + bashio::config.require 'dns.infomaniak_api_token' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# INWX +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-inwx" ]; then + bashio::config.require 'dns.inwx_username' + bashio::config.require 'dns.inwx_password' + bashio::config.require 'dns.inwx_shared_secret' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# IONOS +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-ionos" ]; then + bashio::config.require 'dns.ionos_prefix' + bashio::config.require 'dns.ionos_secret' + bashio::config.require 'dns.ionos_endpoint' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# Joker +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-joker" ]; then + bashio::config.require 'dns.joker_username' + bashio::config.require 'dns.joker_password' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# Loopia +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-loopia" ]; then + bashio::config.require 'dns.loopia_user' + bashio::config.require 'dns.loopia_password' + if (( PROPAGATION_SECONDS < 900 )); then + bashio::log.info "Increasing DNS propagation limit for Loopia to at least 900 seconds due to caching issues." + PROPAGATION_SECONDS=900 + fi + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# mijn.host +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-mijn-host" ]; then + bashio::config.require 'dns.mijn_host_api_key' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# Namecheap +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-namecheap" ]; then + bashio::config.require 'dns.namecheap_username' + bashio::config.require 'dns.namecheap_api_key' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# Netcup +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-netcup" ]; then + bashio::config.require 'dns.netcup_customer_id' + bashio::config.require 'dns.netcup_api_key' + bashio::config.require 'dns.netcup_api_password' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") # Njalla elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-njalla" ]; then bashio::config.require 'dns.njalla_token' - PROVIDER_ARGUMENTS+=("--authenticator" "certbot-dns-njalla:dns-njalla" "--certbot-dns-njalla:dns-njalla-credentials" /data/dnsapikey "--certbot-dns-njalla:dns-njalla-propagation-seconds" "${PROPAGATION_SECONDS}") + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# noris network +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-noris" ]; then + bashio::config.require 'dns.noris_token' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# Plesk +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-plesk" ]; then + bashio::config.require 'dns.plesk_username' + bashio::config.require 'dns.plesk_password' + bashio::config.require 'dns.plesk_api_url' + if (( PROPAGATION_SECONDS < 120 )); then + bashio::log.info "Increasing DNS propagation limit for Plesk to at least 120 seconds." + PROPAGATION_SECONDS=120 + fi + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +#Porkbun +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-porkbun" ]; then + bashio::config.require 'dns.porkbun_key' + bashio::config.require 'dns.porkbun_secret' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# rfc2136 +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-rfc2136" ]; then + PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# route53 - AWS +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-route53" ]; then + bashio::config.require 'dns.aws_access_key_id' + bashio::config.require 'dns.aws_secret_access_key' + + AWS_ACCESS_KEY_ID="$(bashio::config 'dns.aws_access_key_id')" + AWS_SECRET_ACCESS_KEY="$(bashio::config 'dns.aws_secret_access_key')" + + export AWS_ACCESS_KEY_ID + export AWS_SECRET_ACCESS_KEY + PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}") + +# Simply +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-simply" ]; then + bashio::config.require 'dns.simply_account_name' + bashio::config.require 'dns.simply_api_key' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# TransIP +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-transip" ]; then + bashio::config.require 'dns.transip_username' + bashio::config.require 'dns.transip_api_key' + if (( PROPAGATION_SECONDS < 240 )); then + bashio::log.info "Increasing DNS propagation time for TransIP to at least 240 seconds." + PROPAGATION_SECONDS=240 + fi + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") + +# WebSupport +elif [ "${CHALLENGE}" == "dns" ] && [ "${DNS_PROVIDER}" == "dns-websupport" ]; then + bashio::config.require 'dns.websupport_identifier' + bashio::config.require 'dns.websupport_secret_key' + PROVIDER_ARGUMENTS+=("--authenticator" "${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey" "--${DNS_PROVIDER}-propagation-seconds" "${PROPAGATION_SECONDS}") #All others else - PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" /data/dnsapikey) + PROVIDER_ARGUMENTS+=("--${DNS_PROVIDER}" "--${DNS_PROVIDER}-credentials" "/data/dnsapikey") fi if bashio::config.has_value 'acme_server' ; then @@ -118,17 +309,81 @@ for line in $DOMAINS; do done echo "$DOMAINS" > /data/domains.gen +# Key detection or manual ECDSA/RSA selection +if bashio::config.exists 'key_type'; then + # Use key type set in configuration + KEY_TYPE=$(bashio::config 'key_type') + KEY_ARGUMENTS+=("--key-type" "${KEY_TYPE}") + if [ "${KEY_TYPE}" == "ecdsa" ]; then + if bashio::config.exists 'elliptic_curve'; then + ELLIPTIC_CURVE=$(bashio::config 'elliptic_curve') + KEY_ARGUMENTS+=("--elliptic-curve" "${ELLIPTIC_CURVE}") + else + KEY_ARGUMENTS+=("--elliptic-curve" "secp384r1") + fi + fi +else + bashio::log.info "Detecting existing certificate type for ${DOMAIN_ARR[1]}" + readarray -t CBCERTS < <(certbot certificates --non-interactive --cert-name "${DOMAIN_ARR[1]}" --config-dir "$CERT_DIR" --work-dir "$WORK_DIR") + for output in "${CBCERTS[@]}"; do + # shellcheck disable=SC2076 + if [[ $output =~ "No certificates found." ]]; then + bashio::log.info "No certificate found - using 'ecdsa' key type." + KEY_ARGUMENTS+=("--key-type" "ecdsa") + break + fi + if [[ $output =~ "Key Type: RSA" ]]; then + bashio::log.info "Existing certificate using 'rsa' key type." + KEY_ARGUMENTS+=("--key-type" "rsa") + break + fi + if [[ $output =~ "Key Type: ECDSA" ]]; then + bashio::log.info "Existing certificate using 'ecdsa' key type." + KEY_ARGUMENTS+=("--key-type" "ecdsa") + break + fi + done +fi + +# Set External Account Binding +if bashio::config.has_value 'eab_kid' ; then + bashio::config.require 'eab_hmac_key' + EAB_ARGUMENTS+=("--eab-kid" "${EAB_KID}" "--eab-hmac-key" "${EAB_HMAC_KEY}") +fi + +# Define additional arguments based on configuration +ADDITIONAL_ARGS=() +if [ "${DRY_RUN}" = "true" ]; then + ADDITIONAL_ARGS+=("--dry-run") +fi +if [ "${TEST_CERT}" = "true" ]; then + ADDITIONAL_ARGS+=("--test-cert") +fi +if [ "${VERBOSE}" = "true" ]; then + ADDITIONAL_ARGS+=("-vvv") +fi + # Generate a new certificate if necessary or expand a previous certificate if domains has changed if [ "$CHALLENGE" == "dns" ]; then certbot certonly --non-interactive --keep-until-expiring --expand \ --email "$EMAIL" --agree-tos \ + "${KEY_ARGUMENTS[@]}" \ + "${ADDITIONAL_ARGS[@]}" \ + --cert-name "${DOMAIN_ARR[1]}" "${DOMAIN_ARR[@]}" \ --config-dir "$CERT_DIR" --work-dir "$WORK_DIR" \ - --preferred-challenges "$CHALLENGE" "${DOMAIN_ARR[@]}" "${PROVIDER_ARGUMENTS[@]}" + --preferred-challenges "$CHALLENGE" "${PROVIDER_ARGUMENTS[@]}" \ + --preferred-chain "ISRG Root X1" \ + "${EAB_ARGUMENTS[@]}" else certbot certonly --non-interactive --keep-until-expiring --expand \ --email "$EMAIL" --agree-tos \ + "${KEY_ARGUMENTS[@]}" \ + "${ADDITIONAL_ARGS[@]}" \ + --cert-name "${DOMAIN_ARR[1]}" "${DOMAIN_ARR[@]}" \ --config-dir "$CERT_DIR" --work-dir "$WORK_DIR" \ - --preferred-challenges "$CHALLENGE" "${DOMAIN_ARR[@]}" "${ACME_CUSTOM_SERVER_ARGUMENTS[@]}" --standalone + --preferred-challenges "$CHALLENGE" "${ACME_CUSTOM_SERVER_ARGUMENTS[@]}" --standalone \ + --preferred-chain "ISRG Root X1" \ + "${EAB_ARGUMENTS[@]}" fi # Get the last modified cert directory and copy the cert and private key to store diff --git a/letsencrypt/translations/en.yaml b/letsencrypt/translations/en.yaml new file mode 100644 index 00000000000..c4b26813ea3 --- /dev/null +++ b/letsencrypt/translations/en.yaml @@ -0,0 +1,58 @@ +--- +configuration: + domains: + name: Domains + description: >- + The domain names to issue certificates for, use "*.yourdomain.com" for + wildcard certificates. + email: + name: Email + description: The email address that will be registered for the certificate. + keyfile: + name: Private Key File + description: Path to where the Private Key File will be placed. + certfile: + name: Certificate File + description: Path to where the Certificate File will be placed. + challenge: + name: Challenge + description: The type of challenge used to validate the domain. + acme_root_ca_cert: + name: ACME Root CA Certificate + description: >- + If your custom ACME server uses a certificate signed by an untrusted + certificate authority (CA), you can add the root certificate to the trust + store by setting its content. + acme_server: + name: ACME Server + description: >- + By default, The addon uses Let's Encrypt's default server at + https://acme-v02.api.letsencrypt.org/. You can instruct the addon to use a + different ACME server. + dns: + name: DNS + description: DNS Provider configuration + key_type: + name: Key Type + description: >- + Select the certificate key type. If unset, will auto-detect based on + the key type of the existing certificate or default to ecdsa. + elliptic_curve: + name: Elliptic Curve + description: >- + Elliptic curve for ECDSA keys. This option must be used with Key Type + set to ECDSA. If unset the Certbot default will be used. + dry_run: + name: Dry Run + description: >- + Do a certbot dry-run for requesting the certificates. + test_cert: + name: Issue test certificates + description: >- + Obtain a test certificate from a staging server. + verbose: + name: Verbose Mode + description: >- + Run certbot in verbose mode. +network: + 80/tcp: Only needed for http challenge diff --git a/mariadb/CHANGELOG.md b/mariadb/CHANGELOG.md index bcf71463c6e..803fa242323 100644 --- a/mariadb/CHANGELOG.md +++ b/mariadb/CHANGELOG.md @@ -1,5 +1,42 @@ # Changelog +## 2.7.2 + +- Add option to configure MariaDB server parameters (see also [home-assistant/addons#3754](https://github.com/home-assistant/addons/issues/3754)) + +## 2.7.1 + +**Note:** Restart the add-on before upgrade if the current version is lower +than 2.7.0! This is to ensure a clean stop right before the update (see also +https://github.com/home-assistant/addons/issues/3566). + +- Increase MariaDB add-on shutdown timeout to 300s + +## 2.7.0 + +- Update to Alpine 3.19 + +## 2.6.1 + +- Use proper log redirection during backup + +## 2.6.0 + +- Migrate add-on layout to S6 Overlay +- Update to MariaDB version 10.6.12 + +## 2.5.2 + +- Update to MariaDB version 10.6.10 + +## 2.5.1 + +- Remove deprecated `innodb-buffer-pool-instances` + +## 2.5.0 + +- Update alpine to 3.16 and s6 to v3 + ## 2.4.0 - Add lock capabilities during snapshot @@ -13,6 +50,7 @@ - Update options schema for passwords ## 2.2.1 + - Don't delete the mariadb.sys user, it's needed in MariaDB >= 10.4.13 ## 2.2.0 diff --git a/mariadb/DOCS.md b/mariadb/DOCS.md index f44d26faf66..f2b49c7176c 100644 --- a/mariadb/DOCS.md +++ b/mariadb/DOCS.md @@ -4,7 +4,7 @@ Follow these steps to get the add-on installed on your system: -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. 2. Find the "MariaDB" add-on and click it. 3. Click on the "INSTALL" button. @@ -13,7 +13,7 @@ Follow these steps to get the add-on installed on your system: 1. Set the `logins` -> `password` field to something strong and unique. 2. Start the add-on. 3. Check the add-on log output to see the result. -4. Add `recorder` component to your Home Assistant configuration. +4. Add the `recorder` integration to your Home Assistant configuration. ## Add-on Configuration @@ -74,6 +74,13 @@ If omitted, grants `ALL PRIVILEGES` to the user. Restricting privileges of the u that Home Assistant uses is not recommended but if you want to allow other applications to view recorder data should create a user limited to read-only access on the database. +### Option: `mariadb_server_args` (optional) + +Some users have experienced [errors][migration-issues] during Home Assistant schema updates on large databases. +Defining the recommended parameters can help if there is RAM available. + +Example: `--innodb_buffer_pool_size=512M` + ## Home Assistant Configuration MariaDB will be used by the `recorder` and `history` components within Home Assistant. For more information about setting this up, see the [recorder integration][mariadb-ha-recorder] documentation for Home Assistant. @@ -97,14 +104,15 @@ You have several options to get them answered: In case you've found a bug, please [open an issue on our GitHub][issue]. -[createuser]: https://mariadb.com/kb/en/library/create-user -[username]: https://mariadb.com/kb/en/library/create-user/#user-name-component -[hostname]: https://mariadb.com/kb/en/library/create-user/#host-name-component -[grant]: https://mariadb.com/kb/en/library/grant +[createuser]: https://mariadb.com/kb/en/create-user/ +[username]: https://mariadb.com/kb/en/create-user/#user-name-component +[hostname]: https://mariadb.com/kb/en/create-user/#host-name-component +[grant]: https://mariadb.com/kb/en/grant/ +[migration-issues]: https://github.com/home-assistant/core/issues/125339 [mariadb-ha-recorder]: https://www.home-assistant.io/integrations/recorder/ [discord]: https://discord.gg/c5DvZ4e [forum]: https://community.home-assistant.io [i386-shield]: https://img.shields.io/badge/i386-yes-green.svg -[issue]: https://github.com/home-assistant/hassio-addons/issues +[issue]: https://github.com/home-assistant/addons/issues [reddit]: https://reddit.com/r/homeassistant [repository]: https://github.com/hassio-addons/repository diff --git a/mariadb/Dockerfile b/mariadb/Dockerfile index ceb644ed459..bf255ff1778 100644 --- a/mariadb/Dockerfile +++ b/mariadb/Dockerfile @@ -9,8 +9,7 @@ RUN apk add --no-cache \ pwgen ENV \ - LD_PRELOAD="/usr/local/lib/libjemalloc.so.2" \ - S6_SERVICES_GRACETIME=18000 + LD_PRELOAD="/usr/local/lib/libjemalloc.so.2" # Copy data COPY rootfs / diff --git a/mariadb/build.json b/mariadb/build.json deleted file mode 100644 index 8b1f9c0b01a..00000000000 --- a/mariadb/build.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "build_from": { - "aarch64": "homeassistant/aarch64-base:3.12", - "amd64": "homeassistant/amd64-base:3.12", - "armhf": "homeassistant/armhf-base:3.12", - "armv7": "homeassistant/armv7-base:3.12", - "i386": "homeassistant/i386-base:3.12" - } -} diff --git a/mariadb/build.yaml b/mariadb/build.yaml new file mode 100644 index 00000000000..039821f92e6 --- /dev/null +++ b/mariadb/build.yaml @@ -0,0 +1,10 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base:3.19 + amd64: ghcr.io/home-assistant/amd64-base:3.19 + armhf: ghcr.io/home-assistant/armhf-base:3.19 + armv7: ghcr.io/home-assistant/armv7-base:3.19 + i386: ghcr.io/home-assistant/i386-base:3.19 +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io diff --git a/mariadb/config.json b/mariadb/config.json deleted file mode 100644 index 5c55576479c..00000000000 --- a/mariadb/config.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "MariaDB", - "version": "2.4.0", - "slug": "mariadb", - "description": "A SQL database server", - "url": "https://github.com/home-assistant/hassio-addons/tree/master/mariadb", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "startup": "system", - "init": false, - "timeout": 20, - "snapshot_pre": "/bin/s6-svc -wU -u /run/s6/services/mariadb-lock/", - "snapshot_post": "/bin/s6-svc -wd -d /run/s6/services/mariadb-lock/", - "services": ["mysql:provide"], - "ports": { - "3306/tcp": null - }, - "options": { - "databases": ["homeassistant"], - "logins": [{ "username": "homeassistant", "password": null }], - "rights": [ - { - "username": "homeassistant", - "database": "homeassistant" - } - ] - }, - "schema": { - "databases": ["str"], - "logins": [{ "username": "str", "password": "password" }], - "rights": [ - { - "username": "str", - "database": "str", - "privileges": [ - "list(ALTER|CREATE|CREATE ROUTINE|CREATE TEMPORARY TABLES|CREATE VIEW|DELETE|DELETE HISTORY|DROP|EVENT|GRANT OPTION|INDEX|INSERT|LOCK TABLES|SELECT|SHOW VIEW|TRIGGER|UPDATE)?" - ] - } - ] - }, - "image": "homeassistant/{arch}-addon-mariadb" -} diff --git a/mariadb/config.yaml b/mariadb/config.yaml new file mode 100644 index 00000000000..828018ecd71 --- /dev/null +++ b/mariadb/config.yaml @@ -0,0 +1,46 @@ +--- +version: 2.7.2 +slug: mariadb +name: MariaDB +description: A SQL database server +url: https://github.com/home-assistant/addons/tree/master/mariadb +arch: + - armhf + - armv7 + - aarch64 + - amd64 + - i386 +backup_post: unlock-tables-for-backup +backup_pre: lock-tables-for-backup +image: homeassistant/{arch}-addon-mariadb +init: false +options: + databases: + - homeassistant + logins: + - password: null + username: homeassistant + rights: + - database: homeassistant + username: homeassistant +ports: + 3306/tcp: null +schema: + databases: + - str + logins: + - username: str + password: password + rights: + - database: str + privileges: + - "list(ALTER|CREATE|CREATE ROUTINE|CREATE TEMPORARY TABLES|\ + CREATE VIEW|DELETE|DELETE HISTORY|DROP|EVENT|GRANT OPTION|INDEX|\ + INSERT|LOCK TABLES|SELECT|SHOW VIEW|TRIGGER|UPDATE)?" + username: str + mariadb_server_args: + - str? +services: + - mysql:provide +startup: system +timeout: 300 diff --git a/mariadb/logo.png b/mariadb/logo.png index 63a48ec1087..8b337cc7075 100644 Binary files a/mariadb/logo.png and b/mariadb/logo.png differ diff --git a/mariadb/rootfs/etc/my.cnf.d/mariadb-server.cnf b/mariadb/rootfs/etc/my.cnf.d/mariadb-server.cnf index ff604aa2979..43225475306 100644 --- a/mariadb/rootfs/etc/my.cnf.d/mariadb-server.cnf +++ b/mariadb/rootfs/etc/my.cnf.d/mariadb-server.cnf @@ -33,7 +33,6 @@ query_cache_size = 0M query_cache_type = 0 # InnoDB Tweaks -innodb_buffer_pool_instances = 1 innodb_buffer_pool_size = 128M innodb_log_buffer_size = 8M innodb_log_file_size = 48M diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/dependencies.d/mariadb-pre b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/dependencies.d/mariadb-pre new file mode 100644 index 00000000000..e69de29bb2d diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/finish b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/finish new file mode 100755 index 00000000000..5b47ebd627e --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/finish @@ -0,0 +1,27 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Take down the S6 supervision tree when daemon fails +# ============================================================================== +# shellcheck disable=SC2155 +readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode + fi + [[ "${exit_code_signal}" -eq 15 ]] && exec /run/s6/basedir/bin/halt +elif [[ "${exit_code_service}" -ne 0 ]]; then + if [[ "${exit_code_container}" -eq 0 ]]; then + echo "${exit_code_service}" > /run/s6-linux-init-container-results/exitcode + fi + exec /run/s6/basedir/bin/halt +fi diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/run b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/run new file mode 100755 index 00000000000..be4a0d6c2ee --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/run @@ -0,0 +1,22 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start MariaDB service +# ============================================================================== + +if bashio::config.has_value "mariadb_server_args"; then + readarray -t extra_args <<< "$(bashio::config 'mariadb_server_args')" + bashio::log.info "Starting MariaDB with command line parameters: ${extra_args[*]}" +else + bashio::log.info "Starting MariaDB" +fi + +# Start mariadb +mkdir -p /run/mysqld + +if [ -z "${extra_args+x}" ] || [ ${#extra_args[@]} -eq 0 ]; then + exec mysqld --datadir="${MARIADB_DATA}" --user=root < /dev/null +else + exec mysqld --datadir="${MARIADB_DATA}" --user=root "${extra_args[@]}" < /dev/null +fi diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/timeout-kill b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/timeout-kill new file mode 100644 index 00000000000..94ca7aa4c37 --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/timeout-kill @@ -0,0 +1 @@ +295000 diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/type b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-core/type @@ -0,0 +1 @@ +longrun diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/dependencies.d/mariadb b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/dependencies.d/mariadb new file mode 100644 index 00000000000..e69de29bb2d diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/finish b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/finish new file mode 100755 index 00000000000..1bd7048c0a8 --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/finish @@ -0,0 +1,8 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# MariaDB client (to lock tables for backups) stopped +# ============================================================================== + +bashio::log.info "MariaDB client (to lock tables for backups) stopped" diff --git a/mariadb/rootfs/etc/services.d/mariadb-lock/notification-fd b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/notification-fd similarity index 100% rename from mariadb/rootfs/etc/services.d/mariadb-lock/notification-fd rename to mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/notification-fd diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/run b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/run new file mode 100755 index 00000000000..29e8cc3ff62 --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/run @@ -0,0 +1,15 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start MariaDB client (to lock tables for backups) +# ============================================================================== + +bashio::log.info "Start MariaDB client (to lock tables for backups)" + +# File descriptor &4 is used as stdin for mysql, because &0 is closed after the mariadb-lock-core service is started +exec 4> >(mysql) + +# We need to delay the starting of the dependent services until mysql is started +echo "" >&3 +wait diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/type b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-core/type @@ -0,0 +1 @@ +longrun diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/dependencies.d/mariadb-lock-core b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/dependencies.d/mariadb-lock-core new file mode 100644 index 00000000000..e69de29bb2d diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/down b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/down new file mode 100644 index 00000000000..cc429603ea7 --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/down @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/mariadb-lock-post/finish diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/finish b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/finish new file mode 100755 index 00000000000..5761b87dbec --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/finish @@ -0,0 +1,20 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Unlock tables locked for backups +# ============================================================================== + +declare MARIADB_LOCK_CORE_PID +MARIADB_LOCK_CORE_PID=$(s6-svstat -o pid "/run/service/mariadb-lock-core") +# shellcheck disable=SC2086 +if bashio::var.equals ${MARIADB_LOCK_CORE_PID} -1; then + bashio::log.error "Invalid mariadb-lock-core process id ${MARIADB_LOCK_CORE_PID}" + bashio::exit.nok +fi + +# File descriptor &4 is used as stdin for mysql, because &0 is closed after the mariadb-lock-core service is started +# shellcheck disable=SC2086 +echo "UNLOCK TABLES;" > /proc/${MARIADB_LOCK_CORE_PID}/fd/4 + +bashio::log.info "MariaDB tables unlocked" diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/run b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/run new file mode 100755 index 00000000000..44ecf545321 --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/run @@ -0,0 +1,20 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Lock tables for backups +# ============================================================================== + +declare MARIADB_LOCK_CORE_PID +MARIADB_LOCK_CORE_PID=$(s6-svstat -o pid "/run/service/mariadb-lock-core") +# shellcheck disable=SC2086 +if bashio::var.equals ${MARIADB_LOCK_CORE_PID} -1; then + bashio::log.error "Invalid mariadb-lock-core process id ${MARIADB_LOCK_CORE_PID}" + bashio::exit.nok +fi + +# File descriptor &4 is used as stdin for mysql, because &0 is closed after the mariadb-lock-core service is started +# shellcheck disable=SC2086 +echo "FLUSH TABLES WITH READ LOCK;" > /proc/${MARIADB_LOCK_CORE_PID}/fd/4 + +bashio::log.info "MariaDB tables locked" diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/type b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/type new file mode 100644 index 00000000000..bdd22a1850a --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/type @@ -0,0 +1 @@ +oneshot diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/up b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/up new file mode 100644 index 00000000000..3a9f5f1b878 --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock-post/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/mariadb-lock-post/run diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock/contents.d/mariadb-lock-core b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock/contents.d/mariadb-lock-core new file mode 100644 index 00000000000..e69de29bb2d diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock/contents.d/mariadb-lock-post b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock/contents.d/mariadb-lock-post new file mode 100644 index 00000000000..e69de29bb2d diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock/type b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock/type new file mode 100644 index 00000000000..757b4221150 --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-lock/type @@ -0,0 +1 @@ +bundle diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/dependencies.d/mariadb-core b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/dependencies.d/mariadb-core new file mode 100644 index 00000000000..e69de29bb2d diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/down b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/down new file mode 100644 index 00000000000..32c87d2a4b3 --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/down @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/mariadb-post/finish diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/finish b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/finish new file mode 100755 index 00000000000..59c6b743f57 --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/finish @@ -0,0 +1,9 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Post-start finalization of MariaDB service +# ============================================================================== + +bashio::log.info "Deleting service information from Home Assistant" +bashio::services.delete "mysql" || true diff --git a/mariadb/rootfs/etc/services.d/mariadb/run b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/run old mode 100644 new mode 100755 similarity index 77% rename from mariadb/rootfs/etc/services.d/mariadb/run rename to mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/run index 91b99f43a33..231072576f4 --- a/mariadb/rootfs/etc/services.d/mariadb/run +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/run @@ -1,32 +1,29 @@ -#!/usr/bin/with-contenv bashio +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== -# Start MariaDB service if enabled +# Post-start initialization of MariaDB service # ============================================================================== -MARIADB_DATA=/data/databases -NEW_INSTALL=false -# Init mariadb -if ! bashio::fs.directory_exists "${MARIADB_DATA}"; then - bashio::log.info "Create a new mariadb initial system" - mysql_install_db --user=root --datadir="${MARIADB_DATA}" --skip-name-resolve --skip-test-db > /dev/null - NEW_INSTALL=true -else - bashio::log.info "Using existing mariadb initial system" -fi - -# Redirect log output -rm -f "${MARIADB_DATA}/mariadb.err" -ln -s /proc/1/fd/1 "${MARIADB_DATA}/mariadb.err" - -# Start mariadb -bashio::log.info "Starting MariaDB" -mysqld_safe --datadir="${MARIADB_DATA}" --user=root < /dev/null & -MARIADB_PID=$! +function execute_without_error_messages() { + local current_log_level="${__BASHIO_LOG_LEVELS[${__BASHIO_LOG_LEVEL}]}" + bashio::log.level fatal + local exit_code=0 + # shellcheck disable=SC2068 + $@ || exit_code=$? + # shellcheck disable=SC2086 + bashio::log.level ${current_log_level} + return ${exit_code} +} # Wait until DB is running while ! mysql -e "" 2> /dev/null; do sleep 1 done +bashio::log.info "MariaDB started" + +# Delete service information, just in case the previous instance somehow did not cleanup +execute_without_error_messages bashio::services.delete "mysql" || true bashio::log.info "Check data integrity and fix corruptions" mysqlcheck --no-defaults --databases mysql --fix-db-names --fix-table-names || true @@ -116,19 +113,5 @@ PAYLOAD=$(\ username "service" \ password "${SECRET}" ) -if bashio::services.publish "mysql" "${PAYLOAD}"; then - bashio::log.info "Successfully send service information to Home Assistant." -else - bashio::log.warning "Service message to Home Assistant failed!" -fi - -# Register stop -function stop_mariadb() { - bashio::services.delete "mysql" - mysqladmin shutdown - # Successful exit, avoid wait exit status to propagate - exit 0 -} -trap "stop_mariadb" SIGTERM SIGHUP - -wait "${MARIADB_PID}" +bashio::log.info "Sending service information to Home Assistant" +bashio::services.publish "mysql" "${PAYLOAD}" diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/type b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/type new file mode 100644 index 00000000000..bdd22a1850a --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/type @@ -0,0 +1 @@ +oneshot diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/up b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/up new file mode 100644 index 00000000000..9cac052a7f2 --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-post/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/mariadb-post/run diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-pre/dependencies.d/base b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-pre/dependencies.d/base new file mode 100644 index 00000000000..e69de29bb2d diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-pre/run b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-pre/run new file mode 100755 index 00000000000..5024041a543 --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-pre/run @@ -0,0 +1,29 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Pre-start initialization of MariaDB service +# ============================================================================== +MARIADB_DATA=/data/databases +NEW_INSTALL=false + +if ! bashio::fs.directory_exists "${MARIADB_DATA}"; then + NEW_INSTALL=true +fi + +# Save variables +echo -n "${MARIADB_DATA}" > /var/run/s6/container_environment/MARIADB_DATA +echo -n "${NEW_INSTALL}" > /var/run/s6/container_environment/NEW_INSTALL + +# Redirect log output +mkdir -p "${MARIADB_DATA}" +rm -f "${MARIADB_DATA}/mariadb.err" +ln -s /proc/1/fd/1 "${MARIADB_DATA}/mariadb.err" + +# Init mariadb +if bashio::var.true "${NEW_INSTALL}"; then + bashio::log.info "Create a new mariadb" + mysql_install_db --user=root --datadir="${MARIADB_DATA}" --skip-name-resolve --skip-test-db > /dev/null +else + bashio::log.info "Using existing mariadb" +fi diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-pre/type b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-pre/type new file mode 100644 index 00000000000..bdd22a1850a --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-pre/type @@ -0,0 +1 @@ +oneshot diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-pre/up b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-pre/up new file mode 100644 index 00000000000..06f3a3c4164 --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb-pre/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/mariadb-pre/run diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb/contents.d/mariadb-core b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb/contents.d/mariadb-core new file mode 100644 index 00000000000..e69de29bb2d diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb/contents.d/mariadb-post b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb/contents.d/mariadb-post new file mode 100644 index 00000000000..e69de29bb2d diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb/contents.d/mariadb-pre b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb/contents.d/mariadb-pre new file mode 100644 index 00000000000..e69de29bb2d diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb/type b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb/type new file mode 100644 index 00000000000..757b4221150 --- /dev/null +++ b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/mariadb/type @@ -0,0 +1 @@ +bundle diff --git a/mariadb/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/mariadb b/mariadb/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/mariadb new file mode 100644 index 00000000000..e69de29bb2d diff --git a/mariadb/rootfs/etc/services.d/mariadb-lock/run b/mariadb/rootfs/etc/services.d/mariadb-lock/run deleted file mode 100755 index 7fd249aaaf6..00000000000 --- a/mariadb/rootfs/etc/services.d/mariadb-lock/run +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Start MariaDB client to lock tables (for snapshots) -# ============================================================================== - -bashio::log.info "Lock tables using mariadb client..." - -exec 4> >(mariadb) -MARIADB_PID=$! - -echo "FLUSH TABLES WITH READ LOCK;" >&4 - -# Notify s6 about successful service start -echo "" >&3 - -bashio::log.info "MariaDB tables locked." - -# Register stop -function stop_mariadb_client() { - echo "UNLOCK TABLES;" >&4 - bashio::log.info "MariaDB tables unlocked." - exec 4>&- - # Successful exit, avoid wait exit status to propagate - exit 0 -} -trap "stop_mariadb_client" SIGTERM SIGHUP - -wait "${MARIADB_PID}" diff --git a/mariadb/rootfs/etc/services.d/mariadb/finish b/mariadb/rootfs/etc/services.d/mariadb/finish deleted file mode 100644 index 0957a0a9466..00000000000 --- a/mariadb/rootfs/etc/services.d/mariadb/finish +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/execlineb -S0 -# ============================================================================== -# Take down the S6 supervision tree when mariadb fails -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } - -s6-svscanctl -t /var/run/s6/services \ No newline at end of file diff --git a/mariadb/rootfs/usr/bin/lock-tables-for-backup b/mariadb/rootfs/usr/bin/lock-tables-for-backup new file mode 100755 index 00000000000..b63418732fc --- /dev/null +++ b/mariadb/rootfs/usr/bin/lock-tables-for-backup @@ -0,0 +1,10 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Lock tables for backup +# ============================================================================== + +# Redirect stdout to the add-on's log +exec &> /proc/1/fd/1 +exec s6-rc -v 2 -u change mariadb-lock diff --git a/mariadb/rootfs/usr/bin/unlock-tables-for-backup b/mariadb/rootfs/usr/bin/unlock-tables-for-backup new file mode 100755 index 00000000000..2d09c79ce17 --- /dev/null +++ b/mariadb/rootfs/usr/bin/unlock-tables-for-backup @@ -0,0 +1,10 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Unlock tables for backup +# ============================================================================== + +# Redirect stdout to the add-on's log +exec &> /proc/1/fd/1 +exec s6-rc -v 2 -d change mariadb-lock diff --git a/mariadb/translations/en.yaml b/mariadb/translations/en.yaml new file mode 100644 index 00000000000..1c5288884e2 --- /dev/null +++ b/mariadb/translations/en.yaml @@ -0,0 +1,13 @@ +--- +configuration: + databases: + name: Databases + description: Database names. + logins: + name: Logins + description: This section defines a create user definition in MariaDB. + rights: + name: Rights + description: This section grant privileges to users in MariaDB. +network: + 3306/tcp: The port to access the database engine. diff --git a/matter_server/CHANGELOG.md b/matter_server/CHANGELOG.md new file mode 100644 index 00000000000..773e702617f --- /dev/null +++ b/matter_server/CHANGELOG.md @@ -0,0 +1,340 @@ +# Changelog + +## 7.0.0 + +- Bump Python Matter Server to [7.0.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/7.0.1) + - This updates Matter to 1.4 +- Update base image components to what is being used in Home Assistant Debian + base images: + - Update tempio to 2024.11.2 + - Update s6-overlay to 3.1.6.2 + - Update bashio to 0.16.2 + +## 6.6.1 + +- Bump Python Matter Server to [6.6.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.6.1) + +## 6.6.0 + +- Bump Python Matter Server to [6.6.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.6.0) + +## 6.5.1 + +- Bump Python Matter Server to [6.5.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.5.1) + +## 6.5.0 + +- Bump Python Matter Server to [6.5.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.5.0) + +## 6.4.2 + +- Add support for custom Matter Server arguments +- Add support to install custom Matter Server and Matter SDK (CHIP) versions + +## 6.4.1 + +- Bump Python Matter Server to [6.4.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.4.0) + +## 6.4.0 + +- Use add-on config directory as update directory + +## 6.3.1 + +- Fix Matter SDK log level when using beta flag + +## 6.3.0 + +- Bump Python Matter Server to [6.3.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.3.0) + +## 6.2.1 + +- Bump Python Matter Server to [6.2.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.2.1) + +## 6.1.2 + +- Bump Python Matter Server to [6.1.2](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.1.2) + +## 6.1.1 + +- Bump Python Matter Server to [6.1.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.1.1) + +## 6.1.0 + +- Bump Python Matter Server to [6.1.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.1.0) + - This update is required for Home Assistant Core 2024.6.0 + +## 6.0.0 + +- Bump Python Matter Server to [6.0.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/6.0.0) + - This updates Matter to 1.3 + +## 5.6.0 + +- Bump Python Matter Server to [5.10.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/5.10.0) + +## 5.5.1 + +- Fix logging in case fallback method for determining the primary network interface is used + +## 5.5.0 + +- Bump Python Matter Server to [5.9.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/5.9.0) +- Enable Ingress for the Python Matter Server built-in web interface +- Store PAA root certificates in /data to avoid download on every startup (downloads once a day) + +## 5.4.1 + +- Bump Python Matter Server to [5.8.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/5.8.1) + +## 5.4.0 + +- Bump Python Matter Server to [5.8.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/5.8.0) + +## 5.3.0 + +- Bump Python Matter Server to [5.7.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/5.7.0) +- Add Matter SDK log options + +## 5.2.0 + +- Bump Python Matter Server to [5.6.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/5.6.0) + +## 5.1.2 + +- Bump Python Matter Server to [5.5.3](https://github.com/home-assistant-libs/python-matter-server/releases/tag/5.5.3) + +## 5.1.1 + +- Bump Python Matter Server to [5.5.2](https://github.com/home-assistant-libs/python-matter-server/releases/tag/5.5.2) + +## 5.1.0 + +- Bump Python Matter Server to [5.5.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/5.5.1) +- Bind Python WebSocket on internal interface only by default + +## 5.0.4 + +- Correctly bump Python Matter Server to [5.2.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/5.2.1) + +## 5.0.3 + +- Bump Python Matter Server to [5.2.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/5.2.1) +- Pass primary interface to Python Matter server + +## 5.0.2 + +- Bump Python Matter Server to [5.1.4](https://github.com/home-assistant-libs/python-matter-server/releases/tag/5.1.4) + +## 5.0.1 + +- Bump Python Matter Server to [5.0.3](https://github.com/home-assistant-libs/python-matter-server/releases/tag/5.0.3) +- Fix matter-server finish script to report exit code +- Attach gdb debugger in beta mode to print stack traces on crash + +## 5.0.0 + +- Bump Python Matter Server to [5.0.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/5.0.1) +- Bump minimum required Home Assistant core version to 2023.12 due to breaking changes in the schema + +## 4.10.2 + +- Bump Python Matter Server to [4.0.2](https://github.com/home-assistant-libs/python-matter-server/releases/tag/4.0.2) + +## 4.10.1 + +- Bump Python Matter Server to [4.0.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/4.0.1) + +## 4.10.0 + +- Add beta flag to the add-on which installs Python Matter Server pre-releases at startup. + +## 4.9.0 + +- Bump Python Matter Server to [3.7.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/3.7.0) + +## 4.8.3 + +- Bump Python Matter Server to [3.6.4](https://github.com/home-assistant-libs/python-matter-server/releases/tag/3.6.4) + +## 4.8.2 + +- Bump Python Matter Server to [3.6.3](https://github.com/home-assistant-libs/python-matter-server/releases/tag/3.6.3) + +## 4.8.1 + +- Bump Python Matter Server to [3.6.2](https://github.com/home-assistant-libs/python-matter-server/releases/tag/3.6.2) + +## 4.8.0 + +- Bump Python Matter Server to [3.6.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/3.6.1) + +## 4.7.0 + +- Use the Python Matter Server container as base +- Bump Python Matter Server to [3.5.2](https://github.com/home-assistant-libs/python-matter-server/releases/tag/3.5.2) + +## 4.6.1 + +- Bump Python Matter Server to [3.5.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/3.5.1) + - Various small bug/stability fixes + +## 4.6.0 + +- Bump Python Matter Server to [3.5.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/3.5.0) + - Uses libnl based address selection to avoid using deprecated/temporary IP addresses + - libnl avoids "Endpoint pool full" errors as well +- Add dependency to support libnl based IP address selection + +## 4.5.1 + +- Bump Python Matter Server to [3.4.2](https://github.com/home-assistant-libs/python-matter-server/releases/tag/3.4.2) + +## 4.5.0 + +- Bump Python Matter Server to [3.4.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/3.4.1) +- Bump to Python 3.11 + +## 4.4.0 + +- Bump Python Matter Server to [3.4.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/3.4.0) + - This updates Matter to 1.1 +- Update S6 Overlay to v3.1.5.0 + +## 4.3.1 + +- Bump Python Matter Server to [3.3.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/3.3.1) + +## 4.3.0 + +- Bump Matter Server to [3.3.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/3.3.0) + +## 4.2.0 + +- Bump Matter Server to [3.2.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/3.2.0) +- Significantly reduced add-on size + +## 4.1.0 + +- Bump Matter Server to [3.1.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/3.1.0) + +## 4.0.0 + +- Bump Matter Server to [3.0.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/3.0.0) + +## 3.1.0 + +- Use Python 3.10 + +## 3.0.4 + +- Bump Matter Server to [2.1.1](https://github.com/home-assistant-libs/python-matter-server/releases/tag/2.1.1) +- Drop unnecessary Python dependencies from image + +## 3.0.3 + +- Bump Matter Server to [2.1.0](https://github.com/home-assistant-libs/python-matter-server/releases/tag/2.1.0) + +## 3.0.2 + +- Bump Matter Server to [2.0.2](https://github.com/home-assistant-libs/python-matter-server/releases/tag/2.0.2) + +## 3.0.1 + +- Bump Matter Server fabric ID after changing vendor ID + +## 3.0.0 + +- Bump Matter Server to 2.0.1 +- Use Nabu Casa Vendor ID by default + +### Breaking + +- All commissioned devices need to be recommissioned. + +## 2.1.0 + +- Bump Matter Server to 1.1.0 + +## 2.0.0 + +- Require Home Assistant Core 2023.1.0b1 to install the add-on. The chip SDK was bumped in [Matter Server 1.0.8](https://github.com/home-assistant-libs/python-matter-server/releases/tag/1.0.8). + +## 1.2.0 + +- Bump Matter Server to 1.0.8 +- Bump pre-built Matter SDK wheels to 2022.12.0 +- Make sure production PAA certificates work too + +## 1.1.2 + +- Get most recent certificates from master branch + +## 1.1.1 + +- Fix startup when Matter Server WebSocket port is not exposed + +## 1.1.0 + +- Allow to set Matter Server logging level +- Set storage path correctly +- Fix support for custom port + +## 1.0.7 + +- Bump Matter Server to 1.0.7 + +## 1.0.6 + +- Bump Matter Server to 1.0.6 + +## 1.0.5 + +- Bump Matter Server to 1.0.5 + +## 1.0.4 + +- Bump Matter Server to 1.0.4 + +## 1.0.1 + +- Bump Matter Server to 1.0.1 +- Use pre-built Matter SDK (CHIP) wheels + +## 0.4.0 + +- Add add-on discovery + +## 0.3.0 + +- Bump to CHIP version 989ad8e (2022-09-16 16:52 -0500) (start of the v1 branch!) +- Bump Matter Server to 0.3.0 + +## 0.2.2 + +- Bump to CHIP version 5b603f3874 (2022-07-05 21:21:19 -0700) +- Bump Matter Server to 0.2.3 +- Avoid cloning not required git repositories during build speedup build process + +## 0.2.1 + +- Bump Matter Server to 0.2.2 + +## 0.2.0 + +- Bump to CHIP version 5d8599d195 (2022-06-09 12:57:45 -0400) +- Bump Matter Server to 0.2.1 + +## 0.1.2 + +- Bump Matter Server to first official release 0.1.0 + +## 0.1.1 + +- Fix Matter Server start location so it can find device certificates +- Bump Matter Server to git version ac5545b (2022-06-11 00:04:34 +0200) + +## 0.1.0 + +- initial version +- CHIP version 55ab764bea (2022-06-06 23:10:48 -0400) diff --git a/matter_server/DOCS.md b/matter_server/DOCS.md new file mode 100644 index 00000000000..7c96639baba --- /dev/null +++ b/matter_server/DOCS.md @@ -0,0 +1,58 @@ +# Home Assistant Add-on: Matter Server + +## Installation + +Use the following steps to install this add-on. + +1. Click the Home Assistant My button below to open the add-on page on your + Home Assistant instance. + + [![Open this add-on in your Home Assistant instance.][addon-badge]][addon] + +1. Click the "Install" button to install the add-on. + +## How to use + +Start the Matter Server add-on to make the WebSocket available to Home +Assistant Core. Install the [Matter integration][matter_integration] +in Home Assistant Core. + +### Access WebSocket interface externally (advanced) + +By default, the Python Matter Server's WebSocket interface is only exposed +internally. It is still possible to enable access through the host interface +To do so, click on "Show disabled ports" and enter a port (e.g. 5580) in the +Matter Server WebSocket server port field. + +## Configuration + +Add-on configuration: + +| Configuration | Description | +|---------------------|-------------------------------------------------------------| +| log_level | Logging level of the Matter Server component. | +| log_level_sdk | Logging level for Matter SDK logs. | +| beta | Whether to install the latest beta version on startup | +| enable_test_net_dcl | Enable test-net DCL for PAA root certificates and other device information. | +| bluetooth_adapter_id | Set BlueZ Bluetooth Controller ID (for local commissioning) | + +## Support + +Got questions? + +You have several options to get them answered: + +- The [Home Assistant Discord Chat Server][discord]. +- The Home Assistant [Community Forum][forum]. +- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit] + +In case you've found a bug, please [open an issue on our GitHub][issue]. + +[addon]: https://my.home-assistant.io/redirect/supervisor_addon/?addon=core_matter_server +[addon-badge]: https://my.home-assistant.io/badges/supervisor_addon.svg +[discord]: https://discord.gg/c5DvZ4e +[forum]: https://community.home-assistant.io +[reddit]: https://reddit.com/r/homeassistant +[issue]: https://github.com/home-assistant/addons/issues +[matter_server_repo]: https://github.com/home-assistant-libs/python-matter-server +[matter_integration]: https://www.home-assistant.io/integrations/matter/ diff --git a/matter_server/Dockerfile b/matter_server/Dockerfile new file mode 100644 index 00000000000..135f97efc13 --- /dev/null +++ b/matter_server/Dockerfile @@ -0,0 +1,76 @@ +ARG BUILD_FROM +FROM ${BUILD_FROM} + +# Default ENV +ENV \ + LANG="C.UTF-8" \ + DEBIAN_FRONTEND="noninteractive" \ + CURL_CA_BUNDLE="/etc/ssl/certs/ca-certificates.crt" \ + S6_BEHAVIOUR_IF_STAGE2_FAILS=2 \ + S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \ + S6_CMD_WAIT_FOR_SERVICES=1 \ + S6_SERVICES_READYTIME=50 + +# Set shell +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +# Build Args +ARG \ + BASHIO_VERSION \ + TEMPIO_VERSION \ + S6_OVERLAY_VERSION + +# Base system +WORKDIR /usr/src +ARG BUILD_ARCH + +RUN \ + set -x \ + && apt-get update && apt-get install -y --no-install-recommends \ + bash \ + jq \ + tzdata \ + curl \ + ca-certificates \ + xz-utils \ + && mkdir -p /usr/share/man/man1 \ + \ + && if [ "${BUILD_ARCH}" = "armv7" ]; then \ + export S6_ARCH="arm"; \ + elif [ "${BUILD_ARCH}" = "i386" ]; then \ + export S6_ARCH="i686"; \ + elif [ "${BUILD_ARCH}" = "amd64" ]; then \ + export S6_ARCH="x86_64"; \ + else \ + export S6_ARCH="${BUILD_ARCH}"; \ + fi \ + \ + && curl -L -f -s "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-${S6_ARCH}.tar.xz" \ + | tar Jxvf - -C / \ + && curl -L -f -s "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz" \ + | tar Jxvf - -C / \ + && curl -L -f -s "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-symlinks-arch.tar.xz" \ + | tar Jxvf - -C / \ + && curl -L -f -s "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-symlinks-noarch.tar.xz" \ + | tar Jxvf - -C / \ + && mkdir -p /etc/fix-attrs.d \ + && mkdir -p /etc/services.d \ + \ + && curl -L -f -s -o /usr/bin/tempio \ + "https://github.com/home-assistant/tempio/releases/download/${TEMPIO_VERSION}/tempio_${BUILD_ARCH}" \ + && chmod a+x /usr/bin/tempio \ + \ + && mkdir -p /usr/src/bashio \ + && curl -L -f -s "https://github.com/hassio-addons/bashio/archive/v${BASHIO_VERSION}.tar.gz" \ + | tar -xzf - --strip 1 -C /usr/src/bashio \ + && mv /usr/src/bashio/lib /usr/lib/bashio \ + && ln -s /usr/lib/bashio/bashio /usr/bin/bashio \ + \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /usr/src/* + +# S6-Overlay +WORKDIR /root +ENTRYPOINT ["/init"] + +COPY rootfs / diff --git a/matter_server/README.md b/matter_server/README.md new file mode 100644 index 00000000000..1cab39a8791 --- /dev/null +++ b/matter_server/README.md @@ -0,0 +1,15 @@ +# Home Assistant Add-on: Matter Server + +![Supports aarch64 Architecture][aarch64-shield] +![Supports amd64 Architecture][amd64-shield] + +## About + +Matter Python WebSocket Server for Home Assistant Core. Matter (formerly +known as Connected Home over IP or CHIP) is an IPv6 based smart home +standard. This add-on provides a Matter Controller which allows you to +commission and control of Matter devices. The matching Home Assistant Core +integration communicates via WebSocket with this server. + +[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg +[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg diff --git a/matter_server/RELEASE.md b/matter_server/RELEASE.md new file mode 100644 index 00000000000..66d639186dd --- /dev/null +++ b/matter_server/RELEASE.md @@ -0,0 +1,11 @@ +# Release documentation for developers + +## Matter Server Update Procedure + +When updating the server library in the add-on follow these steps: + +1. Update the `MATTER_SERVER_VERSION` argument in `build.yaml`. +2. Check if the chip SDK version has changed in the server library. +3. If the minimal supported schema version has changed, set the `homeassistant` key in `config.yaml` to the minimum version of Home Assistant Core required to install or update the add-on. +4. Update the add-on version in `config.yaml`. Bump to a new major version if the minimum schema version has changed. +5. Update the changelog in `CHANGELOG.md`. Include a markdown link to the GitHub release of the server in the changelog. diff --git a/matter_server/build.yaml b/matter_server/build.yaml new file mode 100644 index 00000000000..862f4f603f3 --- /dev/null +++ b/matter_server/build.yaml @@ -0,0 +1,8 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant-libs/python-matter-server:7.0.1 + amd64: ghcr.io/home-assistant-libs/python-matter-server:7.0.1 +args: + BASHIO_VERSION: 0.16.2 + TEMPIO_VERSION: 2024.11.2 + S6_OVERLAY_VERSION: 3.1.6.2 diff --git a/matter_server/config.yaml b/matter_server/config.yaml new file mode 100644 index 00000000000..c2cf22096af --- /dev/null +++ b/matter_server/config.yaml @@ -0,0 +1,44 @@ +--- +version: 7.0.0 +slug: matter_server +name: Matter Server +description: Matter WebSocket Server for Home Assistant Matter support. +url: >- + https://github.com/home-assistant/addons/tree/master/matter_server +arch: + - aarch64 + - amd64 +discovery: + - matter +hassio_api: true +homeassistant: 2024.6.0 +# IPC is only used within the Add-on +host_ipc: false +host_network: true +host_dbus: true +image: homeassistant/{arch}-addon-matter-server +ingress: true +ingress_port: 5580 +init: false +map: + - type: addon_config + read_only: false +options: + log_level: info + log_level_sdk: error + beta: false + enable_test_net_dcl: false +schema: + log_level: list(verbose|debug|info|warning|error|critical) + log_level_sdk: list(automation|detail|progress|error|none)? + beta: bool? + enable_test_net_dcl: bool? + bluetooth_adapter_id: int? + matter_server_args: + - str? + matter_server_version: str? + matter_sdk_wheels_version: str? +ports: + 5580/tcp: null +stage: stable +startup: services diff --git a/matter_server/icon.png b/matter_server/icon.png new file mode 100644 index 00000000000..1fe6a564109 Binary files /dev/null and b/matter_server/icon.png differ diff --git a/matter_server/logo.png b/matter_server/logo.png new file mode 100644 index 00000000000..3ba729e191d Binary files /dev/null and b/matter_server/logo.png differ diff --git a/matter_server/rootfs/etc/s6-overlay/s6-rc.d/banner/type b/matter_server/rootfs/etc/s6-overlay/s6-rc.d/banner/type new file mode 100644 index 00000000000..bdd22a1850a --- /dev/null +++ b/matter_server/rootfs/etc/s6-overlay/s6-rc.d/banner/type @@ -0,0 +1 @@ +oneshot diff --git a/matter_server/rootfs/etc/s6-overlay/s6-rc.d/banner/up b/matter_server/rootfs/etc/s6-overlay/s6-rc.d/banner/up new file mode 100644 index 00000000000..dc292313ac5 --- /dev/null +++ b/matter_server/rootfs/etc/s6-overlay/s6-rc.d/banner/up @@ -0,0 +1 @@ +/etc/s6-overlay/scripts/banner.sh diff --git a/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/dependencies.d/banner b/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/dependencies.d/banner new file mode 100644 index 00000000000..e69de29bb2d diff --git a/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/finish b/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/finish new file mode 100755 index 00000000000..40aba91d0b4 --- /dev/null +++ b/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/finish @@ -0,0 +1,19 @@ +#!/usr/bin/env bashio +# vim: ft=bash +# ============================================================================== +# s6-overlay docs: https://github.com/just-containers/s6-overlay +# ============================================================================== + +if test "$1" -eq 256 ; then + e=$((128 + $2)) +else + e="$1" +fi + +if test "$e" -ne 0; then + bashio::log.warning "matter-server service exited with code $e (by signal $2)." + echo "$e" > /run/s6-linux-init-container-results/exitcode + exec /run/s6/basedir/bin/halt +else + bashio::log.info "matter-server service exited with code $e (by signal $2)." +fi diff --git a/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/run b/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/run new file mode 100755 index 00000000000..4b74c1065da --- /dev/null +++ b/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/run @@ -0,0 +1,107 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start matter-server service +# ============================================================================== +bashio::log.info "Starting Matter Server..." + +declare server_port +declare log_level +declare log_level_sdk +declare primary_interface +declare matter_server_version +declare chip_version +matter_server_args=() +extra_args=() + +if ! bashio::config.exists log_level; then + bashio::log.magenta 'No log_level set in config, fallback to info' +fi +log_level=$(bashio::string.lower "$(bashio::config log_level info)") + +# Make Matter SDK log level currently default to error +log_level_sdk=$(bashio::string.lower "$(bashio::config log_level_sdk error)") + +if bashio::config.has_value "matter_server_version"; then + matter_server_version=$(bashio::config 'matter_server_version') + bashio::log.info "Installing Python Matter Server ${matter_server_version}" + # shellcheck disable=SC2102 + pip3 install --pre python-matter-server[server]=="${matter_server_version}" +elif bashio::config.true "beta"; then + bashio::log.info 'Upgrading Python Matter Server to latest pre-release' + # shellcheck disable=SC2102 + pip3 install --upgrade --pre python-matter-server[server] +fi + +if bashio::config.has_value "matter_sdk_wheels_version"; then + chip_version=$(bashio::config 'matter_sdk_wheels_version') + bashio::log.info "Installing Matter SDK ${chip_version}" + pip3 install --pre --no-dependencies \ + home-assistant-chip-clusters=="${chip_version}" \ + home-assistant-chip-core=="${chip_version}" +fi + +# Bind to internal hassio network only unless user requests to expose +server_port="$(bashio::addon.port 5580)" +if ! bashio::var.has_value "${server_port}"; then + server_port=5580 + extra_args+=('--listen-address' "$(bashio::addon.ip_address)") +fi + +if bashio::config.true "enable_test_net_dcl"; then + extra_args+=('--enable-test-net-dcl') +fi + +primary_interface="$(bashio::api.supervisor 'GET' '/network/info' '' 'first(.interfaces[] | select (.primary == true)) .interface')" + +# Try fallback method (e.g. in case NetworkManager is not available) +# shellcheck disable=SC2086 +if [ -z ${primary_interface} ]; then + bashio::log.warning 'Trying fallback method to determine primary interface' + primary_interface="$(ip --json route show default | jq --raw-output '.[0].dev')" +fi + +# shellcheck disable=SC2086 +if [ -z ${primary_interface} ] || [ ${primary_interface} == "null" ]; then + bashio::exit.nok "No primary network interface found!" +fi + +if bashio::config.has_value "bluetooth_adapter_id"; then + # shellcheck disable=SC2207 + extra_args+=('--bluetooth-adapter' $(bashio::config 'bluetooth_adapter_id')) +fi + +if bashio::config.has_value "matter_server_args"; then + # shellcheck disable=SC2207 + extra_args+=($(bashio::config 'matter_server_args')) +fi + +bashio::log.info "Using '${primary_interface}' as primary network interface." + +# Send out discovery information to Home Assistant +/etc/s6-overlay/scripts/matter-server-discovery & + +# shellcheck disable=SC2164 +cd /root + +# shellcheck disable=SC2206 +matter_server_args+=( + '--storage-path' "/data" + '--port' "${server_port}" + '--log-level' "${log_level}" + '--log-level-sdk' "${log_level_sdk}" + '--primary-interface' "${primary_interface}" + '--paa-root-cert-dir' "/data/credentials" + '--ota-provider-dir' "/config/updates" + '--fabricid' 2 + '--vendorid' 4939 + ${extra_args[@]} +) + +if bashio::config.true "beta"; then + exec /usr/bin/gdb --quiet -ex="set confirm off" -ex run -ex backtrace -ex "quit \$_exitcode" --args /usr/local/bin/python \ + /usr/local/bin/matter-server "${matter_server_args[@]}" +else + exec /usr/local/bin/matter-server "${matter_server_args[@]}" +fi diff --git a/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/type b/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/matter_server/rootfs/etc/s6-overlay/s6-rc.d/matter-server/type @@ -0,0 +1 @@ +longrun diff --git a/matter_server/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/matter-server b/matter_server/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/matter-server new file mode 100644 index 00000000000..e69de29bb2d diff --git a/matter_server/rootfs/etc/s6-overlay/scripts/banner.sh b/matter_server/rootfs/etc/s6-overlay/scripts/banner.sh new file mode 100755 index 00000000000..074dc4179e5 --- /dev/null +++ b/matter_server/rootfs/etc/s6-overlay/scripts/banner.sh @@ -0,0 +1,38 @@ +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash +# ============================================================================== +# Home Assistant Community Add-on: Base Images +# Displays a simple add-on banner on startup +# ============================================================================== +if bashio::supervisor.ping; then + bashio::log.blue \ + '-----------------------------------------------------------' + bashio::log.blue " Add-on: $(bashio::addon.name)" + bashio::log.blue " $(bashio::addon.description)" + bashio::log.blue \ + '-----------------------------------------------------------' + + bashio::log.blue " Add-on version: $(bashio::addon.version)" + if bashio::var.true "$(bashio::addon.update_available)"; then + bashio::log.magenta ' There is an update available for this add-on!' + bashio::log.magenta \ + " Latest add-on version: $(bashio::addon.version_latest)" + bashio::log.magenta ' Please consider upgrading as soon as possible.' + else + bashio::log.green ' You are running the latest version of this add-on.' + fi + + bashio::log.blue " System: $(bashio::info.operating_system)" \ + " ($(bashio::info.arch) / $(bashio::info.machine))" + bashio::log.blue " Home Assistant Core: $(bashio::info.homeassistant)" + bashio::log.blue " Home Assistant Supervisor: $(bashio::info.supervisor)" + + bashio::log.blue \ + '-----------------------------------------------------------' + bashio::log.blue \ + ' Please, share the above information when looking for help' + bashio::log.blue \ + ' or support in, e.g., GitHub, forums or the Discord chat.' + bashio::log.blue \ + '-----------------------------------------------------------' +fi diff --git a/almond/rootfs/etc/services.d/almond/discovery b/matter_server/rootfs/etc/s6-overlay/scripts/matter-server-discovery similarity index 68% rename from almond/rootfs/etc/services.d/almond/discovery rename to matter_server/rootfs/etc/s6-overlay/scripts/matter-server-discovery index dcf36fa62a0..d36992d8b2f 100755 --- a/almond/rootfs/etc/services.d/almond/discovery +++ b/matter_server/rootfs/etc/s6-overlay/scripts/matter-server-discovery @@ -1,20 +1,19 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== -# Send Almond discovery information to Home Assistant +# Send matter discovery information to Home Assistant # ============================================================================== declare ha_config -# Wait for the Almond service to be available -bashio::net.wait_for 3000 - # Prepare discovery payload ha_config=$(\ bashio::var.json \ host "$(hostname)" \ - port "3001" \ + port "^5580" \ ) -if bashio::discovery "almond" "${ha_config}" > /dev/null; then +if bashio::discovery "matter" "${ha_config}" > /dev/null; then bashio::log.info "Successfully send discovery information to Home Assistant." else bashio::log.error "Discovery message to Home Assistant failed!" diff --git a/matter_server/translations/en.yaml b/matter_server/translations/en.yaml new file mode 100644 index 00000000000..d7e4432f33c --- /dev/null +++ b/matter_server/translations/en.yaml @@ -0,0 +1,46 @@ +--- +configuration: + log_level: + name: Matter Server Log Level + description: Logging level of the Matter Server component. + log_level_sdk: + name: Matter SDK Log Level + description: Logging level of the Matter SDK. + beta: + name: Use the latest beta version + description: >- + Installs the latest beta of the Python Matter Server. It is recommended + to create a backup before starting the add-on with this flag enabled! + enable_test_net_dcl: + name: Enable test-net DCL usage. + description: >- + Enable PAA root certificates and other device information from test-net + DCL. This is meant for development and testing purposes. + bluetooth_adapter_id: + name: Bluetooth Adapter ID + description: >- + BlueZ Bluetooth Adapter Controller ID used by the Matter Server. This is + required if local commissioning via Bluetooth is used. Note: Using the + Home Assistant Companion app commissioning method is recommended as it is + better tested and allows to commission directly in proximity of the device + itself. + matter_server_args: + name: Extra Matter Server arguments + description: >- + This allows to pass additional command line arguments to the Python Matter + Server. Use `--help` to get a list of possible arguments. Note that + arguments are also added by the startup script controlled by other add-on + options. + matter_server_version: + name: Matter Server version + description: >- + Install custom Matter Server version. WARNING: An older version might have + an incompatible storage format! Use this feature with caution! Make sure + you have a recent backup of the add-on! + matter_sdk_wheels_version: + name: Matter SDK wheels version + description: >- + Install custom Matter SDK wheels version. NOTE: The API might not be + compatible with the Python Matter server. +network: + 5580/tcp: Matter Server WebSocket server port. diff --git a/mosquitto/CHANGELOG.md b/mosquitto/CHANGELOG.md index 580e947a032..c4c2ddf0a61 100644 --- a/mosquitto/CHANGELOG.md +++ b/mosquitto/CHANGELOG.md @@ -1,5 +1,63 @@ # Changelog +## 6.5.0 + +- Update base image to Debian 12 (bookworm) +- Update mosquitto to version 2.0.20 +- Update mosquitto-go-auth to version 2.1.0 +- Update libwebsockets to version 4.3.3 + +## 6.4.1 + +- Increase default max_queued_messages to 8192 to fix dropped messages during Home Assistant startup + +## 6.4.0 + +- Update mosquitto to 2.0.18 + +## 6.3.1 + +- Add ability to use a pre-hashed password for custom logins + +## 6.3.0 + +- Update mosquitto to 2.0.17 + +## 6.2.1 + +- Add explicit dependencies for dynamic security plugin and asynchronous name resolver + +## 6.2.0 + +- Update mosquitto to 2.0.15 +- Update libwebsockets to 4.3.2 (fixes Unable to create websockets listener) + +## 6.1.3 + +- Change timestamp format in logs + +## 6.1.2 + +- Add debug option to help with issues + +## 6.1.1 + +- Don't purge openssl in cleanup + +## 6.1.0 + +- Update mosquitto to 2.0.11 +- Remove `mosquitto-auth-plug` and replace with `mosquitto-go-auth` 1.8.2 +- Change base image from Alpine to Debian (required for `mosquitto-go-auth`) + +Note: Mosquitto 2.0.0 did contain some breaking changes. We don't anticipate +most users to be affected by them but if you have a heavily customized mosquitto +config we would advise reviewing [their changelog](https://mosquitto.org/ChangeLog.txt). + +## 6.0.2 + +- Mention homeassistant and addon users in ACL doc + ## 6.0.1 - Fix loading custom mosquitto configuration diff --git a/mosquitto/DOCS.md b/mosquitto/DOCS.md index 5c2165e002e..4a1ace6728f 100644 --- a/mosquitto/DOCS.md +++ b/mosquitto/DOCS.md @@ -4,7 +4,7 @@ Follow these steps to get the add-on installed on your system: -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. 2. Find the "Mosquitto broker" add-on and click it. 3. Click on the "INSTALL" button. @@ -16,15 +16,15 @@ The add-on has a couple of options available. To get the add-on running: 2. Have some patience and wait a couple of minutes. 3. Check the add-on log output to see the result. -Create a new user for MQTT via the **Configuration** -> **Users (manage users)**. +Create a new user for MQTT via your Home Assistant's frontend **Settings** -> **People** -> **Users** , (i.e. not on Mosquitto's **Configuration** tab). Notes: -1. This name cannot be `homeassistant` or `addon`, those are reserved usernames. -2. If you do not see the option to create a new user, ensure that **Advanced Mode** is enabled in your profile. +1. This name cannot be `homeassistant` or `addons`, those are reserved usernames. +2. If you do not see the option to create a new user, ensure that **Advanced Mode** is enabled in your Home Assistant profile. To use the Mosquitto as a broker, go to the integration page and install the configuration with one click: -1. Navigate in your Home Assistant frontend to **Configuration** -> **Integrations**. +1. Navigate in your Home Assistant frontend to **Settings** -> **Devices & Services** -> **Integrations**. 2. MQTT should appear as a discovered integration at the top of the page 3. Select it and check the box to enable MQTT discovery if desired, and hit submit. @@ -54,6 +54,22 @@ logins: password: passwd ``` +You can also optionally set a `password` value using the hashed password obtained from the `pw` command (which is present inside the Mosquitto container). If doing so, you must also specify `password_pre_hashed: true` alongside the `username` and `password` values: + +```console +$ pw -p "foo" +PBKDF2$sha512$100000$qsU7xQ8YCV/9nRuBBJVTxA==$jqw94Ej3aEr97UofY6rClmVCRkTdDiubQW0A6ZYmUI+pZjW9Hax+2w2FeYB3y5ut1SliB7+HAwIl2iONLKkohw== +``` + +```yaml +logins: + - username: user + password: "PBKDF2$sha512$100000$qsU7xQ8YCV/9nRuBBJVTxA==$jqw94Ej3aEr97UofY6rClmVCRkTdDiubQW0A6ZYmUI+pZjW9Hax+2w2FeYB3y5ut1SliB7+HAwIl2iONLKkohw==" + password_pre_hashed: true +``` + +**Note:** This add-on does not support anonymous logins; all connections must use a username/password to connect. `allow_anonymous true` nor any anonymous ACLs will not work with this add-on. + #### Option: `customize.active` If set to `true` additional configuration files will be read, see the next option. @@ -72,13 +88,40 @@ A file containing a root certificate. Place this file in the Home Assistant `ssl A file containing a certificate, including its chain. Place this file in the Home Assistant `ssl` folder. +**Note on `certfile` and `keyfile`** +- If `certfile` and `keyfile` are _not_ provided + - Unencrypted connections are possible on the unencrypted ports (default: `1883`, `1884` for websockets) +- If `certfile` and `keyfile` are provided + - Unencrypted connections are possible on the unencrypted ports (default: `1883`, `1884` for websockets) + - Encrypted connections are possible on the encrypted ports (default: `8883`, `8884` for websockets) + - In that case, the client must trust the server's certificate + ### Option: `keyfile` A file containing the private key. Place this file in the Home Assistant `ssl` folder. +**Note on `certfile` and `keyfile`** +- If `certfile` and `keyfile` are _not_ provided + - Unencrypted connections are possible on the unencrypted ports (default: `1883`, `1884` for websockets) +- If `certfile` and `keyfile` are provided + - Unencrypted connections are possible on the unencrypted ports (default: `1883`, `1884` for websockets) + - Encrypted connections are possible on the encrypted ports (default: `8883`, `8884` for websockets) + - In that case, the client must trust the server's certificate + ### Option: `require_certificate` -If set to `true` encryption will be enabled using the cert- and keyfile options. +If set to `false`: +- Client is **not required** to provide a certificate to connect, username/password is enough +- `cafile` option is ignored + +If set to `true`: +- Client is **required** to provide its own certificate to connect, username/password is _not_ enough +- A certificate authority (CA) must be provided: `cafile` option +- The client certificate must be signed by the CA provided (`cafile`) + +### Option: `debug` + +If set to `true` turns on debug logging for mosquitto and its auth plugin. This an help when tracking down an issue however running with this long term is not recommended as sensitive information will be logged. ## Home Assistant user management @@ -97,7 +140,9 @@ See the following links for more information: - [Mosquitto topic restrictions](http://www.steves-internet-guide.com/topic-restriction-mosquitto-configuration/) - [Mosquitto.conf man page](https://mosquitto.org/man/mosquitto-conf-5.html) -Add the following configuration to enable **unrestricted** access to all topics. +Add the following configuration to enable **unrestricted** access to all topics for `[YOUR_MQTT_USER]`. + +**Note:** Home Assistant expects the users `homeassistant` and `addons` to have unrestricted readwrite access to all topics. If you choose to enable ACLs, you should grant this access to these users as demonstrated below. Otherwise you will run into issues. 1. Enable the customize flag @@ -116,6 +161,12 @@ Add the following configuration to enable **unrestricted** access to all topics. 3. Create `/share/mosquitto/accesscontrollist` with the contents: ```text + user addons + topic readwrite # + + user homeassistant + topic readwrite # + user [YOUR_MQTT_USER] topic readwrite # ``` @@ -136,7 +187,7 @@ In case you've found a bug, please [open an issue on our GitHub][issue]. [discord]: https://discord.gg/c5DvZ4e [forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues +[issue]: https://github.com/home-assistant/addons/issues [reddit]: https://reddit.com/r/homeassistant [repository]: https://github.com/hassio-addons/repository [mosquitto]: https://mosquitto.org/ diff --git a/mosquitto/Dockerfile b/mosquitto/Dockerfile index ab3f9b8ddcc..5de4082485a 100644 --- a/mosquitto/Dockerfile +++ b/mosquitto/Dockerfile @@ -3,37 +3,84 @@ FROM $BUILD_FROM # Install mosquitto + auth plugin WORKDIR /usr/src +ARG LIBWEBSOCKET_VERSION +ARG MOSQUITTO_VERSION ARG MOSQUITTO_AUTH_VERSION -RUN apk add --no-cache \ - mosquitto \ +RUN apt-get update \ + && apt-get install -qy --no-install-recommends \ nginx \ pwgen \ - && apk add --no-cache --virtual .build-dependencies \ - build-base \ - curl-dev \ + build-essential \ + cmake \ git \ - mosquitto-dev \ - openssl-dev \ + openssl \ + libssl-dev \ + libc-ares2 \ + libc-ares-dev \ + libcjson1 \ + libcjson-dev \ + xsltproc \ + docbook-xsl \ + golang-go \ \ + # Compile and install libwebsocket + # + # DLWS_WITHOUT_TESTAPPS is just a workaround, see + # https://github.com/warmcat/libwebsockets/issues/2790 for more + && git clone --depth 1 -b "v${LIBWEBSOCKET_VERSION}" \ + https://libwebsockets.org/repo/libwebsockets \ + \ + && cd libwebsockets \ + && mkdir build \ + && cd build \ + && cmake -DLWS_WITH_EXTERNAL_POLL=ON -DLWS_WITHOUT_TESTAPPS=ON .. \ + && make install \ + && ldconfig \ + && cd ../.. \ + # Compile and install mosquitto + && git clone --depth 1 -b "v${MOSQUITTO_VERSION}" \ + https://github.com/eclipse/mosquitto \ + \ + && cd mosquitto \ + && make WITH_WEBSOCKETS=yes WITH_SRV=yes \ + && make install \ + && cd .. \ + # Compile and install mosquitto-go-auth && git clone --depth 1 -b "${MOSQUITTO_AUTH_VERSION}" \ - https://github.com/pvizeli/mosquitto-auth-plug \ + https://github.com/iegomez/mosquitto-go-auth \ \ - && cd mosquitto-auth-plug \ - && cp config.mk.in config.mk \ + && cd mosquitto-go-auth \ + && sed -i 's/-I\/usr\/local\/include/-I\/usr\/include/' Makefile \ + && sed -i 's/LDFLAGS := .*$/& -Wl,-unresolved-symbols=ignore-all/' Makefile \ && make \ && mkdir -p /usr/share/mosquitto \ - && cp -f auth-plug.so /usr/share/mosquitto \ - && cp -f np /usr/local/bin \ + && cp -f go-auth.so /usr/share/mosquitto \ + && cp -f pw /usr/local/bin \ \ - && apk del --no-cache .build-dependencies \ + && apt-get purge -y --auto-remove \ + build-essential \ + git \ + cmake \ + libssl-dev \ + libc-ares-dev \ + libcjson-dev \ + xsltproc \ + docbook-xsl \ + golang-go \ + && apt-get clean \ && rm -fr \ /etc/logrotate.d \ /etc/mosquitto/* \ /etc/nginx/* \ /usr/share/nginx \ - /usr/src/mosquitto-auth-plug \ + /usr/src/libwebsockets \ + /usr/src/mosquitto \ + /usr/src/mosquitto-go-auth \ /var/lib/nginx/html \ - /var/www + /var/www \ + /var/lib/apt/lists/* \ + /root/.cache \ + /root/go # Copy rootfs COPY rootfs / diff --git a/mosquitto/build.json b/mosquitto/build.json deleted file mode 100644 index 2447a413e7c..00000000000 --- a/mosquitto/build.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "build_from": { - "aarch64": "ghcr.io/home-assistant/aarch64-base:3.13", - "amd64": "ghcr.io/home-assistant/amd64-base:3.13", - "armhf": "ghcr.io/home-assistant/armhf-base:3.13", - "armv7": "ghcr.io/home-assistant/armv7-base:3.13", - "i386": "ghcr.io/home-assistant/i386-base:3.13" - }, - "args": { - "MOSQUITTO_AUTH_VERSION": "0.1.5" - } -} diff --git a/mosquitto/build.yaml b/mosquitto/build.yaml new file mode 100644 index 00000000000..963c7f2a98f --- /dev/null +++ b/mosquitto/build.yaml @@ -0,0 +1,14 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base-debian:bookworm + amd64: ghcr.io/home-assistant/amd64-base-debian:bookworm + armhf: ghcr.io/home-assistant/armhf-base-debian:bookworm + armv7: ghcr.io/home-assistant/armv7-base-debian:bookworm + i386: ghcr.io/home-assistant/i386-base-debian:bookworm +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io +args: + LIBWEBSOCKET_VERSION: 4.3.3 + MOSQUITTO_VERSION: 2.0.20 + MOSQUITTO_AUTH_VERSION: 2.1.0 diff --git a/mosquitto/config.json b/mosquitto/config.json deleted file mode 100644 index 648eb7b5bfb..00000000000 --- a/mosquitto/config.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "Mosquitto broker", - "version": "6.0.1", - "slug": "mosquitto", - "description": "An Open Source MQTT broker", - "url": "https://github.com/home-assistant/hassio-addons/tree/master/mosquitto", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "startup": "system", - "map": ["ssl", "share"], - "discovery": ["mqtt"], - "services": ["mqtt:provide"], - "watchdog": "tcp://[HOST]:1883", - "auth_api": true, - "ports": { - "1883/tcp": 1883, - "1884/tcp": 1884, - "8883/tcp": 8883, - "8884/tcp": 8884 - }, - "ports_description": { - "1883/tcp": "Normal MQTT", - "1884/tcp": "MQTT over WebSocket", - "8883/tcp": "Normal MQTT with SSL", - "8884/tcp": "MQTT over WebSocket with SSL" - }, - "options": { - "logins": [], - "customize": { - "active": false, - "folder": "mosquitto" - }, - "certfile": "fullchain.pem", - "keyfile": "privkey.pem", - "require_certificate": false - }, - "schema": { - "logins": [ - { - "username": "str", - "password": "password" - } - ], - "customize": { - "active": "bool", - "folder": "str" - }, - "cafile": "str?", - "certfile": "str", - "keyfile": "str", - "require_certificate": "bool" - }, - "image": "homeassistant/{arch}-addon-mosquitto" -} diff --git a/mosquitto/config.yaml b/mosquitto/config.yaml new file mode 100644 index 00000000000..2135f6724cb --- /dev/null +++ b/mosquitto/config.yaml @@ -0,0 +1,51 @@ +--- +version: 6.5.0 +slug: mosquitto +name: Mosquitto broker +description: An Open Source MQTT broker +url: https://github.com/home-assistant/addons/tree/master/mosquitto +codenotary: notary@home-assistant.io +arch: + - armhf + - armv7 + - aarch64 + - amd64 + - i386 +auth_api: true +discovery: + - mqtt +image: homeassistant/{arch}-addon-mosquitto +map: + - ssl + - share +options: + logins: [] + require_certificate: false + certfile: fullchain.pem + keyfile: privkey.pem + customize: + active: false + folder: mosquitto +ports: + 1883/tcp: 1883 + 1884/tcp: 1884 + 8883/tcp: 8883 + 8884/tcp: 8884 +schema: + logins: + - username: str + password: password + password_pre_hashed: "bool?" + require_certificate: bool + certfile: str + cafile: str? + keyfile: str + customize: + active: bool + folder: str + debug: bool? +services: + - mqtt:provide +startup: system +watchdog: tcp://[HOST]:1883 +init: false diff --git a/mosquitto/logo.png b/mosquitto/logo.png index e003f9c809e..9418e64c343 100644 Binary files a/mosquitto/logo.png and b/mosquitto/logo.png differ diff --git a/mosquitto/rootfs/etc/cont-init.d/mosquitto.sh b/mosquitto/rootfs/etc/cont-init.d/mosquitto.sh old mode 100644 new mode 100755 index f9f1f7d43fa..3a0600d8634 --- a/mosquitto/rootfs/etc/cont-init.d/mosquitto.sh +++ b/mosquitto/rootfs/etc/cont-init.d/mosquitto.sh @@ -1,4 +1,5 @@ #!/usr/bin/with-contenv bashio +# shellcheck shell=bash # ============================================================================== # Configures mosquitto # ============================================================================== @@ -31,12 +32,12 @@ else fi # Set up discovery user -password=$(np -p "${discovery_password}") +password=$(pw -p "${discovery_password}") echo "homeassistant:${password}" >> "${PW}" echo "user homeassistant" >> "${ACL}" # Set up service user -password=$(np -p "${service_password}") +password=$(pw -p "${service_password}") echo "addons:${password}" >> "${PW}" echo "user addons" >> "${ACL}" @@ -49,7 +50,12 @@ for login in $(bashio::config 'logins|keys'); do password=$(bashio::config "logins[${login}].password") bashio::log.info "Setting up user ${username}" - password=$(np -p "${password}") + if ! bashio::config.true "logins[${login}].password_pre_hashed" + then + password=$(pw -p "${password}") + else + bashio::log.info "Using pre-hashed password for ${username}" + fi echo "${username}:${password}" >> "${PW}" echo "user ${username}" >> "${ACL}" done @@ -79,6 +85,7 @@ bashio::var.json \ keyfile "${keyfile}" \ require_certificate "^$(bashio::config 'require_certificate')" \ ssl "^${ssl}" \ + debug "^$(bashio::config 'debug')" \ | tempio \ -template /usr/share/tempio/mosquitto.gtpl \ -out /etc/mosquitto/mosquitto.conf diff --git a/mosquitto/rootfs/etc/cont-init.d/nginx.sh b/mosquitto/rootfs/etc/cont-init.d/nginx.sh old mode 100644 new mode 100755 index e4a4a5126f6..25dcfa5d6b8 --- a/mosquitto/rootfs/etc/cont-init.d/nginx.sh +++ b/mosquitto/rootfs/etc/cont-init.d/nginx.sh @@ -1,4 +1,5 @@ #!/usr/bin/with-contenv bashio +# shellcheck shell=bash # ============================================================================== # Configures NGINX # ============================================================================== diff --git a/mosquitto/rootfs/etc/services.d/mosquitto/discovery b/mosquitto/rootfs/etc/services.d/mosquitto/discovery index 732d66966db..6f330537dbf 100755 --- a/mosquitto/rootfs/etc/services.d/mosquitto/discovery +++ b/mosquitto/rootfs/etc/services.d/mosquitto/discovery @@ -1,4 +1,6 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Send MQTT discovery information to Home Assistant and service information # to the Supervisor (for other add-ons). @@ -8,7 +10,7 @@ declare config declare discovery_password declare service_password -# Wait for mosquitti to start before continuing +# Wait for mosquitto to start before continuing bashio::net.wait_for 1883 # Read the existing values diff --git a/mosquitto/rootfs/etc/services.d/mosquitto/finish b/mosquitto/rootfs/etc/services.d/mosquitto/finish old mode 100644 new mode 100755 index 9fa0c9fec78..f4c53b282d0 --- a/mosquitto/rootfs/etc/services.d/mosquitto/finish +++ b/mosquitto/rootfs/etc/services.d/mosquitto/finish @@ -1,8 +1,13 @@ -#!/usr/bin/execlineb -S0 +#!/usr/bin/env bashio +# vim: ft=bash # ============================================================================== -# Take down the S6 supervision tree when mosquitto crashes +# Take down the S6 supervision tree when service fails +# s6-overlay docs: https://github.com/just-containers/s6-overlay # ============================================================================== -if -n { s6-test $# -ne 0 } -if -n { s6-test ${1} -eq 256 } -s6-svscanctl -t /var/run/s6/services +if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then + bashio::log.warning "Halt add-on" + exec /run/s6/basedir/bin/halt +fi + +bashio::log.info "Service restart after closing" diff --git a/mosquitto/rootfs/etc/services.d/mosquitto/run b/mosquitto/rootfs/etc/services.d/mosquitto/run old mode 100644 new mode 100755 index f25b2bc495b..79e114469ef --- a/mosquitto/rootfs/etc/services.d/mosquitto/run +++ b/mosquitto/rootfs/etc/services.d/mosquitto/run @@ -1,4 +1,6 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Runs mosquitto # ============================================================================== diff --git a/mosquitto/rootfs/etc/services.d/nginx/finish b/mosquitto/rootfs/etc/services.d/nginx/finish old mode 100644 new mode 100755 index 9a770c54eea..f4c53b282d0 --- a/mosquitto/rootfs/etc/services.d/nginx/finish +++ b/mosquitto/rootfs/etc/services.d/nginx/finish @@ -1,8 +1,13 @@ -#!/usr/bin/execlineb -S0 +#!/usr/bin/env bashio +# vim: ft=bash # ============================================================================== -# Take down the S6 supervision tree when nginx crashes +# Take down the S6 supervision tree when service fails +# s6-overlay docs: https://github.com/just-containers/s6-overlay # ============================================================================== -if -n { s6-test $# -ne 0 } -if -n { s6-test ${1} -eq 256 } -s6-svscanctl -t /var/run/s6/services +if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then + bashio::log.warning "Halt add-on" + exec /run/s6/basedir/bin/halt +fi + +bashio::log.info "Service restart after closing" diff --git a/mosquitto/rootfs/etc/services.d/nginx/run b/mosquitto/rootfs/etc/services.d/nginx/run old mode 100644 new mode 100755 index a585b2ba91c..b433b18d5bd --- a/mosquitto/rootfs/etc/services.d/nginx/run +++ b/mosquitto/rootfs/etc/services.d/nginx/run @@ -1,4 +1,6 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Runs the NGINX daemon # ============================================================================== diff --git a/mosquitto/rootfs/usr/share/tempio/mosquitto.gtpl b/mosquitto/rootfs/usr/share/tempio/mosquitto.gtpl index ac4d1cab418..c1a840461c9 100644 --- a/mosquitto/rootfs/usr/share/tempio/mosquitto.gtpl +++ b/mosquitto/rootfs/usr/share/tempio/mosquitto.gtpl @@ -1,29 +1,41 @@ protocol mqtt user root log_dest stdout +{{ if .debug }} +log_type all +{{ else }} log_type error log_type warning log_type notice log_type information +{{ end }} +log_timestamp_format %Y-%m-%d %H:%M:%S persistence true persistence_location /data/ +# Limits +# max_queued_messages is effectively the upper limit of +# the number of entities on Home Assistant if startup +# is busy and cannot read messages fast enough +max_queued_messages 8192 + # Authentication plugin -auth_plugin /usr/share/mosquitto/auth-plug.so +auth_plugin /usr/share/mosquitto/go-auth.so auth_opt_backends files,http +auth_opt_hasher pbkdf2 auth_opt_cache true -auth_opt_auth_cacheseconds 300 -auth_opt_auth_cachejitter 30 -auth_opt_acl_cacheseconds 300 -auth_opt_acl_cachejitter 30 -auth_opt_log_quiet true +auth_opt_auth_cache_seconds 300 +auth_opt_auth_jitter_seconds 30 +auth_opt_acl_cache_seconds 300 +auth_opt_acl_jitter_seconds 30 +auth_opt_log_level {{ if .debug }}debug{{ else }}error{{ end }} # HTTP backend for the authentication plugin -auth_opt_password_file /etc/mosquitto/pw -auth_opt_acl_file /etc/mosquitto/acl +auth_opt_files_password_path /etc/mosquitto/pw +auth_opt_files_acl_path /etc/mosquitto/acl # HTTP backend for the authentication plugin -auth_opt_http_ip 127.0.0.1 +auth_opt_http_host 127.0.0.1 auth_opt_http_port 80 auth_opt_http_getuser_uri /authentication auth_opt_http_superuser_uri /superuser diff --git a/mosquitto/translations/en.yaml b/mosquitto/translations/en.yaml new file mode 100644 index 00000000000..22f6147e4ad --- /dev/null +++ b/mosquitto/translations/en.yaml @@ -0,0 +1,44 @@ +--- +configuration: + logins: + name: Logins + description: >- + A list of local users that will be created with username and password. + You don't need to do this because you can use Home Assistant users too, + without any configuration. You can also specify + `password_pre_hashed: true` to utilize a pre-hashed password from the + output of the `pw` command (which is present inside the container). + require_certificate: + name: Require Client Certificate + description: >- + If enabled client will need to provide its own certificate on top of + username/password. 'cafile' must be set. + certfile: + name: Certificate File + description: >- + A file containing a certificate, including its chain. Place this file in + the Home Assistant `ssl` folder. + cafile: + name: CA File + description: >- + A file containing a root certificate that signed the client certificate + (only used if 'require_certificate' enabled). Place this file in the Home + Assistant `ssl` folder. + keyfile: + name: Private Key File + description: >- + A file containing the private key. Place this file in the Home Assistant + `ssl` folder. + customize: + name: Customize + description: >- + See the Documentation tab for more information about these options. + debug: + name: Debug + description: >- + If enabled will turn on debug logging for mosquitto and the auth plugin. +network: + 1883/tcp: Normal MQTT + 1884/tcp: MQTT over WebSocket + 8883/tcp: Normal MQTT with SSL + 8884/tcp: MQTT over WebSocket with SSL diff --git a/nginx_proxy/CHANGELOG.md b/nginx_proxy/CHANGELOG.md index 5c6c4b9be73..9dc6ee2027a 100644 --- a/nginx_proxy/CHANGELOG.md +++ b/nginx_proxy/CHANGELOG.md @@ -1,5 +1,86 @@ # Changelog +## 3.11.1 + +- Update to new nginx http2 directive. This also suppress a deprecation warning. + +## 3.11.0 + +- Update Alpine Linux to 3.20 (nginx 1.26.x) + +## 3.10.1 + +- Make `real_ip_from` optional through an empty default value + +## 3.10.0 + +- Supporting TCP Proxy Protocol + +## 3.9.0 + +- Add `map_hash_bucket_size` to add support for longer matches in `map` + +## 3.8.0 + +- Update Alpine Linux to 3.19 + +## 3.7.0 + +- Modify `server_names_hash_bucket_size` to add support for longer domain names + +## 3.6.0 + +- Add port to Host header to fix origin issues affecting ESPHome and other addons + +## 3.5.0 + +- Update Alpine to 3.18 (nginx 1.24.x) + +## 3.4.2 + +- Decrease crond log level + +## 3.4.1 + +- Avoid logging to system console + +## 3.4.0 + +- Add X-Forwarded-Host to fix origin issues affecting VSCode and other addons + +## 3.3.0 + +- Check certificate renewal daily and reload nginx if necessary +- Migrate add-on layout to S6 Overlay + +## 3.2.0 + +- Update Alpine to 3.16 (nginx 1.22.x) + +## 3.1.5 + +- Fixed container environment + +## 3.1.4 + +- Fixed init config + +## 3.1.3 + +- Reject SSL on unknown domains instead of responding with an invalid certificate + +## 3.1.2 + +- Fix TLSv1.3 support + +## 3.1.1 + +- Hide server version banner + +## 3.1.0 + +- Allow use of ports other than 8123 in Home Assistant Core + ## 3.0.2 - Update Alpine to 3.14 diff --git a/nginx_proxy/DOCS.md b/nginx_proxy/DOCS.md index 5a55eb7b325..0cda915d6c8 100644 --- a/nginx_proxy/DOCS.md +++ b/nginx_proxy/DOCS.md @@ -4,34 +4,30 @@ Follow these steps to get the add-on installed on your system: -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. 2. Find the "NGINX Home Assistant SSL proxy" add-on and click it. 3. Click on the "INSTALL" button. ## How to use -The NGINX Proxy add-on is commonly used in conjunction with the [Duck DNS](https://github.com/home-assistant/hassio-addons/tree/master/duckdns) add-on to set up secure remote access to your Home Assistant instance. The following instructions covers this scenario. - -1. The certificate to your registered domain should already be created via the [Duck DNS](https://github.com/home-assistant/hassio-addons/tree/master/duckdns) add-on or another method. Make sure that the certificate files exist in the `/ssl` directory. -2. In the `configuration.yaml` file, some options in the `http:` section are no longer necessary for this scenario, and should be commented out or removed: - - `ssl_certificate` - - `ssl_key` - - `server_port` -3. And you need to add the `trusted_proxies` section (requests from reverse proxies will be blocked if these options are not set). - - ```yaml - http: - use_x_forwarded_for: true - trusted_proxies: - - 172.30.33.0/24 - ``` - -4. In the nginx addon configuration, change the `domain` option to the domain name you registered (from DuckDNS or any other domain you control). -5. Leave all other options as-is. -6. Save configuration. -7. Start the add-on. -8. Have some patience and wait a couple of minutes. -9. Check the add-on log output to see the result. +The NGINX Proxy add-on is commonly used in conjunction with the [Duck DNS](https://github.com/home-assistant/addons/tree/master/duckdns) and/or the [Let's Encrypt](https://github.com/home-assistant/addons/tree/master/letsencrypt) add-on to set up secure remote access to your Home Assistant instance. The following instructions covers this scenario. + +1. The certificate to your registered domain should already be created via [Duck DNS](https://github.com/home-assistant/addons/tree/master/duckdns), [Let's Encrypt](https://github.com/home-assistant/addons/tree/master/letsencrypt) or another method. Make sure that the certificate files exist in the `/ssl` directory. +2. You must add the following section to your [Home Assistant configuration.yaml](https://www.home-assistant.io/docs/configuration/). If the `http` section is using the `ssl_certificate`, `ssl_key` or `server_port` keys, make sure to remove them. + + ```yaml + http: + use_x_forwarded_for: true + trusted_proxies: + - 172.30.33.0/24 + ``` +3. In the nginx addon configuration, change the `domain` option to the domain name you registered (from DuckDNS or any other domain you control). +4. Leave all other options as-is. +5. Save configuration. +6. Start the add-on. +7. Have some patience and wait a couple of minutes. +8. Check the add-on log output to see the result. + ## Configuration @@ -47,15 +43,16 @@ customize: default: "nginx_proxy_default*.conf" servers: "nginx_proxy/*.conf" cloudflare: false +real_ip_from: [] ``` ### Option: `domain` (required) -The domain name to use for the proxy. +The server's fully qualified domain name to use for the proxy. ### Option: `certfile` (required) -The certificate file to use in the `/ssl` directory. Keep filename as-is if you used default settings to create the certificate with the [Duck DNS](https://github.com/home-assistant/hassio-addons/tree/master/duckdns) add-on. +The certificate file to use in the `/ssl` directory. Keep filename as-is if you used default settings to create the certificate with the [Duck DNS](https://github.com/home-assistant/addons/tree/master/duckdns) add-on. ### Option: `keyfile` (required) @@ -82,10 +79,18 @@ The filename(s) of the NGINX configuration for the additional servers, found in If enabled, configure Nginx with a list of IP addresses directly from Cloudflare that will be used for `set_real_ip_from` directive Nginx config. This is so the `ip_ban_enabled` feature can be used and work correctly in /config/customize.yaml. +### Option `real_ip_from` (optional) + +If specified, configures Nginx to use Proxy Protocol to get the Real Ip from an upstream load balancer; [for more information](https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/). + ## Known issues and limitations - By default, port 80 is disabled in the add-on configuration in case the port is needed for other components or add-ons like `emulated_hue`. +## Troubleshooting + +- `400 Bad Request` response for requests over this proxy mean you are probably missing the `trusted_proxies` configuration option, see above. + ## Support Got questions? @@ -98,8 +103,9 @@ You have several options to get them answered: In case you've found a bug, please [open an issue on our GitHub][issue]. +[discord]: https://discord.gg/c5DvZ4e [forum]: https://community.home-assistant.io [hsts]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security -[issue]: https://github.com/home-assistant/hassio-addons/issues +[issue]: https://github.com/home-assistant/addons/issues [reddit]: https://reddit.com/r/homeassistant [repository]: https://github.com/hassio-addons/repository diff --git a/nginx_proxy/Dockerfile b/nginx_proxy/Dockerfile index 4b7e46d964c..e350e48229d 100644 --- a/nginx_proxy/Dockerfile +++ b/nginx_proxy/Dockerfile @@ -5,7 +5,6 @@ FROM $BUILD_FROM RUN apk add --no-cache nginx openssl # Copy data -COPY data/run.sh / -COPY data/nginx.conf /etc/ +COPY rootfs / -CMD [ "/run.sh" ] +WORKDIR / diff --git a/nginx_proxy/build.json b/nginx_proxy/build.json deleted file mode 100644 index 5a03630f139..00000000000 --- a/nginx_proxy/build.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "build_from": { - "aarch64": "ghcr.io/home-assistant/aarch64-base:3.14", - "amd64": "ghcr.io/home-assistant/amd64-base:3.14", - "armhf": "ghcr.io/home-assistant/armhf-base:3.14", - "armv7": "ghcr.io/home-assistant/armv7-base:3.14", - "i386": "ghcr.io/home-assistant/i386-base:3.14" - } -} diff --git a/nginx_proxy/build.yaml b/nginx_proxy/build.yaml new file mode 100644 index 00000000000..ddb806cecdd --- /dev/null +++ b/nginx_proxy/build.yaml @@ -0,0 +1,10 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base:3.20 + amd64: ghcr.io/home-assistant/amd64-base:3.20 + armhf: ghcr.io/home-assistant/armhf-base:3.20 + armv7: ghcr.io/home-assistant/armv7-base:3.20 + i386: ghcr.io/home-assistant/i386-base:3.20 +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io diff --git a/nginx_proxy/config.json b/nginx_proxy/config.json deleted file mode 100644 index 82758bb8b6e..00000000000 --- a/nginx_proxy/config.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "NGINX Home Assistant SSL proxy", - "version": "3.0.2", - "slug": "nginx_proxy", - "description": "An SSL/TLS proxy", - "url": "https://github.com/home-assistant/hassio-addons/tree/master/nginx_proxy", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "ports": { - "80/tcp": null, - "443/tcp": 443 - }, - "map": ["ssl", "share"], - "options": { - "domain": null, - "certfile": "fullchain.pem", - "keyfile": "privkey.pem", - "hsts": "max-age=31536000; includeSubDomains", - "cloudflare": false, - "customize": { - "active": false, - "default": "nginx_proxy_default*.conf", - "servers": "nginx_proxy/*.conf" - } - }, - "schema": { - "domain": "str", - "certfile": "str", - "keyfile": "str", - "hsts": "str", - "cloudflare": "bool", - "customize": { - "active": "bool", - "default": "str", - "servers": "str" - } - }, - "image": "homeassistant/{arch}-addon-nginx_proxy" -} diff --git a/nginx_proxy/config.yaml b/nginx_proxy/config.yaml new file mode 100644 index 00000000000..9bfcac14182 --- /dev/null +++ b/nginx_proxy/config.yaml @@ -0,0 +1,44 @@ +--- +version: 3.11.1 +hassio_api: true +slug: nginx_proxy +name: NGINX Home Assistant SSL proxy +description: An SSL/TLS proxy +url: https://github.com/home-assistant/addons/tree/master/nginx_proxy +arch: + - armhf + - armv7 + - aarch64 + - amd64 + - i386 +image: homeassistant/{arch}-addon-nginx_proxy +init: false +map: + - ssl + - share +options: + domain: null + hsts: max-age=31536000; includeSubDomains + certfile: fullchain.pem + keyfile: privkey.pem + cloudflare: false + customize: + active: false + default: nginx_proxy_default*.conf + servers: nginx_proxy/*.conf + real_ip_from: [] +ports: + 443/tcp: 443 + 80/tcp: null +schema: + domain: str + hsts: str + certfile: str + keyfile: str + cloudflare: bool + customize: + active: bool + default: str + servers: str + real_ip_from: + - str diff --git a/nginx_proxy/data/nginx.conf b/nginx_proxy/data/nginx.conf deleted file mode 100644 index fdc091f2621..00000000000 --- a/nginx_proxy/data/nginx.conf +++ /dev/null @@ -1,72 +0,0 @@ -daemon off; -error_log stderr; -pid /var/run/nginx.pid; - -events { - worker_connections 1024; -} - -http { - map $http_upgrade $connection_upgrade { - default upgrade; - '' close; - } - - server_names_hash_bucket_size 64; - - #include /data/cloudflare.conf; - - server { - server_name _; - listen 80 default_server; - listen 443 ssl http2 default_server; - ssl_certificate /data/ssl-cert-snakeoil.pem; - ssl_certificate_key /data/ssl-cert-snakeoil.key; - return 444; - } - - server { - server_name %%DOMAIN%%; - - # These shouldn't need to be changed - listen 80; - return 301 https://$host$request_uri; - } - - server { - server_name %%DOMAIN%%; - - ssl_session_timeout 1d; - ssl_session_cache shared:MozSSL:10m; - ssl_session_tickets off; - ssl_certificate /ssl/%%FULLCHAIN%%; - ssl_certificate_key /ssl/%%PRIVKEY%%; - - # dhparams file - ssl_dhparam /data/dhparams.pem; - - listen 443 ssl http2; - %%HSTS%% - - # intermediate configuration - ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; - ssl_prefer_server_ciphers off; - - proxy_buffering off; - - #include /share/nginx_proxy_default*.conf; - - location / { - proxy_pass http://homeassistant.local.hass.io:8123; - proxy_set_header Host $host; - proxy_redirect http:// https://; - proxy_http_version 1.1; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - } - } - - #include /share/nginx_proxy/*.conf; -} diff --git a/nginx_proxy/data/run.sh b/nginx_proxy/data/run.sh deleted file mode 100755 index 6e26713ce71..00000000000 --- a/nginx_proxy/data/run.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env bashio -set -e - -DHPARAMS_PATH=/data/dhparams.pem - -SNAKEOIL_CERT=/data/ssl-cert-snakeoil.pem -SNAKEOIL_KEY=/data/ssl-cert-snakeoil.key - -CLOUDFLARE_CONF=/data/cloudflare.conf - -DOMAIN=$(bashio::config 'domain') -KEYFILE=$(bashio::config 'keyfile') -CERTFILE=$(bashio::config 'certfile') -HSTS=$(bashio::config 'hsts') - -# Generate dhparams -if ! bashio::fs.file_exists "${DHPARAMS_PATH}"; then - bashio::log.info "Generating dhparams (this will take some time)..." - openssl dhparam -dsaparam -out "$DHPARAMS_PATH" 4096 > /dev/null -fi - -if ! bashio::fs.file_exists "${SNAKEOIL_CERT}"; then - bashio::log.info "Creating 'snakeoil' self-signed certificate..." - openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout $SNAKEOIL_KEY -out $SNAKEOIL_CERT -subj '/CN=localhost' -fi - -if bashio::config.true 'cloudflare'; then - sed -i "s|#include /data/cloudflare.conf;|include /data/cloudflare.conf;|" /etc/nginx.conf - # Generate cloudflare.conf - if ! bashio::fs.file_exists "${CLOUDFLARE_CONF}"; then - bashio::log.info "Creating 'cloudflare.conf' for real visitor IP address..." - echo "# Cloudflare IP addresses" > $CLOUDFLARE_CONF; - echo "" >> $CLOUDFLARE_CONF; - - echo "# - IPv4" >> $CLOUDFLARE_CONF; - for i in $(curl https://www.cloudflare.com/ips-v4); do - echo "set_real_ip_from ${i};" >> $CLOUDFLARE_CONF; - done - - echo "" >> $CLOUDFLARE_CONF; - echo "# - IPv6" >> $CLOUDFLARE_CONF; - for i in $(curl https://www.cloudflare.com/ips-v6); do - echo "set_real_ip_from ${i};" >> $CLOUDFLARE_CONF; - done - - echo "" >> $CLOUDFLARE_CONF; - echo "real_ip_header CF-Connecting-IP;" >> $CLOUDFLARE_CONF; - fi -fi - -# Prepare config file -sed -i "s#%%FULLCHAIN%%#$CERTFILE#g" /etc/nginx.conf -sed -i "s#%%PRIVKEY%%#$KEYFILE#g" /etc/nginx.conf -sed -i "s/%%DOMAIN%%/$DOMAIN/g" /etc/nginx.conf - -[ -n "$HSTS" ] && HSTS="add_header Strict-Transport-Security \"$HSTS\" always;" -sed -i "s/%%HSTS%%/$HSTS/g" /etc/nginx.conf - -# Allow customize configs from share -if bashio::config.true 'customize.active'; then - CUSTOMIZE_DEFAULT=$(bashio::config 'customize.default') - sed -i "s|#include /share/nginx_proxy_default.*|include /share/$CUSTOMIZE_DEFAULT;|" /etc/nginx.conf - CUSTOMIZE_SERVERS=$(bashio::config 'customize.servers') - sed -i "s|#include /share/nginx_proxy/.*|include /share/$CUSTOMIZE_SERVERS;|" /etc/nginx.conf -fi - -# start server -bashio::log.info "Running nginx..." -exec nginx -c /etc/nginx.conf < /dev/null diff --git a/nginx_proxy/rootfs/etc/nginx/nginx.conf.gtpl b/nginx_proxy/rootfs/etc/nginx/nginx.conf.gtpl new file mode 100644 index 00000000000..58cd8d06e8f --- /dev/null +++ b/nginx_proxy/rootfs/etc/nginx/nginx.conf.gtpl @@ -0,0 +1,105 @@ +{{/* + Options saved in the addon UI are available in .options + Some variables are available in .variables, these are added in nginx/run +*/}} +daemon off; +error_log stderr; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + map_hash_bucket_size 128; + + map $http_upgrade $connection_upgrade { + default upgrade; + '' close; + } + + server_tokens off; + + server_names_hash_bucket_size 128; + + # intermediate configuration + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; + ssl_prefer_server_ciphers off; + + {{- if .options.cloudflare }} + include /data/cloudflare.conf; + {{- end }} + + server { + server_name _; + listen 80 default_server; + listen 443 ssl default_server; + http2 on; + ssl_reject_handshake on; + return 444; + } + + server { + server_name {{ .options.domain }}; + + # These shouldn't need to be changed + listen 80; + return 301 https://$host$request_uri; + } + + server { + server_name {{ .options.domain }}; + + ssl_session_timeout 1d; + ssl_session_cache shared:MozSSL:10m; + ssl_session_tickets off; + ssl_certificate /ssl/{{ .options.certfile }}; + ssl_certificate_key /ssl/{{ .options.keyfile }}; + + # dhparams file + ssl_dhparam /data/dhparams.pem; + + {{- if not .options.real_ip_from }} + listen 443 ssl; + http2 on; + {{- else }} + listen 443 ssl proxy_protocol; + http2 on; + {{- range .options.real_ip_from }} + set_real_ip_from {{.}}; + {{- end }} + real_ip_header proxy_protocol; + {{- end }} + + {{- if .options.hsts }} + add_header Strict-Transport-Security "{{ .options.hsts }}" always; + {{- end }} + + proxy_buffering off; + + {{- if .options.customize.active }} + include /share/{{ .options.customize.default }}; + {{- end }} + + location / { + proxy_pass http://homeassistant.local.hass.io:{{ .variables.port }}; + proxy_set_header Host $http_host; + proxy_redirect http:// https://; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header X-Forwarded-Host $http_host; + {{- if not .options.real_ip_from }} + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + {{- else }} + proxy_set_header X-Real-IP $proxy_protocol_addr; + proxy_set_header X-Forwarded-For $proxy_protocol_addr; + {{- end }} + } + } + + {{- if .options.customize.active }} + include /share/{{ .options.customize.servers }}; + {{- end }} +} diff --git a/nginx_proxy/rootfs/etc/periodic/daily/check_certificate_renewal b/nginx_proxy/rootfs/etc/periodic/daily/check_certificate_renewal new file mode 100755 index 00000000000..95da6ff7044 --- /dev/null +++ b/nginx_proxy/rootfs/etc/periodic/daily/check_certificate_renewal @@ -0,0 +1,14 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Check certificate renewal +# ============================================================================== + +CERTFILE=$(bashio::config 'certfile') + +if [ ! -f /tmp/certificate_timestamp ] || [[ $(stat "/ssl/${CERTFILE}" -c %y) != $(cat /tmp/certificate_timestamp) ]]; then + bashio::log.info "Reloading nginx to reload new certificate file" + stat "/ssl/${CERTFILE}" -c %y > /tmp/certificate_timestamp + nginx -c /etc/nginx.conf -s reload +fi diff --git a/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/dependencies.d/nginx b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/dependencies.d/nginx new file mode 100644 index 00000000000..e69de29bb2d diff --git a/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/finish b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/finish new file mode 100644 index 00000000000..c24c56f2dfd --- /dev/null +++ b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/finish @@ -0,0 +1,27 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Take down the S6 supervision tree when daemon fails +# ============================================================================== +# shellcheck disable=SC2155 +readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode + fi + [[ "${exit_code_signal}" -eq 15 ]] && exec /run/s6/basedir/bin/halt +elif [[ "${exit_code_service}" -ne 0 ]]; then + if [[ "${exit_code_container}" -eq 0 ]]; then + echo "${exit_code_service}" > /run/s6-linux-init-container-results/exitcode + fi + exec /run/s6/basedir/bin/halt +fi diff --git a/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/run b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/run new file mode 100644 index 00000000000..a97b8f4bf73 --- /dev/null +++ b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/run @@ -0,0 +1,8 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start crond service +# ============================================================================== + +exec crond -f -d 9 diff --git a/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/type b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/crond/type @@ -0,0 +1 @@ +longrun diff --git a/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/dependencies.d/base b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/dependencies.d/base new file mode 100644 index 00000000000..e69de29bb2d diff --git a/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish new file mode 100644 index 00000000000..4a4c070f1bb --- /dev/null +++ b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish @@ -0,0 +1,27 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Take down the S6 supervision tree when daemon fails +# ============================================================================== +# shellcheck disable=SC2155 +readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode + fi + [[ "${exit_code_signal}" -eq 15 ]] && exec /run/s6/basedir/bin/halt +elif [[ "${exit_code_service}" -ne 0 ]]; then + if [[ "${exit_code_container}" -eq 0 ]]; then + echo "${exit_code_service}" > /run/s6-linux-init-container-results/exitcode + fi + exec /run/s6/basedir/bin/halt +fi diff --git a/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/run b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/run new file mode 100644 index 00000000000..b04196a3e56 --- /dev/null +++ b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/run @@ -0,0 +1,57 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start nginx service +# ============================================================================== + +set -e + +bashio::log.info "Merging options & variables for template" +# shellcheck disable=SC2046 +JSON_CONF=$(jq --arg port $(bashio::core.port) \ + '({options: .}) + ({variables: {port: $port}})' \ + /data/options.json) +bashio::log.info "Generating nginx.conf from template in /etc/nginx/nginx.conf.gtpl" +# shellcheck disable=SC2086 +echo $JSON_CONF | tempio \ + -template /etc/nginx/nginx.conf.gtpl \ + -out /etc/nginx.conf + +DHPARAMS_PATH=/data/dhparams.pem + +CLOUDFLARE_CONF=/data/cloudflare.conf + +# Generate dhparams +if ! bashio::fs.file_exists "${DHPARAMS_PATH}"; then + bashio::log.info "Generating dhparams (this will take some time)..." + openssl dhparam -dsaparam -out "$DHPARAMS_PATH" 4096 > /dev/null +fi + +if bashio::config.true 'cloudflare'; then + # Generate cloudflare.conf + if ! bashio::fs.file_exists "${CLOUDFLARE_CONF}"; then + bashio::log.info "Creating 'cloudflare.conf' for real visitor IP address..." + echo "# Cloudflare IP addresses" > $CLOUDFLARE_CONF; + echo "" >> $CLOUDFLARE_CONF; + + echo "# - IPv4" >> $CLOUDFLARE_CONF; + for i in $(curl https://www.cloudflare.com/ips-v4); do + echo "set_real_ip_from ${i};" >> $CLOUDFLARE_CONF; + done + + echo "" >> $CLOUDFLARE_CONF; + echo "# - IPv6" >> $CLOUDFLARE_CONF; + for i in $(curl https://www.cloudflare.com/ips-v6); do + echo "set_real_ip_from ${i};" >> $CLOUDFLARE_CONF; + done + + echo "" >> $CLOUDFLARE_CONF; + echo "real_ip_header CF-Connecting-IP;" >> $CLOUDFLARE_CONF; + fi +fi + +# start server +bashio::log.info "Running nginx..." +stat "/ssl/$(bashio::config 'certfile')" -c %y > /tmp/certificate_timestamp +exec nginx -c /etc/nginx.conf < /dev/null diff --git a/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/type b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/type @@ -0,0 +1 @@ +longrun diff --git a/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/crond b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/crond new file mode 100644 index 00000000000..e69de29bb2d diff --git a/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/nginx b/nginx_proxy/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/nginx new file mode 100644 index 00000000000..e69de29bb2d diff --git a/nginx_proxy/translations/en.yaml b/nginx_proxy/translations/en.yaml new file mode 100644 index 00000000000..3720821495a --- /dev/null +++ b/nginx_proxy/translations/en.yaml @@ -0,0 +1,34 @@ +--- +configuration: + domain: + name: Domain + description: The domain name to use for the proxy. + hsts: + name: HSTS + description: >- + Value for the HSTS HTTP header to send. If empty, the header is not sent. + certfile: + name: Certificate File + description: >- + The certificate file to use in the `/ssl` directory. + keyfile: + name: Private Key File + description: Private Private Key File to use in the `/ssl` directory. + cloudflare: + name: CloudFlare + description: >- + If enabled, configure Nginx with a list of IP addresses directly from + Cloudflare that will be used for `set_real_ip_from` directive Nginx + config. + customize: + name: Customize + description: >- + See the Documentation tab for more information about these options. + real_ip_from: + name: Real IP from (enables PROXY protocol) + description: >- + Configures Nginx to use TCP Proxy Protocol, + specifies what IP to trust TLS upstream requests from. +network: + 443/tcp: HTTPS (SSL) Port + 80/tcp: HTTP (non-SSL) Port diff --git a/openthread_border_router/0001-channel-monitor-disable-by-default.patch b/openthread_border_router/0001-channel-monitor-disable-by-default.patch new file mode 100644 index 00000000000..702ecd13cfd --- /dev/null +++ b/openthread_border_router/0001-channel-monitor-disable-by-default.patch @@ -0,0 +1,32 @@ +From 2d67b5d8d711e61551a28cac522484fd5cbc4982 Mon Sep 17 00:00:00 2001 +From: Stefan Agner +Date: Sun, 7 Jan 2024 00:35:53 +0100 +Subject: [PATCH] [channel-monitor] disable by default + +Leave the channel monitor disabled by default. The impact on production +systems is not entirly clear. The channel scan could lead to missed +packets. Disabling by default allows to enable the feature at compile +time so developers and users can enable it at runtime for testing. + +Signed-off-by: Stefan Agner +--- + src/core/thread/thread_netif.cpp | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/src/core/thread/thread_netif.cpp b/src/core/thread/thread_netif.cpp +index 8e6848832..c79660de8 100644 +--- a/src/core/thread/thread_netif.cpp ++++ b/src/core/thread/thread_netif.cpp +@@ -59,9 +59,6 @@ void ThreadNetif::Up(void) + + // Enable the MAC just in case it was disabled while the Interface was down. + Get().SetEnabled(true); +-#if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE +- IgnoreError(Get().Start()); +-#endif + Get().Start(); + + mIsUp = true; +-- +2.45.2 + diff --git a/openthread_border_router/CHANGELOG.md b/openthread_border_router/CHANGELOG.md new file mode 100644 index 00000000000..0573b2df9ed --- /dev/null +++ b/openthread_border_router/CHANGELOG.md @@ -0,0 +1,245 @@ +# Changelog + +## 2.13.0 +- Bump to OTBR POSIX version b067e5ac (2025-01-13 22:32:22 -0500) +- Bump universal-silabs-flasher to 0.0.28 +- Remove dataset deletion REST API backwards compatibility patch. The minimum Core version for this add-on is now 2023.9.0 + +## 2.12.4 + +- Fix OTBR addon does not start after updating containerd.io to 1.7.24-1 + +## 2.12.3 + +- Enable recovery mechanism from "radio tx timeout" errors +- Increase the number of mesh header fragmentation tag entries to address + "Failed to get forwarded frame priority" notice messages in logs. Note that + these types of messages are non-critical (default priority will be applied in + that case). +- Make some compile time configurations via project header file + +## 2.12.2 + +- Update flasher script to work with Home Assistant Yellow with CM5 + +## 2.12.1 +- Fix possible race condition between otbr-agent-configure and otbr-agent-rest-discovery + services causing failed startup ([#3826](https://github.com/home-assistant/addons/issues/3826)) + +## 2.12.0 +- Bump universal-silabs-flasher to 0.0.23 +- Bump OTBR firmwares to latest versions +- Bump to OTBR POSIX version b041fa52daa (2024-11-14 08:18:28 -0800) +- Add radio firmware version to discovery information + +## 2.11.1 + +- Fix issue with USB TI CC2652 based devices + +## 2.11.0 + +- Bump to OTBR POSIX version ff7227ea9a2 (2024-09-25 14:54:08 -0700) +- Make log output unbuffered +- Avoid ipset errors when firewall is disabled + +## 2.10.0 + +- Bump to OTBR POSIX version b66cabfaa0 (2024-08-14 08:01:56 -0700) +- Avoid OTBR Web spamming system console +- Bump universal SiLabs flasher to 0.0.22 + +## 2.9.1 + +- Abort firmware flasher if network device is selected + +## 2.9.0 + +- Avoid triggering reset/boot loader on TI CC2652 based devices + +## 2.8.0 + +- Bump to OTBR POSIX version 41474ce29a (2024-06-21 08:41:31 -0700) + +## 2.7.0 + +- Support auto firmware updates for Sonoff ZBDongle-E +- Support auto firmware updates for SMLIGHT SLZB-07 +- Bump universal SiLabs flasher to 0.0.20 + +## 2.6.0 + +- Add support for network sockets using socat + +## 2.5.1 + +- Support Home Assistant Connect ZBT-1. + +## 2.5.0 + +- Bump to OTBR POSIX version 2279c02f3c (2024-02-28 22:36:55 -0800) +- Bump base image to Debian bookworm + +## 2.4.7 + +- Better fix for container shutdown in case of OTBR agent failures + +## 2.4.6 + +- Bump to OTBR POSIX version 9bdaa91016 (2024-02-15 08:50:34 -0800) +- Bump universal SiLabs flasher to 0.0.18 +- Fix container shutdown in case OTBR agent fails to startup +- Shutdown mDNS daemon after OTBR agent (allows the OTBR service to + properly sign off on the network) + +## 2.4.5 + +- Set default transmit power on startup +- Enable DNS when NAT64 is enabled +- Bump universal SiLabs flasher to 0.0.17 +- Bump to OTBR POSIX version 13d583e361 (2024-01-26 09:51:26 -0800) + +## 2.4.4 + +- Fix Thread network interface (wpan0) route metric + This fixes devices becoming unreachable when operating the OTBR with other TBRs +- Bump to OTBR POSIX version 02421b0ea6 (2024-01-19 15:58:03 -0800) + +## 2.4.3 + +- Enable TREL support on infrastructure link +- Enable Channel Monitor support (disabled by default) +- Bump to OTBR POSIX version 657e775cd9 (2024-01-05 17:10:13 -0800) + +## 2.4.2 + +- Update firmare for Home Assistant SkyConnect and Yellow to the latest version + built from Gecko SDK v4.4.0.0. +- Bump universal SiLabs flasher to 0.0.16 + +## 2.4.1 + +- Fix NAT64 enable script + +## 2.4.0 + +- Enable TREL +- Enable NAT64 (disabled by default) +- Bump to OTBR POSIX version 27ed99f375 (2023-12-13 10:11:52 -0800) +- Bump universal SiLabs flasher to 0.0.15 +- Shutdown add-on on otbr-agent crash (use Supervisor Watchdog functionality + for automatic restarts) + +## 2.3.2 + +- Bump to OTBR POSIX version 9e50efa8de (2023-08-23 21:28:30 -0700) + This updates mDNSResponder to 1790.80.10 + +## 2.3.1 + +- Update firmare for Home Assistant SkyConnect and Yellow to the latest version + built from Gecko SDK v4.3.1.0. + +## 2.3.0 + +- Bump to OTBR POSIX version 8d12b242db (2023-07-13 20:00:34 +0200) + This update includes the new REST API to reset the OTBR +- Bump universal SiLabs flasher to 0.0.13 +- Use add-on hostname to connect to OTBR REST API + +## 2.2.0 + +- Update firmare for Home Assistant SkyConnect and Yellow to the latest version + built from Gecko SDK v4.3.0.0. + +## 2.1.0 + +- Add REST API patches to fix a bugs and support deleting datasets + +## 2.0.0 + +- Bump to OTBR POSIX version f46f68956b (2023-05-23 09:28:30 -0700) + This update includes the new REST API part of upstream OTBR + +## 1.2.0 + +- Fix firmware flashing on Home Assistant Yellow +- Bump universal SiLabs flasher to 0.0.12 +- Bump to OTBR POSIX version cbeaf817c5 (2023-03-29 11:06:31 -0700) +- Don't start Web interface unnecessarily + +## 1.1.0 + +- Automatically flash firmware for Home Assistant SkyConnect and Yellow +- Update serial port defaults to match latest firmware builds +- Drop armv7 support + +## 1.0.0 + +- Bump to OTBR POSIX version d83fee189a (2023-02-28 08:48:56 -0800) +- Remove Web UI via ingress (expose ports to use the Web UI, see documentation) +- Change vendor name to "Home Assistant" and product name to Silicon Labs + Multiprotocol" (used in OTBR mDNS/DNS-SD announcments) +- Set default baudrate 115200 correctly +- Let the OTBR REST API listen on local interface only by default +- Fix REST API to correctly set the Connection HTTP header +- Fix REST API to return an HTTP compliant status line +- Add OTBR discovery support + +## 0.3.0 + +- Bump to OTBR POSIX version 079bbce34a (2022-12-22 19:00:41 -0800) +- Add REST API with full active and pending dataset as well as state support +- Avoid start error in case multiple primary interfaces are returned +- Add fine grained OTBR log level control +- Fix service stop (finish) scripts + +## 0.2.6 + +- Accept IPv6 forwarding explicitly (required for HAOS 9.x) +- Add egress firewall rules for forwarding if firewall is enabled + +## 0.2.5 + +- Bump to OTBR POSIX version 110eb2507c (2022-11-24 14:36:14 -0800) + +## 0.2.4 + +- Bump to OTBR POSIX version 0e15296792 (2022-11-07 12:33:00 +0100) + +## 0.2.3 + +- Fix Firewall shutdown + +## 0.2.2 + +- Bump to OTBR POSIX version 9fea68cfbe (2022-06-03 11:53:19 -0700) +- Use s6-overlay v3 style services + +## 0.2.1 + +- Fix missing common script + +## 0.2.0 + +- Support OpenThread Border Router firewall to avoid unnecessary traffic in the + OpenThread network. + +## 0.1.4 + +- Enable OpenThread diagnostic mode + +## 0.1.3 + +- Fix startup without hardware flow control + +## 0.1.2 + +- Bump OTBR to ot-br-posix git f8399eb08/openthread git 7dfde1f12 + +## 0.1.1 + +- Add baudrate and hardware flow control configurations + +## 0.1.0 + +- initial version diff --git a/openthread_border_router/DOCS.md b/openthread_border_router/DOCS.md new file mode 100644 index 00000000000..7ec95d6ae70 --- /dev/null +++ b/openthread_border_router/DOCS.md @@ -0,0 +1,105 @@ +# Home Assistant Add-on: OpenThread Border Router + +## Installation + +Follow these steps to get the add-on installed on your system: + +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons, Backup & Supervisor** -> **Add-on Store**. +2. Click on the top right menu and "Repository" +3. Add "https://github.com/home-assistant/addons" to add the "Home Assistant Add-on Repository for Development" repository. +4. Find the "OpenThread Border Router" add-on and click it. +5. Click on the "INSTALL" button. + +## How to use + +You will need a 802.15.4 capable radio supported by OpenThread. Home Assistant +Yellow as well as Home Assistant SkyConnect/Connect ZBT-1 are both capable to run +OpenThread. This add-on automatically installs the necessary firmware on these systems. + +If you are using Home Assistant Yellow, choose `/dev/ttyAMA1` as device. + +### Alternative radios + +The website [openthread.io maintains a list of supported platforms][openthread-platforms] +lists other Thread capable radios. A well documented Radio for development is the +Nordic Semiconductor [nRF52840 Dongle][nordic-nrf52840-dongle]. The Dongle needs +a recent version of the OpenThread RCP firmware. +[This article][nordic-nrf52840-dongle-install] outlines the steps to install the +RCP firmware for the nRF52840 Dongle. + +Once the firmware is loaded follow the following steps: + +1. Select the correct `device` in the add-on configuration tab and press `Save`. +2. Start the add-on. + +### OpenThread Border Router + +This add-on makes your Home Assistant installation an OpenThread Border Router +(OTBR). The border router can be used to comission Matter devices which connect +through Thread. Home Assistant Core will automatically detect this add-on and +create a new integration named "Open Thread Border Router". With Home Assistant +Core 2023.3 and newer the OTBR will get configured automatically. The Thread +integration allows to inspect the network configuration. + +### Web interface (advanced) + +There is also a web interface provided by the OTBR. However, the web +interface has caveats (e.g. forming a network does not generate an off-mesh +routable IPv6 prefix which causes changing IPv6 addressing on first add-on +restart). It is still possible to enable the web interface for debugging +purpose. Make sure to expose both the Web UI port and REST API port (the +latter needs to be on port 8081) on the host interface. To do so, click on +"Show disabled ports" and enter a port (e.g. 8080) in the OpenThread Web UI +and 8081 in the OpenThread REST API port field). + +## Configuration + +Add-on configuration: + +| Configuration | Description | +|--------------------|--------------------------------------------------------| +| device (mandatory) | Serial port where the OpenThread RCP Radio is attached | +| baudrate | Serial port baudrate (depends on firmware) | +| flow_control | If hardware flow control should be enabled (depends on firmware) | +| autoflash_firmware | Automatically install/update firmware (Home Assistant SkyConnect/Yellow) | +| otbr_log_level | Set the log level of the OpenThread BorderRouter Agent | +| firewall | Enable OpenThread Border Router firewall to block unnecessary traffic | +| nat64 | Enable NAT64 to allow Thread devices accessing IPv4 addresses | +| network_device | IP address and port to connect to a network-based RCP (see below) | + +> [!WARNING] +> The OTBR expects the RCP connected radio to be on a reliable link such as +> UART or SPI. Using TCP/IP to reach a remote RCP radio breaks this assumption. +> If the TCP/IP connection fails, the OTBR will not shutdown cleanly and leave +> stale routes in your network. This will lead to Thread devices to be +> potentially unreachable for up to 30 minutes (route lifetime) even when other +> routers are available. +> +> The RCP protocol is not designed to be transferred over an IP network: It is +> a timing-sensitive protocol. You might experience Thread issues if your +> network link has excessive latencies. As Thread is networking capable, +> running a Thread border router on the system the RCP radio is plugged in is +> recommended. + +> [!NOTE] +> When using a network device, you still need to set a dummy serial port device, e.g. `/dev/ttyS3`. + +## Support + +Got questions? + +You have several options to get them answered: + +- The [Home Assistant Discord Chat Server][discord]. +- The Home Assistant [Community Forum][forum]. +- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit] + +In case you've found a bug, please [open an issue on our GitHub][issue]. + +[discord]: https://discord.gg/c5DvZ4e +[forum]: https://community.home-assistant.io +[reddit]: https://reddit.com/r/homeassistant +[issue]: https://github.com/home-assistant/addons/issues +[openthread-platforms]: https://openthread.io/platforms +[nordic-nrf52840-dongle]: https://www.nordicsemi.com/Products/Development-hardware/nrf52840-dongle +[nordic-nrf52840-dongle-install]: https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/protocols/thread/tools.html#configuring_a_radio_co-processor diff --git a/openthread_border_router/Dockerfile b/openthread_border_router/Dockerfile new file mode 100644 index 00000000000..a758d34377b --- /dev/null +++ b/openthread_border_router/Dockerfile @@ -0,0 +1,110 @@ +ARG BUILD_FROM +FROM $BUILD_FROM + +ARG BUILD_ARCH +ARG OTBR_VERSION +ARG UNIVERSAL_SILABS_FLASHER + +# Set shell +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +ENV BORDER_ROUTING 1 +ENV BACKBONE_ROUTER 1 +ENV PLATFORM debian +ENV RELEASE 1 +ENV WEB_GUI 1 +ENV REST_API 1 +ENV DHCPV6_PD_REF 0 +ENV DOCKER 1 + +COPY 0001-channel-monitor-disable-by-default.patch /usr/src +COPY openthread-core-ha-config-posix.h /usr/src +# Required and installed (script/bootstrap) can be removed after build +ENV OTBR_BUILD_DEPS build-essential ninja-build cmake wget ca-certificates \ + libreadline-dev libncurses-dev libcpputest-dev libdbus-1-dev libavahi-common-dev \ + libavahi-client-dev libboost-dev libboost-filesystem-dev libboost-system-dev \ + libnetfilter-queue-dev + +# Installed during build (script/bootstrap) but unused in our configuration +ENV OTBR_UNUSED_DEBS libavahi-client3 avahi-daemon rsyslog + +WORKDIR /usr/src + +# Install npm/nodejs for WebUI before calling script/bootstrap to avoid +# systemd getting pulled in +RUN \ + set -x \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + iproute2 \ + python3 \ + python3-pip \ + lsb-release \ + netcat-openbsd \ + socat \ + sudo \ + git \ + nodejs \ + npm \ + && git clone --depth 1 -b main \ + https://github.com/openthread/ot-br-posix.git \ + && cd ot-br-posix \ + && git fetch origin ${OTBR_VERSION} \ + && git checkout ${OTBR_VERSION} \ + && git submodule update --init \ + && ./script/bootstrap \ + && ( \ + cd third_party/openthread/repo \ + && patch -p1 < /usr/src/0001-channel-monitor-disable-by-default.patch \ + && cp /usr/src/openthread-core-ha-config-posix.h . \ + ) \ + # Mimic rt_tables_install \ + && echo "88 openthread" >> /etc/iproute2/rt_tables \ + # Mimic otbr_install \ + && (./script/cmake-build \ + -DBUILD_TESTING=OFF \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DOTBR_FEATURE_FLAGS=ON \ + -DOTBR_DNSSD_DISCOVERY_PROXY=ON \ + -DOTBR_SRP_ADVERTISING_PROXY=ON \ + -DOTBR_MDNS=mDNSResponder \ + -DOTBR_VERSION= \ + -DOT_PACKAGE_VERSION= \ + -DOTBR_DBUS=OFF \ + -DOT_POSIX_RCP_BUS_UART=ON \ + -DOT_LINK_RAW=1 \ + -DOTBR_VENDOR_NAME="Home Assistant" \ + -DOTBR_PRODUCT_NAME="OpenThread Border Router" \ + -DOTBR_WEB=ON \ + -DOTBR_BORDER_ROUTING=ON \ + -DOTBR_REST=ON \ + -DOTBR_BACKBONE_ROUTER=ON \ + -DOTBR_TREL=ON \ + -DOTBR_NAT64=ON \ + -DOT_POSIX_NAT64_CIDR="192.168.255.0/24" \ + -DOTBR_DNS_UPSTREAM_QUERY=ON \ + -DOT_CHANNEL_MONITOR=ON \ + -DOT_COAP=OFF \ + -DOT_COAPS=OFF \ + -DOT_DNS_CLIENT_OVER_TCP=OFF \ + -DOT_THREAD_VERSION=1.3 \ + -DOT_PROJECT_CONFIG="../openthread-core-ha-config-posix.h" \ + -DOT_RCP_RESTORATION_MAX_COUNT=2 \ + && cd build/otbr/ \ + && ninja \ + && ninja install) \ + && pip install --break-system-packages \ + universal-silabs-flasher==${UNIVERSAL_SILABS_FLASHER} \ + && apt-get purge -y --auto-remove \ + git \ + nodejs \ + npm \ + ${OTBR_BUILD_DEPS} \ + ${OTBR_UNUSED_DEBS} \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /usr/src/* + +COPY rootfs / + +ENV \ + S6_STAGE2_HOOK=/etc/s6-overlay/scripts/enable-check.sh diff --git a/openthread_border_router/README.md b/openthread_border_router/README.md new file mode 100644 index 00000000000..2bfd79cfac6 --- /dev/null +++ b/openthread_border_router/README.md @@ -0,0 +1,19 @@ +# Home Assistant Add-on: OpenThread Border Router Add-on + +OpenThread Border Router add-on. The add-on uses the upstream OpenThread +Border Router implementation and wraps it as an add-on for Home Assistant. + +**NOTE:** This requires a supported 802.15.4 capable radio with OpenThread +RCP firmware. If you are using [Home Assistant Yellow](https://www.home-assistant.io/yellow/) or [Home Assistant Connect ZBT-1](https://www.home-assistant.io/connectzbt1/) (previously called SkyConnect) then +the correct firmware is automatically installed. + +![Supports aarch64 Architecture][aarch64-shield] +![Supports amd64 Architecture][amd64-shield] + +## About + +This add-on allows you to form or join a Thread network and make Home Assistant +a Thread Border Router. + +[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg +[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg diff --git a/openthread_border_router/build.yaml b/openthread_border_router/build.yaml new file mode 100644 index 00000000000..8bf57d2054f --- /dev/null +++ b/openthread_border_router/build.yaml @@ -0,0 +1,7 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base-debian:bookworm + amd64: ghcr.io/home-assistant/amd64-base-debian:bookworm +args: + OTBR_VERSION: b067e5ac5f8b3e92750df24922017eee2bc0fa04 + UNIVERSAL_SILABS_FLASHER: 0.0.28 diff --git a/openthread_border_router/config.yaml b/openthread_border_router/config.yaml new file mode 100644 index 00000000000..3e982a32837 --- /dev/null +++ b/openthread_border_router/config.yaml @@ -0,0 +1,50 @@ +--- +version: 2.13.0 +slug: openthread_border_router +name: OpenThread Border Router +description: OpenThread Border Router add-on +url: >- + https://github.com/home-assistant/addons/tree/master/openthread_border_router +arch: + - aarch64 + - amd64 +homeassistant: 2023.9.0 +gpio: true +hassio_api: true +discovery: + - otbr +# IPC is only used within the Add-on +host_ipc: false +host_network: true +host_uts: true +privileged: + - IPC_LOCK + - NET_ADMIN +devices: + - /dev/net/tun +image: homeassistant/{arch}-addon-otbr +init: false +options: + device: null + baudrate: "460800" + flow_control: true + autoflash_firmware: true + otbr_log_level: notice + firewall: true + nat64: false +ports: + 8080/tcp: null + 8081/tcp: null +ports_description: + 8080/tcp: OpenThread Web port + 8081/tcp: OpenThread REST API port +schema: + device: device(subsystem=tty) + baudrate: list(57600|115200|230400|460800|921600) + flow_control: bool + network_device: str? + autoflash_firmware: bool + otbr_log_level: list(debug|info|notice|warning|error|critical|alert|emergency) + firewall: bool + nat64: bool +startup: services diff --git a/openthread_border_router/icon.png b/openthread_border_router/icon.png new file mode 100644 index 00000000000..86148a1bd4a Binary files /dev/null and b/openthread_border_router/icon.png differ diff --git a/openthread_border_router/logo.png b/openthread_border_router/logo.png new file mode 100644 index 00000000000..c80bce24065 Binary files /dev/null and b/openthread_border_router/logo.png differ diff --git a/openthread_border_router/openthread-core-ha-config-posix.h b/openthread_border_router/openthread-core-ha-config-posix.h new file mode 100644 index 00000000000..70431aa0e82 --- /dev/null +++ b/openthread_border_router/openthread-core-ha-config-posix.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef OPENTHREAD_CORE_HA_CONFIG_POSIX_H_ +#define OPENTHREAD_CORE_HA_CONFIG_POSIX_H_ + +/** + * This header file defines the OpenThread core configuration options for + * Home Assistant with POSIX platform. + */ + +/** + * It seems that routes learned through IPv6 Neighbor Discovery Protocol + * get a metric of 128 when NetworkManager is used. Make sure the + * OpenThread network interface's own route is lower than that, to ensure + * that the local radio is preferred over learned routes. + */ +#define OPENTHREAD_POSIX_CONFIG_NETIF_PREFIX_ROUTE_METRIC 64 + +/** + * Increase delay aware queue management entry list size from its default of + * 16 to 64. This is to avoid/decrease the number of "Failed to get forwarded + * frame priority" notice messages. + */ +#define OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_FRAG_TAG_ENTRY_LIST_SIZE 64 + +#endif /* OPENTHREAD_CORE_HA_CONFIG_POSIX_H_ */ diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/banner/type b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/banner/type new file mode 100644 index 00000000000..bdd22a1850a --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/banner/type @@ -0,0 +1 @@ +oneshot diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/banner/up b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/banner/up new file mode 100644 index 00000000000..dc292313ac5 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/banner/up @@ -0,0 +1 @@ +/etc/s6-overlay/scripts/banner.sh diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/mdns/finish b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/mdns/finish new file mode 100755 index 00000000000..92b89c6b491 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/mdns/finish @@ -0,0 +1,7 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +#============================================================================== +# mDNSResponder finish script +#============================================================================== +bashio::log.info "mDNS ended with exit code ${1} (signal ${2})..." diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/mdns/run b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/mdns/run new file mode 100755 index 00000000000..6affe2c5577 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/mdns/run @@ -0,0 +1,12 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start mDNSResponder daemon +# ============================================================================== +bashio::log.info "Starting mDNS Responder..." + +# mdnsd runs as daemon except when using debug mode. We prefer non-daemon, so +# start in debug by default. It seems nto to generate a vast amount of +# messages. +exec /usr/sbin/mdnsd -debug diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/mdns/type b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/mdns/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/mdns/type @@ -0,0 +1 @@ +longrun diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-configure/dependencies.d/otbr-agent b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-configure/dependencies.d/otbr-agent new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-configure/type b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-configure/type new file mode 100644 index 00000000000..bdd22a1850a --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-configure/type @@ -0,0 +1 @@ +oneshot diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-configure/up b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-configure/up new file mode 100755 index 00000000000..0737177921a --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-configure/up @@ -0,0 +1 @@ +/etc/s6-overlay/scripts/otbr-agent-configure.sh diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/dependencies.d/otbr-agent b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/dependencies.d/otbr-agent new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/dependencies.d/otbr-agent-configure b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/dependencies.d/otbr-agent-configure new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/type b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/type new file mode 100644 index 00000000000..bdd22a1850a --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/type @@ -0,0 +1 @@ +oneshot diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/up b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/up new file mode 100755 index 00000000000..75f80eec7d5 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/up @@ -0,0 +1 @@ +/etc/s6-overlay/scripts/otbr-agent-rest-discovery.sh diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/data/check b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/data/check new file mode 100755 index 00000000000..662155dbcd4 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/data/check @@ -0,0 +1,6 @@ +#!/bin/bash + +# Check if openthread socket exists +mapfile -t < /tmp/otbr-agent-rest-api +test -S /run/openthread-wpan0.sock && nc -z "${MAPFILE[@]}" +exit diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/dependencies.d/banner b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/dependencies.d/banner new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/dependencies.d/base b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/dependencies.d/base new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/dependencies.d/mdns b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/dependencies.d/mdns new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/dependencies.d/universal-silabs-flasher b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/dependencies.d/universal-silabs-flasher new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/finish b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/finish new file mode 100755 index 00000000000..7ece6a29d75 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/finish @@ -0,0 +1,65 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +#============================================================================== +# OpenThread BorderRouter Daemon finish script +#============================================================================== +if test "$1" -eq 256 ; then + e=$((128 + $2)) +else + e="$1" +fi + +if test "$e" -ne 0; then + bashio::log.warning "otbr-agent exited with code $e (by signal $2)." +else + bashio::log.info "otbr-agent exited with code $e (by signal $2)." +fi + +# shellcheck disable=SC1091 +. /etc/s6-overlay/scripts/otbr-agent-common + +ipset_destroy_if_exist() +{ + # The ipset seems to be in use by the kernel for a brief period, + # retry destroying it + while ipset list -n "$1" 2> /dev/null; do + ipset destroy "$1" || true + done +} + +# shellcheck disable=SC2154,SC2086 +while ip6tables -C FORWARD -o $thread_if -j $otbr_forward_ingress_chain 2> /dev/null; do + # shellcheck disable=SC2086 + ip6tables -D FORWARD -o $thread_if -j $otbr_forward_ingress_chain +done + +# shellcheck disable=SC2086 +if ip6tables -L $otbr_forward_ingress_chain 2> /dev/null; then + ip6tables -w -F $otbr_forward_ingress_chain + ip6tables -w -X $otbr_forward_ingress_chain +fi + +ipset_destroy_if_exist otbr-ingress-deny-src +ipset_destroy_if_exist otbr-ingress-deny-src-swap +ipset_destroy_if_exist otbr-ingress-allow-dst +ipset_destroy_if_exist otbr-ingress-allow-dst-swap + +# shellcheck disable=SC2154,SC2086 +while ip6tables -C FORWARD -i $thread_if -j $otbr_forward_egress_chain 2> /dev/null; do + ip6tables -D FORWARD -i $thread_if -j $otbr_forward_egress_chain +done + +# shellcheck disable=SC2086 +if ip6tables -L $otbr_forward_egress_chain 2> /dev/null; then + ip6tables -w -F $otbr_forward_egress_chain + ip6tables -w -X $otbr_forward_egress_chain +fi +bashio::log.info "OTBR firewall teardown completed." + +if test "$e" -ne 0; then + echo "$e" > /run/s6-linux-init-container-results/exitcode + /run/s6/basedir/bin/halt + # Consider any otbr-agent exit as permanent failure according to s6 + exit 125 +fi diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/notification-fd b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/notification-fd new file mode 100644 index 00000000000..00750edc07d --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/notification-fd @@ -0,0 +1 @@ +3 diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/run b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/run new file mode 100755 index 00000000000..af84f245307 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/run @@ -0,0 +1,148 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# OpenThread BorderRouter start script +# ============================================================================== + +# shellcheck disable=SC1091 +. /etc/s6-overlay/scripts/otbr-agent-common + +declare backbone_if +declare device +declare baudrate +declare flow_control +declare otbr_log_level +declare otbr_log_level_int +declare otbr_rest_listen +declare otbr_rest_listen_port + +backbone_if="$(bashio::api.supervisor 'GET' '/network/info' '' 'first(.interfaces[] | select (.primary == true)) .interface')" +device=$(bashio::config 'device') + +if bashio::config.has_value 'network_device'; then + device="/tmp/ttyOTBR" +fi + +baudrate=$(bashio::config 'baudrate') +flow_control="" + +if bashio::config.true 'flow_control'; then + flow_control="&uart-flow-control" +else + flow_control="&uart-init-deassert" +fi + +otbr_log_level=$(bashio::string.lower "$(bashio::config otbr_log_level)") +case "${otbr_log_level}" in + debug) + otbr_log_level_int="7" + ;; + info) + otbr_log_level_int="6" + ;; + notice) + otbr_log_level_int="5" + ;; + warning) + otbr_log_level_int="4" + ;; + error) + otbr_log_level_int="3" + ;; + critical) + otbr_log_level_int="2" + ;; + alert) + otbr_log_level_int="1" + ;; + emergency) + otbr_log_level_int="0" + ;; + *) + bashio::exit.nok "Unknown otbr_log_level: ${otbr_log_level}" + ;; +esac + +# shellcheck disable=SC2086 +if [ -z ${backbone_if} ]; then + bashio::log.warning "No primary network interface found! Using static eth0." + backbone_if="eth0" +fi + +# shellcheck disable=SC2015 +mkdir -p /data/thread && ln -sft /var/lib /data/thread || bashio::exit.nok "Could not create directory /var/lib/thread to store Thread data." + +# We compile the OTBR with firewall support, so otbr-agent tries to update the +# ipsets. Therefor, create ipsets always to avoid errors from otbr-agent. Just +# the ipsets won't have an effect in practice when the firewall is disabled. +ipset create -exist otbr-ingress-deny-src hash:net family inet6 +ipset create -exist otbr-ingress-deny-src-swap hash:net family inet6 +ipset create -exist otbr-ingress-allow-dst hash:net family inet6 +ipset create -exist otbr-ingress-allow-dst-swap hash:net family inet6 + +if bashio::config.true 'firewall'; then + bashio::log.info "Setup OTBR firewall..." +# shellcheck disable=SC2086,SC2154 + ip6tables -N $otbr_forward_ingress_chain +# shellcheck disable=SC2086,SC2154 + ip6tables -I FORWARD 1 -o $thread_if -j $otbr_forward_ingress_chain + + # shellcheck disable=SC2086 + ip6tables -A $otbr_forward_ingress_chain -m pkttype --pkt-type unicast -i ${thread_if} -j DROP + # shellcheck disable=SC2086 + ip6tables -A $otbr_forward_ingress_chain -m set --match-set otbr-ingress-deny-src src -j DROP + # shellcheck disable=SC2086 + ip6tables -A $otbr_forward_ingress_chain -m set --match-set otbr-ingress-allow-dst dst -j ACCEPT + # shellcheck disable=SC2086 + ip6tables -A $otbr_forward_ingress_chain -m pkttype --pkt-type unicast -j DROP + # shellcheck disable=SC2086 + ip6tables -A $otbr_forward_ingress_chain -j ACCEPT + + # shellcheck disable=SC2086,SC2154 + ip6tables -N $otbr_forward_egress_chain + # shellcheck disable=SC2086 + ip6tables -I FORWARD 2 -i $thread_if -j $otbr_forward_egress_chain + # shellcheck disable=SC2086 + ip6tables -A $otbr_forward_egress_chain -j ACCEPT +else + # Make sure ip6tables (as used by Docker) allow IP forwarding + ip6tables -P FORWARD ACCEPT + # HAOS 9.3 and earlier (for 9.4 accept is the default so this won't do anything) + ip6tables-legacy -P FORWARD ACCEPT +fi + +if bashio::config.true 'nat64'; then + # shellcheck disable=SC2086 + iptables -t mangle -A PREROUTING -i ${thread_if} -j MARK --set-mark 0x1001 + iptables -t nat -A POSTROUTING -m mark --mark 0x1001 -j MASQUERADE + # shellcheck disable=SC2086 + iptables -t filter -A FORWARD -o ${backbone_if} -j ACCEPT + # shellcheck disable=SC2086 + iptables -t filter -A FORWARD -i ${backbone_if} -j ACCEPT +fi + +otbr_rest_listen="::" +otbr_rest_listen_port="$(bashio::addon.port 8081)" + +# If user port is not set, listen on local interface only +if ! bashio::var.has_value "${otbr_rest_listen_port}"; then + otbr_rest_listen="$(bashio::addon.ip_address)" + otbr_rest_listen_port="8081" +elif [ "${otbr_rest_listen_port}" != "8081" ]; then + bashio::log.warning "Custom OpenThread REST API port is not supported. Using 8081." + otbr_rest_listen_port="8081" +fi + +# Store REST API listen information for check script +echo "${otbr_rest_listen}" > /tmp/otbr-agent-rest-api +echo "${otbr_rest_listen_port}" >> /tmp/otbr-agent-rest-api + +bashio::log.info "Starting otbr-agent..." +# shellcheck disable=SC2086 +exec s6-notifyoncheck -d -s 300 -w 300 -n 0 stdbuf -oL \ + "/usr/sbin/otbr-agent" -I ${thread_if} -B "${backbone_if}" \ + --rest-listen-address "${otbr_rest_listen}" \ + -d${otbr_log_level_int} -v -s \ + "spinel+hdlc+uart://${device}?uart-baudrate=${baudrate}${flow_control}" \ + "trel://${backbone_if}" diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/type b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/type @@ -0,0 +1 @@ +longrun diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/dependencies.d/otbr-agent b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/dependencies.d/otbr-agent new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/finish b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/finish new file mode 100755 index 00000000000..2035d588936 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/finish @@ -0,0 +1,7 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +#============================================================================== +# OpenThread BorderRouter web interface finish script +#============================================================================== +bashio::log.info "otbr-web ended with exit code ${1} (signal ${2})..." diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/run b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/run new file mode 100755 index 00000000000..ac681f1838c --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/run @@ -0,0 +1,12 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start OpenThread BorderRouter web interface +# ============================================================================== +bashio::log.info "Starting otbr-web..." +declare otbr_web_port + +otbr_web_port="$(bashio::addon.port 8080)" + +exec stdbuf -oL /usr/sbin/otbr-web -I wpan0 -d6 -s -p "${otbr_web_port}" diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/type b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/type @@ -0,0 +1 @@ +longrun diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/data/check b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/data/check new file mode 100755 index 00000000000..b41abdafe79 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/data/check @@ -0,0 +1,4 @@ +#!/bin/sh + +test -c /tmp/ttyOTBR +exit diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/notification-fd b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/notification-fd new file mode 100644 index 00000000000..00750edc07d --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/notification-fd @@ -0,0 +1 @@ +3 diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/run b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/run new file mode 100755 index 00000000000..c81a9ef86f2 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/run @@ -0,0 +1,15 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start socat TCP client for OTBR agent daemon +# ============================================================================== + +declare network_device + +network_device=$(bashio::config 'network_device') + +bashio::log.info "Starting socat TCP client for OTBR daemon..." +exec s6-notifyoncheck -d -s 300 -w 300 \ + "/usr/bin/socat" -d pty,raw,echo=0,link=/tmp/ttyOTBR,ignoreeof \ + "tcp:${network_device}" diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/type b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/socat-otbr-tcp/type @@ -0,0 +1 @@ +longrun diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/dependencies.d/banner b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/dependencies.d/banner new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/notification-fd b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/notification-fd new file mode 100644 index 00000000000..00750edc07d --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/notification-fd @@ -0,0 +1 @@ +3 diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/type b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/type new file mode 100644 index 00000000000..bdd22a1850a --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/type @@ -0,0 +1 @@ +oneshot diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/up b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/up new file mode 100644 index 00000000000..56e09fe7678 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/up @@ -0,0 +1 @@ +/etc/s6-overlay/scripts/universal-silabs-flasher-up diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/mdns b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/mdns new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/otbr-agent b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/otbr-agent new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/otbr-agent-configure b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/otbr-agent-configure new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/otbr-agent-rest-discovery b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/otbr-agent-rest-discovery new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/otbr-web b/openthread_border_router/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/otbr-web new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openthread_border_router/rootfs/etc/s6-overlay/scripts/banner.sh b/openthread_border_router/rootfs/etc/s6-overlay/scripts/banner.sh new file mode 100755 index 00000000000..074dc4179e5 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/scripts/banner.sh @@ -0,0 +1,38 @@ +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash +# ============================================================================== +# Home Assistant Community Add-on: Base Images +# Displays a simple add-on banner on startup +# ============================================================================== +if bashio::supervisor.ping; then + bashio::log.blue \ + '-----------------------------------------------------------' + bashio::log.blue " Add-on: $(bashio::addon.name)" + bashio::log.blue " $(bashio::addon.description)" + bashio::log.blue \ + '-----------------------------------------------------------' + + bashio::log.blue " Add-on version: $(bashio::addon.version)" + if bashio::var.true "$(bashio::addon.update_available)"; then + bashio::log.magenta ' There is an update available for this add-on!' + bashio::log.magenta \ + " Latest add-on version: $(bashio::addon.version_latest)" + bashio::log.magenta ' Please consider upgrading as soon as possible.' + else + bashio::log.green ' You are running the latest version of this add-on.' + fi + + bashio::log.blue " System: $(bashio::info.operating_system)" \ + " ($(bashio::info.arch) / $(bashio::info.machine))" + bashio::log.blue " Home Assistant Core: $(bashio::info.homeassistant)" + bashio::log.blue " Home Assistant Supervisor: $(bashio::info.supervisor)" + + bashio::log.blue \ + '-----------------------------------------------------------' + bashio::log.blue \ + ' Please, share the above information when looking for help' + bashio::log.blue \ + ' or support in, e.g., GitHub, forums or the Discord chat.' + bashio::log.blue \ + '-----------------------------------------------------------' +fi diff --git a/openthread_border_router/rootfs/etc/s6-overlay/scripts/enable-check.sh b/openthread_border_router/rootfs/etc/s6-overlay/scripts/enable-check.sh new file mode 100755 index 00000000000..1b38bffe06a --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/scripts/enable-check.sh @@ -0,0 +1,23 @@ +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash +# ============================================================================== +# Disable OTBR Web if necessary ports are not exposed +# ============================================================================== + +if bashio::var.has_value "$(bashio::addon.port 8080)" \ + && bashio::var.has_value "$(bashio::addon.port 8081)"; then + bashio::log.info "Web UI and REST API port are exposed, starting otbr-web." +else + rm /etc/s6-overlay/s6-rc.d/user/contents.d/otbr-web + bashio::log.info "The otbr-web is disabled." +fi + +# ============================================================================== +# Enable socat-otbr-tcp service if needed +# ============================================================================== + +if bashio::config.has_value 'network_device'; then + touch /etc/s6-overlay/s6-rc.d/user/contents.d/socat-otbr-tcp + touch /etc/s6-overlay/s6-rc.d/otbr-agent/dependencies.d/socat-otbr-tcp + bashio::log.info "Enabled socat-otbr-tcp." +fi diff --git a/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-common b/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-common new file mode 100644 index 00000000000..e4d4669a9e4 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-common @@ -0,0 +1,9 @@ +#!/bin/sh + +declare thread_if +declare otbr_forward_ingress_chain +declare otbr_forward_egress_chain +thread_if="wpan0" +otbr_forward_ingress_chain="OTBR_FORWARD_INGRESS" +otbr_forward_egress_chain="OTBR_FORWARD_EGRESS" + diff --git a/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-configure.sh b/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-configure.sh new file mode 100755 index 00000000000..d8f96785e92 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-configure.sh @@ -0,0 +1,15 @@ +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash +# ============================================================================== +# Configure OTBR depending on add-on settings +# ============================================================================== + +if bashio::config.true 'nat64'; then + bashio::log.info "Enabling NAT64." + ot-ctl nat64 enable + ot-ctl dns server upstream enable +fi + +# To avoid asymmetric link quality the TX power from the controller should not +# exceed that of what other Thread routers devices typically use. +ot-ctl txpower 6 diff --git a/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-rest-discovery.sh b/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-rest-discovery.sh new file mode 100755 index 00000000000..190bfd7dd45 --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/scripts/otbr-agent-rest-discovery.sh @@ -0,0 +1,20 @@ +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash +# ============================================================================== +# Send OTBR discovery information to Home Assistant +# ============================================================================== +declare config + +config=$(bashio::var.json \ + host "$(bashio::addon.hostname)" \ + port "^8081" \ + device "$(bashio::config 'device')" \ + firmware "$(ot-ctl rcp version | head -n 1)" \ +) + +# Send discovery info +if bashio::discovery "otbr" "${config}" > /dev/null; then + bashio::log.info "Successfully sent discovery information to Home Assistant." +else + bashio::log.error "Discovery message to Home Assistant failed!" +fi diff --git a/openthread_border_router/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up b/openthread_border_router/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up new file mode 100755 index 00000000000..fc632d8139f --- /dev/null +++ b/openthread_border_router/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up @@ -0,0 +1,95 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start universal-silabs-flasher if requested +# ============================================================================== + +# shellcheck disable=SC2034 +declare autoflash_firmware +declare device +declare firmware +declare usb_device_path +declare usb_manufacturer +declare usb_product +declare gpio_reset_flag + +function exit_no_firmware { + bashio::log.warning "No firmware found for the selected device, assuming firmware is installed." + exit 0 +} + +# Function to check if the device is Home Assistant Yellow +function is_home_assistant_yellow { + # First, ensure the device is /dev/ttyAMA1 + if [ "${device}" != "/dev/ttyAMA1" ]; then + return 1 + fi + + # Check the known paths for Home Assistant Yellow + local paths=( + "/sys/devices/platform/soc/fe201800.serial/tty/ttyAMA1" + "/sys/devices/platform/axi/1000120000.pcie/1f0003c000.serial/tty/ttyAMA1" + ) + for path in "${paths[@]}"; do + if [ -d "${path}" ]; then + return 0 + fi + done + return 1 +} + +device=$(bashio::config 'device') +gpio_reset_flag="" + +if bashio::config.false 'autoflash_firmware'; then + bashio::log.info "Flashing firmware is disabled" + exit 0 +fi + +if bashio::config.has_value 'network_device'; then + bashio::log.info "Network device is selected, skipping firmware flashing" + exit 0 +fi + +if is_home_assistant_yellow; then + bashio::log.info "Detected Home Assistant Yellow" + firmware="yellow_openthread_rcp_2.4.4.0_GitHub-7074a43e4_gsdk_4.4.4.gbl" + gpio_reset_flag="--bootloader-reset yellow" +else + # Check device manufacturer/product information + # shellcheck disable=SC2046,SC2086 + usb_device_path=$(realpath /sys/class/tty/$(readlink /sys/class/tty/$(basename ${device}) | sed 's:/[^/]*tty[^/]*::g' )/../) + if [ ! -f "${usb_device_path}/idProduct" ]; then + bashio::log.info "The selected serial port is not a USB device." + exit_no_firmware + fi + + if [ ! -f "${usb_device_path}/manufacturer" ] || [ ! -f "${usb_device_path}/product" ]; then + bashio::log.info "USB device is missing manufacturer or product name." + exit_no_firmware + fi + + usb_manufacturer=$(cat "${usb_device_path}/manufacturer") + usb_product=$(cat "${usb_device_path}/product") + + bashio::log.info "Checking ${device} identifying ${usb_product} from ${usb_manufacturer}." + if [[ "${usb_manufacturer}" == "Nabu Casa" && "${usb_product}" == "SkyConnect"* ]]; then + firmware="skyconnect_openthread_rcp_2.4.4.0_GitHub-7074a43e4_gsdk_4.4.4.gbl" + elif [[ "${usb_manufacturer}" == "Nabu Casa" && "${usb_product}" == "Home Assistant Connect ZBT-1"* ]]; then + firmware="skyconnect_openthread_rcp_2.4.4.0_GitHub-7074a43e4_gsdk_4.4.4.gbl" + elif [[ "${usb_manufacturer}" == "ITEAD" && "${usb_product}" == "SONOFF Zigbee 3.0 USB Dongle Plus V2" ]]; then + firmware="ot-rcp-v2.4.2.0-zbdonglee-460800.gbl" + gpio_reset_flag="--bootloader-reset sonoff" + elif [[ "${usb_manufacturer}" == "SMLIGHT" && "${usb_product}" == "SMLIGHT SLZB-07" ]]; then + firmware="ot-rcp-v2.4.2.0-slzb-07-460800.gbl" + gpio_reset_flag="--bootloader-reset slzb07" + else + exit_no_firmware + fi +fi + +bashio::log.info "Starting universal-silabs-flasher with ${device}" +# shellcheck disable=SC2086 +exec universal-silabs-flasher --device ${device} ${gpio_reset_flag} \ + flash --ensure-exact-version --allow-cross-flashing --firmware "/root/${firmware}" diff --git a/openthread_border_router/rootfs/root/ot-rcp-v2.4.2.0-slzb-07-460800.gbl b/openthread_border_router/rootfs/root/ot-rcp-v2.4.2.0-slzb-07-460800.gbl new file mode 100644 index 00000000000..81f92cb757c Binary files /dev/null and b/openthread_border_router/rootfs/root/ot-rcp-v2.4.2.0-slzb-07-460800.gbl differ diff --git a/openthread_border_router/rootfs/root/ot-rcp-v2.4.2.0-zbdonglee-460800.gbl b/openthread_border_router/rootfs/root/ot-rcp-v2.4.2.0-zbdonglee-460800.gbl new file mode 100644 index 00000000000..6b62389913f Binary files /dev/null and b/openthread_border_router/rootfs/root/ot-rcp-v2.4.2.0-zbdonglee-460800.gbl differ diff --git a/openthread_border_router/rootfs/root/skyconnect_openthread_rcp_2.4.4.0_GitHub-7074a43e4_gsdk_4.4.4.gbl b/openthread_border_router/rootfs/root/skyconnect_openthread_rcp_2.4.4.0_GitHub-7074a43e4_gsdk_4.4.4.gbl new file mode 100644 index 00000000000..2b7b9cb91d3 Binary files /dev/null and b/openthread_border_router/rootfs/root/skyconnect_openthread_rcp_2.4.4.0_GitHub-7074a43e4_gsdk_4.4.4.gbl differ diff --git a/openthread_border_router/rootfs/root/yellow_openthread_rcp_2.4.4.0_GitHub-7074a43e4_gsdk_4.4.4.gbl b/openthread_border_router/rootfs/root/yellow_openthread_rcp_2.4.4.0_GitHub-7074a43e4_gsdk_4.4.4.gbl new file mode 100644 index 00000000000..c20313baa94 Binary files /dev/null and b/openthread_border_router/rootfs/root/yellow_openthread_rcp_2.4.4.0_GitHub-7074a43e4_gsdk_4.4.4.gbl differ diff --git a/openthread_border_router/translations/en.yaml b/openthread_border_router/translations/en.yaml new file mode 100644 index 00000000000..8f55f9b9951 --- /dev/null +++ b/openthread_border_router/translations/en.yaml @@ -0,0 +1,39 @@ +--- +configuration: + device: + name: Device + description: The serial port where the OpenThread RCP radio is attached. + baudrate: + name: Baudrate + description: >- + The serial port baudrate used to communicate with the Silicon Labs radio. + flow_control: + name: Hardware flow control + description: Enable hardware flow control for serial port. + network_device: + name: Network Device + description: >- + when connecting to a device via sockets (takes precedence + over above configuration). Not recommended! See documentation for more + information. + autoflash_firmware: + name: Automatically flash firmware + description: >- + Automatically flash OpenThread RCP firmware on Home Assistant Yellow and + SkyConnect/Connect ZBT-1. + otbr_log_level: + name: OpenThread Border Router agent log level + description: >- + Set logging level of the OpenThread Border Router agent (otbr-agent). + firewall: + name: OTBR firewall + description: >- + Use OpenThread Border Router firewall to block unnecessary traffic. + nat64: + name: NAT64 + description: >- + Enable IPv6 to IPv4 network address translation. This allows Thread + devices to communicate with devices on the Internet. +network: + 8080/tcp: OpenThread Web port + 8081/tcp: OpenThread REST API port diff --git a/openwakeword/CHANGELOG.md b/openwakeword/CHANGELOG.md new file mode 100644 index 00000000000..7f4f96145ea --- /dev/null +++ b/openwakeword/CHANGELOG.md @@ -0,0 +1,54 @@ +# Changelog + +## 1.10.0 + +- Upgrade to wyoming 1.5.3 +- Add wake word phrase + +## 1.8.2 + +- Add `armv7` image to `build.yaml` + +## 1.8.1 + +- Remove batching from wake word processing since not all models support it + +## 1.8.0 + +- Include fix for potential deadlock +- Only process wake words that a client requests +- armv7 support + +## 1.7.1 + +- Always use wake word file name as key (avoid duplicate model loading) + +## 1.7.0 + +- Make wake word loading completely dynamic (new models are automatically discovered) +- Rebuild Wyoming info message on each request +- Deprecate --model + +## 1.6.0 + +- Automatically search /share/openwakeword for custom models (`*.tflite`) +- Change share permissions to read only + +## 1.5.1 + +- Include language in wake word descriptions + +## 1.5.0 + +- Remove webrtc (done in core now) +- Remove audio options related to webrtc +- Remove wake word option (dynamic loading) +- Dynamically load wake word models + +## 1.4.0 + +- Add noise suppression/auto gain with webrtc + +## 1.1.0 + +- Initial release diff --git a/openwakeword/DOCS.md b/openwakeword/DOCS.md new file mode 100644 index 00000000000..63b21436a67 --- /dev/null +++ b/openwakeword/DOCS.md @@ -0,0 +1,61 @@ +# Home Assistant Add-on: openWakeWord + +## Installation + +Follow these steps to get the add-on installed on your system: + +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. +2. Find the "openWakeWord" add-on and click it. +3. Click on the "INSTALL" button. + +## How to use + +After this add-on is installed and running, it will be automatically discovered +by the Wyoming integration in Home Assistant. To finish the setup, +click the following my button: + +[![Open your Home Assistant instance and start setting up a new integration.](https://my.home-assistant.io/badges/config_flow_start.svg)](https://my.home-assistant.io/redirect/config_flow_start/?domain=wyoming) + +Alternatively, you can install the Wyoming integration manually, see the +[Wyoming integration documentation](https://www.home-assistant.io/integrations/wyoming/) +for more information. + +## Configuration + +### Option: `threshold` + +Activation threshold (0-1), where higher means fewer activations. See trigger +level for the relationship between activations and wake word detections. + +### Option: `trigger_level` + +Number of activations before a detection is registered. A higher trigger level +means fewer detections. + +### Option: `debug_logging` + +Enable debug logging. Useful for seeing satellite connections and each wake word detection in the logs. + +## Custom Wake Word Models + +The add-on will automatically load custom wake word models from the `/share/openwakeword` directory. [Install the Samba add-on](https://www.home-assistant.io/common-tasks/supervised/#installing-and-using-the-samba-add-on) to copy wake word model files (`*.tflite`) to this directory. + +After adding new models to `/share/openwakeword`, make sure to reload any Wyoming integrations for openWakeWord. Once reloaded, the new wake words will be available to select in the Voice Assistants settings page. + +## Support + +Got questions? + +You have several options to get them answered: + +- The [Home Assistant Discord Chat Server][discord]. +- The Home Assistant [Community Forum][forum]. +- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit] + +In case you've found an bug, please [open an issue on our GitHub][issue]. + +[discord]: https://discord.gg/c5DvZ4e +[forum]: https://community.home-assistant.io +[issue]: https://github.com/home-assistant/addons/issues +[reddit]: https://reddit.com/r/homeassistant +[repository]: https://github.com/hassio-addons/repository diff --git a/openwakeword/Dockerfile b/openwakeword/Dockerfile new file mode 100644 index 00000000000..c4c3858b89b --- /dev/null +++ b/openwakeword/Dockerfile @@ -0,0 +1,36 @@ +ARG BUILD_FROM +FROM ${BUILD_FROM} + +# Set shell +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +# Install openWakeWord +WORKDIR /usr/src +ARG WYOMING_OPENWAKEWORD_VERSION +ENV PIP_BREAK_SYSTEM_PACKAGES=1 + +RUN \ + apt-get update \ + && apt-get install -y --no-install-recommends \ + netcat-traditional \ + python3 \ + python3-pip \ + libopenblas0 \ + \ + && pip3 install --no-cache-dir -U \ + setuptools \ + wheel \ + && pip3 install --no-cache-dir \ + --extra-index-url https://www.piwheels.org/simple \ + "wyoming-openwakeword @ https://github.com/rhasspy/wyoming-openwakeword/archive/refs/tags/v${WYOMING_OPENWAKEWORD_VERSION}.tar.gz" \ + \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR / +COPY rootfs / + +HEALTHCHECK --start-period=10m \ + CMD echo '{ "type": "describe" }' \ + | nc -w 1 localhost 10400 \ + | grep -iq "openWakeWord" \ + || exit 1 diff --git a/openwakeword/README.md b/openwakeword/README.md new file mode 100644 index 00000000000..4496fd41817 --- /dev/null +++ b/openwakeword/README.md @@ -0,0 +1,15 @@ +# Home Assistant Add-on: openWakeWord + +![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armv7 Architecture][armv7-shield] + +Home Assistant add-on that uses [openWakeWord](https://github.com/dscripka/openwakeword) for wake word detection. + +Part of the [Year of Voice](https://www.home-assistant.io/blog/2022/12/20/year-of-voice/). + +Requires Home Assistant 2023.9 or later. + +[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg +[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg +[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg +[armhf-shield]: https://img.shields.io/badge/armhf-no-red.svg +[i386-shield]: https://img.shields.io/badge/i386-no-red.svg diff --git a/openwakeword/build.yaml b/openwakeword/build.yaml new file mode 100644 index 00000000000..e880a2dd014 --- /dev/null +++ b/openwakeword/build.yaml @@ -0,0 +1,10 @@ +--- +build_from: + amd64: ghcr.io/home-assistant/amd64-base-debian:bookworm + aarch64: ghcr.io/home-assistant/aarch64-base-debian:bookworm + armv7: ghcr.io/home-assistant/armv7-base-debian:bookworm +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io +args: + WYOMING_OPENWAKEWORD_VERSION: 1.10.0 diff --git a/openwakeword/config.yaml b/openwakeword/config.yaml new file mode 100644 index 00000000000..cb2254ef922 --- /dev/null +++ b/openwakeword/config.yaml @@ -0,0 +1,29 @@ +--- +version: 1.10.0 +slug: openwakeword +name: openWakeWord +description: openWakeWord using the Wyoming protocol +url: https://github.com/home-assistant/addons/blob/master/openwakeword +arch: + - amd64 + - aarch64 + - armv7 +init: false +discovery: + - wyoming +backup_exclude: + - "*.tflite" +map: + - share:ro +options: + threshold: 0.5 + trigger_level: 1 + debug_logging: false +schema: + threshold: float + trigger_level: int + debug_logging: bool +ports: + "10400/tcp": null +homeassistant: 2023.9.0.dev20230809 +image: homeassistant/{arch}-addon-openwakeword diff --git a/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/discovery/dependencies.d/openwakeword b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/discovery/dependencies.d/openwakeword new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/discovery/run b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/discovery/run new file mode 100755 index 00000000000..b584069e104 --- /dev/null +++ b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/discovery/run @@ -0,0 +1,25 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Sends discovery information to Home Assistant. +# ============================================================================== +declare config + +# Wait for openWakeWord to become available +bash -c \ + "until + echo '{ \"type\": \"describe\" }' + > /dev/tcp/localhost/10400; do sleep 0.5; + done" > /dev/null 2>&1 || true; + +config=$(\ + bashio::var.json \ + uri "tcp://$(hostname):10400" \ +) + +if bashio::discovery "wyoming" "${config}" > /dev/null; then + bashio::log.info "Successfully sent discovery information to Home Assistant." +else + bashio::log.error "Discovery message to Home Assistant failed!" +fi diff --git a/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/discovery/type b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/discovery/type new file mode 100644 index 00000000000..3d92b15f2d5 --- /dev/null +++ b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/discovery/type @@ -0,0 +1 @@ +oneshot \ No newline at end of file diff --git a/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/discovery/up b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/discovery/up new file mode 100755 index 00000000000..31b0a0205b5 --- /dev/null +++ b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/discovery/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/discovery/run \ No newline at end of file diff --git a/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/dependencies.d/base b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/dependencies.d/base new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/finish b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/finish new file mode 100755 index 00000000000..8558b9a95ea --- /dev/null +++ b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/finish @@ -0,0 +1,27 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Take down the S6 supervision tree when service fails +# s6-overlay docs: https://github.com/just-containers/s6-overlay +# ============================================================================== +# shellcheck disable=SC2155 +readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode + fi + [[ "${exit_code_signal}" -eq 15 ]] && exec /run/s6/basedir/bin/halt +elif [[ "${exit_code_service}" -ne 0 ]]; then + if [[ "${exit_code_container}" -eq 0 ]]; then + echo "${exit_code_service}" > /run/s6-linux-init-container-results/exitcode + fi + exec /run/s6/basedir/bin/halt +fi diff --git a/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/run b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/run new file mode 100755 index 00000000000..17431b97304 --- /dev/null +++ b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/run @@ -0,0 +1,19 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start openWakeWord service +# ============================================================================== +flags=() + +if bashio::config.true 'debug_logging'; then + flags+=('--debug') +fi + +# shellcheck disable=SC2068 +exec python3 -m wyoming_openwakeword \ + --uri 'tcp://0.0.0.0:10400' \ + --preload-model 'ok_nabu' \ + --custom-model-dir /share/openwakeword \ + --threshold "$(bashio::config 'threshold')" \ + --trigger-level "$(bashio::config 'trigger_level')" ${flags[@]} diff --git a/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/type b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/type new file mode 100644 index 00000000000..1780f9f44ef --- /dev/null +++ b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/openwakeword/type @@ -0,0 +1 @@ +longrun \ No newline at end of file diff --git a/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/discovery b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/discovery new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/openwakeword b/openwakeword/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/openwakeword new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openwakeword/translations/en.yaml b/openwakeword/translations/en.yaml new file mode 100644 index 00000000000..d8fe4733b35 --- /dev/null +++ b/openwakeword/translations/en.yaml @@ -0,0 +1,20 @@ +--- +configuration: + threshold: + name: Threshold + description: >- + Activation threshold (0-1), where higher means fewer activations. See + trigger level for the relationship between activations and wake word + detections. + trigger_level: + name: Trigger level + description: >- + Number of activations before a detection is registered. A higher trigger + level means fewer detections. + debug_logging: + name: Debug logging + description: >- + Enable debug logging. Useful for seeing each wake word detection in the + logs. +network: + 10400/tcp: openWakeWord Wyoming Protocol diff --git a/piper/CHANGELOG.md b/piper/CHANGELOG.md new file mode 100644 index 00000000000..b949ca18b04 --- /dev/null +++ b/piper/CHANGELOG.md @@ -0,0 +1,64 @@ +# Changelog + +## 1.5.2 + +- Add missing voices supported by Piper (gwryw_gogleddol, bryce, john, norman and paola) + +## 1.5.1 + +- Add voice for English: cori + +## 1.5.0 + +- Add voices for Persian: amir, gyro +- Add voice for Slovenian: artur +- Add voice for Turkish: fettah +- Add voices for French: tom, mls +- Add voice for Dutch: mls +- Add voice for German: mls + +## 1.4.0 + +- Add voices for Arabic (kareem), Hungarian (imre), English (libritts_r), and more +- Fix error when voice contains UTF-8 character (quote url) +- Fix missing "dataset" key error +- Fix unnecessary downloads due to /share + +## 1.3.2 + +- Add voices for Hungarian, Turkish, Portuguese, Slovak, and Czech +- Look for custom voices in `/share/piper` +- Add `upgrade_voices` and `debug_logging` options +- Upgrade to Debian bookworm + +## 1.2.0 + +- Upgrade to Piper 1.2 +- Add over 30 new voices +- Change voice format to `_--` +- Voices are downloaded from https://huggingface.co/rhasspy/piper-voices +- Add `max_piper_procs` option + +## 0.1.3 + +- Fix multi-line input +- Verify voice hashes on download +- Add 4 Icelandic voices + - `is-bui-medium` + - `is-salka-medium` + - `is-steinn-medium` + - `is-ugla-medium` +- Add 1 Russian voice + - `ru-irinia-medium` + +## 0.1.2 + +- Update list of available voices + +## 0.1.1 + +- Enable Wyoming protocol discovery + +## 0.1.0 + +- Initial release diff --git a/piper/DOCS.md b/piper/DOCS.md new file mode 100644 index 00000000000..7ffa39ed134 --- /dev/null +++ b/piper/DOCS.md @@ -0,0 +1,101 @@ +# Home Assistant Add-on: Piper + +## Installation + +Follow these steps to get the add-on installed on your system: + +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. +2. Find the "Piper" add-on and click it. +3. Click on the "INSTALL" button. + +## How to use + +After this add-on is installed and running, it will be automatically discovered +by the Wyoming integration in Home Assistant. To finish the setup, +click the following my button: + +[![Open your Home Assistant instance and start setting up a new integration.](https://my.home-assistant.io/badges/config_flow_start.svg)](https://my.home-assistant.io/redirect/config_flow_start/?domain=wyoming) + +Alternatively, you can install the Wyoming integration manually, see the +[Wyoming integration documentation](https://www.home-assistant.io/integrations/wyoming/) +for more information. + +## Configuration + +### Option: `voice` + +[Listen to voice samples](https://rhasspy.github.io/piper-samples/) + +Name of the Piper voice to use, such as `en_US-lessac-medium` (the default). +Voice models are automatically downloaded from https://huggingface.co/rhasspy/piper-voices/tree/v1.0.0 + +Voices are named according to the following scheme: `_--` +The `` portion comes from the dataset used to train the voice or the speaker's name if it was provided. + +A voice's quality comes in 4 different levels: + +- `x_low` - 16Khz, smallest/fastest +- `low` - 16Khz, fast +- `medium` - 22.05Khz, slower but better sounding +- `high` - 22.05Khz, slowest but best sounding + +On a Raspberry Pi 4, up to the `medium` models will run with usable speed. If audio quality is not a priority, prefer the `low` or `x-low` voices as they will be noticeably faster than `medium`. + +### Option: `speaker` + +Speaker number to use if the voice supports multiple speakers, such as [`en-us-libritts-high`](https://rhasspy.github.io/piper-samples/#en-us-libritts-high). + +By default, the first speaker (speaker 0) will be used. + +### Option: `length_scale` + +Speeds up or slows down the voice. A value of 1.0 means to use the voice's default speaking rate, with < 1.0 being faster and > 1.0 being slower. + +### Option: `noise_scale` + +Controls the variability of audio by adding noise during audio generation. The effect highly depends on the voice itself, but in general a value of 0 removes variability and values above 1 will start to degrade audio. + +### Option: `noise_w` + +Controls the variability of speaking cadence (phoneme widths). The effect highly depends on the voice itself, but in general a value of 0 removes variability and values above 1 produce extreme stutters and pauses. + +### Option: `max_piper_procs` + +Number of Piper processes to run simultaneously (default is 1). Each Piper process loads a single voice model into RAM, so using multiple voices at the same time requires: + +- Starting/stopping Piper processes as voices are used, or +- Running more Piper processes + +This add-on will start a Piper process for each requested voice up to `max_piper_procs`. After that, the least recently used voice will be stopped. +Increase `max_piper_procs` if you need to quickly switch between multiple voices, but beware that this will increase RAM usage by the add-on. + +### Option: `update_voices` + +Download the list of new voices automatically every time the add-on starts. You must also reload the Wyoming integration for Piper in Home Assistant to see new voices. + +### Option: `debug_logging` + +Print DEBUG level messages to the add-on's log. + +## Custom Voices + +Add custom voice files to the `/share/piper` directory. Each custom voice must include a model file (`.onnx`) and config file (`.onnx.json`). +See the [training guide](https://github.com/rhasspy/piper/blob/master/TRAINING.md) for details on how to train and export a custom voice. + +## Support + +Got questions? + +You have several options to get them answered: + +- The [Home Assistant Discord Chat Server][discord]. +- The Home Assistant [Community Forum][forum]. +- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit] + +In case you've found an bug, please [open an issue on our GitHub][issue]. + +[discord]: https://discord.gg/c5DvZ4e +[forum]: https://community.home-assistant.io +[issue]: https://github.com/home-assistant/addons/issues +[reddit]: https://reddit.com/r/homeassistant +[repository]: https://github.com/hassio-addons/repository diff --git a/piper/Dockerfile b/piper/Dockerfile new file mode 100644 index 00000000000..8969f0b8c32 --- /dev/null +++ b/piper/Dockerfile @@ -0,0 +1,41 @@ +ARG BUILD_FROM +FROM ${BUILD_FROM} + +# Set shell +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +# Install Piper +WORKDIR /usr/src +ARG BUILD_ARCH +ARG WYOMING_PIPER_VERSION +ARG BINARY_PIPER_VERSION +ENV PIP_BREAK_SYSTEM_PACKAGES=1 +RUN \ + apt-get update \ + && apt-get install -y --no-install-recommends \ + netcat-traditional \ + python3 \ + python3-pip \ + \ + && pip3 install --no-cache-dir -U \ + setuptools \ + wheel \ + && pip3 install --no-cache-dir \ + "wyoming-piper @ https://github.com/rhasspy/wyoming-piper/archive/refs/tags/v${WYOMING_PIPER_VERSION}.tar.gz" \ + \ + && ARCH="${BUILD_ARCH}" \ + && if [[ "${BUILD_ARCH}" = "aarch64" ]]; then ARCH="arm64"; fi \ + && curl -L -s \ + "https://github.com/rhasspy/piper/releases/download/v${BINARY_PIPER_VERSION}/piper_${ARCH}.tar.gz" \ + | tar -zxvf - -C /usr/share \ + \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR / +COPY rootfs / + +HEALTHCHECK --start-period=10m \ + CMD echo '{ "type": "describe" }' \ + | nc -w 1 localhost 10200 \ + | grep -q "piper" \ + || exit 1 diff --git a/piper/README.md b/piper/README.md new file mode 100644 index 00000000000..8bd711a1c4e --- /dev/null +++ b/piper/README.md @@ -0,0 +1,13 @@ +# Home Assistant Add-on: Piper + +![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] + +Home Assistant add-on that uses [piper](https://github.com/rhasspy/piper/) for text-to-speech. + +Part of the [Year of Voice](https://www.home-assistant.io/blog/2022/12/20/year-of-voice/). + +[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg +[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg +[armhf-shield]: https://img.shields.io/badge/armhf-no-red.svg +[armv7-shield]: https://img.shields.io/badge/armv7-no-red.svg +[i386-shield]: https://img.shields.io/badge/i386-no-red.svg diff --git a/piper/build.yaml b/piper/build.yaml new file mode 100644 index 00000000000..be1e3763e5d --- /dev/null +++ b/piper/build.yaml @@ -0,0 +1,10 @@ +--- +build_from: + amd64: ghcr.io/home-assistant/amd64-base-debian:bookworm + aarch64: ghcr.io/home-assistant/aarch64-base-debian:bookworm +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io +args: + WYOMING_PIPER_VERSION: 1.5.0 + BINARY_PIPER_VERSION: 1.2.0 diff --git a/piper/config.yaml b/piper/config.yaml new file mode 100644 index 00000000000..52df1f2c12a --- /dev/null +++ b/piper/config.yaml @@ -0,0 +1,39 @@ +--- +version: 1.5.2 +slug: piper +name: Piper +description: Text-to-speech with Piper +url: https://github.com/home-assistant/addons/blob/master/piper +arch: + - amd64 + - aarch64 +init: false +discovery: + - wyoming +backup_exclude: + - "*.onnx" +map: + - share +options: + voice: en_US-lessac-medium + speaker: 0 + length_scale: 1.0 + noise_scale: 0.667 + noise_w: 0.333 + max_piper_procs: 1 + debug_logging: false + update_voices: true +schema: + voice: | + list(ar_JO-kareem-low|ar_JO-kareem-medium|ca_ES-upc_ona-medium|ca_ES-upc_ona-x_low|ca_ES-upc_pau-x_low|cs_CZ-jirka-low|cs_CZ-jirka-medium|cy_GB-gwryw_gogleddol-medium|da_DK-talesyntese-medium|de_DE-eva_k-x_low|de_DE-karlsson-low|de_DE-kerstin-low|de_DE-mls-medium|de_DE-pavoque-low|de_DE-ramona-low|de_DE-thorsten_emotional-medium|de_DE-thorsten-high|de_DE-thorsten-low|de_DE-thorsten-medium|el_GR-rapunzelina-low|en_GB-alan-low|en_GB-alan-medium|en_GB-alba-medium|en_GB-aru-medium|en_GB-cori-high|en_GB-cori-medium|en_GB-jenny_dioco-medium|en_GB-northern_english_male-medium|en_GB-semaine-medium|en_GB-southern_english_female-low|en_GB-vctk-medium|en_US-amy-low|en_US-amy-medium|en_US-arctic-medium|en_US-bryce-medium|en_US-danny-low|en_US-hfc_female-medium|en_US-hfc_male-medium|en_US-joe-medium|en_US-john-medium|en_US-kathleen-low|en_US-kusal-medium|en_US-l2arctic-medium|en_US-lessac-high|en_US-lessac-low|en_US-lessac-medium|en_US-libritts-high|en_US-libritts_r-medium|en_US-norman-medium|en_US-ryan-high|en_US-ryan-low|en_US-ryan-medium|es_ES-carlfm-x_low|es_ES-davefx-medium|es_ES-mls_10246-low|es_ES-mls_9972-low|es_ES-sharvard-medium|es_MX-ald-medium|fa_IR-amir-medium|fa_IR-gyro-medium|fi_FI-harri-low|fi_FI-harri-medium|fr_FR-gilles-low|fr_FR-mls_1840-low|fr_FR-mls-medium|fr_FR-siwis-low|fr_FR-siwis-medium|fr_FR-tom-medium|fr_FR-upmc-medium|hu_HU-anna-medium|hu_HU-berta-medium|hu_HU-imre-medium|is_IS-bui-medium|is_IS-salka-medium|is_IS-steinn-medium|is_IS-ugla-medium|it_IT-paola-medium|it_IT-riccardo-x_low|ka_GE-natia-medium|kk_KZ-iseke-x_low|kk_KZ-issai-high|kk_KZ-raya-x_low|lb_LU-marylux-medium|ne_NP-google-medium|ne_NP-google-x_low|nl_BE-nathalie-medium|nl_BE-nathalie-x_low|nl_BE-rdh-medium|nl_BE-rdh-x_low|nl_NL-mls_5809-low|nl_NL-mls_7432-low|nl_NL-mls-medium|no_NO-talesyntese-medium|pl_PL-darkman-medium|pl_PL-gosia-medium|pl_PL-mc_speech-medium|pl_PL-mls_6892-low|pt_BR-edresson-low|pt_BR-faber-medium|pt_PT-tugão-medium|ro_RO-mihai-medium|ru_RU-denis-medium|ru_RU-dmitri-medium|ru_RU-irina-medium|ru_RU-ruslan-medium|sk_SK-lili-medium|sl_SI-artur-medium|sr_RS-serbski_institut-medium|sv_SE-nst-medium|sw_CD-lanfrica-medium|tr_TR-dfki-medium|tr_TR-fahrettin-medium|tr_TR-fettah-medium|uk_UA-lada-x_low|uk_UA-ukrainian_tts-medium|vi_VN-25hours_single-low|vi_VN-vais1000-medium|vi_VN-vivos-x_low|zh_CN-huayan-medium|zh_CN-huayan-x_low|ca-upc_ona-x-low|ca-upc_pau-x-low|da-nst_talesyntese-medium|de-eva_k-x-low|de-karlsson-low|de-kerstin-low|de-pavoque-low|de-ramona-low|de-thorsten-low|el-gr-rapunzelina-low|en-gb-alan-low|en-gb-southern_english_female-low|en-us-amy-low|en-us-danny-low|en-us-kathleen-low|en-us-lessac-low|en-us-lessac-medium|en-us-libritts-high|en-us-ryan-high|en-us-ryan-low|en-us-ryan-medium|es-carlfm-x-low|es-mls_10246-low|es-mls_9972-low|fi-harri-low|fr-gilles-low|fr-mls_1840-low|fr-siwis-low|fr-siwis-medium|is-bui-medium|is-salka-medium|is-steinn-medium|is-ugla-medium|it-riccardo_fasol-x-low|kk-iseke-x-low|kk-issai-high|kk-raya-x-low|ne-google-medium|ne-google-x-low|nl-mls_5809-low|nl-mls_7432-low|nl-nathalie-x-low|nl-rdh-medium|nl-rdh-x-low|no-talesyntese-medium|pl-mls_6892-low|pt-br-edresson-low|ru-irinia-medium|uk-lada-x-low|vi-25hours-single-low|vi-vivos-x-low|zh-cn-huayan-x-low) + speaker: int + length_scale: float + noise_scale: float + noise_w: float + max_piper_procs: int + debug_logging: bool + update_voices: bool +ports: + "10200/tcp": null +homeassistant: 2023.8.0.dev20230718 +image: homeassistant/{arch}-addon-piper diff --git a/piper/icon.png b/piper/icon.png new file mode 100644 index 00000000000..350c9419e0a Binary files /dev/null and b/piper/icon.png differ diff --git a/piper/logo.png b/piper/logo.png new file mode 100644 index 00000000000..f75f435c99f Binary files /dev/null and b/piper/logo.png differ diff --git a/piper/rootfs/etc/s6-overlay/s6-rc.d/discovery/dependencies.d/piper b/piper/rootfs/etc/s6-overlay/s6-rc.d/discovery/dependencies.d/piper new file mode 100644 index 00000000000..e69de29bb2d diff --git a/piper/rootfs/etc/s6-overlay/s6-rc.d/discovery/run b/piper/rootfs/etc/s6-overlay/s6-rc.d/discovery/run new file mode 100755 index 00000000000..17bf8e4c181 --- /dev/null +++ b/piper/rootfs/etc/s6-overlay/s6-rc.d/discovery/run @@ -0,0 +1,25 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Sends discovery information to Home Assistant. +# ============================================================================== +declare config + +# Wait for Piper to become available +bash -c \ + "until + echo '{ \"type\": \"describe\" }' + > /dev/tcp/localhost/10200; do sleep 0.5; + done" > /dev/null 2>&1 || true; + +config=$(\ + bashio::var.json \ + uri "tcp://$(hostname):10200" \ +) + +if bashio::discovery "wyoming" "${config}" > /dev/null; then + bashio::log.info "Successfully send discovery information to Home Assistant." +else + bashio::log.error "Discovery message to Home Assistant failed!" +fi \ No newline at end of file diff --git a/piper/rootfs/etc/s6-overlay/s6-rc.d/discovery/type b/piper/rootfs/etc/s6-overlay/s6-rc.d/discovery/type new file mode 100644 index 00000000000..3d92b15f2d5 --- /dev/null +++ b/piper/rootfs/etc/s6-overlay/s6-rc.d/discovery/type @@ -0,0 +1 @@ +oneshot \ No newline at end of file diff --git a/piper/rootfs/etc/s6-overlay/s6-rc.d/discovery/up b/piper/rootfs/etc/s6-overlay/s6-rc.d/discovery/up new file mode 100755 index 00000000000..31b0a0205b5 --- /dev/null +++ b/piper/rootfs/etc/s6-overlay/s6-rc.d/discovery/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/discovery/run \ No newline at end of file diff --git a/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/dependencies.d/base b/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/dependencies.d/base new file mode 100644 index 00000000000..e69de29bb2d diff --git a/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/finish b/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/finish new file mode 100755 index 00000000000..8558b9a95ea --- /dev/null +++ b/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/finish @@ -0,0 +1,27 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Take down the S6 supervision tree when service fails +# s6-overlay docs: https://github.com/just-containers/s6-overlay +# ============================================================================== +# shellcheck disable=SC2155 +readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode + fi + [[ "${exit_code_signal}" -eq 15 ]] && exec /run/s6/basedir/bin/halt +elif [[ "${exit_code_service}" -ne 0 ]]; then + if [[ "${exit_code_container}" -eq 0 ]]; then + echo "${exit_code_service}" > /run/s6-linux-init-container-results/exitcode + fi + exec /run/s6/basedir/bin/halt +fi diff --git a/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/run b/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/run new file mode 100755 index 00000000000..3b807607c44 --- /dev/null +++ b/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/run @@ -0,0 +1,28 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start Piper service +# ============================================================================== +flags=() +if bashio::config.true 'update_voices'; then + flags+=('--update-voices') +fi + +if bashio::config.true 'debug_logging'; then + flags+=('--debug') +fi + +# shellcheck disable=SC2068 +exec python3 -m wyoming_piper \ + --piper '/usr/share/piper/piper' \ + --uri 'tcp://0.0.0.0:10200' \ + --length-scale "$(bashio::config 'length_scale')" \ + --noise-scale "$(bashio::config 'noise_scale')" \ + --noise-w "$(bashio::config 'noise_w')" \ + --speaker "$(bashio::config 'speaker')" \ + --voice "$(bashio::config 'voice')" \ + --max-piper-procs "$(bashio::config 'max_piper_procs')" \ + --data-dir /data \ + --data-dir /share/piper \ + --download-dir /data ${flags[@]} diff --git a/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/type b/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/type new file mode 100644 index 00000000000..1780f9f44ef --- /dev/null +++ b/piper/rootfs/etc/s6-overlay/s6-rc.d/piper/type @@ -0,0 +1 @@ +longrun \ No newline at end of file diff --git a/piper/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/discovery b/piper/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/discovery new file mode 100644 index 00000000000..e69de29bb2d diff --git a/piper/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/piper b/piper/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/piper new file mode 100644 index 00000000000..e69de29bb2d diff --git a/piper/translations/en.yaml b/piper/translations/en.yaml new file mode 100644 index 00000000000..df874ab7482 --- /dev/null +++ b/piper/translations/en.yaml @@ -0,0 +1,47 @@ +--- +configuration: + voice: + name: Voice + description: >- + The Piper voice to use. Voices are named according to the following + scheme: `--`. + speaker: + name: Speaker + description: >- + Speaker number to use if the voice supports multiple speakers. + By default, the first speaker (speaker 0) will be used. + length_scale: + name: Length scale + description: >- + Speeds up or slows down the voice. A value of 1.0 means to use the voice's + default speaking rate, with < 1.0 being faster and > 1.0 being slower. + noise_scale: + name: Noise scale + description: >- + Controls the variability of audio by adding noise during audio generation. + The effect highly depends on the voice itself, but in general a value of 0 + removes variability and values above 1 will start to degrade audio. + noise_w: + name: Speaking cadence + description: >- + Controls the variability of speaking cadence (phoneme widths). The effect + highly depends on the voice itself, but in general a value of 0 removes + variability and values above 1 produce extreme stutters and pauses. + max_piper_procs: + name: Maximum Piper processes + description: >- + Number of Piper processes to run simultaneously (default is 1). Increase + if you need to quickly switch between multiple voices, but beware that + this will increase RAM usage by the add-on. + update_voices: + name: Update voices + description: >- + Download the list of new voices automatically every time the add-on + starts. You must also reload the Wyoming integration for Piper in Home + Assistant to see new voices. + debug_logging: + name: Debug logging + description: >- + Print DEBUG level messages to the add-on's log. +network: + 10200/tcp: Piper Wyoming Protocol diff --git a/rpc_shutdown/CHANGELOG.md b/rpc_shutdown/CHANGELOG.md index cc1836ffe1f..a38139102fc 100644 --- a/rpc_shutdown/CHANGELOG.md +++ b/rpc_shutdown/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## 2.5 + +- Update to Alpine 3.19 + +## 2.4 + +- Update to Alpine 3.17 + +## 2.3 + +- Allow '%' sign in the password + ## 2.2 - Set delay to zero when it is empty (to not break existing configurations) (bugfix) diff --git a/rpc_shutdown/DOCS.md b/rpc_shutdown/DOCS.md index d2e2a09fe23..0f69024ea7a 100644 --- a/rpc_shutdown/DOCS.md +++ b/rpc_shutdown/DOCS.md @@ -4,7 +4,7 @@ Follow these steps to get the add-on installed on your system: -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. 2. Find the "RPC Shutdown" add-on and click it. 3. Click on the "INSTALL" button. @@ -88,6 +88,6 @@ You have several options to get them answered: In case you've found a bug, please [open an issue on our GitHub][issue]. [forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues +[issue]: https://github.com/home-assistant/addons/issues [reddit]: https://reddit.com/r/homeassistant -[repository]: https://github.com/hassio-addons/repository \ No newline at end of file +[discord]: https://www.home-assistant.io/join-chat diff --git a/rpc_shutdown/build.yaml b/rpc_shutdown/build.yaml new file mode 100644 index 00000000000..039821f92e6 --- /dev/null +++ b/rpc_shutdown/build.yaml @@ -0,0 +1,10 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base:3.19 + amd64: ghcr.io/home-assistant/amd64-base:3.19 + armhf: ghcr.io/home-assistant/armhf-base:3.19 + armv7: ghcr.io/home-assistant/armv7-base:3.19 + i386: ghcr.io/home-assistant/i386-base:3.19 +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io diff --git a/rpc_shutdown/config.json b/rpc_shutdown/config.json deleted file mode 100644 index 623f72c2187..00000000000 --- a/rpc_shutdown/config.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "RPC Shutdown", - "version": "2.2", - "slug": "rpc_shutdown", - "description": "Shutdown Windows machines remotely", - "url": "https://github.com/home-assistant/hassio-addons/tree/master/rpc_shutdown", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "startup": "services", - "stdin": true, - "host_network": true, - "options": { - "computers": [ - { - "alias": "test-pc", - "address": "192.168.0.1", - "credentials": "user%password", - "delay": 0, - "message": "Home Assistant is shutting down this PC. This cannot be canceled. Please save your work!" - } - ] - }, - "schema": { - "computers": [ - { - "alias": "match(^[\\w-]*$)", - "address": "str", - "credentials": "match(^[^%]*(?:%[^%]*)?$)", - "delay": "int(0,600)?", - "message": "str?" - } - ] - }, - "image": "homeassistant/{arch}-addon-rpc_shutdown" -} diff --git a/rpc_shutdown/config.yaml b/rpc_shutdown/config.yaml new file mode 100644 index 00000000000..58cb902e23d --- /dev/null +++ b/rpc_shutdown/config.yaml @@ -0,0 +1,33 @@ +--- +version: "2.5" +slug: rpc_shutdown +name: RPC Shutdown +description: Shutdown Windows machines remotely +url: https://github.com/home-assistant/addons/tree/master/rpc_shutdown +arch: + - armhf + - armv7 + - aarch64 + - amd64 + - i386 +host_network: true +image: homeassistant/{arch}-addon-rpc_shutdown +options: + computers: + - address: 192.168.0.1 + alias: test-pc + credentials: user%password + delay: 0 + message: + Home Assistant is shutting down this PC. This cannot be canceled. Please + save your work! +schema: + computers: + - address: str + alias: match(^[\w-]*$) + credentials: match(^[^%]*(?:%.*)?$) + delay: int(0,600)? + message: str? +startup: services +stdin: true +init: false diff --git a/rpc_shutdown/data/run.sh b/rpc_shutdown/data/run.sh index 5a329a8d2f4..f3d5e2cec61 100755 --- a/rpc_shutdown/data/run.sh +++ b/rpc_shutdown/data/run.sh @@ -1,4 +1,5 @@ -#!/usr/bin/env bashio +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash set -e # Read from STDIN aliases to send shutdown @@ -27,7 +28,7 @@ while read -r input; do bashio::log.info "Shutdown $input -> $ADDRESS" if ! msg="$(net rpc shutdown -I "$ADDRESS" -U "$CREDENTIALS" -t "$DELAY" -C "$MESSAGE")"; then - bashio::log.error "Shutdown fails -> $msg" + bashio::log.error "Shutdown failed: $msg" fi done -done \ No newline at end of file +done diff --git a/rpc_shutdown/translations/en.yaml b/rpc_shutdown/translations/en.yaml new file mode 100644 index 00000000000..40520612eb3 --- /dev/null +++ b/rpc_shutdown/translations/en.yaml @@ -0,0 +1,6 @@ +--- +configuration: + computers: + name: Computers + description: >- + A list of computer objects to be able to shutdown from Home-Assistant. diff --git a/samba/CHANGELOG.md b/samba/CHANGELOG.md index 54edeee4ce2..ace5335f0f1 100644 --- a/samba/CHANGELOG.md +++ b/samba/CHANGELOG.md @@ -1,5 +1,86 @@ # Changelog +## 12.5.0 + +- Add the ability to enable and disable trying to become a local master browser on a subnet + +## 12.4.0 + +- Add the ability to enable and disable specific shares, improving user control over folder access + +## 12.3.3 + +- Enable Samba configurations to improve interoperability with Apple devices + +## 12.3.2 + +- Suppress benign idmap logged error + +## 12.3.1 + +- Handle passwords with backslash correctly + +## 12.3.0 + +- Upgrade Alpine Linux to 3.19 + +## 12.2.0 + +- Decrease Samba log level + +## 12.1.0 + +- Use the new Home Assistant folder for the `config` share +- Add support for accessing public add-on configurations + +## 12.0.0 + +- Temporary remove access to add-on config shares, until Supervisor 2023.11.2 has been rolled out stable +- Revert `config` share name change to avoid user facing change +- Adjust location of Home Assistant config to match latest dev/beta Supervisor +- Migrate add-on layout to S6 Overlay + +## 11.0.0 + +- The `config` share has been renamed to `homeassistant` to match upstream changes. +- Add support for accessing public add-on configurations +- Update to Alpine 3.18 +- Adds HEALTCHECK support + +## 10.0.2 + +- Enable IPv6 ULA and IPv4 link-local addresses by default + +## 10.0.1 + +- Update to Alpine 3.17 + +## 10.0.0 + +BREAKING CHANGE: Don't mangle filenames + +By default, Samba mangles filenames with special characters to ensure +compatibility with really old versions of Windows which have a very limited +charset for filenames. The add-on no longer does this as modern operating +systems do not have these restrictions. + +- Don't mangle filenames (fixes #2541) +- Upgrade Alpine Linux to 3.16 + +## 9.7.0 + +- Upgrade Alpine Linux to 3.15 +- Sign add-on with Codenotary Community Attestation Service (CAS) + +## 9.6.1 + +- Remove lo from interface list +- Exit with error if there are no supported interfaces to run Samba on + +## 9.6.0 + +- Run on all supported interfaces + ## 9.5.1 - Add `hassio_api` to add-on configuration @@ -55,4 +136,3 @@ ## 8.0.0 - Fix access to /backup - diff --git a/samba/DOCS.md b/samba/DOCS.md index 7cdee0d47a4..99ec6e1423c 100644 --- a/samba/DOCS.md +++ b/samba/DOCS.md @@ -4,7 +4,7 @@ Follow these steps to get the add-on installed on your system: -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. 2. Find the "Samba share" add-on and click it. 3. Click on the "INSTALL" button. @@ -12,9 +12,7 @@ Follow these steps to get the add-on installed on your system: 1. In the configuration section, set a username and password. You can specify any username and password; these are not related in any way to the login credentials you use to log in to Home Assistant or to log in to the computer with which you will use Samba share. -2. Save the configuration. -3. Start the add-on. -4. Check the add-on log output to see the result. +2. Review the enabled shares. Disable any you do not plan to use. Shares can be re-enabled later if needed. ## Connection @@ -25,7 +23,8 @@ This addon exposes the following directories over smb (samba): Directory | Description -- | -- `addons` | This is for your local add-ons. -`backup` | This is for your snapshots. +`addon_configs` | This is for the configuration files of your add-ons. +`backup` | This is for your backups. `config` | This is for your Home Assistant configuration. `media` | This is for local media files. `share` | This is for your data that is shared between add-ons and Home Assistant. @@ -37,13 +36,24 @@ Add-on configuration: ```yaml workgroup: WORKGROUP +local_master: true username: homeassistant password: YOUR_PASSWORD +enabled_shares: + - addons + - addon_configs + - backup + - config + - media + - share + - ssl allow_hosts: - 10.0.0.0/8 - 172.16.0.0/12 - 192.168.0.0/16 + - 169.254.0.0/16 - fe80::/10 + - fc00::/7 veto_files: - "._*" - ".DS_Store" @@ -55,6 +65,10 @@ compatibility_mode: false Change WORKGROUP to reflect your network needs. +### Option: `local_master` (required) + +Enable to try and become a local master browser on a subnet. + ### Option: `username` (required) The username you would like to use to authenticate with the Samba server. @@ -63,6 +77,10 @@ The username you would like to use to authenticate with the Samba server. The password that goes with the username configured for authentication. +### Option: `enabled_shares` (required) + +List of Samba shares that will be accessible. Any shares removed or commented out of the list will not be accessible. + ### Option: `allow_hosts` (required) List of hosts/networks allowed to access the shared folders. @@ -96,6 +114,6 @@ In case you've found a bug, please [open an issue on our GitHub][issue]. [discord]: https://discord.gg/c5DvZ4e [forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues +[issue]: https://github.com/home-assistant/addons/issues [reddit]: https://reddit.com/r/homeassistant [repository]: https://github.com/hassio-addons/repository diff --git a/samba/Dockerfile b/samba/Dockerfile index 5dede8ab72c..2c2d1fe505a 100644 --- a/samba/Dockerfile +++ b/samba/Dockerfile @@ -6,10 +6,7 @@ ENV LANG C.UTF-8 # Setup base RUN \ - apk add --no-cache \ - samba-common-tools \ - samba-server \ - \ + apk add --no-cache samba \ && mkdir -p /var/lib/samba \ && touch \ /etc/samba/lmhosts \ @@ -19,3 +16,6 @@ RUN \ # Copy data COPY rootfs / + +HEALTHCHECK \ + CMD smbclient -L '\\localhost' -U '%' -m SMB3 diff --git a/samba/build.json b/samba/build.json deleted file mode 100644 index 9376c79edca..00000000000 --- a/samba/build.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "build_from": { - "aarch64": "ghcr.io/home-assistant/aarch64-base:3.13", - "amd64": "ghcr.io/home-assistant/amd64-base:3.13", - "armhf": "ghcr.io/home-assistant/armhf-base:3.13", - "armv7": "ghcr.io/home-assistant/armv7-base:3.13", - "i386": "ghcr.io/home-assistant/i386-base:3.13" - } -} diff --git a/samba/build.yaml b/samba/build.yaml new file mode 100644 index 00000000000..039821f92e6 --- /dev/null +++ b/samba/build.yaml @@ -0,0 +1,10 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base:3.19 + amd64: ghcr.io/home-assistant/amd64-base:3.19 + armhf: ghcr.io/home-assistant/armhf-base:3.19 + armv7: ghcr.io/home-assistant/armv7-base:3.19 + i386: ghcr.io/home-assistant/i386-base:3.19 +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io diff --git a/samba/config.json b/samba/config.json deleted file mode 100644 index ece2b92077f..00000000000 --- a/samba/config.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "Samba share", - "version": "9.5.1", - "slug": "samba", - "description": "Expose Home Assistant folders with SMB/CIFS", - "url": "https://github.com/home-assistant/hassio-addons/tree/master/samba", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "startup": "services", - "init": false, - "hassio_api": true, - "host_network": true, - "map": [ - "config:rw", - "ssl:rw", - "addons:rw", - "share:rw", - "backup:rw", - "media:rw" - ], - "options": { - "workgroup": "WORKGROUP", - "username": "homeassistant", - "password": null, - "allow_hosts": [ - "10.0.0.0/8", - "172.16.0.0/12", - "192.168.0.0/16", - "fe80::/10" - ], - "veto_files": ["._*", ".DS_Store", "Thumbs.db", "icon?", ".Trashes"], - "compatibility_mode": false - }, - "schema": { - "workgroup": "str", - "username": "str", - "password": "password", - "allow_hosts": ["str"], - "veto_files": ["str"], - "compatibility_mode": "bool" - }, - "image": "homeassistant/{arch}-addon-samba" -} diff --git a/samba/config.yaml b/samba/config.yaml new file mode 100644 index 00000000000..b682678cdbc --- /dev/null +++ b/samba/config.yaml @@ -0,0 +1,65 @@ +--- +version: 12.5.0 +slug: samba +name: Samba share +description: Expose Home Assistant folders with SMB/CIFS +url: https://github.com/home-assistant/addons/tree/master/samba +codenotary: notary@home-assistant.io +arch: + - armhf + - armv7 + - aarch64 + - amd64 + - i386 +hassio_api: true +host_network: true +image: homeassistant/{arch}-addon-samba +init: false +map: + - addons:rw + - all_addon_configs:rw + - backup:rw + - homeassistant_config:rw + - media:rw + - share:rw + - ssl:rw +options: + username: homeassistant + password: null + workgroup: WORKGROUP + local_master: true + enabled_shares: + - addons + - addon_configs + - backup + - config + - media + - share + - ssl + compatibility_mode: false + veto_files: + - ._* + - .DS_Store + - Thumbs.db + - icon? + - .Trashes + allow_hosts: + - 10.0.0.0/8 + - 172.16.0.0/12 + - 192.168.0.0/16 + - 169.254.0.0/16 + - fe80::/10 + - fc00::/7 +schema: + username: str + password: password + workgroup: str + local_master: bool + enabled_shares: + - "match(^(?i:(addons|addon_configs|backup|config|media|share|ssl))$)" + compatibility_mode: bool + veto_files: + - str + allow_hosts: + - str +startup: services diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/dependencies.d/base b/samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/dependencies.d/base new file mode 100644 index 00000000000..e69de29bb2d diff --git a/samba/rootfs/etc/cont-init.d/samba.sh b/samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/run similarity index 57% rename from samba/rootfs/etc/cont-init.d/samba.sh rename to samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/run index e8345eaed09..422b1b6439d 100755 --- a/samba/rootfs/etc/cont-init.d/samba.sh +++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/run @@ -1,10 +1,12 @@ -#!/usr/bin/with-contenv bashio +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Prepare the Samba service for running # ============================================================================== declare password declare username -declare interface +declare -a interfaces=() export HOSTNAME # Check Login data @@ -12,20 +14,28 @@ if ! bashio::config.has_value 'username' || ! bashio::config.has_value 'password bashio::exit.nok "Setting a username and password is required!" fi +bashio::config.require "enabled_shares" "Samba is a tool for sharing folders. Starting it without sharing any folders defeats the purpose." + # Read hostname from API or setting default "hassio" HOSTNAME=$(bashio::info.hostname) if bashio::var.is_empty "${HOSTNAME}"; then bashio::log.warning "Can't read hostname, using default." HOSTNAME="hassio" fi +bashio::log.info "Hostname: ${HOSTNAME}" -# Get default interface -interface=$(bashio::network.name) - -bashio::log.info "Using hostname=${HOSTNAME} interface=${interface}" +# Get supported interfaces +for interface in $(bashio::network.interfaces); do + interfaces+=("${interface}") +done +if [ ${#interfaces[@]} -eq 0 ]; then + bashio::exit.nok 'No supported interfaces found to bind on.' +fi +bashio::log.info "Interfaces: $(printf '%s ' "${interfaces[@]}")" # Generate Samba configuration. -jq ".interface = \"${interface}\"" /data/options.json \ +jq ".interfaces = $(jq -c -n '$ARGS.positional' --args -- "${interfaces[@]}") | + .enabled_shares.[] |= ascii_downcase" /data/options.json \ | tempio \ -template /usr/share/tempio/smb.gtpl \ -out /etc/samba/smb.conf @@ -35,6 +45,6 @@ username=$(bashio::config 'username') password=$(bashio::config 'password') addgroup "${username}" adduser -D -H -G "${username}" -s /bin/false "${username}" -# shellcheck disable=SC1117 -echo -e "${password}\n${password}" \ + +(echo "$password"; echo "$password") \ | smbpasswd -a -s -c "/etc/samba/smb.conf" "${username}" diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/type b/samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/type new file mode 100644 index 00000000000..bdd22a1850a --- /dev/null +++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/type @@ -0,0 +1 @@ +oneshot diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/up b/samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/up new file mode 100644 index 00000000000..1abccc03b02 --- /dev/null +++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/init-smbd/run diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/dependencies.d/smbd b/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/dependencies.d/smbd new file mode 100644 index 00000000000..e69de29bb2d diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/finish b/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/finish new file mode 100755 index 00000000000..25b9f61011c --- /dev/null +++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/finish @@ -0,0 +1,27 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Take down the S6 supervision tree when nmbd fails +# ============================================================================== +# shellcheck disable=SC2155 +readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode + fi + [[ "${exit_code_signal}" -eq 15 ]] && exec /run/s6/basedir/bin/halt +elif [[ "${exit_code_service}" -ne 0 ]]; then + if [[ "${exit_code_container}" -eq 0 ]]; then + echo "${exit_code_service}" > /run/s6-linux-init-container-results/exitcode + fi + exec /run/s6/basedir/bin/halt +fi diff --git a/samba/rootfs/etc/services.d/nmbd/run b/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/run old mode 100644 new mode 100755 similarity index 72% rename from samba/rootfs/etc/services.d/nmbd/run rename to samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/run index f1d53eaca50..74bb858e842 --- a/samba/rootfs/etc/services.d/nmbd/run +++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/run @@ -1,8 +1,10 @@ -#!/usr/bin/env bash +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Start nmbd service # ============================================================================== exec nmbd \ --foreground \ - --log-stdout \ + --debug-stdout \ --no-process-group diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/type b/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/type @@ -0,0 +1 @@ +longrun diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/dependencies.d/init-smbd b/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/dependencies.d/init-smbd new file mode 100644 index 00000000000..e69de29bb2d diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/finish b/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/finish new file mode 100755 index 00000000000..e60184ba47e --- /dev/null +++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/finish @@ -0,0 +1,27 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Take down the S6 supervision tree when smbd fails +# ============================================================================== +# shellcheck disable=SC2155 +readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode + fi + [[ "${exit_code_signal}" -eq 15 ]] && exec /run/s6/basedir/bin/halt +elif [[ "${exit_code_service}" -ne 0 ]]; then + if [[ "${exit_code_container}" -eq 0 ]]; then + echo "${exit_code_service}" > /run/s6-linux-init-container-results/exitcode + fi + exec /run/s6/basedir/bin/halt +fi diff --git a/samba/rootfs/etc/services.d/smbd/run b/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/run old mode 100644 new mode 100755 similarity index 72% rename from samba/rootfs/etc/services.d/smbd/run rename to samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/run index 6fcffa26b81..219d3d4ebfa --- a/samba/rootfs/etc/services.d/smbd/run +++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/run @@ -1,8 +1,10 @@ -#!/usr/bin/env bash +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Start smbd service # ============================================================================== exec smbd \ --foreground \ - --log-stdout \ + --debug-stdout \ --no-process-group diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/type b/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/type @@ -0,0 +1 @@ +longrun diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/init-smbd b/samba/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/init-smbd new file mode 100644 index 00000000000..e69de29bb2d diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/nmbd b/samba/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/nmbd new file mode 100644 index 00000000000..e69de29bb2d diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/smbd b/samba/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/smbd new file mode 100644 index 00000000000..e69de29bb2d diff --git a/samba/rootfs/etc/services.d/nmbd/finish b/samba/rootfs/etc/services.d/nmbd/finish deleted file mode 100644 index a29ced9a496..00000000000 --- a/samba/rootfs/etc/services.d/nmbd/finish +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/execlineb -S1 -# ============================================================================== -# Take down the S6 supervision tree based on service exit code -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } - -s6-svscanctl -t /var/run/s6/services diff --git a/samba/rootfs/etc/services.d/smbd/finish b/samba/rootfs/etc/services.d/smbd/finish deleted file mode 100644 index a29ced9a496..00000000000 --- a/samba/rootfs/etc/services.d/smbd/finish +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/execlineb -S1 -# ============================================================================== -# Take down the S6 supervision tree based on service exit code -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } - -s6-svscanctl -t /var/run/s6/services diff --git a/samba/rootfs/usr/share/tempio/smb.gtpl b/samba/rootfs/usr/share/tempio/smb.gtpl index 3a2ae1bd66c..d923890ccb3 100644 --- a/samba/rootfs/usr/share/tempio/smb.gtpl +++ b/samba/rootfs/usr/share/tempio/smb.gtpl @@ -2,35 +2,47 @@ netbios name = {{ env "HOSTNAME" }} workgroup = {{ .workgroup }} server string = Samba Home Assistant + local master = {{ .local_master | ternary "yes" "no" }} security = user ntlm auth = yes + idmap config * : backend = tdb + idmap config * : range = 1000000-2000000 load printers = no disable spoolss = yes - log level = 2 + log level = 1 bind interfaces only = yes - interfaces = {{ .interface }} - hosts allow = {{ .allow_hosts | join " " }} + interfaces = 127.0.0.1 {{ .interfaces | join " " }} + hosts allow = 127.0.0.1 {{ .allow_hosts | join " " }} {{ if .compatibility_mode }} client min protocol = NT1 server min protocol = NT1 {{ end }} + mangled names = no + dos charset = CP850 + unix charset = UTF-8 + + vfs objects = catia fruit streams_xattr + +{{ if (has "config" .enabled_shares) }} [config] browseable = yes writeable = yes - path = /config + path = /homeassistant valid users = {{ .username }} force user = root force group = root veto files = /{{ .veto_files | join "/" }}/ delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }} +{{ end }} +{{ if (has "addons" .enabled_shares) }} [addons] browseable = yes writeable = yes @@ -41,7 +53,22 @@ force group = root veto files = /{{ .veto_files | join "/" }}/ delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }} +{{ end }} + +{{ if (has "addon_configs" .enabled_shares) }} +[addon_configs] + browseable = yes + writeable = yes + path = /addon_configs + + valid users = {{ .username }} + force user = root + force group = root + veto files = /{{ .veto_files | join "/" }}/ + delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }} +{{ end }} +{{ if (has "ssl" .enabled_shares) }} [ssl] browseable = yes writeable = yes @@ -52,7 +79,9 @@ force group = root veto files = /{{ .veto_files | join "/" }}/ delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }} +{{ end }} +{{ if (has "share" .enabled_shares) }} [share] browseable = yes writeable = yes @@ -63,7 +92,9 @@ force group = root veto files = /{{ .veto_files | join "/" }}/ delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }} +{{ end }} +{{ if (has "backup" .enabled_shares) }} [backup] browseable = yes writeable = yes @@ -74,7 +105,9 @@ force group = root veto files = /{{ .veto_files | join "/" }}/ delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }} +{{ end }} +{{ if (has "media" .enabled_shares) }} [media] browseable = yes writeable = yes @@ -85,3 +118,4 @@ force group = root veto files = /{{ .veto_files | join "/" }}/ delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }} +{{ end }} diff --git a/samba/translations/en.yaml b/samba/translations/en.yaml new file mode 100644 index 00000000000..1013cf85f07 --- /dev/null +++ b/samba/translations/en.yaml @@ -0,0 +1,35 @@ +--- +configuration: + username: + name: Username + description: >- + The username you would like to use to authenticate with the Samba server. + password: + name: Password + description: >- + The password that goes with the username configured for authentication. + workgroup: + name: Workgroup + description: Change WORKGROUP to reflect your network needs. + local_master: + name: Local master + description: Enable to try and become a local master browser on a subnet. + enabled_shares: + name: >- + Enabled Shares - allowed values are: + addons, addon_configs, backup, config, media, share, or ssl. + description: >- + List of file shares to make available. + Adding a share requires typing its name to add it. + The listed values are the only allowed values. + The configuration cannot be saved if any non-allowed value is in the list. + compatibility_mode: + name: Enable Compatibility Mode + description: >- + Enable this to use old legacy Samba protocols on the Samba add-on. + veto_files: + name: Veto Files + description: List of files that are neither visible nor accessible. + allow_hosts: + name: Allowed Hosts + description: List of hosts/networks allowed to access the shared folders. diff --git a/silabs-multiprotocol/CHANGELOG.md b/silabs-multiprotocol/CHANGELOG.md new file mode 100644 index 00000000000..e62764a6018 --- /dev/null +++ b/silabs-multiprotocol/CHANGELOG.md @@ -0,0 +1,227 @@ +# Changelog + +## 2.4.5 +- Support Home Assistant Connect ZBT-1. + +## 2.4.4 +- Revert back to Silicon Labs Gecko SDK 4.3.1 while 4.4.0 instability is investigated. +- Backport firmware modifications for improved stability. +- Bump universal SiLabs flasher to 0.0.17 + +## 2.4.3 +- ⚠️ Zigbee2MQTT does not yet support this version of the Gecko SDK. Do not update if you are using Z2M! ⚠️. +- This is a re-release of 2.4.0 that is compatible only with Home Assistant Core 2024.1.0 and above. + +## 2.4.2 +- Bump universal SiLabs flasher to 0.0.16 so that firmware is successfully installed on startup. + +## 2.4.1 + +- Revert back to Silicon Labs Gecko SDK 4.3.1 to maintain compatibility with Home Assistant Core 2023.12.0 and Zigbee2MQTT. If you are running 2024.1.0 with ZHA, you don't have to downgrade. + +## 2.4.0 + +- Use Silicon Labs Gecko SDK 4.4.0 +- Bump universal SiLabs flasher to 0.0.16 +- Improved firmware configurations for Home Assistant Yellow and SkyConnect + for stability (without ZGP, with watchdog) + +## 2.3.2 + +- Update mDNSResponder to 1790.80.10 + +## 2.3.1 + +- Use Silicon Labs Gecko SDK 4.3.1 + +## 2.3.0 + +- Add patch with new REST API to reset the OTBR +- Bump universal SiLabs flasher to 0.0.13 + +## 2.2.0 + +- Use Silicon Labs Gecko SDK 4.3.0 + - With this we get the OTBR version from May 17th, along with Border Agent ID + support (required for Android and iOS APIs) +- Note: This update needs a new Multi-PAN firmware. Home Assistant SkyConnect and Yellow get automatically updated by this add-on. + +## 2.1.0 + +- Add REST API patches to fix a bugs and support deleting datasets + +## 2.0.0 + +- Update OpenThread REST API to latest upstreamed API variant + +## 1.1.3 + +- Use native zigbeed on x86-64/amd64 architecture +- Avoid deleting otbr-web user content twice + +## 1.1.2 + +- Use Silicon Labs Gecko SDK 4.2.3 +- Avoid starting mdnsd when OpenThread Border Router is not enabled + +## 1.1.1 + +- Bugfix: bump universal SiLabs flasher to 0.0.12 for amd64 + +## 1.1.0 + +- Use default baudrate of 460800 (WARNING: You MUST update your configuration!) +- Bump universal SiLabs flasher to 0.0.12 + +## 1.0.2 + +- Use Silicon Labs Gecko SDK 4.2.2 + +## 1.0.1 + +- Use host namespace for hostname (make sure that the BR is announced with the + systems real hostname) + +## 1.0.0 + +- Remove Web UI via ingress (expose ports to use the Web UI, see documentation) +- Change vendor name to "Home Assistant" and product name to Silicon Labs + Multiprotocol" (used in OTBR mDNS/DNS-SD announcments) + +## 0.13.1 + +- Set default baudrate 115200 correctly +- Prevent OTBR discovery service from start when OTBR is disabled +- Fix REST API to correctly set the Connection HTTP header on amd64 +- Fix network device support (properly start socat if necessary) on amd64 + +## 0.13.0 + +- Use Silicon Labs Gecko SDK 4.2.1 +- Let the OTBR REST API listen on local interface only by default +- Automatically flash firmware by default +- Disable OTBR web interface by default (see documentation) +- Fix network device support (properly start socat if necessary) + +## 0.12.0 + +- Use Silicon Labs Gecko SDK 4.1.4 + +## 0.11.4 + +- Fix REST API to correctly set the Connection HTTP header + +## 0.11.3 + +- Fix REST API to return an HTTP compliant status line + +## 0.11.2 + +- Add OTBR discovery support + +## 0.11.1 + +- Update REST API with full active and pending dataset as well as state support + +## 0.11.0 + +- Use Silicon Labs Gecko SDK 4.2.0 + +## 0.10.0 + +- Add REST API to get and set the active dataset to the OpenThrad Border Router + +## 0.9.1 + +- Avoid start error in case multiple primary interfaces are returned +- Fix zigbeed argument parsing for 32-bit add-on +- Remove unnecessary error message "Cannot open file /usr/local/etc/zigbeed.conf" + +## 0.9.0 + +- Allow IPv6 forwarding explicitly (required for HAOS 9.x without firewall) +- Add OTBR firewall option (enabled by default, requires HAOS 9.4 or newer) +- Add egress firewall rules for forwarding +- Add fine grained OTBR log level control +- Fix service stop (finish) scripts + +## 0.8.1 + +- Bugfix: give GPIO permissions to container to allow flashing Yellow + +## 0.8.0 + +- Initial AMD64/x86-64 support (zigbeed via QEMU) +- Increase multicast table size to 16 (as expected by ZHA by default) + +## 0.7.2 + +- Fix OTBR enable flag (allow to disable the OTBR) +- Fix zigbeed and cpcd finish scripts +- Start banner after initialization scripts + +## 0.7.1 + +- Bump universal SiLabs flasher to 0.0.7 +- Use baudrate 115200 by default +- Add Docker health check to monitor zigbeed + +## 0.7.0 + +- Support firmware flashing for Home Assistant SkyConnect/Yellow +- Allow quick reconnects by ZHA (required during config flow) + +## 0.6.2 + +- Use Silicon Labs Gecko SDK 4.1.3 + +## 0.6.1 + +- Use Silicon Labs Gecko SDK 4.1.2 + +## 0.6.0 + +- Implement native TCP/IP support for zigbeed (requires bellows 0.34.0 or newer) +- Bind only to add-ons local address + +## 0.5.1 + +- Use Silicon Labs Gecko SDK 4.1.1 +- Readd aarch64 support + +## 0.5.0 + +- Use Silicon Labs Gecko SDK 4.1.0 +- Build zigbeed from source (as binaries are no longer provided) +- Bump OTBR to Silicon Labs forked version of Gecko SDK v4.1.0 + (based on OTBR POSIX version 3a98779dc9 (2022-06-02 09:34:58 -0700)) +- Use s6-overlay v3 style services +- Drop aarch64 support (all CPC communication blocks on aarch64 since 4.1.0) + +## 0.4.1 + +- Support network device (CPC daemon via TCP/IP socket) + +## 0.4.0 + +- Use Silicon Labs Gecko SDK 4.0.2 +- Enable native aarch64 support +- Support baudrate and hardware flow control + +## 0.3.1 + +- Fix permissions to make otbr-agent start correctly +- Add OpenThread Border Router web frontend via ingress + +## 0.3.0 + +- Initial OpenThread support + +## 0.2.0 + +- Use Silicon Labs Gecko SDK 4.0.1 +- Fix port description + +## 0.1.0 + +- initial version diff --git a/silabs-multiprotocol/DOCS.md b/silabs-multiprotocol/DOCS.md new file mode 100644 index 00000000000..d333b0a445a --- /dev/null +++ b/silabs-multiprotocol/DOCS.md @@ -0,0 +1,109 @@ +# Home Assistant Add-on: Silicon Labs Multiprotocol + +**NOTE**: This add-on has the option to automatically install the right firmware for Home Assistant Yellow, SkyConnect, and Connect ZBT-1. Follow [this guide](https://github.com/NabuCasa/silabs-firmware/wiki/Flash-Silicon-Labs-radio-firmware-manually) to change back to a firmware that is compatible with other Zigbee software. + +## Installation + +Follow these steps to get the add-on installed on your system: + +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons, Backup & Supervisor** -> **Add-on Store**. +2. Find the "Silicon Labs Multiprotocol" add-on and click it. +3. Click on the "INSTALL" button. + +## How to use + +The add-on needs a Silicon Labs based wireless module accessible through a +serial port (like the module on Yellow or most USB based wireless adapters). + +Once the firmware is loaded follow the following steps: + +1. Select the correct `device` in the add-on configuration tab and press `Save`. + On Home Assistant Yellow use `/dev/ttyAMA1`. +2. Start the add-on. + +**NOTE:** the Web frontend is only accessible when OpenThread is enabled (see below). + +### Zigbee + +To use Zigbee with ZHA configure the Integration as follows: + +1. Remember/copy the hostname of the add-on (e.g. `c8f00288-silabs-multiprotocol`). +2. Add the Zigbee Home Automation (ZHA) integration to Home Assistant Core +3. When asked for the Serial Device Path, choose `Enter Manually`. +4. Choose `EZSP` as Radio type. +5. As serial path, enter `socket://:9999`. +6. Port speed and flow control don't matter. +7. Press `Submit`. Adding ZHA should succeed and you should be able to use ZHA + as if using any other supported radio type. + +### OpenThread + +At this point OpenThread support is experimental. This add-on makes your Home +Assistant installation an OpenThread Border Router (OTBR). A basic integration +for Home Assistant Core named `otbr` is currently in the making. + +To use the OTBR enable it in the Configuration tab and restart the add-on. Home +Assistant should discover the OpenThread border router automatically and +configure it as necessary. + +### Web interface (advanced) + +There is also a web interface provided by the OTBR. However, the web +interface has caveats (e.g. forming a network does not generate an off-mesh +routable IPv6 prefix which causes changing IPv6 addressing on first add-on +restart). It is still possible to enable the web interface for debugging +purpose. Make sure to expose both the Web UI port and REST API port (the +latter needs to be on port 8081) on the host interface. To do so, click on +"Show disabled ports" and enter a port (e.g. 8080) in the OpenThread Web UI +and 8081 in the OpenThread REST API port field). + +### Automatic firmware upgrade + +If the `autoflash_firmware` configuration is set, the add-on will automatically +install or update to the RCP Multi-PAN firmware if a Home Assistant Connect ZBT-1/ +SkyConnect or Home Assistant Yellow is detected. + +**NOTE:** Switching back to a Zigbee only (EmberZNet) firmware requires manual +steps currently. You can find a guide on the Nabu Casa Silicon Labs firmware +repository Wiki on flashing [Silicon Labs radio firmware +manually](https://github.com/NabuCasa/silabs-firmware/wiki/Flash-Silicon-Labs-radio-firmware-manually). + +## Configuration + +Add-on configuration: + +| Configuration | Description | +|--------------------|--------------------------------------------------------| +| device (mandatory) | Serial service where the Silicon Labs radio is attached | +| baudrate | Serial port baudrate (depends on firmware) | +| flow_control | If hardware flow control should be enabled (depends on firmware) | +| autoflash_firmware | Automatically install/update firmware (Home Assistant Connect ZBT-1/SkyConnect/Yellow) | +| network_device | Host and port where CPC daemon can find the Silicon Labs radio (takes precedence over device) | +| cpcd_trace | Co-Processor Communication tracing (trace in log) | +| otbr_enable | Enable OpenThread BorderRouter | +| otbr_log_level | Set the log level of the OpenThread BorderRouter Agent | +| otbr_firewall | Enable OpenThread Border Router firewall to block unnecessary traffic | + +## Architecture + +The add-on runs several service internally. This architecture diagram shows what +the add-on currently implements. + +![Silicon Labs Multiprotocol Add-on Architecture](https://raw.githubusercontent.com/home-assistant/addons/master/silabs-multiprotocol/images/architecture.png) + +## Support + +Got questions? + +You have several options to get them answered: + +- The [Home Assistant Discord Chat Server][discord]. +- The Home Assistant [Community Forum][forum]. +- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit] + +In case you've found a bug, please [open an issue on our GitHub][issue]. + +[discord]: https://discord.gg/c5DvZ4e +[forum]: https://community.home-assistant.io +[reddit]: https://reddit.com/r/homeassistant +[issue]: https://github.com/home-assistant/addons/issues diff --git a/silabs-multiprotocol/Dockerfile b/silabs-multiprotocol/Dockerfile new file mode 100644 index 00000000000..3852a7fa2fa --- /dev/null +++ b/silabs-multiprotocol/Dockerfile @@ -0,0 +1,269 @@ +ARG BUILD_FROM +ARG BUILD_ARCH +FROM --platform=linux/amd64 debian:bullseye AS cross-builder-base + +ENV \ + LANG="C.UTF-8" \ + DEBIAN_FRONTEND="noninteractive" \ + CURL_CA_BUNDLE="/etc/ssl/certs/ca-certificates.crt" + +WORKDIR /usr/src + +# Allow to reuse downloaded packages (these are only staged build images) +# hadolint ignore=DL3009 +RUN \ + set -x \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + bash \ + curl \ + ca-certificates \ + build-essential \ + git + +FROM --platform=linux/amd64 cross-builder-base AS cross-builder-armv7 + +COPY debian-armv7.cmake /usr/src/debian.cmake + +ENV DEBIAN_ARCH=armhf +ENV DEBIAN_CROSS_PREFIX=arm-linux-gnueabihf +ENV SLC_ARCH=linux_arch_32 + +RUN \ + set -x \ + && dpkg --add-architecture armhf \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + crossbuild-essential-armhf + +FROM --platform=linux/amd64 cross-builder-base AS cross-builder-aarch64 + +COPY debian-arm64.cmake /usr/src/debian.cmake + +ENV DEBIAN_ARCH=arm64 +ENV DEBIAN_CROSS_PREFIX=aarch64-linux-gnu +ENV SLC_ARCH=linux_arch_64 + +RUN \ + set -x \ + && dpkg --add-architecture arm64 \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + crossbuild-essential-arm64 + +FROM --platform=linux/amd64 cross-builder-base AS cross-builder-amd64 + +COPY debian-amd64.cmake /usr/src/debian.cmake + +ENV DEBIAN_ARCH=amd64 \ + DEBIAN_CROSS_PREFIX=x86_64-linux-gnu \ + SLC_ARCH=zigbee_x86_64 + +RUN \ + set -x \ + && dpkg --add-architecture amd64 \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + crossbuild-essential-amd64 + + +FROM --platform=linux/amd64 cross-builder-${BUILD_ARCH} AS cpcd-builder + +ARG CPCD_VERSION + +RUN \ + set -x \ + && apt-get install -y --no-install-recommends \ + cmake \ + "libmbedtls-dev:${DEBIAN_ARCH}" \ + "libmbedtls12:${DEBIAN_ARCH}" \ + && git clone --depth 1 -b "${CPCD_VERSION}" \ + https://github.com/SiliconLabs/cpc-daemon.git \ + && mkdir cpc-daemon/build && cd cpc-daemon/build \ + && cmake ../ \ + -DCMAKE_TOOLCHAIN_FILE=../debian.cmake \ + -DENABLE_ENCRYPTION=FALSE \ + && make \ + && make install + +FROM --platform=linux/amd64 cross-builder-${BUILD_ARCH} AS zigbeed-builder + +ARG GECKO_SDK_VERSION + +RUN \ + set -x \ + && apt-get install -y --no-install-recommends \ + python3 \ + python3-jinja2 \ + python3-pip \ + openjdk-17-jre \ + git-lfs \ + unzip \ + && curl -O https://www.silabs.com/documents/login/software/slc_cli_linux.zip \ + && unzip slc_cli_linux.zip \ + && cd slc_cli/ && chmod +x slc + +ENV PATH="/usr/src/slc_cli/:$PATH" + +RUN \ + set -x \ + && git clone --depth 1 -b ${GECKO_SDK_VERSION} \ + https://github.com/SiliconLabs/gecko_sdk.git + +# zigbeed links against libcpc.so +COPY --from=cpcd-builder /usr/local/ /usr/${DEBIAN_CROSS_PREFIX}/ +COPY gecko-sdk-patches/0001-Use-TCP-socket-instead-of-serial-port-SDK.patch /usr/src +COPY zigbeed-app-patches/0001-Use-TCP-socket-instead-of-serial-port-main-app.patch /usr/src + +RUN \ + set -x \ + && cd gecko_sdk \ + && patch -p1 < /usr/src/0001-Use-TCP-socket-instead-of-serial-port-SDK.patch \ + && GECKO_SDK=$(pwd) \ + && slc signature trust --sdk=${GECKO_SDK} \ + && cd protocol/zigbee \ + && slc generate \ + --sdk=${GECKO_SDK} \ + --with="${SLC_ARCH}" \ + --project-file=$(pwd)/app/zigbeed/zigbeed.slcp \ + --export-destination=$(pwd)/app/zigbeed/output \ + --copy-proj-sources \ + && cd app/zigbeed/output \ + && patch -p1 < /usr/src/0001-Use-TCP-socket-instead-of-serial-port-main-app.patch \ + && make -f zigbeed.Makefile \ + AR="${DEBIAN_CROSS_PREFIX}-ar" \ + CC="${DEBIAN_CROSS_PREFIX}-gcc" \ + LD="${DEBIAN_CROSS_PREFIX}-gcc" \ + CXX="${DEBIAN_CROSS_PREFIX}-g++" \ + C_FLAGS="-std=gnu99 -DEMBER_MULTICAST_TABLE_SIZE=16" \ + debug + +FROM $BUILD_FROM + +ARG UNIVERSAL_SILABS_FLASHER + +RUN \ + set -x \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + libmbedtls12 \ + socat \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /usr/src/* + + +COPY --from=zigbeed-builder \ + /usr/src/gecko_sdk/util/third_party/ot-br-posix /usr/src/ot-br-posix +COPY --from=zigbeed-builder \ + /usr/src/gecko_sdk/util/third_party/openthread /usr/src/openthread +COPY --from=zigbeed-builder \ + /usr/src/gecko_sdk/protocol/openthread/platform-abstraction/posix/ /usr/src/silabs-vendor-interface +COPY --from=cpcd-builder /usr/local/ /usr/local/ + +ENV BORDER_ROUTING=1 +ENV BACKBONE_ROUTER=1 +ENV WEB_GUI=1 +ENV DOCKER 1 + +COPY otbr-patches/0001-Avoid-writing-to-system-console.patch /usr/src +COPY otbr-patches/0001-rest-support-erasing-all-persistent-info-1908.patch /usr/src +COPY otbr-patches/0002-rest-support-deleting-the-dataset.patch /usr/src +COPY otbr-patches/0003-mdns-update-mDNSResponder-to-1790.80.10.patch /usr/src +COPY otbr-patches/0004-mdns-add-Linux-specific-patches.patch /usr/src + +# Required and installed during build (script/bootstrap), could be removed +ENV OTBR_BUILD_DEPS build-essential ninja-build cmake wget ca-certificates \ + libreadline-dev libncurses-dev libcpputest-dev libdbus-1-dev libavahi-common-dev \ + libavahi-client-dev libboost-dev libboost-filesystem-dev libboost-system-dev \ + libnetfilter-queue-dev + +# Build OTBR natively from Gecko SDK sources +WORKDIR /usr/src +RUN \ + set -x \ + && apt-get update \ + # Install npm/nodejs for WebUI manually to avoid systemd getting pulled in \ + && apt-get install -y --no-install-recommends \ + nodejs \ + npm \ + iproute2 \ + patch \ + python3 \ + python3-dev \ + python3-pip \ + python3-aiohttp \ + python3-cryptography \ + python3-yarl \ + lsb-release \ + netcat \ + sudo \ + && cd ot-br-posix \ + && patch -p1 < /usr/src/0001-Avoid-writing-to-system-console.patch \ + && patch -p1 < /usr/src/0001-rest-support-erasing-all-persistent-info-1908.patch \ + && patch -p1 < /usr/src/0002-rest-support-deleting-the-dataset.patch \ + && patch -p1 < /usr/src/0003-mdns-update-mDNSResponder-to-1790.80.10.patch \ + && patch -p1 < /usr/src/0004-mdns-add-Linux-specific-patches.patch \ + && ln -s ../../../openthread/ third_party/openthread/repo \ + && (cd third_party/openthread/repo \ + && ln -s ../../../../silabs-vendor-interface/openthread-core-silabs-posix-config.h src/posix/platform/openthread-core-silabs-posix-config.h) \ + && chmod +x ./script/* \ + && ./script/bootstrap \ + # Mimic rt_tables_install \ + && echo "88 openthread" >> /etc/iproute2/rt_tables \ + # Mimic otbr_install \ + && (./script/cmake-build \ + -DBUILD_TESTING=OFF \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_MODULE_PATH=/usr/src/silabs-vendor-interface/ \ + -DOTBR_FEATURE_FLAGS=ON \ + -DOTBR_DNSSD_DISCOVERY_PROXY=ON \ + -DOTBR_SRP_ADVERTISING_PROXY=ON \ + -DOTBR_INFRA_IF_NAME=eth0 \ + -DOTBR_MDNS=mDNSResponder \ + -DOTBR_VERSION= \ + -DOT_PACKAGE_VERSION= \ + -DOTBR_DBUS=OFF \ + -DOT_MULTIPAN_RCP=ON \ + -DOT_POSIX_CONFIG_RCP_BUS=VENDOR \ + -DOT_POSIX_CONFIG_RCP_VENDOR_DEPS_PACKAGE=SilabsRcpDeps \ + -DOT_POSIX_CONFIG_RCP_VENDOR_INTERFACE=/usr/src/silabs-vendor-interface/cpc_interface.cpp \ + -DOT_CONFIG="openthread-core-silabs-posix-config.h" \ + -DOT_LINK_RAW=1 \ + -DOTBR_VENDOR_NAME="Home Assistant" \ + -DOTBR_PRODUCT_NAME="Silicon Labs Multiprotocol" \ + -DOTBR_WEB=ON \ + -DOTBR_BORDER_ROUTING=ON \ + -DOTBR_REST=ON \ + -DOTBR_BACKBONE_ROUTER=ON \ + && cd build/otbr/ \ + && ninja \ + && ninja install) \ + && pip install universal-silabs-flasher==${UNIVERSAL_SILABS_FLASHER} \ + && apt-get purge -y --auto-remove \ + build-essential \ + patch \ + python3-pip \ + python3-dev \ + git \ + git-lfs \ + libmbedtls-dev \ + ${OTBR_BUILD_DEPS} \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /usr/src/* + +COPY --from=zigbeed-builder \ + /usr/src/gecko_sdk/protocol/zigbee/app/zigbeed/output/build/debug/zigbeed \ + /usr/local/bin + +RUN ldconfig && touch /accept_silabs_msla + +COPY rootfs / + +ENV \ + S6_STAGE2_HOOK=/etc/s6-overlay/scripts/enable-check.sh + +HEALTHCHECK --interval=10s --start-period=120s CMD [ "$(s6-svstat -u /run/service/zigbeed)" = "true" ] + +# use s6-overlay as init system +WORKDIR / +ENTRYPOINT ["/init"] diff --git a/silabs-multiprotocol/README.md b/silabs-multiprotocol/README.md new file mode 100644 index 00000000000..ef701bee92a --- /dev/null +++ b/silabs-multiprotocol/README.md @@ -0,0 +1,19 @@ +# Home Assistant Add-on: SiliconLabs Zigbee/OpenThread Multiprotocol Add-on + +Zigbee/OpenThread Multiprotocol container for Silicon Labs based radios such as +Home Assistant Yellow, Home Assistant SkyConnect, and Home Assistant Connect ZBT-1. + +![Supports armv7 Architecture][armv7-shield] +![Supports aarch64 Architecture][aarch64-shield] +![Supports amd64 Architecture][amd64-shield] + +## About + +This add-on allows you to use Zigbee and OpenThread protocol simultaneous on a +single Silicon Labs based radio. The radio needs the RCP Multi-PAN firmware +installed to support multiple IEEE 802.15.4 Personal Area Networks (PAN). The +addon has been tested with EFR32 Series 2 based radios. + +[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg +[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg +[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg diff --git a/silabs-multiprotocol/build.yaml b/silabs-multiprotocol/build.yaml new file mode 100644 index 00000000000..b6983d81fbd --- /dev/null +++ b/silabs-multiprotocol/build.yaml @@ -0,0 +1,9 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base-debian:bullseye + armv7: ghcr.io/home-assistant/armv7-base-debian:bullseye + amd64: ghcr.io/home-assistant/amd64-base-debian:bullseye +args: + CPCD_VERSION: v4.3.1 + GECKO_SDK_VERSION: v4.3.1 + UNIVERSAL_SILABS_FLASHER: 0.0.17 diff --git a/silabs-multiprotocol/config.yaml b/silabs-multiprotocol/config.yaml new file mode 100644 index 00000000000..6d5b2b11f6a --- /dev/null +++ b/silabs-multiprotocol/config.yaml @@ -0,0 +1,54 @@ +--- +version: 2.4.5 +slug: silabs_multiprotocol +name: Silicon Labs Multiprotocol +description: Zigbee and OpenThread multiprotocol add-on +url: > + https://github.com/home-assistant/addons/tree/master/silabs-multiprotocol +arch: + - armv7 + - aarch64 + - amd64 +homeassistant: 2024.1.0 +gpio: true +hassio_api: true +discovery: + - otbr +# IPC is only used within the Add-on +host_ipc: false +host_network: true +host_uts: true +privileged: + - IPC_LOCK + - NET_ADMIN +image: homeassistant/{arch}-addon-silabs-multiprotocol +init: false +options: + device: null + baudrate: "460800" + flow_control: true + autoflash_firmware: true + cpcd_trace: false + otbr_enable: true + otbr_log_level: notice + otbr_firewall: true +ports: + 9999/tcp: null + 8080/tcp: null + 8081/tcp: null +ports_description: + 9999/tcp: EmberZNet EZSP/ASH port + 8080/tcp: OpenThread Web port + 8081/tcp: OpenThread REST API port +schema: + device: device(subsystem=tty)? + baudrate: list(57600|115200|230400|460800|921600) + flow_control: bool? + network_device: str? + autoflash_firmware: bool + cpcd_trace: bool + otbr_enable: bool + otbr_log_level: list(debug|info|notice|warning|error|critical|alert|emergency) + otbr_firewall: bool +stage: experimental +startup: services diff --git a/silabs-multiprotocol/debian-amd64.cmake b/silabs-multiprotocol/debian-amd64.cmake new file mode 100644 index 00000000000..1a515398ac2 --- /dev/null +++ b/silabs-multiprotocol/debian-amd64.cmake @@ -0,0 +1,14 @@ +SET(CMAKE_SYSTEM_NAME Linux) +SET(CMAKE_SYSTEM_PROCESSOR x86_64) +SET(CMAKE_SYSTEM_VERSION 1) + +# Specify the cross compiler +SET(CMAKE_C_COMPILER /usr/bin/x86_64-linux-gnu-gcc) +SET(CMAKE_CXX_COMPILER /usr/bin/x86_64-linux-gnu-g++) + +# Search for programs only in the build host directories +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +# Search for libraries and headers only in the target directories +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/silabs-multiprotocol/debian-arm64.cmake b/silabs-multiprotocol/debian-arm64.cmake new file mode 100644 index 00000000000..5732b65a28d --- /dev/null +++ b/silabs-multiprotocol/debian-arm64.cmake @@ -0,0 +1,14 @@ +SET(CMAKE_SYSTEM_NAME Linux) +SET(CMAKE_SYSTEM_PROCESSOR aarch64) +SET(CMAKE_SYSTEM_VERSION 1) + +# Specify the cross compiler +SET(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc) +SET(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++) + +# Search for programs only in the build host directories +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +# Search for libraries and headers only in the target directories +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/silabs-multiprotocol/debian-armv7.cmake b/silabs-multiprotocol/debian-armv7.cmake new file mode 100644 index 00000000000..d1449e74904 --- /dev/null +++ b/silabs-multiprotocol/debian-armv7.cmake @@ -0,0 +1,14 @@ +SET(CMAKE_SYSTEM_NAME Linux) +SET(CMAKE_SYSTEM_PROCESSOR aarch64) +SET(CMAKE_SYSTEM_VERSION 1) + +# Specify the cross compiler +SET(CMAKE_C_COMPILER /usr/bin/arm-linux-gnueabihf-gcc) +SET(CMAKE_CXX_COMPILER /usr/bin/arm-linux-gnueabihf-g++) + +# Search for programs only in the build host directories +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +# Search for libraries and headers only in the target directories +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/silabs-multiprotocol/gecko-sdk-patches/0001-Use-TCP-socket-instead-of-serial-port-SDK.patch b/silabs-multiprotocol/gecko-sdk-patches/0001-Use-TCP-socket-instead-of-serial-port-SDK.patch new file mode 100644 index 00000000000..d58806a03cd --- /dev/null +++ b/silabs-multiprotocol/gecko-sdk-patches/0001-Use-TCP-socket-instead-of-serial-port-SDK.patch @@ -0,0 +1,278 @@ +From a6c952a9c31a535d7eae22e1803ad2f2ab7de915 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Stefan Agner +Date: Thu, 15 Dec 2022 16:38:34 +0100 +Subject: [PATCH] Use TCP socket instead of serial port (SDK) + +Instead of opening a serial port, open a TCP socket on port 9999. Pass +the listening socket to the new instance in case a controller reset is +being requested. This makes sure the TCP connection stays up even when +zigbeed restarts. +--- + protocol/zigbee/app/zigbeed/serial_adapter.c | 169 +++++++++++-------- + 1 file changed, 99 insertions(+), 70 deletions(-) + +diff --git a/protocol/zigbee/app/zigbeed/serial_adapter.c b/protocol/zigbee/app/zigbeed/serial_adapter.c +index f48630509..2807ab91c 100644 +--- a/protocol/zigbee/app/zigbeed/serial_adapter.c ++++ b/protocol/zigbee/app/zigbeed/serial_adapter.c +@@ -17,13 +17,16 @@ + * + ******************************************************************************/ + +-#include +-#include + #include + #include ++#include ++#include ++#include + #include ++#include + #include +-#include ++#include ++#include + #include + + #include "ember-types.h" +@@ -37,19 +40,17 @@ + #define MAX_OUT_BLOCK_LEN 512 // maximum bytes to output at one time + #define MAX_IN_BLOCK_LEN 512 // maximum bytes to input at one time + +-#define DEFAULT_SERIAL_PORT "/tmp/ttyZigbeed" + #define DEFAULT_OUT_BLOCK_LEN 1 + #define DEFAULT_IN_BLOCK_LEN 256 + +-char serialPort[SERIAL_PORT_NAME_MAX_LEN] = DEFAULT_SERIAL_PORT; + +-#ifdef ZIGBEE_PRO_COMPLIANCE_ON_HOST +-#include "sl_cli_threaded_host.h" +-extern bool sli_cli_is_input_handled(void); +-extern int sli_cli_get_pipe_read_fd(void); +-#endif // ZIGBEE_PRO_COMPLIANCE_ON_HOST ++struct in6_addr ezspListenAddress = IN6ADDR_ANY_INIT; ++uint16_t ezspPort = 9999; ++ ++extern jmp_buf gResetJump; ++ ++static int socketFd = NULL_FILE_DESCRIPTOR; + +-static int serialFd = NULL_FILE_DESCRIPTOR; // file descriptor for serial port + static uint8_t outBuffer[MAX_OUT_BLOCK_LEN]; // array to buffer output + static uint8_t *outBufRd; // outBuffer read pointer + static uint8_t *outBufWr; // outBuffer write pointer +@@ -59,13 +60,59 @@ static uint8_t *inBufRd; // inBuffer read pointer + static uint8_t *inBufWr; // inBuffer write pointer + static uint16_t inBlockLen; // bytes to read ahead + +-static void serialClose(void) ++static EmberStatus initSocket(void) + { +- if (serialFd != NULL_FILE_DESCRIPTOR) { +- tcflush(serialFd, TCIOFLUSH); +- close(serialFd); +- serialFd = NULL_FILE_DESCRIPTOR; ++ struct sockaddr_in6 address; ++ int addrlen = sizeof(address); ++ int opt = 1; ++ static int serverFd = -1; ++ ++ if ((serverFd = socket(AF_INET6, SOCK_STREAM, 0)) < 0) { ++ fprintf(stderr, "Failed to create server socket: %s\r\n", strerror(errno)); ++ return EMBER_ERR_FATAL; ++ } ++ ++ // Forcefully attaching socket to the port 8080 ++ if (setsockopt(serverFd, SOL_SOCKET, ++ SO_REUSEADDR, &opt, ++ sizeof(opt))) { ++ fprintf(stderr, "Failed to set server socket options: %s\r\n", strerror(errno)); ++ return EMBER_ERR_FATAL; + } ++ ++ address.sin6_family = AF_INET6; ++ address.sin6_addr = ezspListenAddress; ++ address.sin6_port = htons(ezspPort); ++ ++ if (bind(serverFd, (struct sockaddr*)&address, sizeof(address)) < 0) { ++ fprintf(stderr, "Failed to bind server socket to port %d: %s\r\n", ezspPort, strerror(errno)); ++ return EMBER_ERR_FATAL; ++ } ++ ++ fprintf(stderr, "Listening on port %d for connection...\r\n", ezspPort); ++ if (listen(serverFd, 3) < 0) { ++ fprintf(stderr, "Failed to listen on server socket: %s\r\n", strerror(errno)); ++ return EMBER_ERR_FATAL; ++ } ++ ++ fprintf(stderr, "Accepting connection.\r\n"); ++ if ((socketFd = accept(serverFd, (struct sockaddr*)&address, (socklen_t*)&addrlen)) < 0) { ++ fprintf(stderr, "Failed to accept on server socket: %s\r\n", strerror(errno)); ++ return EMBER_SERIAL_RX_EMPTY; ++ } ++ fprintf(stderr, "Accepted connection %d.\r\n", socketFd); ++ ++ close(serverFd); ++ ++ fcntl(socketFd, F_SETFL, O_NONBLOCK); ++ ++ if (setsockopt(socketFd, IPPROTO_TCP, ++ TCP_NODELAY, &opt, ++ sizeof(opt))) { ++ fprintf(stderr, "Failed to set server socket options: %s\r\n", strerror(errno)); ++ } ++ ++ return EMBER_SUCCESS; + } + + static void writeFlush(void) +@@ -73,11 +120,10 @@ static void writeFlush(void) + int16_t count; + + if (outBufWr - outBufRd) { +- count = write(serialFd, outBufRd, outBufWr - outBufRd); ++ count = write(socketFd, outBufRd, outBufWr - outBufRd); + if (count > 0) { + outBufRd += count; + } +- fsync(serialFd); + if (outBufRd == outBufWr) { + outBufRd = outBufWr = outBuffer; + } +@@ -86,13 +132,23 @@ static void writeFlush(void) + + static EmberStatus readAvailable(uint16_t *count) + { +- int16_t bytesRead; ++ int bytesRead; ++ + if (inBufRd == inBufWr) { + inBufRd = inBufWr = inBuffer; +- bytesRead = read(serialFd, inBuffer, inBlockLen); ++ bytesRead = read(socketFd, inBuffer, inBlockLen); + if (bytesRead > 0) { + inBufWr += bytesRead; + } ++ if (bytesRead == 0) { ++ fprintf(stderr, "Socket connection has been closed, restarting...\r\n"); ++ close(socketFd); ++ socketFd = -1; ++ ++ // ZHA cannot handle short interruptions of the port, so reopen the ++ // port asap ++ initSocket(); ++ } + } + *count = inBufWr - inBufRd; + if (inBufRd == inBufWr) { +@@ -113,7 +169,8 @@ EmberStatus emberSerialInit(uint8_t port, + #ifdef IO_LOG + logFile = fopen(IO_LOG, "w"); + #endif +- struct termios tios; ++ const char *env; ++ + outBufRd = outBuffer; + outBufWr = outBuffer; + outBlockLen = DEFAULT_OUT_BLOCK_LEN; +@@ -127,38 +184,28 @@ EmberStatus emberSerialInit(uint8_t port, + inBlockLen = MAX_IN_BLOCK_LEN; + } + +- // Make sure any previous file descriptor is nicely closed. +- // This should only be necessary during a failure recovery when the +- // host encountered an error. +- serialClose(); +- +- serialFd = open(serialPort, +- O_RDWR | O_NOCTTY | O_NONBLOCK); +- +- if (serialFd == NULL_FILE_DESCRIPTOR) { +- fprintf(stderr, "Failed to open %s: %s\r\n", serialPort, strerror(errno)); +- fprintf(stderr, "Use socat to create PTYs for zigbeed and the host app. Eg:\r\n"); +- fprintf(stderr, "socat -x -v pty,link=/dev/ttyZigbeeNCP pty,link=/tmp/ttyZigbeeNCP\r\n"); +- serialClose(); +- return EMBER_ERR_FATAL; ++ // Get file descriptor from previous instance, if valid. ++ env = getenv("ZIGBEED_SOCKET_FD"); ++ if (env && (socketFd = strtol(env, NULL, 10)) > 0) { ++ fprintf(stderr, "Reusing socket from previous instance.\r\n"); ++ return EMBER_SUCCESS; + } + +- tcflush(serialFd, TCIOFLUSH); // flush all input and output data +- fcntl(serialFd, F_SETFL, O_NDELAY); +- tcgetattr(serialFd, &tios); // get current serial port options +- +- tios.c_iflag &= ~(BRKINT | INLCR | IGNCR | ICRNL | INPCK +- | ISTRIP | IMAXBEL | IXON | IXOFF | IXANY); +- +- tios.c_lflag &= ~(ICANON | ECHO | IEXTEN | ISIG); // raw input +- +- tios.c_oflag &= ~OPOST; // raw output +- +- (void) memset(tios.c_cc, _POSIX_VDISABLE, NCCS); // disable all control chars ++ return initSocket(); ++} + +- tcsetattr(serialFd, TCSAFLUSH, &tios); // set EZSP serial port options ++void serialShutdown(void) ++{ ++ char buf[16]; + +- return EMBER_SUCCESS; ++ // If we aave a valid socket, leave it open and pass fd number to ++ // the new instance. ++ if (socketFd > 0) { ++ snprintf(buf, sizeof(buf), "%d", socketFd); ++ setenv("ZIGBEED_SOCKET_FD", buf, true); ++ } else { ++ unsetenv("ZIGBEED_SOCKET_FD"); ++ } + } + + EmberStatus emberSerialWriteByte(uint8_t port, uint8_t dataByte) +@@ -211,36 +258,18 @@ void sli_serial_adapter_tick_callback(void) + FD_ZERO(&mainloop.mWriteFdSet); + FD_ZERO(&mainloop.mErrorFdSet); + +-#ifdef ZIGBEE_PRO_COMPLIANCE_ON_HOST +- // pro-compliance on host has CLI interface +- // need to set pipeReadFd into the mainloop file descriptor. +- int pipeReadFd = sli_cli_get_pipe_read_fd(); +- FD_SET(pipeReadFd, &mainloop.mReadFdSet); +- FD_SET(pipeReadFd, &mainloop.mErrorFdSet); +- serialFd = (serialFd > pipeReadFd ? serialFd : pipeReadFd); +-#endif // ZIGBEE_PRO_COMPLIANCE_ON_HOST +- + // Update mainloop initial FD and its timeout value +- mainloop.mMaxFd = serialFd; ++ mainloop.mMaxFd = socketFd; + mainloop.mTimeout.tv_sec = timeoutMs / 1000; + mainloop.mTimeout.tv_usec = (timeoutMs - mainloop.mTimeout.tv_sec * 1000) * 1000; + + // Update mainloop FDs to monitor +- FD_SET(serialFd, &mainloop.mReadFdSet); +- FD_SET(serialFd, &mainloop.mErrorFdSet); ++ FD_SET(socketFd, &mainloop.mReadFdSet); ++ FD_SET(socketFd, &mainloop.mErrorFdSet); + otSysMainloopUpdate(NULL, &mainloop); + + if (otSysMainloopPoll(&mainloop) >= 0) { + otSysMainloopProcess(NULL, &mainloop); +-#ifdef ZIGBEE_PRO_COMPLIANCE_ON_HOST +- // If the command is handled by the CLI component, read the data +- // to empty the pipe so that it is ready for the next command. +- if (sli_cli_is_input_handled()) { +- char buff[SL_CLI_THREADED_HOST_PIPE_DATA_LENGTH]; +- assert(SL_CLI_THREADED_HOST_PIPE_DATA_LENGTH +- == read(sli_cli_get_pipe_read_fd(), buff, SL_CLI_THREADED_HOST_PIPE_DATA_LENGTH)); +- } +-#endif // ZIGBEE_PRO_COMPLIANCE_ON_HOST + } else if (errno != EINTR) { + //printf("%d\n", errno); + assert(false); +-- +2.39.0 + diff --git a/silabs-multiprotocol/icon.png b/silabs-multiprotocol/icon.png new file mode 100644 index 00000000000..aebde6cef00 Binary files /dev/null and b/silabs-multiprotocol/icon.png differ diff --git a/silabs-multiprotocol/images/architecture-old.png b/silabs-multiprotocol/images/architecture-old.png new file mode 100644 index 00000000000..63df739384a Binary files /dev/null and b/silabs-multiprotocol/images/architecture-old.png differ diff --git a/silabs-multiprotocol/images/architecture.png b/silabs-multiprotocol/images/architecture.png new file mode 100644 index 00000000000..c8b4fee5314 Binary files /dev/null and b/silabs-multiprotocol/images/architecture.png differ diff --git a/silabs-multiprotocol/logo.png b/silabs-multiprotocol/logo.png new file mode 100644 index 00000000000..b0013c9cb3a Binary files /dev/null and b/silabs-multiprotocol/logo.png differ diff --git a/silabs-multiprotocol/otbr-patches/0001-Avoid-writing-to-system-console.patch b/silabs-multiprotocol/otbr-patches/0001-Avoid-writing-to-system-console.patch new file mode 100644 index 00000000000..366cda920a5 --- /dev/null +++ b/silabs-multiprotocol/otbr-patches/0001-Avoid-writing-to-system-console.patch @@ -0,0 +1,30 @@ +From 53d4be5c893dac04a909563444453fb471852ccc Mon Sep 17 00:00:00 2001 +Message-Id: <53d4be5c893dac04a909563444453fb471852ccc.1677692173.git.stefan@agner.ch> +From: Stefan Agner +Date: Thu, 17 Feb 2022 22:57:16 +0100 +Subject: [PATCH] Avoid writing to system console + +Add-ons do not have a working syslog infrastructure. The LOG_CONS +options causes syslog() calls to log to the system console +(/dev/console). Avoid writing to system console as we use logging to +stderr. +--- + src/common/logging.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/common/logging.cpp b/src/common/logging.cpp +index 5398e47133..69f150dadb 100644 +--- a/src/common/logging.cpp ++++ b/src/common/logging.cpp +@@ -83,7 +83,7 @@ void otbrLogInit(const char *aIdent, otbrLogLevel aLevel, bool aPrintStderr) + assert(aIdent); + assert(aLevel >= OTBR_LOG_EMERG && aLevel <= OTBR_LOG_DEBUG); + +- openlog(aIdent, (LOG_CONS | LOG_PID) | (aPrintStderr ? LOG_PERROR : 0), OTBR_SYSLOG_FACILITY_ID); ++ openlog(aIdent, LOG_PID | (aPrintStderr ? LOG_PERROR : 0), LOG_USER); + sLevel = aLevel; + sDefaultLevel = sLevel; + } +-- +2.39.1 + diff --git a/silabs-multiprotocol/otbr-patches/0001-rest-support-erasing-all-persistent-info-1908.patch b/silabs-multiprotocol/otbr-patches/0001-rest-support-erasing-all-persistent-info-1908.patch new file mode 100644 index 00000000000..4976a8dd98c --- /dev/null +++ b/silabs-multiprotocol/otbr-patches/0001-rest-support-erasing-all-persistent-info-1908.patch @@ -0,0 +1,123 @@ +From 29c0b6b142c6692a53a83fb4604fc2bcebeb17af Mon Sep 17 00:00:00 2001 +Message-ID: <29c0b6b142c6692a53a83fb4604fc2bcebeb17af.1691047014.git.stefan@agner.ch> +From: Stefan Agner +Date: Thu, 13 Jul 2023 20:00:34 +0200 +Subject: [PATCH] [rest] support erasing all persistent info (#1908) + +Add REST API to support erasing all persistent information, effectively +factory resetting the OTBR. The implementation follows the semantic of +the D-Bus API and automatically disables the Thread network. + +After erasing all persistent information the dataset is cleared too. So +this allows to build a new Thread network with subsequent use of the +PUT method to the /node/dataset/active endpoint. +--- + src/rest/openapi.yaml | 9 +++++++++ + src/rest/resource.cpp | 38 ++++++++++++++++++++++++++++++++++---- + src/rest/resource.hpp | 1 + + src/rest/response.cpp | 2 +- + 4 files changed, 45 insertions(+), 5 deletions(-) + +diff --git a/src/rest/openapi.yaml b/src/rest/openapi.yaml +index 43747e2e01..2ba2a4dd56 100644 +--- a/src/rest/openapi.yaml ++++ b/src/rest/openapi.yaml +@@ -43,6 +43,15 @@ paths: + application/json: + schema: + type: object ++ delete: ++ tags: ++ - node ++ summary: Erase all persistent information, essentially factory reset the Border Router. ++ responses: ++ "200": ++ description: Successful operation ++ "409": ++ description: Thread interface is in wrong state. + /node/ba-id: + get: + tags: +diff --git a/src/rest/resource.cpp b/src/rest/resource.cpp +index 1139a2d788..a60e9d9483 100644 +--- a/src/rest/resource.cpp ++++ b/src/rest/resource.cpp +@@ -257,16 +257,46 @@ exit: + } + } + +-void Resource::NodeInfo(const Request &aRequest, Response &aResponse) const ++void Resource::DeleteNodeInfo(Response &aResponse) const + { ++ otbrError error = OTBR_ERROR_NONE; + std::string errorCode; +- if (aRequest.GetMethod() == HttpMethod::kGet) ++ ++ VerifyOrExit(mNcp->GetThreadHelper()->Detach() == OT_ERROR_NONE, error = OTBR_ERROR_INVALID_STATE); ++ VerifyOrExit(otInstanceErasePersistentInfo(mInstance) == OT_ERROR_NONE, error = OTBR_ERROR_REST); ++ mNcp->Reset(); ++ ++exit: ++ if (error == OTBR_ERROR_NONE) + { +- GetNodeInfo(aResponse); ++ errorCode = GetHttpStatus(HttpStatusCode::kStatusOk); ++ aResponse.SetResponsCode(errorCode); + } +- else ++ else if (error == OTBR_ERROR_INVALID_STATE) ++ { ++ ErrorHandler(aResponse, HttpStatusCode::kStatusConflict); ++ } ++ else if (error != OTBR_ERROR_NONE) + { ++ ErrorHandler(aResponse, HttpStatusCode::kStatusInternalServerError); ++ } ++} ++ ++void Resource::NodeInfo(const Request &aRequest, Response &aResponse) const ++{ ++ std::string errorCode; ++ ++ switch (aRequest.GetMethod()) ++ { ++ case HttpMethod::kGet: ++ GetNodeInfo(aResponse); ++ break; ++ case HttpMethod::kDelete: ++ DeleteNodeInfo(aResponse); ++ break; ++ default: + ErrorHandler(aResponse, HttpStatusCode::kStatusMethodNotAllowed); ++ break; + } + } + +diff --git a/src/rest/resource.hpp b/src/rest/resource.hpp +index 0c089c7296..d79085dbfc 100644 +--- a/src/rest/resource.hpp ++++ b/src/rest/resource.hpp +@@ -137,6 +137,7 @@ private: + void HandleDiagnosticCallback(const Request &aRequest, Response &aResponse); + + void GetNodeInfo(Response &aResponse) const; ++ void DeleteNodeInfo(Response &aResponse) const; + void GetDataBaId(Response &aResponse) const; + void GetDataExtendedAddr(Response &aResponse) const; + void GetDataState(Response &aResponse) const; +diff --git a/src/rest/response.cpp b/src/rest/response.cpp +index 93cbe0b6df..3460b90e1f 100644 +--- a/src/rest/response.cpp ++++ b/src/rest/response.cpp +@@ -34,7 +34,7 @@ + #define OT_REST_RESPONSE_ACCESS_CONTROL_ALLOW_HEADERS \ + "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, " \ + "Access-Control-Request-Headers" +-#define OT_REST_RESPONSE_ACCESS_CONTROL_ALLOW_METHOD "GET, OPTIONS, PUT" ++#define OT_REST_RESPONSE_ACCESS_CONTROL_ALLOW_METHOD "DELETE, GET, OPTIONS, PUT" + #define OT_REST_RESPONSE_CONNECTION "close" + + namespace otbr { +-- +2.41.0 + diff --git a/silabs-multiprotocol/otbr-patches/0002-rest-support-deleting-the-dataset.patch b/silabs-multiprotocol/otbr-patches/0002-rest-support-deleting-the-dataset.patch new file mode 100644 index 00000000000..876c67b00cb --- /dev/null +++ b/silabs-multiprotocol/otbr-patches/0002-rest-support-deleting-the-dataset.patch @@ -0,0 +1,126 @@ +From ab31af226c8d4ad1f46d03616e68a80f2a04a35e Mon Sep 17 00:00:00 2001 +Message-ID: +In-Reply-To: <29c0b6b142c6692a53a83fb4604fc2bcebeb17af.1691047014.git.stefan@agner.ch> +References: <29c0b6b142c6692a53a83fb4604fc2bcebeb17af.1691047014.git.stefan@agner.ch> +From: Stefan Agner +Date: Mon, 5 Jun 2023 23:41:50 +0200 +Subject: [PATCH] [rest] support deleting the dataset + +Add REST API to support deleting the active or pending operational +dataset. Deleting the active operational dataset requires the Thread +network to be disabled (just like modifying the active operational +dataset). Subsequent use of the PUT method allows to build entirly +new datasets with values generated by the stack (through +otDatasetCreateNewNetwork). +--- + src/rest/openapi.yaml | 21 +++++++++++++++++++++ + src/rest/resource.cpp | 35 +++++++++++++++++++++++++++++++++++ + src/rest/resource.hpp | 1 + + 3 files changed, 57 insertions(+) + +diff --git a/src/rest/openapi.yaml b/src/rest/openapi.yaml +index 2ba2a4dd56..2edc4af29a 100644 +--- a/src/rest/openapi.yaml ++++ b/src/rest/openapi.yaml +@@ -248,6 +248,18 @@ paths: + description: Invalid request body. + "409": + description: Writing active operational dataset rejected because Thread network is active. ++ delete: ++ tags: ++ - node ++ summary: Deletes the active operational dataset ++ description: |- ++ Deletes the the active operational dataset on the current node. Only allowed if the Thread node ++ is inactive. ++ responses: ++ "200": ++ description: Successfully deleted the active operational dataset. ++ "409": ++ description: Deleting active operational dataset rejected because Thread network is active. + /node/dataset/pending: + get: + tags: +@@ -291,6 +303,15 @@ paths: + description: Successfully created the pending operational dataset. + "400": + description: Invalid request body. ++ delete: ++ tags: ++ - node ++ summary: Deletes the pending operational dataset ++ description: |- ++ Deletes the the pending operational dataset on the current node. ++ responses: ++ "200": ++ description: Successfully deleted the active operational dataset. + components: + schemas: + LeaderData: +diff --git a/src/rest/resource.cpp b/src/rest/resource.cpp +index a60e9d9483..829835341a 100644 +--- a/src/rest/resource.cpp ++++ b/src/rest/resource.cpp +@@ -767,12 +767,47 @@ exit: + } + } + ++void Resource::DeleteDataset(DatasetType aDatasetType, Response &aResponse) const ++{ ++ otbrError error = OTBR_ERROR_NONE; ++ std::string errorCode = GetHttpStatus(HttpStatusCode::kStatusOk); ++ otOperationalDatasetTlvs datasetTlvs = {}; ++ ++ if (aDatasetType == DatasetType::kActive) ++ { ++ VerifyOrExit(otThreadGetDeviceRole(mInstance) == OT_DEVICE_ROLE_DISABLED, error = OTBR_ERROR_INVALID_STATE); ++ } ++ ++ if (aDatasetType == DatasetType::kActive) ++ { ++ VerifyOrExit(otDatasetSetActiveTlvs(mInstance, &datasetTlvs) == OT_ERROR_NONE, error = OTBR_ERROR_REST); ++ } ++ else if (aDatasetType == DatasetType::kPending) ++ { ++ VerifyOrExit(otDatasetSetPendingTlvs(mInstance, &datasetTlvs) == OT_ERROR_NONE, error = OTBR_ERROR_REST); ++ } ++ aResponse.SetResponsCode(errorCode); ++ ++exit: ++ if (error == OTBR_ERROR_INVALID_STATE) ++ { ++ ErrorHandler(aResponse, HttpStatusCode::kStatusConflict); ++ } ++ else if (error != OTBR_ERROR_NONE) ++ { ++ ErrorHandler(aResponse, HttpStatusCode::kStatusInternalServerError); ++ } ++} ++ + void Resource::Dataset(DatasetType aDatasetType, const Request &aRequest, Response &aResponse) const + { + std::string errorCode; + + switch (aRequest.GetMethod()) + { ++ case HttpMethod::kDelete: ++ DeleteDataset(aDatasetType, aResponse); ++ break; + case HttpMethod::kGet: + GetDataset(aDatasetType, aRequest, aResponse); + break; +diff --git a/src/rest/resource.hpp b/src/rest/resource.hpp +index d79085dbfc..362e501471 100644 +--- a/src/rest/resource.hpp ++++ b/src/rest/resource.hpp +@@ -150,6 +150,7 @@ private: + void GetDataRloc(Response &aResponse) const; + void GetDataset(DatasetType aDatasetType, const Request &aRequest, Response &aResponse) const; + void SetDataset(DatasetType aDatasetType, const Request &aRequest, Response &aResponse) const; ++ void DeleteDataset(DatasetType aDatasetType, Response &aResponse) const; + + void DeleteOutDatedDiagnostic(void); + void UpdateDiag(std::string aKey, std::vector &aDiag); +-- +2.41.0 + diff --git a/silabs-multiprotocol/otbr-patches/0003-mdns-update-mDNSResponder-to-1790.80.10.patch b/silabs-multiprotocol/otbr-patches/0003-mdns-update-mDNSResponder-to-1790.80.10.patch new file mode 100644 index 00000000000..854de89214e --- /dev/null +++ b/silabs-multiprotocol/otbr-patches/0003-mdns-update-mDNSResponder-to-1790.80.10.patch @@ -0,0 +1,66 @@ +From b7c0c61b56d32ec5fc65160d10c0fd66f0ac9c8a Mon Sep 17 00:00:00 2001 +Message-ID: +In-Reply-To: <29c0b6b142c6692a53a83fb4604fc2bcebeb17af.1691047014.git.stefan@agner.ch> +References: <29c0b6b142c6692a53a83fb4604fc2bcebeb17af.1691047014.git.stefan@agner.ch> +From: Stefan Agner +Date: Wed, 21 Jun 2023 12:04:33 +0200 +Subject: [PATCH] [mdns] update mDNSResponder to 1790.80.10 + +--- + script/bootstrap | 11 +++++------ + tests/scripts/bootstrap.sh | 9 ++++----- + 2 files changed, 9 insertions(+), 11 deletions(-) + +diff --git a/script/bootstrap b/script/bootstrap +index 0b72aa4971..2256f5e437 100755 +--- a/script/bootstrap ++++ b/script/bootstrap +@@ -56,16 +56,15 @@ install_packages_apt() + + # mDNS + sudo apt-get install --no-install-recommends -y libavahi-client3 libavahi-common-dev libavahi-client-dev avahi-daemon +- (MDNS_RESPONDER_SOURCE_NAME=mDNSResponder-1310.80.1 \ ++ (MDNS_RESPONDER_SOURCE_NAME=mDNSResponder-1790.80.10 \ + && cd /tmp \ + && wget --no-check-certificate https://github.com/apple-oss-distributions/mDNSResponder/archive/refs/tags/$MDNS_RESPONDER_SOURCE_NAME.tar.gz \ + && mkdir -p $MDNS_RESPONDER_SOURCE_NAME \ + && tar xvf $MDNS_RESPONDER_SOURCE_NAME.tar.gz -C $MDNS_RESPONDER_SOURCE_NAME --strip-components=1 \ +- && cd /tmp/$MDNS_RESPONDER_SOURCE_NAME/Clients \ +- && sed -i '/#include /a #include ' dns-sd.c \ +- && sed -i '/#include /a #include ' dns-sd.c \ +- && cd /tmp/$MDNS_RESPONDER_SOURCE_NAME/mDNSPosix \ +- && make os=linux && sudo make install os=linux) ++ && cd /tmp/"$MDNS_RESPONDER_SOURCE_NAME"/mDNSShared \ ++ && sed -i 's/__block mStatus err;/mStatus err;/' uds_daemon.c \ ++ && cd /tmp/"$MDNS_RESPONDER_SOURCE_NAME"/mDNSPosix \ ++ && make os=linux tls=no && sudo make install os=linux tls=no) + + # Boost + sudo apt-get install --no-install-recommends -y libboost-dev libboost-filesystem-dev libboost-system-dev +diff --git a/tests/scripts/bootstrap.sh b/tests/scripts/bootstrap.sh +index a89e9ccd6e..6b4affffce 100755 +--- a/tests/scripts/bootstrap.sh ++++ b/tests/scripts/bootstrap.sh +@@ -126,15 +126,14 @@ case "$(uname)" in + fi + + if [ "${OTBR_MDNS-}" == 'mDNSResponder' ]; then +- SOURCE_NAME=mDNSResponder-1310.80.1 ++ SOURCE_NAME=mDNSResponder-1790.80.10 + wget https://github.com/apple-oss-distributions/mDNSResponder/archive/refs/tags/$SOURCE_NAME.tar.gz \ + && mkdir -p $SOURCE_NAME \ + && tar xvf $SOURCE_NAME.tar.gz -C $SOURCE_NAME --strip-components=1 \ +- && cd $SOURCE_NAME/Clients \ +- && sed -i '/#include /a #include ' dns-sd.c \ +- && sed -i '/#include /a #include ' dns-sd.c \ ++ && cd "$SOURCE_NAME"/mDNSShared \ ++ && sed -i 's/__block mStatus err;/mStatus err;/' uds_daemon.c \ + && cd ../mDNSPosix \ +- && make os=linux && sudo make install os=linux ++ && make os=linux tls=no && sudo make install os=linux tls=no + fi + + # Enable IPv6 +-- +2.41.0 + diff --git a/silabs-multiprotocol/otbr-patches/0004-mdns-add-Linux-specific-patches.patch b/silabs-multiprotocol/otbr-patches/0004-mdns-add-Linux-specific-patches.patch new file mode 100644 index 00000000000..58feb40c2ca --- /dev/null +++ b/silabs-multiprotocol/otbr-patches/0004-mdns-add-Linux-specific-patches.patch @@ -0,0 +1,1004 @@ +From ae25221254a6e59e51bac2cce981e1bcc313446a Mon Sep 17 00:00:00 2001 +Message-ID: +In-Reply-To: <29c0b6b142c6692a53a83fb4604fc2bcebeb17af.1691047014.git.stefan@agner.ch> +References: <29c0b6b142c6692a53a83fb4604fc2bcebeb17af.1691047014.git.stefan@agner.ch> +From: Stefan Agner +Date: Fri, 23 Jun 2023 10:38:07 +0200 +Subject: [PATCH] [mdns] add Linux specific patches + +--- + etc/docker/Dockerfile | 1 + + script/bootstrap | 11 +- + tests/scripts/bootstrap.sh | 11 +- + .../mDNSResponder/0001-Fix-Linux-build.patch | 32 +++ + ...utine-for-cleaning-recent-interfaces.patch | 64 +++++ + ...outine-for-tearing-down-an-interface.patch | 62 +++++ + .../0004-Track-interface-socket-family.patch | 54 ++++ + ...cate-loopback-interface-to-mDNS-core.patch | 61 +++++ + ...0006-Use-list-for-changed-interfaces.patch | 178 ++++++++++++ + .../0007-Handle-noisy-netlink-sockets.patch | 255 ++++++++++++++++++ + ...-deleted-interfaces-as-being-changed.patch | 43 +++ + ...0009-Handle-errors-from-socket-calls.patch | 66 +++++ + ...10-Handle-interface-without-ifa_addr.patch | 41 +++ + 13 files changed, 873 insertions(+), 6 deletions(-) + create mode 100644 third_party/mDNSResponder/0001-Fix-Linux-build.patch + create mode 100644 third_party/mDNSResponder/0002-Create-subroutine-for-cleaning-recent-interfaces.patch + create mode 100644 third_party/mDNSResponder/0003-Create-subroutine-for-tearing-down-an-interface.patch + create mode 100644 third_party/mDNSResponder/0004-Track-interface-socket-family.patch + create mode 100644 third_party/mDNSResponder/0005-Indicate-loopback-interface-to-mDNS-core.patch + create mode 100644 third_party/mDNSResponder/0006-Use-list-for-changed-interfaces.patch + create mode 100644 third_party/mDNSResponder/0007-Handle-noisy-netlink-sockets.patch + create mode 100644 third_party/mDNSResponder/0008-Mark-deleted-interfaces-as-being-changed.patch + create mode 100644 third_party/mDNSResponder/0009-Handle-errors-from-socket-calls.patch + create mode 100644 third_party/mDNSResponder/0010-Handle-interface-without-ifa_addr.patch + +diff --git a/script/bootstrap b/script/bootstrap +index 2256f5e437..2ad1d0800b 100755 +--- a/script/bootstrap ++++ b/script/bootstrap +@@ -57,13 +57,18 @@ install_packages_apt() + # mDNS + sudo apt-get install --no-install-recommends -y libavahi-client3 libavahi-common-dev libavahi-client-dev avahi-daemon + (MDNS_RESPONDER_SOURCE_NAME=mDNSResponder-1790.80.10 \ ++ && MDNS_RESPONDER_PATCH_PATH=$(realpath "$(dirname "$0")"/../third_party/mDNSResponder) \ + && cd /tmp \ + && wget --no-check-certificate https://github.com/apple-oss-distributions/mDNSResponder/archive/refs/tags/$MDNS_RESPONDER_SOURCE_NAME.tar.gz \ + && mkdir -p $MDNS_RESPONDER_SOURCE_NAME \ + && tar xvf $MDNS_RESPONDER_SOURCE_NAME.tar.gz -C $MDNS_RESPONDER_SOURCE_NAME --strip-components=1 \ +- && cd /tmp/"$MDNS_RESPONDER_SOURCE_NAME"/mDNSShared \ +- && sed -i 's/__block mStatus err;/mStatus err;/' uds_daemon.c \ +- && cd /tmp/"$MDNS_RESPONDER_SOURCE_NAME"/mDNSPosix \ ++ && cd /tmp/"$MDNS_RESPONDER_SOURCE_NAME" \ ++ && ( ++ for patch in "$MDNS_RESPONDER_PATCH_PATH"/*.patch; do ++ patch -p1 <"$patch" ++ done ++ ) \ ++ && cd mDNSPosix \ + && make os=linux tls=no && sudo make install os=linux tls=no) + + # Boost +diff --git a/tests/scripts/bootstrap.sh b/tests/scripts/bootstrap.sh +index 6b4affffce..42182b8748 100755 +--- a/tests/scripts/bootstrap.sh ++++ b/tests/scripts/bootstrap.sh +@@ -127,12 +127,17 @@ case "$(uname)" in + + if [ "${OTBR_MDNS-}" == 'mDNSResponder' ]; then + SOURCE_NAME=mDNSResponder-1790.80.10 ++ PATCH_PATH=$(realpath "$(dirname "$0")"/../../third_party/mDNSResponder) + wget https://github.com/apple-oss-distributions/mDNSResponder/archive/refs/tags/$SOURCE_NAME.tar.gz \ + && mkdir -p $SOURCE_NAME \ + && tar xvf $SOURCE_NAME.tar.gz -C $SOURCE_NAME --strip-components=1 \ +- && cd "$SOURCE_NAME"/mDNSShared \ +- && sed -i 's/__block mStatus err;/mStatus err;/' uds_daemon.c \ +- && cd ../mDNSPosix \ ++ && cd "$SOURCE_NAME" \ ++ && ( ++ for patch in "$PATCH_PATH"/*.patch; do ++ patch -p1 <"$patch" ++ done ++ ) \ ++ && cd mDNSPosix \ + && make os=linux tls=no && sudo make install os=linux tls=no + fi + +diff --git a/third_party/mDNSResponder/0001-Fix-Linux-build.patch b/third_party/mDNSResponder/0001-Fix-Linux-build.patch +new file mode 100644 +index 0000000000..1dc01f3fca +--- /dev/null ++++ b/third_party/mDNSResponder/0001-Fix-Linux-build.patch +@@ -0,0 +1,32 @@ ++From e136dcdcdd93ef32ada981e89c195905eb809eea Mon Sep 17 00:00:00 2001 ++Message-ID: ++From: Nate Karstens ++Date: Thu, 23 Mar 2023 00:15:52 -0500 ++Subject: [PATCH] Fix Linux build ++ ++The __block qualifier is not used in Linux builds. ++ ++Signed-off-by: Nate Karstens ++--- ++ mDNSShared/uds_daemon.c | 4 ++++ ++ 1 file changed, 4 insertions(+) ++ ++diff --git a/mDNSShared/uds_daemon.c b/mDNSShared/uds_daemon.c ++index 9ae5f78..5a00bb5 100644 ++--- a/mDNSShared/uds_daemon.c +++++ b/mDNSShared/uds_daemon.c ++@@ -2912,7 +2912,11 @@ exit: ++ mDNSlocal mStatus add_domain_to_browser(request_state *info, const domainname *d) ++ { ++ browser_t *b, *p; +++#if defined(TARGET_OS_MAC) && TARGET_OS_MAC ++ __block mStatus err; +++#else +++ mStatus err; +++#endif ++ ++ for (p = info->u.browser.browsers; p; p = p->next) ++ { ++-- ++2.41.0 ++ +diff --git a/third_party/mDNSResponder/0002-Create-subroutine-for-cleaning-recent-interfaces.patch b/third_party/mDNSResponder/0002-Create-subroutine-for-cleaning-recent-interfaces.patch +new file mode 100644 +index 0000000000..98da74c500 +--- /dev/null ++++ b/third_party/mDNSResponder/0002-Create-subroutine-for-cleaning-recent-interfaces.patch +@@ -0,0 +1,64 @@ ++From 4f7970ac1615aba7a39ae94c1ca14135265574e9 Mon Sep 17 00:00:00 2001 ++Message-ID: <4f7970ac1615aba7a39ae94c1ca14135265574e9.1687508149.git.stefan@agner.ch> ++In-Reply-To: ++References: ++From: Nate Karstens ++Date: Wed, 28 Jun 2017 17:30:00 -0500 ++Subject: [PATCH] Create subroutine for cleaning recent interfaces ++ ++Moves functionality for cleaning the list of recent ++interfaces into its own subroutine. ++ ++Upstream-Status: Submitted [dts@apple.com] ++ ++Signed-off-by: Nate Karstens ++Signed-off-by: Alex Kiernan ++--- ++ mDNSPosix/mDNSPosix.c | 24 ++++++++++++++---------- ++ 1 file changed, 14 insertions(+), 10 deletions(-) ++ ++diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c ++index 0a7c3df..fe7242d 100644 ++--- a/mDNSPosix/mDNSPosix.c +++++ b/mDNSPosix/mDNSPosix.c ++@@ -1322,6 +1322,19 @@ mDNSlocal int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interf ++ return err; ++ } ++ +++// Clean up any interfaces that have been hanging around on the RecentInterfaces list for more than a minute +++mDNSlocal void CleanRecentInterfaces(void) +++{ +++ PosixNetworkInterface **ri = &gRecentInterfaces; +++ const mDNSs32 utc = mDNSPlatformUTC(); +++ while (*ri) +++ { +++ PosixNetworkInterface *pi = *ri; +++ if (utc - pi->LastSeen < 60) ri = (PosixNetworkInterface **)&pi->coreIntf.next; +++ else { *ri = (PosixNetworkInterface *)pi->coreIntf.next; mdns_free(pi); } +++ } +++} +++ ++ // Creates a PosixNetworkInterface for the interface whose IP address is ++ // intfAddr and whose name is intfName and registers it with mDNS core. ++ mDNSlocal int SetupOneInterface(mDNS *const m, struct sockaddr *intfAddr, struct sockaddr *intfMask, ++@@ -1559,16 +1572,7 @@ mDNSlocal int SetupInterfaceList(mDNS *const m) ++ ++ // Clean up. ++ if (intfList != NULL) freeifaddrs(intfList); ++- ++- // Clean up any interfaces that have been hanging around on the RecentInterfaces list for more than a minute ++- PosixNetworkInterface **ri = &gRecentInterfaces; ++- const mDNSs32 utc = mDNSPlatformUTC(); ++- while (*ri) ++- { ++- PosixNetworkInterface *pi = *ri; ++- if (utc - pi->LastSeen < 60) ri = (PosixNetworkInterface **)&pi->coreIntf.next; ++- else { *ri = (PosixNetworkInterface *)pi->coreIntf.next; mdns_free(pi); } ++- } +++ CleanRecentInterfaces(); ++ ++ return err; ++ } ++-- ++2.41.0 ++ +diff --git a/third_party/mDNSResponder/0003-Create-subroutine-for-tearing-down-an-interface.patch b/third_party/mDNSResponder/0003-Create-subroutine-for-tearing-down-an-interface.patch +new file mode 100644 +index 0000000000..812bd20c57 +--- /dev/null ++++ b/third_party/mDNSResponder/0003-Create-subroutine-for-tearing-down-an-interface.patch +@@ -0,0 +1,62 @@ ++From f7ab91f739b936305ca56743adfb4673e3f2f4ba Mon Sep 17 00:00:00 2001 ++Message-ID: ++In-Reply-To: ++References: ++From: Nate Karstens ++Date: Wed, 28 Jun 2017 17:30:00 -0500 ++Subject: [PATCH] Create subroutine for tearing down an interface ++ ++Creates a subroutine for tearing down an interface. ++ ++Upstream-Status: Submitted [dts@apple.com] ++ ++Signed-off-by: Nate Karstens ++Signed-off-by: Alex Kiernan ++--- ++ mDNSPosix/mDNSPosix.c | 22 ++++++++++++++++------ ++ 1 file changed, 16 insertions(+), 6 deletions(-) ++ ++diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c ++index fe7242d..a32a880 100644 ++--- a/mDNSPosix/mDNSPosix.c +++++ b/mDNSPosix/mDNSPosix.c ++@@ -1043,6 +1043,19 @@ mDNSlocal void FreePosixNetworkInterface(PosixNetworkInterface *intf) ++ gRecentInterfaces = intf; ++ } ++ +++mDNSlocal void TearDownInterface(mDNS *const m, PosixNetworkInterface *intf) +++{ +++ mDNS_DeregisterInterface(m, &intf->coreIntf, NormalActivation); +++ if (gMDNSPlatformPosixVerboseLevel > 0) fprintf(stderr, "Deregistered interface %s\n", intf->intfName); +++ FreePosixNetworkInterface(intf); +++ +++ num_registered_interfaces--; +++ if (num_registered_interfaces == 0) { +++ num_pkts_accepted = 0; +++ num_pkts_rejected = 0; +++ } +++} +++ ++ // Grab the first interface, deregister it, free it, and repeat until done. ++ mDNSlocal void ClearInterfaceList(mDNS *const m) ++ { ++@@ -1051,13 +1064,10 @@ mDNSlocal void ClearInterfaceList(mDNS *const m) ++ while (m->HostInterfaces) ++ { ++ PosixNetworkInterface *intf = (PosixNetworkInterface*)(m->HostInterfaces); ++- mDNS_DeregisterInterface(m, &intf->coreIntf, NormalActivation); ++- if (gMDNSPlatformPosixVerboseLevel > 0) fprintf(stderr, "Deregistered interface %s\n", intf->intfName); ++- FreePosixNetworkInterface(intf); +++ TearDownInterface(m, intf); ++ } ++- num_registered_interfaces = 0; ++- num_pkts_accepted = 0; ++- num_pkts_rejected = 0; +++ +++ assert(num_registered_interfaces == 0); ++ } ++ ++ mDNSlocal int SetupIPv6Socket(int fd) ++-- ++2.41.0 ++ +diff --git a/third_party/mDNSResponder/0004-Track-interface-socket-family.patch b/third_party/mDNSResponder/0004-Track-interface-socket-family.patch +new file mode 100644 +index 0000000000..48fbc741b8 +--- /dev/null ++++ b/third_party/mDNSResponder/0004-Track-interface-socket-family.patch +@@ -0,0 +1,54 @@ ++From 542c1b2ce1dcc069cf848d11978c8b6ae5982b6e Mon Sep 17 00:00:00 2001 ++Message-ID: <542c1b2ce1dcc069cf848d11978c8b6ae5982b6e.1687508149.git.stefan@agner.ch> ++In-Reply-To: ++References: ++From: Nate Karstens ++Date: Wed, 28 Jun 2017 17:30:00 -0500 ++Subject: [PATCH] Track interface socket family ++ ++Tracks the socket family associated with the interface. ++ ++Upstream-Status: Submitted [dts@apple.com] ++ ++Signed-off-by: Nate Karstens ++Signed-off-by: Alex Kiernan ++--- ++ mDNSPosix/mDNSPosix.c | 1 + ++ mDNSPosix/mDNSPosix.h | 2 ++ ++ 2 files changed, 3 insertions(+) ++ ++diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c ++index a32a880..9a5b4d7 100644 ++--- a/mDNSPosix/mDNSPosix.c +++++ b/mDNSPosix/mDNSPosix.c ++@@ -1415,6 +1415,7 @@ mDNSlocal int SetupOneInterface(mDNS *const m, struct sockaddr *intfAddr, struct ++ // Set up the extra fields in PosixNetworkInterface. ++ assert(intf->intfName != NULL); // intf->intfName already set up above ++ intf->index = intfIndex; +++ intf->sa_family = intfAddr->sa_family; ++ intf->multicastSocket4 = -1; ++ #if HAVE_IPV6 ++ intf->multicastSocket6 = -1; ++diff --git a/mDNSPosix/mDNSPosix.h b/mDNSPosix/mDNSPosix.h ++index 9675591..dd7864c 100644 ++--- a/mDNSPosix/mDNSPosix.h +++++ b/mDNSPosix/mDNSPosix.h ++@@ -19,6 +19,7 @@ ++ #define __mDNSPlatformPosix_h ++ ++ #include +++#include ++ #include ++ ++ #ifdef __cplusplus ++@@ -40,6 +41,7 @@ struct PosixNetworkInterface ++ char * intfName; ++ PosixNetworkInterface * aliasIntf; ++ int index; +++ sa_family_t sa_family; ++ int multicastSocket4; ++ #if HAVE_IPV6 ++ int multicastSocket6; ++-- ++2.41.0 ++ +diff --git a/third_party/mDNSResponder/0005-Indicate-loopback-interface-to-mDNS-core.patch b/third_party/mDNSResponder/0005-Indicate-loopback-interface-to-mDNS-core.patch +new file mode 100644 +index 0000000000..f7aa461767 +--- /dev/null ++++ b/third_party/mDNSResponder/0005-Indicate-loopback-interface-to-mDNS-core.patch +@@ -0,0 +1,61 @@ ++From 44385771ef63f081ed7e80eae6f24591046b4c7c Mon Sep 17 00:00:00 2001 ++Message-ID: <44385771ef63f081ed7e80eae6f24591046b4c7c.1687508149.git.stefan@agner.ch> ++In-Reply-To: ++References: ++From: Nate Karstens ++Date: Tue, 1 Aug 2017 17:06:01 -0500 ++Subject: [PATCH] Indicate loopback interface to mDNS core ++ ++Tells the mDNS core if an interface is a loopback interface, ++similar to AddInterfaceToList() in the MacOS implementation. ++ ++Upstream-Status: Submitted [dts@apple.com] ++ ++Signed-off-by: Nate Karstens ++Signed-off-by: Alex Kiernan ++--- ++ mDNSPosix/mDNSPosix.c | 7 ++++--- ++ 1 file changed, 4 insertions(+), 3 deletions(-) ++ ++diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c ++index 9a5b4d7..02a19b4 100644 ++--- a/mDNSPosix/mDNSPosix.c +++++ b/mDNSPosix/mDNSPosix.c ++@@ -1348,7 +1348,7 @@ mDNSlocal void CleanRecentInterfaces(void) ++ // Creates a PosixNetworkInterface for the interface whose IP address is ++ // intfAddr and whose name is intfName and registers it with mDNS core. ++ mDNSlocal int SetupOneInterface(mDNS *const m, struct sockaddr *intfAddr, struct sockaddr *intfMask, ++- const mDNSu8 *intfHaddr, mDNSu16 intfHlen, const char *intfName, int intfIndex) +++ const mDNSu8 *intfHaddr, mDNSu16 intfHlen, const char *intfName, int intfIndex, int intfFlags) ++ { ++ int err = 0; ++ PosixNetworkInterface *intf; ++@@ -1411,6 +1411,7 @@ mDNSlocal int SetupOneInterface(mDNS *const m, struct sockaddr *intfAddr, struct ++ ++ intf->coreIntf.Advertise = m->AdvertiseLocalAddresses; ++ intf->coreIntf.McastTxRx = mDNStrue; +++ intf->coreIntf.Loopback = ((intfFlags & IFF_LOOPBACK) != 0) ? mDNStrue : mDNSfalse; ++ ++ // Set up the extra fields in PosixNetworkInterface. ++ assert(intf->intfName != NULL); // intf->intfName already set up above ++@@ -1561,7 +1562,7 @@ mDNSlocal int SetupInterfaceList(mDNS *const m) ++ } ++ #endif ++ if (SetupOneInterface(m, i->ifa_addr, i->ifa_netmask, ++- hwaddr, hwaddr_len, i->ifa_name, ifIndex) == 0) +++ hwaddr, hwaddr_len, i->ifa_name, ifIndex, i->ifa_flags) == 0) ++ { ++ if (i->ifa_addr->sa_family == AF_INET) ++ foundav4 = mDNStrue; ++@@ -1578,7 +1579,7 @@ mDNSlocal int SetupInterfaceList(mDNS *const m) ++ // if ((m->HostInterfaces == NULL) && (firstLoopback != NULL)) ++ if (!foundav4 && firstLoopback) ++ (void) SetupOneInterface(m, firstLoopback->ifa_addr, firstLoopback->ifa_netmask, ++- NULL, 0, firstLoopback->ifa_name, firstLoopbackIndex); +++ NULL, 0, firstLoopback->ifa_name, firstLoopbackIndex, firstLoopback->ifa_flags); ++ } ++ ++ // Clean up. ++-- ++2.41.0 ++ +diff --git a/third_party/mDNSResponder/0006-Use-list-for-changed-interfaces.patch b/third_party/mDNSResponder/0006-Use-list-for-changed-interfaces.patch +new file mode 100644 +index 0000000000..87ac19074d +--- /dev/null ++++ b/third_party/mDNSResponder/0006-Use-list-for-changed-interfaces.patch +@@ -0,0 +1,178 @@ ++From 2a0f873184068f21e1d0d2a3e0d8c26bc705bf88 Mon Sep 17 00:00:00 2001 ++Message-ID: <2a0f873184068f21e1d0d2a3e0d8c26bc705bf88.1687508149.git.stefan@agner.ch> ++In-Reply-To: ++References: ++From: Nate Karstens ++Date: Thu, 13 Jul 2017 09:00:00 -0500 ++Subject: [PATCH] Use list for changed interfaces ++ ++Uses a linked list to store the index of changed network interfaces ++instead of a bitfield. This allows for network interfaces with an ++index greater than 31 (an index of 36 was seen on Android). ++ ++Upstream-Status: Submitted [dts@apple.com] ++ ++Signed-off-by: Nate Karstens ++Signed-off-by: Alex Kiernan ++Change-Id: Ibeab0ec68ca0d21da8384d4362e59afd2951f138 ++--- ++ mDNSPosix/mDNSPosix.c | 60 +++++++++++++++++++++++++++++++------------ ++ 1 file changed, 44 insertions(+), 16 deletions(-) ++ ++diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c ++index 02a19b4..9867881 100644 ++--- a/mDNSPosix/mDNSPosix.c +++++ b/mDNSPosix/mDNSPosix.c ++@@ -74,6 +74,14 @@ struct IfChangeRec ++ }; ++ typedef struct IfChangeRec IfChangeRec; ++ +++// Used to build a list of network interface indices +++struct NetworkInterfaceIndex +++{ +++ int if_index; +++ struct NetworkInterfaceIndex *Next; +++}; +++typedef struct NetworkInterfaceIndex NetworkInterfaceIndex; +++ ++ // Note that static data is initialized to zero in (modern) C. ++ static PosixEventSource *gEventSources; // linked list of PosixEventSource's ++ static sigset_t gEventSignalSet; // Signals which event loop listens for ++@@ -1621,6 +1629,23 @@ mDNSlocal mStatus OpenIfNotifySocket(int *pFD) ++ return err; ++ } ++ +++mDNSlocal void AddInterfaceIndexToList(GenLinkedList *list, int if_index) +++{ +++ NetworkInterfaceIndex *item; +++ +++ for (item = (NetworkInterfaceIndex*)list->Head; item != NULL; item = item->Next) +++ { +++ if (if_index == item->if_index) return; +++ } +++ +++ item = mdns_malloc(sizeof *item); +++ if (item == NULL) return; +++ +++ item->if_index = if_index; +++ item->Next = NULL; +++ AddToTail(list, item); +++} +++ ++ #if MDNS_DEBUGMSGS ++ mDNSlocal void PrintNetLinkMsg(const struct nlmsghdr *pNLMsg) ++ { ++@@ -1648,14 +1673,13 @@ mDNSlocal void PrintNetLinkMsg(const struct nlmsghdr *pNLMsg) ++ } ++ #endif ++ ++-mDNSlocal mDNSu32 ProcessRoutingNotification(int sd) +++mDNSlocal void ProcessRoutingNotification(int sd, GenLinkedList *changedInterfaces) ++ // Read through the messages on sd and if any indicate that any interface records should ++ // be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0. ++ { ++ ssize_t readCount; ++ char buff[4096]; ++ struct nlmsghdr *pNLMsg = (struct nlmsghdr*) buff; ++- mDNSu32 result = 0; ++ ++ // The structure here is more complex than it really ought to be because, ++ // unfortunately, there's no good way to size a buffer in advance large ++@@ -1691,9 +1715,9 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd) ++ ++ // Process the NetLink message ++ if (pNLMsg->nlmsg_type == RTM_GETLINK || pNLMsg->nlmsg_type == RTM_NEWLINK) ++- result |= 1 << ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index; +++ AddInterfaceIndexToList(changedInterfaces, ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index); ++ else if (pNLMsg->nlmsg_type == RTM_DELADDR || pNLMsg->nlmsg_type == RTM_NEWADDR) ++- result |= 1 << ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index; +++ AddInterfaceIndexToList(changedInterfaces, ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index); ++ ++ // Advance pNLMsg to the next message in the buffer ++ if ((pNLMsg->nlmsg_flags & NLM_F_MULTI) != 0 && pNLMsg->nlmsg_type != NLMSG_DONE) ++@@ -1704,8 +1728,6 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd) ++ else ++ break; // all done! ++ } ++- ++- return result; ++ } ++ ++ #else // USES_NETLINK ++@@ -1737,18 +1759,17 @@ mDNSlocal void PrintRoutingSocketMsg(const struct ifa_msghdr *pRSMsg) ++ } ++ #endif ++ ++-mDNSlocal mDNSu32 ProcessRoutingNotification(int sd) +++mDNSlocal void ProcessRoutingNotification(int sd, GenLinkedList *changedInterfaces) ++ // Read through the messages on sd and if any indicate that any interface records should ++ // be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0. ++ { ++ ssize_t readCount; ++ char buff[4096]; ++ struct ifa_msghdr *pRSMsg = (struct ifa_msghdr*) buff; ++- mDNSu32 result = 0; ++ ++ readCount = read(sd, buff, sizeof buff); ++ if (readCount < (ssize_t) sizeof(struct ifa_msghdr)) ++- return mStatus_UnsupportedErr; // cannot decipher message +++ return; // cannot decipher message ++ ++ #if MDNS_DEBUGMSGS ++ PrintRoutingSocketMsg(pRSMsg); ++@@ -1759,12 +1780,10 @@ mDNSlocal mDNSu32 ProcessRoutingNotification(int sd) ++ pRSMsg->ifam_type == RTM_IFINFO) ++ { ++ if (pRSMsg->ifam_type == RTM_IFINFO) ++- result |= 1 << ((struct if_msghdr*) pRSMsg)->ifm_index; +++ AddInterfaceIndexToList(changedInterfaces, ((struct if_msghdr*) pRSMsg)->ifm_index); ++ else ++- result |= 1 << pRSMsg->ifam_index; +++ AddInterfaceIndexToList(changedInterfaces, pRSMsg->ifam_index); ++ } ++- ++- return result; ++ } ++ ++ #endif // USES_NETLINK ++@@ -1774,7 +1793,8 @@ mDNSlocal void InterfaceChangeCallback(int fd, void *context) ++ { ++ IfChangeRec *pChgRec = (IfChangeRec*) context; ++ fd_set readFDs; ++- mDNSu32 changedInterfaces = 0; +++ GenLinkedList changedInterfaces; +++ NetworkInterfaceIndex *changedInterface; ++ struct timeval zeroTimeout = { 0, 0 }; ++ ++ (void)fd; // Unused ++@@ -1782,17 +1802,25 @@ mDNSlocal void InterfaceChangeCallback(int fd, void *context) ++ FD_ZERO(&readFDs); ++ FD_SET(pChgRec->NotifySD, &readFDs); ++ +++ InitLinkedList(&changedInterfaces, offsetof(NetworkInterfaceIndex, Next)); +++ ++ do ++ { ++- changedInterfaces |= ProcessRoutingNotification(pChgRec->NotifySD); +++ ProcessRoutingNotification(pChgRec->NotifySD, &changedInterfaces); ++ } ++ while (0 < select(pChgRec->NotifySD + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout)); ++ ++ // Currently we rebuild the entire interface list whenever any interface change is ++ // detected. If this ever proves to be a performance issue in a multi-homed ++ // configuration, more care should be paid to changedInterfaces. ++- if (changedInterfaces) +++ if (changedInterfaces.Head != NULL) ++ mDNSPlatformPosixRefreshInterfaceList(pChgRec->mDNS); +++ +++ while ((changedInterface = (NetworkInterfaceIndex*)changedInterfaces.Head) != NULL) +++ { +++ RemoveFromList(&changedInterfaces, changedInterface); +++ mdns_free(changedInterface); +++ } ++ } ++ ++ // Register with either a Routing Socket or RtNetLink to listen for interface changes. ++-- ++2.41.0 ++ +diff --git a/third_party/mDNSResponder/0007-Handle-noisy-netlink-sockets.patch b/third_party/mDNSResponder/0007-Handle-noisy-netlink-sockets.patch +new file mode 100644 +index 0000000000..08cce016b0 +--- /dev/null ++++ b/third_party/mDNSResponder/0007-Handle-noisy-netlink-sockets.patch +@@ -0,0 +1,255 @@ ++From 00289e89cccb9567d6ea6bd2a394fd14b61e5ad1 Mon Sep 17 00:00:00 2001 ++Message-ID: <00289e89cccb9567d6ea6bd2a394fd14b61e5ad1.1687508149.git.stefan@agner.ch> ++In-Reply-To: ++References: ++From: Nate Karstens ++Date: Mon, 24 Jul 2017 09:38:55 -0500 ++Subject: [PATCH] Handle noisy netlink sockets ++ ++The POSIX implementation currently clears all network interfaces ++when netlink indicates that there has been a change. This causes ++the following problems: ++ ++ 1) Applications are informed that all of the services they are ++ tracking have been removed. ++ 2) Increases network load because the client must re-query for ++ all records it is interested in. ++ ++This changes netlink notification handling by: ++ ++ 1) Always comparing with the latest interface list returned ++ by the OS. ++ 2) Confirming that the interface has been changed in a way ++ that we care about. ++ ++Upstream-Status: Submitted [dts@apple.com] ++ ++Signed-off-by: Nate Karstens ++Signed-off-by: Alex Kiernan ++--- ++ mDNSPosix/mDNSPosix.c | 182 +++++++++++++++++++++++++++++++++++++++--- ++ 1 file changed, 172 insertions(+), 10 deletions(-) ++ ++diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c ++index 9867881..ad7000d 100644 ++--- a/mDNSPosix/mDNSPosix.c +++++ b/mDNSPosix/mDNSPosix.c ++@@ -1788,14 +1788,43 @@ mDNSlocal void ProcessRoutingNotification(int sd, GenLinkedList *change ++ ++ #endif // USES_NETLINK ++ +++// Test whether the given PosixNetworkInterface matches the given struct ifaddrs +++mDNSlocal mDNSBool InterfacesMatch(PosixNetworkInterface *intf, struct ifaddrs *ifi) +++{ +++ mDNSBool match = mDNSfalse; +++ mDNSAddr ip, mask; +++ int if_index; +++ +++ if_index = if_nametoindex(ifi->ifa_name); +++ if (if_index == 0) +++ return mDNSfalse; +++ +++ if((intf->index == if_index) && +++ (intf->sa_family == ifi->ifa_addr->sa_family) && +++ (strcmp(intf->coreIntf.ifname, ifi->ifa_name) == 0)) +++ { +++ SockAddrTomDNSAddr(ifi->ifa_addr, &ip, NULL); +++ SockAddrTomDNSAddr(ifi->ifa_netmask, &mask, NULL); +++ +++ match = mDNSSameAddress(&intf->coreIntf.ip, &ip) && +++ mDNSSameAddress(&intf->coreIntf.mask, &mask); +++ } +++ +++ return match; +++} +++ ++ // Called when data appears on interface change notification socket ++ mDNSlocal void InterfaceChangeCallback(int fd, void *context) ++ { ++ IfChangeRec *pChgRec = (IfChangeRec*) context; +++ mDNS *m = pChgRec->mDNS; ++ fd_set readFDs; ++ GenLinkedList changedInterfaces; ++ NetworkInterfaceIndex *changedInterface; ++ struct timeval zeroTimeout = { 0, 0 }; +++ struct ifaddrs *ifa_list, **ifi, *ifa_loop4 = NULL; +++ PosixNetworkInterface *intf, *intfNext; +++ mDNSBool found, foundav4; ++ ++ (void)fd; // Unused ++ ++@@ -1810,12 +1839,149 @@ mDNSlocal void InterfaceChangeCallback(int fd, void *context) ++ } ++ while (0 < select(pChgRec->NotifySD + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout)); ++ ++- // Currently we rebuild the entire interface list whenever any interface change is ++- // detected. If this ever proves to be a performance issue in a multi-homed ++- // configuration, more care should be paid to changedInterfaces. ++- if (changedInterfaces.Head != NULL) ++- mDNSPlatformPosixRefreshInterfaceList(pChgRec->mDNS); +++ CleanRecentInterfaces(); +++ +++ if (changedInterfaces.Head == NULL) goto cleanup; +++ +++ if (getifaddrs(&ifa_list) < 0) goto cleanup; +++ +++ for (intf = (PosixNetworkInterface*)(m->HostInterfaces); intf != NULL; intf = intfNext) +++ { +++ intfNext = (PosixNetworkInterface*)(intf->coreIntf.next); +++ +++ // Loopback interface(s) are handled later +++ if (intf->coreIntf.Loopback) continue; +++ +++ found = mDNSfalse; +++ for (ifi = &ifa_list; *ifi != NULL; ifi = &(*ifi)->ifa_next) +++ { +++ if (InterfacesMatch(intf, *ifi)) +++ { +++ found = mDNStrue; +++ break; +++ } +++ } +++ +++ // Removes changed and old interfaces from m->HostInterfaces +++ if (!found) TearDownInterface(m, intf); +++ } +++ +++ // Add new and changed interfaces in ifa_list +++ // Save off loopback interface in case it is needed later +++ for (ifi = &ifa_list; *ifi != NULL; ifi = &(*ifi)->ifa_next) +++ { +++ found = mDNSfalse; +++ for (intf = (PosixNetworkInterface*)(m->HostInterfaces); intf != NULL; intf = intfNext) +++ { +++ intfNext = (PosixNetworkInterface*)(intf->coreIntf.next); +++ +++ // Loopback interface(s) are handled later +++ if (intf->coreIntf.Loopback) continue; +++ +++ if (InterfacesMatch(intf, *ifi)) +++ { +++ found = mDNStrue; +++ break; +++ } +++ +++ // Removes changed and old interfaces from m->HostInterfaces +++ } +++ if (found) +++ continue; +++ +++ if ((ifa_loop4 == NULL) && +++ ((*ifi)->ifa_addr->sa_family == AF_INET) && +++ ((*ifi)->ifa_flags & IFF_UP) && +++ ((*ifi)->ifa_flags & IFF_LOOPBACK)) +++ { +++ ifa_loop4 = *ifi; +++ continue; +++ } +++ +++ if ( (((*ifi)->ifa_addr->sa_family == AF_INET) +++#if HAVE_IPV6 +++ || ((*ifi)->ifa_addr->sa_family == AF_INET6) +++#endif +++ ) && ((*ifi)->ifa_flags & IFF_UP) +++ && !((*ifi)->ifa_flags & IFF_POINTOPOINT) +++ && !((*ifi)->ifa_flags & IFF_LOOPBACK)) +++ { +++ struct ifaddrs *i = *ifi; +++ +++#define ethernet_addr_len 6 +++ uint8_t hwaddr[ethernet_addr_len]; +++ int hwaddr_len = 0; +++ +++#if defined(TARGET_OS_LINUX) && TARGET_OS_LINUX +++ struct ifreq ifr; +++ int sockfd = socket(AF_INET6, SOCK_DGRAM, 0); +++ if (sockfd >= 0) +++ { +++ /* Add hardware address */ +++ memcpy(ifr.ifr_name, i->ifa_name, IFNAMSIZ); +++ if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) != -1) +++ { +++ if (ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER) +++ { +++ memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ethernet_addr_len); +++ hwaddr_len = ethernet_addr_len; +++ } +++ } +++ close(sockfd); +++ } +++ else +++ { +++ memset(hwaddr, 0, sizeof(hwaddr)); +++ } +++#endif // TARGET_OS_LINUX +++ SetupOneInterface(m, i->ifa_addr, i->ifa_netmask, +++ hwaddr, hwaddr_len, i->ifa_name, if_nametoindex(i->ifa_name), i->ifa_flags); +++ } +++ } +++ +++ // Determine if there is at least one non-loopback IPv4 interface. This is to work around issues +++ // with multicast loopback on IPv6 interfaces -- see corresponding logic in SetupInterfaceList(). +++ foundav4 = mDNSfalse; +++ for (intf = (PosixNetworkInterface*)(m->HostInterfaces); intf != NULL; intf = (PosixNetworkInterface*)(intf->coreIntf.next)) +++ { +++ if (intf->sa_family == AF_INET && !intf->coreIntf.Loopback) +++ { +++ foundav4 = mDNStrue; +++ break; +++ } +++ } +++ +++ if (foundav4) +++ { +++ for (intf = (PosixNetworkInterface*)(m->HostInterfaces); intf != NULL; intf = intfNext) +++ { +++ intfNext = (PosixNetworkInterface*)(intf->coreIntf.next); +++ if (intf->coreIntf.Loopback) TearDownInterface(m, intf); +++ } +++ } +++ else +++ { +++ found = mDNSfalse; +++ +++ for (intf = (PosixNetworkInterface*)(m->HostInterfaces); intf != NULL; intf = (PosixNetworkInterface*)(intf->coreIntf.next)) +++ { +++ if (intf->coreIntf.Loopback) +++ { +++ found = mDNStrue; +++ break; +++ } +++ } +++ +++ if (!found && (ifa_loop4 != NULL)) +++ { +++ SetupOneInterface(m, ifa_loop4->ifa_addr, ifa_loop4->ifa_netmask, +++ NULL, 0, ifa_loop4->ifa_name, if_nametoindex(ifa_loop4->ifa_name), ifa_loop4->ifa_flags); +++ } +++ } +++ +++ if (ifa_list != NULL) freeifaddrs(ifa_list); ++ +++cleanup: ++ while ((changedInterface = (NetworkInterfaceIndex*)changedInterfaces.Head) != NULL) ++ { ++ RemoveFromList(&changedInterfaces, changedInterface); ++@@ -1947,15 +2113,11 @@ mDNSexport void mDNSPlatformClose(mDNS *const m) ++ #endif ++ } ++ ++-// This is used internally by InterfaceChangeCallback. ++-// It's also exported so that the Standalone Responder (mDNSResponderPosix) +++// This is exported so that the Standalone Responder (mDNSResponderPosix) ++ // can call it in response to a SIGHUP (mainly for debugging purposes). ++ mDNSexport mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m) ++ { ++ int err; ++- // This is a pretty heavyweight way to process interface changes -- ++- // destroying the entire interface list and then making fresh one from scratch. ++- // We should make it like the OS X version, which leaves unchanged interfaces alone. ++ ClearInterfaceList(m); ++ err = SetupInterfaceList(m); ++ return PosixErrorToStatus(err); ++-- ++2.41.0 ++ +diff --git a/third_party/mDNSResponder/0008-Mark-deleted-interfaces-as-being-changed.patch b/third_party/mDNSResponder/0008-Mark-deleted-interfaces-as-being-changed.patch +new file mode 100644 +index 0000000000..216fde7f03 +--- /dev/null ++++ b/third_party/mDNSResponder/0008-Mark-deleted-interfaces-as-being-changed.patch +@@ -0,0 +1,43 @@ ++From 8ebfeaf55ab364a1e51a3438dfa9a742a01b8d36 Mon Sep 17 00:00:00 2001 ++Message-ID: <8ebfeaf55ab364a1e51a3438dfa9a742a01b8d36.1687508149.git.stefan@agner.ch> ++In-Reply-To: ++References: ++From: Nate Karstens ++Date: Wed, 9 Aug 2017 09:16:58 -0500 ++Subject: [PATCH] Mark deleted interfaces as being changed ++ ++Netlink notification handling ignores messages for deleted links, ++RTM_DELLINK. It does handle RTM_GETLINK. According to libnl docu- ++mentation (http://www.infradead.org/~tgr/libnl/doc/route.html) ++RTM_DELLINK can be sent by the kernel, but RTM_GETLINK cannot. ++There was likely a mixup in the original implementation, so this ++change replaces handling for RTM_GETLINK with RTM_DELLINK. ++ ++Testing and Verification Instructions: ++ 1. Use ip-link to add and remove a VLAN interface and verify ++ that mDNSResponder handles the deleted link. ++ ++Upstream-Status: Submitted [dts@apple.com] ++ ++Signed-off-by: Nate Karstens ++Signed-off-by: Alex Kiernan ++--- ++ mDNSPosix/mDNSPosix.c | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c ++index ad7000d..010f266 100644 ++--- a/mDNSPosix/mDNSPosix.c +++++ b/mDNSPosix/mDNSPosix.c ++@@ -1714,7 +1714,7 @@ mDNSlocal void ProcessRoutingNotification(int sd, GenLinkedList *change ++ #endif ++ ++ // Process the NetLink message ++- if (pNLMsg->nlmsg_type == RTM_GETLINK || pNLMsg->nlmsg_type == RTM_NEWLINK) +++ if (pNLMsg->nlmsg_type == RTM_DELLINK || pNLMsg->nlmsg_type == RTM_NEWLINK) ++ AddInterfaceIndexToList(changedInterfaces, ((struct ifinfomsg*) NLMSG_DATA(pNLMsg))->ifi_index); ++ else if (pNLMsg->nlmsg_type == RTM_DELADDR || pNLMsg->nlmsg_type == RTM_NEWADDR) ++ AddInterfaceIndexToList(changedInterfaces, ((struct ifaddrmsg*) NLMSG_DATA(pNLMsg))->ifa_index); ++-- ++2.41.0 ++ +diff --git a/third_party/mDNSResponder/0009-Handle-errors-from-socket-calls.patch b/third_party/mDNSResponder/0009-Handle-errors-from-socket-calls.patch +new file mode 100644 +index 0000000000..2057e2cb3e +--- /dev/null ++++ b/third_party/mDNSResponder/0009-Handle-errors-from-socket-calls.patch +@@ -0,0 +1,66 @@ ++From dae89c4e97faf408394961c0f4b1577a7d5976cc Mon Sep 17 00:00:00 2001 ++Message-ID: ++In-Reply-To: ++References: ++From: Nate Karstens ++Date: Thu, 10 Aug 2017 08:27:32 -0500 ++Subject: [PATCH] Handle errors from socket calls ++ ++Adds handling for socket() or read() returning a ++negative value (indicating an error has occurred). ++ ++Upstream-Status: Submitted [dts@apple.com] ++ ++Signed-off-by: Nate Karstens ++Signed-off-by: Alex Kiernan ++--- ++ mDNSPosix/mDNSPosix.c | 12 +++++++++--- ++ 1 file changed, 9 insertions(+), 3 deletions(-) ++ ++diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c ++index 010f266..89e108f 100644 ++--- a/mDNSPosix/mDNSPosix.c +++++ b/mDNSPosix/mDNSPosix.c ++@@ -1677,7 +1677,7 @@ mDNSlocal void ProcessRoutingNotification(int sd, GenLinkedList *change ++ // Read through the messages on sd and if any indicate that any interface records should ++ // be torn down and rebuilt, return affected indices as a bitmask. Otherwise return 0. ++ { ++- ssize_t readCount; +++ ssize_t readVal, readCount; ++ char buff[4096]; ++ struct nlmsghdr *pNLMsg = (struct nlmsghdr*) buff; ++ ++@@ -1686,7 +1686,10 @@ mDNSlocal void ProcessRoutingNotification(int sd, GenLinkedList *change ++ // enough to hold all pending data and so avoid message fragmentation. ++ // (Note that FIONREAD is not supported on AF_NETLINK.) ++ ++- readCount = read(sd, buff, sizeof buff); +++ readVal = read(sd, buff, sizeof buff); +++ if (readVal < 0) return; +++ readCount = readVal; +++ ++ while (1) ++ { ++ // Make sure we've got an entire nlmsghdr in the buffer, and payload, too. ++@@ -1702,7 +1705,9 @@ mDNSlocal void ProcessRoutingNotification(int sd, GenLinkedList *change ++ pNLMsg = (struct nlmsghdr*) buff; ++ ++ // read more data ++- readCount += read(sd, buff + readCount, sizeof buff - readCount); +++ readVal = read(sd, buff + readCount, sizeof buff - readCount); +++ if (readVal < 0) return; +++ readCount += readVal; ++ continue; // spin around and revalidate with new readCount ++ } ++ else ++@@ -2017,6 +2022,7 @@ mDNSlocal mDNSBool mDNSPlatformInit_CanReceiveUnicast(void) ++ int err; ++ int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); ++ struct sockaddr_in s5353; +++ if (s < 0) return mDNSfalse; ++ s5353.sin_family = AF_INET; ++ s5353.sin_port = MulticastDNSPort.NotAnInteger; ++ s5353.sin_addr.s_addr = 0; ++-- ++2.41.0 ++ +diff --git a/third_party/mDNSResponder/0010-Handle-interface-without-ifa_addr.patch b/third_party/mDNSResponder/0010-Handle-interface-without-ifa_addr.patch +new file mode 100644 +index 0000000000..602b205e3f +--- /dev/null ++++ b/third_party/mDNSResponder/0010-Handle-interface-without-ifa_addr.patch +@@ -0,0 +1,41 @@ ++From e501d58e9ec6cb6e19a682d425fa638069585fbc Mon Sep 17 00:00:00 2001 ++Message-ID: ++In-Reply-To: ++References: ++From: Stefan Agner ++Date: Fri, 23 Jun 2023 10:10:00 +0200 ++Subject: [PATCH] Handle interface without `ifa_addr` ++ ++It seems that certain interface types may have `ifa_addr` set to null. ++Handle this case gracefully. ++ ++Signed-off-by: Stefan Agner ++--- ++ mDNSPosix/mDNSPosix.c | 4 +++- ++ 1 file changed, 3 insertions(+), 1 deletion(-) ++ ++diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c ++index 89e108f..2056871 100644 ++--- a/mDNSPosix/mDNSPosix.c +++++ b/mDNSPosix/mDNSPosix.c ++@@ -1895,6 +1895,7 @@ mDNSlocal void InterfaceChangeCallback(int fd, void *context) ++ continue; ++ ++ if ((ifa_loop4 == NULL) && +++ ((*ifi)->ifa_addr != NULL) && ++ ((*ifi)->ifa_addr->sa_family == AF_INET) && ++ ((*ifi)->ifa_flags & IFF_UP) && ++ ((*ifi)->ifa_flags & IFF_LOOPBACK)) ++@@ -1903,7 +1904,8 @@ mDNSlocal void InterfaceChangeCallback(int fd, void *context) ++ continue; ++ } ++ ++- if ( (((*ifi)->ifa_addr->sa_family == AF_INET) +++ if ( ((*ifi)->ifa_addr != NULL) && +++ (((*ifi)->ifa_addr->sa_family == AF_INET) ++ #if HAVE_IPV6 ++ || ((*ifi)->ifa_addr->sa_family == AF_INET6) ++ #endif ++-- ++2.41.0 ++ +-- +2.41.0 + diff --git a/deconz/rootfs/etc/services.d/otau-deconz/run b/silabs-multiprotocol/rootfs/etc/cont-init.d/check-cpcd-shm.sh old mode 100644 new mode 100755 similarity index 51% rename from deconz/rootfs/etc/services.d/otau-deconz/run rename to silabs-multiprotocol/rootfs/etc/cont-init.d/check-cpcd-shm.sh index 109535eb7bd..318970c6764 --- a/deconz/rootfs/etc/services.d/otau-deconz/run +++ b/silabs-multiprotocol/rootfs/etc/cont-init.d/check-cpcd-shm.sh @@ -1,10 +1,9 @@ #!/usr/bin/with-contenv bashio +# shellcheck shell=bash # ============================================================================== -# Download available firmware update for IKEA +# Check that no other CPC instance is running on this system # ============================================================================== - -# Start OTA updates for deCONZ -bashio::log.info "Running the deCONZ OTA updater..." -deCONZ-otau-dl.sh &> /dev/null - -exec sleep 259200 +if test -d /dev/shm/cpcd; then + bashio::log.error "Another CPC daemon running!" + exit 1 +fi diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/banner/dependencies.d/legacy-cont-init b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/banner/dependencies.d/legacy-cont-init new file mode 100644 index 00000000000..e69de29bb2d diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/banner/type b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/banner/type new file mode 100644 index 00000000000..bdd22a1850a --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/banner/type @@ -0,0 +1 @@ +oneshot diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/banner/up b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/banner/up new file mode 100644 index 00000000000..dc292313ac5 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/banner/up @@ -0,0 +1 @@ +/etc/s6-overlay/scripts/banner.sh diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd-config/dependencies.d/banner b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd-config/dependencies.d/banner new file mode 100644 index 00000000000..e69de29bb2d diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd-config/dependencies.d/universal-silabs-flasher b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd-config/dependencies.d/universal-silabs-flasher new file mode 100644 index 00000000000..e69de29bb2d diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd-config/type b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd-config/type new file mode 100644 index 00000000000..bdd22a1850a --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd-config/type @@ -0,0 +1 @@ +oneshot diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd-config/up b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd-config/up new file mode 100644 index 00000000000..0f8b09d75ff --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd-config/up @@ -0,0 +1 @@ +/etc/s6-overlay/scripts/cpcd-config-up diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/data/check b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/data/check new file mode 100755 index 00000000000..fba3172698d --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/data/check @@ -0,0 +1,5 @@ +#!/bin/bash + +# Check if CPC daemon socket exists +test -S /dev/shm/cpcd/cpcd_0/ctrl.cpcd.sock +exit diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/dependencies.d/cpcd-config b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/dependencies.d/cpcd-config new file mode 100644 index 00000000000..e69de29bb2d diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/finish b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/finish new file mode 100755 index 00000000000..89abb4b2c6b --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/finish @@ -0,0 +1,14 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Take down the container if cpcd exits +# ============================================================================== +bashio::log.info "CPC ended with exit code ${1} (signal ${2})..." +rm -r /dev/shm/cpcd + + +# shellcheck disable=SC2086 +if [ ${1} -ne 0 ] && [ ${1} -ne 256 ]; then + /run/s6/basedir/bin/halt +fi diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/notification-fd b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/notification-fd new file mode 100644 index 00000000000..00750edc07d --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/notification-fd @@ -0,0 +1 @@ +3 diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/run b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/run new file mode 100755 index 00000000000..97f737aee39 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/run @@ -0,0 +1,10 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start Co-Processor Communication Daemon (CPCd) +# ============================================================================== + +bashio::log.info "Starting cpcd..." +exec s6-notifyoncheck -d -s 300 -w 300 -n 0 \ + "/usr/bin/stdbuf" -o0 /usr/local/bin/cpcd diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/type b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/cpcd/type @@ -0,0 +1 @@ +longrun diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/mdns/finish b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/mdns/finish new file mode 100755 index 00000000000..92b89c6b491 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/mdns/finish @@ -0,0 +1,7 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +#============================================================================== +# mDNSResponder finish script +#============================================================================== +bashio::log.info "mDNS ended with exit code ${1} (signal ${2})..." diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/mdns/run b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/mdns/run new file mode 100755 index 00000000000..6affe2c5577 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/mdns/run @@ -0,0 +1,12 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start mDNSResponder daemon +# ============================================================================== +bashio::log.info "Starting mDNS Responder..." + +# mdnsd runs as daemon except when using debug mode. We prefer non-daemon, so +# start in debug by default. It seems nto to generate a vast amount of +# messages. +exec /usr/sbin/mdnsd -debug diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/mdns/type b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/mdns/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/mdns/type @@ -0,0 +1 @@ +longrun diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/dependencies.d/otbr-agent b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/dependencies.d/otbr-agent new file mode 100644 index 00000000000..e69de29bb2d diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/type b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/type new file mode 100644 index 00000000000..bdd22a1850a --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/type @@ -0,0 +1 @@ +oneshot diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/up b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/up new file mode 100755 index 00000000000..75f80eec7d5 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent-rest-discovery/up @@ -0,0 +1 @@ +/etc/s6-overlay/scripts/otbr-agent-rest-discovery.sh diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/data/check b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/data/check new file mode 100755 index 00000000000..662155dbcd4 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/data/check @@ -0,0 +1,6 @@ +#!/bin/bash + +# Check if openthread socket exists +mapfile -t < /tmp/otbr-agent-rest-api +test -S /run/openthread-wpan0.sock && nc -z "${MAPFILE[@]}" +exit diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/dependencies.d/cpcd b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/dependencies.d/cpcd new file mode 100644 index 00000000000..e69de29bb2d diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/finish b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/finish new file mode 100755 index 00000000000..78a78bf56f8 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/finish @@ -0,0 +1,68 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +#============================================================================== +# OpenThread BorderRouter Daemon finish script +#============================================================================== +bashio::log.info "otbr-agent ended with exit code ${1} (signal ${2})..." + + +# shellcheck disable=SC1091 +. /etc/s6-overlay/scripts/otbr-agent-common + +ipset_destroy_if_exist() +{ + # The ipset seems to be in use by the kernel for a brief period, + # retry destroying it + while ipset list -n "$1" 2> /dev/null; do + ipset destroy "$1" || true + done +} + +# shellcheck disable=SC2086,SC2154 +while ip6tables -C FORWARD -o $thread_if -j $otbr_forward_ingress_chain 2> /dev/null; do + # shellcheck disable=SC2086 + ip6tables -D FORWARD -o $thread_if -j $otbr_forward_ingress_chain +done + +# shellcheck disable=SC2086 +if ip6tables -L $otbr_forward_ingress_chain 2> /dev/null; then + # shellcheck disable=SC2086 + ip6tables -w -F $otbr_forward_ingress_chain + # shellcheck disable=SC2086 + ip6tables -w -X $otbr_forward_ingress_chain +fi + +ipset_destroy_if_exist otbr-ingress-deny-src +ipset_destroy_if_exist otbr-ingress-deny-src-swap +ipset_destroy_if_exist otbr-ingress-allow-dst +ipset_destroy_if_exist otbr-ingress-allow-dst-swap + +# shellcheck disable=SC2086,SC2154 +while ip6tables -C FORWARD -i $thread_if -j $otbr_forward_egress_chain 2> /dev/null; do + # shellcheck disable=SC2086 + ip6tables -D FORWARD -i $thread_if -j $otbr_forward_egress_chain +done + +# shellcheck disable=SC2086 +if ip6tables -L $otbr_forward_egress_chain 2> /dev/null; then + # shellcheck disable=SC2086 + ip6tables -w -F $otbr_forward_egress_chain + # shellcheck disable=SC2086 + ip6tables -w -X $otbr_forward_egress_chain +fi +bashio::log.info "OTBR firewall teardown completed." + +if test "$1" -eq 256 ; then + e=$((128 + $2)) +else + e="$1" +fi + +if test "$e" -ne 0; then + bashio::log.warning "otbr-agent exited with code $e (by signal $2)." + echo "$e" > /run/s6-linux-init-container-results/exitcode + exec /run/s6/basedir/bin/halt +else + bashio::log.info "otbr-agent exited with code $e (by signal $2)." +fi diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/notification-fd b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/notification-fd new file mode 100644 index 00000000000..00750edc07d --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/notification-fd @@ -0,0 +1 @@ +3 diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/run b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/run new file mode 100755 index 00000000000..b3bb2f7067c --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/run @@ -0,0 +1,123 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# OpenThread BorderRouter start script +# ============================================================================== + +# shellcheck disable=SC1091 +. /etc/s6-overlay/scripts/otbr-agent-common + +declare backbone_if +# shellcheck disable=SC2034 +declare device +# shellcheck disable=SC2034 +declare baudrate +# shellcheck disable=SC2034 +declare flow_control +declare otbr_log_level +declare otbr_log_level_int +declare otbr_rest_listen +declare otbr_rest_listen_port + +backbone_if="$(bashio::api.supervisor 'GET' '/network/info' '' 'first(.interfaces[] | select (.primary == true)) .interface')" + +otbr_log_level=$(bashio::string.lower "$(bashio::config otbr_log_level)") +case "${otbr_log_level}" in + debug) + otbr_log_level_int="7" + ;; + info) + otbr_log_level_int="6" + ;; + notice) + otbr_log_level_int="5" + ;; + warning) + otbr_log_level_int="4" + ;; + error) + otbr_log_level_int="3" + ;; + critical) + otbr_log_level_int="2" + ;; + alert) + otbr_log_level_int="1" + ;; + emergency) + otbr_log_level_int="0" + ;; + *) + bashio::exit.nok "Unknown otbr_log_level: ${otbr_log_level}" + ;; +esac + +# shellcheck disable=SC2086 +if [ -z ${backbone_if} ]; then + bashio::log.warning "No primary network interface found! Using static eth0." + backbone_if="eth0" +fi + +# shellcheck disable=SC2015 +mkdir -p /data/thread && ln -sft /var/lib /data/thread || bashio::exit.nok "Could not create directory /var/lib/thread to store Thread data." + +if bashio::config.true 'otbr_firewall'; then + bashio::log.info "Setup OTBR firewall..." + ipset create -exist otbr-ingress-deny-src hash:net family inet6 + ipset create -exist otbr-ingress-deny-src-swap hash:net family inet6 + ipset create -exist otbr-ingress-allow-dst hash:net family inet6 + ipset create -exist otbr-ingress-allow-dst-swap hash:net family inet6 + + # shellcheck disable=SC2086,SC2154 + ip6tables -N $otbr_forward_ingress_chain + # shellcheck disable=SC2086,SC2154 + ip6tables -I FORWARD 1 -o $thread_if -j $otbr_forward_ingress_chain + + # shellcheck disable=SC2086 + ip6tables -A $otbr_forward_ingress_chain -m pkttype --pkt-type unicast -i ${thread_if} -j DROP + # shellcheck disable=SC2086 + ip6tables -A $otbr_forward_ingress_chain -m set --match-set otbr-ingress-deny-src src -j DROP + # shellcheck disable=SC2086 + ip6tables -A $otbr_forward_ingress_chain -m set --match-set otbr-ingress-allow-dst dst -j ACCEPT + # shellcheck disable=SC2086 + ip6tables -A $otbr_forward_ingress_chain -m pkttype --pkt-type unicast -j DROP + # shellcheck disable=SC2086 + ip6tables -A $otbr_forward_ingress_chain -j ACCEPT + + # shellcheck disable=SC2086,SC2154 + ip6tables -N $otbr_forward_egress_chain + # shellcheck disable=SC2086 + ip6tables -I FORWARD 2 -i $thread_if -j $otbr_forward_egress_chain + # shellcheck disable=SC2086 + ip6tables -A $otbr_forward_egress_chain -j ACCEPT +else + # Make sure ip6tables (as used by Docker) allow IP forwarding + ip6tables -P FORWARD ACCEPT + # HAOS 9.3 and earlier (for 9.4 accept is the default so this won't do anything) + ip6tables-legacy -P FORWARD ACCEPT +fi + +otbr_rest_listen="::" +otbr_rest_listen_port="$(bashio::addon.port 8081)" + +# If user port is not set, listen on local interface only +if ! bashio::var.has_value "${otbr_rest_listen_port}"; then + otbr_rest_listen="$(bashio::addon.ip_address)" + otbr_rest_listen_port="8081" +elif [ "${otbr_rest_listen_port}" != "8081" ]; then + bashio::log.warning "Custom OpenThread REST API port is not supported. Using 8081." + otbr_rest_listen_port="8081" +fi + +# Store REST API listen information for check script +echo "${otbr_rest_listen}" > /tmp/otbr-agent-rest-api +echo "${otbr_rest_listen_port}" >> /tmp/otbr-agent-rest-api + +bashio::log.info "Starting otbr-agent..." +# shellcheck disable=SC2086 +exec s6-notifyoncheck -d -s 300 -w 300 -n 0 \ + "/usr/sbin/otbr-agent" -I ${thread_if} -B "${backbone_if}" \ + --rest-listen-address "${otbr_rest_listen}" \ + -d${otbr_log_level_int} -v \ + "spinel+cpc://cpcd_0?iid=2&iid-list=0" diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/type b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-agent/type @@ -0,0 +1 @@ +longrun diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/dependencies.d/otbr-agent b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/dependencies.d/otbr-agent new file mode 100644 index 00000000000..e69de29bb2d diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/finish b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/finish new file mode 100755 index 00000000000..2035d588936 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/finish @@ -0,0 +1,7 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +#============================================================================== +# OpenThread BorderRouter web interface finish script +#============================================================================== +bashio::log.info "otbr-web ended with exit code ${1} (signal ${2})..." diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/run b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/run new file mode 100755 index 00000000000..8d82419865d --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/run @@ -0,0 +1,12 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start OpenThread BorderRouter web interface +# ============================================================================== +bashio::log.info "Starting otbr-web..." +declare otbr_web_port + +otbr_web_port="$(bashio::addon.port 8080)" + +exec /usr/sbin/otbr-web -I wpan0 -d6 -p "${otbr_web_port}" diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/type b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/otbr-web/type @@ -0,0 +1 @@ +longrun diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/socat-cpcd-tcp/data/check b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/socat-cpcd-tcp/data/check new file mode 100755 index 00000000000..ee0a22bebcd --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/socat-cpcd-tcp/data/check @@ -0,0 +1,4 @@ +#!/bin/sh + +test -c /tmp/ttyCPC +exit diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/socat-cpcd-tcp/notification-fd b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/socat-cpcd-tcp/notification-fd new file mode 100644 index 00000000000..00750edc07d --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/socat-cpcd-tcp/notification-fd @@ -0,0 +1 @@ +3 diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/socat-cpcd-tcp/run b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/socat-cpcd-tcp/run new file mode 100755 index 00000000000..5d3127a066f --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/socat-cpcd-tcp/run @@ -0,0 +1,15 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start socat TCP client for CPC daemon +# ============================================================================== + +declare network_device + +network_device=$(bashio::config 'network_device') + +bashio::log.info "Starting socat TCP client for CPC daemon..." +exec s6-notifyoncheck -d -s 300 -w 300 \ + "/usr/bin/socat" -d pty,raw,echo=0,link=/tmp/ttyCPC,ignoreeof \ + "tcp:${network_device}" diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/socat-cpcd-tcp/type b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/socat-cpcd-tcp/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/socat-cpcd-tcp/type @@ -0,0 +1 @@ +longrun diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/dependencies.d/banner b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/dependencies.d/banner new file mode 100644 index 00000000000..e69de29bb2d diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/type b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/type new file mode 100644 index 00000000000..bdd22a1850a --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/type @@ -0,0 +1 @@ +oneshot diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/up b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/up new file mode 100644 index 00000000000..56e09fe7678 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/up @@ -0,0 +1 @@ +/etc/s6-overlay/scripts/universal-silabs-flasher-up diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/cpcd b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/cpcd new file mode 100644 index 00000000000..e69de29bb2d diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/mdns b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/mdns new file mode 100644 index 00000000000..e69de29bb2d diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/otbr-agent b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/otbr-agent new file mode 100644 index 00000000000..e69de29bb2d diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/otbr-agent-rest-discovery b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/otbr-agent-rest-discovery new file mode 100644 index 00000000000..e69de29bb2d diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/otbr-web b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/otbr-web new file mode 100644 index 00000000000..e69de29bb2d diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/zigbeed b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/zigbeed new file mode 100644 index 00000000000..e69de29bb2d diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/dependencies.d/cpcd b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/dependencies.d/cpcd new file mode 100644 index 00000000000..e69de29bb2d diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/finish b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/finish new file mode 100755 index 00000000000..4dbf2fbea29 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/finish @@ -0,0 +1,7 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +#============================================================================== +# EmberZNet Zigbee Daemon finish script +#============================================================================== +bashio::log.info "zigbeed ended with exit code ${1} (signal ${2})..." diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/run b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/run new file mode 100755 index 00000000000..56683e5f0f8 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/run @@ -0,0 +1,23 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start EmberZNet Zigbee Daemon +# ============================================================================== +# shellcheck disable=SC2015 +mkdir -p /data/zigbeed && cd /data/zigbeed || bashio::exit.nok "Could not change to zigbeed working directory" + +ezsp_listen="::" +ezsp_listen_port="$(bashio::addon.port 9999)" + +# If user port is not set, listen on local interface only +if ! bashio::var.has_value "${ezsp_listen_port}"; then + ezsp_listen="$(bashio::addon.ip_address)" + ezsp_listen_port="9999" +fi + +bashio::log.info "Starting zigbeed..." +# shellcheck disable=SC2086 +exec /usr/local/bin/zigbeed --radio-url "spinel+cpc://cpcd_0?iid=1&iid-list=0" \ + --ezsp-listen ${ezsp_listen} \ + --ezsp-listen-port ${ezsp_listen_port} diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/type b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/s6-rc.d/zigbeed/type @@ -0,0 +1 @@ +longrun diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/banner.sh b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/banner.sh new file mode 100755 index 00000000000..074dc4179e5 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/banner.sh @@ -0,0 +1,38 @@ +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash +# ============================================================================== +# Home Assistant Community Add-on: Base Images +# Displays a simple add-on banner on startup +# ============================================================================== +if bashio::supervisor.ping; then + bashio::log.blue \ + '-----------------------------------------------------------' + bashio::log.blue " Add-on: $(bashio::addon.name)" + bashio::log.blue " $(bashio::addon.description)" + bashio::log.blue \ + '-----------------------------------------------------------' + + bashio::log.blue " Add-on version: $(bashio::addon.version)" + if bashio::var.true "$(bashio::addon.update_available)"; then + bashio::log.magenta ' There is an update available for this add-on!' + bashio::log.magenta \ + " Latest add-on version: $(bashio::addon.version_latest)" + bashio::log.magenta ' Please consider upgrading as soon as possible.' + else + bashio::log.green ' You are running the latest version of this add-on.' + fi + + bashio::log.blue " System: $(bashio::info.operating_system)" \ + " ($(bashio::info.arch) / $(bashio::info.machine))" + bashio::log.blue " Home Assistant Core: $(bashio::info.homeassistant)" + bashio::log.blue " Home Assistant Supervisor: $(bashio::info.supervisor)" + + bashio::log.blue \ + '-----------------------------------------------------------' + bashio::log.blue \ + ' Please, share the above information when looking for help' + bashio::log.blue \ + ' or support in, e.g., GitHub, forums or the Discord chat.' + bashio::log.blue \ + '-----------------------------------------------------------' +fi diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/cpcd-config-up b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/cpcd-config-up new file mode 100755 index 00000000000..48793059b20 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/cpcd-config-up @@ -0,0 +1,54 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Generate Silicon Labs Multiprotocol configurations +# ============================================================================== + +declare device +declare baudrate +declare flow_control +declare cpcd_trace + +if ! bashio::config.has_value 'device'; then + bashio::log.fatal "No serial port device set!" + bashio::exit.nok +fi +device=$(bashio::config 'device') + +if bashio::config.has_value 'network_device'; then + device="/tmp/ttyCPC" +fi + +baudrate=$(bashio::config 'baudrate') +if [ -f /tmp/known-baudrate ]; then + baudrate=$(cat /tmp/known-baudrate) + bashio::log.info "Using known baudrate of ${baudrate} for cpcd!" +elif bashio::config.has_value 'baudrate'; then + baudrate=$(bashio::config 'baudrate') +else + bashio::log.fatal "No serial port baudrate set!" + bashio::exit.nok +fi + +if ! bashio::config.has_value 'flow_control'; then + flow_control="false" +else + flow_control=$(bashio::config 'flow_control') +fi + +if ! bashio::config.has_value 'cpcd_trace'; then + cpcd_trace="false" +else + cpcd_trace=$(bashio::config 'cpcd_trace') +fi + +bashio::log.info "Generating cpcd configuration." +bashio::var.json \ + device "${device}" \ + baudrate "${baudrate}" \ + flow_control "${flow_control}" \ + cpcd_trace "${cpcd_trace}" \ + | tempio \ + -template /usr/local/share/cpcd.conf \ + -out /usr/local/etc/cpcd.conf diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/enable-check.sh b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/enable-check.sh new file mode 100755 index 00000000000..7810d3bd034 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/enable-check.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +/etc/s6-overlay/scripts/otbr-enable-check.sh +/etc/s6-overlay/scripts/socat-cpcd-tcp-enable-check.sh diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/otbr-agent-common b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/otbr-agent-common new file mode 100644 index 00000000000..e4d4669a9e4 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/otbr-agent-common @@ -0,0 +1,9 @@ +#!/bin/sh + +declare thread_if +declare otbr_forward_ingress_chain +declare otbr_forward_egress_chain +thread_if="wpan0" +otbr_forward_ingress_chain="OTBR_FORWARD_INGRESS" +otbr_forward_egress_chain="OTBR_FORWARD_EGRESS" + diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/otbr-agent-rest-discovery.sh b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/otbr-agent-rest-discovery.sh new file mode 100755 index 00000000000..bc3ef5d28fa --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/otbr-agent-rest-discovery.sh @@ -0,0 +1,18 @@ +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash +# ============================================================================== +# Send OTBR discovery information to Home Assistant +# ============================================================================== +declare config + +config=$(bashio::var.json \ + host "$(bashio::addon.hostname)" \ + port "^8081" \ +) + +# Send discovery info +if bashio::discovery "otbr" "${config}" > /dev/null; then + bashio::log.info "Successfully sent discovery information to Home Assistant." +else + bashio::log.error "Discovery message to Home Assistant failed!" +fi diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/otbr-enable-check.sh b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/otbr-enable-check.sh new file mode 100755 index 00000000000..8cd2c2d30dc --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/otbr-enable-check.sh @@ -0,0 +1,22 @@ +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash +# ============================================================================== +# Disable OTBR if not enabled +# ============================================================================== + +if bashio::config.false 'otbr_enable'; then + rm /etc/s6-overlay/s6-rc.d/user/contents.d/otbr-agent + rm /etc/s6-overlay/s6-rc.d/user/contents.d/otbr-web + rm /etc/s6-overlay/s6-rc.d/user/contents.d/otbr-agent-rest-discovery + rm /etc/s6-overlay/s6-rc.d/user/contents.d/mdns + bashio::log.info "The otbr-agent is disabled." + bashio::exit.ok +fi + +if bashio::var.has_value "$(bashio::addon.port 8080)" \ + && bashio::var.has_value "$(bashio::addon.port 8081)"; then + bashio::log.info "Web UI and REST API port are exposed, starting otbr-web." +else + rm /etc/s6-overlay/s6-rc.d/user/contents.d/otbr-web + bashio::log.info "The otbr-web is disabled." +fi diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/socat-cpcd-tcp-enable-check.sh b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/socat-cpcd-tcp-enable-check.sh new file mode 100755 index 00000000000..6166b077da2 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/socat-cpcd-tcp-enable-check.sh @@ -0,0 +1,11 @@ +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash +# ============================================================================== +# Enable socat-cpcd-tcp service if needed +# ============================================================================== + +if bashio::config.has_value 'network_device'; then + touch /etc/s6-overlay/s6-rc.d/user/contents.d/socat-cpcd-tcp + touch /etc/s6-overlay/s6-rc.d/cpcd/dependencies.d/socat-cpcd-tcp + bashio::log.info "Enabled socat-cpcd-tcp." +fi diff --git a/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up new file mode 100755 index 00000000000..a8410b36f18 --- /dev/null +++ b/silabs-multiprotocol/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up @@ -0,0 +1,68 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start universal-silabs-flasher if requested +# ============================================================================== + +# shellcheck disable=SC2034 +declare autoflash_firmware +declare device +declare firmware +declare usb_device_path +declare usb_manufacturer +declare usb_product +declare gpio_reset_flag + +function exit_no_firmware { + bashio::log.warning "No firmware found for the selected device, assuming firmware is installed." + exit 0 +} + +device=$(bashio::config 'device') + +if bashio::config.false 'autoflash_firmware'; then + bashio::log.info "Flashing firmware is disabled" + exit 0 +fi + +# Assume to run on Yellow if UART4 is mapped to ttyAMA1 +if [ -d /sys/devices/platform/soc/fe201800.serial/tty/ttyAMA1 ] && [ "${device}" == "/dev/ttyAMA1" ]; then + bashio::log.info "Detected Home Assistant Yellow" + firmware="NabuCasa_Yellow_RCP_v4.3.1_rcp-uart-hw-802154_460800.gbl" + gpio_reset_flag="--yellow-gpio-reset" +else + # Check device manufacturer/product information + # shellcheck disable=SC2046,SC2086 + usb_device_path=$(realpath /sys/class/tty/$(readlink /sys/class/tty/$(basename ${device}))/../../../../) + if [ ! -f "${usb_device_path}/idProduct" ]; then + bashio::log.info "The selected serial port is not a USB device." + exit_no_firmware + fi + + if [ ! -f "${usb_device_path}/manufacturer" ] || [ ! -f "${usb_device_path}/product" ]; then + bashio::log.info "USB device is missing manufacturer or product name." + exit_no_firmware + fi + + usb_manufacturer=$(cat "${usb_device_path}/manufacturer") + usb_product=$(cat "${usb_device_path}/product") + + bashio::log.info "Checking ${device} identifying ${usb_product} from ${usb_manufacturer}." + if [[ "${usb_manufacturer}" == "Nabu Casa" && "${usb_product}" == "SkyConnect"* ]]; then + firmware="NabuCasa_SkyConnect_RCP_v4.3.1_rcp-uart-hw-802154_460800.gbl" + elif [[ "${usb_manufacturer}" == "Nabu Casa" && "${usb_product}" == "Home Assistant Connect ZBT-1"* ]]; then + firmware="NabuCasa_SkyConnect_RCP_v4.3.1_rcp-uart-hw-802154_460800.gbl" + else + exit_no_firmware + fi + gpio_reset_flag="" +fi + +# All firmware we flash have a known baudrate of 460800, let cpcd know. +echo 460800 > /tmp/known-baudrate + +bashio::log.info "Starting universal-silabs-flasher with ${device}" +# shellcheck disable=SC2086 +exec universal-silabs-flasher --device ${device} \ + flash ${gpio_reset_flag} --ensure-exact-version --allow-cross-flashing --firmware "/root/${firmware}" diff --git a/silabs-multiprotocol/rootfs/root/NabuCasa_SkyConnect_RCP_v4.3.1_rcp-uart-hw-802154_460800.gbl b/silabs-multiprotocol/rootfs/root/NabuCasa_SkyConnect_RCP_v4.3.1_rcp-uart-hw-802154_460800.gbl new file mode 100644 index 00000000000..382b594fdc9 Binary files /dev/null and b/silabs-multiprotocol/rootfs/root/NabuCasa_SkyConnect_RCP_v4.3.1_rcp-uart-hw-802154_460800.gbl differ diff --git a/silabs-multiprotocol/rootfs/root/NabuCasa_Yellow_RCP_v4.3.1_rcp-uart-hw-802154_460800.gbl b/silabs-multiprotocol/rootfs/root/NabuCasa_Yellow_RCP_v4.3.1_rcp-uart-hw-802154_460800.gbl new file mode 100644 index 00000000000..1ebc94e72d1 Binary files /dev/null and b/silabs-multiprotocol/rootfs/root/NabuCasa_Yellow_RCP_v4.3.1_rcp-uart-hw-802154_460800.gbl differ diff --git a/silabs-multiprotocol/rootfs/usr/local/share/cpcd.conf b/silabs-multiprotocol/rootfs/usr/local/share/cpcd.conf new file mode 100644 index 00000000000..a8a882579ef --- /dev/null +++ b/silabs-multiprotocol/rootfs/usr/local/share/cpcd.conf @@ -0,0 +1,100 @@ +# Instance Name +# Optional, defaults to "cpcd_0" +# This string uniquely identifies the running cpcd instance. +# An application must pass this value to cpc_init() to connect +# to this particular instance. +instance_name: cpcd_0 + +# Bus type selection +# Mandatory +# Allowed values : UART or SPI +bus_type: UART + +# SPI device file +# Mandatory if spi chosen, ignored if uart chosen +spi_device_file: /dev/spidev0.0 + +# SPI RX IRQ gpio chip +# Ignored when using the gpio sysfs interface +spi_rx_irq_gpio_chip: gpiochip0 + +# SPI RX IRQ gpio +# RX interrupt gpio selection +spi_rx_irq_gpio: 22 + +# SPI bitrate. +# Ignored if uart chosen. +# See doc/spi_bitrate.md for a complete explanation +spi_device_bitrate: 1000000 + +# UART device file +# Mandatory if uart chosen, ignored if spi chosen +uart_device_file: {{ .device }} + +# UART baud rate. +# Optional if uart chosen, ignored if spi chosen. Defaults to 115200 +# Allowed values : standard UART baud rates listed in 'termios.h' +uart_device_baud: {{ .baudrate }} + +# UART flow control. +# Optional if uart chosen, ignored if spi chosen. Defaults to 'true' +# Allowed values are 'true' or 'false' +uart_hardflow: {{ .flow_control }} + +# BOOTLOADER Recovery Pins Enabled +# Set to true to enter bootloader via wake and reset pins +# If true, bootloader_wake_gpio and bootloader_reset_gpio must be configured +bootloader_recovery_pins_enabled: false + +# BOOTLOADER WAKE gpio chip +# Ignored when using the gpio sysfs interface +bootloader_wake_gpio_chip: gpiochip0 + +# BOOTLOADER WAKE gpio +# Wakeup gpio used by the bootloader +# Ensure bootloader_recovery_pins_enabled=true to use this pin +bootloader_wake_gpio: 24 + +# BOOTLOADER RESET gpio chip +# Ignored when using the gpio sysfs interface +bootloader_reset_gpio_chip: gpiochip0 + +# BOOTLOADER RESET gpio +# Reset pin +# Ensure bootloader_recovery_pins_enabled=true to use this pin +bootloader_reset_gpio: 23 + +# Prints tracing information to stdout +# Optional, defaults to 'false' +# Allowed values are 'true' or 'false' +stdout_trace: {{ .cpcd_trace }} + +# Prints tracing information to a file located under traces_folder +# Optional, defaults to 'false' +# Allowed values are 'true' or 'false' +trace_to_file: false + +# Traces folder +# Optional, defaults to '/dev/shm/cpcd-traces' +# Folder mounted on a tmpfs is preferred +traces_folder: /dev/shm/cpcd-traces + +# Enable frame trace +# Optional, defaults to 'false' +# Allowed values are 'true' or 'false' +enable_frame_trace: false + +# Number of open file descriptors. +# Optional, defaults to 2000 +# If the error 'Too many open files' occurs, this is the value to increase. +rlimit_nofile: 2000 + +# Disable the encryption over CPC endpoints +# Optional, defaults false +disable_encryption: true + +# Binding key file +# Mandatory when security is used +# Must have 32 alphanumeric characters as the first line, representing a 128 bit binding key +# If ECDH encryption is used, this file will be created during the binding process +binding_key_file: /etc/binding-key.key diff --git a/silabs-multiprotocol/translations/en.yaml b/silabs-multiprotocol/translations/en.yaml new file mode 100644 index 00000000000..97c2fbc8266 --- /dev/null +++ b/silabs-multiprotocol/translations/en.yaml @@ -0,0 +1,40 @@ +--- +configuration: + device: + name: Device + description: The serial port where the Silicon Labs radio is connected to. + baudrate: + name: Baudrate + description: >- + The serial port baudrate used to communicate with the Silicon Labs radio. + flow_control: + name: Hardware flow control + description: Enable hardware flow control for serial port. + network_device: + name: Network Device + description: >- + Host and Port when connecting to a device via sockets (takes precedence + over above configuration). + autoflash_firmware: + name: Automatically flash firmware + description: >- + Automatically flash Multi-PAN firmware on Home Assistant SkyConnect + (WARNING: flashing the original EmberZNet is a manual process currently) + cpcd_trace: + name: Co-Processor Communication tracing + description: Enable tracing for the Co-Processor Communication daemon. + otbr_enable: + name: Enable OpenThread Border Router + description: Enable OpenThread Border Router agent. + otbr_log_level: + name: OpenThread Border Router agent log level + description: >- + Set logging level of the OpenThread Border Router agent (otbr-agent). + otbr_firewall: + name: OTBR firewall + description: >- + Use OpenThread Border Router firewall to block unnecessary traffic. +network: + 9999/tcp: EmberZNet EZSP/ASH port + 8080/tcp: OpenThread Web port + 8081/tcp: OpenThread REST API port diff --git a/silabs-multiprotocol/zigbeed-app-patches/0001-Use-TCP-socket-instead-of-serial-port-main-app.patch b/silabs-multiprotocol/zigbeed-app-patches/0001-Use-TCP-socket-instead-of-serial-port-main-app.patch new file mode 100644 index 00000000000..2e4895e35ef --- /dev/null +++ b/silabs-multiprotocol/zigbeed-app-patches/0001-Use-TCP-socket-instead-of-serial-port-main-app.patch @@ -0,0 +1,164 @@ +From 2a6cc51eb53fcc7d3b6525cb8190d212c430263f Mon Sep 17 00:00:00 2001 +Message-ID: <2a6cc51eb53fcc7d3b6525cb8190d212c430263f.1686315449.git.stefan@agner.ch> +From: Stefan Agner +Date: Thu, 15 Dec 2022 16:37:02 +0100 +Subject: [PATCH] Use TCP socket instead of serial port (main/app) + +Instead of opening a serial port, open a TCP socket on port 9999. Pass +the listening socket to the new instance in case a controller reset is +being requested. This makes sure the TCP connection stays up even when +zigbeed restarts. +--- + app.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++--------- + main.c | 3 +++ + 2 files changed, 56 insertions(+), 9 deletions(-) + +diff --git a/app.c b/app.c +index 2b74eab..e7286dd 100644 +--- a/app.c ++++ b/app.c +@@ -27,6 +27,7 @@ + */ + + #define _GNU_SOURCE ++#include + #include + #include + +@@ -83,6 +84,9 @@ extern jmp_buf gResetJump; + #define RADIO_URL_MAX_LEN 150 + char radioUrl[RADIO_URL_MAX_LEN]; + ++extern struct in6_addr ezspListenAddress; ++extern uint16_t ezspPort; ++ + /** + * This enumeration defines the argument return values. + * +@@ -90,16 +94,18 @@ char radioUrl[RADIO_URL_MAX_LEN]; + enum { + OT_POSIX_OPT_RADIO_URL = 'r', + OT_POSIX_OPT_DEBUG_LEVEL = 'd', +- OT_POSIX_OPT_EZSP_INTERFACE = 'p', ++ OT_POSIX_OPT_EZSP_LISTEN = 'l', ++ OT_POSIX_OPT_EZSP_LISTEN_PORT = 'p', + OT_POSIX_OPT_HELP = 'h', + OT_POSIX_OPT_VERBOSE = 'v', + }; + +-#define GETOPT_OPTION_STRING "r:d:p:hv" ++#define GETOPT_OPTION_STRING "r:d:l:p:hv" + static const struct option kOptions[] = { + { "radio-url", required_argument, NULL, OT_POSIX_OPT_RADIO_URL }, + { "debug-level", required_argument, NULL, OT_POSIX_OPT_DEBUG_LEVEL }, +- { "ezsp-interface", required_argument, NULL, OT_POSIX_OPT_EZSP_INTERFACE }, ++ { "ezsp-listen", required_argument, NULL, OT_POSIX_OPT_EZSP_LISTEN }, ++ { "ezsp-listen-port", required_argument, NULL, OT_POSIX_OPT_EZSP_LISTEN_PORT }, + { "help", no_argument, NULL, OT_POSIX_OPT_HELP }, + { "verbose", no_argument, NULL, OT_POSIX_OPT_VERBOSE }, + { 0, 0, 0, 0 } +@@ -113,7 +119,8 @@ static void PrintUsage(const char *aProgramName, FILE *aStream, int aExitCode) + "Options:\n" + " -r --radio-url URL to the radio device. Must include iid=n with n=1,2, or 3.\n" + " -d --debug-level Debug level for Spinel syslog logging.\n" +- " -p --ezsp-interface EZSP interface name.\n" ++ " -l --ezsp-listen
Address to listen on (EZSP protocol).\n" ++ " -p --ezsp-listen-port Port to listen on (EZSP protocol).\n" + " -h --help Display this usage information.\n" + " -v --verbose Also log Spinel to stderr.\n", + aProgramName); +@@ -126,7 +133,6 @@ static ssize_t ParseEtcConf(char *confFilePath, int aArgVectorSize, char *aArgVe + ssize_t argCount = 0; + FILE *fp = fopen(confFilePath, "r"); + if (fp == NULL) { +- fprintf(stderr, "Cannot open file %s\n", confFilePath); + return 0; // no config file + } + +@@ -203,6 +209,39 @@ static ssize_t ParseEtcConf(char *confFilePath, int aArgVectorSize, char *aArgVe + return argCount; + } + ++static bool parseListenPort(const char *arg) ++{ ++ unsigned long port = strtoul(optarg, NULL, 10); ++ if (!port || port > UINT16_MAX) { ++ return false; ++ } ++ ezspPort = (uint16_t)port; ++ return true; ++} ++ ++static bool parseListenAddress(const char *arg) ++{ ++ char *tmp; ++ const char ipv4_prefix[] = "::FFFF:"; ++ const int ipv4_prefix_len = sizeof(ipv4_prefix) - 1; ++ const int arg_len = strlen(arg); ++ ++ if (inet_pton(AF_INET6, arg, &ezspListenAddress) == 1) { ++ return true; ++ } ++ ++ tmp = malloc(arg_len + ipv4_prefix_len + 1); ++ strcpy(tmp, ipv4_prefix); ++ strncpy(tmp + ipv4_prefix_len, arg, arg_len + 1); ++ if (inet_pton(AF_INET6, tmp, &ezspListenAddress) == 1) { ++ free(tmp); ++ return true; ++ } ++ free(tmp); ++ ++ return false; ++} ++ + static void ParseArg(int aArgCount, char *aArgVector[], PosixConfig *aConfig) + { + optind = 1; +@@ -224,13 +263,18 @@ static void ParseArg(int aArgCount, char *aArgVector[], PosixConfig *aConfig) + case OT_POSIX_OPT_HELP: + PrintUsage(aArgVector[0], stdout, OT_EXIT_SUCCESS); + break; +- case OT_POSIX_OPT_EZSP_INTERFACE: +- if (strlen(optarg) > SERIAL_PORT_NAME_MAX_LEN) { +- fprintf(stderr, "Error: ezsp-interface name too long\n"); ++ case OT_POSIX_OPT_EZSP_LISTEN: ++ if (!parseListenAddress(optarg)) { ++ fprintf(stderr, "Error: could not parse ezsp-listen address\n"); + exit(OT_EXIT_INVALID_ARGUMENTS); + } +- strcpy(serialPort, optarg); + break; ++ case OT_POSIX_OPT_EZSP_LISTEN_PORT: ++ if (!parseListenPort(optarg)) { ++ fprintf(stderr, "Error: could not parse ezsp-listen port\n"); ++ exit(OT_EXIT_INVALID_ARGUMENTS); ++ } ++ break; + case OT_POSIX_OPT_RADIO_URL: + if (strlen(optarg) > RADIO_URL_MAX_LEN) { + fprintf(stderr, "Error: Radio URL too long\n"); +diff --git a/main.c b/main.c +index 0091acf..c26a90d 100644 +--- a/main.c ++++ b/main.c +@@ -51,6 +51,8 @@ void __gcov_flush(); + // From platform/base/phy/simulation/security.h: + extern uint8_t simulatorEncryptionType; + ++extern void serialShutdown(void); ++ + void app_init(void) + { + #if defined(EMBER_TEST) +@@ -94,6 +96,7 @@ int main(void) + app_process_args(argc, argv); + + if (setjmp(gResetJump)) { ++ serialShutdown(); + fprintf(stderr, "Restarting\n"); + execvp(argv[0], argv); + } +-- +2.41.0 + diff --git a/silabs_flasher/CHANGELOG.md b/silabs_flasher/CHANGELOG.md new file mode 100644 index 00000000000..22b7b305c04 --- /dev/null +++ b/silabs_flasher/CHANGELOG.md @@ -0,0 +1,41 @@ +# Changelog + +## 0.3.2 + +- Update flasher script to work with Home Assistant Yellow with CM5 + +## 0.3.1 +- Update firmwares to EmberZNet 7.4.4 +- Update universal-silabs-flasher to v0.0.25 + +## 0.3.0 +- Update firmwares to EmberZNet 7.4.3 +- Update universal-silabs-flasher to v0.0.22 + +## 0.2.3 + +- Upgrade to Alpine 3.19 + +## 0.2.2 + +- Update universal-silabs-flasher to v0.0.19 + +## 0.2.1 + +- Support flashing the Connect ZBT-1. + +## 0.2.0 + +- Update universal-silabs-flasher to v0.0.13 +- Update firmware for Home Assistant Yellow and SkyConnect to v7.3.1.0 +- Use Alpine 3.17/Python 3.11 base image + +## 0.1.1 + +- Fix firmware installation from URL +- Exit add-on after flashing completed +- Allow to start universal-silabs-flasher in verbose mode + +## 0.1.0 + +- initial version diff --git a/silabs_flasher/DOCS.md b/silabs_flasher/DOCS.md new file mode 100644 index 00000000000..714467c013a --- /dev/null +++ b/silabs_flasher/DOCS.md @@ -0,0 +1,46 @@ +# Home Assistant Add-on: Silicon Labs Flasher Add-on + +## Installation + +Follow these steps to get the add-on installed on your system: + +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons, Backup & Supervisor** -> **Add-on Store**. +2. Find the "Silicon Labs Flasher" add-on and click it. +3. Click on the "INSTALL" button. + +## How to use + +The add-on needs a Silicon Labs based wireless module accessible through a +serial port (like the module on Home Assistant Yellow, Home Assistant +SkyConnect/ZBT-1 or other USB based wireless adapters). + +1. Select the correct `device` in the add-on configuration tab and press `Save`. +2. Start the add-on. + +## Configuration + +Add-on configuration: + +| Configuration | Description | +|--------------------|--------------------------------------------------------| +| device (mandatory) | Serial service where the Silicon Labs radio is attached | +| baudrate | Serial port baudrate (depends on firmware) | +| flow_control | If hardware flow control should be enabled (depends on firmware) | +| firmware_url | Custom URL to flash firmware from | + +## Support + +Got questions? + +You have several options to get them answered: + +- The [Home Assistant Discord Chat Server][discord]. +- The Home Assistant [Community Forum][forum]. +- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit] + +In case you've found a bug, please [open an issue on our GitHub][issue]. + +[discord]: https://discord.gg/c5DvZ4e +[forum]: https://community.home-assistant.io +[reddit]: https://reddit.com/r/homeassistant +[issue]: https://github.com/home-assistant/addons/issues diff --git a/silabs_flasher/Dockerfile b/silabs_flasher/Dockerfile new file mode 100644 index 00000000000..e5c8a033563 --- /dev/null +++ b/silabs_flasher/Dockerfile @@ -0,0 +1,23 @@ +ARG BUILD_FROM +ARG BUILD_ARCH + +FROM $BUILD_FROM + +ARG UNIVERSAL_SILABS_FLASHER + +RUN \ + set -x \ + && apk add --no-cache \ + py3-pip \ + python3 \ + && pip3 install \ + --no-cache-dir \ + --prefer-binary \ + --find-links "https://wheels.home-assistant.io/musllinux/${BUILD_ARCH}/" \ + universal-silabs-flasher=="${UNIVERSAL_SILABS_FLASHER}" + +COPY rootfs / + +# use s6-overlay as init system +WORKDIR / +ENTRYPOINT ["/init"] diff --git a/silabs_flasher/README.md b/silabs_flasher/README.md new file mode 100644 index 00000000000..a805b190fe7 --- /dev/null +++ b/silabs_flasher/README.md @@ -0,0 +1,28 @@ +# Home Assistant Add-on: Silicon Labs Flasher Add-on + +Silicon Labs Flasher add-on to flash Silicon Labs based radios. + +By default this add-on flashes the firmware to use Zigbee (Silicon +Labs EmberZNet Zigbee stack). + +**NOTE:** Make sure no other add-on or integration is using the radio. In +particular disable the Zigbee Home Automation integration and the Silicon Labs +Multiprotocol add-on. + +![Supports aarch64 Architecture][aarch64-shield] +![Supports amd64 Architecture][amd64-shield] +![Supports armhf Architecture][armhf-shield] +![Supports armv7 Architecture][armv7-shield] +![Supports i386 Architecture][i386-shield] + +## About + +This add-on allows you to flash firmwares using the Gecko Bootloader file format +(gbl). By default it comes with firmware for Home Assistant SkyConnect/ZBT-1 and +Home Assistant Yellow to flash Zigbee. + +[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg +[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg +[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg +[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg +[i386-shield]: https://img.shields.io/badge/i386-yes-green.svg \ No newline at end of file diff --git a/silabs_flasher/build.yaml b/silabs_flasher/build.yaml new file mode 100644 index 00000000000..0ac17423164 --- /dev/null +++ b/silabs_flasher/build.yaml @@ -0,0 +1,9 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base-python:3.11-alpine3.19 + amd64: ghcr.io/home-assistant/amd64-base-python:3.11-alpine3.19 + armhf: ghcr.io/home-assistant/armhf-base-python:3.11-alpine3.19 + armv7: ghcr.io/home-assistant/armv7-base-python:3.11-alpine3.19 + i386: ghcr.io/home-assistant/i386-base-python:3.11-alpine3.19 +args: + UNIVERSAL_SILABS_FLASHER: 0.0.25 diff --git a/silabs_flasher/config.yaml b/silabs_flasher/config.yaml new file mode 100644 index 00000000000..a9f33694b5d --- /dev/null +++ b/silabs_flasher/config.yaml @@ -0,0 +1,31 @@ +--- +version: 0.3.2 +slug: silabs_flasher +name: Silicon Labs Flasher +description: Silicon Labs firmware flasher add-on +url: > + https://github.com/home-assistant/addons/tree/master/silabs_flasher +arch: + - aarch64 + - amd64 + - armhf + - armv7 + - i386 +gpio: true +hassio_api: true +image: homeassistant/{arch}-addon-silabs-flasher +init: false +options: + device: null + bootloader_baudrate: "115200" + flow_control: true + verbose: false +schema: + device: device(subsystem=tty)? + bootloader_baudrate: list(57600|115200|230400|460800|921600) + flow_control: bool? + firmware_url: str? + verbose: bool? +stage: experimental +startup: once +boot: manual diff --git a/silabs_flasher/icon.png b/silabs_flasher/icon.png new file mode 100644 index 00000000000..aebde6cef00 Binary files /dev/null and b/silabs_flasher/icon.png differ diff --git a/silabs_flasher/logo.png b/silabs_flasher/logo.png new file mode 100644 index 00000000000..b0013c9cb3a Binary files /dev/null and b/silabs_flasher/logo.png differ diff --git a/silabs_flasher/rootfs/etc/s6-overlay/s6-rc.d/banner/dependencies.d/legacy-cont-init b/silabs_flasher/rootfs/etc/s6-overlay/s6-rc.d/banner/dependencies.d/legacy-cont-init new file mode 100644 index 00000000000..e69de29bb2d diff --git a/silabs_flasher/rootfs/etc/s6-overlay/s6-rc.d/banner/type b/silabs_flasher/rootfs/etc/s6-overlay/s6-rc.d/banner/type new file mode 100644 index 00000000000..bdd22a1850a --- /dev/null +++ b/silabs_flasher/rootfs/etc/s6-overlay/s6-rc.d/banner/type @@ -0,0 +1 @@ +oneshot diff --git a/silabs_flasher/rootfs/etc/s6-overlay/s6-rc.d/banner/up b/silabs_flasher/rootfs/etc/s6-overlay/s6-rc.d/banner/up new file mode 100644 index 00000000000..dc292313ac5 --- /dev/null +++ b/silabs_flasher/rootfs/etc/s6-overlay/s6-rc.d/banner/up @@ -0,0 +1 @@ +/etc/s6-overlay/scripts/banner.sh diff --git a/silabs_flasher/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/dependencies.d/banner b/silabs_flasher/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/dependencies.d/banner new file mode 100644 index 00000000000..e69de29bb2d diff --git a/silabs_flasher/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/type b/silabs_flasher/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/type new file mode 100644 index 00000000000..bdd22a1850a --- /dev/null +++ b/silabs_flasher/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/type @@ -0,0 +1 @@ +oneshot diff --git a/silabs_flasher/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/up b/silabs_flasher/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/up new file mode 100644 index 00000000000..56e09fe7678 --- /dev/null +++ b/silabs_flasher/rootfs/etc/s6-overlay/s6-rc.d/universal-silabs-flasher/up @@ -0,0 +1 @@ +/etc/s6-overlay/scripts/universal-silabs-flasher-up diff --git a/silabs_flasher/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/universal-silabs-flasher b/silabs_flasher/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/universal-silabs-flasher new file mode 100644 index 00000000000..e69de29bb2d diff --git a/silabs_flasher/rootfs/etc/s6-overlay/scripts/banner.sh b/silabs_flasher/rootfs/etc/s6-overlay/scripts/banner.sh new file mode 100755 index 00000000000..074dc4179e5 --- /dev/null +++ b/silabs_flasher/rootfs/etc/s6-overlay/scripts/banner.sh @@ -0,0 +1,38 @@ +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash +# ============================================================================== +# Home Assistant Community Add-on: Base Images +# Displays a simple add-on banner on startup +# ============================================================================== +if bashio::supervisor.ping; then + bashio::log.blue \ + '-----------------------------------------------------------' + bashio::log.blue " Add-on: $(bashio::addon.name)" + bashio::log.blue " $(bashio::addon.description)" + bashio::log.blue \ + '-----------------------------------------------------------' + + bashio::log.blue " Add-on version: $(bashio::addon.version)" + if bashio::var.true "$(bashio::addon.update_available)"; then + bashio::log.magenta ' There is an update available for this add-on!' + bashio::log.magenta \ + " Latest add-on version: $(bashio::addon.version_latest)" + bashio::log.magenta ' Please consider upgrading as soon as possible.' + else + bashio::log.green ' You are running the latest version of this add-on.' + fi + + bashio::log.blue " System: $(bashio::info.operating_system)" \ + " ($(bashio::info.arch) / $(bashio::info.machine))" + bashio::log.blue " Home Assistant Core: $(bashio::info.homeassistant)" + bashio::log.blue " Home Assistant Supervisor: $(bashio::info.supervisor)" + + bashio::log.blue \ + '-----------------------------------------------------------' + bashio::log.blue \ + ' Please, share the above information when looking for help' + bashio::log.blue \ + ' or support in, e.g., GitHub, forums or the Discord chat.' + bashio::log.blue \ + '-----------------------------------------------------------' +fi diff --git a/silabs_flasher/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up b/silabs_flasher/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up new file mode 100755 index 00000000000..5437841279e --- /dev/null +++ b/silabs_flasher/rootfs/etc/s6-overlay/scripts/universal-silabs-flasher-up @@ -0,0 +1,121 @@ +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start universal-silabs-flasher +# ============================================================================== + +set -e + +# shellcheck disable=SC2034 +declare autoflash_firmware +declare device +declare bootloader_baudrate +declare firmware +declare verbose +declare usb_device_path +declare usb_manufacturer +declare usb_product +declare gpio_reset_flag +declare exit_status + +function cleanup() { + exit_status=$? + bashio::log.info "universal-silabs-flasher-up script exited with code ${exit_status}" + echo "${exit_status}" > /run/s6-linux-init-container-results/exitcode + + /run/s6/basedir/bin/halt +} +trap cleanup EXIT + +function exit_no_firmware { + bashio::log.warning "No firmware found for the selected device, assuming firmware is installed." + exit 0 +} + +# Function to check if the device is Home Assistant Yellow +function is_home_assistant_yellow { + # First, ensure the device is /dev/ttyAMA1 + if [ "${device}" != "/dev/ttyAMA1" ]; then + return 1 + fi + + # Check the known paths for Home Assistant Yellow + local paths=( + "/sys/devices/platform/soc/fe201800.serial/tty/ttyAMA1" + "/sys/devices/platform/axi/1000120000.pcie/1f0003c000.serial/tty/ttyAMA1" + ) + for path in "${paths[@]}"; do + if [ -d "${path}" ]; then + return 0 + fi + done + return 1 +} + +device=$(bashio::config 'device') +bootloader_baudrate=$(bashio::config 'bootloader_baudrate') + +if is_home_assistant_yellow; then + bashio::log.info "Detected Home Assistant Yellow" + gpio_reset_flag="--bootloader-reset yellow" +else + gpio_reset_flag="" +fi + +if bashio::config.has_value 'firmware_url'; then + curl --silent -L -o "/root/firmware.gbl" "$(bashio::config 'firmware_url')" + if [ ! -f "/root/firmware.gbl" ]; then + bashio::log.warning "Downloading firmware failed" + exit 0 + fi + + firmware="firmware.gbl" +else + # Assume to run on Yellow if UART4 is mapped to ttyAMA1 + if is_home_assistant_yellow; then + firmware="yellow_zigbee_ncp_7.4.4.0.gbl" + else + # Check device manufacturer/product information + # shellcheck disable=SC2046,SC2086 + usb_device_path=$(realpath /sys/class/tty/$(readlink /sys/class/tty/$(basename ${device}) | sed 's:/[^/]*tty[^/]*::g' )/../) + if [ ! -f "${usb_device_path}/idProduct" ]; then + bashio::log.info "The selected serial port is not a USB device." + exit_no_firmware + fi + + if [ ! -f "${usb_device_path}/manufacturer" ] || [ ! -f "${usb_device_path}/product" ]; then + bashio::log.info "USB device is missing manufacturer or product name." + exit_no_firmware + fi + + usb_manufacturer=$(cat "${usb_device_path}/manufacturer") + usb_product=$(cat "${usb_device_path}/product") + + bashio::log.info "Checking ${device} identifying ${usb_product} from ${usb_manufacturer}." + if [[ "${usb_manufacturer}" == "Nabu Casa" && "${usb_product}" == "SkyConnect"* ]]; then + firmware="skyconnect_zigbee_ncp_7.4.4.0.gbl" + elif [[ "${usb_manufacturer}" == "Nabu Casa" && "${usb_product}" == "Home Assistant Connect ZBT-1"* ]]; then + firmware="skyconnect_zigbee_ncp_7.4.4.0.gbl" + else + exit_no_firmware + fi + gpio_reset_flag="" + fi +fi + +verbose="" +if bashio::config.true 'verbose'; then + verbose="-v" +fi + +bashio::log.info "Starting universal-silabs-flasher with ${device} (bootloader baudrate ${bootloader_baudrate})" +# shellcheck disable=SC2086 +universal-silabs-flasher \ + ${verbose} \ + --device ${device} \ + --bootloader-baudrate "${bootloader_baudrate}" \ + ${gpio_reset_flag} \ + flash --force --firmware "/root/${firmware}" + + diff --git a/silabs_flasher/rootfs/root/skyconnect_zigbee_ncp_7.4.4.0.gbl b/silabs_flasher/rootfs/root/skyconnect_zigbee_ncp_7.4.4.0.gbl new file mode 100644 index 00000000000..bce7aec4eae Binary files /dev/null and b/silabs_flasher/rootfs/root/skyconnect_zigbee_ncp_7.4.4.0.gbl differ diff --git a/silabs_flasher/rootfs/root/yellow_zigbee_ncp_7.4.4.0.gbl b/silabs_flasher/rootfs/root/yellow_zigbee_ncp_7.4.4.0.gbl new file mode 100644 index 00000000000..14a8f5e9490 Binary files /dev/null and b/silabs_flasher/rootfs/root/yellow_zigbee_ncp_7.4.4.0.gbl differ diff --git a/silabs_flasher/translations/en.yaml b/silabs_flasher/translations/en.yaml new file mode 100644 index 00000000000..3a8065549fd --- /dev/null +++ b/silabs_flasher/translations/en.yaml @@ -0,0 +1,21 @@ +--- +configuration: + device: + name: Device + description: The serial port where the Silicon Labs radio is connected to. + bootloader_baudrate: + name: Bootloader Baudrate + description: >- + The serial port baudrate used to communicate with the Silicon Labs radio + in bootloader mode. + flow_control: + name: Hardware flow control + description: Enable hardware flow control for serial port. + firmware_url: + name: Firmware URL + description: >- + Flash Custom firmware downloaded from URL. + verbose: + name: Verbose mode + description: >- + Start universal-silabs-flasher in verbose mode. diff --git a/speech_to_phrase/CHANGELOG.md b/speech_to_phrase/CHANGELOG.md new file mode 100644 index 00000000000..315a67cbfce --- /dev/null +++ b/speech_to_phrase/CHANGELOG.md @@ -0,0 +1,22 @@ +# Changelog + +## 1.3.0 + +- Add Coqui STT +- Support range fractions in custom sentences (https://github.com/OHF-Voice/speech-to-phrase/issues/5) +- Do full re-train at startup (https://github.com/OHF-Voice/speech-to-phrase/issues/11) +- Remove websocket command message limit (https://github.com/OHF-Voice/speech-to-phrase/issues/6) +- Bump `unicode-rbnf` to 2.3.0 (https://github.com/OHF-Voice/speech-to-phrase/issues/15) + +## 1.2.0 + +- Split words on dashes `-` and underscores `_` +- Remove template syntax from names (`[]<>{}()`) + +## 1.1.0 + +- Add custom sentences + +## 1.0.0 + +- Initial release diff --git a/speech_to_phrase/DOCS.md b/speech_to_phrase/DOCS.md new file mode 100644 index 00000000000..252af1dabf9 --- /dev/null +++ b/speech_to_phrase/DOCS.md @@ -0,0 +1,64 @@ +# Home Assistant Add-on: Speech to phrase + +## Installation + +Follow these steps to get the add-on installed on your system: + +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. +2. Find the "Speech to phrase" add-on and click it. +3. Click on the "INSTALL" button. + +## How to use + +After this add-on is installed and running, it should automatically train itself based on your [exposed][] entities, areas, floors, and [sentence triggers][sentence trigger]. +The add-on will automatically re-train if necessary. + +The add-on will be automatically discovered by the Wyoming integration in Home Assistant. To finish the setup, click the following my button: + +[![Open your Home Assistant instance and start setting up a new integration.](https://my.home-assistant.io/badges/config_flow_start.svg)](https://my.home-assistant.io/redirect/config_flow_start/?domain=wyoming) + +Alternatively, you can install the Wyoming integration manually, see the +[Wyoming integration documentation](https://www.home-assistant.io/integrations/wyoming/) +for more information. + +### Voice commands + +- [English](https://github.com/OHF-Voice/speech-to-phrase/blob/main/docs/english.md) +- [Français (French)](https://github.com/OHF-Voice/speech-to-phrase/blob/main/docs/french.md) +- [Deutsch (German)](https://github.com/OHF-Voice/speech-to-phrase/blob/main/docs/german.md) +- [Nederlands (Dutch)](https://github.com/OHF-Voice/speech-to-phrase/blob/main/docs/dutch.md) +- [Spanish (Español)](https://github.com/OHF-Voice/speech-to-phrase/blob/main/docs/spanish.md) +- [Italian (Italiano)](https://github.com/OHF-Voice/speech-to-phrase/blob/main/docs/italian.md) + +### Custom sentences + +You can add [custom sentences][] to `/share/speech-to-phrase/custom_sentences//sentences.yaml` where `` is: + +* `en` - English +* `fr` - French +* `de` - German +* `nl` - Dutch +* `es` - Spanish +* `it` - Italian + +## Support + +Got questions? + +You have several options to get them answered: + +- The [Home Assistant Discord Chat Server][discord]. +- The Home Assistant [Community Forum][forum]. +- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit] + +In case you've found an bug, please [open an issue on our GitHub][issue]. + +[discord]: https://discord.gg/c5DvZ4e +[forum]: https://community.home-assistant.io +[issue]: https://github.com/home-assistant/addons/issues +[reddit]: https://reddit.com/r/homeassistant +[repository]: https://github.com/hassio-addons/repository + +[sentence trigger]: https://www.home-assistant.io/docs/automation/trigger/#sentence-trigger +[exposed]: https://www.home-assistant.io/voice_control/voice_remote_expose_devices/ +[custom sentences]: https://github.com/OHF-voice/speech-to-phrase?tab=readme-ov-file#custom-sentences diff --git a/speech_to_phrase/Dockerfile b/speech_to_phrase/Dockerfile new file mode 100644 index 00000000000..7e7d7db3433 --- /dev/null +++ b/speech_to_phrase/Dockerfile @@ -0,0 +1,46 @@ +ARG BUILD_FROM +FROM ${BUILD_FROM} +ARG BUILD_ARCH + +# Set shell +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +# Install speech-to-phrase +ARG SPEECH_TO_PHRASE_VERSION +WORKDIR /usr/src + +RUN mkdir -p ./tools + +RUN \ + apt-get update \ + && apt-get install -y --no-install-recommends \ + netcat-traditional \ + python3 \ + python3-pip \ + python3-dev \ + python3-venv \ + build-essential \ + curl \ + libopenblas0 \ + libencode-perl \ + && ARCH="${BUILD_ARCH}" \ + && if [[ "${BUILD_ARCH}" = "aarch64" ]]; then ARCH="arm64"; fi \ + && curl --location --output - \ + "https://huggingface.co/datasets/rhasspy/rhasspy-speech/resolve/main/tools/rhasspy-speech_${ARCH}.tar.gz?download=true" | \ + tar -C ./tools -xzf - \ + && python3 -m venv .venv \ + && .venv/bin/pip3 install --no-cache-dir \ + "speech-to-phrase @ https://github.com/OHF-Voice/speech-to-phrase/archive/refs/tags/v${SPEECH_TO_PHRASE_VERSION}.tar.gz" \ + && apt-get remove --yes build-essential \ + && apt-get autoclean \ + && apt-get purge \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR / +COPY rootfs / + +HEALTHCHECK --start-period=10m \ + CMD echo '{ "type": "describe" }' \ + | nc -w 1 localhost 10300 \ + | grep -iq "speech-to-phrase" \ + || exit 1 diff --git a/speech_to_phrase/README.md b/speech_to_phrase/README.md new file mode 100644 index 00000000000..131f17934f7 --- /dev/null +++ b/speech_to_phrase/README.md @@ -0,0 +1,18 @@ +# Home Assistant Add-on: Speech to phrase + +![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] + +A fast and local speech-to-text system that is personalized with the names of things in your home. +[Speech-to-phrase](https://github.com/OHF-voice/speech-to-phrase) is targeted at lower-end hardware, such as the Raspberry Pi 4 and Home Assistant Green. + +See the [documentation](http://github.com/OHF-voice/speech-to-phrase) for available voice commands. + +Built on top of the [Year of Voice](https://www.home-assistant.io/blog/2022/12/20/year-of-voice/). + +Requires Home Assistant 2023.11 or later. + +[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg +[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg +[armv7-shield]: https://img.shields.io/badge/armv7-no-red.svg +[armhf-shield]: https://img.shields.io/badge/armhf-no-red.svg +[i386-shield]: https://img.shields.io/badge/i386-no-red.svg diff --git a/speech_to_phrase/build.yaml b/speech_to_phrase/build.yaml new file mode 100644 index 00000000000..736e1c3ba0b --- /dev/null +++ b/speech_to_phrase/build.yaml @@ -0,0 +1,9 @@ +--- +build_from: + amd64: ghcr.io/home-assistant/amd64-base-debian:bookworm + aarch64: ghcr.io/home-assistant/aarch64-base-debian:bookworm +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io +args: + SPEECH_TO_PHRASE_VERSION: 1.3.0 diff --git a/speech_to_phrase/config.yaml b/speech_to_phrase/config.yaml new file mode 100644 index 00000000000..cac2f2858fd --- /dev/null +++ b/speech_to_phrase/config.yaml @@ -0,0 +1,25 @@ +--- +version: 1.3.0 +slug: speech-to-phrase +name: Speech-to-Phrase +description: Fast and personalized local speech-to-text +url: http://github.com/OHF-voice/speech-to-phrase +arch: + - amd64 + - aarch64 +init: false +discovery: + - wyoming +map: + - share:rw +backup_exclude: + - "*/models/*" +homeassistant_api: true +options: + debug_logging: false +schema: + debug_logging: bool +ports: + "10300/tcp": null +homeassistant: 2023.11.0 +image: homeassistant/{arch}-addon-speech-to-phrase diff --git a/speech_to_phrase/icon.png b/speech_to_phrase/icon.png new file mode 100644 index 00000000000..1013d7fcdb7 Binary files /dev/null and b/speech_to_phrase/icon.png differ diff --git a/speech_to_phrase/logo.png b/speech_to_phrase/logo.png new file mode 100644 index 00000000000..5e965abbe3a Binary files /dev/null and b/speech_to_phrase/logo.png differ diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/dependencies.d/speech-to-phrase b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/dependencies.d/speech-to-phrase new file mode 100644 index 00000000000..e69de29bb2d diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/run b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/run new file mode 100755 index 00000000000..9bd21d640de --- /dev/null +++ b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/run @@ -0,0 +1,24 @@ +#!/command/with-contenv bashio +# shellcheck shell=bash +# ============================================================================== +# Sends discovery information to Home Assistant. +# ============================================================================== +declare config + +# Wait for speech-to-phrase to become available +bash -c \ + "until + echo '{ \"type\": \"describe\" }' + > /dev/tcp/localhost/10300; do sleep 0.5; + done" > /dev/null 2>&1 || true; + +config=$(\ + bashio::var.json \ + uri "tcp://$(hostname):10300" \ +) + +if bashio::discovery "wyoming" "${config}" > /dev/null; then + bashio::log.info "Successfully sent discovery information to Home Assistant." +else + bashio::log.error "Discovery message to Home Assistant failed!" +fi diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/type b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/type new file mode 100644 index 00000000000..3d92b15f2d5 --- /dev/null +++ b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/type @@ -0,0 +1 @@ +oneshot \ No newline at end of file diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/up b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/up new file mode 100755 index 00000000000..31b0a0205b5 --- /dev/null +++ b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/discovery/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/discovery/run \ No newline at end of file diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/dependencies.d/base b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/dependencies.d/base new file mode 100644 index 00000000000..e69de29bb2d diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/finish b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/finish new file mode 100755 index 00000000000..1c046b21855 --- /dev/null +++ b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/finish @@ -0,0 +1,26 @@ +#!/command/with-contenv bashio +# shellcheck shell=bash +# ============================================================================== +# Take down the S6 supervision tree when service fails +# s6-overlay docs: https://github.com/just-containers/s6-overlay +# ============================================================================== +# shellcheck disable=SC2155 +readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode + fi + [[ "${exit_code_signal}" -eq 15 ]] && exec /run/s6/basedir/bin/halt +elif [[ "${exit_code_service}" -ne 0 ]]; then + if [[ "${exit_code_container}" -eq 0 ]]; then + echo "${exit_code_service}" > /run/s6-linux-init-container-results/exitcode + fi + exec /run/s6/basedir/bin/halt +fi diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/run b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/run new file mode 100755 index 00000000000..c161807ef21 --- /dev/null +++ b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/run @@ -0,0 +1,40 @@ +#!/command/with-contenv bashio +# shellcheck shell=bash +# ============================================================================== +# Start speech-to-phrase service +# ============================================================================== +cd /usr/src || exit 1 + +flags=() + +if bashio::config.has_value 'hass_websocket_uri'; then + hass_websocket_uri="$(bashio::config 'hass_websocket_uri')" +else + hass_websocket_uri='ws://supervisor/core/websocket' +fi + +if bashio::config.has_value 'hass_token'; then + hass_token="$(bashio::config 'hass_token')" +else + hass_token="${SUPERVISOR_TOKEN}" +fi + +if bashio::config.true 'debug_logging'; then + flags+=('--debug') +fi + +models_dir='/data/models' +mkdir -p "${models_dir}" + +# shellcheck disable=SC2068 +exec .venv/bin/python3 -m speech_to_phrase \ + --uri 'tcp://0.0.0.0:10300' \ + --tools-dir /usr/src/tools \ + --train-dir /share/speech-to-phrase/train \ + --models-dir "${models_dir}" \ + --retrain-on-start \ + --retrain-on-connect \ + --retrain-seconds 300 \ + --custom-sentences-dir /share/speech-to-phrase/custom_sentences \ + --hass-token "${hass_token}" \ + --hass-websocket-uri "${hass_websocket_uri}" ${flags[@]} diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/type b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/type new file mode 100644 index 00000000000..1780f9f44ef --- /dev/null +++ b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/speech-to-phrase/type @@ -0,0 +1 @@ +longrun \ No newline at end of file diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/discovery b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/discovery new file mode 100644 index 00000000000..e69de29bb2d diff --git a/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/speech-to-phrase b/speech_to_phrase/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/speech-to-phrase new file mode 100644 index 00000000000..e69de29bb2d diff --git a/speech_to_phrase/translations/en.yaml b/speech_to_phrase/translations/en.yaml new file mode 100644 index 00000000000..31c8cf2c313 --- /dev/null +++ b/speech_to_phrase/translations/en.yaml @@ -0,0 +1,8 @@ +--- +configuration: + debug_logging: + name: Debug logging + description: >- + Enable debug logging. +network: + 10300/tcp: speech-to-phrase Wyoming Protocol diff --git a/ssh/CHANGELOG.md b/ssh/CHANGELOG.md index 8f1be0875e5..772d834e478 100644 --- a/ssh/CHANGELOG.md +++ b/ssh/CHANGELOG.md @@ -1,5 +1,108 @@ # Changelog +## 9.16.0 + +- Upgrade ttyd to 1.7.7 (fixes copy to clipboard using shift and drag) + +## 9.15.0 + +- Upgrade Home Assistant CLI to 4.36.0 + +## 9.14.0 + +- Upgrade Home Assistant CLI to 4.34.0 + +## 9.13.0 + +- Enable ha command completion for non-login shell (e.g. the web terminal) + +## 9.12.0 + +- Install completions for ha commands +- Fix bash_history file check in startup + +## 9.11.0 + +- Upgrade Home Assistant CLI to 4.32.0 + +## 9.10.0 + +- Upgrade Home Assistant CLI to 4.31.0 + +## 9.9.0 + +- Upgrade to Alpine Linux 3.19 +- Upgrade Home Assistant CLI to 4.29.0 +- Upgrade libwebsockets to 4.3.3 +- Upgrade ttyd to 1.7.4 + +## 9.8.1 + +- Add `/config` symlink to for backward and docs compatibility. + +## 9.8.0 + +- Please note: the `/config` folder has been renamed to `/homeassistant`. +- Add support for accessing public add-on configurations +- Upgrade to Alpine 3.18 + +## 9.7.1 + +- Upgrade Home Assistant CLI to 4.26.0 + +## 9.7.0 + +- Upgrade Home Assistant CLI to 4.23.0 +- Upgrade to Alpine 3.17 +- Update ttyd to 1.7.3 +- Update libwebsockets to 4.3.2 + +## 9.6.2 + +- Make SUPERVISOR_TOKEN available as an SSH environment variable, + making it possible to invoke the Home Assistant CLI + without an interactive bash session. + +## 9.6.1 + +- Upgrade Home Assistant CLI to 4.21.0 + +## 9.6.0 + +**Breaking change**: RSA keys generated using the SHA-1 hash algorithm +were disabled by OpenSSH due to a security vulnerability. If you find +your RSA key does not work after update you will need to make a new key +with a stronger algorithm or switch to an ECDSA or Ed25519 type key. For +more information see [OpenSSH v8.8 release notes](https://www.openssh.com/releasenotes.html). + +- Upgrade Home Assistant CLI to 4.18.0 +- Upgrade to Alpine 3.16 +- Refactor out usage of fix-attrs for s6 v3 + +## 9.4.0 + +- Upgrade Home Assistant CLI to 4.17.0 +- Enabled image signature + +## 9.3.0 + +- Update libwebsockets to 4.2.1 +- Update ttyd to `3e37e33b1cd927ae8f25cfbcf0da268723b6d230` + +## 9.2.2 + +- Fix escape codes in color bash prompt + +## 9.2.1 + +- Upgrade Home Assistant CLI to 4.14.0 + +## 9.2.0 + +- Upgrade to Alpine 3.14 +- Make Bash prompt more colorful +- Upgrade Home Assistant CLI to 4.13.0 + ## 9.1.3 - Upgrade Home Assistant CLI to 4.12.3 @@ -60,7 +163,6 @@ - Update Home Assistant CLI to 4.4.0 - Upgrade Alpine Linux to 3.12 - ## 8.6.0 - Add support for local TCP forwarding @@ -118,4 +220,3 @@ - Improve Hass.io API token handling - Persist .ssh folder across restarts - Add helper symlink folders to user home folder - diff --git a/ssh/DOCS.md b/ssh/DOCS.md index aa057eada8a..66f279ffc6c 100644 --- a/ssh/DOCS.md +++ b/ssh/DOCS.md @@ -5,7 +5,7 @@ Follow these steps to get the add-on installed on your system: 1. This add-on is only visible to "Advanced Mode" users. To enable advanced mode, go to **Profile** -> and turn on **Advanced Mode**. -2. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +2. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. 3. Find the "Terminal & SSH" add-on and click it. 4. Click on the "INSTALL" button. @@ -19,7 +19,7 @@ This add-on adds two main features to your Home Assistant installation: Regardless of how you connect (using the web terminal or using an SSH client), you end up in this add-on's container. The Home Assistant configuration directory is located on the path `/config`. -This add-on comes bundled with [The Home Assistant CLI](https://www.home-assistant.io/hassio/commandline/). Try it out using: +This add-on comes bundled with [The Home Assistant CLI](https://www.home-assistant.io/common-tasks/os#home-assistant-via-the-command-line). Try it out using: ```bash ha help @@ -29,6 +29,14 @@ ha help You can access the web terminal by clicking the "Open Web UI" button on this add-on's Info tab. If you set the "Show in sidebar" setting (found on the same Info tab) to "on", a shortcut is added to the sidebar allowing you to access the web terminal quickly. +To copy text from the Web UI: +1. Hold down the SHIFT key. +2. Select the text you want to copy using your mouse. +3. On releasing the left mouse button, the text gets copied to your system clipboard. + +To paste text into the Web UI: +1. Press SHIFT + INSERT. + ### SSH Server Connection Remote SSH access from the network is disabled by default (See Network below). To connect using an SSH client, such as PuTTY or Linux terminal, you need to supply additional configuration for this add-on. To enable SSH connectivity, you need to: @@ -40,6 +48,8 @@ You can then connect to the port specified, using the username `root`. Please no If you enable connecting to the SSH Server using an SSH client, you are strongly recommended to use private/public keys to log in. As long as you keep the private part of your key safe, this makes your system much harder to break into. Using passwords is, therefore, generally considered a less secure mechanism. To generate private/public SSH keys, follow the [instructions for Windows][keygen-windows] and [these for other platforms][keygen]. +**Note**: While following the instructions above, select ECDSA as `Type of key to generate` instead of RSA. RSA is no longer supported. + Enabling login via password will disable key-based login. You can not run both variants at the same time. ## Configuration @@ -75,7 +85,7 @@ Some SSH server options. #### Option `tcp_forwarding` -Specifies whether TCP forwarding is permitted or not. +Specifies whether TCP port forwarding (-L -R etc.) is permitted or not. **Note**: _Enabling this option lowers the security of your SSH server! Nevertheless, this warning is debatable._ @@ -104,7 +114,7 @@ In case you've found a bug, please [open an issue on our GitHub][issue]. [discord]: https://discord.gg/c5DvZ4e [forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues +[issue]: https://github.com/home-assistant/addons/issues [keygen-windows]: https://www.digitalocean.com/community/tutorials/how-to-create-ssh-keys-with-putty-to-connect-to-a-vps -[keygen]: https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/ +[keygen]: https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent [reddit]: https://reddit.com/r/homeassistant diff --git a/ssh/Dockerfile b/ssh/Dockerfile index e2098985d94..78c3d7b3116 100644 --- a/ssh/Dockerfile +++ b/ssh/Dockerfile @@ -43,7 +43,7 @@ RUN \ -DCMAKE_VERBOSE_MAKEFILE=TRUE \ -DLWS_IPV6=ON \ -DLWS_STATIC_PIC=ON \ - -DLWS_UNIX_SOCK=OFF \ + -DLWS_UNIX_SOCK=ON \ -DLWS_WITH_LIBUV=ON \ -DLWS_WITH_SHARED=ON \ -DLWS_WITHOUT_TESTAPPS=ON \ diff --git a/ssh/build.json b/ssh/build.json deleted file mode 100644 index 5690e941ecf..00000000000 --- a/ssh/build.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "build_from": { - "aarch64": "ghcr.io/home-assistant/aarch64-base:3.13", - "amd64": "ghcr.io/home-assistant/amd64-base:3.13", - "armhf": "ghcr.io/home-assistant/armhf-base:3.13", - "armv7": "ghcr.io/home-assistant/armv7-base:3.13", - "i386": "ghcr.io/home-assistant/i386-base:3.13" - }, - "args": { - "CLI_VERSION": "4.12.3", - "LIBWEBSOCKETS_VERSION": "4.1.4", - "TTYD_VERSION": "1.6.3" - } -} diff --git a/ssh/build.yaml b/ssh/build.yaml new file mode 100644 index 00000000000..abdfd2f6900 --- /dev/null +++ b/ssh/build.yaml @@ -0,0 +1,14 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base:3.19 + amd64: ghcr.io/home-assistant/amd64-base:3.19 + armhf: ghcr.io/home-assistant/armhf-base:3.19 + armv7: ghcr.io/home-assistant/armv7-base:3.19 + i386: ghcr.io/home-assistant/i386-base:3.19 +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io +args: + CLI_VERSION: 4.36.0 + LIBWEBSOCKETS_VERSION: 4.3.3 + TTYD_VERSION: 1.7.7 diff --git a/ssh/config.json b/ssh/config.json deleted file mode 100644 index 85100ccff37..00000000000 --- a/ssh/config.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "Terminal & SSH", - "version": "9.1.3", - "slug": "ssh", - "description": "Allow logging in remotely to Home Assistant using SSH", - "url": "https://github.com/home-assistant/hassio-addons/tree/master/ssh", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "init": false, - "advanced": true, - "startup": "services", - "host_dbus": true, - "ingress": true, - "panel_icon": "mdi:console", - "panel_title": "Terminal", - "hassio_api": true, - "hassio_role": "manager", - "audio": true, - "uart": true, - "ports": { - "22/tcp": null - }, - "map": [ - "config:rw", - "ssl:rw", - "addons:rw", - "share:rw", - "backup:rw", - "media:rw" - ], - "options": { - "authorized_keys": [], - "apks": [], - "password": "", - "server": { - "tcp_forwarding": false - } - }, - "schema": { - "authorized_keys": ["str"], - "password": "password", - "server": { - "tcp_forwarding": "bool" - }, - "apks": ["str"] - }, - "image": "homeassistant/{arch}-addon-ssh" -} diff --git a/ssh/config.yaml b/ssh/config.yaml new file mode 100644 index 00000000000..60379a6f49d --- /dev/null +++ b/ssh/config.yaml @@ -0,0 +1,49 @@ +--- +version: 9.16.0 +slug: ssh +name: Terminal & SSH +description: Allow logging in remotely to Home Assistant using SSH +url: https://github.com/home-assistant/addons/tree/master/ssh +codenotary: notary@home-assistant.io +advanced: true +arch: + - armhf + - armv7 + - aarch64 + - amd64 + - i386 +audio: true +hassio_api: true +hassio_role: manager +host_dbus: true +image: homeassistant/{arch}-addon-ssh +ingress: true +init: false +map: + - addons:rw + - all_addon_configs:rw + - backup:rw + - homeassistant_config:rw + - media:rw + - share:rw + - ssl:rw +options: + authorized_keys: [] + password: "" + apks: [] + server: + tcp_forwarding: false +panel_icon: mdi:console +panel_title: Terminal +ports: + 22/tcp: null +schema: + authorized_keys: + - str + password: password + apks: + - str + server: + tcp_forwarding: bool +startup: services +uart: true diff --git a/ssh/rootfs/etc/cont-init.d/apks.sh b/ssh/rootfs/etc/cont-init.d/apks.sh old mode 100644 new mode 100755 index 35b1d44aa31..f30f784441e --- a/ssh/rootfs/etc/cont-init.d/apks.sh +++ b/ssh/rootfs/etc/cont-init.d/apks.sh @@ -1,4 +1,5 @@ #!/usr/bin/with-contenv bashio +# shellcheck shell=bash # ============================================================================== # SSH install additional packages on startup # ============================================================================== diff --git a/ssh/rootfs/etc/cont-init.d/keygen.sh b/ssh/rootfs/etc/cont-init.d/keygen.sh old mode 100644 new mode 100755 index c913a51a8b8..6dd9efdbd57 --- a/ssh/rootfs/etc/cont-init.d/keygen.sh +++ b/ssh/rootfs/etc/cont-init.d/keygen.sh @@ -1,4 +1,5 @@ #!/usr/bin/with-contenv bashio +# shellcheck shell=bash # ============================================================================== # SSH Host keys # ============================================================================== diff --git a/ssh/rootfs/etc/cont-init.d/profile.sh b/ssh/rootfs/etc/cont-init.d/profile.sh old mode 100644 new mode 100755 index aa816f106e6..6d4642db4eb --- a/ssh/rootfs/etc/cont-init.d/profile.sh +++ b/ssh/rootfs/etc/cont-init.d/profile.sh @@ -1,14 +1,15 @@ #!/usr/bin/with-contenv bashio +# shellcheck shell=bash # ============================================================================== # Setup persistent user settings # ============================================================================== -readonly DIRECTORIES=(addons backup config share ssl) +readonly DIRECTORIES=(addon_configs addons backup homeassistant media share ssl) # Persist shell history by redirecting .bash_history to /data -if ! bashio::fs.file_exists /data/.bash_profile; then +if ! bashio::fs.file_exists /data/.bash_history; then touch /data/.bash_history - chmod 600 /data/.bash_history fi +chmod 600 /data/.bash_history # Make Home Assistant TOKEN available on the CLI mkdir -p /etc/profile.d @@ -22,8 +23,8 @@ bashio::var.json \ # Persist shell profile by redirecting .bash_profile to /data if ! bashio::fs.file_exists /data/.bash_profile; then touch /data/.bash_profile - chmod 600 /data/.bash_profile fi +chmod 600 /data/.bash_profile # Links some common directories to the user's home folder for convenience for dir in "${DIRECTORIES[@]}"; do @@ -31,12 +32,9 @@ for dir in "${DIRECTORIES[@]}"; do || bashio::log.warning "Failed linking common directory: ${dir}" done -# Sets up the users .ssh folder to be persistent -if ! bashio::fs.directory_exists /data/.ssh; then - mkdir -p /data/.ssh \ - || bashio::exit.nok 'Failed to create a persistent .ssh folder' - - chmod 700 /data/.ssh \ - || bashio::exit.nok \ - 'Failed setting permissions on persistent .ssh folder' -fi +# Some links to "old" locations, to match documentation, +# backwards compatibility and musle memory +ln -s "/homeassistant" "/config" \ + || bashio::log.warning "Failed linking common directory: /config" +ln -s "/homeassistant" "${HOME}/config" \ + || bashio::log.warning "Failed linking common directory: ${HOME}/config" diff --git a/ssh/rootfs/etc/cont-init.d/ssh.sh b/ssh/rootfs/etc/cont-init.d/ssh.sh old mode 100644 new mode 100755 index 975860e6706..4b6f2b7b29b --- a/ssh/rootfs/etc/cont-init.d/ssh.sh +++ b/ssh/rootfs/etc/cont-init.d/ssh.sh @@ -1,12 +1,29 @@ #!/usr/bin/with-contenv bashio +# shellcheck shell=bash # ============================================================================== # SSH setup & user # ============================================================================== + +# Sets up the users .ssh folder to be persistent +if ! bashio::fs.directory_exists /data/.ssh; then + mkdir -p /data/.ssh \ + || bashio::exit.nok 'Failed to create a persistent .ssh folder' + +fi +chmod 700 /data/.ssh \ + || bashio::exit.nok \ + 'Failed setting permissions on persistent .ssh folder' + +# Make Home Assistant TOKEN available for non-interactive SSH commands +bashio::var.json \ + supervisor_token "${SUPERVISOR_TOKEN}" \ + | tempio \ + -template /usr/share/tempio/ssh.environment \ + -out /data/.ssh/environment + if bashio::config.has_value 'authorized_keys'; then bashio::log.info "Setup authorized_keys" - mkdir -p /data/.ssh - chmod 700 /data/.ssh rm -f /data/.ssh/authorized_keys while read -r line; do echo "$line" >> /data/.ssh/authorized_keys @@ -32,3 +49,4 @@ tempio \ -conf /data/options.json \ -template /usr/share/tempio/sshd_config \ -out /etc/ssh/sshd_config + diff --git a/ssh/rootfs/etc/fix-attrs.d/cli b/ssh/rootfs/etc/fix-attrs.d/cli deleted file mode 100644 index dbd6e177ba5..00000000000 --- a/ssh/rootfs/etc/fix-attrs.d/cli +++ /dev/null @@ -1,4 +0,0 @@ -/usr/bin/hassio false root 0755 0755 -/usr/bin/ha false root 0755 0755 -/usr/local/bin/reboot false root 0755 0755 -/usr/local/bin/shutdown false root 0755 0755 diff --git a/ssh/rootfs/etc/fix-attrs.d/profile b/ssh/rootfs/etc/fix-attrs.d/profile deleted file mode 100644 index 45857cb4098..00000000000 --- a/ssh/rootfs/etc/fix-attrs.d/profile +++ /dev/null @@ -1,2 +0,0 @@ -/data/.bash_history false root 0600 0755 -/data/.bash_profile false root 0600 0755 diff --git a/ssh/rootfs/etc/fix-attrs.d/ssh b/ssh/rootfs/etc/fix-attrs.d/ssh deleted file mode 100644 index a6fdf24d3f1..00000000000 --- a/ssh/rootfs/etc/fix-attrs.d/ssh +++ /dev/null @@ -1,3 +0,0 @@ -/data/.ssh false root 0644 0700 -/data/.ssh/authorized_keys false root 0600 0755 -/etc/ssh false root 0644 0755 diff --git a/ssh/rootfs/etc/services.d/sshd/finish b/ssh/rootfs/etc/services.d/sshd/finish old mode 100644 new mode 100755 index e5bd8e53c88..f4c53b282d0 --- a/ssh/rootfs/etc/services.d/sshd/finish +++ b/ssh/rootfs/etc/services.d/sshd/finish @@ -1,8 +1,13 @@ -#!/usr/bin/execlineb -S1 +#!/usr/bin/env bashio +# vim: ft=bash # ============================================================================== -# Take down the S6 supervision tree when sshd fails +# Take down the S6 supervision tree when service fails +# s6-overlay docs: https://github.com/just-containers/s6-overlay # ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } -s6-svscanctl -t /var/run/s6/services +if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then + bashio::log.warning "Halt add-on" + exec /run/s6/basedir/bin/halt +fi + +bashio::log.info "Service restart after closing" diff --git a/ssh/rootfs/etc/services.d/sshd/run b/ssh/rootfs/etc/services.d/sshd/run old mode 100644 new mode 100755 index 4be0401f395..8c17525a26e --- a/ssh/rootfs/etc/services.d/sshd/run +++ b/ssh/rootfs/etc/services.d/sshd/run @@ -1,4 +1,6 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Start sshd service if enabled # ============================================================================== diff --git a/ssh/rootfs/etc/services.d/ttyd/finish b/ssh/rootfs/etc/services.d/ttyd/finish old mode 100644 new mode 100755 index 2235a7002aa..f4c53b282d0 --- a/ssh/rootfs/etc/services.d/ttyd/finish +++ b/ssh/rootfs/etc/services.d/ttyd/finish @@ -1,8 +1,13 @@ -#!/usr/bin/execlineb -S1 +#!/usr/bin/env bashio +# vim: ft=bash # ============================================================================== -# Take down the S6 supervision tree when ttyd fails +# Take down the S6 supervision tree when service fails +# s6-overlay docs: https://github.com/just-containers/s6-overlay # ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } -s6-svscanctl -t /var/run/s6/services +if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then + bashio::log.warning "Halt add-on" + exec /run/s6/basedir/bin/halt +fi + +bashio::log.info "Service restart after closing" diff --git a/ssh/rootfs/etc/services.d/ttyd/run b/ssh/rootfs/etc/services.d/ttyd/run old mode 100644 new mode 100755 index b9ea319139d..4f5caad76cb --- a/ssh/rootfs/etc/services.d/ttyd/run +++ b/ssh/rootfs/etc/services.d/ttyd/run @@ -1,8 +1,10 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Start ttyd service for ingress # ============================================================================== bashio::log.info "Starting Web Terminal..." cd /root || bashio::exit.nok "Can't find root folder!" -exec ttyd -p 8099 tmux -u new -A -s homeassistant bash -l \ No newline at end of file +exec ttyd --writable -p 8099 tmux -u new -A -s homeassistant bash -l \ No newline at end of file diff --git a/ssh/rootfs/usr/bin/hassio b/ssh/rootfs/usr/bin/hassio old mode 100644 new mode 100755 index e38eb8633a2..d96db19561b --- a/ssh/rootfs/usr/bin/hassio +++ b/ssh/rootfs/usr/bin/hassio @@ -1,3 +1,4 @@ #!/usr/bin/env bashio +# vim: ft=bash bashio::log.yellow "The 'hassio' command is deprecated, please use 'ha' instead!" ha "$@" diff --git a/ssh/rootfs/usr/local/bin/reboot b/ssh/rootfs/usr/local/bin/reboot old mode 100644 new mode 100755 index 8ab18283c9d..15a93cd88dd --- a/ssh/rootfs/usr/local/bin/reboot +++ b/ssh/rootfs/usr/local/bin/reboot @@ -1,4 +1,6 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # This script overrides the reboot command to reboot the host machine. # ============================================================================== diff --git a/ssh/rootfs/usr/local/bin/shutdown b/ssh/rootfs/usr/local/bin/shutdown old mode 100644 new mode 100755 index 8dc27e3b5d7..3ab4529e2d5 --- a/ssh/rootfs/usr/local/bin/shutdown +++ b/ssh/rootfs/usr/local/bin/shutdown @@ -1,5 +1,7 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# This script overrides the shutdown command to shutdown the host machine. -# ============================================================================== -bashio::host.shutdown +#!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# This script overrides the shutdown command to shutdown the host machine. +# ============================================================================== +bashio::host.shutdown diff --git a/ssh/rootfs/usr/share/tempio/homeassistant.profile b/ssh/rootfs/usr/share/tempio/homeassistant.profile index 58bceacc622..fb3e1471ea4 100644 --- a/ssh/rootfs/usr/share/tempio/homeassistant.profile +++ b/ssh/rootfs/usr/share/tempio/homeassistant.profile @@ -1,5 +1,7 @@ #!/usr/bin/env bash -export PS1="\W \$ " +export PS1="\[\e[0;32m\][\h \W]\$ \[\e[m\]" export SUPERVISOR_TOKEN={{ .supervisor_token }} ha banner +# shellcheck disable=SC1090 +source <(ha completion bash) diff --git a/ssh/rootfs/usr/share/tempio/ssh.environment b/ssh/rootfs/usr/share/tempio/ssh.environment new file mode 100644 index 00000000000..9cfc65cf48c --- /dev/null +++ b/ssh/rootfs/usr/share/tempio/ssh.environment @@ -0,0 +1 @@ +SUPERVISOR_TOKEN={{ .supervisor_token }} diff --git a/ssh/rootfs/usr/share/tempio/sshd_config b/ssh/rootfs/usr/share/tempio/sshd_config index 72e42550192..604dd7d777c 100644 --- a/ssh/rootfs/usr/share/tempio/sshd_config +++ b/ssh/rootfs/usr/share/tempio/sshd_config @@ -24,3 +24,4 @@ PasswordAuthentication yes PermitEmptyPasswords no {{ end }} +PermitUserEnvironment SUPERVISOR_TOKEN diff --git a/ssh/translations/en.yaml b/ssh/translations/en.yaml new file mode 100644 index 00000000000..8157e0a9971 --- /dev/null +++ b/ssh/translations/en.yaml @@ -0,0 +1,17 @@ +--- +configuration: + authorized_keys: + name: Authorized Keys + description: Your public keys that you wish to accept for login. + password: + name: Password + description: Set a password for login. We do NOT recommend this variant. + apks: + name: Packages + description: >- + Additional software packages to install in the add-on container. + server: + name: Server + description: SSH Server configuration +network: + 22/tcp: SSH Port diff --git a/tellstick/CHANGELOG.md b/tellstick/CHANGELOG.md index ca5808914e6..9be6437ccf8 100644 --- a/tellstick/CHANGELOG.md +++ b/tellstick/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 2.2.0 + +**Deprecation notice** +This will be the final update for this addon. The library it depends on is abandoned. +It's last activity was 5 years ago it it cannot be built on alpine >3.15. Users +can continue to use it but no issues or PRs will be accepted for it going forward. + +- Use Alpine 3.15 + ## 2.1.0 - Update hardware configuration for Supervisor 2021.02.5 diff --git a/tellstick/DOCS.md b/tellstick/DOCS.md index b66478c82f6..d775d268c57 100644 --- a/tellstick/DOCS.md +++ b/tellstick/DOCS.md @@ -4,7 +4,7 @@ Follow these steps to get the add-on installed on your system: -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. 2. Find the "TellStick" add-on and click it. 3. Click on the "INSTALL" button. @@ -161,7 +161,7 @@ In case you've found a bug, please [open an issue on our GitHub][issue]. [conf]: http://developer.telldus.com/wiki/TellStick_conf [discord]: https://discord.gg/c5DvZ4e [forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues +[issue]: https://github.com/home-assistant/addons/issues [protocol-list]: http://developer.telldus.com/wiki/TellStick_conf [reddit]: https://reddit.com/r/homeassistant [repository]: https://github.com/hassio-addons/repository diff --git a/tellstick/README.md b/tellstick/README.md index 24b498b2bf3..ca8be041709 100644 --- a/tellstick/README.md +++ b/tellstick/README.md @@ -1,5 +1,11 @@ # Home Assistant Add-on: TellStick +> [!CAUTION] +> **Deprecation notice** +> The library this add-on depends on is abandoned. Its last activity was 5 +> years ago and it cannot be built on Alpine versions above 3.15. Users can continue +> using the add-on, but no issues or pull requests will be accepted. + TellStick and TellStick Duo service. ![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield] @@ -21,4 +27,4 @@ For more details, please check the TellStick [protocol list][protocol-list]. [amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg [armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg [armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg -[i386-shield]: https://img.shields.io/badge/i386-yes-green.svg \ No newline at end of file +[i386-shield]: https://img.shields.io/badge/i386-yes-green.svg diff --git a/tellstick/build.json b/tellstick/build.json deleted file mode 100644 index 5d49c247c55..00000000000 --- a/tellstick/build.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "build_from": { - "aarch64": "homeassistant/aarch64-base:3.13", - "amd64": "homeassistant/amd64-base:3.13", - "armhf": "homeassistant/armhf-base:3.13", - "armv7": "homeassistant/armv7-base:3.13", - "i386": "homeassistant/i386-base:3.13" - }, - "args": { - "TELLDUS_COMMIT": "2598bbed16ffd701f2a07c99582f057a3decbaf3" - } -} diff --git a/tellstick/build.yaml b/tellstick/build.yaml new file mode 100644 index 00000000000..fb0bee1d4e1 --- /dev/null +++ b/tellstick/build.yaml @@ -0,0 +1,12 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base:3.15 + amd64: ghcr.io/home-assistant/amd64-base:3.15 + armhf: ghcr.io/home-assistant/armhf-base:3.15 + armv7: ghcr.io/home-assistant/armv7-base:3.15 + i386: ghcr.io/home-assistant/i386-base:3.15 +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io +args: + TELLDUS_COMMIT: 2598bbed16ffd701f2a07c99582f057a3decbaf3 diff --git a/tellstick/config.json b/tellstick/config.json deleted file mode 100644 index 1cdb7362476..00000000000 --- a/tellstick/config.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "TellStick", - "version": "2.1.0", - "slug": "tellstick", - "description": "TellStick and TellStick Duo service", - "url": "https://github.com/home-assistant/hassio-addons/tree/master/tellstick", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "startup": "system", - "stdin": true, - "usb": true, - "options": { - "devices": [ - { - "id": 1, - "name": "Example device", - "protocol": "everflourish", - "model": "selflearning-switch", - "house": "A", - "unit": "1" - }, - { - "id": 2, - "name": "Example device two", - "protocol": "everflourish", - "model": "selflearning-switch", - "house": "A", - "unit": "2" - } - ] - }, - "schema": { - "devices": [ - { - "id": "int(1,)", - "name": "str", - "protocol": "match(arctech|brateck|comen|everflourish|fineoffset|fuhaote|hasta|ikea|kangtai|mandolyn|oregon|risingsun|sartano|silvanchip|upm|waveman|x10|yidong)", - "model": "match(codeswitch|bell|selflearning-switch|selflearning-dimmer|selflearning|ecosavers|kp100|temperaturehumidity|temperature)?", - "house": "str?", - "code": "str?", - "unit": "str?", - "fade": "str?" - } - ] - }, - "image": "homeassistant/{arch}-addon-tellstick" -} diff --git a/tellstick/config.yaml b/tellstick/config.yaml new file mode 100644 index 00000000000..053a820d696 --- /dev/null +++ b/tellstick/config.yaml @@ -0,0 +1,45 @@ +--- +version: 2.2.0 +slug: tellstick +name: TellStick +description: TellStick and TellStick Duo service +url: https://github.com/home-assistant/addons/tree/master/tellstick +arch: + - armhf + - armv7 + - aarch64 + - amd64 + - i386 +image: homeassistant/{arch}-addon-tellstick +options: + devices: + - house: A + id: 1 + model: selflearning-switch + name: Example device + protocol: everflourish + unit: "1" + - house: A + id: 2 + model: selflearning-switch + name: Example device two + protocol: everflourish + unit: "2" +schema: + devices: + - code: str? + fade: str? + house: str? + id: int(1,) + model: "match(codeswitch|bell|selflearning-switch|selflearning-dimmer|\ + selflearning|ecosavers|kp100|temperaturehumidity|temperature)?" + name: str + protocol: "match(arctech|brateck|comen|everflourish|fineoffset|fuhaote|\ + hasta|ikea|kangtai|mandolyn|oregon|risingsun|sartano|\ + silvanchip|upm|waveman|x10|yidong)" + unit: str? +startup: system +stdin: true +usb: true +init: false +stage: deprecated diff --git a/tellstick/data/run.sh b/tellstick/data/run.sh index 65ff3db2ff8..f2ca631f59d 100755 --- a/tellstick/data/run.sh +++ b/tellstick/data/run.sh @@ -1,4 +1,5 @@ -#!/usr/bin/env bashio +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash set -e CONFIG="/etc/tellstick.conf" diff --git a/tellstick/translations/en.yaml b/tellstick/translations/en.yaml new file mode 100644 index 00000000000..22b08727503 --- /dev/null +++ b/tellstick/translations/en.yaml @@ -0,0 +1,7 @@ +--- +configuration: + devices: + name: Devices + description: >- + Add one or more devices entries to the add-on configuration for each + device you'd like to add. diff --git a/vlc/CHANGELOG.md b/vlc/CHANGELOG.md index 7ad84f45249..b505485fa3d 100644 --- a/vlc/CHANGELOG.md +++ b/vlc/CHANGELOG.md @@ -1,13 +1,28 @@ -# Changelog - -## 0.1.2 - -- Revert restart nginx service on error - -## 0.1.1 - -- Restart nginx service on error - -## 0.1.0 - -- Inital release +# Changelog + +## 0.3.0 + +- Prevent race condition reading secrets on startup +- Update to Alpine 3.19 + +## 0.2.0 + +- Update to Alpine 3.17 +- Mark add-on as stable +- Use new s6-overlay + +## 0.1.3 + +- Correct port on discovery + +## 0.1.2 + +- Revert restart nginx service on error + +## 0.1.1 + +- Restart nginx service on error + +## 0.1.0 + +- Initial release diff --git a/vlc/DOCS.md b/vlc/DOCS.md index 928e8a2600f..0af36af75e5 100644 --- a/vlc/DOCS.md +++ b/vlc/DOCS.md @@ -4,7 +4,7 @@ Follow these steps to get the add-on installed on your system: -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. 2. Find the "VLC" add-on and click it. 3. Click on the "INSTALL" button. @@ -17,10 +17,7 @@ Follow these steps to get the add-on installed on your system: ## Configuration -Add-on configuration: - -```yaml -``` +Note that automatic discovery is expected when the add-on is being installed. If no "VLC media player via Telnet" integration is being discovered, make sure to remove any stale "VLC media player via Telnet" integrations and reinstall the add-on to trigger discovery again. ## Support @@ -36,5 +33,5 @@ In case you've found a bug, please [open an issue on our GitHub][issue]. [discord]: https://discord.gg/c5DvZ4e [forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues +[issue]: https://github.com/home-assistant/addons/issues [reddit]: https://reddit.com/r/homeassistant diff --git a/vlc/build.json b/vlc/build.json deleted file mode 100644 index 61333837332..00000000000 --- a/vlc/build.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "build_from": { - "amd64": "homeassistant/amd64-base:3.13", - "i386": "homeassistant/i386-base:3.13", - "armv7": "homeassistant/armv7-base:3.13", - "aarch64": "homeassistant/aarch64-base:3.13" - } -} diff --git a/vlc/build.yaml b/vlc/build.yaml new file mode 100644 index 00000000000..ecb8cacf60b --- /dev/null +++ b/vlc/build.yaml @@ -0,0 +1,9 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base:3.19 + amd64: ghcr.io/home-assistant/amd64-base:3.19 + armv7: ghcr.io/home-assistant/armv7-base:3.19 + i386: ghcr.io/home-assistant/i386-base:3.19 +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io diff --git a/vlc/config.json b/vlc/config.json deleted file mode 100644 index 50099dab0c4..00000000000 --- a/vlc/config.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "VLC", - "version": "0.1.2", - "slug": "vlc", - "description": "Turn your device into a Media Player with VLC", - "arch": ["amd64", "i386", "armv7", "aarch64"], - "url": "https://github.com/home-assistant/hassio-addons/tree/master/vlc", - "startup": "services", - "init": false, - "stage": "experimental", - "map": ["share:ro", "media:ro"], - "homeassistant": "2021.3.0.dev20210216", - "ingress": true, - "panel_icon": "mdi:vlc", - "discovery": ["vlc_telnet"], - "audio": true, - "options": {}, - "schema": false, - "image": "homeassistant/{arch}-addon-vlc" -} diff --git a/vlc/config.yaml b/vlc/config.yaml new file mode 100644 index 00000000000..92364b428f2 --- /dev/null +++ b/vlc/config.yaml @@ -0,0 +1,26 @@ +--- +version: 0.3.0 +slug: vlc +name: VLC +description: Turn your device into a Media Player with VLC +url: https://github.com/home-assistant/addons/tree/master/vlc +arch: + - amd64 + - i386 + - armv7 + - aarch64 +audio: true +discovery: + - vlc_telnet +homeassistant: 2021.3.0.dev20210216 +image: homeassistant/{arch}-addon-vlc +ingress: true +init: false +map: + - share:ro + - media:ro +options: {} +panel_icon: mdi:vlc +schema: false +stage: stable +startup: services diff --git a/vlc/rootfs/etc/cont-init.d/ingress.sh b/vlc/rootfs/etc/cont-init.d/ingress.sh old mode 100644 new mode 100755 index 34feefd6105..1a40e83ff0d --- a/vlc/rootfs/etc/cont-init.d/ingress.sh +++ b/vlc/rootfs/etc/cont-init.d/ingress.sh @@ -1,6 +1,7 @@ #!/usr/bin/with-contenv bashio +# shellcheck shell=bash # ============================================================================== -# Prepair VLC for ingress access +# Prepare VLC for ingress access # ============================================================================== # Generate NGINX config diff --git a/vlc/rootfs/etc/cont-init.d/secret.sh b/vlc/rootfs/etc/cont-init.d/secret.sh old mode 100644 new mode 100755 index e44da81a8fb..c690bc8cc9d --- a/vlc/rootfs/etc/cont-init.d/secret.sh +++ b/vlc/rootfs/etc/cont-init.d/secret.sh @@ -1,4 +1,5 @@ #!/usr/bin/with-contenv bashio +# shellcheck shell=bash # ============================================================================== # Create VLC secret # ============================================================================== diff --git a/vlc/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish b/vlc/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish new file mode 100755 index 00000000000..277f3b37937 --- /dev/null +++ b/vlc/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish @@ -0,0 +1,14 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Take down the S6 supervision tree when service fails +# s6-overlay docs: https://github.com/just-containers/s6-overlay +# ============================================================================== + +if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then + bashio::log.warning "Halt add-on" + exec /run/s6/basedir/bin/halt +fi + +bashio::log.info "Service restart after closing" diff --git a/vlc/rootfs/etc/services.d/nginx/run b/vlc/rootfs/etc/s6-overlay/s6-rc.d/nginx/run old mode 100644 new mode 100755 similarity index 73% rename from vlc/rootfs/etc/services.d/nginx/run rename to vlc/rootfs/etc/s6-overlay/s6-rc.d/nginx/run index bd6f1e811a8..28b0ae417aa --- a/vlc/rootfs/etc/services.d/nginx/run +++ b/vlc/rootfs/etc/s6-overlay/s6-rc.d/nginx/run @@ -1,4 +1,6 @@ -#!/usr/bin/env bashio +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Start NGINX service # ============================================================================== diff --git a/vlc/rootfs/etc/s6-overlay/s6-rc.d/nginx/type b/vlc/rootfs/etc/s6-overlay/s6-rc.d/nginx/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/vlc/rootfs/etc/s6-overlay/s6-rc.d/nginx/type @@ -0,0 +1 @@ +longrun diff --git a/vlc/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/nginx b/vlc/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/nginx new file mode 100644 index 00000000000..e69de29bb2d diff --git a/vlc/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/vlc b/vlc/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/vlc new file mode 100644 index 00000000000..e69de29bb2d diff --git a/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/dependencies.d/base b/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/dependencies.d/base new file mode 100644 index 00000000000..e69de29bb2d diff --git a/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/finish b/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/finish new file mode 100755 index 00000000000..277f3b37937 --- /dev/null +++ b/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/finish @@ -0,0 +1,14 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Take down the S6 supervision tree when service fails +# s6-overlay docs: https://github.com/just-containers/s6-overlay +# ============================================================================== + +if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then + bashio::log.warning "Halt add-on" + exec /run/s6/basedir/bin/halt +fi + +bashio::log.info "Service restart after closing" diff --git a/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/run b/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/run new file mode 100755 index 00000000000..913716ffba8 --- /dev/null +++ b/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/run @@ -0,0 +1,14 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start VLC service +# ============================================================================== +# shellcheck disable=SC2155 +readonly PASSWORD="$(cat /data/secret)" + +# Send out discovery information to Home Assistant +/etc/s6-overlay/scripts/vlc-discovery & + +# Run daemon +exec cvlc -I http --no-dbus --extraintf telnet --http-host 127.0.0.1 --http-password "INGRESS" --telnet-password "${PASSWORD}" --aout=pulse diff --git a/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/type b/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/type new file mode 100644 index 00000000000..5883cff0cd1 --- /dev/null +++ b/vlc/rootfs/etc/s6-overlay/s6-rc.d/vlc/type @@ -0,0 +1 @@ +longrun diff --git a/vlc/rootfs/etc/services.d/vlc/discovery b/vlc/rootfs/etc/s6-overlay/scripts/vlc-discovery similarity index 91% rename from vlc/rootfs/etc/services.d/vlc/discovery rename to vlc/rootfs/etc/s6-overlay/scripts/vlc-discovery index ad4af057b42..70910304477 100755 --- a/vlc/rootfs/etc/services.d/vlc/discovery +++ b/vlc/rootfs/etc/s6-overlay/scripts/vlc-discovery @@ -1,4 +1,6 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Send vlc_telnet discovery information to Home Assistant # ============================================================================== @@ -8,7 +10,7 @@ declare ha_config ha_config=$(\ bashio::var.json \ host "$(hostname)" \ - port "^3000" \ + port "^4212" \ password "$(cat /data/secret)" \ ) diff --git a/vlc/rootfs/etc/services.d/nginx/finish b/vlc/rootfs/etc/services.d/nginx/finish deleted file mode 100644 index 5bb07a651c9..00000000000 --- a/vlc/rootfs/etc/services.d/nginx/finish +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/execlineb -S1 -# ============================================================================== -# Take down the S6 supervision tree based on service exit code -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } - -s6-svscanctl -t /var/run/s6/services diff --git a/vlc/rootfs/etc/services.d/vlc/finish b/vlc/rootfs/etc/services.d/vlc/finish deleted file mode 100644 index d886e9f6b34..00000000000 --- a/vlc/rootfs/etc/services.d/vlc/finish +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/execlineb -S1 -# ============================================================================== -# Take down the S6 supervision tree when Z-Wave JS fails -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } - -s6-svscanctl -t /var/run/s6/services diff --git a/vlc/rootfs/etc/services.d/vlc/run b/vlc/rootfs/etc/services.d/vlc/run deleted file mode 100644 index 90d2c0ed4a3..00000000000 --- a/vlc/rootfs/etc/services.d/vlc/run +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Start Z-Wave JS service for Z-Wave radio -# ============================================================================== -readonly PASSWORD="$(cat /data/secret)" - -# Send out discovery information to Home Assistant -./discovery & - -# Run daemon -exec cvlc -I http --extraintf telnet --http-host 127.0.0.1 --http-password "INGRESS" --telnet-password "${PASSWORD}" --aout=pulse diff --git a/whisper/CHANGELOG.md b/whisper/CHANGELOG.md new file mode 100644 index 00000000000..46636f52029 --- /dev/null +++ b/whisper/CHANGELOG.md @@ -0,0 +1,68 @@ +# Changelog + +## 2.4.0 + +- Add "auto" for model and beam size (0) to select values based on CPU + +## 2.3.1 + +- Move `turbo` down the list closer to `large` to avoid confusion + +## 2.3.0 + +- Bump `wyoming-whisper` to 2.3.0 (`faster-whisper` to 1.1.0) +- Supports model `turbo` for faster processing + +## 2.2.0 + +- Bump `wyoming-whisper` to 2.2.0 (`faster-whisper` to 1.0.3) + +## 2.1.2 + +- Fix excluding models files from backup + +## 2.1.1 + +- Exclude `data/models*` files from backup + +## 2.1.0 + +- Add distil-large-v3 `model` option + +## 2.0.0 + +- Add more models for `model` option +- Add "custom" option for `model` that will use `custom_model` instead +- Add `custom_model` that can be a path to a model directory or HuggingFace Hub model ID +- Use faster-whisper PyPI package +- Add `initial_prompt` for helping with unusual words (see: https://github.com/openai/whisper/discussions/963) + +## 1.0.2 + +- Convert error to warning for CPUs not supporting AVX instructions + +## 1.0.1 + +- Handle unsupported CPU configurations + +## 1.0.0 + +- Upgrade to `wyoming-whisper` 1.0.1 +- Allow multiple languages to be used simultaneously without restart + +## 0.2.1 + +- Exclude `*.bin` model files from backup + +## 0.2.0 + +- Hash model files at startup to detect bad downloads +- Fix "auto" language + +## 0.1.1 + +- Enable Wyoming protocol discovery + +## 0.1.0 + +- Initial release diff --git a/whisper/DOCS.md b/whisper/DOCS.md new file mode 100644 index 00000000000..6079448f363 --- /dev/null +++ b/whisper/DOCS.md @@ -0,0 +1,103 @@ +# Home Assistant Add-on: Whisper + +## Installation + +Follow these steps to get the add-on installed on your system: + +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on store**. +2. Find the "Whisper" add-on and click it. +3. Click on the "INSTALL" button. + +## How to use + +After this add-on is installed and running, it will be automatically discovered +by the Wyoming integration in Home Assistant. To finish the setup, +click the following my button: + +[![Open your Home Assistant instance and start setting up a new integration.](https://my.home-assistant.io/badges/config_flow_start.svg)](https://my.home-assistant.io/redirect/config_flow_start/?domain=wyoming) + +Alternatively, you can install the Wyoming integration manually, see the +[Wyoming integration documentation](https://www.home-assistant.io/integrations/wyoming/) +for more information. + +## Configuration + +### Option: `language` + +Default language for the add-on. In Home Assist 2023.8+, multiple languages can be used simultaneously by different [Assist pipelines](https://www.home-assistant.io/voice_control/voice_remote_local_assistant/). + +If you select "auto", the model will run **much** slower but will auto-detect the spoken language. + +[Performance of supported languages](https://github.com/openai/whisper#available-models-and-languages) + +[List of two-letter language codes](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) + +### Option: `model` + +Whisper model that will be used for transcription. Choose `custom` to use the model name in `custom_model`, which may be a HuggingFace model ID like "Systran/faster-distil-whisper-small.en". + +The default model is `auto`, which selects `tiny-int8` for ARM devices like the Raspberry Pi 4 and `base-int8` otherwise. +Compressed models (`int8`) are slightly less accurate than their counterparts, but smaller and faster. [Distilled](https://github.com/huggingface/distil-whisper) models are not compressed, but are faster and smaller than their non-distilled counterparts. + +Available models: + +- `auto` (select based on CPU) +- `tiny-int8` (compressed) +- `tiny` +- `tiny.en` (English only) +- `base-int8` (compressed) +- `base` +- `base.en` (English only) +- `small-int8` (compressed) +- `distil-small.en` (distilled, English only) +- `small` +- `small.en` (English only) +- `medium-int8` (compressed) +- `distil-medium.en` (distilled, English only) +- `medium` +- `medium.en` (English only) +- `large` +- `large-v1` +- `distil-large-v2` (distilled, English only) +- `large-v2` +- `distil-large-v3` (distilled, English only) +- `large-v3` +- `turbo` (faster than `large-v3`) + +### Option: `custom_model` + +Path to a converted model directory, or a CTranslate2-converted Whisper model ID from the HuggingFace Hub like "Systran/faster-distil-whisper-small.en". + +### Option: `beam_size` + +Number of candidates to consider simultaneously during transcription (see [beam search](https://en.wikipedia.org/wiki/Beam_search)). +The default value of `0` will automatically select `1` of ARM devices like the Raspberry Pi 4 and `5` otherwise. + +Increasing the beam size will increase accuracy at the cost of performance. + +### Option: `initial_prompt` + +Description of audio that can help Whisper transcribe unusual words better. +See [this discussion](https://github.com/openai/whisper/discussions/963) for an example. + +## Backups + +Whisper model files can be quite large, so they are automatically excluded from backups. The models will be re-downloaded when the backup is restored. + +## Support + +Got questions? + +You have several options to get them answered: + +- The [Home Assistant Discord Chat Server][discord]. +- The Home Assistant [Community Forum][forum]. +- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit] + +In case you've found an bug, please [open an issue on our GitHub][issue]. + +[discord]: https://discord.gg/c5DvZ4e +[forum]: https://community.home-assistant.io +[issue]: https://github.com/home-assistant/addons/issues +[reddit]: https://reddit.com/r/homeassistant +[repository]: https://github.com/hassio-addons/repository diff --git a/whisper/Dockerfile b/whisper/Dockerfile new file mode 100644 index 00000000000..eeecbda4a92 --- /dev/null +++ b/whisper/Dockerfile @@ -0,0 +1,35 @@ +ARG BUILD_FROM +FROM ${BUILD_FROM} + +# Install Whisper +WORKDIR /usr/src +ARG WYOMING_WHISPER_VERSION + +RUN \ + apt-get update \ + && apt-get install -y --no-install-recommends \ + build-essential \ + netcat \ + python3 \ + python3-dev \ + python3-pip \ + \ + && pip3 install --no-cache-dir -U \ + setuptools \ + wheel \ + && pip3 install --no-cache-dir \ + "wyoming-faster-whisper @ https://github.com/rhasspy/wyoming-faster-whisper/archive/refs/tags/v${WYOMING_WHISPER_VERSION}.tar.gz" \ + \ + && apt-get purge -y --auto-remove \ + build-essential \ + python3-dev \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR / +COPY rootfs / + +HEALTHCHECK --start-period=10m \ + CMD echo '{ "type": "describe" }' \ + | nc -w 1 localhost 10300 \ + | grep -q "faster-whisper" \ + || exit 1 diff --git a/whisper/README.md b/whisper/README.md new file mode 100644 index 00000000000..75d92c987e9 --- /dev/null +++ b/whisper/README.md @@ -0,0 +1,13 @@ +# Home Assistant Add-on: Whisper + +![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] + +Home Assistant add-on that uses [faster-whisper](https://github.com/guillaumekln/faster-whisper/) for speech-to-text. + +Part of the [Year of Voice](https://www.home-assistant.io/blog/2022/12/20/year-of-voice/). + +[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg +[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg +[armhf-shield]: https://img.shields.io/badge/armhf-no-red.svg +[armv7-shield]: https://img.shields.io/badge/armv7-no-red.svg +[i386-shield]: https://img.shields.io/badge/i386-no-red.svg diff --git a/whisper/build.yaml b/whisper/build.yaml new file mode 100644 index 00000000000..c9e004246ab --- /dev/null +++ b/whisper/build.yaml @@ -0,0 +1,9 @@ +--- +build_from: + amd64: ghcr.io/home-assistant/amd64-base-debian:bullseye + aarch64: ghcr.io/home-assistant/aarch64-base-debian:bullseye +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io +args: + WYOMING_WHISPER_VERSION: 2.4.0 diff --git a/whisper/config.yaml b/whisper/config.yaml new file mode 100644 index 00000000000..788b0e03d45 --- /dev/null +++ b/whisper/config.yaml @@ -0,0 +1,32 @@ +--- +version: 2.4.0 +slug: whisper +name: Whisper +description: Speech-to-text with Whisper +url: https://github.com/home-assistant/addons/blob/master/whisper +arch: + - amd64 + - aarch64 +init: false +discovery: + - wyoming +backup_exclude: + - "models*" +options: + model: auto + language: en + beam_size: 0 + debug_logging: false +schema: + model: | + list(auto|tiny-int8|tiny|tiny.en|base-int8|base|base.en|small-int8|distil-small.en|small|small.en|distil-medium.en|medium-int8|medium|medium.en|large|large-v1|distil-large-v2|large-v2|distil-large-v3|large-v3|turbo|custom) + custom_model: str? + language: | + list(auto|af|am|ar|as|az|ba|be|bg|bn|bo|br|bs|ca|cs|cy|da|de|el|en|es|et|eu|fa|fi|fo|fr|gl|gu|ha|haw|he|hi|hr|ht|hu|hy|id|is|it|ja|jw|ka|kk|km|kn|ko|la|lb|ln|lo|lt|lv|mg|mi|mk|ml|mn|mr|ms|mt|my|ne|nl|nn|no|oc|pa|pl|ps|pt|ro|ru|sa|sd|si|sk|sl|sn|so|sq|sr|su|sv|sw|ta|te|tg|th|tk|tl|tr|tt|uk|ur|uz|vi|yi|yo|zh|yue) + beam_size: int + initial_prompt: str? + debug_logging: bool +ports: + "10300/tcp": null +homeassistant: 2023.8.0.dev20230728 +image: homeassistant/{arch}-addon-whisper diff --git a/whisper/icon.png b/whisper/icon.png new file mode 100644 index 00000000000..a9bdb11ad5b Binary files /dev/null and b/whisper/icon.png differ diff --git a/whisper/logo.png b/whisper/logo.png new file mode 100644 index 00000000000..ed85b39c88d Binary files /dev/null and b/whisper/logo.png differ diff --git a/whisper/rootfs/etc/s6-overlay/s6-rc.d/discovery/dependencies.d/whisper b/whisper/rootfs/etc/s6-overlay/s6-rc.d/discovery/dependencies.d/whisper new file mode 100644 index 00000000000..e69de29bb2d diff --git a/whisper/rootfs/etc/s6-overlay/s6-rc.d/discovery/run b/whisper/rootfs/etc/s6-overlay/s6-rc.d/discovery/run new file mode 100755 index 00000000000..979e7a58ab0 --- /dev/null +++ b/whisper/rootfs/etc/s6-overlay/s6-rc.d/discovery/run @@ -0,0 +1,25 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Sends discovery information to Home Assistant. +# ============================================================================== +declare config + +# Wait for Whisper to become available +bash -c \ + "until + echo '{ \"type\": \"describe\" }' + > /dev/tcp/localhost/10300; do sleep 0.5; + done" > /dev/null 2>&1 || true; + +config=$(\ + bashio::var.json \ + uri "tcp://$(hostname):10300" \ +) + +if bashio::discovery "wyoming" "${config}" > /dev/null; then + bashio::log.info "Successfully send discovery information to Home Assistant." +else + bashio::log.error "Discovery message to Home Assistant failed!" +fi diff --git a/whisper/rootfs/etc/s6-overlay/s6-rc.d/discovery/type b/whisper/rootfs/etc/s6-overlay/s6-rc.d/discovery/type new file mode 100644 index 00000000000..3d92b15f2d5 --- /dev/null +++ b/whisper/rootfs/etc/s6-overlay/s6-rc.d/discovery/type @@ -0,0 +1 @@ +oneshot \ No newline at end of file diff --git a/whisper/rootfs/etc/s6-overlay/s6-rc.d/discovery/up b/whisper/rootfs/etc/s6-overlay/s6-rc.d/discovery/up new file mode 100755 index 00000000000..31b0a0205b5 --- /dev/null +++ b/whisper/rootfs/etc/s6-overlay/s6-rc.d/discovery/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/discovery/run \ No newline at end of file diff --git a/whisper/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/discovery b/whisper/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/discovery new file mode 100644 index 00000000000..e69de29bb2d diff --git a/whisper/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/whisper b/whisper/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/whisper new file mode 100644 index 00000000000..e69de29bb2d diff --git a/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/dependencies.d/base b/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/dependencies.d/base new file mode 100644 index 00000000000..e69de29bb2d diff --git a/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/finish b/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/finish new file mode 100755 index 00000000000..0bc8d2e7ab5 --- /dev/null +++ b/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/finish @@ -0,0 +1,27 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Take down the S6 supervision tree when service fails +# s6-overlay docs: https://github.com/just-containers/s6-overlay +# ============================================================================== +# shellcheck disable=SC2155 +readonly exit_code_container=$( /run/s6-linux-init-container-results/exitcode + fi + [[ "${exit_code_signal}" -eq 15 ]] && exec /run/s6/basedir/bin/halt +elif [[ "${exit_code_service}" -ne 0 ]]; then + if [[ "${exit_code_container}" -eq 0 ]]; then + echo "${exit_code_service}" > /run/s6-linux-init-container-results/exitcode + fi + exec /run/s6/basedir/bin/halt +fi \ No newline at end of file diff --git a/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/run b/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/run new file mode 100755 index 00000000000..c9584fbaa01 --- /dev/null +++ b/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/run @@ -0,0 +1,33 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash +# ============================================================================== +# Start Whisper service +# ============================================================================== + +if [ "$(uname -m)" == "x86_64" ] && ! grep -qw 'avx' /proc/cpuinfo; then + bashio::log.warning "Your CPU does not support Advanced Vector Extensions (AVX). Whisper will run slower than normal." +fi + +model="$(bashio::config 'model')" +if [ "${model}" = 'custom' ]; then + # Override with custom model + model="$(bashio::config 'custom_model')" + if [ -z "${model}" ]; then + bashio::exit.nok "Custom model is not set" + fi +fi + +if bashio::config.true 'debug_logging'; then + flags+=('--debug') +fi + +# shellcheck disable=SC2068 +exec python3 -m wyoming_faster_whisper \ + --uri 'tcp://0.0.0.0:10300' \ + --model "${model}" \ + --beam-size "$(bashio::config 'beam_size')" \ + --language "$(bashio::config 'language')" \ + --initial-prompt "$(bashio::config 'initial_prompt')" \ + --data-dir /data \ + --download-dir /data ${flags[@]} diff --git a/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/type b/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/type new file mode 100644 index 00000000000..1780f9f44ef --- /dev/null +++ b/whisper/rootfs/etc/s6-overlay/s6-rc.d/whisper/type @@ -0,0 +1 @@ +longrun \ No newline at end of file diff --git a/whisper/translations/en.yaml b/whisper/translations/en.yaml new file mode 100644 index 00000000000..3e0c1b5aad4 --- /dev/null +++ b/whisper/translations/en.yaml @@ -0,0 +1,39 @@ +--- +configuration: + beam_size: + name: Beam size + description: >- + Number of candidates to consider simultaneously during transcription. + Increasing the beam size will increase accuracy at the cost of + performance. + language: + name: Language + description: >- + Language that you will speak to the add-on. If you select "auto", + the model will run much slower but will auto-detect the spoken language. + model: + name: Model + description: | + Whisper model that will be used for transcription. + + The default model is `tiny-int8`, a compressed version of the smallest + Whisper model which is able to run on a Raspberry Pi 4. Compressed models + (`int8`) are slightly less accurate than their counterparts, but smaller + and faster. + custom_model: + name: Custom model + description: | + Path to a converted model directory, or a CTranslate2-converted Whisper + model ID from the HuggingFace Hub like + "Systran/faster-distil-whisper-small.en". + initial_prompt: + name: Initial prompt + description: >- + Description of audio that can help Whisper transcribe unusual words + better. + debug_logging: + name: Debug logging + description: >- + Print DEBUG level messages to the add-on's log. +network: + 10300/tcp: Whisper Wyoming Protocol diff --git a/zwave/CHANGELOG.md b/zwave/CHANGELOG.md deleted file mode 100644 index 0c8dfc4ad04..00000000000 --- a/zwave/CHANGELOG.md +++ /dev/null @@ -1,112 +0,0 @@ -# Changelog - -## 0.9.1 - -- Update hardware configuration for Supervisor 2021.02.5 - -## 0.9.0 - -- Update OpenZWave to ee90c89 -- Cleanup permissions - -## 0.8.0 - -- Update OpenZWave to 66619ed -- Update ozw-admin to f68b43e - -## 0.7.1 - -- Fix timezone issue on Alpine - -## 0.7.0 - -- Fix vnc / ozwadmin -- Update Openzwave to 1c7b620 -- Update qt-openzwave to 7ebd43e2 - -## 0.6.0 - -- Fix vnc / ozwadmin - -## 0.5.4 - -- Fix build issues with 32bit CPU - -## 0.5.3 - -- Update Openzwave to 7eaae21 - -## 0.5.2 - -- Fix startup failure due to stray OZW Daemon status retained in MQTT -- Propagate shutdown OZW Daemon status to upstream MQTT on shutdown -- Update OpenZWave to 6cf3729 - -## 0.5.1 - -- Roll-back alpine to 3.11 and qt 5.12 -- Roll-back OpenZWave to 6c2ca613 - -## 0.5.0 - -- Update OpenZWave to 5d3978d5 -- Update ozw-admin to da04ebfb -- Update qt-openzwave to 3ad9138f -- Update alpine to 3.12 - -## 0.4.4 - -- Update OpenZWave to a35732f -- Update ozw-admin to 278427b - -## 0.4.3 - -- Update OpenZWave to 6cec95b -- Update ozw-admin to 167180c - -## 0.4.2 - -- Improve error message when using documented network_key - -## 0.4.1 - -- Fix optional instance parameter - -## 0.4.0 - -- Add OZW instance ID configuration option -- Fix persistent storage of OpenZWave -- Fix permissions on discovery script -- Fix OZW database location -- Improve build speed by using all available cores -- Add built-in ozw-admin -- Add VNC access to add-on to access ozw-admin -- Add Ingress support to add-on to access ozw-admin -- Documentation improvements -- Update OpenZWave (and database) to d2de699 -- Update ozwdaemon to 337e488 -- Add logo and icon -- Detect use of example network key from documentation - -## 0.3.0 - -- Add port to allow ozw-admin to connect -- Enable discovery again -- Set network key default to empty - -## 0.2.1 - -- Disable discovery for 0.110.0 - -## 0.2.0 - -- Update OZW / QTOZW -- Rename `zwave_mqtt` to `ozw` - -## 0.1.1 - -- Fix i386 build - -## 0.1.0 - -- Initial release diff --git a/zwave/DOCS.md b/zwave/DOCS.md deleted file mode 100644 index aaee28898f5..00000000000 --- a/zwave/DOCS.md +++ /dev/null @@ -1,179 +0,0 @@ -# Home Assistant Add-on: OpenZWave - -## Installation - -Follow these steps to get the add-on installed on your system: - -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. -2. Find the "OpenZWave" add-on and click it. -3. Click on the "INSTALL" button. -4. This add-on currently requires to have the Mosquitto add-on installed. - Please make sure to install and set up that add-on before continuing. - -## How to use - -The add-on needs to know where your Z-Wave stick can be found, and therefore, -you'll need to configure the add-on to point to the right device. - -If you're using Home Assistant you may find the correct value for this on the -`Supervisor -> System -> Host system -> Hardware` page. It is recommended -to use a "by-id" path to the device if one exists, as it is not subject to -change if other devices are added to the system. - -1. Replace `null` in the `device` option in the add-on configuration and specify - the device name in quotes: e.g., something like - `"/dev/serial/by-id/usb-0658_0200-if00"`, - `"/dev/ttyUSB0"`, `"/dev/ttyAMA0"`, or `"/dev/ttyACM0"`. -2. Set your 16-byte network key in the form `0x01, 0x02...` used in order to - connect securely to compatible devices. It is recommended that a network key - is configured as security enabled devices may not function correctly if they - are not added securely. -3. Click on "SAVE" to save the add-on configuration. -4. Start the add-on. -5. Add the OpenZWave integration to Home Assistant, see documentation: - - -After installing and starting this add-on, access the ozw-admin interface using -the "OPEN WEBUI" button. - -## Configuration - -Add-on configuration: - -```yaml -device: /dev/ttyUSB0 -network_key: 0x2e, 0xcc, 0xab, 0x1c, 0xa3, 0x7f, 0x0e, 0xb5, 0x70, 0x71, 0x2d, 0x98, 0x25, 0x43, 0xee, 0x0c -instance: 1 -``` - -### Option `device` - -The device address of your Z-Wave controller. - -If you're using Home Assistant you may find the correct value for this on the -`Supervisor -> System -> Host system -> Hardware` page. It is recommended -to use a "by-id" path to the device if one exists, as it is not subject to -change if other devices are added to the system. - -In most cases this looks like one of the following: - -- `"/dev/serial/by-id/usb-0658_0200-if00"` -- `"/dev/ttyUSB0"` -- `"/dev/ttyAMA0"` -- `"/dev/ttyACM0"` - -### Option `network_key` - -Security Z-Wave devices require a network key before being added to the network. -You must set the `network_key` configuration option to use a network key before -adding these devices. - -To generate a network key, you can use the following script in, e.g., the SSH -add-on: - -```bash -cat /dev/urandom | tr -dc '0-9A-F' | fold -w 32 | head -n 1 | sed -e 's/\(..\)/0x\1, /g' -e 's/, $//' -``` - -You can also use sites like this one to generate the required data, -just remember to put `0x` before each pair of characters: - - - -Ensure you keep a backup of this key. If you have to rebuild your system and -don't have a backup of this key, you won't be able to reconnect to any security -devices. This may mean you have to do a factory reset on those devices, and your -controller, before rebuilding your Z-Wave network. - -### Option `instance` (optional) - -Z-Wave instance number as reported to MQTT. This corresponds with the -`instance_id` attribute of `ozw` services in Home Assistant. - -The instance ID defaults to `1`, which is generally fine to keep and use. -Only change this in case you are using multiple instances on the same MQTT -server. - -## Accessing the ozw-admin application - -The add-on allows you to access the underlying ozw-admin application running -in this add-on. This allows you to view, configure and control your Z-Wave -network and its devices. - -### Accessing the ozw-admin application via Ingress - -You can access the built-in ozw-admin application directly via Home Assistant -Ingress. Click on the "OPEN WEBUI" button to access it. - -If it does not auto connect to your Z-Wave network automatically: -Click on the "Open" button in the menu bar of the application and click on -the start button in the **"Remote OZWDaemon"** section. - -If you need to access the application more often, it can be added to the -Home Assistant sidebar by toggling the "Show in sidebar" switch on the -add-on page. - -### Accessing the ozw-admin application via VNC - -You can access the built-in ozw-admin application via a VNC viewer. - -Please note, you can access the same interface using the "OPEN WEBUI" button, -described above. - -To enable it: - -- Set a port number for VNC in the "Network" configuration section of the - add-on and hit "SAVE". Advised is to use port 5900, but any other port above - 5900 works as well. -- Restart the add-on. - -To access it, you need a [VNC Viewer][vnc-viewer] application. If you are using -macOS, you are in luck, since VNC is built-in. Open the spotlight search and -enter the VNC service URL. - -The VNC service URL looks like [vnc://homeassistant.local:5900](vnc-service-url). -Adjust port and possibly hostname if you've changed it in Home Assistant host system -settings. - -### Connecting remotely using a local ozw-admin application - -Alternatively, the ozw-admin application can be downloaded and installed on a -remote machine, like your desktop computer. To connect your remote machine: - -- Set a port number for the ozw-admin in the "Network" configuration section of - the add-on and hit "SAVE". Advised is to use port 1983, as this is the default. -- Restart the add-on. - -To access your Z-Wave network with the ozw-admin, you need to first download the ozw-admin application. The latest -version can be found here: - - - -After you've installed and started the ozw-admin application, click "Open" -and set the remote host and port in the "Remote OZWDaemon" section. -For example, host: `homeassistant.local`, with port `1983` in the second field. - -Next, click on "Start" to connect. - -## Known issues and limitations - -- Your hardware needs to be compatible with OpenZWave library - -## Support - -Got questions? - -You have several options to get them answered: - -- The [Home Assistant Discord Chat Server][discord]. -- The Home Assistant [Community Forum][forum]. -- Join the [Reddit subreddit][reddit] in [/r/homeassistant][reddit] - -In case you've found a bug, please [open an issue on our GitHub][issue]. - -[discord]: https://discord.gg/c5DvZ4e -[forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues -[reddit]: https://reddit.com/r/homeassistant -[vnc-service-url]: vnc://homeassistant.local:5900 -[vnc-viewer]: https://bintray.com/tigervnc/stable/tigervnc/ diff --git a/zwave/Dockerfile b/zwave/Dockerfile deleted file mode 100644 index 5052a1f3015..00000000000 --- a/zwave/Dockerfile +++ /dev/null @@ -1,110 +0,0 @@ -ARG BUILD_FROM -FROM ${BUILD_FROM} - -ENV QT_ASSUME_STDERR_HAS_CONSOLE=1 - -ARG OZW_VERSION -ARG QTMQTT_VERSION -ARG QTOZW_VERSION -ARG QTOZWADMIN_VERSION -ARG QTWEBSOCKETS_VERSION -ARG NOVNC_VERSION -ARG WEBSOCKIFY_VERSION - -# Install QT Open Z-Wave -WORKDIR /usr/src -RUN \ - apk add --no-cache \ - eudev-libs \ - fontconfig \ - mosquitto \ - mosquitto-clients \ - openssl \ - pwgen \ - qt5-qtbase \ - qt5-qtremoteobjects \ - qt5-qtserialport \ - qt5-qtsvg \ - rapidjson \ - ttf-freefont \ - python3 \ - py3-numpy \ - net-tools \ - && apk add --no-cache --virtual .build-dependencies \ - binutils \ - build-base \ - cmake \ - coreutils \ - curl-dev \ - eudev-dev \ - git \ - openssl-dev \ - qt5-qtbase-dev \ - qt5-qtremoteobjects-dev \ - qt5-qtserialport-dev \ - qt5-qtsvg-dev \ - rapidjson-dev \ - && apk add --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/v3.12/main \ - libunwind \ - libunwind-dev \ - \ - && git clone --depth 1 -b \ - ${QTWEBSOCKETS_VERSION} https://github.com/qt/qtwebsockets /usr/src/qtwebsockets \ - && cd /usr/src/qtwebsockets \ - && /usr/lib/qt5/bin/qmake QT_BUILD_PARTS="libs tools" \ - && make -j $(( $(nproc) + 1 )) \ - && make install \ - \ - && git clone --depth 1 -b \ - ${QTMQTT_VERSION} https://github.com/qt/qtmqtt /usr/src/qtmqtt \ - && cd /usr/src/qtmqtt \ - && /usr/lib/qt5/bin/qmake CONFIG+=release QT_BUILD_PARTS="libs tools" \ - && make -j $(( $(nproc) + 1 )) \ - && make install \ - \ - && git clone \ - https://github.com/OpenZWave/open-zwave /usr/src/ozw \ - && cd /usr/src/ozw \ - && git checkout ${OZW_VERSION} \ - && make -j $(( $(nproc) + 1 )) \ - && make install \ - \ - && git clone \ - https://github.com/OpenZWave/qt-openzwave /usr/src/qtozw \ - && cd /usr/src/qtozw \ - && git checkout ${QTOZW_VERSION} \ - && /usr/lib/qt5/bin/qmake -r CONFIG+=release \ - && make -j $(( $(nproc) + 1 )) \ - && make install \ - \ - && git clone \ - https://github.com/OpenZWave/ozw-admin.git /usr/src/ozw-admin \ - && cd /usr/src/ozw-admin \ - && git checkout ${QTOZWADMIN_VERSION} \ - && /usr/lib/qt5/bin/qmake -r CONFIG+=release \ - && make -j $(( $(nproc) + 1 )) \ - && make install \ - \ - && git clone --depth 1 -b \ - v${NOVNC_VERSION} https://github.com/novnc/noVNC \ - && cd noVNC \ - && mkdir -p /usr/share/novnc \ - && rm -rf .git utils \ - && cp -rf ./* /usr/share/novnc/ \ - \ - && git clone --depth 1 -b \ - v${WEBSOCKIFY_VERSION} https://github.com/novnc/websockify \ - && cd websockify \ - && python3 setup.py build \ - && python3 setup.py install --prefix=/usr \ - \ - && mkdir -p /usr/share/OpenZWave \ - && mv /usr/share/qt5/qt-openzwavedatabase.rcc /usr/share/OpenZWave/ \ - \ - && apk del --no-cache \ - .build-dependencies \ - libunwind-dev \ - && rm -rf /usr/src/* - -WORKDIR / -COPY rootfs / diff --git a/zwave/README.md b/zwave/README.md deleted file mode 100644 index 22a78173cda..00000000000 --- a/zwave/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Home Assistant Add-on: OpenZWave - -Allow Home Assistant to talk to a Z-Wave Network via a USB Controller. - -![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield] - - -[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg -[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg -[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg -[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg -[i386-shield]: https://img.shields.io/badge/i386-yes-green.svg diff --git a/zwave/build.json b/zwave/build.json deleted file mode 100644 index f6e880813a3..00000000000 --- a/zwave/build.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "build_from": { - "amd64": "homeassistant/amd64-base:3.11", - "i386": "homeassistant/i386-base:3.11", - "armhf": "homeassistant/armhf-base:3.11", - "armv7": "homeassistant/armv7-base:3.11", - "aarch64": "homeassistant/aarch64-base:3.11" - }, - "args": { - "OZW_VERSION": "ee90c896c137b3a473232565c45a51d70c41c431", - "QTOZW_VERSION": "7ebd43e246e97851ad20f2b1bb9c62bfd6a4a6ef", - "QTOZWADMIN_VERSION": "f68b43ec162f6eb59173710e00b1f1aa192ce373", - "QTMQTT_VERSION": "5.12.8", - "QTWEBSOCKETS_VERSION": "5.12.8", - "NOVNC_VERSION": "1.2.0", - "WEBSOCKIFY_VERSION": "0.9.0" - } -} diff --git a/zwave/config.json b/zwave/config.json deleted file mode 100644 index 1a0b9fba604..00000000000 --- a/zwave/config.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "OpenZWave", - "version": "0.9.1", - "slug": "zwave", - "description": "Control a ZWave network with Home Assistant", - "arch": ["amd64", "i386", "armhf", "armv7", "aarch64"], - "url": "https://github.com/home-assistant/hassio-addons/tree/master/zwave", - "ingress": true, - "ingress_entry": "vnc_lite.html", - "panel_icon": "mdi:z-wave", - "panel_title": "OpenZWave", - "startup": "services", - "init": false, - "stage": "experimental", - "homeassistant": "0.110.0.dev", - "ports": { - "1983/tcp": null, - "5900/tcp": null - }, - "ports_description": { - "1983/tcp": "ozw-admin port", - "5900/tcp": "VNC port" - }, - "services": ["mqtt:want"], - "discovery": ["ozw"], - "options": { - "device": null, - "network_key": "" - }, - "schema": { - "device": "device(subsystem=tty)", - "network_key": "password", - "instance": "int(1,)?" - }, - "image": "homeassistant/{arch}-addon-zwave" -} diff --git a/zwave/icon.png b/zwave/icon.png deleted file mode 100644 index 65dfc13893e..00000000000 Binary files a/zwave/icon.png and /dev/null differ diff --git a/zwave/logo.png b/zwave/logo.png deleted file mode 100644 index 6f55d126047..00000000000 Binary files a/zwave/logo.png and /dev/null differ diff --git a/zwave/rootfs/etc/cont-finish.d/mqtt.sh b/zwave/rootfs/etc/cont-finish.d/mqtt.sh deleted file mode 100644 index 2c67b4bbb43..00000000000 --- a/zwave/rootfs/etc/cont-finish.d/mqtt.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Ensure upstream MQTT server has the correct OZW status retained on shutdown. -# ============================================================================== -# shellcheck disable=SC1091 -source /usr/lib/mqtt_helper.sh - -declare host -declare password -declare port -declare username - -if bashio::services.available "mqtt"; then - bashio::log.info "Ensure upstream MQTT server has the correct OZW status" - host=$(bashio::services "mqtt" "host") - password=$(bashio::services "mqtt" "password") - port=$(bashio::services "mqtt" "port") - username=$(bashio::services "mqtt" "username") - - mqtt::ensure_ozw_offline_status \ - "${host}" "${port}" "${username}" "${password}" -fi diff --git a/zwave/rootfs/etc/cont-init.d/auth.sh b/zwave/rootfs/etc/cont-init.d/auth.sh deleted file mode 100644 index 110917f3777..00000000000 --- a/zwave/rootfs/etc/cont-init.d/auth.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Setup auth data -# ============================================================================== -declare homeassistant_pw -declare ozw_pw - -AUTH_FILE=/data/auth.db - -if bashio::fs.file_exists ${AUTH_FILE}; then - bashio::log.info "Auth database exists" - bashio::exit.ok -fi - -homeassistant_pw="$(pwgen 64 1)" -ozw_pw="$(pwgen 64 1)" - -bashio::log.info "Setup mqtt auth db" - -( - echo "ozw:${ozw_pw}" - echo "homeassistant:${homeassistant_pw}" -) > "${AUTH_FILE}" - -# Encrypt data -mosquitto_passwd -U ${AUTH_FILE} - -config=$(bashio::var.json \ - ozw_password "${ozw_pw}" \ - homeassistant_password "${homeassistant_pw}" \ -) - -echo "$config" > /data/auth.json diff --git a/zwave/rootfs/etc/cont-init.d/mqtt.sh b/zwave/rootfs/etc/cont-init.d/mqtt.sh deleted file mode 100644 index 356a670de3e..00000000000 --- a/zwave/rootfs/etc/cont-init.d/mqtt.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Setup MQTT settings -# ============================================================================== -# shellcheck disable=SC1091 -source /usr/lib/mqtt_helper.sh - -declare host -declare password -declare port -declare username - -if ! bashio::services.available "mqtt"; then - bashio::log.info "No internal MqTT service found" -else - host=$(bashio::services "mqtt" "host") - password=$(bashio::services "mqtt" "password") - port=$(bashio::services "mqtt" "port") - username=$(bashio::services "mqtt" "username") - - ( - echo "connection main-mqtt" - echo "address ${host}:${port}" - echo "remote_clientid zwave" - echo "local_clientid zwave" - echo "cleansession true" - echo "notifications true" - echo "try_private true" - ) >> /etc/mosquitto.conf - - # Need auth? - if bashio::var.has_value "${username}" && bashio::var.has_value "${password}"; then - ( - echo "username ${username}" - echo "password ${password}" - ) >> /etc/mosquitto.conf - fi - - ( - echo "topic OpenZWave/# out" - echo "topic # IN OpenZWave/" - ) >> /etc/mosquitto.conf - - # Ensure upstream MQTT server has the right OZW status - # Workaround for an incorrect retained OZW status in MQTT - # In this case, the LWT is not relayed to the upstream MQTT server. - # https://github.com/home-assistant/hassio-addons/issues/1462 - mqtt::ensure_ozw_offline_status \ - "${host}" "${port}" "${username}" "${password}" - - - bashio::log.info "Connected to internal MQTT service" -fi diff --git a/zwave/rootfs/etc/cont-init.d/network_key.sh b/zwave/rootfs/etc/cont-init.d/network_key.sh deleted file mode 100644 index 8e945b3df26..00000000000 --- a/zwave/rootfs/etc/cont-init.d/network_key.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Check to see if example network key from documentation is used -# ============================================================================== -readonly DOCS_EXAMPLE_KEY="0x2e, 0xcc, 0xab, 0x1c, 0xa3, 0x7f, 0x0e, 0xb5, 0x70, 0x71, 0x2d, 0x98, 0x25, 0x43, 0xee, 0x0c" - -if [[ "${DOCS_EXAMPLE_KEY}" == "$(bashio::config 'network_key')" ]]; then - bashio::log.fatal - bashio::log.fatal 'The add-on detected that the Z-Wave network key used' - bashio::log.fatal 'is from the documented example.' - bashio::log.fatal - bashio::log.fatal 'Using this key is insecure, because it is publicly' - bashio::log.fatal 'listed in the documentation.' - bashio::log.fatal - bashio::log.fatal 'Please check the add-on documentation on how to' - bashio::log.fatal 'create your own, secret, "network_key" and replace' - bashio::log.fatal 'the one you have configured.' - bashio::log.fatal - bashio::log.fatal 'Click on the "Documentation" tab in the OpenZWave' - bashio::log.fatal 'add-on panel for more information.' - bashio::log.fatal - bashio::exit.nok -fi diff --git a/zwave/rootfs/etc/cont-init.d/novnc.sh b/zwave/rootfs/etc/cont-init.d/novnc.sh deleted file mode 100644 index bc2fcb7f235..00000000000 --- a/zwave/rootfs/etc/cont-init.d/novnc.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Setup noVNC -# ============================================================================== -declare ingress_entry -ingress_entry=$(bashio::addon.ingress_entry) -sed -i "s#websockify#${ingress_entry#?}/websockify#g" /usr/share/novnc/vnc_lite.html diff --git a/zwave/rootfs/etc/cont-init.d/structure.sh b/zwave/rootfs/etc/cont-init.d/structure.sh deleted file mode 100644 index 0f1a09dd629..00000000000 --- a/zwave/rootfs/etc/cont-init.d/structure.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Setup folder structure -# ============================================================================== -mkdir -p /data/ozw/config diff --git a/zwave/rootfs/etc/mosquitto.conf b/zwave/rootfs/etc/mosquitto.conf deleted file mode 100644 index a6d7b688489..00000000000 --- a/zwave/rootfs/etc/mosquitto.conf +++ /dev/null @@ -1,20 +0,0 @@ -## -# defaults -listener 1883 -user root - -## -# logging -log_dest stdout - -## -# datastore -persistence true -persistence_location /data/ - -## -# auth -allow_anonymous false -password_file /data/auth.db - -# Dynamic config diff --git a/zwave/rootfs/etc/services.d/mosquitto/finish b/zwave/rootfs/etc/services.d/mosquitto/finish deleted file mode 100644 index 4c235122526..00000000000 --- a/zwave/rootfs/etc/services.d/mosquitto/finish +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/execlineb -S1 -# ============================================================================== -# Take down the S6 supervision tree when mosquitto fails -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } - -s6-svscanctl -t /var/run/s6/services diff --git a/zwave/rootfs/etc/services.d/mosquitto/run b/zwave/rootfs/etc/services.d/mosquitto/run deleted file mode 100644 index d4e8fbee5f3..00000000000 --- a/zwave/rootfs/etc/services.d/mosquitto/run +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Start mosquitto service for communication -# ============================================================================== -bashio::log.info "Starting internal MQTT broker..." - -exec mosquitto -c /etc/mosquitto.conf diff --git a/zwave/rootfs/etc/services.d/ozwadmin/finish b/zwave/rootfs/etc/services.d/ozwadmin/finish deleted file mode 100644 index 698a9da14a6..00000000000 --- a/zwave/rootfs/etc/services.d/ozwadmin/finish +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/execlineb -S1 -# ============================================================================== -# Take down the S6 supervision tree when ozw-admin fails -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } - -s6-svscanctl -t /var/run/s6/services diff --git a/zwave/rootfs/etc/services.d/ozwadmin/run b/zwave/rootfs/etc/services.d/ozwadmin/run deleted file mode 100644 index bba39be4554..00000000000 --- a/zwave/rootfs/etc/services.d/ozwadmin/run +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Start ozw-admin -# ============================================================================== -OZW_CONFIG=/data/ozw/config - -# Wait until ozw is up and running -bashio::net.wait_for 1983 -bashio::log.info "Starting ozw-admin..." - -cd /data/ozw || bashio::exit.nok "Could not change to OZW working directory" -exec ozwadmin \ - -platform vnc:size=1024x768:port=5900 \ - —-host "localhost:1983" \ - --config-dir "${OZW_CONFIG}" \ - --user-dir "${OZW_CONFIG}" diff --git a/zwave/rootfs/etc/services.d/websockify/finish b/zwave/rootfs/etc/services.d/websockify/finish deleted file mode 100644 index 585d7783519..00000000000 --- a/zwave/rootfs/etc/services.d/websockify/finish +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/execlineb -S1 -# ============================================================================== -# Take down the S6 supervision tree when websockify fails -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } - -s6-svscanctl -t /var/run/s6/services diff --git a/zwave/rootfs/etc/services.d/websockify/run b/zwave/rootfs/etc/services.d/websockify/run deleted file mode 100644 index 1975096fd02..00000000000 --- a/zwave/rootfs/etc/services.d/websockify/run +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Start ozw-admin -# ============================================================================== - -# Wait until ozwadmin is up and running -bashio::net.wait_for 5900 -bashio::log.info "Starting websockify..." - -exec websockify --web /usr/share/novnc/ 8099 127.0.0.1:5900 diff --git a/zwave/rootfs/etc/services.d/zwave/discovery b/zwave/rootfs/etc/services.d/zwave/discovery deleted file mode 100755 index f159a8dc772..00000000000 --- a/zwave/rootfs/etc/services.d/zwave/discovery +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Send ozw discovery information to Home Assistant -# ============================================================================== -declare ha_config - -# Prepare discovery payload -ha_config=$(\ - bashio::var.json \ - host "$(hostname)" \ - port "^1883" \ - username "homeassistant" \ - password "$(bashio::jq /data/auth.json '.homeassistant_password')" \ -) - -if bashio::discovery "ozw" "${ha_config}" > /dev/null; then - bashio::log.info "Successfully send discovery information to Home Assistant." -else - bashio::log.error "Discovery message to Home Assistant failed!" -fi diff --git a/zwave/rootfs/etc/services.d/zwave/finish b/zwave/rootfs/etc/services.d/zwave/finish deleted file mode 100644 index 20a8bb8a6d5..00000000000 --- a/zwave/rootfs/etc/services.d/zwave/finish +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/execlineb -S1 -# ============================================================================== -# Take down the S6 supervision tree when OpenZWave fails -# ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } - -s6-svscanctl -t /var/run/s6/services diff --git a/zwave/rootfs/etc/services.d/zwave/run b/zwave/rootfs/etc/services.d/zwave/run deleted file mode 100644 index 2d0a551b7f8..00000000000 --- a/zwave/rootfs/etc/services.d/zwave/run +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Start OpenZWave service for zwave radio -# ============================================================================== -# shellcheck disable=SC1091 -source /usr/lib/mqtt_helper.sh - -export MQTT_PASSWORD -export OZW_NETWORK_KEY - -MQTT_PASSWORD="$(bashio::jq /data/auth.json '.ozw_password')" -OZW_CONFIG=/data/ozw/config -OZW_DEVICE=$(bashio::config 'device') -OZW_INSTANCE=1 -OZW_NETWORK_KEY=$(bashio::config 'network_key') - -# Set custom instance ID if configured -if bashio::config.has_value 'instance'; then - OZW_INSTANCE=$(bashio::config 'instance') -fi - -# Wait until mosqitto is up and running -bashio::log.info "Starting OpenZWave..." -bashio::net.wait_for 1883 - -# Ensure local MQTT server has the right OZW status -# Workaround for an incorrect retained OZW status in MQTT -# https://github.com/home-assistant/hassio-addons/issues/1462 -mqtt::ensure_ozw_offline_status \ - 127.0.0.1 1883 ozw "${MQTT_PASSWORD}" "${OZW_INSTANCE}" - -# Send out discovery information to Home Assistant -./discovery & - -# Run daemon -cd /data/ozw || bashio::exit.nok "Could not change to OZW working directory" -exec ozwdaemon \ - -s "${OZW_DEVICE}" \ - --config-dir "${OZW_CONFIG}" \ - --user-dir "${OZW_CONFIG}" \ - --mqtt-server 127.0.0.1 \ - --mqtt-port 1883 \ - --mqtt-username ozw \ - --mqtt-instance "${OZW_INSTANCE}" \ - --stop-on-failure diff --git a/zwave/rootfs/usr/lib/mqtt_helper.sh b/zwave/rootfs/usr/lib/mqtt_helper.sh deleted file mode 100644 index 7c849b51584..00000000000 --- a/zwave/rootfs/usr/lib/mqtt_helper.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# MQTT helpers for the zwave add-on. -# ============================================================================== - -# ------------------------------------------------------------------------------ -# Ensure upstream MQTT server has the correct OZW status retained on shutdown. -# -# Arguments: -# $1 MQTT Server host -# $2 MQTT Server port -# $3 MQTT Server username -# $4 MQTT Server password -# $5 OZW Instance ID (optional) -# ------------------------------------------------------------------------------ -function mqtt::ensure_ozw_offline_status() { - local host=${1} - local port=${2} - local username=${3} - local password=${4} - local ozw_instance=${5:-} - local ozw_status - - bashio::log.trace "${FUNCNAME[0]}:" "$@" - - if ! bashio::var.has_value "${ozw_instance}"; then - ozw_instance=1 - if bashio::config.has_value 'instance'; then - ozw_instance=$(bashio::config 'instance') - fi - fi - - ozw_status=$(\ - mosquitto_sub \ - --host "${host}" \ - --port "${port}" \ - --username "${username}" \ - --pw "${password}" \ - -C 1 \ - -W 3 \ - --retained-only \ - --topic "OpenZWave/${ozw_instance}/status/" \ - ) - if bashio::var.has_value "${ozw_status}" \ - && [[ $(bashio::jq "${ozw_status}" ".Status") != "Offline" ]]; - then - mosquitto_pub \ - --host "${host}" \ - --port "${port}" \ - --username "${username}" \ - --pw "${password}" \ - --retain \ - --topic "OpenZWave/${ozw_instance}/status/" \ - --message "$(bashio::var.json "Status" "Offline")" - fi -} diff --git a/zwave_js/CHANGELOG.md b/zwave_js/CHANGELOG.md index 2971dc837bb..c08c825e9ad 100644 --- a/zwave_js/CHANGELOG.md +++ b/zwave_js/CHANGELOG.md @@ -1,108 +1,1273 @@ # Changelog -# 0.1.32 +## 0.10.0 + +### Features + +- Z-Wave JS Server: Forward driver ready event +- Z-Wave JS Server: Support controller.cancelSecureBootstrapS2 +- Z-Wave JS Server: Support zwave-js v14 +- Z-Wave JS: Allow specifying RF region for OTA firmware updates if the region is unknown or cannot be queried +- Z-Wave JS: Add tryUnzipFirmwareFile utility to support zipped OTA firmware files + +### Bug fixes + +- Z-Wave JS Server: Fix stringify Uint8Arrays like Buffers +- Z-Wave JS: Fixed firmware updates fail to start on some devices with error "invalid hardware version" +- Z-Wave JS: Fixed another issue where some CC API methods would incorrectly fail validation of their arguments, causing the node interview to fail +- Z-Wave JS: Fixed an issue that prevented the nvmedit CI utility from starting +- Z-Wave JS: Fixed an issue where some CC API methods would incorrectly fail validation of their arguments +- Z-Wave JS: Fixed an issue where CC classes would have a different name when zwave-js was loaded as CommonJS, changing how those CCs were handled +- Z-Wave JS: Fix parsing of some older 500 series NVM formats +- Z-Wave JS: Fixed an issue where mock-server would not start due to an incorrect module format +- Z-Wave JS: Fixed an issue where the auto-generated argument validation for CC API methods would not work correctly in some cases when zwave-js was bundled +- Z-Wave JS: Fixed an issue where encoding a buffer as an ASCII string would throw an error on Node.js builds without full ICU +- Z-Wave JS: Parse negative setback state consistently +- Z-Wave JS: Ignore LR nodes when computing neighbor discovery timeout +- Z-Wave JS: Automatically fall back to Europe when setting region to Default (EU) + +### Config file changes + +- Preserve all endpoints for Fibaro FGFS101, FW 26.26 +- Preserve all endpoints for Fibaro FGFS101, FW 25.25 +- Updates to AEON Labs Minimote +- Auto-assign Lifeline for Trane XL624 +- Disable Supervision for Everspring SP817 Motion Sensor +- Add wakeup instructions for ZSE43 +- Add wakeup instructions for ZSE42 +- Add wakeup instructions for ZSE41 +- Add Zooz ZSE70 800LR +- Add new device config for Philips DDL240X-15HZW lock +- Add Z-Wave.me Z-Station +- Add HomeSys HomeMech-2001/2 +- Ignore setpoint range for Ecolink TBZ500 +- Add Aeotec TriSensor 8 +- Disable Supervision for Everspring SE813 + +### Detailed changelogs + +- [Z-Wave JS Server 1.40.3](https://github.com/zwave-js/zwave-js-server/releases/tag/1.40.3) +- [Z-Wave JS Server 1.40.2](https://github.com/zwave-js/zwave-js-server/releases/tag/1.40.2) +- [Z-Wave JS Server 1.40.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.40.0) +- [Z-Wave JS 14.3.8](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.8) +- [Z-Wave JS 14.3.7](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.7) +- [Z-Wave JS 14.3.6](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.6) +- [Z-Wave JS 14.3.5](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.5) +- [Z-Wave JS 14.3.4](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.4) +- [Z-Wave JS 14.3.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.3) +- [Z-Wave JS 14.3.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.2) +- [Z-Wave JS 14.3.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.3.1) +- [Z-Wave JS 14.2.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.2.0) +- [Z-Wave JS 14.1.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.1.0) +- [Z-Wave JS 14.0.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v14.0.0) +- [Z-Wave JS 13.10.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.10.3) -- Bump Z-Wave JS to 8.0.5 +## 0.9.0 + +### Features + +- Z-Wave JS: mock-server now supports putting the simulated controller into add and remove mode +- Z-Wave JS Server: Support get_raw_config_parameter_value +- Z-Wave JS Server: Support all signatures of node.manuallyIdleNotificationValue + +### Bug fixes + +- Z-Wave JS: Fixed an issue where preferred scales were not being found when set as a string +- Z-Wave JS: Correct unit of Meter CC values +- Z-Wave JS: Bootloader mode is now detected even when short chunks of data are received +- Z-Wave JS: Corrected the wording of idle/busy queue logging + +### Config file changes + +- Add Heatit Z-TEMP3 +- Add new parameters 17 and 18 for HeatIt TF016_TF021 FW 1.92 +- Disable Supervision for Heatit TF021 +- Add ZVIDAR WB04V Smartwings Day Night Shades +- Add ZVIDAR WM25L Smartwings Smart Motor +- Add ZVIDAR ZW881 Multi-Protocol Gateway +- Add include, exclude, and wakeup instructions for VCZ1 +- Add new Product ID to Namron 16A Switch +- Add Minoston MP24Z 800LR Outdoor Smart Plug - 2 Outlet +- Disable Supervision for Everspring SE813 + +### Detailed changelogs + +- [Z-Wave JS Server 1.39.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.39.0) +- [Z-Wave JS 13.10.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.10.3) +- [Z-Wave JS 13.10.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.10.2) +- [Z-Wave JS 13.10.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.10.1) +- [Z-Wave JS 13.10.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.10.0) +- [Z-Wave JS 13.9.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.9.1) + +## 0.8.1 + +Rename Z-Wave watchdog option to avoid confusion with add-on watchdog. + +## 0.8.0 + +### Features + +- Add-on: Add `disable_watchdog` configuration option. When enabled, the driver will not enable the hardware watchdog of the Z-Wave controller. This is an advanced configuration option that should not be adjusted in most cases and is therefore hidden from the default view. +- Z-Wave JS: Multiple parallel firmware updates are now supported + +### Bug fixes + +- Z-Wave JS: Fixed an issue where open/close for some covers was inverted + +### Config file changes + +- Update Z-Wave SDK warnings to mention recommended versions +- Update Zooz device labels +- Add fingerprint to Aeotec ZWA024 +- Correct max. value of SKU parameters for Kwikset locks +- Add fingerprint to Remotec ZXT-800 +- Add incompatibility warning to UZB1 +- Override Central Scene CC version for Springs Window Fashions VCZ1 +- Add manual and reset metadata for Danfoss LC-13 + +### Detailed changelogs + +- [Z-Wave JS 13.4.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.4.0) +- [Z-Wave JS 13.5.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.5.0) +- [Z-Wave JS 13.6.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.6.0) +- [Z-Wave JS 13.7.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.7.0) +- [Z-Wave JS 13.8.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.8.0) +- [Z-Wave JS 13.9.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.9.0) + +## 0.7.2 + +### Bug fixes + +- Z-Wave JS: Fixed the identification of the primary controller role on some older controllers +- Z-Wave JS: Fixed an issue where passing a custom log transport to updateOptions would cause a call stack overflow +- Z-Wave JS: Implement deserialization for more WindowCoveringCC commands to be used in mocks + +### Config file changes + +- Add Philio Technology Smart Keypad +- Add LED indication parameter for Inovelli NZW31 dimmer + +### Detailed changelogs + +- [Z-Wave JS 13.3.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.3.1) + +## 0.7.1 + +### Bug fixes + +- Add-on: Fix the soft reset driver option that was moved in driver v.13. + +## 0.7.0 + +### Features + +- Z-Wave JS: Add support for EU Long Range +- Z-Wave JS: Support learn mode to become a secondary controller +- Z-Wave JS: Add method to query supported RF regions and their info +- Z-Wave JS: Support Firmware Update Meta Data CC v8 +- Z-Wave JS: Implement 32-bit addressed NVM operations +- Z-Wave JS: Add methods to reset SPAN of one or all nodes +- Z-Wave JS: Add method to enumerate all device classes +- Z-Wave JS: Update list of manufacturers and existing CCs +- Z-Wave JS: Add inclusion state changed event +- Z-Wave JS: Add support for new notifications +- Z-Wave JS: Bump version of Association CC and Multi Channel Association CC +- Z-Wave JS: Add link reliability check feature +- Z-Wave JS: Enable hardware watchdog on 700/800 series controllers +- Z-Wave JS: Add method to query supported RF regions +- Z-Wave JS: Add notification variable for Door/Window tilt state + +### Bug fixes + +- Z-Wave JS: Fix missing values in endpoint dump +- Z-Wave JS: Preserve granted security classes of provisioning entries when switching protocols +- Z-Wave JS: Version of Humidity Control Mode CC is 1, not 2 +- Z-Wave JS: Abort S2 bootstrapping when KEXSetEcho has reserved bits set +- Z-Wave JS: Fixed an issue causing non-implemented CCs to be dropped before applications could handle them +- Z-Wave JS: Fixed an issue causing all ZWLR multicast groups to be considered identical +- Z-Wave JS: Fixed a startup crash on Zniffers older than FW 2.55 +- Z-Wave JS: Fixed latency calculation in link reliability check, distinguish between latency and RTT +- Z-Wave JS: Fixed a regression that could cause incorrect units and missing sensor readings +- Z-Wave JS: Don't verify delivery of S2 frames in link reliability check +- Z-Wave JS: Reset aborted flags when starting link reliability or route health check +- Z-Wave JS: Supported CCs of endpoints are now reset during a re-interview +- Z-Wave JS: Basic CC is no longer automatically marked as supported if included in the list of securely supported commands +- Z-Wave JS: Set highest version also for Basic CC if Version CC is not supported +- Z-Wave JS: Fixed an issue where CC values could be returned for the controller node +- Z-Wave JS: Fixed a regression from v12.12.3 would result in Basic CC values being exposed unnecessarily for some devices +- Z-Wave JS: Fixed an issue where Basic CC values would be exposed unnecessarily for devices with a compat flag that maps Basic CC Set to a different CC +- Z-Wave JS: When responding to Version CC Get queries, Z-Wave JS's own version is now included as the Firmware 1 version +- Z-Wave JS: When receiving a notification with an unknown notification type, the created "unknown" value now correctly has metadata set +- Z-Wave JS: When receiving an idle notification, the values for unknown notification events are now also reset to idle +- Z-Wave JS: Auto-enable all supported Barrier Operator signaling subsystem during the interview +- Z-Wave JS: Fixed an issue where the watchdog feature could cause Z-Wave JS to stall after attempting controller recovery +- Z-Wave JS: Reset controller again when transmitting to a problematic node makes the controller become unresponsive again after automatic recovery +- Z-Wave JS: Node interviews are now aborted in more cases when node is determined to be dead +- Z-Wave JS: Expose Basic CC currentValue when certain compat flags are set +- Z-Wave JS: Fixed an issue where value metadata for unknown notification events with known notification types would only be created if the CC version was exactly 2 + +### Config file changes + +- Add new fingerprint for TZ45 thermostat +- Add alarm mapping for Schlage lock CKPD FE599 +- Add fingerprint for Climax Technology SDCO-1 +- Add Shelly Wave Pro 3 and Wave Pro Shutter +- Remove endpoint workaround for Zooz ZEN30, FW 3.20+ +- Add ZVIDAR ZW872 800 series Pi Module +- Add ZVIDAR ZW871 800 series USB Controller +- Rename Zvidar config file name Z-PI to Z-PI.json +- Update Zooz ZEN30 to latest revisions +- Support MCO Home MH-S412 parameters properly +- Add Ring Flood Freeze Sensor +- Override user code count for Yale ZW2 locks to expose admin code +- Add GDZW7-ECO Ecolink 700 Series Garage Door Controller +- Correct label for Remote 3-Way Switch parameter on Zooz ZEN32 +- Add UltraPro 700 Series Z-Wave In-Wall Smart Dimmer +- Add Yale Assure 2 Biometric Deadbolt locks +- Add iDevices In-Wall Smart Dimmer +- Support Comet parameters properly +- Update label of Nortek GD00Z-6, -7, -8 +- Disable Supervision for Zooz ZSE11 +- Clarify parameters and units for Everspring AN158 +- Force-add support for Multilevel Switch CC to FGRM-222, remove Binary Switch CC +- Add ZVIDAR Z-PI 800 Series PI Module + +### Detailed changelogs + +- [Z-Wave JS 13.3.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.3.0) +- [Z-Wave JS 13.2.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.2.0) +- [Z-Wave JS 13.1.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.1.0) +- [Z-Wave JS 13.0.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.0.3) +- [Z-Wave JS 13.0.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.0.2) +- [Z-Wave JS 13.0.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.0.1) +- [Z-Wave JS 13.0.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v13.0.0) +- [Z-Wave JS 12.13.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.13.0) +- [Z-Wave JS 12.12.5](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.12.5) +- [Z-Wave JS 12.12.4](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.12.4) +- [Z-Wave JS 12.12.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.12.3) +- [Z-Wave JS 12.12.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.12.2) +- [Z-Wave JS 12.12.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.12.1) +- [Z-Wave JS 12.12.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.12.0) + +## 0.6.2 + +### Bug fixes + +- Z-Wave JS: Fixed a regression causing commands to sleeping nodes to block communication with other nodes + +### Detailed changelogs + +- [Z-Wave JS 12.11.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.11.2) + +## 0.6.1 + +### Bug fixes + +- Z-Wave JS: When attempting communication with a node that's considered dead, the command is now sent immediately instead of pinging first +- Z-Wave JS: Fixed prioritization of queued transactions once a node wakes up + +### Config file changes + +- Remove endpoint workaround for Zooz ZEN30 800LR +- Encode CCs using target's CC version for TKB Home TZ67 + +### Detailed changelogs + +- [Z-Wave JS 12.11.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.11.1) + +## 0.6.0 + +### Features + +- Z-Wave JS: Map more Basic CC values to more useful command classes +- Z-Wave JS: Automatically prefer ZWLR-capable RF regions over their non-ZWLR counterparts +- Z-Wave JS: Add driver option to configure vendor-specific constants Z-Wave JS uses to reply to requests from other nodes, including manufacturer ID, product type/ID and hardware version + +### Bug fixes + +- Z-Wave JS: NVM restore now works around an issue that affects some 800 series controllers +- Z-Wave JS: More gracefully handle scenario where inclusion couldn't be completed due to missing security keys +- Z-Wave JS: Fixed an issue where excluded ZWLR nodes were not removed from the list of nodes until restart +- Z-Wave JS: Always query Basic CC version as part of the interview +- Z-Wave JS: Add support for Z-Wave Long Range devices in NVM backup and restore +- Z-Wave JS: Abort S2 bootstrapping when CSA is requested (not supported in Z-Wave JS) +- Z-Wave JS: Implement workaround to recover jammed controller by soft-resetting +- Z-Wave JS: Fixed a race condition that would cause a timeout error to be shown after an actually successful OTW update + +### Config file changes + +- Add HomeSeer PS100 presence sensor, fix broken links +- Fix value size for Fibaro FGWCEU-201, params 150/151 +- Disable Supervision for Heatit Z-Temp2, firmware 1.2.1 +- Use specific float encoding for Namron 4512757 +- Add fingerprint for Aeotec MultiSensor 7 +- Override CC versions for Wayne Dalton WDTC-20 +- Disable Supervision for Everspring EH403 +- Add parameter 117 to Shelly Wave Plug US and UK +- Add params 12, 20, 254 for Aeotec DSB09 +- Use HomeSeer template for LED Indicator (parameter 3) for all HomeSeer switches +- Add Fibaro FGR-224 Roller Shutter 4 +- Parameter update for Zooz Zen16 v2.0 and v2.10 +- Override Central Scene CC version for Springs Window Fashions BRZ +- Add fingerprint 0x0004:0xffff to "Yale YRD210" +- Correct config parameters for Minoston MP21ZD Dimmer Plug + +### Detailed changelogs + +- [Z-Wave JS 12.11.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.11.0) +- [Z-Wave JS 12.10.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.10.1) +- [Z-Wave JS 12.10.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.10.0) +- [Z-Wave JS 12.9.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.9.1) +- [Z-Wave JS 12.9.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.9.0) +- [Z-Wave JS 12.8.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.8.1) +- [Z-Wave JS 12.8.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.8.0) +- [Z-Wave JS 12.7.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.7.0) +- [Z-Wave JS 12.6.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.6.0) +- [Z-Wave JS 12.5.6](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.5.6) + +## 0.5.0 + +### Features + +- Z-Wave JS: Map more Basic CC values to more useful command classes +- Z-Wave JS: Add Z-Wave Long Range support +- Z-Wave JS Server: Add Z-Wave Long Range support +- Addon: Add support for collecting Z-Wave Long Range security keys + +### Bug fixes + +- Z-Wave JS: Fixed an issue that caused additional invalid values to be discovered +- Z-Wave JS: Fixed a crash that could happen in some cases during the Configuration CC interview +- Z-Wave JS: Fixed an issue where provisioning entries could disappear +- Z-Wave JS: Fixed an infinite loop during NVM migration which could happen in rare cases +- Z-Wave JS: Firmware updates on Z-Wave Long Range now utilize the larger frame size better +- Z-Wave JS: Fixed an issue with multicast setValue response +- Z-Wave JS: Disallow associating a node with itself and skip self-associations when rebuilding routes + +### Config file changes + +- Always map Basic CC to Binary Sensor CC for Aeotec ZW100 Multisensor 6 +- Fix versioning logic for parameter 26 of Zooz ZEN72 +- Add new Leviton 800 series devices +- Add UltraPro Z-Wave Plus In-Wall Toggle Switch, 700S +- Rename generic 700 series controller to include 800 series +- Add fingerprint and config parameters for UltraPro 700 Switch +- Add Zooz Zen37 800LR Wall Remote +- Added 11 Shelly Qubino Wave devices +- Add Heatit Leakage Water Stopper +- Add Ring Smoke/CO Listener +- Add ZVIDAR Z-TRV-V01 thermostatic valve +- Add Safe Grow NSG-AB-02 Z-Wave Plus Smart Outlet Plug +- Add a new productId and add parameters to 14297/ZW1002 outlet +- Remove Association Groups 2 & 3 from AEON Labs DSB09 +- Correct group 3 label for GE/Enbrighten 26931/ZW4006 +- Add new Fingerprint for Ring Contact sensor +- Preserve root endpoint in Vision ZL7432 +- Add new Product ID to Fibaro Smoke Detector +- Add Product ID for Benext Energy Switch FW1.6 +- Add fingerprint for Ring Glass Break Sensor EU +- Change MH9-CO2 Temperature Reporting Threshold step size to 0.1 +- Add new product ID to Fibaro FGS-213 +- Add units, improve descriptions for Everspring ST814 +- Label and parameter definitions for Sensative Drip 700 +- Override supported sensor scales for HELTUN HE-ZW-THERM-FL2 + +### Detailed changelogs + +- [Z-Wave JS Server 1.35.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.35.0) +- [Z-Wave JS 12.5.5](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.5.5) +- [Z-Wave JS 12.5.4](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.5.4) +- [Z-Wave JS 12.5.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.5.3) +- [Z-Wave JS 12.5.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.5.2) +- [Z-Wave JS 12.5.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.5.1) +- [Z-Wave JS 12.5.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.5.0) + +## 0.4.5 + +### Bug fixes + +- Z-Wave JS: NVM backups can now be restored onto 800 series controllers + +### Config file changes + +- Use Color Switch V2 for Inovelli LZW42 +- Correct Zooz ZEN1x timer config params + +### Detailed changelogs + +- [Z-Wave JS 12.4.4](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.4.4) + +## 0.4.4 + +### Bug fixes + +- Z-Wave JS: Reduce idle CPU load + +### Config file changes + +- Add 2nd product ID for Ring Panic Button Gen2 +- Disable Supervision for Alfred DB1 Digital Deadbolt Lock to work around battery drain issue +- Extend version range for Vesternet VES-ZW-DIM-001 + +### Detailed changelogs + +- [Z-Wave JS 12.4.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.4.3) +- [Z-Wave JS 12.4.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.4.2) + +## 0.4.3 + +### Features + +- Z-Wave JS Server: Enable server to listen on IPv6 interfaces + +### Bug fixes + +- Z-Wave JS: Handle more cases of unexpected Serial API restarts + +### Config file changes + +- Add wakeup instructions for Nexia ZSENS930 +- Correct parameter 5 size for Zooz ZEN34 + +### Detailed changelogs + +- [Z-Wave JS 12.4.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.4.1) +- [Z-Wave JS Server 1.34.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.34.0) + +## 0.4.2 + +### Features + +- Z-Wave JS: Expose rebuild routes progress as a controller property + +### Bug fixes + +- Z-Wave JS: On devices that should/must not support `Basic CC`, but use it for reporting, only the `currentValue` is now exposed. This allows applications to consider it a sensor, not an actor + +### Config file changes + +- Correct firmware version condition for Zooz ZSE40 v3.0 + +### Detailed changelogs + +- [Z-Wave JS 12.4.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.4.0) +- [Z-Wave JS 12.3.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.3.2) + +## 0.4.1 + +### Bug fixes + +- Z-Wave JS: Fixed an issue where the unresponsive controller recovery could do the wrong thing and block all outgoing communication. + +### Config file changes + +- Add missing units and firmware condition for Heatit Z-Temp2 +- Correct device label for Airzone Aidoo Control HVAC unit + +### Detailed changelogs + +- [Z-Wave JS 12.3.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.3.1) + +## 0.4.0 + +### Features + +- Add-On: Provide access to Z-Wave JS cache files for debugging in `/addon_configs/core_zwave_js/cache` +- Add-On: Add configuration option to log to file. When enabled, logs will be written to `/addon_configs/core_zwave_js` with the `.log` file extension + +## 0.3.0 + +### Features + +- Add-On: Add `disable_controller_recovery` configuration option. When enabled, the driver will not attempt to automatically recover from an unresponsive controller and will instead either let the controller recover on its own or wait for the user to restart the add-on to attempt recovery. This is an advanced configuration option that should not be adjusted in most cases and is therefore hidden from the default view. + +### Bug fixes + +- Z-Wave JS: Ensure the default Basic CC values are only exposed if they should be +- Z-Wave JS: Auto-remove failed SmartStart nodes when bootstrapping times out +- Z-Wave JS: Improve how unresponsive controllers are handled + +### Config file changes + +- Tweak Heatit Z-TRM6 options +- Add Ring Alarm Panic Button Gen2 +- Update fingerprints for Vesternet device + +### Detailed changelogs + +- [Z-Wave JS 12.3.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.3.0) + +## 0.2.1 + +### Config file changes + +- Treat Binary Switch Set and Thermostat Mode Set as reports for SRT321 HRT4-ZW +- Override supported Thermostat modes for Eurotronics Spirit TRV +- Correct firmware warnings for Zooz controllers +- Correct overridden thermostatMode metadata for ZME_FT +- Add MCOHome C521/C621 shutters, fix C321, make shutters consistent +- Correct product id for Fakro ZWS12 +- add PM-B400ZW-N +- Ensure kWh is written consistently in parameter units + +### Detailed changelogs + +- [Z-Wave JS 12.2.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.2.3) +- [Z-Wave JS 12.2.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.2.2) +- [Z-Wave JS 12.2.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.2.1) +- [Z-Wave JS Server 1.33.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.33.0) + +## 0.2.0 + +### Features + +- Add-on: Add `safe_mode` configuration option to put Z-Wave network in safe mode. This can be used help with troubleshooting network issues, such as being unable to start it, but will likely slow down your network and should therefore be used sparingly. This is an advanced configuration option that should not be adjusted in most cases and is therefore hidden from the default view. +- Add-on: Switch to [semantic versioning](https://semver.org/). With this change, major version changes to the addon will now reflect e.g. a major version release of Z-Wave JS or a significant change to the add-on structure. This should help users better understand the potential impact of an upgrade. + +### Bug fixes + +- Z-Wave JS: Includes several more fixes and workarounds for the problematic interaction between some controller firmware bugs and the automatic controller recovery introduced in the `v12` release + +### Config file changes + +- Add NEO Cool Cam Repeater +- Increase report timeout for Aeotec Multisensor 6 to 2s + +### Detailed changelogs + +- [Z-Wave JS 12.2.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.2.0) +- [Z-Wave JS Server 1.32.2](https://github.com/zwave-js/zwave-js-server/releases/tag/1.32.2) + +## 0.1.98 + +### Bug fixes + +- Z-Wave JS: Fixed an issue with multi-target firmware updates that prevented updates from being applied correctly + +### Config file changes + +Almost 1000 device configuration files have been reworked to be more consistent, mostly affecting device labels, parameter labels, descriptions and predefined options. After updating, you should expect to see several notifications for changed device configurations, prompting you to re-interview the affected nodes. Unless the device is mentioned below, there's no need to do this immediately. + +- Add parameter 26 to Inovelli VZW31-SN +- Always set time for Namron 16A thermostats as UTC +- Add Alloy (Zipato) devices +- Parameter 21 of Inovelli VZW31-SN is readonly +- Add Shelly Wave Shutter +- Add Eurotronic Comet Z (700 series) +- Add params 7, 18, 19 to Zooz ZEN71 FW 10.20 +- Add Qubino Shades Remote Controller +- Add fingerprint for new MH8-FC version, add new option for param 1 +- Add Hank HKZW-SO08 +- Add link to manual of Honeywell T6 Pro Thermostat + +### Detailed changelogs + +- [Z-Wave JS 12.1.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.1.0) +- [Z-Wave JS 12.1.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.1.1) + +## 0.1.97 + +### Bug fixes + +- Z-Wave JS: Fixed a crash that could happen while logging dropped sensor readings. +- Z-Wave JS: Change the default timeout to handle slow 500 series controllers. + +### Config file changes + +- Treat Basic Set as events for TKB TZ35S/D and TZ55S/D +- Add Zooz ZAC38 Range Extender +- Corrected the label of the notification event `0x0a` to be `Emergency Alarm` + +### Detailed changelogs + +- [Z-Wave JS 12.0.4](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.0.4) + +## 0.1.96 + +### Bug fixes + +- Add-on: Make `soft_reset` configuration option optional since, when required, it breaks add-on installations done through the `zwave_js` integration. + +## 0.1.95 + +### Bug fixes + +- Z-Wave JS: Fixes or works around multiple issues with 500 series controllers that could trigger the unresponsive controller detection in Z-Wave JS 12 in situations where it was not necessary, causing restart loops. + +### Bug fixes + +- [Z-Wave JS 12.0.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.0.3) + +## 0.1.94 + +### Features + +- Add-on: Add a `soft_reset` configuration option to choose how to handle soft-reset functionality for 500 series controllers. +- Add-on: Extend timeout from 3 seconds to 30 to give Z-Wave JS more time to commit things to disk. + +### Bug fixes + +- Z-Wave JS: The workaround from v12.0.0 for the 7.19.x SDK bug was not working correctly when the command that caused the controller to get stuck could be retried. This has now been fixed. +- Z-Wave JS: Ignore when a node reports Security S0/S2 CC to have version 0 (unsupported) although it is using that CC + +### Config file changes + +- Add Shelly to manufacturers +- Add Shelly Wave 1, Wave 2PM, update Wave 1PM association labels +- Add Sunricher SR-ZV2833PAC + +### Detailed changelog + +- [Z-Wave JS 12.0.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.0.1) +- [Z-Wave JS 12.0.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.0.2) + +## 0.1.93 + +### Bug fixes + +- Z-Wave JS Server: For users that have opted in to data collection in their Home Assistant Z-Wave configuration, a missing return caused the server to try to soft reset the controller during Home Assistant startup for Home Assiststant versions 2023.9.x or less. This has now been resolved. + +### Detailed changelog + +- [Z-Wave JS Server 1.32.1](https://github.com/zwave-js/zwave-js-server/releases/tag/1.32.1) + +## 0.1.92 + +### Bug fixes + +- Add-on: Revert change to stop rebuilding @serialport/bindings-cpp from source as the problem is fixed on some CPU platforms but not all + +## 0.1.91 + +### Breaking changes + +- Z-Wave JS: Firmware updates may no longer work properly in Home Assistant versions 2023.9.x and earlier due to a breaking change upstream that couldn't be made backward compatible, but will work once again starting in 2023.10.0. This breaking change ultimately improves firmware updates, as checking for updates no longer requires communication with the device, therefore reducing the risk of corrupting manufacturer information. This also means that updates for battery-powered devices can be detected without waking up the devices. + +### Features + +- Z-Wave JS: Unresponsive controllers are now detected and automatically restarted if possible. +- Z-Wave JS: Battery-powered devices are sent back to sleep after 250 ms with no command (down from 1000 ms). This should result in significant battery savings for devices that frequently wake up. +- Add-on: We no longer rebuild the @serialport/bindings-cpp package from source. + +### Bug fixes + +- Z-Wave JS: A bug in the 7.19.x SDK has surfaced where the controller gets stuck in the middle of a transmission. Previously, this would go unnoticed because the failed commands would cause the nodes to be marked dead until the controller finally recovered. Since v11.12.0, however, Z-Wave JS would consider the controller jammed and retry the last command indefinitely. This situation is now detected, and Z-Wave JS attempts to recover by soft resetting the controller when this happens. +- Z-Wave JS: Fixed an issue where supporting controllers would no longer be automatically restarted after failing to do so once. +- Z-Wave JS: Devices that send notifications from endpoints, like Aeotec Wallmote, are now properly supported. + +### Config file changes + +- Add warnings about broken controller firmware versions +- Add Heatit Z-Water 2 +- Add Shelly Wave 1PM +- Add Heatit Z-TRM6 +- Increase poll delay for ZW500D +- Add fingerprint for Simon IO Master Roller Blind +- Add HOPPE eHandle ConnectSense +- Add parameters to Zooz ZEN17 from firmware 1.30 +- Update Zooz ZEN32 config to the latest firmware, include 800 series + +### Detailed changelogs + +- [Z-Wave JS 11.14.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.14.3) +- [Z-Wave JS 12.0.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v12.0.0) +- [Z-Wave JS Server 1.32.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.32.0) + +## 0.1.90 + +### Bug fixes + +- Z-Wave JS: Fixed an issue causing commands that have previously been moved to the wakeup queue for sleeping nodes to no longer be handled correctly on wakeup and block the send queue for an extended amount of time + +### Detailed changelogs + +- [Z-Wave JS 11.14.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.14.1) +- [Z-Wave JS 11.14.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.14.2) + +## 0.1.89 + +### Features + +- Z-Wave JS: Optimized the order of node communication during startup to ensure responsive nodes are ready first + +### Bug fixes + +- Z-Wave JS: The start/stop time and date values in `Schedule Entry Lock` CC commands are now validated +- Z-Wave JS: Fixed an issue where `hasDeviceConfigChanged` would return the opposite of what it should, triggering repair issues for users on HA version >= 2023.9.0b0. + +### Config file changes + +- Delay value refresh for ZW500D +- Update several Zooz devices to their 800 series revisions +- Extend version range for Vesternet VES-ZW-DIM-001 + +### Detailed changelogs + +- [Z-Wave JS 11.14.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.14.0) + +## 0.1.88 + +### Features + +- Z-Wave JS: Applications can now report on controller status +- Z-Wave JS Server: Added support for controller identify event + +### Bug fixes + +- Z-Wave JS: Fixed a regression from v11.10.1 where the controller's firmware version was not fully queried +- Z-Wave JS: Change order of commands so the startup does not fail when a controller is already set to use 16-bit node IDs and soft-reset is disabled +- Z-Wave JS: Soft-reset is now always enabled on 700+ series controllers +- Z-Wave JS: Queried user codes and their status are now preserved during re-interview when they won't be re-queried automatically +- Z-Wave JS: Fixed an issue where nodes were being marked as dead because the controller couldn't transmit. +- Z-Wave JS: Fixed an issue where 700 series controllers were not soft-reset after NVM backup when soft-reset was disabled via config +- Z-Wave JS: Discard Meter CC and Multilevel Sensor CC reports when the node they supposedly come from does not support them +- Z-Wave JS: Abort inclusion when a node with the same ID is already part of the network +- Z-Wave JS: Fixed a startup crash that happens when the controller returns an empty list of nodes +- Z-Wave JS: Fixed an issue where API calls would be rejected early or incorrectly resolved while the driver was still retrying a command to an unresponsive node +- Z-Wave JS: Fixed an issue where the controller would be considered jammed if it responds with a Fail status, even after transmitting + +### Config file changes + +- Disable Supervision for Kwikset HC620 to work around a device bug causing it to flood the network +- Add fingerprint for Ring Outdoor Contact Sensor +- Remove unnecessary endpoint functionality for CT100 +- Correct reporting frequency parameter values for Sensative AB Strips Comfort / Drips Multisensor + +### Detailed changelogs + +- [Bump Z-Wave JS Server to 1.31.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.31.0) +- [Bump Z-Wave JS to 11.11.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.11.0) +- [Bump Z-Wave JS to 11.12.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.12.0) +- [Bump Z-Wave JS to 11.13.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.13.0) +- [Bump Z-Wave JS to 11.13.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.13.1) + +## 0.1.87 + +### Bug fixes + +- Z-Wave JS: Fixed a bug where firmware links that redirected to another URL were not supported +- Z-Wave JS: Change order of commands so the startup does not fail when a controller is already set to use 16-bit node IDs and soft-reset is disabled +- Z-Wave JS: Soft-reset is now always enabled on 700+ series controllers +- Z-Wave JS: Queried user codes and their status are now preserved during re-interview when they won't be re-queried automatically + +### Config file changes + +- Add parameters 9-13 to Minoston MP21ZP / MP31ZP +- Add fingerprint to Yale YRD446-ZW2 +- Add and update Yale Assure ZW3 series locks +- Remove unnecessary endpoint functionality for CT101 + +### Detailed changelogs + +- [Bump Z-Wave JS to 11.10.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.10.0) +- [Bump Z-Wave JS to 11.10.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.10.1) + +## 0.1.86 + +### Bug fixes + +- Z-Wave JS: Fixed an issue where a delayed endpoint capability report could be associated with the wrong query +- Z-Wave JS: During NVM migration, some invalid/unexpected bytes in the 500 series NVM can now be corrected +- Z-Wave JS: Hide configuration values for Door Lock CC v4 functionality that is not supported by a lock +- Z-Wave JS: When a CC version query times out, the CC version is now actually assumed to be 1 +- Z-Wave JS: Recover from Security S2 collisions in a common scenario where nodes send a supervised command at the same time Z-Wave JS is trying to control them +- Z-Wave JS: During NVM migration, an incorrect flag for "on other network" is now automatically corrected instead of raising an error +- Z-Wave JS: Fixed an issue where turning on a Multilevel Switch with transition duration could update the currentValue to an illegal value +- Z-Wave JS: Improve heuristic to refresh values from legacy nodes when receiving a node information frame +- Z-Wave JS: Fixed an issue where no control values were exposed for devices that do not support/advertise Version CC +- Z-Wave JS: Fixed a regression introduced in 11.9.1 that would sometimes cause the startup process to hang + +### Config file changes + +- Add Leviton RZM10-1L +- Force use of Multi Channel CC v1 for all versions of PE653 +- Correct state after power failure for Minoston MP21Z/31Z +- Add Namron 4512757 +- Preserve endpoint 0 for Zooz ZEN14 to toggle both outlets at once +- Correct value size for some Nortek PD300EMZ5-1 params that were previously swapped +- Add new MCOHome MH-S411/S412 models + +### Detailed changelogs + +- [Bump Z-Wave JS to 11.7.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.7.0) +- [Bump Z-Wave JS to 11.8.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.8.0) +- [Bump Z-Wave JS to 11.8.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.8.1) +- [Bump Z-Wave JS to 11.9.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.9.0) +- [Bump Z-Wave JS to 11.9.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.9.1) +- [Bump Z-Wave JS to 11.9.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.9.2) + +## 0.1.85 + +### New features + +- Z-Wave JS Server: Add support for inclusions that are started outside of Z-Wave JS Server +- Z-Wave JS Server: Add support for lastSeen property +- Z-Wave JS: Add support for identifying on request of other nodes +- Z-Wave JS: Improved auto-discovery of config parameters + +### Bug fixes + +- Z-Wave JS Server: Fix hard reset support in Z-Wave JS Server +- Z-Wave JS: Increased OTA update timeout, which can help with firmware updates in busy/unstable networks +- Z-Wave JS: Fixed a crash that could happen when including a device with an inclusion controller +- Z-Wave JS: Improved the automatic removal of factory-reset devices that are slow to leave the network +- Z-Wave JS: Devices that failed to join using SmartStart are now automatically removed +- Z-Wave JS: Fix an issue where Z-Wave JS could get stuck when removing a node from the network failed + +### Config file changes + +- Correct config parameters for Duwi ZW ESJ 300 +- Add new FW3.6 parameters to Aeotec ZW141 Nano Shutter +- Add metadata to HANK Electronics Ltd. HKZW-SO01 +- Hide Binary Switch CC in favor of Window Covering CC on iBlinds v3 +- Remove unnecessary endpoints for RTC CT32 +- Update Swidget devices to match their June 8th 2023 spec +- Add endpoint configuration parameters to SES 302 +- Disable Window Covering CC for ZVIDAR Roller Blind +- Add missing product type to Aeotec Water Sensor 7 Basic ZWA018 +- Override endpoint indizes for heatapp! floor +- Override schedule slot count for P-KFCON-MOD-YALE +- Override supported color channels for Zipato RGBW Bulb2 +- Override supported thermostat modes for Z-Wave.me ZME_FT +- Add Heatit ZM Dimmer +- Add Heatit Z-HAN2 +- Add Remotec ZXT-800 +- Clarify Hand Button action for ZVIDAR Z-CM-V01 Smart Curtain Motor +- Add MCOHome MH-S220 FW 3.2 +- Add another device ID for Switch IO On/Off Power Switch +- Add/fix params for Intermatic PE653 +- Add ShenZhen Sunricher Technology Multisensor SR-ZV9032A-EU +- Add new fingerprint for Zooz ZST10-700 +- Fix Zooz ZSE40 parameters 7 and 8 +- Correct parameters of Zooz ZEN05 +- Override supported setpoint types for Intermatic PE653 +- Update Inovelli LZW31 parameter 52 for FW 1.54 +- Add new product id to Fakro ZWS12 +- Disable Supervision for NICE Spa IBT4ZWAVE +- Add variant of Inovelli NZW31T with manufacturer ID 0x015d +- Split and correct Minoston MP21Z/MP31Z/MP21ZP/MP31ZP config files +- Add EVA LOGIK (NIE Tech) ZKS31 Rotary Dimmer + +### Detailed changelogs + +- [Bump Z-Wave JS Server to 1.29.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.29.0) +- [Bump Z-Wave JS Server to 1.29.1](https://github.com/zwave-js/zwave-js-server/releases/tag/1.29.1) +- [Bump Z-Wave JS Server to 1.30.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.30.0) +- [Bump Z-Wave JS to 10.23.4](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.23.4) +- [Bump Z-Wave JS to 10.23.5](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.23.5) +- [Bump Z-Wave JS to 10.23.6](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.23.6) +- [Bump Z-Wave JS to 11.0.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.0.0) +- [Bump Z-Wave JS to 11.1.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.1.0) +- [Bump Z-Wave JS to 11.2.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.2.0) +- [Bump Z-Wave JS to 11.3.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.3.0) +- [Bump Z-Wave JS to 11.4.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.4.0) +- [Bump Z-Wave JS to 11.4.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.4.1) +- [Bump Z-Wave JS to 11.4.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.4.2) +- [Bump Z-Wave JS to 11.5.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.5.0) +- [Bump Z-Wave JS to 11.5.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.5.1) +- [Bump Z-Wave JS to 11.5.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.5.2) +- [Bump Z-Wave JS to 11.5.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.5.3) +- [Bump Z-Wave JS to 11.6.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v11.6.0) + +## 0.1.84 + +### Bug fixes + +- Fixed an issue which could cause temperature to be shown in Celsius instead of Fahrenheit +- Fixed an issue which could cause devices to be incorrectly considered to be awake +- Verify state change for barrier devices without support for Supervision CC instead of assuming commands to succeed + +### Config file changes + +- Correct config parameters for Duwi ZW ESJ 300 + +### Detailed changelogs + +- [Bump Z-Wave JS to 10.23.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.23.0) +- [Bump Z-Wave JS to 10.23.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.23.1) +- [Bump Z-Wave JS to 10.23.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.23.2) + +## 0.1.83 + +### Bug fixes + +- Fixed an issue introduced in Z-Wave JS `10.21.0` where some optimistic value updates would no longer happen after successful multicast commands + +### Detailed changelogs + +- [Bump Z-Wave JS to 10.22.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.22.3) + +## 0.1.82 + +### Bug fixes + +- Fixed a crash scenario +- Fixed an issue that caused device values to stop updating + +### Config file changes + +- Add LG U+ smart switches +- Add/correct config files for iSurpass J1825 +- Added another variant of Kwikset 914C +- Add Dawon PM-S140-ZW, PM-S340-ZW and KR frequencies + +### Detailed changelogs + +- [Bump Z-Wave JS to 10.22.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.22.1) +- [Bump Z-Wave JS to 10.22.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.22.2) + +## 0.1.81 + +### Bug fixes + +- Fixed several crashes +- Expose some device functionality that would previously be hidden as redundant +- Auto-discovered config parameters (for new devices) can now be edited +- Properly support config parameters above number 255 +- Optimized the config parameter queries during the interview to take much less time in many cases +- Some minor changes to better comply with the Z-Wave specification + +### Config file changes + +- Add configuration for Zooz ZEN53, 54, 55 +- Extend version range for Vesternet VES-ZW-HLD-016 +- Add 700 series variant of SimonTech Roller Blind +- Updated instructions for Leviton VRS15 and ZW15R + +### Detailed changelogs + +- [Bump Z-Wave JS to 10.21.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.21.0) +- [Bump Z-Wave JS to 10.20.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.20.0) +- [Bump Z-Wave JS to 10.19.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.19.0) +- [Bump Z-Wave JS to 10.18.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.18.0) +- [Bump Z-Wave JS to 10.17.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.17.1) + +## 0.1.80 + +- [Bump Z-Wave JS to 10.17.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.17.0) + +## 0.1.79 + +- [Bump Z-Wave JS to 10.16.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.16.0) + +## 0.1.78 + +- [Bump Z-Wave JS Server to 1.28.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.28.0) +- [Bump Z-Wave JS to 10.15.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.15.0) +- [Bump Z-Wave JS to 10.14.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.14.1) +- [Bump Z-Wave JS to 10.14.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.14.0) +- [Bump Z-Wave JS to 10.13.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.13.0) + +## 0.1.77 + +- [Bump Z-Wave JS Server to 1.27.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.27.0) +- [Bump Z-Wave JS to 10.12.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.12.0) +- [Bump Z-Wave JS to 10.11.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.11.1) +- [Bump Z-Wave JS to 10.11.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.11.0) + +## 0.1.76 + +- [Bump Z-Wave JS Server to 1.26.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.26.0) +- [Bump Z-Wave JS to 10.10.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.10.0) + +## 0.1.75 + +- [Bump Z-Wave JS Server to 1.25.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.25.0) +- [Bump Z-Wave JS to 10.5.4](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.5.4) + +## 0.1.74 + +- [Bump Z-Wave JS Server to 1.24.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.24.0) +- [Bump Z-Wave JS to 10.3.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.3.0) + +## 0.1.73 + +- [Bump Z-Wave JS Server to 1.23.1](https://github.com/zwave-js/zwave-js-server/releases/tag/1.23.1) +- [Bump Z-Wave JS to 10.2.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.2.0) +- Bump Z-Wave JS to test build to try to address memory leak +- Revert to default base image + +## 0.1.72 + +- Use same base image as community add-on zwave-js-ui + +## 0.1.71 + +- [Bump Z-Wave JS to 10.1.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.1.0) + +## 0.1.70 + +- [Bump Z-Wave JS to 10.0.4](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.0.4) + +## 0.1.69 + +- Use edge version of NodeJS (16.17.0) +- Bump Alpine to 3.16 + +## 0.1.68 + +- [Bump Z-Wave JS to 10.0.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.0.3) + +## 0.1.67 + +- [Bump Z-Wave JS to 10.0.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.0.2) + +## 0.1.66 + +- [Bump Z-Wave JS Server to 1.22.1](https://github.com/zwave-js/zwave-js-server/releases/tag/1.22.1) +- [Bump Z-Wave JS to 10.0.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v10.0.1) + +## 0.1.65 + +- [Bump Z-Wave JS Server to 1.21.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.21.0) +- [Bump Z-Wave JS to 9.6.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v9.6.2) + +## 0.1.64 + +- Fix finish script for S6 V3 + +## 0.1.63 + +- [Bump Z-Wave JS Server to 1.20.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.20.0) + +## 0.1.62 + +- [Bump Z-Wave JS Server to 1.19.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.19.0) + +## 0.1.61 + +- [Bump Z-Wave JS to 9.4.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v9.4.0) +- [Bump Z-Wave JS Server to 1.18.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.18.0) + +## 0.1.60 + +- Fix permissions issue with startup scripts + +## 0.1.59 + +- [Bump Z-Wave JS to 9.3.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v9.3.0) +- [Bump Z-Wave JS Server to 1.17.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.17.0) + +## 0.1.58 + +- [Bump Z-Wave JS to 9.0.7](https://github.com/zwave-js/node-zwave-js/releases/tag/v9.0.7) +- [Bump Z-Wave JS Server to 1.16.1](https://github.com/zwave-js/zwave-js-server/releases/tag/1.16.1) + +## 0.1.57 + +- [Bump Z-Wave JS to 9.0.4](https://github.com/zwave-js/node-zwave-js/releases/tag/v9.0.4) + +## 0.1.56 + +- [Bump Z-Wave JS to 9.0.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v9.0.2) +- [Bump Z-Wave JS Server to 1.16.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.16.0) + +## 0.1.55 + +- [Bump Z-Wave JS to 8.11.9](https://github.com/zwave-js/node-zwave-js/releases/tag/v8.11.9) + +## 0.1.54 + +- [Bump Z-Wave JS to 8.11.6](https://github.com/zwave-js/node-zwave-js/releases/tag/v8.11.6) +- [Bump Z-Wave JS Server to 1.15.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.15.0) + +## 0.1.53 + +- [Bump Z-Wave JS to 8.11.5](https://github.com/zwave-js/node-zwave-js/releases/tag/v8.11.5) + +## 0.1.52 + +- [Bump Z-Wave JS to 8.10.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v8.10.2) +- [Bump Z-Wave JS Server to 1.14.1](https://github.com/zwave-js/zwave-js-server/releases/tag/1.14.1) + +## 0.1.51 + +- [Bump Z-Wave JS to 8.9.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v8.9.2) +- [Bump Z-Wave JS Server to 1.14.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.14.0) + +## 0.1.50 + +- [Bump Z-Wave JS to 8.8.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v8.8.3) + +## 0.1.49 + +- [Bump Z-Wave JS to 8.7.7](https://github.com/zwave-js/node-zwave-js/releases/tag/v8.7.7) +- [Bump Z-Wave JS Server to 1.12.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.12.0) + +## 0.1.48 + +- [Bump Z-Wave JS to 8.7.6](https://github.com/zwave-js/node-zwave-js/releases/tag/v8.7.6) +- [Bump Z-Wave JS Server to 1.11.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.11.0) + +## 0.1.47 + +- Disable soft-reset if VM is detected + +## 0.1.46 + +- [Bump Z-Wave JS to 8.7.5](https://github.com/zwave-js/node-zwave-js/releases/tag/v8.7.5) +- [Bump Z-Wave JS Server to 1.10.8](https://github.com/zwave-js/zwave-js-server/releases/tag/1.10.8) + +## 0.1.45 + +- [Bump Z-Wave JS Server to 1.10.7](https://github.com/zwave-js/zwave-js-server/releases/tag/1.10.7) + +## 0.1.44 + +- Fix casing issues with security keys +- Fix `emulate_hardware` configuration option + +## 0.1.43 + +- [Bump Z-Wave JS Server to 1.10.6](https://github.com/zwave-js/zwave-js-server/releases/tag/1.10.6) + +## 0.1.42 + +- Retain legacy network_key config option to stay backwards compatible. + +## 0.1.41 + +- [Bump Z-Wave JS Server to 1.10.5](https://github.com/zwave-js/zwave-js-server/releases/tag/1.10.5) +- [Bump Z-Wave JS to 8.4.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v8.4.1) +- Add support for S2 keys in the addon configuration (check the Security Keys section of the configuration docs for more details) + +## 0.1.40 + +- [Bump Z-Wave JS to 8.3.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v8.3.0) + +## 0.1.39 + +- [Bump Z-Wave JS to 8.2.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v8.2.3) + +## 0.1.38 + +- [Bump Z-Wave JS Server to 1.10.3](https://github.com/zwave-js/zwave-js-server/releases/tag/1.10.3) +- [Bump Z-Wave JS to 8.2.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v8.2.1) + +## 0.1.37 + +- [Bump Z-Wave JS Server to 1.10.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.10.0) + +## 0.1.36 + +- [Bump Z-Wave JS to 8.1.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v8.1.1) + +## 0.1.35 + +- [Bump Z-Wave JS Server to 1.9.3](https://github.com/zwave-js/zwave-js-server/releases/tag/1.9.3) +- [Bump Z-Wave JS to 8.0.8](https://github.com/zwave-js/node-zwave-js/releases/tag/v8.0.8) + +## 0.1.34 + +- [Bump Z-Wave JS Server to 1.9.2](https://github.com/zwave-js/zwave-js-server/releases/tag/1.9.2) + +## 0.1.33 + +- [Bump Z-Wave JS to 8.0.6](https://github.com/zwave-js/node-zwave-js/releases/tag/v8.0.6) + +## 0.1.32 + +- [Bump Z-Wave JS to 8.0.5](https://github.com/zwave-js/node-zwave-js/releases/tag/v8.0.5) ## 0.1.31 -- Bump Z-Wave JS Server to 1.9.1 +- [Bump Z-Wave JS Server to 1.9.1](https://github.com/zwave-js/zwave-js-server/releases/tag/1.9.1) ## 0.1.30 -- Bump Z-Wave JS to 8.0.3 -- Bump Z-Wave JS Server to 1.9.0 +- [Bump Z-Wave JS to 8.0.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v8.0.3) +- [Bump Z-Wave JS Server to 1.9.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.9.0) ## 0.1.29 -- Bump Z-Wave JS to 7.12.0 +- [Bump Z-Wave JS to 7.12.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v7.12.0) ## 0.1.28 -- Bump Z-Wave JS to 7.10.0 -- Bump Z-Wave JS Server to 1.8.0 +- [Bump Z-Wave JS to 7.10.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v7.10.0) +- [Bump Z-Wave JS Server to 1.8.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.8.0) ## 0.1.27 -- Bump Z-Wave JS to 7.9.0 +- [Bump Z-Wave JS to 7.9.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v7.9.0) ## 0.1.26 -- Bump Z-Wave JS to 7.7.4 +- [Bump Z-Wave JS to 7.7.4](https://github.com/zwave-js/node-zwave-js/releases/tag/v7.7.4) ## 0.1.25 -- Bump Z-Wave JS to 7.7.3 +- [Bump Z-Wave JS to 7.7.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v7.7.3) ## 0.1.24 -- Bump Z-Wave JS to 7.7.0 +- [Bump Z-Wave JS to 7.7.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v7.7.0) - Create persistent directory for device config files to allow for future config updating functionality through the Home Assistant UI. ## 0.1.23 -- Bump Z-Wave JS Server to 1.7.0 -- Pin Z-Wave JS to 7.6.0 +- [Bump Z-Wave JS Server to 1.7.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.7.0) +- [Pin Z-Wave JS to 7.6.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v7.6.0) ## 0.1.22 -- Bump Z-Wave JS Server to 1.6.0 -- Pin Z-Wave JS to 7.5.2 +- [Bump Z-Wave JS Server to 1.6.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.6.0) +- [Pin Z-Wave JS to 7.5.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v7.5.2) ## 0.1.21 -- Pin Z-Wave JS to 7.3.0 +- [Pin Z-Wave JS to 7.3.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v7.3.0) ## 0.1.20 -- Bump Z-Wave JS Server to 1.5.0 -- Pin Z-Wave JS to 7.2.4 +- [Bump Z-Wave JS Server to 1.5.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.5.0) +- [Pin Z-Wave JS to 7.2.4](https://github.com/zwave-js/node-zwave-js/releases/tag/v7.2.4) ## 0.1.19 -- Pin Z-Wave JS to 7.2.3 +- [Pin Z-Wave JS to 7.2.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v7.2.3) - Make log level a configuration option ## 0.1.18 -- Pin Z-Wave JS to 7.2.2 +- [Pin Z-Wave JS to 7.2.2](https://github.com/zwave-js/node-zwave-js/releases/tag/v7.2.2) ## 0.1.17 -- Bump Z-Wave JS Server to 1.4.0 -- Pin Z-Wave JS to 7.1.1 +- [Bump Z-Wave JS Server to 1.4.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.4.0) +- [Pin Z-Wave JS to 7.1.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v7.1.1) ## 0.1.16 -- Bump Z-Wave JS Server to 1.3.1 +- [Bump Z-Wave JS Server to 1.3.1](https://github.com/zwave-js/zwave-js-server/releases/tag/1.3.1) ## 0.1.15 -- Pin Z-Wave JS to version 7.0.1 +- [Pin Z-Wave JS to version 7.0.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v7.0.1) ## 0.1.14 -- Bump Z-Wave JS Server to 1.3.0 -- Pin Z-Wave JS to version 7.0.0 +- [Bump Z-Wave JS Server to 1.3.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.3.0) +- [Pin Z-Wave JS to version 7.0.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v7.0.0) ## 0.1.13 -- Bump Z-Wave JS Server to 1.2.1 -- Pin Z-Wave JS to version 6.6.3 +- [Bump Z-Wave JS Server to 1.2.1](https://github.com/zwave-js/zwave-js-server/releases/tag/1.2.1) +- [Pin Z-Wave JS to version 6.6.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v6.6.3) - Unpin Z-Wave JS dependencies ## 0.1.12 -- Bump Z-Wave JS to 6.5.1 +- [Bump Z-Wave JS to 6.5.1](https://github.com/zwave-js/node-zwave-js/releases/tag/v6.5.1) - Pin Z-Wave JS dependencies ## 0.1.11 -- Bump Z-Wave JS Server to 1.1.1 +- [Bump Z-Wave JS Server to 1.1.1](https://github.com/zwave-js/zwave-js-server/releases/tag/1.1.1) ## 0.1.10 -- Bump Z-Wave JS Server to 1.1.0. This is the same code as 2.0.0. Home Assistant 2021.2 rejects any ZJS Server version that is v2+ +- [Bump Z-Wave JS Server to 1.1.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.1.0) This is the same code as 2.0.0. Home Assistant 2021.2 rejects any ZJS Server version that is v2+ ## 0.1.9 @@ -110,39 +1275,39 @@ ## 0.1.8 -- Bump Z-Wave JS Server to 1.0.0 -- Pin Z-Wave JS to version 6.5.0 +- [Bump Z-Wave JS Server to 1.0.0](https://github.com/zwave-js/zwave-js-server/releases/tag/1.0.0) +- [Pin Z-Wave JS to version 6.5.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v6.5.0) ## 0.1.7 -- Bump Z-Wave JS Server to 1.0.0-beta.6 +- [Bump Z-Wave JS Server to 1.0.0-beta.6](https://github.com/zwave-js/zwave-js-server/releases/tag/1.0.0-beta.6) ## 0.1.6 -- Update zwave-js to version 6.2.0 +- [Update Z-Wave JS to version 6.2.0](https://github.com/zwave-js/node-zwave-js/releases/tag/v6.2.0) ## 0.1.5 - Update hardware configuration for Supervisor 2021.02.5 -- Upgrade Z-Wave JS Server to 1.0.0-beta 5 -- Pin Z-Wave JS to version 6.1.3 +- [Upgrade Z-Wave JS Server to 1.0.0-beta.5](https://github.com/zwave-js/zwave-js-server/releases/tag/1.0.0-beta.5) +- [Pin Z-Wave JS to version 6.1.3](https://github.com/zwave-js/node-zwave-js/releases/tag/v6.1.3) ## 0.1.4 -- Bump Z-Wave JS Server to 1.0.0-beta.4 +- [Bump Z-Wave JS Server to 1.0.0-beta.4](https://github.com/zwave-js/zwave-js-server/releases/tag/1.0.0-beta.4) ## 0.1.3 -- Bump Z-Wave JS Server to 1.0.0-beta.3 +- [Bump Z-Wave JS Server to 1.0.0-beta.3](https://github.com/zwave-js/zwave-js-server/releases/tag/1.0.0-beta.3) ## 0.1.2 -- Bump Z-Wave JS Server to 1.0.0-beta.2 +- [Bump Z-Wave JS Server to 1.0.0-beta.2](https://github.com/zwave-js/zwave-js-server/releases/tag/1.0.0-beta.2) ## 0.1.1 -- Bump Z-Wave JS Server to 1.0.0-beta.1 +- [Bump Z-Wave JS Server to 1.0.0-beta.1](https://github.com/zwave-js/zwave-js-server/releases/tag/1.0.0-beta.1) ## 0.1.0 -- Inital release +- Initial release diff --git a/zwave_js/DOCS.md b/zwave_js/DOCS.md index 4f9a4745c72..6030c868b2c 100644 --- a/zwave_js/DOCS.md +++ b/zwave_js/DOCS.md @@ -4,7 +4,7 @@ Follow these steps to get the add-on installed on your system: -1. Navigate in your Home Assistant frontend to **Supervisor** -> **Add-on Store**. +1. Navigate in your Home Assistant frontend to **Settings** -> **Add-ons** -> **Add-on Store**. 2. Find the "Z-Wave JS" add-on and click it. 3. Click on the "INSTALL" button. @@ -13,44 +13,49 @@ Follow these steps to get the add-on installed on your system: The add-on needs to know where your Z-Wave stick can be found, and therefore, you'll need to configure the add-on to point to the right device. -If you're using Home Assistant you may find the correct value for this on the -`Supervisor -> System -> Host system -> Hardware` page. It is recommended -to use a "by-id" path to the device if one exists, as it is not subject to -change if other devices are added to the system. +If you're using Home Assistant you may find the correct value for this by going to +`Settings -> System -> Hardware` and then clicking the three dots menu and selecting +`All Hardware`. It is recommended to use a "by-id" path to the device if one exists, +as it is not subject to change if other devices are added to the system. 1. Replace `null` in the `device` option in the add-on configuration and specify the device name in quotes: e.g., something like `"/dev/serial/by-id/usb-0658_0200-if00"`, `"/dev/ttyUSB0"`, `"/dev/ttyAMA0"`, or `"/dev/ttyACM0"`. -2. Set your 16-byte (32 character hex) network key in the form `2232666D1...` - used in order to connect securely to compatible devices. It is recommended - that a network key is configured as some security enabled devices (locks, etc) +2. Set your 16-byte (32 character hex) security keys in the form `2232666D1...` + in order to connect securely to compatible devices. It is recommended + that all four network keys are configured as some security enabled devices (locks, etc) may not function correctly if they are not added securely. - * As a note, it is not recommended to securely connect *all* devices unless - necessary as it triples the amount of messages sent on the mesh. + - As a note, it is not recommended to securely connect _all_ devices unless they support S2 security + as the S0 security triples the amount of messages sent on the mesh. 3. Click on "SAVE" to save the add-on configuration. 4. Start the add-on. 5. Add the Z-Wave JS integration to Home Assistant, see documentation: - ## Configuration Add-on configuration: ```yaml device: /dev/ttyUSB0 -network_key: 2232666D100F795E5BB17F0A1BB7A146 +s0_legacy_key: 2232666D100F795E5BB17F0A1BB7A146 +s2_access_control_key: A97D2A51A6D4022998BEFC7B5DAE8EA1 +s2_authenticated_key: 309D4AAEF63EFD85967D76ECA014D1DF +s2_unauthenticated_key: CF338FE0CB99549F7C0EA96308E5A403 +lr_s2_access_control_key: E2CEA6B5986C818EEC0D0065D81E2BD5 +lr_s2_authenticated_key: 863027C59CFC522A9A3C41976AE54254 ``` ### Option `device` -The device address of your Z-Wave controller. +The Z-Wave controller device. -If you're using Home Assistant you may find the correct value for this on the -`Supervisor -> System -> Host system -> Hardware` page. It is recommended -to use a "by-id" path to the device if one exists, as it is not subject to -change if other devices are added to the system. +If you're using Home Assistant you may find the correct value for this by going to +`Settings -> System -> Hardware` and then clicking the three dots menu and +selecting `All Hardware`. It is recommended to use a "by-id" path to the device +if one exists, as it is not subject to change if other devices are added to +the system. In most cases this looks like one of the following: @@ -59,16 +64,20 @@ In most cases this looks like one of the following: - `"/dev/ttyAMA0"` - `"/dev/ttyACM0"` -### Option `network_key` +### Security Keys -Security Z-Wave devices require a network key before being added to the network. -You must set the `network_key` configuration option to use a network key before -adding these devices. +There are six different security keys required to take full advantage of the +different inclusion methods that Z-Wave JS supports: `s0_legacy_key`, +`s2_access_control_key`, `s2_authenticated_key`, `s2_unauthenticated_key`, `lr_s2_access_control_key`, and `lr_s2_authenticated_key`. -If you don't add a network key, it will autogenerate one for you. +If you are coming from a previous version of `zwave-js`, you likely have a key +stored in the `network_key` configuration option. When the addon is first +started, the key will be migrated from `network_key` to `s0_legacy_key` which +will ensure that your S0 secured devices will continue to function. -To generate a network key manually, you can use the following script in, e.g., -the SSH add-on: +If any of these keys are missing on startup, the addon will autogenerate one for +you. To generate a network key manually, you can use the following script in, +e.g., the SSH add-on: ```bash hexdump -n 16 -e '4/4 "%08X" 1 "\n"' /dev/random @@ -78,14 +87,60 @@ You can also use sites like this one to generate the required data: -Ensure you keep a backup of this key. If you have to rebuild your system and -don't have a backup of this key, you won't be able to reconnect to any securely -included devices. This may mean you have to do a factory reset on those devices -and your controller, before rebuilding your Z-Wave network. +Ensure you keep a backup of these keys. If you have to rebuild your system and +don't have a backup of these keys, you won't be able to communicate to any +securely included devices. This may mean you have to do a factory reset on +those devices and your controller, before rebuilding your Z-Wave network. + +> NOTE: Sharing keys between multiple security classes is a security risk, so +> if you choose to configure these keys on your own, be sure to make them +> unique! + +#### Option `s0_legacy_key` + +S0 Security Z-Wave devices require a network key before being added to the network. +This configuration option is required, but if it is unset the addon will generate +a new one automatically on startup. + +#### Option `s2_access_control_key` + +The `s2_access_control_key` must be provided in order to include devices with the +S2 Access Control security class. This security class is needed by devices such +as door locks and garage door openers. This configuration option is required, +but if it is unset the addon will generate a new one automatically on startup. + +#### Option `s2_authenticated_key` + +The `s2_authenticated_key` must be provided in order to include devices with +the S2 Authenticated security class. Devices such as security systems, sensors, +lighting, etc. can request this security class. This configuration option is +required, but if it is unset the addon will generate a new one automatically +on startup. + +### Option `s2_unauthenticated_key` + +The `s2_unauthenticated_key` must be provided in order to include devices with +the S2 Unauthenticated security class. This is similar to S2 Authenticated, but +without verification that the correct device was included. This configuration +option is required, but if it is unset the addon will generate a new one +automatically on startup. + +#### Option `lr_s2_access_control_key` + +The `lr_s2_access_control_key` must be provided in order to include devices using +Z-Wave Long Range. This configuration option is required, but if it is unset +the addon will generate a new one automatically on startup. + +#### Option `lr_s2_authenticated_key` + +The `lr_s2_authenticated_key` must be provided in order to include devices using +Z-Wave Long Range. This configuration option is required, but if it is unset +the addon will generate a new one automatically on startup. ### Option `log_level` (optional) This option sets the log level of Z-Wave JS. Valid options are: + - silly - debug - verbose @@ -97,11 +152,73 @@ This option sets the log level of Z-Wave JS. Valid options are: If no `log_level` is specified, the log level will be set to the level set in the Supervisor. +### Option `log_to_file` (optional) + +When this option is enabled, logs will be written to the `/addon_configs/core_zwave_js` +folder with the `.log` file extension. + +### Option `log_max_files` (optional) + +When `log_to_file` is true, Z-Wave JS will create a log file for each +day. This option allows you to control the maximum number of files that +Z-Wave JS will keep. + +### Option `soft_reset` (optional) + +This setting tells the add-on how to handle soft-resets for 500 series controllers: +1. Automatic - the add-on will decide whether soft-reset should be enabled or disabled for 500 series controllers. This is the default option and should work for most people. +2. Enabled - Soft-reset will be explicitly enabled for 500 series controllers. +3. Disabled - Soft-reset will be explicitly disabled for 500 series controllers. + ### Option `emulate_hardware` (optional) If you don't have a USB stick, you can use a fake stick for testing purposes. It will not be able to control any real devices. +### Option `disable_controller_recovery` (optional): + +This setting will disable Z-Wave JS's automatic recovery process when the +controller appears to be unresponsive and will instead let the controller +recover on its own if it's capable of doing so. While the controller is +unresponsive, commands will start to fail and nodes may randomly get +marked as dead. If a controller is not able to recover on its own, you +will need to restart the add-on to attempt recovery. In most cases, users +will never need to use this feature, so only change this setting if you +know what you are doing and/or you are asked to. + +### Option `disable_watchdog` (optional): + +This setting will prevent Z-Wave JS from enabling the hardware watchdog +on supporting controllers. In most cases, users will never need to use this +feature, so only change this setting if you know what you are doing and/or +you are asked to. + +### Option `safe_mode` (optional) + +This setting puts your network in safe mode, which could significantly decrease +the performance of your network but may also help get the network up and running +so that you can troubleshoot issues, grab logs, etc. In most cases, users will +never need to use this feature, so only change this setting if you know what you +are doing and/or you are asked to. + +### Option `network_key` (deprecated) + +In previous versions of the addon, this was the only key that was needed. With +the introduction of S2 security inclusion in zwave-js, this option has been +deprecated in favor of `s0_legacy_key`. If still set, the `network_key` value will be +migrated to `s0_legacy_key` on first startup. + +### Troubleshooting network issues + +There are several features available in the add-on that can help you in troubleshooting network issues and/or providing data to either the Home Assistant or Z-Wave JS team to help in tracing an issue: + +1. **Update the log level:** It is extremely helpful when opening a GitHub issue to set the `log_level` configuration option to `debug` and capture when the issue occurs. +2. **Log to file:** The `log_to_file` and `log_max_files` configuration options allow you to enable and configure that. Note that in order to access the log files, you will need to be able to access the filesystem of your HA instance, which you can do with the file editor, samba, or ssh add-ons among others. +3. **Access Z-Wave JS cache:** Z-Wave JS stores information it discovers about your network in cache files so that your devices don't have to be reinterviewed on every startup. In some cases, when opening a GitHub issue, you may be asked to provide the cache files. You can access them in `/addon_configs/core_zwave_js/cache`. Note that in order to access the cache, you will need to be able to access the filesystem of your HA instance, which you can do with the file editor, samba, or ssh add-ons among others. +4. **Change soft reset behavior:** By default, the addon will choose whether or not to soft reset the controller at startup automatically. In most cases that shouldn't be changed, but if asked to make a change when troubleshooting an issue, you can do so using the `soft_reset` configuration option. +5. **Disable controller recovery:** By default, if the network controller appears to be jammed, Z-Wave JS will automatically try to restore the controller to a healthy state. In most cases that shouldn't be changed, but if asked to make a change when troubleshooting an issue, you can do so using the `disable_controller_recovery` configuration option. +6. **Enable safe mode:** When Z-Wave JS is having trouble starting up, it can sometimes be hard to get useful logs to troubleshoot the issue. By setting `safe_mode` to true, Z-Wave JS may be able to start up in cases where it wouldn't with the `safe_mode` set to false. Note that enabling `safe_mode` will have a negative impact on the performance of your network and should be used sparingly. + ## Known issues and limitations - Your hardware needs to be compatible with the Z-Wave JS library @@ -120,5 +237,5 @@ In case you've found a bug, please [open an issue on our GitHub][issue]. [discord]: https://discord.gg/c5DvZ4e [forum]: https://community.home-assistant.io -[issue]: https://github.com/home-assistant/hassio-addons/issues +[issue]: https://github.com/home-assistant/addons/issues [reddit]: https://reddit.com/r/homeassistant diff --git a/zwave_js/Dockerfile b/zwave_js/Dockerfile index 9f499d686c3..632d3a8cfbd 100644 --- a/zwave_js/Dockerfile +++ b/zwave_js/Dockerfile @@ -4,6 +4,11 @@ FROM ${BUILD_FROM} ARG ZWAVEJS_SERVER_VERSION ARG ZWAVEJS_VERSION +# Environment configuration +ENV \ + S6_KILL_GRACETIME=30000 \ + S6_SERVICES_GRACETIME=30000 + # Install Z-Wave JS WORKDIR /usr/src RUN \ @@ -17,11 +22,11 @@ RUN \ linux-headers \ python3 \ \ - && npm config set unsafe-perm \ - && npm install \ + && npm install --force \ "zwave-js@${ZWAVEJS_VERSION}" \ "@zwave-js/server@${ZWAVEJS_SERVER_VERSION}" \ \ + && npm rebuild --build-from-source @serialport/bindings-cpp \ && apk del --no-cache \ .build-dependencies diff --git a/zwave_js/build.json b/zwave_js/build.json deleted file mode 100644 index 21bf9f8c423..00000000000 --- a/zwave_js/build.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "build_from": { - "amd64": "homeassistant/amd64-base:3.13", - "i386": "homeassistant/i386-base:3.13", - "armhf": "homeassistant/armhf-base:3.13", - "armv7": "homeassistant/armv7-base:3.13", - "aarch64": "homeassistant/aarch64-base:3.13" - }, - "args": { - "ZWAVEJS_SERVER_VERSION": "1.9.1", - "ZWAVEJS_VERSION": "8.0.5" - } -} diff --git a/zwave_js/build.yaml b/zwave_js/build.yaml new file mode 100644 index 00000000000..5c71d782983 --- /dev/null +++ b/zwave_js/build.yaml @@ -0,0 +1,13 @@ +--- +build_from: + aarch64: ghcr.io/home-assistant/aarch64-base:3.18 + amd64: ghcr.io/home-assistant/amd64-base:3.18 + armhf: ghcr.io/home-assistant/armhf-base:3.18 + armv7: ghcr.io/home-assistant/armv7-base:3.18 + i386: ghcr.io/home-assistant/i386-base:3.18 +codenotary: + signer: notary@home-assistant.io + base_image: notary@home-assistant.io +args: + ZWAVEJS_SERVER_VERSION: 1.40.3 + ZWAVEJS_VERSION: 14.3.8 diff --git a/zwave_js/config.json b/zwave_js/config.json deleted file mode 100644 index 830d0768711..00000000000 --- a/zwave_js/config.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "Z-Wave JS", - "version": "0.1.32", - "slug": "zwave_js", - "description": "Control a ZWave network with Home Assistant Z-Wave JS", - "arch": ["amd64", "i386", "armhf", "armv7", "aarch64"], - "url": "https://github.com/home-assistant/hassio-addons/tree/master/zwave_js", - "startup": "services", - "init": false, - "stage": "experimental", - "homeassistant": "2021.2.0b0", - "ports": { - "3000/tcp": null - }, - "ports_description": { - "3000/tcp": "Z-Wave JS communication" - }, - "discovery": ["zwave_js"], - "options": { - "device": null, - "network_key": "", - "log_level": "info" - }, - "schema": { - "device": "device(subsystem=tty)", - "network_key": "match(|[0-9a-fA-F]{32,32})", - "log_level": "list(silly|debug|verbose|http|info|warn|error)?", - "emulate_hardware": "bool?" - }, - "image": "homeassistant/{arch}-addon-zwave_js" -} diff --git a/zwave_js/config.yaml b/zwave_js/config.yaml new file mode 100644 index 00000000000..cc3e27acede --- /dev/null +++ b/zwave_js/config.yaml @@ -0,0 +1,55 @@ +--- +version: 0.10.0 +slug: zwave_js +name: Z-Wave JS +description: Control a Z-Wave network with Home Assistant Z-Wave JS +url: https://github.com/home-assistant/addons/tree/master/zwave_js +arch: + - amd64 + - i386 + - armhf + - armv7 + - aarch64 +codenotary: notary@home-assistant.io +discovery: + - zwave_js +hassio_api: true +homeassistant: 2021.2.0b0 +image: homeassistant/{arch}-addon-zwave_js +init: false +map: + - addon_config:rw +options: + device: null + log_level: info + log_to_file: false + log_max_files: 7 + soft_reset: Automatic + s0_legacy_key: "" + s2_access_control_key: "" + s2_authenticated_key: "" + s2_unauthenticated_key: "" + lr_s2_access_control_key: "" + lr_s2_authenticated_key: "" +ports: + 3000/tcp: null +schema: + device: device(subsystem=tty) + log_level: list(silly|debug|verbose|http|info|warn|error)? + log_to_file: bool? + log_max_files: int(1,)? + soft_reset: list(Automatic|Enabled|Disabled)? + s0_legacy_key: match(|[0-9a-fA-F]{32,32})? + s2_access_control_key: match(|[0-9a-fA-F]{32,32})? + s2_authenticated_key: match(|[0-9a-fA-F]{32,32})? + s2_unauthenticated_key: match(|[0-9a-fA-F]{32,32})? + lr_s2_access_control_key: match(|[0-9a-fA-F]{32,32})? + lr_s2_authenticated_key: match(|[0-9a-fA-F]{32,32})? + network_key: match(|[0-9a-fA-F]{32,32})? + emulate_hardware: bool? + disable_controller_recovery: bool? + disable_watchdog: bool? + safe_mode: bool? +stage: stable +startup: services +timeout: 30 diff --git a/zwave_js/rootfs/etc/cont-init.d/config.sh b/zwave_js/rootfs/etc/cont-init.d/config.sh old mode 100644 new mode 100755 index bcc7796abdf..6ac16a22d4b --- a/zwave_js/rootfs/etc/cont-init.d/config.sh +++ b/zwave_js/rootfs/etc/cont-init.d/config.sh @@ -1,36 +1,105 @@ #!/usr/bin/with-contenv bashio +# shellcheck shell=bash # ============================================================================== # Generate Z-Wave JS config file # ============================================================================== declare network_key +declare network_key_upper +declare s0_legacy_key +declare s0_legacy +declare s2_access_control +declare s2_authenticated +declare s2_unauthenticated +declare log_level +declare flush_to_disk +declare host_chassis +declare soft_reset +declare presets_array +declare presets -readonly DOCS_EXAMPLE_KEY="2232666D100F795E5BB17F0A1BB7A146" - -if [[ "${DOCS_EXAMPLE_KEY}" == "$(bashio::config 'network_key')" ]]; then - bashio::log.fatal - bashio::log.fatal 'The add-on detected that the Z-Wave network key used' - bashio::log.fatal 'is from the documented example.' - bashio::log.fatal - bashio::log.fatal 'Using this key is insecure, because it is publicly' - bashio::log.fatal 'listed in the documentation.' - bashio::log.fatal - bashio::log.fatal 'Please check the add-on documentation on how to' - bashio::log.fatal 'create your own, secret, "network_key" and replace' - bashio::log.fatal 'the one you have configured.' - bashio::log.fatal - bashio::log.fatal 'Click on the "Documentation" tab in the Z-Wave JS' - bashio::log.fatal 'add-on panel for more information.' - bashio::log.fatal - bashio::exit.nok -elif ! bashio::config.has_value 'network_key'; then - bashio::log.info "No Network Key is set, generate one..." - network_key=$(hexdump -n 16 -e '4/4 "%08X" 1 "\n"' /dev/random) - bashio::addon.option network_key "${network_key}" -else - network_key=$(bashio::config 'network_key') +readonly DOCS_EXAMPLE_KEY_1="2232666D100F795E5BB17F0A1BB7A146" +readonly DOCS_EXAMPLE_KEY_2="A97D2A51A6D4022998BEFC7B5DAE8EA1" +readonly DOCS_EXAMPLE_KEY_3="309D4AAEF63EFD85967D76ECA014D1DF" +readonly DOCS_EXAMPLE_KEY_4="CF338FE0CB99549F7C0EA96308E5A403" +readonly DOCS_EXAMPLE_KEY_5="E2CEA6B5986C818EEC0D0065D81E2BD5" +readonly DOCS_EXAMPLE_KEY_6="863027C59CFC522A9A3C41976AE54254" + +if bashio::config.has_value 'network_key'; then + # If both 'network_key' and 's0_legacy_key' are set and keys don't match, + # we don't know which one to pick so we have to exit. If they are both set + # and do match, we don't need to do anything + if bashio::config.has_value 's0_legacy_key'; then + network_key=$(bashio::string.upper "$(bashio::config 'network_key')") + s0_legacy_key=$(bashio::string.upper "$(bashio::config 's0_legacy_key')") + if [ "${network_key}" == "${s0_legacy_key}" ]; then + bashio::log.info "Both 'network_key' and 's0_legacy_key' are set and match. All ok." + else + bashio::log.fatal "Both 'network_key' and 's0_legacy_key' are set to different values " + bashio::log.fatal "so we are unsure which one to use. One needs to be removed from the " + bashio::log.fatal "configuration in order to start the addon." + bashio::exit.nok + fi + # If we get here, 'network_key' is set and 's0_legacy_key' is not set so we need + # to migrate the key from 'network_key' to 's0_legacy_key' + else + bashio::log.info "Migrating \"network_key\" option to \"s0_legacy_key\"..." + bashio::addon.option s0_legacy_key "$(bashio::config 'network_key')" + bashio::log.info "Flushing config to disk due to key migration..." + bashio::addon.options >"/data/options.json" + fi +fi + +# Validate that no keys are using the example from the docs and generate new random +# keys for any missing keys. +for key in "s0_legacy_key" "s2_access_control_key" "s2_authenticated_key" "s2_unauthenticated_key" "lr_s2_access_control_key" "lr_s2_authenticated_key"; do + network_key=$(bashio::config "${key}") + network_key_upper=$(bashio::string.upper "${network_key}") + if [ "${network_key_upper}" == "${DOCS_EXAMPLE_KEY_1}" ] || [ "${network_key_upper}" == "${DOCS_EXAMPLE_KEY_2}" ] || [ "${network_key_upper}" == "${DOCS_EXAMPLE_KEY_3}" ] || [ "${network_key_upper}" == "${DOCS_EXAMPLE_KEY_4}" ] || [ "${network_key_upper}" == "${DOCS_EXAMPLE_KEY_5}" ] || [ "${network_key_upper}" == "${DOCS_EXAMPLE_KEY_6}" ]; then + bashio::log.fatal + bashio::log.fatal "The add-on detected that the Z-Wave network key used" + bashio::log.fatal "is from the documented example." + bashio::log.fatal + bashio::log.fatal "Using this key is insecure, because it is publicly" + bashio::log.fatal "listed in the documentation." + bashio::log.fatal + bashio::log.fatal "Please check the add-on documentation on how to" + bashio::log.fatal "create your own, secret, \"${key}\" and replace" + bashio::log.fatal "the one you have configured." + bashio::log.fatal + bashio::log.fatal "Click on the \"Documentation\" tab in the Z-Wave JS" + bashio::log.fatal "add-on panel for more information." + bashio::log.fatal + bashio::exit.nok + elif ! bashio::var.has_value "${network_key}"; then + bashio::log.info "No ${key} is set, generating one..." + network_key="$(hexdump -n 16 -e '4/4 "%08X" 1 "\n"' /dev/random)" + bashio::addon.option ${key} "${network_key}" + flush_to_disk=1 + fi + + # If `network_key` is unset, we set it to match `s0_legacy_key` for backwards compatibility + if bashio::var.equals "${key}" "s0_legacy_key" && ! bashio::config.has_value "network_key"; then + bashio::log.info "No 'network_key' detected, setting it to 's0_legacy_key' for backwards compatibility" + bashio::addon.option network_key "${network_key}" + flush_to_disk=1 + fi +done + +# If flush_to_disk is set, it means we have generated new key(s) and they need to get +# flushed to disk +if [[ ${flush_to_disk:+x} ]]; then + bashio::log.info "Flushing config to disk due to creation of new key(s)..." + bashio::addon.options >"/data/options.json" fi -if ! bashio::config.has_value 'log_level'; then +s0_legacy=$(bashio::config "s0_legacy_key") +s2_access_control=$(bashio::config "s2_access_control_key") +s2_authenticated=$(bashio::config "s2_authenticated_key") +s2_unauthenticated=$(bashio::config "s2_unauthenticated_key") +lr_s2_access_control=$(bashio::config "lr_s2_access_control_key") +lr_s2_authenticated=$(bashio::config "lr_s2_authenticated_key") + +if ! bashio::config.has_value 'log_level'; then log_level=$(bashio::info.logging) bashio::log.info "No log level specified, falling back to Supervisor" bashio::log.info "log level (${log_level})..." @@ -38,11 +107,71 @@ else log_level=$(bashio::config 'log_level') fi +host_chassis=$(bashio::host.chassis) + +if bashio::config.equals 'soft_reset' 'Automatic'; then + bashio::log.info "Soft-reset set to automatic" + if [ "${host_chassis}" == "vm" ]; then + soft_reset=false + bashio::log.info "Virtual Machine detected, disabling soft-reset" + else + soft_reset=true + bashio::log.info "Virtual Machine not detected, enabling soft-reset" + fi +elif bashio::config.equals 'soft_reset' 'Enabled'; then + soft_reset=true + bashio::log.info "Soft-reset enabled by user" +else + soft_reset=false + bashio::log.info "Soft-reset disabled by user" +fi + +# Create empty presets array +presets_array=() + +if bashio::config.true 'safe_mode'; then + bashio::log.info "Safe mode enabled" + bashio::log.warning "WARNING: While in safe mode, the performance of your Z-Wave network will be in a reduced state. This is only meant for debugging purposes." + # Add SAFE_MODE to presets array + presets_array+=("SAFE_MODE") +fi + +if bashio::config.true 'disable_controller_recovery'; then + bashio::log.info "Automatic controller recovery disabled" + bashio::log.warning "WARNING: If your controller becomes unresponsive, commands may start to fail and nodes may start to get marked as dead until the controller is able to recover on its own. If it doesn't recover on its own, you will need to restart the add-on manually to try to recover yourself." + # Add NO_CONTROLLER_RECOVERY to presets array + presets_array+=("NO_CONTROLLER_RECOVERY") +fi + +if bashio::config.true 'disable_watchdog'; then + bashio::log.info "Hardware watchdog disabled" + # Add NO_WATCHDOG to presets array + presets_array+=("NO_WATCHDOG") +fi + +# Convert presets array to JSON string and add to config +if [[ ${#presets_array[@]} -eq 0 ]]; then + presets="[]" +else + presets="$(printf '%s\n' "${presets_array[@]}" | jq -R . | jq -s .)" +fi + +log_to_file=$(bashio::config "log_to_file") +log_max_files=$(bashio::config "log_max_files") # Generate config bashio::var.json \ - network_key "${network_key}" \ + s0_legacy "${s0_legacy}" \ + s2_access_control "${s2_access_control}" \ + s2_authenticated "${s2_authenticated}" \ + s2_unauthenticated "${s2_unauthenticated}" \ + lr_s2_access_control "${lr_s2_access_control}" \ + lr_s2_authenticated "${lr_s2_authenticated}" \ log_level "${log_level}" \ - | tempio \ + log_to_file "${log_to_file}" \ + log_max_files "${log_max_files}" \ + soft_reset "^${soft_reset}" \ + presets "${presets}" | + tempio \ -template /usr/share/tempio/zwave_config.conf \ -out /etc/zwave_config.json diff --git a/zwave_js/rootfs/etc/cont-init.d/structure.sh b/zwave_js/rootfs/etc/cont-init.d/structure.sh old mode 100644 new mode 100755 index 98f5fb1c5cb..2e698f35a5a --- a/zwave_js/rootfs/etc/cont-init.d/structure.sh +++ b/zwave_js/rootfs/etc/cont-init.d/structure.sh @@ -1,6 +1,15 @@ #!/usr/bin/with-contenv bashio +# shellcheck shell=bash # ============================================================================== # Setup folder structure # ============================================================================== -mkdir -p /data/cache mkdir -p /data/db + +if bashio::fs.directory_exists '/data/cache'; then + bashio::log.info "Migrating 'cache' folder from private storage to /addon_configs/core_zwave_js" + mv /data/cache /config/cache +fi + +if ! bashio::fs.directory_exists '/config/cache'; then + mkdir -p /config/cache +fi diff --git a/zwave_js/rootfs/etc/services.d/zwave_js/discovery b/zwave_js/rootfs/etc/services.d/zwave_js/discovery index a9acd83418f..3303c089dbb 100755 --- a/zwave_js/rootfs/etc/services.d/zwave_js/discovery +++ b/zwave_js/rootfs/etc/services.d/zwave_js/discovery @@ -1,4 +1,6 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Send zwave_js discovery information to Home Assistant # ============================================================================== diff --git a/zwave_js/rootfs/etc/services.d/zwave_js/finish b/zwave_js/rootfs/etc/services.d/zwave_js/finish old mode 100644 new mode 100755 index d886e9f6b34..f4c53b282d0 --- a/zwave_js/rootfs/etc/services.d/zwave_js/finish +++ b/zwave_js/rootfs/etc/services.d/zwave_js/finish @@ -1,8 +1,13 @@ -#!/usr/bin/execlineb -S1 +#!/usr/bin/env bashio +# vim: ft=bash # ============================================================================== -# Take down the S6 supervision tree when Z-Wave JS fails +# Take down the S6 supervision tree when service fails +# s6-overlay docs: https://github.com/just-containers/s6-overlay # ============================================================================== -if { s6-test ${1} -ne 0 } -if { s6-test ${1} -ne 256 } -s6-svscanctl -t /var/run/s6/services +if [[ "$1" -ne 0 ]] && [[ "$1" -ne 256 ]]; then + bashio::log.warning "Halt add-on" + exec /run/s6/basedir/bin/halt +fi + +bashio::log.info "Service restart after closing" diff --git a/zwave_js/rootfs/etc/services.d/zwave_js/run b/zwave_js/rootfs/etc/services.d/zwave_js/run old mode 100644 new mode 100755 index 7fcd4f2baa2..9d5d150bd22 --- a/zwave_js/rootfs/etc/services.d/zwave_js/run +++ b/zwave_js/rootfs/etc/services.d/zwave_js/run @@ -1,4 +1,6 @@ #!/usr/bin/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash # ============================================================================== # Start Z-Wave JS service for Z-Wave radio # ============================================================================== @@ -6,7 +8,7 @@ SERIAL_DEVICE=$(bashio::config 'device') # Emulate serial Hardware for test & development if bashio::config.true 'emulate_hardware'; then - SERIAL_DEVICE="--mock" + SERIAL_DEVICE="--mock-driver" fi # Send out discovery information to Home Assistant @@ -16,4 +18,5 @@ fi export ZWAVEJS_EXTERNAL_CONFIG=/data/db # Run daemon, passing external config directory in as environment variable -exec zwave-server ${SERIAL_DEVICE} --config /etc/zwave_config.json +# shellcheck disable=SC2086 +exec zwave-server ${SERIAL_DEVICE} --config /etc/zwave_config.json --disable-dns-sd diff --git a/zwave_js/rootfs/usr/share/tempio/zwave_config.conf b/zwave_js/rootfs/usr/share/tempio/zwave_config.conf index 22fc22352c9..4f95abe6579 100644 --- a/zwave_js/rootfs/usr/share/tempio/zwave_config.conf +++ b/zwave_js/rootfs/usr/share/tempio/zwave_config.conf @@ -2,11 +2,27 @@ "logConfig": { "enabled": true, "level": "{{ .log_level }}", + "logToFile": {{ .log_to_file }}, + "maxFiles": {{ .log_max_files }}, + "filename": "/config/zwave", "forceConsole": true }, "storage": { - "cacheDir": "/data/cache", + "cacheDir": "/config/cache", "throttle": "slow" }, - "networkKey": "{{ .network_key }}" + "securityKeys": { + "S0_Legacy": "{{ .s0_legacy }}", + "S2_AccessControl": "{{ .s2_access_control }}", + "S2_Authenticated": "{{ .s2_authenticated }}", + "S2_Unauthenticated": "{{ .s2_unauthenticated }}" + }, + "securityKeysLongRange": { + "S2_AccessControl": "{{ .lr_s2_access_control }}", + "S2_Authenticated": "{{ .lr_s2_authenticated }}" + }, + "features": { + "softReset": {{ .soft_reset }} + }, + "presets": {{ .presets }} } diff --git a/zwave_js/translations/en.yaml b/zwave_js/translations/en.yaml new file mode 100644 index 00000000000..5a000030f2b --- /dev/null +++ b/zwave_js/translations/en.yaml @@ -0,0 +1,97 @@ +--- +configuration: + device: + name: Device + description: The Z-Wave controller device. + emulate_hardware: + name: Enable Emulated Hardware + description: >- + If you don't have a USB stick, you can use a fake stick for testing + purposes. + log_level: + name: Log Level + description: This option sets the log level of Z-Wave JS. + log_to_file: + name: Log to File? + description: >- + When this option is enabled, logs will be written to the + `/addon_configs/core_zwave_js` folder with the `.log` file extension. + log_max_files: + name: Max number of log files to keep + description: >- + When `log_to_file` is true, Z-Wave JS will create a log file for each + day. This option allows you to control the maximum number of files that + Z-Wave JS will keep. + network_key: + name: Network Key + description: >- + In previous versions of the addon, this was the only key that was needed. + With the introduction of S2 security inclusion in zwave-js, this option + has been deprecated. + s0_legacy_key: + name: S0 Legacy Key + description: >- + S0 Security Z-Wave devices require a network key before being added to the + network. + s2_access_control_key: + name: S2 Access Control Key + description: >- + This must be provided in order to include devices with the S2 Access + Control security class. + s2_authenticated_key: + name: S2 Authenticated Key + description: >- + This must be provided in order to include devices with the S2 + Authenticated security class. + s2_unauthenticated_key: + name: S2 Unauthenticated Key + description: >- + This must be provided in order to include devices with the S2 + Unauthenticated security class. + lr_s2_access_control_key: + name: Z-Wave Long Range S2 Access Control Key + description: >- + This must be provided in order to include devices using Z-Wave + Long Range with the S2 Access Control security class. + lr_s2_authenticated_key: + name: Z-Wave Long Range S2 Authenticated Key + description: >- + This must be provided in order to include devices using Z-Wave + Long Range with the S2 Authenticated security class. + soft_reset: + name: 500 series controller soft-reset + description: >- + This setting tells the add-on how to handle soft-resets for 500 series + controllers. The default setting, Automatic, instructs the add-on to + automatically detect whether or not this needs to be enabled. The + default setting should work for most users, so only change this setting + if you know what you are doing and/or you are asked to. + disable_controller_recovery: + name: Disable automatic controller recovery + description: >- + This setting will disable Z-Wave JS's automatic recovery process when the + controller appears to be unresponsive and will instead let the controller + recover on its own if it's capable of doing so. While the controller is + unresponsive, commands will start to fail and nodes may randomly get + marked as dead. If a controller is not able to recover on its own, you + will need to restart the add-on to attempt recovery. In most cases, users + will never need to use this feature, so only change this setting if you + know what you are doing and/or you are asked to. + disable_watchdog: + name: Disable Z-Wave JS (hardware) watchdog + description: >- + This setting will prevent Z-Wave JS from enabling the hardware watchdog + on supporting controllers. In most cases, users will never need to use + this feature, so only change this setting if you know what you are doing + and/or you are asked to. + safe_mode: + name: Enable safe mode + description: >- + This setting puts your network in safe mode, which could significantly + decrease the performance of your network but may also help get the + network up and running so that you can troubleshoot issues, grab logs, + etc. In most cases, users will never need to use this feature, so only + change this setting if you know what you are doing and/or you are asked + to. +network: + 3000/tcp: Z-Wave JS communication