Compare commits

..

2 Commits

Author SHA1 Message Date
Erik
2f608d8650 Use numerical_value when compiling statistics 2023-02-01 14:03:33 +01:00
Erik
65324431a4 Add numerical_value state attribute to sensor 2023-02-01 13:58:43 +01:00
24428 changed files with 627484 additions and 239677 deletions

View File

@@ -114,10 +114,6 @@ tests: &tests
- tests/auth/**
- tests/backports/**
- tests/common.py
- tests/components/history/**
- tests/components/logbook/**
- tests/components/recorder/**
- tests/components/sensor/**
- tests/conftest.py
- tests/hassfest/**
- tests/helpers/**
@@ -125,7 +121,6 @@ tests: &tests
- tests/mock/**
- tests/pylint/**
- tests/scripts/**
- tests/syrupy.py
- tests/test_util/**
- tests/testing_config/**
- tests/util/**

View File

@@ -36,7 +36,6 @@ omit =
homeassistant/components/airnow/__init__.py
homeassistant/components/airnow/sensor.py
homeassistant/components/airq/__init__.py
homeassistant/components/airq/coordinator.py
homeassistant/components/airq/sensor.py
homeassistant/components/airthings/__init__.py
homeassistant/components/airthings/sensor.py
@@ -105,6 +104,7 @@ omit =
homeassistant/components/baf/sensor.py
homeassistant/components/baf/switch.py
homeassistant/components/baidu/tts.py
homeassistant/components/balboa/__init__.py
homeassistant/components/bbox/device_tracker.py
homeassistant/components/bbox/sensor.py
homeassistant/components/beewi_smartclim/sensor.py
@@ -198,6 +198,7 @@ omit =
homeassistant/components/denonavr/__init__.py
homeassistant/components/denonavr/media_player.py
homeassistant/components/denonavr/receiver.py
homeassistant/components/devolo_home_control/switch.py
homeassistant/components/digital_ocean/*
homeassistant/components/discogs/sensor.py
homeassistant/components/discord/__init__.py
@@ -212,11 +213,6 @@ omit =
homeassistant/components/doorbird/camera.py
homeassistant/components/doorbird/entity.py
homeassistant/components/doorbird/util.py
homeassistant/components/dormakaba_dkey/__init__.py
homeassistant/components/dormakaba_dkey/binary_sensor.py
homeassistant/components/dormakaba_dkey/entity.py
homeassistant/components/dormakaba_dkey/lock.py
homeassistant/components/dormakaba_dkey/sensor.py
homeassistant/components/dovado/*
homeassistant/components/downloader/*
homeassistant/components/dsmr_reader/__init__.py
@@ -226,7 +222,6 @@ omit =
homeassistant/components/dublin_bus_transport/sensor.py
homeassistant/components/dunehd/__init__.py
homeassistant/components/dunehd/media_player.py
homeassistant/components/dwd_weather_warnings/const.py
homeassistant/components/dwd_weather_warnings/sensor.py
homeassistant/components/dweet/*
homeassistant/components/ebox/sensor.py
@@ -250,8 +245,7 @@ omit =
homeassistant/components/ecowitt/sensor.py
homeassistant/components/eddystone_temperature/sensor.py
homeassistant/components/edimax/switch.py
homeassistant/components/edl21/__init__.py
homeassistant/components/edl21/sensor.py
homeassistant/components/edl21/*
homeassistant/components/egardia/*
homeassistant/components/eight_sleep/__init__.py
homeassistant/components/eight_sleep/binary_sensor.py
@@ -386,10 +380,7 @@ omit =
homeassistant/components/foscam/camera.py
homeassistant/components/foursquare/*
homeassistant/components/free_mobile/notify.py
homeassistant/components/freebox/camera.py
homeassistant/components/freebox/device_tracker.py
homeassistant/components/freebox/home_base.py
homeassistant/components/freebox/router.py
homeassistant/components/freebox/sensor.py
homeassistant/components/freebox/switch.py
homeassistant/components/fritz/common.py
@@ -399,8 +390,7 @@ omit =
homeassistant/components/fritzbox_callmonitor/__init__.py
homeassistant/components/fritzbox_callmonitor/base.py
homeassistant/components/fritzbox_callmonitor/sensor.py
homeassistant/components/frontier_silicon/__init__.py
homeassistant/components/frontier_silicon/browse_media.py
homeassistant/components/frontier_silicon/const.py
homeassistant/components/frontier_silicon/media_player.py
homeassistant/components/futurenow/light.py
homeassistant/components/garadget/cover.py
@@ -420,7 +410,6 @@ omit =
homeassistant/components/goalfeed/*
homeassistant/components/goodwe/__init__.py
homeassistant/components/goodwe/button.py
homeassistant/components/goodwe/coordinator.py
homeassistant/components/goodwe/number.py
homeassistant/components/goodwe/select.py
homeassistant/components/goodwe/sensor.py
@@ -483,6 +472,8 @@ omit =
homeassistant/components/homematic/sensor.py
homeassistant/components/homematic/switch.py
homeassistant/components/homeworks/*
homeassistant/components/honeywell/__init__.py
homeassistant/components/honeywell/climate.py
homeassistant/components/horizon/media_player.py
homeassistant/components/hp_ilo/sensor.py
homeassistant/components/huawei_lte/__init__.py
@@ -520,6 +511,9 @@ omit =
homeassistant/components/ifttt/alarm_control_panel.py
homeassistant/components/iglo/light.py
homeassistant/components/ihc/*
homeassistant/components/imap/__init__.py
homeassistant/components/imap/coordinator.py
homeassistant/components/imap/sensor.py
homeassistant/components/imap_email_content/sensor.py
homeassistant/components/incomfort/*
homeassistant/components/insteon/binary_sensor.py
@@ -628,6 +622,9 @@ omit =
homeassistant/components/lg_netcast/media_player.py
homeassistant/components/lg_soundbar/__init__.py
homeassistant/components/lg_soundbar/media_player.py
homeassistant/components/lidarr/__init__.py
homeassistant/components/lidarr/coordinator.py
homeassistant/components/lidarr/sensor.py
homeassistant/components/life360/__init__.py
homeassistant/components/life360/coordinator.py
homeassistant/components/life360/device_tracker.py
@@ -637,12 +634,6 @@ omit =
homeassistant/components/linode/*
homeassistant/components/linux_battery/sensor.py
homeassistant/components/lirc/*
homeassistant/components/livisi/__init__.py
homeassistant/components/livisi/binary_sensor.py
homeassistant/components/livisi/climate.py
homeassistant/components/livisi/coordinator.py
homeassistant/components/livisi/entity.py
homeassistant/components/livisi/switch.py
homeassistant/components/llamalab_automate/notify.py
homeassistant/components/logi_circle/__init__.py
homeassistant/components/logi_circle/camera.py
@@ -674,6 +665,7 @@ omit =
homeassistant/components/lyric/api.py
homeassistant/components/lyric/climate.py
homeassistant/components/lyric/sensor.py
homeassistant/components/magicseaweed/sensor.py
homeassistant/components/mailgun/notify.py
homeassistant/components/map/*
homeassistant/components/mastodon/notify.py
@@ -774,11 +766,7 @@ omit =
homeassistant/components/nexia/climate.py
homeassistant/components/nexia/entity.py
homeassistant/components/nexia/switch.py
homeassistant/components/nextcloud/__init__.py
homeassistant/components/nextcloud/binary_sensor.py
homeassistant/components/nextcloud/coordinator.py
homeassistant/components/nextcloud/entity.py
homeassistant/components/nextcloud/sensor.py
homeassistant/components/nextcloud/*
homeassistant/components/nfandroidtv/__init__.py
homeassistant/components/nfandroidtv/notify.py
homeassistant/components/nibe_heatpump/__init__.py
@@ -810,10 +798,7 @@ omit =
homeassistant/components/nuki/sensor.py
homeassistant/components/nx584/alarm_control_panel.py
homeassistant/components/oasa_telematics/sensor.py
homeassistant/components/obihai/__init__.py
homeassistant/components/obihai/button.py
homeassistant/components/obihai/connectivity.py
homeassistant/components/obihai/sensor.py
homeassistant/components/obihai/*
homeassistant/components/octoprint/__init__.py
homeassistant/components/oem/climate.py
homeassistant/components/ohmconnect/sensor.py
@@ -833,7 +818,6 @@ omit =
homeassistant/components/onvif/event.py
homeassistant/components/onvif/parsers.py
homeassistant/components/onvif/sensor.py
homeassistant/components/onvif/util.py
homeassistant/components/open_meteo/weather.py
homeassistant/components/opencv/*
homeassistant/components/openevse/sensor.py
@@ -909,6 +893,7 @@ omit =
homeassistant/components/ping/binary_sensor.py
homeassistant/components/ping/device_tracker.py
homeassistant/components/pioneer/media_player.py
homeassistant/components/pjlink/media_player.py
homeassistant/components/plaato/__init__.py
homeassistant/components/plaato/binary_sensor.py
homeassistant/components/plaato/entity.py
@@ -941,7 +926,6 @@ omit =
homeassistant/components/pushover/notify.py
homeassistant/components/pushsafer/notify.py
homeassistant/components/pyload/sensor.py
homeassistant/components/qbittorrent/__init__.py
homeassistant/components/qbittorrent/sensor.py
homeassistant/components/qnap/sensor.py
homeassistant/components/qrcode/image_processing.py
@@ -978,28 +962,20 @@ omit =
homeassistant/components/rejseplanen/sensor.py
homeassistant/components/remember_the_milk/__init__.py
homeassistant/components/remote_rpi_gpio/*
homeassistant/components/reolink/__init__.py
homeassistant/components/reolink/binary_sensor.py
homeassistant/components/reolink/button.py
homeassistant/components/reolink/camera.py
homeassistant/components/reolink/entity.py
homeassistant/components/reolink/host.py
homeassistant/components/reolink/light.py
homeassistant/components/reolink/number.py
homeassistant/components/reolink/select.py
homeassistant/components/reolink/siren.py
homeassistant/components/reolink/switch.py
homeassistant/components/reolink/update.py
homeassistant/components/repetier/__init__.py
homeassistant/components/repetier/sensor.py
homeassistant/components/rest/notify.py
homeassistant/components/rest/switch.py
homeassistant/components/ridwell/__init__.py
homeassistant/components/ridwell/calendar.py
homeassistant/components/ridwell/coordinator.py
homeassistant/components/ridwell/switch.py
homeassistant/components/ring/camera.py
homeassistant/components/ripple/sensor.py
homeassistant/components/roborock/coordinator.py
homeassistant/components/rocketchat/notify.py
homeassistant/components/roomba/__init__.py
homeassistant/components/roomba/binary_sensor.py
@@ -1032,7 +1008,6 @@ omit =
homeassistant/components/screenlogic/__init__.py
homeassistant/components/screenlogic/binary_sensor.py
homeassistant/components/screenlogic/climate.py
homeassistant/components/screenlogic/entity.py
homeassistant/components/screenlogic/light.py
homeassistant/components/screenlogic/number.py
homeassistant/components/screenlogic/sensor.py
@@ -1105,9 +1080,7 @@ omit =
homeassistant/components/sms/notify.py
homeassistant/components/sms/sensor.py
homeassistant/components/smtp/notify.py
homeassistant/components/snapcast/__init__.py
homeassistant/components/snapcast/media_player.py
homeassistant/components/snapcast/server.py
homeassistant/components/snapcast/*
homeassistant/components/snmp/device_tracker.py
homeassistant/components/snmp/sensor.py
homeassistant/components/snmp/switch.py
@@ -1295,12 +1268,6 @@ omit =
homeassistant/components/totalconnect/binary_sensor.py
homeassistant/components/touchline/climate.py
homeassistant/components/tplink_lte/*
homeassistant/components/tplink_omada/__init__.py
homeassistant/components/tplink_omada/controller.py
homeassistant/components/tplink_omada/coordinator.py
homeassistant/components/tplink_omada/entity.py
homeassistant/components/tplink_omada/switch.py
homeassistant/components/tplink_omada/update.py
homeassistant/components/traccar/device_tracker.py
homeassistant/components/tractive/__init__.py
homeassistant/components/tractive/binary_sensor.py
@@ -1368,7 +1335,6 @@ omit =
homeassistant/components/velbus/entity.py
homeassistant/components/velbus/light.py
homeassistant/components/velbus/sensor.py
homeassistant/components/velbus/select.py
homeassistant/components/velbus/switch.py
homeassistant/components/velux/__init__.py
homeassistant/components/velux/cover.py
@@ -1386,6 +1352,8 @@ omit =
homeassistant/components/verisure/sensor.py
homeassistant/components/verisure/switch.py
homeassistant/components/versasense/*
homeassistant/components/vesync/__init__.py
homeassistant/components/vesync/common.py
homeassistant/components/vesync/fan.py
homeassistant/components/vesync/light.py
homeassistant/components/vesync/sensor.py
@@ -1441,6 +1409,7 @@ omit =
homeassistant/components/xbox/media_player.py
homeassistant/components/xbox/remote.py
homeassistant/components/xbox/sensor.py
homeassistant/components/xbox_live/sensor.py
homeassistant/components/xeoma/camera.py
homeassistant/components/xiaomi/camera.py
homeassistant/components/xiaomi_aqara/__init__.py
@@ -1513,8 +1482,8 @@ omit =
homeassistant/components/zeversolar/coordinator.py
homeassistant/components/zeversolar/entity.py
homeassistant/components/zeversolar/sensor.py
homeassistant/components/zha/websocket_api.py
homeassistant/components/zha/core/cluster_handlers/*
homeassistant/components/zha/api.py
homeassistant/components/zha/core/channels/*
homeassistant/components/zha/core/device.py
homeassistant/components/zha/core/gateway.py
homeassistant/components/zha/core/helpers.py

View File

@@ -20,6 +20,7 @@
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.formatting.blackPath": "/usr/local/bin/black",
"python.linting.flake8Path": "/usr/local/bin/flake8",
"python.linting.pycodestylePath": "/usr/local/bin/pycodestyle",
"python.linting.pydocstylePath": "/usr/local/bin/pydocstyle",
"python.linting.mypyPath": "/usr/local/bin/mypy",

1
.gitattributes vendored
View File

@@ -8,6 +8,5 @@
*.png binary
*.zip binary
*.mp3 binary
*.pcm binary
Dockerfile.dev linguist-language=Dockerfile

View File

@@ -31,9 +31,9 @@ body:
label: What version of Home Assistant Core has the issue?
placeholder: core-
description: >
Can be found in: [Settings ⇒ System ⇒ Repairs ⇒ Three Dots in Upper Right ⇒ System information](https://my.home-assistant.io/redirect/system_health/).
Can be found in: [Settings -> About](https://my.home-assistant.io/redirect/info/).
[![Open your Home Assistant instance and show the system information.](https://my.home-assistant.io/badges/system_health.svg)](https://my.home-assistant.io/redirect/system_health/)
[![Open your Home Assistant instance and show your Home Assistant version information.](https://my.home-assistant.io/badges/info.svg)](https://my.home-assistant.io/redirect/info/)
- type: input
attributes:
label: What was the last working version of Home Assistant Core?
@@ -46,9 +46,9 @@ body:
attributes:
label: What type of installation are you running?
description: >
Can be found in: [Settings System Repairs Three Dots in Upper Right System information](https://my.home-assistant.io/redirect/system_health/).
Can be found in: [Settings -> System-> Repairs -> Three Dots in Upper Right -> System information](https://my.home-assistant.io/redirect/system_health/).
[![Open your Home Assistant instance and show the system information.](https://my.home-assistant.io/badges/system_health.svg)](https://my.home-assistant.io/redirect/system_health/)
[![Open your Home Assistant instance and show health information about your system.](https://my.home-assistant.io/badges/system_health.svg)](https://my.home-assistant.io/redirect/system_health/)
options:
- Home Assistant OS
- Home Assistant Container

View File

@@ -1,6 +1,6 @@
blank_issues_enabled: false
contact_links:
- name: Report a bug with the UI, Frontend or Dashboards
- name: Report a bug with the UI, Frontend or Lovelace
url: https://github.com/home-assistant/frontend/issues
about: This is the issue tracker for our backend. Please report issues with the UI in the frontend repository.
- name: Report incorrect or missing information on our website

View File

@@ -59,7 +59,6 @@
- [ ] Local tests pass. **Your PR cannot be merged unless tests pass**
- [ ] There is no commented out code in this PR.
- [ ] I have followed the [development checklist][dev-checklist]
- [ ] I have followed the [perfect PR recommendations][perfect-pr]
- [ ] The code has been formatted using Black (`black --fast homeassistant tests`)
- [ ] Tests have been added to verify that the new code works.
@@ -108,4 +107,3 @@ To help with the load of incoming pull requests:
[manifest-docs]: https://developers.home-assistant.io/docs/en/creating_integration_manifest.html
[quality-scale]: https://developers.home-assistant.io/docs/en/next/integration_quality_scale_index.html
[docs-repository]: https://github.com/home-assistant/home-assistant.io
[perfect-pr]: https://developers.home-assistant.io/docs/review-process/#creating-the-perfect-pr

View File

@@ -24,12 +24,12 @@ jobs:
publish: ${{ steps.version.outputs.publish }}
steps:
- name: Checkout the repository
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
with:
fetch-depth: 0
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v4.6.0
uses: actions/setup-python@v4.5.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
@@ -67,18 +67,13 @@ jobs:
if: github.repository_owner == 'home-assistant' && needs.init.outputs.publish == 'true'
steps:
- name: Checkout the repository
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v4.6.0
uses: actions/setup-python@v4.5.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Download Translations
run: python3 -m script.translations download
env:
LOKALISE_TOKEN: ${{ secrets.LOKALISE_TOKEN }}
- name: Build package
shell: bash
run: |
@@ -105,7 +100,7 @@ jobs:
arch: ${{ fromJson(needs.init.outputs.architectures) }}
steps:
- name: Checkout the repository
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Download nightly wheels of frontend
if: needs.init.outputs.channel == 'dev'
@@ -131,7 +126,7 @@ jobs:
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
if: needs.init.outputs.channel == 'dev'
uses: actions/setup-python@v4.6.0
uses: actions/setup-python@v4.5.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
@@ -174,11 +169,6 @@ jobs:
python -m script.gen_requirements_all
fi
- name: Download Translations
run: python3 -m script.translations download
env:
LOKALISE_TOKEN: ${{ secrets.LOKALISE_TOKEN }}
- name: Write meta info file
shell: bash
run: |
@@ -198,7 +188,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build base image
uses: home-assistant/builder@2023.03.0
uses: home-assistant/builder@2022.11.0
with:
args: |
$BUILD_ARGS \
@@ -208,17 +198,6 @@ jobs:
env:
CAS_API_KEY: ${{ secrets.CAS_TOKEN }}
- name: Archive translations
shell: bash
run: find ./homeassistant/components/*/translations -name "*.json" | tar zcvf translations.tar.gz -T -
- name: Upload translations
uses: actions/upload-artifact@v3
with:
name: translations
path: translations.tar.gz
if-no-files-found: error
build_machine:
name: Build ${{ matrix.machine }} machine core image
if: github.repository_owner == 'home-assistant'
@@ -232,7 +211,6 @@ jobs:
- khadas-vim3
- odroid-c2
- odroid-c4
- odroid-m1
- odroid-n2
- odroid-xu
- qemuarm
@@ -249,7 +227,7 @@ jobs:
- yellow
steps:
- name: Checkout the repository
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Set build additional args
run: |
@@ -276,7 +254,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build base image
uses: home-assistant/builder@2023.03.0
uses: home-assistant/builder@2022.11.0
with:
args: |
$BUILD_ARGS \
@@ -292,7 +270,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Initialize git
uses: home-assistant/actions/helpers/git-init@master
@@ -331,7 +309,7 @@ jobs:
- "homeassistant"
steps:
- name: Checkout the repository
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Login to DockerHub
if: matrix.registry == 'homeassistant'

View File

