Merge pull request #40179 from home-assistant/rc

This commit is contained in:
Paulus Schoutsen 2020-09-17 17:37:29 +02:00 committed by GitHub
commit 58c6702080
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2974 changed files with 77842 additions and 20333 deletions

View File

@ -8,10 +8,6 @@ omit =
homeassistant/scripts/*.py homeassistant/scripts/*.py
# omit pieces of code that rely on external devices being present # omit pieces of code that rely on external devices being present
homeassistant/components/accuweather/__init__.py
homeassistant/components/accuweather/const.py
homeassistant/components/accuweather/sensor.py
homeassistant/components/accuweather/weather.py
homeassistant/components/acer_projector/switch.py homeassistant/components/acer_projector/switch.py
homeassistant/components/actiontec/device_tracker.py homeassistant/components/actiontec/device_tracker.py
homeassistant/components/acmeda/__init__.py homeassistant/components/acmeda/__init__.py
@ -29,6 +25,7 @@ omit =
homeassistant/components/ads/* homeassistant/components/ads/*
homeassistant/components/aftership/sensor.py homeassistant/components/aftership/sensor.py
homeassistant/components/agent_dvr/__init__.py homeassistant/components/agent_dvr/__init__.py
homeassistant/components/agent_dvr/alarm_control_panel.py
homeassistant/components/agent_dvr/camera.py homeassistant/components/agent_dvr/camera.py
homeassistant/components/agent_dvr/const.py homeassistant/components/agent_dvr/const.py
homeassistant/components/agent_dvr/helpers.py homeassistant/components/agent_dvr/helpers.py
@ -103,11 +100,11 @@ omit =
homeassistant/components/braviatv/__init__.py homeassistant/components/braviatv/__init__.py
homeassistant/components/braviatv/const.py homeassistant/components/braviatv/const.py
homeassistant/components/braviatv/media_player.py homeassistant/components/braviatv/media_player.py
homeassistant/components/broadlink/__init__.py
homeassistant/components/broadlink/const.py homeassistant/components/broadlink/const.py
homeassistant/components/broadlink/device.py
homeassistant/components/broadlink/remote.py homeassistant/components/broadlink/remote.py
homeassistant/components/broadlink/sensor.py
homeassistant/components/broadlink/switch.py homeassistant/components/broadlink/switch.py
homeassistant/components/broadlink/updater.py
homeassistant/components/brottsplatskartan/sensor.py homeassistant/components/brottsplatskartan/sensor.py
homeassistant/components/browser/* homeassistant/components/browser/*
homeassistant/components/brunt/cover.py homeassistant/components/brunt/cover.py
@ -169,7 +166,9 @@ omit =
homeassistant/components/deutsche_bahn/sensor.py homeassistant/components/deutsche_bahn/sensor.py
homeassistant/components/devolo_home_control/__init__.py homeassistant/components/devolo_home_control/__init__.py
homeassistant/components/devolo_home_control/binary_sensor.py homeassistant/components/devolo_home_control/binary_sensor.py
homeassistant/components/devolo_home_control/climate.py
homeassistant/components/devolo_home_control/const.py homeassistant/components/devolo_home_control/const.py
homeassistant/components/devolo_home_control/cover.py
homeassistant/components/devolo_home_control/devolo_device.py homeassistant/components/devolo_home_control/devolo_device.py
homeassistant/components/devolo_home_control/devolo_multi_level_switch.py homeassistant/components/devolo_home_control/devolo_multi_level_switch.py
homeassistant/components/devolo_home_control/light.py homeassistant/components/devolo_home_control/light.py
@ -221,7 +220,6 @@ omit =
homeassistant/components/emby/media_player.py homeassistant/components/emby/media_player.py
homeassistant/components/emoncms/sensor.py homeassistant/components/emoncms/sensor.py
homeassistant/components/emoncms_history/* homeassistant/components/emoncms_history/*
homeassistant/components/emulated_hue/upnp.py
homeassistant/components/enigma2/media_player.py homeassistant/components/enigma2/media_player.py
homeassistant/components/enocean/__init__.py homeassistant/components/enocean/__init__.py
homeassistant/components/enocean/binary_sensor.py homeassistant/components/enocean/binary_sensor.py
@ -309,8 +307,6 @@ omit =
homeassistant/components/gc100/* homeassistant/components/gc100/*
homeassistant/components/geniushub/* homeassistant/components/geniushub/*
homeassistant/components/geizhals/sensor.py homeassistant/components/geizhals/sensor.py
homeassistant/components/gios/__init__.py
homeassistant/components/gios/air_quality.py
homeassistant/components/github/sensor.py homeassistant/components/github/sensor.py
homeassistant/components/gitlab_ci/sensor.py homeassistant/components/gitlab_ci/sensor.py
homeassistant/components/gitter/sensor.py homeassistant/components/gitter/sensor.py
@ -397,7 +393,17 @@ omit =
homeassistant/components/ihc/* homeassistant/components/ihc/*
homeassistant/components/imap/sensor.py homeassistant/components/imap/sensor.py
homeassistant/components/imap_email_content/sensor.py homeassistant/components/imap_email_content/sensor.py
homeassistant/components/insteon/* homeassistant/components/insteon/binary_sensor.py
homeassistant/components/insteon/climate.py
homeassistant/components/insteon/const.py
homeassistant/components/insteon/cover.py
homeassistant/components/insteon/fan.py
homeassistant/components/insteon/insteon_entity.py
homeassistant/components/insteon/ipdb.py
homeassistant/components/insteon/light.py
homeassistant/components/insteon/schemas.py
homeassistant/components/insteon/switch.py
homeassistant/components/insteon/utils.py
homeassistant/components/incomfort/* homeassistant/components/incomfort/*
homeassistant/components/intesishome/* homeassistant/components/intesishome/*
homeassistant/components/ios/* homeassistant/components/ios/*
@ -440,6 +446,7 @@ omit =
homeassistant/components/knx/climate.py homeassistant/components/knx/climate.py
homeassistant/components/knx/cover.py homeassistant/components/knx/cover.py
homeassistant/components/kodi/__init__.py homeassistant/components/kodi/__init__.py
homeassistant/components/kodi/browse_media.py
homeassistant/components/kodi/const.py homeassistant/components/kodi/const.py
homeassistant/components/kodi/media_player.py homeassistant/components/kodi/media_player.py
homeassistant/components/kodi/notify.py homeassistant/components/kodi/notify.py
@ -581,8 +588,7 @@ omit =
homeassistant/components/nuki/lock.py homeassistant/components/nuki/lock.py
homeassistant/components/nut/sensor.py homeassistant/components/nut/sensor.py
homeassistant/components/nx584/alarm_control_panel.py homeassistant/components/nx584/alarm_control_panel.py
homeassistant/components/nzbget/__init__.py homeassistant/components/nzbget/coordinator.py
homeassistant/components/nzbget/sensor.py
homeassistant/components/obihai/* homeassistant/components/obihai/*
homeassistant/components/octoprint/* homeassistant/components/octoprint/*
homeassistant/components/oem/climate.py homeassistant/components/oem/climate.py
@ -617,6 +623,9 @@ omit =
homeassistant/components/openuv/sensor.py homeassistant/components/openuv/sensor.py
homeassistant/components/openweathermap/sensor.py homeassistant/components/openweathermap/sensor.py
homeassistant/components/openweathermap/weather.py homeassistant/components/openweathermap/weather.py
homeassistant/components/openweathermap/forecast_update_coordinator.py
homeassistant/components/openweathermap/weather_update_coordinator.py
homeassistant/components/openweathermap/abstract_owm_sensor.py
homeassistant/components/opnsense/* homeassistant/components/opnsense/*
homeassistant/components/opple/light.py homeassistant/components/opple/light.py
homeassistant/components/orangepi_gpio/* homeassistant/components/orangepi_gpio/*
@ -647,19 +656,16 @@ omit =
homeassistant/components/plaato/* homeassistant/components/plaato/*
homeassistant/components/plex/media_player.py homeassistant/components/plex/media_player.py
homeassistant/components/plex/sensor.py homeassistant/components/plex/sensor.py
homeassistant/components/plugwise/__init__.py
homeassistant/components/plugwise/binary_sensor.py
homeassistant/components/plugwise/climate.py
homeassistant/components/plugwise/sensor.py
homeassistant/components/plugwise/switch.py
homeassistant/components/plum_lightpad/light.py homeassistant/components/plum_lightpad/light.py
homeassistant/components/pocketcasts/sensor.py homeassistant/components/pocketcasts/sensor.py
homeassistant/components/point/* homeassistant/components/point/*
homeassistant/components/poolsense/__init__.py homeassistant/components/poolsense/__init__.py
homeassistant/components/poolsense/sensor.py homeassistant/components/poolsense/sensor.py
homeassistant/components/poolsense/binary_sensor.py homeassistant/components/poolsense/binary_sensor.py
homeassistant/components/prezzibenzina/sensor.py
homeassistant/components/proliphix/climate.py homeassistant/components/proliphix/climate.py
homeassistant/components/progettihwsw/__init__.py
homeassistant/components/progettihwsw/binary_sensor.py
homeassistant/components/progettihwsw/switch.py
homeassistant/components/prometheus/* homeassistant/components/prometheus/*
homeassistant/components/prowl/notify.py homeassistant/components/prowl/notify.py
homeassistant/components/proxmoxve/* homeassistant/components/proxmoxve/*
@ -711,6 +717,10 @@ omit =
homeassistant/components/roomba/roomba.py homeassistant/components/roomba/roomba.py
homeassistant/components/roomba/sensor.py homeassistant/components/roomba/sensor.py
homeassistant/components/roomba/vacuum.py homeassistant/components/roomba/vacuum.py
homeassistant/components/roon/__init__.py
homeassistant/components/roon/const.py
homeassistant/components/roon/media_player.py
homeassistant/components/roon/server.py
homeassistant/components/route53/* homeassistant/components/route53/*
homeassistant/components/rova/sensor.py homeassistant/components/rova/sensor.py
homeassistant/components/rpi_camera/* homeassistant/components/rpi_camera/*
@ -735,7 +745,6 @@ omit =
homeassistant/components/sensehat/light.py homeassistant/components/sensehat/light.py
homeassistant/components/sensehat/sensor.py homeassistant/components/sensehat/sensor.py
homeassistant/components/sensibo/climate.py homeassistant/components/sensibo/climate.py
homeassistant/components/sentry/__init__.py
homeassistant/components/serial/sensor.py homeassistant/components/serial/sensor.py
homeassistant/components/serial_pm/sensor.py homeassistant/components/serial_pm/sensor.py
homeassistant/components/sesame/lock.py homeassistant/components/sesame/lock.py
@ -743,6 +752,13 @@ omit =
homeassistant/components/seventeentrack/sensor.py homeassistant/components/seventeentrack/sensor.py
homeassistant/components/shiftr/* homeassistant/components/shiftr/*
homeassistant/components/shodan/sensor.py homeassistant/components/shodan/sensor.py
homeassistant/components/shelly/__init__.py
homeassistant/components/shelly/binary_sensor.py
homeassistant/components/shelly/cover.py
homeassistant/components/shelly/entity.py
homeassistant/components/shelly/light.py
homeassistant/components/shelly/sensor.py
homeassistant/components/shelly/switch.py
homeassistant/components/sht31/sensor.py homeassistant/components/sht31/sensor.py
homeassistant/components/sigfox/sensor.py homeassistant/components/sigfox/sensor.py
homeassistant/components/simplepush/notify.py homeassistant/components/simplepush/notify.py
@ -801,7 +817,8 @@ omit =
homeassistant/components/streamlabswater/* homeassistant/components/streamlabswater/*
homeassistant/components/suez_water/* homeassistant/components/suez_water/*
homeassistant/components/supervisord/sensor.py homeassistant/components/supervisord/sensor.py
homeassistant/components/surepetcare/*.py homeassistant/components/surepetcare/__init__.py
homeassistant/components/surepetcare/sensor.py
homeassistant/components/swiss_hydrological_data/sensor.py homeassistant/components/swiss_hydrological_data/sensor.py
homeassistant/components/swiss_public_transport/sensor.py homeassistant/components/swiss_public_transport/sensor.py
homeassistant/components/swisscom/device_tracker.py homeassistant/components/swisscom/device_tracker.py
@ -921,6 +938,7 @@ omit =
homeassistant/components/vesync/__init__.py homeassistant/components/vesync/__init__.py
homeassistant/components/vesync/common.py homeassistant/components/vesync/common.py
homeassistant/components/vesync/const.py homeassistant/components/vesync/const.py
homeassistant/components/vesync/fan.py
homeassistant/components/vesync/switch.py homeassistant/components/vesync/switch.py
homeassistant/components/viaggiatreno/sensor.py homeassistant/components/viaggiatreno/sensor.py
homeassistant/components/vicare/* homeassistant/components/vicare/*
@ -1010,7 +1028,6 @@ omit =
homeassistant/components/supla/* homeassistant/components/supla/*
homeassistant/components/zwave/util.py homeassistant/components/zwave/util.py
homeassistant/components/ozw/__init__.py homeassistant/components/ozw/__init__.py
homeassistant/components/ozw/discovery.py
homeassistant/components/ozw/entity.py homeassistant/components/ozw/entity.py
homeassistant/components/ozw/services.py homeassistant/components/ozw/services.py

View File

@ -16,7 +16,7 @@
<!-- <!--
Provide details about the versions you are using, which helps us to reproduce Provide details about the versions you are using, which helps us to reproduce
and find the issue quicker. Version information is found in the and find the issue quicker. Version information is found in the
Home Assistant frontend: Developer tools -> Info. Home Assistant frontend: Configuration -> Info.
--> -->
- Home Assistant Core release with the issue: - Home Assistant Core release with the issue:

View File

@ -20,7 +20,7 @@ about: Report an issue with Home Assistant Core
<!-- <!--
Provide details about the versions you are using, which helps us to reproduce Provide details about the versions you are using, which helps us to reproduce
and find the issue quicker. Version information is found in the and find the issue quicker. Version information is found in the
Home Assistant frontend: Developer tools -> Info. Home Assistant frontend: Configuration -> Info.
--> -->
- Home Assistant Core release with the issue: - Home Assistant Core release with the issue:

View File

@ -98,6 +98,29 @@ The integration reached or maintains the following [Integration Quality Scale][q
- [ ] 🥇 Gold - [ ] 🥇 Gold
- [ ] 🏆 Platinum - [ ] 🏆 Platinum
<!--
This project is very active and we have a high turnover of pull requests.
Unfortunately, the number of incoming pull requests is higher than what our
reviewers can review and merge so there is a long backlog of pull requests
waiting for review. You can help here!
By reviewing another pull request, you will help raise the code quality of
that pull request and the final review will be faster. This way the general
pace of pull request reviews will go up and your wait time will go down.
When picking a pull request to review, try to choose one that hasn't yet
been reviewed.
Thanks for helping out!
-->
To help with the load of incoming pull requests:
- [ ] I have reviewed two other [open pull requests][prs] in this repository.
[prs]: https://github.com/home-assistant/core/pulls?q=is%3Aopen+is%3Apr+-author%3A%40me+-draft%3Atrue+-label%3Awaiting-for-upstream+sort%3Acreated-asc+-review%3Aapproved
<!-- <!--
Thank you for contributing <3 Thank you for contributing <3

View File

@ -10,6 +10,7 @@ on:
pull_request: ~ pull_request: ~
env: env:
CACHE_VERSION: 1
DEFAULT_PYTHON: 3.7 DEFAULT_PYTHON: 3.7
PRE_COMMIT_HOME: ~/.cache/pre-commit PRE_COMMIT_HOME: ~/.cache/pre-commit
@ -24,7 +25,7 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }} - name: Set up Python ${{ env.DEFAULT_PYTHON }}
id: python id: python
uses: actions/setup-python@v2.1.1 uses: actions/setup-python@v2.1.2
with: with:
python-version: ${{ env.DEFAULT_PYTHON }} python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore base Python virtual environment - name: Restore base Python virtual environment
@ -33,34 +34,31 @@ jobs:
with: with:
path: venv path: venv
key: >- key: >-
${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
}}-${{ hashFiles('requirements.txt') }}-${{ steps.python.outputs.python-version }}-${{
hashFiles('requirements.txt') }}-${{
hashFiles('requirements_test.txt') }}-${{ hashFiles('requirements_test.txt') }}-${{
hashFiles('homeassistant/package_constraints.txt') }} hashFiles('homeassistant/package_constraints.txt') }}
restore-keys: | restore-keys: |
${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_test.txt') }}- ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_test.txt') }}-
${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements.txt') }} ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements.txt') }}
${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version }}- ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version }}-
- name: Create Python virtual environment - name: Create Python virtual environment
if: steps.cache-venv.outputs.cache-hit != 'true' if: steps.cache-venv.outputs.cache-hit != 'true'
run: | run: |
python -m venv venv python -m venv venv
. venv/bin/activate . venv/bin/activate
pip install -U pip==20.1.1 setuptools pip install -U pip setuptools
pip install -r requirements.txt -r requirements_test.txt pip install -r requirements.txt -r requirements_test.txt
# Uninstalling typing as a workaround. Eventually we should make sure
# all our dependencies drop typing.
# Find offending deps with `pipdeptree -r -p typing`
pip uninstall -y typing
- name: Restore pre-commit environment from cache - name: Restore pre-commit environment from cache
id: cache-precommit id: cache-precommit
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: ${{ env.PRE_COMMIT_HOME }} path: ${{ env.PRE_COMMIT_HOME }}
key: | key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} ${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
restore-keys: | restore-keys: |
${{ runner.os }}-pre-commit- ${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-
- name: Install pre-commit dependencies - name: Install pre-commit dependencies
if: steps.cache-precommit.outputs.cache-hit != 'true' if: steps.cache-precommit.outputs.cache-hit != 'true'
run: | run: |
@ -75,7 +73,7 @@ jobs:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }} - name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1 uses: actions/setup-python@v2.1.2
id: python id: python
with: with:
python-version: ${{ env.DEFAULT_PYTHON }} python-version: ${{ env.DEFAULT_PYTHON }}
@ -85,8 +83,9 @@ jobs:
with: with:
path: venv path: venv
key: >- key: >-
${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
}}-${{ hashFiles('requirements.txt') }}-${{ steps.python.outputs.python-version }}-${{
hashFiles('requirements.txt') }}-${{
hashFiles('requirements_test.txt') }}-${{ hashFiles('requirements_test.txt') }}-${{
hashFiles('homeassistant/package_constraints.txt') }} hashFiles('homeassistant/package_constraints.txt') }}
- name: Fail job if Python cache restore failed - name: Fail job if Python cache restore failed
@ -100,7 +99,7 @@ jobs:
with: with:
path: ${{ env.PRE_COMMIT_HOME }} path: ${{ env.PRE_COMMIT_HOME }}
key: | key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} ${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Fail job if cache restore failed - name: Fail job if cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true' if: steps.cache-venv.outputs.cache-hit != 'true'
run: | run: |
@ -119,7 +118,7 @@ jobs:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }} - name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1 uses: actions/setup-python@v2.1.2
id: python id: python
with: with:
python-version: ${{ env.DEFAULT_PYTHON }} python-version: ${{ env.DEFAULT_PYTHON }}
@ -129,8 +128,9 @@ jobs:
with: with:
path: venv path: venv
key: >- key: >-
${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
}}-${{ hashFiles('requirements.txt') }}-${{ steps.python.outputs.python-version }}-${{
hashFiles('requirements.txt') }}-${{
hashFiles('requirements_test.txt') }}-${{ hashFiles('requirements_test.txt') }}-${{
hashFiles('homeassistant/package_constraints.txt') }} hashFiles('homeassistant/package_constraints.txt') }}
- name: Fail job if Python cache restore failed - name: Fail job if Python cache restore failed
@ -144,7 +144,7 @@ jobs:
with: with:
path: ${{ env.PRE_COMMIT_HOME }} path: ${{ env.PRE_COMMIT_HOME }}
key: | key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} ${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Fail job if cache restore failed - name: Fail job if cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true' if: steps.cache-venv.outputs.cache-hit != 'true'
run: | run: |
@ -163,7 +163,7 @@ jobs:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }} - name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1 uses: actions/setup-python@v2.1.2
id: python id: python
with: with:
python-version: ${{ env.DEFAULT_PYTHON }} python-version: ${{ env.DEFAULT_PYTHON }}
@ -173,8 +173,9 @@ jobs:
with: with:
path: venv path: venv
key: >- key: >-
${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
}}-${{ hashFiles('requirements.txt') }}-${{ steps.python.outputs.python-version }}-${{
hashFiles('requirements.txt') }}-${{
hashFiles('requirements_test.txt') }}-${{ hashFiles('requirements_test.txt') }}-${{
hashFiles('homeassistant/package_constraints.txt') }} hashFiles('homeassistant/package_constraints.txt') }}
- name: Fail job if Python cache restore failed - name: Fail job if Python cache restore failed
@ -188,7 +189,7 @@ jobs:
with: with:
path: ${{ env.PRE_COMMIT_HOME }} path: ${{ env.PRE_COMMIT_HOME }}
key: | key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} ${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Fail job if cache restore failed - name: Fail job if cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true' if: steps.cache-venv.outputs.cache-hit != 'true'
run: | run: |
@ -229,7 +230,7 @@ jobs:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }} - name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1 uses: actions/setup-python@v2.1.2
id: python id: python
with: with:
python-version: ${{ env.DEFAULT_PYTHON }} python-version: ${{ env.DEFAULT_PYTHON }}
@ -239,8 +240,9 @@ jobs:
with: with:
path: venv path: venv
key: >- key: >-
${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
}}-${{ hashFiles('requirements.txt') }}-${{ steps.python.outputs.python-version }}-${{
hashFiles('requirements.txt') }}-${{
hashFiles('requirements_test.txt') }}-${{ hashFiles('requirements_test.txt') }}-${{
hashFiles('homeassistant/package_constraints.txt') }} hashFiles('homeassistant/package_constraints.txt') }}
- name: Fail job if Python cache restore failed - name: Fail job if Python cache restore failed
@ -254,7 +256,7 @@ jobs:
with: with:
path: ${{ env.PRE_COMMIT_HOME }} path: ${{ env.PRE_COMMIT_HOME }}
key: | key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} ${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Fail job if cache restore failed - name: Fail job if cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true' if: steps.cache-venv.outputs.cache-hit != 'true'
run: | run: |
@ -276,7 +278,7 @@ jobs:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }} - name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1 uses: actions/setup-python@v2.1.2
id: python id: python
with: with:
python-version: ${{ env.DEFAULT_PYTHON }} python-version: ${{ env.DEFAULT_PYTHON }}
@ -286,8 +288,9 @@ jobs:
with: with:
path: venv path: venv
key: >- key: >-
${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
}}-${{ hashFiles('requirements.txt') }}-${{ steps.python.outputs.python-version }}-${{
hashFiles('requirements.txt') }}-${{
hashFiles('requirements_test.txt') }}-${{ hashFiles('requirements_test.txt') }}-${{
hashFiles('homeassistant/package_constraints.txt') }} hashFiles('homeassistant/package_constraints.txt') }}
- name: Fail job if Python cache restore failed - name: Fail job if Python cache restore failed
@ -301,7 +304,7 @@ jobs:
with: with:
path: ${{ env.PRE_COMMIT_HOME }} path: ${{ env.PRE_COMMIT_HOME }}
key: | key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} ${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Fail job if cache restore failed - name: Fail job if cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true' if: steps.cache-venv.outputs.cache-hit != 'true'
run: | run: |
@ -323,7 +326,7 @@ jobs:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }} - name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1 uses: actions/setup-python@v2.1.2
id: python id: python
with: with:
python-version: ${{ env.DEFAULT_PYTHON }} python-version: ${{ env.DEFAULT_PYTHON }}
@ -333,8 +336,9 @@ jobs:
with: with:
path: venv path: venv
key: >- key: >-
${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
}}-${{ hashFiles('requirements.txt') }}-${{ steps.python.outputs.python-version }}-${{
hashFiles('requirements.txt') }}-${{
hashFiles('requirements_test.txt') }}-${{ hashFiles('requirements_test.txt') }}-${{
hashFiles('homeassistant/package_constraints.txt') }} hashFiles('homeassistant/package_constraints.txt') }}
- name: Fail job if Python cache restore failed - name: Fail job if Python cache restore failed
@ -348,7 +352,7 @@ jobs:
with: with:
path: ${{ env.PRE_COMMIT_HOME }} path: ${{ env.PRE_COMMIT_HOME }}
key: | key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} ${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Fail job if cache restore failed - name: Fail job if cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true' if: steps.cache-venv.outputs.cache-hit != 'true'
run: | run: |
@ -367,7 +371,7 @@ jobs:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }} - name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1 uses: actions/setup-python@v2.1.2
id: python id: python
with: with:
python-version: ${{ env.DEFAULT_PYTHON }} python-version: ${{ env.DEFAULT_PYTHON }}
@ -377,8 +381,9 @@ jobs:
with: with:
path: venv path: venv
key: >- key: >-
${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
}}-${{ hashFiles('requirements.txt') }}-${{ steps.python.outputs.python-version }}-${{
hashFiles('requirements.txt') }}-${{
hashFiles('requirements_test.txt') }}-${{ hashFiles('requirements_test.txt') }}-${{
hashFiles('homeassistant/package_constraints.txt') }} hashFiles('homeassistant/package_constraints.txt') }}
- name: Fail job if Python cache restore failed - name: Fail job if Python cache restore failed
@ -392,7 +397,7 @@ jobs:
with: with:
path: ${{ env.PRE_COMMIT_HOME }} path: ${{ env.PRE_COMMIT_HOME }}
key: | key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} ${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Fail job if cache restore failed - name: Fail job if cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true' if: steps.cache-venv.outputs.cache-hit != 'true'
run: | run: |
@ -414,7 +419,7 @@ jobs:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }} - name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1 uses: actions/setup-python@v2.1.2
id: python id: python
with: with:
python-version: ${{ env.DEFAULT_PYTHON }} python-version: ${{ env.DEFAULT_PYTHON }}
@ -424,8 +429,9 @@ jobs:
with: with:
path: venv path: venv
key: >- key: >-
${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
}}-${{ hashFiles('requirements.txt') }}-${{ steps.python.outputs.python-version }}-${{
hashFiles('requirements.txt') }}-${{
hashFiles('requirements_test.txt') }}-${{ hashFiles('requirements_test.txt') }}-${{
hashFiles('homeassistant/package_constraints.txt') }} hashFiles('homeassistant/package_constraints.txt') }}
- name: Fail job if Python cache restore failed - name: Fail job if Python cache restore failed
@ -439,7 +445,7 @@ jobs:
with: with:
path: ${{ env.PRE_COMMIT_HOME }} path: ${{ env.PRE_COMMIT_HOME }}
key: | key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} ${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Fail job if cache restore failed - name: Fail job if cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true' if: steps.cache-venv.outputs.cache-hit != 'true'
run: | run: |
@ -469,7 +475,7 @@ jobs:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }} - name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1 uses: actions/setup-python@v2.1.2
id: python id: python
with: with:
python-version: ${{ env.DEFAULT_PYTHON }} python-version: ${{ env.DEFAULT_PYTHON }}
@ -479,8 +485,9 @@ jobs:
with: with:
path: venv path: venv
key: >- key: >-
${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
}}-${{ hashFiles('requirements.txt') }}-${{ steps.python.outputs.python-version }}-${{
hashFiles('requirements.txt') }}-${{
hashFiles('requirements_test.txt') }}-${{ hashFiles('requirements_test.txt') }}-${{
hashFiles('homeassistant/package_constraints.txt') }} hashFiles('homeassistant/package_constraints.txt') }}
- name: Fail job if Python cache restore failed - name: Fail job if Python cache restore failed
@ -494,7 +501,7 @@ jobs:
with: with:
path: ${{ env.PRE_COMMIT_HOME }} path: ${{ env.PRE_COMMIT_HOME }}
key: | key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} ${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Fail job if cache restore failed - name: Fail job if cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true' if: steps.cache-venv.outputs.cache-hit != 'true'
run: | run: |
@ -516,7 +523,7 @@ jobs:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }} - name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1 uses: actions/setup-python@v2.1.2
id: python id: python
with: with:
python-version: ${{ env.DEFAULT_PYTHON }} python-version: ${{ env.DEFAULT_PYTHON }}
@ -526,8 +533,9 @@ jobs:
with: with:
path: venv path: venv
key: >- key: >-
${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
}}-${{ hashFiles('requirements.txt') }}-${{ steps.python.outputs.python-version }}-${{
hashFiles('requirements.txt') }}-${{
hashFiles('requirements_test.txt') }}-${{ hashFiles('requirements_test.txt') }}-${{
hashFiles('homeassistant/package_constraints.txt') }} hashFiles('homeassistant/package_constraints.txt') }}
- name: Fail job if Python cache restore failed - name: Fail job if Python cache restore failed
@ -548,7 +556,7 @@ jobs:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }} - name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1 uses: actions/setup-python@v2.1.2
id: python id: python
with: with:
python-version: ${{ env.DEFAULT_PYTHON }} python-version: ${{ env.DEFAULT_PYTHON }}
@ -558,8 +566,9 @@ jobs:
with: with:
path: venv path: venv
key: >- key: >-
${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version ${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
}}-${{ hashFiles('requirements.txt') }}-${{ steps.python.outputs.python-version }}-${{
hashFiles('requirements.txt') }}-${{
hashFiles('requirements_test.txt') }}-${{ hashFiles('requirements_test.txt') }}-${{
hashFiles('homeassistant/package_constraints.txt') }} hashFiles('homeassistant/package_constraints.txt') }}
- name: Fail job if Python cache restore failed - name: Fail job if Python cache restore failed
@ -582,34 +591,28 @@ jobs:
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: - name: Restore full Python ${{ matrix.python-version }} virtual environment
Restore full Python ${{ matrix.python-version }} virtual environment
id: cache-venv id: cache-venv
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: venv path: venv
key: >- key: >-
${{ runner.os }}-venv-${{ matrix.python-version }}-${{ ${{ env.CACHE_VERSION}}-${{ runner.os }}-venv-${{
hashFiles('requirements_test.txt') }}-${{ matrix.python-version }}-${{ hashFiles('requirements_test.txt')
hashFiles('requirements_all.txt') }}-${{ }}-${{ hashFiles('requirements_all.txt') }}-${{
hashFiles('homeassistant/package_constraints.txt') }} hashFiles('homeassistant/package_constraints.txt') }}
restore-keys: | restore-keys: |
${{ runner.os }}-venv-${{ matrix.python-version }}-${{ hashFiles('requirements_test.txt') }}-${{ hashFiles('requirements_all.txt') }} ${{ env.CACHE_VERSION}}-${{ runner.os }}-venv-${{ matrix.python-version }}-${{ hashFiles('requirements_test.txt') }}-${{ hashFiles('requirements_all.txt') }}
${{ runner.os }}-venv-${{ matrix.python-version }}-${{ hashFiles('requirements_test.txt') }} ${{ env.CACHE_VERSION}}-${{ runner.os }}-venv-${{ matrix.python-version }}-${{ hashFiles('requirements_test.txt') }}
${{ runner.os }}-venv-${{ matrix.python-version }}- ${{ env.CACHE_VERSION}}-${{ runner.os }}-venv-${{ matrix.python-version }}-
- name: - name: Create full Python ${{ matrix.python-version }} virtual environment
Create full Python ${{ matrix.python-version }} virtual environment
if: steps.cache-venv.outputs.cache-hit != 'true' if: steps.cache-venv.outputs.cache-hit != 'true'
run: | run: |
python -m venv venv python -m venv venv
. venv/bin/activate . venv/bin/activate
pip install -U pip==20.1.1 setuptools wheel pip install -U pip setuptools wheel
pip install -r requirements_all.txt pip install -r requirements_all.txt
pip install -r requirements_test.txt pip install -r requirements_test.txt
# Uninstalling typing as a workaround. Eventually we should make sure
# all our dependencies drop typing.
# Find offending deps with `pipdeptree -r -p typing`
pip uninstall -y typing
pip install -e . pip install -e .
pylint: pylint:
@ -623,16 +626,15 @@ jobs:
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: - name: Restore full Python ${{ matrix.python-version }} virtual environment
Restore full Python ${{ matrix.python-version }} virtual environment
id: cache-venv id: cache-venv
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: venv path: venv
key: >- key: >-
${{ runner.os }}-venv-${{ matrix.python-version }}-${{ ${{ env.CACHE_VERSION}}-${{ runner.os }}-venv-${{
hashFiles('requirements_test.txt') }}-${{ matrix.python-version }}-${{ hashFiles('requirements_test.txt')
hashFiles('requirements_all.txt') }}-${{ }}-${{ hashFiles('requirements_all.txt') }}-${{
hashFiles('homeassistant/package_constraints.txt') }} hashFiles('homeassistant/package_constraints.txt') }}
- name: Fail job if Python cache restore failed - name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true' if: steps.cache-venv.outputs.cache-hit != 'true'
@ -658,16 +660,15 @@ jobs:
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: - name: Restore full Python ${{ matrix.python-version }} virtual environment
Restore full Python ${{ matrix.python-version }} virtual environment
id: cache-venv id: cache-venv
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: venv path: venv
key: >- key: >-
${{ runner.os }}-venv-${{ matrix.python-version }}-${{ ${{ env.CACHE_VERSION}}-${{ runner.os }}-venv-${{
hashFiles('requirements_test.txt') }}-${{ matrix.python-version }}-${{ hashFiles('requirements_test.txt')
hashFiles('requirements_all.txt') }}-${{ }}-${{ hashFiles('requirements_all.txt') }}-${{
hashFiles('homeassistant/package_constraints.txt') }} hashFiles('homeassistant/package_constraints.txt') }}
- name: Fail job if Python cache restore failed - name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true' if: steps.cache-venv.outputs.cache-hit != 'true'
@ -695,16 +696,15 @@ jobs:
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: - name: Restore full Python ${{ matrix.python-version }} virtual environment
Restore full Python ${{ matrix.python-version }} virtual environment
id: cache-venv id: cache-venv
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: venv path: venv
key: >- key: >-
${{ runner.os }}-venv-${{ matrix.python-version }}-${{ ${{ env.CACHE_VERSION}}-${{ runner.os }}-venv-${{
hashFiles('requirements_test.txt') }}-${{ matrix.python-version }}-${{ hashFiles('requirements_test.txt')
hashFiles('requirements_all.txt') }}-${{ }}-${{ hashFiles('requirements_all.txt') }}-${{
hashFiles('homeassistant/package_constraints.txt') }} hashFiles('homeassistant/package_constraints.txt') }}
- name: Fail job if Python cache restore failed - name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true' if: steps.cache-venv.outputs.cache-hit != 'true'
@ -737,7 +737,7 @@ jobs:
-p no:sugar \ -p no:sugar \
tests tests
- name: Upload coverage artifact - name: Upload coverage artifact
uses: actions/upload-artifact@v2.1.3 uses: actions/upload-artifact@v2.1.4
with: with:
name: coverage-${{ matrix.python-version }}-group${{ matrix.group }} name: coverage-${{ matrix.python-version }}-group${{ matrix.group }}
path: .coverage path: .coverage
@ -756,16 +756,15 @@ jobs:
steps: steps:
- name: Check out code from GitHub - name: Check out code from GitHub
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: - name: Restore full Python ${{ matrix.python-version }} virtual environment
Restore full Python ${{ matrix.python-version }} virtual environment
id: cache-venv id: cache-venv
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: venv path: venv
key: >- key: >-
${{ runner.os }}-venv-${{ matrix.python-version }}-${{ ${{ env.CACHE_VERSION}}-${{ runner.os }}-venv-${{
hashFiles('requirements_test.txt') }}-${{ matrix.python-version }}-${{ hashFiles('requirements_test.txt')
hashFiles('requirements_all.txt') }}-${{ }}-${{ hashFiles('requirements_all.txt') }}-${{
hashFiles('homeassistant/package_constraints.txt') }} hashFiles('homeassistant/package_constraints.txt') }}
- name: Fail job if Python cache restore failed - name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true' if: steps.cache-venv.outputs.cache-hit != 'true'
@ -781,4 +780,4 @@ jobs:
coverage report --fail-under=94 coverage report --fail-under=94
coverage xml coverage xml
- name: Upload coverage to Codecov - name: Upload coverage to Codecov
uses: codecov/codecov-action@v1.0.12 uses: codecov/codecov-action@v1.0.13

View File

@ -1,11 +1,11 @@
repos: repos:
- repo: https://github.com/asottile/pyupgrade - repo: https://github.com/asottile/pyupgrade
rev: v2.3.0 rev: v2.7.2
hooks: hooks:
- id: pyupgrade - id: pyupgrade
args: [--py37-plus] args: [--py37-plus]
- repo: https://github.com/psf/black - repo: https://github.com/psf/black
rev: 19.10b0 rev: 20.8b1
hooks: hooks:
- id: black - id: black
args: args:
@ -13,11 +13,11 @@ repos:
- --quiet - --quiet
files: ^((homeassistant|script|tests)/.+)?[^/]+\.py$ files: ^((homeassistant|script|tests)/.+)?[^/]+\.py$
- repo: https://github.com/codespell-project/codespell - repo: https://github.com/codespell-project/codespell
rev: v1.16.0 rev: v1.17.1
hooks: hooks:
- id: codespell - id: codespell
args: args:
- --ignore-words-list=hass,alot,datas,dof,dur,farenheit,hist,iff,ines,ist,lightsensor,mut,nd,pres,referer,ser,serie,te,technik,ue,uint,visability,wan,wanna,withing - --ignore-words-list=hass,alot,datas,dof,dur,farenheit,hist,iff,ines,ist,lightsensor,mut,nd,pres,referer,ser,serie,te,technik,ue,uint,visability,wan,wanna,withing,iam,incomfort
- --skip="./.*,*.csv,*.json" - --skip="./.*,*.csv,*.json"
- --quiet-level=2 - --quiet-level=2
exclude_types: [csv, json] exclude_types: [csv, json]
@ -27,7 +27,7 @@ repos:
- id: flake8 - id: flake8
additional_dependencies: additional_dependencies:
- flake8-docstrings==1.5.0 - flake8-docstrings==1.5.0
- pydocstyle==5.0.2 - pydocstyle==5.1.1
files: ^(homeassistant|script|tests)/.+\.py$ files: ^(homeassistant|script|tests)/.+\.py$
- repo: https://github.com/PyCQA/bandit - repo: https://github.com/PyCQA/bandit
rev: 1.6.2 rev: 1.6.2
@ -38,12 +38,12 @@ repos:
- --format=custom - --format=custom
- --configfile=tests/bandit.yaml - --configfile=tests/bandit.yaml
files: ^(homeassistant|script|tests)/.+\.py$ files: ^(homeassistant|script|tests)/.+\.py$
- repo: https://github.com/pre-commit/mirrors-isort - repo: https://github.com/PyCQA/isort
rev: v4.3.21 rev: 5.5.1
hooks: hooks:
- id: isort - id: isort
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.4.0 rev: v3.2.0
hooks: hooks:
- id: check-executables-have-shebangs - id: check-executables-have-shebangs
stages: [manual] stages: [manual]
@ -54,7 +54,7 @@ repos:
- --branch=master - --branch=master
- --branch=rc - --branch=rc
- repo: https://github.com/adrienverge/yamllint.git - repo: https://github.com/adrienverge/yamllint.git
rev: v1.23.0 rev: v1.24.2
hooks: hooks:
- id: yamllint - id: yamllint
- repo: https://github.com/prettier/prettier - repo: https://github.com/prettier/prettier

View File

@ -2,6 +2,7 @@ dist: bionic
addons: addons:
apt: apt:
packages: packages:
- ffmpeg
- libudev-dev - libudev-dev
- libavformat-dev - libavformat-dev
- libavcodec-dev - libavcodec-dev
@ -30,7 +31,8 @@ jobs:
- python: "3.7.1" - python: "3.7.1"
env: TOXENV=lint env: TOXENV=lint
- python: "3.7.1" - python: "3.7.1"
env: TOXENV=pylint PYLINT_ARGS=--jobs=0 TRAVIS_WAIT=30 # PYLINT_ARGS=--jobs=0 disabled for now: https://github.com/PyCQA/pylint/issues/3584
env: TOXENV=pylint TRAVIS_WAIT=30
- python: "3.7.1" - python: "3.7.1"
env: TOXENV=typing env: TOXENV=typing

View File

@ -102,11 +102,14 @@ homeassistant/components/digital_ocean/* @fabaff
homeassistant/components/directv/* @ctalkington homeassistant/components/directv/* @ctalkington
homeassistant/components/discogs/* @thibmaek homeassistant/components/discogs/* @thibmaek
homeassistant/components/doorbird/* @oblogic7 @bdraco homeassistant/components/doorbird/* @oblogic7 @bdraco
homeassistant/components/dsmr/* @Robbie1221
homeassistant/components/dsmr_reader/* @depl0y homeassistant/components/dsmr_reader/* @depl0y
homeassistant/components/dunehd/* @bieniu homeassistant/components/dunehd/* @bieniu
homeassistant/components/dwd_weather_warnings/* @runningman84 @stephan192 @Hummel95
homeassistant/components/dweet/* @fabaff homeassistant/components/dweet/* @fabaff
homeassistant/components/dynalite/* @ziv1234 homeassistant/components/dynalite/* @ziv1234
homeassistant/components/dyson/* @etheralm homeassistant/components/dyson/* @etheralm
homeassistant/components/eafm/* @Jc2k
homeassistant/components/ecobee/* @marthoc homeassistant/components/ecobee/* @marthoc
homeassistant/components/ecovacs/* @OverloadUT homeassistant/components/ecovacs/* @OverloadUT
homeassistant/components/edl21/* @mtdcr homeassistant/components/edl21/* @mtdcr
@ -117,6 +120,7 @@ homeassistant/components/elkm1/* @gwww @bdraco
homeassistant/components/elv/* @majuss homeassistant/components/elv/* @majuss
homeassistant/components/emby/* @mezz64 homeassistant/components/emby/* @mezz64
homeassistant/components/emoncms/* @borpin homeassistant/components/emoncms/* @borpin
homeassistant/components/emulated_kasa/* @kbickar
homeassistant/components/enigma2/* @fbradyirl homeassistant/components/enigma2/* @fbradyirl
homeassistant/components/enocean/* @bdurrer homeassistant/components/enocean/* @bdurrer
homeassistant/components/entur_public_transport/* @hfurubotten homeassistant/components/entur_public_transport/* @hfurubotten
@ -134,6 +138,7 @@ homeassistant/components/filter/* @dgomes
homeassistant/components/firmata/* @DaAwesomeP homeassistant/components/firmata/* @DaAwesomeP
homeassistant/components/fixer/* @fabaff homeassistant/components/fixer/* @fabaff
homeassistant/components/flick_electric/* @ZephireNZ homeassistant/components/flick_electric/* @ZephireNZ
homeassistant/components/flo/* @dmulcahey
homeassistant/components/flock/* @fabaff homeassistant/components/flock/* @fabaff
homeassistant/components/flume/* @ChrisMandich @bdraco homeassistant/components/flume/* @ChrisMandich @bdraco
homeassistant/components/flunearyou/* @bachya homeassistant/components/flunearyou/* @bachya
@ -192,6 +197,7 @@ homeassistant/components/iammeter/* @lewei50
homeassistant/components/iaqualink/* @flz homeassistant/components/iaqualink/* @flz
homeassistant/components/icloud/* @Quentame homeassistant/components/icloud/* @Quentame
homeassistant/components/ign_sismologia/* @exxamalte homeassistant/components/ign_sismologia/* @exxamalte
homeassistant/components/image/* @home-assistant/core
homeassistant/components/incomfort/* @zxdavb homeassistant/components/incomfort/* @zxdavb
homeassistant/components/influxdb/* @fabaff @mdegat01 homeassistant/components/influxdb/* @fabaff @mdegat01
homeassistant/components/input_boolean/* @home-assistant/core homeassistant/components/input_boolean/* @home-assistant/core
@ -219,8 +225,8 @@ homeassistant/components/keba/* @dannerph
homeassistant/components/keenetic_ndms2/* @foxel homeassistant/components/keenetic_ndms2/* @foxel
homeassistant/components/kef/* @basnijholt homeassistant/components/kef/* @basnijholt
homeassistant/components/keyboard_remote/* @bendavid homeassistant/components/keyboard_remote/* @bendavid
homeassistant/components/knx/* @Julius2342 homeassistant/components/knx/* @Julius2342 @farmio @marvin-w
homeassistant/components/kodi/* @armills homeassistant/components/kodi/* @OnFreund
homeassistant/components/konnected/* @heythisisnate @kit-klein homeassistant/components/konnected/* @heythisisnate @kit-klein
homeassistant/components/lametric/* @robbiet480 homeassistant/components/lametric/* @robbiet480
homeassistant/components/launch_library/* @ludeeus homeassistant/components/launch_library/* @ludeeus
@ -230,6 +236,7 @@ homeassistant/components/linux_battery/* @fabaff
homeassistant/components/local_ip/* @issacg homeassistant/components/local_ip/* @issacg
homeassistant/components/logger/* @home-assistant/core homeassistant/components/logger/* @home-assistant/core
homeassistant/components/logi_circle/* @evanjd homeassistant/components/logi_circle/* @evanjd
homeassistant/components/loopenergy/* @pavoni
homeassistant/components/lovelace/* @home-assistant/frontend homeassistant/components/lovelace/* @home-assistant/frontend
homeassistant/components/luci/* @fbradyirl @mzdrale homeassistant/components/luci/* @fbradyirl @mzdrale
homeassistant/components/luftdaten/* @fabaff homeassistant/components/luftdaten/* @fabaff
@ -239,14 +246,15 @@ homeassistant/components/lutron_caseta/* @swails
homeassistant/components/mastodon/* @fabaff homeassistant/components/mastodon/* @fabaff
homeassistant/components/matrix/* @tinloaf homeassistant/components/matrix/* @tinloaf
homeassistant/components/mcp23017/* @jardiamj homeassistant/components/mcp23017/* @jardiamj
homeassistant/components/media_source/* @hunterjm
homeassistant/components/mediaroom/* @dgomes homeassistant/components/mediaroom/* @dgomes
homeassistant/components/melcloud/* @vilppuvuorinen homeassistant/components/melcloud/* @vilppuvuorinen
homeassistant/components/melissa/* @kennedyshead homeassistant/components/melissa/* @kennedyshead
homeassistant/components/met/* @danielhiversen homeassistant/components/met/* @danielhiversen @thimic
homeassistant/components/meteo_france/* @hacf-fr @oncleben31 @Quentame homeassistant/components/meteo_france/* @hacf-fr @oncleben31 @Quentame
homeassistant/components/meteoalarm/* @rolfberkenbosch homeassistant/components/meteoalarm/* @rolfberkenbosch
homeassistant/components/metoffice/* @MrHarcombe homeassistant/components/metoffice/* @MrHarcombe
homeassistant/components/miflora/* @danielhiversen @ChristianKuehnel homeassistant/components/miflora/* @danielhiversen @ChristianKuehnel @basnijholt
homeassistant/components/mikrotik/* @engrbm87 homeassistant/components/mikrotik/* @engrbm87
homeassistant/components/mill/* @danielhiversen homeassistant/components/mill/* @danielhiversen
homeassistant/components/min_max/* @fabaff homeassistant/components/min_max/* @fabaff
@ -272,10 +280,12 @@ homeassistant/components/netdata/* @fabaff
homeassistant/components/nexia/* @ryannazaretian @bdraco homeassistant/components/nexia/* @ryannazaretian @bdraco
homeassistant/components/nextbus/* @vividboarder homeassistant/components/nextbus/* @vividboarder
homeassistant/components/nextcloud/* @meichthys homeassistant/components/nextcloud/* @meichthys
homeassistant/components/nightscout/* @marciogranzotto
homeassistant/components/nilu/* @hfurubotten homeassistant/components/nilu/* @hfurubotten
homeassistant/components/nissan_leaf/* @filcole homeassistant/components/nissan_leaf/* @filcole
homeassistant/components/nmbs/* @thibmaek homeassistant/components/nmbs/* @thibmaek
homeassistant/components/no_ip/* @fabaff homeassistant/components/no_ip/* @fabaff
homeassistant/components/noaa_tides/* @jdelaney72
homeassistant/components/notify/* @home-assistant/core homeassistant/components/notify/* @home-assistant/core
homeassistant/components/notify_events/* @matrozov @papajojo homeassistant/components/notify_events/* @matrozov @papajojo
homeassistant/components/notion/* @bachya homeassistant/components/notion/* @bachya
@ -297,7 +307,7 @@ homeassistant/components/openerz/* @misialq
homeassistant/components/opengarage/* @danielhiversen homeassistant/components/opengarage/* @danielhiversen
homeassistant/components/opentherm_gw/* @mvn23 homeassistant/components/opentherm_gw/* @mvn23
homeassistant/components/openuv/* @bachya homeassistant/components/openuv/* @bachya
homeassistant/components/openweathermap/* @fabaff homeassistant/components/openweathermap/* @fabaff @freekode
homeassistant/components/opnsense/* @mtreinish homeassistant/components/opnsense/* @mtreinish
homeassistant/components/orangepi_gpio/* @pascallj homeassistant/components/orangepi_gpio/* @pascallj
homeassistant/components/oru/* @bvlaicu homeassistant/components/oru/* @bvlaicu
@ -320,6 +330,7 @@ homeassistant/components/plum_lightpad/* @ColinHarrington @prystupa
homeassistant/components/point/* @fredrike homeassistant/components/point/* @fredrike
homeassistant/components/poolsense/* @haemishkyd homeassistant/components/poolsense/* @haemishkyd
homeassistant/components/powerwall/* @bdraco @jrester homeassistant/components/powerwall/* @bdraco @jrester
homeassistant/components/progettihwsw/* @ardaseremet
homeassistant/components/prometheus/* @knyar homeassistant/components/prometheus/* @knyar
homeassistant/components/proxmoxve/* @k4ds3 @jhollowe homeassistant/components/proxmoxve/* @k4ds3 @jhollowe
homeassistant/components/ps4/* @ktnrg45 homeassistant/components/ps4/* @ktnrg45
@ -341,9 +352,11 @@ homeassistant/components/random/* @fabaff
homeassistant/components/repetier/* @MTrab homeassistant/components/repetier/* @MTrab
homeassistant/components/rfxtrx/* @danielhiversen @elupus homeassistant/components/rfxtrx/* @danielhiversen @elupus
homeassistant/components/ring/* @balloob homeassistant/components/ring/* @balloob
homeassistant/components/risco/* @OnFreund
homeassistant/components/rmvtransport/* @cgtobi homeassistant/components/rmvtransport/* @cgtobi
homeassistant/components/roku/* @ctalkington homeassistant/components/roku/* @ctalkington
homeassistant/components/roomba/* @pschmitt @cyr-ius @shenxn homeassistant/components/roomba/* @pschmitt @cyr-ius @shenxn
homeassistant/components/roon/* @pavoni
homeassistant/components/safe_mode/* @home-assistant/core homeassistant/components/safe_mode/* @home-assistant/core
homeassistant/components/saj/* @fredericvl homeassistant/components/saj/* @fredericvl
homeassistant/components/salt/* @bjornorri homeassistant/components/salt/* @bjornorri
@ -355,11 +368,13 @@ homeassistant/components/script/* @home-assistant/core
homeassistant/components/search/* @home-assistant/core homeassistant/components/search/* @home-assistant/core
homeassistant/components/sense/* @kbickar homeassistant/components/sense/* @kbickar
homeassistant/components/sensibo/* @andrey-git homeassistant/components/sensibo/* @andrey-git
homeassistant/components/sentry/* @dcramer homeassistant/components/sentry/* @dcramer @frenck
homeassistant/components/serial/* @fabaff homeassistant/components/serial/* @fabaff
homeassistant/components/seven_segments/* @fabaff homeassistant/components/seven_segments/* @fabaff
homeassistant/components/seventeentrack/* @bachya homeassistant/components/seventeentrack/* @bachya
homeassistant/components/sharkiq/* @ajmarks
homeassistant/components/shell_command/* @home-assistant/core homeassistant/components/shell_command/* @home-assistant/core
homeassistant/components/shelly/* @balloob @bieniu
homeassistant/components/shiftr/* @fabaff homeassistant/components/shiftr/* @fabaff
homeassistant/components/shodan/* @fabaff homeassistant/components/shodan/* @fabaff
homeassistant/components/sighthound/* @robmarkcole homeassistant/components/sighthound/* @robmarkcole
@ -371,6 +386,7 @@ homeassistant/components/sky_hub/* @rogerselwyn
homeassistant/components/slide/* @ualex73 homeassistant/components/slide/* @ualex73
homeassistant/components/sma/* @kellerza homeassistant/components/sma/* @kellerza
homeassistant/components/smappee/* @bsmappee homeassistant/components/smappee/* @bsmappee
homeassistant/components/smart_meter_texas/* @grahamwetzler
homeassistant/components/smarthab/* @outadoc homeassistant/components/smarthab/* @outadoc
homeassistant/components/smartthings/* @andrewsayre homeassistant/components/smartthings/* @andrewsayre
homeassistant/components/smarty/* @z0mbieprocess homeassistant/components/smarty/* @z0mbieprocess
@ -393,7 +409,7 @@ homeassistant/components/starline/* @anonym-tsk
homeassistant/components/statistics/* @fabaff homeassistant/components/statistics/* @fabaff
homeassistant/components/stiebel_eltron/* @fucm homeassistant/components/stiebel_eltron/* @fucm
homeassistant/components/stookalert/* @fwestenberg homeassistant/components/stookalert/* @fwestenberg
homeassistant/components/stream/* @hunterjm homeassistant/components/stream/* @hunterjm @uvjustin
homeassistant/components/stt/* @pvizeli homeassistant/components/stt/* @pvizeli
homeassistant/components/suez_water/* @ooii homeassistant/components/suez_water/* @ooii
homeassistant/components/sun/* @Swamp-Ig homeassistant/components/sun/* @Swamp-Ig
@ -409,6 +425,7 @@ homeassistant/components/synology_dsm/* @ProtoThis @Quentame
homeassistant/components/synology_srm/* @aerialls homeassistant/components/synology_srm/* @aerialls
homeassistant/components/syslog/* @fabaff homeassistant/components/syslog/* @fabaff
homeassistant/components/tado/* @michaelarnauts @bdraco homeassistant/components/tado/* @michaelarnauts @bdraco
homeassistant/components/tag/* @balloob @dmulcahey
homeassistant/components/tahoma/* @philklei homeassistant/components/tahoma/* @philklei
homeassistant/components/tankerkoenig/* @guillempages homeassistant/components/tankerkoenig/* @guillempages
homeassistant/components/tautulli/* @ludeeus homeassistant/components/tautulli/* @ludeeus
@ -429,6 +446,7 @@ homeassistant/components/tplink/* @rytilahti
homeassistant/components/traccar/* @ludeeus homeassistant/components/traccar/* @ludeeus
homeassistant/components/tradfri/* @ggravlingen homeassistant/components/tradfri/* @ggravlingen
homeassistant/components/trafikverket_train/* @endor-force homeassistant/components/trafikverket_train/* @endor-force
homeassistant/components/trafikverket_weatherstation/* @endor-force
homeassistant/components/transmission/* @engrbm87 @JPHutchins homeassistant/components/transmission/* @engrbm87 @JPHutchins
homeassistant/components/tts/* @pvizeli homeassistant/components/tts/* @pvizeli
homeassistant/components/tuya/* @ollo69 homeassistant/components/tuya/* @ollo69
@ -437,7 +455,7 @@ homeassistant/components/ubee/* @mzdrale
homeassistant/components/unifi/* @Kane610 homeassistant/components/unifi/* @Kane610
homeassistant/components/unifiled/* @florisvdk homeassistant/components/unifiled/* @florisvdk
homeassistant/components/upb/* @gwww homeassistant/components/upb/* @gwww
homeassistant/components/upc_connect/* @pvizeli homeassistant/components/upc_connect/* @pvizeli @fabaff
homeassistant/components/upcloud/* @scop homeassistant/components/upcloud/* @scop
homeassistant/components/updater/* @home-assistant/core homeassistant/components/updater/* @home-assistant/core
homeassistant/components/upnp/* @StevenLooman homeassistant/components/upnp/* @StevenLooman
@ -448,13 +466,14 @@ homeassistant/components/velbus/* @Cereal2nd @brefra
homeassistant/components/velux/* @Julius2342 homeassistant/components/velux/* @Julius2342
homeassistant/components/vera/* @vangorra homeassistant/components/vera/* @vangorra
homeassistant/components/versasense/* @flamm3blemuff1n homeassistant/components/versasense/* @flamm3blemuff1n
homeassistant/components/version/* @fabaff homeassistant/components/version/* @fabaff @ludeeus
homeassistant/components/vesync/* @markperdue @webdjoe homeassistant/components/vesync/* @markperdue @webdjoe @thegardenmonkey
homeassistant/components/vicare/* @oischinger homeassistant/components/vicare/* @oischinger
homeassistant/components/vilfo/* @ManneW homeassistant/components/vilfo/* @ManneW
homeassistant/components/vivotek/* @HarlemSquirrel homeassistant/components/vivotek/* @HarlemSquirrel
homeassistant/components/vizio/* @raman325 homeassistant/components/vizio/* @raman325
homeassistant/components/vlc_telnet/* @rodripf homeassistant/components/vlc_telnet/* @rodripf
homeassistant/components/volkszaehler/* @fabaff
homeassistant/components/volumio/* @OnFreund homeassistant/components/volumio/* @OnFreund
homeassistant/components/waqi/* @andrey-git homeassistant/components/waqi/* @andrey-git
homeassistant/components/watson_tts/* @rutkai homeassistant/components/watson_tts/* @rutkai
@ -462,6 +481,7 @@ homeassistant/components/weather/* @fabaff
homeassistant/components/webostv/* @bendavid homeassistant/components/webostv/* @bendavid
homeassistant/components/websocket_api/* @home-assistant/core homeassistant/components/websocket_api/* @home-assistant/core
homeassistant/components/wiffi/* @mampfes homeassistant/components/wiffi/* @mampfes
homeassistant/components/wilight/* @leofig-rj
homeassistant/components/withings/* @vangorra homeassistant/components/withings/* @vangorra
homeassistant/components/wled/* @frenck homeassistant/components/wled/* @frenck
homeassistant/components/wolflink/* @adamkrol93 homeassistant/components/wolflink/* @adamkrol93
@ -475,11 +495,10 @@ homeassistant/components/xiaomi_tv/* @simse
homeassistant/components/xmpp/* @fabaff @flowolf homeassistant/components/xmpp/* @fabaff @flowolf
homeassistant/components/yamaha_musiccast/* @jalmeroth homeassistant/components/yamaha_musiccast/* @jalmeroth
homeassistant/components/yandex_transport/* @rishatik92 @devbis homeassistant/components/yandex_transport/* @rishatik92 @devbis
homeassistant/components/yeelight/* @rytilahti @zewelor homeassistant/components/yeelight/* @rytilahti @zewelor @shenxn
homeassistant/components/yeelightsunflower/* @lindsaymarkward homeassistant/components/yeelightsunflower/* @lindsaymarkward
homeassistant/components/yessssms/* @flowolf homeassistant/components/yessssms/* @flowolf
homeassistant/components/yi/* @bachya homeassistant/components/yi/* @bachya
homeassistant/components/yr/* @danielhiversen
homeassistant/components/zeroconf/* @Kane610 homeassistant/components/zeroconf/* @Kane610
homeassistant/components/zerproc/* @emlove homeassistant/components/zerproc/* @emlove
homeassistant/components/zha/* @dmulcahey @adminiuga homeassistant/components/zha/* @dmulcahey @adminiuga

View File

@ -11,7 +11,6 @@ COPY . homeassistant/
RUN \ RUN \
pip3 install --no-cache-dir --no-index --only-binary=:all: --find-links "${WHEELS_LINKS}" \ pip3 install --no-cache-dir --no-index --only-binary=:all: --find-links "${WHEELS_LINKS}" \
-r homeassistant/requirements_all.txt \ -r homeassistant/requirements_all.txt \
&& pip3 uninstall -y typing \
&& pip3 install --no-cache-dir --no-index --only-binary=:all: --find-links "${WHEELS_LINKS}" \ && pip3 install --no-cache-dir --no-index --only-binary=:all: --find-links "${WHEELS_LINKS}" \
-e ./homeassistant \ -e ./homeassistant \
&& python3 -m compileall homeassistant/homeassistant && python3 -m compileall homeassistant/homeassistant

View File

@ -166,9 +166,6 @@ stages:
. venv/bin/activate . venv/bin/activate
pip install -U pip setuptools pytest-azurepipelines pytest-xdist -c homeassistant/package_constraints.txt pip install -U pip setuptools pytest-azurepipelines pytest-xdist -c homeassistant/package_constraints.txt
pip install -r requirements_test_all.txt pip install -r requirements_test_all.txt
# This is a TEMP. Eventually we should make sure our 4 dependencies drop typing.
# Find offending deps with `pipdeptree -r -p typing`
pip uninstall -y typing
- script: | - script: |
. venv/bin/activate . venv/bin/activate
pip install -e . pip install -e .
@ -211,9 +208,6 @@ stages:
pip install -U pip setuptools wheel pip install -U pip setuptools wheel
pip install -r requirements_all.txt pip install -r requirements_all.txt
pip install -r requirements_test.txt pip install -r requirements_test.txt
# This is a TEMP. Eventually we should make sure our 4 dependencies drop typing.
# Find offending deps with `pipdeptree -r -p typing`
pip uninstall -y typing
- script: | - script: |
. venv/bin/activate . venv/bin/activate
pip install -e . pip install -e .

View File

@ -47,8 +47,9 @@ jobs:
- template: templates/azp-job-wheels.yaml@azure - template: templates/azp-job-wheels.yaml@azure
parameters: parameters:
builderVersion: '$(versionWheels)' builderVersion: '$(versionWheels)'
builderApk: 'build-base;cmake;git;linux-headers;bluez-dev;libffi-dev;openssl-dev;glib-dev;eudev-dev;libxml2-dev;libxslt-dev;libpng-dev;libjpeg-turbo-dev;tiff-dev;autoconf;automake;cups-dev;gmp-dev;mpfr-dev;mpc1-dev;ffmpeg-dev;gammu-dev' builderApk: 'build-base;cmake;git;linux-headers;libexecinfo-dev;bluez-dev;libffi-dev;openssl-dev;glib-dev;eudev-dev;libxml2-dev;libxslt-dev;libpng-dev;libjpeg-turbo-dev;tiff-dev;autoconf;automake;cups-dev;gmp-dev;mpfr-dev;mpc1-dev;ffmpeg-dev;gammu-dev'
builderPip: 'Cython;numpy;scikit-build' builderPip: 'Cython;numpy;scikit-build'
builderEnvFile: true
skipBinary: 'aiohttp' skipBinary: 'aiohttp'
wheelsRequirement: 'requirements_wheels.txt' wheelsRequirement: 'requirements_wheels.txt'
wheelsRequirementDiff: 'requirements_diff.txt' wheelsRequirementDiff: 'requirements_diff.txt'
@ -90,4 +91,10 @@ jobs:
sed -i "s|# bme680|bme680|g" ${requirement_file} sed -i "s|# bme680|bme680|g" ${requirement_file}
sed -i "s|# python-gammu|python-gammu|g" ${requirement_file} sed -i "s|# python-gammu|python-gammu|g" ${requirement_file}
done done
# Write env for build settings
(
echo "GRPC_BUILD_WITH_BORING_SSL_ASM="
echo "GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=1"
) > .env_file
displayName: 'Prepare requirements files for Home Assistant wheels' displayName: 'Prepare requirements files for Home Assistant wheels'

View File

@ -1,11 +1,11 @@
{ {
"image": "homeassistant/{arch}-homeassistant", "image": "homeassistant/{arch}-homeassistant",
"build_from": { "build_from": {
"aarch64": "homeassistant/aarch64-homeassistant-base:8.2.1", "aarch64": "homeassistant/aarch64-homeassistant-base:8.4.0",
"armhf": "homeassistant/armhf-homeassistant-base:8.2.1", "armhf": "homeassistant/armhf-homeassistant-base:8.4.0",
"armv7": "homeassistant/armv7-homeassistant-base:8.2.1", "armv7": "homeassistant/armv7-homeassistant-base:8.4.0",
"amd64": "homeassistant/amd64-homeassistant-base:8.2.1", "amd64": "homeassistant/amd64-homeassistant-base:8.4.0",
"i386": "homeassistant/i386-homeassistant-base:8.2.1" "i386": "homeassistant/i386-homeassistant-base:8.4.0"
}, },
"labels": { "labels": {
"io.hass.type": "core" "io.hass.type": "core"

View File

@ -195,7 +195,7 @@ def closefds_osx(min_fd: int, max_fd: int) -> None:
get rid of. get rid of.
""" """
# pylint: disable=import-outside-toplevel # pylint: disable=import-outside-toplevel
from fcntl import fcntl, F_GETFD, F_SETFD, FD_CLOEXEC from fcntl import F_GETFD, F_SETFD, FD_CLOEXEC, fcntl
for _fd in range(min_fd, max_fd): for _fd in range(min_fd, max_fd):
try: try:

View File

@ -312,9 +312,7 @@ class AuthManager:
if provider is not None and hasattr(provider, "async_will_remove_credentials"): if provider is not None and hasattr(provider, "async_will_remove_credentials"):
# https://github.com/python/mypy/issues/1424 # https://github.com/python/mypy/issues/1424
await provider.async_will_remove_credentials( # type: ignore await provider.async_will_remove_credentials(credentials) # type: ignore
credentials
)
await self._store.async_remove_credentials(credentials) await self._store.async_remove_credentials(credentials)

View File

@ -150,7 +150,9 @@ async def _load_mfa_module(hass: HomeAssistant, module_name: str) -> types.Modul
module = importlib.import_module(module_path) module = importlib.import_module(module_path)
except ImportError as err: except ImportError as err:
_LOGGER.error("Unable to load mfa module %s: %s", module_name, err) _LOGGER.error("Unable to load mfa module %s: %s", module_name, err)
raise HomeAssistantError(f"Unable to load mfa module {module_name}: {err}") raise HomeAssistantError(
f"Unable to load mfa module {module_name}: {err}"
) from err
if hass.config.skip_pip or not hasattr(module, "REQUIREMENTS"): if hass.config.skip_pip or not hasattr(module, "REQUIREMENTS"):
return module return module

View File

@ -48,7 +48,10 @@ class User:
) )
_permissions: Optional[perm_mdl.PolicyPermissions] = attr.ib( _permissions: Optional[perm_mdl.PolicyPermissions] = attr.ib(
init=False, eq=False, order=False, default=None, init=False,
eq=False,
order=False,
default=None,
) )
@property @property

View File

@ -72,4 +72,4 @@ class _OwnerPermissions(AbstractPermissions):
return lambda entity_id, key: True return lambda entity_id, key: True
OwnerPermissions = _OwnerPermissions() # pylint: disable=invalid-name OwnerPermissions = _OwnerPermissions()

View File

@ -5,8 +5,10 @@ import attr
if TYPE_CHECKING: if TYPE_CHECKING:
# pylint: disable=unused-import # pylint: disable=unused-import
from homeassistant.helpers import entity_registry as ent_reg # noqa: F401 from homeassistant.helpers import ( # noqa: F401
from homeassistant.helpers import device_registry as dev_reg # noqa: F401 device_registry as dev_reg,
entity_registry as ent_reg,
)
@attr.s(slots=True) @attr.s(slots=True)

View File

@ -146,7 +146,9 @@ async def load_auth_provider_module(
module = importlib.import_module(f"homeassistant.auth.providers.{provider}") module = importlib.import_module(f"homeassistant.auth.providers.{provider}")
except ImportError as err: except ImportError as err:
_LOGGER.error("Unable to load auth provider %s: %s", provider, err) _LOGGER.error("Unable to load auth provider %s: %s", provider, err)
raise HomeAssistantError(f"Unable to load auth provider {provider}: {err}") raise HomeAssistantError(
f"Unable to load auth provider {provider}: {err}"
) from err
if hass.config.skip_pip or not hasattr(module, "REQUIREMENTS"): if hass.config.skip_pip or not hasattr(module, "REQUIREMENTS"):
return module return module

View File

@ -71,7 +71,7 @@ class CommandLineAuthProvider(AuthProvider):
except OSError as err: except OSError as err:
# happens when command doesn't exist or permission is denied # happens when command doesn't exist or permission is denied
_LOGGER.error("Error while authenticating %r: %s", username, err) _LOGGER.error("Error while authenticating %r: %s", username, err)
raise InvalidAuthError raise InvalidAuthError from err
if process.returncode != 0: if process.returncode != 0:
_LOGGER.error( _LOGGER.error(

View File

@ -30,6 +30,16 @@ def _disallow_id(conf: Dict[str, Any]) -> Dict[str, Any]:
CONFIG_SCHEMA = vol.All(AUTH_PROVIDER_SCHEMA, _disallow_id) CONFIG_SCHEMA = vol.All(AUTH_PROVIDER_SCHEMA, _disallow_id)
@callback
def async_get_provider(hass: HomeAssistant) -> "HassAuthProvider":
"""Get the provider."""
for prv in hass.auth.auth_providers:
if prv.type == "homeassistant":
return cast(HassAuthProvider, prv)
raise RuntimeError("Provider not found")
class InvalidAuth(HomeAssistantError): class InvalidAuth(HomeAssistantError):
"""Raised when we encounter invalid authentication.""" """Raised when we encounter invalid authentication."""
@ -235,6 +245,35 @@ class HassAuthProvider(AuthProvider):
self.data.validate_login, username, password self.data.validate_login, username, password
) )
async def async_add_auth(self, username: str, password: str) -> None:
"""Call add_auth on data."""
if self.data is None:
await self.async_initialize()
assert self.data is not None
await self.hass.async_add_executor_job(self.data.add_auth, username, password)
await self.data.async_save()
async def async_remove_auth(self, username: str) -> None:
"""Call remove_auth on data."""
if self.data is None:
await self.async_initialize()
assert self.data is not None
self.data.async_remove_auth(username)
await self.data.async_save()
async def async_change_password(self, username: str, new_password: str) -> None:
"""Call change_password on data."""
if self.data is None:
await self.async_initialize()
assert self.data is not None
await self.hass.async_add_executor_job(
self.data.change_password, username, new_password
)
await self.data.async_save()
async def async_get_or_create_credentials( async def async_get_or_create_credentials(
self, flow_result: Dict[str, str] self, flow_result: Dict[str, str]
) -> Credentials: ) -> Credentials:

View File

@ -112,7 +112,8 @@ async def async_setup_hass(
config_dict = await conf_util.async_hass_config_yaml(hass) config_dict = await conf_util.async_hass_config_yaml(hass)
except HomeAssistantError as err: except HomeAssistantError as err:
_LOGGER.error( _LOGGER.error(
"Failed to parse configuration.yaml: %s. Activating safe mode", err, "Failed to parse configuration.yaml: %s. Activating safe mode",
err,
) )
else: else:
if not is_virtual_env(): if not is_virtual_env():
@ -160,7 +161,8 @@ async def async_setup_hass(
http_conf = (await http.async_get_last_config(hass)) or {} http_conf = (await http.async_get_last_config(hass)) or {}
await async_from_config_dict( await async_from_config_dict(
{"safe_mode": {}, "http": http_conf}, hass, {"safe_mode": {}, "http": http_conf},
hass,
) )
if runtime_config.open_ui: if runtime_config.open_ui:
@ -331,8 +333,10 @@ def async_enable_logging(
): ):
if log_rotate_days: if log_rotate_days:
err_handler: logging.FileHandler = logging.handlers.TimedRotatingFileHandler( err_handler: logging.FileHandler = (
err_log_path, when="midnight", backupCount=log_rotate_days logging.handlers.TimedRotatingFileHandler(
err_log_path, when="midnight", backupCount=log_rotate_days
)
) )
else: else:
err_handler = logging.FileHandler(err_log_path, mode="w", delay=True) err_handler = logging.FileHandler(err_log_path, mode="w", delay=True)
@ -391,7 +395,8 @@ async def _async_log_pending_setups(
if remaining: if remaining:
_LOGGER.warning( _LOGGER.warning(
"Waiting on integrations to complete setup: %s", ", ".join(remaining), "Waiting on integrations to complete setup: %s",
", ".join(remaining),
) )

View File

@ -120,7 +120,7 @@ async def async_setup_entry(hass, config_entry):
except (AbodeException, ConnectTimeout, HTTPError) as ex: except (AbodeException, ConnectTimeout, HTTPError) as ex:
LOGGER.error("Unable to connect to Abode: %s", str(ex)) LOGGER.error("Unable to connect to Abode: %s", str(ex))
raise ConfigEntryNotReady raise ConfigEntryNotReady from ex
for platform in ABODE_PLATFORMS: for platform in ABODE_PLATFORMS:
hass.async_create_task( hass.async_create_task(

View File

@ -127,6 +127,6 @@ class AccuWeatherDataUpdateCoordinator(DataUpdateCoordinator):
InvalidApiKeyError, InvalidApiKeyError,
RequestsExceededError, RequestsExceededError,
) as error: ) as error:
raise UpdateFailed(error) raise UpdateFailed(error) from error
_LOGGER.debug("Requests remaining: %s", self.accuweather.requests_remaining) _LOGGER.debug("Requests remaining: %s", self.accuweather.requests_remaining)
return {**current, **{ATTR_FORECAST: forecast}} return {**current, **{ATTR_FORECAST: forecast}}

View File

@ -34,7 +34,7 @@ class AccuWeatherFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
if user_input is not None: if user_input is not None:
websession = async_get_clientsession(self.hass) websession = async_get_clientsession(self.hass)
try: try:
with timeout(10): async with timeout(10):
accuweather = AccuWeather( accuweather = AccuWeather(
user_input[CONF_API_KEY], user_input[CONF_API_KEY],
websession, websession,

View File

@ -5,12 +5,12 @@ from homeassistant.const import (
LENGTH_FEET, LENGTH_FEET,
LENGTH_INCHES, LENGTH_INCHES,
LENGTH_METERS, LENGTH_METERS,
PERCENTAGE,
SPEED_KILOMETERS_PER_HOUR, SPEED_KILOMETERS_PER_HOUR,
SPEED_MILES_PER_HOUR, SPEED_MILES_PER_HOUR,
TEMP_CELSIUS, TEMP_CELSIUS,
TEMP_FAHRENHEIT, TEMP_FAHRENHEIT,
TIME_HOURS, TIME_HOURS,
UNIT_PERCENTAGE,
UV_INDEX, UV_INDEX,
VOLUME_CUBIC_METERS, VOLUME_CUBIC_METERS,
) )
@ -53,15 +53,15 @@ FORECAST_SENSOR_TYPES = {
ATTR_DEVICE_CLASS: None, ATTR_DEVICE_CLASS: None,
ATTR_ICON: "mdi:weather-cloudy", ATTR_ICON: "mdi:weather-cloudy",
ATTR_LABEL: "Cloud Cover Day", ATTR_LABEL: "Cloud Cover Day",
ATTR_UNIT_METRIC: UNIT_PERCENTAGE, ATTR_UNIT_METRIC: PERCENTAGE,
ATTR_UNIT_IMPERIAL: UNIT_PERCENTAGE, ATTR_UNIT_IMPERIAL: PERCENTAGE,
}, },
"CloudCoverNight": { "CloudCoverNight": {
ATTR_DEVICE_CLASS: None, ATTR_DEVICE_CLASS: None,
ATTR_ICON: "mdi:weather-cloudy", ATTR_ICON: "mdi:weather-cloudy",
ATTR_LABEL: "Cloud Cover Night", ATTR_LABEL: "Cloud Cover Night",
ATTR_UNIT_METRIC: UNIT_PERCENTAGE, ATTR_UNIT_METRIC: PERCENTAGE,
ATTR_UNIT_IMPERIAL: UNIT_PERCENTAGE, ATTR_UNIT_IMPERIAL: PERCENTAGE,
}, },
"Grass": { "Grass": {
ATTR_DEVICE_CLASS: None, ATTR_DEVICE_CLASS: None,
@ -130,15 +130,15 @@ FORECAST_SENSOR_TYPES = {
ATTR_DEVICE_CLASS: None, ATTR_DEVICE_CLASS: None,
ATTR_ICON: "mdi:weather-lightning", ATTR_ICON: "mdi:weather-lightning",
ATTR_LABEL: "Thunderstorm Probability Day", ATTR_LABEL: "Thunderstorm Probability Day",
ATTR_UNIT_METRIC: UNIT_PERCENTAGE, ATTR_UNIT_METRIC: PERCENTAGE,
ATTR_UNIT_IMPERIAL: UNIT_PERCENTAGE, ATTR_UNIT_IMPERIAL: PERCENTAGE,
}, },
"ThunderstormProbabilityNight": { "ThunderstormProbabilityNight": {
ATTR_DEVICE_CLASS: None, ATTR_DEVICE_CLASS: None,
ATTR_ICON: "mdi:weather-lightning", ATTR_ICON: "mdi:weather-lightning",
ATTR_LABEL: "Thunderstorm Probability Night", ATTR_LABEL: "Thunderstorm Probability Night",
ATTR_UNIT_METRIC: UNIT_PERCENTAGE, ATTR_UNIT_METRIC: PERCENTAGE,
ATTR_UNIT_IMPERIAL: UNIT_PERCENTAGE, ATTR_UNIT_IMPERIAL: PERCENTAGE,
}, },
"Tree": { "Tree": {
ATTR_DEVICE_CLASS: None, ATTR_DEVICE_CLASS: None,
@ -210,8 +210,8 @@ SENSOR_TYPES = {
ATTR_DEVICE_CLASS: None, ATTR_DEVICE_CLASS: None,
ATTR_ICON: "mdi:weather-cloudy", ATTR_ICON: "mdi:weather-cloudy",
ATTR_LABEL: "Cloud Cover", ATTR_LABEL: "Cloud Cover",
ATTR_UNIT_METRIC: UNIT_PERCENTAGE, ATTR_UNIT_METRIC: PERCENTAGE,
ATTR_UNIT_IMPERIAL: UNIT_PERCENTAGE, ATTR_UNIT_IMPERIAL: PERCENTAGE,
}, },
"DewPoint": { "DewPoint": {
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,

View File

@ -2,7 +2,8 @@
"domain": "accuweather", "domain": "accuweather",
"name": "AccuWeather", "name": "AccuWeather",
"documentation": "https://www.home-assistant.io/integrations/accuweather/", "documentation": "https://www.home-assistant.io/integrations/accuweather/",
"requirements": ["accuweather==0.0.9"], "requirements": ["accuweather==0.0.10"],
"codeowners": ["@bieniu"], "codeowners": ["@bieniu"],
"config_flow": true "config_flow": true,
"quality_scale": "platinum"
} }

View File

@ -5,7 +5,7 @@ from homeassistant.const import (
CONF_NAME, CONF_NAME,
DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_TEMPERATURE,
) )
from homeassistant.helpers.entity import Entity from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import ( from .const import (
ATTR_FORECAST, ATTR_FORECAST,
@ -48,14 +48,14 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
async_add_entities(sensors, False) async_add_entities(sensors, False)
class AccuWeatherSensor(Entity): class AccuWeatherSensor(CoordinatorEntity):
"""Define an AccuWeather entity.""" """Define an AccuWeather entity."""
def __init__(self, name, kind, coordinator, forecast_day=None): def __init__(self, name, kind, coordinator, forecast_day=None):
"""Initialize.""" """Initialize."""
super().__init__(coordinator)
self._name = name self._name = name
self.kind = kind self.kind = kind
self.coordinator = coordinator
self._device_class = None self._device_class = None
self._attrs = {ATTR_ATTRIBUTION: ATTRIBUTION} self._attrs = {ATTR_ATTRIBUTION: ATTRIBUTION}
self._unit_system = "Metric" if self.coordinator.is_metric else "Imperial" self._unit_system = "Metric" if self.coordinator.is_metric else "Imperial"
@ -85,16 +85,6 @@ class AccuWeatherSensor(Entity):
"entry_type": "service", "entry_type": "service",
} }
@property
def should_poll(self):
"""Return the polling requirement of the entity."""
return False
@property
def available(self):
"""Return True if entity is available."""
return self.coordinator.last_update_success
@property @property
def state(self): def state(self):
"""Return the state.""" """Return the state."""
@ -154,11 +144,7 @@ class AccuWeatherSensor(Entity):
def device_state_attributes(self): def device_state_attributes(self):
"""Return the state attributes.""" """Return the state attributes."""
if self.forecast_day is not None: if self.forecast_day is not None:
if self.kind == "WindGustDay": if self.kind in ["WindGustDay", "WindGustNight"]:
self._attrs["direction"] = self.coordinator.data[ATTR_FORECAST][
self.forecast_day
][self.kind]["Direction"]["English"]
elif self.kind == "WindGustNight":
self._attrs["direction"] = self.coordinator.data[ATTR_FORECAST][ self._attrs["direction"] = self.coordinator.data[ATTR_FORECAST][
self.forecast_day self.forecast_day
][self.kind]["Direction"]["English"] ][self.kind]["Direction"]["English"]
@ -177,13 +163,3 @@ class AccuWeatherSensor(Entity):
def entity_registry_enabled_default(self): def entity_registry_enabled_default(self):
"""Return if the entity should be enabled when first added to the entity registry.""" """Return if the entity should be enabled when first added to the entity registry."""
return bool(self.kind not in OPTIONAL_SENSORS) return bool(self.kind not in OPTIONAL_SENSORS)
async def async_added_to_hass(self):
"""Connect to dispatcher listening for entity data notifications."""
self.async_on_remove(
self.coordinator.async_add_listener(self.async_write_ha_state)
)
async def async_update(self):
"""Update AccuWeather entity."""
await self.coordinator.async_request_refresh()

View File

@ -16,7 +16,7 @@
"longitude": "Longitud", "longitude": "Longitud",
"name": "Nom de la integraci\u00f3" "name": "Nom de la integraci\u00f3"
}, },
"description": "Si necessites ajuda amb la configuraci\u00f3, consulta: https://www.home-assistant.io/integrations/accuweather/ \n\n La previsi\u00f3 meteorol\u00f2gica no est\u00e0 habilitada de manera predeterminada. Pots activar-la en les opcions de la integraci\u00f3.", "description": "Si necessites ajuda amb la configuraci\u00f3, consulta els seg\u00fcent enlla\u00e7: https://www.home-assistant.io/integrations/accuweather/ \n\n Alguns sensors no estan activats de manera predeterminada. Els pots activar des del registre d'entitats, despr\u00e9s de la configurraci\u00f3 de la integraci\u00f3.\n La previsi\u00f3 meteorol\u00f2gica no est\u00e0 activada de manera predeterminada. Pots activar-la en les opcions de la integraci\u00f3.",
"title": "AccuWeather" "title": "AccuWeather"
} }
} }

View File

@ -0,0 +1,12 @@
{
"config": {
"step": {
"user": {
"data": {
"latitude": "Zem\u011bpisn\u00e1 \u0161\u00ed\u0159ka",
"longitude": "Zem\u011bpisn\u00e1 d\u00e9lka"
}
}
}
}
}

View File

@ -0,0 +1,12 @@
{
"config": {
"abort": {
"single_instance_allowed": "D\u00e9j\u00e0 configur\u00e9. Une seule configuration possible."
},
"step": {
"user": {
"description": "Si vous avez besoin d'aide pour la configuration, consultez le site suivant : https://www.home-assistant.io/integrations/accuweather/\n\nCertains capteurs ne sont pas activ\u00e9s par d\u00e9faut. Vous pouvez les activer dans le registre des entit\u00e9s apr\u00e8s la configuration de l'int\u00e9gration.\nLes pr\u00e9visions m\u00e9t\u00e9orologiques ne sont pas activ\u00e9es par d\u00e9faut. Vous pouvez l'activer dans les options d'int\u00e9gration."
}
}
}
}

View File

@ -0,0 +1,9 @@
{
"config": {
"step": {
"user": {
"description": "\uad6c\uc131\uc5d0 \ub300\ud55c \ub3c4\uc6c0\uc774 \ud544\uc694\ud55c \uacbd\uc6b0 \ub2e4\uc74c\uc744 \ucc38\uc870\ud574\uc8fc\uc138\uc694:\nhttps://www.home-assistant.io/integrations/accuweather/\n\n\uc77c\ubd80 \uc13c\uc11c\ub294 \uae30\ubcf8\uc801\uc73c\ub85c \ud65c\uc131\ud654\ub418\uc5b4 \uc788\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \uc5f0\ub3d9 \uad6c\uc131 \ud6c4 \uad6c\uc131\uc694\uc18c \ub808\uc9c0\uc2a4\ud2b8\ub9ac\uc5d0\uc11c \ud65c\uc131\ud654\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\n\uc77c\uae30\uc608\ubcf4\ub294 \uae30\ubcf8\uc801\uc73c\ub85c \ud65c\uc131\ud654\ub418\uc5b4 \uc788\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \uc5f0\ub3d9 \uc635\uc158\uc5d0\uc11c \ud65c\uc131\ud654\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4."
}
}
}
}

View File

@ -16,8 +16,7 @@
"longitude": "Lengdegrad", "longitude": "Lengdegrad",
"name": "Navn p\u00e5 integrasjon" "name": "Navn p\u00e5 integrasjon"
}, },
"description": "Hvis du trenger hjelp med konfigurasjonen, kan du se her: https://www.home-assistant.io/integrations/accuweather/ \n\n Noen sensorer er ikke aktivert som standard. Du kan aktivere dem i enhetsregisteret etter integrasjonskonfigurasjonen. \n V\u00e6rmelding er ikke aktivert som standard. Du kan aktivere det i integrasjonsalternativene.", "description": "Hvis du trenger hjelp med konfigurasjonen, kan du se her: https://www.home-assistant.io/integrations/accuweather/ \n\n Noen sensorer er ikke aktivert som standard. Du kan aktivere dem i enhetsregisteret etter integrasjonskonfigurasjonen. \n V\u00e6rmelding er ikke aktivert som standard. Du kan aktivere det i integrasjonsalternativene."
"title": ""
} }
} }
}, },

View File

@ -6,7 +6,7 @@
"error": { "error": {
"cannot_connect": "Nie mo\u017cna nawi\u0105za\u0107 po\u0142\u0105czenia.", "cannot_connect": "Nie mo\u017cna nawi\u0105za\u0107 po\u0142\u0105czenia.",
"invalid_api_key": "Nieprawid\u0142owy klucz API.", "invalid_api_key": "Nieprawid\u0142owy klucz API.",
"requests_exceeded": "Dozwolona liczba zapyta\u0144 do interfejsu API Accuweather zosta\u0142a przekroczona. Musisz poczeka\u0107 lub zmieni\u0107 klucz API." "requests_exceeded": "Dozwolona liczba zapyta\u0144 do interfejsu API AccuWeather zosta\u0142a przekroczona. Musisz poczeka\u0107 lub zmieni\u0107 klucz API."
}, },
"step": { "step": {
"user": { "user": {

View File

@ -0,0 +1,24 @@
{
"config": {
"step": {
"user": {
"data": {
"api_key": "Chave API",
"latitude": "Latitude",
"longitude": "Longitude"
},
"title": "AccuWeather"
}
}
},
"options": {
"step": {
"user": {
"data": {
"forecast": "Previs\u00e3o do Tempo"
},
"description": "Devido \u00e0s limita\u00e7\u00f5es da vers\u00e3o gratuita da chave da API AccuWeather, quando voc\u00ea habilita a previs\u00e3o do tempo, as atualiza\u00e7\u00f5es de dados ser\u00e3o realizadas a cada 64 minutos em vez de a cada 32 minutos."
}
}
}
}

View File

@ -1,8 +1,16 @@
{ {
"config": { "config": {
"abort": {
"single_instance_allowed": "J\u00e1 configurado. Apenas uma \u00fanica configura\u00e7\u00e3o \u00e9 poss\u00edvel."
},
"error": {
"cannot_connect": "Falha na liga\u00e7\u00e3o",
"invalid_api_key": "Chave de API inv\u00e1lida"
},
"step": { "step": {
"user": { "user": {
"data": { "data": {
"api_key": "Chave de API",
"latitude": "Latitude", "latitude": "Latitude",
"longitude": "Longitude" "longitude": "Longitude"
} }

View File

@ -4,7 +4,7 @@
"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." "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": { "error": {
"cannot_connect": "\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f.", "cannot_connect": "\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f.",
"invalid_api_key": "\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 API.", "invalid_api_key": "\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 API.",
"requests_exceeded": "\u041f\u0440\u0435\u0432\u044b\u0448\u0435\u043d\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a API Accuweather. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u0434\u043e\u0436\u0434\u0430\u0442\u044c \u0438\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043a\u043b\u044e\u0447 API." "requests_exceeded": "\u041f\u0440\u0435\u0432\u044b\u0448\u0435\u043d\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a API Accuweather. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u0434\u043e\u0436\u0434\u0430\u0442\u044c \u0438\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043a\u043b\u044e\u0447 API."
}, },

View File

@ -0,0 +1,9 @@
{
"state": {
"accuweather__pressure_tendency": {
"falling": "Disminuint",
"rising": "Augmentant",
"steady": "Estable"
}
}
}

View File

@ -0,0 +1,9 @@
{
"state": {
"accuweather__pressure_tendency": {
"falling": "R\u00e9ckleefeg",
"rising": "Erh\u00e9ijung",
"steady": "Stabil"
}
}
}

View File

@ -0,0 +1,9 @@
{
"state": {
"accuweather__pressure_tendency": {
"falling": "\u4e0b\u964d",
"rising": "\u4e0a\u5347",
"steady": "\u7a69\u5b9a"
}
}
}

View File

@ -16,7 +16,7 @@
"longitude": "\u7d93\u5ea6", "longitude": "\u7d93\u5ea6",
"name": "\u6574\u5408\u540d\u7a31" "name": "\u6574\u5408\u540d\u7a31"
}, },
"description": "\u5047\u5982\u4f60\u9700\u8981\u5354\u52a9\u9032\u884c\u8a2d\u5b9a\uff0c\u8acb\u53c3\u95b1\uff1ahttps://www.home-assistant.io/integrations/accuweather/\n\n\u5929\u6c23\u9810\u5831\u9810\u8a2d\u672a\u958b\u555f\u3002\u53ef\u4ee5\u65bc\u6574\u5408\u9078\u9805\u4e2d\u958b\u555f\u3002", "description": "\u5047\u5982\u4f60\u9700\u8981\u5354\u52a9\u9032\u884c\u8a2d\u5b9a\uff0c\u8acb\u53c3\u95b1\uff1ahttps://www.home-assistant.io/integrations/accuweather/\n\n\u67d0\u4e9b\u50b3\u611f\u5668\u9810\u8a2d\u70ba\u672a\u555f\u7528\uff0c\u53ef\u4ee5\u65bc\u6574\u5408\u8a2d\u5b9a\u4e2d\u555f\u7528\u9019\u4e9b\u5be6\u9ad4\u3002\u5929\u6c23\u9810\u5831\u9810\u8a2d\u672a\u958b\u555f\u3002\u53ef\u4ee5\u65bc\u6574\u5408\u9078\u9805\u4e2d\u958b\u555f\u3002",
"title": "AccuWeather" "title": "AccuWeather"
} }
} }

View File

@ -13,6 +13,7 @@ from homeassistant.components.weather import (
WeatherEntity, WeatherEntity,
) )
from homeassistant.const import CONF_NAME, TEMP_CELSIUS, TEMP_FAHRENHEIT from homeassistant.const import CONF_NAME, TEMP_CELSIUS, TEMP_FAHRENHEIT
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.util.dt import utc_from_timestamp from homeassistant.util.dt import utc_from_timestamp
from .const import ( from .const import (
@ -37,13 +38,13 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
async_add_entities([AccuWeatherEntity(name, coordinator)], False) async_add_entities([AccuWeatherEntity(name, coordinator)], False)
class AccuWeatherEntity(WeatherEntity): class AccuWeatherEntity(CoordinatorEntity, WeatherEntity):
"""Define an AccuWeather entity.""" """Define an AccuWeather entity."""
def __init__(self, name, coordinator): def __init__(self, name, coordinator):
"""Initialize.""" """Initialize."""
super().__init__(coordinator)
self._name = name self._name = name
self.coordinator = coordinator
self._attrs = {} self._attrs = {}
self._unit_system = "Metric" if self.coordinator.is_metric else "Imperial" self._unit_system = "Metric" if self.coordinator.is_metric else "Imperial"
@ -72,16 +73,6 @@ class AccuWeatherEntity(WeatherEntity):
"entry_type": "service", "entry_type": "service",
} }
@property
def should_poll(self):
"""Return the polling requirement of the entity."""
return False
@property
def available(self):
"""Return True if entity is available."""
return self.coordinator.last_update_success
@property @property
def condition(self): def condition(self):
"""Return the current condition.""" """Return the current condition."""
@ -169,16 +160,6 @@ class AccuWeatherEntity(WeatherEntity):
] ]
return forecast return forecast
async def async_added_to_hass(self):
"""Connect to dispatcher listening for entity data notifications."""
self.async_on_remove(
self.coordinator.async_add_listener(self.async_write_ha_state)
)
async def async_update(self):
"""Update AccuWeather entity."""
await self.coordinator.async_request_refresh()
@staticmethod @staticmethod
def _calc_precipitation(day: dict) -> float: def _calc_precipitation(day: dict) -> float:
"""Return sum of the precipitation.""" """Return sum of the precipitation."""

View File

@ -26,10 +26,8 @@ class AcmedaFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
if ( if (
user_input is not None user_input is not None
and self.discovered_hubs is not None and self.discovered_hubs is not None
# pylint: disable=unsupported-membership-test
and user_input["id"] in self.discovered_hubs and user_input["id"] in self.discovered_hubs
): ):
# pylint: disable=unsubscriptable-object
return await self.async_create(self.discovered_hubs[user_input["id"]]) return await self.async_create(self.discovered_hubs[user_input["id"]])
# Already configured hosts # Already configured hosts

View File

@ -37,5 +37,6 @@ async def update_devices(hass, config_entry, api):
) )
if device is not None: if device is not None:
dev_registry.async_update_device( dev_registry.async_update_device(
device.id, name=api_item.name, device.id,
name=api_item.name,
) )

View File

@ -1,5 +1,5 @@
"""Support for Acmeda Roller Blind Batteries.""" """Support for Acmeda Roller Blind Batteries."""
from homeassistant.const import DEVICE_CLASS_BATTERY, UNIT_PERCENTAGE from homeassistant.const import DEVICE_CLASS_BATTERY, PERCENTAGE
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
@ -33,7 +33,7 @@ class AcmedaBattery(AcmedaBase):
"""Representation of a Acmeda cover device.""" """Representation of a Acmeda cover device."""
device_class = DEVICE_CLASS_BATTERY device_class = DEVICE_CLASS_BATTERY
unit_of_measurement = UNIT_PERCENTAGE unit_of_measurement = PERCENTAGE
@property @property
def name(self): def name(self):

View File

@ -11,6 +11,5 @@
"title": "Velg en hub du vil legge til" "title": "Velg en hub du vil legge til"
} }
} }
}, }
"title": ""
} }

View File

@ -11,7 +11,7 @@ from homeassistant.components.adguard.const import (
DOMAIN, DOMAIN,
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import TIME_MILLISECONDS, UNIT_PERCENTAGE from homeassistant.const import PERCENTAGE, TIME_MILLISECONDS
from homeassistant.exceptions import PlatformNotReady from homeassistant.exceptions import PlatformNotReady
from homeassistant.helpers.typing import HomeAssistantType from homeassistant.helpers.typing import HomeAssistantType
@ -134,7 +134,7 @@ class AdGuardHomePercentageBlockedSensor(AdGuardHomeSensor):
"AdGuard DNS Queries Blocked Ratio", "AdGuard DNS Queries Blocked Ratio",
"mdi:magnify-close", "mdi:magnify-close",
"blocked_percentage", "blocked_percentage",
UNIT_PERCENTAGE, PERCENTAGE,
) )
async def _adguard_update(self) -> None: async def _adguard_update(self) -> None:

View File

@ -1,8 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"adguard_home_addon_outdated": "\u0422\u0430\u0437\u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0438\u0437\u0438\u0441\u043a\u0432\u0430 AdGuard Home {minimal_version} \u0438\u043b\u0438 \u043f\u043e-\u043d\u043e\u0432\u0430 {minimal_version}, \u0438\u043c\u0430\u0442\u0435 {current_version}. \u041c\u043e\u043b\u044f, \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u0439\u0442\u0435 \u0432\u0430\u0448\u0430\u0442\u0430 \u0434\u043e\u0431\u0430\u0432\u043a\u0430 \u0437\u0430 Hass.io AdGuard Home.",
"adguard_home_outdated": "\u0422\u0430\u0437\u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0438\u0437\u0438\u0441\u043a\u0432\u0430 AdGuard Home {minimal_version} \u0438\u043b\u0438 \u043f\u043e-\u043d\u043e\u0432\u0430 {minimal_version}, \u0438\u043c\u0430\u0442\u0435 {current_version}.",
"existing_instance_updated": "\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0449\u0430\u0442\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f.", "existing_instance_updated": "\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0449\u0430\u0442\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f.",
"single_instance_allowed": "\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0430 \u0435 \u0441\u0430\u043c\u043e \u0435\u0434\u043d\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043d\u0430 AdGuard Home." "single_instance_allowed": "\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0430 \u0435 \u0441\u0430\u043c\u043e \u0435\u0434\u043d\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043d\u0430 AdGuard Home."
}, },

View File

@ -1,8 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"adguard_home_addon_outdated": "Aquesta integraci\u00f3 necessita la versi\u00f3 d'AdGuard Home {minimal_version} o una superior, tens la {current_version}. Actualitza el complement de Hass.io d'AdGuard Home.",
"adguard_home_outdated": "Aquesta integraci\u00f3 necessita la versi\u00f3 d'AdGuard Home {minimal_version} o una superior, tens la {current_version}.",
"existing_instance_updated": "S'ha actualitzat la configuraci\u00f3 existent.", "existing_instance_updated": "S'ha actualitzat la configuraci\u00f3 existent.",
"single_instance_allowed": "Nom\u00e9s es permet una \u00fanica configuraci\u00f3 d'AdGuard Home." "single_instance_allowed": "Nom\u00e9s es permet una \u00fanica configuraci\u00f3 d'AdGuard Home."
}, },

View File

@ -1,8 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"adguard_home_addon_outdated": "Denne integration kr\u00e6ver AdGuard Home {minimal_version} eller h\u00f8jere, du har {current_version}. Opdater venligst din Hass.io AdGuard Home-tilf\u00f8jelse.",
"adguard_home_outdated": "Denne integration kr\u00e6ver AdGuard Home {minimal_version} eller h\u00f8jere, du har {current_version}.",
"existing_instance_updated": "Opdaterede eksisterende konfiguration.", "existing_instance_updated": "Opdaterede eksisterende konfiguration.",
"single_instance_allowed": "Kun en enkelt konfiguration af AdGuard Home er tilladt." "single_instance_allowed": "Kun en enkelt konfiguration af AdGuard Home er tilladt."
}, },

View File

@ -1,8 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"adguard_home_addon_outdated": "Diese Integration erfordert AdGuard Home {minimal_version} oder h\u00f6her, du hast {current_version}. Bitte aktualisiere dein Hass.io AdGuard Home Add-on.",
"adguard_home_outdated": "Diese Integration erfordert AdGuard Home {minimal_version} oder h\u00f6her, du hast {current_version}.",
"existing_instance_updated": "Bestehende Konfiguration wurde aktualisiert.", "existing_instance_updated": "Bestehende Konfiguration wurde aktualisiert.",
"single_instance_allowed": "Es ist nur eine einzige Konfiguration von AdGuard Home zul\u00e4ssig." "single_instance_allowed": "Es ist nur eine einzige Konfiguration von AdGuard Home zul\u00e4ssig."
}, },

View File

@ -1,8 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"adguard_home_addon_outdated": "This integration requires AdGuard Home {minimal_version} or higher, you have {current_version}. Please update your Hass.io AdGuard Home add-on.",
"adguard_home_outdated": "This integration requires AdGuard Home {minimal_version} or higher, you have {current_version}.",
"existing_instance_updated": "Updated existing configuration.", "existing_instance_updated": "Updated existing configuration.",
"single_instance_allowed": "Only a single configuration of AdGuard Home is allowed." "single_instance_allowed": "Only a single configuration of AdGuard Home is allowed."
}, },

View File

@ -1,8 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"adguard_home_addon_outdated": "Esta integraci\u00f3n requiere AdGuard Home {minimal_version} o superior, tiene {current_version}. Actualice su complemento Hass.io AdGuard Home.",
"adguard_home_outdated": "Esta integraci\u00f3n requiere AdGuard Home {minimal_version} o superior, tiene {current_version}.",
"existing_instance_updated": "Se actualiz\u00f3 la configuraci\u00f3n existente.", "existing_instance_updated": "Se actualiz\u00f3 la configuraci\u00f3n existente.",
"single_instance_allowed": "Solo se permite una \u00fanica configuraci\u00f3n de AdGuard Home." "single_instance_allowed": "Solo se permite una \u00fanica configuraci\u00f3n de AdGuard Home."
}, },

View File

@ -1,8 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"adguard_home_addon_outdated": "Esta integraci\u00f3n requiere AdGuard Home {minimal_version} o superior, usted tiene {current_version}. Por favor, actualice su complemento Hass.io AdGuard Home.",
"adguard_home_outdated": "Esta integraci\u00f3n requiere AdGuard Home {minimal_version} o superior, usted tiene {current_version}.",
"existing_instance_updated": "Se ha actualizado la configuraci\u00f3n existente.", "existing_instance_updated": "Se ha actualizado la configuraci\u00f3n existente.",
"single_instance_allowed": "S\u00f3lo se permite una \u00fanica configuraci\u00f3n de AdGuard Home." "single_instance_allowed": "S\u00f3lo se permite una \u00fanica configuraci\u00f3n de AdGuard Home."
}, },

View File

@ -1,8 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"adguard_home_addon_outdated": "Cette int\u00e9gration n\u00e9cessite AdGuard Home {minimal_version} ou une version ult\u00e9rieure, vous disposez de {current_version}. Veuillez mettre \u00e0 jour votre compl\u00e9ment Hass.io AdGuard Home.",
"adguard_home_outdated": "Cette int\u00e9gration n\u00e9cessite AdGuard Home {minimal_version} ou une version ult\u00e9rieure, vous disposez de {current_version}.",
"existing_instance_updated": "La configuration existante a \u00e9t\u00e9 mise \u00e0 jour.", "existing_instance_updated": "La configuration existante a \u00e9t\u00e9 mise \u00e0 jour.",
"single_instance_allowed": "Une seule configuration d'AdGuard Home est autoris\u00e9e." "single_instance_allowed": "Une seule configuration d'AdGuard Home est autoris\u00e9e."
}, },

View File

@ -1,8 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"adguard_home_addon_outdated": "Questa integrazione richiede AdGuard Home {minimal_version} o versione successiva, si dispone di {current_version}. Aggiorna il componente aggiuntivo AdGuard Home di Hass.io.",
"adguard_home_outdated": "Questa integrazione richiede AdGuard Home {minimal_version} o versione successiva, si dispone di {current_version}.",
"existing_instance_updated": "Configurazione esistente aggiornata.", "existing_instance_updated": "Configurazione esistente aggiornata.",
"single_instance_allowed": "\u00c8 consentita solo una singola configurazione di AdGuard Home." "single_instance_allowed": "\u00c8 consentita solo una singola configurazione di AdGuard Home."
}, },

View File

@ -1,8 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"adguard_home_addon_outdated": "\uc774 \ud1b5\ud569 \uad6c\uc131\uc694\uc18c\ub294 AdGuard Home {minimal_version} \uc774\uc0c1\uc774 \ud544\uc694\ud569\ub2c8\ub2e4. \ud604\uc7ac \ubc84\uc804\uc740 {current_version} \uc785\ub2c8\ub2e4. Hass.io AdGuard Home \uc560\ub4dc\uc628\uc744 \uc5c5\ub370\uc774\ud2b8 \ud574\uc8fc\uc138\uc694.",
"adguard_home_outdated": "\uc774 \ud1b5\ud569 \uad6c\uc131\uc694\uc18c\ub294 AdGuard Home {minimal_version} \uc774\uc0c1\uc774 \ud544\uc694\ud569\ub2c8\ub2e4. \ud604\uc7ac \ubc84\uc804\uc740 {current_version} \uc785\ub2c8\ub2e4.",
"existing_instance_updated": "\uae30\uc874 \uad6c\uc131\uc744 \uc5c5\ub370\uc774\ud2b8\ud588\uc2b5\ub2c8\ub2e4.", "existing_instance_updated": "\uae30\uc874 \uad6c\uc131\uc744 \uc5c5\ub370\uc774\ud2b8\ud588\uc2b5\ub2c8\ub2e4.",
"single_instance_allowed": "\ud558\ub098\uc758 AdGuard Home \ub9cc \uad6c\uc131\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4." "single_instance_allowed": "\ud558\ub098\uc758 AdGuard Home \ub9cc \uad6c\uc131\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4."
}, },

View File

@ -1,8 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"adguard_home_addon_outdated": "D\u00ebs Integratioun ben\u00e9idegt AdgGuard Home {minimal_version} oder m\u00e9i, dir hutt {current_version}. Aktualis\u00e9iert w.e.g. \u00e4ren Hass.io AdGuard Home Add-on.",
"adguard_home_outdated": "D\u00ebs Integratioun ben\u00e9idegt AdgGuard Home {minimal_version} oder m\u00e9i, dir hutt {current_version}.",
"existing_instance_updated": "D\u00e9i bestehend Konfiguratioun ass ge\u00e4nnert.", "existing_instance_updated": "D\u00e9i bestehend Konfiguratioun ass ge\u00e4nnert.",
"single_instance_allowed": "N\u00ebmmen eng eenzeg Konfiguratioun vun AdGuard Home ass erlaabt." "single_instance_allowed": "N\u00ebmmen eng eenzeg Konfiguratioun vun AdGuard Home ass erlaabt."
}, },

View File

@ -1,8 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"adguard_home_addon_outdated": "Deze integratie vereist AdGuard Home {minimal_version} of hoger, u heeft {current_version}. Update uw Hass.io AdGuard Home-add-on.",
"adguard_home_outdated": "Deze integratie vereist AdGuard Home {minimal_version} of hoger, u heeft {current_version}.",
"existing_instance_updated": "Bestaande configuratie bijgewerkt.", "existing_instance_updated": "Bestaande configuratie bijgewerkt.",
"single_instance_allowed": "Slechts \u00e9\u00e9n configuratie van AdGuard Home is toegestaan." "single_instance_allowed": "Slechts \u00e9\u00e9n configuratie van AdGuard Home is toegestaan."
}, },

View File

@ -1,8 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"adguard_home_addon_outdated": "Denne integrasjonen krever AdGuard Home {minimal_version} eller h\u00f8yere, du har {current_version}. Vennligst oppdater Hass.io AdGuard Home-tillegget.",
"adguard_home_outdated": "Denne integrasjonen krever AdGuard Home {minimal_version} eller h\u00f8yere, du har {current_version}.",
"existing_instance_updated": "Oppdatert eksisterende konfigurasjon.", "existing_instance_updated": "Oppdatert eksisterende konfigurasjon.",
"single_instance_allowed": "Kun en konfigurasjon av AdGuard Hjemer tillatt." "single_instance_allowed": "Kun en konfigurasjon av AdGuard Hjemer tillatt."
}, },
@ -18,7 +16,6 @@
"data": { "data": {
"host": "Vert", "host": "Vert",
"password": "Passord", "password": "Passord",
"port": "",
"ssl": "AdGuard Hjem bruker et SSL-sertifikat", "ssl": "AdGuard Hjem bruker et SSL-sertifikat",
"username": "Brukernavn", "username": "Brukernavn",
"verify_ssl": "AdGuard Home bruker et riktig sertifikat" "verify_ssl": "AdGuard Home bruker et riktig sertifikat"

View File

@ -1,8 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"adguard_home_addon_outdated": "Ta integracja wymaga AdGuard Home {minimal_version} lub nowszej wersji, masz {current_version}. Zaktualizuj sw\u00f3j dodatek Hass.io AdGuard Home.",
"adguard_home_outdated": "Ta integracja wymaga AdGuard Home {minimal_version} lub nowszej wersji, masz {current_version}.",
"existing_instance_updated": "Zaktualizowano istniej\u0105c\u0105 konfiguracj\u0119.", "existing_instance_updated": "Zaktualizowano istniej\u0105c\u0105 konfiguracj\u0119.",
"single_instance_allowed": "Dozwolona jest tylko jedna konfiguracja AdGuard Home." "single_instance_allowed": "Dozwolona jest tylko jedna konfiguracja AdGuard Home."
}, },

View File

@ -16,7 +16,7 @@
"data": { "data": {
"password": "Senha", "password": "Senha",
"ssl": "O AdGuard Home usa um certificado SSL", "ssl": "O AdGuard Home usa um certificado SSL",
"username": "Nome de usu\u00e1rio", "username": "Usu\u00e1rio",
"verify_ssl": "O AdGuard Home usa um certificado apropriado" "verify_ssl": "O AdGuard Home usa um certificado apropriado"
}, },
"description": "Configure sua inst\u00e2ncia do AdGuard Home para permitir o monitoramento e o controle." "description": "Configure sua inst\u00e2ncia do AdGuard Home para permitir o monitoramento e o controle."

View File

@ -1,8 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"adguard_home_addon_outdated": "\u042d\u0442\u0430 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 AdGuard Home \u0432\u0435\u0440\u0441\u0438\u0438 {current_version}. \u0414\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432\u0435\u0440\u0441\u0438\u044f {minimal_version}, \u0438\u043b\u0438 \u0431\u043e\u043b\u0435\u0435 \u043d\u043e\u0432\u0430\u044f. \u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438, \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 Hass.io.",
"adguard_home_outdated": "\u042d\u0442\u0430 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 AdGuard Home \u0432\u0435\u0440\u0441\u0438\u0438 {current_version}. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0432\u0435\u0440\u0441\u0438\u044e {minimal_version} \u0438\u043b\u0438 \u0431\u043e\u043b\u0435\u0435 \u043d\u043e\u0432\u0443\u044e.",
"existing_instance_updated": "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0430.", "existing_instance_updated": "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0430.",
"single_instance_allowed": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0443\u0436\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430." "single_instance_allowed": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0443\u0436\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430."
}, },

View File

@ -1,8 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"adguard_home_addon_outdated": "Za to integracijo je potrebna AdGuard Home {minimal_version} ali vi\u0161ja, vi imate {current_version}. Prosimo posodobite va\u0161 hass.io AdGuard Home dodatek.",
"adguard_home_outdated": "Za to integracijo je potrebna AdGuard Home {minimal_version} ali vi\u0161ja, vi imate {current_version}.",
"existing_instance_updated": "Posodobljena obstoje\u010da konfiguracija.", "existing_instance_updated": "Posodobljena obstoje\u010da konfiguracija.",
"single_instance_allowed": "Dovoljena je samo ena konfiguracija AdGuard Home." "single_instance_allowed": "Dovoljena je samo ena konfiguracija AdGuard Home."
}, },

View File

@ -1,8 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"adguard_home_addon_outdated": "Den h\u00e4r integrationen kr\u00e4ver AdGuard Home {minimal_version} eller senare, du har {current_version}. Uppdatera ditt Hass.io AdGuard Home-till\u00e4gg.",
"adguard_home_outdated": "Den h\u00e4r integrationen kr\u00e4ver AdGuard Home {minimal_version} eller senare, du har {current_version}.",
"existing_instance_updated": "Uppdaterade existerande konfiguration.", "existing_instance_updated": "Uppdaterade existerande konfiguration.",
"single_instance_allowed": "Endast en enda konfiguration av AdGuard Home \u00e4r till\u00e5ten." "single_instance_allowed": "Endast en enda konfiguration av AdGuard Home \u00e4r till\u00e5ten."
}, },

View File

@ -1,8 +1,6 @@
{ {
"config": { "config": {
"abort": { "abort": {
"adguard_home_addon_outdated": "\u6574\u5408\u9700\u8981 AdGuard Home {minimal_version} \u6216\u66f4\u65b0\u7248\u672c\uff0c\u60a8\u76ee\u524d\u4f7f\u7528\u7248\u672c\u70ba {current_version}\u3002\u8acb\u66f4\u65b0 Hass.io AdGuard Home \u5143\u4ef6\u3002",
"adguard_home_outdated": "\u6574\u5408\u9700\u8981 AdGuard Home {minimal_version} \u6216\u66f4\u65b0\u7248\u672c\uff0c\u60a8\u76ee\u524d\u4f7f\u7528\u7248\u672c\u70ba {current_version}\u3002",
"existing_instance_updated": "\u5df2\u66f4\u65b0\u73fe\u6709\u8a2d\u5b9a\u3002", "existing_instance_updated": "\u5df2\u66f4\u65b0\u73fe\u6709\u8a2d\u5b9a\u3002",
"single_instance_allowed": "\u50c5\u5141\u8a31\u8a2d\u5b9a\u4e00\u7d44 AdGuard Home\u3002" "single_instance_allowed": "\u50c5\u5141\u8a31\u8a2d\u5b9a\u4e00\u7d44 AdGuard Home\u3002"
}, },

View File

@ -2,6 +2,6 @@
"domain": "ads", "domain": "ads",
"name": "ADS", "name": "ADS",
"documentation": "https://www.home-assistant.io/integrations/ads", "documentation": "https://www.home-assistant.io/integrations/ads",
"requirements": ["pyads==3.2.1"], "requirements": ["pyads==3.2.2"],
"codeowners": [] "codeowners": []
} }

View File

@ -16,7 +16,7 @@ DEFAULT_BRAND = "Agent DVR by ispyconnect.com"
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
FORWARDS = ["camera"] FORWARDS = ["alarm_control_panel", "camera"]
async def async_setup(hass, config): async def async_setup(hass, config):
@ -33,9 +33,9 @@ async def async_setup_entry(hass, config_entry):
agent_client = Agent(server_origin, async_get_clientsession(hass)) agent_client = Agent(server_origin, async_get_clientsession(hass))
try: try:
await agent_client.update() await agent_client.update()
except AgentError: except AgentError as err:
await agent_client.close() await agent_client.close()
raise ConfigEntryNotReady raise ConfigEntryNotReady from err
if not agent_client.is_available: if not agent_client.is_available:
raise ConfigEntryNotReady raise ConfigEntryNotReady

View File

@ -0,0 +1,124 @@
"""Support for Agent DVR Alarm Control Panels."""
from homeassistant.components.alarm_control_panel import AlarmControlPanelEntity
from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY,
SUPPORT_ALARM_ARM_HOME,
SUPPORT_ALARM_ARM_NIGHT,
)
from homeassistant.const import (
STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_HOME,
STATE_ALARM_ARMED_NIGHT,
STATE_ALARM_DISARMED,
)
from .const import CONNECTION, DOMAIN as AGENT_DOMAIN
ICON = "mdi:security"
CONF_HOME_MODE_NAME = "home"
CONF_AWAY_MODE_NAME = "away"
CONF_NIGHT_MODE_NAME = "night"
CONST_ALARM_CONTROL_PANEL_NAME = "Alarm Panel"
async def async_setup_entry(
hass, config_entry, async_add_entities, discovery_info=None
):
"""Set up the Agent DVR Alarm Control Panels."""
async_add_entities(
[AgentBaseStation(hass.data[AGENT_DOMAIN][config_entry.entry_id][CONNECTION])]
)
class AgentBaseStation(AlarmControlPanelEntity):
"""Representation of an Agent DVR Alarm Control Panel."""
def __init__(self, client):
"""Initialize the alarm control panel."""
self._state = None
self._client = client
self._unique_id = f"{client.unique}_CP"
name = CONST_ALARM_CONTROL_PANEL_NAME
self._name = name = f"{client.name} {name}"
@property
def icon(self):
"""Return icon."""
return ICON
@property
def state(self):
"""Return the state of the device."""
return self._state
@property
def supported_features(self) -> int:
"""Return the list of supported features."""
return SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_AWAY | SUPPORT_ALARM_ARM_NIGHT
@property
def device_info(self):
"""Return the device info for adding the entity to the agent object."""
return {
"identifiers": {(AGENT_DOMAIN, self._client.unique)},
"manufacturer": "Agent",
"model": CONST_ALARM_CONTROL_PANEL_NAME,
"sw_version": self._client.version,
}
async def async_update(self):
"""Update the state of the device."""
await self._client.update()
armed = self._client.is_armed
if armed is None:
self._state = None
return
if armed:
prof = (await self._client.get_active_profile()).lower()
self._state = STATE_ALARM_ARMED_AWAY
if prof == CONF_HOME_MODE_NAME:
self._state = STATE_ALARM_ARMED_HOME
elif prof == CONF_NIGHT_MODE_NAME:
self._state = STATE_ALARM_ARMED_NIGHT
else:
self._state = STATE_ALARM_DISARMED
async def async_alarm_disarm(self, code=None):
"""Send disarm command."""
await self._client.disarm()
self._state = STATE_ALARM_DISARMED
async def async_alarm_arm_away(self, code=None):
"""Send arm away command. Uses custom mode."""
await self._client.arm()
await self._client.set_active_profile(CONF_AWAY_MODE_NAME)
self._state = STATE_ALARM_ARMED_AWAY
async def async_alarm_arm_home(self, code=None):
"""Send arm home command. Uses custom mode."""
await self._client.arm()
await self._client.set_active_profile(CONF_HOME_MODE_NAME)
self._state = STATE_ALARM_ARMED_HOME
async def async_alarm_arm_night(self, code=None):
"""Send arm night command. Uses custom mode."""
await self._client.arm()
await self._client.set_active_profile(CONF_NIGHT_MODE_NAME)
self._state = STATE_ALARM_ARMED_NIGHT
@property
def name(self):
"""Return the name of the base station."""
return self._name
@property
def available(self) -> bool:
"""Device available."""
return self._client.is_available
@property
def unique_id(self) -> str:
"""Return a unique ID."""
return self._unique_id

View File

@ -10,8 +10,7 @@
"step": { "step": {
"user": { "user": {
"data": { "data": {
"host": "Vert", "host": "Vert"
"port": ""
}, },
"title": "Konfigurere Agent DVR" "title": "Konfigurere Agent DVR"
} }

View File

@ -2,6 +2,13 @@
"config": { "config": {
"error": { "error": {
"device_unavailable": "O dispositivo n\u00e3o est\u00e1 dispon\u00edvel" "device_unavailable": "O dispositivo n\u00e3o est\u00e1 dispon\u00edvel"
},
"step": {
"user": {
"data": {
"port": "Porta"
}
}
} }
} }
} }

View File

@ -125,7 +125,7 @@ class AirlyDataUpdateCoordinator(DataUpdateCoordinator):
try: try:
await measurements.update() await measurements.update()
except (AirlyError, ClientConnectorError) as error: except (AirlyError, ClientConnectorError) as error:
raise UpdateFailed(error) raise UpdateFailed(error) from error
values = measurements.current["values"] values = measurements.current["values"]
index = measurements.current["indexes"][0] index = measurements.current["indexes"][0]

View File

@ -6,6 +6,7 @@ from homeassistant.components.air_quality import (
AirQualityEntity, AirQualityEntity,
) )
from homeassistant.const import CONF_NAME from homeassistant.const import CONF_NAME
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import ( from .const import (
ATTR_API_ADVICE, ATTR_API_ADVICE,
@ -57,12 +58,12 @@ def round_state(func):
return _decorator return _decorator
class AirlyAirQuality(AirQualityEntity): class AirlyAirQuality(CoordinatorEntity, AirQualityEntity):
"""Define an Airly air quality.""" """Define an Airly air quality."""
def __init__(self, coordinator, name): def __init__(self, coordinator, name):
"""Initialize.""" """Initialize."""
self.coordinator = coordinator super().__init__(coordinator)
self._name = name self._name = name
self._icon = "mdi:blur" self._icon = "mdi:blur"
@ -71,11 +72,6 @@ class AirlyAirQuality(AirQualityEntity):
"""Return the name.""" """Return the name."""
return self._name return self._name
@property
def should_poll(self):
"""Return the polling requirement of the entity."""
return False
@property @property
def icon(self): def icon(self):
"""Return the icon.""" """Return the icon."""
@ -121,11 +117,6 @@ class AirlyAirQuality(AirQualityEntity):
"entry_type": "service", "entry_type": "service",
} }
@property
def available(self):
"""Return True if entity is available."""
return self.coordinator.last_update_success
@property @property
def device_state_attributes(self): def device_state_attributes(self):
"""Return the state attributes.""" """Return the state attributes."""
@ -138,13 +129,3 @@ class AirlyAirQuality(AirQualityEntity):
LABEL_PM_10_LIMIT: self.coordinator.data[ATTR_API_PM10_LIMIT], LABEL_PM_10_LIMIT: self.coordinator.data[ATTR_API_PM10_LIMIT],
LABEL_PM_10_PERCENT: round(self.coordinator.data[ATTR_API_PM10_PERCENT]), LABEL_PM_10_PERCENT: round(self.coordinator.data[ATTR_API_PM10_PERCENT]),
} }
async def async_added_to_hass(self):
"""Connect to dispatcher listening for entity data notifications."""
self.async_on_remove(
self.coordinator.async_add_listener(self.async_write_ha_state)
)
async def async_update(self):
"""Update Airly entity."""
await self.coordinator.async_request_refresh()

View File

@ -7,11 +7,11 @@ from homeassistant.const import (
DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_HUMIDITY,
DEVICE_CLASS_PRESSURE, DEVICE_CLASS_PRESSURE,
DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_TEMPERATURE,
PERCENTAGE,
PRESSURE_HPA, PRESSURE_HPA,
TEMP_CELSIUS, TEMP_CELSIUS,
UNIT_PERCENTAGE,
) )
from homeassistant.helpers.entity import Entity from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import ( from .const import (
ATTR_API_HUMIDITY, ATTR_API_HUMIDITY,
@ -42,7 +42,7 @@ SENSOR_TYPES = {
ATTR_DEVICE_CLASS: DEVICE_CLASS_HUMIDITY, ATTR_DEVICE_CLASS: DEVICE_CLASS_HUMIDITY,
ATTR_ICON: None, ATTR_ICON: None,
ATTR_LABEL: ATTR_API_HUMIDITY.capitalize(), ATTR_LABEL: ATTR_API_HUMIDITY.capitalize(),
ATTR_UNIT: UNIT_PERCENTAGE, ATTR_UNIT: PERCENTAGE,
}, },
ATTR_API_PRESSURE: { ATTR_API_PRESSURE: {
ATTR_DEVICE_CLASS: DEVICE_CLASS_PRESSURE, ATTR_DEVICE_CLASS: DEVICE_CLASS_PRESSURE,
@ -72,12 +72,12 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
async_add_entities(sensors, False) async_add_entities(sensors, False)
class AirlySensor(Entity): class AirlySensor(CoordinatorEntity):
"""Define an Airly sensor.""" """Define an Airly sensor."""
def __init__(self, coordinator, name, kind): def __init__(self, coordinator, name, kind):
"""Initialize.""" """Initialize."""
self.coordinator = coordinator super().__init__(coordinator)
self._name = name self._name = name
self.kind = kind self.kind = kind
self._device_class = None self._device_class = None
@ -91,11 +91,6 @@ class AirlySensor(Entity):
"""Return the name.""" """Return the name."""
return f"{self._name} {SENSOR_TYPES[self.kind][ATTR_LABEL]}" return f"{self._name} {SENSOR_TYPES[self.kind][ATTR_LABEL]}"
@property
def should_poll(self):
"""Return the polling requirement of the entity."""
return False
@property @property
def state(self): def state(self):
"""Return the state.""" """Return the state."""
@ -143,18 +138,3 @@ class AirlySensor(Entity):
def unit_of_measurement(self): def unit_of_measurement(self):
"""Return the unit the value is expressed in.""" """Return the unit the value is expressed in."""
return SENSOR_TYPES[self.kind][ATTR_UNIT] return SENSOR_TYPES[self.kind][ATTR_UNIT]
@property
def available(self):
"""Return True if entity is available."""
return self.coordinator.last_update_success
async def async_added_to_hass(self):
"""Connect to dispatcher listening for entity data notifications."""
self.async_on_remove(
self.coordinator.async_add_listener(self.async_write_ha_state)
)
async def async_update(self):
"""Update Airly entity."""
await self.coordinator.async_request_refresh()

View File

@ -10,7 +10,7 @@
"step": { "step": {
"user": { "user": {
"data": { "data": {
"api_key": "Cl\u00e9 API Airly", "api_key": "Cl\u00e9 d'API",
"latitude": "Latitude", "latitude": "Latitude",
"longitude": "Longitude", "longitude": "Longitude",
"name": "Nom de l'int\u00e9gration" "name": "Nom de l'int\u00e9gration"

View File

@ -15,8 +15,7 @@
"longitude": "Lengdegrad", "longitude": "Lengdegrad",
"name": "Navn p\u00e5 integrasjonen" "name": "Navn p\u00e5 integrasjonen"
}, },
"description": "Sett opp Airly luftkvalitet integrasjon. For \u00e5 opprette API-n\u00f8kkel, g\u00e5 til [https://developer.airly.eu/register](https://developer.airly.eu/register)", "description": "Sett opp Airly luftkvalitet integrasjon. For \u00e5 opprette API-n\u00f8kkel, g\u00e5 til [https://developer.airly.eu/register](https://developer.airly.eu/register)"
"title": ""
} }
} }
} }

View File

@ -3,11 +3,9 @@
"step": { "step": {
"user": { "user": {
"data": { "data": {
"api_key": "",
"latitude": "Latitude", "latitude": "Latitude",
"longitude": "Longitude" "longitude": "Longitude"
}, }
"title": ""
} }
} }
} }

View File

@ -20,8 +20,11 @@ from homeassistant.const import (
) )
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers import aiohttp_client, config_validation as cv from homeassistant.helpers import aiohttp_client, config_validation as cv
from homeassistant.helpers.entity import Entity from homeassistant.helpers.update_coordinator import (
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed CoordinatorEntity,
DataUpdateCoordinator,
UpdateFailed,
)
from .const import ( from .const import (
CONF_CITY, CONF_CITY,
@ -220,13 +223,14 @@ async def async_setup_entry(hass, config_entry):
) )
else: else:
api_coro = client.api.nearest_city( api_coro = client.api.nearest_city(
config_entry.data[CONF_LATITUDE], config_entry.data[CONF_LONGITUDE], config_entry.data[CONF_LATITUDE],
config_entry.data[CONF_LONGITUDE],
) )
try: try:
return await api_coro return await api_coro
except AirVisualError as err: except AirVisualError as err:
raise UpdateFailed(f"Error while retrieving data: {err}") raise UpdateFailed(f"Error while retrieving data: {err}") from err
coordinator = DataUpdateCoordinator( coordinator = DataUpdateCoordinator(
hass, hass,
@ -262,7 +266,7 @@ async def async_setup_entry(hass, config_entry):
include_trends=False, include_trends=False,
) )
except NodeProError as err: except NodeProError as err:
raise UpdateFailed(f"Error while retrieving data: {err}") raise UpdateFailed(f"Error while retrieving data: {err}") from err
coordinator = DataUpdateCoordinator( coordinator = DataUpdateCoordinator(
hass, hass,
@ -350,20 +354,15 @@ async def async_update_options(hass, config_entry):
await coordinator.async_request_refresh() await coordinator.async_request_refresh()
class AirVisualEntity(Entity): class AirVisualEntity(CoordinatorEntity):
"""Define a generic AirVisual entity.""" """Define a generic AirVisual entity."""
def __init__(self, coordinator): def __init__(self, coordinator):
"""Initialize.""" """Initialize."""
super().__init__(coordinator)
self._attrs = {ATTR_ATTRIBUTION: DEFAULT_ATTRIBUTION} self._attrs = {ATTR_ATTRIBUTION: DEFAULT_ATTRIBUTION}
self._icon = None self._icon = None
self._unit = None self._unit = None
self.coordinator = coordinator
@property
def available(self):
"""Return if entity is available."""
return self.coordinator.last_update_success
@property @property
def device_state_attributes(self): def device_state_attributes(self):
@ -375,11 +374,6 @@ class AirVisualEntity(Entity):
"""Return the icon.""" """Return the icon."""
return self._icon return self._icon
@property
def should_poll(self) -> bool:
"""Disable polling."""
return False
@property @property
def unit_of_measurement(self): def unit_of_measurement(self):
"""Return the unit the value is expressed in.""" """Return the unit the value is expressed in."""
@ -398,13 +392,6 @@ class AirVisualEntity(Entity):
self.update_from_latest_data() self.update_from_latest_data()
async def async_update(self):
"""Update the entity.
Only used by the generic entity update service.
"""
await self.coordinator.async_request_refresh()
@callback @callback
def update_from_latest_data(self): def update_from_latest_data(self):
"""Update the entity from the latest data.""" """Update the entity from the latest data."""

View File

@ -15,8 +15,8 @@ from homeassistant.const import (
DEVICE_CLASS_BATTERY, DEVICE_CLASS_BATTERY,
DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_HUMIDITY,
DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_TEMPERATURE,
PERCENTAGE,
TEMP_CELSIUS, TEMP_CELSIUS,
UNIT_PERCENTAGE,
) )
from homeassistant.core import callback from homeassistant.core import callback
@ -57,8 +57,8 @@ GEOGRAPHY_SENSORS = [
GEOGRAPHY_SENSOR_LOCALES = {"cn": "Chinese", "us": "U.S."} GEOGRAPHY_SENSOR_LOCALES = {"cn": "Chinese", "us": "U.S."}
NODE_PRO_SENSORS = [ NODE_PRO_SENSORS = [
(SENSOR_KIND_BATTERY_LEVEL, "Battery", DEVICE_CLASS_BATTERY, UNIT_PERCENTAGE), (SENSOR_KIND_BATTERY_LEVEL, "Battery", DEVICE_CLASS_BATTERY, PERCENTAGE),
(SENSOR_KIND_HUMIDITY, "Humidity", DEVICE_CLASS_HUMIDITY, UNIT_PERCENTAGE), (SENSOR_KIND_HUMIDITY, "Humidity", DEVICE_CLASS_HUMIDITY, PERCENTAGE),
(SENSOR_KIND_TEMPERATURE, "Temperature", DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS), (SENSOR_KIND_TEMPERATURE, "Temperature", DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS),
] ]
@ -98,7 +98,13 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
if config_entry.data[CONF_INTEGRATION_TYPE] == INTEGRATION_TYPE_GEOGRAPHY: if config_entry.data[CONF_INTEGRATION_TYPE] == INTEGRATION_TYPE_GEOGRAPHY:
sensors = [ sensors = [
AirVisualGeographySensor( AirVisualGeographySensor(
coordinator, config_entry, kind, name, icon, unit, locale, coordinator,
config_entry,
kind,
name,
icon,
unit,
locale,
) )
for locale in GEOGRAPHY_SENSOR_LOCALES for locale in GEOGRAPHY_SENSOR_LOCALES
for kind, name, icon, unit in GEOGRAPHY_SENSORS for kind, name, icon, unit in GEOGRAPHY_SENSORS

View File

@ -21,7 +21,7 @@
"node_pro": { "node_pro": {
"data": { "data": {
"ip_address": "Adresse IP / nom d'h\u00f4te de l'unit\u00e9", "ip_address": "Adresse IP / nom d'h\u00f4te de l'unit\u00e9",
"password": "Mot de passe de l'unit\u00e9" "password": "Mot de passe"
}, },
"description": "Surveillez une unit\u00e9 AirVisual personnelle. Le mot de passe peut \u00eatre r\u00e9cup\u00e9r\u00e9 dans l'interface utilisateur de l'unit\u00e9.", "description": "Surveillez une unit\u00e9 AirVisual personnelle. Le mot de passe peut \u00eatre r\u00e9cup\u00e9r\u00e9 dans l'interface utilisateur de l'unit\u00e9.",
"title": "Configurer un AirVisual Node/Pro" "title": "Configurer un AirVisual Node/Pro"
@ -32,7 +32,7 @@
"node_pro": "AirVisual Node Pro", "node_pro": "AirVisual Node Pro",
"type": "Type d'int\u00e9gration" "type": "Type d'int\u00e9gration"
}, },
"description": "Surveiller la qualit\u00e9 de l\u2019air dans un emplacement g\u00e9ographique.", "description": "Choisissez le type de donn\u00e9es AirVisual que vous souhaitez surveiller.",
"title": "Configurer AirVisual" "title": "Configurer AirVisual"
} }
} }

View File

@ -29,7 +29,6 @@
"user": { "user": {
"data": { "data": {
"cloud_api": "Geografisk plassering", "cloud_api": "Geografisk plassering",
"node_pro": "",
"type": "Integrasjonstype" "type": "Integrasjonstype"
}, },
"description": "Velg hvilken type AirVisual-data du vil overv\u00e5ke.", "description": "Velg hvilken type AirVisual-data du vil overv\u00e5ke.",

View File

@ -11,6 +11,11 @@
"longitude": "Longitude" "longitude": "Longitude"
} }
}, },
"node_pro": {
"data": {
"password": "Senha"
}
},
"user": { "user": {
"data": { "data": {
"type": "Tipo de Integra\u00e7\u00e3o" "type": "Tipo de Integra\u00e7\u00e3o"

View File

@ -8,8 +8,9 @@ from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_HOME, SUPPORT_ALARM_ARM_HOME,
SUPPORT_ALARM_ARM_NIGHT, SUPPORT_ALARM_ARM_NIGHT,
) )
from homeassistant.components.automation import AutomationActionType, state from homeassistant.components.automation import AutomationActionType
from homeassistant.components.device_automation import TRIGGER_BASE_SCHEMA from homeassistant.components.device_automation import TRIGGER_BASE_SCHEMA
from homeassistant.components.homeassistant.triggers import state as state_trigger
from homeassistant.const import ( from homeassistant.const import (
CONF_DEVICE_ID, CONF_DEVICE_ID,
CONF_DOMAIN, CONF_DOMAIN,
@ -151,13 +152,13 @@ async def async_attach_trigger(
to_state = STATE_ALARM_ARMED_NIGHT to_state = STATE_ALARM_ARMED_NIGHT
state_config = { state_config = {
state.CONF_PLATFORM: "state", state_trigger.CONF_PLATFORM: "state",
CONF_ENTITY_ID: config[CONF_ENTITY_ID], CONF_ENTITY_ID: config[CONF_ENTITY_ID],
state.CONF_TO: to_state, state_trigger.CONF_TO: to_state,
} }
if from_state: if from_state:
state_config[state.CONF_FROM] = from_state state_config[state_trigger.CONF_FROM] = from_state
state_config = state.TRIGGER_SCHEMA(state_config) state_config = state_trigger.TRIGGER_SCHEMA(state_config)
return await state.async_attach_trigger( return await state_trigger.async_attach_trigger(
hass, state_config, action, automation_info, platform_type="device" hass, state_config, action, automation_info, platform_type="device"
) )

View File

@ -25,7 +25,7 @@
"state": { "state": {
"_": { "_": {
"armed": "Zabezpe\u010deno", "armed": "Zabezpe\u010deno",
"armed_away": "Re\u017eim nep\u0159\u00edtomnost", "armed_away": "Nep\u0159\u00edtomnost",
"armed_custom_bypass": "Zabezpe\u010deno u\u017eivatelsk\u00fdm obejit\u00edm", "armed_custom_bypass": "Zabezpe\u010deno u\u017eivatelsk\u00fdm obejit\u00edm",
"armed_home": "Re\u017eim domov", "armed_home": "Re\u017eim domov",
"armed_night": "No\u010dn\u00ed re\u017eim", "armed_night": "No\u010dn\u00ed re\u017eim",

View File

@ -26,7 +26,7 @@
"_": { "_": {
"armed": "Activ\u00e9", "armed": "Activ\u00e9",
"armed_away": "Enclench\u00e9e (absent)", "armed_away": "Enclench\u00e9e (absent)",
"armed_custom_bypass": "Activ\u00e9e avec exception", "armed_custom_bypass": "Arm\u00e9 avec exception personnalis\u00e9e",
"armed_home": "Enclench\u00e9e (pr\u00e9sent)", "armed_home": "Enclench\u00e9e (pr\u00e9sent)",
"armed_night": "Enclench\u00e9 (nuit)", "armed_night": "Enclench\u00e9 (nuit)",
"arming": "Activation", "arming": "Activation",

View File

@ -1,5 +1,6 @@
"""Alexa capabilities.""" """Alexa capabilities."""
import logging import logging
from typing import List, Optional
from homeassistant.components import ( from homeassistant.components import (
cover, cover,
@ -36,6 +37,7 @@ from homeassistant.const import (
STATE_UNKNOWN, STATE_UNKNOWN,
STATE_UNLOCKED, STATE_UNLOCKED,
) )
from homeassistant.core import State
import homeassistant.util.color as color_util import homeassistant.util.color as color_util
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
@ -71,32 +73,32 @@ class AlexaCapability:
supported_locales = {"en-US"} supported_locales = {"en-US"}
def __init__(self, entity, instance=None): def __init__(self, entity: State, instance: Optional[str] = None):
"""Initialize an Alexa capability.""" """Initialize an Alexa capability."""
self.entity = entity self.entity = entity
self.instance = instance self.instance = instance
def name(self): def name(self) -> str:
"""Return the Alexa API name of this interface.""" """Return the Alexa API name of this interface."""
raise NotImplementedError raise NotImplementedError
@staticmethod @staticmethod
def properties_supported(): def properties_supported() -> List[dict]:
"""Return what properties this entity supports.""" """Return what properties this entity supports."""
return [] return []
@staticmethod @staticmethod
def properties_proactively_reported(): def properties_proactively_reported() -> bool:
"""Return True if properties asynchronously reported.""" """Return True if properties asynchronously reported."""
return False return False
@staticmethod @staticmethod
def properties_retrievable(): def properties_retrievable() -> bool:
"""Return True if properties can be retrieved.""" """Return True if properties can be retrieved."""
return False return False
@staticmethod @staticmethod
def properties_non_controllable(): def properties_non_controllable() -> bool:
"""Return True if non controllable.""" """Return True if non controllable."""
return None return None
@ -237,20 +239,34 @@ class AlexaCapability:
"""Return properties serialized for an API response.""" """Return properties serialized for an API response."""
for prop in self.properties_supported(): for prop in self.properties_supported():
prop_name = prop["name"] prop_name = prop["name"]
prop_value = self.get_property(prop_name) try:
if prop_value is not None: prop_value = self.get_property(prop_name)
result = { except UnsupportedProperty:
"name": prop_name, raise
"namespace": self.name(), except Exception: # pylint: disable=broad-except
"value": prop_value, _LOGGER.exception(
"timeOfSample": dt_util.utcnow().strftime(DATE_FORMAT), "Unexpected error getting %s.%s property from %s",
"uncertaintyInMilliseconds": 0, self.name(),
} prop_name,
instance = self.instance self.entity,
if instance is not None: )
result["instance"] = instance prop_value = None
yield result if prop_value is None:
continue
result = {
"name": prop_name,
"namespace": self.name(),
"value": prop_value,
"timeOfSample": dt_util.utcnow().strftime(DATE_FORMAT),
"uncertaintyInMilliseconds": 0,
}
instance = self.instance
if instance is not None:
result["instance"] = instance
yield result
class Alexa(AlexaCapability): class Alexa(AlexaCapability):
@ -850,7 +866,7 @@ class AlexaContactSensor(AlexaCapability):
https://developer.amazon.com/docs/device-apis/alexa-contactsensor.html https://developer.amazon.com/docs/device-apis/alexa-contactsensor.html
""" """
supported_locales = {"en-CA", "en-US"} supported_locales = {"en-CA", "en-US", "it-IT"}
def __init__(self, hass, entity): def __init__(self, hass, entity):
"""Initialize the entity.""" """Initialize the entity."""
@ -889,7 +905,7 @@ class AlexaMotionSensor(AlexaCapability):
https://developer.amazon.com/docs/device-apis/alexa-motionsensor.html https://developer.amazon.com/docs/device-apis/alexa-motionsensor.html
""" """
supported_locales = {"en-CA", "en-US"} supported_locales = {"en-CA", "en-US", "it-IT"}
def __init__(self, hass, entity): def __init__(self, hass, entity):
"""Initialize the entity.""" """Initialize the entity."""
@ -1097,7 +1113,22 @@ class AlexaSecurityPanelController(AlexaCapability):
https://developer.amazon.com/docs/device-apis/alexa-securitypanelcontroller.html https://developer.amazon.com/docs/device-apis/alexa-securitypanelcontroller.html
""" """
supported_locales = {"en-AU", "en-CA", "en-IN", "en-US"} supported_locales = {
"de-DE",
"en-AU",
"en-CA",
"en-GB",
"en-IN",
"en-US",
"es-ES",
"es-MX",
"es-US",
"fr-CA",
"fr-FR",
"it-IT",
"ja-JP",
"pt_BR",
}
def __init__(self, hass, entity): def __init__(self, hass, entity):
"""Initialize the entity.""" """Initialize the entity."""

View File

@ -1,6 +1,6 @@
"""Alexa entity adapters.""" """Alexa entity adapters."""
import logging import logging
from typing import List from typing import TYPE_CHECKING, List
from homeassistant.components import ( from homeassistant.components import (
alarm_control_panel, alarm_control_panel,
@ -34,7 +34,7 @@ from homeassistant.const import (
TEMP_CELSIUS, TEMP_CELSIUS,
TEMP_FAHRENHEIT, TEMP_FAHRENHEIT,
) )
from homeassistant.core import callback from homeassistant.core import HomeAssistant, State, callback
from homeassistant.helpers import network from homeassistant.helpers import network
from homeassistant.util.decorator import Registry from homeassistant.util.decorator import Registry
@ -42,6 +42,7 @@ from .capabilities import (
Alexa, Alexa,
AlexaBrightnessController, AlexaBrightnessController,
AlexaCameraStreamController, AlexaCameraStreamController,
AlexaCapability,
AlexaChannelController, AlexaChannelController,
AlexaColorController, AlexaColorController,
AlexaColorTemperatureController, AlexaColorTemperatureController,
@ -72,6 +73,9 @@ from .capabilities import (
) )
from .const import CONF_DESCRIPTION, CONF_DISPLAY_CATEGORIES from .const import CONF_DESCRIPTION, CONF_DISPLAY_CATEGORIES
if TYPE_CHECKING:
from .config import AbstractConfig
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
ENTITY_ADAPTERS = Registry() ENTITY_ADAPTERS = Registry()
@ -197,13 +201,18 @@ class DisplayCategory:
WEARABLE = "WEARABLE" WEARABLE = "WEARABLE"
def generate_alexa_id(entity_id: str) -> str:
"""Return the alexa ID for an entity ID."""
return entity_id.replace(".", "#").translate(TRANSLATION_TABLE)
class AlexaEntity: class AlexaEntity:
"""An adaptation of an entity, expressed in Alexa's terms. """An adaptation of an entity, expressed in Alexa's terms.
The API handlers should manipulate entities only through this interface. The API handlers should manipulate entities only through this interface.
""" """
def __init__(self, hass, config, entity): def __init__(self, hass: HomeAssistant, config: "AbstractConfig", entity: State):
"""Initialize Alexa Entity.""" """Initialize Alexa Entity."""
self.hass = hass self.hass = hass
self.config = config self.config = config
@ -228,7 +237,7 @@ class AlexaEntity:
def alexa_id(self): def alexa_id(self):
"""Return the Alexa API entity id.""" """Return the Alexa API entity id."""
return self.entity.entity_id.replace(".", "#").translate(TRANSLATION_TABLE) return generate_alexa_id(self.entity.entity_id)
def display_categories(self): def display_categories(self):
"""Return a list of display categories.""" """Return a list of display categories."""
@ -246,13 +255,13 @@ class AlexaEntity:
""" """
raise NotImplementedError raise NotImplementedError
def get_interface(self, capability): def get_interface(self, capability) -> AlexaCapability:
"""Return the given AlexaInterface. """Return the given AlexaInterface.
Raises _UnsupportedInterface. Raises _UnsupportedInterface.
""" """
def interfaces(self): def interfaces(self) -> List[AlexaCapability]:
"""Return a list of supported interfaces. """Return a list of supported interfaces.
Used for discovery. The list should contain AlexaInterface instances. Used for discovery. The list should contain AlexaInterface instances.
@ -280,11 +289,18 @@ class AlexaEntity:
} }
locale = self.config.locale locale = self.config.locale
capabilities = [ capabilities = []
i.serialize_discovery()
for i in self.interfaces() for i in self.interfaces():
if locale in i.supported_locales if locale not in i.supported_locales:
] continue
try:
capabilities.append(i.serialize_discovery())
except Exception: # pylint: disable=broad-except
_LOGGER.exception(
"Error serializing %s discovery for %s", i.name(), self.entity
)
result["capabilities"] = capabilities result["capabilities"] = capabilities

View File

@ -1542,8 +1542,10 @@ async def async_api_initialize_camera_stream(hass, config, directive, context):
require_ssl=True, require_ssl=True,
require_standard_port=True, require_standard_port=True,
) )
except network.NoURLAvailableError: except network.NoURLAvailableError as err:
raise AlexaInvalidValueError("Failed to find suitable URL to serve to Alexa") raise AlexaInvalidValueError(
"Failed to find suitable URL to serve to Alexa"
) from err
payload = { payload = {
"cameraStreams": [ "cameraStreams": [

View File

@ -10,7 +10,7 @@ from homeassistant.const import MATCH_ALL, STATE_ON
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from .const import API_CHANGE, Cause from .const import API_CHANGE, Cause
from .entities import ENTITY_ADAPTERS from .entities import ENTITY_ADAPTERS, generate_alexa_id
from .messages import AlexaResponse from .messages import AlexaResponse
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -181,8 +181,7 @@ async def async_send_delete_message(hass, config, entity_ids):
if domain not in ENTITY_ADAPTERS: if domain not in ENTITY_ADAPTERS:
continue continue
alexa_entity = ENTITY_ADAPTERS[domain](hass, config, hass.states.get(entity_id)) endpoints.append({"endpointId": generate_alexa_id(entity_id)})
endpoints.append({"endpointId": alexa_entity.alexa_id()})
payload = {"endpoints": endpoints, "scope": {"type": "BearerToken", "token": token}} payload = {"endpoints": endpoints, "scope": {"type": "BearerToken", "token": token}}

View File

@ -108,8 +108,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: config_entries.ConfigEnt
auth = AlmondLocalAuth(entry.data["host"], websession) auth = AlmondLocalAuth(entry.data["host"], websession)
else: else:
# OAuth2 # OAuth2
implementation = await config_entry_oauth2_flow.async_get_config_entry_implementation( implementation = (
hass, entry await config_entry_oauth2_flow.async_get_config_entry_implementation(
hass, entry
)
) )
oauth_session = config_entry_oauth2_flow.OAuth2Session( oauth_session = config_entry_oauth2_flow.OAuth2Session(
hass, entry, implementation hass, entry, implementation
@ -206,7 +208,7 @@ async def _configure_almond_for_ha(
msg = err msg = err
_LOGGER.warning("Unable to configure Almond: %s", msg) _LOGGER.warning("Unable to configure Almond: %s", msg)
await hass.auth.async_remove_refresh_token(refresh_token) await hass.auth.async_remove_refresh_token(refresh_token)
raise ConfigEntryNotReady raise ConfigEntryNotReady from err
# Clear all other refresh tokens # Clear all other refresh tokens
for token in list(user.refresh_tokens.values()): for token in list(user.refresh_tokens.values()):

View File

@ -11,7 +11,7 @@ from yarl import URL
from homeassistant import config_entries, core, data_entry_flow from homeassistant import config_entries, core, data_entry_flow
from homeassistant.helpers import aiohttp_client, config_entry_oauth2_flow from homeassistant.helpers import aiohttp_client, config_entry_oauth2_flow
from .const import DOMAIN, TYPE_LOCAL, TYPE_OAUTH2 from .const import DOMAIN as ALMOND_DOMAIN, TYPE_LOCAL, TYPE_OAUTH2
async def async_verify_local_connection(hass: core.HomeAssistant, host: str): async def async_verify_local_connection(hass: core.HomeAssistant, host: str):
@ -28,11 +28,11 @@ async def async_verify_local_connection(hass: core.HomeAssistant, host: str):
return False return False
@config_entries.HANDLERS.register(DOMAIN) @config_entries.HANDLERS.register(ALMOND_DOMAIN)
class AlmondFlowHandler(config_entry_oauth2_flow.AbstractOAuth2FlowHandler): class AlmondFlowHandler(config_entry_oauth2_flow.AbstractOAuth2FlowHandler):
"""Implementation of the Almond OAuth2 config flow.""" """Implementation of the Almond OAuth2 config flow."""
DOMAIN = DOMAIN DOMAIN = ALMOND_DOMAIN
host = None host = None
hassio_discovery = None hassio_discovery = None

View File

@ -10,7 +10,8 @@
"abort": { "abort": {
"already_setup": "You can only configure one Almond account.", "already_setup": "You can only configure one Almond account.",
"cannot_connect": "Unable to connect to the Almond server.", "cannot_connect": "Unable to connect to the Almond server.",
"missing_configuration": "Please check the documentation on how to set up Almond." "missing_configuration": "Please check the documentation on how to set up Almond.",
"no_url_available": "[%key:common::config_flow::abort::oauth2_no_url_available%]"
} }
} }
} }

View File

@ -7,8 +7,7 @@
}, },
"step": { "step": {
"hassio_confirm": { "hassio_confirm": {
"description": "Vil du konfigurere Home Assistant til \u00e5 koble til Almond levert av Hass.io add-on: {addon}?", "description": "Vil du konfigurere Home Assistant til \u00e5 koble til Almond levert av Hass.io add-on: {addon}?"
"title": ""
}, },
"pick_implementation": { "pick_implementation": {
"title": "Velg godkjenningsmetode" "title": "Velg godkjenningsmetode"

View File

@ -2,7 +2,7 @@
"config": { "config": {
"abort": { "abort": {
"access_token": "\u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430.", "access_token": "\u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0442\u043e\u043a\u0435\u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430.",
"already_setup": "\u0423\u0447\u0451\u0442\u043d\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c \u0443\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430.", "already_setup": "\u042d\u0442\u0430 \u0443\u0447\u0451\u0442\u043d\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c \u0443\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u0432 Home Assistant.",
"no_config": "\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 Ambiclimate \u043f\u0435\u0440\u0435\u0434 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435\u043c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 [\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f\u043c\u0438](https://www.home-assistant.io/components/ambiclimate/)." "no_config": "\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 Ambiclimate \u043f\u0435\u0440\u0435\u0434 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435\u043c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 [\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f\u043c\u0438](https://www.home-assistant.io/components/ambiclimate/)."
}, },
"create_entry": { "create_entry": {

View File

@ -15,10 +15,10 @@ from homeassistant.const import (
CONF_API_KEY, CONF_API_KEY,
DEGREE, DEGREE,
EVENT_HOMEASSISTANT_STOP, EVENT_HOMEASSISTANT_STOP,
PERCENTAGE,
POWER_WATT, POWER_WATT,
SPEED_MILES_PER_HOUR, SPEED_MILES_PER_HOUR,
TEMP_FAHRENHEIT, TEMP_FAHRENHEIT,
UNIT_PERCENTAGE,
) )
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.exceptions import ConfigEntryNotReady
@ -160,18 +160,18 @@ SENSOR_TYPES = {
TYPE_EVENTRAININ: ("Event Rain", "in", TYPE_SENSOR, None), TYPE_EVENTRAININ: ("Event Rain", "in", TYPE_SENSOR, None),
TYPE_FEELSLIKE: ("Feels Like", TEMP_FAHRENHEIT, TYPE_SENSOR, "temperature"), TYPE_FEELSLIKE: ("Feels Like", TEMP_FAHRENHEIT, TYPE_SENSOR, "temperature"),
TYPE_HOURLYRAININ: ("Hourly Rain Rate", "in/hr", TYPE_SENSOR, None), TYPE_HOURLYRAININ: ("Hourly Rain Rate", "in/hr", TYPE_SENSOR, None),
TYPE_HUMIDITY10: ("Humidity 10", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_HUMIDITY10: ("Humidity 10", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_HUMIDITY1: ("Humidity 1", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_HUMIDITY1: ("Humidity 1", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_HUMIDITY2: ("Humidity 2", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_HUMIDITY2: ("Humidity 2", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_HUMIDITY3: ("Humidity 3", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_HUMIDITY3: ("Humidity 3", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_HUMIDITY4: ("Humidity 4", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_HUMIDITY4: ("Humidity 4", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_HUMIDITY5: ("Humidity 5", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_HUMIDITY5: ("Humidity 5", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_HUMIDITY6: ("Humidity 6", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_HUMIDITY6: ("Humidity 6", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_HUMIDITY7: ("Humidity 7", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_HUMIDITY7: ("Humidity 7", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_HUMIDITY8: ("Humidity 8", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_HUMIDITY8: ("Humidity 8", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_HUMIDITY9: ("Humidity 9", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_HUMIDITY9: ("Humidity 9", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_HUMIDITY: ("Humidity", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_HUMIDITY: ("Humidity", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_HUMIDITYIN: ("Humidity In", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_HUMIDITYIN: ("Humidity In", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_LASTRAIN: ("Last Rain", None, TYPE_SENSOR, "timestamp"), TYPE_LASTRAIN: ("Last Rain", None, TYPE_SENSOR, "timestamp"),
TYPE_MAXDAILYGUST: ("Max Gust", SPEED_MILES_PER_HOUR, TYPE_SENSOR, None), TYPE_MAXDAILYGUST: ("Max Gust", SPEED_MILES_PER_HOUR, TYPE_SENSOR, None),
TYPE_MONTHLYRAININ: ("Monthly Rain", "in", TYPE_SENSOR, None), TYPE_MONTHLYRAININ: ("Monthly Rain", "in", TYPE_SENSOR, None),
@ -185,16 +185,16 @@ SENSOR_TYPES = {
TYPE_RELAY7: ("Relay 7", None, TYPE_BINARY_SENSOR, "connectivity"), TYPE_RELAY7: ("Relay 7", None, TYPE_BINARY_SENSOR, "connectivity"),
TYPE_RELAY8: ("Relay 8", None, TYPE_BINARY_SENSOR, "connectivity"), TYPE_RELAY8: ("Relay 8", None, TYPE_BINARY_SENSOR, "connectivity"),
TYPE_RELAY9: ("Relay 9", None, TYPE_BINARY_SENSOR, "connectivity"), TYPE_RELAY9: ("Relay 9", None, TYPE_BINARY_SENSOR, "connectivity"),
TYPE_SOILHUM10: ("Soil Humidity 10", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_SOILHUM10: ("Soil Humidity 10", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_SOILHUM1: ("Soil Humidity 1", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_SOILHUM1: ("Soil Humidity 1", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_SOILHUM2: ("Soil Humidity 2", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_SOILHUM2: ("Soil Humidity 2", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_SOILHUM3: ("Soil Humidity 3", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_SOILHUM3: ("Soil Humidity 3", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_SOILHUM4: ("Soil Humidity 4", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_SOILHUM4: ("Soil Humidity 4", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_SOILHUM5: ("Soil Humidity 5", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_SOILHUM5: ("Soil Humidity 5", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_SOILHUM6: ("Soil Humidity 6", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_SOILHUM6: ("Soil Humidity 6", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_SOILHUM7: ("Soil Humidity 7", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_SOILHUM7: ("Soil Humidity 7", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_SOILHUM8: ("Soil Humidity 8", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_SOILHUM8: ("Soil Humidity 8", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_SOILHUM9: ("Soil Humidity 9", UNIT_PERCENTAGE, TYPE_SENSOR, "humidity"), TYPE_SOILHUM9: ("Soil Humidity 9", PERCENTAGE, TYPE_SENSOR, "humidity"),
TYPE_SOILTEMP10F: ("Soil Temp 10", TEMP_FAHRENHEIT, TYPE_SENSOR, "temperature"), TYPE_SOILTEMP10F: ("Soil Temp 10", TEMP_FAHRENHEIT, TYPE_SENSOR, "temperature"),
TYPE_SOILTEMP1F: ("Soil Temp 1", TEMP_FAHRENHEIT, TYPE_SENSOR, "temperature"), TYPE_SOILTEMP1F: ("Soil Temp 1", TEMP_FAHRENHEIT, TYPE_SENSOR, "temperature"),
TYPE_SOILTEMP2F: ("Soil Temp 2", TEMP_FAHRENHEIT, TYPE_SENSOR, "temperature"), TYPE_SOILTEMP2F: ("Soil Temp 2", TEMP_FAHRENHEIT, TYPE_SENSOR, "temperature"),
@ -300,7 +300,7 @@ async def async_setup_entry(hass, config_entry):
hass.data[DOMAIN][DATA_CLIENT][config_entry.entry_id] = ambient hass.data[DOMAIN][DATA_CLIENT][config_entry.entry_id] = ambient
except WebsocketError as err: except WebsocketError as err:
_LOGGER.error("Config entry failed: %s", err) _LOGGER.error("Config entry failed: %s", err)
raise ConfigEntryNotReady raise ConfigEntryNotReady from err
hass.bus.async_listen_once( hass.bus.async_listen_once(
EVENT_HOMEASSISTANT_STOP, ambient.client.websocket.disconnect() EVENT_HOMEASSISTANT_STOP, ambient.client.websocket.disconnect()

View File

@ -4,7 +4,7 @@ import logging
from amcrest import AmcrestError from amcrest import AmcrestError
from homeassistant.const import CONF_NAME, CONF_SENSORS, UNIT_PERCENTAGE from homeassistant.const import CONF_NAME, CONF_SENSORS, PERCENTAGE
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
@ -20,7 +20,7 @@ SENSOR_SDCARD = "sdcard"
# Sensor types are defined like: Name, units, icon # Sensor types are defined like: Name, units, icon
SENSORS = { SENSORS = {
SENSOR_PTZ_PRESET: ["PTZ Preset", None, "mdi:camera-iris"], SENSOR_PTZ_PRESET: ["PTZ Preset", None, "mdi:camera-iris"],
SENSOR_SDCARD: ["SD Used", UNIT_PERCENTAGE, "mdi:sd"], SENSOR_SDCARD: ["SD Used", PERCENTAGE, "mdi:sd"],
} }

View File

@ -4,8 +4,8 @@
"documentation": "https://www.home-assistant.io/integrations/androidtv", "documentation": "https://www.home-assistant.io/integrations/androidtv",
"requirements": [ "requirements": [
"adb-shell[async]==0.2.1", "adb-shell[async]==0.2.1",
"androidtv[async]==0.0.47", "androidtv[async]==0.0.50",
"pure-python-adb==0.2.2.dev0" "pure-python-adb[async]==0.3.0.dev0"
], ],
"codeowners": ["@JeffLIrion"] "codeowners": ["@JeffLIrion"]
} }

View File

@ -374,8 +374,14 @@ def adb_decorator(override_available=False):
err, err,
) )
await self.aftv.adb_close() await self.aftv.adb_close()
self._available = False # pylint: disable=protected-access self._available = False
return None return None
except Exception:
# An unforeseen exception occurred. Close the ADB connection so that
# it doesn't happen over and over again, then raise the exception.
await self.aftv.adb_close()
self._available = False
raise
return _adb_exception_catcher return _adb_exception_catcher
@ -421,10 +427,8 @@ class ADBDevice(MediaPlayerEntity):
# Using "adb_shell" (Python ADB implementation) # Using "adb_shell" (Python ADB implementation)
self.exceptions = ( self.exceptions = (
AdbTimeoutError, AdbTimeoutError,
AttributeError,
BrokenPipeError, BrokenPipeError,
ConnectionResetError, ConnectionResetError,
TypeError,
ValueError, ValueError,
InvalidChecksumError, InvalidChecksumError,
InvalidCommandError, InvalidCommandError,
@ -597,7 +601,8 @@ class ADBDevice(MediaPlayerEntity):
msg = f"Output from service '{SERVICE_LEARN_SENDEVENT}' from {self.entity_id}: '{output}'" msg = f"Output from service '{SERVICE_LEARN_SENDEVENT}' from {self.entity_id}: '{output}'"
self.hass.components.persistent_notification.async_create( self.hass.components.persistent_notification.async_create(
msg, title="Android TV", msg,
title="Android TV",
) )
_LOGGER.info("%s", msg) _LOGGER.info("%s", msg)

View File

@ -8,7 +8,9 @@ import voluptuous as vol
from homeassistant.const import ( from homeassistant.const import (
CONF_IP_ADDRESS, CONF_IP_ADDRESS,
CONF_PASSWORD,
CONF_PORT, CONF_PORT,
CONF_USERNAME,
EVENT_HOMEASSISTANT_STOP, EVENT_HOMEASSISTANT_STOP,
EVENT_STATE_CHANGED, EVENT_STATE_CHANGED,
STATE_UNAVAILABLE, STATE_UNAVAILABLE,
@ -16,6 +18,7 @@ from homeassistant.const import (
) )
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entityfilter import FILTER_SCHEMA from homeassistant.helpers.entityfilter import FILTER_SCHEMA
from homeassistant.util import ssl as ssl_util
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -23,6 +26,7 @@ DOMAIN = "apache_kafka"
CONF_FILTER = "filter" CONF_FILTER = "filter"
CONF_TOPIC = "topic" CONF_TOPIC = "topic"
CONF_SECURITY_PROTOCOL = "security_protocol"
CONFIG_SCHEMA = vol.Schema( CONFIG_SCHEMA = vol.Schema(
{ {
@ -32,6 +36,11 @@ CONFIG_SCHEMA = vol.Schema(
vol.Required(CONF_PORT): cv.port, vol.Required(CONF_PORT): cv.port,
vol.Required(CONF_TOPIC): cv.string, vol.Required(CONF_TOPIC): cv.string,
vol.Optional(CONF_FILTER, default={}): FILTER_SCHEMA, vol.Optional(CONF_FILTER, default={}): FILTER_SCHEMA,
vol.Optional(CONF_SECURITY_PROTOCOL, default="PLAINTEXT"): vol.In(
["PLAINTEXT", "SASL_SSL"]
),
vol.Optional(CONF_USERNAME): cv.string,
vol.Optional(CONF_PASSWORD): cv.string,
} }
) )
}, },
@ -49,6 +58,9 @@ async def async_setup(hass, config):
conf[CONF_PORT], conf[CONF_PORT],
conf[CONF_TOPIC], conf[CONF_TOPIC],
conf[CONF_FILTER], conf[CONF_FILTER],
conf[CONF_SECURITY_PROTOCOL],
conf.get(CONF_USERNAME),
conf.get(CONF_PASSWORD),
) )
hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, kafka.shutdown()) hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, kafka.shutdown())
@ -64,7 +76,7 @@ class DateTimeJSONEncoder(json.JSONEncoder):
Additionally add encoding for datetime objects as isoformat. Additionally add encoding for datetime objects as isoformat.
""" """
def default(self, o): # pylint: disable=method-hidden def default(self, o):
"""Implement encoding logic.""" """Implement encoding logic."""
if isinstance(o, datetime): if isinstance(o, datetime):
return o.isoformat() return o.isoformat()
@ -74,15 +86,31 @@ class DateTimeJSONEncoder(json.JSONEncoder):
class KafkaManager: class KafkaManager:
"""Define a manager to buffer events to Kafka.""" """Define a manager to buffer events to Kafka."""
def __init__(self, hass, ip_address, port, topic, entities_filter): def __init__(
self,
hass,
ip_address,
port,
topic,
entities_filter,
security_protocol,
username,
password,
):
"""Initialize.""" """Initialize."""
self._encoder = DateTimeJSONEncoder() self._encoder = DateTimeJSONEncoder()
self._entities_filter = entities_filter self._entities_filter = entities_filter
self._hass = hass self._hass = hass
ssl_context = ssl_util.client_context()
self._producer = AIOKafkaProducer( self._producer = AIOKafkaProducer(
loop=hass.loop, loop=hass.loop,
bootstrap_servers=f"{ip_address}:{port}", bootstrap_servers=f"{ip_address}:{port}",
compression_type="gzip", compression_type="gzip",
security_protocol=security_protocol,
ssl_context=ssl_context,
sasl_mechanism="PLAIN",
sasl_plain_username=username,
sasl_plain_password=password,
) )
self._topic = topic self._topic = topic

View File

@ -10,11 +10,11 @@ from homeassistant.const import (
ELECTRICAL_CURRENT_AMPERE, ELECTRICAL_CURRENT_AMPERE,
ELECTRICAL_VOLT_AMPERE, ELECTRICAL_VOLT_AMPERE,
FREQUENCY_HERTZ, FREQUENCY_HERTZ,
PERCENTAGE,
POWER_WATT, POWER_WATT,
TEMP_CELSIUS, TEMP_CELSIUS,
TIME_MINUTES, TIME_MINUTES,
TIME_SECONDS, TIME_SECONDS,
UNIT_PERCENTAGE,
VOLT, VOLT,
) )
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
@ -34,7 +34,7 @@ SENSOR_TYPES = {
"battdate": ["Battery Replaced", "", "mdi:calendar-clock"], "battdate": ["Battery Replaced", "", "mdi:calendar-clock"],
"battstat": ["Battery Status", "", "mdi:information-outline"], "battstat": ["Battery Status", "", "mdi:information-outline"],
"battv": ["Battery Voltage", VOLT, "mdi:flash"], "battv": ["Battery Voltage", VOLT, "mdi:flash"],
"bcharge": ["Battery", UNIT_PERCENTAGE, "mdi:battery"], "bcharge": ["Battery", PERCENTAGE, "mdi:battery"],
"cable": ["Cable Type", "", "mdi:ethernet-cable"], "cable": ["Cable Type", "", "mdi:ethernet-cable"],
"cumonbatt": ["Total Time on Battery", "", "mdi:timer-outline"], "cumonbatt": ["Total Time on Battery", "", "mdi:timer-outline"],
"date": ["Status Date", "", "mdi:calendar-clock"], "date": ["Status Date", "", "mdi:calendar-clock"],
@ -48,20 +48,20 @@ SENSOR_TYPES = {
"firmware": ["Firmware Version", "", "mdi:information-outline"], "firmware": ["Firmware Version", "", "mdi:information-outline"],
"hitrans": ["Transfer High", VOLT, "mdi:flash"], "hitrans": ["Transfer High", VOLT, "mdi:flash"],
"hostname": ["Hostname", "", "mdi:information-outline"], "hostname": ["Hostname", "", "mdi:information-outline"],
"humidity": ["Ambient Humidity", UNIT_PERCENTAGE, "mdi:water-percent"], "humidity": ["Ambient Humidity", PERCENTAGE, "mdi:water-percent"],
"itemp": ["Internal Temperature", TEMP_CELSIUS, "mdi:thermometer"], "itemp": ["Internal Temperature", TEMP_CELSIUS, "mdi:thermometer"],
"lastxfer": ["Last Transfer", "", "mdi:transfer"], "lastxfer": ["Last Transfer", "", "mdi:transfer"],
"linefail": ["Input Voltage Status", "", "mdi:information-outline"], "linefail": ["Input Voltage Status", "", "mdi:information-outline"],
"linefreq": ["Line Frequency", FREQUENCY_HERTZ, "mdi:information-outline"], "linefreq": ["Line Frequency", FREQUENCY_HERTZ, "mdi:information-outline"],
"linev": ["Input Voltage", VOLT, "mdi:flash"], "linev": ["Input Voltage", VOLT, "mdi:flash"],
"loadpct": ["Load", UNIT_PERCENTAGE, "mdi:gauge"], "loadpct": ["Load", PERCENTAGE, "mdi:gauge"],
"loadapnt": ["Load Apparent Power", UNIT_PERCENTAGE, "mdi:gauge"], "loadapnt": ["Load Apparent Power", PERCENTAGE, "mdi:gauge"],
"lotrans": ["Transfer Low", VOLT, "mdi:flash"], "lotrans": ["Transfer Low", VOLT, "mdi:flash"],
"mandate": ["Manufacture Date", "", "mdi:calendar"], "mandate": ["Manufacture Date", "", "mdi:calendar"],
"masterupd": ["Master Update", "", "mdi:information-outline"], "masterupd": ["Master Update", "", "mdi:information-outline"],
"maxlinev": ["Input Voltage High", VOLT, "mdi:flash"], "maxlinev": ["Input Voltage High", VOLT, "mdi:flash"],
"maxtime": ["Battery Timeout", "", "mdi:timer-off-outline"], "maxtime": ["Battery Timeout", "", "mdi:timer-off-outline"],
"mbattchg": ["Battery Shutdown", UNIT_PERCENTAGE, "mdi:battery-alert"], "mbattchg": ["Battery Shutdown", PERCENTAGE, "mdi:battery-alert"],
"minlinev": ["Input Voltage Low", VOLT, "mdi:flash"], "minlinev": ["Input Voltage Low", VOLT, "mdi:flash"],
"mintimel": ["Shutdown Time", "", "mdi:timer-outline"], "mintimel": ["Shutdown Time", "", "mdi:timer-outline"],
"model": ["Model", "", "mdi:information-outline"], "model": ["Model", "", "mdi:information-outline"],
@ -76,7 +76,7 @@ SENSOR_TYPES = {
"reg1": ["Register 1 Fault", "", "mdi:information-outline"], "reg1": ["Register 1 Fault", "", "mdi:information-outline"],
"reg2": ["Register 2 Fault", "", "mdi:information-outline"], "reg2": ["Register 2 Fault", "", "mdi:information-outline"],
"reg3": ["Register 3 Fault", "", "mdi:information-outline"], "reg3": ["Register 3 Fault", "", "mdi:information-outline"],
"retpct": ["Restore Requirement", UNIT_PERCENTAGE, "mdi:battery-alert"], "retpct": ["Restore Requirement", PERCENTAGE, "mdi:battery-alert"],
"selftest": ["Last Self Test", "", "mdi:calendar-clock"], "selftest": ["Last Self Test", "", "mdi:calendar-clock"],
"sense": ["Sensitivity", "", "mdi:information-outline"], "sense": ["Sensitivity", "", "mdi:information-outline"],
"serialno": ["Serial Number", "", "mdi:information-outline"], "serialno": ["Serial Number", "", "mdi:information-outline"],
@ -98,14 +98,14 @@ SPECIFIC_UNITS = {"ITEMP": TEMP_CELSIUS}
INFERRED_UNITS = { INFERRED_UNITS = {
" Minutes": TIME_MINUTES, " Minutes": TIME_MINUTES,
" Seconds": TIME_SECONDS, " Seconds": TIME_SECONDS,
" Percent": UNIT_PERCENTAGE, " Percent": PERCENTAGE,
" Volts": VOLT, " Volts": VOLT,
" Ampere": ELECTRICAL_CURRENT_AMPERE, " Ampere": ELECTRICAL_CURRENT_AMPERE,
" Volt-Ampere": ELECTRICAL_VOLT_AMPERE, " Volt-Ampere": ELECTRICAL_VOLT_AMPERE,
" Watts": POWER_WATT, " Watts": POWER_WATT,
" Hz": FREQUENCY_HERTZ, " Hz": FREQUENCY_HERTZ,
" C": TEMP_CELSIUS, " C": TEMP_CELSIUS,
" Percent Load Capacity": UNIT_PERCENTAGE, " Percent Load Capacity": PERCENTAGE,
} }
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(

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