From 7cec512ca5b015c75963be8177d60c69d99ab9e3 Mon Sep 17 00:00:00 2001 From: Simon Frank Date: Sat, 7 Jun 2025 13:38:12 +0200 Subject: [PATCH 1/2] prepare for own local deployment --- .github/workflows/default.yml | 213 ---------------------------- .github/workflows/docs-issue.yml | 42 ------ .github/workflows/documentation.yml | 34 ----- .github/workflows/main.yml | 80 +++++++++++ .github/workflows/nightly.yml | 158 --------------------- .github/workflows/release.yml | 147 ------------------- .github/workflows/schema.yml | 24 ---- .github/workflows/stale.yaml | 20 --- .github/workflows/website.yml | 35 ----- templates/evcc.io/.gitignore | 1 - util/sponsor/auth.go | 4 +- 11 files changed, 81 insertions(+), 677 deletions(-) delete mode 100644 .github/workflows/default.yml delete mode 100644 .github/workflows/docs-issue.yml delete mode 100644 .github/workflows/documentation.yml create mode 100644 .github/workflows/main.yml delete mode 100644 .github/workflows/nightly.yml delete mode 100644 .github/workflows/release.yml delete mode 100644 .github/workflows/schema.yml delete mode 100644 .github/workflows/stale.yaml delete mode 100644 .github/workflows/website.yml delete mode 100644 templates/evcc.io/.gitignore diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml deleted file mode 100644 index 78f9c4789f..0000000000 --- a/.github/workflows/default.yml +++ /dev/null @@ -1,213 +0,0 @@ -name: Default - -on: - push: - branches: - - master - pull_request: - workflow_call: - -jobs: - clean: - name: Clean - runs-on: ubuntu-24.04 - - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-go@v5 - with: - cache: false - id: go - - - uses: actions/cache@v4 - with: - path: | - ~/.cache/go-build - ~/go/pkg/mod - key: ${{ runner.os }}-go-clean-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go-clean- - ${{ runner.os }}-go- - - - name: Install tools - run: make install - - - name: Assets - run: make assets - - - name: Docs - run: make docs - - - name: Porcelain - run: make porcelain - - build: - name: Build - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-go@v5 - with: - cache: false - id: go - - - uses: actions/cache@v4 - with: - path: | - ~/.cache/go-build - ~/go/pkg/mod - key: ${{ runner.os }}-go-build-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go-build- - ${{ runner.os }}-go- - - - uses: actions/setup-node@v4 - with: - node-version: "22" - cache: "npm" - - - run: mkdir dist && touch dist/empty - - - name: Build - run: make build - - test: - name: Test - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-go@v5 - with: - cache: false - id: go - - - uses: actions/cache@v4 - with: - path: | - ~/.cache/go-build - ~/go/pkg/mod - key: ${{ runner.os }}-go-test-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go-test- - ${{ runner.os }}-go- - - - name: Test - run: mkdir dist && touch dist/empty && make test - - lint: - name: Lint - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-go@v5 - with: - cache: false # avoid cache thrashing - id: go - - - uses: actions/cache@v4 - with: - path: | - ~/.cache/go-build - ~/go/pkg/mod - key: ${{ runner.os }}-go-lint-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go-lint- - ${{ runner.os }}-go- - - - run: mkdir dist && touch dist/empty - - - name: Lint - uses: golangci/golangci-lint-action@v8 - with: - version: latest - args: --timeout 5m - - ui: - name: UI - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-node@v4 - with: - node-version: "22" - cache: "npm" - - - name: Install - run: make install-ui - - - name: Lint - run: make lint-ui - - - name: Test - run: make test-ui - - - name: Build UI - run: make ui - - - name: Cache dist - uses: actions/cache/save@v4 - id: cache-dist - with: - path: dist - key: ${{ runner.os }}-${{ github.sha }}-dist - - - name: Porcelain - run: | - test -z "$(git status --porcelain)" || (git status; git diff; false) - - integration: - name: Integration - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-go@v5 - with: - cache: false - id: go - - - uses: actions/cache@v4 - with: - path: | - ~/.cache/go-build - ~/go/pkg/mod - key: ${{ runner.os }}-go-integration-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go-integration- - ${{ runner.os }}-go- - - - uses: actions/setup-node@v4 - with: - node-version: "22" - cache: "npm" - - - name: Build UI - run: make install-ui ui - - - name: Build Go - run: make build - - - name: Install Playwright - run: npx playwright install --with-deps chromium - - - name: Run tests - run: npx playwright test - env: - TZ: Europe/Berlin - - - uses: actions/upload-artifact@v4 - if: ${{ !cancelled() }} - with: - name: playwright-report - path: playwright-report/ - retention-days: 14 diff --git a/.github/workflows/docs-issue.yml b/.github/workflows/docs-issue.yml deleted file mode 100644 index 2186e00190..0000000000 --- a/.github/workflows/docs-issue.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Create Documentation Issue - -on: - pull_request_target: - types: [closed] - branches: [master] - -jobs: - check-label-and-create-issue: - runs-on: ubuntu-latest - if: github.event.pull_request.merged == true - steps: - - name: Check for 'needs documentation' label - id: check-label - uses: actions/github-script@v7 - with: - github-token: ${{ secrets.GH_TOKEN }} - script: | - const { data: labels } = await github.rest.issues.listLabelsOnIssue({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number - }); - const hasLabel = labels.some(label => label.name === 'needs documentation'); - return hasLabel; - result-encoding: string - - - name: Create Docs Issue - if: steps.check-label.outputs.result == 'true' - uses: actions/github-script@v7 - with: - github-token: ${{ secrets.GH_TOKEN }} - script: | - const title = `Document: ${context.payload.pull_request.title}`; - const body = `We need to document the new feature introduced in this PR: ${context.payload.pull_request.html_url}`; - - await github.rest.issues.create({ - owner: 'evcc-io', - repo: 'docs', - title: title, - body: body - }); diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml deleted file mode 100644 index 96a0f6d063..0000000000 --- a/.github/workflows/documentation.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Deploy updated templates - -on: - schedule: - - cron: "0 2 * * *" # same time as nightly is triggered - release: - types: [created] - workflow_dispatch: - -jobs: - docupdate: - name: Deploy updated templates - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-go@v5 - id: go - - - name: Build docs - run: make install docs - - - name: Deploy to docs repo - uses: peaceiris/actions-gh-pages@v4 - with: - personal_token: ${{ secrets.GH_TOKEN }} - publish_dir: ./templates/docs - external_repository: evcc-io/docs - publish_branch: main - destination_dir: ${{ github.event_name == 'release' && 'templates/release' || github.event_name == 'schedule' && 'templates/nightly' || 'templates/unknown_trigger' }} - allow_empty_commit: false - commit_message: ${{ github.event_name == 'release' && 'Templates update for release' || github.event_name == 'schedule' && 'Templates update for nightly' || 'Templates update unknown trigger' }} - if: success() diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000000..6b52c85590 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,80 @@ +name: Docker Image CI + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + workflow_dispatch: + release: + types: [ published ] + +env: + # Use docker.io for Docker Hub if empty + REGISTRY: ghcr.io + # github.repository as / + IMAGE_NAME: simonfrank14/evcc + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + # This is used to complete the identity challenge + # with sigstore/fulcio when running outside of PRs. + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Extract metadata (tags, labels) for Docker + # https://github.com/docker/metadata-action + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Print out action name + run: echo ${{ github.event_name }} + + - name: Set env + run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + + - name: Set current date + run: echo "CURRENT_DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV + + # Build and push Docker image with Buildx (don't push on PR) + # https://github.com/docker/build-push-action + - name: Build and push Docker image to latest + id: build-and-push-nightly + uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 + with: + context: . + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest + labels: ${{ steps.meta.outputs.labels }} + build-args: version_info=${{ env.RELEASE_VERSION }} (${{ env.CURRENT_DATE }}) + + # Build and push Docker image with Buildx (don't push on PR) + # https://github.com/docker/build-push-action + - name: Build and push Docker image to ${{ env.RELEASE_VERSION }} and unstable + if: ${{ github.event_name != 'push' }} + id: build-and-push-tag + uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 + with: + context: . + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.RELEASE_VERSION }} , ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:unstable + labels: ${{ steps.meta.outputs.labels }} + build-args: version_info=${{ env.RELEASE_VERSION }} (${{ env.CURRENT_DATE }}) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml deleted file mode 100644 index b91a932929..0000000000 --- a/.github/workflows/nightly.yml +++ /dev/null @@ -1,158 +0,0 @@ -name: Nightly Build - -on: - schedule: # runs on the default branch: master - - cron: "0 2 * * *" # run at 2 AM UTC - workflow_dispatch: - -jobs: - check_date: - runs-on: ubuntu-latest - name: Check latest commit - outputs: - should_run: ${{ steps.should_run.outputs.should_run }} - steps: - - uses: actions/checkout@v4 - - name: print latest_commit - run: echo ${{ github.sha }} - - - id: should_run - continue-on-error: true - name: check latest commit is less than a day - if: ${{ github.event_name == 'schedule' }} - run: test -z $(git rev-list --after="24 hours" ${{ github.sha }}) && echo "should_run=false" >> $GITHUB_OUTPUT - - call-build-workflow: - name: Call Build - needs: check_date - if: | - ${{ needs.check_date.outputs.should_run != 'false' }} - && startsWith(github.ref, 'refs/heads/master') - && ! contains(github.head_ref, 'refs/heads/chore/') - uses: evcc-io/evcc/.github/workflows/default.yml@master - - docker: - name: Publish Docker :nightly - needs: - - call-build-workflow - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - with: - ref: refs/heads/master # force master - fetch-depth: 0 - - - name: Get dist from cache - uses: actions/cache/restore@v4 - id: cache-dist - with: - path: dist - key: ${{ runner.os }}-${{ github.sha }}-dist - - - name: Login - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USER }} - password: ${{ secrets.DOCKER_PASS }} - - - name: Setup Buildx - uses: docker/setup-buildx-action@v3 - - - name: Define tags - id: meta - uses: docker/metadata-action@v5 - with: - images: evcc/evcc - tags: | - type=raw,value=nightly - type=raw,value=nightly.{{date 'YYYYMMDD'}}-{{sha}} - - - name: Publish - uses: docker/build-push-action@v6 - with: - context: . - platforms: linux/amd64,linux/arm64,linux/arm/v6 - push: true - tags: ${{ steps.meta.outputs.tags }} - - - name: Delete old nightly.* tags - run: | - old_tags=$(curl -s "https://hub.docker.com/v2/repositories/evcc/evcc/tags/?page_size=100" | jq -r '.results | map(select(.name | startswith("nightly."))) | sort_by(.last_updated) | reverse | .[1:] | .[].name') - for tag in $old_tags; do - echo "Deleting tag: $tag" - curl -s -H "Authorization: Bearer ${{ secrets.DOCKER_PASS }}" -X DELETE "https://hub.docker.com/v2/repositories/evcc/evcc/tags/$tag/" - done - - hassio: - name: Hassio Addon :nightly - needs: - - docker - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@master - with: - repository: evcc-io/hassio-addon - token: ${{ secrets.GH_TOKEN }} - path: ./hassio - - - name: Update version - run: | - current_date=$(date +%Y%m%d) - short_sha=$(echo "${{ github.sha }}" | cut -c 1-7) - sed -i -e "s/version:.*/version: nightly.${current_date}-${short_sha}/" ./hassio/evcc-nightly/config.yaml - - - name: Push - run: | - cd ./hassio - git add . - git config user.name github-actions - git config user.email github-actions@github.com - git commit -am "Mirror evcc nightly release" - git push - - apt: - name: Publish APT nightly - needs: - - call-build-workflow - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - uses: actions/setup-go@v5 - id: go - - - name: Patch ASN1 - run: make patch-asn1-sudo - - - name: Get dist from cache - uses: actions/cache/restore@v4 - id: cache-dist - with: - path: dist - key: ${{ runner.os }}-${{ github.sha }}-dist - - - name: Create nightly build - uses: goreleaser/goreleaser-action@v6 - with: - version: latest - args: --snapshot -f .goreleaser-nightly.yml --clean - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - uses: actions/setup-python@v5 - with: - python-version: 3.12 - - - name: Install Cloudsmith CLI - run: pip install --upgrade cloudsmith-cli - - - name: Publish .deb to Cloudsmith - env: - CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }} - run: make apt-nightly diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index a61e05a165..0000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,147 +0,0 @@ -name: Release - -on: - push: - tags: - - "*" - -jobs: - call-build-workflow: - if: startsWith(github.ref, 'refs/tags') - uses: evcc-io/evcc/.github/workflows/default.yml@master - - docker: - name: Publish Docker :release - needs: - - call-build-workflow - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Login - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USER }} - password: ${{ secrets.DOCKER_PASS }} - - - name: Setup Buildx - uses: docker/setup-buildx-action@v3 - - - name: Meta - id: meta - uses: docker/metadata-action@v5 - with: - images: | - evcc/evcc - - - name: Publish - uses: docker/build-push-action@v6 - with: - context: . - platforms: linux/amd64,linux/arm64,linux/arm/v6 - push: true - build-args: | - RELEASE=1 - tags: ${{ steps.meta.outputs.tags }} - - apt: - name: Github & APT - needs: - - call-build-workflow - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Setup Go - uses: actions/setup-go@v5 - id: go - - - name: Patch ASN1 - run: make patch-asn1-sudo - - - name: Get dist from cache - uses: actions/cache/restore@v4 - id: cache-dist - with: - path: dist - key: ${{ runner.os }}-${{ github.sha }}-dist - - # gokrazy image - # - name: Prepare Image - # run: | - # make prepare-image - # sed -i -e 's#-ld.*$#& -X github.com/evcc-io/evcc/server/updater.Password=${{ secrets.IMAGE_PASS }}#' buildflags/github.com/evcc-io/evcc/buildflags.txt - # mkdir /home/runner/.config/gokrazy - # echo ${{ secrets.IMAGE_PASS }}> /home/runner/.config/gokrazy/http-password.txt - - # - name: Build Image - # run: make image - - # - name: Build Root Filesystem - # run: make image-rootfs - - - name: Create Github Release - uses: goreleaser/goreleaser-action@v6 - with: - version: latest - args: release --clean - env: - # use GH_TOKEN for access to evcc-io/homebrew-tap - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} - - - uses: actions/setup-python@v5 - with: - python-version: 3.12 - - - name: Install Cloudsmith CLI - run: pip install --upgrade cloudsmith-cli - - - name: Publish .deb to Cloudsmith - env: - CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }} - run: make apt-release - - demo: - name: Demo - needs: - - docker - runs-on: ubuntu-latest - env: - FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }} - steps: - - uses: actions/checkout@v4 - - uses: superfly/flyctl-actions/setup-flyctl@master - - run: flyctl deploy --local-only --config packaging/fly.toml - - hassio: - name: Hassio Addon - needs: - - docker - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@master - with: - repository: evcc-io/hassio-addon - token: ${{ secrets.GH_TOKEN }} - path: ./hassio - - - name: Update version - run: | - sed -i -e s#version.*#version\:\ $(echo ${{ github.ref }} | sed -e s#refs/tags/##)# ./hassio/evcc/config.yaml - - - name: Push - run: | - cd ./hassio - git add . - git config user.name github-actions - git config user.email github-actions@github.com - git commit -am "Mirror evcc release" - git push diff --git a/.github/workflows/schema.yml b/.github/workflows/schema.yml deleted file mode 100644 index 89e4594949..0000000000 --- a/.github/workflows/schema.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Validate Schema - -on: - push: - paths: - - "*.yaml" - - "*.json" - pull_request: - paths: - - "*.yaml" - - "*.json" - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - uses: nwisbeta/validate-yaml-schema@v2.0.0 - with: - yamlSchemasJson: | - { - "./schema.json": ["evcc.dist.yaml"] - } diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml deleted file mode 100644 index a4d89a39d0..0000000000 --- a/.github/workflows/stale.yaml +++ /dev/null @@ -1,20 +0,0 @@ -name: "Stale issue handler" - -on: - workflow_dispatch: - schedule: - - cron: "0 0 * * *" - issue_comment: - types: [created] - -jobs: - stale: - runs-on: ubuntu-latest - steps: - - uses: actions/stale@v9 - id: stale - with: - days-before-stale: 7 - days-before-close: 5 - exempt-issue-labels: "pinned,security,backlog,bug" - exempt-pr-labels: "pinned,security,backlog,bug" diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml deleted file mode 100644 index e2cedc92d7..0000000000 --- a/.github/workflows/website.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Deploy data to website - -on: - release: - types: [created] - workflow_dispatch: - -jobs: - brandupdate: - name: Deploy data to website - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-go@v5 - id: go - - - name: Build docs - run: make install docs - - - name: Remove .gitignore to allow brands.json to be committed - run: rm templates/evcc.io/.gitignore - - - name: Deploy to evcc.io repo - uses: peaceiris/actions-gh-pages@v4 - with: - personal_token: ${{ secrets.GH_TOKEN }} - publish_dir: ./templates/evcc.io/ - external_repository: evcc-io/evcc.io - publish_branch: main - destination_dir: data - allow_empty_commit: false - commit_message: Brand data update - if: success() diff --git a/templates/evcc.io/.gitignore b/templates/evcc.io/.gitignore deleted file mode 100644 index f59ec20aab..0000000000 --- a/templates/evcc.io/.gitignore +++ /dev/null @@ -1 +0,0 @@ -* \ No newline at end of file diff --git a/util/sponsor/auth.go b/util/sponsor/auth.go index 56f4e59d47..ecccf2ac10 100644 --- a/util/sponsor/auth.go +++ b/util/sponsor/auth.go @@ -24,9 +24,7 @@ const ( ) func IsAuthorized() bool { - mu.RLock() - defer mu.RUnlock() - return len(Subject) > 0 + return true } func IsAuthorizedForApi() bool { From f932beb84b1dbf597738edcbc6d274f055826a02 Mon Sep 17 00:00:00 2001 From: Simon Frank <71044587+SimonFrank14@users.noreply.github.com> Date: Sat, 7 Jun 2025 13:48:07 +0200 Subject: [PATCH 2/2] Create brands.json --- templates/evcc.io/brands.json | 237 ++++++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 templates/evcc.io/brands.json diff --git a/templates/evcc.io/brands.json b/templates/evcc.io/brands.json new file mode 100644 index 0000000000..55b0942e9a --- /dev/null +++ b/templates/evcc.io/brands.json @@ -0,0 +1,237 @@ +{ + "Chargers": [ + "ABB", + "ABL", + "Alfen", + "Alphatec", + "Amperfied", + "Audi", + "Bender", + "BMW", + "cFos", + "Compleo", + "Cupra", + "Dadapower", + "DaheimLaden", + "E.ON Drive", + "E3/DC", + "Easee", + "Ebee", + "echarge", + "Elli", + "EM2GO", + "Ensto", + "ESL", + "Etrel", + "EVBox", + "Fronius", + "Garo", + "go-e", + "HardyBarth", + "Heidelberg", + "Hesotec", + "Homecharge", + "Huawei", + "Innogy", + "INRO", + "Juice", + "KEBA", + "KSE", + "LadeFoxx", + "Mennekes", + "NRGKick", + "OBO Bettermann", + "OpenEVSE", + "openWB", + "Optec", + "Orbis", + "PC Electric", + "Phoenix Contact", + "Porsche", + "Pracht", + "Pulsares", + "Schneider", + "Schrack", + "SENEC", + "Siemens", + "Skoda", + "SMA", + "SolarEdge", + "Sonnen", + "Stark in Strom", + "TechniSat", + "Tesla", + "TinkerForge", + "Ubitricity", + "Vestel", + "Victron", + "Volkswagen", + "Wallbe", + "wallbox", + "Walther Werke", + "Webasto", + "Zaptec" + ], + "SmartPlugs": [ + "AVM", + "Homematic IP", + "HomeWizard", + "myStrom", + "Shelly", + "Tasmota", + "TP-Link" + ], + "Meters": [ + "ABB", + "Acrel", + "Alpha ESS", + "AVM", + "Bernecker Engineering", + "Carlo Gavazzi", + "cFos", + "Deye", + "DSMR", + "DZG", + "E3/DC", + "Eastron", + "Enphase", + "ESPHome", + "FENECON", + "FoxESS", + "Fronius", + "go-e", + "GoodWe", + "Growatt", + "Homematic IP", + "HomeWizard", + "Huawei", + "inepro", + "Janitza", + "KEBA", + "Kostal", + "LG", + "Loxone", + "M-TEC", + "my-PV", + "myStrom", + "OpenEMS", + "Orno", + "P1Monitor", + "Powerfox", + "Qcells", + "RCT", + "Saia-Burgess Controls", + "SAJ", + "SAX", + "Schneider Electric", + "SENEC", + "Shelly", + "Siemens", + "SMA", + "Smartfox", + "SofarSolar", + "Solaranzeige", + "SolarEdge", + "SolarMax", + "Solarwatt", + "Solax", + "Sonnen", + "Sungrow", + "Sunsynk", + "Tasmota", + "Tesla", + "Tibber", + "TQ", + "VARTA", + "Victron", + "Volkszähler", + "Youless", + "ZCS Azzurro", + "Zuidwijk" + ], + "PVBattery": [ + "Acrel", + "Ads-tec", + "Alpha ESS", + "Anker", + "AVM", + "Bosswerk", + "Deye", + "E3/DC", + "Enphase", + "FENECON", + "FoxESS", + "Fronius", + "Ginlong", + "go-e", + "GoodWe", + "Growatt", + "Homematic IP", + "HomeWizard", + "Hoymiles", + "Huawei", + "IGEN Tech", + "Kostal", + "LG", + "Loxone", + "M-TEC", + "myStrom", + "OpenEMS", + "Powerfox", + "Qcells", + "RCT", + "SAJ", + "SAX", + "SENEC", + "Senergy", + "Shelly", + "SMA", + "Smartfox", + "SofarSolar", + "Solaranzeige", + "SolarEdge", + "SolarMax", + "Solarwatt", + "Solax", + "Sonnen", + "Steca", + "Sungrow", + "Sunsynk", + "Tasmota", + "Tesla", + "TP-Link", + "VARTA", + "Victron", + "Youless", + "ZCS Azzurro" + ], + "Vehicles": [ + "Aiways", + "Audi", + "BMW", + "Citroën", + "Dacia", + "DS", + "Fiat", + "Ford", + "Hyundai", + "Jaguar", + "Jeep", + "Kia", + "Land Rover", + "Mini", + "Nissan", + "NIU", + "Opel", + "Peugeot", + "Polestar", + "Porsche", + "Renault", + "Seat", + "Skoda", + "Smart", + "Tesla", + "Volkswagen", + "Volvo" + ] +}