@@ -1,5 +1,4 @@
name: CI
run-name: "${{ github.event_name == 'workflow_dispatch' && format('CI: {0}', github.ref_name) || '' }}"
# yamllint disable-line rule:truthy
on:
@@ -29,26 +28,12 @@ on:
type: boolean
env:
CACHE_VERSION: 5
PIP_CACHE_VERSION: 4
MYPY_CACHE_VERSION: 4
HA_SHORT_VERSION: 2023.5
CACHE_VERSION: 3
PIP_CACHE_VERSION: 3
MYPY_CACHE_VERSION: 3
HA_SHORT_VERSION: 2023.3
DEFAULT_PYTHON: "3.10"
ALL_PYTHON_VERSIONS: "['3.10', '3.11']"
# 10.3 is the oldest supported version
# - 10.3.32 is the version currently shipped with Synology (as of 17 Feb 2022)
# 10.6 is the current long-term-support
# - 10.6.10 is the version currently shipped with the Add-on (as of 31 Jan 2023)
# 10.10 is the latest short-term-support
# - 10.10.3 is the latest (as of 6 Feb 2023)
# mysql 8.0.32 does not always behave the same as MariaDB
# and some queries that work on MariaDB do not work on MySQL
MARIADB_VERSIONS: "['mariadb:10.3.32','mariadb:10.6.10','mariadb:10.10.3','mysql:8.0.32']"
# 12 is the oldest supported version
# - 12.14 is the latest (as of 9 Feb 2023)
# 15 is the latest version
# - 15.2 is the latest (as of 9 Feb 2023)
POSTGRESQL_VERSIONS: "['postgres:12.14','postgres:15.2']"
ALL_PYTHON_VERSIONS: "['3.10']"
PRE_COMMIT_CACHE: ~/.cache/pre-commit
PIP_CACHE: /tmp/pip-cache
SQLALCHEMY_WARN_20: 1
@@ -71,18 +56,16 @@ jobs:
pre-commit_cache_key: ${{ steps.generate_pre-commit_cache_key.outputs.key }}
python_cache_key: ${{ steps.generate_python_cache_key.outputs.key }}
requirements: ${{ steps.core.outputs.requirements }}
mariadb_groups: ${{ steps.info.outputs.mariadb_groups }}
postgresql_groups: ${{ steps.info.outputs.postgresql_groups }}
python_versions: ${{ steps.info.outputs.python_versions }}
test_full_suite: ${{ steps.info.outputs.test_full_suite }}
test_group_count: ${{ steps.info.outputs.test_group_count }}
test_groups: ${{ steps.info.outputs.test_groups }}
tests_glob: ${{ steps.info.outputs.tests_glob }}
tests: ${{ steps.info.outputs.tests }}
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Generate partial Python venv restore key
id: generate_python_cache_key
run: >-
@@ -120,8 +103,6 @@ jobs:
run: |
# Defaults
integrations_glob=""
mariadb_groups=${MARIADB_VERSIONS}
postgresql_groups=${POSTGRESQL_VERSIONS}
test_full_suite="true"
test_groups="[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]"
test_group_count=10
@@ -155,8 +136,6 @@ jobs:
tests_glob=$(echo "${tests}" | jq -cSr '. | join(",")')
[[ "${tests_glob}" == *","* ]] && tests_glob="{${tests_glob}}"
mariadb_groups="[]"
postgresql_groups="[]"
test_full_suite="false"
fi
@@ -169,18 +148,12 @@ jobs:
|| [[ "${{ github.event.inputs.full }}" == "true" ]] \
|| [[ "${{ contains(github.event.pull_request.labels.*.name, 'ci-full-run') }}" == "true" ]];
then
mariadb_groups=${MARIADB_VERSIONS}
postgresql_groups=${POSTGRESQL_VERSIONS}
test_groups="[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]"
test_group_count=10
test_full_suite="true"
fi
# Output & sent to GitHub Actions
echo "mariadb_groups: ${mariadb_groups}"
echo "mariadb_groups=${mariadb_groups}" >> $GITHUB_OUTPUT
echo "postgresql_groups: ${postgresql_groups}"
echo "postgresql_groups=${postgresql_groups}" >> $GITHUB_OUTPUT
echo "python_versions: ${ALL_PYTHON_VERSIONS}"
echo "python_versions=${ALL_PYTHON_VERSIONS}" >> $GITHUB_OUTPUT
echo "test_full_suite: ${test_full_suite}"
@@ -198,7 +171,7 @@ jobs:
pre-commit:
name: Prepare pre-commit base
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
if: |
github.event.inputs.pylint-only != 'true'
&& github.event.inputs.mypy-only != 'true'
@@ -206,16 +179,16 @@ jobs:
- info
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
id: python
uses: actions/setup-python@v4.6.0
uses: actions/setup-python@v4.5.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
check-latest: true
- name: Restore base Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.1
uses: actions/cache@v3.2.4
with:
path: venv
key: >-
@@ -230,10 +203,9 @@ jobs:
pip install "$(cat requirements_test.txt | grep pre-commit)"
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v3.3.1
uses: actions/cache@v3.2.4
with:
path: ${{ env.PRE_COMMIT_CACHE }}
lookup-only: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.pre-commit_cache_key }}
@@ -245,22 +217,22 @@ jobs:
lint-black:
name: Check black
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
needs:
- info
- pre-commit
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v4.6.0
uses: actions/setup-python@v4.5.0
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
check-latest: true
- name: Restore base Python virtual environment
id: cache-venv
uses: actions/cache/restore@v3.3.1
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
@@ -269,7 +241,7 @@ jobs:
needs.info.outputs.pre-commit_cache_key }}
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache/restore@v3.3.1
uses: actions/cache/restore@v3.2.4
with:
path: ${{ env.PRE_COMMIT_CACHE }}
fail-on-cache-miss: true
@@ -289,24 +261,24 @@ jobs:
shopt -s globstar
pre-commit run --hook-stage manual black --files {homeassistant,tests}/components/${{ needs.info.outputs.integrations_glob }}/{*,**/*} --show-diff-on-failure
lint-ruff:
name: Check ruff
runs-on: ubuntu-22.04
lint-flake8:
name: Check flake8
runs-on: ubuntu-20.04
needs:
- info
- pre-commit
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v4.6.0
uses: actions/setup-python@v4.5.0
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
check-latest: true
- name: Restore base Python virtual environment
id: cache-venv
uses: actions/cache/restore@v3.3.1
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
@@ -315,7 +287,56 @@ jobs:
needs.info.outputs.pre-commit_cache_key }}
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache/restore@v3.3.1
uses: actions/cache/restore@v3.2.4
with:
path: ${{ env.PRE_COMMIT_CACHE }}
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.pre-commit_cache_key }}
- name: Register flake8 problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/flake8.json"
- name: Run flake8 (fully)
if: needs.info.outputs.test_full_suite == 'true'
run: |
. venv/bin/activate
pre-commit run --hook-stage manual flake8 --all-files
- name: Run flake8 (partially)
if: needs.info.outputs.test_full_suite == 'false'
shell: bash
run: |
. venv/bin/activate
shopt -s globstar
pre-commit run --hook-stage manual flake8 --files {homeassistant,tests}/components/${{ needs.info.outputs.integrations_glob }}/{*,**/*}
lint-ruff:
name: Check ruff
runs-on: ubuntu-latest
needs:
- info
- pre-commit
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.3.0
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v4.5.0
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
check-latest: true
- name: Restore base Python virtual environment
id: cache-venv
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-venv-${{
needs.info.outputs.pre-commit_cache_key }}
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache/restore@v3.2.4
with:
path: ${{ env.PRE_COMMIT_CACHE }}
fail-on-cache-miss: true
@@ -329,33 +350,33 @@ jobs:
if: needs.info.outputs.test_full_suite == 'true'
run: |
. venv/bin/activate
pre-commit run --hook-stage manual ruff --all-files --show-diff-on-failure
pre-commit run --hook-stage manual ruff --all-files
- name: Run ruff (partially)
if: needs.info.outputs.test_full_suite == 'false'
shell: bash
run: |
. venv/bin/activate
shopt -s globstar
pre-commit run --hook-stage manual ruff --files {homeassistant,tests}/components/${{ needs.info.outputs.integrations_glob }}/{*,**/*} --show-diff-on-failure
pre-commit run --hook-stage manual ruff --files {homeassistant,tests}/components/${{ needs.info.outputs.integrations_glob }}/{*,**/*}
lint-isort:
name: Check isort
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
needs:
- info
- pre-commit
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v4.6.0
uses: actions/setup-python@v4.5.0
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
check-latest: true
- name: Restore base Python virtual environment
id: cache-venv
uses: actions/cache/restore@v3.3.1
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
@@ -364,7 +385,7 @@ jobs:
needs.info.outputs.pre-commit_cache_key }}
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache/restore@v3.3.1
uses: actions/cache/restore@v3.2.4
with:
path: ${{ env.PRE_COMMIT_CACHE }}
fail-on-cache-miss: true
@@ -378,22 +399,22 @@ jobs:
lint-other:
name: Check other linters
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
needs:
- info
- pre-commit
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v4.6.0
uses: actions/setup-python@v4.5.0
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
check-latest: true
- name: Restore base Python virtual environment
id: cache-venv
uses: actions/cache/restore@v3.3.1
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
@@ -402,7 +423,7 @@ jobs:
needs.info.outputs.pre-commit_cache_key }}
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache/restore@v3.3.1
uses: actions/cache/restore@v3.2.4
with:
path: ${{ env.PRE_COMMIT_CACHE }}
fail-on-cache-miss: true
@@ -410,6 +431,19 @@ jobs:
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.pre-commit_cache_key }}
- name: Run pyupgrade (fully)
if: needs.info.outputs.test_full_suite == 'true'
run: |
. venv/bin/activate
pre-commit run --hook-stage manual pyupgrade --all-files --show-diff-on-failure
- name: Run pyupgrade (partially)
if: needs.info.outputs.test_full_suite == 'false'
shell: bash
run: |
. venv/bin/activate
shopt -s globstar
pre-commit run --hook-stage manual pyupgrade --files {homeassistant,tests}/components/${{ needs.info.outputs.integrations_glob }}/{*,**/*} --show-diff-on-failure
- name: Register yamllint problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/yamllint.json"
@@ -437,7 +471,6 @@ jobs:
shell: bash
run: |
. venv/bin/activate
shopt -s globstar
pre-commit run --hook-stage manual prettier --files {homeassistant,tests}/components/${{ needs.info.outputs.integrations_glob }}/{*,**/*}
- name: Register check executables problem matcher
@@ -483,7 +516,7 @@ jobs:
base:
name: Prepare dependencies
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
needs: info
timeout-minutes: 60
strategy:
@@ -491,10 +524,10 @@ jobs:
python-version: ${{ fromJSON(needs.info.outputs.python_versions) }}
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Set up Python ${{ matrix.python-version }}
id: python
uses: actions/setup-python@v4.6.0
uses: actions/setup-python@v4.5.0
with:
python-version: ${{ matrix.python-version }}
check-latest: true
@@ -505,16 +538,15 @@ jobs:
env.HA_SHORT_VERSION }}-$(date -u '+%Y-%m-%dT%H:%M:%s')" >> $GITHUB_OUTPUT
- name: Restore base Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.1
uses: actions/cache@v3.2.4
with:
path: venv
lookup-only: true
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Restore pip wheel cache
if: steps.cache-venv.outputs.cache-hit != 'true'
uses: actions/cache@v3.3.1
uses: actions/cache@v3.2.4
with:
path: ${{ env.PIP_CACHE }}
key: >-
@@ -543,14 +575,14 @@ jobs:
python -m venv venv
. venv/bin/activate
python --version
pip install --cache-dir=$PIP_CACHE -U "pip>=21.0,<23.2" setuptools wheel
pip install --cache-dir=$PIP_CACHE -U "pip>=21.0,<22.4" setuptools wheel
pip install --cache-dir=$PIP_CACHE -r requirements_all.txt --use-deprecated=legacy-resolver
pip install --cache-dir=$PIP_CACHE -r requirements_test.txt --use-deprecated=legacy-resolver
pip install -e .
hassfest:
name: Check hassfest
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
if: |
github.event.inputs.pylint-only != 'true'
&& github.event.inputs.mypy-only != 'true'
@@ -559,16 +591,16 @@ jobs:
- base
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
id: python
uses: actions/setup-python@v4.6.0
uses: actions/setup-python@v4.5.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
check-latest: true
- name: Restore full Python ${{ env.DEFAULT_PYTHON }} virtual environment
id: cache-venv
uses: actions/cache/restore@v3.3.1
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
@@ -582,7 +614,7 @@ jobs:
gen-requirements-all:
name: Check all requirements
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
if: |
github.event.inputs.pylint-only != 'true'
&& github.event.inputs.mypy-only != 'true'
@@ -591,16 +623,16 @@ jobs:
- base
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
id: python
uses: actions/setup-python@v4.6.0
uses: actions/setup-python@v4.5.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
check-latest: true
- name: Restore base Python virtual environment
id: cache-venv
uses: actions/cache/restore@v3.3.1
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
@@ -614,7 +646,7 @@ jobs:
pylint:
name: Check pylint
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
timeout-minutes: 20
if: |
github.event.inputs.mypy-only != 'true'
@@ -624,16 +656,16 @@ jobs:
- base
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
id: python
uses: actions/setup-python@v4.6.0
uses: actions/setup-python@v4.5.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
check-latest: true
- name: Restore full Python ${{ env.DEFAULT_PYTHON }} virtual environment
id: cache-venv
uses: actions/cache/restore@v3.3.1
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
@@ -659,7 +691,7 @@ jobs:
mypy:
name: Check mypy
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
if: |
github.event.inputs.pylint-only != 'true'
|| github.event.inputs.mypy-only == 'true'
@@ -668,10 +700,10 @@ jobs:
- base
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
id: python
uses: actions/setup-python@v4.6.0
uses: actions/setup-python@v4.5.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
check-latest: true
@@ -684,7 +716,7 @@ jobs:
env.HA_SHORT_VERSION }}-$(date -u '+%Y-%m-%dT%H:%M:%s')" >> $GITHUB_OUTPUT
- name: Restore full Python ${{ env.DEFAULT_PYTHON }} virtual environment
id: cache-venv
uses: actions/cache/restore@v3.3.1
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
@@ -692,7 +724,7 @@ jobs:
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Restore mypy cache
uses: actions/cache@v3.3.1
uses: actions/cache@v3.2.4
with:
path: .mypy_cache
key: >-
@@ -720,7 +752,7 @@ jobs:
mypy homeassistant/components/${{ needs.info.outputs.integrations_glob }}
pip-check:
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
if: |
github.event.inputs.pylint-only != 'true'
&& github.event.inputs.mypy-only != 'true'
@@ -734,16 +766,16 @@ jobs:
name: Run pip check ${{ matrix.python-version }}
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Set up Python ${{ matrix.python-version }}
id: python
uses: actions/setup-python@v4.6.0
uses: actions/setup-python@v4.5.0
with:
python-version: ${{ matrix.python-version }}
check-latest: true
- name: Restore full Python ${{ matrix.python-version }} virtual environment
id: cache-venv
uses: actions/cache/restore@v3.3.1
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
@@ -756,7 +788,7 @@ jobs:
./script/pip_check $PIP_CACHE
pytest:
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
if: |
(github.event_name != 'push' || github.event.repository.full_name == 'home-assistant/core')
&& github.event.inputs.lint-only != 'true'
@@ -768,6 +800,7 @@ jobs:
- base
- gen-requirements-all
- hassfest
- lint-black
- lint-isort
- lint-other
- lint-ruff
@@ -787,16 +820,16 @@ jobs:
bluez \
ffmpeg
- name: Check out code from GitHub
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Set up Python ${{ matrix.python-version }}
id: python
uses: actions/setup-python@v4.6.0
uses: actions/setup-python@v4.5.0
with:
python-version: ${{ matrix.python-version }}
check-latest: true
- name: Restore full Python ${{ matrix.python-version }} virtual environment
id: cache-venv
uses: actions/cache/restore@v3.3.1
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
@@ -815,10 +848,6 @@ jobs:
- name: Register pytest slow test problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/pytest-slow.json"
- name: Compile English translations
run: |
. venv/bin/activate
python3 -m script.translations develop --all
- name: Run pytest (fully)
if: needs.info.outputs.test_full_suite == 'true'
timeout-minutes: 60
@@ -873,10 +902,10 @@ jobs:
./script/check_dirty
pytest-mariadb:
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
services:
mariadb:
image: ${{ matrix.mariadb-group }}
image: mariadb:10.9.3
ports:
- 3306:3306
env:
@@ -887,12 +916,13 @@ jobs:
&& github.event.inputs.lint-only != 'true'
&& github.event.inputs.pylint-only != 'true'
&& github.event.inputs.mypy-only != 'true'
&& needs.info.outputs.mariadb_groups != '[]'
&& needs.info.outputs.test_full_suite == 'true'
needs:
- info
- base
- gen-requirements-all
- hassfest
- lint-black
- lint-isort
- lint-other
- lint-ruff
@@ -901,9 +931,8 @@ jobs:
fail-fast: false
matrix:
python-version: ${{ fromJson(needs.info.outputs.python_versions) }}
mariadb-group: ${{ fromJson(needs.info.outputs.mariadb_groups) }}
name: >-
Run ${{ matrix.mariadb-group }} tests Python ${{ matrix.python-version }}
Run tests Python ${{ matrix.python-version }} (mariadb)
steps:
- name: Install additional OS dependencies
run: |
@@ -913,16 +942,16 @@ jobs:
ffmpeg \
libmariadb-dev-compat
- name: Check out code from GitHub
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Set up Python ${{ matrix.python-version }}
id: python
uses: actions/setup-python@v4.6.0
uses: actions/setup-python@v4.5.0
with:
python-version: ${{ matrix.python-version }}
check-latest: true
- name: Restore full Python ${{ matrix.python-version }} virtual environment
id: cache-venv
uses: actions/cache/restore@v3.3.1
uses: actions/cache/restore@v3.2.4
with:
path: venv
fail-on-cache-miss: true
@@ -945,12 +974,8 @@ jobs:
run: |
. venv/bin/activate
pip install mysqlclient sqlalchemy_utils
- name: Compile English translations
run: |
. venv/bin/activate
python3 -m script.translations develop --all
- name: Run pytest (partially)
timeout-minutes: 20
timeout-minutes: 15
shell: bash
run: |
. venv/bin/activate
@@ -967,10 +992,7 @@ jobs:
--durations=10 \
-p no:sugar \
--dburl=mysql://root:password@127.0.0.1/homeassistant-test \
tests/components/history \
tests/components/logbook \
tests/components/recorder \
tests/components/sensor
tests/components/recorder
- name: Upload coverage artifact
uses: actions/upload-artifact@v3.1.2
with:
@@ -980,143 +1002,22 @@ jobs:
run: |
./script/check_dirty
pytest-postgres:
runs-on: ubuntu-22.04
services:
postgres:
image: ${{ matrix.postgresql-group }}
ports:
- 5432:5432
env:
POSTGRES_PASSWORD: password
options: --health-cmd="pg_isready -hlocalhost -Upostgres" --health-interval=5s --health-timeout=2s --health-retries=3
if: |
(github.event_name != 'push' || github.event.repository.full_name == 'home-assistant/core')
&& github.event.inputs.lint-only != 'true'
&& github.event.inputs.pylint-only != 'true'
&& github.event.inputs.mypy-only != 'true'
&& needs.info.outputs.postgresql_groups != '[]'
needs:
- info
- base
- gen-requirements-all
- hassfest
- lint-isort
- lint-other
- lint-ruff
- mypy
strategy:
fail-fast: false
matrix:
python-version: ${{ fromJson(needs.info.outputs.python_versions) }}
postgresql-group: ${{ fromJson(needs.info.outputs.postgresql_groups) }}
name: >-
Run ${{ matrix.postgresql-group }} tests Python ${{ matrix.python-version }}
steps:
- name: Install additional OS dependencies
run: |
sudo apt-get update
sudo apt-get -y install \
bluez \
ffmpeg \
postgresql-server-dev-14
- name: Check out code from GitHub
uses: actions/checkout@v3.5.2
- name: Set up Python ${{ matrix.python-version }}
id: python
uses: actions/setup-python@v4.6.0
with:
python-version: ${{ matrix.python-version }}
check-latest: true
- name: Restore full Python ${{ matrix.python-version }} virtual environment
id: cache-venv
uses: actions/cache/restore@v3.3.1
with:
path: venv
fail-on-cache-miss: true
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.info.outputs.python_cache_key }}
- name: Register Python problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/python.json"
- name: Install Pytest Annotation plugin
run: |
. venv/bin/activate
# Ideally this should be part of our dependencies
# However this plugin is fairly new and doesn't run correctly
# on a non-GitHub environment.
pip install pytest-github-actions-annotate-failures==0.1.3
- name: Register pytest slow test problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/pytest-slow.json"
- name: Install SQL Python libraries
run: |
. venv/bin/activate
pip install psycopg2 sqlalchemy_utils
- name: Compile English translations
run: |
. venv/bin/activate
python3 -m script.translations develop --all
- name: Run pytest (partially)
timeout-minutes: 20
shell: bash
run: |
. venv/bin/activate
python --version
python3 -X dev -m pytest \
-qq \
--timeout=9 \
-n 1 \
--cov="homeassistant.components.recorder" \
--cov-report=xml \
--cov-report=term-missing \
-o console_output_style=count \
--durations=0 \
--durations-min=10 \
-p no:sugar \
--dburl=postgresql://postgres:password@127.0.0.1/homeassistant-test \
tests/components/history \
tests/components/logbook \
tests/components/recorder \
tests/components/sensor
- name: Upload coverage artifact
uses: actions/upload-artifact@v3.1.0
with:
name: coverage-${{ matrix.python-version }}-postgresql
path: coverage.xml
- name: Check dirty
run: |
./script/check_dirty
coverage:
name: Upload test coverage to Codecov
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
needs:
- info
- pytest
timeout-minutes: 10
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Download all coverage artifacts
uses: actions/download-artifact@v3
- name: Upload coverage to Codecov (full coverage)
if: needs.info.outputs.test_full_suite == 'true'
uses: Wandalen/wretry.action@v1.0.36
uses: codecov/codecov-action@v3.1.1
with:
action: codecov/codecov-action@v3.1.3
with: |
fail_ci_if_error: true
flags: full-suite
attempt_limit: 5
attempt_delay: 30000
flags: full-suite
- name: Upload coverage to Codecov (partial coverage)
if: needs.info.outputs.test_full_suite == 'false'
uses: Wandalen/wretry.action@v1.0.36
with:
action: codecov/codecov-action@v3.1.3
with: |
fail_ci_if_error: true
attempt_limit: 5
attempt_delay: 30000
uses: codecov/codecov-action@v3.1.1

30
.github/workflows/matchers/flake8.json vendored Normal file
View File

@@ -0,0 +1,30 @@
{
"problemMatcher": [
{
"owner": "flake8-error",
"severity": "error",
"pattern": [
{
"regexp": "^(.*):(\\d+):(\\d+):\\s([EF]\\d{3}\\s.*)$",
"file": 1,
"line": 2,
"column": 3,
"message": 4
}
]
},
{
"owner": "flake8-warning",
"severity": "warning",
"pattern": [
{
"regexp": "^(.*):(\\d+):(\\d+):\\s([CDNW]\\d{3}\\s.*)$",
"file": 1,
"line": 2,
"column": 3,
"message": 4
}
]
}
]
}

View File

@@ -17,7 +17,7 @@ jobs:
# - No PRs marked as no-stale
# - No issues (-1)
- name: 90 days stale PRs policy
uses: actions/stale@v8.0.0
uses: actions/stale@v7.0.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 90
@@ -53,7 +53,7 @@ jobs:
# - No issues marked as no-stale or help-wanted
# - No PRs (-1)
- name: 90 days stale issues
uses: actions/stale@v8.0.0
uses: actions/stale@v7.0.0
with:
repo-token: ${{ steps.token.outputs.token }}
days-before-stale: 90
@@ -83,7 +83,7 @@ jobs:
# - No Issues marked as no-stale or help-wanted
# - No PRs (-1)
- name: Needs more information stale issues policy
uses: actions/stale@v8.0.0
uses: actions/stale@v7.0.0
with:
repo-token: ${{ steps.token.outputs.token }}
only-labels: "needs-more-information"

65
.github/workflows/translations.yaml vendored Normal file
View File

@@ -0,0 +1,65 @@
name: Translations
# yamllint disable-line rule:truthy
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *"
push:
branches:
- dev
paths:
- "**strings.json"
env:
DEFAULT_PYTHON: "3.10"
jobs:
upload:
name: Upload
if: github.repository_owner == 'home-assistant'
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@v3.3.0
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v4.5.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Upload Translations
run: |
export LOKALISE_TOKEN="${{ secrets.LOKALISE_TOKEN }}"
python3 -m script.translations upload
download:
name: Download
needs: upload
if: github.repository_owner == 'home-assistant' && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@v3.3.0
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v4.5.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Download Translations
run: |
export LOKALISE_TOKEN="${{ secrets.LOKALISE_TOKEN }}"
python3 -m script.translations download
- name: Initialize git
uses: home-assistant/actions/helpers/git-init@master
with:
name: GitHub Action
email: github-action@users.noreply.github.com
- name: Update translation
run: |
git add homeassistant
git commit -am "[ci skip] Translation update"
git push

View File

@@ -1,32 +0,0 @@
name: Translations
# yamllint disable-line rule:truthy
on:
workflow_dispatch:
push:
branches:
- dev
paths:
- "**strings.json"
env:
DEFAULT_PYTHON: "3.10"
jobs:
upload:
name: Upload
if: github.repository_owner == 'home-assistant'
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@v3.5.2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v4.6.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Upload Translations
run: |
export LOKALISE_TOKEN="${{ secrets.LOKALISE_TOKEN }}"
python3 -m script.translations upload

View File

