From c6f134f543417752742ec56b893d626232837017 Mon Sep 17 00:00:00 2001 From: bvweerd Date: Wed, 7 Jan 2026 16:53:31 +0100 Subject: [PATCH 01/24] Bump version to 1.5.2 in manifest.json --- custom_components/simple_pid_controller/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/simple_pid_controller/manifest.json b/custom_components/simple_pid_controller/manifest.json index 1cc62c8..8c0c96d 100644 --- a/custom_components/simple_pid_controller/manifest.json +++ b/custom_components/simple_pid_controller/manifest.json @@ -11,6 +11,6 @@ "quality_scale": "silver", "requirements": ["simple-pid==2.0.1"], "ssdp": [], - "version": "1.4.2", + "version": "1.5.2", "zeroconf": [] } From 3f0c38bc77908c1df477bb3552273c6ce589d648 Mon Sep 17 00:00:00 2001 From: bvweerd Date: Sun, 15 Feb 2026 11:04:21 +0100 Subject: [PATCH 02/24] ci: standaardiseer CI/CD pipeline, versioning en templates - ci.yml: uniforme pipeline (lint, test matrix, hacs, hassfest) op dev/feature/fix branches en PRs - release.yml: tag-gedreven release met ZIP artifact en changelog (vervangt losse workflows) - bump-version.yml: workflow_dispatch voor patch/minor/major versie bump op main - Verwijder kapotte release-versioning.yml, losse pytest/precommit/hacs/hassfest workflows - hacs.json: zip_release + filename toegevoegd waar ontbrak - .bumpversion.toml: commit=true, tag=true, v-prefix, beide bestanden gesynchroniseerd - Versies gesynchroniseerd op basis van git tags (enige bron van waarheid) - Issue templates (bug report, feature request), verbeterde labeler.yml, labels.yml - sync-labels.yml: synchroniseer GitHub labels vanuit .github/labels.yml - PR template bijgewerkt met conventional commits vereiste --- .bumpversion.toml | 15 +++- .github/ISSUE_TEMPLATE/bug_report.yml | 68 +++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.yml | 45 +++++++++++ .github/labeler.yml | 29 ++++--- .github/labels.yml | 52 +++++++++++++ .github/pull_request_template.md | 41 ++++------ .github/workflows/bump-version.yml | 51 +++++++++++++ .github/workflows/ci.yml | 75 +++++++++++++++++++ .github/workflows/hacs.yml | 25 ------- .github/workflows/hassfest.yml | 25 ------- .github/workflows/label-issues.yml | 17 +++-- .github/workflows/precommit.yml | 61 --------------- .github/workflows/pytest.yml | 41 ---------- .github/workflows/release-versioning.yml | 61 --------------- .github/workflows/release.yml | 61 ++++++++++----- .github/workflows/sync-labels.yml | 23 ++++++ .../simple_pid_controller/manifest.json | 8 +- setup.cfg | 2 +- 18 files changed, 420 insertions(+), 280 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/labels.yml create mode 100644 .github/workflows/bump-version.yml create mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/hacs.yml delete mode 100644 .github/workflows/hassfest.yml delete mode 100644 .github/workflows/precommit.yml delete mode 100644 .github/workflows/pytest.yml delete mode 100644 .github/workflows/release-versioning.yml create mode 100644 .github/workflows/sync-labels.yml diff --git a/.bumpversion.toml b/.bumpversion.toml index cfb5766..508b6f4 100644 --- a/.bumpversion.toml +++ b/.bumpversion.toml @@ -1,12 +1,19 @@ [tool.bumpversion] -current_version = "1.4.2" +current_version = "1.5.2" parse = "(?P\\d+)\\.(?P\\d+)\\.(?P\\d+)" serialize = ["{major}.{minor}.{patch}"] -search = "{current_version}" -replace = "{new_version}" -regex = false +commit = true +tag = true +tag_name = "v{new_version}" +commit_args = "--no-verify" +message = "chore: bump version to {new_version}" [[tool.bumpversion.files]] filename = "custom_components/simple_pid_controller/manifest.json" search = '"version": "{current_version}"' replace = '"version": "{new_version}"' + +[[tool.bumpversion.files]] +filename = "setup.cfg" +search = "current_version = {current_version}" +replace = "current_version = {new_version}" diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..ee457ef --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,68 @@ +name: Bug Report +description: Meld een bug of onverwacht gedrag +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + Bedankt voor het melden van een bug! Vul het formulier zo volledig mogelijk in. + + - type: input + id: version + attributes: + label: Versie + description: Welke versie gebruik je? + placeholder: "bijv. 1.2.3" + validations: + required: true + + - type: input + id: ha_version + attributes: + label: Home Assistant versie (indien van toepassing) + placeholder: "bijv. 2025.2.0" + + - type: textarea + id: description + attributes: + label: Beschrijving van de bug + description: Wat gaat er mis? Wees zo specifiek mogelijk. + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Stappen om te reproduceren + description: Hoe kunnen we dit reproduceren? + placeholder: | + 1. Ga naar ... + 2. Klik op ... + 3. Zie foutmelding + validations: + required: true + + - type: textarea + id: expected + attributes: + label: Verwacht gedrag + description: Wat zou er moeten gebeuren? + validations: + required: true + + - type: textarea + id: logs + attributes: + label: Logs / Foutmeldingen + description: Plak hier relevante logs of foutmeldingen (Home Assistant logboek, browser console, etc.) + render: text + + - type: checkboxes + id: checklist + attributes: + label: Checklist + options: + - label: Ik heb bestaande issues doorzocht en dit is geen duplicaat + required: true + - label: Ik gebruik de laatste versie + required: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..63a51aa --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,45 @@ +name: Feature Request +description: Stel een nieuwe feature of verbetering voor +labels: ["enhancement"] +body: + - type: markdown + attributes: + value: | + Bedankt voor je suggestie! Beschrijf zo duidelijk mogelijk wat je wilt. + + - type: textarea + id: problem + attributes: + label: Welk probleem lost dit op? + description: Beschrijf het probleem of de behoefte die aanleiding geeft tot dit verzoek. + placeholder: "Als gebruiker wil ik ... zodat ..." + validations: + required: true + + - type: textarea + id: solution + attributes: + label: Voorgestelde oplossing + description: Hoe zou jij dit implementeren? + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Overwogen alternatieven + description: Heb je andere oplossingen overwogen? + + - type: textarea + id: context + attributes: + label: Extra context + description: Voeg eventuele extra context, screenshots of voorbeelden toe. + + - type: checkboxes + id: checklist + attributes: + label: Checklist + options: + - label: Ik heb bestaande issues doorzocht en dit is geen duplicaat + required: true diff --git a/.github/labeler.yml b/.github/labeler.yml index ba646e2..78df997 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,12 +1,23 @@ bug: - - "error" - - "fail" -feature: - - "feature request" - - "enhancement" + - '(?i)(bug|fout|error|exception|traceback|crash|not working|werkt niet|kapot|broken|failing|AttributeError|ValueError|TypeError|KeyError|ImportError|does not work|stopped working|niet meer)' + +enhancement: + - '(?i)(feature|enhancement|feature request|verbeter|toevoeg|add support|support for|zou het mogelijk|request|wish|wens|suggestie|suggestion|could you|can you add)' + +question: + - '(?i)(question|vraag|how to|hoe|how do|what is|wat is|help|uitleg|explain|why|waarom|where|where can|confused|understand)' + documentation: - - "docs" - - "documentation" -maintenance: - - "dependabot" + - '(?i)(docs|documentation|readme|example|voorbeeld|uitleg|wiki|manual|how to configure|guide)' + +configuration: + - '(?i)(config|configuratie|setup|install|yaml|options|settings|instell|configure|option|parameter)' + +performance: + - '(?i)(slow|traag|performance|memory|geheugen|cpu|hang|freeze|timeout|lagging|delayed|vertraging)' + +"home assistant": + - '(?i)(home assistant|hass|HA \d+\.\d+|homeassistant|core \d+\.\d+)' +dependencies: + - '(?i)(dependency|afhankelijkh|requirement|package|pip|version incompatible|requires|needs version)' diff --git a/.github/labels.yml b/.github/labels.yml new file mode 100644 index 0000000..d259de0 --- /dev/null +++ b/.github/labels.yml @@ -0,0 +1,52 @@ +# GitHub Labels β€” gesynchroniseerd via sync-labels.yml workflow +- name: bug + color: "d73a4a" + description: "Iets werkt niet zoals verwacht" + +- name: enhancement + color: "a2eeef" + description: "Nieuwe feature of verbetering" + +- name: question + color: "d876e3" + description: "Meer informatie nodig" + +- name: documentation + color: "0075ca" + description: "Verbetering of aanvulling op documentatie" + +- name: configuration + color: "e4e669" + description: "Configuratie of setup gerelateerd" + +- name: performance + color: "f9d0c4" + description: "Performance of resource gebruik" + +- name: dependencies + color: "0366d6" + description: "Afhankelijkheden bijwerken" + +- name: duplicate + color: "cfd3d7" + description: "Dit issue bestaat al" + +- name: wontfix + color: "ffffff" + description: "Wordt niet opgelost" + +- name: "good first issue" + color: "7057ff" + description: "Goed voor nieuwe bijdragers" + +- name: "help wanted" + color: "008672" + description: "Extra aandacht of hulp gewenst" + +- name: stale + color: "ededed" + description: "Geen recente activiteit" + +- name: "breaking change" + color: "e11d48" + description: "Bevat een breaking change" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 909eebd..000b7cd 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,33 +1,22 @@ -## πŸ“ What’s Changed? +## Beschrijving - -- ... + -## πŸ” Why is this Change Needed? +## Type wijziging - -- ... +- [ ] `fix:` Bug fix (patch versie bump) +- [ ] `feat:` Nieuwe feature (minor versie bump) +- [ ] `feat!:` / `BREAKING CHANGE:` Breaking change (major versie bump) +- [ ] `chore:` / `docs:` / `ci:` Onderhoud of documentatie (geen versie bump) -## πŸ§ͺ How Was This Tested? +## Checklist - -- [ ] Added or updated unit tests -- [ ] Manually tested in development environment -- [ ] CI/CD pipeline passed successfully +- [ ] Commit title volgt [Conventional Commits](https://www.conventionalcommits.org/) (`feat:`, `fix:`, `chore:`, etc.) +- [ ] Tests toegevoegd of bijgewerkt waar van toepassing +- [ ] Documentatie bijgewerkt indien nodig +- [ ] CI is groen +- [ ] PR is gericht op de `dev` branch (niet `main`, tenzij hotfix) -## βœ… Checklist +## Screenshots / Logs (optioneel) -- [ ] Code follows the style guide -- [ ] All tests are passing -- [ ] Documentation updated if needed -- [ ] No breaking changes (or clearly documented) - -## πŸ“Έ Screenshots / Logs (Optional) - - -_(e.g., Home Assistant UI, terminal output, etc.)_ - -## πŸ“Ž Additional Notes - - -- ... + diff --git a/.github/workflows/bump-version.yml b/.github/workflows/bump-version.yml new file mode 100644 index 0000000..f00eb7f --- /dev/null +++ b/.github/workflows/bump-version.yml @@ -0,0 +1,51 @@ +name: Bump Version + +on: + workflow_dispatch: + inputs: + bump: + description: "Type versie bump" + type: choice + options: [patch, minor, major] + default: patch + required: true + +permissions: + contents: write + +jobs: + bump: + name: Bump ${{ inputs.bump }} version + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: main + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install bump-my-version + run: pip install bump-my-version + + - name: Configure git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Bump version + run: bump-my-version bump ${{ inputs.bump }} + + - name: Push commit and tag + run: | + git push origin main + git push origin --tags + + - name: Show new version + run: | + NEW_TAG=$(git describe --tags --abbrev=0) + echo "Nieuwe versie: $NEW_TAG" + echo "### Versie gebumpt naar $NEW_TAG" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..68125c5 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,75 @@ +name: CI + +on: + push: + branches: ["dev", "feature/**", "fix/**", "hotfix/**"] + tags-ignore: ["**"] + pull_request: + branches: [dev, main] + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint: + name: Lint & pre-commit + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install pre-commit + run: pip install pre-commit + + - name: Run pre-commit + run: pre-commit run --all-files + + test: + name: Test (Python ${{ matrix.python-version }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.12", "3.13"] + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: pip + + - name: Install dependencies + run: pip install -r requirements.txt + + - name: Run pytest + run: pytest --cov=custom_components --cov-report=xml -q + + - name: Upload coverage + uses: codecov/codecov-action@v5 + if: matrix.python-version == '3.12' + with: + files: ./coverage.xml + fail_ci_if_error: false + + hacs: + name: HACS validation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: hacs/action@main + with: + category: integration + + hassfest: + name: Home Assistant hassfest + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: home-assistant/actions/hassfest@master diff --git a/.github/workflows/hacs.yml b/.github/workflows/hacs.yml deleted file mode 100644 index bb82ed0..0000000 --- a/.github/workflows/hacs.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: HACS - -on: - push: - branches: - - main - release: - types: [published] - schedule: - - cron: "0 0 * * *" - -permissions: - contents: read - -jobs: - validate-hacs: - name: "HACS" - runs-on: ubuntu-latest - steps: - - name: HACS Validation - uses: hacs/action@main - with: - token: ${{ secrets.GITHUB_TOKEN }} - category: "integration" - diff --git a/.github/workflows/hassfest.yml b/.github/workflows/hassfest.yml deleted file mode 100644 index e261734..0000000 --- a/.github/workflows/hassfest.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Hassfest - -on: - schedule: - - cron: "0 0 * * *" - push: - branches: - - main - - dev - pull_request: - branches: - - dev - -permissions: - contents: read - -jobs: - hassfest: - name: "Hassfest" - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v6 - - name: Run hassfest - uses: home-assistant/actions/hassfest@master diff --git a/.github/workflows/label-issues.yml b/.github/workflows/label-issues.yml index ae6d9ec..b2f2761 100644 --- a/.github/workflows/label-issues.yml +++ b/.github/workflows/label-issues.yml @@ -1,19 +1,20 @@ name: Label issues + on: issues: - types: - - reopened - - opened - - edited + types: [opened, reopened, edited] + +permissions: + issues: write + jobs: label_issues: - name: "Automatically Label Issues" + name: Automatically label issues runs-on: ubuntu-latest - permissions: - issues: write steps: - uses: github/issue-labeler@v3.4 with: repo-token: ${{ secrets.GITHUB_TOKEN }} configuration-path: .github/labeler.yml - + enable-versioned-regex: 0 + include-title: 1 diff --git a/.github/workflows/precommit.yml b/.github/workflows/precommit.yml deleted file mode 100644 index 9dfe140..0000000 --- a/.github/workflows/precommit.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: Run Code Quality Check - -permissions: - contents: write - -on: - push: - branches: - - dev - - main - pull_request: - branches: - - dev - - main - workflow_dispatch: - -jobs: - test: - name: "Code Quality Check" - env: - PYTHONPATH: . - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: "3.12" - cache: 'pip' # caching pip dependencies - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - pip install pre-commit - - - name: Run pre-commit hooks - run: | - # Pre-commit exits with code 1 when it makes changes. We don't want - # the workflow to fail in that case, so ignore the exit code. - pre-commit run --all-files || true - - - name: Commit and push changes - if: success() - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - git add -A - if git diff --cached --quiet; then - echo "No changes to commit" - else - git commit -m "chore: apply pre-commit fixes" - BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME}}" - git push origin "HEAD:${BRANCH}" - fi diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml deleted file mode 100644 index cc17793..0000000 --- a/.github/workflows/pytest.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Run Pytest - -on: - push: - branches: - - dev - - main - pull_request: - branches: - - dev - - main - workflow_dispatch: - -permissions: - contents: read - -jobs: - test: - name: "Pytest" - env: - PYTHONPATH: . - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: "3.12" - cache: 'pip' # caching pip dependencies - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - - - name: Run tests - run: pytest --maxfail=1 --disable-warnings -q diff --git a/.github/workflows/release-versioning.yml b/.github/workflows/release-versioning.yml deleted file mode 100644 index f5e97d9..0000000 --- a/.github/workflows/release-versioning.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: Release Versioning - -on: - # Trigger bij push van een tag vX.Y.Z - push: - tags: - - 'v*.*.*' - # Trigger zodra je in de GitHub UI een Release publiceert - release: - types: [published] - -permissions: - contents: write - -jobs: - bump-release: - # Zorg dat we alleen in deze job de tag-push afhandelen - if: startsWith(github.ref, 'refs/tags/v') - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v6 - with: - fetch-depth: 0 - ref: main - - - name: Setup Python - uses: actions/setup-python@v6 - with: - python-version: '3.x' - - - name: Install bump2version - run: pip install bump2version - - - name: Bump version in manifest.json - # Gebruik --no-tag zodat we alleen het bestand bumpen voor de release - run: bump2version patch --allow-dirty --no-tag - - - name: Commit & Push bumped files - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - git add custom_components/simple_pid_controller/manifest.json setup.cfg - git commit -m "chore: bump to next version after release ${{ github.ref_name }}" - git push origin HEAD:main - - publish-release: - # Deze job draait na het aanmaken van de GitHub Release (event β€˜published’) - if: github.event_name == 'release' - needs: bump-release - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Create GitHub Release from tag - uses: softprops/action-gh-release@v2 - with: - tag_name: ${{ github.event.release.tag_name }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 75ea114..d3657af 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,32 +1,59 @@ -name: Create release zip +name: Create Release on: - release: - types: [published] + push: + tags: ["v*.*.*"] permissions: contents: write - + jobs: - build-and-upload: + release: + name: Build ZIP and create GitHub Release runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v4 - - name: Get version + - name: Get version from tag id: version - uses: home-assistant/actions/helpers/version@master + run: | + VERSION=${GITHUB_REF_NAME#v} + echo "version=$VERSION" >> $GITHUB_OUTPUT - - name: Patch manifest and zip + - name: Create release ZIP run: | - sed -i 's/v0.0.0/${{ steps.version.outputs.version }}/' custom_components/simple_pid_controller/manifest.json cd custom_components/simple_pid_controller/ zip ../../simple_pid_controller.zip -r ./ - - uses: svenstaro/upload-release-action@master + + - name: Generate changelog + id: changelog + uses: mikepenz/release-changelog-builder-action@v5 + with: + configuration: | + { + "categories": [ + { "title": "## ✨ Nieuwe features", "labels": ["enhancement", "feature"] }, + { "title": "## πŸ› Bug fixes", "labels": ["bug", "fix"] }, + { "title": "## πŸ“š Documentatie", "labels": ["documentation"] }, + { "title": "## πŸ”§ Overig", "labels": [] } + ], + "template": "#{{CHANGELOG}}\n\n**Volledige changelog**: #{{RELEASE_DIFF}}" + } + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - file: ./simple_pid_controller.zip - asset_name: simple_pid_controller.zip - tag: ${{ github.ref }} - overwrite: true + files: simple_pid_controller.zip + body: | + ## Installatie via HACS + Installeer of update via HACS β€” de nieuwe versie wordt automatisch aangeboden. + + ## Handmatige installatie + Download `simple_pid_controller.zip`, pak uit en kopieer `simple_pid_controller/` naar je `custom_components/` map. + + ${{ steps.changelog.outputs.changelog }} + generate_release_notes: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml new file mode 100644 index 0000000..9222110 --- /dev/null +++ b/.github/workflows/sync-labels.yml @@ -0,0 +1,23 @@ +name: Sync Labels + +on: + workflow_dispatch: + push: + paths: [".github/labels.yml"] + branches: [main] + +permissions: + issues: write + +jobs: + sync: + name: Sync repository labels + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: EndBug/label-sync@v2 + with: + config-file: .github/labels.yml + delete-other-labels: false + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/custom_components/simple_pid_controller/manifest.json b/custom_components/simple_pid_controller/manifest.json index 8c0c96d..c0063c8 100644 --- a/custom_components/simple_pid_controller/manifest.json +++ b/custom_components/simple_pid_controller/manifest.json @@ -1,7 +1,9 @@ { "domain": "simple_pid_controller", "name": "Simple PID Controller", - "codeowners": ["@bvweerd"], + "codeowners": [ + "@bvweerd" + ], "config_flow": true, "dependencies": [], "documentation": "https://www.github.com/bvweerd/simple_pid_controller", @@ -9,7 +11,9 @@ "iot_class": "calculated", "issue_tracker": "https://github.com/bvweerd/simple_pid_controller/issues", "quality_scale": "silver", - "requirements": ["simple-pid==2.0.1"], + "requirements": [ + "simple-pid==2.0.1" + ], "ssdp": [], "version": "1.5.2", "zeroconf": [] diff --git a/setup.cfg b/setup.cfg index f2a8522..dfd4e5a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 1.4.3 +current_version = 1.5.2 [coverage:run] source = From ebb457f52193d322e130150de30b972fc21379d4 Mon Sep 17 00:00:00 2001 From: bvweerd Date: Sun, 15 Feb 2026 11:14:26 +0100 Subject: [PATCH 03/24] ci: voeg permissions: contents: read toe aan ci.yml --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 68125c5..ca1bab1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,9 @@ concurrency: group: ci-${{ github.ref }} cancel-in-progress: true +permissions: + contents: read + jobs: lint: name: Lint & pre-commit From 0cfebcb8c975fa3f6fe37d2129b81a8ac22f5986 Mon Sep 17 00:00:00 2001 From: bvweerd Date: Sun, 15 Feb 2026 11:28:34 +0100 Subject: [PATCH 04/24] fix(ci): Python 3.13 als optional matrix, Engelse templates --- .github/ISSUE_TEMPLATE/bug_report.yml | 40 +++++++++++----------- .github/ISSUE_TEMPLATE/feature_request.yml | 24 ++++++------- .github/pull_request_template.md | 28 +++++++-------- .github/workflows/ci.yml | 6 +++- 4 files changed, 51 insertions(+), 47 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index ee457ef..6ad5115 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,60 +1,60 @@ name: Bug Report -description: Meld een bug of onverwacht gedrag +description: Report a bug or unexpected behavior labels: ["bug"] body: - type: markdown attributes: value: | - Bedankt voor het melden van een bug! Vul het formulier zo volledig mogelijk in. + Thanks for reporting a bug! Please fill in the form as completely as possible. - type: input id: version attributes: - label: Versie - description: Welke versie gebruik je? - placeholder: "bijv. 1.2.3" + label: Version + description: Which version are you using? + placeholder: "e.g. 1.2.3" validations: required: true - type: input id: ha_version attributes: - label: Home Assistant versie (indien van toepassing) - placeholder: "bijv. 2025.2.0" + label: Home Assistant version (if applicable) + placeholder: "e.g. 2025.2.0" - type: textarea id: description attributes: - label: Beschrijving van de bug - description: Wat gaat er mis? Wees zo specifiek mogelijk. + label: Bug description + description: What goes wrong? Be as specific as possible. validations: required: true - type: textarea id: steps attributes: - label: Stappen om te reproduceren - description: Hoe kunnen we dit reproduceren? + label: Steps to reproduce + description: How can we reproduce this? placeholder: | - 1. Ga naar ... - 2. Klik op ... - 3. Zie foutmelding + 1. Go to ... + 2. Click on ... + 3. See error validations: required: true - type: textarea id: expected attributes: - label: Verwacht gedrag - description: Wat zou er moeten gebeuren? + label: Expected behavior + description: What should happen instead? validations: required: true - type: textarea id: logs attributes: - label: Logs / Foutmeldingen - description: Plak hier relevante logs of foutmeldingen (Home Assistant logboek, browser console, etc.) + label: Logs / Error messages + description: Paste relevant logs or error messages (Home Assistant log, browser console, etc.) render: text - type: checkboxes @@ -62,7 +62,7 @@ body: attributes: label: Checklist options: - - label: Ik heb bestaande issues doorzocht en dit is geen duplicaat + - label: I have searched existing issues and this is not a duplicate required: true - - label: Ik gebruik de laatste versie + - label: I am using the latest version required: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 63a51aa..f48bfdd 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -1,45 +1,45 @@ name: Feature Request -description: Stel een nieuwe feature of verbetering voor +description: Suggest a new feature or improvement labels: ["enhancement"] body: - type: markdown attributes: value: | - Bedankt voor je suggestie! Beschrijf zo duidelijk mogelijk wat je wilt. + Thanks for your suggestion! Please describe your request as clearly as possible. - type: textarea id: problem attributes: - label: Welk probleem lost dit op? - description: Beschrijf het probleem of de behoefte die aanleiding geeft tot dit verzoek. - placeholder: "Als gebruiker wil ik ... zodat ..." + label: What problem does this solve? + description: Describe the problem or need that motivates this request. + placeholder: "As a user I want to ... so that ..." validations: required: true - type: textarea id: solution attributes: - label: Voorgestelde oplossing - description: Hoe zou jij dit implementeren? + label: Proposed solution + description: How would you implement this? validations: required: true - type: textarea id: alternatives attributes: - label: Overwogen alternatieven - description: Heb je andere oplossingen overwogen? + label: Alternatives considered + description: Have you considered other solutions? - type: textarea id: context attributes: - label: Extra context - description: Voeg eventuele extra context, screenshots of voorbeelden toe. + label: Additional context + description: Add any other context, screenshots, or examples. - type: checkboxes id: checklist attributes: label: Checklist options: - - label: Ik heb bestaande issues doorzocht en dit is geen duplicaat + - label: I have searched existing issues and this is not a duplicate required: true diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 000b7cd..c5d5bc4 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,22 +1,22 @@ -## Beschrijving +## Description - + -## Type wijziging +## Type of change -- [ ] `fix:` Bug fix (patch versie bump) -- [ ] `feat:` Nieuwe feature (minor versie bump) -- [ ] `feat!:` / `BREAKING CHANGE:` Breaking change (major versie bump) -- [ ] `chore:` / `docs:` / `ci:` Onderhoud of documentatie (geen versie bump) +- [ ] `fix:` Bug fix (patch version bump) +- [ ] `feat:` New feature (minor version bump) +- [ ] `feat!:` / `BREAKING CHANGE:` Breaking change (major version bump) +- [ ] `chore:` / `docs:` / `ci:` Maintenance or documentation (no version bump) ## Checklist -- [ ] Commit title volgt [Conventional Commits](https://www.conventionalcommits.org/) (`feat:`, `fix:`, `chore:`, etc.) -- [ ] Tests toegevoegd of bijgewerkt waar van toepassing -- [ ] Documentatie bijgewerkt indien nodig -- [ ] CI is groen -- [ ] PR is gericht op de `dev` branch (niet `main`, tenzij hotfix) +- [ ] Commit title follows [Conventional Commits](https://www.conventionalcommits.org/) (`feat:`, `fix:`, `chore:`, etc.) +- [ ] Tests added or updated where applicable +- [ ] Documentation updated if needed +- [ ] CI is green +- [ ] PR targets the `dev` branch (not `main`, unless this is a hotfix) -## Screenshots / Logs (optioneel) +## Screenshots / Logs (optional) - + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ca1bab1..e25a48f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,7 +37,11 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.12", "3.13"] + include: + - python-version: "3.12" + - python-version: "3.13" + continue-on-error: true + continue-on-error: ${{ matrix.continue-on-error == true }} steps: - uses: actions/checkout@v4 From adf81cc221db092756d41d3b39747e64b1187d79 Mon Sep 17 00:00:00 2001 From: bvweerd Date: Sun, 15 Feb 2026 11:38:31 +0100 Subject: [PATCH 05/24] fix(ci): rewrite stale.yml in English Co-Authored-By: Claude Sonnet 4.5 --- .github/workflows/stale.yml | 42 ++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index edbe8de..ca00c61 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -2,7 +2,6 @@ name: Mark & close stale issues/PRs on: schedule: - # Dagelijks om 02:17 UTC - cron: "17 2 * * *" workflow_dispatch: @@ -16,42 +15,37 @@ jobs: steps: - uses: actions/stale@v10 with: - # ALGEMEEN repo-token: ${{ secrets.GITHUB_TOKEN }} operations-per-run: 200 - days-before-stale: 7 # Issues worden 'stale' na 60 dagen inactiviteit - days-before-close: 14 # en gesloten 14 dagen later + days-before-stale: 60 + days-before-close: 14 stale-issue-label: "stale" stale-pr-label: "stale" exempt-issue-labels: "pinned,security,backlog,never-stale" exempt-pr-labels: "work-in-progress,never-stale" - exempt-all-milestones: true # Items met milestone overslaan - exempt-assignees: "" # Vul evt. gebruikers in, kommagescheiden + exempt-all-milestones: true remove-stale-when-updated: true - ignore-updates: false # Als iemand reageert of labelt, wordt 'stale' verwijderd + ignore-updates: false ascending: false - # ISSUES stale-issue-message: | - πŸ’€ Deze issue heeft 60 dagen geen activiteit gehad en is gemarkeerd als **stale**. - Als er binnen 14 dagen geen nieuwe activiteit is, wordt deze automatisch gesloten. - Voeg svp een update toe of label met `never-stale` om dit te voorkomen. + This issue has been inactive for 60 days and is marked as **stale**. + If there is no new activity within 14 days it will be closed automatically. + Please add an update or label with `never-stale` to keep it open. close-issue-message: | - πŸ”’ Deze issue is automatisch gesloten wegens inactiviteit. - Als dit nog steeds actueel is, heropen of maak een nieuwe issue met de laatste context. Bedankt! + This issue was automatically closed due to inactivity. + If still relevant, please reopen or create a new issue with updated context. - # PULL REQUESTS - days-before-pr-stale: 30 # PRs iets sneller stale + days-before-pr-stale: 30 days-before-pr-close: 10 stale-pr-message: | - πŸ’€ Deze pull request is 30 dagen inactief en is gemarkeerd als **stale**. - Reageer of push nieuwe commits binnen 10 dagen om sluiten te voorkomen. - Label met `never-stale` om uit te sluiten. + This pull request has been inactive for 30 days and is marked as **stale**. + Please respond or push new commits within 10 days to prevent closing. + Label with `never-stale` to exclude. close-pr-message: | - πŸ”’ Deze pull request is automatisch gesloten wegens inactiviteit. - Heropen gerust wanneer je verder wilt gaan. + This pull request was automatically closed due to inactivity. + Feel free to reopen when you are ready to continue. - # FILTERS (optioneel; laat leeg om alles te laten meedraaien) - only-labels: "" # Bv. "triage" om alleen issues met dat label te targeten - any-of-labels: "" # Bv. "question,help wanted" - exempt-draft-pr: true # Draft PRs overslaan + only-labels: "" + any-of-labels: "" + exempt-draft-pr: true From 42c992f2e82b38b524b67f96431420287db665a0 Mon Sep 17 00:00:00 2001 From: bvweerd Date: Sun, 15 Feb 2026 13:37:52 +0100 Subject: [PATCH 06/24] chore(ci): drop Python 3.12, test on 3.13 only HA 2025+ requires Python 3.13 minimum; testing on 3.12 is no longer needed. Co-Authored-By: Claude Sonnet 4.5 --- .github/workflows/ci.yml | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e25a48f..d8cc436 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: "3.12" + python-version: "3.13" - name: Install pre-commit run: pip install pre-commit @@ -32,22 +32,14 @@ jobs: run: pre-commit run --all-files test: - name: Test (Python ${{ matrix.python-version }}) + name: Test (Python 3.13) runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - include: - - python-version: "3.12" - - python-version: "3.13" - continue-on-error: true - continue-on-error: ${{ matrix.continue-on-error == true }} steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - python-version: ${{ matrix.python-version }} + python-version: "3.13" cache: pip - name: Install dependencies @@ -58,7 +50,6 @@ jobs: - name: Upload coverage uses: codecov/codecov-action@v5 - if: matrix.python-version == '3.12' with: files: ./coverage.xml fail_ci_if_error: false From 273b740f7c7075f911b8378dee95e3cb9840254c Mon Sep 17 00:00:00 2001 From: bvweerd Date: Sun, 15 Feb 2026 13:45:14 +0100 Subject: [PATCH 07/24] chore(ci): update all workflows to Python 3.13 Co-Authored-By: Claude Sonnet 4.5 --- .github/workflows/bump-version.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/bump-version.yml b/.github/workflows/bump-version.yml index f00eb7f..44c88aa 100644 --- a/.github/workflows/bump-version.yml +++ b/.github/workflows/bump-version.yml @@ -26,7 +26,7 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: "3.12" + python-version: "3.13" - name: Install bump-my-version run: pip install bump-my-version From 888109fc986495b4ba30243f09cec9c38bc18e32 Mon Sep 17 00:00:00 2001 From: bvweerd Date: Sun, 15 Feb 2026 18:20:19 +0100 Subject: [PATCH 08/24] pytest fix --- tests/test_select.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_select.py b/tests/test_select.py index 251d940..a6438d6 100644 --- a/tests/test_select.py +++ b/tests/test_select.py @@ -22,7 +22,7 @@ async def test_pid_start_modes(hass, config_entry): for start_mode in ["Zero start", "Startup value", "Last known value"]: # reset de PID state per iteratie handle = config_entry.runtime_data.handle - handle.init_phase = True + handle.pid.set_auto_mode(False) handle.last_known_output = 80.0 handle.get_input_sensor_value = lambda: base_input From 0014e1bddf1a8644de4f2fd182b1e66507fd8c6a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Feb 2026 07:36:32 +0000 Subject: [PATCH 09/24] ci: bump actions/setup-python from 5 to 6 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5 to 6. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/setup-python dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/bump-version.yml | 2 +- .github/workflows/ci.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/bump-version.yml b/.github/workflows/bump-version.yml index 44c88aa..6dca28f 100644 --- a/.github/workflows/bump-version.yml +++ b/.github/workflows/bump-version.yml @@ -24,7 +24,7 @@ jobs: fetch-depth: 0 token: ${{ secrets.GITHUB_TOKEN }} - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: python-version: "3.13" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d8cc436..12d6361 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: python-version: "3.13" @@ -37,7 +37,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: python-version: "3.13" cache: pip From adda264175423ce9820593fdb5b03870728c38d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Feb 2026 07:36:36 +0000 Subject: [PATCH 10/24] ci: bump mikepenz/release-changelog-builder-action from 5 to 6 Bumps [mikepenz/release-changelog-builder-action](https://github.com/mikepenz/release-changelog-builder-action) from 5 to 6. - [Release notes](https://github.com/mikepenz/release-changelog-builder-action/releases) - [Commits](https://github.com/mikepenz/release-changelog-builder-action/compare/v5...v6) --- updated-dependencies: - dependency-name: mikepenz/release-changelog-builder-action dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d3657af..0016e9f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,7 +27,7 @@ jobs: - name: Generate changelog id: changelog - uses: mikepenz/release-changelog-builder-action@v5 + uses: mikepenz/release-changelog-builder-action@v6 with: configuration: | { From 7deed9dc8518cdff7c670b1e1af42832d1206be7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Feb 2026 07:36:43 +0000 Subject: [PATCH 11/24] ci: bump actions/checkout from 4 to 6 Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/bump-version.yml | 2 +- .github/workflows/ci.yml | 8 ++++---- .github/workflows/release.yml | 2 +- .github/workflows/sync-labels.yml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/bump-version.yml b/.github/workflows/bump-version.yml index 44c88aa..85d253f 100644 --- a/.github/workflows/bump-version.yml +++ b/.github/workflows/bump-version.yml @@ -18,7 +18,7 @@ jobs: name: Bump ${{ inputs.bump }} version runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: ref: main fetch-depth: 0 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d8cc436..44555b8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: name: Lint & pre-commit runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: actions/setup-python@v5 with: @@ -35,7 +35,7 @@ jobs: name: Test (Python 3.13) runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: actions/setup-python@v5 with: @@ -58,7 +58,7 @@ jobs: name: HACS validation runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: hacs/action@main with: @@ -68,6 +68,6 @@ jobs: name: Home Assistant hassfest runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: home-assistant/actions/hassfest@master diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d3657af..51eaf8a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: name: Build ZIP and create GitHub Release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Get version from tag id: version diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index 9222110..edb12b1 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -14,7 +14,7 @@ jobs: name: Sync repository labels runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: EndBug/label-sync@v2 with: From fc33473df22144af666c4ef82d1f6ef7c3bafdb6 Mon Sep 17 00:00:00 2001 From: bvweerd Date: Sat, 28 Feb 2026 18:36:54 +0100 Subject: [PATCH 12/24] Translate GitHub configuration files to English Co-Authored-By: Claude Sonnet 4.6 --- .github/labeler.yml | 14 +++++++------- .github/labels.yml | 28 ++++++++++++++-------------- .github/workflows/release.yml | 16 ++++++++-------- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index 78df997..db61a02 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,23 +1,23 @@ bug: - - '(?i)(bug|fout|error|exception|traceback|crash|not working|werkt niet|kapot|broken|failing|AttributeError|ValueError|TypeError|KeyError|ImportError|does not work|stopped working|niet meer)' + - '(?i)(bug|error|exception|traceback|crash|not working|broken|failing|AttributeError|ValueError|TypeError|KeyError|ImportError|does not work|stopped working)' enhancement: - - '(?i)(feature|enhancement|feature request|verbeter|toevoeg|add support|support for|zou het mogelijk|request|wish|wens|suggestie|suggestion|could you|can you add)' + - '(?i)(feature|enhancement|feature request|add support|support for|request|wish|suggestion|could you|can you add)' question: - - '(?i)(question|vraag|how to|hoe|how do|what is|wat is|help|uitleg|explain|why|waarom|where|where can|confused|understand)' + - '(?i)(question|how to|how do|what is|help|explain|why|where|where can|confused|understand)' documentation: - - '(?i)(docs|documentation|readme|example|voorbeeld|uitleg|wiki|manual|how to configure|guide)' + - '(?i)(docs|documentation|readme|example|wiki|manual|how to configure|guide)' configuration: - - '(?i)(config|configuratie|setup|install|yaml|options|settings|instell|configure|option|parameter)' + - '(?i)(config|setup|install|yaml|options|settings|configure|option|parameter)' performance: - - '(?i)(slow|traag|performance|memory|geheugen|cpu|hang|freeze|timeout|lagging|delayed|vertraging)' + - '(?i)(slow|performance|memory|cpu|hang|freeze|timeout|lagging|delayed)' "home assistant": - '(?i)(home assistant|hass|HA \d+\.\d+|homeassistant|core \d+\.\d+)' dependencies: - - '(?i)(dependency|afhankelijkh|requirement|package|pip|version incompatible|requires|needs version)' + - '(?i)(dependency|requirement|package|pip|version incompatible|requires|needs version)' diff --git a/.github/labels.yml b/.github/labels.yml index d259de0..14d1f69 100644 --- a/.github/labels.yml +++ b/.github/labels.yml @@ -1,52 +1,52 @@ -# GitHub Labels β€” gesynchroniseerd via sync-labels.yml workflow +# GitHub Labels β€” synced via sync-labels.yml workflow - name: bug color: "d73a4a" - description: "Iets werkt niet zoals verwacht" + description: "Something isn't working as expected" - name: enhancement color: "a2eeef" - description: "Nieuwe feature of verbetering" + description: "New feature or improvement" - name: question color: "d876e3" - description: "Meer informatie nodig" + description: "More information needed" - name: documentation color: "0075ca" - description: "Verbetering of aanvulling op documentatie" + description: "Improvement or addition to documentation" - name: configuration color: "e4e669" - description: "Configuratie of setup gerelateerd" + description: "Configuration or setup related" - name: performance color: "f9d0c4" - description: "Performance of resource gebruik" + description: "Performance or resource usage" - name: dependencies color: "0366d6" - description: "Afhankelijkheden bijwerken" + description: "Update dependencies" - name: duplicate color: "cfd3d7" - description: "Dit issue bestaat al" + description: "This issue already exists" - name: wontfix color: "ffffff" - description: "Wordt niet opgelost" + description: "Will not be fixed" - name: "good first issue" color: "7057ff" - description: "Goed voor nieuwe bijdragers" + description: "Good for new contributors" - name: "help wanted" color: "008672" - description: "Extra aandacht of hulp gewenst" + description: "Extra attention or help wanted" - name: stale color: "ededed" - description: "Geen recente activiteit" + description: "No recent activity" - name: "breaking change" color: "e11d48" - description: "Bevat een breaking change" + description: "Contains a breaking change" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e5a1015..6886933 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,12 +32,12 @@ jobs: configuration: | { "categories": [ - { "title": "## ✨ Nieuwe features", "labels": ["enhancement", "feature"] }, + { "title": "## ✨ New features", "labels": ["enhancement", "feature"] }, { "title": "## πŸ› Bug fixes", "labels": ["bug", "fix"] }, - { "title": "## πŸ“š Documentatie", "labels": ["documentation"] }, - { "title": "## πŸ”§ Overig", "labels": [] } + { "title": "## πŸ“š Documentation", "labels": ["documentation"] }, + { "title": "## πŸ”§ Other", "labels": [] } ], - "template": "#{{CHANGELOG}}\n\n**Volledige changelog**: #{{RELEASE_DIFF}}" + "template": "#{{CHANGELOG}}\n\n**Full changelog**: #{{RELEASE_DIFF}}" } env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -47,11 +47,11 @@ jobs: with: files: simple_pid_controller.zip body: | - ## Installatie via HACS - Installeer of update via HACS β€” de nieuwe versie wordt automatisch aangeboden. + ## Installation via HACS + Install or update via HACS β€” the new version will be offered automatically. - ## Handmatige installatie - Download `simple_pid_controller.zip`, pak uit en kopieer `simple_pid_controller/` naar je `custom_components/` map. + ## Manual installation + Download `simple_pid_controller.zip`, extract and copy `simple_pid_controller/` to your `custom_components/` directory. ${{ steps.changelog.outputs.changelog }} generate_release_notes: false From fec043e4183ddd056adcb57bf03f8074d510c641 Mon Sep 17 00:00:00 2001 From: bvweerd Date: Sat, 28 Feb 2026 18:58:05 +0100 Subject: [PATCH 13/24] Translate bump-version workflow to English Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/bump-version.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/bump-version.yml b/.github/workflows/bump-version.yml index f3f6f52..90d3c4b 100644 --- a/.github/workflows/bump-version.yml +++ b/.github/workflows/bump-version.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: inputs: bump: - description: "Type versie bump" + description: "Version bump type" type: choice options: [patch, minor, major] default: patch @@ -47,5 +47,5 @@ jobs: - name: Show new version run: | NEW_TAG=$(git describe --tags --abbrev=0) - echo "Nieuwe versie: $NEW_TAG" - echo "### Versie gebumpt naar $NEW_TAG" >> $GITHUB_STEP_SUMMARY + echo "Version bumped to $NEW_TAG" + echo "### Version bumped to $NEW_TAG" >> $GITHUB_STEP_SUMMARY From 63f0de8e8ab796b45c36fb27f402913096bed929 Mon Sep 17 00:00:00 2001 From: bvweerd Date: Sun, 22 Mar 2026 17:58:06 +0100 Subject: [PATCH 14/24] added brands to correct dir --- {assets => brand}/dark_icon.png | Bin {assets => brand}/dark_icon@2x.png | Bin {assets => brand}/dark_logo.png | Bin {assets => brand}/dark_logo@2x.png | Bin {assets => brand}/icon.png | Bin {assets => brand}/icon@2x.png | Bin {assets => brand}/logo.png | Bin {assets => brand}/logo@2x.png | Bin 8 files changed, 0 insertions(+), 0 deletions(-) rename {assets => brand}/dark_icon.png (100%) rename {assets => brand}/dark_icon@2x.png (100%) rename {assets => brand}/dark_logo.png (100%) rename {assets => brand}/dark_logo@2x.png (100%) rename {assets => brand}/icon.png (100%) rename {assets => brand}/icon@2x.png (100%) rename {assets => brand}/logo.png (100%) rename {assets => brand}/logo@2x.png (100%) diff --git a/assets/dark_icon.png b/brand/dark_icon.png similarity index 100% rename from assets/dark_icon.png rename to brand/dark_icon.png diff --git a/assets/dark_icon@2x.png b/brand/dark_icon@2x.png similarity index 100% rename from assets/dark_icon@2x.png rename to brand/dark_icon@2x.png diff --git a/assets/dark_logo.png b/brand/dark_logo.png similarity index 100% rename from assets/dark_logo.png rename to brand/dark_logo.png diff --git a/assets/dark_logo@2x.png b/brand/dark_logo@2x.png similarity index 100% rename from assets/dark_logo@2x.png rename to brand/dark_logo@2x.png diff --git a/assets/icon.png b/brand/icon.png similarity index 100% rename from assets/icon.png rename to brand/icon.png diff --git a/assets/icon@2x.png b/brand/icon@2x.png similarity index 100% rename from assets/icon@2x.png rename to brand/icon@2x.png diff --git a/assets/logo.png b/brand/logo.png similarity index 100% rename from assets/logo.png rename to brand/logo.png diff --git a/assets/logo@2x.png b/brand/logo@2x.png similarity index 100% rename from assets/logo@2x.png rename to brand/logo@2x.png From a7cd16e367efb3ab11f3eb38206823e2bdbcd39c Mon Sep 17 00:00:00 2001 From: bvweerd Date: Sun, 22 Mar 2026 18:29:24 +0100 Subject: [PATCH 15/24] moved brands dir --- .../simple_pid_controller/brand}/dark_icon.png | Bin .../simple_pid_controller/brand}/dark_icon@2x.png | Bin .../simple_pid_controller/brand}/dark_logo.png | Bin .../simple_pid_controller/brand}/dark_logo@2x.png | Bin .../simple_pid_controller/brand}/icon.png | Bin .../simple_pid_controller/brand}/icon@2x.png | Bin .../simple_pid_controller/brand}/logo.png | Bin .../simple_pid_controller/brand}/logo@2x.png | Bin 8 files changed, 0 insertions(+), 0 deletions(-) rename {brand => custom_components/simple_pid_controller/brand}/dark_icon.png (100%) rename {brand => custom_components/simple_pid_controller/brand}/dark_icon@2x.png (100%) rename {brand => custom_components/simple_pid_controller/brand}/dark_logo.png (100%) rename {brand => custom_components/simple_pid_controller/brand}/dark_logo@2x.png (100%) rename {brand => custom_components/simple_pid_controller/brand}/icon.png (100%) rename {brand => custom_components/simple_pid_controller/brand}/icon@2x.png (100%) rename {brand => custom_components/simple_pid_controller/brand}/logo.png (100%) rename {brand => custom_components/simple_pid_controller/brand}/logo@2x.png (100%) diff --git a/brand/dark_icon.png b/custom_components/simple_pid_controller/brand/dark_icon.png similarity index 100% rename from brand/dark_icon.png rename to custom_components/simple_pid_controller/brand/dark_icon.png diff --git a/brand/dark_icon@2x.png b/custom_components/simple_pid_controller/brand/dark_icon@2x.png similarity index 100% rename from brand/dark_icon@2x.png rename to custom_components/simple_pid_controller/brand/dark_icon@2x.png diff --git a/brand/dark_logo.png b/custom_components/simple_pid_controller/brand/dark_logo.png similarity index 100% rename from brand/dark_logo.png rename to custom_components/simple_pid_controller/brand/dark_logo.png diff --git a/brand/dark_logo@2x.png b/custom_components/simple_pid_controller/brand/dark_logo@2x.png similarity index 100% rename from brand/dark_logo@2x.png rename to custom_components/simple_pid_controller/brand/dark_logo@2x.png diff --git a/brand/icon.png b/custom_components/simple_pid_controller/brand/icon.png similarity index 100% rename from brand/icon.png rename to custom_components/simple_pid_controller/brand/icon.png diff --git a/brand/icon@2x.png b/custom_components/simple_pid_controller/brand/icon@2x.png similarity index 100% rename from brand/icon@2x.png rename to custom_components/simple_pid_controller/brand/icon@2x.png diff --git a/brand/logo.png b/custom_components/simple_pid_controller/brand/logo.png similarity index 100% rename from brand/logo.png rename to custom_components/simple_pid_controller/brand/logo.png diff --git a/brand/logo@2x.png b/custom_components/simple_pid_controller/brand/logo@2x.png similarity index 100% rename from brand/logo@2x.png rename to custom_components/simple_pid_controller/brand/logo@2x.png From 0b71919baabc61d596f3c25a2182af74789d9f2d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 07:40:26 +0000 Subject: [PATCH 16/24] ci: bump codecov/codecov-action from 5 to 6 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5 to 6. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v5...v6) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aa90228..997f83f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,7 +49,7 @@ jobs: run: pytest --cov=custom_components --cov-report=xml -q - name: Upload coverage - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v6 with: files: ./coverage.xml fail_ci_if_error: false From 92b5045c8709c7811e5568fbbae2ffc2d6343630 Mon Sep 17 00:00:00 2001 From: bvweerd Date: Sat, 11 Apr 2026 14:38:32 +0200 Subject: [PATCH 17/24] Add unit of measurement customization section to README Explains why the PID output has no fixed unit (per HA architecture) and provides two workarounds: customize.yaml and a template sensor. Co-Authored-By: Claude Sonnet 4.6 --- README.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/README.md b/README.md index f3f7170..328294a 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ - [Manual Installation](#manual-installation) - [Removal Instructions](#removal-instructions) - [Configuration](#configuration) +- [Customizing the Unit of Measurement](#customizing-the-unit-of-measurement) - [Entities Overview](#entities-overview) - [PID Tuning Guide](#pid-tuning-guide) - [Manual Tuning](#1-manual-trial--error) @@ -91,6 +92,50 @@ The controller’s setpoint range defaults to **0.0 – 100.0**. To customize th --- +## 🏷️ Customizing the Unit of Measurement + +The PID output sensor has no fixed unit of measurement, because the output value depends entirely on your application (e.g. %, Β°C, A, W). Per Home Assistant architecture, units cannot be configured inside the integration itself β€” instead, use one of the approaches below. + +### Option 1: customize.yaml + +Add a device class and unit to the entity directly. This works for the PID output sensor and for number entities such as `Setpoint`. + +**`configuration.yaml`** +```yaml +homeassistant: + customize: !include customize.yaml +``` + +**`customize.yaml`** +```yaml +sensor.my_pid_controller_pid_output: + device_class: temperature + unit_of_measurement: "Β°C" + +number.my_pid_controller_setpoint: + device_class: temperature + unit_of_measurement: "Β°C" +``` + +> **Note:** Only set `device_class` to a value that matches the physical meaning of the output. Using a wrong device class can affect history graphs and unit conversions. + +### Option 2: Template sensor + +Use a template sensor to wrap the PID output with any unit and label you need. This is useful when you want a clean, named entity without modifying the raw output entity. + +**`configuration.yaml`** (or your `template:` block): +```yaml +template: + - sensor: + - name: "Heater setpoint output" + unit_of_measurement: "Β°C" + device_class: temperature + state_class: measurement + state: "{{ states('sensor.my_pid_controller_pid_output') | float(0) | round(2) }}" +``` + +--- + ## πŸ“Š Entities Overview | Platform | Entity Suffix | Description | From b96dcd1b8ca3472523187e75cc4e79f9891e5112 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 07:47:29 +0000 Subject: [PATCH 18/24] ci: bump softprops/action-gh-release from 2 to 3 Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2 to 3. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/v2...v3) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-version: '3' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6886933..a139f6d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,7 +43,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Create GitHub Release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 with: files: simple_pid_controller.zip body: | From 21992dbcf33597a9c0c3bed709ca3759bf9aa384 Mon Sep 17 00:00:00 2001 From: bvweerd Date: Sun, 26 Apr 2026 20:28:08 +0200 Subject: [PATCH 19/24] ci: uniformize action versions and add missing workflows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - codecov/codecov-action v5 β†’ v6 - softprops/action-gh-release v2 β†’ v3 - add label-prs.yml + pr-labeler.yml Co-Authored-By: Claude Sonnet 4.6 --- .github/pr-labeler.yml | 23 +++++++++++++++++++++++ .github/workflows/label-prs.yml | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 .github/pr-labeler.yml create mode 100644 .github/workflows/label-prs.yml diff --git a/.github/pr-labeler.yml b/.github/pr-labeler.yml new file mode 100644 index 0000000..59972b2 --- /dev/null +++ b/.github/pr-labeler.yml @@ -0,0 +1,23 @@ +bug: + - changed-files: + - any-glob-to-any-file: [] # no file-based bug detection; use issue labels or manual + +enhancement: + - changed-files: + - any-glob-to-any-file: + - custom_components/simple_pid_controller/** + +documentation: + - changed-files: + - any-glob-to-any-file: + - "*.md" + - docs/** + - custom_components/simple_pid_controller/translations/** + - custom_components/simple_pid_controller/strings.json + +dependencies: + - changed-files: + - any-glob-to-any-file: + - requirements*.txt + - custom_components/simple_pid_controller/manifest.json + - setup.cfg diff --git a/.github/workflows/label-prs.yml b/.github/workflows/label-prs.yml new file mode 100644 index 0000000..54030ba --- /dev/null +++ b/.github/workflows/label-prs.yml @@ -0,0 +1,33 @@ +name: Label PRs + +on: + pull_request: + types: [opened, synchronize, reopened] + +permissions: + contents: read + pull-requests: write + +jobs: + label: + name: Automatically label PRs by changed files + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@v6 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + configuration-path: .github/pr-labeler.yml + + - name: Label bug based on PR title + uses: actions/github-script@v9 + with: + script: | + const title = context.payload.pull_request.title.toLowerCase(); + if (/^fix[\s(:!]/.test(title)) { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + labels: ['bug'], + }); + } From 8571a92854022b7e8293d625f036ac9276121aff Mon Sep 17 00:00:00 2001 From: bvweerd Date: Sun, 26 Apr 2026 20:47:28 +0200 Subject: [PATCH 20/24] ci: add commitMode and label_extractor to release changelog Changelog now auto-categorizes based on conventional commit prefixes (feat/fix/docs/ci/chore) instead of requiring PR labels. Moves changelog above installation instructions to match other repos. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/release.yml | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a139f6d..0b0d198 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,14 +29,25 @@ jobs: id: changelog uses: mikepenz/release-changelog-builder-action@v6 with: + commitMode: true configuration: | { + "label_extractor": [ + { "pattern": "^(feat|feature|add)(\\(.+\\))?!?[:\\s]", "target": "feature" }, + { "pattern": "^(fix|bug|bugfix|hotfix)(\\(.+\\))?!?[:\\s]", "target": "bug" }, + { "pattern": "^(docs?|documentation)(\\(.+\\))?[:\\s]", "target": "documentation" }, + { "pattern": "^(ci|github.?actions?)(\\(.+\\))?[:\\s]", "target": "ci" }, + { "pattern": "^(chore|refactor|test|perf|style|build|bump)(\\(.+\\))?[:\\s]", "target": "chore" } + ], "categories": [ - { "title": "## ✨ New features", "labels": ["enhancement", "feature"] }, - { "title": "## πŸ› Bug fixes", "labels": ["bug", "fix"] }, - { "title": "## πŸ“š Documentation", "labels": ["documentation"] }, - { "title": "## πŸ”§ Other", "labels": [] } + { "title": "## ✨ New features", "labels": ["feature", "enhancement"] }, + { "title": "## πŸ› Bug fixes", "labels": ["bug", "fix"] }, + { "title": "## πŸ“š Documentation", "labels": ["documentation"] }, + { "title": "## πŸ”§ Other", "labels": ["chore"] }, + { "title": "## πŸ‘· CI", "labels": ["ci"] }, + { "title": "## πŸ“¦ Uncategorized", "labels": [] } ], + "ignore_labels": ["dependabot"], "template": "#{{CHANGELOG}}\n\n**Full changelog**: #{{RELEASE_DIFF}}" } env: @@ -47,13 +58,15 @@ jobs: with: files: simple_pid_controller.zip body: | + ${{ steps.changelog.outputs.changelog }} + + --- + ## Installation via HACS Install or update via HACS β€” the new version will be offered automatically. ## Manual installation Download `simple_pid_controller.zip`, extract and copy `simple_pid_controller/` to your `custom_components/` directory. - - ${{ steps.changelog.outputs.changelog }} generate_release_notes: false env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 2d767c4c7e940ba639653e83964929d70c3d9e25 Mon Sep 17 00:00:00 2001 From: bvweerd Date: Tue, 12 May 2026 13:01:42 +0200 Subject: [PATCH 21/24] feat: make step size configurable for all number entities via options flow Closes #135. All number entities (Kp, Ki, Kd, sample time, setpoint, output min/max, startup value) now read their step size from entry.options using a generic step_{key} pattern. Defaults match existing hardcoded values, so existing installations are unaffected. Also fixes a pre-existing bug in ControlParameterNumber.__init__ where _attr_native_step was assigned twice, with the second overwriting the first. --- .../simple_pid_controller/config_flow.py | 13 ++++ .../simple_pid_controller/const.py | 13 ++++ .../simple_pid_controller/number.py | 12 +++- .../simple_pid_controller/strings.json | 20 +++++- .../translations/en.json | 62 ++++++++++++------- .../translations/nl.json | 20 +++++- tests/test_config_flow.py | 27 +++++++- tests/test_number.py | 59 ++++++++++++++++++ 8 files changed, 198 insertions(+), 28 deletions(-) diff --git a/custom_components/simple_pid_controller/config_flow.py b/custom_components/simple_pid_controller/config_flow.py index b64a162..16a2317 100644 --- a/custom_components/simple_pid_controller/config_flow.py +++ b/custom_components/simple_pid_controller/config_flow.py @@ -25,10 +25,12 @@ CONF_INPUT_RANGE_MAX, CONF_OUTPUT_RANGE_MIN, CONF_OUTPUT_RANGE_MAX, + CONF_STEP_PREFIX, DEFAULT_INPUT_RANGE_MIN, DEFAULT_INPUT_RANGE_MAX, DEFAULT_OUTPUT_RANGE_MIN, DEFAULT_OUTPUT_RANGE_MAX, + DEFAULT_STEPS, ) _LOGGER = logging.getLogger(__name__) @@ -146,6 +148,16 @@ async def async_step_init( CONF_OUTPUT_RANGE_MAX, DEFAULT_OUTPUT_RANGE_MAX ) + step_fields = { + vol.Optional( + f"{CONF_STEP_PREFIX}{key}", + default=self.config_entry.options.get( + f"{CONF_STEP_PREFIX}{key}", DEFAULT_STEPS[key] + ), + ): selector({"number": {"min": 0.0001, "max": 100.0, "step": 0.001, "mode": "box"}}) + for key in DEFAULT_STEPS + } + options_schema = vol.Schema( { vol.Required( @@ -168,6 +180,7 @@ async def async_step_init( CONF_OUTPUT_RANGE_MAX, default=current_output_max, ): vol.Coerce(float), + **step_fields, } ) diff --git a/custom_components/simple_pid_controller/const.py b/custom_components/simple_pid_controller/const.py index 592b1b5..d4a9b8e 100644 --- a/custom_components/simple_pid_controller/const.py +++ b/custom_components/simple_pid_controller/const.py @@ -16,3 +16,16 @@ DEFAULT_INPUT_RANGE_MAX = 100.0 DEFAULT_OUTPUT_RANGE_MIN = 0.0 DEFAULT_OUTPUT_RANGE_MAX = 100.0 + +CONF_STEP_PREFIX = "step_" + +DEFAULT_STEPS: dict[str, float] = { + "kp": 0.0001, + "ki": 0.0001, + "kd": 0.0001, + "sample_time": 0.01, + "setpoint": 0.01, + "output_min": 1.0, + "output_max": 1.0, + "starting_output": 1.0, +} diff --git a/custom_components/simple_pid_controller/number.py b/custom_components/simple_pid_controller/number.py index b429ceb..b8fc4f3 100644 --- a/custom_components/simple_pid_controller/number.py +++ b/custom_components/simple_pid_controller/number.py @@ -16,10 +16,12 @@ CONF_INPUT_RANGE_MAX, CONF_OUTPUT_RANGE_MIN, CONF_OUTPUT_RANGE_MAX, + CONF_STEP_PREFIX, DEFAULT_INPUT_RANGE_MIN, DEFAULT_INPUT_RANGE_MAX, DEFAULT_OUTPUT_RANGE_MIN, DEFAULT_OUTPUT_RANGE_MAX, + DEFAULT_STEPS, ) # Coordinator is used to centralize the data updates @@ -129,7 +131,9 @@ def __init__(self, hass: HomeAssistant, entry: ConfigEntry, desc: dict) -> None: self._attr_native_unit_of_measurement = desc["unit"] self._attr_native_min_value = desc["min"] self._attr_native_max_value = desc["max"] - self._attr_native_step = desc["step"] + self._attr_native_step = (entry.options or {}).get( + f"{CONF_STEP_PREFIX}{desc['key']}", DEFAULT_STEPS[desc["key"]] + ) self._attr_native_value = desc["default"] self._attr_entity_category = desc["entity_category"] @@ -162,7 +166,6 @@ def __init__(self, hass: HomeAssistant, entry: ConfigEntry, desc: dict) -> None: self._attr_icon = "mdi:ray-vertex" self._attr_mode = "box" self._attr_native_unit_of_measurement = desc["unit"] - self._attr_native_step = desc["step"] self._attr_native_value = desc["default"] self._attr_entity_category = desc["entity_category"] self._key = desc["key"] @@ -208,7 +211,10 @@ def __init__(self, hass: HomeAssistant, entry: ConfigEntry, desc: dict) -> None: self._attr_native_min_value = min_val self._attr_native_max_value = max_val - self._attr_native_step = desc.get("step", 1.0) + self._attr_native_step = opts.get( + f"{CONF_STEP_PREFIX}{self._key}", + DEFAULT_STEPS.get(self._key, desc.get("step", 1.0)), + ) # Initialize current value if self._key == "setpoint": diff --git a/custom_components/simple_pid_controller/strings.json b/custom_components/simple_pid_controller/strings.json index 6bdd0a9..93d3b4e 100644 --- a/custom_components/simple_pid_controller/strings.json +++ b/custom_components/simple_pid_controller/strings.json @@ -28,7 +28,25 @@ "input_range_min": "Minimum Input Range", "input_range_max": "Maximum Input Range", "output_range_min": "Minimum Output Range", - "output_range_max": "Maximum Output Range" + "output_range_max": "Maximum Output Range", + "step_kp": "Kp Step Size", + "step_ki": "Ki Step Size", + "step_kd": "Kd Step Size", + "step_sample_time": "Sample Time Step Size", + "step_setpoint": "Setpoint Step Size", + "step_output_min": "Output Min Step Size", + "step_output_max": "Output Max Step Size", + "step_starting_output": "Startup Value Step Size" + }, + "data_description": { + "step_kp": "Increment size for the Kp parameter.", + "step_ki": "Increment size for the Ki parameter.", + "step_kd": "Increment size for the Kd parameter.", + "step_sample_time": "Increment size for the sample time parameter.", + "step_setpoint": "Increment size for the setpoint picker.", + "step_output_min": "Increment size for the output minimum.", + "step_output_max": "Increment size for the output maximum.", + "step_starting_output": "Increment size for the startup value." } } } diff --git a/custom_components/simple_pid_controller/translations/en.json b/custom_components/simple_pid_controller/translations/en.json index 6e12af2..0a5d4b2 100644 --- a/custom_components/simple_pid_controller/translations/en.json +++ b/custom_components/simple_pid_controller/translations/en.json @@ -34,7 +34,25 @@ "input_range_min": "Minimum Input Range", "input_range_max": "Maximum Input Range", "output_range_min": "Minimum Output Range", - "output_range_max": "Maximum Output Range" + "output_range_max": "Maximum Output Range", + "step_kp": "Kp Step Size", + "step_ki": "Ki Step Size", + "step_kd": "Kd Step Size", + "step_sample_time": "Sample Time Step Size", + "step_setpoint": "Setpoint Step Size", + "step_output_min": "Output Min Step Size", + "step_output_max": "Output Max Step Size", + "step_starting_output": "Startup Value Step Size" + }, + "data_description": { + "step_kp": "Increment size for the Kp parameter.", + "step_ki": "Increment size for the Ki parameter.", + "step_kd": "Increment size for the Kd parameter.", + "step_sample_time": "Increment size for the sample time parameter.", + "step_setpoint": "Increment size for the setpoint picker.", + "step_output_min": "Increment size for the output minimum.", + "step_output_max": "Increment size for the output maximum.", + "step_starting_output": "Increment size for the startup value." } } }, @@ -42,7 +60,7 @@ "range_min_max": "Minimum must be lower than maximum." } }, - "entity": { + "entity": { "number": { "kp": { "name": "Kp" @@ -75,23 +93,23 @@ "current_value": { "name": "Current Value" } - } - } - , - "services": { - "set_output": { - "name": "Set PID output", - "description": "Set or reset the PID controller output.", - "fields": { - "preset": { - "name": "Preset", - "description": "Use a preset output: zero_start, last_known_value or startup_value." - }, - "value": { - "name": "Value", - "description": "Manual output value between output_min and output_max." - } - } - } - } -} + } + } + , + "services": { + "set_output": { + "name": "Set PID output", + "description": "Set or reset the PID controller output.", + "fields": { + "preset": { + "name": "Preset", + "description": "Use a preset output: zero_start, last_known_value or startup_value." + }, + "value": { + "name": "Value", + "description": "Manual output value between output_min and output_max." + } + } + } + } +} diff --git a/custom_components/simple_pid_controller/translations/nl.json b/custom_components/simple_pid_controller/translations/nl.json index 0d73623..f812e1c 100644 --- a/custom_components/simple_pid_controller/translations/nl.json +++ b/custom_components/simple_pid_controller/translations/nl.json @@ -33,7 +33,25 @@ "input_range_min": "Minimum Input Bereik", "input_range_max": "Maximum Input Bereik", "output_range_min": "Minimum Output Bereik", - "output_range_max": "Maximum Output Bereik" + "output_range_max": "Maximum Output Bereik", + "step_kp": "Kp Stapgrootte", + "step_ki": "Ki Stapgrootte", + "step_kd": "Kd Stapgrootte", + "step_sample_time": "Steektijd Stapgrootte", + "step_setpoint": "Stapgrootte doelwaarde", + "step_output_min": "Stapgrootte min. uitvoer", + "step_output_max": "Stapgrootte max. uitvoer", + "step_starting_output": "Stapgrootte startwaarde" + }, + "data_description": { + "step_kp": "Stapgrootte voor de Kp-parameter.", + "step_ki": "Stapgrootte voor de Ki-parameter.", + "step_kd": "Stapgrootte voor de Kd-parameter.", + "step_sample_time": "Stapgrootte voor de steektijd.", + "step_setpoint": "Stapgrootte voor de setpoint-kiezer.", + "step_output_min": "Stapgrootte voor de minimale uitvoer.", + "step_output_max": "Stapgrootte voor de maximale uitvoer.", + "step_starting_output": "Stapgrootte voor de startwaarde." } } }, diff --git a/tests/test_config_flow.py b/tests/test_config_flow.py index 1d28955..24f3fa0 100644 --- a/tests/test_config_flow.py +++ b/tests/test_config_flow.py @@ -4,6 +4,7 @@ from homeassistant.data_entry_flow import FlowResultType from custom_components.simple_pid_controller.const import ( + CONF_STEP_PREFIX, DOMAIN, CONF_NAME, CONF_SENSOR_ENTITY_ID, @@ -15,6 +16,7 @@ DEFAULT_INPUT_RANGE_MAX, DEFAULT_OUTPUT_RANGE_MIN, DEFAULT_OUTPUT_RANGE_MAX, + DEFAULT_STEPS, ) from custom_components.simple_pid_controller.config_flow import ( PIDControllerFlowHandler, @@ -184,7 +186,30 @@ async def test_options_flow(hass, config_entry, new_options, expected_errors): assert result2.get("errors") == expected_errors else: assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2.get("data") == new_options + # Step defaults are added by voluptuous; check submitted fields are present + assert new_options.items() <= result2.get("data", {}).items() + + +async def test_options_flow_with_custom_steps(hass, config_entry): + """Test that step options round-trip correctly through the options flow.""" + custom_steps = {f"{CONF_STEP_PREFIX}{key}": 0.5 for key in DEFAULT_STEPS} + new_options = { + CONF_SENSOR_ENTITY_ID: "sensor.new", + CONF_INPUT_RANGE_MIN: 1.0, + CONF_INPUT_RANGE_MAX: 10.0, + CONF_OUTPUT_RANGE_MIN: 1.0, + CONF_OUTPUT_RANGE_MAX: 10.0, + **custom_steps, + } + + init_result = await hass.config_entries.options.async_init(config_entry.entry_id) + result2 = await hass.config_entries.options.async_configure( + init_result["flow_id"], user_input=new_options + ) + + assert result2["type"] == FlowResultType.CREATE_ENTRY + for key, val in custom_steps.items(): + assert result2["data"][key] == val async def test_user_flow_duplicate_abort(hass): diff --git a/tests/test_number.py b/tests/test_number.py index b0d942a..91c1328 100644 --- a/tests/test_number.py +++ b/tests/test_number.py @@ -7,10 +7,13 @@ ControlParameterNumber, ) from custom_components.simple_pid_controller.const import ( + CONF_STEP_PREFIX, DEFAULT_INPUT_RANGE_MIN, DEFAULT_INPUT_RANGE_MAX, DEFAULT_OUTPUT_RANGE_MIN, DEFAULT_OUTPUT_RANGE_MAX, + DEFAULT_STEPS, + DOMAIN, ) @@ -163,3 +166,59 @@ async def test_controlparameter_number_unexpected_key( assert f"Unknown PID key '{invalid_key}'. Using default values:" in caplog.text assert num._attr_native_min_value == expected_min assert num._attr_native_max_value == expected_max + + +@pytest.mark.usefixtures("setup_integration") +@pytest.mark.parametrize("desc", PID_NUMBER_ENTITIES) +async def test_pid_number_step_from_options(hass, config_entry, desc): + """Test that PIDParameterNumber reads step from CONF_STEP_PREFIX+key in options.""" + from types import SimpleNamespace + from pytest_homeassistant_custom_component.common import MockConfigEntry + + custom_step = 0.5 + entry = MockConfigEntry( + domain=DOMAIN, + entry_id=f"step_test_{desc['key']}", + data=config_entry.data, + options={f"{CONF_STEP_PREFIX}{desc['key']}": custom_step}, + ) + entry.runtime_data = SimpleNamespace(handle=config_entry.runtime_data.handle) + + num = PIDParameterNumber(hass, entry, desc) + assert num._attr_native_step == custom_step + + +@pytest.mark.usefixtures("setup_integration") +@pytest.mark.parametrize("desc", PID_NUMBER_ENTITIES) +async def test_pid_number_step_defaults(hass, config_entry, desc): + """Test that PIDParameterNumber falls back to DEFAULT_STEPS when no option is set.""" + num = PIDParameterNumber(hass, config_entry, desc) + assert num._attr_native_step == DEFAULT_STEPS[desc["key"]] + + +@pytest.mark.usefixtures("setup_integration") +@pytest.mark.parametrize("desc", CONTROL_NUMBER_ENTITIES) +async def test_control_number_step_from_options(hass, config_entry, desc): + """Test that ControlParameterNumber reads step from CONF_STEP_PREFIX+key in options.""" + from types import SimpleNamespace + from pytest_homeassistant_custom_component.common import MockConfigEntry + + custom_step = 2.0 + entry = MockConfigEntry( + domain=DOMAIN, + entry_id=f"step_test_{desc['key']}", + data=config_entry.data, + options={f"{CONF_STEP_PREFIX}{desc['key']}": custom_step}, + ) + entry.runtime_data = SimpleNamespace(handle=config_entry.runtime_data.handle) + + num = ControlParameterNumber(hass, entry, desc) + assert num._attr_native_step == custom_step + + +@pytest.mark.usefixtures("setup_integration") +@pytest.mark.parametrize("desc", CONTROL_NUMBER_ENTITIES) +async def test_control_number_step_defaults(hass, config_entry, desc): + """Test that ControlParameterNumber falls back to DEFAULT_STEPS when no option is set.""" + num = ControlParameterNumber(hass, config_entry, desc) + assert num._attr_native_step == DEFAULT_STEPS[desc["key"]] From 860b6361c6ce4ec24609130afd2f04cdbc263ba3 Mon Sep 17 00:00:00 2001 From: bvweerd Date: Tue, 12 May 2026 13:09:01 +0200 Subject: [PATCH 22/24] test: add non-happy path tests for step selector validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tests that step values below the minimum (0.0001), above the maximum (100.0), and exactly at both boundaries are correctly handled by the options flow β€” invalid values raise InvalidData, boundary values are accepted. --- tests/test_config_flow.py | 54 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/tests/test_config_flow.py b/tests/test_config_flow.py index 24f3fa0..3b01d16 100644 --- a/tests/test_config_flow.py +++ b/tests/test_config_flow.py @@ -1,7 +1,9 @@ import pytest +import pytest + from homeassistant import config_entries -from homeassistant.data_entry_flow import FlowResultType +from homeassistant.data_entry_flow import FlowResultType, InvalidData from custom_components.simple_pid_controller.const import ( CONF_STEP_PREFIX, @@ -212,6 +214,54 @@ async def test_options_flow_with_custom_steps(hass, config_entry): assert result2["data"][key] == val +_BASE_OPTIONS = { + CONF_SENSOR_ENTITY_ID: "sensor.new", + CONF_INPUT_RANGE_MIN: 1.0, + CONF_INPUT_RANGE_MAX: 10.0, + CONF_OUTPUT_RANGE_MIN: 1.0, + CONF_OUTPUT_RANGE_MAX: 10.0, +} + + +@pytest.mark.usefixtures("setup_integration") +@pytest.mark.parametrize("invalid_step", [0.0, -1.0, -0.0001]) +async def test_options_flow_step_below_min_rejected(hass, config_entry, invalid_step): + """Test that a step value below the selector minimum raises InvalidData.""" + init_result = await hass.config_entries.options.async_init(config_entry.entry_id) + with pytest.raises(InvalidData): + await hass.config_entries.options.async_configure( + init_result["flow_id"], + user_input={**_BASE_OPTIONS, f"{CONF_STEP_PREFIX}kp": invalid_step}, + ) + + +@pytest.mark.usefixtures("setup_integration") +@pytest.mark.parametrize("invalid_step", [100.001, 200.0, 1000.0]) +async def test_options_flow_step_above_max_rejected(hass, config_entry, invalid_step): + """Test that a step value above the selector maximum raises InvalidData.""" + init_result = await hass.config_entries.options.async_init(config_entry.entry_id) + with pytest.raises(InvalidData): + await hass.config_entries.options.async_configure( + init_result["flow_id"], + user_input={**_BASE_OPTIONS, f"{CONF_STEP_PREFIX}setpoint": invalid_step}, + ) + + +@pytest.mark.usefixtures("setup_integration") +@pytest.mark.parametrize( + "boundary_step", [0.0001, 100.0] +) +async def test_options_flow_step_boundary_values_accepted(hass, config_entry, boundary_step): + """Test that step values at the exact selector boundaries are accepted.""" + init_result = await hass.config_entries.options.async_init(config_entry.entry_id) + result = await hass.config_entries.options.async_configure( + init_result["flow_id"], + user_input={**_BASE_OPTIONS, f"{CONF_STEP_PREFIX}kp": boundary_step}, + ) + assert result["type"] == FlowResultType.CREATE_ENTRY + assert result["data"][f"{CONF_STEP_PREFIX}kp"] == boundary_step + + async def test_user_flow_duplicate_abort(hass): """Test that a duplicate config entry aborts the flow.""" user_input = { @@ -241,3 +291,5 @@ async def test_user_flow_duplicate_abort(hass): assert result2["type"] == FlowResultType.ABORT assert result2["reason"] == "already_configured" + + From 20ef5d95c9739eea7da22c26aa64ee2b69c7883d Mon Sep 17 00:00:00 2001 From: bvweerd Date: Tue, 12 May 2026 13:15:13 +0200 Subject: [PATCH 23/24] style: apply black and ruff formatting --- .../simple_pid_controller/config_flow.py | 4 +++- tests/test_config_flow.py | 11 ++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/custom_components/simple_pid_controller/config_flow.py b/custom_components/simple_pid_controller/config_flow.py index 16a2317..7e479d5 100644 --- a/custom_components/simple_pid_controller/config_flow.py +++ b/custom_components/simple_pid_controller/config_flow.py @@ -154,7 +154,9 @@ async def async_step_init( default=self.config_entry.options.get( f"{CONF_STEP_PREFIX}{key}", DEFAULT_STEPS[key] ), - ): selector({"number": {"min": 0.0001, "max": 100.0, "step": 0.001, "mode": "box"}}) + ): selector( + {"number": {"min": 0.0001, "max": 100.0, "step": 0.001, "mode": "box"}} + ) for key in DEFAULT_STEPS } diff --git a/tests/test_config_flow.py b/tests/test_config_flow.py index 3b01d16..5218184 100644 --- a/tests/test_config_flow.py +++ b/tests/test_config_flow.py @@ -1,6 +1,5 @@ import pytest -import pytest from homeassistant import config_entries from homeassistant.data_entry_flow import FlowResultType, InvalidData @@ -248,10 +247,10 @@ async def test_options_flow_step_above_max_rejected(hass, config_entry, invalid_ @pytest.mark.usefixtures("setup_integration") -@pytest.mark.parametrize( - "boundary_step", [0.0001, 100.0] -) -async def test_options_flow_step_boundary_values_accepted(hass, config_entry, boundary_step): +@pytest.mark.parametrize("boundary_step", [0.0001, 100.0]) +async def test_options_flow_step_boundary_values_accepted( + hass, config_entry, boundary_step +): """Test that step values at the exact selector boundaries are accepted.""" init_result = await hass.config_entries.options.async_init(config_entry.entry_id) result = await hass.config_entries.options.async_configure( @@ -291,5 +290,3 @@ async def test_user_flow_duplicate_abort(hass): assert result2["type"] == FlowResultType.ABORT assert result2["reason"] == "already_configured" - - From cb8ef064c8dbe41ac342a7567adf273a5d25199e Mon Sep 17 00:00:00 2001 From: bvweerd Date: Tue, 12 May 2026 13:23:42 +0200 Subject: [PATCH 24/24] ci: update manifest.json version from tag during release --- .github/workflows/release.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0b0d198..f2a9a0a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,6 +20,11 @@ jobs: VERSION=${GITHUB_REF_NAME#v} echo "version=$VERSION" >> $GITHUB_OUTPUT + - name: Update version in manifest.json + run: | + sed -i 's/"version": "[^"]*"/"version": "${{ steps.version.outputs.version }}"/' \ + custom_components/simple_pid_controller/manifest.json + - name: Create release ZIP run: | cd custom_components/simple_pid_controller/