mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 04:37:06 +00:00
Merge pull request #71297 from home-assistant/rc
This commit is contained in:
commit
4196c4e81c
33
.coveragerc
33
.coveragerc
@ -73,7 +73,6 @@ omit =
|
||||
homeassistant/components/arest/binary_sensor.py
|
||||
homeassistant/components/arest/sensor.py
|
||||
homeassistant/components/arest/switch.py
|
||||
homeassistant/components/arlo/*
|
||||
homeassistant/components/arris_tg2492lg/*
|
||||
homeassistant/components/aruba/device_tracker.py
|
||||
homeassistant/components/arwn/sensor.py
|
||||
@ -83,9 +82,7 @@ omit =
|
||||
homeassistant/components/aseko_pool_live/sensor.py
|
||||
homeassistant/components/asterisk_cdr/mailbox.py
|
||||
homeassistant/components/asterisk_mbox/*
|
||||
homeassistant/components/asuswrt/__init__.py
|
||||
homeassistant/components/asuswrt/diagnostics.py
|
||||
homeassistant/components/asuswrt/router.py
|
||||
homeassistant/components/aten_pe/*
|
||||
homeassistant/components/atome/*
|
||||
homeassistant/components/aurora/__init__.py
|
||||
@ -120,6 +117,7 @@ omit =
|
||||
homeassistant/components/bmw_connected_drive/__init__.py
|
||||
homeassistant/components/bmw_connected_drive/binary_sensor.py
|
||||
homeassistant/components/bmw_connected_drive/button.py
|
||||
homeassistant/components/bmw_connected_drive/coordinator.py
|
||||
homeassistant/components/bmw_connected_drive/device_tracker.py
|
||||
homeassistant/components/bmw_connected_drive/lock.py
|
||||
homeassistant/components/bmw_connected_drive/notify.py
|
||||
@ -215,7 +213,6 @@ omit =
|
||||
homeassistant/components/devolo_home_control/subscriber.py
|
||||
homeassistant/components/devolo_home_control/switch.py
|
||||
homeassistant/components/digital_ocean/*
|
||||
homeassistant/components/digitalloggers/switch.py
|
||||
homeassistant/components/discogs/sensor.py
|
||||
homeassistant/components/discord/__init__.py
|
||||
homeassistant/components/discord/notify.py
|
||||
@ -593,10 +590,6 @@ omit =
|
||||
homeassistant/components/keyboard_remote/*
|
||||
homeassistant/components/kira/*
|
||||
homeassistant/components/kiwi/lock.py
|
||||
homeassistant/components/knx/__init__.py
|
||||
homeassistant/components/knx/climate.py
|
||||
homeassistant/components/knx/cover.py
|
||||
homeassistant/components/knx/notify.py
|
||||
homeassistant/components/kodi/__init__.py
|
||||
homeassistant/components/kodi/browse_media.py
|
||||
homeassistant/components/kodi/const.py
|
||||
@ -678,6 +671,9 @@ omit =
|
||||
homeassistant/components/map/*
|
||||
homeassistant/components/mastodon/notify.py
|
||||
homeassistant/components/matrix/*
|
||||
homeassistant/components/meater/__init__.py
|
||||
homeassistant/components/meater/const.py
|
||||
homeassistant/components/meater/sensor.py
|
||||
homeassistant/components/media_extractor/*
|
||||
homeassistant/components/mediaroom/media_player.py
|
||||
homeassistant/components/melcloud/__init__.py
|
||||
@ -996,7 +992,8 @@ omit =
|
||||
homeassistant/components/rtorrent/sensor.py
|
||||
homeassistant/components/russound_rio/media_player.py
|
||||
homeassistant/components/russound_rnet/media_player.py
|
||||
homeassistant/components/sabnzbd/*
|
||||
homeassistant/components/sabnzbd/__init__.py
|
||||
homeassistant/components/sabnzbd/sensor.py
|
||||
homeassistant/components/saj/sensor.py
|
||||
homeassistant/components/satel_integra/*
|
||||
homeassistant/components/schluter/*
|
||||
@ -1030,6 +1027,10 @@ omit =
|
||||
homeassistant/components/sensibo/number.py
|
||||
homeassistant/components/sensibo/select.py
|
||||
homeassistant/components/sensibo/sensor.py
|
||||
homeassistant/components/sensibo/update.py
|
||||
homeassistant/components/senz/__init__.py
|
||||
homeassistant/components/senz/api.py
|
||||
homeassistant/components/senz/climate.py
|
||||
homeassistant/components/serial/sensor.py
|
||||
homeassistant/components/serial_pm/sensor.py
|
||||
homeassistant/components/sesame/lock.py
|
||||
@ -1128,6 +1129,8 @@ omit =
|
||||
homeassistant/components/spotify/media_player.py
|
||||
homeassistant/components/spotify/system_health.py
|
||||
homeassistant/components/spotify/util.py
|
||||
homeassistant/components/slimproto/__init__.py
|
||||
homeassistant/components/slimproto/media_player.py
|
||||
homeassistant/components/squeezebox/__init__.py
|
||||
homeassistant/components/squeezebox/browse_media.py
|
||||
homeassistant/components/squeezebox/media_player.py
|
||||
@ -1177,6 +1180,7 @@ omit =
|
||||
homeassistant/components/synology_dsm/camera.py
|
||||
homeassistant/components/synology_dsm/diagnostics.py
|
||||
homeassistant/components/synology_dsm/common.py
|
||||
homeassistant/components/synology_dsm/entity.py
|
||||
homeassistant/components/synology_dsm/sensor.py
|
||||
homeassistant/components/synology_dsm/service.py
|
||||
homeassistant/components/synology_dsm/switch.py
|
||||
@ -1201,7 +1205,7 @@ omit =
|
||||
homeassistant/components/tankerkoenig/const.py
|
||||
homeassistant/components/tankerkoenig/sensor.py
|
||||
homeassistant/components/tapsaff/binary_sensor.py
|
||||
homeassistant/components/tautulli/const.py
|
||||
homeassistant/components/tautulli/__init__.py
|
||||
homeassistant/components/tautulli/coordinator.py
|
||||
homeassistant/components/tautulli/sensor.py
|
||||
homeassistant/components/ted5000/sensor.py
|
||||
@ -1265,6 +1269,7 @@ omit =
|
||||
homeassistant/components/tractive/__init__.py
|
||||
homeassistant/components/tractive/binary_sensor.py
|
||||
homeassistant/components/tractive/device_tracker.py
|
||||
homeassistant/components/tractive/diagnostics.py
|
||||
homeassistant/components/tractive/entity.py
|
||||
homeassistant/components/tractive/sensor.py
|
||||
homeassistant/components/tractive/switch.py
|
||||
@ -1276,6 +1281,9 @@ omit =
|
||||
homeassistant/components/tradfri/light.py
|
||||
homeassistant/components/tradfri/sensor.py
|
||||
homeassistant/components/tradfri/switch.py
|
||||
homeassistant/components/trafikverket_ferry/__init__.py
|
||||
homeassistant/components/trafikverket_ferry/coordinator.py
|
||||
homeassistant/components/trafikverket_ferry/sensor.py
|
||||
homeassistant/components/trafikverket_train/__init__.py
|
||||
homeassistant/components/trafikverket_train/sensor.py
|
||||
homeassistant/components/trafikverket_weatherstation/__init__.py
|
||||
@ -1365,6 +1373,7 @@ omit =
|
||||
homeassistant/components/vicare/button.py
|
||||
homeassistant/components/vicare/climate.py
|
||||
homeassistant/components/vicare/const.py
|
||||
homeassistant/components/vicare/diagnostics.py
|
||||
homeassistant/components/vicare/__init__.py
|
||||
homeassistant/components/vicare/sensor.py
|
||||
homeassistant/components/vicare/water_heater.py
|
||||
@ -1428,6 +1437,7 @@ omit =
|
||||
homeassistant/components/xiaomi_miio/button.py
|
||||
homeassistant/components/xiaomi_miio/device.py
|
||||
homeassistant/components/xiaomi_miio/device_tracker.py
|
||||
homeassistant/components/xiaomi_miio/diagnostics.py
|
||||
homeassistant/components/xiaomi_miio/fan.py
|
||||
homeassistant/components/xiaomi_miio/gateway.py
|
||||
homeassistant/components/xiaomi_miio/humidifier.py
|
||||
@ -1443,6 +1453,7 @@ omit =
|
||||
homeassistant/components/yale_smart_alarm/__init__.py
|
||||
homeassistant/components/yale_smart_alarm/alarm_control_panel.py
|
||||
homeassistant/components/yale_smart_alarm/binary_sensor.py
|
||||
homeassistant/components/yale_smart_alarm/button.py
|
||||
homeassistant/components/yale_smart_alarm/const.py
|
||||
homeassistant/components/yale_smart_alarm/coordinator.py
|
||||
homeassistant/components/yale_smart_alarm/diagnostics.py
|
||||
@ -1452,6 +1463,7 @@ omit =
|
||||
homeassistant/components/yamaha_musiccast/media_player.py
|
||||
homeassistant/components/yamaha_musiccast/number.py
|
||||
homeassistant/components/yamaha_musiccast/select.py
|
||||
homeassistant/components/yamaha_musiccast/switch.py
|
||||
homeassistant/components/yandex_transport/*
|
||||
homeassistant/components/yeelightsunflower/light.py
|
||||
homeassistant/components/yi/camera.py
|
||||
@ -1489,6 +1501,7 @@ omit =
|
||||
homeassistant/components/zwave_me/button.py
|
||||
homeassistant/components/zwave_me/cover.py
|
||||
homeassistant/components/zwave_me/climate.py
|
||||
homeassistant/components/zwave_me/fan.py
|
||||
homeassistant/components/zwave_me/helpers.py
|
||||
homeassistant/components/zwave_me/light.py
|
||||
homeassistant/components/zwave_me/lock.py
|
||||
|
@ -11,7 +11,8 @@
|
||||
"ms-python.vscode-pylance",
|
||||
"visualstudioexptteam.vscodeintellicode",
|
||||
"redhat.vscode-yaml",
|
||||
"esbenp.prettier-vscode"
|
||||
"esbenp.prettier-vscode",
|
||||
"GitHub.vscode-pull-request-github"
|
||||
],
|
||||
// Please keep this file in sync with settings in home-assistant/.vscode/settings.default.json
|
||||
"settings": {
|
||||
|
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -78,12 +78,13 @@ body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Diagnostics information
|
||||
placeholder: "drag-and-drop the diagnostics data file here (do not copy-and-paste the content)"
|
||||
description: >-
|
||||
Many integrations provide the ability to download diagnostic data
|
||||
on the device page (and on the integration dashboard).
|
||||
|
||||
**It would really help if you could download the diagnostics data for the device you are having issues with,
|
||||
and drag-and-drop that file into the textbox below.**
|
||||
and <ins>drag-and-drop that file into the textbox below.</ins>**
|
||||
|
||||
It generally allows pinpointing defects and thus resolving issues faster.
|
||||
- type: textarea
|
||||
|
18
.github/workflows/builder.yml
vendored
18
.github/workflows/builder.yml
vendored
@ -24,12 +24,12 @@ jobs:
|
||||
publish: ${{ steps.version.outputs.publish }}
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v3.0.0
|
||||
uses: actions/setup-python@v3.1.2
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
|
||||
@ -67,10 +67,10 @@ jobs:
|
||||
if: github.repository_owner == 'home-assistant' && needs.init.outputs.publish == 'true'
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v3.0.0
|
||||
uses: actions/setup-python@v3.1.2
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
|
||||
@ -100,11 +100,11 @@ jobs:
|
||||
arch: ${{ fromJson(needs.init.outputs.architectures) }}
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
if: needs.init.outputs.channel == 'dev'
|
||||
uses: actions/setup-python@v3.0.0
|
||||
uses: actions/setup-python@v3.1.2
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
|
||||
@ -173,7 +173,7 @@ jobs:
|
||||
- tinker
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
|
||||
- name: Set build additional args
|
||||
run: |
|
||||
@ -216,7 +216,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
|
||||
- name: Initialize git
|
||||
uses: home-assistant/actions/helpers/git-init@master
|
||||
@ -255,7 +255,7 @@ jobs:
|
||||
- "homeassistant"
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
|
||||
- name: Login to DockerHub
|
||||
if: matrix.registry == 'homeassistant'
|
||||
|
96
.github/workflows/ci.yaml
vendored
96
.github/workflows/ci.yaml
vendored
@ -22,7 +22,7 @@ on:
|
||||
env:
|
||||
CACHE_VERSION: 9
|
||||
PIP_CACHE_VERSION: 3
|
||||
HA_SHORT_VERSION: 2022.4
|
||||
HA_SHORT_VERSION: 2022.5
|
||||
DEFAULT_PYTHON: 3.9
|
||||
PRE_COMMIT_CACHE: ~/.cache/pre-commit
|
||||
PIP_CACHE: /tmp/pip-cache
|
||||
@ -51,7 +51,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
- name: Filter for core changes
|
||||
uses: dorny/paths-filter@v2.10.2
|
||||
id: core
|
||||
@ -152,10 +152,10 @@ jobs:
|
||||
pre-commit-key: ${{ steps.generate-pre-commit-key.outputs.key }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
id: python
|
||||
uses: actions/setup-python@v3.0.0
|
||||
uses: actions/setup-python@v3.1.2
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Generate partial Python venv restore key
|
||||
@ -172,7 +172,7 @@ jobs:
|
||||
env.HA_SHORT_VERSION }}-$(date -u '+%Y-%m-%dT%H:%M:%s')"
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
@ -189,7 +189,7 @@ jobs:
|
||||
# ${{ runner.os }}-${{ steps.python.outputs.python-version }}-base-venv-${{ env.CACHE_VERSION }}-
|
||||
- name: Restore pip wheel cache
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: ${{ env.PIP_CACHE }}
|
||||
key: >-
|
||||
@ -212,7 +212,7 @@ jobs:
|
||||
hashFiles('.pre-commit-config.yaml') }}"
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
||||
key: >-
|
||||
@ -233,15 +233,15 @@ jobs:
|
||||
- prepare-base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v3.0.0
|
||||
uses: actions/setup-python@v3.1.2
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: venv
|
||||
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||
@ -253,7 +253,7 @@ jobs:
|
||||
exit 1
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
||||
key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }}
|
||||
@ -283,15 +283,15 @@ jobs:
|
||||
- prepare-base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v3.0.0
|
||||
uses: actions/setup-python@v3.1.2
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: venv
|
||||
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||
@ -303,7 +303,7 @@ jobs:
|
||||
exit 1
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
||||
key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }}
|
||||
@ -334,15 +334,15 @@ jobs:
|
||||
needs: prepare-base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v3.0.0
|
||||
uses: actions/setup-python@v3.1.2
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: venv
|
||||
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||
@ -354,7 +354,7 @@ jobs:
|
||||
exit 1
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
||||
key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }}
|
||||
@ -376,15 +376,15 @@ jobs:
|
||||
- prepare-base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v3.0.0
|
||||
uses: actions/setup-python@v3.1.2
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: venv
|
||||
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||
@ -396,7 +396,7 @@ jobs:
|
||||
exit 1
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
||||
key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }}
|
||||
@ -435,11 +435,19 @@ jobs:
|
||||
. venv/bin/activate
|
||||
pre-commit run --hook-stage manual check-json --all-files
|
||||
|
||||
- name: Run prettier
|
||||
- name: Run prettier (fully)
|
||||
if: needs.changes.outputs.test_full_suite == 'true'
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
pre-commit run --hook-stage manual prettier --all-files
|
||||
|
||||
- name: Run prettier (partially)
|
||||
if: needs.changes.outputs.test_full_suite == 'false'
|
||||
shell: bash
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
pre-commit run --hook-stage manual prettier --files {homeassistant,tests}/components/${{ needs.changes.outputs.integrations_glob }}/**/*
|
||||
|
||||
- name: Register check executables problem matcher
|
||||
run: |
|
||||
echo "::add-matcher::.github/workflows/matchers/check-executables-have-shebangs.json"
|
||||
@ -491,10 +499,10 @@ jobs:
|
||||
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: venv
|
||||
key: ${{ runner.os }}-${{ matrix.python-version }}-${{
|
||||
@ -515,15 +523,15 @@ jobs:
|
||||
needs: prepare-base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v3.0.0
|
||||
uses: actions/setup-python@v3.1.2
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: venv
|
||||
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||
@ -550,7 +558,7 @@ jobs:
|
||||
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
- name: Generate partial Python venv restore key
|
||||
id: generate-python-key
|
||||
run: >-
|
||||
@ -565,7 +573,7 @@ jobs:
|
||||
env.HA_SHORT_VERSION }}-$(date -u '+%Y-%m-%dT%H:%M:%s')"
|
||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
@ -582,7 +590,7 @@ jobs:
|
||||
# ${{ runner.os }}-${{ matrix.python-version }}-venv-${{ env.CACHE_VERSION }}-
|
||||
- name: Restore pip wheel cache
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: ${{ env.PIP_CACHE }}
|
||||
key: >-
|
||||
@ -618,10 +626,10 @@ jobs:
|
||||
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: venv
|
||||
key: ${{ runner.os }}-${{ matrix.python-version }}-${{
|
||||
@ -660,10 +668,10 @@ jobs:
|
||||
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: venv
|
||||
key: ${{ runner.os }}-${{ matrix.python-version }}-${{
|
||||
@ -704,10 +712,10 @@ jobs:
|
||||
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: venv
|
||||
key: ${{ runner.os }}-${{ matrix.python-version }}-${{
|
||||
@ -747,10 +755,10 @@ jobs:
|
||||
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v3.0.0
|
||||
uses: actions/cache@v3.0.2
|
||||
with:
|
||||
path: venv
|
||||
key: ${{ runner.os }}-${{ matrix.python-version }}-${{
|
||||
@ -835,14 +843,14 @@ jobs:
|
||||
- pytest
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
- name: Download all coverage artifacts
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
- name: Upload coverage to Codecov (full coverage)
|
||||
if: needs.changes.outputs.test_full_suite == 'true'
|
||||
uses: codecov/codecov-action@v2.1.0
|
||||
uses: codecov/codecov-action@v3.1.0
|
||||
with:
|
||||
flags: full-suite
|
||||
- name: Upload coverage to Codecov (partial coverage)
|
||||
if: needs.changes.outputs.test_full_suite == 'false'
|
||||
uses: codecov/codecov-action@v2.1.0
|
||||
uses: codecov/codecov-action@v3.1.0
|
||||
|
7
.github/workflows/stale.yml
vendored
7
.github/workflows/stale.yml
vendored
@ -8,6 +8,7 @@ on:
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
if: github.repository_owner == 'home-assistant'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# The 90 day stale policy
|
||||
@ -16,7 +17,7 @@ jobs:
|
||||
# - No PRs marked as no-stale
|
||||
# - No issues marked as no-stale or help-wanted
|
||||
- name: 90 days stale issues & PRs policy
|
||||
uses: actions/stale@v4
|
||||
uses: actions/stale@v5
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
days-before-stale: 90
|
||||
@ -53,7 +54,7 @@ jobs:
|
||||
# - No PRs marked as no-stale or new-integrations
|
||||
# - No issues (-1)
|
||||
- name: 30 days stale PRs policy
|
||||
uses: actions/stale@v4
|
||||
uses: actions/stale@v5
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
days-before-stale: 30
|
||||
@ -78,7 +79,7 @@ jobs:
|
||||
# - No Issues marked as no-stale or help-wanted
|
||||
# - No PRs (-1)
|
||||
- name: Needs more information stale issues policy
|
||||
uses: actions/stale@v4
|
||||
uses: actions/stale@v5
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
only-labels: "needs-more-information"
|
||||
|
8
.github/workflows/translations.yaml
vendored
8
.github/workflows/translations.yaml
vendored
@ -21,10 +21,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v3.0.0
|
||||
uses: actions/setup-python@v3.1.2
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
|
||||
@ -40,10 +40,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v3.0.0
|
||||
uses: actions/setup-python@v3.1.2
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
|
||||
|
14
.github/workflows/wheels.yml
vendored
14
.github/workflows/wheels.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
||||
architectures: ${{ steps.info.outputs.architectures }}
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
|
||||
- name: Get information
|
||||
id: info
|
||||
@ -74,15 +74,15 @@ jobs:
|
||||
- "3.9-alpine3.14"
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
|
||||
- name: Download env_file
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: env_file
|
||||
|
||||
- name: Download requirements_diff
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: requirements_diff
|
||||
|
||||
@ -115,15 +115,15 @@ jobs:
|
||||
- "3.9-alpine3.14"
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.0.0
|
||||
uses: actions/checkout@v3.0.2
|
||||
|
||||
- name: Download env_file
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: env_file
|
||||
|
||||
- name: Download requirements_diff
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: requirements_diff
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
repos:
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v2.31.1
|
||||
rev: v2.32.0
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--py39-plus]
|
||||
|
@ -46,6 +46,7 @@ homeassistant.components.ambient_station.*
|
||||
homeassistant.components.amcrest.*
|
||||
homeassistant.components.ampio.*
|
||||
homeassistant.components.aseko_pool_live.*
|
||||
homeassistant.components.asuswrt.*
|
||||
homeassistant.components.automation.*
|
||||
homeassistant.components.backup.*
|
||||
homeassistant.components.binary_sensor.*
|
||||
@ -62,11 +63,7 @@ homeassistant.components.canary.*
|
||||
homeassistant.components.cover.*
|
||||
homeassistant.components.crownstone.*
|
||||
homeassistant.components.cpuspeed.*
|
||||
homeassistant.components.deconz
|
||||
homeassistant.components.deconz.config_flow
|
||||
homeassistant.components.deconz.diagnostics
|
||||
homeassistant.components.deconz.gateway
|
||||
homeassistant.components.deconz.services
|
||||
homeassistant.components.deconz.*
|
||||
homeassistant.components.device_automation.*
|
||||
homeassistant.components.device_tracker.*
|
||||
homeassistant.components.devolo_home_control.*
|
||||
@ -78,6 +75,7 @@ homeassistant.components.dsmr.*
|
||||
homeassistant.components.dunehd.*
|
||||
homeassistant.components.efergy.*
|
||||
homeassistant.components.elgato.*
|
||||
homeassistant.components.elkm1.*
|
||||
homeassistant.components.esphome.*
|
||||
homeassistant.components.energy.*
|
||||
homeassistant.components.evil_genius_labs.*
|
||||
@ -88,6 +86,7 @@ homeassistant.components.flunearyou.*
|
||||
homeassistant.components.flux_led.*
|
||||
homeassistant.components.forecast_solar.*
|
||||
homeassistant.components.fritzbox.*
|
||||
homeassistant.components.fritzbox_callmonitor.*
|
||||
homeassistant.components.fronius.*
|
||||
homeassistant.components.frontend.*
|
||||
homeassistant.components.fritz.*
|
||||
@ -196,6 +195,7 @@ homeassistant.components.scene.*
|
||||
homeassistant.components.select.*
|
||||
homeassistant.components.sensor.*
|
||||
homeassistant.components.senseme.*
|
||||
homeassistant.components.senz.*
|
||||
homeassistant.components.shelly.*
|
||||
homeassistant.components.simplisafe.*
|
||||
homeassistant.components.slack.*
|
||||
|
66
CODEOWNERS
66
CODEOWNERS
@ -56,7 +56,6 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/alexa/ @home-assistant/cloud @ochlocracy
|
||||
/homeassistant/components/almond/ @gcampax @balloob
|
||||
/tests/components/almond/ @gcampax @balloob
|
||||
/homeassistant/components/alpha_vantage/ @fabaff
|
||||
/homeassistant/components/ambee/ @frenck
|
||||
/tests/components/ambee/ @frenck
|
||||
/homeassistant/components/amberelectric/ @madpilot
|
||||
@ -82,7 +81,6 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/aprs/ @PhilRW
|
||||
/homeassistant/components/arcam_fmj/ @elupus
|
||||
/tests/components/arcam_fmj/ @elupus
|
||||
/homeassistant/components/arest/ @fabaff
|
||||
/homeassistant/components/arris_tg2492lg/ @vanbalken
|
||||
/homeassistant/components/aseko_pool_live/ @milanmeu
|
||||
/tests/components/aseko_pool_live/ @milanmeu
|
||||
@ -121,7 +119,6 @@ build.json @home-assistant/supervisor
|
||||
/homeassistant/components/beewi_smartclim/ @alemuro
|
||||
/homeassistant/components/binary_sensor/ @home-assistant/core
|
||||
/tests/components/binary_sensor/ @home-assistant/core
|
||||
/homeassistant/components/bitcoin/ @fabaff
|
||||
/homeassistant/components/bizkaibus/ @UgaitzEtxebarria
|
||||
/homeassistant/components/blebox/ @bbx-a @bbx-jp
|
||||
/tests/components/blebox/ @bbx-a @bbx-jp
|
||||
@ -253,7 +250,6 @@ build.json @home-assistant/supervisor
|
||||
/homeassistant/components/dunehd/ @bieniu
|
||||
/tests/components/dunehd/ @bieniu
|
||||
/homeassistant/components/dwd_weather_warnings/ @runningman84 @stephan192 @Hummel95
|
||||
/homeassistant/components/dweet/ @fabaff
|
||||
/homeassistant/components/dynalite/ @ziv1234
|
||||
/tests/components/dynalite/ @ziv1234
|
||||
/homeassistant/components/eafm/ @Jc2k
|
||||
@ -332,7 +328,6 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/flipr/ @cnico
|
||||
/homeassistant/components/flo/ @dmulcahey
|
||||
/tests/components/flo/ @dmulcahey
|
||||
/homeassistant/components/flock/ @fabaff
|
||||
/homeassistant/components/flume/ @ChrisMandich @bdraco
|
||||
/tests/components/flume/ @ChrisMandich @bdraco
|
||||
/homeassistant/components/flunearyou/ @bachya
|
||||
@ -354,6 +349,8 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/fritz/ @mammuth @AaronDavidSchneider @chemelli74 @mib1185
|
||||
/homeassistant/components/fritzbox/ @mib1185 @flabbamann
|
||||
/tests/components/fritzbox/ @mib1185 @flabbamann
|
||||
/homeassistant/components/fritzbox_callmonitor/ @cdce8p
|
||||
/tests/components/fritzbox_callmonitor/ @cdce8p
|
||||
/homeassistant/components/fronius/ @nielstron @farmio
|
||||
/tests/components/fronius/ @nielstron @farmio
|
||||
/homeassistant/components/frontend/ @home-assistant/frontend
|
||||
@ -381,9 +378,8 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/gios/ @bieniu
|
||||
/homeassistant/components/github/ @timmo001 @ludeeus
|
||||
/tests/components/github/ @timmo001 @ludeeus
|
||||
/homeassistant/components/gitter/ @fabaff
|
||||
/homeassistant/components/glances/ @fabaff @engrbm87
|
||||
/tests/components/glances/ @fabaff @engrbm87
|
||||
/homeassistant/components/glances/ @engrbm87
|
||||
/tests/components/glances/ @engrbm87
|
||||
/homeassistant/components/goalzero/ @tkdrob
|
||||
/tests/components/goalzero/ @tkdrob
|
||||
/homeassistant/components/gogogate2/ @vangorra @bdraco
|
||||
@ -476,8 +472,8 @@ build.json @home-assistant/supervisor
|
||||
/homeassistant/components/image_processing/ @home-assistant/core
|
||||
/tests/components/image_processing/ @home-assistant/core
|
||||
/homeassistant/components/incomfort/ @zxdavb
|
||||
/homeassistant/components/influxdb/ @fabaff @mdegat01
|
||||
/tests/components/influxdb/ @fabaff @mdegat01
|
||||
/homeassistant/components/influxdb/ @mdegat01
|
||||
/tests/components/influxdb/ @mdegat01
|
||||
/homeassistant/components/input_boolean/ @home-assistant/core
|
||||
/tests/components/input_boolean/ @home-assistant/core
|
||||
/homeassistant/components/input_button/ @home-assistant/core
|
||||
@ -554,6 +550,7 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/lcn/ @alengwenus
|
||||
/homeassistant/components/lg_netcast/ @Drafteed
|
||||
/homeassistant/components/life360/ @pnbruckner
|
||||
/homeassistant/components/lifx/ @Djelibeybi
|
||||
/homeassistant/components/light/ @home-assistant/core
|
||||
/tests/components/light/ @home-assistant/core
|
||||
/homeassistant/components/linux_battery/ @fabaff
|
||||
@ -588,6 +585,8 @@ build.json @home-assistant/supervisor
|
||||
/homeassistant/components/matrix/ @tinloaf
|
||||
/homeassistant/components/mazda/ @bdr99
|
||||
/tests/components/mazda/ @bdr99
|
||||
/homeassistant/components/meater/ @Sotolotl @emontnemery
|
||||
/tests/components/meater/ @Sotolotl @emontnemery
|
||||
/homeassistant/components/media_player/ @home-assistant/core
|
||||
/tests/components/media_player/ @home-assistant/core
|
||||
/homeassistant/components/media_source/ @hunterjm
|
||||
@ -637,7 +636,6 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/motion_blinds/ @starkillerOG
|
||||
/homeassistant/components/motioneye/ @dermotduffy
|
||||
/tests/components/motioneye/ @dermotduffy
|
||||
/homeassistant/components/mpd/ @fabaff
|
||||
/homeassistant/components/mqtt/ @emontnemery
|
||||
/tests/components/mqtt/ @emontnemery
|
||||
/homeassistant/components/msteams/ @peroyvind
|
||||
@ -684,8 +682,6 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/nina/ @DeerMaximum
|
||||
/homeassistant/components/nissan_leaf/ @filcole
|
||||
/homeassistant/components/nmbs/ @thibmaek
|
||||
/homeassistant/components/no_ip/ @fabaff
|
||||
/tests/components/no_ip/ @fabaff
|
||||
/homeassistant/components/noaa_tides/ @jdelaney72
|
||||
/homeassistant/components/notify/ @home-assistant/core
|
||||
/tests/components/notify/ @home-assistant/core
|
||||
@ -758,8 +754,8 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/persistent_notification/ @home-assistant/core
|
||||
/homeassistant/components/philips_js/ @elupus
|
||||
/tests/components/philips_js/ @elupus
|
||||
/homeassistant/components/pi_hole/ @fabaff @johnluetke @shenxn
|
||||
/tests/components/pi_hole/ @fabaff @johnluetke @shenxn
|
||||
/homeassistant/components/pi_hole/ @johnluetke @shenxn
|
||||
/tests/components/pi_hole/ @johnluetke @shenxn
|
||||
/homeassistant/components/picnic/ @corneyl
|
||||
/tests/components/picnic/ @corneyl
|
||||
/homeassistant/components/pilight/ @trekky12
|
||||
@ -793,13 +789,15 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/pure_energie/ @klaasnicolaas
|
||||
/homeassistant/components/push/ @dgomes
|
||||
/tests/components/push/ @dgomes
|
||||
/homeassistant/components/pvoutput/ @fabaff @frenck
|
||||
/tests/components/pvoutput/ @fabaff @frenck
|
||||
/homeassistant/components/pvoutput/ @frenck
|
||||
/tests/components/pvoutput/ @frenck
|
||||
/homeassistant/components/pvpc_hourly_pricing/ @azogue
|
||||
/tests/components/pvpc_hourly_pricing/ @azogue
|
||||
/homeassistant/components/qbittorrent/ @geoffreylagaisse
|
||||
/homeassistant/components/qld_bushfire/ @exxamalte
|
||||
/tests/components/qld_bushfire/ @exxamalte
|
||||
/homeassistant/components/qnap_qsw/ @Noltari
|
||||
/tests/components/qnap_qsw/ @Noltari
|
||||
/homeassistant/components/quantum_gateway/ @cisasteelersfan
|
||||
/homeassistant/components/qvr_pro/ @oblogic7
|
||||
/homeassistant/components/qwikswitch/ @kellerza
|
||||
@ -857,6 +855,8 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/rtsp_to_webrtc/ @allenporter
|
||||
/homeassistant/components/ruckus_unleashed/ @gabe565
|
||||
/tests/components/ruckus_unleashed/ @gabe565
|
||||
/homeassistant/components/sabnzbd/ @shaiu
|
||||
/tests/components/sabnzbd/ @shaiu
|
||||
/homeassistant/components/safe_mode/ @home-assistant/core
|
||||
/tests/components/safe_mode/ @home-assistant/core
|
||||
/homeassistant/components/saj/ @fredericvl
|
||||
@ -887,6 +887,8 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/sensor/ @home-assistant/core
|
||||
/homeassistant/components/sentry/ @dcramer @frenck
|
||||
/tests/components/sentry/ @dcramer @frenck
|
||||
/homeassistant/components/senz/ @milanmeu
|
||||
/tests/components/senz/ @milanmeu
|
||||
/homeassistant/components/serial/ @fabaff
|
||||
/homeassistant/components/seven_segments/ @fabaff
|
||||
/homeassistant/components/sharkiq/ @JeffResc @funkybunch @AritroSaha10
|
||||
@ -915,6 +917,8 @@ build.json @home-assistant/supervisor
|
||||
/homeassistant/components/sleepiq/ @mfugate1 @kbickar
|
||||
/tests/components/sleepiq/ @mfugate1 @kbickar
|
||||
/homeassistant/components/slide/ @ualex73
|
||||
/homeassistant/components/slimproto/ @marcelveldt
|
||||
/tests/components/slimproto/ @marcelveldt
|
||||
/homeassistant/components/sma/ @kellerza @rklomp
|
||||
/tests/components/sma/ @kellerza @rklomp
|
||||
/homeassistant/components/smappee/ @bsmappee
|
||||
@ -929,8 +933,6 @@ build.json @home-assistant/supervisor
|
||||
/homeassistant/components/smhi/ @gjohansson-ST
|
||||
/tests/components/smhi/ @gjohansson-ST
|
||||
/homeassistant/components/sms/ @ocalvo
|
||||
/homeassistant/components/smtp/ @fabaff
|
||||
/tests/components/smtp/ @fabaff
|
||||
/homeassistant/components/solaredge/ @frenck
|
||||
/tests/components/solaredge/ @frenck
|
||||
/homeassistant/components/solaredge_local/ @drobtravels @scheric
|
||||
@ -957,8 +959,8 @@ build.json @home-assistant/supervisor
|
||||
/homeassistant/components/splunk/ @Bre77
|
||||
/homeassistant/components/spotify/ @frenck
|
||||
/tests/components/spotify/ @frenck
|
||||
/homeassistant/components/sql/ @dgomes
|
||||
/tests/components/sql/ @dgomes
|
||||
/homeassistant/components/sql/ @dgomes @gjohansson-ST
|
||||
/tests/components/sql/ @dgomes @gjohansson-ST
|
||||
/homeassistant/components/squeezebox/ @rajlaud
|
||||
/tests/components/squeezebox/ @rajlaud
|
||||
/homeassistant/components/srp_energy/ @briglx
|
||||
@ -967,6 +969,8 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/starline/ @anonym-tsk
|
||||
/homeassistant/components/statistics/ @fabaff @ThomDietrich
|
||||
/tests/components/statistics/ @fabaff @ThomDietrich
|
||||
/homeassistant/components/steam_online/ @tkdrob
|
||||
/tests/components/steam_online/ @tkdrob
|
||||
/homeassistant/components/steamist/ @bdraco
|
||||
/tests/components/steamist/ @bdraco
|
||||
/homeassistant/components/stiebel_eltron/ @fucm
|
||||
@ -1002,7 +1006,6 @@ build.json @home-assistant/supervisor
|
||||
/homeassistant/components/synology_dsm/ @hacf-fr @Quentame @mib1185
|
||||
/tests/components/synology_dsm/ @hacf-fr @Quentame @mib1185
|
||||
/homeassistant/components/synology_srm/ @aerialls
|
||||
/homeassistant/components/syslog/ @fabaff
|
||||
/homeassistant/components/system_bridge/ @timmo001
|
||||
/tests/components/system_bridge/ @timmo001
|
||||
/homeassistant/components/tado/ @michaelarnauts @north3221
|
||||
@ -1016,7 +1019,8 @@ build.json @home-assistant/supervisor
|
||||
/homeassistant/components/tapsaff/ @bazwilliams
|
||||
/homeassistant/components/tasmota/ @emontnemery
|
||||
/tests/components/tasmota/ @emontnemery
|
||||
/homeassistant/components/tautulli/ @ludeeus
|
||||
/homeassistant/components/tautulli/ @ludeeus @tkdrob
|
||||
/tests/components/tautulli/ @ludeeus @tkdrob
|
||||
/homeassistant/components/tellduslive/ @fredrike
|
||||
/tests/components/tellduslive/ @fredrike
|
||||
/homeassistant/components/template/ @PhracturedBlue @tetienne @home-assistant/core
|
||||
@ -1042,14 +1046,16 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/tomorrowio/ @raman325
|
||||
/homeassistant/components/totalconnect/ @austinmroczek
|
||||
/tests/components/totalconnect/ @austinmroczek
|
||||
/homeassistant/components/tplink/ @rytilahti @thegardenmonkey
|
||||
/tests/components/tplink/ @rytilahti @thegardenmonkey
|
||||
/homeassistant/components/tplink/ @rytilahti @thegardenmonkey @bdraco
|
||||
/tests/components/tplink/ @rytilahti @thegardenmonkey @bdraco
|
||||
/homeassistant/components/traccar/ @ludeeus
|
||||
/tests/components/traccar/ @ludeeus
|
||||
/homeassistant/components/trace/ @home-assistant/core
|
||||
/tests/components/trace/ @home-assistant/core
|
||||
/homeassistant/components/tractive/ @Danielhiversen @zhulik @bieniu
|
||||
/tests/components/tractive/ @Danielhiversen @zhulik @bieniu
|
||||
/homeassistant/components/trafikverket_ferry/ @gjohansson-ST
|
||||
/tests/components/trafikverket_ferry/ @gjohansson-ST
|
||||
/homeassistant/components/trafikverket_train/ @endor-force @gjohansson-ST
|
||||
/tests/components/trafikverket_train/ @endor-force @gjohansson-ST
|
||||
/homeassistant/components/trafikverket_weatherstation/ @endor-force @gjohansson-ST
|
||||
@ -1058,8 +1064,8 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/transmission/ @engrbm87 @JPHutchins
|
||||
/homeassistant/components/tts/ @pvizeli
|
||||
/tests/components/tts/ @pvizeli
|
||||
/homeassistant/components/tuya/ @Tuya @zlinoliver @METISU @frenck
|
||||
/tests/components/tuya/ @Tuya @zlinoliver @METISU @frenck
|
||||
/homeassistant/components/tuya/ @Tuya @zlinoliver @frenck
|
||||
/tests/components/tuya/ @Tuya @zlinoliver @frenck
|
||||
/homeassistant/components/twentemilieu/ @frenck
|
||||
/tests/components/twentemilieu/ @frenck
|
||||
/homeassistant/components/twinkly/ @dr1rrb @Robbie1221
|
||||
@ -1076,8 +1082,6 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/upcloud/ @scop
|
||||
/homeassistant/components/update/ @home-assistant/core
|
||||
/tests/components/update/ @home-assistant/core
|
||||
/homeassistant/components/updater/ @home-assistant/core
|
||||
/tests/components/updater/ @home-assistant/core
|
||||
/homeassistant/components/upnp/ @StevenLooman @ehendrix23
|
||||
/tests/components/upnp/ @StevenLooman @ehendrix23
|
||||
/homeassistant/components/uptime/ @frenck
|
||||
@ -1104,8 +1108,8 @@ build.json @home-assistant/supervisor
|
||||
/homeassistant/components/verisure/ @frenck
|
||||
/tests/components/verisure/ @frenck
|
||||
/homeassistant/components/versasense/ @flamm3blemuff1n
|
||||
/homeassistant/components/version/ @fabaff @ludeeus
|
||||
/tests/components/version/ @fabaff @ludeeus
|
||||
/homeassistant/components/version/ @ludeeus
|
||||
/tests/components/version/ @ludeeus
|
||||
/homeassistant/components/vesync/ @markperdue @webdjoe @thegardenmonkey
|
||||
/tests/components/vesync/ @markperdue @webdjoe @thegardenmonkey
|
||||
/homeassistant/components/vicare/ @oischinger
|
||||
|
@ -19,6 +19,7 @@ RUN \
|
||||
libpcap-dev \
|
||||
libturbojpeg0 \
|
||||
git \
|
||||
cmake \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
@ -147,9 +147,7 @@ class Data:
|
||||
if not bcrypt.checkpw(password.encode(), user_hash):
|
||||
raise InvalidAuth
|
||||
|
||||
def hash_password( # pylint: disable=no-self-use
|
||||
self, password: str, for_storage: bool = False
|
||||
) -> bytes:
|
||||
def hash_password(self, password: str, for_storage: bool = False) -> bytes:
|
||||
"""Encode a password."""
|
||||
hashed: bytes = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))
|
||||
|
||||
|
@ -4,10 +4,7 @@ from __future__ import annotations
|
||||
from abodepy.devices.alarm import AbodeAlarm as AbodeAl
|
||||
|
||||
import homeassistant.components.alarm_control_panel as alarm
|
||||
from homeassistant.components.alarm_control_panel.const import (
|
||||
SUPPORT_ALARM_ARM_AWAY,
|
||||
SUPPORT_ALARM_ARM_HOME,
|
||||
)
|
||||
from homeassistant.components.alarm_control_panel import AlarmControlPanelEntityFeature
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
STATE_ALARM_ARMED_AWAY,
|
||||
@ -38,7 +35,10 @@ class AbodeAlarm(AbodeDevice, alarm.AlarmControlPanelEntity):
|
||||
|
||||
_attr_icon = ICON
|
||||
_attr_code_arm_required = False
|
||||
_attr_supported_features = SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_AWAY
|
||||
_attr_supported_features = (
|
||||
AlarmControlPanelEntityFeature.ARM_HOME
|
||||
| AlarmControlPanelEntityFeature.ARM_AWAY
|
||||
)
|
||||
_device: AbodeAl
|
||||
|
||||
@property
|
||||
|
@ -3,6 +3,9 @@
|
||||
"abort": {
|
||||
"single_instance_allowed": "Ja configurat. Nom\u00e9s \u00e9s possible una sola configuraci\u00f3."
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "Alguns sensors no estan activats de manera predeterminada. Els pots activar des del registre d'entitats, despr\u00e9s de la configuraci\u00f3 de la integraci\u00f3.\nLa previsi\u00f3 meteorol\u00f2gica no est\u00e0 activada de manera predeterminada. Pots activar-la a les opcions de la integraci\u00f3."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Ha fallat la connexi\u00f3",
|
||||
"invalid_api_key": "Clau API inv\u00e0lida",
|
||||
|
@ -3,6 +3,9 @@
|
||||
"abort": {
|
||||
"single_instance_allowed": "Bereits konfiguriert. Nur eine einzige Konfiguration m\u00f6glich."
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "Einige Sensoren sind standardm\u00e4\u00dfig nicht aktiviert. Du kannst sie nach der Integrationskonfiguration in der Entit\u00e4tsregistrierung aktivieren.\nDie Wettervorhersage ist nicht standardm\u00e4\u00dfig aktiviert. Du kannst sie in den Integrationsoptionen aktivieren."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Verbindung fehlgeschlagen",
|
||||
"invalid_api_key": "Ung\u00fcltiger API-Schl\u00fcssel",
|
||||
|
@ -3,6 +3,9 @@
|
||||
"abort": {
|
||||
"single_instance_allowed": "\u0388\u03c7\u03b5\u03b9 \u03ae\u03b4\u03b7 \u03c1\u03c5\u03b8\u03bc\u03b9\u03c3\u03c4\u03b5\u03af. \u039c\u03cc\u03bd\u03bf \u03bc\u03af\u03b1 \u03b4\u03b9\u03b1\u03bc\u03cc\u03c1\u03c6\u03c9\u03c3\u03b7 \u03b5\u03af\u03bd\u03b1\u03b9 \u03b4\u03c5\u03bd\u03b1\u03c4\u03ae."
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "\u039f\u03c1\u03b9\u03c3\u03bc\u03ad\u03bd\u03bf\u03b9 \u03b1\u03b9\u03c3\u03b8\u03b7\u03c4\u03ae\u03c1\u03b5\u03c2 \u03b4\u03b5\u03bd \u03b5\u03af\u03bd\u03b1\u03b9 \u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03b7\u03bc\u03ad\u03bd\u03bf\u03b9 \u03b1\u03c0\u03cc \u03c0\u03c1\u03bf\u03b5\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae. \u039c\u03c0\u03bf\u03c1\u03b5\u03af\u03c4\u03b5 \u03bd\u03b1 \u03c4\u03b1 \u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03c4\u03b5 \u03c3\u03c4\u03bf \u03bc\u03b7\u03c4\u03c1\u03ce\u03bf \u03bf\u03bd\u03c4\u03bf\u03c4\u03ae\u03c4\u03c9\u03bd \u03bc\u03b5\u03c4\u03ac \u03c4\u03b7 \u03b4\u03b9\u03b1\u03bc\u03cc\u03c1\u03c6\u03c9\u03c3\u03b7 \u03c4\u03b7\u03c2 \u03b5\u03bd\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7\u03c2.\n \u0397 \u03c0\u03c1\u03cc\u03b3\u03bd\u03c9\u03c3\u03b7 \u03ba\u03b1\u03b9\u03c1\u03bf\u03cd \u03b4\u03b5\u03bd \u03b5\u03af\u03bd\u03b1\u03b9 \u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03b7\u03bc\u03ad\u03bd\u03b7 \u03b1\u03c0\u03cc \u03c0\u03c1\u03bf\u03b5\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae. \u039c\u03c0\u03bf\u03c1\u03b5\u03af\u03c4\u03b5 \u03bd\u03b1 \u03c4\u03bf \u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03c4\u03b5 \u03c3\u03c4\u03b9\u03c2 \u03b5\u03c0\u03b9\u03bb\u03bf\u03b3\u03ad\u03c2 \u03b5\u03bd\u03c3\u03c9\u03bc\u03ac\u03c4\u03c9\u03c3\u03b7\u03c2."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7\u03c2",
|
||||
"invalid_api_key": "\u039c\u03b7 \u03ad\u03b3\u03ba\u03c5\u03c1\u03bf \u03ba\u03bb\u03b5\u03b9\u03b4\u03af API",
|
||||
|
@ -3,6 +3,9 @@
|
||||
"abort": {
|
||||
"single_instance_allowed": "Already configured. Only a single configuration possible."
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "Some sensors are not enabled by default. You can enable them in the entity registry after the integration configuration.\nWeather forecast is not enabled by default. You can enable it in the integration options."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Failed to connect",
|
||||
"invalid_api_key": "Invalid API key",
|
||||
|
@ -3,6 +3,9 @@
|
||||
"abort": {
|
||||
"single_instance_allowed": "Sidumine juba tehtud. V\u00f5imalik on ainult 1 sidumine."
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "M\u00f5ned andurid ei ole vaikimisi lubatud. Saad neid lubada \u00fcksuse registris p\u00e4rast sidumise seadistamist.\nIlmaprognoos ei ole vaikimisi lubatud. Saad selle lubada sidumise valikutes."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "\u00dchendamine nurjus",
|
||||
"invalid_api_key": "API v\u00f5ti on vale",
|
||||
|
@ -3,6 +3,9 @@
|
||||
"abort": {
|
||||
"single_instance_allowed": "D\u00e9j\u00e0 configur\u00e9. Une seule configuration possible."
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "Certains capteurs ne sont pas activ\u00e9s par d\u00e9faut. Vous pouvez les activer dans le registre des entit\u00e9s une fois la configuration de l'int\u00e9gration termin\u00e9e.\nLes pr\u00e9visions m\u00e9t\u00e9orologiques ne sont pas activ\u00e9es par d\u00e9faut. Vous pouvez les activer dans les options de l'int\u00e9gration."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "\u00c9chec de connexion",
|
||||
"invalid_api_key": "Cl\u00e9 d'API non valide",
|
||||
@ -16,7 +19,7 @@
|
||||
"longitude": "Longitude",
|
||||
"name": "Nom"
|
||||
},
|
||||
"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.",
|
||||
"description": "Si vous avez besoin d'aide pour la configuration, consultez\u00a0: 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 une fois la configuration de l'int\u00e9gration termin\u00e9e.\nLes pr\u00e9visions m\u00e9t\u00e9orologiques ne sont pas activ\u00e9es par d\u00e9faut. Vous pouvez les activer dans les options de l'int\u00e9gration.",
|
||||
"title": "AccuWeather"
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,9 @@
|
||||
"abort": {
|
||||
"single_instance_allowed": "M\u00e1r konfigur\u00e1lva van. Csak egy konfigur\u00e1ci\u00f3 lehets\u00e9ges."
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "Egyes \u00e9rz\u00e9kel\u0151k alap\u00e9rtelmez\u00e9s szerint nincsenek enged\u00e9lyezve. Az integr\u00e1ci\u00f3s konfigur\u00e1ci\u00f3 ut\u00e1n enged\u00e9lyezheti \u0151ket az entit\u00e1s rendszerle\u00edr\u00f3 adatb\u00e1zis\u00e1ban.\nAz id\u0151j\u00e1r\u00e1s-el\u0151rejelz\u00e9s alap\u00e9rtelmez\u00e9s szerint nincs enged\u00e9lyezve. Ezt az integr\u00e1ci\u00f3s be\u00e1ll\u00edt\u00e1sokban enged\u00e9lyezheti."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Sikertelen csatlakoz\u00e1s",
|
||||
"invalid_api_key": "\u00c9rv\u00e9nytelen API kulcs",
|
||||
@ -14,7 +17,7 @@
|
||||
"api_key": "API kulcs",
|
||||
"latitude": "Sz\u00e9less\u00e9g",
|
||||
"longitude": "Hossz\u00fas\u00e1g",
|
||||
"name": "N\u00e9v"
|
||||
"name": "Elnevez\u00e9s"
|
||||
},
|
||||
"description": "Ha seg\u00edts\u00e9gre van sz\u00fcks\u00e9ge a konfigur\u00e1l\u00e1shoz, n\u00e9zze meg itt: https://www.home-assistant.io/integrations/accuweather/ \n\nEgyes \u00e9rz\u00e9kel\u0151k alap\u00e9rtelmez\u00e9s szerint nincsenek enged\u00e9lyezve. Az integr\u00e1ci\u00f3s konfigur\u00e1ci\u00f3 ut\u00e1n enged\u00e9lyezheti \u0151ket az entit\u00e1s-nyilv\u00e1ntart\u00e1sban.\nAz id\u0151j\u00e1r\u00e1s-el\u0151rejelz\u00e9s alap\u00e9rtelmez\u00e9s szerint nincs enged\u00e9lyezve. Ezt az integr\u00e1ci\u00f3s be\u00e1ll\u00edt\u00e1sokban enged\u00e9lyezheti.",
|
||||
"title": "AccuWeather"
|
||||
|
@ -3,6 +3,9 @@
|
||||
"abort": {
|
||||
"single_instance_allowed": "Sudah dikonfigurasi. Hanya satu konfigurasi yang diizinkan."
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "Beberapa sensor tidak diaktifkan secara default. Anda dapat mengaktifkannya di registri entitas setelah konfigurasi integrasi.\nPrakiraan cuaca tidak diaktifkan secara default. Anda dapat mengaktifkannya di opsi integrasi."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Gagal terhubung",
|
||||
"invalid_api_key": "Kunci API tidak valid",
|
||||
|
@ -3,6 +3,9 @@
|
||||
"abort": {
|
||||
"single_instance_allowed": "Gi\u00e0 configurato. \u00c8 possibile una sola configurazione."
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "Alcuni sensori non sono abilitati per impostazione predefinita. Puoi abilitarli nel registro delle entit\u00e0 dopo la configurazione dell'integrazione.\nLe previsioni del tempo non sono abilitate per impostazione predefinita. Puoi abilitarlo nelle opzioni di integrazione."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Impossibile connettersi",
|
||||
"invalid_api_key": "Chiave API non valida",
|
||||
|
@ -3,6 +3,9 @@
|
||||
"abort": {
|
||||
"single_instance_allowed": "\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u5358\u4e00\u306e\u8a2d\u5b9a\u3057\u304b\u3067\u304d\u307e\u305b\u3093\u3002"
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "\u4e00\u90e8\u306e\u30bb\u30f3\u30b5\u30fc\u306f\u3001\u30c7\u30d5\u30a9\u30eb\u30c8\u3067\u306f\u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u305b\u3093\u3002\u30a4\u30f3\u30c6\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u306e\u69cb\u6210\u5f8c\u3001\u30a8\u30f3\u30c6\u30a3\u30c6\u30a3\u30ec\u30b8\u30b9\u30c8\u30ea\u3067\u305d\u308c\u3089\u3092\u6709\u52b9\u306b\u3067\u304d\u307e\u3059\u3002\n\u5929\u6c17\u4e88\u5831\u306f\u30c7\u30d5\u30a9\u30eb\u30c8\u3067\u306f\u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u305b\u3093\u3002\u30a4\u30f3\u30c6\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3067\u6709\u52b9\u306b\u3067\u304d\u307e\u3059\u3002"
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f",
|
||||
"invalid_api_key": "\u7121\u52b9\u306aAPI\u30ad\u30fc",
|
||||
|
@ -3,6 +3,9 @@
|
||||
"abort": {
|
||||
"single_instance_allowed": "Al geconfigureerd. Slechts een enkele configuratie mogelijk."
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "Sommige sensoren zijn standaard niet ingeschakeld. U kunt ze inschakelen in het entiteitenregister na de integratieconfiguratie.\nWeersvoorspelling is niet standaard ingeschakeld. U kunt deze inschakelen in de integratieopties."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Kan geen verbinding maken",
|
||||
"invalid_api_key": "API-sleutel",
|
||||
|
@ -3,6 +3,9 @@
|
||||
"abort": {
|
||||
"single_instance_allowed": "Allerede konfigurert. Bare \u00e9n enkelt konfigurasjon er mulig."
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "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 integreringsalternativene."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Tilkobling mislyktes",
|
||||
"invalid_api_key": "Ugyldig API-n\u00f8kkel",
|
||||
|
@ -3,6 +3,9 @@
|
||||
"abort": {
|
||||
"single_instance_allowed": "Ju\u017c skonfigurowano. Mo\u017cliwa jest tylko jedna konfiguracja."
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "Niekt\u00f3re sensory nie s\u0105 domy\u015blnie w\u0142\u0105czone. Mo\u017cesz je w\u0142\u0105czy\u0107 w rejestrze encji po skonfigurowaniu integracji.\nPrognoza pogody nie jest domy\u015blnie w\u0142\u0105czona. Mo\u017cesz to w\u0142\u0105czy\u0107 w opcjach integracji."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Nie mo\u017cna nawi\u0105za\u0107 po\u0142\u0105czenia",
|
||||
"invalid_api_key": "Nieprawid\u0142owy klucz API",
|
||||
|
@ -3,6 +3,9 @@
|
||||
"abort": {
|
||||
"single_instance_allowed": "J\u00e1 configurado. Apenas uma configura\u00e7\u00e3o \u00e9 poss\u00edvel."
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "Alguns sensores n\u00e3o s\u00e3o ativados por padr\u00e3o. Voc\u00ea pode habilit\u00e1-los no registro da entidade ap\u00f3s a configura\u00e7\u00e3o da integra\u00e7\u00e3o.\n A previs\u00e3o do tempo n\u00e3o est\u00e1 habilitada por padr\u00e3o. Voc\u00ea pode habilit\u00e1-lo nas op\u00e7\u00f5es de integra\u00e7\u00e3o."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Falha ao conectar",
|
||||
"invalid_api_key": "Chave de API inv\u00e1lida",
|
||||
|
@ -3,6 +3,9 @@
|
||||
"abort": {
|
||||
"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."
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0435\u043d\u0441\u043e\u0440\u044b \u0441\u043a\u0440\u044b\u0442\u044b \u0438 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u043f\u043e\u0433\u043e\u0434\u044b. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0443\u0436\u043d\u044b\u0445 \u0441\u0435\u043d\u0441\u043e\u0440\u043e\u0432 \u0432 \u0440\u0435\u0435\u0441\u0442\u0440\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0438 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u043f\u043e\u0433\u043e\u0434\u044b \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f.",
|
||||
"invalid_api_key": "\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 API.",
|
||||
|
@ -3,6 +3,9 @@
|
||||
"abort": {
|
||||
"single_instance_allowed": "Zaten yap\u0131land\u0131r\u0131lm\u0131\u015f. Yaln\u0131zca tek bir konfig\u00fcrasyon m\u00fcmk\u00fcnd\u00fcr."
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "Baz\u0131 sens\u00f6rler varsay\u0131lan olarak etkin de\u011fildir. Bunlar\u0131, entegrasyon yap\u0131land\u0131rmas\u0131ndan sonra varl\u0131k kay\u0131t defterinde etkinle\u015ftirebilirsiniz.\n Hava tahmini varsay\u0131lan olarak etkin de\u011fildir. Entegrasyon se\u00e7eneklerinde etkinle\u015ftirebilirsiniz."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Ba\u011flanma hatas\u0131",
|
||||
"invalid_api_key": "Ge\u00e7ersiz API anahtar\u0131",
|
||||
|
@ -3,6 +3,9 @@
|
||||
"abort": {
|
||||
"single_instance_allowed": "\u5df2\u7d93\u8a2d\u5b9a\u5b8c\u6210\u3001\u50c5\u80fd\u8a2d\u5b9a\u4e00\u7d44\u88dd\u7f6e\u3002"
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "\u90e8\u5206\u611f\u6e2c\u5668\u9810\u8a2d\u70ba\u4e0d\u555f\u7528\u72c0\u614b\u3002\u53ef\u4ee5\u7a0d\u5f8c\u65bc\u6574\u5408\u8a2d\u5b9a\u9801\u9762\u4e2d\u7684\u5be6\u9ad4\u8a3b\u518a\u8868\u9032\u884c\u555f\u7528\u3002\n\u5929\u6c23\u9810\u5831\u9810\u8a2d\u70ba\u4e0d\u555f\u7528\u3001\u53ef\u4ee5\u65bc\u6574\u5408\u9078\u9805\u4e2d\u9032\u884c\u555f\u7528\u3002"
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "\u9023\u7dda\u5931\u6557",
|
||||
"invalid_api_key": "API \u91d1\u9470\u7121\u6548",
|
||||
|
@ -3,15 +3,8 @@ from __future__ import annotations
|
||||
|
||||
from homeassistant.components.cover import (
|
||||
ATTR_POSITION,
|
||||
SUPPORT_CLOSE,
|
||||
SUPPORT_CLOSE_TILT,
|
||||
SUPPORT_OPEN,
|
||||
SUPPORT_OPEN_TILT,
|
||||
SUPPORT_SET_POSITION,
|
||||
SUPPORT_SET_TILT_POSITION,
|
||||
SUPPORT_STOP,
|
||||
SUPPORT_STOP_TILT,
|
||||
CoverEntity,
|
||||
CoverEntityFeature,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
@ -79,14 +72,17 @@ class AcmedaCover(AcmedaBase, CoverEntity):
|
||||
supported_features = 0
|
||||
if self.current_cover_position is not None:
|
||||
supported_features |= (
|
||||
SUPPORT_OPEN | SUPPORT_CLOSE | SUPPORT_STOP | SUPPORT_SET_POSITION
|
||||
CoverEntityFeature.OPEN
|
||||
| CoverEntityFeature.CLOSE
|
||||
| CoverEntityFeature.STOP
|
||||
| CoverEntityFeature.SET_POSITION
|
||||
)
|
||||
if self.current_cover_tilt_position is not None:
|
||||
supported_features |= (
|
||||
SUPPORT_OPEN_TILT
|
||||
| SUPPORT_CLOSE_TILT
|
||||
| SUPPORT_STOP_TILT
|
||||
| SUPPORT_SET_TILT_POSITION
|
||||
CoverEntityFeature.OPEN_TILT
|
||||
| CoverEntityFeature.CLOSE_TILT
|
||||
| CoverEntityFeature.STOP_TILT
|
||||
| CoverEntityFeature.SET_TILT_POSITION
|
||||
)
|
||||
|
||||
return supported_features
|
||||
|
@ -7,11 +7,7 @@ from adax import Adax
|
||||
from adax_local import Adax as AdaxLocal
|
||||
|
||||
from homeassistant.components.climate import ClimateEntity
|
||||
from homeassistant.components.climate.const import (
|
||||
HVAC_MODE_HEAT,
|
||||
HVAC_MODE_OFF,
|
||||
SUPPORT_TARGET_TEMPERATURE,
|
||||
)
|
||||
from homeassistant.components.climate.const import ClimateEntityFeature, HVACMode
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
ATTR_TEMPERATURE,
|
||||
@ -65,10 +61,10 @@ async def async_setup_entry(
|
||||
class AdaxDevice(ClimateEntity):
|
||||
"""Representation of a heater."""
|
||||
|
||||
_attr_hvac_modes = [HVAC_MODE_HEAT, HVAC_MODE_OFF]
|
||||
_attr_hvac_modes = [HVACMode.HEAT, HVACMode.OFF]
|
||||
_attr_max_temp = 35
|
||||
_attr_min_temp = 5
|
||||
_attr_supported_features = SUPPORT_TARGET_TEMPERATURE
|
||||
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
_attr_target_temperature_step = PRECISION_WHOLE
|
||||
_attr_temperature_unit = TEMP_CELSIUS
|
||||
|
||||
@ -86,12 +82,12 @@ class AdaxDevice(ClimateEntity):
|
||||
|
||||
async def async_set_hvac_mode(self, hvac_mode: str) -> None:
|
||||
"""Set hvac mode."""
|
||||
if hvac_mode == HVAC_MODE_HEAT:
|
||||
if hvac_mode == HVACMode.HEAT:
|
||||
temperature = max(self.min_temp, self.target_temperature or self.min_temp)
|
||||
await self._adax_data_handler.set_room_target_temperature(
|
||||
self._device_id, temperature, True
|
||||
)
|
||||
elif hvac_mode == HVAC_MODE_OFF:
|
||||
elif hvac_mode == HVACMode.OFF:
|
||||
await self._adax_data_handler.set_room_target_temperature(
|
||||
self._device_id, self.min_temp, False
|
||||
)
|
||||
@ -116,10 +112,10 @@ class AdaxDevice(ClimateEntity):
|
||||
self._attr_current_temperature = room.get("temperature")
|
||||
self._attr_target_temperature = room.get("targetTemperature")
|
||||
if room["heatingEnabled"]:
|
||||
self._attr_hvac_mode = HVAC_MODE_HEAT
|
||||
self._attr_hvac_mode = HVACMode.HEAT
|
||||
self._attr_icon = "mdi:radiator"
|
||||
else:
|
||||
self._attr_hvac_mode = HVAC_MODE_OFF
|
||||
self._attr_hvac_mode = HVACMode.OFF
|
||||
self._attr_icon = "mdi:radiator-off"
|
||||
return
|
||||
|
||||
@ -127,11 +123,11 @@ class AdaxDevice(ClimateEntity):
|
||||
class LocalAdaxDevice(ClimateEntity):
|
||||
"""Representation of a heater."""
|
||||
|
||||
_attr_hvac_modes = [HVAC_MODE_HEAT]
|
||||
_attr_hvac_mode = HVAC_MODE_HEAT
|
||||
_attr_hvac_modes = [HVACMode.HEAT]
|
||||
_attr_hvac_mode = HVACMode.HEAT
|
||||
_attr_max_temp = 35
|
||||
_attr_min_temp = 5
|
||||
_attr_supported_features = SUPPORT_TARGET_TEMPERATURE
|
||||
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
_attr_target_temperature_step = PRECISION_WHOLE
|
||||
_attr_temperature_unit = TEMP_CELSIUS
|
||||
|
||||
|
@ -20,9 +20,9 @@
|
||||
"local": {
|
||||
"data": {
|
||||
"wifi_pswd": "WiFi jelsz\u00f3",
|
||||
"wifi_ssid": "WiFi ssid"
|
||||
"wifi_ssid": "Wi-Fi SSID"
|
||||
},
|
||||
"description": "\u00c1ll\u00edtsa vissza a f\u0171t\u0151berendez\u00e9st a + \u00e9s az OK gomb nyomvatart\u00e1s\u00e1val, m\u00edg a kijelz\u0151n a \"Reset\" (Vissza\u00e1ll\u00edt\u00e1s) felirat nem jelenik meg. Ezut\u00e1n nyomja meg \u00e9s tartsa lenyomva a f\u0171t\u0151berendez\u00e9s OK gombj\u00e1t, am\u00edg a k\u00e9k led villogni nem kezd, majd nyomja meg a K\u00fcld\u00e9s gombot. A f\u0171t\u0151berendez\u00e9s konfigur\u00e1l\u00e1sa n\u00e9h\u00e1ny percet vehet ig\u00e9nybe."
|
||||
"description": "\u00c1ll\u00edtsa vissza a f\u0171t\u0151berendez\u00e9st a + \u00e9s az OK gomb nyomvatart\u00e1s\u00e1val, m\u00edg a kijelz\u0151n a \"Reset\" (Vissza\u00e1ll\u00edt\u00e1s) felirat nem jelenik meg. Ezut\u00e1n nyomja meg \u00e9s tartsa lenyomva a f\u0171t\u0151berendez\u00e9s OK gombj\u00e1t, am\u00edg a k\u00e9k led villogni nem kezd, l\u00e9pjen tov\u00e1bb. A f\u0171t\u0151berendez\u00e9s konfigur\u00e1l\u00e1sa n\u00e9h\u00e1ny percet vehet ig\u00e9nybe."
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
|
@ -31,7 +31,7 @@
|
||||
"host": "Host",
|
||||
"password": "Wachtwoord"
|
||||
},
|
||||
"description": "Selecteer verbindingstype. Lokaal vereist verwarming met bluetooth"
|
||||
"description": "Selecteer verbindingstype. Lokaal vereist verwarming met Bluetooth."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,11 +8,8 @@ from homeassistant.components.cover import (
|
||||
ATTR_POSITION,
|
||||
DEVICE_CLASSES_SCHEMA,
|
||||
PLATFORM_SCHEMA,
|
||||
SUPPORT_CLOSE,
|
||||
SUPPORT_OPEN,
|
||||
SUPPORT_SET_POSITION,
|
||||
SUPPORT_STOP,
|
||||
CoverEntity,
|
||||
CoverEntityFeature,
|
||||
)
|
||||
from homeassistant.const import CONF_DEVICE_CLASS, CONF_NAME
|
||||
from homeassistant.core import HomeAssistant
|
||||
@ -117,11 +114,13 @@ class AdsCover(AdsEntity, CoverEntity):
|
||||
self._ads_var_close = ads_var_close
|
||||
self._ads_var_stop = ads_var_stop
|
||||
self._attr_device_class = device_class
|
||||
self._attr_supported_features = SUPPORT_OPEN | SUPPORT_CLOSE
|
||||
self._attr_supported_features = (
|
||||
CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE
|
||||
)
|
||||
if ads_var_stop is not None:
|
||||
self._attr_supported_features |= SUPPORT_STOP
|
||||
self._attr_supported_features |= CoverEntityFeature.STOP
|
||||
if ads_var_pos_set is not None:
|
||||
self._attr_supported_features |= SUPPORT_SET_POSITION
|
||||
self._attr_supported_features |= CoverEntityFeature.SET_POSITION
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Register device notification."""
|
||||
|
@ -7,7 +7,7 @@ import voluptuous as vol
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
PLATFORM_SCHEMA,
|
||||
SUPPORT_BRIGHTNESS,
|
||||
ColorMode,
|
||||
LightEntity,
|
||||
)
|
||||
from homeassistant.const import CONF_NAME
|
||||
@ -60,7 +60,11 @@ class AdsLight(AdsEntity, LightEntity):
|
||||
self._state_dict[STATE_KEY_BRIGHTNESS] = None
|
||||
self._ads_var_brightness = ads_var_brightness
|
||||
if ads_var_brightness is not None:
|
||||
self._attr_supported_features = SUPPORT_BRIGHTNESS
|
||||
self._attr_color_mode = ColorMode.BRIGHTNESS
|
||||
self._attr_supported_color_modes = {ColorMode.BRIGHTNESS}
|
||||
else:
|
||||
self._attr_color_mode = ColorMode.ONOFF
|
||||
self._attr_supported_color_modes = {ColorMode.ONOFF}
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Register device notification."""
|
||||
|
@ -9,15 +9,8 @@ from homeassistant.components.climate.const import (
|
||||
FAN_HIGH,
|
||||
FAN_LOW,
|
||||
FAN_MEDIUM,
|
||||
HVAC_MODE_AUTO,
|
||||
HVAC_MODE_COOL,
|
||||
HVAC_MODE_DRY,
|
||||
HVAC_MODE_FAN_ONLY,
|
||||
HVAC_MODE_HEAT,
|
||||
HVAC_MODE_HEAT_COOL,
|
||||
HVAC_MODE_OFF,
|
||||
SUPPORT_FAN_MODE,
|
||||
SUPPORT_TARGET_TEMPERATURE,
|
||||
ClimateEntityFeature,
|
||||
HVACMode,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ATTR_TEMPERATURE, PRECISION_WHOLE, TEMP_CELSIUS
|
||||
@ -35,20 +28,20 @@ from .const import (
|
||||
from .entity import AdvantageAirEntity
|
||||
|
||||
ADVANTAGE_AIR_HVAC_MODES = {
|
||||
"heat": HVAC_MODE_HEAT,
|
||||
"cool": HVAC_MODE_COOL,
|
||||
"vent": HVAC_MODE_FAN_ONLY,
|
||||
"dry": HVAC_MODE_DRY,
|
||||
"myauto": HVAC_MODE_AUTO,
|
||||
"heat": HVACMode.HEAT,
|
||||
"cool": HVACMode.COOL,
|
||||
"vent": HVACMode.FAN_ONLY,
|
||||
"dry": HVACMode.DRY,
|
||||
"myauto": HVACMode.AUTO,
|
||||
}
|
||||
HASS_HVAC_MODES = {v: k for k, v in ADVANTAGE_AIR_HVAC_MODES.items()}
|
||||
|
||||
AC_HVAC_MODES = [
|
||||
HVAC_MODE_OFF,
|
||||
HVAC_MODE_COOL,
|
||||
HVAC_MODE_HEAT,
|
||||
HVAC_MODE_FAN_ONLY,
|
||||
HVAC_MODE_DRY,
|
||||
HVACMode.OFF,
|
||||
HVACMode.COOL,
|
||||
HVACMode.HEAT,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.DRY,
|
||||
]
|
||||
|
||||
ADVANTAGE_AIR_FAN_MODES = {
|
||||
@ -61,7 +54,7 @@ HASS_FAN_MODES = {v: k for k, v in ADVANTAGE_AIR_FAN_MODES.items()}
|
||||
FAN_SPEEDS = {FAN_LOW: 30, FAN_MEDIUM: 60, FAN_HIGH: 100}
|
||||
|
||||
ADVANTAGE_AIR_SERVICE_SET_MYZONE = "set_myzone"
|
||||
ZONE_HVAC_MODES = [HVAC_MODE_OFF, HVAC_MODE_HEAT_COOL]
|
||||
ZONE_HVAC_MODES = [HVACMode.OFF, HVACMode.HEAT_COOL]
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
@ -108,7 +101,9 @@ class AdvantageAirAC(AdvantageAirClimateEntity):
|
||||
|
||||
_attr_fan_modes = [FAN_AUTO, FAN_LOW, FAN_MEDIUM, FAN_HIGH]
|
||||
_attr_hvac_modes = AC_HVAC_MODES
|
||||
_attr_supported_features = SUPPORT_TARGET_TEMPERATURE | SUPPORT_FAN_MODE
|
||||
_attr_supported_features = (
|
||||
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.FAN_MODE
|
||||
)
|
||||
|
||||
def __init__(self, instance, ac_key):
|
||||
"""Initialize an AdvantageAir AC unit."""
|
||||
@ -116,7 +111,7 @@ class AdvantageAirAC(AdvantageAirClimateEntity):
|
||||
self._attr_name = self._ac["name"]
|
||||
self._attr_unique_id = f'{self.coordinator.data["system"]["rid"]}-{ac_key}'
|
||||
if self._ac.get("myAutoModeEnabled"):
|
||||
self._attr_hvac_modes = AC_HVAC_MODES + [HVAC_MODE_AUTO]
|
||||
self._attr_hvac_modes = AC_HVAC_MODES + [HVACMode.AUTO]
|
||||
|
||||
@property
|
||||
def target_temperature(self):
|
||||
@ -128,7 +123,7 @@ class AdvantageAirAC(AdvantageAirClimateEntity):
|
||||
"""Return the current HVAC modes."""
|
||||
if self._ac["state"] == ADVANTAGE_AIR_STATE_ON:
|
||||
return ADVANTAGE_AIR_HVAC_MODES.get(self._ac["mode"])
|
||||
return HVAC_MODE_OFF
|
||||
return HVACMode.OFF
|
||||
|
||||
@property
|
||||
def fan_mode(self):
|
||||
@ -137,7 +132,7 @@ class AdvantageAirAC(AdvantageAirClimateEntity):
|
||||
|
||||
async def async_set_hvac_mode(self, hvac_mode):
|
||||
"""Set the HVAC Mode and State."""
|
||||
if hvac_mode == HVAC_MODE_OFF:
|
||||
if hvac_mode == HVACMode.OFF:
|
||||
await self.async_change(
|
||||
{self.ac_key: {"info": {"state": ADVANTAGE_AIR_STATE_OFF}}}
|
||||
)
|
||||
@ -169,7 +164,7 @@ class AdvantageAirZone(AdvantageAirClimateEntity):
|
||||
"""AdvantageAir Zone control."""
|
||||
|
||||
_attr_hvac_modes = ZONE_HVAC_MODES
|
||||
_attr_supported_features = SUPPORT_TARGET_TEMPERATURE
|
||||
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
|
||||
def __init__(self, instance, ac_key, zone_key):
|
||||
"""Initialize an AdvantageAir Zone control."""
|
||||
@ -183,8 +178,8 @@ class AdvantageAirZone(AdvantageAirClimateEntity):
|
||||
def hvac_mode(self):
|
||||
"""Return the current state as HVAC mode."""
|
||||
if self._zone["state"] == ADVANTAGE_AIR_STATE_OPEN:
|
||||
return HVAC_MODE_HEAT_COOL
|
||||
return HVAC_MODE_OFF
|
||||
return HVACMode.HEAT_COOL
|
||||
return HVACMode.OFF
|
||||
|
||||
@property
|
||||
def current_temperature(self):
|
||||
@ -198,7 +193,7 @@ class AdvantageAirZone(AdvantageAirClimateEntity):
|
||||
|
||||
async def async_set_hvac_mode(self, hvac_mode):
|
||||
"""Set the HVAC Mode and State."""
|
||||
if hvac_mode == HVAC_MODE_OFF:
|
||||
if hvac_mode == HVACMode.OFF:
|
||||
await self.async_change(
|
||||
{
|
||||
self.ac_key: {
|
||||
|
@ -1,11 +1,9 @@
|
||||
"""Cover platform for Advantage Air integration."""
|
||||
from homeassistant.components.cover import (
|
||||
ATTR_POSITION,
|
||||
SUPPORT_CLOSE,
|
||||
SUPPORT_OPEN,
|
||||
SUPPORT_SET_POSITION,
|
||||
CoverDeviceClass,
|
||||
CoverEntity,
|
||||
CoverEntityFeature,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
@ -43,7 +41,11 @@ class AdvantageAirZoneVent(AdvantageAirEntity, CoverEntity):
|
||||
"""Advantage Air Cover Class."""
|
||||
|
||||
_attr_device_class = CoverDeviceClass.DAMPER
|
||||
_attr_supported_features = SUPPORT_OPEN | SUPPORT_CLOSE | SUPPORT_SET_POSITION
|
||||
_attr_supported_features = (
|
||||
CoverEntityFeature.OPEN
|
||||
| CoverEntityFeature.CLOSE
|
||||
| CoverEntityFeature.SET_POSITION
|
||||
)
|
||||
|
||||
def __init__(self, instance, ac_key, zone_key):
|
||||
"""Initialize an Advantage Air Cover Class."""
|
||||
|
@ -14,7 +14,7 @@
|
||||
"longitude": "Longitud",
|
||||
"name": "Nom de la integraci\u00f3"
|
||||
},
|
||||
"description": "Configura la integraci\u00f3 d'AEMET OpenData. Per generar la clau API, v\u00e9s a https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"description": "Per generar la clau API, v\u00e9s a https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"title": "AEMET OpenData"
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
"longitude": "L\u00e4ngengrad",
|
||||
"name": "Name der Integration"
|
||||
},
|
||||
"description": "Richte die AEMET OpenData Integration ein. Um den API-Schl\u00fcssel zu generieren, besuche https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"description": "Um den API-Schl\u00fcssel zu generieren, besuche https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"title": "AEMET OpenData"
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
"longitude": "Longitude",
|
||||
"name": "Name of the integration"
|
||||
},
|
||||
"description": "Set up AEMET OpenData integration. To generate API key go to https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"description": "To generate API key go to https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"title": "AEMET OpenData"
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
"longitude": "Pikkuskraad",
|
||||
"name": "Sidumise nimi"
|
||||
},
|
||||
"description": "Seadista AEMET OpenData sidumine. API v\u00f5tme loomiseks mine aadressile https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"description": "API-v\u00f5tme loomiseks mine aadressile https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"title": "AEMET OpenData"
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
"longitude": "Longitude",
|
||||
"name": "Nom de l'int\u00e9gration"
|
||||
},
|
||||
"description": "Configurez l'int\u00e9gration AEMET OpenData. Pour g\u00e9n\u00e9rer la cl\u00e9 API, acc\u00e9dez \u00e0 https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"description": "Pour g\u00e9n\u00e9rer une cl\u00e9 d'API, rendez-vous sur https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"title": "AEMET OpenData"
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
"longitude": "Hossz\u00fas\u00e1g",
|
||||
"name": "Az integr\u00e1ci\u00f3 neve"
|
||||
},
|
||||
"description": "\u00c1ll\u00edtsa be az AEMET OpenData integr\u00e1ci\u00f3t. Az API-kulcs el\u0151\u00e1ll\u00edt\u00e1s\u00e1hoz keresse fel a https://opendata.aemet.es/centrodedescargas/altaUsuario webhelyet.",
|
||||
"description": "Az API-kulcs l\u00e9trehoz\u00e1s\u00e1hoz keresse fel a https://opendata.aemet.es/centrodedescargas/altaUsuario webhelyet",
|
||||
"title": "AEMET OpenData"
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
"longitude": "Bujur",
|
||||
"name": "Nama integrasi"
|
||||
},
|
||||
"description": "Siapkan integrasi AEMET OpenData. Untuk menghasilkan kunci API, buka https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"description": "Untuk membuat kunci API, buka https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"title": "AEMET OpenData"
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
"longitude": "Logitudine",
|
||||
"name": "Nome dell'integrazione"
|
||||
},
|
||||
"description": "Imposta l'integrazione di AEMET OpenData. Per generare la chiave API, vai su https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"description": "Per generare la chiave API, vai su https://opendata.aemet.es/centrodescargas/altaUsuario",
|
||||
"title": "AEMET OpenData"
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
"longitude": "Lengtegraad",
|
||||
"name": "Naam van de integratie"
|
||||
},
|
||||
"description": "Stel AEMET OpenData-integratie in. Ga naar https://opendata.aemet.es/centrodedescargas/altaUsuario om een API-sleutel te genereren",
|
||||
"description": "Om een API sleutel te genereren ga naar https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"title": "AEMET OpenData"
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
"longitude": "Lengdegrad",
|
||||
"name": "Navnet p\u00e5 integrasjonen"
|
||||
},
|
||||
"description": "Sett opp AEMET OpenData-integrasjon. For \u00e5 generere API-n\u00f8kkel, g\u00e5 til https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"description": "For \u00e5 generere API-n\u00f8kkel, g\u00e5 til https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"title": "AEMET OpenData"
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
"longitude": "D\u0142ugo\u015b\u0107 geograficzna",
|
||||
"name": "Nazwa integracji"
|
||||
},
|
||||
"description": "Skonfiguruj integracj\u0119 AEMET OpenData. Aby wygenerowa\u0107 klucz API, przejd\u017a do https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"description": "Aby wygenerowa\u0107 klucz API, przejd\u017a do https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"title": "AEMET OpenData"
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
"longitude": "Longitude",
|
||||
"name": "Nome da integra\u00e7\u00e3o"
|
||||
},
|
||||
"description": "Configure a integra\u00e7\u00e3o AEMET OpenData. Para gerar a chave API acesse https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"description": "Para gerar a chave API acesse https://opendata.aemet.es/centrodedescargas/altaUsuario",
|
||||
"title": "AEMET OpenData"
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
"longitude": "\u0414\u043e\u043b\u0433\u043e\u0442\u0430",
|
||||
"name": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435"
|
||||
},
|
||||
"description": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Home Assistant \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 AEMET OpenData. \u0427\u0442\u043e\u0431\u044b \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u044e\u0447 API, \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043d\u0430 https://opendata.aemet.es/centrodedescargas/altaUsuario.",
|
||||
"description": "\u0427\u0442\u043e\u0431\u044b \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u044e\u0447 API, \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 https://opendata.aemet.es/centrodedescargas/altaUsuario.",
|
||||
"title": "AEMET OpenData"
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
"longitude": "Boylam",
|
||||
"name": "Entegrasyonun ad\u0131"
|
||||
},
|
||||
"description": "AEMET OpenData entegrasyonunu ayarlay\u0131n. API anahtar\u0131 olu\u015fturmak i\u00e7in https://opendata.aemet.es/centrodedescargas/altaUsuario adresine gidin.",
|
||||
"description": "API anahtar\u0131 olu\u015fturmak i\u00e7in https://opendata.aemet.es/centrodedescargas/altaUsuario adresine gidin.",
|
||||
"title": "AEMET OpenData"
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
"longitude": "\u7d93\u5ea6",
|
||||
"name": "\u6574\u5408\u540d\u7a31"
|
||||
},
|
||||
"description": "\u6b32\u8a2d\u5b9a AEMET OpenData \u6574\u5408\u3002\u8acb\u81f3 https://opendata.aemet.es/centrodedescargas/altaUsuario \u7522\u751f API \u91d1\u9470",
|
||||
"description": "\u8acb\u81f3 https://opendata.aemet.es/centrodedescargas/altaUsuario \u4ee5\u7522\u751f API \u91d1\u9470",
|
||||
"title": "AEMET OpenData"
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
"""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.components.alarm_control_panel import (
|
||||
AlarmControlPanelEntity,
|
||||
AlarmControlPanelEntityFeature,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
STATE_ALARM_ARMED_AWAY,
|
||||
@ -38,7 +36,9 @@ class AgentBaseStation(AlarmControlPanelEntity):
|
||||
|
||||
_attr_icon = ICON
|
||||
_attr_supported_features = (
|
||||
SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_AWAY | SUPPORT_ALARM_ARM_NIGHT
|
||||
AlarmControlPanelEntityFeature.ARM_HOME
|
||||
| AlarmControlPanelEntityFeature.ARM_AWAY
|
||||
| AlarmControlPanelEntityFeature.ARM_NIGHT
|
||||
)
|
||||
|
||||
def __init__(self, client):
|
||||
|
@ -4,7 +4,7 @@ import logging
|
||||
|
||||
from agent import AgentError
|
||||
|
||||
from homeassistant.components.camera import SUPPORT_ON_OFF
|
||||
from homeassistant.components.camera import CameraEntityFeature
|
||||
from homeassistant.components.mjpeg import MjpegCamera, filter_urllib3_logging
|
||||
from homeassistant.const import ATTR_ATTRIBUTION
|
||||
from homeassistant.helpers import entity_platform
|
||||
@ -63,6 +63,8 @@ async def async_setup_entry(
|
||||
class AgentCamera(MjpegCamera):
|
||||
"""Representation of an Agent Device Stream."""
|
||||
|
||||
_attr_supported_features = CameraEntityFeature.ON_OFF
|
||||
|
||||
def __init__(self, device):
|
||||
"""Initialize as a subclass of MjpegCamera."""
|
||||
self.device = device
|
||||
@ -134,11 +136,6 @@ class AgentCamera(MjpegCamera):
|
||||
"""Return True if entity is connected."""
|
||||
return self.device.connected
|
||||
|
||||
@property
|
||||
def supported_features(self) -> int:
|
||||
"""Return supported features."""
|
||||
return SUPPORT_ON_OFF
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return true if on."""
|
||||
|
@ -4,7 +4,7 @@
|
||||
"already_configured": "Az eszk\u00f6z m\u00e1r konfigur\u00e1lva van"
|
||||
},
|
||||
"error": {
|
||||
"already_in_progress": "A konfigur\u00e1l\u00e1s m\u00e1r folyamatban van",
|
||||
"already_in_progress": "A be\u00e1ll\u00edt\u00e1si folyamat m\u00e1r el lett kezdve",
|
||||
"cannot_connect": "Sikertelen csatlakoz\u00e1s"
|
||||
},
|
||||
"step": {
|
||||
|
31
homeassistant/components/airly/diagnostics.py
Normal file
31
homeassistant/components/airly/diagnostics.py
Normal file
@ -0,0 +1,31 @@
|
||||
"""Diagnostics support for Airly."""
|
||||
from __future__ import annotations
|
||||
|
||||
from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
CONF_API_KEY,
|
||||
CONF_LATITUDE,
|
||||
CONF_LONGITUDE,
|
||||
CONF_UNIQUE_ID,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import AirlyDataUpdateCoordinator
|
||||
from .const import DOMAIN
|
||||
|
||||
TO_REDACT = {CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, CONF_UNIQUE_ID}
|
||||
|
||||
|
||||
async def async_get_config_entry_diagnostics(
|
||||
hass: HomeAssistant, config_entry: ConfigEntry
|
||||
) -> dict:
|
||||
"""Return diagnostics for a config entry."""
|
||||
coordinator: AirlyDataUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
||||
|
||||
diagnostics_data = {
|
||||
"config_entry": async_redact_data(config_entry.as_dict(), TO_REDACT),
|
||||
"coordinator_data": coordinator.data,
|
||||
}
|
||||
|
||||
return diagnostics_data
|
@ -15,7 +15,7 @@
|
||||
"longitude": "Longitud",
|
||||
"name": "Nom"
|
||||
},
|
||||
"description": "Configura la integraci\u00f3 de qualitat de l'aire Airly. Per generar la clau API, v\u00e9s a https://developer.airly.eu/register",
|
||||
"description": "Per generar la clau API, v\u00e9s a https://developer.airly.eu/register",
|
||||
"title": "Airly"
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
"longitude": "L\u00e4ngengrad",
|
||||
"name": "Name"
|
||||
},
|
||||
"description": "Einrichtung der Airly-Luftqualit\u00e4t Integration. Um einen API-Schl\u00fcssel zu generieren, registriere dich auf https://developer.airly.eu/register",
|
||||
"description": "Um einen API-Schl\u00fcssel zu generieren, besuche https://developer.airly.eu/register",
|
||||
"title": "Airly"
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
"longitude": "Longitude",
|
||||
"name": "Name"
|
||||
},
|
||||
"description": "Set up Airly air quality integration. To generate API key go to https://developer.airly.eu/register",
|
||||
"description": "To generate API key go to https://developer.airly.eu/register",
|
||||
"title": "Airly"
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
"longitude": "Pikkuskraad",
|
||||
"name": "Nimi"
|
||||
},
|
||||
"description": "Seadista Airly \u00f5hukvaliteedi andmete sidumine. API v\u00f5tme loomiseks mine aadressile https://developer.airly.eu/register",
|
||||
"description": "API-v\u00f5tme loomiseks mine aadressile https://developer.airly.eu/register",
|
||||
"title": ""
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
"longitude": "Longitude",
|
||||
"name": "Nom"
|
||||
},
|
||||
"description": "Configurez l'int\u00e9gration de la qualit\u00e9 de l'air Airly. Pour g\u00e9n\u00e9rer une cl\u00e9 API, rendez-vous sur https://developer.airly.eu/register.",
|
||||
"description": "Pour g\u00e9n\u00e9rer une cl\u00e9 d'API, rendez-vous sur https://developer.airly.eu/register",
|
||||
"title": "Airly"
|
||||
}
|
||||
}
|
||||
|
@ -13,9 +13,9 @@
|
||||
"api_key": "API kulcs",
|
||||
"latitude": "Sz\u00e9less\u00e9g",
|
||||
"longitude": "Hossz\u00fas\u00e1g",
|
||||
"name": "N\u00e9v"
|
||||
"name": "Elnevez\u00e9s"
|
||||
},
|
||||
"description": "Az Airly leveg\u0151min\u0151s\u00e9gi integr\u00e1ci\u00f3j\u00e1nak be\u00e1ll\u00edt\u00e1sa. Api-kulcs l\u00e9trehoz\u00e1s\u00e1hoz nyissa meg a k\u00f6vetkez\u0151 weboldalt: https://developer.airly.eu/register",
|
||||
"description": "Az API-kulcs l\u00e9trehoz\u00e1s\u00e1hoz keresse fel a https://developer.airly.eu/register webhelyet",
|
||||
"title": "Airly"
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
"longitude": "Bujur",
|
||||
"name": "Nama"
|
||||
},
|
||||
"description": "Siapkan integrasi kualitas udara Airly. Untuk membuat kunci API, buka https://developer.airly.eu/register",
|
||||
"description": "Untuk membuat kunci API, buka https://developer.airly.eu/register",
|
||||
"title": "Airly"
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
"longitude": "Logitudine",
|
||||
"name": "Nome"
|
||||
},
|
||||
"description": "Configurazione dell'integrazione della qualit\u00e0 dell'aria Airly. Per generare la chiave API vai su https://developer.airly.eu/register",
|
||||
"description": "Per generare la chiave API, vai su https://developer.airly.eu/register",
|
||||
"title": "Airly"
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
"longitude": "Lengtegraad",
|
||||
"name": "Naam"
|
||||
},
|
||||
"description": "Airly-integratie van luchtkwaliteit instellen. Ga naar https://developer.airly.eu/register om de API-sleutel te genereren",
|
||||
"description": "Om een API sleutel te genereren ga naar https://developer.airly.eu/register",
|
||||
"title": "Airly"
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
"longitude": "Lengdegrad",
|
||||
"name": "Navn"
|
||||
},
|
||||
"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": "For \u00e5 generere API-n\u00f8kkel, g\u00e5 til https://developer.airly.eu/register",
|
||||
"title": ""
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
"longitude": "D\u0142ugo\u015b\u0107 geograficzna",
|
||||
"name": "Nazwa"
|
||||
},
|
||||
"description": "Konfiguracja integracji Airly. By wygenerowa\u0107 klucz API, przejd\u017a na stron\u0119 https://developer.airly.eu/register",
|
||||
"description": "By wygenerowa\u0107 klucz API, przejd\u017a na stron\u0119 https://developer.airly.eu/register",
|
||||
"title": "Airly"
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
"longitude": "Longitude",
|
||||
"name": "Nome"
|
||||
},
|
||||
"description": "Configure a integra\u00e7\u00e3o da qualidade do ar airly. Para gerar a chave de API v\u00e1 para https://developer.airly.eu/register",
|
||||
"description": "Para gerar a chave de API, acesse https://developer.airly.eu/register",
|
||||
"title": "Airly"
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
"longitude": "\u0414\u043e\u043b\u0433\u043e\u0442\u0430",
|
||||
"name": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435"
|
||||
},
|
||||
"description": "\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043f\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0443 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430 Airly. \u0427\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u044e\u0447 API, \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 https://developer.airly.eu/register.",
|
||||
"description": "\u0427\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u044e\u0447 API, \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 https://developer.airly.eu/register.",
|
||||
"title": "Airly"
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
"longitude": "Boylam",
|
||||
"name": "Ad"
|
||||
},
|
||||
"description": "Airly hava kalitesi entegrasyonunu ayarlay\u0131n. API anahtar\u0131 olu\u015fturmak i\u00e7in https://developer.airly.eu/register adresine gidin.",
|
||||
"description": "API anahtar\u0131 olu\u015fturmak i\u00e7in https://developer.airly.eu/register adresine gidin.",
|
||||
"title": "Airly"
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
"longitude": "\u7d93\u5ea6",
|
||||
"name": "\u540d\u7a31"
|
||||
},
|
||||
"description": "\u6b32\u8a2d\u5b9a Airly \u7a7a\u6c23\u54c1\u8cea\u6574\u5408\u3002\u8acb\u81f3 https://developer.airly.eu/register \u7522\u751f API \u91d1\u9470",
|
||||
"description": "\u8acb\u81f3 https://developer.airly.eu/register \u4ee5\u7522\u751f API \u91d1\u9470",
|
||||
"title": "Airly"
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
"longitude": "Longitud",
|
||||
"radius": "Radi de l'estaci\u00f3 (milles; opcional)"
|
||||
},
|
||||
"description": "Configura la integraci\u00f3 de qualitat d'aire AirNow. Per generar la clau API, v\u00e9s a https://docs.airnowapi.org/account/request/",
|
||||
"description": "Per generar la clau API, v\u00e9s a https://docs.airnowapi.org/account/request/",
|
||||
"title": "AirNow"
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
"longitude": "L\u00e4ngengrad",
|
||||
"radius": "Stationsradius (Meilen; optional)"
|
||||
},
|
||||
"description": "Richte die AirNow-Luftqualit\u00e4tsintegration ein. Um den API-Schl\u00fcssel zu generieren, besuche https://docs.airnowapi.org/account/request/.",
|
||||
"description": "Um den API-Schl\u00fcssel zu generieren, besuche https://docs.airnowapi.org/account/request/",
|
||||
"title": "AirNow"
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
"longitude": "Longitude",
|
||||
"radius": "Station Radius (miles; optional)"
|
||||
},
|
||||
"description": "Set up AirNow air quality integration. To generate API key go to https://docs.airnowapi.org/account/request/",
|
||||
"description": "To generate API key go to https://docs.airnowapi.org/account/request/",
|
||||
"title": "AirNow"
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
"longitude": "Pikkuskraad",
|
||||
"radius": "Jaama raadius (miilid; valikuline)"
|
||||
},
|
||||
"description": "Seadista AirNow \u00f5hukvaliteedi sidumine. API-v\u00f5tme loomiseks mine aadressile https://docs.airnowapi.org/account/request/",
|
||||
"description": "API-v\u00f5tme loomiseks mine aadressile https://docs.airnowapi.org/account/request/",
|
||||
"title": ""
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
"longitude": "Longitude",
|
||||
"radius": "Rayon d'action de la station (en miles, facultatif)"
|
||||
},
|
||||
"description": "Configurez l'int\u00e9gration de la qualit\u00e9 de l'air AirNow. Pour g\u00e9n\u00e9rer la cl\u00e9 API, acc\u00e9dez \u00e0 https://docs.airnowapi.org/account/request/",
|
||||
"description": "Pour g\u00e9n\u00e9rer une cl\u00e9 d'API, rendez-vous sur https://docs.airnowapi.org/account/request/",
|
||||
"title": "AirNow"
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
"longitude": "Hossz\u00fas\u00e1g",
|
||||
"radius": "\u00c1llom\u00e1s sugara (m\u00e9rf\u00f6ld; opcion\u00e1lis)"
|
||||
},
|
||||
"description": "\u00c1ll\u00edtsa be az AirNow leveg\u0151min\u0151s\u00e9gi integr\u00e1ci\u00f3t. Az API-kulcs el\u0151\u00e1ll\u00edt\u00e1s\u00e1hoz keresse fel a https://docs.airnowapi.org/account/request/ oldalt.",
|
||||
"description": "Az API-kulcs l\u00e9trehoz\u00e1s\u00e1hoz keresse fel a https://docs.airnowapi.org/account/request/ webhelyet",
|
||||
"title": "AirNow"
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
"longitude": "Bujur",
|
||||
"radius": "Radius Stasiun (mil; opsional)"
|
||||
},
|
||||
"description": "Siapkan integrasi kualitas udara AirNow. Untuk membuat kunci API buka https://docs.airnowapi.org/account/request/",
|
||||
"description": "Untuk membuat kunci API buka https://docs.airnowapi.org/account/request/",
|
||||
"title": "AirNow"
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
"longitude": "Logitudine",
|
||||
"radius": "Raggio stazione (miglia; opzionale)"
|
||||
},
|
||||
"description": "Configura l'integrazione per la qualit\u00e0 dell'aria AirNow. Per generare la chiave API, vai su https://docs.airnowapi.org/account/request/",
|
||||
"description": "Per generare la chiave API vai su https://docs.airnowapi.org/account/request/",
|
||||
"title": "AirNow"
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
"longitude": "Lengtegraad",
|
||||
"radius": "Stationsradius (mijl; optioneel)"
|
||||
},
|
||||
"description": "AirNow luchtkwaliteit integratie opzetten. Om een API sleutel te genereren ga naar https://docs.airnowapi.org/account/request/",
|
||||
"description": "Om een API sleutel te genereren ga naar https://docs.airnowapi.org/account/request/",
|
||||
"title": "AirNow"
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
"longitude": "Lengdegrad",
|
||||
"radius": "Stasjonsradius (miles; valgfritt)"
|
||||
},
|
||||
"description": "Konfigurer integrering av luftkvalitet i AirNow. For \u00e5 generere en API-n\u00f8kkel, g\u00e5r du til https://docs.airnowapi.org/account/request/",
|
||||
"description": "For \u00e5 generere API-n\u00f8kkel, g\u00e5 til https://docs.airnowapi.org/account/request/",
|
||||
"title": ""
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
"longitude": "D\u0142ugo\u015b\u0107 geograficzna",
|
||||
"radius": "Promie\u0144 od stacji (w milach; opcjonalnie)"
|
||||
},
|
||||
"description": "Konfiguracja integracji jako\u015bci powietrza AirNow. Aby wygenerowa\u0107 klucz API, przejd\u017a do https://docs.airnowapi.org/account/request/",
|
||||
"description": "Aby wygenerowa\u0107 klucz API, przejd\u017a do https://docs.airnowapi.org/account/request/",
|
||||
"title": "AirNow"
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
"longitude": "Longitude",
|
||||
"radius": "Raio da Esta\u00e7\u00e3o (milhas; opcional)"
|
||||
},
|
||||
"description": "Configure a integra\u00e7\u00e3o da qualidade do ar AirNow. Para gerar a chave de API, acesse https://docs.airnowapi.org/account/request/",
|
||||
"description": "Para gerar a chave de API, acesse https://docs.airnowapi.org/account/request/",
|
||||
"title": "AirNow"
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
"longitude": "\u0414\u043e\u043b\u0433\u043e\u0442\u0430",
|
||||
"radius": "\u0420\u0430\u0434\u0438\u0443\u0441 \u0441\u0442\u0430\u043d\u0446\u0438\u0438 (\u0432 \u043c\u0438\u043b\u044f\u0445; \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e)"
|
||||
},
|
||||
"description": "\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043f\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0443 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u0432\u043e\u0437\u0434\u0443\u0445\u0430 AirNow. \u0427\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u044e\u0447 API, \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 https://docs.airnowapi.org/account/request/.",
|
||||
"description": "\u0427\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u044e\u0447 API, \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 https://docs.airnowapi.org/account/request/.",
|
||||
"title": "AirNow"
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
"longitude": "Boylam",
|
||||
"radius": "\u0130stasyon Yar\u0131\u00e7ap\u0131 (mil; iste\u011fe ba\u011fl\u0131)"
|
||||
},
|
||||
"description": "AirNow hava kalitesi entegrasyonunu ayarlay\u0131n. API anahtar\u0131 olu\u015fturmak i\u00e7in https://docs.airnowapi.org/account/request/ adresine gidin.",
|
||||
"description": "API anahtar\u0131 olu\u015fturmak i\u00e7in https://docs.airnowapi.org/account/request/ adresine gidin.",
|
||||
"title": "AirNow"
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
"longitude": "\u7d93\u5ea6",
|
||||
"radius": "\u89c0\u6e2c\u7ad9\u534a\u5f91\uff08\u82f1\u91cc\uff1b\u9078\u9805\uff09"
|
||||
},
|
||||
"description": "\u6b32\u8a2d\u5b9a AirNow \u7a7a\u6c23\u54c1\u8cea\u6574\u5408\u3002\u8acb\u81f3 https://docs.airnowapi.org/account/request/ \u7522\u751f API \u91d1\u9470",
|
||||
"description": "\u8acb\u81f3 https://docs.airnowapi.org/account/request/ \u4ee5\u7522\u751f API \u91d1\u9470",
|
||||
"title": "AirNow"
|
||||
}
|
||||
}
|
||||
|
@ -11,14 +11,8 @@ from homeassistant.components.climate.const import (
|
||||
FAN_HIGH,
|
||||
FAN_LOW,
|
||||
FAN_MEDIUM,
|
||||
HVAC_MODE_AUTO,
|
||||
HVAC_MODE_COOL,
|
||||
HVAC_MODE_DRY,
|
||||
HVAC_MODE_FAN_ONLY,
|
||||
HVAC_MODE_HEAT,
|
||||
HVAC_MODE_OFF,
|
||||
SUPPORT_FAN_MODE,
|
||||
SUPPORT_TARGET_TEMPERATURE,
|
||||
ClimateEntityFeature,
|
||||
HVACMode,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS
|
||||
@ -29,24 +23,23 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE | SUPPORT_FAN_MODE
|
||||
AT_TO_HA_STATE = {
|
||||
"Heat": HVAC_MODE_HEAT,
|
||||
"Cool": HVAC_MODE_COOL,
|
||||
"AutoHeat": HVAC_MODE_AUTO, # airtouch reports either autoheat or autocool
|
||||
"AutoCool": HVAC_MODE_AUTO,
|
||||
"Auto": HVAC_MODE_AUTO,
|
||||
"Dry": HVAC_MODE_DRY,
|
||||
"Fan": HVAC_MODE_FAN_ONLY,
|
||||
"Heat": HVACMode.HEAT,
|
||||
"Cool": HVACMode.COOL,
|
||||
"AutoHeat": HVACMode.AUTO, # airtouch reports either autoheat or autocool
|
||||
"AutoCool": HVACMode.AUTO,
|
||||
"Auto": HVACMode.AUTO,
|
||||
"Dry": HVACMode.DRY,
|
||||
"Fan": HVACMode.FAN_ONLY,
|
||||
}
|
||||
|
||||
HA_STATE_TO_AT = {
|
||||
HVAC_MODE_HEAT: "Heat",
|
||||
HVAC_MODE_COOL: "Cool",
|
||||
HVAC_MODE_AUTO: "Auto",
|
||||
HVAC_MODE_DRY: "Dry",
|
||||
HVAC_MODE_FAN_ONLY: "Fan",
|
||||
HVAC_MODE_OFF: "Off",
|
||||
HVACMode.HEAT: "Heat",
|
||||
HVACMode.COOL: "Cool",
|
||||
HVACMode.AUTO: "Auto",
|
||||
HVACMode.DRY: "Dry",
|
||||
HVACMode.FAN_ONLY: "Fan",
|
||||
HVACMode.OFF: "Off",
|
||||
}
|
||||
|
||||
AT_TO_HA_FAN_SPEED = {
|
||||
@ -59,7 +52,7 @@ AT_TO_HA_FAN_SPEED = {
|
||||
"Turbo": "turbo",
|
||||
}
|
||||
|
||||
AT_GROUP_MODES = [HVAC_MODE_OFF, HVAC_MODE_FAN_ONLY]
|
||||
AT_GROUP_MODES = [HVACMode.OFF, HVACMode.FAN_ONLY]
|
||||
|
||||
HA_FAN_SPEED_TO_AT = {value: key for key, value in AT_TO_HA_FAN_SPEED.items()}
|
||||
|
||||
@ -90,7 +83,9 @@ async def async_setup_entry(
|
||||
class AirtouchAC(CoordinatorEntity, ClimateEntity):
|
||||
"""Representation of an AirTouch 4 ac."""
|
||||
|
||||
_attr_supported_features = SUPPORT_TARGET_TEMPERATURE | SUPPORT_FAN_MODE
|
||||
_attr_supported_features = (
|
||||
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.FAN_MODE
|
||||
)
|
||||
_attr_temperature_unit = TEMP_CELSIUS
|
||||
|
||||
def __init__(self, coordinator, ac_number, info):
|
||||
@ -147,7 +142,7 @@ class AirtouchAC(CoordinatorEntity, ClimateEntity):
|
||||
"""Return hvac target hvac state."""
|
||||
is_off = self._unit.PowerState == "Off"
|
||||
if is_off:
|
||||
return HVAC_MODE_OFF
|
||||
return HVACMode.OFF
|
||||
|
||||
return AT_TO_HA_STATE[self._airtouch.acs[self._ac_number].AcMode]
|
||||
|
||||
@ -156,7 +151,7 @@ class AirtouchAC(CoordinatorEntity, ClimateEntity):
|
||||
"""Return the list of available operation modes."""
|
||||
airtouch_modes = self._airtouch.GetSupportedCoolingModesForAc(self._ac_number)
|
||||
modes = [AT_TO_HA_STATE[mode] for mode in airtouch_modes]
|
||||
modes.append(HVAC_MODE_OFF)
|
||||
modes.append(HVACMode.OFF)
|
||||
return modes
|
||||
|
||||
async def async_set_hvac_mode(self, hvac_mode):
|
||||
@ -164,7 +159,7 @@ class AirtouchAC(CoordinatorEntity, ClimateEntity):
|
||||
if hvac_mode not in HA_STATE_TO_AT:
|
||||
raise ValueError(f"Unsupported HVAC mode: {hvac_mode}")
|
||||
|
||||
if hvac_mode == HVAC_MODE_OFF:
|
||||
if hvac_mode == HVACMode.OFF:
|
||||
return await self.async_turn_off()
|
||||
await self._airtouch.SetCoolingModeForAc(
|
||||
self._ac_number, HA_STATE_TO_AT[hvac_mode]
|
||||
@ -204,7 +199,7 @@ class AirtouchAC(CoordinatorEntity, ClimateEntity):
|
||||
class AirtouchGroup(CoordinatorEntity, ClimateEntity):
|
||||
"""Representation of an AirTouch 4 group."""
|
||||
|
||||
_attr_supported_features = SUPPORT_TARGET_TEMPERATURE
|
||||
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
_attr_temperature_unit = TEMP_CELSIUS
|
||||
_attr_hvac_modes = AT_GROUP_MODES
|
||||
|
||||
@ -267,18 +262,18 @@ class AirtouchGroup(CoordinatorEntity, ClimateEntity):
|
||||
# there are other power states that aren't 'on' but still count as on (eg. 'Turbo')
|
||||
is_off = self._unit.PowerState == "Off"
|
||||
if is_off:
|
||||
return HVAC_MODE_OFF
|
||||
return HVACMode.OFF
|
||||
|
||||
return HVAC_MODE_FAN_ONLY
|
||||
return HVACMode.FAN_ONLY
|
||||
|
||||
async def async_set_hvac_mode(self, hvac_mode):
|
||||
"""Set new operation mode."""
|
||||
if hvac_mode not in HA_STATE_TO_AT:
|
||||
raise ValueError(f"Unsupported HVAC mode: {hvac_mode}")
|
||||
|
||||
if hvac_mode == HVAC_MODE_OFF:
|
||||
if hvac_mode == HVACMode.OFF:
|
||||
return await self.async_turn_off()
|
||||
if self.hvac_mode == HVAC_MODE_OFF:
|
||||
if self.hvac_mode == HVACMode.OFF:
|
||||
await self.async_turn_on()
|
||||
self._unit = self._airtouch.GetGroups()[self._group_number]
|
||||
_LOGGER.debug(
|
||||
|
@ -10,7 +10,7 @@
|
||||
},
|
||||
"airvisual__pollutant_level": {
|
||||
"good": "Bon",
|
||||
"hazardous": "Hasardeux",
|
||||
"hazardous": "Dangereux",
|
||||
"moderate": "Mod\u00e9r\u00e9",
|
||||
"unhealthy": "Malsain",
|
||||
"unhealthy_sensitive": "Malsain pour les groupes sensibles",
|
||||
|
@ -1,23 +1,30 @@
|
||||
"""The Airzone integration."""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from aioairzone.common import ConnectionOptions
|
||||
from aioairzone.const import (
|
||||
AZD_ID,
|
||||
AZD_MAC,
|
||||
AZD_NAME,
|
||||
AZD_SYSTEM,
|
||||
AZD_THERMOSTAT_FW,
|
||||
AZD_THERMOSTAT_MODEL,
|
||||
AZD_WEBSERVER,
|
||||
AZD_ZONES,
|
||||
DEFAULT_SYSTEM_ID,
|
||||
)
|
||||
from aioairzone.localapi import AirzoneLocalApi
|
||||
from aioairzone.localapi import AirzoneLocalApi, ConnectionOptions
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import aiohttp_client
|
||||
from homeassistant.const import CONF_HOST, CONF_ID, CONF_PORT, Platform
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import (
|
||||
aiohttp_client,
|
||||
device_registry as dr,
|
||||
entity_registry as er,
|
||||
)
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
@ -26,10 +33,20 @@ from .coordinator import AirzoneUpdateCoordinator
|
||||
|
||||
PLATFORMS: list[Platform] = [Platform.BINARY_SENSOR, Platform.CLIMATE, Platform.SENSOR]
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AirzoneEntity(CoordinatorEntity[AirzoneUpdateCoordinator]):
|
||||
"""Define an Airzone entity."""
|
||||
|
||||
def get_airzone_value(self, key) -> Any:
|
||||
"""Return Airzone entity value by key."""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class AirzoneZoneEntity(AirzoneEntity):
|
||||
"""Define an Airzone Zone entity."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: AirzoneUpdateCoordinator,
|
||||
@ -47,12 +64,15 @@ class AirzoneEntity(CoordinatorEntity[AirzoneUpdateCoordinator]):
|
||||
self._attr_device_info: DeviceInfo = {
|
||||
"identifiers": {(DOMAIN, f"{entry.entry_id}_{system_zone_id}")},
|
||||
"manufacturer": MANUFACTURER,
|
||||
"model": self.get_zone_value(AZD_THERMOSTAT_MODEL),
|
||||
"model": self.get_airzone_value(AZD_THERMOSTAT_MODEL),
|
||||
"name": f"Airzone [{system_zone_id}] {zone_data[AZD_NAME]}",
|
||||
"sw_version": self.get_zone_value(AZD_THERMOSTAT_FW),
|
||||
"sw_version": self.get_airzone_value(AZD_THERMOSTAT_FW),
|
||||
}
|
||||
self._attr_unique_id = (
|
||||
entry.entry_id if entry.unique_id is None else entry.unique_id
|
||||
)
|
||||
|
||||
def get_zone_value(self, key):
|
||||
def get_airzone_value(self, key) -> Any:
|
||||
"""Return zone value by key."""
|
||||
value = None
|
||||
if self.system_zone_id in self.coordinator.data[AZD_ZONES]:
|
||||
@ -62,17 +82,58 @@ class AirzoneEntity(CoordinatorEntity[AirzoneUpdateCoordinator]):
|
||||
return value
|
||||
|
||||
|
||||
async def _async_migrate_unique_ids(
|
||||
hass: HomeAssistant,
|
||||
entry: ConfigEntry,
|
||||
coordinator: AirzoneUpdateCoordinator,
|
||||
) -> None:
|
||||
"""Migrate entities when the mac address gets discovered."""
|
||||
|
||||
@callback
|
||||
def _async_migrator(entity_entry: er.RegistryEntry) -> dict[str, Any] | None:
|
||||
updates = None
|
||||
|
||||
unique_id = entry.unique_id
|
||||
entry_id = entry.entry_id
|
||||
entity_unique_id = entity_entry.unique_id
|
||||
|
||||
if entity_unique_id.startswith(entry_id):
|
||||
new_unique_id = f"{unique_id}{entity_unique_id[len(entry_id):]}"
|
||||
_LOGGER.info(
|
||||
"Migrating unique_id from [%s] to [%s]",
|
||||
entity_unique_id,
|
||||
new_unique_id,
|
||||
)
|
||||
updates = {"new_unique_id": new_unique_id}
|
||||
|
||||
return updates
|
||||
|
||||
if (
|
||||
entry.unique_id is None
|
||||
and AZD_WEBSERVER in coordinator.data
|
||||
and AZD_MAC in coordinator.data[AZD_WEBSERVER]
|
||||
and (mac := coordinator.data[AZD_WEBSERVER][AZD_MAC]) is not None
|
||||
):
|
||||
updates: dict[str, Any] = {
|
||||
"unique_id": dr.format_mac(mac),
|
||||
}
|
||||
hass.config_entries.async_update_entry(entry, **updates)
|
||||
|
||||
await er.async_migrate_entries(hass, entry.entry_id, _async_migrator)
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up Airzone from a config entry."""
|
||||
options = ConnectionOptions(
|
||||
entry.data[CONF_HOST],
|
||||
entry.data[CONF_PORT],
|
||||
entry.data.get(CONF_ID, DEFAULT_SYSTEM_ID),
|
||||
)
|
||||
|
||||
airzone = AirzoneLocalApi(aiohttp_client.async_get_clientsession(hass), options)
|
||||
|
||||
coordinator = AirzoneUpdateCoordinator(hass, airzone)
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
await _async_migrate_unique_ids(hass, entry, coordinator)
|
||||
|
||||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator
|
||||
|
||||
|
@ -7,6 +7,7 @@ from typing import Any, Final
|
||||
|
||||
from aioairzone.const import (
|
||||
AZD_AIR_DEMAND,
|
||||
AZD_BATTERY_LOW,
|
||||
AZD_ERRORS,
|
||||
AZD_FLOOR_DEMAND,
|
||||
AZD_NAME,
|
||||
@ -15,8 +16,7 @@ from aioairzone.const import (
|
||||
)
|
||||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
DEVICE_CLASS_PROBLEM,
|
||||
DEVICE_CLASS_RUNNING,
|
||||
BinarySensorDeviceClass,
|
||||
BinarySensorEntity,
|
||||
BinarySensorEntityDescription,
|
||||
)
|
||||
@ -25,7 +25,7 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import AirzoneEntity
|
||||
from . import AirzoneEntity, AirzoneZoneEntity
|
||||
from .const import DOMAIN
|
||||
from .coordinator import AirzoneUpdateCoordinator
|
||||
|
||||
@ -37,14 +37,19 @@ class AirzoneBinarySensorEntityDescription(BinarySensorEntityDescription):
|
||||
attributes: dict[str, str] | None = None
|
||||
|
||||
|
||||
BINARY_SENSOR_TYPES: Final[tuple[AirzoneBinarySensorEntityDescription, ...]] = (
|
||||
ZONE_BINARY_SENSOR_TYPES: Final[tuple[AirzoneBinarySensorEntityDescription, ...]] = (
|
||||
AirzoneBinarySensorEntityDescription(
|
||||
device_class=DEVICE_CLASS_RUNNING,
|
||||
device_class=BinarySensorDeviceClass.RUNNING,
|
||||
key=AZD_AIR_DEMAND,
|
||||
name="Air Demand",
|
||||
),
|
||||
AirzoneBinarySensorEntityDescription(
|
||||
device_class=DEVICE_CLASS_RUNNING,
|
||||
device_class=BinarySensorDeviceClass.BATTERY,
|
||||
key=AZD_BATTERY_LOW,
|
||||
name="Battery Low",
|
||||
),
|
||||
AirzoneBinarySensorEntityDescription(
|
||||
device_class=BinarySensorDeviceClass.RUNNING,
|
||||
key=AZD_FLOOR_DEMAND,
|
||||
name="Floor Demand",
|
||||
),
|
||||
@ -52,7 +57,7 @@ BINARY_SENSOR_TYPES: Final[tuple[AirzoneBinarySensorEntityDescription, ...]] = (
|
||||
attributes={
|
||||
"errors": AZD_ERRORS,
|
||||
},
|
||||
device_class=DEVICE_CLASS_PROBLEM,
|
||||
device_class=BinarySensorDeviceClass.PROBLEM,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
key=AZD_PROBLEMS,
|
||||
name="Problem",
|
||||
@ -66,12 +71,12 @@ async def async_setup_entry(
|
||||
"""Add Airzone binary sensors from a config_entry."""
|
||||
coordinator = hass.data[DOMAIN][entry.entry_id]
|
||||
|
||||
binary_sensors = []
|
||||
binary_sensors: list[AirzoneBinarySensor] = []
|
||||
for system_zone_id, zone_data in coordinator.data[AZD_ZONES].items():
|
||||
for description in BINARY_SENSOR_TYPES:
|
||||
for description in ZONE_BINARY_SENSOR_TYPES:
|
||||
if description.key in zone_data:
|
||||
binary_sensors.append(
|
||||
AirzoneBinarySensor(
|
||||
AirzoneZoneBinarySensor(
|
||||
coordinator,
|
||||
description,
|
||||
entry,
|
||||
@ -84,7 +89,28 @@ async def async_setup_entry(
|
||||
|
||||
|
||||
class AirzoneBinarySensor(AirzoneEntity, BinarySensorEntity):
|
||||
"""Define an Airzone sensor."""
|
||||
"""Define an Airzone binary sensor."""
|
||||
|
||||
entity_description: AirzoneBinarySensorEntityDescription
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> Mapping[str, Any] | None:
|
||||
"""Return state attributes."""
|
||||
if not self.entity_description.attributes:
|
||||
return None
|
||||
return {
|
||||
key: self.get_airzone_value(val)
|
||||
for key, val in self.entity_description.attributes.items()
|
||||
}
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool | None:
|
||||
"""Return true if the binary sensor is on."""
|
||||
return self.get_airzone_value(self.entity_description.key)
|
||||
|
||||
|
||||
class AirzoneZoneBinarySensor(AirzoneZoneEntity, AirzoneBinarySensor):
|
||||
"""Define an Airzone Zone binary sensor."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -96,19 +122,9 @@ class AirzoneBinarySensor(AirzoneEntity, BinarySensorEntity):
|
||||
) -> None:
|
||||
"""Initialize."""
|
||||
super().__init__(coordinator, entry, system_zone_id, zone_data)
|
||||
|
||||
self._attr_name = f"{zone_data[AZD_NAME]} {description.name}"
|
||||
self._attr_unique_id = f"{entry.entry_id}_{system_zone_id}_{description.key}"
|
||||
self.attributes = description.attributes
|
||||
self._attr_unique_id = (
|
||||
f"{self._attr_unique_id}_{system_zone_id}_{description.key}"
|
||||
)
|
||||
self.entity_description = description
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> Mapping[str, Any] | None:
|
||||
"""Return state attributes."""
|
||||
if not self.attributes:
|
||||
return None
|
||||
return {key: self.get_zone_value(val) for key, val in self.attributes.items()}
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool | None:
|
||||
"""Return true if the binary sensor is on."""
|
||||
return self.get_zone_value(self.entity_description.key)
|
||||
|
@ -2,7 +2,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Final
|
||||
from typing import Any, Final
|
||||
|
||||
from aioairzone.common import OperationMode
|
||||
from aioairzone.const import (
|
||||
@ -26,23 +26,12 @@ from aioairzone.const import (
|
||||
AZD_ZONES,
|
||||
)
|
||||
from aioairzone.exceptions import AirzoneError
|
||||
from aiohttp.client_exceptions import ClientConnectorError
|
||||
|
||||
from homeassistant.components.climate import ClimateEntity
|
||||
from homeassistant.components.climate.const import (
|
||||
CURRENT_HVAC_COOL,
|
||||
CURRENT_HVAC_DRY,
|
||||
CURRENT_HVAC_FAN,
|
||||
CURRENT_HVAC_HEAT,
|
||||
CURRENT_HVAC_IDLE,
|
||||
CURRENT_HVAC_OFF,
|
||||
HVAC_MODE_COOL,
|
||||
HVAC_MODE_DRY,
|
||||
HVAC_MODE_FAN_ONLY,
|
||||
HVAC_MODE_HEAT,
|
||||
HVAC_MODE_HEAT_COOL,
|
||||
HVAC_MODE_OFF,
|
||||
SUPPORT_TARGET_TEMPERATURE,
|
||||
ClimateEntityFeature,
|
||||
HVACAction,
|
||||
HVACMode,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ATTR_TEMPERATURE
|
||||
@ -50,35 +39,35 @@ from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import AirzoneEntity
|
||||
from . import AirzoneZoneEntity
|
||||
from .const import API_TEMPERATURE_STEP, DOMAIN, TEMP_UNIT_LIB_TO_HASS
|
||||
from .coordinator import AirzoneUpdateCoordinator
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
HVAC_ACTION_LIB_TO_HASS: Final[dict[OperationMode, str]] = {
|
||||
OperationMode.STOP: CURRENT_HVAC_OFF,
|
||||
OperationMode.COOLING: CURRENT_HVAC_COOL,
|
||||
OperationMode.HEATING: CURRENT_HVAC_HEAT,
|
||||
OperationMode.FAN: CURRENT_HVAC_FAN,
|
||||
OperationMode.DRY: CURRENT_HVAC_DRY,
|
||||
HVAC_ACTION_LIB_TO_HASS: Final[dict[OperationMode, HVACAction]] = {
|
||||
OperationMode.STOP: HVACAction.OFF,
|
||||
OperationMode.COOLING: HVACAction.COOLING,
|
||||
OperationMode.HEATING: HVACAction.HEATING,
|
||||
OperationMode.FAN: HVACAction.FAN,
|
||||
OperationMode.DRY: HVACAction.DRYING,
|
||||
}
|
||||
HVAC_MODE_LIB_TO_HASS: Final[dict[OperationMode, str]] = {
|
||||
OperationMode.STOP: HVAC_MODE_OFF,
|
||||
OperationMode.COOLING: HVAC_MODE_COOL,
|
||||
OperationMode.HEATING: HVAC_MODE_HEAT,
|
||||
OperationMode.FAN: HVAC_MODE_FAN_ONLY,
|
||||
OperationMode.DRY: HVAC_MODE_DRY,
|
||||
OperationMode.AUTO: HVAC_MODE_HEAT_COOL,
|
||||
HVAC_MODE_LIB_TO_HASS: Final[dict[OperationMode, HVACMode]] = {
|
||||
OperationMode.STOP: HVACMode.OFF,
|
||||
OperationMode.COOLING: HVACMode.COOL,
|
||||
OperationMode.HEATING: HVACMode.HEAT,
|
||||
OperationMode.FAN: HVACMode.FAN_ONLY,
|
||||
OperationMode.DRY: HVACMode.DRY,
|
||||
OperationMode.AUTO: HVACMode.HEAT_COOL,
|
||||
}
|
||||
HVAC_MODE_HASS_TO_LIB: Final[dict[str, OperationMode]] = {
|
||||
HVAC_MODE_OFF: OperationMode.STOP,
|
||||
HVAC_MODE_COOL: OperationMode.COOLING,
|
||||
HVAC_MODE_HEAT: OperationMode.HEATING,
|
||||
HVAC_MODE_FAN_ONLY: OperationMode.FAN,
|
||||
HVAC_MODE_DRY: OperationMode.DRY,
|
||||
HVAC_MODE_HEAT_COOL: OperationMode.AUTO,
|
||||
HVAC_MODE_HASS_TO_LIB: Final[dict[HVACMode, OperationMode]] = {
|
||||
HVACMode.OFF: OperationMode.STOP,
|
||||
HVACMode.COOL: OperationMode.COOLING,
|
||||
HVACMode.HEAT: OperationMode.HEATING,
|
||||
HVACMode.FAN_ONLY: OperationMode.FAN,
|
||||
HVACMode.DRY: OperationMode.DRY,
|
||||
HVACMode.HEAT_COOL: OperationMode.AUTO,
|
||||
}
|
||||
|
||||
|
||||
@ -98,7 +87,7 @@ async def async_setup_entry(
|
||||
)
|
||||
|
||||
|
||||
class AirzoneClimate(AirzoneEntity, ClimateEntity):
|
||||
class AirzoneClimate(AirzoneZoneEntity, ClimateEntity):
|
||||
"""Define an Airzone sensor."""
|
||||
|
||||
def __init__(
|
||||
@ -110,61 +99,74 @@ class AirzoneClimate(AirzoneEntity, ClimateEntity):
|
||||
) -> None:
|
||||
"""Initialize Airzone climate entity."""
|
||||
super().__init__(coordinator, entry, system_zone_id, zone_data)
|
||||
|
||||
self._attr_name = f"{zone_data[AZD_NAME]}"
|
||||
self._attr_unique_id = f"{entry.entry_id}_{system_zone_id}"
|
||||
self._attr_supported_features = SUPPORT_TARGET_TEMPERATURE
|
||||
self._attr_unique_id = f"{self._attr_unique_id}_{system_zone_id}"
|
||||
self._attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
self._attr_target_temperature_step = API_TEMPERATURE_STEP
|
||||
self._attr_max_temp = self.get_zone_value(AZD_TEMP_MAX)
|
||||
self._attr_min_temp = self.get_zone_value(AZD_TEMP_MIN)
|
||||
self._attr_max_temp = self.get_airzone_value(AZD_TEMP_MAX)
|
||||
self._attr_min_temp = self.get_airzone_value(AZD_TEMP_MIN)
|
||||
self._attr_temperature_unit = TEMP_UNIT_LIB_TO_HASS[
|
||||
self.get_zone_value(AZD_TEMP_UNIT)
|
||||
self.get_airzone_value(AZD_TEMP_UNIT)
|
||||
]
|
||||
self._attr_hvac_modes = [
|
||||
HVAC_MODE_LIB_TO_HASS[mode] for mode in self.get_zone_value(AZD_MODES)
|
||||
HVAC_MODE_LIB_TO_HASS[mode] for mode in self.get_airzone_value(AZD_MODES)
|
||||
]
|
||||
self._async_update_attrs()
|
||||
|
||||
async def _async_update_hvac_params(self, params) -> None:
|
||||
async def _async_update_hvac_params(self, params: dict[str, Any]) -> None:
|
||||
"""Send HVAC parameters to API."""
|
||||
_params = {
|
||||
API_SYSTEM_ID: self.system_id,
|
||||
API_ZONE_ID: self.zone_id,
|
||||
**params,
|
||||
}
|
||||
_LOGGER.debug("update_hvac_params=%s", _params)
|
||||
try:
|
||||
await self.coordinator.airzone.put_hvac(params)
|
||||
except (AirzoneError, ClientConnectorError) as error:
|
||||
await self.coordinator.airzone.put_hvac(_params)
|
||||
except AirzoneError as error:
|
||||
raise HomeAssistantError(
|
||||
f"Failed to set zone {self.name}: {error}"
|
||||
) from error
|
||||
else:
|
||||
self.coordinator.async_set_updated_data(self.coordinator.airzone.data())
|
||||
|
||||
async def async_set_hvac_mode(self, hvac_mode: str) -> None:
|
||||
"""Set hvac mode."""
|
||||
async def async_turn_on(self) -> None:
|
||||
"""Turn the entity on."""
|
||||
params = {
|
||||
API_SYSTEM_ID: self.system_id,
|
||||
API_ZONE_ID: self.zone_id,
|
||||
API_ON: 1,
|
||||
}
|
||||
if hvac_mode == HVAC_MODE_OFF:
|
||||
await self._async_update_hvac_params(params)
|
||||
|
||||
async def async_turn_off(self) -> None:
|
||||
"""Turn the entity off."""
|
||||
params = {
|
||||
API_ON: 0,
|
||||
}
|
||||
await self._async_update_hvac_params(params)
|
||||
|
||||
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||
"""Set hvac mode."""
|
||||
params = {}
|
||||
if hvac_mode == HVACMode.OFF:
|
||||
params[API_ON] = 0
|
||||
else:
|
||||
mode = HVAC_MODE_HASS_TO_LIB[hvac_mode]
|
||||
if mode != self.get_zone_value(AZD_MODE):
|
||||
if self.get_zone_value(AZD_MASTER):
|
||||
if mode != self.get_airzone_value(AZD_MODE):
|
||||
if self.get_airzone_value(AZD_MASTER):
|
||||
params[API_MODE] = mode
|
||||
else:
|
||||
raise HomeAssistantError(
|
||||
f"Mode can't be changed on slave zone {self.name}"
|
||||
)
|
||||
params[API_ON] = 1
|
||||
_LOGGER.debug("Set hvac_mode=%s params=%s", hvac_mode, params)
|
||||
await self._async_update_hvac_params(params)
|
||||
|
||||
async def async_set_temperature(self, **kwargs) -> None:
|
||||
"""Set new target temperature."""
|
||||
temp = kwargs.get(ATTR_TEMPERATURE)
|
||||
params = {
|
||||
API_SYSTEM_ID: self.system_id,
|
||||
API_ZONE_ID: self.zone_id,
|
||||
API_SET_POINT: temp,
|
||||
API_SET_POINT: kwargs.get(ATTR_TEMPERATURE),
|
||||
}
|
||||
_LOGGER.debug("Set temp=%s params=%s", temp, params)
|
||||
await self._async_update_hvac_params(params)
|
||||
|
||||
@callback
|
||||
@ -176,16 +178,16 @@ class AirzoneClimate(AirzoneEntity, ClimateEntity):
|
||||
@callback
|
||||
def _async_update_attrs(self) -> None:
|
||||
"""Update climate attributes."""
|
||||
self._attr_current_temperature = self.get_zone_value(AZD_TEMP)
|
||||
self._attr_current_humidity = self.get_zone_value(AZD_HUMIDITY)
|
||||
if self.get_zone_value(AZD_ON):
|
||||
mode = self.get_zone_value(AZD_MODE)
|
||||
self._attr_current_temperature = self.get_airzone_value(AZD_TEMP)
|
||||
self._attr_current_humidity = self.get_airzone_value(AZD_HUMIDITY)
|
||||
if self.get_airzone_value(AZD_ON):
|
||||
mode = self.get_airzone_value(AZD_MODE)
|
||||
self._attr_hvac_mode = HVAC_MODE_LIB_TO_HASS[mode]
|
||||
if self.get_zone_value(AZD_DEMAND):
|
||||
if self.get_airzone_value(AZD_DEMAND):
|
||||
self._attr_hvac_action = HVAC_ACTION_LIB_TO_HASS[mode]
|
||||
else:
|
||||
self._attr_hvac_action = CURRENT_HVAC_IDLE
|
||||
self._attr_hvac_action = HVACAction.IDLE
|
||||
else:
|
||||
self._attr_hvac_action = CURRENT_HVAC_OFF
|
||||
self._attr_hvac_mode = HVAC_MODE_OFF
|
||||
self._attr_target_temperature = self.get_zone_value(AZD_TEMP_SET)
|
||||
self._attr_hvac_action = HVACAction.OFF
|
||||
self._attr_hvac_mode = HVACMode.OFF
|
||||
self._attr_target_temperature = self.get_airzone_value(AZD_TEMP_SET)
|
||||
|
@ -3,18 +3,30 @@ from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from aioairzone.common import ConnectionOptions
|
||||
from aioairzone.exceptions import InvalidHost
|
||||
from aioairzone.localapi import AirzoneLocalApi
|
||||
from aiohttp.client_exceptions import ClientConnectorError
|
||||
from aioairzone.const import DEFAULT_PORT, DEFAULT_SYSTEM_ID
|
||||
from aioairzone.exceptions import AirzoneError, InvalidSystem
|
||||
from aioairzone.localapi import AirzoneLocalApi, ConnectionOptions
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT
|
||||
from homeassistant.const import CONF_HOST, CONF_ID, CONF_PORT
|
||||
from homeassistant.data_entry_flow import FlowResult
|
||||
from homeassistant.helpers import aiohttp_client
|
||||
from homeassistant.helpers.device_registry import format_mac
|
||||
|
||||
from .const import DEFAULT_LOCAL_API_PORT, DOMAIN
|
||||
from .const import DOMAIN
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_HOST): str,
|
||||
vol.Required(CONF_PORT, default=DEFAULT_PORT): int,
|
||||
}
|
||||
)
|
||||
SYSTEM_ID_SCHEMA = CONFIG_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(CONF_ID, default=1): int,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
@ -24,39 +36,43 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> FlowResult:
|
||||
"""Handle the initial step."""
|
||||
data_schema = CONFIG_SCHEMA
|
||||
errors = {}
|
||||
|
||||
if user_input is not None:
|
||||
self._async_abort_entries_match(
|
||||
{
|
||||
CONF_HOST: user_input[CONF_HOST],
|
||||
CONF_PORT: user_input[CONF_PORT],
|
||||
}
|
||||
)
|
||||
self._async_abort_entries_match(user_input)
|
||||
|
||||
airzone = AirzoneLocalApi(
|
||||
aiohttp_client.async_get_clientsession(self.hass),
|
||||
ConnectionOptions(
|
||||
user_input[CONF_HOST],
|
||||
user_input[CONF_PORT],
|
||||
user_input.get(CONF_ID, DEFAULT_SYSTEM_ID),
|
||||
),
|
||||
)
|
||||
|
||||
try:
|
||||
await airzone.validate_airzone()
|
||||
except (ClientConnectorError, InvalidHost):
|
||||
mac = await airzone.validate()
|
||||
except InvalidSystem:
|
||||
data_schema = SYSTEM_ID_SCHEMA
|
||||
errors[CONF_ID] = "invalid_system_id"
|
||||
except AirzoneError:
|
||||
errors["base"] = "cannot_connect"
|
||||
else:
|
||||
if mac:
|
||||
await self.async_set_unique_id(format_mac(mac))
|
||||
self._abort_if_unique_id_configured(
|
||||
updates={
|
||||
CONF_HOST: user_input[CONF_HOST],
|
||||
CONF_PORT: user_input[CONF_PORT],
|
||||
}
|
||||
)
|
||||
|
||||
title = f"Airzone {user_input[CONF_HOST]}:{user_input[CONF_PORT]}"
|
||||
return self.async_create_entry(title=title, data=user_input)
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="user",
|
||||
data_schema=vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_HOST): str,
|
||||
vol.Required(CONF_PORT, default=DEFAULT_LOCAL_API_PORT): int,
|
||||
}
|
||||
),
|
||||
data_schema=data_schema,
|
||||
errors=errors,
|
||||
)
|
||||
|
@ -11,7 +11,6 @@ MANUFACTURER: Final = "Airzone"
|
||||
|
||||
AIOAIRZONE_DEVICE_TIMEOUT_SEC: Final = 10
|
||||
API_TEMPERATURE_STEP: Final = 0.5
|
||||
DEFAULT_LOCAL_API_PORT: Final = 3000
|
||||
|
||||
TEMP_UNIT_LIB_TO_HASS: Final[dict[TemperatureUnit, str]] = {
|
||||
TemperatureUnit.CELSIUS: TEMP_CELSIUS,
|
||||
|
@ -4,8 +4,8 @@ from __future__ import annotations
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
from aioairzone.exceptions import AirzoneError
|
||||
from aioairzone.localapi import AirzoneLocalApi
|
||||
from aiohttp.client_exceptions import ClientConnectorError
|
||||
import async_timeout
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
@ -36,7 +36,7 @@ class AirzoneUpdateCoordinator(DataUpdateCoordinator):
|
||||
"""Update data via library."""
|
||||
async with async_timeout.timeout(AIOAIRZONE_DEVICE_TIMEOUT_SEC):
|
||||
try:
|
||||
await self.airzone.update_airzone()
|
||||
except ClientConnectorError as error:
|
||||
await self.airzone.update()
|
||||
except AirzoneError as error:
|
||||
raise UpdateFailed(error) from error
|
||||
return self.airzone.data()
|
||||
|
29
homeassistant/components/airzone/diagnostics.py
Normal file
29
homeassistant/components/airzone/diagnostics.py
Normal file
@ -0,0 +1,29 @@
|
||||
"""Support for the Airzone diagnostics."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from aioairzone.const import AZD_MAC
|
||||
|
||||
from homeassistant.components.diagnostics.util import async_redact_data
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .const import DOMAIN
|
||||
from .coordinator import AirzoneUpdateCoordinator
|
||||
|
||||
TO_REDACT = [
|
||||
AZD_MAC,
|
||||
]
|
||||
|
||||
|
||||
async def async_get_config_entry_diagnostics(
|
||||
hass: HomeAssistant, config_entry: ConfigEntry
|
||||
) -> dict[str, Any]:
|
||||
"""Return diagnostics for a config entry."""
|
||||
coordinator: AirzoneUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
||||
|
||||
return {
|
||||
"info": async_redact_data(config_entry.data, TO_REDACT),
|
||||
"data": async_redact_data(coordinator.data, TO_REDACT),
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
"name": "Airzone",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/airzone",
|
||||
"requirements": ["aioairzone==0.3.3"],
|
||||
"requirements": ["aioairzone==0.4.2"],
|
||||
"codeowners": ["@Noltari"],
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["aioairzone"]
|
||||
|
@ -6,38 +6,34 @@ from typing import Any, Final
|
||||
from aioairzone.const import AZD_HUMIDITY, AZD_NAME, AZD_TEMP, AZD_TEMP_UNIT, AZD_ZONES
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
SensorDeviceClass,
|
||||
SensorEntity,
|
||||
SensorEntityDescription,
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
DEVICE_CLASS_HUMIDITY,
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
PERCENTAGE,
|
||||
TEMP_CELSIUS,
|
||||
)
|
||||
from homeassistant.const import PERCENTAGE, TEMP_CELSIUS
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import AirzoneEntity
|
||||
from . import AirzoneEntity, AirzoneZoneEntity
|
||||
from .const import DOMAIN, TEMP_UNIT_LIB_TO_HASS
|
||||
from .coordinator import AirzoneUpdateCoordinator
|
||||
|
||||
SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = (
|
||||
ZONE_SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = (
|
||||
SensorEntityDescription(
|
||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
key=AZD_TEMP,
|
||||
name="Temperature",
|
||||
native_unit_of_measurement=TEMP_CELSIUS,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
device_class=DEVICE_CLASS_HUMIDITY,
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
key=AZD_HUMIDITY,
|
||||
name="Humidity",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
)
|
||||
|
||||
@ -48,12 +44,12 @@ async def async_setup_entry(
|
||||
"""Add Airzone sensors from a config_entry."""
|
||||
coordinator = hass.data[DOMAIN][entry.entry_id]
|
||||
|
||||
sensors = []
|
||||
sensors: list[AirzoneSensor] = []
|
||||
for system_zone_id, zone_data in coordinator.data[AZD_ZONES].items():
|
||||
for description in SENSOR_TYPES:
|
||||
for description in ZONE_SENSOR_TYPES:
|
||||
if description.key in zone_data:
|
||||
sensors.append(
|
||||
AirzoneSensor(
|
||||
AirzoneZoneSensor(
|
||||
coordinator,
|
||||
description,
|
||||
entry,
|
||||
@ -68,6 +64,15 @@ async def async_setup_entry(
|
||||
class AirzoneSensor(AirzoneEntity, SensorEntity):
|
||||
"""Define an Airzone sensor."""
|
||||
|
||||
@property
|
||||
def native_value(self):
|
||||
"""Return the state."""
|
||||
return self.get_airzone_value(self.entity_description.key)
|
||||
|
||||
|
||||
class AirzoneZoneSensor(AirzoneZoneEntity, AirzoneSensor):
|
||||
"""Define an Airzone Zone sensor."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: AirzoneUpdateCoordinator,
|
||||
@ -78,16 +83,14 @@ class AirzoneSensor(AirzoneEntity, SensorEntity):
|
||||
) -> None:
|
||||
"""Initialize."""
|
||||
super().__init__(coordinator, entry, system_zone_id, zone_data)
|
||||
|
||||
self._attr_name = f"{zone_data[AZD_NAME]} {description.name}"
|
||||
self._attr_unique_id = f"{entry.entry_id}_{system_zone_id}_{description.key}"
|
||||
self._attr_unique_id = (
|
||||
f"{self._attr_unique_id}_{system_zone_id}_{description.key}"
|
||||
)
|
||||
self.entity_description = description
|
||||
|
||||
if description.key == AZD_TEMP:
|
||||
self._attr_native_unit_of_measurement = TEMP_UNIT_LIB_TO_HASS.get(
|
||||
self.get_zone_value(AZD_TEMP_UNIT)
|
||||
self.get_airzone_value(AZD_TEMP_UNIT)
|
||||
)
|
||||
|
||||
@property
|
||||
def native_value(self):
|
||||
"""Return the state."""
|
||||
return self.get_zone_value(self.entity_description.key)
|
||||
|
@ -4,7 +4,8 @@
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
"invalid_system_id": "Invalid Airzone System ID"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user