@@ -13,10 +13,6 @@ on:
- "requirements.txt"
- "requirements_all.txt"
concurrency:
group: ${{ github.workflow }}-${{ github.ref_name}}
cancel-in-progress: true
jobs:
init:
name: Initialize wheels builder
@@ -26,7 +22,7 @@ jobs:
architectures: ${{ steps.info.outputs.architectures }}
steps:
- name: Checkout the repository
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Get information
id: info
@@ -58,9 +54,6 @@ jobs:
# OpenCV headless installation
echo "CI_BUILD=1"
echo "ENABLE_HEADLESS=1"
# Use C-Extension for sqlalchemy
echo "REQUIRE_SQLALCHEMY_CEXT=1"
) > .env_file
- name: Upload env_file
@@ -76,18 +69,17 @@ jobs:
path: ./requirements_diff.txt
core:
name: Build Core wheels ${{ matrix.abi }} for ${{ matrix.arch }} (musllinux_1_2)
name: Build musllinux wheels with musllinux_1_2 / cp310 at ${{ matrix.arch }} for core
if: github.repository_owner == 'home-assistant'
needs: init
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
abi: ["cp310", "cp311"]
arch: ${{ fromJson(needs.init.outputs.architectures) }}
steps:
- name: Checkout the repository
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Download env_file
uses: actions/download-artifact@v3
@@ -100,9 +92,9 @@ jobs:
name: requirements_diff
- name: Build wheels
uses: home-assistant/wheels@2023.04.0
uses: home-assistant/wheels@2022.10.1
with:
abi: ${{ matrix.abi }}
abi: cp310
tag: musllinux_1_2
arch: ${{ matrix.arch }}
wheels-key: ${{ secrets.WHEELS_KEY }}
@@ -113,19 +105,18 @@ jobs:
requirements-diff: "requirements_diff.txt"
requirements: "requirements.txt"
integrations_cp310:
name: Build wheels ${{ matrix.abi }} for ${{ matrix.arch }}
integrations:
name: Build musllinux wheels with musllinux_1_2 / cp310 at ${{ matrix.arch }} for integrations
if: github.repository_owner == 'home-assistant'
needs: init
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
abi: ["cp310"]
arch: ${{ fromJson(needs.init.outputs.architectures) }}
steps:
- name: Checkout the repository
uses: actions/checkout@v3.5.2
uses: actions/checkout@v3.3.0
- name: Download env_file
uses: actions/download-artifact@v3
@@ -141,7 +132,6 @@ jobs:
run: |
requirement_files="requirements_all.txt requirements_diff.txt"
for requirement_file in ${requirement_files}; do
sed -i "s|# azure-servicebus|azure-servicebus|g" ${requirement_file}
sed -i "s|# pybluez|pybluez|g" ${requirement_file}
sed -i "s|# beacontools|beacontools|g" ${requirement_file}
sed -i "s|# fritzconnection|fritzconnection|g" ${requirement_file}
@@ -178,177 +168,30 @@ jobs:
sed -i "/numpy/d" homeassistant/package_constraints.txt
- name: Build wheels (part 1)
uses: home-assistant/wheels@2023.04.0
uses: home-assistant/wheels@2022.10.1
with:
abi: ${{ matrix.abi }}
abi: cp310
tag: musllinux_1_2
arch: ${{ matrix.arch }}
wheels-key: ${{ secrets.WHEELS_KEY }}
env-file: true
apk: "bluez-dev;libffi-dev;openssl-dev;glib-dev;eudev-dev;libxml2-dev;libxslt-dev;libpng-dev;libjpeg-turbo-dev;tiff-dev;cups-dev;gmp-dev;mpfr-dev;mpc1-dev;ffmpeg-dev;gammu-dev;yaml-dev;openblas-dev;fftw-dev;lapack-dev;gfortran;blas-dev;eigen-dev;freetype-dev;glew-dev;harfbuzz-dev;hdf5-dev;libdc1394-dev;libtbb-dev;mesa-dev;openexr-dev;openjpeg-dev;uchardet-dev"
skip-binary: aiohttp;grpcio;sqlalchemy;protobuf
apk: "libexecinfo-dev;bluez-dev;libffi-dev;openssl-dev;glib-dev;eudev-dev;libxml2-dev;libxslt-dev;libpng-dev;libjpeg-turbo-dev;tiff-dev;cups-dev;gmp-dev;mpfr-dev;mpc1-dev;ffmpeg-dev;gammu-dev;yaml-dev;openblas-dev;fftw-dev;lapack-dev;gfortran;blas-dev;eigen-dev;freetype-dev;glew-dev;harfbuzz-dev;hdf5-dev;libdc1394-dev;libtbb-dev;mesa-dev;openexr-dev;openjpeg-dev"
skip-binary: aiohttp;grpcio
legacy: true
constraints: "homeassistant/package_constraints.txt"
requirements-diff: "requirements_diff.txt"
requirements: "requirements_all.txtaa"
- name: Build wheels (part 2)
uses: home-assistant/wheels@2023.04.0
uses: home-assistant/wheels@2022.10.1
with:
abi: ${{ matrix.abi }}
abi: cp310
tag: musllinux_1_2
arch: ${{ matrix.arch }}
wheels-key: ${{ secrets.WHEELS_KEY }}
env-file: true
apk: "bluez-dev;libffi-dev;openssl-dev;glib-dev;eudev-dev;libxml2-dev;libxslt-dev;libpng-dev;libjpeg-turbo-dev;tiff-dev;cups-dev;gmp-dev;mpfr-dev;mpc1-dev;ffmpeg-dev;gammu-dev;yaml-dev;openblas-dev;fftw-dev;lapack-dev;gfortran;blas-dev;eigen-dev;freetype-dev;glew-dev;harfbuzz-dev;hdf5-dev;libdc1394-dev;libtbb-dev;mesa-dev;openexr-dev;openjpeg-dev;uchardet-dev"
skip-binary: aiohttp;grpcio;sqlalchemy;protobuf
legacy: true
constraints: "homeassistant/package_constraints.txt"
requirements-diff: "requirements_diff.txt"
requirements: "requirements_all.txtab"
# Wheels building for the cp311 ABI is currently split
# This is mainly until we have figured out to get all wheels built.
# Without harming our current workflow.
integrations_cp311:
name: Build wheels ${{ matrix.abi }} for ${{ matrix.arch }}
if: github.repository_owner == 'home-assistant'
needs: init
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
abi: ["cp311"]
arch: ${{ fromJson(needs.init.outputs.architectures) }}
steps:
- name: Checkout the repository
uses: actions/checkout@v3.5.2
- name: Write alternative env-file for cp311
run: |
(
echo "GRPC_BUILD_WITH_BORING_SSL_ASM=false"
echo "GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=true"
echo "GRPC_PYTHON_BUILD_WITH_CYTHON=true"
echo "GRPC_PYTHON_DISABLE_LIBC_COMPATIBILITY=true"
# GRPC on armv7 needed -lexecinfo (issue #56669) since home assistant installed
# execinfo-dev when building wheels. However, this package is no longer available
# Alpine 3.17, which we use for the cp311 ABI, so the flag should no longer be needed.
echo "GRPC_PYTHON_LDFLAGS=-lpthread -Wl,-wrap,memcpy -static-libgcc" # -lexecinfo
# Fix out of memory issues with rust
echo "CARGO_NET_GIT_FETCH_WITH_CLI=true"
# OpenCV headless installation
echo "CI_BUILD=1"
echo "ENABLE_HEADLESS=1"
# Use C-Extension for sqlalchemy
echo "REQUIRE_SQLALCHEMY_CEXT=1"
) > .env_file
- name: Download requirements_diff
uses: actions/download-artifact@v3
with:
name: requirements_diff
- name: (Un)comment packages
run: |
requirement_files="requirements_all.txt requirements_diff.txt"
for requirement_file in ${requirement_files}; do
# PyBluez no longer compiles. Commented it out for now.
# It need further cleanup down the line, as all machine images
# try to install it.
# sed -i "s|# pybluez|pybluez|g" ${requirement_file}
# beacontools requires PyBluez.
# sed -i "s|# beacontools|beacontools|g" ${requirement_file}
# azure-servicebus requires uamqp, which requires OpenSSL 1.1 to
# compile/build. This is not available on Alpine 3.17. The compat
# layer offered by Alpine conflicts, so we have no way to build
# this package.
# sed -i "s|# azure-servicebus|azure-servicebus|g" ${requirement_file}
# It doesn't build for some reason, so we skip it for now.
# Bumping to the latest version (4.7.0.72) supporting Python 3.11
# doesn't help. Reverted bump in #91871. There are 8 registered
# instances using this integration according to analytics.
# sed -i "s|# opencv-python-headless|opencv-python-headless|g" ${requirement_file}
sed -i "s|# fritzconnection|fritzconnection|g" ${requirement_file}
sed -i "s|# pyuserinput|pyuserinput|g" ${requirement_file}
sed -i "s|# evdev|evdev|g" ${requirement_file}
sed -i "s|# pycups|pycups|g" ${requirement_file}
sed -i "s|# homekit|homekit|g" ${requirement_file}
sed -i "s|# decora_wifi|decora_wifi|g" ${requirement_file}
sed -i "s|# python-gammu|python-gammu|g" ${requirement_file}
# Some packages are not buildable on armhf anymore
if [ "${{ matrix.arch }}" = "armhf" ]; then
# Pandas has issues building on armhf, it is expected they
# will drop the platform in the near future (they consider it
# "flimsy" on 386). The following packages depend on pandas,
# so we comment them out.
sed -i "s|env_canada|# env_canada|g" ${requirement_file}
sed -i "s|noaa-coops|# noaa-coops|g" ${requirement_file}
sed -i "s|pyezviz|# pyezviz|g" ${requirement_file}
sed -i "s|pykrakenapi|# pykrakenapi|g" ${requirement_file}
fi
done
- name: Split requirements all
run: |
# We split requirements all into two different files.
# This is to prevent the build from running out of memory when
# resolving packages on 32-bits systems (like armhf, armv7).
split -l $(expr $(expr $(cat requirements_all.txt | wc -l) + 1) / 2) requirements_all.txt requirements_all.txt
- name: Adjust build env
run: |
if [ "${{ matrix.arch }}" = "i386" ]; then
echo "NPY_DISABLE_SVML=1" >> .env_file
fi
# Probably not an issue anymore. Removing for now.
# (
# # cmake > 3.22.2 have issue on arm
# # Tested until 3.22.5
# echo "cmake==3.22.2"
# ) >> homeassistant/package_constraints.txt
# Do not pin numpy in wheels building
sed -i "/numpy/d" homeassistant/package_constraints.txt
- name: Build wheels (part 1)
uses: home-assistant/wheels@2023.04.0
with:
abi: ${{ matrix.abi }}
tag: musllinux_1_2
arch: ${{ matrix.arch }}
wheels-key: ${{ secrets.WHEELS_KEY }}
env-file: true
apk: "bluez-dev;libffi-dev;openssl-dev;glib-dev;eudev-dev;libxml2-dev;libxslt-dev;libpng-dev;libjpeg-turbo-dev;tiff-dev;cups-dev;gmp-dev;mpfr-dev;mpc1-dev;ffmpeg-dev;gammu-dev;yaml-dev;openblas-dev;fftw-dev;lapack-dev;gfortran;blas-dev;eigen-dev;freetype-dev;glew-dev;harfbuzz-dev;hdf5-dev;libdc1394-dev;libtbb-dev;mesa-dev;openexr-dev;openjpeg-dev;uchardet-dev"
skip-binary: aiohttp;grpcio;sqlalchemy;protobuf
legacy: true
constraints: "homeassistant/package_constraints.txt"
requirements-diff: "requirements_diff.txt"
requirements: "requirements_all.txtaa"
- name: Build wheels (part 2)
uses: home-assistant/wheels@2023.04.0
with:
abi: ${{ matrix.abi }}
tag: musllinux_1_2
arch: ${{ matrix.arch }}
wheels-key: ${{ secrets.WHEELS_KEY }}
env-file: true
apk: "bluez-dev;libffi-dev;openssl-dev;glib-dev;eudev-dev;libxml2-dev;libxslt-dev;libpng-dev;libjpeg-turbo-dev;tiff-dev;cups-dev;gmp-dev;mpfr-dev;mpc1-dev;ffmpeg-dev;gammu-dev;yaml-dev;openblas-dev;fftw-dev;lapack-dev;gfortran;blas-dev;eigen-dev;freetype-dev;glew-dev;harfbuzz-dev;hdf5-dev;libdc1394-dev;libtbb-dev;mesa-dev;openexr-dev;openjpeg-dev;uchardet-dev"
skip-binary: aiohttp;grpcio;sqlalchemy;protobuf
apk: "libexecinfo-dev;bluez-dev;libffi-dev;openssl-dev;glib-dev;eudev-dev;libxml2-dev;libxslt-dev;libpng-dev;libjpeg-turbo-dev;tiff-dev;cups-dev;gmp-dev;mpfr-dev;mpc1-dev;ffmpeg-dev;gammu-dev;yaml-dev;openblas-dev;fftw-dev;lapack-dev;gfortran;blas-dev;eigen-dev;freetype-dev;glew-dev;harfbuzz-dev;hdf5-dev;libdc1394-dev;libtbb-dev;mesa-dev;openexr-dev;openjpeg-dev"
skip-binary: aiohttp;grpcio
legacy: true
constraints: "homeassistant/package_constraints.txt"
requirements-diff: "requirements_diff.txt"

3
.gitignore vendored
View File

@@ -8,9 +8,6 @@ tests/testing_config/home-assistant.log*
data/
.token
# Translations
homeassistant/components/*/translations
# Hide sublime text stuff
*.sublime-project
*.sublime-workspace

View File

@@ -1,12 +1,26 @@
repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.262
rev: v0.0.237
hooks:
- id: ruff
args:
- --fix
- repo: https://github.com/asottile/pyupgrade
rev: v3.3.1
hooks:
- id: pyupgrade
args: [--py310-plus]
stages: [manual]
- repo: https://github.com/PyCQA/autoflake
rev: v2.0.0
hooks:
- id: autoflake
args:
- --in-place
- --remove-all-unused-imports
stages: [manual]
- repo: https://github.com/psf/black
rev: 23.3.0
rev: 22.12.0
hooks:
- id: black
args:
@@ -17,11 +31,25 @@ repos:
hooks:
- id: codespell
args:
- --ignore-words-list=additionals,alle,alot,ba,bre,bund,currenty,datas,dof,dur,ether,farenheit,falsy,fo,haa,hass,hist,iam,iff,iif,incomfort,ines,ist,lightsensor,mut,nam,nd,pres,pullrequests,referer,resset,rime,ser,serie,sur,te,technik,ue,uint,unsecure,visability,wan,wanna,withing,zar
- --ignore-words-list=additionals,alle,alot,ba,bre,bund,datas,dof,dur,ether,farenheit,falsy,fo,haa,hass,hist,iam,iff,iif,incomfort,ines,ist,lightsensor,mut,nam,nd,pres,pullrequests,referer,resset,rime,ser,serie,sur,te,technik,ue,uint,unsecure,visability,wan,wanna,withing,zar
- --skip="./.*,*.csv,*.json"
- --quiet-level=2
exclude_types: [csv, json]
exclude: ^tests/fixtures/|homeassistant/generated/
- repo: https://github.com/PyCQA/flake8
rev: 6.0.0
hooks:
- id: flake8
additional_dependencies:
- pycodestyle==2.10.0
- pyflakes==3.0.1
- flake8-docstrings==1.6.0
- pydocstyle==6.2.3
- flake8-comprehensions==3.10.1
- flake8-noqa==1.3.0
- mccabe==0.7.0
exclude: docs/source/conf.py
stages: [manual]
- repo: https://github.com/PyCQA/bandit
rev: 1.7.4
hooks:

View File

@@ -4,5 +4,3 @@ azure-*.yml
docs/source/_templates/*
homeassistant/components/*/translations/*.json
homeassistant/generated/*
tests/components/lidarr/fixtures/initialize.js
tests/components/lidarr/fixtures/initialize-wrong.js

View File

@@ -57,12 +57,10 @@ homeassistant.components.ambient_station.*
homeassistant.components.amcrest.*
homeassistant.components.ampio.*
homeassistant.components.analytics.*
homeassistant.components.anova.*
homeassistant.components.anthemav.*
homeassistant.components.apcupsd.*
homeassistant.components.aqualogic.*
homeassistant.components.aseko_pool_live.*
homeassistant.components.assist_pipeline.*
homeassistant.components.asuswrt.*
homeassistant.components.auth.*
homeassistant.components.automation.*
@@ -86,7 +84,6 @@ homeassistant.components.camera.*
homeassistant.components.canary.*
homeassistant.components.clickatell.*
homeassistant.components.clicksend.*
homeassistant.components.configurator.*
homeassistant.components.cover.*
homeassistant.components.cpuspeed.*
homeassistant.components.crownstone.*
@@ -101,7 +98,6 @@ homeassistant.components.dhcp.*
homeassistant.components.diagnostics.*
homeassistant.components.dlna_dmr.*
homeassistant.components.dnsip.*
homeassistant.components.dormakaba_dkey.*
homeassistant.components.dsmr.*
homeassistant.components.dunehd.*
homeassistant.components.efergy.*
@@ -139,7 +135,6 @@ homeassistant.components.hardkernel.*
homeassistant.components.hardware.*
homeassistant.components.here_travel_time.*
homeassistant.components.history.*
homeassistant.components.homeassistant.exposed_entities
homeassistant.components.homeassistant.triggers.event
homeassistant.components.homeassistant_alerts.*
homeassistant.components.homeassistant_hardware.*
@@ -189,7 +184,6 @@ homeassistant.components.ld2410_ble.*
homeassistant.components.lidarr.*
homeassistant.components.lifx.*
homeassistant.components.light.*
homeassistant.components.litejet.*
homeassistant.components.litterrobot.*
homeassistant.components.local_ip.*
homeassistant.components.lock.*
@@ -252,7 +246,6 @@ homeassistant.components.recorder.*
homeassistant.components.remote.*
homeassistant.components.renault.*
homeassistant.components.repairs.*
homeassistant.components.rest.*
homeassistant.components.rfxtrx.*
homeassistant.components.rhasspy.*
homeassistant.components.ridwell.*
@@ -300,13 +293,11 @@ homeassistant.components.tag.*
homeassistant.components.tailscale.*
homeassistant.components.tautulli.*
homeassistant.components.tcp.*
homeassistant.components.threshold.*
homeassistant.components.tibber.*
homeassistant.components.tile.*
homeassistant.components.tilt_ble.*
homeassistant.components.tolo.*
homeassistant.components.tplink.*
homeassistant.components.tplink_omada.*
homeassistant.components.tractive.*
homeassistant.components.tradfri.*
homeassistant.components.trafikverket_ferry.*
@@ -314,7 +305,7 @@ homeassistant.components.trafikverket_train.*
homeassistant.components.trafikverket_weatherstation.*
homeassistant.components.tts.*
homeassistant.components.twentemilieu.*
homeassistant.components.unifi.*
homeassistant.components.unifi.update
homeassistant.components.unifiprotect.*
homeassistant.components.upcloud.*
homeassistant.components.update.*
@@ -338,7 +329,6 @@ homeassistant.components.wiz.*
homeassistant.components.wled.*
homeassistant.components.worldclock.*
homeassistant.components.yale_smart_alarm.*
homeassistant.components.yalexs_ble.*
homeassistant.components.zeroconf.*
homeassistant.components.zodiac.*
homeassistant.components.zone.*

10
.vscode/launch.json vendored
View File

@@ -10,8 +10,7 @@
"request": "launch",
"module": "homeassistant",
"justMyCode": false,
"args": ["--debug", "-c", "config"],
"preLaunchTask": "Compile English translations"
"args": ["--debug", "-c", "config"]
},
{
"name": "Home Assistant (skip pip)",
@@ -19,11 +18,10 @@
"request": "launch",
"module": "homeassistant",
"justMyCode": false,
"args": ["--debug", "-c", "config", "--skip-pip"],
"preLaunchTask": "Compile English translations"
"args": ["--debug", "-c", "config", "--skip-pip"]
},
{
// Debug by attaching to local Home Assistant server using Remote Python Debugger.
// Debug by attaching to local Home Asistant server using Remote Python Debugger.
// See https://www.home-assistant.io/integrations/debugpy/
"name": "Home Assistant: Attach Local",
"type": "python",
@@ -38,7 +36,7 @@
]
},
{
// Debug by attaching to remote Home Assistant server using Remote Python Debugger.
// Debug by attaching to remote Home Asistant server using Remote Python Debugger.
// See https://www.home-assistant.io/integrations/debugpy/
"name": "Home Assistant: Attach Remote",
"type": "python",

28
.vscode/tasks.json vendored
View File

@@ -10,8 +10,7 @@
"reveal": "always",
"panel": "new"
},
"problemMatcher": [],
"dependsOn": ["Compile English translations"]
"problemMatcher": []
},
{
"label": "Pytest",
@@ -42,6 +41,20 @@
},
"problemMatcher": []
},
{
"label": "Flake8",
"type": "shell",
"command": "pre-commit run flake8 --all-files",
"group": {
"kind": "test",
"isDefault": true
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},
{
"label": "Ruff",
"type": "shell",
@@ -129,14 +142,19 @@
"problemMatcher": []
},
{
"label": "Compile English translations",
"label": "Compile translations",
"detail": "In order to test changes to translation files, the translation strings must be compiled into Home Assistant's translation directories.",
"type": "shell",
"command": "python3 -m script.translations develop --all",
"command": "python3 -m script.translations develop --integration ${input:integrationName}",
"group": {
"kind": "build",
"isDefault": true
}
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
}
],
"inputs": [

View File

@@ -25,7 +25,7 @@ rules:
comments:
level: error
require-starting-space: true
min-spaces-from-content: 1
min-spaces-from-content: 2
comments-indentation:
level: error
document-end:

View File

@@ -80,10 +80,6 @@ build.json @home-assistant/supervisor
/tests/components/android_ip_webcam/ @engrbm87
/homeassistant/components/androidtv/ @JeffLIrion @ollo69
/tests/components/androidtv/ @JeffLIrion @ollo69
/homeassistant/components/androidtv_remote/ @tronikos
/tests/components/androidtv_remote/ @tronikos
/homeassistant/components/anova/ @Lash-L
/tests/components/anova/ @Lash-L
/homeassistant/components/anthemav/ @hyralex
/tests/components/anthemav/ @hyralex
/homeassistant/components/apache_kafka/ @bachya
@@ -107,8 +103,6 @@ build.json @home-assistant/supervisor
/homeassistant/components/arris_tg2492lg/ @vanbalken
/homeassistant/components/aseko_pool_live/ @milanmeu
/tests/components/aseko_pool_live/ @milanmeu
/homeassistant/components/assist_pipeline/ @balloob @synesthesiam
/tests/components/assist_pipeline/ @balloob @synesthesiam
/homeassistant/components/asuswrt/ @kennedyshead @ollo69
/tests/components/asuswrt/ @kennedyshead @ollo69
/homeassistant/components/atag/ @MatsNL
@@ -141,8 +135,8 @@ build.json @home-assistant/supervisor
/tests/components/backup/ @home-assistant/core
/homeassistant/components/baf/ @bdraco @jfroy
/tests/components/baf/ @bdraco @jfroy
/homeassistant/components/balboa/ @garbled1 @natekspencer
/tests/components/balboa/ @garbled1 @natekspencer
/homeassistant/components/balboa/ @garbled1
/tests/components/balboa/ @garbled1
/homeassistant/components/bayesian/ @HarvsG
/tests/components/bayesian/ @HarvsG
/homeassistant/components/beewi_smartclim/ @alemuro
@@ -174,8 +168,6 @@ build.json @home-assistant/supervisor
/tests/components/broadlink/ @danielhiversen @felipediel @L-I-Am
/homeassistant/components/brother/ @bieniu
/tests/components/brother/ @bieniu
/homeassistant/components/brottsplatskartan/ @gjohansson-ST
/tests/components/brottsplatskartan/ @gjohansson-ST
/homeassistant/components/brunt/ @eavanvalkenburg
/tests/components/brunt/ @eavanvalkenburg
/homeassistant/components/bsblan/ @liudger
@@ -223,6 +215,8 @@ build.json @home-assistant/supervisor
/tests/components/conversation/ @home-assistant/core @synesthesiam
/homeassistant/components/coolmaster/ @OnFreund
/tests/components/coolmaster/ @OnFreund
/homeassistant/components/coronavirus/ @home-assistant/core
/tests/components/coronavirus/ @home-assistant/core
/homeassistant/components/counter/ @fabaff
/tests/components/counter/ @fabaff
/homeassistant/components/cover/ @home-assistant/core
@@ -234,6 +228,8 @@ build.json @home-assistant/supervisor
/homeassistant/components/cups/ @fabaff
/homeassistant/components/daikin/ @fredrike
/tests/components/daikin/ @fredrike
/homeassistant/components/darksky/ @fabaff
/tests/components/darksky/ @fabaff
/homeassistant/components/debugpy/ @frenck
/tests/components/debugpy/ @frenck
/homeassistant/components/deconz/ @Kane610
@@ -279,23 +275,19 @@ build.json @home-assistant/supervisor
/tests/components/dnsip/ @gjohansson-ST
/homeassistant/components/doorbird/ @oblogic7 @bdraco @flacjacket
/tests/components/doorbird/ @oblogic7 @bdraco @flacjacket
/homeassistant/components/dormakaba_dkey/ @emontnemery
/tests/components/dormakaba_dkey/ @emontnemery
/homeassistant/components/dsmr/ @Robbie1221 @frenck
/tests/components/dsmr/ @Robbie1221 @frenck
/homeassistant/components/dsmr_reader/ @depl0y @glodenox
/tests/components/dsmr_reader/ @depl0y @glodenox
/homeassistant/components/dunehd/ @bieniu
/tests/components/dunehd/ @bieniu
/homeassistant/components/dwd_weather_warnings/ @runningman84 @stephan192 @Hummel95 @andarotajo
/homeassistant/components/dwd_weather_warnings/ @runningman84 @stephan192 @Hummel95
/homeassistant/components/dynalite/ @ziv1234
/tests/components/dynalite/ @ziv1234
/homeassistant/components/eafm/ @Jc2k
/tests/components/eafm/ @Jc2k
/homeassistant/components/easyenergy/ @klaasnicolaas
/tests/components/easyenergy/ @klaasnicolaas
/homeassistant/components/ecobee/ @marthoc @marcolivierarsenault
/tests/components/ecobee/ @marthoc @marcolivierarsenault
/homeassistant/components/ecobee/ @marthoc
/tests/components/ecobee/ @marthoc
/homeassistant/components/econet/ @vangorra @w1ll1am23
/tests/components/econet/ @vangorra @w1ll1am23
/homeassistant/components/ecovacs/ @OverloadUT @mib1185
@@ -317,8 +309,8 @@ build.json @home-assistant/supervisor
/homeassistant/components/emoncms/ @borpin
/homeassistant/components/emonitor/ @bdraco
/tests/components/emonitor/ @bdraco
/homeassistant/components/emulated_hue/ @bdraco @Tho85
/tests/components/emulated_hue/ @bdraco @Tho85
/homeassistant/components/emulated_hue/ @bdraco
/tests/components/emulated_hue/ @bdraco
/homeassistant/components/emulated_kasa/ @kbickar
/tests/components/emulated_kasa/ @kbickar
/homeassistant/components/energy/ @home-assistant/core
@@ -405,7 +397,6 @@ build.json @home-assistant/supervisor
/homeassistant/components/frontend/ @home-assistant/frontend
/tests/components/frontend/ @home-assistant/frontend
/homeassistant/components/frontier_silicon/ @wlcrs
/tests/components/frontier_silicon/ @wlcrs
/homeassistant/components/fully_kiosk/ @cgarwood
/tests/components/fully_kiosk/ @cgarwood
/homeassistant/components/garages_amsterdam/ @klaasnicolaas
@@ -416,7 +407,7 @@ build.json @home-assistant/supervisor
/tests/components/generic/ @davet2001
/homeassistant/components/generic_hygrostat/ @Shulyaka
/tests/components/generic_hygrostat/ @Shulyaka
/homeassistant/components/geniushub/ @manzanotti
/homeassistant/components/geniushub/ @zxdavb
/homeassistant/components/geo_json_events/ @exxamalte
/tests/components/geo_json_events/ @exxamalte
/homeassistant/components/geo_location/ @home-assistant/core
@@ -463,8 +454,8 @@ build.json @home-assistant/supervisor
/tests/components/greeneye_monitor/ @jkeljo
/homeassistant/components/group/ @home-assistant/core
/tests/components/group/ @home-assistant/core
/homeassistant/components/growatt_server/ @muppet3000
/tests/components/growatt_server/ @muppet3000
/homeassistant/components/growatt_server/ @indykoning @muppet3000 @JasperPlant
/tests/components/growatt_server/ @indykoning @muppet3000 @JasperPlant
/homeassistant/components/guardian/ @bachya
/tests/components/guardian/ @bachya
/homeassistant/components/habitica/ @ASMfreaK @leikoilja
@@ -550,8 +541,8 @@ build.json @home-assistant/supervisor
/tests/components/image_processing/ @home-assistant/core
/homeassistant/components/image_upload/ @home-assistant/core
/tests/components/image_upload/ @home-assistant/core
/homeassistant/components/imap/ @engrbm87 @jbouwh
/tests/components/imap/ @engrbm87 @jbouwh
/homeassistant/components/imap/ @engrbm87
/tests/components/imap/ @engrbm87
/homeassistant/components/incomfort/ @zxdavb
/homeassistant/components/influxdb/ @mdegat01
/tests/components/influxdb/ @mdegat01
@@ -655,8 +646,8 @@ build.json @home-assistant/supervisor
/tests/components/lidarr/ @tkdrob
/homeassistant/components/life360/ @pnbruckner
/tests/components/life360/ @pnbruckner
/homeassistant/components/lifx/ @bdraco
/tests/components/lifx/ @bdraco
/homeassistant/components/lifx/ @bdraco @Djelibeybi
/tests/components/lifx/ @bdraco @Djelibeybi
/homeassistant/components/light/ @home-assistant/core
/tests/components/light/ @home-assistant/core
/homeassistant/components/linux_battery/ @fabaff
@@ -664,8 +655,8 @@ build.json @home-assistant/supervisor
/tests/components/litejet/ @joncar
/homeassistant/components/litterrobot/ @natekspencer @tkdrob
/tests/components/litterrobot/ @natekspencer @tkdrob
/homeassistant/components/livisi/ @StefanIacobLivisi @planbnet
/tests/components/livisi/ @StefanIacobLivisi @planbnet
/homeassistant/components/livisi/ @StefanIacobLivisi
/tests/components/livisi/ @StefanIacobLivisi
/homeassistant/components/local_calendar/ @allenporter
/tests/components/local_calendar/ @allenporter
/homeassistant/components/local_ip/ @issacg
@@ -789,8 +780,7 @@ build.json @home-assistant/supervisor
/tests/components/nexia/ @bdraco
/homeassistant/components/nextbus/ @vividboarder
/tests/components/nextbus/ @vividboarder
/homeassistant/components/nextcloud/ @mib1185
/tests/components/nextcloud/ @mib1185
/homeassistant/components/nextcloud/ @meichthys
/homeassistant/components/nextdns/ @bieniu
/tests/components/nextdns/ @bieniu
/homeassistant/components/nfandroidtv/ @tkdrob
@@ -825,14 +815,13 @@ build.json @home-assistant/supervisor
/tests/components/numato/ @clssn
/homeassistant/components/number/ @home-assistant/core @Shulyaka
/tests/components/number/ @home-assistant/core @Shulyaka
/homeassistant/components/nut/ @bdraco @ollo69 @pestevez
/tests/components/nut/ @bdraco @ollo69 @pestevez
/homeassistant/components/nut/ @bdraco @ollo69
/tests/components/nut/ @bdraco @ollo69
/homeassistant/components/nws/ @MatthewFlamm @kamiyo
/tests/components/nws/ @MatthewFlamm @kamiyo
/homeassistant/components/nzbget/ @chriscla
/tests/components/nzbget/ @chriscla
/homeassistant/components/obihai/ @dshokouhi @ejpenney
/tests/components/obihai/ @dshokouhi @ejpenney
/homeassistant/components/obihai/ @dshokouhi
/homeassistant/components/octoprint/ @rfleming71
/tests/components/octoprint/ @rfleming71
/homeassistant/components/ohmconnect/ @robbiet480
@@ -899,8 +888,8 @@ build.json @home-assistant/supervisor
/tests/components/plaato/ @JohNan
/homeassistant/components/plex/ @jjlawren
/tests/components/plex/ @jjlawren
/homeassistant/components/plugwise/ @CoMPaTech @bouwew @frenck
/tests/components/plugwise/ @CoMPaTech @bouwew @frenck
/homeassistant/components/plugwise/ @CoMPaTech @bouwew @brefra @frenck
/tests/components/plugwise/ @CoMPaTech @bouwew @brefra @frenck
/homeassistant/components/plum_lightpad/ @ColinHarrington @prystupa
/tests/components/plum_lightpad/ @ColinHarrington @prystupa
/homeassistant/components/point/ @fredrike
@@ -937,7 +926,6 @@ build.json @home-assistant/supervisor
/homeassistant/components/pvpc_hourly_pricing/ @azogue
/tests/components/pvpc_hourly_pricing/ @azogue
/homeassistant/components/qbittorrent/ @geoffreylagaisse
/tests/components/qbittorrent/ @geoffreylagaisse
/homeassistant/components/qingping/ @bdraco @skgsergio
/tests/components/qingping/ @bdraco @skgsergio
/homeassistant/components/qld_bushfire/ @exxamalte
@@ -965,8 +953,6 @@ build.json @home-assistant/supervisor
/tests/components/rainmachine/ @bachya
/homeassistant/components/random/ @fabaff
/tests/components/random/ @fabaff
/homeassistant/components/rapt_ble/ @sairon
/tests/components/rapt_ble/ @sairon
/homeassistant/components/raspberry_pi/ @home-assistant/core
/tests/components/raspberry_pi/ @home-assistant/core
/homeassistant/components/rdw/ @frenck
@@ -985,8 +971,6 @@ build.json @home-assistant/supervisor
/homeassistant/components/repairs/ @home-assistant/core
/tests/components/repairs/ @home-assistant/core
/homeassistant/components/repetier/ @MTrab @ShadowBr0ther
/homeassistant/components/rest/ @epenet
/tests/components/rest/ @epenet
/homeassistant/components/rflink/ @javicalle
/tests/components/rflink/ @javicalle
/homeassistant/components/rfxtrx/ @danielhiversen @elupus @RobBie1221
@@ -1001,8 +985,6 @@ build.json @home-assistant/supervisor
/tests/components/rituals_perfume_genie/ @milanmeu
/homeassistant/components/rmvtransport/ @cgtobi
/tests/components/rmvtransport/ @cgtobi
/homeassistant/components/roborock/ @humbertogontijo @Lash-L
/tests/components/roborock/ @humbertogontijo @Lash-L
/homeassistant/components/roku/ @ctalkington
/tests/components/roku/ @ctalkington
/homeassistant/components/roomba/ @pschmitt @cyr-ius @shenxn
@@ -1069,8 +1051,8 @@ build.json @home-assistant/supervisor
/homeassistant/components/seven_segments/ @fabaff
/homeassistant/components/sfr_box/ @epenet
/tests/components/sfr_box/ @epenet
/homeassistant/components/sharkiq/ @JeffResc @funkybunch
/tests/components/sharkiq/ @JeffResc @funkybunch
/homeassistant/components/sharkiq/ @JeffResc @funkybunch @AritroSaha10
/tests/components/sharkiq/ @JeffResc @funkybunch @AritroSaha10
/homeassistant/components/shell_command/ @home-assistant/core
/tests/components/shell_command/ @home-assistant/core
/homeassistant/components/shelly/ @balloob @bieniu @thecode @chemelli74 @bdraco
@@ -1114,8 +1096,6 @@ build.json @home-assistant/supervisor
/homeassistant/components/smhi/ @gjohansson-ST
/tests/components/smhi/ @gjohansson-ST
/homeassistant/components/sms/ @ocalvo
/homeassistant/components/snapcast/ @luar123
/tests/components/snapcast/ @luar123
/homeassistant/components/snooz/ @AustinBrunkhorst
/tests/components/snooz/ @AustinBrunkhorst
/homeassistant/components/solaredge/ @frenck
@@ -1144,8 +1124,8 @@ build.json @home-assistant/supervisor
/homeassistant/components/splunk/ @Bre77
/homeassistant/components/spotify/ @frenck
/tests/components/spotify/ @frenck
/homeassistant/components/sql/ @dgomes @gjohansson-ST @dougiteixeira
/tests/components/sql/ @dgomes @gjohansson-ST @dougiteixeira
/homeassistant/components/sql/ @dgomes @gjohansson-ST
/tests/components/sql/ @dgomes @gjohansson-ST
/homeassistant/components/squeezebox/ @rajlaud
/tests/components/squeezebox/ @rajlaud
/homeassistant/components/srp_energy/ @briglx
@@ -1154,8 +1134,8 @@ build.json @home-assistant/supervisor
/tests/components/starline/ @anonym-tsk
/homeassistant/components/starlink/ @boswelja
/tests/components/starlink/ @boswelja
/homeassistant/components/statistics/ @ThomDietrich
/tests/components/statistics/ @ThomDietrich
/homeassistant/components/statistics/ @fabaff @ThomDietrich
/tests/components/statistics/ @fabaff @ThomDietrich
/homeassistant/components/steam_online/ @tkdrob
/tests/components/steam_online/ @tkdrob
/homeassistant/components/steamist/ @bdraco
@@ -1167,8 +1147,8 @@ build.json @home-assistant/supervisor
/tests/components/stookwijzer/ @fwestenberg
/homeassistant/components/stream/ @hunterjm @uvjustin @allenporter
/tests/components/stream/ @hunterjm @uvjustin @allenporter
/homeassistant/components/stt/ @home-assistant/core @pvizeli
/tests/components/stt/ @home-assistant/core @pvizeli
/homeassistant/components/stt/ @pvizeli
/tests/components/stt/ @pvizeli
/homeassistant/components/subaru/ @G-Two
/tests/components/subaru/ @G-Two
/homeassistant/components/suez_water/ @ooii
@@ -1228,6 +1208,8 @@ build.json @home-assistant/supervisor
/homeassistant/components/thethingsnetwork/ @fabaff
/homeassistant/components/thread/ @home-assistant/core
/tests/components/thread/ @home-assistant/core
/homeassistant/components/threshold/ @fabaff
/tests/components/threshold/ @fabaff
/homeassistant/components/tibber/ @danielhiversen
/tests/components/tibber/ @danielhiversen
/homeassistant/components/tile/ @bachya
@@ -1247,8 +1229,6 @@ build.json @home-assistant/supervisor
/tests/components/totalconnect/ @austinmroczek
/homeassistant/components/tplink/ @rytilahti @thegardenmonkey
/tests/components/tplink/ @rytilahti @thegardenmonkey
/homeassistant/components/tplink_omada/ @MarkGodwin
/tests/components/tplink_omada/ @MarkGodwin
/homeassistant/components/traccar/ @ludeeus
/tests/components/traccar/ @ludeeus
/homeassistant/components/trace/ @home-assistant/core
@@ -1263,8 +1243,8 @@ build.json @home-assistant/supervisor
/tests/components/trafikverket_weatherstation/ @endor-force @gjohansson-ST
/homeassistant/components/transmission/ @engrbm87 @JPHutchins
/tests/components/transmission/ @engrbm87 @JPHutchins
/homeassistant/components/tts/ @home-assistant/core @pvizeli
/tests/components/tts/ @home-assistant/core @pvizeli
/homeassistant/components/tts/ @pvizeli
/tests/components/tts/ @pvizeli
/homeassistant/components/tuya/ @Tuya @zlinoliver @frenck
/tests/components/tuya/ @Tuya @zlinoliver @frenck
/homeassistant/components/twentemilieu/ @frenck
@@ -1276,8 +1256,8 @@ build.json @home-assistant/supervisor
/homeassistant/components/unifi/ @Kane610
/tests/components/unifi/ @Kane610
/homeassistant/components/unifiled/ @florisvdk
/homeassistant/components/unifiprotect/ @AngellusMortis @bdraco
/tests/components/unifiprotect/ @AngellusMortis @bdraco
/homeassistant/components/unifiprotect/ @briis @AngellusMortis @bdraco
/tests/components/unifiprotect/ @briis @AngellusMortis @bdraco
/homeassistant/components/upb/ @gwww
/tests/components/upb/ @gwww
/homeassistant/components/upc_connect/ @pvizeli @fabaff
@@ -1306,13 +1286,15 @@ build.json @home-assistant/supervisor
/homeassistant/components/velux/ @Julius2342
/homeassistant/components/venstar/ @garbled1
/tests/components/venstar/ @garbled1
/homeassistant/components/verisure/ @frenck @niro1987
/tests/components/verisure/ @frenck @niro1987
/homeassistant/components/verisure/ @frenck
/tests/components/verisure/ @frenck
/homeassistant/components/versasense/ @flamm3blemuff1n
/homeassistant/components/version/ @ludeeus
/tests/components/version/ @ludeeus
/homeassistant/components/vesync/ @markperdue @webdjoe @thegardenmonkey
/tests/components/vesync/ @markperdue @webdjoe @thegardenmonkey
/homeassistant/components/vicare/ @oischinger
/tests/components/vicare/ @oischinger
/homeassistant/components/vilfo/ @ManneW
/tests/components/vilfo/ @ManneW
/homeassistant/components/vivotek/ @HarlemSquirrel
@@ -1320,8 +1302,6 @@ build.json @home-assistant/supervisor
/tests/components/vizio/ @raman325
/homeassistant/components/vlc_telnet/ @rodripf @MartinHjelmare
/tests/components/vlc_telnet/ @rodripf @MartinHjelmare
/homeassistant/components/voip/ @balloob @synesthesiam
/tests/components/voip/ @balloob @synesthesiam
/homeassistant/components/volumio/ @OnFreund
/tests/components/volumio/ @OnFreund
/homeassistant/components/volvooncall/ @molobrakos
@@ -1367,16 +1347,15 @@ build.json @home-assistant/supervisor
/tests/components/wled/ @frenck
/homeassistant/components/wolflink/ @adamkrol93
/tests/components/wolflink/ @adamkrol93
/homeassistant/components/workday/ @fabaff @gjohansson-ST
/tests/components/workday/ @fabaff @gjohansson-ST
/homeassistant/components/workday/ @fabaff
/tests/components/workday/ @fabaff
/homeassistant/components/worldclock/ @fabaff
/tests/components/worldclock/ @fabaff
/homeassistant/components/ws66i/ @ssaenger
/tests/components/ws66i/ @ssaenger
/homeassistant/components/wyoming/ @balloob @synesthesiam
/tests/components/wyoming/ @balloob @synesthesiam
/homeassistant/components/xbox/ @hunterjm
/tests/components/xbox/ @hunterjm
/homeassistant/components/xbox_live/ @MartinHjelmare
/homeassistant/components/xiaomi_aqara/ @danielhiversen @syssi
/tests/components/xiaomi_aqara/ @danielhiversen @syssi
/homeassistant/components/xiaomi_ble/ @Jc2k @Ernst79

View File

@@ -132,8 +132,8 @@ For answers to common questions about this code of conduct, see the FAQ at
<https://www.contributor-covenant.org/faq>. Translations are available at
<https://www.contributor-covenant.org/translations>.
[coc-blog]: https://www.home-assistant.io/blog/2017/01/21/home-assistant-governance/
[coc2-blog]: https://www.home-assistant.io/blog/2020/05/25/code-of-conduct-updated/
[coc-blog]: /blog/2017/01/21/home-assistant-governance/
[coc2-blog]: /blog/2020/05/25/code-of-conduct-updated/
[email]: mailto:safety@home-assistant.io
[homepage]: http://contributor-covenant.org
[mozilla]: https://github.com/mozilla/diversity

View File

@@ -4,12 +4,12 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Uninstall pre-installed formatting and linting tools
# They would conflict with our pinned versions
RUN \
pipx uninstall black \
&& pipx uninstall pydocstyle \
&& pipx uninstall pycodestyle \
&& pipx uninstall mypy \
&& pipx uninstall pylint
RUN pipx uninstall black
RUN pipx uninstall flake8
RUN pipx uninstall pydocstyle
RUN pipx uninstall pycodestyle
RUN pipx uninstall mypy
RUN pipx uninstall pylint
RUN \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \

View File

@@ -4,7 +4,7 @@ Home Assistant |Chat Status|
Open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts. Perfect to run on a Raspberry Pi or a local server.
Check out `home-assistant.io <https://home-assistant.io>`__ for `a
demo <https://demo.home-assistant.io>`__, `installation instructions <https://home-assistant.io/getting-started/>`__,
demo <https://home-assistant.io/demo/>`__, `installation instructions <https://home-assistant.io/getting-started/>`__,
`tutorials <https://home-assistant.io/getting-started/automation/>`__ and `documentation <https://home-assistant.io/docs/>`__.
|screenshot-states|
@@ -23,6 +23,6 @@ of a component, check the `Home Assistant help section <https://home-assistant.i
.. |Chat Status| image:: https://img.shields.io/discord/330944238910963714.svg
:target: https://discord.gg/c5DvZ4e
.. |screenshot-states| image:: https://raw.githubusercontent.com/home-assistant/core/master/docs/screenshots.png
:target: https://demo.home-assistant.io
:target: https://home-assistant.io/demo/
.. |screenshot-integrations| image:: https://raw.githubusercontent.com/home-assistant/core/dev/docs/screenshot-integrations.png
:target: https://home-assistant.io/integrations/

View File

@@ -1,11 +1,11 @@
image: homeassistant/{arch}-homeassistant
shadow_repository: ghcr.io/home-assistant
build_from:
aarch64: ghcr.io/home-assistant/aarch64-homeassistant-base:2023.04.0
armhf: ghcr.io/home-assistant/armhf-homeassistant-base:2023.04.0
armv7: ghcr.io/home-assistant/armv7-homeassistant-base:2023.04.0
amd64: ghcr.io/home-assistant/amd64-homeassistant-base:2023.04.0
i386: ghcr.io/home-assistant/i386-homeassistant-base:2023.04.0
aarch64: ghcr.io/home-assistant/aarch64-homeassistant-base:2022.11.0
armhf: ghcr.io/home-assistant/armhf-homeassistant-base:2022.11.0
armv7: ghcr.io/home-assistant/armv7-homeassistant-base:2022.11.0
amd64: ghcr.io/home-assistant/amd64-homeassistant-base:2022.11.0
i386: ghcr.io/home-assistant/i386-homeassistant-base:2022.11.0
codenotary:
signer: notary@home-assistant.io
base_image: notary@home-assistant.io

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 118 KiB

View File

@@ -1,4 +1,5 @@
"""Sphinx extension for ReadTheDocs-style "Edit on GitHub" links on the sidebar.
"""
Sphinx extension for ReadTheDocs-style "Edit on GitHub" links on the sidebar.
Loosely based on https://github.com/astropy/astropy/pull/347
"""

View File

@@ -14,7 +14,7 @@ from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
from homeassistant.data_entry_flow import FlowResult
from homeassistant.util import dt as dt_util
from . import auth_store, jwt_wrapper, models
from . import auth_store, models
from .const import ACCESS_TOKEN_EXPIRATION, GROUP_ID_ADMIN
from .mfa_modules import MultiFactorAuthModule, auth_mfa_module_from_config
from .providers import AuthProvider, LoginFlow, auth_provider_from_config
@@ -555,7 +555,9 @@ class AuthManager:
) -> models.RefreshToken | None:
"""Return refresh token if an access token is valid."""
try:
unverif_claims = jwt_wrapper.unverified_hs256_token_decode(token)
unverif_claims = jwt.decode(
token, algorithms=["HS256"], options={"verify_signature": False}
)
except jwt.InvalidTokenError:
return None
@@ -571,9 +573,7 @@ class AuthManager:
issuer = refresh_token.id
try:
jwt_wrapper.verify_and_decode(
token, jwt_key, leeway=10, issuer=issuer, algorithms=["HS256"]
)
jwt.decode(token, jwt_key, leeway=10, issuer=issuer, algorithms=["HS256"])
except jwt.InvalidTokenError:
return None

View File

@@ -1,116 +0,0 @@
"""Provide a wrapper around JWT that caches decoding tokens.
Since we decode the same tokens over and over again
we can cache the result of the decode of valid tokens
to speed up the process.
"""
from __future__ import annotations
from datetime import timedelta
from functools import lru_cache, partial
from typing import Any
from jwt import DecodeError, PyJWS, PyJWT
from homeassistant.util.json import json_loads
JWT_TOKEN_CACHE_SIZE = 16
MAX_TOKEN_SIZE = 8192
_VERIFY_KEYS = ("signature", "exp", "nbf", "iat", "aud", "iss")
_VERIFY_OPTIONS: dict[str, Any] = {f"verify_{key}": True for key in _VERIFY_KEYS} | {
"require": []
}
_NO_VERIFY_OPTIONS = {f"verify_{key}": False for key in _VERIFY_KEYS}
class _PyJWSWithLoadCache(PyJWS):
"""PyJWS with a dedicated load implementation."""
@lru_cache(maxsize=JWT_TOKEN_CACHE_SIZE)
# We only ever have a global instance of this class
# so we do not have to worry about the LRU growing
# each time we create a new instance.
def _load(self, jwt: str | bytes) -> tuple[bytes, bytes, dict, bytes]:
"""Load a JWS."""
return super()._load(jwt)
_jws = _PyJWSWithLoadCache()
@lru_cache(maxsize=JWT_TOKEN_CACHE_SIZE)
def _decode_payload(json_payload: str) -> dict[str, Any]:
"""Decode the payload from a JWS dictionary."""
try:
payload = json_loads(json_payload)
except ValueError as err:
raise DecodeError(f"Invalid payload string: {err}") from err
if not isinstance(payload, dict):
raise DecodeError("Invalid payload string: must be a json object")
return payload
class _PyJWTWithVerify(PyJWT):
"""PyJWT with a fast decode implementation."""
def decode_payload(
self, jwt: str, key: str, options: dict[str, Any], algorithms: list[str]
) -> dict[str, Any]:
"""Decode a JWT's payload."""
if len(jwt) > MAX_TOKEN_SIZE:
# Avoid caching impossible tokens
raise DecodeError("Token too large")
return _decode_payload(
_jws.decode_complete(
jwt=jwt,
key=key,
algorithms=algorithms,
options=options,
)["payload"]
)
def verify_and_decode(
self,
jwt: str,
key: str,
algorithms: list[str],
issuer: str | None = None,
leeway: int | float | timedelta = 0,
options: dict[str, Any] | None = None,
) -> dict[str, Any]:
"""Verify a JWT's signature and claims."""
merged_options = {**_VERIFY_OPTIONS, **(options or {})}
payload = self.decode_payload(
jwt=jwt,
key=key,
options=merged_options,
algorithms=algorithms,
)
# These should never be missing since we verify them
# but this is an additional safeguard to make sure
# nothing slips through.
assert "exp" in payload, "exp claim is required"
assert "iat" in payload, "iat claim is required"
self._validate_claims( # type: ignore[no-untyped-call]
payload=payload,
options=merged_options,
issuer=issuer,
leeway=leeway,
)
return payload
_jwt = _PyJWTWithVerify() # type: ignore[no-untyped-call]
verify_and_decode = _jwt.verify_and_decode
unverified_hs256_token_decode = lru_cache(maxsize=JWT_TOKEN_CACHE_SIZE)(
partial(
_jwt.decode_payload, key="", algorithms=["HS256"], options=_NO_VERIFY_OPTIONS
)
)
__all__ = [
"unverified_hs256_token_decode",
"verify_and_decode",
]

View File

@@ -6,12 +6,15 @@ from typing import TYPE_CHECKING
import attr
if TYPE_CHECKING:
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers import (
device_registry as dev_reg,
entity_registry as ent_reg,
)
@attr.s(slots=True)
class PermissionLookup:
"""Class to hold data for permission lookups."""
entity_registry: er.EntityRegistry = attr.ib()
device_registry: dr.DeviceRegistry = attr.ib()
entity_registry: ent_reg.EntityRegistry = attr.ib()
device_registry: dev_reg.DeviceRegistry = attr.ib()

View File

@@ -68,7 +68,6 @@ class CommandLineAuthProvider(AuthProvider):
*self.config[CONF_ARGS],
env=env,
stdout=asyncio.subprocess.PIPE if self.config[CONF_META] else None,
close_fds=False, # required for posix_spawn
)
stdout, _ = await process.communicate()
except OSError as err:

View File

@@ -1,4 +1,5 @@
"""Support Legacy API password auth provider.
"""
Support Legacy API password auth provider.
It will be removed when auth system production ready
"""
@@ -70,7 +71,8 @@ class LegacyApiPasswordAuthProvider(AuthProvider):
async def async_user_meta_for_credentials(
self, credentials: Credentials
) -> UserMeta:
"""Return info for the user.
"""
Return info for the user.
Will be used to populate info when creating a new user.
"""

View File

@@ -2,15 +2,17 @@
from __future__ import annotations
from enum import Enum
from typing import Any
from typing import Any, TypeVar
from typing_extensions import Self
_StrEnumSelfT = TypeVar("_StrEnumSelfT", bound="StrEnum")
class StrEnum(str, Enum):
"""Partial backport of Python 3.11's StrEnum for our basic use cases."""
def __new__(cls, value: str, *args: Any, **kwargs: Any) -> Self:
def __new__(
cls: type[_StrEnumSelfT], value: str, *args: Any, **kwargs: Any
) -> _StrEnumSelfT:
"""Create a new StrEnum instance."""
if not isinstance(value, str):
raise TypeError(f"{value!r} is not a string")
@@ -24,7 +26,8 @@ class StrEnum(str, Enum):
def _generate_next_value_(
name: str, start: int, count: int, last_values: list[Any]
) -> Any:
"""Make `auto()` explicitly unsupported.
"""
Make `auto()` explicitly unsupported.
We may revisit this when it's very clear that Python 3.11's
`StrEnum.auto()` behavior will no longer change.

View File

@@ -8,7 +8,7 @@ from .util.async_ import protect_loop
def enable() -> None:
"""Enable the detection of blocking calls in the event loop."""
# Prevent urllib3 and requests doing I/O in event loop
HTTPConnection.putrequest = protect_loop( # type: ignore[method-assign]
HTTPConnection.putrequest = protect_loop( # type: ignore[assignment]
HTTPConnection.putrequest
)

View File

@@ -27,11 +27,9 @@ from .exceptions import HomeAssistantError
from .helpers import (
area_registry,
device_registry,
entity,
entity_registry,
issue_registry,
recorder,
template,
)
from .helpers.dispatcher import async_dispatcher_send
from .helpers.typing import ConfigType
@@ -238,15 +236,12 @@ async def load_registries(hass: core.HomeAssistant) -> None:
platform.uname().processor # pylint: disable=expression-not-assigned
# Load the registries and cache the result of platform.uname().processor
entity.async_setup(hass)
template.async_setup(hass)
await asyncio.gather(
area_registry.async_load(hass),
device_registry.async_load(hass),
entity_registry.async_load(hass),
issue_registry.async_load(hass),
hass.async_add_executor_job(_cache_uname_processor),
template.async_load_custom_templates(hass),
)
@@ -411,6 +406,7 @@ def async_enable_logging(
if (err_path_exists and os.access(err_log_path, os.W_OK)) or (
not err_path_exists and os.access(err_dir, os.W_OK)
):
err_handler: (
logging.handlers.RotatingFileHandler
| logging.handlers.TimedRotatingFileHandler
@@ -511,20 +507,19 @@ async def async_setup_multi_components(
) -> None:
"""Set up multiple domains. Log on failure."""
futures = {
domain: hass.async_create_task(
async_setup_component(hass, domain, config), f"setup component {domain}"
)
domain: hass.async_create_task(async_setup_component(hass, domain, config))
for domain in domains
}
results = await asyncio.gather(*futures.values(), return_exceptions=True)
for idx, domain in enumerate(futures):
result = results[idx]
if isinstance(result, BaseException):
_LOGGER.error(
"Error setting up integration %s - received exception",
domain,
exc_info=(type(result), result, result.__traceback__),
)
await asyncio.wait(futures.values())
errors = [domain for domain in domains if futures[domain].exception()]
for domain in errors:
exception = futures[domain].exception()
assert exception is not None
_LOGGER.error(
"Error setting up integration %s - received exception",
domain,
exc_info=(type(exception), exception, exception.__traceback__),
)
async def _async_set_up_integrations(
@@ -629,9 +624,6 @@ async def _async_set_up_integrations(
- stage_1_domains
)
# Enables after dependencies when setting up stage 1 domains
async_set_domains_to_be_loaded(hass, stage_1_domains)
# Start setup
if stage_1_domains:
_LOGGER.info("Setting up stage 1: %s", stage_1_domains)
@@ -643,7 +635,7 @@ async def _async_set_up_integrations(
except asyncio.TimeoutError:
_LOGGER.warning("Setup timed out for stage 1 - moving forward")
# Add after dependencies when setting up stage 2 domains
# Enables after dependencies
async_set_domains_to_be_loaded(hass, stage_2_domains)
if stage_2_domains:

View File

@@ -1,5 +0,0 @@
{
"domain": "heltun",
"name": "HELTUN",
"iot_standards": ["zwave"]
}

View File

@@ -1,5 +0,0 @@
{
"domain": "homeseer",
"name": "HomeSeer",
"iot_standards": ["zwave"]
}

View File

@@ -10,6 +10,7 @@
"microsoft_face",
"microsoft",
"msteams",
"xbox"
"xbox",
"xbox_live"
]
}

View File

@@ -1,6 +0,0 @@
{
"domain": "tplink",
"name": "TP-Link",
"integrations": ["tplink", "tplink_omada", "tplink_lte"],
"iot_standards": ["matter"]
}

View File

@@ -1,4 +1,5 @@
"""Contains components that can be plugged into Home Assistant.
"""
This package contains components that can be plugged into Home Assistant.
Component design guidelines:
- Each component defines a constant DOMAIN that is equal to its filename.

View File

@@ -1,6 +1,7 @@
"""Support for Abode Security System binary sensors."""
from __future__ import annotations
from contextlib import suppress
from typing import cast
from jaraco.abode.devices.sensor import BinarySensor as ABBinarySensor
@@ -13,7 +14,6 @@ from homeassistant.components.binary_sensor import (
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util.enum import try_parse_enum
from . import AbodeDevice, AbodeSystem
from .const import DOMAIN
@@ -54,4 +54,6 @@ class AbodeBinarySensor(AbodeDevice, BinarySensorEntity):
"""Return the class of the binary sensor."""
if self._device.get_value("is_window") == "1":
return BinarySensorDeviceClass.WINDOW
return try_parse_enum(BinarySensorDeviceClass, self._device.generic_type)
with suppress(ValueError):
return BinarySensorDeviceClass(cast(str, self._device.generic_type))
return None

View File

@@ -1,13 +1,13 @@
{
"domain": "abode",
"name": "Abode",
"codeowners": ["@shred86"],
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/abode",
"requirements": ["jaraco.abode==3.2.1"],
"codeowners": ["@shred86"],
"homekit": {
"models": ["Abode", "Iota"]
},
"iot_class": "cloud_push",
"loggers": ["jaraco.abode", "lomond"],
"requirements": ["jaraco.abode==3.3.0"]
"loggers": ["jaraco.abode", "lomond"]
}

View File

@@ -0,0 +1,26 @@
{
"config": {
"abort": {
"reauth_successful": "\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u0430\u0442\u0430 \u0430\u0432\u0442\u0435\u043d\u0442\u0438\u043a\u0430\u0446\u0438\u044f \u0431\u0435\u0448\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u0430",
"single_instance_allowed": "\u0412\u0435\u0447\u0435 \u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u043e. \u0412\u044a\u0437\u043c\u043e\u0436\u043d\u0430 \u0435 \u0441\u0430\u043c\u043e \u0435\u0434\u043d\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f."
},
"error": {
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0445 \u043f\u0440\u0438 \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435"
},
"step": {
"reauth_confirm": {
"data": {
"password": "\u041f\u0430\u0440\u043e\u043b\u0430",
"username": "\u0418\u043c\u0435\u0439\u043b"
}
},
"user": {
"data": {
"password": "\u041f\u0430\u0440\u043e\u043b\u0430",
"username": "\u0418\u043c\u0435\u0439\u043b"
},
"title": "\u041f\u043e\u043f\u044a\u043b\u043d\u0435\u0442\u0435 \u0412\u0430\u0448\u0430\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u0432\u0445\u043e\u0434 \u0432 Abode"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "Re-autenticaci\u00f3 realitzada correctament",
"single_instance_allowed": "Ja configurat. Nom\u00e9s \u00e9s possible una sola configuraci\u00f3."
},
"error": {
"cannot_connect": "Ha fallat la connexi\u00f3",
"invalid_auth": "Autenticaci\u00f3 inv\u00e0lida",
"invalid_mfa_code": "Codi MFA inv\u00e0lid"
},
"step": {
"mfa": {
"data": {
"mfa_code": "Codi MFA (6 d\u00edgits)"
},
"title": "Introdueix el codi MFA per a Abode"
},
"reauth_confirm": {
"data": {
"password": "Contrasenya",
"username": "Correu electr\u00f2nic"
},
"title": "Introdueix la informaci\u00f3 d'inici de sessi\u00f3 d'Abode."
},
"user": {
"data": {
"password": "Contrasenya",
"username": "Correu electr\u00f2nic"
},
"title": "Introducci\u00f3 de la informaci\u00f3 d'inici de sessi\u00f3 a Abode."
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "Op\u011btovn\u00e9 ov\u011b\u0159en\u00ed bylo \u00fasp\u011b\u0161n\u00e9",
"single_instance_allowed": "Ji\u017e nastaveno. Je mo\u017en\u00e1 pouze jedin\u00e1 konfigurace."
},
"error": {
"cannot_connect": "Nepoda\u0159ilo se p\u0159ipojit",
"invalid_auth": "Neplatn\u00e9 ov\u011b\u0159en\u00ed",
"invalid_mfa_code": "Neplatn\u00fd k\u00f3d MFA"
},
"step": {
"mfa": {
"data": {
"mfa_code": "K\u00f3d MFA (6 \u010d\u00edslic)"
},
"title": "Zadejte k\u00f3d MFA pro Abode"
},
"reauth_confirm": {
"data": {
"password": "Heslo",
"username": "E-mail"
},
"title": "Vypl\u0148te sv\u00e9 p\u0159ihla\u0161ovac\u00ed \u00fadaje do Abode"
},
"user": {
"data": {
"password": "Heslo",
"username": "E-mail"
},
"title": "Vypl\u0148te p\u0159ihla\u0161ovac\u00ed \u00fadaje Abode"
}
}
}
}

View File

@@ -0,0 +1,16 @@
{
"config": {
"abort": {
"single_instance_allowed": "Det er kun n\u00f8dvendigt med en ops\u00e6tning af Abode."
},
"step": {
"user": {
"data": {
"password": "Adgangskode",
"username": "Email-adresse"
},
"title": "Udfyld dine Abode-loginoplysninger"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "Die erneute Authentifizierung war erfolgreich",
"single_instance_allowed": "Bereits konfiguriert. Nur eine einzige Konfiguration m\u00f6glich."
},
"error": {
"cannot_connect": "Verbindung fehlgeschlagen",
"invalid_auth": "Ung\u00fcltige Authentifizierung",
"invalid_mfa_code": "Ung\u00fcltiger MFA-Code"
},
"step": {
"mfa": {
"data": {
"mfa_code": "MFA-Code (6-stellig)"
},
"title": "Gib deinen MFA-Code f\u00fcr Abode ein"
},
"reauth_confirm": {
"data": {
"password": "Passwort",
"username": "E-Mail"
},
"title": "Gib deine Abode-Anmeldeinformationen ein"
},
"user": {
"data": {
"password": "Passwort",
"username": "E-Mail"
},
"title": "Gib deine Abode Anmeldeinformationen ein"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "\u039f \u03b5\u03ba \u03bd\u03ad\u03bf\u03c5 \u03ad\u03bb\u03b5\u03b3\u03c7\u03bf\u03c2 \u03c4\u03b1\u03c5\u03c4\u03cc\u03c4\u03b7\u03c4\u03b1\u03c2 \u03ae\u03c4\u03b1\u03bd \u03b5\u03c0\u03b9\u03c4\u03c5\u03c7\u03ae\u03c2",
"single_instance_allowed": "\u0388\u03c7\u03b5\u03b9 \u03ae\u03b4\u03b7 \u03c1\u03c5\u03b8\u03bc\u03b9\u03c3\u03c4\u03b5\u03af. \u039c\u03cc\u03bd\u03bf \u03bc\u03af\u03b1 \u03b4\u03b9\u03b1\u03bc\u03cc\u03c1\u03c6\u03c9\u03c3\u03b7 \u03b5\u03af\u03bd\u03b1\u03b9 \u03b4\u03c5\u03bd\u03b1\u03c4\u03ae."
},
"error": {
"cannot_connect": "\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7\u03c2",
"invalid_auth": "\u039c\u03b7 \u03ad\u03b3\u03ba\u03c5\u03c1\u03b7 \u03b1\u03c5\u03b8\u03b5\u03bd\u03c4\u03b9\u03ba\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7",
"invalid_mfa_code": "\u039c\u03b7 \u03ad\u03b3\u03ba\u03c5\u03c1\u03bf\u03c2 \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 MFA"
},
"step": {
"mfa": {
"data": {
"mfa_code": "\u039a\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 MFA (6 \u03c8\u03b7\u03c6\u03af\u03b1)"
},
"title": "\u0395\u03b9\u03c3\u03b1\u03b3\u03ac\u03b3\u03b5\u03c4\u03b5 \u03c4\u03bf\u03bd \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc MFA \u03b3\u03b9\u03b1 \u03c4\u03bf Abode"
},
"reauth_confirm": {
"data": {
"password": "\u039a\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2",
"username": "Email"
},
"title": "\u03a3\u03c5\u03bc\u03c0\u03bb\u03b7\u03c1\u03ce\u03c3\u03c4\u03b5 \u03c4\u03b1 \u03c3\u03c4\u03bf\u03b9\u03c7\u03b5\u03af\u03b1 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03ae\u03c2 \u03c3\u03b1\u03c2 \u03c3\u03c4\u03bf Abode"
},
"user": {
"data": {
"password": "\u039a\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2",
"username": "Email"
},
"title": "\u03a3\u03c5\u03bc\u03c0\u03bb\u03b7\u03c1\u03ce\u03c3\u03c4\u03b5 \u03c4\u03b1 \u03c3\u03c4\u03bf\u03b9\u03c7\u03b5\u03af\u03b1 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03ae\u03c2 \u03c3\u03b1\u03c2 \u03c3\u03c4\u03bf Abode"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "Re-authentication was successful",
"single_instance_allowed": "Already configured. Only a single configuration possible."
},
"error": {
"cannot_connect": "Failed to connect",
"invalid_auth": "Invalid authentication",
"invalid_mfa_code": "Invalid MFA code"
},
"step": {
"mfa": {
"data": {
"mfa_code": "MFA code (6-digits)"
},
"title": "Enter your MFA code for Abode"
},
"reauth_confirm": {
"data": {
"password": "Password",
"username": "Email"
},
"title": "Fill in your Abode login information"
},
"user": {
"data": {
"password": "Password",
"username": "Email"
},
"title": "Fill in your Abode login information"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "La reautenticaci\u00f3n fue exitosa",
"single_instance_allowed": "Solo se permite una \u00fanica configuraci\u00f3n de Abode."
},
"error": {
"cannot_connect": "No se pudo conectar",
"invalid_auth": "Autenticaci\u00f3n inv\u00e1lida",
"invalid_mfa_code": "C\u00f3digo MFA no v\u00e1lido"
},
"step": {
"mfa": {
"data": {
"mfa_code": "C\u00f3digo MFA (6 d\u00edgitos)"
},
"title": "Ingrese su c\u00f3digo MFA para Abode"
},
"reauth_confirm": {
"data": {
"password": "Contrase\u00f1a",
"username": "Correo electr\u00f3nico"
},
"title": "Complete su informaci\u00f3n de inicio de sesi\u00f3n de Abode"
},
"user": {
"data": {
"password": "Contrase\u00f1a",
"username": "Direcci\u00f3n de correo electr\u00f3nico"
},
"title": "Complete su informaci\u00f3n de inicio de sesi\u00f3n de Abode"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "La autenticaci\u00f3n se volvi\u00f3 a realizar correctamente",
"single_instance_allowed": "Ya est\u00e1 configurado. Solo es posible una \u00fanica configuraci\u00f3n."
},
"error": {
"cannot_connect": "No se pudo conectar",
"invalid_auth": "Autenticaci\u00f3n no v\u00e1lida",
"invalid_mfa_code": "C\u00f3digo MFA no v\u00e1lido"
},
"step": {
"mfa": {
"data": {
"mfa_code": "C\u00f3digo MFA (6 d\u00edgitos)"
},
"title": "Introduce tu c\u00f3digo MFA para Abode"
},
"reauth_confirm": {
"data": {
"password": "Contrase\u00f1a",
"username": "Correo electr\u00f3nico"
},
"title": "Completa tu informaci\u00f3n de inicio de sesi\u00f3n de Abode"
},
"user": {
"data": {
"password": "Contrase\u00f1a",
"username": "Correo electr\u00f3nico"
},
"title": "Completa tu informaci\u00f3n de inicio de sesi\u00f3n de Abode"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "Taastuvastamine \u00f5nnestus",
"single_instance_allowed": "Juba seadistatud. V\u00f5imalik on ainult \u00fcks seadistamine."
},
"error": {
"cannot_connect": "\u00dchendamine nurjus",
"invalid_auth": "Tuvastamise viga",
"invalid_mfa_code": "Kehtetu MFA-kood"
},
"step": {
"mfa": {
"data": {
"mfa_code": "MFA kood (6-kohaline)"
},
"title": "Sisesta oma Abode MFA kood"
},
"reauth_confirm": {
"data": {
"password": "Salas\u00f5na",
"username": "E-post"
},
"title": "Sisesta oma Abode sisselogimisteave"
},
"user": {
"data": {
"password": "Salas\u00f5na",
"username": "E-post"
},
"title": "Sisesta oma Abode sisselogimisteave"
}
}
}
}

View File

@@ -0,0 +1,12 @@
{
"config": {
"step": {
"user": {
"data": {
"password": "\u06a9\u0644\u0645\u0647 \u0639\u0628\u0648\u0631",
"username": "\u0627\u06cc\u0645\u06cc\u0644"
}
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "La r\u00e9-authentification a r\u00e9ussi",
"single_instance_allowed": "D\u00e9j\u00e0 configur\u00e9. Une seule configuration possible."
},
"error": {
"cannot_connect": "\u00c9chec de connexion",
"invalid_auth": "Authentification non valide",
"invalid_mfa_code": "Code MFA non valide"
},
"step": {
"mfa": {
"data": {
"mfa_code": "Code MFA (6 chiffres)"
},
"title": "Entrez votre code MFA pour Abode"
},
"reauth_confirm": {
"data": {
"password": "Mot de passe",
"username": "Courriel"
},
"title": "Remplissez vos informations de connexion Abode"
},
"user": {
"data": {
"password": "Mot de passe",
"username": "Courriel"
},
"title": "Remplissez vos informations de connexion Abode"
}
}
}
}

View File

@@ -0,0 +1,27 @@
{
"config": {
"abort": {
"reauth_successful": "\u05d4\u05d0\u05d9\u05de\u05d5\u05ea \u05de\u05d7\u05d3\u05e9 \u05d4\u05e6\u05dc\u05d9\u05d7",
"single_instance_allowed": "\u05ea\u05e6\u05d5\u05e8\u05ea\u05d5 \u05db\u05d1\u05e8 \u05e0\u05e7\u05d1\u05e2\u05d4. \u05e8\u05e7 \u05ea\u05e6\u05d5\u05e8\u05d4 \u05d0\u05d7\u05ea \u05d0\u05e4\u05e9\u05e8\u05d9\u05ea."
},
"error": {
"cannot_connect": "\u05d4\u05d4\u05ea\u05d7\u05d1\u05e8\u05d5\u05ea \u05e0\u05db\u05e9\u05dc\u05d4",
"invalid_auth": "\u05d0\u05d9\u05de\u05d5\u05ea \u05dc\u05d0 \u05d7\u05d5\u05e7\u05d9"
},
"step": {
"reauth_confirm": {
"data": {
"password": "\u05e1\u05d9\u05e1\u05de\u05d4",
"username": "\u05d3\u05d5\u05d0\"\u05dc"
}
},
"user": {
"data": {
"password": "\u05e1\u05d9\u05e1\u05de\u05d4",
"username": "\u05d3\u05d5\u05d0\"\u05dc"
},
"title": "\u05d9\u05e9 \u05dc\u05de\u05dc\u05d0 \u05d0\u05ea \u05e4\u05e8\u05d8\u05d9 \u05d4\u05db\u05e0\u05d9\u05e1\u05d4 \u05e9\u05dc\u05da \u05dc\u05d0\u05d3\u05d5\u05d1\u05d9"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "Az \u00fajrahiteles\u00edt\u00e9s sikeres volt.",
"single_instance_allowed": "M\u00e1r konfigur\u00e1lva van. Csak egy konfigur\u00e1ci\u00f3 lehets\u00e9ges."
},
"error": {
"cannot_connect": "Sikertelen csatlakoz\u00e1s",
"invalid_auth": "\u00c9rv\u00e9nytelen hiteles\u00edt\u00e9s",
"invalid_mfa_code": "\u00c9rv\u00e9nytelen MFA k\u00f3d"
},
"step": {
"mfa": {
"data": {
"mfa_code": "MFA k\u00f3d (6 jegy\u0171)"
},
"title": "Add meg az Abode MFA k\u00f3dj\u00e1t"
},
"reauth_confirm": {
"data": {
"password": "Jelsz\u00f3",
"username": "E-mail"
},
"title": "T\u00f6ltse ki az Abode bejelentkez\u00e9si adatait"
},
"user": {
"data": {
"password": "Jelsz\u00f3",
"username": "E-mail"
},
"title": "T\u00f6ltse ki az Abode bejelentkez\u00e9si adatait"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "Autentikasi ulang berhasil",
"single_instance_allowed": "Sudah dikonfigurasi. Hanya satu konfigurasi yang diizinkan."
},
"error": {
"cannot_connect": "Gagal terhubung",
"invalid_auth": "Autentikasi tidak valid",
"invalid_mfa_code": "Kode MFA tidak valid"
},
"step": {
"mfa": {
"data": {
"mfa_code": "Kode MFA (6 digit)"
},
"title": "Masukkan kode MFA Anda untuk Abode"
},
"reauth_confirm": {
"data": {
"password": "Kata Sandi",
"username": "Email"
},
"title": "Masukkan informasi masuk Abode Anda"
},
"user": {
"data": {
"password": "Kata Sandi",
"username": "Email"
},
"title": "Masukkan informasi masuk Abode Anda"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "La nuova autenticazione \u00e8 stata eseguita correttamente",
"single_instance_allowed": "Gi\u00e0 configurato. \u00c8 possibile una sola configurazione."
},
"error": {
"cannot_connect": "Impossibile connettersi",
"invalid_auth": "Autenticazione non valida",
"invalid_mfa_code": "Codice MFA non valido"
},
"step": {
"mfa": {
"data": {
"mfa_code": "Codice MFA (6 cifre)"
},
"title": "Inserisci il tuo codice MFA per Abode"
},
"reauth_confirm": {
"data": {
"password": "Password",
"username": "Email"
},
"title": "Inserisci le tue informazioni di accesso Abode"
},
"user": {
"data": {
"password": "Password",
"username": "Email"
},
"title": "Inserisci le tue informazioni di accesso Abode"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "\u518d\u8a8d\u8a3c\u306b\u6210\u529f\u3057\u307e\u3057\u305f",
"single_instance_allowed": "\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u8a2d\u5b9a\u3067\u304d\u308b\u306e\u306f1\u3064\u3060\u3051\u3067\u3059\u3002"
},
"error": {
"cannot_connect": "\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f",
"invalid_auth": "\u7121\u52b9\u306a\u8a8d\u8a3c",
"invalid_mfa_code": "\u7121\u52b9\u306aMFA\u30b3\u30fc\u30c9"
},
"step": {
"mfa": {
"data": {
"mfa_code": "MFA\u30b3\u30fc\u30c9(6\u6841)"
},
"title": "Abode\u306eMFA\u30b3\u30fc\u30c9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044"
},
"reauth_confirm": {
"data": {
"password": "\u30d1\u30b9\u30ef\u30fc\u30c9",
"username": "E\u30e1\u30fc\u30eb"
},
"title": "Abode\u306e\u30ed\u30b0\u30a4\u30f3\u60c5\u5831\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044"
},
"user": {
"data": {
"password": "\u30d1\u30b9\u30ef\u30fc\u30c9",
"username": "E\u30e1\u30fc\u30eb"
},
"title": "Abode\u306e\u30ed\u30b0\u30a4\u30f3\u60c5\u5831\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "\uc7ac\uc778\uc99d\uc5d0 \uc131\uacf5\ud588\uc2b5\ub2c8\ub2e4",
"single_instance_allowed": "\uc774\ubbf8 \uad6c\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \ud558\ub098\uc758 \uc778\uc2a4\ud134\uc2a4\ub9cc \uad6c\uc131\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4."
},
"error": {
"cannot_connect": "\uc5f0\uacb0\ud558\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4",
"invalid_auth": "\uc778\uc99d\uc774 \uc798\ubabb\ub418\uc5c8\uc2b5\ub2c8\ub2e4",
"invalid_mfa_code": "MFA \ucf54\ub4dc\uac00 \uc798\ubabb\ub418\uc5c8\uc2b5\ub2c8\ub2e4"
},
"step": {
"mfa": {
"data": {
"mfa_code": "MFA \ucf54\ub4dc (6\uc790\ub9ac)"
},
"title": "Abode\uc5d0 \ub300\ud55c MFA \ucf54\ub4dc\ub97c \uc785\ub825\ud574\uc8fc\uc138\uc694"
},
"reauth_confirm": {
"data": {
"password": "\ube44\ubc00\ubc88\ud638",
"username": "\uc774\uba54\uc77c"
},
"title": "Abode \ub85c\uadf8\uc778 \uc815\ubcf4 \uc785\ub825\ud558\uae30"
},
"user": {
"data": {
"password": "\ube44\ubc00\ubc88\ud638",
"username": "\uc774\uba54\uc77c"
},
"title": "Abode \uc0ac\uc6a9\uc790 \uc815\ubcf4 \uc785\ub825\ud558\uae30"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "Re-authentifikatioun war erfollegr\u00e4ich",
"single_instance_allowed": "Scho konfigur\u00e9iert. N\u00ebmmen eng eenzeg Konfiguratioun m\u00e9iglech."
},
"error": {
"cannot_connect": "Feeler beim verbannen",
"invalid_auth": "Ong\u00eblteg Authentifikatioun",
"invalid_mfa_code": "Ong\u00ebltege MFA Code"
},
"step": {
"mfa": {
"data": {
"mfa_code": "MFA code (6 Zifferen)"
},
"title": "G\u00ebff dain MFA code fir Abode un"
},
"reauth_confirm": {
"data": {
"password": "Passwuert",
"username": "E-Mail"
},
"title": "F\u00ebll deng Abode Login Informatiounen aus"
},
"user": {
"data": {
"password": "Passwuert",
"username": "E-Mail"
},
"title": "F\u00ebllt \u00e4r Abode Login Informatiounen aus."
}
}
}
}

View File

@@ -0,0 +1,12 @@
{
"config": {
"step": {
"user": {
"data": {
"password": "Slapta\u017eodis",
"username": "El. pa\u0161tas"
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
{
"config": {
"step": {
"user": {
"data": {
"password": "Parole",
"username": "E-pasta adrese"
}
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "Herauthenticatie geslaagd",
"single_instance_allowed": "Al geconfigureerd. Slechts \u00e9\u00e9n configuratie mogelijk."
},
"error": {
"cannot_connect": "Kan geen verbinding maken",
"invalid_auth": "Ongeldige authenticatie",
"invalid_mfa_code": "Ongeldige MFA-code"
},
"step": {
"mfa": {
"data": {
"mfa_code": "MFA-code (6-cijfers)"
},
"title": "Voer uw MFA-code voor Abode in"
},
"reauth_confirm": {
"data": {
"password": "Wachtwoord",
"username": "E-mail"
},
"title": "Vul uw Abode-inloggegevens in"
},
"user": {
"data": {
"password": "Wachtwoord",
"username": "E-mail"
},
"title": "Vul uw Abode-inloggegevens in"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "Re-autentisering var vellykket",
"single_instance_allowed": "Allerede konfigurert. Bare \u00e9n enkelt konfigurasjon er mulig."
},
"error": {
"cannot_connect": "Tilkobling mislyktes",
"invalid_auth": "Ugyldig godkjenning",
"invalid_mfa_code": "Ugyldig MFA-kode"
},
"step": {
"mfa": {
"data": {
"mfa_code": "MFA-kode (6-sifre)"
},
"title": "Skriv inn din MFA-kode for Abode"
},
"reauth_confirm": {
"data": {
"password": "Passord",
"username": "E-post"
},
"title": "Fyll ut innloggingsinformasjonen for Abode"
},
"user": {
"data": {
"password": "Passord",
"username": "E-post"
},
"title": "Fyll ut innloggingsinformasjonen for Abode"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "Ponowne uwierzytelnienie powiod\u0142o si\u0119",
"single_instance_allowed": "Ju\u017c skonfigurowano. Mo\u017cliwa jest tylko jedna konfiguracja."
},
"error": {
"cannot_connect": "Nie mo\u017cna nawi\u0105za\u0107 po\u0142\u0105czenia",
"invalid_auth": "Niepoprawne uwierzytelnienie",
"invalid_mfa_code": "Nieprawid\u0142owy kod uwierzytelniania wielosk\u0142adnikowego"
},
"step": {
"mfa": {
"data": {
"mfa_code": "6-cyfrowy kod uwierzytelniania wielosk\u0142adnikowego"
},
"title": "Wprowad\u017a kod uwierzytelniania wielosk\u0142adnikowego dla Abode"
},
"reauth_confirm": {
"data": {
"password": "Has\u0142o",
"username": "Adres e-mail"
},
"title": "Wprowad\u017a informacje logowania Abode"
},
"user": {
"data": {
"password": "Has\u0142o",
"username": "Adres e-mail"
},
"title": "Wprowad\u017a informacje logowania Abode"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "A reautentica\u00e7\u00e3o foi bem-sucedida",
"single_instance_allowed": "J\u00e1 configurado. Apenas uma configura\u00e7\u00e3o \u00e9 poss\u00edvel."
},
"error": {
"cannot_connect": "Falha ao conectar",
"invalid_auth": "Autentica\u00e7\u00e3o inv\u00e1lida",
"invalid_mfa_code": "C\u00f3digo MFA inv\u00e1lido"
},
"step": {
"mfa": {
"data": {
"mfa_code": "C\u00f3digo MFA (6 d\u00edgitos)"
},
"title": "Digite seu c\u00f3digo MFA para Abode"
},
"reauth_confirm": {
"data": {
"password": "Senha",
"username": "Email"
},
"title": "Preencha as informa\u00e7\u00f5es de login da Abode"
},
"user": {
"data": {
"password": "Senha",
"username": "Email"
},
"title": "Preencha suas informa\u00e7\u00f5es de login Abode"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "Reautentica\u00e7\u00e3o bem sucedida",
"single_instance_allowed": "J\u00e1 configurado. Apenas uma \u00fanica configura\u00e7\u00e3o \u00e9 poss\u00edvel."
},
"error": {
"cannot_connect": "A liga\u00e7\u00e3o falhou",
"invalid_auth": "Autentica\u00e7\u00e3o inv\u00e1lida",
"invalid_mfa_code": "C\u00f3digo MFA inv\u00e1lido"
},
"step": {
"mfa": {
"data": {
"mfa_code": "C\u00f3digo MFA (6 d\u00edgitos)"
},
"title": "Introduza seu c\u00f3digo MFA para Abode"
},
"reauth_confirm": {
"data": {
"password": "Palavra-passe",
"username": ""
},
"title": "Preencha as informa\u00e7\u00f5es de login de Abode"
},
"user": {
"data": {
"password": "Palavra-passe",
"username": ""
},
"title": "Preencha as informa\u00e7\u00f5es de login de Abode"
}
}
}
}

View File

@@ -0,0 +1,7 @@
{
"config": {
"abort": {
"reauth_successful": "Re-autentificare efectuata cu succes"
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u0430\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e.",
"single_instance_allowed": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0443\u0436\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0443 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e."
},
"error": {
"cannot_connect": "\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f.",
"invalid_auth": "\u041e\u0448\u0438\u0431\u043a\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.",
"invalid_mfa_code": "\u041d\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 MFA."
},
"step": {
"mfa": {
"data": {
"mfa_code": "\u041a\u043e\u0434 MFA (6 \u0446\u0438\u0444\u0440)"
},
"title": "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043e\u0434 MFA \u0434\u043b\u044f Abode"
},
"reauth_confirm": {
"data": {
"password": "\u041f\u0430\u0440\u043e\u043b\u044c",
"username": "\u0410\u0434\u0440\u0435\u0441 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b"
},
"title": "Abode"
},
"user": {
"data": {
"password": "\u041f\u0430\u0440\u043e\u043b\u044c",
"username": "\u0410\u0434\u0440\u0435\u0441 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b"
},
"title": "Abode"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "Op\u00e4tovn\u00e9 overenie bolo \u00faspe\u0161n\u00e9",
"single_instance_allowed": "U\u017e je nakonfigurovan\u00fd. Mo\u017en\u00e1 len jedna konfigur\u00e1cia."
},
"error": {
"cannot_connect": "Nepodarilo sa pripoji\u0165",
"invalid_auth": "Neplatn\u00e9 overenie",
"invalid_mfa_code": "Neplatn\u00fd k\u00f3d MFA"
},
"step": {
"mfa": {
"data": {
"mfa_code": "K\u00f3d MFA (6-miestny)"
},
"title": "Zadajte svoj k\u00f3d MFA pre Abode"
},
"reauth_confirm": {
"data": {
"password": "Heslo",
"username": "Email"
},
"title": "Vypl\u0148te svoje prihlasovacie \u00fadaje do slu\u017eby Abode"
},
"user": {
"data": {
"password": "Heslo",
"username": "Email"
},
"title": "Vypl\u0148te svoje prihlasovacie \u00fadaje Abode"
}
}
}
}

View File

@@ -0,0 +1,33 @@
{
"config": {
"abort": {
"reauth_successful": "Ponovno overjanje je uspelo",
"single_instance_allowed": "Dovoljena je samo ena konfiguracija Abode."
},
"error": {
"invalid_mfa_code": "Napa\u010dna MFA koda"
},
"step": {
"mfa": {
"data": {
"mfa_code": "MFA koda (6 \u0161tevilk)"
},
"title": "Vnesite MFA kodo za Abode"
},
"reauth_confirm": {
"data": {
"password": "Geslo",
"username": "E-po\u0161tni naslov"
},
"title": "Vnesite podatke za prijavo v Abode"
},
"user": {
"data": {
"password": "Geslo",
"username": "E-po\u0161tni naslov"
},
"title": "Izpolnite svoje podatke za prijavo v Abode"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "\u00c5terautentisering lyckades",
"single_instance_allowed": "Endast en enda konfiguration av Abode \u00e4r till\u00e5ten."
},
"error": {
"cannot_connect": "Det gick inte att ansluta.",
"invalid_auth": "Ogiltig autentisering",
"invalid_mfa_code": "Ogiltig MFA-kod"
},
"step": {
"mfa": {
"data": {
"mfa_code": "MFA-kod (6 siffror)"
},
"title": "Ange din MFA-kod f\u00f6r Abode"
},
"reauth_confirm": {
"data": {
"password": "L\u00f6senord",
"username": "E-postadress"
},
"title": "Fyll i din Abode-inloggningsinformation"
},
"user": {
"data": {
"password": "L\u00f6senord",
"username": "E-postadress"
},
"title": "Fyll i din inloggningsinformation f\u00f6r Abode"
}
}
}
}

View File

@@ -0,0 +1,9 @@
{
"config": {
"step": {
"mfa": {
"title": "\u0e1b\u0e49\u0e2d\u0e19\u0e23\u0e2b\u0e31\u0e2a MFA \u0e08\u0e32\u0e01 Abode"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "Yeniden kimlik do\u011frulama ba\u015far\u0131l\u0131 oldu",
"single_instance_allowed": "Zaten yap\u0131land\u0131r\u0131lm\u0131\u015f. Yaln\u0131zca tek bir konfig\u00fcrasyon m\u00fcmk\u00fcnd\u00fcr."
},
"error": {
"cannot_connect": "Ba\u011flanma hatas\u0131",
"invalid_auth": "Ge\u00e7ersiz kimlik do\u011frulama",
"invalid_mfa_code": "Ge\u00e7ersiz MFA kodu"
},
"step": {
"mfa": {
"data": {
"mfa_code": "MFA kodu (6 basamakl\u0131)"
},
"title": "Abode i\u00e7in MFA kodunuzu girin"
},
"reauth_confirm": {
"data": {
"password": "Parola",
"username": "E-posta"
},
"title": "Abode giri\u015f bilgilerinizi doldurun"
},
"user": {
"data": {
"password": "Parola",
"username": "E-posta"
},
"title": "Abode giri\u015f bilgilerinizi doldurun"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u0430 \u0430\u0432\u0442\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u044f \u043f\u0440\u043e\u0439\u0448\u043b\u0430 \u0443\u0441\u043f\u0456\u0448\u043d\u043e",
"single_instance_allowed": "\u0412\u0436\u0435 \u043d\u0430\u043b\u0430\u0448\u0442\u043e\u0432\u0430\u043d\u043e. \u041c\u043e\u0436\u043b\u0438\u0432\u0430 \u043b\u0438\u0448\u0435 \u043e\u0434\u043d\u0430 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u044f."
},
"error": {
"cannot_connect": "\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u043f\u0456\u0434'\u0454\u0434\u043d\u0430\u0442\u0438\u0441\u044f",
"invalid_auth": "\u041d\u0435\u0432\u0456\u0440\u043d\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u044f.",
"invalid_mfa_code": "\u041d\u0435\u0434\u0456\u0439\u0441\u043d\u0438\u0439 \u043a\u043e\u0434 MFA."
},
"step": {
"mfa": {
"data": {
"mfa_code": "\u041a\u043e\u0434 MFA (6 \u0446\u0438\u0444\u0440)"
},
"title": "\u0412\u0432\u0435\u0434\u0456\u0442\u044c \u043a\u043e\u0434 MFA \u0434\u043b\u044f Abode"
},
"reauth_confirm": {
"data": {
"password": "\u041f\u0430\u0440\u043e\u043b\u044c",
"username": "\u0410\u0434\u0440\u0435\u0441\u0430 \u0435\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0457 \u043f\u043e\u0448\u0442\u0438"
},
"title": "Abode"
},
"user": {
"data": {
"password": "\u041f\u0430\u0440\u043e\u043b\u044c",
"username": "\u0410\u0434\u0440\u0435\u0441\u0430 \u0435\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0457 \u043f\u043e\u0448\u0442\u0438"
},
"title": "Abode"
}
}
}
}

View File

@@ -0,0 +1,35 @@
{
"config": {
"abort": {
"reauth_successful": "\u91cd\u65b0\u8a8d\u8b49\u6210\u529f",
"single_instance_allowed": "\u5df2\u7d93\u8a2d\u5b9a\u5b8c\u6210\u3001\u50c5\u80fd\u8a2d\u5b9a\u4e00\u7d44\u88dd\u7f6e\u3002"
},
"error": {
"cannot_connect": "\u9023\u7dda\u5931\u6557",
"invalid_auth": "\u9a57\u8b49\u78bc\u7121\u6548",
"invalid_mfa_code": "\u591a\u6b65\u9a5f\u8a8d\u8b49\u78bc\u7121\u6548"
},
"step": {
"mfa": {
"data": {
"mfa_code": "\u591a\u6b65\u9a5f\u8a8d\u8b49\u78bc\uff086 \u4f4d\uff09"
},
"title": "\u8f38\u5165 Abode \u591a\u6b65\u9a5f\u8a8d\u8b49\u78bc"
},
"reauth_confirm": {
"data": {
"password": "\u5bc6\u78bc",
"username": "\u96fb\u5b50\u90f5\u4ef6"
},
"title": "\u586b\u5beb Abode \u767b\u5165\u8cc7\u8a0a"
},
"user": {
"data": {
"password": "\u5bc6\u78bc",
"username": "\u96fb\u5b50\u90f5\u4ef6"
},
"title": "\u586b\u5beb Abode \u767b\u5165\u8cc7\u8a0a"
}
}
}
}

View File

@@ -10,15 +10,14 @@ from aiohttp import ClientSession
from aiohttp.client_exceptions import ClientConnectorError
from async_timeout import timeout
from homeassistant.components.sensor import DOMAIN as SENSOR_PLATFORM
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_API_KEY, CONF_NAME, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from homeassistant.util.unit_system import METRIC_SYSTEM
from .const import ATTR_FORECAST, CONF_FORECAST, DOMAIN, MANUFACTURER
@@ -50,14 +49,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
# Remove ozone sensors from registry if they exist
ent_reg = er.async_get(hass)
for day in range(0, 5):
unique_id = f"{coordinator.location_key}-ozone-{day}"
if entity_id := ent_reg.async_get_entity_id(SENSOR_PLATFORM, DOMAIN, unique_id):
_LOGGER.debug("Removing ozone sensor entity %s", entity_id)
ent_reg.async_remove(entity_id)
return True
@@ -125,7 +116,11 @@ class AccuWeatherDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
async with timeout(10):
current = await self.accuweather.async_get_current_conditions()
forecast = (
await self.accuweather.async_get_forecast() if self.forecast else {}
await self.accuweather.async_get_forecast(
metric=self.hass.config.units is METRIC_SYSTEM
)
if self.forecast
else {}
)
except (
ApiError,

View File

@@ -20,6 +20,7 @@ from homeassistant.components.weather import (
ATTR_CONDITION_WINDY,
)
API_IMPERIAL: Final = "Imperial"
API_METRIC: Final = "Metric"
ATTRIBUTION: Final = "Data provided by AccuWeather"
ATTR_CATEGORY: Final = "Category"

View File

@@ -1,12 +1,12 @@
{
"domain": "accuweather",
"name": "AccuWeather",
"documentation": "https://www.home-assistant.io/integrations/accuweather/",
"requirements": ["accuweather==0.5.0"],
"codeowners": ["@bieniu"],
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/accuweather/",
"integration_type": "service",
"quality_scale": "platinum",
"iot_class": "cloud_polling",
"loggers": ["accuweather"],
"quality_scale": "platinum",
"requirements": ["accuweather==0.5.1"]
"integration_type": "service"
}

View File

@@ -26,9 +26,11 @@ from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.util.unit_system import METRIC_SYSTEM
from . import AccuWeatherDataUpdateCoordinator
from .const import (
API_IMPERIAL,
API_METRIC,
ATTR_CATEGORY,
ATTR_DIRECTION,
@@ -49,7 +51,7 @@ PARALLEL_UPDATES = 1
class AccuWeatherSensorDescriptionMixin:
"""Mixin for AccuWeather sensor."""
value_fn: Callable[[dict[str, Any]], StateType]
value_fn: Callable[[dict[str, Any], str], StateType]
@dataclass
@@ -59,25 +61,18 @@ class AccuWeatherSensorDescription(
"""Class describing AccuWeather sensor entities."""
attr_fn: Callable[[dict[str, Any]], dict[str, StateType]] = lambda _: {}
metric_unit: str | None = None
us_customary_unit: str | None = None
FORECAST_SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
AccuWeatherSensorDescription(
key="AirQuality",
icon="mdi:air-filter",
name="Air quality",
value_fn=lambda data: cast(str, data[ATTR_CATEGORY]),
device_class=SensorDeviceClass.ENUM,
options=["good", "hazardous", "high", "low", "moderate", "unhealthy"],
translation_key="air_quality",
),
AccuWeatherSensorDescription(
key="CloudCoverDay",
icon="mdi:weather-cloudy",
name="Cloud cover day",
entity_registry_enabled_default=False,
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda data: cast(int, data),
value_fn=lambda data, _: cast(int, data),
),
AccuWeatherSensorDescription(
key="CloudCoverNight",
@@ -85,7 +80,7 @@ FORECAST_SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
name="Cloud cover night",
entity_registry_enabled_default=False,
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda data: cast(int, data),
value_fn=lambda data, _: cast(int, data),
),
AccuWeatherSensorDescription(
key="Grass",
@@ -93,16 +88,15 @@ FORECAST_SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
name="Grass pollen",
entity_registry_enabled_default=False,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
value_fn=lambda data: cast(int, data[ATTR_VALUE]),
value_fn=lambda data, _: cast(int, data[ATTR_VALUE]),
attr_fn=lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]},
translation_key="grass_pollen",
),
AccuWeatherSensorDescription(
key="HoursOfSun",
icon="mdi:weather-partly-cloudy",
name="Hours of sun",
native_unit_of_measurement=UnitOfTime.HOURS,
value_fn=lambda data: cast(float, data),
value_fn=lambda data, _: cast(float, data),
),
AccuWeatherSensorDescription(
key="Mold",
@@ -110,9 +104,16 @@ FORECAST_SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
name="Mold pollen",
entity_registry_enabled_default=False,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
value_fn=lambda data: cast(int, data[ATTR_VALUE]),
value_fn=lambda data, _: cast(int, data[ATTR_VALUE]),
attr_fn=lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]},
),
AccuWeatherSensorDescription(
key="Ozone",
icon="mdi:vector-triangle",
name="Ozone",
entity_registry_enabled_default=False,
value_fn=lambda data, _: cast(int, data[ATTR_VALUE]),
attr_fn=lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]},
translation_key="mold_pollen",
),
AccuWeatherSensorDescription(
key="Ragweed",
@@ -120,53 +121,56 @@ FORECAST_SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
name="Ragweed pollen",
native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
entity_registry_enabled_default=False,
value_fn=lambda data: cast(int, data[ATTR_VALUE]),
value_fn=lambda data, _: cast(int, data[ATTR_VALUE]),
attr_fn=lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]},
translation_key="ragweed_pollen",
),
AccuWeatherSensorDescription(
key="RealFeelTemperatureMax",
device_class=SensorDeviceClass.TEMPERATURE,
name="RealFeel temperature max",
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
value_fn=lambda data: cast(float, data[ATTR_VALUE]),
metric_unit=UnitOfTemperature.CELSIUS,
us_customary_unit=UnitOfTemperature.FAHRENHEIT,
value_fn=lambda data, _: cast(float, data[ATTR_VALUE]),
),
AccuWeatherSensorDescription(
key="RealFeelTemperatureMin",
device_class=SensorDeviceClass.TEMPERATURE,
name="RealFeel temperature min",
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
value_fn=lambda data: cast(float, data[ATTR_VALUE]),
metric_unit=UnitOfTemperature.CELSIUS,
us_customary_unit=UnitOfTemperature.FAHRENHEIT,
value_fn=lambda data, _: cast(float, data[ATTR_VALUE]),
),
AccuWeatherSensorDescription(
key="RealFeelTemperatureShadeMax",
device_class=SensorDeviceClass.TEMPERATURE,
name="RealFeel temperature shade max",
entity_registry_enabled_default=False,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
value_fn=lambda data: cast(float, data[ATTR_VALUE]),
metric_unit=UnitOfTemperature.CELSIUS,
us_customary_unit=UnitOfTemperature.FAHRENHEIT,
value_fn=lambda data, _: cast(float, data[ATTR_VALUE]),
),
AccuWeatherSensorDescription(
key="RealFeelTemperatureShadeMin",
device_class=SensorDeviceClass.TEMPERATURE,
name="RealFeel temperature shade min",
entity_registry_enabled_default=False,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
value_fn=lambda data: cast(float, data[ATTR_VALUE]),
metric_unit=UnitOfTemperature.CELSIUS,
us_customary_unit=UnitOfTemperature.FAHRENHEIT,
value_fn=lambda data, _: cast(float, data[ATTR_VALUE]),
),
AccuWeatherSensorDescription(
key="ThunderstormProbabilityDay",
icon="mdi:weather-lightning",
name="Thunderstorm probability day",
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda data: cast(int, data),
value_fn=lambda data, _: cast(int, data),
),
AccuWeatherSensorDescription(
key="ThunderstormProbabilityNight",
icon="mdi:weather-lightning",
name="Thunderstorm probability night",
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda data: cast(int, data),
value_fn=lambda data, _: cast(int, data),
),
AccuWeatherSensorDescription(
key="Tree",
@@ -174,26 +178,25 @@ FORECAST_SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
name="Tree pollen",
native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
entity_registry_enabled_default=False,
value_fn=lambda data: cast(int, data[ATTR_VALUE]),
value_fn=lambda data, _: cast(int, data[ATTR_VALUE]),
attr_fn=lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]},
translation_key="tree_pollen",
),
AccuWeatherSensorDescription(
key="UVIndex",
icon="mdi:weather-sunny",
name="UV index",
native_unit_of_measurement=UV_INDEX,
value_fn=lambda data: cast(int, data[ATTR_VALUE]),
value_fn=lambda data, _: cast(int, data[ATTR_VALUE]),
attr_fn=lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]},
translation_key="uv_index",
),
AccuWeatherSensorDescription(
key="WindGustDay",
device_class=SensorDeviceClass.WIND_SPEED,
name="Wind gust day",
entity_registry_enabled_default=False,
native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
value_fn=lambda data: cast(float, data[ATTR_SPEED][ATTR_VALUE]),
metric_unit=UnitOfSpeed.KILOMETERS_PER_HOUR,
us_customary_unit=UnitOfSpeed.MILES_PER_HOUR,
value_fn=lambda data, _: cast(float, data[ATTR_SPEED][ATTR_VALUE]),
attr_fn=lambda data: {"direction": data[ATTR_DIRECTION][ATTR_ENGLISH]},
),
AccuWeatherSensorDescription(
@@ -201,24 +204,27 @@ FORECAST_SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
device_class=SensorDeviceClass.WIND_SPEED,
name="Wind gust night",
entity_registry_enabled_default=False,
native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
value_fn=lambda data: cast(float, data[ATTR_SPEED][ATTR_VALUE]),
metric_unit=UnitOfSpeed.KILOMETERS_PER_HOUR,
us_customary_unit=UnitOfSpeed.MILES_PER_HOUR,
value_fn=lambda data, _: cast(float, data[ATTR_SPEED][ATTR_VALUE]),
attr_fn=lambda data: {"direction": data[ATTR_DIRECTION][ATTR_ENGLISH]},
),
AccuWeatherSensorDescription(
key="WindDay",
device_class=SensorDeviceClass.WIND_SPEED,
name="Wind day",
native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
value_fn=lambda data: cast(float, data[ATTR_SPEED][ATTR_VALUE]),
metric_unit=UnitOfSpeed.KILOMETERS_PER_HOUR,
us_customary_unit=UnitOfSpeed.MILES_PER_HOUR,
value_fn=lambda data, _: cast(float, data[ATTR_SPEED][ATTR_VALUE]),
attr_fn=lambda data: {"direction": data[ATTR_DIRECTION][ATTR_ENGLISH]},
),
AccuWeatherSensorDescription(
key="WindNight",
device_class=SensorDeviceClass.WIND_SPEED,
name="Wind night",
native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
value_fn=lambda data: cast(float, data[ATTR_SPEED][ATTR_VALUE]),
metric_unit=UnitOfSpeed.KILOMETERS_PER_HOUR,
us_customary_unit=UnitOfSpeed.MILES_PER_HOUR,
value_fn=lambda data, _: cast(float, data[ATTR_SPEED][ATTR_VALUE]),
attr_fn=lambda data: {"direction": data[ATTR_DIRECTION][ATTR_ENGLISH]},
),
)
@@ -230,8 +236,9 @@ SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
name="Apparent temperature",
entity_registry_enabled_default=False,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
value_fn=lambda data: cast(float, data[API_METRIC][ATTR_VALUE]),
metric_unit=UnitOfTemperature.CELSIUS,
us_customary_unit=UnitOfTemperature.FAHRENHEIT,
value_fn=lambda data, unit: cast(float, data[unit][ATTR_VALUE]),
),
AccuWeatherSensorDescription(
key="Ceiling",
@@ -239,9 +246,10 @@ SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
icon="mdi:weather-fog",
name="Cloud ceiling",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfLength.METERS,
value_fn=lambda data: cast(float, data[API_METRIC][ATTR_VALUE]),
suggested_display_precision=0,
metric_unit=UnitOfLength.METERS,
us_customary_unit=UnitOfLength.FEET,
value_fn=lambda data, unit: cast(float, data[unit][ATTR_VALUE]),
native_precision=0,
),
AccuWeatherSensorDescription(
key="CloudCover",
@@ -250,7 +258,7 @@ SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
entity_registry_enabled_default=False,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda data: cast(int, data),
value_fn=lambda data, _: cast(int, data),
),
AccuWeatherSensorDescription(
key="DewPoint",
@@ -258,16 +266,18 @@ SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
name="Dew point",
entity_registry_enabled_default=False,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
value_fn=lambda data: cast(float, data[API_METRIC][ATTR_VALUE]),
metric_unit=UnitOfTemperature.CELSIUS,
us_customary_unit=UnitOfTemperature.FAHRENHEIT,
value_fn=lambda data, unit: cast(float, data[unit][ATTR_VALUE]),
),
AccuWeatherSensorDescription(
key="RealFeelTemperature",
device_class=SensorDeviceClass.TEMPERATURE,
name="RealFeel temperature",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
value_fn=lambda data: cast(float, data[API_METRIC][ATTR_VALUE]),
metric_unit=UnitOfTemperature.CELSIUS,
us_customary_unit=UnitOfTemperature.FAHRENHEIT,
value_fn=lambda data, unit: cast(float, data[unit][ATTR_VALUE]),
),
AccuWeatherSensorDescription(
key="RealFeelTemperatureShade",
@@ -275,16 +285,18 @@ SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
name="RealFeel temperature shade",
entity_registry_enabled_default=False,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
value_fn=lambda data: cast(float, data[API_METRIC][ATTR_VALUE]),
metric_unit=UnitOfTemperature.CELSIUS,
us_customary_unit=UnitOfTemperature.FAHRENHEIT,
value_fn=lambda data, unit: cast(float, data[unit][ATTR_VALUE]),
),
AccuWeatherSensorDescription(
key="Precipitation",
device_class=SensorDeviceClass.PRECIPITATION_INTENSITY,
name="Precipitation",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
value_fn=lambda data: cast(float, data[API_METRIC][ATTR_VALUE]),
metric_unit=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
us_customary_unit=UnitOfVolumetricFlux.INCHES_PER_HOUR,
value_fn=lambda data, unit: cast(float, data[unit][ATTR_VALUE]),
attr_fn=lambda data: {"type": data["PrecipitationType"]},
),
AccuWeatherSensorDescription(
@@ -294,7 +306,7 @@ SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
name="Pressure tendency",
options=["falling", "rising", "steady"],
translation_key="pressure_tendency",
value_fn=lambda data: cast(str, data["LocalizedText"]).lower(),
value_fn=lambda data, _: cast(str, data["LocalizedText"]).lower(),
),
AccuWeatherSensorDescription(
key="UVIndex",
@@ -302,7 +314,7 @@ SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
name="UV index",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UV_INDEX,
value_fn=lambda data: cast(int, data),
value_fn=lambda data, _: cast(int, data),
attr_fn=lambda data: {ATTR_LEVEL: data["UVIndexText"]},
),
AccuWeatherSensorDescription(
@@ -311,8 +323,9 @@ SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
name="Wet bulb temperature",
entity_registry_enabled_default=False,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
value_fn=lambda data: cast(float, data[API_METRIC][ATTR_VALUE]),
metric_unit=UnitOfTemperature.CELSIUS,
us_customary_unit=UnitOfTemperature.FAHRENHEIT,
value_fn=lambda data, unit: cast(float, data[unit][ATTR_VALUE]),
),
AccuWeatherSensorDescription(
key="WindChillTemperature",
@@ -320,16 +333,18 @@ SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
name="Wind chill temperature",
entity_registry_enabled_default=False,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
value_fn=lambda data: cast(float, data[API_METRIC][ATTR_VALUE]),
metric_unit=UnitOfTemperature.CELSIUS,
us_customary_unit=UnitOfTemperature.FAHRENHEIT,
value_fn=lambda data, unit: cast(float, data[unit][ATTR_VALUE]),
),
AccuWeatherSensorDescription(
key="Wind",
device_class=SensorDeviceClass.WIND_SPEED,
name="Wind",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
value_fn=lambda data: cast(float, data[ATTR_SPEED][API_METRIC][ATTR_VALUE]),
metric_unit=UnitOfSpeed.KILOMETERS_PER_HOUR,
us_customary_unit=UnitOfSpeed.MILES_PER_HOUR,
value_fn=lambda data, unit: cast(float, data[ATTR_SPEED][unit][ATTR_VALUE]),
),
AccuWeatherSensorDescription(
key="WindGust",
@@ -337,8 +352,9 @@ SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
name="Wind gust",
entity_registry_enabled_default=False,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
value_fn=lambda data: cast(float, data[ATTR_SPEED][API_METRIC][ATTR_VALUE]),
metric_unit=UnitOfSpeed.KILOMETERS_PER_HOUR,
us_customary_unit=UnitOfSpeed.MILES_PER_HOUR,
value_fn=lambda data, unit: cast(float, data[ATTR_SPEED][unit][ATTR_VALUE]),
),
)
@@ -358,7 +374,7 @@ async def async_setup_entry(
# Some air quality/allergy sensors are only available for certain
# locations.
sensors.extend(
AccuWeatherSensor(coordinator, description, forecast_day=day)
AccuWeatherForecastSensor(coordinator, description, forecast_day=day)
for day in range(MAX_FORECAST_DAYS + 1)
for description in FORECAST_SENSOR_TYPES
if description.key in coordinator.data[ATTR_FORECAST][0]
@@ -397,27 +413,34 @@ class AccuWeatherSensor(
self._attr_unique_id = (
f"{coordinator.location_key}-{description.key}".lower()
)
self._attr_native_unit_of_measurement = description.native_unit_of_measurement
if self.coordinator.hass.config.units is METRIC_SYSTEM:
self._unit_system = API_METRIC
if metric_unit := description.metric_unit:
self._attr_native_unit_of_measurement = metric_unit
else:
self._unit_system = API_IMPERIAL
if us_customary_unit := description.us_customary_unit:
self._attr_native_unit_of_measurement = us_customary_unit
self._attr_device_info = coordinator.device_info
self.forecast_day = forecast_day
if forecast_day is not None:
self.forecast_day = forecast_day
@property
def native_value(self) -> StateType:
"""Return the state."""
return self.entity_description.value_fn(self._sensor_data)
return self.entity_description.value_fn(self._sensor_data, self._unit_system)
@property
def extra_state_attributes(self) -> dict[str, Any]:
"""Return the state attributes."""
if self.forecast_day is not None:
return self.entity_description.attr_fn(self._sensor_data)
return self.entity_description.attr_fn(self.coordinator.data)
@callback
def _handle_coordinator_update(self) -> None:
"""Handle data update."""
self._sensor_data = _get_sensor_data(
self.coordinator.data, self.entity_description.key, self.forecast_day
self.coordinator.data, self.entity_description.key
)
self.async_write_ha_state()
@@ -435,3 +458,20 @@ def _get_sensor_data(
return sensors["PrecipitationSummary"]["PastHour"]
return sensors[kind]
class AccuWeatherForecastSensor(AccuWeatherSensor):
"""Define an AccuWeather forecast entity."""
@property
def extra_state_attributes(self) -> dict[str, Any]:
"""Return the state attributes."""
return self.entity_description.attr_fn(self._sensor_data)
@callback
def _handle_coordinator_update(self) -> None:
"""Handle data update."""
self._sensor_data = _get_sensor_data(
self.coordinator.data, self.entity_description.key, self.forecast_day
)
self.async_write_ha_state()

View File

@@ -30,91 +30,6 @@
"rising": "Rising",
"falling": "Falling"
}
},
"air_quality": {
"state": {
"good": "Good",
"hazardous": "Hazardous",
"high": "High",
"low": "Low",
"moderate": "Moderate",
"unhealthy": "Unhealthy"
}
},
"grass_pollen": {
"state_attributes": {
"level": {
"name": "Level",
"state": {
"good": "[%key:component::accuweather::entity::sensor::air_quality::state::good%]",
"hazardous": "[%key:component::accuweather::entity::sensor::air_quality::state::hazardous%]",
"high": "[%key:component::accuweather::entity::sensor::air_quality::state::high%]",
"low": "[%key:component::accuweather::entity::sensor::air_quality::state::low%]",
"moderate": "[%key:component::accuweather::entity::sensor::air_quality::state::moderate%]",
"unhealthy": "[%key:component::accuweather::entity::sensor::air_quality::state::unhealthy%]"
}
}
}
},
"mold_pollen": {
"state_attributes": {
"level": {
"name": "Level",
"state": {
"good": "[%key:component::accuweather::entity::sensor::air_quality::state::good%]",
"hazardous": "[%key:component::accuweather::entity::sensor::air_quality::state::hazardous%]",
"high": "[%key:component::accuweather::entity::sensor::air_quality::state::high%]",
"low": "[%key:component::accuweather::entity::sensor::air_quality::state::low%]",
"moderate": "[%key:component::accuweather::entity::sensor::air_quality::state::moderate%]",
"unhealthy": "[%key:component::accuweather::entity::sensor::air_quality::state::unhealthy%]"
}
}
}
},
"ragweed_pollen": {
"state_attributes": {
"level": {
"name": "Level",
"state": {
"good": "[%key:component::accuweather::entity::sensor::air_quality::state::good%]",
"hazardous": "[%key:component::accuweather::entity::sensor::air_quality::state::hazardous%]",
"high": "[%key:component::accuweather::entity::sensor::air_quality::state::high%]",
"low": "[%key:component::accuweather::entity::sensor::air_quality::state::low%]",
"moderate": "[%key:component::accuweather::entity::sensor::air_quality::state::moderate%]",
"unhealthy": "[%key:component::accuweather::entity::sensor::air_quality::state::unhealthy%]"
}
}
}
},
"tree_pollen": {
"state_attributes": {
"level": {
"name": "Level",
"state": {
"good": "[%key:component::accuweather::entity::sensor::air_quality::state::good%]",
"hazardous": "[%key:component::accuweather::entity::sensor::air_quality::state::hazardous%]",
"high": "[%key:component::accuweather::entity::sensor::air_quality::state::high%]",
"low": "[%key:component::accuweather::entity::sensor::air_quality::state::low%]",
"moderate": "[%key:component::accuweather::entity::sensor::air_quality::state::moderate%]",
"unhealthy": "[%key:component::accuweather::entity::sensor::air_quality::state::unhealthy%]"
}
}
}
},
"uv_index": {
"state_attributes": {
"level": {
"name": "Level",
"state": {
"good": "[%key:component::accuweather::entity::sensor::air_quality::state::good%]",
"hazardous": "[%key:component::accuweather::entity::sensor::air_quality::state::hazardous%]",
"high": "[%key:component::accuweather::entity::sensor::air_quality::state::high%]",
"low": "[%key:component::accuweather::entity::sensor::air_quality::state::low%]",
"moderate": "[%key:component::accuweather::entity::sensor::air_quality::state::moderate%]",
"unhealthy": "[%key:component::accuweather::entity::sensor::air_quality::state::unhealthy%]"
}
}
}
}
}
},

View File

@@ -0,0 +1,13 @@
{
"config": {
"error": {
"requests_exceeded": "\u062a\u0645 \u062a\u062c\u0627\u0648\u0632 \u0627\u0644\u0639\u062f\u062f \u0627\u0644\u0645\u0633\u0645\u0648\u062d \u0628\u0647 \u0645\u0646 \u0627\u0644\u0637\u0644\u0628\u0627\u062a \u0625\u0644\u0649 Accuweather API. \u0639\u0644\u064a\u0643 \u0627\u0644\u0627\u0646\u062a\u0638\u0627\u0631 \u0623\u0648 \u062a\u063a\u064a\u064a\u0631 \u0645\u0641\u062a\u0627\u062d API."
}
},
"system_health": {
"info": {
"can_reach_server": "\u0627\u0644\u0648\u0635\u0648\u0644 \u0625\u0644\u0649 \u062e\u0627\u062f\u0645 AccuWeather",
"remaining_requests": "\u0627\u0644\u0637\u0644\u0628\u0627\u062a \u0627\u0644\u0645\u062a\u0628\u0642\u064a\u0629 \u0627\u0644\u0645\u0633\u0645\u0648\u062d \u0628\u0647\u0627"
}
}
}

View File

@@ -0,0 +1,42 @@
{
"config": {
"abort": {
"single_instance_allowed": "\u0412\u0435\u0447\u0435 \u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u043e. \u0412\u044a\u0437\u043c\u043e\u0436\u043d\u0430 \u0435 \u0441\u0430\u043c\u043e \u0435\u0434\u043d\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f."
},
"error": {
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435",
"invalid_api_key": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d API \u043a\u043b\u044e\u0447"
},
"step": {
"user": {
"data": {
"api_key": "API \u043a\u043b\u044e\u0447",
"latitude": "\u0413\u0435\u043e\u0433\u0440\u0430\u0444\u0441\u043a\u0430 \u0448\u0438\u0440\u0438\u043d\u0430",
"longitude": "\u0413\u0435\u043e\u0433\u0440\u0430\u0444\u0441\u043a\u0430 \u0434\u044a\u043b\u0436\u0438\u043d\u0430",
"name": "\u0418\u043c\u0435"
}
}
}
},
"entity": {
"sensor": {
"pressure_tendency": {
"state": {
"falling": "\u041f\u043e\u043d\u0438\u0436\u0435\u043d\u0438\u0435",
"rising": "\u041f\u043e\u0432\u0438\u0448\u0435\u043d\u0438\u0435",
"steady": "\u0421\u0442\u0430\u0431\u0438\u043b\u043d\u043e"
}
}
}
},
"options": {
"step": {
"init": {
"data": {
"forecast": "\u041f\u0440\u043e\u0433\u043d\u043e\u0437\u0430 \u0437\u0430 \u0432\u0440\u0435\u043c\u0435\u0442\u043e"
},
"description": "\u041f\u043e\u0440\u0430\u0434\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f\u0442\u0430 \u043d\u0430 \u0431\u0435\u0437\u043f\u043b\u0430\u0442\u043d\u0430\u0442\u0430 \u0432\u0435\u0440\u0441\u0438\u044f \u043d\u0430 API \u043a\u043b\u044e\u0447\u0430 \u043d\u0430 AccuWeather, \u043a\u043e\u0433\u0430\u0442\u043e \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u0442\u0435 \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0430\u0442\u0430 \u0437\u0430 \u0432\u0440\u0435\u043c\u0435\u0442\u043e, \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438\u0442\u0435 \u043d\u0430 \u0434\u0430\u043d\u043d\u0438 \u0449\u0435 \u0441\u0435 \u0438\u0437\u0432\u044a\u0440\u0448\u0432\u0430\u0442 \u043d\u0430 \u0432\u0441\u0435\u043a\u0438 80 \u043c\u0438\u043d\u0443\u0442\u0438 \u0432\u043c\u0435\u0441\u0442\u043e \u043d\u0430 \u0432\u0441\u0435\u043a\u0438 40 \u043c\u0438\u043d\u0443\u0442\u0438."
}
}
}
}

View File

@@ -0,0 +1,52 @@
{
"config": {
"abort": {
"single_instance_allowed": "Ja configurat. Nom\u00e9s \u00e9s possible una sola configuraci\u00f3."
},
"create_entry": {
"default": "Alguns sensors no estan activats de manera predeterminada. Els pots activar des del registre d'entitats, despr\u00e9s de la configuraci\u00f3 de la integraci\u00f3.\nLa previsi\u00f3 meteorol\u00f2gica no est\u00e0 activada de manera predeterminada. Pots activar-la a les opcions de la integraci\u00f3."
},
"error": {
"cannot_connect": "Ha fallat la connexi\u00f3",
"invalid_api_key": "Clau API inv\u00e0lida",
"requests_exceeded": "S'ha superat el nombre m\u00e0xim de sol\u00b7licituds permeses a l'API d'AccuWeather. Has d'esperar-te o canviar la clau API."
},
"step": {
"user": {
"data": {
"api_key": "Clau API",
"latitude": "Latitud",
"longitude": "Longitud",
"name": "Nom"
}
}
}
},
"entity": {
"sensor": {
"pressure_tendency": {
"state": {
"falling": "Disminuint",
"rising": "Augmentant",
"steady": "Estable"
}
}
}
},
"options": {
"step": {
"init": {
"data": {
"forecast": "Previsi\u00f3 meteorol\u00f2gica"
},
"description": "Per culpa de les limitacions de la versi\u00f3 gratu\u00efta de l'API d'AccuWeather, quan activis la previsi\u00f3 meteorol\u00f2gica, les actualitzacions de dades es faran cada 80 minuts en comptes de cada 40."
}
}
},
"system_health": {
"info": {
"can_reach_server": "Servidor d'Accuweather accessible",
"remaining_requests": "Sol\u00b7licituds permeses restants"
}
}
}

View File

@@ -0,0 +1,47 @@
{
"config": {
"abort": {
"single_instance_allowed": "Ji\u017e nastaveno. Je mo\u017en\u00e1 pouze jedin\u00e1 konfigurace."
},
"error": {
"cannot_connect": "Nepoda\u0159ilo se p\u0159ipojit",
"invalid_api_key": "Neplatn\u00fd kl\u00ed\u010d API",
"requests_exceeded": "Byl p\u0159ekro\u010den povolen\u00fd po\u010det po\u017eadavk\u016f pro API Accuweather. Mus\u00edte po\u010dkat nebo zm\u011bnit API kl\u00ed\u010d."
},
"step": {
"user": {
"data": {
"api_key": "Kl\u00ed\u010d API",
"latitude": "Zem\u011bpisn\u00e1 \u0161\u00ed\u0159ka",
"longitude": "Zem\u011bpisn\u00e1 d\u00e9lka",
"name": "Jm\u00e9no"
}
}
}
},
"entity": {
"sensor": {
"pressure_tendency": {
"state": {
"steady": "Stabiln\u00ed"
}
}
}
},
"options": {
"step": {
"init": {
"data": {
"forecast": "P\u0159edpov\u011b\u010f po\u010das\u00ed"
},
"description": "Vzhledem k omezen\u00edm bezplatn\u00e9 verze kl\u00ed\u010de AccuWeather API, kdy\u017e povol\u00edte p\u0159edpov\u011b\u010f po\u010das\u00ed, aktualizace dat se budou prov\u00e1d\u011bt ka\u017ed\u00fdch 80 minut m\u00edsto ka\u017ed\u00fdch 40 minut."
}
}
},
"system_health": {
"info": {
"can_reach_server": "Lze kontaktovat AccuWeather server",
"remaining_requests": "Zb\u00fdvaj\u00edc\u00ed povolen\u00e9 \u017e\u00e1dosti"
}
}
}

View File

@@ -0,0 +1,52 @@
{
"config": {
"abort": {
"single_instance_allowed": "Bereits konfiguriert. Nur eine einzige Konfiguration m\u00f6glich."
},
"create_entry": {
"default": "Einige Sensoren sind standardm\u00e4\u00dfig nicht aktiviert. Du kannst sie nach der Integrationskonfiguration in der Entit\u00e4tsregistrierung aktivieren.\nDie Wettervorhersage ist nicht standardm\u00e4\u00dfig aktiviert. Du kannst sie in den Integrationsoptionen aktivieren."
},
"error": {
"cannot_connect": "Verbindung fehlgeschlagen",
"invalid_api_key": "Ung\u00fcltiger API-Schl\u00fcssel",
"requests_exceeded": "Die zul\u00e4ssige Anzahl von Anforderungen an die Accuweather-API wurde \u00fcberschritten. Du musst warten oder den API-Schl\u00fcssel \u00e4ndern."
},
"step": {
"user": {
"data": {
"api_key": "API-Schl\u00fcssel",
"latitude": "Breitengrad",
"longitude": "L\u00e4ngengrad",
"name": "Name"
}
}
}
},
"entity": {
"sensor": {
"pressure_tendency": {
"state": {
"falling": "Fallend",
"rising": "Steigend",
"steady": "Stetig"
}
}
}
},
"options": {
"step": {
"init": {
"data": {
"forecast": "Wettervorhersage"
},
"description": "Aufgrund der Einschr\u00e4nkungen der kostenlosen Version des AccuWeather API-Schl\u00fcssels werden bei aktivierter Wettervorhersage Datenaktualisierungen alle 80 Minuten statt alle 40 Minuten durchgef\u00fchrt."
}
}
},
"system_health": {
"info": {
"can_reach_server": "AccuWeather-Server erreichen",
"remaining_requests": "Verbleibende erlaubte Anfragen"
}
}
}

View File

@@ -0,0 +1,52 @@
{
"config": {
"abort": {
"single_instance_allowed": "\u0388\u03c7\u03b5\u03b9 \u03ae\u03b4\u03b7 \u03c1\u03c5\u03b8\u03bc\u03b9\u03c3\u03c4\u03b5\u03af. \u039c\u03cc\u03bd\u03bf \u03bc\u03af\u03b1 \u03b4\u03b9\u03b1\u03bc\u03cc\u03c1\u03c6\u03c9\u03c3\u03b7 \u03b5\u03af\u03bd\u03b1\u03b9 \u03b4\u03c5\u03bd\u03b1\u03c4\u03ae."
},
"create_entry": {
"default": "\u039f\u03c1\u03b9\u03c3\u03bc\u03ad\u03bd\u03bf\u03b9 \u03b1\u03b9\u03c3\u03b8\u03b7\u03c4\u03ae\u03c1\u03b5\u03c2 \u03b4\u03b5\u03bd \u03b5\u03af\u03bd\u03b1\u03b9 \u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03b7\u03bc\u03ad\u03bd\u03bf\u03b9 \u03b1\u03c0\u03cc \u03c0\u03c1\u03bf\u03b5\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae. \u039c\u03c0\u03bf\u03c1\u03b5\u03af\u03c4\u03b5 \u03bd\u03b1 \u03c4\u03b1 \u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03c4\u03b5 \u03c3\u03c4\u03bf \u03bc\u03b7\u03c4\u03c1\u03ce\u03bf \u03bf\u03bd\u03c4\u03bf\u03c4\u03ae\u03c4\u03c9\u03bd \u03bc\u03b5\u03c4\u03ac \u03c4\u03b7 \u03b4\u03b9\u03b1\u03bc\u03cc\u03c1\u03c6\u03c9\u03c3\u03b7 \u03c4\u03b7\u03c2 \u03b5\u03bd\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7\u03c2.\n \u0397 \u03c0\u03c1\u03cc\u03b3\u03bd\u03c9\u03c3\u03b7 \u03ba\u03b1\u03b9\u03c1\u03bf\u03cd \u03b4\u03b5\u03bd \u03b5\u03af\u03bd\u03b1\u03b9 \u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03b7\u03bc\u03ad\u03bd\u03b7 \u03b1\u03c0\u03cc \u03c0\u03c1\u03bf\u03b5\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae. \u039c\u03c0\u03bf\u03c1\u03b5\u03af\u03c4\u03b5 \u03bd\u03b1 \u03c4\u03bf \u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03c4\u03b5 \u03c3\u03c4\u03b9\u03c2 \u03b5\u03c0\u03b9\u03bb\u03bf\u03b3\u03ad\u03c2 \u03b5\u03bd\u03c3\u03c9\u03bc\u03ac\u03c4\u03c9\u03c3\u03b7\u03c2."
},
"error": {
"cannot_connect": "\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7\u03c2",
"invalid_api_key": "\u039c\u03b7 \u03ad\u03b3\u03ba\u03c5\u03c1\u03bf \u03ba\u03bb\u03b5\u03b9\u03b4\u03af API",
"requests_exceeded": "\u0388\u03c7\u03b5\u03b9 \u03be\u03b5\u03c0\u03b5\u03c1\u03b1\u03c3\u03c4\u03b5\u03af \u03bf \u03b5\u03c0\u03b9\u03c4\u03c1\u03b5\u03c0\u03cc\u03bc\u03b5\u03bd\u03bf\u03c2 \u03b1\u03c1\u03b9\u03b8\u03bc\u03cc\u03c2 \u03b1\u03b9\u03c4\u03ae\u03c3\u03b5\u03c9\u03bd \u03c0\u03c1\u03bf\u03c2 \u03c4\u03bf API \u03c4\u03bf\u03c5 Accuweather. \u03a0\u03c1\u03ad\u03c0\u03b5\u03b9 \u03bd\u03b1 \u03c0\u03b5\u03c1\u03b9\u03bc\u03ad\u03bd\u03b5\u03c4\u03b5 \u03ae \u03bd\u03b1 \u03b1\u03bb\u03bb\u03ac\u03be\u03b5\u03c4\u03b5 \u03c4\u03bf \u03ba\u03bb\u03b5\u03b9\u03b4\u03af API."
},
"step": {
"user": {
"data": {
"api_key": "\u039a\u03bb\u03b5\u03b9\u03b4\u03af API",
"latitude": "\u0393\u03b5\u03c9\u03b3\u03c1\u03b1\u03c6\u03b9\u03ba\u03cc \u03c0\u03bb\u03ac\u03c4\u03bf\u03c2",
"longitude": "\u0393\u03b5\u03c9\u03b3\u03c1\u03b1\u03c6\u03b9\u03ba\u03cc \u03bc\u03ae\u03ba\u03bf\u03c2",
"name": "\u038c\u03bd\u03bf\u03bc\u03b1"
}
}
}
},
"entity": {
"sensor": {
"pressure_tendency": {
"state": {
"falling": "\u03a0\u03c4\u03ce\u03c3\u03b7",
"rising": "\u0391\u03c5\u03be\u03b1\u03bd\u03cc\u03bc\u03b5\u03bd\u03b7",
"steady": "\u03a3\u03c4\u03b1\u03b8\u03b5\u03c1\u03ae"
}
}
}
},
"options": {
"step": {
"init": {
"data": {
"forecast": "\u03a0\u03c1\u03cc\u03b3\u03bd\u03c9\u03c3\u03b7 \u03ba\u03b1\u03b9\u03c1\u03bf\u03cd"
},
"description": "\u039b\u03cc\u03b3\u03c9 \u03c4\u03c9\u03bd \u03c0\u03b5\u03c1\u03b9\u03bf\u03c1\u03b9\u03c3\u03bc\u03ce\u03bd \u03c4\u03b7\u03c2 \u03b4\u03c9\u03c1\u03b5\u03ac\u03bd \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7\u03c2 \u03c4\u03bf\u03c5 \u03ba\u03bb\u03b5\u03b9\u03b4\u03b9\u03bf\u03cd AccuWeather API, \u03cc\u03c4\u03b1\u03bd \u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03b5\u03af\u03c4\u03b5 \u03c4\u03b7\u03bd \u03c0\u03c1\u03cc\u03b3\u03bd\u03c9\u03c3\u03b7 \u03ba\u03b1\u03b9\u03c1\u03bf\u03cd, \u03bf\u03b9 \u03b5\u03bd\u03b7\u03bc\u03b5\u03c1\u03ce\u03c3\u03b5\u03b9\u03c2 \u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03c9\u03bd \u03b8\u03b1 \u03b5\u03ba\u03c4\u03b5\u03bb\u03bf\u03cd\u03bd\u03c4\u03b1\u03b9 \u03ba\u03ac\u03b8\u03b5 80 \u03bb\u03b5\u03c0\u03c4\u03ac \u03b1\u03bd\u03c4\u03af \u03b3\u03b9\u03b1 \u03ba\u03ac\u03b8\u03b5 40 \u03bb\u03b5\u03c0\u03c4\u03ac."
}
}
},
"system_health": {
"info": {
"can_reach_server": "\u03a0\u03c1\u03bf\u03c3\u03b5\u03b3\u03b3\u03af\u03c3\u03c4\u03b5 \u03c4\u03bf\u03bd \u03b4\u03b9\u03b1\u03ba\u03bf\u03bc\u03b9\u03c3\u03c4\u03ae AccuWeather",
"remaining_requests": "\u03a5\u03c0\u03bf\u03bb\u03b5\u03b9\u03c0\u03cc\u03bc\u03b5\u03bd\u03b1 \u03b5\u03c0\u03b9\u03c4\u03c1\u03b5\u03c0\u03cc\u03bc\u03b5\u03bd\u03b1 \u03b1\u03b9\u03c4\u03ae\u03bc\u03b1\u03c4\u03b1"
}
}
}

View File

@@ -0,0 +1,52 @@
{
"config": {
"abort": {
"single_instance_allowed": "Already configured. Only a single configuration possible."
},
"create_entry": {
"default": "Some sensors are not enabled by default. You can enable them in the entity registry after the integration configuration.\nWeather forecast is not enabled by default. You can enable it in the integration options."
},
"error": {
"cannot_connect": "Failed to connect",
"invalid_api_key": "Invalid API key",
"requests_exceeded": "The allowed number of requests to Accuweather API has been exceeded. You have to wait or change API Key."
},
"step": {
"user": {
"data": {
"api_key": "API Key",
"latitude": "Latitude",
"longitude": "Longitude",
"name": "Name"
}
}
}
},
"entity": {
"sensor": {
"pressure_tendency": {
"state": {
"falling": "Falling",
"rising": "Rising",
"steady": "Steady"
}
}
}
},
"options": {
"step": {
"init": {
"data": {
"forecast": "Weather forecast"
},
"description": "Due to the limitations of the free version of the AccuWeather API key, when you enable weather forecast, data updates will be performed every 80 minutes instead of every 40 minutes."
}
}
},
"system_health": {
"info": {
"can_reach_server": "Reach AccuWeather server",
"remaining_requests": "Remaining allowed requests"
}
}
}

View File

@@ -0,0 +1,21 @@
{
"config": {
"abort": {
"single_instance_allowed": "Ya configurado. Solo es posible una \u00fanica configuraci\u00f3n."
},
"create_entry": {
"default": "Algunos sensores no est\u00e1n habilitados de forma predeterminada. Puede habilitarlos en el registro de la entidad despu\u00e9s de la configuraci\u00f3n de la integraci\u00f3n. \nEl pron\u00f3stico del tiempo no est\u00e1 habilitado de forma predeterminada. Puedes habilitarlo en las opciones de integraci\u00f3n."
},
"error": {
"cannot_connect": "No se pudo conectar",
"invalid_api_key": "Clave de API no v\u00e1lida",
"requests_exceeded": "Se super\u00f3 el n\u00famero permitido de solicitudes a la API de Accuweather. Tiene que esperar o cambiar la clave de API."
}
},
"system_health": {
"info": {
"can_reach_server": "Llegar al servidor de AccuWeather",
"remaining_requests": "Solicitudes permitidas restantes"
}
}
}

View File

@@ -0,0 +1,52 @@
{
"config": {
"abort": {
"single_instance_allowed": "Ya est\u00e1 configurado. Solo es posible una \u00fanica configuraci\u00f3n."
},
"create_entry": {
"default": "Algunos sensores no est\u00e1n habilitados de forma predeterminada. Puedes habilitarlos en el registro de la entidad despu\u00e9s de la configuraci\u00f3n de la integraci\u00f3n.\nLa previsi\u00f3n meteorol\u00f3gica no est\u00e1 habilitada de forma predeterminada. Puedes habilitarla en las opciones de integraci\u00f3n."
},
"error": {
"cannot_connect": "No se pudo conectar",
"invalid_api_key": "Clave API no v\u00e1lida",
"requests_exceeded": "Se ha excedido el n\u00famero permitido de solicitudes a la API de Accuweather. Tienes que esperar o cambiar la Clave API."
},
"step": {
"user": {
"data": {
"api_key": "Clave API",
"latitude": "Latitud",
"longitude": "Longitud",
"name": "Nombre"
}
}
}
},
"entity": {
"sensor": {
"pressure_tendency": {
"state": {
"falling": "Descendente",
"rising": "Creciente",
"steady": "Estable"
}
}
}
},
"options": {
"step": {
"init": {
"data": {
"forecast": "Previsi\u00f3n meteorol\u00f3gica"
},
"description": "Debido a las limitaciones de la versi\u00f3n gratuita de la clave API de AccuWeather, cuando habilitas la previsi\u00f3n meteorol\u00f3gica, las actualizaciones de datos se realizar\u00e1n cada 80 minutos en lugar de cada 40 minutos."
}
}
},
"system_health": {
"info": {
"can_reach_server": "Se puede llegar al servidor AccuWeather",
"remaining_requests": "Solicitudes permitidas restantes"
}
}
}

View File

@@ -0,0 +1,52 @@
{
"config": {
"abort": {
"single_instance_allowed": "Sidumine juba tehtud. V\u00f5imalik on ainult 1 sidumine."
},
"create_entry": {
"default": "M\u00f5ned andurid ei ole vaikimisi lubatud. Saad neid lubada \u00fcksuse registris p\u00e4rast sidumise seadistamist.\nIlmaprognoos ei ole vaikimisi lubatud. Saad selle lubada sidumise valikutes."
},
"error": {
"cannot_connect": "\u00dchendamine nurjus",
"invalid_api_key": "API v\u00f5ti on vale",
"requests_exceeded": "Accuweatheri API-le esitatud p\u00e4ringute piirarv on \u00fcletatud. Peate ootama (v\u00f5i muutma API v\u00f5tit)."
},
"step": {
"user": {
"data": {
"api_key": "API v\u00f5ti",
"latitude": "Laiuskraad",
"longitude": "Pikkuskraad",
"name": "Sidumise nimi"
}
}
}
},
"entity": {
"sensor": {
"pressure_tendency": {
"state": {
"falling": "Langev",
"rising": "T\u00f5usev",
"steady": "\u00dchtlane"
}
}
}
},
"options": {
"step": {
"init": {
"data": {
"forecast": "Ilmateade"
},
"description": "AccuWeather API tasuta versioonis toimub ilmaennustuse lubamisel andmete v\u00e4rskendamine iga 80 minuti j\u00e4rel (muidu 40 minutit)."
}
}
},
"system_health": {
"info": {
"can_reach_server": "\u00dchendus Accuweatheri serveriga",
"remaining_requests": "Lubatud taotlusi on j\u00e4\u00e4nud"
}
}
}

View File

@@ -0,0 +1,40 @@
{
"config": {
"abort": {
"single_instance_allowed": "D\u00e9j\u00e0 configur\u00e9. Une seule configuration possible."
},
"create_entry": {
"default": "Certains capteurs ne sont pas activ\u00e9s par d\u00e9faut. Vous pouvez les activer dans le registre des entit\u00e9s une fois la configuration de l'int\u00e9gration termin\u00e9e.\nLes pr\u00e9visions m\u00e9t\u00e9orologiques ne sont pas activ\u00e9es par d\u00e9faut. Vous pouvez les activer dans les options de l'int\u00e9gration."
},
"error": {
"cannot_connect": "\u00c9chec de connexion",
"invalid_api_key": "Cl\u00e9 d'API non valide",
"requests_exceeded": "Le nombre autoris\u00e9 de requ\u00eates adress\u00e9es \u00e0 l'API AccuWeather a \u00e9t\u00e9 d\u00e9pass\u00e9. Vous devez attendre ou modifier la cl\u00e9 API."
},
"step": {
"user": {
"data": {
"api_key": "Cl\u00e9 d'API",
"latitude": "Latitude",
"longitude": "Longitude",
"name": "Nom"
}
}
}
},
"options": {
"step": {
"init": {
"data": {
"forecast": "Pr\u00e9visions m\u00e9t\u00e9orologiques"
}
}
}
},
"system_health": {
"info": {
"can_reach_server": "Acc\u00e8s au serveur AccuWeather",
"remaining_requests": "Demandes restantes autoris\u00e9es"
}
}
}

View File

@@ -0,0 +1,52 @@
{
"config": {
"abort": {
"single_instance_allowed": "\u05ea\u05e6\u05d5\u05e8\u05ea\u05d5 \u05db\u05d1\u05e8 \u05e0\u05e7\u05d1\u05e2\u05d4. \u05e8\u05e7 \u05ea\u05e6\u05d5\u05e8\u05d4 \u05d0\u05d7\u05ea \u05d0\u05e4\u05e9\u05e8\u05d9\u05ea."
},
"create_entry": {
"default": "\u05d7\u05d9\u05d9\u05e9\u05e0\u05d9\u05dd \u05de\u05e1\u05d5\u05d9\u05de\u05d9\u05dd \u05d0\u05d9\u05e0\u05dd \u05de\u05d5\u05e4\u05e2\u05dc\u05d9\u05dd \u05db\u05d1\u05e8\u05d9\u05e8\u05ea \u05de\u05d7\u05d3\u05dc. \u05d1\u05d9\u05db\u05d5\u05dc\u05ea\u05da \u05dc\u05d4\u05e4\u05e2\u05d9\u05dc \u05d0\u05d5\u05ea\u05dd \u05d1\u05e8\u05d9\u05e9\u05d5\u05dd \u05d4\u05d9\u05e9\u05d5\u05d9\u05d5\u05ea \u05dc\u05d0\u05d7\u05e8 \u05ea\u05e6\u05d5\u05e8\u05ea \u05d4\u05e9\u05d9\u05dc\u05d5\u05d1.\n \u05ea\u05d7\u05d6\u05d9\u05ea \u05de\u05d6\u05d2 \u05d4\u05d0\u05d5\u05d5\u05d9\u05e8 \u05d0\u05d9\u05e0\u05d4 \u05de\u05d5\u05e4\u05e2\u05dc\u05ea \u05db\u05d1\u05e8\u05d9\u05e8\u05ea \u05de\u05d7\u05d3\u05dc. \u05d1\u05d9\u05db\u05d5\u05dc\u05ea\u05da \u05dc\u05d4\u05e4\u05e2\u05d9\u05dc \u05d0\u05ea \u05d6\u05d4 \u05d1\u05d0\u05e4\u05e9\u05e8\u05d5\u05d9\u05d5\u05ea \u05d4\u05e9\u05d9\u05dc\u05d5\u05d1."
},
"error": {
"cannot_connect": "\u05d4\u05d4\u05ea\u05d7\u05d1\u05e8\u05d5\u05ea \u05e0\u05db\u05e9\u05dc\u05d4",
"invalid_api_key": "\u05de\u05e4\u05ea\u05d7 API \u05dc\u05d0 \u05d7\u05d5\u05e7\u05d9",
"requests_exceeded": "\u05d0\u05d9\u05e8\u05e2\u05d4 \u05d7\u05e8\u05d9\u05d2\u05d4 \u05de\u05de\u05e1\u05e4\u05e8 \u05d4\u05d1\u05e7\u05e9\u05d5\u05ea \u05d4\u05de\u05d5\u05ea\u05e8 \u05dc-API \u05e9\u05dc Accuweather. \u05e2\u05dc\u05d9\u05da \u05dc\u05d4\u05de\u05ea\u05d9\u05df \u05d0\u05d5 \u05dc\u05e9\u05e0\u05d5\u05ea \u05d0\u05ea \u05de\u05e4\u05ea\u05d7 \u05d4-API."
},
"step": {
"user": {
"data": {
"api_key": "\u05de\u05e4\u05ea\u05d7 API",
"latitude": "\u05e7\u05d5 \u05e8\u05d5\u05d7\u05d1",
"longitude": "\u05e7\u05d5 \u05d0\u05d5\u05e8\u05da",
"name": "\u05e9\u05dd"
}
}
}
},
"entity": {
"sensor": {
"pressure_tendency": {
"state": {
"falling": "\u05e9\u05d5\u05e7\u05e2\u05ea",
"rising": "\u05d6\u05d5\u05e8\u05d7\u05ea",
"steady": "\u05d9\u05e6\u05d9\u05d1"
}
}
}
},
"options": {
"step": {
"init": {
"data": {
"forecast": "\u05ea\u05d7\u05d6\u05d9\u05ea \u05de\u05d6\u05d2 \u05d4\u05d0\u05d5\u05d5\u05d9\u05e8"
},
"description": "\u05d1\u05e9\u05dc \u05de\u05d2\u05d1\u05dc\u05d5\u05ea \u05d4\u05d2\u05d9\u05e8\u05e1\u05d4 \u05d4\u05d7\u05d9\u05e0\u05de\u05d9\u05ea \u05e9\u05dc \u05de\u05e4\u05ea\u05d7 \u05d4-API \u05e9\u05dc AccuWeather, \u05db\u05d0\u05e9\u05e8 \u05ea\u05e4\u05e2\u05d9\u05dc \u05ea\u05d7\u05d6\u05d9\u05ea \u05de\u05d6\u05d2 \u05d0\u05d5\u05d5\u05d9\u05e8, \u05e2\u05d3\u05db\u05d5\u05e0\u05d9 \u05e0\u05ea\u05d5\u05e0\u05d9\u05dd \u05d9\u05d1\u05d5\u05e6\u05e2\u05d5 \u05db\u05dc 80 \u05d3\u05e7\u05d5\u05ea \u05d1\u05de\u05e7\u05d5\u05dd \u05db\u05dc 40 \u05d3\u05e7\u05d5\u05ea."
}
}
},
"system_health": {
"info": {
"can_reach_server": "\u05d4\u05e9\u05d2\u05ea \u05e9\u05e8\u05ea AccuWeather",
"remaining_requests": "\u05d4\u05d1\u05e7\u05e9\u05d5\u05ea \u05d4\u05e0\u05d5\u05ea\u05e8\u05d5\u05ea \u05de\u05d5\u05ea\u05e8\u05d5\u05ea"
}
}
}

View File

@@ -0,0 +1,52 @@
{
"config": {
"abort": {
"single_instance_allowed": "M\u00e1r konfigur\u00e1lva van. Csak egy konfigur\u00e1ci\u00f3 lehets\u00e9ges."
},
"create_entry": {
"default": "Egyes \u00e9rz\u00e9kel\u0151k alap\u00e9rtelmez\u00e9s szerint nincsenek enged\u00e9lyezve. Az integr\u00e1ci\u00f3s konfigur\u00e1ci\u00f3 ut\u00e1n enged\u00e9lyezheti \u0151ket az entit\u00e1s rendszerle\u00edr\u00f3 adatb\u00e1zis\u00e1ban.\nAz id\u0151j\u00e1r\u00e1s-el\u0151rejelz\u00e9s alap\u00e9rtelmez\u00e9s szerint nincs enged\u00e9lyezve. Ezt az integr\u00e1ci\u00f3s be\u00e1ll\u00edt\u00e1sokban enged\u00e9lyezheti."
},
"error": {
"cannot_connect": "Sikertelen csatlakoz\u00e1s",
"invalid_api_key": "\u00c9rv\u00e9nytelen API kulcs",
"requests_exceeded": "Accuweather API-hoz enged\u00e9lyezett lek\u00e9r\u00e9sek sz\u00e1ma t\u00fal lett l\u00e9pve. Meg kell v\u00e1rnia m\u00edg a tilt\u00e1s lej\u00e1r vagy m\u00f3dos\u00edtania kell az API-kulcsot."
},
"step": {
"user": {
"data": {
"api_key": "API kulcs",
"latitude": "Sz\u00e9less\u00e9g",
"longitude": "Hossz\u00fas\u00e1g",
"name": "Elnevez\u00e9s"
}
}
}
},
"entity": {
"sensor": {
"pressure_tendency": {
"state": {
"falling": "Cs\u00f6kken\u0151",
"rising": "Emelked\u0151",
"steady": "\u00c1lland\u00f3"
}
}
}
},
"options": {
"step": {
"init": {
"data": {
"forecast": "Id\u0151j\u00e1r\u00e1s el\u0151rejelz\u00e9s"
},
"description": "Az AccuWeather API-kulcs ingyenes verzi\u00f3j\u00e1nak korl\u00e1tai miatt az id\u0151j\u00e1r\u00e1s-el\u0151rejelz\u00e9s enged\u00e9lyez\u00e9sekor az adatok friss\u00edt\u00e9se 40 perc helyett 80 percenk\u00e9nt t\u00f6rt\u00e9nik."
}
}
},
"system_health": {
"info": {
"can_reach_server": "\u00c9rje el az AccuWeather szervert",
"remaining_requests": "Fennmarad\u00f3 enged\u00e9lyezett k\u00e9r\u00e9sek"
}
}
}

View File

@@ -0,0 +1,52 @@
{
"config": {
"abort": {
"single_instance_allowed": "Sudah dikonfigurasi. Hanya satu konfigurasi yang diizinkan."
},
"create_entry": {
"default": "Beberapa sensor tidak diaktifkan secara default. Anda dapat mengaktifkannya di registri entitas setelah konfigurasi integrasi.\nPrakiraan cuaca tidak diaktifkan secara default. Anda dapat mengaktifkannya di opsi integrasi."
},
"error": {
"cannot_connect": "Gagal terhubung",
"invalid_api_key": "Kunci API tidak valid",
"requests_exceeded": "Jumlah permintaan yang diizinkan ke API Accuweather telah terlampaui. Anda harus menunggu atau mengubah Kunci API."
},
"step": {
"user": {
"data": {
"api_key": "Kunci API",
"latitude": "Lintang",
"longitude": "Bujur",
"name": "Nama"
}
}
}
},
"entity": {
"sensor": {
"pressure_tendency": {
"state": {
"falling": "Turun",
"rising": "Naik",
"steady": "Tetap"
}
}
}
},
"options": {
"step": {
"init": {
"data": {
"forecast": "Prakiraan cuaca"
},
"description": "Karena keterbatasan versi gratis kunci API AccuWeather, ketika Anda mengaktifkan prakiraan cuaca, pembaruan data akan dilakukan setiap 80 menit, bukan setiap 40 menit."
}
}
},
"system_health": {
"info": {
"can_reach_server": "Keterjangkauan server AccuWeather",
"remaining_requests": "Sisa permintaan yang diizinkan"
}
}
}

View File

@@ -0,0 +1,52 @@
{
"config": {
"abort": {
"single_instance_allowed": "Gi\u00e0 configurato. \u00c8 possibile una sola configurazione."
},
"create_entry": {
"default": "Alcuni sensori non sono abilitati per impostazione predefinita. Puoi abilitarli nel registro delle entit\u00e0 dopo la configurazione dell'integrazione.\nLe previsioni del tempo non sono abilitate per impostazione predefinita. Puoi abilitarlo nelle opzioni di integrazione."
},
"error": {
"cannot_connect": "Impossibile connettersi",
"invalid_api_key": "Chiave API non valida",
"requests_exceeded": "\u00c8 stato superato il numero consentito di richieste all'API di Accuweather. \u00c8 necessario attendere o modificare la chiave API."
},
"step": {
"user": {
"data": {
"api_key": "Chiave API",
"latitude": "Latitudine",
"longitude": "Logitudine",
"name": "Nome"
}
}
}
},
"entity": {
"sensor": {
"pressure_tendency": {
"state": {
"falling": "In diminuzione",
"rising": "In aumento",
"steady": "Stabile"
}
}
}
},
"options": {
"step": {
"init": {
"data": {
"forecast": "Previsioni del tempo"
},
"description": "A causa delle limitazioni della versione gratuita della chiave API AccuWeather, quando abiliti le previsioni del tempo, gli aggiornamenti dei dati verranno eseguiti ogni 80 minuti anzich\u00e9 ogni 40 minuti."
}
}
},
"system_health": {
"info": {
"can_reach_server": "Raggiungi il server AccuWeather",
"remaining_requests": "Richieste consentite rimanenti"
}
}
}

View File

@@ -0,0 +1,31 @@
{
"config": {
"abort": {
"single_instance_allowed": "\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u8a2d\u5b9a\u3067\u304d\u308b\u306e\u306f1\u3064\u3060\u3051\u3067\u3059\u3002"
},
"create_entry": {
"default": "\u4e00\u90e8\u306e\u30bb\u30f3\u30b5\u30fc\u306f\u3001\u30c7\u30d5\u30a9\u30eb\u30c8\u3067\u306f\u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u305b\u3093\u3002\u7d71\u5408\u306e\u69cb\u6210\u5f8c\u3001\u30a8\u30f3\u30c6\u30a3\u30c6\u30a3\u30ec\u30b8\u30b9\u30c8\u30ea\u3067\u305d\u308c\u3089\u3092\u6709\u52b9\u306b\u3067\u304d\u307e\u3059\u3002\n\u5929\u6c17\u4e88\u5831\u306f\u30c7\u30d5\u30a9\u30eb\u30c8\u3067\u306f\u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u305b\u3093\u3002\u7d71\u5408\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3067\u6709\u52b9\u306b\u3067\u304d\u307e\u3059\u3002"
},
"error": {
"cannot_connect": "\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f",
"invalid_api_key": "\u7121\u52b9\u306aAPI\u30ad\u30fc",
"requests_exceeded": "Accuweather API\u3078\u306e\u30ea\u30af\u30a8\u30b9\u30c8\u6570\u304c\u8a31\u53ef\u3055\u308c\u305f\u6570\u3092\u8d85\u3048\u307e\u3057\u305f\u3002\u6642\u9593\u3092\u7f6e\u304f\u304b\u3001API\u30ad\u30fc\u3092\u5909\u66f4\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002"
},
"step": {
"user": {
"data": {
"api_key": "API\u30ad\u30fc",
"latitude": "\u7def\u5ea6",
"longitude": "\u7d4c\u5ea6",
"name": "\u540d\u524d"
}
}
}
},
"system_health": {
"info": {
"can_reach_server": "AccuWeather\u30b5\u30fc\u30d0\u30fc\u3078\u306e\u30a2\u30af\u30bb\u30b9",
"remaining_requests": "\u6b8b\u308a\u306e\u8a31\u53ef\u3055\u308c\u305f\u30ea\u30af\u30a8\u30b9\u30c8"
}
}
}

View File

@@ -0,0 +1,49 @@
{
"config": {
"abort": {
"single_instance_allowed": "\uc774\ubbf8 \uad6c\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \ud558\ub098\uc758 \uc778\uc2a4\ud134\uc2a4\ub9cc \uad6c\uc131\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4."
},
"error": {
"cannot_connect": "\uc5f0\uacb0\ud558\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4",
"invalid_api_key": "API \ud0a4\uac00 \uc798\ubabb\ub418\uc5c8\uc2b5\ub2c8\ub2e4",
"requests_exceeded": "Accuweather API\uc5d0 \ud5c8\uc6a9\ub41c \uc694\uccad \uc218\uac00 \ucd08\uacfc\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \uae30\ub2e4\ub9ac\uac70\ub098 API \ud0a4\ub97c \ubcc0\uacbd\ud574\uc57c \ud569\ub2c8\ub2e4."
},
"step": {
"user": {
"data": {
"api_key": "API \ud0a4",
"latitude": "\uc704\ub3c4",
"longitude": "\uacbd\ub3c4",
"name": "\uc774\ub984"
}
}
}
},
"entity": {
"sensor": {
"pressure_tendency": {
"state": {
"falling": "\ud558\uac15",
"rising": "\uc0c1\uc2b9",
"steady": "\uc548\uc815\ub428"
}
}
}
},
"options": {
"step": {
"init": {
"data": {
"forecast": "\ub0a0\uc528 \uc608\ubcf4"
},
"description": "\ubb34\ub8cc \ubc84\uc804 AccuWeather API \ud0a4\uc758 \uc81c\ud55c\uc73c\ub85c \uc778\ud574 \ub0a0\uc528 \uc608\ubcf4\ub97c \ud65c\uc131\ud654\ud558\uba74 \ub370\uc774\ud130 \uc5c5\ub370\uc774\ud2b8\uac00 40\ubd84\uc774 \uc544\ub2cc 80\ubd84\ub9c8\ub2e4 \uc218\ud589\ub429\ub2c8\ub2e4."
}
}
},
"system_health": {
"info": {
"can_reach_server": "AccuWeather \uc11c\ubc84 \uc5f0\uacb0",
"remaining_requests": "\ub0a8\uc740 \ud5c8\uc6a9 \uc694\uccad \ud69f\uc218"
}
}
}

Some files were not shown because too many files have changed in this diff Show More